home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d160 / m4.lha / M4 / Src / serv.c < prev   
C/C++ Source or Header  |  1988-10-02  |  12KB  |  428 lines

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