|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley Software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)sh.lex.c 5.4 (Berkeley) 3/29/86";
9: #endif
10:
11: #include "sh.h"
12: #include <sgtty.h>
13:
14: /*
15: * C shell
16: */
17:
18: /*
19: * These lexical routines read input and form lists of words.
20: * There is some involved processing here, because of the complications
21: * of input buffering, and especially because of history substitution.
22: */
23:
24: char *word();
25:
26: /*
27: * Peekc is a peek characer for getC, peekread for readc.
28: * There is a subtlety here in many places... history routines
29: * will read ahead and then insert stuff into the input stream.
30: * If they push back a character then they must push it behind
31: * the text substituted by the history substitution. On the other
32: * hand in several places we need 2 peek characters. To make this
33: * all work, the history routines read with getC, and make use both
34: * of ungetC and unreadc. The key observation is that the state
35: * of getC at the call of a history reference is such that calls
36: * to getC from the history routines will always yield calls of
37: * readc, unless this peeking is involved. That is to say that during
38: * getexcl the variables lap, exclp, and exclnxt are all zero.
39: *
40: * Getdol invokes history substitution, hence the extra peek, peekd,
41: * which it can ungetD to be before history substitutions.
42: */
43: char peekc, peekd;
44: char peekread;
45:
46: char *exclp; /* (Tail of) current word from ! subst */
47: struct wordent *exclnxt; /* The rest of the ! subst words */
48: int exclc; /* Count of remainig words in ! subst */
49: char *alvecp; /* "Globp" for alias resubstitution */
50:
51: /*
52: * Lex returns to its caller not only a wordlist (as a "var" parameter)
53: * but also whether a history substitution occurred. This is used in
54: * the main (process) routine to determine whether to echo, and also
55: * when called by the alias routine to determine whether to keep the
56: * argument list.
57: */
58: bool hadhist;
59:
60: char getCtmp;
61: #define getC(f) ((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f))
62: #define ungetC(c) peekc = c
63: #define ungetD(c) peekd = c
64:
65: lex(hp)
66: register struct wordent *hp;
67: {
68: register struct wordent *wdp;
69: int c;
70:
71: lineloc = btell();
72: hp->next = hp->prev = hp;
73: hp->word = "";
74: alvecp = 0, hadhist = 0;
75: do
76: c = readc(0);
77: while (c == ' ' || c == '\t');
78: if (c == HISTSUB && intty)
79: /* ^lef^rit from tty is short !:s^lef^rit */
80: getexcl(c);
81: else
82: unreadc(c);
83: wdp = hp;
84: /*
85: * The following loop is written so that the links needed
86: * by freelex will be ready and rarin to go even if it is
87: * interrupted.
88: */
89: do {
90: register struct wordent *new = (struct wordent *) xalloc(sizeof *wdp);
91:
92: new->word = 0;
93: new->prev = wdp;
94: new->next = hp;
95: wdp->next = new;
96: wdp = new;
97: wdp->word = word();
98: } while (wdp->word[0] != '\n');
99: hp->prev = wdp;
100: return (hadhist);
101: }
102:
103: prlex(sp0)
104: struct wordent *sp0;
105: {
106: register struct wordent *sp = sp0->next;
107:
108: for (;;) {
109: printf("%s", sp->word);
110: sp = sp->next;
111: if (sp == sp0)
112: break;
113: if (sp->word[0] != '\n')
114: putchar(' ');
115: }
116: }
117:
118: copylex(hp, fp)
119: register struct wordent *hp;
120: register struct wordent *fp;
121: {
122: register struct wordent *wdp;
123:
124: wdp = hp;
125: fp = fp->next;
126: do {
127: register struct wordent *new = (struct wordent *) xalloc(sizeof *wdp);
128:
129: new->prev = wdp;
130: new->next = hp;
131: wdp->next = new;
132: wdp = new;
133: wdp->word = savestr(fp->word);
134: fp = fp->next;
135: } while (wdp->word[0] != '\n');
136: hp->prev = wdp;
137: }
138:
139: freelex(vp)
140: register struct wordent *vp;
141: {
142: register struct wordent *fp;
143:
144: while (vp->next != vp) {
145: fp = vp->next;
146: vp->next = fp->next;
147: XFREE(fp->word)
148: XFREE((char *)fp)
149: }
150: vp->prev = vp;
151: }
152:
153: char *
154: word()
155: {
156: register char c, c1;
157: register char *wp;
158: char wbuf[BUFSIZ];
159: register bool dolflg;
160: register int i;
161:
162: wp = wbuf;
163: i = BUFSIZ - 4;
164: loop:
165: while ((c = getC(DOALL)) == ' ' || c == '\t')
166: ;
167: if (cmap(c, _META|_ESC))
168: switch (c) {
169: case '&':
170: case '|':
171: case '<':
172: case '>':
173: *wp++ = c;
174: c1 = getC(DOALL);
175: if (c1 == c)
176: *wp++ = c1;
177: else
178: ungetC(c1);
179: goto ret;
180:
181: case '#':
182: if (intty)
183: break;
184: c = 0;
185: do {
186: c1 = c;
187: c = getC(0);
188: } while (c != '\n');
189: if (c1 == '\\')
190: goto loop;
191: /* fall into ... */
192:
193: case ';':
194: case '(':
195: case ')':
196: case '\n':
197: *wp++ = c;
198: goto ret;
199:
200: case '\\':
201: c = getC(0);
202: if (c == '\n') {
203: if (onelflg == 1)
204: onelflg = 2;
205: goto loop;
206: }
207: if (c != HIST)
208: *wp++ = '\\', --i;
209: c |= QUOTE;
210: }
211: c1 = 0;
212: dolflg = DOALL;
213: for (;;) {
214: if (c1) {
215: if (c == c1) {
216: c1 = 0;
217: dolflg = DOALL;
218: } else if (c == '\\') {
219: c = getC(0);
220: if (c == HIST)
221: c |= QUOTE;
222: else {
223: if (c == '\n')
224: /*
225: if (c1 == '`')
226: c = ' ';
227: else
228: */
229: c |= QUOTE;
230: ungetC(c);
231: c = '\\';
232: }
233: } else if (c == '\n') {
234: seterrc("Unmatched ", c1);
235: ungetC(c);
236: break;
237: }
238: } else if (cmap(c, _META|_Q|_Q1|_ESC)) {
239: if (c == '\\') {
240: c = getC(0);
241: if (c == '\n') {
242: if (onelflg == 1)
243: onelflg = 2;
244: break;
245: }
246: if (c != HIST)
247: *wp++ = '\\', --i;
248: c |= QUOTE;
249: } else if (cmap(c, _Q|_Q1)) { /* '"` */
250: c1 = c;
251: dolflg = c == '"' ? DOALL : DOEXCL;
252: } else if (c != '#' || !intty) {
253: ungetC(c);
254: break;
255: }
256: }
257: if (--i > 0) {
258: *wp++ = c;
259: c = getC(dolflg);
260: } else {
261: seterr("Word too long");
262: wp = &wbuf[1];
263: break;
264: }
265: }
266: ret:
267: *wp = 0;
268: return (savestr(wbuf));
269: }
270:
271: getC1(flag)
272: register int flag;
273: {
274: register char c;
275:
276: top:
277: if (c = peekc) {
278: peekc = 0;
279: return (c);
280: }
281: if (lap) {
282: if ((c = *lap++) == 0)
283: lap = 0;
284: else {
285: if (cmap(c, _META|_Q|_Q1))
286: c |= QUOTE;
287: return (c);
288: }
289: }
290: if (c = peekd) {
291: peekd = 0;
292: return (c);
293: }
294: if (exclp) {
295: if (c = *exclp++)
296: return (c);
297: if (exclnxt && --exclc >= 0) {
298: exclnxt = exclnxt->next;
299: setexclp(exclnxt->word);
300: return (' ');
301: }
302: exclp = 0;
303: exclnxt = 0;
304: }
305: if (exclnxt) {
306: exclnxt = exclnxt->next;
307: if (--exclc < 0)
308: exclnxt = 0;
309: else
310: setexclp(exclnxt->word);
311: goto top;
312: }
313: c = readc(0);
314: if (c == '$' && (flag & DODOL)) {
315: getdol();
316: goto top;
317: }
318: if (c == HIST && (flag & DOEXCL)) {
319: getexcl(0);
320: goto top;
321: }
322: return (c);
323: }
324:
325: getdol()
326: {
327: register char *np;
328: char name[40];
329: register int c;
330: int sc;
331: bool special = 0;
332:
333: np = name, *np++ = '$';
334: c = sc = getC(DOEXCL);
335: if (any(c, "\t \n")) {
336: ungetD(c);
337: ungetC('$' | QUOTE);
338: return;
339: }
340: if (c == '{')
341: *np++ = c, c = getC(DOEXCL);
342: if (c == '#' || c == '?')
343: special++, *np++ = c, c = getC(DOEXCL);
344: *np++ = c;
345: switch (c) {
346:
347: case '<':
348: case '$':
349: if (special)
350: goto vsyn;
351: goto ret;
352:
353: case '\n':
354: ungetD(c);
355: np--;
356: goto vsyn;
357:
358: case '*':
359: if (special)
360: goto vsyn;
361: goto ret;
362:
363: default:
364: if (digit(c)) {
365: /*
366: * let $?0 pass for now
367: if (special)
368: goto vsyn;
369: */
370: while (digit(c = getC(DOEXCL))) {
371: if (np < &name[sizeof name / 2])
372: *np++ = c;
373: }
374: } else if (letter(c))
375: while (letter(c = getC(DOEXCL))) {
376: if (np < &name[sizeof name / 2])
377: *np++ = c;
378: }
379: else
380: goto vsyn;
381: }
382: if (c == '[') {
383: *np++ = c;
384: do {
385: c = getC(DOEXCL);
386: if (c == '\n') {
387: ungetD(c);
388: np--;
389: goto vsyn;
390: }
391: if (np >= &name[sizeof name - 8])
392: goto vsyn;
393: *np++ = c;
394: } while (c != ']');
395: c = getC(DOEXCL);
396: }
397: if (c == ':') {
398: *np++ = c, c = getC(DOEXCL);
399: if (c == 'g')
400: *np++ = c, c = getC(DOEXCL);
401: *np++ = c;
402: if (!any(c, "htrqxe"))
403: goto vsyn;
404: } else
405: ungetD(c);
406: if (sc == '{') {
407: c = getC(DOEXCL);
408: if (c != '}') {
409: ungetC(c);
410: goto vsyn;
411: }
412: *np++ = c;
413: }
414: ret:
415: *np = 0;
416: addla(name);
417: return;
418:
419: vsyn:
420: seterr("Variable syntax");
421: goto ret;
422: }
423:
424: addla(cp)
425: char *cp;
426: {
427: char buf[BUFSIZ];
428:
429: if (lap != 0 && strlen(cp) + strlen(lap) >= sizeof (labuf) - 4) {
430: seterr("Expansion buf ovflo");
431: return;
432: }
433: if (lap)
434: (void) strcpy(buf, lap);
435: (void) strcpy(labuf, cp);
436: if (lap)
437: (void) strcat(labuf, buf);
438: lap = labuf;
439: }
440:
441: char lhsb[32];
442: char slhs[32];
443: char rhsb[64];
444: int quesarg;
445:
446: getexcl(sc)
447: char sc;
448: {
449: register struct wordent *hp, *ip;
450: int left, right, dol;
451: register int c;
452:
453: if (sc == 0) {
454: sc = getC(0);
455: if (sc != '{') {
456: ungetC(sc);
457: sc = 0;
458: }
459: }
460: quesarg = -1;
461: lastev = eventno;
462: hp = gethent(sc);
463: if (hp == 0)
464: return;
465: hadhist = 1;
466: dol = 0;
467: if (hp == alhistp)
468: for (ip = hp->next->next; ip != alhistt; ip = ip->next)
469: dol++;
470: else
471: for (ip = hp->next->next; ip != hp->prev; ip = ip->next)
472: dol++;
473: left = 0, right = dol;
474: if (sc == HISTSUB) {
475: ungetC('s'), unreadc(HISTSUB), c = ':';
476: goto subst;
477: }
478: c = getC(0);
479: if (!any(c, ":^$*-%"))
480: goto subst;
481: left = right = -1;
482: if (c == ':') {
483: c = getC(0);
484: unreadc(c);
485: if (letter(c) || c == '&') {
486: c = ':';
487: left = 0, right = dol;
488: goto subst;
489: }
490: } else
491: ungetC(c);
492: if (!getsel(&left, &right, dol))
493: return;
494: c = getC(0);
495: if (c == '*')
496: ungetC(c), c = '-';
497: if (c == '-') {
498: if (!getsel(&left, &right, dol))
499: return;
500: c = getC(0);
501: }
502: subst:
503: exclc = right - left + 1;
504: while (--left >= 0)
505: hp = hp->next;
506: if (sc == HISTSUB || c == ':') {
507: do {
508: hp = getsub(hp);
509: c = getC(0);
510: } while (c == ':');
511: }
512: unreadc(c);
513: if (sc == '{') {
514: c = getC(0);
515: if (c != '}')
516: seterr("Bad ! form");
517: }
518: exclnxt = hp;
519: }
520:
521: struct wordent *
522: getsub(en)
523: struct wordent *en;
524: {
525: register char *cp;
526: int delim;
527: register int c;
528: int sc;
529: bool global = 0;
530: char orhsb[sizeof rhsb];
531:
532: exclnxt = 0;
533: sc = c = getC(0);
534: if (c == 'g')
535: global++, c = getC(0);
536: switch (c) {
537:
538: case 'p':
539: justpr++;
540: goto ret;
541:
542: case 'x':
543: case 'q':
544: global++;
545: /* fall into ... */
546:
547: case 'h':
548: case 'r':
549: case 't':
550: case 'e':
551: break;
552:
553: case '&':
554: if (slhs[0] == 0) {
555: seterr("No prev sub");
556: goto ret;
557: }
558: (void) strcpy(lhsb, slhs);
559: break;
560:
561: /*
562: case '~':
563: if (lhsb[0] == 0)
564: goto badlhs;
565: break;
566: */
567:
568: case 's':
569: delim = getC(0);
570: if (letter(delim) || digit(delim) || any(delim, " \t\n")) {
571: unreadc(delim);
572: bads:
573: lhsb[0] = 0;
574: seterr("Bad substitute");
575: goto ret;
576: }
577: cp = lhsb;
578: for (;;) {
579: c = getC(0);
580: if (c == '\n') {
581: unreadc(c);
582: break;
583: }
584: if (c == delim)
585: break;
586: if (cp > &lhsb[sizeof lhsb - 2])
587: goto bads;
588: if (c == '\\') {
589: c = getC(0);
590: if (c != delim && c != '\\')
591: *cp++ = '\\';
592: }
593: *cp++ = c;
594: }
595: if (cp != lhsb)
596: *cp++ = 0;
597: else if (lhsb[0] == 0) {
598: /*badlhs:*/
599: seterr("No prev lhs");
600: goto ret;
601: }
602: cp = rhsb;
603: (void) strcpy(orhsb, cp);
604: for (;;) {
605: c = getC(0);
606: if (c == '\n') {
607: unreadc(c);
608: break;
609: }
610: if (c == delim)
611: break;
612: /*
613: if (c == '~') {
614: if (&cp[strlen(orhsb)] > &rhsb[sizeof rhsb - 2])
615: goto toorhs;
616: (void) strcpy(cp, orhsb);
617: cp = strend(cp);
618: continue;
619: }
620: */
621: if (cp > &rhsb[sizeof rhsb - 2]) {
622: /*toorhs:*/
623: seterr("Rhs too long");
624: goto ret;
625: }
626: if (c == '\\') {
627: c = getC(0);
628: if (c != delim /* && c != '~' */)
629: *cp++ = '\\';
630: }
631: *cp++ = c;
632: }
633: *cp++ = 0;
634: break;
635:
636: default:
637: if (c == '\n')
638: unreadc(c);
639: seterrc("Bad ! modifier: ", c);
640: goto ret;
641: }
642: (void) strcpy(slhs, lhsb);
643: if (exclc)
644: en = dosub(sc, en, global);
645: ret:
646: return (en);
647: }
648:
649: struct wordent *
650: dosub(sc, en, global)
651: int sc;
652: struct wordent *en;
653: bool global;
654: {
655: struct wordent lex;
656: bool didsub = 0;
657: struct wordent *hp = &lex;
658: register struct wordent *wdp;
659: register int i = exclc;
660:
661: wdp = hp;
662: while (--i >= 0) {
663: register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp);
664:
665: new->prev = wdp;
666: new->next = hp;
667: wdp->next = new;
668: wdp = new;
669: en = en->next;
670: wdp->word = global || didsub == 0 ?
671: subword(en->word, sc, &didsub) : savestr(en->word);
672: }
673: if (didsub == 0)
674: seterr("Modifier failed");
675: hp->prev = wdp;
676: return (&enthist(-1000, &lex, 0)->Hlex);
677: }
678:
679: char *
680: subword(cp, type, adid)
681: char *cp;
682: int type;
683: bool *adid;
684: {
685: char wbuf[BUFSIZ];
686: register char *wp, *mp, *np;
687: register int i;
688:
689: switch (type) {
690:
691: case 'r':
692: case 'e':
693: case 'h':
694: case 't':
695: case 'q':
696: case 'x':
697: wp = domod(cp, type);
698: if (wp == 0)
699: return (savestr(cp));
700: *adid = 1;
701: return (wp);
702:
703: default:
704: wp = wbuf;
705: i = BUFSIZ - 4;
706: for (mp = cp; *mp; mp++)
707: if (matchs(mp, lhsb)) {
708: for (np = cp; np < mp;)
709: *wp++ = *np++, --i;
710: for (np = rhsb; *np; np++) switch (*np) {
711:
712: case '\\':
713: if (np[1] == '&')
714: np++;
715: /* fall into ... */
716:
717: default:
718: if (--i < 0)
719: goto ovflo;
720: *wp++ = *np;
721: continue;
722:
723: case '&':
724: i -= strlen(lhsb);
725: if (i < 0)
726: goto ovflo;
727: *wp = 0;
728: (void) strcat(wp, lhsb);
729: wp = strend(wp);
730: continue;
731: }
732: mp += strlen(lhsb);
733: i -= strlen(mp);
734: if (i < 0) {
735: ovflo:
736: seterr("Subst buf ovflo");
737: return ("");
738: }
739: *wp = 0;
740: (void) strcat(wp, mp);
741: *adid = 1;
742: return (savestr(wbuf));
743: }
744: return (savestr(cp));
745: }
746: }
747:
748: char *
749: domod(cp, type)
750: char *cp;
751: int type;
752: {
753: register char *wp, *xp;
754: register int c;
755:
756: switch (type) {
757:
758: case 'x':
759: case 'q':
760: wp = savestr(cp);
761: for (xp = wp; c = *xp; xp++)
762: if ((c != ' ' && c != '\t') || type == 'q')
763: *xp |= QUOTE;
764: return (wp);
765:
766: case 'h':
767: case 't':
768: if (!any('/', cp))
769: return (type == 't' ? savestr(cp) : 0);
770: wp = strend(cp);
771: while (*--wp != '/')
772: continue;
773: if (type == 'h')
774: xp = savestr(cp), xp[wp - cp] = 0;
775: else
776: xp = savestr(wp + 1);
777: return (xp);
778:
779: case 'e':
780: case 'r':
781: wp = strend(cp);
782: for (wp--; wp >= cp && *wp != '/'; wp--)
783: if (*wp == '.') {
784: if (type == 'e')
785: xp = savestr(wp + 1);
786: else
787: xp = savestr(cp), xp[wp - cp] = 0;
788: return (xp);
789: }
790: return (savestr(type == 'e' ? "" : cp));
791: }
792: return (0);
793: }
794:
795: matchs(str, pat)
796: register char *str, *pat;
797: {
798:
799: while (*str && *pat && *str == *pat)
800: str++, pat++;
801: return (*pat == 0);
802: }
803:
804: getsel(al, ar, dol)
805: register int *al, *ar;
806: int dol;
807: {
808: register int c = getC(0);
809: register int i;
810: bool first = *al < 0;
811:
812: switch (c) {
813:
814: case '%':
815: if (quesarg == -1)
816: goto bad;
817: if (*al < 0)
818: *al = quesarg;
819: *ar = quesarg;
820: break;
821:
822: case '-':
823: if (*al < 0) {
824: *al = 0;
825: *ar = dol - 1;
826: unreadc(c);
827: }
828: return (1);
829:
830: case '^':
831: if (*al < 0)
832: *al = 1;
833: *ar = 1;
834: break;
835:
836: case '$':
837: if (*al < 0)
838: *al = dol;
839: *ar = dol;
840: break;
841:
842: case '*':
843: if (*al < 0)
844: *al = 1;
845: *ar = dol;
846: if (*ar < *al) {
847: *ar = 0;
848: *al = 1;
849: return (1);
850: }
851: break;
852:
853: default:
854: if (digit(c)) {
855: i = 0;
856: while (digit(c)) {
857: i = i * 10 + c - '0';
858: c = getC(0);
859: }
860: if (i < 0)
861: i = dol + 1;
862: if (*al < 0)
863: *al = i;
864: *ar = i;
865: } else
866: if (*al < 0)
867: *al = 0, *ar = dol;
868: else
869: *ar = dol - 1;
870: unreadc(c);
871: break;
872: }
873: if (first) {
874: c = getC(0);
875: unreadc(c);
876: if (any(c, "-$*"))
877: return (1);
878: }
879: if (*al > *ar || *ar > dol) {
880: bad:
881: seterr("Bad ! arg selector");
882: return (0);
883: }
884: return (1);
885:
886: }
887:
888: struct wordent *
889: gethent(sc)
890: int sc;
891: {
892: register struct Hist *hp;
893: register char *np;
894: register int c;
895: int event;
896: bool back = 0;
897:
898: c = sc == HISTSUB ? HIST : getC(0);
899: if (c == HIST) {
900: if (alhistp)
901: return (alhistp);
902: event = eventno;
903: goto skip;
904: }
905: switch (c) {
906:
907: case ':':
908: case '^':
909: case '$':
910: case '*':
911: case '%':
912: ungetC(c);
913: if (lastev == eventno && alhistp)
914: return (alhistp);
915: event = lastev;
916: break;
917:
918: case '-':
919: back = 1;
920: c = getC(0);
921: goto number;
922:
923: case '#': /* !# is command being typed in (mrh) */
924: return(¶ml);
925:
926: default:
927: if (any(c, "(=~")) {
928: unreadc(c);
929: ungetC(HIST);
930: return (0);
931: }
932: if (digit(c))
933: goto number;
934: np = lhsb;
935: while (!any(c, ": \t\\\n}")) {
936: if (np < &lhsb[sizeof lhsb - 2])
937: *np++ = c;
938: c = getC(0);
939: }
940: unreadc(c);
941: if (np == lhsb) {
942: ungetC(HIST);
943: return (0);
944: }
945: *np++ = 0;
946: hp = findev(lhsb, 0);
947: if (hp)
948: lastev = hp->Hnum;
949: return (&hp->Hlex);
950:
951: case '?':
952: np = lhsb;
953: for (;;) {
954: c = getC(0);
955: if (c == '\n') {
956: unreadc(c);
957: break;
958: }
959: if (c == '?')
960: break;
961: if (np < &lhsb[sizeof lhsb - 2])
962: *np++ = c;
963: }
964: if (np == lhsb) {
965: if (lhsb[0] == 0) {
966: seterr("No prev search");
967: return (0);
968: }
969: } else
970: *np++ = 0;
971: hp = findev(lhsb, 1);
972: if (hp)
973: lastev = hp->Hnum;
974: return (&hp->Hlex);
975:
976: number:
977: event = 0;
978: while (digit(c)) {
979: event = event * 10 + c - '0';
980: c = getC(0);
981: }
982: if (back)
983: event = eventno + (alhistp == 0) - (event ? event : 0);
984: unreadc(c);
985: break;
986: }
987: skip:
988: for (hp = Histlist.Hnext; hp; hp = hp->Hnext)
989: if (hp->Hnum == event) {
990: hp->Href = eventno;
991: lastev = hp->Hnum;
992: return (&hp->Hlex);
993: }
994: np = putn(event);
995: noev(np);
996: return (0);
997: }
998:
999: struct Hist *
1000: findev(cp, anyarg)
1001: char *cp;
1002: bool anyarg;
1003: {
1004: register struct Hist *hp;
1005:
1006: for (hp = Histlist.Hnext; hp; hp = hp->Hnext) {
1007: char *dp;
1008: register char *p, *q;
1009: register struct wordent *lp = hp->Hlex.next;
1010: int argno = 0;
1011:
1012: if (lp->word[0] == '\n')
1013: continue;
1014: if (!anyarg) {
1015: p = cp;
1016: q = lp->word;
1017: do
1018: if (!*p)
1019: return (hp);
1020: while (*p++ == *q++);
1021: continue;
1022: }
1023: do {
1024: for (dp = lp->word; *dp; dp++) {
1025: p = cp;
1026: q = dp;
1027: do
1028: if (!*p) {
1029: quesarg = argno;
1030: return (hp);
1031: }
1032: while (*p++ == *q++);
1033: }
1034: lp = lp->next;
1035: argno++;
1036: } while (lp->word[0] != '\n');
1037: }
1038: noev(cp);
1039: return (0);
1040: }
1041:
1042: noev(cp)
1043: char *cp;
1044: {
1045:
1046: seterr2(cp, ": Event not found");
1047: }
1048:
1049: setexclp(cp)
1050: register char *cp;
1051: {
1052:
1053: if (cp && cp[0] == '\n')
1054: return;
1055: exclp = cp;
1056: }
1057:
1058: unreadc(c)
1059: char c;
1060: {
1061:
1062: peekread = c;
1063: }
1064:
1065: readc(wanteof)
1066: bool wanteof;
1067: {
1068: register int c;
1069: static sincereal;
1070:
1071: if (c = peekread) {
1072: peekread = 0;
1073: return (c);
1074: }
1075: top:
1076: if (alvecp) {
1077: if (c = *alvecp++)
1078: return (c);
1079: if (*alvec) {
1080: alvecp = *alvec++;
1081: return (' ');
1082: }
1083: }
1084: if (alvec) {
1085: if (alvecp = *alvec) {
1086: alvec++;
1087: goto top;
1088: }
1089: /* Infinite source! */
1090: return ('\n');
1091: }
1092: if (evalp) {
1093: if (c = *evalp++)
1094: return (c);
1095: if (*evalvec) {
1096: evalp = *evalvec++;
1097: return (' ');
1098: }
1099: evalp = 0;
1100: }
1101: if (evalvec) {
1102: if (evalvec == (char **)1) {
1103: doneinp = 1;
1104: reset();
1105: }
1106: if (evalp = *evalvec) {
1107: evalvec++;
1108: goto top;
1109: }
1110: evalvec = (char **)1;
1111: return ('\n');
1112: }
1113: do {
1114: if (arginp == (char *) 1 || onelflg == 1) {
1115: if (wanteof)
1116: return (-1);
1117: exitstat();
1118: }
1119: if (arginp) {
1120: if ((c = *arginp++) == 0) {
1121: arginp = (char *) 1;
1122: return ('\n');
1123: }
1124: return (c);
1125: }
1126: reread:
1127: c = bgetc();
1128: if (c < 0) {
1129: struct sgttyb tty;
1130:
1131: if (wanteof)
1132: return (-1);
1133: /* was isatty but raw with ignoreeof yields problems */
1134: if (ioctl(SHIN, TIOCGETP, (char *)&tty) == 0 &&
1135: (tty.sg_flags & RAW) == 0) {
1136: /* was 'short' for FILEC */
1137: int ctpgrp;
1138:
1139: if (++sincereal > 25)
1140: goto oops;
1141: if (tpgrp != -1 &&
1142: ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp) == 0 &&
1143: tpgrp != ctpgrp) {
1144: (void) ioctl(FSHTTY, TIOCSPGRP,
1145: (char *)&tpgrp);
1146: (void) killpg(ctpgrp, SIGHUP);
1147: printf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp);
1148: goto reread;
1149: }
1150: if (adrof("ignoreeof")) {
1151: if (loginsh)
1152: printf("\nUse \"logout\" to logout.\n");
1153: else
1154: printf("\nUse \"exit\" to leave csh.\n");
1155: reset();
1156: }
1157: if (chkstop == 0)
1158: panystop(1);
1159: }
1160: oops:
1161: doneinp = 1;
1162: reset();
1163: }
1164: sincereal = 0;
1165: if (c == '\n' && onelflg)
1166: onelflg--;
1167: } while (c == 0);
1168: return (c);
1169: }
1170:
1171: bgetc()
1172: {
1173: register int buf, off, c;
1174: #ifdef FILEC
1175: char ttyline[BUFSIZ];
1176: register int numleft = 0, roomleft;
1177: #endif
1178:
1179: #ifdef TELL
1180: if (cantell) {
1181: if (fseekp < fbobp || fseekp > feobp) {
1182: fbobp = feobp = fseekp;
1183: (void) lseek(SHIN, fseekp, 0);
1184: }
1185: if (fseekp == feobp) {
1186: fbobp = feobp;
1187: do
1188: c = read(SHIN, fbuf[0], BUFSIZ);
1189: while (c < 0 && errno == EINTR);
1190: if (c <= 0)
1191: return (-1);
1192: feobp += c;
1193: }
1194: c = fbuf[0][fseekp - fbobp];
1195: fseekp++;
1196: return (c);
1197: }
1198: #endif
1199: again:
1200: buf = (int) fseekp / BUFSIZ;
1201: if (buf >= fblocks) {
1202: register char **nfbuf =
1203: (char **) calloc((unsigned) (fblocks + 2),
1204: sizeof (char **));
1205:
1206: if (fbuf) {
1207: (void) blkcpy(nfbuf, fbuf);
1208: xfree((char *)fbuf);
1209: }
1210: fbuf = nfbuf;
1211: fbuf[fblocks] = calloc(BUFSIZ, sizeof (char));
1212: fblocks++;
1213: goto again;
1214: }
1215: if (fseekp >= feobp) {
1216: buf = (int) feobp / BUFSIZ;
1217: off = (int) feobp % BUFSIZ;
1218: #ifndef FILEC
1219: for (;;) {
1220: c = read(SHIN, fbuf[buf] + off, BUFSIZ - off);
1221: #else
1222: roomleft = BUFSIZ - off;
1223: for (;;) {
1224: if (filec && intty) {
1225: c = numleft ? numleft : tenex(ttyline, BUFSIZ);
1226: if (c > roomleft) {
1227: /* start with fresh buffer */
1228: feobp = fseekp = fblocks * BUFSIZ;
1229: numleft = c;
1230: goto again;
1231: }
1232: if (c > 0)
1233: copy(fbuf[buf] + off, ttyline, c);
1234: numleft = 0;
1235: } else
1236: c = read(SHIN, fbuf[buf] + off, roomleft);
1237: #endif
1238: if (c >= 0)
1239: break;
1240: if (errno == EWOULDBLOCK) {
1241: int off = 0;
1242:
1243: (void) ioctl(SHIN, FIONBIO, (char *)&off);
1244: } else if (errno != EINTR)
1245: break;
1246: }
1247: if (c <= 0)
1248: return (-1);
1249: feobp += c;
1250: #ifndef FILEC
1251: goto again;
1252: #else
1253: if (filec && !intty)
1254: goto again;
1255: #endif
1256: }
1257: c = fbuf[buf][(int) fseekp % BUFSIZ];
1258: fseekp++;
1259: return (c);
1260: }
1261:
1262: bfree()
1263: {
1264: register int sb, i;
1265:
1266: #ifdef TELL
1267: if (cantell)
1268: return;
1269: #endif
1270: if (whyles)
1271: return;
1272: sb = (int) (fseekp - 1) / BUFSIZ;
1273: if (sb > 0) {
1274: for (i = 0; i < sb; i++)
1275: xfree(fbuf[i]);
1276: (void) blkcpy(fbuf, &fbuf[sb]);
1277: fseekp -= BUFSIZ * sb;
1278: feobp -= BUFSIZ * sb;
1279: fblocks -= sb;
1280: }
1281: }
1282:
1283: bseek(l)
1284: off_t l;
1285: {
1286: register struct whyle *wp;
1287:
1288: fseekp = l;
1289: #ifdef TELL
1290: if (!cantell) {
1291: #endif
1292: if (!whyles)
1293: return;
1294: for (wp = whyles; wp->w_next; wp = wp->w_next)
1295: continue;
1296: if (wp->w_start > l)
1297: l = wp->w_start;
1298: #ifdef TELL
1299: }
1300: #endif
1301: }
1302:
1303: /* any similarity to bell telephone is purely accidental */
1304: #ifndef btell
1305: off_t
1306: btell()
1307: {
1308:
1309: return (fseekp);
1310: }
1311: #endif
1312:
1313: btoeof()
1314: {
1315:
1316: (void) lseek(SHIN, (off_t)0, 2);
1317: fseekp = feobp;
1318: wfree();
1319: bfree();
1320: }
1321:
1322: #ifdef TELL
1323: settell()
1324: {
1325:
1326: cantell = 0;
1327: if (arginp || onelflg || intty)
1328: return;
1329: if (lseek(SHIN, (off_t)0, 1) < 0 || errno == ESPIPE)
1330: return;
1331: fbuf = (char **) calloc(2, sizeof (char **));
1332: fblocks = 1;
1333: fbuf[0] = calloc(BUFSIZ, sizeof (char));
1334: fseekp = fbobp = feobp = lseek(SHIN, (off_t)0, 1);
1335: cantell = 1;
1336: }
1337: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.