File:
[LON-CAPA] /
loncom /
homework /
CAPA-converter /
capaCommon.c
Revision
1.9:
download - view:
text,
annotated -
select for diffs
Sun Nov 18 09:40:45 2001 UTC (22 years, 9 months ago) by
albertel
Branches:
MAIN
CVS tags:
HEAD
- added a cache data structure
- new_cache() adds a new cache strutuce and sets that one as the one
being added to.
- delete_cache() deletes the last cache and sets the previous one as
current
- start_cache() turns on caching for the current cache
- stop_cache() turns off caching for the current cache
(Both append_delayed() and send() data are stuck into the current cache)
- added a streams data structure
- allows multiple versions of the output to be generated simultaneously
- send() and flush_delayed() by default put all data into all streams
- send_stream() lets one pick a stream to send data to
- start_streams() starts off all of the streams requested
- end_streams() sends the specified stream out, and free()s the rest
- start_mode_stream end_mode_stream, allows one to change modes on
specific streams, different streams can be in different modes.
- the global var watch_mode can be used to check if a stream has
changed modes, everytime a mode change occurs on a specific stream
the watch_mode var for that stream gets set to zero.
/* =||>|===================== capaCommon.c =====================|<||= */
/* created 1994 by Isaac Tsai */
/* 1994, 1995, 1996, 1997, 1998, 1999 copyrighted by Isaac Tsai */
/* TODO: restructure capa_check_ans*() calls into one */
/* =||>|===================== capaCommon.c =====================|<||= */
#include <ctype.h>
#if defined(__sun) || defined(linux) || defined(__alpha) || defined(hpux) || defined(AIX) || defined(IRIX)
#include <unistd.h> /* lockf() */
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "capaParser.h"
#include "capaToken.h"
#include "capaCommon.h"
#include "ranlib.h"
/*----------------------------------------------------------*/
/* flock() in SUN is in BSD compatibility lib */
/* #include <sys/file.h> */
/*----------------------------------------------------------*/
char Parse_class[QUARTER_K];
int Parse_set;
int Parse_section;
char Parse_student_number[MAX_STUDENT_NUMBER+1];
char Parse_name[MAX_NAME_CHAR+1];
long capaid_plus_gen;
int managermode;
int yyparse();
int yylex();
extern FILE *yyin;
extern void yyrestart();
/*----------------------------------------------------------*/
/* Lock file shared */
/* lock the file specified by file stream pointer sp */
/*----------------------------------------------------------*/
int
flockstream_sh(sp) FILE *sp;
{
int fd;
fd = fileno(sp);
#if defined(__sun) || defined(hpux) || defined(AIX)
return ( lockf(fd,F_LOCK, 0L) );
#else
return (flock(fd,LOCK_SH));
#endif
}
/*----------------------------------------------------------*/
int
flockstream(sp) FILE *sp;
{
int fd;
fd = fileno(sp);
#if defined(__sun) || defined(hpux) || defined(AIX)
return ( lockf(fd,F_LOCK, 0L) );
#else
return (flock(fd,LOCK_EX));
#endif
}
/*----------------------------------------------------------*/
int
funlockstream(sp) FILE *sp;
{
int fd;
fd = fileno(sp);
#if defined(__sun) || defined(hpux) || defined(AIX)
return ( lockf(fd,F_ULOCK, 0L) );
#else
return ( flock(fd,LOCK_UN) );
#endif
}
int
inquery_a_lock(sp,cmd,type,offset,whence,len)
FILE *sp;int cmd;off_t offset;int whence;off_t len;
{
struct flock lock;
int fd;
lock.l_type = type; lock.l_start = offset;
lock.l_whence = whence; lock.l_len = len;
fd=fileno(sp);
return (fcntl(fd,cmd,&lock));
}
#define Blocked_Write_Lock(sp) \
inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
#define Blocked_Write_Lock(sp) \
inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
#define Un_Lock(sp) \
inquery_a_lock(sp,F_SETLK,F_UNLCK,0,0,0)
/******************************************************************************/
/* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT, unlike capa_parse_student */
/******************************************************************************/
int
capa_parse(set,problem,filename,num_questions,func_ptr)
int set;Problem_t **problem;char *filename;int *num_questions;
void (*func_ptr)();
{
int errcode,temp;
extern FILE *Input_stream[MAX_OPENED_FILE];
extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
extern int Lexi_line;
extern int Lexi_qnum;
extern Problem_t *FirstProblem_p;
extern Problem_t *LastProblem_p;
extern Problem_t *LexiProblem_p;
extern char *StartText_p;
extern char *EndText_p;
extern char *ErrorMsg_p;
extern int ErrorMsg_count;
extern int Symb_count;
extern int first_run;
extern void (*Status_Func)();
char warn_msg[WARN_MSG_LENGTH];
if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
if(EndText_p) { capa_mfree(EndText_p); EndText_p = NULL; }
if(StartText_p) { capa_mfree(StartText_p); StartText_p = NULL; }
ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
FirstProblem_p = LastProblem_p = NULL;
LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
Status_Func=func_ptr;
#ifdef AVOIDYYINPUT
yyin=fopen(filename,"r");
#else
if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
/* printf("Error: can't open %s\n",filename);*/
sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
capa_msg(MESSAGE_ERROR,warn_msg);
return (-1);
}
#endif
sprintf(Opened_filename[0],"%s",filename);
/*yyrestart(yyin);*/
begin_text();
/*if ( !yyparse() ) { errcode = Lexi_qnum; } else { errcode = 0; }*/
if (!(temp=yylex())) { errcode = Lexi_qnum; } else { errcode = 0; }
fprintf(stderr,"\nExited on: %d\n",temp);
fprintf(stderr,"Current cache: %d\n",current_cache);
fprintf(stderr,"Flushing:\n");
flush_delayed();
/* fclose(Input_stream[0]);*/ /*The Lexer handles closing this*/
/* print_symb_stat(); */
/*
capa_mfree((char *)LexiProblem_p);
LexiProblem_p = NULL;
*/
(*problem) = FirstProblem_p;
(*num_questions) = Lexi_qnum;
return (errcode);
}
int dyn_maxlen=1000000;
int delay;
void dyn_init(struct dyn_string *dyn)
{
dyn->len=0;
dyn->max=0;
dyn->str=NULL;
}
void dyn_free(struct dyn_string* dyn)
{
if (dyn->str) {
free(dyn->str);dyn->str=NULL;
dyn->len=0;
dyn->max=0;
}
}
int append_message(struct dyn_string *dyn_msg,char *format,va_list ap) {
char *new;
int len,result;
if ((result=vasprintf(&new,format,ap))==-1) {
fprintf(stderr,"vaspintf didn't like :%s:",format);
exit(1);
}
len=strlen(new);
#ifdef DYN_DEBUG
fprintf(stderr,"before: len %d; gcount %d; max %d\n",
len,dyn_msg->len,dyn_msg->max);
#endif /* DYN_DEBUG */
if (dyn_msg->len+len < dyn_maxlen) {
if (dyn_msg->len+len>dyn_msg->max-2) {
dyn_msg->max=(dyn_msg->len+len)*2;
if (dyn_msg->max>dyn_maxlen) { dyn_msg->max=dyn_maxlen; }
if (dyn_msg->max != 0) {
dyn_msg->str=realloc(dyn_msg->str,dyn_msg->max);
} else {
return 1;
}
dyn_msg->str[dyn_msg->len]='\0';
}
strcat(dyn_msg->str,new);
dyn_msg->len+=len;
} else {
if (dyn_msg->max != dyn_maxlen-1) { /*already maxed out or can
we fit this one in?*/
dyn_msg->max=dyn_maxlen;
dyn_msg->str=realloc(dyn_msg->str,dyn_msg->max);
dyn_msg->str[dyn_msg->len]='\0';
strncat(dyn_msg->str,new,dyn_msg->max-dyn_msg->len-1);
dyn_msg->len=strlen(dyn_msg->str);
}
}
free(new);
#ifdef DYN_DEBUG
fprintf(stderr,"after: len %d; gcount %d; max %d; strlen(dyn_msg): %d\n",
len,dyn_msg->len,dyn_msg->max,strlen(dyn_msg->str));
#endif /* DYN_DEBUG */
return 1;
}
void start_delayed(){ delay=1; }
void end_delayed(){ delay=0; }
void add_delayed(char *format, ...) {
va_list ap;
va_start(ap,format);
append_message(&dyn_delayed,format,ap);
if (do_cache[current_cache]) {
append_message(&cached_data[current_cache],format,ap);
}
}
void flush_delayed()
{
delay=0;
if (dyn_delayed.str) { send(dyn_delayed.str); }
dyn_free(&dyn_delayed);dyn_init(&dyn_delayed);
}
void send_to(int which, char *text, va_list ap)
{
if (delay) {
append_message(&dyn_delayed,text,ap);
} else {
if (num_streams) {
if (which == ALL_STREAMS) {
int i;
for (i=0;i<num_streams;i++) { append_message(&streams[i],text,ap); }
} else {
append_message(&streams[which],text,ap);
}
} else {
vprintf(text,ap);
}
}
if (do_cache[current_cache]) {
append_message(&cached_data[current_cache],text,ap);
}
}
void send(char *text,...)
{
va_list ap;
va_start(ap,text);
send_to(ALL_STREAMS,text,ap);
}
void send_stream(int which, char *text,...)
{
va_list ap;
va_start(ap,text);
send_to(which,text,ap);
}
int num_streams=0;
struct dyn_string streams[MAX_STREAMS];
void start_streams(int num) {
int i;
for(i=0; i<num; i++) { dyn_init(&streams[i]); }
for(i=1; i<num; i++) { mode[i]=mode[0]; }
num_streams=num;
}
void end_streams(int which) {
int i;
fputs(streams[which].str,stdout);
for(i=0; i<num_streams; i++) { dyn_free(&streams[which]); }
num_streams=0;
mode[0]=mode[which];
}
int watch_mode[MAX_STREAMS];
void end_mode()
{
end_mode_stream(ALL_STREAMS);
}
void end_mode_stream(int which)
{
if (num_streams) {
if (which == ALL_STREAMS) {
int i;
for (i=0;i<num_streams;i++) { end_mode_stream(i); }
return;
}
} else {
which=0;/* if streams aren't active make sure which is correct */
}
switch (mode[which]) {
case MODE_COMMENT: send_stream(which,"</comment>\n"); break;
case MODE_BLOCK: send_stream(which,"</block>\n"); break;
case MODE_SCRIPT: send_stream(which,"</script>\n"); break;
case MODE_OUTTEXT: send_stream(which,"<endouttext />\n"); break;
case MODE_ANSWER: send_stream(which,"\n"); break;
case MODE_HINT: send_stream(which,"<endouttext />\n</hintpart>\n</hintgroup>\n"); break;
case MODE_IMPORT: send_stream(which,"</import>\n"); break;
case MODE_NONE: break;
}
mode[which]=MODE_NONE;
watch_mode[which]=0;
}
void start_mode(int newmode,char* args)
{
start_mode_stream(ALL_STREAMS,newmode,args);
}
void start_mode_stream(int which,int newmode,char* args)
{
if (num_streams) {
if (which == ALL_STREAMS) {
int i;
for (i=0;i<num_streams;i++) { start_mode_stream(i,newmode,args); }
return;
} else {
if (newmode == mode[which]) return;
}
} else {
if (newmode == mode[0]) return;
which=0;/* if streams aren't active make sure which is correct */
}
end_mode_stream(which);
switch (newmode) {
case MODE_COMMENT: send_stream(which,"<comment>\n"); break;
case MODE_BLOCK: send_stream(which,"<block %s>\n",args); break;
case MODE_SCRIPT: send_stream(which,"<script type=\"loncapa/perl\">\n"); break;
case MODE_OUTTEXT: send_stream(which,"<startouttext />\n"); break;
case MODE_ANSWER: send_stream(which,"\n"); break;
case MODE_HINT: send_stream(which,"<hintgroup>\n<hintpart on=\"default\">\n<startouttext />\n"); break;
case MODE_IMPORT: send_stream(which,"<import>"); break;
case MODE_NONE: break;
}
mode[which]=newmode;
}
int current_cache=-1;
int do_cache[MAX_CACHE];
struct dyn_string cached_data[MAX_CACHE];
void new_cache()
{
current_cache++;
do_cache[current_cache]=1;
if (current_cache>MAX_CACHE) { exit(CACHE_ERROR); }
dyn_init(&cached_data[current_cache]);
}
void start_cache()
{
do_cache[current_cache]=1;
}
void stop_cache()
{
do_cache[current_cache]=0;
}
void delete_cache()
{
if (current_cache > -1) {
dyn_free(&cached_data[current_cache]);
current_cache--;
}
}
/* =||>|===================== End of capaCommon.c =====================|<||= */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>