summaryrefslogtreecommitdiff
path: root/as/readsrc.c
diff options
context:
space:
mode:
Diffstat (limited to 'as/readsrc.c')
-rw-r--r--as/readsrc.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/as/readsrc.c b/as/readsrc.c
new file mode 100644
index 0000000..f74db84
--- /dev/null
+++ b/as/readsrc.c
@@ -0,0 +1,340 @@
+#define MAXLINE 256 /* when this is made bigger, fix pfcc not
+ * to store the string length in a byte-
+ * sized variable */
+
+/* readsrc.c - read source files for assembler */
+
+#include "const.h"
+#include "type.h"
+#include "flag.h"
+#include "file.h"
+#include "globvar.h"
+#include "macro.h"
+#include "scan.h"
+#undef EXTERN
+#define EXTERN
+#include "source.h"
+
+#ifdef POSIX_HEADERS_MISSING
+#define O_RDONLY 0
+typedef long off_t;
+int close P((int fd));
+off_t lseek P((int fd, off_t offset, int whence));
+int open P((const char *path, int oflag, ...));
+int read P((int fd, void *buf, unsigned nbytes));
+#else
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+struct fcbstruct /* file control block structure */
+{
+ fd_t fd; /* file descriptor */
+ char *lineptr; /* current spot in line */
+ char *buf; /* start of buffer (after partial line) */
+ char *first; /* start of partial line before buf */
+ char *limit; /* end of used part of input buffer */
+ int blocksize; /* chars from last read and partial line flag */
+ struct fbufstruct *includer;/* buffer of file which included current one */
+};
+
+struct fbufstruct /* file buffer structure */
+{
+ struct fcbstruct fcb; /* status after opening an include sub-file */
+ char fpartline[MAXLINE + 1];/* buffer for partial line */
+ char fbuf[INBUFSIZE + 1]; /* buffer to read into */
+ char fname[1]; /* file name (variable length), 1 for null */
+};
+
+struct get_s /* to record included files */
+{
+ fd_t fd;
+ unsigned line;
+ off_t position;
+};
+
+PRIVATE char hid_filnambuf[FILNAMLEN + 1]; /* buffer for file name */
+
+PRIVATE struct get_s hid_getstak[MAXGET]; /* GET stack */
+PRIVATE struct get_s *getstak; /* ptr */
+
+PRIVATE struct fcbstruct input; /* current input file control block */
+ /* input.lineptr is not kept up to date */
+ /* input.fd depends on zero init */
+PRIVATE struct fbufstruct xyz;
+PRIVATE struct fbufstruct *inputbuf; /* current input file buffer */
+ /* its fcb only to date in includes */
+
+PRIVATE char hid_linebuf[LINLEN]; /* line buffer */
+PRIVATE char *maclinebuf;
+PRIVATE char *maclineptr;
+
+FORWARD void clearsource P((void));
+FORWARD void line_too_long P((void));
+
+PRIVATE void clearsource()
+{
+ input.includer = inputbuf;
+ inputbuf = &xyz;
+ input.first = input.limit = input.buf = inputbuf->fbuf;
+ *(lineptr = linebuf = input.first - 1) = EOLCHAR;
+ input.blocksize = 0;
+}
+
+PRIVATE void line_too_long()
+{
+ symname = linebuf + (LINLEN - 1); /* spot for the error */
+ error(LINLONG); /* so error is shown in column LINLEN - 1 */
+}
+
+/* initialise private variables */
+
+PUBLIC void initsource()
+{
+ filnamptr = hid_filnambuf;
+ getstak = hid_getstak + MAXGET;
+ clearsource(); /* sentinel to invoke blank skipping */
+}
+
+PUBLIC fd_t open_input(name)
+char *name;
+{
+ fd_t fd;
+
+ if ((unsigned) (fd = open(name, O_RDONLY)) > 255)
+ as_abort("error opening input file");
+ clearsource();
+ return fd;
+}
+
+/*
+ handle GET pseudo_op
+ stack state of current file, open new file and reset global state vars
+ file must be seekable for the buffer discard/restore method to work
+*/
+
+PUBLIC void pget()
+{
+#if OLD
+ if (infiln >= MAXGET)
+ error(GETOV);
+ else
+ {
+ skipline();
+ listline();
+ if (infiln != 0)
+ {
+ --getstak;
+ getstak->fd = infil;
+ getstak->line = linum;
+ getstak->position = lseek(infil, 0L, 1) - (inbufend - inbufptr);
+ ++infiln;
+ linum = 0;
+ infil = open_input(lineptr - 1);
+ }
+ }
+#else
+ as_abort("get/include pseudo-op not implemented");
+#endif
+}
+
+/* process end of file */
+/* close file, unstack old file if current one is included */
+/* otherwise switch pass 0 to pass 1 or exit on pass 2 */
+/* end of file may be from phyical end of file or an END statement */
+
+PUBLIC void pproceof()
+{
+ if (infiln != 0)
+ close(infil);
+ if (lineptr == linebuf)
+ list.current = FALSE; /* don't list line after last unless error */
+ if (infiln == infil0)
+ /* all conditionals must be closed before end of main file (not GETs) */
+ {
+ if (blocklevel != 0)
+ error(EOFBLOCK);
+ if (iflevel != 0)
+ error(EOFIF);
+ if (lcdata & UNDBIT)
+ error(EOFLC);
+ lcptr->data = lcdata;
+ lcptr->lc = lc;
+ }
+ /* macros must be closed before end of all files */
+ if (macload)
+ error(EOFMAC);
+ listline(); /* last line or line after last if error */
+ if (infiln != infil0)
+ {
+ infil = getstak->fd;
+ linum = getstak->line;
+ if (--infiln != 0)
+ lseek(infil, getstak->position, 0);
+ ++getstak;
+ }
+ else if (!pass)
+ {
+ pass = TRUE;
+ objheader(); /* while pass 1 data all valid */
+ binmbuf = 0; /* reset zero variables */
+ maclevel = iflevel = blocklevel =
+ totwarn = toterr = linum = macnum = 0;
+ initp1p2(); /* reset other varaiables */
+ binaryc = binaryg;
+#ifdef I80386
+ defsize = idefsize;
+#endif
+ list.current = list.global;
+ maclist.current = maclist.global;
+
+ warn.current = TRUE;
+ if (warn.semaphore < 0)
+ warn.current = FALSE;
+ if (infiln != 0)
+ infil = open_input(filnamptr);
+ binheader();
+ }
+ else
+ finishup();
+}
+
+/*
+ read 1 line of source.
+ Source line ends with '\n', line returned is null terminated without '\n'.
+ Control characters other than blank, tab and newline are discarded.
+ Long lines (length > LINLEN) are truncated, and an error is generated.
+ On EOF, calls pproceof(), and gets next line unless loading a macro.
+ This is where macro lines are recursively expanded.
+*/
+
+PUBLIC void readline()
+{
+ listpre = FALSE; /* not listed yet */
+ if (maclevel != 0)
+ {
+ register char *bufptr; /* hold *bufptr in a reg char variable */
+ register char *reglineptr; /* if possible (not done here) */
+ char *oldbufptr;
+ struct schain_s *parameters;
+ char paramnum;
+ unsigned int remaining; /* space remaining in line + 2 */
+ /* value 0 not used except for temp predec */
+ /* value 1 means error already gen */
+ /* values 1 and 2 mean no space */
+
+ for (; maclevel != 0;
+ macpar = macstak->parameters, ++macstak, --maclevel)
+ if (*(bufptr = macstak->text) != ETB)
+ /* nonempty macro, process it and return without continuing the for loop */
+ {
+ if (!macflag)
+ {
+ maclinebuf = linebuf;
+ maclineptr = lineptr;
+ macflag = TRUE;
+ }
+ remaining = LINLEN + 2;
+ lineptr = linebuf = reglineptr = hid_linebuf;
+ while (*bufptr++ != EOLCHAR)
+ {
+ if (bufptr[-1] == MACROCHAR && *bufptr >= '0' && *bufptr <= '9')
+ {
+ parameters = macstak->parameters;
+ for (paramnum = *bufptr++; paramnum-- != '0';)
+ if ((parameters = parameters->next) == NUL_PTR)
+ break;
+ if (parameters != NUL_PTR)
+ {
+ for (oldbufptr = bufptr, bufptr = parameters->string;
+ *bufptr++ != 0;)
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ break; /* forget rest, param on 1 line */
+ }
+ *reglineptr++ = bufptr[-1];
+ }
+ bufptr = oldbufptr;
+ }
+ }
+ else
+ {
+ if (--remaining <= 1)
+ {
+ if (remaining != 0)
+ line_too_long();
+ remaining = 1;
+ }
+ else
+ *reglineptr++ = bufptr[-1];
+ }
+ }
+ macstak->text = bufptr;
+ *reglineptr = EOLCHAR;
+ return;
+ }
+ }
+ if (macflag)
+ {
+ linebuf = maclinebuf;
+ lineptr = maclineptr;
+ macflag = FALSE;
+ }
+again:
+ ++linum;
+ ++lineptr; /* if eof, this is input.limit + 1 */
+ if (input.blocksize != 0) /* and this routine just resets eof */
+ {
+ if (lineptr < input.limit) /* move back partial line */
+ {
+ register char *col;
+
+ col = input.buf;
+ while ((*--col = *--input.limit) != EOLCHAR)
+ ;
+ input.first = col + 1;
+ ++input.limit;
+ input.blocksize = 0;
+ }
+ else /* may be non-terminated line, don't stop */
+ lineptr = input.limit;
+ }
+ if (lineptr == input.limit)
+ {
+ lineptr = input.first;
+ input.blocksize = read(infil, input.buf, INBUFSIZE);
+ if (input.blocksize < 0)
+ as_abort("error reading input");
+ if (input.blocksize == 0)
+ {
+ clearsource();
+ pproceof();
+ if (macload)
+ {
+ symname = lineptr;
+ return; /* macro not allowed across eof */
+ }
+ goto again;
+ }
+ input.first = input.buf;
+ *(input.limit = input.buf + input.blocksize) = EOLCHAR;
+ }
+ linebuf = lineptr;
+ if (lineptr >= input.limit)
+ *(lineptr = input.limit = input.buf) = EOLCHAR;
+}
+
+PUBLIC void skipline()
+{
+ register char *reglineptr;
+
+ reglineptr = lineptr - 1;
+ while (*reglineptr != EOLCHAR)
+ ++reglineptr;
+ lineptr = reglineptr;
+}