Mercurial > ~dholland > hg > tradcpp > index.cgi
comparison directive.c @ 64:f50b4ea6cbfe
Prune single-line comments from (most) directive lines.
Also, don't pass the string length to the directive processing
functions, as half of them weren't honoring it. Instead, ensure that
the directive line is terminated at the place the directive processing
functions should stop looking at it.
author | David A. Holland |
---|---|
date | Sun, 31 Mar 2013 02:04:56 -0400 |
parents | 90c6052410ce |
children | f8507e5ed84c |
comparison
equal
deleted
inserted
replaced
63:5e24746d8335 | 64:f50b4ea6cbfe |
---|---|
55 //////////////////////////////////////////////////////////// | 55 //////////////////////////////////////////////////////////// |
56 // common parsing bits | 56 // common parsing bits |
57 | 57 |
58 static | 58 static |
59 void | 59 void |
60 uncomment(char *buf) | |
61 { | |
62 char *s, *t, *u = NULL; | |
63 bool incomment = false; | |
64 | |
65 for (s = t = buf; *s; s++) { | |
66 if (incomment) { | |
67 if (s[0] == '*' && s[1] == '/') { | |
68 s++; | |
69 incomment = false; | |
70 } | |
71 } else { | |
72 if (s[0] == '/' && s[1] == '*') { | |
73 incomment = true; | |
74 } else { | |
75 if (t != s) { | |
76 *t = *s; | |
77 } | |
78 if (!strchr(ws, *t)) { | |
79 u = t; | |
80 } | |
81 t++; | |
82 } | |
83 } | |
84 } | |
85 if (u) { | |
86 /* end string after last non-whitespace char */ | |
87 u[1] = '\0'; | |
88 } else { | |
89 *t = '\0'; | |
90 } | |
91 } | |
92 | |
93 static | |
94 void | |
60 oneword(const char *what, struct place *p2, char *line) | 95 oneword(const char *what, struct place *p2, char *line) |
61 { | 96 { |
62 size_t pos; | 97 size_t pos; |
63 | 98 |
64 pos = strcspn(line, ws); | 99 pos = strcspn(line, ws); |
117 ifstate_destroy(is); | 152 ifstate_destroy(is); |
118 } | 153 } |
119 | 154 |
120 static | 155 static |
121 void | 156 void |
122 d_if(struct place *p, struct place *p2, char *line, size_t len) | 157 d_if(struct place *p, struct place *p2, char *line) |
123 { | 158 { |
124 char *expr; | 159 char *expr; |
125 bool val; | 160 bool val; |
126 struct place p3 = *p2; | 161 struct place p3 = *p2; |
127 | 162 |
128 expr = macroexpand(p2, line, len, true); | 163 uncomment(line); |
164 expr = macroexpand(p2, line, strlen(line), true); | |
129 val = eval(&p3, expr); | 165 val = eval(&p3, expr); |
130 ifstate_push(p, val); | 166 ifstate_push(p, val); |
131 dostrfree(expr); | 167 dostrfree(expr); |
132 } | 168 } |
133 | 169 |
134 static | 170 static |
135 void | 171 void |
136 d_ifdef(struct place *p, struct place *p2, char *line, size_t len) | 172 d_ifdef(struct place *p, struct place *p2, char *line) |
137 { | 173 { |
174 uncomment(line); | |
138 oneword("#ifdef", p2, line); | 175 oneword("#ifdef", p2, line); |
139 ifstate_push(p, macro_isdefined(line)); | 176 ifstate_push(p, macro_isdefined(line)); |
140 } | 177 } |
141 | 178 |
142 static | 179 static |
143 void | 180 void |
144 d_ifndef(struct place *p, struct place *p2, char *line, size_t len) | 181 d_ifndef(struct place *p, struct place *p2, char *line) |
145 { | 182 { |
183 uncomment(line); | |
146 oneword("#ifndef", p2, line); | 184 oneword("#ifndef", p2, line); |
147 ifstate_push(p, !macro_isdefined(line)); | 185 ifstate_push(p, !macro_isdefined(line)); |
148 } | 186 } |
149 | 187 |
150 static | 188 static |
151 void | 189 void |
152 d_elif(struct place *p, struct place *p2, char *line, size_t len) | 190 d_elif(struct place *p, struct place *p2, char *line) |
153 { | 191 { |
154 char *expr; | 192 char *expr; |
155 struct place p3 = *p2; | 193 struct place p3 = *p2; |
156 | 194 |
157 if (ifstate->seenelse) { | 195 if (ifstate->seenelse) { |
160 } | 198 } |
161 | 199 |
162 if (ifstate->evertrue) { | 200 if (ifstate->evertrue) { |
163 ifstate->curtrue = false; | 201 ifstate->curtrue = false; |
164 } else { | 202 } else { |
165 expr = macroexpand(p2, line, len, true); | 203 uncomment(line); |
204 expr = macroexpand(p2, line, strlen(line), true); | |
166 ifstate->curtrue = eval(&p3, expr); | 205 ifstate->curtrue = eval(&p3, expr); |
167 ifstate->evertrue = ifstate->curtrue; | 206 ifstate->evertrue = ifstate->curtrue; |
168 dostrfree(expr); | 207 dostrfree(expr); |
169 } | 208 } |
170 } | 209 } |
171 | 210 |
172 static | 211 static |
173 void | 212 void |
174 d_else(struct place *p, struct place *p2, char *line, size_t len) | 213 d_else(struct place *p, struct place *p2, char *line) |
175 { | 214 { |
176 if (ifstate->seenelse) { | 215 if (ifstate->seenelse) { |
177 complain(p, "Multiple #else directives in one conditional"); | 216 complain(p, "Multiple #else directives in one conditional"); |
178 complain_fail(); | 217 complain_fail(); |
179 } | 218 } |
183 ifstate->seenelse = true; | 222 ifstate->seenelse = true; |
184 } | 223 } |
185 | 224 |
186 static | 225 static |
187 void | 226 void |
188 d_endif(struct place *p, struct place *p2, char *line, size_t len) | 227 d_endif(struct place *p, struct place *p2, char *line) |
189 { | 228 { |
190 if (ifstate->prev == NULL) { | 229 if (ifstate->prev == NULL) { |
191 complain(p, "Unmatched #endif"); | 230 complain(p, "Unmatched #endif"); |
192 complain_fail(); | 231 complain_fail(); |
193 } else { | 232 } else { |
198 //////////////////////////////////////////////////////////// | 237 //////////////////////////////////////////////////////////// |
199 // macros | 238 // macros |
200 | 239 |
201 static | 240 static |
202 void | 241 void |
203 d_define(struct place *p, struct place *p2, char *line, size_t len) | 242 d_define(struct place *p, struct place *p2, char *line) |
204 { | 243 { |
205 size_t pos, argpos; | 244 size_t pos, argpos; |
206 struct place p3, p4; | 245 struct place p3, p4; |
207 | 246 |
208 /* | 247 /* |
261 } | 300 } |
262 } | 301 } |
263 | 302 |
264 static | 303 static |
265 void | 304 void |
266 d_undef(struct place *p, struct place *p2, char *line, size_t len) | 305 d_undef(struct place *p, struct place *p2, char *line) |
267 { | 306 { |
307 uncomment(line); | |
268 oneword("#undef", p2, line); | 308 oneword("#undef", p2, line); |
269 macro_undef(line); | 309 macro_undef(line); |
270 } | 310 } |
271 | 311 |
272 //////////////////////////////////////////////////////////// | 312 //////////////////////////////////////////////////////////// |
273 // includes | 313 // includes |
274 | 314 |
275 static | 315 static |
276 bool | 316 bool |
277 tryinclude(struct place *p, char *line, size_t len) | 317 tryinclude(struct place *p, char *line) |
278 { | 318 { |
319 size_t len; | |
320 | |
321 len = strlen(line); | |
279 if (len > 2 && line[0] == '"' && line[len-1] == '"') { | 322 if (len > 2 && line[0] == '"' && line[len-1] == '"') { |
280 line[len-1] = '\0'; | 323 line[len-1] = '\0'; |
281 file_readquote(p, line+1); | 324 file_readquote(p, line+1); |
282 line[len-1] = '"'; | 325 line[len-1] = '"'; |
283 return true; | 326 return true; |
291 return false; | 334 return false; |
292 } | 335 } |
293 | 336 |
294 static | 337 static |
295 void | 338 void |
296 d_include(struct place *p, struct place *p2, char *line, size_t len) | 339 d_include(struct place *p, struct place *p2, char *line) |
297 { | 340 { |
298 char *text; | 341 char *text; |
299 | 342 |
300 if (tryinclude(p, line, len)) { | 343 uncomment(line); |
344 if (tryinclude(p, line)) { | |
301 return; | 345 return; |
302 } | 346 } |
303 text = macroexpand(p2, line, len, false); | 347 text = macroexpand(p2, line, strlen(line), false); |
304 if (tryinclude(p, text, strlen(text))) { | 348 if (tryinclude(p, text)) { |
305 dostrfree(text); | 349 dostrfree(text); |
306 return; | 350 return; |
307 } | 351 } |
308 dostrfree(text); | 352 dostrfree(text); |
309 complain(p, "Illegal #include directive"); | 353 complain(p, "Illegal #include directive"); |
310 complain_fail(); | 354 complain_fail(); |
311 } | 355 } |
312 | 356 |
313 static | 357 static |
314 void | 358 void |
315 d_line(struct place *p, struct place *p2, char *line, size_t len) | 359 d_line(struct place *p, struct place *p2, char *line) |
316 { | 360 { |
317 /* XXX */ | 361 /* XXX */ |
318 complain(p, "Sorry, no #line yet"); | 362 complain(p, "Sorry, no #line yet"); |
319 } | 363 } |
320 | 364 |
321 //////////////////////////////////////////////////////////// | 365 //////////////////////////////////////////////////////////// |
322 // messages | 366 // messages |
323 | 367 |
324 static | 368 static |
325 void | 369 void |
326 d_warning(struct place *p, struct place *p2, char *line, size_t len) | 370 d_warning(struct place *p, struct place *p2, char *line) |
327 { | 371 { |
328 char *msg; | 372 char *msg; |
329 | 373 |
330 msg = macroexpand(p2, line, len, false); | 374 msg = macroexpand(p2, line, strlen(line), false); |
331 complain(p, "#warning: %s", msg); | 375 complain(p, "#warning: %s", msg); |
332 if (mode.werror) { | 376 if (mode.werror) { |
333 complain_fail(); | 377 complain_fail(); |
334 } | 378 } |
335 dostrfree(msg); | 379 dostrfree(msg); |
336 } | 380 } |
337 | 381 |
338 static | 382 static |
339 void | 383 void |
340 d_error(struct place *p, struct place *p2, char *line, size_t len) | 384 d_error(struct place *p, struct place *p2, char *line) |
341 { | 385 { |
342 char *msg; | 386 char *msg; |
343 | 387 |
344 msg = macroexpand(p2, line, len, false); | 388 msg = macroexpand(p2, line, strlen(line), false); |
345 complain(p, "#error: %s", msg); | 389 complain(p, "#error: %s", msg); |
346 complain_fail(); | 390 complain_fail(); |
347 dostrfree(msg); | 391 dostrfree(msg); |
348 } | 392 } |
349 | 393 |
350 //////////////////////////////////////////////////////////// | 394 //////////////////////////////////////////////////////////// |
351 // other | 395 // other |
352 | 396 |
353 static | 397 static |
354 void | 398 void |
355 d_pragma(struct place *p, struct place *p2, char *line, size_t len) | 399 d_pragma(struct place *p, struct place *p2, char *line) |
356 { | 400 { |
357 complain(p, "#pragma %s", line); | 401 complain(p, "#pragma %s", line); |
358 complain_fail(); | 402 complain_fail(); |
359 } | 403 } |
360 | 404 |
362 // directive table | 406 // directive table |
363 | 407 |
364 static const struct { | 408 static const struct { |
365 const char *name; | 409 const char *name; |
366 bool ifskip; | 410 bool ifskip; |
367 void (*func)(struct place *, struct place *, char *line, size_t len); | 411 void (*func)(struct place *, struct place *, char *line); |
368 } directives[] = { | 412 } directives[] = { |
369 { "define", true, d_define }, | 413 { "define", true, d_define }, |
370 { "elif", false, d_elif }, | 414 { "elif", false, d_elif }, |
371 { "else", false, d_else }, | 415 { "else", false, d_else }, |
372 { "endif", false, d_endif }, | 416 { "endif", false, d_endif }, |
382 }; | 426 }; |
383 static const unsigned numdirectives = HOWMANY(directives); | 427 static const unsigned numdirectives = HOWMANY(directives); |
384 | 428 |
385 static | 429 static |
386 void | 430 void |
387 directive_gotdirective(struct place *p, char *line, size_t linelen) | 431 directive_gotdirective(struct place *p, char *line) |
388 { | 432 { |
389 struct place p2; | 433 struct place p2; |
390 size_t len, skip; | 434 size_t len, skip; |
391 unsigned i; | 435 unsigned i; |
392 | 436 |
399 return; | 443 return; |
400 } | 444 } |
401 skip = len + strspn(line+len, ws); | 445 skip = len + strspn(line+len, ws); |
402 p2.column += skip; | 446 p2.column += skip; |
403 line += skip; | 447 line += skip; |
404 linelen -= skip; | 448 |
405 linelen = notrailingws(line, linelen); | 449 len = strlen(line); |
406 directives[i].func(p, &p2, line, linelen); | 450 len = notrailingws(line, len); |
451 if (len < strlen(line)) { | |
452 line[len] = '\0'; | |
453 } | |
454 directives[i].func(p, &p2, line); | |
407 return; | 455 return; |
408 } | 456 } |
409 } | 457 } |
410 skip = strcspn(line, ws); | 458 skip = strcspn(line, ws); |
411 complain(p, "Unknown directive #%.*s", (int)skip, line); | 459 complain(p, "Unknown directive #%.*s", (int)skip, line); |
524 } | 572 } |
525 | 573 |
526 /* check if we have a directive line */ | 574 /* check if we have a directive line */ |
527 skip = strspn(line + acomm, ws); | 575 skip = strspn(line + acomm, ws); |
528 if (acomm == 0 && line[skip] == '#') { | 576 if (acomm == 0 && line[skip] == '#') { |
577 char ch; | |
578 | |
529 skip = skip + 1 + strspn(line + skip + 1, ws); | 579 skip = skip + 1 + strspn(line + skip + 1, ws); |
530 assert(skip <= text); | 580 assert(skip <= text); |
531 p->column += skip; | 581 p->column += skip; |
532 directive_gotdirective(p, line+skip, text-skip); | 582 assert(line[len] == '\0'); |
583 /* ensure null termination for directives */ | |
584 ch = line[text]; | |
585 if (ch != '\0') { | |
586 line[text] = '\0'; | |
587 } | |
588 directive_gotdirective(p, line+skip /*, length = text-skip */); | |
589 line[text] = ch; | |
533 p->column += text-skip; | 590 p->column += text-skip; |
534 } else if (ifstate->curtrue) { | 591 } else if (ifstate->curtrue) { |
535 macro_sendline(p, line + acomm, text); | 592 macro_sendline(p, line + acomm, text); |
536 p->column += text; | 593 p->column += text; |
537 } | 594 } |