This commit is contained in:
ceriel
1991-11-13 16:53:49 +00:00
parent 881240fb3c
commit de620e1fd5
14 changed files with 1522 additions and 0 deletions

3
fcc/driver/.distr Normal file
View File

@@ -0,0 +1,3 @@
fcc.1
fcc.c
proto.make

148
fcc/driver/fcc.1 Normal file
View File

@@ -0,0 +1,148 @@
.TH FCC 1
.SH NAME
fcc \- fast CC-compatible C compiler
.SH SYNOPSIS
.B fcc
[
.B \-c
]
[
.B \-v
]
[
.B \-vn
]
[ \fB\-D\fIname\fR ]
[ \fB\-D\fIname\fB=\fIdef\fR ]
[
.BI \-I pathname
]
[
.B \-w
]
[
.B \-o
.I outfile
]
[
.B \-R
]
[
.BI \-U name
]
[
.BI -M compiler
]
.I sourcefile ...
.SH DESCRIPTION
.LP
.I Fcc
is a fast
.B C
compiler. It translates
.B C
programs
into cc(1)-compatible relocatable object modules, and does so in one pass.
Then, if the \fB\-c\fP flag is not given,
.I fcc
offers the object modules to a link-editor,
to create an executable binary.
.LP
.I Fcc
accepts several types of filename arguments. Files with
names ending in
.B .c
are taken to be
.B C
source programs.
They are compiled, and the resulting object module is placed in the current
directory.
The object module is named after its source file, the suffix
.B .o
replacing
.BR .c
in the name of the object.
.LP
Other arguments refer to loader options,
object modules, or object libraries.
Unless the
.B \-c
flag is given, these modules and libraries, together with the results of any
specified compilations, are passed (in the order given) to the
link-editor to produce
an output file named
.IR a.out .
You can specify a name for the executable by using the
.B \-o
option.
.SH OPTIONS
.LP
The \fB\-l\fIlib\fR, \fB\-n\fP, \fB\-N\fP,
\fB\-r\fP, \fB\-s\fP, \fB\-S\fP, and \fB\-u\fP options are
passed to the link-editor program.
The \fB\-u\fP option takes an extra argument.
.IP \fB\-c\fP
.br
Suppress the loading phase of the compilation, and force an object module to
be produced, even if only one program is compiled.
A single object module can be named explicitly using the
.B \-o
option.
.IP \fB\-D\fIname\fR\fB=\fIdef\fR
Define a symbol
.I name
to the
preprocessor, as if by "#define".
.IP \fB\-D\fIname\fR
.br
same as \fB\-D\fIname\fB=1\fR.
.IP \fB\-I\fIpathname\fR
.br
Add
.I pathname
to the list of directories in which to search for
.B #include
files with filenames not beginning with slash.
The compiler first searches for
.B #include
files in the directory containing
.I sourcefile,
then in directories in
.B \-I
options, and finally, in
.I /usr/include.
.IP "\fB\-o \fIoutput\fR"
Name the final output file
.I output.
.IP \fB\-U\fIname\fR
.br
Remove any initial definition of
.I name.
.IP \fB\-v\fP
.br
Verbose. Print the commands as they are executed.
.IP \fB\-vn\fP
.br
Verbose, no execute. Only print the commands, do not execute them.
.IP \fB\-w\fP
suppress warning messages.
.IP \fB\-R\fP
.br
test for more compatibility with Kernighan & Ritchie C [1].
.IP \fB\-M\fIcompiler\fR
.br
use \fIcompiler\fR as C-2 compiler instead of the default.
.LP
Object modules produced by cc(1) and
.I fcc
can be freely mixed, as long as the link-editor is called through
.I fcc.
.SH "SEE ALSO"
.IP [1]
B.W. Kernighan, D. Ritchie, "\fIThe C programming Language\fP", Prentice-Hall Inc., 1978
.IP [2]
E.H. Baalbergen, "\fIThe ACK CEM compiler\fP".
.IP [3]
cc(1) unix manual page.
.SH DIAGNOSTICS
Diagnostics are intended to be self-explanatory.

