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

📄 tclcmdah.c

📁 CMX990 demonstration board (DE9901)
💻 C
📖 第 1 页 / 共 2 页
字号:

  if (argc != 5) {
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                     " start test next command\"", (char *) NULL);
    return TCL_ERROR;
  }

  result = Tcl_Eval(interp, argv[1], 0, (char **) NULL);
  if (result != TCL_OK) {
    if (result == TCL_ERROR) {
      Tcl_AddErrorInfo(interp, "\n    (\"for\" initial command)");
    }
    return result;
  }
  while (1) {
    result = Tcl_ExprBoolean(interp, argv[2], &value);
    if (result != TCL_OK) {
      return result;
    }
    if (!value) {
      break;
    }
    result = Tcl_Eval(interp, argv[4], 0, (char **) NULL);
    if (result == TCL_CONTINUE) {
      result = TCL_OK;
    } else if (result != TCL_OK) {
      if (result == TCL_ERROR) {
        char msg[60];
        sprintf(msg, "\n    (\"for\" body line %d)", interp->errorLine);
        Tcl_AddErrorInfo(interp, msg);
      }
      break;
    }
    result = Tcl_Eval(interp, argv[3], 0, (char **) NULL);
    if (result == TCL_BREAK) {
      break;
    } else if (result != TCL_OK) {
      if (result == TCL_ERROR) {
        Tcl_AddErrorInfo(interp, "\n    (\"for\" loop-end command)");
      }
      return result;
    }
  }
  if (result == TCL_BREAK) {
    result = TCL_OK;
  }
  if (result == TCL_OK) {
    Tcl_ResetResult(interp);
  }
  return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ForeachCmd --
 *
 *	This procedure is invoked to process the "foreach" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */
int Tcl_ForeachCmd(ClientData dummy, Tcl_Interp *interp, int argc, char **argv)
  //ClientData dummy;			/* Not used. */
  //Tcl_Interp *interp;			/* Current interpreter. */
  //int argc;				/* Number of arguments. */
  //char **argv;			/* Argument strings. */
{
  int listArgc, i, result;
  char **listArgv;

  if (argc != 4) {
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                     " varName list command\"", (char *) NULL);
    return TCL_ERROR;
  }

  /*
   * Break the list up into elements, and execute the command once
   * for each value of the element.
   */

  result = Tcl_SplitList(interp, argv[2], &listArgc, &listArgv);
  if (result != TCL_OK) {
    return result;
  }
  for (i = 0; i < listArgc; i++) {
    if (Tcl_SetVar(interp, argv[1], listArgv[i], 0) == NULL) {
      Tcl_SetResult(interp, "couldn't set loop variable", TCL_STATIC);
      result = TCL_ERROR;
      break;
    }

    result = Tcl_Eval(interp, argv[3], 0, (char **) NULL);
    if (result != TCL_OK) {
      if (result == TCL_CONTINUE) {
        result = TCL_OK;
      } else if (result == TCL_BREAK) {
        result = TCL_OK;
        break;
      } else if (result == TCL_ERROR) {
        char msg[100];
        sprintf(msg, "\n    (\"foreach\" body line %d)",
                interp->errorLine);
        Tcl_AddErrorInfo(interp, msg);
        break;
      } else {
        break;
      }
    }
  }
  ckfree((char *) listArgv);
  if (result == TCL_OK) {
    Tcl_ResetResult(interp);
  }
  return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FormatCmd --
 *
 *	This procedure is invoked to process the "format" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */
