Deleted Added
full compact
input.c (8855) input.c (12043)
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 19 unchanged lines hidden (view full) ---

28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $Id: input.c,v 1.2 1994/09/24 02:57:39 davidg Exp $
36 * $Id: input.c,v 1.3 1995/05/30 00:07:15 rgrimes Exp $
37 */
38
39#ifndef lint
40static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 5/31/93";
41#endif /* not lint */
42
43/*
44 * This file implements the input routines used by the parser.

--- 15 unchanged lines hidden (view full) ---

60
61#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
62
63MKINIT
64struct strpush {
65 struct strpush *prev; /* preceding string on stack */
66 char *prevstring;
67 int prevnleft;
37 */
38
39#ifndef lint
40static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 5/31/93";
41#endif /* not lint */
42
43/*
44 * This file implements the input routines used by the parser.

--- 15 unchanged lines hidden (view full) ---

60
61#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
62
63MKINIT
64struct strpush {
65 struct strpush *prev; /* preceding string on stack */
66 char *prevstring;
67 int prevnleft;
68 int prevlleft;
68 struct alias *ap; /* if push was associated with an alias */
69};
70
71/*
72 * The parsefile structure pointed to by the global variable parsefile
73 * contains information about the current file being read.
74 */
75
76MKINIT
77struct parsefile {
78 struct parsefile *prev; /* preceding file on stack */
79 int linno; /* current line */
80 int fd; /* file descriptor (or -1 if string) */
69 struct alias *ap; /* if push was associated with an alias */
70};
71
72/*
73 * The parsefile structure pointed to by the global variable parsefile
74 * contains information about the current file being read.
75 */
76
77MKINIT
78struct parsefile {
79 struct parsefile *prev; /* preceding file on stack */
80 int linno; /* current line */
81 int fd; /* file descriptor (or -1 if string) */
81 int nleft; /* number of chars left in buffer */
82 int nleft; /* number of chars left in line */
83 int lleft; /* number of lines left in buffer */
82 char *nextc; /* next char in buffer */
83 char *buf; /* input buffer */
84 struct strpush *strpush; /* for pushing strings at this level */
85 struct strpush basestrpush; /* so pushing one is fast */
86};
87
88
89int plinno = 1; /* input line number */
90MKINIT int parsenleft; /* copy of parsefile->nleft */
84 char *nextc; /* next char in buffer */
85 char *buf; /* input buffer */
86 struct strpush *strpush; /* for pushing strings at this level */
87 struct strpush basestrpush; /* so pushing one is fast */
88};
89
90
91int plinno = 1; /* input line number */
92MKINIT int parsenleft; /* copy of parsefile->nleft */
93MKINIT int parselleft; /* copy of parsefile->lleft */
91char *parsenextc; /* copy of parsefile->nextc */
92MKINIT struct parsefile basepf; /* top level input file */
93char basebuf[BUFSIZ]; /* buffer for top level input file */
94struct parsefile *parsefile = &basepf; /* current input file */
94char *parsenextc; /* copy of parsefile->nextc */
95MKINIT struct parsefile basepf; /* top level input file */
96char basebuf[BUFSIZ]; /* buffer for top level input file */
97struct parsefile *parsefile = &basepf; /* current input file */
95char *pushedstring; /* copy of parsenextc when text pushed back */
96int pushednleft; /* copy of parsenleft when text pushed back */
97int init_editline = 0; /* editline library initialized? */
98int whichprompt; /* 1 == PS1, 2 == PS2 */
99
100EditLine *el; /* cookie for editline package */
101
102#ifdef __STDC__
103STATIC void pushfile(void);
104#else

--- 9 unchanged lines hidden (view full) ---

114INIT {
115 extern char basebuf[];
116
117 basepf.nextc = basepf.buf = basebuf;
118}
119
120RESET {
121 if (exception != EXSHELLPROC)
98int init_editline = 0; /* editline library initialized? */
99int whichprompt; /* 1 == PS1, 2 == PS2 */
100
101EditLine *el; /* cookie for editline package */
102
103#ifdef __STDC__
104STATIC void pushfile(void);
105#else

--- 9 unchanged lines hidden (view full) ---

115INIT {
116 extern char basebuf[];
117
118 basepf.nextc = basepf.buf = basebuf;
119}
120
121RESET {
122 if (exception != EXSHELLPROC)
122 parsenleft = 0; /* clear input buffer */
123 parselleft = parsenleft = 0; /* clear input buffer */
123 popallfiles();
124}
125
126SHELLPROC {
127 popallfiles();
128}
129#endif
130

--- 32 unchanged lines hidden (view full) ---

163 * Nul characters in the input are silently discarded.
164 */
165
166int
167pgetc() {
168 return pgetc_macro();
169}
170
124 popallfiles();
125}
126
127SHELLPROC {
128 popallfiles();
129}
130#endif
131

