1 /* Copyright (c) 1979 Regents of the University of California */ 2 static char copyright[] = 3 "@(#)Copyright (c) 1979 Regents of the University of California"; 4 5 static char sccsid[] = "@(#)main.c 1.2 02/20/81"; 6 7 #include "whoami.h" 8 #include "0.h" 9 #include "yy.h" 10 #include <signal.h> 11 #include "objfmt.h" 12 13 /* 14 * This version of pi has been in use at Berkeley since May 1977 15 * and is very stable, except for the syntactic error recovery which 16 * has just been written. 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 = "/usr/lib/how_pi\0"; 49 #endif OBJ 50 #ifdef PC 51 char *howfile = "/usr/lib/how_pc"; 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 += 9; 84 # ifdef OBJ 85 if (argv[0][0] == '-' && argv[0][1] == 'o') { 86 obj = &argv[0][2]; 87 usageis = pixusage; 88 howfile[15] = '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('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++; 129 case 'F': 130 fulltrace++; 131 case 'E': 132 errtrace++; 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 'l': 154 case 'n': 155 case 'p': 156 case 's': 157 case 't': 158 case 'u': 159 case 'w': 160 togopt(c); 161 continue; 162 case 'z': 163 monflg++; 164 continue; 165 default: 166 usage: 167 Perror( "Usage", usageis); 168 pexit(NOSTART); 169 } 170 argc--, argv++; 171 } 172 # endif OBJ 173 # ifdef PC 174 opt( 'b' ) = 1; 175 opt( 'g' ) = 0; 176 opt( 't' ) = 0; 177 opt( 'p' ) = 0; 178 usageis = pcusage; 179 while ( argc > 0 ) { 180 cp = argv[0]; 181 if ( *cp++ != '-' ) { 182 break; 183 } 184 c = *cp++; 185 switch( c ) { 186 #ifdef DEBUG 187 case 'k': 188 case 'r': 189 case 'y': 190 togopt(c); 191 break; 192 case 'K': 193 yycosts(); 194 pexit(NOSTART); 195 case 'A': 196 testtrace++; 197 /* and fall through */ 198 case 'F': 199 fulltrace++; 200 /* and fall through */ 201 case 'E': 202 errtrace++; 203 opt('r')++; 204 break; 205 case 'U': 206 yyunique = 0; 207 break; 208 #endif 209 case 'b': 210 opt('b') = 2; 211 break; 212 case 'i': 213 pflist = argv + 1; 214 pflstc = 0; 215 while (argc > 1) { 216 if (dotted(argv[1], 'p')) 217 break; 218 pflstc++, argc--, argv++; 219 } 220 if (pflstc == 0) 221 goto usage; 222 break; 223 /* 224 * output file for the first pass 225 */ 226 case 'o': 227 if ( argc < 2 ) { 228 goto usage; 229 } 230 argv++; 231 argc--; 232 pcname = argv[0]; 233 break; 234 case 'C': 235 /* 236 * since -t is an ld switch, use -C 237 * to turn on tests 238 */ 239 togopt( 't' ); 240 break; 241 case 'g': 242 /* 243 * sdb symbol table 244 */ 245 togopt( 'g' ); 246 break; 247 case 'l': 248 case 's': 249 case 'u': 250 case 'w': 251 togopt(c); 252 break; 253 case 'p': 254 /* 255 * -p on the command line means profile 256 */ 257 profflag++; 258 break; 259 case 'z': 260 monflg++; 261 break; 262 default: 263 usage: 264 Perror( "Usage", usageis); 265 pexit(NOSTART); 266 } 267 argc--; 268 argv++; 269 } 270 # endif PC 271 if (argc != 1) 272 goto usage; 273 efil = open ( errfile, 0 ); 274 if ( efil < 0 ) 275 perror(errfile), pexit(NOSTART); 276 filename = argv[0]; 277 if (!dotted(filename, 'p')) { 278 Perror(filename, "Name must end in '.p'"); 279 pexit(NOSTART); 280 } 281 close(0); 282 if ( ( ibuf = fopen( filename , "r" ) ) == NULL ) 283 perror(filename), pexit(NOSTART); 284 ibp = ibuf; 285 # ifdef PC 286 if ( ( pcstream = fopen( pcname , "w" ) ) == NULL ) { 287 perror( pcname ); 288 pexit( NOSTART ); 289 } 290 stabsource( filename ); 291 # endif PC 292 # ifdef PTREE 293 # define MAXpPAGES 16 294 if ( ! pCreate( pTreeName , MAXpPAGES ) ) { 295 perror( pTreeName ); 296 pexit( NOSTART ); 297 } 298 # endif PTREE 299 if ( signal( SIGINT , SIG_IGN ) != SIG_IGN ) 300 signal( SIGINT , onintr ); 301 if (opt('l')) { 302 opt('n')++; 303 yysetfile(filename); 304 opt('n')--; 305 } 306 yymain(); 307 /* No return */ 308 } 309 310 pchr(c) 311 char c; 312 { 313 314 putc ( c , stdout ); 315 } 316 317 char ugh[] = "Fatal error in pi\n"; 318 /* 319 * Exit from the Pascal system. 320 * We throw in an ungraceful termination 321 * message if c > 1 indicating a severe 322 * error such as running out of memory 323 * or an internal inconsistency. 324 */ 325 pexit(c) 326 int c; 327 { 328 329 if (opt('l') && c != DIED && c != NOSTART) 330 while (getline() != -1) 331 continue; 332 yyflush(); 333 switch (c) { 334 case DIED: 335 write(2, ugh, sizeof ugh); 336 case NOSTART: 337 case ERRS: 338 # ifdef OBJ 339 if (ofil > 0) 340 unlink(obj); 341 # endif OBJ 342 # ifdef PC 343 if ( pcstream != NULL ) { 344 unlink( pcname ); 345 } 346 # endif PC 347 break; 348 case AOK: 349 # ifdef OBJ 350 pflush(); 351 # endif OBJ 352 # ifdef PC 353 puteof(); 354 # endif PC 355 break; 356 } 357 /* 358 * this to gather statistics on programs being compiled 359 * taken 20 june 79 ... peter 360 * 361 * if (fork() == 0) { 362 * char *cp = "-0"; 363 * cp[1] += c; 364 * execl("/usr/lib/gather", "gather", cp, filename, 0); 365 * exit(1); 366 * } 367 */ 368 # ifdef PTREE 369 pFinish(); 370 # endif 371 exit(c); 372 } 373 374 onintr() 375 { 376 377 signal( SIGINT , SIG_IGN ); 378 pexit(NOSTART); 379 } 380 381 /* 382 * Get an error message from the error message file 383 */ 384 geterr(seekpt, buf) 385 int seekpt; 386 char *buf; 387 { 388 389 lseek(efil, (long) seekpt, 0); 390 if (read(efil, buf, 256) <= 0) 391 perror(errfile), pexit(DIED); 392 } 393 394 header() 395 { 396 extern char version[]; 397 static char anyheaders; 398 399 gettime( filename ); 400 if (anyheaders && opt('n')) 401 putc( '\f' , stdout ); 402 anyheaders++; 403 # ifdef OBJ 404 printf("Berkeley Pascal PI -- Version 2.0 (%s)\n\n%s %s\n\n", 405 version, myctime(&tvec), filename); 406 # endif OBJ 407 # ifdef PC 408 printf("Berkeley Pascal PC -- Version 2.0 (%s)\n\n%s %s\n\n", 409 version, myctime(&tvec), filename); 410 # endif PC 411 } 412