home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
EFFO
/
forum16.lzh
/
SOFTWARE
/
C
/
CC
/
fastcc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-15
|
22KB
|
738 lines
/*
* NewCC: a skeleton cc-front-end with piping
* This software is copyright (C) 1989 by Reimer Mellin *
* *
* Permission is granted to reproduce and distribute *
* this package by any means so long as no fee is charged *
* above a nominal handling fee and so long as this *
* notice is always included in the copies. *
* Commerical use or incorporation into commercial software *
* is prohibited without the written permission of the *
* author. *
* *
* Other rights are reserved except as explicitly granted *
* by written permission of the author. *
* Reimer Mellin *
* Sulenstr.8 *
* D-8000 Muenchen 71 (Federal Republic of Germany) *
* *
* EMAIL: *
* ram@altger.sub.org.UUCP *
* ram%ramsys@chiuur.sub.org (home) *
* *
*/
#include <stdio.h>
#include <errno.h>
extern int os9exec(), os9forkc(),errno;
/*
* structure for our lists
*/
struct optlist {
short numel; /* number of elements in list */
char **list;
} cppopt,ccopt,optopt,asopt,lnopt,ccdo,asdo;
char *rdir; /* Rels-dir */
char *tmpdir; /* temp-dir */
short compiler, assembler, linker; /* what to do */
short quietflag, showflag, pipeflag, noopt, sig_rec;
static char *emptylist[] = {
0
};
/*
* Default arg-vector for cpp
*/
static char *cpplist[] = {
"cpp", 0
};
/*
* Default arg-vector for compiler
*/
static char *cclist[] = {
"c68", 0
};
/*
* Default arg-vector for so-called 'optimizer'
*/
static char *optlist[] = {
"o68", 0
};
/*
* Default arg-vector for assembler
*/
static char *asslist[] = {
"r68", "-q", 0
};
/*
* Default arg-vector for linker, see iflag,xflag and jflag in main()
*/
static char *lnlist[] = {
"l68", 0
};
void
mputs( str )
char *str;
{
fprintf(stderr,str);
}
void
usagehelp()
{
fprintf(stderr,"%s: <opts> <files> <opts>\n", _prgname());
mputs("Options:\n");
mputs("\t-a\t\tCompile to assembler files\n");
mputs("\t-bp\t\tshow commands before executing\n");
mputs("\t-bg\t\tcreate ghost module on output\n");
mputs("\t-c\t\tleave comments in assember-files\n");
mputs("\t-d<name>\tdefine for cpp\n");
mputs("\t-e<=num>\tedition number for output\n");
mputs("\t-u<name>\tundefine for cpp\n");
mputs("\t-f<=path>\toutput path (exec-dir)\n");
mputs("\t-fd<=path>\toutpath (data-dir)\n");
mputs("\t-g\t\tgenerate debugging info\n");
mputs("\t-i\t\tuse clib-trap-library\n");
mputs("\t-j\t\tdont generate a jump-table\n");
mputs("\t-l<=name>\tadditional library to search\n");
mputs("\t-n<=name>\toutput module name\n");
mputs("\t-r<=dir>\tcompile/assemble to rel. files\n");
mputs("\t-o\t\tdon't run o68\n");
mputs("\t-p\t\tpipe cpp-output into the compiler\n");
mputs("\t-q\t\tquiet mode\n");
mputs("\t-s\t\tomit stack-checking\n");
mputs("\t-t<=dir>\tdir for temp. files\n");
mputs("\t-x\t\tuse math-trap-lib\n");
mputs("\t-v<=dir>\tsearch-dir for cpp\n");
mputs("\t-m<=n>\t\tadditional memory for stack in output module\n");
exit(1);
}
void *
Malloc( size )
register int size;
{
register void *sp = (void *)malloc(size);
if( sp == (void *)0)
exit(errno);
memset(sp,0,size);
return sp;
}
void *
Realloc( ptr, size)
register void *ptr;
register int size;
{
ptr = (void *)realloc( ptr,size);
if( ptr == (void *)0)
exit(errno);
return ptr;
}
/*
* Set-up a list
*/
initlist( where, list )
struct optlist *where;
char *list[];
{
register int i;
register char **sp,**ssp;
for(i=0,sp=list; *sp; sp++,i++);
where->list = (char **) Malloc( sizeof(char **) * (i + 1));
ssp = where->list; sp = list;
while(*ssp++ = *sp++);
where->numel = i;
}
/*
* append a string to a list
*/
appendlist( where, item)
register struct optlist *where;
register char *item;
{
where->list = (char **) Realloc( where->list,
sizeof(char **) * (where->numel+2));
where->list[where->numel] = (char *)strcpy(Malloc(strlen(item)+1), item);
where->numel += 1;
where->list[where->numel]= (char *)0;
}
/*
* make room in a list for two new args (needed for the filenames)
*/
preplist( where )
register struct optlist *where;
{
where->list = (char **) Realloc( where->list,
sizeof(char **) * (where->numel+3));
where->list[where->numel+2] = (char *)0;
}
/*
* return the char after the rightmost '.' or '?'
*/
char
filetype( name )
char *name;
{
char *rindex();
if((name = rindex(name,'.')) == (char *)0)
return '?';
return( (name[2] != '\0') ? '?' : name[1]);
}
int
sighand( sig)
int sig;
{
sig_rec=sig;
}
main(argc,argv)
int argc;
char *argv[];
{
void compile(),assemble();
int dofork();
char *getenv();
register int i;
register char *sp;
char tmp[100];
char *libs;
char *incs;
int iflag; /* what c-lib to use */
int jflag; /* generating a jumptable ? */
int xflag; /* what math-lib to use */
short files;
/*
* Init the flags
*/
tmpdir = rdir = ".";
jflag = iflag = xflag = compiler = assembler = linker = 1;
files = noopt = quietflag = showflag = pipeflag = sig_rec = 0;
/*
* install a signal-handler
*/
intercept(sighand);
/*
* setup the lists, with the default values
*/
initlist( &cppopt, cpplist);
initlist( &ccopt, cclist);
initlist( &optopt, optlist);
initlist( &asopt, asslist);
initlist( &lnopt, lnlist);
initlist( &ccdo, emptylist);
initlist( &asdo, emptylist);
/*
* get the default dirs for <>-files and libs
*/
if( (libs = getenv("CLIB")) == (char *)0)
libs = "/h0/lib";
if( (incs = getenv("CDEF")) == (char *)0)
incs = "/h0/defs";
/*
* add cstart file to linker-args ...
*/
sprintf(tmp,"%s/cstart.r", libs);
appendlist( &lnopt, tmp);
/*
* add CDEF dir to cpp-args
*/
sprintf(tmp,"-v=%s", incs);
appendlist( &cppopt, tmp);
for( i=1; i < argc; i++) {
sp = argv[i];
switch ( *sp ) {
short contflag;
/*
* various cases in the next switch statement set contflag to 0, indicating
* a completed arg ( eg: -t=<string> )
*/
case '-':
contflag = 1;
for( sp++; *sp && contflag; sp++) {
switch( *sp) {
case '?':
usagehelp();
/* exits */
case 'Q':
case 'q':
quietflag = 1;
break;
case 'a':
case 'A':
/* neither run assembler nor linker */
assembler = 0;
linker = 0;
break;
case 'g':
case 'G':
appendlist( &lnopt, "-g");
appendlist( &ccopt, "-g");
appendlist( &cppopt, "-g");
/* fall though */
case 'o':
case 'O':
noopt = 1;
break;
case 'c':
case 'C':
appendlist( &cppopt, "-l");
noopt = 1;
break;
case 'r':
case 'R':
if( sp[1] ) {
sp += (sp[1] == '=') ? 2:1;
rdir = sp;
}
contflag = 0;
/* linker == 2, if 'cc -r=tmp -f=name...' */
if( linker < 2 )
linker = 0;
break;
case 'f':
case 'F':
if( tolower( sp[1] ) == 'd') {
sp++;
(void)strcpy(tmp,"-O=");
} else
(void)strcpy(tmp,"-o=");
sp += (sp[1] == '=') ? 2:1;
strcat(tmp,sp);
appendlist( &lnopt, tmp);
contflag = 0;
linker = 2;
break;
case 'b':
case 'B':
switch( tolower(sp[1])) {
case 'p':
showflag = 1;
break;
case 'g':
appendlist( &lnopt,"-S");
break;
default:
usagehelp();
}
sp +=1;
break;
case 's':
case 'S':
appendlist( &ccopt, "-s");
break;
case 't':
case 'T':
sp += (sp[1] == '=' ) ? 2:1;
tmpdir = sp;
contflag = 0;
break;
case 'd':
case 'u':
case 'D':
case 'U':
case 'v':
case 'V':
sprintf(tmp,"-%s",sp);
contflag = 0;
appendlist( &cppopt, tmp);
break;
case 'j':
case 'J':
jflag = 0;
break;
case 'I':
case 'i':
iflag = 0;
sprintf(tmp,"-l=%s/cio.l", libs);
appendlist( &lnopt, tmp);
break;
case 'x':
case 'X':
xflag = 0;
sprintf(tmp,"-l=%s/clib.l", libs);
appendlist( &lnopt, tmp);
break;
case 'p':
case 'P':
pipeflag = 1;
break;
case 'e':
case 'E':
case 'l':
case 'L':
case 'N':
case 'n':
case 'm':
case 'M':
sprintf(tmp,"-%s",sp);
contflag = 0;
appendlist( &lnopt, tmp);
break;
default:
usagehelp();
/* exits */
}
}
break;
default:
switch( filetype(sp) ) {
case 'a':
case 'o':
appendlist( &asdo, sp);
break;
case 'c':
appendlist( &ccdo, sp);
break;
default:
fprintf(stderr,"can't handle file: %s, giving to linker\n",sp);
case 'r':
appendlist( &lnopt, sp);
break;
}
files++;
break;
}
}
if( xflag)
appendlist( &ccopt, "-t");
if( linker > 0) {
if( jflag )
appendlist( &lnopt, "-a");
if( xflag) {
appendlist( &ccopt, "-t");
sprintf(tmp,"-l=%s/clibn.l", libs);
appendlist( &lnopt, tmp);
sprintf(tmp,"-l=%s/math.l", libs);
appendlist( &lnopt, tmp);
}
sprintf(tmp,"-l=%s/sys.l", libs);
appendlist( &lnopt, tmp);
}
if( files > 0 ) {
/*
* make room for filenames in the lists
*/
preplist( &cppopt);
preplist( &ccopt);
preplist( &optopt);
preplist( &asopt);
if( compiler > 0)
compile( &ccdo); /* assembles also and adds to lnopt-list */
if( assembler > 0 )
assemble( &asdo); /* adds to lnopt-list */
if( linker > 0 )
exit(dofork( lnopt.list,0 )); /* link */
} else mputs("No Files !!!!!!!!\n");
}
/*
* execute arg and if flag == 1, return with pid else
* wait until finished.
* if we receive a signal, send the signal to the running child too
* return exit-status of child
*/
int
dofork( arg, flag )
char **arg;
int flag;
{
extern char **environ;
int pid,status,i;
if( quietflag == 0) {
register char **sp;
/*
* show the arg-vector or the name of the executed programm
*/
if ( showflag ) {
for( sp= arg; *sp; sp++)
fprintf(stderr,"'%s' ", *sp);
fprintf(stderr,flag ? "|\n" : "\n");
} else
fprintf(stderr,"%s:\n", arg[0]);
}
if( (pid = os9exec(os9forkc, arg[0],arg,environ,0,0,3)) < 0 || flag)
return(pid);
while( pid != (i = wait(&status)))
if( i == 0)
kill(pid,sig_rec);
return(status);
}
/*
* compile a list of files to assembler or rel-files
*/
void
compile( filelist )
register struct optlist *filelist;
{
char **sp;
int i,j;
char newname[32];
char buffer[512];
char buffer2[512];
for(sp = filelist->list; *sp; sp++) {
register char *cp = rindex( *sp, '/');
if( cp != (char *)0)
cp++;
else
cp = *sp;
if( quietflag == 0)
fprintf(stderr,"\n'%s'\n", *sp);
(void) strcpy( newname, cp);
newname[ strlen(newname) -1] = 'a';
if( pipeflag ) {
int fd[5];
int pid[3];
/*
* save fd's of stdin/stdout and open a unnamend pipe
*/
fd[0] = dup(0);
fd[1] = dup(1);
if( (fd[2] = open("/pipe",3)) < 0)
exit(errno);
/*
* prepare cpp-arg-vector, because we are giving only a input-file-
* name the output of the cpp is going to stdout
*/
cppopt.list[cppopt.numel] = *sp;
cppopt.list[cppopt.numel+1] = (char *)0;
/*
* make the /pipe the stdout of the child and fork
*/
close(1);
dup(fd[2]);
if( (pid[0] = dofork( cppopt.list, 1)) < 0)
exit(errno);
/*
* restore out old stdout
*/
close(1);
dup( fd[1] );
/*
* setup the /pipe as stdin and prepare the output-path of
* the compiler (temp-file iff we are going to assemble)
*/
close(0);
dup( fd[2] );
if( assembler == 0 ) {
if( noopt == 0)
newname[ strlen(newname) -1] = 'o';
sprintf(buffer2,"-o=%s", newname);
} else
sprintf(buffer2,"-o=%s/nctmp%d.a", tmpdir, getpid());
/*
* by giving only one name to the compiler the input for the
* compiler is stdin
*/
if( noopt == 0) {
if( (fd[3] = open("/pipe",3)) < 0)
exit(errno);
if( (fd[4] = creat( buffer2+3, 3)) < 0)
exit(errno);
ccopt.list[ccopt.numel] = (char *)0;
close(1);
dup( fd[3] );
} else
ccopt.list[ccopt.numel] = buffer2;
ccopt.list[ccopt.numel+1] = (char *)0;
if( (pid[1] = dofork( ccopt.list,1)) < 0)
exit(errno);
/*
* restore out old stdin - also closing the /pipe
*/
if( noopt == 0) {
close(1);
dup( fd[1] );
}
close(0);
dup(fd[0]);
close(fd[2]);
if( noopt == 0) {
close(0);
dup( fd[3] );
close(1);
dup( fd[4] );
if( (pid[1] = dofork( optopt.list,1)) < 0)
exit(errno);
close(0);
dup(fd[0]);
close(1);
dup(fd[1]);
close( fd[3]);
close( fd[4]);
}
/*
* wait for signal or last process
*/
do {
i = wait(&pid[2]);
if( i == 0) {
kill(pid[0],sig_rec);
kill(pid[1],sig_rec);
unlink( buffer2+3);
exit(errno);
}
} while( i != pid[1]);
close(fd[0]);
close(fd[1]);
} else {
/*
* 'normal' compilation: put cpp-output to tempdir, fork
* and wait for completion
*/
sprintf(buffer,"-o=%s/nctmp%d.p", tmpdir, getpid());
cppopt.list[cppopt.numel] = *sp;
cppopt.list[cppopt.numel+1] = buffer;
if( (i=dofork(cppopt.list,0)) != 0) {
unlink( buffer+3 );
exit(i);
}
/*
* prepare input and output filenames for the compiler
* (temp-file iff we are going to assemble)
*/
ccopt.list[ccopt.numel] = buffer+3;
if( noopt && assembler == 0 )
sprintf(buffer2,"-o=%s", newname);
else {
sprintf(buffer2,"-o=%s/nctmp%d.a", tmpdir, getpid());
}
ccopt.list[ccopt.numel+1] = buffer2;
j=dofork(ccopt.list,0);
/*
* delete cpp-output and iff compiler failed, also the compiler
* output
*/
unlink(buffer+3);
if( j != 0) {
unlink(buffer2+3);
exit(j);
}
if( noopt == 0 ) {
newname[ strlen(newname) -1] = 'o';
strcpy( buffer, buffer2+3);
optopt.list[optopt.numel] = buffer;
if( assembler == 0)
sprintf(buffer2,"-o=%s", newname);
else
sprintf(buffer2,"-o=%s/nctmp%d.o", tmpdir, getpid());
optopt.list[optopt.numel+1] = buffer2+3;
j=dofork(optopt.list,0);
/*
* delete c68-output and iff o68 failed, also the output
*/
unlink(buffer);
if( j != 0) {
unlink(buffer2+3);
exit(j);
}
}
}
if( assembler > 0 ) {
/*
* assemble the output of the compiler/o68 (name in buffer2)
*/
newname[ strlen(newname) -1] = 'r';
sprintf(buffer,"-O=%s/%s",rdir, newname);
asopt.list[asopt.numel] = buffer2+3;
asopt.list[asopt.numel+1]= buffer;
i = dofork( asopt.list,0);
unlink( buffer2+3);
if( i != 0) {
unlink( buffer+3);
exit(i);
}
/*
* iff we are going link later, append output of assembler to
* linker-arg-vector
*/
if( linker > 0)
appendlist( &lnopt, buffer+3);
}
}
}
void
assemble( filelist )
register struct optlist *filelist;
{
char *rindex();
int i;
char **cp;
char newname[32];
char buffer[512];
/*
* The filelist contains only *.s files given as arguments to Newcc
*/
for(cp = filelist->list; *cp; cp++) {
register char *sp = rindex( *cp, '/');
if( sp != (char *)0)
sp++;
else
sp = *cp;
if( quietflag == 0)
fprintf(stderr,"\n'%s'\n", *cp);
(void) strcpy( newname, sp);
newname[ strlen(newname)-1] = 'r';
sprintf(buffer,"-O=%s/%s", rdir, newname);
asopt.list[asopt.numel] = *cp;
asopt.list[asopt.numel+1]= buffer;
i = dofork( asopt.list,0);
unlink( *cp);
if( i != 0) {
unlink( buffer+3);
exit(i);
}
/*
* iff we are going link later, append output of assembler to
* linker-arg-vector
*/
if( linker > 0)
appendlist( &lnopt, buffer+3);
}
}