1 #include "parser.h" 2 3 #include <stdarg.h> 4 #include <stdio.h> 5 #include <string.h> 6 7 #include "log.h" 8 9 void parse_error(struct parse_state *state, const char *fmt, ...) 10 { 11 va_list ap; 12 char buf[128]; 13 int off; 14 15 snprintf(buf, 128, "%s: %d: ", state->filename, state->line); 16 buf[127] = 0; 17 off = strlen(buf); 18 19 va_start(ap, fmt); 20 vsnprintf(buf + off, 128 - off, fmt, ap); 21 va_end(ap); 22 buf[127] = 0; 23 ERROR("%s", buf); 24 } 25 26 int next_token(struct parse_state *state) 27 { 28 char *x = state->ptr; 29 char *s; 30 31 if (state->nexttoken) { 32 int t = state->nexttoken; 33 state->nexttoken = 0; 34 return t; 35 } 36 37 for (;;) { 38 switch (*x) { 39 case 0: 40 state->ptr = x; 41 return T_EOF; 42 case '\n': 43 x++; 44 state->ptr = x; 45 return T_NEWLINE; 46 case ' ': 47 case '\t': 48 case '\r': 49 x++; 50 continue; 51 case '#': 52 while (*x && (*x != '\n')) x++; 53 if (*x == '\n') { 54 state->ptr = x+1; 55 return T_NEWLINE; 56 } else { 57 state->ptr = x; 58 return T_EOF; 59 } 60 default: 61 goto text; 62 } 63 } 64 65 textdone: 66 state->ptr = x; 67 *s = 0; 68 return T_TEXT; 69 text: 70 state->text = s = x; 71 textresume: 72 for (;;) { 73 switch (*x) { 74 case 0: 75 goto textdone; 76 case ' ': 77 case '\t': 78 case '\r': 79 x++; 80 goto textdone; 81 case '\n': 82 state->nexttoken = T_NEWLINE; 83 x++; 84 goto textdone; 85 case '"': 86 x++; 87 for (;;) { 88 switch (*x) { 89 case 0: 90 /* unterminated quoted thing */ 91 state->ptr = x; 92 return T_EOF; 93 case '"': 94 x++; 95 goto textresume; 96 default: 97 *s++ = *x++; 98 } 99 } 100 break; 101 case '\\': 102 x++; 103 switch (*x) { 104 case 0: 105 goto textdone; 106 case 'n': 107 *s++ = '\n'; 108 break; 109 case 'r': 110 *s++ = '\r'; 111 break; 112 case 't': 113 *s++ = '\t'; 114 break; 115 case '\\': 116 *s++ = '\\'; 117 break; 118 case '\r': 119 /* \ <cr> <lf> -> line continuation */ 120 if (x[1] != '\n') { 121 x++; 122 continue; 123 } 124 case '\n': 125 /* \ <lf> -> line continuation */ 126 state->line++; 127 x++; 128 /* eat any extra whitespace */ 129 while((*x == ' ') || (*x == '\t')) x++; 130 continue; 131 default: 132 /* unknown escape -- just copy */ 133 *s++ = *x++; 134 } 135 continue; 136 default: 137 *s++ = *x++; 138 } 139 } 140 return T_EOF; 141 } 142