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