/* The LearningOnline Network with CAPA * Helaper functions for capa convertor. * $Id: capaCommon.c,v 1.11 2001/12/05 18:58:21 albertel Exp $ * * Copyright Michigan State University Board of Trustees * * This file is part of the LearningOnline Network with CAPA (LON-CAPA). * * LON-CAPA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * LON-CAPA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LON-CAPA; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * /home/httpd/html/adm/gpl.txt * * http://www.lon-capa.org/ */ /* =||>|===================== 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 #if defined(__sun) || defined(linux) || defined(__alpha) || defined(hpux) || defined(AIX) || defined(IRIX) #include /* lockf() */ #endif #include #include #include #include "capaParser.h" #include "capaToken.h" #include "capaCommon.h" #include "ranlib.h" /*----------------------------------------------------------*/ /* flock() in SUN is in BSD compatibility lib */ /* #include */ /*----------------------------------------------------------*/ 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); } int current_dest=DEFAULT_DEST; void change_destination(int which_dest) { if (which_dest < MAX_DEST) { current_dest = which_dest; } else { fprintf(stderr,"Tried to set destination above MAX_DEST: %d", which_dest); exit(1); } } void send_to(int which_dest, int which, char *text, va_list ap) { if (delay) { append_message(&dyn_delayed,text,ap); } else { if (num_streams[which_dest]) { if (which == ALL_STREAMS) { int i; for (i=0;i\n"); break; case MODE_BLOCK: send_stream(which,"\n"); break; case MODE_SCRIPT: send_stream(which,"\n"); break; case MODE_OUTTEXT: send_stream(which,"\n"); break; case MODE_ANSWER: send_stream(which,"\n"); break; case MODE_IMPORT: send_stream(which,"\n"); break; case MODE_NONE: break; } mode[which_dest][which]=MODE_NONE; watch_mode[which_dest][which]=0; } void start_mode(int newmode,char* args) { start_mode_stream(current_dest,ALL_STREAMS,newmode,args); } void start_mode_stream(int which_dest,int which,int newmode,char* args) { if (num_streams[which_dest]) { if (which == ALL_STREAMS) { int i; for (i=0;i\n"); break; case MODE_BLOCK: send_stream(which,"\n",args); break; case MODE_SCRIPT: send_stream(which,"