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 --- |