|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3:
4: #ifdef MSDOS
5: #define TMPFILE "m4%dXXX"
6: #define TMPMIN 2 /* minimum temp file length */
7: #else
8: #define TMPFILE "/tmp/m4%dxxxxxx"
9: #define TMPMIN 6
10: #endif
11:
12: #define isletter(c) (isalpha(c)||c=='_')
13: #define BQUOTE '`'
14: #define EQUOTE '\''
15: #define HASHSZ 199
16: #define STRBLK 16 /* block size for dynamic string storage */
17: #if STRBLK < 12
18: need room for decimal rep of long int
19: #endif
20:
21: enum {FUNC, MACD, DSKF, MSTR};
22: enum {EX, MY, DV, MD, AD, SB, EQ, NE, LE, GE, LT, GT, AN, OR, RP, NL};
23:
24: typedef struct { /* for storing variable-length strings */
25: int s_refc; /* references--when zero space is freed */
26: int s_hash; /* raw hash value (sum of chars in body) */
27: char *s_body; /* start of contents */
28: char *s_next; /* end of contents */
29: char *s_last; /* end of storage */
30: } STRING;
31:
32: typedef union ifr { /* input-source stack frame */
33: struct {
34: struct ifr *i_back;
35: char i_cbuf; /* unget buffer for lookahead */
36: int i_type; /* if type is MSTRing */
37: STRING *i_pstr;
38: char *i_pchr; /* next char */
39: } ifb;
40: struct {
41: struct ifr *i_back;
42: char i_cbuf;
43: int i_type; /* if type is DSKFile */
44: FILE *i_fp;
45: } ifdk;
46: } IFRAME;
47:
48: typedef struct fstk { /* file information stack frame */
49: struct fstk *f_back;
50: STRING *f_name; /* pointer to name (NULL if stdin) */
51: int f_flag; /* flag = 0 until EOF is reached */
52: int f_line; /* line counter */
53: } FFRAME;
54:
55: typedef struct ofr { /* argument collection stack frame */
56: struct ofr *o_back;
57: STRING *o_pstr;
58: } OFRAME;
59:
60: typedef struct ent { /* symbol table entry */
61: struct ent *e_next;
62: int e_type; /* FUNC or MACD */
63: union {
64: int (*e_pfun)();
65: STRING *e_pstr;
66: } e_at;
67: STRING *e_name;
68: } ENTRY;
69:
70: /*
71: * built in functions
72: */
73: extern int mchangequote(), mdecr(), mdefine(), mdivert(), mdivnum(), mdnl(),
74: mdumpdef(), merrprint(), meval(), mifdef(), mifelse(),
75: minclude(), mincr(), mindex(), mlen(), mmaketemp(), msinclude(),
76: msubstr(), msyscmd(), mtranslit(), mundefine(), mundivert();
77:
78: /*
79: * output file info
80: */
81: struct {
82: char *name;
83: FILE *fp;
84: } outfile[10] = {{ NULL, stdout }};
85:
86: /*
87: * op table for eval
88: */
89: struct opdata {
90: int optype;
91: char keychar;
92: char secchar;
93: int prec;
94: } optable[] = {
95: #define SI 8 /* precedence of unary + and - */
96: EX, '^', '\0', 7, EX, '*', '*', 7,
97: MY, '*', '\0', 6, DV, '/', '\0', 6, MD, '%', '\0', 6,
98: AD, '+', '\0', 5, SB, '-', '\0', 5,
99: EQ, '=', '=', 4, GE, '>', '=', 4, GT, '>', '\0', 4,
100: NE, '!', '=', 4, LE, '<', '=', 4, LT, '<', '\0', 4,
101: #define NT 3 /* precedence of unary ! */
102: AN, '&', '&', 2, AN, '&', '\0', 2,
103: OR, '|', '|', 1, OR, '|', '\0', 1,
104: RP, ')', '\0', 10, NL, '\0', '\0', 0
105: #define LP 0 /* precedence of open paren */
106: };
107:
108: ENTRY *e_root[HASHSZ]; /* pointers to symbol table hash buckets */
109: OFRAME *ostkptr; /* output stack pointer */
110: IFRAME *istkptr; /* input stack pointer */
111: FFRAME *fstkptr; /* file info stack pointer */
112: FILE *offp = stdout; /* current output file pointer */
113: int ofnum; /* current diversion number */
114: int lstdchr = '\n'; /* last char from stdin */
115: int single; /* single argument flag */
116: int dnlflag; /* delete to newline flag */
117:
118: char bqt = BQUOTE;
119: char eqt = EQUOTE;
120: extern char *alloc();
121: STRING *makestr();
122:
123: main(argc, argv)
124: int argc;
125: char *argv[];
126: {
127: #ifdef MSDOS
128: msdoscvt("m4", &argc, &argv);
129: #endif
130: buildin("changequote", mchangequote);
131: buildin("decr", mdecr);
132: buildin("define", mdefine);
133: buildin("divert", mdivert);
134: buildin("divnum", mdivnum);
135: buildin("dnl", mdnl);
136: buildin("dumpdef", mdumpdef);
137: buildin("errprint", merrprint);
138: buildin("eval", meval);
139: buildin("ifdef", mifdef);
140: buildin("ifelse", mifelse);
141: buildin("include", minclude);
142: buildin("incr", mincr);
143: buildin("index", mindex);
144: buildin("len", mlen);
145: buildin("maketemp", mmaketemp);
146: buildin("sinclude", msinclude);
147: buildin("substr", msubstr);
148: buildin("syscmd", msyscmd);
149: buildin("translit", mtranslit);
150: buildin("undefine", mundefine);
151: buildin("undivert", mundivert);
152:
153: single = (argc == 2);
154: if (argc > 1) {
155: while (--argc)
156: if (pushfile(*++argv))
157: process(0);
158: else
159: errorp(0, "cannot open %s", *argv);
160: } else {
161: pushfile("-");
162: process(0);
163: }
164: mdivert(NULL);
165: mundivert(NULL);
166: exit(0);
167: }
168:
169: process(pct)
170: int pct;
171: {
172: char lc = '\0';
173: register int c, qct = 0;
174: int i;
175: STRING *a[10];
176: register STRING *b;
177: ENTRY *e, *find();
178:
179: for (c=nxch(); pct && isspace(c); c=nxch())
180: ;
181: while (c != '\0') {
182: if (qct)
183: if (c == eqt) {
184: if (--qct)
185: outputc(c);
186: } else {
187: if (c == bqt)
188: ++qct;
189: outputc(c);
190: }
191: else if (c == bqt)
192: ++qct;
193: else if (c==')' && pct && !--pct || c==',' && pct==1)
194: return (c);
195: else if (isletter(c) && !isletter(lc) && !isdigit(lc)) {
196: b = makestr();
197: do {
198: appendstr(b, c);
199: lc = c;
200: c = nxch();
201: } while (isletter(c) || isdigit(c));
202: if ((e=find(b)) == NULL) {
203: outputs(b->s_body);
204: decstr(b);
205: continue;
206: }
207: for (i=9; i; a[i--]=NULL)
208: ;
209: a[0] = b;
210: if (c != '(') {
211: istkptr->i_cbuf = c;
212: if (c=='\n' && istkptr->i_type==DSKF)
213: if (fstkptr->f_flag)
214: --fstkptr->f_back->f_line;
215: else
216: --fstkptr->f_line;
217: } else do {
218: pushout(b=makestr());
219: c = process(1);
220: if (i++<9 && strlen(b->s_body))
221: a[i] = b;
222: else
223: decstr(b);
224: popout();
225: } while (c != ')');
226: if (e->e_type == MACD)
227: macro(e->e_at.e_pstr, a);
228: else
229: (*e->e_at.e_pfun)(a);
230: for (i = 0; i < 10; i++)
231: decstr(a[i]);
232: c = '\0';
233: } else {
234: if (c=='(' && pct)
235: ++pct;
236: outputc(c);
237: }
238: lc = c;
239: c = nxch();
240: }
241: if (pct)
242: errorp(1, "unexpected EOF");
243: return (c);
244: }
245:
246: macro(ps, pps)
247: STRING *ps, **pps;
248: {
249: STRING *x;
250: register char *b, *v;
251:
252: x = makestr();
253: b = ps->s_body;
254: while (*b) {
255: if (*b != '$')
256: appendstr(x, *b++);
257: else if (!isdigit(*++b))
258: appendstr(x, '$');
259: else if (ps = pps[*b++ - '0'])
260: for (v = ps->s_body; *v; v++)
261: appendstr(x, *v);
262: }
263: pushstr(x);
264: decstr(x);
265: }
266:
267: pushfile(s)
268: char *s;
269: {
270: FILE *fp, *fopen();
271: register STRING *a = NULL;
272: register FFRAME *ftemp = fstkptr;
273: char c;
274:
275: if (ftemp!=NULL && ftemp->f_flag) {
276: decstr(ftemp->f_name);
277: fstkptr = ftemp->f_back;
278: free(ftemp);
279: }
280: if ( strcmp(s, "-") == 0 )
281: fp = stdin;
282: else if ( (fp = fopen(s, "r")) == NULL )
283: return (0);
284: pushinp(DSKF);
285: istkptr->i_fp = fp;
286: ftemp = (FFRAME *)alloc(sizeof(FFRAME));
287: ftemp->f_back = fstkptr;
288: ftemp->f_line = 1;
289: ftemp->f_flag = 0;
290: if (fp!=stdin && !(fstkptr==NULL && single)) {
291: a = makestr();
292: while (c = *s++)
293: appendstr(a, c);
294: }
295: ftemp->f_name = a;
296: fstkptr = ftemp;
297: return (1);
298: }
299:
300: pushstr(a)
301: STRING *a;
302: {
303: if (a==NULL || *a->s_body=='\0')
304: return;
305: pushinp(MSTR);
306: istkptr->i_pstr = a;
307: istkptr->i_pchr = a->s_body;
308: ++a->s_refc;
309: }
310:
311: pushnum(x)
312: long x;
313: {
314: register STRING *a;
315:
316: a = makestr();
317: sprintf(a->s_body, "%ld", x);
318: pushstr(a);
319: decstr(a);
320: }
321:
322: pushinp(t)
323: char t;
324: {
325: IFRAME *itemp;
326:
327: itemp = istkptr;
328: istkptr = (IFRAME *)alloc(sizeof(IFRAME));
329: istkptr->i_back = itemp;
330: istkptr->i_type = t;
331: istkptr->i_cbuf = '\0';
332: }
333:
334: popinp()
335: {
336: IFRAME *itemp;
337:
338: itemp = istkptr;
339: switch (istkptr->i_type) {
340: case MSTR:
341: decstr(istkptr->i_pstr);
342: break;
343: case DSKF:
344: if (istkptr->i_fp != stdin)
345: fclose(istkptr->i_fp);
346: fstkptr->f_flag = 1;
347: break;
348: }
349: istkptr = istkptr->i_back;
350: free(itemp);
351: return (istkptr != NULL);
352: }
353:
354: pushout(b)
355: STRING *b;
356: {
357: OFRAME *otemp;
358:
359: otemp = (OFRAME *)alloc(sizeof(OFRAME));
360: otemp->o_back = ostkptr;
361: otemp->o_pstr = b;
362: ostkptr = otemp;
363: ++b->s_refc;
364: }
365:
366: popout()
367: {
368: OFRAME *otemp;
369:
370: otemp = ostkptr;
371: ostkptr = ostkptr->o_back;
372: decstr(otemp->o_pstr);
373: free(otemp);
374: }
375:
376: nxch()
377: {
378: register int c;
379: FFRAME *ftemp;
380:
381: if (istkptr == NULL)
382: return ('\0');
383: if ((ftemp = fstkptr)->f_flag) {
384: decstr(ftemp->f_name);
385: fstkptr = ftemp->f_back;
386: free(ftemp);
387: }
388: switch (istkptr->i_type) {
389: case DSKF:
390: if (c=istkptr->i_cbuf)
391: istkptr->i_cbuf = '\0';
392: else
393: c = getc(istkptr->i_fp);
394: if (istkptr->i_fp == stdin)
395: lstdchr = c;
396: if (c == EOF)
397: c = '\0';
398: else if (c == '\n')
399: if (fstkptr->f_flag)
400: ++fstkptr->f_back->f_line;
401: else
402: ++fstkptr->f_line;
403: break;
404: case MSTR:
405: if (c=istkptr->i_cbuf)
406: istkptr->i_cbuf = '\0';
407: else
408: c = *istkptr->i_pchr++;
409: break;
410: }
411: if (c == '\0')
412: return (popinp()? nxch() : c);
413: else if (!dnlflag)
414: return (c);
415: if (c == '\n')
416: dnlflag = 0;
417: return (nxch());
418: }
419:
420: outputc(c)
421: char c;
422: {
423: if (ostkptr != NULL)
424: appendstr(ostkptr->o_pstr, c);
425: else
426: outc(c);
427: }
428:
429: outc(c)
430: char c;
431: {
432: if (offp != NULL)
433: putc(c, offp);
434: }
435:
436:
437: STRING *
438: makestr()
439: {
440: register STRING *a;
441:
442: a = (STRING *)alloc(sizeof(STRING));
443: a->s_body = a->s_next = (STRING *)alloc(STRBLK);
444: a->s_last = a->s_body + STRBLK - 1;
445: a->s_refc = 1;
446: a->s_hash = 0;
447: *a->s_next = '\0';
448: return (a);
449: }
450:
451: appendstr(a, c)
452: STRING *a;
453: char c;
454: {
455: register char *r, *s, *t;
456: int size;
457:
458: if (a->s_next < a->s_last) {
459: *a->s_next++ = c;
460: *a->s_next = '\0';
461: } else {
462: r = s = alloc(size = a->s_last - (t = a->s_body) + 1 + STRBLK);
463: while (*s++ = *t++)
464: ;
465: *(a->s_next = s) = '\0';
466: *--s = c;
467: free(a->s_body);
468: a->s_last = (a->s_body = r) + size - 1;
469: }
470: a->s_hash += c;
471: }
472:
473: decstr(a)
474: STRING *a;
475: {
476: if (a == NULL)
477: return;
478: if (--a->s_refc)
479: return;
480: free(a->s_body);
481: free(a);
482: }
483:
484: cmpstr(a, b)
485: STRING *a, *b;
486: {
487: if (a==NULL && b==NULL)
488: return (1);
489: if (a==NULL && b!=NULL || a!=NULL && b==NULL)
490: return (0);
491: return (!strcmp(a->s_body, b->s_body));
492: }
493:
494: outputs(s)
495: char *s;
496: {
497: register char *t, c;
498:
499: for (t = s; c = *t++; outputc(c))
500: ;
501: }
502:
503: ENTRY *
504: find(a)
505: STRING *a;
506: {
507: register ENTRY *e;
508: register int hash;
509:
510: hash = a->s_hash;
511: for (e = e_root[hash % HASHSZ]; e != NULL; e = e->e_next)
512: if (e->e_name->s_hash == hash
513: && strcmp(e->e_name->s_body, a->s_body) == 0)
514: return (e);
515: return (NULL);
516: }
517:
518: buildin(s, f)
519: char *s;
520: int (*f)();
521: {
522: STRING *a;
523: register int hash;
524: register ENTRY *e;
525:
526: a = makestr();
527: while (*s)
528: appendstr(a, *s++);
529: hash = a->s_hash % HASHSZ;
530: e = (ENTRY *)alloc(sizeof(ENTRY));
531: e->e_next = e_root[hash];
532: e->e_type = FUNC;
533: e->e_at.e_pfun = f;
534: e->e_name = a;
535: e_root[hash] = e;
536: }
537:
538: char *
539: alloc(n)
540: int n;
541: {
542: char *x;
543:
544: if ((x=malloc(n)) != NULL)
545: return(x);
546: errorp(1, "out of space");
547: }
548:
549: /* VARARGS */
550: errorp(f, x)
551: int f;
552: {
553: fprintf(stderr, "m4: ");
554: if (fstkptr != NULL) {
555: if (fstkptr->f_name != NULL)
556: fprintf(stderr, "%s: ", fstkptr->f_name->s_body);
557: fprintf(stderr, "%d: ", fstkptr->f_line);
558: }
559: fprintf(stderr, "%r", &x);
560: putc('\n', stderr);
561: if (f) {
562: while (lstdchr!=EOF && lstdchr!='\n')
563: lstdchr = getchar();
564: exit(1);
565: }
566: }
567:
568: mchangequote(pps)
569: STRING **pps;
570: {
571: bqt = pps[1]? *pps[1]->s_body : BQUOTE;
572: eqt = pps[2]? *pps[2]->s_body : EQUOTE;
573: }
574:
575: mdefine(pps)
576: STRING **pps;
577: {
578: ENTRY *find();
579: register ENTRY *e;
580: register char *s;
581: register int hash;
582: int c;
583: static char illmac[] = "illegal macro name: %s";
584:
585: if (pps[1]==NULL || !isletter(*pps[1]->s_body)) {
586: errorp(0, illmac, pps[1]!=NULL? pps[1]->s_body : NULL);
587: return;
588: }
589: s = pps[1]->s_body + 1;
590: while (c = *s++)
591: if (!(isletter(c)||isdigit(c))) {
592: errorp(0, illmac, pps[1]->s_body);
593: return;
594: }
595: if (e = find(pps[1])) {
596: if (e->e_type == MACD)
597: decstr(e->e_at.e_pstr);
598: } else {
599: e = (ENTRY *)alloc(sizeof(ENTRY));
600: e->e_next = e_root[hash = pps[1]->s_hash % HASHSZ];
601: e->e_name = pps[1];
602: ++pps[1]->s_refc;
603: e_root[hash] = e;
604: }
605: e->e_type = MACD;
606: if (pps[2]) {
607: e->e_at.e_pstr = pps[2];
608: ++pps[2]->s_refc;
609: } else
610: e->e_at.e_pstr = makestr();
611: }
612:
613: mdivert(pps)
614: STRING **pps;
615: {
616: char *fn;
617:
618: if (pps == NULL)
619: ofnum = 0;
620: else
621: ofnum = (pps[1] != NULL)? atoi(pps[1]->s_body) : 0;
622: if (ofnum>0 && ofnum<=9) {
623: if (outfile[ofnum].fp == NULL) {
624: outfile[ofnum].name = fn = alloc(15);
625: sprintf(fn, TMPFILE, ofnum);
626: mktemp(fn);
627: if ((outfile[ofnum].fp=fopen(fn,"w"))==NULL)
628: errorp(1, "m4: /tmp open error\n");
629: }
630: }
631: if (ofnum>=0 && ofnum<=9)
632: offp = outfile[ofnum].fp;
633: else
634: offp = NULL;
635: }
636:
637: mdivnum()
638: {
639: pushnum((long)ofnum);
640: }
641:
642: mdnl()
643: {
644: dnlflag = 1;
645: }
646:
647: mdumpdef(pps)
648: STRING **pps;
649: {
650: ENTRY *find();
651: register ENTRY *e;
652: register int i, f = 0;
653: int hash;
654:
655: for (i = 1; i <= 9; ++i)
656: if (pps[i] != NULL) {
657: if (e=find(pps[i]))
658: outdef(e);
659: f = 1;
660: }
661: if (!f)
662: for (hash = 0; hash < HASHSZ; ++hash)
663: for (e = e_root[hash]; e; e = e->e_next) {
664: outputc(bqt);
665: outputs(e->e_name->s_body);
666: outputc(eqt);
667: outputc('\t');
668: outdef(e);
669: outputc('\n');
670: }
671: }
672:
673: outdef(e)
674: ENTRY *e;
675: {
676: if (e->e_type == MACD) {
677: outputc(bqt);
678: outputs(e->e_at.e_pstr->s_body);
679: outputc(eqt);
680: }
681: }
682:
683: merrprint(pps)
684: STRING **pps;
685: {
686: register int i;
687:
688: for (i=1; i<=9; i++)
689: if (pps[i])
690: fprintf(stderr, pps[i]->s_body);
691: }
692:
693: meval(pps)
694: STRING **pps;
695: {
696: long calc();
697: char *s;
698:
699: if (pps[1] == NULL)
700: pushnum((long)0);
701: else {
702: s = pps[1]->s_body;
703: pushnum(calc(0, &s));
704: }
705: }
706:
707: long
708: calc(pr, ps)
709: int pr;
710: char **ps;
711: {
712: register struct opdata *opptr;
713: register char c;
714: char *s;
715: long val1, val2, l;
716: int oplength;
717:
718: for (s = *ps; isspace(*s); ++s)
719: ;
720: if (isdigit(c=*s++))
721: for (val1 = c - '0'; isdigit(c = *s); ++s)
722: val1 = 10 * val1 + c - '0';
723: else switch (c) {
724: case '+':
725: val1 = calc(SI, &s);
726: break;
727: case '-':
728: val1 =-calc(SI, &s);
729: break;
730: case '!':
731: val1 =!calc(NT, &s);
732: break;
733: case '(':
734: val1 = calc(LP, &s);
735: break;
736: default:
737: if (c == '\0')
738: errorp(0, "eval: missing value");
739: else
740: errorp(0, "eval: invalid expression");
741: s = NULL;
742: }
743: if ((*ps = s) == NULL)
744: return (0);
745: for (;;) {
746: while (s!=NULL && isspace(c = *s))
747: ++s;
748: oplength = 1;
749: for (opptr = optable; s != NULL; ++opptr)
750: if (c != opptr->keychar) {
751: if (opptr->keychar == '\0')
752: s = NULL;
753: } else if (opptr->secchar=='\0') {
754: break;
755: } else if (opptr->secchar == *(s+1)) {
756: ++oplength;
757: break;
758: }
759: if ((*ps = s) == NULL) {
760: errorp(0, "eval: missing or unknown operator");
761: return (0);
762: }
763: if (opptr->prec <= pr)
764: return (val1);
765: *ps = s += oplength;
766: if (c == ')')
767: return (val1);
768: val2 = calc(opptr->prec, &s);
769: if ((*ps = s) == NULL)
770: return (0);
771: switch (opptr->optype) {
772: case EX:
773: if (val2 < 0)
774: val1 = 0;
775: else {
776: for (l = 1; val2; --val2)
777: l *= val1;
778: val1 = l;
779: }
780: break;
781: case MY:
782: val1 *= val2;
783: break;
784: case DV:
785: val1 /= val2;
786: break;
787: case MD:
788: val1 %= val2;
789: break;
790: case AD:
791: val1 += val2;
792: break;
793: case SB:
794: val1 -= val2;
795: break;
796: case EQ:
797: val1 = (val1 == val2);
798: break;
799: case NE:
800: val1 = (val1 != val2);
801: break;
802: case GE:
803: val1 = (val1 >= val2);
804: break;
805: case LE:
806: val1 = (val1 <= val2);
807: break;
808: case GT:
809: val1 = (val1 > val2);
810: break;
811: case LT:
812: val1 = (val1 < val2);
813: break;
814: case AN:
815: val1 = (val1 && val2);
816: break;
817: case OR:
818: val1 = (val1 || val2);
819: break;
820: }
821: }
822: }
823:
824: mifdef(pps)
825: STRING **pps;
826: {
827: ENTRY *find();
828:
829: if (pps[1] && find(pps[1])) {
830: pushstr(pps[2]);
831: } else
832: pushstr(pps[3]);
833: }
834:
835: mifelse(pps)
836: STRING **pps;
837: {
838: if (cmpstr(pps[1], pps[2]))
839: pushstr(pps[3]);
840: else if (moreargs(pps, 5))
841: if (cmpstr(pps[4], pps[5]))
842: pushstr(pps[6]);
843: else if (moreargs(pps, 8))
844: if (cmpstr(pps[7], pps[8]))
845: pushstr(pps[9]);
846: else
847: return;
848: else
849: pushstr(pps[7]);
850: else
851: pushstr(pps[4]);
852: }
853:
854: moreargs(pps, n)
855: STRING **pps;
856: register int n;
857: {
858: register int i;
859:
860: for (i=n; i<=9; i++)
861: if (pps[i] != NULL)
862: return (1);
863: return (0);
864: }
865:
866: minclude(pps)
867: STRING **pps;
868: {
869: if (msinclude(pps))
870: return;
871: errorp(1, "cannot open %s", pps[1]!=NULL? pps[1]->s_body : NULL);
872: }
873:
874: mincr(pps)
875: STRING **pps;
876: {
877: long atol();
878:
879: pushnum((long)((pps[1] != NULL)? atol(pps[1]->s_body)+1 : 1));
880: }
881:
882: mdecr(pps)
883: STRING **pps;
884: {
885: long atol();
886:
887: pushnum((long)((pps[1] != NULL)? atol(pps[1]->s_body)-1 : -1));
888: }
889:
890: mindex(pps)
891: STRING **pps;
892: {
893: register char *pc, *pf;
894: register int ln;
895: long v;
896: char *index();
897:
898: if (pps[2] == NULL)
899: v = 0;
900: else if (pps[1] == NULL)
901: v = -1;
902: else {
903: pc = pps[1]->s_body;
904: ln = strlen(pf = pps[2]->s_body);
905: while ((pc=index(pc, *pf))!=NULL && strncmp(pc, pf, ln))
906: ++pc;
907: v = (pc != NULL)? (long)(pc-pps[1]->s_body) : -1;
908: }
909: pushnum(v);
910: }
911:
912: mlen(pps)
913: STRING **pps;
914: {
915: pushnum((long)((pps[1] != NULL)? pps[1]->s_next-pps[1]->s_body : 0));
916: }
917:
918: mmaketemp(pps)
919: STRING **pps;
920: {
921: register char *pc;
922: if (pps[1]==NULL || strlen(pc = pps[1]->s_body)<TMPMIN)
923: return;
924: mktemp(pc);
925: pushstr(pps[1]);
926: }
927:
928: msinclude(pps)
929: STRING **pps;
930: {
931: return (pushfile((pps[1] != NULL)? pps[1]->s_body : NULL));
932: }
933:
934: msubstr(pps)
935: STRING **pps;
936: {
937: register char *pc, *pb, *pe;
938: int len, n, s;
939: STRING *a;
940:
941: if (pps[1] == NULL)
942: return;
943: len = strlen(pc = pps[1]->s_body);
944: if (pps[2] == NULL) {
945: n = (pps[3] != NULL)? atoi(pps[3]->s_body) : len;
946: s = (n>0)? 0 : -1;
947: } else {
948: s = atoi(pps[2]->s_body);
949: n = (pps[3] != NULL)? atoi(pps[3]->s_body) : (s>0)? len : -len;
950: }
951: if (n == 0)
952: return;
953: pe = pc + len;
954: if (s < 0)
955: s += len;
956: if (n < 0) {
957: s += n + 1;
958: n = -n;
959: }
960: a = makestr();
961: for (pb = pc + s; n--; ++pb)
962: if (pb>=pc && pb<=pe)
963: appendstr(a, *pb);
964: pushstr(a);
965: decstr(a);
966: }
967:
968: msyscmd(pps)
969: STRING **pps;
970: {
971: if (pps[1])
972: system(pps[1]->s_body);
973: }
974:
975: mtranslit(pps)
976: STRING **pps;
977: {
978: register char *pc, *pt, *pr;
979: char c = '\0';
980: STRING *a;
981:
982: if (pps[1]==NULL || pps[2]==NULL)
983: return;
984: a = makestr();
985: pc = pps[1]->s_body;
986: do {
987: pt = pps[2]->s_body;
988: pr = (pps[3] != NULL)? pps[3]->s_body : &c;
989: do {
990: if (*pc == *pt)
991: break;
992:
993: if (*pr)
994: ++pr;
995: } while (*++pt);
996: if (*pt) {
997: if (*pr)
998: appendstr(a, *pr);
999: } else
1000: appendstr(a, *pc);
1001: } while (*++pc);
1002: pushstr(a);
1003: decstr(a);
1004: }
1005:
1006: mundefine(pps)
1007: STRING **pps;
1008: {
1009: register ENTRY *e, *ep = NULL;
1010: register int hash;
1011:
1012: if (pps[1] == NULL)
1013: return;
1014: hash = pps[1]->s_hash;
1015: for (e = e_root[hash % HASHSZ]; e != NULL; e = e->e_next)
1016: if (e->e_name->s_hash == hash
1017: && strcmp(e->e_name->s_body, pps[1]->s_body) == 0)
1018: break;
1019: else
1020: ep = e;
1021: if (e == NULL)
1022: return;
1023: if (e->e_type == MACD)
1024: decstr(e->e_at.e_pstr);
1025: decstr(e->e_name);
1026: if (ep != NULL)
1027: ep->e_next = e->e_next;
1028: else
1029: e_root[hash % HASHSZ] = e->e_next;
1030: free(e);
1031: }
1032:
1033: mundivert(pps)
1034: STRING **pps;
1035: {
1036: register i, f = 0;
1037:
1038: if (pps)
1039: for (i = 1; i <= 9; i++)
1040: if (pps[i]) {
1041: undiv(atoi(pps[i]->s_body));
1042: f = 1;
1043: }
1044: if (pps==NULL || f==0)
1045: for (i = 1; i <= 9; i++)
1046: undiv(i);
1047: }
1048:
1049: undiv(n)
1050: register int n;
1051: {
1052: register int c;
1053: register FILE *fp;
1054:
1055: if (n>0 && n<=9 && (fp=outfile[n].fp) != NULL && ofnum!=n) {
1056: fclose(fp);
1057: if ((fp=fopen(outfile[n].name, "r")) == NULL)
1058: errorp(1, "cannot open %s", outfile[n].name);
1059: while ((c=getc(fp)) != EOF)
1060: outc(c);
1061: fclose(fp);
1062: unlink(outfile[n].name);
1063: free(outfile[n].name);
1064: outfile[n].name = outfile[n].fp = NULL;
1065: }
1066: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.