Mercurial > ~dholland > hg > tradcpp > index.cgi
comparison directive.c @ 154:a2c2fe8dbea3
Wrap up the current and next line position when invoking directives.
(in preparation for implementing #line)
author | David A. Holland |
---|---|
date | Fri, 12 Jun 2015 00:56:12 -0400 |
parents | 1cda505ddc78 |
children | f14f5352956c |
comparison
equal
deleted
inserted
replaced
153:28ac21a359d1 | 154:a2c2fe8dbea3 |
---|---|
173 ifstate_destroy(is); | 173 ifstate_destroy(is); |
174 } | 174 } |
175 | 175 |
176 static | 176 static |
177 void | 177 void |
178 d_if(struct place *p, struct place *p2, char *line) | 178 d_if(struct lineplace *lp, struct place *p2, char *line) |
179 { | 179 { |
180 char *expr; | 180 char *expr; |
181 bool val; | 181 bool val; |
182 struct place p3 = *p2; | 182 struct place p3 = *p2; |
183 size_t oldlen; | 183 size_t oldlen; |
192 if (ifstate->curtrue) { | 192 if (ifstate->curtrue) { |
193 val = eval(&p3, expr); | 193 val = eval(&p3, expr); |
194 } else { | 194 } else { |
195 val = 0; | 195 val = 0; |
196 } | 196 } |
197 ifstate_push(p, val); | 197 ifstate_push(&lp->current, val); |
198 dostrfree(expr); | 198 dostrfree(expr); |
199 } | 199 } |
200 | 200 |
201 static | 201 static |
202 void | 202 void |
203 d_ifdef(struct place *p, struct place *p2, char *line) | 203 d_ifdef(struct lineplace *lp, struct place *p2, char *line) |
204 { | 204 { |
205 uncomment(line); | 205 uncomment(line); |
206 oneword("#ifdef", p2, line); | 206 oneword("#ifdef", p2, line); |
207 ifstate_push(p, macro_isdefined(line)); | 207 ifstate_push(&lp->current, macro_isdefined(line)); |
208 } | 208 } |
209 | 209 |
210 static | 210 static |
211 void | 211 void |
212 d_ifndef(struct place *p, struct place *p2, char *line) | 212 d_ifndef(struct lineplace *lp, struct place *p2, char *line) |
213 { | 213 { |
214 uncomment(line); | 214 uncomment(line); |
215 oneword("#ifndef", p2, line); | 215 oneword("#ifndef", p2, line); |
216 ifstate_push(p, !macro_isdefined(line)); | 216 ifstate_push(&lp->current, !macro_isdefined(line)); |
217 } | 217 } |
218 | 218 |
219 static | 219 static |
220 void | 220 void |
221 d_elif(struct place *p, struct place *p2, char *line) | 221 d_elif(struct lineplace *lp, struct place *p2, char *line) |
222 { | 222 { |
223 char *expr; | 223 char *expr; |
224 struct place p3 = *p2; | 224 struct place p3 = *p2; |
225 size_t oldlen; | 225 size_t oldlen; |
226 | 226 |
227 if (ifstate->seenelse) { | 227 if (ifstate->seenelse) { |
228 complain(p, "#elif after #else"); | 228 complain(&lp->current, "#elif after #else"); |
229 complain_fail(); | 229 complain_fail(); |
230 } | 230 } |
231 | 231 |
232 if (ifstate->evertrue) { | 232 if (ifstate->evertrue) { |
233 ifstate->curtrue = false; | 233 ifstate->curtrue = false; |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 static | 248 static |
249 void | 249 void |
250 d_else(struct place *p, struct place *p2, char *line) | 250 d_else(struct lineplace *lp, struct place *p2, char *line) |
251 { | 251 { |
252 (void)p2; | 252 (void)p2; |
253 (void)line; | 253 (void)line; |
254 | 254 |
255 if (ifstate->seenelse) { | 255 if (ifstate->seenelse) { |
256 complain(p, "Multiple #else directives in one conditional"); | 256 complain(&lp->current, |
257 "Multiple #else directives in one conditional"); | |
257 complain_fail(); | 258 complain_fail(); |
258 } | 259 } |
259 | 260 |
260 ifstate->curtrue = !ifstate->evertrue; | 261 ifstate->curtrue = !ifstate->evertrue; |
261 ifstate->evertrue = true; | 262 ifstate->evertrue = true; |
262 ifstate->seenelse = true; | 263 ifstate->seenelse = true; |
263 } | 264 } |
264 | 265 |
265 static | 266 static |
266 void | 267 void |
267 d_endif(struct place *p, struct place *p2, char *line) | 268 d_endif(struct lineplace *lp, struct place *p2, char *line) |
268 { | 269 { |
269 (void)p2; | 270 (void)p2; |
270 (void)line; | 271 (void)line; |
271 | 272 |
272 if (ifstate->prev == NULL) { | 273 if (ifstate->prev == NULL) { |
273 complain(p, "Unmatched #endif"); | 274 complain(&lp->current, "Unmatched #endif"); |
274 complain_fail(); | 275 complain_fail(); |
275 } else { | 276 } else { |
276 ifstate_pop(); | 277 ifstate_pop(); |
277 } | 278 } |
278 } | 279 } |
280 //////////////////////////////////////////////////////////// | 281 //////////////////////////////////////////////////////////// |
281 // macros | 282 // macros |
282 | 283 |
283 static | 284 static |
284 void | 285 void |
285 d_define(struct place *p, struct place *p2, char *line) | 286 d_define(struct lineplace *lp, struct place *p2, char *line) |
286 { | 287 { |
287 size_t pos, argpos; | 288 size_t pos, argpos; |
288 struct place p3, p4; | 289 struct place p3, p4; |
289 | 290 |
290 (void)p; | 291 (void)lp; |
291 | 292 |
292 /* | 293 /* |
293 * line may be: | 294 * line may be: |
294 * macro expansion | 295 * macro expansion |
295 * macro(arg, arg, ...) expansion | 296 * macro(arg, arg, ...) expansion |
345 } | 346 } |
346 } | 347 } |
347 | 348 |
348 static | 349 static |
349 void | 350 void |
350 d_undef(struct place *p, struct place *p2, char *line) | 351 d_undef(struct lineplace *lp, struct place *p2, char *line) |
351 { | 352 { |
352 (void)p; | 353 (void)lp; |
353 | 354 |
354 uncomment(line); | 355 uncomment(line); |
355 oneword("#undef", p2, line); | 356 oneword("#undef", p2, line); |
356 macro_undef(line); | 357 macro_undef(line); |
357 } | 358 } |
381 return false; | 382 return false; |
382 } | 383 } |
383 | 384 |
384 static | 385 static |
385 void | 386 void |
386 d_include(struct place *p, struct place *p2, char *line) | 387 d_include(struct lineplace *lp, struct place *p2, char *line) |
387 { | 388 { |
388 char *text; | 389 char *text; |
389 size_t oldlen; | 390 size_t oldlen; |
390 | 391 |
391 uncomment(line); | 392 uncomment(line); |
392 if (tryinclude(p, line)) { | 393 if (tryinclude(&lp->current, line)) { |
393 return; | 394 return; |
394 } | 395 } |
395 text = macroexpand(p2, line, strlen(line), false); | 396 text = macroexpand(p2, line, strlen(line), false); |
396 | 397 |
397 oldlen = strlen(text); | 398 oldlen = strlen(text); |
398 uncomment(text); | 399 uncomment(text); |
399 /* trim to fit, so the malloc debugging won't complain */ | 400 /* trim to fit, so the malloc debugging won't complain */ |
400 text = dorealloc(text, oldlen + 1, strlen(text) + 1); | 401 text = dorealloc(text, oldlen + 1, strlen(text) + 1); |
401 | 402 |
402 if (tryinclude(p, text)) { | 403 if (tryinclude(&lp->current, text)) { |
403 dostrfree(text); | 404 dostrfree(text); |
404 return; | 405 return; |
405 } | 406 } |
406 complain(p, "Illegal #include directive"); | 407 complain(&lp->current, "Illegal #include directive"); |
407 complain(p, "Before macro expansion: #include %s", line); | 408 complain(&lp->current, "Before macro expansion: #include %s", line); |
408 complain(p, "After macro expansion: #include %s", text); | 409 complain(&lp->current, "After macro expansion: #include %s", text); |
409 dostrfree(text); | 410 dostrfree(text); |
410 complain_fail(); | 411 complain_fail(); |
411 } | 412 } |
412 | 413 |
413 static | 414 static |
414 void | 415 void |
415 d_line(struct place *p, struct place *p2, char *line) | 416 d_line(struct lineplace *lp, struct place *p2, char *line) |
416 { | 417 { |
417 (void)p2; | 418 (void)p2; |
418 (void)line; | 419 (void)line; |
419 | 420 |
420 /* XXX */ | 421 /* XXX */ |
421 complain(p, "Sorry, no #line yet"); | 422 complain(&lp->current, "Sorry, no #line yet"); |
422 } | 423 } |
423 | 424 |
424 //////////////////////////////////////////////////////////// | 425 //////////////////////////////////////////////////////////// |
425 // messages | 426 // messages |
426 | 427 |
427 static | 428 static |
428 void | 429 void |
429 d_warning(struct place *p, struct place *p2, char *line) | 430 d_warning(struct lineplace *lp, struct place *p2, char *line) |
430 { | 431 { |
431 char *msg; | 432 char *msg; |
432 | 433 |
433 msg = macroexpand(p2, line, strlen(line), false); | 434 msg = macroexpand(p2, line, strlen(line), false); |
434 complain(p, "#warning: %s", msg); | 435 complain(&lp->current, "#warning: %s", msg); |
435 if (mode.werror) { | 436 if (mode.werror) { |
436 complain_fail(); | 437 complain_fail(); |
437 } | 438 } |
438 dostrfree(msg); | 439 dostrfree(msg); |
439 } | 440 } |
440 | 441 |
441 static | 442 static |
442 void | 443 void |
443 d_error(struct place *p, struct place *p2, char *line) | 444 d_error(struct lineplace *lp, struct place *p2, char *line) |
444 { | 445 { |
445 char *msg; | 446 char *msg; |
446 | 447 |
447 msg = macroexpand(p2, line, strlen(line), false); | 448 msg = macroexpand(p2, line, strlen(line), false); |
448 complain(p, "#error: %s", msg); | 449 complain(&lp->current, "#error: %s", msg); |
449 complain_fail(); | 450 complain_fail(); |
450 dostrfree(msg); | 451 dostrfree(msg); |
451 } | 452 } |
452 | 453 |
453 //////////////////////////////////////////////////////////// | 454 //////////////////////////////////////////////////////////// |
454 // other | 455 // other |
455 | 456 |
456 static | 457 static |
457 void | 458 void |
458 d_pragma(struct place *p, struct place *p2, char *line) | 459 d_pragma(struct lineplace *lp, struct place *p2, char *line) |
459 { | 460 { |
460 (void)p2; | 461 (void)p2; |
461 | 462 |
462 complain(p, "#pragma %s", line); | 463 complain(&lp->current, "#pragma %s", line); |
463 complain_fail(); | 464 complain_fail(); |
464 } | 465 } |
465 | 466 |
466 //////////////////////////////////////////////////////////// | 467 //////////////////////////////////////////////////////////// |
467 // directive table | 468 // directive table |
468 | 469 |
469 static const struct { | 470 static const struct { |
470 const char *name; | 471 const char *name; |
471 bool ifskip; | 472 bool ifskip; |
472 void (*func)(struct place *, struct place *, char *line); | 473 void (*func)(struct lineplace *, struct place *, char *line); |
473 } directives[] = { | 474 } directives[] = { |
474 { "define", true, d_define }, | 475 { "define", true, d_define }, |
475 { "elif", false, d_elif }, | 476 { "elif", false, d_elif }, |
476 { "else", false, d_else }, | 477 { "else", false, d_else }, |
477 { "endif", false, d_endif }, | 478 { "endif", false, d_endif }, |
487 }; | 488 }; |
488 static const unsigned numdirectives = HOWMANY(directives); | 489 static const unsigned numdirectives = HOWMANY(directives); |
489 | 490 |
490 static | 491 static |
491 void | 492 void |
492 directive_gotdirective(struct place *p, char *line) | 493 directive_gotdirective(struct lineplace *lp, char *line) |
493 { | 494 { |
494 struct place p2; | 495 struct place p2; |
495 size_t len, skip; | 496 size_t len, skip; |
496 unsigned i; | 497 unsigned i; |
497 | 498 |
498 p2 = *p; | 499 p2 = lp->current; |
499 for (i=0; i<numdirectives; i++) { | 500 for (i=0; i<numdirectives; i++) { |
500 len = strlen(directives[i].name); | 501 len = strlen(directives[i].name); |
501 if (!strncmp(line, directives[i].name, len) && | 502 if (!strncmp(line, directives[i].name, len) && |
502 strchr(ws, line[len])) { | 503 strchr(ws, line[len])) { |
503 if (directives[i].ifskip && !ifstate->curtrue) { | 504 if (directives[i].ifskip && !ifstate->curtrue) { |
510 len = strlen(line); | 511 len = strlen(line); |
511 len = notrailingws(line, len); | 512 len = notrailingws(line, len); |
512 if (len < strlen(line)) { | 513 if (len < strlen(line)) { |
513 line[len] = '\0'; | 514 line[len] = '\0'; |
514 } | 515 } |
515 directives[i].func(p, &p2, line); | 516 directives[i].func(lp, &p2, line); |
516 return; | 517 return; |
517 } | 518 } |
518 } | 519 } |
519 /* ugh. allow # by itself, including with a comment after it */ | 520 /* ugh. allow # by itself, including with a comment after it */ |
520 uncomment(line); | 521 uncomment(line); |
521 if (line[0] == '\0') { | 522 if (line[0] == '\0') { |
522 return; | 523 return; |
523 } | 524 } |
524 | 525 |
525 skip = strcspn(line, ws); | 526 skip = strcspn(line, ws); |
526 complain(p, "Unknown directive #%.*s", (int)skip, line); | 527 complain(&lp->current, "Unknown directive #%.*s", (int)skip, line); |
527 complain_fail(); | 528 complain_fail(); |
528 } | 529 } |
529 | 530 |
530 /* | 531 /* |
531 * Check for nested comment delimiters in LINE. | 532 * Check for nested comment delimiters in LINE. |
532 */ | 533 */ |
533 static | 534 static |
534 size_t | 535 size_t |
535 directive_scancomments(const struct place *p, char *line, size_t len) | 536 directive_scancomments(const struct lineplace *lp, char *line, size_t len) |
536 { | 537 { |
537 size_t pos; | 538 size_t pos; |
538 bool incomment; | 539 bool incomment; |
539 struct place p2; | 540 struct place p2; |
540 | 541 |
541 p2 = *p; | 542 p2 = lp->current; |
542 incomment = 0; | 543 incomment = 0; |
543 for (pos = 0; pos+1 < len; pos++) { | 544 for (pos = 0; pos+1 < len; pos++) { |
544 if (line[pos] == '/' && line[pos+1] == '*') { | 545 if (line[pos] == '/' && line[pos+1] == '*') { |
545 if (incomment) { | 546 if (incomment) { |
546 complain(&p2, "Warning: %c%c within comment", | 547 complain(&p2, "Warning: %c%c within comment", |
572 assert(!incomment); | 573 assert(!incomment); |
573 return len; | 574 return len; |
574 } | 575 } |
575 | 576 |
576 void | 577 void |
577 directive_gotline(struct place *p, char *line, size_t len) | 578 directive_gotline(struct lineplace *lp, char *line, size_t len) |
578 { | 579 { |
579 size_t skip; | 580 size_t skip; |
580 | 581 |
581 if (warns.nestcomment) { | 582 if (warns.nestcomment) { |
582 directive_scancomments(p, line, len); | 583 directive_scancomments(lp, line, len); |
583 } | 584 } |
584 | 585 |
585 /* check if we have a directive line (# exactly in column 0) */ | 586 /* check if we have a directive line (# exactly in column 0) */ |
586 if (line[0] == '#') { | 587 if (line[0] == '#') { |
587 skip = 1 + strspn(line + 1, ws); | 588 skip = 1 + strspn(line + 1, ws); |
588 assert(skip <= len); | 589 assert(skip <= len); |
589 p->column += skip; | 590 lp->current.column += skip; |
590 assert(line[len] == '\0'); | 591 assert(line[len] == '\0'); |
591 directive_gotdirective(p, line+skip /*, length = len-skip */); | 592 directive_gotdirective(lp, line+skip /*, length = len-skip */); |
592 p->column += len-skip; | 593 lp->current.column += len-skip; |
593 } else if (ifstate->curtrue) { | 594 } else if (ifstate->curtrue) { |
594 macro_sendline(p, line, len); | 595 macro_sendline(&lp->current, line, len); |
595 p->column += len; | 596 lp->current.column += len; |
596 } | 597 } |
597 } | 598 } |
598 | 599 |
599 void | 600 void |
600 directive_goteof(struct place *p) | 601 directive_goteof(struct place *p) |