Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/c/preproc/main.unx
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

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);
}