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