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, 7 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.
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: {
114: int errcode,temp;
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; }*/
155: if (!(temp=yylex())) { errcode = Lexi_qnum; } else { errcode = 0; }
156: fprintf(stderr,"\nExited on: %d\n",temp);
157: fprintf(stderr,"Current cache: %d\n",current_cache);
158: fprintf(stderr,"Flushing:\n");
159: flush_delayed();
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:
171: int dyn_maxlen=1000000;
172: int delay;
173: void dyn_init(struct dyn_string *dyn)
174: {
175: dyn->len=0;
176: dyn->max=0;
177: dyn->str=NULL;
178: }
179:
180: void dyn_free(struct dyn_string* dyn)
181: {
182: if (dyn->str) {
183: free(dyn->str);dyn->str=NULL;
184: dyn->len=0;
185: dyn->max=0;
186: }
187: }
188:
189:
190: int append_message(struct dyn_string *dyn_msg,char *format,va_list ap) {
191: char *new;
192: int len,result;
193:
194: if ((result=vasprintf(&new,format,ap))==-1) {
195: fprintf(stderr,"vaspintf didn't like :%s:",format);
196: exit(1);
197: }
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:
241: void add_delayed(char *format, ...) {
242: va_list ap;
243:
244: va_start(ap,format);
245: append_message(&dyn_delayed,format,ap);
246: if (do_cache[current_cache]) {
247: append_message(&cached_data[current_cache],format,ap);
248: }
249: }
250:
251: void flush_delayed()
252: {
253: delay=0;
254: if (dyn_delayed.str) { send(dyn_delayed.str); }
255: dyn_free(&dyn_delayed);dyn_init(&dyn_delayed);
256: }
257:
258:
259: void send_to(int which, char *text, va_list ap)
260: {
261: if (delay) {
262: append_message(&dyn_delayed,text,ap);
263: } else {
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: }
274: }
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);
285: }
286:
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];
312: void end_mode()
313: {
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;
336: case MODE_NONE: break;
337: }
338: mode[which]=MODE_NONE;
339: watch_mode[which]=0;
340: }
341:
342: void start_mode(int newmode,char* args)
343: {
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);
362: switch (newmode) {
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;
370: case MODE_NONE: break;
371: }
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: }
403: }
404: /* =||>|===================== End of capaCommon.c =====================|<||= */
405:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>