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