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