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