home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Shells / zsh-3.0.5-MIHS / src / Src / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-03  |  14.0 KB  |  512 lines

  1. /*
  2.  * $Id: input.c,v 2.11 1996/10/15 20:16:35 hzoli Exp $
  3.  *
  4.  * input.c - read and store lines of input
  5.  *
  6.  * This file is part of zsh, the Z shell.
  7.  *
  8.  * Copyright (c) 1992-1996 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. #include "zsh.h"
  73.  
  74. /* Input buffer variables:  inbufct and inbufflags are in globals.h. */
  75. static char *inbuf;        /* Current input buffer */
  76. static char *inbufptr;        /* Pointer into input buffer */
  77. static char *inbufpush;        /* Character at which to re-push alias */
  78. static int inbufleft;        /* Characters left in current input
  79.                    stack element */
  80.  
  81. static int lastc;        /* used as flag that end of line was reached */
  82.  
  83.  
  84.  /* Input must be stacked since the input queue is used by
  85.   * various different parts of the shell.
  86.   */
  87.  
  88. struct instacks {
  89.     char *buf, *bufptr;
  90.     Alias alias;
  91.     int bufleft, bufct, flags;
  92. };
  93. static struct instacks *instack, *instacktop;
  94. /*
  95.  * Input stack size.  We need to push the stack for aliases, history
  96.  * expansion, and reading from internal strings: only if these operations
  97.  * are nested do we need more than one extra level.  Thus we shouldn't need
  98.  * too much space as a rule.  Initially, INSTACK_INITIAL is allocated; if
  99.  * more is required, an extra INSTACK_EXPAND is added each time.
  100.  */
  101. #define INSTACK_INITIAL    4
  102. #define INSTACK_EXPAND    4
  103.  
  104. static int instacksz = INSTACK_INITIAL;
  105.  
  106. /* Read a line from bshin.  Convert tokens and   *
  107.  * null characters to Meta c^32 character pairs. */
  108.  
  109. static char *
  110. shingetline(void)
  111. {
  112.     char *line = NULL;
  113.     int ll = 0;
  114.     int c;
  115.     char buf[BUFSIZ];
  116.     char *p;
  117.  
  118.     p = buf;
  119.     for (;;) {
  120.     do {
  121.         errno = 0;
  122.         c = fgetc(bshin);
  123.     } while (c < 0 && errno == EINTR);
  124.     if (c < 0 || c == '\n') {
  125.         if (c == '\n')
  126.         *p++ = '\n';
  127.         if (p > buf) {
  128.         *p++ = '\0';
  129.         line = zrealloc(line, ll + (p - buf));
  130.         memcpy(line + ll, buf, p - buf);
  131.         }
  132.         return line;
  133.     }
  134.     if (imeta(c)) {
  135.         *p++ = Meta;
  136.         *p++ = c ^ 32;
  137.     } else
  138.         *p++ = c;
  139.     if (p >= buf + BUFSIZ - 1) {
  140.         line = zrealloc(line, ll + (p - buf) + 1);
  141.         memcpy(line + ll, buf, p - buf);
  142.         ll += p - buf;
  143.         line[ll] = '\0';
  144.         p = buf;
  145.     }
  146.     }
  147. }
  148.  
  149. /* Get the next character from the input.
  150.  * Will call inputline() to get a new line where necessary.
  151.  */
  152.   
  153. /**/
  154. int
  155. ingetc(void)
  156. {
  157.     if (lexstop)
  158.     return lastc = ' ';
  159.     for (;;) {
  160.     if (inbufleft) {
  161.         inbufleft--;
  162.         inbufct--;
  163.         if (itok(lastc = STOUC(*inbufptr++)))
  164.         continue;
  165.         return lastc;
  166.     }
  167.  
  168.     /* If the next element down the input stack is a continuation of
  169.      * this, use it.
  170.      */ 
  171.     if (inbufflags & INP_CONT) {
  172.         inpoptop();
  173.         continue;
  174.     }
  175.     /*
  176.      * Otherwise, see if we have reached the end of input
  177.      * (due to an error, or to reading from a single string).
  178.      */
  179.     if (strin || errflag) {
  180.         lexstop = 1;
  181.         return lastc = ' ';
  182.     }
  183.     /* As a last resort, get some more input */
  184.     if (inputline())
  185.         return lastc = ' ';
  186.     }
  187. }
  188.  
  189. /* Read a line from the current command stream and store it as input */
  190.  
  191. /**/
  192. int
  193. inputline(void)
  194. {
  195.     unsigned char *ingetcline, *ingetcpmptl = NULL, *ingetcpmptr = NULL;
  196.  
  197.     /* If reading code interactively, work out the prompts. */
  198.     if (interact && isset(SHINSTDIN))
  199.     if (!isfirstln)
  200.         ingetcpmptl = (unsigned char *)prompt2;
  201.     else {
  202.         ingetcpmptl = (unsigned char *)prompt;
  203.         if (rprompt)
  204.         ingetcpmptr = (unsigned char *)rprompt;
  205.     }
  206.     if (!(interact && isset(SHINSTDIN) && SHTTY != -1 && isset(USEZLE))) {
  207.     /*
  208.      * If not using zle, read the line straight from the input file.
  209.      * Possibly we don't get the whole line at once:  in that case,
  210.      * we get another chunk with the next call to inputline().
  211.      */
  212.  
  213.     if (interact && isset(SHINSTDIN)) {
  214.         /*
  215.          * We may still be interactive (e.g. running under emacs),
  216.          * so output a prompt if necessary.  We don't know enough
  217.          * about the input device to be able to handle an rprompt,
  218.          * though.
  219.          */
  220.         char *pptbuf;
  221.         int pptlen;
  222.         pptbuf = putprompt((char *)ingetcpmptl, &pptlen, NULL, 1);
  223.         write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
  224.         free(pptbuf);
  225.     }
  226.     ingetcline = (unsigned char *)shingetline();
  227.     } else
  228.     ingetcline = zleread((char *)ingetcpmptl, (char *)ingetcpmptr);
  229.     if (!ingetcline) {
  230.     return lexstop = 1;
  231.     }
  232.     if (errflag) {
  233.     free(ingetcline);
  234.     return lexstop = errflag = 1;
  235.     }
  236.     /* Look for a space, to see if this shouldn't be put into history */
  237.     if (isfirstln)
  238.     spaceflag = *ingetcline == ' ';
  239.     if (isset(VERBOSE)) {
  240.     /* Output the whole line read so far. */
  241.     zputs((char *)ingetcline, stderr);
  242.     fflush(stderr);
  243.     }
  244.     if (*ingetcline && ingetcline[strlen((char *)ingetcline) - 1] == '\n') {
  245.     /* We've now read a complete line. */
  246.     lineno++;
  247.     if (interact && isset(SUNKEYBOARDHACK) && isset(SHINSTDIN) &&
  248.         SHTTY != -1 && *ingetcline && ingetcline[1] &&
  249.         ingetcline[strlen((char *)ingetcline) - 2] == '`') {
  250.         /* Junk an unmatched "`" at the end of the line. */
  251.         int ct;
  252.         unsigned char *ptr;
  253.  
  254.         for (ct = 0, ptr = ingetcline; *ptr; ptr++)
  255.         if (*ptr == '`')
  256.             ct++;
  257.         if (ct & 1) {
  258.         ptr[-2] = '\n';
  259.         ptr[-1] = '\0';
  260.         }
  261.     }
  262.     }
  263.     isfirstch = 1;
  264.     /* Put this into the input channel. */
  265.     inputsetline((char *)ingetcline, INP_FREE);
  266.  
  267.     return 0;
  268. }
  269.  
  270. /*
  271.  * Put a string in the input queue:
  272.  * inbuf is only freeable if the flags include INP_FREE.
  273.  */
  274.  
  275. /**/
  276. void
  277. inputsetline(char *str, int flags)
  278. {
  279.     if ((inbufflags & INP_FREE) && inbuf) {
  280.     free(inbuf);
  281.     }
  282.     inbuf = inbufptr = str;
  283.     inbufleft = strlen(inbuf);
  284.  
  285.     /*
  286.      * inbufct must reflect the total number of characters left,
  287.      * as it used by other parts of the shell, so we need to take account
  288.      * of whether the input stack continues, and whether there
  289.      * is an extra space to add on at the end.
  290.      */
  291.     if (flags & INP_CONT)
  292.     inbufct += inbufleft;
  293.     else
  294.     inbufct = inbufleft;
  295.     inbufflags = flags;
  296. }
  297.  
  298. /*
  299.  * Backup one character of the input.
  300.  * The last character can always be backed up, provided we didn't just
  301.  * expand an alias or a history reference.
  302.  * In fact, the character is ignored and the previous character is used.
  303.  * (If that's wrong, the bug is in the calling code.  Use the #ifdef DEBUG
  304.  * code to check.) 
  305.  */
  306.  
  307. /**/
  308. void
  309. inungetc(int c)
  310. {
  311.     if (!lexstop) {
  312.     if (inbufptr != inbuf) {
  313. #ifdef DEBUG
  314.         /* Just for debugging: enable only if foul play suspected. */
  315.         if (inbufptr[-1] != (char) c)
  316.         fprintf(stderr, "Warning: backing up wrong character.\n");
  317. #endif
  318.         /* Just decrement the pointer:  if it's not the same
  319.          * character being pushed back, we're in trouble anyway.
  320.          */
  321.         inbufptr--;
  322.         inbufct++;
  323.         inbufleft++;
  324.     }
  325. #ifdef DEBUG
  326.         else if (!(inbufflags & INP_CONT)) {
  327.         /* Just for debugging */
  328.         fprintf(stderr, "Attempt to inungetc() at start of input.\n");
  329.     }
  330. #endif
  331.     else {
  332.         /*
  333.          * The character is being backed up from a previous input stack
  334.          * layer.  However, there was an expansion in the middle, so we
  335.          * can't back up where we want to.  Instead, we just push it
  336.          * onto the input stack as an extra character.
  337.          */
  338.         char *cback = (char *)zcalloc(2);
  339.         cback[0] = (char) c;
  340.         inpush(cback, INP_FREE|INP_CONT, NULL);
  341.     }
  342.     /* If we are back at the start of a segment,
  343.      * we may need to restore an alias popped from the stack.
  344.      * Note this may be a dummy (history expansion) entry.
  345.      */
  346.     if (inbufptr == inbufpush && inbufflags & INP_ALCONT) {
  347.         /*
  348.          * Go back up the stack over all entries which were alias
  349.          * expansions and were pushed with nothing remaining to read.
  350.          */
  351.         do {
  352.         if (instacktop->alias)
  353.             instacktop->alias->inuse = 1;
  354.         instacktop++;
  355.         } while ((instacktop->flags & INP_ALCONT) && !instacktop->bufleft);
  356.         inbufflags = INP_CONT|INP_ALIAS;
  357.         inbufleft = 0;
  358.         inbuf = inbufptr = "";
  359.     }
  360.     }
  361. }
  362.  
  363. /* stuff a whole file into the input queue and print it */
  364.  
  365. /**/
  366. int
  367. stuff(char *fn)
  368. {
  369.     FILE *in;
  370.     char *buf;
  371.     int len;
  372.  
  373.     if (!(in = fopen(unmeta(fn), "r"))) {
  374.     zerr("can't open %s", fn, 0);
  375.     return 1;
  376.     }
  377.     fseek(in, 0, 2);
  378.     len = ftell(in);
  379.     fseek(in, 0, 0);
  380.     buf = (char *)zalloc(len + 1);
  381.     if (!(fread(buf, len, 1, in))) {
  382.     zerr("read error on %s", fn, 0);
  383.     fclose(in);
  384.     zfree(buf, len + 1);
  385.     return 1;
  386.     }
  387.     fclose(in);
  388.     buf[len] = '\0';
  389.     fwrite(buf, len, 1, stderr);
  390.     fflush(stderr);
  391.     inputsetline(metafy(buf, len, META_REALLOC), INP_FREE);
  392.     return 0;
  393. }
  394.  
  395. /* flush input queue */
  396.  
  397. /**/
  398. void
  399. inerrflush(void)
  400. {
  401.     /*
  402.      * This always goes character by character, but at present
  403.      * it is only used in the history code, where that is the only
  404.      * completely safe way of discarding input.
  405.      */
  406.     while ((strin || lastc != '\n') && !lexstop)
  407.     ingetc();
  408. }
  409.  
  410. /* Set some new input onto a new element of the input stack */
  411.  
  412. /**/
  413. void
  414. inpush(char *str, int flags, Alias inalias)
  415. {
  416.     if (!instack) {
  417.     /* Initial stack allocation */
  418.     instack = (struct instacks *)zalloc(instacksz*sizeof(struct instacks));
  419.     instacktop = instack;
  420.     }
  421.  
  422.     instacktop->buf = inbuf;
  423.     instacktop->bufptr = inbufptr;
  424.     instacktop->bufleft = inbufleft;
  425.     instacktop->bufct = inbufct;
  426.     inbufflags &= ~INP_ALCONT;
  427.     if (flags & (INP_ALIAS|INP_HIST)) {
  428.     /*
  429.      * Text is expansion for history or alias, so continue
  430.      * back to old level when done.  Also mark stack top
  431.      * as alias continuation so as to back up if necessary,
  432.      * and mark alias as in use.
  433.      */
  434.     flags |= INP_CONT|INP_ALIAS;
  435.     instacktop->flags = inbufflags | INP_ALCONT;
  436.     if ((instacktop->alias = inalias))
  437.         inalias->inuse = 1;
  438.     } else {
  439.     /* If we are continuing an alias expansion, record the alias
  440.      * expansion in new set of flags (do we need this?)
  441.      */
  442.     if (((instacktop->flags = inbufflags) & INP_ALIAS) &&
  443.         (flags & INP_CONT))
  444.         flags |= INP_ALIAS;
  445.     }
  446.  
  447.     instacktop++;
  448.     if (instacktop == instack + instacksz) {
  449.     /* Expand the stack */
  450.     instack = (struct instacks *)
  451.         realloc(instack,
  452.             (instacksz + INSTACK_EXPAND)*sizeof(struct instacks));
  453.     instacktop = instack + instacksz;
  454.     instacksz += INSTACK_EXPAND;
  455.     }
  456.     /*
  457.      * We maintain the entry above the highest one with real
  458.      * text as a flag to inungetc() that it can stop re-pushing the stack.
  459.      */
  460.     instacktop->flags = 0;
  461.  
  462.     inbufpush = inbuf = NULL;
  463.  
  464.     inputsetline(str, flags);
  465. }
  466.  
  467. /* Remove the top element of the stack */
  468.  
  469. /**/
  470. void
  471. inpoptop(void)
  472. {
  473.     if (inbuf && (inbufflags & INP_FREE))
  474.     free(inbuf);
  475.  
  476.     instacktop--;
  477.  
  478.     inbuf = instacktop->buf;
  479.     inbufptr = inbufpush = instacktop->bufptr;
  480.     inbufleft = instacktop->bufleft;
  481.     inbufct = instacktop->bufct;
  482.     inbufflags = instacktop->flags;
  483.  
  484.     if (!(inbufflags & INP_ALCONT))
  485.     return;
  486.  
  487.     if (instacktop->alias) {
  488.     char *t = instacktop->alias->text;
  489.     /* a real alias:  mark it as unused. */
  490.     instacktop->alias->inuse = 0;
  491.     if (*t && t[strlen(t) - 1] == ' ') {
  492.         inalmore = 1;
  493.         histbackword();
  494.     }
  495.     }
  496. }
  497.  
  498. /* Remove the top element of the stack and all its continuations. */
  499.  
  500. /**/
  501. void
  502. inpop(void)
  503. {
  504.     int remcont;
  505.  
  506.     do {
  507.     remcont = inbufflags & INP_CONT;
  508.  
  509.     inpoptop();
  510.     } while (remcont);
  511. }
  512.