1 /* Frames */
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdarg.h>
5 #include "crt.h"
6 #include "crf.h"
7
8 char compiler_name[MAX_ID_LEN];
9 char module_prefix[MAX_ID_LEN];
10 char source_name[100];
11
12 static char GEN_PREFIX[100]; /* prefix line string used in GenCode */
13 static int CurrTab;
14 static int CurrCol;
15
16 int GenParserOptions(FILE *Out, char *option);
17 int GenScannerOptions(FILE *Out, char *option);
18 void GenParserErrors(FILE *Out);
19 void GenScannerTokens(FILE *Out);
20
21 #define NAMELEN 20
22
23 static char Scan_C_Format[NAMELEN];
24 static char Scan_H_Format[NAMELEN];
25 static char Parser_C_Format[NAMELEN];
26 static char Parser_H_Format[NAMELEN];
27 static char Compiler_Format[NAMELEN];
28
InitFrameVars(void)29 void InitFrameVars(void)
30 {
31 if (getenv("CRFRAMES"))
32 strcpy(Frames_Path, getenv("CRFRAMES"));
33
34 if (getenv("CRHEXT")) {
35 strncpy(h_ext, getenv("CRHEXT"), 5); h_ext[5] = '\0';
36 }
37
38 if (getenv("CRCEXT")) {
39 strncpy(c_ext, getenv("CRCEXT"), 5); c_ext[5] = '\0';
40 }
41 }
42
SetupFrameVars(void)43 void SetupFrameVars(void)
44 {
45 if (strlen(Frames_Path) > 0) {
46 #if __MSDOS__ || MSDOS || WIN32 || __WIN32__
47 if (GenCplusplus) strcat(Frames_Path, "\\cplus2\\");
48 else strcat(Frames_Path, "\\");
49 #else
50 if (GenCplusplus) strcat(Frames_Path, "/cplus2/");
51 else strcat(Frames_Path, "/");
52 #endif
53 }
54
55 sprintf(Scan_C_Format, "%%ss.%s", c_ext);
56 sprintf(Scan_H_Format, "%%ss.%s", h_ext);
57 sprintf(Parser_C_Format, "%%sp.%s", c_ext);
58 sprintf(Parser_H_Format, "%%sp.%s", h_ext);
59 sprintf(Compiler_Format, "%%s.%s", c_ext);
60 }
61
62 /* get next character from a frame */
CopyNextCh(FILE * frame)63 static int CopyNextCh(FILE *frame)
64 {
65 int c;
66
67 c = fgetc(frame);
68 if (c == 10) strcpy(GEN_PREFIX, "");
69 else if (c == '\t') strcat(GEN_PREFIX, "\t");
70 else strcat(GEN_PREFIX, " ");
71 return c;
72 }
73
74 /* reset line prefix */
CopyFrameReset(void)75 static void CopyFrameReset(void)
76 {
77 strcpy(GEN_PREFIX, "");
78 }
79
80 /* copy from "frame" to "out" until an option (-->) is found */
81
CopyFrame(FILE * frame,FILE * out,char * option)82 static void CopyFrame(FILE *frame, FILE *out, char *option)
83 {
84 char *s;
85 int c;
86
87 s = option;
88 while (1) {
89 c = CopyNextCh(frame);
90 /* find first '-' */
91 while (c != EOF && c != '-') {
92 fputc(c, out);
93 c = CopyNextCh(frame);
94 }
95 if (c == EOF) break;
96 /* find second '-' */
97 c = CopyNextCh(frame);
98 if (c != '-') {
99 fputc('-', out);
100 fputc(c, out);
101 continue;
102 }
103 /* find '>' */
104 c = CopyNextCh(frame);
105 if (c != '>') {
106 fputc('-', out);
107 fputc('-', out);
108 fputc(c, out);
109 continue;
110 }
111 /* found '-->' */
112
113 c = fgetc(frame);
114 while (c >= 'A' && c <= 'Z' ||
115 c >= 'a' && c <= 'z' ||
116 c >= '0' && c <= '9') {
117 *s++ = c;
118 c = fgetc(frame);
119 }
120 *s = '\0';
121 GEN_PREFIX[strlen(GEN_PREFIX) - 3] = '\0';
122 ungetc(c, frame);
123 return;
124 }
125 strcpy(option, "ENDFILE");
126 }
127
128 /* generate a Case Terminal Set Condition */
GenCaseTermSet(FILE * out,Set * source)129 static void GenCaseTermSet(FILE *out, Set *source) /* OR only version */
130 {
131 int col = CurrCol, tab = CurrTab;
132 int c, i, t, first = 0;
133
134 if (Set_Empty(source)) {
135 GenCode(out, "default:");
136 return;
137 }
138
139 Set_GetRange(source, &i, &c);
140 for (; i <= c; i++) {
141 if (Set_IsItem(source, i)) {
142 if (first) {
143 GenCode(out, "$$%I", tab);
144 t = col;
145 while(t--) putc(' ', out);
146 }
147 GenCode(out, "case %T: ", i);
148 first++;
149 }
150 }
151 Set_Clean(source);
152 }
153
154 /* generate a Terminal Set Condition */
GenTermSetOR(FILE * out,Set * source)155 static void GenTermSetOR(FILE *out, Set *source) /* OR only version */
156 {
157 int col = CurrCol, tab = CurrTab;
158 int c, i, first, t;
159
160 if (Set_Empty(source)) {
161 GenCode(out, "1");
162 return;
163 }
164
165 first = 1;
166 Set_GetRange(source, &i, &c);
167 for (; i <= c; i++) {
168 if (Set_IsItem(source, i)) {
169 if (!first) {
170 GenCode(out, " ||$$%I", tab);
171 t = col;
172 while(t--) putc(' ', out);
173 }
174 GenCode(out, "Sym == %T", i);
175 first = 0;
176 }
177 }
178 Set_Clean(source);
179 }
180
181 /* generate a terminal set condition */
GenTermSet(FILE * out,Set * source)182 static void GenTermSet(FILE *out, Set *source)
183 {
184 int col = CurrCol, tab = CurrTab;
185 int c, i, j, t, first;
186
187 if (Set_Empty(source)) {
188 GenCode(out, "1");
189 return;
190 }
191
192 first = 1;
193 Set_GetRange(source, &i, &c);
194 do {
195 for (; i <= c; i++) if (Set_IsItem(source, i)) break;
196 if (i > c) break;
197 for (j = i; j <= c && Set_IsItem(source, j); j++);
198 j--;
199
200 if (!first) {
201 GenCode(out, " ||$$%I", tab);
202 t = col;
203 while(t--) putc(' ', out);
204 }
205 if (i == j) GenCode(out, "Sym == %T", i);
206 else GenCode(out, "Sym >= %T && Sym <= %T", i, j);
207 i = j + 1;
208 first = 0;
209 } while (1);
210 }
211
212 /* generate a Caracter Set condition */
GenCharSet(FILE * out,Set * set)213 static void GenCharSet(FILE *out, Set *set)
214 {
215 int col = CurrCol, tab = CurrTab;
216 int i, c, j, t, count;
217
218 Set_GetRange(set, &i, &c);
219 count = 0;
220 do {
221 for (; i <= c; i++) if (Set_IsItem(set, i)) break;
222 if (i>c) break;
223 for (j = i; j <= c && Set_IsItem(set, j); j++);
224 j--;
225
226 if (count) {
227 GenCode(out, " ||$$%I", tab);
228 t = col;
229 while(t--) putc(' ', out);
230 }
231 if (i == j) GenCode(out, "Scan_Ch == %#", i);
232 else GenCode(out, "Scan_Ch >= %# && Scan_Ch <= %#", i, j);
233 i = j + 1;
234 count++;
235 } while (1);
236 }
237
238 /* Gen_Code: (Same as fprintf)
239 $$ ==> New Line
240 $n ==> tabs(n)
241 %T ==> Terminal Name
242 %N ==> No Terminal Name
243 %# ==> char
244 %S ==> Terminals Set (Sym == X ..)
245 %X ==> Terminals Set (Case X: ..)
246 %C ==> Character Set (S_ch == X ...)
247 */
GenCode(FILE * out,char * fmt,...)248 void GenCode(FILE *out, char *fmt, ...)
249 {
250 va_list ap;
251
252 va_start(ap, fmt);
253 for ( ; *fmt; fmt++)
254 if (*fmt == '%')
255 switch (*++fmt) {
256 case 'd':
257 fprintf(out, "%d", va_arg(ap, int));
258 break;
259 case 'x':
260 fprintf(out, "%X", va_arg(ap, int));
261 break;
262 case 'c':
263 fprintf(out, "%c", va_arg(ap, int));
264 break;
265 case 's':
266 fputs(va_arg(ap, char *), out);
267 break;
268 case '#':
269 {
270 int n = va_arg(ap, int);
271 if (n < 32 ||
272 n == '\\' ||
273 n == '\'' ||
274 n > 126) fprintf(out, "%d", n);
275 else fprintf(out, "'%c'", n);
276 break;
277 }
278 case 'T':
279 { /* Terminal */
280 Name s;
281 GetTermName(va_arg(ap, int), s);
282 fprintf(out, "%s", s);
283 break;
284 }
285 case 'N':
286 { /* NonTerminal */
287 PNTermNode ntn = GetNTermP(va_arg(ap, int));
288 fprintf(out, "%s", ntn->name);
289 break;
290 }
291 case 'S':
292 { /* NonTerminal Set */
293 Set *s = va_arg(ap, Set *);
294 if (O_option) GenTermSetOR(out, s);
295 else GenTermSet(out, s);
296 break;
297 }
298 case 'X':
299 { /* NonTerminal Set */
300 Set *s = va_arg(ap, Set *);
301 GenCaseTermSet(out, s);
302 break;
303 }
304 case 'C':
305 { /* Character Set */
306 Set *s = va_arg(ap, Set *);
307 GenCharSet(out, s);
308 break;
309 }
310 case 'I':
311 { /*indent */
312 int n = va_arg(ap, int);
313 CurrTab = n;
314 while (n-- > 0) putc('\t', out);
315 break;
316 }
317 default:
318 {
319 putc('%', out);
320 putc(*fmt, out);
321 break;
322 }
323 }
324 else
325 if (*fmt == '$') {
326 switch (*++fmt) {
327 case '$' :
328 fprintf(out, "\n%s", GEN_PREFIX);
329 CurrCol = 0;
330 break;
331 case '0':
332 case '1':
333 case '2':
334 case '3':
335 case '4':
336 case '5':
337 case '6':
338 case '7':
339 case '8':
340 case '9':
341 {
342 int n = *fmt - '0';
343 while (n-- > 0) putc('\t', out);
344 break;
345 }
346 default :
347 fprintf(out, "$%c", *fmt);
348 }
349 }
350 else {
351 putc(*fmt, out);
352 CurrCol++;
353 }
354 va_end(ap);
355 }
356
357 /* return symbolic character name */
SymCharName(unsigned char c,char * asciiname)358 void SymCharName(unsigned char c, char *asciiname)
359 {
360 switch (c) {
361 case 0 :
362 strcpy(asciiname, "Nul");
363 return;
364 case 8 :
365 strcpy(asciiname, "BS");
366 return;
367 case 9 :
368 strcpy(asciiname, "HT");
369 return;
370 case 10 :
371 strcpy(asciiname, "LF");
372 return;
373 case 12 :
374 strcpy(asciiname, "FF");
375 return;
376 case 13 :
377 strcpy(asciiname, "CR");
378 return;
379 case 27 :
380 strcpy(asciiname, "ESC");
381 return;
382 case ' ' :
383 strcpy(asciiname, "_"); /* SP */
384 return;
385 case '!' :
386 strcpy(asciiname, "Bang");
387 return;
388 case '"' :
389 strcpy(asciiname, "Dquote");
390 return;
391 case '#' :
392 strcpy(asciiname, "Hash");
393 return;
394 case '$' :
395 strcpy(asciiname, "Dollar");
396 return;
397 case '%' :
398 strcpy(asciiname, "Percent");
399 return;
400 case '&' :
401 strcpy(asciiname, "And");
402 return;
403 case '\'':
404 strcpy(asciiname, "Squote");
405 return;
406 case '(' :
407 strcpy(asciiname, "Lparen");
408 return;
409 case ')' :
410 strcpy(asciiname, "Rparen");
411 return;
412 case '*' :
413 strcpy(asciiname, "Star");
414 return;
415 case '+' :
416 strcpy(asciiname, "Plus");
417 return;
418 case ',' :
419 strcpy(asciiname, "Comma");
420 return;
421 case '-' :
422 strcpy(asciiname, "Minus");
423 return;
424 case '.' :
425 strcpy(asciiname, "Point");
426 return;
427 case '/' :
428 strcpy(asciiname, "Slash");
429 return;
430 case ':' :
431 strcpy(asciiname, "Colon");
432 return;
433 case ';' :
434 strcpy(asciiname, "Semicolon");
435 return;
436 case '<' :
437 strcpy(asciiname, "Less");
438 return;
439 case '=' :
440 strcpy(asciiname, "Equal");
441 return;
442 case '>' :
443 strcpy(asciiname, "Greater");
444 return;
445 case '?' :
446 strcpy(asciiname, "Query");
447 return;
448 case '@' :
449 strcpy(asciiname, "At");
450 return;
451 case '[' :
452 strcpy(asciiname, "Lbrack");
453 return;
454 case '\\':
455 strcpy(asciiname, "Backslash");
456 return;
457 case ']' :
458 strcpy(asciiname, "Rbrack");
459 return;
460 case '^' :
461 strcpy(asciiname, "Uparrow");
462 return;
463 case '_' :
464 strcpy(asciiname, "Underscore");
465 return;
466 case '`' :
467 strcpy(asciiname, "Accent");
468 return;
469 case '{' :
470 strcpy(asciiname, "Lbrace");
471 return;
472 case '|' :
473 strcpy(asciiname, "Bar");
474 return;
475 case '}' :
476 strcpy(asciiname, "Rbrace");
477 return;
478 case '~' :
479 strcpy(asciiname, "Tilde");
480 return;
481 case '0' :
482 case '1' :
483 case '2' :
484 case '3' :
485 case '4' :
486 case '5' :
487 case '6' :
488 case '7' :
489 case '8' :
490 case '9' :
491 sprintf(asciiname, "D%c", c);
492 return;
493 default :
494 strcpy(asciiname, " ");
495 if (c >= '0' && c <= '9' ||
496 c >= 'A' && c <= 'Z' ||
497 c >= 'a' && c <= 'z') asciiname[0] = c;
498 else sprintf(asciiname, "Asc%d", c);
499 return;
500 }
501 }
502
OpenFile(char * name,char * op,int GenError)503 FILE *OpenFile(char *name, char *op, int GenError)
504 {
505 FILE *F;
506 if((F = fopen(name, op)) == NULL) {
507 if (GenError) {
508 fprintf(stderr, "Unable to open file %s\n", name);
509 exit(1);
510 }
511 }
512 return F;
513 }
514
515 #if !( __MSDOS__ || MSDOS || WIN32 || __WIN32__)
stricmp(char * s1,char * s2)516 int stricmp(char *s1, char *s2)
517 {
518 char c1, c2;
519 int c;
520
521 if (strlen(s1) > strlen(s2)) c = strlen(s2);
522 else c = strlen(s1);
523
524 while (c--) {
525 c1 = (*s1 >= 'a' && *s1 <= 'z') ? *s1 - 32 : *s1;
526 c2 = (*s2 >= 'a' && *s2 <= 'z') ? *s2 - 32 : *s2;
527 if (c1 < c2) return -1;
528 if (c1 > c2) return 1;
529 s1++;
530 s2++;
531 }
532 return 0;
533 }
534 #endif
535
ProcessFrame(FILE * In,FILE * Out,char * Prefix)536 static void ProcessFrame(FILE *In, FILE *Out, char *Prefix)
537 {
538 char option[100];
539
540 CopyFrameReset();
541 while (1) {
542 CopyFrame(In, Out, option);
543 if (!stricmp(option, "ErrorFile")) {
544 fprintf(Out, "\"%se.%s\"", Prefix, h_ext);
545 } else
546 if (!stricmp(option, "ScanHeader")) {
547 fprintf(Out, "\"%ss.%s\"", Prefix, h_ext);
548 } else
549 if (!stricmp(option, "ParserHeader")) {
550 fprintf(Out, "\"%sp.%s\"", Prefix, h_ext);
551 } else
552 if (!stricmp(option, "ErrorHeader")) {
553 fprintf(Out, "\"%se.%s\"", Prefix, h_ext);
554 } else
555 if (!stricmp(option, "TokensHeader")) {
556 fprintf(Out, "\"%sc.%s\"", Prefix, h_ext);
557 } else
558 if (!stricmp(option, "ScanClass")) {
559 fprintf(Out, "%sScanner", Prefix);
560 } else
561 if (!stricmp(option, "ParserClass")) {
562 fprintf(Out, "%sParser", Prefix);
563 } else
564 if (GenParserOptions(Out, option)) {
565 } else
566 if (GenScannerOptions(Out, option)) {
567 } else
568 if (!stricmp(option, "ENDFILE")) break;
569 }
570 }
571
GenFrame(char * Prefix,char * InName,char * OutName)572 static void GenFrame(char *Prefix, char *InName, char *OutName)
573 {
574 FILE *InFile, *OutFile;
575 char FileName[100];
576
577 sprintf(FileName, "%s%s", Frames_Path, InName);
578 InFile = OpenFile(FileName, "r", 1);
579
580 sprintf(FileName, OutName, Prefix);
581 OutFile = OpenFile(FileName, "w", 1);
582
583 ProcessFrame(InFile, OutFile, Prefix);
584
585 fclose(InFile);
586 fclose(OutFile);
587 }
588
589 /* generate compiler */
GenCompiler()590 void GenCompiler()
591 {
592 FILE *InFile, *OutFile;
593 char FileName[100];
594
595 sprintf(FileName, Compiler_Format, module_prefix);
596 OutFile = OpenFile(FileName, "w", 1);
597
598 sprintf(FileName, "%s.frm", module_prefix);
599 InFile = OpenFile(FileName, "r", 0);
600 if (InFile == NULL) {
601 sprintf(FileName, "%scompiler.frm", Frames_Path);
602 InFile = OpenFile(FileName, "r", 1);
603 }
604
605 ProcessFrame(InFile, OutFile, module_prefix);
606
607 fclose(InFile);
608 fclose(OutFile);
609 }
610
611 /* generate compiler */
GenHeaders()612 void GenHeaders()
613 {
614 FILE *OutFile;
615 char FileName[100];
616
617 sprintf(FileName, "%se.%s", module_prefix, h_ext);
618 OutFile = OpenFile(FileName, "w", 1);
619 GenParserErrors(OutFile);
620 fclose(OutFile);
621
622 sprintf(FileName, "%sc.%s", module_prefix, h_ext);
623 OutFile = OpenFile(FileName, "w", 1);
624 GenScannerTokens(OutFile);
625 fclose(OutFile);
626 }
627
GenParser(void)628 void GenParser(void)
629 {
630 GenFrame(module_prefix, "parser_c.frm", Parser_C_Format);
631 GenFrame(module_prefix, "parser_h.frm", Parser_H_Format);
632 }
633
GenScanner(void)634 void GenScanner(void)
635 {
636 GenFrame(module_prefix, "scan_c.frm", Scan_C_Format);
637 GenFrame(module_prefix, "scan_h.frm", Scan_H_Format);
638 }
639
640
641