File:  [LON-CAPA] / loncom / homework / CAPA-converter / capaCommon.c
Revision 1.10: download - view: text, annotated - select for diffs
Tue Dec 4 15:17:57 2001 UTC (22 years, 6 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
- GPL headers

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

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