include fixes
[unix-history] / usr / src / bin / csh / lex.c
CommitLineData
cc519405 1static char *sccsid = "@(#)lex.c 4.2 %G%";
3802e2ef
BJ
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
15char *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 */
34char peekc, peekd;
35char peekread;
36
37char *exclp; /* (Tail of) current word from ! subst */
38struct wordent *exclnxt; /* The rest of the ! subst words */
39int exclc; /* Count of remainig words in ! subst */
40char *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 */
49bool hadhist;
50
51#define ungetC(c) peekc = c
52#define ungetD(c) peekd = c
53
54lex(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
91prlex(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
105copylex(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
126freelex(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
140char *WORDMETA = "# '`\"\t;&<>()|\n";
141
142char *
143word()
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;
153loop:
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
227casebksl:
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);
241pack:
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 }
265toochars:
266 seterr("Word too long");
267 wp = &wbuf[1];
268ret:
269 *wp = 0;
270 return (savestr(wbuf));
271}
272
273getC(flag)
274 register int flag;
275{
276 register char c;
277
278top:
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
328getdol()
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 }
417ret:
418 *np = 0;
419 addla(name);
420 return;
421
422vsyn:
423 seterr("Variable syntax");
424 goto ret;
425}
426
427addla(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
444char lhsb[32];
445char slhs[32];
446char rhsb[64];
447int quesarg;
448
449getexcl(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 }
505subst:
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
524struct wordent *
525getsub(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);
575bads:
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);
648ret:
649 return (en);
650}
651
652struct wordent *
653dosub(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
682char *
683subword(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) {
737ovflo:
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
750char *
751domod(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')
776take:
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
798matchs(str, pat)
799 register char *str, *pat;
800{
801
802 while (*str && *pat && *str == *pat)
803 str++, pat++;
804 return (*pat == 0);
805}
806
807getsel(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) {
883bad:
884 seterr("Bad ! arg selector");
885 return (0);
886 }
887 return (1);
888
889}
890
891struct wordent *
892gethent(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(&paraml);
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 }
990skip:
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
1002struct Hist *
1003findev(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
1016noev(cp)
1017 char *cp;
1018{
1019
1020 seterr2(cp, ": Event not found");
1021}
1022
1023matchev(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
1049setexclp(cp)
1050 register char *cp;
1051{
1052
1053 if (cp[0] == '\n')
1054 return;
1055 exclp = cp;
1056}
1057
1058unreadc(c)
1059 char c;
1060{
1061
1062 peekread = c;
1063}
1064
1065readc(wanteof)
1066 bool wanteof;
1067{
1068 register int c;
1069 static sincereal;
1070
1071 if (c = peekread) {
1072 peekread = 0;
1073 return (c);
1074 }
1075top:
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 }
1126reread:
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) {
cc519405 1136 int ctpgrp;
3802e2ef
BJ
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);
1145printf("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 }
1158oops:
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
1169bgetc()
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
1193again:
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
1223bfree()
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
1244bseek(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 */
1265long
1266btell()
1267{
1268
1269 return (fseekp);
1270}
1271
1272btoeof()
1273{
1274
1275 lseek(SHIN, 0l, 2);
1276 fseekp = feobp;
1277 wfree();
1278 bfree();
1279}
1280
1281#ifdef TELL
1282settell()
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