summaryrefslogtreecommitdiff
path: root/src/tools/lcc/src/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/lcc/src/input.c')
-rw-r--r--src/tools/lcc/src/input.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/tools/lcc/src/input.c b/src/tools/lcc/src/input.c
new file mode 100644
index 0000000..c2a084e
--- /dev/null
+++ b/src/tools/lcc/src/input.c
@@ -0,0 +1,135 @@
+#include "c.h"
+
+
+static void pragma(void);
+static void resynch(void);
+
+static int bsize;
+static unsigned char buffer[MAXLINE+1 + BUFSIZE+1];
+unsigned char *cp; /* current input character */
+char *file; /* current input file name */
+char *firstfile; /* first input file */
+unsigned char *limit; /* points to last character + 1 */
+char *line; /* current line */
+int lineno; /* line number of current line */
+
+void nextline(void) {
+ do {
+ if (cp >= limit) {
+ fillbuf();
+ if (cp >= limit)
+ cp = limit;
+ if (cp == limit)
+ return;
+ } else {
+ lineno++;
+ for (line = (char *)cp; *cp==' ' || *cp=='\t'; cp++)
+ ;
+ if (*cp == '#') {
+ resynch();
+ nextline();
+ }
+ }
+ } while (*cp == '\n' && cp == limit);
+}
+void fillbuf(void) {
+ if (bsize == 0)
+ return;
+ if (cp >= limit)
+ cp = &buffer[MAXLINE+1];
+ else
+ {
+ int n = limit - cp;
+ unsigned char *s = &buffer[MAXLINE+1] - n;
+ assert(s >= buffer);
+ line = (char *)s - ((char *)cp - line);
+ while (cp < limit)
+ *s++ = *cp++;
+ cp = &buffer[MAXLINE+1] - n;
+ }
+ if (feof(stdin))
+ bsize = 0;
+ else
+ bsize = fread(&buffer[MAXLINE+1], 1, BUFSIZE, stdin);
+ if (bsize < 0) {
+ error("read error\n");
+ exit(EXIT_FAILURE);
+ }
+ limit = &buffer[MAXLINE+1+bsize];
+ *limit = '\n';
+}
+void input_init(int argc, char *argv[]) {
+ static int inited;
+
+ if (inited)
+ return;
+ inited = 1;
+ main_init(argc, argv);
+ limit = cp = &buffer[MAXLINE+1];
+ bsize = -1;
+ lineno = 0;
+ file = NULL;
+ fillbuf();
+ if (cp >= limit)
+ cp = limit;
+ nextline();
+}
+
+/* pragma - handle #pragma ref id... */
+static void pragma(void) {
+ if ((t = gettok()) == ID && strcmp(token, "ref") == 0)
+ for (;;) {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\n' || *cp == 0)
+ break;
+ if ((t = gettok()) == ID && tsym) {
+ tsym->ref++;
+ use(tsym, src);
+ }
+ }
+}
+
+/* resynch - set line number/file name in # n [ "file" ] and #pragma ... */
+static void resynch(void) {
+ for (cp++; *cp == ' ' || *cp == '\t'; )
+ cp++;
+ if (limit - cp < MAXLINE)
+ fillbuf();
+ if (strncmp((char *)cp, "pragma", 6) == 0) {
+ cp += 6;
+ pragma();
+ } else if (*cp >= '0' && *cp <= '9') {
+ line: for (lineno = 0; *cp >= '0' && *cp <= '9'; )
+ lineno = 10*lineno + *cp++ - '0';
+ lineno--;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '"') {
+ file = (char *)++cp;
+ while (*cp && *cp != '"' && *cp != '\n')
+ cp++;
+ file = stringn(file, (char *)cp - file);
+ if (*cp == '\n')
+ warning("missing \" in preprocessor line\n");
+ if (firstfile == 0)
+ firstfile = file;
+ }
+ } else if (strncmp((char *)cp, "line", 4) == 0) {
+ for (cp += 4; *cp == ' ' || *cp == '\t'; )
+ cp++;
+ if (*cp >= '0' && *cp <= '9')
+ goto line;
+ if (Aflag >= 2)
+ warning("unrecognized control line\n");
+ } else if (Aflag >= 2 && *cp != '\n')
+ warning("unrecognized control line\n");
+ while (*cp)
+ if (*cp++ == '\n') {
+ if (cp == limit + 1)
+ nextline();
+ else
+ break;
+ }
+}
+