1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)main.c 5.1 (Berkeley) 6/5/85";
15: #endif not lint
16:
17: #include "whoami.h"
18: #include "0.h"
19: #include "tree_ty.h" /* must be included for yy.h */
20: #include "yy.h"
21: #include <signal.h>
22: #include "objfmt.h"
23: #include "config.h"
24:
25: /*
26: * This version of pi has been in use at Berkeley since May 1977
27: * and is very stable. Please report any problems with the error
28: * recovery to the second author at the address given in the file
29: * READ_ME. The second author takes full responsibility for any bugs
30: * in the syntactic error recovery.
31: */
32:
33: char piusage[] = "pi [ -blnpstuw ] [ -i file ... ] name.p";
34:
35: char *usageis = piusage;
36:
37: #ifdef OBJ
38:
39: char pixusage[] = "pix [ -blnpstuw ] [ -i file ... ] name.p [ arg ... ]";
40: char *obj = "obj";
41:
42: #endif OBJ
43:
44: #ifdef PC
45:
46: char *pcname = "pc.pc0";
47: char pcusage[] = "pc [ options ] [ -o file ] [ -i file ... ] name.p";
48: FILE *pcstream = NULL;
49:
50: #endif PC
51: #ifdef PTREE
52: char *pTreeName = "pi.pTree";
53: #endif PTREE
54:
55: int onintr();
56:
57: extern char *lastname;
58:
59: FILE *ibuf;
60:
61: /*
62: * these are made real variables
63: * so they can be changed
64: * if you are compiling on a smaller machine
65: */
66: double MAXINT = 2147483647.;
67: double MININT = -2147483648.;
68:
69: /*
70: * Main program for pi.
71: * Process options, then call yymain
72: * to do all the real work.
73: */
74: main(argc, argv)
75: int argc;
76: char *argv[];
77: {
78: register char *cp;
79: register c;
80: FILE *fopen();
81: extern char *myctime();
82: extern long lseek();
83: int i;
84:
85: if (argv[0][0] == 'a')
86: err_file += err_pathlen , how_file += how_pathlen;
87: # ifdef OBJ
88: if (argv[0][0] == '-' && argv[0][1] == 'o') {
89: obj = &argv[0][2];
90: usageis = pixusage;
91: how_file[strlen(how_file)] = 'x';
92: ofil = 3;
93: } else {
94: ofil = creat(obj, 0755);
95: if (ofil < 0) {
96: perror(obj);
97: pexit(NOSTART);
98: }
99: }
100: # endif OBJ
101: argv++, argc--;
102: if (argc == 0) {
103: i = fork();
104: if (i == -1)
105: goto usage;
106: if (i == 0) {
107: execl("/bin/cat", "cat", how_file, 0);
108: goto usage;
109: }
110: while (wait(&i) != -1)
111: continue;
112: pexit(NOSTART);
113: }
114: # ifdef OBJ
115: opt('p') = opt('t') = opt('b') = 1;
116: #ifdef vax
117: /* pdx is currently supported only on the vax */
118: opt('g') = 1;
119: #endif vax
120: while (argc > 0) {
121: cp = argv[0];
122: if (*cp++ != '-')
123: break;
124: while (c = *cp++) switch (c) {
125: #ifdef DEBUG
126: case 'k':
127: case 'r':
128: case 'y':
129: togopt(c);
130: continue;
131: case 'K':
132: yycosts();
133: pexit(NOSTART);
134: case 'A':
135: testtrace = TRUE;
136: case 'F':
137: fulltrace = TRUE;
138: case 'E':
139: errtrace = TRUE;
140: opt('r')++;
141: continue;
142: case 'U':
143: yyunique = FALSE;
144: continue;
145: #endif
146: case 'b':
147: opt('b') = 2;
148: continue;
149: case 'i':
150: pflist = argv + 1;
151: pflstc = 0;
152: while (argc > 1) {
153: if (dotted(argv[1], 'p'))
154: break;
155: pflstc++, argc--, argv++;
156: }
157: if (pflstc == 0)
158: goto usage;
159: continue;
160: case 'g':
161: case 'l':
162: case 'n':
163: case 'p':
164: case 's':
165: case 't':
166: case 'u':
167: case 'w':
168: togopt(c);
169: continue;
170: case 'z':
171: monflg = TRUE;
172: continue;
173: case 'L':
174: togopt( 'L' );
175: continue;
176: default:
177: usage:
178: Perror( "Usage", usageis);
179: pexit(NOSTART);
180: }
181: argc--, argv++;
182: }
183: # endif OBJ
184: # ifdef PC
185: opt( 'b' ) = 1;
186: opt( 'g' ) = 0;
187: opt( 't' ) = 0;
188: opt( 'p' ) = 0;
189: usageis = pcusage;
190: while ( argc > 0 ) {
191: cp = argv[0];
192: if ( *cp++ != '-' ) {
193: break;
194: }
195: c = *cp++;
196: switch( c ) {
197: #ifdef DEBUG
198: case 'k':
199: case 'r':
200: case 'y':
201: togopt(c);
202: break;
203: case 'K':
204: yycosts();
205: pexit(NOSTART);
206: case 'A':
207: testtrace = TRUE;
208: /* and fall through */
209: case 'F':
210: fulltrace = TRUE;
211: /* and fall through */
212: case 'E':
213: errtrace = TRUE;
214: opt('r')++;
215: break;
216: case 'U':
217: yyunique = FALSE;
218: break;
219: #endif
220: case 'b':
221: opt('b') = 2;
222: break;
223: case 'i':
224: pflist = argv + 1;
225: pflstc = 0;
226: while (argc > 1) {
227: if (dotted(argv[1], 'p'))
228: break;
229: pflstc++, argc--, argv++;
230: }
231: if (pflstc == 0)
232: goto usage;
233: break;
234: /*
235: * output file for the first pass
236: */
237: case 'o':
238: if ( argc < 2 ) {
239: goto usage;
240: }
241: argv++;
242: argc--;
243: pcname = argv[0];
244: break;
245: case 'J':
246: togopt( 'J' );
247: break;
248: case 'C':
249: /*
250: * since -t is an ld switch, use -C
251: * to turn on tests
252: */
253: togopt( 't' );
254: break;
255: case 'g':
256: /*
257: * sdb symbol table
258: */
259: togopt( 'g' );
260: break;
261: case 'l':
262: case 's':
263: case 'u':
264: case 'w':
265: togopt(c);
266: break;
267: case 'p':
268: /*
269: * -p on the command line means profile
270: */
271: profflag = TRUE;
272: break;
273: case 'z':
274: monflg = TRUE;
275: break;
276: case 'L':
277: togopt( 'L' );
278: break;
279: default:
280: usage:
281: Perror( "Usage", usageis);
282: pexit(NOSTART);
283: }
284: argc--;
285: argv++;
286: }
287: # endif PC
288: if (argc != 1)
289: goto usage;
290: efil = open ( err_file, 0 );
291: if ( efil < 0 )
292: perror(err_file), pexit(NOSTART);
293: filename = argv[0];
294: if (!dotted(filename, 'p')) {
295: Perror(filename, "Name must end in '.p'");
296: pexit(NOSTART);
297: }
298: close(0);
299: if ( ( ibuf = fopen( filename , "r" ) ) == NULL )
300: perror(filename), pexit(NOSTART);
301: ibp = ibuf;
302: # ifdef PC
303: if ( ( pcstream = fopen( pcname , "w" ) ) == NULL ) {
304: perror( pcname );
305: pexit( NOSTART );
306: }
307: stabsource( filename, TRUE );
308: # endif PC
309: # ifdef PTREE
310: # define MAXpPAGES 16
311: if ( ! pCreate( pTreeName , MAXpPAGES ) ) {
312: perror( pTreeName );
313: pexit( NOSTART );
314: }
315: # endif PTREE
316: if ( signal( SIGINT , SIG_IGN ) != SIG_IGN )
317: (void) signal( SIGINT , onintr );
318: if (opt('l')) {
319: opt('n')++;
320: yysetfile(filename);
321: opt('n')--;
322: }
323: yymain();
324: /* No return */
325: }
326:
327: pchr(c)
328: char c;
329: {
330:
331: putc ( c , stdout );
332: }
333:
334: #ifdef PC
335: char ugh[] = "Fatal error in pc\n";
336: #endif
337: #ifdef OBJ
338: char ugh[] = "Fatal error in pi\n";
339: #endif
340: /*
341: * Exit from the Pascal system.
342: * We throw in an ungraceful termination
343: * message if c > 1 indicating a severe
344: * error such as running out of memory
345: * or an internal inconsistency.
346: */
347: pexit(c)
348: int c;
349: {
350:
351: if (opt('l') && c != DIED && c != NOSTART)
352: while (getline() != -1)
353: continue;
354: yyflush();
355: switch (c) {
356: case DIED:
357: write(2, ugh, sizeof ugh);
358: case NOSTART:
359: case ERRS:
360: # ifdef OBJ
361: if (ofil > 0)
362: unlink(obj);
363: /*
364: * remove symbol table temp files
365: */
366: removenlfile();
367:
368: # endif OBJ
369: # ifdef PC
370: if ( pcstream != NULL ) {
371: unlink( pcname );
372: }
373: # endif PC
374: break;
375: case AOK:
376: # ifdef OBJ
377: pflush();
378: /*
379: * copy symbol table temp files to obj file
380: */
381: copynlfile();
382:
383: # endif OBJ
384: # ifdef PC
385: puteof();
386: # endif PC
387: break;
388: }
389: /*
390: * this to gather statistics on programs being compiled
391: * taken 20 june 79 ... peter
392: *
393: * if (fork() == 0) {
394: * char *cp = "-0";
395: * cp[1] += c;
396: * execl("/usr/lib/gather", "gather", cp, filename, 0);
397: * exit(1);
398: * }
399: */
400: # ifdef PTREE
401: pFinish();
402: # endif
403: exit(c);
404: }
405:
406: onintr()
407: {
408:
409: (void) signal( SIGINT , SIG_IGN );
410: pexit(NOSTART);
411: }
412:
413: /*
414: * Get an error message from the error message file
415: */
416: geterr(seekpt, buf)
417: int seekpt;
418: char *buf;
419: {
420:
421: (void) lseek(efil, (long) seekpt, 0);
422: if (read(efil, buf, 256) <= 0)
423: perror(err_file), pexit(DIED);
424: }
425:
426: ()
427: {
428: extern char *version;
429: static char anyheaders;
430:
431: gettime( filename );
432: if (anyheaders && opt('n'))
433: putc( '\f' , stdout );
434: anyheaders++;
435: # ifdef OBJ
436: printf("Berkeley Pascal PI -- Version %s\n\n%s %s\n\n",
437: version, myctime((int *) (&tvec)), filename);
438: # endif OBJ
439: # ifdef PC
440: printf("Berkeley Pascal PC -- Version %s\n\n%s %s\n\n",
441: version, myctime((int *) (&tvec)), filename);
442: # endif PC
443: }