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