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

📄 tclparse.c

📁 CMX990 demonstration board (DE9901)
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
 * tclParse.c --
 *
 *	This file contains a collection of procedures that are used
 *	to parse Tcl commands or parts of commands (like quoted
 *	strings or nested sub-commands).
 *
 * Copyright 1991 Regents of the University of California.
 * Permission to use, copy, modify, and distribute this
 * software and its documentation for any purpose and without
 * fee is hereby granted, provided that the above copyright
 * notice appear in all copies.  The University of California
 * makes no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without
 * express or implied warranty.
 *
 * $Id: tclParse.c,v 1.1.1.1 2001/04/29 20:35:00 karll Exp $
 */

#include "tclInt.h"

/*
 * The following table assigns a type to each character.  Only types
 * meaningful to Tcl parsing are represented here.  The table indexes
 * all 256 characters, with the negative ones first, then the positive
 * ones.
 */

char tclTypeTable[] = {
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_COMMAND_END,   TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_SPACE,         TCL_COMMAND_END,   TCL_SPACE,
  TCL_SPACE,         TCL_SPACE,         TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_SPACE,         TCL_NORMAL,        TCL_QUOTE,         TCL_NORMAL,
  TCL_DOLLAR,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_COMMAND_END,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_OPEN_BRACKET,
  TCL_BACKSLASH,     TCL_COMMAND_END,   TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,
  TCL_NORMAL,        TCL_NORMAL,        TCL_NORMAL,        TCL_OPEN_BRACE,
  TCL_NORMAL,        TCL_CLOSE_BRACE,   TCL_NORMAL,        TCL_NORMAL,
};

/*
 * Function prototypes for procedures local to this file:
 */
static char *	QuoteEnd _ANSI_ARGS_((char *string, int term));
static char *	VarNameEnd _ANSI_ARGS_((char *string));

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Backslash --
 *
 *	Figure out how to handle a backslash sequence.
 *
 * Results:
 *	The return value is the character that should be substituted
 *	in place of the backslash sequence that starts at src, or 0
 *	if the backslash sequence should be replace by nothing (e.g.
 *	backslash followed by newline).  If readPtr isn't NULL then
 *	it is filled in with a count of the number of characters in
 *	the backslash sequence.  Note:  if the backslash isn't followed
 *	by characters that are understood here, then the backslash
 *	sequence is only considered to be one character long, and it
 *	is replaced by a backslash char.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
char Tcl_Backslash(char *src, int *readPtr)
  //  char *src;	/* Points to the backslash character of
  //			 * a backslash sequence. */
  //int *readPtr;	/* Fill in with number of characters read
  //                     * from src, unless NULL. */
{
  register char *p = src+1;
  char result;
  int count;

  count = 2;

  switch (*p) {
  case 'b':
    result = '\b';
    break;
  case 'e':
    result = 033;
    break;
  case 'f':
    result = '\f';
    break;
  case 'n':
    result = '\n';
    break;
  case 'r':
    result = '\r';
    break;
  case 't':
    result = '\t';
    break;
  case 'v':
    result = '\v';
    break;
  case 'C':
    p++;
    if (isspace(*p) || (*p == 0)) {
      result = 'C';
      count = 1;
      break;
    }
    count = 3;
    if (*p == 'M') {
      p++;
      if (isspace(*p) || (*p == 0)) {
        result = 'M' & 037;
        break;
      }
      count = 4;
      result = (*p & 037) | '\200';
      break;
    }
    count = 3;
    result = *p & 037;
    break;
  case 'M':
    p++;
    if (isspace(*p) || (*p == 0)) {
      result = 'M';
      count = 1;
      break;
    }
    count = 3;
    result = *p + '\200';
    break;
  case '}':
  case '{':
  case ']':
  case '[':
  case '$':
  case ' ':
  case ';':
  case '"':
  case '\\':
    result = *p;
    break;
  case '\n':
    result = 0;
    break;
  default:
    if (isdigit(*p)) {
      result = *p - '0';
      p++;
      if (!isdigit(*p)) {
        break;
      }
      count = 3;
      result = (result << 3) + (*p - '0');
      p++;
      if (!isdigit(*p)) {
        break;
      }
      count = 4;
      result = (result << 3) + (*p - '0');
      break;
    }
    result = '\\';
    count = 1;
    break;
  }

  if (readPtr != NULL) {
    *readPtr = count;
  }
  return result;
}

