Annotation of 43BSDReno/pgrm/m4/serv.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.