From d91fa39567f5659e3931cf61517d62fddcd87570 Mon Sep 17 00:00:00 2001 From: Robert de Bath Date: Sat, 12 Jan 2002 20:42:42 +0100 Subject: Import Dev86src-0.16.1.tar.gz --- bcc/bcc.c | 2179 +++++++++++++++++++++++++------------------------------- bcc/const.h | 1 + bcc/function.c | 7 +- bcc/gencode.h | 1 + bcc/idcc | 328 --------- bcc/input.c | 6 + bcc/preproc.c | 29 +- bcc/scan.c | 20 +- bcc/scan.h | 3 + bcc/state.c | 28 +- 10 files changed, 1057 insertions(+), 1545 deletions(-) delete mode 100755 bcc/idcc (limited to 'bcc') diff --git a/bcc/bcc.c b/bcc/bcc.c index 3de0006..abac5a9 100644 --- a/bcc/bcc.c +++ b/bcc/bcc.c @@ -1,26 +1,67 @@ -/* bcc.c - driver for Bruce's C compiler (bcc) and for CvW's C compiler */ - -/* Copyright (C) 1992 Bruce Evans */ - -#define _POSIX_SOURCE 1 - +/* + * bcc.c Version 2001.1 + * Complete rewrite because the old one was just too confusing! + * + * There are no significant compile time options (MC6809 and CCC + * just change defaults) but you should set LOCALPREFIX. + * + * Personality flags are: + * + * -Mn Normal ELKS + * -Md MSDOS + * -Ms PC Standalone. + * -Ml i386 Linux + * -M8 CvW's c386 + * -M9 MC6809 with bcc + */ +#include +#ifdef __STDC__ +#include +#include +#endif +#include +#include +#include +#include #include #include #ifndef MSDOS #include -#include -#endif #include -#include -#include -#include +#endif + +#ifdef MSDOS +#define LOCALPREFIX /linux86 +#define EXESUF ".exe" +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +#define X_OK 1 /* Test for execute permission. */ +#define F_OK 0 /* Test for existence. */ +#define L_TREE 1 /* Use different tree style */ +#define DEFARCH 0 /* Default to 8086 code */ +#else +#define EXESUF +#endif + +#define AS "as" EXESUF +#define LD "ld" EXESUF +#define CPP "cpp" EXESUF +#define CC1 "cc1" EXESUF +#define OPT "opt" EXESUF + +#define CC1C386 "c386" EXESUF + +#define AS09 "as09" EXESUF +#define LD09 "ld09" EXESUF -#define FALSE 0 -#define FORWARD static -#define NUL_PTR ((void*)0) -#define PRIVATE static -#define PUBLIC -#define TRUE 1 +#define CPPBCC "bcc-cc1" EXESUF +#define CC1BCC "bcc-cc1" EXESUF +#define AS86 "as86" EXESUF +#define LD86 "ld86" EXESUF + +#define GCC "gcc" +#define UNPROTO "unproto" EXESUF +#define OPTIM "copt" EXESUF #if __STDC__ == 1 #define P(x) x @@ -32,932 +73,951 @@ #define QUOT(x) "x" #endif +struct command { + char * cmd; + char * fullpath; + int numargs; + int maxargs; + char ** arglist; +} command = { 0,0,0,0,0 }; + +struct file_list { + struct file_list * next; + char * file; + char * oldfile; + char * name; + int filetype; /* Char, notional extention of file. */ +} * files; + +struct opt_list { + struct opt_list * next; + char * opt; + int opttype; /* Where the option should go */ +} * options; + +int opt_v, opt_V, opt_e, opt_x, opt_I, opt_L, opt_W, opt_i, + opt_O, opt_M; + +#ifdef DEFARCH +int opt_arch = (DEFARCH != 0); +#else +int opt_arch = sizeof (char *) >= 4; +#endif + +int do_preproc = 1; /* c -> i */ +int do_unproto = 0; /* i -> i */ +int do_compile = 1; /* i -> s */ +int do_optim = 0; /* s -> s */ +int do_as = 1; /* s -> o */ +int do_link = 1; /* o -> done */ +char * executable_name = 0; + +int file_count = 0; +int dyn_count = 0; +int error_count = 0; +char * progname = "C"; #ifdef MSDOS -#define LOCALPREFIX /linux86 -#define EXESUF ".exe" -#define R_OK 4 /* Test for read permission. */ -#define W_OK 2 /* Test for write permission. */ -#define X_OK 1 /* Test for execute permission. */ -#define F_OK 0 /* Test for existence. */ -#define L_TREE 1 /* Use different tree style */ -#define DEFARCH 0 /* Default to 8086 code */ +char * tmpdir = ""; #else -#define EXESUF +char * tmpdir = "/tmp/"; +#endif + +int main P((int argc, char **argv)); +void getargs P((int argc, char **argv)); +void add_prefix P((char * path)); +void run_aspreproc P((struct file_list * file)); +void run_preproc P((struct file_list * file)); +void run_unproto P((struct file_list * file)); +void run_compile P((struct file_list * file)); +void run_optim P((struct file_list * file)); +void run_as P((struct file_list * file)); +void run_link P((void)); +void command_reset P((void)); +void command_opt P((char * option)); +void command_arch P((void)); +void command_opts P((int opykey)); +void newfilename P((struct file_list * file, int last_stage, int new_extn, int use_o)); +void run_unlink P((void)); +void append_file P((char * filename, int ftype)); +void append_option P((char * option, int otype)); +char * expand_tilde P((char * str)); +void * xalloc P((int size)); +void Usage P((void)); +void fatal P((char * why)); +char * copystr P((char * str)); +char * catstr P((char * str, char * str2)); +#ifdef L_TREE +void reset_localprefix P((void)); #endif +void run_command P((struct file_list * file)); -#if defined(__minix) || defined(__BCC__) -#define realpath(x,y) 0 +#ifndef LOCALPREFIX +#define LOCALPREFIX /usr +#endif +char * localprefix = QUOT(LOCALPREFIX); +#ifndef L_TREE +char * default_include = "-I~/include"; +char * default_libdir0 = "-L~/lib/bcc/i86/"; +char * default_libdir3 = "-L~/lib/bcc/i386/"; +char * optim_rules = "-d~/lib/bcc/i86"; +#else +char * default_include = "-I~/include"; +char * default_libdir0 = "-L~/lib/"; +char * default_libdir3 = "-L~/lib/i386/"; +char * optim_rules = "-d~/lib"; #endif -#define BAS86 -#define BCC86 +char devnull[] = "/dev/null"; +char * exec_prefixs[] = { -#define AS "as86" EXESUF -#define CC1 "bcc-cc1" EXESUF -#define CC1_MINUS_O_BROKEN FALSE -#define CPP "bcc-cc1" EXESUF -#define CPPFLAGS "-E" -#define GCC "gcc" -#define LD "ld86" EXESUF -#define UNPROTO "unproto" EXESUF -#define OPTIM "copt" EXESUF + /* Place fillers for dynamic fill */ + devnull, devnull, devnull, devnull, devnull, -#ifdef L_TREE -#define STANDARD_CRT0_0_PREFIX "~/lib/" -#define STANDARD_CRT0_3_PREFIX "~/lib/i386/" -#define STANDARD_EXEC_PREFIX "~/lib/" -#define STANDARD_EXEC_PREFIX_2 "~/bin/" -#define DEFAULT_INCLUDE "-I~/include" -#define DEFAULT_LIBDIR0 "-L~/lib/" -#define DEFAULT_LIBDIR3 "-L~/lib/i386/" -#define OPTIM_RULES "-d~/lib" -#else -#define STANDARD_CRT0_0_PREFIX "~/lib/bcc/i86/" -#define STANDARD_CRT0_3_PREFIX "~/lib/bcc/i386/" -#define STANDARD_EXEC_PREFIX "~/lib/bcc/" + "~/lib/bcc/", #ifdef BINDIR -#define STANDARD_EXEC_PREFIX_2 QUOT(BINDIR) "/" -#else -#define STANDARD_EXEC_PREFIX_2 "/usr/bin/" + QUOT(BINDIR) "/", #endif -#define DEFAULT_INCLUDE "-I~/include" -#define DEFAULT_LIBDIR0 "-L~/lib/bcc/i86/" -#define DEFAULT_LIBDIR3 "-L~/lib/bcc/i386/" -#define OPTIM_RULES "-d~/lib/bcc/i86" + "~/lib/", + "~/bin/", + "/usr/bin/", + 0 +}; + +char * libc = "-lc"; + +int +main(argc, argv) +int argc; +char ** argv; +{ + struct file_list * next_file; + + progname = argv[0]; +#ifdef L_TREE + reset_localprefix(); #endif + getargs(argc, argv); -#ifdef CCC -#undef BCC86 -#undef CC1 -#define CC1 "c386" -#undef CC1_MINUS_O_BROKEN -#define CC1_MINUS_O_BROKEN TRUE -#undef STANDARD_CRT0_0_PREFIX -#undef STANDARD_CRT0_3_PREFIX -#define STANDARD_CRT0_PREFIX "~/lib/i386/" -#endif /* CCC */ + default_include = expand_tilde(default_include); + default_libdir0 = expand_tilde(default_libdir0); + default_libdir3 = expand_tilde(default_libdir3); + optim_rules = expand_tilde(optim_rules); -#ifdef MC6809 -#undef BAS86 -#undef BCC86 -#undef CRT0 -#undef GCC -#undef STANDARD_CRT0_0_PREFIX -#undef STANDARD_CRT0_3_PREFIX -#undef STANDARD_EXEC_PREFIX -#define STANDARD_EXEC_PREFIX "~/lib/bcc/m09/" -#endif /* MC6809 */ - -#define ALLOC_UNIT 16 /* allocation unit for arg arrays */ -#define DIRCHAR '/' -#define START_ARGS 4 /* number of reserved args */ - -typedef unsigned char bool_T; /* boolean: TRUE if nonzero */ - -struct arg_s + if (opt_v>1) { command.cmd = ""; command_reset(); } + + for(next_file = files; next_file && !error_count; next_file = next_file->next) + { + if (next_file->filetype == 'o') continue; + + if (opt_V) + fprintf(stderr, "%s:\n", next_file->file); + + /* Assembler that's not to be optimised. */ + if (do_preproc && next_file->filetype == 'S') run_aspreproc(next_file); + if (do_as && next_file->filetype == 's') run_as(next_file); + + /* C source */ + if (do_preproc && next_file->filetype == 'c') run_preproc(next_file); + if (do_unproto && next_file->filetype == 'i') run_unproto(next_file); + if (do_compile && next_file->filetype == 'i') run_compile(next_file); + if (do_optim && next_file->filetype == 's') run_optim(next_file); + if (do_as && next_file->filetype == 's') run_as(next_file); + + if (next_file->filetype == '~') error_count++; + } + + if (do_link && !error_count) + run_link(); + + run_unlink(); + exit(error_count>0); +} + +char * +copystr(str) +char * str; { - char *prog; - bool_T minus_O_broken; - int argc; - char **argv; - unsigned nr_allocated; -}; + return strcpy(xalloc(strlen(str)+1), str); +} -struct prefix_s +char * +catstr(str, str2) +char * str, * str2; { - char *name; - struct prefix_s *next; -}; + return strcat(strcpy(xalloc(strlen(str)+strlen(str2)+1), str), str2); +} -PRIVATE struct arg_s asargs = { AS, }; -PRIVATE struct arg_s ccargs = { CC1, CC1_MINUS_O_BROKEN, }; -PRIVATE struct arg_s cppargs = { CPP, }; -PRIVATE struct arg_s unprotoargs = { UNPROTO, TRUE }; -PRIVATE struct arg_s optargs = { OPTIM }; -PRIVATE struct prefix_s exec_prefix; -PRIVATE struct arg_s ldargs = { LD, }; -#ifdef BAS86 -PRIVATE struct arg_s ldrargs = { LD, }; -#endif -PRIVATE char *progname; -PRIVATE bool_T runerror; /* = FALSE */ -PRIVATE struct arg_s tmpargs; /* = empty */ -PRIVATE char *tmpdir; -PRIVATE unsigned verbosity; /* = 0 */ - -PRIVATE char * localprefix = QUOT(LOCALPREFIX); - -#ifdef REDECLARE_STDC_FUNCTIONS -void exit P((int status)); -char *getenv P((const char *name)); -void *malloc P((size_t size)); -void *realloc P((void *ptr, size_t size)); -void (*signal P((int sig, void (*func) P((int sig))))) P((int sig)); -char *strcpy P((char *dest, const char *src)); -size_t strlen P((const char *s)); -char *strrchr P((const char *s, int c)); +void +run_aspreproc(file) +struct file_list * file; +{ + if (opt_arch<5) command.cmd = CPPBCC; + else command.cmd = CPP; + command_reset(); + newfilename(file, !do_as, 's', (opt_arch<5)); + if (opt_arch<5) + command_opt("-E"); + command_opts('p'); + command_opt("-D__ASSEMBLER__"); +#if 0 + if (!opt_I) + command_opt(default_include); #endif + command_arch(); + run_command(file); +} -#ifdef REDECLARE_POSIX_FUNCTIONS -int access P((const char *path, int amode)); -int execv P((const char *path, char * const *argv)); -int execve P((const char *path, char * const *argv, char * const envp)); -pid_t fork P((void)); -pid_t getpid P((void)); -int unlink P((const char *path)); -pid_t wait P((int *status)); -ssize_t write P((int fd, const void *buf, size_t nbytes)); -#endif +void +run_preproc(file) +struct file_list * file; +{ + int last_stage = 0;; -int main P((int argc, char **argv)); + if (opt_arch<5) command.cmd = CPPBCC; + else command.cmd = CPP; + command_reset(); -FORWARD void addarg P((struct arg_s *argp, char *arg)); -FORWARD void adddefine P((char *arg)); -FORWARD void addprefix P((struct prefix_s *prefix, char *name)); -FORWARD char *expand_tilde P((char * str, int canfree)); -FORWARD void fatal P((char *message)); -FORWARD char *fixpath P((char *path, struct prefix_s *prefix, int mode)); -FORWARD void killtemps P((void)); -FORWARD void *my_malloc P((unsigned size, char *where)); -FORWARD char *my_mktemp P((void)); -FORWARD void my_unlink P((char *name)); -FORWARD void outofmemory P((char *where)); -FORWARD int run P((char *in_name, char *out_name, struct arg_s *argp)); -#ifdef L_TREE -FORWARD void reset_localprefix P((void)); -#endif -FORWARD void set_trap P((void)); -FORWARD void show_who P((char *message)); -FORWARD void startarg P((struct arg_s *argp)); -FORWARD char *stralloc P((char *s)); -FORWARD char *stralloc2 P((char *s1, char *s2)); -FORWARD void trap P((int signum)); -FORWARD void writen P((void)); -FORWARD void writes P((char *s)); -FORWARD void writesn P((char *s)); -FORWARD void linux_patch P((char * fname)); + if (!opt_e && !do_optim && !do_as ) last_stage =1; + if (opt_e && !do_unproto && !do_compile ) last_stage =1; -#ifdef __BCC__ -char ** minienviron[] = { - "PATH=/bin:/usr/bin", - "SHELL=/bin/sh", - 0 -}; -#endif + newfilename(file, last_stage, (opt_e?'i':'s'), (opt_arch<5)); -PUBLIC int main(argc, argv) -int argc; -char **argv; + if (opt_e && opt_arch<5) command_opt("-E"); + + command_opts('p'); + if (!opt_e) + { + command_opts('c'); + if (opt_arch<5 && !do_as) + command_opt("-t"); + } + + if (!opt_I) + command_opt(default_include); + + command_arch(); + + run_command(file); +} + +void +run_unproto(file) +struct file_list * file; { - char *arg; - int add_default_inc = 1; - int add_default_lib = 1; - int argcount = argc; - bool_T *argdone = my_malloc((unsigned) argc * sizeof *argdone, "argdone"); - bool_T as_only = FALSE; - char *basename; -#ifdef BCC86 -#ifdef DEFARCH - bool_T bits32 = (DEFARCH != 0); -#else - bool_T bits32 = sizeof (char *) >= 4; -#endif - char *bits_arg; + command.cmd = UNPROTO; + command_reset(); + newfilename(file, !do_compile, 'i', 0); + command_opts('u'); + + run_command(file); +} + +void +run_compile(file) +struct file_list * file; +{ + if (opt_arch == 3) command.cmd = CC1C386; + else if (opt_arch<5) command.cmd = CC1BCC; + else command.cmd = CC1; + command_reset(); + newfilename(file, !(do_optim || do_as), 's', (opt_arch != 3 && opt_arch<5)); + + command_opts('c'); + + command_arch(); + + run_command(file); +} + +void +run_optim(file) +struct file_list * file; +{ + char buf[32]; + if (opt_arch<5) command.cmd = OPTIM; + else command.cmd = OPT; + command_reset(); + newfilename(file, !do_as, 's', 1); + command_opt("-c!"); + if (opt_O) + { + sprintf(buf, "-huse16 %c86", opt_O); + command_opt(buf); + } + command_opt(optim_rules); + + command_opt("rules.start"); + command_opts('o'); + if (opt_O) + { + sprintf(buf, "rules.%c86", opt_O); + command_opt(buf); + } + command_opt("rules.86"); + command_opt("rules.end"); + + run_command(file); +} + +void +run_as(file) +struct file_list * file; +{ + char * buf; + switch(opt_arch) + { + case 0: case 1: case 2: + command.cmd = AS86; break; + case 4: command.cmd = AS09; break; + default: command.cmd = AS; break; + } + command_reset(); + newfilename(file, (!do_link && opt_arch!=2), 'o', 1); + if (opt_arch==3) + command_opt("-j"); + if (opt_arch<5) + command_opt("-u"); + command_opts('a'); + if (opt_W) + command_opt("-w-"); + else + command_opt("-w"); + command_arch(); + command_opt("-n"); + buf = catstr(file->name, ".s"); + command_opt(buf); + free(buf); + + run_command(file); + + if (opt_arch == 2) + { + command.cmd = LD86; + command_reset(); + newfilename(file, !do_link, 'o', 1); + command_opt("-r"); + run_command(file); + } +} + +void +run_link() +{ + struct file_list * next_file; + + switch(opt_arch) + { + case 0: case 1: + command.cmd = LD86; break; + case 2: command.cmd = GCC; break; + case 4: command.cmd = LD09; break; + default: command.cmd = LD; break; + } + command_reset(); + if (executable_name == 0) executable_name = "a.out"; + + command_opt("-o"); + command_opt(executable_name); + + command_opts('l'); + if (opt_arch != 2) + { + if (opt_arch == 0 && !opt_i) + command_opt("-i"); + + if (!opt_L) + { + if (opt_arch==1) command_opt(default_libdir3); + else command_opt(default_libdir0); + } + command_arch(); + + if (!opt_x) + command_opt("-C0"); + } + + for(next_file = files; next_file; next_file = next_file->next) + command_opt(next_file->file); + + if (opt_arch != 2) + command_opt(libc); + run_command(0); +} + +void +command_reset() +{ +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 #endif - bool_T cc_only = FALSE; - bool_T ansi_pass = FALSE; -#ifdef CCC - bool_T cpp_pass = TRUE; + char buf[MAXPATHLEN]; + char ** prefix; + + if (command.arglist) + { + int i; + for(i=0; inext) + if (ol->opttype == optkey) + command_opt(ol->opt); +} + +void newfilename(file, last_stage, new_extn, use_o) +struct file_list * file; +int last_stage; +int new_extn; +int use_o; +{ + file->filetype = new_extn; + if (file->oldfile) free(file->oldfile); + file->oldfile = file->file; + file->file = 0; + + if (last_stage) { + if (executable_name) + file->file = copystr(executable_name); + else + { + char buf[4]; + buf[0] = '.'; + buf[1] = file->filetype; + buf[2] = 0; + file->file = catstr(file->name, buf); + } + } + else + { + char buf[16]; +#ifdef MSDOS + sprintf(buf, "$$%05d$", dyn_count++); #else - bool_T cpp_pass = FALSE; + sprintf(buf, "$$%04d%05d", dyn_count++, getpid()); #endif - char *libc = "-lc"; + file->file = catstr(tmpdir, buf); + } + + command_opt(file->oldfile); + /* *.i files go to the stdout */ + if (last_stage && file->filetype == 'i') return; + if (use_o) command_opt("-o"); + command_opt(file->file); +} + +void +run_unlink() +{ + int i; + for(i=0; iOMAGIC */ - - progname = argv[0]; - addarg(&cppargs, CPPFLAGS); -#ifdef CCC - addarg(&asargs, "-j"); -#endif - addarg(&asargs, "-u"); -#ifdef BAS86 - addarg(&ldrargs, "-r"); - addarg(&ldrargs, "-N"); /* GCC uses native objects */ - /* GCC also uses 386 how to add -3 too ? */ - addarg(&optargs, "-c!"); - optflags = stralloc("start"); + sprintf(buf, "$$%04d%05d", i, getpid()); #endif + p = catstr(tmpdir, buf); + if (opt_v>1) + fprintf(stderr, "rm %s\n", p); + if (opt_v>2) + continue; + if (unlink(p) < 0) + { + if (error_count==0 || opt_v>1) + fprintf(stderr, "Error unlinking %s\n", p); + error_count++; + } + free(p); + } +} -#ifdef L_TREE - reset_localprefix(); -#endif - /* Pass 1 over argv to gather compile options. */ - for (; --argc != 0;) - { - arg = *++argv; - *++argdone = TRUE; - if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) - switch (arg[1]) - { -#ifdef BCC86 - case '0': - bits32 = FALSE; - break; - case '3': - bits32 = TRUE; - break; -#endif - case 'E': - prep_only = prep_line_numbers = cpp_pass = TRUE; - break; -#ifdef BAS86 - case 'G': - gnu_objects = TRUE; - add_default_lib = 0; - break; -#endif - case 'P': - prep_only = cpp_pass = TRUE; - prep_line_numbers = FALSE; - break; - case 'O': - optimize = TRUE; - temp = optflags; - optflags=stralloc2(optflags,",86"); - free(temp); - break; - case 'S': - cc_only = TRUE; -#ifndef CCC - addarg(&ccargs, "-t"); -#endif - break; - case 'V': - echo = TRUE; - break; - case 'c': - as_only = TRUE; - break; - case 'e': - cpp_pass = TRUE; - break; - case 'g': - debug = TRUE; /* unsupported */ - break; - case 'o': - if (argc <= 1) - { - ++errcount; - show_who("output file missing after -o\n"); - } - else - { - argc--; - if (f_out != NUL_PTR) - show_who("more than one output file\n"); - f_out = *++argv; - *++argdone = TRUE; - } - break; - case 'p': - profile = TRUE; - break; - case 'v': - ++verbosity; - break; - case 'w': - compiler_warnings = FALSE; - aswarn = FALSE; - break; - case 'W': - aswarn = TRUE; - break; - case 'x': - has_crt0 = FALSE; - break; - case 'I': - add_default_inc = 0; - break; - case 'L': - add_default_lib = 0; - break; - - default: - *argdone = FALSE; - break; - } - else if (arg[0] == '-') - switch (arg[1]) - { - case 'a': - if (!strcmp(arg, "-ansi")) - { - ansi_pass=TRUE; - cpp_pass=TRUE; - /* NOTE I'm setting this to zero, this isn't a _real_ STDC */ - adddefine("-D__STDC__=0"); - } - break; - case 't': - addarg(&asargs, "-t"); - addarg(&asargs, arg+2); - break; - case 'A': - addarg(&asargs, arg + 2); - break; - case 'B': - addprefix(&exec_prefix, arg + 2); - break; - case 'C': - addarg(&ccargs, arg + 2); - break; - case 'D': - case 'I': - case 'U': - adddefine(arg); - break; - case 'X': - addarg(&ldargs, arg + 2); - break; - case 'L': - addarg(&ldargs, arg); - break; - case 'M': - major_mode=arg[2]; - break; - - case 'O': - optimize = TRUE; - temp=optflags; optflags=stralloc2(optflags,","); free(temp); - temp=optflags; optflags=stralloc2(optflags,arg+2); free(temp); - if( arg[3] == 0 && ( arg[2] >= '1' && arg[2] <= '3' )) - { - temp=optflags; - optflags=stralloc2(optflags,"86,86"); - free(temp); - switch(arg[2]) - { - case '1': addarg(&optargs, "-huse16 186"); break; - case '2': addarg(&optargs, "-huse16 286"); break; - case '3': addarg(&optargs, "-huse16 386"); break; - } - } - break; - case 'P': - addarg(&cppargs, arg + 2); - break; - case 'Q': - addarg(&ccargs, arg); - break; - case 'T': - tmpdir = arg + 2; - break; - default: - *argdone = FALSE; - break; - } - else - { - ++nifiles; - *argdone = FALSE; - length = strlen(arg); - if (length >= 2 && arg[length - 2] == '.' - && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S' - || ext == 's')) - ++ncisfiles; - } - } - npass_specs = prep_only + cc_only + as_only; - if (npass_specs != 0) - { - if (npass_specs > 1) - { - ++errcount; - show_who("more than 1 option from -E -P -S -c\n"); - } - if (f_out != NUL_PTR && ncisfiles > 1) - { - ++errcount; - show_who("cannot have more than 1 input with non-linked output\n"); +void +getargs(argc, argv) +int argc; +char ** argv; +{ + int ar; + char * pflag = 0; + int control_count = 0; + int exe_count = 0; + + for(ar=1; ar= '1' && opt_arg[0] <= '3' )) + opt_O = opt_arg[0]; + else + { + char * p = xalloc(strlen(opt_arg)+8); + strcpy(p, "rules."); + strcat(p, opt_arg); + append_option(p, 'o'); + free(p); + } + break; + + case 'o': + exe_count++; + executable_name = opt_arg; + break; + + case 'B': + add_prefix(opt_arg); + break; + + case 'I': + case 'D': + case 'U': + append_option(argv[ar], 'p'); + break; + + case 'T': + tmpdir = catstr(opt_arg, "/"); + break; + + case 'M': + if (opt_arg[1]) Usage(); + opt_M = *opt_arg; + break; + + default: + pflag = argv[ar]+1; + used_arg = 0; + break; + } + /* Singleton flags */ + if(pflag) switch(opt = *pflag++) + { + case 'P': + append_option("-P", 'p'); + /*FALLTHROUGH*/ + case 'E': + control_count++; + do_compile = do_link = do_as = 0; + opt_e = 1; + break; + case 'S': + control_count++; + do_as = do_link = 0; + break; + case 'c': + control_count++; + do_link = 0; + break; + case 'O': + do_optim=1; + break; + + case 'G': opt_M = 'G'; break; + + case 'v': opt_v++; break; + case 'V': opt_V++; break; + case 'e': opt_e++; break; + case 'x': opt_x++; break; + case 'I': opt_I++; break; + case 'L': opt_L++; break; + case 'i': opt_i++; break; + + case 'W': opt_W++; break; + + case '0': opt_arch=0; opt_M='x'; break; + case '3': opt_arch=1; opt_M='x'; break; + + case 'w': /*IGNORED*/ break; + case 'g': /*IGNORED*/ break; + case 'f': /*IGNORED*/ break; + case 'p': /*IGNORED*/ break; + + default: + if (pflag == argv[ar]+2) { + /* Special; unknown options saved as flags for the linker */ + append_file(argv[ar], 'o'); + pflag = 0; } - } - if (nifiles == 0) - { - ++errcount; - show_who("no input files\n"); - } - if (errcount != 0) - exit(1); - -#ifdef BCC86 - if(!major_mode && !bits32) major_mode='n'; - switch(major_mode) - { - case 'd': /* DOS compile */ - bits32 = FALSE; - libc= "-ldos"; - adddefine("-D__MSDOS__"); - addarg(&ldargs, "-d"); - addarg(&ldargs, "-T100"); - break; - - case 'n': /* Normal Linux-86 */ - bits32 = FALSE; - libc= "-lc"; - adddefine("-D__ELKS__"); - adddefine("-D__unix__"); - break; - - case 'f': /* Caller saves+ax is first arg */ - bits32 = FALSE; - libc= "-lc_f"; - adddefine("-D__ELKS__"); - adddefine("-D__unix__"); - addarg(&ccargs, "-f"); - addarg(&ccargs, "-c"); - break; - - case 'c': /* Just caller saves, normal C-lib is ok */ - bits32 = FALSE; - libc= "-lc"; - adddefine("-D__ELKS__"); - adddefine("-D__unix__"); - addarg(&ccargs, "-c"); - break; - - case 's': /* Standalone executable */ - bits32 = FALSE; - libc= "-lc_s"; - adddefine("-D__STANDALONE__"); - break; - - case 'l': /* Large Linux compile */ - bits32 = TRUE; - libc= "-lc"; - adddefine("-D__linux__"); - adddefine("-D__unix__"); -#ifdef __linux__ - addarg(&ldargs, "-N"); /* Make OMAGIC */ -#else - patch_exe = TRUE; -#endif - break; + else + Usage(); + } + if (!pflag || !*pflag) { ar++; pflag = 0; } + if (used_arg && inc_ar) ar++; + if (used_arg && inc_ar==2) + fatal("Last option requires an argument"); + } - case '?': - case 0: - break; + if (control_count>1) + fatal("only one option from -E -P -S -c allowed"); + if (exe_count>1) + fatal("only one -o option allowed"); - default: - fatal("Fatal error: illegal -M option given"); - } -#endif + if (file_count==0) Usage(); - if( aswarn ) - addarg(&asargs, "-w-"); - else - addarg(&asargs, "-w"); - if( patch_exe ) - addarg(&ldargs, "-s"); -#ifdef BCC86 - else if( !bits32 ) - addarg(&ldargs, "-i"); -#endif - if (verbosity > 2) - { - show_who("localprefix set to "); - writesn(localprefix); - } - if ((temp = getenv("BCC_EXEC_PREFIX")) != NUL_PTR) - addprefix(&exec_prefix, temp); - if( add_default_inc ) - adddefine(DEFAULT_INCLUDE); - if( add_default_lib ) - { -#ifdef BCC86 -#ifdef DEFAULT_LIBDIR3 - if( bits32 ) - addarg(&ldargs, DEFAULT_LIBDIR3); - else -#endif + if (exe_count && file_count != 1 && !do_link) + fatal("only one input file for each non-linked output"); + + add_prefix(getenv("BCC_EXEC_PREFIX")); + +#ifdef MC6809 + if (opt_M==0) opt_M = '9'; #endif - addarg(&ldargs, DEFAULT_LIBDIR0); - } - - if (optimize) - addarg(&asargs, "-O"); - addarg(&optargs, OPTIM_RULES); - temp=optflags; optflags=stralloc2(optflags,",end"); free(temp); - for(temp=strtok(optflags,","); temp; temp=strtok((char*)0,",")) - { - temp = stralloc2("rules.", temp); - addarg(&optargs, temp); - } - addprefix(&exec_prefix, STANDARD_EXEC_PREFIX); - addprefix(&exec_prefix, STANDARD_EXEC_PREFIX_2); - cppargs.prog = fixpath(cppargs.prog, &exec_prefix, X_OK); - ccargs.prog = fixpath(ccargs.prog, &exec_prefix, X_OK); - asargs.prog = fixpath(asargs.prog, &exec_prefix, X_OK); - ldargs.prog = fixpath(ldargs.prog, &exec_prefix, X_OK); -#ifdef BAS86 - ldrargs.prog = fixpath(ldrargs.prog, &exec_prefix, X_OK); +#ifdef CCC + if (opt_M==0) opt_M = '8'; #endif - unprotoargs.prog=fixpath(unprotoargs.prog, &exec_prefix, X_OK); - optargs.prog = fixpath(optargs.prog, &exec_prefix, X_OK); - if (tmpdir == NUL_PTR && (tmpdir = getenv("TMPDIR")) == NUL_PTR) #ifdef MSDOS - tmpdir = "."; -#else - tmpdir = "/tmp"; + if (opt_M==0) opt_M = 'd'; #endif + if (opt_M==0) opt_M = (opt_arch==1 ?'l':'n'); + switch(opt_M) + { + case 'n': + append_option("-D__ELKS__", 'p'); + append_option("-D__unix__", 'p'); + libc="-lc"; + break; + case 'f': + append_option("-D__ELKS__", 'p'); + append_option("-D__unix__", 'p'); + append_option("-c", 'p'); + append_option("-f", 'p'); + libc="-lc_f"; + break; + case 'c': + append_option("-D__ELKS__", 'p'); + append_option("-D__unix__", 'p'); + append_option("-c", 'p'); + libc="-lc"; + break; + case 's': + append_option("-D__STANDALONE__", 'p'); + libc="-lc_s"; + break; + case 'd': + append_option("-D__MSDOS__", 'p'); + libc="-ldos"; + append_option("-d", 'l'); + append_option("-T100", 'l'); + break; + case 'l': + opt_arch=1; + append_option("-D__linux__", 'p'); + append_option("-D__unix__", 'p'); + libc="-lc"; + append_option("-N", 'l'); + break; + case 'G': + opt_arch = 2; + break; + case '8': + opt_arch = 3; + opt_e = 1; + break; + case '9': + opt_arch = 4; + default_libdir0 = "-L~/lib/bcc/m09/"; + optim_rules = "-d~/lib/bcc/m09"; + add_prefix("~/lib/bcc/m09/"); + break; + case '0': + opt_arch = 5; + opt_e = 1; + opt_I = 1; + opt_L = 1; + opt_x = 1; + append_option("/lib/crt0.o", 'l'); + break; + } - if (prep_only && !prep_line_numbers) - addarg(&cppargs, "-P"); -#ifdef BCC86 -#ifdef STANDARD_CRT0_3_PREFIX - if (bits32) - bits_arg = "-3"; - else -#endif - bits_arg = "-0"; - addarg(&ccargs, bits_arg); - addarg(&cppargs, bits_arg); - addarg(&asargs, bits_arg); -#ifdef BAS86 - if (!gnu_objects) - { - addarg(&ldargs, bits_arg); - addarg(&ldrargs, bits_arg); - if( has_crt0 ) - addarg(&ldargs, "-C0"); - } -#endif /* BAS86 */ -#endif /* BCC86 */ - set_trap(); - - /* Pass 2 over argv to compile and assemble .c, .i, .S and .s files and - * gather arguments for linker. - */ - for (argv -= (argc = argcount) - 1, argdone -= argcount - 1; --argc != 0;) - { - arg = *++argv; - if (!*++argdone) - { - length = strlen(arg); - if (length >= 2 && arg[length - 2] == '.' - && ((ext = arg[length - 1]) == 'c' || ext == 'i' || ext == 'S' - || ext == 's')) - { - if (echo || verbosity != 0) - { - writes(arg); - writesn(":"); - } - if ((basename = strrchr(arg, DIRCHAR)) == NUL_PTR) - basename = arg; - else - ++basename; - in_name = arg; - if (ext == 'c') - { - if (cpp_pass) - { - if (prep_only && !ansi_pass) - out_name = f_out; - else - out_name = my_mktemp(); - if (run(in_name, out_name, &cppargs) != 0) - continue; - in_name = out_name; - if (ansi_pass) - { - if (prep_only) - out_name = f_out; - else - out_name = my_mktemp(); - - if (run(in_name, out_name, &unprotoargs) != 0) - continue; - in_name=out_name; - } - } - ext = 'i'; - } - if (ext == 'i') - { - if (prep_only) - continue; - if (cc_only && !optimize) - { - if (f_out != NUL_PTR) - out_name = f_out; - else - { - out_name = stralloc(basename); - out_name[strlen(out_name) - 1] = 's'; - } - } - else - out_name = my_mktemp(); - if (run(in_name, out_name, &ccargs) != 0) - continue; - in_name = out_name; - if( optimize ) - { - if (cc_only) - { - if (f_out != NUL_PTR) - out_name = f_out; - else - { - out_name = stralloc(basename); - out_name[strlen(out_name) - 1] = 's'; - } - } - else - out_name = my_mktemp(); - - if (run(in_name, out_name, &optargs) != 0) - continue; - in_name = out_name; - } - ext = 's'; - } - if (ext == 'S') - { - if (prep_only) - out_name = f_out; - else if (cc_only) - { - if (f_out != NUL_PTR) - out_name = f_out; - else - { - out_name = stralloc(basename); - out_name[strlen(out_name) - 1] = 's'; - } - } - else - out_name = my_mktemp(); - if (run(in_name, out_name, &cppargs) != 0) - continue; - in_name = out_name; - ext = 's'; - } - if (ext == 's') - { - if (prep_only || cc_only) - continue; - out_name = stralloc(basename); - out_name[strlen(out_name) - 1] = 'o'; - if (as_only) - { - if (f_out != NUL_PTR) - out_name = f_out; - else - { - out_name = stralloc(basename); - out_name[strlen(out_name) - 1] = 'o'; - } - } - else - out_name = my_mktemp(); - addarg(&asargs, "-n"); - arg[length - 1] = 's'; - addarg(&asargs, arg); -#ifdef BAS86 - if (gnu_objects) - { - char *tmp_out_name; - - tmp_out_name = my_mktemp(); - status = run(in_name, tmp_out_name, &asargs); - asargs.argc -= 2; - if (status != 0) - continue; - if (run(tmp_out_name, out_name, &ldrargs) != 0) - continue; - } - else -#endif - { - status = run(in_name, out_name, &asargs); - asargs.argc -= 2; - if (status != 0) - continue; - } - ext = 'o'; - in_name = out_name; - } - if (ext == 'o') - { - if (prep_only || cc_only || as_only) - continue; - addarg(&ldargs, in_name); - } - } - else - addarg(&ldargs, arg); - } - } - - if (!prep_only && !cc_only && !as_only && !runerror) - { - int link_st; - - if (f_out == NUL_PTR) - f_out = "a.out"; -#ifdef BAS86 - if (gnu_objects) - { - /* Remove -i and -i-. */ - for (argc = ldargs.argc - 1; argc >= START_ARGS; --argc) - { - arg = ldargs.argv[argc]; - if (arg[0] == '-' && arg[1] == 'i' - && (arg[2] == 0 || (arg[2] == '-' && arg[3] == 0))) - { - --ldargs.argc; - memmove(ldargs.argv + argc, ldargs.argv + argc + 1, - (ldargs.argc - argc) * sizeof ldargs.argv[0]); - ldargs.argv[ldargs.argc] = NUL_PTR; - } - } - - ldargs.prog = fixpath(GCC, &exec_prefix, X_OK); - link_st = run((char *) NUL_PTR, f_out, &ldargs); - } - else -#endif - { - addarg(&ldargs, libc); - link_st = run((char *) NUL_PTR, f_out, &ldargs); - } - if( patch_exe && link_st == 0 ) - linux_patch(f_out); - } - if( runerror && f_out != NUL_PTR ) - my_unlink(f_out); - killtemps(); - return runerror ? 1 : 0; + if (do_optim) + { + if (opt_e) + append_option("-O", 'c'); + append_option("-O", 'p'); + append_option("-O", 'a'); + } } -PRIVATE void linux_patch(fname) -char * fname; +void +add_prefix(path) +char * path; { -/* OMAGIC */ - -#define AOUT_MAG "\x07\x01\x64\x00" /* 0x640107L */ -#define ELKS_MAG1 0x10 -#define ELKS_MAG2 0x11 /* -z */ -#define ELKS_MAG3 0x20 /* -i */ -#define ELKS_MAG4 0x21 /* -i -z */ - -static struct ELKS_exec { /* ELKS a.out header */ - char a_magic1; /* magic number */ - char a_magic2; /* magic number */ - char a_magic3; /* magic number */ - char a_magic4; /* magic number */ - char a_hdrlen; /* length, etc of header */ - char a_hdrlen3[3]; - long a_text; /* size of text segement in bytes */ - long a_data; /* size of data segment in bytes */ - long a_bss; /* size of bss segment in bytes */ - long a_entry; /* entry point */ - long a_total; /* total memory allocated */ - long a_syms; /* size of symbol table */ -} instr; - - -static struct aout_exec { - char a_info[4]; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -} outstr; - - int fd; - - fd = open(fname, O_RDWR); - if( fd<0 ) return; - - if( read(fd, &instr, sizeof(instr)) != sizeof(instr) ) - { - writesn("Cannot re-read executable header"); - return; + char ** p; + if (!path || !*path) return; + + for(p=exec_prefixs; *p; p++) { + if( *p == devnull ) + { + *p = path; + break; + } } + if (!*p) fatal("Too many -B options"); +} - if( instr.a_hdrlen != 0x20 || instr.a_magic1 != 0x01 || - instr.a_magic2 != 0x03 || instr.a_magic4 != 0x10 ) +void append_file (filename, ftype) +char * filename; +int ftype; +{ + struct file_list * newfile = xalloc(sizeof(struct file_list)); + char * s; + char * name; + + newfile->file = copystr(filename); + name = copystr(filename); + + s = strrchr(name, '.'); + + if (ftype) { - writesn("Executable cannot be converted to OMAGIC - bad magics"); - return; + newfile->name = copystr(name); + newfile->filetype = ftype; + } + else if (s && s == name + strlen(name) - 2) { + newfile->filetype = s[1]; + *s = 0; + newfile->name = copystr(name); } + else + newfile->name = copystr(name); + free(name); - switch((int)(instr.a_magic3)) + if (newfile->filetype == 0) newfile->filetype = 'o'; /* Objects */ + + if (files==0) + files = newfile; + else { - case ELKS_MAG1: - break; - case ELKS_MAG2: - writesn("Executable cannot be converted to OMAGIC (compiled with -z)"); - return; - case ELKS_MAG3: - case ELKS_MAG4: - writesn("Executable file is split I/D, data overlaps text"); - return; - default: - writesn("Executable cannot be converted to OMAGIC (unknown type)"); - return; + struct file_list * fptr; + for(fptr=files; fptr->next; fptr=fptr->next); + fptr->next = newfile; } +} - if( instr.a_syms != 0 ) - writesn("Warning: executable file isn't stripped"); - - memcpy(outstr.a_info, AOUT_MAG, 4); - outstr.a_text = instr.a_text; - outstr.a_data = instr.a_data; - outstr.a_bss = instr.a_bss; - outstr.a_entry= instr.a_entry; +void +append_option (option, otype) +char * option; +int otype; +{ + struct opt_list * newopt = xalloc(sizeof(struct opt_list)); - lseek(fd, 0L, 0); + newopt->opt = copystr(option); + newopt->opttype = otype; - if( write(fd, &outstr, sizeof(outstr)) != sizeof(outstr) ) + if (options==0) + options = newopt; + else { - writesn("Cannot re-write executable header"); - return; + struct opt_list * optr; + for(optr=options; optr->next; optr=optr->next); + optr->next = newopt; } +} + +char * expand_tilde(str) +char * str; +{ + char * newstr; + char * ptr = strchr(str, '~'); + if( ptr == 0 ) return copystr(str); + + newstr = xalloc(strlen(str)+strlen(localprefix)); + if( ptr!=str ) memcpy(newstr, str, ptr-str); + strcpy(newstr+(ptr-str), localprefix); + strcat(newstr, ptr+1); + return newstr; +} + +void * +xalloc (size) +int size; +{ + void * p = malloc(size); + if (!p) fatal("Out of memory"); + memset(p, '\0', size); + return p; +} + +void Usage() +{ + fatal("Usage: bcc [-ansi] [-options] [-o output] file [files]"); +} - close(fd); +void fatal(str) +char * str; +{ + fprintf(stderr, "%s: Fatal error: %s.\n", progname, str); + exit(1); } #ifdef L_TREE #ifdef MSDOS -PRIVATE void reset_localprefix() +void reset_localprefix() { char *ptr, *temp; - temp = stralloc(progname); + temp = copystr(progname); if( (ptr = strrchr(temp, '\\')) != 0 && temp 2) - { - show_who("localprefix is now "); - writesn(localprefix); - } } else free(temp); } #else -PRIVATE void reset_localprefix() +void reset_localprefix() { char *ptr, *temp; if( *progname == '/' ) - temp = stralloc(progname); + temp = copystr(progname); else { char * s, * d; ptr = getenv("PATH"); if( ptr==0 || *ptr == 0 ) return; - ptr = stralloc(ptr); - temp = stralloc(""); + ptr = copystr(ptr); + temp = copystr(""); for(d=s=ptr; d && *s; s=d) { @@ -970,14 +1030,14 @@ PRIVATE void reset_localprefix() free(temp); d=strchr(s, ':'); if( d ) *d='\0'; - temp = my_malloc(strlen(progname)+strlen(s)+2, "prefixing"); + temp = xalloc(strlen(progname)+strlen(s)+2); strcpy(temp, s); strcat(temp, "/"); strcat(temp, progname); if( realpath(temp, buf) != 0 ) { free(temp); - temp = stralloc(buf); + temp = copystr(buf); } if( access(temp, X_OK) == 0 ) break; d++; @@ -985,7 +1045,7 @@ PRIVATE void reset_localprefix() if( s == 0 ) { free(temp); - temp = stralloc(progname); + temp = copystr(progname); } free(ptr); } @@ -995,11 +1055,6 @@ PRIVATE void reset_localprefix() { ptr[-4] = 0; localprefix = temp; - if (verbosity > 2) - { - show_who("localprefix is now "); - writesn(localprefix); - } } else free(temp); @@ -1007,355 +1062,71 @@ PRIVATE void reset_localprefix() #endif #endif -PRIVATE char * expand_tilde(str, canfree) -char * str; -int canfree; -{ - char * newstr; - char * ptr = strchr(str, '~'); - if( ptr == 0 ) return str; - - newstr = my_malloc(strlen(str)+strlen(localprefix), "expand tilde"); - if( ptr!=str ) memcpy(newstr, str, ptr-str); - strcpy(newstr+(ptr-str), localprefix); - strcat(newstr, ptr+1); - if( canfree ) free(str); - return newstr; -} -PRIVATE void adddefine(arg) -char *arg; +void +run_command(file) +struct file_list * file; { -#ifndef CCC - addarg(&ccargs, arg); +#ifdef __BCC__ +static char ** minienviron[] = { + "PATH=/bin:/usr/bin", + "SHELL=/bin/sh", + 0 +}; #endif - addarg(&cppargs, arg); -} - -PRIVATE void addarg(argp, arg) -register struct arg_s *argp; -char *arg; -{ - int new_argc; - char **new_argv; - - if (argp->nr_allocated == 0) - startarg(argp); - new_argc = argp->argc + 1; - if (new_argc >= argp->nr_allocated) - { - argp->nr_allocated += ALLOC_UNIT; - new_argv = realloc(argp->argv, argp->nr_allocated * sizeof *argp->argv); - if (new_argv == NUL_PTR) - outofmemory("addarg"); - argp->argv = new_argv; - } - argp->argv[argp->argc] = expand_tilde(arg, 0); - argp->argv[argp->argc = new_argc] = NUL_PTR; -} - -PRIVATE void addprefix(prefix, name) -struct prefix_s *prefix; -char *name; -{ - struct prefix_s *new_prefix; - - if (prefix->name == NUL_PTR) - prefix->name = name; - else - { - new_prefix = my_malloc(sizeof *new_prefix, "addprefix"); - new_prefix->name = expand_tilde(name, 0); - new_prefix->next = NUL_PTR; - while (prefix->next != NUL_PTR) - prefix = prefix->next; - prefix->next = new_prefix; - } -} - -PRIVATE void fatal(message) -char *message; -{ - writesn(message); - killtemps(); - exit(1); -} - -PRIVATE char *fixpath(path, prefix, mode) -char *path; -struct prefix_s *prefix; -int mode; -{ - char *ppath; - - for (; prefix != NUL_PTR; prefix = prefix->next) - { - if (verbosity > 2) - { - show_who("searching for "); - if (mode == R_OK) - writes("readable file "); - else - writes("executable file "); - } - ppath = expand_tilde(stralloc2(prefix->name, path), 1); - if (verbosity > 2) - writes(ppath); - if (access(ppath, mode) == 0) - { - if (verbosity > 2) - writesn(" - found."); - return ppath; - } - if (verbosity > 2) - writesn(" - nope."); - free(ppath); - } - return path; -} - -PRIVATE void killtemps() -{ - while (tmpargs.argc > START_ARGS) - my_unlink(tmpargs.argv[--tmpargs.argc]); -} - -PRIVATE void *my_malloc(size, where) -unsigned size; -char *where; -{ - void *block; - - if ((block = malloc(size)) == NUL_PTR) - outofmemory(where); - return block; -} - -PRIVATE char *my_mktemp() -{ - char *p; - unsigned digit; - unsigned digits; - char *template; - static unsigned tmpnum; - -#ifdef MSDOS - digits = 42; - p = template = stralloc2(tmpdir, "/$$YYYYXX"); -#else - digits = getpid(); - p = template = stralloc2(tmpdir, "/bccYYYYXXXX"); + int i, status; +#ifndef MSDOS + void *oqsig, *oisig, *otsig, *ocsig; #endif - p += strlen(p); - - while (*--p == 'X') - { - if ((digit = digits % 16) > 9) - digit += 'A' - ('9' + 1); - *p = digit + '0'; - digits /= 16; - } - digits = tmpnum; - while (*p == 'Y') - { - if ((digit = digits % 16) > 9) - digit += 'A' - ('9' + 1); - *p-- = digit + '0'; - digits /= 16; - } - ++tmpnum; - addarg(&tmpargs, template); - return template; -} -PRIVATE void my_unlink(name) -char *name; -{ - if (verbosity > 1) - { - show_who("unlinking "); - writesn(name); - } - if (verbosity > 4) return; - if (unlink(name) < 0) - { - if( !runerror || verbosity > 1) - { - show_who("error unlinking "); - writesn(name); - runerror = TRUE; - } - } -} -PRIVATE void outofmemory(where) -char *where; -{ - show_who("out of memory in "); - fatal(where); -} + if (opt_v) + { + fprintf(stderr, "%s", command.fullpath); + for(i=1; command.arglist[i]; i++) + fprintf(stderr, " %s", command.arglist[i]); + fprintf(stderr, "\n"); + if (opt_v>2) return; + } -PRIVATE int run(in_name, out_name, argp) -char *in_name; -char *out_name; -struct arg_s *argp; -{ - int arg0; - int i; - int status; - - arg0 = 0; - if (in_name == NUL_PTR) - ++arg0; - if (out_name == NUL_PTR) - arg0 += 2; - else if (argp->minus_O_broken) - ++arg0; - if (argp->nr_allocated == 0) - startarg(argp); - argp->argv[arg0] = argp->prog; - i = arg0 + 1; - if (in_name != NUL_PTR) - argp->argv[i++] = in_name; - if (out_name != NUL_PTR) - { - if (!argp->minus_O_broken) - argp->argv[i++] = "-o"; - argp->argv[i++] = out_name; - } - if (verbosity != 0) - { - for (i = arg0; i < argp->argc; ++i) - { - writes(argp->argv[i]); - writes(" "); - } - writen(); - } - if (verbosity > 4 ) return 0; #ifdef MSDOS - status = spawnv(0, argp->prog, argp->argv+arg0); - if( status<0 ) - { - show_who("spawn of "); - writes(argp->prog); - writesn(" failed"); - } + status = spawnv(0, command.fullpath, command.arglist); + if (status<0) + { + fprintf(stderr, "Unable to execute %s\n", command.fullpath); + } #else - switch (fork()) - { - case -1: - show_who("fork failed"); - fatal(""); - case 0: + oqsig = signal(SIGQUIT, SIG_IGN); + oisig = signal(SIGINT, SIG_IGN); + otsig = signal(SIGTERM, SIG_IGN); + ocsig = signal(SIGCHLD, SIG_DFL); + + switch(fork()) + { + case -1: + fatal("Forking failure"); + case 0: #ifdef __BCC__ - execve(argp->prog, argp->argv + arg0, minienviron); + execve(command.fullpath, command.arglist, minienviron); #else - execv(argp->prog, argp->argv + arg0); -#endif - show_who("exec of "); - writes(argp->prog); - fatal(" failed"); - default: - wait(&status); - if (status & 0xFF) - { - writes(argp->prog); - writesn(": killed by fatal signal"); - } - } + execv(command.fullpath, command.arglist); #endif - for (i = tmpargs.argc - 1; i >= START_ARGS; --i) - if (in_name == tmpargs.argv[i]) - { - my_unlink(in_name); - --tmpargs.argc; - memmove(tmpargs.argv + i, tmpargs.argv + i + 1, - (tmpargs.argc - i) * sizeof tmpargs.argv[0]); - tmpargs.argv[tmpargs.argc] = NUL_PTR; - break; - } - if (status != 0) - { - runerror = TRUE; - killtemps(); - } - return status; -} + fprintf(stderr, "Unable to execute %s.\n", command.fullpath); + exit(1); + default: + wait(&status); + if (status&0xFF) + { + fprintf(stderr, "%s: killed by signal %d\n", command.fullpath, (status&0xFF)); + } + } -PRIVATE void set_trap() -{ -#ifdef SIGINT - signal(SIGINT, trap); -#endif -#ifdef SIGQUIT - signal(SIGQUIT, trap); -#endif -#ifdef SIGTERM - signal(SIGTERM, trap); + (void) signal(SIGQUIT, oqsig); + (void) signal(SIGINT, oisig); + (void) signal(SIGTERM, otsig); + (void) signal(SIGCHLD, ocsig); #endif + if (status) + file->filetype = '~'; } -PRIVATE void show_who(message) -char *message; -{ -#ifdef MSDOS - char * ptr; - ptr = strrchr(progname, '\\'); - if(ptr) ptr++; else ptr = progname; - writes(ptr); -#else - writes(progname); -#endif - writes(": "); - writes(message); -} - -PRIVATE void startarg(argp) -struct arg_s *argp; -{ - argp->argv = my_malloc((argp->nr_allocated = ALLOC_UNIT) - * sizeof *argp->argv, "startarg"); - argp->argc = START_ARGS; - argp->argv[START_ARGS] = NUL_PTR; -} - -PRIVATE char *stralloc(s) -char *s; -{ - return strcpy(my_malloc(strlen(s) + 1, "stralloc"), s); -} - -PRIVATE char *stralloc2(s1, s2) -char *s1; -char *s2; -{ - return strcat(strcpy(my_malloc( - strlen(s1) + strlen(s2) + 1, "stralloc2"), s1), s2); -} - -PRIVATE void trap(signum) -int signum; -{ - signal(signum, SIG_IGN); - show_who("caught signal"); - fatal(""); -} - -PRIVATE void writen() -{ - writes("\n"); -} - -PRIVATE void writes(s) -char *s; -{ - write(2, s, strlen(s)); -} - -PRIVATE void writesn(s) -char *s; -{ - writes(s); - writen(); -} diff --git a/bcc/const.h b/bcc/const.h index 2383a30..a854685 100644 --- a/bcc/const.h +++ b/bcc/const.h @@ -25,6 +25,7 @@ #ifndef VERY_SMALL_MEMORY #define DEBUG /* generate compiler-debugging code */ +#define OPTIMISE /* include optimisation code */ #endif #ifdef I8088 diff --git a/bcc/function.c b/bcc/function.c index 6c84975..e3dcd61 100644 --- a/bcc/function.c +++ b/bcc/function.c @@ -270,7 +270,12 @@ PRIVATE void out_callstring() PUBLIC void popframe() { +#ifdef STUPIDFRAME + poplist(callee1mask); /*XXX: Add if round this */ + poplist(FRAMEREG); +#else poplist(frame1list); +#endif } #endif @@ -308,7 +313,7 @@ PUBLIC void reslocals() pushreg(FRAMEREG); regtransfer(STACKREG, FRAMEREG); framep = sp; - pushlist(callee1mask); + pushlist(callee1mask); /*XXX: Add if round this */ # else /* not STUPIDFRAME */ # ifdef CANHANDLENOFRAME if (stackarg || softsp != -frameregsize) /* args or locals */ diff --git a/bcc/gencode.h b/bcc/gencode.h index 03de445..6c3908b 100644 --- a/bcc/gencode.h +++ b/bcc/gencode.h @@ -52,6 +52,7 @@ EXTERN bool_t stackarg; /* nonzero to show function has arg on stack */ #endif EXTERN struct switchstruct *switchnow; /* currently active switch */ /* depends on NULL init */ +EXTERN bool_t optimise; /* nonzero to add optimisation code */ /* variables to be initialised to nonzero */ diff --git a/bcc/idcc b/bcc/idcc deleted file mode 100755 index 1dc25b9..0000000 --- a/bcc/idcc +++ /dev/null @@ -1,328 +0,0 @@ -#!/bin/ash -# -# This is a shell version of the bcc compiler driver. It's a little slower -# than a C version but overall seems to be a lot cleaner, perhaps a C version -# based on this might be a good idea ... -# -# The compiler works on a 'modal' basis certain flags given to it put the -# compiler into specific modes, it can only be in one mode for a run. -# -# The mode defines the basic passes and specific options that are available -# -# To define a mode see the functions 'run_0' and 'run_3' for examples. The -# variable assignments just above the definitions enable the functions. -# -# This script is specifically designed so the there is as little interaction -# between the modes as is possible. -# -# It's run using ash because this appears to be _much_ faster than bash, it's -# also reasonable with ksh. -# (On other interpreters I think perl would be too big, but awk might work...) -# - -TMPFIL="/tmp/cc$$" -trap "rm -f $TMPFIL.* ; exit 1" 1 2 3 15 -TMPCNT=0 - -FILES= -OPTS= -RESEXTN= -VERBOSE=no -MULTISRC=no - -LDOPTS= -DESTDEF=no -LDDEST=a.out -DEFMODE=0 - -ccmode= -LIBPATH="/lib:/usr/lib:/usr/bin" - -main() { - scanargs "$@" - - PATH="$LIBPATH:$PATH" - [ "$EXEC_PREFIX" != "" ] && PATH="$EXEC_PREFIX:$PATH" - - rv=0 - LDFILES= - [ "$MULTISRC" = yes -o "$RESEXTN" = "" ] && DESTDEF=no - - for FILE in $FILES - do - case "$FILE" in - *.c ) PASS=cpp ; BASE="`basename $FILE .c`" ;; - *.s ) PASS=as ; BASE="`basename $FILE .s`" ;; - * ) PASS=lnk ;; - esac - - NAME="`basename $FILE`" - DEST="`dirname $FILE`/" - [ "$DEST" = "./" ] && DEST= - DEST="$DEST$BASE.$RESEXTN" - [ "$DESTDEF" = yes ] && DEST="$LDDEST" - - STEMP=0 INTEMP=0 - [ "$PASS" = "cpp" ] && { compile $FILE || rv=$? ; } - [ "$PASS" = "as" ] && { assem $FILE || rv=$? ; } - if [ "$PASS" = "lnk" ] - then - LDFILES="$LDFILES $FILE" - else - # If there's a fail can't link - still assembling to temps tho. - [ "$RESEXTN" = "" ] && RESEXTN=O - fi - [ "$STEMP" = 1 ] && rm -f "$SFILE" - done - - [ "$RESEXTN" != "" ] && { - rm -f $TMPFIL.* - exit $rv - } - - [ "$VERBOSE" = yes ] && eval "echo \"$LINK\"" 1>&2 - eval "$LINK" - rv=$? - rm -f $TMPFIL.* - exit "$rv" -} - -scanargs() { - WILDOPT=no - - while [ "$#" -gt 0 ] - do - case "$1" in - -[DU]* ) CPPDEFS="$CPPDEFS $1" ;; - -B?* ) PATH="`echo '.$1:$PATH' | sed 's/...//'`" ;; - -I?* ) CPPFLAGS="$CPPFLAGS $1" ;; - -L?* ) LDOPTS="$LDOPTS $1" ;; - -o ) LDDEST="$2"; DESTDEF=yes ; shift ;; - -b ) . /usr/lib/idcc/opts_$2 || exit 1; shift ;; - -E ) RESEXTN=i ;; - -S ) RESEXTN=s ;; - -c ) RESEXTN=o ;; - -v ) VERBOSE=yes ;; - -l?* ) FILES="$FILES $1" ; MULTISRC=yes ;; - -* ) OPTS="$OPTS `echo .$1 | sed 's/..//'`" ;; - * ) [ "$FILES" != "" ] && MULTISRC=yes ; FILES="$FILES $1" ;; - esac - shift - done - - while [ "$OPTS" != "" -o "$DEFMODE" != "" ] - do - # So they can try again ... with DEFMODE if needed - MOPTS="$OPTS" - OPTS= - - for opt in $MOPTS - do - # Option can be defined only for specific mode so if we haven't seen - # the mode yet save the opt. If we have check for conflicts too. - [ "$ccmode" = "" -a "$DEFMODE" != "" ] && { - eval "[ \"\$opt_$opt\" = yes ]" || { OPTS="$OPTS $opt" ; opt= ; } - } - [ "$opt" != "" ] && { - [ "$ccmode" = "" ] || { - eval "[ \"\$mode_$opt\" = yes ]" && { - echo Option "-$opt incompatible with -$ccmode" 1>&2 - exit 2 - } - } - - eval "[ \"\$opt_$opt\" = yes ]" || { - { eval "[ \"$WILDOPT\" = yes ]" && wild_opt "-$opt" ; } || { - echo Option '-'$opt unknown for this mode 1>&2 - exit 3 - } - } - - eval "[ \"\$opt_$opt\" = yes ]" && run_$opt - eval "[ \"\$mode_$opt\" = yes ]" && ccmode="$opt" - } - done - [ "$ccmode" = "" -a "$DEFMODE" != "" ] && OPTS="$DEFMODE $OPTS" - DEFMODE= - done -} - -compile() { - [ -r "$FILE" ] || { echo "Cannot open $FILE" 1>&2 ; return 1 ; } - - # Loop for the pass list - # The CCX variables _are_ expanded again. - - ret=1 - for pass in $PASSLIST - do - for extn in '' res opt - do eval "CCX$extn=\"\$CC$pass$extn\"" - done - - [ "$CCX" = "" ] && continue; - - shuffel "$RESEXTN" $CCXres - [ "$VERBOSE" = yes ] && eval "echo \"$CCX\"" 1>&2 - eval "$CCX" || return 1 - ret=0 - [ "$CCXres" = "$RESEXTN" ] && break - done - [ "$ret" = 1 ] && { echo 'CC configuration error' 1>&2 ; return $ret ; } - - [ "$RESEXTN" != "$CCXres" ] && PASS=as - return 0 -} - -assem() { - [ -r "$FILE" ] || { echo "Cannot open $FILE" 1>&2 ; return 1 ; } - - shuffel "$RESEXTN" o - - n= - [ "$ASNAME" != "" ] && n="$ASNAME$NAME" - - [ "$VERBOSE" = yes ] && echo "$AS $ASFLAGS $n $SFILE -o $FILE" 1>&2 - $AS $ASFLAGS $n $SFILE -o $FILE || return - - [ "$RESEXTN" != "o" ] && PASS=lnk - return 0 -} - -if [ "2" = "$[1+1]" ] ; then inc_tmpcnt() { TMPCNT="$[$TMPCNT+1]" ; } -else inc_tmpcnt() { TMPCNT="`expr $TMPCNT + 1`" ; } -fi - -shuffel() { - [ "$STEMP" = 1 ] && rm -f "$SFILE" - - SFILE="$FILE" - STEMP="$INTEMP" - - if [ "$1" = "$2" ] - then - FILE="$DEST" - INTEMP=0 - else - inc_tmpcnt - FILE="$TMPFIL.$TMPCNT.$2" - INTEMP=1 - fi -} - -mode_0=yes opt_0=yes -run_0() -{ - SYSINC="-I/usr/bcc/include" - SYSLIB="-L/usr/bcc/lib/bcc/i86/" - LIBPATH="/usr/bcc/lib/bcc" - CRT0="-C0" - LIBS="-lc" - CGEN='-0' - DEFS= - - CPP="cpp" - - PASSLIST=2 - CC2='bcc-cc1 $SYSINC $DEFS $CPPDEFS $CPPFLAGS $CGEN $SFILE -o $FILE' - CC2res=s - AS="as86" ASFLAGS='-u -w -0' ASNAME='-n ' - LINK='ld86 $SYSLIB $LDOPTS $LDFLAGS -o $LDDEST $CRT0 $LDFILES $LIBS' - LDFLAGS='-i -0' - - [ "$RESEXTN" = "i" ] && { - PASSLIST="0" - CC0='bcc-cc1 $SYSINC $DEFS $CPPDEFS $CPPFLAGS $CGEN $SFILE -E' - CC0res=i - } - - opt_ansi=yes - run_ansi() - { - PASSLIST="0 1 2" - CC0='bcc-cc1 $SYSINC $DEFS $CPPDEFS $CPPFLAGS $CGEN $SFILE -o $FILE -E' - CC0res=k - CC1res=i CC1='unproto $SFILE $FILE' - CC2res=s CC2='bcc-cc1 $CGEN $SFILE -o $FILE' - DEFS='-D__STDC__=0' - } - opt_I=yes; run_I() { SYSINC= ; } - opt_L=yes; run_L() { SYSLIB= ; } - opt_O=yes; run_O() { echo Warning -O ignored 1>&2 ; } - opt_Mf=yes; run_Mf() { LIBS=-lc_f ; CGEN='-0 -f -c' ;} - opt_Md=yes; - run_Md() { LIBS=-ldos ; DEFS=$DEFS' -D__MSDOS__' LDFLAGS='-i -0 -d' ;} - - WILDOPT=yes - wild_opt() - { - case "$1" in - # For normal CC operation unknowns go to the linker. ie: - # * ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - # But do this instead. - -[dMizmts] ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - -[dMizmt]- ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - -T* ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - * ) return 1 ;; - esac - return 0 - } -} - -mode_3=yes opt_3=yes -run_3() -{ - SYSINC="-I/usr/bcc/include" - SYSLIB="-L/usr/bcc/lib/bcc/i386/" - LIBPATH="/usr/bcc/lib/bcc" - CRT0="-C0" - LIBS="-lc" - CGEN='-3' - DEFS= - - CPP="cpp" - - PASSLIST=2 - CC2='bcc-cc1 $SYSINC $DEFS $CPPDEFS $CPPFLAGS $CGEN $SFILE -o $FILE' - CC2res=s - AS="as86" ASFLAGS='-u -w -3' ASNAME='-n ' - LINK='ld86 $SYSLIB $LDOPTS $LDFLAGS -o $LDDEST $CRT0 $LDFILES $LIBS' - LDFLAGS='-3' - - [ "$RESEXTN" = "i" ] && { - PASSLIST="0" - CC0='bcc-cc1 $SYSINC $DEFS $CPPDEFS $CPPFLAGS $CGEN $SFILE -E' - CC0res=i - } - - opt_ansi=yes - run_ansi() - { - PASSLIST="0 1 2" - CC0='bcc-cc1 $SYSINC $DEFS $CPPDEFS $CPPFLAGS $CGEN $SFILE -o $FILE -E' - CC0res=k - CC1res=i CC1='unproto $SFILE $FILE' - CC2res=s CC2='bcc-cc1 $CGEN $SFILE -o $FILE' - DEFS='-D__STDC__=0' - } - opt_I=yes; run_I() { SYSINC= ; } - opt_L=yes; run_L() { SYSLIB= ; } - opt_O=yes; run_O() { echo Warning -O ignored 1>&2 ; } - - WILDOPT=yes - wild_opt() - { - case "$1" in - # For normal CC operation unknowns go to the linker. ie: - # * ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - # But do this instead. - -[dMizmts] ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - -[dMizmt]- ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - -T* ) LDFLAGS="$LDFLAGS $1" ; return 0 ;; - * ) return 1 ;; - esac - return 0 - } -} - -main "$@" diff --git a/bcc/input.c b/bcc/input.c index 5084663..080c7bc 100644 --- a/bcc/input.c +++ b/bcc/input.c @@ -509,6 +509,7 @@ char *argv[]; #endif case 't': /* print source code in asm output */ case 'w': /* watch location counter */ + case 'O': /* Optimisation. */ if (arg[2] == 0) flag[(int)arg[1]] = TRUE; else if (arg[2] == '-' && arg[3] == 0) @@ -597,6 +598,11 @@ ts_s_includelist += sizeof *incnew; definestring("__POS_INDEPENDENT__"); } #endif + if (flag['O']) + { + optimise = TRUE; + definestring("__OPTIMISED__"); + } #ifdef NOFLOAT definestring("__HAS_NO_FLOATS__"); #endif diff --git a/bcc/preproc.c b/bcc/preproc.c index 84262e6..62302e8 100644 --- a/bcc/preproc.c +++ b/bcc/preproc.c @@ -68,8 +68,11 @@ PRIVATE void asmcontrol() #endif asmmode = TRUE; + if (expect_statement) + return; + if (orig_cppmode) - outstr("#asm\n"); + outnstr("#asm"); else { outnstr("!BCC_ASM"); @@ -126,9 +129,9 @@ PRIVATE void asmcontrol() } #endif if (orig_cppmode) - outstr("#endasm"); /* nl is done by skipeol */ + outnstr("#endasm"); else - outstr("!BCC_ENDASM\n"); + outnstr("!BCC_ENDASM"); } /* blanksident() - return nonzero if at blanks followed by an identifier */ @@ -158,6 +161,13 @@ PRIVATE void control() char sname[NAMESIZE + 1]; sym_t ctlcase; struct symstruct *symptr; + if (ctext && asmmode) + { + comment(); + outudec(input.linenumber); + outbyte(' '); + outline(lineptr); + } sname[0] = '#'; /* prepare for bad control */ sname[1] = 0; @@ -188,7 +198,13 @@ PRIVATE void control() switch (ctlcase) { case ASMCNTL: - asmcontrol(); + if (asmmode) + { + if (ifstate.ifflag) + error(" bad control"); + } + else + asmcontrol(); break; case DEFINECNTL: define(); @@ -197,6 +213,11 @@ PRIVATE void control() elsecontrol(); break; case ENDASMCNTL: + if (!asmmode) + { + if (ifstate.ifflag) + error(" bad control"); + } asmmode = FALSE; break; case ENDIFCNTL: diff --git a/bcc/scan.c b/bcc/scan.c index 973bcab..b96093d 100644 --- a/bcc/scan.c +++ b/bcc/scan.c @@ -182,7 +182,10 @@ int asm_only; else { docontrol(); - break; +#ifndef ASM_BARE + virtual_nl = 1; +#endif + continue; } case SLASH: gch1(); @@ -431,7 +434,14 @@ PUBLIC void nextsym() static char lastch; register char *reglineptr; - while (TRUE) /* exit with short, fast returns */ + if (expect_statement && asmmode) + { + outnstr("!BCC_ASM"); + dumplocs(); + cppscan(1); + outnstr("!BCC_ENDASM"); + } + else while (TRUE) /* exit with short, fast returns */ { reglineptr = lineptr; while ((sym = SYMOFCHAR(*reglineptr)) == WHITESPACE) @@ -470,7 +480,13 @@ PUBLIC void nextsym() } else { + int old_asmmode = asmmode; docontrol(); + if (asmmode && !old_asmmode) + { + sym = SEMICOLON; + return; + } break; } case FLOATCONST: diff --git a/bcc/scan.h b/bcc/scan.h index 98db208..e318e9e 100644 --- a/bcc/scan.h +++ b/bcc/scan.h @@ -200,3 +200,6 @@ EXTERN struct symstruct *gsymptr; /* symbol ptr for last identifier */ EXTERN bool_t incppexpr; /* nonzero while scanning cpp expression */ EXTERN sym_t sym; /* current symbol */ extern sym_t symofchar[]; /* table to convert chars to their symbols */ +EXTERN bool_t expect_statement; /* If set #asm needs to clear the recursive + * pending operations. ie: if stmts. */ + diff --git a/bcc/state.c b/bcc/state.c index 620b553..c14ff7b 100644 --- a/bcc/state.c +++ b/bcc/state.c @@ -188,6 +188,7 @@ PUBLIC void compound() /* have just seen "{" */ #endif spmark = sp; newlevel(); + expect_statement++; decllist(); softsp &= alignmask; if (sym != RBRACE) /* no need for locals if empty compound */ @@ -195,6 +196,7 @@ PUBLIC void compound() /* have just seen "{" */ returnflag = FALSE; while (sym != RBRACE && sym != EOFSYM) statement(); + expect_statement--; oldlevel(); if (!returnflag) { @@ -233,17 +235,27 @@ PUBLIC void compound() /* have just seen "{" */ PRIVATE void doasm() { - lparen(); + if (sym == LPAREN) nextsym(); if (sym!=STRINGCONST) error("string const expected"); else { - nextsym(); - constant.value.s[charptr-constant.value.s]='\0'; outnstr("!BCC_ASM"); - outbyte('\t'); - outnstr(constant.value.s); + for(;;) + { + constant.value.s[charptr-constant.value.s]='\0'; + outbyte('\t'); + outnstr(constant.value.s); + /* XXX: Need to investigate: wasting memory? + * + * charptr = constant.value.s; + */ + + nextsym(); + if (sym == COMMA) nextsym(); + if (sym!=STRINGCONST) break; + } outnstr("!BCC_ENDASM"); - rparen(); + if (sym == RPAREN) nextsym(); semicolon(); } } @@ -718,6 +730,10 @@ more: nextsym(); doif(); break; + case ELSESYM: + error("unexpected else"); + nextsym(); + break; case WHILESYM: nextsym(); dowhile(); -- cgit v1.2.1