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