Annotation of loncom/homework/CAPA-converter/capaCommon.c, revision 1.9

1.1       albertel    1: /* =||>|===================== capaCommon.c =====================|<||= */
                      2: /* created 1994 by Isaac Tsai                                         */
                      3: /* 1994, 1995, 1996, 1997, 1998, 1999  copyrighted by Isaac Tsai      */
                      4: /* TODO: restructure capa_check_ans*() calls into one                 */
                      5: /* =||>|===================== capaCommon.c =====================|<||= */
                      6: #include <ctype.h>
                      7: #if defined(__sun) || defined(linux) || defined(__alpha) || defined(hpux) || defined(AIX) || defined(IRIX) 
                      8: #include <unistd.h>  /* lockf() */
                      9: #endif
                     10: #include <sys/types.h>
                     11: #include <sys/stat.h>
                     12: #include <fcntl.h>
                     13: #include "capaParser.h"
                     14: #include "capaToken.h"
                     15: #include "capaCommon.h"
                     16: #include "ranlib.h"
                     17: 
                     18: 
                     19: /*----------------------------------------------------------*/
                     20: /*  flock() in SUN is in BSD compatibility lib              */
                     21: /*  #include <sys/file.h>                                   */
                     22: /*----------------------------------------------------------*/
                     23: char        Parse_class[QUARTER_K];
                     24: int         Parse_set;
                     25: int         Parse_section; 
                     26: char        Parse_student_number[MAX_STUDENT_NUMBER+1];
                     27: char        Parse_name[MAX_NAME_CHAR+1];
                     28: long        capaid_plus_gen;
                     29: int         managermode;
                     30:  
                     31: int     yyparse();
                     32: int     yylex();
                     33: extern  FILE *yyin;
                     34: extern  void yyrestart();
                     35: 
                     36: 
                     37: /*----------------------------------------------------------*/
                     38: /*  Lock file shared                                        */
                     39: /*  lock the file specified by file stream pointer sp       */
                     40: /*----------------------------------------------------------*/
                     41: int
                     42: flockstream_sh(sp) FILE *sp;
                     43: {
                     44:   int fd;
                     45:   
                     46:   fd = fileno(sp);
                     47:   
                     48: #if defined(__sun) || defined(hpux) || defined(AIX)
                     49:   return ( lockf(fd,F_LOCK, 0L) );
                     50: #else
                     51:   return (flock(fd,LOCK_SH));
                     52: #endif
                     53: }
                     54: /*----------------------------------------------------------*/
                     55: int
                     56: flockstream(sp) FILE *sp;
                     57: {
                     58:   int fd;
                     59:   
                     60:   fd = fileno(sp);
                     61:   
                     62: #if defined(__sun) || defined(hpux) || defined(AIX)
                     63:   return ( lockf(fd,F_LOCK, 0L) );
                     64: #else
                     65:   return (flock(fd,LOCK_EX));
                     66: #endif
                     67: }
                     68: /*----------------------------------------------------------*/
                     69: int
                     70: funlockstream(sp) FILE *sp;
                     71: {
                     72:   int fd;
                     73:   
                     74:   fd = fileno(sp);
                     75:   
                     76: #if defined(__sun) || defined(hpux) || defined(AIX)
                     77:   return ( lockf(fd,F_ULOCK, 0L) );
                     78: #else
                     79:   return ( flock(fd,LOCK_UN) );
                     80: #endif
                     81: }
                     82: 
                     83: int
                     84: inquery_a_lock(sp,cmd,type,offset,whence,len)
                     85: FILE *sp;int cmd;off_t offset;int whence;off_t len;
                     86: {
                     87:   struct flock lock;
                     88:   int    fd;
                     89:   lock.l_type   = type;   lock.l_start = offset;
                     90:   lock.l_whence = whence; lock.l_len   = len;
                     91:   fd=fileno(sp);
                     92:   return (fcntl(fd,cmd,&lock));
                     93: }
                     94: #define  Blocked_Write_Lock(sp) \
                     95:           inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
                     96: 
                     97: #define  Blocked_Write_Lock(sp) \
                     98:           inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
                     99: 
                    100: #define  Un_Lock(sp) \
                    101:           inquery_a_lock(sp,F_SETLK,F_UNLCK,0,0,0)
                    102: 
                    103:          
                    104: 
                    105: 
                    106: /******************************************************************************/
                    107: /* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT, unlike capa_parse_student     */
                    108: /******************************************************************************/
                    109: int  
                    110: capa_parse(set,problem,filename,num_questions,func_ptr)
                    111: int  set;Problem_t **problem;char *filename;int  *num_questions;
                    112: void (*func_ptr)();
                    113: {
1.3       albertel  114:   int   errcode,temp;
1.1       albertel  115: extern  FILE      *Input_stream[MAX_OPENED_FILE];
                    116: extern  char       Opened_filename[MAX_OPENED_FILE][QUARTER_K];
                    117: extern  int        Lexi_line;
                    118: extern  int        Lexi_qnum;
                    119: extern  Problem_t *FirstProblem_p;
                    120: extern  Problem_t *LastProblem_p;
                    121: extern  Problem_t *LexiProblem_p;
                    122: extern  char      *StartText_p;
                    123: extern  char      *EndText_p;
                    124: extern  char      *ErrorMsg_p;
                    125: extern  int        ErrorMsg_count;
                    126: extern  int        Symb_count;
                    127: extern  int        first_run;
                    128: extern  void       (*Status_Func)();
                    129:   char             warn_msg[WARN_MSG_LENGTH];
                    130:   
                    131:   if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
                    132:   if(EndText_p)  { capa_mfree(EndText_p);  EndText_p  = NULL; }
                    133:   if(StartText_p)  { capa_mfree(StartText_p);  StartText_p  = NULL; }
                    134:   ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
                    135:   Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
                    136:   FirstProblem_p = LastProblem_p = NULL;
                    137:   LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
                    138:   Status_Func=func_ptr;
                    139: 
                    140: #ifdef AVOIDYYINPUT
                    141:   yyin=fopen(filename,"r");
                    142: #else
                    143:  if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
                    144:      /* printf("Error: can't open %s\n",filename);*/
                    145:      sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
                    146:      capa_msg(MESSAGE_ERROR,warn_msg);
                    147:      return (-1);
                    148:   }
                    149: #endif
                    150:   sprintf(Opened_filename[0],"%s",filename);
                    151:   
                    152:   /*yyrestart(yyin);*/
                    153:   begin_text();
                    154:   /*if ( !yyparse() )  { errcode = Lexi_qnum; } else { errcode = 0; }*/
