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