[BACK]Return to serv.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / m4

Annotation of src/usr.bin/m4/serv.c, Revision 1.1

1.1     ! deraadt     1: /*     $NetBSD: serv.c,v 1.7 1995/09/28 05:37:47 tls Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1989
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  * (c) UNIX System Laboratories, Inc.
        !             7:  * All or some portions of this file are derived from material licensed
        !             8:  * to the University of California by American Telephone and Telegraph
        !             9:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
        !            10:  * the permission of UNIX System Laboratories, Inc.
        !            11:  *
        !            12:  * This code is derived from software contributed to Berkeley by
        !            13:  * Ozan Yigit.
        !            14:  *
        !            15:  * Redistribution and use in source and binary forms, with or without
        !            16:  * modification, are permitted provided that the following conditions
        !            17:  * are met:
        !            18:  * 1. Redistributions of source code must retain the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer.
        !            20:  * 2. Redistributions in binary form must reproduce the above copyright
        !            21:  *    notice, this list of conditions and the following disclaimer in the
        !            22:  *    documentation and/or other materials provided with the distribution.
        !            23:  * 3. All advertising materials mentioning features or use of this software
        !            24:  *    must display the following acknowledgement:
        !            25:  *     This product includes software developed by the University of
        !            26:  *     California, Berkeley and its contributors.
        !            27:  * 4. Neither the name of the University nor the names of its contributors
        !            28:  *    may be used to endorse or promote products derived from this software
        !            29:  *    without specific prior written permission.
        !            30:  *
        !            31:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            32:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            33:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            34:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            35:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            36:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            37:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            38:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            39:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            40:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            41:  * SUCH DAMAGE.
        !            42:  */
        !            43:
        !            44: #ifndef lint
        !            45: #if 0
        !            46: static char sccsid[] = "@(#)serv.c     5.4 (Berkeley) 1/21/94";
        !            47: #else
        !            48: static char rcsid[] = "$NetBSD: serv.c,v 1.7 1995/09/28 05:37:47 tls Exp $";
        !            49: #endif
        !            50: #endif /* not lint */
        !            51:
        !            52: /*
        !            53:  * serv.c
        !            54:  * Facility: m4 macro processor
        !            55:  * by: oz
        !            56:  */
        !            57:
        !            58: #include <stdio.h>
        !            59: #include <stdlib.h>
        !            60: #include <string.h>
        !            61: #include "mdef.h"
        !            62: #include "extr.h"
        !            63: #include "pathnames.h"
        !            64:
        !            65: extern ndptr lookup();
        !            66: extern ndptr addent();
        !            67:
        !            68: char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef   */
        !            69:
        !            70: /*
        !            71:  * expand - user-defined macro expansion
        !            72:  *
        !            73:  */
        !            74: expand(argv, argc)
        !            75: register char *argv[];
        !            76: register int argc;
        !            77: {
        !            78:         register char *t;
        !            79:         register char *p;
        !            80:         register int  n;
        !            81:         register int  argno;
        !            82:
        !            83:         t = argv[0];    /* defn string as a whole */
        !            84:         p = t;
        !            85:         while (*p)
        !            86:                 p++;
        !            87:         p--;            /* last character of defn */
        !            88:         while (p > t) {
        !            89:                 if (*(p-1) != ARGFLAG)
        !            90:                         putback(*p);
        !            91:                 else {
        !            92:                         switch (*p) {
        !            93:
        !            94:                         case '#':
        !            95:                                 pbnum(argc-2);
        !            96:                                 break;
        !            97:                         case '0':
        !            98:                         case '1':
        !            99:                         case '2':
        !           100:                         case '3':
        !           101:                         case '4':
        !           102:                         case '5':
        !           103:                         case '6':
        !           104:                         case '7':
        !           105:                         case '8':
        !           106:                         case '9':
        !           107:                                 if ((argno = *p - '0') < argc-1)
        !           108:                                         pbstr(argv[argno+1]);
        !           109:                                 break;
        !           110:                         case '*':
        !           111:                                 for (n = argc - 1; n > 2; n--) {
        !           112:                                         pbstr(argv[n]);
        !           113:                                         putback(',');
        !           114:                                 }
        !           115:                                 pbstr(argv[2]);
        !           116:                                 break;
        !           117:                         default :
        !           118:                                 putback(*p);
        !           119:                                 break;
        !           120:                         }
        !           121:                         p--;
        !           122:                 }
        !           123:                 p--;
        !           124:         }
        !           125:         if (p == t)         /* do last character */
        !           126:                 putback(*p);
        !           127: }
        !           128:
        !           129: /*
        !           130:  * dodefine - install definition in the table
        !           131:  *
        !           132:  */
        !           133: dodefine(name, defn)
        !           134: register char *name;
        !           135: register char *defn;
        !           136: {
        !           137:         register ndptr p;
        !           138:
        !           139:         if (!*name)
        !           140:                 error("m4: null definition.");
        !           141:         if (strcmp(name, defn) == 0)
        !           142:                 error("m4: recursive definition.");
        !           143:         if ((p = lookup(name)) == nil)
        !           144:                 p = addent(name);
        !           145:         else if (p->defn != null)
        !           146:                 free(p->defn);
        !           147:         if (!*defn)
        !           148:                 p->defn = null;
        !           149:         else
        !           150:                 p->defn = strdup(defn);
        !           151:         p->type = MACRTYPE;
        !           152: }
        !           153:
        !           154: /*
        !           155:  * dodefn - push back a quoted definition of
        !           156:  *      the given name.
        !           157:  */
        !           158:
        !           159: dodefn(name)
        !           160: char *name;
        !           161: {
        !           162:         register ndptr p;
        !           163:
        !           164:         if ((p = lookup(name)) != nil && p->defn != null) {
        !           165:                 putback(rquote);
        !           166:                 pbstr(p->defn);
        !           167:                 putback(lquote);
        !           168:         }
        !           169: }
        !           170:
        !           171: /*
        !           172:  * dopushdef - install a definition in the hash table
        !           173:  *      without removing a previous definition. Since
        !           174:  *      each new entry is entered in *front* of the
        !           175:  *      hash bucket, it hides a previous definition from
        !           176:  *      lookup.
        !           177:  */
        !           178: dopushdef(name, defn)
        !           179: register char *name;
        !           180: register char *defn;
        !           181: {
        !           182:         register ndptr p;
        !           183:
        !           184:         if (!*name)
        !           185:                 error("m4: null definition");
        !           186:         if (strcmp(name, defn) == 0)
        !           187:                 error("m4: recursive definition.");
        !           188:         p = addent(name);
        !           189:         if (!*defn)
        !           190:                 p->defn = null;
        !           191:         else
        !           192:                 p->defn = strdup(defn);
        !           193:         p->type = MACRTYPE;
        !           194: }
        !           195:
        !           196: /*
        !           197:  * dodumpdef - dump the specified definitions in the hash
        !           198:  *      table to stderr. If nothing is specified, the entire
        !           199:  *      hash table is dumped.
        !           200:  *
        !           201:  */
        !           202: dodump(argv, argc)
        !           203: register char *argv[];
        !           204: register int argc;
        !           205: {
        !           206:         register int n;
        !           207:         ndptr p;
        !           208:
        !           209:         if (argc > 2) {
        !           210:                 for (n = 2; n < argc; n++)
        !           211:                         if ((p = lookup(argv[n])) != nil)
        !           212:                                 fprintf(stderr, dumpfmt, p->name,
        !           213:                                 p->defn);
        !           214:         }
        !           215:         else {
        !           216:                 for (n = 0; n < HASHSIZE; n++)
        !           217:                         for (p = hashtab[n]; p != nil; p = p->nxtptr)
        !           218:                                 fprintf(stderr, dumpfmt, p->name,
        !           219:                                 p->defn);
        !           220:         }
        !           221: }
        !           222:
        !           223: /*
        !           224:  * doifelse - select one of two alternatives - loop.
        !           225:  *
        !           226:  */
        !           227: doifelse(argv,argc)
        !           228: register char *argv[];
        !           229: register int argc;
        !           230: {
        !           231:         cycle {
        !           232:                 if (strcmp(argv[2], argv[3]) == 0)
        !           233:                         pbstr(argv[4]);
        !           234:                 else if (argc == 6)
        !           235:                         pbstr(argv[5]);
        !           236:                 else if (argc > 6) {
        !           237:                         argv += 3;
        !           238:                         argc -= 3;
        !           239:                         continue;
        !           240:                 }
        !           241:                 break;
        !           242:         }
        !           243: }
        !           244:
        !           245: /*
        !           246:  * doinclude - include a given file.
        !           247:  *
        !           248:  */
        !           249: doincl(ifile)
        !           250: char *ifile;
        !           251: {
        !           252:         if (ilevel+1 == MAXINP)
        !           253:                 error("m4: too many include files.");
        !           254:         if ((infile[ilevel+1] = fopen(ifile, "r")) != NULL) {
        !           255:                 ilevel++;
        !           256:                 return (1);
        !           257:         }
        !           258:         else
        !           259:                 return (0);
        !           260: }
        !           261:
        !           262: #ifdef EXTENDED
        !           263: /*
        !           264:  * dopaste - include a given file without any
        !           265:  *           macro processing.
        !           266:  */
        !           267: dopaste(pfile)
        !           268: char *pfile;
        !           269: {
        !           270:         FILE *pf;
        !           271:         register int c;
        !           272:
        !           273:         if ((pf = fopen(pfile, "r")) != NULL) {
        !           274:                 while((c = getc(pf)) != EOF)
        !           275:                         putc(c, active);
        !           276:                 (void) fclose(pf);
        !           277:                 return(1);
        !           278:         }
        !           279:         else
        !           280:                 return(0);
        !           281: }
        !           282: #endif
        !           283:
        !           284: /*
        !           285:  * dochq - change quote characters
        !           286:  *
        !           287:  */
        !           288: dochq(argv, argc)
        !           289: register char *argv[];
        !           290: register int argc;
        !           291: {
        !           292:         if (argc > 2) {
        !           293:                 if (*argv[2])
        !           294:                         lquote = *argv[2];
        !           295:                 if (argc > 3) {
        !           296:                         if (*argv[3])
        !           297:                                 rquote = *argv[3];
        !           298:                 }
        !           299:                 else
        !           300:                         rquote = lquote;
        !           301:         }
        !           302:         else {
        !           303:                 lquote = LQUOTE;
        !           304:                 rquote = RQUOTE;
        !           305:         }
        !           306: }
        !           307:
        !           308: /*
        !           309:  * dochc - change comment characters
        !           310:  *
        !           311:  */
        !           312: dochc(argv, argc)
        !           313: register char *argv[];
        !           314: register int argc;
        !           315: {
        !           316:         if (argc > 2) {
        !           317:                 if (*argv[2])
        !           318:                         scommt = *argv[2];
        !           319:                 if (argc > 3) {
        !           320:                         if (*argv[3])
        !           321:                                 ecommt = *argv[3];
        !           322:                 }
        !           323:                 else
        !           324:                         ecommt = ECOMMT;
        !           325:         }
        !           326:         else {
        !           327:                 scommt = SCOMMT;
        !           328:                 ecommt = ECOMMT;
        !           329:         }
        !           330: }
        !           331:
        !           332: /*
        !           333:  * dodivert - divert the output to a temporary file
        !           334:  *
        !           335:  */
        !           336: dodiv(n)
        !           337: register int n;
        !           338: {
        !           339:         if (n < 0 || n >= MAXOUT)
        !           340:                 n = 0;                  /* bitbucket */
        !           341:         if (outfile[n] == NULL) {
        !           342:                 m4temp[UNIQUE] = n + '0';
        !           343:                 if ((outfile[n] = fopen(m4temp, "w")) == NULL)
        !           344:                         error("m4: cannot divert.");
        !           345:         }
        !           346:         oindex = n;
        !           347:         active = outfile[n];
        !           348: }
        !           349:
        !           350: /*
        !           351:  * doundivert - undivert a specified output, or all
        !           352:  *              other outputs, in numerical order.
        !           353:  */
        !           354: doundiv(argv, argc)
        !           355: register char *argv[];
        !           356: register int argc;
        !           357: {
        !           358:         register int ind;
        !           359:         register int n;
        !           360:
        !           361:         if (argc > 2) {
        !           362:                 for (ind = 2; ind < argc; ind++) {
        !           363:                         n = atoi(argv[ind]);
        !           364:                         if (n > 0 && n < MAXOUT && outfile[n] != NULL)
        !           365:                                 getdiv(n);
        !           366:
        !           367:                 }
        !           368:         }
        !           369:         else
        !           370:                 for (n = 1; n < MAXOUT; n++)
        !           371:                         if (outfile[n] != NULL)
        !           372:                                 getdiv(n);
        !           373: }
        !           374:
        !           375: /*
        !           376:  * dosub - select substring
        !           377:  *
        !           378:  */
        !           379: dosub (argv, argc)
        !           380: register char *argv[];
        !           381: register int  argc;
        !           382: {
        !           383:         register char *ap, *fc, *k;
        !           384:         register int nc;
        !           385:
        !           386:         if (argc < 5)
        !           387:                 nc = MAXTOK;
        !           388:         else
        !           389: #ifdef EXPR
        !           390:                 nc = expr(argv[4]);
        !           391: #else
        !           392:                nc = atoi(argv[4]);
        !           393: #endif
        !           394:         ap = argv[2];                   /* target string */
        !           395: #ifdef EXPR
        !           396:         fc = ap + expr(argv[3]);        /* first char */
        !           397: #else
        !           398:         fc = ap + atoi(argv[3]);        /* first char */
        !           399: #endif
        !           400:         if (fc >= ap && fc < ap+strlen(ap))
        !           401:                 for (k = fc+min(nc,strlen(fc))-1; k >= fc; k--)
        !           402:                         putback(*k);
        !           403: }
        !           404:
        !           405: /*
        !           406:  * map:
        !           407:  * map every character of s1 that is specified in from
        !           408:  * into s3 and replace in s. (source s1 remains untouched)
        !           409:  *
        !           410:  * This is a standard implementation of map(s,from,to) function of ICON
        !           411:  * language. Within mapvec, we replace every character of "from" with
        !           412:  * the corresponding character in "to". If "to" is shorter than "from",
        !           413:  * than the corresponding entries are null, which means that those
        !           414:  * characters dissapear altogether. Furthermore, imagine
        !           415:  * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case,
        !           416:  * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s'
        !           417:  * ultimately maps to `*'. In order to achieve this effect in an efficient
        !           418:  * manner (i.e. without multiple passes over the destination string), we
        !           419:  * loop over mapvec, starting with the initial source character. if the
        !           420:  * character value (dch) in this location is different than the source
        !           421:  * character (sch), sch becomes dch, once again to index into mapvec, until
        !           422:  * the character value stabilizes (i.e. sch = dch, in other words
        !           423:  * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary
        !           424:  * character, it will stabilize, since mapvec[0] == 0 at all times. At the
        !           425:  * end, we restore mapvec* back to normal where mapvec[n] == n for
        !           426:  * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is
        !           427:  * about 5 times faster than any algorithm that makes multiple passes over
        !           428:  * destination string.
        !           429:  *
        !           430:  */
        !           431:
        !           432: map(dest,src,from,to)
        !           433: register char *dest;
        !           434: register char *src;
        !           435: register char *from;
        !           436: register char *to;
        !           437: {
        !           438:         register char *tmp;
        !           439:         register char sch, dch;
        !           440:         static char mapvec[128] = {
        !           441:                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
        !           442:                 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
        !           443:                 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
        !           444:                 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
        !           445:                 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
        !           446:                 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
        !           447:                 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
        !           448:                 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
        !           449:                 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
        !           450:                 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
        !           451:                 120, 121, 122, 123, 124, 125, 126, 127
        !           452:         };
        !           453:
        !           454:         if (*src) {
        !           455:                 tmp = from;
        !           456:        /*
        !           457:         * create a mapping between "from" and "to"
        !           458:         */
        !           459:                 while (*from)
        !           460:                         mapvec[*from++] = (*to) ? *to++ : (char) 0;
        !           461:
        !           462:                 while (*src) {
        !           463:                         sch = *src++;
        !           464:                         dch = mapvec[sch];
        !           465:                         while (dch != sch) {
        !           466:                                 sch = dch;
        !           467:                                 dch = mapvec[sch];
        !           468:                         }
        !           469:                         if (*dest = dch)
        !           470:                                 dest++;
        !           471:                 }
        !           472:        /*
        !           473:         * restore all the changed characters
        !           474:         */
        !           475:                 while (*tmp) {
        !           476:                         mapvec[*tmp] = *tmp;
        !           477:                         tmp++;
        !           478:                 }
        !           479:         }
        !           480:         *dest = (char) 0;
        !           481: }