/*1* tclGet.c --2*3* This file contains procedures to convert strings into4* other forms, like integers or floating-point numbers or5* booleans, doing syntax checking along the way.6*7* Copyright (c) 1990-1993 The Regents of the University of California.8* Copyright (c) 1994-1995 Sun Microsystems, Inc.9*10* See the file "license.terms" for information on usage and redistribution11* of this file, and for a DISCLAIMER OF ALL WARRANTIES.12*13* SCCS: @(#) tclGet.c 1.24 96/02/15 11:42:4714*/1516#include "tclInt.h"17#include "tclPort.h"181920/*21*----------------------------------------------------------------------22*23* Tcl_GetInt --24*25* Given a string, produce the corresponding integer value.26*27* Results:28* The return value is normally TCL_OK; in this case *intPtr29* will be set to the integer value equivalent to string. If30* string is improperly formed then TCL_ERROR is returned and31* an error message will be left in interp->result.32*33* Side effects:34* None.35*36*----------------------------------------------------------------------37*/3839int40Tcl_GetInt(interp, string, intPtr)41Tcl_Interp *interp; /* Interpreter to use for error reporting. */42char *string; /* String containing a (possibly signed)43* integer in a form acceptable to strtol. */44int *intPtr; /* Place to store converted result. */45{46char *end, *p;47int i;4849/*50* Note: use strtoul instead of strtol for integer conversions51* to allow full-size unsigned numbers, but don't depend on strtoul52* to handle sign characters; it won't in some implementations.53*/5455errno = 0;56for (p = string; isspace(UCHAR(*p)); p++) {57/* Empty loop body. */58}59if (*p == '-') {60p++;61i = -(int)strtoul(p, &end, 0);62} else if (*p == '+') {63p++;64i = strtoul(p, &end, 0);65} else {66i = strtoul(p, &end, 0);67}68if (end == p) {69badInteger:70if (interp != (Tcl_Interp *) NULL) {71Tcl_AppendResult(interp, "expected integer but got \"", string,72"\"", (char *) NULL);73}74return TCL_ERROR;75}76if (errno == ERANGE) {77if (interp != (Tcl_Interp *) NULL) {78interp->result = "integer value too large to represent";79Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",80interp->result, (char *) NULL);81}82return TCL_ERROR;83}84while ((*end != '\0') && isspace(UCHAR(*end))) {85end++;86}87if (*end != 0) {88goto badInteger;89}90*intPtr = i;91return TCL_OK;92}9394/*95*----------------------------------------------------------------------96*97* Tcl_GetDouble --98*99* Given a string, produce the corresponding double-precision100* floating-point value.101*102* Results:103* The return value is normally TCL_OK; in this case *doublePtr104* will be set to the double-precision value equivalent to string.105* If string is improperly formed then TCL_ERROR is returned and106* an error message will be left in interp->result.107*108* Side effects:109* None.110*111*----------------------------------------------------------------------112*/113114int115Tcl_GetDouble(interp, string, doublePtr)116Tcl_Interp *interp; /* Interpreter to use for error reporting. */117char *string; /* String containing a floating-point number118* in a form acceptable to strtod. */119double *doublePtr; /* Place to store converted result. */120{121char *end;122double d;123124errno = 0;125d = strtod(string, &end);126if (end == string) {127badDouble:128if (interp != (Tcl_Interp *) NULL) {129Tcl_AppendResult(interp,130"expected floating-point number but got \"",131string, "\"", (char *) NULL);132}133return TCL_ERROR;134}135if (errno != 0) {136if (interp != (Tcl_Interp *) NULL) {137TclExprFloatError(interp, d);138}139return TCL_ERROR;140}141while ((*end != 0) && isspace(UCHAR(*end))) {142end++;143}144if (*end != 0) {145goto badDouble;146}147*doublePtr = d;148return TCL_OK;149}150151/*152*----------------------------------------------------------------------153*154* Tcl_GetBoolean --155*156* Given a string, return a 0/1 boolean value corresponding157* to the string.158*159* Results:160* The return value is normally TCL_OK; in this case *boolPtr161* will be set to the 0/1 value equivalent to string. If162* string is improperly formed then TCL_ERROR is returned and163* an error message will be left in interp->result.164*165* Side effects:166* None.167*168*----------------------------------------------------------------------169*/170171int172Tcl_GetBoolean(interp, string, boolPtr)173Tcl_Interp *interp; /* Interpreter to use for error reporting. */174char *string; /* String containing a boolean number175* specified either as 1/0 or true/false or176* yes/no. */177int *boolPtr; /* Place to store converted result, which178* will be 0 or 1. */179{180int i;181char lowerCase[10], c;182size_t length;183184/*185* Convert the input string to all lower-case.186*/187188for (i = 0; i < 9; i++) {189c = string[i];190if (c == 0) {191break;192}193if ((c >= 'A') && (c <= 'Z')) {194c += (char) ('a' - 'A');195}196lowerCase[i] = c;197}198lowerCase[i] = 0;199200length = strlen(lowerCase);201c = lowerCase[0];202if ((c == '0') && (lowerCase[1] == '\0')) {203*boolPtr = 0;204} else if ((c == '1') && (lowerCase[1] == '\0')) {205*boolPtr = 1;206} else if ((c == 'y') && (strncmp(lowerCase, "yes", length) == 0)) {207*boolPtr = 1;208} else if ((c == 'n') && (strncmp(lowerCase, "no", length) == 0)) {209*boolPtr = 0;210} else if ((c == 't') && (strncmp(lowerCase, "true", length) == 0)) {211*boolPtr = 1;212} else if ((c == 'f') && (strncmp(lowerCase, "false", length) == 0)) {213*boolPtr = 0;214} else if ((c == 'o') && (length >= 2)) {215if (strncmp(lowerCase, "on", length) == 0) {216*boolPtr = 1;217} else if (strncmp(lowerCase, "off", length) == 0) {218*boolPtr = 0;219} else {220goto badBoolean;221}222} else {223badBoolean:224if (interp != (Tcl_Interp *) NULL) {225Tcl_AppendResult(interp, "expected boolean value but got \"",226string, "\"", (char *) NULL);227}228return TCL_ERROR;229}230return TCL_OK;231}232233234