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 }