# 2.11BSD#431 - /usr/src/usr.bin/m4/eval.c

##### Functions

    dochc             X
    dochq             X
    dodefine          X
    dodefn            X
    dodiv             X
    dodump            X
    doifelse          X
    doincl            X
    dopaste           X
    dopushdef         X
    dosub             X
    doundiv           X
    eval              X
    expand            X
    map               X

##### Variables

    dumpfmt           X

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

#### Defined functions

dochc defined in line 616; used 1 times

- in line 212

dochq defined in line 592; used 1 times

- in line 208

dodefine defined in line 434; used 1 times

- in line 101

dodefn defined in line 460; used 1 times

- in line 360

dodiv defined in line 640; used 1 times

- in line 245

dodump defined in line 504; used 1 times

- in line 110

doifelse defined in line 529; used 1 times

- in line 124

doincl defined in line 551; used 2 times

- in line 187, 193

dopaste defined in line 571; used 2 times

- in line 198, 204

dopushdef defined in line 480; used 1 times

- in line 106

dosub defined in line 684; used 1 times

- in line 221

doundiv defined in line 659; used 1 times

- in line 253

eval defined in line 75; never used
expand defined in line 374; never used
map defined in line 736; used 2 times

- in line 303-305(2)

#### Defined variables

dumpfmt defined in line 369; used 2 times

- in line 515, 521

sccsid defined in line 38; never used

Last modified: 1994-04-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1803 |