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