diff options
Diffstat (limited to 'bcc/input.c')
-rw-r--r-- | bcc/input.c | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/bcc/input.c b/bcc/input.c new file mode 100644 index 0000000..4cf699a --- /dev/null +++ b/bcc/input.c @@ -0,0 +1,771 @@ +/* input.c - input for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#define ARBITRARY_BACKSLASH_NEWLINES_NOT +#define INSERT_BACKSLASH_NEWLINES_NOT + +#include "const.h" +#include "types.h" +#include "gencode.h" +#include "output.h" +#include "os.h" +#include "sc.h" +#include "scan.h" +#include "table.h" + +#undef EXTERN +#define EXTERN +#include "input.h" + +#define INBUFSIZE 2048 + +struct fbufstruct /* file buffer structure */ +{ + struct fcbstruct fcb; /* status after opening an include sub-file */ + char *fname; /* file name */ + bool_t fname_malloced; /* nonzero if fname was malloced */ + char pushback[3]; /* allows pushback to 2 before start of fbuf + * XXX 3 chars before? + * XXX should do everything in fbuf */ + char fbuf[INBUFSIZE + 1]; /* buffer to read into */ +}; + +struct inclist /* list of include file directories */ +{ + char *incdirname; + struct inclist *incnext; +}; + +PRIVATE char filemacro[] = "__FILE__"; +PRIVATE struct inclist incabsolute; /* dummy list for absolute names */ + /* depends on zero (NULL) init */ +PRIVATE struct inclist incfirst; + /* begin include searches here for "" */ + /* at next in list for <> */ + /* -I directories are put in list */ + /* between first and last */ +PRIVATE struct inclist inclast = +{ +#ifdef DEFAULT_INCLUDE_DIR + DEFAULT_INCLUDE_DIR, +#endif + NULL, +}; +PRIVATE fastin_t inclevel; /* nest level of include files */ + /* depends on zero init */ +PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */ + /* its fcb only to date in includes */ + /* depends on zero (NULL) init */ +PRIVATE bool_t suppress_line_numbers; + +#ifdef ARBITRARY_BACKSLASH_NEWLINES +FORWARD void backslash P((void)); +#endif +FORWARD void definefile P((char *fname)); +FORWARD void inputinit P((char *fname, fd_t fd)); +FORWARD void leaveinclude P((void)); +FORWARD void usage P((void)); + +#ifdef ARBITRARY_BACKSLASH_NEWLINES +PRIVATE void backslash() +{ + static unsigned nbackslash; + + if (nbackslash != 0) + --nbackslash; +more: + ++nbackslash; + while (*(lineptr + 1) == '\\') + { + ++nbackslash; + ++lineptr; + } + if (*(lineptr + 1) != EOL) + { + if (--nbackslash != 0) + *--lineptr = '\\'; /* force look at current backslash again */ + return; + } + ch = *++lineptr; +more1: + if (!eof && lineptr >= input.limit) + skipeol(); + if (ch == EOL) + { + --nbackslash; + if (eof) + eofin("backslash-newline"); + else + { + skipeol(); + if (ch == EOL && !eof && lineptr >= input.limit) + skipeol(); +#ifdef COEOL /* XXX - this should go through specialchar() */ + if (ch == COEOL) + { + ch = *++lineptr; + if (ch == EOL && !eof && lineptr >= input.limit) + skipeol(); + } +#endif + } + if (ch == '\\') + goto more; + if (nbackslash != 0 && ch == EOL && !eof) + goto more1; + if (nbackslash != 0) + { + ch = *--lineptr = '\\'; + if (--nbackslash != 0) + ch = *--lineptr = '\\'; + } + return; + } + if (ch == '\\') + goto more; + if (ch == EOL && !eof) + goto more1; + ch = *--lineptr = '\\'; /* pushback */ + if (--nbackslash != 0) + ch = *--lineptr = '\\'; +} +#endif + +PUBLIC void closein() +{ +#ifdef FAKE_INBUFSIZE_1 + fclose(input.fp); +#else + close(input.fd); +#endif + while (inclevel != 0) + leaveinclude(); +} + +PRIVATE void definefile(fname) +char *fname; +{ + char *def; + + def = ourmalloc(sizeof filemacro - 1 + 2 + strlen(fname) + 1 + 1); + strcpy(def, filemacro); + strcat(def, "=\""); + strcat(def, fname); + strcat(def, "\""); + definestring(def); + ourfree(def); +} + +PUBLIC void errorloc() +{ + register struct fbufstruct *infbuf; + + if ((infbuf = inputbuf) == NULL) + return; + outstr(infbuf->fname); + outbyte(':'); + if (eof) + outstr("eof"); + else + { + outudec(input.linenumber); + outbyte('.'); + if (maclevel == 0) + outudec((unsigned) (lineptr - inputbuf->fbuf) - input.lineoffset); + else + { + outudec((unsigned) (savedlineptr() - inputbuf->fbuf) + - input.lineoffset); + outstr(" (macro level "); + outudec((unsigned) maclevel); + outbyte(')'); + } + } + infbuf->fcb.includer = input.includer; + while ((infbuf = infbuf->fcb.includer) != NULL) + { + outstr(" (from "); + outstr(infbuf->fname); + outbyte(':'); + outudec(infbuf->fcb.linenumber); + outbyte(')'); + } + outstr(": "); +} + +/* gch1() - get next char, advance ptr (only works on current line) */ + +PUBLIC void gch1() +{ + if (SYMOFCHAR(ch = *++lineptr) != SPECIALCHAR) + return; + specialchar(); +} + +/* process #include */ + +PUBLIC void include() +{ + char *dirnameptr; + char *dirnamend; + unsigned dirnamelen; + fd_t fd; + char *fnameptr; + char *fullnameptr; + struct inclist *incptr; + char terminator; + + while (blanksident()) + { + if ((gsymptr = findlorg(gsname)) == NULL || + gsymptr->flags != DEFINITION) + break; + entermac(); + } + if ((terminator = ch) == '<') + terminator = '>'; + else if (terminator != '"') + { + error("bad file name"); + return; + } + gch1(); + fnameptr = charptr; + while (TRUE) + { + if (ch == EOL) /* no escapes in file names */ + break; + if (ch == terminator) + { + gch1(); + break; + } + if (charptr >= chartop) + fnameptr = growobject(fnameptr, 1); +#ifdef TS +++ts_n_filename; +++ts_s_filename; +++ts_s_filename_tot; +#endif + *charptr++ = ch; + gch1(); + } + if (charptr >= chartop) + fnameptr = growobject(fnameptr, 1); +#ifdef TS +++ts_n_filename_term; +++ts_s_filename_term; +++ts_s_filename_tot; +#endif + *charptr++ = 0; + dirnamend = NULL; + if (isabspath(fnameptr, &ch)) + incptr = &incabsolute; + else + { + incptr = &incfirst; + if (terminator == '>') + incptr = incptr->incnext; + else + { + dirnameptr = inputbuf->fname; + if ((dirnamend = strrchr(dirnameptr, DIRCHAR)) == NULL) + incptr->incdirname = NULL; + else + { + *dirnamend = 0; + incptr->incdirname = dirnameptr; + } + } + } + do + { + if (incptr->incdirname == NULL) + { + fullnameptr = ourmalloc(strlen(fnameptr) + 1); +#ifdef TS +++ts_n_pathname; +ts_s_pathname += strlen(fnameptr) + 1; +ts_s_pathname_tot += strlen(fnameptr) + 1; +#endif + strcpy(fullnameptr, fnameptr); + } + else + { + dirnamelen = strlen(incptr->incdirname); + fullnameptr = ourmalloc(dirnamelen + (int) (charptr - fnameptr) + + 2); + /* 2 extra for null and maybe DIRCHAR */ +#ifdef TS +++ts_n_pathname; +ts_s_pathname += dirnamelen + (charptr - fnameptr) + 2; +ts_s_pathname_tot += dirnamelen + (charptr - fnameptr) + 2; +#endif + dirnameptr = fullnameptr + dirnamelen; + strcpy(fullnameptr, incptr->incdirname); + if (*fullnameptr != 0 && *(dirnameptr - 1) != DIRCHAR) + strcat(fullnameptr, DIRSTRING); + strcat(fullnameptr, fnameptr); + if (dirnamend != NULL) + { + *dirnamend = DIRCHAR; + dirnamend = NULL; + } + } + fd = open(fullnameptr, 0); + if (fd >= 0) + { +#ifdef TS +ts_s_filename_tot -= charptr - fnameptr; +#endif + charptr = fnameptr; + input.lineptr = lineptr; + inputbuf->fcb = input; + ++inclevel; /* XXX - will run out of memory before overflow */ + inputinit(fullnameptr, fd); + inputbuf->fname_malloced = TRUE; + return; + } +#ifdef TS +ts_s_pathname_tot -= strlen(fullnameptr) + 1; +#endif + ourfree(fullnameptr); + } + while ((incptr = incptr->incnext) != NULL); + + fullnameptr = ourmalloc(strlen(fnameptr) + 40); + strcpy(fullnameptr, "cannot find include file "); + strcat(fullnameptr, fnameptr); + error(fullnameptr); + ourfree(fullnameptr); + +#ifdef TS +ts_s_filename_tot -= charptr - fnameptr; +#endif + charptr = fnameptr; +} + +/* initialise current input file */ + +PRIVATE void inputinit(fname, fd) +char *fname; +fd_t fd; +{ + register struct fbufstruct *newinputbuf; + + /* don't allocate after saying input.includer = inputbuf (to save a reg) + * or an error in the alloc would cycle trying to print the include list + */ + newinputbuf = (struct fbufstruct *) ourmalloc(sizeof *inputbuf); +#ifdef TS +++ts_n_inputbuf; +ts_s_inputbuf += sizeof *inputbuf; +ts_s_inputbuf_tot += sizeof *inputbuf; +#endif + input.fd = fd; +#ifdef FAKE_INBUFSIZE_1 + input.fp = fdopen(fd, "r"); +#endif + input.linenumber = 0; + input.lineoffset = 0; + input.includer = inputbuf; + inputbuf = newinputbuf; + newinputbuf->fname = fname; + newinputbuf->fname_malloced = FALSE; + undefinestring(filemacro); + definefile(fname); + if (orig_cppmode && !suppress_line_numbers) + outcpplinenumber(1, fname, input.includer == NULL ? "" : " 1"); + *(input.limit = newinputbuf->fbuf) = EOL; + + /* dummy line so #include processing can start with skipline() */ + ch = *(lineptr = newinputbuf->fbuf - 1) = EOL; +} + +PUBLIC void linecontol() +{ +static char linename[32]; + char * ptr; + int i=0; + + blanks(); + input.linenumber = atoi(lineptr)-1; + while( SYMOFCHAR(ch) == INTCONST ) gch1(); + blanks(); + if( ch != '"' ) return; + for(ptr=lineptr+1; *ptr + && *ptr != EOL + && *ptr != '"' + && i<sizeof(linename)-1; i++, ptr++) + linename[i] = *ptr; + linename[i] = '\0'; + + if (inputbuf->fname_malloced) +{ +#ifdef TS +ts_s_pathname_tot -= strlen(inputbuf->fname) + 1; +#endif + ourfree(inputbuf->fname); +} + inputbuf->fname_malloced = FALSE; + inputbuf->fname = linename; + + ptr=lineptr; + undefinestring(filemacro); + definefile(inputbuf->fname); + ch = *(lineptr = ptr); +} + +/* switch from include file to file which included it */ + +PRIVATE void leaveinclude() +{ + --inclevel; + if (inputbuf->fname_malloced) +{ +#ifdef TS +ts_s_pathname_tot -= strlen(inputbuf->fname) + 1; +#endif + ourfree(inputbuf->fname); +} +#ifdef TS +ts_s_inputbuf_tot -= sizeof *inputbuf; +#endif + ourfree((char *) inputbuf); + close(input.fd); +#ifdef FAKE_INBUFSIZE_1 + fclose(input.fp); +#endif + inputbuf = input.includer; + input = inputbuf->fcb; + undefinestring(filemacro); + definefile(inputbuf->fname); + ch = *(lineptr = input.lineptr); + skipline(); + if (orig_cppmode && !suppress_line_numbers) + outcpplinenumber(input.linenumber, inputbuf->fname, " 2"); +} + +/* open input and output files and get options */ + +PUBLIC void openio(argc, argv) +int argc; +char *argv[]; +{ + register char *arg; + int argn; + fd_t fd; + char *fname; + struct inclist *incnew; + struct inclist *incptr; + bool_t flag[128]; + +#if 0 + lineptr = "\n"; /* empty line in case error message */ +#endif + fd = 0; /* standard input */ + memset(flag, 0, sizeof flag); + flag['3'] = sizeof (int) >= 4; + fname = "stdin"; + (incptr = &incfirst)->incnext = &inclast; + initout(); + for (argn = 1; argn < argc; ++argn) + { + arg = argv[argn]; + if (*arg != '-') + { + if (fd != 0) + fatalerror("more than one input file"); + fname = arg; + if ((fd = open(arg, 0)) < 0) + fatalerror("cannot open input"); + } + else + switch (arg[1]) + { +#ifdef I8088 + case '0': /* generate 16-bit code */ + case '3': /* generate 32-bit code */ +#endif + case 'c': /* caller saves */ +#ifdef DEBUG + case 'd': /* print debugging information in asm output */ +#endif + case 'E': /* acting as cpp */ + case 'f': /* pass first argument in register */ +#ifdef DYNAMIC_LONG_ORDER + case 'l': /* long big-endian */ +#endif + case 'P': /* if acting as cpp, suppress line numbers */ +#ifdef POSINDEPENDENT + case 'p': /* generate almost-position-independent code */ +#endif + case 't': /* print source code in asm output */ + case 'w': /* watch location counter */ + if (arg[2] == 0) + flag[(int)arg[1]] = TRUE; + else if (arg[2] == '-' && arg[3] == 0) + flag[(int)arg[1]] = FALSE; + else + usage(); + if (arg[1] == '0') /* flag 0 is negative logic flag 3 */ + flag['3'] = TRUE + FALSE - flag['0']; + break; + case 'D': + definestring(arg + 2); + break; + case 'I': + (incnew = (struct inclist *) ourmalloc(sizeof *incnew)) + ->incdirname = arg + 2; +#ifdef TS +++ts_n_includelist; +ts_s_includelist += sizeof *incnew; +#endif + incnew->incnext = incptr->incnext; + incptr = incptr->incnext = incnew; + break; + case 'U': + undefinestring(arg + 2); + break; + case 'o': + if (arg[2] != 0 || ++argn >= argc) + usage(); + openout(argv[argn]); + break; + default: + usage(); + break; + } + } +#ifdef I8088 + if (flag['3']) + { + i386_32 = TRUE; + definestring("__AS386_32__"); + } + else + definestring("__AS386_16__"); +#endif +#ifdef MC6809 + definestring("__AS09__"); +#endif + if (flag['c']) + { + callersaves = TRUE; + definestring("__CALLER_SAVES__"); + } +#ifdef DEBUG + debugon = flag['d']; +#endif + orig_cppmode = cppmode = flag['E']; + if (flag['f']) + { + arg1inreg = TRUE; +#ifdef I8088 + definestring("__FIRST_ARG_IN_AX__"); +#endif +#ifdef MC6808 + definestring("__FIRST_ARG_IN_X__"); +#endif + } + arg1op = arg1inreg ? ROOTLISTOP : LISTOP; +#ifdef DYNAMIC_LONG_ORDER + if (flag['l']) + { + long_big_endian = TRUE; + definestring("__LONG_BIG_ENDIAN__"); + } +#endif + suppress_line_numbers = flag['P']; +#ifdef POSINDEPENDENT + if (flag['p']) + { + posindependent = TRUE; + definestring("__POS_INDEPENDENT__"); + } +#endif + ctext = flag['t']; + watchlc = flag['w']; + setoutbufs(); + inputinit(fname, fd); +} + +/* advance over EOL sentinel to new line */ + +PUBLIC void skipeol() +{ +#ifdef FAKE_INBUFSIZE_1 + static int ich; +#endif +#ifdef INSERT_BACKSLASH_NEWLINES + static int bs_state; + static bool_t skip_printing_nl; +#endif + int nread; + + if (eof) + return; + if (lineptr < input.limit) + { + ++input.linenumber; + ch = *++lineptr; + if (ctext && !asmmode) + { + comment(); + outudec(input.linenumber); + outbyte(' '); + outline(lineptr); + } + if (orig_cppmode && !asmmode) +#ifdef INSERT_BACKSLASH_NEWLINES + if (!skip_printing_nl) +#endif + + outbyte('\n'); +#ifdef INSERT_BACKSLASH_NEWLINES + if (bs_state == 1 && *(lineptr - 1) == EOL) +#endif + input.lineoffset = (int) (lineptr - inputbuf->fbuf); + return; + } + input.lineoffset -= (int) (lineptr - inputbuf->fbuf); +#ifdef FAKE_INBUFSIZE_1 + lineptr = inputbuf->fbuf; +#ifdef INSERT_BACKSLASH_NEWLINES + switch (bs_state) + { +case0: + case 0: + bs_state = nread = (ich = getc(input.fp)) == EOF ? 0 : 1; + skip_printing_nl = FALSE; + break; + case 1: + if (ich == '\\') + goto case0; /* avoid chance of splitting \EOL */ + ich = '\\'; + nread = 1; + bs_state = 2; + ++input.lineoffset; + break; + case 2: + ich = EOL; + nread = 1; + bs_state = 0; + skip_printing_nl = TRUE; + ++input.lineoffset; + --input.linenumber; + break; + } +#else + nread = (ich = getc(input.fp)) == EOF ? 0 : 1; +#endif + *lineptr = ich; +#else + nread = read(input.fd, lineptr = inputbuf->fbuf, INBUFSIZE); +#endif + if (nread < 0) + fatalerror("input error"); + *(input.limit = lineptr + nread) = EOL; + ch = *lineptr; + if (nread == 0) + { + if (inclevel == 0) + { + eof = TRUE; + checknotinif(); + } + else + { + leaveinclude(); + skipeol(); + } + return; + } + if (ctext && !asmmode) + { + comment(); + outudec(input.linenumber); + outbyte(' '); + outline(lineptr); + } +} + +PUBLIC void specialchar() +{ + if (maclevel != 0) + { + if (ch == EOL) /* it might also be backslash or COEOL */ + leavemac(); + if (ch != EOL) + return; + } +more: +#ifdef ARBITRARY_BACKSLASH_NEWLINES + if (ch == '\\') + backslash(); +#endif + if (!eof && lineptr >= input.limit) + { + skipeol(); +#ifdef ARBITRARY_BACKSLASH_NEWLINES + if (ch == '\\') + backslash(); +#endif + } +#ifndef ARBITRARY_BACKSLASH_NEWLINES + if (ch == '\\') + { + if (*(lineptr + 1) == EOL) + { + if (lineptr + 1 >= input.limit) + { + ++lineptr; + skipeol(); + ch = *--lineptr = '\\'; /* pushback */ + } + if (*(lineptr + 1) == EOL) + { + if (eof) + eofin("backslash-newline"); + else + { + ++lineptr; + skipeol(); + if (SYMOFCHAR(ch) == SPECIALCHAR) + { +#ifdef COEOL + if (ch != COEOL + || SYMOFCHAR(ch = *++lineptr) == SPECIALCHAR) +#endif + goto more; + } + } + } + } +#endif + } +#ifdef COEOL + if (ch == EOL && !eof) + { + if (*(lineptr + 1) == EOL && lineptr + 1 >= input.limit) + { + ++lineptr; + skipeol(); /* refill buffer */ + ch = *--lineptr = EOL; /* pushback */ + } + if (*(lineptr + 1) == COEOL) + *++lineptr = EOL; /* discard COEOL */ + } +#endif +} + +PRIVATE void usage() +{ + fatalerror( +#ifdef MC6809 +"usage: cc1 [-cdfptw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]"); +#else +"usage: cc1 [-03cdfltw[-]] [-Ddefine] [-Iincdir] [-Uundef] [-o outfile] [infile]"); +#endif +} |