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