Annotation of capa/capa51/pProj/qzparse.c, revision 1.4
1.1 albertel 1: /* ======================================================================== */
2: /* Feb. 10 1997 Isaac Tsai */
3: /* ======================================================================== */
4:
5: #ifdef NeXT
6: #include <stdlib.h>
7: #include <sys/types.h>
8: #include <sys/stat.h>
9: #include <bsd/curses.h>
10: #else
11: #include <curses.h>
12: #include <malloc.h>
13: double atof();
14: #endif
15:
16: #include <stdio.h>
17: #include <ctype.h>
18: #include <sys/types.h>
19: #include <sys/stat.h>
20: #include <signal.h>
21: #include <time.h>
22: #include <math.h>
23: #include <string.h>
24:
25:
26: #define YES 1
27:
28: #include "capaParser.h"
29: #include "capaCommon.h"
30: #include "ranlib.h"
31:
1.3 albertel 32: #define Q_ONLY 1
33: #define A_ONLY 2
34: #define QA_BOTH 3
35: #define F_CLASS 1
36: #define F_SECTIONS 2
37: #define F_STUDENT 3
38: #define F_ALPHA 4
39:
1.1 albertel 40: char *progname;
41:
42: void free_header(T_header* header)
43: {
44: capa_mfree(header->weight);
45: capa_mfree(header->partial_credit);
46: }
47:
48: void setdb_error(int set)
49: {
50: fprintf(stderr,"Set #%d has not had it's DB Header set. Please run Quizzer and set the DB Header.\n",set);
51: exit(-1);
52: }
53:
54: void
55: print_header(int mode,FILE *o_fp,int sec,int set,char *stu_nam,char *stu_num)
56: {
57: extern char *StartText_p;
58: int capaid = capa_PIN(stu_num,set,0);
59:
60: if( StartText_p != NULL ) {
61: fprintf(o_fp, "%s", StartText_p);
62: }
63:
1.2 albertel 64: switch(mode) {
65: case TeX_MODE:
66: if (StartText_p == NULL ) {
67: fprintf(o_fp, "Section %d {\\Large %s}\\hspace*{1in}",sec,stu_nam);
68: fprintf(o_fp, "{\\large %s}, CAPAID: %d, set %d",stu_num, capaid, set);
69: }
70: fprintf(o_fp, "\n\\begin{enumerate}\n");
71: break;
72: case ASCII_MODE:
73: fprintf(o_fp, "Section %d %s ", sec,stu_nam);
74: fprintf(o_fp, "%s, CAPAID: %d set %d\n\n",stu_num, capaid, set);
75: break;
76: case HTML_MODE:
77: fprintf(o_fp, "<H2>Section %d %s, ", sec,stu_nam);
78: fprintf(o_fp, "%s, CAPAID:%d set %d</H2>\n", stu_num,capaid,set);
79: fprintf(o_fp, "<OL>\n");
80: break;
81: }
1.1 albertel 82: }
83:
84: void
85: print_begin_item(int mode,FILE *o_fp,int q_idx)
86: {
87:
88: switch(mode) {
89: case TeX_MODE:
90: fprintf(o_fp, "\\item ");
91: break;
92: case ASCII_MODE:
93: fprintf(o_fp, "%d) ", q_idx);
94: break;
95: case HTML_MODE:
96: fprintf(o_fp, "<LI> ");
97: break;
98: }
99: }
100:
101:
102: void
103: unit_toHTML(char *u_str, char *r)
104: {
105: int i;
106: char *ch;
107:
108:
109: while(isspace(*ch)) ch++;
110: while( isalnum(*ch) ) {
111: r[i++] = *ch; ch++;
112: }
113: if( *ch == '^' ) {
114: r[i++] = '<'; r[i++]='s';r[i++]='u';r[i++]='p';r[i++]='>';
115: ch++; while(isspace(*ch)) ch++;
116: while( isalnum(*ch) ) {
117: r[i++] = *ch; ch++;
118: }
119: r[i++] = '<'; r[i++]='/'; r[i++]='s';r[i++]='u';r[i++]='p';r[i++]='>';
120: } else {
121: r[i++] = *ch; ch++;
122: }
123:
124:
125: }
126:
127: void
128: print_footer(int mode,FILE *o_fp)
129: {
130: extern char *EndText_p;
131:
132: switch(mode) {
133: case TeX_MODE:
134: fprintf(o_fp, "\n\\end{enumerate}\n");
135: break;
136: case ASCII_MODE:
137: fprintf(o_fp, "\n");
138: break;
139: case HTML_MODE:
140: fprintf(o_fp, "</OL>\n");
141: break;
142: }
143: if( EndText_p != NULL ) {
144: fprintf(o_fp, "%s", EndText_p);
145: }
146: }
147:
1.3 albertel 148: void output_problems(Problem_t* first_prob,int outputFlag,int q_cnt,FILE* dfp,
149: T_student* a_student,int setIdx)
150: {
151: extern int Parsemode_f;
152: extern char *EndText_p;
153: extern char *StartText_p;
154:
155: Problem_t *p;
156: int q_idx;
157: char* ans_str;
158:
159: p = first_prob;
160: switch(outputFlag) {
161: case Q_ONLY:
162: if( StartText_p != NULL) {
163: fprintf(dfp, "%s", StartText_p); fflush(dfp);
164: }
165: for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) {
166: fprintf(dfp, "%s", p->question); p = p->next;
167: }
168: if( EndText_p != NULL) {
169: fprintf(dfp, "%s", EndText_p); fflush(dfp);
170: }
171: break;
172: case A_ONLY:
173: print_header(Parsemode_f, dfp,a_student->s_sec,setIdx,a_student->s_nm,
174: a_student->s_sn);
175: for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) {
176: print_begin_item(Parsemode_f,dfp,q_idx+1);
177: ans_str = answers_string(Parsemode_f,p);
178: fprintf(dfp, "%s",ans_str); fflush(dfp);
179: capa_mfree((char *)ans_str);
180: p = p->next;
181: }
182: print_footer(Parsemode_f, dfp);
183: break;
184: case QA_BOTH:
185: if( StartText_p != NULL ) {
186: fprintf(dfp, "%s", StartText_p);
187: }
188: for( q_idx = 0; q_idx < q_cnt; printf("."),fflush(stdout), q_idx++ ) {
189: fprintf(dfp, "%s", p->question); fflush(dfp);
190: ans_str = answers_string(Parsemode_f,p);
191: fprintf(dfp, "%s",ans_str); fflush(dfp);
192: capa_mfree((char *)ans_str);
193: p = p->next;
194: }
195: if( EndText_p != NULL ) {
196: fprintf(dfp, "%s", EndText_p);
197: }
198: break;
199: }
200: }
201:
1.1 albertel 202: /* ============================================================== */
203: /* qz --> tex -Tq */
204: /* qz --> html -Ha */
205: /* qz --> ascii -Ab */
206: /* question only q */
207: /* answer only a */
208: /* both b */
209: /* for entire class -C */
210: /* for a range of sections -Sec 2:6 */
211: /* for a section -Sec 2 */
212: /* for a student -Stu 12345678 */
213: /* output a set -Set 2 */
214: /* output a range of sets -Set 1:6 */
215: /* output blocksize -b 30 */
216: /* ============================================================== */
217:
218: void usage()
219: {
220: printf("USAGE: %s [ -[T|H|A][a|b] ] [-Sec [n|n:m] | -Stu sn [-o filename] ]\n",progname);
221: printf(" [ -Set [n|n:m] ] [-c path_to_class] [-d outputdirectory]\n");
222: printf(" Example 1: %s -Tb -sec 2:3 -set 2:5\n", progname);
223: printf(" will generate tex files with both questions and answers\n");
224: printf(" for sections 2 to 3, sets 2 to 5\n");
225: printf(" Example 2: %s -Ha -stu A12345678 -set 3\n", progname);
226: printf(" will generate html files with answer only \n");
227: printf(" for student A12345678 set 3\n");
228: printf(" -T = tex mode\n");
229: printf(" -H = html mode\n");
230: printf(" -A = ascii mode\n");
231: printf(" = default question only\n");
232: printf(" a = answer only\n");
233: printf(" b = both question and answer\n");
234: printf(" -nopagebreak = don't put a \\clearpage between assignments\n");
235: printf(" -Sec 3 = for section 3\n");
236: printf(" -Sec 3:7 = from section 3 to section 7\n");
237: printf(" -Stu A12345678 = for a specified student\n");
238: printf(" -Set 1 = output set 1\n");
239: printf(" -Set 3:4 = output from set 3 to set 4\n");
240: printf(" -c class_path\n");
241: printf(" -o output_filename_with_absolute_path (only for a student)\n");
242: printf(" -d directory_to_create_files_in (default is class_path/TeX)\n");
243: printf("-------This is version %s @ %s\n",CAPA_VER,COMPILE_DATE);
244: printf("------------------------------------------------------\n");
245: }
246:
247: /* filter out the number to be [1:999] */
248: int scan_num(char *num_str,int *first, int *second) {
249: char tmp_str[SMALL_LINE_BUFFER], *ch;
250: int ii=0, a_num, b_num, result=0;
251:
252: ch = num_str;
253: tmp_str[ii] = 0;
254: while( isspace(*ch) ) ch++;
255: while(isdigit(*ch)) { tmp_str[ii++] = *ch; ch++; }
256: tmp_str[ii] = 0;
257: sscanf(tmp_str,"%d",&a_num);
258: if( a_num < 0 || a_num > 999 ) a_num = 1;
259: *first = a_num;
260: result = 1;
261: while( isspace(*ch) ) ch++;
262: if( *ch == ':' ) {
263: ch++;
264: while( isspace(*ch) ) ch++;
265: ii=0; tmp_str[ii] = 0;
266: while( isdigit(*ch) ) { tmp_str[ii++] = *ch; ch++; }
267: tmp_str[ii] = 0;
268: sscanf(tmp_str,"%d",&b_num);
269: if( b_num < 0 || b_num > 999 ) b_num = 1;
270: if( a_num > b_num ) b_num = a_num;
271: *second = b_num;
272: result = 2;
273: }
274: return (result);
275: }
276:
1.3 albertel 277: FILE* start_set(int directory_specified,char* out_directory,int file_specified,
278: char *out_filename,char* filestart,char* filename)
279: {
280: extern int Parsemode_f;
281:
282: char cmd[MAX_BUFFER_SIZE];
283: FILE* dfp;
284:
285: if (file_specified == 0) {
286: if (directory_specified == 0 ) {
287: switch( Parsemode_f ) {
288: case TeX_MODE:
289: sprintf(filename,"TeX/%s.tex",filestart);
290: break;
291: case ASCII_MODE:
292: sprintf(filename,"ASCII/%s.ascii",filestart);
293: break;
294: case HTML_MODE:
295: sprintf(filename,"HTML/%s.text",filestart);
296: break;
297: }
298: } else {
299: switch( Parsemode_f ) {
300: case TeX_MODE:
301: sprintf(filename,"%s/%s.tex",out_directory,filestart);
302: break;
303: case ASCII_MODE:
304: sprintf(filename,"%s/%s.ascii",out_directory,filestart);
305: break;
306: case HTML_MODE:
307: sprintf(filename,"%s/%s.text", out_directory,filestart);
308: break;
309: }
310: }
311: } else {
312: if (directory_specified == 0 ) {
313: sprintf(filename,"%s",out_filename);
314: } else {
315: sprintf(filename,"%s/%s",out_directory,out_filename);
316: }
317: }
318: switch ( Parsemode_f ) {
319: case TeX_MODE: sprintf(cmd, "cp TeXheader %s\n",filename); system(cmd); break;
320: default: sprintf(cmd,"rm %s\n",filename);system(cmd); break;
321: }
322:
323: if((dfp=fopen(filename,"a"))==NULL) { printf("File error\n"); exit(-1); }
324: return dfp;
325: }
326:
327: void end_set(FILE*dfp,char* filename)
328: {
329: extern int Parsemode_f;
330: char cmd[MAX_BUFFER_SIZE];
331: fflush(dfp);
332: fclose(dfp);
333: if(Parsemode_f == TeX_MODE) {
334: sprintf(cmd, "cat TeXfooter >> %s\n", filename);
335: system(cmd);
336: }
337: }
338:
339: void end_page(FILE*dfp,int pagebreak)
340: {
341: extern int Parsemode_f;
342: if( Parsemode_f == TeX_MODE && pagebreak ) {
343: fprintf(dfp, "\\clearpage\n\\setcounter{page}{1}\n"); fflush(dfp);
344: } else {
345: printf("\n");
346: }
347: }
348:
1.1 albertel 349: int main (int argc, char **argv)
350: {
351: extern int Parsemode_f;
352: extern char *EndText_p;
353: extern char *StartText_p;
354: extern char *ErrorMsg_p;
355: extern int ErrorMsg_count;
356:
357: Problem_t *first_prob,*p;
358: T_student *students_p,*s_p, a_student;
359: int num_students, q_cnt, result, inputNotOK = 1,
360: ii, sectionIdx, setIdx = 1, q_idx, outputFlag = 0;
1.3 albertel 361: char filename[FILE_NAME_LENGTH], path[FILE_NAME_LENGTH],
362: filestart[FILE_NAME_LENGTH];
1.1 albertel 363: FILE *dfp;
364: int tmp_num, first_stu, file_specified, directory_specified;
365: int ForWhat = F_SECTIONS, pagebreak=1,
366: StartSec = 1, EndSec = 1, StartSet = 1, EndSet = 1;
367: char StuNum[MAX_STUDENT_NUMBER+1];
368: char out_filename[FILE_NAME_LENGTH],out_directory[FILE_NAME_LENGTH];
369: char cmd[SMALL_LINE_BUFFER], *ans_str;
370:
371: /* qz --> tex -T */
372: /* qz --> html -Ha */
373: /* qz --> ascii -Ab */
374: /* answer only a */
375: /* both b */
376: /* for entire class -C */
377: /* for a range of sections -Sec 2:6 */
378: /* for a section -Sec 2 */
379: /* for a student -Stu 12345678 */
380: /* output a set -Set 2 */
381: /* output a range of sets -Set 1:6 */
382:
383: /* default */
384: Parsemode_f = TeX_MODE; ForWhat = F_SECTIONS; outputFlag=Q_ONLY;
385: file_specified=0;
386: out_filename[0]='\0';
387: directory_specified=0;
388: out_directory[0]='\0';
389: for( progname = *argv++; --argc; argv++) {
390: if ( argv[0][0] == '-' ) {
391: switch(argv[0][1]) {
392: case 'T': Parsemode_f = TeX_MODE;
393: outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY));
394: break;
395: case 'H': Parsemode_f = HTML_MODE;
396: outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY));
397: break;
398: case 'A': Parsemode_f = ASCII_MODE;
399: outputFlag=(argv[0][2] == 'a' ? A_ONLY :(argv[0][2] == 'b' ? QA_BOTH : Q_ONLY));
400: break;
401: case 'S':
402: case 's': if( strncasecmp(argv[0],"-sec",4) == 0 ) {
403: tmp_num = scan_num(argv[1],&StartSec,&EndSec);
404: if( tmp_num == 1 ) { EndSec = StartSec; }
405: ForWhat = F_SECTIONS;
406: } else if( strncasecmp(argv[0],"-stu",4) == 0 ) {
407: for(ii=0;ii<MAX_STUDENT_NUMBER;ii++) {
408: StuNum[ii] = argv[1][ii];
409: }
410: StuNum[ii]=0;
411: ForWhat = F_STUDENT;
412: } else if( strncasecmp(argv[0],"-set",4) == 0 ) {
413: tmp_num = scan_num(argv[1],&StartSet,&EndSet);
414: if( tmp_num == 1 ) { EndSet = StartSet; }
415: } else {
416: usage();
417: }
418: break;
419: case 'c': strcpy(path, argv[1]);
420: if(capa_access(path, F_OK) == -1) {
421: inputNotOK = 1;
422: } else {
423: inputNotOK = 0;
424: }
425: break;
426: case 'o':
427: if (argc == 1 || argv[1][0] == '-') {
428: usage(); return 0;
429: } else {
430: strcpy(out_filename, argv[1]); file_specified=1; break;
431: }
432: case 'd':
433: if (argc == 1 || argv[1][0] == '-') {
434: usage(); return 0; break;
435: } else {
436: strcpy(out_directory, argv[1]); directory_specified=1; break;
437: }
438: case 'n':
439: pagebreak=0;break;
440: case 'u': case 'h': default: usage(); return(0); break;
441: }
442: }
443: }
444: printf(" %s running in %s mode, %s for %s, ", progname,
445: (Parsemode_f == TeX_MODE ? "TeX" : (Parsemode_f == ASCII_MODE ? "ASCII" : "HTML")),
446: (outputFlag==A_ONLY ? "answer only" : (outputFlag==QA_BOTH? "question and answer" : "question only")),
447: (ForWhat == F_STUDENT ? "a student" : "section" ) );
448: if( ForWhat == F_STUDENT ) {
449: printf(" for student %s,",StuNum);
450: } else {
451: if(StartSec==EndSec) {
452: printf(" for section %d,", StartSec);
453: }
454: else {
455: printf(" from section %d to %d,",StartSec, EndSec);
456: }
457: }
458: if(StartSet==EndSet) { printf(" set %d\n",StartSet); } else { printf(" from set %d to %d\n", StartSet, EndSet); }
459:
460: while ( inputNotOK ) {
461: puts("Enter the ABSOLUTE path of class");
462: scanf("%s", path);
463: if( capa_access(path, F_OK) == -1 ) {
464: } else {
465: sprintf(filename,"%s/classl",path);
466: if( capa_access(filename, F_OK) == -1 ) {
467: puts("There isn't a classl file in this CLASS directory\nPlease Specify another class");
468: } else {
469: inputNotOK = 0;
470: }
471: }
472: }
473:
474: if( (ForWhat == F_STUDENT) && strlen(StuNum) == 0 ) {
475: inputNotOK = 1;
476: while ( inputNotOK ) {
477: puts("Enter student number"); scanf("%s", StuNum);
478: if( strlen(StuNum) == MAX_STUDENT_NUMBER ) { inputNotOK = 0; }
479: }
480: }
481: if ( file_specified == 0) {
482: if ( directory_specified == 0) {
483: switch( Parsemode_f ) {
484: case TeX_MODE: sprintf(filename,"%s/TeX",path); break;
485: case ASCII_MODE: sprintf(filename,"%s/ASCII",path); break;
486: case HTML_MODE: sprintf(filename,"%s/HTML",path); break;
487: default: sprintf(filename,"%s/TeX",path); Parsemode_f = TeX_MODE; break;
488: }
489: } else {
490: sprintf(filename,"%s",out_directory);
491: }
492: if( capa_access(filename, F_OK) == -1 ) {
493: if ( mkdir(filename, S_IREAD | S_IWRITE | S_IEXEC ) == -1 ) {
494: printf("Unable to write to %s\n",filename);
495: printf("Please check this directory and run %s again.\n",progname);
496: return(-1);
497: }
498: }
499:
500: } else {
501: if ( directory_specified == 0) {
502: } else {
503: sprintf(filename,"%s",out_directory);
504: }
505: }
506: chdir(path);
507:
508: if ( ForWhat == F_SECTIONS ) {
509: T_dates* dates;
510: T_header header;
511: for(ii=StartSet;ii<=EndSet;ii++) {
1.3 albertel 512: if (capa_get_header(&header,ii)<0) setdb_error(ii);
513: free_header(&header);
514: if (capa_get_all_dates(ii,&dates)<0) setdb_error(ii);
515: free_dates(dates);
1.1 albertel 516: }
517: }
518:
1.3 albertel 519: switch (ForWhat) {
520: case F_STUDENT:
521: result = capa_get_student(StuNum, &a_student);
522: if ( result == 0 ) {
523: fprintf(stderr,"Unable to find student %s in %s/classl",StuNum,path);
524: exit(-1);
525: } else {
526: if (result == -1 ) {
527: fprintf(stderr,"Unable to read %s/classl",path);
528: exit(-1);
529: }
1.1 albertel 530: }
1.3 albertel 531: dfp=start_set(directory_specified,out_directory,file_specified,out_filename,
532: StuNum,filename);
533: for(setIdx=StartSet; setIdx <= EndSet; setIdx++) {
534: result = capa_parse(setIdx, &first_prob, StuNum, &q_cnt, NULL);
535: if ( result != 0 ) {
536: output_problems(first_prob,outputFlag,q_cnt,dfp,&a_student,setIdx);
537: free_problems(first_prob);
538: }
539: if( setIdx < EndSet ) { end_page(dfp,pagebreak); }
540: if( ErrorMsg_count > 0 ) { printf("%s",ErrorMsg_p); }
1.1 albertel 541: }
1.4 ! albertel 542: end_set(dfp,filename);
1.3 albertel 543: printf("\n DONE Student %s\n",StuNum);
544: break;
545: case F_SECTIONS:
546: for(sectionIdx = StartSec; sectionIdx <= EndSec; sectionIdx++ ) {
547: num_students = capa_sorted_section(&students_p, sectionIdx);
548: if( num_students > 0 ) {
549: printf("Section %2d: %d students\n",sectionIdx,num_students);
550: for(setIdx=StartSet; setIdx <= EndSet; setIdx++) {
551: sprintf(filestart,"section%d-set%d",sectionIdx,setIdx);
552: dfp=start_set(directory_specified,out_directory,file_specified,
553: out_filename,filestart,filename);
554: for(s_p = students_p,first_stu=1; s_p ; s_p = s_p->s_next ) {
555: s_p->s_sn[MAX_STUDENT_NUMBER]=0;
556: printf(" Student: %s%s set %d\n",s_p->s_nm,s_p->s_sn,setIdx);
557: result = capa_parse(setIdx, &first_prob, s_p->s_sn, &q_cnt, NULL);
558: if ( result != 0 ) {
559: output_problems(first_prob,outputFlag,q_cnt,dfp,s_p,setIdx);
560: free_problems(first_prob);
561: if( s_p->s_next != NULL ) { end_page(dfp,pagebreak); }
562: }
563: }
564: end_set(dfp,filename);
565: printf("\n DONE set%2d\n",setIdx);
566: }
567: }
568: printf("\n DONE section%2d\n",sectionIdx);
1.1 albertel 569: }
1.3 albertel 570: free_students(students_p);
571: break;
572: case F_ALPHA:
573: break;
1.1 albertel 574: }
575: printf("ALL DONE\n");
576: return (0);
577: }
578:
579:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>