| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | #ifdef _MSC_VER |
| 21 | # define _POSIX_ |
| 22 | #endif |
| 23 | #include <stdio.h> |
| 24 | #include <stdlib.h> |
| 25 | #include <string.h> |
| 26 | #if defined(__IBMC__) || defined(__EMX__) |
| 27 | # define PATH_MAX4096 _MAX_PATH |
| 28 | #endif |
| 29 | #include <limits.h> |
| 30 | |
| 31 | #include "cpp.h" |
| 32 | |
| 33 | #define NCONCAT16384 16384 |
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | void |
| 39 | dodefine(Tokenrow * trp) |
| 40 | { |
| 41 | Token *tp; |
| 42 | Nlist *np; |
| 43 | Source *s; |
| 44 | Tokenrow *def, *args; |
| 45 | static uchar location[(PATH_MAX4096 + 8) * NINC32], *cp; |
| 46 | |
| 47 | tp = trp->tp + 1; |
| 48 | if (tp >= trp->lp || tp->type != NAME) |
| 49 | { |
| 50 | error(ERROR, "#defined token is not a name"); |
| 51 | return; |
| 52 | } |
| 53 | np = lookup(tp, 1); |
| 54 | if (np->flag & ISUNCHANGE0x04) |
| 55 | { |
| 56 | error(ERROR, "#defined token %t can't be redefined", tp); |
| 57 | return; |
| 58 | } |
| 59 | |
| 60 | tp += 1; |
| 61 | args = NULL((void*)0); |
| 62 | if (tp < trp->lp && tp->type == LP && tp->wslen == 0) |
| 63 | { |
| 64 | tp += 1; |
| 65 | args = new(Tokenrow)(Tokenrow *)domalloc(sizeof(Tokenrow)); |
| 66 | maketokenrow(2, args); |
| 67 | if (tp->type != RP) |
| 68 | { |
| 69 | |
| 70 | size_t narg = 0; |
| 71 | int err = 0; |
| 72 | |
| 73 | for (;;) |
| 74 | { |
| 75 | Token *atp; |
| 76 | |
| 77 | if (tp->type != NAME) |
| 78 | { |
| 79 | err++; |
| 80 | break; |
| 81 | } |
| 82 | if (narg >= args->max) |
| 83 | growtokenrow(args); |
| 84 | for (atp = args->bp; atp < args->lp; atp++) |
| 85 | if (atp->len == tp->len |
| 86 | && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0) |
| 87 | error(ERROR, "Duplicate macro argument"); |
| 88 | *args->lp++ = *tp; |
| 89 | narg++; |
| 90 | tp += 1; |
| 91 | if (tp->type == RP) |
| 92 | break; |
| 93 | if (tp->type != COMMA) |
| 94 | { |
| 95 | err++; |
| 96 | break; |
| 97 | } |
| 98 | tp += 1; |
| 99 | } |
| 100 | if (err) |
| 101 | { |
| 102 | error(ERROR, "Syntax error in macro parameters"); |
| 103 | return; |
| 104 | } |
| 105 | } |
| 106 | tp += 1; |
| 107 | } |
| 108 | trp->tp = tp; |
| 109 | if (((trp->lp) - 1)->type == NL) |
| 110 | trp->lp -= 1; |
| 111 | def = normtokenrow(trp); |
| 112 | if (np->flag & ISDEFINED0x01) |
| 113 | { |
| 114 | if (comparetokens(def, np->vp) |
| 115 | || (np->ap == NULL((void*)0)) != (args == NULL((void*)0)) |
| 116 | || (np->ap && comparetokens(args, np->ap))) |
| 117 | { |
| 118 | if ( np->loc ) |
| 119 | error(ERROR, |
| 120 | "Macro redefinition of %t (already defined at %s)", |
| 121 | trp->bp + 2, np->loc); |
| 122 | else |
| 123 | error(ERROR, |
| 124 | "Macro redefinition of %t (already defined at %s)", |
| 125 | trp->bp + 2, "commandline" ); |
| 126 | } |
| 127 | } |
| 128 | if (args) |
| 129 | { |
| 130 | Tokenrow *tap; |
| 131 | |
| 132 | tap = normtokenrow(args); |
| 133 | dofree(args->bp); |
| 134 | args = tap; |
| 135 | } |
| 136 | np->ap = args; |
| 137 | np->vp = def; |
| 138 | np->flag |= ISDEFINED0x01; |
| 139 | |
| 140 | |
| 141 | for (cp = location, s = cursource; s; s = s->next) |
| 142 | if (*s->filename) |
| 143 | { |
| 144 | if (cp != location) |
| 145 | *cp++ = ' '; |
| 146 | sprintf((char *)cp, "%s:%d", s->filename, s->line); |
| 147 | cp += strlen((char *)cp); |
| 148 | } |
| 149 | |
| 150 | np->loc = newstring(location, strlen((char *)location), 0); |
| 151 | |
| 152 | if (Mflag) |
| 153 | { |
| 154 | if (np->ap) |
| 155 | error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp); |
| 156 | else |
| 157 | error(INFO, "Macro definition of %s [%r]", np->name, np->vp); |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | |
| 162 | |
| 163 | |
| 164 | void |
| 165 | doadefine(Tokenrow * trp, int type) |
| 166 | { |
| 167 | Nlist *np; |
| 168 | static uchar onestr[2] = "1"; |
| 169 | static Token onetoken[1] = {{NUMBER, 0, 0, 1, onestr, 0}}; |
| 170 | static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1}; |
| 171 | |
| 172 | trp->tp = trp->bp; |
| 173 | if (type == 'U') |
| 174 | { |
| 175 | if (trp->lp - trp->tp != 2 || trp->tp->type != NAME) |
| 176 | goto syntax; |
| 177 | if ((np = lookup(trp->tp, 0)) == NULL((void*)0)) |
| 178 | return; |
| 179 | np->flag &= ~ISDEFINED0x01; |
| 180 | return; |
| 181 | } |
| 182 | |
| 183 | if (type == 'A') |
| 184 | { |
| 185 | if (trp->tp >= trp->lp || trp->tp->type != NAME) |
| 186 | goto syntax; |
| 187 | trp->tp->type = ARCHITECTURE; |
| 188 | np = lookup(trp->tp, 1); |
| 189 | np->flag |= ISARCHITECTURE0x10; |
| 190 | trp->tp += 1; |
| 191 | if (trp->tp >= trp->lp || trp->tp->type == END) |
| 192 | { |
| 193 | np->vp = &onetr; |
| 194 | return; |
| 195 | } |
| 196 | else |
| 197 | error(FATAL, "Illegal -A argument %r", trp); |
| 198 | } |
| 199 | |
| 200 | if (trp->tp >= trp->lp || trp->tp->type != NAME) |
| 201 | goto syntax; |
| 202 | np = lookup(trp->tp, 1); |
| 203 | np->flag |= ISDEFINED0x01; |
| 204 | trp->tp += 1; |
| 205 | if (trp->tp >= trp->lp || trp->tp->type == END) |
| 206 | { |
| 207 | np->vp = &onetr; |
| 208 | return; |
| 209 | } |
| 210 | if (trp->tp->type != ASGN) |
| 211 | goto syntax; |
| 212 | trp->tp += 1; |
| 213 | if ((trp->lp - 1)->type == END) |
| 214 | trp->lp -= 1; |
| 215 | np->vp = normtokenrow(trp); |
| 216 | return; |
| 217 | syntax: |
| 218 | error(FATAL, "Illegal -D or -U argument %r", trp); |
| 219 | } |
| 220 | |
| 221 | |
| 222 | |
| 223 | |
| 224 | |
| 225 | |
| 226 | |
| 227 | void |
| 228 | expandrow(Tokenrow * trp, char *flag) |
| 229 | { |
| 230 | Token * tp; |
| 231 | Nlist * np; |
| 232 | |
| 233 | MacroValidatorList validators; |
| 234 | mvl_init(&validators); |
| 235 | |
| 236 | tokenrow_zeroTokenIdentifiers(trp); |
| 237 | |
| 238 | if (flag) |
| 239 | setsource(flag, -1, -1, "", 0); |
| 240 | for (tp = trp->tp; tp < trp->lp;) |
| 241 | { |
| 242 | mvl_check(&validators, tp); |
| 243 | |
| 244 | if (tp->type != NAME |
| 245 | || quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0)(namebit[(tp->t[0])&077] & (1<<((tp->len > 1 ? tp->t[1] : 0)&037))) == 0 |
| 246 | || (np = lookup(tp, 0)) == NULL((void*)0) |
| 247 | || (np->flag & (ISDEFINED0x01 | ISMAC0x08)) == 0 |
| 248 | || (np->flag & ISACTIVE0x80) != 0) |
| 249 | { |
| 250 | tp++; |
| 251 | continue; |
| 252 | } |
| 253 | trp->tp = tp; |
| 254 | if (np->val == KDEFINED) |
| 255 | { |
| 256 | tp->type = DEFINED; |
| 257 | if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) |
| 258 | (tp + 1)->type = NAME1; |
| 259 | else |
| 260 | if ((tp + 3) < trp->lp && (tp + 1)->type == LP |
| 261 | && (tp + 2)->type == NAME && (tp + 3)->type == RP) |
| 262 | (tp + 2)->type = NAME1; |
| 263 | else |
| 264 | error(ERROR, "Incorrect syntax for `defined'"); |
| 265 | tp++; |
| 266 | continue; |
| 267 | } |
| 268 | else |
| 269 | if (np->val == KMACHINE) |
| 270 | { |
| 271 | if (((tp - 1) >= trp->bp) && ((tp - 1)->type == SHARP)) |
| 272 | { |
| 273 | tp->type = ARCHITECTURE; |
| 274 | if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) |
| 275 | (tp + 1)->type = NAME2; |
| 276 | else |
| 277 | if ((tp + 3) < trp->lp && (tp + 1)->type == LP |
| 278 | && (tp + 2)->type == NAME && (tp + 3)->type == RP) |
| 279 | (tp + 2)->type = NAME2; |
| 280 | else |
| 281 | error(ERROR, "Incorrect syntax for `#machine'"); |
| 282 | } |
| 283 | tp++; |
| 284 | continue; |
| 285 | } |
| 286 | |
| 287 | if (np->flag & ISMAC0x08) |
| 288 | builtin(trp, np->val); |
| 289 | else |
| 290 | expand(trp, np, &validators); |
| 291 | tp = trp->tp; |
| 292 | } |
| 293 | if (flag) |
| 294 | unsetsource(); |
| 295 | |
| 296 | mvl_destruct(&validators); |
| 297 | } |
| 298 | |
| 299 | |
| 300 | |
| 301 | |
| 302 | |
| 303 | |
| 304 | |
| 305 | |
| 306 | |
| 307 | void |
| 308 | expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators) |
| 309 | { |
| 310 | Tokenrow ntr; |
| 311 | int ntokc, narg; |
| 312 | Tokenrow *atr[NARG32 + 1]; |
| 313 | |
| 314 | if (Mflag == 2) |
| 315 | { |
| 316 | if (np->ap) |
| 317 | error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap); |
| 318 | else |
| 319 | error(INFO, "Macro expansion of %t with %s", trp->tp, np->name); |
| 320 | } |
| 321 | |
| 322 | copytokenrow(&ntr, np->vp); |
| 323 | if (np->ap == NULL((void*)0)) |
| 324 | ntokc = 1; |
| 325 | else |
| 326 | { |
| 327 | int i; |
| 328 | |
| 329 | ntokc = gatherargs(trp, atr, &narg); |
| 330 | if (narg < 0) |
| 331 | { |
| 332 | trp->tp++; |
| 333 | return; |
| 334 | } |
| 335 | if (narg != rowlen(np->ap)((np->ap)->lp - (np->ap)->bp)) |
| 336 | { |
| 337 | error(ERROR, "Disagreement in number of macro arguments"); |
| 338 | trp->tp += ntokc; |
| 339 | return; |
| 340 | } |
| 341 | |
| 342 | |
| 343 | |
| 344 | |
| 345 | |
| 346 | |
| 347 | for (i = 1; i < ntokc; i++) |
| 348 | { |
| 349 | mvl_check(pValidators,trp->tp+i); |
| 350 | } |
| 351 | |
| 352 | substargs(np, &ntr, atr); |
| 353 | for (i = 0; i < narg; i++) |
| 354 | { |
| 355 | dofree(atr[i]->bp); |
| 356 | dofree(atr[i]); |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | doconcat(&ntr); |
| 361 | ntr.tp = ntr.bp; |
| 362 | makespace(&ntr, trp->tp); |
| 363 | |
| 364 | tokenrow_zeroTokenIdentifiers(&ntr); |
| 365 | insertrow(trp, ntokc, &ntr); |
| 366 | |
| 367 | |
| 368 | |
| 369 | np->flag |= ISACTIVE0x80; |
| 370 | if (trp->tp != trp->lp) |
| 371 | { |
| 372 | mvl_add(pValidators,np,trp->tp); |
| 373 | } |
| 374 | else |
| 375 | { |
| 376 | mvl_add(pValidators,np,0); |
| 377 | } |
| 378 | |
| 379 | |
| 380 | trp->tp -= ntr.lp - ntr.bp; |
| 381 | |
| 382 | dofree(ntr.bp); |
| 383 | |
| 384 | return; |
| 385 | } |
| 386 | |
| 387 | |
| 388 | |
| 389 | |
| 390 | |
| 391 | |
| 392 | int |
| 393 | gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg) |
| 394 | { |
| 395 | int parens = 1; |
| 396 | int ntok = 0; |
| 397 | Token *bp, *lp; |
| 398 | Tokenrow ttr; |
| 399 | int ntokp; |
| 400 | int needspace; |
| 401 | |
| 402 | *narg = -1; |
| 403 | |
| 404 | |
| 405 | for (;;) |
| 406 | { |
| 407 | trp->tp++; |
| 408 | ntok++; |
| 409 | if (trp->tp >= trp->lp) |
| 410 | { |
| 411 | gettokens(trp, 0); |
| 412 | if ((trp->lp - 1)->type == END) |
| 413 | { |
| 414 | trp->lp -= 1; |
| 415 | trp->tp -= ntok; |
| 416 | return ntok; |
| 417 | } |
| 418 | } |
| 419 | if (trp->tp->type == LP) |
| 420 | break; |
| 421 | if (trp->tp->type != NL) |
| 422 | return ntok; |
| 423 | } |
| 424 | *narg = 0; |
| 425 | ntok++; |
| 426 | ntokp = ntok; |
| 427 | trp->tp++; |
| 428 | |
| 429 | needspace = 0; |
| 430 | while (parens > 0) |
| 431 | { |
| 432 | if (trp->tp >= trp->lp) |
| 433 | gettokens(trp, 0); |
| 434 | if (needspace) |
| 435 | { |
| 436 | needspace = 0; |
| 437 | |
| 438 | } |
| 439 | if (trp->tp->type == END) |
| 440 | { |
| 441 | trp->lp -= 1; |
| 442 | trp->tp -= ntok; |
| 443 | error(ERROR, "EOF in macro arglist"); |
| 444 | return ntok; |
| 445 | } |
| 446 | if (trp->tp->type == NL) |
| 447 | { |
| 448 | trp->tp += 1; |
| 449 | adjustrow(trp, -1); |
| 450 | trp->tp -= 1; |
| 451 | |
| 452 | needspace = 1; |
| 453 | continue; |
| 454 | } |
| 455 | if (trp->tp->type == LP) |
| 456 | parens++; |
| 457 | else |
| 458 | if (trp->tp->type == RP) |
| 459 | parens--; |
| 460 | trp->tp++; |
| 461 | ntok++; |
| 462 | } |
| 463 | trp->tp -= ntok; |
| 464 | |
| 465 | lp = bp = trp->tp + ntokp; |
| 466 | for (; parens >= 0; lp++) |
| 467 | { |
| 468 | if (lp->type == LP) |
| 469 | { |
| 470 | parens++; |
| 471 | continue; |
| 472 | } |
| 473 | if (lp->type == RP) |
| 474 | parens--; |
| 475 | if (lp->type == DSHARP) |
| 476 | lp->type = DSHARP1; |
| 477 | if ((lp->type == COMMA && parens == 0) || |
| 478 | ( parens < 0 && ((lp - 1)->type != LP))) |
| 479 | { |
| 480 | if (*narg >= NARG32 - 1) |
| 481 | error(FATAL, "Sorry, too many macro arguments"); |
| 482 | ttr.bp = ttr.tp = bp; |
| 483 | ttr.lp = lp; |
| 484 | atr[(*narg)++] = normtokenrow(&ttr); |
| 485 | bp = lp + 1; |
| 486 | } |
| 487 | } |
| 488 | return ntok; |
| 489 | } |
| 490 | |
| 491 | |
| 492 | |
| 493 | |
| 494 | |
| 495 | void |
| 496 | substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr) |
| 497 | { |
| 498 | Tokenrow tatr; |
| 499 | Token *tp; |
| 500 | int ntok, argno; |
| 501 | |
| 502 | for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;) |
| 503 | { |
| 504 | if (rtr->tp->type == SHARP) |
| 505 | { |
| 506 | tp = rtr->tp; |
| 507 | rtr->tp += 1; |
| 508 | if ((argno = lookuparg(np, rtr->tp)) < 0) |
| 509 | { |
| 510 | error(ERROR, "# not followed by macro parameter"); |
| 511 | continue; |
| 512 | } |
| 513 | ntok = 1 + (int)(rtr->tp - tp); |
| 514 | rtr->tp = tp; |
| 515 | insertrow(rtr, ntok, stringify(atr[argno])); |
| 516 | continue; |
| 517 | } |
| 518 | if (rtr->tp->type == NAME |
| 519 | && (argno = lookuparg(np, rtr->tp)) >= 0) |
| 520 | { |
| 521 | if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP) |
| 522 | || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) |
| 523 | { |
| 524 | copytokenrow(&tatr, atr[argno]); |
| 525 | makespace(&tatr, rtr->tp); |
| 526 | insertrow(rtr, 1, &tatr); |
| 527 | dofree(tatr.bp); |
| 528 | } |
| 529 | else |
| 530 | { |
| 531 | copytokenrow(&tatr, atr[argno]); |
| 532 | makespace(&tatr, rtr->tp); |
| 533 | expandrow(&tatr, "<macro>"); |
| 534 | insertrow(rtr, 1, &tatr); |
| 535 | dofree(tatr.bp); |
| 536 | } |
| 537 | continue; |
| 538 | } |
| 539 | rtr->tp++; |
| 540 | } |
| 541 | } |
| 542 | |
| 543 | |
| 544 | |
| 545 | |
| 546 | void |
| 547 | doconcat(Tokenrow * trp) |
| 548 | { |
| 549 | Token *ltp, *ntp; |
| 550 | Tokenrow ntr; |
| 551 | size_t len; |
| 552 | |
| 553 | for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++) |
| 554 | { |
| 555 | if (trp->tp->type == DSHARP1) |
| 556 | trp->tp->type = DSHARP; |
| 557 | else |
| 558 | if (trp->tp->type == DSHARP) |
| 559 | { |
| 560 | int i; |
| 561 | char tt[NCONCAT16384]; |
| 562 | |
| 563 | ltp = trp->tp - 1; |
| 564 | ntp = trp->tp + 1; |
| 565 | |
| 566 | if (ltp < trp->bp || ntp >= trp->lp) |
| 567 | { |
| 568 | error(ERROR, "## occurs at border of replacement"); |
| 569 | continue; |
| 570 | } |
| 571 | |
| 572 | ntp = ltp; |
| 573 | i = 1; |
| 574 | len = 0; |
| 575 | |
| 576 | do |
| 577 | { |
| 578 | if (len + ntp->len + ntp->wslen > sizeof(tt)) |
| 579 | { |
| 580 | error(ERROR, "## string concatination buffer overrun"); |
| 581 | break; |
| 582 | } |
| 583 | |
| 584 | if (ntp != trp->tp + 1) |
| 585 | { |
| 586 | strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen, |
| 587 | ntp->len + ntp->wslen); |
| 588 | len += ntp->len + ntp->wslen; |
| 589 | } |
| 590 | else |
| 591 | { |
| 592 | strncpy((char *) tt + len, (char *) ntp->t, ntp->len); |
| 593 | len += ntp->len; |
| 594 | } |
| 595 | |
| 596 | ntp = trp->tp + i; |
| 597 | i++; |
| 598 | } |
| 599 | while (ntp < trp->lp); |
| 600 | |
| 601 | tt[len] = '\0'; |
| 602 | setsource("<##>", -1, -1, tt, 0); |
| 603 | maketokenrow(3, &ntr); |
| 604 | gettokens(&ntr, 1); |
| 605 | unsetsource(); |
| 606 | if (ntr.bp->type == UNCLASS) |
| 607 | error(WARNING, "Bad token %r produced by ##", &ntr); |
| 608 | while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp) |
| 609 | ntr.lp--; |
| 610 | |
| 611 | doconcat(&ntr); |
| 612 | trp->tp = ltp; |
| 613 | makespace(&ntr, ltp); |
| 614 | insertrow(trp, (int)(ntp - ltp), &ntr); |
| 615 | dofree(ntr.bp); |
| 616 | trp->tp--; |
| 617 | } |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | |
| 622 | |
| 623 | |
| 624 | |
| 625 | |
| 626 | int |
| 627 | lookuparg(Nlist * mac, Token * tp) |
| 628 | { |
| 629 | Token *ap; |
| 630 | |
| 631 | if (tp->type != NAME || mac->ap == NULL((void*)0)) |
| 632 | return -1; |
| 633 | for (ap = mac->ap->bp; ap < mac->ap->lp; ap++) |
| 634 | { |
| 635 | if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0) |
| 636 | return (int)(ap - mac->ap->bp); |
| 637 | } |
| 638 | return -1; |
| 639 | } |
| 640 | |
| 641 | |
| 642 | |
| 643 | |
| 644 | #define STRLEN512 512 |
| 645 | Tokenrow * |
| 646 | stringify(Tokenrow * vp) |
| 647 | { |
| 648 | static Token t = {STRING, 0, 0, 0, NULL((void*)0), 0}; |
| 649 | static Tokenrow tr = {&t, &t, &t + 1, 1}; |
| 650 | Token *tp; |
| 651 | uchar s[STRLEN512]; |
| 652 | uchar *sp = s, *cp; |
| 653 | int i, instring; |
| 654 | |
| 655 | *sp++ = '"'; |
| 656 | for (tp = vp->bp; tp < vp->lp; tp++) |
| 657 | { |
| 658 | instring = tp->type == STRING || tp->type == CCON; |
| 659 | if (sp + 2 * tp->len + tp->wslen >= &s[STRLEN512 - 10]) |
| 660 | { |
| 661 | error(ERROR, "Stringified macro arg is too long"); |
| 662 | break; |
| 663 | } |
| 664 | |
| 665 | |
| 666 | if ( tp->wslen > 0 ) |
| 667 | *sp++ = ' '; |
| 668 | |
| 669 | |
| 670 | for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++) |
| 671 | { |
| 672 | if (instring && (*cp == '"' || *cp == '\\')) |
| 673 | *sp++ = '\\'; |
| 674 | *sp++ = *cp++; |
| 675 | } |
| 676 | } |
| 677 | *sp++ = '"'; |
| 678 | *sp = '\0'; |
| 679 | sp = s; |
| 680 | t.len = strlen((char *) sp); |
| 681 | t.t = newstring(sp, t.len, 0); |
| 682 | return &tr; |
| 683 | } |
| 684 | |
| 685 | |
| 686 | |
| 687 | |
| 688 | void |
| 689 | builtin(Tokenrow * trp, int biname) |
| 690 | { |
| 691 | char *op; |
| 692 | Token *tp; |
| 693 | Source *s; |
| 694 | |
| 695 | tp = trp->tp; |
| 696 | trp->tp++; |
| 697 | |
| 698 | s = cursource; |
| 699 | while (s && s->fd == -1) |
| 700 | s = s->next; |
| 701 | if (s == NULL((void*)0)) |
| |
| 702 | s = cursource; |
| 2 | | Null pointer value stored to 's' | |
|
| 703 | |
| 704 | tp->type = STRING; |
| 705 | if (tp->wslen) |
| |
| 706 | { |
| 707 | *outptr++ = ' '; |
| 708 | tp->wslen = 1; |
| 709 | } |
| 710 | op = outptr; |
| 711 | *op++ = '"'; |
| 712 | switch (biname) |
| 4 | | Control jumps to 'case KFILE:' at line 720 | |
|
| 713 | { |
| 714 | |
| 715 | case KLINENO: |
| 716 | tp->type = NUMBER; |
| 717 | op = outnum(op - 1, s->line); |
| 718 | break; |
| 719 | |
| 720 | case KFILE: |
| 721 | { |
| 722 | char *src = s->filename; |
| 5 | | Access to field 'filename' results in a dereference of a null pointer (loaded from variable 's') |
|
| 723 | |
| 724 | while ((*op++ = *src++) != 0) |
| 725 | if (src[-1] == '\\') |
| 726 | *op++ = '\\'; |
| 727 | op--; |
| 728 | break; |
| 729 | } |
| 730 | |
| 731 | case KDATE: |
| 732 | strncpy(op, curtime + 4, 7); |
| 733 | strncpy(op + 7, curtime + 20, 4); |
| 734 | op += 11; |
| 735 | break; |
| 736 | |
| 737 | case KTIME: |
| 738 | strncpy(op, curtime + 11, 8); |
| 739 | op += 8; |
| 740 | break; |
| 741 | |
| 742 | default: |
| 743 | error(ERROR, "cpp botch: unknown internal macro"); |
| 744 | return; |
| 745 | } |
| 746 | if (tp->type == STRING) |
| 747 | *op++ = '"'; |
| 748 | tp->t = (uchar *) outptr; |
| 749 | tp->len = op - outptr; |
| 750 | outptr = op; |
| 751 | } |
| 752 | |
| 753 | |