--- 32 unchanged lines hidden (view full) ---

164 * Nul characters in the input are silently discarded.
165 */
166
167int
168pgetc() {
169 return pgetc_macro();
170}
171
172static int
173pread()
174{
175 int nr;
171
176
177 parsenextc = parsefile->buf;
178retry:
179 if (parsefile->fd == 0 && el) {
180 const char *rl_cp;
181 int len;
182
183 rl_cp = el_gets(el, &nr);
184 if (rl_cp == NULL)
185 nr = 0;
186 else {
187 /* XXX - BUFSIZE should redesign so not necessary */
188 strcpy(parsenextc, rl_cp);
189 }
190
191 } else {
192 nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
193 }
194
195 if (nr <= 0) {
196 if (nr < 0) {
197 if (errno == EINTR)
198 goto retry;
199 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
200 int flags = fcntl(0, F_GETFL, 0);
201 if (flags >= 0 && flags & O_NONBLOCK) {
202 flags &=~ O_NONBLOCK;
203 if (fcntl(0, F_SETFL, flags) >= 0) {
204 out2str("sh: turning off NDELAY mode\n");
205 goto retry;
206 }
207 }
208 }
209 }
210 nr = -1;
211 }
212 return nr;
213}
214
172/*
173 * Refill the input buffer and return the next input character:
174 *
175 * 1) If a string was pushed back on the input, pop it;
176 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
177 * from a string so we can't refill the buffer, return EOF.
215/*
216 * Refill the input buffer and return the next input character:
217 *
218 * 1) If a string was pushed back on the input, pop it;
219 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
220 * from a string so we can't refill the buffer, return EOF.
178 * 3) Call read to read in the characters.
179 * 4) Delete all nul characters from the buffer.
221 * 3) If there is more in the buffer, use it; else call read to fill it.
222 * 4) Process input up to next newline, deleting nul characters.
180 */
181
182int
183preadbuffer() {
223 */
224
225int
226preadbuffer() {
184 register char *p, *q;
185 register int i;
186 register int something;
227 char *p, *q;
228 int more;
229 int something;
187 extern EditLine *el;
230 extern EditLine *el;
231 char savec;
188
189 if (parsefile->strpush) {
190 popstring();
191 if (--parsenleft >= 0)
192 return (*parsenextc++);
193 }
194 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
195 return PEOF;
196 flushout(&output);
197 flushout(&errout);
232
233 if (parsefile->strpush) {
234 popstring();
235 if (--parsenleft >= 0)
236 return (*parsenextc++);
237 }
238 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
239 return PEOF;
240 flushout(&output);
241 flushout(&errout);
198retry:
199 p = parsenextc = parsefile->buf;
200 if (parsefile->fd == 0 && el) {
201 const char *rl_cp;
202 int len;
203
242
204 rl_cp = el_gets(el, &len);
205 if (rl_cp == NULL) {
206 i = 0;
207 goto eof;
243again:
244 if (parselleft <= 0) {
245 if ((parselleft = pread()) == -1) {
246 parselleft = parsenleft = EOF_NLEFT;
247 return PEOF;
208 }
248 }
209 strcpy(p, rl_cp); /* XXX - BUFSIZE should redesign so not necessary */
210 i = len;
211
212 } else {
213regular_read:
214 i = read(parsefile->fd, p, BUFSIZ - 1);
215 }
249 }
216eof:
217 if (i <= 0) {
218 if (i < 0) {
219 if (errno == EINTR)
220 goto retry;
221 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
222 int flags = fcntl(0, F_GETFL, 0);
223 if (flags >= 0 && flags & O_NONBLOCK) {
224 flags &=~ O_NONBLOCK;
225 if (fcntl(0, F_SETFL, flags) >= 0) {
226 out2str("sh: turning off NDELAY mode\n");
227 goto retry;
228 }
229 }
230 }
231 }
232 parsenleft = EOF_NLEFT;
233 return PEOF;
234 }
235 parsenleft = i - 1; /* we're returning one char in this call */
236
250
251 q = p = parsenextc;
252
237 /* delete nul characters */
238 something = 0;
253 /* delete nul characters */
254 something = 0;
239 for (;;) {
240 if (*p == '\0')
255 for (more = 1; more;) {
256 switch (*p) {
257 case '\0':
258 p++; /* Skip nul */
259 goto check;
260
261 case '\t':
262 case ' ':
241 break;
263 break;
242 if (*p != ' ' && *p != '\t' && *p != '\n')
264
265 case '\n':
266 parsenleft = q - parsenextc;
267 more = 0; /* Stop processing here */
268 break;
269
270 default:
243 something = 1;
271 something = 1;
244 p++;
245 if (--i <= 0) {
246 *p = '\0';
247 goto done; /* no nul characters */
272 break;
248 }
273 }
274
275 *q++ = *p++;
276check:
277 if (--parselleft <= 0) {
278 parsenleft = q - parsenextc - 1;
279 if (parsenleft < 0)
280 goto again;
281 *q = '\0';
282 more = 0;
283 }
249 }
284 }
250 /*
251 * remove nuls
252 */
253 q = p++;
254 while (--i > 0) {
255 if (*p != '\0')
256 *q++ = *p;
257 p++;
258 }
285
286 savec = *q;
259 *q = '\0';
287 *q = '\0';
260 if (q == parsefile->buf)
261 goto retry; /* buffer contained nothing but nuls */
262 parsenleft = q - parsefile->buf - 1;
263
288
264done:
289
265 if (parsefile->fd == 0 && hist && something) {
266 INTOFF;
290 if (parsefile->fd == 0 && hist && something) {
291 INTOFF;
267 history(hist, whichprompt == 1 ? H_ENTER : H_ADD,
268 parsefile->buf);
292 history(hist, whichprompt == 1 ? H_ENTER : H_ADD, parsenextc);
269 INTON;
270 }
293 INTON;
294 }
295
296
271 if (vflag) {
297 if (vflag) {
272 /*
273 * This isn't right. Most shells coordinate it with
274 * reading a line at a time. I honestly don't know if its
275 * worth it.
276 */
277 i = parsenleft + 1;
278 p = parsefile->buf;
279 for (; i--; p++)
280 out2c(*p)
298 out2str(parsenextc);
281 flushout(out2);
282 }
299 flushout(out2);
300 }
301
302 *q = savec;
303
283 return *parsenextc++;
284}
285
286/*
287 * Undo the last call to pgetc. Only one character may be pushed back.
288 * PEOF may be pushed back.
289 */
290

