1 /* $NetBSD: eval.c,v 1.10 1997/10/19 04:39:51 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Ozan Yigit at York University. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)eval.c 8.2 (Berkeley) 4/27/95"; 43 #else 44 __RCSID("$NetBSD: eval.c,v 1.10 1997/10/19 04:39:51 lukem Exp $"); 45 #endif 46 #endif /* not lint */ 47 48 /* 49 * eval.c 50 * Facility: m4 macro processor 51 * by: oz 52 */ 53 54 #include <sys/types.h> 55 #include <err.h> 56 #include <errno.h> 57 #include <unistd.h> 58 #include <stdio.h> 59 #include <stdlib.h> 60 #include <string.h> 61 #include "mdef.h" 62 #include "stdd.h" 63 #include "extern.h" 64 #include "pathnames.h" 65 66 /* 67 * eval - evaluate built-in macros. 68 * argc - number of elements in argv. 69 * argv - element vector : 70 * argv[0] = definition of a user 71 * macro or nil if built-in. 72 * argv[1] = name of the macro or 73 * built-in. 74 * argv[2] = parameters to user-defined 75 * . macro or built-in. 76 * . 77 * 78 * Note that the minimum value for argc is 3. A call in the form 79 * of macro-or-builtin() will result in: 80 * argv[0] = nullstr 81 * argv[1] = macro-or-builtin 82 * argv[2] = nullstr 83 */ 84 85 void 86 eval(argv, argc, td) 87 char *argv[]; 88 int argc; 89 int td; 90 { 91 int c, n; 92 static int sysval = 0; 93 94 #ifdef DEBUG 95 printf("argc = %d\n", argc); 96 for (n = 0; n < argc; n++) 97 printf("argv[%d] = %s\n", n, argv[n]); 98 #endif 99 /* 100 * if argc == 3 and argv[2] is null, then we 101 * have macro-or-builtin() type call. We adjust 102 * argc to avoid further checking.. 103 */ 104 if (argc == 3 && !*(argv[2])) 105 argc--; 106 107 switch (td & ~STATIC) { 108 109 case DEFITYPE: 110 if (argc > 2) 111 dodefine(argv[2], (argc > 3) ? argv[3] : null); 112 break; 113 114 case PUSDTYPE: 115 if (argc > 2) 116 dopushdef(argv[2], (argc > 3) ? argv[3] : null); 117 break; 118 119 case DUMPTYPE: 120 dodump(argv, argc); 121 break; 122 123 case EXPRTYPE: 124 /* 125 * doexpr - evaluate arithmetic 126 * expression 127 */ 128 if (argc > 2) 129 pbnum(expr(argv[2])); 130 break; 131 132 case IFELTYPE: 133 if (argc > 4) 134 doifelse(argv, argc); 135 break; 136 137 case IFDFTYPE: 138 /* 139 * doifdef - select one of two 140 * alternatives based on the existence of 141 * another definition 142 */ 143 if (argc > 3) { 144 if (lookup(argv[2]) != nil) 145 pbstr(argv[3]); 146 else if (argc > 4) 147 pbstr(argv[4]); 148 } 149 break; 150 151 case LENGTYPE: 152 /* 153 * dolen - find the length of the 154 * argument 155 */ 156 if (argc > 2) 157 pbnum((argc > 2) ? strlen(argv[2]) : 0); 158 break; 159 160 case INCRTYPE: 161 /* 162 * doincr - increment the value of the 163 * argument 164 */ 165 if (argc > 2) 166 pbnum(atoi(argv[2]) + 1); 167 break; 168 169 case DECRTYPE: 170 /* 171 * dodecr - decrement the value of the 172 * argument 173 */ 174 if (argc > 2) 175 pbnum(atoi(argv[2]) - 1); 176 break; 177 178 case SYSCTYPE: 179 /* 180 * dosys - execute system command 181 */ 182 if (argc > 2) 183 sysval = system(argv[2]); 184 break; 185 186 case SYSVTYPE: 187 /* 188 * dosysval - return value of the last 189 * system call. 190 * 191 */ 192 pbnum(sysval); 193 break; 194 195 case INCLTYPE: 196 if (argc > 2) 197 if (!doincl(argv[2])) 198 err(1, "%s", argv[2]); 199 break; 200 201 case SINCTYPE: 202 if (argc > 2) 203 (void) doincl(argv[2]); 204 break; 205 #ifdef EXTENDED 206 case PASTTYPE: 207 if (argc > 2) 208 if (!dopaste(argv[2])) 209 err(1, "%s", argv[2]); 210 break; 211 212 case SPASTYPE: 213 if (argc > 2) 214 (void) dopaste(argv[2]); 215 break; 216 #endif 217 case CHNQTYPE: 218 dochq(argv, argc); 219 break; 220 221 case CHNCTYPE: 222 dochc(argv, argc); 223 break; 224 225 case SUBSTYPE: 226 /* 227 * dosub - select substring 228 * 229 */ 230 if (argc > 3) 231 dosub(argv, argc); 232 break; 233 234 case SHIFTYPE: 235 /* 236 * doshift - push back all arguments 237 * except the first one (i.e. skip 238 * argv[2]) 239 */ 240 if (argc > 3) { 241 for (n = argc - 1; n > 3; n--) { 242 pbstr(rquote); 243 pbstr(argv[n]); 244 pbstr(lquote); 245 putback(COMMA); 246 } 247 pbstr(rquote); 248 pbstr(argv[3]); 249 pbstr(lquote); 250 } 251 break; 252 253 case DIVRTYPE: 254 if (argc > 2 && (n = atoi(argv[2])) != 0) 255 dodiv(n); 256 else { 257 active = stdout; 258 oindex = 0; 259 } 260 break; 261 262 case UNDVTYPE: 263 doundiv(argv, argc); 264 break; 265 266 case DIVNTYPE: 267 /* 268 * dodivnum - return the number of 269 * current output diversion 270 */ 271 pbnum(oindex); 272 break; 273 274 case UNDFTYPE: 275 /* 276 * doundefine - undefine a previously 277 * defined macro(s) or m4 keyword(s). 278 */ 279 if (argc > 2) 280 for (n = 2; n < argc; n++) 281 remhash(argv[n], ALL); 282 break; 283 284 case POPDTYPE: 285 /* 286 * dopopdef - remove the topmost 287 * definitions of macro(s) or m4 288 * keyword(s). 289 */ 290 if (argc > 2) 291 for (n = 2; n < argc; n++) 292 remhash(argv[n], TOP); 293 break; 294 295 case MKTMTYPE: 296 /* 297 * dotemp - create a temporary file 298 */ 299 if (argc > 2) 300 pbstr(mktemp(argv[2])); 301 break; 302 303 case TRNLTYPE: 304 /* 305 * dotranslit - replace all characters in 306 * the source string that appears in the 307 * "from" string with the corresponding 308 * characters in the "to" string. 309 */ 310 if (argc > 3) { 311 char temp[MAXTOK]; 312 if (argc > 4) 313 map(temp, argv[2], argv[3], argv[4]); 314 else 315 map(temp, argv[2], argv[3], null); 316 pbstr(temp); 317 } 318 else if (argc > 2) 319 pbstr(argv[2]); 320 break; 321 322 case INDXTYPE: 323 /* 324 * doindex - find the index of the second 325 * argument string in the first argument 326 * string. -1 if not present. 327 */ 328 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 329 break; 330 331 case ERRPTYPE: 332 /* 333 * doerrp - print the arguments to stderr 334 * file 335 */ 336 if (argc > 2) { 337 for (n = 2; n < argc; n++) 338 fprintf(stderr, "%s ", argv[n]); 339 fprintf(stderr, "\n"); 340 } 341 break; 342 343 case DNLNTYPE: 344 /* 345 * dodnl - eat-up-to and including 346 * newline 347 */ 348 while ((c = gpbc()) != '\n' && c != EOF) 349 ; 350 break; 351 352 case M4WRTYPE: 353 /* 354 * dom4wrap - set up for 355 * wrap-up/wind-down activity 356 */ 357 m4wraps = (argc > 2) ? xstrdup(argv[2]) : null; 358 break; 359 360 case EXITTYPE: 361 /* 362 * doexit - immediate exit from m4. 363 */ 364 killdiv(); 365 exit((argc > 2) ? atoi(argv[2]) : 0); 366 break; 367 368 case DEFNTYPE: 369 if (argc > 2) 370 for (n = 2; n < argc; n++) 371 dodefn(argv[n]); 372 break; 373 374 default: 375 errx(1, "eval: major botch"); 376 break; 377 } 378 } 379 380 char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef */ 381 382 /* 383 * expand - user-defined macro expansion 384 */ 385 void 386 expand(argv, argc) 387 char *argv[]; 388 int argc; 389 { 390 char *t; 391 char *p; 392 int n; 393 int argno; 394 395 t = argv[0]; /* defn string as a whole */ 396 p = t; 397 while (*p) 398 p++; 399 p--; /* last character of defn */ 400 while (p > t) { 401 if (*(p - 1) != ARGFLAG) 402 putback(*p); 403 else { 404 switch (*p) { 405 406 case '#': 407 pbnum(argc - 2); 408 break; 409 case '0': 410 case '1': 411 case '2': 412 case '3': 413 case '4': 414 case '5': 415 case '6': 416 case '7': 417 case '8': 418 case '9': 419 if ((argno = *p - '0') < argc - 1) 420 pbstr(argv[argno + 1]); 421 break; 422 case '*': 423 for (n = argc - 1; n > 2; n--) { 424 pbstr(argv[n]); 425 putback(COMMA); 426 } 427 pbstr(argv[2]); 428 break; 429 case '@': 430 for (n = argc - 1; n > 2; n--) { 431 pbstr(rquote); 432 pbstr(argv[n]); 433 pbstr(lquote); 434 putback(COMMA); 435 } 436 pbstr(rquote); 437 pbstr(argv[2]); 438 pbstr(lquote); 439 break; 440 default: 441 putback(*p); 442 putback('$'); 443 break; 444 } 445 p--; 446 } 447 p--; 448 } 449 if (p == t) /* do last character */ 450 putback(*p); 451 } 452 453 /* 454 * dodefine - install definition in the table 455 */ 456 void 457 dodefine(name, defn) 458 char *name; 459 char *defn; 460 { 461 ndptr p; 462 463 if (!*name) 464 errx(1, "null definition"); 465 if (STREQ(name, defn)) 466 errx(1, "%s: recursive definition", name); 467 if ((p = lookup(name)) == nil) 468 p = addent(name); 469 else if (p->defn != null) 470 free((char *) p->defn); 471 if (!*defn) 472 p->defn = null; 473 else 474 p->defn = xstrdup(defn); 475 p->type = MACRTYPE; 476 } 477 478 /* 479 * dodefn - push back a quoted definition of 480 * the given name. 481 */ 482 void 483 dodefn(name) 484 char *name; 485 { 486 ndptr p; 487 488 if ((p = lookup(name)) != nil && p->defn != null) { 489 pbstr(rquote); 490 pbstr(p->defn); 491 pbstr(lquote); 492 } 493 } 494 495 /* 496 * dopushdef - install a definition in the hash table 497 * without removing a previous definition. Since 498 * each new entry is entered in *front* of the 499 * hash bucket, it hides a previous definition from 500 * lookup. 501 */ 502 void 503 dopushdef(name, defn) 504 char *name; 505 char *defn; 506 { 507 ndptr p; 508 509 if (!*name) 510 errx(1, "null definition"); 511 if (STREQ(name, defn)) 512 errx(1, "%s: recursive definition", name); 513 p = addent(name); 514 if (!*defn) 515 p->defn = null; 516 else 517 p->defn = xstrdup(defn); 518 p->type = MACRTYPE; 519 } 520 521 /* 522 * dodumpdef - dump the specified definitions in the hash 523 * table to stderr. If nothing is specified, the entire 524 * hash table is dumped. 525 */ 526 void 527 dodump(argv, argc) 528 char *argv[]; 529 int argc; 530 { 531 int n; 532 ndptr p; 533 534 if (argc > 2) { 535 for (n = 2; n < argc; n++) 536 if ((p = lookup(argv[n])) != nil) 537 fprintf(stderr, dumpfmt, p->name, 538 p->defn); 539 } 540 else { 541 for (n = 0; n < HASHSIZE; n++) 542 for (p = hashtab[n]; p != nil; p = p->nxtptr) 543 fprintf(stderr, dumpfmt, p->name, 544 p->defn); 545 } 546 } 547 548 /* 549 * doifelse - select one of two alternatives - loop. 550 */ 551 void 552 doifelse(argv, argc) 553 char *argv[]; 554 int argc; 555 { 556 cycle { 557 if (STREQ(argv[2], argv[3])) 558 pbstr(argv[4]); 559 else if (argc == 6) 560 pbstr(argv[5]); 561 else if (argc > 6) { 562 argv += 3; 563 argc -= 3; 564 continue; 565 } 566 break; 567 } 568 } 569 570 /* 571 * doinclude - include a given file. 572 */ 573 int 574 doincl(ifile) 575 char *ifile; 576 { 577 if (ilevel + 1 == MAXINP) 578 errx(1, "too many include files"); 579 if ((infile[ilevel + 1] = fopen(ifile, "r")) != NULL) { 580 ilevel++; 581 bbase[ilevel] = bufbase = bp; 582 return (1); 583 } 584 else 585 return (0); 586 } 587 588 #ifdef EXTENDED 589 /* 590 * dopaste - include a given file without any 591 * macro processing. 592 */ 593 int 594 dopaste(pfile) 595 char *pfile; 596 { 597 FILE *pf; 598 int c; 599 600 if ((pf = fopen(pfile, "r")) != NULL) { 601 while ((c = getc(pf)) != EOF) 602 putc(c, active); 603 (void) fclose(pf); 604 return (1); 605 } 606 else 607 return (0); 608 } 609 #endif 610 611 /* 612 * dochq - change quote characters 613 */ 614 void 615 dochq(argv, argc) 616 char *argv[]; 617 int argc; 618 { 619 if (argc > 2) { 620 if (*argv[2]) 621 strncpy(lquote, argv[2], MAXCCHARS); 622 if (argc > 3) { 623 if (*argv[3]) 624 strncpy(rquote, argv[3], MAXCCHARS); 625 } 626 else 627 strcpy(rquote, lquote); 628 } 629 else { 630 lquote[0] = LQUOTE, lquote[1] = '\0'; 631 rquote[0] = RQUOTE, rquote[1] = '\0'; 632 } 633 } 634 635 /* 636 * dochc - change comment characters 637 */ 638 void 639 dochc(argv, argc) 640 char *argv[]; 641 int argc; 642 { 643 if (argc > 2) { 644 if (*argv[2]) 645 strncpy(scommt, argv[2], MAXCCHARS); 646 if (argc > 3) { 647 if (*argv[3]) 648 strncpy(ecommt, argv[3], MAXCCHARS); 649 } 650 else 651 ecommt[0] = ECOMMT, ecommt[1] = '\0'; 652 } 653 else { 654 scommt[0] = SCOMMT, scommt[1] = '\0'; 655 ecommt[0] = ECOMMT, ecommt[1] = '\0'; 656 } 657 } 658 659 /* 660 * dodivert - divert the output to a temporary file 661 */ 662 void 663 dodiv(n) 664 int n; 665 { 666 int tempfilenum; 667 668 /* 669 * direct output to the appropriate temporary file (the bit 670 * bucket, if out of range). 671 */ 672 tempfilenum = (n < 0 || n >= MAXOUT) ? 0 : n; 673 674 if (outfile[tempfilenum] == NULL) { 675 m4temp[UNIQUE] = tempfilenum + '0'; 676 if ((outfile[tempfilenum] = fopen(m4temp, "w")) == NULL) 677 err(1, "%s: cannot divert", m4temp); 678 } 679 oindex = n; 680 active = outfile[tempfilenum]; 681 } 682 683 /* 684 * doundivert - undivert a specified output, or all 685 * other outputs, in numerical order. 686 */ 687 void 688 doundiv(argv, argc) 689 char *argv[]; 690 int argc; 691 { 692 int ind; 693 int n; 694 695 if (argc > 2) { 696 for (ind = 2; ind < argc; ind++) { 697 n = atoi(argv[ind]); 698 if (n > 0 && n < MAXOUT && outfile[n] != NULL) 699 getdiv(n); 700 701 } 702 } 703 else 704 for (n = 1; n < MAXOUT; n++) 705 if (outfile[n] != NULL) 706 getdiv(n); 707 } 708 709 /* 710 * dosub - select substring 711 */ 712 void 713 dosub(argv, argc) 714 char *argv[]; 715 int argc; 716 { 717 char *ap, *fc, *k; 718 int nc; 719 720 if (argc < 5) 721 nc = MAXTOK; 722 else 723 #ifdef EXPR 724 nc = expr(argv[4]); 725 #else 726 nc = atoi(argv[4]); 727 #endif 728 ap = argv[2]; /* target string */ 729 #ifdef EXPR 730 fc = ap + expr(argv[3]); /* first char */ 731 #else 732 fc = ap + atoi(argv[3]); /* first char */ 733 #endif 734 if (fc >= ap && fc < ap + strlen(ap)) 735 for (k = fc + min(nc, strlen(fc)) - 1; k >= fc; k--) 736 putback(*k); 737 } 738 739 /* 740 * map: 741 * map every character of s1 that is specified in from 742 * into s3 and replace in s. (source s1 remains untouched) 743 * 744 * This is a standard implementation of map(s,from,to) function of ICON 745 * language. Within mapvec, we replace every character of "from" with 746 * the corresponding character in "to". If "to" is shorter than "from", 747 * than the corresponding entries are null, which means that those 748 * characters dissapear altogether. Furthermore, imagine 749 * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case, 750 * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' 751 * ultimately maps to `*'. In order to achieve this effect in an efficient 752 * manner (i.e. without multiple passes over the destination string), we 753 * loop over mapvec, starting with the initial source character. if the 754 * character value (dch) in this location is different than the source 755 * character (sch), sch becomes dch, once again to index into mapvec, until 756 * the character value stabilizes (i.e. sch = dch, in other words 757 * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary 758 * character, it will stabilize, since mapvec[0] == 0 at all times. At the 759 * end, we restore mapvec* back to normal where mapvec[n] == n for 760 * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is 761 * about 5 times faster than any algorithm that makes multiple passes over 762 * destination string. 763 */ 764 void 765 map(dest, src, from, to) 766 char *dest; 767 char *src; 768 char *from; 769 char *to; 770 { 771 char *tmp; 772 char sch, dch; 773 static char mapvec[128] = { 774 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 775 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 776 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 777 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 778 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 779 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 780 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 781 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 782 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 783 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 784 120, 121, 122, 123, 124, 125, 126, 127 785 }; 786 787 if (*src) { 788 tmp = from; 789 /* 790 * create a mapping between "from" and 791 * "to" 792 */ 793 while (*from) 794 mapvec[(int)*from++] = (*to) ? *to++ : (char) 0; 795 796 while (*src) { 797 sch = *src++; 798 dch = mapvec[(int)sch]; 799 while (dch != sch) { 800 sch = dch; 801 dch = mapvec[(int)sch]; 802 } 803 if ((*dest = dch) != 0) 804 dest++; 805 } 806 /* 807 * restore all the changed characters 808 */ 809 while (*tmp) { 810 mapvec[(int)*tmp] = *tmp; 811 tmp++; 812 } 813 } 814 *dest = (char) 0; 815 } 816