int Tcl_FormatCmd(ClientData dummy, Tcl_Interp *interp, int argc, char **argv)
  //ClientData dummy;			/* Not used. */
  //Tcl_Interp *interp;			/* Current interpreter. */
  //int argc;				/* Number of arguments. */
  //char **argv;			/* Argument strings. */
{
  register char *format;	/* Used to read characters from the format
				 * string. */
  char newFormat[40];		/* A new format specifier is generated here. */
  int width;			/* Field width from field specifier, or 0 if
				 * no width given. */
  int precision;		/* Field precision from field specifier, or 0
				 * if no precision given. */
  int size;			/* Number of bytes needed for result of
				 * conversion, based on type of conversion
				 * ("e", "s", etc.) and width from above. */
  char *oneWordValue = NULL;	/* Used to hold value to pass to sprintf, if
				 * it's a one-word value. */
  double twoWordValue;	/* Used to hold value to pass to sprintf if
                         * it's a two-word value. */
  int oneTemp;
  int useTwoWords;		/* 0 means use oneWordValue, 1 means use
				 * twoWordValue. */
  char *dst = interp->result;	/* Where result is stored.  Starts off at
				 * interp->resultSpace, but may get dynamically
				 * re-allocated if this isn't enough. */
  int dstSize = 0;		/* Number of non-null characters currently
				 * stored at dst. */
  int dstSpace = TCL_RESULT_SIZE;
  /* Total amount of storage space available
   * in dst (not including null terminator. */
  int noPercent;		/* Special case for speed:  indicates there's
				 * no field specifier, just a string to copy. */
  char **curArg;		/* Remainder of argv array. */
  int useShort;		/* Value to be printed is short (half word). */

  /*
   * This procedure is a bit nasty.  The goal is to use sprintf to
   * do most of the dirty work.  There are several problems:
   * 1. this procedure can't trust its arguments.
   * 2. we must be able to provide a large enough result area to hold
   *    whatever's generated.  This is hard to estimate.
   * 2. there's no way to move the arguments from argv to the call
   *    to sprintf in a reasonable way.  This is particularly nasty
   *    because some of the arguments may be two-word values (doubles).
   * So, what happens here is to scan the format string one % group
   * at a time, making many individual calls to sprintf.
   */

  if (argc < 2) {
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                     " formatString ?arg arg ...?\"", (char *) NULL);
    return TCL_ERROR;
  }
  curArg = argv+2;
  argc -= 2;
  for (format = argv[1]; *format != 0; ) {
    register char *newPtr = newFormat;

    width = precision = useTwoWords = noPercent = useShort = 0;

    /*
     * Get rid of any characters before the next field specifier.
     * Collapse backslash sequences found along the way.
     */

    if (*format != '%') {
      register char *p;
      int bsSize;

      oneWordValue = p = format;
      while ((*format != '%') && (*format != 0)) {
        if (*format == '\\') {
          *p = Tcl_Backslash(format, &bsSize);
          if (*p != 0) {
            p++;
          }
          format += bsSize;
        } else {
          *p = *format;
          p++;
          format++;
        }
      }
      size = p - oneWordValue;
      noPercent = 1;
      goto doField;
    }

    if (format[1] == '%') {
      oneWordValue = format;
      size = 1;
      noPercent = 1;
      format += 2;
      goto doField;
    }

    /*
     * Parse off a field specifier, compute how many characters
     * will be needed to store the result, and substitute for
     * "*" size specifiers.
     */

    *newPtr = '%';
    newPtr++;
    format++;
    while ((*format == '-') || (*format == '#') || (*format == '0')
           || (*format == ' ') || (*format == '+')) {
      *newPtr = *format;
      newPtr++;
      format++;
    }
    if (isdigit(*format)) {
      width = atoi(format);
      do {
        format++;
      } while (isdigit(*format));
    } else if (*format == '*') {
      if (argc <= 0) {
        goto notEnoughArgs;
      }
      if (Tcl_GetInt(interp, *curArg, &width) != TCL_OK) {
        goto fmtError;
      }
      argc--;
      curArg++;
      format++;
    }
    if (width != 0) {
      sprintf(newPtr, "%d", width);
      while (*newPtr != 0) {
        newPtr++;
      }
    }
    if (*format == '.') {
      *newPtr = '.';
      newPtr++;
      format++;
    }
    if (isdigit(*format)) {
      precision = atoi(format);
      do {
        format++;
      } while (isdigit(*format));
    } else if (*format == '*') {
      if (argc <= 0) {
        goto notEnoughArgs;
      }
      if (Tcl_GetInt(interp, *curArg, &precision) != TCL_OK) {
        goto fmtError;
      }
      argc--;
      curArg++;
      format++;
    }
    if (precision != 0) {
      sprintf(newPtr, "%d", precision);
      while (*newPtr != 0) {
        newPtr++;
      }
    }
    if (*format == 'l') {
      format++;
    } else if (*format == 'h') {
      useShort = 1;
      *newPtr = 'h';
      newPtr++;
      format++;
    }
    *newPtr = *format;
    newPtr++;
    *newPtr = 0;
    if (argc <= 0) {
      goto notEnoughArgs;
    }
    switch (*format) {
    case 'D':
    case 'O':
    case 'U':
      if (!useShort) {
        newPtr++;
      } else {
        useShort = 0;
      }
      newPtr[-1] = tolower(*format);
      newPtr[-2] = 'l';
      *newPtr = 0;
    case 'd':
    case 'o':
    case 'u':
    case 'x':
    case 'X':
      if (Tcl_GetInt(interp, *curArg, &oneTemp) != TCL_OK) {
        goto fmtError;
      }
      oneWordValue = (char*)oneTemp;
      size = 40;
      break;
    case 's':
      oneWordValue = *curArg;
      size = strlen(*curArg);
      break;
    case 'c':
      if (Tcl_GetInt(interp, *curArg, &oneTemp) != TCL_OK) {
        goto fmtError;
      }
      oneWordValue = (char*)oneTemp;
      size = 1;
      break;
    case 'F':
      newPtr[-1] = tolower(newPtr[-1]);
    case 'e':
    case 'E':
    case 'f':
    case 'g':
    case 'G':
      if (Tcl_GetDouble(interp, *curArg, &twoWordValue) != TCL_OK) {
        goto fmtError;
      }
      useTwoWords = 1;
      size = 320;
      if (precision > 10) {
        size += precision;
      }
      break;
    case 0:
      interp->result =
        "format string ended in middle of field specifier";
      goto fmtError;
    default:
      sprintf(interp->result, "bad field specifier \"%c\"", *format);
      goto fmtError;
    }
    argc--;
    curArg++;
    format++;

    /*
     * Make sure that there's enough space to hold the formatted
     * result, then format it.
     */

  doField:
    if (width > size) {
      size = width;
    }
    if ((dstSize + size) > dstSpace) {
      char *newDst;
      int newSpace;

      newSpace = 2*(dstSize + size);
      newDst = (char *) ckalloc((unsigned) newSpace+1);
      if (dstSize != 0) {
        memcpy((VOID *) newDst, (VOID *) dst, dstSize);
      }
      if (dstSpace != TCL_RESULT_SIZE) {
        ckfree(dst);
      }
      dst = newDst;
      dstSpace = newSpace;
    }
    if (noPercent) {
      memcpy((VOID *) (dst+dstSize), (VOID *) oneWordValue, size);
      dstSize += size;
      dst[dstSize] = 0;
    } else {
      if (useTwoWords) {
        sprintf(dst+dstSize, newFormat, twoWordValue);
      } else if (useShort) {
        /*
         * The double cast below is needed for a few machines
         * (e.g. Pyramids as of 1/93) that don't like casts
         * directly from pointers to shorts.
         */

        sprintf(dst+dstSize, newFormat, (short) (int) oneWordValue);
      } else {
        sprintf(dst+dstSize, newFormat, (char *) oneWordValue);
      }
      dstSize += strlen(dst+dstSize);
    }
  }

  interp->result = dst;
  if (dstSpace != TCL_RESULT_SIZE) {
    interp->freeProc = (Tcl_FreeProc *) free;
  } else {
    interp->freeProc = 0;
  }
  return TCL_OK;

 notEnoughArgs:
  interp->result = "not enough arguments for all format specifiers";
 fmtError:
  if (dstSpace != TCL_RESULT_SIZE) {
    ckfree(dst);
  }
  return TCL_ERROR;
}

⌨️ 快捷键说明

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