Annotation of 43BSDReno/pgrm/m4/serv.c, revision 1.1.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.