--- 20 unchanged lines hidden (view full) ---

311 if (parsefile->strpush) {
312 sp = ckmalloc(sizeof (struct strpush));
313 sp->prev = parsefile->strpush;
314 parsefile->strpush = sp;
315 } else
316 sp = parsefile->strpush = &(parsefile->basestrpush);
317 sp->prevstring = parsenextc;
318 sp->prevnleft = parsenleft;
304 return *parsenextc++;
305}
306
307/*
308 * Undo the last call to pgetc. Only one character may be pushed back.
309 * PEOF may be pushed back.
310 */
311

--- 20 unchanged lines hidden (view full) ---

332 if (parsefile->strpush) {
333 sp = ckmalloc(sizeof (struct strpush));
334 sp->prev = parsefile->strpush;
335 parsefile->strpush = sp;
336 } else
337 sp = parsefile->strpush = &(parsefile->basestrpush);
338 sp->prevstring = parsenextc;
339 sp->prevnleft = parsenleft;
340 sp->prevlleft = parselleft;
319 sp->ap = (struct alias *)ap;
320 if (ap)
321 ((struct alias *)ap)->flag |= ALIASINUSE;
322 parsenextc = s;
323 parsenleft = len;
324 INTON;
325}
326
327popstring()
328{
329 struct strpush *sp = parsefile->strpush;
330
331 INTOFF;
332 parsenextc = sp->prevstring;
333 parsenleft = sp->prevnleft;
341 sp->ap = (struct alias *)ap;
342 if (ap)
343 ((struct alias *)ap)->flag |= ALIASINUSE;
344 parsenextc = s;
345 parsenleft = len;
346 INTON;
347}
348
349popstring()
350{
351 struct strpush *sp = parsefile->strpush;
352
353 INTOFF;
354 parsenextc = sp->prevstring;
355 parsenleft = sp->prevnleft;
356 parselleft = sp->prevlleft;
334/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
335 if (sp->ap)
336 sp->ap->flag &= ~ALIASINUSE;
337 parsefile->strpush = sp->prev;
338 if (sp != &(parsefile->basestrpush))
339 ckfree(sp);
340 INTON;
341}

