comparison directive.c @ 160:d6e6b3940780

Fully implement #line.
author Joerg Sonnenberger <joerg@bec.de>
date Fri, 27 Feb 2015 02:06:49 +0100
parents 1cda505ddc78
children f14f5352956c
comparison
equal deleted inserted replaced
159:8cef6d7227a8 160:d6e6b3940780
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 place *p, struct place *p2, struct place *np, 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;
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 place *p, struct place *p2, struct place *np, 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(p, 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 place *p, struct place *p2, struct place *np, 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(p, !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 place *p, struct place *p2, struct place *np, 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
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 place *p, struct place *p2, struct place *np, 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) {
262 ifstate->seenelse = true; 262 ifstate->seenelse = true;
263 } 263 }
264 264
265 static 265 static
266 void 266 void
267 d_endif(struct place *p, struct place *p2, char *line) 267 d_endif(struct place *p, struct place *p2, struct place *np, char *line)
268 { 268 {
269 (void)p2; 269 (void)p2;
270 (void)line; 270 (void)line;
271 271
272 if (ifstate->prev == NULL) { 272 if (ifstate->prev == NULL) {
280 //////////////////////////////////////////////////////////// 280 ////////////////////////////////////////////////////////////
281 // macros 281 // macros
282 282
283 static 283 static
284 void 284 void
285 d_define(struct place *p, struct place *p2, char *line) 285 d_define(struct place *p, struct place *p2, struct place *np, char *line)
286 { 286 {
287 size_t pos, argpos; 287 size_t pos, argpos;
288 struct place p3, p4; 288 struct place p3, p4;
289 289
290 (void)p; 290 (void)p;
345 } 345 }
346 } 346 }
347 347
348 static 348 static
349 void 349 void
350 d_undef(struct place *p, struct place *p2, char *line) 350 d_undef(struct place *p, struct place *p2, struct place *np, char *line)
351 { 351 {
352 (void)p; 352 (void)p;
353 353
354 uncomment(line); 354 uncomment(line);
355 oneword("#undef", p2, line); 355 oneword("#undef", p2, line);
381 return false; 381 return false;
382 } 382 }
383 383
384 static 384 static
385 void 385 void
386 d_include(struct place *p, struct place *p2, char *line) 386 d_include(struct place *p, struct place *p2, struct place *np, char *line)
387 { 387 {
388 char *text; 388 char *text;
389 size_t oldlen; 389 size_t oldlen;
390 390
391 uncomment(line); 391 uncomment(line);
410 complain_fail(); 410 complain_fail();
411 } 411 }
412 412
413 static 413 static
414 void 414 void
415 d_line(struct place *p, struct place *p2, char *line) 415 d_line(struct place *p, struct place *p2, struct place *np, char *line)
416 { 416 {
417 (void)p2; 417 char *text;
418 (void)line; 418 size_t oldlen;
419 419 const char *token, *start_lineno, *start_filename;
420 /* XXX */ 420 size_t len_lineno, len_filename;
421 complain(p, "Sorry, no #line yet"); 421
422 text = macroexpand(p2, line, strlen(line), true);
423
424 oldlen = strlen(text);
425 uncomment(text);
426 /* trim to fit, so the malloc debugging won't complain */
427 text = dorealloc(text, oldlen + 1, strlen(text) + 1);
428
429 token = text;
430 token += strspn(token, ws);
431 start_lineno = token;
432 len_lineno = strspn(token, digits);
433 if (len_lineno == 0) {
434 goto illegal_line;
435 }
436 token += len_lineno;
437 token += strspn(ws, token);
438 if (*token == '"') {
439 ++token;
440 start_filename = token;
441 len_filename = strcspn(token, "\"");
442 token += len_filename;
443 if (*token != '"' || len_filename == 0) {
444 goto illegal_line;
445 }
446 ++token;
447 token += strspn(token, ws);
448 if (*token != '\0') {
449 goto illegal_line;
450 }
451 } else {
452 len_filename = 0;
453 token += strspn(token, ws);
454 if (*token != '\0') {
455 goto illegal_line;
456 }
457 }
458 np->line = atoi(start_lineno);
459 if (len_filename) {
460 char *filename = dostrndup(start_filename, len_filename);
461 place_setfile(np, filename);
462 dostrfree(filename);
463 }
464 dostrfree(text);
465 return;
466
467 illegal_line:
468 complain(p, "Illegal #line directive");
469 complain(p, "Before macro expansion: #include %s", line);
470 complain(p, "After macro expansion: #include %s", text);
471 dostrfree(text);
422 } 472 }
423 473
424 //////////////////////////////////////////////////////////// 474 ////////////////////////////////////////////////////////////
425 // messages 475 // messages
426 476
427 static 477 static
428 void 478 void
429 d_warning(struct place *p, struct place *p2, char *line) 479 d_warning(struct place *p, struct place *p2, struct place *np, char *line)
430 { 480 {
431 char *msg; 481 char *msg;
432 482
433 msg = macroexpand(p2, line, strlen(line), false); 483 msg = macroexpand(p2, line, strlen(line), false);
434 complain(p, "#warning: %s", msg); 484 complain(p, "#warning: %s", msg);
438 dostrfree(msg); 488 dostrfree(msg);
439 } 489 }
440 490
441 static 491 static
442 void 492 void
443 d_error(struct place *p, struct place *p2, char *line) 493 d_error(struct place *p, struct place *p2, struct place *np, char *line)
444 { 494 {
445 char *msg; 495 char *msg;
446 496
447 msg = macroexpand(p2, line, strlen(line), false); 497 msg = macroexpand(p2, line, strlen(line), false);
448 complain(p, "#error: %s", msg); 498 complain(p, "#error: %s", msg);
453 //////////////////////////////////////////////////////////// 503 ////////////////////////////////////////////////////////////
454 // other 504 // other
455 505
456 static 506 static
457 void 507 void
458 d_pragma(struct place *p, struct place *p2, char *line) 508 d_pragma(struct place *p, struct place *p2, struct place *np, char *line)
459 { 509 {
460 (void)p2; 510 (void)p2;
461 511
462 complain(p, "#pragma %s", line); 512 complain(p, "#pragma %s", line);
463 complain_fail(); 513 complain_fail();
467 // directive table 517 // directive table
468 518
469 static const struct { 519 static const struct {
470 const char *name; 520 const char *name;
471 bool ifskip; 521 bool ifskip;
472 void (*func)(struct place *, struct place *, char *line); 522 void (*func)(struct place *, struct place *, struct place *,
523 char *line);
473 } directives[] = { 524 } directives[] = {
474 { "define", true, d_define }, 525 { "define", true, d_define },
475 { "elif", false, d_elif }, 526 { "elif", false, d_elif },
476 { "else", false, d_else }, 527 { "else", false, d_else },
477 { "endif", false, d_endif }, 528 { "endif", false, d_endif },
487 }; 538 };
488 static const unsigned numdirectives = HOWMANY(directives); 539 static const unsigned numdirectives = HOWMANY(directives);
489 540
490 static 541 static
491 void 542 void
492 directive_gotdirective(struct place *p, char *line) 543 directive_gotdirective(struct place *p, struct place *np, char *line)
493 { 544 {
494 struct place p2; 545 struct place p2;
495 size_t len, skip; 546 size_t len, skip;
496 unsigned i; 547 unsigned i;
497 548
510 len = strlen(line); 561 len = strlen(line);
511 len = notrailingws(line, len); 562 len = notrailingws(line, len);
512 if (len < strlen(line)) { 563 if (len < strlen(line)) {
513 line[len] = '\0'; 564 line[len] = '\0';
514 } 565 }
515 directives[i].func(p, &p2, line); 566 directives[i].func(p, &p2, np, line);
516 return; 567 return;
517 } 568 }
518 } 569 }
519 /* ugh. allow # by itself, including with a comment after it */ 570 /* ugh. allow # by itself, including with a comment after it */
520 uncomment(line); 571 uncomment(line);
572 assert(!incomment); 623 assert(!incomment);
573 return len; 624 return len;
574 } 625 }
575 626
576 void 627 void
577 directive_gotline(struct place *p, char *line, size_t len) 628 directive_gotline(struct place *p, struct place *np, char *line, size_t len)
578 { 629 {
579 size_t skip; 630 size_t skip;
580 631
581 if (warns.nestcomment) { 632 if (warns.nestcomment) {
582 directive_scancomments(p, line, len); 633 directive_scancomments(p, line, len);
586 if (line[0] == '#') { 637 if (line[0] == '#') {
587 skip = 1 + strspn(line + 1, ws); 638 skip = 1 + strspn(line + 1, ws);
588 assert(skip <= len); 639 assert(skip <= len);
589 p->column += skip; 640 p->column += skip;
590 assert(line[len] == '\0'); 641 assert(line[len] == '\0');
591 directive_gotdirective(p, line+skip /*, length = len-skip */); 642 directive_gotdirective(p, np, line+skip);
592 p->column += len-skip; 643 p->column += len-skip;
593 } else if (ifstate->curtrue) { 644 } else if (ifstate->curtrue) {
594 macro_sendline(p, line, len); 645 macro_sendline(p, line, len);
595 p->column += len; 646 p->column += len;
596 } 647 }