# include "c.defs" # define MERGE_LP 1 # define CALL_ERROR 1 /* C Compiler Command Routine Host machine: PDP-10 TOPS-20 Compiler Options -c compile only -g do not delete MIDAS file -k do not delete intermediate files -s produce symbol table listing -x syntax check or symbol table listing only -b for compiling big functions m=xxx compile code for machine xxx t=abc run TEST versions of phases a, b, c o=abc run OLD versions of phases a, b, c n=abc run NORMAL versions of phases a, b, c d=xxx set compiler debugging argument to xxx Meaningful debugging arguments: a debug code generator d debug parser e debug parser error recovery m debug macro expander */ /* renamings to allow long names */ # define construct_output_file_names cnsofn # define execute_phase execph # define set_program_name setpn # define set_target settrg # define write_statistics wrstat # define print_phase_time prphtm # define perform_assembly perasm # define process_options proopt # define process_minus_option promin # define process_equal_option proeq # define phase_name phsnm # define phase_prog phspr # define phase_argc phsac # define phase_argv phsav # define phase_option phsop # define phase_et phset # define phase_pt phspt # define argv_L avl # define argv_LP avlp # define argv_P avp # define argv_C avc # define argv_M avm # define argv_E ave # define argv_S avs # define target_name tarnam # define target_suffix tarsfx # define target_LP_data tarlpd # define target_obj tarobj /* intermediate file names */ # define fncs "0.cs;t" # define fner "0.er;t" # define fnhm "0.hm;t" # define fnma "0.ma;t" # define fnno "0.no;t" # define fnst "0.st;t" # define fnsy "0.sy;t" # define fnto "0.to;t" # define fnty "0.ty;t" /* program file names */ # define normal_prefix "c20" # define old_prefix "c20" # define test_prefix "c20" # define normal_suffix ".exe" # define old_suffix ".oexe" # define test_suffix ".exe" # define pdp10_suffix "" # define pdp11_suffix "11" # define his6000_suffix "60" # define ibm360_suffix "360" # define cmac_suffix "-cm" # define unix_suffix "-ux" # define new10_suffix "-10" # define file_name_size 100 /* options */ char debug[40]; char idebug[40]; int kflag, cflag, gflag, xflag, bflag, sflag; /* phase information */ # define nphase 7 # define phase_L 0 # define phase_LP 1 # define phase_P 2 # define phase_C 3 # define phase_M 4 # define phase_E 5 # define phase_S 6 # define ARGC_LP 10 /* arg counts without optional args */ # define ARGC_P 8 # define ARGC_C 6 char *argv_L[] {debug, 0, fnto, fncs, fner, fnst}; char *argv_LP[] {debug, 0, fnno, fnty, fner, fnma, fncs, fnst, fnhm, fnsy, 0}; char *argv_P[] {debug, fnto, fnno, fnty, fner, fnma, fnhm, fnsy, 0}; char *argv_C[] {debug, fner, fnno, fnty, fnma, "3000"}; char *argv_M[] {debug, 0, fncs, fner, fnma, fnst, fnhm}; char *argv_E[] {debug, fner, fncs}; char *argv_S[] {fncs, fnty, fnsy, 0}; char *phase_name[] {"L", "LP", "P", "C", "M", "E", "S"}; char phase_prog[nphase][file_name_size]; char *phase_argc[] {6, ARGC_LP, ARGC_P, ARGC_C, 7, 3, 4}; char **phase_argv[] {argv_L, argv_LP, argv_P, argv_C, argv_M, argv_E, argv_S}; int phase_option[] {'n', 'n', 'n', 'n', 'n', 'n', 'n'}; int phase_et[] {0, 0, 0, 0, 0, 0, 0}; int phase_pt[] {0, 0, 0, 0, 0, 0, 0}; /* target machine information */ # define n_target 7 # define pdp10 0 # define pdp11 1 # define his6000 2 # define ibm360 3 # define cmac 4 # define unix 5 # define new10 6 int target pdp10; char *target_name[] { "pdp10", "pdp11", "his6000", "ibm360", "cmac", "unix", "new10" }; char *target_suffix[] { pdp10_suffix, pdp11_suffix, his6000_suffix, ibm360_suffix, cmac_suffix, unix_suffix, new10_suffix }; char *target_LP_data[] { "", "", "", "", "", "", "" }; char *target_obj[] { "mid", "PALX", "GMAP", "BAL", "CMAC", "UNIX", "NMIDAS" }; /********************************************************************** DESCRIPTION OF EXTERNALLY DEFINED ROUTINES part of C compiler: perror - error message processor standard C library: copen - open file for input/output cprint - formatted output cputc - output character cclose - close file istty - is file a terminal? file name routines: file name = fnsfd - set parts of file name fngdr - get directory part of file name fngnm - get "name" part of file name reasonably machine-independent: stcpy - copy string stcmp - compare strings lower - convert char to lower case execv - execute program passing vector of args execs - execute program passing string command line delete - delete file now - get current date and time prcal - print date and time pr60th - print time given in 1/60 second units etime - return an elapsed time in 1/60 sec units */ char *sconcat(); /********************************************************************** THE MAIN PROGRAM **********************************************************************/ main (argc, argv) int argc; char *argv[]; {extern int cout; int snum, cc, f, i, ttyflag; cal start_time; char *s, *source, *fargv[50], buffer[2000]; char obj_name[file_name_size], rel_name[file_name_size], sym_name[file_name_size]; --argc; ++argv; argc = process_options (argc, argv); argc = exparg (argc, argv, fargv, buffer); argv = fargv; # ifdef MERGE_LP s = target_LP_data[target]; if (*s) {phase_argc[phase_LP] = ARGC_LP+1; argv_LP[ARGC_LP] = s; } else phase_argc[phase_LP] = ARGC_LP; # endif # ifndef MERGE_LP s = target_LP_data[target]; if (*s) {phase_argc[phase_P] = ARGC_P+1; argv_P[ARGC_P] = s; } else phase_argc[phase_P] = ARGC_P; # endif ttyflag = istty (cout); for (snum = 0; snum < argc; ++snum) {source = argv[snum]; /* check that source file exists */ if ((f = copen (source, 'r')) == OPENLOSS) {cprint ("Can't Find '%s'.\n", source); continue; } cclose (f); if (!ttyflag || argc>1) cprint ("%s:\n", source); now (&start_time); /* fix debug arg */ if (sflag) sconcat (debug, 2, idebug, "s"); else if (xflag) sconcat (debug, 2, idebug, "x"); else stcpy (idebug, debug); /* construct output file names from source file name */ construct_output_file_names (source, obj_name, rel_name, sym_name); cclose (copen (fner, 'w', "b")); for (i=0;i= 0) {s = *ss++; if (s[0] == '-') process_minus_option (s+1); else if ((opt = s[0]) && s[1] == '=') process_equal_option (opt, s+2); else {*dd++ = s; ++n; } } return (n); } /********************************************************************** PROCESS_MINUS_OPTION **********************************************************************/ process_minus_option (s) char *s; {int c; while (c = *s) {*s++ = c = lower (c); switch (c) { case 'k': kflag = TRUE; break; case 'c': cflag = TRUE; break; case 'g': gflag = TRUE; break; case 's': sflag = TRUE; break; case 'x': xflag = TRUE; break; case 'b': bflag = TRUE; argv_C[5] = "10000"; break; default: cprint ("Unrecognized option: -%c\n", c); break; } } } /********************************************************************** PROCESS_EQUAL_OPTION **********************************************************************/ process_equal_option (opt, s) char *s; {char *r; int c; switch (opt = lower (opt)) { case 'd': r = idebug; while (c = *s++) *r++ = lower (c); *r = 0; return; case 'n': case 'o': case 't': while (c = *s++) set_phase_option (c, opt); return; case 'm': set_target (s); return; default: cprint ("Unrecognized option: %c=%s\n", opt, s); } } /********************************************************************** CONSTRUCT_OUTPUT_FILE_NAMES Construct assembler, relocatable, and symbol table listing file names from source file name. **********************************************************************/ construct_output_file_names (source, obj_name, rel_name, sym_name) char *source, *obj_name, *rel_name; {fnsfd (obj_name, source, "", 0, 0, target_obj[target], 0, 0); fnsfd (rel_name, obj_name, 0, 0, 0, "stk", 0, 0); fnsfd (sym_name, obj_name, 0, 0, 0, "symtab", 0, 0); } /********************************************************************** EXECUTE PHASE **********************************************************************/ execute_phase (n) int n; {extern int exctime, exccode; int t; set_program_name (n); t = etime (); if (execv (phase_prog[n], phase_argc[n], phase_argv[n])) {cprint ("Unable to execute phase %s\n", phase_name[n]); return (-1); } phase_et[n] = etime () - t; phase_pt[n] = exctime; return (exccode); } /********************************************************************** SET_PHASE_OPTION Set phase option for phase PC to be OC. **********************************************************************/ set_phase_option (pc, oc) {int n; pc = lower (pc); switch (pc) { # ifdef MERGE_LP case 'l': case 'p': n = phase_LP; break; # endif # ifndef MERGE_LP case 'l': n = phase_L; break; case 'p': n = phase_P; break; # endif case 'c': n = phase_C; break; case 'm': n = phase_M; break; case 'e': n = phase_E; break; case 's': n = phase_S; break; default: cprint ("Unrecognized Phase Designation: %c\n", pc); return; } phase_option[n] = lower (oc); } /********************************************************************** SET_PROGRAM_NAME Construct the file name of program for the given phase. **********************************************************************/ set_program_name (n) int n; {char *r, *s, *t; switch (phase_option[n]) { case 'o': r = old_prefix; s = old_suffix; break; case 't': r = test_prefix; s = test_suffix; break; default: cprint ("Unrecognized Phase Option: %c\n", phase_option[n]); case 'n': r = normal_prefix; s = normal_suffix; break; } t = target_suffix[target]; if (n == phase_E || n == phase_S) t = ""; sconcat (phase_prog[n], 4, r, phase_name[n], t, s); } /********************************************************************** SET_TARGET - Set Target Machine **********************************************************************/ set_target (s) char *s; {int c, i; char *p; p = s; while (c = *p) *p++ = lower (c); for (i=0; ic.stat", 'a'); if (f == OPENLOSS) f = copen ("c.stat", 'a'); if (f == OPENLOSS) return; cputc ('\n', f); cprint (f, "%s - ", username ()); prcal (st, f); cprint (f, " - "); fngdr (source, temp); if (temp[0]) {slower (temp); cprint (f, "%s/", temp); } fngnm (source, temp); slower (temp); cprint (f, "%s", temp); # define hackery if (flag) {cprint (f, " ("); flag=FALSE;} else cputc (' ', f) if (cflag || gflag || kflag || xflag || bflag || sflag) {hackery; if (cflag) cputc ('c', f); if (gflag) cputc ('g', f); if (kflag) cputc ('k', f); if (xflag) cputc ('x', f); if (bflag) cputc ('b', f); if (sflag) cputc ('s', f); } if (*idebug) {hackery; cprint (f, "d=%s", idebug); } if (target) {hackery; cprint (f, "m=%s", target_name[target]); } if (!flag) cputc (')', f); cprint (f, "\n\n"); for (i=0;i+ '\t' */ {register int c; while ((c = cgetc (f)) > 0) {if (c == '-') {c = cgetc (f); if (!digit (c)) continue; while (digit (c)) c = cgetc (f); if (c != '\t') continue; cprint ("Assembler Errors.\n"); cclose (f); return (TRUE); } } cclose (f); delete (temp); } return (FALSE); } int digit (c) {return (c>='0' && c<='9');} /********************************************************************** SCONCAT - String Concatenate concatenate strings S1 ... Sn into buffer B return B **********************************************************************/ char *sconcat (b, n, s1, s2, s3, s4, s5, s6, s7, s8) char *b, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8; {char **s, *p, *q; int c; q = b; s = &s1; while (--n >= 0) {p = *s++; while (c = *p++) *q++ = c; } *q = 0; return (b); } /********************************************************************** SLOWER - Convert String To Lower Case **********************************************************************/ slower (s) char *s; {int c; while (c = *s) *s++ = lower (c); }