1 | /* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/sh.lex.c,v 1.1.1.2 1998-10-03 21:10:04 danw Exp $ */ |
---|
2 | /* |
---|
3 | * sh.lex.c: Lexical analysis into tokens |
---|
4 | */ |
---|
5 | /*- |
---|
6 | * Copyright (c) 1980, 1991 The Regents of the University of California. |
---|
7 | * All rights reserved. |
---|
8 | * |
---|
9 | * Redistribution and use in source and binary forms, with or without |
---|
10 | * modification, are permitted provided that the following conditions |
---|
11 | * are met: |
---|
12 | * 1. Redistributions of source code must retain the above copyright |
---|
13 | * notice, this list of conditions and the following disclaimer. |
---|
14 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
15 | * notice, this list of conditions and the following disclaimer in the |
---|
16 | * documentation and/or other materials provided with the distribution. |
---|
17 | * 3. All advertising materials mentioning features or use of this software |
---|
18 | * must display the following acknowledgement: |
---|
19 | * This product includes software developed by the University of |
---|
20 | * California, Berkeley and its contributors. |
---|
21 | * 4. Neither the name of the University nor the names of its contributors |
---|
22 | * may be used to endorse or promote products derived from this software |
---|
23 | * without specific prior written permission. |
---|
24 | * |
---|
25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
---|
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
---|
29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
---|
31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
---|
33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
---|
34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
---|
35 | * SUCH DAMAGE. |
---|
36 | */ |
---|
37 | #include "sh.h" |
---|
38 | |
---|
39 | RCSID("$Id: sh.lex.c,v 1.1.1.2 1998-10-03 21:10:04 danw Exp $") |
---|
40 | |
---|
41 | #include "ed.h" |
---|
42 | /* #define DEBUG_INP */ |
---|
43 | /* #define DEBUG_SEEK */ |
---|
44 | |
---|
45 | /* |
---|
46 | * C shell |
---|
47 | */ |
---|
48 | |
---|
49 | /* |
---|
50 | * These lexical routines read input and form lists of words. |
---|
51 | * There is some involved processing here, because of the complications |
---|
52 | * of input buffering, and especially because of history substitution. |
---|
53 | */ |
---|
54 | static Char *word __P((void)); |
---|
55 | static int getC1 __P((int)); |
---|
56 | static void getdol __P((void)); |
---|
57 | static void getexcl __P((int)); |
---|
58 | static struct Hist *findev __P((Char *, bool)); |
---|
59 | static void setexclp __P((Char *)); |
---|
60 | static int bgetc __P((void)); |
---|
61 | static void balloc __P((int)); |
---|
62 | static void bfree __P((void)); |
---|
63 | static struct wordent *gethent __P((int)); |
---|
64 | static int matchs __P((Char *, Char *)); |
---|
65 | static int getsel __P((int *, int *, int)); |
---|
66 | static struct wordent *getsub __P((struct wordent *)); |
---|
67 | static Char *subword __P((Char *, int, bool *)); |
---|
68 | static struct wordent *dosub __P((int, struct wordent *, bool)); |
---|
69 | |
---|
70 | /* |
---|
71 | * Peekc is a peek character for getC, peekread for readc. |
---|
72 | * There is a subtlety here in many places... history routines |
---|
73 | * will read ahead and then insert stuff into the input stream. |
---|
74 | * If they push back a character then they must push it behind |
---|
75 | * the text substituted by the history substitution. On the other |
---|
76 | * hand in several places we need 2 peek characters. To make this |
---|
77 | * all work, the history routines read with getC, and make use both |
---|
78 | * of ungetC and unreadc. The key observation is that the state |
---|
79 | * of getC at the call of a history reference is such that calls |
---|
80 | * to getC from the history routines will always yield calls of |
---|
81 | * readc, unless this peeking is involved. That is to say that during |
---|
82 | * getexcl the variables lap, exclp, and exclnxt are all zero. |
---|
83 | * |
---|
84 | * Getdol invokes history substitution, hence the extra peek, peekd, |
---|
85 | * which it can ungetD to be before history substitutions. |
---|
86 | */ |
---|
87 | static Char peekc = 0, peekd = 0; |
---|
88 | static Char peekread = 0; |
---|
89 | |
---|
90 | /* (Tail of) current word from ! subst */ |
---|
91 | static Char *exclp = NULL; |
---|
92 | |
---|
93 | /* The rest of the ! subst words */ |
---|
94 | static struct wordent *exclnxt = NULL; |
---|
95 | |
---|
96 | /* Count of remaining words in ! subst */ |
---|
97 | static int exclc = 0; |
---|
98 | |
---|
99 | /* "Globp" for alias resubstitution */ |
---|
100 | int aret = F_SEEK; |
---|
101 | |
---|
102 | /* |
---|
103 | * Labuf implements a general buffer for lookahead during lexical operations. |
---|
104 | * Text which is to be placed in the input stream can be stuck here. |
---|
105 | * We stick parsed ahead $ constructs during initial input, |
---|
106 | * process id's from `$$', and modified variable values (from qualifiers |
---|
107 | * during expansion in sh.dol.c) here. |
---|
108 | */ |
---|
109 | static Char labuf[BUFSIZE]; |
---|
110 | |
---|
111 | /* |
---|
112 | * Lex returns to its caller not only a wordlist (as a "var" parameter) |
---|
113 | * but also whether a history substitution occurred. This is used in |
---|
114 | * the main (process) routine to determine whether to echo, and also |
---|
115 | * when called by the alias routine to determine whether to keep the |
---|
116 | * argument list. |
---|
117 | */ |
---|
118 | static bool hadhist = 0; |
---|
119 | |
---|
120 | /* |
---|
121 | * Avoid alias expansion recursion via \!# |
---|
122 | */ |
---|
123 | int hleft; |
---|
124 | |
---|
125 | Char histline[BUFSIZE + 2]; /* last line input */ |
---|
126 | |
---|
127 | /* The +2 is to fool hp's optimizer */ |
---|
128 | bool histvalid = 0; /* is histline valid */ |
---|
129 | static Char *histlinep = NULL; /* current pointer into histline */ |
---|
130 | |
---|
131 | static Char getCtmp; |
---|
132 | |
---|
133 | #define getC(f) (((getCtmp = peekc) != '\0') ? (peekc = 0, getCtmp) : getC1(f)) |
---|
134 | #define ungetC(c) peekc = (Char) c |
---|
135 | #define ungetD(c) peekd = (Char) c |
---|
136 | |
---|
137 | /* Use Htime to store timestamps picked up from history file for enthist() |
---|
138 | * if reading saved history (sg) |
---|
139 | */ |
---|
140 | time_t Htime = (time_t)0; |
---|
141 | static time_t a2time_t __P((Char *)); |
---|
142 | |
---|
143 | /* |
---|
144 | * for history event processing |
---|
145 | * in the command 'echo !?foo?:1 !$' we want the !$ to expand from the line |
---|
146 | * 'foo' was found instead of the last command |
---|
147 | */ |
---|
148 | static int uselastevent = 1; |
---|
149 | |
---|
150 | int |
---|
151 | lex(hp) |
---|
152 | struct wordent *hp; |
---|
153 | { |
---|
154 | struct wordent *wdp; |
---|
155 | int c; |
---|
156 | |
---|
157 | |
---|
158 | uselastevent = 1; |
---|
159 | histvalid = 0; |
---|
160 | histlinep = histline; |
---|
161 | *histlinep = '\0'; |
---|
162 | |
---|
163 | btell(&lineloc); |
---|
164 | hp->next = hp->prev = hp; |
---|
165 | hp->word = STRNULL; |
---|
166 | hadhist = 0; |
---|
167 | do |
---|
168 | c = readc(0); |
---|
169 | while (c == ' ' || c == '\t'); |
---|
170 | if (c == HISTSUB && intty) |
---|
171 | /* ^lef^rit from tty is short !:s^lef^rit */ |
---|
172 | getexcl(c); |
---|
173 | else |
---|
174 | unreadc(c); |
---|
175 | wdp = hp; |
---|
176 | /* |
---|
177 | * The following loop is written so that the links needed by freelex will |
---|
178 | * be ready and rarin to go even if it is interrupted. |
---|
179 | */ |
---|
180 | do { |
---|
181 | struct wordent *new; |
---|
182 | |
---|
183 | new = (struct wordent *) xmalloc((size_t) sizeof(*wdp)); |
---|
184 | new->word = STRNULL; |
---|
185 | new->prev = wdp; |
---|
186 | new->next = hp; |
---|
187 | wdp->next = new; |
---|
188 | hp->prev = new; |
---|
189 | wdp = new; |
---|
190 | wdp->word = word(); |
---|
191 | } while (wdp->word[0] != '\n'); |
---|
192 | if (histlinep < histline + BUFSIZE) { |
---|
193 | *histlinep = '\0'; |
---|
194 | if (histlinep > histline && histlinep[-1] == '\n') |
---|
195 | histlinep[-1] = '\0'; |
---|
196 | histvalid = 1; |
---|
197 | } |
---|
198 | else { |
---|
199 | histline[BUFSIZE - 1] = '\0'; |
---|
200 | } |
---|
201 | |
---|
202 | return (hadhist); |
---|
203 | } |
---|
204 | |
---|
205 | static time_t |
---|
206 | a2time_t(word) |
---|
207 | Char *word; |
---|
208 | { |
---|
209 | /* Attempt to distinguish timestamps from other possible entries. |
---|
210 | * Format: "+NNNNNNNNNN" (10 digits, left padded with ascii '0') */ |
---|
211 | |
---|
212 | time_t ret; |
---|
213 | Char *s; |
---|
214 | int ct; |
---|
215 | |
---|
216 | if (!word || *(s = word) != '+') |
---|
217 | return (time_t)0; |
---|
218 | |
---|
219 | for (++s, ret = 0, ct = 0; *s; ++s, ++ct) |
---|
220 | { |
---|
221 | if (!isdigit((unsigned char)*s)) |
---|
222 | return (time_t)0; |
---|
223 | ret = ret * 10 + (time_t)((unsigned char)*s - '0'); |
---|
224 | } |
---|
225 | |
---|
226 | if (ct != 10) |
---|
227 | return (time_t)0; |
---|
228 | |
---|
229 | return ret; |
---|
230 | } |
---|
231 | |
---|
232 | void |
---|
233 | prlex(sp0) |
---|
234 | struct wordent *sp0; |
---|
235 | { |
---|
236 | struct wordent *sp = sp0->next; |
---|
237 | |
---|
238 | for (;;) { |
---|
239 | xprintf("%S", sp->word); |
---|
240 | sp = sp->next; |
---|
241 | if (sp == sp0) |
---|
242 | break; |
---|
243 | if (sp->word[0] != '\n') |
---|
244 | xputchar(' '); |
---|
245 | } |
---|
246 | } |
---|
247 | |
---|
248 | void |
---|
249 | copylex(hp, fp) |
---|
250 | struct wordent *hp; |
---|
251 | struct wordent *fp; |
---|
252 | { |
---|
253 | struct wordent *wdp; |
---|
254 | |
---|
255 | wdp = hp; |
---|
256 | fp = fp->next; |
---|
257 | do { |
---|
258 | struct wordent *new; |
---|
259 | |
---|
260 | new = (struct wordent *) xmalloc((size_t) sizeof(*wdp)); |
---|
261 | new->word = STRNULL; |
---|
262 | new->prev = wdp; |
---|
263 | new->next = hp; |
---|
264 | wdp->next = new; |
---|
265 | hp->prev = new; |
---|
266 | wdp = new; |
---|
267 | wdp->word = Strsave(fp->word); |
---|
268 | fp = fp->next; |
---|
269 | } while (wdp->word[0] != '\n'); |
---|
270 | } |
---|
271 | |
---|
272 | void |
---|
273 | freelex(vp) |
---|
274 | struct wordent *vp; |
---|
275 | { |
---|
276 | struct wordent *fp; |
---|
277 | |
---|
278 | while (vp->next != vp) { |
---|
279 | fp = vp->next; |
---|
280 | vp->next = fp->next; |
---|
281 | if (fp->word != STRNULL) |
---|
282 | xfree((ptr_t) fp->word); |
---|
283 | xfree((ptr_t) fp); |
---|
284 | } |
---|
285 | vp->prev = vp; |
---|
286 | } |
---|
287 | |
---|
288 | static Char * |
---|
289 | word() |
---|
290 | { |
---|
291 | Char c, c1; |
---|
292 | Char *wp; |
---|
293 | Char wbuf[BUFSIZE]; |
---|
294 | Char hbuf[12]; |
---|
295 | int h; |
---|
296 | bool dolflg; |
---|
297 | int i; |
---|
298 | |
---|
299 | wp = wbuf; |
---|
300 | i = BUFSIZE - 4; |
---|
301 | loop: |
---|
302 | while ((c = getC(DOALL)) == ' ' || c == '\t') |
---|
303 | continue; |
---|
304 | if (cmap(c, _META | _ESC)) |
---|
305 | switch (c) { |
---|
306 | case '&': |
---|
307 | case '|': |
---|
308 | case '<': |
---|
309 | case '>': |
---|
310 | *wp++ = c; |
---|
311 | c1 = getC(DOALL); |
---|
312 | if (c1 == c) |
---|
313 | *wp++ = c1; |
---|
314 | else |
---|
315 | ungetC(c1); |
---|
316 | goto ret; |
---|
317 | |
---|
318 | case '#': |
---|
319 | if (intty) |
---|
320 | break; |
---|
321 | c = 0; |
---|
322 | h = 0; |
---|
323 | do { |
---|
324 | c1 = c; |
---|
325 | c = getC(0); |
---|
326 | if (h < 12) |
---|
327 | hbuf[h++] = c; |
---|
328 | } while (c != '\n'); |
---|
329 | hbuf[11] = '\0'; |
---|
330 | Htime = a2time_t(hbuf); |
---|
331 | if (c1 == '\\') |
---|
332 | goto loop; |
---|
333 | /*FALLTHROUGH*/ |
---|
334 | |
---|
335 | case ';': |
---|
336 | case '(': |
---|
337 | case ')': |
---|
338 | case '\n': |
---|
339 | *wp++ = c; |
---|
340 | goto ret; |
---|
341 | |
---|
342 | case '\\': |
---|
343 | c = getC(0); |
---|
344 | if (c == '\n') { |
---|
345 | if (onelflg == 1) |
---|
346 | onelflg = 2; |
---|
347 | goto loop; |
---|
348 | } |
---|
349 | if (c != HIST) |
---|
350 | *wp++ = '\\', --i; |
---|
351 | c |= QUOTE; |
---|
352 | default: |
---|
353 | break; |
---|
354 | } |
---|
355 | c1 = 0; |
---|
356 | dolflg = DOALL; |
---|
357 | for (;;) { |
---|
358 | if (c1) { |
---|
359 | if (c == c1) { |
---|
360 | c1 = 0; |
---|
361 | dolflg = DOALL; |
---|
362 | } |
---|
363 | else if (c == '\\') { |
---|
364 | c = getC(0); |
---|
365 | /* |
---|
366 | * PWP: this is dumb, but how all of the other shells work. If \ quotes |
---|
367 | * a character OUTSIDE of a set of ''s, why shouldn't it quote EVERY |
---|
368 | * following character INSIDE a set of ''s. |
---|
369 | * |
---|
370 | * Actually, all I really want to be able to say is 'foo\'bar' --> foo'bar |
---|
371 | */ |
---|
372 | if (c == HIST) |
---|
373 | c |= QUOTE; |
---|
374 | else { |
---|
375 | if (bslash_quote && |
---|
376 | ((c == '\'') || (c == '"') || |
---|
377 | (c == '\\'))) { |
---|
378 | c |= QUOTE; |
---|
379 | } |
---|
380 | else { |
---|
381 | if (c == '\n') |
---|
382 | /* |
---|
383 | * if (c1 == '`') c = ' '; else |
---|
384 | */ |
---|
385 | c |= QUOTE; |
---|
386 | ungetC(c); |
---|
387 | c = '\\'; |
---|
388 | } |
---|
389 | } |
---|
390 | } |
---|
391 | else if (c == '\n') { |
---|
392 | seterror(ERR_UNMATCHED, c1); |
---|
393 | ungetC(c); |
---|
394 | break; |
---|
395 | } |
---|
396 | } |
---|
397 | else if (cmap(c, _META | _QF | _QB | _ESC)) { |
---|
398 | if (c == '\\') { |
---|
399 | c = getC(0); |
---|
400 | if (c == '\n') { |
---|
401 | if (onelflg == 1) |
---|
402 | onelflg = 2; |
---|
403 | break; |
---|
404 | } |
---|
405 | if (c != HIST) |
---|
406 | *wp++ = '\\', --i; |
---|
407 | c |= QUOTE; |
---|
408 | } |
---|
409 | else if (cmap(c, _QF | _QB)) { /* '"` */ |
---|
410 | c1 = c; |
---|
411 | dolflg = c == '"' ? DOALL : DOEXCL; |
---|
412 | } |
---|
413 | else if (c != '#' || !intty) { |
---|
414 | ungetC(c); |
---|
415 | break; |
---|
416 | } |
---|
417 | } |
---|
418 | if (--i > 0) { |
---|
419 | *wp++ = c; |
---|
420 | c = getC(dolflg); |
---|
421 | } |
---|
422 | else { |
---|
423 | seterror(ERR_WTOOLONG); |
---|
424 | wp = &wbuf[1]; |
---|
425 | break; |
---|
426 | } |
---|
427 | } |
---|
428 | ret: |
---|
429 | *wp = 0; |
---|
430 | return (Strsave(wbuf)); |
---|
431 | } |
---|
432 | |
---|
433 | static int |
---|
434 | getC1(flag) |
---|
435 | int flag; |
---|
436 | { |
---|
437 | Char c; |
---|
438 | |
---|
439 | for (;;) { |
---|
440 | if ((c = peekc) != 0) { |
---|
441 | peekc = 0; |
---|
442 | return (c); |
---|
443 | } |
---|
444 | if (lap) { |
---|
445 | if ((c = *lap++) == 0) |
---|
446 | lap = 0; |
---|
447 | else { |
---|
448 | if (cmap(c, _META | _QF | _QB)) |
---|
449 | c |= QUOTE; |
---|
450 | return (c); |
---|
451 | } |
---|
452 | } |
---|
453 | if ((c = peekd) != 0) { |
---|
454 | peekd = 0; |
---|
455 | return (c); |
---|
456 | } |
---|
457 | if (exclp) { |
---|
458 | if ((c = *exclp++) != 0) |
---|
459 | return (c); |
---|
460 | if (exclnxt && --exclc >= 0) { |
---|
461 | exclnxt = exclnxt->next; |
---|
462 | setexclp(exclnxt->word); |
---|
463 | return (' '); |
---|
464 | } |
---|
465 | exclp = 0; |
---|
466 | exclnxt = 0; |
---|
467 | /* this will throw away the dummy history entries */ |
---|
468 | savehist(NULL, 0); |
---|
469 | |
---|
470 | } |
---|
471 | if (exclnxt) { |
---|
472 | exclnxt = exclnxt->next; |
---|
473 | if (--exclc < 0) |
---|
474 | exclnxt = 0; |
---|
475 | else |
---|
476 | setexclp(exclnxt->word); |
---|
477 | continue; |
---|
478 | } |
---|
479 | c = readc(0); |
---|
480 | if (c == '$' && (flag & DODOL)) { |
---|
481 | getdol(); |
---|
482 | continue; |
---|
483 | } |
---|
484 | if (c == HIST && (flag & DOEXCL)) { |
---|
485 | getexcl(0); |
---|
486 | continue; |
---|
487 | } |
---|
488 | break; |
---|
489 | } |
---|
490 | return (c); |
---|
491 | } |
---|
492 | |
---|
493 | static void |
---|
494 | getdol() |
---|
495 | { |
---|
496 | Char *np, *ep; |
---|
497 | Char name[4 * MAXVARLEN + 1]; |
---|
498 | int c; |
---|
499 | int sc; |
---|
500 | bool special = 0, toolong; |
---|
501 | |
---|
502 | np = name, *np++ = '$'; |
---|
503 | c = sc = getC(DOEXCL); |
---|
504 | if (any("\t \n", c)) { |
---|
505 | ungetD(c); |
---|
506 | ungetC('$' | QUOTE); |
---|
507 | return; |
---|
508 | } |
---|
509 | if (c == '{') |
---|
510 | *np++ = (Char) c, c = getC(DOEXCL); |
---|
511 | if (c == '#' || c == '?' || c == '%') |
---|
512 | special++, *np++ = (Char) c, c = getC(DOEXCL); |
---|
513 | *np++ = (Char) c; |
---|
514 | switch (c) { |
---|
515 | |
---|
516 | case '<': |
---|
517 | case '$': |
---|
518 | case '!': |
---|
519 | if (special) |
---|
520 | seterror(ERR_SPDOLLT); |
---|
521 | *np = 0; |
---|
522 | addla(name); |
---|
523 | return; |
---|
524 | |
---|
525 | case '\n': |
---|
526 | ungetD(c); |
---|
527 | np--; |
---|
528 | if (!special) |
---|
529 | seterror(ERR_NEWLINE); |
---|
530 | *np = 0; |
---|
531 | addla(name); |
---|
532 | return; |
---|
533 | |
---|
534 | case '*': |
---|
535 | if (special) |
---|
536 | seterror(ERR_SPSTAR); |
---|
537 | *np = 0; |
---|
538 | addla(name); |
---|
539 | return; |
---|
540 | |
---|
541 | default: |
---|
542 | toolong = 0; |
---|
543 | if (Isdigit(c)) { |
---|
544 | #ifdef notdef |
---|
545 | /* let $?0 pass for now */ |
---|
546 | if (special) { |
---|
547 | seterror(ERR_DIGIT); |
---|
548 | *np = 0; |
---|
549 | addla(name); |
---|
550 | return; |
---|
551 | } |
---|
552 | #endif |
---|
553 | /* we know that np < &name[4] */ |
---|
554 | ep = &np[MAXVARLEN]; |
---|
555 | while ((c = getC(DOEXCL)) != 0) { |
---|
556 | if (!Isdigit(c)) |
---|
557 | break; |
---|
558 | if (np < ep) |
---|
559 | *np++ = (Char) c; |
---|
560 | else |
---|
561 | toolong = 1; |
---|
562 | } |
---|
563 | } |
---|
564 | else if (letter(c)) { |
---|
565 | /* we know that np < &name[4] */ |
---|
566 | ep = &np[MAXVARLEN]; |
---|
567 | toolong = 0; |
---|
568 | while ((c = getC(DOEXCL)) != 0) { |
---|
569 | /* Bugfix for ${v123x} from Chris Torek, DAS DEC-90. */ |
---|
570 | if (!letter(c) && !Isdigit(c)) |
---|
571 | break; |
---|
572 | if (np < ep) |
---|
573 | *np++ = (Char) c; |
---|
574 | else |
---|
575 | toolong = 1; |
---|
576 | } |
---|
577 | } |
---|
578 | else { |
---|
579 | if (!special) |
---|
580 | seterror(ERR_VARILL); |
---|
581 | else { |
---|
582 | ungetD(c); |
---|
583 | --np; |
---|
584 | } |
---|
585 | *np = 0; |
---|
586 | addla(name); |
---|
587 | return; |
---|
588 | } |
---|
589 | if (toolong) { |
---|
590 | seterror(ERR_VARTOOLONG); |
---|
591 | *np = 0; |
---|
592 | addla(name); |
---|
593 | return; |
---|
594 | } |
---|
595 | break; |
---|
596 | } |
---|
597 | if (c == '[') { |
---|
598 | *np++ = (Char) c; |
---|
599 | /* |
---|
600 | * Name up to here is a max of MAXVARLEN + 8. |
---|
601 | */ |
---|
602 | ep = &np[2 * MAXVARLEN + 8]; |
---|
603 | do { |
---|
604 | /* |
---|
605 | * Michael Greim: Allow $ expansion to take place in selector |
---|
606 | * expressions. (limits the number of characters returned) |
---|
607 | */ |
---|
608 | c = getC(DOEXCL | DODOL); |
---|
609 | if (c == '\n') { |
---|
610 | ungetD(c); |
---|
611 | np--; |
---|
612 | seterror(ERR_NLINDEX); |
---|
613 | *np = 0; |
---|
614 | addla(name); |
---|
615 | return; |
---|
616 | } |
---|
617 | if (np < ep) |
---|
618 | *np++ = (Char) c; |
---|
619 | } while (c != ']'); |
---|
620 | *np = '\0'; |
---|
621 | if (np >= ep) { |
---|
622 | seterror(ERR_SELOVFL); |
---|
623 | addla(name); |
---|
624 | return; |
---|
625 | } |
---|
626 | c = getC(DOEXCL); |
---|
627 | } |
---|
628 | /* |
---|
629 | * Name up to here is a max of 2 * MAXVARLEN + 8. |
---|
630 | */ |
---|
631 | if (c == ':') { |
---|
632 | /* |
---|
633 | * if the :g modifier is followed by a newline, then error right away! |
---|
634 | * -strike |
---|
635 | */ |
---|
636 | |
---|
637 | int gmodflag = 0, amodflag = 0; |
---|
638 | |
---|
639 | #ifndef COMPAT |
---|
640 | do { |
---|
641 | #endif /* COMPAT */ |
---|
642 | *np++ = (Char) c, c = getC(DOEXCL); |
---|
643 | if (c == 'g' || c == 'a') { |
---|
644 | if (c == 'g') |
---|
645 | gmodflag++; |
---|
646 | else |
---|
647 | amodflag++; |
---|
648 | *np++ = (Char) c; c = getC(DOEXCL); |
---|
649 | } |
---|
650 | if ((c == 'g' && !gmodflag) || (c == 'a' && !amodflag)) { |
---|
651 | if (c == 'g') |
---|
652 | gmodflag++; |
---|
653 | else |
---|
654 | amodflag++; |
---|
655 | *np++ = (Char) c; c = getC(DOEXCL); |
---|
656 | } |
---|
657 | *np++ = (Char) c; |
---|
658 | /* scan s// [eichin:19910926.0512EST] */ |
---|
659 | if (c == 's') { |
---|
660 | int delimcnt = 2; |
---|
661 | int delim = getC(0); |
---|
662 | *np++ = (Char) delim; |
---|
663 | |
---|
664 | if (!delim || letter(delim) |
---|
665 | || Isdigit(delim) || any(" \t\n", delim)) { |
---|
666 | seterror(ERR_BADSUBST); |
---|
667 | break; |
---|
668 | } |
---|
669 | while ((c = getC(0)) != (-1)) { |
---|
670 | *np++ = (Char) c; |
---|
671 | if(c == delim) delimcnt--; |
---|
672 | if(!delimcnt) break; |
---|
673 | } |
---|
674 | if(delimcnt) { |
---|
675 | seterror(ERR_BADSUBST); |
---|
676 | break; |
---|
677 | } |
---|
678 | c = 's'; |
---|
679 | } |
---|
680 | if (!any("htrqxesul", c)) { |
---|
681 | if ((amodflag || gmodflag) && c == '\n') |
---|
682 | stderror(ERR_VARSYN); /* strike */ |
---|
683 | seterror(ERR_BADMOD, c); |
---|
684 | *np = 0; |
---|
685 | addla(name); |
---|
686 | return; |
---|
687 | } |
---|
688 | #ifndef COMPAT |
---|
689 | } |
---|
690 | while ((c = getC(DOEXCL)) == ':'); |
---|
691 | ungetD(c); |
---|
692 | #endif /* COMPAT */ |
---|
693 | } |
---|
694 | else |
---|
695 | ungetD(c); |
---|
696 | if (sc == '{') { |
---|
697 | c = getC(DOEXCL); |
---|
698 | if (c != '}') { |
---|
699 | ungetD(c); |
---|
700 | seterror(ERR_MISSING, '}'); |
---|
701 | *np = 0; |
---|
702 | addla(name); |
---|
703 | return; |
---|
704 | } |
---|
705 | *np++ = (Char) c; |
---|
706 | } |
---|
707 | *np = 0; |
---|
708 | addla(name); |
---|
709 | return; |
---|
710 | } |
---|
711 | |
---|
712 | void |
---|
713 | addla(cp) |
---|
714 | Char *cp; |
---|
715 | { |
---|
716 | Char buf[BUFSIZE]; |
---|
717 | |
---|
718 | if (Strlen(cp) + (lap ? Strlen(lap) : 0) >= |
---|
719 | (sizeof(labuf) - 4) / sizeof(Char)) { |
---|
720 | seterror(ERR_EXPOVFL); |
---|
721 | return; |
---|
722 | } |
---|
723 | if (lap) |
---|
724 | (void) Strcpy(buf, lap); |
---|
725 | (void) Strcpy(labuf, cp); |
---|
726 | if (lap) |
---|
727 | (void) Strcat(labuf, buf); |
---|
728 | lap = labuf; |
---|
729 | } |
---|
730 | |
---|
731 | static Char lhsb[32]; |
---|
732 | static Char slhs[32]; |
---|
733 | static Char rhsb[64]; |
---|
734 | static int quesarg; |
---|
735 | |
---|
736 | static void |
---|
737 | getexcl(sc) |
---|
738 | int sc; |
---|
739 | { |
---|
740 | struct wordent *hp, *ip; |
---|
741 | int left, right, dol; |
---|
742 | int c; |
---|
743 | |
---|
744 | if (sc == 0) { |
---|
745 | sc = getC(0); |
---|
746 | if (sc != '{') { |
---|
747 | ungetC(sc); |
---|
748 | sc = 0; |
---|
749 | } |
---|
750 | } |
---|
751 | quesarg = -1; |
---|
752 | |
---|
753 | if (uselastevent) { |
---|
754 | uselastevent = 0; |
---|
755 | lastev = eventno; |
---|
756 | } |
---|
757 | else |
---|
758 | lastev = eventno; |
---|
759 | hp = gethent(sc); |
---|
760 | if (hp == 0) |
---|
761 | return; |
---|
762 | hadhist = 1; |
---|
763 | dol = 0; |
---|
764 | if (hp == alhistp) |
---|
765 | for (ip = hp->next->next; ip != alhistt; ip = ip->next) |
---|
766 | dol++; |
---|
767 | else |
---|
768 | for (ip = hp->next->next; ip != hp->prev; ip = ip->next) |
---|
769 | dol++; |
---|
770 | left = 0, right = dol; |
---|
771 | if (sc == HISTSUB) { |
---|
772 | ungetC('s'), unreadc(HISTSUB), c = ':'; |
---|
773 | goto subst; |
---|
774 | } |
---|
775 | c = getC(0); |
---|
776 | if (!any(":^$*-%", c)) |
---|
777 | goto subst; |
---|
778 | left = right = -1; |
---|
779 | if (c == ':') { |
---|
780 | c = getC(0); |
---|
781 | unreadc(c); |
---|
782 | if (letter(c) || c == '&') { |
---|
783 | c = ':'; |
---|
784 | left = 0, right = dol; |
---|
785 | goto subst; |
---|
786 | } |
---|
787 | } |
---|
788 | else |
---|
789 | ungetC(c); |
---|
790 | if (!getsel(&left, &right, dol)) |
---|
791 | return; |
---|
792 | c = getC(0); |
---|
793 | if (c == '*') |
---|
794 | ungetC(c), c = '-'; |
---|
795 | if (c == '-') { |
---|
796 | if (!getsel(&left, &right, dol)) |
---|
797 | return; |
---|
798 | c = getC(0); |
---|
799 | } |
---|
800 | subst: |
---|
801 | exclc = right - left + 1; |
---|
802 | while (--left >= 0) |
---|
803 | hp = hp->next; |
---|
804 | if (sc == HISTSUB || c == ':') { |
---|
805 | do { |
---|
806 | hp = getsub(hp); |
---|
807 | c = getC(0); |
---|
808 | } while (c == ':'); |
---|
809 | } |
---|
810 | unreadc(c); |
---|
811 | if (sc == '{') { |
---|
812 | c = getC(0); |
---|
813 | if (c != '}') |
---|
814 | seterror(ERR_BADBANG); |
---|
815 | } |
---|
816 | exclnxt = hp; |
---|
817 | } |
---|
818 | |
---|
819 | static struct wordent * |
---|
820 | getsub(en) |
---|
821 | struct wordent *en; |
---|
822 | { |
---|
823 | Char *cp; |
---|
824 | int delim; |
---|
825 | int c; |
---|
826 | int sc; |
---|
827 | bool global; |
---|
828 | Char orhsb[sizeof(rhsb) / sizeof(Char)]; |
---|
829 | |
---|
830 | #ifndef COMPAT |
---|
831 | do { |
---|
832 | #endif /* COMPAT */ |
---|
833 | exclnxt = 0; |
---|
834 | global = 0; |
---|
835 | sc = c = getC(0); |
---|
836 | if (c == 'g' || c == 'a') { |
---|
837 | global |= (c == 'g') ? 1 : 2; |
---|
838 | sc = c = getC(0); |
---|
839 | } |
---|
840 | if (((c =='g') && !(global & 1)) || ((c == 'a') && !(global & 2))) { |
---|
841 | global |= (c == 'g') ? 1 : 2; |
---|
842 | sc = c = getC(0); |
---|
843 | } |
---|
844 | |
---|
845 | switch (c) { |
---|
846 | case 'p': |
---|
847 | justpr++; |
---|
848 | return (en); |
---|
849 | |
---|
850 | case 'x': |
---|
851 | case 'q': |
---|
852 | global |= 1; |
---|
853 | /*FALLTHROUGH*/ |
---|
854 | |
---|
855 | case 'h': |
---|
856 | case 'r': |
---|
857 | case 't': |
---|
858 | case 'e': |
---|
859 | case 'u': |
---|
860 | case 'l': |
---|
861 | break; |
---|
862 | |
---|
863 | case '&': |
---|
864 | if (slhs[0] == 0) { |
---|
865 | seterror(ERR_NOSUBST); |
---|
866 | return (en); |
---|
867 | } |
---|
868 | (void) Strcpy(lhsb, slhs); |
---|
869 | break; |
---|
870 | |
---|
871 | #ifdef notdef |
---|
872 | case '~': |
---|
873 | if (lhsb[0] == 0) |
---|
874 | goto badlhs; |
---|
875 | break; |
---|
876 | #endif |
---|
877 | |
---|
878 | case 's': |
---|
879 | delim = getC(0); |
---|
880 | if (letter(delim) || Isdigit(delim) || any(" \t\n", delim)) { |
---|
881 | unreadc(delim); |
---|
882 | lhsb[0] = 0; |
---|
883 | seterror(ERR_BADSUBST); |
---|
884 | return (en); |
---|
885 | } |
---|
886 | cp = lhsb; |
---|
887 | for (;;) { |
---|
888 | c = getC(0); |
---|
889 | if (c == '\n') { |
---|
890 | unreadc(c); |
---|
891 | break; |
---|
892 | } |
---|
893 | if (c == delim) |
---|
894 | break; |
---|
895 | if (cp > &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) { |
---|
896 | lhsb[0] = 0; |
---|
897 | seterror(ERR_BADSUBST); |
---|
898 | return (en); |
---|
899 | } |
---|
900 | if (c == '\\') { |
---|
901 | c = getC(0); |
---|
902 | if (c != delim && c != '\\') |
---|
903 | *cp++ = '\\'; |
---|
904 | } |
---|
905 | *cp++ = (Char) c; |
---|
906 | } |
---|
907 | if (cp != lhsb) |
---|
908 | *cp++ = 0; |
---|
909 | else if (lhsb[0] == 0) { |
---|
910 | seterror(ERR_LHS); |
---|
911 | return (en); |
---|
912 | } |
---|
913 | cp = rhsb; |
---|
914 | (void) Strcpy(orhsb, cp); |
---|
915 | for (;;) { |
---|
916 | c = getC(0); |
---|
917 | if (c == '\n') { |
---|
918 | unreadc(c); |
---|
919 | break; |
---|
920 | } |
---|
921 | if (c == delim) |
---|
922 | break; |
---|
923 | #ifdef notdef |
---|
924 | if (c == '~') { |
---|
925 | if (&cp[Strlen(orhsb)] > &rhsb[sizeof(rhsb) / |
---|
926 | sizeof(Char) - 2]) |
---|
927 | goto toorhs; |
---|
928 | (void) Strcpy(cp, orhsb); |
---|
929 | cp = Strend(cp); |
---|
930 | continue; |
---|
931 | } |
---|
932 | #endif |
---|
933 | if (cp > &rhsb[sizeof(rhsb) / sizeof(Char) - 2]) { |
---|
934 | seterror(ERR_RHSLONG); |
---|
935 | return (en); |
---|
936 | } |
---|
937 | if (c == '\\') { |
---|
938 | c = getC(0); |
---|
939 | if (c != delim /* && c != '~' */ ) |
---|
940 | *cp++ = '\\'; |
---|
941 | } |
---|
942 | *cp++ = (Char) c; |
---|
943 | } |
---|
944 | *cp++ = 0; |
---|
945 | break; |
---|
946 | |
---|
947 | default: |
---|
948 | if (c == '\n') |
---|
949 | unreadc(c); |
---|
950 | seterror(ERR_BADBANGMOD, c); |
---|
951 | return (en); |
---|
952 | } |
---|
953 | (void) Strcpy(slhs, lhsb); |
---|
954 | if (exclc) |
---|
955 | en = dosub(sc, en, global); |
---|
956 | #ifndef COMPAT |
---|
957 | } |
---|
958 | while ((c = getC(0)) == ':'); |
---|
959 | unreadc(c); |
---|
960 | #endif /* COMPAT */ |
---|
961 | return (en); |
---|
962 | } |
---|
963 | |
---|
964 | /* |
---|
965 | * |
---|
966 | * From Beto Appleton (beto@aixwiz.austin.ibm.com) |
---|
967 | * |
---|
968 | * when using history substitution, and the variable |
---|
969 | * 'history' is set to a value higher than 1000, |
---|
970 | * the shell might either freeze (hang) or core-dump. |
---|
971 | * We raise the limit to 50000000 |
---|
972 | */ |
---|
973 | |
---|
974 | #define HIST_PURGE -50000000 |
---|
975 | static struct wordent * |
---|
976 | dosub(sc, en, global) |
---|
977 | int sc; |
---|
978 | struct wordent *en; |
---|
979 | bool global; |
---|
980 | { |
---|
981 | struct wordent lexi; |
---|
982 | bool didsub = 0, didone = 0; |
---|
983 | struct wordent *hp = &lexi; |
---|
984 | struct wordent *wdp; |
---|
985 | int i = exclc; |
---|
986 | struct Hist *hst; |
---|
987 | |
---|
988 | wdp = hp; |
---|
989 | while (--i >= 0) { |
---|
990 | struct wordent *new = |
---|
991 | (struct wordent *) xcalloc(1, sizeof *wdp); |
---|
992 | |
---|
993 | new->word = 0; |
---|
994 | new->prev = wdp; |
---|
995 | new->next = hp; |
---|
996 | wdp->next = new; |
---|
997 | wdp = new; |
---|
998 | en = en->next; |
---|
999 | if (en->word) { |
---|
1000 | Char *tword, *otword; |
---|
1001 | |
---|
1002 | if ((global & 1) || didsub == 0) { |
---|
1003 | tword = subword(en->word, sc, &didone); |
---|
1004 | if (didone) |
---|
1005 | didsub = 1; |
---|
1006 | if (global & 2) { |
---|
1007 | while (didone && tword != STRNULL) { |
---|
1008 | otword = tword; |
---|
1009 | tword = subword(otword, sc, &didone); |
---|
1010 | if (Strcmp(tword, otword) == 0) { |
---|
1011 | xfree((ptr_t) otword); |
---|
1012 | break; |
---|
1013 | } |
---|
1014 | else |
---|
1015 | xfree((ptr_t) otword); |
---|
1016 | } |
---|
1017 | } |
---|
1018 | } |
---|
1019 | else |
---|
1020 | tword = Strsave(en->word); |
---|
1021 | wdp->word = tword; |
---|
1022 | } |
---|
1023 | } |
---|
1024 | if (didsub == 0) |
---|
1025 | seterror(ERR_MODFAIL); |
---|
1026 | hp->prev = wdp; |
---|
1027 | /* |
---|
1028 | * ANSI mode HP/UX compiler chokes on |
---|
1029 | * return &enthist(HIST_PURGE, &lexi, 0)->Hlex; |
---|
1030 | */ |
---|
1031 | hst = enthist(HIST_PURGE, &lexi, 0, 0); |
---|
1032 | return &(hst->Hlex); |
---|
1033 | } |
---|
1034 | |
---|
1035 | static Char * |
---|
1036 | subword(cp, type, adid) |
---|
1037 | Char *cp; |
---|
1038 | int type; |
---|
1039 | bool *adid; |
---|
1040 | { |
---|
1041 | Char wbuf[BUFSIZE]; |
---|
1042 | Char *wp, *mp, *np; |
---|
1043 | int i; |
---|
1044 | |
---|
1045 | *adid = 0; |
---|
1046 | switch (type) { |
---|
1047 | |
---|
1048 | case 'r': |
---|
1049 | case 'e': |
---|
1050 | case 'h': |
---|
1051 | case 't': |
---|
1052 | case 'q': |
---|
1053 | case 'x': |
---|
1054 | case 'u': |
---|
1055 | case 'l': |
---|
1056 | wp = domod(cp, type); |
---|
1057 | if (wp == 0) |
---|
1058 | return (Strsave(cp)); |
---|
1059 | *adid = 1; |
---|
1060 | return (wp); |
---|
1061 | |
---|
1062 | default: |
---|
1063 | wp = wbuf; |
---|
1064 | i = BUFSIZE - 4; |
---|
1065 | for (mp = cp; *mp; mp++) |
---|
1066 | if (matchs(mp, lhsb)) { |
---|
1067 | for (np = cp; np < mp;) |
---|
1068 | *wp++ = *np++, --i; |
---|
1069 | for (np = rhsb; *np; np++) |
---|
1070 | switch (*np) { |
---|
1071 | |
---|
1072 | case '\\': |
---|
1073 | if (np[1] == '&') |
---|
1074 | np++; |
---|
1075 | /* fall into ... */ |
---|
1076 | |
---|
1077 | default: |
---|
1078 | if (--i < 0) { |
---|
1079 | seterror(ERR_SUBOVFL); |
---|
1080 | return (STRNULL); |
---|
1081 | } |
---|
1082 | *wp++ = *np; |
---|
1083 | continue; |
---|
1084 | |
---|
1085 | case '&': |
---|
1086 | i -= Strlen(lhsb); |
---|
1087 | if (i < 0) { |
---|
1088 | seterror(ERR_SUBOVFL); |
---|
1089 | return (STRNULL); |
---|
1090 | } |
---|
1091 | *wp = 0; |
---|
1092 | (void) Strcat(wp, lhsb); |
---|
1093 | wp = Strend(wp); |
---|
1094 | continue; |
---|
1095 | } |
---|
1096 | mp += Strlen(lhsb); |
---|
1097 | i -= Strlen(mp); |
---|
1098 | if (i < 0) { |
---|
1099 | seterror(ERR_SUBOVFL); |
---|
1100 | return (STRNULL); |
---|
1101 | } |
---|
1102 | *wp = 0; |
---|
1103 | (void) Strcat(wp, mp); |
---|
1104 | *adid = 1; |
---|
1105 | return (Strsave(wbuf)); |
---|
1106 | } |
---|
1107 | return (Strsave(cp)); |
---|
1108 | } |
---|
1109 | } |
---|
1110 | |
---|
1111 | Char * |
---|
1112 | domod(cp, type) |
---|
1113 | Char *cp; |
---|
1114 | int type; |
---|
1115 | { |
---|
1116 | Char *wp, *xp; |
---|
1117 | int c; |
---|
1118 | |
---|
1119 | switch (type) { |
---|
1120 | |
---|
1121 | case 'x': |
---|
1122 | case 'q': |
---|
1123 | wp = Strsave(cp); |
---|
1124 | for (xp = wp; (c = *xp) != 0; xp++) |
---|
1125 | if ((c != ' ' && c != '\t') || type == 'q') |
---|
1126 | *xp |= QUOTE; |
---|
1127 | return (wp); |
---|
1128 | |
---|
1129 | case 'l': |
---|
1130 | wp = Strsave(cp); |
---|
1131 | for (cp = wp; *cp; cp++) |
---|
1132 | if (Isupper(*cp)) { |
---|
1133 | *cp = Tolower(*cp); |
---|
1134 | return wp; |
---|
1135 | } |
---|
1136 | return wp; |
---|
1137 | |
---|
1138 | case 'u': |
---|
1139 | wp = Strsave(cp); |
---|
1140 | for (cp = wp; *cp; cp++) |
---|
1141 | if (Islower(*cp)) { |
---|
1142 | *cp = Toupper(*cp); |
---|
1143 | return wp; |
---|
1144 | } |
---|
1145 | return wp; |
---|
1146 | |
---|
1147 | case 'h': |
---|
1148 | case 't': |
---|
1149 | if (!any(short2str(cp), '/')) |
---|
1150 | return (type == 't' ? Strsave(cp) : 0); |
---|
1151 | wp = Strend(cp); |
---|
1152 | while (*--wp != '/') |
---|
1153 | continue; |
---|
1154 | if (type == 'h') |
---|
1155 | xp = Strsave(cp), xp[wp - cp] = 0; |
---|
1156 | else |
---|
1157 | xp = Strsave(wp + 1); |
---|
1158 | return (xp); |
---|
1159 | |
---|
1160 | case 'e': |
---|
1161 | case 'r': |
---|
1162 | wp = Strend(cp); |
---|
1163 | for (wp--; wp >= cp && *wp != '/'; wp--) |
---|
1164 | if (*wp == '.') { |
---|
1165 | if (type == 'e') |
---|
1166 | xp = Strsave(wp + 1); |
---|
1167 | else |
---|
1168 | xp = Strsave(cp), xp[wp - cp] = 0; |
---|
1169 | return (xp); |
---|
1170 | } |
---|
1171 | return (Strsave(type == 'e' ? STRNULL : cp)); |
---|
1172 | default: |
---|
1173 | break; |
---|
1174 | } |
---|
1175 | return (0); |
---|
1176 | } |
---|
1177 | |
---|
1178 | static int |
---|
1179 | matchs(str, pat) |
---|
1180 | Char *str, *pat; |
---|
1181 | { |
---|
1182 | while (*str && *pat && *str == *pat) |
---|
1183 | str++, pat++; |
---|
1184 | return (*pat == 0); |
---|
1185 | } |
---|
1186 | |
---|
1187 | static int |
---|
1188 | getsel(al, ar, dol) |
---|
1189 | int *al, *ar; |
---|
1190 | int dol; |
---|
1191 | { |
---|
1192 | int c = getC(0); |
---|
1193 | int i; |
---|
1194 | bool first = *al < 0; |
---|
1195 | |
---|
1196 | switch (c) { |
---|
1197 | |
---|
1198 | case '%': |
---|
1199 | if (quesarg == -1) { |
---|
1200 | seterror(ERR_BADBANGARG); |
---|
1201 | return (0); |
---|
1202 | } |
---|
1203 | if (*al < 0) |
---|
1204 | *al = quesarg; |
---|
1205 | *ar = quesarg; |
---|
1206 | break; |
---|
1207 | |
---|
1208 | case '-': |
---|
1209 | if (*al < 0) { |
---|
1210 | *al = 0; |
---|
1211 | *ar = dol - 1; |
---|
1212 | unreadc(c); |
---|
1213 | } |
---|
1214 | return (1); |
---|
1215 | |
---|
1216 | case '^': |
---|
1217 | if (*al < 0) |
---|
1218 | *al = 1; |
---|
1219 | *ar = 1; |
---|
1220 | break; |
---|
1221 | |
---|
1222 | case '$': |
---|
1223 | if (*al < 0) |
---|
1224 | *al = dol; |
---|
1225 | *ar = dol; |
---|
1226 | break; |
---|
1227 | |
---|
1228 | case '*': |
---|
1229 | if (*al < 0) |
---|
1230 | *al = 1; |
---|
1231 | *ar = dol; |
---|
1232 | if (*ar < *al) { |
---|
1233 | *ar = 0; |
---|
1234 | *al = 1; |
---|
1235 | return (1); |
---|
1236 | } |
---|
1237 | break; |
---|
1238 | |
---|
1239 | default: |
---|
1240 | if (Isdigit(c)) { |
---|
1241 | i = 0; |
---|
1242 | while (Isdigit(c)) { |
---|
1243 | i = i * 10 + c - '0'; |
---|
1244 | c = getC(0); |
---|
1245 | } |
---|
1246 | if (i < 0) |
---|
1247 | i = dol + 1; |
---|
1248 | if (*al < 0) |
---|
1249 | *al = i; |
---|
1250 | *ar = i; |
---|
1251 | } |
---|
1252 | else if (*al < 0) |
---|
1253 | *al = 0, *ar = dol; |
---|
1254 | else |
---|
1255 | *ar = dol - 1; |
---|
1256 | unreadc(c); |
---|
1257 | break; |
---|
1258 | } |
---|
1259 | if (first) { |
---|
1260 | c = getC(0); |
---|
1261 | unreadc(c); |
---|
1262 | if (any("-$*", c)) |
---|
1263 | return (1); |
---|
1264 | } |
---|
1265 | if (*al > *ar || *ar > dol) { |
---|
1266 | seterror(ERR_BADBANGARG); |
---|
1267 | return (0); |
---|
1268 | } |
---|
1269 | return (1); |
---|
1270 | |
---|
1271 | } |
---|
1272 | |
---|
1273 | static struct wordent * |
---|
1274 | gethent(sc) |
---|
1275 | int sc; |
---|
1276 | { |
---|
1277 | struct Hist *hp; |
---|
1278 | Char *np; |
---|
1279 | int c; |
---|
1280 | int event; |
---|
1281 | bool back = 0; |
---|
1282 | |
---|
1283 | c = sc == HISTSUB ? HIST : getC(0); |
---|
1284 | if (c == HIST) { |
---|
1285 | if (alhistp) |
---|
1286 | return (alhistp); |
---|
1287 | event = eventno; |
---|
1288 | } |
---|
1289 | else |
---|
1290 | switch (c) { |
---|
1291 | |
---|
1292 | case ':': |
---|
1293 | case '^': |
---|
1294 | case '$': |
---|
1295 | case '*': |
---|
1296 | case '%': |
---|
1297 | ungetC(c); |
---|
1298 | if (lastev == eventno && alhistp) |
---|
1299 | return (alhistp); |
---|
1300 | event = lastev; |
---|
1301 | break; |
---|
1302 | |
---|
1303 | case '#': /* !# is command being typed in (mrh) */ |
---|
1304 | if (--hleft == 0) { |
---|
1305 | seterror(ERR_HISTLOOP); |
---|
1306 | return (0); |
---|
1307 | } |
---|
1308 | else |
---|
1309 | return (¶ml); |
---|
1310 | /* NOTREACHED */ |
---|
1311 | |
---|
1312 | case '-': |
---|
1313 | back = 1; |
---|
1314 | c = getC(0); |
---|
1315 | /* FALLSTHROUGH */ |
---|
1316 | |
---|
1317 | default: |
---|
1318 | if (any("(=~", c)) { |
---|
1319 | unreadc(c); |
---|
1320 | ungetC(HIST); |
---|
1321 | return (0); |
---|
1322 | } |
---|
1323 | np = lhsb; |
---|
1324 | event = 0; |
---|
1325 | while (!cmap(c, _ESC | _META | _QF | _QB) && !any("^*-%${}:#", c)) { |
---|
1326 | if (event != -1 && Isdigit(c)) |
---|
1327 | event = event * 10 + c - '0'; |
---|
1328 | else |
---|
1329 | event = -1; |
---|
1330 | if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) |
---|
1331 | *np++ = (Char) c; |
---|
1332 | c = getC(0); |
---|
1333 | } |
---|
1334 | unreadc(c); |
---|
1335 | if (np == lhsb) { |
---|
1336 | ungetC(HIST); |
---|
1337 | return (0); |
---|
1338 | } |
---|
1339 | *np++ = 0; |
---|
1340 | if (event != -1) { |
---|
1341 | /* |
---|
1342 | * History had only digits |
---|
1343 | */ |
---|
1344 | if (back) |
---|
1345 | event = eventno + (alhistp == 0) - (event ? event : 0); |
---|
1346 | break; |
---|
1347 | } |
---|
1348 | if (back) { |
---|
1349 | event = sizeof(lhsb) / sizeof(lhsb[0]); |
---|
1350 | np = &lhsb[--event]; |
---|
1351 | *np-- = '\0'; |
---|
1352 | for (event--; np > lhsb; *np-- = lhsb[--event]) |
---|
1353 | continue; |
---|
1354 | *np = '-'; |
---|
1355 | } |
---|
1356 | hp = findev(lhsb, 0); |
---|
1357 | if (hp) |
---|
1358 | lastev = hp->Hnum; |
---|
1359 | return (&hp->Hlex); |
---|
1360 | |
---|
1361 | case '?': |
---|
1362 | np = lhsb; |
---|
1363 | for (;;) { |
---|
1364 | c = getC(0); |
---|
1365 | if (c == '\n') { |
---|
1366 | unreadc(c); |
---|
1367 | break; |
---|
1368 | } |
---|
1369 | if (c == '?') |
---|
1370 | break; |
---|
1371 | if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) |
---|
1372 | *np++ = (Char) c; |
---|
1373 | } |
---|
1374 | if (np == lhsb) { |
---|
1375 | if (lhsb[0] == 0) { |
---|
1376 | seterror(ERR_NOSEARCH); |
---|
1377 | return (0); |
---|
1378 | } |
---|
1379 | } |
---|
1380 | else |
---|
1381 | *np++ = 0; |
---|
1382 | hp = findev(lhsb, 1); |
---|
1383 | if (hp) |
---|
1384 | lastev = hp->Hnum; |
---|
1385 | return (&hp->Hlex); |
---|
1386 | } |
---|
1387 | |
---|
1388 | for (hp = Histlist.Hnext; hp; hp = hp->Hnext) |
---|
1389 | if (hp->Hnum == event) { |
---|
1390 | hp->Href = eventno; |
---|
1391 | lastev = hp->Hnum; |
---|
1392 | return (&hp->Hlex); |
---|
1393 | } |
---|
1394 | np = putn(event); |
---|
1395 | seterror(ERR_NOEVENT, short2str(np)); |
---|
1396 | return (0); |
---|
1397 | } |
---|
1398 | |
---|
1399 | static struct Hist * |
---|
1400 | findev(cp, anyarg) |
---|
1401 | Char *cp; |
---|
1402 | bool anyarg; |
---|
1403 | { |
---|
1404 | struct Hist *hp; |
---|
1405 | |
---|
1406 | for (hp = Histlist.Hnext; hp; hp = hp->Hnext) { |
---|
1407 | Char *dp; |
---|
1408 | Char *p, *q; |
---|
1409 | struct wordent *lp = hp->Hlex.next; |
---|
1410 | int argno = 0; |
---|
1411 | |
---|
1412 | /* |
---|
1413 | * The entries added by alias substitution don't have a newline but do |
---|
1414 | * have a negative event number. Savehist() trims off these entries, |
---|
1415 | * but it happens before alias expansion, too early to delete those |
---|
1416 | * from the previous command. |
---|
1417 | */ |
---|
1418 | if (hp->Hnum < 0) |
---|
1419 | continue; |
---|
1420 | if (lp->word[0] == '\n') |
---|
1421 | continue; |
---|
1422 | if (!anyarg) { |
---|
1423 | p = cp; |
---|
1424 | q = lp->word; |
---|
1425 | do |
---|
1426 | if (!*p) |
---|
1427 | return (hp); |
---|
1428 | while (*p++ == *q++); |
---|
1429 | continue; |
---|
1430 | } |
---|
1431 | do { |
---|
1432 | for (dp = lp->word; *dp; dp++) { |
---|
1433 | p = cp; |
---|
1434 | q = dp; |
---|
1435 | do |
---|
1436 | if (!*p) { |
---|
1437 | quesarg = argno; |
---|
1438 | return (hp); |
---|
1439 | } |
---|
1440 | while (*p++ == *q++); |
---|
1441 | } |
---|
1442 | lp = lp->next; |
---|
1443 | argno++; |
---|
1444 | } while (lp->word[0] != '\n'); |
---|
1445 | } |
---|
1446 | seterror(ERR_NOEVENT, short2str(cp)); |
---|
1447 | return (0); |
---|
1448 | } |
---|
1449 | |
---|
1450 | |
---|
1451 | static void |
---|
1452 | setexclp(cp) |
---|
1453 | Char *cp; |
---|
1454 | { |
---|
1455 | if (cp && cp[0] == '\n') |
---|
1456 | return; |
---|
1457 | exclp = cp; |
---|
1458 | } |
---|
1459 | |
---|
1460 | void |
---|
1461 | unreadc(c) |
---|
1462 | int c; |
---|
1463 | { |
---|
1464 | peekread = (Char) c; |
---|
1465 | } |
---|
1466 | |
---|
1467 | int |
---|
1468 | readc(wanteof) |
---|
1469 | bool wanteof; |
---|
1470 | { |
---|
1471 | int c; |
---|
1472 | static int sincereal; /* Number of real EOFs we've seen */ |
---|
1473 | Char *ptr; /* For STRignoreeof */ |
---|
1474 | int numeof = 0; /* Value of STRignoreeof */ |
---|
1475 | |
---|
1476 | #ifdef DEBUG_INP |
---|
1477 | xprintf("readc\n"); |
---|
1478 | #endif |
---|
1479 | if ((c = peekread) != 0) { |
---|
1480 | peekread = 0; |
---|
1481 | return (c); |
---|
1482 | } |
---|
1483 | |
---|
1484 | /* Compute the value of EOFs */ |
---|
1485 | if ((ptr = varval(STRignoreeof)) != STRNULL) { |
---|
1486 | while (*ptr) { |
---|
1487 | if (!Isdigit(*ptr)) { |
---|
1488 | numeof = 0; |
---|
1489 | break; |
---|
1490 | } |
---|
1491 | numeof = numeof * 10 + *ptr++ - '0'; |
---|
1492 | } |
---|
1493 | } |
---|
1494 | if (numeof < 1) numeof = 26; /* Sanity check */ |
---|
1495 | |
---|
1496 | top: |
---|
1497 | aret = F_SEEK; |
---|
1498 | if (alvecp) { |
---|
1499 | arun = 1; |
---|
1500 | #ifdef DEBUG_INP |
---|
1501 | xprintf("alvecp %c\n", *alvecp & 0xff); |
---|
1502 | #endif |
---|
1503 | aret = A_SEEK; |
---|
1504 | if ((c = *alvecp++) != 0) |
---|
1505 | return (c); |
---|
1506 | if (alvec && *alvec) { |
---|
1507 | alvecp = *alvec++; |
---|
1508 | return (' '); |
---|
1509 | } |
---|
1510 | else { |
---|
1511 | alvecp = NULL; |
---|
1512 | aret = F_SEEK; |
---|
1513 | return('\n'); |
---|
1514 | } |
---|
1515 | } |
---|
1516 | if (alvec) { |
---|
1517 | arun = 1; |
---|
1518 | if ((alvecp = *alvec) != 0) { |
---|
1519 | alvec++; |
---|
1520 | goto top; |
---|
1521 | } |
---|
1522 | /* Infinite source! */ |
---|
1523 | return ('\n'); |
---|
1524 | } |
---|
1525 | arun = 0; |
---|
1526 | if (evalp) { |
---|
1527 | aret = E_SEEK; |
---|
1528 | if ((c = *evalp++) != 0) |
---|
1529 | return (c); |
---|
1530 | if (evalvec && *evalvec) { |
---|
1531 | evalp = *evalvec++; |
---|
1532 | return (' '); |
---|
1533 | } |
---|
1534 | aret = F_SEEK; |
---|
1535 | evalp = 0; |
---|
1536 | } |
---|
1537 | if (evalvec) { |
---|
1538 | if (evalvec == INVPPTR) { |
---|
1539 | doneinp = 1; |
---|
1540 | reset(); |
---|
1541 | } |
---|
1542 | if ((evalp = *evalvec) != 0) { |
---|
1543 | evalvec++; |
---|
1544 | goto top; |
---|
1545 | } |
---|
1546 | evalvec = INVPPTR; |
---|
1547 | return ('\n'); |
---|
1548 | } |
---|
1549 | do { |
---|
1550 | if (arginp == INVPTR || onelflg == 1) { |
---|
1551 | if (wanteof) |
---|
1552 | return (-1); |
---|
1553 | exitstat(); |
---|
1554 | } |
---|
1555 | if (arginp) { |
---|
1556 | if ((c = *arginp++) == 0) { |
---|
1557 | arginp = INVPTR; |
---|
1558 | return ('\n'); |
---|
1559 | } |
---|
1560 | return (c); |
---|
1561 | } |
---|
1562 | #ifdef BSDJOBS |
---|
1563 | reread: |
---|
1564 | #endif /* BSDJOBS */ |
---|
1565 | c = bgetc(); |
---|
1566 | if (c < 0) { |
---|
1567 | #ifndef WINNT |
---|
1568 | # ifndef POSIX |
---|
1569 | # ifdef TERMIO |
---|
1570 | struct termio tty; |
---|
1571 | # else /* SGTTYB */ |
---|
1572 | struct sgttyb tty; |
---|
1573 | # endif /* TERMIO */ |
---|
1574 | # else /* POSIX */ |
---|
1575 | struct termios tty; |
---|
1576 | # endif /* POSIX */ |
---|
1577 | #endif /* !WINNT */ |
---|
1578 | if (wanteof) |
---|
1579 | return (-1); |
---|
1580 | /* was isatty but raw with ignoreeof yields problems */ |
---|
1581 | #ifndef WINNT |
---|
1582 | # ifndef POSIX |
---|
1583 | # ifdef TERMIO |
---|
1584 | if (ioctl(SHIN, TCGETA, (ioctl_t) & tty) == 0 && |
---|
1585 | (tty.c_lflag & ICANON)) |
---|
1586 | # else /* GSTTYB */ |
---|
1587 | if (ioctl(SHIN, TIOCGETP, (ioctl_t) & tty) == 0 && |
---|
1588 | (tty.sg_flags & RAW) == 0) |
---|
1589 | # endif /* TERMIO */ |
---|
1590 | # else /* POSIX */ |
---|
1591 | if (tcgetattr(SHIN, &tty) == 0 && |
---|
1592 | (tty.c_lflag & ICANON)) |
---|
1593 | # endif /* POSIX */ |
---|
1594 | #else /* WINNT */ |
---|
1595 | if (isatty(SHIN)) |
---|
1596 | #endif /* !WINNT */ |
---|
1597 | { |
---|
1598 | /* was 'short' for FILEC */ |
---|
1599 | #ifdef BSDJOBS |
---|
1600 | int ctpgrp; |
---|
1601 | #endif /* BSDJOBS */ |
---|
1602 | |
---|
1603 | if (++sincereal >= numeof) /* Too many EOFs? Bye! */ |
---|
1604 | goto oops; |
---|
1605 | #ifdef BSDJOBS |
---|
1606 | if (tpgrp != -1 && |
---|
1607 | (ctpgrp = tcgetpgrp(FSHTTY)) != -1 && |
---|
1608 | tpgrp != ctpgrp) { |
---|
1609 | (void) tcsetpgrp(FSHTTY, tpgrp); |
---|
1610 | # ifdef _SEQUENT_ |
---|
1611 | if (ctpgrp) |
---|
1612 | # endif /* _SEQUENT */ |
---|
1613 | (void) killpg((pid_t) ctpgrp, SIGHUP); |
---|
1614 | # ifdef notdef |
---|
1615 | /* |
---|
1616 | * With the walking process group fix, this message |
---|
1617 | * is now obsolete. As the foreground process group |
---|
1618 | * changes, the shell needs to adjust. Well too bad. |
---|
1619 | */ |
---|
1620 | xprintf(CGETS(16, 1, "Reset tty pgrp from %d to %d\n"), |
---|
1621 | ctpgrp, tpgrp); |
---|
1622 | # endif /* notdef */ |
---|
1623 | goto reread; |
---|
1624 | } |
---|
1625 | #endif /* BSDJOBS */ |
---|
1626 | /* What follows is complicated EOF handling -- sterling@netcom.com */ |
---|
1627 | /* First, we check to see if we have ignoreeof set */ |
---|
1628 | if (adrof(STRignoreeof)) { |
---|
1629 | /* If so, we check for any stopped jobs only on the first EOF */ |
---|
1630 | if ((sincereal == 1) && (chkstop == 0)) { |
---|
1631 | panystop(1); |
---|
1632 | } |
---|
1633 | } else { |
---|
1634 | /* If we don't have ignoreeof set, always check for stopped jobs */ |
---|
1635 | if (chkstop == 0) { |
---|
1636 | panystop(1); |
---|
1637 | } |
---|
1638 | } |
---|
1639 | /* At this point, if there were stopped jobs, we would have already |
---|
1640 | * called reset(). If we got this far, assume we can print an |
---|
1641 | * exit/logout message if we ignoreeof, or just exit. |
---|
1642 | */ |
---|
1643 | if (adrof(STRignoreeof)) { |
---|
1644 | /* If so, tell the user to use exit or logout */ |
---|
1645 | if (loginsh) { |
---|
1646 | xprintf(CGETS(16, 2, |
---|
1647 | "\nUse \"logout\" to logout.\n")); |
---|
1648 | } else { |
---|
1649 | xprintf(CGETS(16, 3, |
---|
1650 | "\nUse \"exit\" to leave %s.\n"), |
---|
1651 | progname); |
---|
1652 | } |
---|
1653 | reset(); |
---|
1654 | } else { |
---|
1655 | /* If we don't have ignoreeof set, just fall through */ |
---|
1656 | ; /* EMPTY */ |
---|
1657 | } |
---|
1658 | } |
---|
1659 | oops: |
---|
1660 | doneinp = 1; |
---|
1661 | reset(); |
---|
1662 | } |
---|
1663 | sincereal = 0; |
---|
1664 | if (c == '\n' && onelflg) |
---|
1665 | onelflg--; |
---|
1666 | } while (c == 0); |
---|
1667 | if (histlinep < histline + BUFSIZE) |
---|
1668 | *histlinep++ = (Char) c; |
---|
1669 | return (c); |
---|
1670 | } |
---|
1671 | |
---|
1672 | static void |
---|
1673 | balloc(buf) |
---|
1674 | int buf; |
---|
1675 | { |
---|
1676 | Char **nfbuf; |
---|
1677 | |
---|
1678 | while (buf >= fblocks) { |
---|
1679 | nfbuf = (Char **) xcalloc((size_t) (fblocks + 2), |
---|
1680 | sizeof(Char **)); |
---|
1681 | if (fbuf) { |
---|
1682 | (void) blkcpy(nfbuf, fbuf); |
---|
1683 | xfree((ptr_t) fbuf); |
---|
1684 | } |
---|
1685 | fbuf = nfbuf; |
---|
1686 | fbuf[fblocks] = (Char *) xcalloc(BUFSIZE, sizeof(Char)); |
---|
1687 | fblocks++; |
---|
1688 | } |
---|
1689 | } |
---|
1690 | |
---|
1691 | static int |
---|
1692 | bgetc() |
---|
1693 | { |
---|
1694 | int c, off, buf; |
---|
1695 | int numleft = 0, roomleft; |
---|
1696 | char tbuf[BUFSIZE + 1]; |
---|
1697 | |
---|
1698 | if (cantell) { |
---|
1699 | if (fseekp < fbobp || fseekp > feobp) { |
---|
1700 | fbobp = feobp = fseekp; |
---|
1701 | (void) lseek(SHIN, fseekp, L_SET); |
---|
1702 | } |
---|
1703 | if (fseekp == feobp) { |
---|
1704 | int i; |
---|
1705 | |
---|
1706 | fbobp = feobp; |
---|
1707 | do |
---|
1708 | c = read(SHIN, tbuf, BUFSIZE); |
---|
1709 | while (c < 0 && errno == EINTR); |
---|
1710 | #ifdef convex |
---|
1711 | if (c < 0) |
---|
1712 | stderror(ERR_SYSTEM, progname, strerror(errno)); |
---|
1713 | #endif /* convex */ |
---|
1714 | if (c <= 0) |
---|
1715 | return (-1); |
---|
1716 | for (i = 0; i < c; i++) |
---|
1717 | fbuf[0][i] = (unsigned char) tbuf[i]; |
---|
1718 | feobp += c; |
---|
1719 | } |
---|
1720 | #ifndef WINNT |
---|
1721 | c = fbuf[0][fseekp - fbobp]; |
---|
1722 | fseekp++; |
---|
1723 | #else |
---|
1724 | do { |
---|
1725 | c = fbuf[0][fseekp - fbobp]; |
---|
1726 | fseekp++; |
---|
1727 | } while(c == '\r'); |
---|
1728 | #endif /* !WINNT */ |
---|
1729 | return (c); |
---|
1730 | } |
---|
1731 | |
---|
1732 | while (fseekp >= feobp) { |
---|
1733 | if (editing && intty) { /* then use twenex routine */ |
---|
1734 | fseekp = feobp; /* where else? */ |
---|
1735 | c = numleft = Inputl(); /* PWP: get a line */ |
---|
1736 | while (numleft > 0) { |
---|
1737 | off = (int) feobp % BUFSIZE; |
---|
1738 | buf = (int) feobp / BUFSIZE; |
---|
1739 | balloc(buf); |
---|
1740 | roomleft = BUFSIZE - off; |
---|
1741 | if (roomleft > numleft) |
---|
1742 | roomleft = numleft; |
---|
1743 | (void) memmove((ptr_t) (fbuf[buf] + off), (ptr_t) (InputBuf + c - numleft), (size_t) (roomleft * sizeof(Char))); |
---|
1744 | numleft -= roomleft; |
---|
1745 | feobp += roomleft; |
---|
1746 | } |
---|
1747 | } |
---|
1748 | else { |
---|
1749 | off = (int) feobp % BUFSIZE; |
---|
1750 | buf = (int) feobp / BUFSIZE; |
---|
1751 | balloc(buf); |
---|
1752 | roomleft = BUFSIZE - off; |
---|
1753 | c = read(SHIN, tbuf, (size_t) roomleft); |
---|
1754 | if (c > 0) { |
---|
1755 | int i; |
---|
1756 | Char *ptr = fbuf[buf] + off; |
---|
1757 | |
---|
1758 | for (i = 0; i < c; i++) |
---|
1759 | ptr[i] = (unsigned char) tbuf[i]; |
---|
1760 | feobp += c; |
---|
1761 | } |
---|
1762 | } |
---|
1763 | if (c == 0 || (c < 0 && fixio(SHIN, errno) == -1)) |
---|
1764 | return (-1); |
---|
1765 | } |
---|
1766 | #ifndef WINNT |
---|
1767 | c = fbuf[(int) fseekp / BUFSIZE][(int) fseekp % BUFSIZE]; |
---|
1768 | fseekp++; |
---|
1769 | #else |
---|
1770 | do { |
---|
1771 | c = fbuf[(int) fseekp / BUFSIZE][(int) fseekp % BUFSIZE]; |
---|
1772 | fseekp++; |
---|
1773 | } while(c == '\r'); |
---|
1774 | #endif /* !WINNT */ |
---|
1775 | return (c); |
---|
1776 | } |
---|
1777 | |
---|
1778 | static void |
---|
1779 | bfree() |
---|
1780 | { |
---|
1781 | int sb, i; |
---|
1782 | |
---|
1783 | if (cantell) |
---|
1784 | return; |
---|
1785 | if (whyles) |
---|
1786 | return; |
---|
1787 | sb = (int) (fseekp - 1) / BUFSIZE; |
---|
1788 | if (sb > 0) { |
---|
1789 | for (i = 0; i < sb; i++) |
---|
1790 | xfree((ptr_t) fbuf[i]); |
---|
1791 | (void) blkcpy(fbuf, &fbuf[sb]); |
---|
1792 | fseekp -= BUFSIZE * sb; |
---|
1793 | feobp -= BUFSIZE * sb; |
---|
1794 | fblocks -= sb; |
---|
1795 | } |
---|
1796 | } |
---|
1797 | |
---|
1798 | void |
---|
1799 | bseek(l) |
---|
1800 | struct Ain *l; |
---|
1801 | { |
---|
1802 | switch (aret = l->type) { |
---|
1803 | case E_SEEK: |
---|
1804 | evalvec = l->a_seek; |
---|
1805 | evalp = l->c_seek; |
---|
1806 | #ifdef DEBUG_SEEK |
---|
1807 | xprintf(CGETS(16, 4, "seek to eval %x %x\n"), evalvec, evalp); |
---|
1808 | #endif |
---|
1809 | return; |
---|
1810 | case A_SEEK: |
---|
1811 | alvec = l->a_seek; |
---|
1812 | alvecp = l->c_seek; |
---|
1813 | #ifdef DEBUG_SEEK |
---|
1814 | xprintf(CGETS(16, 5, "seek to alias %x %x\n"), alvec, alvecp); |
---|
1815 | #endif |
---|
1816 | return; |
---|
1817 | case F_SEEK: |
---|
1818 | #ifdef DEBUG_SEEK |
---|
1819 | xprintf(CGETS(16, 6, "seek to file %x\n"), fseekp); |
---|
1820 | #endif |
---|
1821 | fseekp = l->f_seek; |
---|
1822 | return; |
---|
1823 | default: |
---|
1824 | xprintf(CGETS(16, 7, "Bad seek type %d\n"), aret); |
---|
1825 | abort(); |
---|
1826 | } |
---|
1827 | } |
---|
1828 | |
---|
1829 | /* any similarity to bell telephone is purely accidental */ |
---|
1830 | void |
---|
1831 | btell(l) |
---|
1832 | struct Ain *l; |
---|
1833 | { |
---|
1834 | switch (l->type = aret) { |
---|
1835 | case E_SEEK: |
---|
1836 | l->a_seek = evalvec; |
---|
1837 | l->c_seek = evalp; |
---|
1838 | #ifdef DEBUG_SEEK |
---|
1839 | xprintf(CGETS(16, 8, "tell eval %x %x\n"), evalvec, evalp); |
---|
1840 | #endif |
---|
1841 | return; |
---|
1842 | case A_SEEK: |
---|
1843 | l->a_seek = alvec; |
---|
1844 | l->c_seek = alvecp; |
---|
1845 | #ifdef DEBUG_SEEK |
---|
1846 | xprintf(CGETS(16, 9, "tell alias %x %x\n"), alvec, alvecp); |
---|
1847 | #endif |
---|
1848 | return; |
---|
1849 | case F_SEEK: |
---|
1850 | /*SUPPRESS 112*/ |
---|
1851 | l->f_seek = fseekp; |
---|
1852 | l->a_seek = NULL; |
---|
1853 | #ifdef DEBUG_SEEK |
---|
1854 | xprintf(CGETS(16, 10, "tell file %x\n"), fseekp); |
---|
1855 | #endif |
---|
1856 | return; |
---|
1857 | default: |
---|
1858 | xprintf(CGETS(16, 7, "Bad seek type %d\n"), aret); |
---|
1859 | abort(); |
---|
1860 | } |
---|
1861 | } |
---|
1862 | |
---|
1863 | void |
---|
1864 | btoeof() |
---|
1865 | { |
---|
1866 | (void) lseek(SHIN, (off_t) 0, L_XTND); |
---|
1867 | aret = F_SEEK; |
---|
1868 | fseekp = feobp; |
---|
1869 | alvec = NULL; |
---|
1870 | alvecp = NULL; |
---|
1871 | evalvec = NULL; |
---|
1872 | evalp = NULL; |
---|
1873 | wfree(); |
---|
1874 | bfree(); |
---|
1875 | } |
---|
1876 | |
---|
1877 | void |
---|
1878 | settell() |
---|
1879 | { |
---|
1880 | off_t x; |
---|
1881 | cantell = 0; |
---|
1882 | if (arginp || onelflg || intty) |
---|
1883 | return; |
---|
1884 | if ((x = lseek(SHIN, (off_t) 0, L_INCR)) == -1) |
---|
1885 | return; |
---|
1886 | fbuf = (Char **) xcalloc(2, sizeof(Char **)); |
---|
1887 | fblocks = 1; |
---|
1888 | fbuf[0] = (Char *) xcalloc(BUFSIZE, sizeof(Char)); |
---|
1889 | fseekp = fbobp = feobp = x; |
---|
1890 | cantell = 1; |
---|
1891 | } |
---|