openenvutils/commandshell/shell/src/input.c
changeset 0 2e3d3ce01487
child 4 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 //input.c - read and store lines of input
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * This file is part of zsh, the Z shell.
       
     7  *
       
     8  * Copyright (c) 1992-1997 Paul Falstad
       
     9  * All rights reserved.
       
    10  *
       
    11  * Permission is hereby granted, without written agreement and without
       
    12  * license or royalty fees, to use, copy, modify, and distribute this
       
    13  * software and to distribute modified versions of this software for any
       
    14  * purpose, provided that the above copyright notice and the following
       
    15  * two paragraphs appear in all copies of this software.
       
    16  *
       
    17  * In no event shall Paul Falstad or the Zsh Development Group be liable
       
    18  * to any party for direct, indirect, special, incidental, or consequential
       
    19  * damages arising out of the use of this software and its documentation,
       
    20  * even if Paul Falstad and the Zsh Development Group have been advised of
       
    21  * the possibility of such damage.
       
    22  *
       
    23  * Paul Falstad and the Zsh Development Group specifically disclaim any
       
    24  * warranties, including, but not limited to, the implied warranties of
       
    25  * merchantability and fitness for a particular purpose.  The software
       
    26  * provided hereunder is on an "as is" basis, and Paul Falstad and the
       
    27  * Zsh Development Group have no obligation to provide maintenance,
       
    28  * support, updates, enhancements, or modifications.
       
    29  *
       
    30  */
       
    31 
       
    32 
       
    33 /*
       
    34  * This file deals with input buffering, supplying characters to the
       
    35  * history expansion code a character at a time.  Input is stored on a
       
    36  * stack, which allows insertion of strings into the input, possibly with
       
    37  * flags marking the end of alias expansion, with minimal copying of
       
    38  * strings.  The same stack is used to record the fact that the input
       
    39  * is a history or alias expansion and to store the alias while it is in use.
       
    40  * 
       
    41  * Input is taken either from zle, if appropriate, or read directly from
       
    42  * the input file, or may be supplied by some other part of the shell (such
       
    43  * as `eval' or $(...) substitution).  In the last case, it should be
       
    44  * supplied by pushing a new level onto the stack, via inpush(input_string,
       
    45  * flag, alias); if the current input really needs to be altered, use
       
    46  * inputsetline(input_string, flag).  `Flag' can include or's of INP_FREE
       
    47  * (if the input string is to be freed when used), INP_CONT (if the input
       
    48  * is to continue onto what's already in the input queue), INP_ALIAS
       
    49  * (push supplied alias onto stack) or INP_HIST (ditto, but used to
       
    50  * mark history expansion).  `alias' is ignored unless INP_ALIAS or
       
    51  * INP_HIST is supplied.  INP_ALIAS is always set if INP_HIST is.
       
    52  * 
       
    53  * Note that the input string is itself used as the input buffer: it is not
       
    54  * copied, nor is it every written back to, so using a constant string
       
    55  * should work.  Consequently, when passing areas of memory from the heap
       
    56  * it is necessary that that heap last as long as the operation of reading
       
    57  * the string.  After the string is read, the stack should be popped with
       
    58  * inpop(), which effectively flushes any unread input as well as restoring
       
    59  * the previous input state.
       
    60  *
       
    61  * The internal flag INP_ALCONT shows that the stack element was pushed
       
    62  * by an alias expansion; it should not be needed elsewhere.
       
    63  *
       
    64  * The global variable inalmore is set to indicate aliases should
       
    65  * continue to be expanded because the last alias expansion ended
       
    66  * in a space.  It is only reset after a complete word was read
       
    67  * without expanding a new alias, in exalias().
       
    68  *
       
    69  * PWS 1996/12/10
       
    70  */
       
    71 
       
    72 #ifdef HAVE_STDIO_H
       
    73 #include <stdio.h>
       
    74 #endif
       
    75 
       
    76 #include "zsh.mdh"
       
    77 #include "input.pro"
       
    78 
       
    79 /* the shell input fd */
       
    80 
       
    81 /**/
       
    82 int SHIN;
       
    83 
       
    84 /* buffered shell input for non-interactive shells */
       
    85 
       
    86 /**/
       
    87 FILE *bshin;
       
    88 
       
    89 /* != 0 means we are reading input from a string */
       
    90  
       
    91 /**/
       
    92 int strin;
       
    93  
       
    94 /* total # of characters waiting to be read. */
       
    95 
       
    96 /**/
       
    97 mod_export int inbufct;
       
    98 
       
    99 /* the flags controlling the input routines in input.c: see INP_* in zsh.h */
       
   100 
       
   101 /**/
       
   102 int inbufflags;
       
   103 
       
   104 static char *inbuf;		/* Current input buffer */
       
   105 static char *inbufptr;		/* Pointer into input buffer */
       
   106 static char *inbufpush;		/* Character at which to re-push alias */
       
   107 static int inbufleft;		/* Characters left in current input
       
   108 				   stack element */
       
   109 
       
   110 
       
   111  /* Input must be stacked since the input queue is used by
       
   112   * various different parts of the shell.
       
   113   */
       
   114 
       
   115 struct instacks {
       
   116     char *buf, *bufptr;
       
   117     Alias alias;
       
   118     int bufleft, bufct, flags;
       
   119 };
       
   120 static struct instacks *instack, *instacktop;
       
   121 /*
       
   122  * Input stack size.  We need to push the stack for aliases, history
       
   123  * expansion, and reading from internal strings: only if these operations
       
   124  * are nested do we need more than one extra level.  Thus we shouldn't need
       
   125  * too much space as a rule.  Initially, INSTACK_INITIAL is allocated; if
       
   126  * more is required, an extra INSTACK_EXPAND is added each time.
       
   127  */
       
   128 #define INSTACK_INITIAL	4
       
   129 #define INSTACK_EXPAND	4
       
   130 
       
   131 static int instacksz = INSTACK_INITIAL;
       
   132 
       
   133 /* Read a line from bshin.  Convert tokens and   *
       
   134  * null characters to Meta c^32 character pairs. */
       
   135 
       
   136 /**/
       
   137 mod_export char *
       
   138 shingetline(void)
       
   139 {
       
   140     char *line = NULL;
       
   141     int ll = 0;
       
   142     int c;
       
   143     char buf[BUFSIZ];
       
   144     char *p;
       
   145 
       
   146     p = buf;
       
   147     for (;;) {
       
   148 	do {
       
   149 	    errno = 0;
       
   150 	    c = fgetc(bshin);
       
   151 	} while (c < 0 && errno == EINTR);
       
   152 	if (c < 0 || c == '\n') {
       
   153 	    if (c == '\n')
       
   154 		*p++ = '\n';
       
   155 	    if (p > buf) {
       
   156 		*p++ = '\0';
       
   157 		line = zrealloc(line, ll + (p - buf));
       
   158 		memcpy(line + ll, buf, p - buf);
       
   159 	    }
       
   160 	    return line;
       
   161 	}
       
   162 	if (imeta(c)) {
       
   163 	    *p++ = Meta;
       
   164 	    *p++ = c ^ 32;
       
   165 	} else
       
   166 	    *p++ = c;
       
   167 	if (p >= buf + BUFSIZ - 1) {
       
   168 	    line = zrealloc(line, ll + (p - buf) + 1);
       
   169 	    memcpy(line + ll, buf, p - buf);
       
   170 	    ll += p - buf;
       
   171 	    line[ll] = '\0';
       
   172 	    p = buf;
       
   173 	}
       
   174     }
       
   175 }
       
   176 
       
   177 /* Get the next character from the input.
       
   178  * Will call inputline() to get a new line where necessary.
       
   179  */
       
   180   
       
   181 /**/
       
   182 int
       
   183 ingetc(void)
       
   184 {
       
   185     int lastc;
       
   186 
       
   187     if (lexstop)
       
   188 	return ' ';
       
   189     for (;;) {
       
   190 	if (inbufleft) {
       
   191 	    inbufleft--;
       
   192 	    inbufct--;
       
   193 	    if (itok(lastc = STOUC(*inbufptr++)))
       
   194 		continue;
       
   195 	    if (((inbufflags & INP_LINENO) || !strin) && lastc == '\n')
       
   196 		lineno++;
       
   197 	    return lastc;
       
   198 	}
       
   199 
       
   200 	/* If the next element down the input stack is a continuation of
       
   201 	 * this, use it.
       
   202 	 */ 
       
   203 	if (inbufflags & INP_CONT) {
       
   204 	    inpoptop();
       
   205 	    continue;
       
   206 	}
       
   207 	/*
       
   208 	 * Otherwise, see if we have reached the end of input
       
   209 	 * (due to an error, or to reading from a single string).
       
   210 	 */
       
   211 	if (strin || errflag) {
       
   212 	    lexstop = 1;
       
   213 	    return ' ';
       
   214 	}
       
   215 	/* As a last resort, get some more input */
       
   216 	if (inputline())
       
   217 	    return ' ';
       
   218     }
       
   219 }
       
   220 
       
   221 /* Read a line from the current command stream and store it as input */
       
   222 
       
   223 /**/
       
   224 static int
       
   225 inputline(void)
       
   226 {
       
   227     char *ingetcline, **ingetcpmptl = NULL, **ingetcpmptr = NULL;
       
   228     int context = ZLCON_LINE_START;
       
   229 
       
   230     /* If reading code interactively, work out the prompts. */
       
   231     if (interact && isset(SHINSTDIN)) {
       
   232 	if (!isfirstln) {
       
   233 	    ingetcpmptl = &prompt2;
       
   234 	    if (rprompt2)
       
   235 		ingetcpmptr = &rprompt2;
       
   236 	    context = ZLCON_LINE_CONT;
       
   237 	}
       
   238 	else {
       
   239 	    ingetcpmptl = &prompt;
       
   240 	    if (rprompt)
       
   241 		ingetcpmptr = &rprompt;
       
   242 	}
       
   243     }
       
   244     if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
       
   245 	/*
       
   246 	 * If not using zle, read the line straight from the input file.
       
   247 	 * Possibly we don't get the whole line at once:  in that case,
       
   248 	 * we get another chunk with the next call to inputline().
       
   249 	 */
       
   250 
       
   251 	if (interact && isset(SHINSTDIN)) {
       
   252 	    /*
       
   253 	     * We may still be interactive (e.g. running under emacs),
       
   254 	     * so output a prompt if necessary.  We don't know enough
       
   255 	     * about the input device to be able to handle an rprompt,
       
   256 	     * though.
       
   257 	     */
       
   258 	    char *pptbuf;
       
   259 	    int pptlen;
       
   260 	    pptbuf = unmetafy(promptexpand(ingetcpmptl ? *ingetcpmptl : NULL,
       
   261 					   0, NULL, NULL), &pptlen);
       
   262 	    write(1, (WRITE_ARG_2_T)pptbuf, pptlen);
       
   263 	    free(pptbuf);
       
   264 	}
       
   265 	ingetcline = shingetline();
       
   266     } else {
       
   267 	/*
       
   268 	 * Since we may have to read multiple lines before getting
       
   269 	 * a complete piece of input, we tell zle not to restore the
       
   270 	 * original tty settings after reading each chunk.  Instead,
       
   271 	 * this is done when the history mechanism for the current input
       
   272 	 * terminates, which is not until we have the whole input.
       
   273 	 * This is supposed to minimise problems on systems that clobber
       
   274 	 * typeahead when the terminal settings are altered.
       
   275 	 *                     pws 1998/03/12
       
   276 	 */
       
   277 	int flags = ZLRF_HISTORY|ZLRF_NOSETTY;
       
   278 	if (isset(IGNOREEOF))
       
   279 	    flags |= ZLRF_IGNOREEOF;
       
   280 	ingetcline = (char *)zleread(ingetcpmptl, ingetcpmptr, flags,
       
   281 				     context);
       
   282 	histdone |= HISTFLAG_SETTY;
       
   283     }
       
   284     if (!ingetcline) {
       
   285 	return lexstop = 1;
       
   286     }
       
   287     if (errflag) {
       
   288 	free(ingetcline);
       
   289 	return lexstop = errflag = 1;
       
   290     }
       
   291     if (isset(VERBOSE)) {
       
   292 	/* Output the whole line read so far. */
       
   293 	zputs(ingetcline, stderr);
       
   294 	fflush(stderr);
       
   295     }
       
   296     if (*ingetcline && ingetcline[strlen(ingetcline) - 1] == '\n' &&
       
   297 	interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) &&
       
   298 	SHTTY != -1 && *ingetcline && ingetcline[1] &&
       
   299 	ingetcline[strlen(ingetcline) - 2] == '`') {
       
   300 	/* Junk an unmatched "`" at the end of the line. */
       
   301 	int ct;
       
   302 	char *ptr;
       
   303 
       
   304 	for (ct = 0, ptr = ingetcline; *ptr; ptr++)
       
   305 	    if (*ptr == '`')
       
   306 		ct++;
       
   307 	if (ct & 1) {
       
   308 	    ptr[-2] = '\n';
       
   309 	    ptr[-1] = '\0';
       
   310 	}
       
   311     }
       
   312     isfirstch = 1;
       
   313     /* Put this into the input channel. */
       
   314     inputsetline(ingetcline, INP_FREE);
       
   315 
       
   316     return 0;
       
   317 }
       
   318 
       
   319 /*
       
   320  * Put a string in the input queue:
       
   321  * inbuf is only freeable if the flags include INP_FREE.
       
   322  */
       
   323 
       
   324 /**/
       
   325 static void
       
   326 inputsetline(char *str, int flags)
       
   327 {
       
   328     if ((inbufflags & INP_FREE) && inbuf) {
       
   329 	free(inbuf);
       
   330     }
       
   331     inbuf = inbufptr = str;
       
   332     inbufleft = strlen(inbuf);
       
   333 
       
   334     /*
       
   335      * inbufct must reflect the total number of characters left,
       
   336      * as it used by other parts of the shell, so we need to take account
       
   337      * of whether the input stack continues, and whether there
       
   338      * is an extra space to add on at the end.
       
   339      */
       
   340     if (flags & INP_CONT)
       
   341 	inbufct += inbufleft;
       
   342     else
       
   343 	inbufct = inbufleft;
       
   344     inbufflags = flags;
       
   345 }
       
   346 
       
   347 /*
       
   348  * Backup one character of the input.
       
   349  * The last character can always be backed up, provided we didn't just
       
   350  * expand an alias or a history reference.
       
   351  * In fact, the character is ignored and the previous character is used.
       
   352  * (If that's wrong, the bug is in the calling code.  Use the #ifdef DEBUG
       
   353  * code to check.) 
       
   354  */
       
   355 
       
   356 /**/
       
   357 void
       
   358 inungetc(int c)
       
   359 {
       
   360     if (!lexstop) {
       
   361 	if (inbufptr != inbuf) {
       
   362 #ifdef DEBUG
       
   363 	    /* Just for debugging: enable only if foul play suspected. */
       
   364 	    if (inbufptr[-1] != (char) c)
       
   365 		fprintf(stderr, "Warning: backing up wrong character.\n");
       
   366 #endif
       
   367 	    /* Just decrement the pointer:  if it's not the same
       
   368 	     * character being pushed back, we're in trouble anyway.
       
   369 	     */
       
   370 	    inbufptr--;
       
   371 	    inbufct++;
       
   372 	    inbufleft++;
       
   373 	    if (((inbufflags & INP_LINENO) || !strin) && c == '\n')
       
   374 		lineno--;
       
   375 	}
       
   376 #ifdef DEBUG
       
   377         else if (!(inbufflags & INP_CONT)) {
       
   378 	    /* Just for debugging */
       
   379 	    fprintf(stderr, "Attempt to inungetc() at start of input.\n");
       
   380 	}
       
   381 #endif
       
   382 	else {
       
   383 	    /*
       
   384 	     * The character is being backed up from a previous input stack
       
   385 	     * layer.  However, there was an expansion in the middle, so we
       
   386 	     * can't back up where we want to.  Instead, we just push it
       
   387 	     * onto the input stack as an extra character.
       
   388 	     */
       
   389 	    char *cback = (char *)zshcalloc(2);
       
   390 	    cback[0] = (char) c;
       
   391 	    inpush(cback, INP_FREE|INP_CONT, NULL);
       
   392 	}
       
   393 	/* If we are back at the start of a segment,
       
   394 	 * we may need to restore an alias popped from the stack.
       
   395 	 * Note this may be a dummy (history expansion) entry.
       
   396 	 */
       
   397 	if (inbufptr == inbufpush && inbufflags & INP_ALCONT) {
       
   398 	    /*
       
   399 	     * Go back up the stack over all entries which were alias
       
   400 	     * expansions and were pushed with nothing remaining to read.
       
   401 	     */
       
   402 	    do {
       
   403 		if (instacktop->alias)
       
   404 		    instacktop->alias->inuse = 1;
       
   405 		instacktop++;
       
   406 	    } while ((instacktop->flags & INP_ALCONT) && !instacktop->bufleft);
       
   407 	    inbufflags = INP_CONT|INP_ALIAS;
       
   408 	    inbufleft = 0;
       
   409 	    inbuf = inbufptr = "";
       
   410 	}
       
   411     }
       
   412 }
       
   413 
       
   414 /* stuff a whole file into the input queue and print it */
       
   415 
       
   416 /**/
       
   417 int
       
   418 stuff(char *fn)
       
   419 {
       
   420     FILE *in;
       
   421     char *buf;
       
   422     off_t len;
       
   423     
       
   424     if (!(in = fopen(unmeta(fn), "r"))) {    
       
   425 	zerr("can't open %s", fn, 0);
       
   426 	return 1;
       
   427     }
       
   428     fseek(in, 0, 2);
       
   429     len = ftell(in);
       
   430     fseek(in, 0, 0);
       
   431     buf = (char *)zalloc(len + 1);
       
   432     if (!(fread(buf, len, 1, in))) {
       
   433 	zerr("read error on %s", fn, 0);
       
   434 	fclose(in);
       
   435 	zfree(buf, len + 1);
       
   436 	return 1;
       
   437     }
       
   438     fclose(in);
       
   439     buf[len] = '\0';
       
   440     fwrite(buf, len, 1, stderr);
       
   441     fflush(stderr);
       
   442 #ifndef __SYMBIAN32__    
       
   443     inputsetline(metafy(buf, len, META_REALLOC), INP_FREE);
       
   444 #endif    
       
   445     return 0;
       
   446 }
       
   447 
       
   448 /* flush input queue */
       
   449 
       
   450 /**/
       
   451 void
       
   452 inerrflush(void)
       
   453 {
       
   454     while (!lexstop && inbufct)
       
   455 	ingetc();
       
   456 }
       
   457 
       
   458 /* Set some new input onto a new element of the input stack */
       
   459 
       
   460 /**/
       
   461 mod_export void
       
   462 inpush(char *str, int flags, Alias inalias)
       
   463 {
       
   464     if (!instack) {
       
   465 	/* Initial stack allocation */
       
   466 	instack = (struct instacks *)zalloc(instacksz*sizeof(struct instacks));
       
   467 	instacktop = instack;
       
   468     }
       
   469 
       
   470     instacktop->buf = inbuf;
       
   471     instacktop->bufptr = inbufptr;
       
   472     instacktop->bufleft = inbufleft;
       
   473     instacktop->bufct = inbufct;
       
   474     inbufflags &= ~INP_ALCONT;
       
   475     if (flags & (INP_ALIAS|INP_HIST)) {
       
   476 	/*
       
   477 	 * Text is expansion for history or alias, so continue
       
   478 	 * back to old level when done.  Also mark stack top
       
   479 	 * as alias continuation so as to back up if necessary,
       
   480 	 * and mark alias as in use.
       
   481 	 */
       
   482 	flags |= INP_CONT|INP_ALIAS;
       
   483 	instacktop->flags = inbufflags | INP_ALCONT;
       
   484 	if ((instacktop->alias = inalias))
       
   485 	    inalias->inuse = 1;
       
   486     } else {
       
   487 	/* If we are continuing an alias expansion, record the alias
       
   488 	 * expansion in new set of flags (do we need this?)
       
   489 	 */
       
   490 	if (((instacktop->flags = inbufflags) & INP_ALIAS) &&
       
   491 	    (flags & INP_CONT))
       
   492 	    flags |= INP_ALIAS;
       
   493     }
       
   494 
       
   495     instacktop++;
       
   496     if (instacktop == instack + instacksz) {
       
   497 	/* Expand the stack */
       
   498 	instack = (struct instacks *)
       
   499 	    realloc(instack,
       
   500 		    (instacksz + INSTACK_EXPAND)*sizeof(struct instacks));
       
   501 	instacktop = instack + instacksz;
       
   502 	instacksz += INSTACK_EXPAND;
       
   503     }
       
   504     /*
       
   505      * We maintain the entry above the highest one with real
       
   506      * text as a flag to inungetc() that it can stop re-pushing the stack.
       
   507      */
       
   508     instacktop->flags = 0;
       
   509 
       
   510     inbufpush = inbuf = NULL;
       
   511 
       
   512     inputsetline(str, flags);
       
   513 }
       
   514 
       
   515 /* Remove the top element of the stack */
       
   516 
       
   517 /**/
       
   518 static void
       
   519 inpoptop(void)
       
   520 {
       
   521     if (inbuf && (inbufflags & INP_FREE))
       
   522 	free(inbuf);
       
   523 
       
   524     instacktop--;
       
   525 
       
   526     inbuf = instacktop->buf;
       
   527     inbufptr = inbufpush = instacktop->bufptr;
       
   528     inbufleft = instacktop->bufleft;
       
   529     inbufct = instacktop->bufct;
       
   530     inbufflags = instacktop->flags;
       
   531 
       
   532     if (!(inbufflags & INP_ALCONT))
       
   533 	return;
       
   534 
       
   535     if (instacktop->alias) {
       
   536 	char *t = instacktop->alias->text;
       
   537 	/* a real alias:  mark it as unused. */
       
   538 	instacktop->alias->inuse = 0;
       
   539 	if (*t && t[strlen(t) - 1] == ' ') {
       
   540 	    inalmore = 1;
       
   541 	    histbackword();
       
   542 	}
       
   543     }
       
   544 }
       
   545 
       
   546 /* Remove the top element of the stack and all its continuations. */
       
   547 
       
   548 /**/
       
   549 mod_export void
       
   550 inpop(void)
       
   551 {
       
   552     int remcont;
       
   553 
       
   554     do {
       
   555 	remcont = inbufflags & INP_CONT;
       
   556 
       
   557 	inpoptop();
       
   558     } while (remcont);
       
   559 }
       
   560 
       
   561 /*
       
   562  * Expunge any aliases from the input stack; they shouldn't appear
       
   563  * in the history and need to be flushed explicitly when we encounter
       
   564  * an error.
       
   565  */
       
   566 
       
   567 /**/
       
   568 void
       
   569 inpopalias(void)
       
   570 {
       
   571     while (inbufflags & INP_ALIAS)
       
   572 	inpoptop();
       
   573 }