| 1 | #include <stdio.h> |
| 2 | #include <signal.h> |
| 3 | |
| 4 | #define ERROR NULL |
| 5 | #define READ "r" |
| 6 | #define WRITE "w" |
| 7 | |
| 8 | #define EOS 0 |
| 9 | int lpar = '('; |
| 10 | #define LPAR lpar |
| 11 | #define RPAR ')' |
| 12 | #define COMMA ',' |
| 13 | #define GRAVE '`' |
| 14 | #define ACUTE '\'' |
| 15 | #define LBRAK '[' |
| 16 | #define RBRAK ']' |
| 17 | #ifdef M4 |
| 18 | char lquote LBRAK; |
| 19 | char rquote RBRAK; |
| 20 | #endif |
| 21 | #ifndef M4 |
| 22 | char lquote = GRAVE; |
| 23 | char rquote = ACUTE; |
| 24 | #endif |
| 25 | #define COMMENT '#' |
| 26 | #define ALPH 1 |
| 27 | #define DIG 2 |
| 28 | |
| 29 | #define HSHSIZ 199 /* prime */ |
| 30 | #define STACKS 50 |
| 31 | #define SAVS 4096 |
| 32 | #define TOKS 128 |
| 33 | |
| 34 | #define putbak(c) *ip++ = c; |
| 35 | #define getchr() (ip>cur_ip?*--ip: getc(infile[infptr])) |
| 36 | #define putchr(c) if (cp==NULL) {if (curfile)putc(c,curfile);} else *op++ = c |
| 37 | char type[] = { |
| 38 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 39 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 40 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 41 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 42 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 43 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 44 | DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, |
| 45 | DIG, DIG, 0, 0, 0, 0, 0, 0, |
| 46 | 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, |
| 47 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, |
| 48 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, |
| 49 | ALPH, ALPH, ALPH, 0, 0, 0, 0, ALPH, |
| 50 | 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, |
| 51 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, |
| 52 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, |
| 53 | ALPH, ALPH, ALPH, 0, 0, 0, 0, 0, |
| 54 | }; |
| 55 | |
| 56 | char token[TOKS]; |
| 57 | char eoa[] = "\0"; |
| 58 | struct nlist { |
| 59 | char *name; |
| 60 | char *def; |
| 61 | struct nlist *next; |
| 62 | }; |
| 63 | |
| 64 | struct nlist *hshtab[HSHSIZ]; |
| 65 | char ibuf[SAVS+TOKS]; |
| 66 | char obuf[SAVS+TOKS]; |
| 67 | char *op = obuf; |
| 68 | char *ip = ibuf; |
| 69 | char *ip_stk[10] = {ibuf}; |
| 70 | char *cur_ip = ibuf; |
| 71 | struct call { |
| 72 | char **argp; |
| 73 | int plev; |
| 74 | }; |
| 75 | struct call *cp = NULL; |
| 76 | |
| 77 | char *makeloc; |
| 78 | char *ifdefloc; |
| 79 | char *lenloc; |
| 80 | char *undefloc; |
| 81 | char *shiftloc; |
| 82 | char *cqloc; |
| 83 | char *defloc; |
| 84 | char *evaloc; |
| 85 | char *incrloc; |
| 86 | char *substrloc; |
| 87 | char *indexloc; |
| 88 | char *transloc; |
| 89 | char *ifloc; |
| 90 | char *divloc; |
| 91 | char *divnumloc; |
| 92 | char *undivloc; |
| 93 | char *dnlloc; |
| 94 | char *inclloc; |
| 95 | char *sinclloc; |
| 96 | char *syscmdloc; |
| 97 | char *dumploc; |
| 98 | char *errploc; |
| 99 | |
| 100 | char *tempname; |
| 101 | struct nlist *lookup(); |
| 102 | char *install(); |
| 103 | char *malloc(); |
| 104 | char *mktemp(); |
| 105 | char *copy(); |
| 106 | long ctol(); |
| 107 | int hshval; |
| 108 | FILE *olist[11] = { stdout }; |
| 109 | int okret; |
| 110 | int curout = 0; |
| 111 | FILE *curfile = { stdout }; |
| 112 | FILE *infile[10] = { stdin }; |
| 113 | int infptr = 0; |
| 114 | |
| 115 | main(argc, argv) |
| 116 | char **argv; |
| 117 | { |
| 118 | char *argstk[STACKS+10]; |
| 119 | struct call callst[STACKS]; |
| 120 | register char *tp, **ap; |
| 121 | int delexit(), catchsig(); |
| 122 | register t; |
| 123 | int i; |
| 124 | |
| 125 | #ifdef gcos |
| 126 | #ifdef M4 |
| 127 | install("GCOS", eoa); |
| 128 | #endif |
| 129 | #ifndef M4 |
| 130 | install("gcos", eoa); |
| 131 | #endif |
| 132 | #endif |
| 133 | #ifdef unix |
| 134 | #ifdef M4 |
| 135 | install("UNIX", eoa); |
| 136 | #endif |
| 137 | #ifndef M4 |
| 138 | install("unix", eoa); |
| 139 | #endif |
| 140 | #endif |
| 141 | |
| 142 | #ifdef M4 |
| 143 | makeloc = install("MAKETEMP", eoa); |
| 144 | ifdefloc = install("IFDEF", eoa); |
| 145 | lenloc = install("LEN", eoa); |
| 146 | undefloc = install("UNDEFINE", eoa); |
| 147 | shiftloc = install("SHIFT", eoa); |
| 148 | cqloc = install("CHANGEQUOTE", eoa); |
| 149 | defloc = install("DEFINE", eoa); |
| 150 | evaloc = install("EVAL", eoa); |
| 151 | inclloc = install("INCLUDE", eoa); |
| 152 | sinclloc = install("SINCLUDE", eoa); |
| 153 | syscmdloc = install("SYSCMD", eoa); |
| 154 | dumploc = install("DUMPDEF", eoa); |
| 155 | errploc = install("ERRPRINT", eoa); |
| 156 | incrloc = install("INCR", eoa); |
| 157 | substrloc = install("SUBSTR", eoa); |
| 158 | indexloc = install("INDEX", eoa); |
| 159 | transloc = install("TRANSLIT", eoa); |
| 160 | ifloc = install("IFELSE", eoa); |
| 161 | divloc = install("DIVERT", eoa); |
| 162 | divnumloc = install("DIVNUM", eoa); |
| 163 | undivloc = install("UNDIVERT", eoa); |
| 164 | dnlloc = install("DNL", eoa); |
| 165 | #endif |
| 166 | |
| 167 | #ifndef M4 |
| 168 | makeloc = install("maketemp", eoa); |
| 169 | ifdefloc = install("ifdef", eoa); |
| 170 | lenloc = install("len", eoa); |
| 171 | undefloc = install("undefine", eoa); |
| 172 | shiftloc = install("shift", eoa); |
| 173 | cqloc = install("changequote", eoa); |
| 174 | defloc = install("define", eoa); |
| 175 | evaloc = install("eval", eoa); |
| 176 | inclloc = install("include", eoa); |
| 177 | sinclloc = install("sinclude", eoa); |
| 178 | syscmdloc = install("syscmd", eoa); |
| 179 | dumploc = install("dumpdef", eoa); |
| 180 | errploc = install("errprint", eoa); |
| 181 | incrloc = install("incr", eoa); |
| 182 | substrloc = install("substr", eoa); |
| 183 | indexloc = install("index", eoa); |
| 184 | transloc = install("translit", eoa); |
| 185 | ifloc = install("ifelse", eoa); |
| 186 | divloc = install("divert", eoa); |
| 187 | divnumloc = install("divnum", eoa); |
| 188 | undivloc = install("undivert", eoa); |
| 189 | dnlloc = install("dnl", eoa); |
| 190 | #endif |
| 191 | ap = argstk; |
| 192 | #ifndef gcos |
| 193 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) |
| 194 | signal(SIGHUP, catchsig); |
| 195 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) |
| 196 | signal(SIGINT, catchsig); |
| 197 | tempname = mktemp("/tmp/m4aXXXXX"); |
| 198 | close(creat(tempname, 0)); |
| 199 | #endif |
| 200 | #ifdef gcos |
| 201 | tempname = "m4.tempa"; |
| 202 | #endif |
| 203 | if (argc>1) |
| 204 | putbak(0); |
| 205 | for (;;) { |
| 206 | tp = token; |
| 207 | *tp++ = t = getchr(); |
| 208 | *tp = EOS; |
| 209 | if (t<=0) { |
| 210 | if (infptr > 0) { |
| 211 | fclose(infile[infptr]); |
| 212 | infptr--; |
| 213 | cur_ip = ip_stk[infptr]; |
| 214 | continue; |
| 215 | } |
| 216 | if (argc<=1) |
| 217 | break; |
| 218 | argc--; |
| 219 | argv++; |
| 220 | if (infile[infptr]!=stdin) |
| 221 | fclose(infile[infptr]); |
| 222 | if (**argv=='-') |
| 223 | infile[infptr] = stdin; |
| 224 | else if ((infile[infptr]=fopen(argv[0], READ))==ERROR) { |
| 225 | fprintf(stderr, "m4: file not found: %s\n", argv[0]); |
| 226 | delexit(); |
| 227 | } |
| 228 | continue; |
| 229 | } |
| 230 | if (type[t]==ALPH) { |
| 231 | while ((t=type[*tp++=getchr()])==ALPH||t==DIG); |
| 232 | putbak(*--tp); |
| 233 | *tp = EOS; |
| 234 | if (*ap = lookup(token)->def) { |
| 235 | if (++ap >= &argstk[STACKS]) { |
| 236 | fprintf(stderr, "m4: arg stack overflow\n"); |
| 237 | delexit(); |
| 238 | } |
| 239 | if (cp==NULL) |
| 240 | cp = callst; |
| 241 | else if (++cp > &callst[STACKS]) { |
| 242 | fprintf(stderr, "m4: call stack overflow\n"); |
| 243 | delexit(); |
| 244 | } |
| 245 | cp->argp = ap; |
| 246 | *ap++ = op; |
| 247 | puttok(); |
| 248 | *op++ = '\0'; |
| 249 | t = getchr(); |
| 250 | putbak(t); |
| 251 | if (t!=LPAR) { |
| 252 | /* if (t!=' ' && t!='\t') */ |
| 253 | putbak(')'); |
| 254 | putbak('('); |
| 255 | } |
| 256 | else /* try to fix arg count */ |
| 257 | *ap++ = op; |
| 258 | cp->plev = 0; |
| 259 | } else |
| 260 | puttok(); |
| 261 | } else if (t==lquote) { |
| 262 | i = 1; |
| 263 | for (;;) { |
| 264 | t = getchr(); |
| 265 | if (t==rquote) { |
| 266 | i--; |
| 267 | if (i==0) |
| 268 | break; |
| 269 | } else if (t==lquote) |
| 270 | i++; |
| 271 | else if (t<0) { |
| 272 | fprintf(stderr, "m4: EOF in string\n"); |
| 273 | delexit(); |
| 274 | } |
| 275 | putchr(t); |
| 276 | } |
| 277 | } else if (t==COMMENT) { |
| 278 | putbak(t); |
| 279 | while ((t = getchr())!='\n'&& t>=0) |
| 280 | if (cp==NULL) |
| 281 | putchr(t); |
| 282 | putbak(t); |
| 283 | } else if (cp==NULL) { |
| 284 | puttok(); |
| 285 | } else if (t==LPAR) { |
| 286 | if (cp->plev) |
| 287 | *op++ = t; |
| 288 | cp->plev++; |
| 289 | while ( (t=getchr())==' ' || t=='\t' || t=='\n') |
| 290 | ; /* skip leading white space during arg collection */ |
| 291 | putbak(t); |
| 292 | /* |
| 293 | } else if (t==' ' || t=='\t' || t=='\n') { |
| 294 | continue; |
| 295 | */ |
| 296 | } else if (t==RPAR) { |
| 297 | cp->plev--; |
| 298 | if (cp->plev==0) { |
| 299 | *op++ = '\0'; |
| 300 | expand(cp->argp, ap-cp->argp-1); |
| 301 | op = *cp->argp; |
| 302 | ap = cp->argp-1; |
| 303 | cp--; |
| 304 | if (cp < callst) |
| 305 | cp = NULL; |
| 306 | } else |
| 307 | *op++ = t; |
| 308 | } else if (t==COMMA && cp->plev<=1) { |
| 309 | *op++ = '\0'; |
| 310 | *ap++ = op; |
| 311 | while ((t=getchr())==' ' || t=='\t' || t=='\n') |
| 312 | ; /* skip leading white space during arg collection */ |
| 313 | putbak(t); |
| 314 | } else |
| 315 | *op++ = t; |
| 316 | } |
| 317 | if (cp!=NULL) { |
| 318 | fprintf(stderr, "m4: unexpected EOF\n"); |
| 319 | delexit(); |
| 320 | } |
| 321 | okret = 1; |
| 322 | delexit(); |
| 323 | } |
| 324 | |
| 325 | catchsig() |
| 326 | { |
| 327 | okret = 0; |
| 328 | delexit(); |
| 329 | } |
| 330 | |
| 331 | delexit() |
| 332 | { |
| 333 | register FILE *fp; |
| 334 | register i, c; |
| 335 | |
| 336 | if (!okret) { |
| 337 | signal(SIGHUP, SIG_IGN); |
| 338 | signal(SIGINT, SIG_IGN); |
| 339 | } |
| 340 | for (i=1; i<10; i++) { |
| 341 | if (olist[i]==NULL) |
| 342 | continue; |
| 343 | fclose(olist[i]); |
| 344 | tempname[7] = 'a'+i; |
| 345 | if (okret) { |
| 346 | fp = fopen(tempname, READ); |
| 347 | while ((c = getc(fp)) > 0) |
| 348 | putchar(c); |
| 349 | fclose(fp); |
| 350 | } |
| 351 | unlink(tempname); |
| 352 | } |
| 353 | tempname[7] = 'a'; |
| 354 | unlink(tempname); |
| 355 | exit(1-okret); |
| 356 | } |
| 357 | |
| 358 | puttok() |
| 359 | { |
| 360 | register char *tp; |
| 361 | |
| 362 | tp = token; |
| 363 | if (cp) { |
| 364 | if (op >= &obuf[SAVS]) { |
| 365 | fprintf(stderr, "m4: argument overflow\n"); |
| 366 | delexit(); |
| 367 | } |
| 368 | while (*tp) |
| 369 | *op++ = *tp++; |
| 370 | } else if (curfile) |
| 371 | while (*tp) |
| 372 | putc(*tp++, curfile); |
| 373 | } |
| 374 | |
| 375 | pbstr(str) |
| 376 | register char *str; |
| 377 | { |
| 378 | register char *p; |
| 379 | |
| 380 | p = str; |
| 381 | while (*p++); |
| 382 | --p; |
| 383 | if (ip >= &ibuf[SAVS]) { |
| 384 | fprintf(stderr, "m4: pushback overflow\n"); |
| 385 | delexit(); |
| 386 | } |
| 387 | while (p > str) |
| 388 | putbak(*--p); |
| 389 | } |
| 390 | |
| 391 | expand(a1, c) |
| 392 | register char **a1; |
| 393 | { |
| 394 | register char *dp; |
| 395 | register n; |
| 396 | |
| 397 | dp = a1[-1]; |
| 398 | if (dp==defloc) |
| 399 | dodef(a1, c); |
| 400 | else if (dp==evaloc) |
| 401 | doeval(a1, c); |
| 402 | else if (dp==inclloc) |
| 403 | doincl(a1, c, 1); |
| 404 | else if (dp==sinclloc) |
| 405 | doincl(a1, c, 0); |
| 406 | else if (dp==makeloc) |
| 407 | domake(a1, c); |
| 408 | else if (dp==syscmdloc) |
| 409 | dosyscmd(a1, c); |
| 410 | else if (dp==incrloc) |
| 411 | doincr(a1, c); |
| 412 | else if (dp==substrloc) |
| 413 | dosubstr(a1, c); |
| 414 | else if (dp==indexloc) |
| 415 | doindex(a1, c); |
| 416 | else if (dp==transloc) |
| 417 | dotransl(a1, c); |
| 418 | else if (dp==ifloc) |
| 419 | doif(a1, c); |
| 420 | else if (dp==divloc) |
| 421 | dodiv(a1, c); |
| 422 | else if (dp==divnumloc) |
| 423 | dodivnum(a1, c); |
| 424 | else if (dp==undivloc) |
| 425 | doundiv(a1, c); |
| 426 | else if (dp==dnlloc) |
| 427 | dodnl(a1, c); |
| 428 | else if (dp==dumploc) |
| 429 | dodump(a1, c); |
| 430 | else if (dp==errploc) |
| 431 | doerrp(a1, c); |
| 432 | else if (dp==lenloc) |
| 433 | dolen(a1, c); |
| 434 | else if (dp==ifdefloc) |
| 435 | doifdef(a1, c); |
| 436 | else if (dp==undefloc) |
| 437 | doundef(a1, c); |
| 438 | else if (dp==shiftloc) |
| 439 | doshift(a1, c); |
| 440 | else if (dp==cqloc) |
| 441 | docq(a1, c); |
| 442 | else { |
| 443 | while (*dp++); |
| 444 | for (dp--; dp>a1[-1]; ) { |
| 445 | if (--dp>a1[-1] && dp[-1]=='$') { |
| 446 | n = *dp-'0'; |
| 447 | if (n>=0 && n<=9) { |
| 448 | if (n <= c) |
| 449 | pbstr(a1[n]); |
| 450 | dp--; |
| 451 | } else |
| 452 | putbak(*dp); |
| 453 | } else |
| 454 | putbak(*dp); |
| 455 | } |
| 456 | } |
| 457 | } |
| 458 | |
| 459 | struct nlist *lookup(str) |
| 460 | char *str; |
| 461 | { |
| 462 | register char *s1, *s2; |
| 463 | register struct nlist *np; |
| 464 | static struct nlist nodef; |
| 465 | |
| 466 | s1 = str; |
| 467 | for (hshval = 0; *s1; ) |
| 468 | hshval += *s1++; |
| 469 | hshval %= HSHSIZ; |
| 470 | for (np = hshtab[hshval]; np!=NULL; np = np->next) { |
| 471 | s1 = str; |
| 472 | s2 = np->name; |
| 473 | while (*s1++ == *s2) |
| 474 | if (*s2++ == EOS) |
| 475 | return(np); |
| 476 | } |
| 477 | return(&nodef); |
| 478 | } |
| 479 | |
| 480 | char *install(nam, val) |
| 481 | char *nam, *val; |
| 482 | { |
| 483 | register struct nlist *np; |
| 484 | |
| 485 | if ((np = lookup(nam))->name == NULL) { |
| 486 | np = (struct nlist *)malloc(sizeof(*np)); |
| 487 | if (np == NULL) { |
| 488 | fprintf(stderr, "m4: no space for alloc\n"); |
| 489 | exit(1); |
| 490 | } |
| 491 | np->name = copy(nam); |
| 492 | np->def = copy(val); |
| 493 | np->next = hshtab[hshval]; |
| 494 | hshtab[hshval] = np; |
| 495 | return(np->def); |
| 496 | } |
| 497 | free(np->def); |
| 498 | np->def = copy(val); |
| 499 | return(np->def); |
| 500 | } |
| 501 | |
| 502 | doundef(ap, c) |
| 503 | char **ap; |
| 504 | { |
| 505 | register struct nlist *np, *tnp; |
| 506 | |
| 507 | if (c < 1 || (np = lookup(ap[1]))->name == NULL) |
| 508 | return; |
| 509 | tnp = hshtab[hshval]; /* lookup sets hshval */ |
| 510 | if (tnp == np) /* it's in first place */ |
| 511 | hshtab[hshval] = np->next; |
| 512 | else { |
| 513 | for ( ; tnp->next != np; tnp = tnp->next) |
| 514 | ; |
| 515 | tnp->next = np->next; |
| 516 | } |
| 517 | free(np->name); |
| 518 | free(np->def); |
| 519 | free((char *)np); |
| 520 | } |
| 521 | |
| 522 | char *copy(s) |
| 523 | register char *s; |
| 524 | { |
| 525 | register char *p, *s1; |
| 526 | |
| 527 | p = s1 = malloc((unsigned)strlen(s)+1); |
| 528 | if (p == NULL) { |
| 529 | fprintf(stderr, "m4: no space for alloc\n"); |
| 530 | exit(1); |
| 531 | } |
| 532 | while (*s1++ = *s++); |
| 533 | return(p); |
| 534 | } |
| 535 | |
| 536 | dodef(ap, c) |
| 537 | char **ap; |
| 538 | { |
| 539 | if (c >= 2) { |
| 540 | if (strcmp(ap[1], ap[2]) == 0) { |
| 541 | fprintf(stderr, "m4: %s defined as itself\n", ap[1]); |
| 542 | delexit(); |
| 543 | } |
| 544 | install(ap[1], ap[2]); |
| 545 | } |
| 546 | else if (c == 1) |
| 547 | install(ap[1], ""); |
| 548 | } |
| 549 | |
| 550 | doifdef(ap, c) |
| 551 | char **ap; |
| 552 | { |
| 553 | register struct nlist *np; |
| 554 | |
| 555 | if (c < 2) |
| 556 | return; |
| 557 | if (lookup(ap[1])->name != NULL) |
| 558 | pbstr(ap[2]); |
| 559 | else if (c >= 3) |
| 560 | pbstr(ap[3]); |
| 561 | } |
| 562 | |
| 563 | dolen(ap, c) |
| 564 | char **ap; |
| 565 | { |
| 566 | putnum((long) strlen(ap[1])); |
| 567 | } |
| 568 | |
| 569 | docq(ap, c) |
| 570 | char **ap; |
| 571 | { |
| 572 | if (c > 1) { |
| 573 | lquote = *ap[1]; |
| 574 | rquote = *ap[2]; |
| 575 | } else if (c == 1) { |
| 576 | lquote = rquote = *ap[1]; |
| 577 | } else { |
| 578 | #ifndef M4 |
| 579 | lquote = GRAVE; |
| 580 | rquote = ACUTE; |
| 581 | #endif |
| 582 | #ifdef M4 |
| 583 | lquote = LBRAK; |
| 584 | rquote = RBRAK; |
| 585 | #endif |
| 586 | } |
| 587 | } |
| 588 | |
| 589 | doshift(ap, c) |
| 590 | char **ap; |
| 591 | { |
| 592 | fprintf(stderr, "m4: shift not yet implemented\n"); |
| 593 | } |
| 594 | |
| 595 | dodump(ap, c) |
| 596 | char **ap; |
| 597 | { |
| 598 | int i; |
| 599 | register struct nlist *np; |
| 600 | |
| 601 | if (c > 0) |
| 602 | while (c--) { |
| 603 | if ((np = lookup(*++ap))->name != NULL) |
| 604 | fprintf(stderr, "`%s' `%s'\n", np->name, np->def); |
| 605 | } |
| 606 | else |
| 607 | for (i=0; i<HSHSIZ; i++) |
| 608 | for (np=hshtab[i]; np!=NULL; np=np->next) |
| 609 | fprintf(stderr, "`%s' `%s'\n", np->name, np->def); |
| 610 | } |
| 611 | |
| 612 | doerrp(ap, c) |
| 613 | char **ap; |
| 614 | { |
| 615 | if (c > 0) { |
| 616 | fprintf(stderr, ap[1], ap[2], ap[3], ap[4], ap[5], ap[6]); |
| 617 | fprintf(stderr, "\n"); |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | |
| 622 | long evalval; /* return value from yacc stuff */ |
| 623 | char *pe; /* used by grammar */ |
| 624 | |
| 625 | doeval(ap, c) |
| 626 | char **ap; |
| 627 | { |
| 628 | |
| 629 | if (c > 0) { |
| 630 | pe = ap[1]; |
| 631 | if (yyparse() == 0) |
| 632 | putnum(evalval); |
| 633 | else |
| 634 | fprintf(stderr, "m4: invalid expression in eval: %s\n", ap[1]); |
| 635 | } |
| 636 | } |
| 637 | |
| 638 | doincl(ap, c, noisy) |
| 639 | char **ap; |
| 640 | { |
| 641 | if (c > 0 && strlen(ap[1]) > 0) { |
| 642 | infptr++; |
| 643 | ip_stk[infptr] = cur_ip = ip; |
| 644 | if ((infile[infptr] = fopen(ap[1], READ))==ERROR) { |
| 645 | if (noisy) { |
| 646 | fprintf(stderr, "m4: file not found: %s\n", ap[1]); |
| 647 | delexit(); |
| 648 | } |
| 649 | else |
| 650 | infptr--; |
| 651 | } |
| 652 | } |
| 653 | } |
| 654 | |
| 655 | dosyscmd(ap, c) |
| 656 | char **ap; |
| 657 | { |
| 658 | if (c > 0) |
| 659 | system(ap[1]); |
| 660 | } |
| 661 | |
| 662 | domake(ap, c) |
| 663 | char **ap; |
| 664 | { |
| 665 | if (c > 0) |
| 666 | pbstr(mktemp(ap[1])); |
| 667 | } |
| 668 | |
| 669 | doincr(ap, c) |
| 670 | char **ap; |
| 671 | { |
| 672 | if (c >= 1) |
| 673 | putnum(ctol(ap[1])+1); |
| 674 | } |
| 675 | |
| 676 | putnum(num) |
| 677 | long num; |
| 678 | { |
| 679 | register sign; |
| 680 | |
| 681 | sign = (num < 0) ? '-' : '\0'; |
| 682 | if (num < 0) |
| 683 | num = -num; |
| 684 | do { |
| 685 | putbak(num%10+'0'); |
| 686 | num = num/10; |
| 687 | } while (num!=0); |
| 688 | if (sign == '-') |
| 689 | putbak('-'); |
| 690 | } |
| 691 | |
| 692 | dosubstr(ap, c) |
| 693 | char **ap; |
| 694 | { |
| 695 | int nc; |
| 696 | register char *sp, *fc; |
| 697 | |
| 698 | if (c<2) |
| 699 | return; |
| 700 | if (c<3) |
| 701 | nc = TOKS; |
| 702 | else |
| 703 | nc = ctoi(ap[3]); |
| 704 | fc = ap[1] + max(0, min(ctoi(ap[2]), strlen(ap[1]))); |
| 705 | sp = fc + min(nc, strlen(fc)); |
| 706 | while (sp > fc) |
| 707 | putbak(*--sp); |
| 708 | } |
| 709 | |
| 710 | doindex(ap, c) |
| 711 | char **ap; |
| 712 | { |
| 713 | if (c >= 2) |
| 714 | putnum((long) strindex(ap[1], ap[2])); |
| 715 | } |
| 716 | |
| 717 | strindex(p1, p2) |
| 718 | char *p1, *p2; |
| 719 | { |
| 720 | register m; |
| 721 | register char *s, *t, *p; |
| 722 | |
| 723 | for (p=p1; *p; p++) { |
| 724 | s = p; |
| 725 | m = 1; |
| 726 | for (t=p2; *t; ) |
| 727 | if (*t++ != *s++) |
| 728 | m = 0; |
| 729 | if (m == 1) |
| 730 | return(p-p1); |
| 731 | } |
| 732 | return(-1); |
| 733 | } |
| 734 | |
| 735 | dotransl(ap, c) |
| 736 | char **ap; |
| 737 | { |
| 738 | register char *s, *fr, *to; |
| 739 | |
| 740 | if (c <= 1) return; |
| 741 | |
| 742 | if (c == 2) { |
| 743 | register int i; |
| 744 | to = ap[1]; |
| 745 | for (s = ap[1]; *s; s++) { |
| 746 | i = 0; |
| 747 | for (fr = ap[2]; *fr; fr++) |
| 748 | if (*s == *fr) { |
| 749 | i++; |
| 750 | break; |
| 751 | } |
| 752 | if (i == 0) |
| 753 | *to++ = *s; |
| 754 | } |
| 755 | *to = '\0'; |
| 756 | } |
| 757 | |
| 758 | if (c >= 3) { |
| 759 | for (s = ap[1]; *s; s++) |
| 760 | for (fr = ap[2], to = ap[3]; *fr && *to; fr++, to++) |
| 761 | if (*s == *fr) |
| 762 | *s = *to; |
| 763 | } |
| 764 | |
| 765 | pbstr(ap[1]); |
| 766 | } |
| 767 | |
| 768 | doif(ap, c) |
| 769 | register char **ap; |
| 770 | { |
| 771 | if (c < 3) |
| 772 | return; |
| 773 | while (c >= 3) { |
| 774 | if (strcmp(ap[1], ap[2]) == 0) { |
| 775 | pbstr(ap[3]); |
| 776 | return; |
| 777 | } |
| 778 | c -= 3; |
| 779 | ap += 3; |
| 780 | } |
| 781 | if (c > 0) |
| 782 | pbstr(ap[1]); |
| 783 | } |
| 784 | |
| 785 | dodiv(ap, c) |
| 786 | register char **ap; |
| 787 | { |
| 788 | register int f; |
| 789 | |
| 790 | if (c<1) |
| 791 | f = 0; |
| 792 | else |
| 793 | f = ctoi(ap[1]); |
| 794 | if (f>=10 || f<0) { |
| 795 | curfile = NULL; |
| 796 | return; |
| 797 | } |
| 798 | tempname[7] = 'a' + f; |
| 799 | if (olist[f] || (olist[f]=fopen(tempname, WRITE))) { |
| 800 | curout = f; |
| 801 | curfile = olist[f]; |
| 802 | } |
| 803 | } |
| 804 | |
| 805 | doundiv(ap, c) |
| 806 | char **ap; |
| 807 | { |
| 808 | register FILE *fp; |
| 809 | register int i, ch; |
| 810 | int j; |
| 811 | |
| 812 | if (c == 0) { |
| 813 | for (i=1; i<10; i++) { |
| 814 | if (i==curout || olist[i]==NULL) |
| 815 | continue; |
| 816 | fclose(olist[i]); |
| 817 | tempname[7] = 'a'+i; |
| 818 | fp = fopen(tempname, READ); |
| 819 | if (curfile != NULL) |
| 820 | while ((ch = getc(fp)) > 0) |
| 821 | putc(ch, curfile); |
| 822 | fclose(fp); |
| 823 | unlink(tempname); |
| 824 | olist[i] = NULL; |
| 825 | } |
| 826 | |
| 827 | } |
| 828 | else { |
| 829 | for (j = 1; j <= c; j++) { |
| 830 | i = ctoi(*++ap); |
| 831 | if (i<1 || i>9 || i==curout || olist[i]==NULL) |
| 832 | continue; |
| 833 | fclose(olist[i]); |
| 834 | tempname[7] = 'a'+i; |
| 835 | fp = fopen(tempname, READ); |
| 836 | if (curfile != NULL) |
| 837 | while ((ch = getc(fp)) > 0) |
| 838 | putc(ch, curfile); |
| 839 | fclose(fp); |
| 840 | unlink(tempname); |
| 841 | olist[i] = NULL; |
| 842 | } |
| 843 | } |
| 844 | } |
| 845 | |
| 846 | dodivnum(ap, c) |
| 847 | char **ap; |
| 848 | { |
| 849 | putnum((long) curout); |
| 850 | } |
| 851 | |
| 852 | dodnl(ap, c) |
| 853 | char **ap; |
| 854 | { |
| 855 | register t; |
| 856 | |
| 857 | while ((t=getchr())!='\n' && t>=0) |
| 858 | ; |
| 859 | } |
| 860 | |
| 861 | long ctol(str) |
| 862 | register char *str; |
| 863 | { |
| 864 | register sign; |
| 865 | long num; |
| 866 | |
| 867 | while (*str==' ' || *str=='\t' || *str=='\n') |
| 868 | str++; |
| 869 | num = 0; |
| 870 | if (*str == '-') { |
| 871 | sign = -1; |
| 872 | str++; |
| 873 | } |
| 874 | else |
| 875 | sign = 1; |
| 876 | while (*str>='0' && *str<='9') |
| 877 | num = num*10 + *str++ - '0'; |
| 878 | return(sign * num); |
| 879 | } |
| 880 | |
| 881 | ctoi(s) |
| 882 | char *s; |
| 883 | { |
| 884 | return(ctol(s)); |
| 885 | } |
| 886 | |
| 887 | min(a, b) |
| 888 | { |
| 889 | if (a>b) |
| 890 | return(b); |
| 891 | return(a); |
| 892 | } |
| 893 | |
| 894 | max(a, b) |
| 895 | { |
| 896 | if (a>b) |
| 897 | return(a); |
| 898 | return(b); |
| 899 | } |