|
|
1.1 root 1: /*************************************************************************
2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3: * provided to you without charge for use only on a licensed Unix *
4: * system. You may copy JOVE provided that this notice is included with *
5: * the copy. You may not sell copies of this program or versions *
6: * modified for use on microcomputer systems, unless the copies are *
7: * included with a Unix system distribution and the source is provided. *
8: *************************************************************************/
9:
10: #include "jove.h"
11: #include "io.h"
12: #include "termcap.h"
13: #include "ctype.h"
14: #ifdef JOB_CONTROL
15: # include <signal.h>
16: #endif
17:
18: #include <varargs.h>
19:
20: int InJoverc = 0;
21:
22: extern int getch(),
23: getchar();
24:
25: /* Auto execute code */
26:
27: #define NEXECS 20
28:
29: private struct {
30: char *a_pattern;
31: data_obj *a_cmd;
32: } AutoExecs[NEXECS] = {0};
33:
34: private int ExecIndex = 0;
35:
36: /* Command auto-execute. */
37:
38: CAutoExec()
39: {
40: DefAutoExec(findcom);
41: }
42:
43: /* Macro auto-execute. */
44:
45: MAutoExec()
46: {
47: DefAutoExec(findmac);
48: }
49:
50: /* VARARGS0 */
51:
52: DefAutoExec(proc)
53: data_obj *(*proc)();
54: {
55: data_obj *d;
56: char *pattern;
57: int i;
58:
59: if (ExecIndex >= NEXECS)
60: complain("Too many auto-executes, max %d.", NEXECS);
61: if ((d = (*proc)(ProcFmt)) == 0)
62: return;
63: pattern = ask((char *) 0, ": %f %s ", d->Name);
64: for (i = 0; i < ExecIndex; i++)
65: if ((AutoExecs[i].a_cmd == d) &&
66: (strcmp(pattern, AutoExecs[i].a_pattern) == 0))
67: return; /* Eliminate duplicates. */
68: AutoExecs[ExecIndex].a_pattern = copystr(pattern);
69: AutoExecs[ExecIndex].a_cmd = d;
70: ExecIndex++;
71: }
72:
73: /* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the
74: same kind of file (i.e., match the same pattern) or OLD is 0 and it
75: matches, we execute the command associated with that kind of file. */
76:
77: DoAutoExec(new, old)
78: register char *new,
79: *old;
80: {
81: register int i;
82:
83: exp_p = 1;
84: exp = 1; /* So minor modes don't toggle. We always want
85: them on. */
86: if (new == 0)
87: return;
88: for (i = 0; i < ExecIndex; i++)
89: if ((LookingAt(AutoExecs[i].a_pattern, new, 0)) &&
90: (old == 0 || !LookingAt(AutoExecs[i].a_pattern, old, 0)))
91: ExecCmd(AutoExecs[i].a_cmd);
92: }
93:
94: BindAKey()
95: {
96: BindSomething(findcom);
97: }
98:
99: BindMac()
100: {
101: BindSomething(findmac);
102: }
103:
104: extern int EscPrefix(),
105: CtlxPrefix(),
106: MiscPrefix();
107:
108: data_obj **
109: IsPrefix(cp)
110: data_obj *cp;
111: {
112: int (*proc)();
113:
114: if (cp == 0 || (cp->Type & TYPEMASK) != FUNCTION)
115: return 0;
116: proc = ((struct cmd *) cp)->c_proc;
117: if (proc == EscPrefix)
118: return pref1map;
119: if (proc == CtlxPrefix)
120: return pref2map;
121: if (proc == MiscPrefix)
122: return miscmap;
123: return 0;
124: }
125:
126: unbind_aux(c)
127: {
128: if (c == CR || c == LF)
129: return FALSE; /* tells do_ask to return */
130: Insert(c);
131: return !FALSE;
132: }
133:
134: UnbindC()
135: {
136: char *keys;
137: data_obj **map = mainmap;
138:
139: keys = do_ask("\r\n\01\02\03\04\05\06\010\011\013\014\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037", unbind_aux, (char *) 0, ProcFmt);
140: if (keys == 0)
141: return;
142: for (;;) {
143: if (keys[1] == '\0')
144: break;
145: if ((map = IsPrefix(map[*keys])) == 0)
146: break;
147: keys++;
148: }
149: if (keys[1] != 0)
150: complain("That's not a legitimate key sequence.");
151: map[keys[0]] = 0;
152: }
153:
154: addgetc()
155: {
156: int c;
157:
158: if (!InJoverc)
159: Asking = strlen(mesgbuf);
160: c = getch();
161: if (InJoverc) {
162: if (c == '\n')
163: return EOF; /* this isn't part of the sequence */
164: else if (c == '\\') {
165: if ((c = getch()) == LF)
166: complain("[Premature end of line]");
167: } else if (c == '^') {
168: if ((c = getch()) == '?')
169: c = RUBOUT;
170: else if (isalpha(c) || index("[\\]^_", c))
171: c = c - '@';
172: else
173: complain("[Unknown control character]");
174: }
175: }
176:
177: Asking = 0;
178: add_mess("%p ", c);
179:
180: return c;
181: }
182:
183: BindWMap(map, lastkey, cmd)
184: data_obj **map,
185: *cmd;
186: {
187: data_obj **nextmap;
188: int c;
189:
190: c = addgetc();
191: if (c == EOF) {
192: if (lastkey == EOF)
193: complain("[Empty key sequence]");
194: complain("[Premature end of key sequence]");
195: } else {
196: if (nextmap = IsPrefix(map[c]))
197: BindWMap(nextmap, c, cmd);
198: else
199: map[c] = cmd;
200: }
201: }
202:
203: /* VARARGS0 */
204:
205: BindSomething(proc)
206: data_obj *(*proc)();
207: {
208: data_obj *d;
209:
210: if ((d = (*proc)(ProcFmt)) == 0)
211: return;
212: s_mess(": %f %s ", d->Name);
213: BindWMap(mainmap, EOF, d);
214: }
215:
216: /* Describe key */
217:
218: DescWMap(map, key)
219: data_obj **map;
220: {
221: data_obj *cp = map[key],
222: **prefp;
223:
224: if (cp == 0)
225: add_mess("is unbound.");
226: else if (prefp = IsPrefix(cp))
227: DescWMap(prefp, addgetc());
228: else
229: add_mess("is bound to %s.", cp->Name);
230: }
231:
232: KeyDesc()
233: {
234: s_mess(ProcFmt);
235: DescWMap(mainmap, addgetc());
236: }
237:
238: DescCom()
239: {
240: data_obj *dp;
241: char pattern[100],
242: doc_type[40],
243: *file = CMD_DB;
244: File *fp;
245:
246: if (!strcmp(LastCmd->Name, "describe-variable"))
247: dp = (data_obj *) findvar(ProcFmt);
248: else
249: dp = (data_obj *) findcom(ProcFmt);
250:
251: if (dp == 0)
252: return;
253: fp = open_file(file, iobuff, F_READ, COMPLAIN, QUIET);
254: Placur(ILI, 0);
255: flusho();
256: sprintf(pattern, "^:entry \"%s\" \"\\([^\"]*\\)\"", dp->Name);
257: TOstart("Help", TRUE);
258: for (;;) {
259: if (f_gets(fp, genbuf, LBSIZE) == EOF) {
260: Typeout("There is no documentation for \"%s\".", dp->Name);
261: goto outahere;
262: }
263: if ((strncmp(genbuf, ":entry", 6) == 0) && LookingAt(pattern, genbuf, 0))
264: break;
265: }
266: /* found it ... let's print it */
267: putmatch(1, doc_type, sizeof doc_type);
268: if (strcmp("Variable", doc_type) == 0)
269: Typeout(dp->Name);
270: else if (strcmp("Command", doc_type) == 0) {
271: char binding[128];
272:
273: find_binds((struct cmd *) dp, binding);
274: if (blnkp(binding))
275: Typeout("To invoke %s, type \"ESC X %s<cr>\".",
276: dp->Name,
277: dp->Name);
278: else
279: Typeout("Type \"%s\" to invoke %s.", binding, dp->Name);
280: }
281: Typeout("");
282: while (f_gets(fp, genbuf, LBSIZE) != EOF)
283: if (strncmp(genbuf, ":entry", 6) == 0)
284: goto outahere;
285: else
286: Typeout("%s", genbuf);
287: outahere:
288: f_close(fp);
289: TOstop();
290: }
291:
292: DescBindings()
293: {
294: extern int Typeout();
295:
296: TOstart("Key Bindings", TRUE);
297: DescMap(mainmap, NullStr);
298: TOstop();
299: }
300:
301: DescMap(map, pref)
302: data_obj **map;
303: char *pref;
304: {
305: int c1,
306: c2 = 0,
307: numbetween;
308: char keydescbuf[40];
309: data_obj **prefp;
310:
311: for (c1 = 0; c1 < 0200 && c2 < 0200; c1 = c2 + 1) {
312: c2 = c1;
313: if (map[c1] == 0)
314: continue;
315: while (++c2 < 0200 && map[c1] == map[c2])
316: ;
317: c2--;
318: numbetween = c2 - c1;
319: if (numbetween == 1)
320: sprintf(keydescbuf, "%s {%p,%p}", pref, c1, c2);
321: else if (numbetween == 0)
322: sprintf(keydescbuf, "%s %p", pref, c1);
323: else
324: sprintf(keydescbuf, "%s [%p-%p]", pref, c1, c2);
325: if (prefp = IsPrefix(map[c1]))
326: DescMap(prefp, keydescbuf);
327: else
328: Typeout("%-14s%s", keydescbuf, map[c1]->Name);
329: }
330: }
331:
332: private
333: find_binds(cp, buf)
334: struct cmd *cp;
335: char *buf;
336: {
337: char *endp;
338:
339: buf[0] = '\0';
340: fb_aux(cp, mainmap, (char *) 0, buf);
341: endp = buf + strlen(buf) - 2;
342: if ((endp > buf) && (strcmp(endp, ", ") == 0))
343: *endp = '\0';
344: }
345:
346: private
347: fb_aux(cp, map, prefix, buf)
348: register data_obj *cp,
349: **map;
350: char *buf,
351: *prefix;
352: {
353: int c1,
354: c2;
355: char *bufp = buf + strlen(buf),
356: prefbuf[20];
357: data_obj **prefp;
358:
359: for (c1 = c2 = 0; c1 < 0200 && c2 < 0200; c1 = c2 + 1) {
360: c2 = c1;
361: if (map[c1] == cp) {
362: while (++c2 < 0200 && map[c1] == map[c2])
363: ;
364: c2--;
365: if (prefix)
366: sprintf(bufp, "%s ", prefix);
367: bufp += strlen(bufp);
368: switch (c2 - c1) {
369: case 0:
370: sprintf(bufp, "%p, ", c1);
371: break;
372:
373: case 1:
374: sprintf(bufp, "{%p,%p}, ", c1, c2);
375: break;
376:
377: default:
378: sprintf(bufp, "[%p-%p], ", c1, c2);
379: break;
380: }
381: }
382: if (prefp = IsPrefix(map[c1])) {
383: sprintf(prefbuf, "%p", c1);
384: fb_aux(cp, prefp, prefbuf, bufp);
385: }
386: bufp += strlen(bufp);
387: }
388: }
389:
390: Apropos()
391: {
392: register struct cmd *cp;
393: register struct macro *m;
394: register struct variable *v;
395: char *ans;
396: int anyfs = 0,
397: anyvs = 0,
398: anyms = 0;
399: char buf[256];
400:
401: ans = ask((char *) 0, ": %f (keyword) ");
402: TOstart("Help", TRUE);
403: for (cp = commands; cp->Name != 0; cp++)
404: if (sindex(ans, cp->Name)) {
405: if (anyfs == 0) {
406: Typeout("Commands");
407: Typeout("--------");
408: }
409: find_binds(cp, buf);
410: if (buf[0])
411: Typeout(": %-30s(%s)", cp->Name, buf);
412: else
413: Typeout(": %s", cp->Name);
414: anyfs++;
415: }
416: if (anyfs)
417: Typeout(NullStr);
418: for (v = variables; v->Name != 0; v++)
419: if (sindex(ans, v->Name)) {
420: if (anyvs == 0) {
421: Typeout("Variables");
422: Typeout("---------");
423: }
424: anyvs++;
425: vpr_aux(v, buf);
426: Typeout(": set %-26s%s", v->Name, buf);
427: }
428: if (anyvs)
429: Typeout(NullStr);
430: for (m = macros; m != 0; m = m->m_nextm)
431: if (sindex(ans, m->Name)) {
432: if (anyms == 0) {
433: Typeout("Macros");
434: Typeout("------");
435: }
436: anyms++;
437: find_binds((data_obj *) m, buf);
438: if (buf[0])
439: Typeout(": %-30s(%s)", m->Name, buf);
440: else
441: Typeout(": %-30s%s", "execute-macro", m->Name);
442: }
443: TOstop();
444: }
445:
446: Extend()
447: {
448: data_obj *d;
449:
450: if (d = findcom(": "))
451: ExecCmd(d);
452: }
453:
454: /* Read a positive integer from CP. It must be in base BASE, and
455: complains if it isn't. If allints is nonzero, all the characters
456: in the string must be integers or we return -1; otherwise we stop
457: reading at the first nondigit. */
458:
459: chr_to_int(cp, base, allints)
460: register char *cp;
461: {
462: register int c;
463: int value = 0;
464:
465: while (c = *cp++) {
466: if (!isdigit(c)) {
467: if (allints)
468: return -1;
469: break;
470: }
471: c = c - '0';
472: if (c >= base)
473: complain("You must specify in base %d.", base);
474: value = value * base + c;
475: }
476: return value;
477: }
478:
479: ask_int(prompt, base)
480: char *prompt;
481: int base;
482: {
483: char *val = ask((char *) 0, prompt);
484: int value = chr_to_int(val, base, 1);
485:
486: if (value < 0)
487: complain("That's not a number!");
488: return value;
489: }
490:
491: private
492: vpr_aux(vp, buf)
493: register struct variable *vp;
494: char *buf;
495: {
496: switch (vp->v_flags & V_TYPEMASK) {
497: case V_BASE10:
498: sprintf(buf, "%d", *(vp->v_value));
499: break;
500:
501: case V_BASE8:
502: sprintf(buf, "%o", *(vp->v_value));
503: break;
504:
505: case V_BOOL:
506: sprintf(buf, (*(vp->v_value)) ? "on" : "off");
507: break;
508:
509: case V_STRING:
510: sprintf(buf, "%s", (char *) vp->v_value);
511: break;
512:
513: case V_CHAR:
514: sprintf(buf, "%p", *(vp->v_value));
515: break;
516: }
517: }
518:
519: PrVar()
520: {
521: struct variable *vp;
522: char prbuf[256];
523:
524: if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
525: return;
526: vpr_aux(vp, prbuf);
527: s_mess(": %f %s => %s", vp->Name, prbuf);
528: }
529:
530: SetVar()
531: {
532: struct variable *vp;
533: char *prompt;
534:
535: if ((vp = (struct variable *) findvar(ProcFmt)) == 0)
536: return;
537: prompt = sprint(": %f %s ", vp->Name);
538:
539: switch (vp->v_flags & V_TYPEMASK) {
540: case V_BASE10:
541: case V_BASE8:
542: {
543: int value;
544:
545: value = ask_int(prompt, ((vp->v_flags & V_TYPEMASK) == V_BASE10)
546: ? 10 : 8);
547: *(vp->v_value) = value;
548: break;
549: }
550:
551: case V_BOOL:
552: {
553: char *def = *(vp->v_value) ? "off" : "on",
554: *on_off;
555: int value;
556:
557: on_off = ask(def, prompt);
558: if (casecmp(on_off, "on") == 0)
559: value = ON;
560: else if (casecmp(on_off, "off") == 0)
561: value = OFF;
562: else
563: complain("Boolean variables must be ON or OFF.");
564: *(vp->v_value) = value;
565: s_mess("%s%s", prompt, value ? "on" : "off");
566: break;
567: }
568:
569: case V_STRING:
570: {
571: char *str;
572:
573: /* Do_ask() so if you want you can set string to
574: "" if you so desire. */
575: str = do_ask("\r\n", (int (*)()) 0, (char *) vp->v_value, prompt);
576: if (str == 0)
577: str = NullStr;
578: strcpy((char *) vp->v_value, str);
579: /* ... and hope there is enough room. */
580: break;
581: }
582: case V_CHAR:
583: f_mess(prompt);
584: *(vp->v_value) = addgetc();
585: break;
586:
587: }
588: if (vp->v_flags & V_MODELINE)
589: UpdModLine++;
590: if (vp->v_flags & V_CLRSCREEN)
591: ClAndRedraw();
592: if (vp->v_flags & V_TTY_RESET)
593: tty_reset();
594: }
595:
596: /* Command completion - possible is an array of strings, prompt is
597: the prompt to use, and flags are ... well read jove.h.
598:
599: If flags are RET_STATE, and the user hits <return> what they typed
600: so far is in the Minibuf string. */
601:
602: private char **Possible;
603: private int comp_value,
604: comp_flags;
605:
606: aux_complete(c)
607: {
608: int command,
609: length,
610: i;
611:
612: switch (c) {
613: case EOF:
614: comp_value = -1;
615: return 0;
616:
617: case '\r':
618: case '\n':
619: command = match(Possible, linebuf);
620: if (command >= 0) {
621: comp_value = command;
622: return 0; /* tells ask to stop */
623: }
624: if (eolp() && bolp()) {
625: comp_value = NULLSTRING;
626: return 0;
627: }
628: if (comp_flags == RET_STATE) switch (command) {
629: case UNIQUE:
630: case ORIGINAL:
631: case NULLSTRING:
632: comp_value = command;
633: return 0;
634:
635: default:
636: break;
637: }
638: if (InJoverc)
639: complain("[\"%s\" unknown]", linebuf);
640: rbell();
641: break;
642:
643: case '\t':
644: case ' ':
645: {
646: int minmatch = 1000,
647: maxmatch = 0,
648: numfound = 0,
649: lastmatch = -1,
650: length = strlen(linebuf);
651:
652: for (i = 0; Possible[i] != 0; i++) {
653: int this_len;
654:
655: this_len = numcomp(Possible[i], linebuf);
656: maxmatch = max(maxmatch, this_len);
657: if (this_len >= length) {
658: if (numfound)
659: minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i]));
660: else
661: minmatch = strlen(Possible[i]);
662: numfound++;
663: lastmatch = i;
664: if (strcmp(linebuf, Possible[i]) == 0)
665: break;
666: }
667: }
668:
669: if (numfound == 0) {
670: rbell();
671: if (InJoverc)
672: complain("[\"%s\" unknown]", linebuf);
673: /* If we're not in the .joverc then
674: let's do something helpful for the
675: user. */
676: if (maxmatch < length) {
677: char *cp;
678:
679: cp = linebuf + maxmatch;
680: *cp = 0;
681: Eol();
682: }
683: break;
684: }
685: if (c != '\t' && numfound == 1) {
686: comp_value = lastmatch;
687: return 0;
688: }
689: null_ncpy(linebuf, Possible[lastmatch], minmatch);
690: Eol();
691: if (minmatch == length) /* No difference */
692: rbell();
693: break;
694: }
695:
696: case '?':
697: if (InJoverc)
698: complain((char *) 0);
699: /* kludge: in case we're using UseBuffers, in which case
700: linebuf gets written all over */
701: strcpy(Minibuf, linebuf);
702: length = strlen(Minibuf);
703: TOstart("Completion", TRUE); /* for now ... */
704: for (i = 0; Possible[i]; i++)
705: if (numcomp(Possible[i], Minibuf) >= length) {
706: Typeout(Possible[i]);
707: if (TOabort != 0)
708: break;
709: }
710:
711: TOstop();
712: break;
713: }
714: return !FALSE;
715: }
716:
717: complete(possible, prompt, flags)
718: register char *possible[];
719: char *prompt;
720: {
721: Possible = possible;
722: comp_flags = flags;
723: (void) do_ask("\r\n \t?", aux_complete, NullStr, prompt);
724: return comp_value;
725: }
726:
727: match(choices, what)
728: register char **choices,
729: *what;
730: {
731: register int len;
732: int i,
733: found = 0,
734: save,
735: exactmatch = -1;
736:
737: len = strlen(what);
738: if (len == 0)
739: return NULLSTRING;
740: for (i = 0; choices[i]; i++) {
741: if (strncmp(what, choices[i], len) == 0) {
742: if (strcmp(what, choices[i]) == 0)
743: exactmatch = i;
744: save = i;
745: found++; /* Found one. */
746: }
747: }
748:
749: if (found == 0)
750: save = ORIGINAL;
751: else if (found > 1) {
752: if (exactmatch != -1)
753: save = exactmatch;
754: else
755: save = AMBIGUOUS;
756: }
757:
758: return save;
759: }
760:
761: Source()
762: {
763: char *com,
764: buf[FILESIZE];
765:
766: sprintf(buf, "%s/.joverc", getenv("HOME"));
767: com = ask_file(buf, buf);
768: if (joverc(buf) == NIL)
769: complain(IOerr("read", com));
770: }
771:
772: BufPos()
773: {
774: register Line *lp = curbuf->b_first;
775: register int i,
776: dotline;
777:
778: for (i = 0; lp != 0; i++, lp = lp->l_next)
779: if (lp == curline)
780: dotline = i + 1;
781:
782: s_mess("\"%s\" line %d of %d --%d%%--, column %d of %d.",
783: filename(curbuf),
784: dotline,
785: i,
786: (int) (((long) dotline * 100) / i),
787: 1 + calc_pos(linebuf, curchar),
788: 1 + calc_pos(linebuf, strlen(linebuf)));
789: }
790:
791: #define IF_UNBOUND -1
792: #define IF_TRUE 1
793: #define IF_FALSE !IF_TRUE
794:
795: do_if(cmd)
796: char *cmd;
797: {
798: int pid,
799: status;
800:
801: switch (pid = fork()) {
802: case -1:
803: complain("[Fork failed: if]");
804:
805: case 0:
806: {
807: char *args[12],
808: *cp = cmd,
809: **ap = args;
810:
811: *ap++ = cmd;
812: for (;;) {
813: if ((cp = index(cp, ' ')) == 0)
814: break;
815: *cp++ = '\0';
816: *ap++ = cp;
817: }
818: *ap = 0;
819:
820: close(0); /* we want reads to fail */
821: /* close(1); but not writes or ioctl's
822: close(2); */
823:
824: (void) execvp(args[0], args);
825: _exit(-10); /* signals exec error (see below) */
826: }
827: }
828: #ifdef IPROCS
829: sighold(SIGCHLD);
830: #endif
831: dowait(pid, &status);
832: #ifdef IPROCS
833: sigrelse(SIGCHLD);
834: #endif
835: if (status == -10)
836: complain("[Exec failed]");
837: if (status < 0)
838: complain("[Exit %d]", status);
839: return (status == 0); /* 0 means successful */
840: }
841:
842: joverc(file)
843: char *file;
844: {
845: char buf[LBSIZE],
846: lbuf[128];
847: int lnum = 0,
848: eof = FALSE;
849: jmp_buf savejmp;
850: int IfStatus = IF_UNBOUND;
851: File *fp;
852:
853: fp = open_file(file, buf, F_READ, !COMPLAIN, QUIET);
854: if (fp == NIL)
855: return NIL;
856:
857: /* Catch any errors, here, and do the right thing with them,
858: and then restore the error handle to whoever did a setjmp
859: last. */
860:
861: push_env(savejmp);
862: if (setjmp(mainjmp)) {
863: Buffer *savebuf = curbuf;
864:
865: SetBuf(do_select((Window *) 0, "RC errors"));
866: ins_str(sprint("%s:%d:%s\t%s\n", pr_name(file), lnum, lbuf, mesgbuf), NO);
867: unmodify();
868: SetBuf(savebuf);
869: Asking = 0;
870: }
871: InJoverc = 1;
872: if (!eof) do {
873: eof = (f_gets(fp, lbuf, sizeof lbuf) == EOF);
874: lnum++;
875: if (casencmp(lbuf, "if", 2) == 0) {
876: char cmd[128];
877:
878: if (IfStatus != IF_UNBOUND)
879: complain("[Cannot have nested if's]");
880: if (LookingAt("if[ \t]*\\(.*\\)$", lbuf, 0) == 0)
881: complain("[If syntax error]");
882: putmatch(1, cmd, sizeof cmd);
883: IfStatus = do_if(cmd) ? IF_TRUE : IF_FALSE;
884: continue;
885: } else if (casencmp(lbuf, "else", 4) == 0) {
886: if (IfStatus == IF_UNBOUND)
887: complain("[Unexpected `else']");
888: IfStatus = !IfStatus;
889: continue;
890: } else if (casencmp(lbuf, "endif", 5) == 0) {
891: if (IfStatus == IF_UNBOUND)
892: complain("[Unexpected `endif']");
893: IfStatus = IF_UNBOUND;
894: continue;
895: }
896: if (IfStatus == IF_FALSE)
897: continue;
898: (void) strcat(lbuf, "\n");
899: Inputp = lbuf;
900: while (*Inputp == ' ' || *Inputp == '\t')
901: Inputp++; /* skip white space */
902: Extend();
903: } while (!eof);
904:
905: f_close(fp);
906: pop_env(savejmp);
907: Inputp = 0;
908: Asking = 0;
909: InJoverc = 0;
910: if (IfStatus != IF_UNBOUND)
911: complain("[Missing endif]");
912: return !NIL;
913: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.