640
fcc/driver/fcc.c Normal file
View File

@@ -0,0 +1,640 @@
/* fcc
Driver for fast cc-compatible ACK C compiler.
Derived from the C compiler driver from Minix.
Compile this file with
cc -O -I<EM home dir>/config driver.c
Install the resulting binaries in the EM bin directory.
Suggested name: fcc
*/
#ifdef sun3
#define MACHNAME "m68020"
#define SYSNAME "sun3"
#endif
#ifdef vax4
#define MACHNAME "vax4"
#define SYSNAME "vax4"
#endif
#include <errno.h>
#include <signal.h>
#include <varargs.h>
#include <stdio.h>
#include <em_path.h>
/*
Version producing cc-compatible .o files in one pass.
*/
#define MAXARGC 256 /* maximum number of arguments allowed in a list */
#define USTR_SIZE 128 /* maximum length of string variable */
typedef char USTRING[USTR_SIZE];
struct arglist {
int al_argc;
char *al_argv[MAXARGC];
};
#define CPP_NAME "$H/lib.bin/cpp"
#define LD_NAME "/bin/ld"
#define AS_NAME "/bin/as"
#define SHELL "/bin/sh"
char *CPP;
char *COMP;
int kids = -1;
int ecount = 0;
struct arglist CPP_FLAGS = {
7,
{
"-Dunix",
"-D_EM_WSIZE=4",
"-D_EM_PSIZE=4",
"-D_EM_SSIZE=2",
"-D_EM_LSIZE=4",
"-D_EM_FSIZE=4",
"-D_EM_DSIZE=8",
}
};
struct arglist LD_HEAD = {
#ifdef sun3
8,
{
"-dc",
"-dp",
"-e",
"start",
"-X",
"-L/usr/lib/fsoft",
"/usr/lib/crt0.o",
"/usr/lib/Fcrt1.o"
}
#endif
#ifdef vax4
2,
{
"-X",
"/lib/crt0.o"
}
#endif
};
struct arglist LD_TAIL = {
2,
{
"$H/lib/$S/tail_ext",
"-lc"
}
};
struct arglist LD_FLAGS;
struct arglist COMP_FLAGS;
char *o_FILE = "a.out"; /* default name for executable file */
#define remove(str) ((noexec || unlink(str)), (str)[0] = '\0')
#define cleanup(str) (str && str[0] && remove(str))
#define init(al) ((al)->al_argc = 1)
char ProgCall[128];
struct arglist SRCFILES;
struct arglist LDFILES;
int RET_CODE = 0;
struct arglist CALL_VEC;
int o_flag = 0;
int c_flag = 0;
int v_flag = 0;
int O_flag = 0;
char *mkstr();
char *malloc();
char *alloc();
char *extension();
char *expand_string();
USTRING ofile;
USTRING BASE;
USTRING tmp_file;
int noexec = 0;
extern char *strcat(), *strcpy(), *mktemp(), *strchr();
trapcc(sig)
int sig;
{
signal(sig, SIG_IGN);
if (kids != -1) kill(kids, sig);
cleanup(ofile);
cleanup(tmp_file);
exit(1);
}
#define lang_suffix() "c"
#define comp_name() "$H/lib.bin/c_cccompat"
int
lang_opt(str)
char *str;
{
switch(str[1]) {
case '-': /* debug options */
case 'R': /* strict K&R */
case 'w': /* disable warnings */
append(&COMP_FLAGS, str);
return 1;
}
return 0;
}
main(argc, argv)
char *argv[];
{
char *str;
char **argvec;
int count;
char *ext;
register struct arglist *call = &CALL_VEC;
char *file;
char *ldfile;
int compile_cnt = 0;
setbuf(stdout, (char *) 0);
basename(*argv++,ProgCall);
COMP = expand_string(comp_name());
CPP = expand_string(CPP_NAME);
#ifdef vax4
append(&CPP_FLAGS, "-Dvax");
#endif
#ifdef sun3
append(&CPP_FLAGS, "-Dsun");
append(&CPP_FLAGS, "-Dmc68020");
append(&CPP_FLAGS, "-Dmc68000");
#endif
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, trapcc);
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, trapcc);
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
signal(SIGQUIT, trapcc);
while (--argc > 0) {
if (*(str = *argv++) != '-') {
append(&SRCFILES, str);
continue;
}
if (lang_opt(str)) {
}
else switch (str[1]) {
case 'c': /* stop after producing .o files */
c_flag = 1;
break;
case 'D': /* preprocessor #define */
case 'U': /* preprocessor #undef */
append(&CPP_FLAGS, str);
break;
case 'I': /* include directory */
append(&CPP_FLAGS, str);
break;
case 'g': /* debugger support */
append(&COMP_FLAGS, str);
break;
case 'o': /* target file */
if (argc-- >= 0) {
o_flag = 1;
o_FILE = *argv++;
ext = extension(o_FILE);
if (ext != o_FILE && ! strcmp(ext, lang_suffix())
) {
error("-o would overwrite %s", o_FILE);
}
}
break;
case 'u': /* mark identifier as undefined */
append(&LD_FLAGS, str);
if (argc-- >= 0)
append(&LD_FLAGS, *argv++);
break;
case 'O': /* use built in peephole optimizer */
O_flag = 1;
break;
case 'v': /* verbose */
v_flag++;
if (str[2] == 'n')
noexec = 1;
break;
case 'l': /* library file */
append(&SRCFILES, str);
break;
case 't': /* -target? */
if (! strcmp(str, "-target")) {
if (argc-- >= 0) argv++;
break;
}
warning("%s flag ignored", str);
break;
case 'M': /* use other compiler (for testing) */
strcpy(COMP, str+2);
break;
case 's': /* strip, -sun3? */
if (! strcmp(str, "-sun3")) {
break;
}
/* fall through */
case 'n': /* text not read-only */
case 'N': /* text read-only */
case 'r': /* relocation produced */
case 'S': /* strip, but leave locals and globals */
if (str[2] == '\0') {
append(&LD_FLAGS, str);
break;
}
/* fall through */
default:
warning("%s flag ignored", str);
break;
}
}
if (ecount) exit(1);
count = SRCFILES.al_argc;
argvec = &(SRCFILES.al_argv[0]);
while (count-- > 0) {
ext = extension(*argvec);
if (*argvec[0] != '-' &&
ext != *argvec++ && (! strcmp(ext, lang_suffix())
)) {
compile_cnt++;
}
}
if (compile_cnt > 1 && c_flag && o_flag) {
warning("-o flag ignored");
o_flag = 0;
}
append(&COMP_FLAGS, "-L");
count = SRCFILES.al_argc;
argvec = &(SRCFILES.al_argv[0]);
while (count-- > 0) {
register char *f;
basename(file = *argvec++, BASE);
ext = extension(file);
if (file[0] != '-' &&
ext != file && (!strcmp(ext, lang_suffix())
)) {
if (compile_cnt > 1) printf("%s\n", file);
ldfile = c_flag ? ofile : alloc((unsigned)strlen(BASE)+3);
if (
!strcmp(ext, "s") &&
needsprep(file)) {
strcpy(tmp_file, TMP_DIR);
strcat(tmp_file, "/F_XXXXXX");
mktemp(tmp_file);
init(call);
append(call, CPP);
concat(call, &CPP_FLAGS);
append(call, file);
if (runvec(call, tmp_file)) {
file = tmp_file;
}
else {
remove(tmp_file);
tmp_file[0] = '\0';
continue;
}
}
init(call);
if (o_flag && c_flag) {
f = o_FILE;
}
else f = mkstr(ldfile, BASE, ".", "o", (char *)0);
if (strcmp(ext, "s")) {
append(call, COMP);
concat(call, &CPP_FLAGS);
concat(call, &COMP_FLAGS);
append(call, file);
append(call, f);
}
else {
append(call, AS_NAME);
append(call, "-o");
append(call, f);
#ifdef sun3
append(call, "-mc68020");
#endif
append(call, file);
}
if (runvec(call, (char *) 0)) {
file = f;
}
else {
remove(f);
continue;
}
cleanup(tmp_file);
tmp_file[0] = '\0';
}
else if (file[0] != '-' &&
strcmp(ext, "o") && strcmp(ext, "a")) {
warning("file with unknown suffix (%s) passed to the loader", ext);
}
if (c_flag)
continue;
append(&LDFILES, file);
}
/* *.s to a.out */
if (RET_CODE == 0 && LDFILES.al_argc > 0) {
init(call);
expand(&LD_HEAD);
expand(&LD_TAIL);
append(call, expand_string(LD_NAME));
concat(call, &LD_FLAGS);
append(call, "-o");
append(call, o_FILE);
concat(call, &LD_HEAD);
concat(call, &LDFILES);
concat(call, &LD_TAIL);
if (! runvec(call, (char *) 0)) {
exit(RET_CODE);
}
}
exit(RET_CODE);
}
needsprep(name)
char *name;
{
int file;
char fc;
file = open(name,0);
if (file < 0) return 0;
if (read(file, &fc, 1) != 1) fc = 0;
close(file);
return fc == '#';
}
char *
alloc(u)
unsigned u;
{
char *p = malloc(u);
if (p == 0)
panic("no space");
return p;
}
char *
expand_string(s)
char *s;
{
char buf[1024];
register char *p = s;
register char *q = &buf[0];
int expanded = 0;
if (!p) return p;
while (*p) {
if (*p == '$') {
p++;
expanded = 1;
switch(*p++) {
case 'H':
strcpy(q, EM_DIR);
break;
case 'M':
strcpy(q, MACHNAME);
break;
case 'S':
strcpy(q, SYSNAME);
break;
default:
panic("internal error");
break;
}
while (*q) q++;
}
else *q++ = *p++;
}
if (! expanded) return s;
*q++ = '\0';
p = alloc((unsigned int) (q - buf));
return strcpy(p, buf);
}
append(al, arg)
register struct arglist *al;
char *arg;
{
if (!arg || !*arg) return;
if (al->al_argc >= MAXARGC)
panic("argument list overflow");
al->al_argv[(al->al_argc)++] = arg;
}
expand(al)
register struct arglist *al;
{
register int i = al->al_argc;
register char **p = &(al->al_argv[0]);
while (i-- > 0) {
*p = expand_string(*p);
p++;
}
}
concat(al1, al2)
struct arglist *al1, *al2;
{
register i = al2->al_argc;
register char **p = &(al1->al_argv[al1->al_argc]);
register char **q = &(al2->al_argv[0]);
if ((al1->al_argc += i) >= MAXARGC)
panic("argument list overflow");
while (i-- > 0) {
*p++ = *q++;
}
}
/*VARARGS*/
char *
mkstr(va_alist)
va_dcl
{
va_list ap;
char *dst;
va_start(ap);
{
register char *p;
register char *q;
dst = q = va_arg(ap, char *);
p = va_arg(ap, char *);
while (p) {
while (*q++ = *p++);
q--;
p = va_arg(ap, char *);
}
}
va_end(ap);
return dst;
}
basename(str, dst)
char *str;
register char *dst;
{
register char *p1 = str;
register char *p2 = p1;
while (*p1)
if (*p1++ == '/')
p2 = p1;
p1--;
while (*p1 != '.' && p1 >= p2) p1--;
if (p1 >= p2) {
*p1 = '\0';
while (*dst++ = *p2++);
*p1 = '.';
}
else
while (*dst++ = *p2++);
}
char *
extension(fn)
char *fn;
{
register char *c = fn;
while (*c++) ;
while (*--c != '.' && c >= fn) { }
if (c++ < fn || !*c) return fn;
return c;
}
runvec(vec, outp)
struct arglist *vec;
char *outp;
{
int pid, status;
if (v_flag) {
pr_vec(vec);
putc('\n', stderr);
}
if ((pid = fork()) == 0) { /* start up the process */
if (outp) { /* redirect standard output */
close(1);
if (creat(outp, 0666) != 1)
panic("cannot create output file");
}
ex_vec(vec);
}
if (pid == -1)
panic("no more processes");
kids = pid;
wait(&status);
if (status) switch(status & 0177) {
case SIGHUP:
case SIGINT:
case SIGQUIT:
case SIGTERM:
case 0:
break;
default:
error("%s died with signal %d\n", vec->al_argv[1], status&0177);
}
kids = -1;
return status ? ((RET_CODE = 1), 0) : 1;
}
/*VARARGS1*/
error(str, s1, s2)
char *str, *s1, *s2;
{
fprintf(stderr, "%s: ", ProgCall);
fprintf(stderr, str, s1, s2);
putc('\n', stderr);
ecount++;
}
/*VARARGS1*/
warning(str, s1, s2)
char *str, *s1, *s2;
{
fprintf(stderr, "%s: (warning) ", ProgCall);
fprintf(stderr, str, s1, s2);
putc('\n', stderr);
}
panic(str)
char *str;
{
error(str);
trapcc(SIGINT);
}
pr_vec(vec)
register struct arglist *vec;
{
register char **ap = &vec->al_argv[1];
vec->al_argv[vec->al_argc] = 0;
fprintf(stderr, "%s", *ap);
while (*++ap) {
fprintf(stderr, " %s", *ap);
}
}
extern int errno;
ex_vec(vec)
register struct arglist *vec;
{
if (noexec)
exit(0);
vec->al_argv[vec->al_argc] = 0;
execv(vec->al_argv[1], &(vec->al_argv[1]));
if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
vec->al_argv[0] = SHELL;
execv(SHELL, &(vec->al_argv[0]));
}
if (access(vec->al_argv[1], 1) == 0) {
/* File is executable. */
error("cannot execute %s", vec->al_argv[1]);
} else {
error("%s is not executable", vec->al_argv[1]);
}
exit(1);
}

