1 #include  <stdio.h>
2 #include  <stdlib.h>
3 #include  <fcntl.h>
4 
5 #if __MSDOS__ || MSDOS || WIN32 || __WIN32__
6 #  include  <io.h>
7 #else
8 #  include <unistd.h>
9 #  define  O_BINARY     0
10 #endif
11 
12 #if NEXTSTEP
13 #   include <sys/file.h>
14 #endif
15 
16 #include  <string.h>
17 #include  "crt.h"
18 #include  "crx.h"
19 #include  "cra.h"
20 #include  "crf.h"
21 #include  "crp.h"
22 #include  "crs.h"
23 
24 struct ErrDesc {
25   int nr, line, col;
26   struct ErrDesc *next;
27 };
28 
29 static FILE *lst;
30 static struct ErrDesc *FirstErr = NULL, *LastErr;
31 int Errors = 0;
32 extern Error_Func Custom_Error;
33 
34 static char *ErrorMsg[] = {
35 #include "cre.h"
36 "User error number clash",
37 ""
38 };
39 
40 static char Version[]     = "1.17 (C/C++ Version)";
41 static char ReleaseDate[] = "Sep 17 2002";
42 
43 /* --------------------------- Help ------------------------------------------ */
44 
Help(void)45 static void Help(void)
46 { fprintf(stdout,
47     "Coco/R - Compiler-Compiler V%s "
48     "(Frankie Arzu, %s)\n\n"
49     "Usage: COCOR  [(/|-)Options] <Grammar.atg>   for Dos/Windows\n"
50     "Usage: COCOR  [-Options] <Grammar.atg>       for Unix\n"
51     "Example: COCOR -C -S Test.atg\n\n"
52     "Options:\n"
53     "A  - Trace automaton               C  - Generate compiler module\n"
54     "D  - Include source debugging information (#line)\n"
55     "F  - Give Start and Follower sets  G  - Print top-down graph\n"
56     "L  - Force listing                 O  - Terminal conditions use OR only\n"
57     "P  - Generate parser only          S  - Print symbol table\n"
58     "T  - Grammar tests only            Q  - Quiet (Edit) mode\n"
59     "X  - Generate C++ with classes     Z  - Force extensions to .hpp and .cpp\n\n"
60     "Environment variables:\n"
61     "CRFRAMES:  Search directory for frames file. If not specified,\n"
62     "           frames must be in the working directory.\n"
63     "CRHEXT:    Extension for the '.h' generated files. If not specified,\n"
64     "           '.h' for C, '.hpp' for C++ (Dos and Unix). \n"
65     "CRCEXT:    Extension for the '.c' generated files. If not specified,\n"
66     "           '.c' for C, '.cpp' for C++ (Dos and Unix). \n"
67     "Frame and extension options may also be set using -Dvarname=value\n",
68     Version, ReleaseDate);
69 }
70 
StoreError(int nr,int line,int col,long pos)71 void StoreError(int nr, int line, int col, long pos)
72 /* Store an error message for later printing */
73 { struct ErrDesc *NextErr;
74 
75   NextErr = (struct ErrDesc *) malloc(sizeof(struct ErrDesc));
76   NextErr->nr = nr; NextErr->line = line; NextErr->col = col;
77   NextErr->next = NULL;
78   if (FirstErr == NULL) FirstErr = NextErr;
79   else LastErr->next = NextErr;
80   LastErr = NextErr;
81   Errors++;
82 }
83 
GetLine(long pos,char * line)84 static long GetLine(long pos, char *line)
85 /* Read a source line.  Return empty line if eof */
86 { char ch;
87   int i;
88   int col = 1;
89 
90   ch = S_CurrentCh(pos);
91   while (ch && ch != LF_CHAR && ch != EOF_CHAR) {
92     if (ch == TAB_CHAR) {
93       i = TAB_SIZE - (col % TAB_SIZE) + 1;
94       while (i--) { *line++ = ' '; col++; }
95     }
96     else if (ch != CR_CHAR) { *line++ = ch; col++; }
97     pos++;
98     ch = S_CurrentCh(pos);
99   }
100   *line = 0;
101   if (ch != EOF_CHAR) return pos + 1;
102   else return -1;
103 }
104 
PrintErrMsg(int nr)105 static void PrintErrMsg(int nr)
106 {
107   if (nr <= MAXERROR) fprintf(lst, "%s", ErrorMsg[nr]);
108   else
109     switch (nr) {
110     case 101:
111       fprintf(lst, "character set may not be empty");
112       break;
113     case 102:
114       fprintf(lst, "string literal may not extend over line end");
115       break;
116     case 103:
117       fprintf(lst, "a literal must not have attributes");
118       break;
119     case 104:
120       fprintf(lst, "this symbol kind not allowed in production");
121       break;
122     case 105:
123       fprintf(lst, "attribute mismatch between declaration and use");
124       break;
125     case 106:
126       fprintf(lst, "undefined string in production");
127       break;
128     case 107:
129       fprintf(lst, "name declared twice");
130       break;
131     case 108:
132       fprintf(lst, "this type not allowed on left side of production");
133       break;
134     case 109:
135       fprintf(lst, "earlier semantic action was not terminated");
136       break;
137     case 111:
138       fprintf(lst, "no production found for grammar name");
139       break;
140     case 112:
141       fprintf(lst, "grammar symbol must not have attributes");
142       break;
143     case 113:
144       fprintf(lst, "a literal must not be declared with a structure");
145       break;
146     case 114:
147       fprintf(lst, "semantic action not allowed here");
148       break;
149     case 115:
150       fprintf(lst, "undefined name");
151       break;
152     case 116:
153       fprintf(lst, "attributes not allowed in token declaration");
154       break;
155     case 117:
156       fprintf(lst, "name does not match name in heading");
157       break;
158     case 118:
159       fprintf(lst, "unacceptable constant value");
160       break;
161     case 119:
162       fprintf(lst, "may not ignore CHR(0)");
163       break;
164     case 120:
165       fprintf(lst, "token might be empty");
166       break;
167     case 121:
168       fprintf(lst, "token must not start with an iteration");
169       break;
170     case 122:
171       fprintf(lst, "comment delimiters may not be structured");
172       break;
173     case 123:
174       fprintf(lst, "only terminals may be weak");
175       break;
176     case 124:
177       fprintf(lst, "literal tokens may not contain white space");
178       break;
179     case 125:
180       fprintf(lst, "comment delimiter must be 1 or 2 characters long");
181       break;
182     case 126:
183       fprintf(lst, "character set contains more than one character");
184       break;
185     case 127:
186       fprintf(lst, "\ncould not make deterministic automaton, check previous token errors");
187       break;
188     case 129:
189       fprintf(lst, "literal tokens may not be empty");
190       break;
191     case 130:
192       fprintf(lst, "IGNORE CASE must appear earlier");
193       break;
194     }
195   fprintf(lst, " (E%d)",nr);
196 }
197 
PrintErr(int nr,int col)198 static void PrintErr(int nr, int col)
199 { fprintf(lst, "*****");
200   while (col--) fprintf(lst, " ");
201   fprintf(lst, " ^ ");
202   PrintErrMsg(nr);
203   fprintf(lst, "\n");
204 }
205 
PrintListing(void)206 static void PrintListing(void)
207 /* Print a source listing with error messages */
208 { struct ErrDesc *nextErr;
209   int lnr, errC;
210   long srcPos;
211   char line[255];
212 
213   fprintf(lst, "Listing:\n\n");
214   srcPos = 0; nextErr = FirstErr;
215   srcPos = GetLine(srcPos, line); lnr = 1; errC = 0;
216   while (srcPos != -1) {
217     fprintf(lst, "%5d  %s\n", lnr, line);
218     while (nextErr != NULL && nextErr->line == lnr) {
219       PrintErr(nextErr->nr, nextErr->col); errC++;
220       nextErr = nextErr->next;
221     }
222     srcPos = GetLine(srcPos, line); lnr++;
223   }
224   if (nextErr != NULL) {
225     fprintf(lst, "%5d\n", lnr);
226     while (nextErr != NULL) {
227       PrintErr(nextErr->nr, nextErr->col); errC++;
228       nextErr = nextErr->next;
229     }
230   }
231   fprintf(lst, "\n\n%5d syntax errors\n", errC);
232 }
233 
SummarizeErrors(void)234 void SummarizeErrors(void)
235 /* Summarize error messages */
236 { struct ErrDesc *nextErr;
237   nextErr = FirstErr;
238   while (nextErr != NULL) {
239     if (Q_option)
240       fprintf(lst, "%s (%d, %d) ",
241               source_name, nextErr->line, nextErr->col);
242     else
243       fprintf(lst, "\"%s\", Line %d, Col %d: ",
244               source_name, nextErr->line, nextErr->col);
245     PrintErrMsg(nextErr->nr);
246     fprintf(lst, "\n");
247     nextErr = nextErr->next;
248   }
249 }
250 
param_options(int argc,char * argv[])251 static void param_options(int argc,char *argv[])
252 { int i;
253   for (i = 1; i < argc; i++)
254 #if __MSDOS__ || MSDOS || WIN32 || __WIN32__
255     if (*argv[i] == '-' || *argv[i] == '/') SetOptions(argv[i]);
256 #else
257     if (*argv[i] == '-') SetOptions(argv[i]);
258 #endif
259     else strcpy(source_name, argv[i]);
260 }
261 
FileGetName(char * name,char * filename)262 static void FileGetName(char *name, char *filename)
263 {  int i;
264    strcpy(name, filename);
265    i = strlen(name)-1;
266    while (i>0 && name[i] != '.') i--;
267    name[i]='\0';
268 }
269 
main(int argc,char * argv[])270 int main(int argc, char *argv[])
271 {
272   char name[100];
273   lst = stderr;
274   if (argc == 1) {
275     Help();
276     exit(EXIT_FAILURE);
277   }
278 
279   InitFrameVars();
280   source_name[0] = '\0';
281   param_options(argc, argv);
282 
283   /* check on correct parameter usage */
284   if (source_name[0] == 0) {
285     fprintf(stderr, "No input file specified");
286     exit(EXIT_FAILURE);
287   }
288 
289   /* open the Source file (Scanner.S_src)  */
290   if ((S_src = open(source_name, O_RDONLY|O_BINARY)) == -1) {
291     fprintf(stderr, "Unable to open input file %s\n", source_name);
292     exit(EXIT_FAILURE);
293   }
294 
295   /* open the listing file */
296   if (L_option) {
297     FileGetName(name, source_name);
298     strcat(name, ".lst");
299     lstfile = OpenFile(name, "w", 1);
300   } else if (!Q_option) lstfile = stderr; else lstfile = stdout;
301 
302   /* install error reporting procedure */
303   Custom_Error = (Error_Func) StoreError;
304 
305   InitTab();
306   InitScannerTab();
307   Parse();
308   close(S_src);
309 
310   lst = lstfile;
311   if (Errors && !L_option) SummarizeErrors();
312   else if (Errors || L_option) PrintListing();
313 
314   if (Errors) {  /* Check for Syntax Errors */
315     fclose(lstfile);
316     exit(EXIT_FAILURE);
317   }
318 
319   MakeScanner();
320   MakeParser();
321 
322   if (Errors) {  /* Check for LL(1) Errors, Undeclared Symbols, etc */
323     fclose(lstfile);
324     exit(EXIT_FAILURE);
325   }
326 
327   SetupFrameVars();
328   if (!T_option) {
329     if (!P_option) GenScanner();
330     GenParser();
331     GenHeaders();
332     if (C_option) GenCompiler();
333   }
334 
335   if (L_option) {
336     if (S_option) {
337       ShowClassTab();
338       ShowTermTab();
339       ShowCommentTab();
340       ShowSymSetTab();
341       ShowNTermTab();
342     }
343     if (A_option) ShowDFA();
344     fclose(lstfile);
345   }
346   DoneTab();
347   DoneScannerTab();
348   return (EXIT_SUCCESS);
349 }
350 
351