comparison directive.c @ 164:f14f5352956c

Merge upstream into Joerg's changes.
author David A. Holland
date Fri, 12 Jun 2015 01:00:38 -0400
parents d6e6b3940780 a2c2fe8dbea3
children cc6d6f27d6ee
comparison
equal deleted inserted replaced
163:e1dfa3f90b6c 164:f14f5352956c
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, struct place *np, 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, struct place *np, 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, struct place *np, 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, struct place *np, 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, struct place *np, 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, struct place *np, 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, struct place *np, 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, struct place *np, 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, struct place *np, 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, struct place *np, char *line) 416 d_line(struct lineplace *lp, struct place *p2, char *line)
416 { 417 {
417 char *text; 418 char *text;
418 size_t oldlen; 419 size_t oldlen;
419 const char *token, *start_lineno, *start_filename; 420 const char *token, *start_lineno, *start_filename;
420 size_t len_lineno, len_filename; 421 size_t len_lineno, len_filename;
453 token += strspn(token, ws); 454 token += strspn(token, ws);
454 if (*token != '\0') { 455 if (*token != '\0') {
455 goto illegal_line; 456 goto illegal_line;
456 } 457 }
457 } 458 }
458 np->line = atoi(start_lineno); 459 lp->nextline.line = atoi(start_lineno);
459 if (len_filename) { 460 if (len_filename) {
460 char *filename = dostrndup(start_filename, len_filename); 461 char *filename = dostrndup(start_filename, len_filename);
461 place_setfile(np, filename); 462 place_setfile(&lp->nextline, filename);
462 dostrfree(filename); 463 dostrfree(filename);
463 } 464 }
464 dostrfree(text); 465 dostrfree(text);
465 return; 466 return;
466 467
467 illegal_line: 468 illegal_line:
468 complain(p, "Illegal #line directive"); 469 complain(&lp->current, "Illegal #line directive");
469 complain(p, "Before macro expansion: #include %s", line); 470 complain(&lp->current, "Before macro expansion: #include %s", line);
470 complain(p, "After macro expansion: #include %s", text); 471 complain(&lp->current, "After macro expansion: #include %s", text);
471 dostrfree(text); 472 dostrfree(text);
472 } 473 }
473 474
474 //////////////////////////////////////////////////////////// 475 ////////////////////////////////////////////////////////////
475 // messages 476 // messages
476 477
477 static 478 static
478 void 479 void
479 d_warning(struct place *p, struct place *p2, struct place *np, char *line) 480 d_warning(struct lineplace *lp, struct place *p2, char *line)
480 { 481 {
481 char *msg; 482 char *msg;
482 483
483 msg = macroexpand(p2, line, strlen(line), false); 484 msg = macroexpand(p2, line, strlen(line), false);
484 complain(p, "#warning: %s", msg); 485 complain(&lp->current, "#warning: %s", msg);
485 if (mode.werror) { 486 if (mode.werror) {
486 complain_fail(); 487 complain_fail();
487 } 488 }
488 dostrfree(msg); 489 dostrfree(msg);
489 } 490 }
490 491
491 static 492 static
492 void 493 void
493 d_error(struct place *p, struct place *p2, struct place *np, char *line) 494 d_error(struct lineplace *lp, struct place *p2, char *line)
494 { 495 {
495 char *msg; 496 char *msg;
496 497
497 msg = macroexpand(p2, line, strlen(line), false); 498 msg = macroexpand(p2, line, strlen(line), false);
498 complain(p, "#error: %s", msg); 499 complain(&lp->current, "#error: %s", msg);
499 complain_fail(); 500 complain_fail();
500 dostrfree(msg); 501 dostrfree(msg);
501 } 502 }
502 503
503 //////////////////////////////////////////////////////////// 504 ////////////////////////////////////////////////////////////
504 // other 505 // other
505 506
506 static 507 static
507 void 508 void
508 d_pragma(struct place *p, struct place *p2, struct place *np, char *line) 509 d_pragma(struct lineplace *lp, struct place *p2, char *line)
509 { 510 {
510 (void)p2; 511 (void)p2;
511 512
512 complain(p, "#pragma %s", line); 513 complain(&lp->current, "#pragma %s", line);
513 complain_fail(); 514 complain_fail();
514 } 515 }
515 516
516 //////////////////////////////////////////////////////////// 517 ////////////////////////////////////////////////////////////
517 // directive table 518 // directive table
518 519
519 static const struct { 520 static const struct {
520 const char *name; 521 const char *name;
521 bool ifskip; 522 bool ifskip;
522 void (*func)(struct place *, struct place *, struct place *, 523 void (*func)(struct lineplace *, struct place *, char *line);
523 char *line);
524 } directives[] = { 524 } directives[] = {
525 { "define", true, d_define }, 525 { "define", true, d_define },
526 { "elif", false, d_elif }, 526 { "elif", false, d_elif },
527 { "else", false, d_else }, 527 { "else", false, d_else },
528 { "endif", false, d_endif }, 528 { "endif", false, d_endif },
538 }; 538 };
539 static const unsigned numdirectives = HOWMANY(directives); 539 static const unsigned numdirectives = HOWMANY(directives);
540 540
541 static 541 static
542 void 542 void
543 directive_gotdirective(struct place *p, struct place *np, char *line) 543 directive_gotdirective(struct lineplace *lp, char *line)
544 { 544 {
545 struct place p2; 545 struct place p2;
546 size_t len, skip; 546 size_t len, skip;
547 unsigned i; 547 unsigned i;
548 548
549 p2 = *p; 549 p2 = lp->current;
550 for (i=0; i<numdirectives; i++) { 550 for (i=0; i<numdirectives; i++) {
551 len = strlen(directives[i].name); 551 len = strlen(directives[i].name);
552 if (!strncmp(line, directives[i].name, len) && 552 if (!strncmp(line, directives[i].name, len) &&
553 strchr(ws, line[len])) { 553 strchr(ws, line[len])) {
554 if (directives[i].ifskip && !ifstate->curtrue) { 554 if (directives[i].ifskip && !ifstate->curtrue) {
561 len = strlen(line); 561 len = strlen(line);
562 len = notrailingws(line, len); 562 len = notrailingws(line, len);
563 if (len < strlen(line)) { 563 if (len < strlen(line)) {
564 line[len] = '\0'; 564 line[len] = '\0';
565 } 565 }
566 directives[i].func(p, &p2, np, line); 566 directives[i].func(lp, &p2, line);
567 return; 567 return;
568 } 568 }
569 } 569 }
570 /* ugh. allow # by itself, including with a comment after it */ 570 /* ugh. allow # by itself, including with a comment after it */
571 uncomment(line); 571 uncomment(line);
572 if (line[0] == '\0') { 572 if (line[0] == '\0') {
573 return; 573 return;
574 } 574 }
575 575
576 skip = strcspn(line, ws); 576 skip = strcspn(line, ws);
577 complain(p, "Unknown directive #%.*s", (int)skip, line); 577 complain(&lp->current, "Unknown directive #%.*s", (int)skip, line);
578 complain_fail(); 578 complain_fail();
579 } 579 }
580 580
581 /* 581 /*
582 * Check for nested comment delimiters in LINE. 582 * Check for nested comment delimiters in LINE.
583 */ 583 */
584 static 584 static
585 size_t 585 size_t
586 directive_scancomments(const struct place *p, char *line, size_t len) 586 directive_scancomments(const struct lineplace *lp, char *line, size_t len)
587 { 587 {
588 size_t pos; 588 size_t pos;
589 bool incomment; 589 bool incomment;
590 struct place p2; 590 struct place p2;
591 591
592 p2 = *p; 592 p2 = lp->current;
593 incomment = 0; 593 incomment = 0;
594 for (pos = 0; pos+1 < len; pos++) { 594 for (pos = 0; pos+1 < len; pos++) {
595 if (line[pos] == '/' && line[pos+1] == '*') { 595 if (line[pos] == '/' && line[pos+1] == '*') {
596 if (incomment) { 596 if (incomment) {
597 complain(&p2, "Warning: %c%c within comment", 597 complain(&p2, "Warning: %c%c within comment",
623 assert(!incomment); 623 assert(!incomment);
624 return len; 624 return len;
625 } 625 }
626 626
627 void 627 void
628 directive_gotline(struct place *p, struct place *np, char *line, size_t len) 628 directive_gotline(struct lineplace *lp, char *line, size_t len)
629 { 629 {
630 size_t skip; 630 size_t skip;
631 631
632 if (warns.nestcomment) { 632 if (warns.nestcomment) {
633 directive_scancomments(p, line, len); 633 directive_scancomments(lp, line, len);
634 } 634 }
635 635
636 /* check if we have a directive line (# exactly in column 0) */ 636 /* check if we have a directive line (# exactly in column 0) */
637 if (line[0] == '#') { 637 if (line[0] == '#') {
638 skip = 1 + strspn(line + 1, ws); 638 skip = 1 + strspn(line + 1, ws);
639 assert(skip <= len); 639 assert(skip <= len);
640 p->column += skip; 640 lp->current.column += skip;
641 assert(line[len] == '\0'); 641 assert(line[len] == '\0');
642 directive_gotdirective(p, np, line+skip); 642 directive_gotdirective(lp, line+skip /*, length = len-skip */);
643 p->column += len-skip; 643 lp->current.column += len-skip;
644 } else if (ifstate->curtrue) { 644 } else if (ifstate->curtrue) {
645 macro_sendline(p, line, len); 645 macro_sendline(&lp->current, line, len);
646 p->column += len; 646 lp->current.column += len;
647 } 647 }
648 } 648 }
649 649
650 void 650 void
651 directive_goteof(struct place *p) 651 directive_goteof(struct place *p)