⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclparse.c

📁 CMX990 demonstration board (DE9901)
💻 C
📖 第 1 页 / 共 3 页
字号:
 *
 * Results:
 *	The buffer space in *pvPtr is reallocated to something
 *	larger, and if pvPtr->clientData is non-zero the old
 *	buffer is freed.  Information is copied from the old
 *	buffer to the new one.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */
void TclExpandParseValue(ParseValue *pvPtr, int needed)
  //  register ParseValue *pvPtr;	/* Information about buffer that
  //					 * must be expanded.  If the clientData
  //					 * in the structure is non-zero, it
  //					 * means that the current buffer is
  //					 * dynamically allocated. */
  //int needed;				/* Minimum amount of additional space
  //					 * to allocate. */
{
  int newSpace;
  char *new;

  /*
   * Either double the size of the buffer or add enough new space
   * to meet the demand, whichever produces a larger new buffer.
   */

  newSpace = (pvPtr->end - pvPtr->buffer) + 1;
  if (newSpace < needed) {
    newSpace += needed;
  } else {
    newSpace += newSpace;
  }
  new = (char *) ckalloc((unsigned) newSpace);

  /*
   * Copy from old buffer to new, free old buffer if needed, and
   * mark new buffer as malloc-ed.
   */

  memcpy((VOID *) new, (VOID *) pvPtr->buffer, pvPtr->next - pvPtr->buffer);
  pvPtr->next = new + (pvPtr->next - pvPtr->buffer);
  if (pvPtr->clientData != 0) {
    ckfree(pvPtr->buffer);
  }
  pvPtr->buffer = new;
  pvPtr->end = new + newSpace - 1;
  pvPtr->clientData = (ClientData) 1;
}

/*
 *----------------------------------------------------------------------
 *
 * TclWordEnd --
 *
 *	Given a pointer into a Tcl command, find the end of the next
 *	word of the command.
 *
 * Results:
 *	The return value is a pointer to the last character that's part
 *	of the word pointed to by "start".  If the word doesn't end
 *	properly within the string then the return value is the address
 *	of the null character at the end of the string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
char *TclWordEnd(char *start, int nested)
  //  char *start;		/* Beginning of a word of a Tcl command. */
  //int nested;			/* Zero means this is a top-level command.
  //				 * One means this is a nested command (close
  //				 * brace is a word terminator). */
{
  register char *p;
  int count;

  p = start;
  while (isspace(*p)) {
    p++;
  }

  /*
   * Handle words beginning with a double-quote or a brace.
   */

  if (*p == '"') {
    p = QuoteEnd(p+1, '"');
    if (*p == 0) {
      return p;
    }
    p++;
  } else if (*p == '{') {
    int braces = 1;
    while (braces != 0) {
      p++;
      while (*p == '\\') {
        (void) Tcl_Backslash(p, &count);
        p += count;
      }
      if (*p == '}') {
        braces--;
      } else if (*p == '{') {
        braces++;
      } else if (*p == 0) {
        return p;
      }
    }
    p++;
  }

  /*
   * Handle words that don't start with a brace or double-quote.
   * This code is also invoked if the word starts with a brace or
   * double-quote and there is garbage after the closing brace or
   * quote.  This is an error as far as Tcl_Eval is concerned, but
   * for here the garbage is treated as part of the word.
   */

  while (1) {
    if (*p == '[') {
      for (p++; *p != ']'; p++) {
        p = TclWordEnd(p, 1);
        if (*p == 0) {
          return p;
        }
      }
      p++;
    } else if (*p == '\\') {
      (void) Tcl_Backslash(p, &count);
      p += count;
      if ((*p == 0) && (count == 2) && (p[-1] == '\n')) {
        return p;
      }
    } else if (*p == '$') {
      p = VarNameEnd(p);
      if (*p == 0) {
        return p;
      }
      p++;
    } else if (*p == ';') {
      /*
       * Include the semi-colon in the word that is returned.
       */

      return p;
    } else if (isspace(*p)) {
      return p-1;
    } else if ((*p == ']') && nested) {
      return p-1;
    } else if (*p == 0) {
      if (nested) {
        /*
         * Nested commands can't end because of the end of the
         * string.
         */
        return p;
      }
      return p-1;
    } else {
      p++;
    }
  }
}

/*
 *----------------------------------------------------------------------
 *
 * QuoteEnd --
 *
 *	Given a pointer to a string that obeys the parsing conventions
 *	for quoted things in Tcl, find the end of that quoted thing.
 *	The actual thing may be a quoted argument or a parenthesized
 *	index name.
 *
 * Results:
 *	The return value is a pointer to the last character that is
 *	part of the quoted string (i.e the character that's equal to
 *	term).  If the quoted string doesn't terminate properly then
 *	the return value is a pointer to the null character at the
 *	end of the string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static char *QuoteEnd(char *string, int term)
  //  char *string;		/* Pointer to character just after opening
  //                             * "quote". */
  //int term;			/* This character will terminate the
  //				 * quoted string (e.g. '"' or ')'). */
{
  register char *p = string;
  int count;

  while (*p != term) {
    if (*p == '\\') {
      (void) Tcl_Backslash(p, &count);
      p += count;
    } else if (*p == '[') {
      for (p++; *p != ']'; p++) {
        p = TclWordEnd(p, 1);
        if (*p == 0) {
          return p;
        }
      }
      p++;
    } else if (*p == '$') {
      p = VarNameEnd(p);
      if (*p == 0) {
        return p;
      }
      p++;
    } else if (*p == 0) {
      return p;
    } else {
      p++;
    }
  }
  return p-1;
}

