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