Jim Tcl
Diff
Not logged in

Differences From Artifact [4a0c5c902820e390]:

To Artifact [8dded17273791ce5]:


88 88 static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, 89 89 const char *prefix, const char *const *tablePtr, const char *name); 90 90 static void JimDeleteLocalProcs(Jim_Interp *interp); 91 91 static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filename, int linenr, 92 92 int argc, Jim_Obj *const *argv); 93 93 static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv, 94 94 const char *filename, int linenr); 95 +static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); 95 96 96 97 static const Jim_HashTableType JimVariablesHashTableType; 97 98 98 99 const char *tt_name(int type); 99 100 100 101 /* ----------------------------------------------------------------------------- 101 102 * Utility functions ................................................................................ 308 309 int Jim_WideToString(char *buf, jim_wide wideValue) 309 310 { 310 311 const char *fmt = "%" JIM_WIDE_MODIFIER; 311 312 312 313 return sprintf(buf, fmt, wideValue); 313 314 } 314 315 315 -int Jim_StringToWide(const char *str, jim_wide * widePtr, int base) 316 +/** 317 + * After an strtol()/strtod()-like conversion, 318 + * check whether something was converted and that 319 + * the only thing left is white space. 320 + * 321 + * Returns JIM_OK or JIM_ERR. 322 + */ 323 +static int JimCheckConversion(const char *str, const char *endptr) 316 324 { 317 - char *endptr; 325 + if (str[0] == '\0' || str == endptr) { 326 + return JIM_ERR; 327 + } 318 328 319 - *widePtr = strtoull(str, &endptr, base); 320 - 321 - if ((str[0] == '\0') || (str == endptr)) 322 - return JIM_ERR; 323 329 if (endptr[0] != '\0') { 324 330 while (*endptr) { 325 331 if (!isspace(*endptr)) { 326 332 return JIM_ERR; 327 333 } 328 334 endptr++; 329 335 } 330 336 } 331 337 return JIM_OK; 332 338 } 339 + 340 +int Jim_StringToWide(const char *str, jim_wide * widePtr, int base) 341 +{ 342 + char *endptr; 343 + 344 + *widePtr = strtoull(str, &endptr, base); 345 + 346 + return JimCheckConversion(str, endptr); 347 +} 333 348 334 349 int Jim_DoubleToString(char *buf, double doubleValue) 335 350 { 336 351 int len; 337 352 338 353 len = sprintf(buf, "%.12g", doubleValue); 339 354 ................................................................................ 356 371 357 372 return len + 2; 358 373 } 359 374 360 375 int Jim_StringToDouble(const char *str, double *doublePtr) 361 376 { 362 377 char *endptr; 378 + 379 + /* Callers can check for underflow via ERANGE */ 380 + errno = 0; 363 381 364 382 *doublePtr = strtod(str, &endptr); 365 - if (str[0] == '\0' || endptr[0] != '\0' || (str == endptr)) { 366 - return JIM_ERR; 367 - } 368 - return JIM_OK; 383 + 384 + return JimCheckConversion(str, endptr); 369 385 } 370 386 371 387 static jim_wide JimPowWide(jim_wide b, jim_wide e) 372 388 { 373 389 jim_wide i, res = 1; 374 390 375 391 if ((b == 0 && e != 0) || (e < 0)) ................................................................................ 2251 2267 2252 2268 buf = Jim_StrDup(strObjPtr->bytes); 2253 2269 trim_right(buf, trimchars); 2254 2270 2255 2271 return Jim_NewStringObjNoAlloc(interp, buf, -1); 2256 2272 } 2257 2273 2274 + 2275 +static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) 2276 +{ 2277 + static const char *strclassnames[] = { 2278 + "integer", "alpha", "alnum", "ascii", "digit", 2279 + "double", "lower", "upper", "space", "xdigit", 2280 + "control", "print", "graph", "punct", 2281 + NULL 2282 + }; 2283 + enum { 2284 + STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, 2285 + STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, 2286 + STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT 2287 + }; 2288 + int strclass; 2289 + int len; 2290 + int i; 2291 + const char *str; 2292 + int (*isclassfunc)(int c) = NULL; 2293 + 2294 + if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { 2295 + return JIM_ERR; 2296 + } 2297 + 2298 + str = Jim_GetString(strObjPtr, &len); 2299 + if (len == 0) { 2300 + Jim_SetResultInt(interp, !strict); 2301 + return JIM_OK; 2302 + } 2303 + 2304 + switch (strclass) { 2305 + case STR_IS_INTEGER: 2306 + { 2307 + jim_wide w; 2308 + Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); 2309 + return JIM_OK; 2310 + } 2311 + 2312 + case STR_IS_DOUBLE: 2313 + { 2314 + double d; 2315 + Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); 2316 + return JIM_OK; 2317 + } 2318 + 2319 + case STR_IS_ALPHA: isclassfunc = isalpha; break; 2320 + case STR_IS_ALNUM: isclassfunc = isalnum; break; 2321 + case STR_IS_ASCII: isclassfunc = isascii; break; 2322 + case STR_IS_DIGIT: isclassfunc = isdigit; break; 2323 + case STR_IS_LOWER: isclassfunc = islower; break; 2324 + case STR_IS_UPPER: isclassfunc = isupper; break; 2325 + case STR_IS_SPACE: isclassfunc = isspace; break; 2326 + case STR_IS_XDIGIT: isclassfunc = isxdigit; break; 2327 + case STR_IS_CONTROL: isclassfunc = iscntrl; break; 2328 + case STR_IS_PRINT: isclassfunc = isprint; break; 2329 + case STR_IS_GRAPH: isclassfunc = isgraph; break; 2330 + case STR_IS_PUNCT: isclassfunc = ispunct; break; 2331 + } 2332 + 2333 + for (i = 0; i < len; i++) { 2334 + if (!isclassfunc(str[i])) { 2335 + Jim_SetResultInt(interp, 0); 2336 + return JIM_OK; 2337 + } 2338 + } 2339 + Jim_SetResultInt(interp, 1); 2340 + return JIM_OK; 2341 +} 2342 + 2258 2343 /* This is the core of the [format] command. 2259 2344 * TODO: Lots of things work - via a hack 2260 2345 * However, no format item can be >= JIM_MAX_FMT 2261 2346 */ 2262 2347 #define JIM_MAX_FMT 2048 2263 2348 static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr, 2264 2349 int objc, Jim_Obj *const *objv, char *sprintf_buf) ................................................................................ 12114 12199 /* [string] */ 12115 12200 static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 12116 12201 { 12117 12202 int len; 12118 12203 int opt_case = 1; 12119 12204 int option; 12120 12205 static const char *options[] = { 12121 - "length", "compare", "match", "equal", "range", "map", 12206 + "length", "compare", "match", "equal", "is", "range", "map", 12122 12207 "repeat", "reverse", "index", "first", "last", 12123 12208 "trim", "trimleft", "trimright", "tolower", "toupper", NULL 12124 12209 }; 12125 12210 enum 12126 12211 { 12127 - OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_RANGE, OPT_MAP, 12212 + OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_RANGE, OPT_MAP, 12128 12213 OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST, 12129 12214 OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER 12130 12215 }; 12131 12216 static const char *nocase_options[] = { 12132 12217 "-nocase", NULL 12133 12218 }; 12134 12219 ................................................................................ 12345 12430 if (option == OPT_TOLOWER) { 12346 12431 Jim_SetResult(interp, JimStringToLower(interp, argv[2])); 12347 12432 } 12348 12433 else { 12349 12434 Jim_SetResult(interp, JimStringToUpper(interp, argv[2])); 12350 12435 } 12351 12436 return JIM_OK; 12437 + 12438 + case OPT_IS: 12439 + if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) { 12440 + return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5); 12441 + } 12442 + Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str"); 12443 + return JIM_ERR; 12352 12444 } 12353 12445 return JIM_OK; 12354 12446 } 12355 12447 12356 12448 /* [time] */ 12357 12449 static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 12358 12450 {