Commit | Line | Data |
---|---|---|
5e785920 | 1 | Virgin BTL M4 as sent out in 4.1 |
17d1455f | 2 | #ifndef lint |
dc0e9d50 | 3 | static char sccsid[] = "@(#)m4.c 1.5 (Berkeley) %G%"; |
17d1455f SL |
4 | #endif |
5 | ||
5e785920 CC |
6 | #include <stdio.h> |
7 | #include <signal.h> | |
dc0e9d50 | 8 | #include "pathnames.h" |
5e785920 CC |
9 | |
10 | #define ERROR NULL | |
11 | #define READ "r" | |
12 | #define WRITE "w" | |
13 | ||
14 | #define EOS 0 | |
15 | int lpar = '('; | |
16 | #define LPAR lpar | |
17 | #define RPAR ')' | |
18 | #define COMMA ',' | |
19 | #define GRAVE '`' | |
20 | #define ACUTE '\'' | |
21 | #define LBRAK '[' | |
22 | #define RBRAK ']' | |
23 | #ifdef M4 | |
24 | char lquote LBRAK; | |
25 | char rquote RBRAK; | |
26 | #endif | |
27 | #ifndef M4 | |
28 | char lquote = GRAVE; | |
29 | char rquote = ACUTE; | |
30 | #endif | |
31 | #define COMMENT '#' | |
32 | #define ALPH 1 | |
33 | #define DIG 2 | |
34 | ||
35 | #define HSHSIZ 199 /* prime */ | |
36 | #define STACKS 50 | |
37 | #define SAVS 4096 | |
38 | #define TOKS 128 | |
39 | ||
40 | #define putbak(c) *ip++ = c; | |
41 | #define getchr() (ip>cur_ip?*--ip: getc(infile[infptr])) | |
42 | #define putchr(c) if (cp==NULL) {if (curfile)putc(c,curfile);} else *op++ = c | |
43 | char type[] = { | |
44 | 0, 0, 0, 0, 0, 0, 0, 0, | |
45 | 0, 0, 0, 0, 0, 0, 0, 0, | |
46 | 0, 0, 0, 0, 0, 0, 0, 0, | |
47 | 0, 0, 0, 0, 0, 0, 0, 0, | |
48 | 0, 0, 0, 0, 0, 0, 0, 0, | |
49 | 0, 0, 0, 0, 0, 0, 0, 0, | |
50 | DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, | |
51 | DIG, DIG, 0, 0, 0, 0, 0, 0, | |
52 | 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, | |
53 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, | |
54 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, | |
55 | ALPH, ALPH, ALPH, 0, 0, 0, 0, ALPH, | |
56 | 0, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, | |
57 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, | |
58 | ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, | |
59 | ALPH, ALPH, ALPH, 0, 0, 0, 0, 0, | |
60 | }; | |
61 | ||
62 | char token[TOKS]; | |
63 | char eoa[] = "\0"; | |
ecc33553 CC |
64 | |
65 | #define RESERVED 01 /* This is a reserved word with side action */ | |
5e785920 CC |
66 | struct nlist { |
67 | char *name; | |
68 | char *def; | |
ecc33553 | 69 | char flag; |
5e785920 CC |
70 | struct nlist *next; |
71 | }; | |
72 | ||
73 | struct nlist *hshtab[HSHSIZ]; | |
74 | char ibuf[SAVS+TOKS]; | |
75 | char obuf[SAVS+TOKS]; | |
76 | char *op = obuf; | |
77 | char *ip = ibuf; | |
78 | char *ip_stk[10] = {ibuf}; | |
79 | char *cur_ip = ibuf; | |
80 | struct call { | |
81 | char **argp; | |
82 | int plev; | |
83 | }; | |
84 | struct call *cp = NULL; | |
85 | ||
86 | char *makeloc; | |
87 | char *ifdefloc; | |
88 | char *lenloc; | |
89 | char *undefloc; | |
90 | char *shiftloc; | |
91 | char *cqloc; | |
92 | char *defloc; | |
93 | char *evaloc; | |
94 | char *incrloc; | |
95 | char *substrloc; | |
96 | char *indexloc; | |
97 | char *transloc; | |
98 | char *ifloc; | |
99 | char *divloc; | |
100 | char *divnumloc; | |
101 | char *undivloc; | |
102 | char *dnlloc; | |
103 | char *inclloc; | |
104 | char *sinclloc; | |
105 | char *syscmdloc; | |
106 | char *dumploc; | |
107 | char *errploc; | |
108 | ||
dc0e9d50 | 109 | char tempname[] = _PATH_TMP; |
5e785920 CC |
110 | struct nlist *lookup(); |
111 | char *install(); | |
112 | char *malloc(); | |
113 | char *mktemp(); | |
114 | char *copy(); | |
115 | long ctol(); | |
116 | int hshval; | |
117 | FILE *olist[11] = { stdout }; | |
118 | int okret; | |
119 | int curout = 0; | |
120 | FILE *curfile = { stdout }; | |
121 | FILE *infile[10] = { stdin }; | |
122 | int infptr = 0; | |
123 | ||
124 | main(argc, argv) | |
125 | char **argv; | |
126 | { | |
127 | char *argstk[STACKS+10]; | |
128 | struct call callst[STACKS]; | |
129 | register char *tp, **ap; | |
130 | int delexit(), catchsig(); | |
131 | register t; | |
132 | int i; | |
133 | ||
134 | #ifdef gcos | |
135 | #ifdef M4 | |
ecc33553 | 136 | install("GCOS", eoa, 0); |
5e785920 CC |
137 | #endif |
138 | #ifndef M4 | |
ecc33553 | 139 | install("gcos", eoa, 0); |
5e785920 CC |
140 | #endif |
141 | #endif | |
142 | #ifdef unix | |
143 | #ifdef M4 | |
ecc33553 | 144 | install("UNIX", eoa, 0); |
5e785920 CC |
145 | #endif |
146 | #ifndef M4 | |
ecc33553 | 147 | install("unix", eoa, 0); |
5e785920 CC |
148 | #endif |
149 | #endif | |
150 | ||
151 | #ifdef M4 | |
ecc33553 CC |
152 | makeloc = install("MAKETEMP", eoa, RESERVED); |
153 | ifdefloc = install("IFDEF", eoa, RESERVED); | |
154 | lenloc = install("LEN", eoa, RESERVED); | |
155 | undefloc = install("UNDEFINE", eoa, RESERVED); | |
156 | shiftloc = install("SHIFT", eoa, RESERVED); | |
157 | cqloc = install("CHANGEQUOTE", eoa, RESERVED); | |
158 | defloc = install("DEFINE", eoa, RESERVED); | |
159 | evaloc = install("EVAL", eoa, RESERVED); | |
160 | inclloc = install("INCLUDE", eoa, RESERVED); | |
161 | sinclloc = install("SINCLUDE", eoa, RESERVED); | |
162 | syscmdloc = install("SYSCMD", eoa, RESERVED); | |
163 | dumploc = install("DUMPDEF", eoa, RESERVED); | |
164 | errploc = install("ERRPRINT", eoa, RESERVED); | |
165 | incrloc = install("INCR", eoa, RESERVED); | |
166 | substrloc = install("SUBSTR", eoa, RESERVED); | |
167 | indexloc = install("INDEX", eoa, RESERVED); | |
168 | transloc = install("TRANSLIT", eoa, RESERVED); | |
169 | ifloc = install("IFELSE", eoa, RESERVED); | |
170 | divloc = install("DIVERT", eoa, RESERVED); | |
171 | divnumloc = install("DIVNUM", eoa, RESERVED); | |
172 | undivloc = install("UNDIVERT", eoa, RESERVED); | |
173 | dnlloc = install("DNL", eoa, RESERVED); | |
5e785920 CC |
174 | #endif |
175 | ||
176 | #ifndef M4 | |
ecc33553 CC |
177 | makeloc = install("maketemp", eoa, RESERVED); |
178 | ifdefloc = install("ifdef", eoa, RESERVED); | |
179 | lenloc = install("len", eoa, RESERVED); | |
180 | undefloc = install("undefine", eoa, RESERVED); | |
181 | shiftloc = install("shift", eoa, RESERVED); | |
182 | cqloc = install("changequote", eoa, RESERVED); | |
183 | defloc = install("define", eoa, RESERVED); | |
184 | evaloc = install("eval", eoa, RESERVED); | |
185 | inclloc = install("include", eoa, RESERVED); | |
186 | sinclloc = install("sinclude", eoa, RESERVED); | |
187 | syscmdloc = install("syscmd", eoa, RESERVED); | |
188 | dumploc = install("dumpdef", eoa, RESERVED); | |
189 | errploc = install("errprint", eoa, RESERVED); | |
190 | incrloc = install("incr", eoa, RESERVED); | |
191 | substrloc = install("substr", eoa, RESERVED); | |
192 | indexloc = install("index", eoa, RESERVED); | |
193 | transloc = install("translit", eoa, RESERVED); | |
194 | ifloc = install("ifelse", eoa, RESERVED); | |
195 | divloc = install("divert", eoa, RESERVED); | |
196 | divnumloc = install("divnum", eoa, RESERVED); | |
197 | undivloc = install("undivert", eoa, RESERVED); | |
198 | dnlloc = install("dnl", eoa, RESERVED); | |
5e785920 CC |
199 | #endif |
200 | ap = argstk; | |
201 | #ifndef gcos | |
202 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) | |
203 | signal(SIGHUP, catchsig); | |
204 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) | |
205 | signal(SIGINT, catchsig); | |
3677395f | 206 | mktemp(tempname); |
5e785920 CC |
207 | close(creat(tempname, 0)); |
208 | #endif | |
209 | #ifdef gcos | |
210 | tempname = "m4.tempa"; | |
211 | #endif | |
212 | if (argc>1) | |
213 | putbak(0); | |
214 | for (;;) { | |
215 | tp = token; | |
216 | *tp++ = t = getchr(); | |
217 | *tp = EOS; | |
218 | if (t<=0) { | |
219 | if (infptr > 0) { | |
220 | fclose(infile[infptr]); | |
221 | infptr--; | |
222 | cur_ip = ip_stk[infptr]; | |
223 | continue; | |
224 | } | |
225 | if (argc<=1) | |
226 | break; | |
227 | argc--; | |
228 | argv++; | |
229 | if (infile[infptr]!=stdin) | |
230 | fclose(infile[infptr]); | |
231 | if (**argv=='-') | |
232 | infile[infptr] = stdin; | |
233 | else if ((infile[infptr]=fopen(argv[0], READ))==ERROR) { | |
234 | fprintf(stderr, "m4: file not found: %s\n", argv[0]); | |
235 | delexit(); | |
236 | } | |
237 | continue; | |
238 | } | |
239 | if (type[t]==ALPH) { | |
240 | while ((t=type[*tp++=getchr()])==ALPH||t==DIG); | |
241 | putbak(*--tp); | |
242 | *tp = EOS; | |
243 | if (*ap = lookup(token)->def) { | |
244 | if (++ap >= &argstk[STACKS]) { | |
245 | fprintf(stderr, "m4: arg stack overflow\n"); | |
246 | delexit(); | |
247 | } | |
248 | if (cp==NULL) | |
249 | cp = callst; | |
250 | else if (++cp > &callst[STACKS]) { | |
251 | fprintf(stderr, "m4: call stack overflow\n"); | |
252 | delexit(); | |
253 | } | |
254 | cp->argp = ap; | |
255 | *ap++ = op; | |
256 | puttok(); | |
257 | *op++ = '\0'; | |
258 | t = getchr(); | |
259 | putbak(t); | |
260 | if (t!=LPAR) { | |
261 | /* if (t!=' ' && t!='\t') */ | |
262 | putbak(')'); | |
263 | putbak('('); | |
264 | } | |
265 | else /* try to fix arg count */ | |
266 | *ap++ = op; | |
267 | cp->plev = 0; | |
268 | } else | |
269 | puttok(); | |
270 | } else if (t==lquote) { | |
271 | i = 1; | |
272 | for (;;) { | |
273 | t = getchr(); | |
274 | if (t==rquote) { | |
275 | i--; | |
276 | if (i==0) | |
277 | break; | |
278 | } else if (t==lquote) | |
279 | i++; | |
280 | else if (t<0) { | |
281 | fprintf(stderr, "m4: EOF in string\n"); | |
282 | delexit(); | |
283 | } | |
284 | putchr(t); | |
285 | } | |
286 | } else if (t==COMMENT) { | |
287 | putbak(t); | |
288 | while ((t = getchr())!='\n'&& t>=0) | |
289 | if (cp==NULL) | |
290 | putchr(t); | |
291 | putbak(t); | |
292 | } else if (cp==NULL) { | |
293 | puttok(); | |
294 | } else if (t==LPAR) { | |
295 | if (cp->plev) | |
296 | *op++ = t; | |
297 | cp->plev++; | |
298 | while ( (t=getchr())==' ' || t=='\t' || t=='\n') | |
299 | ; /* skip leading white space during arg collection */ | |
300 | putbak(t); | |
301 | /* | |
302 | } else if (t==' ' || t=='\t' || t=='\n') { | |
303 | continue; | |
304 | */ | |
305 | } else if (t==RPAR) { | |
306 | cp->plev--; | |
307 | if (cp->plev==0) { | |
308 | *op++ = '\0'; | |
309 | expand(cp->argp, ap-cp->argp-1); | |
310 | op = *cp->argp; | |
311 | ap = cp->argp-1; | |
312 | cp--; | |
313 | if (cp < callst) | |
314 | cp = NULL; | |
315 | } else | |
316 | *op++ = t; | |
317 | } else if (t==COMMA && cp->plev<=1) { | |
318 | *op++ = '\0'; | |
319 | *ap++ = op; | |
320 | while ((t=getchr())==' ' || t=='\t' || t=='\n') | |
321 | ; /* skip leading white space during arg collection */ | |
322 | putbak(t); | |
323 | } else | |
324 | *op++ = t; | |
325 | } | |
326 | if (cp!=NULL) { | |
327 | fprintf(stderr, "m4: unexpected EOF\n"); | |
328 | delexit(); | |
329 | } | |
330 | okret = 1; | |
331 | delexit(); | |
332 | } | |
333 | ||
334 | catchsig() | |
335 | { | |
336 | okret = 0; | |
337 | delexit(); | |
338 | } | |
339 | ||
340 | delexit() | |
341 | { | |
342 | register FILE *fp; | |
343 | register i, c; | |
344 | ||
345 | if (!okret) { | |
346 | signal(SIGHUP, SIG_IGN); | |
347 | signal(SIGINT, SIG_IGN); | |
348 | } | |
349 | for (i=1; i<10; i++) { | |
350 | if (olist[i]==NULL) | |
351 | continue; | |
352 | fclose(olist[i]); | |
353 | tempname[7] = 'a'+i; | |
354 | if (okret) { | |
355 | fp = fopen(tempname, READ); | |
356 | while ((c = getc(fp)) > 0) | |
357 | putchar(c); | |
358 | fclose(fp); | |
359 | } | |
360 | unlink(tempname); | |
361 | } | |
362 | tempname[7] = 'a'; | |
363 | unlink(tempname); | |
364 | exit(1-okret); | |
365 | } | |
366 | ||
367 | puttok() | |
368 | { | |
369 | register char *tp; | |
370 | ||
371 | tp = token; | |
372 | if (cp) { | |
373 | if (op >= &obuf[SAVS]) { | |
374 | fprintf(stderr, "m4: argument overflow\n"); | |
375 | delexit(); | |
376 | } | |
377 | while (*tp) | |
378 | *op++ = *tp++; | |
379 | } else if (curfile) | |
380 | while (*tp) | |
381 | putc(*tp++, curfile); | |
382 | } | |
383 | ||
384 | pbstr(str) | |
385 | register char *str; | |
386 | { | |
387 | register char *p; | |
388 | ||
389 | p = str; | |
390 | while (*p++); | |
391 | --p; | |
392 | if (ip >= &ibuf[SAVS]) { | |
393 | fprintf(stderr, "m4: pushback overflow\n"); | |
394 | delexit(); | |
395 | } | |
396 | while (p > str) | |
397 | putbak(*--p); | |
398 | } | |
399 | ||
400 | expand(a1, c) | |
401 | register char **a1; | |
402 | { | |
403 | register char *dp; | |
404 | register n; | |
405 | ||
406 | dp = a1[-1]; | |
407 | if (dp==defloc) | |
408 | dodef(a1, c); | |
409 | else if (dp==evaloc) | |
410 | doeval(a1, c); | |
411 | else if (dp==inclloc) | |
412 | doincl(a1, c, 1); | |
413 | else if (dp==sinclloc) | |
414 | doincl(a1, c, 0); | |
415 | else if (dp==makeloc) | |
416 | domake(a1, c); | |
417 | else if (dp==syscmdloc) | |
418 | dosyscmd(a1, c); | |
419 | else if (dp==incrloc) | |
420 | doincr(a1, c); | |
421 | else if (dp==substrloc) | |
422 | dosubstr(a1, c); | |
423 | else if (dp==indexloc) | |
424 | doindex(a1, c); | |
425 | else if (dp==transloc) | |
426 | dotransl(a1, c); | |
427 | else if (dp==ifloc) | |
428 | doif(a1, c); | |
429 | else if (dp==divloc) | |
430 | dodiv(a1, c); | |
431 | else if (dp==divnumloc) | |
432 | dodivnum(a1, c); | |
433 | else if (dp==undivloc) | |
434 | doundiv(a1, c); | |
435 | else if (dp==dnlloc) | |
436 | dodnl(a1, c); | |
437 | else if (dp==dumploc) | |
438 | dodump(a1, c); | |
439 | else if (dp==errploc) | |
440 | doerrp(a1, c); | |
441 | else if (dp==lenloc) | |
442 | dolen(a1, c); | |
443 | else if (dp==ifdefloc) | |
444 | doifdef(a1, c); | |
445 | else if (dp==undefloc) | |
446 | doundef(a1, c); | |
447 | else if (dp==shiftloc) | |
448 | doshift(a1, c); | |
449 | else if (dp==cqloc) | |
450 | docq(a1, c); | |
451 | else { | |
452 | while (*dp++); | |
453 | for (dp--; dp>a1[-1]; ) { | |
454 | if (--dp>a1[-1] && dp[-1]=='$') { | |
455 | n = *dp-'0'; | |
456 | if (n>=0 && n<=9) { | |
457 | if (n <= c) | |
458 | pbstr(a1[n]); | |
459 | dp--; | |
460 | } else | |
461 | putbak(*dp); | |
462 | } else | |
463 | putbak(*dp); | |
464 | } | |
465 | } | |
466 | } | |
467 | ||
468 | struct nlist *lookup(str) | |
469 | char *str; | |
470 | { | |
471 | register char *s1, *s2; | |
472 | register struct nlist *np; | |
473 | static struct nlist nodef; | |
474 | ||
475 | s1 = str; | |
476 | for (hshval = 0; *s1; ) | |
477 | hshval += *s1++; | |
478 | hshval %= HSHSIZ; | |
479 | for (np = hshtab[hshval]; np!=NULL; np = np->next) { | |
480 | s1 = str; | |
481 | s2 = np->name; | |
482 | while (*s1++ == *s2) | |
483 | if (*s2++ == EOS) | |
484 | return(np); | |
485 | } | |
486 | return(&nodef); | |
487 | } | |
488 | ||
ecc33553 | 489 | char *install(nam, val, flag) |
5e785920 | 490 | char *nam, *val; |
ecc33553 | 491 | char flag; |
5e785920 CC |
492 | { |
493 | register struct nlist *np; | |
494 | ||
495 | if ((np = lookup(nam))->name == NULL) { | |
496 | np = (struct nlist *)malloc(sizeof(*np)); | |
497 | if (np == NULL) { | |
498 | fprintf(stderr, "m4: no space for alloc\n"); | |
499 | exit(1); | |
500 | } | |
501 | np->name = copy(nam); | |
502 | np->def = copy(val); | |
503 | np->next = hshtab[hshval]; | |
ecc33553 | 504 | np->flag = flag; |
5e785920 CC |
505 | hshtab[hshval] = np; |
506 | return(np->def); | |
507 | } | |
508 | free(np->def); | |
ecc33553 | 509 | np->flag = flag; |
5e785920 CC |
510 | np->def = copy(val); |
511 | return(np->def); | |
512 | } | |
513 | ||
514 | doundef(ap, c) | |
515 | char **ap; | |
516 | { | |
517 | register struct nlist *np, *tnp; | |
518 | ||
519 | if (c < 1 || (np = lookup(ap[1]))->name == NULL) | |
520 | return; | |
521 | tnp = hshtab[hshval]; /* lookup sets hshval */ | |
522 | if (tnp == np) /* it's in first place */ | |
523 | hshtab[hshval] = np->next; | |
524 | else { | |
525 | for ( ; tnp->next != np; tnp = tnp->next) | |
526 | ; | |
527 | tnp->next = np->next; | |
528 | } | |
ecc33553 CC |
529 | /* |
530 | * If this is a reserved word, it has been removed from the | |
531 | * hastable. We do not want to actually free the space because | |
532 | * of the code in expand. Expand wants to to pointer compairs | |
533 | * to tell if this is a reserved word (e.g a special action | |
534 | * needs to take place). Thus if we do not free the space, | |
535 | * expand will still work, but the name will never be found | |
536 | * because it out of the symbol table! | |
537 | */ | |
538 | if (np->flag&RESERVED == 0) { /* If not reserved free it */ | |
539 | free(np->name); | |
540 | free(np->def); | |
541 | free((char *)np); | |
542 | } | |
5e785920 CC |
543 | } |
544 | ||
545 | char *copy(s) | |
546 | register char *s; | |
547 | { | |
548 | register char *p, *s1; | |
549 | ||
550 | p = s1 = malloc((unsigned)strlen(s)+1); | |
551 | if (p == NULL) { | |
552 | fprintf(stderr, "m4: no space for alloc\n"); | |
553 | exit(1); | |
554 | } | |
555 | while (*s1++ = *s++); | |
556 | return(p); | |
557 | } | |
558 | ||
559 | dodef(ap, c) | |
560 | char **ap; | |
561 | { | |
562 | if (c >= 2) { | |
563 | if (strcmp(ap[1], ap[2]) == 0) { | |
564 | fprintf(stderr, "m4: %s defined as itself\n", ap[1]); | |
565 | delexit(); | |
566 | } | |
ecc33553 | 567 | install(ap[1], ap[2], 0); |
5e785920 CC |
568 | } |
569 | else if (c == 1) | |
ecc33553 | 570 | install(ap[1], "", 0); |
5e785920 CC |
571 | } |
572 | ||
573 | doifdef(ap, c) | |
574 | char **ap; | |
575 | { | |
576 | register struct nlist *np; | |
577 | ||
578 | if (c < 2) | |
579 | return; | |
580 | if (lookup(ap[1])->name != NULL) | |
581 | pbstr(ap[2]); | |
582 | else if (c >= 3) | |
583 | pbstr(ap[3]); | |
584 | } | |
585 | ||
586 | dolen(ap, c) | |
587 | char **ap; | |
588 | { | |
589 | putnum((long) strlen(ap[1])); | |
590 | } | |
591 | ||
592 | docq(ap, c) | |
593 | char **ap; | |
594 | { | |
595 | if (c > 1) { | |
596 | lquote = *ap[1]; | |
597 | rquote = *ap[2]; | |
598 | } else if (c == 1) { | |
599 | lquote = rquote = *ap[1]; | |
600 | } else { | |
601 | #ifndef M4 | |
602 | lquote = GRAVE; | |
603 | rquote = ACUTE; | |
604 | #endif | |
605 | #ifdef M4 | |
606 | lquote = LBRAK; | |
607 | rquote = RBRAK; | |
608 | #endif | |
609 | } | |
610 | } | |
611 | ||
612 | doshift(ap, c) | |
613 | char **ap; | |
614 | { | |
615 | fprintf(stderr, "m4: shift not yet implemented\n"); | |
616 | } | |
617 | ||
618 | dodump(ap, c) | |
619 | char **ap; | |
620 | { | |
621 | int i; | |
622 | register struct nlist *np; | |
623 | ||
624 | if (c > 0) | |
625 | while (c--) { | |
626 | if ((np = lookup(*++ap))->name != NULL) | |
627 | fprintf(stderr, "`%s' `%s'\n", np->name, np->def); | |
628 | } | |
629 | else | |
630 | for (i=0; i<HSHSIZ; i++) | |
631 | for (np=hshtab[i]; np!=NULL; np=np->next) | |
632 | fprintf(stderr, "`%s' `%s'\n", np->name, np->def); | |
633 | } | |
634 | ||
635 | doerrp(ap, c) | |
636 | char **ap; | |
637 | { | |
638 | if (c > 0) { | |
639 | fprintf(stderr, ap[1], ap[2], ap[3], ap[4], ap[5], ap[6]); | |
640 | fprintf(stderr, "\n"); | |
641 | } | |
642 | } | |
643 | ||
644 | ||
645 | long evalval; /* return value from yacc stuff */ | |
646 | char *pe; /* used by grammar */ | |
647 | ||
648 | doeval(ap, c) | |
649 | char **ap; | |
650 | { | |
651 | ||
652 | if (c > 0) { | |
653 | pe = ap[1]; | |
654 | if (yyparse() == 0) | |
655 | putnum(evalval); | |
656 | else | |
657 | fprintf(stderr, "m4: invalid expression in eval: %s\n", ap[1]); | |
658 | } | |
659 | } | |
660 | ||
661 | doincl(ap, c, noisy) | |
662 | char **ap; | |
663 | { | |
664 | if (c > 0 && strlen(ap[1]) > 0) { | |
665 | infptr++; | |
666 | ip_stk[infptr] = cur_ip = ip; | |
667 | if ((infile[infptr] = fopen(ap[1], READ))==ERROR) { | |
668 | if (noisy) { | |
669 | fprintf(stderr, "m4: file not found: %s\n", ap[1]); | |
670 | delexit(); | |
671 | } | |
672 | else | |
673 | infptr--; | |
674 | } | |
675 | } | |
676 | } | |
677 | ||
678 | dosyscmd(ap, c) | |
679 | char **ap; | |
680 | { | |
681 | if (c > 0) | |
682 | system(ap[1]); | |
683 | } | |
684 | ||
685 | domake(ap, c) | |
686 | char **ap; | |
687 | { | |
688 | if (c > 0) | |
689 | pbstr(mktemp(ap[1])); | |
690 | } | |
691 | ||
692 | doincr(ap, c) | |
693 | char **ap; | |
694 | { | |
695 | if (c >= 1) | |
696 | putnum(ctol(ap[1])+1); | |
697 | } | |
698 | ||
699 | putnum(num) | |
700 | long num; | |
701 | { | |
702 | register sign; | |
703 | ||
704 | sign = (num < 0) ? '-' : '\0'; | |
705 | if (num < 0) | |
706 | num = -num; | |
707 | do { | |
708 | putbak(num%10+'0'); | |
709 | num = num/10; | |
710 | } while (num!=0); | |
711 | if (sign == '-') | |
712 | putbak('-'); | |
713 | } | |
714 | ||
715 | dosubstr(ap, c) | |
716 | char **ap; | |
717 | { | |
718 | int nc; | |
719 | register char *sp, *fc; | |
720 | ||
721 | if (c<2) | |
722 | return; | |
723 | if (c<3) | |
724 | nc = TOKS; | |
725 | else | |
726 | nc = ctoi(ap[3]); | |
727 | fc = ap[1] + max(0, min(ctoi(ap[2]), strlen(ap[1]))); | |
728 | sp = fc + min(nc, strlen(fc)); | |
729 | while (sp > fc) | |
730 | putbak(*--sp); | |
731 | } | |
732 | ||
733 | doindex(ap, c) | |
734 | char **ap; | |
735 | { | |
736 | if (c >= 2) | |
737 | putnum((long) strindex(ap[1], ap[2])); | |
738 | } | |
739 | ||
740 | strindex(p1, p2) | |
741 | char *p1, *p2; | |
742 | { | |
743 | register m; | |
744 | register char *s, *t, *p; | |
745 | ||
746 | for (p=p1; *p; p++) { | |
747 | s = p; | |
748 | m = 1; | |
749 | for (t=p2; *t; ) | |
750 | if (*t++ != *s++) | |
751 | m = 0; | |
752 | if (m == 1) | |
753 | return(p-p1); | |
754 | } | |
755 | return(-1); | |
756 | } | |
757 | ||
758 | dotransl(ap, c) | |
759 | char **ap; | |
760 | { | |
761 | register char *s, *fr, *to; | |
762 | ||
763 | if (c <= 1) return; | |
764 | ||
765 | if (c == 2) { | |
766 | register int i; | |
767 | to = ap[1]; | |
768 | for (s = ap[1]; *s; s++) { | |
769 | i = 0; | |
770 | for (fr = ap[2]; *fr; fr++) | |
771 | if (*s == *fr) { | |
772 | i++; | |
773 | break; | |
774 | } | |
775 | if (i == 0) | |
776 | *to++ = *s; | |
777 | } | |
778 | *to = '\0'; | |
779 | } | |
780 | ||
781 | if (c >= 3) { | |
782 | for (s = ap[1]; *s; s++) | |
783 | for (fr = ap[2], to = ap[3]; *fr && *to; fr++, to++) | |
784 | if (*s == *fr) | |
785 | *s = *to; | |
786 | } | |
787 | ||
788 | pbstr(ap[1]); | |
789 | } | |
790 | ||
791 | doif(ap, c) | |
792 | register char **ap; | |
793 | { | |
794 | if (c < 3) | |
795 | return; | |
796 | while (c >= 3) { | |
797 | if (strcmp(ap[1], ap[2]) == 0) { | |
798 | pbstr(ap[3]); | |
799 | return; | |
800 | } | |
801 | c -= 3; | |
802 | ap += 3; | |
803 | } | |
804 | if (c > 0) | |
805 | pbstr(ap[1]); | |
806 | } | |
807 | ||
808 | dodiv(ap, c) | |
809 | register char **ap; | |
810 | { | |
811 | register int f; | |
812 | ||
813 | if (c<1) | |
814 | f = 0; | |
815 | else | |
816 | f = ctoi(ap[1]); | |
817 | if (f>=10 || f<0) { | |
818 | curfile = NULL; | |
819 | return; | |
820 | } | |
821 | tempname[7] = 'a' + f; | |
822 | if (olist[f] || (olist[f]=fopen(tempname, WRITE))) { | |
823 | curout = f; | |
824 | curfile = olist[f]; | |
825 | } | |
826 | } | |
827 | ||
828 | doundiv(ap, c) | |
829 | char **ap; | |
830 | { | |
831 | register FILE *fp; | |
832 | register int i, ch; | |
833 | int j; | |
834 | ||
835 | if (c == 0) { | |
836 | for (i=1; i<10; i++) { | |
837 | if (i==curout || olist[i]==NULL) | |
838 | continue; | |
839 | fclose(olist[i]); | |
840 | tempname[7] = 'a'+i; | |
841 | fp = fopen(tempname, READ); | |
842 | if (curfile != NULL) | |
843 | while ((ch = getc(fp)) > 0) | |
844 | putc(ch, curfile); | |
845 | fclose(fp); | |
846 | unlink(tempname); | |
847 | olist[i] = NULL; | |
848 | } | |
849 | ||
850 | } | |
851 | else { | |
852 | for (j = 1; j <= c; j++) { | |
853 | i = ctoi(*++ap); | |
854 | if (i<1 || i>9 || i==curout || olist[i]==NULL) | |
855 | continue; | |
856 | fclose(olist[i]); | |
857 | tempname[7] = 'a'+i; | |
858 | fp = fopen(tempname, READ); | |
859 | if (curfile != NULL) | |
860 | while ((ch = getc(fp)) > 0) | |
861 | putc(ch, curfile); | |
862 | fclose(fp); | |
863 | unlink(tempname); | |
864 | olist[i] = NULL; | |
865 | } | |
866 | } | |
867 | } | |
868 | ||
869 | dodivnum(ap, c) | |
870 | char **ap; | |
871 | { | |
872 | putnum((long) curout); | |
873 | } | |
874 | ||
875 | dodnl(ap, c) | |
876 | char **ap; | |
877 | { | |
878 | register t; | |
879 | ||
880 | while ((t=getchr())!='\n' && t>=0) | |
881 | ; | |
882 | } | |
883 | ||
884 | long ctol(str) | |
885 | register char *str; | |
886 | { | |
887 | register sign; | |
888 | long num; | |
889 | ||
890 | while (*str==' ' || *str=='\t' || *str=='\n') | |
891 | str++; | |
892 | num = 0; | |
893 | if (*str == '-') { | |
894 | sign = -1; | |
895 | str++; | |
896 | } | |
897 | else | |
898 | sign = 1; | |
899 | while (*str>='0' && *str<='9') | |
900 | num = num*10 + *str++ - '0'; | |
901 | return(sign * num); | |
902 | } | |
903 | ||
904 | ctoi(s) | |
905 | char *s; | |
906 | { | |
907 | return(ctol(s)); | |
908 | } | |
909 | ||
910 | min(a, b) | |
911 | { | |
912 | if (a>b) | |
913 | return(b); | |
914 | return(a); | |
915 | } | |
916 | ||
917 | max(a, b) | |
918 | { | |
919 | if (a>b) | |
920 | return(a); | |
921 | return(b); | |
922 | } |