148115Sbostic /*- 2*62213Sbostic * Copyright (c) 1980, 1993 3*62213Sbostic * The Regents of the University of California. All rights reserved. 448115Sbostic * 548115Sbostic * %sccs.include.redist.c% 622177Sdist */ 73075Smckusic 818349Smckusick #ifndef lint 9*62213Sbostic static char copyright[] = 10*62213Sbostic "@(#) Copyright (c) 1980, 1993\n\ 11*62213Sbostic The Regents of the University of California. All rights reserved.\n"; 1248115Sbostic #endif /* not lint */ 13759Speter 1422177Sdist #ifndef lint 15*62213Sbostic static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 06/06/93"; 1648115Sbostic #endif /* not lint */ 17759Speter 18759Speter #include "whoami.h" 19759Speter #include "0.h" 2018349Smckusick #include "tree_ty.h" /* must be included for yy.h */ 21759Speter #include "yy.h" 22759Speter #include <signal.h> 23759Speter #include "objfmt.h" 246407Speter #include "config.h" 25759Speter 26759Speter /* 27759Speter * This version of pi has been in use at Berkeley since May 1977 283075Smckusic * and is very stable. Please report any problems with the error 29759Speter * recovery to the second author at the address given in the file 30759Speter * READ_ME. The second author takes full responsibility for any bugs 31759Speter * in the syntactic error recovery. 32759Speter */ 33759Speter 34759Speter char piusage[] = "pi [ -blnpstuw ] [ -i file ... ] name.p"; 35759Speter 36759Speter char *usageis = piusage; 37759Speter 38759Speter #ifdef OBJ 3918349Smckusick 4018349Smckusick char pixusage[] = "pix [ -blnpstuw ] [ -i file ... ] name.p [ arg ... ]"; 4118349Smckusick char *obj = "obj"; 4218349Smckusick 43759Speter #endif OBJ 4418349Smckusick 45759Speter #ifdef PC 4618349Smckusick 4718349Smckusick char *pcname = "pc.pc0"; 4818349Smckusick char pcusage[] = "pc [ options ] [ -o file ] [ -i file ... ] name.p"; 4918349Smckusick FILE *pcstream = NULL; 5018349Smckusick 51759Speter #endif PC 52759Speter #ifdef PTREE 53759Speter char *pTreeName = "pi.pTree"; 54759Speter #endif PTREE 55759Speter 56759Speter int onintr(); 57759Speter 58759Speter extern char *lastname; 59759Speter 60759Speter FILE *ibuf; 61759Speter 62759Speter /* 63759Speter * these are made real variables 64759Speter * so they can be changed 65759Speter * if you are compiling on a smaller machine 66759Speter */ 67759Speter double MAXINT = 2147483647.; 68759Speter double MININT = -2147483648.; 69759Speter 70759Speter /* 71759Speter * Main program for pi. 72759Speter * Process options, then call yymain 73759Speter * to do all the real work. 74759Speter */ 75759Speter main(argc, argv) 76759Speter int argc; 77759Speter char *argv[]; 78759Speter { 79759Speter register char *cp; 80759Speter register c; 8118349Smckusick FILE *fopen(); 8218349Smckusick extern char *myctime(); 8318349Smckusick extern long lseek(); 84759Speter int i; 85759Speter 86759Speter if (argv[0][0] == 'a') 876407Speter err_file += err_pathlen , how_file += how_pathlen; 88759Speter # ifdef OBJ 89759Speter if (argv[0][0] == '-' && argv[0][1] == 'o') { 90759Speter obj = &argv[0][2]; 91759Speter usageis = pixusage; 926407Speter how_file[strlen(how_file)] = 'x'; 93759Speter ofil = 3; 94759Speter } else { 95759Speter ofil = creat(obj, 0755); 96759Speter if (ofil < 0) { 97759Speter perror(obj); 98759Speter pexit(NOSTART); 99759Speter } 100759Speter } 101759Speter # endif OBJ 102759Speter argv++, argc--; 103759Speter if (argc == 0) { 104759Speter i = fork(); 105759Speter if (i == -1) 106759Speter goto usage; 107759Speter if (i == 0) { 1086407Speter execl("/bin/cat", "cat", how_file, 0); 109759Speter goto usage; 110759Speter } 111759Speter while (wait(&i) != -1) 112759Speter continue; 113759Speter pexit(NOSTART); 114759Speter } 115759Speter # ifdef OBJ 11611884Smckusick opt('p') = opt('t') = opt('b') = 1; 11730838Smckusick #if defined(vax) || defined(tahoe) 11830838Smckusick /* pdx is currently supported on the vax and the tahoe */ 11911884Smckusick opt('g') = 1; 12030838Smckusick #endif 121759Speter while (argc > 0) { 122759Speter cp = argv[0]; 123759Speter if (*cp++ != '-') 124759Speter break; 125759Speter while (c = *cp++) switch (c) { 126759Speter #ifdef DEBUG 127759Speter case 'k': 128759Speter case 'r': 129759Speter case 'y': 130759Speter togopt(c); 131759Speter continue; 132759Speter case 'K': 133759Speter yycosts(); 134759Speter pexit(NOSTART); 135759Speter case 'A': 1363075Smckusic testtrace = TRUE; 137759Speter case 'F': 1383075Smckusic fulltrace = TRUE; 139759Speter case 'E': 1403075Smckusic errtrace = TRUE; 141759Speter opt('r')++; 142759Speter continue; 143759Speter case 'U': 14418349Smckusick yyunique = FALSE; 145759Speter continue; 146759Speter #endif 147759Speter case 'b': 148759Speter opt('b') = 2; 149759Speter continue; 150759Speter case 'i': 151759Speter pflist = argv + 1; 152759Speter pflstc = 0; 153759Speter while (argc > 1) { 154759Speter if (dotted(argv[1], 'p')) 155759Speter break; 156759Speter pflstc++, argc--, argv++; 157759Speter } 158759Speter if (pflstc == 0) 159759Speter goto usage; 160759Speter continue; 1615654Slinton case 'g': 162759Speter case 'l': 163759Speter case 'n': 164759Speter case 'p': 165759Speter case 's': 166759Speter case 't': 167759Speter case 'u': 168759Speter case 'w': 169759Speter togopt(c); 170759Speter continue; 171759Speter case 'z': 1723075Smckusic monflg = TRUE; 173759Speter continue; 17418348Smckusick case 'L': 17518348Smckusick togopt( 'L' ); 17618348Smckusick continue; 177759Speter default: 178759Speter usage: 179759Speter Perror( "Usage", usageis); 180759Speter pexit(NOSTART); 181759Speter } 182759Speter argc--, argv++; 183759Speter } 184759Speter # endif OBJ 185759Speter # ifdef PC 186759Speter opt( 'b' ) = 1; 187759Speter opt( 'g' ) = 0; 188759Speter opt( 't' ) = 0; 189759Speter opt( 'p' ) = 0; 190759Speter usageis = pcusage; 191759Speter while ( argc > 0 ) { 192759Speter cp = argv[0]; 193759Speter if ( *cp++ != '-' ) { 194759Speter break; 195759Speter } 196759Speter c = *cp++; 197759Speter switch( c ) { 198759Speter #ifdef DEBUG 199759Speter case 'k': 200759Speter case 'r': 201759Speter case 'y': 202759Speter togopt(c); 203759Speter break; 204759Speter case 'K': 205759Speter yycosts(); 206759Speter pexit(NOSTART); 207759Speter case 'A': 2083138Smckusic testtrace = TRUE; 209759Speter /* and fall through */ 210759Speter case 'F': 2113138Smckusic fulltrace = TRUE; 212759Speter /* and fall through */ 213759Speter case 'E': 2143138Smckusic errtrace = TRUE; 215759Speter opt('r')++; 216759Speter break; 217759Speter case 'U': 21818349Smckusick yyunique = FALSE; 219759Speter break; 220759Speter #endif 221759Speter case 'b': 222759Speter opt('b') = 2; 223759Speter break; 224759Speter case 'i': 225759Speter pflist = argv + 1; 226759Speter pflstc = 0; 227759Speter while (argc > 1) { 228759Speter if (dotted(argv[1], 'p')) 229759Speter break; 230759Speter pflstc++, argc--, argv++; 231759Speter } 232759Speter if (pflstc == 0) 233759Speter goto usage; 234759Speter break; 235759Speter /* 236759Speter * output file for the first pass 237759Speter */ 238759Speter case 'o': 239759Speter if ( argc < 2 ) { 240759Speter goto usage; 241759Speter } 242759Speter argv++; 243759Speter argc--; 244759Speter pcname = argv[0]; 245759Speter break; 24612967Smckusick case 'J': 24712967Smckusick togopt( 'J' ); 24812967Smckusick break; 249759Speter case 'C': 250759Speter /* 251759Speter * since -t is an ld switch, use -C 252759Speter * to turn on tests 253759Speter */ 254759Speter togopt( 't' ); 255759Speter break; 256759Speter case 'g': 257759Speter /* 258759Speter * sdb symbol table 259759Speter */ 260759Speter togopt( 'g' ); 261759Speter break; 262759Speter case 'l': 263759Speter case 's': 264759Speter case 'u': 265759Speter case 'w': 266759Speter togopt(c); 267759Speter break; 268759Speter case 'p': 269759Speter /* 270759Speter * -p on the command line means profile 271759Speter */ 2723138Smckusic profflag = TRUE; 273759Speter break; 274759Speter case 'z': 2753138Smckusic monflg = TRUE; 276759Speter break; 27718348Smckusick case 'L': 27818348Smckusick togopt( 'L' ); 27918348Smckusick break; 280759Speter default: 281759Speter usage: 282759Speter Perror( "Usage", usageis); 283759Speter pexit(NOSTART); 284759Speter } 285759Speter argc--; 286759Speter argv++; 287759Speter } 288759Speter # endif PC 289759Speter if (argc != 1) 290759Speter goto usage; 2916407Speter efil = open ( err_file, 0 ); 292759Speter if ( efil < 0 ) 2936407Speter perror(err_file), pexit(NOSTART); 294759Speter filename = argv[0]; 295759Speter if (!dotted(filename, 'p')) { 296759Speter Perror(filename, "Name must end in '.p'"); 297759Speter pexit(NOSTART); 298759Speter } 299759Speter close(0); 300759Speter if ( ( ibuf = fopen( filename , "r" ) ) == NULL ) 301759Speter perror(filename), pexit(NOSTART); 302759Speter ibp = ibuf; 303759Speter # ifdef PC 304759Speter if ( ( pcstream = fopen( pcname , "w" ) ) == NULL ) { 305759Speter perror( pcname ); 306759Speter pexit( NOSTART ); 307759Speter } 30818348Smckusick stabsource( filename, TRUE ); 309759Speter # endif PC 310759Speter # ifdef PTREE 311759Speter # define MAXpPAGES 16 312759Speter if ( ! pCreate( pTreeName , MAXpPAGES ) ) { 313759Speter perror( pTreeName ); 314759Speter pexit( NOSTART ); 315759Speter } 316759Speter # endif PTREE 317759Speter if ( signal( SIGINT , SIG_IGN ) != SIG_IGN ) 31818349Smckusick (void) signal( SIGINT , onintr ); 319759Speter if (opt('l')) { 320759Speter opt('n')++; 321759Speter yysetfile(filename); 322759Speter opt('n')--; 323759Speter } 324759Speter yymain(); 325759Speter /* No return */ 326759Speter } 327759Speter 328759Speter pchr(c) 329759Speter char c; 330759Speter { 331759Speter 332759Speter putc ( c , stdout ); 333759Speter } 334759Speter 33518449Smckusick #ifdef PC 33618449Smckusick char ugh[] = "Fatal error in pc\n"; 33718449Smckusick #endif 33818449Smckusick #ifdef OBJ 339759Speter char ugh[] = "Fatal error in pi\n"; 34018449Smckusick #endif 341759Speter /* 342759Speter * Exit from the Pascal system. 343759Speter * We throw in an ungraceful termination 344759Speter * message if c > 1 indicating a severe 345759Speter * error such as running out of memory 346759Speter * or an internal inconsistency. 347759Speter */ 348759Speter pexit(c) 349759Speter int c; 350759Speter { 351759Speter 352759Speter if (opt('l') && c != DIED && c != NOSTART) 353759Speter while (getline() != -1) 354759Speter continue; 355759Speter yyflush(); 356759Speter switch (c) { 357759Speter case DIED: 358759Speter write(2, ugh, sizeof ugh); 359759Speter case NOSTART: 360759Speter case ERRS: 361759Speter # ifdef OBJ 362759Speter if (ofil > 0) 363759Speter unlink(obj); 3645654Slinton /* 3655654Slinton * remove symbol table temp files 3665654Slinton */ 3675654Slinton removenlfile(); 3685654Slinton 369759Speter # endif OBJ 370759Speter # ifdef PC 371759Speter if ( pcstream != NULL ) { 372759Speter unlink( pcname ); 373759Speter } 374759Speter # endif PC 375759Speter break; 376759Speter case AOK: 377759Speter # ifdef OBJ 378759Speter pflush(); 3795654Slinton /* 3805654Slinton * copy symbol table temp files to obj file 3815654Slinton */ 3825654Slinton copynlfile(); 3835654Slinton 384759Speter # endif OBJ 385759Speter # ifdef PC 386759Speter puteof(); 387759Speter # endif PC 388759Speter break; 389759Speter } 390759Speter /* 391759Speter * this to gather statistics on programs being compiled 392759Speter * taken 20 june 79 ... peter 393759Speter * 394759Speter * if (fork() == 0) { 395759Speter * char *cp = "-0"; 396759Speter * cp[1] += c; 397759Speter * execl("/usr/lib/gather", "gather", cp, filename, 0); 398759Speter * exit(1); 399759Speter * } 400759Speter */ 401759Speter # ifdef PTREE 402759Speter pFinish(); 403759Speter # endif 404759Speter exit(c); 405759Speter } 406759Speter 407759Speter onintr() 408759Speter { 409759Speter 41018349Smckusick (void) signal( SIGINT , SIG_IGN ); 411759Speter pexit(NOSTART); 412759Speter } 413759Speter 414759Speter /* 415759Speter * Get an error message from the error message file 416759Speter */ 417759Speter geterr(seekpt, buf) 418759Speter int seekpt; 419759Speter char *buf; 420759Speter { 421759Speter 42218349Smckusick (void) lseek(efil, (long) seekpt, 0); 423759Speter if (read(efil, buf, 256) <= 0) 4246407Speter perror(err_file), pexit(DIED); 425759Speter } 426759Speter 427759Speter header() 428759Speter { 4296407Speter extern char *version; 430759Speter static char anyheaders; 431759Speter 432759Speter gettime( filename ); 433759Speter if (anyheaders && opt('n')) 434759Speter putc( '\f' , stdout ); 435759Speter anyheaders++; 436759Speter # ifdef OBJ 4376407Speter printf("Berkeley Pascal PI -- Version %s\n\n%s %s\n\n", 43818349Smckusick version, myctime((int *) (&tvec)), filename); 439759Speter # endif OBJ 440759Speter # ifdef PC 4416407Speter printf("Berkeley Pascal PC -- Version %s\n\n%s %s\n\n", 44218349Smckusick version, myctime((int *) (&tvec)), filename); 443759Speter # endif PC 444759Speter } 445