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)