scc

simple C compiler
git clone git@git.2f30.org/scc.git
Log | Files | Refs | README | LICENSE

parser.c (2187B)


      1 static char sccsid[] = "@(#) ./as/parser.c";
      2 #include <ctype.h>
      3 #include <setjmp.h>
      4 #include <stdarg.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 #include "../inc/scc.h"
     10 #include "as.h"
     11 
     12 #define NARGS 20
     13 #define MAXLINE 100
     14 
     15 char *filename;
     16 int nerrors;
     17 jmp_buf recover;
     18 
     19 static unsigned lineno;
     20 
     21 void
     22 error(char *msg, ...)
     23 {
     24 	va_list va;
     25 
     26 	va_start(va, msg);
     27 	fprintf(stderr, "as:%s:%u: ", filename, lineno);
     28 	vfprintf(stderr, msg, va);
     29 	putc('\n', stderr);
     30 	nerrors++;
     31 	va_end(va);
     32 
     33 	if (nerrors == 10)
     34 		die("as: too many errors");
     35 	longjmp(recover, 1);
     36 }
     37 
     38 Node **
     39 getargs(char *s)
     40 {
     41 	Node **ap;
     42 	static Node *args[NARGS];
     43 
     44 	if (!s)
     45 		return NULL;
     46 
     47 	for (ap = args; ap < &args[NARGS-1]; ++ap) {
     48 		if ((*ap = expr(&s)) == NULL)
     49 			return args;
     50 	}
     51 	error("too many arguments in one instruction");
     52 }
     53 
     54 static char *
     55 field(char **oldp)
     56 {
     57 	char *s, *begin;
     58 	int c;
     59 
     60 	if ((begin = *oldp) == NULL)
     61 		return NULL;
     62 
     63 	for (s = begin; ; s++) {
     64 		switch (*s) {
     65 		case ';':
     66 			*s = '\0';
     67 		case '\0':
     68 			*oldp = NULL;
     69 			goto out_loop;
     70 		case '\t':
     71 			*s = '\0';
     72 			*oldp = s+1;
     73 			goto out_loop;
     74 		case '\'':
     75 			if (*++s == '\0' || *++s != '\'')
     76 				error("invalid character constant");
     77 			break;
     78 		case '"':
     79 			while ((c = *++s) && c != '"')
     80 				/* nothing */;
     81 			if (c == '\0')
     82 				error("unterminated string");
     83 			break;
     84 		}
     85 	}
     86 
     87 out_loop:
     88 	return (*begin != '\0') ? begin : NULL;
     89 }
     90 
     91 static int
     92 extract(char *s, struct line *lp)
     93 {
     94 	int r = 0;
     95 	size_t len;
     96 
     97 	if (lp->label = field(&s)) {
     98 		len = strlen(lp->label);
     99 		if (lp->label[len-1] == ':')
    100 			lp->label[len-1] = '\0';
    101 		r++;
    102 	}
    103 	if (lp->op = field(&s))
    104 		r++;
    105 	if (lp->args = field(&s))
    106 		r++;
    107 
    108 	if (s) {
    109 		while (isspace(*s))
    110 			++s;
    111 		if (*s != '\0' && *s != ';')
    112 			error("trailing characters at the end of the line");
    113 	}
    114 
    115 	return r;
    116 }
    117 
    118 int
    119 nextline(FILE *fp, struct line *lp)
    120 {
    121 	size_t n;
    122 	static char buff[MAXLINE];
    123 
    124 repeat:
    125 	if (!fgets(buff, sizeof(buff), fp))
    126 		return 0;
    127 
    128 	if (++lineno == 0)
    129 		die("as: file too long");
    130 
    131 	n = strlen(buff);
    132 	if (n == 0)
    133 		goto repeat;
    134 	if (buff[n-1] != '\n') {
    135 		error("line too long");
    136 		goto repeat;
    137 	}
    138 	buff[n-1] = '\0';
    139 	if (extract(buff, lp) == 0)
    140 		goto repeat;
    141 	return 1;
    142 }