tclGet.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclGet.c --
  3.  *
  4.  * This file contains procedures to convert strings into
  5.  * other forms, like integers or floating-point numbers or
  6.  * booleans, doing syntax checking along the way.
  7.  *
  8.  * Copyright (c) 1990-1993 The Regents of the University of California.
  9.  * Copyright (c) 1994-1997 Sun Microsystems, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  *
  14.  * RCS: @(#) $Id: tclGet.c,v 1.8.2.1 2005/04/20 16:06:17 dgp Exp $
  15.  */
  16. #include "tclInt.h"
  17. #include "tclPort.h"
  18. #include "tclMath.h"
  19. /*
  20.  *----------------------------------------------------------------------
  21.  *
  22.  * Tcl_GetInt --
  23.  *
  24.  * Given a string, produce the corresponding integer value.
  25.  *
  26.  * Results:
  27.  * The return value is normally TCL_OK;  in this case *intPtr
  28.  * will be set to the integer value equivalent to string.  If
  29.  * string is improperly formed then TCL_ERROR is returned and
  30.  * an error message will be left in the interp's result.
  31.  *
  32.  * Side effects:
  33.  * None.
  34.  *
  35.  *----------------------------------------------------------------------
  36.  */
  37. int
  38. Tcl_GetInt(interp, string, intPtr)
  39.     Tcl_Interp *interp; /* Interpreter to use for error reporting. */
  40.     CONST char *string; /* String containing a (possibly signed)
  41.  * integer in a form acceptable to strtol. */
  42.     int *intPtr; /* Place to store converted result. */
  43. {
  44.     char *end;
  45.     CONST char *p = string;
  46.     long i;
  47.     /*
  48.      * Note: use strtoul instead of strtol for integer conversions
  49.      * to allow full-size unsigned numbers, but don't depend on strtoul
  50.      * to handle sign characters;  it won't in some implementations.
  51.      */
  52.     errno = 0;
  53. #ifdef TCL_STRTOUL_SIGN_CHECK
  54.     /*
  55.      * This special sign check actually causes bad numbers to be allowed
  56.      * when strtoul.  I can't find a strtoul that doesn't validly handle
  57.      * signed characters, and the C standard implies that this is all
  58.      * unnecessary. [Bug #634856]
  59.      */
  60.     for ( ; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */
  61. /* Empty loop body. */
  62.     }
  63.     if (*p == '-') {
  64. p++;
  65. i = -((long)strtoul(p, &end, 0)); /* INTL: Tcl source. */
  66.     } else if (*p == '+') {
  67. p++;
  68. i = strtoul(p, &end, 0); /* INTL: Tcl source. */
  69.     } else
  70. #else
  71. i = strtoul(p, &end, 0); /* INTL: Tcl source. */
  72. #endif
  73.     if (end == p) {
  74. badInteger:
  75.         if (interp != (Tcl_Interp *) NULL) {
  76.     Tcl_AppendResult(interp, "expected integer but got "", string,
  77.     """, (char *) NULL);
  78.     TclCheckBadOctal(interp, string);
  79.         }
  80. return TCL_ERROR;
  81.     }
  82.     /*
  83.      * The second test below is needed on platforms where "long" is
  84.      * larger than "int" to detect values that fit in a long but not in
  85.      * an int.
  86.      */
  87.     if ((errno == ERANGE) 
  88. #if (LONG_MAX > INT_MAX)
  89.     || (i > UINT_MAX) || (i < -(long)UINT_MAX)
  90. #endif
  91.     ) {
  92.         if (interp != (Tcl_Interp *) NULL) {
  93.     Tcl_SetResult(interp, "integer value too large to represent",
  94.     TCL_STATIC);
  95.             Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
  96.     Tcl_GetStringResult(interp), (char *) NULL);
  97.         }
  98. return TCL_ERROR;
  99.     }
  100.     while ((*end != '') && isspace(UCHAR(*end))) { /* INTL: ISO space. */
  101. end++;
  102.     }
  103.     if (*end != 0) {
  104. goto badInteger;
  105.     }
  106.     *intPtr = (int) i;
  107.     return TCL_OK;
  108. }
  109. /*
  110.  *----------------------------------------------------------------------
  111.  *
  112.  * TclGetLong --
  113.  *
  114.  * Given a string, produce the corresponding long integer value.
  115.  * This routine is a version of Tcl_GetInt but returns a "long"
  116.  * instead of an "int".
  117.  *
  118.  * Results:
  119.  * The return value is normally TCL_OK; in this case *longPtr
  120.  * will be set to the long integer value equivalent to string. If
  121.  * string is improperly formed then TCL_ERROR is returned and
  122.  * an error message will be left in the interp's result if interp
  123.  * is non-NULL. 
  124.  *
  125.  * Side effects:
  126.  * None.
  127.  *
  128.  *----------------------------------------------------------------------
  129.  */
  130. int
  131. TclGetLong(interp, string, longPtr)
  132.     Tcl_Interp *interp; /* Interpreter used for error reporting
  133.  * if not NULL. */
  134.     CONST char *string; /* String containing a (possibly signed)
  135.  * long integer in a form acceptable to
  136.  * strtoul. */
  137.     long *longPtr; /* Place to store converted long result. */
  138. {
  139.     char *end;
  140.     CONST char *p = string;
  141.     long i;
  142.     /*
  143.      * Note: don't depend on strtoul to handle sign characters; it won't
  144.      * in some implementations.
  145.      */
  146.     errno = 0;
  147. #ifdef TCL_STRTOUL_SIGN_CHECK
  148.     for ( ; isspace(UCHAR(*p)); p++) { /* INTL: ISO space. */
  149. /* Empty loop body. */
  150.     }
  151.     if (*p == '-') {
  152. p++;
  153. i = -(int)strtoul(p, &end, 0); /* INTL: Tcl source. */
  154.     } else if (*p == '+') {
  155. p++;
  156. i = strtoul(p, &end, 0); /* INTL: Tcl source. */
  157.     } else
  158. #else
  159. i = strtoul(p, &end, 0); /* INTL: Tcl source. */
  160. #endif
  161.     if (end == p) {
  162. badInteger:
  163.         if (interp != (Tcl_Interp *) NULL) {
  164.     Tcl_AppendResult(interp, "expected integer but got "", string,
  165.     """, (char *) NULL);
  166.     TclCheckBadOctal(interp, string);
  167.         }
  168. return TCL_ERROR;
  169.     }
  170.     if (errno == ERANGE) {
  171.         if (interp != (Tcl_Interp *) NULL) {
  172.     Tcl_SetResult(interp, "integer value too large to represent",
  173.     TCL_STATIC);
  174.             Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
  175.                     Tcl_GetStringResult(interp), (char *) NULL);
  176.         }
  177. return TCL_ERROR;
  178.     }
  179.     while ((*end != '') && isspace(UCHAR(*end))) { /* INTL: ISO space. */
  180. end++;
  181.     }
  182.     if (*end != 0) {
  183. goto badInteger;
  184.     }
  185.     *longPtr = i;
  186.     return TCL_OK;
  187. }
  188. /*
  189.  *----------------------------------------------------------------------
  190.  *
  191.  * Tcl_GetDouble --
  192.  *
  193.  * Given a string, produce the corresponding double-precision
  194.  * floating-point value.
  195.  *
  196.  * Results:
  197.  * The return value is normally TCL_OK; in this case *doublePtr
  198.  * will be set to the double-precision value equivalent to string.
  199.  * If string is improperly formed then TCL_ERROR is returned and
  200.  * an error message will be left in the interp's result.
  201.  *
  202.  * Side effects:
  203.  * None.
  204.  *
  205.  *----------------------------------------------------------------------
  206.  */
  207. int
  208. Tcl_GetDouble(interp, string, doublePtr)
  209.     Tcl_Interp *interp; /* Interpreter used for error reporting. */
  210.     CONST char *string; /* String containing a floating-point number
  211.  * in a form acceptable to strtod. */
  212.     double *doublePtr; /* Place to store converted result. */
  213. {
  214.     char *end;
  215.     double d;
  216.     errno = 0;
  217.     d = strtod(string, &end); /* INTL: Tcl source. */
  218.     if (end == string) {
  219. badDouble:
  220.         if (interp != (Tcl_Interp *) NULL) {
  221.             Tcl_AppendResult(interp,
  222.                     "expected floating-point number but got "",
  223.                     string, """, (char *) NULL);
  224.         }
  225. return TCL_ERROR;
  226.     }
  227.     if (errno != 0 && (d == HUGE_VAL || d == -HUGE_VAL || d == 0)) {
  228.         if (interp != (Tcl_Interp *) NULL) {
  229.             TclExprFloatError(interp, d); 
  230.         }
  231. return TCL_ERROR;
  232.     }
  233.     while ((*end != 0) && isspace(UCHAR(*end))) { /* INTL: ISO space. */
  234. end++;
  235.     }
  236.     if (*end != 0) {
  237. goto badDouble;
  238.     }
  239.     *doublePtr = d;
  240.     return TCL_OK;
  241. }
  242. /*
  243.  *----------------------------------------------------------------------
  244.  *
  245.  * Tcl_GetBoolean --
  246.  *
  247.  * Given a string, return a 0/1 boolean value corresponding
  248.  * to the string.
  249.  *
  250.  * Results:
  251.  * The return value is normally TCL_OK;  in this case *boolPtr
  252.  * will be set to the 0/1 value equivalent to string.  If
  253.  * string is improperly formed then TCL_ERROR is returned and
  254.  * an error message will be left in the interp's result.
  255.  *
  256.  * Side effects:
  257.  * None.
  258.  *
  259.  *----------------------------------------------------------------------
  260.  */
  261. int
  262. Tcl_GetBoolean(interp, string, boolPtr)
  263.     Tcl_Interp *interp; /* Interpreter used for error reporting. */
  264.     CONST char *string; /* String containing a boolean number
  265.  * specified either as 1/0 or true/false or
  266.  * yes/no. */
  267.     int *boolPtr; /* Place to store converted result, which
  268.  * will be 0 or 1. */
  269. {
  270.     int i;
  271.     char lowerCase[10], c;
  272.     size_t length;
  273.     /*
  274.      * Convert the input string to all lower-case. 
  275.      * INTL: This code will work on UTF strings.
  276.      */
  277.     for (i = 0; i < 9; i++) {
  278. c = string[i];
  279. if (c == 0) {
  280.     break;
  281. }
  282. if ((c >= 'A') && (c <= 'Z')) {
  283.     c += (char) ('a' - 'A');
  284. }
  285. lowerCase[i] = c;
  286.     }
  287.     lowerCase[i] = 0;
  288.     length = strlen(lowerCase);
  289.     c = lowerCase[0];
  290.     if ((c == '0') && (lowerCase[1] == '')) {
  291. *boolPtr = 0;
  292.     } else if ((c == '1') && (lowerCase[1] == '')) {
  293. *boolPtr = 1;
  294.     } else if ((c == 'y') && (strncmp(lowerCase, "yes", length) == 0)) {
  295. *boolPtr = 1;
  296.     } else if ((c == 'n') && (strncmp(lowerCase, "no", length) == 0)) {
  297. *boolPtr = 0;
  298.     } else if ((c == 't') && (strncmp(lowerCase, "true", length) == 0)) {
  299. *boolPtr = 1;
  300.     } else if ((c == 'f') && (strncmp(lowerCase, "false", length) == 0)) {
  301. *boolPtr = 0;
  302.     } else if ((c == 'o') && (length >= 2)) {
  303. if (strncmp(lowerCase, "on", length) == 0) {
  304.     *boolPtr = 1;
  305. } else if (strncmp(lowerCase, "off", length) == 0) {
  306.     *boolPtr = 0;
  307. } else {
  308.     goto badBoolean;
  309. }
  310.     } else {
  311. badBoolean:
  312.         if (interp != (Tcl_Interp *) NULL) {
  313.             Tcl_AppendResult(interp, "expected boolean value but got "",
  314.                     string, """, (char *) NULL);
  315.         }
  316. return TCL_ERROR;
  317.     }
  318.     return TCL_OK;
  319. }