mirror of
https://github.com/PDP-10/PCC20.git
synced 2026-01-13 15:17:51 +00:00
343 lines
6.7 KiB
C
343 lines
6.7 KiB
C
# include "cc.h"
|
||
|
||
/*
|
||
|
||
C Compiler
|
||
Test C Compiler Command Routine (for CMAC Versions)
|
||
|
||
|
||
Command format:
|
||
|
||
cc {option ...} name1.c name2.c ...
|
||
|
||
Options:
|
||
|
||
d=xxx set compiler debugging argument to xxx
|
||
k= keep intermediate files around
|
||
s= produce listing of symbol table
|
||
|
||
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 process_options proopt
|
||
# define process_equal_option proeq
|
||
|
||
# define p_argc phsac
|
||
# define p_argv phsav
|
||
|
||
# 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
|
||
|
||
/* intermediate file names */
|
||
|
||
# define fncs "0.cstore"
|
||
# define fner "0.error"
|
||
# define fnhm "0.hmac"
|
||
# define fnma "0.mac"
|
||
# define fnno "0.node"
|
||
# define fnst "0.string"
|
||
# define fnsy "0.symtab"
|
||
# define fnto "0.token"
|
||
# define fnty "0.typtab"
|
||
|
||
/* options */
|
||
|
||
char debug[40];
|
||
int kflag, sflag;
|
||
|
||
/* phase information */
|
||
|
||
# define nphase 7
|
||
|
||
# define p_L 0
|
||
# define p_LP 1
|
||
# define p_P 2
|
||
# define p_C 3
|
||
# define p_M 4
|
||
# define p_E 5
|
||
# define p_S 6
|
||
|
||
char *p_name[] {"L", "LP", "P", "C", "M", "E", "S"};
|
||
char *p_prog[] {"/dsk/c/_l-cm.tbin",
|
||
"/dsk/c/_lp-cm.tbin",
|
||
"/dsk/c/_p-cm.tbin",
|
||
"/dsk/c/_c-cm.tbin",
|
||
"/dsk/c/_m-cm.tbin",
|
||
"/dsk/c/_e-cm.tbin",
|
||
"/dsk/c/_s-cm.tbin"};
|
||
|
||
char *argv_L[] {debug, 0, fnto, fncs, fner, fnst};
|
||
char *argv_LP[] {debug, 0, fnno, fnty, fner, fnma, fncs, fnst, fnhm, fnsy};
|
||
char *argv_P[] {debug, fnto, fnno, fnty, fner, fnma, fnhm, fnsy};
|
||
char *argv_C[] {debug, fner, fnno, fnty, fnma};
|
||
char *argv_M[] {debug, 0, fncs, fner, fnma, fnst, fnhm};
|
||
char *argv_E[] {debug, fner, fncs};
|
||
char *argv_S[] {fncs, fnty, fnsy, 0};
|
||
|
||
char *p_argc[] {6, 10, 8, 5, 7, 3, 4};
|
||
char **p_argv[] {argv_L, argv_LP, argv_P, argv_C, argv_M,
|
||
argv_E, argv_S};
|
||
|
||
# define file_name_size 30
|
||
|
||
/**********************************************************************
|
||
|
||
DESCRIPTION OF EXTERNAL-DEFINED ROUTINES USED
|
||
|
||
part of C compiler:
|
||
|
||
perror - error message processor (if CALL_ERROR config)
|
||
cprint - formatted output (c96.c)
|
||
|
||
standard C library:
|
||
|
||
copen - open file for input/output
|
||
cclose - close file
|
||
|
||
reasonably machine-independent:
|
||
|
||
execv - execute program passing vector of args
|
||
(status returned through exccode)
|
||
delete - delete file
|
||
apfname - append new suffix to file name
|
||
|
||
*/
|
||
|
||
/**********************************************************************
|
||
|
||
THE MAIN PROGRAM
|
||
|
||
**********************************************************************/
|
||
|
||
char *sconcat();
|
||
|
||
main (argc, argv) int argc; char *argv[];
|
||
|
||
{int snum, cc, f;
|
||
char *source;
|
||
char obj_name[file_name_size], sym_name[file_name_size];
|
||
|
||
--argc;
|
||
++argv;
|
||
argc = process_options (argc, argv);
|
||
for (snum = 0; snum < argc; ++snum)
|
||
{source = argv[snum];
|
||
|
||
/* check that source file exists */
|
||
|
||
if ((f = copen (source, MREAD, TEXT)) == OPENLOSS)
|
||
{cprint ("Can't Find '%s'.\n", source);
|
||
continue;
|
||
}
|
||
cclose (f);
|
||
|
||
cprint ("%s:\n", source);
|
||
|
||
/* fix debug arg */
|
||
|
||
if (sflag) sconcat (debug, 2, debug, "s");
|
||
|
||
/* construct output file names from source file name */
|
||
|
||
construct_output_file_names (source, obj_name, sym_name);
|
||
|
||
/* create empty ERROR file for phases to append to */
|
||
|
||
cclose (copen (fner, MWRITE, BINARY));
|
||
|
||
/* set the variable phase arguments */
|
||
|
||
argv_L[1] = source;
|
||
argv_LP[1] = source;
|
||
argv_M[1] = obj_name;
|
||
argv_S[3] = sym_name;
|
||
|
||
/* now execute the phases */
|
||
|
||
# ifdef MERGE_LP
|
||
|
||
cc = execute_phase (p_LP);
|
||
|
||
# endif
|
||
|
||
# ifndef MERGE_LP
|
||
|
||
cc = execute_phase (p_L);
|
||
if (!cc) cc = execute_phase (p_P);
|
||
|
||
# endif
|
||
|
||
if (!cc) cc = execute_phase (p_C);
|
||
if (!cc) cc = execute_phase (p_M);
|
||
|
||
# ifdef CALL_ERROR
|
||
|
||
perror (fner, fncs);
|
||
|
||
# endif
|
||
|
||
# ifndef CALL_ERROR
|
||
|
||
execute_phase (p_E);
|
||
|
||
# endif
|
||
|
||
if (sflag) execute_phase (p_S);
|
||
|
||
if (!kflag)
|
||
{delete (fnto);
|
||
delete (fncs);
|
||
delete (fner);
|
||
delete (fnno);
|
||
delete (fnsy);
|
||
delete (fnma);
|
||
delete (fnhm);
|
||
delete (fnst);
|
||
delete (fnty);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
|
||
PROCESS_OPTIONS - Process options in command arguments
|
||
and remove options from argument list.
|
||
|
||
**********************************************************************/
|
||
|
||
int process_options (argc, argv)
|
||
char *argv[];
|
||
|
||
{char *s, **ss, **dd;
|
||
int n, opt;
|
||
|
||
kflag = sflag = FALSE;
|
||
dd = ss = argv;
|
||
n = 0;
|
||
while (--argc >= 0)
|
||
{s = *ss++;
|
||
if ((opt = s[0]) && s[1] == '=')
|
||
process_equal_option (opt, s+2);
|
||
else
|
||
{*dd++ = s;
|
||
++n;
|
||
}
|
||
}
|
||
return (n);
|
||
}
|
||
|
||
/**********************************************************************
|
||
|
||
PROCESS_EQUAL_OPTION
|
||
|
||
**********************************************************************/
|
||
|
||
process_equal_option (opt, s)
|
||
char *s;
|
||
|
||
{char *r;
|
||
int c;
|
||
|
||
switch (opt = lower (opt)) {
|
||
case 'd': r = debug;
|
||
while (c = *s++) *r++ = lower (c);
|
||
*r = 0;
|
||
return;
|
||
case 'k': kflag = TRUE; return;
|
||
case 's': sflag = TRUE; return;
|
||
default: cprint ("Unrecognized option: %c=%s\n", opt, s);
|
||
}
|
||
}
|
||
|
||
/**********************************************************************
|
||
|
||
CONSTRUCT_OUTPUT_FILE_NAME
|
||
|
||
Construct output file names from source file name.
|
||
|
||
**********************************************************************/
|
||
|
||
construct_output_file_names (source, obj_name, sym_name)
|
||
char *source, *obj_name, *sym_name;
|
||
|
||
{apfname (obj_name, source, "MIDAS");
|
||
apfname (sym_name, source, "SYMTAB");
|
||
}
|
||
|
||
/**********************************************************************
|
||
|
||
EXECUTE PHASE
|
||
|
||
**********************************************************************/
|
||
|
||
int execute_phase (n) int n;
|
||
|
||
{extern int exccode; /* set by execv to phase return code */
|
||
int c;
|
||
char *s;
|
||
|
||
if (execv (p_prog[n], p_argc[n], p_argv[n]))
|
||
{cprint ("Unable to execute phase %s\n", p_name[n]);
|
||
return (-1);
|
||
}
|
||
s = p_name[n];
|
||
while (c = *s++) cprint ("%c\n", c);
|
||
return (exccode);
|
||
}
|
||
|
||
/**********************************************************************
|
||
|
||
LOWER - Convert Character To Lower Case
|
||
|
||
**********************************************************************/
|
||
|
||
int lower (c)
|
||
|
||
{if (c >= 'A' && c <= 'Z') c =+ ('a' - 'A');
|
||
return (c);
|
||
}
|
||
|
||
/**********************************************************************
|
||
|
||
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);
|
||
}
|
||
|
||
|