BSD 4 release
[unix-history] / usr / src / cmd / pc0 / main.c
/* Copyright (c) 1979 Regents of the University of California */
static char sccsid[] = "@(#)main.c 1.1 8/27/80";
#include "whoami.h"
#include "0.h"
#include "yy.h"
#include <signal.h>
#include "objfmt.h"
/*
* This version of pi has been in use at Berkeley since May 1977
* and is very stable, except for the syntactic error recovery which
* has just been written. Please report any problems with the error
* recovery to the second author at the address given in the file
* READ_ME. The second author takes full responsibility for any bugs
* in the syntactic error recovery.
*/
char piusage[] = "pi [ -blnpstuw ] [ -i file ... ] name.p";
char pixusage[] = "pix [ -blnpstuw ] [ -i file ... ] name.p [ arg ... ]";
char pcusage[] = "pc [ options ] [ -o file ] [ -i file ... ] name.p";
char *usageis = piusage;
char *errfile = ERR_STRNGS;
#ifdef OBJ
char *obj = "obj";
#endif OBJ
#ifdef PC
char *pcname = "pc.pc1";
#endif PC
#ifdef PTREE
char *pTreeName = "pi.pTree";
#endif PTREE
/*
* Be careful changing errfile and howfile.
* There are the "magic" constants 9 and 15 immediately below.
* errfile is now defined by ERR_STRNGS, in objfmt.h,
* and its leading path name length is ERR_PATHLEN long.
* this for executing out of the current directory if running as `a.something'.
*/
#ifdef OBJ
char *howfile = "/usr/lib/how_pi\0";
#endif OBJ
#ifdef PC
char *howfile = "/usr/lib/how_pc";
#endif PC
int onintr();
extern char *lastname;
FILE *ibuf;
FILE *pcstream = NULL;
/*
* these are made real variables
* so they can be changed
* if you are compiling on a smaller machine
*/
double MAXINT = 2147483647.;
double MININT = -2147483648.;
/*
* Main program for pi.
* Process options, then call yymain
* to do all the real work.
*/
main(argc, argv)
int argc;
char *argv[];
{
register char *cp;
register c;
int i;
if (argv[0][0] == 'a')
errfile += ERR_PATHLEN , howfile += 9;
# ifdef OBJ
if (argv[0][0] == '-' && argv[0][1] == 'o') {
obj = &argv[0][2];
usageis = pixusage;
howfile[15] = 'x';
ofil = 3;
} else {
ofil = creat(obj, 0755);
if (ofil < 0) {
perror(obj);
pexit(NOSTART);
}
}
# endif OBJ
argv++, argc--;
if (argc == 0) {
i = fork();
if (i == -1)
goto usage;
if (i == 0) {
execl("/bin/cat", "cat", howfile, 0);
goto usage;
}
while (wait(&i) != -1)
continue;
pexit(NOSTART);
}
# ifdef OBJ
opt('p') = opt('t') = opt('b') = 1;
while (argc > 0) {
cp = argv[0];
if (*cp++ != '-')
break;
while (c = *cp++) switch (c) {
#ifdef DEBUG
case 'k':
case 'r':
case 'y':
togopt(c);
continue;
case 'K':
yycosts();
pexit(NOSTART);
case 'A':
testtrace++;
case 'F':
fulltrace++;
case 'E':
errtrace++;
opt('r')++;
continue;
case 'U':
yyunique = 0;
continue;
#endif
case 'b':
opt('b') = 2;
continue;
case 'i':
pflist = argv + 1;
pflstc = 0;
while (argc > 1) {
if (dotted(argv[1], 'p'))
break;
pflstc++, argc--, argv++;
}
if (pflstc == 0)
goto usage;
continue;
case 'l':
case 'n':
case 'p':
case 's':
case 't':
case 'u':
case 'w':
togopt(c);
continue;
case 'z':
monflg++;
continue;
default:
usage:
Perror( "Usage", usageis);
pexit(NOSTART);
}
argc--, argv++;
}
# endif OBJ
# ifdef PC
opt( 'b' ) = 1;
opt( 'g' ) = 0;
opt( 't' ) = 0;
opt( 'p' ) = 0;
usageis = pcusage;
while ( argc > 0 ) {
cp = argv[0];
if ( *cp++ != '-' ) {
break;
}
c = *cp++;
switch( c ) {
#ifdef DEBUG
case 'k':
case 'r':
case 'y':
togopt(c);
break;
case 'K':
yycosts();
pexit(NOSTART);
case 'A':
testtrace++;
/* and fall through */
case 'F':
fulltrace++;
/* and fall through */
case 'E':
errtrace++;
opt('r')++;
break;
case 'U':
yyunique = 0;
break;
#endif
case 'b':
opt('b') = 2;
break;
case 'i':
pflist = argv + 1;
pflstc = 0;
while (argc > 1) {
if (dotted(argv[1], 'p'))
break;
pflstc++, argc--, argv++;
}
if (pflstc == 0)
goto usage;
break;
/*
* output file for the first pass
*/
case 'o':
if ( argc < 2 ) {
goto usage;
}
argv++;
argc--;
pcname = argv[0];
break;
case 'C':
/*
* since -t is an ld switch, use -C
* to turn on tests
*/
togopt( 't' );
break;
case 'g':
/*
* sdb symbol table
*/
togopt( 'g' );
break;
case 'l':
case 's':
case 'u':
case 'w':
togopt(c);
break;
case 'p':
/*
* -p on the command line means profile
*/
profflag++;
break;
case 'z':
monflg++;
break;
default:
usage:
Perror( "Usage", usageis);
pexit(NOSTART);
}
argc--;
argv++;
}
# endif PC
if (argc != 1)
goto usage;
efil = open ( errfile, 0 );
if ( efil < 0 )
perror(errfile), pexit(NOSTART);
filename = argv[0];
if (!dotted(filename, 'p')) {
Perror(filename, "Name must end in '.p'");
pexit(NOSTART);
}
close(0);
if ( ( ibuf = fopen( filename , "r" ) ) == NULL )
perror(filename), pexit(NOSTART);
ibp = ibuf;
# ifdef PC
if ( ( pcstream = fopen( pcname , "w" ) ) == NULL ) {
perror( pcname );
pexit( NOSTART );
}
stabsource( filename );
# endif PC
# ifdef PTREE
# define MAXpPAGES 16
if ( ! pCreate( pTreeName , MAXpPAGES ) ) {
perror( pTreeName );
pexit( NOSTART );
}
# endif PTREE
if ( signal( SIGINT , SIG_IGN ) != SIG_IGN )
signal( SIGINT , onintr );
if (opt('l')) {
opt('n')++;
yysetfile(filename);
opt('n')--;
}
yymain();
/* No return */
}
pchr(c)
char c;
{
putc ( c , stdout );
}
char ugh[] = "Fatal error in pi\n";
/*
* Exit from the Pascal system.
* We throw in an ungraceful termination
* message if c > 1 indicating a severe
* error such as running out of memory
* or an internal inconsistency.
*/
pexit(c)
int c;
{
if (opt('l') && c != DIED && c != NOSTART)
while (getline() != -1)
continue;
yyflush();
switch (c) {
case DIED:
write(2, ugh, sizeof ugh);
case NOSTART:
case ERRS:
# ifdef OBJ
if (ofil > 0)
unlink(obj);
# endif OBJ
# ifdef PC
if ( pcstream != NULL ) {
unlink( pcname );
}
# endif PC
break;
case AOK:
# ifdef OBJ
pflush();
# endif OBJ
# ifdef PC
puteof();
# endif PC
break;
}
/*
* this to gather statistics on programs being compiled
* taken 20 june 79 ... peter
*
* if (fork() == 0) {
* char *cp = "-0";
* cp[1] += c;
* execl("/usr/lib/gather", "gather", cp, filename, 0);
* exit(1);
* }
*/
# ifdef PTREE
pFinish();
# endif
exit(c);
}
onintr()
{
signal( SIGINT , SIG_IGN );
pexit(NOSTART);
}
/*
* Get an error message from the error message file
*/
geterr(seekpt, buf)
int seekpt;
char *buf;
{
lseek(efil, (long) seekpt, 0);
if (read(efil, buf, 256) <= 0)
perror(errfile), pexit(DIED);
}
header()
{
extern char version[];
static char anyheaders;
gettime( filename );
if (anyheaders && opt('n'))
putc( '\f' , stdout );
anyheaders++;
# ifdef OBJ
printf("Berkeley Pascal PI -- Version 2.0 (%s)\n\n%s %s\n\n",
version, myctime(&tvec), filename);
# endif OBJ
# ifdef PC
printf("Berkeley Pascal PC -- Version 2.0 (%s)\n\n%s %s\n\n",
version, myctime(&tvec), filename);
# endif PC
}