Annotation of loncom/homework/CAPA-converter/capaCommon.c, revision 1.11
1.10 albertel 1: /* The LearningOnline Network with CAPA
2: * Helaper functions for capa convertor.
1.11 ! albertel 3: * $Id: capaCommon.c,v 1.10 2001/12/04 15:17:57 albertel Exp $
1.10 albertel 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:
1.1 albertel 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: {
1.3 albertel 141: int errcode,temp;
1.1 albertel 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; }*/
1.3 albertel 182: if (!(temp=yylex())) { errcode = Lexi_qnum; } else { errcode = 0; }
1.9 albertel 183: fprintf(stderr,"\nExited on: %d\n",temp);
184: fprintf(stderr,"Current cache: %d\n",current_cache);
185: fprintf(stderr,"Flushing:\n");
1.3 albertel 186: flush_delayed();
1.1 albertel 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:
1.3 albertel 198: int dyn_maxlen=1000000;
199: int delay;
1.9 albertel 200: void dyn_init(struct dyn_string *dyn)
1.3 albertel 201: {
1.9 albertel 202: dyn->len=0;
203: dyn->max=0;
204: dyn->str=NULL;
1.3 albertel 205: }
206:
1.9 albertel 207: void dyn_free(struct dyn_string* dyn)
1.3 albertel 208: {
1.9 albertel 209: if (dyn->str) {
210: free(dyn->str);dyn->str=NULL;
211: dyn->len=0;
212: dyn->max=0;
213: }
1.3 albertel 214: }
215:
1.9 albertel 216:
1.3 albertel 217: int append_message(struct dyn_string *dyn_msg,char *format,va_list ap) {
218: char *new;
219: int len,result;
220:
1.9 albertel 221: if ((result=vasprintf(&new,format,ap))==-1) {
222: fprintf(stderr,"vaspintf didn't like :%s:",format);
223: exit(1);
224: }
1.3 albertel 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:
1.4 albertel 268: void add_delayed(char *format, ...) {
1.3 albertel 269: va_list ap;
270:
271: va_start(ap,format);
272: append_message(&dyn_delayed,format,ap);
1.9 albertel 273: if (do_cache[current_cache]) {
274: append_message(&cached_data[current_cache],format,ap);
275: }
276: }
1.3 albertel 277:
278: void flush_delayed()
279: {
280: delay=0;
1.9 albertel 281: if (dyn_delayed.str) { send(dyn_delayed.str); }
282: dyn_free(&dyn_delayed);dyn_init(&dyn_delayed);
1.3 albertel 283: }
284:
1.9 albertel 285:
1.11 ! albertel 286: int current_dest=DEFAULT_DEST;
! 287: void change_destination(int which_dest)
! 288: {
! 289: if (which_dest < MAX_DEST) {
! 290: current_dest = which_dest;
! 291: } else {
! 292: fprintf(stderr,"Tried to set destination above MAX_DEST: %d", which_dest);
! 293: exit(1);
! 294: }
! 295: }
! 296:
! 297: void send_to(int which_dest, int which, char *text, va_list ap)
1.1 albertel 298: {
1.3 albertel 299: if (delay) {
300: append_message(&dyn_delayed,text,ap);
301: } else {
1.11 ! albertel 302: if (num_streams[which_dest]) {
1.9 albertel 303: if (which == ALL_STREAMS) {
304: int i;
1.11 ! albertel 305: for (i=0;i<num_streams[which_dest];i++) { append_message(&streams[which_dest][i],text,ap); }
1.9 albertel 306: } else {
1.11 ! albertel 307: append_message(&streams[which_dest][which],text,ap);
1.9 albertel 308: }
309: } else {
310: vprintf(text,ap);
311: }
1.3 albertel 312: }
1.9 albertel 313: if (do_cache[current_cache]) {
314: append_message(&cached_data[current_cache],text,ap);
315: }
316: }
317:
318: void send(char *text,...)
319: {
320: va_list ap;
321: va_start(ap,text);
1.11 ! albertel 322: send_to(current_dest,ALL_STREAMS,text,ap);
1.2 albertel 323: }
324:
1.9 albertel 325: void send_stream(int which, char *text,...)
326: {
327: va_list ap;
328: va_start(ap,text);
1.11 ! albertel 329: send_to(current_dest,which,text,ap);
1.9 albertel 330: }
331:
1.11 ! albertel 332: int num_streams[MAX_DEST];
! 333: struct dyn_string streams[MAX_DEST][MAX_STREAMS];
! 334: void start_streams(int which_dest, int num) {
1.9 albertel 335: int i;
1.11 ! albertel 336: for(i=0; i<num; i++) { dyn_init(&streams[which_dest][i]); }
! 337: for(i=1; i<num; i++) { beg_mode[which_dest][i]=mode[current_dest][0];
! 338: mode[which_dest][i]=mode[current_dest][0]; }
! 339: num_streams[which_dest]=num;
! 340: current_dest = which_dest;
1.9 albertel 341: }
342:
1.11 ! albertel 343: void end_streams(int which_dest, int which) {
1.9 albertel 344: int i;
1.11 ! albertel 345: start_mode(beg_mode[which_dest][which],NULL);
! 346: fputs(streams[which_dest][which].str,stdout);
! 347: for(i=0; i<num_streams[which_dest]; i++) { dyn_free(&streams[which_dest][which]); }
! 348: num_streams[which_dest]=0;
! 349: mode[DEFAULT_DEST][0]=mode[which_dest][which];
! 350: start_mode(mode[DEFAULT_DEST][0],NULL);
! 351: }
! 352:
! 353: int is_dest_empty(int which_dest) {
! 354: int i,empty=1;
! 355:
! 356: if ( num_streams[which_dest] ) {
! 357: for(i=0; i<num_streams[which_dest]; i++) {
! 358: if (streams[which_dest][i].str != NULL) { empty=0; break; }
! 359: }
! 360: } else {
! 361: if (streams[which_dest][0].str != NULL) { empty=0; }
! 362: }
! 363: return empty;
1.9 albertel 364: }
365:
1.11 ! albertel 366: int mode[MAX_DEST][MAX_STREAMS];
! 367: int watch_mode[MAX_DEST][MAX_STREAMS];
! 368: int beg_mode[MAX_DEST][MAX_STREAMS];
1.3 albertel 369: void end_mode()
1.2 albertel 370: {
1.11 ! albertel 371: end_mode_stream(current_dest, ALL_STREAMS);
1.9 albertel 372: }
373:
1.11 ! albertel 374: void end_mode_stream(int which_dest, int which)
1.9 albertel 375: {
1.11 ! albertel 376: if (num_streams[which_dest]) {
1.9 albertel 377: if (which == ALL_STREAMS) {
378: int i;
1.11 ! albertel 379: for (i=0;i<num_streams[which_dest];i++) { end_mode_stream(which_dest,i); }
1.9 albertel 380: return;
381: }
382: } else {
383: which=0;/* if streams aren't active make sure which is correct */
384: }
1.11 ! albertel 385: switch (mode[which_dest][which]) {
1.9 albertel 386: case MODE_COMMENT: send_stream(which,"</comment>\n"); break;
387: case MODE_BLOCK: send_stream(which,"</block>\n"); break;
388: case MODE_SCRIPT: send_stream(which,"</script>\n"); break;
389: case MODE_OUTTEXT: send_stream(which,"<endouttext />\n"); break;
390: case MODE_ANSWER: send_stream(which,"\n"); break;
391: case MODE_IMPORT: send_stream(which,"</import>\n"); break;
1.3 albertel 392: case MODE_NONE: break;
393: }
1.11 ! albertel 394: mode[which_dest][which]=MODE_NONE;
! 395: watch_mode[which_dest][which]=0;
1.2 albertel 396: }
397:
1.3 albertel 398: void start_mode(int newmode,char* args)
1.2 albertel 399: {
1.11 ! albertel 400: start_mode_stream(current_dest,ALL_STREAMS,newmode,args);
1.9 albertel 401: }
402:
1.11 ! albertel 403: void start_mode_stream(int which_dest,int which,int newmode,char* args)
1.9 albertel 404: {
1.11 ! albertel 405: if (num_streams[which_dest]) {
1.9 albertel 406: if (which == ALL_STREAMS) {
407: int i;
1.11 ! albertel 408: for (i=0;i<num_streams[which_dest];i++) { start_mode_stream(which_dest,i,newmode,args); }
1.9 albertel 409: return;
410: } else {
1.11 ! albertel 411: if (newmode == mode[which_dest][which]) return;
1.9 albertel 412: }
413: } else {
1.11 ! albertel 414: if (newmode == mode[which_dest][0]) return;
1.9 albertel 415: which=0;/* if streams aren't active make sure which is correct */
416: }
1.11 ! albertel 417: end_mode_stream(which_dest,which);
1.3 albertel 418: switch (newmode) {
1.9 albertel 419: case MODE_COMMENT: send_stream(which,"<comment>\n"); break;
420: case MODE_BLOCK: send_stream(which,"<block %s>\n",args); break;
421: case MODE_SCRIPT: send_stream(which,"<script type=\"loncapa/perl\">\n"); break;
422: case MODE_OUTTEXT: send_stream(which,"<startouttext />\n"); break;
423: case MODE_ANSWER: send_stream(which,"\n"); break;
424: case MODE_IMPORT: send_stream(which,"<import>"); break;
1.3 albertel 425: case MODE_NONE: break;
426: }
1.11 ! albertel 427: mode[which_dest][which]=newmode;
1.9 albertel 428: }
429:
430: int current_cache=-1;
431: int do_cache[MAX_CACHE];
432: struct dyn_string cached_data[MAX_CACHE];
433:
434: void new_cache()
435: {
436: current_cache++;
437: do_cache[current_cache]=1;
438: if (current_cache>MAX_CACHE) { exit(CACHE_ERROR); }
439: dyn_init(&cached_data[current_cache]);
440: }
441:
442: void start_cache()
443: {
444: do_cache[current_cache]=1;
445: }
446:
447: void stop_cache()
448: {
449: do_cache[current_cache]=0;
450: }
451:
452: void delete_cache()
453: {
454: if (current_cache > -1) {
455: dyn_free(&cached_data[current_cache]);
456: current_cache--;
457: }
1.1 albertel 458: }
459: /* =||>|===================== End of capaCommon.c =====================|<||= */
460:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>