/*
 *--------------------------------------------------------------
 *
 * TclParseQuotes --
 *
 *	This procedure parses a double-quoted string such as a
 *	quoted Tcl command argument or a quoted value in a Tcl
 *	expression.  This procedure is also used to parse array
 *	element names within parentheses, or anything else that
 *	needs all the substitutions that happen in quotes.
 *
 * Results:
 *	The return value is a standard Tcl result, which is
 *	TCL_OK unless there was an error while parsing the
 *	quoted string.  If an error occurs then interp->result
 *	contains a standard error message.  *TermPtr is filled
 *	in with the address of the character just after the
 *	last one successfully processed;  this is usually the
 *	character just after the matching close-quote.  The
 *	fully-substituted contents of the quotes are stored in
 *	standard fashion in *pvPtr, null-terminated with
 *	pvPtr->next pointing to the terminating null character.
 *
 * Side effects:
 *	The buffer space in pvPtr may be enlarged by calling its
 *	expandProc.
 *
 *--------------------------------------------------------------
 */
int TclParseQuotes(Tcl_Interp *interp, char *string, int termChar, int flags,
                   char **termPtr, ParseValue *pvPtr)
  //  Tcl_Interp *interp;	/* Interpreter to use for nested command
  //				 * evaluations and error messages. */
  //char *string;		/* Character just after opening double-
  //                             * quote. */
  //int termChar;		/* Character that terminates "quoted" string
  //                             * (usually double-quote, but sometimes
  //                             * right-paren or something else). */
  //int flags;			/* Flags to pass to nested Tcl_Eval calls. */
  //char **termPtr;		/* Store address of terminating character
  //                             * here. */
  //ParseValue *pvPtr;		/* Information about where to place
  //				 * fully-substituted result of parse. */
{
  register char *src, *dst, c;

  src = string;
  dst = pvPtr->next;

  while (1) {
    if (dst == pvPtr->end) {
      /*
       * Target buffer space is about to run out.  Make more space.
       */

      pvPtr->next = dst;
      (*pvPtr->expandProc)(pvPtr, 1);
      dst = pvPtr->next;
    }

    c = *src;
    src++;
    if (c == termChar) {
      *dst = '\0';
      pvPtr->next = dst;
      *termPtr = src;
      return TCL_OK;
    } else if (CHAR_TYPE(c) == TCL_NORMAL) {
    copy:
      *dst = c;
      dst++;
      continue;
    } else if (c == '$') {
      int length;
      char *value;

      value = Tcl_ParseVar(interp, src-1, termPtr);
      if (value == NULL) {
        return TCL_ERROR;
      }
      src = *termPtr;
      length = strlen(value);
      if ((pvPtr->end - dst) <= length) {
        pvPtr->next = dst;
        (*pvPtr->expandProc)(pvPtr, length);
        dst = pvPtr->next;
      }
      strcpy(dst, value);
      dst += length;
      continue;
    } else if (c == '[') {
      int result;

      pvPtr->next = dst;
      result = TclParseNestedCmd(interp, src, flags, termPtr, pvPtr);
      if (result != TCL_OK) {
        return result;
      }
      src = *termPtr;
      dst = pvPtr->next;
      continue;
    } else if (c == '\\') {
      int numRead;

      src--;
      *dst = Tcl_Backslash(src, &numRead);
      if (*dst != 0) {
        dst++;
      }
      src += numRead;
      continue;
    } else if (c == '\0') {
      Tcl_ResetResult(interp);
      sprintf(interp->result, "missing %c", termChar);
      *termPtr = string-1;
      return TCL_ERROR;
    } else {
      goto copy;
    }
  }
}

/*
 *--------------------------------------------------------------
 *
 * TclParseNestedCmd --
 *
 *	This procedure parses a nested Tcl command between
 *	brackets, returning the result of the command.
 *
 * Results:
 *	The return value is a standard Tcl result, which is
 *	TCL_OK unless there was an error while executing the
 *	nested command.  If an error occurs then interp->result
 *	contains a standard error message.  *TermPtr is filled
 *	in with the address of the character just after the
 *	last one processed;  this is usually the character just
 *	after the matching close-bracket, or the null character
 *	at the end of the string if the close-bracket was missing
 *	(a missing close bracket is an error).  The result returned
 *	by the command is stored in standard fashion in *pvPtr,
 *	null-terminated, with pvPtr->next pointing to the null
 *	character.
 *
 * Side effects:
 *	The storage space at *pvPtr may be expanded.
 *
 *--------------------------------------------------------------
 */

int TclParseNestedCmd(Tcl_Interp *interp, char *string, int flags, char **termPtr, ParseValue *pvPtr)
  //  Tcl_Interp *interp;	/* Interpreter to use for nested command
  //				 * evaluations and error messages. */
  //char *string;		/* Character just after opening bracket. */
  //int flags;			/* Flags to pass to nested Tcl_Eval. */
  //char **termPtr;		/* Store address of terminating character
  //                             * here. */
  //register ParseValue *pvPtr;	/* Information about where to place
  //				 * result of command. */
{
  int result, length, shortfall;
  Interp *iPtr = (Interp *) interp;

  result = Tcl_Eval(interp, string, flags | TCL_BRACKET_TERM, termPtr);

⌨️ 快捷键说明

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