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