/* Z editor options :ma=1 :ts=6 :bk=0 :wm=0 */ /* This program, both executable and sources, are Copyright 1986, Jay Ts, Box 890 West Oneonta NY 13861. You may copy, distribute, alter, and use them, but absolutely no permission is granted to remove copyright notices from them or distribute them, in whole or in part, as, or as part of, a commercial product. */ /* put copyright notice in executable */ char copyright_message[] = "\nCopyright 1986, Jay Ts\n"; #include "stdio.h" #define isdigit(x) ((x) >= '0' && (x) <= '9' ? 1 : 0) /* add option to string of options */ #define addopt(x,opt) \ { \ strcat((x)," "); \ strcat((x),(opt)); \ strcat((x)," "); \ } extern char *getenv(), *mktemp(); extern int geterrs(); char pname[32]; /* the name of the final output file */ char tfile[32]; /* temp file defined by CCTEMP environment variable */ char errfile[32]; /* file to which error messages are written */ char cli[256]; /* CLI command string */ char ccopts[128]; /* strings of options for each phase */ char asopts[128]; char lnopts[128]; /* lists of source file names, and number of files in each list */ #define MFIL 32 char cfiles[MFIL][32], afiles[MFIL][32], lfiles[MFIL][32]; int numcfiles = 0, numafiles = 0, numlfiles = 0; /* flags */ int dontlink = 0; /* don't link, just leave .o file in current directory */ int printonly = 0; /* print what is to be done, but don't do it */ int lintflag = 0; /* allow compiler to print warning messages, then quit */ int zdefined = 0; /* -z option has been defined on command line */ int edefined = 0; /* -e option has been defined on command line */ main(argc,argv) int argc; char *argv[]; { int i, l; char *s; if(argc < 2) { printf("usage: cc [-opts] { Csrc.c | Asrc.a | objfile.o }\n"); exit(0); } if(argv[1][0] == '?') /* standard AmigaDOS help query: cc ? */ { if( ! getenv("DOC")) { printf("cc: can't help, DOC environment variable not set\n"); exit(0); } else { strcpy(cli,"more <* >* "); strcat(cli,getenv("DOC")); strcat(cli,"cc.doc"); Execute(cli,0L,0L); exit(0); } } /* make sure environment variables are set */ if( ! getenv("ML")) printf("environment variable ML unset\n"); if( ! getenv("CLIB")) printf("environment variable CLIB unset\n"); if( ! getenv("CCTEMP")) printf("environment variable CCTEMP unset\n"); if( ! getenv("INCLUDE")) printf("environment variable INCLUDE unset\n"); /* set up temporary file for error output */ strcpy(tfile, getenv("CCTEMP")); strcpy(errfile,tfile); strcat(errfile,"ccom_XXXX"); if(mktemp(errfile) != errfile) { printf("cc: mktemp() failed\n"); exit(1); } /* initialize options strings for three stages */ strcpy(ccopts, " -B -i"); strcat(ccopts, getenv("INCLUDE")); strcat(ccopts, "/manx "); strcpy(asopts, ""); strcpy(lnopts, ""); /* Process arguments for this program. They are either options or file names. Note that these are case sensitive for T/t C/c and F/f options. */ for(i = 1; i < argc; i++) { Chk_Abort(); if(argv[i][0] == '-' || argv[i][0] == '+') /* an option */ { s = argv[i]; switch(s[1]) { case 'p': case 'P': printonly = 1; break; case 'v': case 'V': addopt(lnopts,s); addopt(asopts,s); break; case 'i': case 'I': if(s[0] == '-') addopt(asopts,s); addopt(ccopts,s); break; case 'c': /* Lower case only! */ if(s[0] == '-') dontlink = 1; else { addopt(ccopts,s); s[0] = '-'; addopt(asopts,s); } break; case 'd': case 'D': if(s[0] == '-') addopt(ccopts,s) else { addopt(ccopts,s); s[0] = '-'; addopt(asopts,s); } break; case 's': case 'S': if(strlen(s) == 2) { dontlink = lintflag = 1; addopt(ccopts,"-a"); } else addopt(asopts,s); break; case 'e': case 'E': if(isdigit(s[2])) { edefined = 1; addopt(ccopts,s) } else addopt(asopts,s); break; case 'l': case 'L': if(s[0] == '+' || s[0] == '-' && isdigit(s[2])) addopt(ccopts,s) else if(strlen(s) < 3) addopt(asopts,s) else { addopt(lnopts,s); addlibopt(&s[2]); } break; case 'z': case 'Z': if(isdigit(s[2])) { zdefined = 1; addopt(ccopts,s); } else addopt(asopts,s); break; case 'a': case 'A': case 'h': case 'H': dontlink = 1; case 't': /* Lower case only! */ case 'y': case 'Y': case 'b': case 'B': case 'q': case 'Q': addopt(ccopts,s); break; case 'n': case 'N': addopt(asopts,s); break; case 'T': /* Upper case only! */ case 'w': case 'W': addopt(lnopts,s); break; case 'f': /* Lower case only! */ addopt(lnopts,s); s = argv[++i]; addopt(lnopts,s); break; case 'O': case 'o': case 'C': /* Upper case only! */ case 'F': /* Upper case only! */ addopt(lnopts,s); break; default: printf("bad option: \"%s\"\n", argv[i]); exit(1); break; } } else /* a file -- add to appropriate list */ { l = strlen(argv[i]); if(argv[i][l-2] == '.') { /* The first file in the argument list is special -- the output of the linker is named after it. This name is held in the string pname. */ switch(argv[i][l-1]) { case 'c': if(!numcfiles && !numafiles && !numlfiles) strncpy(pname,argv[i],l-2); if(numcfiles == MFIL) toomany(".c"); strncpy(cfiles[numcfiles],argv[i],l-2); ++numcfiles; break; case 'a': if(!numcfiles && !numafiles && !numlfiles) strncpy(pname,argv[i],l-2); if(numafiles == MFIL) toomany(".a"); strncpy(afiles[numafiles],argv[i],l-2); ++numafiles; break; case 'o': if(!numcfiles && !numafiles && !numlfiles) strncpy(pname,argv[i],l-2); if(numlfiles == MFIL) toomany(".o"); strncpy(lfiles[numlfiles],argv[i],l-2); ++numlfiles; break; default: printf("not a .[cao] file: \"%s\"\n", argv[i]); exit(1); break; } } else { printf("cc: not a .[cao] file: \"%s\"\n", argv[i]); exit(1); } } } if(!numcfiles && !numafiles && !numlfiles) { printf("cc: no files to compile, assemble or link\n"); exit(1); } /* the below are default options which were found to be useful */ if( ! zdefined) strcat(ccopts, " -z4000 "); /* larger string table */ if( ! edefined) strcat(ccopts, " -e200 "); /* larger expr space */ if( ! lintflag) strcat(ccopts, " -s "); /* don't print warnings */ /* run compilation stage: compile .c files into .o files */ for(i = 0; i < numcfiles; ++i) /* do for each .c file on command line */ { strcpy(cli,"c:"); /* build command string */ strcat(cli,"ccom >"); /* COMPILER */ strcat(cli,errfile); /* add error redirection */ strcat(cli,ccopts); /* add options */ if( ! dontlink || lintflag) /* add output file name */ { strcat(cli," -o "); strcat(cli,tfile); strcat(cli,cfiles[i]); strcat(cli,".o "); } strcat(cli,cfiles[i]); /* add .c source file name */ strcat(cli,".c"); if(printonly) printf("%s\n",cli); else { Chk_Abort(); Execute(cli,0L,0L); if(geterrs()) cleanup(20); } } /* assembly stage: assemble files on command line ending with ".a" */ for(i = 0; i < numafiles; i++) { strcpy(cli,"c:"); /* build command string */ strcat(cli,"as >"); /* ASSEMBLER */ strcat(cli,errfile); /* redirect output */ strcat(cli,asopts); /* add options */ if( ! dontlink) /* add output name */ { strcat(cli," -o "); strcat(cli,tfile); strcat(cli,afiles[i]); strcat(cli,".o "); } strcat(cli,afiles[i]); /* add source file name */ strcat(cli,".a"); if(printonly) printf("%s\n",cli); else { Chk_Abort(); Execute(cli,0L,0L); if(geterrs()) cleanup(20); } } /* LINK */ if( ! dontlink ) { addlibopt("c"); /* by default, always load with c.lib */ strcpy(cli,"c:"); /* build CLI command string */ strcat(cli,"ln >"); /* LINKER */ strcat(cli,errfile); /* add error redirection */ for(i = 0; i < numcfiles; i++) /* add .o files from .c compile */ { strcat(cli, " "); strcat(cli, tfile); strcat(cli, cfiles[i]); strcat(cli, ".o"); } for(i = 0; i < numafiles; i++) /* add .o files from .a assembly */ { strcat(cli, " "); strcat(cli, tfile); strcat(cli, afiles[i]); strcat(cli, ".o"); } for(i = 0; i < numlfiles; i++) /* add .o files from arg. list */ { strcat(cli, " "); strcat(cli, lfiles[i]); strcat(cli, ".o"); } strcat(cli, " -o "); /* name output file named by first ... */ strcat(cli, pname); /* ... source file listed in arguments */ strcat(cli, lnopts); /* add options */ strcat(cli, " -lc"); /* always link with std. C library */ if(printonly) printf("%s\n",cli); else { Chk_Abort(); Execute(cli,0L,0L); geterrs(); } } cleanup(0); } cleanup(rval) int rval; { int i; char delcom[32]; /* delete object files in CCTEMP that were made by compile */ if( ! dontlink || lintflag) for(i = 0; i < numcfiles; i++) { strcpy(delcom,tfile); strcat(delcom,cfiles[i]); strcat(delcom,".o"); if(printonly) printf("delete %s\n",delcom); DeleteFile(delcom); } /* delete object files in CCTEMP that were made by assembly */ if( ! dontlink) for(i = 0; i < numafiles; i++) { strcpy(delcom,tfile); strcat(delcom,afiles[i]); strcat(delcom,".o"); if(printonly) printf("delete %s\n",delcom); DeleteFile(delcom); } /* delete intermediate error file */ DeleteFile(errfile); exit(rval); } /* copy library file from ML into CLIB, if it's not already there */ addlibopt(s) char *s; { char libname[32], envlibname[64], srclibname[64], cpycom[64]; strcpy(libname, s); strcat(libname, ".lib"); strcpy(srclibname,getenv("ML")); strcat(srclibname, libname); strcpy(envlibname, getenv("CLIB")); strcat(envlibname, libname); if(access(envlibname,0)) { strcpy(cpycom, "copy "); strcat(cpycom, srclibname); strcat(cpycom, " "); strcat(cpycom, envlibname); if(printonly) printf("%s\n",cpycom); else Execute(cpycom,0L,0L); } } toomany(s) char *s; { printf("cc: can't handle more than %d ",MFIL); printf("%s files\n",s); exit(10); }