--- 36 unchanged lines hidden (view full) ---

378 pushfile();
379 parsefile->buf = ckmalloc(BUFSIZ);
380 }
381 if (parsefile->fd > 0)
382 close(parsefile->fd);
383 parsefile->fd = fd;
384 if (parsefile->buf == NULL)
385 parsefile->buf = ckmalloc(BUFSIZ);
357/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
358 if (sp->ap)
359 sp->ap->flag &= ~ALIASINUSE;
360 parsefile->strpush = sp->prev;
361 if (sp != &(parsefile->basestrpush))
362 ckfree(sp);
363 INTON;
364}

--- 36 unchanged lines hidden (view full) ---

401 pushfile();
402 parsefile->buf = ckmalloc(BUFSIZ);
403 }
404 if (parsefile->fd > 0)
405 close(parsefile->fd);
406 parsefile->fd = fd;
407 if (parsefile->buf == NULL)
408 parsefile->buf = ckmalloc(BUFSIZ);
386 parsenleft = 0;
409 parselleft = parsenleft = 0;
387 plinno = 1;
388}
389
390
391/*
392 * Like setinputfile, but takes input from a string.
393 */
394
395void
396setinputstring(string, push)
397 char *string;
398 {
399 INTOFF;
400 if (push)
401 pushfile();
402 parsenextc = string;
410 plinno = 1;
411}
412
413
414/*
415 * Like setinputfile, but takes input from a string.
416 */
417
418void
419setinputstring(string, push)
420 char *string;
421 {
422 INTOFF;
423 if (push)
424 pushfile();
425 parsenextc = string;
403 parsenleft = strlen(string);
426 parselleft = parsenleft = strlen(string);
404 parsefile->buf = NULL;
405 plinno = 1;
406 INTON;
407}
408
409
410
411/*
412 * To handle the "." command, a stack of input files is used. Pushfile
413 * adds a new entry to the stack and popfile restores the previous level.
414 */
415
416STATIC void
417pushfile() {
418 struct parsefile *pf;
419
420 parsefile->nleft = parsenleft;
427 parsefile->buf = NULL;
428 plinno = 1;
429 INTON;
430}
431
432
433
434/*
435 * To handle the "." command, a stack of input files is used. Pushfile
436 * adds a new entry to the stack and popfile restores the previous level.
437 */
438
439STATIC void
440pushfile() {
441 struct parsefile *pf;
442
443 parsefile->nleft = parsenleft;
444 parsefile->lleft = parselleft;
421 parsefile->nextc = parsenextc;
422 parsefile->linno = plinno;
423 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
424 pf->prev = parsefile;
425 pf->fd = -1;
426 pf->strpush = NULL;
427 pf->basestrpush.prev = NULL;
428 parsefile = pf;

--- 9 unchanged lines hidden (view full) ---

438 close(pf->fd);
439 if (pf->buf)
440 ckfree(pf->buf);
441 while (pf->strpush)
442 popstring();
443 parsefile = pf->prev;
444 ckfree(pf);
445 parsenleft = parsefile->nleft;
445 parsefile->nextc = parsenextc;
446 parsefile->linno = plinno;
447 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
448 pf->prev = parsefile;
449 pf->fd = -1;
450 pf->strpush = NULL;
451 pf->basestrpush.prev = NULL;
452 parsefile = pf;

--- 9 unchanged lines hidden (view full) ---

462 close(pf->fd);
463 if (pf->buf)
464 ckfree(pf->buf);
465 while (pf->strpush)
466 popstring();
467 parsefile = pf->prev;
468 ckfree(pf);
469 parsenleft = parsefile->nleft;
470 parselleft = parsefile->lleft;
446 parsenextc = parsefile->nextc;
447 plinno = parsefile->linno;
448 INTON;
449}
450
451
452/*
453 * Return to top level.

--- 23 unchanged lines hidden ---
471 parsenextc = parsefile->nextc;
472 plinno = parsefile->linno;
473 INTON;
474}
475
476
477/*
478 * Return to top level.

--- 23 unchanged lines hidden ---