|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.