* reordered a little bit
[mascara-docs.git] / i86 / elks / elkscmd / m4 / serv.c
blob260d81c58f7fdced90fb2127f0267739046eaaa2
1 /*
2 * serv.c
3 * Facility: m4 macro processor
4 * by: oz
5 */
7 #include "mdef.h"
8 #include "extr.h"
10 extern ndptr lookup();
11 extern ndptr addent();
12 extern char *strsave();
14 char *dumpfmt = "`%s'\t`%s'\n"; /* format string for dumpdef */
17 * expand - user-defined macro expansion
20 expand(argv, argc)
21 register char *argv[];
22 register int argc;
24 register char *t;
25 register char *p;
26 register int n;
27 register int argno;
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) {
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(',');
61 pbstr(argv[2]);
62 break;
63 default :
64 putback(*p);
65 break;
67 p--;
69 p--;
71 if (p == t) /* do last character */
72 putback(*p);
76 * dodefine - install definition in the table
79 dodefine(name, defn)
80 register char *name;
81 register char *defn;
83 register ndptr p;
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;
101 * dodefn - push back a quoted definition of
102 * the given name.
105 dodefn(name)
106 char *name;
108 register ndptr p;
110 if ((p = lookup(name)) != nil && p->defn != null) {
111 putback(rquote);
112 pbstr(p->defn);
113 putback(lquote);
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.
124 dopushdef(name, defn)
125 register char *name;
126 register char *defn;
128 register ndptr p;
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;
143 * dodumpdef - dump the specified definitions in the hash
144 * table to stderr. If nothing is specified, the entire
145 * hash table is dumped.
148 dodump(argv, argc)
149 register char *argv[];
150 register int argc;
152 register int n;
153 ndptr p;
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);
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);
170 * doifelse - select one of two alternatives - loop.
173 doifelse(argv,argc)
174 register char *argv[];
175 register int argc;
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;
187 break;
192 * doinclude - include a given file.
195 doincl(ifile)
196 char *ifile;
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);
204 else
205 return (0);
208 #ifdef EXTENDED
210 * dopaste - include a given file without any
211 * macro processing.
213 dopaste(pfile)
214 char *pfile;
216 FILE *pf;
217 register int c;
219 if ((pf = fopen(pfile, "r")) != NULL) {
220 while((c = getc(pf)) != EOF)
221 putc(c, active);
222 (void) fclose(pf);
223 return(1);
225 else
226 return(0);
228 #endif
231 * dochq - change quote characters
234 dochq(argv, argc)
235 register char *argv[];
236 register int argc;
238 if (argc > 2) {
239 if (*argv[2])
240 lquote = *argv[2];
241 if (argc > 3) {
242 if (*argv[3])
243 rquote = *argv[3];
245 else
246 rquote = lquote;
248 else {
249 lquote = LQUOTE;
250 rquote = RQUOTE;
255 * dochc - change comment characters
258 dochc(argv, argc)
259 register char *argv[];
260 register int argc;
262 if (argc > 2) {
263 if (*argv[2])
264 scommt = *argv[2];
265 if (argc > 3) {
266 if (*argv[3])
267 ecommt = *argv[3];
269 else
270 ecommt = ECOMMT;
272 else {
273 scommt = SCOMMT;
274 ecommt = ECOMMT;
279 * dodivert - divert the output to a temporary file
282 dodiv(n)
283 register int n;
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.");
292 oindex = n;
293 active = outfile[n];
297 * doundivert - undivert a specified output, or all
298 * other outputs, in numerical order.
300 doundiv(argv, argc)
301 register char *argv[];
302 register int argc;
304 register int ind;
305 register int n;
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);
315 else
316 for (n = 1; n < MAXOUT; n++)
317 if (outfile[n] != NULL)
318 getdiv(n);
322 * dosub - select substring
325 dosub (argv, argc)
326 register char *argv[];
327 register int argc;
329 register char *ap, *fc, *k;
330 register int nc;
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);
352 * map:
353 * map every character of s1 that is specified in from
354 * into s3 and replace in s. (source s1 remains untouched)
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.
378 map(dest,src,from,to)
379 register char *dest;
380 register char *src;
381 register char *from;
382 register char *to;
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
400 if (*src) {
401 tmp = from;
403 * create a mapping between "from" and "to"
405 while (*from)
406 mapvec[*from++] = (*to) ? *to++ : (char) 0;
408 while (*src) {
409 sch = *src++;
410 dch = mapvec[sch];
411 while (dch != sch) {
412 sch = dch;
413 dch = mapvec[sch];
415 if (*dest = dch)
416 dest++;
419 * restore all the changed characters
421 while (*tmp) {
422 mapvec[*tmp] = *tmp;
423 tmp++;
426 *dest = (char) 0;