1 #include <stdio.h> 2 #include <stdarg.h> 3 #include <string.h> 4 5 #include "parser.h" 6 #include "log.h" 7 8 #define RAW(x...) log_write(6, x) 9 10 void DUMP(void) 11 { 12 #if 0 13 struct service *svc; 14 struct action *act; 15 struct command *cmd; 16 struct listnode *node; 17 struct listnode *node2; 18 struct socketinfo *si; 19 int n; 20 21 list_for_each(node, &service_list) { 22 svc = node_to_item(node, struct service, slist); 23 RAW("service %s\n", svc->name); 24 RAW(" class '%s'\n", svc->classname); 25 RAW(" exec"); 26 for (n = 0; n < svc->nargs; n++) { 27 RAW(" '%s'", svc->args[n]); 28 } 29 RAW("\n"); 30 for (si = svc->sockets; si; si = si->next) { 31 RAW(" socket %s %s 0%o\n", si->name, si->type, si->perm); 32 } 33 } 34 35 list_for_each(node, &action_list) { 36 act = node_to_item(node, struct action, alist); 37 RAW("on %s\n", act->name); 38 list_for_each(node2, &act->commands) { 39 cmd = node_to_item(node2, struct command, clist); 40 RAW(" %p", cmd->func); 41 for (n = 0; n < cmd->nargs; n++) { 42 RAW(" %s", cmd->args[n]); 43 } 44 RAW("\n"); 45 } 46 RAW("\n"); 47 } 48 #endif 49 } 50 51 void parse_error(struct parse_state *state, const char *fmt, ...) 52 { 53 va_list ap; 54 char buf[128]; 55 int off; 56 57 snprintf(buf, 128, "%s: %d: ", state->filename, state->line); 58 buf[127] = 0; 59 off = strlen(buf); 60 61 va_start(ap, fmt); 62 vsnprintf(buf + off, 128 - off, fmt, ap); 63 va_end(ap); 64 buf[127] = 0; 65 ERROR("%s", buf); 66 } 67 68 int next_token(struct parse_state *state) 69 { 70 char *x = state->ptr; 71 char *s; 72 73 if (state->nexttoken) { 74 int t = state->nexttoken; 75 state->nexttoken = 0; 76 return t; 77 } 78 79 for (;;) { 80 switch (*x) { 81 case 0: 82 state->ptr = x; 83 return T_EOF; 84 case '\n': 85 x++; 86 state->ptr = x; 87 return T_NEWLINE; 88 case ' ': 89 case '\t': 90 case '\r': 91 x++; 92 continue; 93 case '#': 94 while (*x && (*x != '\n')) x++; 95 if (*x == '\n') { 96 state->ptr = x+1; 97 return T_NEWLINE; 98 } else { 99 state->ptr = x; 100 return T_EOF; 101 } 102 default: 103 goto text; 104 } 105 } 106 107 textdone: 108 state->ptr = x; 109 *s = 0; 110 return T_TEXT; 111 text: 112 state->text = s = x; 113 textresume: 114 for (;;) { 115 switch (*x) { 116 case 0: 117 goto textdone; 118 case ' ': 119 case '\t': 120 case '\r': 121 x++; 122 goto textdone; 123 case '\n': 124 state->nexttoken = T_NEWLINE; 125 x++; 126 goto textdone; 127 case '"': 128 x++; 129 for (;;) { 130 switch (*x) { 131 case 0: 132 /* unterminated quoted thing */ 133 state->ptr = x; 134 return T_EOF; 135 case '"': 136 x++; 137 goto textresume; 138 default: 139 *s++ = *x++; 140 } 141 } 142 break; 143 case '\\': 144 x++; 145 switch (*x) { 146 case 0: 147 goto textdone; 148 case 'n': 149 *s++ = '\n'; 150 break; 151 case 'r': 152 *s++ = '\r'; 153 break; 154 case 't': 155 *s++ = '\t'; 156 break; 157 case '\\': 158 *s++ = '\\'; 159 break; 160 case '\r': 161 /* \ <cr> <lf> -> line continuation */ 162 if (x[1] != '\n') { 163 x++; 164 continue; 165 } 166 case '\n': 167 /* \ <lf> -> line continuation */ 168 state->line++; 169 x++; 170 /* eat any extra whitespace */ 171 while((*x == ' ') || (*x == '\t')) x++; 172 continue; 173 default: 174 /* unknown escape -- just copy */ 175 *s++ = *x++; 176 } 177 continue; 178 default: 179 *s++ = *x++; 180 } 181 } 182 return T_EOF; 183 } 184