1 /**************************************************************************/
2 /* */
3 /* OCaml */
4 /* */
5 /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
6 /* */
7 /* Copyright 1996 Institut National de Recherche en Informatique et */
8 /* en Automatique. */
9 /* */
10 /* All rights reserved. This file is distributed under the terms of */
11 /* the GNU Lesser General Public License version 2.1, with the */
12 /* special exception on linking described in the file LICENSE. */
13 /* */
14 /**************************************************************************/
15
16 /* Based on public-domain code from Berkeley Yacc */
17
18 #include <signal.h>
19 #include <string.h>
20 #include "defs.h"
21 #ifdef HAS_UNISTD
22 #include <unistd.h>
23 #endif
24
25 #include "version.h"
26
27 char dflag;
28 char lflag;
29 char rflag;
30 char tflag;
31 char vflag;
32 char qflag;
33 char eflag;
34 char sflag;
35 char big_endian;
36
37 char *file_prefix = 0;
38 char *myname = "yacc";
39 char temp_form[] = "yacc.XXXXXXX";
40
41 #ifdef NO_UNIX
42 char dirsep = '\\';
43 #else
44 char dirsep = '/';
45 #endif
46
47 int lineno;
48 char *virtual_input_file_name = NULL;
49 int outline;
50
51 char *action_file_name;
52 char *entry_file_name;
53 char *code_file_name;
54 char *interface_file_name;
55 char *defines_file_name;
56 char *input_file_name = "";
57 char *output_file_name;
58 char *text_file_name;
59 char *union_file_name;
60 char *verbose_file_name;
61
62 #ifdef HAS_MKSTEMP
63 int action_fd = -1, entry_fd = -1, text_fd = -1, union_fd = -1;
64 #endif
65
66 FILE *action_file; /* a temp file, used to save actions associated */
67 /* with rules until the parser is written */
68 FILE *entry_file;
69 FILE *code_file; /* y.code.c (used when the -r option is specified) */
70 FILE *defines_file; /* y.tab.h */
71 FILE *input_file; /* the input file */
72 FILE *output_file; /* y.tab.c */
73 FILE *text_file; /* a temp file, used to save text until all */
74 /* symbols have been defined */
75 FILE *union_file; /* a temp file, used to save the union */
76 /* definition until all symbol have been */
77 /* defined */
78 FILE *verbose_file; /* y.output */
79 FILE *interface_file;
80
81 int nitems;
82 int nrules;
83 int ntotalrules;
84 int nsyms;
85 int ntokens;
86 int nvars;
87
88 int start_symbol;
89 char **symbol_name;
90 short *symbol_value;
91 short *symbol_prec;
92 char *symbol_assoc;
93 char **symbol_tag;
94 char *symbol_true_token;
95
96 short *ritem;
97 short *rlhs;
98 short *rrhs;
99 short *rprec;
100 char *rassoc;
101 short **derives;
102 char *nullable;
103
104 #if !defined(HAS_MKSTEMP)
105 extern char *mktemp(char *);
106 #endif
107 #ifndef NO_UNIX
108 extern char *getenv(const char *);
109 #endif
110
111
done(int k)112 void done(int k)
113 {
114 #ifdef HAS_MKSTEMP
115 if (action_fd != -1)
116 unlink(action_file_name);
117 if (entry_fd != -1)
118 unlink(entry_file_name);
119 if (text_fd != -1)
120 unlink(text_file_name);
121 if (union_fd != -1)
122 unlink(union_file_name);
123 #else
124 if (action_file) { fclose(action_file); unlink(action_file_name); }
125 if (entry_file) { fclose(entry_file); unlink(entry_file_name); }
126 if (text_file) { fclose(text_file); unlink(text_file_name); }
127 if (union_file) { fclose(union_file); unlink(union_file_name); }
128 #endif
129 if (output_file && k > 0) {
130 fclose(output_file); unlink(output_file_name);
131 }
132 if (interface_file && k > 0) {
133 fclose(interface_file); unlink(interface_file_name);
134 }
135 exit(k);
136 }
137
138
onintr(int dummy)139 void onintr(int dummy)
140 {
141 done(1);
142 }
143
144
set_signals(void)145 void set_signals(void)
146 {
147 #ifdef SIGINT
148 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
149 signal(SIGINT, onintr);
150 #endif
151 #ifdef SIGTERM
152 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
153 signal(SIGTERM, onintr);
154 #endif
155 #ifdef SIGHUP
156 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
157 signal(SIGHUP, onintr);
158 #endif
159 }
160
161
usage(void)162 void usage(void)
163 {
164 fprintf(stderr, "usage: %s [-v] [--strict] [-q] [-b file_prefix] filename\n",
165 myname);
166 exit(1);
167 }
168
getargs(int argc,char ** argv)169 void getargs(int argc, char **argv)
170 {
171 register int i;
172 register char *s;
173
174 if (argc > 0) myname = argv[0];
175 for (i = 1; i < argc; ++i)
176 {
177 s = argv[i];
178 if (*s != '-') break;
179 switch (*++s)
180 {
181 case '\0':
182 input_file = stdin;
183 file_prefix = "stdin";
184 if (i + 1 < argc) usage();
185 return;
186
187 case '-':
188 if (!strcmp (argv[i], "--strict")){
189 eflag = 1;
190 goto end_of_option;
191 }
192 ++i;
193 goto no_more_options;
194
195 case 'v':
196 if (!strcmp (argv[i], "-version")){
197 printf ("The OCaml parser generator, version "
198 OCAML_VERSION "\n");
199 exit (0);
200 }else if (!strcmp (argv[i], "-vnum")){
201 printf (OCAML_VERSION "\n");
202 exit (0);
203 }else{
204 vflag = 1;
205 }
206 break;
207
208 case 'q':
209 qflag = 1;
210 break;
211
212 case 'b':
213 if (*++s)
214 file_prefix = s;
215 else if (++i < argc)
216 file_prefix = argv[i];
217 else
218 usage();
219 continue;
220
221 default:
222 usage();
223 }
224
225 for (;;)
226 {
227 switch (*++s)
228 {
229 case '\0':
230 goto end_of_option;
231
232 case 'v':
233 vflag = 1;
234 break;
235
236 case 'q':
237 qflag = 1;
238 break;
239
240 default:
241 usage();
242 }
243 }
244 end_of_option:;
245 }
246
247 no_more_options:;
248 if (i + 1 != argc) usage();
249 input_file_name = argv[i];
250 if (file_prefix == 0) {
251 int len;
252 len = strlen(argv[i]);
253 file_prefix = malloc(len + 1);
254 if (file_prefix == 0) no_space();
255 strcpy(file_prefix, argv[i]);
256 while (len > 0) {
257 len--;
258 if (file_prefix[len] == '.') {
259 file_prefix[len] = 0;
260 break;
261 }
262 }
263 }
264 }
265
266
267 char *
allocate(unsigned int n)268 allocate(unsigned int n)
269 {
270 register char *p;
271
272 p = NULL;
273 if (n)
274 {
275 p = CALLOC(1, n);
276 if (!p) no_space();
277 }
278 return (p);
279 }
280
281
create_file_names(void)282 void create_file_names(void)
283 {
284 int i, len;
285 char *tmpdir;
286
287 #ifdef NO_UNIX
288 tmpdir = getenv("TEMP");
289 if (tmpdir == 0) tmpdir = ".";
290 #else
291 tmpdir = getenv("TMPDIR");
292 if (tmpdir == 0) tmpdir = "/tmp";
293 #endif
294 len = strlen(tmpdir);
295 i = len + sizeof(temp_form);
296 if (len && tmpdir[len-1] != dirsep)
297 ++i;
298
299 action_file_name = MALLOC(i);
300 if (action_file_name == 0) no_space();
301 entry_file_name = MALLOC(i);
302 if (entry_file_name == 0) no_space();
303 text_file_name = MALLOC(i);
304 if (text_file_name == 0) no_space();
305 union_file_name = MALLOC(i);
306 if (union_file_name == 0) no_space();
307
308 strcpy(action_file_name, tmpdir);
309 strcpy(entry_file_name, tmpdir);
310 strcpy(text_file_name, tmpdir);
311 strcpy(union_file_name, tmpdir);
312
313 if (len && tmpdir[len - 1] != dirsep)
314 {
315 action_file_name[len] = dirsep;
316 entry_file_name[len] = dirsep;
317 text_file_name[len] = dirsep;
318 union_file_name[len] = dirsep;
319 ++len;
320 }
321
322 strcpy(action_file_name + len, temp_form);
323 strcpy(entry_file_name + len, temp_form);
324 strcpy(text_file_name + len, temp_form);
325 strcpy(union_file_name + len, temp_form);
326
327 action_file_name[len + 5] = 'a';
328 entry_file_name[len + 5] = 'e';
329 text_file_name[len + 5] = 't';
330 union_file_name[len + 5] = 'u';
331
332 #ifdef HAS_MKSTEMP
333 action_fd = mkstemp(action_file_name);
334 if (action_fd == -1)
335 open_error(action_file_name);
336 entry_fd = mkstemp(entry_file_name);
337 if (entry_fd == -1)
338 open_error(entry_file_name);
339 text_fd = mkstemp(text_file_name);
340 if (text_fd == -1)
341 open_error(text_file_name);
342 union_fd = mkstemp(union_file_name);
343 if (union_fd == -1)
344 open_error(union_file_name);
345 #else
346 mktemp(action_file_name);
347 mktemp(entry_file_name);
348 mktemp(text_file_name);
349 mktemp(union_file_name);
350 #endif
351
352 len = strlen(file_prefix);
353
354 output_file_name = MALLOC(len + 7);
355 if (output_file_name == 0)
356 no_space();
357 strcpy(output_file_name, file_prefix);
358 strcpy(output_file_name + len, OUTPUT_SUFFIX);
359
360 code_file_name = output_file_name;
361
362 if (vflag)
363 {
364 verbose_file_name = MALLOC(len + 8);
365 if (verbose_file_name == 0)
366 no_space();
367 strcpy(verbose_file_name, file_prefix);
368 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
369 }
370
371 interface_file_name = MALLOC(len + 8);
372 if (interface_file_name == 0)
373 no_space();
374 strcpy(interface_file_name, file_prefix);
375 strcpy(interface_file_name + len, INTERFACE_SUFFIX);
376
377 }
378
379
open_files(void)380 void open_files(void)
381 {
382 create_file_names();
383
384 if (input_file == 0)
385 {
386 input_file = fopen(input_file_name, "r");
387 if (input_file == 0)
388 open_error(input_file_name);
389 }
390
391 #ifdef HAS_MKSTEMP
392 action_file = fdopen(action_fd, "w");
393 #else
394 action_file = fopen(action_file_name, "w");
395 #endif
396 if (action_file == 0)
397 open_error(action_file_name);
398
399 #ifdef HAS_MKSTEMP
400 entry_file = fdopen(entry_fd, "w");
401 #else
402 entry_file = fopen(entry_file_name, "w");
403 #endif
404 if (entry_file == 0)
405 open_error(entry_file_name);
406
407 #ifdef HAS_MKSTEMP
408 text_file = fdopen(text_fd, "w");
409 #else
410 text_file = fopen(text_file_name, "w");
411 #endif
412 if (text_file == 0)
413 open_error(text_file_name);
414
415 if (vflag)
416 {
417 verbose_file = fopen(verbose_file_name, "w");
418 if (verbose_file == 0)
419 open_error(verbose_file_name);
420 }
421
422 if (dflag)
423 {
424 defines_file = fopen(defines_file_name, "w");
425 if (defines_file == 0)
426 open_error(defines_file_name);
427 #ifdef HAS_MKSTEMP
428 union_file = fdopen(union_fd, "w");
429 #else
430 union_file = fopen(union_file_name, "w");
431 #endif
432 if (union_file == 0)
433 open_error(union_file_name);
434 }
435
436 output_file = fopen(output_file_name, "w");
437 if (output_file == 0)
438 open_error(output_file_name);
439
440 if (rflag)
441 {
442 code_file = fopen(code_file_name, "w");
443 if (code_file == 0)
444 open_error(code_file_name);
445 }
446 else
447 code_file = output_file;
448
449
450 interface_file = fopen(interface_file_name, "w");
451 if (interface_file == 0)
452 open_error(interface_file_name);
453 }
454
main(int argc,char ** argv)455 int main(int argc, char **argv)
456 {
457 set_signals();
458 getargs(argc, argv);
459 open_files();
460 reader();
461 lr0();
462 lalr();
463 make_parser();
464 verbose();
465 if (eflag && SRtotal + RRtotal > 0) forbidden_conflicts();
466 output();
467 done(0);
468 /*NOTREACHED*/
469 return 0;
470 }
471