1.3       albertel  155:   if (!(temp=yylex())) { errcode = Lexi_qnum; } else { errcode = 0; }
1.9     ! albertel  156:   fprintf(stderr,"\nExited on: %d\n",temp);
        !           157:   fprintf(stderr,"Current cache: %d\n",current_cache);
        !           158:   fprintf(stderr,"Flushing:\n"); 
1.3       albertel  159:   flush_delayed();
1.1       albertel  160:   /* fclose(Input_stream[0]);*/ /*The Lexer handles closing this*/
                    161:   /* print_symb_stat(); */
                    162:   /*
                    163:   capa_mfree((char *)LexiProblem_p);
                    164:   LexiProblem_p = NULL;
                    165:   */
                    166:  (*problem) = FirstProblem_p;
                    167:  (*num_questions) = Lexi_qnum;
                    168:   return (errcode);
                    169: }
                    170: 
1.3       albertel  171: int dyn_maxlen=1000000;
                    172: int delay;
1.9     ! albertel  173: void dyn_init(struct dyn_string *dyn)
1.3       albertel  174: {
1.9     ! albertel  175:     dyn->len=0;
        !           176:     dyn->max=0;
        !           177:     dyn->str=NULL;
1.3       albertel  178: }
                    179: 
1.9     ! albertel  180: void dyn_free(struct dyn_string* dyn)
1.3       albertel  181: {
1.9     ! albertel  182:     if (dyn->str) {
        !           183:       free(dyn->str);dyn->str=NULL;
        !           184:       dyn->len=0;
        !           185:       dyn->max=0;
        !           186:     }
1.3       albertel  187: }
                    188: 