38
fcc/driver/proto.make Normal file
View File

@@ -0,0 +1,38 @@
# $Header$
#PARAMS do not remove this line!
SRC_DIR = $(SRC_HOME)/fcc/driver
INCLUDES = -I$(TARGET_HOME)/config
CFLAGS = $(COPTIONS) $(INCLUDES)
LINTFLAGS = $(LINTOPTIONS) $(INCLUDES)
LDFLAGS = $(LDOPTIONS)
all: fcc
install: all
cp fcc $(TARGET_HOME)/bin
if [ $(DO_MACHINE_INDEP) = y ] ; \
then mk_manpage $(SRC_DIR)/fcc.1 $(TARGET_HOME) ; \
fi
cmp: all
-cmp fcc $(TARGET_HOME)/bin/fcc
pr:
@pr $(SRC_DIR)/proto.make $(SRC_DIR)/fcc.c
opr:
make pr | opr
clean:
rm -f *.$(SUF) fcc Out
lint:
$(LINT) $(LINTFLAGS) -D`ack_sys` $(SRC_DIR)/driver.c
fcc.$(SUF): $(SRC_DIR)/fcc.c $(TARGET_HOME)/config/em_path.h
$(CC) $(CFLAGS) -c -D$(MACH) -D`ack_sys` $(SRC_DIR)/fcc.c
fcc: fcc.$(SUF)
$(CC) $(LDFLAGS) -o fcc fcc.$(SUF)