/*
 *----------------------------------------------------------------------
 *
 * VarNameEnd --
 *
 *	Given a pointer to a variable reference using $-notation, find
 *	the end of the variable name spec.
 *
 * Results:
 *	The return value is a pointer to the last character that
 *	is part of the variable name.  If the variable name doesn't
 *	terminate properly then the return value is a pointer to the
 *	null character at the end of the string.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
static char *VarNameEnd(char *string)
  //  char *string;		/* Pointer to dollar-sign character. */
{
  register char *p = string+1;

  if (*p == '{') {
    for (p++; (*p != '}') && (*p != 0); p++) {
      /* Empty loop body. */
    }
    return p;
  }
  while (isalnum(*p) || (*p == '_')) {
    p++;
  }
  if ((*p == '(') && (p != string+1)) {
    return QuoteEnd(p+1, ')');
  }
  return p-1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ParseVar --
 *
 *	Given a string starting with a $ sign, parse off a variable
 *	name and return its value.
 *
 * Results:
 *	The return value is the contents of the variable given by
 *	the leading characters of string.  If termPtr isn't NULL,
 *	*termPtr gets filled in with the address of the character
 *	just after the last one in the variable specifier.  If the
 *	variable doesn't exist, then the return value is NULL and
 *	an error message will be left in interp->result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
char *Tcl_ParseVar(Tcl_Interp *interp, char *string, char **termPtr)
  //  Tcl_Interp *interp;		/* Context for looking up variable. */
  //register char *string;		/* String containing variable name.
  //                                     * First character must be "$". */
  //char **termPtr;			/* If non-NULL, points to word to fill
  //                                     * in with character just after last
  //                                     * one in the variable specifier. */
{
  char *name1, *name1End, c, *result;
  register char *name2;
#define NUM_CHARS 200
  char copyStorage[NUM_CHARS];
  ParseValue pv;

  /*
   * There are three cases:
   * 1. The $ sign is followed by an open curly brace.  Then the variable
   *    name is everything up to the next close curly brace, and the
   *    variable is a scalar variable.
   * 2. The $ sign is not followed by an open curly brace.  Then the
   *    variable name is everything up to the next character that isn't
   *    a letter, digit, or underscore.  If the following character is an
   *    open parenthesis, then the information between parentheses is
   *    the array element name, which can include any of the substitutions
   *    permissible between quotes.
   * 3. The $ sign is followed by something that isn't a letter, digit,
   *    or underscore:  in this case, there is no variable name, and "$"
   *    is returned.
   */

  name2 = NULL;
  string++;
  if (*string == '{') {
    string++;
    name1 = string;
    while (*string != '}') {
      if (*string == 0) {
        Tcl_SetResult(interp, "missing close-brace for variable name",
                      TCL_STATIC);
        if (termPtr != 0) {
          *termPtr = string;
        }
        return NULL;
      }
      string++;
    }
    name1End = string;
    string++;
  } else {
    name1 = string;
    while (isalnum(*string) || (*string == '_')) {
      string++;
    }
    if (string == name1) {
      if (termPtr != 0) {
        *termPtr = string;
      }
      return "$";
    }
    name1End = string;
    if (*string == '(') {
      char *end;

      /*
       * Perform substitutions on the array element name, just as
       * is done for quotes.
       */

      pv.buffer = pv.next = copyStorage;
      pv.end = copyStorage + NUM_CHARS - 1;
      pv.expandProc = TclExpandParseValue;
      pv.clientData = (ClientData) NULL;
      if (TclParseQuotes(interp, string+1, ')', 0, &end, &pv)
          != TCL_OK) {
        char msg[100];
        sprintf(msg, "\n    (parsing index for array \"%.*s\")",
                (int)(string-name1), name1);
        Tcl_AddErrorInfo(interp, msg);
        result = NULL;
        name2 = pv.buffer;
        if (termPtr != 0) {
          *termPtr = end;
        }
        goto done;
      }
      string = end;
      name2 = pv.buffer;
    }
  }
  if (termPtr != 0) {
    *termPtr = string;
  }

  if (((Interp *) interp)->noEval) {
    return "";
  }
  c = *name1End;
  *name1End = 0;
  result = Tcl_GetVar2(interp, name1, name2, TCL_LEAVE_ERR_MSG);
  *name1End = c;

 done:
  if ((name2 != NULL) && (pv.buffer != copyStorage)) {
    ckfree(pv.buffer);
  }
  return result;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -