mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 08:24:18 +00:00
489 lines
10 KiB
Plaintext
489 lines
10 KiB
Plaintext
#
|
|
/*
|
|
Copyright 1981
|
|
Alcyon Corporation
|
|
8474 Commerce Av.
|
|
San Diego, Ca. 92121
|
|
*/
|
|
|
|
#include "preproc.h"
|
|
|
|
#define NARGS 64
|
|
#define ARGSIZE 1024
|
|
#define ICODE 0
|
|
#define STRINGS 1
|
|
#define MTEMP 2
|
|
#define ASTEMP 3
|
|
#define NTEMPS 4
|
|
|
|
|
|
char *fargs[NARGS+1];
|
|
char **fargp;
|
|
char argbuf[ARGSIZE];
|
|
char *cfiles[NARGS+1];
|
|
char *loadargs[NARGS+1];
|
|
char *fns[NTEMPS];
|
|
char *tfns[NTEMPS];
|
|
char *defs[NARGS];
|
|
int ndefs;
|
|
char *argp &argbuf[0];
|
|
int cflag;
|
|
int nflag;
|
|
int lflag;
|
|
int oflag;
|
|
int pflag;
|
|
int sflag;
|
|
int xflag;
|
|
int status;
|
|
int oneflag;
|
|
int errno;
|
|
char *parser "/lib/c068";
|
|
char *cgen "/lib/c168";
|
|
char *onepass "/lib/c0168";
|
|
char *pref "/lib/c680.o";
|
|
char *clib6 "/lib/lib6.a";
|
|
char *loader "/bin/lo68";
|
|
char *asm "/bin/as68";
|
|
#ifdef NOMMU
|
|
int nommu 1;
|
|
#else
|
|
int nommu 0;
|
|
#endif
|
|
|
|
|
|
// cexit - exit from C compiler driver
|
|
// This deletes any existing temps and exits with the error status.
|
|
cexit() // returns - none
|
|
{
|
|
register int i;
|
|
|
|
if( pflag == 0 ) {
|
|
for( i = 0; i < NTEMPS; i++ )
|
|
if( fns[i] )
|
|
unlink(fns[i]);
|
|
}
|
|
exit(status);
|
|
}
|
|
|
|
// main - main routine for C68 Compiler system
|
|
// Handles the C68 arguments. For each C file given, the macro
|
|
// pre-processor is called, then the parser, code generator and
|
|
// assember are fexec'd. The loader arguments are collected and
|
|
// the loader is fexec'd.
|
|
main(argc,argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
register char *arg, **p, **cfilep, **loadp;
|
|
register int nloadfiles, c, i;
|
|
|
|
cfilep = &cfiles[0];
|
|
loadp = &loadargs[0];
|
|
nloadfiles = 0;
|
|
for( p = argv; --argc > 0; ) { //process arguments
|
|
if( *(arg= *++p) == '-' ) {
|
|
arg++;
|
|
for( i = 0; c = *arg++; i++ ) {
|
|
switch( c ) {
|
|
|
|
case 'c':
|
|
cflag++;
|
|
continue;
|
|
|
|
case '1':
|
|
oneflag++;
|
|
parser = onepass;
|
|
continue;
|
|
|
|
case 'D':
|
|
defs[ndefs++] = arg;
|
|
i++;
|
|
break;
|
|
|
|
case 'N':
|
|
nflag++;
|
|
continue;
|
|
|
|
case 'f':
|
|
printf("floating point not yet implemented\n");
|
|
continue;
|
|
|
|
case 'L':
|
|
lflag++;
|
|
continue;
|
|
|
|
case 'o':
|
|
if( --argc <= 0 )
|
|
ferror("bad -o option");
|
|
*loadp++ = *p++;
|
|
*loadp++ = *p;
|
|
continue;
|
|
|
|
case 'P':
|
|
pflag++;
|
|
cflag++;
|
|
continue;
|
|
|
|
case 'S':
|
|
sflag++;
|
|
cflag++;
|
|
nflag++;
|
|
continue;
|
|
|
|
case 't':
|
|
if( (c= *arg++) == '0' )
|
|
parser = "/usr/c68/c068";
|
|
else if( c == '1' )
|
|
cgen = "/usr/c68/c168";
|
|
else if( c == '\0' )
|
|
arg--;
|
|
continue;
|
|
|
|
default:
|
|
if( loadp >= &loadargs[NARGS] )
|
|
ferror("too many loader args");
|
|
*loadp++ = *p;
|
|
i++;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
if( i )
|
|
continue;
|
|
}
|
|
if( strend(arg,".c") || strend(arg,".s") ) {
|
|
|
|
//C or Assembler files to process
|
|
|
|
if( cfilep >= &cfiles[NARGS] )
|
|
ferror("too many files");
|
|
*cfilep++ = arg;
|
|
}
|
|
else if( chkdup(arg) == 0 ) { //check for loader args
|
|
if( loadp >= &loadargs[NARGS] )
|
|
ferror("too many loader args");
|
|
*loadp++ = arg;
|
|
if( strend(arg,".o") )
|
|
nloadfiles++;
|
|
}
|
|
}
|
|
if( cfilep != &cfiles[0] ) { //had a C file?
|
|
signal(2,&cexit); //catch rubouts
|
|
for( i = 0; i < NTEMPS; i++ ) //allocate temps
|
|
fns[i] = maketemp(i);
|
|
for( p = &cfiles[0]; arg = *p++; ) { //handle each C file
|
|
for( i = 0; i < NTEMPS; i++ )
|
|
tfns[i] = fns[i];
|
|
if( cfilep != &cfiles[1] )
|
|
printf("%s:\n",arg);
|
|
|
|
//the following sets things up for the parser, the macro pre-processor
|
|
//is called (not forked), then the parser is fexec'd.
|
|
|
|
asflag = strend(arg,".s");
|
|
if( pflag || asflag )
|
|
tfns[MTEMP] = setend(arg,'i');
|
|
if( domacro(arg,tfns[MTEMP],ndefs,defs) == 0 || pflag ) {
|
|
cflag++;
|
|
continue;
|
|
}
|
|
if( asflag == 0 ) {
|
|
tfns[ASTEMP] = setend(arg,'s');
|
|
initfargs();
|
|
addfarg(parser);
|
|
addfarg(tfns[MTEMP]);
|
|
if( oneflag ) {
|
|
addfarg(tfns[ASTEMP]);
|
|
addfarg(tfns[STRINGS]);
|
|
if( lflag || nommu )
|
|
addfarg("-L");
|
|
if( sflag || nflag )
|
|
addfarg("-D");
|
|
addfarg("-1");
|
|
}
|
|
else {
|
|
addfarg(tfns[ICODE]);
|
|
addfarg(tfns[STRINGS]);
|
|
}
|
|
endfargs();
|
|
if( fexec(parser,fargs) ) {
|
|
status++;
|
|
cflag++;
|
|
continue;
|
|
}
|
|
|
|
//this sets things up for the code generator
|
|
|
|
if( oneflag == 0 ) {
|
|
initfargs();
|
|
addfarg(cgen);
|
|
addfarg(tfns[ICODE]);
|
|
addfarg(tfns[ASTEMP]);
|
|
if( sflag == 0 )
|
|
fns[ASTEMP] = tfns[ASTEMP];
|
|
if( lflag || nommu )
|
|
addfarg("-L");
|
|
if( nflag || sflag )
|
|
addfarg("-D");
|
|
endfargs();
|
|
if( fexec(cgen,fargs) ) {
|
|
status++;
|
|
cflag++;
|
|
continue;
|
|
}
|
|
}
|
|
if( sflag )
|
|
continue;
|
|
}
|
|
else
|
|
tfns[ASTEMP] = tfns[MTEMP];
|
|
|
|
//this sets things up for the assembler
|
|
|
|
initfargs();
|
|
addfarg(asm);
|
|
if( asflag == 0 )
|
|
addfarg("-u");
|
|
if( lflag || nommu )
|
|
addfarg("-L");
|
|
addfarg(tfns[ASTEMP]);
|
|
endfargs();
|
|
if( fexec(asm,fargs) ) {
|
|
cflag++;
|
|
status++;
|
|
}
|
|
unlink(tfns[ASTEMP]);
|
|
}
|
|
}
|
|
if( cflag == 0 && (loadp != &loadargs[0] || cfilep != &cfiles[0] )) {
|
|
|
|
//set things up for the loader, this means that we need to add the
|
|
//C preface at the beginning of the program which has the jsr to
|
|
//main and then exits after return from main.
|
|
|
|
initfargs();
|
|
addfarg(loader);
|
|
addfarg("-X");
|
|
if( nommu )
|
|
addfarg("-r");
|
|
for( p = loadargs; (arg = *p) && *arg == '-'; p++ ) {
|
|
addfarg(arg);
|
|
if( arg[1] == 'o' )
|
|
addfarg(*++p);
|
|
}
|
|
addfarg(pref); //C preface to jsr to main
|
|
for( cfilep = &cfiles[0]; *cfilep; nloadfiles++ ) {
|
|
arg = setend(*cfilep++,'o');
|
|
if( chkdup(arg) == 0 )
|
|
addfarg(arg);
|
|
}
|
|
while( *p )
|
|
addfarg(*p++);
|
|
addfarg(clib6);
|
|
endfargs();
|
|
status =| fexec(loader,fargs);
|
|
|
|
//if we were given one C file and there is one ".o" file, we remove
|
|
//the ".o" file.
|
|
|
|
if( cfilep == &cfiles[1] && nloadfiles == 1 )
|
|
unlink(setend(cfiles[0],'o'));
|
|
}
|
|
cexit();
|
|
}
|
|
|
|
// fexec - fork and exec
|
|
// This forks a new task, then does an execv to execute the given
|
|
// program with the given arguements.
|
|
fexec(fname,args) // returns 1 if error, 0 otherwise
|
|
char *fname; // file to execute
|
|
char **args; // arguments to pass
|
|
{
|
|
register int pid, i;
|
|
int fstat;
|
|
|
|
// if( (pid=fork()) == 0 ) { //child process
|
|
// execv(fname,args);
|
|
// printf("can't execv %s errno=%d\n",fname,errno);
|
|
// exit(1);
|
|
// }
|
|
pid = maketask(fname,0,0,args); //do fork & exec
|
|
if( pid < 0 ) {
|
|
printf("can't fork errno=%d\n",errno);
|
|
return(1);
|
|
}
|
|
while( pid != wait(&fstat) ) //wait for child
|
|
;
|
|
if( (i=fstat&0377) != 0 && i != 14 ) {
|
|
if( i != 2 )
|
|
printf("%s error terminated\n",fname);
|
|
status++;
|
|
cexit();
|
|
}
|
|
return( (fstat>>8) & 0377 );
|
|
}
|
|
|
|
// setend - set the end character of a string
|
|
// This grabs a copy of the string and sets the last character to
|
|
// the given character. This is used to generate ".o", ".i" and
|
|
// ".s" file names.
|
|
char *setend(s,c) // returns pointer to string
|
|
char *s; // pointer to old string
|
|
int c; // character to end string with
|
|
{
|
|
register char *p;
|
|
|
|
p = makecopy(s);
|
|
p[strlen(p)-1] = c;
|
|
return(p);
|
|
}
|
|
|
|
// chkdup - checks for duplicate ".o" files in file list
|
|
// Goes thru the loader argument list checking for the given
|
|
// ".o" file name.
|
|
chkdup(s) // returns 1 if found, 0 otherwise
|
|
char *s; // pointer to argument
|
|
{
|
|
register char **l;
|
|
|
|
if( strend(s,".o") ) {
|
|
for( l = &loadargs[0]; *l; )
|
|
if( strcmp(*l++,s) == 0 )
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
// makecopy - makes a copy of a string
|
|
// This allows for manipulating the file name, while allowing the
|
|
// saving of the old file name.
|
|
char *makecopy(s) // returns pointer to string
|
|
char *s; // string to copy
|
|
{
|
|
register char *p;
|
|
|
|
for( p = argp; *argp++ = *s++; )
|
|
;
|
|
return(p);
|
|
}
|
|
|
|
// initfargs - initialize fexec arg block
|
|
// This sets the arg block pointer to the beginning of the block.
|
|
initfargs() // returns - none
|
|
{
|
|
fargp = &fargs[0];
|
|
}
|
|
|
|
// addfarg - add fexec argument
|
|
// This takes the given arguement and adds it to the argment block
|
|
addfarg(s)
|
|
char *s;
|
|
{
|
|
if( fargp >= &fargs[NARGS] )
|
|
ferror("too many args");
|
|
*fargp++ = s;
|
|
}
|
|
|
|
// endfargs - end fexec argument block
|
|
// This ends the argument block with a zero pointer.
|
|
endfargs() // returns - none
|
|
{
|
|
*fargp = 0;
|
|
}
|
|
|
|
// ferror - fatal error
|
|
// Outputs error message and exits with error status.
|
|
ferror(s,x1,x2,x3,x4,x5,x6) // returns - none
|
|
char *s; // printf string
|
|
int x1, x2, x3, x4, x5, x6; // printf args
|
|
{
|
|
printf(s,x1,x2,x3,x4,x5,x6);
|
|
printf("\n");
|
|
status++;
|
|
cexit();
|
|
}
|
|
|
|
// maketemp - make a temporary file name
|
|
// Generates unique file name with process id
|
|
char *maketemp(arb) // returns file name
|
|
int arb; // arbitrary number
|
|
{
|
|
char *p, tmp[6];
|
|
|
|
p = makecopy("/tmp/ct6");
|
|
argp--;
|
|
itoa(getpid(),tmp,1);
|
|
makecopy(tmp);
|
|
argp--;
|
|
makecopy(".");
|
|
argp--;
|
|
itoa(arb,tmp,1);
|
|
makecopy(tmp);
|
|
return(p);
|
|
}
|
|
|
|
// strcmp - string comparison
|
|
// Compares two strings for equality, less or greater.
|
|
strcmp(s,t) // returns 0 for equality,
|
|
// neg for < and pos for >.
|
|
char *s; // first string
|
|
char *t; // second string
|
|
{
|
|
for( ; *s == *t; s++, t++ )
|
|
if( *s == '\0' )
|
|
return(0);
|
|
return( *s - *t );
|
|
}
|
|
|
|
// strlen - string length
|
|
// Computes number of bytes in string.
|
|
strlen(s) // returns string length
|
|
char *s; // string to compute length
|
|
{
|
|
register int n;
|
|
|
|
for( n = 0; *s++ != '\0'; )
|
|
n++;
|
|
return(n);
|
|
}
|
|
|
|
// itoa - integer to ASCII conversion
|
|
// Converts integer to ASCII string, handles '-'.
|
|
itoa(n,s,w) // returns - none
|
|
int n; // number to convert
|
|
char *s; // resulting string
|
|
int w; // minimum width of string
|
|
{
|
|
register int sign, i;
|
|
char temp[6];
|
|
|
|
if( (sign=n) < 0 )
|
|
n = -n;
|
|
i = 0;
|
|
do {
|
|
temp[i++] = n % 10 + '0';
|
|
} while( (n =/ 10) > 0 );
|
|
if( sign < 0 )
|
|
temp[i++] = '-';
|
|
while( --w >= i ) //pad on left with blanks
|
|
*s++ = ' ';
|
|
while( --i >= 0 ) //move chars reversed
|
|
*s++ = temp[i];
|
|
*s = '\0';
|
|
}
|
|
|
|
// strend - set string end
|
|
// This is used to compare the endings of file names for ".c", etc.
|
|
strend(s,t) // returns 1 if match, 0 otherwise
|
|
char *s; // string to compare
|
|
char *t; // string ending
|
|
{
|
|
int ls, lt;
|
|
|
|
if( (ls=strlen(s)) < (lt=strlen(t)) )
|
|
return(0);
|
|
if( strcmp(&s[ls-lt],t) == 0 )
|
|
return(1);
|
|
return(0);
|
|
}
|