BSD 3 release
[unix-history] / usr / src / cmd / cc.c
#
# include <stdio.h>
# include <ctype.h>
# include <signal.h>
/* C command */
# define SBSIZE 10000
# define MAXINC 10
# define MAXFIL 100
# define MAXLIB 100
# define MAXOPT 100
char tmp0[30];
char *tmp1;
char *tmp2;
char *tmp3;
char *tmp4;
char *tmp5;
char *outfile;
char *copy(),*setsuf();
# define CHSPACE 1000
char ts[CHSPACE+50];
char *tsa = ts;
char *tsp = ts;
char *av[50];
char *clist[MAXFIL];
char *llist[MAXLIB];
char *alist[20];
int Wflag;
int dflag;
int pflag;
int sflag;
int cflag;
int eflag;
int gflag;
int exflag;
int oflag;
int proflag;
int noflflag;
int exfail;
char *chpass ;
char *npassname ;
char pass0[40] = "/lib/ccom";
char pass2[20] = "/lib/c2";
char passp[20] = "/lib/cpp";
char *pref = "/lib/crt0.o";
main(argc, argv)
char *argv[]; {
char *t;
char *savetsp;
char *assource;
char **pv, *ptemp[MAXOPT], **pvt;
int nc, nl, i, j, c, f20, nxo, na;
int idexit();
i = nc = nl = f20 = nxo = 0;
pv = ptemp;
while(++i < argc) {
if(*argv[i] == '-') switch (argv[i][1]) {
default:
goto passa;
case 'S':
sflag++;
cflag++;
break;
case 'o':
if (++i < argc) {
char t;
outfile = argv[i];
if ((t=getsuf(outfile))=='c'||t=='o') {
error("Would overwrite %s", outfile);
exit(8);
}
}
break;
case 'O':
oflag++;
break;
case 'p':
proflag++;
break;
case 'g':
gflag++;
break;
case 'W': /* deprecated */
case 'w':
Wflag++;
break;
case 'E':
exflag++;
case 'P':
pflag++;
if (argv[i][1]=='P')
fprintf(stderr, "(Warning): -P option obsolete\n");
*pv++ = argv[i];
case 'c':
cflag++;
break;
case 'f':
noflflag++;
if (npassname || chpass)
error("-f overwrites earlier option",0);
npassname = "/lib/f";
chpass = "12";
break;
case '2':
if(argv[i][2] == '\0')
pref = "/lib/crt2.o";
else {
pref = "/lib/crt20.o";
f20 = 1;
}
break;
case 'D':
case 'I':
case 'U':
case 'C':
*pv++ = argv[i];
if (pv >= ptemp+MAXOPT)
{
error("Too many DIUC options", 0);
--pv;
}
break;
case 't':
if (chpass)
error("-t overwrites earlier option",0);
chpass = argv[i]+2;
if (chpass[0]==0)
chpass = "012p";
break;
case 'B':
if (npassname)
error("-B overwrites earlier option", 0);
npassname = argv[i]+2;
if (npassname[0]==0)
npassname = "/usr/c/o";
break;
case 'd':
dflag++;
strcpyn(alist, argv[i], 19);
break;
} else {
passa:
t = argv[i];
if((c=getsuf(t))=='c' || c=='s'|| exflag) {
clist[nc++] = t;
if (nc>=MAXFIL)
{
error("Too many source files",0);
exit(1);
}
t = setsuf(t, 'o');
}
if (nodup(llist, t)) {
llist[nl++] = t;
if (nl >= MAXLIB)
{
error("Too many object/library files",0);
exit(1);
}
if (getsuf(t)=='o')
nxo++;
}
}
}
if (gflag) oflag = 0;
if (npassname && chpass ==0)
chpass = "012p";
if (chpass && npassname==0)
npassname = "/usr/c/";
if (chpass)
for (t=chpass; *t; t++)
{
switch (*t)
{
case '0':
strcpy (pass0, npassname);
strcat (pass0, "ccom");
continue;
case '2':
strcpy (pass2, npassname);
strcat (pass2, "c2");
continue;
case 'p':
strcpy (passp, npassname);
strcat (passp, "cpp");
continue;
}
}
if (noflflag)
pref = proflag ? "/lib/fmcrt0.o" : "/lib/fcrt0.o";
else if (proflag)
pref = "/lib/mcrt0.o";
if(nc==0)
goto nocom;
if (pflag==0) {
FILE *c;
sprintf(tmp0,"/tmp/ctm%05.5da",getpid());
while((c=fopen(tmp0, "r")) != NULL) {
fclose(c);
tmp0[9]++;
}
while((creat(tmp0, 0400))<0)
tmp0[9]++;
}
if (signal(SIGINT, SIG_IGN) != SIG_IGN) /* interrupt */
signal(SIGINT, idexit);
if (signal(SIGTERM, SIG_IGN) != SIG_IGN) /* terminate */
signal(SIGTERM, idexit);
(tmp1 = copy(tmp0))[13] = '1';
(tmp2 = copy(tmp0))[13] = '2';
(tmp3 = copy(tmp0))[13] = '3';
if (oflag)
(tmp5 = copy(tmp0))[13] = '5';
if (pflag==0)
(tmp4 = copy(tmp0))[13] = '4';
pvt = pv;
for (i=0; i<nc; i++) {
if (nc>1) {
printf("%s:\n", clist[i]);
fflush(stdout);
}
if (getsuf(clist[i])=='s') {
assource = clist[i];
goto assemble;
} else
assource = tmp3;
if (pflag)
tmp4 = setsuf(clist[i], 'i');
savetsp = tsp;
av[0] = "cpp";
av[1] = clist[i];
av[2] = exflag ? "-" : tmp4;
na = 3;
for(pv=ptemp; pv <pvt; pv++)
av[na++] = *pv;
av[na++]=0;
if (callsys(passp, av))
{exfail++; eflag++;}
av[1] =tmp4;
tsp = savetsp;
av[0]= "ccom";
if (pflag || exfail)
{
cflag++;
continue;
}
if(sflag)
assource = tmp3 = setsuf(clist[i], 's');
av[2] = tmp3;
if(oflag)
av[2] = tmp5;
if (proflag) {
av[3] = "-XP";
av[4] = 0;
} else
av[3] = 0;
if (gflag) {
int i;
i = av[3] ? 4 : 3;
av[i++] = "-Xg";
av[i] = 0;
}
if (Wflag) {
int i;
for (i = 3; i < 10 && av[i] != 0; i++)
;
av[i] = "-W";
av[++i] = 0;
}
if (callsys(pass0, av)) {
cflag++;
eflag++;
continue;
}
if (oflag) {
av[0] = "c2";
av[1] = tmp5;
av[2] = tmp3;
av[3] = 0;
if (callsys(pass2, av)) {
unlink(tmp3);
tmp3 = assource = tmp5;
} else
unlink(tmp5);
}
if (sflag)
continue;
assemble:
av[0] = "as";
av[1] = "-o";
av[2] = setsuf(clist[i], 'o');
av[3] = assource;
if (dflag) {
av[4] = alist;
av[5] = 0;
} else
av[4] = 0;
cunlink(tmp1);
cunlink(tmp2);
cunlink(tmp4);
if (callsys("/bin/as", av) > 1) {
cflag++;
eflag++;
continue;
}
}
nocom:
if (cflag==0 && nl!=0) {
i = 0;
av[0] = "ld";
av[1] = "-X";
av[2] = pref;
j = 3;
if (outfile) {
av[j++] = "-o";
av[j++] = outfile;
}
while(i<nl)
av[j++] = llist[i++];
if (gflag)
av[j++] = "-lg";
if(f20)
av[j++] = "-l2";
else {
av[j++] = "/lib/libc.a";
av[j++] = "-l";
}
av[j++] = 0;
eflag |= callsys("/bin/ld", av);
if (nc==1 && nxo==1 && eflag==0)
cunlink(setsuf(clist[0], 'o'));
}
dexit();
}
idexit()
{
eflag = 100;
dexit();
}
dexit()
{
if (!pflag) {
cunlink(tmp1);
cunlink(tmp2);
if (sflag==0)
cunlink(tmp3);
cunlink(tmp4);
cunlink(tmp5);
cunlink(tmp0);
}
exit(eflag);
}
error(s, x)
{
fprintf(exflag?stderr:stdout , s, x);
putc('\n', exflag? stderr : stdout);
exfail++;
cflag++;
eflag++;
}
getsuf(as)
char as[];
{
register int c;
register char *s;
register int t;
s = as;
c = 0;
while(t = *s++)
if (t=='/')
c = 0;
else
c++;
s -= 3;
if (c<=14 && c>2 && *s++=='.')
return(*s);
return(0);
}
char *
setsuf(as, ch)
char as[];
{
register char *s, *s1;
s = s1 = copy(as);
while(*s)
if (*s++ == '/')
s1 = s;
s[-1] = ch;
return(s1);
}
callsys(f, v)
char f[], *v[]; {
int t, status;
if ((t=vfork())==0) {
execv(f, v);
printf("Can't find %s\n", f);
fflush(stdout);
_exit(100);
} else
if (t == -1) {
printf("Try again\n");
return(100);
}
while(t!=wait(&status));
if ((t=(status&0377)) != 0 && t!=14) {
if (t!=2) /* interrupt */
{
printf("Fatal error in %s\n", f);
eflag = 8;
}
dexit();
}
return((status>>8) & 0377);
}
char *
copy(as)
char as[];
{
register char *otsp, *s;
int i;
otsp = tsp;
s = as;
while(*tsp++ = *s++);
if (tsp >tsa+CHSPACE)
{
tsp = tsa = i = calloc(CHSPACE+50,1);
if (i== -1){
error("no space for file names");
dexit(8);
}
}
return(otsp);
}
nodup(l, os)
char **l, *os;
{
register char *t, *s;
register int c;
s = os;
if (getsuf(s) != 'o')
return(1);
while(t = *l++) {
while(c = *s++)
if (c != *t++)
break;
if (*t=='\0' && c=='\0')
return(0);
s = os;
}
return(1);
}
cunlink(f)
char *f;
{
if (f==0)
return(0);
return(unlink(f));
}