serv.c

Go to the documentation of this file.
00001 /*
00002  * serv.c
00003  * Facility: m4 macro processor
00004  * by: oz
00005  */
00006  
00007 #include "mdef.h"
00008 #include "extr.h" 
00009 
00010 char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef   */
00011  
00012 /*
00013  * expand - user-defined macro expansion
00014  *
00015  */
00016 void expand(argv, argc)
00017 register char *argv[];
00018 register int argc;
00019 {
00020         register char *t;
00021         register char *p;
00022         register int  n;
00023         register int  argno;
00024  
00025         t = argv[0];    /* defn string as a whole */
00026         p = t;
00027         while (*p)
00028                 p++;
00029         p--;            /* last character of defn */
00030         while (p > t) {
00031                 if (*(p-1) != ARGFLAG)
00032                         putback(*p);
00033                 else {
00034                         switch (*p) {
00035  
00036                         case '#':
00037                                 pbnum(argc-2);
00038                                 break;
00039                         case '0':
00040                         case '1':
00041                         case '2':
00042                         case '3':
00043                         case '4':
00044                         case '5':
00045                         case '6':
00046                         case '7':
00047                         case '8':
00048                         case '9':
00049                                 if ((argno = *p - '0') < argc-1)
00050                                         pbstr(argv[argno+1]);
00051                                 break;
00052                         case '*':
00053                                 for (n = argc - 1; n > 2; n--) {
00054                                         pbstr(argv[n]);
00055                                         putback(',');
00056                                 }
00057                                 pbstr(argv[2]);
00058                                 break;
00059                         default :
00060                                 putback(*p);
00061                                 break;
00062                         }
00063                         p--;
00064                 }
00065                 p--;
00066         }
00067         if (p == t)         /* do last character */
00068                 putback(*p);
00069 }
00070  
00071 /*
00072  * dodefine - install definition in the table
00073  *
00074  */
00075 void dodefine(name, defn)
00076 register char *name;
00077 register char *defn;
00078 {
00079         register ndptr p;
00080  
00081         if (!*name)
00082                 error("m4: null definition.");
00083         if (strcmp(name, defn) == 0)
00084                 error("m4: recursive definition.");
00085         if ((p = lookup(name)) == nil)
00086                 p = addent(name);
00087         else if (p->defn != null)
00088                 free(p->defn);
00089         if (!*defn)
00090                 p->defn = null;
00091         else
00092                 p->defn = strsave(defn);
00093         p->type = MACRTYPE;
00094 }
00095  
00096 /*
00097  * dodefn - push back a quoted definition of
00098  *      the given name.
00099  */
00100  
00101 void dodefn(name)
00102 char *name;
00103 {
00104         register ndptr p;
00105  
00106         if ((p = lookup(name)) != nil && p->defn != null) {
00107                 putback(rquote);
00108                 pbstr(p->defn);
00109                 putback(lquote);
00110         }
00111 }
00112      
00113 /*
00114  * dopushdef - install a definition in the hash table
00115  *      without removing a previous definition. Since
00116  *      each new entry is entered in *front* of the
00117  *      hash bucket, it hides a previous definition from
00118  *      lookup.
00119  */
00120 void dopushdef(name, defn)
00121 register char *name;
00122 register char *defn;
00123 {
00124         register ndptr p;
00125  
00126         if (!*name)
00127                 error("m4: null definition");
00128         if (strcmp(name, defn) == 0)
00129                 error("m4: recursive definition.");
00130         p = addent(name);
00131         if (!*defn)
00132                 p->defn = null;
00133         else
00134                 p->defn = strsave(defn);
00135         p->type = MACRTYPE;
00136 }
00137  
00138 /*
00139  * dodumpdef - dump the specified definitions in the hash
00140  *      table to stderr. If nothing is specified, the entire
00141  *      hash table is dumped.
00142  *
00143  */
00144 void dodump(argv, argc)
00145 register char *argv[];
00146 register int argc;
00147 {
00148         register int n;
00149         ndptr p;
00150  
00151         if (argc > 2) {
00152                 for (n = 2; n < argc; n++)
00153                         if ((p = lookup(argv[n])) != nil)
00154                                 fprintf(stderr, dumpfmt, p->name,
00155                                 p->defn);
00156         }
00157         else {
00158                 for (n = 0; n < HASHSIZE; n++)
00159                         for (p = hashtab[n]; p != nil; p = p->nxtptr)
00160                                 fprintf(stderr, dumpfmt, p->name,
00161                                 p->defn);
00162         }
00163 }
00164  
00165 /*
00166  * doifelse - select one of two alternatives - loop.
00167  *
00168  */
00169 void doifelse(argv,argc)
00170 register char *argv[];
00171 register int argc;
00172 {
00173         cycle {
00174                 if (strcmp(argv[2], argv[3]) == 0)
00175                         pbstr(argv[4]);
00176                 else if (argc == 6)
00177                         pbstr(argv[5]);
00178                 else if (argc > 6) {
00179                         argv += 3;
00180                         argc -= 3;
00181                         continue;
00182                 }
00183                 break;
00184         }
00185 }
00186  
00187 /*
00188  * doinclude - include a given file.
00189  *
00190  */
00191 int doincl(ifile)
00192 char *ifile;
00193 {
00194         if (ilevel+1 == MAXINP)
00195                 error("m4: too many include files.");
00196         if ((infile[ilevel+1] = fopen(ifile, "r")) != NULL) {
00197                 ilevel++;
00198                 return (1);
00199         }
00200         else
00201                 return (0);
00202 }
00203  
00204 #ifdef EXTENDED
00205 /*
00206  * dopaste - include a given file without any
00207  *           macro processing.
00208  */
00209 int dopaste(pfile)
00210 char *pfile;
00211 {
00212         FILE *pf;
00213         register int c;
00214  
00215         if ((pf = fopen(pfile, "r")) != NULL) {
00216                 while((c = getc(pf)) != EOF)
00217                         putc(c, active);
00218                 (void) fclose(pf);
00219                 return(1);
00220         }
00221         else
00222                 return(0);
00223 }
00224 #endif
00225  
00226 /*
00227  * dochq - change quote characters
00228  *
00229  */
00230 void dochq(argv, argc)
00231 register char *argv[];
00232 register int argc;
00233 {
00234         if (argc > 2) {
00235                 if (*argv[2])
00236                         lquote = *argv[2];
00237                 if (argc > 3) {
00238                         if (*argv[3])
00239                                 rquote = *argv[3];
00240                 }
00241                 else
00242                         rquote = lquote;
00243         }
00244         else {
00245                 lquote = LQUOTE;
00246                 rquote = RQUOTE;
00247         }
00248 }
00249  
00250 /*
00251  * dochc - change comment characters
00252  *
00253  */
00254 void dochc(argv, argc)
00255 register char *argv[];
00256 register int argc;
00257 {
00258         if (argc > 2) {
00259                 if (*argv[2])
00260                         scommt = *argv[2];
00261                 if (argc > 3) {
00262                         if (*argv[3])
00263                                 ecommt = *argv[3];
00264                 }
00265                 else
00266                         ecommt = ECOMMT;
00267         }
00268         else {
00269                 scommt = SCOMMT;
00270                 ecommt = ECOMMT;
00271         }
00272 }
00273  
00274 /*
00275  * dodivert - divert the output to a temporary file
00276  *
00277  */
00278 void dodiv(n)
00279 register int n;
00280 {
00281         if (n < 0 || n >= MAXOUT)
00282                 n = 0;                  /* bitbucket */
00283         if (outfile[n] == NULL) {
00284                 m4temp[UNIQUE] = n + '0';
00285                 if ((outfile[n] = fopen(m4temp, "w")) == NULL)
00286                         error("m4: cannot divert.");
00287         }
00288         oindex = n;
00289         active = outfile[n];
00290 }
00291  
00292 /*
00293  * doundivert - undivert a specified output, or all
00294  *              other outputs, in numerical order.
00295  */
00296 void doundiv(argv, argc)
00297 register char *argv[];
00298 register int argc;
00299 {
00300         register int ind;
00301         register int n;
00302  
00303         if (argc > 2) {
00304                 for (ind = 2; ind < argc; ind++) {
00305                         n = atoi(argv[ind]);
00306                         if (n > 0 && n < MAXOUT && outfile[n] != NULL)
00307                                 getdiv(n);
00308  
00309                 }
00310         }
00311         else
00312                 for (n = 1; n < MAXOUT; n++)
00313                         if (outfile[n] != NULL)
00314                                 getdiv(n);
00315 }
00316  
00317 /*
00318  * dosub - select substring
00319  *
00320  */
00321 void dosub (argv, argc)
00322 register char *argv[];
00323 register int  argc;
00324 {
00325         register char *ap, *fc, *k;
00326         register int nc;
00327  
00328         if (argc < 5)
00329                 nc = MAXTOK;
00330         else
00331 #ifdef EXPR
00332                 nc = expr(argv[4]);
00333 #else
00334                 nc = atoi(argv[4]);
00335 #endif
00336         ap = argv[2];                   /* target string */
00337 #ifdef EXPR
00338         fc = ap + expr(argv[3]);        /* first char */
00339 #else
00340         fc = ap + atoi(argv[3]);        /* first char */
00341 #endif
00342         if (fc >= ap && fc < ap+strlen(ap))
00343                 for (k = fc+min(nc,strlen(fc))-1; k >= fc; k--)
00344                         putback(*k);
00345 }
00346  
00347 /*
00348  * map:
00349  * map every character of s1 that is specified in from
00350  * into s3 and replace in s. (source s1 remains untouched)
00351  *
00352  * This is a standard implementation of map(s,from,to) function of ICON 
00353  * language. Within mapvec, we replace every character of "from" with 
00354  * the corresponding character in "to". If "to" is shorter than "from", 
00355  * than the corresponding entries are null, which means that those 
00356  * characters dissapear altogether. Furthermore, imagine 
00357  * map(dest, "sourcestring", "srtin", "rn..*") type call. In this case, 
00358  * `s' maps to `r', `r' maps to `n' and `n' maps to `*'. Thus, `s' 
00359  * ultimately maps to `*'. In order to achieve this effect in an efficient 
00360  * manner (i.e. without multiple passes over the destination string), we 
00361  * loop over mapvec, starting with the initial source character. if the 
00362  * character value (dch) in this location is different than the source 
00363  * character (sch), sch becomes dch, once again to index into mapvec, until 
00364  * the character value stabilizes (i.e. sch = dch, in other words 
00365  * mapvec[n] == n). Even if the entry in the mapvec is null for an ordinary 
00366  * character, it will stabilize, since mapvec[0] == 0 at all times. At the 
00367  * end, we restore mapvec* back to normal where mapvec[n] == n for 
00368  * 0 <= n <= 127. This strategy, along with the restoration of mapvec, is 
00369  * about 5 times faster than any algorithm that makes multiple passes over 
00370  * destination string.
00371  *
00372  */
00373      
00374 void map(dest,src,from,to)
00375 register char *dest;
00376 register char *src;
00377 register char *from;
00378 register char *to;
00379 {
00380         register char *tmp;
00381         register char sch, dch;
00382         static char mapvec[128] = {
00383                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
00384                 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
00385                 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
00386                 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
00387                 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
00388                 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
00389                 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
00390                 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
00391                 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
00392                 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
00393                 120, 121, 122, 123, 124, 125, 126, 127
00394         };
00395  
00396         if (*src) {
00397                 tmp = from;
00398         /*
00399          * create a mapping between "from" and "to"
00400          */
00401                 while (*from)
00402                         mapvec[*from++] = (*to) ? *to++ : (char) 0;
00403      
00404                 while (*src) {
00405                         sch = *src++;
00406                         dch = mapvec[sch];
00407                         while (dch != sch) {
00408                                 sch = dch;
00409                                 dch = mapvec[sch];
00410                         }
00411                         if (*dest = dch)
00412                                 dest++;
00413                 }
00414         /*
00415          * restore all the changed characters
00416          */
00417                 while (*tmp) {
00418                         mapvec[*tmp] = *tmp;
00419                         tmp++;
00420                 }
00421         }
00422         *dest = (char) 0;
00423 }

Generated on Fri Apr 14 22:56:58 2006 for minix by  doxygen 1.4.6