1.9     ! albertel  189: 
1.3       albertel  190: int append_message(struct dyn_string *dyn_msg,char *format,va_list ap) {
                    191:     char *new;
                    192:     int len,result;
                    193: 
1.9     ! albertel  194:     if ((result=vasprintf(&new,format,ap))==-1) {
        !           195:       fprintf(stderr,"vaspintf didn't like :%s:",format);
        !           196:       exit(1);
        !           197:     }
1.3       albertel  198:     len=strlen(new);
                    199: 
                    200: #ifdef DYN_DEBUG
                    201:     fprintf(stderr,"before: len %d; gcount %d; max %d\n",
                    202: 	    len,dyn_msg->len,dyn_msg->max);
                    203: #endif /* DYN_DEBUG */
                    204: 
                    205:     if (dyn_msg->len+len < dyn_maxlen) {
                    206: 	if (dyn_msg->len+len>dyn_msg->max-2) {
                    207: 	    dyn_msg->max=(dyn_msg->len+len)*2;
                    208: 	    if (dyn_msg->max>dyn_maxlen) { dyn_msg->max=dyn_maxlen; }
                    209: 	    if (dyn_msg->max != 0) {
                    210: 	      dyn_msg->str=realloc(dyn_msg->str,dyn_msg->max);
                    211: 	    } else {
                    212: 	      return 1;
                    213: 	    }
                    214: 	    dyn_msg->str[dyn_msg->len]='\0';
                    215: 	}
                    216: 	strcat(dyn_msg->str,new);
                    217: 	dyn_msg->len+=len;
                    218:     } else {
                    219: 	if (dyn_msg->max != dyn_maxlen-1) { /*already maxed out or can 
                    220: 					       we fit this one in?*/
                    221: 	    dyn_msg->max=dyn_maxlen;
                    222: 	    dyn_msg->str=realloc(dyn_msg->str,dyn_msg->max);
                    223: 	    dyn_msg->str[dyn_msg->len]='\0';
                    224: 	    strncat(dyn_msg->str,new,dyn_msg->max-dyn_msg->len-1);
                    225: 	    dyn_msg->len=strlen(dyn_msg->str);
                    226: 	}
                    227:     }
                    228:     free(new);
                    229: 
                    230: #ifdef DYN_DEBUG
                    231:     fprintf(stderr,"after: len %d; gcount %d; max %d; strlen(dyn_msg): %d\n",
                    232: 	    len,dyn_msg->len,dyn_msg->max,strlen(dyn_msg->str));
                    233: #endif /* DYN_DEBUG */
                    234: 
                    235:     return 1;
                    236: }
                    237: 
                    238: void start_delayed(){ delay=1; }
                    239: void end_delayed(){ delay=0; }
                    240: 
1.4       albertel  241: void add_delayed(char *format, ...) {
1.3       albertel  242:     va_list ap;
                    243: 
                    244:     va_start(ap,format);
                    245:     append_message(&dyn_delayed,format,ap);
1.9     ! albertel  246:     if (do_cache[current_cache]) {
        !           247:       append_message(&cached_data[current_cache],format,ap);
        !           248:     }	
        !           249: }
1.3       albertel  250: 
                    251: void flush_delayed()
                    252: {
                    253:   delay=0;
1.9     ! albertel  254:   if (dyn_delayed.str) { send(dyn_delayed.str); }
        !           255:   dyn_free(&dyn_delayed);dyn_init(&dyn_delayed);
1.3       albertel  256: }
                    257: 
1.9     ! albertel  258: 
        !           259: void send_to(int which, char *text, va_list ap)
1.1       albertel  260: {
1.3       albertel  261:   if (delay) {
                    262:     append_message(&dyn_delayed,text,ap);
                    263:   } else {
1.9     ! albertel  264:     if (num_streams) {
        !           265:       if (which == ALL_STREAMS) {
        !           266: 	int i;
        !           267: 	for (i=0;i<num_streams;i++) { append_message(&streams[i],text,ap); }
        !           268:       } else {
        !           269: 	append_message(&streams[which],text,ap);
        !           270:       }
        !           271:     } else {
        !           272:       vprintf(text,ap);
        !           273:     }
1.3       albertel  274:   }
1.9     ! albertel  275:   if (do_cache[current_cache]) {
        !           276:     append_message(&cached_data[current_cache],text,ap);
        !           277:   }	
        !           278: }
        !           279: 
        !           280: void send(char *text,...)
        !           281: {
        !           282:   va_list ap;
        !           283:   va_start(ap,text);
        !           284:   send_to(ALL_STREAMS,text,ap);
1.2       albertel  285: }
                    286: 
1.9     ! albertel  287: void send_stream(int which, char *text,...)
        !           288: {
        !           289:   va_list ap;
        !           290:   va_start(ap,text);
        !           291:   send_to(which,text,ap);
        !           292: }
        !           293: 
        !           294: int num_streams=0;
        !           295: struct dyn_string streams[MAX_STREAMS];
        !           296: void start_streams(int num) {
        !           297:   int i;
        !           298:   for(i=0; i<num; i++) { dyn_init(&streams[i]); }
        !           299:   for(i=1; i<num; i++) { mode[i]=mode[0]; }
        !           300:   num_streams=num;
        !           301: }
        !           302: 
        !           303: void end_streams(int which) {
        !           304:   int i;
        !           305:   fputs(streams[which].str,stdout);
        !           306:   for(i=0; i<num_streams; i++) { dyn_free(&streams[which]); }
        !           307:   num_streams=0;
        !           308:   mode[0]=mode[which];
        !           309: }
        !           310: 
        !           311: int watch_mode[MAX_STREAMS];
