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
DUMP(void)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
parse_error(struct parse_state * state,const char * fmt,...)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
next_token(struct parse_state * state)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