1.3       albertel  312: void end_mode()
1.2       albertel  313: {
1.9     ! albertel  314:   end_mode_stream(ALL_STREAMS);
        !           315: }
        !           316: 
        !           317: void end_mode_stream(int which)
        !           318: {
        !           319:   if (num_streams) {
        !           320:     if (which == ALL_STREAMS) {
        !           321:       int i;
        !           322:       for (i=0;i<num_streams;i++) { end_mode_stream(i); }
        !           323:       return;
        !           324:     }
        !           325:   } else {
        !           326:     which=0;/* if streams aren't active make sure which is correct */
        !           327:   }
        !           328:   switch (mode[which]) {
        !           329:   case MODE_COMMENT: send_stream(which,"</comment>\n"); break;
        !           330:   case MODE_BLOCK: send_stream(which,"</block>\n"); break;
        !           331:   case MODE_SCRIPT: send_stream(which,"</script>\n"); break;
        !           332:   case MODE_OUTTEXT: send_stream(which,"<endouttext />\n"); break;
        !           333:   case MODE_ANSWER: send_stream(which,"\n"); break;
        !           334:   case MODE_HINT: send_stream(which,"<endouttext />\n</hintpart>\n</hintgroup>\n"); break;
        !           335:   case MODE_IMPORT: send_stream(which,"</import>\n"); break;
1.3       albertel  336:   case MODE_NONE: break;
                    337:   }
1.9     ! albertel  338:   mode[which]=MODE_NONE;
        !           339:   watch_mode[which]=0;
1.2       albertel  340: }
                    341: 
1.3       albertel  342: void start_mode(int newmode,char* args)
1.2       albertel  343: {
1.9     ! albertel  344:   start_mode_stream(ALL_STREAMS,newmode,args);
        !           345: }
        !           346: 
        !           347: void start_mode_stream(int which,int newmode,char* args)
        !           348: {
        !           349:   if (num_streams) {
        !           350:     if (which == ALL_STREAMS) {
        !           351:       int i;
        !           352:       for (i=0;i<num_streams;i++) { start_mode_stream(i,newmode,args); }
        !           353:       return;
        !           354:     } else {
        !           355:       if (newmode == mode[which]) return;
        !           356:     }
        !           357:   } else {
        !           358:     if (newmode == mode[0]) return;
        !           359:     which=0;/* if streams aren't active make sure which is correct */
        !           360:   }
        !           361:   end_mode_stream(which);
1.3       albertel  362:   switch (newmode) {
1.9     ! albertel  363:   case MODE_COMMENT: send_stream(which,"<comment>\n"); break;
        !           364:   case MODE_BLOCK: send_stream(which,"<block %s>\n",args); break;
        !           365:   case MODE_SCRIPT: send_stream(which,"<script type=\"loncapa/perl\">\n"); break;
        !           366:   case MODE_OUTTEXT: send_stream(which,"<startouttext />\n"); break;
        !           367:   case MODE_ANSWER: send_stream(which,"\n"); break;
        !           368:   case MODE_HINT: send_stream(which,"<hintgroup>\n<hintpart on=\"default\">\n<startouttext />\n"); break;
        !           369:   case MODE_IMPORT: send_stream(which,"<import>"); break;
1.3       albertel  370:   case MODE_NONE: break;
                    371:   }
1.9     ! albertel  372:   mode[which]=newmode;
        !           373: }
        !           374: 
        !           375: int current_cache=-1;
        !           376: int do_cache[MAX_CACHE];
        !           377: struct dyn_string cached_data[MAX_CACHE];
        !           378: 
        !           379: void new_cache()
        !           380: {
        !           381:   current_cache++;
        !           382:   do_cache[current_cache]=1;
        !           383:   if (current_cache>MAX_CACHE) { exit(CACHE_ERROR); }
        !           384:   dyn_init(&cached_data[current_cache]);
        !           385: }
        !           386: 
        !           387: void start_cache() 
        !           388: {
        !           389:   do_cache[current_cache]=1;
        !           390: }
        !           391: 
        !           392: void stop_cache()
        !           393: {
        !           394:   do_cache[current_cache]=0;
        !           395: }
        !           396: 
        !           397: void delete_cache()
        !           398: {
        !           399:   if (current_cache > -1) {
        !           400:     dyn_free(&cached_data[current_cache]);
        !           401:     current_cache--;
        !           402:   }
1.1       albertel  403: }
                    404: /* =||>|===================== End of capaCommon.c =====================|<||= */
                    405: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>