Fossil SCM
Update Jim Tcl to 0.78.
Commit
907f66bfd80710ad7fe03804e1f4a9082c50955d74ff237aba8c7ff0bac26ed7
Parent
dbe16d7bb4cf720…
1 file changed
+3590
-3378
+3590
-3378
| --- autosetup/jimsh0.c | ||
| +++ autosetup/jimsh0.c | ||
| @@ -1,9 +1,7 @@ | ||
| 1 | 1 | /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */ |
| 2 | -#define _GNU_SOURCE | |
| 3 | 2 | #define JIM_TCL_COMPAT |
| 4 | -#define JIM_REFERENCES | |
| 5 | 3 | #define JIM_ANSIC |
| 6 | 4 | #define JIM_REGEXP |
| 7 | 5 | #define HAVE_NO_AUTOCONF |
| 8 | 6 | #define _JIMAUTOCONF_H |
| 9 | 7 | #define TCL_LIBRARY "." |
| @@ -31,24 +29,39 @@ | ||
| 31 | 29 | #define HAVE_MKDIR_ONE_ARG |
| 32 | 30 | #define HAVE_SYSTEM |
| 33 | 31 | #define HAVE_SYS_TIME_H |
| 34 | 32 | #define HAVE_DIRENT_H |
| 35 | 33 | #define HAVE_UNISTD_H |
| 34 | +#define HAVE_UMASK | |
| 35 | +#include <sys/stat.h> | |
| 36 | +#ifndef S_IRWXG | |
| 37 | +#define S_IRWXG 0 | |
| 38 | +#endif | |
| 39 | +#ifndef S_IRWXO | |
| 40 | +#define S_IRWXO 0 | |
| 41 | +#endif | |
| 36 | 42 | #else |
| 37 | 43 | #define TCL_PLATFORM_OS "unknown" |
| 38 | 44 | #define TCL_PLATFORM_PLATFORM "unix" |
| 39 | 45 | #define TCL_PLATFORM_PATH_SEPARATOR ":" |
| 46 | +#ifdef _MINIX | |
| 47 | +#define vfork fork | |
| 48 | +#define _POSIX_SOURCE | |
| 49 | +#else | |
| 50 | +#define _GNU_SOURCE | |
| 51 | +#endif | |
| 40 | 52 | #define HAVE_VFORK |
| 41 | 53 | #define HAVE_WAITPID |
| 42 | 54 | #define HAVE_ISATTY |
| 43 | 55 | #define HAVE_MKSTEMP |
| 44 | 56 | #define HAVE_LINK |
| 45 | 57 | #define HAVE_SYS_TIME_H |
| 46 | 58 | #define HAVE_DIRENT_H |
| 47 | 59 | #define HAVE_UNISTD_H |
| 60 | +#define HAVE_UMASK | |
| 48 | 61 | #endif |
| 49 | -#define JIM_VERSION 76 | |
| 62 | +#define JIM_VERSION 78 | |
| 50 | 63 | #ifndef JIM_WIN32COMPAT_H |
| 51 | 64 | #define JIM_WIN32COMPAT_H |
| 52 | 65 | |
| 53 | 66 | |
| 54 | 67 | |
| @@ -88,11 +101,10 @@ | ||
| 88 | 101 | #define JIM_WIDE_MIN LLONG_MIN |
| 89 | 102 | #define JIM_WIDE_MAX LLONG_MAX |
| 90 | 103 | #define JIM_WIDE_MODIFIER "I64d" |
| 91 | 104 | #define strcasecmp _stricmp |
| 92 | 105 | #define strtoull _strtoui64 |
| 93 | -#define snprintf _snprintf | |
| 94 | 106 | |
| 95 | 107 | #include <io.h> |
| 96 | 108 | |
| 97 | 109 | struct timeval { |
| 98 | 110 | long tv_sec; |
| @@ -105,29 +117,24 @@ | ||
| 105 | 117 | struct dirent { |
| 106 | 118 | char *d_name; |
| 107 | 119 | }; |
| 108 | 120 | |
| 109 | 121 | typedef struct DIR { |
| 110 | - long handle; | |
| 122 | + long handle; | |
| 111 | 123 | struct _finddata_t info; |
| 112 | - struct dirent result; | |
| 113 | - char *name; | |
| 124 | + struct dirent result; | |
| 125 | + char *name; | |
| 114 | 126 | } DIR; |
| 115 | 127 | |
| 116 | 128 | DIR *opendir(const char *name); |
| 117 | 129 | int closedir(DIR *dir); |
| 118 | 130 | struct dirent *readdir(DIR *dir); |
| 119 | 131 | |
| 120 | -#elif defined(__MINGW32__) | |
| 121 | - | |
| 122 | -#include <stdlib.h> | |
| 123 | -#define strtod __strtod | |
| 132 | +#endif | |
| 124 | 133 | |
| 125 | 134 | #endif |
| 126 | 135 | |
| 127 | -#endif | |
| 128 | - | |
| 129 | 136 | #ifdef __cplusplus |
| 130 | 137 | } |
| 131 | 138 | #endif |
| 132 | 139 | |
| 133 | 140 | #endif |
| @@ -146,19 +153,21 @@ | ||
| 146 | 153 | |
| 147 | 154 | #ifndef JIM_UTF8 |
| 148 | 155 | #include <ctype.h> |
| 149 | 156 | |
| 150 | 157 | |
| 151 | -#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) | |
| 158 | +#define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B)) | |
| 159 | +#define utf8_strwidth(S, B) utf8_strlen((S), (B)) | |
| 152 | 160 | #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) |
| 153 | 161 | #define utf8_getchars(CP, C) (*(CP) = (C), 1) |
| 154 | 162 | #define utf8_upper(C) toupper(C) |
| 155 | 163 | #define utf8_title(C) toupper(C) |
| 156 | 164 | #define utf8_lower(C) tolower(C) |
| 157 | 165 | #define utf8_index(C, I) (I) |
| 158 | 166 | #define utf8_charlen(C) 1 |
| 159 | 167 | #define utf8_prev_len(S, L) 1 |
| 168 | +#define utf8_width(C) 1 | |
| 160 | 169 | |
| 161 | 170 | #else |
| 162 | 171 | |
| 163 | 172 | #endif |
| 164 | 173 | |
| @@ -175,13 +184,13 @@ | ||
| 175 | 184 | extern "C" { |
| 176 | 185 | #endif |
| 177 | 186 | |
| 178 | 187 | #include <time.h> |
| 179 | 188 | #include <limits.h> |
| 180 | -#include <stdio.h> | |
| 181 | -#include <stdlib.h> | |
| 182 | -#include <stdarg.h> | |
| 189 | +#include <stdio.h> | |
| 190 | +#include <stdlib.h> | |
| 191 | +#include <stdarg.h> | |
| 183 | 192 | |
| 184 | 193 | |
| 185 | 194 | #ifndef HAVE_NO_AUTOCONF |
| 186 | 195 | #endif |
| 187 | 196 | |
| @@ -224,31 +233,31 @@ | ||
| 224 | 233 | #define JIM_SIGNAL 5 |
| 225 | 234 | #define JIM_EXIT 6 |
| 226 | 235 | |
| 227 | 236 | #define JIM_EVAL 7 |
| 228 | 237 | |
| 229 | -#define JIM_MAX_CALLFRAME_DEPTH 1000 | |
| 230 | -#define JIM_MAX_EVAL_DEPTH 2000 | |
| 238 | +#define JIM_MAX_CALLFRAME_DEPTH 1000 | |
| 239 | +#define JIM_MAX_EVAL_DEPTH 2000 | |
| 231 | 240 | |
| 232 | 241 | |
| 233 | 242 | #define JIM_PRIV_FLAG_SHIFT 20 |
| 234 | 243 | |
| 235 | -#define JIM_NONE 0 | |
| 236 | -#define JIM_ERRMSG 1 | |
| 237 | -#define JIM_ENUM_ABBREV 2 | |
| 238 | -#define JIM_UNSHARED 4 | |
| 239 | -#define JIM_MUSTEXIST 8 | |
| 240 | - | |
| 241 | - | |
| 242 | -#define JIM_SUBST_NOVAR 1 | |
| 243 | -#define JIM_SUBST_NOCMD 2 | |
| 244 | -#define JIM_SUBST_NOESC 4 | |
| 245 | -#define JIM_SUBST_FLAG 128 | |
| 246 | - | |
| 247 | - | |
| 248 | -#define JIM_CASESENS 0 | |
| 249 | -#define JIM_NOCASE 1 | |
| 244 | +#define JIM_NONE 0 | |
| 245 | +#define JIM_ERRMSG 1 | |
| 246 | +#define JIM_ENUM_ABBREV 2 | |
| 247 | +#define JIM_UNSHARED 4 | |
| 248 | +#define JIM_MUSTEXIST 8 | |
| 249 | + | |
| 250 | + | |
| 251 | +#define JIM_SUBST_NOVAR 1 | |
| 252 | +#define JIM_SUBST_NOCMD 2 | |
| 253 | +#define JIM_SUBST_NOESC 4 | |
| 254 | +#define JIM_SUBST_FLAG 128 | |
| 255 | + | |
| 256 | + | |
| 257 | +#define JIM_CASESENS 0 | |
| 258 | +#define JIM_NOCASE 1 | |
| 250 | 259 | |
| 251 | 260 | |
| 252 | 261 | #define JIM_PATH_LEN 1024 |
| 253 | 262 | |
| 254 | 263 | |
| @@ -339,79 +348,80 @@ | ||
| 339 | 348 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 340 | 349 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 341 | 350 | |
| 342 | 351 | |
| 343 | 352 | typedef struct Jim_Obj { |
| 344 | - char *bytes; | |
| 345 | - const struct Jim_ObjType *typePtr; | |
| 346 | - int refCount; | |
| 347 | - int length; | |
| 348 | - | |
| 353 | + char *bytes; | |
| 354 | + const struct Jim_ObjType *typePtr; | |
| 355 | + int refCount; | |
| 356 | + int length; | |
| 357 | + | |
| 349 | 358 | union { |
| 350 | - | |
| 359 | + | |
| 351 | 360 | jim_wide wideValue; |
| 352 | - | |
| 361 | + | |
| 353 | 362 | int intValue; |
| 354 | - | |
| 363 | + | |
| 355 | 364 | double doubleValue; |
| 356 | - | |
| 365 | + | |
| 357 | 366 | void *ptr; |
| 358 | - | |
| 367 | + | |
| 359 | 368 | struct { |
| 360 | 369 | void *ptr1; |
| 361 | 370 | void *ptr2; |
| 362 | 371 | } twoPtrValue; |
| 363 | - | |
| 372 | + | |
| 373 | + struct { | |
| 374 | + void *ptr; | |
| 375 | + int int1; | |
| 376 | + int int2; | |
| 377 | + } ptrIntValue; | |
| 378 | + | |
| 364 | 379 | struct { |
| 365 | 380 | struct Jim_Var *varPtr; |
| 366 | - unsigned long callFrameId; | |
| 367 | - int global; | |
| 381 | + unsigned long callFrameId; | |
| 382 | + int global; | |
| 368 | 383 | } varValue; |
| 369 | - | |
| 384 | + | |
| 370 | 385 | struct { |
| 371 | 386 | struct Jim_Obj *nsObj; |
| 372 | 387 | struct Jim_Cmd *cmdPtr; |
| 373 | - unsigned long procEpoch; | |
| 388 | + unsigned long procEpoch; | |
| 374 | 389 | } cmdValue; |
| 375 | - | |
| 390 | + | |
| 376 | 391 | struct { |
| 377 | - struct Jim_Obj **ele; | |
| 378 | - int len; | |
| 379 | - int maxLen; | |
| 392 | + struct Jim_Obj **ele; | |
| 393 | + int len; | |
| 394 | + int maxLen; | |
| 380 | 395 | } listValue; |
| 381 | - | |
| 396 | + | |
| 382 | 397 | struct { |
| 383 | 398 | int maxLength; |
| 384 | - int charLength; | |
| 399 | + int charLength; | |
| 385 | 400 | } strValue; |
| 386 | - | |
| 401 | + | |
| 387 | 402 | struct { |
| 388 | 403 | unsigned long id; |
| 389 | 404 | struct Jim_Reference *refPtr; |
| 390 | 405 | } refValue; |
| 391 | - | |
| 406 | + | |
| 392 | 407 | struct { |
| 393 | 408 | struct Jim_Obj *fileNameObj; |
| 394 | 409 | int lineNumber; |
| 395 | 410 | } sourceValue; |
| 396 | - | |
| 411 | + | |
| 397 | 412 | struct { |
| 398 | 413 | struct Jim_Obj *varNameObjPtr; |
| 399 | 414 | struct Jim_Obj *indexObjPtr; |
| 400 | 415 | } dictSubstValue; |
| 401 | - | |
| 402 | - struct { | |
| 403 | - void *compre; | |
| 404 | - unsigned flags; | |
| 405 | - } regexpValue; | |
| 406 | 416 | struct { |
| 407 | 417 | int line; |
| 408 | 418 | int argc; |
| 409 | 419 | } scriptLineValue; |
| 410 | 420 | } internalRep; |
| 411 | - struct Jim_Obj *prevObjPtr; | |
| 412 | - struct Jim_Obj *nextObjPtr; | |
| 421 | + struct Jim_Obj *prevObjPtr; | |
| 422 | + struct Jim_Obj *nextObjPtr; | |
| 413 | 423 | } Jim_Obj; |
| 414 | 424 | |
| 415 | 425 | |
| 416 | 426 | #define Jim_IncrRefCount(objPtr) \ |
| 417 | 427 | ++(objPtr)->refCount |
| @@ -442,40 +452,40 @@ | ||
| 442 | 452 | typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, |
| 443 | 453 | struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 444 | 454 | typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); |
| 445 | 455 | |
| 446 | 456 | typedef struct Jim_ObjType { |
| 447 | - const char *name; | |
| 457 | + const char *name; | |
| 448 | 458 | Jim_FreeInternalRepProc *freeIntRepProc; |
| 449 | 459 | Jim_DupInternalRepProc *dupIntRepProc; |
| 450 | 460 | Jim_UpdateStringProc *updateStringProc; |
| 451 | 461 | int flags; |
| 452 | 462 | } Jim_ObjType; |
| 453 | 463 | |
| 454 | 464 | |
| 455 | -#define JIM_TYPE_NONE 0 | |
| 456 | -#define JIM_TYPE_REFERENCES 1 | |
| 465 | +#define JIM_TYPE_NONE 0 | |
| 466 | +#define JIM_TYPE_REFERENCES 1 | |
| 457 | 467 | |
| 458 | 468 | |
| 459 | 469 | |
| 460 | 470 | typedef struct Jim_CallFrame { |
| 461 | - unsigned long id; | |
| 462 | - int level; | |
| 463 | - struct Jim_HashTable vars; | |
| 464 | - struct Jim_HashTable *staticVars; | |
| 465 | - struct Jim_CallFrame *parent; | |
| 466 | - Jim_Obj *const *argv; | |
| 467 | - int argc; | |
| 468 | - Jim_Obj *procArgsObjPtr; | |
| 469 | - Jim_Obj *procBodyObjPtr; | |
| 470 | - struct Jim_CallFrame *next; | |
| 471 | - Jim_Obj *nsObj; | |
| 472 | - Jim_Obj *fileNameObj; | |
| 471 | + unsigned long id; | |
| 472 | + int level; | |
| 473 | + struct Jim_HashTable vars; | |
| 474 | + struct Jim_HashTable *staticVars; | |
| 475 | + struct Jim_CallFrame *parent; | |
| 476 | + Jim_Obj *const *argv; | |
| 477 | + int argc; | |
| 478 | + Jim_Obj *procArgsObjPtr; | |
| 479 | + Jim_Obj *procBodyObjPtr; | |
| 480 | + struct Jim_CallFrame *next; | |
| 481 | + Jim_Obj *nsObj; | |
| 482 | + Jim_Obj *fileNameObj; | |
| 473 | 483 | int line; |
| 474 | - Jim_Stack *localCommands; | |
| 475 | - struct Jim_Obj *tailcallObj; | |
| 476 | - struct Jim_Cmd *tailcallCmd; | |
| 484 | + Jim_Stack *localCommands; | |
| 485 | + struct Jim_Obj *tailcallObj; | |
| 486 | + struct Jim_Cmd *tailcallCmd; | |
| 477 | 487 | } Jim_CallFrame; |
| 478 | 488 | |
| 479 | 489 | typedef struct Jim_Var { |
| 480 | 490 | Jim_Obj *objPtr; |
| 481 | 491 | struct Jim_CallFrame *linkFramePtr; |
| @@ -487,35 +497,35 @@ | ||
| 487 | 497 | typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); |
| 488 | 498 | |
| 489 | 499 | |
| 490 | 500 | |
| 491 | 501 | typedef struct Jim_Cmd { |
| 492 | - int inUse; | |
| 493 | - int isproc; | |
| 494 | - struct Jim_Cmd *prevCmd; | |
| 502 | + int inUse; | |
| 503 | + int isproc; | |
| 504 | + struct Jim_Cmd *prevCmd; | |
| 495 | 505 | union { |
| 496 | 506 | struct { |
| 497 | - | |
| 498 | - Jim_CmdProc *cmdProc; | |
| 499 | - Jim_DelCmdProc *delProc; | |
| 500 | - void *privData; | |
| 507 | + | |
| 508 | + Jim_CmdProc *cmdProc; | |
| 509 | + Jim_DelCmdProc *delProc; | |
| 510 | + void *privData; | |
| 501 | 511 | } native; |
| 502 | 512 | struct { |
| 503 | - | |
| 513 | + | |
| 504 | 514 | Jim_Obj *argListObjPtr; |
| 505 | 515 | Jim_Obj *bodyObjPtr; |
| 506 | - Jim_HashTable *staticVars; | |
| 507 | - int argListLen; | |
| 508 | - int reqArity; | |
| 509 | - int optArity; | |
| 510 | - int argsPos; | |
| 511 | - int upcall; | |
| 516 | + Jim_HashTable *staticVars; | |
| 517 | + int argListLen; | |
| 518 | + int reqArity; | |
| 519 | + int optArity; | |
| 520 | + int argsPos; | |
| 521 | + int upcall; | |
| 512 | 522 | struct Jim_ProcArg { |
| 513 | - Jim_Obj *nameObjPtr; | |
| 514 | - Jim_Obj *defaultObjPtr; | |
| 523 | + Jim_Obj *nameObjPtr; | |
| 524 | + Jim_Obj *defaultObjPtr; | |
| 515 | 525 | } *arglist; |
| 516 | - Jim_Obj *nsObj; | |
| 526 | + Jim_Obj *nsObj; | |
| 517 | 527 | } proc; |
| 518 | 528 | } u; |
| 519 | 529 | } Jim_Cmd; |
| 520 | 530 | |
| 521 | 531 | |
| @@ -523,64 +533,64 @@ | ||
| 523 | 533 | unsigned char sbox[256]; |
| 524 | 534 | unsigned int i, j; |
| 525 | 535 | } Jim_PrngState; |
| 526 | 536 | |
| 527 | 537 | typedef struct Jim_Interp { |
| 528 | - Jim_Obj *result; | |
| 529 | - int errorLine; | |
| 530 | - Jim_Obj *errorFileNameObj; | |
| 531 | - int addStackTrace; | |
| 532 | - int maxCallFrameDepth; | |
| 533 | - int maxEvalDepth; | |
| 534 | - int evalDepth; | |
| 535 | - int returnCode; | |
| 536 | - int returnLevel; | |
| 537 | - int exitCode; | |
| 538 | - long id; | |
| 539 | - int signal_level; | |
| 540 | - jim_wide sigmask; | |
| 541 | - int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); | |
| 542 | - Jim_CallFrame *framePtr; | |
| 543 | - Jim_CallFrame *topFramePtr; | |
| 544 | - struct Jim_HashTable commands; | |
| 538 | + Jim_Obj *result; | |
| 539 | + int errorLine; | |
| 540 | + Jim_Obj *errorFileNameObj; | |
| 541 | + int addStackTrace; | |
| 542 | + int maxCallFrameDepth; | |
| 543 | + int maxEvalDepth; | |
| 544 | + int evalDepth; | |
| 545 | + int returnCode; | |
| 546 | + int returnLevel; | |
| 547 | + int exitCode; | |
| 548 | + long id; | |
| 549 | + int signal_level; | |
| 550 | + jim_wide sigmask; | |
| 551 | + int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); | |
| 552 | + Jim_CallFrame *framePtr; | |
| 553 | + Jim_CallFrame *topFramePtr; | |
| 554 | + struct Jim_HashTable commands; | |
| 545 | 555 | unsigned long procEpoch; /* Incremented every time the result |
| 546 | 556 | of procedures names lookup caching |
| 547 | 557 | may no longer be valid. */ |
| 548 | 558 | unsigned long callFrameEpoch; /* Incremented every time a new |
| 549 | 559 | callframe is created. This id is used for the |
| 550 | 560 | 'ID' field contained in the Jim_CallFrame |
| 551 | 561 | structure. */ |
| 552 | - int local; | |
| 553 | - Jim_Obj *liveList; | |
| 554 | - Jim_Obj *freeList; | |
| 555 | - Jim_Obj *currentScriptObj; | |
| 556 | - Jim_Obj *nullScriptObj; | |
| 557 | - Jim_Obj *emptyObj; | |
| 558 | - Jim_Obj *trueObj; | |
| 559 | - Jim_Obj *falseObj; | |
| 560 | - unsigned long referenceNextId; | |
| 561 | - struct Jim_HashTable references; | |
| 562 | + int local; | |
| 563 | + Jim_Obj *liveList; | |
| 564 | + Jim_Obj *freeList; | |
| 565 | + Jim_Obj *currentScriptObj; | |
| 566 | + Jim_Obj *nullScriptObj; | |
| 567 | + Jim_Obj *emptyObj; | |
| 568 | + Jim_Obj *trueObj; | |
| 569 | + Jim_Obj *falseObj; | |
| 570 | + unsigned long referenceNextId; | |
| 571 | + struct Jim_HashTable references; | |
| 562 | 572 | unsigned long lastCollectId; /* reference max Id of the last GC |
| 563 | 573 | execution. It's set to -1 while the collection |
| 564 | 574 | is running as sentinel to avoid to recursive |
| 565 | 575 | calls via the [collect] command inside |
| 566 | 576 | finalizers. */ |
| 567 | - time_t lastCollectTime; | |
| 568 | - Jim_Obj *stackTrace; | |
| 569 | - Jim_Obj *errorProc; | |
| 570 | - Jim_Obj *unknown; | |
| 571 | - int unknown_called; | |
| 572 | - int errorFlag; | |
| 577 | + time_t lastCollectTime; | |
| 578 | + Jim_Obj *stackTrace; | |
| 579 | + Jim_Obj *errorProc; | |
| 580 | + Jim_Obj *unknown; | |
| 581 | + int unknown_called; | |
| 582 | + int errorFlag; | |
| 573 | 583 | void *cmdPrivData; /* Used to pass the private data pointer to |
| 574 | 584 | a command. It is set to what the user specified |
| 575 | 585 | via Jim_CreateCommand(). */ |
| 576 | 586 | |
| 577 | - struct Jim_CallFrame *freeFramesList; | |
| 578 | - struct Jim_HashTable assocData; | |
| 579 | - Jim_PrngState *prngState; | |
| 580 | - struct Jim_HashTable packages; | |
| 581 | - Jim_Stack *loadHandles; | |
| 587 | + struct Jim_CallFrame *freeFramesList; | |
| 588 | + struct Jim_HashTable assocData; | |
| 589 | + Jim_PrngState *prngState; | |
| 590 | + struct Jim_HashTable packages; | |
| 591 | + Jim_Stack *loadHandles; | |
| 582 | 592 | } Jim_Interp; |
| 583 | 593 | |
| 584 | 594 | #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ |
| 585 | 595 | #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) |
| 586 | 596 | #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) |
| @@ -623,11 +633,11 @@ | ||
| 623 | 633 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 624 | 634 | |
| 625 | 635 | |
| 626 | 636 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 627 | 637 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 628 | -JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template); | |
| 638 | +JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file); | |
| 629 | 639 | |
| 630 | 640 | |
| 631 | 641 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 632 | 642 | |
| 633 | 643 | |
| @@ -816,25 +826,33 @@ | ||
| 816 | 826 | Jim_Obj *newObjPtr, int flags); |
| 817 | 827 | JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, |
| 818 | 828 | Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); |
| 819 | 829 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 820 | 830 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 821 | -JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); | |
| 822 | -JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); | |
| 831 | + | |
| 832 | +#define JIM_DICTMATCH_KEYS 0x0001 | |
| 833 | +#define JIM_DICTMATCH_VALUES 0x002 | |
| 834 | + | |
| 835 | +JIM_EXPORT int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types); | |
| 823 | 836 | JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); |
| 824 | 837 | JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); |
| 838 | +JIM_EXPORT Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv); | |
| 825 | 839 | |
| 826 | 840 | |
| 827 | 841 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, |
| 828 | 842 | int *intPtr); |
| 829 | 843 | |
| 830 | 844 | |
| 831 | 845 | JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, |
| 832 | - Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr); | |
| 846 | + Jim_Obj *exprObjPtr); | |
| 833 | 847 | JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, |
| 834 | 848 | Jim_Obj *exprObjPtr, int *boolPtr); |
| 835 | 849 | |
| 850 | + | |
| 851 | +JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, | |
| 852 | + int *booleanPtr); | |
| 853 | + | |
| 836 | 854 | |
| 837 | 855 | JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, |
| 838 | 856 | jim_wide *widePtr); |
| 839 | 857 | JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, |
| 840 | 858 | long *longPtr); |
| @@ -852,10 +870,12 @@ | ||
| 852 | 870 | |
| 853 | 871 | JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, |
| 854 | 872 | Jim_Obj *const *argv, const char *msg); |
| 855 | 873 | JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, |
| 856 | 874 | const char * const *tablePtr, int *indexPtr, const char *name, int flags); |
| 875 | +JIM_EXPORT int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, | |
| 876 | + const char *const *tablePtr); | |
| 857 | 877 | JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp, |
| 858 | 878 | Jim_Obj *scriptObj, char *stateCharPtr); |
| 859 | 879 | |
| 860 | 880 | JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); |
| 861 | 881 | |
| @@ -878,11 +898,12 @@ | ||
| 878 | 898 | |
| 879 | 899 | |
| 880 | 900 | JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); |
| 881 | 901 | JIM_EXPORT void Jim_HistoryLoad(const char *filename); |
| 882 | 902 | JIM_EXPORT void Jim_HistorySave(const char *filename); |
| 883 | -JIM_EXPORT char *Jim_HistoryGetline(const char *prompt); | |
| 903 | +JIM_EXPORT char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt); | |
| 904 | +JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj); | |
| 884 | 905 | JIM_EXPORT void Jim_HistoryAdd(const char *line); |
| 885 | 906 | JIM_EXPORT void Jim_HistoryShow(void); |
| 886 | 907 | |
| 887 | 908 | |
| 888 | 909 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| @@ -904,11 +925,11 @@ | ||
| 904 | 925 | |
| 905 | 926 | #ifdef __cplusplus |
| 906 | 927 | } |
| 907 | 928 | #endif |
| 908 | 929 | |
| 909 | -#endif | |
| 930 | +#endif | |
| 910 | 931 | |
| 911 | 932 | #ifndef JIM_SUBCMD_H |
| 912 | 933 | #define JIM_SUBCMD_H |
| 913 | 934 | |
| 914 | 935 | |
| @@ -915,24 +936,24 @@ | ||
| 915 | 936 | #ifdef __cplusplus |
| 916 | 937 | extern "C" { |
| 917 | 938 | #endif |
| 918 | 939 | |
| 919 | 940 | |
| 920 | -#define JIM_MODFLAG_HIDDEN 0x0001 | |
| 921 | -#define JIM_MODFLAG_FULLARGV 0x0002 | |
| 941 | +#define JIM_MODFLAG_HIDDEN 0x0001 | |
| 942 | +#define JIM_MODFLAG_FULLARGV 0x0002 | |
| 922 | 943 | |
| 923 | 944 | |
| 924 | 945 | |
| 925 | 946 | typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 926 | 947 | |
| 927 | 948 | typedef struct { |
| 928 | - const char *cmd; | |
| 929 | - const char *args; | |
| 930 | - jim_subcmd_function *function; | |
| 931 | - short minargs; | |
| 932 | - short maxargs; | |
| 933 | - unsigned short flags; | |
| 949 | + const char *cmd; | |
| 950 | + const char *args; | |
| 951 | + jim_subcmd_function *function; | |
| 952 | + short minargs; | |
| 953 | + short maxargs; | |
| 954 | + unsigned short flags; | |
| 934 | 955 | } jim_subcmd_type; |
| 935 | 956 | |
| 936 | 957 | const jim_subcmd_type * |
| 937 | 958 | Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); |
| 938 | 959 | |
| @@ -960,36 +981,36 @@ | ||
| 960 | 981 | int rm_eo; |
| 961 | 982 | } regmatch_t; |
| 962 | 983 | |
| 963 | 984 | |
| 964 | 985 | typedef struct regexp { |
| 965 | - | |
| 966 | - int re_nsub; | |
| 967 | - | |
| 968 | - | |
| 969 | - int cflags; | |
| 970 | - int err; | |
| 971 | - int regstart; | |
| 972 | - int reganch; | |
| 973 | - int regmust; | |
| 974 | - int regmlen; | |
| 975 | - int *program; | |
| 976 | - | |
| 977 | - | |
| 978 | - const char *regparse; | |
| 979 | - int p; | |
| 980 | - int proglen; | |
| 981 | - | |
| 982 | - | |
| 983 | - int eflags; | |
| 984 | - const char *start; | |
| 985 | - const char *reginput; | |
| 986 | - const char *regbol; | |
| 987 | - | |
| 988 | - | |
| 989 | - regmatch_t *pmatch; | |
| 990 | - int nmatch; | |
| 986 | + | |
| 987 | + int re_nsub; | |
| 988 | + | |
| 989 | + | |
| 990 | + int cflags; | |
| 991 | + int err; | |
| 992 | + int regstart; | |
| 993 | + int reganch; | |
| 994 | + int regmust; | |
| 995 | + int regmlen; | |
| 996 | + int *program; | |
| 997 | + | |
| 998 | + | |
| 999 | + const char *regparse; | |
| 1000 | + int p; | |
| 1001 | + int proglen; | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + int eflags; | |
| 1005 | + const char *start; | |
| 1006 | + const char *reginput; | |
| 1007 | + const char *regbol; | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + regmatch_t *pmatch; | |
| 1011 | + int nmatch; | |
| 991 | 1012 | } regexp; |
| 992 | 1013 | |
| 993 | 1014 | typedef regexp regex_t; |
| 994 | 1015 | |
| 995 | 1016 | #define REG_EXTENDED 0 |
| @@ -997,13 +1018,13 @@ | ||
| 997 | 1018 | #define REG_ICASE 2 |
| 998 | 1019 | |
| 999 | 1020 | #define REG_NOTBOL 16 |
| 1000 | 1021 | |
| 1001 | 1022 | enum { |
| 1002 | - REG_NOERROR, | |
| 1003 | - REG_NOMATCH, | |
| 1004 | - REG_BADPAT, | |
| 1023 | + REG_NOERROR, | |
| 1024 | + REG_NOMATCH, | |
| 1025 | + REG_BADPAT, | |
| 1005 | 1026 | REG_ERR_NULL_ARGUMENT, |
| 1006 | 1027 | REG_ERR_UNKNOWN, |
| 1007 | 1028 | REG_ERR_TOO_BIG, |
| 1008 | 1029 | REG_ERR_NOMEM, |
| 1009 | 1030 | REG_ERR_TOO_MANY_PAREN, |
| @@ -1027,10 +1048,83 @@ | ||
| 1027 | 1048 | void regfree(regex_t *preg); |
| 1028 | 1049 | |
| 1029 | 1050 | #ifdef __cplusplus |
| 1030 | 1051 | } |
| 1031 | 1052 | #endif |
| 1053 | + | |
| 1054 | +#endif | |
| 1055 | +#ifndef JIM_SIGNAL_H | |
| 1056 | +#define JIM_SIGNAL_H | |
| 1057 | + | |
| 1058 | +#ifdef __cplusplus | |
| 1059 | +extern "C" { | |
| 1060 | +#endif | |
| 1061 | + | |
| 1062 | +const char *Jim_SignalId(int sig); | |
| 1063 | + | |
| 1064 | +#ifdef __cplusplus | |
| 1065 | +} | |
| 1066 | +#endif | |
| 1067 | + | |
| 1068 | +#endif | |
| 1069 | +#ifndef JIMIOCOMPAT_H | |
| 1070 | +#define JIMIOCOMPAT_H | |
| 1071 | + | |
| 1072 | + | |
| 1073 | +#include <stdio.h> | |
| 1074 | +#include <errno.h> | |
| 1075 | + | |
| 1076 | + | |
| 1077 | +void Jim_SetResultErrno(Jim_Interp *interp, const char *msg); | |
| 1078 | + | |
| 1079 | +int Jim_OpenForWrite(const char *filename, int append); | |
| 1080 | + | |
| 1081 | +int Jim_OpenForRead(const char *filename); | |
| 1082 | + | |
| 1083 | +#if defined(__MINGW32__) | |
| 1084 | + #ifndef STRICT | |
| 1085 | + #define STRICT | |
| 1086 | + #endif | |
| 1087 | + #define WIN32_LEAN_AND_MEAN | |
| 1088 | + #include <windows.h> | |
| 1089 | + #include <fcntl.h> | |
| 1090 | + #include <io.h> | |
| 1091 | + #include <process.h> | |
| 1092 | + | |
| 1093 | + typedef HANDLE pidtype; | |
| 1094 | + #define JIM_BAD_PID INVALID_HANDLE_VALUE | |
| 1095 | + | |
| 1096 | + #define JIM_NO_PID INVALID_HANDLE_VALUE | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + #define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0) | |
| 1100 | + #define WEXITSTATUS(STATUS) ((STATUS) & 0x00ff) | |
| 1101 | + #define WIFSIGNALED(STATUS) (((STATUS) & 0xff00) != 0) | |
| 1102 | + #define WTERMSIG(STATUS) (((STATUS) >> 8) & 0xff) | |
| 1103 | + #define WNOHANG 1 | |
| 1104 | + | |
| 1105 | + int Jim_Errno(void); | |
| 1106 | + pidtype waitpid(pidtype pid, int *status, int nohang); | |
| 1107 | + | |
| 1108 | + #define HAVE_PIPE | |
| 1109 | + #define pipe(P) _pipe((P), 0, O_NOINHERIT) | |
| 1110 | + | |
| 1111 | +#elif defined(HAVE_UNISTD_H) | |
| 1112 | + #include <unistd.h> | |
| 1113 | + #include <fcntl.h> | |
| 1114 | + #include <sys/wait.h> | |
| 1115 | + #include <sys/stat.h> | |
| 1116 | + | |
| 1117 | + typedef int pidtype; | |
| 1118 | + #define Jim_Errno() errno | |
| 1119 | + #define JIM_BAD_PID -1 | |
| 1120 | + #define JIM_NO_PID 0 | |
| 1121 | + | |
| 1122 | + #ifndef HAVE_EXECVPE | |
| 1123 | + #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) | |
| 1124 | + #endif | |
| 1125 | +#endif | |
| 1032 | 1126 | |
| 1033 | 1127 | #endif |
| 1034 | 1128 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1035 | 1129 | { |
| 1036 | 1130 | if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG)) |
| @@ -1100,10 +1194,43 @@ | ||
| 1100 | 1194 | "\n" |
| 1101 | 1195 | "if {$tcl_platform(platform) eq \"windows\"} {\n" |
| 1102 | 1196 | " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n" |
| 1103 | 1197 | "}\n" |
| 1104 | 1198 | "\n" |
| 1199 | +"\n" | |
| 1200 | +"set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n" | |
| 1201 | +"\n" | |
| 1202 | +"\n" | |
| 1203 | +"\n" | |
| 1204 | +"proc tcl::autocomplete {prefix} {\n" | |
| 1205 | +" if {[set space [string first \" \" $prefix]] != -1} {\n" | |
| 1206 | +" set cmd [string range $prefix 0 $space-1]\n" | |
| 1207 | +" if {$cmd in $::tcl::autocomplete_commands || [info channel $cmd] ne \"\"} {\n" | |
| 1208 | +" set arg [string range $prefix $space+1 end]\n" | |
| 1209 | +"\n" | |
| 1210 | +" return [lmap p [$cmd -commands] {\n" | |
| 1211 | +" if {![string match \"${arg}*\" $p]} continue\n" | |
| 1212 | +" function \"$cmd $p\"\n" | |
| 1213 | +" }]\n" | |
| 1214 | +" }\n" | |
| 1215 | +" }\n" | |
| 1216 | +"\n" | |
| 1217 | +" if {[string match \"source *\" $prefix]} {\n" | |
| 1218 | +" set path [string range $prefix 7 end]\n" | |
| 1219 | +" return [lmap p [glob -nocomplain \"${path}*\"] {\n" | |
| 1220 | +" function \"source $p\"\n" | |
| 1221 | +" }]\n" | |
| 1222 | +" }\n" | |
| 1223 | +"\n" | |
| 1224 | +" return [lmap p [lsort [info commands $prefix*]] {\n" | |
| 1225 | +" if {[string match \"* *\" $p]} {\n" | |
| 1226 | +" continue\n" | |
| 1227 | +" }\n" | |
| 1228 | +" function $p\n" | |
| 1229 | +" }]\n" | |
| 1230 | +"}\n" | |
| 1231 | +"\n" | |
| 1105 | 1232 | "_jimsh_init\n" |
| 1106 | 1233 | ); |
| 1107 | 1234 | } |
| 1108 | 1235 | int Jim_globInit(Jim_Interp *interp) |
| 1109 | 1236 | { |
| @@ -1315,10 +1442,17 @@ | ||
| 1315 | 1442 | return JIM_ERR; |
| 1316 | 1443 | |
| 1317 | 1444 | return Jim_EvalSource(interp, "stdlib.tcl", 1, |
| 1318 | 1445 | "\n" |
| 1319 | 1446 | "\n" |
| 1447 | +"if {![exists -command ref]} {\n" | |
| 1448 | +"\n" | |
| 1449 | +" proc ref {args} {{count 0}} {\n" | |
| 1450 | +" format %08x [incr count]\n" | |
| 1451 | +" }\n" | |
| 1452 | +"}\n" | |
| 1453 | +"\n" | |
| 1320 | 1454 | "\n" |
| 1321 | 1455 | "proc lambda {arglist args} {\n" |
| 1322 | 1456 | " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" |
| 1323 | 1457 | "}\n" |
| 1324 | 1458 | "\n" |
| @@ -1375,10 +1509,17 @@ | ||
| 1375 | 1509 | " }\n" |
| 1376 | 1510 | " join $lines \\n\n" |
| 1377 | 1511 | "}\n" |
| 1378 | 1512 | "\n" |
| 1379 | 1513 | "\n" |
| 1514 | +"\n" | |
| 1515 | +"proc defer {script} {\n" | |
| 1516 | +" upvar jim::defer v\n" | |
| 1517 | +" lappend v $script\n" | |
| 1518 | +"}\n" | |
| 1519 | +"\n" | |
| 1520 | +"\n" | |
| 1380 | 1521 | "\n" |
| 1381 | 1522 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1382 | 1523 | " if {$stacktrace eq \"\"} {\n" |
| 1383 | 1524 | "\n" |
| 1384 | 1525 | " set stacktrace [info stacktrace]\n" |
| @@ -1402,31 +1543,10 @@ | ||
| 1402 | 1543 | " if {[exists ::jim::exe]} {\n" |
| 1403 | 1544 | " return $::jim::exe\n" |
| 1404 | 1545 | " }\n" |
| 1405 | 1546 | "}\n" |
| 1406 | 1547 | "\n" |
| 1407 | -"\n" | |
| 1408 | -"proc {dict with} {&dictVar {args key} script} {\n" | |
| 1409 | -" set keys {}\n" | |
| 1410 | -" foreach {n v} [dict get $dictVar {*}$key] {\n" | |
| 1411 | -" upvar $n var_$n\n" | |
| 1412 | -" set var_$n $v\n" | |
| 1413 | -" lappend keys $n\n" | |
| 1414 | -" }\n" | |
| 1415 | -" catch {uplevel 1 $script} msg opts\n" | |
| 1416 | -" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n" | |
| 1417 | -" foreach n $keys {\n" | |
| 1418 | -" if {[info exists var_$n]} {\n" | |
| 1419 | -" dict set dictVar {*}$key $n [set var_$n]\n" | |
| 1420 | -" } else {\n" | |
| 1421 | -" dict unset dictVar {*}$key $n\n" | |
| 1422 | -" }\n" | |
| 1423 | -" }\n" | |
| 1424 | -" }\n" | |
| 1425 | -" return {*}$opts $msg\n" | |
| 1426 | -"}\n" | |
| 1427 | -"\n" | |
| 1428 | 1548 | "\n" |
| 1429 | 1549 | "proc {dict update} {&varName args script} {\n" |
| 1430 | 1550 | " set keys {}\n" |
| 1431 | 1551 | " foreach {n v} $args {\n" |
| 1432 | 1552 | " upvar $v var_$v\n" |
| @@ -1445,23 +1565,10 @@ | ||
| 1445 | 1565 | " }\n" |
| 1446 | 1566 | " }\n" |
| 1447 | 1567 | " return {*}$opts $msg\n" |
| 1448 | 1568 | "}\n" |
| 1449 | 1569 | "\n" |
| 1450 | -"\n" | |
| 1451 | -"\n" | |
| 1452 | -"proc {dict merge} {dict args} {\n" | |
| 1453 | -" foreach d $args {\n" | |
| 1454 | -"\n" | |
| 1455 | -" dict size $d\n" | |
| 1456 | -" foreach {k v} $d {\n" | |
| 1457 | -" dict set dict $k $v\n" | |
| 1458 | -" }\n" | |
| 1459 | -" }\n" | |
| 1460 | -" return $dict\n" | |
| 1461 | -"}\n" | |
| 1462 | -"\n" | |
| 1463 | 1570 | "proc {dict replace} {dictionary {args {key value}}} {\n" |
| 1464 | 1571 | " if {[llength ${key value}] % 2} {\n" |
| 1465 | 1572 | " tailcall {dict replace}\n" |
| 1466 | 1573 | " }\n" |
| 1467 | 1574 | " tailcall dict merge $dictionary ${key value}\n" |
| @@ -1503,15 +1610,10 @@ | ||
| 1503 | 1610 | " dict unset dictionary $k\n" |
| 1504 | 1611 | " }\n" |
| 1505 | 1612 | " return $dictionary\n" |
| 1506 | 1613 | "}\n" |
| 1507 | 1614 | "\n" |
| 1508 | -"\n" | |
| 1509 | -"proc {dict values} {dictionary {pattern *}} {\n" | |
| 1510 | -" dict keys [lreverse $dictionary] $pattern\n" | |
| 1511 | -"}\n" | |
| 1512 | -"\n" | |
| 1513 | 1615 | "\n" |
| 1514 | 1616 | "proc {dict for} {vars dictionary script} {\n" |
| 1515 | 1617 | " if {[llength $vars] != 2} {\n" |
| 1516 | 1618 | " return -code error \"must have exactly two variable names\"\n" |
| 1517 | 1619 | " }\n" |
| @@ -1591,11 +1693,10 @@ | ||
| 1591 | 1693 | " tailcall {*}$args\n" |
| 1592 | 1694 | "}\n" |
| 1593 | 1695 | "\n" |
| 1594 | 1696 | "\n" |
| 1595 | 1697 | "\n" |
| 1596 | -"\n" | |
| 1597 | 1698 | "proc parray {arrayname {pattern *} {puts puts}} {\n" |
| 1598 | 1699 | " upvar $arrayname a\n" |
| 1599 | 1700 | "\n" |
| 1600 | 1701 | " set max 0\n" |
| 1601 | 1702 | " foreach name [array names a $pattern]] {\n" |
| @@ -1647,11 +1748,11 @@ | ||
| 1647 | 1748 | "}\n" |
| 1648 | 1749 | "\n" |
| 1649 | 1750 | "\n" |
| 1650 | 1751 | "\n" |
| 1651 | 1752 | "proc popen {cmd {mode r}} {\n" |
| 1652 | -" lassign [socket pipe] r w\n" | |
| 1753 | +" lassign [pipe] r w\n" | |
| 1653 | 1754 | " try {\n" |
| 1654 | 1755 | " if {[string match \"w*\" $mode]} {\n" |
| 1655 | 1756 | " lappend cmd <@$r &\n" |
| 1656 | 1757 | " set pids [exec {*}$cmd]\n" |
| 1657 | 1758 | " $r close\n" |
| @@ -1663,16 +1764,31 @@ | ||
| 1663 | 1764 | " set f $r\n" |
| 1664 | 1765 | " }\n" |
| 1665 | 1766 | " lambda {cmd args} {f pids} {\n" |
| 1666 | 1767 | " if {$cmd eq \"pid\"} {\n" |
| 1667 | 1768 | " return $pids\n" |
| 1769 | +" }\n" | |
| 1770 | +" if {$cmd eq \"getfd\"} {\n" | |
| 1771 | +" $f getfd\n" | |
| 1668 | 1772 | " }\n" |
| 1669 | 1773 | " if {$cmd eq \"close\"} {\n" |
| 1670 | 1774 | " $f close\n" |
| 1671 | 1775 | "\n" |
| 1672 | -" foreach p $pids { os.wait $p }\n" | |
| 1673 | -" return\n" | |
| 1776 | +" set retopts {}\n" | |
| 1777 | +" foreach p $pids {\n" | |
| 1778 | +" lassign [wait $p] status - rc\n" | |
| 1779 | +" if {$status eq \"CHILDSTATUS\"} {\n" | |
| 1780 | +" if {$rc == 0} {\n" | |
| 1781 | +" continue\n" | |
| 1782 | +" }\n" | |
| 1783 | +" set msg \"child process exited abnormally\"\n" | |
| 1784 | +" } else {\n" | |
| 1785 | +" set msg \"child killed: received signal\"\n" | |
| 1786 | +" }\n" | |
| 1787 | +" set retopts [list -code error -errorcode [list $status $p $rc] $msg]\n" | |
| 1788 | +" }\n" | |
| 1789 | +" return {*}$retopts\n" | |
| 1674 | 1790 | " }\n" |
| 1675 | 1791 | " tailcall $f $cmd {*}$args\n" |
| 1676 | 1792 | " }\n" |
| 1677 | 1793 | " } on error {error opts} {\n" |
| 1678 | 1794 | " $r close\n" |
| @@ -1692,14 +1808,10 @@ | ||
| 1692 | 1808 | " if {[catch {$channelId pid} pids]} {\n" |
| 1693 | 1809 | " return \"\"\n" |
| 1694 | 1810 | " }\n" |
| 1695 | 1811 | " return $pids\n" |
| 1696 | 1812 | "}\n" |
| 1697 | -"\n" | |
| 1698 | -"\n" | |
| 1699 | -"\n" | |
| 1700 | -"\n" | |
| 1701 | 1813 | "\n" |
| 1702 | 1814 | "\n" |
| 1703 | 1815 | "\n" |
| 1704 | 1816 | "\n" |
| 1705 | 1817 | "\n" |
| @@ -1780,10 +1892,13 @@ | ||
| 1780 | 1892 | "}\n" |
| 1781 | 1893 | ); |
| 1782 | 1894 | } |
| 1783 | 1895 | |
| 1784 | 1896 | |
| 1897 | +#ifndef _GNU_SOURCE | |
| 1898 | +#define _GNU_SOURCE | |
| 1899 | +#endif | |
| 1785 | 1900 | #include <stdio.h> |
| 1786 | 1901 | #include <string.h> |
| 1787 | 1902 | #include <errno.h> |
| 1788 | 1903 | #include <fcntl.h> |
| 1789 | 1904 | #ifdef HAVE_UNISTD_H |
| @@ -1793,27 +1908,34 @@ | ||
| 1793 | 1908 | |
| 1794 | 1909 | |
| 1795 | 1910 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1796 | 1911 | #include <sys/socket.h> |
| 1797 | 1912 | #include <netinet/in.h> |
| 1913 | +#include <netinet/tcp.h> | |
| 1798 | 1914 | #include <arpa/inet.h> |
| 1799 | 1915 | #include <netdb.h> |
| 1800 | 1916 | #ifdef HAVE_SYS_UN_H |
| 1801 | 1917 | #include <sys/un.h> |
| 1802 | 1918 | #endif |
| 1919 | +#define HAVE_SOCKETS | |
| 1920 | +#elif defined (__MINGW32__) | |
| 1921 | + | |
| 1803 | 1922 | #else |
| 1804 | 1923 | #define JIM_ANSIC |
| 1805 | 1924 | #endif |
| 1806 | 1925 | |
| 1807 | 1926 | #if defined(JIM_SSL) |
| 1808 | 1927 | #include <openssl/ssl.h> |
| 1809 | 1928 | #include <openssl/err.h> |
| 1810 | 1929 | #endif |
| 1811 | 1930 | |
| 1931 | +#ifdef HAVE_TERMIOS_H | |
| 1932 | +#endif | |
| 1812 | 1933 | |
| 1813 | -#define AIO_CMD_LEN 32 | |
| 1814 | -#define AIO_BUF_LEN 256 | |
| 1934 | + | |
| 1935 | +#define AIO_CMD_LEN 32 | |
| 1936 | +#define AIO_BUF_LEN 256 | |
| 1815 | 1937 | |
| 1816 | 1938 | #ifndef HAVE_FTELLO |
| 1817 | 1939 | #define ftello ftell |
| 1818 | 1940 | #endif |
| 1819 | 1941 | #ifndef HAVE_FSEEKO |
| @@ -1828,10 +1950,16 @@ | ||
| 1828 | 1950 | #define IPV6 0 |
| 1829 | 1951 | #ifndef PF_INET6 |
| 1830 | 1952 | #define PF_INET6 0 |
| 1831 | 1953 | #endif |
| 1832 | 1954 | #endif |
| 1955 | + | |
| 1956 | +#ifdef JIM_ANSIC | |
| 1957 | + | |
| 1958 | +#undef HAVE_PIPE | |
| 1959 | +#undef HAVE_SOCKETPAIR | |
| 1960 | +#endif | |
| 1833 | 1961 | |
| 1834 | 1962 | #define JimCheckStreamError(interp, af) af->fops->error(af) |
| 1835 | 1963 | |
| 1836 | 1964 | |
| 1837 | 1965 | struct AioFile; |
| @@ -1848,11 +1976,11 @@ | ||
| 1848 | 1976 | typedef struct AioFile |
| 1849 | 1977 | { |
| 1850 | 1978 | FILE *fp; |
| 1851 | 1979 | Jim_Obj *filename; |
| 1852 | 1980 | int type; |
| 1853 | - int openFlags; | |
| 1981 | + int openFlags; | |
| 1854 | 1982 | int fd; |
| 1855 | 1983 | Jim_Obj *rEvent; |
| 1856 | 1984 | Jim_Obj *wEvent; |
| 1857 | 1985 | Jim_Obj *eEvent; |
| 1858 | 1986 | int addr_family; |
| @@ -1879,21 +2007,21 @@ | ||
| 1879 | 2007 | { |
| 1880 | 2008 | if (!ferror(af->fp)) { |
| 1881 | 2009 | return JIM_OK; |
| 1882 | 2010 | } |
| 1883 | 2011 | clearerr(af->fp); |
| 1884 | - | |
| 2012 | + | |
| 1885 | 2013 | if (feof(af->fp) || errno == EAGAIN || errno == EINTR) { |
| 1886 | 2014 | return JIM_OK; |
| 1887 | 2015 | } |
| 1888 | 2016 | #ifdef ECONNRESET |
| 1889 | 2017 | if (errno == ECONNRESET) { |
| 1890 | 2018 | return JIM_OK; |
| 1891 | 2019 | } |
| 1892 | 2020 | #endif |
| 1893 | 2021 | #ifdef ECONNABORTED |
| 1894 | - if (errno != ECONNABORTED) { | |
| 2022 | + if (errno == ECONNABORTED) { | |
| 1895 | 2023 | return JIM_OK; |
| 1896 | 2024 | } |
| 1897 | 2025 | #endif |
| 1898 | 2026 | return JIM_ERR; |
| 1899 | 2027 | } |
| @@ -1945,20 +2073,19 @@ | ||
| 1945 | 2073 | JIM_NOTUSED(interp); |
| 1946 | 2074 | |
| 1947 | 2075 | Jim_DecrRefCount(interp, af->filename); |
| 1948 | 2076 | |
| 1949 | 2077 | #ifdef jim_ext_eventloop |
| 1950 | - | |
| 1951 | - Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); | |
| 2078 | + | |
| 2079 | + Jim_DeleteFileHandler(interp, af->fd, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); | |
| 1952 | 2080 | #endif |
| 1953 | 2081 | |
| 1954 | 2082 | #if defined(JIM_SSL) |
| 1955 | 2083 | if (af->ssl != NULL) { |
| 1956 | 2084 | SSL_free(af->ssl); |
| 1957 | 2085 | } |
| 1958 | 2086 | #endif |
| 1959 | - | |
| 1960 | 2087 | if (!(af->openFlags & AIO_KEEPOPEN)) { |
| 1961 | 2088 | fclose(af->fp); |
| 1962 | 2089 | } |
| 1963 | 2090 | |
| 1964 | 2091 | Jim_Free(af); |
| @@ -1968,11 +2095,11 @@ | ||
| 1968 | 2095 | { |
| 1969 | 2096 | AioFile *af = Jim_CmdPrivData(interp); |
| 1970 | 2097 | char buf[AIO_BUF_LEN]; |
| 1971 | 2098 | Jim_Obj *objPtr; |
| 1972 | 2099 | int nonewline = 0; |
| 1973 | - jim_wide neededLen = -1; | |
| 2100 | + jim_wide neededLen = -1; | |
| 1974 | 2101 | |
| 1975 | 2102 | if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { |
| 1976 | 2103 | nonewline = 1; |
| 1977 | 2104 | argv++; |
| 1978 | 2105 | argc--; |
| @@ -2007,11 +2134,11 @@ | ||
| 2007 | 2134 | } |
| 2008 | 2135 | } |
| 2009 | 2136 | if (retval != readlen) |
| 2010 | 2137 | break; |
| 2011 | 2138 | } |
| 2012 | - | |
| 2139 | + | |
| 2013 | 2140 | if (JimCheckStreamError(interp, af)) { |
| 2014 | 2141 | Jim_FreeNewObj(interp, objPtr); |
| 2015 | 2142 | return JIM_ERR; |
| 2016 | 2143 | } |
| 2017 | 2144 | if (nonewline) { |
| @@ -2029,11 +2156,11 @@ | ||
| 2029 | 2156 | |
| 2030 | 2157 | AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command) |
| 2031 | 2158 | { |
| 2032 | 2159 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2033 | 2160 | |
| 2034 | - | |
| 2161 | + | |
| 2035 | 2162 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2036 | 2163 | return (AioFile *) cmdPtr->u.native.privData; |
| 2037 | 2164 | } |
| 2038 | 2165 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2039 | 2166 | return NULL; |
| @@ -2048,10 +2175,20 @@ | ||
| 2048 | 2175 | return NULL; |
| 2049 | 2176 | } |
| 2050 | 2177 | |
| 2051 | 2178 | return af->fp; |
| 2052 | 2179 | } |
| 2180 | + | |
| 2181 | +static int aio_cmd_getfd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 2182 | +{ | |
| 2183 | + AioFile *af = Jim_CmdPrivData(interp); | |
| 2184 | + | |
| 2185 | + fflush(af->fp); | |
| 2186 | + Jim_SetResultInt(interp, fileno(af->fp)); | |
| 2187 | + | |
| 2188 | + return JIM_OK; | |
| 2189 | +} | |
| 2053 | 2190 | |
| 2054 | 2191 | static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2055 | 2192 | { |
| 2056 | 2193 | AioFile *af = Jim_CmdPrivData(interp); |
| 2057 | 2194 | jim_wide count = 0; |
| @@ -2110,21 +2247,21 @@ | ||
| 2110 | 2247 | } |
| 2111 | 2248 | else { |
| 2112 | 2249 | len = strlen(buf); |
| 2113 | 2250 | |
| 2114 | 2251 | if (len && (buf[len - 1] == '\n')) { |
| 2115 | - | |
| 2252 | + | |
| 2116 | 2253 | len--; |
| 2117 | 2254 | } |
| 2118 | 2255 | |
| 2119 | 2256 | Jim_AppendString(interp, objPtr, buf, len); |
| 2120 | 2257 | break; |
| 2121 | 2258 | } |
| 2122 | 2259 | } |
| 2123 | 2260 | |
| 2124 | 2261 | if (JimCheckStreamError(interp, af)) { |
| 2125 | - | |
| 2262 | + | |
| 2126 | 2263 | Jim_FreeNewObj(interp, objPtr); |
| 2127 | 2264 | return JIM_ERR; |
| 2128 | 2265 | } |
| 2129 | 2266 | |
| 2130 | 2267 | if (argc) { |
| @@ -2134,11 +2271,11 @@ | ||
| 2134 | 2271 | } |
| 2135 | 2272 | |
| 2136 | 2273 | len = Jim_Length(objPtr); |
| 2137 | 2274 | |
| 2138 | 2275 | if (len == 0 && feof(af->fp)) { |
| 2139 | - | |
| 2276 | + | |
| 2140 | 2277 | len = -1; |
| 2141 | 2278 | } |
| 2142 | 2279 | Jim_SetResultInt(interp, len); |
| 2143 | 2280 | } |
| 2144 | 2281 | else { |
| @@ -2207,11 +2344,11 @@ | ||
| 2207 | 2344 | } |
| 2208 | 2345 | |
| 2209 | 2346 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2210 | 2347 | { |
| 2211 | 2348 | if (argc == 3) { |
| 2212 | -#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN) | |
| 2349 | +#if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN) | |
| 2213 | 2350 | static const char * const options[] = { "r", "w", NULL }; |
| 2214 | 2351 | enum { OPT_R, OPT_W, }; |
| 2215 | 2352 | int option; |
| 2216 | 2353 | AioFile *af = Jim_CmdPrivData(interp); |
| 2217 | 2354 | |
| @@ -2297,10 +2434,11 @@ | ||
| 2297 | 2434 | } |
| 2298 | 2435 | Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2299 | 2436 | return JIM_OK; |
| 2300 | 2437 | } |
| 2301 | 2438 | #endif |
| 2439 | + | |
| 2302 | 2440 | |
| 2303 | 2441 | #ifdef HAVE_FSYNC |
| 2304 | 2442 | static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2305 | 2443 | { |
| 2306 | 2444 | AioFile *af = Jim_CmdPrivData(interp); |
| @@ -2364,33 +2502,33 @@ | ||
| 2364 | 2502 | |
| 2365 | 2503 | static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, |
| 2366 | 2504 | int argc, Jim_Obj * const *argv) |
| 2367 | 2505 | { |
| 2368 | 2506 | if (argc == 0) { |
| 2369 | - | |
| 2507 | + | |
| 2370 | 2508 | if (*scriptHandlerObj) { |
| 2371 | 2509 | Jim_SetResult(interp, *scriptHandlerObj); |
| 2372 | 2510 | } |
| 2373 | 2511 | return JIM_OK; |
| 2374 | 2512 | } |
| 2375 | 2513 | |
| 2376 | 2514 | if (*scriptHandlerObj) { |
| 2377 | - | |
| 2378 | - Jim_DeleteFileHandler(interp, af->fp, mask); | |
| 2515 | + | |
| 2516 | + Jim_DeleteFileHandler(interp, af->fd, mask); | |
| 2379 | 2517 | } |
| 2380 | 2518 | |
| 2381 | - | |
| 2519 | + | |
| 2382 | 2520 | if (Jim_Length(argv[0]) == 0) { |
| 2383 | - | |
| 2521 | + | |
| 2384 | 2522 | return JIM_OK; |
| 2385 | 2523 | } |
| 2386 | 2524 | |
| 2387 | - | |
| 2525 | + | |
| 2388 | 2526 | Jim_IncrRefCount(argv[0]); |
| 2389 | 2527 | *scriptHandlerObj = argv[0]; |
| 2390 | 2528 | |
| 2391 | - Jim_CreateFileHandler(interp, af->fp, mask, | |
| 2529 | + Jim_CreateFileHandler(interp, af->fd, mask, | |
| 2392 | 2530 | JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer); |
| 2393 | 2531 | |
| 2394 | 2532 | return JIM_OK; |
| 2395 | 2533 | } |
| 2396 | 2534 | |
| @@ -2414,136 +2552,145 @@ | ||
| 2414 | 2552 | |
| 2415 | 2553 | return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); |
| 2416 | 2554 | } |
| 2417 | 2555 | #endif |
| 2418 | 2556 | |
| 2557 | + | |
| 2558 | + | |
| 2419 | 2559 | |
| 2420 | 2560 | static const jim_subcmd_type aio_command_table[] = { |
| 2421 | 2561 | { "read", |
| 2422 | 2562 | "?-nonewline? ?len?", |
| 2423 | 2563 | aio_cmd_read, |
| 2424 | 2564 | 0, |
| 2425 | 2565 | 2, |
| 2426 | - | |
| 2566 | + | |
| 2427 | 2567 | }, |
| 2428 | 2568 | { "copyto", |
| 2429 | 2569 | "handle ?size?", |
| 2430 | 2570 | aio_cmd_copy, |
| 2431 | 2571 | 1, |
| 2432 | 2572 | 2, |
| 2433 | - | |
| 2573 | + | |
| 2574 | + }, | |
| 2575 | + { "getfd", | |
| 2576 | + NULL, | |
| 2577 | + aio_cmd_getfd, | |
| 2578 | + 0, | |
| 2579 | + 0, | |
| 2580 | + | |
| 2434 | 2581 | }, |
| 2435 | 2582 | { "gets", |
| 2436 | 2583 | "?var?", |
| 2437 | 2584 | aio_cmd_gets, |
| 2438 | 2585 | 0, |
| 2439 | 2586 | 1, |
| 2440 | - | |
| 2587 | + | |
| 2441 | 2588 | }, |
| 2442 | 2589 | { "puts", |
| 2443 | 2590 | "?-nonewline? str", |
| 2444 | 2591 | aio_cmd_puts, |
| 2445 | 2592 | 1, |
| 2446 | 2593 | 2, |
| 2447 | - | |
| 2594 | + | |
| 2448 | 2595 | }, |
| 2449 | 2596 | { "isatty", |
| 2450 | 2597 | NULL, |
| 2451 | 2598 | aio_cmd_isatty, |
| 2452 | 2599 | 0, |
| 2453 | 2600 | 0, |
| 2454 | - | |
| 2601 | + | |
| 2455 | 2602 | }, |
| 2456 | 2603 | { "flush", |
| 2457 | 2604 | NULL, |
| 2458 | 2605 | aio_cmd_flush, |
| 2459 | 2606 | 0, |
| 2460 | 2607 | 0, |
| 2461 | - | |
| 2608 | + | |
| 2462 | 2609 | }, |
| 2463 | 2610 | { "eof", |
| 2464 | 2611 | NULL, |
| 2465 | 2612 | aio_cmd_eof, |
| 2466 | 2613 | 0, |
| 2467 | 2614 | 0, |
| 2468 | - | |
| 2615 | + | |
| 2469 | 2616 | }, |
| 2470 | 2617 | { "close", |
| 2471 | 2618 | "?r(ead)|w(rite)?", |
| 2472 | 2619 | aio_cmd_close, |
| 2473 | 2620 | 0, |
| 2474 | 2621 | 1, |
| 2475 | 2622 | JIM_MODFLAG_FULLARGV, |
| 2476 | - | |
| 2623 | + | |
| 2477 | 2624 | }, |
| 2478 | 2625 | { "seek", |
| 2479 | 2626 | "offset ?start|current|end", |
| 2480 | 2627 | aio_cmd_seek, |
| 2481 | 2628 | 1, |
| 2482 | 2629 | 2, |
| 2483 | - | |
| 2630 | + | |
| 2484 | 2631 | }, |
| 2485 | 2632 | { "tell", |
| 2486 | 2633 | NULL, |
| 2487 | 2634 | aio_cmd_tell, |
| 2488 | 2635 | 0, |
| 2489 | 2636 | 0, |
| 2490 | - | |
| 2637 | + | |
| 2491 | 2638 | }, |
| 2492 | 2639 | { "filename", |
| 2493 | 2640 | NULL, |
| 2494 | 2641 | aio_cmd_filename, |
| 2495 | 2642 | 0, |
| 2496 | 2643 | 0, |
| 2497 | - | |
| 2644 | + | |
| 2498 | 2645 | }, |
| 2499 | 2646 | #ifdef O_NDELAY |
| 2500 | 2647 | { "ndelay", |
| 2501 | 2648 | "?0|1?", |
| 2502 | 2649 | aio_cmd_ndelay, |
| 2503 | 2650 | 0, |
| 2504 | 2651 | 1, |
| 2505 | - | |
| 2652 | + | |
| 2506 | 2653 | }, |
| 2507 | 2654 | #endif |
| 2508 | 2655 | #ifdef HAVE_FSYNC |
| 2509 | 2656 | { "sync", |
| 2510 | 2657 | NULL, |
| 2511 | 2658 | aio_cmd_sync, |
| 2512 | 2659 | 0, |
| 2513 | 2660 | 0, |
| 2514 | - | |
| 2661 | + | |
| 2515 | 2662 | }, |
| 2516 | 2663 | #endif |
| 2517 | 2664 | { "buffering", |
| 2518 | 2665 | "none|line|full", |
| 2519 | 2666 | aio_cmd_buffering, |
| 2520 | 2667 | 1, |
| 2521 | 2668 | 1, |
| 2522 | - | |
| 2669 | + | |
| 2523 | 2670 | }, |
| 2524 | 2671 | #ifdef jim_ext_eventloop |
| 2525 | 2672 | { "readable", |
| 2526 | 2673 | "?readable-script?", |
| 2527 | 2674 | aio_cmd_readable, |
| 2528 | 2675 | 0, |
| 2529 | 2676 | 1, |
| 2530 | - | |
| 2677 | + | |
| 2531 | 2678 | }, |
| 2532 | 2679 | { "writable", |
| 2533 | 2680 | "?writable-script?", |
| 2534 | 2681 | aio_cmd_writable, |
| 2535 | 2682 | 0, |
| 2536 | 2683 | 1, |
| 2537 | - | |
| 2684 | + | |
| 2538 | 2685 | }, |
| 2539 | 2686 | { "onexception", |
| 2540 | 2687 | "?exception-script?", |
| 2541 | 2688 | aio_cmd_onexception, |
| 2542 | 2689 | 0, |
| 2543 | 2690 | 1, |
| 2544 | - | |
| 2691 | + | |
| 2545 | 2692 | }, |
| 2546 | 2693 | #endif |
| 2547 | 2694 | { NULL } |
| 2548 | 2695 | }; |
| 2549 | 2696 | |
| @@ -2566,11 +2713,11 @@ | ||
| 2566 | 2713 | |
| 2567 | 2714 | #ifdef jim_ext_tclcompat |
| 2568 | 2715 | { |
| 2569 | 2716 | const char *filename = Jim_String(argv[1]); |
| 2570 | 2717 | |
| 2571 | - | |
| 2718 | + | |
| 2572 | 2719 | if (*filename == '|') { |
| 2573 | 2720 | Jim_Obj *evalObj[3]; |
| 2574 | 2721 | |
| 2575 | 2722 | evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); |
| 2576 | 2723 | evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| @@ -2603,35 +2750,37 @@ | ||
| 2603 | 2750 | } |
| 2604 | 2751 | |
| 2605 | 2752 | Jim_IncrRefCount(filename); |
| 2606 | 2753 | |
| 2607 | 2754 | if (fh == NULL) { |
| 2608 | -#if !defined(JIM_ANSIC) | |
| 2609 | 2755 | if (fd >= 0) { |
| 2756 | +#ifndef JIM_ANSIC | |
| 2610 | 2757 | fh = fdopen(fd, mode); |
| 2758 | +#endif | |
| 2611 | 2759 | } |
| 2612 | 2760 | else |
| 2613 | -#endif | |
| 2614 | 2761 | fh = fopen(Jim_String(filename), mode); |
| 2615 | 2762 | |
| 2616 | 2763 | if (fh == NULL) { |
| 2617 | 2764 | JimAioSetError(interp, filename); |
| 2618 | -#if !defined(JIM_ANSIC) | |
| 2765 | +#ifndef JIM_ANSIC | |
| 2619 | 2766 | if (fd >= 0) { |
| 2620 | 2767 | close(fd); |
| 2621 | 2768 | } |
| 2622 | 2769 | #endif |
| 2623 | 2770 | Jim_DecrRefCount(interp, filename); |
| 2624 | 2771 | return NULL; |
| 2625 | 2772 | } |
| 2626 | 2773 | } |
| 2627 | 2774 | |
| 2628 | - | |
| 2775 | + | |
| 2629 | 2776 | af = Jim_Alloc(sizeof(*af)); |
| 2630 | 2777 | memset(af, 0, sizeof(*af)); |
| 2631 | 2778 | af->fp = fh; |
| 2779 | +#ifndef JIM_ANSIC | |
| 2632 | 2780 | af->fd = fileno(fh); |
| 2781 | +#endif | |
| 2633 | 2782 | af->filename = filename; |
| 2634 | 2783 | #ifdef FD_CLOEXEC |
| 2635 | 2784 | if ((openFlags & AIO_KEEPOPEN) == 0) { |
| 2636 | 2785 | (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2637 | 2786 | } |
| @@ -2653,72 +2802,45 @@ | ||
| 2653 | 2802 | const char *hdlfmt, int family, const char *mode[2]) |
| 2654 | 2803 | { |
| 2655 | 2804 | if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) { |
| 2656 | 2805 | Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); |
| 2657 | 2806 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2658 | - | |
| 2659 | 2807 | if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) { |
| 2660 | 2808 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2661 | 2809 | Jim_SetResult(interp, objPtr); |
| 2662 | 2810 | return JIM_OK; |
| 2663 | 2811 | } |
| 2664 | 2812 | } |
| 2665 | 2813 | |
| 2666 | - | |
| 2814 | + | |
| 2667 | 2815 | close(p[0]); |
| 2668 | 2816 | close(p[1]); |
| 2669 | 2817 | JimAioSetError(interp, NULL); |
| 2670 | 2818 | return JIM_ERR; |
| 2671 | 2819 | } |
| 2672 | 2820 | #endif |
| 2673 | 2821 | |
| 2674 | - | |
| 2675 | -int Jim_MakeTempFile(Jim_Interp *interp, const char *template) | |
| 2676 | -{ | |
| 2677 | -#ifdef HAVE_MKSTEMP | |
| 2678 | - int fd; | |
| 2679 | - mode_t mask; | |
| 2680 | - Jim_Obj *filenameObj; | |
| 2681 | - | |
| 2682 | - if (template == NULL) { | |
| 2683 | - const char *tmpdir = getenv("TMPDIR"); | |
| 2684 | - if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { | |
| 2685 | - tmpdir = "/tmp/"; | |
| 2686 | - } | |
| 2687 | - filenameObj = Jim_NewStringObj(interp, tmpdir, -1); | |
| 2688 | - if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { | |
| 2689 | - Jim_AppendString(interp, filenameObj, "/", 1); | |
| 2690 | - } | |
| 2691 | - Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); | |
| 2692 | - } | |
| 2693 | - else { | |
| 2694 | - filenameObj = Jim_NewStringObj(interp, template, -1); | |
| 2695 | - } | |
| 2696 | - | |
| 2697 | -#if defined(S_IRWXG) && defined(S_IRWXO) | |
| 2698 | - mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); | |
| 2699 | -#else | |
| 2700 | - | |
| 2701 | - mask = umask(S_IXUSR); | |
| 2702 | -#endif | |
| 2703 | - | |
| 2704 | - | |
| 2705 | - fd = mkstemp(filenameObj->bytes); | |
| 2706 | - umask(mask); | |
| 2707 | - if (fd < 0) { | |
| 2708 | - JimAioSetError(interp, filenameObj); | |
| 2709 | - Jim_FreeNewObj(interp, filenameObj); | |
| 2710 | - return -1; | |
| 2711 | - } | |
| 2712 | - | |
| 2713 | - Jim_SetResult(interp, filenameObj); | |
| 2714 | - return fd; | |
| 2715 | -#else | |
| 2716 | - Jim_SetResultString(interp, "platform has no tempfile support", -1); | |
| 2717 | - return -1; | |
| 2718 | -#endif | |
| 2719 | -} | |
| 2822 | +#ifdef HAVE_PIPE | |
| 2823 | +static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 2824 | +{ | |
| 2825 | + int p[2]; | |
| 2826 | + static const char *mode[2] = { "r", "w" }; | |
| 2827 | + | |
| 2828 | + if (argc != 1) { | |
| 2829 | + Jim_WrongNumArgs(interp, 1, argv, ""); | |
| 2830 | + return JIM_ERR; | |
| 2831 | + } | |
| 2832 | + | |
| 2833 | + if (pipe(p) != 0) { | |
| 2834 | + JimAioSetError(interp, NULL); | |
| 2835 | + return JIM_ERR; | |
| 2836 | + } | |
| 2837 | + | |
| 2838 | + return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode); | |
| 2839 | +} | |
| 2840 | +#endif | |
| 2841 | + | |
| 2720 | 2842 | |
| 2721 | 2843 | |
| 2722 | 2844 | int Jim_aioInit(Jim_Interp *interp) |
| 2723 | 2845 | { |
| 2724 | 2846 | if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG)) |
| @@ -2727,15 +2849,18 @@ | ||
| 2727 | 2849 | #if defined(JIM_SSL) |
| 2728 | 2850 | Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL); |
| 2729 | 2851 | #endif |
| 2730 | 2852 | |
| 2731 | 2853 | Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); |
| 2732 | -#ifndef JIM_ANSIC | |
| 2854 | +#ifdef HAVE_SOCKETS | |
| 2733 | 2855 | Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL); |
| 2734 | 2856 | #endif |
| 2857 | +#ifdef HAVE_PIPE | |
| 2858 | + Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL); | |
| 2859 | +#endif | |
| 2735 | 2860 | |
| 2736 | - | |
| 2861 | + | |
| 2737 | 2862 | JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r"); |
| 2738 | 2863 | JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2739 | 2864 | JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 2740 | 2865 | |
| 2741 | 2866 | return JIM_OK; |
| @@ -2813,12 +2938,12 @@ | ||
| 2813 | 2938 | #include <regex.h> |
| 2814 | 2939 | #endif |
| 2815 | 2940 | |
| 2816 | 2941 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2817 | 2942 | { |
| 2818 | - regfree(objPtr->internalRep.regexpValue.compre); | |
| 2819 | - Jim_Free(objPtr->internalRep.regexpValue.compre); | |
| 2943 | + regfree(objPtr->internalRep.ptrIntValue.ptr); | |
| 2944 | + Jim_Free(objPtr->internalRep.ptrIntValue.ptr); | |
| 2820 | 2945 | } |
| 2821 | 2946 | |
| 2822 | 2947 | static const Jim_ObjType regexpObjType = { |
| 2823 | 2948 | "regexp", |
| 2824 | 2949 | FreeRegexpInternalRep, |
| @@ -2831,20 +2956,20 @@ | ||
| 2831 | 2956 | { |
| 2832 | 2957 | regex_t *compre; |
| 2833 | 2958 | const char *pattern; |
| 2834 | 2959 | int ret; |
| 2835 | 2960 | |
| 2836 | - | |
| 2961 | + | |
| 2837 | 2962 | if (objPtr->typePtr == ®expObjType && |
| 2838 | - objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) { | |
| 2839 | - | |
| 2840 | - return objPtr->internalRep.regexpValue.compre; | |
| 2963 | + objPtr->internalRep.ptrIntValue.ptr && objPtr->internalRep.ptrIntValue.int1 == flags) { | |
| 2964 | + | |
| 2965 | + return objPtr->internalRep.ptrIntValue.ptr; | |
| 2841 | 2966 | } |
| 2842 | 2967 | |
| 2843 | - | |
| 2844 | 2968 | |
| 2845 | - | |
| 2969 | + | |
| 2970 | + | |
| 2846 | 2971 | pattern = Jim_String(objPtr); |
| 2847 | 2972 | compre = Jim_Alloc(sizeof(regex_t)); |
| 2848 | 2973 | |
| 2849 | 2974 | if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { |
| 2850 | 2975 | char buf[100]; |
| @@ -2857,12 +2982,12 @@ | ||
| 2857 | 2982 | } |
| 2858 | 2983 | |
| 2859 | 2984 | Jim_FreeIntRep(interp, objPtr); |
| 2860 | 2985 | |
| 2861 | 2986 | objPtr->typePtr = ®expObjType; |
| 2862 | - objPtr->internalRep.regexpValue.flags = flags; | |
| 2863 | - objPtr->internalRep.regexpValue.compre = compre; | |
| 2987 | + objPtr->internalRep.ptrIntValue.int1 = flags; | |
| 2988 | + objPtr->internalRep.ptrIntValue.ptr = compre; | |
| 2864 | 2989 | |
| 2865 | 2990 | return compre; |
| 2866 | 2991 | } |
| 2867 | 2992 | |
| 2868 | 2993 | int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3001,11 +3126,11 @@ | ||
| 3001 | 3126 | } |
| 3002 | 3127 | |
| 3003 | 3128 | num_matches++; |
| 3004 | 3129 | |
| 3005 | 3130 | if (opt_all && !opt_inline) { |
| 3006 | - | |
| 3131 | + | |
| 3007 | 3132 | goto try_next_match; |
| 3008 | 3133 | } |
| 3009 | 3134 | |
| 3010 | 3135 | |
| 3011 | 3136 | j = 0; |
| @@ -3041,11 +3166,11 @@ | ||
| 3041 | 3166 | |
| 3042 | 3167 | if (opt_inline) { |
| 3043 | 3168 | Jim_ListAppendElement(interp, resultListObj, resultObj); |
| 3044 | 3169 | } |
| 3045 | 3170 | else { |
| 3046 | - | |
| 3171 | + | |
| 3047 | 3172 | result = Jim_SetVariable(interp, argv[i], resultObj); |
| 3048 | 3173 | |
| 3049 | 3174 | if (result != JIM_OK) { |
| 3050 | 3175 | Jim_FreeObj(interp, resultObj); |
| 3051 | 3176 | break; |
| @@ -3168,11 +3293,11 @@ | ||
| 3168 | 3293 | |
| 3169 | 3294 | source_str = Jim_GetString(argv[i + 1], &source_len); |
| 3170 | 3295 | replace_str = Jim_GetString(argv[i + 2], &replace_len); |
| 3171 | 3296 | varname = argv[i + 3]; |
| 3172 | 3297 | |
| 3173 | - | |
| 3298 | + | |
| 3174 | 3299 | resultObj = Jim_NewStringObj(interp, "", 0); |
| 3175 | 3300 | |
| 3176 | 3301 | if (offset) { |
| 3177 | 3302 | if (offset < 0) { |
| 3178 | 3303 | offset += source_len + 1; |
| @@ -3183,11 +3308,11 @@ | ||
| 3183 | 3308 | else if (offset < 0) { |
| 3184 | 3309 | offset = 0; |
| 3185 | 3310 | } |
| 3186 | 3311 | } |
| 3187 | 3312 | |
| 3188 | - | |
| 3313 | + | |
| 3189 | 3314 | Jim_AppendString(interp, resultObj, source_str, offset); |
| 3190 | 3315 | |
| 3191 | 3316 | |
| 3192 | 3317 | n = source_len - offset; |
| 3193 | 3318 | p = source_str + offset; |
| @@ -3242,23 +3367,23 @@ | ||
| 3242 | 3367 | } |
| 3243 | 3368 | |
| 3244 | 3369 | p += pmatch[0].rm_eo; |
| 3245 | 3370 | n -= pmatch[0].rm_eo; |
| 3246 | 3371 | |
| 3247 | - | |
| 3372 | + | |
| 3248 | 3373 | if (!opt_all || n == 0) { |
| 3249 | 3374 | break; |
| 3250 | 3375 | } |
| 3251 | 3376 | |
| 3252 | - | |
| 3377 | + | |
| 3253 | 3378 | if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') { |
| 3254 | 3379 | break; |
| 3255 | 3380 | } |
| 3256 | 3381 | |
| 3257 | - | |
| 3382 | + | |
| 3258 | 3383 | if (pattern[0] == '\0' && n) { |
| 3259 | - | |
| 3384 | + | |
| 3260 | 3385 | Jim_AppendString(interp, resultObj, p, 1); |
| 3261 | 3386 | p++; |
| 3262 | 3387 | n--; |
| 3263 | 3388 | } |
| 3264 | 3389 | |
| @@ -3265,11 +3390,11 @@ | ||
| 3265 | 3390 | regexec_flags |= REG_NOTBOL; |
| 3266 | 3391 | } while (n); |
| 3267 | 3392 | |
| 3268 | 3393 | Jim_AppendString(interp, resultObj, p, -1); |
| 3269 | 3394 | |
| 3270 | - | |
| 3395 | + | |
| 3271 | 3396 | if (argc - i == 4) { |
| 3272 | 3397 | result = Jim_SetVariable(interp, varname, resultObj); |
| 3273 | 3398 | |
| 3274 | 3399 | if (result == JIM_OK) { |
| 3275 | 3400 | Jim_SetResultInt(interp, num_matches); |
| @@ -3320,11 +3445,11 @@ | ||
| 3320 | 3445 | |
| 3321 | 3446 | # ifndef MAXPATHLEN |
| 3322 | 3447 | # define MAXPATHLEN JIM_PATH_LEN |
| 3323 | 3448 | # endif |
| 3324 | 3449 | |
| 3325 | -#if defined(__MINGW32__) || defined(_MSC_VER) | |
| 3450 | +#if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER) | |
| 3326 | 3451 | #define ISWINDOWS 1 |
| 3327 | 3452 | #else |
| 3328 | 3453 | #define ISWINDOWS 0 |
| 3329 | 3454 | #endif |
| 3330 | 3455 | |
| @@ -3371,11 +3496,11 @@ | ||
| 3371 | 3496 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); |
| 3372 | 3497 | } |
| 3373 | 3498 | |
| 3374 | 3499 | static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 3375 | 3500 | { |
| 3376 | - | |
| 3501 | + | |
| 3377 | 3502 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 3378 | 3503 | |
| 3379 | 3504 | AppendStatElement(interp, listObj, "dev", sb->st_dev); |
| 3380 | 3505 | AppendStatElement(interp, listObj, "ino", sb->st_ino); |
| 3381 | 3506 | AppendStatElement(interp, listObj, "mode", sb->st_mode); |
| @@ -3387,36 +3512,38 @@ | ||
| 3387 | 3512 | AppendStatElement(interp, listObj, "mtime", sb->st_mtime); |
| 3388 | 3513 | AppendStatElement(interp, listObj, "ctime", sb->st_ctime); |
| 3389 | 3514 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); |
| 3390 | 3515 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); |
| 3391 | 3516 | |
| 3392 | - | |
| 3517 | + | |
| 3393 | 3518 | if (varName) { |
| 3394 | - Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE); | |
| 3519 | + Jim_Obj *objPtr; | |
| 3520 | + objPtr = Jim_GetVariable(interp, varName, JIM_NONE); | |
| 3521 | + | |
| 3395 | 3522 | if (objPtr) { |
| 3396 | - if (Jim_DictSize(interp, objPtr) < 0) { | |
| 3397 | - | |
| 3523 | + Jim_Obj *objv[2]; | |
| 3524 | + | |
| 3525 | + objv[0] = objPtr; | |
| 3526 | + objv[1] = listObj; | |
| 3527 | + | |
| 3528 | + objPtr = Jim_DictMerge(interp, 2, objv); | |
| 3529 | + if (objPtr == NULL) { | |
| 3530 | + | |
| 3398 | 3531 | Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); |
| 3399 | 3532 | Jim_FreeNewObj(interp, listObj); |
| 3400 | 3533 | return JIM_ERR; |
| 3401 | 3534 | } |
| 3402 | 3535 | |
| 3403 | - if (Jim_IsShared(objPtr)) | |
| 3404 | - objPtr = Jim_DuplicateObj(interp, objPtr); | |
| 3405 | - | |
| 3406 | - | |
| 3407 | - Jim_ListAppendList(interp, objPtr, listObj); | |
| 3408 | - Jim_DictSize(interp, objPtr); | |
| 3409 | 3536 | Jim_InvalidateStringRep(objPtr); |
| 3410 | 3537 | |
| 3411 | 3538 | Jim_FreeNewObj(interp, listObj); |
| 3412 | 3539 | listObj = objPtr; |
| 3413 | 3540 | } |
| 3414 | 3541 | Jim_SetVariable(interp, varName, listObj); |
| 3415 | 3542 | } |
| 3416 | 3543 | |
| 3417 | - | |
| 3544 | + | |
| 3418 | 3545 | Jim_SetResult(interp, listObj); |
| 3419 | 3546 | |
| 3420 | 3547 | return JIM_OK; |
| 3421 | 3548 | } |
| 3422 | 3549 | |
| @@ -3432,11 +3559,11 @@ | ||
| 3432 | 3559 | } |
| 3433 | 3560 | else if (p == path) { |
| 3434 | 3561 | Jim_SetResultString(interp, "/", -1); |
| 3435 | 3562 | } |
| 3436 | 3563 | else if (ISWINDOWS && p[-1] == ':') { |
| 3437 | - | |
| 3564 | + | |
| 3438 | 3565 | Jim_SetResultString(interp, path, p - path + 1); |
| 3439 | 3566 | } |
| 3440 | 3567 | else { |
| 3441 | 3568 | Jim_SetResultString(interp, path, p - path); |
| 3442 | 3569 | } |
| @@ -3512,35 +3639,35 @@ | ||
| 3512 | 3639 | char *newname = Jim_Alloc(MAXPATHLEN + 1); |
| 3513 | 3640 | char *last = newname; |
| 3514 | 3641 | |
| 3515 | 3642 | *newname = 0; |
| 3516 | 3643 | |
| 3517 | - | |
| 3644 | + | |
| 3518 | 3645 | for (i = 0; i < argc; i++) { |
| 3519 | 3646 | int len; |
| 3520 | 3647 | const char *part = Jim_GetString(argv[i], &len); |
| 3521 | 3648 | |
| 3522 | 3649 | if (*part == '/') { |
| 3523 | - | |
| 3650 | + | |
| 3524 | 3651 | last = newname; |
| 3525 | 3652 | } |
| 3526 | 3653 | else if (ISWINDOWS && strchr(part, ':')) { |
| 3527 | - | |
| 3654 | + | |
| 3528 | 3655 | last = newname; |
| 3529 | 3656 | } |
| 3530 | 3657 | else if (part[0] == '.') { |
| 3531 | 3658 | if (part[1] == '/') { |
| 3532 | 3659 | part += 2; |
| 3533 | 3660 | len -= 2; |
| 3534 | 3661 | } |
| 3535 | 3662 | else if (part[1] == 0 && last != newname) { |
| 3536 | - | |
| 3663 | + | |
| 3537 | 3664 | continue; |
| 3538 | 3665 | } |
| 3539 | 3666 | } |
| 3540 | 3667 | |
| 3541 | - | |
| 3668 | + | |
| 3542 | 3669 | if (last != newname && last[-1] != '/') { |
| 3543 | 3670 | *last++ = '/'; |
| 3544 | 3671 | } |
| 3545 | 3672 | |
| 3546 | 3673 | if (len) { |
| @@ -3551,22 +3678,22 @@ | ||
| 3551 | 3678 | } |
| 3552 | 3679 | memcpy(last, part, len); |
| 3553 | 3680 | last += len; |
| 3554 | 3681 | } |
| 3555 | 3682 | |
| 3556 | - | |
| 3683 | + | |
| 3557 | 3684 | if (last > newname + 1 && last[-1] == '/') { |
| 3558 | - | |
| 3685 | + | |
| 3559 | 3686 | if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) { |
| 3560 | 3687 | *--last = 0; |
| 3561 | 3688 | } |
| 3562 | 3689 | } |
| 3563 | 3690 | } |
| 3564 | 3691 | |
| 3565 | 3692 | *last = 0; |
| 3566 | 3693 | |
| 3567 | - | |
| 3694 | + | |
| 3568 | 3695 | |
| 3569 | 3696 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname)); |
| 3570 | 3697 | |
| 3571 | 3698 | return JIM_OK; |
| 3572 | 3699 | } |
| @@ -3591,11 +3718,11 @@ | ||
| 3591 | 3718 | static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3592 | 3719 | { |
| 3593 | 3720 | #ifdef X_OK |
| 3594 | 3721 | return file_access(interp, argv[0], X_OK); |
| 3595 | 3722 | #else |
| 3596 | - | |
| 3723 | + | |
| 3597 | 3724 | Jim_SetResultBool(interp, 1); |
| 3598 | 3725 | return JIM_OK; |
| 3599 | 3726 | #endif |
| 3600 | 3727 | } |
| 3601 | 3728 | |
| @@ -3616,11 +3743,11 @@ | ||
| 3616 | 3743 | while (argc--) { |
| 3617 | 3744 | const char *path = Jim_String(argv[0]); |
| 3618 | 3745 | |
| 3619 | 3746 | if (unlink(path) == -1 && errno != ENOENT) { |
| 3620 | 3747 | if (rmdir(path) == -1) { |
| 3621 | - | |
| 3748 | + | |
| 3622 | 3749 | if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) { |
| 3623 | 3750 | Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path, |
| 3624 | 3751 | strerror(errno)); |
| 3625 | 3752 | return JIM_ERR; |
| 3626 | 3753 | } |
| @@ -3639,15 +3766,15 @@ | ||
| 3639 | 3766 | |
| 3640 | 3767 | static int mkdir_all(char *path) |
| 3641 | 3768 | { |
| 3642 | 3769 | int ok = 1; |
| 3643 | 3770 | |
| 3644 | - | |
| 3771 | + | |
| 3645 | 3772 | goto first; |
| 3646 | 3773 | |
| 3647 | 3774 | while (ok--) { |
| 3648 | - | |
| 3775 | + | |
| 3649 | 3776 | { |
| 3650 | 3777 | char *slash = strrchr(path, '/'); |
| 3651 | 3778 | |
| 3652 | 3779 | if (slash && slash != path) { |
| 3653 | 3780 | *slash = 0; |
| @@ -3660,24 +3787,24 @@ | ||
| 3660 | 3787 | first: |
| 3661 | 3788 | if (MKDIR_DEFAULT(path) == 0) { |
| 3662 | 3789 | return 0; |
| 3663 | 3790 | } |
| 3664 | 3791 | if (errno == ENOENT) { |
| 3665 | - | |
| 3792 | + | |
| 3666 | 3793 | continue; |
| 3667 | 3794 | } |
| 3668 | - | |
| 3795 | + | |
| 3669 | 3796 | if (errno == EEXIST) { |
| 3670 | 3797 | struct stat sb; |
| 3671 | 3798 | |
| 3672 | 3799 | if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
| 3673 | 3800 | return 0; |
| 3674 | 3801 | } |
| 3675 | - | |
| 3802 | + | |
| 3676 | 3803 | errno = EEXIST; |
| 3677 | 3804 | } |
| 3678 | - | |
| 3805 | + | |
| 3679 | 3806 | break; |
| 3680 | 3807 | } |
| 3681 | 3808 | return -1; |
| 3682 | 3809 | } |
| 3683 | 3810 | |
| @@ -3698,11 +3825,11 @@ | ||
| 3698 | 3825 | return JIM_OK; |
| 3699 | 3826 | } |
| 3700 | 3827 | |
| 3701 | 3828 | static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3702 | 3829 | { |
| 3703 | - int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL); | |
| 3830 | + int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL, 0); | |
| 3704 | 3831 | |
| 3705 | 3832 | if (fd < 0) { |
| 3706 | 3833 | return JIM_ERR; |
| 3707 | 3834 | } |
| 3708 | 3835 | close(fd); |
| @@ -3962,192 +4089,192 @@ | ||
| 3962 | 4089 | { "atime", |
| 3963 | 4090 | "name", |
| 3964 | 4091 | file_cmd_atime, |
| 3965 | 4092 | 1, |
| 3966 | 4093 | 1, |
| 3967 | - | |
| 4094 | + | |
| 3968 | 4095 | }, |
| 3969 | 4096 | { "mtime", |
| 3970 | 4097 | "name ?time?", |
| 3971 | 4098 | file_cmd_mtime, |
| 3972 | 4099 | 1, |
| 3973 | 4100 | 2, |
| 3974 | - | |
| 4101 | + | |
| 3975 | 4102 | }, |
| 3976 | 4103 | { "copy", |
| 3977 | 4104 | "?-force? source dest", |
| 3978 | 4105 | file_cmd_copy, |
| 3979 | 4106 | 2, |
| 3980 | 4107 | 3, |
| 3981 | - | |
| 4108 | + | |
| 3982 | 4109 | }, |
| 3983 | 4110 | { "dirname", |
| 3984 | 4111 | "name", |
| 3985 | 4112 | file_cmd_dirname, |
| 3986 | 4113 | 1, |
| 3987 | 4114 | 1, |
| 3988 | - | |
| 4115 | + | |
| 3989 | 4116 | }, |
| 3990 | 4117 | { "rootname", |
| 3991 | 4118 | "name", |
| 3992 | 4119 | file_cmd_rootname, |
| 3993 | 4120 | 1, |
| 3994 | 4121 | 1, |
| 3995 | - | |
| 4122 | + | |
| 3996 | 4123 | }, |
| 3997 | 4124 | { "extension", |
| 3998 | 4125 | "name", |
| 3999 | 4126 | file_cmd_extension, |
| 4000 | 4127 | 1, |
| 4001 | 4128 | 1, |
| 4002 | - | |
| 4129 | + | |
| 4003 | 4130 | }, |
| 4004 | 4131 | { "tail", |
| 4005 | 4132 | "name", |
| 4006 | 4133 | file_cmd_tail, |
| 4007 | 4134 | 1, |
| 4008 | 4135 | 1, |
| 4009 | - | |
| 4136 | + | |
| 4010 | 4137 | }, |
| 4011 | 4138 | { "normalize", |
| 4012 | 4139 | "name", |
| 4013 | 4140 | file_cmd_normalize, |
| 4014 | 4141 | 1, |
| 4015 | 4142 | 1, |
| 4016 | - | |
| 4143 | + | |
| 4017 | 4144 | }, |
| 4018 | 4145 | { "join", |
| 4019 | 4146 | "name ?name ...?", |
| 4020 | 4147 | file_cmd_join, |
| 4021 | 4148 | 1, |
| 4022 | 4149 | -1, |
| 4023 | - | |
| 4150 | + | |
| 4024 | 4151 | }, |
| 4025 | 4152 | { "readable", |
| 4026 | 4153 | "name", |
| 4027 | 4154 | file_cmd_readable, |
| 4028 | 4155 | 1, |
| 4029 | 4156 | 1, |
| 4030 | - | |
| 4157 | + | |
| 4031 | 4158 | }, |
| 4032 | 4159 | { "writable", |
| 4033 | 4160 | "name", |
| 4034 | 4161 | file_cmd_writable, |
| 4035 | 4162 | 1, |
| 4036 | 4163 | 1, |
| 4037 | - | |
| 4164 | + | |
| 4038 | 4165 | }, |
| 4039 | 4166 | { "executable", |
| 4040 | 4167 | "name", |
| 4041 | 4168 | file_cmd_executable, |
| 4042 | 4169 | 1, |
| 4043 | 4170 | 1, |
| 4044 | - | |
| 4171 | + | |
| 4045 | 4172 | }, |
| 4046 | 4173 | { "exists", |
| 4047 | 4174 | "name", |
| 4048 | 4175 | file_cmd_exists, |
| 4049 | 4176 | 1, |
| 4050 | 4177 | 1, |
| 4051 | - | |
| 4178 | + | |
| 4052 | 4179 | }, |
| 4053 | 4180 | { "delete", |
| 4054 | 4181 | "?-force|--? name ...", |
| 4055 | 4182 | file_cmd_delete, |
| 4056 | 4183 | 1, |
| 4057 | 4184 | -1, |
| 4058 | - | |
| 4185 | + | |
| 4059 | 4186 | }, |
| 4060 | 4187 | { "mkdir", |
| 4061 | 4188 | "dir ...", |
| 4062 | 4189 | file_cmd_mkdir, |
| 4063 | 4190 | 1, |
| 4064 | 4191 | -1, |
| 4065 | - | |
| 4192 | + | |
| 4066 | 4193 | }, |
| 4067 | 4194 | { "tempfile", |
| 4068 | 4195 | "?template?", |
| 4069 | 4196 | file_cmd_tempfile, |
| 4070 | 4197 | 0, |
| 4071 | 4198 | 1, |
| 4072 | - | |
| 4199 | + | |
| 4073 | 4200 | }, |
| 4074 | 4201 | { "rename", |
| 4075 | 4202 | "?-force? source dest", |
| 4076 | 4203 | file_cmd_rename, |
| 4077 | 4204 | 2, |
| 4078 | 4205 | 3, |
| 4079 | - | |
| 4206 | + | |
| 4080 | 4207 | }, |
| 4081 | 4208 | #if defined(HAVE_LINK) && defined(HAVE_SYMLINK) |
| 4082 | 4209 | { "link", |
| 4083 | 4210 | "?-symbolic|-hard? newname target", |
| 4084 | 4211 | file_cmd_link, |
| 4085 | 4212 | 2, |
| 4086 | 4213 | 3, |
| 4087 | - | |
| 4214 | + | |
| 4088 | 4215 | }, |
| 4089 | 4216 | #endif |
| 4090 | 4217 | #if defined(HAVE_READLINK) |
| 4091 | 4218 | { "readlink", |
| 4092 | 4219 | "name", |
| 4093 | 4220 | file_cmd_readlink, |
| 4094 | 4221 | 1, |
| 4095 | 4222 | 1, |
| 4096 | - | |
| 4223 | + | |
| 4097 | 4224 | }, |
| 4098 | 4225 | #endif |
| 4099 | 4226 | { "size", |
| 4100 | 4227 | "name", |
| 4101 | 4228 | file_cmd_size, |
| 4102 | 4229 | 1, |
| 4103 | 4230 | 1, |
| 4104 | - | |
| 4231 | + | |
| 4105 | 4232 | }, |
| 4106 | 4233 | { "stat", |
| 4107 | 4234 | "name ?var?", |
| 4108 | 4235 | file_cmd_stat, |
| 4109 | 4236 | 1, |
| 4110 | 4237 | 2, |
| 4111 | - | |
| 4238 | + | |
| 4112 | 4239 | }, |
| 4113 | 4240 | { "lstat", |
| 4114 | 4241 | "name ?var?", |
| 4115 | 4242 | file_cmd_lstat, |
| 4116 | 4243 | 1, |
| 4117 | 4244 | 2, |
| 4118 | - | |
| 4245 | + | |
| 4119 | 4246 | }, |
| 4120 | 4247 | { "type", |
| 4121 | 4248 | "name", |
| 4122 | 4249 | file_cmd_type, |
| 4123 | 4250 | 1, |
| 4124 | 4251 | 1, |
| 4125 | - | |
| 4252 | + | |
| 4126 | 4253 | }, |
| 4127 | 4254 | #ifdef HAVE_GETEUID |
| 4128 | 4255 | { "owned", |
| 4129 | 4256 | "name", |
| 4130 | 4257 | file_cmd_owned, |
| 4131 | 4258 | 1, |
| 4132 | 4259 | 1, |
| 4133 | - | |
| 4260 | + | |
| 4134 | 4261 | }, |
| 4135 | 4262 | #endif |
| 4136 | 4263 | { "isdirectory", |
| 4137 | 4264 | "name", |
| 4138 | 4265 | file_cmd_isdirectory, |
| 4139 | 4266 | 1, |
| 4140 | 4267 | 1, |
| 4141 | - | |
| 4268 | + | |
| 4142 | 4269 | }, |
| 4143 | 4270 | { "isfile", |
| 4144 | 4271 | "name", |
| 4145 | 4272 | file_cmd_isfile, |
| 4146 | 4273 | 1, |
| 4147 | 4274 | 1, |
| 4148 | - | |
| 4275 | + | |
| 4149 | 4276 | }, |
| 4150 | 4277 | { |
| 4151 | 4278 | NULL |
| 4152 | 4279 | } |
| 4153 | 4280 | }; |
| @@ -4179,11 +4306,11 @@ | ||
| 4179 | 4306 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 4180 | 4307 | Jim_Free(cwd); |
| 4181 | 4308 | return JIM_ERR; |
| 4182 | 4309 | } |
| 4183 | 4310 | else if (ISWINDOWS) { |
| 4184 | - | |
| 4311 | + | |
| 4185 | 4312 | char *p = cwd; |
| 4186 | 4313 | while ((p = strchr(p, '\\')) != NULL) { |
| 4187 | 4314 | *p++ = '/'; |
| 4188 | 4315 | } |
| 4189 | 4316 | } |
| @@ -4203,10 +4330,13 @@ | ||
| 4203 | 4330 | Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL); |
| 4204 | 4331 | Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL); |
| 4205 | 4332 | return JIM_OK; |
| 4206 | 4333 | } |
| 4207 | 4334 | |
| 4335 | +#ifndef _GNU_SOURCE | |
| 4336 | +#define _GNU_SOURCE | |
| 4337 | +#endif | |
| 4208 | 4338 | #include <string.h> |
| 4209 | 4339 | #include <ctype.h> |
| 4210 | 4340 | |
| 4211 | 4341 | |
| 4212 | 4342 | #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) |
| @@ -4214,20 +4344,20 @@ | ||
| 4214 | 4344 | { |
| 4215 | 4345 | Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp); |
| 4216 | 4346 | int i, j; |
| 4217 | 4347 | int rc; |
| 4218 | 4348 | |
| 4219 | - | |
| 4349 | + | |
| 4220 | 4350 | for (i = 1; i < argc; i++) { |
| 4221 | 4351 | int len; |
| 4222 | 4352 | const char *arg = Jim_GetString(argv[i], &len); |
| 4223 | 4353 | |
| 4224 | 4354 | if (i > 1) { |
| 4225 | 4355 | Jim_AppendString(interp, cmdlineObj, " ", 1); |
| 4226 | 4356 | } |
| 4227 | 4357 | if (strpbrk(arg, "\\\" ") == NULL) { |
| 4228 | - | |
| 4358 | + | |
| 4229 | 4359 | Jim_AppendString(interp, cmdlineObj, arg, len); |
| 4230 | 4360 | continue; |
| 4231 | 4361 | } |
| 4232 | 4362 | |
| 4233 | 4363 | Jim_AppendString(interp, cmdlineObj, "\"", 1); |
| @@ -4266,86 +4396,26 @@ | ||
| 4266 | 4396 | #else |
| 4267 | 4397 | |
| 4268 | 4398 | |
| 4269 | 4399 | #include <errno.h> |
| 4270 | 4400 | #include <signal.h> |
| 4271 | - | |
| 4272 | -#if defined(__MINGW32__) | |
| 4273 | - | |
| 4274 | - #ifndef STRICT | |
| 4275 | - #define STRICT | |
| 4276 | - #endif | |
| 4277 | - #define WIN32_LEAN_AND_MEAN | |
| 4278 | - #include <windows.h> | |
| 4279 | - #include <fcntl.h> | |
| 4280 | - | |
| 4281 | - typedef HANDLE fdtype; | |
| 4282 | - typedef HANDLE pidtype; | |
| 4283 | - #define JIM_BAD_FD INVALID_HANDLE_VALUE | |
| 4284 | - #define JIM_BAD_PID INVALID_HANDLE_VALUE | |
| 4285 | - #define JimCloseFd CloseHandle | |
| 4286 | - | |
| 4287 | - #define WIFEXITED(STATUS) 1 | |
| 4288 | - #define WEXITSTATUS(STATUS) (STATUS) | |
| 4289 | - #define WIFSIGNALED(STATUS) 0 | |
| 4290 | - #define WTERMSIG(STATUS) 0 | |
| 4291 | - #define WNOHANG 1 | |
| 4292 | - | |
| 4293 | - static fdtype JimFileno(FILE *fh); | |
| 4294 | - static pidtype JimWaitPid(pidtype pid, int *status, int nohang); | |
| 4295 | - static fdtype JimDupFd(fdtype infd); | |
| 4296 | - static fdtype JimOpenForRead(const char *filename); | |
| 4297 | - static FILE *JimFdOpenForRead(fdtype fd); | |
| 4298 | - static int JimPipe(fdtype pipefd[2]); | |
| 4299 | - static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, | |
| 4300 | - fdtype inputId, fdtype outputId, fdtype errorId); | |
| 4301 | - static int JimErrno(void); | |
| 4302 | -#else | |
| 4303 | - #include <unistd.h> | |
| 4304 | - #include <fcntl.h> | |
| 4305 | - #include <sys/wait.h> | |
| 4306 | - #include <sys/stat.h> | |
| 4307 | - | |
| 4308 | - typedef int fdtype; | |
| 4309 | - typedef int pidtype; | |
| 4310 | - #define JimPipe pipe | |
| 4311 | - #define JimErrno() errno | |
| 4312 | - #define JIM_BAD_FD -1 | |
| 4313 | - #define JIM_BAD_PID -1 | |
| 4314 | - #define JimFileno fileno | |
| 4315 | - #define JimReadFd read | |
| 4316 | - #define JimCloseFd close | |
| 4317 | - #define JimWaitPid waitpid | |
| 4318 | - #define JimDupFd dup | |
| 4319 | - #define JimFdOpenForRead(FD) fdopen((FD), "r") | |
| 4320 | - #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0) | |
| 4321 | - | |
| 4322 | - #ifndef HAVE_EXECVPE | |
| 4323 | - #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) | |
| 4324 | - #endif | |
| 4325 | -#endif | |
| 4326 | - | |
| 4327 | -static const char *JimStrError(void); | |
| 4401 | +#include <sys/stat.h> | |
| 4402 | + | |
| 4403 | +struct WaitInfoTable; | |
| 4404 | + | |
| 4405 | +static char **JimOriginalEnviron(void); | |
| 4328 | 4406 | static char **JimSaveEnv(char **env); |
| 4329 | 4407 | static void JimRestoreEnv(char **env); |
| 4330 | 4408 | static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, |
| 4331 | - pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr); | |
| 4332 | -static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr); | |
| 4409 | + pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr); | |
| 4410 | +static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr); | |
| 4333 | 4411 | static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj); |
| 4334 | -static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len); | |
| 4335 | -static fdtype JimOpenForWrite(const char *filename, int append); | |
| 4336 | -static int JimRewindFd(fdtype fd); | |
| 4337 | - | |
| 4338 | -static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) | |
| 4339 | -{ | |
| 4340 | - Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError()); | |
| 4341 | -} | |
| 4342 | - | |
| 4343 | -static const char *JimStrError(void) | |
| 4344 | -{ | |
| 4345 | - return strerror(JimErrno()); | |
| 4346 | -} | |
| 4412 | +static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv); | |
| 4413 | + | |
| 4414 | +#if defined(__MINGW32__) | |
| 4415 | +static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId); | |
| 4416 | +#endif | |
| 4347 | 4417 | |
| 4348 | 4418 | static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) |
| 4349 | 4419 | { |
| 4350 | 4420 | int len; |
| 4351 | 4421 | const char *s = Jim_GetString(objPtr, &len); |
| @@ -4354,14 +4424,14 @@ | ||
| 4354 | 4424 | objPtr->length--; |
| 4355 | 4425 | objPtr->bytes[objPtr->length] = '\0'; |
| 4356 | 4426 | } |
| 4357 | 4427 | } |
| 4358 | 4428 | |
| 4359 | -static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj) | |
| 4429 | +static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj) | |
| 4360 | 4430 | { |
| 4361 | 4431 | char buf[256]; |
| 4362 | - FILE *fh = JimFdOpenForRead(fd); | |
| 4432 | + FILE *fh = fdopen(fd, "r"); | |
| 4363 | 4433 | int ret = 0; |
| 4364 | 4434 | |
| 4365 | 4435 | if (fh == NULL) { |
| 4366 | 4436 | return -1; |
| 4367 | 4437 | } |
| @@ -4390,18 +4460,18 @@ | ||
| 4390 | 4460 | char *envdata; |
| 4391 | 4461 | |
| 4392 | 4462 | Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE); |
| 4393 | 4463 | |
| 4394 | 4464 | if (!objPtr) { |
| 4395 | - return Jim_GetEnviron(); | |
| 4465 | + return JimOriginalEnviron(); | |
| 4396 | 4466 | } |
| 4397 | 4467 | |
| 4398 | 4468 | |
| 4399 | - | |
| 4469 | + | |
| 4400 | 4470 | num = Jim_ListLength(interp, objPtr); |
| 4401 | 4471 | if (num % 2) { |
| 4402 | - | |
| 4472 | + | |
| 4403 | 4473 | num--; |
| 4404 | 4474 | } |
| 4405 | 4475 | size = Jim_Length(objPtr) + 2; |
| 4406 | 4476 | |
| 4407 | 4477 | envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); |
| @@ -4433,79 +4503,76 @@ | ||
| 4433 | 4503 | if (env != original_environ) { |
| 4434 | 4504 | Jim_Free(env); |
| 4435 | 4505 | } |
| 4436 | 4506 | } |
| 4437 | 4507 | |
| 4438 | -#ifndef jim_ext_signal | |
| 4439 | - | |
| 4440 | -const char *Jim_SignalId(int sig) | |
| 4441 | -{ | |
| 4442 | - static char buf[10]; | |
| 4443 | - snprintf(buf, sizeof(buf), "%d", sig); | |
| 4444 | - return buf; | |
| 4445 | -} | |
| 4446 | - | |
| 4447 | -const char *Jim_SignalName(int sig) | |
| 4448 | -{ | |
| 4449 | - return Jim_SignalId(sig); | |
| 4450 | -} | |
| 4451 | -#endif | |
| 4452 | - | |
| 4453 | -static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) | |
| 4454 | -{ | |
| 4455 | - Jim_Obj *errorCode; | |
| 4456 | - | |
| 4457 | - if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) { | |
| 4458 | - return JIM_OK; | |
| 4459 | - } | |
| 4460 | - errorCode = Jim_NewListObj(interp, NULL, 0); | |
| 4461 | - | |
| 4462 | - if (WIFEXITED(waitStatus)) { | |
| 4508 | +static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) | |
| 4509 | +{ | |
| 4510 | + Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); | |
| 4511 | + | |
| 4512 | + if (pid == JIM_BAD_PID || pid == JIM_NO_PID) { | |
| 4513 | + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1)); | |
| 4514 | + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); | |
| 4515 | + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1)); | |
| 4516 | + } | |
| 4517 | + else if (WIFEXITED(waitStatus)) { | |
| 4463 | 4518 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); |
| 4464 | 4519 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 4465 | 4520 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); |
| 4466 | 4521 | } |
| 4467 | 4522 | else { |
| 4468 | 4523 | const char *type; |
| 4469 | 4524 | const char *action; |
| 4525 | + const char *signame; | |
| 4470 | 4526 | |
| 4471 | 4527 | if (WIFSIGNALED(waitStatus)) { |
| 4472 | 4528 | type = "CHILDKILLED"; |
| 4473 | 4529 | action = "killed"; |
| 4530 | + signame = Jim_SignalId(WTERMSIG(waitStatus)); | |
| 4474 | 4531 | } |
| 4475 | 4532 | else { |
| 4476 | 4533 | type = "CHILDSUSP"; |
| 4477 | 4534 | action = "suspended"; |
| 4535 | + signame = "none"; | |
| 4478 | 4536 | } |
| 4479 | 4537 | |
| 4480 | 4538 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1)); |
| 4481 | 4539 | |
| 4482 | 4540 | if (errStrObj) { |
| 4483 | 4541 | Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL); |
| 4484 | 4542 | } |
| 4485 | 4543 | |
| 4486 | 4544 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 4487 | - Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1)); | |
| 4488 | - Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1)); | |
| 4545 | + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1)); | |
| 4489 | 4546 | } |
| 4490 | - Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); | |
| 4547 | + return errorCode; | |
| 4548 | +} | |
| 4549 | + | |
| 4550 | +static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) | |
| 4551 | +{ | |
| 4552 | + if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) { | |
| 4553 | + return JIM_OK; | |
| 4554 | + } | |
| 4555 | + Jim_SetGlobalVariableStr(interp, "errorCode", JimMakeErrorCode(interp, pid, waitStatus, errStrObj)); | |
| 4491 | 4556 | |
| 4492 | 4557 | return JIM_ERR; |
| 4493 | 4558 | } |
| 4494 | 4559 | |
| 4495 | 4560 | |
| 4496 | 4561 | struct WaitInfo |
| 4497 | 4562 | { |
| 4498 | - pidtype pid; | |
| 4499 | - int status; | |
| 4500 | - int flags; | |
| 4563 | + pidtype pid; | |
| 4564 | + int status; | |
| 4565 | + int flags; | |
| 4501 | 4566 | }; |
| 4567 | + | |
| 4502 | 4568 | |
| 4503 | 4569 | struct WaitInfoTable { |
| 4504 | - struct WaitInfo *info; | |
| 4505 | - int size; | |
| 4506 | - int used; | |
| 4570 | + struct WaitInfo *info; | |
| 4571 | + int size; | |
| 4572 | + int used; | |
| 4573 | + int refcount; | |
| 4507 | 4574 | }; |
| 4508 | 4575 | |
| 4509 | 4576 | |
| 4510 | 4577 | #define WI_DETACHED 2 |
| 4511 | 4578 | |
| @@ -4513,32 +4580,53 @@ | ||
| 4513 | 4580 | |
| 4514 | 4581 | static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData) |
| 4515 | 4582 | { |
| 4516 | 4583 | struct WaitInfoTable *table = privData; |
| 4517 | 4584 | |
| 4518 | - Jim_Free(table->info); | |
| 4519 | - Jim_Free(table); | |
| 4585 | + if (--table->refcount == 0) { | |
| 4586 | + Jim_Free(table->info); | |
| 4587 | + Jim_Free(table); | |
| 4588 | + } | |
| 4520 | 4589 | } |
| 4521 | 4590 | |
| 4522 | 4591 | static struct WaitInfoTable *JimAllocWaitInfoTable(void) |
| 4523 | 4592 | { |
| 4524 | 4593 | struct WaitInfoTable *table = Jim_Alloc(sizeof(*table)); |
| 4525 | 4594 | table->info = NULL; |
| 4526 | 4595 | table->size = table->used = 0; |
| 4596 | + table->refcount = 1; | |
| 4527 | 4597 | |
| 4528 | 4598 | return table; |
| 4529 | 4599 | } |
| 4600 | + | |
| 4601 | +static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid) | |
| 4602 | +{ | |
| 4603 | + int i; | |
| 4604 | + | |
| 4605 | + | |
| 4606 | + for (i = 0; i < table->used; i++) { | |
| 4607 | + if (pid == table->info[i].pid) { | |
| 4608 | + if (i != table->used - 1) { | |
| 4609 | + table->info[i] = table->info[table->used - 1]; | |
| 4610 | + } | |
| 4611 | + table->used--; | |
| 4612 | + return 0; | |
| 4613 | + } | |
| 4614 | + } | |
| 4615 | + return -1; | |
| 4616 | +} | |
| 4530 | 4617 | |
| 4531 | 4618 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4532 | 4619 | { |
| 4533 | - fdtype outputId; | |
| 4534 | - fdtype errorId; | |
| 4620 | + int outputId; | |
| 4621 | + int errorId; | |
| 4535 | 4622 | pidtype *pidPtr; |
| 4536 | 4623 | int numPids, result; |
| 4537 | 4624 | int child_siginfo = 1; |
| 4538 | 4625 | Jim_Obj *childErrObj; |
| 4539 | 4626 | Jim_Obj *errStrObj; |
| 4627 | + struct WaitInfoTable *table = Jim_CmdPrivData(interp); | |
| 4540 | 4628 | |
| 4541 | 4629 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { |
| 4542 | 4630 | Jim_Obj *listObj; |
| 4543 | 4631 | int i; |
| 4544 | 4632 | |
| @@ -4545,17 +4633,17 @@ | ||
| 4545 | 4633 | argc--; |
| 4546 | 4634 | numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); |
| 4547 | 4635 | if (numPids < 0) { |
| 4548 | 4636 | return JIM_ERR; |
| 4549 | 4637 | } |
| 4550 | - | |
| 4638 | + | |
| 4551 | 4639 | listObj = Jim_NewListObj(interp, NULL, 0); |
| 4552 | 4640 | for (i = 0; i < numPids; i++) { |
| 4553 | 4641 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); |
| 4554 | 4642 | } |
| 4555 | 4643 | Jim_SetResult(interp, listObj); |
| 4556 | - JimDetachPids(interp, numPids, pidPtr); | |
| 4644 | + JimDetachPids(table, numPids, pidPtr); | |
| 4557 | 4645 | Jim_Free(pidPtr); |
| 4558 | 4646 | return JIM_OK; |
| 4559 | 4647 | } |
| 4560 | 4648 | |
| 4561 | 4649 | numPids = |
| @@ -4567,54 +4655,98 @@ | ||
| 4567 | 4655 | |
| 4568 | 4656 | result = JIM_OK; |
| 4569 | 4657 | |
| 4570 | 4658 | errStrObj = Jim_NewStringObj(interp, "", 0); |
| 4571 | 4659 | |
| 4572 | - | |
| 4573 | - if (outputId != JIM_BAD_FD) { | |
| 4660 | + | |
| 4661 | + if (outputId != -1) { | |
| 4574 | 4662 | if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) { |
| 4575 | 4663 | result = JIM_ERR; |
| 4576 | 4664 | Jim_SetResultErrno(interp, "error reading from output pipe"); |
| 4577 | 4665 | } |
| 4578 | 4666 | } |
| 4579 | 4667 | |
| 4580 | - | |
| 4668 | + | |
| 4581 | 4669 | childErrObj = Jim_NewStringObj(interp, "", 0); |
| 4582 | 4670 | Jim_IncrRefCount(childErrObj); |
| 4583 | 4671 | |
| 4584 | 4672 | if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) { |
| 4585 | 4673 | result = JIM_ERR; |
| 4586 | 4674 | } |
| 4587 | 4675 | |
| 4588 | - if (errorId != JIM_BAD_FD) { | |
| 4676 | + if (errorId != -1) { | |
| 4589 | 4677 | int ret; |
| 4590 | - JimRewindFd(errorId); | |
| 4678 | + lseek(errorId, 0, SEEK_SET); | |
| 4591 | 4679 | ret = JimAppendStreamToString(interp, errorId, errStrObj); |
| 4592 | 4680 | if (ret < 0) { |
| 4593 | 4681 | Jim_SetResultErrno(interp, "error reading from error pipe"); |
| 4594 | 4682 | result = JIM_ERR; |
| 4595 | 4683 | } |
| 4596 | 4684 | else if (ret > 0) { |
| 4597 | - | |
| 4685 | + | |
| 4598 | 4686 | child_siginfo = 0; |
| 4599 | 4687 | } |
| 4600 | 4688 | } |
| 4601 | 4689 | |
| 4602 | 4690 | if (child_siginfo) { |
| 4603 | - | |
| 4691 | + | |
| 4604 | 4692 | Jim_AppendObj(interp, errStrObj, childErrObj); |
| 4605 | 4693 | } |
| 4606 | 4694 | Jim_DecrRefCount(interp, childErrObj); |
| 4607 | 4695 | |
| 4608 | - | |
| 4696 | + | |
| 4609 | 4697 | Jim_RemoveTrailingNewline(errStrObj); |
| 4610 | 4698 | |
| 4611 | - | |
| 4699 | + | |
| 4612 | 4700 | Jim_SetResult(interp, errStrObj); |
| 4613 | 4701 | |
| 4614 | 4702 | return result; |
| 4615 | 4703 | } |
| 4704 | + | |
| 4705 | +static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) | |
| 4706 | +{ | |
| 4707 | + if (JimWaitRemove(table, pid) == 0) { | |
| 4708 | + | |
| 4709 | + waitpid(pid, statusPtr, 0); | |
| 4710 | + return pid; | |
| 4711 | + } | |
| 4712 | + | |
| 4713 | + | |
| 4714 | + return JIM_BAD_PID; | |
| 4715 | +} | |
| 4716 | + | |
| 4717 | +static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr) | |
| 4718 | +{ | |
| 4719 | + int j; | |
| 4720 | + | |
| 4721 | + for (j = 0; j < numPids; j++) { | |
| 4722 | + | |
| 4723 | + int i; | |
| 4724 | + for (i = 0; i < table->used; i++) { | |
| 4725 | + if (pidPtr[j] == table->info[i].pid) { | |
| 4726 | + table->info[i].flags |= WI_DETACHED; | |
| 4727 | + break; | |
| 4728 | + } | |
| 4729 | + } | |
| 4730 | + } | |
| 4731 | +} | |
| 4732 | + | |
| 4733 | +static int JimGetChannelFd(Jim_Interp *interp, const char *name) | |
| 4734 | +{ | |
| 4735 | + Jim_Obj *objv[2]; | |
| 4736 | + | |
| 4737 | + objv[0] = Jim_NewStringObj(interp, name, -1); | |
| 4738 | + objv[1] = Jim_NewStringObj(interp, "getfd", -1); | |
| 4739 | + | |
| 4740 | + if (Jim_EvalObjVector(interp, 2, objv) == JIM_OK) { | |
| 4741 | + jim_wide fd; | |
| 4742 | + if (Jim_GetWide(interp, Jim_GetResult(interp), &fd) == JIM_OK) { | |
| 4743 | + return fd; | |
| 4744 | + } | |
| 4745 | + } | |
| 4746 | + return -1; | |
| 4747 | +} | |
| 4616 | 4748 | |
| 4617 | 4749 | static void JimReapDetachedPids(struct WaitInfoTable *table) |
| 4618 | 4750 | { |
| 4619 | 4751 | struct WaitInfo *waitPtr; |
| 4620 | 4752 | int count; |
| @@ -4627,13 +4759,13 @@ | ||
| 4627 | 4759 | waitPtr = table->info; |
| 4628 | 4760 | dest = 0; |
| 4629 | 4761 | for (count = table->used; count > 0; waitPtr++, count--) { |
| 4630 | 4762 | if (waitPtr->flags & WI_DETACHED) { |
| 4631 | 4763 | int status; |
| 4632 | - pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); | |
| 4764 | + pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG); | |
| 4633 | 4765 | if (pid == waitPtr->pid) { |
| 4634 | - | |
| 4766 | + | |
| 4635 | 4767 | table->used--; |
| 4636 | 4768 | continue; |
| 4637 | 4769 | } |
| 4638 | 4770 | } |
| 4639 | 4771 | if (waitPtr != &table->info[dest]) { |
| @@ -4641,66 +4773,62 @@ | ||
| 4641 | 4773 | } |
| 4642 | 4774 | dest++; |
| 4643 | 4775 | } |
| 4644 | 4776 | } |
| 4645 | 4777 | |
| 4646 | -static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) | |
| 4647 | -{ | |
| 4648 | - int i; | |
| 4649 | - | |
| 4650 | - | |
| 4651 | - for (i = 0; i < table->used; i++) { | |
| 4652 | - if (pid == table->info[i].pid) { | |
| 4653 | - | |
| 4654 | - JimWaitPid(pid, statusPtr, 0); | |
| 4655 | - | |
| 4656 | - | |
| 4657 | - if (i != table->used - 1) { | |
| 4658 | - table->info[i] = table->info[table->used - 1]; | |
| 4659 | - } | |
| 4660 | - table->used--; | |
| 4661 | - return pid; | |
| 4662 | - } | |
| 4663 | - } | |
| 4664 | - | |
| 4665 | - | |
| 4666 | - return JIM_BAD_PID; | |
| 4667 | -} | |
| 4668 | - | |
| 4669 | -static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) | |
| 4670 | -{ | |
| 4671 | - int j; | |
| 4778 | +static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 4779 | +{ | |
| 4672 | 4780 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4673 | - | |
| 4674 | - for (j = 0; j < numPids; j++) { | |
| 4675 | - | |
| 4676 | - int i; | |
| 4677 | - for (i = 0; i < table->used; i++) { | |
| 4678 | - if (pidPtr[j] == table->info[i].pid) { | |
| 4679 | - table->info[i].flags |= WI_DETACHED; | |
| 4680 | - break; | |
| 4681 | - } | |
| 4682 | - } | |
| 4683 | - } | |
| 4684 | -} | |
| 4685 | - | |
| 4686 | -static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name) | |
| 4687 | -{ | |
| 4688 | - FILE *fh; | |
| 4689 | - Jim_Obj *fhObj; | |
| 4690 | - | |
| 4691 | - fhObj = Jim_NewStringObj(interp, name, -1); | |
| 4692 | - Jim_IncrRefCount(fhObj); | |
| 4693 | - fh = Jim_AioFilehandle(interp, fhObj); | |
| 4694 | - Jim_DecrRefCount(interp, fhObj); | |
| 4695 | - | |
| 4696 | - return fh; | |
| 4781 | + int nohang = 0; | |
| 4782 | + pidtype pid; | |
| 4783 | + long pidarg; | |
| 4784 | + int status; | |
| 4785 | + Jim_Obj *errCodeObj; | |
| 4786 | + | |
| 4787 | + | |
| 4788 | + if (argc == 1) { | |
| 4789 | + JimReapDetachedPids(table); | |
| 4790 | + return JIM_OK; | |
| 4791 | + } | |
| 4792 | + | |
| 4793 | + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) { | |
| 4794 | + nohang = 1; | |
| 4795 | + } | |
| 4796 | + if (argc != nohang + 2) { | |
| 4797 | + Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?"); | |
| 4798 | + return JIM_ERR; | |
| 4799 | + } | |
| 4800 | + if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) { | |
| 4801 | + return JIM_ERR; | |
| 4802 | + } | |
| 4803 | + | |
| 4804 | + pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0); | |
| 4805 | + | |
| 4806 | + errCodeObj = JimMakeErrorCode(interp, pid, status, NULL); | |
| 4807 | + | |
| 4808 | + if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) { | |
| 4809 | + | |
| 4810 | + JimWaitRemove(table, pid); | |
| 4811 | + } | |
| 4812 | + Jim_SetResult(interp, errCodeObj); | |
| 4813 | + return JIM_OK; | |
| 4814 | +} | |
| 4815 | + | |
| 4816 | +static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 4817 | +{ | |
| 4818 | + if (argc != 1) { | |
| 4819 | + Jim_WrongNumArgs(interp, 1, argv, ""); | |
| 4820 | + return JIM_ERR; | |
| 4821 | + } | |
| 4822 | + | |
| 4823 | + Jim_SetResultInt(interp, (jim_wide)getpid()); | |
| 4824 | + return JIM_OK; | |
| 4697 | 4825 | } |
| 4698 | 4826 | |
| 4699 | 4827 | static int |
| 4700 | 4828 | JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, |
| 4701 | - fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr) | |
| 4829 | + int *inPipePtr, int *outPipePtr, int *errFilePtr) | |
| 4702 | 4830 | { |
| 4703 | 4831 | pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all |
| 4704 | 4832 | * the pids of child processes. */ |
| 4705 | 4833 | int numPids = 0; /* Actual number of processes that exist |
| 4706 | 4834 | * at *pidPtr right now. */ |
| @@ -4707,16 +4835,16 @@ | ||
| 4707 | 4835 | int cmdCount; /* Count of number of distinct commands |
| 4708 | 4836 | * found in argc/argv. */ |
| 4709 | 4837 | const char *input = NULL; /* Describes input for pipeline, depending |
| 4710 | 4838 | * on "inputFile". NULL means take input |
| 4711 | 4839 | * from stdin/pipe. */ |
| 4712 | - int input_len = 0; | |
| 4840 | + int input_len = 0; | |
| 4713 | 4841 | |
| 4714 | -#define FILE_NAME 0 | |
| 4715 | -#define FILE_APPEND 1 | |
| 4716 | -#define FILE_HANDLE 2 | |
| 4717 | -#define FILE_TEXT 3 | |
| 4842 | +#define FILE_NAME 0 | |
| 4843 | +#define FILE_APPEND 1 | |
| 4844 | +#define FILE_HANDLE 2 | |
| 4845 | +#define FILE_TEXT 3 | |
| 4718 | 4846 | |
| 4719 | 4847 | int inputFile = FILE_NAME; /* 1 means input is name of input file. |
| 4720 | 4848 | * 2 means input is filehandle name. |
| 4721 | 4849 | * 0 means input holds actual |
| 4722 | 4850 | * text to be input to command. */ |
| @@ -4733,39 +4861,37 @@ | ||
| 4733 | 4861 | */ |
| 4734 | 4862 | const char *output = NULL; /* Holds name of output file to pipe to, |
| 4735 | 4863 | * or NULL if output goes to stdout/pipe. */ |
| 4736 | 4864 | const char *error = NULL; /* Holds name of stderr file to pipe to, |
| 4737 | 4865 | * or NULL if stderr goes to stderr/pipe. */ |
| 4738 | - fdtype inputId = JIM_BAD_FD; | |
| 4739 | - fdtype outputId = JIM_BAD_FD; | |
| 4740 | - fdtype errorId = JIM_BAD_FD; | |
| 4741 | - fdtype lastOutputId = JIM_BAD_FD; | |
| 4742 | - fdtype pipeIds[2]; | |
| 4866 | + int inputId = -1; | |
| 4867 | + int outputId = -1; | |
| 4868 | + int errorId = -1; | |
| 4869 | + int lastOutputId = -1; | |
| 4870 | + int pipeIds[2]; | |
| 4743 | 4871 | int firstArg, lastArg; /* Indexes of first and last arguments in |
| 4744 | 4872 | * current command. */ |
| 4745 | 4873 | int lastBar; |
| 4746 | 4874 | int i; |
| 4747 | 4875 | pidtype pid; |
| 4748 | 4876 | char **save_environ; |
| 4749 | 4877 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4750 | 4878 | |
| 4751 | - | |
| 4879 | + | |
| 4752 | 4880 | char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1)); |
| 4753 | 4881 | int arg_count = 0; |
| 4754 | 4882 | |
| 4755 | - JimReapDetachedPids(table); | |
| 4756 | - | |
| 4757 | 4883 | if (inPipePtr != NULL) { |
| 4758 | - *inPipePtr = JIM_BAD_FD; | |
| 4884 | + *inPipePtr = -1; | |
| 4759 | 4885 | } |
| 4760 | 4886 | if (outPipePtr != NULL) { |
| 4761 | - *outPipePtr = JIM_BAD_FD; | |
| 4887 | + *outPipePtr = -1; | |
| 4762 | 4888 | } |
| 4763 | 4889 | if (errFilePtr != NULL) { |
| 4764 | - *errFilePtr = JIM_BAD_FD; | |
| 4890 | + *errFilePtr = -1; | |
| 4765 | 4891 | } |
| 4766 | - pipeIds[0] = pipeIds[1] = JIM_BAD_FD; | |
| 4892 | + pipeIds[0] = pipeIds[1] = -1; | |
| 4767 | 4893 | |
| 4768 | 4894 | cmdCount = 1; |
| 4769 | 4895 | lastBar = -1; |
| 4770 | 4896 | for (i = 0; i < argc; i++) { |
| 4771 | 4897 | const char *arg = Jim_String(argv[i]); |
| @@ -4796,11 +4922,11 @@ | ||
| 4796 | 4922 | if (*output == '>') { |
| 4797 | 4923 | outputFile = FILE_APPEND; |
| 4798 | 4924 | output++; |
| 4799 | 4925 | } |
| 4800 | 4926 | if (*output == '&') { |
| 4801 | - | |
| 4927 | + | |
| 4802 | 4928 | output++; |
| 4803 | 4929 | dup_error = 1; |
| 4804 | 4930 | } |
| 4805 | 4931 | if (*output == '@') { |
| 4806 | 4932 | outputFile = FILE_HANDLE; |
| @@ -4837,11 +4963,11 @@ | ||
| 4837 | 4963 | goto badargs; |
| 4838 | 4964 | } |
| 4839 | 4965 | lastBar = i; |
| 4840 | 4966 | cmdCount++; |
| 4841 | 4967 | } |
| 4842 | - | |
| 4968 | + | |
| 4843 | 4969 | arg_array[arg_count++] = (char *)arg; |
| 4844 | 4970 | continue; |
| 4845 | 4971 | } |
| 4846 | 4972 | |
| 4847 | 4973 | if (i >= argc) { |
| @@ -4855,150 +4981,160 @@ | ||
| 4855 | 4981 | badargs: |
| 4856 | 4982 | Jim_Free(arg_array); |
| 4857 | 4983 | return -1; |
| 4858 | 4984 | } |
| 4859 | 4985 | |
| 4860 | - | |
| 4986 | + | |
| 4861 | 4987 | save_environ = JimSaveEnv(JimBuildEnv(interp)); |
| 4862 | 4988 | |
| 4863 | 4989 | if (input != NULL) { |
| 4864 | 4990 | if (inputFile == FILE_TEXT) { |
| 4865 | - inputId = JimCreateTemp(interp, input, input_len); | |
| 4866 | - if (inputId == JIM_BAD_FD) { | |
| 4991 | + inputId = Jim_MakeTempFile(interp, NULL, 1); | |
| 4992 | + if (inputId == -1) { | |
| 4993 | + goto error; | |
| 4994 | + } | |
| 4995 | + if (write(inputId, input, input_len) != input_len) { | |
| 4996 | + Jim_SetResultErrno(interp, "couldn't write temp file"); | |
| 4997 | + close(inputId); | |
| 4867 | 4998 | goto error; |
| 4868 | 4999 | } |
| 5000 | + lseek(inputId, 0L, SEEK_SET); | |
| 4869 | 5001 | } |
| 4870 | 5002 | else if (inputFile == FILE_HANDLE) { |
| 4871 | - | |
| 4872 | - FILE *fh = JimGetAioFilehandle(interp, input); | |
| 5003 | + int fd = JimGetChannelFd(interp, input); | |
| 4873 | 5004 | |
| 4874 | - if (fh == NULL) { | |
| 5005 | + if (fd < 0) { | |
| 4875 | 5006 | goto error; |
| 4876 | 5007 | } |
| 4877 | - inputId = JimDupFd(JimFileno(fh)); | |
| 5008 | + inputId = dup(fd); | |
| 4878 | 5009 | } |
| 4879 | 5010 | else { |
| 4880 | - inputId = JimOpenForRead(input); | |
| 4881 | - if (inputId == JIM_BAD_FD) { | |
| 4882 | - Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError()); | |
| 5011 | + inputId = Jim_OpenForRead(input); | |
| 5012 | + if (inputId == -1) { | |
| 5013 | + Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, strerror(Jim_Errno())); | |
| 4883 | 5014 | goto error; |
| 4884 | 5015 | } |
| 4885 | 5016 | } |
| 4886 | 5017 | } |
| 4887 | 5018 | else if (inPipePtr != NULL) { |
| 4888 | - if (JimPipe(pipeIds) != 0) { | |
| 5019 | + if (pipe(pipeIds) != 0) { | |
| 4889 | 5020 | Jim_SetResultErrno(interp, "couldn't create input pipe for command"); |
| 4890 | 5021 | goto error; |
| 4891 | 5022 | } |
| 4892 | 5023 | inputId = pipeIds[0]; |
| 4893 | 5024 | *inPipePtr = pipeIds[1]; |
| 4894 | - pipeIds[0] = pipeIds[1] = JIM_BAD_FD; | |
| 5025 | + pipeIds[0] = pipeIds[1] = -1; | |
| 4895 | 5026 | } |
| 4896 | 5027 | |
| 4897 | 5028 | if (output != NULL) { |
| 4898 | 5029 | if (outputFile == FILE_HANDLE) { |
| 4899 | - FILE *fh = JimGetAioFilehandle(interp, output); | |
| 4900 | - if (fh == NULL) { | |
| 5030 | + int fd = JimGetChannelFd(interp, output); | |
| 5031 | + if (fd < 0) { | |
| 4901 | 5032 | goto error; |
| 4902 | 5033 | } |
| 4903 | - fflush(fh); | |
| 4904 | - lastOutputId = JimDupFd(JimFileno(fh)); | |
| 5034 | + lastOutputId = dup(fd); | |
| 4905 | 5035 | } |
| 4906 | 5036 | else { |
| 4907 | - lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND); | |
| 4908 | - if (lastOutputId == JIM_BAD_FD) { | |
| 4909 | - Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError()); | |
| 5037 | + lastOutputId = Jim_OpenForWrite(output, outputFile == FILE_APPEND); | |
| 5038 | + if (lastOutputId == -1) { | |
| 5039 | + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, strerror(Jim_Errno())); | |
| 4910 | 5040 | goto error; |
| 4911 | 5041 | } |
| 4912 | 5042 | } |
| 4913 | 5043 | } |
| 4914 | 5044 | else if (outPipePtr != NULL) { |
| 4915 | - if (JimPipe(pipeIds) != 0) { | |
| 5045 | + if (pipe(pipeIds) != 0) { | |
| 4916 | 5046 | Jim_SetResultErrno(interp, "couldn't create output pipe"); |
| 4917 | 5047 | goto error; |
| 4918 | 5048 | } |
| 4919 | 5049 | lastOutputId = pipeIds[1]; |
| 4920 | 5050 | *outPipePtr = pipeIds[0]; |
| 4921 | - pipeIds[0] = pipeIds[1] = JIM_BAD_FD; | |
| 5051 | + pipeIds[0] = pipeIds[1] = -1; | |
| 4922 | 5052 | } |
| 4923 | - | |
| 5053 | + | |
| 4924 | 5054 | if (error != NULL) { |
| 4925 | 5055 | if (errorFile == FILE_HANDLE) { |
| 4926 | 5056 | if (strcmp(error, "1") == 0) { |
| 4927 | - | |
| 4928 | - if (lastOutputId != JIM_BAD_FD) { | |
| 4929 | - errorId = JimDupFd(lastOutputId); | |
| 5057 | + | |
| 5058 | + if (lastOutputId != -1) { | |
| 5059 | + errorId = dup(lastOutputId); | |
| 4930 | 5060 | } |
| 4931 | 5061 | else { |
| 4932 | - | |
| 5062 | + | |
| 4933 | 5063 | error = "stdout"; |
| 4934 | 5064 | } |
| 4935 | 5065 | } |
| 4936 | - if (errorId == JIM_BAD_FD) { | |
| 4937 | - FILE *fh = JimGetAioFilehandle(interp, error); | |
| 4938 | - if (fh == NULL) { | |
| 5066 | + if (errorId == -1) { | |
| 5067 | + int fd = JimGetChannelFd(interp, error); | |
| 5068 | + if (fd < 0) { | |
| 4939 | 5069 | goto error; |
| 4940 | 5070 | } |
| 4941 | - fflush(fh); | |
| 4942 | - errorId = JimDupFd(JimFileno(fh)); | |
| 5071 | + errorId = dup(fd); | |
| 4943 | 5072 | } |
| 4944 | 5073 | } |
| 4945 | 5074 | else { |
| 4946 | - errorId = JimOpenForWrite(error, errorFile == FILE_APPEND); | |
| 4947 | - if (errorId == JIM_BAD_FD) { | |
| 4948 | - Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError()); | |
| 5075 | + errorId = Jim_OpenForWrite(error, errorFile == FILE_APPEND); | |
| 5076 | + if (errorId == -1) { | |
| 5077 | + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, strerror(Jim_Errno())); | |
| 4949 | 5078 | goto error; |
| 4950 | 5079 | } |
| 4951 | 5080 | } |
| 4952 | 5081 | } |
| 4953 | 5082 | else if (errFilePtr != NULL) { |
| 4954 | - errorId = JimCreateTemp(interp, NULL, 0); | |
| 4955 | - if (errorId == JIM_BAD_FD) { | |
| 5083 | + errorId = Jim_MakeTempFile(interp, NULL, 1); | |
| 5084 | + if (errorId == -1) { | |
| 4956 | 5085 | goto error; |
| 4957 | 5086 | } |
| 4958 | - *errFilePtr = JimDupFd(errorId); | |
| 5087 | + *errFilePtr = dup(errorId); | |
| 4959 | 5088 | } |
| 4960 | 5089 | |
| 4961 | 5090 | |
| 4962 | 5091 | pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); |
| 4963 | 5092 | for (i = 0; i < numPids; i++) { |
| 4964 | 5093 | pidPtr[i] = JIM_BAD_PID; |
| 4965 | 5094 | } |
| 4966 | 5095 | for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { |
| 4967 | 5096 | int pipe_dup_err = 0; |
| 4968 | - fdtype origErrorId = errorId; | |
| 5097 | + int origErrorId = errorId; | |
| 4969 | 5098 | |
| 4970 | 5099 | for (lastArg = firstArg; lastArg < arg_count; lastArg++) { |
| 4971 | - if (arg_array[lastArg][0] == '|') { | |
| 4972 | - if (arg_array[lastArg][1] == '&') { | |
| 4973 | - pipe_dup_err = 1; | |
| 4974 | - } | |
| 5100 | + if (strcmp(arg_array[lastArg], "|") == 0) { | |
| 5101 | + break; | |
| 5102 | + } | |
| 5103 | + if (strcmp(arg_array[lastArg], "|&") == 0) { | |
| 5104 | + pipe_dup_err = 1; | |
| 4975 | 5105 | break; |
| 4976 | 5106 | } |
| 4977 | 5107 | } |
| 4978 | - | |
| 5108 | + | |
| 5109 | + if (lastArg == firstArg) { | |
| 5110 | + Jim_SetResultString(interp, "missing command to exec", -1); | |
| 5111 | + goto error; | |
| 5112 | + } | |
| 5113 | + | |
| 5114 | + | |
| 4979 | 5115 | arg_array[lastArg] = NULL; |
| 4980 | 5116 | if (lastArg == arg_count) { |
| 4981 | 5117 | outputId = lastOutputId; |
| 4982 | 5118 | } |
| 4983 | 5119 | else { |
| 4984 | - if (JimPipe(pipeIds) != 0) { | |
| 5120 | + if (pipe(pipeIds) != 0) { | |
| 4985 | 5121 | Jim_SetResultErrno(interp, "couldn't create pipe"); |
| 4986 | 5122 | goto error; |
| 4987 | 5123 | } |
| 4988 | 5124 | outputId = pipeIds[1]; |
| 4989 | 5125 | } |
| 4990 | 5126 | |
| 4991 | - | |
| 5127 | + | |
| 4992 | 5128 | if (pipe_dup_err) { |
| 4993 | 5129 | errorId = outputId; |
| 4994 | 5130 | } |
| 4995 | 5131 | |
| 4996 | - | |
| 5132 | + | |
| 4997 | 5133 | |
| 4998 | 5134 | #ifdef __MINGW32__ |
| 4999 | - pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); | |
| 5135 | + pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId); | |
| 5000 | 5136 | if (pid == JIM_BAD_PID) { |
| 5001 | 5137 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 5002 | 5138 | goto error; |
| 5003 | 5139 | } |
| 5004 | 5140 | #else |
| @@ -5006,32 +5142,37 @@ | ||
| 5006 | 5142 | if (pid < 0) { |
| 5007 | 5143 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 5008 | 5144 | goto error; |
| 5009 | 5145 | } |
| 5010 | 5146 | if (pid == 0) { |
| 5011 | - | |
| 5012 | 5147 | |
| 5013 | - if (inputId != -1) dup2(inputId, 0); | |
| 5014 | - if (outputId != -1) dup2(outputId, 1); | |
| 5015 | - if (errorId != -1) dup2(errorId, 2); | |
| 5148 | + if (inputId != -1) dup2(inputId, fileno(stdin)); | |
| 5149 | + if (outputId != -1) dup2(outputId, fileno(stdout)); | |
| 5150 | + if (errorId != -1) dup2(errorId, fileno(stderr)); | |
| 5016 | 5151 | |
| 5017 | 5152 | for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { |
| 5018 | 5153 | close(i); |
| 5019 | 5154 | } |
| 5020 | 5155 | |
| 5021 | - | |
| 5156 | + | |
| 5022 | 5157 | (void)signal(SIGPIPE, SIG_DFL); |
| 5023 | 5158 | |
| 5024 | 5159 | execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); |
| 5025 | 5160 | |
| 5026 | - | |
| 5027 | 5161 | fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]); |
| 5162 | +#ifdef JIM_MAINTAINER | |
| 5163 | + { | |
| 5164 | + | |
| 5165 | + static char *const false_argv[2] = {"false", NULL}; | |
| 5166 | + execvp(false_argv[0],false_argv); | |
| 5167 | + } | |
| 5168 | +#endif | |
| 5028 | 5169 | _exit(127); |
| 5029 | 5170 | } |
| 5030 | 5171 | #endif |
| 5031 | 5172 | |
| 5032 | - | |
| 5173 | + | |
| 5033 | 5174 | |
| 5034 | 5175 | if (table->used == table->size) { |
| 5035 | 5176 | table->size += WAIT_TABLE_GROW_BY; |
| 5036 | 5177 | table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info)); |
| 5037 | 5178 | } |
| @@ -5040,66 +5181,67 @@ | ||
| 5040 | 5181 | table->info[table->used].flags = 0; |
| 5041 | 5182 | table->used++; |
| 5042 | 5183 | |
| 5043 | 5184 | pidPtr[numPids] = pid; |
| 5044 | 5185 | |
| 5045 | - | |
| 5186 | + | |
| 5046 | 5187 | errorId = origErrorId; |
| 5047 | 5188 | |
| 5048 | 5189 | |
| 5049 | - if (inputId != JIM_BAD_FD) { | |
| 5050 | - JimCloseFd(inputId); | |
| 5190 | + if (inputId != -1) { | |
| 5191 | + close(inputId); | |
| 5051 | 5192 | } |
| 5052 | - if (outputId != JIM_BAD_FD) { | |
| 5053 | - JimCloseFd(outputId); | |
| 5193 | + if (outputId != -1) { | |
| 5194 | + close(outputId); | |
| 5195 | + outputId = -1; | |
| 5054 | 5196 | } |
| 5055 | 5197 | inputId = pipeIds[0]; |
| 5056 | - pipeIds[0] = pipeIds[1] = JIM_BAD_FD; | |
| 5198 | + pipeIds[0] = pipeIds[1] = -1; | |
| 5057 | 5199 | } |
| 5058 | 5200 | *pidArrayPtr = pidPtr; |
| 5059 | 5201 | |
| 5060 | 5202 | |
| 5061 | 5203 | cleanup: |
| 5062 | - if (inputId != JIM_BAD_FD) { | |
| 5063 | - JimCloseFd(inputId); | |
| 5064 | - } | |
| 5065 | - if (lastOutputId != JIM_BAD_FD) { | |
| 5066 | - JimCloseFd(lastOutputId); | |
| 5067 | - } | |
| 5068 | - if (errorId != JIM_BAD_FD) { | |
| 5069 | - JimCloseFd(errorId); | |
| 5204 | + if (inputId != -1) { | |
| 5205 | + close(inputId); | |
| 5206 | + } | |
| 5207 | + if (lastOutputId != -1) { | |
| 5208 | + close(lastOutputId); | |
| 5209 | + } | |
| 5210 | + if (errorId != -1) { | |
| 5211 | + close(errorId); | |
| 5070 | 5212 | } |
| 5071 | 5213 | Jim_Free(arg_array); |
| 5072 | 5214 | |
| 5073 | 5215 | JimRestoreEnv(save_environ); |
| 5074 | 5216 | |
| 5075 | 5217 | return numPids; |
| 5076 | 5218 | |
| 5077 | 5219 | |
| 5078 | 5220 | error: |
| 5079 | - if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) { | |
| 5080 | - JimCloseFd(*inPipePtr); | |
| 5081 | - *inPipePtr = JIM_BAD_FD; | |
| 5082 | - } | |
| 5083 | - if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) { | |
| 5084 | - JimCloseFd(*outPipePtr); | |
| 5085 | - *outPipePtr = JIM_BAD_FD; | |
| 5086 | - } | |
| 5087 | - if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) { | |
| 5088 | - JimCloseFd(*errFilePtr); | |
| 5089 | - *errFilePtr = JIM_BAD_FD; | |
| 5090 | - } | |
| 5091 | - if (pipeIds[0] != JIM_BAD_FD) { | |
| 5092 | - JimCloseFd(pipeIds[0]); | |
| 5093 | - } | |
| 5094 | - if (pipeIds[1] != JIM_BAD_FD) { | |
| 5095 | - JimCloseFd(pipeIds[1]); | |
| 5221 | + if ((inPipePtr != NULL) && (*inPipePtr != -1)) { | |
| 5222 | + close(*inPipePtr); | |
| 5223 | + *inPipePtr = -1; | |
| 5224 | + } | |
| 5225 | + if ((outPipePtr != NULL) && (*outPipePtr != -1)) { | |
| 5226 | + close(*outPipePtr); | |
| 5227 | + *outPipePtr = -1; | |
| 5228 | + } | |
| 5229 | + if ((errFilePtr != NULL) && (*errFilePtr != -1)) { | |
| 5230 | + close(*errFilePtr); | |
| 5231 | + *errFilePtr = -1; | |
| 5232 | + } | |
| 5233 | + if (pipeIds[0] != -1) { | |
| 5234 | + close(pipeIds[0]); | |
| 5235 | + } | |
| 5236 | + if (pipeIds[1] != -1) { | |
| 5237 | + close(pipeIds[1]); | |
| 5096 | 5238 | } |
| 5097 | 5239 | if (pidPtr != NULL) { |
| 5098 | 5240 | for (i = 0; i < numPids; i++) { |
| 5099 | 5241 | if (pidPtr[i] != JIM_BAD_PID) { |
| 5100 | - JimDetachPids(interp, 1, &pidPtr[i]); | |
| 5242 | + JimDetachPids(table, 1, &pidPtr[i]); | |
| 5101 | 5243 | } |
| 5102 | 5244 | } |
| 5103 | 5245 | Jim_Free(pidPtr); |
| 5104 | 5246 | } |
| 5105 | 5247 | numPids = -1; |
| @@ -5111,11 +5253,11 @@ | ||
| 5111 | 5253 | { |
| 5112 | 5254 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 5113 | 5255 | int result = JIM_OK; |
| 5114 | 5256 | int i; |
| 5115 | 5257 | |
| 5116 | - | |
| 5258 | + | |
| 5117 | 5259 | for (i = 0; i < numPids; i++) { |
| 5118 | 5260 | int waitStatus = 0; |
| 5119 | 5261 | if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) { |
| 5120 | 5262 | if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) { |
| 5121 | 5263 | result = JIM_ERR; |
| @@ -5127,234 +5269,30 @@ | ||
| 5127 | 5269 | return result; |
| 5128 | 5270 | } |
| 5129 | 5271 | |
| 5130 | 5272 | int Jim_execInit(Jim_Interp *interp) |
| 5131 | 5273 | { |
| 5274 | + struct WaitInfoTable *waitinfo; | |
| 5132 | 5275 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 5133 | 5276 | return JIM_ERR; |
| 5134 | 5277 | |
| 5135 | 5278 | #ifdef SIGPIPE |
| 5136 | 5279 | (void)signal(SIGPIPE, SIG_IGN); |
| 5137 | 5280 | #endif |
| 5138 | 5281 | |
| 5139 | - Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); | |
| 5282 | + waitinfo = JimAllocWaitInfoTable(); | |
| 5283 | + Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable); | |
| 5284 | + waitinfo->refcount++; | |
| 5285 | + Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable); | |
| 5286 | + Jim_CreateCommand(interp, "pid", Jim_PidCommand, 0, 0); | |
| 5287 | + | |
| 5140 | 5288 | return JIM_OK; |
| 5141 | 5289 | } |
| 5142 | 5290 | |
| 5143 | 5291 | #if defined(__MINGW32__) |
| 5144 | 5292 | |
| 5145 | 5293 | |
| 5146 | -static SECURITY_ATTRIBUTES *JimStdSecAttrs(void) | |
| 5147 | -{ | |
| 5148 | - static SECURITY_ATTRIBUTES secAtts; | |
| 5149 | - | |
| 5150 | - secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); | |
| 5151 | - secAtts.lpSecurityDescriptor = NULL; | |
| 5152 | - secAtts.bInheritHandle = TRUE; | |
| 5153 | - return &secAtts; | |
| 5154 | -} | |
| 5155 | - | |
| 5156 | -static int JimErrno(void) | |
| 5157 | -{ | |
| 5158 | - switch (GetLastError()) { | |
| 5159 | - case ERROR_FILE_NOT_FOUND: return ENOENT; | |
| 5160 | - case ERROR_PATH_NOT_FOUND: return ENOENT; | |
| 5161 | - case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; | |
| 5162 | - case ERROR_ACCESS_DENIED: return EACCES; | |
| 5163 | - case ERROR_INVALID_HANDLE: return EBADF; | |
| 5164 | - case ERROR_BAD_ENVIRONMENT: return E2BIG; | |
| 5165 | - case ERROR_BAD_FORMAT: return ENOEXEC; | |
| 5166 | - case ERROR_INVALID_ACCESS: return EACCES; | |
| 5167 | - case ERROR_INVALID_DRIVE: return ENOENT; | |
| 5168 | - case ERROR_CURRENT_DIRECTORY: return EACCES; | |
| 5169 | - case ERROR_NOT_SAME_DEVICE: return EXDEV; | |
| 5170 | - case ERROR_NO_MORE_FILES: return ENOENT; | |
| 5171 | - case ERROR_WRITE_PROTECT: return EROFS; | |
| 5172 | - case ERROR_BAD_UNIT: return ENXIO; | |
| 5173 | - case ERROR_NOT_READY: return EBUSY; | |
| 5174 | - case ERROR_BAD_COMMAND: return EIO; | |
| 5175 | - case ERROR_CRC: return EIO; | |
| 5176 | - case ERROR_BAD_LENGTH: return EIO; | |
| 5177 | - case ERROR_SEEK: return EIO; | |
| 5178 | - case ERROR_WRITE_FAULT: return EIO; | |
| 5179 | - case ERROR_READ_FAULT: return EIO; | |
| 5180 | - case ERROR_GEN_FAILURE: return EIO; | |
| 5181 | - case ERROR_SHARING_VIOLATION: return EACCES; | |
| 5182 | - case ERROR_LOCK_VIOLATION: return EACCES; | |
| 5183 | - case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; | |
| 5184 | - case ERROR_HANDLE_DISK_FULL: return ENOSPC; | |
| 5185 | - case ERROR_NOT_SUPPORTED: return ENODEV; | |
| 5186 | - case ERROR_REM_NOT_LIST: return EBUSY; | |
| 5187 | - case ERROR_DUP_NAME: return EEXIST; | |
| 5188 | - case ERROR_BAD_NETPATH: return ENOENT; | |
| 5189 | - case ERROR_NETWORK_BUSY: return EBUSY; | |
| 5190 | - case ERROR_DEV_NOT_EXIST: return ENODEV; | |
| 5191 | - case ERROR_TOO_MANY_CMDS: return EAGAIN; | |
| 5192 | - case ERROR_ADAP_HDW_ERR: return EIO; | |
| 5193 | - case ERROR_BAD_NET_RESP: return EIO; | |
| 5194 | - case ERROR_UNEXP_NET_ERR: return EIO; | |
| 5195 | - case ERROR_NETNAME_DELETED: return ENOENT; | |
| 5196 | - case ERROR_NETWORK_ACCESS_DENIED: return EACCES; | |
| 5197 | - case ERROR_BAD_DEV_TYPE: return ENODEV; | |
| 5198 | - case ERROR_BAD_NET_NAME: return ENOENT; | |
| 5199 | - case ERROR_TOO_MANY_NAMES: return ENFILE; | |
| 5200 | - case ERROR_TOO_MANY_SESS: return EIO; | |
| 5201 | - case ERROR_SHARING_PAUSED: return EAGAIN; | |
| 5202 | - case ERROR_REDIR_PAUSED: return EAGAIN; | |
| 5203 | - case ERROR_FILE_EXISTS: return EEXIST; | |
| 5204 | - case ERROR_CANNOT_MAKE: return ENOSPC; | |
| 5205 | - case ERROR_OUT_OF_STRUCTURES: return ENFILE; | |
| 5206 | - case ERROR_ALREADY_ASSIGNED: return EEXIST; | |
| 5207 | - case ERROR_INVALID_PASSWORD: return EPERM; | |
| 5208 | - case ERROR_NET_WRITE_FAULT: return EIO; | |
| 5209 | - case ERROR_NO_PROC_SLOTS: return EAGAIN; | |
| 5210 | - case ERROR_DISK_CHANGE: return EXDEV; | |
| 5211 | - case ERROR_BROKEN_PIPE: return EPIPE; | |
| 5212 | - case ERROR_OPEN_FAILED: return ENOENT; | |
| 5213 | - case ERROR_DISK_FULL: return ENOSPC; | |
| 5214 | - case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; | |
| 5215 | - case ERROR_INVALID_TARGET_HANDLE: return EBADF; | |
| 5216 | - case ERROR_INVALID_NAME: return ENOENT; | |
| 5217 | - case ERROR_PROC_NOT_FOUND: return ESRCH; | |
| 5218 | - case ERROR_WAIT_NO_CHILDREN: return ECHILD; | |
| 5219 | - case ERROR_CHILD_NOT_COMPLETE: return ECHILD; | |
| 5220 | - case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; | |
| 5221 | - case ERROR_SEEK_ON_DEVICE: return ESPIPE; | |
| 5222 | - case ERROR_BUSY_DRIVE: return EAGAIN; | |
| 5223 | - case ERROR_DIR_NOT_EMPTY: return EEXIST; | |
| 5224 | - case ERROR_NOT_LOCKED: return EACCES; | |
| 5225 | - case ERROR_BAD_PATHNAME: return ENOENT; | |
| 5226 | - case ERROR_LOCK_FAILED: return EACCES; | |
| 5227 | - case ERROR_ALREADY_EXISTS: return EEXIST; | |
| 5228 | - case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; | |
| 5229 | - case ERROR_BAD_PIPE: return EPIPE; | |
| 5230 | - case ERROR_PIPE_BUSY: return EAGAIN; | |
| 5231 | - case ERROR_PIPE_NOT_CONNECTED: return EPIPE; | |
| 5232 | - case ERROR_DIRECTORY: return ENOTDIR; | |
| 5233 | - } | |
| 5234 | - return EINVAL; | |
| 5235 | -} | |
| 5236 | - | |
| 5237 | -static int JimPipe(fdtype pipefd[2]) | |
| 5238 | -{ | |
| 5239 | - if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) { | |
| 5240 | - return 0; | |
| 5241 | - } | |
| 5242 | - return -1; | |
| 5243 | -} | |
| 5244 | - | |
| 5245 | -static fdtype JimDupFd(fdtype infd) | |
| 5246 | -{ | |
| 5247 | - fdtype dupfd; | |
| 5248 | - pidtype pid = GetCurrentProcess(); | |
| 5249 | - | |
| 5250 | - if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { | |
| 5251 | - return dupfd; | |
| 5252 | - } | |
| 5253 | - return JIM_BAD_FD; | |
| 5254 | -} | |
| 5255 | - | |
| 5256 | -static int JimRewindFd(fdtype fd) | |
| 5257 | -{ | |
| 5258 | - return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0; | |
| 5259 | -} | |
| 5260 | - | |
| 5261 | -#if 0 | |
| 5262 | -static int JimReadFd(fdtype fd, char *buffer, size_t len) | |
| 5263 | -{ | |
| 5264 | - DWORD num; | |
| 5265 | - | |
| 5266 | - if (ReadFile(fd, buffer, len, &num, NULL)) { | |
| 5267 | - return num; | |
| 5268 | - } | |
| 5269 | - if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) { | |
| 5270 | - return 0; | |
| 5271 | - } | |
| 5272 | - return -1; | |
| 5273 | -} | |
| 5274 | -#endif | |
| 5275 | - | |
| 5276 | -static FILE *JimFdOpenForRead(fdtype fd) | |
| 5277 | -{ | |
| 5278 | - return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r"); | |
| 5279 | -} | |
| 5280 | - | |
| 5281 | -static fdtype JimFileno(FILE *fh) | |
| 5282 | -{ | |
| 5283 | - return (fdtype)_get_osfhandle(_fileno(fh)); | |
| 5284 | -} | |
| 5285 | - | |
| 5286 | -static fdtype JimOpenForRead(const char *filename) | |
| 5287 | -{ | |
| 5288 | - return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, | |
| 5289 | - JimStdSecAttrs(), OPEN_EXISTING, 0, NULL); | |
| 5290 | -} | |
| 5291 | - | |
| 5292 | -static fdtype JimOpenForWrite(const char *filename, int append) | |
| 5293 | -{ | |
| 5294 | - return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, | |
| 5295 | - JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL); | |
| 5296 | -} | |
| 5297 | - | |
| 5298 | -static FILE *JimFdOpenForWrite(fdtype fd) | |
| 5299 | -{ | |
| 5300 | - return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w"); | |
| 5301 | -} | |
| 5302 | - | |
| 5303 | -static pidtype JimWaitPid(pidtype pid, int *status, int nohang) | |
| 5304 | -{ | |
| 5305 | - DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); | |
| 5306 | - if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { | |
| 5307 | - | |
| 5308 | - return JIM_BAD_PID; | |
| 5309 | - } | |
| 5310 | - GetExitCodeProcess(pid, &ret); | |
| 5311 | - *status = ret; | |
| 5312 | - CloseHandle(pid); | |
| 5313 | - return pid; | |
| 5314 | -} | |
| 5315 | - | |
| 5316 | -static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len) | |
| 5317 | -{ | |
| 5318 | - char name[MAX_PATH]; | |
| 5319 | - HANDLE handle; | |
| 5320 | - | |
| 5321 | - if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) { | |
| 5322 | - return JIM_BAD_FD; | |
| 5323 | - } | |
| 5324 | - | |
| 5325 | - handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(), | |
| 5326 | - CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, | |
| 5327 | - NULL); | |
| 5328 | - | |
| 5329 | - if (handle == INVALID_HANDLE_VALUE) { | |
| 5330 | - goto error; | |
| 5331 | - } | |
| 5332 | - | |
| 5333 | - if (contents != NULL) { | |
| 5334 | - | |
| 5335 | - FILE *fh = JimFdOpenForWrite(JimDupFd(handle)); | |
| 5336 | - if (fh == NULL) { | |
| 5337 | - goto error; | |
| 5338 | - } | |
| 5339 | - | |
| 5340 | - if (fwrite(contents, len, 1, fh) != 1) { | |
| 5341 | - fclose(fh); | |
| 5342 | - goto error; | |
| 5343 | - } | |
| 5344 | - fseek(fh, 0, SEEK_SET); | |
| 5345 | - fclose(fh); | |
| 5346 | - } | |
| 5347 | - return handle; | |
| 5348 | - | |
| 5349 | - error: | |
| 5350 | - Jim_SetResultErrno(interp, "failed to create temp file"); | |
| 5351 | - CloseHandle(handle); | |
| 5352 | - DeleteFile(name); | |
| 5353 | - return JIM_BAD_FD; | |
| 5354 | -} | |
| 5355 | - | |
| 5356 | 5294 | static int |
| 5357 | 5295 | JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH]) |
| 5358 | 5296 | { |
| 5359 | 5297 | int i; |
| 5360 | 5298 | static char extensions[][5] = {".exe", "", ".bat"}; |
| @@ -5381,10 +5319,15 @@ | ||
| 5381 | 5319 | |
| 5382 | 5320 | static void JimRestoreEnv(char **env) |
| 5383 | 5321 | { |
| 5384 | 5322 | JimFreeEnv(env, Jim_GetEnviron()); |
| 5385 | 5323 | } |
| 5324 | + | |
| 5325 | +static char **JimOriginalEnviron(void) | |
| 5326 | +{ | |
| 5327 | + return NULL; | |
| 5328 | +} | |
| 5386 | 5329 | |
| 5387 | 5330 | static Jim_Obj * |
| 5388 | 5331 | JimWinBuildCommandLine(Jim_Interp *interp, char **argv) |
| 5389 | 5332 | { |
| 5390 | 5333 | char *start, *special; |
| @@ -5455,18 +5398,19 @@ | ||
| 5455 | 5398 | } |
| 5456 | 5399 | return strObj; |
| 5457 | 5400 | } |
| 5458 | 5401 | |
| 5459 | 5402 | static pidtype |
| 5460 | -JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId) | |
| 5403 | +JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId) | |
| 5461 | 5404 | { |
| 5462 | 5405 | STARTUPINFO startInfo; |
| 5463 | 5406 | PROCESS_INFORMATION procInfo; |
| 5464 | - HANDLE hProcess, h; | |
| 5407 | + HANDLE hProcess; | |
| 5465 | 5408 | char execPath[MAX_PATH]; |
| 5466 | 5409 | pidtype pid = JIM_BAD_PID; |
| 5467 | 5410 | Jim_Obj *cmdLineObj; |
| 5411 | + char *winenv; | |
| 5468 | 5412 | |
| 5469 | 5413 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5470 | 5414 | return JIM_BAD_PID; |
| 5471 | 5415 | } |
| 5472 | 5416 | argv[0] = execPath; |
| @@ -5480,47 +5424,51 @@ | ||
| 5480 | 5424 | startInfo.dwFlags = STARTF_USESTDHANDLES; |
| 5481 | 5425 | startInfo.hStdInput = INVALID_HANDLE_VALUE; |
| 5482 | 5426 | startInfo.hStdOutput= INVALID_HANDLE_VALUE; |
| 5483 | 5427 | startInfo.hStdError = INVALID_HANDLE_VALUE; |
| 5484 | 5428 | |
| 5485 | - if (inputId == JIM_BAD_FD) { | |
| 5486 | - if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { | |
| 5487 | - CloseHandle(h); | |
| 5488 | - } | |
| 5489 | - } else { | |
| 5490 | - DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput, | |
| 5491 | - 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 5492 | - } | |
| 5493 | - if (startInfo.hStdInput == JIM_BAD_FD) { | |
| 5494 | - goto end; | |
| 5495 | - } | |
| 5496 | - | |
| 5497 | - if (outputId == JIM_BAD_FD) { | |
| 5498 | - startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0, | |
| 5499 | - JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
| 5500 | - } else { | |
| 5501 | - DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput, | |
| 5502 | - 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 5503 | - } | |
| 5504 | - if (startInfo.hStdOutput == JIM_BAD_FD) { | |
| 5505 | - goto end; | |
| 5506 | - } | |
| 5507 | - | |
| 5508 | - if (errorId == JIM_BAD_FD) { | |
| 5509 | - | |
| 5510 | - startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0, | |
| 5511 | - JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| 5512 | - } else { | |
| 5513 | - DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError, | |
| 5514 | - 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 5515 | - } | |
| 5516 | - if (startInfo.hStdError == JIM_BAD_FD) { | |
| 5517 | - goto end; | |
| 5518 | - } | |
| 5519 | - | |
| 5520 | - if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE, | |
| 5521 | - 0, env, NULL, &startInfo, &procInfo)) { | |
| 5429 | + if (inputId == -1) { | |
| 5430 | + inputId = _fileno(stdin); | |
| 5431 | + } | |
| 5432 | + DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(inputId), hProcess, &startInfo.hStdInput, | |
| 5433 | + 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 5434 | + if (startInfo.hStdInput == INVALID_HANDLE_VALUE) { | |
| 5435 | + goto end; | |
| 5436 | + } | |
| 5437 | + | |
| 5438 | + if (outputId == -1) { | |
| 5439 | + outputId = _fileno(stdout); | |
| 5440 | + } | |
| 5441 | + DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(outputId), hProcess, &startInfo.hStdOutput, | |
| 5442 | + 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 5443 | + if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) { | |
| 5444 | + goto end; | |
| 5445 | + } | |
| 5446 | + | |
| 5447 | + | |
| 5448 | + if (errorId == -1) { | |
| 5449 | + errorId = _fileno(stderr); | |
| 5450 | + } | |
| 5451 | + DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(errorId), hProcess, &startInfo.hStdError, | |
| 5452 | + 0, TRUE, DUPLICATE_SAME_ACCESS); | |
| 5453 | + if (startInfo.hStdError == INVALID_HANDLE_VALUE) { | |
| 5454 | + goto end; | |
| 5455 | + } | |
| 5456 | + | |
| 5457 | + if (env == NULL) { | |
| 5458 | + | |
| 5459 | + winenv = NULL; | |
| 5460 | + } | |
| 5461 | + else if (env[0] == NULL) { | |
| 5462 | + winenv = (char *)"\0"; | |
| 5463 | + } | |
| 5464 | + else { | |
| 5465 | + winenv = env[0]; | |
| 5466 | + } | |
| 5467 | + | |
| 5468 | + if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE, | |
| 5469 | + 0, winenv, NULL, &startInfo, &procInfo)) { | |
| 5522 | 5470 | goto end; |
| 5523 | 5471 | } |
| 5524 | 5472 | |
| 5525 | 5473 | |
| 5526 | 5474 | WaitForInputIdle(procInfo.hProcess, 5000); |
| @@ -5528,49 +5476,27 @@ | ||
| 5528 | 5476 | |
| 5529 | 5477 | pid = procInfo.hProcess; |
| 5530 | 5478 | |
| 5531 | 5479 | end: |
| 5532 | 5480 | Jim_FreeNewObj(interp, cmdLineObj); |
| 5533 | - if (startInfo.hStdInput != JIM_BAD_FD) { | |
| 5481 | + if (startInfo.hStdInput != INVALID_HANDLE_VALUE) { | |
| 5534 | 5482 | CloseHandle(startInfo.hStdInput); |
| 5535 | 5483 | } |
| 5536 | - if (startInfo.hStdOutput != JIM_BAD_FD) { | |
| 5484 | + if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) { | |
| 5537 | 5485 | CloseHandle(startInfo.hStdOutput); |
| 5538 | 5486 | } |
| 5539 | - if (startInfo.hStdError != JIM_BAD_FD) { | |
| 5487 | + if (startInfo.hStdError != INVALID_HANDLE_VALUE) { | |
| 5540 | 5488 | CloseHandle(startInfo.hStdError); |
| 5541 | 5489 | } |
| 5542 | 5490 | return pid; |
| 5543 | 5491 | } |
| 5492 | + | |
| 5544 | 5493 | #else |
| 5545 | 5494 | |
| 5546 | -static int JimOpenForWrite(const char *filename, int append) | |
| 5547 | -{ | |
| 5548 | - return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); | |
| 5549 | -} | |
| 5550 | - | |
| 5551 | -static int JimRewindFd(int fd) | |
| 5552 | -{ | |
| 5553 | - return lseek(fd, 0L, SEEK_SET); | |
| 5554 | -} | |
| 5555 | - | |
| 5556 | -static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len) | |
| 5557 | -{ | |
| 5558 | - int fd = Jim_MakeTempFile(interp, NULL); | |
| 5559 | - | |
| 5560 | - if (fd != JIM_BAD_FD) { | |
| 5561 | - unlink(Jim_String(Jim_GetResult(interp))); | |
| 5562 | - if (contents) { | |
| 5563 | - if (write(fd, contents, len) != len) { | |
| 5564 | - Jim_SetResultErrno(interp, "couldn't write temp file"); | |
| 5565 | - close(fd); | |
| 5566 | - return -1; | |
| 5567 | - } | |
| 5568 | - lseek(fd, 0L, SEEK_SET); | |
| 5569 | - } | |
| 5570 | - } | |
| 5571 | - return fd; | |
| 5495 | +static char **JimOriginalEnviron(void) | |
| 5496 | +{ | |
| 5497 | + return Jim_GetEnviron(); | |
| 5572 | 5498 | } |
| 5573 | 5499 | |
| 5574 | 5500 | static char **JimSaveEnv(char **env) |
| 5575 | 5501 | { |
| 5576 | 5502 | char **saveenv = Jim_GetEnviron(); |
| @@ -5585,13 +5511,21 @@ | ||
| 5585 | 5511 | } |
| 5586 | 5512 | #endif |
| 5587 | 5513 | #endif |
| 5588 | 5514 | |
| 5589 | 5515 | |
| 5516 | + | |
| 5517 | +#ifdef STRPTIME_NEEDS_XOPEN_SOURCE | |
| 5590 | 5518 | #ifndef _XOPEN_SOURCE |
| 5591 | 5519 | #define _XOPEN_SOURCE 500 |
| 5592 | 5520 | #endif |
| 5521 | +#endif | |
| 5522 | + | |
| 5523 | + | |
| 5524 | +#ifndef _GNU_SOURCE | |
| 5525 | +#define _GNU_SOURCE | |
| 5526 | +#endif | |
| 5593 | 5527 | |
| 5594 | 5528 | #include <stdlib.h> |
| 5595 | 5529 | #include <string.h> |
| 5596 | 5530 | #include <stdio.h> |
| 5597 | 5531 | #include <time.h> |
| @@ -5598,65 +5532,126 @@ | ||
| 5598 | 5532 | |
| 5599 | 5533 | |
| 5600 | 5534 | #ifdef HAVE_SYS_TIME_H |
| 5601 | 5535 | #include <sys/time.h> |
| 5602 | 5536 | #endif |
| 5537 | + | |
| 5538 | +struct clock_options { | |
| 5539 | + int gmt; | |
| 5540 | + const char *format; | |
| 5541 | +}; | |
| 5542 | + | |
| 5543 | +static int parse_clock_options(Jim_Interp *interp, int argc, Jim_Obj *const *argv, struct clock_options *opts) | |
| 5544 | +{ | |
| 5545 | + static const char * const options[] = { "-gmt", "-format", NULL }; | |
| 5546 | + enum { OPT_GMT, OPT_FORMAT, }; | |
| 5547 | + int i; | |
| 5548 | + | |
| 5549 | + for (i = 0; i < argc; i += 2) { | |
| 5550 | + int option; | |
| 5551 | + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { | |
| 5552 | + return JIM_ERR; | |
| 5553 | + } | |
| 5554 | + switch (option) { | |
| 5555 | + case OPT_GMT: | |
| 5556 | + if (Jim_GetBoolean(interp, argv[i + 1], &opts->gmt) != JIM_OK) { | |
| 5557 | + return JIM_ERR; | |
| 5558 | + } | |
| 5559 | + break; | |
| 5560 | + case OPT_FORMAT: | |
| 5561 | + opts->format = Jim_String(argv[i + 1]); | |
| 5562 | + break; | |
| 5563 | + } | |
| 5564 | + } | |
| 5565 | + return JIM_OK; | |
| 5566 | +} | |
| 5603 | 5567 | |
| 5604 | 5568 | static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5605 | 5569 | { |
| 5606 | - | |
| 5570 | + | |
| 5607 | 5571 | char buf[100]; |
| 5608 | 5572 | time_t t; |
| 5609 | - long seconds; | |
| 5573 | + jim_wide seconds; | |
| 5574 | + struct clock_options options = { 0, "%a %b %d %H:%M:%S %Z %Y" }; | |
| 5575 | + struct tm *tm; | |
| 5610 | 5576 | |
| 5611 | - const char *format = "%a %b %d %H:%M:%S %Z %Y"; | |
| 5612 | - | |
| 5613 | - if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { | |
| 5577 | + if (Jim_GetWide(interp, argv[0], &seconds) != JIM_OK) { | |
| 5578 | + return JIM_ERR; | |
| 5579 | + } | |
| 5580 | + if (argc % 2 == 0) { | |
| 5614 | 5581 | return -1; |
| 5615 | 5582 | } |
| 5616 | - | |
| 5617 | - if (argc == 3) { | |
| 5618 | - format = Jim_String(argv[2]); | |
| 5583 | + if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) { | |
| 5584 | + return JIM_ERR; | |
| 5619 | 5585 | } |
| 5620 | 5586 | |
| 5621 | - if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { | |
| 5622 | - return JIM_ERR; | |
| 5623 | - } | |
| 5624 | 5587 | t = seconds; |
| 5588 | + tm = options.gmt ? gmtime(&t) : localtime(&t); | |
| 5625 | 5589 | |
| 5626 | - if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) { | |
| 5627 | - Jim_SetResultString(interp, "format string too long", -1); | |
| 5590 | + if (tm == NULL || strftime(buf, sizeof(buf), options.format, tm) == 0) { | |
| 5591 | + Jim_SetResultString(interp, "format string too long or invalid time", -1); | |
| 5628 | 5592 | return JIM_ERR; |
| 5629 | 5593 | } |
| 5630 | 5594 | |
| 5631 | 5595 | Jim_SetResultString(interp, buf, -1); |
| 5632 | 5596 | |
| 5633 | 5597 | return JIM_OK; |
| 5634 | 5598 | } |
| 5635 | 5599 | |
| 5636 | 5600 | #ifdef HAVE_STRPTIME |
| 5601 | +#ifndef HAVE_TIMEGM | |
| 5602 | + | |
| 5603 | +static time_t timegm(struct tm *tm) | |
| 5604 | +{ | |
| 5605 | + time_t t; | |
| 5606 | + const char *tz = getenv("TZ"); | |
| 5607 | + setenv("TZ", "", 1); | |
| 5608 | + tzset(); | |
| 5609 | + t = mktime(tm); | |
| 5610 | + if (tz) { | |
| 5611 | + setenv("TZ", tz, 1); | |
| 5612 | + } | |
| 5613 | + else { | |
| 5614 | + unsetenv("TZ"); | |
| 5615 | + } | |
| 5616 | + tzset(); | |
| 5617 | + return t; | |
| 5618 | +} | |
| 5619 | +#endif | |
| 5620 | + | |
| 5637 | 5621 | static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5638 | 5622 | { |
| 5639 | 5623 | char *pt; |
| 5640 | 5624 | struct tm tm; |
| 5641 | - time_t now = time(0); | |
| 5642 | 5625 | |
| 5643 | - if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) { | |
| 5626 | + | |
| 5627 | + struct clock_options options = { 0, NULL }; | |
| 5628 | + | |
| 5629 | + if (argc % 2 == 0) { | |
| 5630 | + return -1; | |
| 5631 | + } | |
| 5632 | + | |
| 5633 | + if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) { | |
| 5634 | + return JIM_ERR; | |
| 5635 | + } | |
| 5636 | + if (options.format == NULL) { | |
| 5644 | 5637 | return -1; |
| 5645 | 5638 | } |
| 5646 | 5639 | |
| 5647 | - | |
| 5648 | - localtime_r(&now, &tm); | |
| 5649 | 5640 | |
| 5650 | - pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm); | |
| 5641 | + memset(&tm, 0, sizeof(tm)); | |
| 5642 | + | |
| 5643 | + tm.tm_mday = 1; | |
| 5644 | + | |
| 5645 | + pt = strptime(Jim_String(argv[0]), options.format, &tm); | |
| 5651 | 5646 | if (pt == 0 || *pt != 0) { |
| 5652 | 5647 | Jim_SetResultString(interp, "Failed to parse time according to format", -1); |
| 5653 | 5648 | return JIM_ERR; |
| 5654 | 5649 | } |
| 5655 | 5650 | |
| 5656 | - | |
| 5657 | - Jim_SetResultInt(interp, mktime(&tm)); | |
| 5651 | + | |
| 5652 | + Jim_SetResultInt(interp, options.gmt ? timegm(&tm) : mktime(&tm)); | |
| 5658 | 5653 | |
| 5659 | 5654 | return JIM_OK; |
| 5660 | 5655 | } |
| 5661 | 5656 | #endif |
| 5662 | 5657 | |
| @@ -5688,54 +5683,54 @@ | ||
| 5688 | 5683 | |
| 5689 | 5684 | return JIM_OK; |
| 5690 | 5685 | } |
| 5691 | 5686 | |
| 5692 | 5687 | static const jim_subcmd_type clock_command_table[] = { |
| 5693 | - { "seconds", | |
| 5694 | - NULL, | |
| 5695 | - clock_cmd_seconds, | |
| 5696 | - 0, | |
| 5697 | - 0, | |
| 5698 | - | |
| 5699 | - }, | |
| 5700 | 5688 | { "clicks", |
| 5701 | 5689 | NULL, |
| 5702 | 5690 | clock_cmd_micros, |
| 5703 | 5691 | 0, |
| 5704 | 5692 | 0, |
| 5705 | - | |
| 5693 | + | |
| 5694 | + }, | |
| 5695 | + { "format", | |
| 5696 | + "seconds ?-format string? ?-gmt boolean?", | |
| 5697 | + clock_cmd_format, | |
| 5698 | + 1, | |
| 5699 | + 5, | |
| 5700 | + | |
| 5706 | 5701 | }, |
| 5707 | 5702 | { "microseconds", |
| 5708 | 5703 | NULL, |
| 5709 | 5704 | clock_cmd_micros, |
| 5710 | 5705 | 0, |
| 5711 | 5706 | 0, |
| 5712 | - | |
| 5707 | + | |
| 5713 | 5708 | }, |
| 5714 | 5709 | { "milliseconds", |
| 5715 | 5710 | NULL, |
| 5716 | 5711 | clock_cmd_millis, |
| 5717 | 5712 | 0, |
| 5718 | 5713 | 0, |
| 5719 | - | |
| 5720 | - }, | |
| 5721 | - { "format", | |
| 5722 | - "seconds ?-format format?", | |
| 5723 | - clock_cmd_format, | |
| 5724 | - 1, | |
| 5725 | - 3, | |
| 5726 | - | |
| 5714 | + | |
| 5727 | 5715 | }, |
| 5728 | 5716 | #ifdef HAVE_STRPTIME |
| 5729 | 5717 | { "scan", |
| 5730 | - "str -format format", | |
| 5718 | + "str -format format ?-gmt boolean?", | |
| 5731 | 5719 | clock_cmd_scan, |
| 5732 | 5720 | 3, |
| 5733 | - 3, | |
| 5734 | - | |
| 5721 | + 5, | |
| 5722 | + | |
| 5735 | 5723 | }, |
| 5736 | 5724 | #endif |
| 5725 | + { "seconds", | |
| 5726 | + NULL, | |
| 5727 | + clock_cmd_seconds, | |
| 5728 | + 0, | |
| 5729 | + 0, | |
| 5730 | + | |
| 5731 | + }, | |
| 5737 | 5732 | { NULL } |
| 5738 | 5733 | }; |
| 5739 | 5734 | |
| 5740 | 5735 | int Jim_clockInit(Jim_Interp *interp) |
| 5741 | 5736 | { |
| @@ -5753,12 +5748,13 @@ | ||
| 5753 | 5748 | #include <errno.h> |
| 5754 | 5749 | |
| 5755 | 5750 | |
| 5756 | 5751 | static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5757 | 5752 | { |
| 5758 | - | |
| 5759 | - Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0); | |
| 5753 | + | |
| 5754 | + Jim_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); | |
| 5755 | + Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1); | |
| 5760 | 5756 | return JIM_OK; |
| 5761 | 5757 | } |
| 5762 | 5758 | |
| 5763 | 5759 | static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5764 | 5760 | { |
| @@ -5769,21 +5765,20 @@ | ||
| 5769 | 5765 | return JIM_OK; |
| 5770 | 5766 | } |
| 5771 | 5767 | |
| 5772 | 5768 | patternObj = (argc == 1) ? NULL : argv[1]; |
| 5773 | 5769 | |
| 5774 | - | |
| 5770 | + | |
| 5775 | 5771 | if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { |
| 5776 | 5772 | if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { |
| 5777 | - | |
| 5773 | + | |
| 5778 | 5774 | Jim_SetResult(interp, objPtr); |
| 5779 | 5775 | return JIM_OK; |
| 5780 | 5776 | } |
| 5781 | 5777 | } |
| 5782 | 5778 | |
| 5783 | - | |
| 5784 | - return Jim_DictValues(interp, objPtr, patternObj); | |
| 5779 | + return Jim_DictMatchTypes(interp, objPtr, patternObj, JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS | JIM_DICTMATCH_VALUES); | |
| 5785 | 5780 | } |
| 5786 | 5781 | |
| 5787 | 5782 | static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5788 | 5783 | { |
| 5789 | 5784 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| @@ -5790,11 +5785,11 @@ | ||
| 5790 | 5785 | |
| 5791 | 5786 | if (!objPtr) { |
| 5792 | 5787 | return JIM_OK; |
| 5793 | 5788 | } |
| 5794 | 5789 | |
| 5795 | - return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]); | |
| 5790 | + return Jim_DictMatchTypes(interp, objPtr, argc == 1 ? NULL : argv[1], JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS); | |
| 5796 | 5791 | } |
| 5797 | 5792 | |
| 5798 | 5793 | static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5799 | 5794 | { |
| 5800 | 5795 | int i; |
| @@ -5802,27 +5797,29 @@ | ||
| 5802 | 5797 | Jim_Obj *resultObj; |
| 5803 | 5798 | Jim_Obj *objPtr; |
| 5804 | 5799 | Jim_Obj **dictValuesObj; |
| 5805 | 5800 | |
| 5806 | 5801 | if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { |
| 5807 | - | |
| 5802 | + | |
| 5808 | 5803 | Jim_UnsetVariable(interp, argv[0], JIM_NONE); |
| 5809 | 5804 | return JIM_OK; |
| 5810 | 5805 | } |
| 5811 | 5806 | |
| 5812 | 5807 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5813 | 5808 | |
| 5814 | 5809 | if (objPtr == NULL) { |
| 5815 | - | |
| 5810 | + | |
| 5816 | 5811 | return JIM_OK; |
| 5817 | 5812 | } |
| 5818 | 5813 | |
| 5819 | 5814 | if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 5820 | - return JIM_ERR; | |
| 5815 | + | |
| 5816 | + Jim_SetResultString(interp, "", -1); | |
| 5817 | + return JIM_OK; | |
| 5821 | 5818 | } |
| 5822 | 5819 | |
| 5823 | - | |
| 5820 | + | |
| 5824 | 5821 | resultObj = Jim_NewDictObj(interp, NULL, 0); |
| 5825 | 5822 | |
| 5826 | 5823 | for (i = 0; i < len; i += 2) { |
| 5827 | 5824 | if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { |
| 5828 | 5825 | Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); |
| @@ -5837,16 +5834,18 @@ | ||
| 5837 | 5834 | static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5838 | 5835 | { |
| 5839 | 5836 | Jim_Obj *objPtr; |
| 5840 | 5837 | int len = 0; |
| 5841 | 5838 | |
| 5842 | - | |
| 5839 | + | |
| 5843 | 5840 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5844 | 5841 | if (objPtr) { |
| 5845 | 5842 | len = Jim_DictSize(interp, objPtr); |
| 5846 | 5843 | if (len < 0) { |
| 5847 | - return JIM_ERR; | |
| 5844 | + | |
| 5845 | + Jim_SetResultInt(interp, 0); | |
| 5846 | + return JIM_OK; | |
| 5848 | 5847 | } |
| 5849 | 5848 | } |
| 5850 | 5849 | |
| 5851 | 5850 | Jim_SetResultInt(interp, len); |
| 5852 | 5851 | |
| @@ -5876,11 +5875,11 @@ | ||
| 5876 | 5875 | return JIM_ERR; |
| 5877 | 5876 | } |
| 5878 | 5877 | |
| 5879 | 5878 | dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5880 | 5879 | if (!dictObj) { |
| 5881 | - | |
| 5880 | + | |
| 5882 | 5881 | return Jim_SetVariable(interp, argv[0], listObj); |
| 5883 | 5882 | } |
| 5884 | 5883 | else if (Jim_DictSize(interp, dictObj) < 0) { |
| 5885 | 5884 | return JIM_ERR; |
| 5886 | 5885 | } |
| @@ -5905,53 +5904,53 @@ | ||
| 5905 | 5904 | { "exists", |
| 5906 | 5905 | "arrayName", |
| 5907 | 5906 | array_cmd_exists, |
| 5908 | 5907 | 1, |
| 5909 | 5908 | 1, |
| 5910 | - | |
| 5909 | + | |
| 5911 | 5910 | }, |
| 5912 | 5911 | { "get", |
| 5913 | 5912 | "arrayName ?pattern?", |
| 5914 | 5913 | array_cmd_get, |
| 5915 | 5914 | 1, |
| 5916 | 5915 | 2, |
| 5917 | - | |
| 5916 | + | |
| 5918 | 5917 | }, |
| 5919 | 5918 | { "names", |
| 5920 | 5919 | "arrayName ?pattern?", |
| 5921 | 5920 | array_cmd_names, |
| 5922 | 5921 | 1, |
| 5923 | 5922 | 2, |
| 5924 | - | |
| 5923 | + | |
| 5925 | 5924 | }, |
| 5926 | 5925 | { "set", |
| 5927 | 5926 | "arrayName list", |
| 5928 | 5927 | array_cmd_set, |
| 5929 | 5928 | 2, |
| 5930 | 5929 | 2, |
| 5931 | - | |
| 5930 | + | |
| 5932 | 5931 | }, |
| 5933 | 5932 | { "size", |
| 5934 | 5933 | "arrayName", |
| 5935 | 5934 | array_cmd_size, |
| 5936 | 5935 | 1, |
| 5937 | 5936 | 1, |
| 5938 | - | |
| 5937 | + | |
| 5939 | 5938 | }, |
| 5940 | 5939 | { "stat", |
| 5941 | 5940 | "arrayName", |
| 5942 | 5941 | array_cmd_stat, |
| 5943 | 5942 | 1, |
| 5944 | 5943 | 1, |
| 5945 | - | |
| 5944 | + | |
| 5946 | 5945 | }, |
| 5947 | 5946 | { "unset", |
| 5948 | 5947 | "arrayName ?pattern?", |
| 5949 | 5948 | array_cmd_unset, |
| 5950 | 5949 | 1, |
| 5951 | 5950 | 2, |
| 5952 | - | |
| 5951 | + | |
| 5953 | 5952 | }, |
| 5954 | 5953 | { NULL |
| 5955 | 5954 | } |
| 5956 | 5955 | }; |
| 5957 | 5956 | |
| @@ -5987,11 +5986,14 @@ | ||
| 5987 | 5986 | Jim_arrayInit(interp); |
| 5988 | 5987 | Jim_stdlibInit(interp); |
| 5989 | 5988 | Jim_tclcompatInit(interp); |
| 5990 | 5989 | return JIM_OK; |
| 5991 | 5990 | } |
| 5992 | -#define JIM_OPTIMIZATION | |
| 5991 | +#define JIM_OPTIMIZATION | |
| 5992 | +#ifndef _GNU_SOURCE | |
| 5993 | +#define _GNU_SOURCE | |
| 5994 | +#endif | |
| 5993 | 5995 | |
| 5994 | 5996 | #include <stdio.h> |
| 5995 | 5997 | #include <stdlib.h> |
| 5996 | 5998 | |
| 5997 | 5999 | #include <string.h> |
| @@ -6056,10 +6058,16 @@ | ||
| 6056 | 6058 | #define JimPanic(X) JimPanicDump X |
| 6057 | 6059 | #else |
| 6058 | 6060 | #define JimPanic(X) |
| 6059 | 6061 | #endif |
| 6060 | 6062 | |
| 6063 | +#ifdef JIM_OPTIMIZATION | |
| 6064 | +#define JIM_IF_OPTIM(X) X | |
| 6065 | +#else | |
| 6066 | +#define JIM_IF_OPTIM(X) | |
| 6067 | +#endif | |
| 6068 | + | |
| 6061 | 6069 | |
| 6062 | 6070 | static char JimEmptyStringRep[] = ""; |
| 6063 | 6071 | |
| 6064 | 6072 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); |
| 6065 | 6073 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| @@ -6112,34 +6120,34 @@ | ||
| 6112 | 6120 | if (*pattern == '^') { |
| 6113 | 6121 | not++; |
| 6114 | 6122 | pattern++; |
| 6115 | 6123 | } |
| 6116 | 6124 | |
| 6117 | - | |
| 6125 | + | |
| 6118 | 6126 | if (*pattern == ']') { |
| 6119 | 6127 | goto first; |
| 6120 | 6128 | } |
| 6121 | 6129 | } |
| 6122 | 6130 | |
| 6123 | 6131 | while (*pattern && *pattern != ']') { |
| 6124 | - | |
| 6132 | + | |
| 6125 | 6133 | if (pattern[0] == '\\') { |
| 6126 | 6134 | first: |
| 6127 | 6135 | pattern += utf8_tounicode_case(pattern, &pchar, nocase); |
| 6128 | 6136 | } |
| 6129 | 6137 | else { |
| 6130 | - | |
| 6138 | + | |
| 6131 | 6139 | int start; |
| 6132 | 6140 | int end; |
| 6133 | 6141 | |
| 6134 | 6142 | pattern += utf8_tounicode_case(pattern, &start, nocase); |
| 6135 | 6143 | if (pattern[0] == '-' && pattern[1]) { |
| 6136 | - | |
| 6137 | - pattern += utf8_tounicode(pattern, &pchar); | |
| 6144 | + | |
| 6145 | + pattern++; | |
| 6138 | 6146 | pattern += utf8_tounicode_case(pattern, &end, nocase); |
| 6139 | 6147 | |
| 6140 | - | |
| 6148 | + | |
| 6141 | 6149 | if ((c >= start && c <= end) || (c >= end && c <= start)) { |
| 6142 | 6150 | match = 1; |
| 6143 | 6151 | } |
| 6144 | 6152 | continue; |
| 6145 | 6153 | } |
| @@ -6169,19 +6177,19 @@ | ||
| 6169 | 6177 | while (pattern[1] == '*') { |
| 6170 | 6178 | pattern++; |
| 6171 | 6179 | } |
| 6172 | 6180 | pattern++; |
| 6173 | 6181 | if (!pattern[0]) { |
| 6174 | - return 1; | |
| 6182 | + return 1; | |
| 6175 | 6183 | } |
| 6176 | 6184 | while (*string) { |
| 6177 | - | |
| 6185 | + | |
| 6178 | 6186 | if (JimGlobMatch(pattern, string, nocase)) |
| 6179 | - return 1; | |
| 6187 | + return 1; | |
| 6180 | 6188 | string += utf8_tounicode(string, &c); |
| 6181 | 6189 | } |
| 6182 | - return 0; | |
| 6190 | + return 0; | |
| 6183 | 6191 | |
| 6184 | 6192 | case '?': |
| 6185 | 6193 | string += utf8_tounicode(string, &c); |
| 6186 | 6194 | break; |
| 6187 | 6195 | |
| @@ -6190,20 +6198,20 @@ | ||
| 6190 | 6198 | pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); |
| 6191 | 6199 | if (!pattern) { |
| 6192 | 6200 | return 0; |
| 6193 | 6201 | } |
| 6194 | 6202 | if (!*pattern) { |
| 6195 | - | |
| 6203 | + | |
| 6196 | 6204 | continue; |
| 6197 | 6205 | } |
| 6198 | 6206 | break; |
| 6199 | 6207 | } |
| 6200 | 6208 | case '\\': |
| 6201 | 6209 | if (pattern[1]) { |
| 6202 | 6210 | pattern++; |
| 6203 | 6211 | } |
| 6204 | - | |
| 6212 | + | |
| 6205 | 6213 | default: |
| 6206 | 6214 | string += utf8_tounicode_case(string, &c, nocase); |
| 6207 | 6215 | utf8_tounicode_case(pattern, &pchar, nocase); |
| 6208 | 6216 | if (pchar != c) { |
| 6209 | 6217 | return 0; |
| @@ -6249,11 +6257,11 @@ | ||
| 6249 | 6257 | maxchars--; |
| 6250 | 6258 | } |
| 6251 | 6259 | if (!maxchars) { |
| 6252 | 6260 | return 0; |
| 6253 | 6261 | } |
| 6254 | - | |
| 6262 | + | |
| 6255 | 6263 | if (*s1) { |
| 6256 | 6264 | return 1; |
| 6257 | 6265 | } |
| 6258 | 6266 | if (*s2) { |
| 6259 | 6267 | return -1; |
| @@ -6290,11 +6298,11 @@ | ||
| 6290 | 6298 | const char *p; |
| 6291 | 6299 | |
| 6292 | 6300 | if (!l1 || !l2 || l1 > l2) |
| 6293 | 6301 | return -1; |
| 6294 | 6302 | |
| 6295 | - | |
| 6303 | + | |
| 6296 | 6304 | for (p = s2 + l2 - 1; p != s2 - 1; p--) { |
| 6297 | 6305 | if (*p == *s1 && memcmp(s1, p, l1) == 0) { |
| 6298 | 6306 | return p - s2; |
| 6299 | 6307 | } |
| 6300 | 6308 | } |
| @@ -6349,28 +6357,28 @@ | ||
| 6349 | 6357 | } |
| 6350 | 6358 | *sign = 1; |
| 6351 | 6359 | } |
| 6352 | 6360 | |
| 6353 | 6361 | if (str[i] != '0') { |
| 6354 | - | |
| 6362 | + | |
| 6355 | 6363 | return 0; |
| 6356 | 6364 | } |
| 6357 | 6365 | |
| 6358 | - | |
| 6366 | + | |
| 6359 | 6367 | switch (str[i + 1]) { |
| 6360 | 6368 | case 'x': case 'X': *base = 16; break; |
| 6361 | 6369 | case 'o': case 'O': *base = 8; break; |
| 6362 | 6370 | case 'b': case 'B': *base = 2; break; |
| 6363 | 6371 | default: return 0; |
| 6364 | 6372 | } |
| 6365 | 6373 | i += 2; |
| 6366 | - | |
| 6374 | + | |
| 6367 | 6375 | if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) { |
| 6368 | - | |
| 6376 | + | |
| 6369 | 6377 | return i; |
| 6370 | 6378 | } |
| 6371 | - | |
| 6379 | + | |
| 6372 | 6380 | *base = 10; |
| 6373 | 6381 | return 0; |
| 6374 | 6382 | } |
| 6375 | 6383 | |
| 6376 | 6384 | static long jim_strtol(const char *str, char **endptr) |
| @@ -6384,11 +6392,11 @@ | ||
| 6384 | 6392 | if (endptr == NULL || *endptr != str + i) { |
| 6385 | 6393 | return value * sign; |
| 6386 | 6394 | } |
| 6387 | 6395 | } |
| 6388 | 6396 | |
| 6389 | - | |
| 6397 | + | |
| 6390 | 6398 | return strtol(str, endptr, 10); |
| 6391 | 6399 | } |
| 6392 | 6400 | |
| 6393 | 6401 | |
| 6394 | 6402 | static jim_wide jim_strtoull(const char *str, char **endptr) |
| @@ -6403,11 +6411,11 @@ | ||
| 6403 | 6411 | if (endptr == NULL || *endptr != str + i) { |
| 6404 | 6412 | return value * sign; |
| 6405 | 6413 | } |
| 6406 | 6414 | } |
| 6407 | 6415 | |
| 6408 | - | |
| 6416 | + | |
| 6409 | 6417 | return strtoull(str, endptr, 10); |
| 6410 | 6418 | #else |
| 6411 | 6419 | return (unsigned long)jim_strtol(str, endptr); |
| 6412 | 6420 | #endif |
| 6413 | 6421 | } |
| @@ -6428,26 +6436,40 @@ | ||
| 6428 | 6436 | |
| 6429 | 6437 | int Jim_StringToDouble(const char *str, double *doublePtr) |
| 6430 | 6438 | { |
| 6431 | 6439 | char *endptr; |
| 6432 | 6440 | |
| 6433 | - | |
| 6441 | + | |
| 6434 | 6442 | errno = 0; |
| 6435 | 6443 | |
| 6436 | 6444 | *doublePtr = strtod(str, &endptr); |
| 6437 | 6445 | |
| 6438 | 6446 | return JimCheckConversion(str, endptr); |
| 6439 | 6447 | } |
| 6440 | 6448 | |
| 6441 | 6449 | static jim_wide JimPowWide(jim_wide b, jim_wide e) |
| 6442 | 6450 | { |
| 6443 | - jim_wide i, res = 1; | |
| 6451 | + jim_wide res = 1; | |
| 6444 | 6452 | |
| 6445 | - if ((b == 0 && e != 0) || (e < 0)) | |
| 6446 | - return 0; | |
| 6447 | - for (i = 0; i < e; i++) { | |
| 6448 | - res *= b; | |
| 6453 | + | |
| 6454 | + if (b == 1) { | |
| 6455 | + | |
| 6456 | + return 1; | |
| 6457 | + } | |
| 6458 | + if (e < 0) { | |
| 6459 | + if (b != -1) { | |
| 6460 | + return 0; | |
| 6461 | + } | |
| 6462 | + e = -e; | |
| 6463 | + } | |
| 6464 | + while (e) | |
| 6465 | + { | |
| 6466 | + if (e & 1) { | |
| 6467 | + res *= b; | |
| 6468 | + } | |
| 6469 | + e >>= 1; | |
| 6470 | + b *= b; | |
| 6449 | 6471 | } |
| 6450 | 6472 | return res; |
| 6451 | 6473 | } |
| 6452 | 6474 | |
| 6453 | 6475 | #ifdef JIM_DEBUG_PANIC |
| @@ -6509,11 +6531,11 @@ | ||
| 6509 | 6531 | char *Jim_StrDupLen(const char *s, int l) |
| 6510 | 6532 | { |
| 6511 | 6533 | char *copy = Jim_Alloc(l + 1); |
| 6512 | 6534 | |
| 6513 | 6535 | memcpy(copy, s, l + 1); |
| 6514 | - copy[l] = 0; | |
| 6536 | + copy[l] = 0; | |
| 6515 | 6537 | return copy; |
| 6516 | 6538 | } |
| 6517 | 6539 | |
| 6518 | 6540 | |
| 6519 | 6541 | |
| @@ -6598,52 +6620,52 @@ | ||
| 6598 | 6620 | } |
| 6599 | 6621 | |
| 6600 | 6622 | |
| 6601 | 6623 | void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) |
| 6602 | 6624 | { |
| 6603 | - Jim_HashTable n; | |
| 6625 | + Jim_HashTable n; | |
| 6604 | 6626 | unsigned int realsize = JimHashTableNextPower(size), i; |
| 6605 | 6627 | |
| 6606 | 6628 | if (size <= ht->used) |
| 6607 | 6629 | return; |
| 6608 | 6630 | |
| 6609 | 6631 | Jim_InitHashTable(&n, ht->type, ht->privdata); |
| 6610 | 6632 | n.size = realsize; |
| 6611 | 6633 | n.sizemask = realsize - 1; |
| 6612 | 6634 | n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); |
| 6613 | - | |
| 6635 | + | |
| 6614 | 6636 | n.uniq = ht->uniq; |
| 6615 | 6637 | |
| 6616 | - | |
| 6638 | + | |
| 6617 | 6639 | memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); |
| 6618 | 6640 | |
| 6619 | 6641 | n.used = ht->used; |
| 6620 | 6642 | for (i = 0; ht->used > 0; i++) { |
| 6621 | 6643 | Jim_HashEntry *he, *nextHe; |
| 6622 | 6644 | |
| 6623 | 6645 | if (ht->table[i] == NULL) |
| 6624 | 6646 | continue; |
| 6625 | 6647 | |
| 6626 | - | |
| 6648 | + | |
| 6627 | 6649 | he = ht->table[i]; |
| 6628 | 6650 | while (he) { |
| 6629 | 6651 | unsigned int h; |
| 6630 | 6652 | |
| 6631 | 6653 | nextHe = he->next; |
| 6632 | - | |
| 6654 | + | |
| 6633 | 6655 | h = Jim_HashKey(ht, he->key) & n.sizemask; |
| 6634 | 6656 | he->next = n.table[h]; |
| 6635 | 6657 | n.table[h] = he; |
| 6636 | 6658 | ht->used--; |
| 6637 | - | |
| 6659 | + | |
| 6638 | 6660 | he = nextHe; |
| 6639 | 6661 | } |
| 6640 | 6662 | } |
| 6641 | 6663 | assert(ht->used == 0); |
| 6642 | 6664 | Jim_Free(ht->table); |
| 6643 | 6665 | |
| 6644 | - | |
| 6666 | + | |
| 6645 | 6667 | *ht = n; |
| 6646 | 6668 | } |
| 6647 | 6669 | |
| 6648 | 6670 | |
| 6649 | 6671 | int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) |
| @@ -6652,11 +6674,11 @@ | ||
| 6652 | 6674 | |
| 6653 | 6675 | entry = JimInsertHashEntry(ht, key, 0); |
| 6654 | 6676 | if (entry == NULL) |
| 6655 | 6677 | return JIM_ERR; |
| 6656 | 6678 | |
| 6657 | - | |
| 6679 | + | |
| 6658 | 6680 | Jim_SetHashKey(ht, entry, key); |
| 6659 | 6681 | Jim_SetHashVal(ht, entry, val); |
| 6660 | 6682 | return JIM_OK; |
| 6661 | 6683 | } |
| 6662 | 6684 | |
| @@ -6678,11 +6700,11 @@ | ||
| 6678 | 6700 | Jim_SetHashVal(ht, entry, val); |
| 6679 | 6701 | } |
| 6680 | 6702 | existed = 1; |
| 6681 | 6703 | } |
| 6682 | 6704 | else { |
| 6683 | - | |
| 6705 | + | |
| 6684 | 6706 | Jim_SetHashKey(ht, entry, key); |
| 6685 | 6707 | Jim_SetHashVal(ht, entry, val); |
| 6686 | 6708 | existed = 0; |
| 6687 | 6709 | } |
| 6688 | 6710 | |
| @@ -6701,11 +6723,11 @@ | ||
| 6701 | 6723 | he = ht->table[h]; |
| 6702 | 6724 | |
| 6703 | 6725 | prevHe = NULL; |
| 6704 | 6726 | while (he) { |
| 6705 | 6727 | if (Jim_CompareHashKeys(ht, key, he->key)) { |
| 6706 | - | |
| 6728 | + | |
| 6707 | 6729 | if (prevHe) |
| 6708 | 6730 | prevHe->next = he->next; |
| 6709 | 6731 | else |
| 6710 | 6732 | ht->table[h] = he->next; |
| 6711 | 6733 | Jim_FreeEntryKey(ht, he); |
| @@ -6715,19 +6737,19 @@ | ||
| 6715 | 6737 | return JIM_OK; |
| 6716 | 6738 | } |
| 6717 | 6739 | prevHe = he; |
| 6718 | 6740 | he = he->next; |
| 6719 | 6741 | } |
| 6720 | - return JIM_ERR; | |
| 6742 | + return JIM_ERR; | |
| 6721 | 6743 | } |
| 6722 | 6744 | |
| 6723 | 6745 | |
| 6724 | 6746 | int Jim_FreeHashTable(Jim_HashTable *ht) |
| 6725 | 6747 | { |
| 6726 | 6748 | unsigned int i; |
| 6727 | 6749 | |
| 6728 | - | |
| 6750 | + | |
| 6729 | 6751 | for (i = 0; ht->used > 0; i++) { |
| 6730 | 6752 | Jim_HashEntry *he, *nextHe; |
| 6731 | 6753 | |
| 6732 | 6754 | if ((he = ht->table[i]) == NULL) |
| 6733 | 6755 | continue; |
| @@ -6738,15 +6760,15 @@ | ||
| 6738 | 6760 | Jim_Free(he); |
| 6739 | 6761 | ht->used--; |
| 6740 | 6762 | he = nextHe; |
| 6741 | 6763 | } |
| 6742 | 6764 | } |
| 6743 | - | |
| 6765 | + | |
| 6744 | 6766 | Jim_Free(ht->table); |
| 6745 | - | |
| 6767 | + | |
| 6746 | 6768 | JimResetHashTable(ht); |
| 6747 | - return JIM_OK; | |
| 6769 | + return JIM_OK; | |
| 6748 | 6770 | } |
| 6749 | 6771 | |
| 6750 | 6772 | Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key) |
| 6751 | 6773 | { |
| 6752 | 6774 | Jim_HashEntry *he; |
| @@ -6819,24 +6841,24 @@ | ||
| 6819 | 6841 | static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace) |
| 6820 | 6842 | { |
| 6821 | 6843 | unsigned int h; |
| 6822 | 6844 | Jim_HashEntry *he; |
| 6823 | 6845 | |
| 6824 | - | |
| 6846 | + | |
| 6825 | 6847 | JimExpandHashTableIfNeeded(ht); |
| 6826 | 6848 | |
| 6827 | - | |
| 6849 | + | |
| 6828 | 6850 | h = Jim_HashKey(ht, key) & ht->sizemask; |
| 6829 | - | |
| 6851 | + | |
| 6830 | 6852 | he = ht->table[h]; |
| 6831 | 6853 | while (he) { |
| 6832 | 6854 | if (Jim_CompareHashKeys(ht, key, he->key)) |
| 6833 | 6855 | return replace ? he : NULL; |
| 6834 | 6856 | he = he->next; |
| 6835 | 6857 | } |
| 6836 | 6858 | |
| 6837 | - | |
| 6859 | + | |
| 6838 | 6860 | he = Jim_Alloc(sizeof(*he)); |
| 6839 | 6861 | he->next = ht->table[h]; |
| 6840 | 6862 | ht->table[h] = he; |
| 6841 | 6863 | ht->used++; |
| 6842 | 6864 | he->key = NULL; |
| @@ -6865,16 +6887,16 @@ | ||
| 6865 | 6887 | { |
| 6866 | 6888 | Jim_Free(key); |
| 6867 | 6889 | } |
| 6868 | 6890 | |
| 6869 | 6891 | static const Jim_HashTableType JimPackageHashTableType = { |
| 6870 | - JimStringCopyHTHashFunction, | |
| 6871 | - JimStringCopyHTDup, | |
| 6872 | - NULL, | |
| 6873 | - JimStringCopyHTKeyCompare, | |
| 6874 | - JimStringCopyHTKeyDestructor, | |
| 6875 | - NULL | |
| 6892 | + JimStringCopyHTHashFunction, | |
| 6893 | + JimStringCopyHTDup, | |
| 6894 | + NULL, | |
| 6895 | + JimStringCopyHTKeyCompare, | |
| 6896 | + JimStringCopyHTKeyDestructor, | |
| 6897 | + NULL | |
| 6876 | 6898 | }; |
| 6877 | 6899 | |
| 6878 | 6900 | typedef struct AssocDataValue |
| 6879 | 6901 | { |
| 6880 | 6902 | Jim_InterpDeleteProc *delProc; |
| @@ -6889,16 +6911,16 @@ | ||
| 6889 | 6911 | assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data); |
| 6890 | 6912 | Jim_Free(data); |
| 6891 | 6913 | } |
| 6892 | 6914 | |
| 6893 | 6915 | static const Jim_HashTableType JimAssocDataHashTableType = { |
| 6894 | - JimStringCopyHTHashFunction, | |
| 6895 | - JimStringCopyHTDup, | |
| 6896 | - NULL, | |
| 6897 | - JimStringCopyHTKeyCompare, | |
| 6898 | - JimStringCopyHTKeyDestructor, | |
| 6899 | - JimAssocDataHashTableValueDestructor | |
| 6916 | + JimStringCopyHTHashFunction, | |
| 6917 | + JimStringCopyHTDup, | |
| 6918 | + NULL, | |
| 6919 | + JimStringCopyHTKeyCompare, | |
| 6920 | + JimStringCopyHTKeyDestructor, | |
| 6921 | + JimAssocDataHashTableValueDestructor | |
| 6900 | 6922 | }; |
| 6901 | 6923 | |
| 6902 | 6924 | void Jim_InitStack(Jim_Stack *stack) |
| 6903 | 6925 | { |
| 6904 | 6926 | stack->len = 0; |
| @@ -6951,56 +6973,61 @@ | ||
| 6951 | 6973 | freeFunc(stack->vector[i]); |
| 6952 | 6974 | } |
| 6953 | 6975 | |
| 6954 | 6976 | |
| 6955 | 6977 | |
| 6956 | -#define JIM_TT_NONE 0 | |
| 6957 | -#define JIM_TT_STR 1 | |
| 6958 | -#define JIM_TT_ESC 2 | |
| 6959 | -#define JIM_TT_VAR 3 | |
| 6960 | -#define JIM_TT_DICTSUGAR 4 | |
| 6961 | -#define JIM_TT_CMD 5 | |
| 6962 | - | |
| 6963 | -#define JIM_TT_SEP 6 | |
| 6964 | -#define JIM_TT_EOL 7 | |
| 6965 | -#define JIM_TT_EOF 8 | |
| 6966 | - | |
| 6967 | -#define JIM_TT_LINE 9 | |
| 6968 | -#define JIM_TT_WORD 10 | |
| 6978 | +#define JIM_TT_NONE 0 | |
| 6979 | +#define JIM_TT_STR 1 | |
| 6980 | +#define JIM_TT_ESC 2 | |
| 6981 | +#define JIM_TT_VAR 3 | |
| 6982 | +#define JIM_TT_DICTSUGAR 4 | |
| 6983 | +#define JIM_TT_CMD 5 | |
| 6984 | + | |
| 6985 | +#define JIM_TT_SEP 6 | |
| 6986 | +#define JIM_TT_EOL 7 | |
| 6987 | +#define JIM_TT_EOF 8 | |
| 6988 | + | |
| 6989 | +#define JIM_TT_LINE 9 | |
| 6990 | +#define JIM_TT_WORD 10 | |
| 6969 | 6991 | |
| 6970 | 6992 | |
| 6971 | 6993 | #define JIM_TT_SUBEXPR_START 11 |
| 6972 | 6994 | #define JIM_TT_SUBEXPR_END 12 |
| 6973 | 6995 | #define JIM_TT_SUBEXPR_COMMA 13 |
| 6974 | 6996 | #define JIM_TT_EXPR_INT 14 |
| 6975 | 6997 | #define JIM_TT_EXPR_DOUBLE 15 |
| 6998 | +#define JIM_TT_EXPR_BOOLEAN 16 | |
| 6976 | 6999 | |
| 6977 | -#define JIM_TT_EXPRSUGAR 16 | |
| 7000 | +#define JIM_TT_EXPRSUGAR 17 | |
| 6978 | 7001 | |
| 6979 | 7002 | |
| 6980 | 7003 | #define JIM_TT_EXPR_OP 20 |
| 6981 | 7004 | |
| 6982 | 7005 | #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF) |
| 6983 | 7006 | |
| 7007 | +#define TOKEN_IS_EXPR_START(type) (type == JIM_TT_NONE || type == JIM_TT_SUBEXPR_START || type == JIM_TT_SUBEXPR_COMMA) | |
| 7008 | + | |
| 7009 | +#define TOKEN_IS_EXPR_OP(type) (type >= JIM_TT_EXPR_OP) | |
| 7010 | + | |
| 6984 | 7011 | struct JimParseMissing { |
| 6985 | - int ch; | |
| 6986 | - int line; | |
| 7012 | + int ch; | |
| 7013 | + int line; | |
| 6987 | 7014 | }; |
| 6988 | 7015 | |
| 6989 | 7016 | struct JimParserCtx |
| 6990 | 7017 | { |
| 6991 | - const char *p; | |
| 6992 | - int len; | |
| 6993 | - int linenr; | |
| 7018 | + const char *p; | |
| 7019 | + int len; | |
| 7020 | + int linenr; | |
| 6994 | 7021 | const char *tstart; |
| 6995 | - const char *tend; | |
| 6996 | - int tline; | |
| 6997 | - int tt; | |
| 6998 | - int eof; | |
| 6999 | - int inquote; | |
| 7000 | - int comment; | |
| 7001 | - struct JimParseMissing missing; | |
| 7022 | + const char *tend; | |
| 7023 | + int tline; | |
| 7024 | + int tt; | |
| 7025 | + int eof; | |
| 7026 | + int inquote; | |
| 7027 | + int comment; | |
| 7028 | + struct JimParseMissing missing; | |
| 7002 | 7029 | }; |
| 7003 | 7030 | |
| 7004 | 7031 | static int JimParseScript(struct JimParserCtx *pc); |
| 7005 | 7032 | static int JimParseSep(struct JimParserCtx *pc); |
| 7006 | 7033 | static int JimParseEol(struct JimParserCtx *pc); |
| @@ -7030,11 +7057,11 @@ | ||
| 7030 | 7057 | pc->missing.line = linenr; |
| 7031 | 7058 | } |
| 7032 | 7059 | |
| 7033 | 7060 | static int JimParseScript(struct JimParserCtx *pc) |
| 7034 | 7061 | { |
| 7035 | - while (1) { | |
| 7062 | + while (1) { | |
| 7036 | 7063 | if (!pc->len) { |
| 7037 | 7064 | pc->tstart = pc->p; |
| 7038 | 7065 | pc->tend = pc->p - 1; |
| 7039 | 7066 | pc->tline = pc->linenr; |
| 7040 | 7067 | pc->tt = JIM_TT_EOL; |
| @@ -7066,11 +7093,11 @@ | ||
| 7066 | 7093 | pc->comment = 0; |
| 7067 | 7094 | return JimParseCmd(pc); |
| 7068 | 7095 | case '$': |
| 7069 | 7096 | pc->comment = 0; |
| 7070 | 7097 | if (JimParseVar(pc) == JIM_ERR) { |
| 7071 | - | |
| 7098 | + | |
| 7072 | 7099 | pc->tstart = pc->tend = pc->p++; |
| 7073 | 7100 | pc->len--; |
| 7074 | 7101 | pc->tt = JIM_TT_ESC; |
| 7075 | 7102 | } |
| 7076 | 7103 | return JIM_OK; |
| @@ -7127,11 +7154,11 @@ | ||
| 7127 | 7154 | |
| 7128 | 7155 | static void JimParseSubBrace(struct JimParserCtx *pc) |
| 7129 | 7156 | { |
| 7130 | 7157 | int level = 1; |
| 7131 | 7158 | |
| 7132 | - | |
| 7159 | + | |
| 7133 | 7160 | pc->p++; |
| 7134 | 7161 | pc->len--; |
| 7135 | 7162 | while (pc->len) { |
| 7136 | 7163 | switch (*pc->p) { |
| 7137 | 7164 | case '\\': |
| @@ -7171,11 +7198,11 @@ | ||
| 7171 | 7198 | static int JimParseSubQuote(struct JimParserCtx *pc) |
| 7172 | 7199 | { |
| 7173 | 7200 | int tt = JIM_TT_STR; |
| 7174 | 7201 | int line = pc->tline; |
| 7175 | 7202 | |
| 7176 | - | |
| 7203 | + | |
| 7177 | 7204 | pc->p++; |
| 7178 | 7205 | pc->len--; |
| 7179 | 7206 | while (pc->len) { |
| 7180 | 7207 | switch (*pc->p) { |
| 7181 | 7208 | case '\\': |
| @@ -7220,11 +7247,11 @@ | ||
| 7220 | 7247 | { |
| 7221 | 7248 | int level = 1; |
| 7222 | 7249 | int startofword = 1; |
| 7223 | 7250 | int line = pc->tline; |
| 7224 | 7251 | |
| 7225 | - | |
| 7252 | + | |
| 7226 | 7253 | pc->p++; |
| 7227 | 7254 | pc->len--; |
| 7228 | 7255 | while (pc->len) { |
| 7229 | 7256 | switch (*pc->p) { |
| 7230 | 7257 | case '\\': |
| @@ -7300,17 +7327,17 @@ | ||
| 7300 | 7327 | return JIM_OK; |
| 7301 | 7328 | } |
| 7302 | 7329 | |
| 7303 | 7330 | static int JimParseVar(struct JimParserCtx *pc) |
| 7304 | 7331 | { |
| 7305 | - | |
| 7332 | + | |
| 7306 | 7333 | pc->p++; |
| 7307 | 7334 | pc->len--; |
| 7308 | 7335 | |
| 7309 | 7336 | #ifdef EXPRSUGAR_BRACKET |
| 7310 | 7337 | if (*pc->p == '[') { |
| 7311 | - | |
| 7338 | + | |
| 7312 | 7339 | JimParseCmd(pc); |
| 7313 | 7340 | pc->tt = JIM_TT_EXPRSUGAR; |
| 7314 | 7341 | return JIM_OK; |
| 7315 | 7342 | } |
| 7316 | 7343 | #endif |
| @@ -7336,11 +7363,11 @@ | ||
| 7336 | 7363 | pc->len--; |
| 7337 | 7364 | } |
| 7338 | 7365 | } |
| 7339 | 7366 | else { |
| 7340 | 7367 | while (1) { |
| 7341 | - | |
| 7368 | + | |
| 7342 | 7369 | if (pc->p[0] == ':' && pc->p[1] == ':') { |
| 7343 | 7370 | while (*pc->p == ':') { |
| 7344 | 7371 | pc->p++; |
| 7345 | 7372 | pc->len--; |
| 7346 | 7373 | } |
| @@ -7351,11 +7378,11 @@ | ||
| 7351 | 7378 | pc->len--; |
| 7352 | 7379 | continue; |
| 7353 | 7380 | } |
| 7354 | 7381 | break; |
| 7355 | 7382 | } |
| 7356 | - | |
| 7383 | + | |
| 7357 | 7384 | if (*pc->p == '(') { |
| 7358 | 7385 | int count = 1; |
| 7359 | 7386 | const char *paren = NULL; |
| 7360 | 7387 | |
| 7361 | 7388 | pc->tt = JIM_TT_DICTSUGAR; |
| @@ -7378,11 +7405,11 @@ | ||
| 7378 | 7405 | if (count == 0) { |
| 7379 | 7406 | pc->p++; |
| 7380 | 7407 | pc->len--; |
| 7381 | 7408 | } |
| 7382 | 7409 | else if (paren) { |
| 7383 | - | |
| 7410 | + | |
| 7384 | 7411 | paren++; |
| 7385 | 7412 | pc->len += (pc->p - paren); |
| 7386 | 7413 | pc->p = paren; |
| 7387 | 7414 | } |
| 7388 | 7415 | #ifndef EXPRSUGAR_BRACKET |
| @@ -7403,19 +7430,19 @@ | ||
| 7403 | 7430 | |
| 7404 | 7431 | static int JimParseStr(struct JimParserCtx *pc) |
| 7405 | 7432 | { |
| 7406 | 7433 | if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL || |
| 7407 | 7434 | pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) { |
| 7408 | - | |
| 7435 | + | |
| 7409 | 7436 | if (*pc->p == '{') { |
| 7410 | 7437 | return JimParseBrace(pc); |
| 7411 | 7438 | } |
| 7412 | 7439 | if (*pc->p == '"') { |
| 7413 | 7440 | pc->inquote = 1; |
| 7414 | 7441 | pc->p++; |
| 7415 | 7442 | pc->len--; |
| 7416 | - | |
| 7443 | + | |
| 7417 | 7444 | pc->missing.line = pc->tline; |
| 7418 | 7445 | } |
| 7419 | 7446 | } |
| 7420 | 7447 | pc->tstart = pc->p; |
| 7421 | 7448 | pc->tline = pc->linenr; |
| @@ -7441,25 +7468,25 @@ | ||
| 7441 | 7468 | } |
| 7442 | 7469 | pc->p++; |
| 7443 | 7470 | pc->len--; |
| 7444 | 7471 | } |
| 7445 | 7472 | else if (pc->len == 1) { |
| 7446 | - | |
| 7473 | + | |
| 7447 | 7474 | pc->missing.ch = '\\'; |
| 7448 | 7475 | } |
| 7449 | 7476 | break; |
| 7450 | 7477 | case '(': |
| 7451 | - | |
| 7478 | + | |
| 7452 | 7479 | if (pc->len > 1 && pc->p[1] != '$') { |
| 7453 | 7480 | break; |
| 7454 | 7481 | } |
| 7455 | - | |
| 7482 | + | |
| 7456 | 7483 | case ')': |
| 7457 | - | |
| 7484 | + | |
| 7458 | 7485 | if (*pc->p == '(' || pc->tt == JIM_TT_VAR) { |
| 7459 | 7486 | if (pc->p == pc->tstart) { |
| 7460 | - | |
| 7487 | + | |
| 7461 | 7488 | pc->p++; |
| 7462 | 7489 | pc->len--; |
| 7463 | 7490 | } |
| 7464 | 7491 | pc->tend = pc->p - 1; |
| 7465 | 7492 | pc->tt = JIM_TT_ESC; |
| @@ -7499,11 +7526,11 @@ | ||
| 7499 | 7526 | break; |
| 7500 | 7527 | } |
| 7501 | 7528 | pc->p++; |
| 7502 | 7529 | pc->len--; |
| 7503 | 7530 | } |
| 7504 | - return JIM_OK; | |
| 7531 | + return JIM_OK; | |
| 7505 | 7532 | } |
| 7506 | 7533 | |
| 7507 | 7534 | static int JimParseComment(struct JimParserCtx *pc) |
| 7508 | 7535 | { |
| 7509 | 7536 | while (*pc->p) { |
| @@ -7610,34 +7637,34 @@ | ||
| 7610 | 7637 | if (c == -1) { |
| 7611 | 7638 | break; |
| 7612 | 7639 | } |
| 7613 | 7640 | val = (val << 4) | c; |
| 7614 | 7641 | } |
| 7615 | - | |
| 7642 | + | |
| 7616 | 7643 | if (s[i] == '{') { |
| 7617 | 7644 | if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') { |
| 7618 | - | |
| 7645 | + | |
| 7619 | 7646 | i--; |
| 7620 | 7647 | k = 0; |
| 7621 | 7648 | } |
| 7622 | 7649 | else { |
| 7623 | - | |
| 7650 | + | |
| 7624 | 7651 | k++; |
| 7625 | 7652 | } |
| 7626 | 7653 | } |
| 7627 | 7654 | if (k) { |
| 7628 | - | |
| 7655 | + | |
| 7629 | 7656 | if (s[i] == 'x') { |
| 7630 | 7657 | *p++ = val; |
| 7631 | 7658 | } |
| 7632 | 7659 | else { |
| 7633 | 7660 | p += utf8_fromunicode(p, val); |
| 7634 | 7661 | } |
| 7635 | 7662 | i += k; |
| 7636 | 7663 | break; |
| 7637 | 7664 | } |
| 7638 | - | |
| 7665 | + | |
| 7639 | 7666 | *p++ = s[i]; |
| 7640 | 7667 | } |
| 7641 | 7668 | break; |
| 7642 | 7669 | case 'v': |
| 7643 | 7670 | *p++ = 0xb; |
| @@ -7646,11 +7673,11 @@ | ||
| 7646 | 7673 | case '\0': |
| 7647 | 7674 | *p++ = '\\'; |
| 7648 | 7675 | i++; |
| 7649 | 7676 | break; |
| 7650 | 7677 | case '\n': |
| 7651 | - | |
| 7678 | + | |
| 7652 | 7679 | *p++ = ' '; |
| 7653 | 7680 | do { |
| 7654 | 7681 | i++; |
| 7655 | 7682 | } while (s[i + 1] == ' ' || s[i + 1] == '\t'); |
| 7656 | 7683 | break; |
| @@ -7660,11 +7687,11 @@ | ||
| 7660 | 7687 | case '3': |
| 7661 | 7688 | case '4': |
| 7662 | 7689 | case '5': |
| 7663 | 7690 | case '6': |
| 7664 | 7691 | case '7': |
| 7665 | - | |
| 7692 | + | |
| 7666 | 7693 | { |
| 7667 | 7694 | int val = 0; |
| 7668 | 7695 | int c = odigitval(s[i + 1]); |
| 7669 | 7696 | |
| 7670 | 7697 | val = c; |
| @@ -7708,27 +7735,23 @@ | ||
| 7708 | 7735 | char *token; |
| 7709 | 7736 | int len; |
| 7710 | 7737 | |
| 7711 | 7738 | start = pc->tstart; |
| 7712 | 7739 | end = pc->tend; |
| 7713 | - if (start > end) { | |
| 7740 | + len = (end - start) + 1; | |
| 7741 | + if (len < 0) { | |
| 7714 | 7742 | len = 0; |
| 7715 | - token = Jim_Alloc(1); | |
| 7716 | - token[0] = '\0'; | |
| 7717 | - } | |
| 7718 | - else { | |
| 7719 | - len = (end - start) + 1; | |
| 7720 | - token = Jim_Alloc(len + 1); | |
| 7721 | - if (pc->tt != JIM_TT_ESC) { | |
| 7722 | - | |
| 7723 | - memcpy(token, start, len); | |
| 7724 | - token[len] = '\0'; | |
| 7725 | - } | |
| 7726 | - else { | |
| 7727 | - | |
| 7728 | - len = JimEscape(token, start, len); | |
| 7729 | - } | |
| 7743 | + } | |
| 7744 | + token = Jim_Alloc(len + 1); | |
| 7745 | + if (pc->tt != JIM_TT_ESC) { | |
| 7746 | + | |
| 7747 | + memcpy(token, start, len); | |
| 7748 | + token[len] = '\0'; | |
| 7749 | + } | |
| 7750 | + else { | |
| 7751 | + | |
| 7752 | + len = JimEscape(token, start, len); | |
| 7730 | 7753 | } |
| 7731 | 7754 | |
| 7732 | 7755 | return Jim_NewStringObjNoAlloc(interp, token, len); |
| 7733 | 7756 | } |
| 7734 | 7757 | |
| @@ -7790,11 +7813,11 @@ | ||
| 7790 | 7813 | while (pc->len) { |
| 7791 | 7814 | switch (*pc->p) { |
| 7792 | 7815 | case '\\': |
| 7793 | 7816 | pc->tt = JIM_TT_ESC; |
| 7794 | 7817 | if (--pc->len == 0) { |
| 7795 | - | |
| 7818 | + | |
| 7796 | 7819 | pc->tend = pc->p; |
| 7797 | 7820 | return JIM_OK; |
| 7798 | 7821 | } |
| 7799 | 7822 | pc->p++; |
| 7800 | 7823 | break; |
| @@ -7826,11 +7849,11 @@ | ||
| 7826 | 7849 | pc->tend = pc->p - 1; |
| 7827 | 7850 | return JIM_OK; |
| 7828 | 7851 | } |
| 7829 | 7852 | if (*pc->p == '\\') { |
| 7830 | 7853 | if (--pc->len == 0) { |
| 7831 | - | |
| 7854 | + | |
| 7832 | 7855 | pc->tend = pc->p; |
| 7833 | 7856 | return JIM_OK; |
| 7834 | 7857 | } |
| 7835 | 7858 | pc->tt = JIM_TT_ESC; |
| 7836 | 7859 | pc->p++; |
| @@ -7846,24 +7869,24 @@ | ||
| 7846 | 7869 | |
| 7847 | 7870 | Jim_Obj *Jim_NewObj(Jim_Interp *interp) |
| 7848 | 7871 | { |
| 7849 | 7872 | Jim_Obj *objPtr; |
| 7850 | 7873 | |
| 7851 | - | |
| 7874 | + | |
| 7852 | 7875 | if (interp->freeList != NULL) { |
| 7853 | - | |
| 7876 | + | |
| 7854 | 7877 | objPtr = interp->freeList; |
| 7855 | 7878 | interp->freeList = objPtr->nextObjPtr; |
| 7856 | 7879 | } |
| 7857 | 7880 | else { |
| 7858 | - | |
| 7881 | + | |
| 7859 | 7882 | objPtr = Jim_Alloc(sizeof(*objPtr)); |
| 7860 | 7883 | } |
| 7861 | 7884 | |
| 7862 | 7885 | objPtr->refCount = 0; |
| 7863 | 7886 | |
| 7864 | - | |
| 7887 | + | |
| 7865 | 7888 | objPtr->prevObjPtr = NULL; |
| 7866 | 7889 | objPtr->nextObjPtr = interp->liveList; |
| 7867 | 7890 | if (interp->liveList) |
| 7868 | 7891 | interp->liveList->prevObjPtr = objPtr; |
| 7869 | 7892 | interp->liveList = objPtr; |
| @@ -7871,32 +7894,32 @@ | ||
| 7871 | 7894 | return objPtr; |
| 7872 | 7895 | } |
| 7873 | 7896 | |
| 7874 | 7897 | void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr) |
| 7875 | 7898 | { |
| 7876 | - | |
| 7899 | + | |
| 7877 | 7900 | JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr, |
| 7878 | 7901 | objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>")); |
| 7879 | 7902 | |
| 7880 | - | |
| 7903 | + | |
| 7881 | 7904 | Jim_FreeIntRep(interp, objPtr); |
| 7882 | - | |
| 7905 | + | |
| 7883 | 7906 | if (objPtr->bytes != NULL) { |
| 7884 | 7907 | if (objPtr->bytes != JimEmptyStringRep) |
| 7885 | 7908 | Jim_Free(objPtr->bytes); |
| 7886 | 7909 | } |
| 7887 | - | |
| 7910 | + | |
| 7888 | 7911 | if (objPtr->prevObjPtr) |
| 7889 | 7912 | objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; |
| 7890 | 7913 | if (objPtr->nextObjPtr) |
| 7891 | 7914 | objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; |
| 7892 | 7915 | if (interp->liveList == objPtr) |
| 7893 | 7916 | interp->liveList = objPtr->nextObjPtr; |
| 7894 | 7917 | #ifdef JIM_DISABLE_OBJECT_POOL |
| 7895 | 7918 | Jim_Free(objPtr); |
| 7896 | 7919 | #else |
| 7897 | - | |
| 7920 | + | |
| 7898 | 7921 | objPtr->prevObjPtr = NULL; |
| 7899 | 7922 | objPtr->nextObjPtr = interp->freeList; |
| 7900 | 7923 | if (interp->freeList) |
| 7901 | 7924 | interp->freeList->prevObjPtr = objPtr; |
| 7902 | 7925 | interp->freeList = objPtr; |
| @@ -7919,45 +7942,44 @@ | ||
| 7919 | 7942 | { |
| 7920 | 7943 | Jim_Obj *dupPtr; |
| 7921 | 7944 | |
| 7922 | 7945 | dupPtr = Jim_NewObj(interp); |
| 7923 | 7946 | if (objPtr->bytes == NULL) { |
| 7924 | - | |
| 7947 | + | |
| 7925 | 7948 | dupPtr->bytes = NULL; |
| 7926 | 7949 | } |
| 7927 | 7950 | else if (objPtr->length == 0) { |
| 7928 | - | |
| 7929 | 7951 | dupPtr->bytes = JimEmptyStringRep; |
| 7930 | 7952 | dupPtr->length = 0; |
| 7931 | 7953 | dupPtr->typePtr = NULL; |
| 7932 | 7954 | return dupPtr; |
| 7933 | 7955 | } |
| 7934 | 7956 | else { |
| 7935 | 7957 | dupPtr->bytes = Jim_Alloc(objPtr->length + 1); |
| 7936 | 7958 | dupPtr->length = objPtr->length; |
| 7937 | - | |
| 7959 | + | |
| 7938 | 7960 | memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1); |
| 7939 | 7961 | } |
| 7940 | 7962 | |
| 7941 | - | |
| 7963 | + | |
| 7942 | 7964 | dupPtr->typePtr = objPtr->typePtr; |
| 7943 | 7965 | if (objPtr->typePtr != NULL) { |
| 7944 | 7966 | if (objPtr->typePtr->dupIntRepProc == NULL) { |
| 7945 | 7967 | dupPtr->internalRep = objPtr->internalRep; |
| 7946 | 7968 | } |
| 7947 | 7969 | else { |
| 7948 | - | |
| 7970 | + | |
| 7949 | 7971 | objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr); |
| 7950 | 7972 | } |
| 7951 | 7973 | } |
| 7952 | 7974 | return dupPtr; |
| 7953 | 7975 | } |
| 7954 | 7976 | |
| 7955 | 7977 | const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr) |
| 7956 | 7978 | { |
| 7957 | 7979 | if (objPtr->bytes == NULL) { |
| 7958 | - | |
| 7980 | + | |
| 7959 | 7981 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7960 | 7982 | objPtr->typePtr->updateStringProc(objPtr); |
| 7961 | 7983 | } |
| 7962 | 7984 | if (lenPtr) |
| 7963 | 7985 | *lenPtr = objPtr->length; |
| @@ -7966,25 +7988,22 @@ | ||
| 7966 | 7988 | |
| 7967 | 7989 | |
| 7968 | 7990 | int Jim_Length(Jim_Obj *objPtr) |
| 7969 | 7991 | { |
| 7970 | 7992 | if (objPtr->bytes == NULL) { |
| 7971 | - | |
| 7972 | - JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); | |
| 7973 | - objPtr->typePtr->updateStringProc(objPtr); | |
| 7993 | + | |
| 7994 | + Jim_GetString(objPtr, NULL); | |
| 7974 | 7995 | } |
| 7975 | 7996 | return objPtr->length; |
| 7976 | 7997 | } |
| 7977 | 7998 | |
| 7978 | 7999 | |
| 7979 | 8000 | const char *Jim_String(Jim_Obj *objPtr) |
| 7980 | 8001 | { |
| 7981 | 8002 | if (objPtr->bytes == NULL) { |
| 7982 | - | |
| 7983 | - JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value.")); | |
| 7984 | - JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); | |
| 7985 | - objPtr->typePtr->updateStringProc(objPtr); | |
| 8003 | + | |
| 8004 | + Jim_GetString(objPtr, NULL); | |
| 7986 | 8005 | } |
| 7987 | 8006 | return objPtr->bytes; |
| 7988 | 8007 | } |
| 7989 | 8008 | |
| 7990 | 8009 | static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) |
| @@ -8001,23 +8020,34 @@ | ||
| 8001 | 8020 | FreeDictSubstInternalRep, |
| 8002 | 8021 | DupDictSubstInternalRep, |
| 8003 | 8022 | NULL, |
| 8004 | 8023 | JIM_TYPE_NONE, |
| 8005 | 8024 | }; |
| 8025 | + | |
| 8026 | +static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); | |
| 8027 | +static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); | |
| 8028 | + | |
| 8029 | +static const Jim_ObjType interpolatedObjType = { | |
| 8030 | + "interpolated", | |
| 8031 | + FreeInterpolatedInternalRep, | |
| 8032 | + DupInterpolatedInternalRep, | |
| 8033 | + NULL, | |
| 8034 | + JIM_TYPE_NONE, | |
| 8035 | +}; | |
| 8006 | 8036 | |
| 8007 | 8037 | static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8008 | 8038 | { |
| 8009 | 8039 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); |
| 8010 | 8040 | } |
| 8011 | 8041 | |
| 8012 | -static const Jim_ObjType interpolatedObjType = { | |
| 8013 | - "interpolated", | |
| 8014 | - FreeInterpolatedInternalRep, | |
| 8015 | - NULL, | |
| 8016 | - NULL, | |
| 8017 | - JIM_TYPE_NONE, | |
| 8018 | -}; | |
| 8042 | +static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) | |
| 8043 | +{ | |
| 8044 | + | |
| 8045 | + dupPtr->internalRep = srcPtr->internalRep; | |
| 8046 | + | |
| 8047 | + Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr); | |
| 8048 | +} | |
| 8019 | 8049 | |
| 8020 | 8050 | static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8021 | 8051 | static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8022 | 8052 | |
| 8023 | 8053 | static const Jim_ObjType stringObjType = { |
| @@ -8037,22 +8067,22 @@ | ||
| 8037 | 8067 | } |
| 8038 | 8068 | |
| 8039 | 8069 | static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8040 | 8070 | { |
| 8041 | 8071 | if (objPtr->typePtr != &stringObjType) { |
| 8042 | - | |
| 8072 | + | |
| 8043 | 8073 | if (objPtr->bytes == NULL) { |
| 8044 | - | |
| 8074 | + | |
| 8045 | 8075 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 8046 | 8076 | objPtr->typePtr->updateStringProc(objPtr); |
| 8047 | 8077 | } |
| 8048 | - | |
| 8078 | + | |
| 8049 | 8079 | Jim_FreeIntRep(interp, objPtr); |
| 8050 | - | |
| 8080 | + | |
| 8051 | 8081 | objPtr->typePtr = &stringObjType; |
| 8052 | 8082 | objPtr->internalRep.strValue.maxLength = objPtr->length; |
| 8053 | - | |
| 8083 | + | |
| 8054 | 8084 | objPtr->internalRep.strValue.charLength = -1; |
| 8055 | 8085 | } |
| 8056 | 8086 | return JIM_OK; |
| 8057 | 8087 | } |
| 8058 | 8088 | |
| @@ -8073,39 +8103,37 @@ | ||
| 8073 | 8103 | |
| 8074 | 8104 | Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len) |
| 8075 | 8105 | { |
| 8076 | 8106 | Jim_Obj *objPtr = Jim_NewObj(interp); |
| 8077 | 8107 | |
| 8078 | - | |
| 8108 | + | |
| 8079 | 8109 | if (len == -1) |
| 8080 | 8110 | len = strlen(s); |
| 8081 | - | |
| 8111 | + | |
| 8082 | 8112 | if (len == 0) { |
| 8083 | 8113 | objPtr->bytes = JimEmptyStringRep; |
| 8084 | 8114 | } |
| 8085 | 8115 | else { |
| 8086 | - objPtr->bytes = Jim_Alloc(len + 1); | |
| 8087 | - memcpy(objPtr->bytes, s, len); | |
| 8088 | - objPtr->bytes[len] = '\0'; | |
| 8116 | + objPtr->bytes = Jim_StrDupLen(s, len); | |
| 8089 | 8117 | } |
| 8090 | 8118 | objPtr->length = len; |
| 8091 | 8119 | |
| 8092 | - | |
| 8120 | + | |
| 8093 | 8121 | objPtr->typePtr = NULL; |
| 8094 | 8122 | return objPtr; |
| 8095 | 8123 | } |
| 8096 | 8124 | |
| 8097 | 8125 | |
| 8098 | 8126 | Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen) |
| 8099 | 8127 | { |
| 8100 | 8128 | #ifdef JIM_UTF8 |
| 8101 | - | |
| 8129 | + | |
| 8102 | 8130 | int bytelen = utf8_index(s, charlen); |
| 8103 | 8131 | |
| 8104 | 8132 | Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen); |
| 8105 | 8133 | |
| 8106 | - | |
| 8134 | + | |
| 8107 | 8135 | objPtr->typePtr = &stringObjType; |
| 8108 | 8136 | objPtr->internalRep.strValue.maxLength = bytelen; |
| 8109 | 8137 | objPtr->internalRep.strValue.charLength = charlen; |
| 8110 | 8138 | |
| 8111 | 8139 | return objPtr; |
| @@ -8132,11 +8160,11 @@ | ||
| 8132 | 8160 | len = strlen(str); |
| 8133 | 8161 | needlen = objPtr->length + len; |
| 8134 | 8162 | if (objPtr->internalRep.strValue.maxLength < needlen || |
| 8135 | 8163 | objPtr->internalRep.strValue.maxLength == 0) { |
| 8136 | 8164 | needlen *= 2; |
| 8137 | - | |
| 8165 | + | |
| 8138 | 8166 | if (needlen < 7) { |
| 8139 | 8167 | needlen = 7; |
| 8140 | 8168 | } |
| 8141 | 8169 | if (objPtr->bytes == JimEmptyStringRep) { |
| 8142 | 8170 | objPtr->bytes = Jim_Alloc(needlen + 1); |
| @@ -8148,11 +8176,11 @@ | ||
| 8148 | 8176 | } |
| 8149 | 8177 | memcpy(objPtr->bytes + objPtr->length, str, len); |
| 8150 | 8178 | objPtr->bytes[objPtr->length + len] = '\0'; |
| 8151 | 8179 | |
| 8152 | 8180 | if (objPtr->internalRep.strValue.charLength >= 0) { |
| 8153 | - | |
| 8181 | + | |
| 8154 | 8182 | objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); |
| 8155 | 8183 | } |
| 8156 | 8184 | objPtr->length += len; |
| 8157 | 8185 | } |
| 8158 | 8186 | |
| @@ -8210,11 +8238,11 @@ | ||
| 8210 | 8238 | int l1, l2; |
| 8211 | 8239 | const char *s1 = Jim_GetString(firstObjPtr, &l1); |
| 8212 | 8240 | const char *s2 = Jim_GetString(secondObjPtr, &l2); |
| 8213 | 8241 | |
| 8214 | 8242 | if (nocase) { |
| 8215 | - | |
| 8243 | + | |
| 8216 | 8244 | return JimStringCompareLen(s1, s2, -1, nocase); |
| 8217 | 8245 | } |
| 8218 | 8246 | return JimStringCompare(s1, l1, s2, l2); |
| 8219 | 8247 | } |
| 8220 | 8248 | |
| @@ -8312,11 +8340,11 @@ | ||
| 8312 | 8340 | |
| 8313 | 8341 | if (first == 0 && rangeLen == len) { |
| 8314 | 8342 | return strObjPtr; |
| 8315 | 8343 | } |
| 8316 | 8344 | if (len == bytelen) { |
| 8317 | - | |
| 8345 | + | |
| 8318 | 8346 | return Jim_NewStringObj(interp, str + first, rangeLen); |
| 8319 | 8347 | } |
| 8320 | 8348 | return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen); |
| 8321 | 8349 | #else |
| 8322 | 8350 | return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr); |
| @@ -8341,19 +8369,19 @@ | ||
| 8341 | 8369 | return strObjPtr; |
| 8342 | 8370 | } |
| 8343 | 8371 | |
| 8344 | 8372 | str = Jim_String(strObjPtr); |
| 8345 | 8373 | |
| 8346 | - | |
| 8374 | + | |
| 8347 | 8375 | objPtr = Jim_NewStringObjUtf8(interp, str, first); |
| 8348 | 8376 | |
| 8349 | - | |
| 8377 | + | |
| 8350 | 8378 | if (newStrObj) { |
| 8351 | 8379 | Jim_AppendObj(interp, objPtr, newStrObj); |
| 8352 | 8380 | } |
| 8353 | 8381 | |
| 8354 | - | |
| 8382 | + | |
| 8355 | 8383 | Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1); |
| 8356 | 8384 | |
| 8357 | 8385 | return objPtr; |
| 8358 | 8386 | } |
| 8359 | 8387 | |
| @@ -8371,12 +8399,10 @@ | ||
| 8371 | 8399 | { |
| 8372 | 8400 | char *buf; |
| 8373 | 8401 | int len; |
| 8374 | 8402 | const char *str; |
| 8375 | 8403 | |
| 8376 | - SetStringFromAny(interp, strObjPtr); | |
| 8377 | - | |
| 8378 | 8404 | str = Jim_GetString(strObjPtr, &len); |
| 8379 | 8405 | |
| 8380 | 8406 | #ifdef JIM_UTF8 |
| 8381 | 8407 | len *= 2; |
| 8382 | 8408 | #endif |
| @@ -8389,14 +8415,10 @@ | ||
| 8389 | 8415 | { |
| 8390 | 8416 | char *buf; |
| 8391 | 8417 | const char *str; |
| 8392 | 8418 | int len; |
| 8393 | 8419 | |
| 8394 | - if (strObjPtr->typePtr != &stringObjType) { | |
| 8395 | - SetStringFromAny(interp, strObjPtr); | |
| 8396 | - } | |
| 8397 | - | |
| 8398 | 8420 | str = Jim_GetString(strObjPtr, &len); |
| 8399 | 8421 | |
| 8400 | 8422 | #ifdef JIM_UTF8 |
| 8401 | 8423 | len *= 2; |
| 8402 | 8424 | #endif |
| @@ -8411,13 +8433,11 @@ | ||
| 8411 | 8433 | int len; |
| 8412 | 8434 | int c; |
| 8413 | 8435 | const char *str; |
| 8414 | 8436 | |
| 8415 | 8437 | str = Jim_GetString(strObjPtr, &len); |
| 8416 | - if (len == 0) { | |
| 8417 | - return strObjPtr; | |
| 8418 | - } | |
| 8438 | + | |
| 8419 | 8439 | #ifdef JIM_UTF8 |
| 8420 | 8440 | len *= 2; |
| 8421 | 8441 | #endif |
| 8422 | 8442 | buf = p = Jim_Alloc(len + 1); |
| 8423 | 8443 | |
| @@ -8452,11 +8472,11 @@ | ||
| 8452 | 8472 | while (len) { |
| 8453 | 8473 | int c; |
| 8454 | 8474 | int n = utf8_tounicode(str, &c); |
| 8455 | 8475 | |
| 8456 | 8476 | if (utf8_memchr(trimchars, trimlen, c) == NULL) { |
| 8457 | - | |
| 8477 | + | |
| 8458 | 8478 | break; |
| 8459 | 8479 | } |
| 8460 | 8480 | str += n; |
| 8461 | 8481 | len -= n; |
| 8462 | 8482 | } |
| @@ -8523,41 +8543,41 @@ | ||
| 8523 | 8543 | |
| 8524 | 8544 | len = Jim_Length(strObjPtr); |
| 8525 | 8545 | nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen); |
| 8526 | 8546 | |
| 8527 | 8547 | if (nontrim == NULL) { |
| 8528 | - | |
| 8548 | + | |
| 8529 | 8549 | return Jim_NewEmptyStringObj(interp); |
| 8530 | 8550 | } |
| 8531 | 8551 | if (nontrim == strObjPtr->bytes + len) { |
| 8532 | - | |
| 8552 | + | |
| 8533 | 8553 | return strObjPtr; |
| 8534 | 8554 | } |
| 8535 | 8555 | |
| 8536 | 8556 | if (Jim_IsShared(strObjPtr)) { |
| 8537 | 8557 | strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); |
| 8538 | 8558 | } |
| 8539 | 8559 | else { |
| 8540 | - | |
| 8560 | + | |
| 8541 | 8561 | strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0; |
| 8542 | 8562 | strObjPtr->length = (nontrim - strObjPtr->bytes); |
| 8543 | 8563 | } |
| 8544 | 8564 | |
| 8545 | 8565 | return strObjPtr; |
| 8546 | 8566 | } |
| 8547 | 8567 | |
| 8548 | 8568 | static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) |
| 8549 | 8569 | { |
| 8550 | - | |
| 8570 | + | |
| 8551 | 8571 | Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); |
| 8552 | 8572 | |
| 8553 | - | |
| 8573 | + | |
| 8554 | 8574 | strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); |
| 8555 | 8575 | |
| 8556 | - | |
| 8576 | + | |
| 8557 | 8577 | if (objPtr != strObjPtr && objPtr->refCount == 0) { |
| 8558 | - | |
| 8578 | + | |
| 8559 | 8579 | Jim_FreeNewObj(interp, objPtr); |
| 8560 | 8580 | } |
| 8561 | 8581 | |
| 8562 | 8582 | return strObjPtr; |
| 8563 | 8583 | } |
| @@ -8575,17 +8595,17 @@ | ||
| 8575 | 8595 | static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) |
| 8576 | 8596 | { |
| 8577 | 8597 | static const char * const strclassnames[] = { |
| 8578 | 8598 | "integer", "alpha", "alnum", "ascii", "digit", |
| 8579 | 8599 | "double", "lower", "upper", "space", "xdigit", |
| 8580 | - "control", "print", "graph", "punct", | |
| 8600 | + "control", "print", "graph", "punct", "boolean", | |
| 8581 | 8601 | NULL |
| 8582 | 8602 | }; |
| 8583 | 8603 | enum { |
| 8584 | 8604 | STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, |
| 8585 | 8605 | STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, |
| 8586 | - STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT | |
| 8606 | + STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT, STR_IS_BOOLEAN, | |
| 8587 | 8607 | }; |
| 8588 | 8608 | int strclass; |
| 8589 | 8609 | int len; |
| 8590 | 8610 | int i; |
| 8591 | 8611 | const char *str; |
| @@ -8613,10 +8633,17 @@ | ||
| 8613 | 8633 | { |
| 8614 | 8634 | double d; |
| 8615 | 8635 | Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); |
| 8616 | 8636 | return JIM_OK; |
| 8617 | 8637 | } |
| 8638 | + | |
| 8639 | + case STR_IS_BOOLEAN: | |
| 8640 | + { | |
| 8641 | + int b; | |
| 8642 | + Jim_SetResultBool(interp, Jim_GetBoolean(interp, strObjPtr, &b) == JIM_OK); | |
| 8643 | + return JIM_OK; | |
| 8644 | + } | |
| 8618 | 8645 | |
| 8619 | 8646 | case STR_IS_ALPHA: isclassfunc = isalpha; break; |
| 8620 | 8647 | case STR_IS_ALNUM: isclassfunc = isalnum; break; |
| 8621 | 8648 | case STR_IS_ASCII: isclassfunc = jim_isascii; break; |
| 8622 | 8649 | case STR_IS_DIGIT: isclassfunc = isdigit; break; |
| @@ -8631,11 +8658,11 @@ | ||
| 8631 | 8658 | default: |
| 8632 | 8659 | return JIM_ERR; |
| 8633 | 8660 | } |
| 8634 | 8661 | |
| 8635 | 8662 | for (i = 0; i < len; i++) { |
| 8636 | - if (!isclassfunc(str[i])) { | |
| 8663 | + if (!isclassfunc(UCHAR(str[i]))) { | |
| 8637 | 8664 | Jim_SetResultBool(interp, 0); |
| 8638 | 8665 | return JIM_OK; |
| 8639 | 8666 | } |
| 8640 | 8667 | } |
| 8641 | 8668 | Jim_SetResultBool(interp, 1); |
| @@ -8656,20 +8683,18 @@ | ||
| 8656 | 8683 | { |
| 8657 | 8684 | if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { |
| 8658 | 8685 | return 1; |
| 8659 | 8686 | } |
| 8660 | 8687 | else { |
| 8661 | - const char *objStr = Jim_String(objPtr); | |
| 8662 | - | |
| 8663 | - if (strcmp(str, objStr) != 0) | |
| 8688 | + if (strcmp(str, Jim_String(objPtr)) != 0) | |
| 8664 | 8689 | return 0; |
| 8665 | 8690 | |
| 8666 | 8691 | if (objPtr->typePtr != &comparedStringObjType) { |
| 8667 | 8692 | Jim_FreeIntRep(interp, objPtr); |
| 8668 | 8693 | objPtr->typePtr = &comparedStringObjType; |
| 8669 | 8694 | } |
| 8670 | - objPtr->internalRep.ptr = (char *)str; | |
| 8695 | + objPtr->internalRep.ptr = (char *)str; | |
| 8671 | 8696 | return 1; |
| 8672 | 8697 | } |
| 8673 | 8698 | } |
| 8674 | 8699 | |
| 8675 | 8700 | static int qsortCompareStringPointers(const void *a, const void *b) |
| @@ -8758,20 +8783,20 @@ | ||
| 8758 | 8783 | int type; |
| 8759 | 8784 | } ScriptToken; |
| 8760 | 8785 | |
| 8761 | 8786 | typedef struct ScriptObj |
| 8762 | 8787 | { |
| 8763 | - ScriptToken *token; | |
| 8764 | - Jim_Obj *fileNameObj; | |
| 8765 | - int len; | |
| 8766 | - int substFlags; | |
| 8788 | + ScriptToken *token; | |
| 8789 | + Jim_Obj *fileNameObj; | |
| 8790 | + int len; | |
| 8791 | + int substFlags; | |
| 8767 | 8792 | int inUse; /* Used to share a ScriptObj. Currently |
| 8768 | 8793 | only used by Jim_EvalObj() as protection against |
| 8769 | 8794 | shimmering of the currently evaluated object. */ |
| 8770 | - int firstline; | |
| 8771 | - int linenr; | |
| 8772 | - int missing; | |
| 8795 | + int firstline; | |
| 8796 | + int linenr; | |
| 8797 | + int missing; | |
| 8773 | 8798 | } ScriptObj; |
| 8774 | 8799 | |
| 8775 | 8800 | static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8776 | 8801 | static int JimParseCheckMissing(Jim_Interp *interp, int ch); |
| 8777 | 8802 | static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr); |
| @@ -8799,23 +8824,23 @@ | ||
| 8799 | 8824 | dupPtr->typePtr = NULL; |
| 8800 | 8825 | } |
| 8801 | 8826 | |
| 8802 | 8827 | typedef struct |
| 8803 | 8828 | { |
| 8804 | - const char *token; | |
| 8805 | - int len; | |
| 8806 | - int type; | |
| 8807 | - int line; | |
| 8829 | + const char *token; | |
| 8830 | + int len; | |
| 8831 | + int type; | |
| 8832 | + int line; | |
| 8808 | 8833 | } ParseToken; |
| 8809 | 8834 | |
| 8810 | 8835 | typedef struct |
| 8811 | 8836 | { |
| 8812 | - | |
| 8813 | - ParseToken *list; | |
| 8814 | - int size; | |
| 8815 | - int count; | |
| 8816 | - ParseToken static_list[20]; | |
| 8837 | + | |
| 8838 | + ParseToken *list; | |
| 8839 | + int size; | |
| 8840 | + int count; | |
| 8841 | + ParseToken static_list[20]; | |
| 8817 | 8842 | } ParseTokenList; |
| 8818 | 8843 | |
| 8819 | 8844 | static void ScriptTokenListInit(ParseTokenList *tokenlist) |
| 8820 | 8845 | { |
| 8821 | 8846 | tokenlist->list = tokenlist->static_list; |
| @@ -8834,18 +8859,18 @@ | ||
| 8834 | 8859 | int line) |
| 8835 | 8860 | { |
| 8836 | 8861 | ParseToken *t; |
| 8837 | 8862 | |
| 8838 | 8863 | if (tokenlist->count == tokenlist->size) { |
| 8839 | - | |
| 8864 | + | |
| 8840 | 8865 | tokenlist->size *= 2; |
| 8841 | 8866 | if (tokenlist->list != tokenlist->static_list) { |
| 8842 | 8867 | tokenlist->list = |
| 8843 | 8868 | Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list)); |
| 8844 | 8869 | } |
| 8845 | 8870 | else { |
| 8846 | - | |
| 8871 | + | |
| 8847 | 8872 | tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list)); |
| 8848 | 8873 | memcpy(tokenlist->list, tokenlist->static_list, |
| 8849 | 8874 | tokenlist->count * sizeof(*tokenlist->list)); |
| 8850 | 8875 | } |
| 8851 | 8876 | } |
| @@ -8854,25 +8879,32 @@ | ||
| 8854 | 8879 | t->len = len; |
| 8855 | 8880 | t->type = type; |
| 8856 | 8881 | t->line = line; |
| 8857 | 8882 | } |
| 8858 | 8883 | |
| 8859 | -static int JimCountWordTokens(ParseToken *t) | |
| 8884 | +static int JimCountWordTokens(struct ScriptObj *script, ParseToken *t) | |
| 8860 | 8885 | { |
| 8861 | 8886 | int expand = 1; |
| 8862 | 8887 | int count = 0; |
| 8863 | 8888 | |
| 8864 | - | |
| 8889 | + | |
| 8865 | 8890 | if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { |
| 8866 | 8891 | if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { |
| 8867 | - | |
| 8892 | + | |
| 8868 | 8893 | expand = -1; |
| 8869 | 8894 | t++; |
| 8870 | 8895 | } |
| 8896 | + else { | |
| 8897 | + if (script->missing == ' ') { | |
| 8898 | + | |
| 8899 | + script->missing = '}'; | |
| 8900 | + script->linenr = t[1].line; | |
| 8901 | + } | |
| 8902 | + } | |
| 8871 | 8903 | } |
| 8872 | 8904 | |
| 8873 | - | |
| 8905 | + | |
| 8874 | 8906 | while (!TOKEN_IS_SEP(t->type)) { |
| 8875 | 8907 | t++; |
| 8876 | 8908 | count++; |
| 8877 | 8909 | } |
| 8878 | 8910 | |
| @@ -8882,11 +8914,11 @@ | ||
| 8882 | 8914 | static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t) |
| 8883 | 8915 | { |
| 8884 | 8916 | Jim_Obj *objPtr; |
| 8885 | 8917 | |
| 8886 | 8918 | if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) { |
| 8887 | - | |
| 8919 | + | |
| 8888 | 8920 | int len = t->len; |
| 8889 | 8921 | char *str = Jim_Alloc(len + 1); |
| 8890 | 8922 | len = JimEscape(str, t->token, len); |
| 8891 | 8923 | objPtr = Jim_NewStringObjNoAlloc(interp, str, len); |
| 8892 | 8924 | } |
| @@ -8899,13 +8931,13 @@ | ||
| 8899 | 8931 | static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, |
| 8900 | 8932 | ParseTokenList *tokenlist) |
| 8901 | 8933 | { |
| 8902 | 8934 | int i; |
| 8903 | 8935 | struct ScriptToken *token; |
| 8904 | - | |
| 8936 | + | |
| 8905 | 8937 | int lineargs = 0; |
| 8906 | - | |
| 8938 | + | |
| 8907 | 8939 | ScriptToken *linefirst; |
| 8908 | 8940 | int count; |
| 8909 | 8941 | int linenr; |
| 8910 | 8942 | |
| 8911 | 8943 | #ifdef DEBUG_SHOW_SCRIPT_TOKENS |
| @@ -8914,11 +8946,11 @@ | ||
| 8914 | 8946 | printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type), |
| 8915 | 8947 | tokenlist->list[i].len, tokenlist->list[i].token); |
| 8916 | 8948 | } |
| 8917 | 8949 | #endif |
| 8918 | 8950 | |
| 8919 | - | |
| 8951 | + | |
| 8920 | 8952 | count = tokenlist->count; |
| 8921 | 8953 | for (i = 0; i < tokenlist->count; i++) { |
| 8922 | 8954 | if (tokenlist->list[i].type == JIM_TT_EOL) { |
| 8923 | 8955 | count++; |
| 8924 | 8956 | } |
| @@ -8925,59 +8957,59 @@ | ||
| 8925 | 8957 | } |
| 8926 | 8958 | linenr = script->firstline = tokenlist->list[0].line; |
| 8927 | 8959 | |
| 8928 | 8960 | token = script->token = Jim_Alloc(sizeof(ScriptToken) * count); |
| 8929 | 8961 | |
| 8930 | - | |
| 8962 | + | |
| 8931 | 8963 | linefirst = token++; |
| 8932 | 8964 | |
| 8933 | 8965 | for (i = 0; i < tokenlist->count; ) { |
| 8934 | - | |
| 8966 | + | |
| 8935 | 8967 | int wordtokens; |
| 8936 | 8968 | |
| 8937 | - | |
| 8969 | + | |
| 8938 | 8970 | while (tokenlist->list[i].type == JIM_TT_SEP) { |
| 8939 | 8971 | i++; |
| 8940 | 8972 | } |
| 8941 | 8973 | |
| 8942 | - wordtokens = JimCountWordTokens(tokenlist->list + i); | |
| 8974 | + wordtokens = JimCountWordTokens(script, tokenlist->list + i); | |
| 8943 | 8975 | |
| 8944 | 8976 | if (wordtokens == 0) { |
| 8945 | - | |
| 8977 | + | |
| 8946 | 8978 | if (lineargs) { |
| 8947 | 8979 | linefirst->type = JIM_TT_LINE; |
| 8948 | 8980 | linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); |
| 8949 | 8981 | Jim_IncrRefCount(linefirst->objPtr); |
| 8950 | 8982 | |
| 8951 | - | |
| 8983 | + | |
| 8952 | 8984 | lineargs = 0; |
| 8953 | 8985 | linefirst = token++; |
| 8954 | 8986 | } |
| 8955 | 8987 | i++; |
| 8956 | 8988 | continue; |
| 8957 | 8989 | } |
| 8958 | 8990 | else if (wordtokens != 1) { |
| 8959 | - | |
| 8991 | + | |
| 8960 | 8992 | token->type = JIM_TT_WORD; |
| 8961 | 8993 | token->objPtr = Jim_NewIntObj(interp, wordtokens); |
| 8962 | 8994 | Jim_IncrRefCount(token->objPtr); |
| 8963 | 8995 | token++; |
| 8964 | 8996 | if (wordtokens < 0) { |
| 8965 | - | |
| 8997 | + | |
| 8966 | 8998 | i++; |
| 8967 | 8999 | wordtokens = -wordtokens - 1; |
| 8968 | 9000 | lineargs--; |
| 8969 | 9001 | } |
| 8970 | 9002 | } |
| 8971 | 9003 | |
| 8972 | 9004 | if (lineargs == 0) { |
| 8973 | - | |
| 9005 | + | |
| 8974 | 9006 | linenr = tokenlist->list[i].line; |
| 8975 | 9007 | } |
| 8976 | 9008 | lineargs++; |
| 8977 | 9009 | |
| 8978 | - | |
| 9010 | + | |
| 8979 | 9011 | while (wordtokens--) { |
| 8980 | 9012 | const ParseToken *t = &tokenlist->list[i++]; |
| 8981 | 9013 | |
| 8982 | 9014 | token->type = t->type; |
| 8983 | 9015 | token->objPtr = JimMakeScriptObj(interp, t); |
| @@ -9010,11 +9042,11 @@ | ||
| 9010 | 9042 | { |
| 9011 | 9043 | ScriptObj *script = JimGetScript(interp, scriptObj); |
| 9012 | 9044 | if (stateCharPtr) { |
| 9013 | 9045 | *stateCharPtr = script->missing; |
| 9014 | 9046 | } |
| 9015 | - return (script->missing == ' '); | |
| 9047 | + return script->missing == ' ' || script->missing == '}'; | |
| 9016 | 9048 | } |
| 9017 | 9049 | |
| 9018 | 9050 | static int JimParseCheckMissing(Jim_Interp *interp, int ch) |
| 9019 | 9051 | { |
| 9020 | 9052 | const char *msg; |
| @@ -9028,10 +9060,13 @@ | ||
| 9028 | 9060 | msg = "unmatched \"[\""; |
| 9029 | 9061 | break; |
| 9030 | 9062 | case '{': |
| 9031 | 9063 | msg = "missing close-brace"; |
| 9032 | 9064 | break; |
| 9065 | + case '}': | |
| 9066 | + msg = "extra characters after close-brace"; | |
| 9067 | + break; | |
| 9033 | 9068 | case '"': |
| 9034 | 9069 | default: |
| 9035 | 9070 | msg = "missing quote"; |
| 9036 | 9071 | break; |
| 9037 | 9072 | } |
| @@ -9049,11 +9084,11 @@ | ||
| 9049 | 9084 | token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count); |
| 9050 | 9085 | |
| 9051 | 9086 | for (i = 0; i < tokenlist->count; i++) { |
| 9052 | 9087 | const ParseToken *t = &tokenlist->list[i]; |
| 9053 | 9088 | |
| 9054 | - | |
| 9089 | + | |
| 9055 | 9090 | token->type = t->type; |
| 9056 | 9091 | token->objPtr = JimMakeScriptObj(interp, t); |
| 9057 | 9092 | Jim_IncrRefCount(token->objPtr); |
| 9058 | 9093 | token++; |
| 9059 | 9094 | } |
| @@ -9068,29 +9103,29 @@ | ||
| 9068 | 9103 | struct JimParserCtx parser; |
| 9069 | 9104 | struct ScriptObj *script; |
| 9070 | 9105 | ParseTokenList tokenlist; |
| 9071 | 9106 | int line = 1; |
| 9072 | 9107 | |
| 9073 | - | |
| 9108 | + | |
| 9074 | 9109 | if (objPtr->typePtr == &sourceObjType) { |
| 9075 | 9110 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 9076 | 9111 | } |
| 9077 | 9112 | |
| 9078 | - | |
| 9113 | + | |
| 9079 | 9114 | ScriptTokenListInit(&tokenlist); |
| 9080 | 9115 | |
| 9081 | 9116 | JimParserInit(&parser, scriptText, scriptTextLen, line); |
| 9082 | 9117 | while (!parser.eof) { |
| 9083 | 9118 | JimParseScript(&parser); |
| 9084 | 9119 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 9085 | 9120 | parser.tline); |
| 9086 | 9121 | } |
| 9087 | 9122 | |
| 9088 | - | |
| 9123 | + | |
| 9089 | 9124 | ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); |
| 9090 | 9125 | |
| 9091 | - | |
| 9126 | + | |
| 9092 | 9127 | script = Jim_Alloc(sizeof(*script)); |
| 9093 | 9128 | memset(script, 0, sizeof(*script)); |
| 9094 | 9129 | script->inUse = 1; |
| 9095 | 9130 | if (objPtr->typePtr == &sourceObjType) { |
| 9096 | 9131 | script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| @@ -9102,14 +9137,14 @@ | ||
| 9102 | 9137 | script->missing = parser.missing.ch; |
| 9103 | 9138 | script->linenr = parser.missing.line; |
| 9104 | 9139 | |
| 9105 | 9140 | ScriptObjAddTokens(interp, script, &tokenlist); |
| 9106 | 9141 | |
| 9107 | - | |
| 9142 | + | |
| 9108 | 9143 | ScriptTokenListFree(&tokenlist); |
| 9109 | 9144 | |
| 9110 | - | |
| 9145 | + | |
| 9111 | 9146 | Jim_FreeIntRep(interp, objPtr); |
| 9112 | 9147 | Jim_SetIntRepPtr(objPtr, script); |
| 9113 | 9148 | objPtr->typePtr = &scriptObjType; |
| 9114 | 9149 | } |
| 9115 | 9150 | |
| @@ -9116,11 +9151,11 @@ | ||
| 9116 | 9151 | static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script); |
| 9117 | 9152 | |
| 9118 | 9153 | static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 9119 | 9154 | { |
| 9120 | 9155 | if (objPtr == interp->emptyObj) { |
| 9121 | - | |
| 9156 | + | |
| 9122 | 9157 | objPtr = interp->nullScriptObj; |
| 9123 | 9158 | } |
| 9124 | 9159 | |
| 9125 | 9160 | if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { |
| 9126 | 9161 | JimSetScriptFromAny(interp, objPtr); |
| @@ -9155,67 +9190,66 @@ | ||
| 9155 | 9190 | Jim_FreeHashTable(cmdPtr->u.proc.staticVars); |
| 9156 | 9191 | Jim_Free(cmdPtr->u.proc.staticVars); |
| 9157 | 9192 | } |
| 9158 | 9193 | } |
| 9159 | 9194 | else { |
| 9160 | - | |
| 9195 | + | |
| 9161 | 9196 | if (cmdPtr->u.native.delProc) { |
| 9162 | 9197 | cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData); |
| 9163 | 9198 | } |
| 9164 | 9199 | } |
| 9165 | 9200 | if (cmdPtr->prevCmd) { |
| 9166 | - | |
| 9201 | + | |
| 9167 | 9202 | JimDecrCmdRefCount(interp, cmdPtr->prevCmd); |
| 9168 | 9203 | } |
| 9169 | 9204 | Jim_Free(cmdPtr); |
| 9170 | 9205 | } |
| 9171 | 9206 | } |
| 9172 | - | |
| 9173 | 9207 | |
| 9174 | 9208 | static void JimVariablesHTValDestructor(void *interp, void *val) |
| 9175 | 9209 | { |
| 9176 | 9210 | Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr); |
| 9177 | 9211 | Jim_Free(val); |
| 9178 | 9212 | } |
| 9179 | 9213 | |
| 9180 | 9214 | static const Jim_HashTableType JimVariablesHashTableType = { |
| 9181 | - JimStringCopyHTHashFunction, | |
| 9182 | - JimStringCopyHTDup, | |
| 9183 | - NULL, | |
| 9184 | - JimStringCopyHTKeyCompare, | |
| 9185 | - JimStringCopyHTKeyDestructor, | |
| 9186 | - JimVariablesHTValDestructor | |
| 9215 | + JimStringCopyHTHashFunction, | |
| 9216 | + JimStringCopyHTDup, | |
| 9217 | + NULL, | |
| 9218 | + JimStringCopyHTKeyCompare, | |
| 9219 | + JimStringCopyHTKeyDestructor, | |
| 9220 | + JimVariablesHTValDestructor | |
| 9187 | 9221 | }; |
| 9188 | 9222 | |
| 9189 | 9223 | static void JimCommandsHT_ValDestructor(void *interp, void *val) |
| 9190 | 9224 | { |
| 9191 | 9225 | JimDecrCmdRefCount(interp, val); |
| 9192 | 9226 | } |
| 9193 | 9227 | |
| 9194 | 9228 | static const Jim_HashTableType JimCommandsHashTableType = { |
| 9195 | - JimStringCopyHTHashFunction, | |
| 9196 | - JimStringCopyHTDup, | |
| 9197 | - NULL, | |
| 9198 | - JimStringCopyHTKeyCompare, | |
| 9199 | - JimStringCopyHTKeyDestructor, | |
| 9200 | - JimCommandsHT_ValDestructor | |
| 9229 | + JimStringCopyHTHashFunction, | |
| 9230 | + JimStringCopyHTDup, | |
| 9231 | + NULL, | |
| 9232 | + JimStringCopyHTKeyCompare, | |
| 9233 | + JimStringCopyHTKeyDestructor, | |
| 9234 | + JimCommandsHT_ValDestructor | |
| 9201 | 9235 | }; |
| 9202 | 9236 | |
| 9203 | 9237 | |
| 9204 | 9238 | |
| 9205 | 9239 | #ifdef jim_ext_namespace |
| 9206 | 9240 | static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj) |
| 9207 | 9241 | { |
| 9208 | 9242 | const char *name = Jim_String(nsObj); |
| 9209 | 9243 | if (name[0] == ':' && name[1] == ':') { |
| 9210 | - | |
| 9244 | + | |
| 9211 | 9245 | while (*++name == ':') { |
| 9212 | 9246 | } |
| 9213 | 9247 | nsObj = Jim_NewStringObj(interp, name, -1); |
| 9214 | 9248 | } |
| 9215 | 9249 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9216 | - | |
| 9250 | + | |
| 9217 | 9251 | nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9218 | 9252 | Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 9219 | 9253 | } |
| 9220 | 9254 | return nsObj; |
| 9221 | 9255 | } |
| @@ -9239,16 +9273,16 @@ | ||
| 9239 | 9273 | static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 9240 | 9274 | { |
| 9241 | 9275 | Jim_Obj *objPtr = interp->emptyObj; |
| 9242 | 9276 | |
| 9243 | 9277 | if (name[0] == ':' && name[1] == ':') { |
| 9244 | - | |
| 9278 | + | |
| 9245 | 9279 | while (*++name == ':') { |
| 9246 | 9280 | } |
| 9247 | 9281 | } |
| 9248 | 9282 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9249 | - | |
| 9283 | + | |
| 9250 | 9284 | objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9251 | 9285 | Jim_AppendStrings(interp, objPtr, "::", name, NULL); |
| 9252 | 9286 | name = Jim_String(objPtr); |
| 9253 | 9287 | } |
| 9254 | 9288 | Jim_IncrRefCount(objPtr); |
| @@ -9257,11 +9291,11 @@ | ||
| 9257 | 9291 | } |
| 9258 | 9292 | |
| 9259 | 9293 | #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ)) |
| 9260 | 9294 | |
| 9261 | 9295 | #else |
| 9262 | - | |
| 9296 | + | |
| 9263 | 9297 | #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 9264 | 9298 | #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 9265 | 9299 | |
| 9266 | 9300 | Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 9267 | 9301 | { |
| @@ -9276,17 +9310,17 @@ | ||
| 9276 | 9310 | |
| 9277 | 9311 | Jim_InterpIncrProcEpoch(interp); |
| 9278 | 9312 | } |
| 9279 | 9313 | |
| 9280 | 9314 | if (he && interp->local) { |
| 9281 | - | |
| 9315 | + | |
| 9282 | 9316 | cmd->prevCmd = Jim_GetHashEntryVal(he); |
| 9283 | 9317 | Jim_SetHashVal(&interp->commands, he, cmd); |
| 9284 | 9318 | } |
| 9285 | 9319 | else { |
| 9286 | 9320 | if (he) { |
| 9287 | - | |
| 9321 | + | |
| 9288 | 9322 | Jim_DeleteHashEntry(&interp->commands, name); |
| 9289 | 9323 | } |
| 9290 | 9324 | |
| 9291 | 9325 | Jim_AddHashEntry(&interp->commands, name, cmd); |
| 9292 | 9326 | } |
| @@ -9297,11 +9331,11 @@ | ||
| 9297 | 9331 | int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr, |
| 9298 | 9332 | Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc) |
| 9299 | 9333 | { |
| 9300 | 9334 | Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); |
| 9301 | 9335 | |
| 9302 | - | |
| 9336 | + | |
| 9303 | 9337 | memset(cmdPtr, 0, sizeof(*cmdPtr)); |
| 9304 | 9338 | cmdPtr->inUse = 1; |
| 9305 | 9339 | cmdPtr->u.native.delProc = delProc; |
| 9306 | 9340 | cmdPtr->u.native.cmdProc = cmdProc; |
| 9307 | 9341 | cmdPtr->u.native.privData = privData; |
| @@ -9326,11 +9360,11 @@ | ||
| 9326 | 9360 | Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; |
| 9327 | 9361 | Jim_Var *varPtr; |
| 9328 | 9362 | int subLen; |
| 9329 | 9363 | |
| 9330 | 9364 | objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); |
| 9331 | - | |
| 9365 | + | |
| 9332 | 9366 | subLen = Jim_ListLength(interp, objPtr); |
| 9333 | 9367 | if (subLen == 1 || subLen == 2) { |
| 9334 | 9368 | nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); |
| 9335 | 9369 | if (subLen == 1) { |
| 9336 | 9370 | initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| @@ -9372,19 +9406,19 @@ | ||
| 9372 | 9406 | |
| 9373 | 9407 | static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname) |
| 9374 | 9408 | { |
| 9375 | 9409 | #ifdef jim_ext_namespace |
| 9376 | 9410 | if (cmdPtr->isproc) { |
| 9377 | - | |
| 9411 | + | |
| 9378 | 9412 | const char *pt = strrchr(cmdname, ':'); |
| 9379 | 9413 | if (pt && pt != cmdname && pt[-1] == ':') { |
| 9380 | 9414 | Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); |
| 9381 | 9415 | cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1); |
| 9382 | 9416 | Jim_IncrRefCount(cmdPtr->u.proc.nsObj); |
| 9383 | 9417 | |
| 9384 | 9418 | if (Jim_FindHashEntry(&interp->commands, pt + 1)) { |
| 9385 | - | |
| 9419 | + | |
| 9386 | 9420 | Jim_InterpIncrProcEpoch(interp); |
| 9387 | 9421 | } |
| 9388 | 9422 | } |
| 9389 | 9423 | } |
| 9390 | 9424 | #endif |
| @@ -9397,11 +9431,11 @@ | ||
| 9397 | 9431 | int argListLen; |
| 9398 | 9432 | int i; |
| 9399 | 9433 | |
| 9400 | 9434 | argListLen = Jim_ListLength(interp, argListObjPtr); |
| 9401 | 9435 | |
| 9402 | - | |
| 9436 | + | |
| 9403 | 9437 | cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); |
| 9404 | 9438 | memset(cmdPtr, 0, sizeof(*cmdPtr)); |
| 9405 | 9439 | cmdPtr->inUse = 1; |
| 9406 | 9440 | cmdPtr->isproc = 1; |
| 9407 | 9441 | cmdPtr->u.proc.argListObjPtr = argListObjPtr; |
| @@ -9412,24 +9446,24 @@ | ||
| 9412 | 9446 | cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj; |
| 9413 | 9447 | Jim_IncrRefCount(argListObjPtr); |
| 9414 | 9448 | Jim_IncrRefCount(bodyObjPtr); |
| 9415 | 9449 | Jim_IncrRefCount(cmdPtr->u.proc.nsObj); |
| 9416 | 9450 | |
| 9417 | - | |
| 9451 | + | |
| 9418 | 9452 | if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) { |
| 9419 | 9453 | goto err; |
| 9420 | 9454 | } |
| 9421 | 9455 | |
| 9422 | - | |
| 9423 | - | |
| 9456 | + | |
| 9457 | + | |
| 9424 | 9458 | for (i = 0; i < argListLen; i++) { |
| 9425 | 9459 | Jim_Obj *argPtr; |
| 9426 | 9460 | Jim_Obj *nameObjPtr; |
| 9427 | 9461 | Jim_Obj *defaultObjPtr; |
| 9428 | 9462 | int len; |
| 9429 | 9463 | |
| 9430 | - | |
| 9464 | + | |
| 9431 | 9465 | argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); |
| 9432 | 9466 | len = Jim_ListLength(interp, argPtr); |
| 9433 | 9467 | if (len == 0) { |
| 9434 | 9468 | Jim_SetResultString(interp, "argument with no name", -1); |
| 9435 | 9469 | err: |
| @@ -9440,16 +9474,16 @@ | ||
| 9440 | 9474 | Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr); |
| 9441 | 9475 | goto err; |
| 9442 | 9476 | } |
| 9443 | 9477 | |
| 9444 | 9478 | if (len == 2) { |
| 9445 | - | |
| 9479 | + | |
| 9446 | 9480 | nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); |
| 9447 | 9481 | defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); |
| 9448 | 9482 | } |
| 9449 | 9483 | else { |
| 9450 | - | |
| 9484 | + | |
| 9451 | 9485 | nameObjPtr = argPtr; |
| 9452 | 9486 | defaultObjPtr = NULL; |
| 9453 | 9487 | } |
| 9454 | 9488 | |
| 9455 | 9489 | |
| @@ -9510,29 +9544,29 @@ | ||
| 9510 | 9544 | } |
| 9511 | 9545 | |
| 9512 | 9546 | fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj); |
| 9513 | 9547 | fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj); |
| 9514 | 9548 | |
| 9515 | - | |
| 9549 | + | |
| 9516 | 9550 | he = Jim_FindHashEntry(&interp->commands, fqold); |
| 9517 | 9551 | if (he == NULL) { |
| 9518 | 9552 | Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName); |
| 9519 | 9553 | } |
| 9520 | 9554 | else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9521 | 9555 | Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 9522 | 9556 | } |
| 9523 | 9557 | else { |
| 9524 | - | |
| 9558 | + | |
| 9525 | 9559 | cmdPtr = Jim_GetHashEntryVal(he); |
| 9526 | 9560 | JimIncrCmdRefCount(cmdPtr); |
| 9527 | 9561 | JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9528 | 9562 | Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9529 | 9563 | |
| 9530 | - | |
| 9564 | + | |
| 9531 | 9565 | Jim_DeleteHashEntry(&interp->commands, fqold); |
| 9532 | 9566 | |
| 9533 | - | |
| 9567 | + | |
| 9534 | 9568 | Jim_InterpIncrProcEpoch(interp); |
| 9535 | 9569 | |
| 9536 | 9570 | ret = JIM_OK; |
| 9537 | 9571 | } |
| 9538 | 9572 | |
| @@ -9571,23 +9605,23 @@ | ||
| 9571 | 9605 | objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch |
| 9572 | 9606 | #ifdef jim_ext_namespace |
| 9573 | 9607 | || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj) |
| 9574 | 9608 | #endif |
| 9575 | 9609 | ) { |
| 9576 | - | |
| 9577 | 9610 | |
| 9578 | - | |
| 9611 | + | |
| 9612 | + | |
| 9579 | 9613 | const char *name = Jim_String(objPtr); |
| 9580 | 9614 | Jim_HashEntry *he; |
| 9581 | 9615 | |
| 9582 | 9616 | if (name[0] == ':' && name[1] == ':') { |
| 9583 | 9617 | while (*++name == ':') { |
| 9584 | 9618 | } |
| 9585 | 9619 | } |
| 9586 | 9620 | #ifdef jim_ext_namespace |
| 9587 | 9621 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9588 | - | |
| 9622 | + | |
| 9589 | 9623 | Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9590 | 9624 | Jim_AppendStrings(interp, nameObj, "::", name, NULL); |
| 9591 | 9625 | he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj)); |
| 9592 | 9626 | Jim_FreeNewObj(interp, nameObj); |
| 9593 | 9627 | if (he) { |
| @@ -9594,11 +9628,11 @@ | ||
| 9594 | 9628 | goto found; |
| 9595 | 9629 | } |
| 9596 | 9630 | } |
| 9597 | 9631 | #endif |
| 9598 | 9632 | |
| 9599 | - | |
| 9633 | + | |
| 9600 | 9634 | he = Jim_FindHashEntry(&interp->commands, name); |
| 9601 | 9635 | if (he == NULL) { |
| 9602 | 9636 | if (flags & JIM_ERRMSG) { |
| 9603 | 9637 | Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); |
| 9604 | 9638 | } |
| @@ -9607,11 +9641,11 @@ | ||
| 9607 | 9641 | #ifdef jim_ext_namespace |
| 9608 | 9642 | found: |
| 9609 | 9643 | #endif |
| 9610 | 9644 | cmd = Jim_GetHashEntryVal(he); |
| 9611 | 9645 | |
| 9612 | - | |
| 9646 | + | |
| 9613 | 9647 | Jim_FreeIntRep(interp, objPtr); |
| 9614 | 9648 | objPtr->typePtr = &commandObjType; |
| 9615 | 9649 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| 9616 | 9650 | objPtr->internalRep.cmdValue.cmdPtr = cmd; |
| 9617 | 9651 | objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj; |
| @@ -9626,11 +9660,11 @@ | ||
| 9626 | 9660 | return cmd; |
| 9627 | 9661 | } |
| 9628 | 9662 | |
| 9629 | 9663 | |
| 9630 | 9664 | |
| 9631 | -#define JIM_DICT_SUGAR 100 | |
| 9665 | +#define JIM_DICT_SUGAR 100 | |
| 9632 | 9666 | |
| 9633 | 9667 | static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 9634 | 9668 | |
| 9635 | 9669 | static const Jim_ObjType variableObjType = { |
| 9636 | 9670 | "variable", |
| @@ -9640,11 +9674,11 @@ | ||
| 9640 | 9674 | JIM_TYPE_REFERENCES, |
| 9641 | 9675 | }; |
| 9642 | 9676 | |
| 9643 | 9677 | static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) |
| 9644 | 9678 | { |
| 9645 | - | |
| 9679 | + | |
| 9646 | 9680 | if (nameObjPtr->typePtr != &variableObjType) { |
| 9647 | 9681 | int len; |
| 9648 | 9682 | const char *str = Jim_GetString(nameObjPtr, &len); |
| 9649 | 9683 | if (memchr(str, '\0', len)) { |
| 9650 | 9684 | Jim_SetResultFormatted(interp, "%s name contains embedded null", type); |
| @@ -9660,18 +9694,18 @@ | ||
| 9660 | 9694 | Jim_CallFrame *framePtr; |
| 9661 | 9695 | Jim_HashEntry *he; |
| 9662 | 9696 | int global; |
| 9663 | 9697 | int len; |
| 9664 | 9698 | |
| 9665 | - | |
| 9699 | + | |
| 9666 | 9700 | if (objPtr->typePtr == &variableObjType) { |
| 9667 | 9701 | framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr; |
| 9668 | 9702 | if (objPtr->internalRep.varValue.callFrameId == framePtr->id) { |
| 9669 | - | |
| 9703 | + | |
| 9670 | 9704 | return JIM_OK; |
| 9671 | 9705 | } |
| 9672 | - | |
| 9706 | + | |
| 9673 | 9707 | } |
| 9674 | 9708 | else if (objPtr->typePtr == &dictSubstObjType) { |
| 9675 | 9709 | return JIM_DICT_SUGAR; |
| 9676 | 9710 | } |
| 9677 | 9711 | else if (JimValidName(interp, "variable", objPtr) != JIM_OK) { |
| @@ -9679,11 +9713,11 @@ | ||
| 9679 | 9713 | } |
| 9680 | 9714 | |
| 9681 | 9715 | |
| 9682 | 9716 | varName = Jim_GetString(objPtr, &len); |
| 9683 | 9717 | |
| 9684 | - | |
| 9718 | + | |
| 9685 | 9719 | if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) { |
| 9686 | 9720 | return JIM_DICT_SUGAR; |
| 9687 | 9721 | } |
| 9688 | 9722 | |
| 9689 | 9723 | if (varName[0] == ':' && varName[1] == ':') { |
| @@ -9695,23 +9729,23 @@ | ||
| 9695 | 9729 | else { |
| 9696 | 9730 | global = 0; |
| 9697 | 9731 | framePtr = interp->framePtr; |
| 9698 | 9732 | } |
| 9699 | 9733 | |
| 9700 | - | |
| 9734 | + | |
| 9701 | 9735 | he = Jim_FindHashEntry(&framePtr->vars, varName); |
| 9702 | 9736 | if (he == NULL) { |
| 9703 | 9737 | if (!global && framePtr->staticVars) { |
| 9704 | - | |
| 9738 | + | |
| 9705 | 9739 | he = Jim_FindHashEntry(framePtr->staticVars, varName); |
| 9706 | 9740 | } |
| 9707 | 9741 | if (he == NULL) { |
| 9708 | 9742 | return JIM_ERR; |
| 9709 | 9743 | } |
| 9710 | 9744 | } |
| 9711 | 9745 | |
| 9712 | - | |
| 9746 | + | |
| 9713 | 9747 | Jim_FreeIntRep(interp, objPtr); |
| 9714 | 9748 | objPtr->typePtr = &variableObjType; |
| 9715 | 9749 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9716 | 9750 | objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); |
| 9717 | 9751 | objPtr->internalRep.varValue.global = global; |
| @@ -9726,11 +9760,11 @@ | ||
| 9726 | 9760 | { |
| 9727 | 9761 | const char *name; |
| 9728 | 9762 | Jim_CallFrame *framePtr; |
| 9729 | 9763 | int global; |
| 9730 | 9764 | |
| 9731 | - | |
| 9765 | + | |
| 9732 | 9766 | Jim_Var *var = Jim_Alloc(sizeof(*var)); |
| 9733 | 9767 | |
| 9734 | 9768 | var->objPtr = valObjPtr; |
| 9735 | 9769 | Jim_IncrRefCount(valObjPtr); |
| 9736 | 9770 | var->linkFramePtr = NULL; |
| @@ -9745,14 +9779,14 @@ | ||
| 9745 | 9779 | else { |
| 9746 | 9780 | framePtr = interp->framePtr; |
| 9747 | 9781 | global = 0; |
| 9748 | 9782 | } |
| 9749 | 9783 | |
| 9750 | - | |
| 9784 | + | |
| 9751 | 9785 | Jim_AddHashEntry(&framePtr->vars, name, var); |
| 9752 | 9786 | |
| 9753 | - | |
| 9787 | + | |
| 9754 | 9788 | Jim_FreeIntRep(interp, nameObjPtr); |
| 9755 | 9789 | nameObjPtr->typePtr = &variableObjType; |
| 9756 | 9790 | nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9757 | 9791 | nameObjPtr->internalRep.varValue.varPtr = var; |
| 9758 | 9792 | nameObjPtr->internalRep.varValue.global = global; |
| @@ -9782,11 +9816,11 @@ | ||
| 9782 | 9816 | if (var->linkFramePtr == NULL) { |
| 9783 | 9817 | Jim_IncrRefCount(valObjPtr); |
| 9784 | 9818 | Jim_DecrRefCount(interp, var->objPtr); |
| 9785 | 9819 | var->objPtr = valObjPtr; |
| 9786 | 9820 | } |
| 9787 | - else { | |
| 9821 | + else { | |
| 9788 | 9822 | Jim_CallFrame *savedCallFrame; |
| 9789 | 9823 | |
| 9790 | 9824 | savedCallFrame = interp->framePtr; |
| 9791 | 9825 | interp->framePtr = var->linkFramePtr; |
| 9792 | 9826 | err = Jim_SetVariable(interp, var->objPtr, valObjPtr); |
| @@ -9822,19 +9856,16 @@ | ||
| 9822 | 9856 | return result; |
| 9823 | 9857 | } |
| 9824 | 9858 | |
| 9825 | 9859 | int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) |
| 9826 | 9860 | { |
| 9827 | - Jim_Obj *nameObjPtr, *valObjPtr; | |
| 9861 | + Jim_Obj *valObjPtr; | |
| 9828 | 9862 | int result; |
| 9829 | 9863 | |
| 9830 | - nameObjPtr = Jim_NewStringObj(interp, name, -1); | |
| 9831 | 9864 | valObjPtr = Jim_NewStringObj(interp, val, -1); |
| 9832 | - Jim_IncrRefCount(nameObjPtr); | |
| 9833 | 9865 | Jim_IncrRefCount(valObjPtr); |
| 9834 | - result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); | |
| 9835 | - Jim_DecrRefCount(interp, nameObjPtr); | |
| 9866 | + result = Jim_SetVariableStr(interp, name, valObjPtr); | |
| 9836 | 9867 | Jim_DecrRefCount(interp, valObjPtr); |
| 9837 | 9868 | return result; |
| 9838 | 9869 | } |
| 9839 | 9870 | |
| 9840 | 9871 | int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, |
| @@ -9843,14 +9874,14 @@ | ||
| 9843 | 9874 | const char *varName; |
| 9844 | 9875 | const char *targetName; |
| 9845 | 9876 | Jim_CallFrame *framePtr; |
| 9846 | 9877 | Jim_Var *varPtr; |
| 9847 | 9878 | |
| 9848 | - | |
| 9879 | + | |
| 9849 | 9880 | switch (SetVariableFromAny(interp, nameObjPtr)) { |
| 9850 | 9881 | case JIM_DICT_SUGAR: |
| 9851 | - | |
| 9882 | + | |
| 9852 | 9883 | Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr); |
| 9853 | 9884 | return JIM_ERR; |
| 9854 | 9885 | |
| 9855 | 9886 | case JIM_OK: |
| 9856 | 9887 | varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| @@ -9858,23 +9889,23 @@ | ||
| 9858 | 9889 | if (varPtr->linkFramePtr == NULL) { |
| 9859 | 9890 | Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); |
| 9860 | 9891 | return JIM_ERR; |
| 9861 | 9892 | } |
| 9862 | 9893 | |
| 9863 | - | |
| 9894 | + | |
| 9864 | 9895 | varPtr->linkFramePtr = NULL; |
| 9865 | 9896 | break; |
| 9866 | 9897 | } |
| 9867 | 9898 | |
| 9868 | - | |
| 9869 | - | |
| 9899 | + | |
| 9900 | + | |
| 9870 | 9901 | varName = Jim_String(nameObjPtr); |
| 9871 | 9902 | |
| 9872 | 9903 | if (varName[0] == ':' && varName[1] == ':') { |
| 9873 | 9904 | while (*++varName == ':') { |
| 9874 | 9905 | } |
| 9875 | - | |
| 9906 | + | |
| 9876 | 9907 | framePtr = interp->topFramePtr; |
| 9877 | 9908 | } |
| 9878 | 9909 | else { |
| 9879 | 9910 | framePtr = interp->framePtr; |
| 9880 | 9911 | } |
| @@ -9894,15 +9925,15 @@ | ||
| 9894 | 9925 | nameObjPtr); |
| 9895 | 9926 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9896 | 9927 | return JIM_ERR; |
| 9897 | 9928 | } |
| 9898 | 9929 | |
| 9899 | - | |
| 9930 | + | |
| 9900 | 9931 | if (framePtr == targetCallFrame) { |
| 9901 | 9932 | Jim_Obj *objPtr = targetNameObjPtr; |
| 9902 | 9933 | |
| 9903 | - | |
| 9934 | + | |
| 9904 | 9935 | while (1) { |
| 9905 | 9936 | if (strcmp(Jim_String(objPtr), varName) == 0) { |
| 9906 | 9937 | Jim_SetResultString(interp, "can't upvar from variable to itself", -1); |
| 9907 | 9938 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9908 | 9939 | return JIM_ERR; |
| @@ -9914,13 +9945,13 @@ | ||
| 9914 | 9945 | break; |
| 9915 | 9946 | objPtr = varPtr->objPtr; |
| 9916 | 9947 | } |
| 9917 | 9948 | } |
| 9918 | 9949 | |
| 9919 | - | |
| 9950 | + | |
| 9920 | 9951 | Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); |
| 9921 | - | |
| 9952 | + | |
| 9922 | 9953 | nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; |
| 9923 | 9954 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9924 | 9955 | return JIM_OK; |
| 9925 | 9956 | } |
| 9926 | 9957 | |
| @@ -9934,26 +9965,26 @@ | ||
| 9934 | 9965 | return varPtr->objPtr; |
| 9935 | 9966 | } |
| 9936 | 9967 | else { |
| 9937 | 9968 | Jim_Obj *objPtr; |
| 9938 | 9969 | |
| 9939 | - | |
| 9970 | + | |
| 9940 | 9971 | Jim_CallFrame *savedCallFrame = interp->framePtr; |
| 9941 | 9972 | |
| 9942 | 9973 | interp->framePtr = varPtr->linkFramePtr; |
| 9943 | 9974 | objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); |
| 9944 | 9975 | interp->framePtr = savedCallFrame; |
| 9945 | 9976 | if (objPtr) { |
| 9946 | 9977 | return objPtr; |
| 9947 | 9978 | } |
| 9948 | - | |
| 9979 | + | |
| 9949 | 9980 | } |
| 9950 | 9981 | } |
| 9951 | 9982 | break; |
| 9952 | 9983 | |
| 9953 | 9984 | case JIM_DICT_SUGAR: |
| 9954 | - | |
| 9985 | + | |
| 9955 | 9986 | return JimDictSugarGet(interp, nameObjPtr, flags); |
| 9956 | 9987 | } |
| 9957 | 9988 | if (flags & JIM_ERRMSG) { |
| 9958 | 9989 | Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr); |
| 9959 | 9990 | } |
| @@ -10003,17 +10034,17 @@ | ||
| 10003 | 10034 | int retval; |
| 10004 | 10035 | Jim_CallFrame *framePtr; |
| 10005 | 10036 | |
| 10006 | 10037 | retval = SetVariableFromAny(interp, nameObjPtr); |
| 10007 | 10038 | if (retval == JIM_DICT_SUGAR) { |
| 10008 | - | |
| 10039 | + | |
| 10009 | 10040 | return JimDictSugarSet(interp, nameObjPtr, NULL); |
| 10010 | 10041 | } |
| 10011 | 10042 | else if (retval == JIM_OK) { |
| 10012 | 10043 | varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| 10013 | 10044 | |
| 10014 | - | |
| 10045 | + | |
| 10015 | 10046 | if (varPtr->linkFramePtr) { |
| 10016 | 10047 | framePtr = interp->framePtr; |
| 10017 | 10048 | interp->framePtr = varPtr->linkFramePtr; |
| 10018 | 10049 | retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); |
| 10019 | 10050 | interp->framePtr = framePtr; |
| @@ -10028,11 +10059,11 @@ | ||
| 10028 | 10059 | framePtr = interp->framePtr; |
| 10029 | 10060 | } |
| 10030 | 10061 | |
| 10031 | 10062 | retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 10032 | 10063 | if (retval == JIM_OK) { |
| 10033 | - | |
| 10064 | + | |
| 10034 | 10065 | framePtr->id = interp->callFrameEpoch++; |
| 10035 | 10066 | } |
| 10036 | 10067 | } |
| 10037 | 10068 | } |
| 10038 | 10069 | if (retval != JIM_OK && (flags & JIM_ERRMSG)) { |
| @@ -10061,11 +10092,11 @@ | ||
| 10061 | 10092 | keyLen = (str + len) - p; |
| 10062 | 10093 | if (str[len - 1] == ')') { |
| 10063 | 10094 | keyLen--; |
| 10064 | 10095 | } |
| 10065 | 10096 | |
| 10066 | - | |
| 10097 | + | |
| 10067 | 10098 | keyObjPtr = Jim_NewStringObj(interp, p, keyLen); |
| 10068 | 10099 | |
| 10069 | 10100 | Jim_IncrRefCount(varObjPtr); |
| 10070 | 10101 | Jim_IncrRefCount(keyObjPtr); |
| 10071 | 10102 | *varPtrPtr = varObjPtr; |
| @@ -10080,23 +10111,23 @@ | ||
| 10080 | 10111 | |
| 10081 | 10112 | err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, |
| 10082 | 10113 | &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST); |
| 10083 | 10114 | |
| 10084 | 10115 | if (err == JIM_OK) { |
| 10085 | - | |
| 10116 | + | |
| 10086 | 10117 | Jim_SetEmptyResult(interp); |
| 10087 | 10118 | } |
| 10088 | 10119 | else { |
| 10089 | 10120 | if (!valObjPtr) { |
| 10090 | - | |
| 10121 | + | |
| 10091 | 10122 | if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) { |
| 10092 | 10123 | Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array", |
| 10093 | 10124 | objPtr); |
| 10094 | 10125 | return err; |
| 10095 | 10126 | } |
| 10096 | 10127 | } |
| 10097 | - | |
| 10128 | + | |
| 10098 | 10129 | Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array", |
| 10099 | 10130 | (valObjPtr ? "set" : "unset"), objPtr); |
| 10100 | 10131 | } |
| 10101 | 10132 | return err; |
| 10102 | 10133 | } |
| @@ -10118,11 +10149,11 @@ | ||
| 10118 | 10149 | Jim_SetResultFormatted(interp, |
| 10119 | 10150 | "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, |
| 10120 | 10151 | ret < 0 ? "variable isn't" : "no such element in"); |
| 10121 | 10152 | } |
| 10122 | 10153 | else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { |
| 10123 | - | |
| 10154 | + | |
| 10124 | 10155 | Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); |
| 10125 | 10156 | } |
| 10126 | 10157 | |
| 10127 | 10158 | return resObjPtr; |
| 10128 | 10159 | } |
| @@ -10143,28 +10174,27 @@ | ||
| 10143 | 10174 | { |
| 10144 | 10175 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); |
| 10145 | 10176 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); |
| 10146 | 10177 | } |
| 10147 | 10178 | |
| 10148 | -void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) | |
| 10149 | -{ | |
| 10150 | - JIM_NOTUSED(interp); | |
| 10151 | - | |
| 10152 | - dupPtr->internalRep.dictSubstValue.varNameObjPtr = | |
| 10153 | - srcPtr->internalRep.dictSubstValue.varNameObjPtr; | |
| 10154 | - dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr; | |
| 10155 | - dupPtr->typePtr = &dictSubstObjType; | |
| 10179 | +static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) | |
| 10180 | +{ | |
| 10181 | + | |
| 10182 | + dupPtr->internalRep = srcPtr->internalRep; | |
| 10183 | + | |
| 10184 | + Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.varNameObjPtr); | |
| 10185 | + Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr); | |
| 10156 | 10186 | } |
| 10157 | 10187 | |
| 10158 | 10188 | |
| 10159 | 10189 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10160 | 10190 | { |
| 10161 | 10191 | if (objPtr->typePtr != &dictSubstObjType) { |
| 10162 | 10192 | Jim_Obj *varObjPtr, *keyObjPtr; |
| 10163 | 10193 | |
| 10164 | 10194 | if (objPtr->typePtr == &interpolatedObjType) { |
| 10165 | - | |
| 10195 | + | |
| 10166 | 10196 | |
| 10167 | 10197 | varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr; |
| 10168 | 10198 | keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr; |
| 10169 | 10199 | |
| 10170 | 10200 | Jim_IncrRefCount(varObjPtr); |
| @@ -10202,16 +10232,12 @@ | ||
| 10202 | 10232 | return resObjPtr; |
| 10203 | 10233 | } |
| 10204 | 10234 | |
| 10205 | 10235 | static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10206 | 10236 | { |
| 10207 | - Jim_Obj *resultObjPtr; | |
| 10208 | - | |
| 10209 | - if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) { | |
| 10210 | - | |
| 10211 | - resultObjPtr->refCount--; | |
| 10212 | - return resultObjPtr; | |
| 10237 | + if (Jim_EvalExpression(interp, objPtr) == JIM_OK) { | |
| 10238 | + return Jim_GetResult(interp); | |
| 10213 | 10239 | } |
| 10214 | 10240 | return NULL; |
| 10215 | 10241 | } |
| 10216 | 10242 | |
| 10217 | 10243 | |
| @@ -10249,11 +10275,11 @@ | ||
| 10249 | 10275 | return cf; |
| 10250 | 10276 | } |
| 10251 | 10277 | |
| 10252 | 10278 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) |
| 10253 | 10279 | { |
| 10254 | - | |
| 10280 | + | |
| 10255 | 10281 | if (localCommands) { |
| 10256 | 10282 | Jim_Obj *cmdNameObj; |
| 10257 | 10283 | |
| 10258 | 10284 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 10259 | 10285 | Jim_HashEntry *he; |
| @@ -10268,20 +10294,20 @@ | ||
| 10268 | 10294 | Jim_Cmd *cmd = Jim_GetHashEntryVal(he); |
| 10269 | 10295 | if (cmd->prevCmd) { |
| 10270 | 10296 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 10271 | 10297 | cmd->prevCmd = NULL; |
| 10272 | 10298 | |
| 10273 | - | |
| 10299 | + | |
| 10274 | 10300 | JimDecrCmdRefCount(interp, cmd); |
| 10275 | 10301 | |
| 10276 | - | |
| 10302 | + | |
| 10277 | 10303 | Jim_SetHashVal(ht, he, prevCmd); |
| 10278 | 10304 | } |
| 10279 | 10305 | else { |
| 10280 | 10306 | Jim_DeleteHashEntry(ht, fqname); |
| 10281 | - Jim_InterpIncrProcEpoch(interp); | |
| 10282 | 10307 | } |
| 10308 | + Jim_InterpIncrProcEpoch(interp); | |
| 10283 | 10309 | } |
| 10284 | 10310 | Jim_DecrRefCount(interp, cmdNameObj); |
| 10285 | 10311 | JimFreeQualifiedName(interp, fqObjName); |
| 10286 | 10312 | } |
| 10287 | 10313 | Jim_FreeStack(localCommands); |
| @@ -10288,13 +10314,59 @@ | ||
| 10288 | 10314 | Jim_Free(localCommands); |
| 10289 | 10315 | } |
| 10290 | 10316 | return JIM_OK; |
| 10291 | 10317 | } |
| 10292 | 10318 | |
| 10319 | +static int JimInvokeDefer(Jim_Interp *interp, int retcode) | |
| 10320 | +{ | |
| 10321 | + Jim_Obj *objPtr; | |
| 10293 | 10322 | |
| 10294 | -#define JIM_FCF_FULL 0 | |
| 10295 | -#define JIM_FCF_REUSE 1 | |
| 10323 | + | |
| 10324 | + if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) { | |
| 10325 | + return retcode; | |
| 10326 | + } | |
| 10327 | + | |
| 10328 | + objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE); | |
| 10329 | + | |
| 10330 | + if (objPtr) { | |
| 10331 | + int ret = JIM_OK; | |
| 10332 | + int i; | |
| 10333 | + int listLen = Jim_ListLength(interp, objPtr); | |
| 10334 | + Jim_Obj *resultObjPtr; | |
| 10335 | + | |
| 10336 | + Jim_IncrRefCount(objPtr); | |
| 10337 | + | |
| 10338 | + resultObjPtr = Jim_GetResult(interp); | |
| 10339 | + Jim_IncrRefCount(resultObjPtr); | |
| 10340 | + Jim_SetEmptyResult(interp); | |
| 10341 | + | |
| 10342 | + | |
| 10343 | + for (i = listLen; i > 0; i--) { | |
| 10344 | + | |
| 10345 | + Jim_Obj *scriptObjPtr = Jim_ListGetIndex(interp, objPtr, i - 1); | |
| 10346 | + ret = Jim_EvalObj(interp, scriptObjPtr); | |
| 10347 | + if (ret != JIM_OK) { | |
| 10348 | + break; | |
| 10349 | + } | |
| 10350 | + } | |
| 10351 | + | |
| 10352 | + if (ret == JIM_OK || retcode == JIM_ERR) { | |
| 10353 | + | |
| 10354 | + Jim_SetResult(interp, resultObjPtr); | |
| 10355 | + } | |
| 10356 | + else { | |
| 10357 | + retcode = ret; | |
| 10358 | + } | |
| 10359 | + | |
| 10360 | + Jim_DecrRefCount(interp, resultObjPtr); | |
| 10361 | + Jim_DecrRefCount(interp, objPtr); | |
| 10362 | + } | |
| 10363 | + return retcode; | |
| 10364 | +} | |
| 10365 | + | |
| 10366 | +#define JIM_FCF_FULL 0 | |
| 10367 | +#define JIM_FCF_REUSE 1 | |
| 10296 | 10368 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) |
| 10297 | 10369 | { |
| 10298 | 10370 | JimDeleteLocalProcs(interp, cf->localCommands); |
| 10299 | 10371 | |
| 10300 | 10372 | if (cf->procArgsObjPtr) |
| @@ -10327,263 +10399,10 @@ | ||
| 10327 | 10399 | cf->next = interp->freeFramesList; |
| 10328 | 10400 | interp->freeFramesList = cf; |
| 10329 | 10401 | } |
| 10330 | 10402 | |
| 10331 | 10403 | |
| 10332 | -#ifdef JIM_REFERENCES | |
| 10333 | - | |
| 10334 | -static void JimReferencesHTValDestructor(void *interp, void *val) | |
| 10335 | -{ | |
| 10336 | - Jim_Reference *refPtr = (void *)val; | |
| 10337 | - | |
| 10338 | - Jim_DecrRefCount(interp, refPtr->objPtr); | |
| 10339 | - if (refPtr->finalizerCmdNamePtr != NULL) { | |
| 10340 | - Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); | |
| 10341 | - } | |
| 10342 | - Jim_Free(val); | |
| 10343 | -} | |
| 10344 | - | |
| 10345 | -static unsigned int JimReferencesHTHashFunction(const void *key) | |
| 10346 | -{ | |
| 10347 | - | |
| 10348 | - const unsigned long *widePtr = key; | |
| 10349 | - unsigned int intValue = (unsigned int)*widePtr; | |
| 10350 | - | |
| 10351 | - return Jim_IntHashFunction(intValue); | |
| 10352 | -} | |
| 10353 | - | |
| 10354 | -static void *JimReferencesHTKeyDup(void *privdata, const void *key) | |
| 10355 | -{ | |
| 10356 | - void *copy = Jim_Alloc(sizeof(unsigned long)); | |
| 10357 | - | |
| 10358 | - JIM_NOTUSED(privdata); | |
| 10359 | - | |
| 10360 | - memcpy(copy, key, sizeof(unsigned long)); | |
| 10361 | - return copy; | |
| 10362 | -} | |
| 10363 | - | |
| 10364 | -static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2) | |
| 10365 | -{ | |
| 10366 | - JIM_NOTUSED(privdata); | |
| 10367 | - | |
| 10368 | - return memcmp(key1, key2, sizeof(unsigned long)) == 0; | |
| 10369 | -} | |
| 10370 | - | |
| 10371 | -static void JimReferencesHTKeyDestructor(void *privdata, void *key) | |
| 10372 | -{ | |
| 10373 | - JIM_NOTUSED(privdata); | |
| 10374 | - | |
| 10375 | - Jim_Free(key); | |
| 10376 | -} | |
| 10377 | - | |
| 10378 | -static const Jim_HashTableType JimReferencesHashTableType = { | |
| 10379 | - JimReferencesHTHashFunction, | |
| 10380 | - JimReferencesHTKeyDup, | |
| 10381 | - NULL, | |
| 10382 | - JimReferencesHTKeyCompare, | |
| 10383 | - JimReferencesHTKeyDestructor, | |
| 10384 | - JimReferencesHTValDestructor | |
| 10385 | -}; | |
| 10386 | - | |
| 10387 | - | |
| 10388 | - | |
| 10389 | -#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN) | |
| 10390 | - | |
| 10391 | -static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id) | |
| 10392 | -{ | |
| 10393 | - const char *fmt = "<reference.<%s>.%020lu>"; | |
| 10394 | - | |
| 10395 | - sprintf(buf, fmt, refPtr->tag, id); | |
| 10396 | - return JIM_REFERENCE_SPACE; | |
| 10397 | -} | |
| 10398 | - | |
| 10399 | -static void UpdateStringOfReference(struct Jim_Obj *objPtr); | |
| 10400 | - | |
| 10401 | -static const Jim_ObjType referenceObjType = { | |
| 10402 | - "reference", | |
| 10403 | - NULL, | |
| 10404 | - NULL, | |
| 10405 | - UpdateStringOfReference, | |
| 10406 | - JIM_TYPE_REFERENCES, | |
| 10407 | -}; | |
| 10408 | - | |
| 10409 | -static void UpdateStringOfReference(struct Jim_Obj *objPtr) | |
| 10410 | -{ | |
| 10411 | - char buf[JIM_REFERENCE_SPACE + 1]; | |
| 10412 | - | |
| 10413 | - JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id); | |
| 10414 | - JimSetStringBytes(objPtr, buf); | |
| 10415 | -} | |
| 10416 | - | |
| 10417 | -static int isrefchar(int c) | |
| 10418 | -{ | |
| 10419 | - return (c == '_' || isalnum(c)); | |
| 10420 | -} | |
| 10421 | - | |
| 10422 | -static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 10423 | -{ | |
| 10424 | - unsigned long value; | |
| 10425 | - int i, len; | |
| 10426 | - const char *str, *start, *end; | |
| 10427 | - char refId[21]; | |
| 10428 | - Jim_Reference *refPtr; | |
| 10429 | - Jim_HashEntry *he; | |
| 10430 | - char *endptr; | |
| 10431 | - | |
| 10432 | - | |
| 10433 | - str = Jim_GetString(objPtr, &len); | |
| 10434 | - | |
| 10435 | - if (len < JIM_REFERENCE_SPACE) | |
| 10436 | - goto badformat; | |
| 10437 | - | |
| 10438 | - start = str; | |
| 10439 | - end = str + len - 1; | |
| 10440 | - while (*start == ' ') | |
| 10441 | - start++; | |
| 10442 | - while (*end == ' ' && end > start) | |
| 10443 | - end--; | |
| 10444 | - if (end - start + 1 != JIM_REFERENCE_SPACE) | |
| 10445 | - goto badformat; | |
| 10446 | - | |
| 10447 | - if (memcmp(start, "<reference.<", 12) != 0) | |
| 10448 | - goto badformat; | |
| 10449 | - if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>') | |
| 10450 | - goto badformat; | |
| 10451 | - | |
| 10452 | - for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { | |
| 10453 | - if (!isrefchar(start[12 + i])) | |
| 10454 | - goto badformat; | |
| 10455 | - } | |
| 10456 | - | |
| 10457 | - memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20); | |
| 10458 | - refId[20] = '\0'; | |
| 10459 | - | |
| 10460 | - value = strtoul(refId, &endptr, 10); | |
| 10461 | - if (JimCheckConversion(refId, endptr) != JIM_OK) | |
| 10462 | - goto badformat; | |
| 10463 | - | |
| 10464 | - he = Jim_FindHashEntry(&interp->references, &value); | |
| 10465 | - if (he == NULL) { | |
| 10466 | - Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); | |
| 10467 | - return JIM_ERR; | |
| 10468 | - } | |
| 10469 | - refPtr = Jim_GetHashEntryVal(he); | |
| 10470 | - | |
| 10471 | - Jim_FreeIntRep(interp, objPtr); | |
| 10472 | - objPtr->typePtr = &referenceObjType; | |
| 10473 | - objPtr->internalRep.refValue.id = value; | |
| 10474 | - objPtr->internalRep.refValue.refPtr = refPtr; | |
| 10475 | - return JIM_OK; | |
| 10476 | - | |
| 10477 | - badformat: | |
| 10478 | - Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr); | |
| 10479 | - return JIM_ERR; | |
| 10480 | -} | |
| 10481 | - | |
| 10482 | -Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr) | |
| 10483 | -{ | |
| 10484 | - struct Jim_Reference *refPtr; | |
| 10485 | - unsigned long id; | |
| 10486 | - Jim_Obj *refObjPtr; | |
| 10487 | - const char *tag; | |
| 10488 | - int tagLen, i; | |
| 10489 | - | |
| 10490 | - | |
| 10491 | - Jim_CollectIfNeeded(interp); | |
| 10492 | - | |
| 10493 | - refPtr = Jim_Alloc(sizeof(*refPtr)); | |
| 10494 | - refPtr->objPtr = objPtr; | |
| 10495 | - Jim_IncrRefCount(objPtr); | |
| 10496 | - refPtr->finalizerCmdNamePtr = cmdNamePtr; | |
| 10497 | - if (cmdNamePtr) | |
| 10498 | - Jim_IncrRefCount(cmdNamePtr); | |
| 10499 | - id = interp->referenceNextId++; | |
| 10500 | - Jim_AddHashEntry(&interp->references, &id, refPtr); | |
| 10501 | - refObjPtr = Jim_NewObj(interp); | |
| 10502 | - refObjPtr->typePtr = &referenceObjType; | |
| 10503 | - refObjPtr->bytes = NULL; | |
| 10504 | - refObjPtr->internalRep.refValue.id = id; | |
| 10505 | - refObjPtr->internalRep.refValue.refPtr = refPtr; | |
| 10506 | - interp->referenceNextId++; | |
| 10507 | - tag = Jim_GetString(tagPtr, &tagLen); | |
| 10508 | - if (tagLen > JIM_REFERENCE_TAGLEN) | |
| 10509 | - tagLen = JIM_REFERENCE_TAGLEN; | |
| 10510 | - for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { | |
| 10511 | - if (i < tagLen && isrefchar(tag[i])) | |
| 10512 | - refPtr->tag[i] = tag[i]; | |
| 10513 | - else | |
| 10514 | - refPtr->tag[i] = '_'; | |
| 10515 | - } | |
| 10516 | - refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0'; | |
| 10517 | - return refObjPtr; | |
| 10518 | -} | |
| 10519 | - | |
| 10520 | -Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 10521 | -{ | |
| 10522 | - if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR) | |
| 10523 | - return NULL; | |
| 10524 | - return objPtr->internalRep.refValue.refPtr; | |
| 10525 | -} | |
| 10526 | - | |
| 10527 | -int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr) | |
| 10528 | -{ | |
| 10529 | - Jim_Reference *refPtr; | |
| 10530 | - | |
| 10531 | - if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) | |
| 10532 | - return JIM_ERR; | |
| 10533 | - Jim_IncrRefCount(cmdNamePtr); | |
| 10534 | - if (refPtr->finalizerCmdNamePtr) | |
| 10535 | - Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); | |
| 10536 | - refPtr->finalizerCmdNamePtr = cmdNamePtr; | |
| 10537 | - return JIM_OK; | |
| 10538 | -} | |
| 10539 | - | |
| 10540 | -int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr) | |
| 10541 | -{ | |
| 10542 | - Jim_Reference *refPtr; | |
| 10543 | - | |
| 10544 | - if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) | |
| 10545 | - return JIM_ERR; | |
| 10546 | - *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr; | |
| 10547 | - return JIM_OK; | |
| 10548 | -} | |
| 10549 | - | |
| 10550 | - | |
| 10551 | - | |
| 10552 | -static const Jim_HashTableType JimRefMarkHashTableType = { | |
| 10553 | - JimReferencesHTHashFunction, | |
| 10554 | - JimReferencesHTKeyDup, | |
| 10555 | - NULL, | |
| 10556 | - JimReferencesHTKeyCompare, | |
| 10557 | - JimReferencesHTKeyDestructor, | |
| 10558 | - NULL | |
| 10559 | -}; | |
| 10560 | - | |
| 10561 | - | |
| 10562 | -int Jim_Collect(Jim_Interp *interp) | |
| 10563 | -{ | |
| 10564 | - int collected = 0; | |
| 10565 | - return collected; | |
| 10566 | -} | |
| 10567 | - | |
| 10568 | -#define JIM_COLLECT_ID_PERIOD 5000 | |
| 10569 | -#define JIM_COLLECT_TIME_PERIOD 300 | |
| 10570 | - | |
| 10571 | -void Jim_CollectIfNeeded(Jim_Interp *interp) | |
| 10572 | -{ | |
| 10573 | - unsigned long elapsedId; | |
| 10574 | - int elapsedTime; | |
| 10575 | - | |
| 10576 | - elapsedId = interp->referenceNextId - interp->lastCollectId; | |
| 10577 | - elapsedTime = time(NULL) - interp->lastCollectTime; | |
| 10578 | - | |
| 10579 | - | |
| 10580 | - if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) { | |
| 10581 | - Jim_Collect(interp); | |
| 10582 | - } | |
| 10583 | -} | |
| 10584 | -#endif | |
| 10585 | 10404 | |
| 10586 | 10405 | int Jim_IsBigEndian(void) |
| 10587 | 10406 | { |
| 10588 | 10407 | union { |
| 10589 | 10408 | unsigned short s; |
| @@ -10630,11 +10449,11 @@ | ||
| 10630 | 10449 | Jim_IncrRefCount(i->nullScriptObj); |
| 10631 | 10450 | Jim_IncrRefCount(i->errorProc); |
| 10632 | 10451 | Jim_IncrRefCount(i->trueObj); |
| 10633 | 10452 | Jim_IncrRefCount(i->falseObj); |
| 10634 | 10453 | |
| 10635 | - | |
| 10454 | + | |
| 10636 | 10455 | Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); |
| 10637 | 10456 | Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); |
| 10638 | 10457 | |
| 10639 | 10458 | Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim"); |
| 10640 | 10459 | Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); |
| @@ -10652,12 +10471,14 @@ | ||
| 10652 | 10471 | { |
| 10653 | 10472 | Jim_CallFrame *cf, *cfx; |
| 10654 | 10473 | |
| 10655 | 10474 | Jim_Obj *objPtr, *nextObjPtr; |
| 10656 | 10475 | |
| 10657 | - | |
| 10476 | + | |
| 10658 | 10477 | for (cf = i->framePtr; cf; cf = cfx) { |
| 10478 | + | |
| 10479 | + JimInvokeDefer(i, JIM_OK); | |
| 10659 | 10480 | cfx = cf->parent; |
| 10660 | 10481 | JimFreeCallFrame(i, cf, JIM_FCF_FULL); |
| 10661 | 10482 | } |
| 10662 | 10483 | |
| 10663 | 10484 | Jim_DecrRefCount(i, i->emptyObj); |
| @@ -10684,10 +10505,11 @@ | ||
| 10684 | 10505 | |
| 10685 | 10506 | printf("\n-------------------------------------\n"); |
| 10686 | 10507 | printf("Objects still in the free list:\n"); |
| 10687 | 10508 | while (objPtr) { |
| 10688 | 10509 | const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; |
| 10510 | + Jim_String(objPtr); | |
| 10689 | 10511 | |
| 10690 | 10512 | if (objPtr->bytes && strlen(objPtr->bytes) > 20) { |
| 10691 | 10513 | printf("%p (%d) %-10s: '%.20s...'\n", |
| 10692 | 10514 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes); |
| 10693 | 10515 | } |
| @@ -10705,27 +10527,27 @@ | ||
| 10705 | 10527 | printf("-------------------------------------\n\n"); |
| 10706 | 10528 | JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); |
| 10707 | 10529 | } |
| 10708 | 10530 | #endif |
| 10709 | 10531 | |
| 10710 | - | |
| 10532 | + | |
| 10711 | 10533 | objPtr = i->freeList; |
| 10712 | 10534 | while (objPtr) { |
| 10713 | 10535 | nextObjPtr = objPtr->nextObjPtr; |
| 10714 | 10536 | Jim_Free(objPtr); |
| 10715 | 10537 | objPtr = nextObjPtr; |
| 10716 | 10538 | } |
| 10717 | 10539 | |
| 10718 | - | |
| 10540 | + | |
| 10719 | 10541 | for (cf = i->freeFramesList; cf; cf = cfx) { |
| 10720 | 10542 | cfx = cf->next; |
| 10721 | 10543 | if (cf->vars.table) |
| 10722 | 10544 | Jim_FreeHashTable(&cf->vars); |
| 10723 | 10545 | Jim_Free(cf); |
| 10724 | 10546 | } |
| 10725 | 10547 | |
| 10726 | - | |
| 10548 | + | |
| 10727 | 10549 | Jim_Free(i); |
| 10728 | 10550 | } |
| 10729 | 10551 | |
| 10730 | 10552 | Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr) |
| 10731 | 10553 | { |
| @@ -10746,25 +10568,25 @@ | ||
| 10746 | 10568 | else { |
| 10747 | 10569 | if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) { |
| 10748 | 10570 | level = -1; |
| 10749 | 10571 | } |
| 10750 | 10572 | else { |
| 10751 | - | |
| 10573 | + | |
| 10752 | 10574 | level = interp->framePtr->level - level; |
| 10753 | 10575 | } |
| 10754 | 10576 | } |
| 10755 | 10577 | } |
| 10756 | 10578 | else { |
| 10757 | - str = "1"; | |
| 10579 | + str = "1"; | |
| 10758 | 10580 | level = interp->framePtr->level - 1; |
| 10759 | 10581 | } |
| 10760 | 10582 | |
| 10761 | 10583 | if (level == 0) { |
| 10762 | 10584 | return interp->topFramePtr; |
| 10763 | 10585 | } |
| 10764 | 10586 | if (level > 0) { |
| 10765 | - | |
| 10587 | + | |
| 10766 | 10588 | for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { |
| 10767 | 10589 | if (framePtr->level == level) { |
| 10768 | 10590 | return framePtr; |
| 10769 | 10591 | } |
| 10770 | 10592 | } |
| @@ -10779,19 +10601,19 @@ | ||
| 10779 | 10601 | long level; |
| 10780 | 10602 | Jim_CallFrame *framePtr; |
| 10781 | 10603 | |
| 10782 | 10604 | if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { |
| 10783 | 10605 | if (level <= 0) { |
| 10784 | - | |
| 10606 | + | |
| 10785 | 10607 | level = interp->framePtr->level + level; |
| 10786 | 10608 | } |
| 10787 | 10609 | |
| 10788 | 10610 | if (level == 0) { |
| 10789 | 10611 | return interp->topFramePtr; |
| 10790 | 10612 | } |
| 10791 | 10613 | |
| 10792 | - | |
| 10614 | + | |
| 10793 | 10615 | for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { |
| 10794 | 10616 | if (framePtr->level == level) { |
| 10795 | 10617 | return framePtr; |
| 10796 | 10618 | } |
| 10797 | 10619 | } |
| @@ -10810,11 +10632,11 @@ | ||
| 10810 | 10632 | |
| 10811 | 10633 | static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) |
| 10812 | 10634 | { |
| 10813 | 10635 | int len; |
| 10814 | 10636 | |
| 10815 | - | |
| 10637 | + | |
| 10816 | 10638 | Jim_IncrRefCount(stackTraceObj); |
| 10817 | 10639 | Jim_DecrRefCount(interp, interp->stackTrace); |
| 10818 | 10640 | interp->stackTrace = stackTraceObj; |
| 10819 | 10641 | interp->errorFlag = 1; |
| 10820 | 10642 | |
| @@ -10831,32 +10653,32 @@ | ||
| 10831 | 10653 | { |
| 10832 | 10654 | if (strcmp(procname, "unknown") == 0) { |
| 10833 | 10655 | procname = ""; |
| 10834 | 10656 | } |
| 10835 | 10657 | if (!*procname && !Jim_Length(fileNameObj)) { |
| 10836 | - | |
| 10658 | + | |
| 10837 | 10659 | return; |
| 10838 | 10660 | } |
| 10839 | 10661 | |
| 10840 | 10662 | if (Jim_IsShared(interp->stackTrace)) { |
| 10841 | 10663 | Jim_DecrRefCount(interp, interp->stackTrace); |
| 10842 | 10664 | interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); |
| 10843 | 10665 | Jim_IncrRefCount(interp->stackTrace); |
| 10844 | 10666 | } |
| 10845 | 10667 | |
| 10846 | - | |
| 10668 | + | |
| 10847 | 10669 | if (!*procname && Jim_Length(fileNameObj)) { |
| 10848 | - | |
| 10670 | + | |
| 10849 | 10671 | int len = Jim_ListLength(interp, interp->stackTrace); |
| 10850 | 10672 | |
| 10851 | 10673 | if (len >= 3) { |
| 10852 | 10674 | Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3); |
| 10853 | 10675 | if (Jim_Length(objPtr)) { |
| 10854 | - | |
| 10676 | + | |
| 10855 | 10677 | objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2); |
| 10856 | 10678 | if (Jim_Length(objPtr) == 0) { |
| 10857 | - | |
| 10679 | + | |
| 10858 | 10680 | ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); |
| 10859 | 10681 | ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); |
| 10860 | 10682 | return; |
| 10861 | 10683 | } |
| 10862 | 10684 | } |
| @@ -10958,18 +10780,18 @@ | ||
| 10958 | 10780 | { |
| 10959 | 10781 | jim_wide wideValue; |
| 10960 | 10782 | const char *str; |
| 10961 | 10783 | |
| 10962 | 10784 | if (objPtr->typePtr == &coercedDoubleObjType) { |
| 10963 | - | |
| 10785 | + | |
| 10964 | 10786 | objPtr->typePtr = &intObjType; |
| 10965 | 10787 | return JIM_OK; |
| 10966 | 10788 | } |
| 10967 | 10789 | |
| 10968 | - | |
| 10790 | + | |
| 10969 | 10791 | str = Jim_String(objPtr); |
| 10970 | - | |
| 10792 | + | |
| 10971 | 10793 | if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) { |
| 10972 | 10794 | if (flags & JIM_ERRMSG) { |
| 10973 | 10795 | Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr); |
| 10974 | 10796 | } |
| 10975 | 10797 | return JIM_ERR; |
| @@ -10976,11 +10798,11 @@ | ||
| 10976 | 10798 | } |
| 10977 | 10799 | if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) { |
| 10978 | 10800 | Jim_SetResultString(interp, "Integer value too big to be represented", -1); |
| 10979 | 10801 | return JIM_ERR; |
| 10980 | 10802 | } |
| 10981 | - | |
| 10803 | + | |
| 10982 | 10804 | Jim_FreeIntRep(interp, objPtr); |
| 10983 | 10805 | objPtr->typePtr = &intObjType; |
| 10984 | 10806 | objPtr->internalRep.wideValue = wideValue; |
| 10985 | 10807 | return JIM_OK; |
| 10986 | 10808 | } |
| @@ -11075,17 +10897,17 @@ | ||
| 11075 | 10897 | { |
| 11076 | 10898 | char buf[JIM_DOUBLE_SPACE + 1]; |
| 11077 | 10899 | int i; |
| 11078 | 10900 | int len = sprintf(buf, "%.12g", value); |
| 11079 | 10901 | |
| 11080 | - | |
| 10902 | + | |
| 11081 | 10903 | for (i = 0; i < len; i++) { |
| 11082 | 10904 | if (buf[i] == '.' || buf[i] == 'e') { |
| 11083 | 10905 | #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) |
| 11084 | 10906 | char *e = strchr(buf, 'e'); |
| 11085 | 10907 | if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { |
| 11086 | - | |
| 10908 | + | |
| 11087 | 10909 | e += 2; |
| 11088 | 10910 | memmove(e, e + 1, len - (e - buf)); |
| 11089 | 10911 | } |
| 11090 | 10912 | #endif |
| 11091 | 10913 | break; |
| @@ -11104,41 +10926,40 @@ | ||
| 11104 | 10926 | { |
| 11105 | 10927 | double doubleValue; |
| 11106 | 10928 | jim_wide wideValue; |
| 11107 | 10929 | const char *str; |
| 11108 | 10930 | |
| 11109 | - str = Jim_String(objPtr); | |
| 11110 | - | |
| 11111 | 10931 | #ifdef HAVE_LONG_LONG |
| 11112 | - | |
| 10932 | + | |
| 11113 | 10933 | #define MIN_INT_IN_DOUBLE -(1LL << 53) |
| 11114 | 10934 | #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) |
| 11115 | 10935 | |
| 11116 | 10936 | if (objPtr->typePtr == &intObjType |
| 11117 | 10937 | && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE |
| 11118 | 10938 | && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { |
| 11119 | 10939 | |
| 11120 | - | |
| 10940 | + | |
| 11121 | 10941 | objPtr->typePtr = &coercedDoubleObjType; |
| 11122 | 10942 | return JIM_OK; |
| 11123 | 10943 | } |
| 11124 | - else | |
| 11125 | 10944 | #endif |
| 10945 | + str = Jim_String(objPtr); | |
| 10946 | + | |
| 11126 | 10947 | if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { |
| 11127 | - | |
| 10948 | + | |
| 11128 | 10949 | Jim_FreeIntRep(interp, objPtr); |
| 11129 | 10950 | objPtr->typePtr = &coercedDoubleObjType; |
| 11130 | 10951 | objPtr->internalRep.wideValue = wideValue; |
| 11131 | 10952 | return JIM_OK; |
| 11132 | 10953 | } |
| 11133 | 10954 | else { |
| 11134 | - | |
| 10955 | + | |
| 11135 | 10956 | if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) { |
| 11136 | 10957 | Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr); |
| 11137 | 10958 | return JIM_ERR; |
| 11138 | 10959 | } |
| 11139 | - | |
| 10960 | + | |
| 11140 | 10961 | Jim_FreeIntRep(interp, objPtr); |
| 11141 | 10962 | } |
| 11142 | 10963 | objPtr->typePtr = &doubleObjType; |
| 11143 | 10964 | objPtr->internalRep.doubleValue = doubleValue; |
| 11144 | 10965 | return JIM_OK; |
| @@ -11170,10 +10991,50 @@ | ||
| 11170 | 10991 | objPtr->typePtr = &doubleObjType; |
| 11171 | 10992 | objPtr->bytes = NULL; |
| 11172 | 10993 | objPtr->internalRep.doubleValue = doubleValue; |
| 11173 | 10994 | return objPtr; |
| 11174 | 10995 | } |
| 10996 | + | |
| 10997 | +static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); | |
| 10998 | + | |
| 10999 | +int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int * booleanPtr) | |
| 11000 | +{ | |
| 11001 | + if (objPtr->typePtr != &intObjType && SetBooleanFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR) | |
| 11002 | + return JIM_ERR; | |
| 11003 | + *booleanPtr = (int) JimWideValue(objPtr); | |
| 11004 | + return JIM_OK; | |
| 11005 | +} | |
| 11006 | + | |
| 11007 | +static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) | |
| 11008 | +{ | |
| 11009 | + static const char * const falses[] = { | |
| 11010 | + "0", "false", "no", "off", NULL | |
| 11011 | + }; | |
| 11012 | + static const char * const trues[] = { | |
| 11013 | + "1", "true", "yes", "on", NULL | |
| 11014 | + }; | |
| 11015 | + | |
| 11016 | + int boolean; | |
| 11017 | + | |
| 11018 | + int index; | |
| 11019 | + if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) { | |
| 11020 | + boolean = 0; | |
| 11021 | + } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) { | |
| 11022 | + boolean = 1; | |
| 11023 | + } else { | |
| 11024 | + if (flags & JIM_ERRMSG) { | |
| 11025 | + Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr); | |
| 11026 | + } | |
| 11027 | + return JIM_ERR; | |
| 11028 | + } | |
| 11029 | + | |
| 11030 | + | |
| 11031 | + Jim_FreeIntRep(interp, objPtr); | |
| 11032 | + objPtr->typePtr = &intObjType; | |
| 11033 | + objPtr->internalRep.wideValue = boolean; | |
| 11034 | + return JIM_OK; | |
| 11035 | +} | |
| 11175 | 11036 | |
| 11176 | 11037 | static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec); |
| 11177 | 11038 | static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); |
| 11178 | 11039 | static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 11179 | 11040 | static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| @@ -11221,11 +11082,11 @@ | ||
| 11221 | 11082 | #define JIM_ELESTR_QUOTE 2 |
| 11222 | 11083 | static unsigned char ListElementQuotingType(const char *s, int len) |
| 11223 | 11084 | { |
| 11224 | 11085 | int i, level, blevel, trySimple = 1; |
| 11225 | 11086 | |
| 11226 | - | |
| 11087 | + | |
| 11227 | 11088 | if (len == 0) |
| 11228 | 11089 | return JIM_ELESTR_BRACE; |
| 11229 | 11090 | if (s[0] == '"' || s[0] == '{') { |
| 11230 | 11091 | trySimple = 0; |
| 11231 | 11092 | goto testbrace; |
| @@ -11243,20 +11104,20 @@ | ||
| 11243 | 11104 | case '\n': |
| 11244 | 11105 | case '\t': |
| 11245 | 11106 | case '\f': |
| 11246 | 11107 | case '\v': |
| 11247 | 11108 | trySimple = 0; |
| 11248 | - | |
| 11109 | + | |
| 11249 | 11110 | case '{': |
| 11250 | 11111 | case '}': |
| 11251 | 11112 | goto testbrace; |
| 11252 | 11113 | } |
| 11253 | 11114 | } |
| 11254 | 11115 | return JIM_ELESTR_SIMPLE; |
| 11255 | 11116 | |
| 11256 | 11117 | testbrace: |
| 11257 | - | |
| 11118 | + | |
| 11258 | 11119 | if (s[len - 1] == '\\') |
| 11259 | 11120 | return JIM_ELESTR_QUOTE; |
| 11260 | 11121 | level = 0; |
| 11261 | 11122 | blevel = 0; |
| 11262 | 11123 | for (i = 0; i < len; i++) { |
| @@ -11372,11 +11233,11 @@ | ||
| 11372 | 11233 | int i, bufLen, realLength; |
| 11373 | 11234 | const char *strRep; |
| 11374 | 11235 | char *p; |
| 11375 | 11236 | unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN]; |
| 11376 | 11237 | |
| 11377 | - | |
| 11238 | + | |
| 11378 | 11239 | if (objc > STATIC_QUOTING_LEN) { |
| 11379 | 11240 | quotingType = Jim_Alloc(objc); |
| 11380 | 11241 | } |
| 11381 | 11242 | else { |
| 11382 | 11243 | quotingType = staticQuoting; |
| @@ -11391,25 +11252,25 @@ | ||
| 11391 | 11252 | case JIM_ELESTR_SIMPLE: |
| 11392 | 11253 | if (i != 0 || strRep[0] != '#') { |
| 11393 | 11254 | bufLen += len; |
| 11394 | 11255 | break; |
| 11395 | 11256 | } |
| 11396 | - | |
| 11257 | + | |
| 11397 | 11258 | quotingType[i] = JIM_ELESTR_BRACE; |
| 11398 | - | |
| 11259 | + | |
| 11399 | 11260 | case JIM_ELESTR_BRACE: |
| 11400 | 11261 | bufLen += len + 2; |
| 11401 | 11262 | break; |
| 11402 | 11263 | case JIM_ELESTR_QUOTE: |
| 11403 | 11264 | bufLen += len * 2; |
| 11404 | 11265 | break; |
| 11405 | 11266 | } |
| 11406 | - bufLen++; | |
| 11267 | + bufLen++; | |
| 11407 | 11268 | } |
| 11408 | 11269 | bufLen++; |
| 11409 | 11270 | |
| 11410 | - | |
| 11271 | + | |
| 11411 | 11272 | p = objPtr->bytes = Jim_Alloc(bufLen + 1); |
| 11412 | 11273 | realLength = 0; |
| 11413 | 11274 | for (i = 0; i < objc; i++) { |
| 11414 | 11275 | int len, qlen; |
| 11415 | 11276 | |
| @@ -11436,17 +11297,17 @@ | ||
| 11436 | 11297 | qlen = BackslashQuoteString(strRep, len, p); |
| 11437 | 11298 | p += qlen; |
| 11438 | 11299 | realLength += qlen; |
| 11439 | 11300 | break; |
| 11440 | 11301 | } |
| 11441 | - | |
| 11302 | + | |
| 11442 | 11303 | if (i + 1 != objc) { |
| 11443 | 11304 | *p++ = ' '; |
| 11444 | 11305 | realLength++; |
| 11445 | 11306 | } |
| 11446 | 11307 | } |
| 11447 | - *p = '\0'; | |
| 11308 | + *p = '\0'; | |
| 11448 | 11309 | objPtr->length = realLength; |
| 11449 | 11310 | |
| 11450 | 11311 | if (quotingType != staticQuoting) { |
| 11451 | 11312 | Jim_Free(quotingType); |
| 11452 | 11313 | } |
| @@ -11477,21 +11338,21 @@ | ||
| 11477 | 11338 | listObjPtrPtr = JimDictPairs(objPtr, &len); |
| 11478 | 11339 | for (i = 0; i < len; i++) { |
| 11479 | 11340 | Jim_IncrRefCount(listObjPtrPtr[i]); |
| 11480 | 11341 | } |
| 11481 | 11342 | |
| 11482 | - | |
| 11343 | + | |
| 11483 | 11344 | Jim_FreeIntRep(interp, objPtr); |
| 11484 | 11345 | objPtr->typePtr = &listObjType; |
| 11485 | 11346 | objPtr->internalRep.listValue.len = len; |
| 11486 | 11347 | objPtr->internalRep.listValue.maxLen = len; |
| 11487 | 11348 | objPtr->internalRep.listValue.ele = listObjPtrPtr; |
| 11488 | 11349 | |
| 11489 | 11350 | return JIM_OK; |
| 11490 | 11351 | } |
| 11491 | 11352 | |
| 11492 | - | |
| 11353 | + | |
| 11493 | 11354 | if (objPtr->typePtr == &sourceObjType) { |
| 11494 | 11355 | fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 11495 | 11356 | linenr = objPtr->internalRep.sourceValue.lineNumber; |
| 11496 | 11357 | } |
| 11497 | 11358 | else { |
| @@ -11498,20 +11359,20 @@ | ||
| 11498 | 11359 | fileNameObj = interp->emptyObj; |
| 11499 | 11360 | linenr = 1; |
| 11500 | 11361 | } |
| 11501 | 11362 | Jim_IncrRefCount(fileNameObj); |
| 11502 | 11363 | |
| 11503 | - | |
| 11364 | + | |
| 11504 | 11365 | str = Jim_GetString(objPtr, &strLen); |
| 11505 | 11366 | |
| 11506 | 11367 | Jim_FreeIntRep(interp, objPtr); |
| 11507 | 11368 | objPtr->typePtr = &listObjType; |
| 11508 | 11369 | objPtr->internalRep.listValue.len = 0; |
| 11509 | 11370 | objPtr->internalRep.listValue.maxLen = 0; |
| 11510 | 11371 | objPtr->internalRep.listValue.ele = NULL; |
| 11511 | 11372 | |
| 11512 | - | |
| 11373 | + | |
| 11513 | 11374 | if (strLen) { |
| 11514 | 11375 | JimParserInit(&parser, str, strLen, linenr); |
| 11515 | 11376 | while (!parser.eof) { |
| 11516 | 11377 | Jim_Obj *elementPtr; |
| 11517 | 11378 | |
| @@ -11641,11 +11502,11 @@ | ||
| 11641 | 11502 | Jim_Obj *compare_script; |
| 11642 | 11503 | int rc; |
| 11643 | 11504 | |
| 11644 | 11505 | jim_wide ret = 0; |
| 11645 | 11506 | |
| 11646 | - | |
| 11507 | + | |
| 11647 | 11508 | compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command); |
| 11648 | 11509 | Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj); |
| 11649 | 11510 | Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj); |
| 11650 | 11511 | |
| 11651 | 11512 | rc = Jim_EvalObj(sort_info->interp, compare_script); |
| @@ -11663,23 +11524,27 @@ | ||
| 11663 | 11524 | int dst = 0; |
| 11664 | 11525 | Jim_Obj **ele = listObjPtr->internalRep.listValue.ele; |
| 11665 | 11526 | |
| 11666 | 11527 | for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) { |
| 11667 | 11528 | if (comp(&ele[dst], &ele[src]) == 0) { |
| 11668 | - | |
| 11529 | + | |
| 11669 | 11530 | Jim_DecrRefCount(sort_info->interp, ele[dst]); |
| 11670 | 11531 | } |
| 11671 | 11532 | else { |
| 11672 | - | |
| 11533 | + | |
| 11673 | 11534 | dst++; |
| 11674 | 11535 | } |
| 11675 | 11536 | ele[dst] = ele[src]; |
| 11676 | 11537 | } |
| 11677 | - | |
| 11678 | - ele[++dst] = ele[src]; | |
| 11679 | 11538 | |
| 11680 | - | |
| 11539 | + | |
| 11540 | + dst++; | |
| 11541 | + if (dst < listObjPtr->internalRep.listValue.len) { | |
| 11542 | + ele[dst] = ele[src]; | |
| 11543 | + } | |
| 11544 | + | |
| 11545 | + | |
| 11681 | 11546 | listObjPtr->internalRep.listValue.len = dst; |
| 11682 | 11547 | } |
| 11683 | 11548 | |
| 11684 | 11549 | |
| 11685 | 11550 | static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
| @@ -11693,11 +11558,11 @@ | ||
| 11693 | 11558 | int rc; |
| 11694 | 11559 | |
| 11695 | 11560 | JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); |
| 11696 | 11561 | SetListFromAny(interp, listObjPtr); |
| 11697 | 11562 | |
| 11698 | - | |
| 11563 | + | |
| 11699 | 11564 | prev_info = sort_info; |
| 11700 | 11565 | sort_info = info; |
| 11701 | 11566 | |
| 11702 | 11567 | vector = listObjPtr->internalRep.listValue.ele; |
| 11703 | 11568 | len = listObjPtr->internalRep.listValue.len; |
| @@ -11716,17 +11581,17 @@ | ||
| 11716 | 11581 | break; |
| 11717 | 11582 | case JIM_LSORT_COMMAND: |
| 11718 | 11583 | fn = ListSortCommand; |
| 11719 | 11584 | break; |
| 11720 | 11585 | default: |
| 11721 | - fn = NULL; | |
| 11586 | + fn = NULL; | |
| 11722 | 11587 | JimPanic((1, "ListSort called with invalid sort type")); |
| 11723 | - return -1; | |
| 11588 | + return -1; | |
| 11724 | 11589 | } |
| 11725 | 11590 | |
| 11726 | 11591 | if (info->indexed) { |
| 11727 | - | |
| 11592 | + | |
| 11728 | 11593 | info->subfn = fn; |
| 11729 | 11594 | fn = ListSortIndexHelper; |
| 11730 | 11595 | } |
| 11731 | 11596 | |
| 11732 | 11597 | if ((rc = setjmp(info->jmpbuf)) == 0) { |
| @@ -11750,11 +11615,11 @@ | ||
| 11750 | 11615 | int i; |
| 11751 | 11616 | Jim_Obj **point; |
| 11752 | 11617 | |
| 11753 | 11618 | if (requiredLen > listPtr->internalRep.listValue.maxLen) { |
| 11754 | 11619 | if (requiredLen < 2) { |
| 11755 | - | |
| 11620 | + | |
| 11756 | 11621 | requiredLen = 4; |
| 11757 | 11622 | } |
| 11758 | 11623 | else { |
| 11759 | 11624 | requiredLen *= 2; |
| 11760 | 11625 | } |
| @@ -11936,34 +11801,34 @@ | ||
| 11936 | 11801 | for (i = 0; i < objc; i++) |
| 11937 | 11802 | ListAppendList(objPtr, objv[i]); |
| 11938 | 11803 | return objPtr; |
| 11939 | 11804 | } |
| 11940 | 11805 | else { |
| 11941 | - | |
| 11806 | + | |
| 11942 | 11807 | int len = 0, objLen; |
| 11943 | 11808 | char *bytes, *p; |
| 11944 | 11809 | |
| 11945 | - | |
| 11810 | + | |
| 11946 | 11811 | for (i = 0; i < objc; i++) { |
| 11947 | 11812 | len += Jim_Length(objv[i]); |
| 11948 | 11813 | } |
| 11949 | 11814 | if (objc) |
| 11950 | 11815 | len += objc - 1; |
| 11951 | - | |
| 11816 | + | |
| 11952 | 11817 | p = bytes = Jim_Alloc(len + 1); |
| 11953 | 11818 | for (i = 0; i < objc; i++) { |
| 11954 | 11819 | const char *s = Jim_GetString(objv[i], &objLen); |
| 11955 | 11820 | |
| 11956 | - | |
| 11821 | + | |
| 11957 | 11822 | while (objLen && isspace(UCHAR(*s))) { |
| 11958 | 11823 | s++; |
| 11959 | 11824 | objLen--; |
| 11960 | 11825 | len--; |
| 11961 | 11826 | } |
| 11962 | - | |
| 11827 | + | |
| 11963 | 11828 | while (objLen && isspace(UCHAR(s[objLen - 1]))) { |
| 11964 | - | |
| 11829 | + | |
| 11965 | 11830 | if (objLen > 1 && s[objLen - 2] == '\\') { |
| 11966 | 11831 | break; |
| 11967 | 11832 | } |
| 11968 | 11833 | objLen--; |
| 11969 | 11834 | len--; |
| @@ -11990,11 +11855,11 @@ | ||
| 11990 | 11855 | int len, rangeLen; |
| 11991 | 11856 | |
| 11992 | 11857 | if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || |
| 11993 | 11858 | Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) |
| 11994 | 11859 | return NULL; |
| 11995 | - len = Jim_ListLength(interp, listObjPtr); | |
| 11860 | + len = Jim_ListLength(interp, listObjPtr); | |
| 11996 | 11861 | first = JimRelToAbsIndex(len, first); |
| 11997 | 11862 | last = JimRelToAbsIndex(len, last); |
| 11998 | 11863 | JimRelToAbsRange(len, &first, &last, &rangeLen); |
| 11999 | 11864 | if (first == 0 && last == len) { |
| 12000 | 11865 | return listObjPtr; |
| @@ -12030,16 +11895,16 @@ | ||
| 12030 | 11895 | { |
| 12031 | 11896 | Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 12032 | 11897 | } |
| 12033 | 11898 | |
| 12034 | 11899 | static const Jim_HashTableType JimDictHashTableType = { |
| 12035 | - JimObjectHTHashFunction, | |
| 12036 | - JimObjectHTKeyValDup, | |
| 12037 | - JimObjectHTKeyValDup, | |
| 12038 | - JimObjectHTKeyCompare, | |
| 12039 | - JimObjectHTKeyValDestructor, | |
| 12040 | - JimObjectHTKeyValDestructor | |
| 11900 | + JimObjectHTHashFunction, | |
| 11901 | + JimObjectHTKeyValDup, | |
| 11902 | + JimObjectHTKeyValDup, | |
| 11903 | + JimObjectHTKeyCompare, | |
| 11904 | + JimObjectHTKeyValDestructor, | |
| 11905 | + JimObjectHTKeyValDestructor | |
| 12041 | 11906 | }; |
| 12042 | 11907 | |
| 12043 | 11908 | static const Jim_ObjType dictObjType = { |
| 12044 | 11909 | "dict", |
| 12045 | 11910 | FreeDictInternalRep, |
| @@ -12060,17 +11925,17 @@ | ||
| 12060 | 11925 | { |
| 12061 | 11926 | Jim_HashTable *ht, *dupHt; |
| 12062 | 11927 | Jim_HashTableIterator htiter; |
| 12063 | 11928 | Jim_HashEntry *he; |
| 12064 | 11929 | |
| 12065 | - | |
| 11930 | + | |
| 12066 | 11931 | ht = srcPtr->internalRep.ptr; |
| 12067 | 11932 | dupHt = Jim_Alloc(sizeof(*dupHt)); |
| 12068 | 11933 | Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); |
| 12069 | 11934 | if (ht->size != 0) |
| 12070 | 11935 | Jim_ExpandHashTable(dupHt, ht->size); |
| 12071 | - | |
| 11936 | + | |
| 12072 | 11937 | JimInitHashTableIterator(ht, &htiter); |
| 12073 | 11938 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 12074 | 11939 | Jim_AddHashEntry(dupHt, he->key, he->u.val); |
| 12075 | 11940 | } |
| 12076 | 11941 | |
| @@ -12086,11 +11951,11 @@ | ||
| 12086 | 11951 | Jim_Obj **objv; |
| 12087 | 11952 | int i; |
| 12088 | 11953 | |
| 12089 | 11954 | ht = dictPtr->internalRep.ptr; |
| 12090 | 11955 | |
| 12091 | - | |
| 11956 | + | |
| 12092 | 11957 | objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 12093 | 11958 | JimInitHashTableIterator(ht, &htiter); |
| 12094 | 11959 | i = 0; |
| 12095 | 11960 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 12096 | 11961 | objv[i++] = Jim_GetHashEntryKey(he); |
| @@ -12100,15 +11965,15 @@ | ||
| 12100 | 11965 | return objv; |
| 12101 | 11966 | } |
| 12102 | 11967 | |
| 12103 | 11968 | static void UpdateStringOfDict(struct Jim_Obj *objPtr) |
| 12104 | 11969 | { |
| 12105 | - | |
| 11970 | + | |
| 12106 | 11971 | int len; |
| 12107 | 11972 | Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 12108 | 11973 | |
| 12109 | - | |
| 11974 | + | |
| 12110 | 11975 | JimMakeListStringRep(objPtr, objv, len); |
| 12111 | 11976 | |
| 12112 | 11977 | Jim_Free(objv); |
| 12113 | 11978 | } |
| 12114 | 11979 | |
| @@ -12122,18 +11987,18 @@ | ||
| 12122 | 11987 | |
| 12123 | 11988 | if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { |
| 12124 | 11989 | Jim_String(objPtr); |
| 12125 | 11990 | } |
| 12126 | 11991 | |
| 12127 | - | |
| 11992 | + | |
| 12128 | 11993 | listlen = Jim_ListLength(interp, objPtr); |
| 12129 | 11994 | if (listlen % 2) { |
| 12130 | 11995 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| 12131 | 11996 | return JIM_ERR; |
| 12132 | 11997 | } |
| 12133 | 11998 | else { |
| 12134 | - | |
| 11999 | + | |
| 12135 | 12000 | Jim_HashTable *ht; |
| 12136 | 12001 | int i; |
| 12137 | 12002 | |
| 12138 | 12003 | ht = Jim_Alloc(sizeof(*ht)); |
| 12139 | 12004 | Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| @@ -12158,11 +12023,11 @@ | ||
| 12158 | 12023 | static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 12159 | 12024 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 12160 | 12025 | { |
| 12161 | 12026 | Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 12162 | 12027 | |
| 12163 | - if (valueObjPtr == NULL) { | |
| 12028 | + if (valueObjPtr == NULL) { | |
| 12164 | 12029 | return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 12165 | 12030 | } |
| 12166 | 12031 | Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); |
| 12167 | 12032 | return JIM_OK; |
| 12168 | 12033 | } |
| @@ -12209,12 +12074,14 @@ | ||
| 12209 | 12074 | if (flags & JIM_ERRMSG) { |
| 12210 | 12075 | Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr); |
| 12211 | 12076 | } |
| 12212 | 12077 | return JIM_ERR; |
| 12213 | 12078 | } |
| 12214 | - *objPtrPtr = he->u.val; | |
| 12215 | - return JIM_OK; | |
| 12079 | + else { | |
| 12080 | + *objPtrPtr = Jim_GetHashEntryVal(he); | |
| 12081 | + return JIM_OK; | |
| 12082 | + } | |
| 12216 | 12083 | } |
| 12217 | 12084 | |
| 12218 | 12085 | |
| 12219 | 12086 | int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) |
| 12220 | 12087 | { |
| @@ -12258,11 +12125,11 @@ | ||
| 12258 | 12125 | int shared, i; |
| 12259 | 12126 | |
| 12260 | 12127 | varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags); |
| 12261 | 12128 | if (objPtr == NULL) { |
| 12262 | 12129 | if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) { |
| 12263 | - | |
| 12130 | + | |
| 12264 | 12131 | return JIM_ERR; |
| 12265 | 12132 | } |
| 12266 | 12133 | varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 12267 | 12134 | if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) { |
| 12268 | 12135 | Jim_FreeNewObj(interp, varObjPtr); |
| @@ -12272,26 +12139,26 @@ | ||
| 12272 | 12139 | if ((shared = Jim_IsShared(objPtr))) |
| 12273 | 12140 | varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); |
| 12274 | 12141 | for (i = 0; i < keyc; i++) { |
| 12275 | 12142 | dictObjPtr = objPtr; |
| 12276 | 12143 | |
| 12277 | - | |
| 12144 | + | |
| 12278 | 12145 | if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) { |
| 12279 | 12146 | goto err; |
| 12280 | 12147 | } |
| 12281 | 12148 | |
| 12282 | 12149 | if (i == keyc - 1) { |
| 12283 | - | |
| 12150 | + | |
| 12284 | 12151 | if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) { |
| 12285 | 12152 | if (newObjPtr || (flags & JIM_MUSTEXIST)) { |
| 12286 | 12153 | goto err; |
| 12287 | 12154 | } |
| 12288 | 12155 | } |
| 12289 | 12156 | break; |
| 12290 | 12157 | } |
| 12291 | 12158 | |
| 12292 | - | |
| 12159 | + | |
| 12293 | 12160 | Jim_InvalidateStringRep(dictObjPtr); |
| 12294 | 12161 | if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr, |
| 12295 | 12162 | newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) { |
| 12296 | 12163 | if (Jim_IsShared(objPtr)) { |
| 12297 | 12164 | objPtr = Jim_DuplicateObj(interp, objPtr); |
| @@ -12304,11 +12171,11 @@ | ||
| 12304 | 12171 | } |
| 12305 | 12172 | objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 12306 | 12173 | DictAddElement(interp, dictObjPtr, keyv[i], objPtr); |
| 12307 | 12174 | } |
| 12308 | 12175 | } |
| 12309 | - | |
| 12176 | + | |
| 12310 | 12177 | Jim_InvalidateStringRep(objPtr); |
| 12311 | 12178 | Jim_InvalidateStringRep(varObjPtr); |
| 12312 | 12179 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 12313 | 12180 | goto err; |
| 12314 | 12181 | } |
| @@ -12341,11 +12208,11 @@ | ||
| 12341 | 12208 | char buf[JIM_INTEGER_SPACE + 1]; |
| 12342 | 12209 | if (objPtr->internalRep.intValue >= 0) { |
| 12343 | 12210 | sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 12344 | 12211 | } |
| 12345 | 12212 | else { |
| 12346 | - | |
| 12213 | + | |
| 12347 | 12214 | sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| 12348 | 12215 | } |
| 12349 | 12216 | JimSetStringBytes(objPtr, buf); |
| 12350 | 12217 | } |
| 12351 | 12218 | } |
| @@ -12354,14 +12221,14 @@ | ||
| 12354 | 12221 | { |
| 12355 | 12222 | int idx, end = 0; |
| 12356 | 12223 | const char *str; |
| 12357 | 12224 | char *endptr; |
| 12358 | 12225 | |
| 12359 | - | |
| 12226 | + | |
| 12360 | 12227 | str = Jim_String(objPtr); |
| 12361 | 12228 | |
| 12362 | - | |
| 12229 | + | |
| 12363 | 12230 | if (strncmp(str, "end", 3) == 0) { |
| 12364 | 12231 | end = 1; |
| 12365 | 12232 | str += 3; |
| 12366 | 12233 | idx = 0; |
| 12367 | 12234 | } |
| @@ -12372,21 +12239,21 @@ | ||
| 12372 | 12239 | goto badindex; |
| 12373 | 12240 | } |
| 12374 | 12241 | str = endptr; |
| 12375 | 12242 | } |
| 12376 | 12243 | |
| 12377 | - | |
| 12244 | + | |
| 12378 | 12245 | if (*str == '+' || *str == '-') { |
| 12379 | 12246 | int sign = (*str == '+' ? 1 : -1); |
| 12380 | 12247 | |
| 12381 | 12248 | idx += sign * jim_strtol(++str, &endptr); |
| 12382 | 12249 | if (str == endptr || *endptr) { |
| 12383 | 12250 | goto badindex; |
| 12384 | 12251 | } |
| 12385 | 12252 | str = endptr; |
| 12386 | 12253 | } |
| 12387 | - | |
| 12254 | + | |
| 12388 | 12255 | while (isspace(UCHAR(*str))) { |
| 12389 | 12256 | str++; |
| 12390 | 12257 | } |
| 12391 | 12258 | if (*str) { |
| 12392 | 12259 | goto badindex; |
| @@ -12394,19 +12261,19 @@ | ||
| 12394 | 12261 | if (end) { |
| 12395 | 12262 | if (idx > 0) { |
| 12396 | 12263 | idx = INT_MAX; |
| 12397 | 12264 | } |
| 12398 | 12265 | else { |
| 12399 | - | |
| 12266 | + | |
| 12400 | 12267 | idx--; |
| 12401 | 12268 | } |
| 12402 | 12269 | } |
| 12403 | 12270 | else if (idx < 0) { |
| 12404 | 12271 | idx = -INT_MAX; |
| 12405 | 12272 | } |
| 12406 | 12273 | |
| 12407 | - | |
| 12274 | + | |
| 12408 | 12275 | Jim_FreeIntRep(interp, objPtr); |
| 12409 | 12276 | objPtr->typePtr = &indexObjType; |
| 12410 | 12277 | objPtr->internalRep.intValue = idx; |
| 12411 | 12278 | return JIM_OK; |
| 12412 | 12279 | |
| @@ -12416,11 +12283,11 @@ | ||
| 12416 | 12283 | return JIM_ERR; |
| 12417 | 12284 | } |
| 12418 | 12285 | |
| 12419 | 12286 | int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) |
| 12420 | 12287 | { |
| 12421 | - | |
| 12288 | + | |
| 12422 | 12289 | if (objPtr->typePtr == &intObjType) { |
| 12423 | 12290 | jim_wide val = JimWideValue(objPtr); |
| 12424 | 12291 | |
| 12425 | 12292 | if (val < 0) |
| 12426 | 12293 | *indexPtr = -INT_MAX; |
| @@ -12448,11 +12315,11 @@ | ||
| 12448 | 12315 | "exit", |
| 12449 | 12316 | "eval", |
| 12450 | 12317 | NULL |
| 12451 | 12318 | }; |
| 12452 | 12319 | |
| 12453 | -#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) | |
| 12320 | +#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes) - 1) | |
| 12454 | 12321 | |
| 12455 | 12322 | static const Jim_ObjType returnCodeObjType = { |
| 12456 | 12323 | "return-code", |
| 12457 | 12324 | NULL, |
| 12458 | 12325 | NULL, |
| @@ -12473,18 +12340,18 @@ | ||
| 12473 | 12340 | static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12474 | 12341 | { |
| 12475 | 12342 | int returnCode; |
| 12476 | 12343 | jim_wide wideValue; |
| 12477 | 12344 | |
| 12478 | - | |
| 12345 | + | |
| 12479 | 12346 | if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR) |
| 12480 | 12347 | returnCode = (int)wideValue; |
| 12481 | 12348 | else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) { |
| 12482 | 12349 | Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr); |
| 12483 | 12350 | return JIM_ERR; |
| 12484 | 12351 | } |
| 12485 | - | |
| 12352 | + | |
| 12486 | 12353 | Jim_FreeIntRep(interp, objPtr); |
| 12487 | 12354 | objPtr->typePtr = &returnCodeObjType; |
| 12488 | 12355 | objPtr->internalRep.intValue = returnCode; |
| 12489 | 12356 | return JIM_OK; |
| 12490 | 12357 | } |
| @@ -12498,19 +12365,19 @@ | ||
| 12498 | 12365 | } |
| 12499 | 12366 | |
| 12500 | 12367 | static int JimParseExprOperator(struct JimParserCtx *pc); |
| 12501 | 12368 | static int JimParseExprNumber(struct JimParserCtx *pc); |
| 12502 | 12369 | static int JimParseExprIrrational(struct JimParserCtx *pc); |
| 12503 | - | |
| 12504 | - | |
| 12370 | +static int JimParseExprBoolean(struct JimParserCtx *pc); | |
| 12505 | 12371 | |
| 12506 | 12372 | |
| 12507 | 12373 | enum |
| 12508 | 12374 | { |
| 12509 | - | |
| 12510 | - | |
| 12511 | - JIM_EXPROP_MUL = JIM_TT_EXPR_OP, | |
| 12375 | + | |
| 12376 | + | |
| 12377 | + | |
| 12378 | + JIM_EXPROP_MUL = JIM_TT_EXPR_OP, | |
| 12512 | 12379 | JIM_EXPROP_DIV, |
| 12513 | 12380 | JIM_EXPROP_MOD, |
| 12514 | 12381 | JIM_EXPROP_SUB, |
| 12515 | 12382 | JIM_EXPROP_ADD, |
| 12516 | 12383 | JIM_EXPROP_LSHIFT, |
| @@ -12521,66 +12388,48 @@ | ||
| 12521 | 12388 | JIM_EXPROP_GT, |
| 12522 | 12389 | JIM_EXPROP_LTE, |
| 12523 | 12390 | JIM_EXPROP_GTE, |
| 12524 | 12391 | JIM_EXPROP_NUMEQ, |
| 12525 | 12392 | JIM_EXPROP_NUMNE, |
| 12526 | - JIM_EXPROP_BITAND, | |
| 12393 | + JIM_EXPROP_BITAND, | |
| 12527 | 12394 | JIM_EXPROP_BITXOR, |
| 12528 | 12395 | JIM_EXPROP_BITOR, |
| 12529 | - | |
| 12530 | - | |
| 12531 | - JIM_EXPROP_LOGICAND, | |
| 12532 | - JIM_EXPROP_LOGICAND_LEFT, | |
| 12533 | - JIM_EXPROP_LOGICAND_RIGHT, | |
| 12534 | - | |
| 12535 | - | |
| 12536 | - JIM_EXPROP_LOGICOR, | |
| 12537 | - JIM_EXPROP_LOGICOR_LEFT, | |
| 12538 | - JIM_EXPROP_LOGICOR_RIGHT, | |
| 12539 | - | |
| 12540 | - | |
| 12541 | - | |
| 12542 | - JIM_EXPROP_TERNARY, | |
| 12543 | - JIM_EXPROP_TERNARY_LEFT, | |
| 12544 | - JIM_EXPROP_TERNARY_RIGHT, | |
| 12545 | - | |
| 12546 | - | |
| 12547 | - JIM_EXPROP_COLON, | |
| 12548 | - JIM_EXPROP_COLON_LEFT, | |
| 12549 | - JIM_EXPROP_COLON_RIGHT, | |
| 12550 | - | |
| 12551 | - JIM_EXPROP_POW, | |
| 12552 | - | |
| 12553 | - | |
| 12554 | - JIM_EXPROP_STREQ, | |
| 12396 | + JIM_EXPROP_LOGICAND, | |
| 12397 | + JIM_EXPROP_LOGICOR, | |
| 12398 | + JIM_EXPROP_TERNARY, | |
| 12399 | + JIM_EXPROP_COLON, | |
| 12400 | + JIM_EXPROP_POW, | |
| 12401 | + | |
| 12402 | + | |
| 12403 | + JIM_EXPROP_STREQ, | |
| 12555 | 12404 | JIM_EXPROP_STRNE, |
| 12556 | 12405 | JIM_EXPROP_STRIN, |
| 12557 | 12406 | JIM_EXPROP_STRNI, |
| 12558 | 12407 | |
| 12559 | 12408 | |
| 12560 | - JIM_EXPROP_NOT, | |
| 12409 | + JIM_EXPROP_NOT, | |
| 12561 | 12410 | JIM_EXPROP_BITNOT, |
| 12562 | 12411 | JIM_EXPROP_UNARYMINUS, |
| 12563 | 12412 | JIM_EXPROP_UNARYPLUS, |
| 12564 | 12413 | |
| 12565 | - | |
| 12566 | - JIM_EXPROP_FUNC_FIRST, | |
| 12567 | - JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST, | |
| 12414 | + | |
| 12415 | + JIM_EXPROP_FUNC_INT, | |
| 12568 | 12416 | JIM_EXPROP_FUNC_WIDE, |
| 12569 | 12417 | JIM_EXPROP_FUNC_ABS, |
| 12570 | 12418 | JIM_EXPROP_FUNC_DOUBLE, |
| 12571 | 12419 | JIM_EXPROP_FUNC_ROUND, |
| 12572 | 12420 | JIM_EXPROP_FUNC_RAND, |
| 12573 | 12421 | JIM_EXPROP_FUNC_SRAND, |
| 12574 | 12422 | |
| 12575 | - | |
| 12576 | - JIM_EXPROP_FUNC_SIN, | |
| 12423 | + | |
| 12424 | + JIM_EXPROP_FUNC_SIN, | |
| 12577 | 12425 | JIM_EXPROP_FUNC_COS, |
| 12578 | 12426 | JIM_EXPROP_FUNC_TAN, |
| 12579 | 12427 | JIM_EXPROP_FUNC_ASIN, |
| 12580 | 12428 | JIM_EXPROP_FUNC_ACOS, |
| 12581 | 12429 | JIM_EXPROP_FUNC_ATAN, |
| 12430 | + JIM_EXPROP_FUNC_ATAN2, | |
| 12582 | 12431 | JIM_EXPROP_FUNC_SINH, |
| 12583 | 12432 | JIM_EXPROP_FUNC_COSH, |
| 12584 | 12433 | JIM_EXPROP_FUNC_TANH, |
| 12585 | 12434 | JIM_EXPROP_FUNC_CEIL, |
| 12586 | 12435 | JIM_EXPROP_FUNC_FLOOR, |
| @@ -12587,52 +12436,52 @@ | ||
| 12587 | 12436 | JIM_EXPROP_FUNC_EXP, |
| 12588 | 12437 | JIM_EXPROP_FUNC_LOG, |
| 12589 | 12438 | JIM_EXPROP_FUNC_LOG10, |
| 12590 | 12439 | JIM_EXPROP_FUNC_SQRT, |
| 12591 | 12440 | JIM_EXPROP_FUNC_POW, |
| 12441 | + JIM_EXPROP_FUNC_HYPOT, | |
| 12442 | + JIM_EXPROP_FUNC_FMOD, | |
| 12592 | 12443 | }; |
| 12593 | 12444 | |
| 12594 | -struct JimExprState | |
| 12595 | -{ | |
| 12596 | - Jim_Obj **stack; | |
| 12597 | - int stacklen; | |
| 12598 | - int opcode; | |
| 12599 | - int skip; | |
| 12445 | +struct JimExprNode { | |
| 12446 | + int type; | |
| 12447 | + struct Jim_Obj *objPtr; | |
| 12448 | + | |
| 12449 | + struct JimExprNode *left; | |
| 12450 | + struct JimExprNode *right; | |
| 12451 | + struct JimExprNode *ternary; | |
| 12600 | 12452 | }; |
| 12601 | 12453 | |
| 12602 | 12454 | |
| 12603 | 12455 | typedef struct Jim_ExprOperator |
| 12604 | 12456 | { |
| 12605 | 12457 | const char *name; |
| 12606 | - int (*funcop) (Jim_Interp *interp, struct JimExprState * e); | |
| 12458 | + int (*funcop) (Jim_Interp *interp, struct JimExprNode *opnode); | |
| 12607 | 12459 | unsigned char precedence; |
| 12608 | 12460 | unsigned char arity; |
| 12609 | - unsigned char lazy; | |
| 12461 | + unsigned char attr; | |
| 12610 | 12462 | unsigned char namelen; |
| 12611 | 12463 | } Jim_ExprOperator; |
| 12612 | 12464 | |
| 12613 | -static void ExprPush(struct JimExprState *e, Jim_Obj *obj) | |
| 12614 | -{ | |
| 12615 | - Jim_IncrRefCount(obj); | |
| 12616 | - e->stack[e->stacklen++] = obj; | |
| 12617 | -} | |
| 12618 | - | |
| 12619 | -static Jim_Obj *ExprPop(struct JimExprState *e) | |
| 12620 | -{ | |
| 12621 | - return e->stack[--e->stacklen]; | |
| 12622 | -} | |
| 12623 | - | |
| 12624 | -static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) | |
| 12465 | +static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr); | |
| 12466 | +static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node); | |
| 12467 | +static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node); | |
| 12468 | + | |
| 12469 | +static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node) | |
| 12625 | 12470 | { |
| 12626 | 12471 | int intresult = 1; |
| 12627 | - int rc = JIM_OK; | |
| 12628 | - Jim_Obj *A = ExprPop(e); | |
| 12472 | + int rc; | |
| 12629 | 12473 | double dA, dC = 0; |
| 12630 | 12474 | jim_wide wA, wC = 0; |
| 12475 | + Jim_Obj *A; | |
| 12476 | + | |
| 12477 | + if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { | |
| 12478 | + return rc; | |
| 12479 | + } | |
| 12631 | 12480 | |
| 12632 | 12481 | if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { |
| 12633 | - switch (e->opcode) { | |
| 12482 | + switch (node->type) { | |
| 12634 | 12483 | case JIM_EXPROP_FUNC_INT: |
| 12635 | 12484 | case JIM_EXPROP_FUNC_WIDE: |
| 12636 | 12485 | case JIM_EXPROP_FUNC_ROUND: |
| 12637 | 12486 | case JIM_EXPROP_UNARYPLUS: |
| 12638 | 12487 | wC = wA; |
| @@ -12653,11 +12502,11 @@ | ||
| 12653 | 12502 | default: |
| 12654 | 12503 | abort(); |
| 12655 | 12504 | } |
| 12656 | 12505 | } |
| 12657 | 12506 | else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { |
| 12658 | - switch (e->opcode) { | |
| 12507 | + switch (node->type) { | |
| 12659 | 12508 | case JIM_EXPROP_FUNC_INT: |
| 12660 | 12509 | case JIM_EXPROP_FUNC_WIDE: |
| 12661 | 12510 | wC = dA; |
| 12662 | 12511 | break; |
| 12663 | 12512 | case JIM_EXPROP_FUNC_ROUND: |
| @@ -12667,11 +12516,15 @@ | ||
| 12667 | 12516 | case JIM_EXPROP_UNARYPLUS: |
| 12668 | 12517 | dC = dA; |
| 12669 | 12518 | intresult = 0; |
| 12670 | 12519 | break; |
| 12671 | 12520 | case JIM_EXPROP_FUNC_ABS: |
| 12521 | +#ifdef JIM_MATH_FUNCTIONS | |
| 12522 | + dC = fabs(dA); | |
| 12523 | +#else | |
| 12672 | 12524 | dC = dA >= 0 ? dA : -dA; |
| 12525 | +#endif | |
| 12673 | 12526 | intresult = 0; |
| 12674 | 12527 | break; |
| 12675 | 12528 | case JIM_EXPROP_UNARYMINUS: |
| 12676 | 12529 | dC = -dA; |
| 12677 | 12530 | intresult = 0; |
| @@ -12684,14 +12537,14 @@ | ||
| 12684 | 12537 | } |
| 12685 | 12538 | } |
| 12686 | 12539 | |
| 12687 | 12540 | if (rc == JIM_OK) { |
| 12688 | 12541 | if (intresult) { |
| 12689 | - ExprPush(e, Jim_NewIntObj(interp, wC)); | |
| 12542 | + Jim_SetResultInt(interp, wC); | |
| 12690 | 12543 | } |
| 12691 | 12544 | else { |
| 12692 | - ExprPush(e, Jim_NewDoubleObj(interp, dC)); | |
| 12545 | + Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); | |
| 12693 | 12546 | } |
| 12694 | 12547 | } |
| 12695 | 12548 | |
| 12696 | 12549 | Jim_DecrRefCount(interp, A); |
| 12697 | 12550 | |
| @@ -12704,24 +12557,29 @@ | ||
| 12704 | 12557 | JimRandomBytes(interp, &x, sizeof(x)); |
| 12705 | 12558 | |
| 12706 | 12559 | return (double)x / (unsigned long)~0; |
| 12707 | 12560 | } |
| 12708 | 12561 | |
| 12709 | -static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e) | |
| 12562 | +static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node) | |
| 12710 | 12563 | { |
| 12711 | - Jim_Obj *A = ExprPop(e); | |
| 12712 | 12564 | jim_wide wA; |
| 12565 | + Jim_Obj *A; | |
| 12566 | + int rc; | |
| 12713 | 12567 | |
| 12714 | - int rc = Jim_GetWide(interp, A, &wA); | |
| 12568 | + if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { | |
| 12569 | + return rc; | |
| 12570 | + } | |
| 12571 | + | |
| 12572 | + rc = Jim_GetWide(interp, A, &wA); | |
| 12715 | 12573 | if (rc == JIM_OK) { |
| 12716 | - switch (e->opcode) { | |
| 12574 | + switch (node->type) { | |
| 12717 | 12575 | case JIM_EXPROP_BITNOT: |
| 12718 | - ExprPush(e, Jim_NewIntObj(interp, ~wA)); | |
| 12576 | + Jim_SetResultInt(interp, ~wA); | |
| 12719 | 12577 | break; |
| 12720 | 12578 | case JIM_EXPROP_FUNC_SRAND: |
| 12721 | 12579 | JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); |
| 12722 | - ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); | |
| 12580 | + Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp))); | |
| 12723 | 12581 | break; |
| 12724 | 12582 | default: |
| 12725 | 12583 | abort(); |
| 12726 | 12584 | } |
| 12727 | 12585 | } |
| @@ -12729,29 +12587,33 @@ | ||
| 12729 | 12587 | Jim_DecrRefCount(interp, A); |
| 12730 | 12588 | |
| 12731 | 12589 | return rc; |
| 12732 | 12590 | } |
| 12733 | 12591 | |
| 12734 | -static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e) | |
| 12592 | +static int JimExprOpNone(Jim_Interp *interp, struct JimExprNode *node) | |
| 12735 | 12593 | { |
| 12736 | - JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); | |
| 12594 | + JimPanic((node->type != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); | |
| 12737 | 12595 | |
| 12738 | - ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); | |
| 12596 | + Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp))); | |
| 12739 | 12597 | |
| 12740 | 12598 | return JIM_OK; |
| 12741 | 12599 | } |
| 12742 | 12600 | |
| 12743 | 12601 | #ifdef JIM_MATH_FUNCTIONS |
| 12744 | -static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e) | |
| 12602 | +static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprNode *node) | |
| 12745 | 12603 | { |
| 12746 | 12604 | int rc; |
| 12747 | - Jim_Obj *A = ExprPop(e); | |
| 12748 | 12605 | double dA, dC; |
| 12606 | + Jim_Obj *A; | |
| 12607 | + | |
| 12608 | + if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { | |
| 12609 | + return rc; | |
| 12610 | + } | |
| 12749 | 12611 | |
| 12750 | 12612 | rc = Jim_GetDouble(interp, A, &dA); |
| 12751 | 12613 | if (rc == JIM_OK) { |
| 12752 | - switch (e->opcode) { | |
| 12614 | + switch (node->type) { | |
| 12753 | 12615 | case JIM_EXPROP_FUNC_SIN: |
| 12754 | 12616 | dC = sin(dA); |
| 12755 | 12617 | break; |
| 12756 | 12618 | case JIM_EXPROP_FUNC_COS: |
| 12757 | 12619 | dC = cos(dA); |
| @@ -12796,33 +12658,42 @@ | ||
| 12796 | 12658 | dC = sqrt(dA); |
| 12797 | 12659 | break; |
| 12798 | 12660 | default: |
| 12799 | 12661 | abort(); |
| 12800 | 12662 | } |
| 12801 | - ExprPush(e, Jim_NewDoubleObj(interp, dC)); | |
| 12663 | + Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); | |
| 12802 | 12664 | } |
| 12803 | 12665 | |
| 12804 | 12666 | Jim_DecrRefCount(interp, A); |
| 12805 | 12667 | |
| 12806 | 12668 | return rc; |
| 12807 | 12669 | } |
| 12808 | 12670 | #endif |
| 12809 | 12671 | |
| 12810 | 12672 | |
| 12811 | -static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e) | |
| 12673 | +static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprNode *node) | |
| 12812 | 12674 | { |
| 12813 | - Jim_Obj *B = ExprPop(e); | |
| 12814 | - Jim_Obj *A = ExprPop(e); | |
| 12815 | 12675 | jim_wide wA, wB; |
| 12816 | - int rc = JIM_ERR; | |
| 12676 | + int rc; | |
| 12677 | + Jim_Obj *A, *B; | |
| 12678 | + | |
| 12679 | + if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { | |
| 12680 | + return rc; | |
| 12681 | + } | |
| 12682 | + if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { | |
| 12683 | + Jim_DecrRefCount(interp, A); | |
| 12684 | + return rc; | |
| 12685 | + } | |
| 12686 | + | |
| 12687 | + rc = JIM_ERR; | |
| 12817 | 12688 | |
| 12818 | 12689 | if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { |
| 12819 | 12690 | jim_wide wC; |
| 12820 | 12691 | |
| 12821 | 12692 | rc = JIM_OK; |
| 12822 | 12693 | |
| 12823 | - switch (e->opcode) { | |
| 12694 | + switch (node->type) { | |
| 12824 | 12695 | case JIM_EXPROP_LSHIFT: |
| 12825 | 12696 | wC = wA << wB; |
| 12826 | 12697 | break; |
| 12827 | 12698 | case JIM_EXPROP_RSHIFT: |
| 12828 | 12699 | wC = wA >> wB; |
| @@ -12859,29 +12730,28 @@ | ||
| 12859 | 12730 | } |
| 12860 | 12731 | } |
| 12861 | 12732 | break; |
| 12862 | 12733 | case JIM_EXPROP_ROTL: |
| 12863 | 12734 | case JIM_EXPROP_ROTR:{ |
| 12864 | - | |
| 12735 | + | |
| 12865 | 12736 | unsigned long uA = (unsigned long)wA; |
| 12866 | 12737 | unsigned long uB = (unsigned long)wB; |
| 12867 | 12738 | const unsigned int S = sizeof(unsigned long) * 8; |
| 12868 | 12739 | |
| 12869 | - | |
| 12740 | + | |
| 12870 | 12741 | uB %= S; |
| 12871 | 12742 | |
| 12872 | - if (e->opcode == JIM_EXPROP_ROTR) { | |
| 12743 | + if (node->type == JIM_EXPROP_ROTR) { | |
| 12873 | 12744 | uB = S - uB; |
| 12874 | 12745 | } |
| 12875 | 12746 | wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); |
| 12876 | 12747 | break; |
| 12877 | 12748 | } |
| 12878 | 12749 | default: |
| 12879 | 12750 | abort(); |
| 12880 | 12751 | } |
| 12881 | - ExprPush(e, Jim_NewIntObj(interp, wC)); | |
| 12882 | - | |
| 12752 | + Jim_SetResultInt(interp, wC); | |
| 12883 | 12753 | } |
| 12884 | 12754 | |
| 12885 | 12755 | Jim_DecrRefCount(interp, A); |
| 12886 | 12756 | Jim_DecrRefCount(interp, B); |
| 12887 | 12757 | |
| @@ -12888,44 +12758,55 @@ | ||
| 12888 | 12758 | return rc; |
| 12889 | 12759 | } |
| 12890 | 12760 | |
| 12891 | 12761 | |
| 12892 | 12762 | |
| 12893 | -static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) | |
| 12763 | +static int JimExprOpBin(Jim_Interp *interp, struct JimExprNode *node) | |
| 12894 | 12764 | { |
| 12895 | - int intresult = 1; | |
| 12896 | 12765 | int rc = JIM_OK; |
| 12897 | 12766 | double dA, dB, dC = 0; |
| 12898 | 12767 | jim_wide wA, wB, wC = 0; |
| 12768 | + Jim_Obj *A, *B; | |
| 12899 | 12769 | |
| 12900 | - Jim_Obj *B = ExprPop(e); | |
| 12901 | - Jim_Obj *A = ExprPop(e); | |
| 12770 | + if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { | |
| 12771 | + return rc; | |
| 12772 | + } | |
| 12773 | + if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { | |
| 12774 | + Jim_DecrRefCount(interp, A); | |
| 12775 | + return rc; | |
| 12776 | + } | |
| 12902 | 12777 | |
| 12903 | 12778 | if ((A->typePtr != &doubleObjType || A->bytes) && |
| 12904 | 12779 | (B->typePtr != &doubleObjType || B->bytes) && |
| 12905 | 12780 | JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { |
| 12906 | 12781 | |
| 12907 | - | |
| 12908 | 12782 | |
| 12909 | - switch (e->opcode) { | |
| 12783 | + | |
| 12784 | + switch (node->type) { | |
| 12910 | 12785 | case JIM_EXPROP_POW: |
| 12911 | 12786 | case JIM_EXPROP_FUNC_POW: |
| 12787 | + if (wA == 0 && wB < 0) { | |
| 12788 | + Jim_SetResultString(interp, "exponentiation of zero by negative power", -1); | |
| 12789 | + rc = JIM_ERR; | |
| 12790 | + goto done; | |
| 12791 | + } | |
| 12912 | 12792 | wC = JimPowWide(wA, wB); |
| 12913 | - break; | |
| 12793 | + goto intresult; | |
| 12914 | 12794 | case JIM_EXPROP_ADD: |
| 12915 | 12795 | wC = wA + wB; |
| 12916 | - break; | |
| 12796 | + goto intresult; | |
| 12917 | 12797 | case JIM_EXPROP_SUB: |
| 12918 | 12798 | wC = wA - wB; |
| 12919 | - break; | |
| 12799 | + goto intresult; | |
| 12920 | 12800 | case JIM_EXPROP_MUL: |
| 12921 | 12801 | wC = wA * wB; |
| 12922 | - break; | |
| 12802 | + goto intresult; | |
| 12923 | 12803 | case JIM_EXPROP_DIV: |
| 12924 | 12804 | if (wB == 0) { |
| 12925 | 12805 | Jim_SetResultString(interp, "Division by zero", -1); |
| 12926 | 12806 | rc = JIM_ERR; |
| 12807 | + goto done; | |
| 12927 | 12808 | } |
| 12928 | 12809 | else { |
| 12929 | 12810 | if (wB < 0) { |
| 12930 | 12811 | wB = -wB; |
| 12931 | 12812 | wA = -wA; |
| @@ -12932,55 +12813,67 @@ | ||
| 12932 | 12813 | } |
| 12933 | 12814 | wC = wA / wB; |
| 12934 | 12815 | if (wA % wB < 0) { |
| 12935 | 12816 | wC--; |
| 12936 | 12817 | } |
| 12818 | + goto intresult; | |
| 12937 | 12819 | } |
| 12938 | - break; | |
| 12939 | 12820 | case JIM_EXPROP_LT: |
| 12940 | 12821 | wC = wA < wB; |
| 12941 | - break; | |
| 12822 | + goto intresult; | |
| 12942 | 12823 | case JIM_EXPROP_GT: |
| 12943 | 12824 | wC = wA > wB; |
| 12944 | - break; | |
| 12825 | + goto intresult; | |
| 12945 | 12826 | case JIM_EXPROP_LTE: |
| 12946 | 12827 | wC = wA <= wB; |
| 12947 | - break; | |
| 12828 | + goto intresult; | |
| 12948 | 12829 | case JIM_EXPROP_GTE: |
| 12949 | 12830 | wC = wA >= wB; |
| 12950 | - break; | |
| 12831 | + goto intresult; | |
| 12951 | 12832 | case JIM_EXPROP_NUMEQ: |
| 12952 | 12833 | wC = wA == wB; |
| 12953 | - break; | |
| 12834 | + goto intresult; | |
| 12954 | 12835 | case JIM_EXPROP_NUMNE: |
| 12955 | 12836 | wC = wA != wB; |
| 12956 | - break; | |
| 12957 | - default: | |
| 12958 | - abort(); | |
| 12837 | + goto intresult; | |
| 12959 | 12838 | } |
| 12960 | 12839 | } |
| 12961 | - else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { | |
| 12962 | - intresult = 0; | |
| 12963 | - switch (e->opcode) { | |
| 12840 | + if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { | |
| 12841 | + switch (node->type) { | |
| 12842 | +#ifndef JIM_MATH_FUNCTIONS | |
| 12964 | 12843 | case JIM_EXPROP_POW: |
| 12965 | 12844 | case JIM_EXPROP_FUNC_POW: |
| 12966 | -#ifdef JIM_MATH_FUNCTIONS | |
| 12967 | - dC = pow(dA, dB); | |
| 12968 | -#else | |
| 12845 | + case JIM_EXPROP_FUNC_ATAN2: | |
| 12846 | + case JIM_EXPROP_FUNC_HYPOT: | |
| 12847 | + case JIM_EXPROP_FUNC_FMOD: | |
| 12969 | 12848 | Jim_SetResultString(interp, "unsupported", -1); |
| 12970 | 12849 | rc = JIM_ERR; |
| 12850 | + goto done; | |
| 12851 | +#else | |
| 12852 | + case JIM_EXPROP_POW: | |
| 12853 | + case JIM_EXPROP_FUNC_POW: | |
| 12854 | + dC = pow(dA, dB); | |
| 12855 | + goto doubleresult; | |
| 12856 | + case JIM_EXPROP_FUNC_ATAN2: | |
| 12857 | + dC = atan2(dA, dB); | |
| 12858 | + goto doubleresult; | |
| 12859 | + case JIM_EXPROP_FUNC_HYPOT: | |
| 12860 | + dC = hypot(dA, dB); | |
| 12861 | + goto doubleresult; | |
| 12862 | + case JIM_EXPROP_FUNC_FMOD: | |
| 12863 | + dC = fmod(dA, dB); | |
| 12864 | + goto doubleresult; | |
| 12971 | 12865 | #endif |
| 12972 | - break; | |
| 12973 | 12866 | case JIM_EXPROP_ADD: |
| 12974 | 12867 | dC = dA + dB; |
| 12975 | - break; | |
| 12868 | + goto doubleresult; | |
| 12976 | 12869 | case JIM_EXPROP_SUB: |
| 12977 | 12870 | dC = dA - dB; |
| 12978 | - break; | |
| 12871 | + goto doubleresult; | |
| 12979 | 12872 | case JIM_EXPROP_MUL: |
| 12980 | 12873 | dC = dA * dB; |
| 12981 | - break; | |
| 12874 | + goto doubleresult; | |
| 12982 | 12875 | case JIM_EXPROP_DIV: |
| 12983 | 12876 | if (dB == 0) { |
| 12984 | 12877 | #ifdef INFINITY |
| 12985 | 12878 | dC = dA < 0 ? -INFINITY : INFINITY; |
| 12986 | 12879 | #else |
| @@ -12988,83 +12881,70 @@ | ||
| 12988 | 12881 | #endif |
| 12989 | 12882 | } |
| 12990 | 12883 | else { |
| 12991 | 12884 | dC = dA / dB; |
| 12992 | 12885 | } |
| 12993 | - break; | |
| 12886 | + goto doubleresult; | |
| 12994 | 12887 | case JIM_EXPROP_LT: |
| 12995 | 12888 | wC = dA < dB; |
| 12996 | - intresult = 1; | |
| 12997 | - break; | |
| 12889 | + goto intresult; | |
| 12998 | 12890 | case JIM_EXPROP_GT: |
| 12999 | 12891 | wC = dA > dB; |
| 13000 | - intresult = 1; | |
| 13001 | - break; | |
| 12892 | + goto intresult; | |
| 13002 | 12893 | case JIM_EXPROP_LTE: |
| 13003 | 12894 | wC = dA <= dB; |
| 13004 | - intresult = 1; | |
| 13005 | - break; | |
| 12895 | + goto intresult; | |
| 13006 | 12896 | case JIM_EXPROP_GTE: |
| 13007 | 12897 | wC = dA >= dB; |
| 13008 | - intresult = 1; | |
| 13009 | - break; | |
| 12898 | + goto intresult; | |
| 13010 | 12899 | case JIM_EXPROP_NUMEQ: |
| 13011 | 12900 | wC = dA == dB; |
| 13012 | - intresult = 1; | |
| 13013 | - break; | |
| 12901 | + goto intresult; | |
| 13014 | 12902 | case JIM_EXPROP_NUMNE: |
| 13015 | 12903 | wC = dA != dB; |
| 13016 | - intresult = 1; | |
| 13017 | - break; | |
| 13018 | - default: | |
| 13019 | - abort(); | |
| 12904 | + goto intresult; | |
| 13020 | 12905 | } |
| 13021 | 12906 | } |
| 13022 | 12907 | else { |
| 13023 | - | |
| 13024 | 12908 | |
| 13025 | - | |
| 12909 | + | |
| 12910 | + | |
| 13026 | 12911 | int i = Jim_StringCompareObj(interp, A, B, 0); |
| 13027 | 12912 | |
| 13028 | - switch (e->opcode) { | |
| 12913 | + switch (node->type) { | |
| 13029 | 12914 | case JIM_EXPROP_LT: |
| 13030 | 12915 | wC = i < 0; |
| 13031 | - break; | |
| 12916 | + goto intresult; | |
| 13032 | 12917 | case JIM_EXPROP_GT: |
| 13033 | 12918 | wC = i > 0; |
| 13034 | - break; | |
| 12919 | + goto intresult; | |
| 13035 | 12920 | case JIM_EXPROP_LTE: |
| 13036 | 12921 | wC = i <= 0; |
| 13037 | - break; | |
| 12922 | + goto intresult; | |
| 13038 | 12923 | case JIM_EXPROP_GTE: |
| 13039 | 12924 | wC = i >= 0; |
| 13040 | - break; | |
| 12925 | + goto intresult; | |
| 13041 | 12926 | case JIM_EXPROP_NUMEQ: |
| 13042 | 12927 | wC = i == 0; |
| 13043 | - break; | |
| 12928 | + goto intresult; | |
| 13044 | 12929 | case JIM_EXPROP_NUMNE: |
| 13045 | 12930 | wC = i != 0; |
| 13046 | - break; | |
| 13047 | - default: | |
| 13048 | - rc = JIM_ERR; | |
| 13049 | - break; | |
| 12931 | + goto intresult; | |
| 13050 | 12932 | } |
| 13051 | 12933 | } |
| 13052 | 12934 | |
| 13053 | - if (rc == JIM_OK) { | |
| 13054 | - if (intresult) { | |
| 13055 | - ExprPush(e, Jim_NewIntObj(interp, wC)); | |
| 13056 | - } | |
| 13057 | - else { | |
| 13058 | - ExprPush(e, Jim_NewDoubleObj(interp, dC)); | |
| 13059 | - } | |
| 13060 | - } | |
| 13061 | - | |
| 12935 | + rc = JIM_ERR; | |
| 12936 | +done: | |
| 13062 | 12937 | Jim_DecrRefCount(interp, A); |
| 13063 | 12938 | Jim_DecrRefCount(interp, B); |
| 13064 | - | |
| 13065 | 12939 | return rc; |
| 12940 | +intresult: | |
| 12941 | + Jim_SetResultInt(interp, wC); | |
| 12942 | + goto done; | |
| 12943 | +doubleresult: | |
| 12944 | + Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); | |
| 12945 | + goto done; | |
| 13066 | 12946 | } |
| 13067 | 12947 | |
| 13068 | 12948 | static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) |
| 13069 | 12949 | { |
| 13070 | 12950 | int listlen; |
| @@ -13077,22 +12957,31 @@ | ||
| 13077 | 12957 | } |
| 13078 | 12958 | } |
| 13079 | 12959 | return 0; |
| 13080 | 12960 | } |
| 13081 | 12961 | |
| 13082 | -static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e) | |
| 12962 | + | |
| 12963 | + | |
| 12964 | +static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node) | |
| 13083 | 12965 | { |
| 13084 | - Jim_Obj *B = ExprPop(e); | |
| 13085 | - Jim_Obj *A = ExprPop(e); | |
| 13086 | - | |
| 12966 | + Jim_Obj *A, *B; | |
| 13087 | 12967 | jim_wide wC; |
| 12968 | + int rc; | |
| 13088 | 12969 | |
| 13089 | - switch (e->opcode) { | |
| 12970 | + if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { | |
| 12971 | + return rc; | |
| 12972 | + } | |
| 12973 | + if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { | |
| 12974 | + Jim_DecrRefCount(interp, A); | |
| 12975 | + return rc; | |
| 12976 | + } | |
| 12977 | + | |
| 12978 | + switch (node->type) { | |
| 13090 | 12979 | case JIM_EXPROP_STREQ: |
| 13091 | 12980 | case JIM_EXPROP_STRNE: |
| 13092 | 12981 | wC = Jim_StringEqObj(A, B); |
| 13093 | - if (e->opcode == JIM_EXPROP_STRNE) { | |
| 12982 | + if (node->type == JIM_EXPROP_STRNE) { | |
| 13094 | 12983 | wC = !wC; |
| 13095 | 12984 | } |
| 13096 | 12985 | break; |
| 13097 | 12986 | case JIM_EXPROP_STRIN: |
| 13098 | 12987 | wC = JimSearchList(interp, B, A); |
| @@ -13101,178 +12990,99 @@ | ||
| 13101 | 12990 | wC = !JimSearchList(interp, B, A); |
| 13102 | 12991 | break; |
| 13103 | 12992 | default: |
| 13104 | 12993 | abort(); |
| 13105 | 12994 | } |
| 13106 | - ExprPush(e, Jim_NewIntObj(interp, wC)); | |
| 12995 | + Jim_SetResultInt(interp, wC); | |
| 13107 | 12996 | |
| 13108 | 12997 | Jim_DecrRefCount(interp, A); |
| 13109 | 12998 | Jim_DecrRefCount(interp, B); |
| 13110 | 12999 | |
| 13111 | - return JIM_OK; | |
| 13000 | + return rc; | |
| 13112 | 13001 | } |
| 13113 | 13002 | |
| 13114 | 13003 | static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) |
| 13115 | 13004 | { |
| 13116 | 13005 | long l; |
| 13117 | 13006 | double d; |
| 13007 | + int b; | |
| 13008 | + int ret = -1; | |
| 13009 | + | |
| 13010 | + | |
| 13011 | + Jim_IncrRefCount(obj); | |
| 13118 | 13012 | |
| 13119 | 13013 | if (Jim_GetLong(interp, obj, &l) == JIM_OK) { |
| 13120 | - return l != 0; | |
| 13121 | - } | |
| 13122 | - if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { | |
| 13123 | - return d != 0; | |
| 13124 | - } | |
| 13125 | - return -1; | |
| 13126 | -} | |
| 13127 | - | |
| 13128 | -static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e) | |
| 13129 | -{ | |
| 13130 | - Jim_Obj *skip = ExprPop(e); | |
| 13131 | - Jim_Obj *A = ExprPop(e); | |
| 13132 | - int rc = JIM_OK; | |
| 13133 | - | |
| 13134 | - switch (ExprBool(interp, A)) { | |
| 13135 | - case 0: | |
| 13136 | - | |
| 13137 | - e->skip = JimWideValue(skip); | |
| 13138 | - ExprPush(e, Jim_NewIntObj(interp, 0)); | |
| 13139 | - break; | |
| 13140 | - | |
| 13141 | - case 1: | |
| 13142 | - | |
| 13143 | - break; | |
| 13144 | - | |
| 13145 | - case -1: | |
| 13146 | - | |
| 13147 | - rc = JIM_ERR; | |
| 13148 | - } | |
| 13149 | - Jim_DecrRefCount(interp, A); | |
| 13150 | - Jim_DecrRefCount(interp, skip); | |
| 13151 | - | |
| 13152 | - return rc; | |
| 13153 | -} | |
| 13154 | - | |
| 13155 | -static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e) | |
| 13156 | -{ | |
| 13157 | - Jim_Obj *skip = ExprPop(e); | |
| 13158 | - Jim_Obj *A = ExprPop(e); | |
| 13159 | - int rc = JIM_OK; | |
| 13160 | - | |
| 13161 | - switch (ExprBool(interp, A)) { | |
| 13162 | - case 0: | |
| 13163 | - | |
| 13164 | - break; | |
| 13165 | - | |
| 13166 | - case 1: | |
| 13167 | - | |
| 13168 | - e->skip = JimWideValue(skip); | |
| 13169 | - ExprPush(e, Jim_NewIntObj(interp, 1)); | |
| 13170 | - break; | |
| 13171 | - | |
| 13172 | - case -1: | |
| 13173 | - | |
| 13174 | - rc = JIM_ERR; | |
| 13175 | - break; | |
| 13176 | - } | |
| 13177 | - Jim_DecrRefCount(interp, A); | |
| 13178 | - Jim_DecrRefCount(interp, skip); | |
| 13179 | - | |
| 13180 | - return rc; | |
| 13181 | -} | |
| 13182 | - | |
| 13183 | -static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e) | |
| 13184 | -{ | |
| 13185 | - Jim_Obj *A = ExprPop(e); | |
| 13186 | - int rc = JIM_OK; | |
| 13187 | - | |
| 13188 | - switch (ExprBool(interp, A)) { | |
| 13189 | - case 0: | |
| 13190 | - ExprPush(e, Jim_NewIntObj(interp, 0)); | |
| 13191 | - break; | |
| 13192 | - | |
| 13193 | - case 1: | |
| 13194 | - ExprPush(e, Jim_NewIntObj(interp, 1)); | |
| 13195 | - break; | |
| 13196 | - | |
| 13197 | - case -1: | |
| 13198 | - | |
| 13199 | - rc = JIM_ERR; | |
| 13200 | - break; | |
| 13201 | - } | |
| 13202 | - Jim_DecrRefCount(interp, A); | |
| 13203 | - | |
| 13204 | - return rc; | |
| 13205 | -} | |
| 13206 | - | |
| 13207 | -static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e) | |
| 13208 | -{ | |
| 13209 | - Jim_Obj *skip = ExprPop(e); | |
| 13210 | - Jim_Obj *A = ExprPop(e); | |
| 13211 | - int rc = JIM_OK; | |
| 13212 | - | |
| 13213 | - | |
| 13214 | - ExprPush(e, A); | |
| 13215 | - | |
| 13216 | - switch (ExprBool(interp, A)) { | |
| 13217 | - case 0: | |
| 13218 | - | |
| 13219 | - e->skip = JimWideValue(skip); | |
| 13220 | - | |
| 13221 | - ExprPush(e, Jim_NewIntObj(interp, 0)); | |
| 13222 | - break; | |
| 13223 | - | |
| 13224 | - case 1: | |
| 13225 | - | |
| 13226 | - break; | |
| 13227 | - | |
| 13228 | - case -1: | |
| 13229 | - | |
| 13230 | - rc = JIM_ERR; | |
| 13231 | - break; | |
| 13232 | - } | |
| 13233 | - Jim_DecrRefCount(interp, A); | |
| 13234 | - Jim_DecrRefCount(interp, skip); | |
| 13235 | - | |
| 13236 | - return rc; | |
| 13237 | -} | |
| 13238 | - | |
| 13239 | -static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e) | |
| 13240 | -{ | |
| 13241 | - Jim_Obj *skip = ExprPop(e); | |
| 13242 | - Jim_Obj *B = ExprPop(e); | |
| 13243 | - Jim_Obj *A = ExprPop(e); | |
| 13244 | - | |
| 13245 | - | |
| 13246 | - if (ExprBool(interp, A)) { | |
| 13247 | - | |
| 13248 | - e->skip = JimWideValue(skip); | |
| 13249 | - | |
| 13250 | - ExprPush(e, B); | |
| 13251 | - } | |
| 13252 | - | |
| 13253 | - Jim_DecrRefCount(interp, skip); | |
| 13254 | - Jim_DecrRefCount(interp, A); | |
| 13255 | - Jim_DecrRefCount(interp, B); | |
| 13256 | - return JIM_OK; | |
| 13257 | -} | |
| 13258 | - | |
| 13259 | -static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e) | |
| 13260 | -{ | |
| 13261 | - return JIM_OK; | |
| 13014 | + ret = (l != 0); | |
| 13015 | + } | |
| 13016 | + else if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { | |
| 13017 | + ret = (d != 0); | |
| 13018 | + } | |
| 13019 | + else if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) { | |
| 13020 | + ret = (b != 0); | |
| 13021 | + } | |
| 13022 | + | |
| 13023 | + Jim_DecrRefCount(interp, obj); | |
| 13024 | + return ret; | |
| 13025 | +} | |
| 13026 | + | |
| 13027 | +static int JimExprOpAnd(Jim_Interp *interp, struct JimExprNode *node) | |
| 13028 | +{ | |
| 13029 | + | |
| 13030 | + int result = JimExprGetTermBoolean(interp, node->left); | |
| 13031 | + | |
| 13032 | + if (result == 1) { | |
| 13033 | + | |
| 13034 | + result = JimExprGetTermBoolean(interp, node->right); | |
| 13035 | + } | |
| 13036 | + if (result == -1) { | |
| 13037 | + return JIM_ERR; | |
| 13038 | + } | |
| 13039 | + Jim_SetResultInt(interp, result); | |
| 13040 | + return JIM_OK; | |
| 13041 | +} | |
| 13042 | + | |
| 13043 | +static int JimExprOpOr(Jim_Interp *interp, struct JimExprNode *node) | |
| 13044 | +{ | |
| 13045 | + | |
| 13046 | + int result = JimExprGetTermBoolean(interp, node->left); | |
| 13047 | + | |
| 13048 | + if (result == 0) { | |
| 13049 | + | |
| 13050 | + result = JimExprGetTermBoolean(interp, node->right); | |
| 13051 | + } | |
| 13052 | + if (result == -1) { | |
| 13053 | + return JIM_ERR; | |
| 13054 | + } | |
| 13055 | + Jim_SetResultInt(interp, result); | |
| 13056 | + return JIM_OK; | |
| 13057 | +} | |
| 13058 | + | |
| 13059 | +static int JimExprOpTernary(Jim_Interp *interp, struct JimExprNode *node) | |
| 13060 | +{ | |
| 13061 | + | |
| 13062 | + int result = JimExprGetTermBoolean(interp, node->left); | |
| 13063 | + | |
| 13064 | + if (result == 1) { | |
| 13065 | + | |
| 13066 | + return JimExprEvalTermNode(interp, node->right); | |
| 13067 | + } | |
| 13068 | + else if (result == 0) { | |
| 13069 | + | |
| 13070 | + return JimExprEvalTermNode(interp, node->ternary); | |
| 13071 | + } | |
| 13072 | + | |
| 13073 | + return JIM_ERR; | |
| 13262 | 13074 | } |
| 13263 | 13075 | |
| 13264 | 13076 | enum |
| 13265 | 13077 | { |
| 13266 | - LAZY_NONE, | |
| 13267 | - LAZY_OP, | |
| 13268 | - LAZY_LEFT, | |
| 13269 | - LAZY_RIGHT | |
| 13078 | + OP_FUNC = 0x0001, | |
| 13079 | + OP_RIGHT_ASSOC = 0x0002, | |
| 13270 | 13080 | }; |
| 13271 | 13081 | |
| 13272 | -#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1} | |
| 13273 | -#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} | |
| 13082 | +#define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1} | |
| 13083 | +#define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, 0) | |
| 13274 | 13084 | |
| 13275 | 13085 | static const struct Jim_ExprOperator Jim_ExprOperators[] = { |
| 13276 | 13086 | OPRINIT("*", 110, 2, JimExprOpBin), |
| 13277 | 13087 | OPRINIT("/", 110, 2, JimExprOpBin), |
| 13278 | 13088 | OPRINIT("%", 110, 2, JimExprOpIntBin), |
| @@ -13296,86 +13106,79 @@ | ||
| 13296 | 13106 | |
| 13297 | 13107 | OPRINIT("&", 50, 2, JimExprOpIntBin), |
| 13298 | 13108 | OPRINIT("^", 49, 2, JimExprOpIntBin), |
| 13299 | 13109 | OPRINIT("|", 48, 2, JimExprOpIntBin), |
| 13300 | 13110 | |
| 13301 | - OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP), | |
| 13302 | - OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), | |
| 13303 | - OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), | |
| 13304 | - | |
| 13305 | - OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP), | |
| 13306 | - OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), | |
| 13307 | - OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), | |
| 13308 | - | |
| 13309 | - OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP), | |
| 13310 | - OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), | |
| 13311 | - OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), | |
| 13312 | - | |
| 13313 | - OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP), | |
| 13314 | - OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), | |
| 13315 | - OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), | |
| 13316 | - | |
| 13317 | - OPRINIT("**", 250, 2, JimExprOpBin), | |
| 13111 | + OPRINIT("&&", 10, 2, JimExprOpAnd), | |
| 13112 | + OPRINIT("||", 9, 2, JimExprOpOr), | |
| 13113 | + OPRINIT_ATTR("?", 5, 3, JimExprOpTernary, OP_RIGHT_ASSOC), | |
| 13114 | + OPRINIT_ATTR(":", 5, 3, NULL, OP_RIGHT_ASSOC), | |
| 13115 | + | |
| 13116 | + | |
| 13117 | + OPRINIT_ATTR("**", 120, 2, JimExprOpBin, OP_RIGHT_ASSOC), | |
| 13318 | 13118 | |
| 13319 | 13119 | OPRINIT("eq", 60, 2, JimExprOpStrBin), |
| 13320 | 13120 | OPRINIT("ne", 60, 2, JimExprOpStrBin), |
| 13321 | 13121 | |
| 13322 | 13122 | OPRINIT("in", 55, 2, JimExprOpStrBin), |
| 13323 | 13123 | OPRINIT("ni", 55, 2, JimExprOpStrBin), |
| 13324 | 13124 | |
| 13325 | - OPRINIT("!", 150, 1, JimExprOpNumUnary), | |
| 13326 | - OPRINIT("~", 150, 1, JimExprOpIntUnary), | |
| 13327 | - OPRINIT(NULL, 150, 1, JimExprOpNumUnary), | |
| 13328 | - OPRINIT(NULL, 150, 1, JimExprOpNumUnary), | |
| 13125 | + OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), | |
| 13126 | + OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC), | |
| 13127 | + OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), | |
| 13128 | + OPRINIT_ATTR(" +", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), | |
| 13329 | 13129 | |
| 13330 | 13130 | |
| 13331 | 13131 | |
| 13332 | - OPRINIT("int", 200, 1, JimExprOpNumUnary), | |
| 13333 | - OPRINIT("wide", 200, 1, JimExprOpNumUnary), | |
| 13334 | - OPRINIT("abs", 200, 1, JimExprOpNumUnary), | |
| 13335 | - OPRINIT("double", 200, 1, JimExprOpNumUnary), | |
| 13336 | - OPRINIT("round", 200, 1, JimExprOpNumUnary), | |
| 13337 | - OPRINIT("rand", 200, 0, JimExprOpNone), | |
| 13338 | - OPRINIT("srand", 200, 1, JimExprOpIntUnary), | |
| 13132 | + OPRINIT_ATTR("int", 200, 1, JimExprOpNumUnary, OP_FUNC), | |
| 13133 | + OPRINIT_ATTR("wide", 200, 1, JimExprOpNumUnary, OP_FUNC), | |
| 13134 | + OPRINIT_ATTR("abs", 200, 1, JimExprOpNumUnary, OP_FUNC), | |
| 13135 | + OPRINIT_ATTR("double", 200, 1, JimExprOpNumUnary, OP_FUNC), | |
| 13136 | + OPRINIT_ATTR("round", 200, 1, JimExprOpNumUnary, OP_FUNC), | |
| 13137 | + OPRINIT_ATTR("rand", 200, 0, JimExprOpNone, OP_FUNC), | |
| 13138 | + OPRINIT_ATTR("srand", 200, 1, JimExprOpIntUnary, OP_FUNC), | |
| 13339 | 13139 | |
| 13340 | 13140 | #ifdef JIM_MATH_FUNCTIONS |
| 13341 | - OPRINIT("sin", 200, 1, JimExprOpDoubleUnary), | |
| 13342 | - OPRINIT("cos", 200, 1, JimExprOpDoubleUnary), | |
| 13343 | - OPRINIT("tan", 200, 1, JimExprOpDoubleUnary), | |
| 13344 | - OPRINIT("asin", 200, 1, JimExprOpDoubleUnary), | |
| 13345 | - OPRINIT("acos", 200, 1, JimExprOpDoubleUnary), | |
| 13346 | - OPRINIT("atan", 200, 1, JimExprOpDoubleUnary), | |
| 13347 | - OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary), | |
| 13348 | - OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary), | |
| 13349 | - OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary), | |
| 13350 | - OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary), | |
| 13351 | - OPRINIT("floor", 200, 1, JimExprOpDoubleUnary), | |
| 13352 | - OPRINIT("exp", 200, 1, JimExprOpDoubleUnary), | |
| 13353 | - OPRINIT("log", 200, 1, JimExprOpDoubleUnary), | |
| 13354 | - OPRINIT("log10", 200, 1, JimExprOpDoubleUnary), | |
| 13355 | - OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary), | |
| 13356 | - OPRINIT("pow", 200, 2, JimExprOpBin), | |
| 13141 | + OPRINIT_ATTR("sin", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13142 | + OPRINIT_ATTR("cos", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13143 | + OPRINIT_ATTR("tan", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13144 | + OPRINIT_ATTR("asin", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13145 | + OPRINIT_ATTR("acos", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13146 | + OPRINIT_ATTR("atan", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13147 | + OPRINIT_ATTR("atan2", 200, 2, JimExprOpBin, OP_FUNC), | |
| 13148 | + OPRINIT_ATTR("sinh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13149 | + OPRINIT_ATTR("cosh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13150 | + OPRINIT_ATTR("tanh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13151 | + OPRINIT_ATTR("ceil", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13152 | + OPRINIT_ATTR("floor", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13153 | + OPRINIT_ATTR("exp", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13154 | + OPRINIT_ATTR("log", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13155 | + OPRINIT_ATTR("log10", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13156 | + OPRINIT_ATTR("sqrt", 200, 1, JimExprOpDoubleUnary, OP_FUNC), | |
| 13157 | + OPRINIT_ATTR("pow", 200, 2, JimExprOpBin, OP_FUNC), | |
| 13158 | + OPRINIT_ATTR("hypot", 200, 2, JimExprOpBin, OP_FUNC), | |
| 13159 | + OPRINIT_ATTR("fmod", 200, 2, JimExprOpBin, OP_FUNC), | |
| 13357 | 13160 | #endif |
| 13358 | 13161 | }; |
| 13359 | 13162 | #undef OPRINIT |
| 13360 | -#undef OPRINIT_LAZY | |
| 13163 | +#undef OPRINIT_ATTR | |
| 13361 | 13164 | |
| 13362 | 13165 | #define JIM_EXPR_OPERATORS_NUM \ |
| 13363 | 13166 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 13364 | 13167 | |
| 13365 | 13168 | static int JimParseExpression(struct JimParserCtx *pc) |
| 13366 | 13169 | { |
| 13367 | - | |
| 13170 | + | |
| 13368 | 13171 | while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { |
| 13369 | 13172 | if (*pc->p == '\n') { |
| 13370 | 13173 | pc->linenr++; |
| 13371 | 13174 | } |
| 13372 | 13175 | pc->p++; |
| 13373 | 13176 | pc->len--; |
| 13374 | 13177 | } |
| 13375 | 13178 | |
| 13376 | - | |
| 13179 | + | |
| 13377 | 13180 | pc->tline = pc->linenr; |
| 13378 | 13181 | pc->tstart = pc->p; |
| 13379 | 13182 | |
| 13380 | 13183 | if (pc->len == 0) { |
| 13381 | 13184 | pc->tend = pc->p; |
| @@ -13401,11 +13204,11 @@ | ||
| 13401 | 13204 | return JimParseCmd(pc); |
| 13402 | 13205 | case '$': |
| 13403 | 13206 | if (JimParseVar(pc) == JIM_ERR) |
| 13404 | 13207 | return JimParseExprOperator(pc); |
| 13405 | 13208 | else { |
| 13406 | - | |
| 13209 | + | |
| 13407 | 13210 | if (pc->tt == JIM_TT_EXPRSUGAR) { |
| 13408 | 13211 | return JIM_ERR; |
| 13409 | 13212 | } |
| 13410 | 13213 | return JIM_OK; |
| 13411 | 13214 | } |
| @@ -13430,10 +13233,18 @@ | ||
| 13430 | 13233 | case 'N': |
| 13431 | 13234 | case 'I': |
| 13432 | 13235 | case 'n': |
| 13433 | 13236 | case 'i': |
| 13434 | 13237 | if (JimParseExprIrrational(pc) == JIM_ERR) |
| 13238 | + if (JimParseExprBoolean(pc) == JIM_ERR) | |
| 13239 | + return JimParseExprOperator(pc); | |
| 13240 | + break; | |
| 13241 | + case 't': | |
| 13242 | + case 'f': | |
| 13243 | + case 'o': | |
| 13244 | + case 'y': | |
| 13245 | + if (JimParseExprBoolean(pc) == JIM_ERR) | |
| 13435 | 13246 | return JimParseExprOperator(pc); |
| 13436 | 13247 | break; |
| 13437 | 13248 | default: |
| 13438 | 13249 | return JimParseExprOperator(pc); |
| 13439 | 13250 | break; |
| @@ -13443,21 +13254,21 @@ | ||
| 13443 | 13254 | |
| 13444 | 13255 | static int JimParseExprNumber(struct JimParserCtx *pc) |
| 13445 | 13256 | { |
| 13446 | 13257 | char *end; |
| 13447 | 13258 | |
| 13448 | - | |
| 13259 | + | |
| 13449 | 13260 | pc->tt = JIM_TT_EXPR_INT; |
| 13450 | 13261 | |
| 13451 | 13262 | jim_strtoull(pc->p, (char **)&pc->p); |
| 13452 | - | |
| 13263 | + | |
| 13453 | 13264 | if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { |
| 13454 | - if (strtod(pc->tstart, &end)) { } | |
| 13265 | + if (strtod(pc->tstart, &end)) { } | |
| 13455 | 13266 | if (end == pc->tstart) |
| 13456 | 13267 | return JIM_ERR; |
| 13457 | 13268 | if (end > pc->p) { |
| 13458 | - | |
| 13269 | + | |
| 13459 | 13270 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13460 | 13271 | pc->p = end; |
| 13461 | 13272 | } |
| 13462 | 13273 | } |
| 13463 | 13274 | pc->tend = pc->p - 1; |
| @@ -13481,36 +13292,66 @@ | ||
| 13481 | 13292 | return JIM_OK; |
| 13482 | 13293 | } |
| 13483 | 13294 | } |
| 13484 | 13295 | return JIM_ERR; |
| 13485 | 13296 | } |
| 13297 | + | |
| 13298 | +static int JimParseExprBoolean(struct JimParserCtx *pc) | |
| 13299 | +{ | |
| 13300 | + const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL }; | |
| 13301 | + const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 }; | |
| 13302 | + int i; | |
| 13303 | + | |
| 13304 | + for (i = 0; booleans[i]; i++) { | |
| 13305 | + const char *boolean = booleans[i]; | |
| 13306 | + int length = lengths[i]; | |
| 13307 | + | |
| 13308 | + if (strncmp(boolean, pc->p, length) == 0) { | |
| 13309 | + pc->p += length; | |
| 13310 | + pc->len -= length; | |
| 13311 | + pc->tend = pc->p - 1; | |
| 13312 | + pc->tt = JIM_TT_EXPR_BOOLEAN; | |
| 13313 | + return JIM_OK; | |
| 13314 | + } | |
| 13315 | + } | |
| 13316 | + return JIM_ERR; | |
| 13317 | +} | |
| 13318 | + | |
| 13319 | +static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) | |
| 13320 | +{ | |
| 13321 | + static Jim_ExprOperator dummy_op; | |
| 13322 | + if (opcode < JIM_TT_EXPR_OP) { | |
| 13323 | + return &dummy_op; | |
| 13324 | + } | |
| 13325 | + return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP]; | |
| 13326 | +} | |
| 13486 | 13327 | |
| 13487 | 13328 | static int JimParseExprOperator(struct JimParserCtx *pc) |
| 13488 | 13329 | { |
| 13489 | 13330 | int i; |
| 13490 | - int bestIdx = -1, bestLen = 0; | |
| 13331 | + const struct Jim_ExprOperator *bestOp = NULL; | |
| 13332 | + int bestLen = 0; | |
| 13491 | 13333 | |
| 13492 | - | |
| 13334 | + | |
| 13493 | 13335 | for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { |
| 13494 | - const char * const opname = Jim_ExprOperators[i].name; | |
| 13495 | - const int oplen = Jim_ExprOperators[i].namelen; | |
| 13336 | + const struct Jim_ExprOperator *op = &Jim_ExprOperators[i]; | |
| 13496 | 13337 | |
| 13497 | - if (opname == NULL || opname[0] != pc->p[0]) { | |
| 13338 | + if (op->name[0] != pc->p[0]) { | |
| 13498 | 13339 | continue; |
| 13499 | 13340 | } |
| 13500 | 13341 | |
| 13501 | - if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) { | |
| 13502 | - bestIdx = i + JIM_TT_EXPR_OP; | |
| 13503 | - bestLen = oplen; | |
| 13342 | + if (op->namelen > bestLen && strncmp(op->name, pc->p, op->namelen) == 0) { | |
| 13343 | + bestOp = op; | |
| 13344 | + bestLen = op->namelen; | |
| 13504 | 13345 | } |
| 13505 | 13346 | } |
| 13506 | - if (bestIdx == -1) { | |
| 13347 | + if (bestOp == NULL) { | |
| 13507 | 13348 | return JIM_ERR; |
| 13508 | 13349 | } |
| 13509 | 13350 | |
| 13510 | - | |
| 13511 | - if (bestIdx >= JIM_EXPROP_FUNC_FIRST) { | |
| 13351 | + | |
| 13352 | + if (bestOp->attr & OP_FUNC) { | |
| 13512 | 13353 | const char *p = pc->p + bestLen; |
| 13513 | 13354 | int len = pc->len - bestLen; |
| 13514 | 13355 | |
| 13515 | 13356 | while (len && isspace(UCHAR(*p))) { |
| 13516 | 13357 | len--; |
| @@ -13522,30 +13363,27 @@ | ||
| 13522 | 13363 | } |
| 13523 | 13364 | pc->tend = pc->p + bestLen - 1; |
| 13524 | 13365 | pc->p += bestLen; |
| 13525 | 13366 | pc->len -= bestLen; |
| 13526 | 13367 | |
| 13527 | - pc->tt = bestIdx; | |
| 13368 | + pc->tt = (bestOp - Jim_ExprOperators) + JIM_TT_EXPR_OP; | |
| 13528 | 13369 | return JIM_OK; |
| 13529 | 13370 | } |
| 13530 | 13371 | |
| 13531 | -static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) | |
| 13532 | -{ | |
| 13533 | - static Jim_ExprOperator dummy_op; | |
| 13534 | - if (opcode < JIM_TT_EXPR_OP) { | |
| 13535 | - return &dummy_op; | |
| 13536 | - } | |
| 13537 | - return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP]; | |
| 13538 | -} | |
| 13539 | - | |
| 13540 | 13372 | const char *jim_tt_name(int type) |
| 13541 | 13373 | { |
| 13542 | 13374 | static const char * const tt_names[JIM_TT_EXPR_OP] = |
| 13543 | 13375 | { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", |
| 13544 | - "DBL", "$()" }; | |
| 13376 | + "DBL", "BOO", "$()" }; | |
| 13545 | 13377 | if (type < JIM_TT_EXPR_OP) { |
| 13546 | 13378 | return tt_names[type]; |
| 13379 | + } | |
| 13380 | + else if (type == JIM_EXPROP_UNARYMINUS) { | |
| 13381 | + return "-VE"; | |
| 13382 | + } | |
| 13383 | + else if (type == JIM_EXPROP_UNARYPLUS) { | |
| 13384 | + return "+VE"; | |
| 13547 | 13385 | } |
| 13548 | 13386 | else { |
| 13549 | 13387 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type); |
| 13550 | 13388 | static char buf[20]; |
| 13551 | 13389 | |
| @@ -13568,432 +13406,400 @@ | ||
| 13568 | 13406 | NULL, |
| 13569 | 13407 | JIM_TYPE_REFERENCES, |
| 13570 | 13408 | }; |
| 13571 | 13409 | |
| 13572 | 13410 | |
| 13573 | -typedef struct ExprByteCode | |
| 13574 | -{ | |
| 13575 | - ScriptToken *token; | |
| 13576 | - int len; | |
| 13577 | - int inUse; | |
| 13578 | -} ExprByteCode; | |
| 13579 | - | |
| 13580 | -static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) | |
| 13411 | +struct ExprTree | |
| 13412 | +{ | |
| 13413 | + struct JimExprNode *expr; | |
| 13414 | + struct JimExprNode *nodes; | |
| 13415 | + int len; | |
| 13416 | + int inUse; | |
| 13417 | +}; | |
| 13418 | + | |
| 13419 | +static void ExprTreeFreeNodes(Jim_Interp *interp, struct JimExprNode *nodes, int num) | |
| 13581 | 13420 | { |
| 13582 | 13421 | int i; |
| 13422 | + for (i = 0; i < num; i++) { | |
| 13423 | + if (nodes[i].objPtr) { | |
| 13424 | + Jim_DecrRefCount(interp, nodes[i].objPtr); | |
| 13425 | + } | |
| 13426 | + } | |
| 13427 | + Jim_Free(nodes); | |
| 13428 | +} | |
| 13583 | 13429 | |
| 13584 | - for (i = 0; i < expr->len; i++) { | |
| 13585 | - Jim_DecrRefCount(interp, expr->token[i].objPtr); | |
| 13586 | - } | |
| 13587 | - Jim_Free(expr->token); | |
| 13430 | +static void ExprTreeFree(Jim_Interp *interp, struct ExprTree *expr) | |
| 13431 | +{ | |
| 13432 | + ExprTreeFreeNodes(interp, expr->nodes, expr->len); | |
| 13588 | 13433 | Jim_Free(expr); |
| 13589 | 13434 | } |
| 13590 | 13435 | |
| 13591 | 13436 | static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13592 | 13437 | { |
| 13593 | - ExprByteCode *expr = (void *)objPtr->internalRep.ptr; | |
| 13438 | + struct ExprTree *expr = (void *)objPtr->internalRep.ptr; | |
| 13594 | 13439 | |
| 13595 | 13440 | if (expr) { |
| 13596 | 13441 | if (--expr->inUse != 0) { |
| 13597 | 13442 | return; |
| 13598 | 13443 | } |
| 13599 | 13444 | |
| 13600 | - ExprFreeByteCode(interp, expr); | |
| 13445 | + ExprTreeFree(interp, expr); | |
| 13601 | 13446 | } |
| 13602 | 13447 | } |
| 13603 | 13448 | |
| 13604 | 13449 | static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 13605 | 13450 | { |
| 13606 | 13451 | JIM_NOTUSED(interp); |
| 13607 | 13452 | JIM_NOTUSED(srcPtr); |
| 13608 | 13453 | |
| 13609 | - | |
| 13454 | + | |
| 13610 | 13455 | dupPtr->typePtr = NULL; |
| 13611 | 13456 | } |
| 13612 | 13457 | |
| 13613 | - | |
| 13614 | -static int ExprCheckCorrectness(ExprByteCode * expr) | |
| 13615 | -{ | |
| 13616 | - int i; | |
| 13617 | - int stacklen = 0; | |
| 13618 | - int ternary = 0; | |
| 13619 | - | |
| 13620 | - for (i = 0; i < expr->len; i++) { | |
| 13621 | - ScriptToken *t = &expr->token[i]; | |
| 13622 | - const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); | |
| 13623 | - | |
| 13624 | - stacklen -= op->arity; | |
| 13625 | - if (stacklen < 0) { | |
| 13626 | - break; | |
| 13627 | - } | |
| 13628 | - if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) { | |
| 13629 | - ternary++; | |
| 13630 | - } | |
| 13631 | - else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) { | |
| 13632 | - ternary--; | |
| 13633 | - } | |
| 13634 | - | |
| 13635 | - | |
| 13636 | - stacklen++; | |
| 13637 | - } | |
| 13638 | - if (stacklen != 1 || ternary != 0) { | |
| 13639 | - return JIM_ERR; | |
| 13640 | - } | |
| 13641 | - return JIM_OK; | |
| 13642 | -} | |
| 13643 | - | |
| 13644 | -static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) | |
| 13645 | -{ | |
| 13646 | - int i; | |
| 13647 | - | |
| 13648 | - int leftindex, arity, offset; | |
| 13649 | - | |
| 13650 | - | |
| 13651 | - leftindex = expr->len - 1; | |
| 13652 | - | |
| 13653 | - arity = 1; | |
| 13654 | - while (arity) { | |
| 13655 | - ScriptToken *tt = &expr->token[leftindex]; | |
| 13656 | - | |
| 13657 | - if (tt->type >= JIM_TT_EXPR_OP) { | |
| 13658 | - arity += JimExprOperatorInfoByOpcode(tt->type)->arity; | |
| 13659 | - } | |
| 13660 | - arity--; | |
| 13661 | - if (--leftindex < 0) { | |
| 13662 | - return JIM_ERR; | |
| 13663 | - } | |
| 13664 | - } | |
| 13665 | - leftindex++; | |
| 13666 | - | |
| 13667 | - | |
| 13668 | - memmove(&expr->token[leftindex + 2], &expr->token[leftindex], | |
| 13669 | - sizeof(*expr->token) * (expr->len - leftindex)); | |
| 13670 | - expr->len += 2; | |
| 13671 | - offset = (expr->len - leftindex) - 1; | |
| 13672 | - | |
| 13673 | - expr->token[leftindex + 1].type = t->type + 1; | |
| 13674 | - expr->token[leftindex + 1].objPtr = interp->emptyObj; | |
| 13675 | - | |
| 13676 | - expr->token[leftindex].type = JIM_TT_EXPR_INT; | |
| 13677 | - expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset); | |
| 13678 | - | |
| 13679 | - | |
| 13680 | - expr->token[expr->len].objPtr = interp->emptyObj; | |
| 13681 | - expr->token[expr->len].type = t->type + 2; | |
| 13682 | - expr->len++; | |
| 13683 | - | |
| 13684 | - | |
| 13685 | - for (i = leftindex - 1; i > 0; i--) { | |
| 13686 | - const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type); | |
| 13687 | - if (op->lazy == LAZY_LEFT) { | |
| 13688 | - if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) { | |
| 13689 | - JimWideValue(expr->token[i - 1].objPtr) += 2; | |
| 13690 | - } | |
| 13691 | - } | |
| 13692 | - } | |
| 13693 | - return JIM_OK; | |
| 13694 | -} | |
| 13695 | - | |
| 13696 | -static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) | |
| 13697 | -{ | |
| 13698 | - struct ScriptToken *token = &expr->token[expr->len]; | |
| 13699 | - const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); | |
| 13700 | - | |
| 13701 | - if (op->lazy == LAZY_OP) { | |
| 13702 | - if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) { | |
| 13703 | - Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name); | |
| 13704 | - return JIM_ERR; | |
| 13705 | - } | |
| 13706 | - } | |
| 13707 | - else { | |
| 13708 | - token->objPtr = interp->emptyObj; | |
| 13709 | - token->type = t->type; | |
| 13710 | - expr->len++; | |
| 13711 | - } | |
| 13712 | - return JIM_OK; | |
| 13713 | -} | |
| 13714 | - | |
| 13715 | -static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index) | |
| 13716 | -{ | |
| 13717 | - int ternary_count = 1; | |
| 13718 | - | |
| 13719 | - right_index--; | |
| 13720 | - | |
| 13721 | - while (right_index > 1) { | |
| 13722 | - if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) { | |
| 13723 | - ternary_count--; | |
| 13724 | - } | |
| 13725 | - else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) { | |
| 13726 | - ternary_count++; | |
| 13727 | - } | |
| 13728 | - else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) { | |
| 13729 | - return right_index; | |
| 13730 | - } | |
| 13731 | - right_index--; | |
| 13732 | - } | |
| 13733 | - | |
| 13734 | - | |
| 13735 | - return -1; | |
| 13736 | -} | |
| 13737 | - | |
| 13738 | -static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index) | |
| 13739 | -{ | |
| 13740 | - int i = right_index - 1; | |
| 13741 | - int ternary_count = 1; | |
| 13742 | - | |
| 13743 | - while (i > 1) { | |
| 13744 | - if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) { | |
| 13745 | - if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) { | |
| 13746 | - *prev_right_index = i - 2; | |
| 13747 | - *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index); | |
| 13748 | - return 1; | |
| 13749 | - } | |
| 13750 | - } | |
| 13751 | - else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) { | |
| 13752 | - if (ternary_count == 0) { | |
| 13753 | - return 0; | |
| 13754 | - } | |
| 13755 | - ternary_count++; | |
| 13756 | - } | |
| 13757 | - i--; | |
| 13758 | - } | |
| 13759 | - return 0; | |
| 13760 | -} | |
| 13761 | - | |
| 13762 | -static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr) | |
| 13763 | -{ | |
| 13764 | - int i; | |
| 13765 | - | |
| 13766 | - for (i = expr->len - 1; i > 1; i--) { | |
| 13767 | - int prev_right_index; | |
| 13768 | - int prev_left_index; | |
| 13769 | - int j; | |
| 13770 | - ScriptToken tmp; | |
| 13771 | - | |
| 13772 | - if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) { | |
| 13773 | - continue; | |
| 13774 | - } | |
| 13775 | - | |
| 13776 | - | |
| 13777 | - if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) { | |
| 13778 | - continue; | |
| 13779 | - } | |
| 13780 | - | |
| 13781 | - tmp = expr->token[prev_right_index]; | |
| 13782 | - for (j = prev_right_index; j < i; j++) { | |
| 13783 | - expr->token[j] = expr->token[j + 1]; | |
| 13784 | - } | |
| 13785 | - expr->token[i] = tmp; | |
| 13786 | - | |
| 13787 | - JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index); | |
| 13788 | - | |
| 13789 | - | |
| 13790 | - i++; | |
| 13791 | - } | |
| 13792 | -} | |
| 13793 | - | |
| 13794 | -static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj) | |
| 13795 | -{ | |
| 13458 | +struct ExprBuilder { | |
| 13459 | + int parencount; | |
| 13460 | + int level; | |
| 13461 | + ParseToken *token; | |
| 13462 | + ParseToken *first_token; | |
| 13796 | 13463 | Jim_Stack stack; |
| 13797 | - ExprByteCode *expr; | |
| 13798 | - int ok = 1; | |
| 13464 | + Jim_Obj *exprObjPtr; | |
| 13465 | + Jim_Obj *fileNameObj; | |
| 13466 | + struct JimExprNode *nodes; | |
| 13467 | + struct JimExprNode *next; | |
| 13468 | +}; | |
| 13469 | + | |
| 13470 | +#ifdef DEBUG_SHOW_EXPR | |
| 13471 | +static void JimShowExprNode(struct JimExprNode *node, int level) | |
| 13472 | +{ | |
| 13799 | 13473 | int i; |
| 13800 | - int prevtt = JIM_TT_NONE; | |
| 13801 | - int have_ternary = 0; | |
| 13474 | + for (i = 0; i < level; i++) { | |
| 13475 | + printf(" "); | |
| 13476 | + } | |
| 13477 | + if (TOKEN_IS_EXPR_OP(node->type)) { | |
| 13478 | + printf("%s\n", jim_tt_name(node->type)); | |
| 13479 | + if (node->left) { | |
| 13480 | + JimShowExprNode(node->left, level + 1); | |
| 13481 | + } | |
| 13482 | + if (node->right) { | |
| 13483 | + JimShowExprNode(node->right, level + 1); | |
| 13484 | + } | |
| 13485 | + if (node->ternary) { | |
| 13486 | + JimShowExprNode(node->ternary, level + 1); | |
| 13487 | + } | |
| 13488 | + } | |
| 13489 | + else { | |
| 13490 | + printf("[%s] %s\n", jim_tt_name(node->type), Jim_String(node->objPtr)); | |
| 13491 | + } | |
| 13492 | +} | |
| 13493 | +#endif | |
| 13802 | 13494 | |
| 13803 | - | |
| 13804 | - int count = tokenlist->count - 1; | |
| 13495 | +#define EXPR_UNTIL_CLOSE 0x0001 | |
| 13496 | +#define EXPR_FUNC_ARGS 0x0002 | |
| 13497 | +#define EXPR_TERNARY 0x0004 | |
| 13498 | + | |
| 13499 | +static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms) | |
| 13500 | +{ | |
| 13501 | + int rc; | |
| 13502 | + struct JimExprNode *node; | |
| 13503 | + | |
| 13504 | + int exp_stacklen = builder->stack.len + exp_numterms; | |
| 13505 | + | |
| 13506 | + if (builder->level++ > 200) { | |
| 13507 | + Jim_SetResultString(interp, "Expression too complex", -1); | |
| 13508 | + return JIM_ERR; | |
| 13509 | + } | |
| 13510 | + | |
| 13511 | + while (builder->token->type != JIM_TT_EOL) { | |
| 13512 | + ParseToken *t = builder->token++; | |
| 13513 | + int prevtt; | |
| 13514 | + | |
| 13515 | + if (t == builder->first_token) { | |
| 13516 | + prevtt = JIM_TT_NONE; | |
| 13517 | + } | |
| 13518 | + else { | |
| 13519 | + prevtt = t[-1].type; | |
| 13520 | + } | |
| 13521 | + | |
| 13522 | + if (t->type == JIM_TT_SUBEXPR_START) { | |
| 13523 | + if (builder->stack.len == exp_stacklen) { | |
| 13524 | + Jim_SetResultFormatted(interp, "unexpected open parenthesis in expression: \"%#s\"", builder->exprObjPtr); | |
| 13525 | + return JIM_ERR; | |
| 13526 | + } | |
| 13527 | + builder->parencount++; | |
| 13528 | + rc = ExprTreeBuildTree(interp, builder, 0, EXPR_UNTIL_CLOSE, 1); | |
| 13529 | + if (rc != JIM_OK) { | |
| 13530 | + return rc; | |
| 13531 | + } | |
| 13532 | + | |
| 13533 | + } | |
| 13534 | + else if (t->type == JIM_TT_SUBEXPR_END) { | |
| 13535 | + if (!(flags & EXPR_UNTIL_CLOSE)) { | |
| 13536 | + if (builder->stack.len == exp_stacklen && builder->level > 1) { | |
| 13537 | + builder->token--; | |
| 13538 | + builder->level--; | |
| 13539 | + return JIM_OK; | |
| 13540 | + } | |
| 13541 | + Jim_SetResultFormatted(interp, "unexpected closing parenthesis in expression: \"%#s\"", builder->exprObjPtr); | |
| 13542 | + return JIM_ERR; | |
| 13543 | + } | |
| 13544 | + builder->parencount--; | |
| 13545 | + if (builder->stack.len == exp_stacklen) { | |
| 13546 | + | |
| 13547 | + break; | |
| 13548 | + } | |
| 13549 | + } | |
| 13550 | + else if (t->type == JIM_TT_SUBEXPR_COMMA) { | |
| 13551 | + if (!(flags & EXPR_FUNC_ARGS)) { | |
| 13552 | + if (builder->stack.len == exp_stacklen) { | |
| 13553 | + | |
| 13554 | + builder->token--; | |
| 13555 | + builder->level--; | |
| 13556 | + return JIM_OK; | |
| 13557 | + } | |
| 13558 | + Jim_SetResultFormatted(interp, "unexpected comma in expression: \"%#s\"", builder->exprObjPtr); | |
| 13559 | + return JIM_ERR; | |
| 13560 | + } | |
| 13561 | + else { | |
| 13562 | + | |
| 13563 | + if (builder->stack.len > exp_stacklen) { | |
| 13564 | + Jim_SetResultFormatted(interp, "too many arguments to math function"); | |
| 13565 | + return JIM_ERR; | |
| 13566 | + } | |
| 13567 | + } | |
| 13568 | + | |
| 13569 | + } | |
| 13570 | + else if (t->type == JIM_EXPROP_COLON) { | |
| 13571 | + if (!(flags & EXPR_TERNARY)) { | |
| 13572 | + if (builder->level != 1) { | |
| 13573 | + | |
| 13574 | + builder->token--; | |
| 13575 | + builder->level--; | |
| 13576 | + return JIM_OK; | |
| 13577 | + } | |
| 13578 | + Jim_SetResultFormatted(interp, ": without ? in expression: \"%#s\"", builder->exprObjPtr); | |
| 13579 | + return JIM_ERR; | |
| 13580 | + } | |
| 13581 | + if (builder->stack.len == exp_stacklen) { | |
| 13582 | + | |
| 13583 | + builder->token--; | |
| 13584 | + builder->level--; | |
| 13585 | + return JIM_OK; | |
| 13586 | + } | |
| 13587 | + | |
| 13588 | + } | |
| 13589 | + else if (TOKEN_IS_EXPR_OP(t->type)) { | |
| 13590 | + const struct Jim_ExprOperator *op; | |
| 13591 | + | |
| 13592 | + | |
| 13593 | + if (TOKEN_IS_EXPR_OP(prevtt) || TOKEN_IS_EXPR_START(prevtt)) { | |
| 13594 | + if (t->type == JIM_EXPROP_SUB) { | |
| 13595 | + t->type = JIM_EXPROP_UNARYMINUS; | |
| 13596 | + } | |
| 13597 | + else if (t->type == JIM_EXPROP_ADD) { | |
| 13598 | + t->type = JIM_EXPROP_UNARYPLUS; | |
| 13599 | + } | |
| 13600 | + } | |
| 13601 | + | |
| 13602 | + op = JimExprOperatorInfoByOpcode(t->type); | |
| 13603 | + | |
| 13604 | + if (op->precedence < precedence || (!(op->attr & OP_RIGHT_ASSOC) && op->precedence == precedence)) { | |
| 13605 | + | |
| 13606 | + builder->token--; | |
| 13607 | + break; | |
| 13608 | + } | |
| 13609 | + | |
| 13610 | + if (op->attr & OP_FUNC) { | |
| 13611 | + if (builder->token->type != JIM_TT_SUBEXPR_START) { | |
| 13612 | + Jim_SetResultString(interp, "missing arguments for math function", -1); | |
| 13613 | + return JIM_ERR; | |
| 13614 | + } | |
| 13615 | + builder->token++; | |
| 13616 | + if (op->arity == 0) { | |
| 13617 | + if (builder->token->type != JIM_TT_SUBEXPR_END) { | |
| 13618 | + Jim_SetResultString(interp, "too many arguments for math function", -1); | |
| 13619 | + return JIM_ERR; | |
| 13620 | + } | |
| 13621 | + builder->token++; | |
| 13622 | + goto noargs; | |
| 13623 | + } | |
| 13624 | + builder->parencount++; | |
| 13625 | + | |
| 13626 | + | |
| 13627 | + rc = ExprTreeBuildTree(interp, builder, 0, EXPR_FUNC_ARGS | EXPR_UNTIL_CLOSE, op->arity); | |
| 13628 | + } | |
| 13629 | + else if (t->type == JIM_EXPROP_TERNARY) { | |
| 13630 | + | |
| 13631 | + rc = ExprTreeBuildTree(interp, builder, op->precedence, EXPR_TERNARY, 2); | |
| 13632 | + } | |
| 13633 | + else { | |
| 13634 | + rc = ExprTreeBuildTree(interp, builder, op->precedence, 0, 1); | |
| 13635 | + } | |
| 13636 | + | |
| 13637 | + if (rc != JIM_OK) { | |
| 13638 | + return rc; | |
| 13639 | + } | |
| 13640 | + | |
| 13641 | +noargs: | |
| 13642 | + node = builder->next++; | |
| 13643 | + node->type = t->type; | |
| 13644 | + | |
| 13645 | + if (op->arity >= 3) { | |
| 13646 | + node->ternary = Jim_StackPop(&builder->stack); | |
| 13647 | + if (node->ternary == NULL) { | |
| 13648 | + goto missingoperand; | |
| 13649 | + } | |
| 13650 | + } | |
| 13651 | + if (op->arity >= 2) { | |
| 13652 | + node->right = Jim_StackPop(&builder->stack); | |
| 13653 | + if (node->right == NULL) { | |
| 13654 | + goto missingoperand; | |
| 13655 | + } | |
| 13656 | + } | |
| 13657 | + if (op->arity >= 1) { | |
| 13658 | + node->left = Jim_StackPop(&builder->stack); | |
| 13659 | + if (node->left == NULL) { | |
| 13660 | +missingoperand: | |
| 13661 | + Jim_SetResultFormatted(interp, "missing operand to %s in expression: \"%#s\"", op->name, builder->exprObjPtr); | |
| 13662 | + builder->next--; | |
| 13663 | + return JIM_ERR; | |
| 13664 | + | |
| 13665 | + } | |
| 13666 | + } | |
| 13667 | + | |
| 13668 | + | |
| 13669 | + Jim_StackPush(&builder->stack, node); | |
| 13670 | + } | |
| 13671 | + else { | |
| 13672 | + Jim_Obj *objPtr = NULL; | |
| 13673 | + | |
| 13674 | + | |
| 13675 | + | |
| 13676 | + | |
| 13677 | + if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) { | |
| 13678 | + Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", builder->exprObjPtr); | |
| 13679 | + return JIM_ERR; | |
| 13680 | + } | |
| 13681 | + | |
| 13682 | + | |
| 13683 | + if (t->type == JIM_TT_EXPR_INT || t->type == JIM_TT_EXPR_DOUBLE) { | |
| 13684 | + char *endptr; | |
| 13685 | + if (t->type == JIM_TT_EXPR_INT) { | |
| 13686 | + objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr)); | |
| 13687 | + } | |
| 13688 | + else { | |
| 13689 | + objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr)); | |
| 13690 | + } | |
| 13691 | + if (endptr != t->token + t->len) { | |
| 13692 | + | |
| 13693 | + Jim_FreeNewObj(interp, objPtr); | |
| 13694 | + objPtr = NULL; | |
| 13695 | + } | |
| 13696 | + } | |
| 13697 | + | |
| 13698 | + if (!objPtr) { | |
| 13699 | + | |
| 13700 | + objPtr = Jim_NewStringObj(interp, t->token, t->len); | |
| 13701 | + if (t->type == JIM_TT_CMD) { | |
| 13702 | + | |
| 13703 | + JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line); | |
| 13704 | + } | |
| 13705 | + } | |
| 13706 | + | |
| 13707 | + | |
| 13708 | + node = builder->next++; | |
| 13709 | + node->objPtr = objPtr; | |
| 13710 | + Jim_IncrRefCount(node->objPtr); | |
| 13711 | + node->type = t->type; | |
| 13712 | + Jim_StackPush(&builder->stack, node); | |
| 13713 | + } | |
| 13714 | + } | |
| 13715 | + | |
| 13716 | + if (builder->stack.len == exp_stacklen) { | |
| 13717 | + builder->level--; | |
| 13718 | + return JIM_OK; | |
| 13719 | + } | |
| 13720 | + | |
| 13721 | + if ((flags & EXPR_FUNC_ARGS)) { | |
| 13722 | + Jim_SetResultFormatted(interp, "too %s arguments for math function", (builder->stack.len < exp_stacklen) ? "few" : "many"); | |
| 13723 | + } | |
| 13724 | + else { | |
| 13725 | + if (builder->stack.len < exp_stacklen) { | |
| 13726 | + if (builder->level == 0) { | |
| 13727 | + Jim_SetResultFormatted(interp, "empty expression"); | |
| 13728 | + } | |
| 13729 | + else { | |
| 13730 | + Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": premature end of expression", builder->exprObjPtr); | |
| 13731 | + } | |
| 13732 | + } | |
| 13733 | + else { | |
| 13734 | + Jim_SetResultFormatted(interp, "extra terms after expression"); | |
| 13735 | + } | |
| 13736 | + } | |
| 13737 | + | |
| 13738 | + return JIM_ERR; | |
| 13739 | +} | |
| 13740 | + | |
| 13741 | +static struct ExprTree *ExprTreeCreateTree(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj) | |
| 13742 | +{ | |
| 13743 | + struct ExprTree *expr; | |
| 13744 | + struct ExprBuilder builder; | |
| 13745 | + int rc; | |
| 13746 | + struct JimExprNode *top; | |
| 13747 | + | |
| 13748 | + builder.parencount = 0; | |
| 13749 | + builder.level = 0; | |
| 13750 | + builder.token = builder.first_token = tokenlist->list; | |
| 13751 | + builder.exprObjPtr = exprObjPtr; | |
| 13752 | + builder.fileNameObj = fileNameObj; | |
| 13753 | + | |
| 13754 | + builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1)); | |
| 13755 | + memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1)); | |
| 13756 | + builder.next = builder.nodes; | |
| 13757 | + Jim_InitStack(&builder.stack); | |
| 13758 | + | |
| 13759 | + rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1); | |
| 13760 | + | |
| 13761 | + if (rc == JIM_OK) { | |
| 13762 | + top = Jim_StackPop(&builder.stack); | |
| 13763 | + | |
| 13764 | + if (builder.parencount) { | |
| 13765 | + Jim_SetResultString(interp, "missing close parenthesis", -1); | |
| 13766 | + rc = JIM_ERR; | |
| 13767 | + } | |
| 13768 | + } | |
| 13769 | + | |
| 13770 | + | |
| 13771 | + Jim_FreeStack(&builder.stack); | |
| 13772 | + | |
| 13773 | + if (rc != JIM_OK) { | |
| 13774 | + ExprTreeFreeNodes(interp, builder.nodes, builder.next - builder.nodes); | |
| 13775 | + return NULL; | |
| 13776 | + } | |
| 13805 | 13777 | |
| 13806 | 13778 | expr = Jim_Alloc(sizeof(*expr)); |
| 13807 | 13779 | expr->inUse = 1; |
| 13808 | - expr->len = 0; | |
| 13809 | - | |
| 13810 | - Jim_InitStack(&stack); | |
| 13811 | - | |
| 13812 | - for (i = 0; i < tokenlist->count; i++) { | |
| 13813 | - ParseToken *t = &tokenlist->list[i]; | |
| 13814 | - const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); | |
| 13815 | - | |
| 13816 | - if (op->lazy == LAZY_OP) { | |
| 13817 | - count += 2; | |
| 13818 | - | |
| 13819 | - if (t->type == JIM_EXPROP_TERNARY) { | |
| 13820 | - have_ternary = 1; | |
| 13821 | - } | |
| 13822 | - } | |
| 13823 | - } | |
| 13824 | - | |
| 13825 | - expr->token = Jim_Alloc(sizeof(ScriptToken) * count); | |
| 13826 | - | |
| 13827 | - for (i = 0; i < tokenlist->count && ok; i++) { | |
| 13828 | - ParseToken *t = &tokenlist->list[i]; | |
| 13829 | - | |
| 13830 | - | |
| 13831 | - struct ScriptToken *token = &expr->token[expr->len]; | |
| 13832 | - | |
| 13833 | - if (t->type == JIM_TT_EOL) { | |
| 13834 | - break; | |
| 13835 | - } | |
| 13836 | - | |
| 13837 | - switch (t->type) { | |
| 13838 | - case JIM_TT_STR: | |
| 13839 | - case JIM_TT_ESC: | |
| 13840 | - case JIM_TT_VAR: | |
| 13841 | - case JIM_TT_DICTSUGAR: | |
| 13842 | - case JIM_TT_EXPRSUGAR: | |
| 13843 | - case JIM_TT_CMD: | |
| 13844 | - token->type = t->type; | |
| 13845 | -strexpr: | |
| 13846 | - token->objPtr = Jim_NewStringObj(interp, t->token, t->len); | |
| 13847 | - if (t->type == JIM_TT_CMD) { | |
| 13848 | - | |
| 13849 | - JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line); | |
| 13850 | - } | |
| 13851 | - expr->len++; | |
| 13852 | - break; | |
| 13853 | - | |
| 13854 | - case JIM_TT_EXPR_INT: | |
| 13855 | - case JIM_TT_EXPR_DOUBLE: | |
| 13856 | - { | |
| 13857 | - char *endptr; | |
| 13858 | - if (t->type == JIM_TT_EXPR_INT) { | |
| 13859 | - token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr)); | |
| 13860 | - } | |
| 13861 | - else { | |
| 13862 | - token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr)); | |
| 13863 | - } | |
| 13864 | - if (endptr != t->token + t->len) { | |
| 13865 | - | |
| 13866 | - Jim_FreeNewObj(interp, token->objPtr); | |
| 13867 | - token->type = JIM_TT_STR; | |
| 13868 | - goto strexpr; | |
| 13869 | - } | |
| 13870 | - token->type = t->type; | |
| 13871 | - expr->len++; | |
| 13872 | - } | |
| 13873 | - break; | |
| 13874 | - | |
| 13875 | - case JIM_TT_SUBEXPR_START: | |
| 13876 | - Jim_StackPush(&stack, t); | |
| 13877 | - prevtt = JIM_TT_NONE; | |
| 13878 | - continue; | |
| 13879 | - | |
| 13880 | - case JIM_TT_SUBEXPR_COMMA: | |
| 13881 | - | |
| 13882 | - continue; | |
| 13883 | - | |
| 13884 | - case JIM_TT_SUBEXPR_END: | |
| 13885 | - ok = 0; | |
| 13886 | - while (Jim_StackLen(&stack)) { | |
| 13887 | - ParseToken *tt = Jim_StackPop(&stack); | |
| 13888 | - | |
| 13889 | - if (tt->type == JIM_TT_SUBEXPR_START) { | |
| 13890 | - ok = 1; | |
| 13891 | - break; | |
| 13892 | - } | |
| 13893 | - | |
| 13894 | - if (ExprAddOperator(interp, expr, tt) != JIM_OK) { | |
| 13895 | - goto err; | |
| 13896 | - } | |
| 13897 | - } | |
| 13898 | - if (!ok) { | |
| 13899 | - Jim_SetResultString(interp, "Unexpected close parenthesis", -1); | |
| 13900 | - goto err; | |
| 13901 | - } | |
| 13902 | - break; | |
| 13903 | - | |
| 13904 | - | |
| 13905 | - default:{ | |
| 13906 | - | |
| 13907 | - const struct Jim_ExprOperator *op; | |
| 13908 | - ParseToken *tt; | |
| 13909 | - | |
| 13910 | - | |
| 13911 | - if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) { | |
| 13912 | - if (t->type == JIM_EXPROP_SUB) { | |
| 13913 | - t->type = JIM_EXPROP_UNARYMINUS; | |
| 13914 | - } | |
| 13915 | - else if (t->type == JIM_EXPROP_ADD) { | |
| 13916 | - t->type = JIM_EXPROP_UNARYPLUS; | |
| 13917 | - } | |
| 13918 | - } | |
| 13919 | - | |
| 13920 | - op = JimExprOperatorInfoByOpcode(t->type); | |
| 13921 | - | |
| 13922 | - | |
| 13923 | - while ((tt = Jim_StackPeek(&stack)) != NULL) { | |
| 13924 | - const struct Jim_ExprOperator *tt_op = | |
| 13925 | - JimExprOperatorInfoByOpcode(tt->type); | |
| 13926 | - | |
| 13927 | - | |
| 13928 | - | |
| 13929 | - if (op->arity != 1 && tt_op->precedence >= op->precedence) { | |
| 13930 | - if (ExprAddOperator(interp, expr, tt) != JIM_OK) { | |
| 13931 | - ok = 0; | |
| 13932 | - goto err; | |
| 13933 | - } | |
| 13934 | - Jim_StackPop(&stack); | |
| 13935 | - } | |
| 13936 | - else { | |
| 13937 | - break; | |
| 13938 | - } | |
| 13939 | - } | |
| 13940 | - Jim_StackPush(&stack, t); | |
| 13941 | - break; | |
| 13942 | - } | |
| 13943 | - } | |
| 13944 | - prevtt = t->type; | |
| 13945 | - } | |
| 13946 | - | |
| 13947 | - | |
| 13948 | - while (Jim_StackLen(&stack)) { | |
| 13949 | - ParseToken *tt = Jim_StackPop(&stack); | |
| 13950 | - | |
| 13951 | - if (tt->type == JIM_TT_SUBEXPR_START) { | |
| 13952 | - ok = 0; | |
| 13953 | - Jim_SetResultString(interp, "Missing close parenthesis", -1); | |
| 13954 | - goto err; | |
| 13955 | - } | |
| 13956 | - if (ExprAddOperator(interp, expr, tt) != JIM_OK) { | |
| 13957 | - ok = 0; | |
| 13958 | - goto err; | |
| 13959 | - } | |
| 13960 | - } | |
| 13961 | - | |
| 13962 | - if (have_ternary) { | |
| 13963 | - ExprTernaryReorderExpression(interp, expr); | |
| 13964 | - } | |
| 13965 | - | |
| 13966 | - err: | |
| 13967 | - | |
| 13968 | - Jim_FreeStack(&stack); | |
| 13969 | - | |
| 13970 | - for (i = 0; i < expr->len; i++) { | |
| 13971 | - Jim_IncrRefCount(expr->token[i].objPtr); | |
| 13972 | - } | |
| 13973 | - | |
| 13974 | - if (!ok) { | |
| 13975 | - ExprFreeByteCode(interp, expr); | |
| 13976 | - return NULL; | |
| 13977 | - } | |
| 13780 | + expr->expr = top; | |
| 13781 | + expr->nodes = builder.nodes; | |
| 13782 | + expr->len = builder.next - builder.nodes; | |
| 13783 | + | |
| 13784 | + assert(expr->len <= tokenlist->count - 1); | |
| 13978 | 13785 | |
| 13979 | 13786 | return expr; |
| 13980 | 13787 | } |
| 13981 | - | |
| 13982 | 13788 | |
| 13983 | 13789 | static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) |
| 13984 | 13790 | { |
| 13985 | 13791 | int exprTextLen; |
| 13986 | 13792 | const char *exprText; |
| 13987 | 13793 | struct JimParserCtx parser; |
| 13988 | - struct ExprByteCode *expr; | |
| 13794 | + struct ExprTree *expr; | |
| 13989 | 13795 | ParseTokenList tokenlist; |
| 13990 | 13796 | int line; |
| 13991 | 13797 | Jim_Obj *fileNameObj; |
| 13992 | 13798 | int rc = JIM_ERR; |
| 13993 | 13799 | |
| 13994 | - | |
| 13800 | + | |
| 13995 | 13801 | if (objPtr->typePtr == &sourceObjType) { |
| 13996 | 13802 | fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 13997 | 13803 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 13998 | 13804 | } |
| 13999 | 13805 | else { |
| @@ -14002,18 +13808,17 @@ | ||
| 14002 | 13808 | } |
| 14003 | 13809 | Jim_IncrRefCount(fileNameObj); |
| 14004 | 13810 | |
| 14005 | 13811 | exprText = Jim_GetString(objPtr, &exprTextLen); |
| 14006 | 13812 | |
| 14007 | - | |
| 13813 | + | |
| 14008 | 13814 | ScriptTokenListInit(&tokenlist); |
| 14009 | 13815 | |
| 14010 | 13816 | JimParserInit(&parser, exprText, exprTextLen, line); |
| 14011 | 13817 | while (!parser.eof) { |
| 14012 | 13818 | if (JimParseExpression(&parser) != JIM_OK) { |
| 14013 | 13819 | ScriptTokenListFree(&tokenlist); |
| 14014 | - invalidexpr: | |
| 14015 | 13820 | Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr); |
| 14016 | 13821 | expr = NULL; |
| 14017 | 13822 | goto err; |
| 14018 | 13823 | } |
| 14019 | 13824 | |
| @@ -14036,125 +13841,174 @@ | ||
| 14036 | 13841 | ScriptTokenListFree(&tokenlist); |
| 14037 | 13842 | Jim_DecrRefCount(interp, fileNameObj); |
| 14038 | 13843 | return JIM_ERR; |
| 14039 | 13844 | } |
| 14040 | 13845 | |
| 14041 | - | |
| 14042 | - expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); | |
| 14043 | 13846 | |
| 14044 | - | |
| 13847 | + expr = ExprTreeCreateTree(interp, &tokenlist, objPtr, fileNameObj); | |
| 13848 | + | |
| 13849 | + | |
| 14045 | 13850 | ScriptTokenListFree(&tokenlist); |
| 14046 | 13851 | |
| 14047 | 13852 | if (!expr) { |
| 14048 | 13853 | goto err; |
| 14049 | 13854 | } |
| 14050 | 13855 | |
| 14051 | 13856 | #ifdef DEBUG_SHOW_EXPR |
| 14052 | - { | |
| 14053 | - int i; | |
| 14054 | - | |
| 14055 | - printf("==== Expr ====\n"); | |
| 14056 | - for (i = 0; i < expr->len; i++) { | |
| 14057 | - ScriptToken *t = &expr->token[i]; | |
| 14058 | - | |
| 14059 | - printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); | |
| 14060 | - } | |
| 14061 | - } | |
| 13857 | + printf("==== Expr ====\n"); | |
| 13858 | + JimShowExprNode(expr->expr, 0); | |
| 14062 | 13859 | #endif |
| 14063 | 13860 | |
| 14064 | - | |
| 14065 | - if (ExprCheckCorrectness(expr) != JIM_OK) { | |
| 14066 | - ExprFreeByteCode(interp, expr); | |
| 14067 | - goto invalidexpr; | |
| 14068 | - } | |
| 14069 | - | |
| 14070 | 13861 | rc = JIM_OK; |
| 14071 | 13862 | |
| 14072 | 13863 | err: |
| 14073 | - | |
| 13864 | + | |
| 14074 | 13865 | Jim_DecrRefCount(interp, fileNameObj); |
| 14075 | 13866 | Jim_FreeIntRep(interp, objPtr); |
| 14076 | 13867 | Jim_SetIntRepPtr(objPtr, expr); |
| 14077 | 13868 | objPtr->typePtr = &exprObjType; |
| 14078 | 13869 | return rc; |
| 14079 | 13870 | } |
| 14080 | 13871 | |
| 14081 | -static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 13872 | +static struct ExprTree *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) | |
| 14082 | 13873 | { |
| 14083 | 13874 | if (objPtr->typePtr != &exprObjType) { |
| 14084 | 13875 | if (SetExprFromAny(interp, objPtr) != JIM_OK) { |
| 14085 | 13876 | return NULL; |
| 14086 | 13877 | } |
| 14087 | 13878 | } |
| 14088 | - return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); | |
| 13879 | + return (struct ExprTree *) Jim_GetIntRepPtr(objPtr); | |
| 14089 | 13880 | } |
| 14090 | 13881 | |
| 14091 | 13882 | #ifdef JIM_OPTIMIZATION |
| 14092 | -static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token) | |
| 14093 | -{ | |
| 14094 | - if (token->type == JIM_TT_EXPR_INT) | |
| 14095 | - return token->objPtr; | |
| 14096 | - else if (token->type == JIM_TT_VAR) | |
| 14097 | - return Jim_GetVariable(interp, token->objPtr, JIM_NONE); | |
| 14098 | - else if (token->type == JIM_TT_DICTSUGAR) | |
| 14099 | - return JimExpandDictSugar(interp, token->objPtr); | |
| 13883 | +static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, struct JimExprNode *node) | |
| 13884 | +{ | |
| 13885 | + if (node->type == JIM_TT_EXPR_INT) | |
| 13886 | + return node->objPtr; | |
| 13887 | + else if (node->type == JIM_TT_VAR) | |
| 13888 | + return Jim_GetVariable(interp, node->objPtr, JIM_NONE); | |
| 13889 | + else if (node->type == JIM_TT_DICTSUGAR) | |
| 13890 | + return JimExpandDictSugar(interp, node->objPtr); | |
| 14100 | 13891 | else |
| 14101 | 13892 | return NULL; |
| 14102 | 13893 | } |
| 14103 | 13894 | #endif |
| 14104 | 13895 | |
| 14105 | -#define JIM_EE_STATICSTACK_LEN 10 | |
| 14106 | - | |
| 14107 | -int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) | |
| 14108 | -{ | |
| 14109 | - ExprByteCode *expr; | |
| 14110 | - Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN]; | |
| 14111 | - int i; | |
| 14112 | - int retcode = JIM_OK; | |
| 14113 | - struct JimExprState e; | |
| 13896 | + | |
| 13897 | +static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node) | |
| 13898 | +{ | |
| 13899 | + if (TOKEN_IS_EXPR_OP(node->type)) { | |
| 13900 | + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(node->type); | |
| 13901 | + return op->funcop(interp, node); | |
| 13902 | + } | |
| 13903 | + else { | |
| 13904 | + Jim_Obj *objPtr; | |
| 13905 | + | |
| 13906 | + | |
| 13907 | + switch (node->type) { | |
| 13908 | + case JIM_TT_EXPR_INT: | |
| 13909 | + case JIM_TT_EXPR_DOUBLE: | |
| 13910 | + case JIM_TT_EXPR_BOOLEAN: | |
| 13911 | + case JIM_TT_STR: | |
| 13912 | + Jim_SetResult(interp, node->objPtr); | |
| 13913 | + return JIM_OK; | |
| 13914 | + | |
| 13915 | + case JIM_TT_VAR: | |
| 13916 | + objPtr = Jim_GetVariable(interp, node->objPtr, JIM_ERRMSG); | |
| 13917 | + if (objPtr) { | |
| 13918 | + Jim_SetResult(interp, objPtr); | |
| 13919 | + return JIM_OK; | |
| 13920 | + } | |
| 13921 | + return JIM_ERR; | |
| 13922 | + | |
| 13923 | + case JIM_TT_DICTSUGAR: | |
| 13924 | + objPtr = JimExpandDictSugar(interp, node->objPtr); | |
| 13925 | + if (objPtr) { | |
| 13926 | + Jim_SetResult(interp, objPtr); | |
| 13927 | + return JIM_OK; | |
| 13928 | + } | |
| 13929 | + return JIM_ERR; | |
| 13930 | + | |
| 13931 | + case JIM_TT_ESC: | |
| 13932 | + if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) { | |
| 13933 | + Jim_SetResult(interp, objPtr); | |
| 13934 | + return JIM_OK; | |
| 13935 | + } | |
| 13936 | + return JIM_ERR; | |
| 13937 | + | |
| 13938 | + case JIM_TT_CMD: | |
| 13939 | + return Jim_EvalObj(interp, node->objPtr); | |
| 13940 | + | |
| 13941 | + default: | |
| 13942 | + | |
| 13943 | + return JIM_ERR; | |
| 13944 | + } | |
| 13945 | + } | |
| 13946 | +} | |
| 13947 | + | |
| 13948 | +static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr) | |
| 13949 | +{ | |
| 13950 | + int rc = JimExprEvalTermNode(interp, node); | |
| 13951 | + if (rc == JIM_OK) { | |
| 13952 | + *objPtrPtr = Jim_GetResult(interp); | |
| 13953 | + Jim_IncrRefCount(*objPtrPtr); | |
| 13954 | + } | |
| 13955 | + return rc; | |
| 13956 | +} | |
| 13957 | + | |
| 13958 | +static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node) | |
| 13959 | +{ | |
| 13960 | + if (JimExprEvalTermNode(interp, node) == JIM_OK) { | |
| 13961 | + return ExprBool(interp, Jim_GetResult(interp)); | |
| 13962 | + } | |
| 13963 | + return -1; | |
| 13964 | +} | |
| 13965 | + | |
| 13966 | +int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr) | |
| 13967 | +{ | |
| 13968 | + struct ExprTree *expr; | |
| 13969 | + int retcode = JIM_OK; | |
| 14114 | 13970 | |
| 14115 | 13971 | expr = JimGetExpression(interp, exprObjPtr); |
| 14116 | 13972 | if (!expr) { |
| 14117 | - return JIM_ERR; | |
| 13973 | + return JIM_ERR; | |
| 14118 | 13974 | } |
| 14119 | 13975 | |
| 14120 | 13976 | #ifdef JIM_OPTIMIZATION |
| 14121 | 13977 | { |
| 14122 | 13978 | Jim_Obj *objPtr; |
| 14123 | 13979 | |
| 14124 | 13980 | |
| 14125 | 13981 | switch (expr->len) { |
| 14126 | 13982 | case 1: |
| 14127 | - objPtr = JimExprIntValOrVar(interp, &expr->token[0]); | |
| 13983 | + objPtr = JimExprIntValOrVar(interp, expr->expr); | |
| 14128 | 13984 | if (objPtr) { |
| 14129 | - Jim_IncrRefCount(objPtr); | |
| 14130 | - *exprResultPtrPtr = objPtr; | |
| 13985 | + Jim_SetResult(interp, objPtr); | |
| 14131 | 13986 | return JIM_OK; |
| 14132 | 13987 | } |
| 14133 | 13988 | break; |
| 14134 | 13989 | |
| 14135 | 13990 | case 2: |
| 14136 | - if (expr->token[1].type == JIM_EXPROP_NOT) { | |
| 14137 | - objPtr = JimExprIntValOrVar(interp, &expr->token[0]); | |
| 13991 | + if (expr->expr->type == JIM_EXPROP_NOT) { | |
| 13992 | + objPtr = JimExprIntValOrVar(interp, expr->expr->left); | |
| 14138 | 13993 | |
| 14139 | 13994 | if (objPtr && JimIsWide(objPtr)) { |
| 14140 | - *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj; | |
| 14141 | - Jim_IncrRefCount(*exprResultPtrPtr); | |
| 13995 | + Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj); | |
| 14142 | 13996 | return JIM_OK; |
| 14143 | 13997 | } |
| 14144 | 13998 | } |
| 14145 | 13999 | break; |
| 14146 | 14000 | |
| 14147 | 14001 | case 3: |
| 14148 | - objPtr = JimExprIntValOrVar(interp, &expr->token[0]); | |
| 14002 | + objPtr = JimExprIntValOrVar(interp, expr->expr->left); | |
| 14149 | 14003 | if (objPtr && JimIsWide(objPtr)) { |
| 14150 | - Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]); | |
| 14004 | + Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, expr->expr->right); | |
| 14151 | 14005 | if (objPtr2 && JimIsWide(objPtr2)) { |
| 14152 | 14006 | jim_wide wideValueA = JimWideValue(objPtr); |
| 14153 | 14007 | jim_wide wideValueB = JimWideValue(objPtr2); |
| 14154 | 14008 | int cmpRes; |
| 14155 | - switch (expr->token[2].type) { | |
| 14009 | + switch (expr->expr->type) { | |
| 14156 | 14010 | case JIM_EXPROP_LT: |
| 14157 | 14011 | cmpRes = wideValueA < wideValueB; |
| 14158 | 14012 | break; |
| 14159 | 14013 | case JIM_EXPROP_LTE: |
| 14160 | 14014 | cmpRes = wideValueA <= wideValueB; |
| @@ -14172,12 +14026,11 @@ | ||
| 14172 | 14026 | cmpRes = wideValueA != wideValueB; |
| 14173 | 14027 | break; |
| 14174 | 14028 | default: |
| 14175 | 14029 | goto noopt; |
| 14176 | 14030 | } |
| 14177 | - *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj; | |
| 14178 | - Jim_IncrRefCount(*exprResultPtrPtr); | |
| 14031 | + Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj); | |
| 14179 | 14032 | return JIM_OK; |
| 14180 | 14033 | } |
| 14181 | 14034 | } |
| 14182 | 14035 | break; |
| 14183 | 14036 | } |
| @@ -14185,145 +14038,64 @@ | ||
| 14185 | 14038 | noopt: |
| 14186 | 14039 | #endif |
| 14187 | 14040 | |
| 14188 | 14041 | expr->inUse++; |
| 14189 | 14042 | |
| 14190 | - | |
| 14191 | - | |
| 14192 | - if (expr->len > JIM_EE_STATICSTACK_LEN) | |
| 14193 | - e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len); | |
| 14194 | - else | |
| 14195 | - e.stack = staticStack; | |
| 14196 | - | |
| 14197 | - e.stacklen = 0; | |
| 14198 | - | |
| 14199 | - | |
| 14200 | - for (i = 0; i < expr->len && retcode == JIM_OK; i++) { | |
| 14201 | - Jim_Obj *objPtr; | |
| 14202 | - | |
| 14203 | - switch (expr->token[i].type) { | |
| 14204 | - case JIM_TT_EXPR_INT: | |
| 14205 | - case JIM_TT_EXPR_DOUBLE: | |
| 14206 | - case JIM_TT_STR: | |
| 14207 | - ExprPush(&e, expr->token[i].objPtr); | |
| 14208 | - break; | |
| 14209 | - | |
| 14210 | - case JIM_TT_VAR: | |
| 14211 | - objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG); | |
| 14212 | - if (objPtr) { | |
| 14213 | - ExprPush(&e, objPtr); | |
| 14214 | - } | |
| 14215 | - else { | |
| 14216 | - retcode = JIM_ERR; | |
| 14217 | - } | |
| 14218 | - break; | |
| 14219 | - | |
| 14220 | - case JIM_TT_DICTSUGAR: | |
| 14221 | - objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr); | |
| 14222 | - if (objPtr) { | |
| 14223 | - ExprPush(&e, objPtr); | |
| 14224 | - } | |
| 14225 | - else { | |
| 14226 | - retcode = JIM_ERR; | |
| 14227 | - } | |
| 14228 | - break; | |
| 14229 | - | |
| 14230 | - case JIM_TT_ESC: | |
| 14231 | - retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE); | |
| 14232 | - if (retcode == JIM_OK) { | |
| 14233 | - ExprPush(&e, objPtr); | |
| 14234 | - } | |
| 14235 | - break; | |
| 14236 | - | |
| 14237 | - case JIM_TT_CMD: | |
| 14238 | - retcode = Jim_EvalObj(interp, expr->token[i].objPtr); | |
| 14239 | - if (retcode == JIM_OK) { | |
| 14240 | - ExprPush(&e, Jim_GetResult(interp)); | |
| 14241 | - } | |
| 14242 | - break; | |
| 14243 | - | |
| 14244 | - default:{ | |
| 14245 | - | |
| 14246 | - e.skip = 0; | |
| 14247 | - e.opcode = expr->token[i].type; | |
| 14248 | - | |
| 14249 | - retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e); | |
| 14250 | - | |
| 14251 | - i += e.skip; | |
| 14252 | - continue; | |
| 14253 | - } | |
| 14254 | - } | |
| 14255 | - } | |
| 14043 | + | |
| 14044 | + retcode = JimExprEvalTermNode(interp, expr->expr); | |
| 14256 | 14045 | |
| 14257 | 14046 | expr->inUse--; |
| 14258 | 14047 | |
| 14259 | - if (retcode == JIM_OK) { | |
| 14260 | - *exprResultPtrPtr = ExprPop(&e); | |
| 14261 | - } | |
| 14262 | - else { | |
| 14263 | - for (i = 0; i < e.stacklen; i++) { | |
| 14264 | - Jim_DecrRefCount(interp, e.stack[i]); | |
| 14265 | - } | |
| 14266 | - } | |
| 14267 | - if (e.stack != staticStack) { | |
| 14268 | - Jim_Free(e.stack); | |
| 14269 | - } | |
| 14270 | 14048 | return retcode; |
| 14271 | 14049 | } |
| 14272 | 14050 | |
| 14273 | 14051 | int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) |
| 14274 | 14052 | { |
| 14275 | - int retcode; | |
| 14276 | - jim_wide wideValue; | |
| 14277 | - double doubleValue; | |
| 14278 | - Jim_Obj *exprResultPtr; | |
| 14279 | - | |
| 14280 | - retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr); | |
| 14281 | - if (retcode != JIM_OK) | |
| 14282 | - return retcode; | |
| 14283 | - | |
| 14284 | - if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) { | |
| 14285 | - if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) { | |
| 14286 | - Jim_DecrRefCount(interp, exprResultPtr); | |
| 14287 | - return JIM_ERR; | |
| 14288 | - } | |
| 14289 | - else { | |
| 14290 | - Jim_DecrRefCount(interp, exprResultPtr); | |
| 14291 | - *boolPtr = doubleValue != 0; | |
| 14292 | - return JIM_OK; | |
| 14293 | - } | |
| 14294 | - } | |
| 14295 | - *boolPtr = wideValue != 0; | |
| 14296 | - | |
| 14297 | - Jim_DecrRefCount(interp, exprResultPtr); | |
| 14298 | - return JIM_OK; | |
| 14053 | + int retcode = Jim_EvalExpression(interp, exprObjPtr); | |
| 14054 | + | |
| 14055 | + if (retcode == JIM_OK) { | |
| 14056 | + switch (ExprBool(interp, Jim_GetResult(interp))) { | |
| 14057 | + case 0: | |
| 14058 | + *boolPtr = 0; | |
| 14059 | + break; | |
| 14060 | + | |
| 14061 | + case 1: | |
| 14062 | + *boolPtr = 1; | |
| 14063 | + break; | |
| 14064 | + | |
| 14065 | + case -1: | |
| 14066 | + retcode = JIM_ERR; | |
| 14067 | + break; | |
| 14068 | + } | |
| 14069 | + } | |
| 14070 | + return retcode; | |
| 14299 | 14071 | } |
| 14300 | 14072 | |
| 14301 | 14073 | |
| 14302 | 14074 | |
| 14303 | 14075 | |
| 14304 | 14076 | typedef struct ScanFmtPartDescr |
| 14305 | 14077 | { |
| 14306 | - char *arg; | |
| 14307 | - char *prefix; | |
| 14308 | - size_t width; | |
| 14309 | - int pos; | |
| 14310 | - char type; | |
| 14311 | - char modifier; | |
| 14078 | + const char *arg; | |
| 14079 | + const char *prefix; | |
| 14080 | + size_t width; | |
| 14081 | + int pos; | |
| 14082 | + char type; | |
| 14083 | + char modifier; | |
| 14312 | 14084 | } ScanFmtPartDescr; |
| 14313 | 14085 | |
| 14314 | 14086 | |
| 14315 | 14087 | typedef struct ScanFmtStringObj |
| 14316 | 14088 | { |
| 14317 | - jim_wide size; | |
| 14318 | - char *stringRep; | |
| 14319 | - size_t count; | |
| 14320 | - size_t convCount; | |
| 14321 | - size_t maxPos; | |
| 14322 | - const char *error; | |
| 14323 | - char *scratch; | |
| 14324 | - ScanFmtPartDescr descr[1]; | |
| 14089 | + jim_wide size; | |
| 14090 | + char *stringRep; | |
| 14091 | + size_t count; | |
| 14092 | + size_t convCount; | |
| 14093 | + size_t maxPos; | |
| 14094 | + const char *error; | |
| 14095 | + char *scratch; | |
| 14096 | + ScanFmtPartDescr descr[1]; | |
| 14325 | 14097 | } ScanFmtStringObj; |
| 14326 | 14098 | |
| 14327 | 14099 | |
| 14328 | 14100 | static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 14329 | 14101 | static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| @@ -14364,28 +14136,28 @@ | ||
| 14364 | 14136 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 14365 | 14137 | { |
| 14366 | 14138 | ScanFmtStringObj *fmtObj; |
| 14367 | 14139 | char *buffer; |
| 14368 | 14140 | int maxCount, i, approxSize, lastPos = -1; |
| 14369 | - const char *fmt = objPtr->bytes; | |
| 14370 | - int maxFmtLen = objPtr->length; | |
| 14141 | + const char *fmt = Jim_String(objPtr); | |
| 14142 | + int maxFmtLen = Jim_Length(objPtr); | |
| 14371 | 14143 | const char *fmtEnd = fmt + maxFmtLen; |
| 14372 | 14144 | int curr; |
| 14373 | 14145 | |
| 14374 | 14146 | Jim_FreeIntRep(interp, objPtr); |
| 14375 | - | |
| 14147 | + | |
| 14376 | 14148 | for (i = 0, maxCount = 0; i < maxFmtLen; ++i) |
| 14377 | 14149 | if (fmt[i] == '%') |
| 14378 | 14150 | ++maxCount; |
| 14379 | - | |
| 14380 | - approxSize = sizeof(ScanFmtStringObj) | |
| 14381 | - +(maxCount + 1) * sizeof(ScanFmtPartDescr) | |
| 14382 | - +maxFmtLen * sizeof(char) + 3 + 1 | |
| 14383 | - + maxFmtLen * sizeof(char) + 1 | |
| 14384 | - + maxFmtLen * sizeof(char) | |
| 14385 | - +(maxCount + 1) * sizeof(char) | |
| 14386 | - +1; | |
| 14151 | + | |
| 14152 | + approxSize = sizeof(ScanFmtStringObj) | |
| 14153 | + +(maxCount + 1) * sizeof(ScanFmtPartDescr) | |
| 14154 | + +maxFmtLen * sizeof(char) + 3 + 1 | |
| 14155 | + + maxFmtLen * sizeof(char) + 1 | |
| 14156 | + + maxFmtLen * sizeof(char) | |
| 14157 | + +(maxCount + 1) * sizeof(char) | |
| 14158 | + +1; | |
| 14387 | 14159 | fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize); |
| 14388 | 14160 | memset(fmtObj, 0, approxSize); |
| 14389 | 14161 | fmtObj->size = approxSize; |
| 14390 | 14162 | fmtObj->maxPos = 0; |
| 14391 | 14163 | fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1]; |
| @@ -14397,12 +14169,12 @@ | ||
| 14397 | 14169 | for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) { |
| 14398 | 14170 | int width = 0, skip; |
| 14399 | 14171 | ScanFmtPartDescr *descr = &fmtObj->descr[curr]; |
| 14400 | 14172 | |
| 14401 | 14173 | fmtObj->count++; |
| 14402 | - descr->width = 0; | |
| 14403 | - | |
| 14174 | + descr->width = 0; | |
| 14175 | + | |
| 14404 | 14176 | if (*fmt != '%' || fmt[1] == '%') { |
| 14405 | 14177 | descr->type = 0; |
| 14406 | 14178 | descr->prefix = &buffer[i]; |
| 14407 | 14179 | for (; fmt < fmtEnd; ++fmt) { |
| 14408 | 14180 | if (*fmt == '%') { |
| @@ -14412,65 +14184,70 @@ | ||
| 14412 | 14184 | } |
| 14413 | 14185 | buffer[i++] = *fmt; |
| 14414 | 14186 | } |
| 14415 | 14187 | buffer[i++] = 0; |
| 14416 | 14188 | } |
| 14417 | - | |
| 14189 | + | |
| 14418 | 14190 | ++fmt; |
| 14419 | - | |
| 14191 | + | |
| 14420 | 14192 | if (fmt >= fmtEnd) |
| 14421 | 14193 | goto done; |
| 14422 | - descr->pos = 0; | |
| 14194 | + descr->pos = 0; | |
| 14423 | 14195 | if (*fmt == '*') { |
| 14424 | - descr->pos = -1; | |
| 14196 | + descr->pos = -1; | |
| 14425 | 14197 | ++fmt; |
| 14426 | 14198 | } |
| 14427 | 14199 | else |
| 14428 | - fmtObj->convCount++; | |
| 14429 | - | |
| 14200 | + fmtObj->convCount++; | |
| 14201 | + | |
| 14430 | 14202 | if (sscanf(fmt, "%d%n", &width, &skip) == 1) { |
| 14431 | 14203 | fmt += skip; |
| 14432 | - | |
| 14204 | + | |
| 14433 | 14205 | if (descr->pos != -1 && *fmt == '$') { |
| 14434 | 14206 | int prev; |
| 14435 | 14207 | |
| 14436 | 14208 | ++fmt; |
| 14437 | 14209 | descr->pos = width; |
| 14438 | 14210 | width = 0; |
| 14439 | - | |
| 14211 | + | |
| 14440 | 14212 | if ((lastPos == 0 && descr->pos > 0) |
| 14441 | 14213 | || (lastPos > 0 && descr->pos == 0)) { |
| 14442 | 14214 | fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers"; |
| 14443 | 14215 | return JIM_ERR; |
| 14444 | 14216 | } |
| 14445 | - | |
| 14217 | + | |
| 14446 | 14218 | for (prev = 0; prev < curr; ++prev) { |
| 14447 | 14219 | if (fmtObj->descr[prev].pos == -1) |
| 14448 | 14220 | continue; |
| 14449 | 14221 | if (fmtObj->descr[prev].pos == descr->pos) { |
| 14450 | 14222 | fmtObj->error = |
| 14451 | 14223 | "variable is assigned by multiple \"%n$\" conversion specifiers"; |
| 14452 | 14224 | return JIM_ERR; |
| 14453 | 14225 | } |
| 14454 | 14226 | } |
| 14455 | - | |
| 14227 | + if (descr->pos < 0) { | |
| 14228 | + fmtObj->error = | |
| 14229 | + "\"%n$\" conversion specifier is negative"; | |
| 14230 | + return JIM_ERR; | |
| 14231 | + } | |
| 14232 | + | |
| 14456 | 14233 | if (sscanf(fmt, "%d%n", &width, &skip) == 1) { |
| 14457 | 14234 | descr->width = width; |
| 14458 | 14235 | fmt += skip; |
| 14459 | 14236 | } |
| 14460 | 14237 | if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) |
| 14461 | 14238 | fmtObj->maxPos = descr->pos; |
| 14462 | 14239 | } |
| 14463 | 14240 | else { |
| 14464 | - | |
| 14241 | + | |
| 14465 | 14242 | descr->width = width; |
| 14466 | 14243 | } |
| 14467 | 14244 | } |
| 14468 | - | |
| 14245 | + | |
| 14469 | 14246 | if (lastPos == -1) |
| 14470 | 14247 | lastPos = descr->pos; |
| 14471 | - | |
| 14248 | + | |
| 14472 | 14249 | if (*fmt == '[') { |
| 14473 | 14250 | int swapped = 1, beg = i, end, j; |
| 14474 | 14251 | |
| 14475 | 14252 | descr->type = '['; |
| 14476 | 14253 | descr->arg = &buffer[i]; |
| @@ -14485,11 +14262,11 @@ | ||
| 14485 | 14262 | fmtObj->error = "unmatched [ in format string"; |
| 14486 | 14263 | return JIM_ERR; |
| 14487 | 14264 | } |
| 14488 | 14265 | end = i; |
| 14489 | 14266 | buffer[i++] = 0; |
| 14490 | - | |
| 14267 | + | |
| 14491 | 14268 | while (swapped) { |
| 14492 | 14269 | swapped = 0; |
| 14493 | 14270 | for (j = beg + 1; j < end - 1; ++j) { |
| 14494 | 14271 | if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) { |
| 14495 | 14272 | char tmp = buffer[j - 1]; |
| @@ -14500,13 +14277,18 @@ | ||
| 14500 | 14277 | } |
| 14501 | 14278 | } |
| 14502 | 14279 | } |
| 14503 | 14280 | } |
| 14504 | 14281 | else { |
| 14505 | - | |
| 14506 | - if (strchr("hlL", *fmt) != 0) | |
| 14282 | + | |
| 14283 | + if (fmt < fmtEnd && strchr("hlL", *fmt)) | |
| 14507 | 14284 | descr->modifier = tolower((int)*fmt++); |
| 14285 | + | |
| 14286 | + if (fmt >= fmtEnd) { | |
| 14287 | + fmtObj->error = "missing scan conversion character"; | |
| 14288 | + return JIM_ERR; | |
| 14289 | + } | |
| 14508 | 14290 | |
| 14509 | 14291 | descr->type = *fmt; |
| 14510 | 14292 | if (strchr("efgcsndoxui", *fmt) == 0) { |
| 14511 | 14293 | fmtObj->error = "bad scan conversion character"; |
| 14512 | 14294 | return JIM_ERR; |
| @@ -14543,11 +14325,11 @@ | ||
| 14543 | 14325 | while (*str) { |
| 14544 | 14326 | int c; |
| 14545 | 14327 | int n; |
| 14546 | 14328 | |
| 14547 | 14329 | if (!sdescr && isspace(UCHAR(*str))) |
| 14548 | - break; | |
| 14330 | + break; | |
| 14549 | 14331 | |
| 14550 | 14332 | n = utf8_tounicode(str, &c); |
| 14551 | 14333 | if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) |
| 14552 | 14334 | break; |
| 14553 | 14335 | while (n--) |
| @@ -14566,89 +14348,89 @@ | ||
| 14566 | 14348 | size_t scanned = 0; |
| 14567 | 14349 | size_t anchor = pos; |
| 14568 | 14350 | int i; |
| 14569 | 14351 | Jim_Obj *tmpObj = NULL; |
| 14570 | 14352 | |
| 14571 | - | |
| 14353 | + | |
| 14572 | 14354 | *valObjPtr = 0; |
| 14573 | 14355 | if (descr->prefix) { |
| 14574 | 14356 | for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 14575 | - | |
| 14357 | + | |
| 14576 | 14358 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14577 | 14359 | while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 14578 | 14360 | ++pos; |
| 14579 | 14361 | else if (descr->prefix[i] != str[pos]) |
| 14580 | - break; | |
| 14362 | + break; | |
| 14581 | 14363 | else |
| 14582 | - ++pos; | |
| 14364 | + ++pos; | |
| 14583 | 14365 | } |
| 14584 | 14366 | if (pos >= strLen) { |
| 14585 | - return -1; | |
| 14367 | + return -1; | |
| 14586 | 14368 | } |
| 14587 | 14369 | else if (descr->prefix[i] != 0) |
| 14588 | - return 0; | |
| 14370 | + return 0; | |
| 14589 | 14371 | } |
| 14590 | - | |
| 14372 | + | |
| 14591 | 14373 | if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') |
| 14592 | 14374 | while (isspace(UCHAR(str[pos]))) |
| 14593 | 14375 | ++pos; |
| 14594 | - | |
| 14376 | + | |
| 14595 | 14377 | scanned = pos - anchor; |
| 14596 | 14378 | |
| 14597 | - | |
| 14379 | + | |
| 14598 | 14380 | if (descr->type == 'n') { |
| 14599 | - | |
| 14381 | + | |
| 14600 | 14382 | *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); |
| 14601 | 14383 | } |
| 14602 | 14384 | else if (pos >= strLen) { |
| 14603 | - | |
| 14385 | + | |
| 14604 | 14386 | return -1; |
| 14605 | 14387 | } |
| 14606 | 14388 | else if (descr->type == 'c') { |
| 14607 | 14389 | int c; |
| 14608 | 14390 | scanned += utf8_tounicode(&str[pos], &c); |
| 14609 | 14391 | *valObjPtr = Jim_NewIntObj(interp, c); |
| 14610 | 14392 | return scanned; |
| 14611 | 14393 | } |
| 14612 | 14394 | else { |
| 14613 | - | |
| 14395 | + | |
| 14614 | 14396 | if (descr->width > 0) { |
| 14615 | 14397 | size_t sLen = utf8_strlen(&str[pos], strLen - pos); |
| 14616 | 14398 | size_t tLen = descr->width > sLen ? sLen : descr->width; |
| 14617 | 14399 | |
| 14618 | 14400 | tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); |
| 14619 | 14401 | tok = tmpObj->bytes; |
| 14620 | 14402 | } |
| 14621 | 14403 | else { |
| 14622 | - | |
| 14404 | + | |
| 14623 | 14405 | tok = &str[pos]; |
| 14624 | 14406 | } |
| 14625 | 14407 | switch (descr->type) { |
| 14626 | 14408 | case 'd': |
| 14627 | 14409 | case 'o': |
| 14628 | 14410 | case 'x': |
| 14629 | 14411 | case 'u': |
| 14630 | 14412 | case 'i':{ |
| 14631 | - char *endp; | |
| 14413 | + char *endp; | |
| 14632 | 14414 | jim_wide w; |
| 14633 | 14415 | |
| 14634 | 14416 | int base = descr->type == 'o' ? 8 |
| 14635 | 14417 | : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10; |
| 14636 | 14418 | |
| 14637 | - | |
| 14419 | + | |
| 14638 | 14420 | if (base == 0) { |
| 14639 | 14421 | w = jim_strtoull(tok, &endp); |
| 14640 | 14422 | } |
| 14641 | 14423 | else { |
| 14642 | 14424 | w = strtoull(tok, &endp, base); |
| 14643 | 14425 | } |
| 14644 | 14426 | |
| 14645 | 14427 | if (endp != tok) { |
| 14646 | - | |
| 14428 | + | |
| 14647 | 14429 | *valObjPtr = Jim_NewIntObj(interp, w); |
| 14648 | 14430 | |
| 14649 | - | |
| 14431 | + | |
| 14650 | 14432 | scanned += endp - tok; |
| 14651 | 14433 | } |
| 14652 | 14434 | else { |
| 14653 | 14435 | scanned = *tok ? 0 : -1; |
| 14654 | 14436 | } |
| @@ -14665,13 +14447,13 @@ | ||
| 14665 | 14447 | case 'g':{ |
| 14666 | 14448 | char *endp; |
| 14667 | 14449 | double value = strtod(tok, &endp); |
| 14668 | 14450 | |
| 14669 | 14451 | if (endp != tok) { |
| 14670 | - | |
| 14452 | + | |
| 14671 | 14453 | *valObjPtr = Jim_NewDoubleObj(interp, value); |
| 14672 | - | |
| 14454 | + | |
| 14673 | 14455 | scanned += endp - tok; |
| 14674 | 14456 | } |
| 14675 | 14457 | else { |
| 14676 | 14458 | scanned = *tok ? 0 : -1; |
| 14677 | 14459 | } |
| @@ -14696,65 +14478,65 @@ | ||
| 14696 | 14478 | Jim_Obj **resultVec = 0; |
| 14697 | 14479 | int resultc; |
| 14698 | 14480 | Jim_Obj *emptyStr = 0; |
| 14699 | 14481 | ScanFmtStringObj *fmtObj; |
| 14700 | 14482 | |
| 14701 | - | |
| 14483 | + | |
| 14702 | 14484 | JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format")); |
| 14703 | 14485 | |
| 14704 | 14486 | fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr; |
| 14705 | - | |
| 14487 | + | |
| 14706 | 14488 | if (fmtObj->error != 0) { |
| 14707 | 14489 | if (flags & JIM_ERRMSG) |
| 14708 | 14490 | Jim_SetResultString(interp, fmtObj->error, -1); |
| 14709 | 14491 | return 0; |
| 14710 | 14492 | } |
| 14711 | - | |
| 14493 | + | |
| 14712 | 14494 | emptyStr = Jim_NewEmptyStringObj(interp); |
| 14713 | 14495 | Jim_IncrRefCount(emptyStr); |
| 14714 | - | |
| 14496 | + | |
| 14715 | 14497 | resultList = Jim_NewListObj(interp, NULL, 0); |
| 14716 | 14498 | if (fmtObj->maxPos > 0) { |
| 14717 | 14499 | for (i = 0; i < fmtObj->maxPos; ++i) |
| 14718 | 14500 | Jim_ListAppendElement(interp, resultList, emptyStr); |
| 14719 | 14501 | JimListGetElements(interp, resultList, &resultc, &resultVec); |
| 14720 | 14502 | } |
| 14721 | - | |
| 14503 | + | |
| 14722 | 14504 | for (i = 0, pos = 0; i < fmtObj->count; ++i) { |
| 14723 | 14505 | ScanFmtPartDescr *descr = &(fmtObj->descr[i]); |
| 14724 | 14506 | Jim_Obj *value = 0; |
| 14725 | 14507 | |
| 14726 | - | |
| 14508 | + | |
| 14727 | 14509 | if (descr->type == 0) |
| 14728 | 14510 | continue; |
| 14729 | - | |
| 14511 | + | |
| 14730 | 14512 | if (scanned > 0) |
| 14731 | 14513 | scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); |
| 14732 | - | |
| 14514 | + | |
| 14733 | 14515 | if (scanned == -1 && i == 0) |
| 14734 | 14516 | goto eof; |
| 14735 | - | |
| 14517 | + | |
| 14736 | 14518 | pos += scanned; |
| 14737 | 14519 | |
| 14738 | - | |
| 14520 | + | |
| 14739 | 14521 | if (value == 0) |
| 14740 | 14522 | value = Jim_NewEmptyStringObj(interp); |
| 14741 | - | |
| 14523 | + | |
| 14742 | 14524 | if (descr->pos == -1) { |
| 14743 | 14525 | Jim_FreeNewObj(interp, value); |
| 14744 | 14526 | } |
| 14745 | 14527 | else if (descr->pos == 0) |
| 14746 | - | |
| 14528 | + | |
| 14747 | 14529 | Jim_ListAppendElement(interp, resultList, value); |
| 14748 | 14530 | else if (resultVec[descr->pos - 1] == emptyStr) { |
| 14749 | - | |
| 14531 | + | |
| 14750 | 14532 | Jim_DecrRefCount(interp, resultVec[descr->pos - 1]); |
| 14751 | 14533 | Jim_IncrRefCount(value); |
| 14752 | 14534 | resultVec[descr->pos - 1] = value; |
| 14753 | 14535 | } |
| 14754 | 14536 | else { |
| 14755 | - | |
| 14537 | + | |
| 14756 | 14538 | Jim_FreeNewObj(interp, value); |
| 14757 | 14539 | goto err; |
| 14758 | 14540 | } |
| 14759 | 14541 | } |
| 14760 | 14542 | Jim_DecrRefCount(interp, emptyStr); |
| @@ -14792,15 +14574,15 @@ | ||
| 14792 | 14574 | { |
| 14793 | 14575 | Jim_PrngState *prng; |
| 14794 | 14576 | unsigned char *destByte = (unsigned char *)dest; |
| 14795 | 14577 | unsigned int si, sj, x; |
| 14796 | 14578 | |
| 14797 | - | |
| 14579 | + | |
| 14798 | 14580 | if (interp->prngState == NULL) |
| 14799 | 14581 | JimPrngInit(interp); |
| 14800 | 14582 | prng = interp->prngState; |
| 14801 | - | |
| 14583 | + | |
| 14802 | 14584 | for (x = 0; x < len; x++) { |
| 14803 | 14585 | prng->i = (prng->i + 1) & 0xff; |
| 14804 | 14586 | si = prng->sbox[prng->i]; |
| 14805 | 14587 | prng->j = (prng->j + si) & 0xff; |
| 14806 | 14588 | sj = prng->sbox[prng->j]; |
| @@ -14814,19 +14596,19 @@ | ||
| 14814 | 14596 | static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen) |
| 14815 | 14597 | { |
| 14816 | 14598 | int i; |
| 14817 | 14599 | Jim_PrngState *prng; |
| 14818 | 14600 | |
| 14819 | - | |
| 14601 | + | |
| 14820 | 14602 | if (interp->prngState == NULL) |
| 14821 | 14603 | JimPrngInit(interp); |
| 14822 | 14604 | prng = interp->prngState; |
| 14823 | 14605 | |
| 14824 | - | |
| 14606 | + | |
| 14825 | 14607 | for (i = 0; i < 256; i++) |
| 14826 | 14608 | prng->sbox[i] = i; |
| 14827 | - | |
| 14609 | + | |
| 14828 | 14610 | for (i = 0; i < seedLen; i++) { |
| 14829 | 14611 | unsigned char t; |
| 14830 | 14612 | |
| 14831 | 14613 | t = prng->sbox[i & 0xFF]; |
| 14832 | 14614 | prng->sbox[i & 0xFF] = prng->sbox[seed[i]]; |
| @@ -14853,11 +14635,11 @@ | ||
| 14853 | 14635 | if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) |
| 14854 | 14636 | return JIM_ERR; |
| 14855 | 14637 | } |
| 14856 | 14638 | intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 14857 | 14639 | if (!intObjPtr) { |
| 14858 | - | |
| 14640 | + | |
| 14859 | 14641 | wideValue = 0; |
| 14860 | 14642 | } |
| 14861 | 14643 | else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) { |
| 14862 | 14644 | return JIM_ERR; |
| 14863 | 14645 | } |
| @@ -14867,26 +14649,26 @@ | ||
| 14867 | 14649 | Jim_FreeNewObj(interp, intObjPtr); |
| 14868 | 14650 | return JIM_ERR; |
| 14869 | 14651 | } |
| 14870 | 14652 | } |
| 14871 | 14653 | else { |
| 14872 | - | |
| 14654 | + | |
| 14873 | 14655 | Jim_InvalidateStringRep(intObjPtr); |
| 14874 | 14656 | JimWideValue(intObjPtr) = wideValue + increment; |
| 14875 | 14657 | |
| 14876 | 14658 | if (argv[1]->typePtr != &variableObjType) { |
| 14877 | - | |
| 14659 | + | |
| 14878 | 14660 | Jim_SetVariable(interp, argv[1], intObjPtr); |
| 14879 | 14661 | } |
| 14880 | 14662 | } |
| 14881 | 14663 | Jim_SetResult(interp, intObjPtr); |
| 14882 | 14664 | return JIM_OK; |
| 14883 | 14665 | } |
| 14884 | 14666 | |
| 14885 | 14667 | |
| 14886 | -#define JIM_EVAL_SARGV_LEN 8 | |
| 14887 | -#define JIM_EVAL_SINTV_LEN 8 | |
| 14668 | +#define JIM_EVAL_SARGV_LEN 8 | |
| 14669 | +#define JIM_EVAL_SINTV_LEN 8 | |
| 14888 | 14670 | |
| 14889 | 14671 | |
| 14890 | 14672 | static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 14891 | 14673 | { |
| 14892 | 14674 | int retcode; |
| @@ -14894,16 +14676,16 @@ | ||
| 14894 | 14676 | if (interp->unknown_called > 50) { |
| 14895 | 14677 | return JIM_ERR; |
| 14896 | 14678 | } |
| 14897 | 14679 | |
| 14898 | 14680 | |
| 14899 | - | |
| 14681 | + | |
| 14900 | 14682 | if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) |
| 14901 | 14683 | return JIM_ERR; |
| 14902 | 14684 | |
| 14903 | 14685 | interp->unknown_called++; |
| 14904 | - | |
| 14686 | + | |
| 14905 | 14687 | retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv); |
| 14906 | 14688 | interp->unknown_called--; |
| 14907 | 14689 | |
| 14908 | 14690 | return retcode; |
| 14909 | 14691 | } |
| @@ -14910,10 +14692,11 @@ | ||
| 14910 | 14692 | |
| 14911 | 14693 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14912 | 14694 | { |
| 14913 | 14695 | int retcode; |
| 14914 | 14696 | Jim_Cmd *cmdPtr; |
| 14697 | + void *prevPrivData; | |
| 14915 | 14698 | |
| 14916 | 14699 | #if 0 |
| 14917 | 14700 | printf("invoke"); |
| 14918 | 14701 | int j; |
| 14919 | 14702 | for (j = 0; j < objc; j++) { |
| @@ -14921,11 +14704,11 @@ | ||
| 14921 | 14704 | } |
| 14922 | 14705 | printf("\n"); |
| 14923 | 14706 | #endif |
| 14924 | 14707 | |
| 14925 | 14708 | if (interp->framePtr->tailcallCmd) { |
| 14926 | - | |
| 14709 | + | |
| 14927 | 14710 | cmdPtr = interp->framePtr->tailcallCmd; |
| 14928 | 14711 | interp->framePtr->tailcallCmd = NULL; |
| 14929 | 14712 | } |
| 14930 | 14713 | else { |
| 14931 | 14714 | cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| @@ -14939,20 +14722,22 @@ | ||
| 14939 | 14722 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14940 | 14723 | retcode = JIM_ERR; |
| 14941 | 14724 | goto out; |
| 14942 | 14725 | } |
| 14943 | 14726 | interp->evalDepth++; |
| 14727 | + prevPrivData = interp->cmdPrivData; | |
| 14944 | 14728 | |
| 14945 | - | |
| 14729 | + | |
| 14946 | 14730 | Jim_SetEmptyResult(interp); |
| 14947 | 14731 | if (cmdPtr->isproc) { |
| 14948 | 14732 | retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14949 | 14733 | } |
| 14950 | 14734 | else { |
| 14951 | 14735 | interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14952 | 14736 | retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14953 | 14737 | } |
| 14738 | + interp->cmdPrivData = prevPrivData; | |
| 14954 | 14739 | interp->evalDepth--; |
| 14955 | 14740 | |
| 14956 | 14741 | out: |
| 14957 | 14742 | JimDecrCmdRefCount(interp, cmdPtr); |
| 14958 | 14743 | |
| @@ -14961,17 +14746,17 @@ | ||
| 14961 | 14746 | |
| 14962 | 14747 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14963 | 14748 | { |
| 14964 | 14749 | int i, retcode; |
| 14965 | 14750 | |
| 14966 | - | |
| 14751 | + | |
| 14967 | 14752 | for (i = 0; i < objc; i++) |
| 14968 | 14753 | Jim_IncrRefCount(objv[i]); |
| 14969 | 14754 | |
| 14970 | 14755 | retcode = JimInvokeCommand(interp, objc, objv); |
| 14971 | 14756 | |
| 14972 | - | |
| 14757 | + | |
| 14973 | 14758 | for (i = 0; i < objc; i++) |
| 14974 | 14759 | Jim_DecrRefCount(interp, objv[i]); |
| 14975 | 14760 | |
| 14976 | 14761 | return retcode; |
| 14977 | 14762 | } |
| @@ -14989,25 +14774,25 @@ | ||
| 14989 | 14774 | } |
| 14990 | 14775 | |
| 14991 | 14776 | static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script) |
| 14992 | 14777 | { |
| 14993 | 14778 | if (!interp->errorFlag) { |
| 14994 | - | |
| 14779 | + | |
| 14995 | 14780 | interp->errorFlag = 1; |
| 14996 | 14781 | Jim_IncrRefCount(script->fileNameObj); |
| 14997 | 14782 | Jim_DecrRefCount(interp, interp->errorFileNameObj); |
| 14998 | 14783 | interp->errorFileNameObj = script->fileNameObj; |
| 14999 | 14784 | interp->errorLine = script->linenr; |
| 15000 | 14785 | |
| 15001 | 14786 | JimResetStackTrace(interp); |
| 15002 | - | |
| 14787 | + | |
| 15003 | 14788 | interp->addStackTrace++; |
| 15004 | 14789 | } |
| 15005 | 14790 | |
| 15006 | - | |
| 14791 | + | |
| 15007 | 14792 | if (interp->addStackTrace > 0) { |
| 15008 | - | |
| 14793 | + | |
| 15009 | 14794 | |
| 15010 | 14795 | JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr); |
| 15011 | 14796 | |
| 15012 | 14797 | if (Jim_Length(script->fileNameObj)) { |
| 15013 | 14798 | interp->addStackTrace = 0; |
| @@ -15042,14 +14827,14 @@ | ||
| 15042 | 14827 | case JIM_OK: |
| 15043 | 14828 | case JIM_RETURN: |
| 15044 | 14829 | objPtr = interp->result; |
| 15045 | 14830 | break; |
| 15046 | 14831 | case JIM_BREAK: |
| 15047 | - | |
| 14832 | + | |
| 15048 | 14833 | return JIM_BREAK; |
| 15049 | 14834 | case JIM_CONTINUE: |
| 15050 | - | |
| 14835 | + | |
| 15051 | 14836 | return JIM_CONTINUE; |
| 15052 | 14837 | default: |
| 15053 | 14838 | return JIM_ERR; |
| 15054 | 14839 | } |
| 15055 | 14840 | break; |
| @@ -15084,23 +14869,23 @@ | ||
| 15084 | 14869 | case JIM_OK: |
| 15085 | 14870 | case JIM_RETURN: |
| 15086 | 14871 | break; |
| 15087 | 14872 | case JIM_BREAK: |
| 15088 | 14873 | if (flags & JIM_SUBST_FLAG) { |
| 15089 | - | |
| 14874 | + | |
| 15090 | 14875 | tokens = i; |
| 15091 | 14876 | continue; |
| 15092 | 14877 | } |
| 15093 | - | |
| 15094 | - | |
| 14878 | + | |
| 14879 | + | |
| 15095 | 14880 | case JIM_CONTINUE: |
| 15096 | 14881 | if (flags & JIM_SUBST_FLAG) { |
| 15097 | 14882 | intv[i] = NULL; |
| 15098 | 14883 | continue; |
| 15099 | 14884 | } |
| 15100 | - | |
| 15101 | - | |
| 14885 | + | |
| 14886 | + | |
| 15102 | 14887 | default: |
| 15103 | 14888 | while (i--) { |
| 15104 | 14889 | Jim_DecrRefCount(interp, intv[i]); |
| 15105 | 14890 | } |
| 15106 | 14891 | if (intv != sintv) { |
| @@ -15111,28 +14896,29 @@ | ||
| 15111 | 14896 | Jim_IncrRefCount(intv[i]); |
| 15112 | 14897 | Jim_String(intv[i]); |
| 15113 | 14898 | totlen += intv[i]->length; |
| 15114 | 14899 | } |
| 15115 | 14900 | |
| 15116 | - | |
| 14901 | + | |
| 15117 | 14902 | if (tokens == 1 && intv[0] && intv == sintv) { |
| 15118 | - Jim_DecrRefCount(interp, intv[0]); | |
| 14903 | + | |
| 14904 | + intv[0]->refCount--; | |
| 15119 | 14905 | return intv[0]; |
| 15120 | 14906 | } |
| 15121 | 14907 | |
| 15122 | 14908 | objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); |
| 15123 | 14909 | |
| 15124 | 14910 | if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC |
| 15125 | 14911 | && token[2].type == JIM_TT_VAR) { |
| 15126 | - | |
| 14912 | + | |
| 15127 | 14913 | objPtr->typePtr = &interpolatedObjType; |
| 15128 | 14914 | objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; |
| 15129 | 14915 | objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; |
| 15130 | 14916 | Jim_IncrRefCount(intv[2]); |
| 15131 | 14917 | } |
| 15132 | 14918 | else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { |
| 15133 | - | |
| 14919 | + | |
| 15134 | 14920 | JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); |
| 15135 | 14921 | } |
| 15136 | 14922 | |
| 15137 | 14923 | |
| 15138 | 14924 | s = objPtr->bytes = Jim_Alloc(totlen + 1); |
| @@ -15143,11 +14929,11 @@ | ||
| 15143 | 14929 | s += intv[i]->length; |
| 15144 | 14930 | Jim_DecrRefCount(interp, intv[i]); |
| 15145 | 14931 | } |
| 15146 | 14932 | } |
| 15147 | 14933 | objPtr->bytes[totlen] = '\0'; |
| 15148 | - | |
| 14934 | + | |
| 15149 | 14935 | if (intv != sintv) { |
| 15150 | 14936 | Jim_Free(intv); |
| 15151 | 14937 | } |
| 15152 | 14938 | |
| 15153 | 14939 | return objPtr; |
| @@ -15187,11 +14973,11 @@ | ||
| 15187 | 14973 | |
| 15188 | 14974 | if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { |
| 15189 | 14975 | return JimEvalObjList(interp, scriptObjPtr); |
| 15190 | 14976 | } |
| 15191 | 14977 | |
| 15192 | - Jim_IncrRefCount(scriptObjPtr); | |
| 14978 | + Jim_IncrRefCount(scriptObjPtr); | |
| 15193 | 14979 | script = JimGetScript(interp, scriptObjPtr); |
| 15194 | 14980 | if (!JimScriptValid(interp, script)) { |
| 15195 | 14981 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15196 | 14982 | return JIM_ERR; |
| 15197 | 14983 | } |
| @@ -15223,11 +15009,11 @@ | ||
| 15223 | 15009 | } |
| 15224 | 15010 | #endif |
| 15225 | 15011 | |
| 15226 | 15012 | script->inUse++; |
| 15227 | 15013 | |
| 15228 | - | |
| 15014 | + | |
| 15229 | 15015 | prevScriptObj = interp->currentScriptObj; |
| 15230 | 15016 | interp->currentScriptObj = scriptObjPtr; |
| 15231 | 15017 | |
| 15232 | 15018 | interp->errorFlag = 0; |
| 15233 | 15019 | argv = sargv; |
| @@ -15234,19 +15020,19 @@ | ||
| 15234 | 15020 | |
| 15235 | 15021 | for (i = 0; i < script->len && retcode == JIM_OK; ) { |
| 15236 | 15022 | int argc; |
| 15237 | 15023 | int j; |
| 15238 | 15024 | |
| 15239 | - | |
| 15025 | + | |
| 15240 | 15026 | argc = token[i].objPtr->internalRep.scriptLineValue.argc; |
| 15241 | 15027 | script->linenr = token[i].objPtr->internalRep.scriptLineValue.line; |
| 15242 | 15028 | |
| 15243 | - | |
| 15029 | + | |
| 15244 | 15030 | if (argc > JIM_EVAL_SARGV_LEN) |
| 15245 | 15031 | argv = Jim_Alloc(sizeof(Jim_Obj *) * argc); |
| 15246 | 15032 | |
| 15247 | - | |
| 15033 | + | |
| 15248 | 15034 | i++; |
| 15249 | 15035 | |
| 15250 | 15036 | for (j = 0; j < argc; j++) { |
| 15251 | 15037 | long wordtokens = 1; |
| 15252 | 15038 | int expand = 0; |
| @@ -15302,11 +15088,11 @@ | ||
| 15302 | 15088 | |
| 15303 | 15089 | if (!expand) { |
| 15304 | 15090 | argv[j] = wordObjPtr; |
| 15305 | 15091 | } |
| 15306 | 15092 | else { |
| 15307 | - | |
| 15093 | + | |
| 15308 | 15094 | int len = Jim_ListLength(interp, wordObjPtr); |
| 15309 | 15095 | int newargc = argc + len - 1; |
| 15310 | 15096 | int k; |
| 15311 | 15097 | |
| 15312 | 15098 | if (len > 1) { |
| @@ -15315,39 +15101,39 @@ | ||
| 15315 | 15101 | argv = Jim_Alloc(sizeof(*argv) * newargc); |
| 15316 | 15102 | memcpy(argv, sargv, sizeof(*argv) * j); |
| 15317 | 15103 | } |
| 15318 | 15104 | } |
| 15319 | 15105 | else { |
| 15320 | - | |
| 15106 | + | |
| 15321 | 15107 | argv = Jim_Realloc(argv, sizeof(*argv) * newargc); |
| 15322 | 15108 | } |
| 15323 | 15109 | } |
| 15324 | 15110 | |
| 15325 | - | |
| 15111 | + | |
| 15326 | 15112 | for (k = 0; k < len; k++) { |
| 15327 | 15113 | argv[j++] = wordObjPtr->internalRep.listValue.ele[k]; |
| 15328 | 15114 | Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]); |
| 15329 | 15115 | } |
| 15330 | 15116 | |
| 15331 | 15117 | Jim_DecrRefCount(interp, wordObjPtr); |
| 15332 | 15118 | |
| 15333 | - | |
| 15119 | + | |
| 15334 | 15120 | j--; |
| 15335 | 15121 | argc += len - 1; |
| 15336 | 15122 | } |
| 15337 | 15123 | } |
| 15338 | 15124 | |
| 15339 | 15125 | if (retcode == JIM_OK && argc) { |
| 15340 | - | |
| 15126 | + | |
| 15341 | 15127 | retcode = JimInvokeCommand(interp, argc, argv); |
| 15342 | - | |
| 15128 | + | |
| 15343 | 15129 | if (Jim_CheckSignal(interp)) { |
| 15344 | 15130 | retcode = JIM_SIGNAL; |
| 15345 | 15131 | } |
| 15346 | 15132 | } |
| 15347 | 15133 | |
| 15348 | - | |
| 15134 | + | |
| 15349 | 15135 | while (j-- > 0) { |
| 15350 | 15136 | Jim_DecrRefCount(interp, argv[j]); |
| 15351 | 15137 | } |
| 15352 | 15138 | |
| 15353 | 15139 | if (argv != sargv) { |
| @@ -15354,21 +15140,21 @@ | ||
| 15354 | 15140 | Jim_Free(argv); |
| 15355 | 15141 | argv = sargv; |
| 15356 | 15142 | } |
| 15357 | 15143 | } |
| 15358 | 15144 | |
| 15359 | - | |
| 15145 | + | |
| 15360 | 15146 | if (retcode == JIM_ERR) { |
| 15361 | 15147 | JimAddErrorToStack(interp, script); |
| 15362 | 15148 | } |
| 15363 | - | |
| 15149 | + | |
| 15364 | 15150 | else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) { |
| 15365 | - | |
| 15151 | + | |
| 15366 | 15152 | interp->addStackTrace = 0; |
| 15367 | 15153 | } |
| 15368 | 15154 | |
| 15369 | - | |
| 15155 | + | |
| 15370 | 15156 | interp->currentScriptObj = prevScriptObj; |
| 15371 | 15157 | |
| 15372 | 15158 | Jim_FreeIntRep(interp, scriptObjPtr); |
| 15373 | 15159 | scriptObjPtr->typePtr = &scriptObjType; |
| 15374 | 15160 | Jim_SetIntRepPtr(scriptObjPtr, script); |
| @@ -15378,14 +15164,14 @@ | ||
| 15378 | 15164 | } |
| 15379 | 15165 | |
| 15380 | 15166 | static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj) |
| 15381 | 15167 | { |
| 15382 | 15168 | int retcode; |
| 15383 | - | |
| 15169 | + | |
| 15384 | 15170 | const char *varname = Jim_String(argNameObj); |
| 15385 | 15171 | if (*varname == '&') { |
| 15386 | - | |
| 15172 | + | |
| 15387 | 15173 | Jim_Obj *objPtr; |
| 15388 | 15174 | Jim_CallFrame *savedCallFrame = interp->framePtr; |
| 15389 | 15175 | |
| 15390 | 15176 | interp->framePtr = interp->framePtr->parent; |
| 15391 | 15177 | objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG); |
| @@ -15392,11 +15178,11 @@ | ||
| 15392 | 15178 | interp->framePtr = savedCallFrame; |
| 15393 | 15179 | if (!objPtr) { |
| 15394 | 15180 | return JIM_ERR; |
| 15395 | 15181 | } |
| 15396 | 15182 | |
| 15397 | - | |
| 15183 | + | |
| 15398 | 15184 | objPtr = Jim_NewStringObj(interp, varname + 1, -1); |
| 15399 | 15185 | Jim_IncrRefCount(objPtr); |
| 15400 | 15186 | retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent); |
| 15401 | 15187 | Jim_DecrRefCount(interp, objPtr); |
| 15402 | 15188 | } |
| @@ -15406,26 +15192,26 @@ | ||
| 15406 | 15192 | return retcode; |
| 15407 | 15193 | } |
| 15408 | 15194 | |
| 15409 | 15195 | static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd) |
| 15410 | 15196 | { |
| 15411 | - | |
| 15197 | + | |
| 15412 | 15198 | Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0); |
| 15413 | 15199 | int i; |
| 15414 | 15200 | |
| 15415 | 15201 | for (i = 0; i < cmd->u.proc.argListLen; i++) { |
| 15416 | 15202 | Jim_AppendString(interp, argmsg, " ", 1); |
| 15417 | 15203 | |
| 15418 | 15204 | if (i == cmd->u.proc.argsPos) { |
| 15419 | 15205 | if (cmd->u.proc.arglist[i].defaultObjPtr) { |
| 15420 | - | |
| 15206 | + | |
| 15421 | 15207 | Jim_AppendString(interp, argmsg, "?", 1); |
| 15422 | 15208 | Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); |
| 15423 | 15209 | Jim_AppendString(interp, argmsg, " ...?", -1); |
| 15424 | 15210 | } |
| 15425 | 15211 | else { |
| 15426 | - | |
| 15212 | + | |
| 15427 | 15213 | Jim_AppendString(interp, argmsg, "?arg...?", -1); |
| 15428 | 15214 | } |
| 15429 | 15215 | } |
| 15430 | 15216 | else { |
| 15431 | 15217 | if (cmd->u.proc.arglist[i].defaultObjPtr) { |
| @@ -15441,20 +15227,19 @@ | ||
| 15441 | 15227 | Jim_AppendString(interp, argmsg, arg, -1); |
| 15442 | 15228 | } |
| 15443 | 15229 | } |
| 15444 | 15230 | } |
| 15445 | 15231 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg); |
| 15446 | - Jim_FreeNewObj(interp, argmsg); | |
| 15447 | 15232 | } |
| 15448 | 15233 | |
| 15449 | 15234 | #ifdef jim_ext_namespace |
| 15450 | 15235 | int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj) |
| 15451 | 15236 | { |
| 15452 | 15237 | Jim_CallFrame *callFramePtr; |
| 15453 | 15238 | int retcode; |
| 15454 | 15239 | |
| 15455 | - | |
| 15240 | + | |
| 15456 | 15241 | callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj); |
| 15457 | 15242 | callFramePtr->argv = &interp->emptyObj; |
| 15458 | 15243 | callFramePtr->argc = 0; |
| 15459 | 15244 | callFramePtr->procArgsObjPtr = NULL; |
| 15460 | 15245 | callFramePtr->procBodyObjPtr = scriptObj; |
| @@ -15462,21 +15247,21 @@ | ||
| 15462 | 15247 | callFramePtr->fileNameObj = interp->emptyObj; |
| 15463 | 15248 | callFramePtr->line = 0; |
| 15464 | 15249 | Jim_IncrRefCount(scriptObj); |
| 15465 | 15250 | interp->framePtr = callFramePtr; |
| 15466 | 15251 | |
| 15467 | - | |
| 15252 | + | |
| 15468 | 15253 | if (interp->framePtr->level == interp->maxCallFrameDepth) { |
| 15469 | 15254 | Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); |
| 15470 | 15255 | retcode = JIM_ERR; |
| 15471 | 15256 | } |
| 15472 | 15257 | else { |
| 15473 | - | |
| 15258 | + | |
| 15474 | 15259 | retcode = Jim_EvalObj(interp, scriptObj); |
| 15475 | 15260 | } |
| 15476 | 15261 | |
| 15477 | - | |
| 15262 | + | |
| 15478 | 15263 | interp->framePtr = interp->framePtr->parent; |
| 15479 | 15264 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15480 | 15265 | |
| 15481 | 15266 | return retcode; |
| 15482 | 15267 | } |
| @@ -15486,62 +15271,62 @@ | ||
| 15486 | 15271 | { |
| 15487 | 15272 | Jim_CallFrame *callFramePtr; |
| 15488 | 15273 | int i, d, retcode, optargs; |
| 15489 | 15274 | ScriptObj *script; |
| 15490 | 15275 | |
| 15491 | - | |
| 15276 | + | |
| 15492 | 15277 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15493 | 15278 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| 15494 | 15279 | JimSetProcWrongArgs(interp, argv[0], cmd); |
| 15495 | 15280 | return JIM_ERR; |
| 15496 | 15281 | } |
| 15497 | 15282 | |
| 15498 | 15283 | if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) { |
| 15499 | - | |
| 15284 | + | |
| 15500 | 15285 | return JIM_OK; |
| 15501 | 15286 | } |
| 15502 | 15287 | |
| 15503 | - | |
| 15288 | + | |
| 15504 | 15289 | if (interp->framePtr->level == interp->maxCallFrameDepth) { |
| 15505 | 15290 | Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); |
| 15506 | 15291 | return JIM_ERR; |
| 15507 | 15292 | } |
| 15508 | 15293 | |
| 15509 | - | |
| 15294 | + | |
| 15510 | 15295 | callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj); |
| 15511 | 15296 | callFramePtr->argv = argv; |
| 15512 | 15297 | callFramePtr->argc = argc; |
| 15513 | 15298 | callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; |
| 15514 | 15299 | callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; |
| 15515 | 15300 | callFramePtr->staticVars = cmd->u.proc.staticVars; |
| 15516 | 15301 | |
| 15517 | - | |
| 15302 | + | |
| 15518 | 15303 | script = JimGetScript(interp, interp->currentScriptObj); |
| 15519 | 15304 | callFramePtr->fileNameObj = script->fileNameObj; |
| 15520 | 15305 | callFramePtr->line = script->linenr; |
| 15521 | 15306 | |
| 15522 | 15307 | Jim_IncrRefCount(cmd->u.proc.argListObjPtr); |
| 15523 | 15308 | Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); |
| 15524 | 15309 | interp->framePtr = callFramePtr; |
| 15525 | 15310 | |
| 15526 | - | |
| 15311 | + | |
| 15527 | 15312 | optargs = (argc - 1 - cmd->u.proc.reqArity); |
| 15528 | 15313 | |
| 15529 | - | |
| 15314 | + | |
| 15530 | 15315 | i = 1; |
| 15531 | 15316 | for (d = 0; d < cmd->u.proc.argListLen; d++) { |
| 15532 | 15317 | Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr; |
| 15533 | 15318 | if (d == cmd->u.proc.argsPos) { |
| 15534 | - | |
| 15319 | + | |
| 15535 | 15320 | Jim_Obj *listObjPtr; |
| 15536 | 15321 | int argsLen = 0; |
| 15537 | 15322 | if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) { |
| 15538 | 15323 | argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity); |
| 15539 | 15324 | } |
| 15540 | 15325 | listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen); |
| 15541 | 15326 | |
| 15542 | - | |
| 15327 | + | |
| 15543 | 15328 | if (cmd->u.proc.arglist[d].defaultObjPtr) { |
| 15544 | 15329 | nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr; |
| 15545 | 15330 | } |
| 15546 | 15331 | retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr); |
| 15547 | 15332 | if (retcode != JIM_OK) { |
| @@ -15550,33 +15335,34 @@ | ||
| 15550 | 15335 | |
| 15551 | 15336 | i += argsLen; |
| 15552 | 15337 | continue; |
| 15553 | 15338 | } |
| 15554 | 15339 | |
| 15555 | - | |
| 15340 | + | |
| 15556 | 15341 | if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) { |
| 15557 | 15342 | retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]); |
| 15558 | 15343 | } |
| 15559 | 15344 | else { |
| 15560 | - | |
| 15345 | + | |
| 15561 | 15346 | retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr); |
| 15562 | 15347 | } |
| 15563 | 15348 | if (retcode != JIM_OK) { |
| 15564 | 15349 | goto badargset; |
| 15565 | 15350 | } |
| 15566 | 15351 | } |
| 15567 | 15352 | |
| 15568 | - | |
| 15353 | + | |
| 15569 | 15354 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 15570 | 15355 | |
| 15571 | 15356 | badargset: |
| 15572 | 15357 | |
| 15573 | - | |
| 15358 | + | |
| 15359 | + retcode = JimInvokeDefer(interp, retcode); | |
| 15574 | 15360 | interp->framePtr = interp->framePtr->parent; |
| 15575 | 15361 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15576 | 15362 | |
| 15577 | - | |
| 15363 | + | |
| 15578 | 15364 | if (interp->framePtr->tailcallObj) { |
| 15579 | 15365 | do { |
| 15580 | 15366 | Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; |
| 15581 | 15367 | |
| 15582 | 15368 | interp->framePtr->tailcallObj = NULL; |
| @@ -15588,18 +15374,18 @@ | ||
| 15588 | 15374 | } |
| 15589 | 15375 | } |
| 15590 | 15376 | Jim_DecrRefCount(interp, tailcallObj); |
| 15591 | 15377 | } while (interp->framePtr->tailcallObj); |
| 15592 | 15378 | |
| 15593 | - | |
| 15379 | + | |
| 15594 | 15380 | if (interp->framePtr->tailcallCmd) { |
| 15595 | 15381 | JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); |
| 15596 | 15382 | interp->framePtr->tailcallCmd = NULL; |
| 15597 | 15383 | } |
| 15598 | 15384 | } |
| 15599 | 15385 | |
| 15600 | - | |
| 15386 | + | |
| 15601 | 15387 | if (retcode == JIM_RETURN) { |
| 15602 | 15388 | if (--interp->returnLevel <= 0) { |
| 15603 | 15389 | retcode = interp->returnCode; |
| 15604 | 15390 | interp->returnCode = JIM_OK; |
| 15605 | 15391 | interp->returnLevel = 0; |
| @@ -15711,20 +15497,20 @@ | ||
| 15711 | 15497 | prevScriptObj = interp->currentScriptObj; |
| 15712 | 15498 | interp->currentScriptObj = scriptObjPtr; |
| 15713 | 15499 | |
| 15714 | 15500 | retcode = Jim_EvalObj(interp, scriptObjPtr); |
| 15715 | 15501 | |
| 15716 | - | |
| 15502 | + | |
| 15717 | 15503 | if (retcode == JIM_RETURN) { |
| 15718 | 15504 | if (--interp->returnLevel <= 0) { |
| 15719 | 15505 | retcode = interp->returnCode; |
| 15720 | 15506 | interp->returnCode = JIM_OK; |
| 15721 | 15507 | interp->returnLevel = 0; |
| 15722 | 15508 | } |
| 15723 | 15509 | } |
| 15724 | 15510 | if (retcode == JIM_ERR) { |
| 15725 | - | |
| 15511 | + | |
| 15726 | 15512 | interp->addStackTrace++; |
| 15727 | 15513 | } |
| 15728 | 15514 | |
| 15729 | 15515 | interp->currentScriptObj = prevScriptObj; |
| 15730 | 15516 | |
| @@ -15750,11 +15536,11 @@ | ||
| 15750 | 15536 | } |
| 15751 | 15537 | if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { |
| 15752 | 15538 | if (JimParseVar(pc) == JIM_OK) { |
| 15753 | 15539 | return; |
| 15754 | 15540 | } |
| 15755 | - | |
| 15541 | + | |
| 15756 | 15542 | pc->tstart = pc->p; |
| 15757 | 15543 | flags |= JIM_SUBST_NOVAR; |
| 15758 | 15544 | } |
| 15759 | 15545 | while (pc->len) { |
| 15760 | 15546 | if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { |
| @@ -15781,32 +15567,32 @@ | ||
| 15781 | 15567 | const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); |
| 15782 | 15568 | struct JimParserCtx parser; |
| 15783 | 15569 | struct ScriptObj *script = Jim_Alloc(sizeof(*script)); |
| 15784 | 15570 | ParseTokenList tokenlist; |
| 15785 | 15571 | |
| 15786 | - | |
| 15572 | + | |
| 15787 | 15573 | ScriptTokenListInit(&tokenlist); |
| 15788 | 15574 | |
| 15789 | 15575 | JimParserInit(&parser, scriptText, scriptTextLen, 1); |
| 15790 | 15576 | while (1) { |
| 15791 | 15577 | JimParseSubst(&parser, flags); |
| 15792 | 15578 | if (parser.eof) { |
| 15793 | - | |
| 15579 | + | |
| 15794 | 15580 | break; |
| 15795 | 15581 | } |
| 15796 | 15582 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 15797 | 15583 | parser.tline); |
| 15798 | 15584 | } |
| 15799 | 15585 | |
| 15800 | - | |
| 15586 | + | |
| 15801 | 15587 | script->inUse = 1; |
| 15802 | 15588 | script->substFlags = flags; |
| 15803 | 15589 | script->fileNameObj = interp->emptyObj; |
| 15804 | 15590 | Jim_IncrRefCount(script->fileNameObj); |
| 15805 | 15591 | SubstObjAddTokens(interp, script, &tokenlist); |
| 15806 | 15592 | |
| 15807 | - | |
| 15593 | + | |
| 15808 | 15594 | ScriptTokenListFree(&tokenlist); |
| 15809 | 15595 | |
| 15810 | 15596 | #ifdef DEBUG_SHOW_SUBST |
| 15811 | 15597 | { |
| 15812 | 15598 | int i; |
| @@ -15817,11 +15603,11 @@ | ||
| 15817 | 15603 | Jim_String(script->token[i].objPtr)); |
| 15818 | 15604 | } |
| 15819 | 15605 | } |
| 15820 | 15606 | #endif |
| 15821 | 15607 | |
| 15822 | - | |
| 15608 | + | |
| 15823 | 15609 | Jim_FreeIntRep(interp, objPtr); |
| 15824 | 15610 | Jim_SetIntRepPtr(objPtr, script); |
| 15825 | 15611 | objPtr->typePtr = &scriptObjType; |
| 15826 | 15612 | return JIM_OK; |
| 15827 | 15613 | } |
| @@ -15835,11 +15621,11 @@ | ||
| 15835 | 15621 | |
| 15836 | 15622 | int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) |
| 15837 | 15623 | { |
| 15838 | 15624 | ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); |
| 15839 | 15625 | |
| 15840 | - Jim_IncrRefCount(substObjPtr); | |
| 15626 | + Jim_IncrRefCount(substObjPtr); | |
| 15841 | 15627 | script->inUse++; |
| 15842 | 15628 | |
| 15843 | 15629 | *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); |
| 15844 | 15630 | |
| 15845 | 15631 | script->inUse--; |
| @@ -15851,22 +15637,24 @@ | ||
| 15851 | 15637 | } |
| 15852 | 15638 | |
| 15853 | 15639 | void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg) |
| 15854 | 15640 | { |
| 15855 | 15641 | Jim_Obj *objPtr; |
| 15856 | - Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc); | |
| 15642 | + Jim_Obj *listObjPtr; | |
| 15857 | 15643 | |
| 15858 | - if (*msg) { | |
| 15644 | + JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0")); | |
| 15645 | + | |
| 15646 | + listObjPtr = Jim_NewListObj(interp, argv, argc); | |
| 15647 | + | |
| 15648 | + if (msg && *msg) { | |
| 15859 | 15649 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1)); |
| 15860 | 15650 | } |
| 15861 | 15651 | Jim_IncrRefCount(listObjPtr); |
| 15862 | 15652 | objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1); |
| 15863 | 15653 | Jim_DecrRefCount(interp, listObjPtr); |
| 15864 | 15654 | |
| 15865 | - Jim_IncrRefCount(objPtr); | |
| 15866 | 15655 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr); |
| 15867 | - Jim_DecrRefCount(interp, objPtr); | |
| 15868 | 15656 | } |
| 15869 | 15657 | |
| 15870 | 15658 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15871 | 15659 | Jim_HashEntry *he, int type); |
| 15872 | 15660 | |
| @@ -15876,11 +15664,11 @@ | ||
| 15876 | 15664 | JimHashtableIteratorCallbackType *callback, int type) |
| 15877 | 15665 | { |
| 15878 | 15666 | Jim_HashEntry *he; |
| 15879 | 15667 | Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 15880 | 15668 | |
| 15881 | - | |
| 15669 | + | |
| 15882 | 15670 | if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { |
| 15883 | 15671 | he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); |
| 15884 | 15672 | if (he) { |
| 15885 | 15673 | callback(interp, listObjPtr, he, type); |
| 15886 | 15674 | } |
| @@ -15907,11 +15695,11 @@ | ||
| 15907 | 15695 | { |
| 15908 | 15696 | Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); |
| 15909 | 15697 | Jim_Obj *objPtr; |
| 15910 | 15698 | |
| 15911 | 15699 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15912 | - | |
| 15700 | + | |
| 15913 | 15701 | return; |
| 15914 | 15702 | } |
| 15915 | 15703 | |
| 15916 | 15704 | objPtr = Jim_NewStringObj(interp, he->key, -1); |
| 15917 | 15705 | Jim_IncrRefCount(objPtr); |
| @@ -15967,11 +15755,11 @@ | ||
| 15967 | 15755 | |
| 15968 | 15756 | targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); |
| 15969 | 15757 | if (targetCallFrame == NULL) { |
| 15970 | 15758 | return JIM_ERR; |
| 15971 | 15759 | } |
| 15972 | - | |
| 15760 | + | |
| 15973 | 15761 | if (targetCallFrame == interp->topFramePtr) { |
| 15974 | 15762 | Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); |
| 15975 | 15763 | return JIM_ERR; |
| 15976 | 15764 | } |
| 15977 | 15765 | if (info_level_cmd) { |
| @@ -16095,12 +15883,17 @@ | ||
| 16095 | 15883 | doubleRes = (double)res; |
| 16096 | 15884 | goto trydouble; |
| 16097 | 15885 | } |
| 16098 | 15886 | if (op == JIM_EXPROP_SUB) |
| 16099 | 15887 | res -= wideValue; |
| 16100 | - else | |
| 15888 | + else { | |
| 15889 | + if (wideValue == 0) { | |
| 15890 | + Jim_SetResultString(interp, "Division by zero", -1); | |
| 15891 | + return JIM_ERR; | |
| 15892 | + } | |
| 16101 | 15893 | res /= wideValue; |
| 15894 | + } | |
| 16102 | 15895 | } |
| 16103 | 15896 | Jim_SetResultInt(interp, res); |
| 16104 | 15897 | return JIM_OK; |
| 16105 | 15898 | trydouble: |
| 16106 | 15899 | for (; i < argc; i++) { |
| @@ -16154,11 +15947,11 @@ | ||
| 16154 | 15947 | if (!objPtr) |
| 16155 | 15948 | return JIM_ERR; |
| 16156 | 15949 | Jim_SetResult(interp, objPtr); |
| 16157 | 15950 | return JIM_OK; |
| 16158 | 15951 | } |
| 16159 | - | |
| 15952 | + | |
| 16160 | 15953 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 16161 | 15954 | return JIM_ERR; |
| 16162 | 15955 | Jim_SetResult(interp, argv[2]); |
| 16163 | 15956 | return JIM_OK; |
| 16164 | 15957 | } |
| @@ -16197,11 +15990,11 @@ | ||
| 16197 | 15990 | if (argc != 3) { |
| 16198 | 15991 | Jim_WrongNumArgs(interp, 1, argv, "condition body"); |
| 16199 | 15992 | return JIM_ERR; |
| 16200 | 15993 | } |
| 16201 | 15994 | |
| 16202 | - | |
| 15995 | + | |
| 16203 | 15996 | while (1) { |
| 16204 | 15997 | int boolean, retval; |
| 16205 | 15998 | |
| 16206 | 15999 | if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) |
| 16207 | 16000 | return retval; |
| @@ -16237,11 +16030,11 @@ | ||
| 16237 | 16030 | if (argc != 5) { |
| 16238 | 16031 | Jim_WrongNumArgs(interp, 1, argv, "start test next body"); |
| 16239 | 16032 | return JIM_ERR; |
| 16240 | 16033 | } |
| 16241 | 16034 | |
| 16242 | - | |
| 16035 | + | |
| 16243 | 16036 | if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) { |
| 16244 | 16037 | return retval; |
| 16245 | 16038 | } |
| 16246 | 16039 | |
| 16247 | 16040 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); |
| @@ -16248,78 +16041,84 @@ | ||
| 16248 | 16041 | |
| 16249 | 16042 | |
| 16250 | 16043 | #ifdef JIM_OPTIMIZATION |
| 16251 | 16044 | if (retval == JIM_OK && boolean) { |
| 16252 | 16045 | ScriptObj *incrScript; |
| 16253 | - ExprByteCode *expr; | |
| 16046 | + struct ExprTree *expr; | |
| 16254 | 16047 | jim_wide stop, currentVal; |
| 16255 | 16048 | Jim_Obj *objPtr; |
| 16256 | 16049 | int cmpOffset; |
| 16257 | 16050 | |
| 16258 | - | |
| 16051 | + | |
| 16259 | 16052 | expr = JimGetExpression(interp, argv[2]); |
| 16260 | 16053 | incrScript = JimGetScript(interp, argv[3]); |
| 16261 | 16054 | |
| 16262 | - | |
| 16055 | + | |
| 16263 | 16056 | if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { |
| 16264 | 16057 | goto evalstart; |
| 16265 | 16058 | } |
| 16266 | - | |
| 16267 | - if (incrScript->token[1].type != JIM_TT_ESC || | |
| 16268 | - expr->token[0].type != JIM_TT_VAR || | |
| 16269 | - (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) { | |
| 16059 | + | |
| 16060 | + if (incrScript->token[1].type != JIM_TT_ESC) { | |
| 16270 | 16061 | goto evalstart; |
| 16271 | 16062 | } |
| 16272 | 16063 | |
| 16273 | - if (expr->token[2].type == JIM_EXPROP_LT) { | |
| 16064 | + if (expr->expr->type == JIM_EXPROP_LT) { | |
| 16274 | 16065 | cmpOffset = 0; |
| 16275 | 16066 | } |
| 16276 | - else if (expr->token[2].type == JIM_EXPROP_LTE) { | |
| 16067 | + else if (expr->expr->type == JIM_EXPROP_LTE) { | |
| 16277 | 16068 | cmpOffset = 1; |
| 16278 | 16069 | } |
| 16279 | 16070 | else { |
| 16280 | 16071 | goto evalstart; |
| 16281 | 16072 | } |
| 16282 | 16073 | |
| 16283 | - | |
| 16074 | + if (expr->expr->left->type != JIM_TT_VAR) { | |
| 16075 | + goto evalstart; | |
| 16076 | + } | |
| 16077 | + | |
| 16078 | + if (expr->expr->right->type != JIM_TT_VAR && expr->expr->right->type != JIM_TT_EXPR_INT) { | |
| 16079 | + goto evalstart; | |
| 16080 | + } | |
| 16081 | + | |
| 16082 | + | |
| 16284 | 16083 | if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { |
| 16285 | 16084 | goto evalstart; |
| 16286 | 16085 | } |
| 16287 | 16086 | |
| 16288 | - | |
| 16289 | - if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) { | |
| 16087 | + | |
| 16088 | + if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->expr->left->objPtr)) { | |
| 16290 | 16089 | goto evalstart; |
| 16291 | 16090 | } |
| 16292 | 16091 | |
| 16293 | - | |
| 16294 | - if (expr->token[1].type == JIM_TT_EXPR_INT) { | |
| 16295 | - if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) { | |
| 16092 | + | |
| 16093 | + if (expr->expr->right->type == JIM_TT_EXPR_INT) { | |
| 16094 | + if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) { | |
| 16296 | 16095 | goto evalstart; |
| 16297 | 16096 | } |
| 16298 | 16097 | } |
| 16299 | 16098 | else { |
| 16300 | - stopVarNamePtr = expr->token[1].objPtr; | |
| 16099 | + stopVarNamePtr = expr->expr->right->objPtr; | |
| 16301 | 16100 | Jim_IncrRefCount(stopVarNamePtr); |
| 16302 | - | |
| 16101 | + | |
| 16303 | 16102 | stop = 0; |
| 16304 | 16103 | } |
| 16305 | 16104 | |
| 16306 | - | |
| 16307 | - varNamePtr = expr->token[0].objPtr; | |
| 16105 | + | |
| 16106 | + varNamePtr = expr->expr->left->objPtr; | |
| 16308 | 16107 | Jim_IncrRefCount(varNamePtr); |
| 16309 | 16108 | |
| 16310 | 16109 | objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); |
| 16311 | 16110 | if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { |
| 16312 | 16111 | goto testcond; |
| 16313 | 16112 | } |
| 16314 | 16113 | |
| 16315 | - | |
| 16114 | + | |
| 16316 | 16115 | while (retval == JIM_OK) { |
| 16317 | - | |
| 16318 | - | |
| 16319 | 16116 | |
| 16320 | - | |
| 16117 | + | |
| 16118 | + | |
| 16119 | + | |
| 16321 | 16120 | if (stopVarNamePtr) { |
| 16322 | 16121 | objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE); |
| 16323 | 16122 | if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) { |
| 16324 | 16123 | goto testcond; |
| 16325 | 16124 | } |
| @@ -16327,18 +16126,18 @@ | ||
| 16327 | 16126 | |
| 16328 | 16127 | if (currentVal >= stop + cmpOffset) { |
| 16329 | 16128 | break; |
| 16330 | 16129 | } |
| 16331 | 16130 | |
| 16332 | - | |
| 16131 | + | |
| 16333 | 16132 | retval = Jim_EvalObj(interp, argv[4]); |
| 16334 | 16133 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16335 | 16134 | retval = JIM_OK; |
| 16336 | 16135 | |
| 16337 | 16136 | objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); |
| 16338 | 16137 | |
| 16339 | - | |
| 16138 | + | |
| 16340 | 16139 | if (objPtr == NULL) { |
| 16341 | 16140 | retval = JIM_ERR; |
| 16342 | 16141 | goto out; |
| 16343 | 16142 | } |
| 16344 | 16143 | if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { |
| @@ -16358,25 +16157,25 @@ | ||
| 16358 | 16157 | } |
| 16359 | 16158 | evalstart: |
| 16360 | 16159 | #endif |
| 16361 | 16160 | |
| 16362 | 16161 | while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) { |
| 16363 | - | |
| 16162 | + | |
| 16364 | 16163 | retval = Jim_EvalObj(interp, argv[4]); |
| 16365 | 16164 | |
| 16366 | 16165 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16367 | - | |
| 16368 | - evalnext: | |
| 16166 | + | |
| 16167 | +JIM_IF_OPTIM(evalnext:) | |
| 16369 | 16168 | retval = Jim_EvalObj(interp, argv[3]); |
| 16370 | 16169 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16371 | - | |
| 16372 | - testcond: | |
| 16170 | + | |
| 16171 | +JIM_IF_OPTIM(testcond:) | |
| 16373 | 16172 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); |
| 16374 | 16173 | } |
| 16375 | 16174 | } |
| 16376 | 16175 | } |
| 16377 | - out: | |
| 16176 | +JIM_IF_OPTIM(out:) | |
| 16378 | 16177 | if (stopVarNamePtr) { |
| 16379 | 16178 | Jim_DecrRefCount(interp, stopVarNamePtr); |
| 16380 | 16179 | } |
| 16381 | 16180 | if (varNamePtr) { |
| 16382 | 16181 | Jim_DecrRefCount(interp, varNamePtr); |
| @@ -16418,11 +16217,11 @@ | ||
| 16418 | 16217 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16419 | 16218 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); |
| 16420 | 16219 | |
| 16421 | 16220 | retval = JIM_OK; |
| 16422 | 16221 | |
| 16423 | - | |
| 16222 | + | |
| 16424 | 16223 | i += incr; |
| 16425 | 16224 | |
| 16426 | 16225 | if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { |
| 16427 | 16226 | if (argv[1]->typePtr != &variableObjType) { |
| 16428 | 16227 | if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { |
| @@ -16483,21 +16282,21 @@ | ||
| 16483 | 16282 | |
| 16484 | 16283 | static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) |
| 16485 | 16284 | { |
| 16486 | 16285 | int result = JIM_OK; |
| 16487 | 16286 | int i, numargs; |
| 16488 | - Jim_ListIter twoiters[2]; | |
| 16287 | + Jim_ListIter twoiters[2]; | |
| 16489 | 16288 | Jim_ListIter *iters; |
| 16490 | 16289 | Jim_Obj *script; |
| 16491 | 16290 | Jim_Obj *resultObj; |
| 16492 | 16291 | |
| 16493 | 16292 | if (argc < 4 || argc % 2 != 0) { |
| 16494 | 16293 | Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script"); |
| 16495 | 16294 | return JIM_ERR; |
| 16496 | 16295 | } |
| 16497 | - script = argv[argc - 1]; | |
| 16498 | - numargs = (argc - 1 - 1); | |
| 16296 | + script = argv[argc - 1]; | |
| 16297 | + numargs = (argc - 1 - 1); | |
| 16499 | 16298 | |
| 16500 | 16299 | if (numargs == 2) { |
| 16501 | 16300 | iters = twoiters; |
| 16502 | 16301 | } |
| 16503 | 16302 | else { |
| @@ -16521,34 +16320,34 @@ | ||
| 16521 | 16320 | resultObj = interp->emptyObj; |
| 16522 | 16321 | } |
| 16523 | 16322 | Jim_IncrRefCount(resultObj); |
| 16524 | 16323 | |
| 16525 | 16324 | while (1) { |
| 16526 | - | |
| 16325 | + | |
| 16527 | 16326 | for (i = 0; i < numargs; i += 2) { |
| 16528 | 16327 | if (!JimListIterDone(interp, &iters[i + 1])) { |
| 16529 | 16328 | break; |
| 16530 | 16329 | } |
| 16531 | 16330 | } |
| 16532 | 16331 | if (i == numargs) { |
| 16533 | - | |
| 16332 | + | |
| 16534 | 16333 | break; |
| 16535 | 16334 | } |
| 16536 | 16335 | |
| 16537 | - | |
| 16336 | + | |
| 16538 | 16337 | for (i = 0; i < numargs; i += 2) { |
| 16539 | 16338 | Jim_Obj *varName; |
| 16540 | 16339 | |
| 16541 | - | |
| 16340 | + | |
| 16542 | 16341 | JimListIterInit(&iters[i], argv[i + 1]); |
| 16543 | 16342 | while ((varName = JimListIterNext(interp, &iters[i])) != NULL) { |
| 16544 | 16343 | Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]); |
| 16545 | 16344 | if (!valObj) { |
| 16546 | - | |
| 16345 | + | |
| 16547 | 16346 | valObj = interp->emptyObj; |
| 16548 | 16347 | } |
| 16549 | - | |
| 16348 | + | |
| 16550 | 16349 | Jim_IncrRefCount(valObj); |
| 16551 | 16350 | result = Jim_SetVariable(interp, varName, valObj); |
| 16552 | 16351 | Jim_DecrRefCount(interp, valObj); |
| 16553 | 16352 | if (result != JIM_OK) { |
| 16554 | 16353 | goto err; |
| @@ -16630,41 +16429,41 @@ | ||
| 16630 | 16429 | { |
| 16631 | 16430 | int boolean, retval, current = 1, falsebody = 0; |
| 16632 | 16431 | |
| 16633 | 16432 | if (argc >= 3) { |
| 16634 | 16433 | while (1) { |
| 16635 | - | |
| 16434 | + | |
| 16636 | 16435 | if (current >= argc) |
| 16637 | 16436 | goto err; |
| 16638 | 16437 | if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean)) |
| 16639 | 16438 | != JIM_OK) |
| 16640 | 16439 | return retval; |
| 16641 | - | |
| 16440 | + | |
| 16642 | 16441 | if (current >= argc) |
| 16643 | 16442 | goto err; |
| 16644 | 16443 | if (Jim_CompareStringImmediate(interp, argv[current], "then")) |
| 16645 | 16444 | current++; |
| 16646 | - | |
| 16445 | + | |
| 16647 | 16446 | if (current >= argc) |
| 16648 | 16447 | goto err; |
| 16649 | 16448 | if (boolean) |
| 16650 | 16449 | return Jim_EvalObj(interp, argv[current]); |
| 16651 | - | |
| 16450 | + | |
| 16652 | 16451 | if (++current >= argc) { |
| 16653 | 16452 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 16654 | 16453 | return JIM_OK; |
| 16655 | 16454 | } |
| 16656 | 16455 | falsebody = current++; |
| 16657 | 16456 | if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) { |
| 16658 | - | |
| 16457 | + | |
| 16659 | 16458 | if (current != argc - 1) |
| 16660 | 16459 | goto err; |
| 16661 | 16460 | return Jim_EvalObj(interp, argv[current]); |
| 16662 | 16461 | } |
| 16663 | 16462 | else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif")) |
| 16664 | 16463 | continue; |
| 16665 | - | |
| 16464 | + | |
| 16666 | 16465 | else if (falsebody != argc - 1) |
| 16667 | 16466 | goto err; |
| 16668 | 16467 | return Jim_EvalObj(interp, argv[falsebody]); |
| 16669 | 16468 | } |
| 16670 | 16469 | return JIM_OK; |
| @@ -16698,19 +16497,17 @@ | ||
| 16698 | 16497 | } |
| 16699 | 16498 | |
| 16700 | 16499 | return eq; |
| 16701 | 16500 | } |
| 16702 | 16501 | |
| 16703 | -enum | |
| 16704 | -{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; | |
| 16705 | - | |
| 16706 | 16502 | |
| 16707 | 16503 | static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16708 | 16504 | { |
| 16505 | + enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; | |
| 16709 | 16506 | int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; |
| 16710 | - Jim_Obj *command = 0, *const *caseList = 0, *strObj; | |
| 16711 | - Jim_Obj *script = 0; | |
| 16507 | + Jim_Obj *command = NULL, *scriptObj = NULL, *strObj; | |
| 16508 | + Jim_Obj **caseList; | |
| 16712 | 16509 | |
| 16713 | 16510 | if (argc < 3) { |
| 16714 | 16511 | wrongnumargs: |
| 16715 | 16512 | Jim_WrongNumArgs(interp, 1, argv, "?options? string " |
| 16716 | 16513 | "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); |
| @@ -16747,68 +16544,62 @@ | ||
| 16747 | 16544 | goto wrongnumargs; |
| 16748 | 16545 | } |
| 16749 | 16546 | strObj = argv[opt++]; |
| 16750 | 16547 | patCount = argc - opt; |
| 16751 | 16548 | if (patCount == 1) { |
| 16752 | - Jim_Obj **vector; | |
| 16753 | - | |
| 16754 | - JimListGetElements(interp, argv[opt], &patCount, &vector); | |
| 16755 | - caseList = vector; | |
| 16549 | + JimListGetElements(interp, argv[opt], &patCount, &caseList); | |
| 16756 | 16550 | } |
| 16757 | 16551 | else |
| 16758 | - caseList = &argv[opt]; | |
| 16552 | + caseList = (Jim_Obj **)&argv[opt]; | |
| 16759 | 16553 | if (patCount == 0 || patCount % 2 != 0) |
| 16760 | 16554 | goto wrongnumargs; |
| 16761 | - for (i = 0; script == 0 && i < patCount; i += 2) { | |
| 16555 | + for (i = 0; scriptObj == NULL && i < patCount; i += 2) { | |
| 16762 | 16556 | Jim_Obj *patObj = caseList[i]; |
| 16763 | 16557 | |
| 16764 | 16558 | if (!Jim_CompareStringImmediate(interp, patObj, "default") |
| 16765 | 16559 | || i < (patCount - 2)) { |
| 16766 | 16560 | switch (matchOpt) { |
| 16767 | 16561 | case SWITCH_EXACT: |
| 16768 | 16562 | if (Jim_StringEqObj(strObj, patObj)) |
| 16769 | - script = caseList[i + 1]; | |
| 16563 | + scriptObj = caseList[i + 1]; | |
| 16770 | 16564 | break; |
| 16771 | 16565 | case SWITCH_GLOB: |
| 16772 | 16566 | if (Jim_StringMatchObj(interp, patObj, strObj, 0)) |
| 16773 | - script = caseList[i + 1]; | |
| 16567 | + scriptObj = caseList[i + 1]; | |
| 16774 | 16568 | break; |
| 16775 | 16569 | case SWITCH_RE: |
| 16776 | 16570 | command = Jim_NewStringObj(interp, "regexp", -1); |
| 16777 | - | |
| 16571 | + | |
| 16778 | 16572 | case SWITCH_CMD:{ |
| 16779 | 16573 | int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); |
| 16780 | 16574 | |
| 16781 | 16575 | if (argc - opt == 1) { |
| 16782 | - Jim_Obj **vector; | |
| 16783 | - | |
| 16784 | - JimListGetElements(interp, argv[opt], &patCount, &vector); | |
| 16785 | - caseList = vector; | |
| 16576 | + JimListGetElements(interp, argv[opt], &patCount, &caseList); | |
| 16786 | 16577 | } |
| 16787 | - | |
| 16578 | + | |
| 16788 | 16579 | if (rc < 0) { |
| 16789 | 16580 | return -rc; |
| 16790 | 16581 | } |
| 16791 | 16582 | if (rc) |
| 16792 | - script = caseList[i + 1]; | |
| 16583 | + scriptObj = caseList[i + 1]; | |
| 16793 | 16584 | break; |
| 16794 | 16585 | } |
| 16795 | 16586 | } |
| 16796 | 16587 | } |
| 16797 | 16588 | else { |
| 16798 | - script = caseList[i + 1]; | |
| 16589 | + scriptObj = caseList[i + 1]; | |
| 16799 | 16590 | } |
| 16800 | 16591 | } |
| 16801 | - for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2) | |
| 16802 | - script = caseList[i + 1]; | |
| 16803 | - if (script && Jim_CompareStringImmediate(interp, script, "-")) { | |
| 16592 | + for (; i < patCount && Jim_CompareStringImmediate(interp, scriptObj, "-"); i += 2) | |
| 16593 | + scriptObj = caseList[i + 1]; | |
| 16594 | + if (scriptObj && Jim_CompareStringImmediate(interp, scriptObj, "-")) { | |
| 16804 | 16595 | Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); |
| 16805 | 16596 | return JIM_ERR; |
| 16806 | 16597 | } |
| 16807 | 16598 | Jim_SetEmptyResult(interp); |
| 16808 | - if (script) { | |
| 16809 | - return Jim_EvalObj(interp, script); | |
| 16599 | + if (scriptObj) { | |
| 16600 | + return Jim_EvalObj(interp, scriptObj); | |
| 16810 | 16601 | } |
| 16811 | 16602 | return JIM_OK; |
| 16812 | 16603 | } |
| 16813 | 16604 | |
| 16814 | 16605 | |
| @@ -16920,11 +16711,11 @@ | ||
| 16920 | 16711 | case OPT_COMMAND: |
| 16921 | 16712 | if (i >= argc - 2) { |
| 16922 | 16713 | goto wrongargs; |
| 16923 | 16714 | } |
| 16924 | 16715 | commandObj = argv[++i]; |
| 16925 | - | |
| 16716 | + | |
| 16926 | 16717 | case OPT_EXACT: |
| 16927 | 16718 | case OPT_GLOB: |
| 16928 | 16719 | case OPT_REGEXP: |
| 16929 | 16720 | opt_match = option; |
| 16930 | 16721 | break; |
| @@ -16968,17 +16759,17 @@ | ||
| 16968 | 16759 | goto done; |
| 16969 | 16760 | } |
| 16970 | 16761 | break; |
| 16971 | 16762 | } |
| 16972 | 16763 | |
| 16973 | - | |
| 16764 | + | |
| 16974 | 16765 | if (!eq && opt_bool && opt_not && !opt_all) { |
| 16975 | 16766 | continue; |
| 16976 | 16767 | } |
| 16977 | 16768 | |
| 16978 | 16769 | if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { |
| 16979 | - | |
| 16770 | + | |
| 16980 | 16771 | Jim_Obj *resultObj; |
| 16981 | 16772 | |
| 16982 | 16773 | if (opt_bool) { |
| 16983 | 16774 | resultObj = Jim_NewIntObj(interp, eq ^ opt_not); |
| 16984 | 16775 | } |
| @@ -17001,11 +16792,11 @@ | ||
| 17001 | 16792 | |
| 17002 | 16793 | if (opt_all) { |
| 17003 | 16794 | Jim_SetResult(interp, listObjPtr); |
| 17004 | 16795 | } |
| 17005 | 16796 | else { |
| 17006 | - | |
| 16797 | + | |
| 17007 | 16798 | if (opt_bool) { |
| 17008 | 16799 | Jim_SetResultBool(interp, opt_not); |
| 17009 | 16800 | } |
| 17010 | 16801 | else if (!opt_inline) { |
| 17011 | 16802 | Jim_SetResultInt(interp, -1); |
| @@ -17030,11 +16821,11 @@ | ||
| 17030 | 16821 | Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); |
| 17031 | 16822 | return JIM_ERR; |
| 17032 | 16823 | } |
| 17033 | 16824 | listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 17034 | 16825 | if (!listObjPtr) { |
| 17035 | - | |
| 16826 | + | |
| 17036 | 16827 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 17037 | 16828 | new_obj = 1; |
| 17038 | 16829 | } |
| 17039 | 16830 | else if (Jim_IsShared(listObjPtr)) { |
| 17040 | 16831 | listObjPtr = Jim_DuplicateObj(interp, listObjPtr); |
| @@ -17103,31 +16894,31 @@ | ||
| 17103 | 16894 | first = JimRelToAbsIndex(len, first); |
| 17104 | 16895 | last = JimRelToAbsIndex(len, last); |
| 17105 | 16896 | JimRelToAbsRange(len, &first, &last, &rangeLen); |
| 17106 | 16897 | |
| 17107 | 16898 | |
| 17108 | - | |
| 16899 | + | |
| 17109 | 16900 | if (first < len) { |
| 17110 | - | |
| 16901 | + | |
| 17111 | 16902 | } |
| 17112 | 16903 | else if (len == 0) { |
| 17113 | - | |
| 16904 | + | |
| 17114 | 16905 | first = 0; |
| 17115 | 16906 | } |
| 17116 | 16907 | else { |
| 17117 | 16908 | Jim_SetResultString(interp, "list doesn't contain element ", -1); |
| 17118 | 16909 | Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]); |
| 17119 | 16910 | return JIM_ERR; |
| 17120 | 16911 | } |
| 17121 | 16912 | |
| 17122 | - | |
| 16913 | + | |
| 17123 | 16914 | newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first); |
| 17124 | 16915 | |
| 17125 | - | |
| 16916 | + | |
| 17126 | 16917 | ListInsertElements(newListObj, -1, argc - 4, argv + 4); |
| 17127 | 16918 | |
| 17128 | - | |
| 16919 | + | |
| 17129 | 16920 | ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen); |
| 17130 | 16921 | |
| 17131 | 16922 | Jim_SetResult(interp, newListObj); |
| 17132 | 16923 | return JIM_OK; |
| 17133 | 16924 | } |
| @@ -17138,11 +16929,11 @@ | ||
| 17138 | 16929 | if (argc < 3) { |
| 17139 | 16930 | Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 17140 | 16931 | return JIM_ERR; |
| 17141 | 16932 | } |
| 17142 | 16933 | else if (argc == 3) { |
| 17143 | - | |
| 16934 | + | |
| 17144 | 16935 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 17145 | 16936 | return JIM_ERR; |
| 17146 | 16937 | Jim_SetResult(interp, argv[2]); |
| 17147 | 16938 | return JIM_OK; |
| 17148 | 16939 | } |
| @@ -17158,10 +16949,11 @@ | ||
| 17158 | 16949 | enum |
| 17159 | 16950 | { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; |
| 17160 | 16951 | Jim_Obj *resObj; |
| 17161 | 16952 | int i; |
| 17162 | 16953 | int retCode; |
| 16954 | + int shared; | |
| 17163 | 16955 | |
| 17164 | 16956 | struct lsort_info info; |
| 17165 | 16957 | |
| 17166 | 16958 | if (argc < 2) { |
| 17167 | 16959 | Jim_WrongNumArgs(interp, 1, argv, "?options? list"); |
| @@ -17223,16 +17015,18 @@ | ||
| 17223 | 17015 | info.indexed = 1; |
| 17224 | 17016 | i++; |
| 17225 | 17017 | break; |
| 17226 | 17018 | } |
| 17227 | 17019 | } |
| 17228 | - resObj = Jim_DuplicateObj(interp, argv[argc - 1]); | |
| 17020 | + resObj = argv[argc - 1]; | |
| 17021 | + if ((shared = Jim_IsShared(resObj))) | |
| 17022 | + resObj = Jim_DuplicateObj(interp, resObj); | |
| 17229 | 17023 | retCode = ListSortElements(interp, resObj, &info); |
| 17230 | 17024 | if (retCode == JIM_OK) { |
| 17231 | 17025 | Jim_SetResult(interp, resObj); |
| 17232 | 17026 | } |
| 17233 | - else { | |
| 17027 | + else if (shared) { | |
| 17234 | 17028 | Jim_FreeNewObj(interp, resObj); |
| 17235 | 17029 | } |
| 17236 | 17030 | return retCode; |
| 17237 | 17031 | } |
| 17238 | 17032 | |
| @@ -17253,11 +17047,11 @@ | ||
| 17253 | 17047 | } |
| 17254 | 17048 | else { |
| 17255 | 17049 | int new_obj = 0; |
| 17256 | 17050 | stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 17257 | 17051 | if (!stringObjPtr) { |
| 17258 | - | |
| 17052 | + | |
| 17259 | 17053 | stringObjPtr = Jim_NewEmptyStringObj(interp); |
| 17260 | 17054 | new_obj = 1; |
| 17261 | 17055 | } |
| 17262 | 17056 | else if (Jim_IsShared(stringObjPtr)) { |
| 17263 | 17057 | new_obj = 1; |
| @@ -17274,10 +17068,11 @@ | ||
| 17274 | 17068 | } |
| 17275 | 17069 | } |
| 17276 | 17070 | Jim_SetResult(interp, stringObjPtr); |
| 17277 | 17071 | return JIM_OK; |
| 17278 | 17072 | } |
| 17073 | + | |
| 17279 | 17074 | |
| 17280 | 17075 | |
| 17281 | 17076 | static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17282 | 17077 | { |
| 17283 | 17078 | #if !defined(JIM_DEBUG_COMMAND) |
| @@ -17302,11 +17097,11 @@ | ||
| 17302 | 17097 | else { |
| 17303 | 17098 | rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); |
| 17304 | 17099 | } |
| 17305 | 17100 | |
| 17306 | 17101 | if (rc == JIM_ERR) { |
| 17307 | - | |
| 17102 | + | |
| 17308 | 17103 | interp->addStackTrace++; |
| 17309 | 17104 | } |
| 17310 | 17105 | return rc; |
| 17311 | 17106 | } |
| 17312 | 17107 | |
| @@ -17316,14 +17111,14 @@ | ||
| 17316 | 17111 | if (argc >= 2) { |
| 17317 | 17112 | int retcode; |
| 17318 | 17113 | Jim_CallFrame *savedCallFrame, *targetCallFrame; |
| 17319 | 17114 | const char *str; |
| 17320 | 17115 | |
| 17321 | - | |
| 17116 | + | |
| 17322 | 17117 | savedCallFrame = interp->framePtr; |
| 17323 | 17118 | |
| 17324 | - | |
| 17119 | + | |
| 17325 | 17120 | str = Jim_String(argv[1]); |
| 17326 | 17121 | if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { |
| 17327 | 17122 | targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17328 | 17123 | argc--; |
| 17329 | 17124 | argv++; |
| @@ -17336,11 +17131,11 @@ | ||
| 17336 | 17131 | } |
| 17337 | 17132 | if (argc < 2) { |
| 17338 | 17133 | Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); |
| 17339 | 17134 | return JIM_ERR; |
| 17340 | 17135 | } |
| 17341 | - | |
| 17136 | + | |
| 17342 | 17137 | interp->framePtr = targetCallFrame; |
| 17343 | 17138 | if (argc == 2) { |
| 17344 | 17139 | retcode = Jim_EvalObj(interp, argv[1]); |
| 17345 | 17140 | } |
| 17346 | 17141 | else { |
| @@ -17356,32 +17151,29 @@ | ||
| 17356 | 17151 | } |
| 17357 | 17152 | |
| 17358 | 17153 | |
| 17359 | 17154 | static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17360 | 17155 | { |
| 17361 | - Jim_Obj *exprResultPtr; | |
| 17362 | 17156 | int retcode; |
| 17363 | 17157 | |
| 17364 | 17158 | if (argc == 2) { |
| 17365 | - retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr); | |
| 17159 | + retcode = Jim_EvalExpression(interp, argv[1]); | |
| 17366 | 17160 | } |
| 17367 | 17161 | else if (argc > 2) { |
| 17368 | 17162 | Jim_Obj *objPtr; |
| 17369 | 17163 | |
| 17370 | 17164 | objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); |
| 17371 | 17165 | Jim_IncrRefCount(objPtr); |
| 17372 | - retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr); | |
| 17166 | + retcode = Jim_EvalExpression(interp, objPtr); | |
| 17373 | 17167 | Jim_DecrRefCount(interp, objPtr); |
| 17374 | 17168 | } |
| 17375 | 17169 | else { |
| 17376 | 17170 | Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); |
| 17377 | 17171 | return JIM_ERR; |
| 17378 | 17172 | } |
| 17379 | 17173 | if (retcode != JIM_OK) |
| 17380 | 17174 | return retcode; |
| 17381 | - Jim_SetResult(interp, exprResultPtr); | |
| 17382 | - Jim_DecrRefCount(interp, exprResultPtr); | |
| 17383 | 17175 | return JIM_OK; |
| 17384 | 17176 | } |
| 17385 | 17177 | |
| 17386 | 17178 | |
| 17387 | 17179 | static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -17438,15 +17230,15 @@ | ||
| 17438 | 17230 | if (i != argc - 1 && i != argc) { |
| 17439 | 17231 | Jim_WrongNumArgs(interp, 1, argv, |
| 17440 | 17232 | "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?"); |
| 17441 | 17233 | } |
| 17442 | 17234 | |
| 17443 | - | |
| 17235 | + | |
| 17444 | 17236 | if (stackTraceObj && returnCode == JIM_ERR) { |
| 17445 | 17237 | JimSetStackTrace(interp, stackTraceObj); |
| 17446 | 17238 | } |
| 17447 | - | |
| 17239 | + | |
| 17448 | 17240 | if (errorCodeObj && returnCode == JIM_ERR) { |
| 17449 | 17241 | Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj); |
| 17450 | 17242 | } |
| 17451 | 17243 | interp->returnCode = returnCode; |
| 17452 | 17244 | interp->returnLevel = level; |
| @@ -17463,31 +17255,31 @@ | ||
| 17463 | 17255 | if (interp->framePtr->level == 0) { |
| 17464 | 17256 | Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); |
| 17465 | 17257 | return JIM_ERR; |
| 17466 | 17258 | } |
| 17467 | 17259 | else if (argc >= 2) { |
| 17468 | - | |
| 17260 | + | |
| 17469 | 17261 | Jim_CallFrame *cf = interp->framePtr->parent; |
| 17470 | 17262 | |
| 17471 | 17263 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17472 | 17264 | if (cmdPtr == NULL) { |
| 17473 | 17265 | return JIM_ERR; |
| 17474 | 17266 | } |
| 17475 | 17267 | |
| 17476 | 17268 | JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); |
| 17477 | 17269 | |
| 17478 | - | |
| 17270 | + | |
| 17479 | 17271 | JimIncrCmdRefCount(cmdPtr); |
| 17480 | 17272 | cf->tailcallCmd = cmdPtr; |
| 17481 | 17273 | |
| 17482 | - | |
| 17274 | + | |
| 17483 | 17275 | JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); |
| 17484 | 17276 | |
| 17485 | 17277 | cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); |
| 17486 | 17278 | Jim_IncrRefCount(cf->tailcallObj); |
| 17487 | 17279 | |
| 17488 | - | |
| 17280 | + | |
| 17489 | 17281 | return JIM_EVAL; |
| 17490 | 17282 | } |
| 17491 | 17283 | return JIM_OK; |
| 17492 | 17284 | } |
| 17493 | 17285 | |
| @@ -17494,11 +17286,11 @@ | ||
| 17494 | 17286 | static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17495 | 17287 | { |
| 17496 | 17288 | Jim_Obj *cmdList; |
| 17497 | 17289 | Jim_Obj *prefixListObj = Jim_CmdPrivData(interp); |
| 17498 | 17290 | |
| 17499 | - | |
| 17291 | + | |
| 17500 | 17292 | cmdList = Jim_DuplicateObj(interp, prefixListObj); |
| 17501 | 17293 | Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1); |
| 17502 | 17294 | |
| 17503 | 17295 | return JimEvalObjList(interp, cmdList); |
| 17504 | 17296 | } |
| @@ -17552,22 +17344,22 @@ | ||
| 17552 | 17344 | else { |
| 17553 | 17345 | cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL); |
| 17554 | 17346 | } |
| 17555 | 17347 | |
| 17556 | 17348 | if (cmd) { |
| 17557 | - | |
| 17349 | + | |
| 17558 | 17350 | Jim_Obj *qualifiedCmdNameObj; |
| 17559 | 17351 | const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj); |
| 17560 | 17352 | |
| 17561 | 17353 | JimCreateCommand(interp, cmdname, cmd); |
| 17562 | 17354 | |
| 17563 | - | |
| 17355 | + | |
| 17564 | 17356 | JimUpdateProcNamespace(interp, cmd, cmdname); |
| 17565 | 17357 | |
| 17566 | 17358 | JimFreeQualifiedName(interp, qualifiedCmdNameObj); |
| 17567 | 17359 | |
| 17568 | - | |
| 17360 | + | |
| 17569 | 17361 | Jim_SetResult(interp, argv[1]); |
| 17570 | 17362 | return JIM_OK; |
| 17571 | 17363 | } |
| 17572 | 17364 | return JIM_ERR; |
| 17573 | 17365 | } |
| @@ -17580,17 +17372,17 @@ | ||
| 17580 | 17372 | if (argc < 2) { |
| 17581 | 17373 | Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); |
| 17582 | 17374 | return JIM_ERR; |
| 17583 | 17375 | } |
| 17584 | 17376 | |
| 17585 | - | |
| 17377 | + | |
| 17586 | 17378 | interp->local++; |
| 17587 | 17379 | retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); |
| 17588 | 17380 | interp->local--; |
| 17589 | 17381 | |
| 17590 | 17382 | |
| 17591 | - | |
| 17383 | + | |
| 17592 | 17384 | if (retcode == 0) { |
| 17593 | 17385 | Jim_Obj *cmdNameObj = Jim_GetResult(interp); |
| 17594 | 17386 | |
| 17595 | 17387 | if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) { |
| 17596 | 17388 | return JIM_ERR; |
| @@ -17619,18 +17411,18 @@ | ||
| 17619 | 17411 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17620 | 17412 | if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) { |
| 17621 | 17413 | Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]); |
| 17622 | 17414 | return JIM_ERR; |
| 17623 | 17415 | } |
| 17624 | - | |
| 17416 | + | |
| 17625 | 17417 | cmdPtr->u.proc.upcall++; |
| 17626 | 17418 | JimIncrCmdRefCount(cmdPtr); |
| 17627 | 17419 | |
| 17628 | - | |
| 17420 | + | |
| 17629 | 17421 | retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); |
| 17630 | 17422 | |
| 17631 | - | |
| 17423 | + | |
| 17632 | 17424 | cmdPtr->u.proc.upcall--; |
| 17633 | 17425 | JimDecrCmdRefCount(interp, cmdPtr); |
| 17634 | 17426 | |
| 17635 | 17427 | return retcode; |
| 17636 | 17428 | } |
| @@ -17657,11 +17449,11 @@ | ||
| 17657 | 17449 | return JIM_ERR; |
| 17658 | 17450 | } |
| 17659 | 17451 | |
| 17660 | 17452 | if (len == 3) { |
| 17661 | 17453 | #ifdef jim_ext_namespace |
| 17662 | - | |
| 17454 | + | |
| 17663 | 17455 | nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2)); |
| 17664 | 17456 | #else |
| 17665 | 17457 | Jim_SetResultString(interp, "namespaces not enabled", -1); |
| 17666 | 17458 | return JIM_ERR; |
| 17667 | 17459 | #endif |
| @@ -17670,11 +17462,11 @@ | ||
| 17670 | 17462 | bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1); |
| 17671 | 17463 | |
| 17672 | 17464 | cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj); |
| 17673 | 17465 | |
| 17674 | 17466 | if (cmd) { |
| 17675 | - | |
| 17467 | + | |
| 17676 | 17468 | nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv)); |
| 17677 | 17469 | nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1); |
| 17678 | 17470 | Jim_IncrRefCount(nargv[0]); |
| 17679 | 17471 | memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv)); |
| 17680 | 17472 | ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv); |
| @@ -17700,11 +17492,11 @@ | ||
| 17700 | 17492 | static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17701 | 17493 | { |
| 17702 | 17494 | int i; |
| 17703 | 17495 | Jim_CallFrame *targetCallFrame; |
| 17704 | 17496 | |
| 17705 | - | |
| 17497 | + | |
| 17706 | 17498 | if (argc > 3 && (argc % 2 == 0)) { |
| 17707 | 17499 | targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17708 | 17500 | argc--; |
| 17709 | 17501 | argv++; |
| 17710 | 17502 | } |
| @@ -17713,17 +17505,17 @@ | ||
| 17713 | 17505 | } |
| 17714 | 17506 | if (targetCallFrame == NULL) { |
| 17715 | 17507 | return JIM_ERR; |
| 17716 | 17508 | } |
| 17717 | 17509 | |
| 17718 | - | |
| 17510 | + | |
| 17719 | 17511 | if (argc < 3) { |
| 17720 | 17512 | Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?"); |
| 17721 | 17513 | return JIM_ERR; |
| 17722 | 17514 | } |
| 17723 | 17515 | |
| 17724 | - | |
| 17516 | + | |
| 17725 | 17517 | for (i = 1; i < argc; i += 2) { |
| 17726 | 17518 | if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK) |
| 17727 | 17519 | return JIM_ERR; |
| 17728 | 17520 | } |
| 17729 | 17521 | return JIM_OK; |
| @@ -17736,15 +17528,15 @@ | ||
| 17736 | 17528 | |
| 17737 | 17529 | if (argc < 2) { |
| 17738 | 17530 | Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?"); |
| 17739 | 17531 | return JIM_ERR; |
| 17740 | 17532 | } |
| 17741 | - | |
| 17533 | + | |
| 17742 | 17534 | if (interp->framePtr->level == 0) |
| 17743 | - return JIM_OK; | |
| 17535 | + return JIM_OK; | |
| 17744 | 17536 | for (i = 1; i < argc; i++) { |
| 17745 | - | |
| 17537 | + | |
| 17746 | 17538 | const char *name = Jim_String(argv[i]); |
| 17747 | 17539 | if (name[0] != ':' || name[1] != ':') { |
| 17748 | 17540 | if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK) |
| 17749 | 17541 | return JIM_ERR; |
| 17750 | 17542 | } |
| @@ -17767,21 +17559,21 @@ | ||
| 17767 | 17559 | } |
| 17768 | 17560 | |
| 17769 | 17561 | str = Jim_String(objPtr); |
| 17770 | 17562 | strLen = Jim_Utf8Length(interp, objPtr); |
| 17771 | 17563 | |
| 17772 | - | |
| 17564 | + | |
| 17773 | 17565 | resultObjPtr = Jim_NewStringObj(interp, "", 0); |
| 17774 | 17566 | while (strLen) { |
| 17775 | 17567 | for (i = 0; i < numMaps; i += 2) { |
| 17776 | - Jim_Obj *objPtr; | |
| 17568 | + Jim_Obj *eachObjPtr; | |
| 17777 | 17569 | const char *k; |
| 17778 | 17570 | int kl; |
| 17779 | 17571 | |
| 17780 | - objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); | |
| 17781 | - k = Jim_String(objPtr); | |
| 17782 | - kl = Jim_Utf8Length(interp, objPtr); | |
| 17572 | + eachObjPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); | |
| 17573 | + k = Jim_String(eachObjPtr); | |
| 17574 | + kl = Jim_Utf8Length(interp, eachObjPtr); | |
| 17783 | 17575 | |
| 17784 | 17576 | if (strLen >= kl && kl) { |
| 17785 | 17577 | int rc; |
| 17786 | 17578 | rc = JimStringCompareLen(str, k, kl, nocase); |
| 17787 | 17579 | if (rc == 0) { |
| @@ -17794,11 +17586,11 @@ | ||
| 17794 | 17586 | strLen -= kl; |
| 17795 | 17587 | break; |
| 17796 | 17588 | } |
| 17797 | 17589 | } |
| 17798 | 17590 | } |
| 17799 | - if (i == numMaps) { | |
| 17591 | + if (i == numMaps) { | |
| 17800 | 17592 | int c; |
| 17801 | 17593 | if (noMatchStart == NULL) |
| 17802 | 17594 | noMatchStart = str; |
| 17803 | 17595 | str += utf8_tounicode(str, &c); |
| 17804 | 17596 | strLen--; |
| @@ -17838,11 +17630,11 @@ | ||
| 17838 | 17630 | Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); |
| 17839 | 17631 | return JIM_ERR; |
| 17840 | 17632 | } |
| 17841 | 17633 | if (Jim_GetEnum(interp, argv[1], options, &option, NULL, |
| 17842 | 17634 | JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) |
| 17843 | - return JIM_ERR; | |
| 17635 | + return Jim_CheckShowCommands(interp, argv[1], options); | |
| 17844 | 17636 | |
| 17845 | 17637 | switch (option) { |
| 17846 | 17638 | case OPT_LENGTH: |
| 17847 | 17639 | case OPT_BYTELENGTH: |
| 17848 | 17640 | if (argc != 3) { |
| @@ -17859,11 +17651,11 @@ | ||
| 17859 | 17651 | return JIM_OK; |
| 17860 | 17652 | |
| 17861 | 17653 | case OPT_CAT:{ |
| 17862 | 17654 | Jim_Obj *objPtr; |
| 17863 | 17655 | if (argc == 3) { |
| 17864 | - | |
| 17656 | + | |
| 17865 | 17657 | objPtr = argv[2]; |
| 17866 | 17658 | } |
| 17867 | 17659 | else { |
| 17868 | 17660 | int i; |
| 17869 | 17661 | |
| @@ -17878,11 +17670,11 @@ | ||
| 17878 | 17670 | } |
| 17879 | 17671 | |
| 17880 | 17672 | case OPT_COMPARE: |
| 17881 | 17673 | case OPT_EQUAL: |
| 17882 | 17674 | { |
| 17883 | - | |
| 17675 | + | |
| 17884 | 17676 | long opt_length = -1; |
| 17885 | 17677 | int n = argc - 4; |
| 17886 | 17678 | int i = 2; |
| 17887 | 17679 | while (n > 0) { |
| 17888 | 17680 | int subopt; |
| @@ -17891,16 +17683,16 @@ | ||
| 17891 | 17683 | badcompareargs: |
| 17892 | 17684 | Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2"); |
| 17893 | 17685 | return JIM_ERR; |
| 17894 | 17686 | } |
| 17895 | 17687 | if (subopt == 0) { |
| 17896 | - | |
| 17688 | + | |
| 17897 | 17689 | opt_case = 0; |
| 17898 | 17690 | n--; |
| 17899 | 17691 | } |
| 17900 | 17692 | else { |
| 17901 | - | |
| 17693 | + | |
| 17902 | 17694 | if (n < 2) { |
| 17903 | 17695 | goto badcompareargs; |
| 17904 | 17696 | } |
| 17905 | 17697 | if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) { |
| 17906 | 17698 | return JIM_ERR; |
| @@ -17911,11 +17703,11 @@ | ||
| 17911 | 17703 | if (n) { |
| 17912 | 17704 | goto badcompareargs; |
| 17913 | 17705 | } |
| 17914 | 17706 | argv += argc - 2; |
| 17915 | 17707 | if (opt_length < 0 && option != OPT_COMPARE && opt_case) { |
| 17916 | - | |
| 17708 | + | |
| 17917 | 17709 | Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1])); |
| 17918 | 17710 | } |
| 17919 | 17711 | else { |
| 17920 | 17712 | if (opt_length >= 0) { |
| 17921 | 17713 | n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case); |
| @@ -18025,11 +17817,10 @@ | ||
| 18025 | 17817 | } |
| 18026 | 17818 | |
| 18027 | 17819 | case OPT_REVERSE:{ |
| 18028 | 17820 | char *buf, *p; |
| 18029 | 17821 | const char *str; |
| 18030 | - int len; | |
| 18031 | 17822 | int i; |
| 18032 | 17823 | |
| 18033 | 17824 | if (argc != 3) { |
| 18034 | 17825 | Jim_WrongNumArgs(interp, 2, argv, "string"); |
| 18035 | 17826 | return JIM_ERR; |
| @@ -18069,11 +17860,11 @@ | ||
| 18069 | 17860 | } |
| 18070 | 17861 | if (idx < 0 || idx >= len || str == NULL) { |
| 18071 | 17862 | Jim_SetResultString(interp, "", 0); |
| 18072 | 17863 | } |
| 18073 | 17864 | else if (len == Jim_Length(argv[2])) { |
| 18074 | - | |
| 17865 | + | |
| 18075 | 17866 | Jim_SetResultString(interp, str + idx, 1); |
| 18076 | 17867 | } |
| 18077 | 17868 | else { |
| 18078 | 17869 | int c; |
| 18079 | 17870 | int i = utf8_index(str, idx); |
| @@ -18223,11 +18014,11 @@ | ||
| 18223 | 18014 | { |
| 18224 | 18015 | int exitCode = 0; |
| 18225 | 18016 | int i; |
| 18226 | 18017 | int sig = 0; |
| 18227 | 18018 | |
| 18228 | - | |
| 18019 | + | |
| 18229 | 18020 | jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); |
| 18230 | 18021 | static const int max_ignore_code = sizeof(ignore_mask) * 8; |
| 18231 | 18022 | |
| 18232 | 18023 | Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); |
| 18233 | 18024 | |
| @@ -18234,11 +18025,11 @@ | ||
| 18234 | 18025 | for (i = 1; i < argc - 1; i++) { |
| 18235 | 18026 | const char *arg = Jim_String(argv[i]); |
| 18236 | 18027 | jim_wide option; |
| 18237 | 18028 | int ignore; |
| 18238 | 18029 | |
| 18239 | - | |
| 18030 | + | |
| 18240 | 18031 | if (strcmp(arg, "--") == 0) { |
| 18241 | 18032 | i++; |
| 18242 | 18033 | break; |
| 18243 | 18034 | } |
| 18244 | 18035 | if (*arg != '-') { |
| @@ -18285,28 +18076,28 @@ | ||
| 18285 | 18076 | sig++; |
| 18286 | 18077 | } |
| 18287 | 18078 | |
| 18288 | 18079 | interp->signal_level += sig; |
| 18289 | 18080 | if (Jim_CheckSignal(interp)) { |
| 18290 | - | |
| 18081 | + | |
| 18291 | 18082 | exitCode = JIM_SIGNAL; |
| 18292 | 18083 | } |
| 18293 | 18084 | else { |
| 18294 | 18085 | exitCode = Jim_EvalObj(interp, argv[0]); |
| 18295 | - | |
| 18086 | + | |
| 18296 | 18087 | interp->errorFlag = 0; |
| 18297 | 18088 | } |
| 18298 | 18089 | interp->signal_level -= sig; |
| 18299 | 18090 | |
| 18300 | - | |
| 18091 | + | |
| 18301 | 18092 | if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { |
| 18302 | - | |
| 18093 | + | |
| 18303 | 18094 | return exitCode; |
| 18304 | 18095 | } |
| 18305 | 18096 | |
| 18306 | 18097 | if (sig && exitCode == JIM_SIGNAL) { |
| 18307 | - | |
| 18098 | + | |
| 18308 | 18099 | if (interp->signal_set_result) { |
| 18309 | 18100 | interp->signal_set_result(interp, interp->sigmask); |
| 18310 | 18101 | } |
| 18311 | 18102 | else { |
| 18312 | 18103 | Jim_SetResultInt(interp, interp->sigmask); |
| @@ -18345,125 +18136,10 @@ | ||
| 18345 | 18136 | } |
| 18346 | 18137 | Jim_SetResultInt(interp, exitCode); |
| 18347 | 18138 | return JIM_OK; |
| 18348 | 18139 | } |
| 18349 | 18140 | |
| 18350 | -#ifdef JIM_REFERENCES | |
| 18351 | - | |
| 18352 | - | |
| 18353 | -static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 18354 | -{ | |
| 18355 | - if (argc != 3 && argc != 4) { | |
| 18356 | - Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?"); | |
| 18357 | - return JIM_ERR; | |
| 18358 | - } | |
| 18359 | - if (argc == 3) { | |
| 18360 | - Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL)); | |
| 18361 | - } | |
| 18362 | - else { | |
| 18363 | - Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3])); | |
| 18364 | - } | |
| 18365 | - return JIM_OK; | |
| 18366 | -} | |
| 18367 | - | |
| 18368 | - | |
| 18369 | -static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 18370 | -{ | |
| 18371 | - Jim_Reference *refPtr; | |
| 18372 | - | |
| 18373 | - if (argc != 2) { | |
| 18374 | - Jim_WrongNumArgs(interp, 1, argv, "reference"); | |
| 18375 | - return JIM_ERR; | |
| 18376 | - } | |
| 18377 | - if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) | |
| 18378 | - return JIM_ERR; | |
| 18379 | - Jim_SetResult(interp, refPtr->objPtr); | |
| 18380 | - return JIM_OK; | |
| 18381 | -} | |
| 18382 | - | |
| 18383 | - | |
| 18384 | -static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 18385 | -{ | |
| 18386 | - Jim_Reference *refPtr; | |
| 18387 | - | |
| 18388 | - if (argc != 3) { | |
| 18389 | - Jim_WrongNumArgs(interp, 1, argv, "reference newValue"); | |
| 18390 | - return JIM_ERR; | |
| 18391 | - } | |
| 18392 | - if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) | |
| 18393 | - return JIM_ERR; | |
| 18394 | - Jim_IncrRefCount(argv[2]); | |
| 18395 | - Jim_DecrRefCount(interp, refPtr->objPtr); | |
| 18396 | - refPtr->objPtr = argv[2]; | |
| 18397 | - Jim_SetResult(interp, argv[2]); | |
| 18398 | - return JIM_OK; | |
| 18399 | -} | |
| 18400 | - | |
| 18401 | - | |
| 18402 | -static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 18403 | -{ | |
| 18404 | - if (argc != 1) { | |
| 18405 | - Jim_WrongNumArgs(interp, 1, argv, ""); | |
| 18406 | - return JIM_ERR; | |
| 18407 | - } | |
| 18408 | - Jim_SetResultInt(interp, Jim_Collect(interp)); | |
| 18409 | - | |
| 18410 | - | |
| 18411 | - while (interp->freeList) { | |
| 18412 | - Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr; | |
| 18413 | - Jim_Free(interp->freeList); | |
| 18414 | - interp->freeList = nextObjPtr; | |
| 18415 | - } | |
| 18416 | - | |
| 18417 | - return JIM_OK; | |
| 18418 | -} | |
| 18419 | - | |
| 18420 | - | |
| 18421 | -static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 18422 | -{ | |
| 18423 | - if (argc != 2 && argc != 3) { | |
| 18424 | - Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?"); | |
| 18425 | - return JIM_ERR; | |
| 18426 | - } | |
| 18427 | - if (argc == 2) { | |
| 18428 | - Jim_Obj *cmdNamePtr; | |
| 18429 | - | |
| 18430 | - if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK) | |
| 18431 | - return JIM_ERR; | |
| 18432 | - if (cmdNamePtr != NULL) | |
| 18433 | - Jim_SetResult(interp, cmdNamePtr); | |
| 18434 | - } | |
| 18435 | - else { | |
| 18436 | - if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK) | |
| 18437 | - return JIM_ERR; | |
| 18438 | - Jim_SetResult(interp, argv[2]); | |
| 18439 | - } | |
| 18440 | - return JIM_OK; | |
| 18441 | -} | |
| 18442 | - | |
| 18443 | - | |
| 18444 | -static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) | |
| 18445 | -{ | |
| 18446 | - Jim_Obj *listObjPtr; | |
| 18447 | - Jim_HashTableIterator htiter; | |
| 18448 | - Jim_HashEntry *he; | |
| 18449 | - | |
| 18450 | - listObjPtr = Jim_NewListObj(interp, NULL, 0); | |
| 18451 | - | |
| 18452 | - JimInitHashTableIterator(&interp->references, &htiter); | |
| 18453 | - while ((he = Jim_NextHashEntry(&htiter)) != NULL) { | |
| 18454 | - char buf[JIM_REFERENCE_SPACE + 1]; | |
| 18455 | - Jim_Reference *refPtr = Jim_GetHashEntryVal(he); | |
| 18456 | - const unsigned long *refId = he->key; | |
| 18457 | - | |
| 18458 | - JimFormatReference(buf, refPtr, *refId); | |
| 18459 | - Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); | |
| 18460 | - } | |
| 18461 | - Jim_SetResult(interp, listObjPtr); | |
| 18462 | - return JIM_OK; | |
| 18463 | -} | |
| 18464 | -#endif | |
| 18465 | 18141 | |
| 18466 | 18142 | |
| 18467 | 18143 | static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18468 | 18144 | { |
| 18469 | 18145 | if (argc != 3) { |
| @@ -18476,56 +18152,43 @@ | ||
| 18476 | 18152 | } |
| 18477 | 18153 | |
| 18478 | 18154 | return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2])); |
| 18479 | 18155 | } |
| 18480 | 18156 | |
| 18481 | -#define JIM_DICTMATCH_VALUES 0x0001 | |
| 18482 | - | |
| 18483 | -typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type); | |
| 18484 | - | |
| 18485 | -static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) | |
| 18486 | -{ | |
| 18487 | - Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); | |
| 18488 | - if (type & JIM_DICTMATCH_VALUES) { | |
| 18489 | - Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); | |
| 18490 | - } | |
| 18491 | -} | |
| 18492 | - | |
| 18493 | -static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, | |
| 18494 | - JimDictMatchCallbackType *callback, int type) | |
| 18495 | -{ | |
| 18496 | - Jim_HashEntry *he; | |
| 18497 | - Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); | |
| 18498 | - | |
| 18499 | - | |
| 18500 | - Jim_HashTableIterator htiter; | |
| 18501 | - JimInitHashTableIterator(ht, &htiter); | |
| 18502 | - while ((he = Jim_NextHashEntry(&htiter)) != NULL) { | |
| 18503 | - if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) { | |
| 18504 | - callback(interp, listObjPtr, he, type); | |
| 18505 | - } | |
| 18506 | - } | |
| 18507 | - | |
| 18508 | - return listObjPtr; | |
| 18509 | -} | |
| 18510 | - | |
| 18511 | - | |
| 18512 | -int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) | |
| 18513 | -{ | |
| 18514 | - if (SetDictFromAny(interp, objPtr) != JIM_OK) { | |
| 18515 | - return JIM_ERR; | |
| 18516 | - } | |
| 18517 | - Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0)); | |
| 18518 | - return JIM_OK; | |
| 18519 | -} | |
| 18520 | - | |
| 18521 | -int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) | |
| 18522 | -{ | |
| 18523 | - if (SetDictFromAny(interp, objPtr) != JIM_OK) { | |
| 18524 | - return JIM_ERR; | |
| 18525 | - } | |
| 18526 | - Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES)); | |
| 18157 | +#define JIM_DICTMATCH_KEYS 0x0001 | |
| 18158 | +#define JIM_DICTMATCH_VALUES 0x002 | |
| 18159 | + | |
| 18160 | +int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types) | |
| 18161 | +{ | |
| 18162 | + Jim_HashEntry *he; | |
| 18163 | + Jim_Obj *listObjPtr; | |
| 18164 | + Jim_HashTableIterator htiter; | |
| 18165 | + | |
| 18166 | + if (SetDictFromAny(interp, objPtr) != JIM_OK) { | |
| 18167 | + return JIM_ERR; | |
| 18168 | + } | |
| 18169 | + | |
| 18170 | + listObjPtr = Jim_NewListObj(interp, NULL, 0); | |
| 18171 | + | |
| 18172 | + JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter); | |
| 18173 | + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { | |
| 18174 | + if (patternObj) { | |
| 18175 | + Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he); | |
| 18176 | + if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) { | |
| 18177 | + | |
| 18178 | + continue; | |
| 18179 | + } | |
| 18180 | + } | |
| 18181 | + if (return_types & JIM_DICTMATCH_KEYS) { | |
| 18182 | + Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); | |
| 18183 | + } | |
| 18184 | + if (return_types & JIM_DICTMATCH_VALUES) { | |
| 18185 | + Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); | |
| 18186 | + } | |
| 18187 | + } | |
| 18188 | + | |
| 18189 | + Jim_SetResult(interp, listObjPtr); | |
| 18527 | 18190 | return JIM_OK; |
| 18528 | 18191 | } |
| 18529 | 18192 | |
| 18530 | 18193 | int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18531 | 18194 | { |
| @@ -18532,38 +18195,85 @@ | ||
| 18532 | 18195 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18533 | 18196 | return -1; |
| 18534 | 18197 | } |
| 18535 | 18198 | return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 18536 | 18199 | } |
| 18200 | + | |
| 18201 | +Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv) | |
| 18202 | +{ | |
| 18203 | + Jim_Obj *objPtr = Jim_NewDictObj(interp, NULL, 0); | |
| 18204 | + int i; | |
| 18205 | + | |
| 18206 | + JimPanic((objc == 0, "Jim_DictMerge called with objc=0")); | |
| 18207 | + | |
| 18208 | + | |
| 18209 | + | |
| 18210 | + for (i = 0; i < objc; i++) { | |
| 18211 | + Jim_HashTable *ht; | |
| 18212 | + Jim_HashTableIterator htiter; | |
| 18213 | + Jim_HashEntry *he; | |
| 18214 | + | |
| 18215 | + if (SetDictFromAny(interp, objv[i]) != JIM_OK) { | |
| 18216 | + Jim_FreeNewObj(interp, objPtr); | |
| 18217 | + return NULL; | |
| 18218 | + } | |
| 18219 | + ht = objv[i]->internalRep.ptr; | |
| 18220 | + JimInitHashTableIterator(ht, &htiter); | |
| 18221 | + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { | |
| 18222 | + Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he)); | |
| 18223 | + } | |
| 18224 | + } | |
| 18225 | + return objPtr; | |
| 18226 | +} | |
| 18537 | 18227 | |
| 18538 | 18228 | int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18539 | 18229 | { |
| 18540 | 18230 | Jim_HashTable *ht; |
| 18541 | 18231 | unsigned int i; |
| 18232 | + char buffer[100]; | |
| 18233 | + int sum = 0; | |
| 18234 | + int nonzero_count = 0; | |
| 18235 | + Jim_Obj *output; | |
| 18236 | + int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | |
| 18542 | 18237 | |
| 18543 | 18238 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18544 | 18239 | return JIM_ERR; |
| 18545 | 18240 | } |
| 18546 | 18241 | |
| 18547 | 18242 | ht = (Jim_HashTable *)objPtr->internalRep.ptr; |
| 18548 | 18243 | |
| 18549 | - | |
| 18550 | - printf("%d entries in table, %d buckets\n", ht->used, ht->size); | |
| 18244 | + | |
| 18245 | + snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size); | |
| 18246 | + output = Jim_NewStringObj(interp, buffer, -1); | |
| 18551 | 18247 | |
| 18552 | 18248 | for (i = 0; i < ht->size; i++) { |
| 18553 | 18249 | Jim_HashEntry *he = ht->table[i]; |
| 18554 | - | |
| 18555 | - if (he) { | |
| 18556 | - printf("%d: ", i); | |
| 18557 | - | |
| 18558 | - while (he) { | |
| 18559 | - printf(" %s", Jim_String(he->key)); | |
| 18560 | - he = he->next; | |
| 18561 | - } | |
| 18562 | - printf("\n"); | |
| 18250 | + int entries = 0; | |
| 18251 | + while (he) { | |
| 18252 | + entries++; | |
| 18253 | + he = he->next; | |
| 18254 | + } | |
| 18255 | + if (entries > 9) { | |
| 18256 | + bucket_counts[10]++; | |
| 18257 | + } | |
| 18258 | + else { | |
| 18259 | + bucket_counts[entries]++; | |
| 18260 | + } | |
| 18261 | + if (entries) { | |
| 18262 | + sum += entries; | |
| 18263 | + nonzero_count++; | |
| 18563 | 18264 | } |
| 18564 | 18265 | } |
| 18266 | + for (i = 0; i < 10; i++) { | |
| 18267 | + snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]); | |
| 18268 | + Jim_AppendString(interp, output, buffer, -1); | |
| 18269 | + } | |
| 18270 | + snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]); | |
| 18271 | + Jim_AppendString(interp, output, buffer, -1); | |
| 18272 | + snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0); | |
| 18273 | + Jim_AppendString(interp, output, buffer, -1); | |
| 18274 | + Jim_SetResult(interp, output); | |
| 18565 | 18275 | return JIM_OK; |
| 18566 | 18276 | } |
| 18567 | 18277 | |
| 18568 | 18278 | static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) |
| 18569 | 18279 | { |
| @@ -18573,14 +18283,67 @@ | ||
| 18573 | 18283 | Jim_AppendString(interp, prefixObj, subcmd, -1); |
| 18574 | 18284 | |
| 18575 | 18285 | return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); |
| 18576 | 18286 | } |
| 18577 | 18287 | |
| 18288 | +static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const *keyv, int keyc, Jim_Obj *scriptObj) | |
| 18289 | +{ | |
| 18290 | + int i; | |
| 18291 | + Jim_Obj *objPtr; | |
| 18292 | + Jim_Obj *dictObj; | |
| 18293 | + Jim_Obj **dictValues; | |
| 18294 | + int len; | |
| 18295 | + int ret = JIM_OK; | |
| 18296 | + | |
| 18297 | + | |
| 18298 | + dictObj = Jim_GetVariable(interp, dictVarName, JIM_ERRMSG); | |
| 18299 | + if (dictObj == NULL || Jim_DictKeysVector(interp, dictObj, keyv, keyc, &objPtr, JIM_ERRMSG) != JIM_OK) { | |
| 18300 | + return JIM_ERR; | |
| 18301 | + } | |
| 18302 | + | |
| 18303 | + if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) { | |
| 18304 | + return JIM_ERR; | |
| 18305 | + } | |
| 18306 | + for (i = 0; i < len; i += 2) { | |
| 18307 | + if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) { | |
| 18308 | + Jim_Free(dictValues); | |
| 18309 | + return JIM_ERR; | |
| 18310 | + } | |
| 18311 | + } | |
| 18312 | + | |
| 18313 | + | |
| 18314 | + if (Jim_Length(scriptObj)) { | |
| 18315 | + ret = Jim_EvalObj(interp, scriptObj); | |
| 18316 | + | |
| 18317 | + | |
| 18318 | + if (ret == JIM_OK && Jim_GetVariable(interp, dictVarName, 0) != NULL) { | |
| 18319 | + | |
| 18320 | + Jim_Obj **newkeyv = Jim_Alloc(sizeof(*newkeyv) * (keyc + 1)); | |
| 18321 | + for (i = 0; i < keyc; i++) { | |
| 18322 | + newkeyv[i] = keyv[i]; | |
| 18323 | + } | |
| 18324 | + | |
| 18325 | + for (i = 0; i < len; i += 2) { | |
| 18326 | + | |
| 18327 | + objPtr = Jim_GetVariable(interp, dictValues[i], 0); | |
| 18328 | + newkeyv[keyc] = dictValues[i]; | |
| 18329 | + Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0); | |
| 18330 | + } | |
| 18331 | + Jim_Free(newkeyv); | |
| 18332 | + } | |
| 18333 | + } | |
| 18334 | + | |
| 18335 | + Jim_Free(dictValues); | |
| 18336 | + | |
| 18337 | + return ret; | |
| 18338 | +} | |
| 18339 | + | |
| 18578 | 18340 | |
| 18579 | 18341 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18580 | 18342 | { |
| 18581 | 18343 | Jim_Obj *objPtr; |
| 18344 | + int types = JIM_DICTMATCH_KEYS; | |
| 18582 | 18345 | int option; |
| 18583 | 18346 | static const char * const options[] = { |
| 18584 | 18347 | "create", "get", "set", "unset", "exists", "keys", "size", "info", |
| 18585 | 18348 | "merge", "with", "append", "lappend", "incr", "remove", "values", "for", |
| 18586 | 18349 | "replace", "update", NULL |
| @@ -18596,11 +18359,11 @@ | ||
| 18596 | 18359 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18597 | 18360 | return JIM_ERR; |
| 18598 | 18361 | } |
| 18599 | 18362 | |
| 18600 | 18363 | if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { |
| 18601 | - return JIM_ERR; | |
| 18364 | + return Jim_CheckShowCommands(interp, argv[1], options); | |
| 18602 | 18365 | } |
| 18603 | 18366 | |
| 18604 | 18367 | switch (option) { |
| 18605 | 18368 | case OPT_GET: |
| 18606 | 18369 | if (argc < 3) { |
| @@ -18643,16 +18406,19 @@ | ||
| 18643 | 18406 | if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { |
| 18644 | 18407 | return JIM_ERR; |
| 18645 | 18408 | } |
| 18646 | 18409 | return JIM_OK; |
| 18647 | 18410 | |
| 18411 | + case OPT_VALUES: | |
| 18412 | + types = JIM_DICTMATCH_VALUES; | |
| 18413 | + | |
| 18648 | 18414 | case OPT_KEYS: |
| 18649 | 18415 | if (argc != 3 && argc != 4) { |
| 18650 | 18416 | Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); |
| 18651 | 18417 | return JIM_ERR; |
| 18652 | 18418 | } |
| 18653 | - return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); | |
| 18419 | + return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types); | |
| 18654 | 18420 | |
| 18655 | 18421 | case OPT_SIZE: |
| 18656 | 18422 | if (argc != 3) { |
| 18657 | 18423 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18658 | 18424 | return JIM_ERR; |
| @@ -18665,19 +18431,20 @@ | ||
| 18665 | 18431 | |
| 18666 | 18432 | case OPT_MERGE: |
| 18667 | 18433 | if (argc == 2) { |
| 18668 | 18434 | return JIM_OK; |
| 18669 | 18435 | } |
| 18670 | - if (Jim_DictSize(interp, argv[2]) < 0) { | |
| 18436 | + objPtr = Jim_DictMerge(interp, argc - 2, argv + 2); | |
| 18437 | + if (objPtr == NULL) { | |
| 18671 | 18438 | return JIM_ERR; |
| 18672 | 18439 | } |
| 18673 | - | |
| 18674 | - break; | |
| 18440 | + Jim_SetResult(interp, objPtr); | |
| 18441 | + return JIM_OK; | |
| 18675 | 18442 | |
| 18676 | 18443 | case OPT_UPDATE: |
| 18677 | 18444 | if (argc < 6 || argc % 2) { |
| 18678 | - | |
| 18445 | + | |
| 18679 | 18446 | argc = 2; |
| 18680 | 18447 | } |
| 18681 | 18448 | break; |
| 18682 | 18449 | |
| 18683 | 18450 | case OPT_CREATE: |
| @@ -18693,12 +18460,19 @@ | ||
| 18693 | 18460 | if (argc != 3) { |
| 18694 | 18461 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18695 | 18462 | return JIM_ERR; |
| 18696 | 18463 | } |
| 18697 | 18464 | return Jim_DictInfo(interp, argv[2]); |
| 18465 | + | |
| 18466 | + case OPT_WITH: | |
| 18467 | + if (argc < 4) { | |
| 18468 | + Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); | |
| 18469 | + return JIM_ERR; | |
| 18470 | + } | |
| 18471 | + return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]); | |
| 18698 | 18472 | } |
| 18699 | - | |
| 18473 | + | |
| 18700 | 18474 | return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); |
| 18701 | 18475 | } |
| 18702 | 18476 | |
| 18703 | 18477 | |
| 18704 | 18478 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -18764,11 +18538,11 @@ | ||
| 18764 | 18538 | |
| 18765 | 18539 | #ifdef jim_ext_namespace |
| 18766 | 18540 | int nons = 0; |
| 18767 | 18541 | |
| 18768 | 18542 | if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) { |
| 18769 | - | |
| 18543 | + | |
| 18770 | 18544 | argc--; |
| 18771 | 18545 | argv++; |
| 18772 | 18546 | nons = 1; |
| 18773 | 18547 | } |
| 18774 | 18548 | #endif |
| @@ -18775,16 +18549,15 @@ | ||
| 18775 | 18549 | |
| 18776 | 18550 | if (argc < 2) { |
| 18777 | 18551 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); |
| 18778 | 18552 | return JIM_ERR; |
| 18779 | 18553 | } |
| 18780 | - if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) | |
| 18781 | - != JIM_OK) { | |
| 18782 | - return JIM_ERR; | |
| 18554 | + if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { | |
| 18555 | + return Jim_CheckShowCommands(interp, argv[1], commands); | |
| 18783 | 18556 | } |
| 18784 | 18557 | |
| 18785 | - | |
| 18558 | + | |
| 18786 | 18559 | switch (cmd) { |
| 18787 | 18560 | case INFO_EXISTS: |
| 18788 | 18561 | if (argc != 3) { |
| 18789 | 18562 | Jim_WrongNumArgs(interp, 2, argv, "varName"); |
| 18790 | 18563 | return JIM_ERR; |
| @@ -18809,21 +18582,21 @@ | ||
| 18809 | 18582 | Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData); |
| 18810 | 18583 | return JIM_OK; |
| 18811 | 18584 | } |
| 18812 | 18585 | |
| 18813 | 18586 | case INFO_CHANNELS: |
| 18814 | - mode++; | |
| 18587 | + mode++; | |
| 18815 | 18588 | #ifndef jim_ext_aio |
| 18816 | 18589 | Jim_SetResultString(interp, "aio not enabled", -1); |
| 18817 | 18590 | return JIM_ERR; |
| 18818 | 18591 | #endif |
| 18819 | - | |
| 18592 | + | |
| 18820 | 18593 | case INFO_PROCS: |
| 18821 | - mode++; | |
| 18822 | - | |
| 18594 | + mode++; | |
| 18595 | + | |
| 18823 | 18596 | case INFO_COMMANDS: |
| 18824 | - | |
| 18597 | + | |
| 18825 | 18598 | if (argc != 2 && argc != 3) { |
| 18826 | 18599 | Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18827 | 18600 | return JIM_ERR; |
| 18828 | 18601 | } |
| 18829 | 18602 | #ifdef jim_ext_namespace |
| @@ -18835,17 +18608,17 @@ | ||
| 18835 | 18608 | #endif |
| 18836 | 18609 | Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode)); |
| 18837 | 18610 | break; |
| 18838 | 18611 | |
| 18839 | 18612 | case INFO_VARS: |
| 18840 | - mode++; | |
| 18841 | - | |
| 18613 | + mode++; | |
| 18614 | + | |
| 18842 | 18615 | case INFO_LOCALS: |
| 18843 | - mode++; | |
| 18844 | - | |
| 18616 | + mode++; | |
| 18617 | + | |
| 18845 | 18618 | case INFO_GLOBALS: |
| 18846 | - | |
| 18619 | + | |
| 18847 | 18620 | if (argc != 2 && argc != 3) { |
| 18848 | 18621 | Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18849 | 18622 | return JIM_ERR; |
| 18850 | 18623 | } |
| 18851 | 18624 | #ifdef jim_ext_namespace |
| @@ -18951,13 +18724,12 @@ | ||
| 18951 | 18724 | case INFO_ARGS: |
| 18952 | 18725 | Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr); |
| 18953 | 18726 | break; |
| 18954 | 18727 | case INFO_STATICS: |
| 18955 | 18728 | if (cmdPtr->u.proc.staticVars) { |
| 18956 | - int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES; | |
| 18957 | 18729 | Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars, |
| 18958 | - NULL, JimVariablesMatch, mode)); | |
| 18730 | + NULL, JimVariablesMatch, JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES)); | |
| 18959 | 18731 | } |
| 18960 | 18732 | break; |
| 18961 | 18733 | } |
| 18962 | 18734 | break; |
| 18963 | 18735 | } |
| @@ -18985,15 +18757,15 @@ | ||
| 18985 | 18757 | } |
| 18986 | 18758 | } |
| 18987 | 18759 | break; |
| 18988 | 18760 | |
| 18989 | 18761 | case INFO_HOSTNAME: |
| 18990 | - | |
| 18762 | + | |
| 18991 | 18763 | return Jim_Eval(interp, "os.gethostname"); |
| 18992 | 18764 | |
| 18993 | 18765 | case INFO_NAMEOFEXECUTABLE: |
| 18994 | - | |
| 18766 | + | |
| 18995 | 18767 | return Jim_Eval(interp, "{info nameofexecutable}"); |
| 18996 | 18768 | |
| 18997 | 18769 | case INFO_RETURNCODES: |
| 18998 | 18770 | if (argc == 2) { |
| 18999 | 18771 | int i; |
| @@ -19070,11 +18842,11 @@ | ||
| 19070 | 18842 | |
| 19071 | 18843 | if (option == OPT_VAR) { |
| 19072 | 18844 | result = Jim_GetVariable(interp, objPtr, 0) != NULL; |
| 19073 | 18845 | } |
| 19074 | 18846 | else { |
| 19075 | - | |
| 18847 | + | |
| 19076 | 18848 | Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); |
| 19077 | 18849 | |
| 19078 | 18850 | if (cmd) { |
| 19079 | 18851 | switch (option) { |
| 19080 | 18852 | case OPT_COMMAND: |
| @@ -19113,11 +18885,11 @@ | ||
| 19113 | 18885 | if (len == 0) { |
| 19114 | 18886 | return JIM_OK; |
| 19115 | 18887 | } |
| 19116 | 18888 | strLen = Jim_Utf8Length(interp, argv[1]); |
| 19117 | 18889 | |
| 19118 | - | |
| 18890 | + | |
| 19119 | 18891 | if (argc == 2) { |
| 19120 | 18892 | splitChars = " \n\t\r"; |
| 19121 | 18893 | splitLen = 4; |
| 19122 | 18894 | } |
| 19123 | 18895 | else { |
| @@ -19126,11 +18898,11 @@ | ||
| 19126 | 18898 | } |
| 19127 | 18899 | |
| 19128 | 18900 | noMatchStart = str; |
| 19129 | 18901 | resObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 19130 | 18902 | |
| 19131 | - | |
| 18903 | + | |
| 19132 | 18904 | if (splitLen) { |
| 19133 | 18905 | Jim_Obj *objPtr; |
| 19134 | 18906 | while (strLen--) { |
| 19135 | 18907 | const char *sc = splitChars; |
| 19136 | 18908 | int scLen = splitLen; |
| @@ -19155,11 +18927,11 @@ | ||
| 19155 | 18927 | #define NUM_COMMON (128 - 9) |
| 19156 | 18928 | while (strLen--) { |
| 19157 | 18929 | int n = utf8_tounicode(str, &c); |
| 19158 | 18930 | #ifdef JIM_OPTIMIZATION |
| 19159 | 18931 | if (c >= 9 && c < 128) { |
| 19160 | - | |
| 18932 | + | |
| 19161 | 18933 | c -= 9; |
| 19162 | 18934 | if (!commonObj) { |
| 19163 | 18935 | commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON); |
| 19164 | 18936 | memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON); |
| 19165 | 18937 | } |
| @@ -19189,11 +18961,11 @@ | ||
| 19189 | 18961 | |
| 19190 | 18962 | if (argc != 2 && argc != 3) { |
| 19191 | 18963 | Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?"); |
| 19192 | 18964 | return JIM_ERR; |
| 19193 | 18965 | } |
| 19194 | - | |
| 18966 | + | |
| 19195 | 18967 | if (argc == 2) { |
| 19196 | 18968 | joinStr = " "; |
| 19197 | 18969 | joinStrLen = 1; |
| 19198 | 18970 | } |
| 19199 | 18971 | else { |
| @@ -19468,13 +19240,13 @@ | ||
| 19468 | 19240 | return -1; |
| 19469 | 19241 | else if (step < 0 && end > start) |
| 19470 | 19242 | return -1; |
| 19471 | 19243 | len = end - start; |
| 19472 | 19244 | if (len < 0) |
| 19473 | - len = -len; | |
| 19245 | + len = -len; | |
| 19474 | 19246 | if (step < 0) |
| 19475 | - step = -step; | |
| 19247 | + step = -step; | |
| 19476 | 19248 | len = 1 + ((len - 1) / step); |
| 19477 | 19249 | if (len > INT_MAX) |
| 19478 | 19250 | len = INT_MAX; |
| 19479 | 19251 | return (int)((len < 0) ? -1 : len); |
| 19480 | 19252 | } |
| @@ -19644,57 +19416,102 @@ | ||
| 19644 | 19416 | argv[1] = interp->result; |
| 19645 | 19417 | |
| 19646 | 19418 | Jim_EvalObjVector(interp, 2, argv); |
| 19647 | 19419 | } |
| 19648 | 19420 | |
| 19649 | -static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, | |
| 19650 | - const char *prefix, const char *const *tablePtr, const char *name) | |
| 19421 | +static char **JimSortStringTable(const char *const *tablePtr) | |
| 19651 | 19422 | { |
| 19652 | 19423 | int count; |
| 19653 | 19424 | char **tablePtrSorted; |
| 19654 | - int i; | |
| 19425 | + | |
| 19655 | 19426 | |
| 19656 | 19427 | for (count = 0; tablePtr[count]; count++) { |
| 19657 | 19428 | } |
| 19658 | 19429 | |
| 19430 | + | |
| 19431 | + tablePtrSorted = Jim_Alloc(sizeof(char *) * (count + 1)); | |
| 19432 | + memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); | |
| 19433 | + qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); | |
| 19434 | + tablePtrSorted[count] = NULL; | |
| 19435 | + | |
| 19436 | + return tablePtrSorted; | |
| 19437 | +} | |
| 19438 | + | |
| 19439 | +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, | |
| 19440 | + const char *prefix, const char *const *tablePtr, const char *name) | |
| 19441 | +{ | |
| 19442 | + char **tablePtrSorted; | |
| 19443 | + int i; | |
| 19444 | + | |
| 19659 | 19445 | if (name == NULL) { |
| 19660 | 19446 | name = "option"; |
| 19661 | 19447 | } |
| 19662 | 19448 | |
| 19663 | 19449 | Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); |
| 19664 | - tablePtrSorted = Jim_Alloc(sizeof(char *) * count); | |
| 19665 | - memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); | |
| 19666 | - qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); | |
| 19667 | - for (i = 0; i < count; i++) { | |
| 19668 | - if (i + 1 == count && count > 1) { | |
| 19450 | + tablePtrSorted = JimSortStringTable(tablePtr); | |
| 19451 | + for (i = 0; tablePtrSorted[i]; i++) { | |
| 19452 | + if (tablePtrSorted[i + 1] == NULL && i > 0) { | |
| 19669 | 19453 | Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); |
| 19670 | 19454 | } |
| 19671 | 19455 | Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); |
| 19672 | - if (i + 1 != count) { | |
| 19456 | + if (tablePtrSorted[i + 1]) { | |
| 19673 | 19457 | Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); |
| 19674 | 19458 | } |
| 19675 | 19459 | } |
| 19676 | 19460 | Jim_Free(tablePtrSorted); |
| 19677 | 19461 | } |
| 19678 | 19462 | |
| 19463 | + | |
| 19464 | +int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr) | |
| 19465 | +{ | |
| 19466 | + if (Jim_CompareStringImmediate(interp, objPtr, "-commands")) { | |
| 19467 | + int i; | |
| 19468 | + char **tablePtrSorted = JimSortStringTable(tablePtr); | |
| 19469 | + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); | |
| 19470 | + for (i = 0; tablePtrSorted[i]; i++) { | |
| 19471 | + Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1)); | |
| 19472 | + } | |
| 19473 | + Jim_Free(tablePtrSorted); | |
| 19474 | + return JIM_OK; | |
| 19475 | + } | |
| 19476 | + return JIM_ERR; | |
| 19477 | +} | |
| 19478 | + | |
| 19479 | +static const Jim_ObjType getEnumObjType = { | |
| 19480 | + "get-enum", | |
| 19481 | + NULL, | |
| 19482 | + NULL, | |
| 19483 | + NULL, | |
| 19484 | + JIM_TYPE_REFERENCES | |
| 19485 | +}; | |
| 19486 | + | |
| 19679 | 19487 | int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, |
| 19680 | 19488 | const char *const *tablePtr, int *indexPtr, const char *name, int flags) |
| 19681 | 19489 | { |
| 19682 | 19490 | const char *bad = "bad "; |
| 19683 | 19491 | const char *const *entryPtr = NULL; |
| 19684 | 19492 | int i; |
| 19685 | 19493 | int match = -1; |
| 19686 | 19494 | int arglen; |
| 19687 | - const char *arg = Jim_GetString(objPtr, &arglen); | |
| 19495 | + const char *arg; | |
| 19496 | + | |
| 19497 | + if (objPtr->typePtr == &getEnumObjType) { | |
| 19498 | + if (objPtr->internalRep.ptrIntValue.ptr == tablePtr && objPtr->internalRep.ptrIntValue.int1 == flags) { | |
| 19499 | + *indexPtr = objPtr->internalRep.ptrIntValue.int2; | |
| 19500 | + return JIM_OK; | |
| 19501 | + } | |
| 19502 | + } | |
| 19503 | + | |
| 19504 | + arg = Jim_GetString(objPtr, &arglen); | |
| 19688 | 19505 | |
| 19689 | 19506 | *indexPtr = -1; |
| 19690 | 19507 | |
| 19691 | 19508 | for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { |
| 19692 | 19509 | if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { |
| 19693 | - | |
| 19694 | - *indexPtr = i; | |
| 19695 | - return JIM_OK; | |
| 19510 | + | |
| 19511 | + match = i; | |
| 19512 | + goto found; | |
| 19696 | 19513 | } |
| 19697 | 19514 | if (flags & JIM_ENUM_ABBREV) { |
| 19698 | 19515 | if (strncmp(arg, *entryPtr, arglen) == 0) { |
| 19699 | 19516 | if (*arg == '-' && arglen == 1) { |
| 19700 | 19517 | break; |
| @@ -19706,12 +19523,20 @@ | ||
| 19706 | 19523 | match = i; |
| 19707 | 19524 | } |
| 19708 | 19525 | } |
| 19709 | 19526 | } |
| 19710 | 19527 | |
| 19711 | - | |
| 19528 | + | |
| 19712 | 19529 | if (match >= 0) { |
| 19530 | + found: | |
| 19531 | + | |
| 19532 | + Jim_FreeIntRep(interp, objPtr); | |
| 19533 | + objPtr->typePtr = &getEnumObjType; | |
| 19534 | + objPtr->internalRep.ptrIntValue.ptr = (void *)tablePtr; | |
| 19535 | + objPtr->internalRep.ptrIntValue.int1 = flags; | |
| 19536 | + objPtr->internalRep.ptrIntValue.int2 = match; | |
| 19537 | + | |
| 19713 | 19538 | *indexPtr = match; |
| 19714 | 19539 | return JIM_OK; |
| 19715 | 19540 | } |
| 19716 | 19541 | |
| 19717 | 19542 | ambiguous: |
| @@ -19743,15 +19568,17 @@ | ||
| 19743 | 19568 | return objPtr->typePtr == &listObjType; |
| 19744 | 19569 | } |
| 19745 | 19570 | |
| 19746 | 19571 | void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...) |
| 19747 | 19572 | { |
| 19748 | - | |
| 19573 | + | |
| 19749 | 19574 | int len = strlen(format); |
| 19750 | 19575 | int extra = 0; |
| 19751 | 19576 | int n = 0; |
| 19752 | 19577 | const char *params[5]; |
| 19578 | + int nobjparam = 0; | |
| 19579 | + Jim_Obj *objparam[5]; | |
| 19753 | 19580 | char *buf; |
| 19754 | 19581 | va_list args; |
| 19755 | 19582 | int i; |
| 19756 | 19583 | |
| 19757 | 19584 | va_start(args, format); |
| @@ -19766,10 +19593,12 @@ | ||
| 19766 | 19593 | } |
| 19767 | 19594 | else if (strncmp(format + i, "%#s", 3) == 0) { |
| 19768 | 19595 | Jim_Obj *objPtr = va_arg(args, Jim_Obj *); |
| 19769 | 19596 | |
| 19770 | 19597 | params[n] = Jim_GetString(objPtr, &l); |
| 19598 | + objparam[nobjparam++] = objPtr; | |
| 19599 | + Jim_IncrRefCount(objPtr); | |
| 19771 | 19600 | } |
| 19772 | 19601 | else { |
| 19773 | 19602 | if (format[i] == '%') { |
| 19774 | 19603 | i++; |
| 19775 | 19604 | } |
| @@ -19784,10 +19613,14 @@ | ||
| 19784 | 19613 | len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); |
| 19785 | 19614 | |
| 19786 | 19615 | va_end(args); |
| 19787 | 19616 | |
| 19788 | 19617 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); |
| 19618 | + | |
| 19619 | + for (i = 0; i < nobjparam; i++) { | |
| 19620 | + Jim_DecrRefCount(interp, objparam[i]); | |
| 19621 | + } | |
| 19789 | 19622 | } |
| 19790 | 19623 | |
| 19791 | 19624 | |
| 19792 | 19625 | #ifndef jim_ext_package |
| 19793 | 19626 | int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) |
| @@ -19808,11 +19641,11 @@ | ||
| 19808 | 19641 | #include <string.h> |
| 19809 | 19642 | |
| 19810 | 19643 | |
| 19811 | 19644 | static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19812 | 19645 | { |
| 19813 | - | |
| 19646 | + | |
| 19814 | 19647 | return JIM_OK; |
| 19815 | 19648 | } |
| 19816 | 19649 | |
| 19817 | 19650 | static const jim_subcmd_type dummy_subcmd = { |
| 19818 | 19651 | "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN |
| @@ -19831,22 +19664,18 @@ | ||
| 19831 | 19664 | } |
| 19832 | 19665 | |
| 19833 | 19666 | static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, |
| 19834 | 19667 | Jim_Obj *cmd, Jim_Obj *subcmd) |
| 19835 | 19668 | { |
| 19836 | - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); | |
| 19837 | - Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type, | |
| 19838 | - " command \"", Jim_String(subcmd), "\": should be ", NULL); | |
| 19669 | + Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd); | |
| 19839 | 19670 | add_commands(interp, command_table, ", "); |
| 19840 | 19671 | } |
| 19841 | 19672 | |
| 19842 | 19673 | static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, |
| 19843 | 19674 | Jim_Obj *const *argv) |
| 19844 | 19675 | { |
| 19845 | - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); | |
| 19846 | - Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]), | |
| 19847 | - " command ... \", where command is one of: ", NULL); | |
| 19676 | + Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]); | |
| 19848 | 19677 | add_commands(interp, command_table, ", "); |
| 19849 | 19678 | } |
| 19850 | 19679 | |
| 19851 | 19680 | static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) |
| 19852 | 19681 | { |
| @@ -19863,67 +19692,78 @@ | ||
| 19863 | 19692 | { |
| 19864 | 19693 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19865 | 19694 | add_cmd_usage(interp, command_table, subcmd); |
| 19866 | 19695 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19867 | 19696 | } |
| 19697 | + | |
| 19698 | +static const Jim_ObjType subcmdLookupObjType = { | |
| 19699 | + "subcmd-lookup", | |
| 19700 | + NULL, | |
| 19701 | + NULL, | |
| 19702 | + NULL, | |
| 19703 | + JIM_TYPE_REFERENCES | |
| 19704 | +}; | |
| 19868 | 19705 | |
| 19869 | 19706 | const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, |
| 19870 | 19707 | int argc, Jim_Obj *const *argv) |
| 19871 | 19708 | { |
| 19872 | 19709 | const jim_subcmd_type *ct; |
| 19873 | 19710 | const jim_subcmd_type *partial = 0; |
| 19874 | 19711 | int cmdlen; |
| 19875 | 19712 | Jim_Obj *cmd; |
| 19876 | 19713 | const char *cmdstr; |
| 19877 | - const char *cmdname; | |
| 19878 | 19714 | int help = 0; |
| 19879 | 19715 | |
| 19880 | - cmdname = Jim_String(argv[0]); | |
| 19881 | - | |
| 19882 | 19716 | if (argc < 2) { |
| 19883 | - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); | |
| 19884 | - Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname, | |
| 19885 | - " command ...\"\n", NULL); | |
| 19886 | - Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL); | |
| 19717 | + Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n" | |
| 19718 | + "Use \"%#s -help ?command?\" for help", argv[0], argv[0]); | |
| 19887 | 19719 | return 0; |
| 19888 | 19720 | } |
| 19889 | 19721 | |
| 19890 | 19722 | cmd = argv[1]; |
| 19891 | 19723 | |
| 19892 | - | |
| 19724 | + | |
| 19725 | + if (cmd->typePtr == &subcmdLookupObjType) { | |
| 19726 | + if (cmd->internalRep.ptrIntValue.ptr == command_table) { | |
| 19727 | + ct = command_table + cmd->internalRep.ptrIntValue.int1; | |
| 19728 | + goto found; | |
| 19729 | + } | |
| 19730 | + } | |
| 19731 | + | |
| 19732 | + | |
| 19893 | 19733 | if (Jim_CompareStringImmediate(interp, cmd, "-help")) { |
| 19894 | 19734 | if (argc == 2) { |
| 19895 | - | |
| 19735 | + | |
| 19896 | 19736 | show_cmd_usage(interp, command_table, argc, argv); |
| 19897 | 19737 | return &dummy_subcmd; |
| 19898 | 19738 | } |
| 19899 | 19739 | help = 1; |
| 19900 | 19740 | |
| 19901 | - | |
| 19741 | + | |
| 19902 | 19742 | cmd = argv[2]; |
| 19903 | 19743 | } |
| 19904 | 19744 | |
| 19905 | - | |
| 19745 | + | |
| 19906 | 19746 | if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { |
| 19907 | - | |
| 19747 | + | |
| 19908 | 19748 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 19909 | 19749 | add_commands(interp, command_table, " "); |
| 19910 | 19750 | return &dummy_subcmd; |
| 19911 | 19751 | } |
| 19912 | 19752 | |
| 19913 | 19753 | cmdstr = Jim_GetString(cmd, &cmdlen); |
| 19914 | 19754 | |
| 19915 | 19755 | for (ct = command_table; ct->cmd; ct++) { |
| 19916 | 19756 | if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) { |
| 19917 | - | |
| 19757 | + | |
| 19918 | 19758 | break; |
| 19919 | 19759 | } |
| 19920 | 19760 | if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) { |
| 19921 | 19761 | if (partial) { |
| 19922 | - | |
| 19762 | + | |
| 19923 | 19763 | if (help) { |
| 19924 | - | |
| 19764 | + | |
| 19925 | 19765 | show_cmd_usage(interp, command_table, argc, argv); |
| 19926 | 19766 | return &dummy_subcmd; |
| 19927 | 19767 | } |
| 19928 | 19768 | bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]); |
| 19929 | 19769 | return 0; |
| @@ -19931,44 +19771,51 @@ | ||
| 19931 | 19771 | partial = ct; |
| 19932 | 19772 | } |
| 19933 | 19773 | continue; |
| 19934 | 19774 | } |
| 19935 | 19775 | |
| 19936 | - | |
| 19776 | + | |
| 19937 | 19777 | if (partial && !ct->cmd) { |
| 19938 | 19778 | ct = partial; |
| 19939 | 19779 | } |
| 19940 | 19780 | |
| 19941 | 19781 | if (!ct->cmd) { |
| 19942 | - | |
| 19782 | + | |
| 19943 | 19783 | if (help) { |
| 19944 | - | |
| 19784 | + | |
| 19945 | 19785 | show_cmd_usage(interp, command_table, argc, argv); |
| 19946 | 19786 | return &dummy_subcmd; |
| 19947 | 19787 | } |
| 19948 | 19788 | bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]); |
| 19949 | 19789 | return 0; |
| 19950 | 19790 | } |
| 19951 | 19791 | |
| 19952 | 19792 | if (help) { |
| 19953 | 19793 | Jim_SetResultString(interp, "Usage: ", -1); |
| 19954 | - | |
| 19794 | + | |
| 19955 | 19795 | add_cmd_usage(interp, ct, argv[0]); |
| 19956 | 19796 | return &dummy_subcmd; |
| 19957 | 19797 | } |
| 19958 | 19798 | |
| 19959 | - | |
| 19799 | + | |
| 19800 | + Jim_FreeIntRep(interp, cmd); | |
| 19801 | + cmd->typePtr = &subcmdLookupObjType; | |
| 19802 | + cmd->internalRep.ptrIntValue.ptr = (void *)command_table; | |
| 19803 | + cmd->internalRep.ptrIntValue.int1 = ct - command_table; | |
| 19804 | + | |
| 19805 | +found: | |
| 19806 | + | |
| 19960 | 19807 | if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { |
| 19961 | 19808 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19962 | - | |
| 19809 | + | |
| 19963 | 19810 | add_cmd_usage(interp, ct, argv[0]); |
| 19964 | 19811 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19965 | 19812 | |
| 19966 | 19813 | return 0; |
| 19967 | 19814 | } |
| 19968 | 19815 | |
| 19969 | - | |
| 19816 | + | |
| 19970 | 19817 | return ct; |
| 19971 | 19818 | } |
| 19972 | 19819 | |
| 19973 | 19820 | int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv) |
| 19974 | 19821 | { |
| @@ -20019,11 +19866,11 @@ | ||
| 20019 | 19866 | *p++ = 0xe0 | ((uc & 0xf000) >> 12); |
| 20020 | 19867 | *p++ = 0x80 | ((uc & 0xfc0) >> 6); |
| 20021 | 19868 | *p = 0x80 | (uc & 0x3f); |
| 20022 | 19869 | return 3; |
| 20023 | 19870 | } |
| 20024 | - | |
| 19871 | + | |
| 20025 | 19872 | else { |
| 20026 | 19873 | *p++ = 0xf0 | ((uc & 0x1c0000) >> 18); |
| 20027 | 19874 | *p++ = 0x80 | ((uc & 0x3f000) >> 12); |
| 20028 | 19875 | *p++ = 0x80 | ((uc & 0xfc0) >> 6); |
| 20029 | 19876 | *p = 0x80 | (uc & 0x3f); |
| @@ -20146,11 +19993,12 @@ | ||
| 20146 | 19993 | continue; |
| 20147 | 19994 | } |
| 20148 | 19995 | *p++ = ch; |
| 20149 | 19996 | format += step; |
| 20150 | 19997 | step = utf8_tounicode(format, &ch); |
| 20151 | - } while (sawFlag); | |
| 19998 | + | |
| 19999 | + } while (sawFlag && (p - spec <= 5)); | |
| 20152 | 20000 | |
| 20153 | 20001 | |
| 20154 | 20002 | width = 0; |
| 20155 | 20003 | if (isdigit(ch)) { |
| 20156 | 20004 | width = strtoul(format, &end, 10); |
| @@ -20210,11 +20058,11 @@ | ||
| 20210 | 20058 | if (ch == 'h') { |
| 20211 | 20059 | useShort = 1; |
| 20212 | 20060 | format += step; |
| 20213 | 20061 | step = utf8_tounicode(format, &ch); |
| 20214 | 20062 | } else if (ch == 'l') { |
| 20215 | - | |
| 20063 | + | |
| 20216 | 20064 | format += step; |
| 20217 | 20065 | step = utf8_tounicode(format, &ch); |
| 20218 | 20066 | if (ch == 'l') { |
| 20219 | 20067 | format += step; |
| 20220 | 20068 | step = utf8_tounicode(format, &ch); |
| @@ -20237,11 +20085,11 @@ | ||
| 20237 | 20085 | goto errorMsg; |
| 20238 | 20086 | case 's': { |
| 20239 | 20087 | formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); |
| 20240 | 20088 | formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); |
| 20241 | 20089 | if (gotPrecision && (precision < formatted_chars)) { |
| 20242 | - | |
| 20090 | + | |
| 20243 | 20091 | formatted_chars = precision; |
| 20244 | 20092 | formatted_bytes = utf8_index(formatted_buf, precision); |
| 20245 | 20093 | } |
| 20246 | 20094 | break; |
| 20247 | 20095 | } |
| @@ -20249,11 +20097,11 @@ | ||
| 20249 | 20097 | jim_wide code; |
| 20250 | 20098 | |
| 20251 | 20099 | if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { |
| 20252 | 20100 | goto error; |
| 20253 | 20101 | } |
| 20254 | - | |
| 20102 | + | |
| 20255 | 20103 | formatted_bytes = utf8_getchars(spec, code); |
| 20256 | 20104 | formatted_buf = spec; |
| 20257 | 20105 | formatted_chars = 1; |
| 20258 | 20106 | break; |
| 20259 | 20107 | } |
| @@ -20267,11 +20115,11 @@ | ||
| 20267 | 20115 | goto error; |
| 20268 | 20116 | } |
| 20269 | 20117 | length = sizeof(w) * 8; |
| 20270 | 20118 | |
| 20271 | 20119 | |
| 20272 | - | |
| 20120 | + | |
| 20273 | 20121 | if (num_buffer_size < length + 1) { |
| 20274 | 20122 | num_buffer_size = length + 1; |
| 20275 | 20123 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20276 | 20124 | } |
| 20277 | 20125 | |
| @@ -20295,29 +20143,29 @@ | ||
| 20295 | 20143 | case 'E': |
| 20296 | 20144 | case 'f': |
| 20297 | 20145 | case 'g': |
| 20298 | 20146 | case 'G': |
| 20299 | 20147 | doubleType = 1; |
| 20300 | - | |
| 20148 | + | |
| 20301 | 20149 | case 'd': |
| 20302 | 20150 | case 'u': |
| 20303 | 20151 | case 'o': |
| 20304 | 20152 | case 'x': |
| 20305 | 20153 | case 'X': { |
| 20306 | 20154 | jim_wide w; |
| 20307 | 20155 | double d; |
| 20308 | 20156 | int length; |
| 20309 | 20157 | |
| 20310 | - | |
| 20158 | + | |
| 20311 | 20159 | if (width) { |
| 20312 | 20160 | p += sprintf(p, "%ld", width); |
| 20313 | 20161 | } |
| 20314 | 20162 | if (gotPrecision) { |
| 20315 | 20163 | p += sprintf(p, ".%ld", precision); |
| 20316 | 20164 | } |
| 20317 | 20165 | |
| 20318 | - | |
| 20166 | + | |
| 20319 | 20167 | if (doubleType) { |
| 20320 | 20168 | if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { |
| 20321 | 20169 | goto error; |
| 20322 | 20170 | } |
| 20323 | 20171 | length = MAX_FLOAT_WIDTH; |
| @@ -20344,19 +20192,26 @@ | ||
| 20344 | 20192 | } |
| 20345 | 20193 | |
| 20346 | 20194 | *p++ = (char) ch; |
| 20347 | 20195 | *p = '\0'; |
| 20348 | 20196 | |
| 20349 | - | |
| 20197 | + | |
| 20198 | + if (width > 10000 || length > 10000 || precision > 10000) { | |
| 20199 | + Jim_SetResultString(interp, "format too long", -1); | |
| 20200 | + goto error; | |
| 20201 | + } | |
| 20202 | + | |
| 20203 | + | |
| 20204 | + | |
| 20350 | 20205 | if (width > length) { |
| 20351 | 20206 | length = width; |
| 20352 | 20207 | } |
| 20353 | 20208 | if (gotPrecision) { |
| 20354 | 20209 | length += precision; |
| 20355 | 20210 | } |
| 20356 | 20211 | |
| 20357 | - | |
| 20212 | + | |
| 20358 | 20213 | if (num_buffer_size < length + 1) { |
| 20359 | 20214 | num_buffer_size = length + 1; |
| 20360 | 20215 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20361 | 20216 | } |
| 20362 | 20217 | |
| @@ -20370,11 +20225,11 @@ | ||
| 20370 | 20225 | formatted_buf = num_buffer; |
| 20371 | 20226 | break; |
| 20372 | 20227 | } |
| 20373 | 20228 | |
| 20374 | 20229 | default: { |
| 20375 | - | |
| 20230 | + | |
| 20376 | 20231 | spec[0] = ch; |
| 20377 | 20232 | spec[1] = '\0'; |
| 20378 | 20233 | Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); |
| 20379 | 20234 | goto error; |
| 20380 | 20235 | } |
| @@ -20422,37 +20277,37 @@ | ||
| 20422 | 20277 | |
| 20423 | 20278 | #define REG_MAX_PAREN 100 |
| 20424 | 20279 | |
| 20425 | 20280 | |
| 20426 | 20281 | |
| 20427 | -#define END 0 | |
| 20428 | -#define BOL 1 | |
| 20429 | -#define EOL 2 | |
| 20430 | -#define ANY 3 | |
| 20431 | -#define ANYOF 4 | |
| 20432 | -#define ANYBUT 5 | |
| 20433 | -#define BRANCH 6 | |
| 20434 | -#define BACK 7 | |
| 20435 | -#define EXACTLY 8 | |
| 20436 | -#define NOTHING 9 | |
| 20437 | -#define REP 10 | |
| 20438 | -#define REPMIN 11 | |
| 20439 | -#define REPX 12 | |
| 20440 | -#define REPXMIN 13 | |
| 20441 | -#define BOLX 14 | |
| 20442 | -#define EOLX 15 | |
| 20443 | -#define WORDA 16 | |
| 20444 | -#define WORDZ 17 | |
| 20445 | - | |
| 20446 | -#define OPENNC 1000 | |
| 20447 | -#define OPEN 1001 | |
| 20448 | - | |
| 20449 | - | |
| 20450 | - | |
| 20451 | - | |
| 20452 | -#define CLOSENC 2000 | |
| 20453 | -#define CLOSE 2001 | |
| 20282 | +#define END 0 | |
| 20283 | +#define BOL 1 | |
| 20284 | +#define EOL 2 | |
| 20285 | +#define ANY 3 | |
| 20286 | +#define ANYOF 4 | |
| 20287 | +#define ANYBUT 5 | |
| 20288 | +#define BRANCH 6 | |
| 20289 | +#define BACK 7 | |
| 20290 | +#define EXACTLY 8 | |
| 20291 | +#define NOTHING 9 | |
| 20292 | +#define REP 10 | |
| 20293 | +#define REPMIN 11 | |
| 20294 | +#define REPX 12 | |
| 20295 | +#define REPXMIN 13 | |
| 20296 | +#define BOLX 14 | |
| 20297 | +#define EOLX 15 | |
| 20298 | +#define WORDA 16 | |
| 20299 | +#define WORDZ 17 | |
| 20300 | + | |
| 20301 | +#define OPENNC 1000 | |
| 20302 | +#define OPEN 1001 | |
| 20303 | + | |
| 20304 | + | |
| 20305 | + | |
| 20306 | + | |
| 20307 | +#define CLOSENC 2000 | |
| 20308 | +#define CLOSE 2001 | |
| 20454 | 20309 | #define CLOSE_END (CLOSE+REG_MAX_PAREN) |
| 20455 | 20310 | |
| 20456 | 20311 | #define REG_MAGIC 0xFADED00D |
| 20457 | 20312 | |
| 20458 | 20313 | |
| @@ -20465,18 +20320,18 @@ | ||
| 20465 | 20320 | |
| 20466 | 20321 | #define FAIL(R,M) { (R)->err = (M); return (M); } |
| 20467 | 20322 | #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') |
| 20468 | 20323 | #define META "^$.[()|?{+*" |
| 20469 | 20324 | |
| 20470 | -#define HASWIDTH 1 | |
| 20471 | -#define SIMPLE 2 | |
| 20472 | -#define SPSTART 4 | |
| 20473 | -#define WORST 0 | |
| 20325 | +#define HASWIDTH 1 | |
| 20326 | +#define SIMPLE 2 | |
| 20327 | +#define SPSTART 4 | |
| 20328 | +#define WORST 0 | |
| 20474 | 20329 | |
| 20475 | 20330 | #define MAX_REP_COUNT 1000000 |
| 20476 | 20331 | |
| 20477 | -static int reg(regex_t *preg, int paren , int *flagp ); | |
| 20332 | +static int reg(regex_t *preg, int paren, int *flagp ); | |
| 20478 | 20333 | static int regpiece(regex_t *preg, int *flagp ); |
| 20479 | 20334 | static int regbranch(regex_t *preg, int *flagp ); |
| 20480 | 20335 | static int regatom(regex_t *preg, int *flagp ); |
| 20481 | 20336 | static int regnode(regex_t *preg, int op ); |
| 20482 | 20337 | static int regnext(regex_t *preg, int p ); |
| @@ -20520,15 +20375,15 @@ | ||
| 20520 | 20375 | memset(preg, 0, sizeof(*preg)); |
| 20521 | 20376 | |
| 20522 | 20377 | if (exp == NULL) |
| 20523 | 20378 | FAIL(preg, REG_ERR_NULL_ARGUMENT); |
| 20524 | 20379 | |
| 20525 | - | |
| 20380 | + | |
| 20526 | 20381 | preg->cflags = cflags; |
| 20527 | 20382 | preg->regparse = exp; |
| 20528 | 20383 | |
| 20529 | - | |
| 20384 | + | |
| 20530 | 20385 | preg->proglen = (strlen(exp) + 1) * 5; |
| 20531 | 20386 | preg->program = malloc(preg->proglen * sizeof(int)); |
| 20532 | 20387 | if (preg->program == NULL) |
| 20533 | 20388 | FAIL(preg, REG_ERR_NOMEM); |
| 20534 | 20389 | |
| @@ -20535,24 +20390,24 @@ | ||
| 20535 | 20390 | regc(preg, REG_MAGIC); |
| 20536 | 20391 | if (reg(preg, 0, &flags) == 0) { |
| 20537 | 20392 | return preg->err; |
| 20538 | 20393 | } |
| 20539 | 20394 | |
| 20540 | - | |
| 20541 | - if (preg->re_nsub >= REG_MAX_PAREN) | |
| 20395 | + | |
| 20396 | + if (preg->re_nsub >= REG_MAX_PAREN) | |
| 20542 | 20397 | FAIL(preg,REG_ERR_TOO_BIG); |
| 20543 | 20398 | |
| 20544 | - | |
| 20545 | - preg->regstart = 0; | |
| 20399 | + | |
| 20400 | + preg->regstart = 0; | |
| 20546 | 20401 | preg->reganch = 0; |
| 20547 | 20402 | preg->regmust = 0; |
| 20548 | 20403 | preg->regmlen = 0; |
| 20549 | - scan = 1; | |
| 20550 | - if (OP(preg, regnext(preg, scan)) == END) { | |
| 20404 | + scan = 1; | |
| 20405 | + if (OP(preg, regnext(preg, scan)) == END) { | |
| 20551 | 20406 | scan = OPERAND(scan); |
| 20552 | 20407 | |
| 20553 | - | |
| 20408 | + | |
| 20554 | 20409 | if (OP(preg, scan) == EXACTLY) { |
| 20555 | 20410 | preg->regstart = preg->program[OPERAND(scan)]; |
| 20556 | 20411 | } |
| 20557 | 20412 | else if (OP(preg, scan) == BOL) |
| 20558 | 20413 | preg->reganch++; |
| @@ -20579,24 +20434,24 @@ | ||
| 20579 | 20434 | #endif |
| 20580 | 20435 | |
| 20581 | 20436 | return 0; |
| 20582 | 20437 | } |
| 20583 | 20438 | |
| 20584 | -static int reg(regex_t *preg, int paren , int *flagp ) | |
| 20439 | +static int reg(regex_t *preg, int paren, int *flagp ) | |
| 20585 | 20440 | { |
| 20586 | 20441 | int ret; |
| 20587 | 20442 | int br; |
| 20588 | 20443 | int ender; |
| 20589 | 20444 | int parno = 0; |
| 20590 | 20445 | int flags; |
| 20591 | 20446 | |
| 20592 | - *flagp = HASWIDTH; | |
| 20447 | + *flagp = HASWIDTH; | |
| 20593 | 20448 | |
| 20594 | - | |
| 20449 | + | |
| 20595 | 20450 | if (paren) { |
| 20596 | 20451 | if (preg->regparse[0] == '?' && preg->regparse[1] == ':') { |
| 20597 | - | |
| 20452 | + | |
| 20598 | 20453 | preg->regparse += 2; |
| 20599 | 20454 | parno = -1; |
| 20600 | 20455 | } |
| 20601 | 20456 | else { |
| 20602 | 20457 | parno = ++preg->re_nsub; |
| @@ -20603,16 +20458,16 @@ | ||
| 20603 | 20458 | } |
| 20604 | 20459 | ret = regnode(preg, OPEN+parno); |
| 20605 | 20460 | } else |
| 20606 | 20461 | ret = 0; |
| 20607 | 20462 | |
| 20608 | - | |
| 20463 | + | |
| 20609 | 20464 | br = regbranch(preg, &flags); |
| 20610 | 20465 | if (br == 0) |
| 20611 | 20466 | return 0; |
| 20612 | 20467 | if (ret != 0) |
| 20613 | - regtail(preg, ret, br); | |
| 20468 | + regtail(preg, ret, br); | |
| 20614 | 20469 | else |
| 20615 | 20470 | ret = br; |
| 20616 | 20471 | if (!(flags&HASWIDTH)) |
| 20617 | 20472 | *flagp &= ~HASWIDTH; |
| 20618 | 20473 | *flagp |= flags&SPSTART; |
| @@ -20619,25 +20474,25 @@ | ||
| 20619 | 20474 | while (*preg->regparse == '|') { |
| 20620 | 20475 | preg->regparse++; |
| 20621 | 20476 | br = regbranch(preg, &flags); |
| 20622 | 20477 | if (br == 0) |
| 20623 | 20478 | return 0; |
| 20624 | - regtail(preg, ret, br); | |
| 20479 | + regtail(preg, ret, br); | |
| 20625 | 20480 | if (!(flags&HASWIDTH)) |
| 20626 | 20481 | *flagp &= ~HASWIDTH; |
| 20627 | 20482 | *flagp |= flags&SPSTART; |
| 20628 | 20483 | } |
| 20629 | 20484 | |
| 20630 | - | |
| 20485 | + | |
| 20631 | 20486 | ender = regnode(preg, (paren) ? CLOSE+parno : END); |
| 20632 | 20487 | regtail(preg, ret, ender); |
| 20633 | 20488 | |
| 20634 | - | |
| 20489 | + | |
| 20635 | 20490 | for (br = ret; br != 0; br = regnext(preg, br)) |
| 20636 | 20491 | regoptail(preg, br, ender); |
| 20637 | 20492 | |
| 20638 | - | |
| 20493 | + | |
| 20639 | 20494 | if (paren && *preg->regparse++ != ')') { |
| 20640 | 20495 | preg->err = REG_ERR_UNMATCHED_PAREN; |
| 20641 | 20496 | return 0; |
| 20642 | 20497 | } else if (!paren && *preg->regparse != '\0') { |
| 20643 | 20498 | if (*preg->regparse == ')') { |
| @@ -20657,11 +20512,11 @@ | ||
| 20657 | 20512 | int ret; |
| 20658 | 20513 | int chain; |
| 20659 | 20514 | int latest; |
| 20660 | 20515 | int flags; |
| 20661 | 20516 | |
| 20662 | - *flagp = WORST; | |
| 20517 | + *flagp = WORST; | |
| 20663 | 20518 | |
| 20664 | 20519 | ret = regnode(preg, BRANCH); |
| 20665 | 20520 | chain = 0; |
| 20666 | 20521 | while (*preg->regparse != '\0' && *preg->regparse != ')' && |
| 20667 | 20522 | *preg->regparse != '|') { |
| @@ -20675,11 +20530,11 @@ | ||
| 20675 | 20530 | else { |
| 20676 | 20531 | regtail(preg, chain, latest); |
| 20677 | 20532 | } |
| 20678 | 20533 | chain = latest; |
| 20679 | 20534 | } |
| 20680 | - if (chain == 0) | |
| 20535 | + if (chain == 0) | |
| 20681 | 20536 | (void) regnode(preg, NOTHING); |
| 20682 | 20537 | |
| 20683 | 20538 | return(ret); |
| 20684 | 20539 | } |
| 20685 | 20540 | |
| @@ -20705,11 +20560,11 @@ | ||
| 20705 | 20560 | if (!(flags&HASWIDTH) && op != '?') { |
| 20706 | 20561 | preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY; |
| 20707 | 20562 | return 0; |
| 20708 | 20563 | } |
| 20709 | 20564 | |
| 20710 | - | |
| 20565 | + | |
| 20711 | 20566 | if (op == '{') { |
| 20712 | 20567 | char *end; |
| 20713 | 20568 | |
| 20714 | 20569 | min = strtoul(preg->regparse + 1, &end, 10); |
| 20715 | 20570 | if (end == preg->regparse + 1) { |
| @@ -20716,10 +20571,14 @@ | ||
| 20716 | 20571 | preg->err = REG_ERR_BAD_COUNT; |
| 20717 | 20572 | return 0; |
| 20718 | 20573 | } |
| 20719 | 20574 | if (*end == '}') { |
| 20720 | 20575 | max = min; |
| 20576 | + } | |
| 20577 | + else if (*end == '\0') { | |
| 20578 | + preg->err = REG_ERR_UNMATCHED_BRACES; | |
| 20579 | + return 0; | |
| 20721 | 20580 | } |
| 20722 | 20581 | else { |
| 20723 | 20582 | preg->regparse = end; |
| 20724 | 20583 | max = strtoul(preg->regparse + 1, &end, 10); |
| 20725 | 20584 | if (*end != '}') { |
| @@ -20777,11 +20636,11 @@ | ||
| 20777 | 20636 | static void reg_addrange(regex_t *preg, int lower, int upper) |
| 20778 | 20637 | { |
| 20779 | 20638 | if (lower > upper) { |
| 20780 | 20639 | reg_addrange(preg, upper, lower); |
| 20781 | 20640 | } |
| 20782 | - | |
| 20641 | + | |
| 20783 | 20642 | regc(preg, upper - lower + 1); |
| 20784 | 20643 | regc(preg, lower); |
| 20785 | 20644 | } |
| 20786 | 20645 | |
| 20787 | 20646 | static void reg_addrange_str(regex_t *preg, const char *str) |
| @@ -20845,17 +20704,17 @@ | ||
| 20845 | 20704 | case 'r': *ch = '\r'; break; |
| 20846 | 20705 | case 't': *ch = '\t'; break; |
| 20847 | 20706 | case 'v': *ch = '\v'; break; |
| 20848 | 20707 | case 'u': |
| 20849 | 20708 | if (*s == '{') { |
| 20850 | - | |
| 20709 | + | |
| 20851 | 20710 | n = parse_hex(s + 1, 6, ch); |
| 20852 | 20711 | if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) { |
| 20853 | 20712 | s += n + 2; |
| 20854 | 20713 | } |
| 20855 | 20714 | else { |
| 20856 | - | |
| 20715 | + | |
| 20857 | 20716 | *ch = 'u'; |
| 20858 | 20717 | } |
| 20859 | 20718 | } |
| 20860 | 20719 | else if ((n = parse_hex(s, 4, ch)) > 0) { |
| 20861 | 20720 | s += n; |
| @@ -20886,15 +20745,15 @@ | ||
| 20886 | 20745 | int nocase = (preg->cflags & REG_ICASE); |
| 20887 | 20746 | |
| 20888 | 20747 | int ch; |
| 20889 | 20748 | int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase); |
| 20890 | 20749 | |
| 20891 | - *flagp = WORST; | |
| 20750 | + *flagp = WORST; | |
| 20892 | 20751 | |
| 20893 | 20752 | preg->regparse += n; |
| 20894 | 20753 | switch (ch) { |
| 20895 | - | |
| 20754 | + | |
| 20896 | 20755 | case '^': |
| 20897 | 20756 | ret = regnode(preg, BOL); |
| 20898 | 20757 | break; |
| 20899 | 20758 | case '$': |
| 20900 | 20759 | ret = regnode(preg, EOL); |
| @@ -20904,37 +20763,60 @@ | ||
| 20904 | 20763 | *flagp |= HASWIDTH|SIMPLE; |
| 20905 | 20764 | break; |
| 20906 | 20765 | case '[': { |
| 20907 | 20766 | const char *pattern = preg->regparse; |
| 20908 | 20767 | |
| 20909 | - if (*pattern == '^') { | |
| 20768 | + if (*pattern == '^') { | |
| 20910 | 20769 | ret = regnode(preg, ANYBUT); |
| 20911 | 20770 | pattern++; |
| 20912 | 20771 | } else |
| 20913 | 20772 | ret = regnode(preg, ANYOF); |
| 20914 | 20773 | |
| 20915 | - | |
| 20774 | + | |
| 20916 | 20775 | if (*pattern == ']' || *pattern == '-') { |
| 20917 | 20776 | reg_addrange(preg, *pattern, *pattern); |
| 20918 | 20777 | pattern++; |
| 20919 | 20778 | } |
| 20920 | 20779 | |
| 20921 | 20780 | while (*pattern && *pattern != ']') { |
| 20922 | - | |
| 20781 | + | |
| 20923 | 20782 | int start; |
| 20924 | 20783 | int end; |
| 20925 | 20784 | |
| 20785 | + enum { | |
| 20786 | + CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER, | |
| 20787 | + CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT, | |
| 20788 | + CC_NUM | |
| 20789 | + }; | |
| 20790 | + int cc; | |
| 20791 | + | |
| 20926 | 20792 | pattern += reg_utf8_tounicode_case(pattern, &start, nocase); |
| 20927 | 20793 | if (start == '\\') { |
| 20794 | + | |
| 20795 | + switch (*pattern) { | |
| 20796 | + case 's': | |
| 20797 | + pattern++; | |
| 20798 | + cc = CC_SPACE; | |
| 20799 | + goto cc_switch; | |
| 20800 | + case 'd': | |
| 20801 | + pattern++; | |
| 20802 | + cc = CC_DIGIT; | |
| 20803 | + goto cc_switch; | |
| 20804 | + case 'w': | |
| 20805 | + pattern++; | |
| 20806 | + reg_addrange(preg, '_', '_'); | |
| 20807 | + cc = CC_ALNUM; | |
| 20808 | + goto cc_switch; | |
| 20809 | + } | |
| 20928 | 20810 | pattern += reg_decode_escape(pattern, &start); |
| 20929 | 20811 | if (start == 0) { |
| 20930 | 20812 | preg->err = REG_ERR_NULL_CHAR; |
| 20931 | 20813 | return 0; |
| 20932 | 20814 | } |
| 20933 | 20815 | } |
| 20934 | 20816 | if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') { |
| 20935 | - | |
| 20817 | + | |
| 20936 | 20818 | pattern += utf8_tounicode(pattern, &end); |
| 20937 | 20819 | pattern += reg_utf8_tounicode_case(pattern, &end, nocase); |
| 20938 | 20820 | if (end == '\\') { |
| 20939 | 20821 | pattern += reg_decode_escape(pattern, &end); |
| 20940 | 20822 | if (end == 0) { |
| @@ -20949,30 +20831,25 @@ | ||
| 20949 | 20831 | if (start == '[' && pattern[0] == ':') { |
| 20950 | 20832 | static const char *character_class[] = { |
| 20951 | 20833 | ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:", |
| 20952 | 20834 | ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:", |
| 20953 | 20835 | }; |
| 20954 | - enum { | |
| 20955 | - CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER, | |
| 20956 | - CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT, | |
| 20957 | - CC_NUM | |
| 20958 | - }; | |
| 20959 | - int i; | |
| 20960 | - | |
| 20961 | - for (i = 0; i < CC_NUM; i++) { | |
| 20962 | - int n = strlen(character_class[i]); | |
| 20963 | - if (strncmp(pattern, character_class[i], n) == 0) { | |
| 20964 | - | |
| 20836 | + | |
| 20837 | + for (cc = 0; cc < CC_NUM; cc++) { | |
| 20838 | + n = strlen(character_class[cc]); | |
| 20839 | + if (strncmp(pattern, character_class[cc], n) == 0) { | |
| 20840 | + | |
| 20965 | 20841 | pattern += n + 1; |
| 20966 | 20842 | break; |
| 20967 | 20843 | } |
| 20968 | 20844 | } |
| 20969 | - if (i != CC_NUM) { | |
| 20970 | - switch (i) { | |
| 20845 | + if (cc != CC_NUM) { | |
| 20846 | +cc_switch: | |
| 20847 | + switch (cc) { | |
| 20971 | 20848 | case CC_ALNUM: |
| 20972 | 20849 | reg_addrange(preg, '0', '9'); |
| 20973 | - | |
| 20850 | + | |
| 20974 | 20851 | case CC_ALPHA: |
| 20975 | 20852 | if ((preg->cflags & REG_ICASE) == 0) { |
| 20976 | 20853 | reg_addrange(preg, 'a', 'z'); |
| 20977 | 20854 | } |
| 20978 | 20855 | reg_addrange(preg, 'A', 'Z'); |
| @@ -20990,11 +20867,11 @@ | ||
| 20990 | 20867 | reg_addrange(preg, 'a', 'z'); |
| 20991 | 20868 | break; |
| 20992 | 20869 | case CC_XDIGIT: |
| 20993 | 20870 | reg_addrange(preg, 'a', 'f'); |
| 20994 | 20871 | reg_addrange(preg, 'A', 'F'); |
| 20995 | - | |
| 20872 | + | |
| 20996 | 20873 | case CC_DIGIT: |
| 20997 | 20874 | reg_addrange(preg, '0', '9'); |
| 20998 | 20875 | break; |
| 20999 | 20876 | case CC_CNTRL: |
| 21000 | 20877 | reg_addrange(preg, 0, 31); |
| @@ -21014,11 +20891,11 @@ | ||
| 21014 | 20891 | break; |
| 21015 | 20892 | } |
| 21016 | 20893 | continue; |
| 21017 | 20894 | } |
| 21018 | 20895 | } |
| 21019 | - | |
| 20896 | + | |
| 21020 | 20897 | reg_addrange(preg, start, start); |
| 21021 | 20898 | } |
| 21022 | 20899 | regc(preg, '\0'); |
| 21023 | 20900 | |
| 21024 | 20901 | if (*pattern) { |
| @@ -21037,11 +20914,11 @@ | ||
| 21037 | 20914 | break; |
| 21038 | 20915 | case '\0': |
| 21039 | 20916 | case '|': |
| 21040 | 20917 | case ')': |
| 21041 | 20918 | preg->err = REG_ERR_INTERNAL; |
| 21042 | - return 0; | |
| 20919 | + return 0; | |
| 21043 | 20920 | case '?': |
| 21044 | 20921 | case '+': |
| 21045 | 20922 | case '*': |
| 21046 | 20923 | case '{': |
| 21047 | 20924 | preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING; |
| @@ -21090,34 +20967,34 @@ | ||
| 21090 | 20967 | ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT); |
| 21091 | 20968 | reg_addrange_str(preg," \t\r\n\f\v"); |
| 21092 | 20969 | regc(preg, '\0'); |
| 21093 | 20970 | *flagp |= HASWIDTH|SIMPLE; |
| 21094 | 20971 | break; |
| 21095 | - | |
| 20972 | + | |
| 21096 | 20973 | default: |
| 21097 | - | |
| 21098 | - | |
| 20974 | + | |
| 20975 | + | |
| 21099 | 20976 | preg->regparse--; |
| 21100 | 20977 | goto de_fault; |
| 21101 | 20978 | } |
| 21102 | 20979 | break; |
| 21103 | 20980 | de_fault: |
| 21104 | 20981 | default: { |
| 21105 | 20982 | int added = 0; |
| 21106 | 20983 | |
| 21107 | - | |
| 20984 | + | |
| 21108 | 20985 | preg->regparse -= n; |
| 21109 | 20986 | |
| 21110 | 20987 | ret = regnode(preg, EXACTLY); |
| 21111 | 20988 | |
| 21112 | 20989 | |
| 21113 | - | |
| 20990 | + | |
| 21114 | 20991 | while (*preg->regparse && strchr(META, *preg->regparse) == NULL) { |
| 21115 | 20992 | n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE)); |
| 21116 | 20993 | if (ch == '\\' && preg->regparse[n]) { |
| 21117 | 20994 | if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) { |
| 21118 | - | |
| 20995 | + | |
| 21119 | 20996 | break; |
| 21120 | 20997 | } |
| 21121 | 20998 | n += reg_decode_escape(preg->regparse + n, &ch); |
| 21122 | 20999 | if (ch == 0) { |
| 21123 | 21000 | preg->err = REG_ERR_NULL_CHAR; |
| @@ -21125,23 +21002,23 @@ | ||
| 21125 | 21002 | } |
| 21126 | 21003 | } |
| 21127 | 21004 | |
| 21128 | 21005 | |
| 21129 | 21006 | if (ISMULT(preg->regparse[n])) { |
| 21130 | - | |
| 21007 | + | |
| 21131 | 21008 | if (added) { |
| 21132 | - | |
| 21009 | + | |
| 21133 | 21010 | break; |
| 21134 | 21011 | } |
| 21135 | - | |
| 21012 | + | |
| 21136 | 21013 | regc(preg, ch); |
| 21137 | 21014 | added++; |
| 21138 | 21015 | preg->regparse += n; |
| 21139 | 21016 | break; |
| 21140 | 21017 | } |
| 21141 | 21018 | |
| 21142 | - | |
| 21019 | + | |
| 21143 | 21020 | regc(preg, ch); |
| 21144 | 21021 | added++; |
| 21145 | 21022 | preg->regparse += n; |
| 21146 | 21023 | } |
| 21147 | 21024 | regc(preg, '\0'); |
| @@ -21168,15 +21045,15 @@ | ||
| 21168 | 21045 | |
| 21169 | 21046 | static int regnode(regex_t *preg, int op) |
| 21170 | 21047 | { |
| 21171 | 21048 | reg_grow(preg, 2); |
| 21172 | 21049 | |
| 21173 | - | |
| 21050 | + | |
| 21174 | 21051 | preg->program[preg->p++] = op; |
| 21175 | 21052 | preg->program[preg->p++] = 0; |
| 21176 | 21053 | |
| 21177 | - | |
| 21054 | + | |
| 21178 | 21055 | return preg->p - 2; |
| 21179 | 21056 | } |
| 21180 | 21057 | |
| 21181 | 21058 | static void regc(regex_t *preg, int b ) |
| 21182 | 21059 | { |
| @@ -21186,13 +21063,13 @@ | ||
| 21186 | 21063 | |
| 21187 | 21064 | static int reginsert(regex_t *preg, int op, int size, int opnd ) |
| 21188 | 21065 | { |
| 21189 | 21066 | reg_grow(preg, size); |
| 21190 | 21067 | |
| 21191 | - | |
| 21068 | + | |
| 21192 | 21069 | memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd)); |
| 21193 | - | |
| 21070 | + | |
| 21194 | 21071 | memset(preg->program + opnd, 0, sizeof(int) * size); |
| 21195 | 21072 | |
| 21196 | 21073 | preg->program[opnd] = op; |
| 21197 | 21074 | |
| 21198 | 21075 | preg->p += size; |
| @@ -21204,11 +21081,11 @@ | ||
| 21204 | 21081 | { |
| 21205 | 21082 | int scan; |
| 21206 | 21083 | int temp; |
| 21207 | 21084 | int offset; |
| 21208 | 21085 | |
| 21209 | - | |
| 21086 | + | |
| 21210 | 21087 | scan = p; |
| 21211 | 21088 | for (;;) { |
| 21212 | 21089 | temp = regnext(preg, scan); |
| 21213 | 21090 | if (temp == 0) |
| 21214 | 21091 | break; |
| @@ -21224,11 +21101,11 @@ | ||
| 21224 | 21101 | } |
| 21225 | 21102 | |
| 21226 | 21103 | |
| 21227 | 21104 | static void regoptail(regex_t *preg, int p, int val ) |
| 21228 | 21105 | { |
| 21229 | - | |
| 21106 | + | |
| 21230 | 21107 | if (p != 0 && OP(preg, p) == BRANCH) { |
| 21231 | 21108 | regtail(preg, OPERAND(p), val); |
| 21232 | 21109 | } |
| 21233 | 21110 | } |
| 21234 | 21111 | |
| @@ -21240,16 +21117,16 @@ | ||
| 21240 | 21117 | int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) |
| 21241 | 21118 | { |
| 21242 | 21119 | const char *s; |
| 21243 | 21120 | int scan; |
| 21244 | 21121 | |
| 21245 | - | |
| 21122 | + | |
| 21246 | 21123 | if (preg == NULL || preg->program == NULL || string == NULL) { |
| 21247 | 21124 | return REG_ERR_NULL_ARGUMENT; |
| 21248 | 21125 | } |
| 21249 | 21126 | |
| 21250 | - | |
| 21127 | + | |
| 21251 | 21128 | if (*preg->program != REG_MAGIC) { |
| 21252 | 21129 | return REG_ERR_CORRUPTED; |
| 21253 | 21130 | } |
| 21254 | 21131 | |
| 21255 | 21132 | #ifdef DEBUG |
| @@ -21258,51 +21135,51 @@ | ||
| 21258 | 21135 | #endif |
| 21259 | 21136 | |
| 21260 | 21137 | preg->eflags = eflags; |
| 21261 | 21138 | preg->pmatch = pmatch; |
| 21262 | 21139 | preg->nmatch = nmatch; |
| 21263 | - preg->start = string; | |
| 21140 | + preg->start = string; | |
| 21264 | 21141 | |
| 21265 | - | |
| 21142 | + | |
| 21266 | 21143 | for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { |
| 21267 | 21144 | int op = OP(preg, scan); |
| 21268 | 21145 | if (op == END) |
| 21269 | 21146 | break; |
| 21270 | 21147 | if (op == REPX || op == REPXMIN) |
| 21271 | 21148 | preg->program[scan + 4] = 0; |
| 21272 | 21149 | } |
| 21273 | 21150 | |
| 21274 | - | |
| 21151 | + | |
| 21275 | 21152 | if (preg->regmust != 0) { |
| 21276 | 21153 | s = string; |
| 21277 | 21154 | while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) { |
| 21278 | 21155 | if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) { |
| 21279 | 21156 | break; |
| 21280 | 21157 | } |
| 21281 | 21158 | s++; |
| 21282 | 21159 | } |
| 21283 | - if (s == NULL) | |
| 21160 | + if (s == NULL) | |
| 21284 | 21161 | return REG_NOMATCH; |
| 21285 | 21162 | } |
| 21286 | 21163 | |
| 21287 | - | |
| 21164 | + | |
| 21288 | 21165 | preg->regbol = string; |
| 21289 | 21166 | |
| 21290 | - | |
| 21167 | + | |
| 21291 | 21168 | if (preg->reganch) { |
| 21292 | 21169 | if (eflags & REG_NOTBOL) { |
| 21293 | - | |
| 21170 | + | |
| 21294 | 21171 | goto nextline; |
| 21295 | 21172 | } |
| 21296 | 21173 | while (1) { |
| 21297 | 21174 | if (regtry(preg, string)) { |
| 21298 | 21175 | return REG_NOERROR; |
| 21299 | 21176 | } |
| 21300 | 21177 | if (*string) { |
| 21301 | 21178 | nextline: |
| 21302 | 21179 | if (preg->cflags & REG_NEWLINE) { |
| 21303 | - | |
| 21180 | + | |
| 21304 | 21181 | string = strchr(string, '\n'); |
| 21305 | 21182 | if (string) { |
| 21306 | 21183 | preg->regbol = ++string; |
| 21307 | 21184 | continue; |
| 21308 | 21185 | } |
| @@ -21310,22 +21187,22 @@ | ||
| 21310 | 21187 | } |
| 21311 | 21188 | return REG_NOMATCH; |
| 21312 | 21189 | } |
| 21313 | 21190 | } |
| 21314 | 21191 | |
| 21315 | - | |
| 21192 | + | |
| 21316 | 21193 | s = string; |
| 21317 | 21194 | if (preg->regstart != '\0') { |
| 21318 | - | |
| 21195 | + | |
| 21319 | 21196 | while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) { |
| 21320 | 21197 | if (regtry(preg, s)) |
| 21321 | 21198 | return REG_NOERROR; |
| 21322 | 21199 | s++; |
| 21323 | 21200 | } |
| 21324 | 21201 | } |
| 21325 | 21202 | else |
| 21326 | - | |
| 21203 | + | |
| 21327 | 21204 | while (1) { |
| 21328 | 21205 | if (regtry(preg, s)) |
| 21329 | 21206 | return REG_NOERROR; |
| 21330 | 21207 | if (*s == '\0') { |
| 21331 | 21208 | break; |
| @@ -21334,15 +21211,15 @@ | ||
| 21334 | 21211 | int c; |
| 21335 | 21212 | s += utf8_tounicode(s, &c); |
| 21336 | 21213 | } |
| 21337 | 21214 | } |
| 21338 | 21215 | |
| 21339 | - | |
| 21216 | + | |
| 21340 | 21217 | return REG_NOMATCH; |
| 21341 | 21218 | } |
| 21342 | 21219 | |
| 21343 | - | |
| 21220 | + | |
| 21344 | 21221 | static int regtry( regex_t *preg, const char *string ) |
| 21345 | 21222 | { |
| 21346 | 21223 | int i; |
| 21347 | 21224 | |
| 21348 | 21225 | preg->reginput = string; |
| @@ -21379,11 +21256,11 @@ | ||
| 21379 | 21256 | } |
| 21380 | 21257 | |
| 21381 | 21258 | static int reg_range_find(const int *range, int c) |
| 21382 | 21259 | { |
| 21383 | 21260 | while (*range) { |
| 21384 | - | |
| 21261 | + | |
| 21385 | 21262 | if (c >= range[1] && c <= (range[0] + range[1] - 1)) { |
| 21386 | 21263 | return 1; |
| 21387 | 21264 | } |
| 21388 | 21265 | range += 2; |
| 21389 | 21266 | } |
| @@ -21391,11 +21268,11 @@ | ||
| 21391 | 21268 | } |
| 21392 | 21269 | |
| 21393 | 21270 | static const char *str_find(const char *string, int c, int nocase) |
| 21394 | 21271 | { |
| 21395 | 21272 | if (nocase) { |
| 21396 | - | |
| 21273 | + | |
| 21397 | 21274 | c = utf8_upper(c); |
| 21398 | 21275 | } |
| 21399 | 21276 | while (*string) { |
| 21400 | 21277 | int ch; |
| 21401 | 21278 | int n = reg_utf8_tounicode_case(string, &ch, nocase); |
| @@ -21435,15 +21312,15 @@ | ||
| 21435 | 21312 | no = regrepeat(preg, scan + 5, max); |
| 21436 | 21313 | if (no < min) { |
| 21437 | 21314 | return 0; |
| 21438 | 21315 | } |
| 21439 | 21316 | if (matchmin) { |
| 21440 | - | |
| 21317 | + | |
| 21441 | 21318 | max = no; |
| 21442 | 21319 | no = min; |
| 21443 | 21320 | } |
| 21444 | - | |
| 21321 | + | |
| 21445 | 21322 | while (1) { |
| 21446 | 21323 | if (matchmin) { |
| 21447 | 21324 | if (no > max) { |
| 21448 | 21325 | break; |
| 21449 | 21326 | } |
| @@ -21453,22 +21330,22 @@ | ||
| 21453 | 21330 | break; |
| 21454 | 21331 | } |
| 21455 | 21332 | } |
| 21456 | 21333 | preg->reginput = save + utf8_index(save, no); |
| 21457 | 21334 | reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); |
| 21458 | - | |
| 21335 | + | |
| 21459 | 21336 | if (reg_iseol(preg, nextch) || c == nextch) { |
| 21460 | 21337 | if (regmatch(preg, next)) { |
| 21461 | 21338 | return(1); |
| 21462 | 21339 | } |
| 21463 | 21340 | } |
| 21464 | 21341 | if (matchmin) { |
| 21465 | - | |
| 21342 | + | |
| 21466 | 21343 | no++; |
| 21467 | 21344 | } |
| 21468 | 21345 | else { |
| 21469 | - | |
| 21346 | + | |
| 21470 | 21347 | no--; |
| 21471 | 21348 | } |
| 21472 | 21349 | } |
| 21473 | 21350 | return(0); |
| 21474 | 21351 | } |
| @@ -21478,13 +21355,13 @@ | ||
| 21478 | 21355 | int *scanpt = preg->program + scan; |
| 21479 | 21356 | |
| 21480 | 21357 | int max = scanpt[2]; |
| 21481 | 21358 | int min = scanpt[3]; |
| 21482 | 21359 | |
| 21483 | - | |
| 21360 | + | |
| 21484 | 21361 | if (scanpt[4] < min) { |
| 21485 | - | |
| 21362 | + | |
| 21486 | 21363 | scanpt[4]++; |
| 21487 | 21364 | if (regmatch(preg, scan + 5)) { |
| 21488 | 21365 | return 1; |
| 21489 | 21366 | } |
| 21490 | 21367 | scanpt[4]--; |
| @@ -21493,39 +21370,39 @@ | ||
| 21493 | 21370 | if (scanpt[4] > max) { |
| 21494 | 21371 | return 0; |
| 21495 | 21372 | } |
| 21496 | 21373 | |
| 21497 | 21374 | if (matchmin) { |
| 21498 | - | |
| 21375 | + | |
| 21499 | 21376 | if (regmatch(preg, regnext(preg, scan))) { |
| 21500 | 21377 | return 1; |
| 21501 | 21378 | } |
| 21502 | - | |
| 21379 | + | |
| 21503 | 21380 | scanpt[4]++; |
| 21504 | 21381 | if (regmatch(preg, scan + 5)) { |
| 21505 | 21382 | return 1; |
| 21506 | 21383 | } |
| 21507 | 21384 | scanpt[4]--; |
| 21508 | 21385 | return 0; |
| 21509 | 21386 | } |
| 21510 | - | |
| 21387 | + | |
| 21511 | 21388 | if (scanpt[4] < max) { |
| 21512 | 21389 | scanpt[4]++; |
| 21513 | 21390 | if (regmatch(preg, scan + 5)) { |
| 21514 | 21391 | return 1; |
| 21515 | 21392 | } |
| 21516 | 21393 | scanpt[4]--; |
| 21517 | 21394 | } |
| 21518 | - | |
| 21395 | + | |
| 21519 | 21396 | return regmatch(preg, regnext(preg, scan)); |
| 21520 | 21397 | } |
| 21521 | 21398 | |
| 21522 | 21399 | |
| 21523 | 21400 | static int regmatch(regex_t *preg, int prog) |
| 21524 | 21401 | { |
| 21525 | - int scan; | |
| 21526 | - int next; | |
| 21402 | + int scan; | |
| 21403 | + int next; | |
| 21527 | 21404 | const char *save; |
| 21528 | 21405 | |
| 21529 | 21406 | scan = prog; |
| 21530 | 21407 | |
| 21531 | 21408 | #ifdef DEBUG |
| @@ -21535,11 +21412,11 @@ | ||
| 21535 | 21412 | while (scan != 0) { |
| 21536 | 21413 | int n; |
| 21537 | 21414 | int c; |
| 21538 | 21415 | #ifdef DEBUG |
| 21539 | 21416 | if (regnarrate) { |
| 21540 | - fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); | |
| 21417 | + fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); | |
| 21541 | 21418 | } |
| 21542 | 21419 | #endif |
| 21543 | 21420 | next = regnext(preg, scan); |
| 21544 | 21421 | n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); |
| 21545 | 21422 | |
| @@ -21546,49 +21423,49 @@ | ||
| 21546 | 21423 | switch (OP(preg, scan)) { |
| 21547 | 21424 | case BOLX: |
| 21548 | 21425 | if ((preg->eflags & REG_NOTBOL)) { |
| 21549 | 21426 | return(0); |
| 21550 | 21427 | } |
| 21551 | - | |
| 21428 | + | |
| 21552 | 21429 | case BOL: |
| 21553 | 21430 | if (preg->reginput != preg->regbol) { |
| 21554 | 21431 | return(0); |
| 21555 | 21432 | } |
| 21556 | 21433 | break; |
| 21557 | 21434 | case EOLX: |
| 21558 | 21435 | if (c != 0) { |
| 21559 | - | |
| 21436 | + | |
| 21560 | 21437 | return 0; |
| 21561 | 21438 | } |
| 21562 | 21439 | break; |
| 21563 | 21440 | case EOL: |
| 21564 | 21441 | if (!reg_iseol(preg, c)) { |
| 21565 | 21442 | return(0); |
| 21566 | 21443 | } |
| 21567 | 21444 | break; |
| 21568 | 21445 | case WORDA: |
| 21569 | - | |
| 21446 | + | |
| 21570 | 21447 | if ((!isalnum(UCHAR(c))) && c != '_') |
| 21571 | 21448 | return(0); |
| 21572 | - | |
| 21449 | + | |
| 21573 | 21450 | if (preg->reginput > preg->regbol && |
| 21574 | 21451 | (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_')) |
| 21575 | 21452 | return(0); |
| 21576 | 21453 | break; |
| 21577 | 21454 | case WORDZ: |
| 21578 | - | |
| 21455 | + | |
| 21579 | 21456 | if (preg->reginput > preg->regbol) { |
| 21580 | - | |
| 21457 | + | |
| 21581 | 21458 | if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { |
| 21582 | 21459 | c = preg->reginput[-1]; |
| 21583 | - | |
| 21460 | + | |
| 21584 | 21461 | if (isalnum(UCHAR(c)) || c == '_') { |
| 21585 | 21462 | break; |
| 21586 | 21463 | } |
| 21587 | 21464 | } |
| 21588 | 21465 | } |
| 21589 | - | |
| 21466 | + | |
| 21590 | 21467 | return(0); |
| 21591 | 21468 | |
| 21592 | 21469 | case ANY: |
| 21593 | 21470 | if (reg_iseol(preg, c)) |
| 21594 | 21471 | return 0; |
| @@ -21624,12 +21501,12 @@ | ||
| 21624 | 21501 | case NOTHING: |
| 21625 | 21502 | break; |
| 21626 | 21503 | case BACK: |
| 21627 | 21504 | break; |
| 21628 | 21505 | case BRANCH: |
| 21629 | - if (OP(preg, next) != BRANCH) | |
| 21630 | - next = OPERAND(scan); | |
| 21506 | + if (OP(preg, next) != BRANCH) | |
| 21507 | + next = OPERAND(scan); | |
| 21631 | 21508 | else { |
| 21632 | 21509 | do { |
| 21633 | 21510 | save = preg->reginput; |
| 21634 | 21511 | if (regmatch(preg, OPERAND(scan))) { |
| 21635 | 21512 | return(1); |
| @@ -21636,11 +21513,11 @@ | ||
| 21636 | 21513 | } |
| 21637 | 21514 | preg->reginput = save; |
| 21638 | 21515 | scan = regnext(preg, scan); |
| 21639 | 21516 | } while (scan != 0 && OP(preg, scan) == BRANCH); |
| 21640 | 21517 | return(0); |
| 21641 | - | |
| 21518 | + | |
| 21642 | 21519 | } |
| 21643 | 21520 | break; |
| 21644 | 21521 | case REP: |
| 21645 | 21522 | case REPMIN: |
| 21646 | 21523 | return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); |
| @@ -21648,11 +21525,11 @@ | ||
| 21648 | 21525 | case REPX: |
| 21649 | 21526 | case REPXMIN: |
| 21650 | 21527 | return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); |
| 21651 | 21528 | |
| 21652 | 21529 | case END: |
| 21653 | - return 1; | |
| 21530 | + return 1; | |
| 21654 | 21531 | |
| 21655 | 21532 | case OPENNC: |
| 21656 | 21533 | case CLOSENC: |
| 21657 | 21534 | return regmatch(preg, next); |
| 21658 | 21535 | |
| @@ -21695,11 +21572,11 @@ | ||
| 21695 | 21572 | |
| 21696 | 21573 | scan = preg->reginput; |
| 21697 | 21574 | opnd = OPERAND(p); |
| 21698 | 21575 | switch (OP(preg, p)) { |
| 21699 | 21576 | case ANY: |
| 21700 | - | |
| 21577 | + | |
| 21701 | 21578 | while (!reg_iseol(preg, *scan) && count < max) { |
| 21702 | 21579 | count++; |
| 21703 | 21580 | scan++; |
| 21704 | 21581 | } |
| 21705 | 21582 | break; |
| @@ -21731,13 +21608,13 @@ | ||
| 21731 | 21608 | } |
| 21732 | 21609 | count++; |
| 21733 | 21610 | scan += n; |
| 21734 | 21611 | } |
| 21735 | 21612 | break; |
| 21736 | - default: | |
| 21613 | + default: | |
| 21737 | 21614 | preg->err = REG_ERR_INTERNAL; |
| 21738 | - count = 0; | |
| 21615 | + count = 0; | |
| 21739 | 21616 | break; |
| 21740 | 21617 | } |
| 21741 | 21618 | preg->reginput = scan; |
| 21742 | 21619 | |
| 21743 | 21620 | return(count); |
| @@ -21758,11 +21635,11 @@ | ||
| 21758 | 21635 | return(p+offset); |
| 21759 | 21636 | } |
| 21760 | 21637 | |
| 21761 | 21638 | static int regopsize(regex_t *preg, int p ) |
| 21762 | 21639 | { |
| 21763 | - | |
| 21640 | + | |
| 21764 | 21641 | switch (OP(preg, p)) { |
| 21765 | 21642 | case REP: |
| 21766 | 21643 | case REPMIN: |
| 21767 | 21644 | case REPX: |
| 21768 | 21645 | case REPXMIN: |
| @@ -21818,10 +21695,223 @@ | ||
| 21818 | 21695 | |
| 21819 | 21696 | void regfree(regex_t *preg) |
| 21820 | 21697 | { |
| 21821 | 21698 | free(preg->program); |
| 21822 | 21699 | } |
| 21700 | + | |
| 21701 | +#endif | |
| 21702 | +#include <string.h> | |
| 21703 | + | |
| 21704 | +void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) | |
| 21705 | +{ | |
| 21706 | + Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno())); | |
| 21707 | +} | |
| 21708 | + | |
| 21709 | +#if defined(__MINGW32__) | |
| 21710 | +#include <sys/stat.h> | |
| 21711 | + | |
| 21712 | +int Jim_Errno(void) | |
| 21713 | +{ | |
| 21714 | + switch (GetLastError()) { | |
| 21715 | + case ERROR_FILE_NOT_FOUND: return ENOENT; | |
| 21716 | + case ERROR_PATH_NOT_FOUND: return ENOENT; | |
| 21717 | + case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; | |
| 21718 | + case ERROR_ACCESS_DENIED: return EACCES; | |
| 21719 | + case ERROR_INVALID_HANDLE: return EBADF; | |
| 21720 | + case ERROR_BAD_ENVIRONMENT: return E2BIG; | |
| 21721 | + case ERROR_BAD_FORMAT: return ENOEXEC; | |
| 21722 | + case ERROR_INVALID_ACCESS: return EACCES; | |
| 21723 | + case ERROR_INVALID_DRIVE: return ENOENT; | |
| 21724 | + case ERROR_CURRENT_DIRECTORY: return EACCES; | |
| 21725 | + case ERROR_NOT_SAME_DEVICE: return EXDEV; | |
| 21726 | + case ERROR_NO_MORE_FILES: return ENOENT; | |
| 21727 | + case ERROR_WRITE_PROTECT: return EROFS; | |
| 21728 | + case ERROR_BAD_UNIT: return ENXIO; | |
| 21729 | + case ERROR_NOT_READY: return EBUSY; | |
| 21730 | + case ERROR_BAD_COMMAND: return EIO; | |
| 21731 | + case ERROR_CRC: return EIO; | |
| 21732 | + case ERROR_BAD_LENGTH: return EIO; | |
| 21733 | + case ERROR_SEEK: return EIO; | |
| 21734 | + case ERROR_WRITE_FAULT: return EIO; | |
| 21735 | + case ERROR_READ_FAULT: return EIO; | |
| 21736 | + case ERROR_GEN_FAILURE: return EIO; | |
| 21737 | + case ERROR_SHARING_VIOLATION: return EACCES; | |
| 21738 | + case ERROR_LOCK_VIOLATION: return EACCES; | |
| 21739 | + case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; | |
| 21740 | + case ERROR_HANDLE_DISK_FULL: return ENOSPC; | |
| 21741 | + case ERROR_NOT_SUPPORTED: return ENODEV; | |
| 21742 | + case ERROR_REM_NOT_LIST: return EBUSY; | |
| 21743 | + case ERROR_DUP_NAME: return EEXIST; | |
| 21744 | + case ERROR_BAD_NETPATH: return ENOENT; | |
| 21745 | + case ERROR_NETWORK_BUSY: return EBUSY; | |
| 21746 | + case ERROR_DEV_NOT_EXIST: return ENODEV; | |
| 21747 | + case ERROR_TOO_MANY_CMDS: return EAGAIN; | |
| 21748 | + case ERROR_ADAP_HDW_ERR: return EIO; | |
| 21749 | + case ERROR_BAD_NET_RESP: return EIO; | |
| 21750 | + case ERROR_UNEXP_NET_ERR: return EIO; | |
| 21751 | + case ERROR_NETNAME_DELETED: return ENOENT; | |
| 21752 | + case ERROR_NETWORK_ACCESS_DENIED: return EACCES; | |
| 21753 | + case ERROR_BAD_DEV_TYPE: return ENODEV; | |
| 21754 | + case ERROR_BAD_NET_NAME: return ENOENT; | |
| 21755 | + case ERROR_TOO_MANY_NAMES: return ENFILE; | |
| 21756 | + case ERROR_TOO_MANY_SESS: return EIO; | |
| 21757 | + case ERROR_SHARING_PAUSED: return EAGAIN; | |
| 21758 | + case ERROR_REDIR_PAUSED: return EAGAIN; | |
| 21759 | + case ERROR_FILE_EXISTS: return EEXIST; | |
| 21760 | + case ERROR_CANNOT_MAKE: return ENOSPC; | |
| 21761 | + case ERROR_OUT_OF_STRUCTURES: return ENFILE; | |
| 21762 | + case ERROR_ALREADY_ASSIGNED: return EEXIST; | |
| 21763 | + case ERROR_INVALID_PASSWORD: return EPERM; | |
| 21764 | + case ERROR_NET_WRITE_FAULT: return EIO; | |
| 21765 | + case ERROR_NO_PROC_SLOTS: return EAGAIN; | |
| 21766 | + case ERROR_DISK_CHANGE: return EXDEV; | |
| 21767 | + case ERROR_BROKEN_PIPE: return EPIPE; | |
| 21768 | + case ERROR_OPEN_FAILED: return ENOENT; | |
| 21769 | + case ERROR_DISK_FULL: return ENOSPC; | |
| 21770 | + case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; | |
| 21771 | + case ERROR_INVALID_TARGET_HANDLE: return EBADF; | |
| 21772 | + case ERROR_INVALID_NAME: return ENOENT; | |
| 21773 | + case ERROR_PROC_NOT_FOUND: return ESRCH; | |
| 21774 | + case ERROR_WAIT_NO_CHILDREN: return ECHILD; | |
| 21775 | + case ERROR_CHILD_NOT_COMPLETE: return ECHILD; | |
| 21776 | + case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; | |
| 21777 | + case ERROR_SEEK_ON_DEVICE: return ESPIPE; | |
| 21778 | + case ERROR_BUSY_DRIVE: return EAGAIN; | |
| 21779 | + case ERROR_DIR_NOT_EMPTY: return EEXIST; | |
| 21780 | + case ERROR_NOT_LOCKED: return EACCES; | |
| 21781 | + case ERROR_BAD_PATHNAME: return ENOENT; | |
| 21782 | + case ERROR_LOCK_FAILED: return EACCES; | |
| 21783 | + case ERROR_ALREADY_EXISTS: return EEXIST; | |
| 21784 | + case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; | |
| 21785 | + case ERROR_BAD_PIPE: return EPIPE; | |
| 21786 | + case ERROR_PIPE_BUSY: return EAGAIN; | |
| 21787 | + case ERROR_PIPE_NOT_CONNECTED: return EPIPE; | |
| 21788 | + case ERROR_DIRECTORY: return ENOTDIR; | |
| 21789 | + } | |
| 21790 | + return EINVAL; | |
| 21791 | +} | |
| 21792 | + | |
| 21793 | +pidtype waitpid(pidtype pid, int *status, int nohang) | |
| 21794 | +{ | |
| 21795 | + DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); | |
| 21796 | + if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { | |
| 21797 | + | |
| 21798 | + return JIM_BAD_PID; | |
| 21799 | + } | |
| 21800 | + GetExitCodeProcess(pid, &ret); | |
| 21801 | + *status = ret; | |
| 21802 | + CloseHandle(pid); | |
| 21803 | + return pid; | |
| 21804 | +} | |
| 21805 | + | |
| 21806 | +int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file) | |
| 21807 | +{ | |
| 21808 | + char name[MAX_PATH]; | |
| 21809 | + HANDLE handle; | |
| 21810 | + | |
| 21811 | + if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, filename_template ? filename_template : "JIM", 0, name)) { | |
| 21812 | + return -1; | |
| 21813 | + } | |
| 21814 | + | |
| 21815 | + handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, | |
| 21816 | + CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | (unlink_file ? FILE_FLAG_DELETE_ON_CLOSE : 0), | |
| 21817 | + NULL); | |
| 21818 | + | |
| 21819 | + if (handle == INVALID_HANDLE_VALUE) { | |
| 21820 | + goto error; | |
| 21821 | + } | |
| 21822 | + | |
| 21823 | + Jim_SetResultString(interp, name, -1); | |
| 21824 | + return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT); | |
| 21825 | + | |
| 21826 | + error: | |
| 21827 | + Jim_SetResultErrno(interp, name); | |
| 21828 | + DeleteFile(name); | |
| 21829 | + return -1; | |
| 21830 | +} | |
| 21831 | + | |
| 21832 | +int Jim_OpenForWrite(const char *filename, int append) | |
| 21833 | +{ | |
| 21834 | + if (strcmp(filename, "/dev/null") == 0) { | |
| 21835 | + filename = "nul:"; | |
| 21836 | + } | |
| 21837 | + int fd = _open(filename, _O_WRONLY | _O_CREAT | _O_TEXT | (append ? _O_APPEND : _O_TRUNC), _S_IREAD | _S_IWRITE); | |
| 21838 | + if (fd >= 0 && append) { | |
| 21839 | + | |
| 21840 | + _lseek(fd, 0L, SEEK_END); | |
| 21841 | + } | |
| 21842 | + return fd; | |
| 21843 | +} | |
| 21844 | + | |
| 21845 | +int Jim_OpenForRead(const char *filename) | |
| 21846 | +{ | |
| 21847 | + if (strcmp(filename, "/dev/null") == 0) { | |
| 21848 | + filename = "nul:"; | |
| 21849 | + } | |
| 21850 | + return _open(filename, _O_RDONLY | _O_TEXT, 0); | |
| 21851 | +} | |
| 21852 | + | |
| 21853 | +#elif defined(HAVE_UNISTD_H) | |
| 21854 | + | |
| 21855 | + | |
| 21856 | + | |
| 21857 | +int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file) | |
| 21858 | +{ | |
| 21859 | + int fd; | |
| 21860 | + mode_t mask; | |
| 21861 | + Jim_Obj *filenameObj; | |
| 21862 | + | |
| 21863 | + if (filename_template == NULL) { | |
| 21864 | + const char *tmpdir = getenv("TMPDIR"); | |
| 21865 | + if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { | |
| 21866 | + tmpdir = "/tmp/"; | |
| 21867 | + } | |
| 21868 | + filenameObj = Jim_NewStringObj(interp, tmpdir, -1); | |
| 21869 | + if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { | |
| 21870 | + Jim_AppendString(interp, filenameObj, "/", 1); | |
| 21871 | + } | |
| 21872 | + Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); | |
| 21873 | + } | |
| 21874 | + else { | |
| 21875 | + filenameObj = Jim_NewStringObj(interp, filename_template, -1); | |
| 21876 | + } | |
| 21877 | + | |
| 21878 | + | |
| 21879 | + mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); | |
| 21880 | +#ifdef HAVE_MKSTEMP | |
| 21881 | + fd = mkstemp(filenameObj->bytes); | |
| 21882 | +#else | |
| 21883 | + if (mktemp(filenameObj->bytes) == NULL) { | |
| 21884 | + fd = -1; | |
| 21885 | + } | |
| 21886 | + else { | |
| 21887 | + fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC); | |
| 21888 | + } | |
| 21889 | +#endif | |
| 21890 | + umask(mask); | |
| 21891 | + if (fd < 0) { | |
| 21892 | + Jim_SetResultErrno(interp, Jim_String(filenameObj)); | |
| 21893 | + Jim_FreeNewObj(interp, filenameObj); | |
| 21894 | + return -1; | |
| 21895 | + } | |
| 21896 | + if (unlink_file) { | |
| 21897 | + remove(Jim_String(filenameObj)); | |
| 21898 | + } | |
| 21899 | + | |
| 21900 | + Jim_SetResult(interp, filenameObj); | |
| 21901 | + return fd; | |
| 21902 | +} | |
| 21903 | + | |
| 21904 | +int Jim_OpenForWrite(const char *filename, int append) | |
| 21905 | +{ | |
| 21906 | + return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); | |
| 21907 | +} | |
| 21908 | + | |
| 21909 | +int Jim_OpenForRead(const char *filename) | |
| 21910 | +{ | |
| 21911 | + return open(filename, O_RDONLY, 0); | |
| 21912 | +} | |
| 21823 | 21913 | |
| 21824 | 21914 | #endif |
| 21825 | 21915 | |
| 21826 | 21916 | #if defined(_WIN32) || defined(WIN32) |
| 21827 | 21917 | #ifndef STRICT |
| @@ -21879,26 +21969,26 @@ | ||
| 21879 | 21969 | { |
| 21880 | 21970 | DIR *dir = 0; |
| 21881 | 21971 | |
| 21882 | 21972 | if (name && name[0]) { |
| 21883 | 21973 | size_t base_length = strlen(name); |
| 21884 | - const char *all = | |
| 21974 | + const char *all = | |
| 21885 | 21975 | strchr("/\\", name[base_length - 1]) ? "*" : "/*"; |
| 21886 | 21976 | |
| 21887 | 21977 | if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 && |
| 21888 | 21978 | (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) { |
| 21889 | 21979 | strcat(strcpy(dir->name, name), all); |
| 21890 | 21980 | |
| 21891 | 21981 | if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1) |
| 21892 | 21982 | dir->result.d_name = 0; |
| 21893 | - else { | |
| 21983 | + else { | |
| 21894 | 21984 | Jim_Free(dir->name); |
| 21895 | 21985 | Jim_Free(dir); |
| 21896 | 21986 | dir = 0; |
| 21897 | 21987 | } |
| 21898 | 21988 | } |
| 21899 | - else { | |
| 21989 | + else { | |
| 21900 | 21990 | Jim_Free(dir); |
| 21901 | 21991 | dir = 0; |
| 21902 | 21992 | errno = ENOMEM; |
| 21903 | 21993 | } |
| 21904 | 21994 | } |
| @@ -21916,11 +22006,11 @@ | ||
| 21916 | 22006 | if (dir->handle != -1) |
| 21917 | 22007 | result = _findclose(dir->handle); |
| 21918 | 22008 | Jim_Free(dir->name); |
| 21919 | 22009 | Jim_Free(dir); |
| 21920 | 22010 | } |
| 21921 | - if (result == -1) | |
| 22011 | + if (result == -1) | |
| 21922 | 22012 | errno = EBADF; |
| 21923 | 22013 | return result; |
| 21924 | 22014 | } |
| 21925 | 22015 | |
| 21926 | 22016 | struct dirent *readdir(DIR * dir) |
| @@ -21938,28 +22028,77 @@ | ||
| 21938 | 22028 | } |
| 21939 | 22029 | return result; |
| 21940 | 22030 | } |
| 21941 | 22031 | #endif |
| 21942 | 22032 | #endif |
| 22033 | +#include <stdio.h> | |
| 22034 | +#include <signal.h> | |
| 22035 | + | |
| 22036 | + | |
| 22037 | + | |
| 22038 | + | |
| 22039 | + | |
| 22040 | + | |
| 22041 | +#ifndef SIGPIPE | |
| 22042 | +#define SIGPIPE 13 | |
| 22043 | +#endif | |
| 22044 | +#ifndef SIGINT | |
| 22045 | +#define SIGINT 2 | |
| 22046 | +#endif | |
| 22047 | + | |
| 22048 | +const char *Jim_SignalId(int sig) | |
| 22049 | +{ | |
| 22050 | + static char buf[10]; | |
| 22051 | + switch (sig) { | |
| 22052 | + case SIGINT: return "SIGINT"; | |
| 22053 | + case SIGPIPE: return "SIGPIPE"; | |
| 22054 | + | |
| 22055 | + } | |
| 22056 | + snprintf(buf, sizeof(buf), "%d", sig); | |
| 22057 | + return buf; | |
| 22058 | +} | |
| 21943 | 22059 | #ifndef JIM_BOOTSTRAP_LIB_ONLY |
| 21944 | 22060 | #include <errno.h> |
| 21945 | 22061 | #include <string.h> |
| 21946 | 22062 | |
| 21947 | 22063 | |
| 21948 | 22064 | #ifdef USE_LINENOISE |
| 21949 | 22065 | #ifdef HAVE_UNISTD_H |
| 21950 | 22066 | #include <unistd.h> |
| 21951 | 22067 | #endif |
| 22068 | +#ifdef HAVE_SYS_STAT_H | |
| 22069 | + #include <sys/stat.h> | |
| 22070 | +#endif | |
| 21952 | 22071 | #include "linenoise.h" |
| 21953 | 22072 | #else |
| 21954 | 22073 | #define MAX_LINE_LEN 512 |
| 21955 | 22074 | #endif |
| 21956 | 22075 | |
| 21957 | -char *Jim_HistoryGetline(const char *prompt) | |
| 22076 | +#ifdef USE_LINENOISE | |
| 22077 | +static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata); | |
| 22078 | +static const char completion_callback_assoc_key[] = "interactive-completion"; | |
| 22079 | +#endif | |
| 22080 | + | |
| 22081 | +char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt) | |
| 21958 | 22082 | { |
| 21959 | 22083 | #ifdef USE_LINENOISE |
| 21960 | - return linenoise(prompt); | |
| 22084 | + struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key); | |
| 22085 | + char *result; | |
| 22086 | + Jim_Obj *objPtr; | |
| 22087 | + long mlmode = 0; | |
| 22088 | + if (compinfo) { | |
| 22089 | + linenoiseSetCompletionCallback(JimCompletionCallback, compinfo); | |
| 22090 | + } | |
| 22091 | + objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE); | |
| 22092 | + if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) { | |
| 22093 | + linenoiseSetMultiLine(mlmode); | |
| 22094 | + } | |
| 22095 | + | |
| 22096 | + result = linenoise(prompt); | |
| 22097 | + | |
| 22098 | + linenoiseSetCompletionCallback(NULL, NULL); | |
| 22099 | + return result; | |
| 21961 | 22100 | #else |
| 21962 | 22101 | int len; |
| 21963 | 22102 | char *line = malloc(MAX_LINE_LEN); |
| 21964 | 22103 | |
| 21965 | 22104 | fputs(prompt, stdout); |
| @@ -21992,26 +22131,92 @@ | ||
| 21992 | 22131 | } |
| 21993 | 22132 | |
| 21994 | 22133 | void Jim_HistorySave(const char *filename) |
| 21995 | 22134 | { |
| 21996 | 22135 | #ifdef USE_LINENOISE |
| 22136 | +#ifdef HAVE_UMASK | |
| 22137 | + mode_t mask; | |
| 22138 | + | |
| 22139 | + mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); | |
| 22140 | +#endif | |
| 21997 | 22141 | linenoiseHistorySave(filename); |
| 22142 | +#ifdef HAVE_UMASK | |
| 22143 | + mask = umask(mask); | |
| 22144 | +#endif | |
| 21998 | 22145 | #endif |
| 21999 | 22146 | } |
| 22000 | 22147 | |
| 22001 | 22148 | void Jim_HistoryShow(void) |
| 22002 | 22149 | { |
| 22003 | 22150 | #ifdef USE_LINENOISE |
| 22004 | - | |
| 22151 | + | |
| 22005 | 22152 | int i; |
| 22006 | 22153 | int len; |
| 22007 | 22154 | char **history = linenoiseHistory(&len); |
| 22008 | 22155 | for (i = 0; i < len; i++) { |
| 22009 | 22156 | printf("%4d %s\n", i + 1, history[i]); |
| 22010 | 22157 | } |
| 22011 | 22158 | #endif |
| 22012 | 22159 | } |
| 22160 | + | |
| 22161 | +#ifdef USE_LINENOISE | |
| 22162 | +struct JimCompletionInfo { | |
| 22163 | + Jim_Interp *interp; | |
| 22164 | + Jim_Obj *command; | |
| 22165 | +}; | |
| 22166 | + | |
| 22167 | +static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata) | |
| 22168 | +{ | |
| 22169 | + struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata; | |
| 22170 | + Jim_Obj *objv[2]; | |
| 22171 | + int ret; | |
| 22172 | + | |
| 22173 | + objv[0] = info->command; | |
| 22174 | + objv[1] = Jim_NewStringObj(info->interp, prefix, -1); | |
| 22175 | + | |
| 22176 | + ret = Jim_EvalObjVector(info->interp, 2, objv); | |
| 22177 | + | |
| 22178 | + | |
| 22179 | + if (ret == JIM_OK) { | |
| 22180 | + int i; | |
| 22181 | + Jim_Obj *listObj = Jim_GetResult(info->interp); | |
| 22182 | + int len = Jim_ListLength(info->interp, listObj); | |
| 22183 | + for (i = 0; i < len; i++) { | |
| 22184 | + linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i))); | |
| 22185 | + } | |
| 22186 | + } | |
| 22187 | +} | |
| 22188 | + | |
| 22189 | +static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data) | |
| 22190 | +{ | |
| 22191 | + struct JimCompletionInfo *compinfo = data; | |
| 22192 | + | |
| 22193 | + Jim_DecrRefCount(interp, compinfo->command); | |
| 22194 | + | |
| 22195 | + Jim_Free(compinfo); | |
| 22196 | +} | |
| 22197 | +#endif | |
| 22198 | + | |
| 22199 | +void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj) | |
| 22200 | +{ | |
| 22201 | +#ifdef USE_LINENOISE | |
| 22202 | + if (commandObj) { | |
| 22203 | + | |
| 22204 | + Jim_IncrRefCount(commandObj); | |
| 22205 | + } | |
| 22206 | + | |
| 22207 | + Jim_DeleteAssocData(interp, completion_callback_assoc_key); | |
| 22208 | + | |
| 22209 | + if (commandObj) { | |
| 22210 | + struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo)); | |
| 22211 | + compinfo->interp = interp; | |
| 22212 | + compinfo->command = commandObj; | |
| 22213 | + | |
| 22214 | + Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo); | |
| 22215 | + } | |
| 22216 | +#endif | |
| 22217 | +} | |
| 22013 | 22218 | |
| 22014 | 22219 | int Jim_InteractivePrompt(Jim_Interp *interp) |
| 22015 | 22220 | { |
| 22016 | 22221 | int retcode = JIM_OK; |
| 22017 | 22222 | char *history_file = NULL; |
| @@ -22023,10 +22228,12 @@ | ||
| 22023 | 22228 | int history_len = strlen(home) + sizeof("/.jim_history"); |
| 22024 | 22229 | history_file = Jim_Alloc(history_len); |
| 22025 | 22230 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 22026 | 22231 | Jim_HistoryLoad(history_file); |
| 22027 | 22232 | } |
| 22233 | + | |
| 22234 | + Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1)); | |
| 22028 | 22235 | #endif |
| 22029 | 22236 | |
| 22030 | 22237 | printf("Welcome to Jim version %d.%d\n", |
| 22031 | 22238 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 22032 | 22239 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| @@ -22055,21 +22262,21 @@ | ||
| 22055 | 22262 | Jim_IncrRefCount(scriptObjPtr); |
| 22056 | 22263 | while (1) { |
| 22057 | 22264 | char state; |
| 22058 | 22265 | char *line; |
| 22059 | 22266 | |
| 22060 | - line = Jim_HistoryGetline(prompt); | |
| 22267 | + line = Jim_HistoryGetline(interp, prompt); | |
| 22061 | 22268 | if (line == NULL) { |
| 22062 | 22269 | if (errno == EINTR) { |
| 22063 | 22270 | continue; |
| 22064 | 22271 | } |
| 22065 | 22272 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 22066 | 22273 | retcode = JIM_OK; |
| 22067 | 22274 | goto out; |
| 22068 | 22275 | } |
| 22069 | 22276 | if (Jim_Length(scriptObjPtr) != 0) { |
| 22070 | - | |
| 22277 | + | |
| 22071 | 22278 | Jim_AppendString(interp, scriptObjPtr, "\n", 1); |
| 22072 | 22279 | } |
| 22073 | 22280 | Jim_AppendString(interp, scriptObjPtr, line, -1); |
| 22074 | 22281 | free(line); |
| 22075 | 22282 | if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state)) |
| @@ -22077,11 +22284,11 @@ | ||
| 22077 | 22284 | |
| 22078 | 22285 | snprintf(prompt, sizeof(prompt), "%c> ", state); |
| 22079 | 22286 | } |
| 22080 | 22287 | #ifdef USE_LINENOISE |
| 22081 | 22288 | if (strcmp(Jim_String(scriptObjPtr), "h") == 0) { |
| 22082 | - | |
| 22289 | + | |
| 22083 | 22290 | Jim_HistoryShow(); |
| 22084 | 22291 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 22085 | 22292 | continue; |
| 22086 | 22293 | } |
| 22087 | 22294 | |
| @@ -22104,10 +22311,11 @@ | ||
| 22104 | 22311 | printf("%s\n", result); |
| 22105 | 22312 | } |
| 22106 | 22313 | } |
| 22107 | 22314 | out: |
| 22108 | 22315 | Jim_Free(history_file); |
| 22316 | + | |
| 22109 | 22317 | return retcode; |
| 22110 | 22318 | } |
| 22111 | 22319 | |
| 22112 | 22320 | #include <stdio.h> |
| 22113 | 22321 | #include <stdlib.h> |
| @@ -22120,11 +22328,11 @@ | ||
| 22120 | 22328 | static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) |
| 22121 | 22329 | { |
| 22122 | 22330 | int n; |
| 22123 | 22331 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 22124 | 22332 | |
| 22125 | - | |
| 22333 | + | |
| 22126 | 22334 | for (n = 0; n < argc; n++) { |
| 22127 | 22335 | Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1); |
| 22128 | 22336 | |
| 22129 | 22337 | Jim_ListAppendElement(interp, listObj, obj); |
| 22130 | 22338 | } |
| @@ -22146,71 +22354,75 @@ | ||
| 22146 | 22354 | printf("or : %s [options] [filename]\n", executable_name); |
| 22147 | 22355 | printf("\n"); |
| 22148 | 22356 | printf("Without options: Interactive mode\n"); |
| 22149 | 22357 | printf("\n"); |
| 22150 | 22358 | printf("Options:\n"); |
| 22151 | - printf(" --version : prints the version string\n"); | |
| 22152 | - printf(" --help : prints this text\n"); | |
| 22153 | - printf(" -e CMD : executes command CMD\n"); | |
| 22154 | - printf(" NOTE: all subsequent options will be passed as arguments to the command\n"); | |
| 22155 | - printf(" [filename] : executes the script contained in the named file\n"); | |
| 22156 | - printf(" NOTE: all subsequent options will be passed to the script\n\n"); | |
| 22359 | + printf(" --version : prints the version string\n"); | |
| 22360 | + printf(" --help : prints this text\n"); | |
| 22361 | + printf(" -e CMD : executes command CMD\n"); | |
| 22362 | + printf(" NOTE: all subsequent options will be passed as arguments to the command\n"); | |
| 22363 | + printf(" [filename|-] : executes the script contained in the named file, or from stdin if \"-\"\n"); | |
| 22364 | + printf(" NOTE: all subsequent options will be passed to the script\n\n"); | |
| 22157 | 22365 | } |
| 22158 | 22366 | |
| 22159 | 22367 | int main(int argc, char *const argv[]) |
| 22160 | 22368 | { |
| 22161 | 22369 | int retcode; |
| 22162 | 22370 | Jim_Interp *interp; |
| 22163 | 22371 | char *const orig_argv0 = argv[0]; |
| 22164 | 22372 | |
| 22165 | - | |
| 22373 | + | |
| 22166 | 22374 | if (argc > 1 && strcmp(argv[1], "--version") == 0) { |
| 22167 | 22375 | printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100); |
| 22168 | 22376 | return 0; |
| 22169 | 22377 | } |
| 22170 | 22378 | else if (argc > 1 && strcmp(argv[1], "--help") == 0) { |
| 22171 | 22379 | usage(argv[0]); |
| 22172 | 22380 | return 0; |
| 22173 | 22381 | } |
| 22174 | 22382 | |
| 22175 | - | |
| 22383 | + | |
| 22176 | 22384 | interp = Jim_CreateInterp(); |
| 22177 | 22385 | Jim_RegisterCoreCommands(interp); |
| 22178 | 22386 | |
| 22179 | - | |
| 22387 | + | |
| 22180 | 22388 | if (Jim_InitStaticExtensions(interp) != JIM_OK) { |
| 22181 | 22389 | JimPrintErrorMessage(interp); |
| 22182 | 22390 | } |
| 22183 | 22391 | |
| 22184 | 22392 | Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0); |
| 22185 | 22393 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); |
| 22186 | 22394 | retcode = Jim_initjimshInit(interp); |
| 22187 | 22395 | |
| 22188 | 22396 | if (argc == 1) { |
| 22189 | - | |
| 22397 | + | |
| 22190 | 22398 | if (retcode == JIM_ERR) { |
| 22191 | 22399 | JimPrintErrorMessage(interp); |
| 22192 | 22400 | } |
| 22193 | 22401 | if (retcode != JIM_EXIT) { |
| 22194 | 22402 | JimSetArgv(interp, 0, NULL); |
| 22195 | 22403 | retcode = Jim_InteractivePrompt(interp); |
| 22196 | 22404 | } |
| 22197 | 22405 | } |
| 22198 | 22406 | else { |
| 22199 | - | |
| 22407 | + | |
| 22200 | 22408 | if (argc > 2 && strcmp(argv[1], "-e") == 0) { |
| 22201 | - | |
| 22409 | + | |
| 22202 | 22410 | JimSetArgv(interp, argc - 3, argv + 3); |
| 22203 | 22411 | retcode = Jim_Eval(interp, argv[2]); |
| 22204 | 22412 | if (retcode != JIM_ERR) { |
| 22205 | 22413 | printf("%s\n", Jim_String(Jim_GetResult(interp))); |
| 22206 | 22414 | } |
| 22207 | 22415 | } |
| 22208 | 22416 | else { |
| 22209 | 22417 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 22210 | 22418 | JimSetArgv(interp, argc - 2, argv + 2); |
| 22211 | - retcode = Jim_EvalFile(interp, argv[1]); | |
| 22419 | + if (strcmp(argv[1], "-") == 0) { | |
| 22420 | + retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]"); | |
| 22421 | + } else { | |
| 22422 | + retcode = Jim_EvalFile(interp, argv[1]); | |
| 22423 | + } | |
| 22212 | 22424 | } |
| 22213 | 22425 | if (retcode == JIM_ERR) { |
| 22214 | 22426 | JimPrintErrorMessage(interp); |
| 22215 | 22427 | } |
| 22216 | 22428 | } |
| 22217 | 22429 |
| --- autosetup/jimsh0.c | |
| +++ autosetup/jimsh0.c | |
| @@ -1,9 +1,7 @@ | |
| 1 | /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */ |
| 2 | #define _GNU_SOURCE |
| 3 | #define JIM_TCL_COMPAT |
| 4 | #define JIM_REFERENCES |
| 5 | #define JIM_ANSIC |
| 6 | #define JIM_REGEXP |
| 7 | #define HAVE_NO_AUTOCONF |
| 8 | #define _JIMAUTOCONF_H |
| 9 | #define TCL_LIBRARY "." |
| @@ -31,24 +29,39 @@ | |
| 31 | #define HAVE_MKDIR_ONE_ARG |
| 32 | #define HAVE_SYSTEM |
| 33 | #define HAVE_SYS_TIME_H |
| 34 | #define HAVE_DIRENT_H |
| 35 | #define HAVE_UNISTD_H |
| 36 | #else |
| 37 | #define TCL_PLATFORM_OS "unknown" |
| 38 | #define TCL_PLATFORM_PLATFORM "unix" |
| 39 | #define TCL_PLATFORM_PATH_SEPARATOR ":" |
| 40 | #define HAVE_VFORK |
| 41 | #define HAVE_WAITPID |
| 42 | #define HAVE_ISATTY |
| 43 | #define HAVE_MKSTEMP |
| 44 | #define HAVE_LINK |
| 45 | #define HAVE_SYS_TIME_H |
| 46 | #define HAVE_DIRENT_H |
| 47 | #define HAVE_UNISTD_H |
| 48 | #endif |
| 49 | #define JIM_VERSION 76 |
| 50 | #ifndef JIM_WIN32COMPAT_H |
| 51 | #define JIM_WIN32COMPAT_H |
| 52 | |
| 53 | |
| 54 | |
| @@ -88,11 +101,10 @@ | |
| 88 | #define JIM_WIDE_MIN LLONG_MIN |
| 89 | #define JIM_WIDE_MAX LLONG_MAX |
| 90 | #define JIM_WIDE_MODIFIER "I64d" |
| 91 | #define strcasecmp _stricmp |
| 92 | #define strtoull _strtoui64 |
| 93 | #define snprintf _snprintf |
| 94 | |
| 95 | #include <io.h> |
| 96 | |
| 97 | struct timeval { |
| 98 | long tv_sec; |
| @@ -105,29 +117,24 @@ | |
| 105 | struct dirent { |
| 106 | char *d_name; |
| 107 | }; |
| 108 | |
| 109 | typedef struct DIR { |
| 110 | long handle; |
| 111 | struct _finddata_t info; |
| 112 | struct dirent result; |
| 113 | char *name; |
| 114 | } DIR; |
| 115 | |
| 116 | DIR *opendir(const char *name); |
| 117 | int closedir(DIR *dir); |
| 118 | struct dirent *readdir(DIR *dir); |
| 119 | |
| 120 | #elif defined(__MINGW32__) |
| 121 | |
| 122 | #include <stdlib.h> |
| 123 | #define strtod __strtod |
| 124 | |
| 125 | #endif |
| 126 | |
| 127 | #endif |
| 128 | |
| 129 | #ifdef __cplusplus |
| 130 | } |
| 131 | #endif |
| 132 | |
| 133 | #endif |
| @@ -146,19 +153,21 @@ | |
| 146 | |
| 147 | #ifndef JIM_UTF8 |
| 148 | #include <ctype.h> |
| 149 | |
| 150 | |
| 151 | #define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) |
| 152 | #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) |
| 153 | #define utf8_getchars(CP, C) (*(CP) = (C), 1) |
| 154 | #define utf8_upper(C) toupper(C) |
| 155 | #define utf8_title(C) toupper(C) |
| 156 | #define utf8_lower(C) tolower(C) |
| 157 | #define utf8_index(C, I) (I) |
| 158 | #define utf8_charlen(C) 1 |
| 159 | #define utf8_prev_len(S, L) 1 |
| 160 | |
| 161 | #else |
| 162 | |
| 163 | #endif |
| 164 | |
| @@ -175,13 +184,13 @@ | |
| 175 | extern "C" { |
| 176 | #endif |
| 177 | |
| 178 | #include <time.h> |
| 179 | #include <limits.h> |
| 180 | #include <stdio.h> |
| 181 | #include <stdlib.h> |
| 182 | #include <stdarg.h> |
| 183 | |
| 184 | |
| 185 | #ifndef HAVE_NO_AUTOCONF |
| 186 | #endif |
| 187 | |
| @@ -224,31 +233,31 @@ | |
| 224 | #define JIM_SIGNAL 5 |
| 225 | #define JIM_EXIT 6 |
| 226 | |
| 227 | #define JIM_EVAL 7 |
| 228 | |
| 229 | #define JIM_MAX_CALLFRAME_DEPTH 1000 |
| 230 | #define JIM_MAX_EVAL_DEPTH 2000 |
| 231 | |
| 232 | |
| 233 | #define JIM_PRIV_FLAG_SHIFT 20 |
| 234 | |
| 235 | #define JIM_NONE 0 |
| 236 | #define JIM_ERRMSG 1 |
| 237 | #define JIM_ENUM_ABBREV 2 |
| 238 | #define JIM_UNSHARED 4 |
| 239 | #define JIM_MUSTEXIST 8 |
| 240 | |
| 241 | |
| 242 | #define JIM_SUBST_NOVAR 1 |
| 243 | #define JIM_SUBST_NOCMD 2 |
| 244 | #define JIM_SUBST_NOESC 4 |
| 245 | #define JIM_SUBST_FLAG 128 |
| 246 | |
| 247 | |
| 248 | #define JIM_CASESENS 0 |
| 249 | #define JIM_NOCASE 1 |
| 250 | |
| 251 | |
| 252 | #define JIM_PATH_LEN 1024 |
| 253 | |
| 254 | |
| @@ -339,79 +348,80 @@ | |
| 339 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 340 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 341 | |
| 342 | |
| 343 | typedef struct Jim_Obj { |
| 344 | char *bytes; |
| 345 | const struct Jim_ObjType *typePtr; |
| 346 | int refCount; |
| 347 | int length; |
| 348 | |
| 349 | union { |
| 350 | |
| 351 | jim_wide wideValue; |
| 352 | |
| 353 | int intValue; |
| 354 | |
| 355 | double doubleValue; |
| 356 | |
| 357 | void *ptr; |
| 358 | |
| 359 | struct { |
| 360 | void *ptr1; |
| 361 | void *ptr2; |
| 362 | } twoPtrValue; |
| 363 | |
| 364 | struct { |
| 365 | struct Jim_Var *varPtr; |
| 366 | unsigned long callFrameId; |
| 367 | int global; |
| 368 | } varValue; |
| 369 | |
| 370 | struct { |
| 371 | struct Jim_Obj *nsObj; |
| 372 | struct Jim_Cmd *cmdPtr; |
| 373 | unsigned long procEpoch; |
| 374 | } cmdValue; |
| 375 | |
| 376 | struct { |
| 377 | struct Jim_Obj **ele; |
| 378 | int len; |
| 379 | int maxLen; |
| 380 | } listValue; |
| 381 | |
| 382 | struct { |
| 383 | int maxLength; |
| 384 | int charLength; |
| 385 | } strValue; |
| 386 | |
| 387 | struct { |
| 388 | unsigned long id; |
| 389 | struct Jim_Reference *refPtr; |
| 390 | } refValue; |
| 391 | |
| 392 | struct { |
| 393 | struct Jim_Obj *fileNameObj; |
| 394 | int lineNumber; |
| 395 | } sourceValue; |
| 396 | |
| 397 | struct { |
| 398 | struct Jim_Obj *varNameObjPtr; |
| 399 | struct Jim_Obj *indexObjPtr; |
| 400 | } dictSubstValue; |
| 401 | |
| 402 | struct { |
| 403 | void *compre; |
| 404 | unsigned flags; |
| 405 | } regexpValue; |
| 406 | struct { |
| 407 | int line; |
| 408 | int argc; |
| 409 | } scriptLineValue; |
| 410 | } internalRep; |
| 411 | struct Jim_Obj *prevObjPtr; |
| 412 | struct Jim_Obj *nextObjPtr; |
| 413 | } Jim_Obj; |
| 414 | |
| 415 | |
| 416 | #define Jim_IncrRefCount(objPtr) \ |
| 417 | ++(objPtr)->refCount |
| @@ -442,40 +452,40 @@ | |
| 442 | typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, |
| 443 | struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 444 | typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); |
| 445 | |
| 446 | typedef struct Jim_ObjType { |
| 447 | const char *name; |
| 448 | Jim_FreeInternalRepProc *freeIntRepProc; |
| 449 | Jim_DupInternalRepProc *dupIntRepProc; |
| 450 | Jim_UpdateStringProc *updateStringProc; |
| 451 | int flags; |
| 452 | } Jim_ObjType; |
| 453 | |
| 454 | |
| 455 | #define JIM_TYPE_NONE 0 |
| 456 | #define JIM_TYPE_REFERENCES 1 |
| 457 | |
| 458 | |
| 459 | |
| 460 | typedef struct Jim_CallFrame { |
| 461 | unsigned long id; |
| 462 | int level; |
| 463 | struct Jim_HashTable vars; |
| 464 | struct Jim_HashTable *staticVars; |
| 465 | struct Jim_CallFrame *parent; |
| 466 | Jim_Obj *const *argv; |
| 467 | int argc; |
| 468 | Jim_Obj *procArgsObjPtr; |
| 469 | Jim_Obj *procBodyObjPtr; |
| 470 | struct Jim_CallFrame *next; |
| 471 | Jim_Obj *nsObj; |
| 472 | Jim_Obj *fileNameObj; |
| 473 | int line; |
| 474 | Jim_Stack *localCommands; |
| 475 | struct Jim_Obj *tailcallObj; |
| 476 | struct Jim_Cmd *tailcallCmd; |
| 477 | } Jim_CallFrame; |
| 478 | |
| 479 | typedef struct Jim_Var { |
| 480 | Jim_Obj *objPtr; |
| 481 | struct Jim_CallFrame *linkFramePtr; |
| @@ -487,35 +497,35 @@ | |
| 487 | typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); |
| 488 | |
| 489 | |
| 490 | |
| 491 | typedef struct Jim_Cmd { |
| 492 | int inUse; |
| 493 | int isproc; |
| 494 | struct Jim_Cmd *prevCmd; |
| 495 | union { |
| 496 | struct { |
| 497 | |
| 498 | Jim_CmdProc *cmdProc; |
| 499 | Jim_DelCmdProc *delProc; |
| 500 | void *privData; |
| 501 | } native; |
| 502 | struct { |
| 503 | |
| 504 | Jim_Obj *argListObjPtr; |
| 505 | Jim_Obj *bodyObjPtr; |
| 506 | Jim_HashTable *staticVars; |
| 507 | int argListLen; |
| 508 | int reqArity; |
| 509 | int optArity; |
| 510 | int argsPos; |
| 511 | int upcall; |
| 512 | struct Jim_ProcArg { |
| 513 | Jim_Obj *nameObjPtr; |
| 514 | Jim_Obj *defaultObjPtr; |
| 515 | } *arglist; |
| 516 | Jim_Obj *nsObj; |
| 517 | } proc; |
| 518 | } u; |
| 519 | } Jim_Cmd; |
| 520 | |
| 521 | |
| @@ -523,64 +533,64 @@ | |
| 523 | unsigned char sbox[256]; |
| 524 | unsigned int i, j; |
| 525 | } Jim_PrngState; |
| 526 | |
| 527 | typedef struct Jim_Interp { |
| 528 | Jim_Obj *result; |
| 529 | int errorLine; |
| 530 | Jim_Obj *errorFileNameObj; |
| 531 | int addStackTrace; |
| 532 | int maxCallFrameDepth; |
| 533 | int maxEvalDepth; |
| 534 | int evalDepth; |
| 535 | int returnCode; |
| 536 | int returnLevel; |
| 537 | int exitCode; |
| 538 | long id; |
| 539 | int signal_level; |
| 540 | jim_wide sigmask; |
| 541 | int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); |
| 542 | Jim_CallFrame *framePtr; |
| 543 | Jim_CallFrame *topFramePtr; |
| 544 | struct Jim_HashTable commands; |
| 545 | unsigned long procEpoch; /* Incremented every time the result |
| 546 | of procedures names lookup caching |
| 547 | may no longer be valid. */ |
| 548 | unsigned long callFrameEpoch; /* Incremented every time a new |
| 549 | callframe is created. This id is used for the |
| 550 | 'ID' field contained in the Jim_CallFrame |
| 551 | structure. */ |
| 552 | int local; |
| 553 | Jim_Obj *liveList; |
| 554 | Jim_Obj *freeList; |
| 555 | Jim_Obj *currentScriptObj; |
| 556 | Jim_Obj *nullScriptObj; |
| 557 | Jim_Obj *emptyObj; |
| 558 | Jim_Obj *trueObj; |
| 559 | Jim_Obj *falseObj; |
| 560 | unsigned long referenceNextId; |
| 561 | struct Jim_HashTable references; |
| 562 | unsigned long lastCollectId; /* reference max Id of the last GC |
| 563 | execution. It's set to -1 while the collection |
| 564 | is running as sentinel to avoid to recursive |
| 565 | calls via the [collect] command inside |
| 566 | finalizers. */ |
| 567 | time_t lastCollectTime; |
| 568 | Jim_Obj *stackTrace; |
| 569 | Jim_Obj *errorProc; |
| 570 | Jim_Obj *unknown; |
| 571 | int unknown_called; |
| 572 | int errorFlag; |
| 573 | void *cmdPrivData; /* Used to pass the private data pointer to |
| 574 | a command. It is set to what the user specified |
| 575 | via Jim_CreateCommand(). */ |
| 576 | |
| 577 | struct Jim_CallFrame *freeFramesList; |
| 578 | struct Jim_HashTable assocData; |
| 579 | Jim_PrngState *prngState; |
| 580 | struct Jim_HashTable packages; |
| 581 | Jim_Stack *loadHandles; |
| 582 | } Jim_Interp; |
| 583 | |
| 584 | #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ |
| 585 | #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) |
| 586 | #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) |
| @@ -623,11 +633,11 @@ | |
| 623 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 624 | |
| 625 | |
| 626 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 627 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 628 | JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template); |
| 629 | |
| 630 | |
| 631 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 632 | |
| 633 | |
| @@ -816,25 +826,33 @@ | |
| 816 | Jim_Obj *newObjPtr, int flags); |
| 817 | JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, |
| 818 | Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); |
| 819 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 820 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 821 | JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); |
| 822 | JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); |
| 823 | JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); |
| 824 | JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); |
| 825 | |
| 826 | |
| 827 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, |
| 828 | int *intPtr); |
| 829 | |
| 830 | |
| 831 | JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, |
| 832 | Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr); |
| 833 | JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, |
| 834 | Jim_Obj *exprObjPtr, int *boolPtr); |
| 835 | |
| 836 | |
| 837 | JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, |
| 838 | jim_wide *widePtr); |
| 839 | JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, |
| 840 | long *longPtr); |
| @@ -852,10 +870,12 @@ | |
| 852 | |
| 853 | JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, |
| 854 | Jim_Obj *const *argv, const char *msg); |
| 855 | JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, |
| 856 | const char * const *tablePtr, int *indexPtr, const char *name, int flags); |
| 857 | JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp, |
| 858 | Jim_Obj *scriptObj, char *stateCharPtr); |
| 859 | |
| 860 | JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); |
| 861 | |
| @@ -878,11 +898,12 @@ | |
| 878 | |
| 879 | |
| 880 | JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); |
| 881 | JIM_EXPORT void Jim_HistoryLoad(const char *filename); |
| 882 | JIM_EXPORT void Jim_HistorySave(const char *filename); |
| 883 | JIM_EXPORT char *Jim_HistoryGetline(const char *prompt); |
| 884 | JIM_EXPORT void Jim_HistoryAdd(const char *line); |
| 885 | JIM_EXPORT void Jim_HistoryShow(void); |
| 886 | |
| 887 | |
| 888 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| @@ -904,11 +925,11 @@ | |
| 904 | |
| 905 | #ifdef __cplusplus |
| 906 | } |
| 907 | #endif |
| 908 | |
| 909 | #endif |
| 910 | |
| 911 | #ifndef JIM_SUBCMD_H |
| 912 | #define JIM_SUBCMD_H |
| 913 | |
| 914 | |
| @@ -915,24 +936,24 @@ | |
| 915 | #ifdef __cplusplus |
| 916 | extern "C" { |
| 917 | #endif |
| 918 | |
| 919 | |
| 920 | #define JIM_MODFLAG_HIDDEN 0x0001 |
| 921 | #define JIM_MODFLAG_FULLARGV 0x0002 |
| 922 | |
| 923 | |
| 924 | |
| 925 | typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 926 | |
| 927 | typedef struct { |
| 928 | const char *cmd; |
| 929 | const char *args; |
| 930 | jim_subcmd_function *function; |
| 931 | short minargs; |
| 932 | short maxargs; |
| 933 | unsigned short flags; |
| 934 | } jim_subcmd_type; |
| 935 | |
| 936 | const jim_subcmd_type * |
| 937 | Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); |
| 938 | |
| @@ -960,36 +981,36 @@ | |
| 960 | int rm_eo; |
| 961 | } regmatch_t; |
| 962 | |
| 963 | |
| 964 | typedef struct regexp { |
| 965 | |
| 966 | int re_nsub; |
| 967 | |
| 968 | |
| 969 | int cflags; |
| 970 | int err; |
| 971 | int regstart; |
| 972 | int reganch; |
| 973 | int regmust; |
| 974 | int regmlen; |
| 975 | int *program; |
| 976 | |
| 977 | |
| 978 | const char *regparse; |
| 979 | int p; |
| 980 | int proglen; |
| 981 | |
| 982 | |
| 983 | int eflags; |
| 984 | const char *start; |
| 985 | const char *reginput; |
| 986 | const char *regbol; |
| 987 | |
| 988 | |
| 989 | regmatch_t *pmatch; |
| 990 | int nmatch; |
| 991 | } regexp; |
| 992 | |
| 993 | typedef regexp regex_t; |
| 994 | |
| 995 | #define REG_EXTENDED 0 |
| @@ -997,13 +1018,13 @@ | |
| 997 | #define REG_ICASE 2 |
| 998 | |
| 999 | #define REG_NOTBOL 16 |
| 1000 | |
| 1001 | enum { |
| 1002 | REG_NOERROR, |
| 1003 | REG_NOMATCH, |
| 1004 | REG_BADPAT, |
| 1005 | REG_ERR_NULL_ARGUMENT, |
| 1006 | REG_ERR_UNKNOWN, |
| 1007 | REG_ERR_TOO_BIG, |
| 1008 | REG_ERR_NOMEM, |
| 1009 | REG_ERR_TOO_MANY_PAREN, |
| @@ -1027,10 +1048,83 @@ | |
| 1027 | void regfree(regex_t *preg); |
| 1028 | |
| 1029 | #ifdef __cplusplus |
| 1030 | } |
| 1031 | #endif |
| 1032 | |
| 1033 | #endif |
| 1034 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1035 | { |
| 1036 | if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG)) |
| @@ -1100,10 +1194,43 @@ | |
| 1100 | "\n" |
| 1101 | "if {$tcl_platform(platform) eq \"windows\"} {\n" |
| 1102 | " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n" |
| 1103 | "}\n" |
| 1104 | "\n" |
| 1105 | "_jimsh_init\n" |
| 1106 | ); |
| 1107 | } |
| 1108 | int Jim_globInit(Jim_Interp *interp) |
| 1109 | { |
| @@ -1315,10 +1442,17 @@ | |
| 1315 | return JIM_ERR; |
| 1316 | |
| 1317 | return Jim_EvalSource(interp, "stdlib.tcl", 1, |
| 1318 | "\n" |
| 1319 | "\n" |
| 1320 | "\n" |
| 1321 | "proc lambda {arglist args} {\n" |
| 1322 | " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" |
| 1323 | "}\n" |
| 1324 | "\n" |
| @@ -1375,10 +1509,17 @@ | |
| 1375 | " }\n" |
| 1376 | " join $lines \\n\n" |
| 1377 | "}\n" |
| 1378 | "\n" |
| 1379 | "\n" |
| 1380 | "\n" |
| 1381 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1382 | " if {$stacktrace eq \"\"} {\n" |
| 1383 | "\n" |
| 1384 | " set stacktrace [info stacktrace]\n" |
| @@ -1402,31 +1543,10 @@ | |
| 1402 | " if {[exists ::jim::exe]} {\n" |
| 1403 | " return $::jim::exe\n" |
| 1404 | " }\n" |
| 1405 | "}\n" |
| 1406 | "\n" |
| 1407 | "\n" |
| 1408 | "proc {dict with} {&dictVar {args key} script} {\n" |
| 1409 | " set keys {}\n" |
| 1410 | " foreach {n v} [dict get $dictVar {*}$key] {\n" |
| 1411 | " upvar $n var_$n\n" |
| 1412 | " set var_$n $v\n" |
| 1413 | " lappend keys $n\n" |
| 1414 | " }\n" |
| 1415 | " catch {uplevel 1 $script} msg opts\n" |
| 1416 | " if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n" |
| 1417 | " foreach n $keys {\n" |
| 1418 | " if {[info exists var_$n]} {\n" |
| 1419 | " dict set dictVar {*}$key $n [set var_$n]\n" |
| 1420 | " } else {\n" |
| 1421 | " dict unset dictVar {*}$key $n\n" |
| 1422 | " }\n" |
| 1423 | " }\n" |
| 1424 | " }\n" |
| 1425 | " return {*}$opts $msg\n" |
| 1426 | "}\n" |
| 1427 | "\n" |
| 1428 | "\n" |
| 1429 | "proc {dict update} {&varName args script} {\n" |
| 1430 | " set keys {}\n" |
| 1431 | " foreach {n v} $args {\n" |
| 1432 | " upvar $v var_$v\n" |
| @@ -1445,23 +1565,10 @@ | |
| 1445 | " }\n" |
| 1446 | " }\n" |
| 1447 | " return {*}$opts $msg\n" |
| 1448 | "}\n" |
| 1449 | "\n" |
| 1450 | "\n" |
| 1451 | "\n" |
| 1452 | "proc {dict merge} {dict args} {\n" |
| 1453 | " foreach d $args {\n" |
| 1454 | "\n" |
| 1455 | " dict size $d\n" |
| 1456 | " foreach {k v} $d {\n" |
| 1457 | " dict set dict $k $v\n" |
| 1458 | " }\n" |
| 1459 | " }\n" |
| 1460 | " return $dict\n" |
| 1461 | "}\n" |
| 1462 | "\n" |
| 1463 | "proc {dict replace} {dictionary {args {key value}}} {\n" |
| 1464 | " if {[llength ${key value}] % 2} {\n" |
| 1465 | " tailcall {dict replace}\n" |
| 1466 | " }\n" |
| 1467 | " tailcall dict merge $dictionary ${key value}\n" |
| @@ -1503,15 +1610,10 @@ | |
| 1503 | " dict unset dictionary $k\n" |
| 1504 | " }\n" |
| 1505 | " return $dictionary\n" |
| 1506 | "}\n" |
| 1507 | "\n" |
| 1508 | "\n" |
| 1509 | "proc {dict values} {dictionary {pattern *}} {\n" |
| 1510 | " dict keys [lreverse $dictionary] $pattern\n" |
| 1511 | "}\n" |
| 1512 | "\n" |
| 1513 | "\n" |
| 1514 | "proc {dict for} {vars dictionary script} {\n" |
| 1515 | " if {[llength $vars] != 2} {\n" |
| 1516 | " return -code error \"must have exactly two variable names\"\n" |
| 1517 | " }\n" |
| @@ -1591,11 +1693,10 @@ | |
| 1591 | " tailcall {*}$args\n" |
| 1592 | "}\n" |
| 1593 | "\n" |
| 1594 | "\n" |
| 1595 | "\n" |
| 1596 | "\n" |
| 1597 | "proc parray {arrayname {pattern *} {puts puts}} {\n" |
| 1598 | " upvar $arrayname a\n" |
| 1599 | "\n" |
| 1600 | " set max 0\n" |
| 1601 | " foreach name [array names a $pattern]] {\n" |
| @@ -1647,11 +1748,11 @@ | |
| 1647 | "}\n" |
| 1648 | "\n" |
| 1649 | "\n" |
| 1650 | "\n" |
| 1651 | "proc popen {cmd {mode r}} {\n" |
| 1652 | " lassign [socket pipe] r w\n" |
| 1653 | " try {\n" |
| 1654 | " if {[string match \"w*\" $mode]} {\n" |
| 1655 | " lappend cmd <@$r &\n" |
| 1656 | " set pids [exec {*}$cmd]\n" |
| 1657 | " $r close\n" |
| @@ -1663,16 +1764,31 @@ | |
| 1663 | " set f $r\n" |
| 1664 | " }\n" |
| 1665 | " lambda {cmd args} {f pids} {\n" |
| 1666 | " if {$cmd eq \"pid\"} {\n" |
| 1667 | " return $pids\n" |
| 1668 | " }\n" |
| 1669 | " if {$cmd eq \"close\"} {\n" |
| 1670 | " $f close\n" |
| 1671 | "\n" |
| 1672 | " foreach p $pids { os.wait $p }\n" |
| 1673 | " return\n" |
| 1674 | " }\n" |
| 1675 | " tailcall $f $cmd {*}$args\n" |
| 1676 | " }\n" |
| 1677 | " } on error {error opts} {\n" |
| 1678 | " $r close\n" |
| @@ -1692,14 +1808,10 @@ | |
| 1692 | " if {[catch {$channelId pid} pids]} {\n" |
| 1693 | " return \"\"\n" |
| 1694 | " }\n" |
| 1695 | " return $pids\n" |
| 1696 | "}\n" |
| 1697 | "\n" |
| 1698 | "\n" |
| 1699 | "\n" |
| 1700 | "\n" |
| 1701 | "\n" |
| 1702 | "\n" |
| 1703 | "\n" |
| 1704 | "\n" |
| 1705 | "\n" |
| @@ -1780,10 +1892,13 @@ | |
| 1780 | "}\n" |
| 1781 | ); |
| 1782 | } |
| 1783 | |
| 1784 | |
| 1785 | #include <stdio.h> |
| 1786 | #include <string.h> |
| 1787 | #include <errno.h> |
| 1788 | #include <fcntl.h> |
| 1789 | #ifdef HAVE_UNISTD_H |
| @@ -1793,27 +1908,34 @@ | |
| 1793 | |
| 1794 | |
| 1795 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1796 | #include <sys/socket.h> |
| 1797 | #include <netinet/in.h> |
| 1798 | #include <arpa/inet.h> |
| 1799 | #include <netdb.h> |
| 1800 | #ifdef HAVE_SYS_UN_H |
| 1801 | #include <sys/un.h> |
| 1802 | #endif |
| 1803 | #else |
| 1804 | #define JIM_ANSIC |
| 1805 | #endif |
| 1806 | |
| 1807 | #if defined(JIM_SSL) |
| 1808 | #include <openssl/ssl.h> |
| 1809 | #include <openssl/err.h> |
| 1810 | #endif |
| 1811 | |
| 1812 | |
| 1813 | #define AIO_CMD_LEN 32 |
| 1814 | #define AIO_BUF_LEN 256 |
| 1815 | |
| 1816 | #ifndef HAVE_FTELLO |
| 1817 | #define ftello ftell |
| 1818 | #endif |
| 1819 | #ifndef HAVE_FSEEKO |
| @@ -1828,10 +1950,16 @@ | |
| 1828 | #define IPV6 0 |
| 1829 | #ifndef PF_INET6 |
| 1830 | #define PF_INET6 0 |
| 1831 | #endif |
| 1832 | #endif |
| 1833 | |
| 1834 | #define JimCheckStreamError(interp, af) af->fops->error(af) |
| 1835 | |
| 1836 | |
| 1837 | struct AioFile; |
| @@ -1848,11 +1976,11 @@ | |
| 1848 | typedef struct AioFile |
| 1849 | { |
| 1850 | FILE *fp; |
| 1851 | Jim_Obj *filename; |
| 1852 | int type; |
| 1853 | int openFlags; |
| 1854 | int fd; |
| 1855 | Jim_Obj *rEvent; |
| 1856 | Jim_Obj *wEvent; |
| 1857 | Jim_Obj *eEvent; |
| 1858 | int addr_family; |
| @@ -1879,21 +2007,21 @@ | |
| 1879 | { |
| 1880 | if (!ferror(af->fp)) { |
| 1881 | return JIM_OK; |
| 1882 | } |
| 1883 | clearerr(af->fp); |
| 1884 | |
| 1885 | if (feof(af->fp) || errno == EAGAIN || errno == EINTR) { |
| 1886 | return JIM_OK; |
| 1887 | } |
| 1888 | #ifdef ECONNRESET |
| 1889 | if (errno == ECONNRESET) { |
| 1890 | return JIM_OK; |
| 1891 | } |
| 1892 | #endif |
| 1893 | #ifdef ECONNABORTED |
| 1894 | if (errno != ECONNABORTED) { |
| 1895 | return JIM_OK; |
| 1896 | } |
| 1897 | #endif |
| 1898 | return JIM_ERR; |
| 1899 | } |
| @@ -1945,20 +2073,19 @@ | |
| 1945 | JIM_NOTUSED(interp); |
| 1946 | |
| 1947 | Jim_DecrRefCount(interp, af->filename); |
| 1948 | |
| 1949 | #ifdef jim_ext_eventloop |
| 1950 | |
| 1951 | Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); |
| 1952 | #endif |
| 1953 | |
| 1954 | #if defined(JIM_SSL) |
| 1955 | if (af->ssl != NULL) { |
| 1956 | SSL_free(af->ssl); |
| 1957 | } |
| 1958 | #endif |
| 1959 | |
| 1960 | if (!(af->openFlags & AIO_KEEPOPEN)) { |
| 1961 | fclose(af->fp); |
| 1962 | } |
| 1963 | |
| 1964 | Jim_Free(af); |
| @@ -1968,11 +2095,11 @@ | |
| 1968 | { |
| 1969 | AioFile *af = Jim_CmdPrivData(interp); |
| 1970 | char buf[AIO_BUF_LEN]; |
| 1971 | Jim_Obj *objPtr; |
| 1972 | int nonewline = 0; |
| 1973 | jim_wide neededLen = -1; |
| 1974 | |
| 1975 | if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { |
| 1976 | nonewline = 1; |
| 1977 | argv++; |
| 1978 | argc--; |
| @@ -2007,11 +2134,11 @@ | |
| 2007 | } |
| 2008 | } |
| 2009 | if (retval != readlen) |
| 2010 | break; |
| 2011 | } |
| 2012 | |
| 2013 | if (JimCheckStreamError(interp, af)) { |
| 2014 | Jim_FreeNewObj(interp, objPtr); |
| 2015 | return JIM_ERR; |
| 2016 | } |
| 2017 | if (nonewline) { |
| @@ -2029,11 +2156,11 @@ | |
| 2029 | |
| 2030 | AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command) |
| 2031 | { |
| 2032 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2033 | |
| 2034 | |
| 2035 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2036 | return (AioFile *) cmdPtr->u.native.privData; |
| 2037 | } |
| 2038 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2039 | return NULL; |
| @@ -2048,10 +2175,20 @@ | |
| 2048 | return NULL; |
| 2049 | } |
| 2050 | |
| 2051 | return af->fp; |
| 2052 | } |
| 2053 | |
| 2054 | static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2055 | { |
| 2056 | AioFile *af = Jim_CmdPrivData(interp); |
| 2057 | jim_wide count = 0; |
| @@ -2110,21 +2247,21 @@ | |
| 2110 | } |
| 2111 | else { |
| 2112 | len = strlen(buf); |
| 2113 | |
| 2114 | if (len && (buf[len - 1] == '\n')) { |
| 2115 | |
| 2116 | len--; |
| 2117 | } |
| 2118 | |
| 2119 | Jim_AppendString(interp, objPtr, buf, len); |
| 2120 | break; |
| 2121 | } |
| 2122 | } |
| 2123 | |
| 2124 | if (JimCheckStreamError(interp, af)) { |
| 2125 | |
| 2126 | Jim_FreeNewObj(interp, objPtr); |
| 2127 | return JIM_ERR; |
| 2128 | } |
| 2129 | |
| 2130 | if (argc) { |
| @@ -2134,11 +2271,11 @@ | |
| 2134 | } |
| 2135 | |
| 2136 | len = Jim_Length(objPtr); |
| 2137 | |
| 2138 | if (len == 0 && feof(af->fp)) { |
| 2139 | |
| 2140 | len = -1; |
| 2141 | } |
| 2142 | Jim_SetResultInt(interp, len); |
| 2143 | } |
| 2144 | else { |
| @@ -2207,11 +2344,11 @@ | |
| 2207 | } |
| 2208 | |
| 2209 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2210 | { |
| 2211 | if (argc == 3) { |
| 2212 | #if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN) |
| 2213 | static const char * const options[] = { "r", "w", NULL }; |
| 2214 | enum { OPT_R, OPT_W, }; |
| 2215 | int option; |
| 2216 | AioFile *af = Jim_CmdPrivData(interp); |
| 2217 | |
| @@ -2297,10 +2434,11 @@ | |
| 2297 | } |
| 2298 | Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2299 | return JIM_OK; |
| 2300 | } |
| 2301 | #endif |
| 2302 | |
| 2303 | #ifdef HAVE_FSYNC |
| 2304 | static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2305 | { |
| 2306 | AioFile *af = Jim_CmdPrivData(interp); |
| @@ -2364,33 +2502,33 @@ | |
| 2364 | |
| 2365 | static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, |
| 2366 | int argc, Jim_Obj * const *argv) |
| 2367 | { |
| 2368 | if (argc == 0) { |
| 2369 | |
| 2370 | if (*scriptHandlerObj) { |
| 2371 | Jim_SetResult(interp, *scriptHandlerObj); |
| 2372 | } |
| 2373 | return JIM_OK; |
| 2374 | } |
| 2375 | |
| 2376 | if (*scriptHandlerObj) { |
| 2377 | |
| 2378 | Jim_DeleteFileHandler(interp, af->fp, mask); |
| 2379 | } |
| 2380 | |
| 2381 | |
| 2382 | if (Jim_Length(argv[0]) == 0) { |
| 2383 | |
| 2384 | return JIM_OK; |
| 2385 | } |
| 2386 | |
| 2387 | |
| 2388 | Jim_IncrRefCount(argv[0]); |
| 2389 | *scriptHandlerObj = argv[0]; |
| 2390 | |
| 2391 | Jim_CreateFileHandler(interp, af->fp, mask, |
| 2392 | JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer); |
| 2393 | |
| 2394 | return JIM_OK; |
| 2395 | } |
| 2396 | |
| @@ -2414,136 +2552,145 @@ | |
| 2414 | |
| 2415 | return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); |
| 2416 | } |
| 2417 | #endif |
| 2418 | |
| 2419 | |
| 2420 | static const jim_subcmd_type aio_command_table[] = { |
| 2421 | { "read", |
| 2422 | "?-nonewline? ?len?", |
| 2423 | aio_cmd_read, |
| 2424 | 0, |
| 2425 | 2, |
| 2426 | |
| 2427 | }, |
| 2428 | { "copyto", |
| 2429 | "handle ?size?", |
| 2430 | aio_cmd_copy, |
| 2431 | 1, |
| 2432 | 2, |
| 2433 | |
| 2434 | }, |
| 2435 | { "gets", |
| 2436 | "?var?", |
| 2437 | aio_cmd_gets, |
| 2438 | 0, |
| 2439 | 1, |
| 2440 | |
| 2441 | }, |
| 2442 | { "puts", |
| 2443 | "?-nonewline? str", |
| 2444 | aio_cmd_puts, |
| 2445 | 1, |
| 2446 | 2, |
| 2447 | |
| 2448 | }, |
| 2449 | { "isatty", |
| 2450 | NULL, |
| 2451 | aio_cmd_isatty, |
| 2452 | 0, |
| 2453 | 0, |
| 2454 | |
| 2455 | }, |
| 2456 | { "flush", |
| 2457 | NULL, |
| 2458 | aio_cmd_flush, |
| 2459 | 0, |
| 2460 | 0, |
| 2461 | |
| 2462 | }, |
| 2463 | { "eof", |
| 2464 | NULL, |
| 2465 | aio_cmd_eof, |
| 2466 | 0, |
| 2467 | 0, |
| 2468 | |
| 2469 | }, |
| 2470 | { "close", |
| 2471 | "?r(ead)|w(rite)?", |
| 2472 | aio_cmd_close, |
| 2473 | 0, |
| 2474 | 1, |
| 2475 | JIM_MODFLAG_FULLARGV, |
| 2476 | |
| 2477 | }, |
| 2478 | { "seek", |
| 2479 | "offset ?start|current|end", |
| 2480 | aio_cmd_seek, |
| 2481 | 1, |
| 2482 | 2, |
| 2483 | |
| 2484 | }, |
| 2485 | { "tell", |
| 2486 | NULL, |
| 2487 | aio_cmd_tell, |
| 2488 | 0, |
| 2489 | 0, |
| 2490 | |
| 2491 | }, |
| 2492 | { "filename", |
| 2493 | NULL, |
| 2494 | aio_cmd_filename, |
| 2495 | 0, |
| 2496 | 0, |
| 2497 | |
| 2498 | }, |
| 2499 | #ifdef O_NDELAY |
| 2500 | { "ndelay", |
| 2501 | "?0|1?", |
| 2502 | aio_cmd_ndelay, |
| 2503 | 0, |
| 2504 | 1, |
| 2505 | |
| 2506 | }, |
| 2507 | #endif |
| 2508 | #ifdef HAVE_FSYNC |
| 2509 | { "sync", |
| 2510 | NULL, |
| 2511 | aio_cmd_sync, |
| 2512 | 0, |
| 2513 | 0, |
| 2514 | |
| 2515 | }, |
| 2516 | #endif |
| 2517 | { "buffering", |
| 2518 | "none|line|full", |
| 2519 | aio_cmd_buffering, |
| 2520 | 1, |
| 2521 | 1, |
| 2522 | |
| 2523 | }, |
| 2524 | #ifdef jim_ext_eventloop |
| 2525 | { "readable", |
| 2526 | "?readable-script?", |
| 2527 | aio_cmd_readable, |
| 2528 | 0, |
| 2529 | 1, |
| 2530 | |
| 2531 | }, |
| 2532 | { "writable", |
| 2533 | "?writable-script?", |
| 2534 | aio_cmd_writable, |
| 2535 | 0, |
| 2536 | 1, |
| 2537 | |
| 2538 | }, |
| 2539 | { "onexception", |
| 2540 | "?exception-script?", |
| 2541 | aio_cmd_onexception, |
| 2542 | 0, |
| 2543 | 1, |
| 2544 | |
| 2545 | }, |
| 2546 | #endif |
| 2547 | { NULL } |
| 2548 | }; |
| 2549 | |
| @@ -2566,11 +2713,11 @@ | |
| 2566 | |
| 2567 | #ifdef jim_ext_tclcompat |
| 2568 | { |
| 2569 | const char *filename = Jim_String(argv[1]); |
| 2570 | |
| 2571 | |
| 2572 | if (*filename == '|') { |
| 2573 | Jim_Obj *evalObj[3]; |
| 2574 | |
| 2575 | evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); |
| 2576 | evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| @@ -2603,35 +2750,37 @@ | |
| 2603 | } |
| 2604 | |
| 2605 | Jim_IncrRefCount(filename); |
| 2606 | |
| 2607 | if (fh == NULL) { |
| 2608 | #if !defined(JIM_ANSIC) |
| 2609 | if (fd >= 0) { |
| 2610 | fh = fdopen(fd, mode); |
| 2611 | } |
| 2612 | else |
| 2613 | #endif |
| 2614 | fh = fopen(Jim_String(filename), mode); |
| 2615 | |
| 2616 | if (fh == NULL) { |
| 2617 | JimAioSetError(interp, filename); |
| 2618 | #if !defined(JIM_ANSIC) |
| 2619 | if (fd >= 0) { |
| 2620 | close(fd); |
| 2621 | } |
| 2622 | #endif |
| 2623 | Jim_DecrRefCount(interp, filename); |
| 2624 | return NULL; |
| 2625 | } |
| 2626 | } |
| 2627 | |
| 2628 | |
| 2629 | af = Jim_Alloc(sizeof(*af)); |
| 2630 | memset(af, 0, sizeof(*af)); |
| 2631 | af->fp = fh; |
| 2632 | af->fd = fileno(fh); |
| 2633 | af->filename = filename; |
| 2634 | #ifdef FD_CLOEXEC |
| 2635 | if ((openFlags & AIO_KEEPOPEN) == 0) { |
| 2636 | (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2637 | } |
| @@ -2653,72 +2802,45 @@ | |
| 2653 | const char *hdlfmt, int family, const char *mode[2]) |
| 2654 | { |
| 2655 | if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) { |
| 2656 | Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); |
| 2657 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2658 | |
| 2659 | if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) { |
| 2660 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2661 | Jim_SetResult(interp, objPtr); |
| 2662 | return JIM_OK; |
| 2663 | } |
| 2664 | } |
| 2665 | |
| 2666 | |
| 2667 | close(p[0]); |
| 2668 | close(p[1]); |
| 2669 | JimAioSetError(interp, NULL); |
| 2670 | return JIM_ERR; |
| 2671 | } |
| 2672 | #endif |
| 2673 | |
| 2674 | |
| 2675 | int Jim_MakeTempFile(Jim_Interp *interp, const char *template) |
| 2676 | { |
| 2677 | #ifdef HAVE_MKSTEMP |
| 2678 | int fd; |
| 2679 | mode_t mask; |
| 2680 | Jim_Obj *filenameObj; |
| 2681 | |
| 2682 | if (template == NULL) { |
| 2683 | const char *tmpdir = getenv("TMPDIR"); |
| 2684 | if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { |
| 2685 | tmpdir = "/tmp/"; |
| 2686 | } |
| 2687 | filenameObj = Jim_NewStringObj(interp, tmpdir, -1); |
| 2688 | if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { |
| 2689 | Jim_AppendString(interp, filenameObj, "/", 1); |
| 2690 | } |
| 2691 | Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); |
| 2692 | } |
| 2693 | else { |
| 2694 | filenameObj = Jim_NewStringObj(interp, template, -1); |
| 2695 | } |
| 2696 | |
| 2697 | #if defined(S_IRWXG) && defined(S_IRWXO) |
| 2698 | mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); |
| 2699 | #else |
| 2700 | |
| 2701 | mask = umask(S_IXUSR); |
| 2702 | #endif |
| 2703 | |
| 2704 | |
| 2705 | fd = mkstemp(filenameObj->bytes); |
| 2706 | umask(mask); |
| 2707 | if (fd < 0) { |
| 2708 | JimAioSetError(interp, filenameObj); |
| 2709 | Jim_FreeNewObj(interp, filenameObj); |
| 2710 | return -1; |
| 2711 | } |
| 2712 | |
| 2713 | Jim_SetResult(interp, filenameObj); |
| 2714 | return fd; |
| 2715 | #else |
| 2716 | Jim_SetResultString(interp, "platform has no tempfile support", -1); |
| 2717 | return -1; |
| 2718 | #endif |
| 2719 | } |
| 2720 | |
| 2721 | |
| 2722 | int Jim_aioInit(Jim_Interp *interp) |
| 2723 | { |
| 2724 | if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG)) |
| @@ -2727,15 +2849,18 @@ | |
| 2727 | #if defined(JIM_SSL) |
| 2728 | Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL); |
| 2729 | #endif |
| 2730 | |
| 2731 | Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); |
| 2732 | #ifndef JIM_ANSIC |
| 2733 | Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL); |
| 2734 | #endif |
| 2735 | |
| 2736 | |
| 2737 | JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r"); |
| 2738 | JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2739 | JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 2740 | |
| 2741 | return JIM_OK; |
| @@ -2813,12 +2938,12 @@ | |
| 2813 | #include <regex.h> |
| 2814 | #endif |
| 2815 | |
| 2816 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2817 | { |
| 2818 | regfree(objPtr->internalRep.regexpValue.compre); |
| 2819 | Jim_Free(objPtr->internalRep.regexpValue.compre); |
| 2820 | } |
| 2821 | |
| 2822 | static const Jim_ObjType regexpObjType = { |
| 2823 | "regexp", |
| 2824 | FreeRegexpInternalRep, |
| @@ -2831,20 +2956,20 @@ | |
| 2831 | { |
| 2832 | regex_t *compre; |
| 2833 | const char *pattern; |
| 2834 | int ret; |
| 2835 | |
| 2836 | |
| 2837 | if (objPtr->typePtr == ®expObjType && |
| 2838 | objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) { |
| 2839 | |
| 2840 | return objPtr->internalRep.regexpValue.compre; |
| 2841 | } |
| 2842 | |
| 2843 | |
| 2844 | |
| 2845 | |
| 2846 | pattern = Jim_String(objPtr); |
| 2847 | compre = Jim_Alloc(sizeof(regex_t)); |
| 2848 | |
| 2849 | if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { |
| 2850 | char buf[100]; |
| @@ -2857,12 +2982,12 @@ | |
| 2857 | } |
| 2858 | |
| 2859 | Jim_FreeIntRep(interp, objPtr); |
| 2860 | |
| 2861 | objPtr->typePtr = ®expObjType; |
| 2862 | objPtr->internalRep.regexpValue.flags = flags; |
| 2863 | objPtr->internalRep.regexpValue.compre = compre; |
| 2864 | |
| 2865 | return compre; |
| 2866 | } |
| 2867 | |
| 2868 | int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3001,11 +3126,11 @@ | |
| 3001 | } |
| 3002 | |
| 3003 | num_matches++; |
| 3004 | |
| 3005 | if (opt_all && !opt_inline) { |
| 3006 | |
| 3007 | goto try_next_match; |
| 3008 | } |
| 3009 | |
| 3010 | |
| 3011 | j = 0; |
| @@ -3041,11 +3166,11 @@ | |
| 3041 | |
| 3042 | if (opt_inline) { |
| 3043 | Jim_ListAppendElement(interp, resultListObj, resultObj); |
| 3044 | } |
| 3045 | else { |
| 3046 | |
| 3047 | result = Jim_SetVariable(interp, argv[i], resultObj); |
| 3048 | |
| 3049 | if (result != JIM_OK) { |
| 3050 | Jim_FreeObj(interp, resultObj); |
| 3051 | break; |
| @@ -3168,11 +3293,11 @@ | |
| 3168 | |
| 3169 | source_str = Jim_GetString(argv[i + 1], &source_len); |
| 3170 | replace_str = Jim_GetString(argv[i + 2], &replace_len); |
| 3171 | varname = argv[i + 3]; |
| 3172 | |
| 3173 | |
| 3174 | resultObj = Jim_NewStringObj(interp, "", 0); |
| 3175 | |
| 3176 | if (offset) { |
| 3177 | if (offset < 0) { |
| 3178 | offset += source_len + 1; |
| @@ -3183,11 +3308,11 @@ | |
| 3183 | else if (offset < 0) { |
| 3184 | offset = 0; |
| 3185 | } |
| 3186 | } |
| 3187 | |
| 3188 | |
| 3189 | Jim_AppendString(interp, resultObj, source_str, offset); |
| 3190 | |
| 3191 | |
| 3192 | n = source_len - offset; |
| 3193 | p = source_str + offset; |
| @@ -3242,23 +3367,23 @@ | |
| 3242 | } |
| 3243 | |
| 3244 | p += pmatch[0].rm_eo; |
| 3245 | n -= pmatch[0].rm_eo; |
| 3246 | |
| 3247 | |
| 3248 | if (!opt_all || n == 0) { |
| 3249 | break; |
| 3250 | } |
| 3251 | |
| 3252 | |
| 3253 | if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') { |
| 3254 | break; |
| 3255 | } |
| 3256 | |
| 3257 | |
| 3258 | if (pattern[0] == '\0' && n) { |
| 3259 | |
| 3260 | Jim_AppendString(interp, resultObj, p, 1); |
| 3261 | p++; |
| 3262 | n--; |
| 3263 | } |
| 3264 | |
| @@ -3265,11 +3390,11 @@ | |
| 3265 | regexec_flags |= REG_NOTBOL; |
| 3266 | } while (n); |
| 3267 | |
| 3268 | Jim_AppendString(interp, resultObj, p, -1); |
| 3269 | |
| 3270 | |
| 3271 | if (argc - i == 4) { |
| 3272 | result = Jim_SetVariable(interp, varname, resultObj); |
| 3273 | |
| 3274 | if (result == JIM_OK) { |
| 3275 | Jim_SetResultInt(interp, num_matches); |
| @@ -3320,11 +3445,11 @@ | |
| 3320 | |
| 3321 | # ifndef MAXPATHLEN |
| 3322 | # define MAXPATHLEN JIM_PATH_LEN |
| 3323 | # endif |
| 3324 | |
| 3325 | #if defined(__MINGW32__) || defined(_MSC_VER) |
| 3326 | #define ISWINDOWS 1 |
| 3327 | #else |
| 3328 | #define ISWINDOWS 0 |
| 3329 | #endif |
| 3330 | |
| @@ -3371,11 +3496,11 @@ | |
| 3371 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); |
| 3372 | } |
| 3373 | |
| 3374 | static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 3375 | { |
| 3376 | |
| 3377 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 3378 | |
| 3379 | AppendStatElement(interp, listObj, "dev", sb->st_dev); |
| 3380 | AppendStatElement(interp, listObj, "ino", sb->st_ino); |
| 3381 | AppendStatElement(interp, listObj, "mode", sb->st_mode); |
| @@ -3387,36 +3512,38 @@ | |
| 3387 | AppendStatElement(interp, listObj, "mtime", sb->st_mtime); |
| 3388 | AppendStatElement(interp, listObj, "ctime", sb->st_ctime); |
| 3389 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); |
| 3390 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); |
| 3391 | |
| 3392 | |
| 3393 | if (varName) { |
| 3394 | Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE); |
| 3395 | if (objPtr) { |
| 3396 | if (Jim_DictSize(interp, objPtr) < 0) { |
| 3397 | |
| 3398 | Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); |
| 3399 | Jim_FreeNewObj(interp, listObj); |
| 3400 | return JIM_ERR; |
| 3401 | } |
| 3402 | |
| 3403 | if (Jim_IsShared(objPtr)) |
| 3404 | objPtr = Jim_DuplicateObj(interp, objPtr); |
| 3405 | |
| 3406 | |
| 3407 | Jim_ListAppendList(interp, objPtr, listObj); |
| 3408 | Jim_DictSize(interp, objPtr); |
| 3409 | Jim_InvalidateStringRep(objPtr); |
| 3410 | |
| 3411 | Jim_FreeNewObj(interp, listObj); |
| 3412 | listObj = objPtr; |
| 3413 | } |
| 3414 | Jim_SetVariable(interp, varName, listObj); |
| 3415 | } |
| 3416 | |
| 3417 | |
| 3418 | Jim_SetResult(interp, listObj); |
| 3419 | |
| 3420 | return JIM_OK; |
| 3421 | } |
| 3422 | |
| @@ -3432,11 +3559,11 @@ | |
| 3432 | } |
| 3433 | else if (p == path) { |
| 3434 | Jim_SetResultString(interp, "/", -1); |
| 3435 | } |
| 3436 | else if (ISWINDOWS && p[-1] == ':') { |
| 3437 | |
| 3438 | Jim_SetResultString(interp, path, p - path + 1); |
| 3439 | } |
| 3440 | else { |
| 3441 | Jim_SetResultString(interp, path, p - path); |
| 3442 | } |
| @@ -3512,35 +3639,35 @@ | |
| 3512 | char *newname = Jim_Alloc(MAXPATHLEN + 1); |
| 3513 | char *last = newname; |
| 3514 | |
| 3515 | *newname = 0; |
| 3516 | |
| 3517 | |
| 3518 | for (i = 0; i < argc; i++) { |
| 3519 | int len; |
| 3520 | const char *part = Jim_GetString(argv[i], &len); |
| 3521 | |
| 3522 | if (*part == '/') { |
| 3523 | |
| 3524 | last = newname; |
| 3525 | } |
| 3526 | else if (ISWINDOWS && strchr(part, ':')) { |
| 3527 | |
| 3528 | last = newname; |
| 3529 | } |
| 3530 | else if (part[0] == '.') { |
| 3531 | if (part[1] == '/') { |
| 3532 | part += 2; |
| 3533 | len -= 2; |
| 3534 | } |
| 3535 | else if (part[1] == 0 && last != newname) { |
| 3536 | |
| 3537 | continue; |
| 3538 | } |
| 3539 | } |
| 3540 | |
| 3541 | |
| 3542 | if (last != newname && last[-1] != '/') { |
| 3543 | *last++ = '/'; |
| 3544 | } |
| 3545 | |
| 3546 | if (len) { |
| @@ -3551,22 +3678,22 @@ | |
| 3551 | } |
| 3552 | memcpy(last, part, len); |
| 3553 | last += len; |
| 3554 | } |
| 3555 | |
| 3556 | |
| 3557 | if (last > newname + 1 && last[-1] == '/') { |
| 3558 | |
| 3559 | if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) { |
| 3560 | *--last = 0; |
| 3561 | } |
| 3562 | } |
| 3563 | } |
| 3564 | |
| 3565 | *last = 0; |
| 3566 | |
| 3567 | |
| 3568 | |
| 3569 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname)); |
| 3570 | |
| 3571 | return JIM_OK; |
| 3572 | } |
| @@ -3591,11 +3718,11 @@ | |
| 3591 | static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3592 | { |
| 3593 | #ifdef X_OK |
| 3594 | return file_access(interp, argv[0], X_OK); |
| 3595 | #else |
| 3596 | |
| 3597 | Jim_SetResultBool(interp, 1); |
| 3598 | return JIM_OK; |
| 3599 | #endif |
| 3600 | } |
| 3601 | |
| @@ -3616,11 +3743,11 @@ | |
| 3616 | while (argc--) { |
| 3617 | const char *path = Jim_String(argv[0]); |
| 3618 | |
| 3619 | if (unlink(path) == -1 && errno != ENOENT) { |
| 3620 | if (rmdir(path) == -1) { |
| 3621 | |
| 3622 | if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) { |
| 3623 | Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path, |
| 3624 | strerror(errno)); |
| 3625 | return JIM_ERR; |
| 3626 | } |
| @@ -3639,15 +3766,15 @@ | |
| 3639 | |
| 3640 | static int mkdir_all(char *path) |
| 3641 | { |
| 3642 | int ok = 1; |
| 3643 | |
| 3644 | |
| 3645 | goto first; |
| 3646 | |
| 3647 | while (ok--) { |
| 3648 | |
| 3649 | { |
| 3650 | char *slash = strrchr(path, '/'); |
| 3651 | |
| 3652 | if (slash && slash != path) { |
| 3653 | *slash = 0; |
| @@ -3660,24 +3787,24 @@ | |
| 3660 | first: |
| 3661 | if (MKDIR_DEFAULT(path) == 0) { |
| 3662 | return 0; |
| 3663 | } |
| 3664 | if (errno == ENOENT) { |
| 3665 | |
| 3666 | continue; |
| 3667 | } |
| 3668 | |
| 3669 | if (errno == EEXIST) { |
| 3670 | struct stat sb; |
| 3671 | |
| 3672 | if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
| 3673 | return 0; |
| 3674 | } |
| 3675 | |
| 3676 | errno = EEXIST; |
| 3677 | } |
| 3678 | |
| 3679 | break; |
| 3680 | } |
| 3681 | return -1; |
| 3682 | } |
| 3683 | |
| @@ -3698,11 +3825,11 @@ | |
| 3698 | return JIM_OK; |
| 3699 | } |
| 3700 | |
| 3701 | static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3702 | { |
| 3703 | int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL); |
| 3704 | |
| 3705 | if (fd < 0) { |
| 3706 | return JIM_ERR; |
| 3707 | } |
| 3708 | close(fd); |
| @@ -3962,192 +4089,192 @@ | |
| 3962 | { "atime", |
| 3963 | "name", |
| 3964 | file_cmd_atime, |
| 3965 | 1, |
| 3966 | 1, |
| 3967 | |
| 3968 | }, |
| 3969 | { "mtime", |
| 3970 | "name ?time?", |
| 3971 | file_cmd_mtime, |
| 3972 | 1, |
| 3973 | 2, |
| 3974 | |
| 3975 | }, |
| 3976 | { "copy", |
| 3977 | "?-force? source dest", |
| 3978 | file_cmd_copy, |
| 3979 | 2, |
| 3980 | 3, |
| 3981 | |
| 3982 | }, |
| 3983 | { "dirname", |
| 3984 | "name", |
| 3985 | file_cmd_dirname, |
| 3986 | 1, |
| 3987 | 1, |
| 3988 | |
| 3989 | }, |
| 3990 | { "rootname", |
| 3991 | "name", |
| 3992 | file_cmd_rootname, |
| 3993 | 1, |
| 3994 | 1, |
| 3995 | |
| 3996 | }, |
| 3997 | { "extension", |
| 3998 | "name", |
| 3999 | file_cmd_extension, |
| 4000 | 1, |
| 4001 | 1, |
| 4002 | |
| 4003 | }, |
| 4004 | { "tail", |
| 4005 | "name", |
| 4006 | file_cmd_tail, |
| 4007 | 1, |
| 4008 | 1, |
| 4009 | |
| 4010 | }, |
| 4011 | { "normalize", |
| 4012 | "name", |
| 4013 | file_cmd_normalize, |
| 4014 | 1, |
| 4015 | 1, |
| 4016 | |
| 4017 | }, |
| 4018 | { "join", |
| 4019 | "name ?name ...?", |
| 4020 | file_cmd_join, |
| 4021 | 1, |
| 4022 | -1, |
| 4023 | |
| 4024 | }, |
| 4025 | { "readable", |
| 4026 | "name", |
| 4027 | file_cmd_readable, |
| 4028 | 1, |
| 4029 | 1, |
| 4030 | |
| 4031 | }, |
| 4032 | { "writable", |
| 4033 | "name", |
| 4034 | file_cmd_writable, |
| 4035 | 1, |
| 4036 | 1, |
| 4037 | |
| 4038 | }, |
| 4039 | { "executable", |
| 4040 | "name", |
| 4041 | file_cmd_executable, |
| 4042 | 1, |
| 4043 | 1, |
| 4044 | |
| 4045 | }, |
| 4046 | { "exists", |
| 4047 | "name", |
| 4048 | file_cmd_exists, |
| 4049 | 1, |
| 4050 | 1, |
| 4051 | |
| 4052 | }, |
| 4053 | { "delete", |
| 4054 | "?-force|--? name ...", |
| 4055 | file_cmd_delete, |
| 4056 | 1, |
| 4057 | -1, |
| 4058 | |
| 4059 | }, |
| 4060 | { "mkdir", |
| 4061 | "dir ...", |
| 4062 | file_cmd_mkdir, |
| 4063 | 1, |
| 4064 | -1, |
| 4065 | |
| 4066 | }, |
| 4067 | { "tempfile", |
| 4068 | "?template?", |
| 4069 | file_cmd_tempfile, |
| 4070 | 0, |
| 4071 | 1, |
| 4072 | |
| 4073 | }, |
| 4074 | { "rename", |
| 4075 | "?-force? source dest", |
| 4076 | file_cmd_rename, |
| 4077 | 2, |
| 4078 | 3, |
| 4079 | |
| 4080 | }, |
| 4081 | #if defined(HAVE_LINK) && defined(HAVE_SYMLINK) |
| 4082 | { "link", |
| 4083 | "?-symbolic|-hard? newname target", |
| 4084 | file_cmd_link, |
| 4085 | 2, |
| 4086 | 3, |
| 4087 | |
| 4088 | }, |
| 4089 | #endif |
| 4090 | #if defined(HAVE_READLINK) |
| 4091 | { "readlink", |
| 4092 | "name", |
| 4093 | file_cmd_readlink, |
| 4094 | 1, |
| 4095 | 1, |
| 4096 | |
| 4097 | }, |
| 4098 | #endif |
| 4099 | { "size", |
| 4100 | "name", |
| 4101 | file_cmd_size, |
| 4102 | 1, |
| 4103 | 1, |
| 4104 | |
| 4105 | }, |
| 4106 | { "stat", |
| 4107 | "name ?var?", |
| 4108 | file_cmd_stat, |
| 4109 | 1, |
| 4110 | 2, |
| 4111 | |
| 4112 | }, |
| 4113 | { "lstat", |
| 4114 | "name ?var?", |
| 4115 | file_cmd_lstat, |
| 4116 | 1, |
| 4117 | 2, |
| 4118 | |
| 4119 | }, |
| 4120 | { "type", |
| 4121 | "name", |
| 4122 | file_cmd_type, |
| 4123 | 1, |
| 4124 | 1, |
| 4125 | |
| 4126 | }, |
| 4127 | #ifdef HAVE_GETEUID |
| 4128 | { "owned", |
| 4129 | "name", |
| 4130 | file_cmd_owned, |
| 4131 | 1, |
| 4132 | 1, |
| 4133 | |
| 4134 | }, |
| 4135 | #endif |
| 4136 | { "isdirectory", |
| 4137 | "name", |
| 4138 | file_cmd_isdirectory, |
| 4139 | 1, |
| 4140 | 1, |
| 4141 | |
| 4142 | }, |
| 4143 | { "isfile", |
| 4144 | "name", |
| 4145 | file_cmd_isfile, |
| 4146 | 1, |
| 4147 | 1, |
| 4148 | |
| 4149 | }, |
| 4150 | { |
| 4151 | NULL |
| 4152 | } |
| 4153 | }; |
| @@ -4179,11 +4306,11 @@ | |
| 4179 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 4180 | Jim_Free(cwd); |
| 4181 | return JIM_ERR; |
| 4182 | } |
| 4183 | else if (ISWINDOWS) { |
| 4184 | |
| 4185 | char *p = cwd; |
| 4186 | while ((p = strchr(p, '\\')) != NULL) { |
| 4187 | *p++ = '/'; |
| 4188 | } |
| 4189 | } |
| @@ -4203,10 +4330,13 @@ | |
| 4203 | Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL); |
| 4204 | Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL); |
| 4205 | return JIM_OK; |
| 4206 | } |
| 4207 | |
| 4208 | #include <string.h> |
| 4209 | #include <ctype.h> |
| 4210 | |
| 4211 | |
| 4212 | #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) |
| @@ -4214,20 +4344,20 @@ | |
| 4214 | { |
| 4215 | Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp); |
| 4216 | int i, j; |
| 4217 | int rc; |
| 4218 | |
| 4219 | |
| 4220 | for (i = 1; i < argc; i++) { |
| 4221 | int len; |
| 4222 | const char *arg = Jim_GetString(argv[i], &len); |
| 4223 | |
| 4224 | if (i > 1) { |
| 4225 | Jim_AppendString(interp, cmdlineObj, " ", 1); |
| 4226 | } |
| 4227 | if (strpbrk(arg, "\\\" ") == NULL) { |
| 4228 | |
| 4229 | Jim_AppendString(interp, cmdlineObj, arg, len); |
| 4230 | continue; |
| 4231 | } |
| 4232 | |
| 4233 | Jim_AppendString(interp, cmdlineObj, "\"", 1); |
| @@ -4266,86 +4396,26 @@ | |
| 4266 | #else |
| 4267 | |
| 4268 | |
| 4269 | #include <errno.h> |
| 4270 | #include <signal.h> |
| 4271 | |
| 4272 | #if defined(__MINGW32__) |
| 4273 | |
| 4274 | #ifndef STRICT |
| 4275 | #define STRICT |
| 4276 | #endif |
| 4277 | #define WIN32_LEAN_AND_MEAN |
| 4278 | #include <windows.h> |
| 4279 | #include <fcntl.h> |
| 4280 | |
| 4281 | typedef HANDLE fdtype; |
| 4282 | typedef HANDLE pidtype; |
| 4283 | #define JIM_BAD_FD INVALID_HANDLE_VALUE |
| 4284 | #define JIM_BAD_PID INVALID_HANDLE_VALUE |
| 4285 | #define JimCloseFd CloseHandle |
| 4286 | |
| 4287 | #define WIFEXITED(STATUS) 1 |
| 4288 | #define WEXITSTATUS(STATUS) (STATUS) |
| 4289 | #define WIFSIGNALED(STATUS) 0 |
| 4290 | #define WTERMSIG(STATUS) 0 |
| 4291 | #define WNOHANG 1 |
| 4292 | |
| 4293 | static fdtype JimFileno(FILE *fh); |
| 4294 | static pidtype JimWaitPid(pidtype pid, int *status, int nohang); |
| 4295 | static fdtype JimDupFd(fdtype infd); |
| 4296 | static fdtype JimOpenForRead(const char *filename); |
| 4297 | static FILE *JimFdOpenForRead(fdtype fd); |
| 4298 | static int JimPipe(fdtype pipefd[2]); |
| 4299 | static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, |
| 4300 | fdtype inputId, fdtype outputId, fdtype errorId); |
| 4301 | static int JimErrno(void); |
| 4302 | #else |
| 4303 | #include <unistd.h> |
| 4304 | #include <fcntl.h> |
| 4305 | #include <sys/wait.h> |
| 4306 | #include <sys/stat.h> |
| 4307 | |
| 4308 | typedef int fdtype; |
| 4309 | typedef int pidtype; |
| 4310 | #define JimPipe pipe |
| 4311 | #define JimErrno() errno |
| 4312 | #define JIM_BAD_FD -1 |
| 4313 | #define JIM_BAD_PID -1 |
| 4314 | #define JimFileno fileno |
| 4315 | #define JimReadFd read |
| 4316 | #define JimCloseFd close |
| 4317 | #define JimWaitPid waitpid |
| 4318 | #define JimDupFd dup |
| 4319 | #define JimFdOpenForRead(FD) fdopen((FD), "r") |
| 4320 | #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0) |
| 4321 | |
| 4322 | #ifndef HAVE_EXECVPE |
| 4323 | #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) |
| 4324 | #endif |
| 4325 | #endif |
| 4326 | |
| 4327 | static const char *JimStrError(void); |
| 4328 | static char **JimSaveEnv(char **env); |
| 4329 | static void JimRestoreEnv(char **env); |
| 4330 | static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, |
| 4331 | pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr); |
| 4332 | static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr); |
| 4333 | static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj); |
| 4334 | static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len); |
| 4335 | static fdtype JimOpenForWrite(const char *filename, int append); |
| 4336 | static int JimRewindFd(fdtype fd); |
| 4337 | |
| 4338 | static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) |
| 4339 | { |
| 4340 | Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError()); |
| 4341 | } |
| 4342 | |
| 4343 | static const char *JimStrError(void) |
| 4344 | { |
| 4345 | return strerror(JimErrno()); |
| 4346 | } |
| 4347 | |
| 4348 | static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) |
| 4349 | { |
| 4350 | int len; |
| 4351 | const char *s = Jim_GetString(objPtr, &len); |
| @@ -4354,14 +4424,14 @@ | |
| 4354 | objPtr->length--; |
| 4355 | objPtr->bytes[objPtr->length] = '\0'; |
| 4356 | } |
| 4357 | } |
| 4358 | |
| 4359 | static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj) |
| 4360 | { |
| 4361 | char buf[256]; |
| 4362 | FILE *fh = JimFdOpenForRead(fd); |
| 4363 | int ret = 0; |
| 4364 | |
| 4365 | if (fh == NULL) { |
| 4366 | return -1; |
| 4367 | } |
| @@ -4390,18 +4460,18 @@ | |
| 4390 | char *envdata; |
| 4391 | |
| 4392 | Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE); |
| 4393 | |
| 4394 | if (!objPtr) { |
| 4395 | return Jim_GetEnviron(); |
| 4396 | } |
| 4397 | |
| 4398 | |
| 4399 | |
| 4400 | num = Jim_ListLength(interp, objPtr); |
| 4401 | if (num % 2) { |
| 4402 | |
| 4403 | num--; |
| 4404 | } |
| 4405 | size = Jim_Length(objPtr) + 2; |
| 4406 | |
| 4407 | envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); |
| @@ -4433,79 +4503,76 @@ | |
| 4433 | if (env != original_environ) { |
| 4434 | Jim_Free(env); |
| 4435 | } |
| 4436 | } |
| 4437 | |
| 4438 | #ifndef jim_ext_signal |
| 4439 | |
| 4440 | const char *Jim_SignalId(int sig) |
| 4441 | { |
| 4442 | static char buf[10]; |
| 4443 | snprintf(buf, sizeof(buf), "%d", sig); |
| 4444 | return buf; |
| 4445 | } |
| 4446 | |
| 4447 | const char *Jim_SignalName(int sig) |
| 4448 | { |
| 4449 | return Jim_SignalId(sig); |
| 4450 | } |
| 4451 | #endif |
| 4452 | |
| 4453 | static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) |
| 4454 | { |
| 4455 | Jim_Obj *errorCode; |
| 4456 | |
| 4457 | if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) { |
| 4458 | return JIM_OK; |
| 4459 | } |
| 4460 | errorCode = Jim_NewListObj(interp, NULL, 0); |
| 4461 | |
| 4462 | if (WIFEXITED(waitStatus)) { |
| 4463 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); |
| 4464 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 4465 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); |
| 4466 | } |
| 4467 | else { |
| 4468 | const char *type; |
| 4469 | const char *action; |
| 4470 | |
| 4471 | if (WIFSIGNALED(waitStatus)) { |
| 4472 | type = "CHILDKILLED"; |
| 4473 | action = "killed"; |
| 4474 | } |
| 4475 | else { |
| 4476 | type = "CHILDSUSP"; |
| 4477 | action = "suspended"; |
| 4478 | } |
| 4479 | |
| 4480 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1)); |
| 4481 | |
| 4482 | if (errStrObj) { |
| 4483 | Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL); |
| 4484 | } |
| 4485 | |
| 4486 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 4487 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1)); |
| 4488 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1)); |
| 4489 | } |
| 4490 | Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); |
| 4491 | |
| 4492 | return JIM_ERR; |
| 4493 | } |
| 4494 | |
| 4495 | |
| 4496 | struct WaitInfo |
| 4497 | { |
| 4498 | pidtype pid; |
| 4499 | int status; |
| 4500 | int flags; |
| 4501 | }; |
| 4502 | |
| 4503 | struct WaitInfoTable { |
| 4504 | struct WaitInfo *info; |
| 4505 | int size; |
| 4506 | int used; |
| 4507 | }; |
| 4508 | |
| 4509 | |
| 4510 | #define WI_DETACHED 2 |
| 4511 | |
| @@ -4513,32 +4580,53 @@ | |
| 4513 | |
| 4514 | static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData) |
| 4515 | { |
| 4516 | struct WaitInfoTable *table = privData; |
| 4517 | |
| 4518 | Jim_Free(table->info); |
| 4519 | Jim_Free(table); |
| 4520 | } |
| 4521 | |
| 4522 | static struct WaitInfoTable *JimAllocWaitInfoTable(void) |
| 4523 | { |
| 4524 | struct WaitInfoTable *table = Jim_Alloc(sizeof(*table)); |
| 4525 | table->info = NULL; |
| 4526 | table->size = table->used = 0; |
| 4527 | |
| 4528 | return table; |
| 4529 | } |
| 4530 | |
| 4531 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4532 | { |
| 4533 | fdtype outputId; |
| 4534 | fdtype errorId; |
| 4535 | pidtype *pidPtr; |
| 4536 | int numPids, result; |
| 4537 | int child_siginfo = 1; |
| 4538 | Jim_Obj *childErrObj; |
| 4539 | Jim_Obj *errStrObj; |
| 4540 | |
| 4541 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { |
| 4542 | Jim_Obj *listObj; |
| 4543 | int i; |
| 4544 | |
| @@ -4545,17 +4633,17 @@ | |
| 4545 | argc--; |
| 4546 | numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); |
| 4547 | if (numPids < 0) { |
| 4548 | return JIM_ERR; |
| 4549 | } |
| 4550 | |
| 4551 | listObj = Jim_NewListObj(interp, NULL, 0); |
| 4552 | for (i = 0; i < numPids; i++) { |
| 4553 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); |
| 4554 | } |
| 4555 | Jim_SetResult(interp, listObj); |
| 4556 | JimDetachPids(interp, numPids, pidPtr); |
| 4557 | Jim_Free(pidPtr); |
| 4558 | return JIM_OK; |
| 4559 | } |
| 4560 | |
| 4561 | numPids = |
| @@ -4567,54 +4655,98 @@ | |
| 4567 | |
| 4568 | result = JIM_OK; |
| 4569 | |
| 4570 | errStrObj = Jim_NewStringObj(interp, "", 0); |
| 4571 | |
| 4572 | |
| 4573 | if (outputId != JIM_BAD_FD) { |
| 4574 | if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) { |
| 4575 | result = JIM_ERR; |
| 4576 | Jim_SetResultErrno(interp, "error reading from output pipe"); |
| 4577 | } |
| 4578 | } |
| 4579 | |
| 4580 | |
| 4581 | childErrObj = Jim_NewStringObj(interp, "", 0); |
| 4582 | Jim_IncrRefCount(childErrObj); |
| 4583 | |
| 4584 | if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) { |
| 4585 | result = JIM_ERR; |
| 4586 | } |
| 4587 | |
| 4588 | if (errorId != JIM_BAD_FD) { |
| 4589 | int ret; |
| 4590 | JimRewindFd(errorId); |
| 4591 | ret = JimAppendStreamToString(interp, errorId, errStrObj); |
| 4592 | if (ret < 0) { |
| 4593 | Jim_SetResultErrno(interp, "error reading from error pipe"); |
| 4594 | result = JIM_ERR; |
| 4595 | } |
| 4596 | else if (ret > 0) { |
| 4597 | |
| 4598 | child_siginfo = 0; |
| 4599 | } |
| 4600 | } |
| 4601 | |
| 4602 | if (child_siginfo) { |
| 4603 | |
| 4604 | Jim_AppendObj(interp, errStrObj, childErrObj); |
| 4605 | } |
| 4606 | Jim_DecrRefCount(interp, childErrObj); |
| 4607 | |
| 4608 | |
| 4609 | Jim_RemoveTrailingNewline(errStrObj); |
| 4610 | |
| 4611 | |
| 4612 | Jim_SetResult(interp, errStrObj); |
| 4613 | |
| 4614 | return result; |
| 4615 | } |
| 4616 | |
| 4617 | static void JimReapDetachedPids(struct WaitInfoTable *table) |
| 4618 | { |
| 4619 | struct WaitInfo *waitPtr; |
| 4620 | int count; |
| @@ -4627,13 +4759,13 @@ | |
| 4627 | waitPtr = table->info; |
| 4628 | dest = 0; |
| 4629 | for (count = table->used; count > 0; waitPtr++, count--) { |
| 4630 | if (waitPtr->flags & WI_DETACHED) { |
| 4631 | int status; |
| 4632 | pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); |
| 4633 | if (pid == waitPtr->pid) { |
| 4634 | |
| 4635 | table->used--; |
| 4636 | continue; |
| 4637 | } |
| 4638 | } |
| 4639 | if (waitPtr != &table->info[dest]) { |
| @@ -4641,66 +4773,62 @@ | |
| 4641 | } |
| 4642 | dest++; |
| 4643 | } |
| 4644 | } |
| 4645 | |
| 4646 | static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) |
| 4647 | { |
| 4648 | int i; |
| 4649 | |
| 4650 | |
| 4651 | for (i = 0; i < table->used; i++) { |
| 4652 | if (pid == table->info[i].pid) { |
| 4653 | |
| 4654 | JimWaitPid(pid, statusPtr, 0); |
| 4655 | |
| 4656 | |
| 4657 | if (i != table->used - 1) { |
| 4658 | table->info[i] = table->info[table->used - 1]; |
| 4659 | } |
| 4660 | table->used--; |
| 4661 | return pid; |
| 4662 | } |
| 4663 | } |
| 4664 | |
| 4665 | |
| 4666 | return JIM_BAD_PID; |
| 4667 | } |
| 4668 | |
| 4669 | static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) |
| 4670 | { |
| 4671 | int j; |
| 4672 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4673 | |
| 4674 | for (j = 0; j < numPids; j++) { |
| 4675 | |
| 4676 | int i; |
| 4677 | for (i = 0; i < table->used; i++) { |
| 4678 | if (pidPtr[j] == table->info[i].pid) { |
| 4679 | table->info[i].flags |= WI_DETACHED; |
| 4680 | break; |
| 4681 | } |
| 4682 | } |
| 4683 | } |
| 4684 | } |
| 4685 | |
| 4686 | static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name) |
| 4687 | { |
| 4688 | FILE *fh; |
| 4689 | Jim_Obj *fhObj; |
| 4690 | |
| 4691 | fhObj = Jim_NewStringObj(interp, name, -1); |
| 4692 | Jim_IncrRefCount(fhObj); |
| 4693 | fh = Jim_AioFilehandle(interp, fhObj); |
| 4694 | Jim_DecrRefCount(interp, fhObj); |
| 4695 | |
| 4696 | return fh; |
| 4697 | } |
| 4698 | |
| 4699 | static int |
| 4700 | JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, |
| 4701 | fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr) |
| 4702 | { |
| 4703 | pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all |
| 4704 | * the pids of child processes. */ |
| 4705 | int numPids = 0; /* Actual number of processes that exist |
| 4706 | * at *pidPtr right now. */ |
| @@ -4707,16 +4835,16 @@ | |
| 4707 | int cmdCount; /* Count of number of distinct commands |
| 4708 | * found in argc/argv. */ |
| 4709 | const char *input = NULL; /* Describes input for pipeline, depending |
| 4710 | * on "inputFile". NULL means take input |
| 4711 | * from stdin/pipe. */ |
| 4712 | int input_len = 0; |
| 4713 | |
| 4714 | #define FILE_NAME 0 |
| 4715 | #define FILE_APPEND 1 |
| 4716 | #define FILE_HANDLE 2 |
| 4717 | #define FILE_TEXT 3 |
| 4718 | |
| 4719 | int inputFile = FILE_NAME; /* 1 means input is name of input file. |
| 4720 | * 2 means input is filehandle name. |
| 4721 | * 0 means input holds actual |
| 4722 | * text to be input to command. */ |
| @@ -4733,39 +4861,37 @@ | |
| 4733 | */ |
| 4734 | const char *output = NULL; /* Holds name of output file to pipe to, |
| 4735 | * or NULL if output goes to stdout/pipe. */ |
| 4736 | const char *error = NULL; /* Holds name of stderr file to pipe to, |
| 4737 | * or NULL if stderr goes to stderr/pipe. */ |
| 4738 | fdtype inputId = JIM_BAD_FD; |
| 4739 | fdtype outputId = JIM_BAD_FD; |
| 4740 | fdtype errorId = JIM_BAD_FD; |
| 4741 | fdtype lastOutputId = JIM_BAD_FD; |
| 4742 | fdtype pipeIds[2]; |
| 4743 | int firstArg, lastArg; /* Indexes of first and last arguments in |
| 4744 | * current command. */ |
| 4745 | int lastBar; |
| 4746 | int i; |
| 4747 | pidtype pid; |
| 4748 | char **save_environ; |
| 4749 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4750 | |
| 4751 | |
| 4752 | char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1)); |
| 4753 | int arg_count = 0; |
| 4754 | |
| 4755 | JimReapDetachedPids(table); |
| 4756 | |
| 4757 | if (inPipePtr != NULL) { |
| 4758 | *inPipePtr = JIM_BAD_FD; |
| 4759 | } |
| 4760 | if (outPipePtr != NULL) { |
| 4761 | *outPipePtr = JIM_BAD_FD; |
| 4762 | } |
| 4763 | if (errFilePtr != NULL) { |
| 4764 | *errFilePtr = JIM_BAD_FD; |
| 4765 | } |
| 4766 | pipeIds[0] = pipeIds[1] = JIM_BAD_FD; |
| 4767 | |
| 4768 | cmdCount = 1; |
| 4769 | lastBar = -1; |
| 4770 | for (i = 0; i < argc; i++) { |
| 4771 | const char *arg = Jim_String(argv[i]); |
| @@ -4796,11 +4922,11 @@ | |
| 4796 | if (*output == '>') { |
| 4797 | outputFile = FILE_APPEND; |
| 4798 | output++; |
| 4799 | } |
| 4800 | if (*output == '&') { |
| 4801 | |
| 4802 | output++; |
| 4803 | dup_error = 1; |
| 4804 | } |
| 4805 | if (*output == '@') { |
| 4806 | outputFile = FILE_HANDLE; |
| @@ -4837,11 +4963,11 @@ | |
| 4837 | goto badargs; |
| 4838 | } |
| 4839 | lastBar = i; |
| 4840 | cmdCount++; |
| 4841 | } |
| 4842 | |
| 4843 | arg_array[arg_count++] = (char *)arg; |
| 4844 | continue; |
| 4845 | } |
| 4846 | |
| 4847 | if (i >= argc) { |
| @@ -4855,150 +4981,160 @@ | |
| 4855 | badargs: |
| 4856 | Jim_Free(arg_array); |
| 4857 | return -1; |
| 4858 | } |
| 4859 | |
| 4860 | |
| 4861 | save_environ = JimSaveEnv(JimBuildEnv(interp)); |
| 4862 | |
| 4863 | if (input != NULL) { |
| 4864 | if (inputFile == FILE_TEXT) { |
| 4865 | inputId = JimCreateTemp(interp, input, input_len); |
| 4866 | if (inputId == JIM_BAD_FD) { |
| 4867 | goto error; |
| 4868 | } |
| 4869 | } |
| 4870 | else if (inputFile == FILE_HANDLE) { |
| 4871 | |
| 4872 | FILE *fh = JimGetAioFilehandle(interp, input); |
| 4873 | |
| 4874 | if (fh == NULL) { |
| 4875 | goto error; |
| 4876 | } |
| 4877 | inputId = JimDupFd(JimFileno(fh)); |
| 4878 | } |
| 4879 | else { |
| 4880 | inputId = JimOpenForRead(input); |
| 4881 | if (inputId == JIM_BAD_FD) { |
| 4882 | Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError()); |
| 4883 | goto error; |
| 4884 | } |
| 4885 | } |
| 4886 | } |
| 4887 | else if (inPipePtr != NULL) { |
| 4888 | if (JimPipe(pipeIds) != 0) { |
| 4889 | Jim_SetResultErrno(interp, "couldn't create input pipe for command"); |
| 4890 | goto error; |
| 4891 | } |
| 4892 | inputId = pipeIds[0]; |
| 4893 | *inPipePtr = pipeIds[1]; |
| 4894 | pipeIds[0] = pipeIds[1] = JIM_BAD_FD; |
| 4895 | } |
| 4896 | |
| 4897 | if (output != NULL) { |
| 4898 | if (outputFile == FILE_HANDLE) { |
| 4899 | FILE *fh = JimGetAioFilehandle(interp, output); |
| 4900 | if (fh == NULL) { |
| 4901 | goto error; |
| 4902 | } |
| 4903 | fflush(fh); |
| 4904 | lastOutputId = JimDupFd(JimFileno(fh)); |
| 4905 | } |
| 4906 | else { |
| 4907 | lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND); |
| 4908 | if (lastOutputId == JIM_BAD_FD) { |
| 4909 | Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError()); |
| 4910 | goto error; |
| 4911 | } |
| 4912 | } |
| 4913 | } |
| 4914 | else if (outPipePtr != NULL) { |
| 4915 | if (JimPipe(pipeIds) != 0) { |
| 4916 | Jim_SetResultErrno(interp, "couldn't create output pipe"); |
| 4917 | goto error; |
| 4918 | } |
| 4919 | lastOutputId = pipeIds[1]; |
| 4920 | *outPipePtr = pipeIds[0]; |
| 4921 | pipeIds[0] = pipeIds[1] = JIM_BAD_FD; |
| 4922 | } |
| 4923 | |
| 4924 | if (error != NULL) { |
| 4925 | if (errorFile == FILE_HANDLE) { |
| 4926 | if (strcmp(error, "1") == 0) { |
| 4927 | |
| 4928 | if (lastOutputId != JIM_BAD_FD) { |
| 4929 | errorId = JimDupFd(lastOutputId); |
| 4930 | } |
| 4931 | else { |
| 4932 | |
| 4933 | error = "stdout"; |
| 4934 | } |
| 4935 | } |
| 4936 | if (errorId == JIM_BAD_FD) { |
| 4937 | FILE *fh = JimGetAioFilehandle(interp, error); |
| 4938 | if (fh == NULL) { |
| 4939 | goto error; |
| 4940 | } |
| 4941 | fflush(fh); |
| 4942 | errorId = JimDupFd(JimFileno(fh)); |
| 4943 | } |
| 4944 | } |
| 4945 | else { |
| 4946 | errorId = JimOpenForWrite(error, errorFile == FILE_APPEND); |
| 4947 | if (errorId == JIM_BAD_FD) { |
| 4948 | Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError()); |
| 4949 | goto error; |
| 4950 | } |
| 4951 | } |
| 4952 | } |
| 4953 | else if (errFilePtr != NULL) { |
| 4954 | errorId = JimCreateTemp(interp, NULL, 0); |
| 4955 | if (errorId == JIM_BAD_FD) { |
| 4956 | goto error; |
| 4957 | } |
| 4958 | *errFilePtr = JimDupFd(errorId); |
| 4959 | } |
| 4960 | |
| 4961 | |
| 4962 | pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); |
| 4963 | for (i = 0; i < numPids; i++) { |
| 4964 | pidPtr[i] = JIM_BAD_PID; |
| 4965 | } |
| 4966 | for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { |
| 4967 | int pipe_dup_err = 0; |
| 4968 | fdtype origErrorId = errorId; |
| 4969 | |
| 4970 | for (lastArg = firstArg; lastArg < arg_count; lastArg++) { |
| 4971 | if (arg_array[lastArg][0] == '|') { |
| 4972 | if (arg_array[lastArg][1] == '&') { |
| 4973 | pipe_dup_err = 1; |
| 4974 | } |
| 4975 | break; |
| 4976 | } |
| 4977 | } |
| 4978 | |
| 4979 | arg_array[lastArg] = NULL; |
| 4980 | if (lastArg == arg_count) { |
| 4981 | outputId = lastOutputId; |
| 4982 | } |
| 4983 | else { |
| 4984 | if (JimPipe(pipeIds) != 0) { |
| 4985 | Jim_SetResultErrno(interp, "couldn't create pipe"); |
| 4986 | goto error; |
| 4987 | } |
| 4988 | outputId = pipeIds[1]; |
| 4989 | } |
| 4990 | |
| 4991 | |
| 4992 | if (pipe_dup_err) { |
| 4993 | errorId = outputId; |
| 4994 | } |
| 4995 | |
| 4996 | |
| 4997 | |
| 4998 | #ifdef __MINGW32__ |
| 4999 | pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); |
| 5000 | if (pid == JIM_BAD_PID) { |
| 5001 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 5002 | goto error; |
| 5003 | } |
| 5004 | #else |
| @@ -5006,32 +5142,37 @@ | |
| 5006 | if (pid < 0) { |
| 5007 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 5008 | goto error; |
| 5009 | } |
| 5010 | if (pid == 0) { |
| 5011 | |
| 5012 | |
| 5013 | if (inputId != -1) dup2(inputId, 0); |
| 5014 | if (outputId != -1) dup2(outputId, 1); |
| 5015 | if (errorId != -1) dup2(errorId, 2); |
| 5016 | |
| 5017 | for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { |
| 5018 | close(i); |
| 5019 | } |
| 5020 | |
| 5021 | |
| 5022 | (void)signal(SIGPIPE, SIG_DFL); |
| 5023 | |
| 5024 | execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); |
| 5025 | |
| 5026 | |
| 5027 | fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]); |
| 5028 | _exit(127); |
| 5029 | } |
| 5030 | #endif |
| 5031 | |
| 5032 | |
| 5033 | |
| 5034 | if (table->used == table->size) { |
| 5035 | table->size += WAIT_TABLE_GROW_BY; |
| 5036 | table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info)); |
| 5037 | } |
| @@ -5040,66 +5181,67 @@ | |
| 5040 | table->info[table->used].flags = 0; |
| 5041 | table->used++; |
| 5042 | |
| 5043 | pidPtr[numPids] = pid; |
| 5044 | |
| 5045 | |
| 5046 | errorId = origErrorId; |
| 5047 | |
| 5048 | |
| 5049 | if (inputId != JIM_BAD_FD) { |
| 5050 | JimCloseFd(inputId); |
| 5051 | } |
| 5052 | if (outputId != JIM_BAD_FD) { |
| 5053 | JimCloseFd(outputId); |
| 5054 | } |
| 5055 | inputId = pipeIds[0]; |
| 5056 | pipeIds[0] = pipeIds[1] = JIM_BAD_FD; |
| 5057 | } |
| 5058 | *pidArrayPtr = pidPtr; |
| 5059 | |
| 5060 | |
| 5061 | cleanup: |
| 5062 | if (inputId != JIM_BAD_FD) { |
| 5063 | JimCloseFd(inputId); |
| 5064 | } |
| 5065 | if (lastOutputId != JIM_BAD_FD) { |
| 5066 | JimCloseFd(lastOutputId); |
| 5067 | } |
| 5068 | if (errorId != JIM_BAD_FD) { |
| 5069 | JimCloseFd(errorId); |
| 5070 | } |
| 5071 | Jim_Free(arg_array); |
| 5072 | |
| 5073 | JimRestoreEnv(save_environ); |
| 5074 | |
| 5075 | return numPids; |
| 5076 | |
| 5077 | |
| 5078 | error: |
| 5079 | if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) { |
| 5080 | JimCloseFd(*inPipePtr); |
| 5081 | *inPipePtr = JIM_BAD_FD; |
| 5082 | } |
| 5083 | if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) { |
| 5084 | JimCloseFd(*outPipePtr); |
| 5085 | *outPipePtr = JIM_BAD_FD; |
| 5086 | } |
| 5087 | if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) { |
| 5088 | JimCloseFd(*errFilePtr); |
| 5089 | *errFilePtr = JIM_BAD_FD; |
| 5090 | } |
| 5091 | if (pipeIds[0] != JIM_BAD_FD) { |
| 5092 | JimCloseFd(pipeIds[0]); |
| 5093 | } |
| 5094 | if (pipeIds[1] != JIM_BAD_FD) { |
| 5095 | JimCloseFd(pipeIds[1]); |
| 5096 | } |
| 5097 | if (pidPtr != NULL) { |
| 5098 | for (i = 0; i < numPids; i++) { |
| 5099 | if (pidPtr[i] != JIM_BAD_PID) { |
| 5100 | JimDetachPids(interp, 1, &pidPtr[i]); |
| 5101 | } |
| 5102 | } |
| 5103 | Jim_Free(pidPtr); |
| 5104 | } |
| 5105 | numPids = -1; |
| @@ -5111,11 +5253,11 @@ | |
| 5111 | { |
| 5112 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 5113 | int result = JIM_OK; |
| 5114 | int i; |
| 5115 | |
| 5116 | |
| 5117 | for (i = 0; i < numPids; i++) { |
| 5118 | int waitStatus = 0; |
| 5119 | if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) { |
| 5120 | if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) { |
| 5121 | result = JIM_ERR; |
| @@ -5127,234 +5269,30 @@ | |
| 5127 | return result; |
| 5128 | } |
| 5129 | |
| 5130 | int Jim_execInit(Jim_Interp *interp) |
| 5131 | { |
| 5132 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 5133 | return JIM_ERR; |
| 5134 | |
| 5135 | #ifdef SIGPIPE |
| 5136 | (void)signal(SIGPIPE, SIG_IGN); |
| 5137 | #endif |
| 5138 | |
| 5139 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); |
| 5140 | return JIM_OK; |
| 5141 | } |
| 5142 | |
| 5143 | #if defined(__MINGW32__) |
| 5144 | |
| 5145 | |
| 5146 | static SECURITY_ATTRIBUTES *JimStdSecAttrs(void) |
| 5147 | { |
| 5148 | static SECURITY_ATTRIBUTES secAtts; |
| 5149 | |
| 5150 | secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); |
| 5151 | secAtts.lpSecurityDescriptor = NULL; |
| 5152 | secAtts.bInheritHandle = TRUE; |
| 5153 | return &secAtts; |
| 5154 | } |
| 5155 | |
| 5156 | static int JimErrno(void) |
| 5157 | { |
| 5158 | switch (GetLastError()) { |
| 5159 | case ERROR_FILE_NOT_FOUND: return ENOENT; |
| 5160 | case ERROR_PATH_NOT_FOUND: return ENOENT; |
| 5161 | case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; |
| 5162 | case ERROR_ACCESS_DENIED: return EACCES; |
| 5163 | case ERROR_INVALID_HANDLE: return EBADF; |
| 5164 | case ERROR_BAD_ENVIRONMENT: return E2BIG; |
| 5165 | case ERROR_BAD_FORMAT: return ENOEXEC; |
| 5166 | case ERROR_INVALID_ACCESS: return EACCES; |
| 5167 | case ERROR_INVALID_DRIVE: return ENOENT; |
| 5168 | case ERROR_CURRENT_DIRECTORY: return EACCES; |
| 5169 | case ERROR_NOT_SAME_DEVICE: return EXDEV; |
| 5170 | case ERROR_NO_MORE_FILES: return ENOENT; |
| 5171 | case ERROR_WRITE_PROTECT: return EROFS; |
| 5172 | case ERROR_BAD_UNIT: return ENXIO; |
| 5173 | case ERROR_NOT_READY: return EBUSY; |
| 5174 | case ERROR_BAD_COMMAND: return EIO; |
| 5175 | case ERROR_CRC: return EIO; |
| 5176 | case ERROR_BAD_LENGTH: return EIO; |
| 5177 | case ERROR_SEEK: return EIO; |
| 5178 | case ERROR_WRITE_FAULT: return EIO; |
| 5179 | case ERROR_READ_FAULT: return EIO; |
| 5180 | case ERROR_GEN_FAILURE: return EIO; |
| 5181 | case ERROR_SHARING_VIOLATION: return EACCES; |
| 5182 | case ERROR_LOCK_VIOLATION: return EACCES; |
| 5183 | case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; |
| 5184 | case ERROR_HANDLE_DISK_FULL: return ENOSPC; |
| 5185 | case ERROR_NOT_SUPPORTED: return ENODEV; |
| 5186 | case ERROR_REM_NOT_LIST: return EBUSY; |
| 5187 | case ERROR_DUP_NAME: return EEXIST; |
| 5188 | case ERROR_BAD_NETPATH: return ENOENT; |
| 5189 | case ERROR_NETWORK_BUSY: return EBUSY; |
| 5190 | case ERROR_DEV_NOT_EXIST: return ENODEV; |
| 5191 | case ERROR_TOO_MANY_CMDS: return EAGAIN; |
| 5192 | case ERROR_ADAP_HDW_ERR: return EIO; |
| 5193 | case ERROR_BAD_NET_RESP: return EIO; |
| 5194 | case ERROR_UNEXP_NET_ERR: return EIO; |
| 5195 | case ERROR_NETNAME_DELETED: return ENOENT; |
| 5196 | case ERROR_NETWORK_ACCESS_DENIED: return EACCES; |
| 5197 | case ERROR_BAD_DEV_TYPE: return ENODEV; |
| 5198 | case ERROR_BAD_NET_NAME: return ENOENT; |
| 5199 | case ERROR_TOO_MANY_NAMES: return ENFILE; |
| 5200 | case ERROR_TOO_MANY_SESS: return EIO; |
| 5201 | case ERROR_SHARING_PAUSED: return EAGAIN; |
| 5202 | case ERROR_REDIR_PAUSED: return EAGAIN; |
| 5203 | case ERROR_FILE_EXISTS: return EEXIST; |
| 5204 | case ERROR_CANNOT_MAKE: return ENOSPC; |
| 5205 | case ERROR_OUT_OF_STRUCTURES: return ENFILE; |
| 5206 | case ERROR_ALREADY_ASSIGNED: return EEXIST; |
| 5207 | case ERROR_INVALID_PASSWORD: return EPERM; |
| 5208 | case ERROR_NET_WRITE_FAULT: return EIO; |
| 5209 | case ERROR_NO_PROC_SLOTS: return EAGAIN; |
| 5210 | case ERROR_DISK_CHANGE: return EXDEV; |
| 5211 | case ERROR_BROKEN_PIPE: return EPIPE; |
| 5212 | case ERROR_OPEN_FAILED: return ENOENT; |
| 5213 | case ERROR_DISK_FULL: return ENOSPC; |
| 5214 | case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; |
| 5215 | case ERROR_INVALID_TARGET_HANDLE: return EBADF; |
| 5216 | case ERROR_INVALID_NAME: return ENOENT; |
| 5217 | case ERROR_PROC_NOT_FOUND: return ESRCH; |
| 5218 | case ERROR_WAIT_NO_CHILDREN: return ECHILD; |
| 5219 | case ERROR_CHILD_NOT_COMPLETE: return ECHILD; |
| 5220 | case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; |
| 5221 | case ERROR_SEEK_ON_DEVICE: return ESPIPE; |
| 5222 | case ERROR_BUSY_DRIVE: return EAGAIN; |
| 5223 | case ERROR_DIR_NOT_EMPTY: return EEXIST; |
| 5224 | case ERROR_NOT_LOCKED: return EACCES; |
| 5225 | case ERROR_BAD_PATHNAME: return ENOENT; |
| 5226 | case ERROR_LOCK_FAILED: return EACCES; |
| 5227 | case ERROR_ALREADY_EXISTS: return EEXIST; |
| 5228 | case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; |
| 5229 | case ERROR_BAD_PIPE: return EPIPE; |
| 5230 | case ERROR_PIPE_BUSY: return EAGAIN; |
| 5231 | case ERROR_PIPE_NOT_CONNECTED: return EPIPE; |
| 5232 | case ERROR_DIRECTORY: return ENOTDIR; |
| 5233 | } |
| 5234 | return EINVAL; |
| 5235 | } |
| 5236 | |
| 5237 | static int JimPipe(fdtype pipefd[2]) |
| 5238 | { |
| 5239 | if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) { |
| 5240 | return 0; |
| 5241 | } |
| 5242 | return -1; |
| 5243 | } |
| 5244 | |
| 5245 | static fdtype JimDupFd(fdtype infd) |
| 5246 | { |
| 5247 | fdtype dupfd; |
| 5248 | pidtype pid = GetCurrentProcess(); |
| 5249 | |
| 5250 | if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { |
| 5251 | return dupfd; |
| 5252 | } |
| 5253 | return JIM_BAD_FD; |
| 5254 | } |
| 5255 | |
| 5256 | static int JimRewindFd(fdtype fd) |
| 5257 | { |
| 5258 | return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0; |
| 5259 | } |
| 5260 | |
| 5261 | #if 0 |
| 5262 | static int JimReadFd(fdtype fd, char *buffer, size_t len) |
| 5263 | { |
| 5264 | DWORD num; |
| 5265 | |
| 5266 | if (ReadFile(fd, buffer, len, &num, NULL)) { |
| 5267 | return num; |
| 5268 | } |
| 5269 | if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) { |
| 5270 | return 0; |
| 5271 | } |
| 5272 | return -1; |
| 5273 | } |
| 5274 | #endif |
| 5275 | |
| 5276 | static FILE *JimFdOpenForRead(fdtype fd) |
| 5277 | { |
| 5278 | return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r"); |
| 5279 | } |
| 5280 | |
| 5281 | static fdtype JimFileno(FILE *fh) |
| 5282 | { |
| 5283 | return (fdtype)_get_osfhandle(_fileno(fh)); |
| 5284 | } |
| 5285 | |
| 5286 | static fdtype JimOpenForRead(const char *filename) |
| 5287 | { |
| 5288 | return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, |
| 5289 | JimStdSecAttrs(), OPEN_EXISTING, 0, NULL); |
| 5290 | } |
| 5291 | |
| 5292 | static fdtype JimOpenForWrite(const char *filename, int append) |
| 5293 | { |
| 5294 | return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, |
| 5295 | JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL); |
| 5296 | } |
| 5297 | |
| 5298 | static FILE *JimFdOpenForWrite(fdtype fd) |
| 5299 | { |
| 5300 | return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w"); |
| 5301 | } |
| 5302 | |
| 5303 | static pidtype JimWaitPid(pidtype pid, int *status, int nohang) |
| 5304 | { |
| 5305 | DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); |
| 5306 | if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { |
| 5307 | |
| 5308 | return JIM_BAD_PID; |
| 5309 | } |
| 5310 | GetExitCodeProcess(pid, &ret); |
| 5311 | *status = ret; |
| 5312 | CloseHandle(pid); |
| 5313 | return pid; |
| 5314 | } |
| 5315 | |
| 5316 | static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len) |
| 5317 | { |
| 5318 | char name[MAX_PATH]; |
| 5319 | HANDLE handle; |
| 5320 | |
| 5321 | if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) { |
| 5322 | return JIM_BAD_FD; |
| 5323 | } |
| 5324 | |
| 5325 | handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(), |
| 5326 | CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, |
| 5327 | NULL); |
| 5328 | |
| 5329 | if (handle == INVALID_HANDLE_VALUE) { |
| 5330 | goto error; |
| 5331 | } |
| 5332 | |
| 5333 | if (contents != NULL) { |
| 5334 | |
| 5335 | FILE *fh = JimFdOpenForWrite(JimDupFd(handle)); |
| 5336 | if (fh == NULL) { |
| 5337 | goto error; |
| 5338 | } |
| 5339 | |
| 5340 | if (fwrite(contents, len, 1, fh) != 1) { |
| 5341 | fclose(fh); |
| 5342 | goto error; |
| 5343 | } |
| 5344 | fseek(fh, 0, SEEK_SET); |
| 5345 | fclose(fh); |
| 5346 | } |
| 5347 | return handle; |
| 5348 | |
| 5349 | error: |
| 5350 | Jim_SetResultErrno(interp, "failed to create temp file"); |
| 5351 | CloseHandle(handle); |
| 5352 | DeleteFile(name); |
| 5353 | return JIM_BAD_FD; |
| 5354 | } |
| 5355 | |
| 5356 | static int |
| 5357 | JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH]) |
| 5358 | { |
| 5359 | int i; |
| 5360 | static char extensions[][5] = {".exe", "", ".bat"}; |
| @@ -5381,10 +5319,15 @@ | |
| 5381 | |
| 5382 | static void JimRestoreEnv(char **env) |
| 5383 | { |
| 5384 | JimFreeEnv(env, Jim_GetEnviron()); |
| 5385 | } |
| 5386 | |
| 5387 | static Jim_Obj * |
| 5388 | JimWinBuildCommandLine(Jim_Interp *interp, char **argv) |
| 5389 | { |
| 5390 | char *start, *special; |
| @@ -5455,18 +5398,19 @@ | |
| 5455 | } |
| 5456 | return strObj; |
| 5457 | } |
| 5458 | |
| 5459 | static pidtype |
| 5460 | JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId) |
| 5461 | { |
| 5462 | STARTUPINFO startInfo; |
| 5463 | PROCESS_INFORMATION procInfo; |
| 5464 | HANDLE hProcess, h; |
| 5465 | char execPath[MAX_PATH]; |
| 5466 | pidtype pid = JIM_BAD_PID; |
| 5467 | Jim_Obj *cmdLineObj; |
| 5468 | |
| 5469 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5470 | return JIM_BAD_PID; |
| 5471 | } |
| 5472 | argv[0] = execPath; |
| @@ -5480,47 +5424,51 @@ | |
| 5480 | startInfo.dwFlags = STARTF_USESTDHANDLES; |
| 5481 | startInfo.hStdInput = INVALID_HANDLE_VALUE; |
| 5482 | startInfo.hStdOutput= INVALID_HANDLE_VALUE; |
| 5483 | startInfo.hStdError = INVALID_HANDLE_VALUE; |
| 5484 | |
| 5485 | if (inputId == JIM_BAD_FD) { |
| 5486 | if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { |
| 5487 | CloseHandle(h); |
| 5488 | } |
| 5489 | } else { |
| 5490 | DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput, |
| 5491 | 0, TRUE, DUPLICATE_SAME_ACCESS); |
| 5492 | } |
| 5493 | if (startInfo.hStdInput == JIM_BAD_FD) { |
| 5494 | goto end; |
| 5495 | } |
| 5496 | |
| 5497 | if (outputId == JIM_BAD_FD) { |
| 5498 | startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0, |
| 5499 | JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
| 5500 | } else { |
| 5501 | DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput, |
| 5502 | 0, TRUE, DUPLICATE_SAME_ACCESS); |
| 5503 | } |
| 5504 | if (startInfo.hStdOutput == JIM_BAD_FD) { |
| 5505 | goto end; |
| 5506 | } |
| 5507 | |
| 5508 | if (errorId == JIM_BAD_FD) { |
| 5509 | |
| 5510 | startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0, |
| 5511 | JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
| 5512 | } else { |
| 5513 | DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError, |
| 5514 | 0, TRUE, DUPLICATE_SAME_ACCESS); |
| 5515 | } |
| 5516 | if (startInfo.hStdError == JIM_BAD_FD) { |
| 5517 | goto end; |
| 5518 | } |
| 5519 | |
| 5520 | if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE, |
| 5521 | 0, env, NULL, &startInfo, &procInfo)) { |
| 5522 | goto end; |
| 5523 | } |
| 5524 | |
| 5525 | |
| 5526 | WaitForInputIdle(procInfo.hProcess, 5000); |
| @@ -5528,49 +5476,27 @@ | |
| 5528 | |
| 5529 | pid = procInfo.hProcess; |
| 5530 | |
| 5531 | end: |
| 5532 | Jim_FreeNewObj(interp, cmdLineObj); |
| 5533 | if (startInfo.hStdInput != JIM_BAD_FD) { |
| 5534 | CloseHandle(startInfo.hStdInput); |
| 5535 | } |
| 5536 | if (startInfo.hStdOutput != JIM_BAD_FD) { |
| 5537 | CloseHandle(startInfo.hStdOutput); |
| 5538 | } |
| 5539 | if (startInfo.hStdError != JIM_BAD_FD) { |
| 5540 | CloseHandle(startInfo.hStdError); |
| 5541 | } |
| 5542 | return pid; |
| 5543 | } |
| 5544 | #else |
| 5545 | |
| 5546 | static int JimOpenForWrite(const char *filename, int append) |
| 5547 | { |
| 5548 | return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); |
| 5549 | } |
| 5550 | |
| 5551 | static int JimRewindFd(int fd) |
| 5552 | { |
| 5553 | return lseek(fd, 0L, SEEK_SET); |
| 5554 | } |
| 5555 | |
| 5556 | static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len) |
| 5557 | { |
| 5558 | int fd = Jim_MakeTempFile(interp, NULL); |
| 5559 | |
| 5560 | if (fd != JIM_BAD_FD) { |
| 5561 | unlink(Jim_String(Jim_GetResult(interp))); |
| 5562 | if (contents) { |
| 5563 | if (write(fd, contents, len) != len) { |
| 5564 | Jim_SetResultErrno(interp, "couldn't write temp file"); |
| 5565 | close(fd); |
| 5566 | return -1; |
| 5567 | } |
| 5568 | lseek(fd, 0L, SEEK_SET); |
| 5569 | } |
| 5570 | } |
| 5571 | return fd; |
| 5572 | } |
| 5573 | |
| 5574 | static char **JimSaveEnv(char **env) |
| 5575 | { |
| 5576 | char **saveenv = Jim_GetEnviron(); |
| @@ -5585,13 +5511,21 @@ | |
| 5585 | } |
| 5586 | #endif |
| 5587 | #endif |
| 5588 | |
| 5589 | |
| 5590 | #ifndef _XOPEN_SOURCE |
| 5591 | #define _XOPEN_SOURCE 500 |
| 5592 | #endif |
| 5593 | |
| 5594 | #include <stdlib.h> |
| 5595 | #include <string.h> |
| 5596 | #include <stdio.h> |
| 5597 | #include <time.h> |
| @@ -5598,65 +5532,126 @@ | |
| 5598 | |
| 5599 | |
| 5600 | #ifdef HAVE_SYS_TIME_H |
| 5601 | #include <sys/time.h> |
| 5602 | #endif |
| 5603 | |
| 5604 | static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5605 | { |
| 5606 | |
| 5607 | char buf[100]; |
| 5608 | time_t t; |
| 5609 | long seconds; |
| 5610 | |
| 5611 | const char *format = "%a %b %d %H:%M:%S %Z %Y"; |
| 5612 | |
| 5613 | if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { |
| 5614 | return -1; |
| 5615 | } |
| 5616 | |
| 5617 | if (argc == 3) { |
| 5618 | format = Jim_String(argv[2]); |
| 5619 | } |
| 5620 | |
| 5621 | if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { |
| 5622 | return JIM_ERR; |
| 5623 | } |
| 5624 | t = seconds; |
| 5625 | |
| 5626 | if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) { |
| 5627 | Jim_SetResultString(interp, "format string too long", -1); |
| 5628 | return JIM_ERR; |
| 5629 | } |
| 5630 | |
| 5631 | Jim_SetResultString(interp, buf, -1); |
| 5632 | |
| 5633 | return JIM_OK; |
| 5634 | } |
| 5635 | |
| 5636 | #ifdef HAVE_STRPTIME |
| 5637 | static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5638 | { |
| 5639 | char *pt; |
| 5640 | struct tm tm; |
| 5641 | time_t now = time(0); |
| 5642 | |
| 5643 | if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) { |
| 5644 | return -1; |
| 5645 | } |
| 5646 | |
| 5647 | |
| 5648 | localtime_r(&now, &tm); |
| 5649 | |
| 5650 | pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm); |
| 5651 | if (pt == 0 || *pt != 0) { |
| 5652 | Jim_SetResultString(interp, "Failed to parse time according to format", -1); |
| 5653 | return JIM_ERR; |
| 5654 | } |
| 5655 | |
| 5656 | |
| 5657 | Jim_SetResultInt(interp, mktime(&tm)); |
| 5658 | |
| 5659 | return JIM_OK; |
| 5660 | } |
| 5661 | #endif |
| 5662 | |
| @@ -5688,54 +5683,54 @@ | |
| 5688 | |
| 5689 | return JIM_OK; |
| 5690 | } |
| 5691 | |
| 5692 | static const jim_subcmd_type clock_command_table[] = { |
| 5693 | { "seconds", |
| 5694 | NULL, |
| 5695 | clock_cmd_seconds, |
| 5696 | 0, |
| 5697 | 0, |
| 5698 | |
| 5699 | }, |
| 5700 | { "clicks", |
| 5701 | NULL, |
| 5702 | clock_cmd_micros, |
| 5703 | 0, |
| 5704 | 0, |
| 5705 | |
| 5706 | }, |
| 5707 | { "microseconds", |
| 5708 | NULL, |
| 5709 | clock_cmd_micros, |
| 5710 | 0, |
| 5711 | 0, |
| 5712 | |
| 5713 | }, |
| 5714 | { "milliseconds", |
| 5715 | NULL, |
| 5716 | clock_cmd_millis, |
| 5717 | 0, |
| 5718 | 0, |
| 5719 | |
| 5720 | }, |
| 5721 | { "format", |
| 5722 | "seconds ?-format format?", |
| 5723 | clock_cmd_format, |
| 5724 | 1, |
| 5725 | 3, |
| 5726 | |
| 5727 | }, |
| 5728 | #ifdef HAVE_STRPTIME |
| 5729 | { "scan", |
| 5730 | "str -format format", |
| 5731 | clock_cmd_scan, |
| 5732 | 3, |
| 5733 | 3, |
| 5734 | |
| 5735 | }, |
| 5736 | #endif |
| 5737 | { NULL } |
| 5738 | }; |
| 5739 | |
| 5740 | int Jim_clockInit(Jim_Interp *interp) |
| 5741 | { |
| @@ -5753,12 +5748,13 @@ | |
| 5753 | #include <errno.h> |
| 5754 | |
| 5755 | |
| 5756 | static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5757 | { |
| 5758 | |
| 5759 | Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0); |
| 5760 | return JIM_OK; |
| 5761 | } |
| 5762 | |
| 5763 | static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5764 | { |
| @@ -5769,21 +5765,20 @@ | |
| 5769 | return JIM_OK; |
| 5770 | } |
| 5771 | |
| 5772 | patternObj = (argc == 1) ? NULL : argv[1]; |
| 5773 | |
| 5774 | |
| 5775 | if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { |
| 5776 | if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { |
| 5777 | |
| 5778 | Jim_SetResult(interp, objPtr); |
| 5779 | return JIM_OK; |
| 5780 | } |
| 5781 | } |
| 5782 | |
| 5783 | |
| 5784 | return Jim_DictValues(interp, objPtr, patternObj); |
| 5785 | } |
| 5786 | |
| 5787 | static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5788 | { |
| 5789 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| @@ -5790,11 +5785,11 @@ | |
| 5790 | |
| 5791 | if (!objPtr) { |
| 5792 | return JIM_OK; |
| 5793 | } |
| 5794 | |
| 5795 | return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]); |
| 5796 | } |
| 5797 | |
| 5798 | static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5799 | { |
| 5800 | int i; |
| @@ -5802,27 +5797,29 @@ | |
| 5802 | Jim_Obj *resultObj; |
| 5803 | Jim_Obj *objPtr; |
| 5804 | Jim_Obj **dictValuesObj; |
| 5805 | |
| 5806 | if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { |
| 5807 | |
| 5808 | Jim_UnsetVariable(interp, argv[0], JIM_NONE); |
| 5809 | return JIM_OK; |
| 5810 | } |
| 5811 | |
| 5812 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5813 | |
| 5814 | if (objPtr == NULL) { |
| 5815 | |
| 5816 | return JIM_OK; |
| 5817 | } |
| 5818 | |
| 5819 | if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 5820 | return JIM_ERR; |
| 5821 | } |
| 5822 | |
| 5823 | |
| 5824 | resultObj = Jim_NewDictObj(interp, NULL, 0); |
| 5825 | |
| 5826 | for (i = 0; i < len; i += 2) { |
| 5827 | if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { |
| 5828 | Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); |
| @@ -5837,16 +5834,18 @@ | |
| 5837 | static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5838 | { |
| 5839 | Jim_Obj *objPtr; |
| 5840 | int len = 0; |
| 5841 | |
| 5842 | |
| 5843 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5844 | if (objPtr) { |
| 5845 | len = Jim_DictSize(interp, objPtr); |
| 5846 | if (len < 0) { |
| 5847 | return JIM_ERR; |
| 5848 | } |
| 5849 | } |
| 5850 | |
| 5851 | Jim_SetResultInt(interp, len); |
| 5852 | |
| @@ -5876,11 +5875,11 @@ | |
| 5876 | return JIM_ERR; |
| 5877 | } |
| 5878 | |
| 5879 | dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5880 | if (!dictObj) { |
| 5881 | |
| 5882 | return Jim_SetVariable(interp, argv[0], listObj); |
| 5883 | } |
| 5884 | else if (Jim_DictSize(interp, dictObj) < 0) { |
| 5885 | return JIM_ERR; |
| 5886 | } |
| @@ -5905,53 +5904,53 @@ | |
| 5905 | { "exists", |
| 5906 | "arrayName", |
| 5907 | array_cmd_exists, |
| 5908 | 1, |
| 5909 | 1, |
| 5910 | |
| 5911 | }, |
| 5912 | { "get", |
| 5913 | "arrayName ?pattern?", |
| 5914 | array_cmd_get, |
| 5915 | 1, |
| 5916 | 2, |
| 5917 | |
| 5918 | }, |
| 5919 | { "names", |
| 5920 | "arrayName ?pattern?", |
| 5921 | array_cmd_names, |
| 5922 | 1, |
| 5923 | 2, |
| 5924 | |
| 5925 | }, |
| 5926 | { "set", |
| 5927 | "arrayName list", |
| 5928 | array_cmd_set, |
| 5929 | 2, |
| 5930 | 2, |
| 5931 | |
| 5932 | }, |
| 5933 | { "size", |
| 5934 | "arrayName", |
| 5935 | array_cmd_size, |
| 5936 | 1, |
| 5937 | 1, |
| 5938 | |
| 5939 | }, |
| 5940 | { "stat", |
| 5941 | "arrayName", |
| 5942 | array_cmd_stat, |
| 5943 | 1, |
| 5944 | 1, |
| 5945 | |
| 5946 | }, |
| 5947 | { "unset", |
| 5948 | "arrayName ?pattern?", |
| 5949 | array_cmd_unset, |
| 5950 | 1, |
| 5951 | 2, |
| 5952 | |
| 5953 | }, |
| 5954 | { NULL |
| 5955 | } |
| 5956 | }; |
| 5957 | |
| @@ -5987,11 +5986,14 @@ | |
| 5987 | Jim_arrayInit(interp); |
| 5988 | Jim_stdlibInit(interp); |
| 5989 | Jim_tclcompatInit(interp); |
| 5990 | return JIM_OK; |
| 5991 | } |
| 5992 | #define JIM_OPTIMIZATION |
| 5993 | |
| 5994 | #include <stdio.h> |
| 5995 | #include <stdlib.h> |
| 5996 | |
| 5997 | #include <string.h> |
| @@ -6056,10 +6058,16 @@ | |
| 6056 | #define JimPanic(X) JimPanicDump X |
| 6057 | #else |
| 6058 | #define JimPanic(X) |
| 6059 | #endif |
| 6060 | |
| 6061 | |
| 6062 | static char JimEmptyStringRep[] = ""; |
| 6063 | |
| 6064 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); |
| 6065 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| @@ -6112,34 +6120,34 @@ | |
| 6112 | if (*pattern == '^') { |
| 6113 | not++; |
| 6114 | pattern++; |
| 6115 | } |
| 6116 | |
| 6117 | |
| 6118 | if (*pattern == ']') { |
| 6119 | goto first; |
| 6120 | } |
| 6121 | } |
| 6122 | |
| 6123 | while (*pattern && *pattern != ']') { |
| 6124 | |
| 6125 | if (pattern[0] == '\\') { |
| 6126 | first: |
| 6127 | pattern += utf8_tounicode_case(pattern, &pchar, nocase); |
| 6128 | } |
| 6129 | else { |
| 6130 | |
| 6131 | int start; |
| 6132 | int end; |
| 6133 | |
| 6134 | pattern += utf8_tounicode_case(pattern, &start, nocase); |
| 6135 | if (pattern[0] == '-' && pattern[1]) { |
| 6136 | |
| 6137 | pattern += utf8_tounicode(pattern, &pchar); |
| 6138 | pattern += utf8_tounicode_case(pattern, &end, nocase); |
| 6139 | |
| 6140 | |
| 6141 | if ((c >= start && c <= end) || (c >= end && c <= start)) { |
| 6142 | match = 1; |
| 6143 | } |
| 6144 | continue; |
| 6145 | } |
| @@ -6169,19 +6177,19 @@ | |
| 6169 | while (pattern[1] == '*') { |
| 6170 | pattern++; |
| 6171 | } |
| 6172 | pattern++; |
| 6173 | if (!pattern[0]) { |
| 6174 | return 1; |
| 6175 | } |
| 6176 | while (*string) { |
| 6177 | |
| 6178 | if (JimGlobMatch(pattern, string, nocase)) |
| 6179 | return 1; |
| 6180 | string += utf8_tounicode(string, &c); |
| 6181 | } |
| 6182 | return 0; |
| 6183 | |
| 6184 | case '?': |
| 6185 | string += utf8_tounicode(string, &c); |
| 6186 | break; |
| 6187 | |
| @@ -6190,20 +6198,20 @@ | |
| 6190 | pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); |
| 6191 | if (!pattern) { |
| 6192 | return 0; |
| 6193 | } |
| 6194 | if (!*pattern) { |
| 6195 | |
| 6196 | continue; |
| 6197 | } |
| 6198 | break; |
| 6199 | } |
| 6200 | case '\\': |
| 6201 | if (pattern[1]) { |
| 6202 | pattern++; |
| 6203 | } |
| 6204 | |
| 6205 | default: |
| 6206 | string += utf8_tounicode_case(string, &c, nocase); |
| 6207 | utf8_tounicode_case(pattern, &pchar, nocase); |
| 6208 | if (pchar != c) { |
| 6209 | return 0; |
| @@ -6249,11 +6257,11 @@ | |
| 6249 | maxchars--; |
| 6250 | } |
| 6251 | if (!maxchars) { |
| 6252 | return 0; |
| 6253 | } |
| 6254 | |
| 6255 | if (*s1) { |
| 6256 | return 1; |
| 6257 | } |
| 6258 | if (*s2) { |
| 6259 | return -1; |
| @@ -6290,11 +6298,11 @@ | |
| 6290 | const char *p; |
| 6291 | |
| 6292 | if (!l1 || !l2 || l1 > l2) |
| 6293 | return -1; |
| 6294 | |
| 6295 | |
| 6296 | for (p = s2 + l2 - 1; p != s2 - 1; p--) { |
| 6297 | if (*p == *s1 && memcmp(s1, p, l1) == 0) { |
| 6298 | return p - s2; |
| 6299 | } |
| 6300 | } |
| @@ -6349,28 +6357,28 @@ | |
| 6349 | } |
| 6350 | *sign = 1; |
| 6351 | } |
| 6352 | |
| 6353 | if (str[i] != '0') { |
| 6354 | |
| 6355 | return 0; |
| 6356 | } |
| 6357 | |
| 6358 | |
| 6359 | switch (str[i + 1]) { |
| 6360 | case 'x': case 'X': *base = 16; break; |
| 6361 | case 'o': case 'O': *base = 8; break; |
| 6362 | case 'b': case 'B': *base = 2; break; |
| 6363 | default: return 0; |
| 6364 | } |
| 6365 | i += 2; |
| 6366 | |
| 6367 | if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) { |
| 6368 | |
| 6369 | return i; |
| 6370 | } |
| 6371 | |
| 6372 | *base = 10; |
| 6373 | return 0; |
| 6374 | } |
| 6375 | |
| 6376 | static long jim_strtol(const char *str, char **endptr) |
| @@ -6384,11 +6392,11 @@ | |
| 6384 | if (endptr == NULL || *endptr != str + i) { |
| 6385 | return value * sign; |
| 6386 | } |
| 6387 | } |
| 6388 | |
| 6389 | |
| 6390 | return strtol(str, endptr, 10); |
| 6391 | } |
| 6392 | |
| 6393 | |
| 6394 | static jim_wide jim_strtoull(const char *str, char **endptr) |
| @@ -6403,11 +6411,11 @@ | |
| 6403 | if (endptr == NULL || *endptr != str + i) { |
| 6404 | return value * sign; |
| 6405 | } |
| 6406 | } |
| 6407 | |
| 6408 | |
| 6409 | return strtoull(str, endptr, 10); |
| 6410 | #else |
| 6411 | return (unsigned long)jim_strtol(str, endptr); |
| 6412 | #endif |
| 6413 | } |
| @@ -6428,26 +6436,40 @@ | |
| 6428 | |
| 6429 | int Jim_StringToDouble(const char *str, double *doublePtr) |
| 6430 | { |
| 6431 | char *endptr; |
| 6432 | |
| 6433 | |
| 6434 | errno = 0; |
| 6435 | |
| 6436 | *doublePtr = strtod(str, &endptr); |
| 6437 | |
| 6438 | return JimCheckConversion(str, endptr); |
| 6439 | } |
| 6440 | |
| 6441 | static jim_wide JimPowWide(jim_wide b, jim_wide e) |
| 6442 | { |
| 6443 | jim_wide i, res = 1; |
| 6444 | |
| 6445 | if ((b == 0 && e != 0) || (e < 0)) |
| 6446 | return 0; |
| 6447 | for (i = 0; i < e; i++) { |
| 6448 | res *= b; |
| 6449 | } |
| 6450 | return res; |
| 6451 | } |
| 6452 | |
| 6453 | #ifdef JIM_DEBUG_PANIC |
| @@ -6509,11 +6531,11 @@ | |
| 6509 | char *Jim_StrDupLen(const char *s, int l) |
| 6510 | { |
| 6511 | char *copy = Jim_Alloc(l + 1); |
| 6512 | |
| 6513 | memcpy(copy, s, l + 1); |
| 6514 | copy[l] = 0; |
| 6515 | return copy; |
| 6516 | } |
| 6517 | |
| 6518 | |
| 6519 | |
| @@ -6598,52 +6620,52 @@ | |
| 6598 | } |
| 6599 | |
| 6600 | |
| 6601 | void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) |
| 6602 | { |
| 6603 | Jim_HashTable n; |
| 6604 | unsigned int realsize = JimHashTableNextPower(size), i; |
| 6605 | |
| 6606 | if (size <= ht->used) |
| 6607 | return; |
| 6608 | |
| 6609 | Jim_InitHashTable(&n, ht->type, ht->privdata); |
| 6610 | n.size = realsize; |
| 6611 | n.sizemask = realsize - 1; |
| 6612 | n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); |
| 6613 | |
| 6614 | n.uniq = ht->uniq; |
| 6615 | |
| 6616 | |
| 6617 | memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); |
| 6618 | |
| 6619 | n.used = ht->used; |
| 6620 | for (i = 0; ht->used > 0; i++) { |
| 6621 | Jim_HashEntry *he, *nextHe; |
| 6622 | |
| 6623 | if (ht->table[i] == NULL) |
| 6624 | continue; |
| 6625 | |
| 6626 | |
| 6627 | he = ht->table[i]; |
| 6628 | while (he) { |
| 6629 | unsigned int h; |
| 6630 | |
| 6631 | nextHe = he->next; |
| 6632 | |
| 6633 | h = Jim_HashKey(ht, he->key) & n.sizemask; |
| 6634 | he->next = n.table[h]; |
| 6635 | n.table[h] = he; |
| 6636 | ht->used--; |
| 6637 | |
| 6638 | he = nextHe; |
| 6639 | } |
| 6640 | } |
| 6641 | assert(ht->used == 0); |
| 6642 | Jim_Free(ht->table); |
| 6643 | |
| 6644 | |
| 6645 | *ht = n; |
| 6646 | } |
| 6647 | |
| 6648 | |
| 6649 | int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) |
| @@ -6652,11 +6674,11 @@ | |
| 6652 | |
| 6653 | entry = JimInsertHashEntry(ht, key, 0); |
| 6654 | if (entry == NULL) |
| 6655 | return JIM_ERR; |
| 6656 | |
| 6657 | |
| 6658 | Jim_SetHashKey(ht, entry, key); |
| 6659 | Jim_SetHashVal(ht, entry, val); |
| 6660 | return JIM_OK; |
| 6661 | } |
| 6662 | |
| @@ -6678,11 +6700,11 @@ | |
| 6678 | Jim_SetHashVal(ht, entry, val); |
| 6679 | } |
| 6680 | existed = 1; |
| 6681 | } |
| 6682 | else { |
| 6683 | |
| 6684 | Jim_SetHashKey(ht, entry, key); |
| 6685 | Jim_SetHashVal(ht, entry, val); |
| 6686 | existed = 0; |
| 6687 | } |
| 6688 | |
| @@ -6701,11 +6723,11 @@ | |
| 6701 | he = ht->table[h]; |
| 6702 | |
| 6703 | prevHe = NULL; |
| 6704 | while (he) { |
| 6705 | if (Jim_CompareHashKeys(ht, key, he->key)) { |
| 6706 | |
| 6707 | if (prevHe) |
| 6708 | prevHe->next = he->next; |
| 6709 | else |
| 6710 | ht->table[h] = he->next; |
| 6711 | Jim_FreeEntryKey(ht, he); |
| @@ -6715,19 +6737,19 @@ | |
| 6715 | return JIM_OK; |
| 6716 | } |
| 6717 | prevHe = he; |
| 6718 | he = he->next; |
| 6719 | } |
| 6720 | return JIM_ERR; |
| 6721 | } |
| 6722 | |
| 6723 | |
| 6724 | int Jim_FreeHashTable(Jim_HashTable *ht) |
| 6725 | { |
| 6726 | unsigned int i; |
| 6727 | |
| 6728 | |
| 6729 | for (i = 0; ht->used > 0; i++) { |
| 6730 | Jim_HashEntry *he, *nextHe; |
| 6731 | |
| 6732 | if ((he = ht->table[i]) == NULL) |
| 6733 | continue; |
| @@ -6738,15 +6760,15 @@ | |
| 6738 | Jim_Free(he); |
| 6739 | ht->used--; |
| 6740 | he = nextHe; |
| 6741 | } |
| 6742 | } |
| 6743 | |
| 6744 | Jim_Free(ht->table); |
| 6745 | |
| 6746 | JimResetHashTable(ht); |
| 6747 | return JIM_OK; |
| 6748 | } |
| 6749 | |
| 6750 | Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key) |
| 6751 | { |
| 6752 | Jim_HashEntry *he; |
| @@ -6819,24 +6841,24 @@ | |
| 6819 | static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace) |
| 6820 | { |
| 6821 | unsigned int h; |
| 6822 | Jim_HashEntry *he; |
| 6823 | |
| 6824 | |
| 6825 | JimExpandHashTableIfNeeded(ht); |
| 6826 | |
| 6827 | |
| 6828 | h = Jim_HashKey(ht, key) & ht->sizemask; |
| 6829 | |
| 6830 | he = ht->table[h]; |
| 6831 | while (he) { |
| 6832 | if (Jim_CompareHashKeys(ht, key, he->key)) |
| 6833 | return replace ? he : NULL; |
| 6834 | he = he->next; |
| 6835 | } |
| 6836 | |
| 6837 | |
| 6838 | he = Jim_Alloc(sizeof(*he)); |
| 6839 | he->next = ht->table[h]; |
| 6840 | ht->table[h] = he; |
| 6841 | ht->used++; |
| 6842 | he->key = NULL; |
| @@ -6865,16 +6887,16 @@ | |
| 6865 | { |
| 6866 | Jim_Free(key); |
| 6867 | } |
| 6868 | |
| 6869 | static const Jim_HashTableType JimPackageHashTableType = { |
| 6870 | JimStringCopyHTHashFunction, |
| 6871 | JimStringCopyHTDup, |
| 6872 | NULL, |
| 6873 | JimStringCopyHTKeyCompare, |
| 6874 | JimStringCopyHTKeyDestructor, |
| 6875 | NULL |
| 6876 | }; |
| 6877 | |
| 6878 | typedef struct AssocDataValue |
| 6879 | { |
| 6880 | Jim_InterpDeleteProc *delProc; |
| @@ -6889,16 +6911,16 @@ | |
| 6889 | assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data); |
| 6890 | Jim_Free(data); |
| 6891 | } |
| 6892 | |
| 6893 | static const Jim_HashTableType JimAssocDataHashTableType = { |
| 6894 | JimStringCopyHTHashFunction, |
| 6895 | JimStringCopyHTDup, |
| 6896 | NULL, |
| 6897 | JimStringCopyHTKeyCompare, |
| 6898 | JimStringCopyHTKeyDestructor, |
| 6899 | JimAssocDataHashTableValueDestructor |
| 6900 | }; |
| 6901 | |
| 6902 | void Jim_InitStack(Jim_Stack *stack) |
| 6903 | { |
| 6904 | stack->len = 0; |
| @@ -6951,56 +6973,61 @@ | |
| 6951 | freeFunc(stack->vector[i]); |
| 6952 | } |
| 6953 | |
| 6954 | |
| 6955 | |
| 6956 | #define JIM_TT_NONE 0 |
| 6957 | #define JIM_TT_STR 1 |
| 6958 | #define JIM_TT_ESC 2 |
| 6959 | #define JIM_TT_VAR 3 |
| 6960 | #define JIM_TT_DICTSUGAR 4 |
| 6961 | #define JIM_TT_CMD 5 |
| 6962 | |
| 6963 | #define JIM_TT_SEP 6 |
| 6964 | #define JIM_TT_EOL 7 |
| 6965 | #define JIM_TT_EOF 8 |
| 6966 | |
| 6967 | #define JIM_TT_LINE 9 |
| 6968 | #define JIM_TT_WORD 10 |
| 6969 | |
| 6970 | |
| 6971 | #define JIM_TT_SUBEXPR_START 11 |
| 6972 | #define JIM_TT_SUBEXPR_END 12 |
| 6973 | #define JIM_TT_SUBEXPR_COMMA 13 |
| 6974 | #define JIM_TT_EXPR_INT 14 |
| 6975 | #define JIM_TT_EXPR_DOUBLE 15 |
| 6976 | |
| 6977 | #define JIM_TT_EXPRSUGAR 16 |
| 6978 | |
| 6979 | |
| 6980 | #define JIM_TT_EXPR_OP 20 |
| 6981 | |
| 6982 | #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF) |
| 6983 | |
| 6984 | struct JimParseMissing { |
| 6985 | int ch; |
| 6986 | int line; |
| 6987 | }; |
| 6988 | |
| 6989 | struct JimParserCtx |
| 6990 | { |
| 6991 | const char *p; |
| 6992 | int len; |
| 6993 | int linenr; |
| 6994 | const char *tstart; |
| 6995 | const char *tend; |
| 6996 | int tline; |
| 6997 | int tt; |
| 6998 | int eof; |
| 6999 | int inquote; |
| 7000 | int comment; |
| 7001 | struct JimParseMissing missing; |
| 7002 | }; |
| 7003 | |
| 7004 | static int JimParseScript(struct JimParserCtx *pc); |
| 7005 | static int JimParseSep(struct JimParserCtx *pc); |
| 7006 | static int JimParseEol(struct JimParserCtx *pc); |
| @@ -7030,11 +7057,11 @@ | |
| 7030 | pc->missing.line = linenr; |
| 7031 | } |
| 7032 | |
| 7033 | static int JimParseScript(struct JimParserCtx *pc) |
| 7034 | { |
| 7035 | while (1) { |
| 7036 | if (!pc->len) { |
| 7037 | pc->tstart = pc->p; |
| 7038 | pc->tend = pc->p - 1; |
| 7039 | pc->tline = pc->linenr; |
| 7040 | pc->tt = JIM_TT_EOL; |
| @@ -7066,11 +7093,11 @@ | |
| 7066 | pc->comment = 0; |
| 7067 | return JimParseCmd(pc); |
| 7068 | case '$': |
| 7069 | pc->comment = 0; |
| 7070 | if (JimParseVar(pc) == JIM_ERR) { |
| 7071 | |
| 7072 | pc->tstart = pc->tend = pc->p++; |
| 7073 | pc->len--; |
| 7074 | pc->tt = JIM_TT_ESC; |
| 7075 | } |
| 7076 | return JIM_OK; |
| @@ -7127,11 +7154,11 @@ | |
| 7127 | |
| 7128 | static void JimParseSubBrace(struct JimParserCtx *pc) |
| 7129 | { |
| 7130 | int level = 1; |
| 7131 | |
| 7132 | |
| 7133 | pc->p++; |
| 7134 | pc->len--; |
| 7135 | while (pc->len) { |
| 7136 | switch (*pc->p) { |
| 7137 | case '\\': |
| @@ -7171,11 +7198,11 @@ | |
| 7171 | static int JimParseSubQuote(struct JimParserCtx *pc) |
| 7172 | { |
| 7173 | int tt = JIM_TT_STR; |
| 7174 | int line = pc->tline; |
| 7175 | |
| 7176 | |
| 7177 | pc->p++; |
| 7178 | pc->len--; |
| 7179 | while (pc->len) { |
| 7180 | switch (*pc->p) { |
| 7181 | case '\\': |
| @@ -7220,11 +7247,11 @@ | |
| 7220 | { |
| 7221 | int level = 1; |
| 7222 | int startofword = 1; |
| 7223 | int line = pc->tline; |
| 7224 | |
| 7225 | |
| 7226 | pc->p++; |
| 7227 | pc->len--; |
| 7228 | while (pc->len) { |
| 7229 | switch (*pc->p) { |
| 7230 | case '\\': |
| @@ -7300,17 +7327,17 @@ | |
| 7300 | return JIM_OK; |
| 7301 | } |
| 7302 | |
| 7303 | static int JimParseVar(struct JimParserCtx *pc) |
| 7304 | { |
| 7305 | |
| 7306 | pc->p++; |
| 7307 | pc->len--; |
| 7308 | |
| 7309 | #ifdef EXPRSUGAR_BRACKET |
| 7310 | if (*pc->p == '[') { |
| 7311 | |
| 7312 | JimParseCmd(pc); |
| 7313 | pc->tt = JIM_TT_EXPRSUGAR; |
| 7314 | return JIM_OK; |
| 7315 | } |
| 7316 | #endif |
| @@ -7336,11 +7363,11 @@ | |
| 7336 | pc->len--; |
| 7337 | } |
| 7338 | } |
| 7339 | else { |
| 7340 | while (1) { |
| 7341 | |
| 7342 | if (pc->p[0] == ':' && pc->p[1] == ':') { |
| 7343 | while (*pc->p == ':') { |
| 7344 | pc->p++; |
| 7345 | pc->len--; |
| 7346 | } |
| @@ -7351,11 +7378,11 @@ | |
| 7351 | pc->len--; |
| 7352 | continue; |
| 7353 | } |
| 7354 | break; |
| 7355 | } |
| 7356 | |
| 7357 | if (*pc->p == '(') { |
| 7358 | int count = 1; |
| 7359 | const char *paren = NULL; |
| 7360 | |
| 7361 | pc->tt = JIM_TT_DICTSUGAR; |
| @@ -7378,11 +7405,11 @@ | |
| 7378 | if (count == 0) { |
| 7379 | pc->p++; |
| 7380 | pc->len--; |
| 7381 | } |
| 7382 | else if (paren) { |
| 7383 | |
| 7384 | paren++; |
| 7385 | pc->len += (pc->p - paren); |
| 7386 | pc->p = paren; |
| 7387 | } |
| 7388 | #ifndef EXPRSUGAR_BRACKET |
| @@ -7403,19 +7430,19 @@ | |
| 7403 | |
| 7404 | static int JimParseStr(struct JimParserCtx *pc) |
| 7405 | { |
| 7406 | if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL || |
| 7407 | pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) { |
| 7408 | |
| 7409 | if (*pc->p == '{') { |
| 7410 | return JimParseBrace(pc); |
| 7411 | } |
| 7412 | if (*pc->p == '"') { |
| 7413 | pc->inquote = 1; |
| 7414 | pc->p++; |
| 7415 | pc->len--; |
| 7416 | |
| 7417 | pc->missing.line = pc->tline; |
| 7418 | } |
| 7419 | } |
| 7420 | pc->tstart = pc->p; |
| 7421 | pc->tline = pc->linenr; |
| @@ -7441,25 +7468,25 @@ | |
| 7441 | } |
| 7442 | pc->p++; |
| 7443 | pc->len--; |
| 7444 | } |
| 7445 | else if (pc->len == 1) { |
| 7446 | |
| 7447 | pc->missing.ch = '\\'; |
| 7448 | } |
| 7449 | break; |
| 7450 | case '(': |
| 7451 | |
| 7452 | if (pc->len > 1 && pc->p[1] != '$') { |
| 7453 | break; |
| 7454 | } |
| 7455 | |
| 7456 | case ')': |
| 7457 | |
| 7458 | if (*pc->p == '(' || pc->tt == JIM_TT_VAR) { |
| 7459 | if (pc->p == pc->tstart) { |
| 7460 | |
| 7461 | pc->p++; |
| 7462 | pc->len--; |
| 7463 | } |
| 7464 | pc->tend = pc->p - 1; |
| 7465 | pc->tt = JIM_TT_ESC; |
| @@ -7499,11 +7526,11 @@ | |
| 7499 | break; |
| 7500 | } |
| 7501 | pc->p++; |
| 7502 | pc->len--; |
| 7503 | } |
| 7504 | return JIM_OK; |
| 7505 | } |
| 7506 | |
| 7507 | static int JimParseComment(struct JimParserCtx *pc) |
| 7508 | { |
| 7509 | while (*pc->p) { |
| @@ -7610,34 +7637,34 @@ | |
| 7610 | if (c == -1) { |
| 7611 | break; |
| 7612 | } |
| 7613 | val = (val << 4) | c; |
| 7614 | } |
| 7615 | |
| 7616 | if (s[i] == '{') { |
| 7617 | if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') { |
| 7618 | |
| 7619 | i--; |
| 7620 | k = 0; |
| 7621 | } |
| 7622 | else { |
| 7623 | |
| 7624 | k++; |
| 7625 | } |
| 7626 | } |
| 7627 | if (k) { |
| 7628 | |
| 7629 | if (s[i] == 'x') { |
| 7630 | *p++ = val; |
| 7631 | } |
| 7632 | else { |
| 7633 | p += utf8_fromunicode(p, val); |
| 7634 | } |
| 7635 | i += k; |
| 7636 | break; |
| 7637 | } |
| 7638 | |
| 7639 | *p++ = s[i]; |
| 7640 | } |
| 7641 | break; |
| 7642 | case 'v': |
| 7643 | *p++ = 0xb; |
| @@ -7646,11 +7673,11 @@ | |
| 7646 | case '\0': |
| 7647 | *p++ = '\\'; |
| 7648 | i++; |
| 7649 | break; |
| 7650 | case '\n': |
| 7651 | |
| 7652 | *p++ = ' '; |
| 7653 | do { |
| 7654 | i++; |
| 7655 | } while (s[i + 1] == ' ' || s[i + 1] == '\t'); |
| 7656 | break; |
| @@ -7660,11 +7687,11 @@ | |
| 7660 | case '3': |
| 7661 | case '4': |
| 7662 | case '5': |
| 7663 | case '6': |
| 7664 | case '7': |
| 7665 | |
| 7666 | { |
| 7667 | int val = 0; |
| 7668 | int c = odigitval(s[i + 1]); |
| 7669 | |
| 7670 | val = c; |
| @@ -7708,27 +7735,23 @@ | |
| 7708 | char *token; |
| 7709 | int len; |
| 7710 | |
| 7711 | start = pc->tstart; |
| 7712 | end = pc->tend; |
| 7713 | if (start > end) { |
| 7714 | len = 0; |
| 7715 | token = Jim_Alloc(1); |
| 7716 | token[0] = '\0'; |
| 7717 | } |
| 7718 | else { |
| 7719 | len = (end - start) + 1; |
| 7720 | token = Jim_Alloc(len + 1); |
| 7721 | if (pc->tt != JIM_TT_ESC) { |
| 7722 | |
| 7723 | memcpy(token, start, len); |
| 7724 | token[len] = '\0'; |
| 7725 | } |
| 7726 | else { |
| 7727 | |
| 7728 | len = JimEscape(token, start, len); |
| 7729 | } |
| 7730 | } |
| 7731 | |
| 7732 | return Jim_NewStringObjNoAlloc(interp, token, len); |
| 7733 | } |
| 7734 | |
| @@ -7790,11 +7813,11 @@ | |
| 7790 | while (pc->len) { |
| 7791 | switch (*pc->p) { |
| 7792 | case '\\': |
| 7793 | pc->tt = JIM_TT_ESC; |
| 7794 | if (--pc->len == 0) { |
| 7795 | |
| 7796 | pc->tend = pc->p; |
| 7797 | return JIM_OK; |
| 7798 | } |
| 7799 | pc->p++; |
| 7800 | break; |
| @@ -7826,11 +7849,11 @@ | |
| 7826 | pc->tend = pc->p - 1; |
| 7827 | return JIM_OK; |
| 7828 | } |
| 7829 | if (*pc->p == '\\') { |
| 7830 | if (--pc->len == 0) { |
| 7831 | |
| 7832 | pc->tend = pc->p; |
| 7833 | return JIM_OK; |
| 7834 | } |
| 7835 | pc->tt = JIM_TT_ESC; |
| 7836 | pc->p++; |
| @@ -7846,24 +7869,24 @@ | |
| 7846 | |
| 7847 | Jim_Obj *Jim_NewObj(Jim_Interp *interp) |
| 7848 | { |
| 7849 | Jim_Obj *objPtr; |
| 7850 | |
| 7851 | |
| 7852 | if (interp->freeList != NULL) { |
| 7853 | |
| 7854 | objPtr = interp->freeList; |
| 7855 | interp->freeList = objPtr->nextObjPtr; |
| 7856 | } |
| 7857 | else { |
| 7858 | |
| 7859 | objPtr = Jim_Alloc(sizeof(*objPtr)); |
| 7860 | } |
| 7861 | |
| 7862 | objPtr->refCount = 0; |
| 7863 | |
| 7864 | |
| 7865 | objPtr->prevObjPtr = NULL; |
| 7866 | objPtr->nextObjPtr = interp->liveList; |
| 7867 | if (interp->liveList) |
| 7868 | interp->liveList->prevObjPtr = objPtr; |
| 7869 | interp->liveList = objPtr; |
| @@ -7871,32 +7894,32 @@ | |
| 7871 | return objPtr; |
| 7872 | } |
| 7873 | |
| 7874 | void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr) |
| 7875 | { |
| 7876 | |
| 7877 | JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr, |
| 7878 | objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>")); |
| 7879 | |
| 7880 | |
| 7881 | Jim_FreeIntRep(interp, objPtr); |
| 7882 | |
| 7883 | if (objPtr->bytes != NULL) { |
| 7884 | if (objPtr->bytes != JimEmptyStringRep) |
| 7885 | Jim_Free(objPtr->bytes); |
| 7886 | } |
| 7887 | |
| 7888 | if (objPtr->prevObjPtr) |
| 7889 | objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; |
| 7890 | if (objPtr->nextObjPtr) |
| 7891 | objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; |
| 7892 | if (interp->liveList == objPtr) |
| 7893 | interp->liveList = objPtr->nextObjPtr; |
| 7894 | #ifdef JIM_DISABLE_OBJECT_POOL |
| 7895 | Jim_Free(objPtr); |
| 7896 | #else |
| 7897 | |
| 7898 | objPtr->prevObjPtr = NULL; |
| 7899 | objPtr->nextObjPtr = interp->freeList; |
| 7900 | if (interp->freeList) |
| 7901 | interp->freeList->prevObjPtr = objPtr; |
| 7902 | interp->freeList = objPtr; |
| @@ -7919,45 +7942,44 @@ | |
| 7919 | { |
| 7920 | Jim_Obj *dupPtr; |
| 7921 | |
| 7922 | dupPtr = Jim_NewObj(interp); |
| 7923 | if (objPtr->bytes == NULL) { |
| 7924 | |
| 7925 | dupPtr->bytes = NULL; |
| 7926 | } |
| 7927 | else if (objPtr->length == 0) { |
| 7928 | |
| 7929 | dupPtr->bytes = JimEmptyStringRep; |
| 7930 | dupPtr->length = 0; |
| 7931 | dupPtr->typePtr = NULL; |
| 7932 | return dupPtr; |
| 7933 | } |
| 7934 | else { |
| 7935 | dupPtr->bytes = Jim_Alloc(objPtr->length + 1); |
| 7936 | dupPtr->length = objPtr->length; |
| 7937 | |
| 7938 | memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1); |
| 7939 | } |
| 7940 | |
| 7941 | |
| 7942 | dupPtr->typePtr = objPtr->typePtr; |
| 7943 | if (objPtr->typePtr != NULL) { |
| 7944 | if (objPtr->typePtr->dupIntRepProc == NULL) { |
| 7945 | dupPtr->internalRep = objPtr->internalRep; |
| 7946 | } |
| 7947 | else { |
| 7948 | |
| 7949 | objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr); |
| 7950 | } |
| 7951 | } |
| 7952 | return dupPtr; |
| 7953 | } |
| 7954 | |
| 7955 | const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr) |
| 7956 | { |
| 7957 | if (objPtr->bytes == NULL) { |
| 7958 | |
| 7959 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7960 | objPtr->typePtr->updateStringProc(objPtr); |
| 7961 | } |
| 7962 | if (lenPtr) |
| 7963 | *lenPtr = objPtr->length; |
| @@ -7966,25 +7988,22 @@ | |
| 7966 | |
| 7967 | |
| 7968 | int Jim_Length(Jim_Obj *objPtr) |
| 7969 | { |
| 7970 | if (objPtr->bytes == NULL) { |
| 7971 | |
| 7972 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7973 | objPtr->typePtr->updateStringProc(objPtr); |
| 7974 | } |
| 7975 | return objPtr->length; |
| 7976 | } |
| 7977 | |
| 7978 | |
| 7979 | const char *Jim_String(Jim_Obj *objPtr) |
| 7980 | { |
| 7981 | if (objPtr->bytes == NULL) { |
| 7982 | |
| 7983 | JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value.")); |
| 7984 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7985 | objPtr->typePtr->updateStringProc(objPtr); |
| 7986 | } |
| 7987 | return objPtr->bytes; |
| 7988 | } |
| 7989 | |
| 7990 | static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) |
| @@ -8001,23 +8020,34 @@ | |
| 8001 | FreeDictSubstInternalRep, |
| 8002 | DupDictSubstInternalRep, |
| 8003 | NULL, |
| 8004 | JIM_TYPE_NONE, |
| 8005 | }; |
| 8006 | |
| 8007 | static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8008 | { |
| 8009 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); |
| 8010 | } |
| 8011 | |
| 8012 | static const Jim_ObjType interpolatedObjType = { |
| 8013 | "interpolated", |
| 8014 | FreeInterpolatedInternalRep, |
| 8015 | NULL, |
| 8016 | NULL, |
| 8017 | JIM_TYPE_NONE, |
| 8018 | }; |
| 8019 | |
| 8020 | static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8021 | static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8022 | |
| 8023 | static const Jim_ObjType stringObjType = { |
| @@ -8037,22 +8067,22 @@ | |
| 8037 | } |
| 8038 | |
| 8039 | static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8040 | { |
| 8041 | if (objPtr->typePtr != &stringObjType) { |
| 8042 | |
| 8043 | if (objPtr->bytes == NULL) { |
| 8044 | |
| 8045 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 8046 | objPtr->typePtr->updateStringProc(objPtr); |
| 8047 | } |
| 8048 | |
| 8049 | Jim_FreeIntRep(interp, objPtr); |
| 8050 | |
| 8051 | objPtr->typePtr = &stringObjType; |
| 8052 | objPtr->internalRep.strValue.maxLength = objPtr->length; |
| 8053 | |
| 8054 | objPtr->internalRep.strValue.charLength = -1; |
| 8055 | } |
| 8056 | return JIM_OK; |
| 8057 | } |
| 8058 | |
| @@ -8073,39 +8103,37 @@ | |
| 8073 | |
| 8074 | Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len) |
| 8075 | { |
| 8076 | Jim_Obj *objPtr = Jim_NewObj(interp); |
| 8077 | |
| 8078 | |
| 8079 | if (len == -1) |
| 8080 | len = strlen(s); |
| 8081 | |
| 8082 | if (len == 0) { |
| 8083 | objPtr->bytes = JimEmptyStringRep; |
| 8084 | } |
| 8085 | else { |
| 8086 | objPtr->bytes = Jim_Alloc(len + 1); |
| 8087 | memcpy(objPtr->bytes, s, len); |
| 8088 | objPtr->bytes[len] = '\0'; |
| 8089 | } |
| 8090 | objPtr->length = len; |
| 8091 | |
| 8092 | |
| 8093 | objPtr->typePtr = NULL; |
| 8094 | return objPtr; |
| 8095 | } |
| 8096 | |
| 8097 | |
| 8098 | Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen) |
| 8099 | { |
| 8100 | #ifdef JIM_UTF8 |
| 8101 | |
| 8102 | int bytelen = utf8_index(s, charlen); |
| 8103 | |
| 8104 | Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen); |
| 8105 | |
| 8106 | |
| 8107 | objPtr->typePtr = &stringObjType; |
| 8108 | objPtr->internalRep.strValue.maxLength = bytelen; |
| 8109 | objPtr->internalRep.strValue.charLength = charlen; |
| 8110 | |
| 8111 | return objPtr; |
| @@ -8132,11 +8160,11 @@ | |
| 8132 | len = strlen(str); |
| 8133 | needlen = objPtr->length + len; |
| 8134 | if (objPtr->internalRep.strValue.maxLength < needlen || |
| 8135 | objPtr->internalRep.strValue.maxLength == 0) { |
| 8136 | needlen *= 2; |
| 8137 | |
| 8138 | if (needlen < 7) { |
| 8139 | needlen = 7; |
| 8140 | } |
| 8141 | if (objPtr->bytes == JimEmptyStringRep) { |
| 8142 | objPtr->bytes = Jim_Alloc(needlen + 1); |
| @@ -8148,11 +8176,11 @@ | |
| 8148 | } |
| 8149 | memcpy(objPtr->bytes + objPtr->length, str, len); |
| 8150 | objPtr->bytes[objPtr->length + len] = '\0'; |
| 8151 | |
| 8152 | if (objPtr->internalRep.strValue.charLength >= 0) { |
| 8153 | |
| 8154 | objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); |
| 8155 | } |
| 8156 | objPtr->length += len; |
| 8157 | } |
| 8158 | |
| @@ -8210,11 +8238,11 @@ | |
| 8210 | int l1, l2; |
| 8211 | const char *s1 = Jim_GetString(firstObjPtr, &l1); |
| 8212 | const char *s2 = Jim_GetString(secondObjPtr, &l2); |
| 8213 | |
| 8214 | if (nocase) { |
| 8215 | |
| 8216 | return JimStringCompareLen(s1, s2, -1, nocase); |
| 8217 | } |
| 8218 | return JimStringCompare(s1, l1, s2, l2); |
| 8219 | } |
| 8220 | |
| @@ -8312,11 +8340,11 @@ | |
| 8312 | |
| 8313 | if (first == 0 && rangeLen == len) { |
| 8314 | return strObjPtr; |
| 8315 | } |
| 8316 | if (len == bytelen) { |
| 8317 | |
| 8318 | return Jim_NewStringObj(interp, str + first, rangeLen); |
| 8319 | } |
| 8320 | return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen); |
| 8321 | #else |
| 8322 | return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr); |
| @@ -8341,19 +8369,19 @@ | |
| 8341 | return strObjPtr; |
| 8342 | } |
| 8343 | |
| 8344 | str = Jim_String(strObjPtr); |
| 8345 | |
| 8346 | |
| 8347 | objPtr = Jim_NewStringObjUtf8(interp, str, first); |
| 8348 | |
| 8349 | |
| 8350 | if (newStrObj) { |
| 8351 | Jim_AppendObj(interp, objPtr, newStrObj); |
| 8352 | } |
| 8353 | |
| 8354 | |
| 8355 | Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1); |
| 8356 | |
| 8357 | return objPtr; |
| 8358 | } |
| 8359 | |
| @@ -8371,12 +8399,10 @@ | |
| 8371 | { |
| 8372 | char *buf; |
| 8373 | int len; |
| 8374 | const char *str; |
| 8375 | |
| 8376 | SetStringFromAny(interp, strObjPtr); |
| 8377 | |
| 8378 | str = Jim_GetString(strObjPtr, &len); |
| 8379 | |
| 8380 | #ifdef JIM_UTF8 |
| 8381 | len *= 2; |
| 8382 | #endif |
| @@ -8389,14 +8415,10 @@ | |
| 8389 | { |
| 8390 | char *buf; |
| 8391 | const char *str; |
| 8392 | int len; |
| 8393 | |
| 8394 | if (strObjPtr->typePtr != &stringObjType) { |
| 8395 | SetStringFromAny(interp, strObjPtr); |
| 8396 | } |
| 8397 | |
| 8398 | str = Jim_GetString(strObjPtr, &len); |
| 8399 | |
| 8400 | #ifdef JIM_UTF8 |
| 8401 | len *= 2; |
| 8402 | #endif |
| @@ -8411,13 +8433,11 @@ | |
| 8411 | int len; |
| 8412 | int c; |
| 8413 | const char *str; |
| 8414 | |
| 8415 | str = Jim_GetString(strObjPtr, &len); |
| 8416 | if (len == 0) { |
| 8417 | return strObjPtr; |
| 8418 | } |
| 8419 | #ifdef JIM_UTF8 |
| 8420 | len *= 2; |
| 8421 | #endif |
| 8422 | buf = p = Jim_Alloc(len + 1); |
| 8423 | |
| @@ -8452,11 +8472,11 @@ | |
| 8452 | while (len) { |
| 8453 | int c; |
| 8454 | int n = utf8_tounicode(str, &c); |
| 8455 | |
| 8456 | if (utf8_memchr(trimchars, trimlen, c) == NULL) { |
| 8457 | |
| 8458 | break; |
| 8459 | } |
| 8460 | str += n; |
| 8461 | len -= n; |
| 8462 | } |
| @@ -8523,41 +8543,41 @@ | |
| 8523 | |
| 8524 | len = Jim_Length(strObjPtr); |
| 8525 | nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen); |
| 8526 | |
| 8527 | if (nontrim == NULL) { |
| 8528 | |
| 8529 | return Jim_NewEmptyStringObj(interp); |
| 8530 | } |
| 8531 | if (nontrim == strObjPtr->bytes + len) { |
| 8532 | |
| 8533 | return strObjPtr; |
| 8534 | } |
| 8535 | |
| 8536 | if (Jim_IsShared(strObjPtr)) { |
| 8537 | strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); |
| 8538 | } |
| 8539 | else { |
| 8540 | |
| 8541 | strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0; |
| 8542 | strObjPtr->length = (nontrim - strObjPtr->bytes); |
| 8543 | } |
| 8544 | |
| 8545 | return strObjPtr; |
| 8546 | } |
| 8547 | |
| 8548 | static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) |
| 8549 | { |
| 8550 | |
| 8551 | Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); |
| 8552 | |
| 8553 | |
| 8554 | strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); |
| 8555 | |
| 8556 | |
| 8557 | if (objPtr != strObjPtr && objPtr->refCount == 0) { |
| 8558 | |
| 8559 | Jim_FreeNewObj(interp, objPtr); |
| 8560 | } |
| 8561 | |
| 8562 | return strObjPtr; |
| 8563 | } |
| @@ -8575,17 +8595,17 @@ | |
| 8575 | static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) |
| 8576 | { |
| 8577 | static const char * const strclassnames[] = { |
| 8578 | "integer", "alpha", "alnum", "ascii", "digit", |
| 8579 | "double", "lower", "upper", "space", "xdigit", |
| 8580 | "control", "print", "graph", "punct", |
| 8581 | NULL |
| 8582 | }; |
| 8583 | enum { |
| 8584 | STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, |
| 8585 | STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, |
| 8586 | STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT |
| 8587 | }; |
| 8588 | int strclass; |
| 8589 | int len; |
| 8590 | int i; |
| 8591 | const char *str; |
| @@ -8613,10 +8633,17 @@ | |
| 8613 | { |
| 8614 | double d; |
| 8615 | Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); |
| 8616 | return JIM_OK; |
| 8617 | } |
| 8618 | |
| 8619 | case STR_IS_ALPHA: isclassfunc = isalpha; break; |
| 8620 | case STR_IS_ALNUM: isclassfunc = isalnum; break; |
| 8621 | case STR_IS_ASCII: isclassfunc = jim_isascii; break; |
| 8622 | case STR_IS_DIGIT: isclassfunc = isdigit; break; |
| @@ -8631,11 +8658,11 @@ | |
| 8631 | default: |
| 8632 | return JIM_ERR; |
| 8633 | } |
| 8634 | |
| 8635 | for (i = 0; i < len; i++) { |
| 8636 | if (!isclassfunc(str[i])) { |
| 8637 | Jim_SetResultBool(interp, 0); |
| 8638 | return JIM_OK; |
| 8639 | } |
| 8640 | } |
| 8641 | Jim_SetResultBool(interp, 1); |
| @@ -8656,20 +8683,18 @@ | |
| 8656 | { |
| 8657 | if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { |
| 8658 | return 1; |
| 8659 | } |
| 8660 | else { |
| 8661 | const char *objStr = Jim_String(objPtr); |
| 8662 | |
| 8663 | if (strcmp(str, objStr) != 0) |
| 8664 | return 0; |
| 8665 | |
| 8666 | if (objPtr->typePtr != &comparedStringObjType) { |
| 8667 | Jim_FreeIntRep(interp, objPtr); |
| 8668 | objPtr->typePtr = &comparedStringObjType; |
| 8669 | } |
| 8670 | objPtr->internalRep.ptr = (char *)str; |
| 8671 | return 1; |
| 8672 | } |
| 8673 | } |
| 8674 | |
| 8675 | static int qsortCompareStringPointers(const void *a, const void *b) |
| @@ -8758,20 +8783,20 @@ | |
| 8758 | int type; |
| 8759 | } ScriptToken; |
| 8760 | |
| 8761 | typedef struct ScriptObj |
| 8762 | { |
| 8763 | ScriptToken *token; |
| 8764 | Jim_Obj *fileNameObj; |
| 8765 | int len; |
| 8766 | int substFlags; |
| 8767 | int inUse; /* Used to share a ScriptObj. Currently |
| 8768 | only used by Jim_EvalObj() as protection against |
| 8769 | shimmering of the currently evaluated object. */ |
| 8770 | int firstline; |
| 8771 | int linenr; |
| 8772 | int missing; |
| 8773 | } ScriptObj; |
| 8774 | |
| 8775 | static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8776 | static int JimParseCheckMissing(Jim_Interp *interp, int ch); |
| 8777 | static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr); |
| @@ -8799,23 +8824,23 @@ | |
| 8799 | dupPtr->typePtr = NULL; |
| 8800 | } |
| 8801 | |
| 8802 | typedef struct |
| 8803 | { |
| 8804 | const char *token; |
| 8805 | int len; |
| 8806 | int type; |
| 8807 | int line; |
| 8808 | } ParseToken; |
| 8809 | |
| 8810 | typedef struct |
| 8811 | { |
| 8812 | |
| 8813 | ParseToken *list; |
| 8814 | int size; |
| 8815 | int count; |
| 8816 | ParseToken static_list[20]; |
| 8817 | } ParseTokenList; |
| 8818 | |
| 8819 | static void ScriptTokenListInit(ParseTokenList *tokenlist) |
| 8820 | { |
| 8821 | tokenlist->list = tokenlist->static_list; |
| @@ -8834,18 +8859,18 @@ | |
| 8834 | int line) |
| 8835 | { |
| 8836 | ParseToken *t; |
| 8837 | |
| 8838 | if (tokenlist->count == tokenlist->size) { |
| 8839 | |
| 8840 | tokenlist->size *= 2; |
| 8841 | if (tokenlist->list != tokenlist->static_list) { |
| 8842 | tokenlist->list = |
| 8843 | Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list)); |
| 8844 | } |
| 8845 | else { |
| 8846 | |
| 8847 | tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list)); |
| 8848 | memcpy(tokenlist->list, tokenlist->static_list, |
| 8849 | tokenlist->count * sizeof(*tokenlist->list)); |
| 8850 | } |
| 8851 | } |
| @@ -8854,25 +8879,32 @@ | |
| 8854 | t->len = len; |
| 8855 | t->type = type; |
| 8856 | t->line = line; |
| 8857 | } |
| 8858 | |
| 8859 | static int JimCountWordTokens(ParseToken *t) |
| 8860 | { |
| 8861 | int expand = 1; |
| 8862 | int count = 0; |
| 8863 | |
| 8864 | |
| 8865 | if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { |
| 8866 | if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { |
| 8867 | |
| 8868 | expand = -1; |
| 8869 | t++; |
| 8870 | } |
| 8871 | } |
| 8872 | |
| 8873 | |
| 8874 | while (!TOKEN_IS_SEP(t->type)) { |
| 8875 | t++; |
| 8876 | count++; |
| 8877 | } |
| 8878 | |
| @@ -8882,11 +8914,11 @@ | |
| 8882 | static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t) |
| 8883 | { |
| 8884 | Jim_Obj *objPtr; |
| 8885 | |
| 8886 | if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) { |
| 8887 | |
| 8888 | int len = t->len; |
| 8889 | char *str = Jim_Alloc(len + 1); |
| 8890 | len = JimEscape(str, t->token, len); |
| 8891 | objPtr = Jim_NewStringObjNoAlloc(interp, str, len); |
| 8892 | } |
| @@ -8899,13 +8931,13 @@ | |
| 8899 | static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, |
| 8900 | ParseTokenList *tokenlist) |
| 8901 | { |
| 8902 | int i; |
| 8903 | struct ScriptToken *token; |
| 8904 | |
| 8905 | int lineargs = 0; |
| 8906 | |
| 8907 | ScriptToken *linefirst; |
| 8908 | int count; |
| 8909 | int linenr; |
| 8910 | |
| 8911 | #ifdef DEBUG_SHOW_SCRIPT_TOKENS |
| @@ -8914,11 +8946,11 @@ | |
| 8914 | printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type), |
| 8915 | tokenlist->list[i].len, tokenlist->list[i].token); |
| 8916 | } |
| 8917 | #endif |
| 8918 | |
| 8919 | |
| 8920 | count = tokenlist->count; |
| 8921 | for (i = 0; i < tokenlist->count; i++) { |
| 8922 | if (tokenlist->list[i].type == JIM_TT_EOL) { |
| 8923 | count++; |
| 8924 | } |
| @@ -8925,59 +8957,59 @@ | |
| 8925 | } |
| 8926 | linenr = script->firstline = tokenlist->list[0].line; |
| 8927 | |
| 8928 | token = script->token = Jim_Alloc(sizeof(ScriptToken) * count); |
| 8929 | |
| 8930 | |
| 8931 | linefirst = token++; |
| 8932 | |
| 8933 | for (i = 0; i < tokenlist->count; ) { |
| 8934 | |
| 8935 | int wordtokens; |
| 8936 | |
| 8937 | |
| 8938 | while (tokenlist->list[i].type == JIM_TT_SEP) { |
| 8939 | i++; |
| 8940 | } |
| 8941 | |
| 8942 | wordtokens = JimCountWordTokens(tokenlist->list + i); |
| 8943 | |
| 8944 | if (wordtokens == 0) { |
| 8945 | |
| 8946 | if (lineargs) { |
| 8947 | linefirst->type = JIM_TT_LINE; |
| 8948 | linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); |
| 8949 | Jim_IncrRefCount(linefirst->objPtr); |
| 8950 | |
| 8951 | |
| 8952 | lineargs = 0; |
| 8953 | linefirst = token++; |
| 8954 | } |
| 8955 | i++; |
| 8956 | continue; |
| 8957 | } |
| 8958 | else if (wordtokens != 1) { |
| 8959 | |
| 8960 | token->type = JIM_TT_WORD; |
| 8961 | token->objPtr = Jim_NewIntObj(interp, wordtokens); |
| 8962 | Jim_IncrRefCount(token->objPtr); |
| 8963 | token++; |
| 8964 | if (wordtokens < 0) { |
| 8965 | |
| 8966 | i++; |
| 8967 | wordtokens = -wordtokens - 1; |
| 8968 | lineargs--; |
| 8969 | } |
| 8970 | } |
| 8971 | |
| 8972 | if (lineargs == 0) { |
| 8973 | |
| 8974 | linenr = tokenlist->list[i].line; |
| 8975 | } |
| 8976 | lineargs++; |
| 8977 | |
| 8978 | |
| 8979 | while (wordtokens--) { |
| 8980 | const ParseToken *t = &tokenlist->list[i++]; |
| 8981 | |
| 8982 | token->type = t->type; |
| 8983 | token->objPtr = JimMakeScriptObj(interp, t); |
| @@ -9010,11 +9042,11 @@ | |
| 9010 | { |
| 9011 | ScriptObj *script = JimGetScript(interp, scriptObj); |
| 9012 | if (stateCharPtr) { |
| 9013 | *stateCharPtr = script->missing; |
| 9014 | } |
| 9015 | return (script->missing == ' '); |
| 9016 | } |
| 9017 | |
| 9018 | static int JimParseCheckMissing(Jim_Interp *interp, int ch) |
| 9019 | { |
| 9020 | const char *msg; |
| @@ -9028,10 +9060,13 @@ | |
| 9028 | msg = "unmatched \"[\""; |
| 9029 | break; |
| 9030 | case '{': |
| 9031 | msg = "missing close-brace"; |
| 9032 | break; |
| 9033 | case '"': |
| 9034 | default: |
| 9035 | msg = "missing quote"; |
| 9036 | break; |
| 9037 | } |
| @@ -9049,11 +9084,11 @@ | |
| 9049 | token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count); |
| 9050 | |
| 9051 | for (i = 0; i < tokenlist->count; i++) { |
| 9052 | const ParseToken *t = &tokenlist->list[i]; |
| 9053 | |
| 9054 | |
| 9055 | token->type = t->type; |
| 9056 | token->objPtr = JimMakeScriptObj(interp, t); |
| 9057 | Jim_IncrRefCount(token->objPtr); |
| 9058 | token++; |
| 9059 | } |
| @@ -9068,29 +9103,29 @@ | |
| 9068 | struct JimParserCtx parser; |
| 9069 | struct ScriptObj *script; |
| 9070 | ParseTokenList tokenlist; |
| 9071 | int line = 1; |
| 9072 | |
| 9073 | |
| 9074 | if (objPtr->typePtr == &sourceObjType) { |
| 9075 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 9076 | } |
| 9077 | |
| 9078 | |
| 9079 | ScriptTokenListInit(&tokenlist); |
| 9080 | |
| 9081 | JimParserInit(&parser, scriptText, scriptTextLen, line); |
| 9082 | while (!parser.eof) { |
| 9083 | JimParseScript(&parser); |
| 9084 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 9085 | parser.tline); |
| 9086 | } |
| 9087 | |
| 9088 | |
| 9089 | ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); |
| 9090 | |
| 9091 | |
| 9092 | script = Jim_Alloc(sizeof(*script)); |
| 9093 | memset(script, 0, sizeof(*script)); |
| 9094 | script->inUse = 1; |
| 9095 | if (objPtr->typePtr == &sourceObjType) { |
| 9096 | script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| @@ -9102,14 +9137,14 @@ | |
| 9102 | script->missing = parser.missing.ch; |
| 9103 | script->linenr = parser.missing.line; |
| 9104 | |
| 9105 | ScriptObjAddTokens(interp, script, &tokenlist); |
| 9106 | |
| 9107 | |
| 9108 | ScriptTokenListFree(&tokenlist); |
| 9109 | |
| 9110 | |
| 9111 | Jim_FreeIntRep(interp, objPtr); |
| 9112 | Jim_SetIntRepPtr(objPtr, script); |
| 9113 | objPtr->typePtr = &scriptObjType; |
| 9114 | } |
| 9115 | |
| @@ -9116,11 +9151,11 @@ | |
| 9116 | static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script); |
| 9117 | |
| 9118 | static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 9119 | { |
| 9120 | if (objPtr == interp->emptyObj) { |
| 9121 | |
| 9122 | objPtr = interp->nullScriptObj; |
| 9123 | } |
| 9124 | |
| 9125 | if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { |
| 9126 | JimSetScriptFromAny(interp, objPtr); |
| @@ -9155,67 +9190,66 @@ | |
| 9155 | Jim_FreeHashTable(cmdPtr->u.proc.staticVars); |
| 9156 | Jim_Free(cmdPtr->u.proc.staticVars); |
| 9157 | } |
| 9158 | } |
| 9159 | else { |
| 9160 | |
| 9161 | if (cmdPtr->u.native.delProc) { |
| 9162 | cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData); |
| 9163 | } |
| 9164 | } |
| 9165 | if (cmdPtr->prevCmd) { |
| 9166 | |
| 9167 | JimDecrCmdRefCount(interp, cmdPtr->prevCmd); |
| 9168 | } |
| 9169 | Jim_Free(cmdPtr); |
| 9170 | } |
| 9171 | } |
| 9172 | |
| 9173 | |
| 9174 | static void JimVariablesHTValDestructor(void *interp, void *val) |
| 9175 | { |
| 9176 | Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr); |
| 9177 | Jim_Free(val); |
| 9178 | } |
| 9179 | |
| 9180 | static const Jim_HashTableType JimVariablesHashTableType = { |
| 9181 | JimStringCopyHTHashFunction, |
| 9182 | JimStringCopyHTDup, |
| 9183 | NULL, |
| 9184 | JimStringCopyHTKeyCompare, |
| 9185 | JimStringCopyHTKeyDestructor, |
| 9186 | JimVariablesHTValDestructor |
| 9187 | }; |
| 9188 | |
| 9189 | static void JimCommandsHT_ValDestructor(void *interp, void *val) |
| 9190 | { |
| 9191 | JimDecrCmdRefCount(interp, val); |
| 9192 | } |
| 9193 | |
| 9194 | static const Jim_HashTableType JimCommandsHashTableType = { |
| 9195 | JimStringCopyHTHashFunction, |
| 9196 | JimStringCopyHTDup, |
| 9197 | NULL, |
| 9198 | JimStringCopyHTKeyCompare, |
| 9199 | JimStringCopyHTKeyDestructor, |
| 9200 | JimCommandsHT_ValDestructor |
| 9201 | }; |
| 9202 | |
| 9203 | |
| 9204 | |
| 9205 | #ifdef jim_ext_namespace |
| 9206 | static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj) |
| 9207 | { |
| 9208 | const char *name = Jim_String(nsObj); |
| 9209 | if (name[0] == ':' && name[1] == ':') { |
| 9210 | |
| 9211 | while (*++name == ':') { |
| 9212 | } |
| 9213 | nsObj = Jim_NewStringObj(interp, name, -1); |
| 9214 | } |
| 9215 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9216 | |
| 9217 | nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9218 | Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 9219 | } |
| 9220 | return nsObj; |
| 9221 | } |
| @@ -9239,16 +9273,16 @@ | |
| 9239 | static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 9240 | { |
| 9241 | Jim_Obj *objPtr = interp->emptyObj; |
| 9242 | |
| 9243 | if (name[0] == ':' && name[1] == ':') { |
| 9244 | |
| 9245 | while (*++name == ':') { |
| 9246 | } |
| 9247 | } |
| 9248 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9249 | |
| 9250 | objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9251 | Jim_AppendStrings(interp, objPtr, "::", name, NULL); |
| 9252 | name = Jim_String(objPtr); |
| 9253 | } |
| 9254 | Jim_IncrRefCount(objPtr); |
| @@ -9257,11 +9291,11 @@ | |
| 9257 | } |
| 9258 | |
| 9259 | #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ)) |
| 9260 | |
| 9261 | #else |
| 9262 | |
| 9263 | #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 9264 | #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 9265 | |
| 9266 | Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 9267 | { |
| @@ -9276,17 +9310,17 @@ | |
| 9276 | |
| 9277 | Jim_InterpIncrProcEpoch(interp); |
| 9278 | } |
| 9279 | |
| 9280 | if (he && interp->local) { |
| 9281 | |
| 9282 | cmd->prevCmd = Jim_GetHashEntryVal(he); |
| 9283 | Jim_SetHashVal(&interp->commands, he, cmd); |
| 9284 | } |
| 9285 | else { |
| 9286 | if (he) { |
| 9287 | |
| 9288 | Jim_DeleteHashEntry(&interp->commands, name); |
| 9289 | } |
| 9290 | |
| 9291 | Jim_AddHashEntry(&interp->commands, name, cmd); |
| 9292 | } |
| @@ -9297,11 +9331,11 @@ | |
| 9297 | int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr, |
| 9298 | Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc) |
| 9299 | { |
| 9300 | Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); |
| 9301 | |
| 9302 | |
| 9303 | memset(cmdPtr, 0, sizeof(*cmdPtr)); |
| 9304 | cmdPtr->inUse = 1; |
| 9305 | cmdPtr->u.native.delProc = delProc; |
| 9306 | cmdPtr->u.native.cmdProc = cmdProc; |
| 9307 | cmdPtr->u.native.privData = privData; |
| @@ -9326,11 +9360,11 @@ | |
| 9326 | Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; |
| 9327 | Jim_Var *varPtr; |
| 9328 | int subLen; |
| 9329 | |
| 9330 | objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); |
| 9331 | |
| 9332 | subLen = Jim_ListLength(interp, objPtr); |
| 9333 | if (subLen == 1 || subLen == 2) { |
| 9334 | nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); |
| 9335 | if (subLen == 1) { |
| 9336 | initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| @@ -9372,19 +9406,19 @@ | |
| 9372 | |
| 9373 | static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname) |
| 9374 | { |
| 9375 | #ifdef jim_ext_namespace |
| 9376 | if (cmdPtr->isproc) { |
| 9377 | |
| 9378 | const char *pt = strrchr(cmdname, ':'); |
| 9379 | if (pt && pt != cmdname && pt[-1] == ':') { |
| 9380 | Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); |
| 9381 | cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1); |
| 9382 | Jim_IncrRefCount(cmdPtr->u.proc.nsObj); |
| 9383 | |
| 9384 | if (Jim_FindHashEntry(&interp->commands, pt + 1)) { |
| 9385 | |
| 9386 | Jim_InterpIncrProcEpoch(interp); |
| 9387 | } |
| 9388 | } |
| 9389 | } |
| 9390 | #endif |
| @@ -9397,11 +9431,11 @@ | |
| 9397 | int argListLen; |
| 9398 | int i; |
| 9399 | |
| 9400 | argListLen = Jim_ListLength(interp, argListObjPtr); |
| 9401 | |
| 9402 | |
| 9403 | cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); |
| 9404 | memset(cmdPtr, 0, sizeof(*cmdPtr)); |
| 9405 | cmdPtr->inUse = 1; |
| 9406 | cmdPtr->isproc = 1; |
| 9407 | cmdPtr->u.proc.argListObjPtr = argListObjPtr; |
| @@ -9412,24 +9446,24 @@ | |
| 9412 | cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj; |
| 9413 | Jim_IncrRefCount(argListObjPtr); |
| 9414 | Jim_IncrRefCount(bodyObjPtr); |
| 9415 | Jim_IncrRefCount(cmdPtr->u.proc.nsObj); |
| 9416 | |
| 9417 | |
| 9418 | if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) { |
| 9419 | goto err; |
| 9420 | } |
| 9421 | |
| 9422 | |
| 9423 | |
| 9424 | for (i = 0; i < argListLen; i++) { |
| 9425 | Jim_Obj *argPtr; |
| 9426 | Jim_Obj *nameObjPtr; |
| 9427 | Jim_Obj *defaultObjPtr; |
| 9428 | int len; |
| 9429 | |
| 9430 | |
| 9431 | argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); |
| 9432 | len = Jim_ListLength(interp, argPtr); |
| 9433 | if (len == 0) { |
| 9434 | Jim_SetResultString(interp, "argument with no name", -1); |
| 9435 | err: |
| @@ -9440,16 +9474,16 @@ | |
| 9440 | Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr); |
| 9441 | goto err; |
| 9442 | } |
| 9443 | |
| 9444 | if (len == 2) { |
| 9445 | |
| 9446 | nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); |
| 9447 | defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); |
| 9448 | } |
| 9449 | else { |
| 9450 | |
| 9451 | nameObjPtr = argPtr; |
| 9452 | defaultObjPtr = NULL; |
| 9453 | } |
| 9454 | |
| 9455 | |
| @@ -9510,29 +9544,29 @@ | |
| 9510 | } |
| 9511 | |
| 9512 | fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj); |
| 9513 | fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj); |
| 9514 | |
| 9515 | |
| 9516 | he = Jim_FindHashEntry(&interp->commands, fqold); |
| 9517 | if (he == NULL) { |
| 9518 | Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName); |
| 9519 | } |
| 9520 | else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9521 | Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 9522 | } |
| 9523 | else { |
| 9524 | |
| 9525 | cmdPtr = Jim_GetHashEntryVal(he); |
| 9526 | JimIncrCmdRefCount(cmdPtr); |
| 9527 | JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9528 | Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9529 | |
| 9530 | |
| 9531 | Jim_DeleteHashEntry(&interp->commands, fqold); |
| 9532 | |
| 9533 | |
| 9534 | Jim_InterpIncrProcEpoch(interp); |
| 9535 | |
| 9536 | ret = JIM_OK; |
| 9537 | } |
| 9538 | |
| @@ -9571,23 +9605,23 @@ | |
| 9571 | objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch |
| 9572 | #ifdef jim_ext_namespace |
| 9573 | || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj) |
| 9574 | #endif |
| 9575 | ) { |
| 9576 | |
| 9577 | |
| 9578 | |
| 9579 | const char *name = Jim_String(objPtr); |
| 9580 | Jim_HashEntry *he; |
| 9581 | |
| 9582 | if (name[0] == ':' && name[1] == ':') { |
| 9583 | while (*++name == ':') { |
| 9584 | } |
| 9585 | } |
| 9586 | #ifdef jim_ext_namespace |
| 9587 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9588 | |
| 9589 | Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9590 | Jim_AppendStrings(interp, nameObj, "::", name, NULL); |
| 9591 | he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj)); |
| 9592 | Jim_FreeNewObj(interp, nameObj); |
| 9593 | if (he) { |
| @@ -9594,11 +9628,11 @@ | |
| 9594 | goto found; |
| 9595 | } |
| 9596 | } |
| 9597 | #endif |
| 9598 | |
| 9599 | |
| 9600 | he = Jim_FindHashEntry(&interp->commands, name); |
| 9601 | if (he == NULL) { |
| 9602 | if (flags & JIM_ERRMSG) { |
| 9603 | Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); |
| 9604 | } |
| @@ -9607,11 +9641,11 @@ | |
| 9607 | #ifdef jim_ext_namespace |
| 9608 | found: |
| 9609 | #endif |
| 9610 | cmd = Jim_GetHashEntryVal(he); |
| 9611 | |
| 9612 | |
| 9613 | Jim_FreeIntRep(interp, objPtr); |
| 9614 | objPtr->typePtr = &commandObjType; |
| 9615 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| 9616 | objPtr->internalRep.cmdValue.cmdPtr = cmd; |
| 9617 | objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj; |
| @@ -9626,11 +9660,11 @@ | |
| 9626 | return cmd; |
| 9627 | } |
| 9628 | |
| 9629 | |
| 9630 | |
| 9631 | #define JIM_DICT_SUGAR 100 |
| 9632 | |
| 9633 | static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 9634 | |
| 9635 | static const Jim_ObjType variableObjType = { |
| 9636 | "variable", |
| @@ -9640,11 +9674,11 @@ | |
| 9640 | JIM_TYPE_REFERENCES, |
| 9641 | }; |
| 9642 | |
| 9643 | static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) |
| 9644 | { |
| 9645 | |
| 9646 | if (nameObjPtr->typePtr != &variableObjType) { |
| 9647 | int len; |
| 9648 | const char *str = Jim_GetString(nameObjPtr, &len); |
| 9649 | if (memchr(str, '\0', len)) { |
| 9650 | Jim_SetResultFormatted(interp, "%s name contains embedded null", type); |
| @@ -9660,18 +9694,18 @@ | |
| 9660 | Jim_CallFrame *framePtr; |
| 9661 | Jim_HashEntry *he; |
| 9662 | int global; |
| 9663 | int len; |
| 9664 | |
| 9665 | |
| 9666 | if (objPtr->typePtr == &variableObjType) { |
| 9667 | framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr; |
| 9668 | if (objPtr->internalRep.varValue.callFrameId == framePtr->id) { |
| 9669 | |
| 9670 | return JIM_OK; |
| 9671 | } |
| 9672 | |
| 9673 | } |
| 9674 | else if (objPtr->typePtr == &dictSubstObjType) { |
| 9675 | return JIM_DICT_SUGAR; |
| 9676 | } |
| 9677 | else if (JimValidName(interp, "variable", objPtr) != JIM_OK) { |
| @@ -9679,11 +9713,11 @@ | |
| 9679 | } |
| 9680 | |
| 9681 | |
| 9682 | varName = Jim_GetString(objPtr, &len); |
| 9683 | |
| 9684 | |
| 9685 | if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) { |
| 9686 | return JIM_DICT_SUGAR; |
| 9687 | } |
| 9688 | |
| 9689 | if (varName[0] == ':' && varName[1] == ':') { |
| @@ -9695,23 +9729,23 @@ | |
| 9695 | else { |
| 9696 | global = 0; |
| 9697 | framePtr = interp->framePtr; |
| 9698 | } |
| 9699 | |
| 9700 | |
| 9701 | he = Jim_FindHashEntry(&framePtr->vars, varName); |
| 9702 | if (he == NULL) { |
| 9703 | if (!global && framePtr->staticVars) { |
| 9704 | |
| 9705 | he = Jim_FindHashEntry(framePtr->staticVars, varName); |
| 9706 | } |
| 9707 | if (he == NULL) { |
| 9708 | return JIM_ERR; |
| 9709 | } |
| 9710 | } |
| 9711 | |
| 9712 | |
| 9713 | Jim_FreeIntRep(interp, objPtr); |
| 9714 | objPtr->typePtr = &variableObjType; |
| 9715 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9716 | objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); |
| 9717 | objPtr->internalRep.varValue.global = global; |
| @@ -9726,11 +9760,11 @@ | |
| 9726 | { |
| 9727 | const char *name; |
| 9728 | Jim_CallFrame *framePtr; |
| 9729 | int global; |
| 9730 | |
| 9731 | |
| 9732 | Jim_Var *var = Jim_Alloc(sizeof(*var)); |
| 9733 | |
| 9734 | var->objPtr = valObjPtr; |
| 9735 | Jim_IncrRefCount(valObjPtr); |
| 9736 | var->linkFramePtr = NULL; |
| @@ -9745,14 +9779,14 @@ | |
| 9745 | else { |
| 9746 | framePtr = interp->framePtr; |
| 9747 | global = 0; |
| 9748 | } |
| 9749 | |
| 9750 | |
| 9751 | Jim_AddHashEntry(&framePtr->vars, name, var); |
| 9752 | |
| 9753 | |
| 9754 | Jim_FreeIntRep(interp, nameObjPtr); |
| 9755 | nameObjPtr->typePtr = &variableObjType; |
| 9756 | nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9757 | nameObjPtr->internalRep.varValue.varPtr = var; |
| 9758 | nameObjPtr->internalRep.varValue.global = global; |
| @@ -9782,11 +9816,11 @@ | |
| 9782 | if (var->linkFramePtr == NULL) { |
| 9783 | Jim_IncrRefCount(valObjPtr); |
| 9784 | Jim_DecrRefCount(interp, var->objPtr); |
| 9785 | var->objPtr = valObjPtr; |
| 9786 | } |
| 9787 | else { |
| 9788 | Jim_CallFrame *savedCallFrame; |
| 9789 | |
| 9790 | savedCallFrame = interp->framePtr; |
| 9791 | interp->framePtr = var->linkFramePtr; |
| 9792 | err = Jim_SetVariable(interp, var->objPtr, valObjPtr); |
| @@ -9822,19 +9856,16 @@ | |
| 9822 | return result; |
| 9823 | } |
| 9824 | |
| 9825 | int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) |
| 9826 | { |
| 9827 | Jim_Obj *nameObjPtr, *valObjPtr; |
| 9828 | int result; |
| 9829 | |
| 9830 | nameObjPtr = Jim_NewStringObj(interp, name, -1); |
| 9831 | valObjPtr = Jim_NewStringObj(interp, val, -1); |
| 9832 | Jim_IncrRefCount(nameObjPtr); |
| 9833 | Jim_IncrRefCount(valObjPtr); |
| 9834 | result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); |
| 9835 | Jim_DecrRefCount(interp, nameObjPtr); |
| 9836 | Jim_DecrRefCount(interp, valObjPtr); |
| 9837 | return result; |
| 9838 | } |
| 9839 | |
| 9840 | int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, |
| @@ -9843,14 +9874,14 @@ | |
| 9843 | const char *varName; |
| 9844 | const char *targetName; |
| 9845 | Jim_CallFrame *framePtr; |
| 9846 | Jim_Var *varPtr; |
| 9847 | |
| 9848 | |
| 9849 | switch (SetVariableFromAny(interp, nameObjPtr)) { |
| 9850 | case JIM_DICT_SUGAR: |
| 9851 | |
| 9852 | Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr); |
| 9853 | return JIM_ERR; |
| 9854 | |
| 9855 | case JIM_OK: |
| 9856 | varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| @@ -9858,23 +9889,23 @@ | |
| 9858 | if (varPtr->linkFramePtr == NULL) { |
| 9859 | Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); |
| 9860 | return JIM_ERR; |
| 9861 | } |
| 9862 | |
| 9863 | |
| 9864 | varPtr->linkFramePtr = NULL; |
| 9865 | break; |
| 9866 | } |
| 9867 | |
| 9868 | |
| 9869 | |
| 9870 | varName = Jim_String(nameObjPtr); |
| 9871 | |
| 9872 | if (varName[0] == ':' && varName[1] == ':') { |
| 9873 | while (*++varName == ':') { |
| 9874 | } |
| 9875 | |
| 9876 | framePtr = interp->topFramePtr; |
| 9877 | } |
| 9878 | else { |
| 9879 | framePtr = interp->framePtr; |
| 9880 | } |
| @@ -9894,15 +9925,15 @@ | |
| 9894 | nameObjPtr); |
| 9895 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9896 | return JIM_ERR; |
| 9897 | } |
| 9898 | |
| 9899 | |
| 9900 | if (framePtr == targetCallFrame) { |
| 9901 | Jim_Obj *objPtr = targetNameObjPtr; |
| 9902 | |
| 9903 | |
| 9904 | while (1) { |
| 9905 | if (strcmp(Jim_String(objPtr), varName) == 0) { |
| 9906 | Jim_SetResultString(interp, "can't upvar from variable to itself", -1); |
| 9907 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9908 | return JIM_ERR; |
| @@ -9914,13 +9945,13 @@ | |
| 9914 | break; |
| 9915 | objPtr = varPtr->objPtr; |
| 9916 | } |
| 9917 | } |
| 9918 | |
| 9919 | |
| 9920 | Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); |
| 9921 | |
| 9922 | nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; |
| 9923 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9924 | return JIM_OK; |
| 9925 | } |
| 9926 | |
| @@ -9934,26 +9965,26 @@ | |
| 9934 | return varPtr->objPtr; |
| 9935 | } |
| 9936 | else { |
| 9937 | Jim_Obj *objPtr; |
| 9938 | |
| 9939 | |
| 9940 | Jim_CallFrame *savedCallFrame = interp->framePtr; |
| 9941 | |
| 9942 | interp->framePtr = varPtr->linkFramePtr; |
| 9943 | objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); |
| 9944 | interp->framePtr = savedCallFrame; |
| 9945 | if (objPtr) { |
| 9946 | return objPtr; |
| 9947 | } |
| 9948 | |
| 9949 | } |
| 9950 | } |
| 9951 | break; |
| 9952 | |
| 9953 | case JIM_DICT_SUGAR: |
| 9954 | |
| 9955 | return JimDictSugarGet(interp, nameObjPtr, flags); |
| 9956 | } |
| 9957 | if (flags & JIM_ERRMSG) { |
| 9958 | Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr); |
| 9959 | } |
| @@ -10003,17 +10034,17 @@ | |
| 10003 | int retval; |
| 10004 | Jim_CallFrame *framePtr; |
| 10005 | |
| 10006 | retval = SetVariableFromAny(interp, nameObjPtr); |
| 10007 | if (retval == JIM_DICT_SUGAR) { |
| 10008 | |
| 10009 | return JimDictSugarSet(interp, nameObjPtr, NULL); |
| 10010 | } |
| 10011 | else if (retval == JIM_OK) { |
| 10012 | varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| 10013 | |
| 10014 | |
| 10015 | if (varPtr->linkFramePtr) { |
| 10016 | framePtr = interp->framePtr; |
| 10017 | interp->framePtr = varPtr->linkFramePtr; |
| 10018 | retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); |
| 10019 | interp->framePtr = framePtr; |
| @@ -10028,11 +10059,11 @@ | |
| 10028 | framePtr = interp->framePtr; |
| 10029 | } |
| 10030 | |
| 10031 | retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 10032 | if (retval == JIM_OK) { |
| 10033 | |
| 10034 | framePtr->id = interp->callFrameEpoch++; |
| 10035 | } |
| 10036 | } |
| 10037 | } |
| 10038 | if (retval != JIM_OK && (flags & JIM_ERRMSG)) { |
| @@ -10061,11 +10092,11 @@ | |
| 10061 | keyLen = (str + len) - p; |
| 10062 | if (str[len - 1] == ')') { |
| 10063 | keyLen--; |
| 10064 | } |
| 10065 | |
| 10066 | |
| 10067 | keyObjPtr = Jim_NewStringObj(interp, p, keyLen); |
| 10068 | |
| 10069 | Jim_IncrRefCount(varObjPtr); |
| 10070 | Jim_IncrRefCount(keyObjPtr); |
| 10071 | *varPtrPtr = varObjPtr; |
| @@ -10080,23 +10111,23 @@ | |
| 10080 | |
| 10081 | err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, |
| 10082 | &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST); |
| 10083 | |
| 10084 | if (err == JIM_OK) { |
| 10085 | |
| 10086 | Jim_SetEmptyResult(interp); |
| 10087 | } |
| 10088 | else { |
| 10089 | if (!valObjPtr) { |
| 10090 | |
| 10091 | if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) { |
| 10092 | Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array", |
| 10093 | objPtr); |
| 10094 | return err; |
| 10095 | } |
| 10096 | } |
| 10097 | |
| 10098 | Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array", |
| 10099 | (valObjPtr ? "set" : "unset"), objPtr); |
| 10100 | } |
| 10101 | return err; |
| 10102 | } |
| @@ -10118,11 +10149,11 @@ | |
| 10118 | Jim_SetResultFormatted(interp, |
| 10119 | "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, |
| 10120 | ret < 0 ? "variable isn't" : "no such element in"); |
| 10121 | } |
| 10122 | else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { |
| 10123 | |
| 10124 | Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); |
| 10125 | } |
| 10126 | |
| 10127 | return resObjPtr; |
| 10128 | } |
| @@ -10143,28 +10174,27 @@ | |
| 10143 | { |
| 10144 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); |
| 10145 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); |
| 10146 | } |
| 10147 | |
| 10148 | void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 10149 | { |
| 10150 | JIM_NOTUSED(interp); |
| 10151 | |
| 10152 | dupPtr->internalRep.dictSubstValue.varNameObjPtr = |
| 10153 | srcPtr->internalRep.dictSubstValue.varNameObjPtr; |
| 10154 | dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr; |
| 10155 | dupPtr->typePtr = &dictSubstObjType; |
| 10156 | } |
| 10157 | |
| 10158 | |
| 10159 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10160 | { |
| 10161 | if (objPtr->typePtr != &dictSubstObjType) { |
| 10162 | Jim_Obj *varObjPtr, *keyObjPtr; |
| 10163 | |
| 10164 | if (objPtr->typePtr == &interpolatedObjType) { |
| 10165 | |
| 10166 | |
| 10167 | varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr; |
| 10168 | keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr; |
| 10169 | |
| 10170 | Jim_IncrRefCount(varObjPtr); |
| @@ -10202,16 +10232,12 @@ | |
| 10202 | return resObjPtr; |
| 10203 | } |
| 10204 | |
| 10205 | static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10206 | { |
| 10207 | Jim_Obj *resultObjPtr; |
| 10208 | |
| 10209 | if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) { |
| 10210 | |
| 10211 | resultObjPtr->refCount--; |
| 10212 | return resultObjPtr; |
| 10213 | } |
| 10214 | return NULL; |
| 10215 | } |
| 10216 | |
| 10217 | |
| @@ -10249,11 +10275,11 @@ | |
| 10249 | return cf; |
| 10250 | } |
| 10251 | |
| 10252 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) |
| 10253 | { |
| 10254 | |
| 10255 | if (localCommands) { |
| 10256 | Jim_Obj *cmdNameObj; |
| 10257 | |
| 10258 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 10259 | Jim_HashEntry *he; |
| @@ -10268,20 +10294,20 @@ | |
| 10268 | Jim_Cmd *cmd = Jim_GetHashEntryVal(he); |
| 10269 | if (cmd->prevCmd) { |
| 10270 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 10271 | cmd->prevCmd = NULL; |
| 10272 | |
| 10273 | |
| 10274 | JimDecrCmdRefCount(interp, cmd); |
| 10275 | |
| 10276 | |
| 10277 | Jim_SetHashVal(ht, he, prevCmd); |
| 10278 | } |
| 10279 | else { |
| 10280 | Jim_DeleteHashEntry(ht, fqname); |
| 10281 | Jim_InterpIncrProcEpoch(interp); |
| 10282 | } |
| 10283 | } |
| 10284 | Jim_DecrRefCount(interp, cmdNameObj); |
| 10285 | JimFreeQualifiedName(interp, fqObjName); |
| 10286 | } |
| 10287 | Jim_FreeStack(localCommands); |
| @@ -10288,13 +10314,59 @@ | |
| 10288 | Jim_Free(localCommands); |
| 10289 | } |
| 10290 | return JIM_OK; |
| 10291 | } |
| 10292 | |
| 10293 | |
| 10294 | #define JIM_FCF_FULL 0 |
| 10295 | #define JIM_FCF_REUSE 1 |
| 10296 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) |
| 10297 | { |
| 10298 | JimDeleteLocalProcs(interp, cf->localCommands); |
| 10299 | |
| 10300 | if (cf->procArgsObjPtr) |
| @@ -10327,263 +10399,10 @@ | |
| 10327 | cf->next = interp->freeFramesList; |
| 10328 | interp->freeFramesList = cf; |
| 10329 | } |
| 10330 | |
| 10331 | |
| 10332 | #ifdef JIM_REFERENCES |
| 10333 | |
| 10334 | static void JimReferencesHTValDestructor(void *interp, void *val) |
| 10335 | { |
| 10336 | Jim_Reference *refPtr = (void *)val; |
| 10337 | |
| 10338 | Jim_DecrRefCount(interp, refPtr->objPtr); |
| 10339 | if (refPtr->finalizerCmdNamePtr != NULL) { |
| 10340 | Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); |
| 10341 | } |
| 10342 | Jim_Free(val); |
| 10343 | } |
| 10344 | |
| 10345 | static unsigned int JimReferencesHTHashFunction(const void *key) |
| 10346 | { |
| 10347 | |
| 10348 | const unsigned long *widePtr = key; |
| 10349 | unsigned int intValue = (unsigned int)*widePtr; |
| 10350 | |
| 10351 | return Jim_IntHashFunction(intValue); |
| 10352 | } |
| 10353 | |
| 10354 | static void *JimReferencesHTKeyDup(void *privdata, const void *key) |
| 10355 | { |
| 10356 | void *copy = Jim_Alloc(sizeof(unsigned long)); |
| 10357 | |
| 10358 | JIM_NOTUSED(privdata); |
| 10359 | |
| 10360 | memcpy(copy, key, sizeof(unsigned long)); |
| 10361 | return copy; |
| 10362 | } |
| 10363 | |
| 10364 | static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2) |
| 10365 | { |
| 10366 | JIM_NOTUSED(privdata); |
| 10367 | |
| 10368 | return memcmp(key1, key2, sizeof(unsigned long)) == 0; |
| 10369 | } |
| 10370 | |
| 10371 | static void JimReferencesHTKeyDestructor(void *privdata, void *key) |
| 10372 | { |
| 10373 | JIM_NOTUSED(privdata); |
| 10374 | |
| 10375 | Jim_Free(key); |
| 10376 | } |
| 10377 | |
| 10378 | static const Jim_HashTableType JimReferencesHashTableType = { |
| 10379 | JimReferencesHTHashFunction, |
| 10380 | JimReferencesHTKeyDup, |
| 10381 | NULL, |
| 10382 | JimReferencesHTKeyCompare, |
| 10383 | JimReferencesHTKeyDestructor, |
| 10384 | JimReferencesHTValDestructor |
| 10385 | }; |
| 10386 | |
| 10387 | |
| 10388 | |
| 10389 | #define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN) |
| 10390 | |
| 10391 | static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id) |
| 10392 | { |
| 10393 | const char *fmt = "<reference.<%s>.%020lu>"; |
| 10394 | |
| 10395 | sprintf(buf, fmt, refPtr->tag, id); |
| 10396 | return JIM_REFERENCE_SPACE; |
| 10397 | } |
| 10398 | |
| 10399 | static void UpdateStringOfReference(struct Jim_Obj *objPtr); |
| 10400 | |
| 10401 | static const Jim_ObjType referenceObjType = { |
| 10402 | "reference", |
| 10403 | NULL, |
| 10404 | NULL, |
| 10405 | UpdateStringOfReference, |
| 10406 | JIM_TYPE_REFERENCES, |
| 10407 | }; |
| 10408 | |
| 10409 | static void UpdateStringOfReference(struct Jim_Obj *objPtr) |
| 10410 | { |
| 10411 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 10412 | |
| 10413 | JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id); |
| 10414 | JimSetStringBytes(objPtr, buf); |
| 10415 | } |
| 10416 | |
| 10417 | static int isrefchar(int c) |
| 10418 | { |
| 10419 | return (c == '_' || isalnum(c)); |
| 10420 | } |
| 10421 | |
| 10422 | static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10423 | { |
| 10424 | unsigned long value; |
| 10425 | int i, len; |
| 10426 | const char *str, *start, *end; |
| 10427 | char refId[21]; |
| 10428 | Jim_Reference *refPtr; |
| 10429 | Jim_HashEntry *he; |
| 10430 | char *endptr; |
| 10431 | |
| 10432 | |
| 10433 | str = Jim_GetString(objPtr, &len); |
| 10434 | |
| 10435 | if (len < JIM_REFERENCE_SPACE) |
| 10436 | goto badformat; |
| 10437 | |
| 10438 | start = str; |
| 10439 | end = str + len - 1; |
| 10440 | while (*start == ' ') |
| 10441 | start++; |
| 10442 | while (*end == ' ' && end > start) |
| 10443 | end--; |
| 10444 | if (end - start + 1 != JIM_REFERENCE_SPACE) |
| 10445 | goto badformat; |
| 10446 | |
| 10447 | if (memcmp(start, "<reference.<", 12) != 0) |
| 10448 | goto badformat; |
| 10449 | if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>') |
| 10450 | goto badformat; |
| 10451 | |
| 10452 | for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { |
| 10453 | if (!isrefchar(start[12 + i])) |
| 10454 | goto badformat; |
| 10455 | } |
| 10456 | |
| 10457 | memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20); |
| 10458 | refId[20] = '\0'; |
| 10459 | |
| 10460 | value = strtoul(refId, &endptr, 10); |
| 10461 | if (JimCheckConversion(refId, endptr) != JIM_OK) |
| 10462 | goto badformat; |
| 10463 | |
| 10464 | he = Jim_FindHashEntry(&interp->references, &value); |
| 10465 | if (he == NULL) { |
| 10466 | Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); |
| 10467 | return JIM_ERR; |
| 10468 | } |
| 10469 | refPtr = Jim_GetHashEntryVal(he); |
| 10470 | |
| 10471 | Jim_FreeIntRep(interp, objPtr); |
| 10472 | objPtr->typePtr = &referenceObjType; |
| 10473 | objPtr->internalRep.refValue.id = value; |
| 10474 | objPtr->internalRep.refValue.refPtr = refPtr; |
| 10475 | return JIM_OK; |
| 10476 | |
| 10477 | badformat: |
| 10478 | Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr); |
| 10479 | return JIM_ERR; |
| 10480 | } |
| 10481 | |
| 10482 | Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr) |
| 10483 | { |
| 10484 | struct Jim_Reference *refPtr; |
| 10485 | unsigned long id; |
| 10486 | Jim_Obj *refObjPtr; |
| 10487 | const char *tag; |
| 10488 | int tagLen, i; |
| 10489 | |
| 10490 | |
| 10491 | Jim_CollectIfNeeded(interp); |
| 10492 | |
| 10493 | refPtr = Jim_Alloc(sizeof(*refPtr)); |
| 10494 | refPtr->objPtr = objPtr; |
| 10495 | Jim_IncrRefCount(objPtr); |
| 10496 | refPtr->finalizerCmdNamePtr = cmdNamePtr; |
| 10497 | if (cmdNamePtr) |
| 10498 | Jim_IncrRefCount(cmdNamePtr); |
| 10499 | id = interp->referenceNextId++; |
| 10500 | Jim_AddHashEntry(&interp->references, &id, refPtr); |
| 10501 | refObjPtr = Jim_NewObj(interp); |
| 10502 | refObjPtr->typePtr = &referenceObjType; |
| 10503 | refObjPtr->bytes = NULL; |
| 10504 | refObjPtr->internalRep.refValue.id = id; |
| 10505 | refObjPtr->internalRep.refValue.refPtr = refPtr; |
| 10506 | interp->referenceNextId++; |
| 10507 | tag = Jim_GetString(tagPtr, &tagLen); |
| 10508 | if (tagLen > JIM_REFERENCE_TAGLEN) |
| 10509 | tagLen = JIM_REFERENCE_TAGLEN; |
| 10510 | for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { |
| 10511 | if (i < tagLen && isrefchar(tag[i])) |
| 10512 | refPtr->tag[i] = tag[i]; |
| 10513 | else |
| 10514 | refPtr->tag[i] = '_'; |
| 10515 | } |
| 10516 | refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0'; |
| 10517 | return refObjPtr; |
| 10518 | } |
| 10519 | |
| 10520 | Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10521 | { |
| 10522 | if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR) |
| 10523 | return NULL; |
| 10524 | return objPtr->internalRep.refValue.refPtr; |
| 10525 | } |
| 10526 | |
| 10527 | int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr) |
| 10528 | { |
| 10529 | Jim_Reference *refPtr; |
| 10530 | |
| 10531 | if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) |
| 10532 | return JIM_ERR; |
| 10533 | Jim_IncrRefCount(cmdNamePtr); |
| 10534 | if (refPtr->finalizerCmdNamePtr) |
| 10535 | Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); |
| 10536 | refPtr->finalizerCmdNamePtr = cmdNamePtr; |
| 10537 | return JIM_OK; |
| 10538 | } |
| 10539 | |
| 10540 | int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr) |
| 10541 | { |
| 10542 | Jim_Reference *refPtr; |
| 10543 | |
| 10544 | if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) |
| 10545 | return JIM_ERR; |
| 10546 | *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr; |
| 10547 | return JIM_OK; |
| 10548 | } |
| 10549 | |
| 10550 | |
| 10551 | |
| 10552 | static const Jim_HashTableType JimRefMarkHashTableType = { |
| 10553 | JimReferencesHTHashFunction, |
| 10554 | JimReferencesHTKeyDup, |
| 10555 | NULL, |
| 10556 | JimReferencesHTKeyCompare, |
| 10557 | JimReferencesHTKeyDestructor, |
| 10558 | NULL |
| 10559 | }; |
| 10560 | |
| 10561 | |
| 10562 | int Jim_Collect(Jim_Interp *interp) |
| 10563 | { |
| 10564 | int collected = 0; |
| 10565 | return collected; |
| 10566 | } |
| 10567 | |
| 10568 | #define JIM_COLLECT_ID_PERIOD 5000 |
| 10569 | #define JIM_COLLECT_TIME_PERIOD 300 |
| 10570 | |
| 10571 | void Jim_CollectIfNeeded(Jim_Interp *interp) |
| 10572 | { |
| 10573 | unsigned long elapsedId; |
| 10574 | int elapsedTime; |
| 10575 | |
| 10576 | elapsedId = interp->referenceNextId - interp->lastCollectId; |
| 10577 | elapsedTime = time(NULL) - interp->lastCollectTime; |
| 10578 | |
| 10579 | |
| 10580 | if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) { |
| 10581 | Jim_Collect(interp); |
| 10582 | } |
| 10583 | } |
| 10584 | #endif |
| 10585 | |
| 10586 | int Jim_IsBigEndian(void) |
| 10587 | { |
| 10588 | union { |
| 10589 | unsigned short s; |
| @@ -10630,11 +10449,11 @@ | |
| 10630 | Jim_IncrRefCount(i->nullScriptObj); |
| 10631 | Jim_IncrRefCount(i->errorProc); |
| 10632 | Jim_IncrRefCount(i->trueObj); |
| 10633 | Jim_IncrRefCount(i->falseObj); |
| 10634 | |
| 10635 | |
| 10636 | Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); |
| 10637 | Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); |
| 10638 | |
| 10639 | Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim"); |
| 10640 | Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); |
| @@ -10652,12 +10471,14 @@ | |
| 10652 | { |
| 10653 | Jim_CallFrame *cf, *cfx; |
| 10654 | |
| 10655 | Jim_Obj *objPtr, *nextObjPtr; |
| 10656 | |
| 10657 | |
| 10658 | for (cf = i->framePtr; cf; cf = cfx) { |
| 10659 | cfx = cf->parent; |
| 10660 | JimFreeCallFrame(i, cf, JIM_FCF_FULL); |
| 10661 | } |
| 10662 | |
| 10663 | Jim_DecrRefCount(i, i->emptyObj); |
| @@ -10684,10 +10505,11 @@ | |
| 10684 | |
| 10685 | printf("\n-------------------------------------\n"); |
| 10686 | printf("Objects still in the free list:\n"); |
| 10687 | while (objPtr) { |
| 10688 | const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; |
| 10689 | |
| 10690 | if (objPtr->bytes && strlen(objPtr->bytes) > 20) { |
| 10691 | printf("%p (%d) %-10s: '%.20s...'\n", |
| 10692 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes); |
| 10693 | } |
| @@ -10705,27 +10527,27 @@ | |
| 10705 | printf("-------------------------------------\n\n"); |
| 10706 | JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); |
| 10707 | } |
| 10708 | #endif |
| 10709 | |
| 10710 | |
| 10711 | objPtr = i->freeList; |
| 10712 | while (objPtr) { |
| 10713 | nextObjPtr = objPtr->nextObjPtr; |
| 10714 | Jim_Free(objPtr); |
| 10715 | objPtr = nextObjPtr; |
| 10716 | } |
| 10717 | |
| 10718 | |
| 10719 | for (cf = i->freeFramesList; cf; cf = cfx) { |
| 10720 | cfx = cf->next; |
| 10721 | if (cf->vars.table) |
| 10722 | Jim_FreeHashTable(&cf->vars); |
| 10723 | Jim_Free(cf); |
| 10724 | } |
| 10725 | |
| 10726 | |
| 10727 | Jim_Free(i); |
| 10728 | } |
| 10729 | |
| 10730 | Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr) |
| 10731 | { |
| @@ -10746,25 +10568,25 @@ | |
| 10746 | else { |
| 10747 | if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) { |
| 10748 | level = -1; |
| 10749 | } |
| 10750 | else { |
| 10751 | |
| 10752 | level = interp->framePtr->level - level; |
| 10753 | } |
| 10754 | } |
| 10755 | } |
| 10756 | else { |
| 10757 | str = "1"; |
| 10758 | level = interp->framePtr->level - 1; |
| 10759 | } |
| 10760 | |
| 10761 | if (level == 0) { |
| 10762 | return interp->topFramePtr; |
| 10763 | } |
| 10764 | if (level > 0) { |
| 10765 | |
| 10766 | for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { |
| 10767 | if (framePtr->level == level) { |
| 10768 | return framePtr; |
| 10769 | } |
| 10770 | } |
| @@ -10779,19 +10601,19 @@ | |
| 10779 | long level; |
| 10780 | Jim_CallFrame *framePtr; |
| 10781 | |
| 10782 | if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { |
| 10783 | if (level <= 0) { |
| 10784 | |
| 10785 | level = interp->framePtr->level + level; |
| 10786 | } |
| 10787 | |
| 10788 | if (level == 0) { |
| 10789 | return interp->topFramePtr; |
| 10790 | } |
| 10791 | |
| 10792 | |
| 10793 | for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { |
| 10794 | if (framePtr->level == level) { |
| 10795 | return framePtr; |
| 10796 | } |
| 10797 | } |
| @@ -10810,11 +10632,11 @@ | |
| 10810 | |
| 10811 | static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) |
| 10812 | { |
| 10813 | int len; |
| 10814 | |
| 10815 | |
| 10816 | Jim_IncrRefCount(stackTraceObj); |
| 10817 | Jim_DecrRefCount(interp, interp->stackTrace); |
| 10818 | interp->stackTrace = stackTraceObj; |
| 10819 | interp->errorFlag = 1; |
| 10820 | |
| @@ -10831,32 +10653,32 @@ | |
| 10831 | { |
| 10832 | if (strcmp(procname, "unknown") == 0) { |
| 10833 | procname = ""; |
| 10834 | } |
| 10835 | if (!*procname && !Jim_Length(fileNameObj)) { |
| 10836 | |
| 10837 | return; |
| 10838 | } |
| 10839 | |
| 10840 | if (Jim_IsShared(interp->stackTrace)) { |
| 10841 | Jim_DecrRefCount(interp, interp->stackTrace); |
| 10842 | interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); |
| 10843 | Jim_IncrRefCount(interp->stackTrace); |
| 10844 | } |
| 10845 | |
| 10846 | |
| 10847 | if (!*procname && Jim_Length(fileNameObj)) { |
| 10848 | |
| 10849 | int len = Jim_ListLength(interp, interp->stackTrace); |
| 10850 | |
| 10851 | if (len >= 3) { |
| 10852 | Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3); |
| 10853 | if (Jim_Length(objPtr)) { |
| 10854 | |
| 10855 | objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2); |
| 10856 | if (Jim_Length(objPtr) == 0) { |
| 10857 | |
| 10858 | ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); |
| 10859 | ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); |
| 10860 | return; |
| 10861 | } |
| 10862 | } |
| @@ -10958,18 +10780,18 @@ | |
| 10958 | { |
| 10959 | jim_wide wideValue; |
| 10960 | const char *str; |
| 10961 | |
| 10962 | if (objPtr->typePtr == &coercedDoubleObjType) { |
| 10963 | |
| 10964 | objPtr->typePtr = &intObjType; |
| 10965 | return JIM_OK; |
| 10966 | } |
| 10967 | |
| 10968 | |
| 10969 | str = Jim_String(objPtr); |
| 10970 | |
| 10971 | if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) { |
| 10972 | if (flags & JIM_ERRMSG) { |
| 10973 | Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr); |
| 10974 | } |
| 10975 | return JIM_ERR; |
| @@ -10976,11 +10798,11 @@ | |
| 10976 | } |
| 10977 | if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) { |
| 10978 | Jim_SetResultString(interp, "Integer value too big to be represented", -1); |
| 10979 | return JIM_ERR; |
| 10980 | } |
| 10981 | |
| 10982 | Jim_FreeIntRep(interp, objPtr); |
| 10983 | objPtr->typePtr = &intObjType; |
| 10984 | objPtr->internalRep.wideValue = wideValue; |
| 10985 | return JIM_OK; |
| 10986 | } |
| @@ -11075,17 +10897,17 @@ | |
| 11075 | { |
| 11076 | char buf[JIM_DOUBLE_SPACE + 1]; |
| 11077 | int i; |
| 11078 | int len = sprintf(buf, "%.12g", value); |
| 11079 | |
| 11080 | |
| 11081 | for (i = 0; i < len; i++) { |
| 11082 | if (buf[i] == '.' || buf[i] == 'e') { |
| 11083 | #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) |
| 11084 | char *e = strchr(buf, 'e'); |
| 11085 | if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { |
| 11086 | |
| 11087 | e += 2; |
| 11088 | memmove(e, e + 1, len - (e - buf)); |
| 11089 | } |
| 11090 | #endif |
| 11091 | break; |
| @@ -11104,41 +10926,40 @@ | |
| 11104 | { |
| 11105 | double doubleValue; |
| 11106 | jim_wide wideValue; |
| 11107 | const char *str; |
| 11108 | |
| 11109 | str = Jim_String(objPtr); |
| 11110 | |
| 11111 | #ifdef HAVE_LONG_LONG |
| 11112 | |
| 11113 | #define MIN_INT_IN_DOUBLE -(1LL << 53) |
| 11114 | #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) |
| 11115 | |
| 11116 | if (objPtr->typePtr == &intObjType |
| 11117 | && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE |
| 11118 | && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { |
| 11119 | |
| 11120 | |
| 11121 | objPtr->typePtr = &coercedDoubleObjType; |
| 11122 | return JIM_OK; |
| 11123 | } |
| 11124 | else |
| 11125 | #endif |
| 11126 | if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { |
| 11127 | |
| 11128 | Jim_FreeIntRep(interp, objPtr); |
| 11129 | objPtr->typePtr = &coercedDoubleObjType; |
| 11130 | objPtr->internalRep.wideValue = wideValue; |
| 11131 | return JIM_OK; |
| 11132 | } |
| 11133 | else { |
| 11134 | |
| 11135 | if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) { |
| 11136 | Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr); |
| 11137 | return JIM_ERR; |
| 11138 | } |
| 11139 | |
| 11140 | Jim_FreeIntRep(interp, objPtr); |
| 11141 | } |
| 11142 | objPtr->typePtr = &doubleObjType; |
| 11143 | objPtr->internalRep.doubleValue = doubleValue; |
| 11144 | return JIM_OK; |
| @@ -11170,10 +10991,50 @@ | |
| 11170 | objPtr->typePtr = &doubleObjType; |
| 11171 | objPtr->bytes = NULL; |
| 11172 | objPtr->internalRep.doubleValue = doubleValue; |
| 11173 | return objPtr; |
| 11174 | } |
| 11175 | |
| 11176 | static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec); |
| 11177 | static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); |
| 11178 | static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 11179 | static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| @@ -11221,11 +11082,11 @@ | |
| 11221 | #define JIM_ELESTR_QUOTE 2 |
| 11222 | static unsigned char ListElementQuotingType(const char *s, int len) |
| 11223 | { |
| 11224 | int i, level, blevel, trySimple = 1; |
| 11225 | |
| 11226 | |
| 11227 | if (len == 0) |
| 11228 | return JIM_ELESTR_BRACE; |
| 11229 | if (s[0] == '"' || s[0] == '{') { |
| 11230 | trySimple = 0; |
| 11231 | goto testbrace; |
| @@ -11243,20 +11104,20 @@ | |
| 11243 | case '\n': |
| 11244 | case '\t': |
| 11245 | case '\f': |
| 11246 | case '\v': |
| 11247 | trySimple = 0; |
| 11248 | |
| 11249 | case '{': |
| 11250 | case '}': |
| 11251 | goto testbrace; |
| 11252 | } |
| 11253 | } |
| 11254 | return JIM_ELESTR_SIMPLE; |
| 11255 | |
| 11256 | testbrace: |
| 11257 | |
| 11258 | if (s[len - 1] == '\\') |
| 11259 | return JIM_ELESTR_QUOTE; |
| 11260 | level = 0; |
| 11261 | blevel = 0; |
| 11262 | for (i = 0; i < len; i++) { |
| @@ -11372,11 +11233,11 @@ | |
| 11372 | int i, bufLen, realLength; |
| 11373 | const char *strRep; |
| 11374 | char *p; |
| 11375 | unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN]; |
| 11376 | |
| 11377 | |
| 11378 | if (objc > STATIC_QUOTING_LEN) { |
| 11379 | quotingType = Jim_Alloc(objc); |
| 11380 | } |
| 11381 | else { |
| 11382 | quotingType = staticQuoting; |
| @@ -11391,25 +11252,25 @@ | |
| 11391 | case JIM_ELESTR_SIMPLE: |
| 11392 | if (i != 0 || strRep[0] != '#') { |
| 11393 | bufLen += len; |
| 11394 | break; |
| 11395 | } |
| 11396 | |
| 11397 | quotingType[i] = JIM_ELESTR_BRACE; |
| 11398 | |
| 11399 | case JIM_ELESTR_BRACE: |
| 11400 | bufLen += len + 2; |
| 11401 | break; |
| 11402 | case JIM_ELESTR_QUOTE: |
| 11403 | bufLen += len * 2; |
| 11404 | break; |
| 11405 | } |
| 11406 | bufLen++; |
| 11407 | } |
| 11408 | bufLen++; |
| 11409 | |
| 11410 | |
| 11411 | p = objPtr->bytes = Jim_Alloc(bufLen + 1); |
| 11412 | realLength = 0; |
| 11413 | for (i = 0; i < objc; i++) { |
| 11414 | int len, qlen; |
| 11415 | |
| @@ -11436,17 +11297,17 @@ | |
| 11436 | qlen = BackslashQuoteString(strRep, len, p); |
| 11437 | p += qlen; |
| 11438 | realLength += qlen; |
| 11439 | break; |
| 11440 | } |
| 11441 | |
| 11442 | if (i + 1 != objc) { |
| 11443 | *p++ = ' '; |
| 11444 | realLength++; |
| 11445 | } |
| 11446 | } |
| 11447 | *p = '\0'; |
| 11448 | objPtr->length = realLength; |
| 11449 | |
| 11450 | if (quotingType != staticQuoting) { |
| 11451 | Jim_Free(quotingType); |
| 11452 | } |
| @@ -11477,21 +11338,21 @@ | |
| 11477 | listObjPtrPtr = JimDictPairs(objPtr, &len); |
| 11478 | for (i = 0; i < len; i++) { |
| 11479 | Jim_IncrRefCount(listObjPtrPtr[i]); |
| 11480 | } |
| 11481 | |
| 11482 | |
| 11483 | Jim_FreeIntRep(interp, objPtr); |
| 11484 | objPtr->typePtr = &listObjType; |
| 11485 | objPtr->internalRep.listValue.len = len; |
| 11486 | objPtr->internalRep.listValue.maxLen = len; |
| 11487 | objPtr->internalRep.listValue.ele = listObjPtrPtr; |
| 11488 | |
| 11489 | return JIM_OK; |
| 11490 | } |
| 11491 | |
| 11492 | |
| 11493 | if (objPtr->typePtr == &sourceObjType) { |
| 11494 | fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 11495 | linenr = objPtr->internalRep.sourceValue.lineNumber; |
| 11496 | } |
| 11497 | else { |
| @@ -11498,20 +11359,20 @@ | |
| 11498 | fileNameObj = interp->emptyObj; |
| 11499 | linenr = 1; |
| 11500 | } |
| 11501 | Jim_IncrRefCount(fileNameObj); |
| 11502 | |
| 11503 | |
| 11504 | str = Jim_GetString(objPtr, &strLen); |
| 11505 | |
| 11506 | Jim_FreeIntRep(interp, objPtr); |
| 11507 | objPtr->typePtr = &listObjType; |
| 11508 | objPtr->internalRep.listValue.len = 0; |
| 11509 | objPtr->internalRep.listValue.maxLen = 0; |
| 11510 | objPtr->internalRep.listValue.ele = NULL; |
| 11511 | |
| 11512 | |
| 11513 | if (strLen) { |
| 11514 | JimParserInit(&parser, str, strLen, linenr); |
| 11515 | while (!parser.eof) { |
| 11516 | Jim_Obj *elementPtr; |
| 11517 | |
| @@ -11641,11 +11502,11 @@ | |
| 11641 | Jim_Obj *compare_script; |
| 11642 | int rc; |
| 11643 | |
| 11644 | jim_wide ret = 0; |
| 11645 | |
| 11646 | |
| 11647 | compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command); |
| 11648 | Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj); |
| 11649 | Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj); |
| 11650 | |
| 11651 | rc = Jim_EvalObj(sort_info->interp, compare_script); |
| @@ -11663,23 +11524,27 @@ | |
| 11663 | int dst = 0; |
| 11664 | Jim_Obj **ele = listObjPtr->internalRep.listValue.ele; |
| 11665 | |
| 11666 | for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) { |
| 11667 | if (comp(&ele[dst], &ele[src]) == 0) { |
| 11668 | |
| 11669 | Jim_DecrRefCount(sort_info->interp, ele[dst]); |
| 11670 | } |
| 11671 | else { |
| 11672 | |
| 11673 | dst++; |
| 11674 | } |
| 11675 | ele[dst] = ele[src]; |
| 11676 | } |
| 11677 | |
| 11678 | ele[++dst] = ele[src]; |
| 11679 | |
| 11680 | |
| 11681 | listObjPtr->internalRep.listValue.len = dst; |
| 11682 | } |
| 11683 | |
| 11684 | |
| 11685 | static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
| @@ -11693,11 +11558,11 @@ | |
| 11693 | int rc; |
| 11694 | |
| 11695 | JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); |
| 11696 | SetListFromAny(interp, listObjPtr); |
| 11697 | |
| 11698 | |
| 11699 | prev_info = sort_info; |
| 11700 | sort_info = info; |
| 11701 | |
| 11702 | vector = listObjPtr->internalRep.listValue.ele; |
| 11703 | len = listObjPtr->internalRep.listValue.len; |
| @@ -11716,17 +11581,17 @@ | |
| 11716 | break; |
| 11717 | case JIM_LSORT_COMMAND: |
| 11718 | fn = ListSortCommand; |
| 11719 | break; |
| 11720 | default: |
| 11721 | fn = NULL; |
| 11722 | JimPanic((1, "ListSort called with invalid sort type")); |
| 11723 | return -1; |
| 11724 | } |
| 11725 | |
| 11726 | if (info->indexed) { |
| 11727 | |
| 11728 | info->subfn = fn; |
| 11729 | fn = ListSortIndexHelper; |
| 11730 | } |
| 11731 | |
| 11732 | if ((rc = setjmp(info->jmpbuf)) == 0) { |
| @@ -11750,11 +11615,11 @@ | |
| 11750 | int i; |
| 11751 | Jim_Obj **point; |
| 11752 | |
| 11753 | if (requiredLen > listPtr->internalRep.listValue.maxLen) { |
| 11754 | if (requiredLen < 2) { |
| 11755 | |
| 11756 | requiredLen = 4; |
| 11757 | } |
| 11758 | else { |
| 11759 | requiredLen *= 2; |
| 11760 | } |
| @@ -11936,34 +11801,34 @@ | |
| 11936 | for (i = 0; i < objc; i++) |
| 11937 | ListAppendList(objPtr, objv[i]); |
| 11938 | return objPtr; |
| 11939 | } |
| 11940 | else { |
| 11941 | |
| 11942 | int len = 0, objLen; |
| 11943 | char *bytes, *p; |
| 11944 | |
| 11945 | |
| 11946 | for (i = 0; i < objc; i++) { |
| 11947 | len += Jim_Length(objv[i]); |
| 11948 | } |
| 11949 | if (objc) |
| 11950 | len += objc - 1; |
| 11951 | |
| 11952 | p = bytes = Jim_Alloc(len + 1); |
| 11953 | for (i = 0; i < objc; i++) { |
| 11954 | const char *s = Jim_GetString(objv[i], &objLen); |
| 11955 | |
| 11956 | |
| 11957 | while (objLen && isspace(UCHAR(*s))) { |
| 11958 | s++; |
| 11959 | objLen--; |
| 11960 | len--; |
| 11961 | } |
| 11962 | |
| 11963 | while (objLen && isspace(UCHAR(s[objLen - 1]))) { |
| 11964 | |
| 11965 | if (objLen > 1 && s[objLen - 2] == '\\') { |
| 11966 | break; |
| 11967 | } |
| 11968 | objLen--; |
| 11969 | len--; |
| @@ -11990,11 +11855,11 @@ | |
| 11990 | int len, rangeLen; |
| 11991 | |
| 11992 | if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || |
| 11993 | Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) |
| 11994 | return NULL; |
| 11995 | len = Jim_ListLength(interp, listObjPtr); |
| 11996 | first = JimRelToAbsIndex(len, first); |
| 11997 | last = JimRelToAbsIndex(len, last); |
| 11998 | JimRelToAbsRange(len, &first, &last, &rangeLen); |
| 11999 | if (first == 0 && last == len) { |
| 12000 | return listObjPtr; |
| @@ -12030,16 +11895,16 @@ | |
| 12030 | { |
| 12031 | Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 12032 | } |
| 12033 | |
| 12034 | static const Jim_HashTableType JimDictHashTableType = { |
| 12035 | JimObjectHTHashFunction, |
| 12036 | JimObjectHTKeyValDup, |
| 12037 | JimObjectHTKeyValDup, |
| 12038 | JimObjectHTKeyCompare, |
| 12039 | JimObjectHTKeyValDestructor, |
| 12040 | JimObjectHTKeyValDestructor |
| 12041 | }; |
| 12042 | |
| 12043 | static const Jim_ObjType dictObjType = { |
| 12044 | "dict", |
| 12045 | FreeDictInternalRep, |
| @@ -12060,17 +11925,17 @@ | |
| 12060 | { |
| 12061 | Jim_HashTable *ht, *dupHt; |
| 12062 | Jim_HashTableIterator htiter; |
| 12063 | Jim_HashEntry *he; |
| 12064 | |
| 12065 | |
| 12066 | ht = srcPtr->internalRep.ptr; |
| 12067 | dupHt = Jim_Alloc(sizeof(*dupHt)); |
| 12068 | Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); |
| 12069 | if (ht->size != 0) |
| 12070 | Jim_ExpandHashTable(dupHt, ht->size); |
| 12071 | |
| 12072 | JimInitHashTableIterator(ht, &htiter); |
| 12073 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 12074 | Jim_AddHashEntry(dupHt, he->key, he->u.val); |
| 12075 | } |
| 12076 | |
| @@ -12086,11 +11951,11 @@ | |
| 12086 | Jim_Obj **objv; |
| 12087 | int i; |
| 12088 | |
| 12089 | ht = dictPtr->internalRep.ptr; |
| 12090 | |
| 12091 | |
| 12092 | objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 12093 | JimInitHashTableIterator(ht, &htiter); |
| 12094 | i = 0; |
| 12095 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 12096 | objv[i++] = Jim_GetHashEntryKey(he); |
| @@ -12100,15 +11965,15 @@ | |
| 12100 | return objv; |
| 12101 | } |
| 12102 | |
| 12103 | static void UpdateStringOfDict(struct Jim_Obj *objPtr) |
| 12104 | { |
| 12105 | |
| 12106 | int len; |
| 12107 | Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 12108 | |
| 12109 | |
| 12110 | JimMakeListStringRep(objPtr, objv, len); |
| 12111 | |
| 12112 | Jim_Free(objv); |
| 12113 | } |
| 12114 | |
| @@ -12122,18 +11987,18 @@ | |
| 12122 | |
| 12123 | if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { |
| 12124 | Jim_String(objPtr); |
| 12125 | } |
| 12126 | |
| 12127 | |
| 12128 | listlen = Jim_ListLength(interp, objPtr); |
| 12129 | if (listlen % 2) { |
| 12130 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| 12131 | return JIM_ERR; |
| 12132 | } |
| 12133 | else { |
| 12134 | |
| 12135 | Jim_HashTable *ht; |
| 12136 | int i; |
| 12137 | |
| 12138 | ht = Jim_Alloc(sizeof(*ht)); |
| 12139 | Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| @@ -12158,11 +12023,11 @@ | |
| 12158 | static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 12159 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 12160 | { |
| 12161 | Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 12162 | |
| 12163 | if (valueObjPtr == NULL) { |
| 12164 | return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 12165 | } |
| 12166 | Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); |
| 12167 | return JIM_OK; |
| 12168 | } |
| @@ -12209,12 +12074,14 @@ | |
| 12209 | if (flags & JIM_ERRMSG) { |
| 12210 | Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr); |
| 12211 | } |
| 12212 | return JIM_ERR; |
| 12213 | } |
| 12214 | *objPtrPtr = he->u.val; |
| 12215 | return JIM_OK; |
| 12216 | } |
| 12217 | |
| 12218 | |
| 12219 | int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) |
| 12220 | { |
| @@ -12258,11 +12125,11 @@ | |
| 12258 | int shared, i; |
| 12259 | |
| 12260 | varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags); |
| 12261 | if (objPtr == NULL) { |
| 12262 | if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) { |
| 12263 | |
| 12264 | return JIM_ERR; |
| 12265 | } |
| 12266 | varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 12267 | if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) { |
| 12268 | Jim_FreeNewObj(interp, varObjPtr); |
| @@ -12272,26 +12139,26 @@ | |
| 12272 | if ((shared = Jim_IsShared(objPtr))) |
| 12273 | varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); |
| 12274 | for (i = 0; i < keyc; i++) { |
| 12275 | dictObjPtr = objPtr; |
| 12276 | |
| 12277 | |
| 12278 | if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) { |
| 12279 | goto err; |
| 12280 | } |
| 12281 | |
| 12282 | if (i == keyc - 1) { |
| 12283 | |
| 12284 | if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) { |
| 12285 | if (newObjPtr || (flags & JIM_MUSTEXIST)) { |
| 12286 | goto err; |
| 12287 | } |
| 12288 | } |
| 12289 | break; |
| 12290 | } |
| 12291 | |
| 12292 | |
| 12293 | Jim_InvalidateStringRep(dictObjPtr); |
| 12294 | if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr, |
| 12295 | newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) { |
| 12296 | if (Jim_IsShared(objPtr)) { |
| 12297 | objPtr = Jim_DuplicateObj(interp, objPtr); |
| @@ -12304,11 +12171,11 @@ | |
| 12304 | } |
| 12305 | objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 12306 | DictAddElement(interp, dictObjPtr, keyv[i], objPtr); |
| 12307 | } |
| 12308 | } |
| 12309 | |
| 12310 | Jim_InvalidateStringRep(objPtr); |
| 12311 | Jim_InvalidateStringRep(varObjPtr); |
| 12312 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 12313 | goto err; |
| 12314 | } |
| @@ -12341,11 +12208,11 @@ | |
| 12341 | char buf[JIM_INTEGER_SPACE + 1]; |
| 12342 | if (objPtr->internalRep.intValue >= 0) { |
| 12343 | sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 12344 | } |
| 12345 | else { |
| 12346 | |
| 12347 | sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| 12348 | } |
| 12349 | JimSetStringBytes(objPtr, buf); |
| 12350 | } |
| 12351 | } |
| @@ -12354,14 +12221,14 @@ | |
| 12354 | { |
| 12355 | int idx, end = 0; |
| 12356 | const char *str; |
| 12357 | char *endptr; |
| 12358 | |
| 12359 | |
| 12360 | str = Jim_String(objPtr); |
| 12361 | |
| 12362 | |
| 12363 | if (strncmp(str, "end", 3) == 0) { |
| 12364 | end = 1; |
| 12365 | str += 3; |
| 12366 | idx = 0; |
| 12367 | } |
| @@ -12372,21 +12239,21 @@ | |
| 12372 | goto badindex; |
| 12373 | } |
| 12374 | str = endptr; |
| 12375 | } |
| 12376 | |
| 12377 | |
| 12378 | if (*str == '+' || *str == '-') { |
| 12379 | int sign = (*str == '+' ? 1 : -1); |
| 12380 | |
| 12381 | idx += sign * jim_strtol(++str, &endptr); |
| 12382 | if (str == endptr || *endptr) { |
| 12383 | goto badindex; |
| 12384 | } |
| 12385 | str = endptr; |
| 12386 | } |
| 12387 | |
| 12388 | while (isspace(UCHAR(*str))) { |
| 12389 | str++; |
| 12390 | } |
| 12391 | if (*str) { |
| 12392 | goto badindex; |
| @@ -12394,19 +12261,19 @@ | |
| 12394 | if (end) { |
| 12395 | if (idx > 0) { |
| 12396 | idx = INT_MAX; |
| 12397 | } |
| 12398 | else { |
| 12399 | |
| 12400 | idx--; |
| 12401 | } |
| 12402 | } |
| 12403 | else if (idx < 0) { |
| 12404 | idx = -INT_MAX; |
| 12405 | } |
| 12406 | |
| 12407 | |
| 12408 | Jim_FreeIntRep(interp, objPtr); |
| 12409 | objPtr->typePtr = &indexObjType; |
| 12410 | objPtr->internalRep.intValue = idx; |
| 12411 | return JIM_OK; |
| 12412 | |
| @@ -12416,11 +12283,11 @@ | |
| 12416 | return JIM_ERR; |
| 12417 | } |
| 12418 | |
| 12419 | int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) |
| 12420 | { |
| 12421 | |
| 12422 | if (objPtr->typePtr == &intObjType) { |
| 12423 | jim_wide val = JimWideValue(objPtr); |
| 12424 | |
| 12425 | if (val < 0) |
| 12426 | *indexPtr = -INT_MAX; |
| @@ -12448,11 +12315,11 @@ | |
| 12448 | "exit", |
| 12449 | "eval", |
| 12450 | NULL |
| 12451 | }; |
| 12452 | |
| 12453 | #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) |
| 12454 | |
| 12455 | static const Jim_ObjType returnCodeObjType = { |
| 12456 | "return-code", |
| 12457 | NULL, |
| 12458 | NULL, |
| @@ -12473,18 +12340,18 @@ | |
| 12473 | static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12474 | { |
| 12475 | int returnCode; |
| 12476 | jim_wide wideValue; |
| 12477 | |
| 12478 | |
| 12479 | if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR) |
| 12480 | returnCode = (int)wideValue; |
| 12481 | else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) { |
| 12482 | Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr); |
| 12483 | return JIM_ERR; |
| 12484 | } |
| 12485 | |
| 12486 | Jim_FreeIntRep(interp, objPtr); |
| 12487 | objPtr->typePtr = &returnCodeObjType; |
| 12488 | objPtr->internalRep.intValue = returnCode; |
| 12489 | return JIM_OK; |
| 12490 | } |
| @@ -12498,19 +12365,19 @@ | |
| 12498 | } |
| 12499 | |
| 12500 | static int JimParseExprOperator(struct JimParserCtx *pc); |
| 12501 | static int JimParseExprNumber(struct JimParserCtx *pc); |
| 12502 | static int JimParseExprIrrational(struct JimParserCtx *pc); |
| 12503 | |
| 12504 | |
| 12505 | |
| 12506 | |
| 12507 | enum |
| 12508 | { |
| 12509 | |
| 12510 | |
| 12511 | JIM_EXPROP_MUL = JIM_TT_EXPR_OP, |
| 12512 | JIM_EXPROP_DIV, |
| 12513 | JIM_EXPROP_MOD, |
| 12514 | JIM_EXPROP_SUB, |
| 12515 | JIM_EXPROP_ADD, |
| 12516 | JIM_EXPROP_LSHIFT, |
| @@ -12521,66 +12388,48 @@ | |
| 12521 | JIM_EXPROP_GT, |
| 12522 | JIM_EXPROP_LTE, |
| 12523 | JIM_EXPROP_GTE, |
| 12524 | JIM_EXPROP_NUMEQ, |
| 12525 | JIM_EXPROP_NUMNE, |
| 12526 | JIM_EXPROP_BITAND, |
| 12527 | JIM_EXPROP_BITXOR, |
| 12528 | JIM_EXPROP_BITOR, |
| 12529 | |
| 12530 | |
| 12531 | JIM_EXPROP_LOGICAND, |
| 12532 | JIM_EXPROP_LOGICAND_LEFT, |
| 12533 | JIM_EXPROP_LOGICAND_RIGHT, |
| 12534 | |
| 12535 | |
| 12536 | JIM_EXPROP_LOGICOR, |
| 12537 | JIM_EXPROP_LOGICOR_LEFT, |
| 12538 | JIM_EXPROP_LOGICOR_RIGHT, |
| 12539 | |
| 12540 | |
| 12541 | |
| 12542 | JIM_EXPROP_TERNARY, |
| 12543 | JIM_EXPROP_TERNARY_LEFT, |
| 12544 | JIM_EXPROP_TERNARY_RIGHT, |
| 12545 | |
| 12546 | |
| 12547 | JIM_EXPROP_COLON, |
| 12548 | JIM_EXPROP_COLON_LEFT, |
| 12549 | JIM_EXPROP_COLON_RIGHT, |
| 12550 | |
| 12551 | JIM_EXPROP_POW, |
| 12552 | |
| 12553 | |
| 12554 | JIM_EXPROP_STREQ, |
| 12555 | JIM_EXPROP_STRNE, |
| 12556 | JIM_EXPROP_STRIN, |
| 12557 | JIM_EXPROP_STRNI, |
| 12558 | |
| 12559 | |
| 12560 | JIM_EXPROP_NOT, |
| 12561 | JIM_EXPROP_BITNOT, |
| 12562 | JIM_EXPROP_UNARYMINUS, |
| 12563 | JIM_EXPROP_UNARYPLUS, |
| 12564 | |
| 12565 | |
| 12566 | JIM_EXPROP_FUNC_FIRST, |
| 12567 | JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST, |
| 12568 | JIM_EXPROP_FUNC_WIDE, |
| 12569 | JIM_EXPROP_FUNC_ABS, |
| 12570 | JIM_EXPROP_FUNC_DOUBLE, |
| 12571 | JIM_EXPROP_FUNC_ROUND, |
| 12572 | JIM_EXPROP_FUNC_RAND, |
| 12573 | JIM_EXPROP_FUNC_SRAND, |
| 12574 | |
| 12575 | |
| 12576 | JIM_EXPROP_FUNC_SIN, |
| 12577 | JIM_EXPROP_FUNC_COS, |
| 12578 | JIM_EXPROP_FUNC_TAN, |
| 12579 | JIM_EXPROP_FUNC_ASIN, |
| 12580 | JIM_EXPROP_FUNC_ACOS, |
| 12581 | JIM_EXPROP_FUNC_ATAN, |
| 12582 | JIM_EXPROP_FUNC_SINH, |
| 12583 | JIM_EXPROP_FUNC_COSH, |
| 12584 | JIM_EXPROP_FUNC_TANH, |
| 12585 | JIM_EXPROP_FUNC_CEIL, |
| 12586 | JIM_EXPROP_FUNC_FLOOR, |
| @@ -12587,52 +12436,52 @@ | |
| 12587 | JIM_EXPROP_FUNC_EXP, |
| 12588 | JIM_EXPROP_FUNC_LOG, |
| 12589 | JIM_EXPROP_FUNC_LOG10, |
| 12590 | JIM_EXPROP_FUNC_SQRT, |
| 12591 | JIM_EXPROP_FUNC_POW, |
| 12592 | }; |
| 12593 | |
| 12594 | struct JimExprState |
| 12595 | { |
| 12596 | Jim_Obj **stack; |
| 12597 | int stacklen; |
| 12598 | int opcode; |
| 12599 | int skip; |
| 12600 | }; |
| 12601 | |
| 12602 | |
| 12603 | typedef struct Jim_ExprOperator |
| 12604 | { |
| 12605 | const char *name; |
| 12606 | int (*funcop) (Jim_Interp *interp, struct JimExprState * e); |
| 12607 | unsigned char precedence; |
| 12608 | unsigned char arity; |
| 12609 | unsigned char lazy; |
| 12610 | unsigned char namelen; |
| 12611 | } Jim_ExprOperator; |
| 12612 | |
| 12613 | static void ExprPush(struct JimExprState *e, Jim_Obj *obj) |
| 12614 | { |
| 12615 | Jim_IncrRefCount(obj); |
| 12616 | e->stack[e->stacklen++] = obj; |
| 12617 | } |
| 12618 | |
| 12619 | static Jim_Obj *ExprPop(struct JimExprState *e) |
| 12620 | { |
| 12621 | return e->stack[--e->stacklen]; |
| 12622 | } |
| 12623 | |
| 12624 | static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) |
| 12625 | { |
| 12626 | int intresult = 1; |
| 12627 | int rc = JIM_OK; |
| 12628 | Jim_Obj *A = ExprPop(e); |
| 12629 | double dA, dC = 0; |
| 12630 | jim_wide wA, wC = 0; |
| 12631 | |
| 12632 | if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { |
| 12633 | switch (e->opcode) { |
| 12634 | case JIM_EXPROP_FUNC_INT: |
| 12635 | case JIM_EXPROP_FUNC_WIDE: |
| 12636 | case JIM_EXPROP_FUNC_ROUND: |
| 12637 | case JIM_EXPROP_UNARYPLUS: |
| 12638 | wC = wA; |
| @@ -12653,11 +12502,11 @@ | |
| 12653 | default: |
| 12654 | abort(); |
| 12655 | } |
| 12656 | } |
| 12657 | else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { |
| 12658 | switch (e->opcode) { |
| 12659 | case JIM_EXPROP_FUNC_INT: |
| 12660 | case JIM_EXPROP_FUNC_WIDE: |
| 12661 | wC = dA; |
| 12662 | break; |
| 12663 | case JIM_EXPROP_FUNC_ROUND: |
| @@ -12667,11 +12516,15 @@ | |
| 12667 | case JIM_EXPROP_UNARYPLUS: |
| 12668 | dC = dA; |
| 12669 | intresult = 0; |
| 12670 | break; |
| 12671 | case JIM_EXPROP_FUNC_ABS: |
| 12672 | dC = dA >= 0 ? dA : -dA; |
| 12673 | intresult = 0; |
| 12674 | break; |
| 12675 | case JIM_EXPROP_UNARYMINUS: |
| 12676 | dC = -dA; |
| 12677 | intresult = 0; |
| @@ -12684,14 +12537,14 @@ | |
| 12684 | } |
| 12685 | } |
| 12686 | |
| 12687 | if (rc == JIM_OK) { |
| 12688 | if (intresult) { |
| 12689 | ExprPush(e, Jim_NewIntObj(interp, wC)); |
| 12690 | } |
| 12691 | else { |
| 12692 | ExprPush(e, Jim_NewDoubleObj(interp, dC)); |
| 12693 | } |
| 12694 | } |
| 12695 | |
| 12696 | Jim_DecrRefCount(interp, A); |
| 12697 | |
| @@ -12704,24 +12557,29 @@ | |
| 12704 | JimRandomBytes(interp, &x, sizeof(x)); |
| 12705 | |
| 12706 | return (double)x / (unsigned long)~0; |
| 12707 | } |
| 12708 | |
| 12709 | static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e) |
| 12710 | { |
| 12711 | Jim_Obj *A = ExprPop(e); |
| 12712 | jim_wide wA; |
| 12713 | |
| 12714 | int rc = Jim_GetWide(interp, A, &wA); |
| 12715 | if (rc == JIM_OK) { |
| 12716 | switch (e->opcode) { |
| 12717 | case JIM_EXPROP_BITNOT: |
| 12718 | ExprPush(e, Jim_NewIntObj(interp, ~wA)); |
| 12719 | break; |
| 12720 | case JIM_EXPROP_FUNC_SRAND: |
| 12721 | JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); |
| 12722 | ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); |
| 12723 | break; |
| 12724 | default: |
| 12725 | abort(); |
| 12726 | } |
| 12727 | } |
| @@ -12729,29 +12587,33 @@ | |
| 12729 | Jim_DecrRefCount(interp, A); |
| 12730 | |
| 12731 | return rc; |
| 12732 | } |
| 12733 | |
| 12734 | static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e) |
| 12735 | { |
| 12736 | JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); |
| 12737 | |
| 12738 | ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); |
| 12739 | |
| 12740 | return JIM_OK; |
| 12741 | } |
| 12742 | |
| 12743 | #ifdef JIM_MATH_FUNCTIONS |
| 12744 | static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e) |
| 12745 | { |
| 12746 | int rc; |
| 12747 | Jim_Obj *A = ExprPop(e); |
| 12748 | double dA, dC; |
| 12749 | |
| 12750 | rc = Jim_GetDouble(interp, A, &dA); |
| 12751 | if (rc == JIM_OK) { |
| 12752 | switch (e->opcode) { |
| 12753 | case JIM_EXPROP_FUNC_SIN: |
| 12754 | dC = sin(dA); |
| 12755 | break; |
| 12756 | case JIM_EXPROP_FUNC_COS: |
| 12757 | dC = cos(dA); |
| @@ -12796,33 +12658,42 @@ | |
| 12796 | dC = sqrt(dA); |
| 12797 | break; |
| 12798 | default: |
| 12799 | abort(); |
| 12800 | } |
| 12801 | ExprPush(e, Jim_NewDoubleObj(interp, dC)); |
| 12802 | } |
| 12803 | |
| 12804 | Jim_DecrRefCount(interp, A); |
| 12805 | |
| 12806 | return rc; |
| 12807 | } |
| 12808 | #endif |
| 12809 | |
| 12810 | |
| 12811 | static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e) |
| 12812 | { |
| 12813 | Jim_Obj *B = ExprPop(e); |
| 12814 | Jim_Obj *A = ExprPop(e); |
| 12815 | jim_wide wA, wB; |
| 12816 | int rc = JIM_ERR; |
| 12817 | |
| 12818 | if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { |
| 12819 | jim_wide wC; |
| 12820 | |
| 12821 | rc = JIM_OK; |
| 12822 | |
| 12823 | switch (e->opcode) { |
| 12824 | case JIM_EXPROP_LSHIFT: |
| 12825 | wC = wA << wB; |
| 12826 | break; |
| 12827 | case JIM_EXPROP_RSHIFT: |
| 12828 | wC = wA >> wB; |
| @@ -12859,29 +12730,28 @@ | |
| 12859 | } |
| 12860 | } |
| 12861 | break; |
| 12862 | case JIM_EXPROP_ROTL: |
| 12863 | case JIM_EXPROP_ROTR:{ |
| 12864 | |
| 12865 | unsigned long uA = (unsigned long)wA; |
| 12866 | unsigned long uB = (unsigned long)wB; |
| 12867 | const unsigned int S = sizeof(unsigned long) * 8; |
| 12868 | |
| 12869 | |
| 12870 | uB %= S; |
| 12871 | |
| 12872 | if (e->opcode == JIM_EXPROP_ROTR) { |
| 12873 | uB = S - uB; |
| 12874 | } |
| 12875 | wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); |
| 12876 | break; |
| 12877 | } |
| 12878 | default: |
| 12879 | abort(); |
| 12880 | } |
| 12881 | ExprPush(e, Jim_NewIntObj(interp, wC)); |
| 12882 | |
| 12883 | } |
| 12884 | |
| 12885 | Jim_DecrRefCount(interp, A); |
| 12886 | Jim_DecrRefCount(interp, B); |
| 12887 | |
| @@ -12888,44 +12758,55 @@ | |
| 12888 | return rc; |
| 12889 | } |
| 12890 | |
| 12891 | |
| 12892 | |
| 12893 | static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) |
| 12894 | { |
| 12895 | int intresult = 1; |
| 12896 | int rc = JIM_OK; |
| 12897 | double dA, dB, dC = 0; |
| 12898 | jim_wide wA, wB, wC = 0; |
| 12899 | |
| 12900 | Jim_Obj *B = ExprPop(e); |
| 12901 | Jim_Obj *A = ExprPop(e); |
| 12902 | |
| 12903 | if ((A->typePtr != &doubleObjType || A->bytes) && |
| 12904 | (B->typePtr != &doubleObjType || B->bytes) && |
| 12905 | JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { |
| 12906 | |
| 12907 | |
| 12908 | |
| 12909 | switch (e->opcode) { |
| 12910 | case JIM_EXPROP_POW: |
| 12911 | case JIM_EXPROP_FUNC_POW: |
| 12912 | wC = JimPowWide(wA, wB); |
| 12913 | break; |
| 12914 | case JIM_EXPROP_ADD: |
| 12915 | wC = wA + wB; |
| 12916 | break; |
| 12917 | case JIM_EXPROP_SUB: |
| 12918 | wC = wA - wB; |
| 12919 | break; |
| 12920 | case JIM_EXPROP_MUL: |
| 12921 | wC = wA * wB; |
| 12922 | break; |
| 12923 | case JIM_EXPROP_DIV: |
| 12924 | if (wB == 0) { |
| 12925 | Jim_SetResultString(interp, "Division by zero", -1); |
| 12926 | rc = JIM_ERR; |
| 12927 | } |
| 12928 | else { |
| 12929 | if (wB < 0) { |
| 12930 | wB = -wB; |
| 12931 | wA = -wA; |
| @@ -12932,55 +12813,67 @@ | |
| 12932 | } |
| 12933 | wC = wA / wB; |
| 12934 | if (wA % wB < 0) { |
| 12935 | wC--; |
| 12936 | } |
| 12937 | } |
| 12938 | break; |
| 12939 | case JIM_EXPROP_LT: |
| 12940 | wC = wA < wB; |
| 12941 | break; |
| 12942 | case JIM_EXPROP_GT: |
| 12943 | wC = wA > wB; |
| 12944 | break; |
| 12945 | case JIM_EXPROP_LTE: |
| 12946 | wC = wA <= wB; |
| 12947 | break; |
| 12948 | case JIM_EXPROP_GTE: |
| 12949 | wC = wA >= wB; |
| 12950 | break; |
| 12951 | case JIM_EXPROP_NUMEQ: |
| 12952 | wC = wA == wB; |
| 12953 | break; |
| 12954 | case JIM_EXPROP_NUMNE: |
| 12955 | wC = wA != wB; |
| 12956 | break; |
| 12957 | default: |
| 12958 | abort(); |
| 12959 | } |
| 12960 | } |
| 12961 | else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { |
| 12962 | intresult = 0; |
| 12963 | switch (e->opcode) { |
| 12964 | case JIM_EXPROP_POW: |
| 12965 | case JIM_EXPROP_FUNC_POW: |
| 12966 | #ifdef JIM_MATH_FUNCTIONS |
| 12967 | dC = pow(dA, dB); |
| 12968 | #else |
| 12969 | Jim_SetResultString(interp, "unsupported", -1); |
| 12970 | rc = JIM_ERR; |
| 12971 | #endif |
| 12972 | break; |
| 12973 | case JIM_EXPROP_ADD: |
| 12974 | dC = dA + dB; |
| 12975 | break; |
| 12976 | case JIM_EXPROP_SUB: |
| 12977 | dC = dA - dB; |
| 12978 | break; |
| 12979 | case JIM_EXPROP_MUL: |
| 12980 | dC = dA * dB; |
| 12981 | break; |
| 12982 | case JIM_EXPROP_DIV: |
| 12983 | if (dB == 0) { |
| 12984 | #ifdef INFINITY |
| 12985 | dC = dA < 0 ? -INFINITY : INFINITY; |
| 12986 | #else |
| @@ -12988,83 +12881,70 @@ | |
| 12988 | #endif |
| 12989 | } |
| 12990 | else { |
| 12991 | dC = dA / dB; |
| 12992 | } |
| 12993 | break; |
| 12994 | case JIM_EXPROP_LT: |
| 12995 | wC = dA < dB; |
| 12996 | intresult = 1; |
| 12997 | break; |
| 12998 | case JIM_EXPROP_GT: |
| 12999 | wC = dA > dB; |
| 13000 | intresult = 1; |
| 13001 | break; |
| 13002 | case JIM_EXPROP_LTE: |
| 13003 | wC = dA <= dB; |
| 13004 | intresult = 1; |
| 13005 | break; |
| 13006 | case JIM_EXPROP_GTE: |
| 13007 | wC = dA >= dB; |
| 13008 | intresult = 1; |
| 13009 | break; |
| 13010 | case JIM_EXPROP_NUMEQ: |
| 13011 | wC = dA == dB; |
| 13012 | intresult = 1; |
| 13013 | break; |
| 13014 | case JIM_EXPROP_NUMNE: |
| 13015 | wC = dA != dB; |
| 13016 | intresult = 1; |
| 13017 | break; |
| 13018 | default: |
| 13019 | abort(); |
| 13020 | } |
| 13021 | } |
| 13022 | else { |
| 13023 | |
| 13024 | |
| 13025 | |
| 13026 | int i = Jim_StringCompareObj(interp, A, B, 0); |
| 13027 | |
| 13028 | switch (e->opcode) { |
| 13029 | case JIM_EXPROP_LT: |
| 13030 | wC = i < 0; |
| 13031 | break; |
| 13032 | case JIM_EXPROP_GT: |
| 13033 | wC = i > 0; |
| 13034 | break; |
| 13035 | case JIM_EXPROP_LTE: |
| 13036 | wC = i <= 0; |
| 13037 | break; |
| 13038 | case JIM_EXPROP_GTE: |
| 13039 | wC = i >= 0; |
| 13040 | break; |
| 13041 | case JIM_EXPROP_NUMEQ: |
| 13042 | wC = i == 0; |
| 13043 | break; |
| 13044 | case JIM_EXPROP_NUMNE: |
| 13045 | wC = i != 0; |
| 13046 | break; |
| 13047 | default: |
| 13048 | rc = JIM_ERR; |
| 13049 | break; |
| 13050 | } |
| 13051 | } |
| 13052 | |
| 13053 | if (rc == JIM_OK) { |
| 13054 | if (intresult) { |
| 13055 | ExprPush(e, Jim_NewIntObj(interp, wC)); |
| 13056 | } |
| 13057 | else { |
| 13058 | ExprPush(e, Jim_NewDoubleObj(interp, dC)); |
| 13059 | } |
| 13060 | } |
| 13061 | |
| 13062 | Jim_DecrRefCount(interp, A); |
| 13063 | Jim_DecrRefCount(interp, B); |
| 13064 | |
| 13065 | return rc; |
| 13066 | } |
| 13067 | |
| 13068 | static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) |
| 13069 | { |
| 13070 | int listlen; |
| @@ -13077,22 +12957,31 @@ | |
| 13077 | } |
| 13078 | } |
| 13079 | return 0; |
| 13080 | } |
| 13081 | |
| 13082 | static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e) |
| 13083 | { |
| 13084 | Jim_Obj *B = ExprPop(e); |
| 13085 | Jim_Obj *A = ExprPop(e); |
| 13086 | |
| 13087 | jim_wide wC; |
| 13088 | |
| 13089 | switch (e->opcode) { |
| 13090 | case JIM_EXPROP_STREQ: |
| 13091 | case JIM_EXPROP_STRNE: |
| 13092 | wC = Jim_StringEqObj(A, B); |
| 13093 | if (e->opcode == JIM_EXPROP_STRNE) { |
| 13094 | wC = !wC; |
| 13095 | } |
| 13096 | break; |
| 13097 | case JIM_EXPROP_STRIN: |
| 13098 | wC = JimSearchList(interp, B, A); |
| @@ -13101,178 +12990,99 @@ | |
| 13101 | wC = !JimSearchList(interp, B, A); |
| 13102 | break; |
| 13103 | default: |
| 13104 | abort(); |
| 13105 | } |
| 13106 | ExprPush(e, Jim_NewIntObj(interp, wC)); |
| 13107 | |
| 13108 | Jim_DecrRefCount(interp, A); |
| 13109 | Jim_DecrRefCount(interp, B); |
| 13110 | |
| 13111 | return JIM_OK; |
| 13112 | } |
| 13113 | |
| 13114 | static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) |
| 13115 | { |
| 13116 | long l; |
| 13117 | double d; |
| 13118 | |
| 13119 | if (Jim_GetLong(interp, obj, &l) == JIM_OK) { |
| 13120 | return l != 0; |
| 13121 | } |
| 13122 | if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { |
| 13123 | return d != 0; |
| 13124 | } |
| 13125 | return -1; |
| 13126 | } |
| 13127 | |
| 13128 | static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e) |
| 13129 | { |
| 13130 | Jim_Obj *skip = ExprPop(e); |
| 13131 | Jim_Obj *A = ExprPop(e); |
| 13132 | int rc = JIM_OK; |
| 13133 | |
| 13134 | switch (ExprBool(interp, A)) { |
| 13135 | case 0: |
| 13136 | |
| 13137 | e->skip = JimWideValue(skip); |
| 13138 | ExprPush(e, Jim_NewIntObj(interp, 0)); |
| 13139 | break; |
| 13140 | |
| 13141 | case 1: |
| 13142 | |
| 13143 | break; |
| 13144 | |
| 13145 | case -1: |
| 13146 | |
| 13147 | rc = JIM_ERR; |
| 13148 | } |
| 13149 | Jim_DecrRefCount(interp, A); |
| 13150 | Jim_DecrRefCount(interp, skip); |
| 13151 | |
| 13152 | return rc; |
| 13153 | } |
| 13154 | |
| 13155 | static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e) |
| 13156 | { |
| 13157 | Jim_Obj *skip = ExprPop(e); |
| 13158 | Jim_Obj *A = ExprPop(e); |
| 13159 | int rc = JIM_OK; |
| 13160 | |
| 13161 | switch (ExprBool(interp, A)) { |
| 13162 | case 0: |
| 13163 | |
| 13164 | break; |
| 13165 | |
| 13166 | case 1: |
| 13167 | |
| 13168 | e->skip = JimWideValue(skip); |
| 13169 | ExprPush(e, Jim_NewIntObj(interp, 1)); |
| 13170 | break; |
| 13171 | |
| 13172 | case -1: |
| 13173 | |
| 13174 | rc = JIM_ERR; |
| 13175 | break; |
| 13176 | } |
| 13177 | Jim_DecrRefCount(interp, A); |
| 13178 | Jim_DecrRefCount(interp, skip); |
| 13179 | |
| 13180 | return rc; |
| 13181 | } |
| 13182 | |
| 13183 | static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e) |
| 13184 | { |
| 13185 | Jim_Obj *A = ExprPop(e); |
| 13186 | int rc = JIM_OK; |
| 13187 | |
| 13188 | switch (ExprBool(interp, A)) { |
| 13189 | case 0: |
| 13190 | ExprPush(e, Jim_NewIntObj(interp, 0)); |
| 13191 | break; |
| 13192 | |
| 13193 | case 1: |
| 13194 | ExprPush(e, Jim_NewIntObj(interp, 1)); |
| 13195 | break; |
| 13196 | |
| 13197 | case -1: |
| 13198 | |
| 13199 | rc = JIM_ERR; |
| 13200 | break; |
| 13201 | } |
| 13202 | Jim_DecrRefCount(interp, A); |
| 13203 | |
| 13204 | return rc; |
| 13205 | } |
| 13206 | |
| 13207 | static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e) |
| 13208 | { |
| 13209 | Jim_Obj *skip = ExprPop(e); |
| 13210 | Jim_Obj *A = ExprPop(e); |
| 13211 | int rc = JIM_OK; |
| 13212 | |
| 13213 | |
| 13214 | ExprPush(e, A); |
| 13215 | |
| 13216 | switch (ExprBool(interp, A)) { |
| 13217 | case 0: |
| 13218 | |
| 13219 | e->skip = JimWideValue(skip); |
| 13220 | |
| 13221 | ExprPush(e, Jim_NewIntObj(interp, 0)); |
| 13222 | break; |
| 13223 | |
| 13224 | case 1: |
| 13225 | |
| 13226 | break; |
| 13227 | |
| 13228 | case -1: |
| 13229 | |
| 13230 | rc = JIM_ERR; |
| 13231 | break; |
| 13232 | } |
| 13233 | Jim_DecrRefCount(interp, A); |
| 13234 | Jim_DecrRefCount(interp, skip); |
| 13235 | |
| 13236 | return rc; |
| 13237 | } |
| 13238 | |
| 13239 | static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e) |
| 13240 | { |
| 13241 | Jim_Obj *skip = ExprPop(e); |
| 13242 | Jim_Obj *B = ExprPop(e); |
| 13243 | Jim_Obj *A = ExprPop(e); |
| 13244 | |
| 13245 | |
| 13246 | if (ExprBool(interp, A)) { |
| 13247 | |
| 13248 | e->skip = JimWideValue(skip); |
| 13249 | |
| 13250 | ExprPush(e, B); |
| 13251 | } |
| 13252 | |
| 13253 | Jim_DecrRefCount(interp, skip); |
| 13254 | Jim_DecrRefCount(interp, A); |
| 13255 | Jim_DecrRefCount(interp, B); |
| 13256 | return JIM_OK; |
| 13257 | } |
| 13258 | |
| 13259 | static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e) |
| 13260 | { |
| 13261 | return JIM_OK; |
| 13262 | } |
| 13263 | |
| 13264 | enum |
| 13265 | { |
| 13266 | LAZY_NONE, |
| 13267 | LAZY_OP, |
| 13268 | LAZY_LEFT, |
| 13269 | LAZY_RIGHT |
| 13270 | }; |
| 13271 | |
| 13272 | #define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1} |
| 13273 | #define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} |
| 13274 | |
| 13275 | static const struct Jim_ExprOperator Jim_ExprOperators[] = { |
| 13276 | OPRINIT("*", 110, 2, JimExprOpBin), |
| 13277 | OPRINIT("/", 110, 2, JimExprOpBin), |
| 13278 | OPRINIT("%", 110, 2, JimExprOpIntBin), |
| @@ -13296,86 +13106,79 @@ | |
| 13296 | |
| 13297 | OPRINIT("&", 50, 2, JimExprOpIntBin), |
| 13298 | OPRINIT("^", 49, 2, JimExprOpIntBin), |
| 13299 | OPRINIT("|", 48, 2, JimExprOpIntBin), |
| 13300 | |
| 13301 | OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP), |
| 13302 | OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), |
| 13303 | OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 13304 | |
| 13305 | OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP), |
| 13306 | OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), |
| 13307 | OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), |
| 13308 | |
| 13309 | OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP), |
| 13310 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), |
| 13311 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 13312 | |
| 13313 | OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP), |
| 13314 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), |
| 13315 | OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), |
| 13316 | |
| 13317 | OPRINIT("**", 250, 2, JimExprOpBin), |
| 13318 | |
| 13319 | OPRINIT("eq", 60, 2, JimExprOpStrBin), |
| 13320 | OPRINIT("ne", 60, 2, JimExprOpStrBin), |
| 13321 | |
| 13322 | OPRINIT("in", 55, 2, JimExprOpStrBin), |
| 13323 | OPRINIT("ni", 55, 2, JimExprOpStrBin), |
| 13324 | |
| 13325 | OPRINIT("!", 150, 1, JimExprOpNumUnary), |
| 13326 | OPRINIT("~", 150, 1, JimExprOpIntUnary), |
| 13327 | OPRINIT(NULL, 150, 1, JimExprOpNumUnary), |
| 13328 | OPRINIT(NULL, 150, 1, JimExprOpNumUnary), |
| 13329 | |
| 13330 | |
| 13331 | |
| 13332 | OPRINIT("int", 200, 1, JimExprOpNumUnary), |
| 13333 | OPRINIT("wide", 200, 1, JimExprOpNumUnary), |
| 13334 | OPRINIT("abs", 200, 1, JimExprOpNumUnary), |
| 13335 | OPRINIT("double", 200, 1, JimExprOpNumUnary), |
| 13336 | OPRINIT("round", 200, 1, JimExprOpNumUnary), |
| 13337 | OPRINIT("rand", 200, 0, JimExprOpNone), |
| 13338 | OPRINIT("srand", 200, 1, JimExprOpIntUnary), |
| 13339 | |
| 13340 | #ifdef JIM_MATH_FUNCTIONS |
| 13341 | OPRINIT("sin", 200, 1, JimExprOpDoubleUnary), |
| 13342 | OPRINIT("cos", 200, 1, JimExprOpDoubleUnary), |
| 13343 | OPRINIT("tan", 200, 1, JimExprOpDoubleUnary), |
| 13344 | OPRINIT("asin", 200, 1, JimExprOpDoubleUnary), |
| 13345 | OPRINIT("acos", 200, 1, JimExprOpDoubleUnary), |
| 13346 | OPRINIT("atan", 200, 1, JimExprOpDoubleUnary), |
| 13347 | OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary), |
| 13348 | OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary), |
| 13349 | OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary), |
| 13350 | OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary), |
| 13351 | OPRINIT("floor", 200, 1, JimExprOpDoubleUnary), |
| 13352 | OPRINIT("exp", 200, 1, JimExprOpDoubleUnary), |
| 13353 | OPRINIT("log", 200, 1, JimExprOpDoubleUnary), |
| 13354 | OPRINIT("log10", 200, 1, JimExprOpDoubleUnary), |
| 13355 | OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary), |
| 13356 | OPRINIT("pow", 200, 2, JimExprOpBin), |
| 13357 | #endif |
| 13358 | }; |
| 13359 | #undef OPRINIT |
| 13360 | #undef OPRINIT_LAZY |
| 13361 | |
| 13362 | #define JIM_EXPR_OPERATORS_NUM \ |
| 13363 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 13364 | |
| 13365 | static int JimParseExpression(struct JimParserCtx *pc) |
| 13366 | { |
| 13367 | |
| 13368 | while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { |
| 13369 | if (*pc->p == '\n') { |
| 13370 | pc->linenr++; |
| 13371 | } |
| 13372 | pc->p++; |
| 13373 | pc->len--; |
| 13374 | } |
| 13375 | |
| 13376 | |
| 13377 | pc->tline = pc->linenr; |
| 13378 | pc->tstart = pc->p; |
| 13379 | |
| 13380 | if (pc->len == 0) { |
| 13381 | pc->tend = pc->p; |
| @@ -13401,11 +13204,11 @@ | |
| 13401 | return JimParseCmd(pc); |
| 13402 | case '$': |
| 13403 | if (JimParseVar(pc) == JIM_ERR) |
| 13404 | return JimParseExprOperator(pc); |
| 13405 | else { |
| 13406 | |
| 13407 | if (pc->tt == JIM_TT_EXPRSUGAR) { |
| 13408 | return JIM_ERR; |
| 13409 | } |
| 13410 | return JIM_OK; |
| 13411 | } |
| @@ -13430,10 +13233,18 @@ | |
| 13430 | case 'N': |
| 13431 | case 'I': |
| 13432 | case 'n': |
| 13433 | case 'i': |
| 13434 | if (JimParseExprIrrational(pc) == JIM_ERR) |
| 13435 | return JimParseExprOperator(pc); |
| 13436 | break; |
| 13437 | default: |
| 13438 | return JimParseExprOperator(pc); |
| 13439 | break; |
| @@ -13443,21 +13254,21 @@ | |
| 13443 | |
| 13444 | static int JimParseExprNumber(struct JimParserCtx *pc) |
| 13445 | { |
| 13446 | char *end; |
| 13447 | |
| 13448 | |
| 13449 | pc->tt = JIM_TT_EXPR_INT; |
| 13450 | |
| 13451 | jim_strtoull(pc->p, (char **)&pc->p); |
| 13452 | |
| 13453 | if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { |
| 13454 | if (strtod(pc->tstart, &end)) { } |
| 13455 | if (end == pc->tstart) |
| 13456 | return JIM_ERR; |
| 13457 | if (end > pc->p) { |
| 13458 | |
| 13459 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13460 | pc->p = end; |
| 13461 | } |
| 13462 | } |
| 13463 | pc->tend = pc->p - 1; |
| @@ -13481,36 +13292,66 @@ | |
| 13481 | return JIM_OK; |
| 13482 | } |
| 13483 | } |
| 13484 | return JIM_ERR; |
| 13485 | } |
| 13486 | |
| 13487 | static int JimParseExprOperator(struct JimParserCtx *pc) |
| 13488 | { |
| 13489 | int i; |
| 13490 | int bestIdx = -1, bestLen = 0; |
| 13491 | |
| 13492 | |
| 13493 | for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { |
| 13494 | const char * const opname = Jim_ExprOperators[i].name; |
| 13495 | const int oplen = Jim_ExprOperators[i].namelen; |
| 13496 | |
| 13497 | if (opname == NULL || opname[0] != pc->p[0]) { |
| 13498 | continue; |
| 13499 | } |
| 13500 | |
| 13501 | if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) { |
| 13502 | bestIdx = i + JIM_TT_EXPR_OP; |
| 13503 | bestLen = oplen; |
| 13504 | } |
| 13505 | } |
| 13506 | if (bestIdx == -1) { |
| 13507 | return JIM_ERR; |
| 13508 | } |
| 13509 | |
| 13510 | |
| 13511 | if (bestIdx >= JIM_EXPROP_FUNC_FIRST) { |
| 13512 | const char *p = pc->p + bestLen; |
| 13513 | int len = pc->len - bestLen; |
| 13514 | |
| 13515 | while (len && isspace(UCHAR(*p))) { |
| 13516 | len--; |
| @@ -13522,30 +13363,27 @@ | |
| 13522 | } |
| 13523 | pc->tend = pc->p + bestLen - 1; |
| 13524 | pc->p += bestLen; |
| 13525 | pc->len -= bestLen; |
| 13526 | |
| 13527 | pc->tt = bestIdx; |
| 13528 | return JIM_OK; |
| 13529 | } |
| 13530 | |
| 13531 | static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) |
| 13532 | { |
| 13533 | static Jim_ExprOperator dummy_op; |
| 13534 | if (opcode < JIM_TT_EXPR_OP) { |
| 13535 | return &dummy_op; |
| 13536 | } |
| 13537 | return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP]; |
| 13538 | } |
| 13539 | |
| 13540 | const char *jim_tt_name(int type) |
| 13541 | { |
| 13542 | static const char * const tt_names[JIM_TT_EXPR_OP] = |
| 13543 | { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", |
| 13544 | "DBL", "$()" }; |
| 13545 | if (type < JIM_TT_EXPR_OP) { |
| 13546 | return tt_names[type]; |
| 13547 | } |
| 13548 | else { |
| 13549 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type); |
| 13550 | static char buf[20]; |
| 13551 | |
| @@ -13568,432 +13406,400 @@ | |
| 13568 | NULL, |
| 13569 | JIM_TYPE_REFERENCES, |
| 13570 | }; |
| 13571 | |
| 13572 | |
| 13573 | typedef struct ExprByteCode |
| 13574 | { |
| 13575 | ScriptToken *token; |
| 13576 | int len; |
| 13577 | int inUse; |
| 13578 | } ExprByteCode; |
| 13579 | |
| 13580 | static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) |
| 13581 | { |
| 13582 | int i; |
| 13583 | |
| 13584 | for (i = 0; i < expr->len; i++) { |
| 13585 | Jim_DecrRefCount(interp, expr->token[i].objPtr); |
| 13586 | } |
| 13587 | Jim_Free(expr->token); |
| 13588 | Jim_Free(expr); |
| 13589 | } |
| 13590 | |
| 13591 | static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13592 | { |
| 13593 | ExprByteCode *expr = (void *)objPtr->internalRep.ptr; |
| 13594 | |
| 13595 | if (expr) { |
| 13596 | if (--expr->inUse != 0) { |
| 13597 | return; |
| 13598 | } |
| 13599 | |
| 13600 | ExprFreeByteCode(interp, expr); |
| 13601 | } |
| 13602 | } |
| 13603 | |
| 13604 | static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 13605 | { |
| 13606 | JIM_NOTUSED(interp); |
| 13607 | JIM_NOTUSED(srcPtr); |
| 13608 | |
| 13609 | |
| 13610 | dupPtr->typePtr = NULL; |
| 13611 | } |
| 13612 | |
| 13613 | |
| 13614 | static int ExprCheckCorrectness(ExprByteCode * expr) |
| 13615 | { |
| 13616 | int i; |
| 13617 | int stacklen = 0; |
| 13618 | int ternary = 0; |
| 13619 | |
| 13620 | for (i = 0; i < expr->len; i++) { |
| 13621 | ScriptToken *t = &expr->token[i]; |
| 13622 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); |
| 13623 | |
| 13624 | stacklen -= op->arity; |
| 13625 | if (stacklen < 0) { |
| 13626 | break; |
| 13627 | } |
| 13628 | if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) { |
| 13629 | ternary++; |
| 13630 | } |
| 13631 | else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) { |
| 13632 | ternary--; |
| 13633 | } |
| 13634 | |
| 13635 | |
| 13636 | stacklen++; |
| 13637 | } |
| 13638 | if (stacklen != 1 || ternary != 0) { |
| 13639 | return JIM_ERR; |
| 13640 | } |
| 13641 | return JIM_OK; |
| 13642 | } |
| 13643 | |
| 13644 | static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) |
| 13645 | { |
| 13646 | int i; |
| 13647 | |
| 13648 | int leftindex, arity, offset; |
| 13649 | |
| 13650 | |
| 13651 | leftindex = expr->len - 1; |
| 13652 | |
| 13653 | arity = 1; |
| 13654 | while (arity) { |
| 13655 | ScriptToken *tt = &expr->token[leftindex]; |
| 13656 | |
| 13657 | if (tt->type >= JIM_TT_EXPR_OP) { |
| 13658 | arity += JimExprOperatorInfoByOpcode(tt->type)->arity; |
| 13659 | } |
| 13660 | arity--; |
| 13661 | if (--leftindex < 0) { |
| 13662 | return JIM_ERR; |
| 13663 | } |
| 13664 | } |
| 13665 | leftindex++; |
| 13666 | |
| 13667 | |
| 13668 | memmove(&expr->token[leftindex + 2], &expr->token[leftindex], |
| 13669 | sizeof(*expr->token) * (expr->len - leftindex)); |
| 13670 | expr->len += 2; |
| 13671 | offset = (expr->len - leftindex) - 1; |
| 13672 | |
| 13673 | expr->token[leftindex + 1].type = t->type + 1; |
| 13674 | expr->token[leftindex + 1].objPtr = interp->emptyObj; |
| 13675 | |
| 13676 | expr->token[leftindex].type = JIM_TT_EXPR_INT; |
| 13677 | expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset); |
| 13678 | |
| 13679 | |
| 13680 | expr->token[expr->len].objPtr = interp->emptyObj; |
| 13681 | expr->token[expr->len].type = t->type + 2; |
| 13682 | expr->len++; |
| 13683 | |
| 13684 | |
| 13685 | for (i = leftindex - 1; i > 0; i--) { |
| 13686 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type); |
| 13687 | if (op->lazy == LAZY_LEFT) { |
| 13688 | if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) { |
| 13689 | JimWideValue(expr->token[i - 1].objPtr) += 2; |
| 13690 | } |
| 13691 | } |
| 13692 | } |
| 13693 | return JIM_OK; |
| 13694 | } |
| 13695 | |
| 13696 | static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) |
| 13697 | { |
| 13698 | struct ScriptToken *token = &expr->token[expr->len]; |
| 13699 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); |
| 13700 | |
| 13701 | if (op->lazy == LAZY_OP) { |
| 13702 | if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) { |
| 13703 | Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name); |
| 13704 | return JIM_ERR; |
| 13705 | } |
| 13706 | } |
| 13707 | else { |
| 13708 | token->objPtr = interp->emptyObj; |
| 13709 | token->type = t->type; |
| 13710 | expr->len++; |
| 13711 | } |
| 13712 | return JIM_OK; |
| 13713 | } |
| 13714 | |
| 13715 | static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index) |
| 13716 | { |
| 13717 | int ternary_count = 1; |
| 13718 | |
| 13719 | right_index--; |
| 13720 | |
| 13721 | while (right_index > 1) { |
| 13722 | if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) { |
| 13723 | ternary_count--; |
| 13724 | } |
| 13725 | else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) { |
| 13726 | ternary_count++; |
| 13727 | } |
| 13728 | else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) { |
| 13729 | return right_index; |
| 13730 | } |
| 13731 | right_index--; |
| 13732 | } |
| 13733 | |
| 13734 | |
| 13735 | return -1; |
| 13736 | } |
| 13737 | |
| 13738 | static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index) |
| 13739 | { |
| 13740 | int i = right_index - 1; |
| 13741 | int ternary_count = 1; |
| 13742 | |
| 13743 | while (i > 1) { |
| 13744 | if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) { |
| 13745 | if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) { |
| 13746 | *prev_right_index = i - 2; |
| 13747 | *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index); |
| 13748 | return 1; |
| 13749 | } |
| 13750 | } |
| 13751 | else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) { |
| 13752 | if (ternary_count == 0) { |
| 13753 | return 0; |
| 13754 | } |
| 13755 | ternary_count++; |
| 13756 | } |
| 13757 | i--; |
| 13758 | } |
| 13759 | return 0; |
| 13760 | } |
| 13761 | |
| 13762 | static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr) |
| 13763 | { |
| 13764 | int i; |
| 13765 | |
| 13766 | for (i = expr->len - 1; i > 1; i--) { |
| 13767 | int prev_right_index; |
| 13768 | int prev_left_index; |
| 13769 | int j; |
| 13770 | ScriptToken tmp; |
| 13771 | |
| 13772 | if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) { |
| 13773 | continue; |
| 13774 | } |
| 13775 | |
| 13776 | |
| 13777 | if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) { |
| 13778 | continue; |
| 13779 | } |
| 13780 | |
| 13781 | tmp = expr->token[prev_right_index]; |
| 13782 | for (j = prev_right_index; j < i; j++) { |
| 13783 | expr->token[j] = expr->token[j + 1]; |
| 13784 | } |
| 13785 | expr->token[i] = tmp; |
| 13786 | |
| 13787 | JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index); |
| 13788 | |
| 13789 | |
| 13790 | i++; |
| 13791 | } |
| 13792 | } |
| 13793 | |
| 13794 | static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj) |
| 13795 | { |
| 13796 | Jim_Stack stack; |
| 13797 | ExprByteCode *expr; |
| 13798 | int ok = 1; |
| 13799 | int i; |
| 13800 | int prevtt = JIM_TT_NONE; |
| 13801 | int have_ternary = 0; |
| 13802 | |
| 13803 | |
| 13804 | int count = tokenlist->count - 1; |
| 13805 | |
| 13806 | expr = Jim_Alloc(sizeof(*expr)); |
| 13807 | expr->inUse = 1; |
| 13808 | expr->len = 0; |
| 13809 | |
| 13810 | Jim_InitStack(&stack); |
| 13811 | |
| 13812 | for (i = 0; i < tokenlist->count; i++) { |
| 13813 | ParseToken *t = &tokenlist->list[i]; |
| 13814 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); |
| 13815 | |
| 13816 | if (op->lazy == LAZY_OP) { |
| 13817 | count += 2; |
| 13818 | |
| 13819 | if (t->type == JIM_EXPROP_TERNARY) { |
| 13820 | have_ternary = 1; |
| 13821 | } |
| 13822 | } |
| 13823 | } |
| 13824 | |
| 13825 | expr->token = Jim_Alloc(sizeof(ScriptToken) * count); |
| 13826 | |
| 13827 | for (i = 0; i < tokenlist->count && ok; i++) { |
| 13828 | ParseToken *t = &tokenlist->list[i]; |
| 13829 | |
| 13830 | |
| 13831 | struct ScriptToken *token = &expr->token[expr->len]; |
| 13832 | |
| 13833 | if (t->type == JIM_TT_EOL) { |
| 13834 | break; |
| 13835 | } |
| 13836 | |
| 13837 | switch (t->type) { |
| 13838 | case JIM_TT_STR: |
| 13839 | case JIM_TT_ESC: |
| 13840 | case JIM_TT_VAR: |
| 13841 | case JIM_TT_DICTSUGAR: |
| 13842 | case JIM_TT_EXPRSUGAR: |
| 13843 | case JIM_TT_CMD: |
| 13844 | token->type = t->type; |
| 13845 | strexpr: |
| 13846 | token->objPtr = Jim_NewStringObj(interp, t->token, t->len); |
| 13847 | if (t->type == JIM_TT_CMD) { |
| 13848 | |
| 13849 | JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line); |
| 13850 | } |
| 13851 | expr->len++; |
| 13852 | break; |
| 13853 | |
| 13854 | case JIM_TT_EXPR_INT: |
| 13855 | case JIM_TT_EXPR_DOUBLE: |
| 13856 | { |
| 13857 | char *endptr; |
| 13858 | if (t->type == JIM_TT_EXPR_INT) { |
| 13859 | token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr)); |
| 13860 | } |
| 13861 | else { |
| 13862 | token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr)); |
| 13863 | } |
| 13864 | if (endptr != t->token + t->len) { |
| 13865 | |
| 13866 | Jim_FreeNewObj(interp, token->objPtr); |
| 13867 | token->type = JIM_TT_STR; |
| 13868 | goto strexpr; |
| 13869 | } |
| 13870 | token->type = t->type; |
| 13871 | expr->len++; |
| 13872 | } |
| 13873 | break; |
| 13874 | |
| 13875 | case JIM_TT_SUBEXPR_START: |
| 13876 | Jim_StackPush(&stack, t); |
| 13877 | prevtt = JIM_TT_NONE; |
| 13878 | continue; |
| 13879 | |
| 13880 | case JIM_TT_SUBEXPR_COMMA: |
| 13881 | |
| 13882 | continue; |
| 13883 | |
| 13884 | case JIM_TT_SUBEXPR_END: |
| 13885 | ok = 0; |
| 13886 | while (Jim_StackLen(&stack)) { |
| 13887 | ParseToken *tt = Jim_StackPop(&stack); |
| 13888 | |
| 13889 | if (tt->type == JIM_TT_SUBEXPR_START) { |
| 13890 | ok = 1; |
| 13891 | break; |
| 13892 | } |
| 13893 | |
| 13894 | if (ExprAddOperator(interp, expr, tt) != JIM_OK) { |
| 13895 | goto err; |
| 13896 | } |
| 13897 | } |
| 13898 | if (!ok) { |
| 13899 | Jim_SetResultString(interp, "Unexpected close parenthesis", -1); |
| 13900 | goto err; |
| 13901 | } |
| 13902 | break; |
| 13903 | |
| 13904 | |
| 13905 | default:{ |
| 13906 | |
| 13907 | const struct Jim_ExprOperator *op; |
| 13908 | ParseToken *tt; |
| 13909 | |
| 13910 | |
| 13911 | if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) { |
| 13912 | if (t->type == JIM_EXPROP_SUB) { |
| 13913 | t->type = JIM_EXPROP_UNARYMINUS; |
| 13914 | } |
| 13915 | else if (t->type == JIM_EXPROP_ADD) { |
| 13916 | t->type = JIM_EXPROP_UNARYPLUS; |
| 13917 | } |
| 13918 | } |
| 13919 | |
| 13920 | op = JimExprOperatorInfoByOpcode(t->type); |
| 13921 | |
| 13922 | |
| 13923 | while ((tt = Jim_StackPeek(&stack)) != NULL) { |
| 13924 | const struct Jim_ExprOperator *tt_op = |
| 13925 | JimExprOperatorInfoByOpcode(tt->type); |
| 13926 | |
| 13927 | |
| 13928 | |
| 13929 | if (op->arity != 1 && tt_op->precedence >= op->precedence) { |
| 13930 | if (ExprAddOperator(interp, expr, tt) != JIM_OK) { |
| 13931 | ok = 0; |
| 13932 | goto err; |
| 13933 | } |
| 13934 | Jim_StackPop(&stack); |
| 13935 | } |
| 13936 | else { |
| 13937 | break; |
| 13938 | } |
| 13939 | } |
| 13940 | Jim_StackPush(&stack, t); |
| 13941 | break; |
| 13942 | } |
| 13943 | } |
| 13944 | prevtt = t->type; |
| 13945 | } |
| 13946 | |
| 13947 | |
| 13948 | while (Jim_StackLen(&stack)) { |
| 13949 | ParseToken *tt = Jim_StackPop(&stack); |
| 13950 | |
| 13951 | if (tt->type == JIM_TT_SUBEXPR_START) { |
| 13952 | ok = 0; |
| 13953 | Jim_SetResultString(interp, "Missing close parenthesis", -1); |
| 13954 | goto err; |
| 13955 | } |
| 13956 | if (ExprAddOperator(interp, expr, tt) != JIM_OK) { |
| 13957 | ok = 0; |
| 13958 | goto err; |
| 13959 | } |
| 13960 | } |
| 13961 | |
| 13962 | if (have_ternary) { |
| 13963 | ExprTernaryReorderExpression(interp, expr); |
| 13964 | } |
| 13965 | |
| 13966 | err: |
| 13967 | |
| 13968 | Jim_FreeStack(&stack); |
| 13969 | |
| 13970 | for (i = 0; i < expr->len; i++) { |
| 13971 | Jim_IncrRefCount(expr->token[i].objPtr); |
| 13972 | } |
| 13973 | |
| 13974 | if (!ok) { |
| 13975 | ExprFreeByteCode(interp, expr); |
| 13976 | return NULL; |
| 13977 | } |
| 13978 | |
| 13979 | return expr; |
| 13980 | } |
| 13981 | |
| 13982 | |
| 13983 | static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) |
| 13984 | { |
| 13985 | int exprTextLen; |
| 13986 | const char *exprText; |
| 13987 | struct JimParserCtx parser; |
| 13988 | struct ExprByteCode *expr; |
| 13989 | ParseTokenList tokenlist; |
| 13990 | int line; |
| 13991 | Jim_Obj *fileNameObj; |
| 13992 | int rc = JIM_ERR; |
| 13993 | |
| 13994 | |
| 13995 | if (objPtr->typePtr == &sourceObjType) { |
| 13996 | fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 13997 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 13998 | } |
| 13999 | else { |
| @@ -14002,18 +13808,17 @@ | |
| 14002 | } |
| 14003 | Jim_IncrRefCount(fileNameObj); |
| 14004 | |
| 14005 | exprText = Jim_GetString(objPtr, &exprTextLen); |
| 14006 | |
| 14007 | |
| 14008 | ScriptTokenListInit(&tokenlist); |
| 14009 | |
| 14010 | JimParserInit(&parser, exprText, exprTextLen, line); |
| 14011 | while (!parser.eof) { |
| 14012 | if (JimParseExpression(&parser) != JIM_OK) { |
| 14013 | ScriptTokenListFree(&tokenlist); |
| 14014 | invalidexpr: |
| 14015 | Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr); |
| 14016 | expr = NULL; |
| 14017 | goto err; |
| 14018 | } |
| 14019 | |
| @@ -14036,125 +13841,174 @@ | |
| 14036 | ScriptTokenListFree(&tokenlist); |
| 14037 | Jim_DecrRefCount(interp, fileNameObj); |
| 14038 | return JIM_ERR; |
| 14039 | } |
| 14040 | |
| 14041 | |
| 14042 | expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); |
| 14043 | |
| 14044 | |
| 14045 | ScriptTokenListFree(&tokenlist); |
| 14046 | |
| 14047 | if (!expr) { |
| 14048 | goto err; |
| 14049 | } |
| 14050 | |
| 14051 | #ifdef DEBUG_SHOW_EXPR |
| 14052 | { |
| 14053 | int i; |
| 14054 | |
| 14055 | printf("==== Expr ====\n"); |
| 14056 | for (i = 0; i < expr->len; i++) { |
| 14057 | ScriptToken *t = &expr->token[i]; |
| 14058 | |
| 14059 | printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); |
| 14060 | } |
| 14061 | } |
| 14062 | #endif |
| 14063 | |
| 14064 | |
| 14065 | if (ExprCheckCorrectness(expr) != JIM_OK) { |
| 14066 | ExprFreeByteCode(interp, expr); |
| 14067 | goto invalidexpr; |
| 14068 | } |
| 14069 | |
| 14070 | rc = JIM_OK; |
| 14071 | |
| 14072 | err: |
| 14073 | |
| 14074 | Jim_DecrRefCount(interp, fileNameObj); |
| 14075 | Jim_FreeIntRep(interp, objPtr); |
| 14076 | Jim_SetIntRepPtr(objPtr, expr); |
| 14077 | objPtr->typePtr = &exprObjType; |
| 14078 | return rc; |
| 14079 | } |
| 14080 | |
| 14081 | static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) |
| 14082 | { |
| 14083 | if (objPtr->typePtr != &exprObjType) { |
| 14084 | if (SetExprFromAny(interp, objPtr) != JIM_OK) { |
| 14085 | return NULL; |
| 14086 | } |
| 14087 | } |
| 14088 | return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); |
| 14089 | } |
| 14090 | |
| 14091 | #ifdef JIM_OPTIMIZATION |
| 14092 | static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token) |
| 14093 | { |
| 14094 | if (token->type == JIM_TT_EXPR_INT) |
| 14095 | return token->objPtr; |
| 14096 | else if (token->type == JIM_TT_VAR) |
| 14097 | return Jim_GetVariable(interp, token->objPtr, JIM_NONE); |
| 14098 | else if (token->type == JIM_TT_DICTSUGAR) |
| 14099 | return JimExpandDictSugar(interp, token->objPtr); |
| 14100 | else |
| 14101 | return NULL; |
| 14102 | } |
| 14103 | #endif |
| 14104 | |
| 14105 | #define JIM_EE_STATICSTACK_LEN 10 |
| 14106 | |
| 14107 | int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) |
| 14108 | { |
| 14109 | ExprByteCode *expr; |
| 14110 | Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN]; |
| 14111 | int i; |
| 14112 | int retcode = JIM_OK; |
| 14113 | struct JimExprState e; |
| 14114 | |
| 14115 | expr = JimGetExpression(interp, exprObjPtr); |
| 14116 | if (!expr) { |
| 14117 | return JIM_ERR; |
| 14118 | } |
| 14119 | |
| 14120 | #ifdef JIM_OPTIMIZATION |
| 14121 | { |
| 14122 | Jim_Obj *objPtr; |
| 14123 | |
| 14124 | |
| 14125 | switch (expr->len) { |
| 14126 | case 1: |
| 14127 | objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 14128 | if (objPtr) { |
| 14129 | Jim_IncrRefCount(objPtr); |
| 14130 | *exprResultPtrPtr = objPtr; |
| 14131 | return JIM_OK; |
| 14132 | } |
| 14133 | break; |
| 14134 | |
| 14135 | case 2: |
| 14136 | if (expr->token[1].type == JIM_EXPROP_NOT) { |
| 14137 | objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 14138 | |
| 14139 | if (objPtr && JimIsWide(objPtr)) { |
| 14140 | *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj; |
| 14141 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 14142 | return JIM_OK; |
| 14143 | } |
| 14144 | } |
| 14145 | break; |
| 14146 | |
| 14147 | case 3: |
| 14148 | objPtr = JimExprIntValOrVar(interp, &expr->token[0]); |
| 14149 | if (objPtr && JimIsWide(objPtr)) { |
| 14150 | Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]); |
| 14151 | if (objPtr2 && JimIsWide(objPtr2)) { |
| 14152 | jim_wide wideValueA = JimWideValue(objPtr); |
| 14153 | jim_wide wideValueB = JimWideValue(objPtr2); |
| 14154 | int cmpRes; |
| 14155 | switch (expr->token[2].type) { |
| 14156 | case JIM_EXPROP_LT: |
| 14157 | cmpRes = wideValueA < wideValueB; |
| 14158 | break; |
| 14159 | case JIM_EXPROP_LTE: |
| 14160 | cmpRes = wideValueA <= wideValueB; |
| @@ -14172,12 +14026,11 @@ | |
| 14172 | cmpRes = wideValueA != wideValueB; |
| 14173 | break; |
| 14174 | default: |
| 14175 | goto noopt; |
| 14176 | } |
| 14177 | *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj; |
| 14178 | Jim_IncrRefCount(*exprResultPtrPtr); |
| 14179 | return JIM_OK; |
| 14180 | } |
| 14181 | } |
| 14182 | break; |
| 14183 | } |
| @@ -14185,145 +14038,64 @@ | |
| 14185 | noopt: |
| 14186 | #endif |
| 14187 | |
| 14188 | expr->inUse++; |
| 14189 | |
| 14190 | |
| 14191 | |
| 14192 | if (expr->len > JIM_EE_STATICSTACK_LEN) |
| 14193 | e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len); |
| 14194 | else |
| 14195 | e.stack = staticStack; |
| 14196 | |
| 14197 | e.stacklen = 0; |
| 14198 | |
| 14199 | |
| 14200 | for (i = 0; i < expr->len && retcode == JIM_OK; i++) { |
| 14201 | Jim_Obj *objPtr; |
| 14202 | |
| 14203 | switch (expr->token[i].type) { |
| 14204 | case JIM_TT_EXPR_INT: |
| 14205 | case JIM_TT_EXPR_DOUBLE: |
| 14206 | case JIM_TT_STR: |
| 14207 | ExprPush(&e, expr->token[i].objPtr); |
| 14208 | break; |
| 14209 | |
| 14210 | case JIM_TT_VAR: |
| 14211 | objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG); |
| 14212 | if (objPtr) { |
| 14213 | ExprPush(&e, objPtr); |
| 14214 | } |
| 14215 | else { |
| 14216 | retcode = JIM_ERR; |
| 14217 | } |
| 14218 | break; |
| 14219 | |
| 14220 | case JIM_TT_DICTSUGAR: |
| 14221 | objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr); |
| 14222 | if (objPtr) { |
| 14223 | ExprPush(&e, objPtr); |
| 14224 | } |
| 14225 | else { |
| 14226 | retcode = JIM_ERR; |
| 14227 | } |
| 14228 | break; |
| 14229 | |
| 14230 | case JIM_TT_ESC: |
| 14231 | retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE); |
| 14232 | if (retcode == JIM_OK) { |
| 14233 | ExprPush(&e, objPtr); |
| 14234 | } |
| 14235 | break; |
| 14236 | |
| 14237 | case JIM_TT_CMD: |
| 14238 | retcode = Jim_EvalObj(interp, expr->token[i].objPtr); |
| 14239 | if (retcode == JIM_OK) { |
| 14240 | ExprPush(&e, Jim_GetResult(interp)); |
| 14241 | } |
| 14242 | break; |
| 14243 | |
| 14244 | default:{ |
| 14245 | |
| 14246 | e.skip = 0; |
| 14247 | e.opcode = expr->token[i].type; |
| 14248 | |
| 14249 | retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e); |
| 14250 | |
| 14251 | i += e.skip; |
| 14252 | continue; |
| 14253 | } |
| 14254 | } |
| 14255 | } |
| 14256 | |
| 14257 | expr->inUse--; |
| 14258 | |
| 14259 | if (retcode == JIM_OK) { |
| 14260 | *exprResultPtrPtr = ExprPop(&e); |
| 14261 | } |
| 14262 | else { |
| 14263 | for (i = 0; i < e.stacklen; i++) { |
| 14264 | Jim_DecrRefCount(interp, e.stack[i]); |
| 14265 | } |
| 14266 | } |
| 14267 | if (e.stack != staticStack) { |
| 14268 | Jim_Free(e.stack); |
| 14269 | } |
| 14270 | return retcode; |
| 14271 | } |
| 14272 | |
| 14273 | int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) |
| 14274 | { |
| 14275 | int retcode; |
| 14276 | jim_wide wideValue; |
| 14277 | double doubleValue; |
| 14278 | Jim_Obj *exprResultPtr; |
| 14279 | |
| 14280 | retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr); |
| 14281 | if (retcode != JIM_OK) |
| 14282 | return retcode; |
| 14283 | |
| 14284 | if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) { |
| 14285 | if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) { |
| 14286 | Jim_DecrRefCount(interp, exprResultPtr); |
| 14287 | return JIM_ERR; |
| 14288 | } |
| 14289 | else { |
| 14290 | Jim_DecrRefCount(interp, exprResultPtr); |
| 14291 | *boolPtr = doubleValue != 0; |
| 14292 | return JIM_OK; |
| 14293 | } |
| 14294 | } |
| 14295 | *boolPtr = wideValue != 0; |
| 14296 | |
| 14297 | Jim_DecrRefCount(interp, exprResultPtr); |
| 14298 | return JIM_OK; |
| 14299 | } |
| 14300 | |
| 14301 | |
| 14302 | |
| 14303 | |
| 14304 | typedef struct ScanFmtPartDescr |
| 14305 | { |
| 14306 | char *arg; |
| 14307 | char *prefix; |
| 14308 | size_t width; |
| 14309 | int pos; |
| 14310 | char type; |
| 14311 | char modifier; |
| 14312 | } ScanFmtPartDescr; |
| 14313 | |
| 14314 | |
| 14315 | typedef struct ScanFmtStringObj |
| 14316 | { |
| 14317 | jim_wide size; |
| 14318 | char *stringRep; |
| 14319 | size_t count; |
| 14320 | size_t convCount; |
| 14321 | size_t maxPos; |
| 14322 | const char *error; |
| 14323 | char *scratch; |
| 14324 | ScanFmtPartDescr descr[1]; |
| 14325 | } ScanFmtStringObj; |
| 14326 | |
| 14327 | |
| 14328 | static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 14329 | static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| @@ -14364,28 +14136,28 @@ | |
| 14364 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 14365 | { |
| 14366 | ScanFmtStringObj *fmtObj; |
| 14367 | char *buffer; |
| 14368 | int maxCount, i, approxSize, lastPos = -1; |
| 14369 | const char *fmt = objPtr->bytes; |
| 14370 | int maxFmtLen = objPtr->length; |
| 14371 | const char *fmtEnd = fmt + maxFmtLen; |
| 14372 | int curr; |
| 14373 | |
| 14374 | Jim_FreeIntRep(interp, objPtr); |
| 14375 | |
| 14376 | for (i = 0, maxCount = 0; i < maxFmtLen; ++i) |
| 14377 | if (fmt[i] == '%') |
| 14378 | ++maxCount; |
| 14379 | |
| 14380 | approxSize = sizeof(ScanFmtStringObj) |
| 14381 | +(maxCount + 1) * sizeof(ScanFmtPartDescr) |
| 14382 | +maxFmtLen * sizeof(char) + 3 + 1 |
| 14383 | + maxFmtLen * sizeof(char) + 1 |
| 14384 | + maxFmtLen * sizeof(char) |
| 14385 | +(maxCount + 1) * sizeof(char) |
| 14386 | +1; |
| 14387 | fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize); |
| 14388 | memset(fmtObj, 0, approxSize); |
| 14389 | fmtObj->size = approxSize; |
| 14390 | fmtObj->maxPos = 0; |
| 14391 | fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1]; |
| @@ -14397,12 +14169,12 @@ | |
| 14397 | for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) { |
| 14398 | int width = 0, skip; |
| 14399 | ScanFmtPartDescr *descr = &fmtObj->descr[curr]; |
| 14400 | |
| 14401 | fmtObj->count++; |
| 14402 | descr->width = 0; |
| 14403 | |
| 14404 | if (*fmt != '%' || fmt[1] == '%') { |
| 14405 | descr->type = 0; |
| 14406 | descr->prefix = &buffer[i]; |
| 14407 | for (; fmt < fmtEnd; ++fmt) { |
| 14408 | if (*fmt == '%') { |
| @@ -14412,65 +14184,70 @@ | |
| 14412 | } |
| 14413 | buffer[i++] = *fmt; |
| 14414 | } |
| 14415 | buffer[i++] = 0; |
| 14416 | } |
| 14417 | |
| 14418 | ++fmt; |
| 14419 | |
| 14420 | if (fmt >= fmtEnd) |
| 14421 | goto done; |
| 14422 | descr->pos = 0; |
| 14423 | if (*fmt == '*') { |
| 14424 | descr->pos = -1; |
| 14425 | ++fmt; |
| 14426 | } |
| 14427 | else |
| 14428 | fmtObj->convCount++; |
| 14429 | |
| 14430 | if (sscanf(fmt, "%d%n", &width, &skip) == 1) { |
| 14431 | fmt += skip; |
| 14432 | |
| 14433 | if (descr->pos != -1 && *fmt == '$') { |
| 14434 | int prev; |
| 14435 | |
| 14436 | ++fmt; |
| 14437 | descr->pos = width; |
| 14438 | width = 0; |
| 14439 | |
| 14440 | if ((lastPos == 0 && descr->pos > 0) |
| 14441 | || (lastPos > 0 && descr->pos == 0)) { |
| 14442 | fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers"; |
| 14443 | return JIM_ERR; |
| 14444 | } |
| 14445 | |
| 14446 | for (prev = 0; prev < curr; ++prev) { |
| 14447 | if (fmtObj->descr[prev].pos == -1) |
| 14448 | continue; |
| 14449 | if (fmtObj->descr[prev].pos == descr->pos) { |
| 14450 | fmtObj->error = |
| 14451 | "variable is assigned by multiple \"%n$\" conversion specifiers"; |
| 14452 | return JIM_ERR; |
| 14453 | } |
| 14454 | } |
| 14455 | |
| 14456 | if (sscanf(fmt, "%d%n", &width, &skip) == 1) { |
| 14457 | descr->width = width; |
| 14458 | fmt += skip; |
| 14459 | } |
| 14460 | if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) |
| 14461 | fmtObj->maxPos = descr->pos; |
| 14462 | } |
| 14463 | else { |
| 14464 | |
| 14465 | descr->width = width; |
| 14466 | } |
| 14467 | } |
| 14468 | |
| 14469 | if (lastPos == -1) |
| 14470 | lastPos = descr->pos; |
| 14471 | |
| 14472 | if (*fmt == '[') { |
| 14473 | int swapped = 1, beg = i, end, j; |
| 14474 | |
| 14475 | descr->type = '['; |
| 14476 | descr->arg = &buffer[i]; |
| @@ -14485,11 +14262,11 @@ | |
| 14485 | fmtObj->error = "unmatched [ in format string"; |
| 14486 | return JIM_ERR; |
| 14487 | } |
| 14488 | end = i; |
| 14489 | buffer[i++] = 0; |
| 14490 | |
| 14491 | while (swapped) { |
| 14492 | swapped = 0; |
| 14493 | for (j = beg + 1; j < end - 1; ++j) { |
| 14494 | if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) { |
| 14495 | char tmp = buffer[j - 1]; |
| @@ -14500,13 +14277,18 @@ | |
| 14500 | } |
| 14501 | } |
| 14502 | } |
| 14503 | } |
| 14504 | else { |
| 14505 | |
| 14506 | if (strchr("hlL", *fmt) != 0) |
| 14507 | descr->modifier = tolower((int)*fmt++); |
| 14508 | |
| 14509 | descr->type = *fmt; |
| 14510 | if (strchr("efgcsndoxui", *fmt) == 0) { |
| 14511 | fmtObj->error = "bad scan conversion character"; |
| 14512 | return JIM_ERR; |
| @@ -14543,11 +14325,11 @@ | |
| 14543 | while (*str) { |
| 14544 | int c; |
| 14545 | int n; |
| 14546 | |
| 14547 | if (!sdescr && isspace(UCHAR(*str))) |
| 14548 | break; |
| 14549 | |
| 14550 | n = utf8_tounicode(str, &c); |
| 14551 | if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) |
| 14552 | break; |
| 14553 | while (n--) |
| @@ -14566,89 +14348,89 @@ | |
| 14566 | size_t scanned = 0; |
| 14567 | size_t anchor = pos; |
| 14568 | int i; |
| 14569 | Jim_Obj *tmpObj = NULL; |
| 14570 | |
| 14571 | |
| 14572 | *valObjPtr = 0; |
| 14573 | if (descr->prefix) { |
| 14574 | for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 14575 | |
| 14576 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14577 | while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 14578 | ++pos; |
| 14579 | else if (descr->prefix[i] != str[pos]) |
| 14580 | break; |
| 14581 | else |
| 14582 | ++pos; |
| 14583 | } |
| 14584 | if (pos >= strLen) { |
| 14585 | return -1; |
| 14586 | } |
| 14587 | else if (descr->prefix[i] != 0) |
| 14588 | return 0; |
| 14589 | } |
| 14590 | |
| 14591 | if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') |
| 14592 | while (isspace(UCHAR(str[pos]))) |
| 14593 | ++pos; |
| 14594 | |
| 14595 | scanned = pos - anchor; |
| 14596 | |
| 14597 | |
| 14598 | if (descr->type == 'n') { |
| 14599 | |
| 14600 | *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); |
| 14601 | } |
| 14602 | else if (pos >= strLen) { |
| 14603 | |
| 14604 | return -1; |
| 14605 | } |
| 14606 | else if (descr->type == 'c') { |
| 14607 | int c; |
| 14608 | scanned += utf8_tounicode(&str[pos], &c); |
| 14609 | *valObjPtr = Jim_NewIntObj(interp, c); |
| 14610 | return scanned; |
| 14611 | } |
| 14612 | else { |
| 14613 | |
| 14614 | if (descr->width > 0) { |
| 14615 | size_t sLen = utf8_strlen(&str[pos], strLen - pos); |
| 14616 | size_t tLen = descr->width > sLen ? sLen : descr->width; |
| 14617 | |
| 14618 | tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); |
| 14619 | tok = tmpObj->bytes; |
| 14620 | } |
| 14621 | else { |
| 14622 | |
| 14623 | tok = &str[pos]; |
| 14624 | } |
| 14625 | switch (descr->type) { |
| 14626 | case 'd': |
| 14627 | case 'o': |
| 14628 | case 'x': |
| 14629 | case 'u': |
| 14630 | case 'i':{ |
| 14631 | char *endp; |
| 14632 | jim_wide w; |
| 14633 | |
| 14634 | int base = descr->type == 'o' ? 8 |
| 14635 | : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10; |
| 14636 | |
| 14637 | |
| 14638 | if (base == 0) { |
| 14639 | w = jim_strtoull(tok, &endp); |
| 14640 | } |
| 14641 | else { |
| 14642 | w = strtoull(tok, &endp, base); |
| 14643 | } |
| 14644 | |
| 14645 | if (endp != tok) { |
| 14646 | |
| 14647 | *valObjPtr = Jim_NewIntObj(interp, w); |
| 14648 | |
| 14649 | |
| 14650 | scanned += endp - tok; |
| 14651 | } |
| 14652 | else { |
| 14653 | scanned = *tok ? 0 : -1; |
| 14654 | } |
| @@ -14665,13 +14447,13 @@ | |
| 14665 | case 'g':{ |
| 14666 | char *endp; |
| 14667 | double value = strtod(tok, &endp); |
| 14668 | |
| 14669 | if (endp != tok) { |
| 14670 | |
| 14671 | *valObjPtr = Jim_NewDoubleObj(interp, value); |
| 14672 | |
| 14673 | scanned += endp - tok; |
| 14674 | } |
| 14675 | else { |
| 14676 | scanned = *tok ? 0 : -1; |
| 14677 | } |
| @@ -14696,65 +14478,65 @@ | |
| 14696 | Jim_Obj **resultVec = 0; |
| 14697 | int resultc; |
| 14698 | Jim_Obj *emptyStr = 0; |
| 14699 | ScanFmtStringObj *fmtObj; |
| 14700 | |
| 14701 | |
| 14702 | JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format")); |
| 14703 | |
| 14704 | fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr; |
| 14705 | |
| 14706 | if (fmtObj->error != 0) { |
| 14707 | if (flags & JIM_ERRMSG) |
| 14708 | Jim_SetResultString(interp, fmtObj->error, -1); |
| 14709 | return 0; |
| 14710 | } |
| 14711 | |
| 14712 | emptyStr = Jim_NewEmptyStringObj(interp); |
| 14713 | Jim_IncrRefCount(emptyStr); |
| 14714 | |
| 14715 | resultList = Jim_NewListObj(interp, NULL, 0); |
| 14716 | if (fmtObj->maxPos > 0) { |
| 14717 | for (i = 0; i < fmtObj->maxPos; ++i) |
| 14718 | Jim_ListAppendElement(interp, resultList, emptyStr); |
| 14719 | JimListGetElements(interp, resultList, &resultc, &resultVec); |
| 14720 | } |
| 14721 | |
| 14722 | for (i = 0, pos = 0; i < fmtObj->count; ++i) { |
| 14723 | ScanFmtPartDescr *descr = &(fmtObj->descr[i]); |
| 14724 | Jim_Obj *value = 0; |
| 14725 | |
| 14726 | |
| 14727 | if (descr->type == 0) |
| 14728 | continue; |
| 14729 | |
| 14730 | if (scanned > 0) |
| 14731 | scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); |
| 14732 | |
| 14733 | if (scanned == -1 && i == 0) |
| 14734 | goto eof; |
| 14735 | |
| 14736 | pos += scanned; |
| 14737 | |
| 14738 | |
| 14739 | if (value == 0) |
| 14740 | value = Jim_NewEmptyStringObj(interp); |
| 14741 | |
| 14742 | if (descr->pos == -1) { |
| 14743 | Jim_FreeNewObj(interp, value); |
| 14744 | } |
| 14745 | else if (descr->pos == 0) |
| 14746 | |
| 14747 | Jim_ListAppendElement(interp, resultList, value); |
| 14748 | else if (resultVec[descr->pos - 1] == emptyStr) { |
| 14749 | |
| 14750 | Jim_DecrRefCount(interp, resultVec[descr->pos - 1]); |
| 14751 | Jim_IncrRefCount(value); |
| 14752 | resultVec[descr->pos - 1] = value; |
| 14753 | } |
| 14754 | else { |
| 14755 | |
| 14756 | Jim_FreeNewObj(interp, value); |
| 14757 | goto err; |
| 14758 | } |
| 14759 | } |
| 14760 | Jim_DecrRefCount(interp, emptyStr); |
| @@ -14792,15 +14574,15 @@ | |
| 14792 | { |
| 14793 | Jim_PrngState *prng; |
| 14794 | unsigned char *destByte = (unsigned char *)dest; |
| 14795 | unsigned int si, sj, x; |
| 14796 | |
| 14797 | |
| 14798 | if (interp->prngState == NULL) |
| 14799 | JimPrngInit(interp); |
| 14800 | prng = interp->prngState; |
| 14801 | |
| 14802 | for (x = 0; x < len; x++) { |
| 14803 | prng->i = (prng->i + 1) & 0xff; |
| 14804 | si = prng->sbox[prng->i]; |
| 14805 | prng->j = (prng->j + si) & 0xff; |
| 14806 | sj = prng->sbox[prng->j]; |
| @@ -14814,19 +14596,19 @@ | |
| 14814 | static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen) |
| 14815 | { |
| 14816 | int i; |
| 14817 | Jim_PrngState *prng; |
| 14818 | |
| 14819 | |
| 14820 | if (interp->prngState == NULL) |
| 14821 | JimPrngInit(interp); |
| 14822 | prng = interp->prngState; |
| 14823 | |
| 14824 | |
| 14825 | for (i = 0; i < 256; i++) |
| 14826 | prng->sbox[i] = i; |
| 14827 | |
| 14828 | for (i = 0; i < seedLen; i++) { |
| 14829 | unsigned char t; |
| 14830 | |
| 14831 | t = prng->sbox[i & 0xFF]; |
| 14832 | prng->sbox[i & 0xFF] = prng->sbox[seed[i]]; |
| @@ -14853,11 +14635,11 @@ | |
| 14853 | if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) |
| 14854 | return JIM_ERR; |
| 14855 | } |
| 14856 | intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 14857 | if (!intObjPtr) { |
| 14858 | |
| 14859 | wideValue = 0; |
| 14860 | } |
| 14861 | else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) { |
| 14862 | return JIM_ERR; |
| 14863 | } |
| @@ -14867,26 +14649,26 @@ | |
| 14867 | Jim_FreeNewObj(interp, intObjPtr); |
| 14868 | return JIM_ERR; |
| 14869 | } |
| 14870 | } |
| 14871 | else { |
| 14872 | |
| 14873 | Jim_InvalidateStringRep(intObjPtr); |
| 14874 | JimWideValue(intObjPtr) = wideValue + increment; |
| 14875 | |
| 14876 | if (argv[1]->typePtr != &variableObjType) { |
| 14877 | |
| 14878 | Jim_SetVariable(interp, argv[1], intObjPtr); |
| 14879 | } |
| 14880 | } |
| 14881 | Jim_SetResult(interp, intObjPtr); |
| 14882 | return JIM_OK; |
| 14883 | } |
| 14884 | |
| 14885 | |
| 14886 | #define JIM_EVAL_SARGV_LEN 8 |
| 14887 | #define JIM_EVAL_SINTV_LEN 8 |
| 14888 | |
| 14889 | |
| 14890 | static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 14891 | { |
| 14892 | int retcode; |
| @@ -14894,16 +14676,16 @@ | |
| 14894 | if (interp->unknown_called > 50) { |
| 14895 | return JIM_ERR; |
| 14896 | } |
| 14897 | |
| 14898 | |
| 14899 | |
| 14900 | if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) |
| 14901 | return JIM_ERR; |
| 14902 | |
| 14903 | interp->unknown_called++; |
| 14904 | |
| 14905 | retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv); |
| 14906 | interp->unknown_called--; |
| 14907 | |
| 14908 | return retcode; |
| 14909 | } |
| @@ -14910,10 +14692,11 @@ | |
| 14910 | |
| 14911 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14912 | { |
| 14913 | int retcode; |
| 14914 | Jim_Cmd *cmdPtr; |
| 14915 | |
| 14916 | #if 0 |
| 14917 | printf("invoke"); |
| 14918 | int j; |
| 14919 | for (j = 0; j < objc; j++) { |
| @@ -14921,11 +14704,11 @@ | |
| 14921 | } |
| 14922 | printf("\n"); |
| 14923 | #endif |
| 14924 | |
| 14925 | if (interp->framePtr->tailcallCmd) { |
| 14926 | |
| 14927 | cmdPtr = interp->framePtr->tailcallCmd; |
| 14928 | interp->framePtr->tailcallCmd = NULL; |
| 14929 | } |
| 14930 | else { |
| 14931 | cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| @@ -14939,20 +14722,22 @@ | |
| 14939 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14940 | retcode = JIM_ERR; |
| 14941 | goto out; |
| 14942 | } |
| 14943 | interp->evalDepth++; |
| 14944 | |
| 14945 | |
| 14946 | Jim_SetEmptyResult(interp); |
| 14947 | if (cmdPtr->isproc) { |
| 14948 | retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14949 | } |
| 14950 | else { |
| 14951 | interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14952 | retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14953 | } |
| 14954 | interp->evalDepth--; |
| 14955 | |
| 14956 | out: |
| 14957 | JimDecrCmdRefCount(interp, cmdPtr); |
| 14958 | |
| @@ -14961,17 +14746,17 @@ | |
| 14961 | |
| 14962 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14963 | { |
| 14964 | int i, retcode; |
| 14965 | |
| 14966 | |
| 14967 | for (i = 0; i < objc; i++) |
| 14968 | Jim_IncrRefCount(objv[i]); |
| 14969 | |
| 14970 | retcode = JimInvokeCommand(interp, objc, objv); |
| 14971 | |
| 14972 | |
| 14973 | for (i = 0; i < objc; i++) |
| 14974 | Jim_DecrRefCount(interp, objv[i]); |
| 14975 | |
| 14976 | return retcode; |
| 14977 | } |
| @@ -14989,25 +14774,25 @@ | |
| 14989 | } |
| 14990 | |
| 14991 | static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script) |
| 14992 | { |
| 14993 | if (!interp->errorFlag) { |
| 14994 | |
| 14995 | interp->errorFlag = 1; |
| 14996 | Jim_IncrRefCount(script->fileNameObj); |
| 14997 | Jim_DecrRefCount(interp, interp->errorFileNameObj); |
| 14998 | interp->errorFileNameObj = script->fileNameObj; |
| 14999 | interp->errorLine = script->linenr; |
| 15000 | |
| 15001 | JimResetStackTrace(interp); |
| 15002 | |
| 15003 | interp->addStackTrace++; |
| 15004 | } |
| 15005 | |
| 15006 | |
| 15007 | if (interp->addStackTrace > 0) { |
| 15008 | |
| 15009 | |
| 15010 | JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr); |
| 15011 | |
| 15012 | if (Jim_Length(script->fileNameObj)) { |
| 15013 | interp->addStackTrace = 0; |
| @@ -15042,14 +14827,14 @@ | |
| 15042 | case JIM_OK: |
| 15043 | case JIM_RETURN: |
| 15044 | objPtr = interp->result; |
| 15045 | break; |
| 15046 | case JIM_BREAK: |
| 15047 | |
| 15048 | return JIM_BREAK; |
| 15049 | case JIM_CONTINUE: |
| 15050 | |
| 15051 | return JIM_CONTINUE; |
| 15052 | default: |
| 15053 | return JIM_ERR; |
| 15054 | } |
| 15055 | break; |
| @@ -15084,23 +14869,23 @@ | |
| 15084 | case JIM_OK: |
| 15085 | case JIM_RETURN: |
| 15086 | break; |
| 15087 | case JIM_BREAK: |
| 15088 | if (flags & JIM_SUBST_FLAG) { |
| 15089 | |
| 15090 | tokens = i; |
| 15091 | continue; |
| 15092 | } |
| 15093 | |
| 15094 | |
| 15095 | case JIM_CONTINUE: |
| 15096 | if (flags & JIM_SUBST_FLAG) { |
| 15097 | intv[i] = NULL; |
| 15098 | continue; |
| 15099 | } |
| 15100 | |
| 15101 | |
| 15102 | default: |
| 15103 | while (i--) { |
| 15104 | Jim_DecrRefCount(interp, intv[i]); |
| 15105 | } |
| 15106 | if (intv != sintv) { |
| @@ -15111,28 +14896,29 @@ | |
| 15111 | Jim_IncrRefCount(intv[i]); |
| 15112 | Jim_String(intv[i]); |
| 15113 | totlen += intv[i]->length; |
| 15114 | } |
| 15115 | |
| 15116 | |
| 15117 | if (tokens == 1 && intv[0] && intv == sintv) { |
| 15118 | Jim_DecrRefCount(interp, intv[0]); |
| 15119 | return intv[0]; |
| 15120 | } |
| 15121 | |
| 15122 | objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); |
| 15123 | |
| 15124 | if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC |
| 15125 | && token[2].type == JIM_TT_VAR) { |
| 15126 | |
| 15127 | objPtr->typePtr = &interpolatedObjType; |
| 15128 | objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; |
| 15129 | objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; |
| 15130 | Jim_IncrRefCount(intv[2]); |
| 15131 | } |
| 15132 | else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { |
| 15133 | |
| 15134 | JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); |
| 15135 | } |
| 15136 | |
| 15137 | |
| 15138 | s = objPtr->bytes = Jim_Alloc(totlen + 1); |
| @@ -15143,11 +14929,11 @@ | |
| 15143 | s += intv[i]->length; |
| 15144 | Jim_DecrRefCount(interp, intv[i]); |
| 15145 | } |
| 15146 | } |
| 15147 | objPtr->bytes[totlen] = '\0'; |
| 15148 | |
| 15149 | if (intv != sintv) { |
| 15150 | Jim_Free(intv); |
| 15151 | } |
| 15152 | |
| 15153 | return objPtr; |
| @@ -15187,11 +14973,11 @@ | |
| 15187 | |
| 15188 | if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { |
| 15189 | return JimEvalObjList(interp, scriptObjPtr); |
| 15190 | } |
| 15191 | |
| 15192 | Jim_IncrRefCount(scriptObjPtr); |
| 15193 | script = JimGetScript(interp, scriptObjPtr); |
| 15194 | if (!JimScriptValid(interp, script)) { |
| 15195 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 15196 | return JIM_ERR; |
| 15197 | } |
| @@ -15223,11 +15009,11 @@ | |
| 15223 | } |
| 15224 | #endif |
| 15225 | |
| 15226 | script->inUse++; |
| 15227 | |
| 15228 | |
| 15229 | prevScriptObj = interp->currentScriptObj; |
| 15230 | interp->currentScriptObj = scriptObjPtr; |
| 15231 | |
| 15232 | interp->errorFlag = 0; |
| 15233 | argv = sargv; |
| @@ -15234,19 +15020,19 @@ | |
| 15234 | |
| 15235 | for (i = 0; i < script->len && retcode == JIM_OK; ) { |
| 15236 | int argc; |
| 15237 | int j; |
| 15238 | |
| 15239 | |
| 15240 | argc = token[i].objPtr->internalRep.scriptLineValue.argc; |
| 15241 | script->linenr = token[i].objPtr->internalRep.scriptLineValue.line; |
| 15242 | |
| 15243 | |
| 15244 | if (argc > JIM_EVAL_SARGV_LEN) |
| 15245 | argv = Jim_Alloc(sizeof(Jim_Obj *) * argc); |
| 15246 | |
| 15247 | |
| 15248 | i++; |
| 15249 | |
| 15250 | for (j = 0; j < argc; j++) { |
| 15251 | long wordtokens = 1; |
| 15252 | int expand = 0; |
| @@ -15302,11 +15088,11 @@ | |
| 15302 | |
| 15303 | if (!expand) { |
| 15304 | argv[j] = wordObjPtr; |
| 15305 | } |
| 15306 | else { |
| 15307 | |
| 15308 | int len = Jim_ListLength(interp, wordObjPtr); |
| 15309 | int newargc = argc + len - 1; |
| 15310 | int k; |
| 15311 | |
| 15312 | if (len > 1) { |
| @@ -15315,39 +15101,39 @@ | |
| 15315 | argv = Jim_Alloc(sizeof(*argv) * newargc); |
| 15316 | memcpy(argv, sargv, sizeof(*argv) * j); |
| 15317 | } |
| 15318 | } |
| 15319 | else { |
| 15320 | |
| 15321 | argv = Jim_Realloc(argv, sizeof(*argv) * newargc); |
| 15322 | } |
| 15323 | } |
| 15324 | |
| 15325 | |
| 15326 | for (k = 0; k < len; k++) { |
| 15327 | argv[j++] = wordObjPtr->internalRep.listValue.ele[k]; |
| 15328 | Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]); |
| 15329 | } |
| 15330 | |
| 15331 | Jim_DecrRefCount(interp, wordObjPtr); |
| 15332 | |
| 15333 | |
| 15334 | j--; |
| 15335 | argc += len - 1; |
| 15336 | } |
| 15337 | } |
| 15338 | |
| 15339 | if (retcode == JIM_OK && argc) { |
| 15340 | |
| 15341 | retcode = JimInvokeCommand(interp, argc, argv); |
| 15342 | |
| 15343 | if (Jim_CheckSignal(interp)) { |
| 15344 | retcode = JIM_SIGNAL; |
| 15345 | } |
| 15346 | } |
| 15347 | |
| 15348 | |
| 15349 | while (j-- > 0) { |
| 15350 | Jim_DecrRefCount(interp, argv[j]); |
| 15351 | } |
| 15352 | |
| 15353 | if (argv != sargv) { |
| @@ -15354,21 +15140,21 @@ | |
| 15354 | Jim_Free(argv); |
| 15355 | argv = sargv; |
| 15356 | } |
| 15357 | } |
| 15358 | |
| 15359 | |
| 15360 | if (retcode == JIM_ERR) { |
| 15361 | JimAddErrorToStack(interp, script); |
| 15362 | } |
| 15363 | |
| 15364 | else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) { |
| 15365 | |
| 15366 | interp->addStackTrace = 0; |
| 15367 | } |
| 15368 | |
| 15369 | |
| 15370 | interp->currentScriptObj = prevScriptObj; |
| 15371 | |
| 15372 | Jim_FreeIntRep(interp, scriptObjPtr); |
| 15373 | scriptObjPtr->typePtr = &scriptObjType; |
| 15374 | Jim_SetIntRepPtr(scriptObjPtr, script); |
| @@ -15378,14 +15164,14 @@ | |
| 15378 | } |
| 15379 | |
| 15380 | static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj) |
| 15381 | { |
| 15382 | int retcode; |
| 15383 | |
| 15384 | const char *varname = Jim_String(argNameObj); |
| 15385 | if (*varname == '&') { |
| 15386 | |
| 15387 | Jim_Obj *objPtr; |
| 15388 | Jim_CallFrame *savedCallFrame = interp->framePtr; |
| 15389 | |
| 15390 | interp->framePtr = interp->framePtr->parent; |
| 15391 | objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG); |
| @@ -15392,11 +15178,11 @@ | |
| 15392 | interp->framePtr = savedCallFrame; |
| 15393 | if (!objPtr) { |
| 15394 | return JIM_ERR; |
| 15395 | } |
| 15396 | |
| 15397 | |
| 15398 | objPtr = Jim_NewStringObj(interp, varname + 1, -1); |
| 15399 | Jim_IncrRefCount(objPtr); |
| 15400 | retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent); |
| 15401 | Jim_DecrRefCount(interp, objPtr); |
| 15402 | } |
| @@ -15406,26 +15192,26 @@ | |
| 15406 | return retcode; |
| 15407 | } |
| 15408 | |
| 15409 | static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd) |
| 15410 | { |
| 15411 | |
| 15412 | Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0); |
| 15413 | int i; |
| 15414 | |
| 15415 | for (i = 0; i < cmd->u.proc.argListLen; i++) { |
| 15416 | Jim_AppendString(interp, argmsg, " ", 1); |
| 15417 | |
| 15418 | if (i == cmd->u.proc.argsPos) { |
| 15419 | if (cmd->u.proc.arglist[i].defaultObjPtr) { |
| 15420 | |
| 15421 | Jim_AppendString(interp, argmsg, "?", 1); |
| 15422 | Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); |
| 15423 | Jim_AppendString(interp, argmsg, " ...?", -1); |
| 15424 | } |
| 15425 | else { |
| 15426 | |
| 15427 | Jim_AppendString(interp, argmsg, "?arg...?", -1); |
| 15428 | } |
| 15429 | } |
| 15430 | else { |
| 15431 | if (cmd->u.proc.arglist[i].defaultObjPtr) { |
| @@ -15441,20 +15227,19 @@ | |
| 15441 | Jim_AppendString(interp, argmsg, arg, -1); |
| 15442 | } |
| 15443 | } |
| 15444 | } |
| 15445 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg); |
| 15446 | Jim_FreeNewObj(interp, argmsg); |
| 15447 | } |
| 15448 | |
| 15449 | #ifdef jim_ext_namespace |
| 15450 | int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj) |
| 15451 | { |
| 15452 | Jim_CallFrame *callFramePtr; |
| 15453 | int retcode; |
| 15454 | |
| 15455 | |
| 15456 | callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj); |
| 15457 | callFramePtr->argv = &interp->emptyObj; |
| 15458 | callFramePtr->argc = 0; |
| 15459 | callFramePtr->procArgsObjPtr = NULL; |
| 15460 | callFramePtr->procBodyObjPtr = scriptObj; |
| @@ -15462,21 +15247,21 @@ | |
| 15462 | callFramePtr->fileNameObj = interp->emptyObj; |
| 15463 | callFramePtr->line = 0; |
| 15464 | Jim_IncrRefCount(scriptObj); |
| 15465 | interp->framePtr = callFramePtr; |
| 15466 | |
| 15467 | |
| 15468 | if (interp->framePtr->level == interp->maxCallFrameDepth) { |
| 15469 | Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); |
| 15470 | retcode = JIM_ERR; |
| 15471 | } |
| 15472 | else { |
| 15473 | |
| 15474 | retcode = Jim_EvalObj(interp, scriptObj); |
| 15475 | } |
| 15476 | |
| 15477 | |
| 15478 | interp->framePtr = interp->framePtr->parent; |
| 15479 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15480 | |
| 15481 | return retcode; |
| 15482 | } |
| @@ -15486,62 +15271,62 @@ | |
| 15486 | { |
| 15487 | Jim_CallFrame *callFramePtr; |
| 15488 | int i, d, retcode, optargs; |
| 15489 | ScriptObj *script; |
| 15490 | |
| 15491 | |
| 15492 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15493 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| 15494 | JimSetProcWrongArgs(interp, argv[0], cmd); |
| 15495 | return JIM_ERR; |
| 15496 | } |
| 15497 | |
| 15498 | if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) { |
| 15499 | |
| 15500 | return JIM_OK; |
| 15501 | } |
| 15502 | |
| 15503 | |
| 15504 | if (interp->framePtr->level == interp->maxCallFrameDepth) { |
| 15505 | Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); |
| 15506 | return JIM_ERR; |
| 15507 | } |
| 15508 | |
| 15509 | |
| 15510 | callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj); |
| 15511 | callFramePtr->argv = argv; |
| 15512 | callFramePtr->argc = argc; |
| 15513 | callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; |
| 15514 | callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; |
| 15515 | callFramePtr->staticVars = cmd->u.proc.staticVars; |
| 15516 | |
| 15517 | |
| 15518 | script = JimGetScript(interp, interp->currentScriptObj); |
| 15519 | callFramePtr->fileNameObj = script->fileNameObj; |
| 15520 | callFramePtr->line = script->linenr; |
| 15521 | |
| 15522 | Jim_IncrRefCount(cmd->u.proc.argListObjPtr); |
| 15523 | Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); |
| 15524 | interp->framePtr = callFramePtr; |
| 15525 | |
| 15526 | |
| 15527 | optargs = (argc - 1 - cmd->u.proc.reqArity); |
| 15528 | |
| 15529 | |
| 15530 | i = 1; |
| 15531 | for (d = 0; d < cmd->u.proc.argListLen; d++) { |
| 15532 | Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr; |
| 15533 | if (d == cmd->u.proc.argsPos) { |
| 15534 | |
| 15535 | Jim_Obj *listObjPtr; |
| 15536 | int argsLen = 0; |
| 15537 | if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) { |
| 15538 | argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity); |
| 15539 | } |
| 15540 | listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen); |
| 15541 | |
| 15542 | |
| 15543 | if (cmd->u.proc.arglist[d].defaultObjPtr) { |
| 15544 | nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr; |
| 15545 | } |
| 15546 | retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr); |
| 15547 | if (retcode != JIM_OK) { |
| @@ -15550,33 +15335,34 @@ | |
| 15550 | |
| 15551 | i += argsLen; |
| 15552 | continue; |
| 15553 | } |
| 15554 | |
| 15555 | |
| 15556 | if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) { |
| 15557 | retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]); |
| 15558 | } |
| 15559 | else { |
| 15560 | |
| 15561 | retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr); |
| 15562 | } |
| 15563 | if (retcode != JIM_OK) { |
| 15564 | goto badargset; |
| 15565 | } |
| 15566 | } |
| 15567 | |
| 15568 | |
| 15569 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 15570 | |
| 15571 | badargset: |
| 15572 | |
| 15573 | |
| 15574 | interp->framePtr = interp->framePtr->parent; |
| 15575 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15576 | |
| 15577 | |
| 15578 | if (interp->framePtr->tailcallObj) { |
| 15579 | do { |
| 15580 | Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; |
| 15581 | |
| 15582 | interp->framePtr->tailcallObj = NULL; |
| @@ -15588,18 +15374,18 @@ | |
| 15588 | } |
| 15589 | } |
| 15590 | Jim_DecrRefCount(interp, tailcallObj); |
| 15591 | } while (interp->framePtr->tailcallObj); |
| 15592 | |
| 15593 | |
| 15594 | if (interp->framePtr->tailcallCmd) { |
| 15595 | JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); |
| 15596 | interp->framePtr->tailcallCmd = NULL; |
| 15597 | } |
| 15598 | } |
| 15599 | |
| 15600 | |
| 15601 | if (retcode == JIM_RETURN) { |
| 15602 | if (--interp->returnLevel <= 0) { |
| 15603 | retcode = interp->returnCode; |
| 15604 | interp->returnCode = JIM_OK; |
| 15605 | interp->returnLevel = 0; |
| @@ -15711,20 +15497,20 @@ | |
| 15711 | prevScriptObj = interp->currentScriptObj; |
| 15712 | interp->currentScriptObj = scriptObjPtr; |
| 15713 | |
| 15714 | retcode = Jim_EvalObj(interp, scriptObjPtr); |
| 15715 | |
| 15716 | |
| 15717 | if (retcode == JIM_RETURN) { |
| 15718 | if (--interp->returnLevel <= 0) { |
| 15719 | retcode = interp->returnCode; |
| 15720 | interp->returnCode = JIM_OK; |
| 15721 | interp->returnLevel = 0; |
| 15722 | } |
| 15723 | } |
| 15724 | if (retcode == JIM_ERR) { |
| 15725 | |
| 15726 | interp->addStackTrace++; |
| 15727 | } |
| 15728 | |
| 15729 | interp->currentScriptObj = prevScriptObj; |
| 15730 | |
| @@ -15750,11 +15536,11 @@ | |
| 15750 | } |
| 15751 | if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { |
| 15752 | if (JimParseVar(pc) == JIM_OK) { |
| 15753 | return; |
| 15754 | } |
| 15755 | |
| 15756 | pc->tstart = pc->p; |
| 15757 | flags |= JIM_SUBST_NOVAR; |
| 15758 | } |
| 15759 | while (pc->len) { |
| 15760 | if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { |
| @@ -15781,32 +15567,32 @@ | |
| 15781 | const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); |
| 15782 | struct JimParserCtx parser; |
| 15783 | struct ScriptObj *script = Jim_Alloc(sizeof(*script)); |
| 15784 | ParseTokenList tokenlist; |
| 15785 | |
| 15786 | |
| 15787 | ScriptTokenListInit(&tokenlist); |
| 15788 | |
| 15789 | JimParserInit(&parser, scriptText, scriptTextLen, 1); |
| 15790 | while (1) { |
| 15791 | JimParseSubst(&parser, flags); |
| 15792 | if (parser.eof) { |
| 15793 | |
| 15794 | break; |
| 15795 | } |
| 15796 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 15797 | parser.tline); |
| 15798 | } |
| 15799 | |
| 15800 | |
| 15801 | script->inUse = 1; |
| 15802 | script->substFlags = flags; |
| 15803 | script->fileNameObj = interp->emptyObj; |
| 15804 | Jim_IncrRefCount(script->fileNameObj); |
| 15805 | SubstObjAddTokens(interp, script, &tokenlist); |
| 15806 | |
| 15807 | |
| 15808 | ScriptTokenListFree(&tokenlist); |
| 15809 | |
| 15810 | #ifdef DEBUG_SHOW_SUBST |
| 15811 | { |
| 15812 | int i; |
| @@ -15817,11 +15603,11 @@ | |
| 15817 | Jim_String(script->token[i].objPtr)); |
| 15818 | } |
| 15819 | } |
| 15820 | #endif |
| 15821 | |
| 15822 | |
| 15823 | Jim_FreeIntRep(interp, objPtr); |
| 15824 | Jim_SetIntRepPtr(objPtr, script); |
| 15825 | objPtr->typePtr = &scriptObjType; |
| 15826 | return JIM_OK; |
| 15827 | } |
| @@ -15835,11 +15621,11 @@ | |
| 15835 | |
| 15836 | int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) |
| 15837 | { |
| 15838 | ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); |
| 15839 | |
| 15840 | Jim_IncrRefCount(substObjPtr); |
| 15841 | script->inUse++; |
| 15842 | |
| 15843 | *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); |
| 15844 | |
| 15845 | script->inUse--; |
| @@ -15851,22 +15637,24 @@ | |
| 15851 | } |
| 15852 | |
| 15853 | void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg) |
| 15854 | { |
| 15855 | Jim_Obj *objPtr; |
| 15856 | Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc); |
| 15857 | |
| 15858 | if (*msg) { |
| 15859 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1)); |
| 15860 | } |
| 15861 | Jim_IncrRefCount(listObjPtr); |
| 15862 | objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1); |
| 15863 | Jim_DecrRefCount(interp, listObjPtr); |
| 15864 | |
| 15865 | Jim_IncrRefCount(objPtr); |
| 15866 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr); |
| 15867 | Jim_DecrRefCount(interp, objPtr); |
| 15868 | } |
| 15869 | |
| 15870 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15871 | Jim_HashEntry *he, int type); |
| 15872 | |
| @@ -15876,11 +15664,11 @@ | |
| 15876 | JimHashtableIteratorCallbackType *callback, int type) |
| 15877 | { |
| 15878 | Jim_HashEntry *he; |
| 15879 | Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 15880 | |
| 15881 | |
| 15882 | if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { |
| 15883 | he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); |
| 15884 | if (he) { |
| 15885 | callback(interp, listObjPtr, he, type); |
| 15886 | } |
| @@ -15907,11 +15695,11 @@ | |
| 15907 | { |
| 15908 | Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); |
| 15909 | Jim_Obj *objPtr; |
| 15910 | |
| 15911 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15912 | |
| 15913 | return; |
| 15914 | } |
| 15915 | |
| 15916 | objPtr = Jim_NewStringObj(interp, he->key, -1); |
| 15917 | Jim_IncrRefCount(objPtr); |
| @@ -15967,11 +15755,11 @@ | |
| 15967 | |
| 15968 | targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); |
| 15969 | if (targetCallFrame == NULL) { |
| 15970 | return JIM_ERR; |
| 15971 | } |
| 15972 | |
| 15973 | if (targetCallFrame == interp->topFramePtr) { |
| 15974 | Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); |
| 15975 | return JIM_ERR; |
| 15976 | } |
| 15977 | if (info_level_cmd) { |
| @@ -16095,12 +15883,17 @@ | |
| 16095 | doubleRes = (double)res; |
| 16096 | goto trydouble; |
| 16097 | } |
| 16098 | if (op == JIM_EXPROP_SUB) |
| 16099 | res -= wideValue; |
| 16100 | else |
| 16101 | res /= wideValue; |
| 16102 | } |
| 16103 | Jim_SetResultInt(interp, res); |
| 16104 | return JIM_OK; |
| 16105 | trydouble: |
| 16106 | for (; i < argc; i++) { |
| @@ -16154,11 +15947,11 @@ | |
| 16154 | if (!objPtr) |
| 16155 | return JIM_ERR; |
| 16156 | Jim_SetResult(interp, objPtr); |
| 16157 | return JIM_OK; |
| 16158 | } |
| 16159 | |
| 16160 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 16161 | return JIM_ERR; |
| 16162 | Jim_SetResult(interp, argv[2]); |
| 16163 | return JIM_OK; |
| 16164 | } |
| @@ -16197,11 +15990,11 @@ | |
| 16197 | if (argc != 3) { |
| 16198 | Jim_WrongNumArgs(interp, 1, argv, "condition body"); |
| 16199 | return JIM_ERR; |
| 16200 | } |
| 16201 | |
| 16202 | |
| 16203 | while (1) { |
| 16204 | int boolean, retval; |
| 16205 | |
| 16206 | if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) |
| 16207 | return retval; |
| @@ -16237,11 +16030,11 @@ | |
| 16237 | if (argc != 5) { |
| 16238 | Jim_WrongNumArgs(interp, 1, argv, "start test next body"); |
| 16239 | return JIM_ERR; |
| 16240 | } |
| 16241 | |
| 16242 | |
| 16243 | if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) { |
| 16244 | return retval; |
| 16245 | } |
| 16246 | |
| 16247 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); |
| @@ -16248,78 +16041,84 @@ | |
| 16248 | |
| 16249 | |
| 16250 | #ifdef JIM_OPTIMIZATION |
| 16251 | if (retval == JIM_OK && boolean) { |
| 16252 | ScriptObj *incrScript; |
| 16253 | ExprByteCode *expr; |
| 16254 | jim_wide stop, currentVal; |
| 16255 | Jim_Obj *objPtr; |
| 16256 | int cmpOffset; |
| 16257 | |
| 16258 | |
| 16259 | expr = JimGetExpression(interp, argv[2]); |
| 16260 | incrScript = JimGetScript(interp, argv[3]); |
| 16261 | |
| 16262 | |
| 16263 | if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { |
| 16264 | goto evalstart; |
| 16265 | } |
| 16266 | |
| 16267 | if (incrScript->token[1].type != JIM_TT_ESC || |
| 16268 | expr->token[0].type != JIM_TT_VAR || |
| 16269 | (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) { |
| 16270 | goto evalstart; |
| 16271 | } |
| 16272 | |
| 16273 | if (expr->token[2].type == JIM_EXPROP_LT) { |
| 16274 | cmpOffset = 0; |
| 16275 | } |
| 16276 | else if (expr->token[2].type == JIM_EXPROP_LTE) { |
| 16277 | cmpOffset = 1; |
| 16278 | } |
| 16279 | else { |
| 16280 | goto evalstart; |
| 16281 | } |
| 16282 | |
| 16283 | |
| 16284 | if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { |
| 16285 | goto evalstart; |
| 16286 | } |
| 16287 | |
| 16288 | |
| 16289 | if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) { |
| 16290 | goto evalstart; |
| 16291 | } |
| 16292 | |
| 16293 | |
| 16294 | if (expr->token[1].type == JIM_TT_EXPR_INT) { |
| 16295 | if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) { |
| 16296 | goto evalstart; |
| 16297 | } |
| 16298 | } |
| 16299 | else { |
| 16300 | stopVarNamePtr = expr->token[1].objPtr; |
| 16301 | Jim_IncrRefCount(stopVarNamePtr); |
| 16302 | |
| 16303 | stop = 0; |
| 16304 | } |
| 16305 | |
| 16306 | |
| 16307 | varNamePtr = expr->token[0].objPtr; |
| 16308 | Jim_IncrRefCount(varNamePtr); |
| 16309 | |
| 16310 | objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); |
| 16311 | if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { |
| 16312 | goto testcond; |
| 16313 | } |
| 16314 | |
| 16315 | |
| 16316 | while (retval == JIM_OK) { |
| 16317 | |
| 16318 | |
| 16319 | |
| 16320 | |
| 16321 | if (stopVarNamePtr) { |
| 16322 | objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE); |
| 16323 | if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) { |
| 16324 | goto testcond; |
| 16325 | } |
| @@ -16327,18 +16126,18 @@ | |
| 16327 | |
| 16328 | if (currentVal >= stop + cmpOffset) { |
| 16329 | break; |
| 16330 | } |
| 16331 | |
| 16332 | |
| 16333 | retval = Jim_EvalObj(interp, argv[4]); |
| 16334 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16335 | retval = JIM_OK; |
| 16336 | |
| 16337 | objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); |
| 16338 | |
| 16339 | |
| 16340 | if (objPtr == NULL) { |
| 16341 | retval = JIM_ERR; |
| 16342 | goto out; |
| 16343 | } |
| 16344 | if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { |
| @@ -16358,25 +16157,25 @@ | |
| 16358 | } |
| 16359 | evalstart: |
| 16360 | #endif |
| 16361 | |
| 16362 | while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) { |
| 16363 | |
| 16364 | retval = Jim_EvalObj(interp, argv[4]); |
| 16365 | |
| 16366 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16367 | |
| 16368 | evalnext: |
| 16369 | retval = Jim_EvalObj(interp, argv[3]); |
| 16370 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16371 | |
| 16372 | testcond: |
| 16373 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); |
| 16374 | } |
| 16375 | } |
| 16376 | } |
| 16377 | out: |
| 16378 | if (stopVarNamePtr) { |
| 16379 | Jim_DecrRefCount(interp, stopVarNamePtr); |
| 16380 | } |
| 16381 | if (varNamePtr) { |
| 16382 | Jim_DecrRefCount(interp, varNamePtr); |
| @@ -16418,11 +16217,11 @@ | |
| 16418 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16419 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); |
| 16420 | |
| 16421 | retval = JIM_OK; |
| 16422 | |
| 16423 | |
| 16424 | i += incr; |
| 16425 | |
| 16426 | if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { |
| 16427 | if (argv[1]->typePtr != &variableObjType) { |
| 16428 | if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { |
| @@ -16483,21 +16282,21 @@ | |
| 16483 | |
| 16484 | static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) |
| 16485 | { |
| 16486 | int result = JIM_OK; |
| 16487 | int i, numargs; |
| 16488 | Jim_ListIter twoiters[2]; |
| 16489 | Jim_ListIter *iters; |
| 16490 | Jim_Obj *script; |
| 16491 | Jim_Obj *resultObj; |
| 16492 | |
| 16493 | if (argc < 4 || argc % 2 != 0) { |
| 16494 | Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script"); |
| 16495 | return JIM_ERR; |
| 16496 | } |
| 16497 | script = argv[argc - 1]; |
| 16498 | numargs = (argc - 1 - 1); |
| 16499 | |
| 16500 | if (numargs == 2) { |
| 16501 | iters = twoiters; |
| 16502 | } |
| 16503 | else { |
| @@ -16521,34 +16320,34 @@ | |
| 16521 | resultObj = interp->emptyObj; |
| 16522 | } |
| 16523 | Jim_IncrRefCount(resultObj); |
| 16524 | |
| 16525 | while (1) { |
| 16526 | |
| 16527 | for (i = 0; i < numargs; i += 2) { |
| 16528 | if (!JimListIterDone(interp, &iters[i + 1])) { |
| 16529 | break; |
| 16530 | } |
| 16531 | } |
| 16532 | if (i == numargs) { |
| 16533 | |
| 16534 | break; |
| 16535 | } |
| 16536 | |
| 16537 | |
| 16538 | for (i = 0; i < numargs; i += 2) { |
| 16539 | Jim_Obj *varName; |
| 16540 | |
| 16541 | |
| 16542 | JimListIterInit(&iters[i], argv[i + 1]); |
| 16543 | while ((varName = JimListIterNext(interp, &iters[i])) != NULL) { |
| 16544 | Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]); |
| 16545 | if (!valObj) { |
| 16546 | |
| 16547 | valObj = interp->emptyObj; |
| 16548 | } |
| 16549 | |
| 16550 | Jim_IncrRefCount(valObj); |
| 16551 | result = Jim_SetVariable(interp, varName, valObj); |
| 16552 | Jim_DecrRefCount(interp, valObj); |
| 16553 | if (result != JIM_OK) { |
| 16554 | goto err; |
| @@ -16630,41 +16429,41 @@ | |
| 16630 | { |
| 16631 | int boolean, retval, current = 1, falsebody = 0; |
| 16632 | |
| 16633 | if (argc >= 3) { |
| 16634 | while (1) { |
| 16635 | |
| 16636 | if (current >= argc) |
| 16637 | goto err; |
| 16638 | if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean)) |
| 16639 | != JIM_OK) |
| 16640 | return retval; |
| 16641 | |
| 16642 | if (current >= argc) |
| 16643 | goto err; |
| 16644 | if (Jim_CompareStringImmediate(interp, argv[current], "then")) |
| 16645 | current++; |
| 16646 | |
| 16647 | if (current >= argc) |
| 16648 | goto err; |
| 16649 | if (boolean) |
| 16650 | return Jim_EvalObj(interp, argv[current]); |
| 16651 | |
| 16652 | if (++current >= argc) { |
| 16653 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 16654 | return JIM_OK; |
| 16655 | } |
| 16656 | falsebody = current++; |
| 16657 | if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) { |
| 16658 | |
| 16659 | if (current != argc - 1) |
| 16660 | goto err; |
| 16661 | return Jim_EvalObj(interp, argv[current]); |
| 16662 | } |
| 16663 | else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif")) |
| 16664 | continue; |
| 16665 | |
| 16666 | else if (falsebody != argc - 1) |
| 16667 | goto err; |
| 16668 | return Jim_EvalObj(interp, argv[falsebody]); |
| 16669 | } |
| 16670 | return JIM_OK; |
| @@ -16698,19 +16497,17 @@ | |
| 16698 | } |
| 16699 | |
| 16700 | return eq; |
| 16701 | } |
| 16702 | |
| 16703 | enum |
| 16704 | { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; |
| 16705 | |
| 16706 | |
| 16707 | static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16708 | { |
| 16709 | int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; |
| 16710 | Jim_Obj *command = 0, *const *caseList = 0, *strObj; |
| 16711 | Jim_Obj *script = 0; |
| 16712 | |
| 16713 | if (argc < 3) { |
| 16714 | wrongnumargs: |
| 16715 | Jim_WrongNumArgs(interp, 1, argv, "?options? string " |
| 16716 | "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); |
| @@ -16747,68 +16544,62 @@ | |
| 16747 | goto wrongnumargs; |
| 16748 | } |
| 16749 | strObj = argv[opt++]; |
| 16750 | patCount = argc - opt; |
| 16751 | if (patCount == 1) { |
| 16752 | Jim_Obj **vector; |
| 16753 | |
| 16754 | JimListGetElements(interp, argv[opt], &patCount, &vector); |
| 16755 | caseList = vector; |
| 16756 | } |
| 16757 | else |
| 16758 | caseList = &argv[opt]; |
| 16759 | if (patCount == 0 || patCount % 2 != 0) |
| 16760 | goto wrongnumargs; |
| 16761 | for (i = 0; script == 0 && i < patCount; i += 2) { |
| 16762 | Jim_Obj *patObj = caseList[i]; |
| 16763 | |
| 16764 | if (!Jim_CompareStringImmediate(interp, patObj, "default") |
| 16765 | || i < (patCount - 2)) { |
| 16766 | switch (matchOpt) { |
| 16767 | case SWITCH_EXACT: |
| 16768 | if (Jim_StringEqObj(strObj, patObj)) |
| 16769 | script = caseList[i + 1]; |
| 16770 | break; |
| 16771 | case SWITCH_GLOB: |
| 16772 | if (Jim_StringMatchObj(interp, patObj, strObj, 0)) |
| 16773 | script = caseList[i + 1]; |
| 16774 | break; |
| 16775 | case SWITCH_RE: |
| 16776 | command = Jim_NewStringObj(interp, "regexp", -1); |
| 16777 | |
| 16778 | case SWITCH_CMD:{ |
| 16779 | int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); |
| 16780 | |
| 16781 | if (argc - opt == 1) { |
| 16782 | Jim_Obj **vector; |
| 16783 | |
| 16784 | JimListGetElements(interp, argv[opt], &patCount, &vector); |
| 16785 | caseList = vector; |
| 16786 | } |
| 16787 | |
| 16788 | if (rc < 0) { |
| 16789 | return -rc; |
| 16790 | } |
| 16791 | if (rc) |
| 16792 | script = caseList[i + 1]; |
| 16793 | break; |
| 16794 | } |
| 16795 | } |
| 16796 | } |
| 16797 | else { |
| 16798 | script = caseList[i + 1]; |
| 16799 | } |
| 16800 | } |
| 16801 | for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2) |
| 16802 | script = caseList[i + 1]; |
| 16803 | if (script && Jim_CompareStringImmediate(interp, script, "-")) { |
| 16804 | Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); |
| 16805 | return JIM_ERR; |
| 16806 | } |
| 16807 | Jim_SetEmptyResult(interp); |
| 16808 | if (script) { |
| 16809 | return Jim_EvalObj(interp, script); |
| 16810 | } |
| 16811 | return JIM_OK; |
| 16812 | } |
| 16813 | |
| 16814 | |
| @@ -16920,11 +16711,11 @@ | |
| 16920 | case OPT_COMMAND: |
| 16921 | if (i >= argc - 2) { |
| 16922 | goto wrongargs; |
| 16923 | } |
| 16924 | commandObj = argv[++i]; |
| 16925 | |
| 16926 | case OPT_EXACT: |
| 16927 | case OPT_GLOB: |
| 16928 | case OPT_REGEXP: |
| 16929 | opt_match = option; |
| 16930 | break; |
| @@ -16968,17 +16759,17 @@ | |
| 16968 | goto done; |
| 16969 | } |
| 16970 | break; |
| 16971 | } |
| 16972 | |
| 16973 | |
| 16974 | if (!eq && opt_bool && opt_not && !opt_all) { |
| 16975 | continue; |
| 16976 | } |
| 16977 | |
| 16978 | if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { |
| 16979 | |
| 16980 | Jim_Obj *resultObj; |
| 16981 | |
| 16982 | if (opt_bool) { |
| 16983 | resultObj = Jim_NewIntObj(interp, eq ^ opt_not); |
| 16984 | } |
| @@ -17001,11 +16792,11 @@ | |
| 17001 | |
| 17002 | if (opt_all) { |
| 17003 | Jim_SetResult(interp, listObjPtr); |
| 17004 | } |
| 17005 | else { |
| 17006 | |
| 17007 | if (opt_bool) { |
| 17008 | Jim_SetResultBool(interp, opt_not); |
| 17009 | } |
| 17010 | else if (!opt_inline) { |
| 17011 | Jim_SetResultInt(interp, -1); |
| @@ -17030,11 +16821,11 @@ | |
| 17030 | Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); |
| 17031 | return JIM_ERR; |
| 17032 | } |
| 17033 | listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 17034 | if (!listObjPtr) { |
| 17035 | |
| 17036 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 17037 | new_obj = 1; |
| 17038 | } |
| 17039 | else if (Jim_IsShared(listObjPtr)) { |
| 17040 | listObjPtr = Jim_DuplicateObj(interp, listObjPtr); |
| @@ -17103,31 +16894,31 @@ | |
| 17103 | first = JimRelToAbsIndex(len, first); |
| 17104 | last = JimRelToAbsIndex(len, last); |
| 17105 | JimRelToAbsRange(len, &first, &last, &rangeLen); |
| 17106 | |
| 17107 | |
| 17108 | |
| 17109 | if (first < len) { |
| 17110 | |
| 17111 | } |
| 17112 | else if (len == 0) { |
| 17113 | |
| 17114 | first = 0; |
| 17115 | } |
| 17116 | else { |
| 17117 | Jim_SetResultString(interp, "list doesn't contain element ", -1); |
| 17118 | Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]); |
| 17119 | return JIM_ERR; |
| 17120 | } |
| 17121 | |
| 17122 | |
| 17123 | newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first); |
| 17124 | |
| 17125 | |
| 17126 | ListInsertElements(newListObj, -1, argc - 4, argv + 4); |
| 17127 | |
| 17128 | |
| 17129 | ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen); |
| 17130 | |
| 17131 | Jim_SetResult(interp, newListObj); |
| 17132 | return JIM_OK; |
| 17133 | } |
| @@ -17138,11 +16929,11 @@ | |
| 17138 | if (argc < 3) { |
| 17139 | Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 17140 | return JIM_ERR; |
| 17141 | } |
| 17142 | else if (argc == 3) { |
| 17143 | |
| 17144 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 17145 | return JIM_ERR; |
| 17146 | Jim_SetResult(interp, argv[2]); |
| 17147 | return JIM_OK; |
| 17148 | } |
| @@ -17158,10 +16949,11 @@ | |
| 17158 | enum |
| 17159 | { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; |
| 17160 | Jim_Obj *resObj; |
| 17161 | int i; |
| 17162 | int retCode; |
| 17163 | |
| 17164 | struct lsort_info info; |
| 17165 | |
| 17166 | if (argc < 2) { |
| 17167 | Jim_WrongNumArgs(interp, 1, argv, "?options? list"); |
| @@ -17223,16 +17015,18 @@ | |
| 17223 | info.indexed = 1; |
| 17224 | i++; |
| 17225 | break; |
| 17226 | } |
| 17227 | } |
| 17228 | resObj = Jim_DuplicateObj(interp, argv[argc - 1]); |
| 17229 | retCode = ListSortElements(interp, resObj, &info); |
| 17230 | if (retCode == JIM_OK) { |
| 17231 | Jim_SetResult(interp, resObj); |
| 17232 | } |
| 17233 | else { |
| 17234 | Jim_FreeNewObj(interp, resObj); |
| 17235 | } |
| 17236 | return retCode; |
| 17237 | } |
| 17238 | |
| @@ -17253,11 +17047,11 @@ | |
| 17253 | } |
| 17254 | else { |
| 17255 | int new_obj = 0; |
| 17256 | stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 17257 | if (!stringObjPtr) { |
| 17258 | |
| 17259 | stringObjPtr = Jim_NewEmptyStringObj(interp); |
| 17260 | new_obj = 1; |
| 17261 | } |
| 17262 | else if (Jim_IsShared(stringObjPtr)) { |
| 17263 | new_obj = 1; |
| @@ -17274,10 +17068,11 @@ | |
| 17274 | } |
| 17275 | } |
| 17276 | Jim_SetResult(interp, stringObjPtr); |
| 17277 | return JIM_OK; |
| 17278 | } |
| 17279 | |
| 17280 | |
| 17281 | static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17282 | { |
| 17283 | #if !defined(JIM_DEBUG_COMMAND) |
| @@ -17302,11 +17097,11 @@ | |
| 17302 | else { |
| 17303 | rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); |
| 17304 | } |
| 17305 | |
| 17306 | if (rc == JIM_ERR) { |
| 17307 | |
| 17308 | interp->addStackTrace++; |
| 17309 | } |
| 17310 | return rc; |
| 17311 | } |
| 17312 | |
| @@ -17316,14 +17111,14 @@ | |
| 17316 | if (argc >= 2) { |
| 17317 | int retcode; |
| 17318 | Jim_CallFrame *savedCallFrame, *targetCallFrame; |
| 17319 | const char *str; |
| 17320 | |
| 17321 | |
| 17322 | savedCallFrame = interp->framePtr; |
| 17323 | |
| 17324 | |
| 17325 | str = Jim_String(argv[1]); |
| 17326 | if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { |
| 17327 | targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17328 | argc--; |
| 17329 | argv++; |
| @@ -17336,11 +17131,11 @@ | |
| 17336 | } |
| 17337 | if (argc < 2) { |
| 17338 | Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); |
| 17339 | return JIM_ERR; |
| 17340 | } |
| 17341 | |
| 17342 | interp->framePtr = targetCallFrame; |
| 17343 | if (argc == 2) { |
| 17344 | retcode = Jim_EvalObj(interp, argv[1]); |
| 17345 | } |
| 17346 | else { |
| @@ -17356,32 +17151,29 @@ | |
| 17356 | } |
| 17357 | |
| 17358 | |
| 17359 | static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17360 | { |
| 17361 | Jim_Obj *exprResultPtr; |
| 17362 | int retcode; |
| 17363 | |
| 17364 | if (argc == 2) { |
| 17365 | retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr); |
| 17366 | } |
| 17367 | else if (argc > 2) { |
| 17368 | Jim_Obj *objPtr; |
| 17369 | |
| 17370 | objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); |
| 17371 | Jim_IncrRefCount(objPtr); |
| 17372 | retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr); |
| 17373 | Jim_DecrRefCount(interp, objPtr); |
| 17374 | } |
| 17375 | else { |
| 17376 | Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); |
| 17377 | return JIM_ERR; |
| 17378 | } |
| 17379 | if (retcode != JIM_OK) |
| 17380 | return retcode; |
| 17381 | Jim_SetResult(interp, exprResultPtr); |
| 17382 | Jim_DecrRefCount(interp, exprResultPtr); |
| 17383 | return JIM_OK; |
| 17384 | } |
| 17385 | |
| 17386 | |
| 17387 | static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -17438,15 +17230,15 @@ | |
| 17438 | if (i != argc - 1 && i != argc) { |
| 17439 | Jim_WrongNumArgs(interp, 1, argv, |
| 17440 | "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?"); |
| 17441 | } |
| 17442 | |
| 17443 | |
| 17444 | if (stackTraceObj && returnCode == JIM_ERR) { |
| 17445 | JimSetStackTrace(interp, stackTraceObj); |
| 17446 | } |
| 17447 | |
| 17448 | if (errorCodeObj && returnCode == JIM_ERR) { |
| 17449 | Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj); |
| 17450 | } |
| 17451 | interp->returnCode = returnCode; |
| 17452 | interp->returnLevel = level; |
| @@ -17463,31 +17255,31 @@ | |
| 17463 | if (interp->framePtr->level == 0) { |
| 17464 | Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); |
| 17465 | return JIM_ERR; |
| 17466 | } |
| 17467 | else if (argc >= 2) { |
| 17468 | |
| 17469 | Jim_CallFrame *cf = interp->framePtr->parent; |
| 17470 | |
| 17471 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17472 | if (cmdPtr == NULL) { |
| 17473 | return JIM_ERR; |
| 17474 | } |
| 17475 | |
| 17476 | JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); |
| 17477 | |
| 17478 | |
| 17479 | JimIncrCmdRefCount(cmdPtr); |
| 17480 | cf->tailcallCmd = cmdPtr; |
| 17481 | |
| 17482 | |
| 17483 | JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); |
| 17484 | |
| 17485 | cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); |
| 17486 | Jim_IncrRefCount(cf->tailcallObj); |
| 17487 | |
| 17488 | |
| 17489 | return JIM_EVAL; |
| 17490 | } |
| 17491 | return JIM_OK; |
| 17492 | } |
| 17493 | |
| @@ -17494,11 +17286,11 @@ | |
| 17494 | static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17495 | { |
| 17496 | Jim_Obj *cmdList; |
| 17497 | Jim_Obj *prefixListObj = Jim_CmdPrivData(interp); |
| 17498 | |
| 17499 | |
| 17500 | cmdList = Jim_DuplicateObj(interp, prefixListObj); |
| 17501 | Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1); |
| 17502 | |
| 17503 | return JimEvalObjList(interp, cmdList); |
| 17504 | } |
| @@ -17552,22 +17344,22 @@ | |
| 17552 | else { |
| 17553 | cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL); |
| 17554 | } |
| 17555 | |
| 17556 | if (cmd) { |
| 17557 | |
| 17558 | Jim_Obj *qualifiedCmdNameObj; |
| 17559 | const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj); |
| 17560 | |
| 17561 | JimCreateCommand(interp, cmdname, cmd); |
| 17562 | |
| 17563 | |
| 17564 | JimUpdateProcNamespace(interp, cmd, cmdname); |
| 17565 | |
| 17566 | JimFreeQualifiedName(interp, qualifiedCmdNameObj); |
| 17567 | |
| 17568 | |
| 17569 | Jim_SetResult(interp, argv[1]); |
| 17570 | return JIM_OK; |
| 17571 | } |
| 17572 | return JIM_ERR; |
| 17573 | } |
| @@ -17580,17 +17372,17 @@ | |
| 17580 | if (argc < 2) { |
| 17581 | Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); |
| 17582 | return JIM_ERR; |
| 17583 | } |
| 17584 | |
| 17585 | |
| 17586 | interp->local++; |
| 17587 | retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); |
| 17588 | interp->local--; |
| 17589 | |
| 17590 | |
| 17591 | |
| 17592 | if (retcode == 0) { |
| 17593 | Jim_Obj *cmdNameObj = Jim_GetResult(interp); |
| 17594 | |
| 17595 | if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) { |
| 17596 | return JIM_ERR; |
| @@ -17619,18 +17411,18 @@ | |
| 17619 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17620 | if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) { |
| 17621 | Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]); |
| 17622 | return JIM_ERR; |
| 17623 | } |
| 17624 | |
| 17625 | cmdPtr->u.proc.upcall++; |
| 17626 | JimIncrCmdRefCount(cmdPtr); |
| 17627 | |
| 17628 | |
| 17629 | retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); |
| 17630 | |
| 17631 | |
| 17632 | cmdPtr->u.proc.upcall--; |
| 17633 | JimDecrCmdRefCount(interp, cmdPtr); |
| 17634 | |
| 17635 | return retcode; |
| 17636 | } |
| @@ -17657,11 +17449,11 @@ | |
| 17657 | return JIM_ERR; |
| 17658 | } |
| 17659 | |
| 17660 | if (len == 3) { |
| 17661 | #ifdef jim_ext_namespace |
| 17662 | |
| 17663 | nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2)); |
| 17664 | #else |
| 17665 | Jim_SetResultString(interp, "namespaces not enabled", -1); |
| 17666 | return JIM_ERR; |
| 17667 | #endif |
| @@ -17670,11 +17462,11 @@ | |
| 17670 | bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1); |
| 17671 | |
| 17672 | cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj); |
| 17673 | |
| 17674 | if (cmd) { |
| 17675 | |
| 17676 | nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv)); |
| 17677 | nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1); |
| 17678 | Jim_IncrRefCount(nargv[0]); |
| 17679 | memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv)); |
| 17680 | ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv); |
| @@ -17700,11 +17492,11 @@ | |
| 17700 | static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17701 | { |
| 17702 | int i; |
| 17703 | Jim_CallFrame *targetCallFrame; |
| 17704 | |
| 17705 | |
| 17706 | if (argc > 3 && (argc % 2 == 0)) { |
| 17707 | targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17708 | argc--; |
| 17709 | argv++; |
| 17710 | } |
| @@ -17713,17 +17505,17 @@ | |
| 17713 | } |
| 17714 | if (targetCallFrame == NULL) { |
| 17715 | return JIM_ERR; |
| 17716 | } |
| 17717 | |
| 17718 | |
| 17719 | if (argc < 3) { |
| 17720 | Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?"); |
| 17721 | return JIM_ERR; |
| 17722 | } |
| 17723 | |
| 17724 | |
| 17725 | for (i = 1; i < argc; i += 2) { |
| 17726 | if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK) |
| 17727 | return JIM_ERR; |
| 17728 | } |
| 17729 | return JIM_OK; |
| @@ -17736,15 +17528,15 @@ | |
| 17736 | |
| 17737 | if (argc < 2) { |
| 17738 | Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?"); |
| 17739 | return JIM_ERR; |
| 17740 | } |
| 17741 | |
| 17742 | if (interp->framePtr->level == 0) |
| 17743 | return JIM_OK; |
| 17744 | for (i = 1; i < argc; i++) { |
| 17745 | |
| 17746 | const char *name = Jim_String(argv[i]); |
| 17747 | if (name[0] != ':' || name[1] != ':') { |
| 17748 | if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK) |
| 17749 | return JIM_ERR; |
| 17750 | } |
| @@ -17767,21 +17559,21 @@ | |
| 17767 | } |
| 17768 | |
| 17769 | str = Jim_String(objPtr); |
| 17770 | strLen = Jim_Utf8Length(interp, objPtr); |
| 17771 | |
| 17772 | |
| 17773 | resultObjPtr = Jim_NewStringObj(interp, "", 0); |
| 17774 | while (strLen) { |
| 17775 | for (i = 0; i < numMaps; i += 2) { |
| 17776 | Jim_Obj *objPtr; |
| 17777 | const char *k; |
| 17778 | int kl; |
| 17779 | |
| 17780 | objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); |
| 17781 | k = Jim_String(objPtr); |
| 17782 | kl = Jim_Utf8Length(interp, objPtr); |
| 17783 | |
| 17784 | if (strLen >= kl && kl) { |
| 17785 | int rc; |
| 17786 | rc = JimStringCompareLen(str, k, kl, nocase); |
| 17787 | if (rc == 0) { |
| @@ -17794,11 +17586,11 @@ | |
| 17794 | strLen -= kl; |
| 17795 | break; |
| 17796 | } |
| 17797 | } |
| 17798 | } |
| 17799 | if (i == numMaps) { |
| 17800 | int c; |
| 17801 | if (noMatchStart == NULL) |
| 17802 | noMatchStart = str; |
| 17803 | str += utf8_tounicode(str, &c); |
| 17804 | strLen--; |
| @@ -17838,11 +17630,11 @@ | |
| 17838 | Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); |
| 17839 | return JIM_ERR; |
| 17840 | } |
| 17841 | if (Jim_GetEnum(interp, argv[1], options, &option, NULL, |
| 17842 | JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) |
| 17843 | return JIM_ERR; |
| 17844 | |
| 17845 | switch (option) { |
| 17846 | case OPT_LENGTH: |
| 17847 | case OPT_BYTELENGTH: |
| 17848 | if (argc != 3) { |
| @@ -17859,11 +17651,11 @@ | |
| 17859 | return JIM_OK; |
| 17860 | |
| 17861 | case OPT_CAT:{ |
| 17862 | Jim_Obj *objPtr; |
| 17863 | if (argc == 3) { |
| 17864 | |
| 17865 | objPtr = argv[2]; |
| 17866 | } |
| 17867 | else { |
| 17868 | int i; |
| 17869 | |
| @@ -17878,11 +17670,11 @@ | |
| 17878 | } |
| 17879 | |
| 17880 | case OPT_COMPARE: |
| 17881 | case OPT_EQUAL: |
| 17882 | { |
| 17883 | |
| 17884 | long opt_length = -1; |
| 17885 | int n = argc - 4; |
| 17886 | int i = 2; |
| 17887 | while (n > 0) { |
| 17888 | int subopt; |
| @@ -17891,16 +17683,16 @@ | |
| 17891 | badcompareargs: |
| 17892 | Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2"); |
| 17893 | return JIM_ERR; |
| 17894 | } |
| 17895 | if (subopt == 0) { |
| 17896 | |
| 17897 | opt_case = 0; |
| 17898 | n--; |
| 17899 | } |
| 17900 | else { |
| 17901 | |
| 17902 | if (n < 2) { |
| 17903 | goto badcompareargs; |
| 17904 | } |
| 17905 | if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) { |
| 17906 | return JIM_ERR; |
| @@ -17911,11 +17703,11 @@ | |
| 17911 | if (n) { |
| 17912 | goto badcompareargs; |
| 17913 | } |
| 17914 | argv += argc - 2; |
| 17915 | if (opt_length < 0 && option != OPT_COMPARE && opt_case) { |
| 17916 | |
| 17917 | Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1])); |
| 17918 | } |
| 17919 | else { |
| 17920 | if (opt_length >= 0) { |
| 17921 | n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case); |
| @@ -18025,11 +17817,10 @@ | |
| 18025 | } |
| 18026 | |
| 18027 | case OPT_REVERSE:{ |
| 18028 | char *buf, *p; |
| 18029 | const char *str; |
| 18030 | int len; |
| 18031 | int i; |
| 18032 | |
| 18033 | if (argc != 3) { |
| 18034 | Jim_WrongNumArgs(interp, 2, argv, "string"); |
| 18035 | return JIM_ERR; |
| @@ -18069,11 +17860,11 @@ | |
| 18069 | } |
| 18070 | if (idx < 0 || idx >= len || str == NULL) { |
| 18071 | Jim_SetResultString(interp, "", 0); |
| 18072 | } |
| 18073 | else if (len == Jim_Length(argv[2])) { |
| 18074 | |
| 18075 | Jim_SetResultString(interp, str + idx, 1); |
| 18076 | } |
| 18077 | else { |
| 18078 | int c; |
| 18079 | int i = utf8_index(str, idx); |
| @@ -18223,11 +18014,11 @@ | |
| 18223 | { |
| 18224 | int exitCode = 0; |
| 18225 | int i; |
| 18226 | int sig = 0; |
| 18227 | |
| 18228 | |
| 18229 | jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); |
| 18230 | static const int max_ignore_code = sizeof(ignore_mask) * 8; |
| 18231 | |
| 18232 | Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); |
| 18233 | |
| @@ -18234,11 +18025,11 @@ | |
| 18234 | for (i = 1; i < argc - 1; i++) { |
| 18235 | const char *arg = Jim_String(argv[i]); |
| 18236 | jim_wide option; |
| 18237 | int ignore; |
| 18238 | |
| 18239 | |
| 18240 | if (strcmp(arg, "--") == 0) { |
| 18241 | i++; |
| 18242 | break; |
| 18243 | } |
| 18244 | if (*arg != '-') { |
| @@ -18285,28 +18076,28 @@ | |
| 18285 | sig++; |
| 18286 | } |
| 18287 | |
| 18288 | interp->signal_level += sig; |
| 18289 | if (Jim_CheckSignal(interp)) { |
| 18290 | |
| 18291 | exitCode = JIM_SIGNAL; |
| 18292 | } |
| 18293 | else { |
| 18294 | exitCode = Jim_EvalObj(interp, argv[0]); |
| 18295 | |
| 18296 | interp->errorFlag = 0; |
| 18297 | } |
| 18298 | interp->signal_level -= sig; |
| 18299 | |
| 18300 | |
| 18301 | if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { |
| 18302 | |
| 18303 | return exitCode; |
| 18304 | } |
| 18305 | |
| 18306 | if (sig && exitCode == JIM_SIGNAL) { |
| 18307 | |
| 18308 | if (interp->signal_set_result) { |
| 18309 | interp->signal_set_result(interp, interp->sigmask); |
| 18310 | } |
| 18311 | else { |
| 18312 | Jim_SetResultInt(interp, interp->sigmask); |
| @@ -18345,125 +18136,10 @@ | |
| 18345 | } |
| 18346 | Jim_SetResultInt(interp, exitCode); |
| 18347 | return JIM_OK; |
| 18348 | } |
| 18349 | |
| 18350 | #ifdef JIM_REFERENCES |
| 18351 | |
| 18352 | |
| 18353 | static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18354 | { |
| 18355 | if (argc != 3 && argc != 4) { |
| 18356 | Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?"); |
| 18357 | return JIM_ERR; |
| 18358 | } |
| 18359 | if (argc == 3) { |
| 18360 | Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL)); |
| 18361 | } |
| 18362 | else { |
| 18363 | Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3])); |
| 18364 | } |
| 18365 | return JIM_OK; |
| 18366 | } |
| 18367 | |
| 18368 | |
| 18369 | static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18370 | { |
| 18371 | Jim_Reference *refPtr; |
| 18372 | |
| 18373 | if (argc != 2) { |
| 18374 | Jim_WrongNumArgs(interp, 1, argv, "reference"); |
| 18375 | return JIM_ERR; |
| 18376 | } |
| 18377 | if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) |
| 18378 | return JIM_ERR; |
| 18379 | Jim_SetResult(interp, refPtr->objPtr); |
| 18380 | return JIM_OK; |
| 18381 | } |
| 18382 | |
| 18383 | |
| 18384 | static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18385 | { |
| 18386 | Jim_Reference *refPtr; |
| 18387 | |
| 18388 | if (argc != 3) { |
| 18389 | Jim_WrongNumArgs(interp, 1, argv, "reference newValue"); |
| 18390 | return JIM_ERR; |
| 18391 | } |
| 18392 | if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) |
| 18393 | return JIM_ERR; |
| 18394 | Jim_IncrRefCount(argv[2]); |
| 18395 | Jim_DecrRefCount(interp, refPtr->objPtr); |
| 18396 | refPtr->objPtr = argv[2]; |
| 18397 | Jim_SetResult(interp, argv[2]); |
| 18398 | return JIM_OK; |
| 18399 | } |
| 18400 | |
| 18401 | |
| 18402 | static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18403 | { |
| 18404 | if (argc != 1) { |
| 18405 | Jim_WrongNumArgs(interp, 1, argv, ""); |
| 18406 | return JIM_ERR; |
| 18407 | } |
| 18408 | Jim_SetResultInt(interp, Jim_Collect(interp)); |
| 18409 | |
| 18410 | |
| 18411 | while (interp->freeList) { |
| 18412 | Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr; |
| 18413 | Jim_Free(interp->freeList); |
| 18414 | interp->freeList = nextObjPtr; |
| 18415 | } |
| 18416 | |
| 18417 | return JIM_OK; |
| 18418 | } |
| 18419 | |
| 18420 | |
| 18421 | static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18422 | { |
| 18423 | if (argc != 2 && argc != 3) { |
| 18424 | Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?"); |
| 18425 | return JIM_ERR; |
| 18426 | } |
| 18427 | if (argc == 2) { |
| 18428 | Jim_Obj *cmdNamePtr; |
| 18429 | |
| 18430 | if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK) |
| 18431 | return JIM_ERR; |
| 18432 | if (cmdNamePtr != NULL) |
| 18433 | Jim_SetResult(interp, cmdNamePtr); |
| 18434 | } |
| 18435 | else { |
| 18436 | if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK) |
| 18437 | return JIM_ERR; |
| 18438 | Jim_SetResult(interp, argv[2]); |
| 18439 | } |
| 18440 | return JIM_OK; |
| 18441 | } |
| 18442 | |
| 18443 | |
| 18444 | static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18445 | { |
| 18446 | Jim_Obj *listObjPtr; |
| 18447 | Jim_HashTableIterator htiter; |
| 18448 | Jim_HashEntry *he; |
| 18449 | |
| 18450 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18451 | |
| 18452 | JimInitHashTableIterator(&interp->references, &htiter); |
| 18453 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18454 | char buf[JIM_REFERENCE_SPACE + 1]; |
| 18455 | Jim_Reference *refPtr = Jim_GetHashEntryVal(he); |
| 18456 | const unsigned long *refId = he->key; |
| 18457 | |
| 18458 | JimFormatReference(buf, refPtr, *refId); |
| 18459 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); |
| 18460 | } |
| 18461 | Jim_SetResult(interp, listObjPtr); |
| 18462 | return JIM_OK; |
| 18463 | } |
| 18464 | #endif |
| 18465 | |
| 18466 | |
| 18467 | static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18468 | { |
| 18469 | if (argc != 3) { |
| @@ -18476,56 +18152,43 @@ | |
| 18476 | } |
| 18477 | |
| 18478 | return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2])); |
| 18479 | } |
| 18480 | |
| 18481 | #define JIM_DICTMATCH_VALUES 0x0001 |
| 18482 | |
| 18483 | typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type); |
| 18484 | |
| 18485 | static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) |
| 18486 | { |
| 18487 | Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); |
| 18488 | if (type & JIM_DICTMATCH_VALUES) { |
| 18489 | Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); |
| 18490 | } |
| 18491 | } |
| 18492 | |
| 18493 | static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, |
| 18494 | JimDictMatchCallbackType *callback, int type) |
| 18495 | { |
| 18496 | Jim_HashEntry *he; |
| 18497 | Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18498 | |
| 18499 | |
| 18500 | Jim_HashTableIterator htiter; |
| 18501 | JimInitHashTableIterator(ht, &htiter); |
| 18502 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18503 | if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) { |
| 18504 | callback(interp, listObjPtr, he, type); |
| 18505 | } |
| 18506 | } |
| 18507 | |
| 18508 | return listObjPtr; |
| 18509 | } |
| 18510 | |
| 18511 | |
| 18512 | int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) |
| 18513 | { |
| 18514 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18515 | return JIM_ERR; |
| 18516 | } |
| 18517 | Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0)); |
| 18518 | return JIM_OK; |
| 18519 | } |
| 18520 | |
| 18521 | int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) |
| 18522 | { |
| 18523 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18524 | return JIM_ERR; |
| 18525 | } |
| 18526 | Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES)); |
| 18527 | return JIM_OK; |
| 18528 | } |
| 18529 | |
| 18530 | int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18531 | { |
| @@ -18532,38 +18195,85 @@ | |
| 18532 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18533 | return -1; |
| 18534 | } |
| 18535 | return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 18536 | } |
| 18537 | |
| 18538 | int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18539 | { |
| 18540 | Jim_HashTable *ht; |
| 18541 | unsigned int i; |
| 18542 | |
| 18543 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18544 | return JIM_ERR; |
| 18545 | } |
| 18546 | |
| 18547 | ht = (Jim_HashTable *)objPtr->internalRep.ptr; |
| 18548 | |
| 18549 | |
| 18550 | printf("%d entries in table, %d buckets\n", ht->used, ht->size); |
| 18551 | |
| 18552 | for (i = 0; i < ht->size; i++) { |
| 18553 | Jim_HashEntry *he = ht->table[i]; |
| 18554 | |
| 18555 | if (he) { |
| 18556 | printf("%d: ", i); |
| 18557 | |
| 18558 | while (he) { |
| 18559 | printf(" %s", Jim_String(he->key)); |
| 18560 | he = he->next; |
| 18561 | } |
| 18562 | printf("\n"); |
| 18563 | } |
| 18564 | } |
| 18565 | return JIM_OK; |
| 18566 | } |
| 18567 | |
| 18568 | static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) |
| 18569 | { |
| @@ -18573,14 +18283,67 @@ | |
| 18573 | Jim_AppendString(interp, prefixObj, subcmd, -1); |
| 18574 | |
| 18575 | return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); |
| 18576 | } |
| 18577 | |
| 18578 | |
| 18579 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18580 | { |
| 18581 | Jim_Obj *objPtr; |
| 18582 | int option; |
| 18583 | static const char * const options[] = { |
| 18584 | "create", "get", "set", "unset", "exists", "keys", "size", "info", |
| 18585 | "merge", "with", "append", "lappend", "incr", "remove", "values", "for", |
| 18586 | "replace", "update", NULL |
| @@ -18596,11 +18359,11 @@ | |
| 18596 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18597 | return JIM_ERR; |
| 18598 | } |
| 18599 | |
| 18600 | if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { |
| 18601 | return JIM_ERR; |
| 18602 | } |
| 18603 | |
| 18604 | switch (option) { |
| 18605 | case OPT_GET: |
| 18606 | if (argc < 3) { |
| @@ -18643,16 +18406,19 @@ | |
| 18643 | if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { |
| 18644 | return JIM_ERR; |
| 18645 | } |
| 18646 | return JIM_OK; |
| 18647 | |
| 18648 | case OPT_KEYS: |
| 18649 | if (argc != 3 && argc != 4) { |
| 18650 | Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); |
| 18651 | return JIM_ERR; |
| 18652 | } |
| 18653 | return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); |
| 18654 | |
| 18655 | case OPT_SIZE: |
| 18656 | if (argc != 3) { |
| 18657 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18658 | return JIM_ERR; |
| @@ -18665,19 +18431,20 @@ | |
| 18665 | |
| 18666 | case OPT_MERGE: |
| 18667 | if (argc == 2) { |
| 18668 | return JIM_OK; |
| 18669 | } |
| 18670 | if (Jim_DictSize(interp, argv[2]) < 0) { |
| 18671 | return JIM_ERR; |
| 18672 | } |
| 18673 | |
| 18674 | break; |
| 18675 | |
| 18676 | case OPT_UPDATE: |
| 18677 | if (argc < 6 || argc % 2) { |
| 18678 | |
| 18679 | argc = 2; |
| 18680 | } |
| 18681 | break; |
| 18682 | |
| 18683 | case OPT_CREATE: |
| @@ -18693,12 +18460,19 @@ | |
| 18693 | if (argc != 3) { |
| 18694 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18695 | return JIM_ERR; |
| 18696 | } |
| 18697 | return Jim_DictInfo(interp, argv[2]); |
| 18698 | } |
| 18699 | |
| 18700 | return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); |
| 18701 | } |
| 18702 | |
| 18703 | |
| 18704 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -18764,11 +18538,11 @@ | |
| 18764 | |
| 18765 | #ifdef jim_ext_namespace |
| 18766 | int nons = 0; |
| 18767 | |
| 18768 | if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) { |
| 18769 | |
| 18770 | argc--; |
| 18771 | argv++; |
| 18772 | nons = 1; |
| 18773 | } |
| 18774 | #endif |
| @@ -18775,16 +18549,15 @@ | |
| 18775 | |
| 18776 | if (argc < 2) { |
| 18777 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); |
| 18778 | return JIM_ERR; |
| 18779 | } |
| 18780 | if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) |
| 18781 | != JIM_OK) { |
| 18782 | return JIM_ERR; |
| 18783 | } |
| 18784 | |
| 18785 | |
| 18786 | switch (cmd) { |
| 18787 | case INFO_EXISTS: |
| 18788 | if (argc != 3) { |
| 18789 | Jim_WrongNumArgs(interp, 2, argv, "varName"); |
| 18790 | return JIM_ERR; |
| @@ -18809,21 +18582,21 @@ | |
| 18809 | Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData); |
| 18810 | return JIM_OK; |
| 18811 | } |
| 18812 | |
| 18813 | case INFO_CHANNELS: |
| 18814 | mode++; |
| 18815 | #ifndef jim_ext_aio |
| 18816 | Jim_SetResultString(interp, "aio not enabled", -1); |
| 18817 | return JIM_ERR; |
| 18818 | #endif |
| 18819 | |
| 18820 | case INFO_PROCS: |
| 18821 | mode++; |
| 18822 | |
| 18823 | case INFO_COMMANDS: |
| 18824 | |
| 18825 | if (argc != 2 && argc != 3) { |
| 18826 | Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18827 | return JIM_ERR; |
| 18828 | } |
| 18829 | #ifdef jim_ext_namespace |
| @@ -18835,17 +18608,17 @@ | |
| 18835 | #endif |
| 18836 | Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode)); |
| 18837 | break; |
| 18838 | |
| 18839 | case INFO_VARS: |
| 18840 | mode++; |
| 18841 | |
| 18842 | case INFO_LOCALS: |
| 18843 | mode++; |
| 18844 | |
| 18845 | case INFO_GLOBALS: |
| 18846 | |
| 18847 | if (argc != 2 && argc != 3) { |
| 18848 | Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18849 | return JIM_ERR; |
| 18850 | } |
| 18851 | #ifdef jim_ext_namespace |
| @@ -18951,13 +18724,12 @@ | |
| 18951 | case INFO_ARGS: |
| 18952 | Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr); |
| 18953 | break; |
| 18954 | case INFO_STATICS: |
| 18955 | if (cmdPtr->u.proc.staticVars) { |
| 18956 | int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES; |
| 18957 | Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars, |
| 18958 | NULL, JimVariablesMatch, mode)); |
| 18959 | } |
| 18960 | break; |
| 18961 | } |
| 18962 | break; |
| 18963 | } |
| @@ -18985,15 +18757,15 @@ | |
| 18985 | } |
| 18986 | } |
| 18987 | break; |
| 18988 | |
| 18989 | case INFO_HOSTNAME: |
| 18990 | |
| 18991 | return Jim_Eval(interp, "os.gethostname"); |
| 18992 | |
| 18993 | case INFO_NAMEOFEXECUTABLE: |
| 18994 | |
| 18995 | return Jim_Eval(interp, "{info nameofexecutable}"); |
| 18996 | |
| 18997 | case INFO_RETURNCODES: |
| 18998 | if (argc == 2) { |
| 18999 | int i; |
| @@ -19070,11 +18842,11 @@ | |
| 19070 | |
| 19071 | if (option == OPT_VAR) { |
| 19072 | result = Jim_GetVariable(interp, objPtr, 0) != NULL; |
| 19073 | } |
| 19074 | else { |
| 19075 | |
| 19076 | Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); |
| 19077 | |
| 19078 | if (cmd) { |
| 19079 | switch (option) { |
| 19080 | case OPT_COMMAND: |
| @@ -19113,11 +18885,11 @@ | |
| 19113 | if (len == 0) { |
| 19114 | return JIM_OK; |
| 19115 | } |
| 19116 | strLen = Jim_Utf8Length(interp, argv[1]); |
| 19117 | |
| 19118 | |
| 19119 | if (argc == 2) { |
| 19120 | splitChars = " \n\t\r"; |
| 19121 | splitLen = 4; |
| 19122 | } |
| 19123 | else { |
| @@ -19126,11 +18898,11 @@ | |
| 19126 | } |
| 19127 | |
| 19128 | noMatchStart = str; |
| 19129 | resObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 19130 | |
| 19131 | |
| 19132 | if (splitLen) { |
| 19133 | Jim_Obj *objPtr; |
| 19134 | while (strLen--) { |
| 19135 | const char *sc = splitChars; |
| 19136 | int scLen = splitLen; |
| @@ -19155,11 +18927,11 @@ | |
| 19155 | #define NUM_COMMON (128 - 9) |
| 19156 | while (strLen--) { |
| 19157 | int n = utf8_tounicode(str, &c); |
| 19158 | #ifdef JIM_OPTIMIZATION |
| 19159 | if (c >= 9 && c < 128) { |
| 19160 | |
| 19161 | c -= 9; |
| 19162 | if (!commonObj) { |
| 19163 | commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON); |
| 19164 | memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON); |
| 19165 | } |
| @@ -19189,11 +18961,11 @@ | |
| 19189 | |
| 19190 | if (argc != 2 && argc != 3) { |
| 19191 | Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?"); |
| 19192 | return JIM_ERR; |
| 19193 | } |
| 19194 | |
| 19195 | if (argc == 2) { |
| 19196 | joinStr = " "; |
| 19197 | joinStrLen = 1; |
| 19198 | } |
| 19199 | else { |
| @@ -19468,13 +19240,13 @@ | |
| 19468 | return -1; |
| 19469 | else if (step < 0 && end > start) |
| 19470 | return -1; |
| 19471 | len = end - start; |
| 19472 | if (len < 0) |
| 19473 | len = -len; |
| 19474 | if (step < 0) |
| 19475 | step = -step; |
| 19476 | len = 1 + ((len - 1) / step); |
| 19477 | if (len > INT_MAX) |
| 19478 | len = INT_MAX; |
| 19479 | return (int)((len < 0) ? -1 : len); |
| 19480 | } |
| @@ -19644,57 +19416,102 @@ | |
| 19644 | argv[1] = interp->result; |
| 19645 | |
| 19646 | Jim_EvalObjVector(interp, 2, argv); |
| 19647 | } |
| 19648 | |
| 19649 | static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, |
| 19650 | const char *prefix, const char *const *tablePtr, const char *name) |
| 19651 | { |
| 19652 | int count; |
| 19653 | char **tablePtrSorted; |
| 19654 | int i; |
| 19655 | |
| 19656 | for (count = 0; tablePtr[count]; count++) { |
| 19657 | } |
| 19658 | |
| 19659 | if (name == NULL) { |
| 19660 | name = "option"; |
| 19661 | } |
| 19662 | |
| 19663 | Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); |
| 19664 | tablePtrSorted = Jim_Alloc(sizeof(char *) * count); |
| 19665 | memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); |
| 19666 | qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); |
| 19667 | for (i = 0; i < count; i++) { |
| 19668 | if (i + 1 == count && count > 1) { |
| 19669 | Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); |
| 19670 | } |
| 19671 | Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); |
| 19672 | if (i + 1 != count) { |
| 19673 | Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); |
| 19674 | } |
| 19675 | } |
| 19676 | Jim_Free(tablePtrSorted); |
| 19677 | } |
| 19678 | |
| 19679 | int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, |
| 19680 | const char *const *tablePtr, int *indexPtr, const char *name, int flags) |
| 19681 | { |
| 19682 | const char *bad = "bad "; |
| 19683 | const char *const *entryPtr = NULL; |
| 19684 | int i; |
| 19685 | int match = -1; |
| 19686 | int arglen; |
| 19687 | const char *arg = Jim_GetString(objPtr, &arglen); |
| 19688 | |
| 19689 | *indexPtr = -1; |
| 19690 | |
| 19691 | for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { |
| 19692 | if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { |
| 19693 | |
| 19694 | *indexPtr = i; |
| 19695 | return JIM_OK; |
| 19696 | } |
| 19697 | if (flags & JIM_ENUM_ABBREV) { |
| 19698 | if (strncmp(arg, *entryPtr, arglen) == 0) { |
| 19699 | if (*arg == '-' && arglen == 1) { |
| 19700 | break; |
| @@ -19706,12 +19523,20 @@ | |
| 19706 | match = i; |
| 19707 | } |
| 19708 | } |
| 19709 | } |
| 19710 | |
| 19711 | |
| 19712 | if (match >= 0) { |
| 19713 | *indexPtr = match; |
| 19714 | return JIM_OK; |
| 19715 | } |
| 19716 | |
| 19717 | ambiguous: |
| @@ -19743,15 +19568,17 @@ | |
| 19743 | return objPtr->typePtr == &listObjType; |
| 19744 | } |
| 19745 | |
| 19746 | void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...) |
| 19747 | { |
| 19748 | |
| 19749 | int len = strlen(format); |
| 19750 | int extra = 0; |
| 19751 | int n = 0; |
| 19752 | const char *params[5]; |
| 19753 | char *buf; |
| 19754 | va_list args; |
| 19755 | int i; |
| 19756 | |
| 19757 | va_start(args, format); |
| @@ -19766,10 +19593,12 @@ | |
| 19766 | } |
| 19767 | else if (strncmp(format + i, "%#s", 3) == 0) { |
| 19768 | Jim_Obj *objPtr = va_arg(args, Jim_Obj *); |
| 19769 | |
| 19770 | params[n] = Jim_GetString(objPtr, &l); |
| 19771 | } |
| 19772 | else { |
| 19773 | if (format[i] == '%') { |
| 19774 | i++; |
| 19775 | } |
| @@ -19784,10 +19613,14 @@ | |
| 19784 | len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); |
| 19785 | |
| 19786 | va_end(args); |
| 19787 | |
| 19788 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); |
| 19789 | } |
| 19790 | |
| 19791 | |
| 19792 | #ifndef jim_ext_package |
| 19793 | int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) |
| @@ -19808,11 +19641,11 @@ | |
| 19808 | #include <string.h> |
| 19809 | |
| 19810 | |
| 19811 | static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19812 | { |
| 19813 | |
| 19814 | return JIM_OK; |
| 19815 | } |
| 19816 | |
| 19817 | static const jim_subcmd_type dummy_subcmd = { |
| 19818 | "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN |
| @@ -19831,22 +19664,18 @@ | |
| 19831 | } |
| 19832 | |
| 19833 | static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, |
| 19834 | Jim_Obj *cmd, Jim_Obj *subcmd) |
| 19835 | { |
| 19836 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 19837 | Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type, |
| 19838 | " command \"", Jim_String(subcmd), "\": should be ", NULL); |
| 19839 | add_commands(interp, command_table, ", "); |
| 19840 | } |
| 19841 | |
| 19842 | static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, |
| 19843 | Jim_Obj *const *argv) |
| 19844 | { |
| 19845 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 19846 | Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]), |
| 19847 | " command ... \", where command is one of: ", NULL); |
| 19848 | add_commands(interp, command_table, ", "); |
| 19849 | } |
| 19850 | |
| 19851 | static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) |
| 19852 | { |
| @@ -19863,67 +19692,78 @@ | |
| 19863 | { |
| 19864 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19865 | add_cmd_usage(interp, command_table, subcmd); |
| 19866 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19867 | } |
| 19868 | |
| 19869 | const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, |
| 19870 | int argc, Jim_Obj *const *argv) |
| 19871 | { |
| 19872 | const jim_subcmd_type *ct; |
| 19873 | const jim_subcmd_type *partial = 0; |
| 19874 | int cmdlen; |
| 19875 | Jim_Obj *cmd; |
| 19876 | const char *cmdstr; |
| 19877 | const char *cmdname; |
| 19878 | int help = 0; |
| 19879 | |
| 19880 | cmdname = Jim_String(argv[0]); |
| 19881 | |
| 19882 | if (argc < 2) { |
| 19883 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 19884 | Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname, |
| 19885 | " command ...\"\n", NULL); |
| 19886 | Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL); |
| 19887 | return 0; |
| 19888 | } |
| 19889 | |
| 19890 | cmd = argv[1]; |
| 19891 | |
| 19892 | |
| 19893 | if (Jim_CompareStringImmediate(interp, cmd, "-help")) { |
| 19894 | if (argc == 2) { |
| 19895 | |
| 19896 | show_cmd_usage(interp, command_table, argc, argv); |
| 19897 | return &dummy_subcmd; |
| 19898 | } |
| 19899 | help = 1; |
| 19900 | |
| 19901 | |
| 19902 | cmd = argv[2]; |
| 19903 | } |
| 19904 | |
| 19905 | |
| 19906 | if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { |
| 19907 | |
| 19908 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 19909 | add_commands(interp, command_table, " "); |
| 19910 | return &dummy_subcmd; |
| 19911 | } |
| 19912 | |
| 19913 | cmdstr = Jim_GetString(cmd, &cmdlen); |
| 19914 | |
| 19915 | for (ct = command_table; ct->cmd; ct++) { |
| 19916 | if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) { |
| 19917 | |
| 19918 | break; |
| 19919 | } |
| 19920 | if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) { |
| 19921 | if (partial) { |
| 19922 | |
| 19923 | if (help) { |
| 19924 | |
| 19925 | show_cmd_usage(interp, command_table, argc, argv); |
| 19926 | return &dummy_subcmd; |
| 19927 | } |
| 19928 | bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]); |
| 19929 | return 0; |
| @@ -19931,44 +19771,51 @@ | |
| 19931 | partial = ct; |
| 19932 | } |
| 19933 | continue; |
| 19934 | } |
| 19935 | |
| 19936 | |
| 19937 | if (partial && !ct->cmd) { |
| 19938 | ct = partial; |
| 19939 | } |
| 19940 | |
| 19941 | if (!ct->cmd) { |
| 19942 | |
| 19943 | if (help) { |
| 19944 | |
| 19945 | show_cmd_usage(interp, command_table, argc, argv); |
| 19946 | return &dummy_subcmd; |
| 19947 | } |
| 19948 | bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]); |
| 19949 | return 0; |
| 19950 | } |
| 19951 | |
| 19952 | if (help) { |
| 19953 | Jim_SetResultString(interp, "Usage: ", -1); |
| 19954 | |
| 19955 | add_cmd_usage(interp, ct, argv[0]); |
| 19956 | return &dummy_subcmd; |
| 19957 | } |
| 19958 | |
| 19959 | |
| 19960 | if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { |
| 19961 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19962 | |
| 19963 | add_cmd_usage(interp, ct, argv[0]); |
| 19964 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19965 | |
| 19966 | return 0; |
| 19967 | } |
| 19968 | |
| 19969 | |
| 19970 | return ct; |
| 19971 | } |
| 19972 | |
| 19973 | int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv) |
| 19974 | { |
| @@ -20019,11 +19866,11 @@ | |
| 20019 | *p++ = 0xe0 | ((uc & 0xf000) >> 12); |
| 20020 | *p++ = 0x80 | ((uc & 0xfc0) >> 6); |
| 20021 | *p = 0x80 | (uc & 0x3f); |
| 20022 | return 3; |
| 20023 | } |
| 20024 | |
| 20025 | else { |
| 20026 | *p++ = 0xf0 | ((uc & 0x1c0000) >> 18); |
| 20027 | *p++ = 0x80 | ((uc & 0x3f000) >> 12); |
| 20028 | *p++ = 0x80 | ((uc & 0xfc0) >> 6); |
| 20029 | *p = 0x80 | (uc & 0x3f); |
| @@ -20146,11 +19993,12 @@ | |
| 20146 | continue; |
| 20147 | } |
| 20148 | *p++ = ch; |
| 20149 | format += step; |
| 20150 | step = utf8_tounicode(format, &ch); |
| 20151 | } while (sawFlag); |
| 20152 | |
| 20153 | |
| 20154 | width = 0; |
| 20155 | if (isdigit(ch)) { |
| 20156 | width = strtoul(format, &end, 10); |
| @@ -20210,11 +20058,11 @@ | |
| 20210 | if (ch == 'h') { |
| 20211 | useShort = 1; |
| 20212 | format += step; |
| 20213 | step = utf8_tounicode(format, &ch); |
| 20214 | } else if (ch == 'l') { |
| 20215 | |
| 20216 | format += step; |
| 20217 | step = utf8_tounicode(format, &ch); |
| 20218 | if (ch == 'l') { |
| 20219 | format += step; |
| 20220 | step = utf8_tounicode(format, &ch); |
| @@ -20237,11 +20085,11 @@ | |
| 20237 | goto errorMsg; |
| 20238 | case 's': { |
| 20239 | formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); |
| 20240 | formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); |
| 20241 | if (gotPrecision && (precision < formatted_chars)) { |
| 20242 | |
| 20243 | formatted_chars = precision; |
| 20244 | formatted_bytes = utf8_index(formatted_buf, precision); |
| 20245 | } |
| 20246 | break; |
| 20247 | } |
| @@ -20249,11 +20097,11 @@ | |
| 20249 | jim_wide code; |
| 20250 | |
| 20251 | if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { |
| 20252 | goto error; |
| 20253 | } |
| 20254 | |
| 20255 | formatted_bytes = utf8_getchars(spec, code); |
| 20256 | formatted_buf = spec; |
| 20257 | formatted_chars = 1; |
| 20258 | break; |
| 20259 | } |
| @@ -20267,11 +20115,11 @@ | |
| 20267 | goto error; |
| 20268 | } |
| 20269 | length = sizeof(w) * 8; |
| 20270 | |
| 20271 | |
| 20272 | |
| 20273 | if (num_buffer_size < length + 1) { |
| 20274 | num_buffer_size = length + 1; |
| 20275 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20276 | } |
| 20277 | |
| @@ -20295,29 +20143,29 @@ | |
| 20295 | case 'E': |
| 20296 | case 'f': |
| 20297 | case 'g': |
| 20298 | case 'G': |
| 20299 | doubleType = 1; |
| 20300 | |
| 20301 | case 'd': |
| 20302 | case 'u': |
| 20303 | case 'o': |
| 20304 | case 'x': |
| 20305 | case 'X': { |
| 20306 | jim_wide w; |
| 20307 | double d; |
| 20308 | int length; |
| 20309 | |
| 20310 | |
| 20311 | if (width) { |
| 20312 | p += sprintf(p, "%ld", width); |
| 20313 | } |
| 20314 | if (gotPrecision) { |
| 20315 | p += sprintf(p, ".%ld", precision); |
| 20316 | } |
| 20317 | |
| 20318 | |
| 20319 | if (doubleType) { |
| 20320 | if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { |
| 20321 | goto error; |
| 20322 | } |
| 20323 | length = MAX_FLOAT_WIDTH; |
| @@ -20344,19 +20192,26 @@ | |
| 20344 | } |
| 20345 | |
| 20346 | *p++ = (char) ch; |
| 20347 | *p = '\0'; |
| 20348 | |
| 20349 | |
| 20350 | if (width > length) { |
| 20351 | length = width; |
| 20352 | } |
| 20353 | if (gotPrecision) { |
| 20354 | length += precision; |
| 20355 | } |
| 20356 | |
| 20357 | |
| 20358 | if (num_buffer_size < length + 1) { |
| 20359 | num_buffer_size = length + 1; |
| 20360 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20361 | } |
| 20362 | |
| @@ -20370,11 +20225,11 @@ | |
| 20370 | formatted_buf = num_buffer; |
| 20371 | break; |
| 20372 | } |
| 20373 | |
| 20374 | default: { |
| 20375 | |
| 20376 | spec[0] = ch; |
| 20377 | spec[1] = '\0'; |
| 20378 | Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); |
| 20379 | goto error; |
| 20380 | } |
| @@ -20422,37 +20277,37 @@ | |
| 20422 | |
| 20423 | #define REG_MAX_PAREN 100 |
| 20424 | |
| 20425 | |
| 20426 | |
| 20427 | #define END 0 |
| 20428 | #define BOL 1 |
| 20429 | #define EOL 2 |
| 20430 | #define ANY 3 |
| 20431 | #define ANYOF 4 |
| 20432 | #define ANYBUT 5 |
| 20433 | #define BRANCH 6 |
| 20434 | #define BACK 7 |
| 20435 | #define EXACTLY 8 |
| 20436 | #define NOTHING 9 |
| 20437 | #define REP 10 |
| 20438 | #define REPMIN 11 |
| 20439 | #define REPX 12 |
| 20440 | #define REPXMIN 13 |
| 20441 | #define BOLX 14 |
| 20442 | #define EOLX 15 |
| 20443 | #define WORDA 16 |
| 20444 | #define WORDZ 17 |
| 20445 | |
| 20446 | #define OPENNC 1000 |
| 20447 | #define OPEN 1001 |
| 20448 | |
| 20449 | |
| 20450 | |
| 20451 | |
| 20452 | #define CLOSENC 2000 |
| 20453 | #define CLOSE 2001 |
| 20454 | #define CLOSE_END (CLOSE+REG_MAX_PAREN) |
| 20455 | |
| 20456 | #define REG_MAGIC 0xFADED00D |
| 20457 | |
| 20458 | |
| @@ -20465,18 +20320,18 @@ | |
| 20465 | |
| 20466 | #define FAIL(R,M) { (R)->err = (M); return (M); } |
| 20467 | #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') |
| 20468 | #define META "^$.[()|?{+*" |
| 20469 | |
| 20470 | #define HASWIDTH 1 |
| 20471 | #define SIMPLE 2 |
| 20472 | #define SPSTART 4 |
| 20473 | #define WORST 0 |
| 20474 | |
| 20475 | #define MAX_REP_COUNT 1000000 |
| 20476 | |
| 20477 | static int reg(regex_t *preg, int paren , int *flagp ); |
| 20478 | static int regpiece(regex_t *preg, int *flagp ); |
| 20479 | static int regbranch(regex_t *preg, int *flagp ); |
| 20480 | static int regatom(regex_t *preg, int *flagp ); |
| 20481 | static int regnode(regex_t *preg, int op ); |
| 20482 | static int regnext(regex_t *preg, int p ); |
| @@ -20520,15 +20375,15 @@ | |
| 20520 | memset(preg, 0, sizeof(*preg)); |
| 20521 | |
| 20522 | if (exp == NULL) |
| 20523 | FAIL(preg, REG_ERR_NULL_ARGUMENT); |
| 20524 | |
| 20525 | |
| 20526 | preg->cflags = cflags; |
| 20527 | preg->regparse = exp; |
| 20528 | |
| 20529 | |
| 20530 | preg->proglen = (strlen(exp) + 1) * 5; |
| 20531 | preg->program = malloc(preg->proglen * sizeof(int)); |
| 20532 | if (preg->program == NULL) |
| 20533 | FAIL(preg, REG_ERR_NOMEM); |
| 20534 | |
| @@ -20535,24 +20390,24 @@ | |
| 20535 | regc(preg, REG_MAGIC); |
| 20536 | if (reg(preg, 0, &flags) == 0) { |
| 20537 | return preg->err; |
| 20538 | } |
| 20539 | |
| 20540 | |
| 20541 | if (preg->re_nsub >= REG_MAX_PAREN) |
| 20542 | FAIL(preg,REG_ERR_TOO_BIG); |
| 20543 | |
| 20544 | |
| 20545 | preg->regstart = 0; |
| 20546 | preg->reganch = 0; |
| 20547 | preg->regmust = 0; |
| 20548 | preg->regmlen = 0; |
| 20549 | scan = 1; |
| 20550 | if (OP(preg, regnext(preg, scan)) == END) { |
| 20551 | scan = OPERAND(scan); |
| 20552 | |
| 20553 | |
| 20554 | if (OP(preg, scan) == EXACTLY) { |
| 20555 | preg->regstart = preg->program[OPERAND(scan)]; |
| 20556 | } |
| 20557 | else if (OP(preg, scan) == BOL) |
| 20558 | preg->reganch++; |
| @@ -20579,24 +20434,24 @@ | |
| 20579 | #endif |
| 20580 | |
| 20581 | return 0; |
| 20582 | } |
| 20583 | |
| 20584 | static int reg(regex_t *preg, int paren , int *flagp ) |
| 20585 | { |
| 20586 | int ret; |
| 20587 | int br; |
| 20588 | int ender; |
| 20589 | int parno = 0; |
| 20590 | int flags; |
| 20591 | |
| 20592 | *flagp = HASWIDTH; |
| 20593 | |
| 20594 | |
| 20595 | if (paren) { |
| 20596 | if (preg->regparse[0] == '?' && preg->regparse[1] == ':') { |
| 20597 | |
| 20598 | preg->regparse += 2; |
| 20599 | parno = -1; |
| 20600 | } |
| 20601 | else { |
| 20602 | parno = ++preg->re_nsub; |
| @@ -20603,16 +20458,16 @@ | |
| 20603 | } |
| 20604 | ret = regnode(preg, OPEN+parno); |
| 20605 | } else |
| 20606 | ret = 0; |
| 20607 | |
| 20608 | |
| 20609 | br = regbranch(preg, &flags); |
| 20610 | if (br == 0) |
| 20611 | return 0; |
| 20612 | if (ret != 0) |
| 20613 | regtail(preg, ret, br); |
| 20614 | else |
| 20615 | ret = br; |
| 20616 | if (!(flags&HASWIDTH)) |
| 20617 | *flagp &= ~HASWIDTH; |
| 20618 | *flagp |= flags&SPSTART; |
| @@ -20619,25 +20474,25 @@ | |
| 20619 | while (*preg->regparse == '|') { |
| 20620 | preg->regparse++; |
| 20621 | br = regbranch(preg, &flags); |
| 20622 | if (br == 0) |
| 20623 | return 0; |
| 20624 | regtail(preg, ret, br); |
| 20625 | if (!(flags&HASWIDTH)) |
| 20626 | *flagp &= ~HASWIDTH; |
| 20627 | *flagp |= flags&SPSTART; |
| 20628 | } |
| 20629 | |
| 20630 | |
| 20631 | ender = regnode(preg, (paren) ? CLOSE+parno : END); |
| 20632 | regtail(preg, ret, ender); |
| 20633 | |
| 20634 | |
| 20635 | for (br = ret; br != 0; br = regnext(preg, br)) |
| 20636 | regoptail(preg, br, ender); |
| 20637 | |
| 20638 | |
| 20639 | if (paren && *preg->regparse++ != ')') { |
| 20640 | preg->err = REG_ERR_UNMATCHED_PAREN; |
| 20641 | return 0; |
| 20642 | } else if (!paren && *preg->regparse != '\0') { |
| 20643 | if (*preg->regparse == ')') { |
| @@ -20657,11 +20512,11 @@ | |
| 20657 | int ret; |
| 20658 | int chain; |
| 20659 | int latest; |
| 20660 | int flags; |
| 20661 | |
| 20662 | *flagp = WORST; |
| 20663 | |
| 20664 | ret = regnode(preg, BRANCH); |
| 20665 | chain = 0; |
| 20666 | while (*preg->regparse != '\0' && *preg->regparse != ')' && |
| 20667 | *preg->regparse != '|') { |
| @@ -20675,11 +20530,11 @@ | |
| 20675 | else { |
| 20676 | regtail(preg, chain, latest); |
| 20677 | } |
| 20678 | chain = latest; |
| 20679 | } |
| 20680 | if (chain == 0) |
| 20681 | (void) regnode(preg, NOTHING); |
| 20682 | |
| 20683 | return(ret); |
| 20684 | } |
| 20685 | |
| @@ -20705,11 +20560,11 @@ | |
| 20705 | if (!(flags&HASWIDTH) && op != '?') { |
| 20706 | preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY; |
| 20707 | return 0; |
| 20708 | } |
| 20709 | |
| 20710 | |
| 20711 | if (op == '{') { |
| 20712 | char *end; |
| 20713 | |
| 20714 | min = strtoul(preg->regparse + 1, &end, 10); |
| 20715 | if (end == preg->regparse + 1) { |
| @@ -20716,10 +20571,14 @@ | |
| 20716 | preg->err = REG_ERR_BAD_COUNT; |
| 20717 | return 0; |
| 20718 | } |
| 20719 | if (*end == '}') { |
| 20720 | max = min; |
| 20721 | } |
| 20722 | else { |
| 20723 | preg->regparse = end; |
| 20724 | max = strtoul(preg->regparse + 1, &end, 10); |
| 20725 | if (*end != '}') { |
| @@ -20777,11 +20636,11 @@ | |
| 20777 | static void reg_addrange(regex_t *preg, int lower, int upper) |
| 20778 | { |
| 20779 | if (lower > upper) { |
| 20780 | reg_addrange(preg, upper, lower); |
| 20781 | } |
| 20782 | |
| 20783 | regc(preg, upper - lower + 1); |
| 20784 | regc(preg, lower); |
| 20785 | } |
| 20786 | |
| 20787 | static void reg_addrange_str(regex_t *preg, const char *str) |
| @@ -20845,17 +20704,17 @@ | |
| 20845 | case 'r': *ch = '\r'; break; |
| 20846 | case 't': *ch = '\t'; break; |
| 20847 | case 'v': *ch = '\v'; break; |
| 20848 | case 'u': |
| 20849 | if (*s == '{') { |
| 20850 | |
| 20851 | n = parse_hex(s + 1, 6, ch); |
| 20852 | if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) { |
| 20853 | s += n + 2; |
| 20854 | } |
| 20855 | else { |
| 20856 | |
| 20857 | *ch = 'u'; |
| 20858 | } |
| 20859 | } |
| 20860 | else if ((n = parse_hex(s, 4, ch)) > 0) { |
| 20861 | s += n; |
| @@ -20886,15 +20745,15 @@ | |
| 20886 | int nocase = (preg->cflags & REG_ICASE); |
| 20887 | |
| 20888 | int ch; |
| 20889 | int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase); |
| 20890 | |
| 20891 | *flagp = WORST; |
| 20892 | |
| 20893 | preg->regparse += n; |
| 20894 | switch (ch) { |
| 20895 | |
| 20896 | case '^': |
| 20897 | ret = regnode(preg, BOL); |
| 20898 | break; |
| 20899 | case '$': |
| 20900 | ret = regnode(preg, EOL); |
| @@ -20904,37 +20763,60 @@ | |
| 20904 | *flagp |= HASWIDTH|SIMPLE; |
| 20905 | break; |
| 20906 | case '[': { |
| 20907 | const char *pattern = preg->regparse; |
| 20908 | |
| 20909 | if (*pattern == '^') { |
| 20910 | ret = regnode(preg, ANYBUT); |
| 20911 | pattern++; |
| 20912 | } else |
| 20913 | ret = regnode(preg, ANYOF); |
| 20914 | |
| 20915 | |
| 20916 | if (*pattern == ']' || *pattern == '-') { |
| 20917 | reg_addrange(preg, *pattern, *pattern); |
| 20918 | pattern++; |
| 20919 | } |
| 20920 | |
| 20921 | while (*pattern && *pattern != ']') { |
| 20922 | |
| 20923 | int start; |
| 20924 | int end; |
| 20925 | |
| 20926 | pattern += reg_utf8_tounicode_case(pattern, &start, nocase); |
| 20927 | if (start == '\\') { |
| 20928 | pattern += reg_decode_escape(pattern, &start); |
| 20929 | if (start == 0) { |
| 20930 | preg->err = REG_ERR_NULL_CHAR; |
| 20931 | return 0; |
| 20932 | } |
| 20933 | } |
| 20934 | if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') { |
| 20935 | |
| 20936 | pattern += utf8_tounicode(pattern, &end); |
| 20937 | pattern += reg_utf8_tounicode_case(pattern, &end, nocase); |
| 20938 | if (end == '\\') { |
| 20939 | pattern += reg_decode_escape(pattern, &end); |
| 20940 | if (end == 0) { |
| @@ -20949,30 +20831,25 @@ | |
| 20949 | if (start == '[' && pattern[0] == ':') { |
| 20950 | static const char *character_class[] = { |
| 20951 | ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:", |
| 20952 | ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:", |
| 20953 | }; |
| 20954 | enum { |
| 20955 | CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER, |
| 20956 | CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT, |
| 20957 | CC_NUM |
| 20958 | }; |
| 20959 | int i; |
| 20960 | |
| 20961 | for (i = 0; i < CC_NUM; i++) { |
| 20962 | int n = strlen(character_class[i]); |
| 20963 | if (strncmp(pattern, character_class[i], n) == 0) { |
| 20964 | |
| 20965 | pattern += n + 1; |
| 20966 | break; |
| 20967 | } |
| 20968 | } |
| 20969 | if (i != CC_NUM) { |
| 20970 | switch (i) { |
| 20971 | case CC_ALNUM: |
| 20972 | reg_addrange(preg, '0', '9'); |
| 20973 | |
| 20974 | case CC_ALPHA: |
| 20975 | if ((preg->cflags & REG_ICASE) == 0) { |
| 20976 | reg_addrange(preg, 'a', 'z'); |
| 20977 | } |
| 20978 | reg_addrange(preg, 'A', 'Z'); |
| @@ -20990,11 +20867,11 @@ | |
| 20990 | reg_addrange(preg, 'a', 'z'); |
| 20991 | break; |
| 20992 | case CC_XDIGIT: |
| 20993 | reg_addrange(preg, 'a', 'f'); |
| 20994 | reg_addrange(preg, 'A', 'F'); |
| 20995 | |
| 20996 | case CC_DIGIT: |
| 20997 | reg_addrange(preg, '0', '9'); |
| 20998 | break; |
| 20999 | case CC_CNTRL: |
| 21000 | reg_addrange(preg, 0, 31); |
| @@ -21014,11 +20891,11 @@ | |
| 21014 | break; |
| 21015 | } |
| 21016 | continue; |
| 21017 | } |
| 21018 | } |
| 21019 | |
| 21020 | reg_addrange(preg, start, start); |
| 21021 | } |
| 21022 | regc(preg, '\0'); |
| 21023 | |
| 21024 | if (*pattern) { |
| @@ -21037,11 +20914,11 @@ | |
| 21037 | break; |
| 21038 | case '\0': |
| 21039 | case '|': |
| 21040 | case ')': |
| 21041 | preg->err = REG_ERR_INTERNAL; |
| 21042 | return 0; |
| 21043 | case '?': |
| 21044 | case '+': |
| 21045 | case '*': |
| 21046 | case '{': |
| 21047 | preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING; |
| @@ -21090,34 +20967,34 @@ | |
| 21090 | ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT); |
| 21091 | reg_addrange_str(preg," \t\r\n\f\v"); |
| 21092 | regc(preg, '\0'); |
| 21093 | *flagp |= HASWIDTH|SIMPLE; |
| 21094 | break; |
| 21095 | |
| 21096 | default: |
| 21097 | |
| 21098 | |
| 21099 | preg->regparse--; |
| 21100 | goto de_fault; |
| 21101 | } |
| 21102 | break; |
| 21103 | de_fault: |
| 21104 | default: { |
| 21105 | int added = 0; |
| 21106 | |
| 21107 | |
| 21108 | preg->regparse -= n; |
| 21109 | |
| 21110 | ret = regnode(preg, EXACTLY); |
| 21111 | |
| 21112 | |
| 21113 | |
| 21114 | while (*preg->regparse && strchr(META, *preg->regparse) == NULL) { |
| 21115 | n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE)); |
| 21116 | if (ch == '\\' && preg->regparse[n]) { |
| 21117 | if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) { |
| 21118 | |
| 21119 | break; |
| 21120 | } |
| 21121 | n += reg_decode_escape(preg->regparse + n, &ch); |
| 21122 | if (ch == 0) { |
| 21123 | preg->err = REG_ERR_NULL_CHAR; |
| @@ -21125,23 +21002,23 @@ | |
| 21125 | } |
| 21126 | } |
| 21127 | |
| 21128 | |
| 21129 | if (ISMULT(preg->regparse[n])) { |
| 21130 | |
| 21131 | if (added) { |
| 21132 | |
| 21133 | break; |
| 21134 | } |
| 21135 | |
| 21136 | regc(preg, ch); |
| 21137 | added++; |
| 21138 | preg->regparse += n; |
| 21139 | break; |
| 21140 | } |
| 21141 | |
| 21142 | |
| 21143 | regc(preg, ch); |
| 21144 | added++; |
| 21145 | preg->regparse += n; |
| 21146 | } |
| 21147 | regc(preg, '\0'); |
| @@ -21168,15 +21045,15 @@ | |
| 21168 | |
| 21169 | static int regnode(regex_t *preg, int op) |
| 21170 | { |
| 21171 | reg_grow(preg, 2); |
| 21172 | |
| 21173 | |
| 21174 | preg->program[preg->p++] = op; |
| 21175 | preg->program[preg->p++] = 0; |
| 21176 | |
| 21177 | |
| 21178 | return preg->p - 2; |
| 21179 | } |
| 21180 | |
| 21181 | static void regc(regex_t *preg, int b ) |
| 21182 | { |
| @@ -21186,13 +21063,13 @@ | |
| 21186 | |
| 21187 | static int reginsert(regex_t *preg, int op, int size, int opnd ) |
| 21188 | { |
| 21189 | reg_grow(preg, size); |
| 21190 | |
| 21191 | |
| 21192 | memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd)); |
| 21193 | |
| 21194 | memset(preg->program + opnd, 0, sizeof(int) * size); |
| 21195 | |
| 21196 | preg->program[opnd] = op; |
| 21197 | |
| 21198 | preg->p += size; |
| @@ -21204,11 +21081,11 @@ | |
| 21204 | { |
| 21205 | int scan; |
| 21206 | int temp; |
| 21207 | int offset; |
| 21208 | |
| 21209 | |
| 21210 | scan = p; |
| 21211 | for (;;) { |
| 21212 | temp = regnext(preg, scan); |
| 21213 | if (temp == 0) |
| 21214 | break; |
| @@ -21224,11 +21101,11 @@ | |
| 21224 | } |
| 21225 | |
| 21226 | |
| 21227 | static void regoptail(regex_t *preg, int p, int val ) |
| 21228 | { |
| 21229 | |
| 21230 | if (p != 0 && OP(preg, p) == BRANCH) { |
| 21231 | regtail(preg, OPERAND(p), val); |
| 21232 | } |
| 21233 | } |
| 21234 | |
| @@ -21240,16 +21117,16 @@ | |
| 21240 | int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) |
| 21241 | { |
| 21242 | const char *s; |
| 21243 | int scan; |
| 21244 | |
| 21245 | |
| 21246 | if (preg == NULL || preg->program == NULL || string == NULL) { |
| 21247 | return REG_ERR_NULL_ARGUMENT; |
| 21248 | } |
| 21249 | |
| 21250 | |
| 21251 | if (*preg->program != REG_MAGIC) { |
| 21252 | return REG_ERR_CORRUPTED; |
| 21253 | } |
| 21254 | |
| 21255 | #ifdef DEBUG |
| @@ -21258,51 +21135,51 @@ | |
| 21258 | #endif |
| 21259 | |
| 21260 | preg->eflags = eflags; |
| 21261 | preg->pmatch = pmatch; |
| 21262 | preg->nmatch = nmatch; |
| 21263 | preg->start = string; |
| 21264 | |
| 21265 | |
| 21266 | for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { |
| 21267 | int op = OP(preg, scan); |
| 21268 | if (op == END) |
| 21269 | break; |
| 21270 | if (op == REPX || op == REPXMIN) |
| 21271 | preg->program[scan + 4] = 0; |
| 21272 | } |
| 21273 | |
| 21274 | |
| 21275 | if (preg->regmust != 0) { |
| 21276 | s = string; |
| 21277 | while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) { |
| 21278 | if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) { |
| 21279 | break; |
| 21280 | } |
| 21281 | s++; |
| 21282 | } |
| 21283 | if (s == NULL) |
| 21284 | return REG_NOMATCH; |
| 21285 | } |
| 21286 | |
| 21287 | |
| 21288 | preg->regbol = string; |
| 21289 | |
| 21290 | |
| 21291 | if (preg->reganch) { |
| 21292 | if (eflags & REG_NOTBOL) { |
| 21293 | |
| 21294 | goto nextline; |
| 21295 | } |
| 21296 | while (1) { |
| 21297 | if (regtry(preg, string)) { |
| 21298 | return REG_NOERROR; |
| 21299 | } |
| 21300 | if (*string) { |
| 21301 | nextline: |
| 21302 | if (preg->cflags & REG_NEWLINE) { |
| 21303 | |
| 21304 | string = strchr(string, '\n'); |
| 21305 | if (string) { |
| 21306 | preg->regbol = ++string; |
| 21307 | continue; |
| 21308 | } |
| @@ -21310,22 +21187,22 @@ | |
| 21310 | } |
| 21311 | return REG_NOMATCH; |
| 21312 | } |
| 21313 | } |
| 21314 | |
| 21315 | |
| 21316 | s = string; |
| 21317 | if (preg->regstart != '\0') { |
| 21318 | |
| 21319 | while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) { |
| 21320 | if (regtry(preg, s)) |
| 21321 | return REG_NOERROR; |
| 21322 | s++; |
| 21323 | } |
| 21324 | } |
| 21325 | else |
| 21326 | |
| 21327 | while (1) { |
| 21328 | if (regtry(preg, s)) |
| 21329 | return REG_NOERROR; |
| 21330 | if (*s == '\0') { |
| 21331 | break; |
| @@ -21334,15 +21211,15 @@ | |
| 21334 | int c; |
| 21335 | s += utf8_tounicode(s, &c); |
| 21336 | } |
| 21337 | } |
| 21338 | |
| 21339 | |
| 21340 | return REG_NOMATCH; |
| 21341 | } |
| 21342 | |
| 21343 | |
| 21344 | static int regtry( regex_t *preg, const char *string ) |
| 21345 | { |
| 21346 | int i; |
| 21347 | |
| 21348 | preg->reginput = string; |
| @@ -21379,11 +21256,11 @@ | |
| 21379 | } |
| 21380 | |
| 21381 | static int reg_range_find(const int *range, int c) |
| 21382 | { |
| 21383 | while (*range) { |
| 21384 | |
| 21385 | if (c >= range[1] && c <= (range[0] + range[1] - 1)) { |
| 21386 | return 1; |
| 21387 | } |
| 21388 | range += 2; |
| 21389 | } |
| @@ -21391,11 +21268,11 @@ | |
| 21391 | } |
| 21392 | |
| 21393 | static const char *str_find(const char *string, int c, int nocase) |
| 21394 | { |
| 21395 | if (nocase) { |
| 21396 | |
| 21397 | c = utf8_upper(c); |
| 21398 | } |
| 21399 | while (*string) { |
| 21400 | int ch; |
| 21401 | int n = reg_utf8_tounicode_case(string, &ch, nocase); |
| @@ -21435,15 +21312,15 @@ | |
| 21435 | no = regrepeat(preg, scan + 5, max); |
| 21436 | if (no < min) { |
| 21437 | return 0; |
| 21438 | } |
| 21439 | if (matchmin) { |
| 21440 | |
| 21441 | max = no; |
| 21442 | no = min; |
| 21443 | } |
| 21444 | |
| 21445 | while (1) { |
| 21446 | if (matchmin) { |
| 21447 | if (no > max) { |
| 21448 | break; |
| 21449 | } |
| @@ -21453,22 +21330,22 @@ | |
| 21453 | break; |
| 21454 | } |
| 21455 | } |
| 21456 | preg->reginput = save + utf8_index(save, no); |
| 21457 | reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); |
| 21458 | |
| 21459 | if (reg_iseol(preg, nextch) || c == nextch) { |
| 21460 | if (regmatch(preg, next)) { |
| 21461 | return(1); |
| 21462 | } |
| 21463 | } |
| 21464 | if (matchmin) { |
| 21465 | |
| 21466 | no++; |
| 21467 | } |
| 21468 | else { |
| 21469 | |
| 21470 | no--; |
| 21471 | } |
| 21472 | } |
| 21473 | return(0); |
| 21474 | } |
| @@ -21478,13 +21355,13 @@ | |
| 21478 | int *scanpt = preg->program + scan; |
| 21479 | |
| 21480 | int max = scanpt[2]; |
| 21481 | int min = scanpt[3]; |
| 21482 | |
| 21483 | |
| 21484 | if (scanpt[4] < min) { |
| 21485 | |
| 21486 | scanpt[4]++; |
| 21487 | if (regmatch(preg, scan + 5)) { |
| 21488 | return 1; |
| 21489 | } |
| 21490 | scanpt[4]--; |
| @@ -21493,39 +21370,39 @@ | |
| 21493 | if (scanpt[4] > max) { |
| 21494 | return 0; |
| 21495 | } |
| 21496 | |
| 21497 | if (matchmin) { |
| 21498 | |
| 21499 | if (regmatch(preg, regnext(preg, scan))) { |
| 21500 | return 1; |
| 21501 | } |
| 21502 | |
| 21503 | scanpt[4]++; |
| 21504 | if (regmatch(preg, scan + 5)) { |
| 21505 | return 1; |
| 21506 | } |
| 21507 | scanpt[4]--; |
| 21508 | return 0; |
| 21509 | } |
| 21510 | |
| 21511 | if (scanpt[4] < max) { |
| 21512 | scanpt[4]++; |
| 21513 | if (regmatch(preg, scan + 5)) { |
| 21514 | return 1; |
| 21515 | } |
| 21516 | scanpt[4]--; |
| 21517 | } |
| 21518 | |
| 21519 | return regmatch(preg, regnext(preg, scan)); |
| 21520 | } |
| 21521 | |
| 21522 | |
| 21523 | static int regmatch(regex_t *preg, int prog) |
| 21524 | { |
| 21525 | int scan; |
| 21526 | int next; |
| 21527 | const char *save; |
| 21528 | |
| 21529 | scan = prog; |
| 21530 | |
| 21531 | #ifdef DEBUG |
| @@ -21535,11 +21412,11 @@ | |
| 21535 | while (scan != 0) { |
| 21536 | int n; |
| 21537 | int c; |
| 21538 | #ifdef DEBUG |
| 21539 | if (regnarrate) { |
| 21540 | fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); |
| 21541 | } |
| 21542 | #endif |
| 21543 | next = regnext(preg, scan); |
| 21544 | n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); |
| 21545 | |
| @@ -21546,49 +21423,49 @@ | |
| 21546 | switch (OP(preg, scan)) { |
| 21547 | case BOLX: |
| 21548 | if ((preg->eflags & REG_NOTBOL)) { |
| 21549 | return(0); |
| 21550 | } |
| 21551 | |
| 21552 | case BOL: |
| 21553 | if (preg->reginput != preg->regbol) { |
| 21554 | return(0); |
| 21555 | } |
| 21556 | break; |
| 21557 | case EOLX: |
| 21558 | if (c != 0) { |
| 21559 | |
| 21560 | return 0; |
| 21561 | } |
| 21562 | break; |
| 21563 | case EOL: |
| 21564 | if (!reg_iseol(preg, c)) { |
| 21565 | return(0); |
| 21566 | } |
| 21567 | break; |
| 21568 | case WORDA: |
| 21569 | |
| 21570 | if ((!isalnum(UCHAR(c))) && c != '_') |
| 21571 | return(0); |
| 21572 | |
| 21573 | if (preg->reginput > preg->regbol && |
| 21574 | (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_')) |
| 21575 | return(0); |
| 21576 | break; |
| 21577 | case WORDZ: |
| 21578 | |
| 21579 | if (preg->reginput > preg->regbol) { |
| 21580 | |
| 21581 | if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { |
| 21582 | c = preg->reginput[-1]; |
| 21583 | |
| 21584 | if (isalnum(UCHAR(c)) || c == '_') { |
| 21585 | break; |
| 21586 | } |
| 21587 | } |
| 21588 | } |
| 21589 | |
| 21590 | return(0); |
| 21591 | |
| 21592 | case ANY: |
| 21593 | if (reg_iseol(preg, c)) |
| 21594 | return 0; |
| @@ -21624,12 +21501,12 @@ | |
| 21624 | case NOTHING: |
| 21625 | break; |
| 21626 | case BACK: |
| 21627 | break; |
| 21628 | case BRANCH: |
| 21629 | if (OP(preg, next) != BRANCH) |
| 21630 | next = OPERAND(scan); |
| 21631 | else { |
| 21632 | do { |
| 21633 | save = preg->reginput; |
| 21634 | if (regmatch(preg, OPERAND(scan))) { |
| 21635 | return(1); |
| @@ -21636,11 +21513,11 @@ | |
| 21636 | } |
| 21637 | preg->reginput = save; |
| 21638 | scan = regnext(preg, scan); |
| 21639 | } while (scan != 0 && OP(preg, scan) == BRANCH); |
| 21640 | return(0); |
| 21641 | |
| 21642 | } |
| 21643 | break; |
| 21644 | case REP: |
| 21645 | case REPMIN: |
| 21646 | return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); |
| @@ -21648,11 +21525,11 @@ | |
| 21648 | case REPX: |
| 21649 | case REPXMIN: |
| 21650 | return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); |
| 21651 | |
| 21652 | case END: |
| 21653 | return 1; |
| 21654 | |
| 21655 | case OPENNC: |
| 21656 | case CLOSENC: |
| 21657 | return regmatch(preg, next); |
| 21658 | |
| @@ -21695,11 +21572,11 @@ | |
| 21695 | |
| 21696 | scan = preg->reginput; |
| 21697 | opnd = OPERAND(p); |
| 21698 | switch (OP(preg, p)) { |
| 21699 | case ANY: |
| 21700 | |
| 21701 | while (!reg_iseol(preg, *scan) && count < max) { |
| 21702 | count++; |
| 21703 | scan++; |
| 21704 | } |
| 21705 | break; |
| @@ -21731,13 +21608,13 @@ | |
| 21731 | } |
| 21732 | count++; |
| 21733 | scan += n; |
| 21734 | } |
| 21735 | break; |
| 21736 | default: |
| 21737 | preg->err = REG_ERR_INTERNAL; |
| 21738 | count = 0; |
| 21739 | break; |
| 21740 | } |
| 21741 | preg->reginput = scan; |
| 21742 | |
| 21743 | return(count); |
| @@ -21758,11 +21635,11 @@ | |
| 21758 | return(p+offset); |
| 21759 | } |
| 21760 | |
| 21761 | static int regopsize(regex_t *preg, int p ) |
| 21762 | { |
| 21763 | |
| 21764 | switch (OP(preg, p)) { |
| 21765 | case REP: |
| 21766 | case REPMIN: |
| 21767 | case REPX: |
| 21768 | case REPXMIN: |
| @@ -21818,10 +21695,223 @@ | |
| 21818 | |
| 21819 | void regfree(regex_t *preg) |
| 21820 | { |
| 21821 | free(preg->program); |
| 21822 | } |
| 21823 | |
| 21824 | #endif |
| 21825 | |
| 21826 | #if defined(_WIN32) || defined(WIN32) |
| 21827 | #ifndef STRICT |
| @@ -21879,26 +21969,26 @@ | |
| 21879 | { |
| 21880 | DIR *dir = 0; |
| 21881 | |
| 21882 | if (name && name[0]) { |
| 21883 | size_t base_length = strlen(name); |
| 21884 | const char *all = |
| 21885 | strchr("/\\", name[base_length - 1]) ? "*" : "/*"; |
| 21886 | |
| 21887 | if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 && |
| 21888 | (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) { |
| 21889 | strcat(strcpy(dir->name, name), all); |
| 21890 | |
| 21891 | if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1) |
| 21892 | dir->result.d_name = 0; |
| 21893 | else { |
| 21894 | Jim_Free(dir->name); |
| 21895 | Jim_Free(dir); |
| 21896 | dir = 0; |
| 21897 | } |
| 21898 | } |
| 21899 | else { |
| 21900 | Jim_Free(dir); |
| 21901 | dir = 0; |
| 21902 | errno = ENOMEM; |
| 21903 | } |
| 21904 | } |
| @@ -21916,11 +22006,11 @@ | |
| 21916 | if (dir->handle != -1) |
| 21917 | result = _findclose(dir->handle); |
| 21918 | Jim_Free(dir->name); |
| 21919 | Jim_Free(dir); |
| 21920 | } |
| 21921 | if (result == -1) |
| 21922 | errno = EBADF; |
| 21923 | return result; |
| 21924 | } |
| 21925 | |
| 21926 | struct dirent *readdir(DIR * dir) |
| @@ -21938,28 +22028,77 @@ | |
| 21938 | } |
| 21939 | return result; |
| 21940 | } |
| 21941 | #endif |
| 21942 | #endif |
| 21943 | #ifndef JIM_BOOTSTRAP_LIB_ONLY |
| 21944 | #include <errno.h> |
| 21945 | #include <string.h> |
| 21946 | |
| 21947 | |
| 21948 | #ifdef USE_LINENOISE |
| 21949 | #ifdef HAVE_UNISTD_H |
| 21950 | #include <unistd.h> |
| 21951 | #endif |
| 21952 | #include "linenoise.h" |
| 21953 | #else |
| 21954 | #define MAX_LINE_LEN 512 |
| 21955 | #endif |
| 21956 | |
| 21957 | char *Jim_HistoryGetline(const char *prompt) |
| 21958 | { |
| 21959 | #ifdef USE_LINENOISE |
| 21960 | return linenoise(prompt); |
| 21961 | #else |
| 21962 | int len; |
| 21963 | char *line = malloc(MAX_LINE_LEN); |
| 21964 | |
| 21965 | fputs(prompt, stdout); |
| @@ -21992,26 +22131,92 @@ | |
| 21992 | } |
| 21993 | |
| 21994 | void Jim_HistorySave(const char *filename) |
| 21995 | { |
| 21996 | #ifdef USE_LINENOISE |
| 21997 | linenoiseHistorySave(filename); |
| 21998 | #endif |
| 21999 | } |
| 22000 | |
| 22001 | void Jim_HistoryShow(void) |
| 22002 | { |
| 22003 | #ifdef USE_LINENOISE |
| 22004 | |
| 22005 | int i; |
| 22006 | int len; |
| 22007 | char **history = linenoiseHistory(&len); |
| 22008 | for (i = 0; i < len; i++) { |
| 22009 | printf("%4d %s\n", i + 1, history[i]); |
| 22010 | } |
| 22011 | #endif |
| 22012 | } |
| 22013 | |
| 22014 | int Jim_InteractivePrompt(Jim_Interp *interp) |
| 22015 | { |
| 22016 | int retcode = JIM_OK; |
| 22017 | char *history_file = NULL; |
| @@ -22023,10 +22228,12 @@ | |
| 22023 | int history_len = strlen(home) + sizeof("/.jim_history"); |
| 22024 | history_file = Jim_Alloc(history_len); |
| 22025 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 22026 | Jim_HistoryLoad(history_file); |
| 22027 | } |
| 22028 | #endif |
| 22029 | |
| 22030 | printf("Welcome to Jim version %d.%d\n", |
| 22031 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 22032 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| @@ -22055,21 +22262,21 @@ | |
| 22055 | Jim_IncrRefCount(scriptObjPtr); |
| 22056 | while (1) { |
| 22057 | char state; |
| 22058 | char *line; |
| 22059 | |
| 22060 | line = Jim_HistoryGetline(prompt); |
| 22061 | if (line == NULL) { |
| 22062 | if (errno == EINTR) { |
| 22063 | continue; |
| 22064 | } |
| 22065 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 22066 | retcode = JIM_OK; |
| 22067 | goto out; |
| 22068 | } |
| 22069 | if (Jim_Length(scriptObjPtr) != 0) { |
| 22070 | |
| 22071 | Jim_AppendString(interp, scriptObjPtr, "\n", 1); |
| 22072 | } |
| 22073 | Jim_AppendString(interp, scriptObjPtr, line, -1); |
| 22074 | free(line); |
| 22075 | if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state)) |
| @@ -22077,11 +22284,11 @@ | |
| 22077 | |
| 22078 | snprintf(prompt, sizeof(prompt), "%c> ", state); |
| 22079 | } |
| 22080 | #ifdef USE_LINENOISE |
| 22081 | if (strcmp(Jim_String(scriptObjPtr), "h") == 0) { |
| 22082 | |
| 22083 | Jim_HistoryShow(); |
| 22084 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 22085 | continue; |
| 22086 | } |
| 22087 | |
| @@ -22104,10 +22311,11 @@ | |
| 22104 | printf("%s\n", result); |
| 22105 | } |
| 22106 | } |
| 22107 | out: |
| 22108 | Jim_Free(history_file); |
| 22109 | return retcode; |
| 22110 | } |
| 22111 | |
| 22112 | #include <stdio.h> |
| 22113 | #include <stdlib.h> |
| @@ -22120,11 +22328,11 @@ | |
| 22120 | static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) |
| 22121 | { |
| 22122 | int n; |
| 22123 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 22124 | |
| 22125 | |
| 22126 | for (n = 0; n < argc; n++) { |
| 22127 | Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1); |
| 22128 | |
| 22129 | Jim_ListAppendElement(interp, listObj, obj); |
| 22130 | } |
| @@ -22146,71 +22354,75 @@ | |
| 22146 | printf("or : %s [options] [filename]\n", executable_name); |
| 22147 | printf("\n"); |
| 22148 | printf("Without options: Interactive mode\n"); |
| 22149 | printf("\n"); |
| 22150 | printf("Options:\n"); |
| 22151 | printf(" --version : prints the version string\n"); |
| 22152 | printf(" --help : prints this text\n"); |
| 22153 | printf(" -e CMD : executes command CMD\n"); |
| 22154 | printf(" NOTE: all subsequent options will be passed as arguments to the command\n"); |
| 22155 | printf(" [filename] : executes the script contained in the named file\n"); |
| 22156 | printf(" NOTE: all subsequent options will be passed to the script\n\n"); |
| 22157 | } |
| 22158 | |
| 22159 | int main(int argc, char *const argv[]) |
| 22160 | { |
| 22161 | int retcode; |
| 22162 | Jim_Interp *interp; |
| 22163 | char *const orig_argv0 = argv[0]; |
| 22164 | |
| 22165 | |
| 22166 | if (argc > 1 && strcmp(argv[1], "--version") == 0) { |
| 22167 | printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100); |
| 22168 | return 0; |
| 22169 | } |
| 22170 | else if (argc > 1 && strcmp(argv[1], "--help") == 0) { |
| 22171 | usage(argv[0]); |
| 22172 | return 0; |
| 22173 | } |
| 22174 | |
| 22175 | |
| 22176 | interp = Jim_CreateInterp(); |
| 22177 | Jim_RegisterCoreCommands(interp); |
| 22178 | |
| 22179 | |
| 22180 | if (Jim_InitStaticExtensions(interp) != JIM_OK) { |
| 22181 | JimPrintErrorMessage(interp); |
| 22182 | } |
| 22183 | |
| 22184 | Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0); |
| 22185 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); |
| 22186 | retcode = Jim_initjimshInit(interp); |
| 22187 | |
| 22188 | if (argc == 1) { |
| 22189 | |
| 22190 | if (retcode == JIM_ERR) { |
| 22191 | JimPrintErrorMessage(interp); |
| 22192 | } |
| 22193 | if (retcode != JIM_EXIT) { |
| 22194 | JimSetArgv(interp, 0, NULL); |
| 22195 | retcode = Jim_InteractivePrompt(interp); |
| 22196 | } |
| 22197 | } |
| 22198 | else { |
| 22199 | |
| 22200 | if (argc > 2 && strcmp(argv[1], "-e") == 0) { |
| 22201 | |
| 22202 | JimSetArgv(interp, argc - 3, argv + 3); |
| 22203 | retcode = Jim_Eval(interp, argv[2]); |
| 22204 | if (retcode != JIM_ERR) { |
| 22205 | printf("%s\n", Jim_String(Jim_GetResult(interp))); |
| 22206 | } |
| 22207 | } |
| 22208 | else { |
| 22209 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 22210 | JimSetArgv(interp, argc - 2, argv + 2); |
| 22211 | retcode = Jim_EvalFile(interp, argv[1]); |
| 22212 | } |
| 22213 | if (retcode == JIM_ERR) { |
| 22214 | JimPrintErrorMessage(interp); |
| 22215 | } |
| 22216 | } |
| 22217 |
| --- autosetup/jimsh0.c | |
| +++ autosetup/jimsh0.c | |
| @@ -1,9 +1,7 @@ | |
| 1 | /* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */ |
| 2 | #define JIM_TCL_COMPAT |
| 3 | #define JIM_ANSIC |
| 4 | #define JIM_REGEXP |
| 5 | #define HAVE_NO_AUTOCONF |
| 6 | #define _JIMAUTOCONF_H |
| 7 | #define TCL_LIBRARY "." |
| @@ -31,24 +29,39 @@ | |
| 29 | #define HAVE_MKDIR_ONE_ARG |
| 30 | #define HAVE_SYSTEM |
| 31 | #define HAVE_SYS_TIME_H |
| 32 | #define HAVE_DIRENT_H |
| 33 | #define HAVE_UNISTD_H |
| 34 | #define HAVE_UMASK |
| 35 | #include <sys/stat.h> |
| 36 | #ifndef S_IRWXG |
| 37 | #define S_IRWXG 0 |
| 38 | #endif |
| 39 | #ifndef S_IRWXO |
| 40 | #define S_IRWXO 0 |
| 41 | #endif |
| 42 | #else |
| 43 | #define TCL_PLATFORM_OS "unknown" |
| 44 | #define TCL_PLATFORM_PLATFORM "unix" |
| 45 | #define TCL_PLATFORM_PATH_SEPARATOR ":" |
| 46 | #ifdef _MINIX |
| 47 | #define vfork fork |
| 48 | #define _POSIX_SOURCE |
| 49 | #else |
| 50 | #define _GNU_SOURCE |
| 51 | #endif |
| 52 | #define HAVE_VFORK |
| 53 | #define HAVE_WAITPID |
| 54 | #define HAVE_ISATTY |
| 55 | #define HAVE_MKSTEMP |
| 56 | #define HAVE_LINK |
| 57 | #define HAVE_SYS_TIME_H |
| 58 | #define HAVE_DIRENT_H |
| 59 | #define HAVE_UNISTD_H |
| 60 | #define HAVE_UMASK |
| 61 | #endif |
| 62 | #define JIM_VERSION 78 |
| 63 | #ifndef JIM_WIN32COMPAT_H |
| 64 | #define JIM_WIN32COMPAT_H |
| 65 | |
| 66 | |
| 67 | |
| @@ -88,11 +101,10 @@ | |
| 101 | #define JIM_WIDE_MIN LLONG_MIN |
| 102 | #define JIM_WIDE_MAX LLONG_MAX |
| 103 | #define JIM_WIDE_MODIFIER "I64d" |
| 104 | #define strcasecmp _stricmp |
| 105 | #define strtoull _strtoui64 |
| 106 | |
| 107 | #include <io.h> |
| 108 | |
| 109 | struct timeval { |
| 110 | long tv_sec; |
| @@ -105,29 +117,24 @@ | |
| 117 | struct dirent { |
| 118 | char *d_name; |
| 119 | }; |
| 120 | |
| 121 | typedef struct DIR { |
| 122 | long handle; |
| 123 | struct _finddata_t info; |
| 124 | struct dirent result; |
| 125 | char *name; |
| 126 | } DIR; |
| 127 | |
| 128 | DIR *opendir(const char *name); |
| 129 | int closedir(DIR *dir); |
| 130 | struct dirent *readdir(DIR *dir); |
| 131 | |
| 132 | #endif |
| 133 | |
| 134 | #endif |
| 135 | |
| 136 | #ifdef __cplusplus |
| 137 | } |
| 138 | #endif |
| 139 | |
| 140 | #endif |
| @@ -146,19 +153,21 @@ | |
| 153 | |
| 154 | #ifndef JIM_UTF8 |
| 155 | #include <ctype.h> |
| 156 | |
| 157 | |
| 158 | #define utf8_strlen(S, B) ((B) < 0 ? (int)strlen(S) : (B)) |
| 159 | #define utf8_strwidth(S, B) utf8_strlen((S), (B)) |
| 160 | #define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) |
| 161 | #define utf8_getchars(CP, C) (*(CP) = (C), 1) |
| 162 | #define utf8_upper(C) toupper(C) |
| 163 | #define utf8_title(C) toupper(C) |
| 164 | #define utf8_lower(C) tolower(C) |
| 165 | #define utf8_index(C, I) (I) |
| 166 | #define utf8_charlen(C) 1 |
| 167 | #define utf8_prev_len(S, L) 1 |
| 168 | #define utf8_width(C) 1 |
| 169 | |
| 170 | #else |
| 171 | |
| 172 | #endif |
| 173 | |
| @@ -175,13 +184,13 @@ | |
| 184 | extern "C" { |
| 185 | #endif |
| 186 | |
| 187 | #include <time.h> |
| 188 | #include <limits.h> |
| 189 | #include <stdio.h> |
| 190 | #include <stdlib.h> |
| 191 | #include <stdarg.h> |
| 192 | |
| 193 | |
| 194 | #ifndef HAVE_NO_AUTOCONF |
| 195 | #endif |
| 196 | |
| @@ -224,31 +233,31 @@ | |
| 233 | #define JIM_SIGNAL 5 |
| 234 | #define JIM_EXIT 6 |
| 235 | |
| 236 | #define JIM_EVAL 7 |
| 237 | |
| 238 | #define JIM_MAX_CALLFRAME_DEPTH 1000 |
| 239 | #define JIM_MAX_EVAL_DEPTH 2000 |
| 240 | |
| 241 | |
| 242 | #define JIM_PRIV_FLAG_SHIFT 20 |
| 243 | |
| 244 | #define JIM_NONE 0 |
| 245 | #define JIM_ERRMSG 1 |
| 246 | #define JIM_ENUM_ABBREV 2 |
| 247 | #define JIM_UNSHARED 4 |
| 248 | #define JIM_MUSTEXIST 8 |
| 249 | |
| 250 | |
| 251 | #define JIM_SUBST_NOVAR 1 |
| 252 | #define JIM_SUBST_NOCMD 2 |
| 253 | #define JIM_SUBST_NOESC 4 |
| 254 | #define JIM_SUBST_FLAG 128 |
| 255 | |
| 256 | |
| 257 | #define JIM_CASESENS 0 |
| 258 | #define JIM_NOCASE 1 |
| 259 | |
| 260 | |
| 261 | #define JIM_PATH_LEN 1024 |
| 262 | |
| 263 | |
| @@ -339,79 +348,80 @@ | |
| 348 | #define Jim_GetHashTableSize(ht) ((ht)->size) |
| 349 | #define Jim_GetHashTableUsed(ht) ((ht)->used) |
| 350 | |
| 351 | |
| 352 | typedef struct Jim_Obj { |
| 353 | char *bytes; |
| 354 | const struct Jim_ObjType *typePtr; |
| 355 | int refCount; |
| 356 | int length; |
| 357 | |
| 358 | union { |
| 359 | |
| 360 | jim_wide wideValue; |
| 361 | |
| 362 | int intValue; |
| 363 | |
| 364 | double doubleValue; |
| 365 | |
| 366 | void *ptr; |
| 367 | |
| 368 | struct { |
| 369 | void *ptr1; |
| 370 | void *ptr2; |
| 371 | } twoPtrValue; |
| 372 | |
| 373 | struct { |
| 374 | void *ptr; |
| 375 | int int1; |
| 376 | int int2; |
| 377 | } ptrIntValue; |
| 378 | |
| 379 | struct { |
| 380 | struct Jim_Var *varPtr; |
| 381 | unsigned long callFrameId; |
| 382 | int global; |
| 383 | } varValue; |
| 384 | |
| 385 | struct { |
| 386 | struct Jim_Obj *nsObj; |
| 387 | struct Jim_Cmd *cmdPtr; |
| 388 | unsigned long procEpoch; |
| 389 | } cmdValue; |
| 390 | |
| 391 | struct { |
| 392 | struct Jim_Obj **ele; |
| 393 | int len; |
| 394 | int maxLen; |
| 395 | } listValue; |
| 396 | |
| 397 | struct { |
| 398 | int maxLength; |
| 399 | int charLength; |
| 400 | } strValue; |
| 401 | |
| 402 | struct { |
| 403 | unsigned long id; |
| 404 | struct Jim_Reference *refPtr; |
| 405 | } refValue; |
| 406 | |
| 407 | struct { |
| 408 | struct Jim_Obj *fileNameObj; |
| 409 | int lineNumber; |
| 410 | } sourceValue; |
| 411 | |
| 412 | struct { |
| 413 | struct Jim_Obj *varNameObjPtr; |
| 414 | struct Jim_Obj *indexObjPtr; |
| 415 | } dictSubstValue; |
| 416 | struct { |
| 417 | int line; |
| 418 | int argc; |
| 419 | } scriptLineValue; |
| 420 | } internalRep; |
| 421 | struct Jim_Obj *prevObjPtr; |
| 422 | struct Jim_Obj *nextObjPtr; |
| 423 | } Jim_Obj; |
| 424 | |
| 425 | |
| 426 | #define Jim_IncrRefCount(objPtr) \ |
| 427 | ++(objPtr)->refCount |
| @@ -442,40 +452,40 @@ | |
| 452 | typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, |
| 453 | struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 454 | typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); |
| 455 | |
| 456 | typedef struct Jim_ObjType { |
| 457 | const char *name; |
| 458 | Jim_FreeInternalRepProc *freeIntRepProc; |
| 459 | Jim_DupInternalRepProc *dupIntRepProc; |
| 460 | Jim_UpdateStringProc *updateStringProc; |
| 461 | int flags; |
| 462 | } Jim_ObjType; |
| 463 | |
| 464 | |
| 465 | #define JIM_TYPE_NONE 0 |
| 466 | #define JIM_TYPE_REFERENCES 1 |
| 467 | |
| 468 | |
| 469 | |
| 470 | typedef struct Jim_CallFrame { |
| 471 | unsigned long id; |
| 472 | int level; |
| 473 | struct Jim_HashTable vars; |
| 474 | struct Jim_HashTable *staticVars; |
| 475 | struct Jim_CallFrame *parent; |
| 476 | Jim_Obj *const *argv; |
| 477 | int argc; |
| 478 | Jim_Obj *procArgsObjPtr; |
| 479 | Jim_Obj *procBodyObjPtr; |
| 480 | struct Jim_CallFrame *next; |
| 481 | Jim_Obj *nsObj; |
| 482 | Jim_Obj *fileNameObj; |
| 483 | int line; |
| 484 | Jim_Stack *localCommands; |
| 485 | struct Jim_Obj *tailcallObj; |
| 486 | struct Jim_Cmd *tailcallCmd; |
| 487 | } Jim_CallFrame; |
| 488 | |
| 489 | typedef struct Jim_Var { |
| 490 | Jim_Obj *objPtr; |
| 491 | struct Jim_CallFrame *linkFramePtr; |
| @@ -487,35 +497,35 @@ | |
| 497 | typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); |
| 498 | |
| 499 | |
| 500 | |
| 501 | typedef struct Jim_Cmd { |
| 502 | int inUse; |
| 503 | int isproc; |
| 504 | struct Jim_Cmd *prevCmd; |
| 505 | union { |
| 506 | struct { |
| 507 | |
| 508 | Jim_CmdProc *cmdProc; |
| 509 | Jim_DelCmdProc *delProc; |
| 510 | void *privData; |
| 511 | } native; |
| 512 | struct { |
| 513 | |
| 514 | Jim_Obj *argListObjPtr; |
| 515 | Jim_Obj *bodyObjPtr; |
| 516 | Jim_HashTable *staticVars; |
| 517 | int argListLen; |
| 518 | int reqArity; |
| 519 | int optArity; |
| 520 | int argsPos; |
| 521 | int upcall; |
| 522 | struct Jim_ProcArg { |
| 523 | Jim_Obj *nameObjPtr; |
| 524 | Jim_Obj *defaultObjPtr; |
| 525 | } *arglist; |
| 526 | Jim_Obj *nsObj; |
| 527 | } proc; |
| 528 | } u; |
| 529 | } Jim_Cmd; |
| 530 | |
| 531 | |
| @@ -523,64 +533,64 @@ | |
| 533 | unsigned char sbox[256]; |
| 534 | unsigned int i, j; |
| 535 | } Jim_PrngState; |
| 536 | |
| 537 | typedef struct Jim_Interp { |
| 538 | Jim_Obj *result; |
| 539 | int errorLine; |
| 540 | Jim_Obj *errorFileNameObj; |
| 541 | int addStackTrace; |
| 542 | int maxCallFrameDepth; |
| 543 | int maxEvalDepth; |
| 544 | int evalDepth; |
| 545 | int returnCode; |
| 546 | int returnLevel; |
| 547 | int exitCode; |
| 548 | long id; |
| 549 | int signal_level; |
| 550 | jim_wide sigmask; |
| 551 | int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); |
| 552 | Jim_CallFrame *framePtr; |
| 553 | Jim_CallFrame *topFramePtr; |
| 554 | struct Jim_HashTable commands; |
| 555 | unsigned long procEpoch; /* Incremented every time the result |
| 556 | of procedures names lookup caching |
| 557 | may no longer be valid. */ |
| 558 | unsigned long callFrameEpoch; /* Incremented every time a new |
| 559 | callframe is created. This id is used for the |
| 560 | 'ID' field contained in the Jim_CallFrame |
| 561 | structure. */ |
| 562 | int local; |
| 563 | Jim_Obj *liveList; |
| 564 | Jim_Obj *freeList; |
| 565 | Jim_Obj *currentScriptObj; |
| 566 | Jim_Obj *nullScriptObj; |
| 567 | Jim_Obj *emptyObj; |
| 568 | Jim_Obj *trueObj; |
| 569 | Jim_Obj *falseObj; |
| 570 | unsigned long referenceNextId; |
| 571 | struct Jim_HashTable references; |
| 572 | unsigned long lastCollectId; /* reference max Id of the last GC |
| 573 | execution. It's set to -1 while the collection |
| 574 | is running as sentinel to avoid to recursive |
| 575 | calls via the [collect] command inside |
| 576 | finalizers. */ |
| 577 | time_t lastCollectTime; |
| 578 | Jim_Obj *stackTrace; |
| 579 | Jim_Obj *errorProc; |
| 580 | Jim_Obj *unknown; |
| 581 | int unknown_called; |
| 582 | int errorFlag; |
| 583 | void *cmdPrivData; /* Used to pass the private data pointer to |
| 584 | a command. It is set to what the user specified |
| 585 | via Jim_CreateCommand(). */ |
| 586 | |
| 587 | struct Jim_CallFrame *freeFramesList; |
| 588 | struct Jim_HashTable assocData; |
| 589 | Jim_PrngState *prngState; |
| 590 | struct Jim_HashTable packages; |
| 591 | Jim_Stack *loadHandles; |
| 592 | } Jim_Interp; |
| 593 | |
| 594 | #define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ |
| 595 | #define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) |
| 596 | #define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) |
| @@ -623,11 +633,11 @@ | |
| 633 | JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); |
| 634 | |
| 635 | |
| 636 | JIM_EXPORT char **Jim_GetEnviron(void); |
| 637 | JIM_EXPORT void Jim_SetEnviron(char **env); |
| 638 | JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file); |
| 639 | |
| 640 | |
| 641 | JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); |
| 642 | |
| 643 | |
| @@ -816,25 +826,33 @@ | |
| 826 | Jim_Obj *newObjPtr, int flags); |
| 827 | JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, |
| 828 | Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); |
| 829 | JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 830 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); |
| 831 | |
| 832 | #define JIM_DICTMATCH_KEYS 0x0001 |
| 833 | #define JIM_DICTMATCH_VALUES 0x002 |
| 834 | |
| 835 | JIM_EXPORT int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types); |
| 836 | JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); |
| 837 | JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); |
| 838 | JIM_EXPORT Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv); |
| 839 | |
| 840 | |
| 841 | JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, |
| 842 | int *intPtr); |
| 843 | |
| 844 | |
| 845 | JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, |
| 846 | Jim_Obj *exprObjPtr); |
| 847 | JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, |
| 848 | Jim_Obj *exprObjPtr, int *boolPtr); |
| 849 | |
| 850 | |
| 851 | JIM_EXPORT int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, |
| 852 | int *booleanPtr); |
| 853 | |
| 854 | |
| 855 | JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, |
| 856 | jim_wide *widePtr); |
| 857 | JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, |
| 858 | long *longPtr); |
| @@ -852,10 +870,12 @@ | |
| 870 | |
| 871 | JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, |
| 872 | Jim_Obj *const *argv, const char *msg); |
| 873 | JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, |
| 874 | const char * const *tablePtr, int *indexPtr, const char *name, int flags); |
| 875 | JIM_EXPORT int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, |
| 876 | const char *const *tablePtr); |
| 877 | JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp, |
| 878 | Jim_Obj *scriptObj, char *stateCharPtr); |
| 879 | |
| 880 | JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); |
| 881 | |
| @@ -878,11 +898,12 @@ | |
| 898 | |
| 899 | |
| 900 | JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); |
| 901 | JIM_EXPORT void Jim_HistoryLoad(const char *filename); |
| 902 | JIM_EXPORT void Jim_HistorySave(const char *filename); |
| 903 | JIM_EXPORT char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt); |
| 904 | JIM_EXPORT void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj); |
| 905 | JIM_EXPORT void Jim_HistoryAdd(const char *line); |
| 906 | JIM_EXPORT void Jim_HistoryShow(void); |
| 907 | |
| 908 | |
| 909 | JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); |
| @@ -904,11 +925,11 @@ | |
| 925 | |
| 926 | #ifdef __cplusplus |
| 927 | } |
| 928 | #endif |
| 929 | |
| 930 | #endif |
| 931 | |
| 932 | #ifndef JIM_SUBCMD_H |
| 933 | #define JIM_SUBCMD_H |
| 934 | |
| 935 | |
| @@ -915,24 +936,24 @@ | |
| 936 | #ifdef __cplusplus |
| 937 | extern "C" { |
| 938 | #endif |
| 939 | |
| 940 | |
| 941 | #define JIM_MODFLAG_HIDDEN 0x0001 |
| 942 | #define JIM_MODFLAG_FULLARGV 0x0002 |
| 943 | |
| 944 | |
| 945 | |
| 946 | typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 947 | |
| 948 | typedef struct { |
| 949 | const char *cmd; |
| 950 | const char *args; |
| 951 | jim_subcmd_function *function; |
| 952 | short minargs; |
| 953 | short maxargs; |
| 954 | unsigned short flags; |
| 955 | } jim_subcmd_type; |
| 956 | |
| 957 | const jim_subcmd_type * |
| 958 | Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); |
| 959 | |
| @@ -960,36 +981,36 @@ | |
| 981 | int rm_eo; |
| 982 | } regmatch_t; |
| 983 | |
| 984 | |
| 985 | typedef struct regexp { |
| 986 | |
| 987 | int re_nsub; |
| 988 | |
| 989 | |
| 990 | int cflags; |
| 991 | int err; |
| 992 | int regstart; |
| 993 | int reganch; |
| 994 | int regmust; |
| 995 | int regmlen; |
| 996 | int *program; |
| 997 | |
| 998 | |
| 999 | const char *regparse; |
| 1000 | int p; |
| 1001 | int proglen; |
| 1002 | |
| 1003 | |
| 1004 | int eflags; |
| 1005 | const char *start; |
| 1006 | const char *reginput; |
| 1007 | const char *regbol; |
| 1008 | |
| 1009 | |
| 1010 | regmatch_t *pmatch; |
| 1011 | int nmatch; |
| 1012 | } regexp; |
| 1013 | |
| 1014 | typedef regexp regex_t; |
| 1015 | |
| 1016 | #define REG_EXTENDED 0 |
| @@ -997,13 +1018,13 @@ | |
| 1018 | #define REG_ICASE 2 |
| 1019 | |
| 1020 | #define REG_NOTBOL 16 |
| 1021 | |
| 1022 | enum { |
| 1023 | REG_NOERROR, |
| 1024 | REG_NOMATCH, |
| 1025 | REG_BADPAT, |
| 1026 | REG_ERR_NULL_ARGUMENT, |
| 1027 | REG_ERR_UNKNOWN, |
| 1028 | REG_ERR_TOO_BIG, |
| 1029 | REG_ERR_NOMEM, |
| 1030 | REG_ERR_TOO_MANY_PAREN, |
| @@ -1027,10 +1048,83 @@ | |
| 1048 | void regfree(regex_t *preg); |
| 1049 | |
| 1050 | #ifdef __cplusplus |
| 1051 | } |
| 1052 | #endif |
| 1053 | |
| 1054 | #endif |
| 1055 | #ifndef JIM_SIGNAL_H |
| 1056 | #define JIM_SIGNAL_H |
| 1057 | |
| 1058 | #ifdef __cplusplus |
| 1059 | extern "C" { |
| 1060 | #endif |
| 1061 | |
| 1062 | const char *Jim_SignalId(int sig); |
| 1063 | |
| 1064 | #ifdef __cplusplus |
| 1065 | } |
| 1066 | #endif |
| 1067 | |
| 1068 | #endif |
| 1069 | #ifndef JIMIOCOMPAT_H |
| 1070 | #define JIMIOCOMPAT_H |
| 1071 | |
| 1072 | |
| 1073 | #include <stdio.h> |
| 1074 | #include <errno.h> |
| 1075 | |
| 1076 | |
| 1077 | void Jim_SetResultErrno(Jim_Interp *interp, const char *msg); |
| 1078 | |
| 1079 | int Jim_OpenForWrite(const char *filename, int append); |
| 1080 | |
| 1081 | int Jim_OpenForRead(const char *filename); |
| 1082 | |
| 1083 | #if defined(__MINGW32__) |
| 1084 | #ifndef STRICT |
| 1085 | #define STRICT |
| 1086 | #endif |
| 1087 | #define WIN32_LEAN_AND_MEAN |
| 1088 | #include <windows.h> |
| 1089 | #include <fcntl.h> |
| 1090 | #include <io.h> |
| 1091 | #include <process.h> |
| 1092 | |
| 1093 | typedef HANDLE pidtype; |
| 1094 | #define JIM_BAD_PID INVALID_HANDLE_VALUE |
| 1095 | |
| 1096 | #define JIM_NO_PID INVALID_HANDLE_VALUE |
| 1097 | |
| 1098 | |
| 1099 | #define WIFEXITED(STATUS) (((STATUS) & 0xff00) == 0) |
| 1100 | #define WEXITSTATUS(STATUS) ((STATUS) & 0x00ff) |
| 1101 | #define WIFSIGNALED(STATUS) (((STATUS) & 0xff00) != 0) |
| 1102 | #define WTERMSIG(STATUS) (((STATUS) >> 8) & 0xff) |
| 1103 | #define WNOHANG 1 |
| 1104 | |
| 1105 | int Jim_Errno(void); |
| 1106 | pidtype waitpid(pidtype pid, int *status, int nohang); |
| 1107 | |
| 1108 | #define HAVE_PIPE |
| 1109 | #define pipe(P) _pipe((P), 0, O_NOINHERIT) |
| 1110 | |
| 1111 | #elif defined(HAVE_UNISTD_H) |
| 1112 | #include <unistd.h> |
| 1113 | #include <fcntl.h> |
| 1114 | #include <sys/wait.h> |
| 1115 | #include <sys/stat.h> |
| 1116 | |
| 1117 | typedef int pidtype; |
| 1118 | #define Jim_Errno() errno |
| 1119 | #define JIM_BAD_PID -1 |
| 1120 | #define JIM_NO_PID 0 |
| 1121 | |
| 1122 | #ifndef HAVE_EXECVPE |
| 1123 | #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) |
| 1124 | #endif |
| 1125 | #endif |
| 1126 | |
| 1127 | #endif |
| 1128 | int Jim_bootstrapInit(Jim_Interp *interp) |
| 1129 | { |
| 1130 | if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG)) |
| @@ -1100,10 +1194,43 @@ | |
| 1194 | "\n" |
| 1195 | "if {$tcl_platform(platform) eq \"windows\"} {\n" |
| 1196 | " set jim::argv0 [string map {\\\\ /} $jim::argv0]\n" |
| 1197 | "}\n" |
| 1198 | "\n" |
| 1199 | "\n" |
| 1200 | "set tcl::autocomplete_commands {info tcl::prefix socket namespace array clock file package string dict signal history}\n" |
| 1201 | "\n" |
| 1202 | "\n" |
| 1203 | "\n" |
| 1204 | "proc tcl::autocomplete {prefix} {\n" |
| 1205 | " if {[set space [string first \" \" $prefix]] != -1} {\n" |
| 1206 | " set cmd [string range $prefix 0 $space-1]\n" |
| 1207 | " if {$cmd in $::tcl::autocomplete_commands || [info channel $cmd] ne \"\"} {\n" |
| 1208 | " set arg [string range $prefix $space+1 end]\n" |
| 1209 | "\n" |
| 1210 | " return [lmap p [$cmd -commands] {\n" |
| 1211 | " if {![string match \"${arg}*\" $p]} continue\n" |
| 1212 | " function \"$cmd $p\"\n" |
| 1213 | " }]\n" |
| 1214 | " }\n" |
| 1215 | " }\n" |
| 1216 | "\n" |
| 1217 | " if {[string match \"source *\" $prefix]} {\n" |
| 1218 | " set path [string range $prefix 7 end]\n" |
| 1219 | " return [lmap p [glob -nocomplain \"${path}*\"] {\n" |
| 1220 | " function \"source $p\"\n" |
| 1221 | " }]\n" |
| 1222 | " }\n" |
| 1223 | "\n" |
| 1224 | " return [lmap p [lsort [info commands $prefix*]] {\n" |
| 1225 | " if {[string match \"* *\" $p]} {\n" |
| 1226 | " continue\n" |
| 1227 | " }\n" |
| 1228 | " function $p\n" |
| 1229 | " }]\n" |
| 1230 | "}\n" |
| 1231 | "\n" |
| 1232 | "_jimsh_init\n" |
| 1233 | ); |
| 1234 | } |
| 1235 | int Jim_globInit(Jim_Interp *interp) |
| 1236 | { |
| @@ -1315,10 +1442,17 @@ | |
| 1442 | return JIM_ERR; |
| 1443 | |
| 1444 | return Jim_EvalSource(interp, "stdlib.tcl", 1, |
| 1445 | "\n" |
| 1446 | "\n" |
| 1447 | "if {![exists -command ref]} {\n" |
| 1448 | "\n" |
| 1449 | " proc ref {args} {{count 0}} {\n" |
| 1450 | " format %08x [incr count]\n" |
| 1451 | " }\n" |
| 1452 | "}\n" |
| 1453 | "\n" |
| 1454 | "\n" |
| 1455 | "proc lambda {arglist args} {\n" |
| 1456 | " tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" |
| 1457 | "}\n" |
| 1458 | "\n" |
| @@ -1375,10 +1509,17 @@ | |
| 1509 | " }\n" |
| 1510 | " join $lines \\n\n" |
| 1511 | "}\n" |
| 1512 | "\n" |
| 1513 | "\n" |
| 1514 | "\n" |
| 1515 | "proc defer {script} {\n" |
| 1516 | " upvar jim::defer v\n" |
| 1517 | " lappend v $script\n" |
| 1518 | "}\n" |
| 1519 | "\n" |
| 1520 | "\n" |
| 1521 | "\n" |
| 1522 | "proc errorInfo {msg {stacktrace \"\"}} {\n" |
| 1523 | " if {$stacktrace eq \"\"} {\n" |
| 1524 | "\n" |
| 1525 | " set stacktrace [info stacktrace]\n" |
| @@ -1402,31 +1543,10 @@ | |
| 1543 | " if {[exists ::jim::exe]} {\n" |
| 1544 | " return $::jim::exe\n" |
| 1545 | " }\n" |
| 1546 | "}\n" |
| 1547 | "\n" |
| 1548 | "\n" |
| 1549 | "proc {dict update} {&varName args script} {\n" |
| 1550 | " set keys {}\n" |
| 1551 | " foreach {n v} $args {\n" |
| 1552 | " upvar $v var_$v\n" |
| @@ -1445,23 +1565,10 @@ | |
| 1565 | " }\n" |
| 1566 | " }\n" |
| 1567 | " return {*}$opts $msg\n" |
| 1568 | "}\n" |
| 1569 | "\n" |
| 1570 | "proc {dict replace} {dictionary {args {key value}}} {\n" |
| 1571 | " if {[llength ${key value}] % 2} {\n" |
| 1572 | " tailcall {dict replace}\n" |
| 1573 | " }\n" |
| 1574 | " tailcall dict merge $dictionary ${key value}\n" |
| @@ -1503,15 +1610,10 @@ | |
| 1610 | " dict unset dictionary $k\n" |
| 1611 | " }\n" |
| 1612 | " return $dictionary\n" |
| 1613 | "}\n" |
| 1614 | "\n" |
| 1615 | "\n" |
| 1616 | "proc {dict for} {vars dictionary script} {\n" |
| 1617 | " if {[llength $vars] != 2} {\n" |
| 1618 | " return -code error \"must have exactly two variable names\"\n" |
| 1619 | " }\n" |
| @@ -1591,11 +1693,10 @@ | |
| 1693 | " tailcall {*}$args\n" |
| 1694 | "}\n" |
| 1695 | "\n" |
| 1696 | "\n" |
| 1697 | "\n" |
| 1698 | "proc parray {arrayname {pattern *} {puts puts}} {\n" |
| 1699 | " upvar $arrayname a\n" |
| 1700 | "\n" |
| 1701 | " set max 0\n" |
| 1702 | " foreach name [array names a $pattern]] {\n" |
| @@ -1647,11 +1748,11 @@ | |
| 1748 | "}\n" |
| 1749 | "\n" |
| 1750 | "\n" |
| 1751 | "\n" |
| 1752 | "proc popen {cmd {mode r}} {\n" |
| 1753 | " lassign [pipe] r w\n" |
| 1754 | " try {\n" |
| 1755 | " if {[string match \"w*\" $mode]} {\n" |
| 1756 | " lappend cmd <@$r &\n" |
| 1757 | " set pids [exec {*}$cmd]\n" |
| 1758 | " $r close\n" |
| @@ -1663,16 +1764,31 @@ | |
| 1764 | " set f $r\n" |
| 1765 | " }\n" |
| 1766 | " lambda {cmd args} {f pids} {\n" |
| 1767 | " if {$cmd eq \"pid\"} {\n" |
| 1768 | " return $pids\n" |
| 1769 | " }\n" |
| 1770 | " if {$cmd eq \"getfd\"} {\n" |
| 1771 | " $f getfd\n" |
| 1772 | " }\n" |
| 1773 | " if {$cmd eq \"close\"} {\n" |
| 1774 | " $f close\n" |
| 1775 | "\n" |
| 1776 | " set retopts {}\n" |
| 1777 | " foreach p $pids {\n" |
| 1778 | " lassign [wait $p] status - rc\n" |
| 1779 | " if {$status eq \"CHILDSTATUS\"} {\n" |
| 1780 | " if {$rc == 0} {\n" |
| 1781 | " continue\n" |
| 1782 | " }\n" |
| 1783 | " set msg \"child process exited abnormally\"\n" |
| 1784 | " } else {\n" |
| 1785 | " set msg \"child killed: received signal\"\n" |
| 1786 | " }\n" |
| 1787 | " set retopts [list -code error -errorcode [list $status $p $rc] $msg]\n" |
| 1788 | " }\n" |
| 1789 | " return {*}$retopts\n" |
| 1790 | " }\n" |
| 1791 | " tailcall $f $cmd {*}$args\n" |
| 1792 | " }\n" |
| 1793 | " } on error {error opts} {\n" |
| 1794 | " $r close\n" |
| @@ -1692,14 +1808,10 @@ | |
| 1808 | " if {[catch {$channelId pid} pids]} {\n" |
| 1809 | " return \"\"\n" |
| 1810 | " }\n" |
| 1811 | " return $pids\n" |
| 1812 | "}\n" |
| 1813 | "\n" |
| 1814 | "\n" |
| 1815 | "\n" |
| 1816 | "\n" |
| 1817 | "\n" |
| @@ -1780,10 +1892,13 @@ | |
| 1892 | "}\n" |
| 1893 | ); |
| 1894 | } |
| 1895 | |
| 1896 | |
| 1897 | #ifndef _GNU_SOURCE |
| 1898 | #define _GNU_SOURCE |
| 1899 | #endif |
| 1900 | #include <stdio.h> |
| 1901 | #include <string.h> |
| 1902 | #include <errno.h> |
| 1903 | #include <fcntl.h> |
| 1904 | #ifdef HAVE_UNISTD_H |
| @@ -1793,27 +1908,34 @@ | |
| 1908 | |
| 1909 | |
| 1910 | #if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) |
| 1911 | #include <sys/socket.h> |
| 1912 | #include <netinet/in.h> |
| 1913 | #include <netinet/tcp.h> |
| 1914 | #include <arpa/inet.h> |
| 1915 | #include <netdb.h> |
| 1916 | #ifdef HAVE_SYS_UN_H |
| 1917 | #include <sys/un.h> |
| 1918 | #endif |
| 1919 | #define HAVE_SOCKETS |
| 1920 | #elif defined (__MINGW32__) |
| 1921 | |
| 1922 | #else |
| 1923 | #define JIM_ANSIC |
| 1924 | #endif |
| 1925 | |
| 1926 | #if defined(JIM_SSL) |
| 1927 | #include <openssl/ssl.h> |
| 1928 | #include <openssl/err.h> |
| 1929 | #endif |
| 1930 | |
| 1931 | #ifdef HAVE_TERMIOS_H |
| 1932 | #endif |
| 1933 | |
| 1934 | |
| 1935 | #define AIO_CMD_LEN 32 |
| 1936 | #define AIO_BUF_LEN 256 |
| 1937 | |
| 1938 | #ifndef HAVE_FTELLO |
| 1939 | #define ftello ftell |
| 1940 | #endif |
| 1941 | #ifndef HAVE_FSEEKO |
| @@ -1828,10 +1950,16 @@ | |
| 1950 | #define IPV6 0 |
| 1951 | #ifndef PF_INET6 |
| 1952 | #define PF_INET6 0 |
| 1953 | #endif |
| 1954 | #endif |
| 1955 | |
| 1956 | #ifdef JIM_ANSIC |
| 1957 | |
| 1958 | #undef HAVE_PIPE |
| 1959 | #undef HAVE_SOCKETPAIR |
| 1960 | #endif |
| 1961 | |
| 1962 | #define JimCheckStreamError(interp, af) af->fops->error(af) |
| 1963 | |
| 1964 | |
| 1965 | struct AioFile; |
| @@ -1848,11 +1976,11 @@ | |
| 1976 | typedef struct AioFile |
| 1977 | { |
| 1978 | FILE *fp; |
| 1979 | Jim_Obj *filename; |
| 1980 | int type; |
| 1981 | int openFlags; |
| 1982 | int fd; |
| 1983 | Jim_Obj *rEvent; |
| 1984 | Jim_Obj *wEvent; |
| 1985 | Jim_Obj *eEvent; |
| 1986 | int addr_family; |
| @@ -1879,21 +2007,21 @@ | |
| 2007 | { |
| 2008 | if (!ferror(af->fp)) { |
| 2009 | return JIM_OK; |
| 2010 | } |
| 2011 | clearerr(af->fp); |
| 2012 | |
| 2013 | if (feof(af->fp) || errno == EAGAIN || errno == EINTR) { |
| 2014 | return JIM_OK; |
| 2015 | } |
| 2016 | #ifdef ECONNRESET |
| 2017 | if (errno == ECONNRESET) { |
| 2018 | return JIM_OK; |
| 2019 | } |
| 2020 | #endif |
| 2021 | #ifdef ECONNABORTED |
| 2022 | if (errno == ECONNABORTED) { |
| 2023 | return JIM_OK; |
| 2024 | } |
| 2025 | #endif |
| 2026 | return JIM_ERR; |
| 2027 | } |
| @@ -1945,20 +2073,19 @@ | |
| 2073 | JIM_NOTUSED(interp); |
| 2074 | |
| 2075 | Jim_DecrRefCount(interp, af->filename); |
| 2076 | |
| 2077 | #ifdef jim_ext_eventloop |
| 2078 | |
| 2079 | Jim_DeleteFileHandler(interp, af->fd, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); |
| 2080 | #endif |
| 2081 | |
| 2082 | #if defined(JIM_SSL) |
| 2083 | if (af->ssl != NULL) { |
| 2084 | SSL_free(af->ssl); |
| 2085 | } |
| 2086 | #endif |
| 2087 | if (!(af->openFlags & AIO_KEEPOPEN)) { |
| 2088 | fclose(af->fp); |
| 2089 | } |
| 2090 | |
| 2091 | Jim_Free(af); |
| @@ -1968,11 +2095,11 @@ | |
| 2095 | { |
| 2096 | AioFile *af = Jim_CmdPrivData(interp); |
| 2097 | char buf[AIO_BUF_LEN]; |
| 2098 | Jim_Obj *objPtr; |
| 2099 | int nonewline = 0; |
| 2100 | jim_wide neededLen = -1; |
| 2101 | |
| 2102 | if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { |
| 2103 | nonewline = 1; |
| 2104 | argv++; |
| 2105 | argc--; |
| @@ -2007,11 +2134,11 @@ | |
| 2134 | } |
| 2135 | } |
| 2136 | if (retval != readlen) |
| 2137 | break; |
| 2138 | } |
| 2139 | |
| 2140 | if (JimCheckStreamError(interp, af)) { |
| 2141 | Jim_FreeNewObj(interp, objPtr); |
| 2142 | return JIM_ERR; |
| 2143 | } |
| 2144 | if (nonewline) { |
| @@ -2029,11 +2156,11 @@ | |
| 2156 | |
| 2157 | AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command) |
| 2158 | { |
| 2159 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); |
| 2160 | |
| 2161 | |
| 2162 | if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { |
| 2163 | return (AioFile *) cmdPtr->u.native.privData; |
| 2164 | } |
| 2165 | Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); |
| 2166 | return NULL; |
| @@ -2048,10 +2175,20 @@ | |
| 2175 | return NULL; |
| 2176 | } |
| 2177 | |
| 2178 | return af->fp; |
| 2179 | } |
| 2180 | |
| 2181 | static int aio_cmd_getfd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2182 | { |
| 2183 | AioFile *af = Jim_CmdPrivData(interp); |
| 2184 | |
| 2185 | fflush(af->fp); |
| 2186 | Jim_SetResultInt(interp, fileno(af->fp)); |
| 2187 | |
| 2188 | return JIM_OK; |
| 2189 | } |
| 2190 | |
| 2191 | static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2192 | { |
| 2193 | AioFile *af = Jim_CmdPrivData(interp); |
| 2194 | jim_wide count = 0; |
| @@ -2110,21 +2247,21 @@ | |
| 2247 | } |
| 2248 | else { |
| 2249 | len = strlen(buf); |
| 2250 | |
| 2251 | if (len && (buf[len - 1] == '\n')) { |
| 2252 | |
| 2253 | len--; |
| 2254 | } |
| 2255 | |
| 2256 | Jim_AppendString(interp, objPtr, buf, len); |
| 2257 | break; |
| 2258 | } |
| 2259 | } |
| 2260 | |
| 2261 | if (JimCheckStreamError(interp, af)) { |
| 2262 | |
| 2263 | Jim_FreeNewObj(interp, objPtr); |
| 2264 | return JIM_ERR; |
| 2265 | } |
| 2266 | |
| 2267 | if (argc) { |
| @@ -2134,11 +2271,11 @@ | |
| 2271 | } |
| 2272 | |
| 2273 | len = Jim_Length(objPtr); |
| 2274 | |
| 2275 | if (len == 0 && feof(af->fp)) { |
| 2276 | |
| 2277 | len = -1; |
| 2278 | } |
| 2279 | Jim_SetResultInt(interp, len); |
| 2280 | } |
| 2281 | else { |
| @@ -2207,11 +2344,11 @@ | |
| 2344 | } |
| 2345 | |
| 2346 | static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2347 | { |
| 2348 | if (argc == 3) { |
| 2349 | #if defined(HAVE_SOCKETS) && defined(HAVE_SHUTDOWN) |
| 2350 | static const char * const options[] = { "r", "w", NULL }; |
| 2351 | enum { OPT_R, OPT_W, }; |
| 2352 | int option; |
| 2353 | AioFile *af = Jim_CmdPrivData(interp); |
| 2354 | |
| @@ -2297,10 +2434,11 @@ | |
| 2434 | } |
| 2435 | Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); |
| 2436 | return JIM_OK; |
| 2437 | } |
| 2438 | #endif |
| 2439 | |
| 2440 | |
| 2441 | #ifdef HAVE_FSYNC |
| 2442 | static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2443 | { |
| 2444 | AioFile *af = Jim_CmdPrivData(interp); |
| @@ -2364,33 +2502,33 @@ | |
| 2502 | |
| 2503 | static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, |
| 2504 | int argc, Jim_Obj * const *argv) |
| 2505 | { |
| 2506 | if (argc == 0) { |
| 2507 | |
| 2508 | if (*scriptHandlerObj) { |
| 2509 | Jim_SetResult(interp, *scriptHandlerObj); |
| 2510 | } |
| 2511 | return JIM_OK; |
| 2512 | } |
| 2513 | |
| 2514 | if (*scriptHandlerObj) { |
| 2515 | |
| 2516 | Jim_DeleteFileHandler(interp, af->fd, mask); |
| 2517 | } |
| 2518 | |
| 2519 | |
| 2520 | if (Jim_Length(argv[0]) == 0) { |
| 2521 | |
| 2522 | return JIM_OK; |
| 2523 | } |
| 2524 | |
| 2525 | |
| 2526 | Jim_IncrRefCount(argv[0]); |
| 2527 | *scriptHandlerObj = argv[0]; |
| 2528 | |
| 2529 | Jim_CreateFileHandler(interp, af->fd, mask, |
| 2530 | JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer); |
| 2531 | |
| 2532 | return JIM_OK; |
| 2533 | } |
| 2534 | |
| @@ -2414,136 +2552,145 @@ | |
| 2552 | |
| 2553 | return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); |
| 2554 | } |
| 2555 | #endif |
| 2556 | |
| 2557 | |
| 2558 | |
| 2559 | |
| 2560 | static const jim_subcmd_type aio_command_table[] = { |
| 2561 | { "read", |
| 2562 | "?-nonewline? ?len?", |
| 2563 | aio_cmd_read, |
| 2564 | 0, |
| 2565 | 2, |
| 2566 | |
| 2567 | }, |
| 2568 | { "copyto", |
| 2569 | "handle ?size?", |
| 2570 | aio_cmd_copy, |
| 2571 | 1, |
| 2572 | 2, |
| 2573 | |
| 2574 | }, |
| 2575 | { "getfd", |
| 2576 | NULL, |
| 2577 | aio_cmd_getfd, |
| 2578 | 0, |
| 2579 | 0, |
| 2580 | |
| 2581 | }, |
| 2582 | { "gets", |
| 2583 | "?var?", |
| 2584 | aio_cmd_gets, |
| 2585 | 0, |
| 2586 | 1, |
| 2587 | |
| 2588 | }, |
| 2589 | { "puts", |
| 2590 | "?-nonewline? str", |
| 2591 | aio_cmd_puts, |
| 2592 | 1, |
| 2593 | 2, |
| 2594 | |
| 2595 | }, |
| 2596 | { "isatty", |
| 2597 | NULL, |
| 2598 | aio_cmd_isatty, |
| 2599 | 0, |
| 2600 | 0, |
| 2601 | |
| 2602 | }, |
| 2603 | { "flush", |
| 2604 | NULL, |
| 2605 | aio_cmd_flush, |
| 2606 | 0, |
| 2607 | 0, |
| 2608 | |
| 2609 | }, |
| 2610 | { "eof", |
| 2611 | NULL, |
| 2612 | aio_cmd_eof, |
| 2613 | 0, |
| 2614 | 0, |
| 2615 | |
| 2616 | }, |
| 2617 | { "close", |
| 2618 | "?r(ead)|w(rite)?", |
| 2619 | aio_cmd_close, |
| 2620 | 0, |
| 2621 | 1, |
| 2622 | JIM_MODFLAG_FULLARGV, |
| 2623 | |
| 2624 | }, |
| 2625 | { "seek", |
| 2626 | "offset ?start|current|end", |
| 2627 | aio_cmd_seek, |
| 2628 | 1, |
| 2629 | 2, |
| 2630 | |
| 2631 | }, |
| 2632 | { "tell", |
| 2633 | NULL, |
| 2634 | aio_cmd_tell, |
| 2635 | 0, |
| 2636 | 0, |
| 2637 | |
| 2638 | }, |
| 2639 | { "filename", |
| 2640 | NULL, |
| 2641 | aio_cmd_filename, |
| 2642 | 0, |
| 2643 | 0, |
| 2644 | |
| 2645 | }, |
| 2646 | #ifdef O_NDELAY |
| 2647 | { "ndelay", |
| 2648 | "?0|1?", |
| 2649 | aio_cmd_ndelay, |
| 2650 | 0, |
| 2651 | 1, |
| 2652 | |
| 2653 | }, |
| 2654 | #endif |
| 2655 | #ifdef HAVE_FSYNC |
| 2656 | { "sync", |
| 2657 | NULL, |
| 2658 | aio_cmd_sync, |
| 2659 | 0, |
| 2660 | 0, |
| 2661 | |
| 2662 | }, |
| 2663 | #endif |
| 2664 | { "buffering", |
| 2665 | "none|line|full", |
| 2666 | aio_cmd_buffering, |
| 2667 | 1, |
| 2668 | 1, |
| 2669 | |
| 2670 | }, |
| 2671 | #ifdef jim_ext_eventloop |
| 2672 | { "readable", |
| 2673 | "?readable-script?", |
| 2674 | aio_cmd_readable, |
| 2675 | 0, |
| 2676 | 1, |
| 2677 | |
| 2678 | }, |
| 2679 | { "writable", |
| 2680 | "?writable-script?", |
| 2681 | aio_cmd_writable, |
| 2682 | 0, |
| 2683 | 1, |
| 2684 | |
| 2685 | }, |
| 2686 | { "onexception", |
| 2687 | "?exception-script?", |
| 2688 | aio_cmd_onexception, |
| 2689 | 0, |
| 2690 | 1, |
| 2691 | |
| 2692 | }, |
| 2693 | #endif |
| 2694 | { NULL } |
| 2695 | }; |
| 2696 | |
| @@ -2566,11 +2713,11 @@ | |
| 2713 | |
| 2714 | #ifdef jim_ext_tclcompat |
| 2715 | { |
| 2716 | const char *filename = Jim_String(argv[1]); |
| 2717 | |
| 2718 | |
| 2719 | if (*filename == '|') { |
| 2720 | Jim_Obj *evalObj[3]; |
| 2721 | |
| 2722 | evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); |
| 2723 | evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); |
| @@ -2603,35 +2750,37 @@ | |
| 2750 | } |
| 2751 | |
| 2752 | Jim_IncrRefCount(filename); |
| 2753 | |
| 2754 | if (fh == NULL) { |
| 2755 | if (fd >= 0) { |
| 2756 | #ifndef JIM_ANSIC |
| 2757 | fh = fdopen(fd, mode); |
| 2758 | #endif |
| 2759 | } |
| 2760 | else |
| 2761 | fh = fopen(Jim_String(filename), mode); |
| 2762 | |
| 2763 | if (fh == NULL) { |
| 2764 | JimAioSetError(interp, filename); |
| 2765 | #ifndef JIM_ANSIC |
| 2766 | if (fd >= 0) { |
| 2767 | close(fd); |
| 2768 | } |
| 2769 | #endif |
| 2770 | Jim_DecrRefCount(interp, filename); |
| 2771 | return NULL; |
| 2772 | } |
| 2773 | } |
| 2774 | |
| 2775 | |
| 2776 | af = Jim_Alloc(sizeof(*af)); |
| 2777 | memset(af, 0, sizeof(*af)); |
| 2778 | af->fp = fh; |
| 2779 | #ifndef JIM_ANSIC |
| 2780 | af->fd = fileno(fh); |
| 2781 | #endif |
| 2782 | af->filename = filename; |
| 2783 | #ifdef FD_CLOEXEC |
| 2784 | if ((openFlags & AIO_KEEPOPEN) == 0) { |
| 2785 | (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); |
| 2786 | } |
| @@ -2653,72 +2802,45 @@ | |
| 2802 | const char *hdlfmt, int family, const char *mode[2]) |
| 2803 | { |
| 2804 | if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) { |
| 2805 | Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); |
| 2806 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2807 | if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) { |
| 2808 | Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); |
| 2809 | Jim_SetResult(interp, objPtr); |
| 2810 | return JIM_OK; |
| 2811 | } |
| 2812 | } |
| 2813 | |
| 2814 | |
| 2815 | close(p[0]); |
| 2816 | close(p[1]); |
| 2817 | JimAioSetError(interp, NULL); |
| 2818 | return JIM_ERR; |
| 2819 | } |
| 2820 | #endif |
| 2821 | |
| 2822 | #ifdef HAVE_PIPE |
| 2823 | static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 2824 | { |
| 2825 | int p[2]; |
| 2826 | static const char *mode[2] = { "r", "w" }; |
| 2827 | |
| 2828 | if (argc != 1) { |
| 2829 | Jim_WrongNumArgs(interp, 1, argv, ""); |
| 2830 | return JIM_ERR; |
| 2831 | } |
| 2832 | |
| 2833 | if (pipe(p) != 0) { |
| 2834 | JimAioSetError(interp, NULL); |
| 2835 | return JIM_ERR; |
| 2836 | } |
| 2837 | |
| 2838 | return JimMakeChannelPair(interp, p, argv[0], "aio.pipe%ld", 0, mode); |
| 2839 | } |
| 2840 | #endif |
| 2841 | |
| 2842 | |
| 2843 | |
| 2844 | int Jim_aioInit(Jim_Interp *interp) |
| 2845 | { |
| 2846 | if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG)) |
| @@ -2727,15 +2849,18 @@ | |
| 2849 | #if defined(JIM_SSL) |
| 2850 | Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL); |
| 2851 | #endif |
| 2852 | |
| 2853 | Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); |
| 2854 | #ifdef HAVE_SOCKETS |
| 2855 | Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL); |
| 2856 | #endif |
| 2857 | #ifdef HAVE_PIPE |
| 2858 | Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL); |
| 2859 | #endif |
| 2860 | |
| 2861 | |
| 2862 | JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r"); |
| 2863 | JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); |
| 2864 | JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); |
| 2865 | |
| 2866 | return JIM_OK; |
| @@ -2813,12 +2938,12 @@ | |
| 2938 | #include <regex.h> |
| 2939 | #endif |
| 2940 | |
| 2941 | static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 2942 | { |
| 2943 | regfree(objPtr->internalRep.ptrIntValue.ptr); |
| 2944 | Jim_Free(objPtr->internalRep.ptrIntValue.ptr); |
| 2945 | } |
| 2946 | |
| 2947 | static const Jim_ObjType regexpObjType = { |
| 2948 | "regexp", |
| 2949 | FreeRegexpInternalRep, |
| @@ -2831,20 +2956,20 @@ | |
| 2956 | { |
| 2957 | regex_t *compre; |
| 2958 | const char *pattern; |
| 2959 | int ret; |
| 2960 | |
| 2961 | |
| 2962 | if (objPtr->typePtr == ®expObjType && |
| 2963 | objPtr->internalRep.ptrIntValue.ptr && objPtr->internalRep.ptrIntValue.int1 == flags) { |
| 2964 | |
| 2965 | return objPtr->internalRep.ptrIntValue.ptr; |
| 2966 | } |
| 2967 | |
| 2968 | |
| 2969 | |
| 2970 | |
| 2971 | pattern = Jim_String(objPtr); |
| 2972 | compre = Jim_Alloc(sizeof(regex_t)); |
| 2973 | |
| 2974 | if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { |
| 2975 | char buf[100]; |
| @@ -2857,12 +2982,12 @@ | |
| 2982 | } |
| 2983 | |
| 2984 | Jim_FreeIntRep(interp, objPtr); |
| 2985 | |
| 2986 | objPtr->typePtr = ®expObjType; |
| 2987 | objPtr->internalRep.ptrIntValue.int1 = flags; |
| 2988 | objPtr->internalRep.ptrIntValue.ptr = compre; |
| 2989 | |
| 2990 | return compre; |
| 2991 | } |
| 2992 | |
| 2993 | int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -3001,11 +3126,11 @@ | |
| 3126 | } |
| 3127 | |
| 3128 | num_matches++; |
| 3129 | |
| 3130 | if (opt_all && !opt_inline) { |
| 3131 | |
| 3132 | goto try_next_match; |
| 3133 | } |
| 3134 | |
| 3135 | |
| 3136 | j = 0; |
| @@ -3041,11 +3166,11 @@ | |
| 3166 | |
| 3167 | if (opt_inline) { |
| 3168 | Jim_ListAppendElement(interp, resultListObj, resultObj); |
| 3169 | } |
| 3170 | else { |
| 3171 | |
| 3172 | result = Jim_SetVariable(interp, argv[i], resultObj); |
| 3173 | |
| 3174 | if (result != JIM_OK) { |
| 3175 | Jim_FreeObj(interp, resultObj); |
| 3176 | break; |
| @@ -3168,11 +3293,11 @@ | |
| 3293 | |
| 3294 | source_str = Jim_GetString(argv[i + 1], &source_len); |
| 3295 | replace_str = Jim_GetString(argv[i + 2], &replace_len); |
| 3296 | varname = argv[i + 3]; |
| 3297 | |
| 3298 | |
| 3299 | resultObj = Jim_NewStringObj(interp, "", 0); |
| 3300 | |
| 3301 | if (offset) { |
| 3302 | if (offset < 0) { |
| 3303 | offset += source_len + 1; |
| @@ -3183,11 +3308,11 @@ | |
| 3308 | else if (offset < 0) { |
| 3309 | offset = 0; |
| 3310 | } |
| 3311 | } |
| 3312 | |
| 3313 | |
| 3314 | Jim_AppendString(interp, resultObj, source_str, offset); |
| 3315 | |
| 3316 | |
| 3317 | n = source_len - offset; |
| 3318 | p = source_str + offset; |
| @@ -3242,23 +3367,23 @@ | |
| 3367 | } |
| 3368 | |
| 3369 | p += pmatch[0].rm_eo; |
| 3370 | n -= pmatch[0].rm_eo; |
| 3371 | |
| 3372 | |
| 3373 | if (!opt_all || n == 0) { |
| 3374 | break; |
| 3375 | } |
| 3376 | |
| 3377 | |
| 3378 | if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') { |
| 3379 | break; |
| 3380 | } |
| 3381 | |
| 3382 | |
| 3383 | if (pattern[0] == '\0' && n) { |
| 3384 | |
| 3385 | Jim_AppendString(interp, resultObj, p, 1); |
| 3386 | p++; |
| 3387 | n--; |
| 3388 | } |
| 3389 | |
| @@ -3265,11 +3390,11 @@ | |
| 3390 | regexec_flags |= REG_NOTBOL; |
| 3391 | } while (n); |
| 3392 | |
| 3393 | Jim_AppendString(interp, resultObj, p, -1); |
| 3394 | |
| 3395 | |
| 3396 | if (argc - i == 4) { |
| 3397 | result = Jim_SetVariable(interp, varname, resultObj); |
| 3398 | |
| 3399 | if (result == JIM_OK) { |
| 3400 | Jim_SetResultInt(interp, num_matches); |
| @@ -3320,11 +3445,11 @@ | |
| 3445 | |
| 3446 | # ifndef MAXPATHLEN |
| 3447 | # define MAXPATHLEN JIM_PATH_LEN |
| 3448 | # endif |
| 3449 | |
| 3450 | #if defined(__MINGW32__) || defined(__MSYS__) || defined(_MSC_VER) |
| 3451 | #define ISWINDOWS 1 |
| 3452 | #else |
| 3453 | #define ISWINDOWS 0 |
| 3454 | #endif |
| 3455 | |
| @@ -3371,11 +3496,11 @@ | |
| 3496 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); |
| 3497 | } |
| 3498 | |
| 3499 | static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) |
| 3500 | { |
| 3501 | |
| 3502 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 3503 | |
| 3504 | AppendStatElement(interp, listObj, "dev", sb->st_dev); |
| 3505 | AppendStatElement(interp, listObj, "ino", sb->st_ino); |
| 3506 | AppendStatElement(interp, listObj, "mode", sb->st_mode); |
| @@ -3387,36 +3512,38 @@ | |
| 3512 | AppendStatElement(interp, listObj, "mtime", sb->st_mtime); |
| 3513 | AppendStatElement(interp, listObj, "ctime", sb->st_ctime); |
| 3514 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); |
| 3515 | Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); |
| 3516 | |
| 3517 | |
| 3518 | if (varName) { |
| 3519 | Jim_Obj *objPtr; |
| 3520 | objPtr = Jim_GetVariable(interp, varName, JIM_NONE); |
| 3521 | |
| 3522 | if (objPtr) { |
| 3523 | Jim_Obj *objv[2]; |
| 3524 | |
| 3525 | objv[0] = objPtr; |
| 3526 | objv[1] = listObj; |
| 3527 | |
| 3528 | objPtr = Jim_DictMerge(interp, 2, objv); |
| 3529 | if (objPtr == NULL) { |
| 3530 | |
| 3531 | Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); |
| 3532 | Jim_FreeNewObj(interp, listObj); |
| 3533 | return JIM_ERR; |
| 3534 | } |
| 3535 | |
| 3536 | Jim_InvalidateStringRep(objPtr); |
| 3537 | |
| 3538 | Jim_FreeNewObj(interp, listObj); |
| 3539 | listObj = objPtr; |
| 3540 | } |
| 3541 | Jim_SetVariable(interp, varName, listObj); |
| 3542 | } |
| 3543 | |
| 3544 | |
| 3545 | Jim_SetResult(interp, listObj); |
| 3546 | |
| 3547 | return JIM_OK; |
| 3548 | } |
| 3549 | |
| @@ -3432,11 +3559,11 @@ | |
| 3559 | } |
| 3560 | else if (p == path) { |
| 3561 | Jim_SetResultString(interp, "/", -1); |
| 3562 | } |
| 3563 | else if (ISWINDOWS && p[-1] == ':') { |
| 3564 | |
| 3565 | Jim_SetResultString(interp, path, p - path + 1); |
| 3566 | } |
| 3567 | else { |
| 3568 | Jim_SetResultString(interp, path, p - path); |
| 3569 | } |
| @@ -3512,35 +3639,35 @@ | |
| 3639 | char *newname = Jim_Alloc(MAXPATHLEN + 1); |
| 3640 | char *last = newname; |
| 3641 | |
| 3642 | *newname = 0; |
| 3643 | |
| 3644 | |
| 3645 | for (i = 0; i < argc; i++) { |
| 3646 | int len; |
| 3647 | const char *part = Jim_GetString(argv[i], &len); |
| 3648 | |
| 3649 | if (*part == '/') { |
| 3650 | |
| 3651 | last = newname; |
| 3652 | } |
| 3653 | else if (ISWINDOWS && strchr(part, ':')) { |
| 3654 | |
| 3655 | last = newname; |
| 3656 | } |
| 3657 | else if (part[0] == '.') { |
| 3658 | if (part[1] == '/') { |
| 3659 | part += 2; |
| 3660 | len -= 2; |
| 3661 | } |
| 3662 | else if (part[1] == 0 && last != newname) { |
| 3663 | |
| 3664 | continue; |
| 3665 | } |
| 3666 | } |
| 3667 | |
| 3668 | |
| 3669 | if (last != newname && last[-1] != '/') { |
| 3670 | *last++ = '/'; |
| 3671 | } |
| 3672 | |
| 3673 | if (len) { |
| @@ -3551,22 +3678,22 @@ | |
| 3678 | } |
| 3679 | memcpy(last, part, len); |
| 3680 | last += len; |
| 3681 | } |
| 3682 | |
| 3683 | |
| 3684 | if (last > newname + 1 && last[-1] == '/') { |
| 3685 | |
| 3686 | if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) { |
| 3687 | *--last = 0; |
| 3688 | } |
| 3689 | } |
| 3690 | } |
| 3691 | |
| 3692 | *last = 0; |
| 3693 | |
| 3694 | |
| 3695 | |
| 3696 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname)); |
| 3697 | |
| 3698 | return JIM_OK; |
| 3699 | } |
| @@ -3591,11 +3718,11 @@ | |
| 3718 | static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3719 | { |
| 3720 | #ifdef X_OK |
| 3721 | return file_access(interp, argv[0], X_OK); |
| 3722 | #else |
| 3723 | |
| 3724 | Jim_SetResultBool(interp, 1); |
| 3725 | return JIM_OK; |
| 3726 | #endif |
| 3727 | } |
| 3728 | |
| @@ -3616,11 +3743,11 @@ | |
| 3743 | while (argc--) { |
| 3744 | const char *path = Jim_String(argv[0]); |
| 3745 | |
| 3746 | if (unlink(path) == -1 && errno != ENOENT) { |
| 3747 | if (rmdir(path) == -1) { |
| 3748 | |
| 3749 | if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) { |
| 3750 | Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path, |
| 3751 | strerror(errno)); |
| 3752 | return JIM_ERR; |
| 3753 | } |
| @@ -3639,15 +3766,15 @@ | |
| 3766 | |
| 3767 | static int mkdir_all(char *path) |
| 3768 | { |
| 3769 | int ok = 1; |
| 3770 | |
| 3771 | |
| 3772 | goto first; |
| 3773 | |
| 3774 | while (ok--) { |
| 3775 | |
| 3776 | { |
| 3777 | char *slash = strrchr(path, '/'); |
| 3778 | |
| 3779 | if (slash && slash != path) { |
| 3780 | *slash = 0; |
| @@ -3660,24 +3787,24 @@ | |
| 3787 | first: |
| 3788 | if (MKDIR_DEFAULT(path) == 0) { |
| 3789 | return 0; |
| 3790 | } |
| 3791 | if (errno == ENOENT) { |
| 3792 | |
| 3793 | continue; |
| 3794 | } |
| 3795 | |
| 3796 | if (errno == EEXIST) { |
| 3797 | struct stat sb; |
| 3798 | |
| 3799 | if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { |
| 3800 | return 0; |
| 3801 | } |
| 3802 | |
| 3803 | errno = EEXIST; |
| 3804 | } |
| 3805 | |
| 3806 | break; |
| 3807 | } |
| 3808 | return -1; |
| 3809 | } |
| 3810 | |
| @@ -3698,11 +3825,11 @@ | |
| 3825 | return JIM_OK; |
| 3826 | } |
| 3827 | |
| 3828 | static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 3829 | { |
| 3830 | int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL, 0); |
| 3831 | |
| 3832 | if (fd < 0) { |
| 3833 | return JIM_ERR; |
| 3834 | } |
| 3835 | close(fd); |
| @@ -3962,192 +4089,192 @@ | |
| 4089 | { "atime", |
| 4090 | "name", |
| 4091 | file_cmd_atime, |
| 4092 | 1, |
| 4093 | 1, |
| 4094 | |
| 4095 | }, |
| 4096 | { "mtime", |
| 4097 | "name ?time?", |
| 4098 | file_cmd_mtime, |
| 4099 | 1, |
| 4100 | 2, |
| 4101 | |
| 4102 | }, |
| 4103 | { "copy", |
| 4104 | "?-force? source dest", |
| 4105 | file_cmd_copy, |
| 4106 | 2, |
| 4107 | 3, |
| 4108 | |
| 4109 | }, |
| 4110 | { "dirname", |
| 4111 | "name", |
| 4112 | file_cmd_dirname, |
| 4113 | 1, |
| 4114 | 1, |
| 4115 | |
| 4116 | }, |
| 4117 | { "rootname", |
| 4118 | "name", |
| 4119 | file_cmd_rootname, |
| 4120 | 1, |
| 4121 | 1, |
| 4122 | |
| 4123 | }, |
| 4124 | { "extension", |
| 4125 | "name", |
| 4126 | file_cmd_extension, |
| 4127 | 1, |
| 4128 | 1, |
| 4129 | |
| 4130 | }, |
| 4131 | { "tail", |
| 4132 | "name", |
| 4133 | file_cmd_tail, |
| 4134 | 1, |
| 4135 | 1, |
| 4136 | |
| 4137 | }, |
| 4138 | { "normalize", |
| 4139 | "name", |
| 4140 | file_cmd_normalize, |
| 4141 | 1, |
| 4142 | 1, |
| 4143 | |
| 4144 | }, |
| 4145 | { "join", |
| 4146 | "name ?name ...?", |
| 4147 | file_cmd_join, |
| 4148 | 1, |
| 4149 | -1, |
| 4150 | |
| 4151 | }, |
| 4152 | { "readable", |
| 4153 | "name", |
| 4154 | file_cmd_readable, |
| 4155 | 1, |
| 4156 | 1, |
| 4157 | |
| 4158 | }, |
| 4159 | { "writable", |
| 4160 | "name", |
| 4161 | file_cmd_writable, |
| 4162 | 1, |
| 4163 | 1, |
| 4164 | |
| 4165 | }, |
| 4166 | { "executable", |
| 4167 | "name", |
| 4168 | file_cmd_executable, |
| 4169 | 1, |
| 4170 | 1, |
| 4171 | |
| 4172 | }, |
| 4173 | { "exists", |
| 4174 | "name", |
| 4175 | file_cmd_exists, |
| 4176 | 1, |
| 4177 | 1, |
| 4178 | |
| 4179 | }, |
| 4180 | { "delete", |
| 4181 | "?-force|--? name ...", |
| 4182 | file_cmd_delete, |
| 4183 | 1, |
| 4184 | -1, |
| 4185 | |
| 4186 | }, |
| 4187 | { "mkdir", |
| 4188 | "dir ...", |
| 4189 | file_cmd_mkdir, |
| 4190 | 1, |
| 4191 | -1, |
| 4192 | |
| 4193 | }, |
| 4194 | { "tempfile", |
| 4195 | "?template?", |
| 4196 | file_cmd_tempfile, |
| 4197 | 0, |
| 4198 | 1, |
| 4199 | |
| 4200 | }, |
| 4201 | { "rename", |
| 4202 | "?-force? source dest", |
| 4203 | file_cmd_rename, |
| 4204 | 2, |
| 4205 | 3, |
| 4206 | |
| 4207 | }, |
| 4208 | #if defined(HAVE_LINK) && defined(HAVE_SYMLINK) |
| 4209 | { "link", |
| 4210 | "?-symbolic|-hard? newname target", |
| 4211 | file_cmd_link, |
| 4212 | 2, |
| 4213 | 3, |
| 4214 | |
| 4215 | }, |
| 4216 | #endif |
| 4217 | #if defined(HAVE_READLINK) |
| 4218 | { "readlink", |
| 4219 | "name", |
| 4220 | file_cmd_readlink, |
| 4221 | 1, |
| 4222 | 1, |
| 4223 | |
| 4224 | }, |
| 4225 | #endif |
| 4226 | { "size", |
| 4227 | "name", |
| 4228 | file_cmd_size, |
| 4229 | 1, |
| 4230 | 1, |
| 4231 | |
| 4232 | }, |
| 4233 | { "stat", |
| 4234 | "name ?var?", |
| 4235 | file_cmd_stat, |
| 4236 | 1, |
| 4237 | 2, |
| 4238 | |
| 4239 | }, |
| 4240 | { "lstat", |
| 4241 | "name ?var?", |
| 4242 | file_cmd_lstat, |
| 4243 | 1, |
| 4244 | 2, |
| 4245 | |
| 4246 | }, |
| 4247 | { "type", |
| 4248 | "name", |
| 4249 | file_cmd_type, |
| 4250 | 1, |
| 4251 | 1, |
| 4252 | |
| 4253 | }, |
| 4254 | #ifdef HAVE_GETEUID |
| 4255 | { "owned", |
| 4256 | "name", |
| 4257 | file_cmd_owned, |
| 4258 | 1, |
| 4259 | 1, |
| 4260 | |
| 4261 | }, |
| 4262 | #endif |
| 4263 | { "isdirectory", |
| 4264 | "name", |
| 4265 | file_cmd_isdirectory, |
| 4266 | 1, |
| 4267 | 1, |
| 4268 | |
| 4269 | }, |
| 4270 | { "isfile", |
| 4271 | "name", |
| 4272 | file_cmd_isfile, |
| 4273 | 1, |
| 4274 | 1, |
| 4275 | |
| 4276 | }, |
| 4277 | { |
| 4278 | NULL |
| 4279 | } |
| 4280 | }; |
| @@ -4179,11 +4306,11 @@ | |
| 4306 | Jim_SetResultString(interp, "Failed to get pwd", -1); |
| 4307 | Jim_Free(cwd); |
| 4308 | return JIM_ERR; |
| 4309 | } |
| 4310 | else if (ISWINDOWS) { |
| 4311 | |
| 4312 | char *p = cwd; |
| 4313 | while ((p = strchr(p, '\\')) != NULL) { |
| 4314 | *p++ = '/'; |
| 4315 | } |
| 4316 | } |
| @@ -4203,10 +4330,13 @@ | |
| 4330 | Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL); |
| 4331 | Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL); |
| 4332 | return JIM_OK; |
| 4333 | } |
| 4334 | |
| 4335 | #ifndef _GNU_SOURCE |
| 4336 | #define _GNU_SOURCE |
| 4337 | #endif |
| 4338 | #include <string.h> |
| 4339 | #include <ctype.h> |
| 4340 | |
| 4341 | |
| 4342 | #if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) |
| @@ -4214,20 +4344,20 @@ | |
| 4344 | { |
| 4345 | Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp); |
| 4346 | int i, j; |
| 4347 | int rc; |
| 4348 | |
| 4349 | |
| 4350 | for (i = 1; i < argc; i++) { |
| 4351 | int len; |
| 4352 | const char *arg = Jim_GetString(argv[i], &len); |
| 4353 | |
| 4354 | if (i > 1) { |
| 4355 | Jim_AppendString(interp, cmdlineObj, " ", 1); |
| 4356 | } |
| 4357 | if (strpbrk(arg, "\\\" ") == NULL) { |
| 4358 | |
| 4359 | Jim_AppendString(interp, cmdlineObj, arg, len); |
| 4360 | continue; |
| 4361 | } |
| 4362 | |
| 4363 | Jim_AppendString(interp, cmdlineObj, "\"", 1); |
| @@ -4266,86 +4396,26 @@ | |
| 4396 | #else |
| 4397 | |
| 4398 | |
| 4399 | #include <errno.h> |
| 4400 | #include <signal.h> |
| 4401 | #include <sys/stat.h> |
| 4402 | |
| 4403 | struct WaitInfoTable; |
| 4404 | |
| 4405 | static char **JimOriginalEnviron(void); |
| 4406 | static char **JimSaveEnv(char **env); |
| 4407 | static void JimRestoreEnv(char **env); |
| 4408 | static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, |
| 4409 | pidtype **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr); |
| 4410 | static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr); |
| 4411 | static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj); |
| 4412 | static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv); |
| 4413 | |
| 4414 | #if defined(__MINGW32__) |
| 4415 | static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId); |
| 4416 | #endif |
| 4417 | |
| 4418 | static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) |
| 4419 | { |
| 4420 | int len; |
| 4421 | const char *s = Jim_GetString(objPtr, &len); |
| @@ -4354,14 +4424,14 @@ | |
| 4424 | objPtr->length--; |
| 4425 | objPtr->bytes[objPtr->length] = '\0'; |
| 4426 | } |
| 4427 | } |
| 4428 | |
| 4429 | static int JimAppendStreamToString(Jim_Interp *interp, int fd, Jim_Obj *strObj) |
| 4430 | { |
| 4431 | char buf[256]; |
| 4432 | FILE *fh = fdopen(fd, "r"); |
| 4433 | int ret = 0; |
| 4434 | |
| 4435 | if (fh == NULL) { |
| 4436 | return -1; |
| 4437 | } |
| @@ -4390,18 +4460,18 @@ | |
| 4460 | char *envdata; |
| 4461 | |
| 4462 | Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE); |
| 4463 | |
| 4464 | if (!objPtr) { |
| 4465 | return JimOriginalEnviron(); |
| 4466 | } |
| 4467 | |
| 4468 | |
| 4469 | |
| 4470 | num = Jim_ListLength(interp, objPtr); |
| 4471 | if (num % 2) { |
| 4472 | |
| 4473 | num--; |
| 4474 | } |
| 4475 | size = Jim_Length(objPtr) + 2; |
| 4476 | |
| 4477 | envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); |
| @@ -4433,79 +4503,76 @@ | |
| 4503 | if (env != original_environ) { |
| 4504 | Jim_Free(env); |
| 4505 | } |
| 4506 | } |
| 4507 | |
| 4508 | static Jim_Obj *JimMakeErrorCode(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) |
| 4509 | { |
| 4510 | Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); |
| 4511 | |
| 4512 | if (pid == JIM_BAD_PID || pid == JIM_NO_PID) { |
| 4513 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1)); |
| 4514 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 4515 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, -1)); |
| 4516 | } |
| 4517 | else if (WIFEXITED(waitStatus)) { |
| 4518 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); |
| 4519 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 4520 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); |
| 4521 | } |
| 4522 | else { |
| 4523 | const char *type; |
| 4524 | const char *action; |
| 4525 | const char *signame; |
| 4526 | |
| 4527 | if (WIFSIGNALED(waitStatus)) { |
| 4528 | type = "CHILDKILLED"; |
| 4529 | action = "killed"; |
| 4530 | signame = Jim_SignalId(WTERMSIG(waitStatus)); |
| 4531 | } |
| 4532 | else { |
| 4533 | type = "CHILDSUSP"; |
| 4534 | action = "suspended"; |
| 4535 | signame = "none"; |
| 4536 | } |
| 4537 | |
| 4538 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1)); |
| 4539 | |
| 4540 | if (errStrObj) { |
| 4541 | Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL); |
| 4542 | } |
| 4543 | |
| 4544 | Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); |
| 4545 | Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, signame, -1)); |
| 4546 | } |
| 4547 | return errorCode; |
| 4548 | } |
| 4549 | |
| 4550 | static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj) |
| 4551 | { |
| 4552 | if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) { |
| 4553 | return JIM_OK; |
| 4554 | } |
| 4555 | Jim_SetGlobalVariableStr(interp, "errorCode", JimMakeErrorCode(interp, pid, waitStatus, errStrObj)); |
| 4556 | |
| 4557 | return JIM_ERR; |
| 4558 | } |
| 4559 | |
| 4560 | |
| 4561 | struct WaitInfo |
| 4562 | { |
| 4563 | pidtype pid; |
| 4564 | int status; |
| 4565 | int flags; |
| 4566 | }; |
| 4567 | |
| 4568 | |
| 4569 | struct WaitInfoTable { |
| 4570 | struct WaitInfo *info; |
| 4571 | int size; |
| 4572 | int used; |
| 4573 | int refcount; |
| 4574 | }; |
| 4575 | |
| 4576 | |
| 4577 | #define WI_DETACHED 2 |
| 4578 | |
| @@ -4513,32 +4580,53 @@ | |
| 4580 | |
| 4581 | static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData) |
| 4582 | { |
| 4583 | struct WaitInfoTable *table = privData; |
| 4584 | |
| 4585 | if (--table->refcount == 0) { |
| 4586 | Jim_Free(table->info); |
| 4587 | Jim_Free(table); |
| 4588 | } |
| 4589 | } |
| 4590 | |
| 4591 | static struct WaitInfoTable *JimAllocWaitInfoTable(void) |
| 4592 | { |
| 4593 | struct WaitInfoTable *table = Jim_Alloc(sizeof(*table)); |
| 4594 | table->info = NULL; |
| 4595 | table->size = table->used = 0; |
| 4596 | table->refcount = 1; |
| 4597 | |
| 4598 | return table; |
| 4599 | } |
| 4600 | |
| 4601 | static int JimWaitRemove(struct WaitInfoTable *table, pidtype pid) |
| 4602 | { |
| 4603 | int i; |
| 4604 | |
| 4605 | |
| 4606 | for (i = 0; i < table->used; i++) { |
| 4607 | if (pid == table->info[i].pid) { |
| 4608 | if (i != table->used - 1) { |
| 4609 | table->info[i] = table->info[table->used - 1]; |
| 4610 | } |
| 4611 | table->used--; |
| 4612 | return 0; |
| 4613 | } |
| 4614 | } |
| 4615 | return -1; |
| 4616 | } |
| 4617 | |
| 4618 | static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4619 | { |
| 4620 | int outputId; |
| 4621 | int errorId; |
| 4622 | pidtype *pidPtr; |
| 4623 | int numPids, result; |
| 4624 | int child_siginfo = 1; |
| 4625 | Jim_Obj *childErrObj; |
| 4626 | Jim_Obj *errStrObj; |
| 4627 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4628 | |
| 4629 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { |
| 4630 | Jim_Obj *listObj; |
| 4631 | int i; |
| 4632 | |
| @@ -4545,17 +4633,17 @@ | |
| 4633 | argc--; |
| 4634 | numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); |
| 4635 | if (numPids < 0) { |
| 4636 | return JIM_ERR; |
| 4637 | } |
| 4638 | |
| 4639 | listObj = Jim_NewListObj(interp, NULL, 0); |
| 4640 | for (i = 0; i < numPids; i++) { |
| 4641 | Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); |
| 4642 | } |
| 4643 | Jim_SetResult(interp, listObj); |
| 4644 | JimDetachPids(table, numPids, pidPtr); |
| 4645 | Jim_Free(pidPtr); |
| 4646 | return JIM_OK; |
| 4647 | } |
| 4648 | |
| 4649 | numPids = |
| @@ -4567,54 +4655,98 @@ | |
| 4655 | |
| 4656 | result = JIM_OK; |
| 4657 | |
| 4658 | errStrObj = Jim_NewStringObj(interp, "", 0); |
| 4659 | |
| 4660 | |
| 4661 | if (outputId != -1) { |
| 4662 | if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) { |
| 4663 | result = JIM_ERR; |
| 4664 | Jim_SetResultErrno(interp, "error reading from output pipe"); |
| 4665 | } |
| 4666 | } |
| 4667 | |
| 4668 | |
| 4669 | childErrObj = Jim_NewStringObj(interp, "", 0); |
| 4670 | Jim_IncrRefCount(childErrObj); |
| 4671 | |
| 4672 | if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) { |
| 4673 | result = JIM_ERR; |
| 4674 | } |
| 4675 | |
| 4676 | if (errorId != -1) { |
| 4677 | int ret; |
| 4678 | lseek(errorId, 0, SEEK_SET); |
| 4679 | ret = JimAppendStreamToString(interp, errorId, errStrObj); |
| 4680 | if (ret < 0) { |
| 4681 | Jim_SetResultErrno(interp, "error reading from error pipe"); |
| 4682 | result = JIM_ERR; |
| 4683 | } |
| 4684 | else if (ret > 0) { |
| 4685 | |
| 4686 | child_siginfo = 0; |
| 4687 | } |
| 4688 | } |
| 4689 | |
| 4690 | if (child_siginfo) { |
| 4691 | |
| 4692 | Jim_AppendObj(interp, errStrObj, childErrObj); |
| 4693 | } |
| 4694 | Jim_DecrRefCount(interp, childErrObj); |
| 4695 | |
| 4696 | |
| 4697 | Jim_RemoveTrailingNewline(errStrObj); |
| 4698 | |
| 4699 | |
| 4700 | Jim_SetResult(interp, errStrObj); |
| 4701 | |
| 4702 | return result; |
| 4703 | } |
| 4704 | |
| 4705 | static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) |
| 4706 | { |
| 4707 | if (JimWaitRemove(table, pid) == 0) { |
| 4708 | |
| 4709 | waitpid(pid, statusPtr, 0); |
| 4710 | return pid; |
| 4711 | } |
| 4712 | |
| 4713 | |
| 4714 | return JIM_BAD_PID; |
| 4715 | } |
| 4716 | |
| 4717 | static void JimDetachPids(struct WaitInfoTable *table, int numPids, const pidtype *pidPtr) |
| 4718 | { |
| 4719 | int j; |
| 4720 | |
| 4721 | for (j = 0; j < numPids; j++) { |
| 4722 | |
| 4723 | int i; |
| 4724 | for (i = 0; i < table->used; i++) { |
| 4725 | if (pidPtr[j] == table->info[i].pid) { |
| 4726 | table->info[i].flags |= WI_DETACHED; |
| 4727 | break; |
| 4728 | } |
| 4729 | } |
| 4730 | } |
| 4731 | } |
| 4732 | |
| 4733 | static int JimGetChannelFd(Jim_Interp *interp, const char *name) |
| 4734 | { |
| 4735 | Jim_Obj *objv[2]; |
| 4736 | |
| 4737 | objv[0] = Jim_NewStringObj(interp, name, -1); |
| 4738 | objv[1] = Jim_NewStringObj(interp, "getfd", -1); |
| 4739 | |
| 4740 | if (Jim_EvalObjVector(interp, 2, objv) == JIM_OK) { |
| 4741 | jim_wide fd; |
| 4742 | if (Jim_GetWide(interp, Jim_GetResult(interp), &fd) == JIM_OK) { |
| 4743 | return fd; |
| 4744 | } |
| 4745 | } |
| 4746 | return -1; |
| 4747 | } |
| 4748 | |
| 4749 | static void JimReapDetachedPids(struct WaitInfoTable *table) |
| 4750 | { |
| 4751 | struct WaitInfo *waitPtr; |
| 4752 | int count; |
| @@ -4627,13 +4759,13 @@ | |
| 4759 | waitPtr = table->info; |
| 4760 | dest = 0; |
| 4761 | for (count = table->used; count > 0; waitPtr++, count--) { |
| 4762 | if (waitPtr->flags & WI_DETACHED) { |
| 4763 | int status; |
| 4764 | pidtype pid = waitpid(waitPtr->pid, &status, WNOHANG); |
| 4765 | if (pid == waitPtr->pid) { |
| 4766 | |
| 4767 | table->used--; |
| 4768 | continue; |
| 4769 | } |
| 4770 | } |
| 4771 | if (waitPtr != &table->info[dest]) { |
| @@ -4641,66 +4773,62 @@ | |
| 4773 | } |
| 4774 | dest++; |
| 4775 | } |
| 4776 | } |
| 4777 | |
| 4778 | static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4779 | { |
| 4780 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4781 | int nohang = 0; |
| 4782 | pidtype pid; |
| 4783 | long pidarg; |
| 4784 | int status; |
| 4785 | Jim_Obj *errCodeObj; |
| 4786 | |
| 4787 | |
| 4788 | if (argc == 1) { |
| 4789 | JimReapDetachedPids(table); |
| 4790 | return JIM_OK; |
| 4791 | } |
| 4792 | |
| 4793 | if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) { |
| 4794 | nohang = 1; |
| 4795 | } |
| 4796 | if (argc != nohang + 2) { |
| 4797 | Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?"); |
| 4798 | return JIM_ERR; |
| 4799 | } |
| 4800 | if (Jim_GetLong(interp, argv[nohang + 1], &pidarg) != JIM_OK) { |
| 4801 | return JIM_ERR; |
| 4802 | } |
| 4803 | |
| 4804 | pid = waitpid((pidtype)pidarg, &status, nohang ? WNOHANG : 0); |
| 4805 | |
| 4806 | errCodeObj = JimMakeErrorCode(interp, pid, status, NULL); |
| 4807 | |
| 4808 | if (pid != JIM_BAD_PID && (WIFEXITED(status) || WIFSIGNALED(status))) { |
| 4809 | |
| 4810 | JimWaitRemove(table, pid); |
| 4811 | } |
| 4812 | Jim_SetResult(interp, errCodeObj); |
| 4813 | return JIM_OK; |
| 4814 | } |
| 4815 | |
| 4816 | static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 4817 | { |
| 4818 | if (argc != 1) { |
| 4819 | Jim_WrongNumArgs(interp, 1, argv, ""); |
| 4820 | return JIM_ERR; |
| 4821 | } |
| 4822 | |
| 4823 | Jim_SetResultInt(interp, (jim_wide)getpid()); |
| 4824 | return JIM_OK; |
| 4825 | } |
| 4826 | |
| 4827 | static int |
| 4828 | JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, |
| 4829 | int *inPipePtr, int *outPipePtr, int *errFilePtr) |
| 4830 | { |
| 4831 | pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all |
| 4832 | * the pids of child processes. */ |
| 4833 | int numPids = 0; /* Actual number of processes that exist |
| 4834 | * at *pidPtr right now. */ |
| @@ -4707,16 +4835,16 @@ | |
| 4835 | int cmdCount; /* Count of number of distinct commands |
| 4836 | * found in argc/argv. */ |
| 4837 | const char *input = NULL; /* Describes input for pipeline, depending |
| 4838 | * on "inputFile". NULL means take input |
| 4839 | * from stdin/pipe. */ |
| 4840 | int input_len = 0; |
| 4841 | |
| 4842 | #define FILE_NAME 0 |
| 4843 | #define FILE_APPEND 1 |
| 4844 | #define FILE_HANDLE 2 |
| 4845 | #define FILE_TEXT 3 |
| 4846 | |
| 4847 | int inputFile = FILE_NAME; /* 1 means input is name of input file. |
| 4848 | * 2 means input is filehandle name. |
| 4849 | * 0 means input holds actual |
| 4850 | * text to be input to command. */ |
| @@ -4733,39 +4861,37 @@ | |
| 4861 | */ |
| 4862 | const char *output = NULL; /* Holds name of output file to pipe to, |
| 4863 | * or NULL if output goes to stdout/pipe. */ |
| 4864 | const char *error = NULL; /* Holds name of stderr file to pipe to, |
| 4865 | * or NULL if stderr goes to stderr/pipe. */ |
| 4866 | int inputId = -1; |
| 4867 | int outputId = -1; |
| 4868 | int errorId = -1; |
| 4869 | int lastOutputId = -1; |
| 4870 | int pipeIds[2]; |
| 4871 | int firstArg, lastArg; /* Indexes of first and last arguments in |
| 4872 | * current command. */ |
| 4873 | int lastBar; |
| 4874 | int i; |
| 4875 | pidtype pid; |
| 4876 | char **save_environ; |
| 4877 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 4878 | |
| 4879 | |
| 4880 | char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1)); |
| 4881 | int arg_count = 0; |
| 4882 | |
| 4883 | if (inPipePtr != NULL) { |
| 4884 | *inPipePtr = -1; |
| 4885 | } |
| 4886 | if (outPipePtr != NULL) { |
| 4887 | *outPipePtr = -1; |
| 4888 | } |
| 4889 | if (errFilePtr != NULL) { |
| 4890 | *errFilePtr = -1; |
| 4891 | } |
| 4892 | pipeIds[0] = pipeIds[1] = -1; |
| 4893 | |
| 4894 | cmdCount = 1; |
| 4895 | lastBar = -1; |
| 4896 | for (i = 0; i < argc; i++) { |
| 4897 | const char *arg = Jim_String(argv[i]); |
| @@ -4796,11 +4922,11 @@ | |
| 4922 | if (*output == '>') { |
| 4923 | outputFile = FILE_APPEND; |
| 4924 | output++; |
| 4925 | } |
| 4926 | if (*output == '&') { |
| 4927 | |
| 4928 | output++; |
| 4929 | dup_error = 1; |
| 4930 | } |
| 4931 | if (*output == '@') { |
| 4932 | outputFile = FILE_HANDLE; |
| @@ -4837,11 +4963,11 @@ | |
| 4963 | goto badargs; |
| 4964 | } |
| 4965 | lastBar = i; |
| 4966 | cmdCount++; |
| 4967 | } |
| 4968 | |
| 4969 | arg_array[arg_count++] = (char *)arg; |
| 4970 | continue; |
| 4971 | } |
| 4972 | |
| 4973 | if (i >= argc) { |
| @@ -4855,150 +4981,160 @@ | |
| 4981 | badargs: |
| 4982 | Jim_Free(arg_array); |
| 4983 | return -1; |
| 4984 | } |
| 4985 | |
| 4986 | |
| 4987 | save_environ = JimSaveEnv(JimBuildEnv(interp)); |
| 4988 | |
| 4989 | if (input != NULL) { |
| 4990 | if (inputFile == FILE_TEXT) { |
| 4991 | inputId = Jim_MakeTempFile(interp, NULL, 1); |
| 4992 | if (inputId == -1) { |
| 4993 | goto error; |
| 4994 | } |
| 4995 | if (write(inputId, input, input_len) != input_len) { |
| 4996 | Jim_SetResultErrno(interp, "couldn't write temp file"); |
| 4997 | close(inputId); |
| 4998 | goto error; |
| 4999 | } |
| 5000 | lseek(inputId, 0L, SEEK_SET); |
| 5001 | } |
| 5002 | else if (inputFile == FILE_HANDLE) { |
| 5003 | int fd = JimGetChannelFd(interp, input); |
| 5004 | |
| 5005 | if (fd < 0) { |
| 5006 | goto error; |
| 5007 | } |
| 5008 | inputId = dup(fd); |
| 5009 | } |
| 5010 | else { |
| 5011 | inputId = Jim_OpenForRead(input); |
| 5012 | if (inputId == -1) { |
| 5013 | Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, strerror(Jim_Errno())); |
| 5014 | goto error; |
| 5015 | } |
| 5016 | } |
| 5017 | } |
| 5018 | else if (inPipePtr != NULL) { |
| 5019 | if (pipe(pipeIds) != 0) { |
| 5020 | Jim_SetResultErrno(interp, "couldn't create input pipe for command"); |
| 5021 | goto error; |
| 5022 | } |
| 5023 | inputId = pipeIds[0]; |
| 5024 | *inPipePtr = pipeIds[1]; |
| 5025 | pipeIds[0] = pipeIds[1] = -1; |
| 5026 | } |
| 5027 | |
| 5028 | if (output != NULL) { |
| 5029 | if (outputFile == FILE_HANDLE) { |
| 5030 | int fd = JimGetChannelFd(interp, output); |
| 5031 | if (fd < 0) { |
| 5032 | goto error; |
| 5033 | } |
| 5034 | lastOutputId = dup(fd); |
| 5035 | } |
| 5036 | else { |
| 5037 | lastOutputId = Jim_OpenForWrite(output, outputFile == FILE_APPEND); |
| 5038 | if (lastOutputId == -1) { |
| 5039 | Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, strerror(Jim_Errno())); |
| 5040 | goto error; |
| 5041 | } |
| 5042 | } |
| 5043 | } |
| 5044 | else if (outPipePtr != NULL) { |
| 5045 | if (pipe(pipeIds) != 0) { |
| 5046 | Jim_SetResultErrno(interp, "couldn't create output pipe"); |
| 5047 | goto error; |
| 5048 | } |
| 5049 | lastOutputId = pipeIds[1]; |
| 5050 | *outPipePtr = pipeIds[0]; |
| 5051 | pipeIds[0] = pipeIds[1] = -1; |
| 5052 | } |
| 5053 | |
| 5054 | if (error != NULL) { |
| 5055 | if (errorFile == FILE_HANDLE) { |
| 5056 | if (strcmp(error, "1") == 0) { |
| 5057 | |
| 5058 | if (lastOutputId != -1) { |
| 5059 | errorId = dup(lastOutputId); |
| 5060 | } |
| 5061 | else { |
| 5062 | |
| 5063 | error = "stdout"; |
| 5064 | } |
| 5065 | } |
| 5066 | if (errorId == -1) { |
| 5067 | int fd = JimGetChannelFd(interp, error); |
| 5068 | if (fd < 0) { |
| 5069 | goto error; |
| 5070 | } |
| 5071 | errorId = dup(fd); |
| 5072 | } |
| 5073 | } |
| 5074 | else { |
| 5075 | errorId = Jim_OpenForWrite(error, errorFile == FILE_APPEND); |
| 5076 | if (errorId == -1) { |
| 5077 | Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, strerror(Jim_Errno())); |
| 5078 | goto error; |
| 5079 | } |
| 5080 | } |
| 5081 | } |
| 5082 | else if (errFilePtr != NULL) { |
| 5083 | errorId = Jim_MakeTempFile(interp, NULL, 1); |
| 5084 | if (errorId == -1) { |
| 5085 | goto error; |
| 5086 | } |
| 5087 | *errFilePtr = dup(errorId); |
| 5088 | } |
| 5089 | |
| 5090 | |
| 5091 | pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); |
| 5092 | for (i = 0; i < numPids; i++) { |
| 5093 | pidPtr[i] = JIM_BAD_PID; |
| 5094 | } |
| 5095 | for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { |
| 5096 | int pipe_dup_err = 0; |
| 5097 | int origErrorId = errorId; |
| 5098 | |
| 5099 | for (lastArg = firstArg; lastArg < arg_count; lastArg++) { |
| 5100 | if (strcmp(arg_array[lastArg], "|") == 0) { |
| 5101 | break; |
| 5102 | } |
| 5103 | if (strcmp(arg_array[lastArg], "|&") == 0) { |
| 5104 | pipe_dup_err = 1; |
| 5105 | break; |
| 5106 | } |
| 5107 | } |
| 5108 | |
| 5109 | if (lastArg == firstArg) { |
| 5110 | Jim_SetResultString(interp, "missing command to exec", -1); |
| 5111 | goto error; |
| 5112 | } |
| 5113 | |
| 5114 | |
| 5115 | arg_array[lastArg] = NULL; |
| 5116 | if (lastArg == arg_count) { |
| 5117 | outputId = lastOutputId; |
| 5118 | } |
| 5119 | else { |
| 5120 | if (pipe(pipeIds) != 0) { |
| 5121 | Jim_SetResultErrno(interp, "couldn't create pipe"); |
| 5122 | goto error; |
| 5123 | } |
| 5124 | outputId = pipeIds[1]; |
| 5125 | } |
| 5126 | |
| 5127 | |
| 5128 | if (pipe_dup_err) { |
| 5129 | errorId = outputId; |
| 5130 | } |
| 5131 | |
| 5132 | |
| 5133 | |
| 5134 | #ifdef __MINGW32__ |
| 5135 | pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId); |
| 5136 | if (pid == JIM_BAD_PID) { |
| 5137 | Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); |
| 5138 | goto error; |
| 5139 | } |
| 5140 | #else |
| @@ -5006,32 +5142,37 @@ | |
| 5142 | if (pid < 0) { |
| 5143 | Jim_SetResultErrno(interp, "couldn't fork child process"); |
| 5144 | goto error; |
| 5145 | } |
| 5146 | if (pid == 0) { |
| 5147 | |
| 5148 | if (inputId != -1) dup2(inputId, fileno(stdin)); |
| 5149 | if (outputId != -1) dup2(outputId, fileno(stdout)); |
| 5150 | if (errorId != -1) dup2(errorId, fileno(stderr)); |
| 5151 | |
| 5152 | for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { |
| 5153 | close(i); |
| 5154 | } |
| 5155 | |
| 5156 | |
| 5157 | (void)signal(SIGPIPE, SIG_DFL); |
| 5158 | |
| 5159 | execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); |
| 5160 | |
| 5161 | fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]); |
| 5162 | #ifdef JIM_MAINTAINER |
| 5163 | { |
| 5164 | |
| 5165 | static char *const false_argv[2] = {"false", NULL}; |
| 5166 | execvp(false_argv[0],false_argv); |
| 5167 | } |
| 5168 | #endif |
| 5169 | _exit(127); |
| 5170 | } |
| 5171 | #endif |
| 5172 | |
| 5173 | |
| 5174 | |
| 5175 | if (table->used == table->size) { |
| 5176 | table->size += WAIT_TABLE_GROW_BY; |
| 5177 | table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info)); |
| 5178 | } |
| @@ -5040,66 +5181,67 @@ | |
| 5181 | table->info[table->used].flags = 0; |
| 5182 | table->used++; |
| 5183 | |
| 5184 | pidPtr[numPids] = pid; |
| 5185 | |
| 5186 | |
| 5187 | errorId = origErrorId; |
| 5188 | |
| 5189 | |
| 5190 | if (inputId != -1) { |
| 5191 | close(inputId); |
| 5192 | } |
| 5193 | if (outputId != -1) { |
| 5194 | close(outputId); |
| 5195 | outputId = -1; |
| 5196 | } |
| 5197 | inputId = pipeIds[0]; |
| 5198 | pipeIds[0] = pipeIds[1] = -1; |
| 5199 | } |
| 5200 | *pidArrayPtr = pidPtr; |
| 5201 | |
| 5202 | |
| 5203 | cleanup: |
| 5204 | if (inputId != -1) { |
| 5205 | close(inputId); |
| 5206 | } |
| 5207 | if (lastOutputId != -1) { |
| 5208 | close(lastOutputId); |
| 5209 | } |
| 5210 | if (errorId != -1) { |
| 5211 | close(errorId); |
| 5212 | } |
| 5213 | Jim_Free(arg_array); |
| 5214 | |
| 5215 | JimRestoreEnv(save_environ); |
| 5216 | |
| 5217 | return numPids; |
| 5218 | |
| 5219 | |
| 5220 | error: |
| 5221 | if ((inPipePtr != NULL) && (*inPipePtr != -1)) { |
| 5222 | close(*inPipePtr); |
| 5223 | *inPipePtr = -1; |
| 5224 | } |
| 5225 | if ((outPipePtr != NULL) && (*outPipePtr != -1)) { |
| 5226 | close(*outPipePtr); |
| 5227 | *outPipePtr = -1; |
| 5228 | } |
| 5229 | if ((errFilePtr != NULL) && (*errFilePtr != -1)) { |
| 5230 | close(*errFilePtr); |
| 5231 | *errFilePtr = -1; |
| 5232 | } |
| 5233 | if (pipeIds[0] != -1) { |
| 5234 | close(pipeIds[0]); |
| 5235 | } |
| 5236 | if (pipeIds[1] != -1) { |
| 5237 | close(pipeIds[1]); |
| 5238 | } |
| 5239 | if (pidPtr != NULL) { |
| 5240 | for (i = 0; i < numPids; i++) { |
| 5241 | if (pidPtr[i] != JIM_BAD_PID) { |
| 5242 | JimDetachPids(table, 1, &pidPtr[i]); |
| 5243 | } |
| 5244 | } |
| 5245 | Jim_Free(pidPtr); |
| 5246 | } |
| 5247 | numPids = -1; |
| @@ -5111,11 +5253,11 @@ | |
| 5253 | { |
| 5254 | struct WaitInfoTable *table = Jim_CmdPrivData(interp); |
| 5255 | int result = JIM_OK; |
| 5256 | int i; |
| 5257 | |
| 5258 | |
| 5259 | for (i = 0; i < numPids; i++) { |
| 5260 | int waitStatus = 0; |
| 5261 | if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) { |
| 5262 | if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) { |
| 5263 | result = JIM_ERR; |
| @@ -5127,234 +5269,30 @@ | |
| 5269 | return result; |
| 5270 | } |
| 5271 | |
| 5272 | int Jim_execInit(Jim_Interp *interp) |
| 5273 | { |
| 5274 | struct WaitInfoTable *waitinfo; |
| 5275 | if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) |
| 5276 | return JIM_ERR; |
| 5277 | |
| 5278 | #ifdef SIGPIPE |
| 5279 | (void)signal(SIGPIPE, SIG_IGN); |
| 5280 | #endif |
| 5281 | |
| 5282 | waitinfo = JimAllocWaitInfoTable(); |
| 5283 | Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable); |
| 5284 | waitinfo->refcount++; |
| 5285 | Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable); |
| 5286 | Jim_CreateCommand(interp, "pid", Jim_PidCommand, 0, 0); |
| 5287 | |
| 5288 | return JIM_OK; |
| 5289 | } |
| 5290 | |
| 5291 | #if defined(__MINGW32__) |
| 5292 | |
| 5293 | |
| 5294 | static int |
| 5295 | JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH]) |
| 5296 | { |
| 5297 | int i; |
| 5298 | static char extensions[][5] = {".exe", "", ".bat"}; |
| @@ -5381,10 +5319,15 @@ | |
| 5319 | |
| 5320 | static void JimRestoreEnv(char **env) |
| 5321 | { |
| 5322 | JimFreeEnv(env, Jim_GetEnviron()); |
| 5323 | } |
| 5324 | |
| 5325 | static char **JimOriginalEnviron(void) |
| 5326 | { |
| 5327 | return NULL; |
| 5328 | } |
| 5329 | |
| 5330 | static Jim_Obj * |
| 5331 | JimWinBuildCommandLine(Jim_Interp *interp, char **argv) |
| 5332 | { |
| 5333 | char *start, *special; |
| @@ -5455,18 +5398,19 @@ | |
| 5398 | } |
| 5399 | return strObj; |
| 5400 | } |
| 5401 | |
| 5402 | static pidtype |
| 5403 | JimStartWinProcess(Jim_Interp *interp, char **argv, char **env, int inputId, int outputId, int errorId) |
| 5404 | { |
| 5405 | STARTUPINFO startInfo; |
| 5406 | PROCESS_INFORMATION procInfo; |
| 5407 | HANDLE hProcess; |
| 5408 | char execPath[MAX_PATH]; |
| 5409 | pidtype pid = JIM_BAD_PID; |
| 5410 | Jim_Obj *cmdLineObj; |
| 5411 | char *winenv; |
| 5412 | |
| 5413 | if (JimWinFindExecutable(argv[0], execPath) < 0) { |
| 5414 | return JIM_BAD_PID; |
| 5415 | } |
| 5416 | argv[0] = execPath; |
| @@ -5480,47 +5424,51 @@ | |
| 5424 | startInfo.dwFlags = STARTF_USESTDHANDLES; |
| 5425 | startInfo.hStdInput = INVALID_HANDLE_VALUE; |
| 5426 | startInfo.hStdOutput= INVALID_HANDLE_VALUE; |
| 5427 | startInfo.hStdError = INVALID_HANDLE_VALUE; |
| 5428 | |
| 5429 | if (inputId == -1) { |
| 5430 | inputId = _fileno(stdin); |
| 5431 | } |
| 5432 | DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(inputId), hProcess, &startInfo.hStdInput, |
| 5433 | 0, TRUE, DUPLICATE_SAME_ACCESS); |
| 5434 | if (startInfo.hStdInput == INVALID_HANDLE_VALUE) { |
| 5435 | goto end; |
| 5436 | } |
| 5437 | |
| 5438 | if (outputId == -1) { |
| 5439 | outputId = _fileno(stdout); |
| 5440 | } |
| 5441 | DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(outputId), hProcess, &startInfo.hStdOutput, |
| 5442 | 0, TRUE, DUPLICATE_SAME_ACCESS); |
| 5443 | if (startInfo.hStdOutput == INVALID_HANDLE_VALUE) { |
| 5444 | goto end; |
| 5445 | } |
| 5446 | |
| 5447 | |
| 5448 | if (errorId == -1) { |
| 5449 | errorId = _fileno(stderr); |
| 5450 | } |
| 5451 | DuplicateHandle(hProcess, (HANDLE)_get_osfhandle(errorId), hProcess, &startInfo.hStdError, |
| 5452 | 0, TRUE, DUPLICATE_SAME_ACCESS); |
| 5453 | if (startInfo.hStdError == INVALID_HANDLE_VALUE) { |
| 5454 | goto end; |
| 5455 | } |
| 5456 | |
| 5457 | if (env == NULL) { |
| 5458 | |
| 5459 | winenv = NULL; |
| 5460 | } |
| 5461 | else if (env[0] == NULL) { |
| 5462 | winenv = (char *)"\0"; |
| 5463 | } |
| 5464 | else { |
| 5465 | winenv = env[0]; |
| 5466 | } |
| 5467 | |
| 5468 | if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE, |
| 5469 | 0, winenv, NULL, &startInfo, &procInfo)) { |
| 5470 | goto end; |
| 5471 | } |
| 5472 | |
| 5473 | |
| 5474 | WaitForInputIdle(procInfo.hProcess, 5000); |
| @@ -5528,49 +5476,27 @@ | |
| 5476 | |
| 5477 | pid = procInfo.hProcess; |
| 5478 | |
| 5479 | end: |
| 5480 | Jim_FreeNewObj(interp, cmdLineObj); |
| 5481 | if (startInfo.hStdInput != INVALID_HANDLE_VALUE) { |
| 5482 | CloseHandle(startInfo.hStdInput); |
| 5483 | } |
| 5484 | if (startInfo.hStdOutput != INVALID_HANDLE_VALUE) { |
| 5485 | CloseHandle(startInfo.hStdOutput); |
| 5486 | } |
| 5487 | if (startInfo.hStdError != INVALID_HANDLE_VALUE) { |
| 5488 | CloseHandle(startInfo.hStdError); |
| 5489 | } |
| 5490 | return pid; |
| 5491 | } |
| 5492 | |
| 5493 | #else |
| 5494 | |
| 5495 | static char **JimOriginalEnviron(void) |
| 5496 | { |
| 5497 | return Jim_GetEnviron(); |
| 5498 | } |
| 5499 | |
| 5500 | static char **JimSaveEnv(char **env) |
| 5501 | { |
| 5502 | char **saveenv = Jim_GetEnviron(); |
| @@ -5585,13 +5511,21 @@ | |
| 5511 | } |
| 5512 | #endif |
| 5513 | #endif |
| 5514 | |
| 5515 | |
| 5516 | |
| 5517 | #ifdef STRPTIME_NEEDS_XOPEN_SOURCE |
| 5518 | #ifndef _XOPEN_SOURCE |
| 5519 | #define _XOPEN_SOURCE 500 |
| 5520 | #endif |
| 5521 | #endif |
| 5522 | |
| 5523 | |
| 5524 | #ifndef _GNU_SOURCE |
| 5525 | #define _GNU_SOURCE |
| 5526 | #endif |
| 5527 | |
| 5528 | #include <stdlib.h> |
| 5529 | #include <string.h> |
| 5530 | #include <stdio.h> |
| 5531 | #include <time.h> |
| @@ -5598,65 +5532,126 @@ | |
| 5532 | |
| 5533 | |
| 5534 | #ifdef HAVE_SYS_TIME_H |
| 5535 | #include <sys/time.h> |
| 5536 | #endif |
| 5537 | |
| 5538 | struct clock_options { |
| 5539 | int gmt; |
| 5540 | const char *format; |
| 5541 | }; |
| 5542 | |
| 5543 | static int parse_clock_options(Jim_Interp *interp, int argc, Jim_Obj *const *argv, struct clock_options *opts) |
| 5544 | { |
| 5545 | static const char * const options[] = { "-gmt", "-format", NULL }; |
| 5546 | enum { OPT_GMT, OPT_FORMAT, }; |
| 5547 | int i; |
| 5548 | |
| 5549 | for (i = 0; i < argc; i += 2) { |
| 5550 | int option; |
| 5551 | if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { |
| 5552 | return JIM_ERR; |
| 5553 | } |
| 5554 | switch (option) { |
| 5555 | case OPT_GMT: |
| 5556 | if (Jim_GetBoolean(interp, argv[i + 1], &opts->gmt) != JIM_OK) { |
| 5557 | return JIM_ERR; |
| 5558 | } |
| 5559 | break; |
| 5560 | case OPT_FORMAT: |
| 5561 | opts->format = Jim_String(argv[i + 1]); |
| 5562 | break; |
| 5563 | } |
| 5564 | } |
| 5565 | return JIM_OK; |
| 5566 | } |
| 5567 | |
| 5568 | static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5569 | { |
| 5570 | |
| 5571 | char buf[100]; |
| 5572 | time_t t; |
| 5573 | jim_wide seconds; |
| 5574 | struct clock_options options = { 0, "%a %b %d %H:%M:%S %Z %Y" }; |
| 5575 | struct tm *tm; |
| 5576 | |
| 5577 | if (Jim_GetWide(interp, argv[0], &seconds) != JIM_OK) { |
| 5578 | return JIM_ERR; |
| 5579 | } |
| 5580 | if (argc % 2 == 0) { |
| 5581 | return -1; |
| 5582 | } |
| 5583 | if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) { |
| 5584 | return JIM_ERR; |
| 5585 | } |
| 5586 | |
| 5587 | t = seconds; |
| 5588 | tm = options.gmt ? gmtime(&t) : localtime(&t); |
| 5589 | |
| 5590 | if (tm == NULL || strftime(buf, sizeof(buf), options.format, tm) == 0) { |
| 5591 | Jim_SetResultString(interp, "format string too long or invalid time", -1); |
| 5592 | return JIM_ERR; |
| 5593 | } |
| 5594 | |
| 5595 | Jim_SetResultString(interp, buf, -1); |
| 5596 | |
| 5597 | return JIM_OK; |
| 5598 | } |
| 5599 | |
| 5600 | #ifdef HAVE_STRPTIME |
| 5601 | #ifndef HAVE_TIMEGM |
| 5602 | |
| 5603 | static time_t timegm(struct tm *tm) |
| 5604 | { |
| 5605 | time_t t; |
| 5606 | const char *tz = getenv("TZ"); |
| 5607 | setenv("TZ", "", 1); |
| 5608 | tzset(); |
| 5609 | t = mktime(tm); |
| 5610 | if (tz) { |
| 5611 | setenv("TZ", tz, 1); |
| 5612 | } |
| 5613 | else { |
| 5614 | unsetenv("TZ"); |
| 5615 | } |
| 5616 | tzset(); |
| 5617 | return t; |
| 5618 | } |
| 5619 | #endif |
| 5620 | |
| 5621 | static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5622 | { |
| 5623 | char *pt; |
| 5624 | struct tm tm; |
| 5625 | |
| 5626 | |
| 5627 | struct clock_options options = { 0, NULL }; |
| 5628 | |
| 5629 | if (argc % 2 == 0) { |
| 5630 | return -1; |
| 5631 | } |
| 5632 | |
| 5633 | if (parse_clock_options(interp, argc - 1, argv + 1, &options) == JIM_ERR) { |
| 5634 | return JIM_ERR; |
| 5635 | } |
| 5636 | if (options.format == NULL) { |
| 5637 | return -1; |
| 5638 | } |
| 5639 | |
| 5640 | |
| 5641 | memset(&tm, 0, sizeof(tm)); |
| 5642 | |
| 5643 | tm.tm_mday = 1; |
| 5644 | |
| 5645 | pt = strptime(Jim_String(argv[0]), options.format, &tm); |
| 5646 | if (pt == 0 || *pt != 0) { |
| 5647 | Jim_SetResultString(interp, "Failed to parse time according to format", -1); |
| 5648 | return JIM_ERR; |
| 5649 | } |
| 5650 | |
| 5651 | |
| 5652 | Jim_SetResultInt(interp, options.gmt ? timegm(&tm) : mktime(&tm)); |
| 5653 | |
| 5654 | return JIM_OK; |
| 5655 | } |
| 5656 | #endif |
| 5657 | |
| @@ -5688,54 +5683,54 @@ | |
| 5683 | |
| 5684 | return JIM_OK; |
| 5685 | } |
| 5686 | |
| 5687 | static const jim_subcmd_type clock_command_table[] = { |
| 5688 | { "clicks", |
| 5689 | NULL, |
| 5690 | clock_cmd_micros, |
| 5691 | 0, |
| 5692 | 0, |
| 5693 | |
| 5694 | }, |
| 5695 | { "format", |
| 5696 | "seconds ?-format string? ?-gmt boolean?", |
| 5697 | clock_cmd_format, |
| 5698 | 1, |
| 5699 | 5, |
| 5700 | |
| 5701 | }, |
| 5702 | { "microseconds", |
| 5703 | NULL, |
| 5704 | clock_cmd_micros, |
| 5705 | 0, |
| 5706 | 0, |
| 5707 | |
| 5708 | }, |
| 5709 | { "milliseconds", |
| 5710 | NULL, |
| 5711 | clock_cmd_millis, |
| 5712 | 0, |
| 5713 | 0, |
| 5714 | |
| 5715 | }, |
| 5716 | #ifdef HAVE_STRPTIME |
| 5717 | { "scan", |
| 5718 | "str -format format ?-gmt boolean?", |
| 5719 | clock_cmd_scan, |
| 5720 | 3, |
| 5721 | 5, |
| 5722 | |
| 5723 | }, |
| 5724 | #endif |
| 5725 | { "seconds", |
| 5726 | NULL, |
| 5727 | clock_cmd_seconds, |
| 5728 | 0, |
| 5729 | 0, |
| 5730 | |
| 5731 | }, |
| 5732 | { NULL } |
| 5733 | }; |
| 5734 | |
| 5735 | int Jim_clockInit(Jim_Interp *interp) |
| 5736 | { |
| @@ -5753,12 +5748,13 @@ | |
| 5748 | #include <errno.h> |
| 5749 | |
| 5750 | |
| 5751 | static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5752 | { |
| 5753 | |
| 5754 | Jim_Obj *dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5755 | Jim_SetResultInt(interp, dictObj && Jim_DictSize(interp, dictObj) != -1); |
| 5756 | return JIM_OK; |
| 5757 | } |
| 5758 | |
| 5759 | static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5760 | { |
| @@ -5769,21 +5765,20 @@ | |
| 5765 | return JIM_OK; |
| 5766 | } |
| 5767 | |
| 5768 | patternObj = (argc == 1) ? NULL : argv[1]; |
| 5769 | |
| 5770 | |
| 5771 | if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { |
| 5772 | if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { |
| 5773 | |
| 5774 | Jim_SetResult(interp, objPtr); |
| 5775 | return JIM_OK; |
| 5776 | } |
| 5777 | } |
| 5778 | |
| 5779 | return Jim_DictMatchTypes(interp, objPtr, patternObj, JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS | JIM_DICTMATCH_VALUES); |
| 5780 | } |
| 5781 | |
| 5782 | static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5783 | { |
| 5784 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| @@ -5790,11 +5785,11 @@ | |
| 5785 | |
| 5786 | if (!objPtr) { |
| 5787 | return JIM_OK; |
| 5788 | } |
| 5789 | |
| 5790 | return Jim_DictMatchTypes(interp, objPtr, argc == 1 ? NULL : argv[1], JIM_DICTMATCH_KEYS, JIM_DICTMATCH_KEYS); |
| 5791 | } |
| 5792 | |
| 5793 | static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5794 | { |
| 5795 | int i; |
| @@ -5802,27 +5797,29 @@ | |
| 5797 | Jim_Obj *resultObj; |
| 5798 | Jim_Obj *objPtr; |
| 5799 | Jim_Obj **dictValuesObj; |
| 5800 | |
| 5801 | if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { |
| 5802 | |
| 5803 | Jim_UnsetVariable(interp, argv[0], JIM_NONE); |
| 5804 | return JIM_OK; |
| 5805 | } |
| 5806 | |
| 5807 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5808 | |
| 5809 | if (objPtr == NULL) { |
| 5810 | |
| 5811 | return JIM_OK; |
| 5812 | } |
| 5813 | |
| 5814 | if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { |
| 5815 | |
| 5816 | Jim_SetResultString(interp, "", -1); |
| 5817 | return JIM_OK; |
| 5818 | } |
| 5819 | |
| 5820 | |
| 5821 | resultObj = Jim_NewDictObj(interp, NULL, 0); |
| 5822 | |
| 5823 | for (i = 0; i < len; i += 2) { |
| 5824 | if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { |
| 5825 | Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); |
| @@ -5837,16 +5834,18 @@ | |
| 5834 | static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 5835 | { |
| 5836 | Jim_Obj *objPtr; |
| 5837 | int len = 0; |
| 5838 | |
| 5839 | |
| 5840 | objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); |
| 5841 | if (objPtr) { |
| 5842 | len = Jim_DictSize(interp, objPtr); |
| 5843 | if (len < 0) { |
| 5844 | |
| 5845 | Jim_SetResultInt(interp, 0); |
| 5846 | return JIM_OK; |
| 5847 | } |
| 5848 | } |
| 5849 | |
| 5850 | Jim_SetResultInt(interp, len); |
| 5851 | |
| @@ -5876,11 +5875,11 @@ | |
| 5875 | return JIM_ERR; |
| 5876 | } |
| 5877 | |
| 5878 | dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); |
| 5879 | if (!dictObj) { |
| 5880 | |
| 5881 | return Jim_SetVariable(interp, argv[0], listObj); |
| 5882 | } |
| 5883 | else if (Jim_DictSize(interp, dictObj) < 0) { |
| 5884 | return JIM_ERR; |
| 5885 | } |
| @@ -5905,53 +5904,53 @@ | |
| 5904 | { "exists", |
| 5905 | "arrayName", |
| 5906 | array_cmd_exists, |
| 5907 | 1, |
| 5908 | 1, |
| 5909 | |
| 5910 | }, |
| 5911 | { "get", |
| 5912 | "arrayName ?pattern?", |
| 5913 | array_cmd_get, |
| 5914 | 1, |
| 5915 | 2, |
| 5916 | |
| 5917 | }, |
| 5918 | { "names", |
| 5919 | "arrayName ?pattern?", |
| 5920 | array_cmd_names, |
| 5921 | 1, |
| 5922 | 2, |
| 5923 | |
| 5924 | }, |
| 5925 | { "set", |
| 5926 | "arrayName list", |
| 5927 | array_cmd_set, |
| 5928 | 2, |
| 5929 | 2, |
| 5930 | |
| 5931 | }, |
| 5932 | { "size", |
| 5933 | "arrayName", |
| 5934 | array_cmd_size, |
| 5935 | 1, |
| 5936 | 1, |
| 5937 | |
| 5938 | }, |
| 5939 | { "stat", |
| 5940 | "arrayName", |
| 5941 | array_cmd_stat, |
| 5942 | 1, |
| 5943 | 1, |
| 5944 | |
| 5945 | }, |
| 5946 | { "unset", |
| 5947 | "arrayName ?pattern?", |
| 5948 | array_cmd_unset, |
| 5949 | 1, |
| 5950 | 2, |
| 5951 | |
| 5952 | }, |
| 5953 | { NULL |
| 5954 | } |
| 5955 | }; |
| 5956 | |
| @@ -5987,11 +5986,14 @@ | |
| 5986 | Jim_arrayInit(interp); |
| 5987 | Jim_stdlibInit(interp); |
| 5988 | Jim_tclcompatInit(interp); |
| 5989 | return JIM_OK; |
| 5990 | } |
| 5991 | #define JIM_OPTIMIZATION |
| 5992 | #ifndef _GNU_SOURCE |
| 5993 | #define _GNU_SOURCE |
| 5994 | #endif |
| 5995 | |
| 5996 | #include <stdio.h> |
| 5997 | #include <stdlib.h> |
| 5998 | |
| 5999 | #include <string.h> |
| @@ -6056,10 +6058,16 @@ | |
| 6058 | #define JimPanic(X) JimPanicDump X |
| 6059 | #else |
| 6060 | #define JimPanic(X) |
| 6061 | #endif |
| 6062 | |
| 6063 | #ifdef JIM_OPTIMIZATION |
| 6064 | #define JIM_IF_OPTIM(X) X |
| 6065 | #else |
| 6066 | #define JIM_IF_OPTIM(X) |
| 6067 | #endif |
| 6068 | |
| 6069 | |
| 6070 | static char JimEmptyStringRep[] = ""; |
| 6071 | |
| 6072 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); |
| 6073 | static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, |
| @@ -6112,34 +6120,34 @@ | |
| 6120 | if (*pattern == '^') { |
| 6121 | not++; |
| 6122 | pattern++; |
| 6123 | } |
| 6124 | |
| 6125 | |
| 6126 | if (*pattern == ']') { |
| 6127 | goto first; |
| 6128 | } |
| 6129 | } |
| 6130 | |
| 6131 | while (*pattern && *pattern != ']') { |
| 6132 | |
| 6133 | if (pattern[0] == '\\') { |
| 6134 | first: |
| 6135 | pattern += utf8_tounicode_case(pattern, &pchar, nocase); |
| 6136 | } |
| 6137 | else { |
| 6138 | |
| 6139 | int start; |
| 6140 | int end; |
| 6141 | |
| 6142 | pattern += utf8_tounicode_case(pattern, &start, nocase); |
| 6143 | if (pattern[0] == '-' && pattern[1]) { |
| 6144 | |
| 6145 | pattern++; |
| 6146 | pattern += utf8_tounicode_case(pattern, &end, nocase); |
| 6147 | |
| 6148 | |
| 6149 | if ((c >= start && c <= end) || (c >= end && c <= start)) { |
| 6150 | match = 1; |
| 6151 | } |
| 6152 | continue; |
| 6153 | } |
| @@ -6169,19 +6177,19 @@ | |
| 6177 | while (pattern[1] == '*') { |
| 6178 | pattern++; |
| 6179 | } |
| 6180 | pattern++; |
| 6181 | if (!pattern[0]) { |
| 6182 | return 1; |
| 6183 | } |
| 6184 | while (*string) { |
| 6185 | |
| 6186 | if (JimGlobMatch(pattern, string, nocase)) |
| 6187 | return 1; |
| 6188 | string += utf8_tounicode(string, &c); |
| 6189 | } |
| 6190 | return 0; |
| 6191 | |
| 6192 | case '?': |
| 6193 | string += utf8_tounicode(string, &c); |
| 6194 | break; |
| 6195 | |
| @@ -6190,20 +6198,20 @@ | |
| 6198 | pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); |
| 6199 | if (!pattern) { |
| 6200 | return 0; |
| 6201 | } |
| 6202 | if (!*pattern) { |
| 6203 | |
| 6204 | continue; |
| 6205 | } |
| 6206 | break; |
| 6207 | } |
| 6208 | case '\\': |
| 6209 | if (pattern[1]) { |
| 6210 | pattern++; |
| 6211 | } |
| 6212 | |
| 6213 | default: |
| 6214 | string += utf8_tounicode_case(string, &c, nocase); |
| 6215 | utf8_tounicode_case(pattern, &pchar, nocase); |
| 6216 | if (pchar != c) { |
| 6217 | return 0; |
| @@ -6249,11 +6257,11 @@ | |
| 6257 | maxchars--; |
| 6258 | } |
| 6259 | if (!maxchars) { |
| 6260 | return 0; |
| 6261 | } |
| 6262 | |
| 6263 | if (*s1) { |
| 6264 | return 1; |
| 6265 | } |
| 6266 | if (*s2) { |
| 6267 | return -1; |
| @@ -6290,11 +6298,11 @@ | |
| 6298 | const char *p; |
| 6299 | |
| 6300 | if (!l1 || !l2 || l1 > l2) |
| 6301 | return -1; |
| 6302 | |
| 6303 | |
| 6304 | for (p = s2 + l2 - 1; p != s2 - 1; p--) { |
| 6305 | if (*p == *s1 && memcmp(s1, p, l1) == 0) { |
| 6306 | return p - s2; |
| 6307 | } |
| 6308 | } |
| @@ -6349,28 +6357,28 @@ | |
| 6357 | } |
| 6358 | *sign = 1; |
| 6359 | } |
| 6360 | |
| 6361 | if (str[i] != '0') { |
| 6362 | |
| 6363 | return 0; |
| 6364 | } |
| 6365 | |
| 6366 | |
| 6367 | switch (str[i + 1]) { |
| 6368 | case 'x': case 'X': *base = 16; break; |
| 6369 | case 'o': case 'O': *base = 8; break; |
| 6370 | case 'b': case 'B': *base = 2; break; |
| 6371 | default: return 0; |
| 6372 | } |
| 6373 | i += 2; |
| 6374 | |
| 6375 | if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) { |
| 6376 | |
| 6377 | return i; |
| 6378 | } |
| 6379 | |
| 6380 | *base = 10; |
| 6381 | return 0; |
| 6382 | } |
| 6383 | |
| 6384 | static long jim_strtol(const char *str, char **endptr) |
| @@ -6384,11 +6392,11 @@ | |
| 6392 | if (endptr == NULL || *endptr != str + i) { |
| 6393 | return value * sign; |
| 6394 | } |
| 6395 | } |
| 6396 | |
| 6397 | |
| 6398 | return strtol(str, endptr, 10); |
| 6399 | } |
| 6400 | |
| 6401 | |
| 6402 | static jim_wide jim_strtoull(const char *str, char **endptr) |
| @@ -6403,11 +6411,11 @@ | |
| 6411 | if (endptr == NULL || *endptr != str + i) { |
| 6412 | return value * sign; |
| 6413 | } |
| 6414 | } |
| 6415 | |
| 6416 | |
| 6417 | return strtoull(str, endptr, 10); |
| 6418 | #else |
| 6419 | return (unsigned long)jim_strtol(str, endptr); |
| 6420 | #endif |
| 6421 | } |
| @@ -6428,26 +6436,40 @@ | |
| 6436 | |
| 6437 | int Jim_StringToDouble(const char *str, double *doublePtr) |
| 6438 | { |
| 6439 | char *endptr; |
| 6440 | |
| 6441 | |
| 6442 | errno = 0; |
| 6443 | |
| 6444 | *doublePtr = strtod(str, &endptr); |
| 6445 | |
| 6446 | return JimCheckConversion(str, endptr); |
| 6447 | } |
| 6448 | |
| 6449 | static jim_wide JimPowWide(jim_wide b, jim_wide e) |
| 6450 | { |
| 6451 | jim_wide res = 1; |
| 6452 | |
| 6453 | |
| 6454 | if (b == 1) { |
| 6455 | |
| 6456 | return 1; |
| 6457 | } |
| 6458 | if (e < 0) { |
| 6459 | if (b != -1) { |
| 6460 | return 0; |
| 6461 | } |
| 6462 | e = -e; |
| 6463 | } |
| 6464 | while (e) |
| 6465 | { |
| 6466 | if (e & 1) { |
| 6467 | res *= b; |
| 6468 | } |
| 6469 | e >>= 1; |
| 6470 | b *= b; |
| 6471 | } |
| 6472 | return res; |
| 6473 | } |
| 6474 | |
| 6475 | #ifdef JIM_DEBUG_PANIC |
| @@ -6509,11 +6531,11 @@ | |
| 6531 | char *Jim_StrDupLen(const char *s, int l) |
| 6532 | { |
| 6533 | char *copy = Jim_Alloc(l + 1); |
| 6534 | |
| 6535 | memcpy(copy, s, l + 1); |
| 6536 | copy[l] = 0; |
| 6537 | return copy; |
| 6538 | } |
| 6539 | |
| 6540 | |
| 6541 | |
| @@ -6598,52 +6620,52 @@ | |
| 6620 | } |
| 6621 | |
| 6622 | |
| 6623 | void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) |
| 6624 | { |
| 6625 | Jim_HashTable n; |
| 6626 | unsigned int realsize = JimHashTableNextPower(size), i; |
| 6627 | |
| 6628 | if (size <= ht->used) |
| 6629 | return; |
| 6630 | |
| 6631 | Jim_InitHashTable(&n, ht->type, ht->privdata); |
| 6632 | n.size = realsize; |
| 6633 | n.sizemask = realsize - 1; |
| 6634 | n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); |
| 6635 | |
| 6636 | n.uniq = ht->uniq; |
| 6637 | |
| 6638 | |
| 6639 | memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); |
| 6640 | |
| 6641 | n.used = ht->used; |
| 6642 | for (i = 0; ht->used > 0; i++) { |
| 6643 | Jim_HashEntry *he, *nextHe; |
| 6644 | |
| 6645 | if (ht->table[i] == NULL) |
| 6646 | continue; |
| 6647 | |
| 6648 | |
| 6649 | he = ht->table[i]; |
| 6650 | while (he) { |
| 6651 | unsigned int h; |
| 6652 | |
| 6653 | nextHe = he->next; |
| 6654 | |
| 6655 | h = Jim_HashKey(ht, he->key) & n.sizemask; |
| 6656 | he->next = n.table[h]; |
| 6657 | n.table[h] = he; |
| 6658 | ht->used--; |
| 6659 | |
| 6660 | he = nextHe; |
| 6661 | } |
| 6662 | } |
| 6663 | assert(ht->used == 0); |
| 6664 | Jim_Free(ht->table); |
| 6665 | |
| 6666 | |
| 6667 | *ht = n; |
| 6668 | } |
| 6669 | |
| 6670 | |
| 6671 | int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) |
| @@ -6652,11 +6674,11 @@ | |
| 6674 | |
| 6675 | entry = JimInsertHashEntry(ht, key, 0); |
| 6676 | if (entry == NULL) |
| 6677 | return JIM_ERR; |
| 6678 | |
| 6679 | |
| 6680 | Jim_SetHashKey(ht, entry, key); |
| 6681 | Jim_SetHashVal(ht, entry, val); |
| 6682 | return JIM_OK; |
| 6683 | } |
| 6684 | |
| @@ -6678,11 +6700,11 @@ | |
| 6700 | Jim_SetHashVal(ht, entry, val); |
| 6701 | } |
| 6702 | existed = 1; |
| 6703 | } |
| 6704 | else { |
| 6705 | |
| 6706 | Jim_SetHashKey(ht, entry, key); |
| 6707 | Jim_SetHashVal(ht, entry, val); |
| 6708 | existed = 0; |
| 6709 | } |
| 6710 | |
| @@ -6701,11 +6723,11 @@ | |
| 6723 | he = ht->table[h]; |
| 6724 | |
| 6725 | prevHe = NULL; |
| 6726 | while (he) { |
| 6727 | if (Jim_CompareHashKeys(ht, key, he->key)) { |
| 6728 | |
| 6729 | if (prevHe) |
| 6730 | prevHe->next = he->next; |
| 6731 | else |
| 6732 | ht->table[h] = he->next; |
| 6733 | Jim_FreeEntryKey(ht, he); |
| @@ -6715,19 +6737,19 @@ | |
| 6737 | return JIM_OK; |
| 6738 | } |
| 6739 | prevHe = he; |
| 6740 | he = he->next; |
| 6741 | } |
| 6742 | return JIM_ERR; |
| 6743 | } |
| 6744 | |
| 6745 | |
| 6746 | int Jim_FreeHashTable(Jim_HashTable *ht) |
| 6747 | { |
| 6748 | unsigned int i; |
| 6749 | |
| 6750 | |
| 6751 | for (i = 0; ht->used > 0; i++) { |
| 6752 | Jim_HashEntry *he, *nextHe; |
| 6753 | |
| 6754 | if ((he = ht->table[i]) == NULL) |
| 6755 | continue; |
| @@ -6738,15 +6760,15 @@ | |
| 6760 | Jim_Free(he); |
| 6761 | ht->used--; |
| 6762 | he = nextHe; |
| 6763 | } |
| 6764 | } |
| 6765 | |
| 6766 | Jim_Free(ht->table); |
| 6767 | |
| 6768 | JimResetHashTable(ht); |
| 6769 | return JIM_OK; |
| 6770 | } |
| 6771 | |
| 6772 | Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key) |
| 6773 | { |
| 6774 | Jim_HashEntry *he; |
| @@ -6819,24 +6841,24 @@ | |
| 6841 | static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace) |
| 6842 | { |
| 6843 | unsigned int h; |
| 6844 | Jim_HashEntry *he; |
| 6845 | |
| 6846 | |
| 6847 | JimExpandHashTableIfNeeded(ht); |
| 6848 | |
| 6849 | |
| 6850 | h = Jim_HashKey(ht, key) & ht->sizemask; |
| 6851 | |
| 6852 | he = ht->table[h]; |
| 6853 | while (he) { |
| 6854 | if (Jim_CompareHashKeys(ht, key, he->key)) |
| 6855 | return replace ? he : NULL; |
| 6856 | he = he->next; |
| 6857 | } |
| 6858 | |
| 6859 | |
| 6860 | he = Jim_Alloc(sizeof(*he)); |
| 6861 | he->next = ht->table[h]; |
| 6862 | ht->table[h] = he; |
| 6863 | ht->used++; |
| 6864 | he->key = NULL; |
| @@ -6865,16 +6887,16 @@ | |
| 6887 | { |
| 6888 | Jim_Free(key); |
| 6889 | } |
| 6890 | |
| 6891 | static const Jim_HashTableType JimPackageHashTableType = { |
| 6892 | JimStringCopyHTHashFunction, |
| 6893 | JimStringCopyHTDup, |
| 6894 | NULL, |
| 6895 | JimStringCopyHTKeyCompare, |
| 6896 | JimStringCopyHTKeyDestructor, |
| 6897 | NULL |
| 6898 | }; |
| 6899 | |
| 6900 | typedef struct AssocDataValue |
| 6901 | { |
| 6902 | Jim_InterpDeleteProc *delProc; |
| @@ -6889,16 +6911,16 @@ | |
| 6911 | assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data); |
| 6912 | Jim_Free(data); |
| 6913 | } |
| 6914 | |
| 6915 | static const Jim_HashTableType JimAssocDataHashTableType = { |
| 6916 | JimStringCopyHTHashFunction, |
| 6917 | JimStringCopyHTDup, |
| 6918 | NULL, |
| 6919 | JimStringCopyHTKeyCompare, |
| 6920 | JimStringCopyHTKeyDestructor, |
| 6921 | JimAssocDataHashTableValueDestructor |
| 6922 | }; |
| 6923 | |
| 6924 | void Jim_InitStack(Jim_Stack *stack) |
| 6925 | { |
| 6926 | stack->len = 0; |
| @@ -6951,56 +6973,61 @@ | |
| 6973 | freeFunc(stack->vector[i]); |
| 6974 | } |
| 6975 | |
| 6976 | |
| 6977 | |
| 6978 | #define JIM_TT_NONE 0 |
| 6979 | #define JIM_TT_STR 1 |
| 6980 | #define JIM_TT_ESC 2 |
| 6981 | #define JIM_TT_VAR 3 |
| 6982 | #define JIM_TT_DICTSUGAR 4 |
| 6983 | #define JIM_TT_CMD 5 |
| 6984 | |
| 6985 | #define JIM_TT_SEP 6 |
| 6986 | #define JIM_TT_EOL 7 |
| 6987 | #define JIM_TT_EOF 8 |
| 6988 | |
| 6989 | #define JIM_TT_LINE 9 |
| 6990 | #define JIM_TT_WORD 10 |
| 6991 | |
| 6992 | |
| 6993 | #define JIM_TT_SUBEXPR_START 11 |
| 6994 | #define JIM_TT_SUBEXPR_END 12 |
| 6995 | #define JIM_TT_SUBEXPR_COMMA 13 |
| 6996 | #define JIM_TT_EXPR_INT 14 |
| 6997 | #define JIM_TT_EXPR_DOUBLE 15 |
| 6998 | #define JIM_TT_EXPR_BOOLEAN 16 |
| 6999 | |
| 7000 | #define JIM_TT_EXPRSUGAR 17 |
| 7001 | |
| 7002 | |
| 7003 | #define JIM_TT_EXPR_OP 20 |
| 7004 | |
| 7005 | #define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF) |
| 7006 | |
| 7007 | #define TOKEN_IS_EXPR_START(type) (type == JIM_TT_NONE || type == JIM_TT_SUBEXPR_START || type == JIM_TT_SUBEXPR_COMMA) |
| 7008 | |
| 7009 | #define TOKEN_IS_EXPR_OP(type) (type >= JIM_TT_EXPR_OP) |
| 7010 | |
| 7011 | struct JimParseMissing { |
| 7012 | int ch; |
| 7013 | int line; |
| 7014 | }; |
| 7015 | |
| 7016 | struct JimParserCtx |
| 7017 | { |
| 7018 | const char *p; |
| 7019 | int len; |
| 7020 | int linenr; |
| 7021 | const char *tstart; |
| 7022 | const char *tend; |
| 7023 | int tline; |
| 7024 | int tt; |
| 7025 | int eof; |
| 7026 | int inquote; |
| 7027 | int comment; |
| 7028 | struct JimParseMissing missing; |
| 7029 | }; |
| 7030 | |
| 7031 | static int JimParseScript(struct JimParserCtx *pc); |
| 7032 | static int JimParseSep(struct JimParserCtx *pc); |
| 7033 | static int JimParseEol(struct JimParserCtx *pc); |
| @@ -7030,11 +7057,11 @@ | |
| 7057 | pc->missing.line = linenr; |
| 7058 | } |
| 7059 | |
| 7060 | static int JimParseScript(struct JimParserCtx *pc) |
| 7061 | { |
| 7062 | while (1) { |
| 7063 | if (!pc->len) { |
| 7064 | pc->tstart = pc->p; |
| 7065 | pc->tend = pc->p - 1; |
| 7066 | pc->tline = pc->linenr; |
| 7067 | pc->tt = JIM_TT_EOL; |
| @@ -7066,11 +7093,11 @@ | |
| 7093 | pc->comment = 0; |
| 7094 | return JimParseCmd(pc); |
| 7095 | case '$': |
| 7096 | pc->comment = 0; |
| 7097 | if (JimParseVar(pc) == JIM_ERR) { |
| 7098 | |
| 7099 | pc->tstart = pc->tend = pc->p++; |
| 7100 | pc->len--; |
| 7101 | pc->tt = JIM_TT_ESC; |
| 7102 | } |
| 7103 | return JIM_OK; |
| @@ -7127,11 +7154,11 @@ | |
| 7154 | |
| 7155 | static void JimParseSubBrace(struct JimParserCtx *pc) |
| 7156 | { |
| 7157 | int level = 1; |
| 7158 | |
| 7159 | |
| 7160 | pc->p++; |
| 7161 | pc->len--; |
| 7162 | while (pc->len) { |
| 7163 | switch (*pc->p) { |
| 7164 | case '\\': |
| @@ -7171,11 +7198,11 @@ | |
| 7198 | static int JimParseSubQuote(struct JimParserCtx *pc) |
| 7199 | { |
| 7200 | int tt = JIM_TT_STR; |
| 7201 | int line = pc->tline; |
| 7202 | |
| 7203 | |
| 7204 | pc->p++; |
| 7205 | pc->len--; |
| 7206 | while (pc->len) { |
| 7207 | switch (*pc->p) { |
| 7208 | case '\\': |
| @@ -7220,11 +7247,11 @@ | |
| 7247 | { |
| 7248 | int level = 1; |
| 7249 | int startofword = 1; |
| 7250 | int line = pc->tline; |
| 7251 | |
| 7252 | |
| 7253 | pc->p++; |
| 7254 | pc->len--; |
| 7255 | while (pc->len) { |
| 7256 | switch (*pc->p) { |
| 7257 | case '\\': |
| @@ -7300,17 +7327,17 @@ | |
| 7327 | return JIM_OK; |
| 7328 | } |
| 7329 | |
| 7330 | static int JimParseVar(struct JimParserCtx *pc) |
| 7331 | { |
| 7332 | |
| 7333 | pc->p++; |
| 7334 | pc->len--; |
| 7335 | |
| 7336 | #ifdef EXPRSUGAR_BRACKET |
| 7337 | if (*pc->p == '[') { |
| 7338 | |
| 7339 | JimParseCmd(pc); |
| 7340 | pc->tt = JIM_TT_EXPRSUGAR; |
| 7341 | return JIM_OK; |
| 7342 | } |
| 7343 | #endif |
| @@ -7336,11 +7363,11 @@ | |
| 7363 | pc->len--; |
| 7364 | } |
| 7365 | } |
| 7366 | else { |
| 7367 | while (1) { |
| 7368 | |
| 7369 | if (pc->p[0] == ':' && pc->p[1] == ':') { |
| 7370 | while (*pc->p == ':') { |
| 7371 | pc->p++; |
| 7372 | pc->len--; |
| 7373 | } |
| @@ -7351,11 +7378,11 @@ | |
| 7378 | pc->len--; |
| 7379 | continue; |
| 7380 | } |
| 7381 | break; |
| 7382 | } |
| 7383 | |
| 7384 | if (*pc->p == '(') { |
| 7385 | int count = 1; |
| 7386 | const char *paren = NULL; |
| 7387 | |
| 7388 | pc->tt = JIM_TT_DICTSUGAR; |
| @@ -7378,11 +7405,11 @@ | |
| 7405 | if (count == 0) { |
| 7406 | pc->p++; |
| 7407 | pc->len--; |
| 7408 | } |
| 7409 | else if (paren) { |
| 7410 | |
| 7411 | paren++; |
| 7412 | pc->len += (pc->p - paren); |
| 7413 | pc->p = paren; |
| 7414 | } |
| 7415 | #ifndef EXPRSUGAR_BRACKET |
| @@ -7403,19 +7430,19 @@ | |
| 7430 | |
| 7431 | static int JimParseStr(struct JimParserCtx *pc) |
| 7432 | { |
| 7433 | if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL || |
| 7434 | pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) { |
| 7435 | |
| 7436 | if (*pc->p == '{') { |
| 7437 | return JimParseBrace(pc); |
| 7438 | } |
| 7439 | if (*pc->p == '"') { |
| 7440 | pc->inquote = 1; |
| 7441 | pc->p++; |
| 7442 | pc->len--; |
| 7443 | |
| 7444 | pc->missing.line = pc->tline; |
| 7445 | } |
| 7446 | } |
| 7447 | pc->tstart = pc->p; |
| 7448 | pc->tline = pc->linenr; |
| @@ -7441,25 +7468,25 @@ | |
| 7468 | } |
| 7469 | pc->p++; |
| 7470 | pc->len--; |
| 7471 | } |
| 7472 | else if (pc->len == 1) { |
| 7473 | |
| 7474 | pc->missing.ch = '\\'; |
| 7475 | } |
| 7476 | break; |
| 7477 | case '(': |
| 7478 | |
| 7479 | if (pc->len > 1 && pc->p[1] != '$') { |
| 7480 | break; |
| 7481 | } |
| 7482 | |
| 7483 | case ')': |
| 7484 | |
| 7485 | if (*pc->p == '(' || pc->tt == JIM_TT_VAR) { |
| 7486 | if (pc->p == pc->tstart) { |
| 7487 | |
| 7488 | pc->p++; |
| 7489 | pc->len--; |
| 7490 | } |
| 7491 | pc->tend = pc->p - 1; |
| 7492 | pc->tt = JIM_TT_ESC; |
| @@ -7499,11 +7526,11 @@ | |
| 7526 | break; |
| 7527 | } |
| 7528 | pc->p++; |
| 7529 | pc->len--; |
| 7530 | } |
| 7531 | return JIM_OK; |
| 7532 | } |
| 7533 | |
| 7534 | static int JimParseComment(struct JimParserCtx *pc) |
| 7535 | { |
| 7536 | while (*pc->p) { |
| @@ -7610,34 +7637,34 @@ | |
| 7637 | if (c == -1) { |
| 7638 | break; |
| 7639 | } |
| 7640 | val = (val << 4) | c; |
| 7641 | } |
| 7642 | |
| 7643 | if (s[i] == '{') { |
| 7644 | if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') { |
| 7645 | |
| 7646 | i--; |
| 7647 | k = 0; |
| 7648 | } |
| 7649 | else { |
| 7650 | |
| 7651 | k++; |
| 7652 | } |
| 7653 | } |
| 7654 | if (k) { |
| 7655 | |
| 7656 | if (s[i] == 'x') { |
| 7657 | *p++ = val; |
| 7658 | } |
| 7659 | else { |
| 7660 | p += utf8_fromunicode(p, val); |
| 7661 | } |
| 7662 | i += k; |
| 7663 | break; |
| 7664 | } |
| 7665 | |
| 7666 | *p++ = s[i]; |
| 7667 | } |
| 7668 | break; |
| 7669 | case 'v': |
| 7670 | *p++ = 0xb; |
| @@ -7646,11 +7673,11 @@ | |
| 7673 | case '\0': |
| 7674 | *p++ = '\\'; |
| 7675 | i++; |
| 7676 | break; |
| 7677 | case '\n': |
| 7678 | |
| 7679 | *p++ = ' '; |
| 7680 | do { |
| 7681 | i++; |
| 7682 | } while (s[i + 1] == ' ' || s[i + 1] == '\t'); |
| 7683 | break; |
| @@ -7660,11 +7687,11 @@ | |
| 7687 | case '3': |
| 7688 | case '4': |
| 7689 | case '5': |
| 7690 | case '6': |
| 7691 | case '7': |
| 7692 | |
| 7693 | { |
| 7694 | int val = 0; |
| 7695 | int c = odigitval(s[i + 1]); |
| 7696 | |
| 7697 | val = c; |
| @@ -7708,27 +7735,23 @@ | |
| 7735 | char *token; |
| 7736 | int len; |
| 7737 | |
| 7738 | start = pc->tstart; |
| 7739 | end = pc->tend; |
| 7740 | len = (end - start) + 1; |
| 7741 | if (len < 0) { |
| 7742 | len = 0; |
| 7743 | } |
| 7744 | token = Jim_Alloc(len + 1); |
| 7745 | if (pc->tt != JIM_TT_ESC) { |
| 7746 | |
| 7747 | memcpy(token, start, len); |
| 7748 | token[len] = '\0'; |
| 7749 | } |
| 7750 | else { |
| 7751 | |
| 7752 | len = JimEscape(token, start, len); |
| 7753 | } |
| 7754 | |
| 7755 | return Jim_NewStringObjNoAlloc(interp, token, len); |
| 7756 | } |
| 7757 | |
| @@ -7790,11 +7813,11 @@ | |
| 7813 | while (pc->len) { |
| 7814 | switch (*pc->p) { |
| 7815 | case '\\': |
| 7816 | pc->tt = JIM_TT_ESC; |
| 7817 | if (--pc->len == 0) { |
| 7818 | |
| 7819 | pc->tend = pc->p; |
| 7820 | return JIM_OK; |
| 7821 | } |
| 7822 | pc->p++; |
| 7823 | break; |
| @@ -7826,11 +7849,11 @@ | |
| 7849 | pc->tend = pc->p - 1; |
| 7850 | return JIM_OK; |
| 7851 | } |
| 7852 | if (*pc->p == '\\') { |
| 7853 | if (--pc->len == 0) { |
| 7854 | |
| 7855 | pc->tend = pc->p; |
| 7856 | return JIM_OK; |
| 7857 | } |
| 7858 | pc->tt = JIM_TT_ESC; |
| 7859 | pc->p++; |
| @@ -7846,24 +7869,24 @@ | |
| 7869 | |
| 7870 | Jim_Obj *Jim_NewObj(Jim_Interp *interp) |
| 7871 | { |
| 7872 | Jim_Obj *objPtr; |
| 7873 | |
| 7874 | |
| 7875 | if (interp->freeList != NULL) { |
| 7876 | |
| 7877 | objPtr = interp->freeList; |
| 7878 | interp->freeList = objPtr->nextObjPtr; |
| 7879 | } |
| 7880 | else { |
| 7881 | |
| 7882 | objPtr = Jim_Alloc(sizeof(*objPtr)); |
| 7883 | } |
| 7884 | |
| 7885 | objPtr->refCount = 0; |
| 7886 | |
| 7887 | |
| 7888 | objPtr->prevObjPtr = NULL; |
| 7889 | objPtr->nextObjPtr = interp->liveList; |
| 7890 | if (interp->liveList) |
| 7891 | interp->liveList->prevObjPtr = objPtr; |
| 7892 | interp->liveList = objPtr; |
| @@ -7871,32 +7894,32 @@ | |
| 7894 | return objPtr; |
| 7895 | } |
| 7896 | |
| 7897 | void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr) |
| 7898 | { |
| 7899 | |
| 7900 | JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr, |
| 7901 | objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>")); |
| 7902 | |
| 7903 | |
| 7904 | Jim_FreeIntRep(interp, objPtr); |
| 7905 | |
| 7906 | if (objPtr->bytes != NULL) { |
| 7907 | if (objPtr->bytes != JimEmptyStringRep) |
| 7908 | Jim_Free(objPtr->bytes); |
| 7909 | } |
| 7910 | |
| 7911 | if (objPtr->prevObjPtr) |
| 7912 | objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; |
| 7913 | if (objPtr->nextObjPtr) |
| 7914 | objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; |
| 7915 | if (interp->liveList == objPtr) |
| 7916 | interp->liveList = objPtr->nextObjPtr; |
| 7917 | #ifdef JIM_DISABLE_OBJECT_POOL |
| 7918 | Jim_Free(objPtr); |
| 7919 | #else |
| 7920 | |
| 7921 | objPtr->prevObjPtr = NULL; |
| 7922 | objPtr->nextObjPtr = interp->freeList; |
| 7923 | if (interp->freeList) |
| 7924 | interp->freeList->prevObjPtr = objPtr; |
| 7925 | interp->freeList = objPtr; |
| @@ -7919,45 +7942,44 @@ | |
| 7942 | { |
| 7943 | Jim_Obj *dupPtr; |
| 7944 | |
| 7945 | dupPtr = Jim_NewObj(interp); |
| 7946 | if (objPtr->bytes == NULL) { |
| 7947 | |
| 7948 | dupPtr->bytes = NULL; |
| 7949 | } |
| 7950 | else if (objPtr->length == 0) { |
| 7951 | dupPtr->bytes = JimEmptyStringRep; |
| 7952 | dupPtr->length = 0; |
| 7953 | dupPtr->typePtr = NULL; |
| 7954 | return dupPtr; |
| 7955 | } |
| 7956 | else { |
| 7957 | dupPtr->bytes = Jim_Alloc(objPtr->length + 1); |
| 7958 | dupPtr->length = objPtr->length; |
| 7959 | |
| 7960 | memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1); |
| 7961 | } |
| 7962 | |
| 7963 | |
| 7964 | dupPtr->typePtr = objPtr->typePtr; |
| 7965 | if (objPtr->typePtr != NULL) { |
| 7966 | if (objPtr->typePtr->dupIntRepProc == NULL) { |
| 7967 | dupPtr->internalRep = objPtr->internalRep; |
| 7968 | } |
| 7969 | else { |
| 7970 | |
| 7971 | objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr); |
| 7972 | } |
| 7973 | } |
| 7974 | return dupPtr; |
| 7975 | } |
| 7976 | |
| 7977 | const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr) |
| 7978 | { |
| 7979 | if (objPtr->bytes == NULL) { |
| 7980 | |
| 7981 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 7982 | objPtr->typePtr->updateStringProc(objPtr); |
| 7983 | } |
| 7984 | if (lenPtr) |
| 7985 | *lenPtr = objPtr->length; |
| @@ -7966,25 +7988,22 @@ | |
| 7988 | |
| 7989 | |
| 7990 | int Jim_Length(Jim_Obj *objPtr) |
| 7991 | { |
| 7992 | if (objPtr->bytes == NULL) { |
| 7993 | |
| 7994 | Jim_GetString(objPtr, NULL); |
| 7995 | } |
| 7996 | return objPtr->length; |
| 7997 | } |
| 7998 | |
| 7999 | |
| 8000 | const char *Jim_String(Jim_Obj *objPtr) |
| 8001 | { |
| 8002 | if (objPtr->bytes == NULL) { |
| 8003 | |
| 8004 | Jim_GetString(objPtr, NULL); |
| 8005 | } |
| 8006 | return objPtr->bytes; |
| 8007 | } |
| 8008 | |
| 8009 | static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) |
| @@ -8001,23 +8020,34 @@ | |
| 8020 | FreeDictSubstInternalRep, |
| 8021 | DupDictSubstInternalRep, |
| 8022 | NULL, |
| 8023 | JIM_TYPE_NONE, |
| 8024 | }; |
| 8025 | |
| 8026 | static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 8027 | static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8028 | |
| 8029 | static const Jim_ObjType interpolatedObjType = { |
| 8030 | "interpolated", |
| 8031 | FreeInterpolatedInternalRep, |
| 8032 | DupInterpolatedInternalRep, |
| 8033 | NULL, |
| 8034 | JIM_TYPE_NONE, |
| 8035 | }; |
| 8036 | |
| 8037 | static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8038 | { |
| 8039 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); |
| 8040 | } |
| 8041 | |
| 8042 | static void DupInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 8043 | { |
| 8044 | |
| 8045 | dupPtr->internalRep = srcPtr->internalRep; |
| 8046 | |
| 8047 | Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr); |
| 8048 | } |
| 8049 | |
| 8050 | static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| 8051 | static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8052 | |
| 8053 | static const Jim_ObjType stringObjType = { |
| @@ -8037,22 +8067,22 @@ | |
| 8067 | } |
| 8068 | |
| 8069 | static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 8070 | { |
| 8071 | if (objPtr->typePtr != &stringObjType) { |
| 8072 | |
| 8073 | if (objPtr->bytes == NULL) { |
| 8074 | |
| 8075 | JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); |
| 8076 | objPtr->typePtr->updateStringProc(objPtr); |
| 8077 | } |
| 8078 | |
| 8079 | Jim_FreeIntRep(interp, objPtr); |
| 8080 | |
| 8081 | objPtr->typePtr = &stringObjType; |
| 8082 | objPtr->internalRep.strValue.maxLength = objPtr->length; |
| 8083 | |
| 8084 | objPtr->internalRep.strValue.charLength = -1; |
| 8085 | } |
| 8086 | return JIM_OK; |
| 8087 | } |
| 8088 | |
| @@ -8073,39 +8103,37 @@ | |
| 8103 | |
| 8104 | Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len) |
| 8105 | { |
| 8106 | Jim_Obj *objPtr = Jim_NewObj(interp); |
| 8107 | |
| 8108 | |
| 8109 | if (len == -1) |
| 8110 | len = strlen(s); |
| 8111 | |
| 8112 | if (len == 0) { |
| 8113 | objPtr->bytes = JimEmptyStringRep; |
| 8114 | } |
| 8115 | else { |
| 8116 | objPtr->bytes = Jim_StrDupLen(s, len); |
| 8117 | } |
| 8118 | objPtr->length = len; |
| 8119 | |
| 8120 | |
| 8121 | objPtr->typePtr = NULL; |
| 8122 | return objPtr; |
| 8123 | } |
| 8124 | |
| 8125 | |
| 8126 | Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen) |
| 8127 | { |
| 8128 | #ifdef JIM_UTF8 |
| 8129 | |
| 8130 | int bytelen = utf8_index(s, charlen); |
| 8131 | |
| 8132 | Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen); |
| 8133 | |
| 8134 | |
| 8135 | objPtr->typePtr = &stringObjType; |
| 8136 | objPtr->internalRep.strValue.maxLength = bytelen; |
| 8137 | objPtr->internalRep.strValue.charLength = charlen; |
| 8138 | |
| 8139 | return objPtr; |
| @@ -8132,11 +8160,11 @@ | |
| 8160 | len = strlen(str); |
| 8161 | needlen = objPtr->length + len; |
| 8162 | if (objPtr->internalRep.strValue.maxLength < needlen || |
| 8163 | objPtr->internalRep.strValue.maxLength == 0) { |
| 8164 | needlen *= 2; |
| 8165 | |
| 8166 | if (needlen < 7) { |
| 8167 | needlen = 7; |
| 8168 | } |
| 8169 | if (objPtr->bytes == JimEmptyStringRep) { |
| 8170 | objPtr->bytes = Jim_Alloc(needlen + 1); |
| @@ -8148,11 +8176,11 @@ | |
| 8176 | } |
| 8177 | memcpy(objPtr->bytes + objPtr->length, str, len); |
| 8178 | objPtr->bytes[objPtr->length + len] = '\0'; |
| 8179 | |
| 8180 | if (objPtr->internalRep.strValue.charLength >= 0) { |
| 8181 | |
| 8182 | objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); |
| 8183 | } |
| 8184 | objPtr->length += len; |
| 8185 | } |
| 8186 | |
| @@ -8210,11 +8238,11 @@ | |
| 8238 | int l1, l2; |
| 8239 | const char *s1 = Jim_GetString(firstObjPtr, &l1); |
| 8240 | const char *s2 = Jim_GetString(secondObjPtr, &l2); |
| 8241 | |
| 8242 | if (nocase) { |
| 8243 | |
| 8244 | return JimStringCompareLen(s1, s2, -1, nocase); |
| 8245 | } |
| 8246 | return JimStringCompare(s1, l1, s2, l2); |
| 8247 | } |
| 8248 | |
| @@ -8312,11 +8340,11 @@ | |
| 8340 | |
| 8341 | if (first == 0 && rangeLen == len) { |
| 8342 | return strObjPtr; |
| 8343 | } |
| 8344 | if (len == bytelen) { |
| 8345 | |
| 8346 | return Jim_NewStringObj(interp, str + first, rangeLen); |
| 8347 | } |
| 8348 | return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen); |
| 8349 | #else |
| 8350 | return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr); |
| @@ -8341,19 +8369,19 @@ | |
| 8369 | return strObjPtr; |
| 8370 | } |
| 8371 | |
| 8372 | str = Jim_String(strObjPtr); |
| 8373 | |
| 8374 | |
| 8375 | objPtr = Jim_NewStringObjUtf8(interp, str, first); |
| 8376 | |
| 8377 | |
| 8378 | if (newStrObj) { |
| 8379 | Jim_AppendObj(interp, objPtr, newStrObj); |
| 8380 | } |
| 8381 | |
| 8382 | |
| 8383 | Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1); |
| 8384 | |
| 8385 | return objPtr; |
| 8386 | } |
| 8387 | |
| @@ -8371,12 +8399,10 @@ | |
| 8399 | { |
| 8400 | char *buf; |
| 8401 | int len; |
| 8402 | const char *str; |
| 8403 | |
| 8404 | str = Jim_GetString(strObjPtr, &len); |
| 8405 | |
| 8406 | #ifdef JIM_UTF8 |
| 8407 | len *= 2; |
| 8408 | #endif |
| @@ -8389,14 +8415,10 @@ | |
| 8415 | { |
| 8416 | char *buf; |
| 8417 | const char *str; |
| 8418 | int len; |
| 8419 | |
| 8420 | str = Jim_GetString(strObjPtr, &len); |
| 8421 | |
| 8422 | #ifdef JIM_UTF8 |
| 8423 | len *= 2; |
| 8424 | #endif |
| @@ -8411,13 +8433,11 @@ | |
| 8433 | int len; |
| 8434 | int c; |
| 8435 | const char *str; |
| 8436 | |
| 8437 | str = Jim_GetString(strObjPtr, &len); |
| 8438 | |
| 8439 | #ifdef JIM_UTF8 |
| 8440 | len *= 2; |
| 8441 | #endif |
| 8442 | buf = p = Jim_Alloc(len + 1); |
| 8443 | |
| @@ -8452,11 +8472,11 @@ | |
| 8472 | while (len) { |
| 8473 | int c; |
| 8474 | int n = utf8_tounicode(str, &c); |
| 8475 | |
| 8476 | if (utf8_memchr(trimchars, trimlen, c) == NULL) { |
| 8477 | |
| 8478 | break; |
| 8479 | } |
| 8480 | str += n; |
| 8481 | len -= n; |
| 8482 | } |
| @@ -8523,41 +8543,41 @@ | |
| 8543 | |
| 8544 | len = Jim_Length(strObjPtr); |
| 8545 | nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen); |
| 8546 | |
| 8547 | if (nontrim == NULL) { |
| 8548 | |
| 8549 | return Jim_NewEmptyStringObj(interp); |
| 8550 | } |
| 8551 | if (nontrim == strObjPtr->bytes + len) { |
| 8552 | |
| 8553 | return strObjPtr; |
| 8554 | } |
| 8555 | |
| 8556 | if (Jim_IsShared(strObjPtr)) { |
| 8557 | strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); |
| 8558 | } |
| 8559 | else { |
| 8560 | |
| 8561 | strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0; |
| 8562 | strObjPtr->length = (nontrim - strObjPtr->bytes); |
| 8563 | } |
| 8564 | |
| 8565 | return strObjPtr; |
| 8566 | } |
| 8567 | |
| 8568 | static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) |
| 8569 | { |
| 8570 | |
| 8571 | Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); |
| 8572 | |
| 8573 | |
| 8574 | strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); |
| 8575 | |
| 8576 | |
| 8577 | if (objPtr != strObjPtr && objPtr->refCount == 0) { |
| 8578 | |
| 8579 | Jim_FreeNewObj(interp, objPtr); |
| 8580 | } |
| 8581 | |
| 8582 | return strObjPtr; |
| 8583 | } |
| @@ -8575,17 +8595,17 @@ | |
| 8595 | static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) |
| 8596 | { |
| 8597 | static const char * const strclassnames[] = { |
| 8598 | "integer", "alpha", "alnum", "ascii", "digit", |
| 8599 | "double", "lower", "upper", "space", "xdigit", |
| 8600 | "control", "print", "graph", "punct", "boolean", |
| 8601 | NULL |
| 8602 | }; |
| 8603 | enum { |
| 8604 | STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, |
| 8605 | STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, |
| 8606 | STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT, STR_IS_BOOLEAN, |
| 8607 | }; |
| 8608 | int strclass; |
| 8609 | int len; |
| 8610 | int i; |
| 8611 | const char *str; |
| @@ -8613,10 +8633,17 @@ | |
| 8633 | { |
| 8634 | double d; |
| 8635 | Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); |
| 8636 | return JIM_OK; |
| 8637 | } |
| 8638 | |
| 8639 | case STR_IS_BOOLEAN: |
| 8640 | { |
| 8641 | int b; |
| 8642 | Jim_SetResultBool(interp, Jim_GetBoolean(interp, strObjPtr, &b) == JIM_OK); |
| 8643 | return JIM_OK; |
| 8644 | } |
| 8645 | |
| 8646 | case STR_IS_ALPHA: isclassfunc = isalpha; break; |
| 8647 | case STR_IS_ALNUM: isclassfunc = isalnum; break; |
| 8648 | case STR_IS_ASCII: isclassfunc = jim_isascii; break; |
| 8649 | case STR_IS_DIGIT: isclassfunc = isdigit; break; |
| @@ -8631,11 +8658,11 @@ | |
| 8658 | default: |
| 8659 | return JIM_ERR; |
| 8660 | } |
| 8661 | |
| 8662 | for (i = 0; i < len; i++) { |
| 8663 | if (!isclassfunc(UCHAR(str[i]))) { |
| 8664 | Jim_SetResultBool(interp, 0); |
| 8665 | return JIM_OK; |
| 8666 | } |
| 8667 | } |
| 8668 | Jim_SetResultBool(interp, 1); |
| @@ -8656,20 +8683,18 @@ | |
| 8683 | { |
| 8684 | if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { |
| 8685 | return 1; |
| 8686 | } |
| 8687 | else { |
| 8688 | if (strcmp(str, Jim_String(objPtr)) != 0) |
| 8689 | return 0; |
| 8690 | |
| 8691 | if (objPtr->typePtr != &comparedStringObjType) { |
| 8692 | Jim_FreeIntRep(interp, objPtr); |
| 8693 | objPtr->typePtr = &comparedStringObjType; |
| 8694 | } |
| 8695 | objPtr->internalRep.ptr = (char *)str; |
| 8696 | return 1; |
| 8697 | } |
| 8698 | } |
| 8699 | |
| 8700 | static int qsortCompareStringPointers(const void *a, const void *b) |
| @@ -8758,20 +8783,20 @@ | |
| 8783 | int type; |
| 8784 | } ScriptToken; |
| 8785 | |
| 8786 | typedef struct ScriptObj |
| 8787 | { |
| 8788 | ScriptToken *token; |
| 8789 | Jim_Obj *fileNameObj; |
| 8790 | int len; |
| 8791 | int substFlags; |
| 8792 | int inUse; /* Used to share a ScriptObj. Currently |
| 8793 | only used by Jim_EvalObj() as protection against |
| 8794 | shimmering of the currently evaluated object. */ |
| 8795 | int firstline; |
| 8796 | int linenr; |
| 8797 | int missing; |
| 8798 | } ScriptObj; |
| 8799 | |
| 8800 | static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 8801 | static int JimParseCheckMissing(Jim_Interp *interp, int ch); |
| 8802 | static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr); |
| @@ -8799,23 +8824,23 @@ | |
| 8824 | dupPtr->typePtr = NULL; |
| 8825 | } |
| 8826 | |
| 8827 | typedef struct |
| 8828 | { |
| 8829 | const char *token; |
| 8830 | int len; |
| 8831 | int type; |
| 8832 | int line; |
| 8833 | } ParseToken; |
| 8834 | |
| 8835 | typedef struct |
| 8836 | { |
| 8837 | |
| 8838 | ParseToken *list; |
| 8839 | int size; |
| 8840 | int count; |
| 8841 | ParseToken static_list[20]; |
| 8842 | } ParseTokenList; |
| 8843 | |
| 8844 | static void ScriptTokenListInit(ParseTokenList *tokenlist) |
| 8845 | { |
| 8846 | tokenlist->list = tokenlist->static_list; |
| @@ -8834,18 +8859,18 @@ | |
| 8859 | int line) |
| 8860 | { |
| 8861 | ParseToken *t; |
| 8862 | |
| 8863 | if (tokenlist->count == tokenlist->size) { |
| 8864 | |
| 8865 | tokenlist->size *= 2; |
| 8866 | if (tokenlist->list != tokenlist->static_list) { |
| 8867 | tokenlist->list = |
| 8868 | Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list)); |
| 8869 | } |
| 8870 | else { |
| 8871 | |
| 8872 | tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list)); |
| 8873 | memcpy(tokenlist->list, tokenlist->static_list, |
| 8874 | tokenlist->count * sizeof(*tokenlist->list)); |
| 8875 | } |
| 8876 | } |
| @@ -8854,25 +8879,32 @@ | |
| 8879 | t->len = len; |
| 8880 | t->type = type; |
| 8881 | t->line = line; |
| 8882 | } |
| 8883 | |
| 8884 | static int JimCountWordTokens(struct ScriptObj *script, ParseToken *t) |
| 8885 | { |
| 8886 | int expand = 1; |
| 8887 | int count = 0; |
| 8888 | |
| 8889 | |
| 8890 | if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { |
| 8891 | if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { |
| 8892 | |
| 8893 | expand = -1; |
| 8894 | t++; |
| 8895 | } |
| 8896 | else { |
| 8897 | if (script->missing == ' ') { |
| 8898 | |
| 8899 | script->missing = '}'; |
| 8900 | script->linenr = t[1].line; |
| 8901 | } |
| 8902 | } |
| 8903 | } |
| 8904 | |
| 8905 | |
| 8906 | while (!TOKEN_IS_SEP(t->type)) { |
| 8907 | t++; |
| 8908 | count++; |
| 8909 | } |
| 8910 | |
| @@ -8882,11 +8914,11 @@ | |
| 8914 | static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t) |
| 8915 | { |
| 8916 | Jim_Obj *objPtr; |
| 8917 | |
| 8918 | if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) { |
| 8919 | |
| 8920 | int len = t->len; |
| 8921 | char *str = Jim_Alloc(len + 1); |
| 8922 | len = JimEscape(str, t->token, len); |
| 8923 | objPtr = Jim_NewStringObjNoAlloc(interp, str, len); |
| 8924 | } |
| @@ -8899,13 +8931,13 @@ | |
| 8931 | static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, |
| 8932 | ParseTokenList *tokenlist) |
| 8933 | { |
| 8934 | int i; |
| 8935 | struct ScriptToken *token; |
| 8936 | |
| 8937 | int lineargs = 0; |
| 8938 | |
| 8939 | ScriptToken *linefirst; |
| 8940 | int count; |
| 8941 | int linenr; |
| 8942 | |
| 8943 | #ifdef DEBUG_SHOW_SCRIPT_TOKENS |
| @@ -8914,11 +8946,11 @@ | |
| 8946 | printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type), |
| 8947 | tokenlist->list[i].len, tokenlist->list[i].token); |
| 8948 | } |
| 8949 | #endif |
| 8950 | |
| 8951 | |
| 8952 | count = tokenlist->count; |
| 8953 | for (i = 0; i < tokenlist->count; i++) { |
| 8954 | if (tokenlist->list[i].type == JIM_TT_EOL) { |
| 8955 | count++; |
| 8956 | } |
| @@ -8925,59 +8957,59 @@ | |
| 8957 | } |
| 8958 | linenr = script->firstline = tokenlist->list[0].line; |
| 8959 | |
| 8960 | token = script->token = Jim_Alloc(sizeof(ScriptToken) * count); |
| 8961 | |
| 8962 | |
| 8963 | linefirst = token++; |
| 8964 | |
| 8965 | for (i = 0; i < tokenlist->count; ) { |
| 8966 | |
| 8967 | int wordtokens; |
| 8968 | |
| 8969 | |
| 8970 | while (tokenlist->list[i].type == JIM_TT_SEP) { |
| 8971 | i++; |
| 8972 | } |
| 8973 | |
| 8974 | wordtokens = JimCountWordTokens(script, tokenlist->list + i); |
| 8975 | |
| 8976 | if (wordtokens == 0) { |
| 8977 | |
| 8978 | if (lineargs) { |
| 8979 | linefirst->type = JIM_TT_LINE; |
| 8980 | linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); |
| 8981 | Jim_IncrRefCount(linefirst->objPtr); |
| 8982 | |
| 8983 | |
| 8984 | lineargs = 0; |
| 8985 | linefirst = token++; |
| 8986 | } |
| 8987 | i++; |
| 8988 | continue; |
| 8989 | } |
| 8990 | else if (wordtokens != 1) { |
| 8991 | |
| 8992 | token->type = JIM_TT_WORD; |
| 8993 | token->objPtr = Jim_NewIntObj(interp, wordtokens); |
| 8994 | Jim_IncrRefCount(token->objPtr); |
| 8995 | token++; |
| 8996 | if (wordtokens < 0) { |
| 8997 | |
| 8998 | i++; |
| 8999 | wordtokens = -wordtokens - 1; |
| 9000 | lineargs--; |
| 9001 | } |
| 9002 | } |
| 9003 | |
| 9004 | if (lineargs == 0) { |
| 9005 | |
| 9006 | linenr = tokenlist->list[i].line; |
| 9007 | } |
| 9008 | lineargs++; |
| 9009 | |
| 9010 | |
| 9011 | while (wordtokens--) { |
| 9012 | const ParseToken *t = &tokenlist->list[i++]; |
| 9013 | |
| 9014 | token->type = t->type; |
| 9015 | token->objPtr = JimMakeScriptObj(interp, t); |
| @@ -9010,11 +9042,11 @@ | |
| 9042 | { |
| 9043 | ScriptObj *script = JimGetScript(interp, scriptObj); |
| 9044 | if (stateCharPtr) { |
| 9045 | *stateCharPtr = script->missing; |
| 9046 | } |
| 9047 | return script->missing == ' ' || script->missing == '}'; |
| 9048 | } |
| 9049 | |
| 9050 | static int JimParseCheckMissing(Jim_Interp *interp, int ch) |
| 9051 | { |
| 9052 | const char *msg; |
| @@ -9028,10 +9060,13 @@ | |
| 9060 | msg = "unmatched \"[\""; |
| 9061 | break; |
| 9062 | case '{': |
| 9063 | msg = "missing close-brace"; |
| 9064 | break; |
| 9065 | case '}': |
| 9066 | msg = "extra characters after close-brace"; |
| 9067 | break; |
| 9068 | case '"': |
| 9069 | default: |
| 9070 | msg = "missing quote"; |
| 9071 | break; |
| 9072 | } |
| @@ -9049,11 +9084,11 @@ | |
| 9084 | token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count); |
| 9085 | |
| 9086 | for (i = 0; i < tokenlist->count; i++) { |
| 9087 | const ParseToken *t = &tokenlist->list[i]; |
| 9088 | |
| 9089 | |
| 9090 | token->type = t->type; |
| 9091 | token->objPtr = JimMakeScriptObj(interp, t); |
| 9092 | Jim_IncrRefCount(token->objPtr); |
| 9093 | token++; |
| 9094 | } |
| @@ -9068,29 +9103,29 @@ | |
| 9103 | struct JimParserCtx parser; |
| 9104 | struct ScriptObj *script; |
| 9105 | ParseTokenList tokenlist; |
| 9106 | int line = 1; |
| 9107 | |
| 9108 | |
| 9109 | if (objPtr->typePtr == &sourceObjType) { |
| 9110 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 9111 | } |
| 9112 | |
| 9113 | |
| 9114 | ScriptTokenListInit(&tokenlist); |
| 9115 | |
| 9116 | JimParserInit(&parser, scriptText, scriptTextLen, line); |
| 9117 | while (!parser.eof) { |
| 9118 | JimParseScript(&parser); |
| 9119 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 9120 | parser.tline); |
| 9121 | } |
| 9122 | |
| 9123 | |
| 9124 | ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); |
| 9125 | |
| 9126 | |
| 9127 | script = Jim_Alloc(sizeof(*script)); |
| 9128 | memset(script, 0, sizeof(*script)); |
| 9129 | script->inUse = 1; |
| 9130 | if (objPtr->typePtr == &sourceObjType) { |
| 9131 | script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| @@ -9102,14 +9137,14 @@ | |
| 9137 | script->missing = parser.missing.ch; |
| 9138 | script->linenr = parser.missing.line; |
| 9139 | |
| 9140 | ScriptObjAddTokens(interp, script, &tokenlist); |
| 9141 | |
| 9142 | |
| 9143 | ScriptTokenListFree(&tokenlist); |
| 9144 | |
| 9145 | |
| 9146 | Jim_FreeIntRep(interp, objPtr); |
| 9147 | Jim_SetIntRepPtr(objPtr, script); |
| 9148 | objPtr->typePtr = &scriptObjType; |
| 9149 | } |
| 9150 | |
| @@ -9116,11 +9151,11 @@ | |
| 9151 | static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script); |
| 9152 | |
| 9153 | static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr) |
| 9154 | { |
| 9155 | if (objPtr == interp->emptyObj) { |
| 9156 | |
| 9157 | objPtr = interp->nullScriptObj; |
| 9158 | } |
| 9159 | |
| 9160 | if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { |
| 9161 | JimSetScriptFromAny(interp, objPtr); |
| @@ -9155,67 +9190,66 @@ | |
| 9190 | Jim_FreeHashTable(cmdPtr->u.proc.staticVars); |
| 9191 | Jim_Free(cmdPtr->u.proc.staticVars); |
| 9192 | } |
| 9193 | } |
| 9194 | else { |
| 9195 | |
| 9196 | if (cmdPtr->u.native.delProc) { |
| 9197 | cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData); |
| 9198 | } |
| 9199 | } |
| 9200 | if (cmdPtr->prevCmd) { |
| 9201 | |
| 9202 | JimDecrCmdRefCount(interp, cmdPtr->prevCmd); |
| 9203 | } |
| 9204 | Jim_Free(cmdPtr); |
| 9205 | } |
| 9206 | } |
| 9207 | |
| 9208 | static void JimVariablesHTValDestructor(void *interp, void *val) |
| 9209 | { |
| 9210 | Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr); |
| 9211 | Jim_Free(val); |
| 9212 | } |
| 9213 | |
| 9214 | static const Jim_HashTableType JimVariablesHashTableType = { |
| 9215 | JimStringCopyHTHashFunction, |
| 9216 | JimStringCopyHTDup, |
| 9217 | NULL, |
| 9218 | JimStringCopyHTKeyCompare, |
| 9219 | JimStringCopyHTKeyDestructor, |
| 9220 | JimVariablesHTValDestructor |
| 9221 | }; |
| 9222 | |
| 9223 | static void JimCommandsHT_ValDestructor(void *interp, void *val) |
| 9224 | { |
| 9225 | JimDecrCmdRefCount(interp, val); |
| 9226 | } |
| 9227 | |
| 9228 | static const Jim_HashTableType JimCommandsHashTableType = { |
| 9229 | JimStringCopyHTHashFunction, |
| 9230 | JimStringCopyHTDup, |
| 9231 | NULL, |
| 9232 | JimStringCopyHTKeyCompare, |
| 9233 | JimStringCopyHTKeyDestructor, |
| 9234 | JimCommandsHT_ValDestructor |
| 9235 | }; |
| 9236 | |
| 9237 | |
| 9238 | |
| 9239 | #ifdef jim_ext_namespace |
| 9240 | static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj) |
| 9241 | { |
| 9242 | const char *name = Jim_String(nsObj); |
| 9243 | if (name[0] == ':' && name[1] == ':') { |
| 9244 | |
| 9245 | while (*++name == ':') { |
| 9246 | } |
| 9247 | nsObj = Jim_NewStringObj(interp, name, -1); |
| 9248 | } |
| 9249 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9250 | |
| 9251 | nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9252 | Jim_AppendStrings(interp, nsObj, "::", name, NULL); |
| 9253 | } |
| 9254 | return nsObj; |
| 9255 | } |
| @@ -9239,16 +9273,16 @@ | |
| 9273 | static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) |
| 9274 | { |
| 9275 | Jim_Obj *objPtr = interp->emptyObj; |
| 9276 | |
| 9277 | if (name[0] == ':' && name[1] == ':') { |
| 9278 | |
| 9279 | while (*++name == ':') { |
| 9280 | } |
| 9281 | } |
| 9282 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9283 | |
| 9284 | objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9285 | Jim_AppendStrings(interp, objPtr, "::", name, NULL); |
| 9286 | name = Jim_String(objPtr); |
| 9287 | } |
| 9288 | Jim_IncrRefCount(objPtr); |
| @@ -9257,11 +9291,11 @@ | |
| 9291 | } |
| 9292 | |
| 9293 | #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ)) |
| 9294 | |
| 9295 | #else |
| 9296 | |
| 9297 | #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) |
| 9298 | #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) |
| 9299 | |
| 9300 | Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) |
| 9301 | { |
| @@ -9276,17 +9310,17 @@ | |
| 9310 | |
| 9311 | Jim_InterpIncrProcEpoch(interp); |
| 9312 | } |
| 9313 | |
| 9314 | if (he && interp->local) { |
| 9315 | |
| 9316 | cmd->prevCmd = Jim_GetHashEntryVal(he); |
| 9317 | Jim_SetHashVal(&interp->commands, he, cmd); |
| 9318 | } |
| 9319 | else { |
| 9320 | if (he) { |
| 9321 | |
| 9322 | Jim_DeleteHashEntry(&interp->commands, name); |
| 9323 | } |
| 9324 | |
| 9325 | Jim_AddHashEntry(&interp->commands, name, cmd); |
| 9326 | } |
| @@ -9297,11 +9331,11 @@ | |
| 9331 | int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr, |
| 9332 | Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc) |
| 9333 | { |
| 9334 | Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); |
| 9335 | |
| 9336 | |
| 9337 | memset(cmdPtr, 0, sizeof(*cmdPtr)); |
| 9338 | cmdPtr->inUse = 1; |
| 9339 | cmdPtr->u.native.delProc = delProc; |
| 9340 | cmdPtr->u.native.cmdProc = cmdProc; |
| 9341 | cmdPtr->u.native.privData = privData; |
| @@ -9326,11 +9360,11 @@ | |
| 9360 | Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; |
| 9361 | Jim_Var *varPtr; |
| 9362 | int subLen; |
| 9363 | |
| 9364 | objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); |
| 9365 | |
| 9366 | subLen = Jim_ListLength(interp, objPtr); |
| 9367 | if (subLen == 1 || subLen == 2) { |
| 9368 | nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); |
| 9369 | if (subLen == 1) { |
| 9370 | initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); |
| @@ -9372,19 +9406,19 @@ | |
| 9406 | |
| 9407 | static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname) |
| 9408 | { |
| 9409 | #ifdef jim_ext_namespace |
| 9410 | if (cmdPtr->isproc) { |
| 9411 | |
| 9412 | const char *pt = strrchr(cmdname, ':'); |
| 9413 | if (pt && pt != cmdname && pt[-1] == ':') { |
| 9414 | Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); |
| 9415 | cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1); |
| 9416 | Jim_IncrRefCount(cmdPtr->u.proc.nsObj); |
| 9417 | |
| 9418 | if (Jim_FindHashEntry(&interp->commands, pt + 1)) { |
| 9419 | |
| 9420 | Jim_InterpIncrProcEpoch(interp); |
| 9421 | } |
| 9422 | } |
| 9423 | } |
| 9424 | #endif |
| @@ -9397,11 +9431,11 @@ | |
| 9431 | int argListLen; |
| 9432 | int i; |
| 9433 | |
| 9434 | argListLen = Jim_ListLength(interp, argListObjPtr); |
| 9435 | |
| 9436 | |
| 9437 | cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); |
| 9438 | memset(cmdPtr, 0, sizeof(*cmdPtr)); |
| 9439 | cmdPtr->inUse = 1; |
| 9440 | cmdPtr->isproc = 1; |
| 9441 | cmdPtr->u.proc.argListObjPtr = argListObjPtr; |
| @@ -9412,24 +9446,24 @@ | |
| 9446 | cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj; |
| 9447 | Jim_IncrRefCount(argListObjPtr); |
| 9448 | Jim_IncrRefCount(bodyObjPtr); |
| 9449 | Jim_IncrRefCount(cmdPtr->u.proc.nsObj); |
| 9450 | |
| 9451 | |
| 9452 | if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) { |
| 9453 | goto err; |
| 9454 | } |
| 9455 | |
| 9456 | |
| 9457 | |
| 9458 | for (i = 0; i < argListLen; i++) { |
| 9459 | Jim_Obj *argPtr; |
| 9460 | Jim_Obj *nameObjPtr; |
| 9461 | Jim_Obj *defaultObjPtr; |
| 9462 | int len; |
| 9463 | |
| 9464 | |
| 9465 | argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); |
| 9466 | len = Jim_ListLength(interp, argPtr); |
| 9467 | if (len == 0) { |
| 9468 | Jim_SetResultString(interp, "argument with no name", -1); |
| 9469 | err: |
| @@ -9440,16 +9474,16 @@ | |
| 9474 | Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr); |
| 9475 | goto err; |
| 9476 | } |
| 9477 | |
| 9478 | if (len == 2) { |
| 9479 | |
| 9480 | nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); |
| 9481 | defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); |
| 9482 | } |
| 9483 | else { |
| 9484 | |
| 9485 | nameObjPtr = argPtr; |
| 9486 | defaultObjPtr = NULL; |
| 9487 | } |
| 9488 | |
| 9489 | |
| @@ -9510,29 +9544,29 @@ | |
| 9544 | } |
| 9545 | |
| 9546 | fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj); |
| 9547 | fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj); |
| 9548 | |
| 9549 | |
| 9550 | he = Jim_FindHashEntry(&interp->commands, fqold); |
| 9551 | if (he == NULL) { |
| 9552 | Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName); |
| 9553 | } |
| 9554 | else if (Jim_FindHashEntry(&interp->commands, fqnew)) { |
| 9555 | Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); |
| 9556 | } |
| 9557 | else { |
| 9558 | |
| 9559 | cmdPtr = Jim_GetHashEntryVal(he); |
| 9560 | JimIncrCmdRefCount(cmdPtr); |
| 9561 | JimUpdateProcNamespace(interp, cmdPtr, fqnew); |
| 9562 | Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); |
| 9563 | |
| 9564 | |
| 9565 | Jim_DeleteHashEntry(&interp->commands, fqold); |
| 9566 | |
| 9567 | |
| 9568 | Jim_InterpIncrProcEpoch(interp); |
| 9569 | |
| 9570 | ret = JIM_OK; |
| 9571 | } |
| 9572 | |
| @@ -9571,23 +9605,23 @@ | |
| 9605 | objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch |
| 9606 | #ifdef jim_ext_namespace |
| 9607 | || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj) |
| 9608 | #endif |
| 9609 | ) { |
| 9610 | |
| 9611 | |
| 9612 | |
| 9613 | const char *name = Jim_String(objPtr); |
| 9614 | Jim_HashEntry *he; |
| 9615 | |
| 9616 | if (name[0] == ':' && name[1] == ':') { |
| 9617 | while (*++name == ':') { |
| 9618 | } |
| 9619 | } |
| 9620 | #ifdef jim_ext_namespace |
| 9621 | else if (Jim_Length(interp->framePtr->nsObj)) { |
| 9622 | |
| 9623 | Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); |
| 9624 | Jim_AppendStrings(interp, nameObj, "::", name, NULL); |
| 9625 | he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj)); |
| 9626 | Jim_FreeNewObj(interp, nameObj); |
| 9627 | if (he) { |
| @@ -9594,11 +9628,11 @@ | |
| 9628 | goto found; |
| 9629 | } |
| 9630 | } |
| 9631 | #endif |
| 9632 | |
| 9633 | |
| 9634 | he = Jim_FindHashEntry(&interp->commands, name); |
| 9635 | if (he == NULL) { |
| 9636 | if (flags & JIM_ERRMSG) { |
| 9637 | Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); |
| 9638 | } |
| @@ -9607,11 +9641,11 @@ | |
| 9641 | #ifdef jim_ext_namespace |
| 9642 | found: |
| 9643 | #endif |
| 9644 | cmd = Jim_GetHashEntryVal(he); |
| 9645 | |
| 9646 | |
| 9647 | Jim_FreeIntRep(interp, objPtr); |
| 9648 | objPtr->typePtr = &commandObjType; |
| 9649 | objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; |
| 9650 | objPtr->internalRep.cmdValue.cmdPtr = cmd; |
| 9651 | objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj; |
| @@ -9626,11 +9660,11 @@ | |
| 9660 | return cmd; |
| 9661 | } |
| 9662 | |
| 9663 | |
| 9664 | |
| 9665 | #define JIM_DICT_SUGAR 100 |
| 9666 | |
| 9667 | static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); |
| 9668 | |
| 9669 | static const Jim_ObjType variableObjType = { |
| 9670 | "variable", |
| @@ -9640,11 +9674,11 @@ | |
| 9674 | JIM_TYPE_REFERENCES, |
| 9675 | }; |
| 9676 | |
| 9677 | static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) |
| 9678 | { |
| 9679 | |
| 9680 | if (nameObjPtr->typePtr != &variableObjType) { |
| 9681 | int len; |
| 9682 | const char *str = Jim_GetString(nameObjPtr, &len); |
| 9683 | if (memchr(str, '\0', len)) { |
| 9684 | Jim_SetResultFormatted(interp, "%s name contains embedded null", type); |
| @@ -9660,18 +9694,18 @@ | |
| 9694 | Jim_CallFrame *framePtr; |
| 9695 | Jim_HashEntry *he; |
| 9696 | int global; |
| 9697 | int len; |
| 9698 | |
| 9699 | |
| 9700 | if (objPtr->typePtr == &variableObjType) { |
| 9701 | framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr; |
| 9702 | if (objPtr->internalRep.varValue.callFrameId == framePtr->id) { |
| 9703 | |
| 9704 | return JIM_OK; |
| 9705 | } |
| 9706 | |
| 9707 | } |
| 9708 | else if (objPtr->typePtr == &dictSubstObjType) { |
| 9709 | return JIM_DICT_SUGAR; |
| 9710 | } |
| 9711 | else if (JimValidName(interp, "variable", objPtr) != JIM_OK) { |
| @@ -9679,11 +9713,11 @@ | |
| 9713 | } |
| 9714 | |
| 9715 | |
| 9716 | varName = Jim_GetString(objPtr, &len); |
| 9717 | |
| 9718 | |
| 9719 | if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) { |
| 9720 | return JIM_DICT_SUGAR; |
| 9721 | } |
| 9722 | |
| 9723 | if (varName[0] == ':' && varName[1] == ':') { |
| @@ -9695,23 +9729,23 @@ | |
| 9729 | else { |
| 9730 | global = 0; |
| 9731 | framePtr = interp->framePtr; |
| 9732 | } |
| 9733 | |
| 9734 | |
| 9735 | he = Jim_FindHashEntry(&framePtr->vars, varName); |
| 9736 | if (he == NULL) { |
| 9737 | if (!global && framePtr->staticVars) { |
| 9738 | |
| 9739 | he = Jim_FindHashEntry(framePtr->staticVars, varName); |
| 9740 | } |
| 9741 | if (he == NULL) { |
| 9742 | return JIM_ERR; |
| 9743 | } |
| 9744 | } |
| 9745 | |
| 9746 | |
| 9747 | Jim_FreeIntRep(interp, objPtr); |
| 9748 | objPtr->typePtr = &variableObjType; |
| 9749 | objPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9750 | objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); |
| 9751 | objPtr->internalRep.varValue.global = global; |
| @@ -9726,11 +9760,11 @@ | |
| 9760 | { |
| 9761 | const char *name; |
| 9762 | Jim_CallFrame *framePtr; |
| 9763 | int global; |
| 9764 | |
| 9765 | |
| 9766 | Jim_Var *var = Jim_Alloc(sizeof(*var)); |
| 9767 | |
| 9768 | var->objPtr = valObjPtr; |
| 9769 | Jim_IncrRefCount(valObjPtr); |
| 9770 | var->linkFramePtr = NULL; |
| @@ -9745,14 +9779,14 @@ | |
| 9779 | else { |
| 9780 | framePtr = interp->framePtr; |
| 9781 | global = 0; |
| 9782 | } |
| 9783 | |
| 9784 | |
| 9785 | Jim_AddHashEntry(&framePtr->vars, name, var); |
| 9786 | |
| 9787 | |
| 9788 | Jim_FreeIntRep(interp, nameObjPtr); |
| 9789 | nameObjPtr->typePtr = &variableObjType; |
| 9790 | nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; |
| 9791 | nameObjPtr->internalRep.varValue.varPtr = var; |
| 9792 | nameObjPtr->internalRep.varValue.global = global; |
| @@ -9782,11 +9816,11 @@ | |
| 9816 | if (var->linkFramePtr == NULL) { |
| 9817 | Jim_IncrRefCount(valObjPtr); |
| 9818 | Jim_DecrRefCount(interp, var->objPtr); |
| 9819 | var->objPtr = valObjPtr; |
| 9820 | } |
| 9821 | else { |
| 9822 | Jim_CallFrame *savedCallFrame; |
| 9823 | |
| 9824 | savedCallFrame = interp->framePtr; |
| 9825 | interp->framePtr = var->linkFramePtr; |
| 9826 | err = Jim_SetVariable(interp, var->objPtr, valObjPtr); |
| @@ -9822,19 +9856,16 @@ | |
| 9856 | return result; |
| 9857 | } |
| 9858 | |
| 9859 | int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) |
| 9860 | { |
| 9861 | Jim_Obj *valObjPtr; |
| 9862 | int result; |
| 9863 | |
| 9864 | valObjPtr = Jim_NewStringObj(interp, val, -1); |
| 9865 | Jim_IncrRefCount(valObjPtr); |
| 9866 | result = Jim_SetVariableStr(interp, name, valObjPtr); |
| 9867 | Jim_DecrRefCount(interp, valObjPtr); |
| 9868 | return result; |
| 9869 | } |
| 9870 | |
| 9871 | int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, |
| @@ -9843,14 +9874,14 @@ | |
| 9874 | const char *varName; |
| 9875 | const char *targetName; |
| 9876 | Jim_CallFrame *framePtr; |
| 9877 | Jim_Var *varPtr; |
| 9878 | |
| 9879 | |
| 9880 | switch (SetVariableFromAny(interp, nameObjPtr)) { |
| 9881 | case JIM_DICT_SUGAR: |
| 9882 | |
| 9883 | Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr); |
| 9884 | return JIM_ERR; |
| 9885 | |
| 9886 | case JIM_OK: |
| 9887 | varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| @@ -9858,23 +9889,23 @@ | |
| 9889 | if (varPtr->linkFramePtr == NULL) { |
| 9890 | Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); |
| 9891 | return JIM_ERR; |
| 9892 | } |
| 9893 | |
| 9894 | |
| 9895 | varPtr->linkFramePtr = NULL; |
| 9896 | break; |
| 9897 | } |
| 9898 | |
| 9899 | |
| 9900 | |
| 9901 | varName = Jim_String(nameObjPtr); |
| 9902 | |
| 9903 | if (varName[0] == ':' && varName[1] == ':') { |
| 9904 | while (*++varName == ':') { |
| 9905 | } |
| 9906 | |
| 9907 | framePtr = interp->topFramePtr; |
| 9908 | } |
| 9909 | else { |
| 9910 | framePtr = interp->framePtr; |
| 9911 | } |
| @@ -9894,15 +9925,15 @@ | |
| 9925 | nameObjPtr); |
| 9926 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9927 | return JIM_ERR; |
| 9928 | } |
| 9929 | |
| 9930 | |
| 9931 | if (framePtr == targetCallFrame) { |
| 9932 | Jim_Obj *objPtr = targetNameObjPtr; |
| 9933 | |
| 9934 | |
| 9935 | while (1) { |
| 9936 | if (strcmp(Jim_String(objPtr), varName) == 0) { |
| 9937 | Jim_SetResultString(interp, "can't upvar from variable to itself", -1); |
| 9938 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9939 | return JIM_ERR; |
| @@ -9914,13 +9945,13 @@ | |
| 9945 | break; |
| 9946 | objPtr = varPtr->objPtr; |
| 9947 | } |
| 9948 | } |
| 9949 | |
| 9950 | |
| 9951 | Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); |
| 9952 | |
| 9953 | nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; |
| 9954 | Jim_DecrRefCount(interp, targetNameObjPtr); |
| 9955 | return JIM_OK; |
| 9956 | } |
| 9957 | |
| @@ -9934,26 +9965,26 @@ | |
| 9965 | return varPtr->objPtr; |
| 9966 | } |
| 9967 | else { |
| 9968 | Jim_Obj *objPtr; |
| 9969 | |
| 9970 | |
| 9971 | Jim_CallFrame *savedCallFrame = interp->framePtr; |
| 9972 | |
| 9973 | interp->framePtr = varPtr->linkFramePtr; |
| 9974 | objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); |
| 9975 | interp->framePtr = savedCallFrame; |
| 9976 | if (objPtr) { |
| 9977 | return objPtr; |
| 9978 | } |
| 9979 | |
| 9980 | } |
| 9981 | } |
| 9982 | break; |
| 9983 | |
| 9984 | case JIM_DICT_SUGAR: |
| 9985 | |
| 9986 | return JimDictSugarGet(interp, nameObjPtr, flags); |
| 9987 | } |
| 9988 | if (flags & JIM_ERRMSG) { |
| 9989 | Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr); |
| 9990 | } |
| @@ -10003,17 +10034,17 @@ | |
| 10034 | int retval; |
| 10035 | Jim_CallFrame *framePtr; |
| 10036 | |
| 10037 | retval = SetVariableFromAny(interp, nameObjPtr); |
| 10038 | if (retval == JIM_DICT_SUGAR) { |
| 10039 | |
| 10040 | return JimDictSugarSet(interp, nameObjPtr, NULL); |
| 10041 | } |
| 10042 | else if (retval == JIM_OK) { |
| 10043 | varPtr = nameObjPtr->internalRep.varValue.varPtr; |
| 10044 | |
| 10045 | |
| 10046 | if (varPtr->linkFramePtr) { |
| 10047 | framePtr = interp->framePtr; |
| 10048 | interp->framePtr = varPtr->linkFramePtr; |
| 10049 | retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); |
| 10050 | interp->framePtr = framePtr; |
| @@ -10028,11 +10059,11 @@ | |
| 10059 | framePtr = interp->framePtr; |
| 10060 | } |
| 10061 | |
| 10062 | retval = Jim_DeleteHashEntry(&framePtr->vars, name); |
| 10063 | if (retval == JIM_OK) { |
| 10064 | |
| 10065 | framePtr->id = interp->callFrameEpoch++; |
| 10066 | } |
| 10067 | } |
| 10068 | } |
| 10069 | if (retval != JIM_OK && (flags & JIM_ERRMSG)) { |
| @@ -10061,11 +10092,11 @@ | |
| 10092 | keyLen = (str + len) - p; |
| 10093 | if (str[len - 1] == ')') { |
| 10094 | keyLen--; |
| 10095 | } |
| 10096 | |
| 10097 | |
| 10098 | keyObjPtr = Jim_NewStringObj(interp, p, keyLen); |
| 10099 | |
| 10100 | Jim_IncrRefCount(varObjPtr); |
| 10101 | Jim_IncrRefCount(keyObjPtr); |
| 10102 | *varPtrPtr = varObjPtr; |
| @@ -10080,23 +10111,23 @@ | |
| 10111 | |
| 10112 | err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, |
| 10113 | &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST); |
| 10114 | |
| 10115 | if (err == JIM_OK) { |
| 10116 | |
| 10117 | Jim_SetEmptyResult(interp); |
| 10118 | } |
| 10119 | else { |
| 10120 | if (!valObjPtr) { |
| 10121 | |
| 10122 | if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) { |
| 10123 | Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array", |
| 10124 | objPtr); |
| 10125 | return err; |
| 10126 | } |
| 10127 | } |
| 10128 | |
| 10129 | Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array", |
| 10130 | (valObjPtr ? "set" : "unset"), objPtr); |
| 10131 | } |
| 10132 | return err; |
| 10133 | } |
| @@ -10118,11 +10149,11 @@ | |
| 10149 | Jim_SetResultFormatted(interp, |
| 10150 | "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, |
| 10151 | ret < 0 ? "variable isn't" : "no such element in"); |
| 10152 | } |
| 10153 | else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { |
| 10154 | |
| 10155 | Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); |
| 10156 | } |
| 10157 | |
| 10158 | return resObjPtr; |
| 10159 | } |
| @@ -10143,28 +10174,27 @@ | |
| 10174 | { |
| 10175 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); |
| 10176 | Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); |
| 10177 | } |
| 10178 | |
| 10179 | static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 10180 | { |
| 10181 | |
| 10182 | dupPtr->internalRep = srcPtr->internalRep; |
| 10183 | |
| 10184 | Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.varNameObjPtr); |
| 10185 | Jim_IncrRefCount(dupPtr->internalRep.dictSubstValue.indexObjPtr); |
| 10186 | } |
| 10187 | |
| 10188 | |
| 10189 | static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10190 | { |
| 10191 | if (objPtr->typePtr != &dictSubstObjType) { |
| 10192 | Jim_Obj *varObjPtr, *keyObjPtr; |
| 10193 | |
| 10194 | if (objPtr->typePtr == &interpolatedObjType) { |
| 10195 | |
| 10196 | |
| 10197 | varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr; |
| 10198 | keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr; |
| 10199 | |
| 10200 | Jim_IncrRefCount(varObjPtr); |
| @@ -10202,16 +10232,12 @@ | |
| 10232 | return resObjPtr; |
| 10233 | } |
| 10234 | |
| 10235 | static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) |
| 10236 | { |
| 10237 | if (Jim_EvalExpression(interp, objPtr) == JIM_OK) { |
| 10238 | return Jim_GetResult(interp); |
| 10239 | } |
| 10240 | return NULL; |
| 10241 | } |
| 10242 | |
| 10243 | |
| @@ -10249,11 +10275,11 @@ | |
| 10275 | return cf; |
| 10276 | } |
| 10277 | |
| 10278 | static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) |
| 10279 | { |
| 10280 | |
| 10281 | if (localCommands) { |
| 10282 | Jim_Obj *cmdNameObj; |
| 10283 | |
| 10284 | while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { |
| 10285 | Jim_HashEntry *he; |
| @@ -10268,20 +10294,20 @@ | |
| 10294 | Jim_Cmd *cmd = Jim_GetHashEntryVal(he); |
| 10295 | if (cmd->prevCmd) { |
| 10296 | Jim_Cmd *prevCmd = cmd->prevCmd; |
| 10297 | cmd->prevCmd = NULL; |
| 10298 | |
| 10299 | |
| 10300 | JimDecrCmdRefCount(interp, cmd); |
| 10301 | |
| 10302 | |
| 10303 | Jim_SetHashVal(ht, he, prevCmd); |
| 10304 | } |
| 10305 | else { |
| 10306 | Jim_DeleteHashEntry(ht, fqname); |
| 10307 | } |
| 10308 | Jim_InterpIncrProcEpoch(interp); |
| 10309 | } |
| 10310 | Jim_DecrRefCount(interp, cmdNameObj); |
| 10311 | JimFreeQualifiedName(interp, fqObjName); |
| 10312 | } |
| 10313 | Jim_FreeStack(localCommands); |
| @@ -10288,13 +10314,59 @@ | |
| 10314 | Jim_Free(localCommands); |
| 10315 | } |
| 10316 | return JIM_OK; |
| 10317 | } |
| 10318 | |
| 10319 | static int JimInvokeDefer(Jim_Interp *interp, int retcode) |
| 10320 | { |
| 10321 | Jim_Obj *objPtr; |
| 10322 | |
| 10323 | |
| 10324 | if (Jim_FindHashEntry(&interp->framePtr->vars, "jim::defer") == NULL) { |
| 10325 | return retcode; |
| 10326 | } |
| 10327 | |
| 10328 | objPtr = Jim_GetVariableStr(interp, "jim::defer", JIM_NONE); |
| 10329 | |
| 10330 | if (objPtr) { |
| 10331 | int ret = JIM_OK; |
| 10332 | int i; |
| 10333 | int listLen = Jim_ListLength(interp, objPtr); |
| 10334 | Jim_Obj *resultObjPtr; |
| 10335 | |
| 10336 | Jim_IncrRefCount(objPtr); |
| 10337 | |
| 10338 | resultObjPtr = Jim_GetResult(interp); |
| 10339 | Jim_IncrRefCount(resultObjPtr); |
| 10340 | Jim_SetEmptyResult(interp); |
| 10341 | |
| 10342 | |
| 10343 | for (i = listLen; i > 0; i--) { |
| 10344 | |
| 10345 | Jim_Obj *scriptObjPtr = Jim_ListGetIndex(interp, objPtr, i - 1); |
| 10346 | ret = Jim_EvalObj(interp, scriptObjPtr); |
| 10347 | if (ret != JIM_OK) { |
| 10348 | break; |
| 10349 | } |
| 10350 | } |
| 10351 | |
| 10352 | if (ret == JIM_OK || retcode == JIM_ERR) { |
| 10353 | |
| 10354 | Jim_SetResult(interp, resultObjPtr); |
| 10355 | } |
| 10356 | else { |
| 10357 | retcode = ret; |
| 10358 | } |
| 10359 | |
| 10360 | Jim_DecrRefCount(interp, resultObjPtr); |
| 10361 | Jim_DecrRefCount(interp, objPtr); |
| 10362 | } |
| 10363 | return retcode; |
| 10364 | } |
| 10365 | |
| 10366 | #define JIM_FCF_FULL 0 |
| 10367 | #define JIM_FCF_REUSE 1 |
| 10368 | static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) |
| 10369 | { |
| 10370 | JimDeleteLocalProcs(interp, cf->localCommands); |
| 10371 | |
| 10372 | if (cf->procArgsObjPtr) |
| @@ -10327,263 +10399,10 @@ | |
| 10399 | cf->next = interp->freeFramesList; |
| 10400 | interp->freeFramesList = cf; |
| 10401 | } |
| 10402 | |
| 10403 | |
| 10404 | |
| 10405 | int Jim_IsBigEndian(void) |
| 10406 | { |
| 10407 | union { |
| 10408 | unsigned short s; |
| @@ -10630,11 +10449,11 @@ | |
| 10449 | Jim_IncrRefCount(i->nullScriptObj); |
| 10450 | Jim_IncrRefCount(i->errorProc); |
| 10451 | Jim_IncrRefCount(i->trueObj); |
| 10452 | Jim_IncrRefCount(i->falseObj); |
| 10453 | |
| 10454 | |
| 10455 | Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); |
| 10456 | Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); |
| 10457 | |
| 10458 | Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim"); |
| 10459 | Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); |
| @@ -10652,12 +10471,14 @@ | |
| 10471 | { |
| 10472 | Jim_CallFrame *cf, *cfx; |
| 10473 | |
| 10474 | Jim_Obj *objPtr, *nextObjPtr; |
| 10475 | |
| 10476 | |
| 10477 | for (cf = i->framePtr; cf; cf = cfx) { |
| 10478 | |
| 10479 | JimInvokeDefer(i, JIM_OK); |
| 10480 | cfx = cf->parent; |
| 10481 | JimFreeCallFrame(i, cf, JIM_FCF_FULL); |
| 10482 | } |
| 10483 | |
| 10484 | Jim_DecrRefCount(i, i->emptyObj); |
| @@ -10684,10 +10505,11 @@ | |
| 10505 | |
| 10506 | printf("\n-------------------------------------\n"); |
| 10507 | printf("Objects still in the free list:\n"); |
| 10508 | while (objPtr) { |
| 10509 | const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; |
| 10510 | Jim_String(objPtr); |
| 10511 | |
| 10512 | if (objPtr->bytes && strlen(objPtr->bytes) > 20) { |
| 10513 | printf("%p (%d) %-10s: '%.20s...'\n", |
| 10514 | (void *)objPtr, objPtr->refCount, type, objPtr->bytes); |
| 10515 | } |
| @@ -10705,27 +10527,27 @@ | |
| 10527 | printf("-------------------------------------\n\n"); |
| 10528 | JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); |
| 10529 | } |
| 10530 | #endif |
| 10531 | |
| 10532 | |
| 10533 | objPtr = i->freeList; |
| 10534 | while (objPtr) { |
| 10535 | nextObjPtr = objPtr->nextObjPtr; |
| 10536 | Jim_Free(objPtr); |
| 10537 | objPtr = nextObjPtr; |
| 10538 | } |
| 10539 | |
| 10540 | |
| 10541 | for (cf = i->freeFramesList; cf; cf = cfx) { |
| 10542 | cfx = cf->next; |
| 10543 | if (cf->vars.table) |
| 10544 | Jim_FreeHashTable(&cf->vars); |
| 10545 | Jim_Free(cf); |
| 10546 | } |
| 10547 | |
| 10548 | |
| 10549 | Jim_Free(i); |
| 10550 | } |
| 10551 | |
| 10552 | Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr) |
| 10553 | { |
| @@ -10746,25 +10568,25 @@ | |
| 10568 | else { |
| 10569 | if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) { |
| 10570 | level = -1; |
| 10571 | } |
| 10572 | else { |
| 10573 | |
| 10574 | level = interp->framePtr->level - level; |
| 10575 | } |
| 10576 | } |
| 10577 | } |
| 10578 | else { |
| 10579 | str = "1"; |
| 10580 | level = interp->framePtr->level - 1; |
| 10581 | } |
| 10582 | |
| 10583 | if (level == 0) { |
| 10584 | return interp->topFramePtr; |
| 10585 | } |
| 10586 | if (level > 0) { |
| 10587 | |
| 10588 | for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { |
| 10589 | if (framePtr->level == level) { |
| 10590 | return framePtr; |
| 10591 | } |
| 10592 | } |
| @@ -10779,19 +10601,19 @@ | |
| 10601 | long level; |
| 10602 | Jim_CallFrame *framePtr; |
| 10603 | |
| 10604 | if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { |
| 10605 | if (level <= 0) { |
| 10606 | |
| 10607 | level = interp->framePtr->level + level; |
| 10608 | } |
| 10609 | |
| 10610 | if (level == 0) { |
| 10611 | return interp->topFramePtr; |
| 10612 | } |
| 10613 | |
| 10614 | |
| 10615 | for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { |
| 10616 | if (framePtr->level == level) { |
| 10617 | return framePtr; |
| 10618 | } |
| 10619 | } |
| @@ -10810,11 +10632,11 @@ | |
| 10632 | |
| 10633 | static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) |
| 10634 | { |
| 10635 | int len; |
| 10636 | |
| 10637 | |
| 10638 | Jim_IncrRefCount(stackTraceObj); |
| 10639 | Jim_DecrRefCount(interp, interp->stackTrace); |
| 10640 | interp->stackTrace = stackTraceObj; |
| 10641 | interp->errorFlag = 1; |
| 10642 | |
| @@ -10831,32 +10653,32 @@ | |
| 10653 | { |
| 10654 | if (strcmp(procname, "unknown") == 0) { |
| 10655 | procname = ""; |
| 10656 | } |
| 10657 | if (!*procname && !Jim_Length(fileNameObj)) { |
| 10658 | |
| 10659 | return; |
| 10660 | } |
| 10661 | |
| 10662 | if (Jim_IsShared(interp->stackTrace)) { |
| 10663 | Jim_DecrRefCount(interp, interp->stackTrace); |
| 10664 | interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); |
| 10665 | Jim_IncrRefCount(interp->stackTrace); |
| 10666 | } |
| 10667 | |
| 10668 | |
| 10669 | if (!*procname && Jim_Length(fileNameObj)) { |
| 10670 | |
| 10671 | int len = Jim_ListLength(interp, interp->stackTrace); |
| 10672 | |
| 10673 | if (len >= 3) { |
| 10674 | Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3); |
| 10675 | if (Jim_Length(objPtr)) { |
| 10676 | |
| 10677 | objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2); |
| 10678 | if (Jim_Length(objPtr) == 0) { |
| 10679 | |
| 10680 | ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); |
| 10681 | ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); |
| 10682 | return; |
| 10683 | } |
| 10684 | } |
| @@ -10958,18 +10780,18 @@ | |
| 10780 | { |
| 10781 | jim_wide wideValue; |
| 10782 | const char *str; |
| 10783 | |
| 10784 | if (objPtr->typePtr == &coercedDoubleObjType) { |
| 10785 | |
| 10786 | objPtr->typePtr = &intObjType; |
| 10787 | return JIM_OK; |
| 10788 | } |
| 10789 | |
| 10790 | |
| 10791 | str = Jim_String(objPtr); |
| 10792 | |
| 10793 | if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) { |
| 10794 | if (flags & JIM_ERRMSG) { |
| 10795 | Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr); |
| 10796 | } |
| 10797 | return JIM_ERR; |
| @@ -10976,11 +10798,11 @@ | |
| 10798 | } |
| 10799 | if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) { |
| 10800 | Jim_SetResultString(interp, "Integer value too big to be represented", -1); |
| 10801 | return JIM_ERR; |
| 10802 | } |
| 10803 | |
| 10804 | Jim_FreeIntRep(interp, objPtr); |
| 10805 | objPtr->typePtr = &intObjType; |
| 10806 | objPtr->internalRep.wideValue = wideValue; |
| 10807 | return JIM_OK; |
| 10808 | } |
| @@ -11075,17 +10897,17 @@ | |
| 10897 | { |
| 10898 | char buf[JIM_DOUBLE_SPACE + 1]; |
| 10899 | int i; |
| 10900 | int len = sprintf(buf, "%.12g", value); |
| 10901 | |
| 10902 | |
| 10903 | for (i = 0; i < len; i++) { |
| 10904 | if (buf[i] == '.' || buf[i] == 'e') { |
| 10905 | #if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) |
| 10906 | char *e = strchr(buf, 'e'); |
| 10907 | if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { |
| 10908 | |
| 10909 | e += 2; |
| 10910 | memmove(e, e + 1, len - (e - buf)); |
| 10911 | } |
| 10912 | #endif |
| 10913 | break; |
| @@ -11104,41 +10926,40 @@ | |
| 10926 | { |
| 10927 | double doubleValue; |
| 10928 | jim_wide wideValue; |
| 10929 | const char *str; |
| 10930 | |
| 10931 | #ifdef HAVE_LONG_LONG |
| 10932 | |
| 10933 | #define MIN_INT_IN_DOUBLE -(1LL << 53) |
| 10934 | #define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) |
| 10935 | |
| 10936 | if (objPtr->typePtr == &intObjType |
| 10937 | && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE |
| 10938 | && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { |
| 10939 | |
| 10940 | |
| 10941 | objPtr->typePtr = &coercedDoubleObjType; |
| 10942 | return JIM_OK; |
| 10943 | } |
| 10944 | #endif |
| 10945 | str = Jim_String(objPtr); |
| 10946 | |
| 10947 | if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { |
| 10948 | |
| 10949 | Jim_FreeIntRep(interp, objPtr); |
| 10950 | objPtr->typePtr = &coercedDoubleObjType; |
| 10951 | objPtr->internalRep.wideValue = wideValue; |
| 10952 | return JIM_OK; |
| 10953 | } |
| 10954 | else { |
| 10955 | |
| 10956 | if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) { |
| 10957 | Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr); |
| 10958 | return JIM_ERR; |
| 10959 | } |
| 10960 | |
| 10961 | Jim_FreeIntRep(interp, objPtr); |
| 10962 | } |
| 10963 | objPtr->typePtr = &doubleObjType; |
| 10964 | objPtr->internalRep.doubleValue = doubleValue; |
| 10965 | return JIM_OK; |
| @@ -11170,10 +10991,50 @@ | |
| 10991 | objPtr->typePtr = &doubleObjType; |
| 10992 | objPtr->bytes = NULL; |
| 10993 | objPtr->internalRep.doubleValue = doubleValue; |
| 10994 | return objPtr; |
| 10995 | } |
| 10996 | |
| 10997 | static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); |
| 10998 | |
| 10999 | int Jim_GetBoolean(Jim_Interp *interp, Jim_Obj *objPtr, int * booleanPtr) |
| 11000 | { |
| 11001 | if (objPtr->typePtr != &intObjType && SetBooleanFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR) |
| 11002 | return JIM_ERR; |
| 11003 | *booleanPtr = (int) JimWideValue(objPtr); |
| 11004 | return JIM_OK; |
| 11005 | } |
| 11006 | |
| 11007 | static int SetBooleanFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) |
| 11008 | { |
| 11009 | static const char * const falses[] = { |
| 11010 | "0", "false", "no", "off", NULL |
| 11011 | }; |
| 11012 | static const char * const trues[] = { |
| 11013 | "1", "true", "yes", "on", NULL |
| 11014 | }; |
| 11015 | |
| 11016 | int boolean; |
| 11017 | |
| 11018 | int index; |
| 11019 | if (Jim_GetEnum(interp, objPtr, falses, &index, NULL, 0) == JIM_OK) { |
| 11020 | boolean = 0; |
| 11021 | } else if (Jim_GetEnum(interp, objPtr, trues, &index, NULL, 0) == JIM_OK) { |
| 11022 | boolean = 1; |
| 11023 | } else { |
| 11024 | if (flags & JIM_ERRMSG) { |
| 11025 | Jim_SetResultFormatted(interp, "expected boolean but got \"%#s\"", objPtr); |
| 11026 | } |
| 11027 | return JIM_ERR; |
| 11028 | } |
| 11029 | |
| 11030 | |
| 11031 | Jim_FreeIntRep(interp, objPtr); |
| 11032 | objPtr->typePtr = &intObjType; |
| 11033 | objPtr->internalRep.wideValue = boolean; |
| 11034 | return JIM_OK; |
| 11035 | } |
| 11036 | |
| 11037 | static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec); |
| 11038 | static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); |
| 11039 | static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 11040 | static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| @@ -11221,11 +11082,11 @@ | |
| 11082 | #define JIM_ELESTR_QUOTE 2 |
| 11083 | static unsigned char ListElementQuotingType(const char *s, int len) |
| 11084 | { |
| 11085 | int i, level, blevel, trySimple = 1; |
| 11086 | |
| 11087 | |
| 11088 | if (len == 0) |
| 11089 | return JIM_ELESTR_BRACE; |
| 11090 | if (s[0] == '"' || s[0] == '{') { |
| 11091 | trySimple = 0; |
| 11092 | goto testbrace; |
| @@ -11243,20 +11104,20 @@ | |
| 11104 | case '\n': |
| 11105 | case '\t': |
| 11106 | case '\f': |
| 11107 | case '\v': |
| 11108 | trySimple = 0; |
| 11109 | |
| 11110 | case '{': |
| 11111 | case '}': |
| 11112 | goto testbrace; |
| 11113 | } |
| 11114 | } |
| 11115 | return JIM_ELESTR_SIMPLE; |
| 11116 | |
| 11117 | testbrace: |
| 11118 | |
| 11119 | if (s[len - 1] == '\\') |
| 11120 | return JIM_ELESTR_QUOTE; |
| 11121 | level = 0; |
| 11122 | blevel = 0; |
| 11123 | for (i = 0; i < len; i++) { |
| @@ -11372,11 +11233,11 @@ | |
| 11233 | int i, bufLen, realLength; |
| 11234 | const char *strRep; |
| 11235 | char *p; |
| 11236 | unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN]; |
| 11237 | |
| 11238 | |
| 11239 | if (objc > STATIC_QUOTING_LEN) { |
| 11240 | quotingType = Jim_Alloc(objc); |
| 11241 | } |
| 11242 | else { |
| 11243 | quotingType = staticQuoting; |
| @@ -11391,25 +11252,25 @@ | |
| 11252 | case JIM_ELESTR_SIMPLE: |
| 11253 | if (i != 0 || strRep[0] != '#') { |
| 11254 | bufLen += len; |
| 11255 | break; |
| 11256 | } |
| 11257 | |
| 11258 | quotingType[i] = JIM_ELESTR_BRACE; |
| 11259 | |
| 11260 | case JIM_ELESTR_BRACE: |
| 11261 | bufLen += len + 2; |
| 11262 | break; |
| 11263 | case JIM_ELESTR_QUOTE: |
| 11264 | bufLen += len * 2; |
| 11265 | break; |
| 11266 | } |
| 11267 | bufLen++; |
| 11268 | } |
| 11269 | bufLen++; |
| 11270 | |
| 11271 | |
| 11272 | p = objPtr->bytes = Jim_Alloc(bufLen + 1); |
| 11273 | realLength = 0; |
| 11274 | for (i = 0; i < objc; i++) { |
| 11275 | int len, qlen; |
| 11276 | |
| @@ -11436,17 +11297,17 @@ | |
| 11297 | qlen = BackslashQuoteString(strRep, len, p); |
| 11298 | p += qlen; |
| 11299 | realLength += qlen; |
| 11300 | break; |
| 11301 | } |
| 11302 | |
| 11303 | if (i + 1 != objc) { |
| 11304 | *p++ = ' '; |
| 11305 | realLength++; |
| 11306 | } |
| 11307 | } |
| 11308 | *p = '\0'; |
| 11309 | objPtr->length = realLength; |
| 11310 | |
| 11311 | if (quotingType != staticQuoting) { |
| 11312 | Jim_Free(quotingType); |
| 11313 | } |
| @@ -11477,21 +11338,21 @@ | |
| 11338 | listObjPtrPtr = JimDictPairs(objPtr, &len); |
| 11339 | for (i = 0; i < len; i++) { |
| 11340 | Jim_IncrRefCount(listObjPtrPtr[i]); |
| 11341 | } |
| 11342 | |
| 11343 | |
| 11344 | Jim_FreeIntRep(interp, objPtr); |
| 11345 | objPtr->typePtr = &listObjType; |
| 11346 | objPtr->internalRep.listValue.len = len; |
| 11347 | objPtr->internalRep.listValue.maxLen = len; |
| 11348 | objPtr->internalRep.listValue.ele = listObjPtrPtr; |
| 11349 | |
| 11350 | return JIM_OK; |
| 11351 | } |
| 11352 | |
| 11353 | |
| 11354 | if (objPtr->typePtr == &sourceObjType) { |
| 11355 | fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 11356 | linenr = objPtr->internalRep.sourceValue.lineNumber; |
| 11357 | } |
| 11358 | else { |
| @@ -11498,20 +11359,20 @@ | |
| 11359 | fileNameObj = interp->emptyObj; |
| 11360 | linenr = 1; |
| 11361 | } |
| 11362 | Jim_IncrRefCount(fileNameObj); |
| 11363 | |
| 11364 | |
| 11365 | str = Jim_GetString(objPtr, &strLen); |
| 11366 | |
| 11367 | Jim_FreeIntRep(interp, objPtr); |
| 11368 | objPtr->typePtr = &listObjType; |
| 11369 | objPtr->internalRep.listValue.len = 0; |
| 11370 | objPtr->internalRep.listValue.maxLen = 0; |
| 11371 | objPtr->internalRep.listValue.ele = NULL; |
| 11372 | |
| 11373 | |
| 11374 | if (strLen) { |
| 11375 | JimParserInit(&parser, str, strLen, linenr); |
| 11376 | while (!parser.eof) { |
| 11377 | Jim_Obj *elementPtr; |
| 11378 | |
| @@ -11641,11 +11502,11 @@ | |
| 11502 | Jim_Obj *compare_script; |
| 11503 | int rc; |
| 11504 | |
| 11505 | jim_wide ret = 0; |
| 11506 | |
| 11507 | |
| 11508 | compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command); |
| 11509 | Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj); |
| 11510 | Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj); |
| 11511 | |
| 11512 | rc = Jim_EvalObj(sort_info->interp, compare_script); |
| @@ -11663,23 +11524,27 @@ | |
| 11524 | int dst = 0; |
| 11525 | Jim_Obj **ele = listObjPtr->internalRep.listValue.ele; |
| 11526 | |
| 11527 | for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) { |
| 11528 | if (comp(&ele[dst], &ele[src]) == 0) { |
| 11529 | |
| 11530 | Jim_DecrRefCount(sort_info->interp, ele[dst]); |
| 11531 | } |
| 11532 | else { |
| 11533 | |
| 11534 | dst++; |
| 11535 | } |
| 11536 | ele[dst] = ele[src]; |
| 11537 | } |
| 11538 | |
| 11539 | |
| 11540 | dst++; |
| 11541 | if (dst < listObjPtr->internalRep.listValue.len) { |
| 11542 | ele[dst] = ele[src]; |
| 11543 | } |
| 11544 | |
| 11545 | |
| 11546 | listObjPtr->internalRep.listValue.len = dst; |
| 11547 | } |
| 11548 | |
| 11549 | |
| 11550 | static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) |
| @@ -11693,11 +11558,11 @@ | |
| 11558 | int rc; |
| 11559 | |
| 11560 | JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); |
| 11561 | SetListFromAny(interp, listObjPtr); |
| 11562 | |
| 11563 | |
| 11564 | prev_info = sort_info; |
| 11565 | sort_info = info; |
| 11566 | |
| 11567 | vector = listObjPtr->internalRep.listValue.ele; |
| 11568 | len = listObjPtr->internalRep.listValue.len; |
| @@ -11716,17 +11581,17 @@ | |
| 11581 | break; |
| 11582 | case JIM_LSORT_COMMAND: |
| 11583 | fn = ListSortCommand; |
| 11584 | break; |
| 11585 | default: |
| 11586 | fn = NULL; |
| 11587 | JimPanic((1, "ListSort called with invalid sort type")); |
| 11588 | return -1; |
| 11589 | } |
| 11590 | |
| 11591 | if (info->indexed) { |
| 11592 | |
| 11593 | info->subfn = fn; |
| 11594 | fn = ListSortIndexHelper; |
| 11595 | } |
| 11596 | |
| 11597 | if ((rc = setjmp(info->jmpbuf)) == 0) { |
| @@ -11750,11 +11615,11 @@ | |
| 11615 | int i; |
| 11616 | Jim_Obj **point; |
| 11617 | |
| 11618 | if (requiredLen > listPtr->internalRep.listValue.maxLen) { |
| 11619 | if (requiredLen < 2) { |
| 11620 | |
| 11621 | requiredLen = 4; |
| 11622 | } |
| 11623 | else { |
| 11624 | requiredLen *= 2; |
| 11625 | } |
| @@ -11936,34 +11801,34 @@ | |
| 11801 | for (i = 0; i < objc; i++) |
| 11802 | ListAppendList(objPtr, objv[i]); |
| 11803 | return objPtr; |
| 11804 | } |
| 11805 | else { |
| 11806 | |
| 11807 | int len = 0, objLen; |
| 11808 | char *bytes, *p; |
| 11809 | |
| 11810 | |
| 11811 | for (i = 0; i < objc; i++) { |
| 11812 | len += Jim_Length(objv[i]); |
| 11813 | } |
| 11814 | if (objc) |
| 11815 | len += objc - 1; |
| 11816 | |
| 11817 | p = bytes = Jim_Alloc(len + 1); |
| 11818 | for (i = 0; i < objc; i++) { |
| 11819 | const char *s = Jim_GetString(objv[i], &objLen); |
| 11820 | |
| 11821 | |
| 11822 | while (objLen && isspace(UCHAR(*s))) { |
| 11823 | s++; |
| 11824 | objLen--; |
| 11825 | len--; |
| 11826 | } |
| 11827 | |
| 11828 | while (objLen && isspace(UCHAR(s[objLen - 1]))) { |
| 11829 | |
| 11830 | if (objLen > 1 && s[objLen - 2] == '\\') { |
| 11831 | break; |
| 11832 | } |
| 11833 | objLen--; |
| 11834 | len--; |
| @@ -11990,11 +11855,11 @@ | |
| 11855 | int len, rangeLen; |
| 11856 | |
| 11857 | if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || |
| 11858 | Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) |
| 11859 | return NULL; |
| 11860 | len = Jim_ListLength(interp, listObjPtr); |
| 11861 | first = JimRelToAbsIndex(len, first); |
| 11862 | last = JimRelToAbsIndex(len, last); |
| 11863 | JimRelToAbsRange(len, &first, &last, &rangeLen); |
| 11864 | if (first == 0 && last == len) { |
| 11865 | return listObjPtr; |
| @@ -12030,16 +11895,16 @@ | |
| 11895 | { |
| 11896 | Jim_DecrRefCount(interp, (Jim_Obj *)val); |
| 11897 | } |
| 11898 | |
| 11899 | static const Jim_HashTableType JimDictHashTableType = { |
| 11900 | JimObjectHTHashFunction, |
| 11901 | JimObjectHTKeyValDup, |
| 11902 | JimObjectHTKeyValDup, |
| 11903 | JimObjectHTKeyCompare, |
| 11904 | JimObjectHTKeyValDestructor, |
| 11905 | JimObjectHTKeyValDestructor |
| 11906 | }; |
| 11907 | |
| 11908 | static const Jim_ObjType dictObjType = { |
| 11909 | "dict", |
| 11910 | FreeDictInternalRep, |
| @@ -12060,17 +11925,17 @@ | |
| 11925 | { |
| 11926 | Jim_HashTable *ht, *dupHt; |
| 11927 | Jim_HashTableIterator htiter; |
| 11928 | Jim_HashEntry *he; |
| 11929 | |
| 11930 | |
| 11931 | ht = srcPtr->internalRep.ptr; |
| 11932 | dupHt = Jim_Alloc(sizeof(*dupHt)); |
| 11933 | Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); |
| 11934 | if (ht->size != 0) |
| 11935 | Jim_ExpandHashTable(dupHt, ht->size); |
| 11936 | |
| 11937 | JimInitHashTableIterator(ht, &htiter); |
| 11938 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11939 | Jim_AddHashEntry(dupHt, he->key, he->u.val); |
| 11940 | } |
| 11941 | |
| @@ -12086,11 +11951,11 @@ | |
| 11951 | Jim_Obj **objv; |
| 11952 | int i; |
| 11953 | |
| 11954 | ht = dictPtr->internalRep.ptr; |
| 11955 | |
| 11956 | |
| 11957 | objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); |
| 11958 | JimInitHashTableIterator(ht, &htiter); |
| 11959 | i = 0; |
| 11960 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 11961 | objv[i++] = Jim_GetHashEntryKey(he); |
| @@ -12100,15 +11965,15 @@ | |
| 11965 | return objv; |
| 11966 | } |
| 11967 | |
| 11968 | static void UpdateStringOfDict(struct Jim_Obj *objPtr) |
| 11969 | { |
| 11970 | |
| 11971 | int len; |
| 11972 | Jim_Obj **objv = JimDictPairs(objPtr, &len); |
| 11973 | |
| 11974 | |
| 11975 | JimMakeListStringRep(objPtr, objv, len); |
| 11976 | |
| 11977 | Jim_Free(objv); |
| 11978 | } |
| 11979 | |
| @@ -12122,18 +11987,18 @@ | |
| 11987 | |
| 11988 | if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { |
| 11989 | Jim_String(objPtr); |
| 11990 | } |
| 11991 | |
| 11992 | |
| 11993 | listlen = Jim_ListLength(interp, objPtr); |
| 11994 | if (listlen % 2) { |
| 11995 | Jim_SetResultString(interp, "missing value to go with key", -1); |
| 11996 | return JIM_ERR; |
| 11997 | } |
| 11998 | else { |
| 11999 | |
| 12000 | Jim_HashTable *ht; |
| 12001 | int i; |
| 12002 | |
| 12003 | ht = Jim_Alloc(sizeof(*ht)); |
| 12004 | Jim_InitHashTable(ht, &JimDictHashTableType, interp); |
| @@ -12158,11 +12023,11 @@ | |
| 12023 | static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, |
| 12024 | Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) |
| 12025 | { |
| 12026 | Jim_HashTable *ht = objPtr->internalRep.ptr; |
| 12027 | |
| 12028 | if (valueObjPtr == NULL) { |
| 12029 | return Jim_DeleteHashEntry(ht, keyObjPtr); |
| 12030 | } |
| 12031 | Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); |
| 12032 | return JIM_OK; |
| 12033 | } |
| @@ -12209,12 +12074,14 @@ | |
| 12074 | if (flags & JIM_ERRMSG) { |
| 12075 | Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr); |
| 12076 | } |
| 12077 | return JIM_ERR; |
| 12078 | } |
| 12079 | else { |
| 12080 | *objPtrPtr = Jim_GetHashEntryVal(he); |
| 12081 | return JIM_OK; |
| 12082 | } |
| 12083 | } |
| 12084 | |
| 12085 | |
| 12086 | int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) |
| 12087 | { |
| @@ -12258,11 +12125,11 @@ | |
| 12125 | int shared, i; |
| 12126 | |
| 12127 | varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags); |
| 12128 | if (objPtr == NULL) { |
| 12129 | if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) { |
| 12130 | |
| 12131 | return JIM_ERR; |
| 12132 | } |
| 12133 | varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 12134 | if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) { |
| 12135 | Jim_FreeNewObj(interp, varObjPtr); |
| @@ -12272,26 +12139,26 @@ | |
| 12139 | if ((shared = Jim_IsShared(objPtr))) |
| 12140 | varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); |
| 12141 | for (i = 0; i < keyc; i++) { |
| 12142 | dictObjPtr = objPtr; |
| 12143 | |
| 12144 | |
| 12145 | if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) { |
| 12146 | goto err; |
| 12147 | } |
| 12148 | |
| 12149 | if (i == keyc - 1) { |
| 12150 | |
| 12151 | if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) { |
| 12152 | if (newObjPtr || (flags & JIM_MUSTEXIST)) { |
| 12153 | goto err; |
| 12154 | } |
| 12155 | } |
| 12156 | break; |
| 12157 | } |
| 12158 | |
| 12159 | |
| 12160 | Jim_InvalidateStringRep(dictObjPtr); |
| 12161 | if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr, |
| 12162 | newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) { |
| 12163 | if (Jim_IsShared(objPtr)) { |
| 12164 | objPtr = Jim_DuplicateObj(interp, objPtr); |
| @@ -12304,11 +12171,11 @@ | |
| 12171 | } |
| 12172 | objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 12173 | DictAddElement(interp, dictObjPtr, keyv[i], objPtr); |
| 12174 | } |
| 12175 | } |
| 12176 | |
| 12177 | Jim_InvalidateStringRep(objPtr); |
| 12178 | Jim_InvalidateStringRep(varObjPtr); |
| 12179 | if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { |
| 12180 | goto err; |
| 12181 | } |
| @@ -12341,11 +12208,11 @@ | |
| 12208 | char buf[JIM_INTEGER_SPACE + 1]; |
| 12209 | if (objPtr->internalRep.intValue >= 0) { |
| 12210 | sprintf(buf, "%d", objPtr->internalRep.intValue); |
| 12211 | } |
| 12212 | else { |
| 12213 | |
| 12214 | sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); |
| 12215 | } |
| 12216 | JimSetStringBytes(objPtr, buf); |
| 12217 | } |
| 12218 | } |
| @@ -12354,14 +12221,14 @@ | |
| 12221 | { |
| 12222 | int idx, end = 0; |
| 12223 | const char *str; |
| 12224 | char *endptr; |
| 12225 | |
| 12226 | |
| 12227 | str = Jim_String(objPtr); |
| 12228 | |
| 12229 | |
| 12230 | if (strncmp(str, "end", 3) == 0) { |
| 12231 | end = 1; |
| 12232 | str += 3; |
| 12233 | idx = 0; |
| 12234 | } |
| @@ -12372,21 +12239,21 @@ | |
| 12239 | goto badindex; |
| 12240 | } |
| 12241 | str = endptr; |
| 12242 | } |
| 12243 | |
| 12244 | |
| 12245 | if (*str == '+' || *str == '-') { |
| 12246 | int sign = (*str == '+' ? 1 : -1); |
| 12247 | |
| 12248 | idx += sign * jim_strtol(++str, &endptr); |
| 12249 | if (str == endptr || *endptr) { |
| 12250 | goto badindex; |
| 12251 | } |
| 12252 | str = endptr; |
| 12253 | } |
| 12254 | |
| 12255 | while (isspace(UCHAR(*str))) { |
| 12256 | str++; |
| 12257 | } |
| 12258 | if (*str) { |
| 12259 | goto badindex; |
| @@ -12394,19 +12261,19 @@ | |
| 12261 | if (end) { |
| 12262 | if (idx > 0) { |
| 12263 | idx = INT_MAX; |
| 12264 | } |
| 12265 | else { |
| 12266 | |
| 12267 | idx--; |
| 12268 | } |
| 12269 | } |
| 12270 | else if (idx < 0) { |
| 12271 | idx = -INT_MAX; |
| 12272 | } |
| 12273 | |
| 12274 | |
| 12275 | Jim_FreeIntRep(interp, objPtr); |
| 12276 | objPtr->typePtr = &indexObjType; |
| 12277 | objPtr->internalRep.intValue = idx; |
| 12278 | return JIM_OK; |
| 12279 | |
| @@ -12416,11 +12283,11 @@ | |
| 12283 | return JIM_ERR; |
| 12284 | } |
| 12285 | |
| 12286 | int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) |
| 12287 | { |
| 12288 | |
| 12289 | if (objPtr->typePtr == &intObjType) { |
| 12290 | jim_wide val = JimWideValue(objPtr); |
| 12291 | |
| 12292 | if (val < 0) |
| 12293 | *indexPtr = -INT_MAX; |
| @@ -12448,11 +12315,11 @@ | |
| 12315 | "exit", |
| 12316 | "eval", |
| 12317 | NULL |
| 12318 | }; |
| 12319 | |
| 12320 | #define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes) - 1) |
| 12321 | |
| 12322 | static const Jim_ObjType returnCodeObjType = { |
| 12323 | "return-code", |
| 12324 | NULL, |
| 12325 | NULL, |
| @@ -12473,18 +12340,18 @@ | |
| 12340 | static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 12341 | { |
| 12342 | int returnCode; |
| 12343 | jim_wide wideValue; |
| 12344 | |
| 12345 | |
| 12346 | if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR) |
| 12347 | returnCode = (int)wideValue; |
| 12348 | else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) { |
| 12349 | Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr); |
| 12350 | return JIM_ERR; |
| 12351 | } |
| 12352 | |
| 12353 | Jim_FreeIntRep(interp, objPtr); |
| 12354 | objPtr->typePtr = &returnCodeObjType; |
| 12355 | objPtr->internalRep.intValue = returnCode; |
| 12356 | return JIM_OK; |
| 12357 | } |
| @@ -12498,19 +12365,19 @@ | |
| 12365 | } |
| 12366 | |
| 12367 | static int JimParseExprOperator(struct JimParserCtx *pc); |
| 12368 | static int JimParseExprNumber(struct JimParserCtx *pc); |
| 12369 | static int JimParseExprIrrational(struct JimParserCtx *pc); |
| 12370 | static int JimParseExprBoolean(struct JimParserCtx *pc); |
| 12371 | |
| 12372 | |
| 12373 | enum |
| 12374 | { |
| 12375 | |
| 12376 | |
| 12377 | |
| 12378 | JIM_EXPROP_MUL = JIM_TT_EXPR_OP, |
| 12379 | JIM_EXPROP_DIV, |
| 12380 | JIM_EXPROP_MOD, |
| 12381 | JIM_EXPROP_SUB, |
| 12382 | JIM_EXPROP_ADD, |
| 12383 | JIM_EXPROP_LSHIFT, |
| @@ -12521,66 +12388,48 @@ | |
| 12388 | JIM_EXPROP_GT, |
| 12389 | JIM_EXPROP_LTE, |
| 12390 | JIM_EXPROP_GTE, |
| 12391 | JIM_EXPROP_NUMEQ, |
| 12392 | JIM_EXPROP_NUMNE, |
| 12393 | JIM_EXPROP_BITAND, |
| 12394 | JIM_EXPROP_BITXOR, |
| 12395 | JIM_EXPROP_BITOR, |
| 12396 | JIM_EXPROP_LOGICAND, |
| 12397 | JIM_EXPROP_LOGICOR, |
| 12398 | JIM_EXPROP_TERNARY, |
| 12399 | JIM_EXPROP_COLON, |
| 12400 | JIM_EXPROP_POW, |
| 12401 | |
| 12402 | |
| 12403 | JIM_EXPROP_STREQ, |
| 12404 | JIM_EXPROP_STRNE, |
| 12405 | JIM_EXPROP_STRIN, |
| 12406 | JIM_EXPROP_STRNI, |
| 12407 | |
| 12408 | |
| 12409 | JIM_EXPROP_NOT, |
| 12410 | JIM_EXPROP_BITNOT, |
| 12411 | JIM_EXPROP_UNARYMINUS, |
| 12412 | JIM_EXPROP_UNARYPLUS, |
| 12413 | |
| 12414 | |
| 12415 | JIM_EXPROP_FUNC_INT, |
| 12416 | JIM_EXPROP_FUNC_WIDE, |
| 12417 | JIM_EXPROP_FUNC_ABS, |
| 12418 | JIM_EXPROP_FUNC_DOUBLE, |
| 12419 | JIM_EXPROP_FUNC_ROUND, |
| 12420 | JIM_EXPROP_FUNC_RAND, |
| 12421 | JIM_EXPROP_FUNC_SRAND, |
| 12422 | |
| 12423 | |
| 12424 | JIM_EXPROP_FUNC_SIN, |
| 12425 | JIM_EXPROP_FUNC_COS, |
| 12426 | JIM_EXPROP_FUNC_TAN, |
| 12427 | JIM_EXPROP_FUNC_ASIN, |
| 12428 | JIM_EXPROP_FUNC_ACOS, |
| 12429 | JIM_EXPROP_FUNC_ATAN, |
| 12430 | JIM_EXPROP_FUNC_ATAN2, |
| 12431 | JIM_EXPROP_FUNC_SINH, |
| 12432 | JIM_EXPROP_FUNC_COSH, |
| 12433 | JIM_EXPROP_FUNC_TANH, |
| 12434 | JIM_EXPROP_FUNC_CEIL, |
| 12435 | JIM_EXPROP_FUNC_FLOOR, |
| @@ -12587,52 +12436,52 @@ | |
| 12436 | JIM_EXPROP_FUNC_EXP, |
| 12437 | JIM_EXPROP_FUNC_LOG, |
| 12438 | JIM_EXPROP_FUNC_LOG10, |
| 12439 | JIM_EXPROP_FUNC_SQRT, |
| 12440 | JIM_EXPROP_FUNC_POW, |
| 12441 | JIM_EXPROP_FUNC_HYPOT, |
| 12442 | JIM_EXPROP_FUNC_FMOD, |
| 12443 | }; |
| 12444 | |
| 12445 | struct JimExprNode { |
| 12446 | int type; |
| 12447 | struct Jim_Obj *objPtr; |
| 12448 | |
| 12449 | struct JimExprNode *left; |
| 12450 | struct JimExprNode *right; |
| 12451 | struct JimExprNode *ternary; |
| 12452 | }; |
| 12453 | |
| 12454 | |
| 12455 | typedef struct Jim_ExprOperator |
| 12456 | { |
| 12457 | const char *name; |
| 12458 | int (*funcop) (Jim_Interp *interp, struct JimExprNode *opnode); |
| 12459 | unsigned char precedence; |
| 12460 | unsigned char arity; |
| 12461 | unsigned char attr; |
| 12462 | unsigned char namelen; |
| 12463 | } Jim_ExprOperator; |
| 12464 | |
| 12465 | static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr); |
| 12466 | static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node); |
| 12467 | static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node); |
| 12468 | |
| 12469 | static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprNode *node) |
| 12470 | { |
| 12471 | int intresult = 1; |
| 12472 | int rc; |
| 12473 | double dA, dC = 0; |
| 12474 | jim_wide wA, wC = 0; |
| 12475 | Jim_Obj *A; |
| 12476 | |
| 12477 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| 12478 | return rc; |
| 12479 | } |
| 12480 | |
| 12481 | if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { |
| 12482 | switch (node->type) { |
| 12483 | case JIM_EXPROP_FUNC_INT: |
| 12484 | case JIM_EXPROP_FUNC_WIDE: |
| 12485 | case JIM_EXPROP_FUNC_ROUND: |
| 12486 | case JIM_EXPROP_UNARYPLUS: |
| 12487 | wC = wA; |
| @@ -12653,11 +12502,11 @@ | |
| 12502 | default: |
| 12503 | abort(); |
| 12504 | } |
| 12505 | } |
| 12506 | else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { |
| 12507 | switch (node->type) { |
| 12508 | case JIM_EXPROP_FUNC_INT: |
| 12509 | case JIM_EXPROP_FUNC_WIDE: |
| 12510 | wC = dA; |
| 12511 | break; |
| 12512 | case JIM_EXPROP_FUNC_ROUND: |
| @@ -12667,11 +12516,15 @@ | |
| 12516 | case JIM_EXPROP_UNARYPLUS: |
| 12517 | dC = dA; |
| 12518 | intresult = 0; |
| 12519 | break; |
| 12520 | case JIM_EXPROP_FUNC_ABS: |
| 12521 | #ifdef JIM_MATH_FUNCTIONS |
| 12522 | dC = fabs(dA); |
| 12523 | #else |
| 12524 | dC = dA >= 0 ? dA : -dA; |
| 12525 | #endif |
| 12526 | intresult = 0; |
| 12527 | break; |
| 12528 | case JIM_EXPROP_UNARYMINUS: |
| 12529 | dC = -dA; |
| 12530 | intresult = 0; |
| @@ -12684,14 +12537,14 @@ | |
| 12537 | } |
| 12538 | } |
| 12539 | |
| 12540 | if (rc == JIM_OK) { |
| 12541 | if (intresult) { |
| 12542 | Jim_SetResultInt(interp, wC); |
| 12543 | } |
| 12544 | else { |
| 12545 | Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); |
| 12546 | } |
| 12547 | } |
| 12548 | |
| 12549 | Jim_DecrRefCount(interp, A); |
| 12550 | |
| @@ -12704,24 +12557,29 @@ | |
| 12557 | JimRandomBytes(interp, &x, sizeof(x)); |
| 12558 | |
| 12559 | return (double)x / (unsigned long)~0; |
| 12560 | } |
| 12561 | |
| 12562 | static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprNode *node) |
| 12563 | { |
| 12564 | jim_wide wA; |
| 12565 | Jim_Obj *A; |
| 12566 | int rc; |
| 12567 | |
| 12568 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| 12569 | return rc; |
| 12570 | } |
| 12571 | |
| 12572 | rc = Jim_GetWide(interp, A, &wA); |
| 12573 | if (rc == JIM_OK) { |
| 12574 | switch (node->type) { |
| 12575 | case JIM_EXPROP_BITNOT: |
| 12576 | Jim_SetResultInt(interp, ~wA); |
| 12577 | break; |
| 12578 | case JIM_EXPROP_FUNC_SRAND: |
| 12579 | JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); |
| 12580 | Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp))); |
| 12581 | break; |
| 12582 | default: |
| 12583 | abort(); |
| 12584 | } |
| 12585 | } |
| @@ -12729,29 +12587,33 @@ | |
| 12587 | Jim_DecrRefCount(interp, A); |
| 12588 | |
| 12589 | return rc; |
| 12590 | } |
| 12591 | |
| 12592 | static int JimExprOpNone(Jim_Interp *interp, struct JimExprNode *node) |
| 12593 | { |
| 12594 | JimPanic((node->type != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); |
| 12595 | |
| 12596 | Jim_SetResult(interp, Jim_NewDoubleObj(interp, JimRandDouble(interp))); |
| 12597 | |
| 12598 | return JIM_OK; |
| 12599 | } |
| 12600 | |
| 12601 | #ifdef JIM_MATH_FUNCTIONS |
| 12602 | static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprNode *node) |
| 12603 | { |
| 12604 | int rc; |
| 12605 | double dA, dC; |
| 12606 | Jim_Obj *A; |
| 12607 | |
| 12608 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| 12609 | return rc; |
| 12610 | } |
| 12611 | |
| 12612 | rc = Jim_GetDouble(interp, A, &dA); |
| 12613 | if (rc == JIM_OK) { |
| 12614 | switch (node->type) { |
| 12615 | case JIM_EXPROP_FUNC_SIN: |
| 12616 | dC = sin(dA); |
| 12617 | break; |
| 12618 | case JIM_EXPROP_FUNC_COS: |
| 12619 | dC = cos(dA); |
| @@ -12796,33 +12658,42 @@ | |
| 12658 | dC = sqrt(dA); |
| 12659 | break; |
| 12660 | default: |
| 12661 | abort(); |
| 12662 | } |
| 12663 | Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); |
| 12664 | } |
| 12665 | |
| 12666 | Jim_DecrRefCount(interp, A); |
| 12667 | |
| 12668 | return rc; |
| 12669 | } |
| 12670 | #endif |
| 12671 | |
| 12672 | |
| 12673 | static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprNode *node) |
| 12674 | { |
| 12675 | jim_wide wA, wB; |
| 12676 | int rc; |
| 12677 | Jim_Obj *A, *B; |
| 12678 | |
| 12679 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| 12680 | return rc; |
| 12681 | } |
| 12682 | if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { |
| 12683 | Jim_DecrRefCount(interp, A); |
| 12684 | return rc; |
| 12685 | } |
| 12686 | |
| 12687 | rc = JIM_ERR; |
| 12688 | |
| 12689 | if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { |
| 12690 | jim_wide wC; |
| 12691 | |
| 12692 | rc = JIM_OK; |
| 12693 | |
| 12694 | switch (node->type) { |
| 12695 | case JIM_EXPROP_LSHIFT: |
| 12696 | wC = wA << wB; |
| 12697 | break; |
| 12698 | case JIM_EXPROP_RSHIFT: |
| 12699 | wC = wA >> wB; |
| @@ -12859,29 +12730,28 @@ | |
| 12730 | } |
| 12731 | } |
| 12732 | break; |
| 12733 | case JIM_EXPROP_ROTL: |
| 12734 | case JIM_EXPROP_ROTR:{ |
| 12735 | |
| 12736 | unsigned long uA = (unsigned long)wA; |
| 12737 | unsigned long uB = (unsigned long)wB; |
| 12738 | const unsigned int S = sizeof(unsigned long) * 8; |
| 12739 | |
| 12740 | |
| 12741 | uB %= S; |
| 12742 | |
| 12743 | if (node->type == JIM_EXPROP_ROTR) { |
| 12744 | uB = S - uB; |
| 12745 | } |
| 12746 | wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); |
| 12747 | break; |
| 12748 | } |
| 12749 | default: |
| 12750 | abort(); |
| 12751 | } |
| 12752 | Jim_SetResultInt(interp, wC); |
| 12753 | } |
| 12754 | |
| 12755 | Jim_DecrRefCount(interp, A); |
| 12756 | Jim_DecrRefCount(interp, B); |
| 12757 | |
| @@ -12888,44 +12758,55 @@ | |
| 12758 | return rc; |
| 12759 | } |
| 12760 | |
| 12761 | |
| 12762 | |
| 12763 | static int JimExprOpBin(Jim_Interp *interp, struct JimExprNode *node) |
| 12764 | { |
| 12765 | int rc = JIM_OK; |
| 12766 | double dA, dB, dC = 0; |
| 12767 | jim_wide wA, wB, wC = 0; |
| 12768 | Jim_Obj *A, *B; |
| 12769 | |
| 12770 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| 12771 | return rc; |
| 12772 | } |
| 12773 | if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { |
| 12774 | Jim_DecrRefCount(interp, A); |
| 12775 | return rc; |
| 12776 | } |
| 12777 | |
| 12778 | if ((A->typePtr != &doubleObjType || A->bytes) && |
| 12779 | (B->typePtr != &doubleObjType || B->bytes) && |
| 12780 | JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { |
| 12781 | |
| 12782 | |
| 12783 | |
| 12784 | switch (node->type) { |
| 12785 | case JIM_EXPROP_POW: |
| 12786 | case JIM_EXPROP_FUNC_POW: |
| 12787 | if (wA == 0 && wB < 0) { |
| 12788 | Jim_SetResultString(interp, "exponentiation of zero by negative power", -1); |
| 12789 | rc = JIM_ERR; |
| 12790 | goto done; |
| 12791 | } |
| 12792 | wC = JimPowWide(wA, wB); |
| 12793 | goto intresult; |
| 12794 | case JIM_EXPROP_ADD: |
| 12795 | wC = wA + wB; |
| 12796 | goto intresult; |
| 12797 | case JIM_EXPROP_SUB: |
| 12798 | wC = wA - wB; |
| 12799 | goto intresult; |
| 12800 | case JIM_EXPROP_MUL: |
| 12801 | wC = wA * wB; |
| 12802 | goto intresult; |
| 12803 | case JIM_EXPROP_DIV: |
| 12804 | if (wB == 0) { |
| 12805 | Jim_SetResultString(interp, "Division by zero", -1); |
| 12806 | rc = JIM_ERR; |
| 12807 | goto done; |
| 12808 | } |
| 12809 | else { |
| 12810 | if (wB < 0) { |
| 12811 | wB = -wB; |
| 12812 | wA = -wA; |
| @@ -12932,55 +12813,67 @@ | |
| 12813 | } |
| 12814 | wC = wA / wB; |
| 12815 | if (wA % wB < 0) { |
| 12816 | wC--; |
| 12817 | } |
| 12818 | goto intresult; |
| 12819 | } |
| 12820 | case JIM_EXPROP_LT: |
| 12821 | wC = wA < wB; |
| 12822 | goto intresult; |
| 12823 | case JIM_EXPROP_GT: |
| 12824 | wC = wA > wB; |
| 12825 | goto intresult; |
| 12826 | case JIM_EXPROP_LTE: |
| 12827 | wC = wA <= wB; |
| 12828 | goto intresult; |
| 12829 | case JIM_EXPROP_GTE: |
| 12830 | wC = wA >= wB; |
| 12831 | goto intresult; |
| 12832 | case JIM_EXPROP_NUMEQ: |
| 12833 | wC = wA == wB; |
| 12834 | goto intresult; |
| 12835 | case JIM_EXPROP_NUMNE: |
| 12836 | wC = wA != wB; |
| 12837 | goto intresult; |
| 12838 | } |
| 12839 | } |
| 12840 | if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { |
| 12841 | switch (node->type) { |
| 12842 | #ifndef JIM_MATH_FUNCTIONS |
| 12843 | case JIM_EXPROP_POW: |
| 12844 | case JIM_EXPROP_FUNC_POW: |
| 12845 | case JIM_EXPROP_FUNC_ATAN2: |
| 12846 | case JIM_EXPROP_FUNC_HYPOT: |
| 12847 | case JIM_EXPROP_FUNC_FMOD: |
| 12848 | Jim_SetResultString(interp, "unsupported", -1); |
| 12849 | rc = JIM_ERR; |
| 12850 | goto done; |
| 12851 | #else |
| 12852 | case JIM_EXPROP_POW: |
| 12853 | case JIM_EXPROP_FUNC_POW: |
| 12854 | dC = pow(dA, dB); |
| 12855 | goto doubleresult; |
| 12856 | case JIM_EXPROP_FUNC_ATAN2: |
| 12857 | dC = atan2(dA, dB); |
| 12858 | goto doubleresult; |
| 12859 | case JIM_EXPROP_FUNC_HYPOT: |
| 12860 | dC = hypot(dA, dB); |
| 12861 | goto doubleresult; |
| 12862 | case JIM_EXPROP_FUNC_FMOD: |
| 12863 | dC = fmod(dA, dB); |
| 12864 | goto doubleresult; |
| 12865 | #endif |
| 12866 | case JIM_EXPROP_ADD: |
| 12867 | dC = dA + dB; |
| 12868 | goto doubleresult; |
| 12869 | case JIM_EXPROP_SUB: |
| 12870 | dC = dA - dB; |
| 12871 | goto doubleresult; |
| 12872 | case JIM_EXPROP_MUL: |
| 12873 | dC = dA * dB; |
| 12874 | goto doubleresult; |
| 12875 | case JIM_EXPROP_DIV: |
| 12876 | if (dB == 0) { |
| 12877 | #ifdef INFINITY |
| 12878 | dC = dA < 0 ? -INFINITY : INFINITY; |
| 12879 | #else |
| @@ -12988,83 +12881,70 @@ | |
| 12881 | #endif |
| 12882 | } |
| 12883 | else { |
| 12884 | dC = dA / dB; |
| 12885 | } |
| 12886 | goto doubleresult; |
| 12887 | case JIM_EXPROP_LT: |
| 12888 | wC = dA < dB; |
| 12889 | goto intresult; |
| 12890 | case JIM_EXPROP_GT: |
| 12891 | wC = dA > dB; |
| 12892 | goto intresult; |
| 12893 | case JIM_EXPROP_LTE: |
| 12894 | wC = dA <= dB; |
| 12895 | goto intresult; |
| 12896 | case JIM_EXPROP_GTE: |
| 12897 | wC = dA >= dB; |
| 12898 | goto intresult; |
| 12899 | case JIM_EXPROP_NUMEQ: |
| 12900 | wC = dA == dB; |
| 12901 | goto intresult; |
| 12902 | case JIM_EXPROP_NUMNE: |
| 12903 | wC = dA != dB; |
| 12904 | goto intresult; |
| 12905 | } |
| 12906 | } |
| 12907 | else { |
| 12908 | |
| 12909 | |
| 12910 | |
| 12911 | int i = Jim_StringCompareObj(interp, A, B, 0); |
| 12912 | |
| 12913 | switch (node->type) { |
| 12914 | case JIM_EXPROP_LT: |
| 12915 | wC = i < 0; |
| 12916 | goto intresult; |
| 12917 | case JIM_EXPROP_GT: |
| 12918 | wC = i > 0; |
| 12919 | goto intresult; |
| 12920 | case JIM_EXPROP_LTE: |
| 12921 | wC = i <= 0; |
| 12922 | goto intresult; |
| 12923 | case JIM_EXPROP_GTE: |
| 12924 | wC = i >= 0; |
| 12925 | goto intresult; |
| 12926 | case JIM_EXPROP_NUMEQ: |
| 12927 | wC = i == 0; |
| 12928 | goto intresult; |
| 12929 | case JIM_EXPROP_NUMNE: |
| 12930 | wC = i != 0; |
| 12931 | goto intresult; |
| 12932 | } |
| 12933 | } |
| 12934 | |
| 12935 | rc = JIM_ERR; |
| 12936 | done: |
| 12937 | Jim_DecrRefCount(interp, A); |
| 12938 | Jim_DecrRefCount(interp, B); |
| 12939 | return rc; |
| 12940 | intresult: |
| 12941 | Jim_SetResultInt(interp, wC); |
| 12942 | goto done; |
| 12943 | doubleresult: |
| 12944 | Jim_SetResult(interp, Jim_NewDoubleObj(interp, dC)); |
| 12945 | goto done; |
| 12946 | } |
| 12947 | |
| 12948 | static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) |
| 12949 | { |
| 12950 | int listlen; |
| @@ -13077,22 +12957,31 @@ | |
| 12957 | } |
| 12958 | } |
| 12959 | return 0; |
| 12960 | } |
| 12961 | |
| 12962 | |
| 12963 | |
| 12964 | static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node) |
| 12965 | { |
| 12966 | Jim_Obj *A, *B; |
| 12967 | jim_wide wC; |
| 12968 | int rc; |
| 12969 | |
| 12970 | if ((rc = JimExprGetTerm(interp, node->left, &A)) != JIM_OK) { |
| 12971 | return rc; |
| 12972 | } |
| 12973 | if ((rc = JimExprGetTerm(interp, node->right, &B)) != JIM_OK) { |
| 12974 | Jim_DecrRefCount(interp, A); |
| 12975 | return rc; |
| 12976 | } |
| 12977 | |
| 12978 | switch (node->type) { |
| 12979 | case JIM_EXPROP_STREQ: |
| 12980 | case JIM_EXPROP_STRNE: |
| 12981 | wC = Jim_StringEqObj(A, B); |
| 12982 | if (node->type == JIM_EXPROP_STRNE) { |
| 12983 | wC = !wC; |
| 12984 | } |
| 12985 | break; |
| 12986 | case JIM_EXPROP_STRIN: |
| 12987 | wC = JimSearchList(interp, B, A); |
| @@ -13101,178 +12990,99 @@ | |
| 12990 | wC = !JimSearchList(interp, B, A); |
| 12991 | break; |
| 12992 | default: |
| 12993 | abort(); |
| 12994 | } |
| 12995 | Jim_SetResultInt(interp, wC); |
| 12996 | |
| 12997 | Jim_DecrRefCount(interp, A); |
| 12998 | Jim_DecrRefCount(interp, B); |
| 12999 | |
| 13000 | return rc; |
| 13001 | } |
| 13002 | |
| 13003 | static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) |
| 13004 | { |
| 13005 | long l; |
| 13006 | double d; |
| 13007 | int b; |
| 13008 | int ret = -1; |
| 13009 | |
| 13010 | |
| 13011 | Jim_IncrRefCount(obj); |
| 13012 | |
| 13013 | if (Jim_GetLong(interp, obj, &l) == JIM_OK) { |
| 13014 | ret = (l != 0); |
| 13015 | } |
| 13016 | else if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { |
| 13017 | ret = (d != 0); |
| 13018 | } |
| 13019 | else if (Jim_GetBoolean(interp, obj, &b) == JIM_OK) { |
| 13020 | ret = (b != 0); |
| 13021 | } |
| 13022 | |
| 13023 | Jim_DecrRefCount(interp, obj); |
| 13024 | return ret; |
| 13025 | } |
| 13026 | |
| 13027 | static int JimExprOpAnd(Jim_Interp *interp, struct JimExprNode *node) |
| 13028 | { |
| 13029 | |
| 13030 | int result = JimExprGetTermBoolean(interp, node->left); |
| 13031 | |
| 13032 | if (result == 1) { |
| 13033 | |
| 13034 | result = JimExprGetTermBoolean(interp, node->right); |
| 13035 | } |
| 13036 | if (result == -1) { |
| 13037 | return JIM_ERR; |
| 13038 | } |
| 13039 | Jim_SetResultInt(interp, result); |
| 13040 | return JIM_OK; |
| 13041 | } |
| 13042 | |
| 13043 | static int JimExprOpOr(Jim_Interp *interp, struct JimExprNode *node) |
| 13044 | { |
| 13045 | |
| 13046 | int result = JimExprGetTermBoolean(interp, node->left); |
| 13047 | |
| 13048 | if (result == 0) { |
| 13049 | |
| 13050 | result = JimExprGetTermBoolean(interp, node->right); |
| 13051 | } |
| 13052 | if (result == -1) { |
| 13053 | return JIM_ERR; |
| 13054 | } |
| 13055 | Jim_SetResultInt(interp, result); |
| 13056 | return JIM_OK; |
| 13057 | } |
| 13058 | |
| 13059 | static int JimExprOpTernary(Jim_Interp *interp, struct JimExprNode *node) |
| 13060 | { |
| 13061 | |
| 13062 | int result = JimExprGetTermBoolean(interp, node->left); |
| 13063 | |
| 13064 | if (result == 1) { |
| 13065 | |
| 13066 | return JimExprEvalTermNode(interp, node->right); |
| 13067 | } |
| 13068 | else if (result == 0) { |
| 13069 | |
| 13070 | return JimExprEvalTermNode(interp, node->ternary); |
| 13071 | } |
| 13072 | |
| 13073 | return JIM_ERR; |
| 13074 | } |
| 13075 | |
| 13076 | enum |
| 13077 | { |
| 13078 | OP_FUNC = 0x0001, |
| 13079 | OP_RIGHT_ASSOC = 0x0002, |
| 13080 | }; |
| 13081 | |
| 13082 | #define OPRINIT_ATTR(N, P, ARITY, F, ATTR) {N, F, P, ARITY, ATTR, sizeof(N) - 1} |
| 13083 | #define OPRINIT(N, P, ARITY, F) OPRINIT_ATTR(N, P, ARITY, F, 0) |
| 13084 | |
| 13085 | static const struct Jim_ExprOperator Jim_ExprOperators[] = { |
| 13086 | OPRINIT("*", 110, 2, JimExprOpBin), |
| 13087 | OPRINIT("/", 110, 2, JimExprOpBin), |
| 13088 | OPRINIT("%", 110, 2, JimExprOpIntBin), |
| @@ -13296,86 +13106,79 @@ | |
| 13106 | |
| 13107 | OPRINIT("&", 50, 2, JimExprOpIntBin), |
| 13108 | OPRINIT("^", 49, 2, JimExprOpIntBin), |
| 13109 | OPRINIT("|", 48, 2, JimExprOpIntBin), |
| 13110 | |
| 13111 | OPRINIT("&&", 10, 2, JimExprOpAnd), |
| 13112 | OPRINIT("||", 9, 2, JimExprOpOr), |
| 13113 | OPRINIT_ATTR("?", 5, 3, JimExprOpTernary, OP_RIGHT_ASSOC), |
| 13114 | OPRINIT_ATTR(":", 5, 3, NULL, OP_RIGHT_ASSOC), |
| 13115 | |
| 13116 | |
| 13117 | OPRINIT_ATTR("**", 120, 2, JimExprOpBin, OP_RIGHT_ASSOC), |
| 13118 | |
| 13119 | OPRINIT("eq", 60, 2, JimExprOpStrBin), |
| 13120 | OPRINIT("ne", 60, 2, JimExprOpStrBin), |
| 13121 | |
| 13122 | OPRINIT("in", 55, 2, JimExprOpStrBin), |
| 13123 | OPRINIT("ni", 55, 2, JimExprOpStrBin), |
| 13124 | |
| 13125 | OPRINIT_ATTR("!", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), |
| 13126 | OPRINIT_ATTR("~", 150, 1, JimExprOpIntUnary, OP_RIGHT_ASSOC), |
| 13127 | OPRINIT_ATTR(" -", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), |
| 13128 | OPRINIT_ATTR(" +", 150, 1, JimExprOpNumUnary, OP_RIGHT_ASSOC), |
| 13129 | |
| 13130 | |
| 13131 | |
| 13132 | OPRINIT_ATTR("int", 200, 1, JimExprOpNumUnary, OP_FUNC), |
| 13133 | OPRINIT_ATTR("wide", 200, 1, JimExprOpNumUnary, OP_FUNC), |
| 13134 | OPRINIT_ATTR("abs", 200, 1, JimExprOpNumUnary, OP_FUNC), |
| 13135 | OPRINIT_ATTR("double", 200, 1, JimExprOpNumUnary, OP_FUNC), |
| 13136 | OPRINIT_ATTR("round", 200, 1, JimExprOpNumUnary, OP_FUNC), |
| 13137 | OPRINIT_ATTR("rand", 200, 0, JimExprOpNone, OP_FUNC), |
| 13138 | OPRINIT_ATTR("srand", 200, 1, JimExprOpIntUnary, OP_FUNC), |
| 13139 | |
| 13140 | #ifdef JIM_MATH_FUNCTIONS |
| 13141 | OPRINIT_ATTR("sin", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13142 | OPRINIT_ATTR("cos", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13143 | OPRINIT_ATTR("tan", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13144 | OPRINIT_ATTR("asin", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13145 | OPRINIT_ATTR("acos", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13146 | OPRINIT_ATTR("atan", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13147 | OPRINIT_ATTR("atan2", 200, 2, JimExprOpBin, OP_FUNC), |
| 13148 | OPRINIT_ATTR("sinh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13149 | OPRINIT_ATTR("cosh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13150 | OPRINIT_ATTR("tanh", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13151 | OPRINIT_ATTR("ceil", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13152 | OPRINIT_ATTR("floor", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13153 | OPRINIT_ATTR("exp", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13154 | OPRINIT_ATTR("log", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13155 | OPRINIT_ATTR("log10", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13156 | OPRINIT_ATTR("sqrt", 200, 1, JimExprOpDoubleUnary, OP_FUNC), |
| 13157 | OPRINIT_ATTR("pow", 200, 2, JimExprOpBin, OP_FUNC), |
| 13158 | OPRINIT_ATTR("hypot", 200, 2, JimExprOpBin, OP_FUNC), |
| 13159 | OPRINIT_ATTR("fmod", 200, 2, JimExprOpBin, OP_FUNC), |
| 13160 | #endif |
| 13161 | }; |
| 13162 | #undef OPRINIT |
| 13163 | #undef OPRINIT_ATTR |
| 13164 | |
| 13165 | #define JIM_EXPR_OPERATORS_NUM \ |
| 13166 | (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) |
| 13167 | |
| 13168 | static int JimParseExpression(struct JimParserCtx *pc) |
| 13169 | { |
| 13170 | |
| 13171 | while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { |
| 13172 | if (*pc->p == '\n') { |
| 13173 | pc->linenr++; |
| 13174 | } |
| 13175 | pc->p++; |
| 13176 | pc->len--; |
| 13177 | } |
| 13178 | |
| 13179 | |
| 13180 | pc->tline = pc->linenr; |
| 13181 | pc->tstart = pc->p; |
| 13182 | |
| 13183 | if (pc->len == 0) { |
| 13184 | pc->tend = pc->p; |
| @@ -13401,11 +13204,11 @@ | |
| 13204 | return JimParseCmd(pc); |
| 13205 | case '$': |
| 13206 | if (JimParseVar(pc) == JIM_ERR) |
| 13207 | return JimParseExprOperator(pc); |
| 13208 | else { |
| 13209 | |
| 13210 | if (pc->tt == JIM_TT_EXPRSUGAR) { |
| 13211 | return JIM_ERR; |
| 13212 | } |
| 13213 | return JIM_OK; |
| 13214 | } |
| @@ -13430,10 +13233,18 @@ | |
| 13233 | case 'N': |
| 13234 | case 'I': |
| 13235 | case 'n': |
| 13236 | case 'i': |
| 13237 | if (JimParseExprIrrational(pc) == JIM_ERR) |
| 13238 | if (JimParseExprBoolean(pc) == JIM_ERR) |
| 13239 | return JimParseExprOperator(pc); |
| 13240 | break; |
| 13241 | case 't': |
| 13242 | case 'f': |
| 13243 | case 'o': |
| 13244 | case 'y': |
| 13245 | if (JimParseExprBoolean(pc) == JIM_ERR) |
| 13246 | return JimParseExprOperator(pc); |
| 13247 | break; |
| 13248 | default: |
| 13249 | return JimParseExprOperator(pc); |
| 13250 | break; |
| @@ -13443,21 +13254,21 @@ | |
| 13254 | |
| 13255 | static int JimParseExprNumber(struct JimParserCtx *pc) |
| 13256 | { |
| 13257 | char *end; |
| 13258 | |
| 13259 | |
| 13260 | pc->tt = JIM_TT_EXPR_INT; |
| 13261 | |
| 13262 | jim_strtoull(pc->p, (char **)&pc->p); |
| 13263 | |
| 13264 | if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { |
| 13265 | if (strtod(pc->tstart, &end)) { } |
| 13266 | if (end == pc->tstart) |
| 13267 | return JIM_ERR; |
| 13268 | if (end > pc->p) { |
| 13269 | |
| 13270 | pc->tt = JIM_TT_EXPR_DOUBLE; |
| 13271 | pc->p = end; |
| 13272 | } |
| 13273 | } |
| 13274 | pc->tend = pc->p - 1; |
| @@ -13481,36 +13292,66 @@ | |
| 13292 | return JIM_OK; |
| 13293 | } |
| 13294 | } |
| 13295 | return JIM_ERR; |
| 13296 | } |
| 13297 | |
| 13298 | static int JimParseExprBoolean(struct JimParserCtx *pc) |
| 13299 | { |
| 13300 | const char *booleans[] = { "false", "no", "off", "true", "yes", "on", NULL }; |
| 13301 | const int lengths[] = { 5, 2, 3, 4, 3, 2, 0 }; |
| 13302 | int i; |
| 13303 | |
| 13304 | for (i = 0; booleans[i]; i++) { |
| 13305 | const char *boolean = booleans[i]; |
| 13306 | int length = lengths[i]; |
| 13307 | |
| 13308 | if (strncmp(boolean, pc->p, length) == 0) { |
| 13309 | pc->p += length; |
| 13310 | pc->len -= length; |
| 13311 | pc->tend = pc->p - 1; |
| 13312 | pc->tt = JIM_TT_EXPR_BOOLEAN; |
| 13313 | return JIM_OK; |
| 13314 | } |
| 13315 | } |
| 13316 | return JIM_ERR; |
| 13317 | } |
| 13318 | |
| 13319 | static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) |
| 13320 | { |
| 13321 | static Jim_ExprOperator dummy_op; |
| 13322 | if (opcode < JIM_TT_EXPR_OP) { |
| 13323 | return &dummy_op; |
| 13324 | } |
| 13325 | return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP]; |
| 13326 | } |
| 13327 | |
| 13328 | static int JimParseExprOperator(struct JimParserCtx *pc) |
| 13329 | { |
| 13330 | int i; |
| 13331 | const struct Jim_ExprOperator *bestOp = NULL; |
| 13332 | int bestLen = 0; |
| 13333 | |
| 13334 | |
| 13335 | for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { |
| 13336 | const struct Jim_ExprOperator *op = &Jim_ExprOperators[i]; |
| 13337 | |
| 13338 | if (op->name[0] != pc->p[0]) { |
| 13339 | continue; |
| 13340 | } |
| 13341 | |
| 13342 | if (op->namelen > bestLen && strncmp(op->name, pc->p, op->namelen) == 0) { |
| 13343 | bestOp = op; |
| 13344 | bestLen = op->namelen; |
| 13345 | } |
| 13346 | } |
| 13347 | if (bestOp == NULL) { |
| 13348 | return JIM_ERR; |
| 13349 | } |
| 13350 | |
| 13351 | |
| 13352 | if (bestOp->attr & OP_FUNC) { |
| 13353 | const char *p = pc->p + bestLen; |
| 13354 | int len = pc->len - bestLen; |
| 13355 | |
| 13356 | while (len && isspace(UCHAR(*p))) { |
| 13357 | len--; |
| @@ -13522,30 +13363,27 @@ | |
| 13363 | } |
| 13364 | pc->tend = pc->p + bestLen - 1; |
| 13365 | pc->p += bestLen; |
| 13366 | pc->len -= bestLen; |
| 13367 | |
| 13368 | pc->tt = (bestOp - Jim_ExprOperators) + JIM_TT_EXPR_OP; |
| 13369 | return JIM_OK; |
| 13370 | } |
| 13371 | |
| 13372 | const char *jim_tt_name(int type) |
| 13373 | { |
| 13374 | static const char * const tt_names[JIM_TT_EXPR_OP] = |
| 13375 | { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", |
| 13376 | "DBL", "BOO", "$()" }; |
| 13377 | if (type < JIM_TT_EXPR_OP) { |
| 13378 | return tt_names[type]; |
| 13379 | } |
| 13380 | else if (type == JIM_EXPROP_UNARYMINUS) { |
| 13381 | return "-VE"; |
| 13382 | } |
| 13383 | else if (type == JIM_EXPROP_UNARYPLUS) { |
| 13384 | return "+VE"; |
| 13385 | } |
| 13386 | else { |
| 13387 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type); |
| 13388 | static char buf[20]; |
| 13389 | |
| @@ -13568,432 +13406,400 @@ | |
| 13406 | NULL, |
| 13407 | JIM_TYPE_REFERENCES, |
| 13408 | }; |
| 13409 | |
| 13410 | |
| 13411 | struct ExprTree |
| 13412 | { |
| 13413 | struct JimExprNode *expr; |
| 13414 | struct JimExprNode *nodes; |
| 13415 | int len; |
| 13416 | int inUse; |
| 13417 | }; |
| 13418 | |
| 13419 | static void ExprTreeFreeNodes(Jim_Interp *interp, struct JimExprNode *nodes, int num) |
| 13420 | { |
| 13421 | int i; |
| 13422 | for (i = 0; i < num; i++) { |
| 13423 | if (nodes[i].objPtr) { |
| 13424 | Jim_DecrRefCount(interp, nodes[i].objPtr); |
| 13425 | } |
| 13426 | } |
| 13427 | Jim_Free(nodes); |
| 13428 | } |
| 13429 | |
| 13430 | static void ExprTreeFree(Jim_Interp *interp, struct ExprTree *expr) |
| 13431 | { |
| 13432 | ExprTreeFreeNodes(interp, expr->nodes, expr->len); |
| 13433 | Jim_Free(expr); |
| 13434 | } |
| 13435 | |
| 13436 | static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13437 | { |
| 13438 | struct ExprTree *expr = (void *)objPtr->internalRep.ptr; |
| 13439 | |
| 13440 | if (expr) { |
| 13441 | if (--expr->inUse != 0) { |
| 13442 | return; |
| 13443 | } |
| 13444 | |
| 13445 | ExprTreeFree(interp, expr); |
| 13446 | } |
| 13447 | } |
| 13448 | |
| 13449 | static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) |
| 13450 | { |
| 13451 | JIM_NOTUSED(interp); |
| 13452 | JIM_NOTUSED(srcPtr); |
| 13453 | |
| 13454 | |
| 13455 | dupPtr->typePtr = NULL; |
| 13456 | } |
| 13457 | |
| 13458 | struct ExprBuilder { |
| 13459 | int parencount; |
| 13460 | int level; |
| 13461 | ParseToken *token; |
| 13462 | ParseToken *first_token; |
| 13463 | Jim_Stack stack; |
| 13464 | Jim_Obj *exprObjPtr; |
| 13465 | Jim_Obj *fileNameObj; |
| 13466 | struct JimExprNode *nodes; |
| 13467 | struct JimExprNode *next; |
| 13468 | }; |
| 13469 | |
| 13470 | #ifdef DEBUG_SHOW_EXPR |
| 13471 | static void JimShowExprNode(struct JimExprNode *node, int level) |
| 13472 | { |
| 13473 | int i; |
| 13474 | for (i = 0; i < level; i++) { |
| 13475 | printf(" "); |
| 13476 | } |
| 13477 | if (TOKEN_IS_EXPR_OP(node->type)) { |
| 13478 | printf("%s\n", jim_tt_name(node->type)); |
| 13479 | if (node->left) { |
| 13480 | JimShowExprNode(node->left, level + 1); |
| 13481 | } |
| 13482 | if (node->right) { |
| 13483 | JimShowExprNode(node->right, level + 1); |
| 13484 | } |
| 13485 | if (node->ternary) { |
| 13486 | JimShowExprNode(node->ternary, level + 1); |
| 13487 | } |
| 13488 | } |
| 13489 | else { |
| 13490 | printf("[%s] %s\n", jim_tt_name(node->type), Jim_String(node->objPtr)); |
| 13491 | } |
| 13492 | } |
| 13493 | #endif |
| 13494 | |
| 13495 | #define EXPR_UNTIL_CLOSE 0x0001 |
| 13496 | #define EXPR_FUNC_ARGS 0x0002 |
| 13497 | #define EXPR_TERNARY 0x0004 |
| 13498 | |
| 13499 | static int ExprTreeBuildTree(Jim_Interp *interp, struct ExprBuilder *builder, int precedence, int flags, int exp_numterms) |
| 13500 | { |
| 13501 | int rc; |
| 13502 | struct JimExprNode *node; |
| 13503 | |
| 13504 | int exp_stacklen = builder->stack.len + exp_numterms; |
| 13505 | |
| 13506 | if (builder->level++ > 200) { |
| 13507 | Jim_SetResultString(interp, "Expression too complex", -1); |
| 13508 | return JIM_ERR; |
| 13509 | } |
| 13510 | |
| 13511 | while (builder->token->type != JIM_TT_EOL) { |
| 13512 | ParseToken *t = builder->token++; |
| 13513 | int prevtt; |
| 13514 | |
| 13515 | if (t == builder->first_token) { |
| 13516 | prevtt = JIM_TT_NONE; |
| 13517 | } |
| 13518 | else { |
| 13519 | prevtt = t[-1].type; |
| 13520 | } |
| 13521 | |
| 13522 | if (t->type == JIM_TT_SUBEXPR_START) { |
| 13523 | if (builder->stack.len == exp_stacklen) { |
| 13524 | Jim_SetResultFormatted(interp, "unexpected open parenthesis in expression: \"%#s\"", builder->exprObjPtr); |
| 13525 | return JIM_ERR; |
| 13526 | } |
| 13527 | builder->parencount++; |
| 13528 | rc = ExprTreeBuildTree(interp, builder, 0, EXPR_UNTIL_CLOSE, 1); |
| 13529 | if (rc != JIM_OK) { |
| 13530 | return rc; |
| 13531 | } |
| 13532 | |
| 13533 | } |
| 13534 | else if (t->type == JIM_TT_SUBEXPR_END) { |
| 13535 | if (!(flags & EXPR_UNTIL_CLOSE)) { |
| 13536 | if (builder->stack.len == exp_stacklen && builder->level > 1) { |
| 13537 | builder->token--; |
| 13538 | builder->level--; |
| 13539 | return JIM_OK; |
| 13540 | } |
| 13541 | Jim_SetResultFormatted(interp, "unexpected closing parenthesis in expression: \"%#s\"", builder->exprObjPtr); |
| 13542 | return JIM_ERR; |
| 13543 | } |
| 13544 | builder->parencount--; |
| 13545 | if (builder->stack.len == exp_stacklen) { |
| 13546 | |
| 13547 | break; |
| 13548 | } |
| 13549 | } |
| 13550 | else if (t->type == JIM_TT_SUBEXPR_COMMA) { |
| 13551 | if (!(flags & EXPR_FUNC_ARGS)) { |
| 13552 | if (builder->stack.len == exp_stacklen) { |
| 13553 | |
| 13554 | builder->token--; |
| 13555 | builder->level--; |
| 13556 | return JIM_OK; |
| 13557 | } |
| 13558 | Jim_SetResultFormatted(interp, "unexpected comma in expression: \"%#s\"", builder->exprObjPtr); |
| 13559 | return JIM_ERR; |
| 13560 | } |
| 13561 | else { |
| 13562 | |
| 13563 | if (builder->stack.len > exp_stacklen) { |
| 13564 | Jim_SetResultFormatted(interp, "too many arguments to math function"); |
| 13565 | return JIM_ERR; |
| 13566 | } |
| 13567 | } |
| 13568 | |
| 13569 | } |
| 13570 | else if (t->type == JIM_EXPROP_COLON) { |
| 13571 | if (!(flags & EXPR_TERNARY)) { |
| 13572 | if (builder->level != 1) { |
| 13573 | |
| 13574 | builder->token--; |
| 13575 | builder->level--; |
| 13576 | return JIM_OK; |
| 13577 | } |
| 13578 | Jim_SetResultFormatted(interp, ": without ? in expression: \"%#s\"", builder->exprObjPtr); |
| 13579 | return JIM_ERR; |
| 13580 | } |
| 13581 | if (builder->stack.len == exp_stacklen) { |
| 13582 | |
| 13583 | builder->token--; |
| 13584 | builder->level--; |
| 13585 | return JIM_OK; |
| 13586 | } |
| 13587 | |
| 13588 | } |
| 13589 | else if (TOKEN_IS_EXPR_OP(t->type)) { |
| 13590 | const struct Jim_ExprOperator *op; |
| 13591 | |
| 13592 | |
| 13593 | if (TOKEN_IS_EXPR_OP(prevtt) || TOKEN_IS_EXPR_START(prevtt)) { |
| 13594 | if (t->type == JIM_EXPROP_SUB) { |
| 13595 | t->type = JIM_EXPROP_UNARYMINUS; |
| 13596 | } |
| 13597 | else if (t->type == JIM_EXPROP_ADD) { |
| 13598 | t->type = JIM_EXPROP_UNARYPLUS; |
| 13599 | } |
| 13600 | } |
| 13601 | |
| 13602 | op = JimExprOperatorInfoByOpcode(t->type); |
| 13603 | |
| 13604 | if (op->precedence < precedence || (!(op->attr & OP_RIGHT_ASSOC) && op->precedence == precedence)) { |
| 13605 | |
| 13606 | builder->token--; |
| 13607 | break; |
| 13608 | } |
| 13609 | |
| 13610 | if (op->attr & OP_FUNC) { |
| 13611 | if (builder->token->type != JIM_TT_SUBEXPR_START) { |
| 13612 | Jim_SetResultString(interp, "missing arguments for math function", -1); |
| 13613 | return JIM_ERR; |
| 13614 | } |
| 13615 | builder->token++; |
| 13616 | if (op->arity == 0) { |
| 13617 | if (builder->token->type != JIM_TT_SUBEXPR_END) { |
| 13618 | Jim_SetResultString(interp, "too many arguments for math function", -1); |
| 13619 | return JIM_ERR; |
| 13620 | } |
| 13621 | builder->token++; |
| 13622 | goto noargs; |
| 13623 | } |
| 13624 | builder->parencount++; |
| 13625 | |
| 13626 | |
| 13627 | rc = ExprTreeBuildTree(interp, builder, 0, EXPR_FUNC_ARGS | EXPR_UNTIL_CLOSE, op->arity); |
| 13628 | } |
| 13629 | else if (t->type == JIM_EXPROP_TERNARY) { |
| 13630 | |
| 13631 | rc = ExprTreeBuildTree(interp, builder, op->precedence, EXPR_TERNARY, 2); |
| 13632 | } |
| 13633 | else { |
| 13634 | rc = ExprTreeBuildTree(interp, builder, op->precedence, 0, 1); |
| 13635 | } |
| 13636 | |
| 13637 | if (rc != JIM_OK) { |
| 13638 | return rc; |
| 13639 | } |
| 13640 | |
| 13641 | noargs: |
| 13642 | node = builder->next++; |
| 13643 | node->type = t->type; |
| 13644 | |
| 13645 | if (op->arity >= 3) { |
| 13646 | node->ternary = Jim_StackPop(&builder->stack); |
| 13647 | if (node->ternary == NULL) { |
| 13648 | goto missingoperand; |
| 13649 | } |
| 13650 | } |
| 13651 | if (op->arity >= 2) { |
| 13652 | node->right = Jim_StackPop(&builder->stack); |
| 13653 | if (node->right == NULL) { |
| 13654 | goto missingoperand; |
| 13655 | } |
| 13656 | } |
| 13657 | if (op->arity >= 1) { |
| 13658 | node->left = Jim_StackPop(&builder->stack); |
| 13659 | if (node->left == NULL) { |
| 13660 | missingoperand: |
| 13661 | Jim_SetResultFormatted(interp, "missing operand to %s in expression: \"%#s\"", op->name, builder->exprObjPtr); |
| 13662 | builder->next--; |
| 13663 | return JIM_ERR; |
| 13664 | |
| 13665 | } |
| 13666 | } |
| 13667 | |
| 13668 | |
| 13669 | Jim_StackPush(&builder->stack, node); |
| 13670 | } |
| 13671 | else { |
| 13672 | Jim_Obj *objPtr = NULL; |
| 13673 | |
| 13674 | |
| 13675 | |
| 13676 | |
| 13677 | if (!TOKEN_IS_EXPR_START(prevtt) && !TOKEN_IS_EXPR_OP(prevtt)) { |
| 13678 | Jim_SetResultFormatted(interp, "missing operator in expression: \"%#s\"", builder->exprObjPtr); |
| 13679 | return JIM_ERR; |
| 13680 | } |
| 13681 | |
| 13682 | |
| 13683 | if (t->type == JIM_TT_EXPR_INT || t->type == JIM_TT_EXPR_DOUBLE) { |
| 13684 | char *endptr; |
| 13685 | if (t->type == JIM_TT_EXPR_INT) { |
| 13686 | objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr)); |
| 13687 | } |
| 13688 | else { |
| 13689 | objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr)); |
| 13690 | } |
| 13691 | if (endptr != t->token + t->len) { |
| 13692 | |
| 13693 | Jim_FreeNewObj(interp, objPtr); |
| 13694 | objPtr = NULL; |
| 13695 | } |
| 13696 | } |
| 13697 | |
| 13698 | if (!objPtr) { |
| 13699 | |
| 13700 | objPtr = Jim_NewStringObj(interp, t->token, t->len); |
| 13701 | if (t->type == JIM_TT_CMD) { |
| 13702 | |
| 13703 | JimSetSourceInfo(interp, objPtr, builder->fileNameObj, t->line); |
| 13704 | } |
| 13705 | } |
| 13706 | |
| 13707 | |
| 13708 | node = builder->next++; |
| 13709 | node->objPtr = objPtr; |
| 13710 | Jim_IncrRefCount(node->objPtr); |
| 13711 | node->type = t->type; |
| 13712 | Jim_StackPush(&builder->stack, node); |
| 13713 | } |
| 13714 | } |
| 13715 | |
| 13716 | if (builder->stack.len == exp_stacklen) { |
| 13717 | builder->level--; |
| 13718 | return JIM_OK; |
| 13719 | } |
| 13720 | |
| 13721 | if ((flags & EXPR_FUNC_ARGS)) { |
| 13722 | Jim_SetResultFormatted(interp, "too %s arguments for math function", (builder->stack.len < exp_stacklen) ? "few" : "many"); |
| 13723 | } |
| 13724 | else { |
| 13725 | if (builder->stack.len < exp_stacklen) { |
| 13726 | if (builder->level == 0) { |
| 13727 | Jim_SetResultFormatted(interp, "empty expression"); |
| 13728 | } |
| 13729 | else { |
| 13730 | Jim_SetResultFormatted(interp, "syntax error in expression \"%#s\": premature end of expression", builder->exprObjPtr); |
| 13731 | } |
| 13732 | } |
| 13733 | else { |
| 13734 | Jim_SetResultFormatted(interp, "extra terms after expression"); |
| 13735 | } |
| 13736 | } |
| 13737 | |
| 13738 | return JIM_ERR; |
| 13739 | } |
| 13740 | |
| 13741 | static struct ExprTree *ExprTreeCreateTree(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *exprObjPtr, Jim_Obj *fileNameObj) |
| 13742 | { |
| 13743 | struct ExprTree *expr; |
| 13744 | struct ExprBuilder builder; |
| 13745 | int rc; |
| 13746 | struct JimExprNode *top; |
| 13747 | |
| 13748 | builder.parencount = 0; |
| 13749 | builder.level = 0; |
| 13750 | builder.token = builder.first_token = tokenlist->list; |
| 13751 | builder.exprObjPtr = exprObjPtr; |
| 13752 | builder.fileNameObj = fileNameObj; |
| 13753 | |
| 13754 | builder.nodes = malloc(sizeof(struct JimExprNode) * (tokenlist->count - 1)); |
| 13755 | memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1)); |
| 13756 | builder.next = builder.nodes; |
| 13757 | Jim_InitStack(&builder.stack); |
| 13758 | |
| 13759 | rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1); |
| 13760 | |
| 13761 | if (rc == JIM_OK) { |
| 13762 | top = Jim_StackPop(&builder.stack); |
| 13763 | |
| 13764 | if (builder.parencount) { |
| 13765 | Jim_SetResultString(interp, "missing close parenthesis", -1); |
| 13766 | rc = JIM_ERR; |
| 13767 | } |
| 13768 | } |
| 13769 | |
| 13770 | |
| 13771 | Jim_FreeStack(&builder.stack); |
| 13772 | |
| 13773 | if (rc != JIM_OK) { |
| 13774 | ExprTreeFreeNodes(interp, builder.nodes, builder.next - builder.nodes); |
| 13775 | return NULL; |
| 13776 | } |
| 13777 | |
| 13778 | expr = Jim_Alloc(sizeof(*expr)); |
| 13779 | expr->inUse = 1; |
| 13780 | expr->expr = top; |
| 13781 | expr->nodes = builder.nodes; |
| 13782 | expr->len = builder.next - builder.nodes; |
| 13783 | |
| 13784 | assert(expr->len <= tokenlist->count - 1); |
| 13785 | |
| 13786 | return expr; |
| 13787 | } |
| 13788 | |
| 13789 | static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) |
| 13790 | { |
| 13791 | int exprTextLen; |
| 13792 | const char *exprText; |
| 13793 | struct JimParserCtx parser; |
| 13794 | struct ExprTree *expr; |
| 13795 | ParseTokenList tokenlist; |
| 13796 | int line; |
| 13797 | Jim_Obj *fileNameObj; |
| 13798 | int rc = JIM_ERR; |
| 13799 | |
| 13800 | |
| 13801 | if (objPtr->typePtr == &sourceObjType) { |
| 13802 | fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; |
| 13803 | line = objPtr->internalRep.sourceValue.lineNumber; |
| 13804 | } |
| 13805 | else { |
| @@ -14002,18 +13808,17 @@ | |
| 13808 | } |
| 13809 | Jim_IncrRefCount(fileNameObj); |
| 13810 | |
| 13811 | exprText = Jim_GetString(objPtr, &exprTextLen); |
| 13812 | |
| 13813 | |
| 13814 | ScriptTokenListInit(&tokenlist); |
| 13815 | |
| 13816 | JimParserInit(&parser, exprText, exprTextLen, line); |
| 13817 | while (!parser.eof) { |
| 13818 | if (JimParseExpression(&parser) != JIM_OK) { |
| 13819 | ScriptTokenListFree(&tokenlist); |
| 13820 | Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr); |
| 13821 | expr = NULL; |
| 13822 | goto err; |
| 13823 | } |
| 13824 | |
| @@ -14036,125 +13841,174 @@ | |
| 13841 | ScriptTokenListFree(&tokenlist); |
| 13842 | Jim_DecrRefCount(interp, fileNameObj); |
| 13843 | return JIM_ERR; |
| 13844 | } |
| 13845 | |
| 13846 | |
| 13847 | expr = ExprTreeCreateTree(interp, &tokenlist, objPtr, fileNameObj); |
| 13848 | |
| 13849 | |
| 13850 | ScriptTokenListFree(&tokenlist); |
| 13851 | |
| 13852 | if (!expr) { |
| 13853 | goto err; |
| 13854 | } |
| 13855 | |
| 13856 | #ifdef DEBUG_SHOW_EXPR |
| 13857 | printf("==== Expr ====\n"); |
| 13858 | JimShowExprNode(expr->expr, 0); |
| 13859 | #endif |
| 13860 | |
| 13861 | rc = JIM_OK; |
| 13862 | |
| 13863 | err: |
| 13864 | |
| 13865 | Jim_DecrRefCount(interp, fileNameObj); |
| 13866 | Jim_FreeIntRep(interp, objPtr); |
| 13867 | Jim_SetIntRepPtr(objPtr, expr); |
| 13868 | objPtr->typePtr = &exprObjType; |
| 13869 | return rc; |
| 13870 | } |
| 13871 | |
| 13872 | static struct ExprTree *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) |
| 13873 | { |
| 13874 | if (objPtr->typePtr != &exprObjType) { |
| 13875 | if (SetExprFromAny(interp, objPtr) != JIM_OK) { |
| 13876 | return NULL; |
| 13877 | } |
| 13878 | } |
| 13879 | return (struct ExprTree *) Jim_GetIntRepPtr(objPtr); |
| 13880 | } |
| 13881 | |
| 13882 | #ifdef JIM_OPTIMIZATION |
| 13883 | static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, struct JimExprNode *node) |
| 13884 | { |
| 13885 | if (node->type == JIM_TT_EXPR_INT) |
| 13886 | return node->objPtr; |
| 13887 | else if (node->type == JIM_TT_VAR) |
| 13888 | return Jim_GetVariable(interp, node->objPtr, JIM_NONE); |
| 13889 | else if (node->type == JIM_TT_DICTSUGAR) |
| 13890 | return JimExpandDictSugar(interp, node->objPtr); |
| 13891 | else |
| 13892 | return NULL; |
| 13893 | } |
| 13894 | #endif |
| 13895 | |
| 13896 | |
| 13897 | static int JimExprEvalTermNode(Jim_Interp *interp, struct JimExprNode *node) |
| 13898 | { |
| 13899 | if (TOKEN_IS_EXPR_OP(node->type)) { |
| 13900 | const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(node->type); |
| 13901 | return op->funcop(interp, node); |
| 13902 | } |
| 13903 | else { |
| 13904 | Jim_Obj *objPtr; |
| 13905 | |
| 13906 | |
| 13907 | switch (node->type) { |
| 13908 | case JIM_TT_EXPR_INT: |
| 13909 | case JIM_TT_EXPR_DOUBLE: |
| 13910 | case JIM_TT_EXPR_BOOLEAN: |
| 13911 | case JIM_TT_STR: |
| 13912 | Jim_SetResult(interp, node->objPtr); |
| 13913 | return JIM_OK; |
| 13914 | |
| 13915 | case JIM_TT_VAR: |
| 13916 | objPtr = Jim_GetVariable(interp, node->objPtr, JIM_ERRMSG); |
| 13917 | if (objPtr) { |
| 13918 | Jim_SetResult(interp, objPtr); |
| 13919 | return JIM_OK; |
| 13920 | } |
| 13921 | return JIM_ERR; |
| 13922 | |
| 13923 | case JIM_TT_DICTSUGAR: |
| 13924 | objPtr = JimExpandDictSugar(interp, node->objPtr); |
| 13925 | if (objPtr) { |
| 13926 | Jim_SetResult(interp, objPtr); |
| 13927 | return JIM_OK; |
| 13928 | } |
| 13929 | return JIM_ERR; |
| 13930 | |
| 13931 | case JIM_TT_ESC: |
| 13932 | if (Jim_SubstObj(interp, node->objPtr, &objPtr, JIM_NONE) == JIM_OK) { |
| 13933 | Jim_SetResult(interp, objPtr); |
| 13934 | return JIM_OK; |
| 13935 | } |
| 13936 | return JIM_ERR; |
| 13937 | |
| 13938 | case JIM_TT_CMD: |
| 13939 | return Jim_EvalObj(interp, node->objPtr); |
| 13940 | |
| 13941 | default: |
| 13942 | |
| 13943 | return JIM_ERR; |
| 13944 | } |
| 13945 | } |
| 13946 | } |
| 13947 | |
| 13948 | static int JimExprGetTerm(Jim_Interp *interp, struct JimExprNode *node, Jim_Obj **objPtrPtr) |
| 13949 | { |
| 13950 | int rc = JimExprEvalTermNode(interp, node); |
| 13951 | if (rc == JIM_OK) { |
| 13952 | *objPtrPtr = Jim_GetResult(interp); |
| 13953 | Jim_IncrRefCount(*objPtrPtr); |
| 13954 | } |
| 13955 | return rc; |
| 13956 | } |
| 13957 | |
| 13958 | static int JimExprGetTermBoolean(Jim_Interp *interp, struct JimExprNode *node) |
| 13959 | { |
| 13960 | if (JimExprEvalTermNode(interp, node) == JIM_OK) { |
| 13961 | return ExprBool(interp, Jim_GetResult(interp)); |
| 13962 | } |
| 13963 | return -1; |
| 13964 | } |
| 13965 | |
| 13966 | int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr) |
| 13967 | { |
| 13968 | struct ExprTree *expr; |
| 13969 | int retcode = JIM_OK; |
| 13970 | |
| 13971 | expr = JimGetExpression(interp, exprObjPtr); |
| 13972 | if (!expr) { |
| 13973 | return JIM_ERR; |
| 13974 | } |
| 13975 | |
| 13976 | #ifdef JIM_OPTIMIZATION |
| 13977 | { |
| 13978 | Jim_Obj *objPtr; |
| 13979 | |
| 13980 | |
| 13981 | switch (expr->len) { |
| 13982 | case 1: |
| 13983 | objPtr = JimExprIntValOrVar(interp, expr->expr); |
| 13984 | if (objPtr) { |
| 13985 | Jim_SetResult(interp, objPtr); |
| 13986 | return JIM_OK; |
| 13987 | } |
| 13988 | break; |
| 13989 | |
| 13990 | case 2: |
| 13991 | if (expr->expr->type == JIM_EXPROP_NOT) { |
| 13992 | objPtr = JimExprIntValOrVar(interp, expr->expr->left); |
| 13993 | |
| 13994 | if (objPtr && JimIsWide(objPtr)) { |
| 13995 | Jim_SetResult(interp, JimWideValue(objPtr) ? interp->falseObj : interp->trueObj); |
| 13996 | return JIM_OK; |
| 13997 | } |
| 13998 | } |
| 13999 | break; |
| 14000 | |
| 14001 | case 3: |
| 14002 | objPtr = JimExprIntValOrVar(interp, expr->expr->left); |
| 14003 | if (objPtr && JimIsWide(objPtr)) { |
| 14004 | Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, expr->expr->right); |
| 14005 | if (objPtr2 && JimIsWide(objPtr2)) { |
| 14006 | jim_wide wideValueA = JimWideValue(objPtr); |
| 14007 | jim_wide wideValueB = JimWideValue(objPtr2); |
| 14008 | int cmpRes; |
| 14009 | switch (expr->expr->type) { |
| 14010 | case JIM_EXPROP_LT: |
| 14011 | cmpRes = wideValueA < wideValueB; |
| 14012 | break; |
| 14013 | case JIM_EXPROP_LTE: |
| 14014 | cmpRes = wideValueA <= wideValueB; |
| @@ -14172,12 +14026,11 @@ | |
| 14026 | cmpRes = wideValueA != wideValueB; |
| 14027 | break; |
| 14028 | default: |
| 14029 | goto noopt; |
| 14030 | } |
| 14031 | Jim_SetResult(interp, cmpRes ? interp->trueObj : interp->falseObj); |
| 14032 | return JIM_OK; |
| 14033 | } |
| 14034 | } |
| 14035 | break; |
| 14036 | } |
| @@ -14185,145 +14038,64 @@ | |
| 14038 | noopt: |
| 14039 | #endif |
| 14040 | |
| 14041 | expr->inUse++; |
| 14042 | |
| 14043 | |
| 14044 | retcode = JimExprEvalTermNode(interp, expr->expr); |
| 14045 | |
| 14046 | expr->inUse--; |
| 14047 | |
| 14048 | return retcode; |
| 14049 | } |
| 14050 | |
| 14051 | int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) |
| 14052 | { |
| 14053 | int retcode = Jim_EvalExpression(interp, exprObjPtr); |
| 14054 | |
| 14055 | if (retcode == JIM_OK) { |
| 14056 | switch (ExprBool(interp, Jim_GetResult(interp))) { |
| 14057 | case 0: |
| 14058 | *boolPtr = 0; |
| 14059 | break; |
| 14060 | |
| 14061 | case 1: |
| 14062 | *boolPtr = 1; |
| 14063 | break; |
| 14064 | |
| 14065 | case -1: |
| 14066 | retcode = JIM_ERR; |
| 14067 | break; |
| 14068 | } |
| 14069 | } |
| 14070 | return retcode; |
| 14071 | } |
| 14072 | |
| 14073 | |
| 14074 | |
| 14075 | |
| 14076 | typedef struct ScanFmtPartDescr |
| 14077 | { |
| 14078 | const char *arg; |
| 14079 | const char *prefix; |
| 14080 | size_t width; |
| 14081 | int pos; |
| 14082 | char type; |
| 14083 | char modifier; |
| 14084 | } ScanFmtPartDescr; |
| 14085 | |
| 14086 | |
| 14087 | typedef struct ScanFmtStringObj |
| 14088 | { |
| 14089 | jim_wide size; |
| 14090 | char *stringRep; |
| 14091 | size_t count; |
| 14092 | size_t convCount; |
| 14093 | size_t maxPos; |
| 14094 | const char *error; |
| 14095 | char *scratch; |
| 14096 | ScanFmtPartDescr descr[1]; |
| 14097 | } ScanFmtStringObj; |
| 14098 | |
| 14099 | |
| 14100 | static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); |
| 14101 | static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); |
| @@ -14364,28 +14136,28 @@ | |
| 14136 | static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) |
| 14137 | { |
| 14138 | ScanFmtStringObj *fmtObj; |
| 14139 | char *buffer; |
| 14140 | int maxCount, i, approxSize, lastPos = -1; |
| 14141 | const char *fmt = Jim_String(objPtr); |
| 14142 | int maxFmtLen = Jim_Length(objPtr); |
| 14143 | const char *fmtEnd = fmt + maxFmtLen; |
| 14144 | int curr; |
| 14145 | |
| 14146 | Jim_FreeIntRep(interp, objPtr); |
| 14147 | |
| 14148 | for (i = 0, maxCount = 0; i < maxFmtLen; ++i) |
| 14149 | if (fmt[i] == '%') |
| 14150 | ++maxCount; |
| 14151 | |
| 14152 | approxSize = sizeof(ScanFmtStringObj) |
| 14153 | +(maxCount + 1) * sizeof(ScanFmtPartDescr) |
| 14154 | +maxFmtLen * sizeof(char) + 3 + 1 |
| 14155 | + maxFmtLen * sizeof(char) + 1 |
| 14156 | + maxFmtLen * sizeof(char) |
| 14157 | +(maxCount + 1) * sizeof(char) |
| 14158 | +1; |
| 14159 | fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize); |
| 14160 | memset(fmtObj, 0, approxSize); |
| 14161 | fmtObj->size = approxSize; |
| 14162 | fmtObj->maxPos = 0; |
| 14163 | fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1]; |
| @@ -14397,12 +14169,12 @@ | |
| 14169 | for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) { |
| 14170 | int width = 0, skip; |
| 14171 | ScanFmtPartDescr *descr = &fmtObj->descr[curr]; |
| 14172 | |
| 14173 | fmtObj->count++; |
| 14174 | descr->width = 0; |
| 14175 | |
| 14176 | if (*fmt != '%' || fmt[1] == '%') { |
| 14177 | descr->type = 0; |
| 14178 | descr->prefix = &buffer[i]; |
| 14179 | for (; fmt < fmtEnd; ++fmt) { |
| 14180 | if (*fmt == '%') { |
| @@ -14412,65 +14184,70 @@ | |
| 14184 | } |
| 14185 | buffer[i++] = *fmt; |
| 14186 | } |
| 14187 | buffer[i++] = 0; |
| 14188 | } |
| 14189 | |
| 14190 | ++fmt; |
| 14191 | |
| 14192 | if (fmt >= fmtEnd) |
| 14193 | goto done; |
| 14194 | descr->pos = 0; |
| 14195 | if (*fmt == '*') { |
| 14196 | descr->pos = -1; |
| 14197 | ++fmt; |
| 14198 | } |
| 14199 | else |
| 14200 | fmtObj->convCount++; |
| 14201 | |
| 14202 | if (sscanf(fmt, "%d%n", &width, &skip) == 1) { |
| 14203 | fmt += skip; |
| 14204 | |
| 14205 | if (descr->pos != -1 && *fmt == '$') { |
| 14206 | int prev; |
| 14207 | |
| 14208 | ++fmt; |
| 14209 | descr->pos = width; |
| 14210 | width = 0; |
| 14211 | |
| 14212 | if ((lastPos == 0 && descr->pos > 0) |
| 14213 | || (lastPos > 0 && descr->pos == 0)) { |
| 14214 | fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers"; |
| 14215 | return JIM_ERR; |
| 14216 | } |
| 14217 | |
| 14218 | for (prev = 0; prev < curr; ++prev) { |
| 14219 | if (fmtObj->descr[prev].pos == -1) |
| 14220 | continue; |
| 14221 | if (fmtObj->descr[prev].pos == descr->pos) { |
| 14222 | fmtObj->error = |
| 14223 | "variable is assigned by multiple \"%n$\" conversion specifiers"; |
| 14224 | return JIM_ERR; |
| 14225 | } |
| 14226 | } |
| 14227 | if (descr->pos < 0) { |
| 14228 | fmtObj->error = |
| 14229 | "\"%n$\" conversion specifier is negative"; |
| 14230 | return JIM_ERR; |
| 14231 | } |
| 14232 | |
| 14233 | if (sscanf(fmt, "%d%n", &width, &skip) == 1) { |
| 14234 | descr->width = width; |
| 14235 | fmt += skip; |
| 14236 | } |
| 14237 | if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) |
| 14238 | fmtObj->maxPos = descr->pos; |
| 14239 | } |
| 14240 | else { |
| 14241 | |
| 14242 | descr->width = width; |
| 14243 | } |
| 14244 | } |
| 14245 | |
| 14246 | if (lastPos == -1) |
| 14247 | lastPos = descr->pos; |
| 14248 | |
| 14249 | if (*fmt == '[') { |
| 14250 | int swapped = 1, beg = i, end, j; |
| 14251 | |
| 14252 | descr->type = '['; |
| 14253 | descr->arg = &buffer[i]; |
| @@ -14485,11 +14262,11 @@ | |
| 14262 | fmtObj->error = "unmatched [ in format string"; |
| 14263 | return JIM_ERR; |
| 14264 | } |
| 14265 | end = i; |
| 14266 | buffer[i++] = 0; |
| 14267 | |
| 14268 | while (swapped) { |
| 14269 | swapped = 0; |
| 14270 | for (j = beg + 1; j < end - 1; ++j) { |
| 14271 | if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) { |
| 14272 | char tmp = buffer[j - 1]; |
| @@ -14500,13 +14277,18 @@ | |
| 14277 | } |
| 14278 | } |
| 14279 | } |
| 14280 | } |
| 14281 | else { |
| 14282 | |
| 14283 | if (fmt < fmtEnd && strchr("hlL", *fmt)) |
| 14284 | descr->modifier = tolower((int)*fmt++); |
| 14285 | |
| 14286 | if (fmt >= fmtEnd) { |
| 14287 | fmtObj->error = "missing scan conversion character"; |
| 14288 | return JIM_ERR; |
| 14289 | } |
| 14290 | |
| 14291 | descr->type = *fmt; |
| 14292 | if (strchr("efgcsndoxui", *fmt) == 0) { |
| 14293 | fmtObj->error = "bad scan conversion character"; |
| 14294 | return JIM_ERR; |
| @@ -14543,11 +14325,11 @@ | |
| 14325 | while (*str) { |
| 14326 | int c; |
| 14327 | int n; |
| 14328 | |
| 14329 | if (!sdescr && isspace(UCHAR(*str))) |
| 14330 | break; |
| 14331 | |
| 14332 | n = utf8_tounicode(str, &c); |
| 14333 | if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) |
| 14334 | break; |
| 14335 | while (n--) |
| @@ -14566,89 +14348,89 @@ | |
| 14348 | size_t scanned = 0; |
| 14349 | size_t anchor = pos; |
| 14350 | int i; |
| 14351 | Jim_Obj *tmpObj = NULL; |
| 14352 | |
| 14353 | |
| 14354 | *valObjPtr = 0; |
| 14355 | if (descr->prefix) { |
| 14356 | for (i = 0; pos < strLen && descr->prefix[i]; ++i) { |
| 14357 | |
| 14358 | if (isspace(UCHAR(descr->prefix[i]))) |
| 14359 | while (pos < strLen && isspace(UCHAR(str[pos]))) |
| 14360 | ++pos; |
| 14361 | else if (descr->prefix[i] != str[pos]) |
| 14362 | break; |
| 14363 | else |
| 14364 | ++pos; |
| 14365 | } |
| 14366 | if (pos >= strLen) { |
| 14367 | return -1; |
| 14368 | } |
| 14369 | else if (descr->prefix[i] != 0) |
| 14370 | return 0; |
| 14371 | } |
| 14372 | |
| 14373 | if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') |
| 14374 | while (isspace(UCHAR(str[pos]))) |
| 14375 | ++pos; |
| 14376 | |
| 14377 | scanned = pos - anchor; |
| 14378 | |
| 14379 | |
| 14380 | if (descr->type == 'n') { |
| 14381 | |
| 14382 | *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); |
| 14383 | } |
| 14384 | else if (pos >= strLen) { |
| 14385 | |
| 14386 | return -1; |
| 14387 | } |
| 14388 | else if (descr->type == 'c') { |
| 14389 | int c; |
| 14390 | scanned += utf8_tounicode(&str[pos], &c); |
| 14391 | *valObjPtr = Jim_NewIntObj(interp, c); |
| 14392 | return scanned; |
| 14393 | } |
| 14394 | else { |
| 14395 | |
| 14396 | if (descr->width > 0) { |
| 14397 | size_t sLen = utf8_strlen(&str[pos], strLen - pos); |
| 14398 | size_t tLen = descr->width > sLen ? sLen : descr->width; |
| 14399 | |
| 14400 | tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); |
| 14401 | tok = tmpObj->bytes; |
| 14402 | } |
| 14403 | else { |
| 14404 | |
| 14405 | tok = &str[pos]; |
| 14406 | } |
| 14407 | switch (descr->type) { |
| 14408 | case 'd': |
| 14409 | case 'o': |
| 14410 | case 'x': |
| 14411 | case 'u': |
| 14412 | case 'i':{ |
| 14413 | char *endp; |
| 14414 | jim_wide w; |
| 14415 | |
| 14416 | int base = descr->type == 'o' ? 8 |
| 14417 | : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10; |
| 14418 | |
| 14419 | |
| 14420 | if (base == 0) { |
| 14421 | w = jim_strtoull(tok, &endp); |
| 14422 | } |
| 14423 | else { |
| 14424 | w = strtoull(tok, &endp, base); |
| 14425 | } |
| 14426 | |
| 14427 | if (endp != tok) { |
| 14428 | |
| 14429 | *valObjPtr = Jim_NewIntObj(interp, w); |
| 14430 | |
| 14431 | |
| 14432 | scanned += endp - tok; |
| 14433 | } |
| 14434 | else { |
| 14435 | scanned = *tok ? 0 : -1; |
| 14436 | } |
| @@ -14665,13 +14447,13 @@ | |
| 14447 | case 'g':{ |
| 14448 | char *endp; |
| 14449 | double value = strtod(tok, &endp); |
| 14450 | |
| 14451 | if (endp != tok) { |
| 14452 | |
| 14453 | *valObjPtr = Jim_NewDoubleObj(interp, value); |
| 14454 | |
| 14455 | scanned += endp - tok; |
| 14456 | } |
| 14457 | else { |
| 14458 | scanned = *tok ? 0 : -1; |
| 14459 | } |
| @@ -14696,65 +14478,65 @@ | |
| 14478 | Jim_Obj **resultVec = 0; |
| 14479 | int resultc; |
| 14480 | Jim_Obj *emptyStr = 0; |
| 14481 | ScanFmtStringObj *fmtObj; |
| 14482 | |
| 14483 | |
| 14484 | JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format")); |
| 14485 | |
| 14486 | fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr; |
| 14487 | |
| 14488 | if (fmtObj->error != 0) { |
| 14489 | if (flags & JIM_ERRMSG) |
| 14490 | Jim_SetResultString(interp, fmtObj->error, -1); |
| 14491 | return 0; |
| 14492 | } |
| 14493 | |
| 14494 | emptyStr = Jim_NewEmptyStringObj(interp); |
| 14495 | Jim_IncrRefCount(emptyStr); |
| 14496 | |
| 14497 | resultList = Jim_NewListObj(interp, NULL, 0); |
| 14498 | if (fmtObj->maxPos > 0) { |
| 14499 | for (i = 0; i < fmtObj->maxPos; ++i) |
| 14500 | Jim_ListAppendElement(interp, resultList, emptyStr); |
| 14501 | JimListGetElements(interp, resultList, &resultc, &resultVec); |
| 14502 | } |
| 14503 | |
| 14504 | for (i = 0, pos = 0; i < fmtObj->count; ++i) { |
| 14505 | ScanFmtPartDescr *descr = &(fmtObj->descr[i]); |
| 14506 | Jim_Obj *value = 0; |
| 14507 | |
| 14508 | |
| 14509 | if (descr->type == 0) |
| 14510 | continue; |
| 14511 | |
| 14512 | if (scanned > 0) |
| 14513 | scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); |
| 14514 | |
| 14515 | if (scanned == -1 && i == 0) |
| 14516 | goto eof; |
| 14517 | |
| 14518 | pos += scanned; |
| 14519 | |
| 14520 | |
| 14521 | if (value == 0) |
| 14522 | value = Jim_NewEmptyStringObj(interp); |
| 14523 | |
| 14524 | if (descr->pos == -1) { |
| 14525 | Jim_FreeNewObj(interp, value); |
| 14526 | } |
| 14527 | else if (descr->pos == 0) |
| 14528 | |
| 14529 | Jim_ListAppendElement(interp, resultList, value); |
| 14530 | else if (resultVec[descr->pos - 1] == emptyStr) { |
| 14531 | |
| 14532 | Jim_DecrRefCount(interp, resultVec[descr->pos - 1]); |
| 14533 | Jim_IncrRefCount(value); |
| 14534 | resultVec[descr->pos - 1] = value; |
| 14535 | } |
| 14536 | else { |
| 14537 | |
| 14538 | Jim_FreeNewObj(interp, value); |
| 14539 | goto err; |
| 14540 | } |
| 14541 | } |
| 14542 | Jim_DecrRefCount(interp, emptyStr); |
| @@ -14792,15 +14574,15 @@ | |
| 14574 | { |
| 14575 | Jim_PrngState *prng; |
| 14576 | unsigned char *destByte = (unsigned char *)dest; |
| 14577 | unsigned int si, sj, x; |
| 14578 | |
| 14579 | |
| 14580 | if (interp->prngState == NULL) |
| 14581 | JimPrngInit(interp); |
| 14582 | prng = interp->prngState; |
| 14583 | |
| 14584 | for (x = 0; x < len; x++) { |
| 14585 | prng->i = (prng->i + 1) & 0xff; |
| 14586 | si = prng->sbox[prng->i]; |
| 14587 | prng->j = (prng->j + si) & 0xff; |
| 14588 | sj = prng->sbox[prng->j]; |
| @@ -14814,19 +14596,19 @@ | |
| 14596 | static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen) |
| 14597 | { |
| 14598 | int i; |
| 14599 | Jim_PrngState *prng; |
| 14600 | |
| 14601 | |
| 14602 | if (interp->prngState == NULL) |
| 14603 | JimPrngInit(interp); |
| 14604 | prng = interp->prngState; |
| 14605 | |
| 14606 | |
| 14607 | for (i = 0; i < 256; i++) |
| 14608 | prng->sbox[i] = i; |
| 14609 | |
| 14610 | for (i = 0; i < seedLen; i++) { |
| 14611 | unsigned char t; |
| 14612 | |
| 14613 | t = prng->sbox[i & 0xFF]; |
| 14614 | prng->sbox[i & 0xFF] = prng->sbox[seed[i]]; |
| @@ -14853,11 +14635,11 @@ | |
| 14635 | if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) |
| 14636 | return JIM_ERR; |
| 14637 | } |
| 14638 | intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 14639 | if (!intObjPtr) { |
| 14640 | |
| 14641 | wideValue = 0; |
| 14642 | } |
| 14643 | else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) { |
| 14644 | return JIM_ERR; |
| 14645 | } |
| @@ -14867,26 +14649,26 @@ | |
| 14649 | Jim_FreeNewObj(interp, intObjPtr); |
| 14650 | return JIM_ERR; |
| 14651 | } |
| 14652 | } |
| 14653 | else { |
| 14654 | |
| 14655 | Jim_InvalidateStringRep(intObjPtr); |
| 14656 | JimWideValue(intObjPtr) = wideValue + increment; |
| 14657 | |
| 14658 | if (argv[1]->typePtr != &variableObjType) { |
| 14659 | |
| 14660 | Jim_SetVariable(interp, argv[1], intObjPtr); |
| 14661 | } |
| 14662 | } |
| 14663 | Jim_SetResult(interp, intObjPtr); |
| 14664 | return JIM_OK; |
| 14665 | } |
| 14666 | |
| 14667 | |
| 14668 | #define JIM_EVAL_SARGV_LEN 8 |
| 14669 | #define JIM_EVAL_SINTV_LEN 8 |
| 14670 | |
| 14671 | |
| 14672 | static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 14673 | { |
| 14674 | int retcode; |
| @@ -14894,16 +14676,16 @@ | |
| 14676 | if (interp->unknown_called > 50) { |
| 14677 | return JIM_ERR; |
| 14678 | } |
| 14679 | |
| 14680 | |
| 14681 | |
| 14682 | if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) |
| 14683 | return JIM_ERR; |
| 14684 | |
| 14685 | interp->unknown_called++; |
| 14686 | |
| 14687 | retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv); |
| 14688 | interp->unknown_called--; |
| 14689 | |
| 14690 | return retcode; |
| 14691 | } |
| @@ -14910,10 +14692,11 @@ | |
| 14692 | |
| 14693 | static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14694 | { |
| 14695 | int retcode; |
| 14696 | Jim_Cmd *cmdPtr; |
| 14697 | void *prevPrivData; |
| 14698 | |
| 14699 | #if 0 |
| 14700 | printf("invoke"); |
| 14701 | int j; |
| 14702 | for (j = 0; j < objc; j++) { |
| @@ -14921,11 +14704,11 @@ | |
| 14704 | } |
| 14705 | printf("\n"); |
| 14706 | #endif |
| 14707 | |
| 14708 | if (interp->framePtr->tailcallCmd) { |
| 14709 | |
| 14710 | cmdPtr = interp->framePtr->tailcallCmd; |
| 14711 | interp->framePtr->tailcallCmd = NULL; |
| 14712 | } |
| 14713 | else { |
| 14714 | cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); |
| @@ -14939,20 +14722,22 @@ | |
| 14722 | Jim_SetResultString(interp, "Infinite eval recursion", -1); |
| 14723 | retcode = JIM_ERR; |
| 14724 | goto out; |
| 14725 | } |
| 14726 | interp->evalDepth++; |
| 14727 | prevPrivData = interp->cmdPrivData; |
| 14728 | |
| 14729 | |
| 14730 | Jim_SetEmptyResult(interp); |
| 14731 | if (cmdPtr->isproc) { |
| 14732 | retcode = JimCallProcedure(interp, cmdPtr, objc, objv); |
| 14733 | } |
| 14734 | else { |
| 14735 | interp->cmdPrivData = cmdPtr->u.native.privData; |
| 14736 | retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); |
| 14737 | } |
| 14738 | interp->cmdPrivData = prevPrivData; |
| 14739 | interp->evalDepth--; |
| 14740 | |
| 14741 | out: |
| 14742 | JimDecrCmdRefCount(interp, cmdPtr); |
| 14743 | |
| @@ -14961,17 +14746,17 @@ | |
| 14746 | |
| 14747 | int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 14748 | { |
| 14749 | int i, retcode; |
| 14750 | |
| 14751 | |
| 14752 | for (i = 0; i < objc; i++) |
| 14753 | Jim_IncrRefCount(objv[i]); |
| 14754 | |
| 14755 | retcode = JimInvokeCommand(interp, objc, objv); |
| 14756 | |
| 14757 | |
| 14758 | for (i = 0; i < objc; i++) |
| 14759 | Jim_DecrRefCount(interp, objv[i]); |
| 14760 | |
| 14761 | return retcode; |
| 14762 | } |
| @@ -14989,25 +14774,25 @@ | |
| 14774 | } |
| 14775 | |
| 14776 | static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script) |
| 14777 | { |
| 14778 | if (!interp->errorFlag) { |
| 14779 | |
| 14780 | interp->errorFlag = 1; |
| 14781 | Jim_IncrRefCount(script->fileNameObj); |
| 14782 | Jim_DecrRefCount(interp, interp->errorFileNameObj); |
| 14783 | interp->errorFileNameObj = script->fileNameObj; |
| 14784 | interp->errorLine = script->linenr; |
| 14785 | |
| 14786 | JimResetStackTrace(interp); |
| 14787 | |
| 14788 | interp->addStackTrace++; |
| 14789 | } |
| 14790 | |
| 14791 | |
| 14792 | if (interp->addStackTrace > 0) { |
| 14793 | |
| 14794 | |
| 14795 | JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr); |
| 14796 | |
| 14797 | if (Jim_Length(script->fileNameObj)) { |
| 14798 | interp->addStackTrace = 0; |
| @@ -15042,14 +14827,14 @@ | |
| 14827 | case JIM_OK: |
| 14828 | case JIM_RETURN: |
| 14829 | objPtr = interp->result; |
| 14830 | break; |
| 14831 | case JIM_BREAK: |
| 14832 | |
| 14833 | return JIM_BREAK; |
| 14834 | case JIM_CONTINUE: |
| 14835 | |
| 14836 | return JIM_CONTINUE; |
| 14837 | default: |
| 14838 | return JIM_ERR; |
| 14839 | } |
| 14840 | break; |
| @@ -15084,23 +14869,23 @@ | |
| 14869 | case JIM_OK: |
| 14870 | case JIM_RETURN: |
| 14871 | break; |
| 14872 | case JIM_BREAK: |
| 14873 | if (flags & JIM_SUBST_FLAG) { |
| 14874 | |
| 14875 | tokens = i; |
| 14876 | continue; |
| 14877 | } |
| 14878 | |
| 14879 | |
| 14880 | case JIM_CONTINUE: |
| 14881 | if (flags & JIM_SUBST_FLAG) { |
| 14882 | intv[i] = NULL; |
| 14883 | continue; |
| 14884 | } |
| 14885 | |
| 14886 | |
| 14887 | default: |
| 14888 | while (i--) { |
| 14889 | Jim_DecrRefCount(interp, intv[i]); |
| 14890 | } |
| 14891 | if (intv != sintv) { |
| @@ -15111,28 +14896,29 @@ | |
| 14896 | Jim_IncrRefCount(intv[i]); |
| 14897 | Jim_String(intv[i]); |
| 14898 | totlen += intv[i]->length; |
| 14899 | } |
| 14900 | |
| 14901 | |
| 14902 | if (tokens == 1 && intv[0] && intv == sintv) { |
| 14903 | |
| 14904 | intv[0]->refCount--; |
| 14905 | return intv[0]; |
| 14906 | } |
| 14907 | |
| 14908 | objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); |
| 14909 | |
| 14910 | if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC |
| 14911 | && token[2].type == JIM_TT_VAR) { |
| 14912 | |
| 14913 | objPtr->typePtr = &interpolatedObjType; |
| 14914 | objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; |
| 14915 | objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; |
| 14916 | Jim_IncrRefCount(intv[2]); |
| 14917 | } |
| 14918 | else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { |
| 14919 | |
| 14920 | JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); |
| 14921 | } |
| 14922 | |
| 14923 | |
| 14924 | s = objPtr->bytes = Jim_Alloc(totlen + 1); |
| @@ -15143,11 +14929,11 @@ | |
| 14929 | s += intv[i]->length; |
| 14930 | Jim_DecrRefCount(interp, intv[i]); |
| 14931 | } |
| 14932 | } |
| 14933 | objPtr->bytes[totlen] = '\0'; |
| 14934 | |
| 14935 | if (intv != sintv) { |
| 14936 | Jim_Free(intv); |
| 14937 | } |
| 14938 | |
| 14939 | return objPtr; |
| @@ -15187,11 +14973,11 @@ | |
| 14973 | |
| 14974 | if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { |
| 14975 | return JimEvalObjList(interp, scriptObjPtr); |
| 14976 | } |
| 14977 | |
| 14978 | Jim_IncrRefCount(scriptObjPtr); |
| 14979 | script = JimGetScript(interp, scriptObjPtr); |
| 14980 | if (!JimScriptValid(interp, script)) { |
| 14981 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 14982 | return JIM_ERR; |
| 14983 | } |
| @@ -15223,11 +15009,11 @@ | |
| 15009 | } |
| 15010 | #endif |
| 15011 | |
| 15012 | script->inUse++; |
| 15013 | |
| 15014 | |
| 15015 | prevScriptObj = interp->currentScriptObj; |
| 15016 | interp->currentScriptObj = scriptObjPtr; |
| 15017 | |
| 15018 | interp->errorFlag = 0; |
| 15019 | argv = sargv; |
| @@ -15234,19 +15020,19 @@ | |
| 15020 | |
| 15021 | for (i = 0; i < script->len && retcode == JIM_OK; ) { |
| 15022 | int argc; |
| 15023 | int j; |
| 15024 | |
| 15025 | |
| 15026 | argc = token[i].objPtr->internalRep.scriptLineValue.argc; |
| 15027 | script->linenr = token[i].objPtr->internalRep.scriptLineValue.line; |
| 15028 | |
| 15029 | |
| 15030 | if (argc > JIM_EVAL_SARGV_LEN) |
| 15031 | argv = Jim_Alloc(sizeof(Jim_Obj *) * argc); |
| 15032 | |
| 15033 | |
| 15034 | i++; |
| 15035 | |
| 15036 | for (j = 0; j < argc; j++) { |
| 15037 | long wordtokens = 1; |
| 15038 | int expand = 0; |
| @@ -15302,11 +15088,11 @@ | |
| 15088 | |
| 15089 | if (!expand) { |
| 15090 | argv[j] = wordObjPtr; |
| 15091 | } |
| 15092 | else { |
| 15093 | |
| 15094 | int len = Jim_ListLength(interp, wordObjPtr); |
| 15095 | int newargc = argc + len - 1; |
| 15096 | int k; |
| 15097 | |
| 15098 | if (len > 1) { |
| @@ -15315,39 +15101,39 @@ | |
| 15101 | argv = Jim_Alloc(sizeof(*argv) * newargc); |
| 15102 | memcpy(argv, sargv, sizeof(*argv) * j); |
| 15103 | } |
| 15104 | } |
| 15105 | else { |
| 15106 | |
| 15107 | argv = Jim_Realloc(argv, sizeof(*argv) * newargc); |
| 15108 | } |
| 15109 | } |
| 15110 | |
| 15111 | |
| 15112 | for (k = 0; k < len; k++) { |
| 15113 | argv[j++] = wordObjPtr->internalRep.listValue.ele[k]; |
| 15114 | Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]); |
| 15115 | } |
| 15116 | |
| 15117 | Jim_DecrRefCount(interp, wordObjPtr); |
| 15118 | |
| 15119 | |
| 15120 | j--; |
| 15121 | argc += len - 1; |
| 15122 | } |
| 15123 | } |
| 15124 | |
| 15125 | if (retcode == JIM_OK && argc) { |
| 15126 | |
| 15127 | retcode = JimInvokeCommand(interp, argc, argv); |
| 15128 | |
| 15129 | if (Jim_CheckSignal(interp)) { |
| 15130 | retcode = JIM_SIGNAL; |
| 15131 | } |
| 15132 | } |
| 15133 | |
| 15134 | |
| 15135 | while (j-- > 0) { |
| 15136 | Jim_DecrRefCount(interp, argv[j]); |
| 15137 | } |
| 15138 | |
| 15139 | if (argv != sargv) { |
| @@ -15354,21 +15140,21 @@ | |
| 15140 | Jim_Free(argv); |
| 15141 | argv = sargv; |
| 15142 | } |
| 15143 | } |
| 15144 | |
| 15145 | |
| 15146 | if (retcode == JIM_ERR) { |
| 15147 | JimAddErrorToStack(interp, script); |
| 15148 | } |
| 15149 | |
| 15150 | else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) { |
| 15151 | |
| 15152 | interp->addStackTrace = 0; |
| 15153 | } |
| 15154 | |
| 15155 | |
| 15156 | interp->currentScriptObj = prevScriptObj; |
| 15157 | |
| 15158 | Jim_FreeIntRep(interp, scriptObjPtr); |
| 15159 | scriptObjPtr->typePtr = &scriptObjType; |
| 15160 | Jim_SetIntRepPtr(scriptObjPtr, script); |
| @@ -15378,14 +15164,14 @@ | |
| 15164 | } |
| 15165 | |
| 15166 | static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj) |
| 15167 | { |
| 15168 | int retcode; |
| 15169 | |
| 15170 | const char *varname = Jim_String(argNameObj); |
| 15171 | if (*varname == '&') { |
| 15172 | |
| 15173 | Jim_Obj *objPtr; |
| 15174 | Jim_CallFrame *savedCallFrame = interp->framePtr; |
| 15175 | |
| 15176 | interp->framePtr = interp->framePtr->parent; |
| 15177 | objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG); |
| @@ -15392,11 +15178,11 @@ | |
| 15178 | interp->framePtr = savedCallFrame; |
| 15179 | if (!objPtr) { |
| 15180 | return JIM_ERR; |
| 15181 | } |
| 15182 | |
| 15183 | |
| 15184 | objPtr = Jim_NewStringObj(interp, varname + 1, -1); |
| 15185 | Jim_IncrRefCount(objPtr); |
| 15186 | retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent); |
| 15187 | Jim_DecrRefCount(interp, objPtr); |
| 15188 | } |
| @@ -15406,26 +15192,26 @@ | |
| 15192 | return retcode; |
| 15193 | } |
| 15194 | |
| 15195 | static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd) |
| 15196 | { |
| 15197 | |
| 15198 | Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0); |
| 15199 | int i; |
| 15200 | |
| 15201 | for (i = 0; i < cmd->u.proc.argListLen; i++) { |
| 15202 | Jim_AppendString(interp, argmsg, " ", 1); |
| 15203 | |
| 15204 | if (i == cmd->u.proc.argsPos) { |
| 15205 | if (cmd->u.proc.arglist[i].defaultObjPtr) { |
| 15206 | |
| 15207 | Jim_AppendString(interp, argmsg, "?", 1); |
| 15208 | Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); |
| 15209 | Jim_AppendString(interp, argmsg, " ...?", -1); |
| 15210 | } |
| 15211 | else { |
| 15212 | |
| 15213 | Jim_AppendString(interp, argmsg, "?arg...?", -1); |
| 15214 | } |
| 15215 | } |
| 15216 | else { |
| 15217 | if (cmd->u.proc.arglist[i].defaultObjPtr) { |
| @@ -15441,20 +15227,19 @@ | |
| 15227 | Jim_AppendString(interp, argmsg, arg, -1); |
| 15228 | } |
| 15229 | } |
| 15230 | } |
| 15231 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg); |
| 15232 | } |
| 15233 | |
| 15234 | #ifdef jim_ext_namespace |
| 15235 | int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj) |
| 15236 | { |
| 15237 | Jim_CallFrame *callFramePtr; |
| 15238 | int retcode; |
| 15239 | |
| 15240 | |
| 15241 | callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj); |
| 15242 | callFramePtr->argv = &interp->emptyObj; |
| 15243 | callFramePtr->argc = 0; |
| 15244 | callFramePtr->procArgsObjPtr = NULL; |
| 15245 | callFramePtr->procBodyObjPtr = scriptObj; |
| @@ -15462,21 +15247,21 @@ | |
| 15247 | callFramePtr->fileNameObj = interp->emptyObj; |
| 15248 | callFramePtr->line = 0; |
| 15249 | Jim_IncrRefCount(scriptObj); |
| 15250 | interp->framePtr = callFramePtr; |
| 15251 | |
| 15252 | |
| 15253 | if (interp->framePtr->level == interp->maxCallFrameDepth) { |
| 15254 | Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); |
| 15255 | retcode = JIM_ERR; |
| 15256 | } |
| 15257 | else { |
| 15258 | |
| 15259 | retcode = Jim_EvalObj(interp, scriptObj); |
| 15260 | } |
| 15261 | |
| 15262 | |
| 15263 | interp->framePtr = interp->framePtr->parent; |
| 15264 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15265 | |
| 15266 | return retcode; |
| 15267 | } |
| @@ -15486,62 +15271,62 @@ | |
| 15271 | { |
| 15272 | Jim_CallFrame *callFramePtr; |
| 15273 | int i, d, retcode, optargs; |
| 15274 | ScriptObj *script; |
| 15275 | |
| 15276 | |
| 15277 | if (argc - 1 < cmd->u.proc.reqArity || |
| 15278 | (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { |
| 15279 | JimSetProcWrongArgs(interp, argv[0], cmd); |
| 15280 | return JIM_ERR; |
| 15281 | } |
| 15282 | |
| 15283 | if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) { |
| 15284 | |
| 15285 | return JIM_OK; |
| 15286 | } |
| 15287 | |
| 15288 | |
| 15289 | if (interp->framePtr->level == interp->maxCallFrameDepth) { |
| 15290 | Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); |
| 15291 | return JIM_ERR; |
| 15292 | } |
| 15293 | |
| 15294 | |
| 15295 | callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj); |
| 15296 | callFramePtr->argv = argv; |
| 15297 | callFramePtr->argc = argc; |
| 15298 | callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; |
| 15299 | callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; |
| 15300 | callFramePtr->staticVars = cmd->u.proc.staticVars; |
| 15301 | |
| 15302 | |
| 15303 | script = JimGetScript(interp, interp->currentScriptObj); |
| 15304 | callFramePtr->fileNameObj = script->fileNameObj; |
| 15305 | callFramePtr->line = script->linenr; |
| 15306 | |
| 15307 | Jim_IncrRefCount(cmd->u.proc.argListObjPtr); |
| 15308 | Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); |
| 15309 | interp->framePtr = callFramePtr; |
| 15310 | |
| 15311 | |
| 15312 | optargs = (argc - 1 - cmd->u.proc.reqArity); |
| 15313 | |
| 15314 | |
| 15315 | i = 1; |
| 15316 | for (d = 0; d < cmd->u.proc.argListLen; d++) { |
| 15317 | Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr; |
| 15318 | if (d == cmd->u.proc.argsPos) { |
| 15319 | |
| 15320 | Jim_Obj *listObjPtr; |
| 15321 | int argsLen = 0; |
| 15322 | if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) { |
| 15323 | argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity); |
| 15324 | } |
| 15325 | listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen); |
| 15326 | |
| 15327 | |
| 15328 | if (cmd->u.proc.arglist[d].defaultObjPtr) { |
| 15329 | nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr; |
| 15330 | } |
| 15331 | retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr); |
| 15332 | if (retcode != JIM_OK) { |
| @@ -15550,33 +15335,34 @@ | |
| 15335 | |
| 15336 | i += argsLen; |
| 15337 | continue; |
| 15338 | } |
| 15339 | |
| 15340 | |
| 15341 | if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) { |
| 15342 | retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]); |
| 15343 | } |
| 15344 | else { |
| 15345 | |
| 15346 | retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr); |
| 15347 | } |
| 15348 | if (retcode != JIM_OK) { |
| 15349 | goto badargset; |
| 15350 | } |
| 15351 | } |
| 15352 | |
| 15353 | |
| 15354 | retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); |
| 15355 | |
| 15356 | badargset: |
| 15357 | |
| 15358 | |
| 15359 | retcode = JimInvokeDefer(interp, retcode); |
| 15360 | interp->framePtr = interp->framePtr->parent; |
| 15361 | JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); |
| 15362 | |
| 15363 | |
| 15364 | if (interp->framePtr->tailcallObj) { |
| 15365 | do { |
| 15366 | Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; |
| 15367 | |
| 15368 | interp->framePtr->tailcallObj = NULL; |
| @@ -15588,18 +15374,18 @@ | |
| 15374 | } |
| 15375 | } |
| 15376 | Jim_DecrRefCount(interp, tailcallObj); |
| 15377 | } while (interp->framePtr->tailcallObj); |
| 15378 | |
| 15379 | |
| 15380 | if (interp->framePtr->tailcallCmd) { |
| 15381 | JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); |
| 15382 | interp->framePtr->tailcallCmd = NULL; |
| 15383 | } |
| 15384 | } |
| 15385 | |
| 15386 | |
| 15387 | if (retcode == JIM_RETURN) { |
| 15388 | if (--interp->returnLevel <= 0) { |
| 15389 | retcode = interp->returnCode; |
| 15390 | interp->returnCode = JIM_OK; |
| 15391 | interp->returnLevel = 0; |
| @@ -15711,20 +15497,20 @@ | |
| 15497 | prevScriptObj = interp->currentScriptObj; |
| 15498 | interp->currentScriptObj = scriptObjPtr; |
| 15499 | |
| 15500 | retcode = Jim_EvalObj(interp, scriptObjPtr); |
| 15501 | |
| 15502 | |
| 15503 | if (retcode == JIM_RETURN) { |
| 15504 | if (--interp->returnLevel <= 0) { |
| 15505 | retcode = interp->returnCode; |
| 15506 | interp->returnCode = JIM_OK; |
| 15507 | interp->returnLevel = 0; |
| 15508 | } |
| 15509 | } |
| 15510 | if (retcode == JIM_ERR) { |
| 15511 | |
| 15512 | interp->addStackTrace++; |
| 15513 | } |
| 15514 | |
| 15515 | interp->currentScriptObj = prevScriptObj; |
| 15516 | |
| @@ -15750,11 +15536,11 @@ | |
| 15536 | } |
| 15537 | if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { |
| 15538 | if (JimParseVar(pc) == JIM_OK) { |
| 15539 | return; |
| 15540 | } |
| 15541 | |
| 15542 | pc->tstart = pc->p; |
| 15543 | flags |= JIM_SUBST_NOVAR; |
| 15544 | } |
| 15545 | while (pc->len) { |
| 15546 | if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { |
| @@ -15781,32 +15567,32 @@ | |
| 15567 | const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); |
| 15568 | struct JimParserCtx parser; |
| 15569 | struct ScriptObj *script = Jim_Alloc(sizeof(*script)); |
| 15570 | ParseTokenList tokenlist; |
| 15571 | |
| 15572 | |
| 15573 | ScriptTokenListInit(&tokenlist); |
| 15574 | |
| 15575 | JimParserInit(&parser, scriptText, scriptTextLen, 1); |
| 15576 | while (1) { |
| 15577 | JimParseSubst(&parser, flags); |
| 15578 | if (parser.eof) { |
| 15579 | |
| 15580 | break; |
| 15581 | } |
| 15582 | ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, |
| 15583 | parser.tline); |
| 15584 | } |
| 15585 | |
| 15586 | |
| 15587 | script->inUse = 1; |
| 15588 | script->substFlags = flags; |
| 15589 | script->fileNameObj = interp->emptyObj; |
| 15590 | Jim_IncrRefCount(script->fileNameObj); |
| 15591 | SubstObjAddTokens(interp, script, &tokenlist); |
| 15592 | |
| 15593 | |
| 15594 | ScriptTokenListFree(&tokenlist); |
| 15595 | |
| 15596 | #ifdef DEBUG_SHOW_SUBST |
| 15597 | { |
| 15598 | int i; |
| @@ -15817,11 +15603,11 @@ | |
| 15603 | Jim_String(script->token[i].objPtr)); |
| 15604 | } |
| 15605 | } |
| 15606 | #endif |
| 15607 | |
| 15608 | |
| 15609 | Jim_FreeIntRep(interp, objPtr); |
| 15610 | Jim_SetIntRepPtr(objPtr, script); |
| 15611 | objPtr->typePtr = &scriptObjType; |
| 15612 | return JIM_OK; |
| 15613 | } |
| @@ -15835,11 +15621,11 @@ | |
| 15621 | |
| 15622 | int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) |
| 15623 | { |
| 15624 | ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); |
| 15625 | |
| 15626 | Jim_IncrRefCount(substObjPtr); |
| 15627 | script->inUse++; |
| 15628 | |
| 15629 | *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); |
| 15630 | |
| 15631 | script->inUse--; |
| @@ -15851,22 +15637,24 @@ | |
| 15637 | } |
| 15638 | |
| 15639 | void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg) |
| 15640 | { |
| 15641 | Jim_Obj *objPtr; |
| 15642 | Jim_Obj *listObjPtr; |
| 15643 | |
| 15644 | JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0")); |
| 15645 | |
| 15646 | listObjPtr = Jim_NewListObj(interp, argv, argc); |
| 15647 | |
| 15648 | if (msg && *msg) { |
| 15649 | Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1)); |
| 15650 | } |
| 15651 | Jim_IncrRefCount(listObjPtr); |
| 15652 | objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1); |
| 15653 | Jim_DecrRefCount(interp, listObjPtr); |
| 15654 | |
| 15655 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr); |
| 15656 | } |
| 15657 | |
| 15658 | typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, |
| 15659 | Jim_HashEntry *he, int type); |
| 15660 | |
| @@ -15876,11 +15664,11 @@ | |
| 15664 | JimHashtableIteratorCallbackType *callback, int type) |
| 15665 | { |
| 15666 | Jim_HashEntry *he; |
| 15667 | Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 15668 | |
| 15669 | |
| 15670 | if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { |
| 15671 | he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); |
| 15672 | if (he) { |
| 15673 | callback(interp, listObjPtr, he, type); |
| 15674 | } |
| @@ -15907,11 +15695,11 @@ | |
| 15695 | { |
| 15696 | Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); |
| 15697 | Jim_Obj *objPtr; |
| 15698 | |
| 15699 | if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { |
| 15700 | |
| 15701 | return; |
| 15702 | } |
| 15703 | |
| 15704 | objPtr = Jim_NewStringObj(interp, he->key, -1); |
| 15705 | Jim_IncrRefCount(objPtr); |
| @@ -15967,11 +15755,11 @@ | |
| 15755 | |
| 15756 | targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); |
| 15757 | if (targetCallFrame == NULL) { |
| 15758 | return JIM_ERR; |
| 15759 | } |
| 15760 | |
| 15761 | if (targetCallFrame == interp->topFramePtr) { |
| 15762 | Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); |
| 15763 | return JIM_ERR; |
| 15764 | } |
| 15765 | if (info_level_cmd) { |
| @@ -16095,12 +15883,17 @@ | |
| 15883 | doubleRes = (double)res; |
| 15884 | goto trydouble; |
| 15885 | } |
| 15886 | if (op == JIM_EXPROP_SUB) |
| 15887 | res -= wideValue; |
| 15888 | else { |
| 15889 | if (wideValue == 0) { |
| 15890 | Jim_SetResultString(interp, "Division by zero", -1); |
| 15891 | return JIM_ERR; |
| 15892 | } |
| 15893 | res /= wideValue; |
| 15894 | } |
| 15895 | } |
| 15896 | Jim_SetResultInt(interp, res); |
| 15897 | return JIM_OK; |
| 15898 | trydouble: |
| 15899 | for (; i < argc; i++) { |
| @@ -16154,11 +15947,11 @@ | |
| 15947 | if (!objPtr) |
| 15948 | return JIM_ERR; |
| 15949 | Jim_SetResult(interp, objPtr); |
| 15950 | return JIM_OK; |
| 15951 | } |
| 15952 | |
| 15953 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 15954 | return JIM_ERR; |
| 15955 | Jim_SetResult(interp, argv[2]); |
| 15956 | return JIM_OK; |
| 15957 | } |
| @@ -16197,11 +15990,11 @@ | |
| 15990 | if (argc != 3) { |
| 15991 | Jim_WrongNumArgs(interp, 1, argv, "condition body"); |
| 15992 | return JIM_ERR; |
| 15993 | } |
| 15994 | |
| 15995 | |
| 15996 | while (1) { |
| 15997 | int boolean, retval; |
| 15998 | |
| 15999 | if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) |
| 16000 | return retval; |
| @@ -16237,11 +16030,11 @@ | |
| 16030 | if (argc != 5) { |
| 16031 | Jim_WrongNumArgs(interp, 1, argv, "start test next body"); |
| 16032 | return JIM_ERR; |
| 16033 | } |
| 16034 | |
| 16035 | |
| 16036 | if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) { |
| 16037 | return retval; |
| 16038 | } |
| 16039 | |
| 16040 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); |
| @@ -16248,78 +16041,84 @@ | |
| 16041 | |
| 16042 | |
| 16043 | #ifdef JIM_OPTIMIZATION |
| 16044 | if (retval == JIM_OK && boolean) { |
| 16045 | ScriptObj *incrScript; |
| 16046 | struct ExprTree *expr; |
| 16047 | jim_wide stop, currentVal; |
| 16048 | Jim_Obj *objPtr; |
| 16049 | int cmpOffset; |
| 16050 | |
| 16051 | |
| 16052 | expr = JimGetExpression(interp, argv[2]); |
| 16053 | incrScript = JimGetScript(interp, argv[3]); |
| 16054 | |
| 16055 | |
| 16056 | if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { |
| 16057 | goto evalstart; |
| 16058 | } |
| 16059 | |
| 16060 | if (incrScript->token[1].type != JIM_TT_ESC) { |
| 16061 | goto evalstart; |
| 16062 | } |
| 16063 | |
| 16064 | if (expr->expr->type == JIM_EXPROP_LT) { |
| 16065 | cmpOffset = 0; |
| 16066 | } |
| 16067 | else if (expr->expr->type == JIM_EXPROP_LTE) { |
| 16068 | cmpOffset = 1; |
| 16069 | } |
| 16070 | else { |
| 16071 | goto evalstart; |
| 16072 | } |
| 16073 | |
| 16074 | if (expr->expr->left->type != JIM_TT_VAR) { |
| 16075 | goto evalstart; |
| 16076 | } |
| 16077 | |
| 16078 | if (expr->expr->right->type != JIM_TT_VAR && expr->expr->right->type != JIM_TT_EXPR_INT) { |
| 16079 | goto evalstart; |
| 16080 | } |
| 16081 | |
| 16082 | |
| 16083 | if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { |
| 16084 | goto evalstart; |
| 16085 | } |
| 16086 | |
| 16087 | |
| 16088 | if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->expr->left->objPtr)) { |
| 16089 | goto evalstart; |
| 16090 | } |
| 16091 | |
| 16092 | |
| 16093 | if (expr->expr->right->type == JIM_TT_EXPR_INT) { |
| 16094 | if (Jim_GetWide(interp, expr->expr->right->objPtr, &stop) == JIM_ERR) { |
| 16095 | goto evalstart; |
| 16096 | } |
| 16097 | } |
| 16098 | else { |
| 16099 | stopVarNamePtr = expr->expr->right->objPtr; |
| 16100 | Jim_IncrRefCount(stopVarNamePtr); |
| 16101 | |
| 16102 | stop = 0; |
| 16103 | } |
| 16104 | |
| 16105 | |
| 16106 | varNamePtr = expr->expr->left->objPtr; |
| 16107 | Jim_IncrRefCount(varNamePtr); |
| 16108 | |
| 16109 | objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); |
| 16110 | if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { |
| 16111 | goto testcond; |
| 16112 | } |
| 16113 | |
| 16114 | |
| 16115 | while (retval == JIM_OK) { |
| 16116 | |
| 16117 | |
| 16118 | |
| 16119 | |
| 16120 | if (stopVarNamePtr) { |
| 16121 | objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE); |
| 16122 | if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) { |
| 16123 | goto testcond; |
| 16124 | } |
| @@ -16327,18 +16126,18 @@ | |
| 16126 | |
| 16127 | if (currentVal >= stop + cmpOffset) { |
| 16128 | break; |
| 16129 | } |
| 16130 | |
| 16131 | |
| 16132 | retval = Jim_EvalObj(interp, argv[4]); |
| 16133 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16134 | retval = JIM_OK; |
| 16135 | |
| 16136 | objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); |
| 16137 | |
| 16138 | |
| 16139 | if (objPtr == NULL) { |
| 16140 | retval = JIM_ERR; |
| 16141 | goto out; |
| 16142 | } |
| 16143 | if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { |
| @@ -16358,25 +16157,25 @@ | |
| 16157 | } |
| 16158 | evalstart: |
| 16159 | #endif |
| 16160 | |
| 16161 | while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) { |
| 16162 | |
| 16163 | retval = Jim_EvalObj(interp, argv[4]); |
| 16164 | |
| 16165 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16166 | |
| 16167 | JIM_IF_OPTIM(evalnext:) |
| 16168 | retval = Jim_EvalObj(interp, argv[3]); |
| 16169 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16170 | |
| 16171 | JIM_IF_OPTIM(testcond:) |
| 16172 | retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); |
| 16173 | } |
| 16174 | } |
| 16175 | } |
| 16176 | JIM_IF_OPTIM(out:) |
| 16177 | if (stopVarNamePtr) { |
| 16178 | Jim_DecrRefCount(interp, stopVarNamePtr); |
| 16179 | } |
| 16180 | if (varNamePtr) { |
| 16181 | Jim_DecrRefCount(interp, varNamePtr); |
| @@ -16418,11 +16217,11 @@ | |
| 16217 | if (retval == JIM_OK || retval == JIM_CONTINUE) { |
| 16218 | Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); |
| 16219 | |
| 16220 | retval = JIM_OK; |
| 16221 | |
| 16222 | |
| 16223 | i += incr; |
| 16224 | |
| 16225 | if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { |
| 16226 | if (argv[1]->typePtr != &variableObjType) { |
| 16227 | if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { |
| @@ -16483,21 +16282,21 @@ | |
| 16282 | |
| 16283 | static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) |
| 16284 | { |
| 16285 | int result = JIM_OK; |
| 16286 | int i, numargs; |
| 16287 | Jim_ListIter twoiters[2]; |
| 16288 | Jim_ListIter *iters; |
| 16289 | Jim_Obj *script; |
| 16290 | Jim_Obj *resultObj; |
| 16291 | |
| 16292 | if (argc < 4 || argc % 2 != 0) { |
| 16293 | Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script"); |
| 16294 | return JIM_ERR; |
| 16295 | } |
| 16296 | script = argv[argc - 1]; |
| 16297 | numargs = (argc - 1 - 1); |
| 16298 | |
| 16299 | if (numargs == 2) { |
| 16300 | iters = twoiters; |
| 16301 | } |
| 16302 | else { |
| @@ -16521,34 +16320,34 @@ | |
| 16320 | resultObj = interp->emptyObj; |
| 16321 | } |
| 16322 | Jim_IncrRefCount(resultObj); |
| 16323 | |
| 16324 | while (1) { |
| 16325 | |
| 16326 | for (i = 0; i < numargs; i += 2) { |
| 16327 | if (!JimListIterDone(interp, &iters[i + 1])) { |
| 16328 | break; |
| 16329 | } |
| 16330 | } |
| 16331 | if (i == numargs) { |
| 16332 | |
| 16333 | break; |
| 16334 | } |
| 16335 | |
| 16336 | |
| 16337 | for (i = 0; i < numargs; i += 2) { |
| 16338 | Jim_Obj *varName; |
| 16339 | |
| 16340 | |
| 16341 | JimListIterInit(&iters[i], argv[i + 1]); |
| 16342 | while ((varName = JimListIterNext(interp, &iters[i])) != NULL) { |
| 16343 | Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]); |
| 16344 | if (!valObj) { |
| 16345 | |
| 16346 | valObj = interp->emptyObj; |
| 16347 | } |
| 16348 | |
| 16349 | Jim_IncrRefCount(valObj); |
| 16350 | result = Jim_SetVariable(interp, varName, valObj); |
| 16351 | Jim_DecrRefCount(interp, valObj); |
| 16352 | if (result != JIM_OK) { |
| 16353 | goto err; |
| @@ -16630,41 +16429,41 @@ | |
| 16429 | { |
| 16430 | int boolean, retval, current = 1, falsebody = 0; |
| 16431 | |
| 16432 | if (argc >= 3) { |
| 16433 | while (1) { |
| 16434 | |
| 16435 | if (current >= argc) |
| 16436 | goto err; |
| 16437 | if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean)) |
| 16438 | != JIM_OK) |
| 16439 | return retval; |
| 16440 | |
| 16441 | if (current >= argc) |
| 16442 | goto err; |
| 16443 | if (Jim_CompareStringImmediate(interp, argv[current], "then")) |
| 16444 | current++; |
| 16445 | |
| 16446 | if (current >= argc) |
| 16447 | goto err; |
| 16448 | if (boolean) |
| 16449 | return Jim_EvalObj(interp, argv[current]); |
| 16450 | |
| 16451 | if (++current >= argc) { |
| 16452 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 16453 | return JIM_OK; |
| 16454 | } |
| 16455 | falsebody = current++; |
| 16456 | if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) { |
| 16457 | |
| 16458 | if (current != argc - 1) |
| 16459 | goto err; |
| 16460 | return Jim_EvalObj(interp, argv[current]); |
| 16461 | } |
| 16462 | else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif")) |
| 16463 | continue; |
| 16464 | |
| 16465 | else if (falsebody != argc - 1) |
| 16466 | goto err; |
| 16467 | return Jim_EvalObj(interp, argv[falsebody]); |
| 16468 | } |
| 16469 | return JIM_OK; |
| @@ -16698,19 +16497,17 @@ | |
| 16497 | } |
| 16498 | |
| 16499 | return eq; |
| 16500 | } |
| 16501 | |
| 16502 | |
| 16503 | static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 16504 | { |
| 16505 | enum { SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; |
| 16506 | int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; |
| 16507 | Jim_Obj *command = NULL, *scriptObj = NULL, *strObj; |
| 16508 | Jim_Obj **caseList; |
| 16509 | |
| 16510 | if (argc < 3) { |
| 16511 | wrongnumargs: |
| 16512 | Jim_WrongNumArgs(interp, 1, argv, "?options? string " |
| 16513 | "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); |
| @@ -16747,68 +16544,62 @@ | |
| 16544 | goto wrongnumargs; |
| 16545 | } |
| 16546 | strObj = argv[opt++]; |
| 16547 | patCount = argc - opt; |
| 16548 | if (patCount == 1) { |
| 16549 | JimListGetElements(interp, argv[opt], &patCount, &caseList); |
| 16550 | } |
| 16551 | else |
| 16552 | caseList = (Jim_Obj **)&argv[opt]; |
| 16553 | if (patCount == 0 || patCount % 2 != 0) |
| 16554 | goto wrongnumargs; |
| 16555 | for (i = 0; scriptObj == NULL && i < patCount; i += 2) { |
| 16556 | Jim_Obj *patObj = caseList[i]; |
| 16557 | |
| 16558 | if (!Jim_CompareStringImmediate(interp, patObj, "default") |
| 16559 | || i < (patCount - 2)) { |
| 16560 | switch (matchOpt) { |
| 16561 | case SWITCH_EXACT: |
| 16562 | if (Jim_StringEqObj(strObj, patObj)) |
| 16563 | scriptObj = caseList[i + 1]; |
| 16564 | break; |
| 16565 | case SWITCH_GLOB: |
| 16566 | if (Jim_StringMatchObj(interp, patObj, strObj, 0)) |
| 16567 | scriptObj = caseList[i + 1]; |
| 16568 | break; |
| 16569 | case SWITCH_RE: |
| 16570 | command = Jim_NewStringObj(interp, "regexp", -1); |
| 16571 | |
| 16572 | case SWITCH_CMD:{ |
| 16573 | int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); |
| 16574 | |
| 16575 | if (argc - opt == 1) { |
| 16576 | JimListGetElements(interp, argv[opt], &patCount, &caseList); |
| 16577 | } |
| 16578 | |
| 16579 | if (rc < 0) { |
| 16580 | return -rc; |
| 16581 | } |
| 16582 | if (rc) |
| 16583 | scriptObj = caseList[i + 1]; |
| 16584 | break; |
| 16585 | } |
| 16586 | } |
| 16587 | } |
| 16588 | else { |
| 16589 | scriptObj = caseList[i + 1]; |
| 16590 | } |
| 16591 | } |
| 16592 | for (; i < patCount && Jim_CompareStringImmediate(interp, scriptObj, "-"); i += 2) |
| 16593 | scriptObj = caseList[i + 1]; |
| 16594 | if (scriptObj && Jim_CompareStringImmediate(interp, scriptObj, "-")) { |
| 16595 | Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); |
| 16596 | return JIM_ERR; |
| 16597 | } |
| 16598 | Jim_SetEmptyResult(interp); |
| 16599 | if (scriptObj) { |
| 16600 | return Jim_EvalObj(interp, scriptObj); |
| 16601 | } |
| 16602 | return JIM_OK; |
| 16603 | } |
| 16604 | |
| 16605 | |
| @@ -16920,11 +16711,11 @@ | |
| 16711 | case OPT_COMMAND: |
| 16712 | if (i >= argc - 2) { |
| 16713 | goto wrongargs; |
| 16714 | } |
| 16715 | commandObj = argv[++i]; |
| 16716 | |
| 16717 | case OPT_EXACT: |
| 16718 | case OPT_GLOB: |
| 16719 | case OPT_REGEXP: |
| 16720 | opt_match = option; |
| 16721 | break; |
| @@ -16968,17 +16759,17 @@ | |
| 16759 | goto done; |
| 16760 | } |
| 16761 | break; |
| 16762 | } |
| 16763 | |
| 16764 | |
| 16765 | if (!eq && opt_bool && opt_not && !opt_all) { |
| 16766 | continue; |
| 16767 | } |
| 16768 | |
| 16769 | if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { |
| 16770 | |
| 16771 | Jim_Obj *resultObj; |
| 16772 | |
| 16773 | if (opt_bool) { |
| 16774 | resultObj = Jim_NewIntObj(interp, eq ^ opt_not); |
| 16775 | } |
| @@ -17001,11 +16792,11 @@ | |
| 16792 | |
| 16793 | if (opt_all) { |
| 16794 | Jim_SetResult(interp, listObjPtr); |
| 16795 | } |
| 16796 | else { |
| 16797 | |
| 16798 | if (opt_bool) { |
| 16799 | Jim_SetResultBool(interp, opt_not); |
| 16800 | } |
| 16801 | else if (!opt_inline) { |
| 16802 | Jim_SetResultInt(interp, -1); |
| @@ -17030,11 +16821,11 @@ | |
| 16821 | Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); |
| 16822 | return JIM_ERR; |
| 16823 | } |
| 16824 | listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 16825 | if (!listObjPtr) { |
| 16826 | |
| 16827 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 16828 | new_obj = 1; |
| 16829 | } |
| 16830 | else if (Jim_IsShared(listObjPtr)) { |
| 16831 | listObjPtr = Jim_DuplicateObj(interp, listObjPtr); |
| @@ -17103,31 +16894,31 @@ | |
| 16894 | first = JimRelToAbsIndex(len, first); |
| 16895 | last = JimRelToAbsIndex(len, last); |
| 16896 | JimRelToAbsRange(len, &first, &last, &rangeLen); |
| 16897 | |
| 16898 | |
| 16899 | |
| 16900 | if (first < len) { |
| 16901 | |
| 16902 | } |
| 16903 | else if (len == 0) { |
| 16904 | |
| 16905 | first = 0; |
| 16906 | } |
| 16907 | else { |
| 16908 | Jim_SetResultString(interp, "list doesn't contain element ", -1); |
| 16909 | Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]); |
| 16910 | return JIM_ERR; |
| 16911 | } |
| 16912 | |
| 16913 | |
| 16914 | newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first); |
| 16915 | |
| 16916 | |
| 16917 | ListInsertElements(newListObj, -1, argc - 4, argv + 4); |
| 16918 | |
| 16919 | |
| 16920 | ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen); |
| 16921 | |
| 16922 | Jim_SetResult(interp, newListObj); |
| 16923 | return JIM_OK; |
| 16924 | } |
| @@ -17138,11 +16929,11 @@ | |
| 16929 | if (argc < 3) { |
| 16930 | Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); |
| 16931 | return JIM_ERR; |
| 16932 | } |
| 16933 | else if (argc == 3) { |
| 16934 | |
| 16935 | if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) |
| 16936 | return JIM_ERR; |
| 16937 | Jim_SetResult(interp, argv[2]); |
| 16938 | return JIM_OK; |
| 16939 | } |
| @@ -17158,10 +16949,11 @@ | |
| 16949 | enum |
| 16950 | { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; |
| 16951 | Jim_Obj *resObj; |
| 16952 | int i; |
| 16953 | int retCode; |
| 16954 | int shared; |
| 16955 | |
| 16956 | struct lsort_info info; |
| 16957 | |
| 16958 | if (argc < 2) { |
| 16959 | Jim_WrongNumArgs(interp, 1, argv, "?options? list"); |
| @@ -17223,16 +17015,18 @@ | |
| 17015 | info.indexed = 1; |
| 17016 | i++; |
| 17017 | break; |
| 17018 | } |
| 17019 | } |
| 17020 | resObj = argv[argc - 1]; |
| 17021 | if ((shared = Jim_IsShared(resObj))) |
| 17022 | resObj = Jim_DuplicateObj(interp, resObj); |
| 17023 | retCode = ListSortElements(interp, resObj, &info); |
| 17024 | if (retCode == JIM_OK) { |
| 17025 | Jim_SetResult(interp, resObj); |
| 17026 | } |
| 17027 | else if (shared) { |
| 17028 | Jim_FreeNewObj(interp, resObj); |
| 17029 | } |
| 17030 | return retCode; |
| 17031 | } |
| 17032 | |
| @@ -17253,11 +17047,11 @@ | |
| 17047 | } |
| 17048 | else { |
| 17049 | int new_obj = 0; |
| 17050 | stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); |
| 17051 | if (!stringObjPtr) { |
| 17052 | |
| 17053 | stringObjPtr = Jim_NewEmptyStringObj(interp); |
| 17054 | new_obj = 1; |
| 17055 | } |
| 17056 | else if (Jim_IsShared(stringObjPtr)) { |
| 17057 | new_obj = 1; |
| @@ -17274,10 +17068,11 @@ | |
| 17068 | } |
| 17069 | } |
| 17070 | Jim_SetResult(interp, stringObjPtr); |
| 17071 | return JIM_OK; |
| 17072 | } |
| 17073 | |
| 17074 | |
| 17075 | |
| 17076 | static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17077 | { |
| 17078 | #if !defined(JIM_DEBUG_COMMAND) |
| @@ -17302,11 +17097,11 @@ | |
| 17097 | else { |
| 17098 | rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); |
| 17099 | } |
| 17100 | |
| 17101 | if (rc == JIM_ERR) { |
| 17102 | |
| 17103 | interp->addStackTrace++; |
| 17104 | } |
| 17105 | return rc; |
| 17106 | } |
| 17107 | |
| @@ -17316,14 +17111,14 @@ | |
| 17111 | if (argc >= 2) { |
| 17112 | int retcode; |
| 17113 | Jim_CallFrame *savedCallFrame, *targetCallFrame; |
| 17114 | const char *str; |
| 17115 | |
| 17116 | |
| 17117 | savedCallFrame = interp->framePtr; |
| 17118 | |
| 17119 | |
| 17120 | str = Jim_String(argv[1]); |
| 17121 | if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { |
| 17122 | targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17123 | argc--; |
| 17124 | argv++; |
| @@ -17336,11 +17131,11 @@ | |
| 17131 | } |
| 17132 | if (argc < 2) { |
| 17133 | Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); |
| 17134 | return JIM_ERR; |
| 17135 | } |
| 17136 | |
| 17137 | interp->framePtr = targetCallFrame; |
| 17138 | if (argc == 2) { |
| 17139 | retcode = Jim_EvalObj(interp, argv[1]); |
| 17140 | } |
| 17141 | else { |
| @@ -17356,32 +17151,29 @@ | |
| 17151 | } |
| 17152 | |
| 17153 | |
| 17154 | static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17155 | { |
| 17156 | int retcode; |
| 17157 | |
| 17158 | if (argc == 2) { |
| 17159 | retcode = Jim_EvalExpression(interp, argv[1]); |
| 17160 | } |
| 17161 | else if (argc > 2) { |
| 17162 | Jim_Obj *objPtr; |
| 17163 | |
| 17164 | objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); |
| 17165 | Jim_IncrRefCount(objPtr); |
| 17166 | retcode = Jim_EvalExpression(interp, objPtr); |
| 17167 | Jim_DecrRefCount(interp, objPtr); |
| 17168 | } |
| 17169 | else { |
| 17170 | Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); |
| 17171 | return JIM_ERR; |
| 17172 | } |
| 17173 | if (retcode != JIM_OK) |
| 17174 | return retcode; |
| 17175 | return JIM_OK; |
| 17176 | } |
| 17177 | |
| 17178 | |
| 17179 | static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -17438,15 +17230,15 @@ | |
| 17230 | if (i != argc - 1 && i != argc) { |
| 17231 | Jim_WrongNumArgs(interp, 1, argv, |
| 17232 | "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?"); |
| 17233 | } |
| 17234 | |
| 17235 | |
| 17236 | if (stackTraceObj && returnCode == JIM_ERR) { |
| 17237 | JimSetStackTrace(interp, stackTraceObj); |
| 17238 | } |
| 17239 | |
| 17240 | if (errorCodeObj && returnCode == JIM_ERR) { |
| 17241 | Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj); |
| 17242 | } |
| 17243 | interp->returnCode = returnCode; |
| 17244 | interp->returnLevel = level; |
| @@ -17463,31 +17255,31 @@ | |
| 17255 | if (interp->framePtr->level == 0) { |
| 17256 | Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); |
| 17257 | return JIM_ERR; |
| 17258 | } |
| 17259 | else if (argc >= 2) { |
| 17260 | |
| 17261 | Jim_CallFrame *cf = interp->framePtr->parent; |
| 17262 | |
| 17263 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17264 | if (cmdPtr == NULL) { |
| 17265 | return JIM_ERR; |
| 17266 | } |
| 17267 | |
| 17268 | JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); |
| 17269 | |
| 17270 | |
| 17271 | JimIncrCmdRefCount(cmdPtr); |
| 17272 | cf->tailcallCmd = cmdPtr; |
| 17273 | |
| 17274 | |
| 17275 | JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); |
| 17276 | |
| 17277 | cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); |
| 17278 | Jim_IncrRefCount(cf->tailcallObj); |
| 17279 | |
| 17280 | |
| 17281 | return JIM_EVAL; |
| 17282 | } |
| 17283 | return JIM_OK; |
| 17284 | } |
| 17285 | |
| @@ -17494,11 +17286,11 @@ | |
| 17286 | static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17287 | { |
| 17288 | Jim_Obj *cmdList; |
| 17289 | Jim_Obj *prefixListObj = Jim_CmdPrivData(interp); |
| 17290 | |
| 17291 | |
| 17292 | cmdList = Jim_DuplicateObj(interp, prefixListObj); |
| 17293 | Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1); |
| 17294 | |
| 17295 | return JimEvalObjList(interp, cmdList); |
| 17296 | } |
| @@ -17552,22 +17344,22 @@ | |
| 17344 | else { |
| 17345 | cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL); |
| 17346 | } |
| 17347 | |
| 17348 | if (cmd) { |
| 17349 | |
| 17350 | Jim_Obj *qualifiedCmdNameObj; |
| 17351 | const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj); |
| 17352 | |
| 17353 | JimCreateCommand(interp, cmdname, cmd); |
| 17354 | |
| 17355 | |
| 17356 | JimUpdateProcNamespace(interp, cmd, cmdname); |
| 17357 | |
| 17358 | JimFreeQualifiedName(interp, qualifiedCmdNameObj); |
| 17359 | |
| 17360 | |
| 17361 | Jim_SetResult(interp, argv[1]); |
| 17362 | return JIM_OK; |
| 17363 | } |
| 17364 | return JIM_ERR; |
| 17365 | } |
| @@ -17580,17 +17372,17 @@ | |
| 17372 | if (argc < 2) { |
| 17373 | Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); |
| 17374 | return JIM_ERR; |
| 17375 | } |
| 17376 | |
| 17377 | |
| 17378 | interp->local++; |
| 17379 | retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); |
| 17380 | interp->local--; |
| 17381 | |
| 17382 | |
| 17383 | |
| 17384 | if (retcode == 0) { |
| 17385 | Jim_Obj *cmdNameObj = Jim_GetResult(interp); |
| 17386 | |
| 17387 | if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) { |
| 17388 | return JIM_ERR; |
| @@ -17619,18 +17411,18 @@ | |
| 17411 | Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); |
| 17412 | if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) { |
| 17413 | Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]); |
| 17414 | return JIM_ERR; |
| 17415 | } |
| 17416 | |
| 17417 | cmdPtr->u.proc.upcall++; |
| 17418 | JimIncrCmdRefCount(cmdPtr); |
| 17419 | |
| 17420 | |
| 17421 | retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); |
| 17422 | |
| 17423 | |
| 17424 | cmdPtr->u.proc.upcall--; |
| 17425 | JimDecrCmdRefCount(interp, cmdPtr); |
| 17426 | |
| 17427 | return retcode; |
| 17428 | } |
| @@ -17657,11 +17449,11 @@ | |
| 17449 | return JIM_ERR; |
| 17450 | } |
| 17451 | |
| 17452 | if (len == 3) { |
| 17453 | #ifdef jim_ext_namespace |
| 17454 | |
| 17455 | nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2)); |
| 17456 | #else |
| 17457 | Jim_SetResultString(interp, "namespaces not enabled", -1); |
| 17458 | return JIM_ERR; |
| 17459 | #endif |
| @@ -17670,11 +17462,11 @@ | |
| 17462 | bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1); |
| 17463 | |
| 17464 | cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj); |
| 17465 | |
| 17466 | if (cmd) { |
| 17467 | |
| 17468 | nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv)); |
| 17469 | nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1); |
| 17470 | Jim_IncrRefCount(nargv[0]); |
| 17471 | memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv)); |
| 17472 | ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv); |
| @@ -17700,11 +17492,11 @@ | |
| 17492 | static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 17493 | { |
| 17494 | int i; |
| 17495 | Jim_CallFrame *targetCallFrame; |
| 17496 | |
| 17497 | |
| 17498 | if (argc > 3 && (argc % 2 == 0)) { |
| 17499 | targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); |
| 17500 | argc--; |
| 17501 | argv++; |
| 17502 | } |
| @@ -17713,17 +17505,17 @@ | |
| 17505 | } |
| 17506 | if (targetCallFrame == NULL) { |
| 17507 | return JIM_ERR; |
| 17508 | } |
| 17509 | |
| 17510 | |
| 17511 | if (argc < 3) { |
| 17512 | Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?"); |
| 17513 | return JIM_ERR; |
| 17514 | } |
| 17515 | |
| 17516 | |
| 17517 | for (i = 1; i < argc; i += 2) { |
| 17518 | if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK) |
| 17519 | return JIM_ERR; |
| 17520 | } |
| 17521 | return JIM_OK; |
| @@ -17736,15 +17528,15 @@ | |
| 17528 | |
| 17529 | if (argc < 2) { |
| 17530 | Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?"); |
| 17531 | return JIM_ERR; |
| 17532 | } |
| 17533 | |
| 17534 | if (interp->framePtr->level == 0) |
| 17535 | return JIM_OK; |
| 17536 | for (i = 1; i < argc; i++) { |
| 17537 | |
| 17538 | const char *name = Jim_String(argv[i]); |
| 17539 | if (name[0] != ':' || name[1] != ':') { |
| 17540 | if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK) |
| 17541 | return JIM_ERR; |
| 17542 | } |
| @@ -17767,21 +17559,21 @@ | |
| 17559 | } |
| 17560 | |
| 17561 | str = Jim_String(objPtr); |
| 17562 | strLen = Jim_Utf8Length(interp, objPtr); |
| 17563 | |
| 17564 | |
| 17565 | resultObjPtr = Jim_NewStringObj(interp, "", 0); |
| 17566 | while (strLen) { |
| 17567 | for (i = 0; i < numMaps; i += 2) { |
| 17568 | Jim_Obj *eachObjPtr; |
| 17569 | const char *k; |
| 17570 | int kl; |
| 17571 | |
| 17572 | eachObjPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); |
| 17573 | k = Jim_String(eachObjPtr); |
| 17574 | kl = Jim_Utf8Length(interp, eachObjPtr); |
| 17575 | |
| 17576 | if (strLen >= kl && kl) { |
| 17577 | int rc; |
| 17578 | rc = JimStringCompareLen(str, k, kl, nocase); |
| 17579 | if (rc == 0) { |
| @@ -17794,11 +17586,11 @@ | |
| 17586 | strLen -= kl; |
| 17587 | break; |
| 17588 | } |
| 17589 | } |
| 17590 | } |
| 17591 | if (i == numMaps) { |
| 17592 | int c; |
| 17593 | if (noMatchStart == NULL) |
| 17594 | noMatchStart = str; |
| 17595 | str += utf8_tounicode(str, &c); |
| 17596 | strLen--; |
| @@ -17838,11 +17630,11 @@ | |
| 17630 | Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); |
| 17631 | return JIM_ERR; |
| 17632 | } |
| 17633 | if (Jim_GetEnum(interp, argv[1], options, &option, NULL, |
| 17634 | JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) |
| 17635 | return Jim_CheckShowCommands(interp, argv[1], options); |
| 17636 | |
| 17637 | switch (option) { |
| 17638 | case OPT_LENGTH: |
| 17639 | case OPT_BYTELENGTH: |
| 17640 | if (argc != 3) { |
| @@ -17859,11 +17651,11 @@ | |
| 17651 | return JIM_OK; |
| 17652 | |
| 17653 | case OPT_CAT:{ |
| 17654 | Jim_Obj *objPtr; |
| 17655 | if (argc == 3) { |
| 17656 | |
| 17657 | objPtr = argv[2]; |
| 17658 | } |
| 17659 | else { |
| 17660 | int i; |
| 17661 | |
| @@ -17878,11 +17670,11 @@ | |
| 17670 | } |
| 17671 | |
| 17672 | case OPT_COMPARE: |
| 17673 | case OPT_EQUAL: |
| 17674 | { |
| 17675 | |
| 17676 | long opt_length = -1; |
| 17677 | int n = argc - 4; |
| 17678 | int i = 2; |
| 17679 | while (n > 0) { |
| 17680 | int subopt; |
| @@ -17891,16 +17683,16 @@ | |
| 17683 | badcompareargs: |
| 17684 | Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2"); |
| 17685 | return JIM_ERR; |
| 17686 | } |
| 17687 | if (subopt == 0) { |
| 17688 | |
| 17689 | opt_case = 0; |
| 17690 | n--; |
| 17691 | } |
| 17692 | else { |
| 17693 | |
| 17694 | if (n < 2) { |
| 17695 | goto badcompareargs; |
| 17696 | } |
| 17697 | if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) { |
| 17698 | return JIM_ERR; |
| @@ -17911,11 +17703,11 @@ | |
| 17703 | if (n) { |
| 17704 | goto badcompareargs; |
| 17705 | } |
| 17706 | argv += argc - 2; |
| 17707 | if (opt_length < 0 && option != OPT_COMPARE && opt_case) { |
| 17708 | |
| 17709 | Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1])); |
| 17710 | } |
| 17711 | else { |
| 17712 | if (opt_length >= 0) { |
| 17713 | n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case); |
| @@ -18025,11 +17817,10 @@ | |
| 17817 | } |
| 17818 | |
| 17819 | case OPT_REVERSE:{ |
| 17820 | char *buf, *p; |
| 17821 | const char *str; |
| 17822 | int i; |
| 17823 | |
| 17824 | if (argc != 3) { |
| 17825 | Jim_WrongNumArgs(interp, 2, argv, "string"); |
| 17826 | return JIM_ERR; |
| @@ -18069,11 +17860,11 @@ | |
| 17860 | } |
| 17861 | if (idx < 0 || idx >= len || str == NULL) { |
| 17862 | Jim_SetResultString(interp, "", 0); |
| 17863 | } |
| 17864 | else if (len == Jim_Length(argv[2])) { |
| 17865 | |
| 17866 | Jim_SetResultString(interp, str + idx, 1); |
| 17867 | } |
| 17868 | else { |
| 17869 | int c; |
| 17870 | int i = utf8_index(str, idx); |
| @@ -18223,11 +18014,11 @@ | |
| 18014 | { |
| 18015 | int exitCode = 0; |
| 18016 | int i; |
| 18017 | int sig = 0; |
| 18018 | |
| 18019 | |
| 18020 | jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); |
| 18021 | static const int max_ignore_code = sizeof(ignore_mask) * 8; |
| 18022 | |
| 18023 | Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); |
| 18024 | |
| @@ -18234,11 +18025,11 @@ | |
| 18025 | for (i = 1; i < argc - 1; i++) { |
| 18026 | const char *arg = Jim_String(argv[i]); |
| 18027 | jim_wide option; |
| 18028 | int ignore; |
| 18029 | |
| 18030 | |
| 18031 | if (strcmp(arg, "--") == 0) { |
| 18032 | i++; |
| 18033 | break; |
| 18034 | } |
| 18035 | if (*arg != '-') { |
| @@ -18285,28 +18076,28 @@ | |
| 18076 | sig++; |
| 18077 | } |
| 18078 | |
| 18079 | interp->signal_level += sig; |
| 18080 | if (Jim_CheckSignal(interp)) { |
| 18081 | |
| 18082 | exitCode = JIM_SIGNAL; |
| 18083 | } |
| 18084 | else { |
| 18085 | exitCode = Jim_EvalObj(interp, argv[0]); |
| 18086 | |
| 18087 | interp->errorFlag = 0; |
| 18088 | } |
| 18089 | interp->signal_level -= sig; |
| 18090 | |
| 18091 | |
| 18092 | if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { |
| 18093 | |
| 18094 | return exitCode; |
| 18095 | } |
| 18096 | |
| 18097 | if (sig && exitCode == JIM_SIGNAL) { |
| 18098 | |
| 18099 | if (interp->signal_set_result) { |
| 18100 | interp->signal_set_result(interp, interp->sigmask); |
| 18101 | } |
| 18102 | else { |
| 18103 | Jim_SetResultInt(interp, interp->sigmask); |
| @@ -18345,125 +18136,10 @@ | |
| 18136 | } |
| 18137 | Jim_SetResultInt(interp, exitCode); |
| 18138 | return JIM_OK; |
| 18139 | } |
| 18140 | |
| 18141 | |
| 18142 | |
| 18143 | static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18144 | { |
| 18145 | if (argc != 3) { |
| @@ -18476,56 +18152,43 @@ | |
| 18152 | } |
| 18153 | |
| 18154 | return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2])); |
| 18155 | } |
| 18156 | |
| 18157 | #define JIM_DICTMATCH_KEYS 0x0001 |
| 18158 | #define JIM_DICTMATCH_VALUES 0x002 |
| 18159 | |
| 18160 | int Jim_DictMatchTypes(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj, int match_type, int return_types) |
| 18161 | { |
| 18162 | Jim_HashEntry *he; |
| 18163 | Jim_Obj *listObjPtr; |
| 18164 | Jim_HashTableIterator htiter; |
| 18165 | |
| 18166 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18167 | return JIM_ERR; |
| 18168 | } |
| 18169 | |
| 18170 | listObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18171 | |
| 18172 | JimInitHashTableIterator(objPtr->internalRep.ptr, &htiter); |
| 18173 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18174 | if (patternObj) { |
| 18175 | Jim_Obj *matchObj = (match_type == JIM_DICTMATCH_KEYS) ? (Jim_Obj *)he->key : Jim_GetHashEntryVal(he); |
| 18176 | if (!JimGlobMatch(Jim_String(patternObj), Jim_String(matchObj), 0)) { |
| 18177 | |
| 18178 | continue; |
| 18179 | } |
| 18180 | } |
| 18181 | if (return_types & JIM_DICTMATCH_KEYS) { |
| 18182 | Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); |
| 18183 | } |
| 18184 | if (return_types & JIM_DICTMATCH_VALUES) { |
| 18185 | Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); |
| 18186 | } |
| 18187 | } |
| 18188 | |
| 18189 | Jim_SetResult(interp, listObjPtr); |
| 18190 | return JIM_OK; |
| 18191 | } |
| 18192 | |
| 18193 | int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18194 | { |
| @@ -18532,38 +18195,85 @@ | |
| 18195 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18196 | return -1; |
| 18197 | } |
| 18198 | return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; |
| 18199 | } |
| 18200 | |
| 18201 | Jim_Obj *Jim_DictMerge(Jim_Interp *interp, int objc, Jim_Obj *const *objv) |
| 18202 | { |
| 18203 | Jim_Obj *objPtr = Jim_NewDictObj(interp, NULL, 0); |
| 18204 | int i; |
| 18205 | |
| 18206 | JimPanic((objc == 0, "Jim_DictMerge called with objc=0")); |
| 18207 | |
| 18208 | |
| 18209 | |
| 18210 | for (i = 0; i < objc; i++) { |
| 18211 | Jim_HashTable *ht; |
| 18212 | Jim_HashTableIterator htiter; |
| 18213 | Jim_HashEntry *he; |
| 18214 | |
| 18215 | if (SetDictFromAny(interp, objv[i]) != JIM_OK) { |
| 18216 | Jim_FreeNewObj(interp, objPtr); |
| 18217 | return NULL; |
| 18218 | } |
| 18219 | ht = objv[i]->internalRep.ptr; |
| 18220 | JimInitHashTableIterator(ht, &htiter); |
| 18221 | while ((he = Jim_NextHashEntry(&htiter)) != NULL) { |
| 18222 | Jim_ReplaceHashEntry(objPtr->internalRep.ptr, Jim_GetHashEntryKey(he), Jim_GetHashEntryVal(he)); |
| 18223 | } |
| 18224 | } |
| 18225 | return objPtr; |
| 18226 | } |
| 18227 | |
| 18228 | int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) |
| 18229 | { |
| 18230 | Jim_HashTable *ht; |
| 18231 | unsigned int i; |
| 18232 | char buffer[100]; |
| 18233 | int sum = 0; |
| 18234 | int nonzero_count = 0; |
| 18235 | Jim_Obj *output; |
| 18236 | int bucket_counts[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
| 18237 | |
| 18238 | if (SetDictFromAny(interp, objPtr) != JIM_OK) { |
| 18239 | return JIM_ERR; |
| 18240 | } |
| 18241 | |
| 18242 | ht = (Jim_HashTable *)objPtr->internalRep.ptr; |
| 18243 | |
| 18244 | |
| 18245 | snprintf(buffer, sizeof(buffer), "%d entries in table, %d buckets\n", ht->used, ht->size); |
| 18246 | output = Jim_NewStringObj(interp, buffer, -1); |
| 18247 | |
| 18248 | for (i = 0; i < ht->size; i++) { |
| 18249 | Jim_HashEntry *he = ht->table[i]; |
| 18250 | int entries = 0; |
| 18251 | while (he) { |
| 18252 | entries++; |
| 18253 | he = he->next; |
| 18254 | } |
| 18255 | if (entries > 9) { |
| 18256 | bucket_counts[10]++; |
| 18257 | } |
| 18258 | else { |
| 18259 | bucket_counts[entries]++; |
| 18260 | } |
| 18261 | if (entries) { |
| 18262 | sum += entries; |
| 18263 | nonzero_count++; |
| 18264 | } |
| 18265 | } |
| 18266 | for (i = 0; i < 10; i++) { |
| 18267 | snprintf(buffer, sizeof(buffer), "number of buckets with %d entries: %d\n", i, bucket_counts[i]); |
| 18268 | Jim_AppendString(interp, output, buffer, -1); |
| 18269 | } |
| 18270 | snprintf(buffer, sizeof(buffer), "number of buckets with 10 or more entries: %d\n", bucket_counts[10]); |
| 18271 | Jim_AppendString(interp, output, buffer, -1); |
| 18272 | snprintf(buffer, sizeof(buffer), "average search distance for entry: %.1f", nonzero_count ? (double)sum / nonzero_count : 0.0); |
| 18273 | Jim_AppendString(interp, output, buffer, -1); |
| 18274 | Jim_SetResult(interp, output); |
| 18275 | return JIM_OK; |
| 18276 | } |
| 18277 | |
| 18278 | static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) |
| 18279 | { |
| @@ -18573,14 +18283,67 @@ | |
| 18283 | Jim_AppendString(interp, prefixObj, subcmd, -1); |
| 18284 | |
| 18285 | return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); |
| 18286 | } |
| 18287 | |
| 18288 | static int JimDictWith(Jim_Interp *interp, Jim_Obj *dictVarName, Jim_Obj *const *keyv, int keyc, Jim_Obj *scriptObj) |
| 18289 | { |
| 18290 | int i; |
| 18291 | Jim_Obj *objPtr; |
| 18292 | Jim_Obj *dictObj; |
| 18293 | Jim_Obj **dictValues; |
| 18294 | int len; |
| 18295 | int ret = JIM_OK; |
| 18296 | |
| 18297 | |
| 18298 | dictObj = Jim_GetVariable(interp, dictVarName, JIM_ERRMSG); |
| 18299 | if (dictObj == NULL || Jim_DictKeysVector(interp, dictObj, keyv, keyc, &objPtr, JIM_ERRMSG) != JIM_OK) { |
| 18300 | return JIM_ERR; |
| 18301 | } |
| 18302 | |
| 18303 | if (Jim_DictPairs(interp, objPtr, &dictValues, &len) == JIM_ERR) { |
| 18304 | return JIM_ERR; |
| 18305 | } |
| 18306 | for (i = 0; i < len; i += 2) { |
| 18307 | if (Jim_SetVariable(interp, dictValues[i], dictValues[i + 1]) == JIM_ERR) { |
| 18308 | Jim_Free(dictValues); |
| 18309 | return JIM_ERR; |
| 18310 | } |
| 18311 | } |
| 18312 | |
| 18313 | |
| 18314 | if (Jim_Length(scriptObj)) { |
| 18315 | ret = Jim_EvalObj(interp, scriptObj); |
| 18316 | |
| 18317 | |
| 18318 | if (ret == JIM_OK && Jim_GetVariable(interp, dictVarName, 0) != NULL) { |
| 18319 | |
| 18320 | Jim_Obj **newkeyv = Jim_Alloc(sizeof(*newkeyv) * (keyc + 1)); |
| 18321 | for (i = 0; i < keyc; i++) { |
| 18322 | newkeyv[i] = keyv[i]; |
| 18323 | } |
| 18324 | |
| 18325 | for (i = 0; i < len; i += 2) { |
| 18326 | |
| 18327 | objPtr = Jim_GetVariable(interp, dictValues[i], 0); |
| 18328 | newkeyv[keyc] = dictValues[i]; |
| 18329 | Jim_SetDictKeysVector(interp, dictVarName, newkeyv, keyc + 1, objPtr, 0); |
| 18330 | } |
| 18331 | Jim_Free(newkeyv); |
| 18332 | } |
| 18333 | } |
| 18334 | |
| 18335 | Jim_Free(dictValues); |
| 18336 | |
| 18337 | return ret; |
| 18338 | } |
| 18339 | |
| 18340 | |
| 18341 | static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 18342 | { |
| 18343 | Jim_Obj *objPtr; |
| 18344 | int types = JIM_DICTMATCH_KEYS; |
| 18345 | int option; |
| 18346 | static const char * const options[] = { |
| 18347 | "create", "get", "set", "unset", "exists", "keys", "size", "info", |
| 18348 | "merge", "with", "append", "lappend", "incr", "remove", "values", "for", |
| 18349 | "replace", "update", NULL |
| @@ -18596,11 +18359,11 @@ | |
| 18359 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); |
| 18360 | return JIM_ERR; |
| 18361 | } |
| 18362 | |
| 18363 | if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { |
| 18364 | return Jim_CheckShowCommands(interp, argv[1], options); |
| 18365 | } |
| 18366 | |
| 18367 | switch (option) { |
| 18368 | case OPT_GET: |
| 18369 | if (argc < 3) { |
| @@ -18643,16 +18406,19 @@ | |
| 18406 | if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { |
| 18407 | return JIM_ERR; |
| 18408 | } |
| 18409 | return JIM_OK; |
| 18410 | |
| 18411 | case OPT_VALUES: |
| 18412 | types = JIM_DICTMATCH_VALUES; |
| 18413 | |
| 18414 | case OPT_KEYS: |
| 18415 | if (argc != 3 && argc != 4) { |
| 18416 | Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); |
| 18417 | return JIM_ERR; |
| 18418 | } |
| 18419 | return Jim_DictMatchTypes(interp, argv[2], argc == 4 ? argv[3] : NULL, types, types); |
| 18420 | |
| 18421 | case OPT_SIZE: |
| 18422 | if (argc != 3) { |
| 18423 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18424 | return JIM_ERR; |
| @@ -18665,19 +18431,20 @@ | |
| 18431 | |
| 18432 | case OPT_MERGE: |
| 18433 | if (argc == 2) { |
| 18434 | return JIM_OK; |
| 18435 | } |
| 18436 | objPtr = Jim_DictMerge(interp, argc - 2, argv + 2); |
| 18437 | if (objPtr == NULL) { |
| 18438 | return JIM_ERR; |
| 18439 | } |
| 18440 | Jim_SetResult(interp, objPtr); |
| 18441 | return JIM_OK; |
| 18442 | |
| 18443 | case OPT_UPDATE: |
| 18444 | if (argc < 6 || argc % 2) { |
| 18445 | |
| 18446 | argc = 2; |
| 18447 | } |
| 18448 | break; |
| 18449 | |
| 18450 | case OPT_CREATE: |
| @@ -18693,12 +18460,19 @@ | |
| 18460 | if (argc != 3) { |
| 18461 | Jim_WrongNumArgs(interp, 2, argv, "dictionary"); |
| 18462 | return JIM_ERR; |
| 18463 | } |
| 18464 | return Jim_DictInfo(interp, argv[2]); |
| 18465 | |
| 18466 | case OPT_WITH: |
| 18467 | if (argc < 4) { |
| 18468 | Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); |
| 18469 | return JIM_ERR; |
| 18470 | } |
| 18471 | return JimDictWith(interp, argv[2], argv + 3, argc - 4, argv[argc - 1]); |
| 18472 | } |
| 18473 | |
| 18474 | return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); |
| 18475 | } |
| 18476 | |
| 18477 | |
| 18478 | static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| @@ -18764,11 +18538,11 @@ | |
| 18538 | |
| 18539 | #ifdef jim_ext_namespace |
| 18540 | int nons = 0; |
| 18541 | |
| 18542 | if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) { |
| 18543 | |
| 18544 | argc--; |
| 18545 | argv++; |
| 18546 | nons = 1; |
| 18547 | } |
| 18548 | #endif |
| @@ -18775,16 +18549,15 @@ | |
| 18549 | |
| 18550 | if (argc < 2) { |
| 18551 | Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); |
| 18552 | return JIM_ERR; |
| 18553 | } |
| 18554 | if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { |
| 18555 | return Jim_CheckShowCommands(interp, argv[1], commands); |
| 18556 | } |
| 18557 | |
| 18558 | |
| 18559 | switch (cmd) { |
| 18560 | case INFO_EXISTS: |
| 18561 | if (argc != 3) { |
| 18562 | Jim_WrongNumArgs(interp, 2, argv, "varName"); |
| 18563 | return JIM_ERR; |
| @@ -18809,21 +18582,21 @@ | |
| 18582 | Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData); |
| 18583 | return JIM_OK; |
| 18584 | } |
| 18585 | |
| 18586 | case INFO_CHANNELS: |
| 18587 | mode++; |
| 18588 | #ifndef jim_ext_aio |
| 18589 | Jim_SetResultString(interp, "aio not enabled", -1); |
| 18590 | return JIM_ERR; |
| 18591 | #endif |
| 18592 | |
| 18593 | case INFO_PROCS: |
| 18594 | mode++; |
| 18595 | |
| 18596 | case INFO_COMMANDS: |
| 18597 | |
| 18598 | if (argc != 2 && argc != 3) { |
| 18599 | Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18600 | return JIM_ERR; |
| 18601 | } |
| 18602 | #ifdef jim_ext_namespace |
| @@ -18835,17 +18608,17 @@ | |
| 18608 | #endif |
| 18609 | Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode)); |
| 18610 | break; |
| 18611 | |
| 18612 | case INFO_VARS: |
| 18613 | mode++; |
| 18614 | |
| 18615 | case INFO_LOCALS: |
| 18616 | mode++; |
| 18617 | |
| 18618 | case INFO_GLOBALS: |
| 18619 | |
| 18620 | if (argc != 2 && argc != 3) { |
| 18621 | Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); |
| 18622 | return JIM_ERR; |
| 18623 | } |
| 18624 | #ifdef jim_ext_namespace |
| @@ -18951,13 +18724,12 @@ | |
| 18724 | case INFO_ARGS: |
| 18725 | Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr); |
| 18726 | break; |
| 18727 | case INFO_STATICS: |
| 18728 | if (cmdPtr->u.proc.staticVars) { |
| 18729 | Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars, |
| 18730 | NULL, JimVariablesMatch, JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES)); |
| 18731 | } |
| 18732 | break; |
| 18733 | } |
| 18734 | break; |
| 18735 | } |
| @@ -18985,15 +18757,15 @@ | |
| 18757 | } |
| 18758 | } |
| 18759 | break; |
| 18760 | |
| 18761 | case INFO_HOSTNAME: |
| 18762 | |
| 18763 | return Jim_Eval(interp, "os.gethostname"); |
| 18764 | |
| 18765 | case INFO_NAMEOFEXECUTABLE: |
| 18766 | |
| 18767 | return Jim_Eval(interp, "{info nameofexecutable}"); |
| 18768 | |
| 18769 | case INFO_RETURNCODES: |
| 18770 | if (argc == 2) { |
| 18771 | int i; |
| @@ -19070,11 +18842,11 @@ | |
| 18842 | |
| 18843 | if (option == OPT_VAR) { |
| 18844 | result = Jim_GetVariable(interp, objPtr, 0) != NULL; |
| 18845 | } |
| 18846 | else { |
| 18847 | |
| 18848 | Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); |
| 18849 | |
| 18850 | if (cmd) { |
| 18851 | switch (option) { |
| 18852 | case OPT_COMMAND: |
| @@ -19113,11 +18885,11 @@ | |
| 18885 | if (len == 0) { |
| 18886 | return JIM_OK; |
| 18887 | } |
| 18888 | strLen = Jim_Utf8Length(interp, argv[1]); |
| 18889 | |
| 18890 | |
| 18891 | if (argc == 2) { |
| 18892 | splitChars = " \n\t\r"; |
| 18893 | splitLen = 4; |
| 18894 | } |
| 18895 | else { |
| @@ -19126,11 +18898,11 @@ | |
| 18898 | } |
| 18899 | |
| 18900 | noMatchStart = str; |
| 18901 | resObjPtr = Jim_NewListObj(interp, NULL, 0); |
| 18902 | |
| 18903 | |
| 18904 | if (splitLen) { |
| 18905 | Jim_Obj *objPtr; |
| 18906 | while (strLen--) { |
| 18907 | const char *sc = splitChars; |
| 18908 | int scLen = splitLen; |
| @@ -19155,11 +18927,11 @@ | |
| 18927 | #define NUM_COMMON (128 - 9) |
| 18928 | while (strLen--) { |
| 18929 | int n = utf8_tounicode(str, &c); |
| 18930 | #ifdef JIM_OPTIMIZATION |
| 18931 | if (c >= 9 && c < 128) { |
| 18932 | |
| 18933 | c -= 9; |
| 18934 | if (!commonObj) { |
| 18935 | commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON); |
| 18936 | memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON); |
| 18937 | } |
| @@ -19189,11 +18961,11 @@ | |
| 18961 | |
| 18962 | if (argc != 2 && argc != 3) { |
| 18963 | Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?"); |
| 18964 | return JIM_ERR; |
| 18965 | } |
| 18966 | |
| 18967 | if (argc == 2) { |
| 18968 | joinStr = " "; |
| 18969 | joinStrLen = 1; |
| 18970 | } |
| 18971 | else { |
| @@ -19468,13 +19240,13 @@ | |
| 19240 | return -1; |
| 19241 | else if (step < 0 && end > start) |
| 19242 | return -1; |
| 19243 | len = end - start; |
| 19244 | if (len < 0) |
| 19245 | len = -len; |
| 19246 | if (step < 0) |
| 19247 | step = -step; |
| 19248 | len = 1 + ((len - 1) / step); |
| 19249 | if (len > INT_MAX) |
| 19250 | len = INT_MAX; |
| 19251 | return (int)((len < 0) ? -1 : len); |
| 19252 | } |
| @@ -19644,57 +19416,102 @@ | |
| 19416 | argv[1] = interp->result; |
| 19417 | |
| 19418 | Jim_EvalObjVector(interp, 2, argv); |
| 19419 | } |
| 19420 | |
| 19421 | static char **JimSortStringTable(const char *const *tablePtr) |
| 19422 | { |
| 19423 | int count; |
| 19424 | char **tablePtrSorted; |
| 19425 | |
| 19426 | |
| 19427 | for (count = 0; tablePtr[count]; count++) { |
| 19428 | } |
| 19429 | |
| 19430 | |
| 19431 | tablePtrSorted = Jim_Alloc(sizeof(char *) * (count + 1)); |
| 19432 | memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); |
| 19433 | qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); |
| 19434 | tablePtrSorted[count] = NULL; |
| 19435 | |
| 19436 | return tablePtrSorted; |
| 19437 | } |
| 19438 | |
| 19439 | static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, |
| 19440 | const char *prefix, const char *const *tablePtr, const char *name) |
| 19441 | { |
| 19442 | char **tablePtrSorted; |
| 19443 | int i; |
| 19444 | |
| 19445 | if (name == NULL) { |
| 19446 | name = "option"; |
| 19447 | } |
| 19448 | |
| 19449 | Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); |
| 19450 | tablePtrSorted = JimSortStringTable(tablePtr); |
| 19451 | for (i = 0; tablePtrSorted[i]; i++) { |
| 19452 | if (tablePtrSorted[i + 1] == NULL && i > 0) { |
| 19453 | Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); |
| 19454 | } |
| 19455 | Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); |
| 19456 | if (tablePtrSorted[i + 1]) { |
| 19457 | Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); |
| 19458 | } |
| 19459 | } |
| 19460 | Jim_Free(tablePtrSorted); |
| 19461 | } |
| 19462 | |
| 19463 | |
| 19464 | int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr) |
| 19465 | { |
| 19466 | if (Jim_CompareStringImmediate(interp, objPtr, "-commands")) { |
| 19467 | int i; |
| 19468 | char **tablePtrSorted = JimSortStringTable(tablePtr); |
| 19469 | Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); |
| 19470 | for (i = 0; tablePtrSorted[i]; i++) { |
| 19471 | Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1)); |
| 19472 | } |
| 19473 | Jim_Free(tablePtrSorted); |
| 19474 | return JIM_OK; |
| 19475 | } |
| 19476 | return JIM_ERR; |
| 19477 | } |
| 19478 | |
| 19479 | static const Jim_ObjType getEnumObjType = { |
| 19480 | "get-enum", |
| 19481 | NULL, |
| 19482 | NULL, |
| 19483 | NULL, |
| 19484 | JIM_TYPE_REFERENCES |
| 19485 | }; |
| 19486 | |
| 19487 | int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, |
| 19488 | const char *const *tablePtr, int *indexPtr, const char *name, int flags) |
| 19489 | { |
| 19490 | const char *bad = "bad "; |
| 19491 | const char *const *entryPtr = NULL; |
| 19492 | int i; |
| 19493 | int match = -1; |
| 19494 | int arglen; |
| 19495 | const char *arg; |
| 19496 | |
| 19497 | if (objPtr->typePtr == &getEnumObjType) { |
| 19498 | if (objPtr->internalRep.ptrIntValue.ptr == tablePtr && objPtr->internalRep.ptrIntValue.int1 == flags) { |
| 19499 | *indexPtr = objPtr->internalRep.ptrIntValue.int2; |
| 19500 | return JIM_OK; |
| 19501 | } |
| 19502 | } |
| 19503 | |
| 19504 | arg = Jim_GetString(objPtr, &arglen); |
| 19505 | |
| 19506 | *indexPtr = -1; |
| 19507 | |
| 19508 | for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { |
| 19509 | if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { |
| 19510 | |
| 19511 | match = i; |
| 19512 | goto found; |
| 19513 | } |
| 19514 | if (flags & JIM_ENUM_ABBREV) { |
| 19515 | if (strncmp(arg, *entryPtr, arglen) == 0) { |
| 19516 | if (*arg == '-' && arglen == 1) { |
| 19517 | break; |
| @@ -19706,12 +19523,20 @@ | |
| 19523 | match = i; |
| 19524 | } |
| 19525 | } |
| 19526 | } |
| 19527 | |
| 19528 | |
| 19529 | if (match >= 0) { |
| 19530 | found: |
| 19531 | |
| 19532 | Jim_FreeIntRep(interp, objPtr); |
| 19533 | objPtr->typePtr = &getEnumObjType; |
| 19534 | objPtr->internalRep.ptrIntValue.ptr = (void *)tablePtr; |
| 19535 | objPtr->internalRep.ptrIntValue.int1 = flags; |
| 19536 | objPtr->internalRep.ptrIntValue.int2 = match; |
| 19537 | |
| 19538 | *indexPtr = match; |
| 19539 | return JIM_OK; |
| 19540 | } |
| 19541 | |
| 19542 | ambiguous: |
| @@ -19743,15 +19568,17 @@ | |
| 19568 | return objPtr->typePtr == &listObjType; |
| 19569 | } |
| 19570 | |
| 19571 | void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...) |
| 19572 | { |
| 19573 | |
| 19574 | int len = strlen(format); |
| 19575 | int extra = 0; |
| 19576 | int n = 0; |
| 19577 | const char *params[5]; |
| 19578 | int nobjparam = 0; |
| 19579 | Jim_Obj *objparam[5]; |
| 19580 | char *buf; |
| 19581 | va_list args; |
| 19582 | int i; |
| 19583 | |
| 19584 | va_start(args, format); |
| @@ -19766,10 +19593,12 @@ | |
| 19593 | } |
| 19594 | else if (strncmp(format + i, "%#s", 3) == 0) { |
| 19595 | Jim_Obj *objPtr = va_arg(args, Jim_Obj *); |
| 19596 | |
| 19597 | params[n] = Jim_GetString(objPtr, &l); |
| 19598 | objparam[nobjparam++] = objPtr; |
| 19599 | Jim_IncrRefCount(objPtr); |
| 19600 | } |
| 19601 | else { |
| 19602 | if (format[i] == '%') { |
| 19603 | i++; |
| 19604 | } |
| @@ -19784,10 +19613,14 @@ | |
| 19613 | len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); |
| 19614 | |
| 19615 | va_end(args); |
| 19616 | |
| 19617 | Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); |
| 19618 | |
| 19619 | for (i = 0; i < nobjparam; i++) { |
| 19620 | Jim_DecrRefCount(interp, objparam[i]); |
| 19621 | } |
| 19622 | } |
| 19623 | |
| 19624 | |
| 19625 | #ifndef jim_ext_package |
| 19626 | int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) |
| @@ -19808,11 +19641,11 @@ | |
| 19641 | #include <string.h> |
| 19642 | |
| 19643 | |
| 19644 | static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv) |
| 19645 | { |
| 19646 | |
| 19647 | return JIM_OK; |
| 19648 | } |
| 19649 | |
| 19650 | static const jim_subcmd_type dummy_subcmd = { |
| 19651 | "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN |
| @@ -19831,22 +19664,18 @@ | |
| 19664 | } |
| 19665 | |
| 19666 | static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, |
| 19667 | Jim_Obj *cmd, Jim_Obj *subcmd) |
| 19668 | { |
| 19669 | Jim_SetResultFormatted(interp, "%#s, %s command \"%#s\": should be ", cmd, type, subcmd); |
| 19670 | add_commands(interp, command_table, ", "); |
| 19671 | } |
| 19672 | |
| 19673 | static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, |
| 19674 | Jim_Obj *const *argv) |
| 19675 | { |
| 19676 | Jim_SetResultFormatted(interp, "Usage: \"%#s command ... \", where command is one of: ", argv[0]); |
| 19677 | add_commands(interp, command_table, ", "); |
| 19678 | } |
| 19679 | |
| 19680 | static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) |
| 19681 | { |
| @@ -19863,67 +19692,78 @@ | |
| 19692 | { |
| 19693 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19694 | add_cmd_usage(interp, command_table, subcmd); |
| 19695 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19696 | } |
| 19697 | |
| 19698 | static const Jim_ObjType subcmdLookupObjType = { |
| 19699 | "subcmd-lookup", |
| 19700 | NULL, |
| 19701 | NULL, |
| 19702 | NULL, |
| 19703 | JIM_TYPE_REFERENCES |
| 19704 | }; |
| 19705 | |
| 19706 | const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, |
| 19707 | int argc, Jim_Obj *const *argv) |
| 19708 | { |
| 19709 | const jim_subcmd_type *ct; |
| 19710 | const jim_subcmd_type *partial = 0; |
| 19711 | int cmdlen; |
| 19712 | Jim_Obj *cmd; |
| 19713 | const char *cmdstr; |
| 19714 | int help = 0; |
| 19715 | |
| 19716 | if (argc < 2) { |
| 19717 | Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s command ...\"\n" |
| 19718 | "Use \"%#s -help ?command?\" for help", argv[0], argv[0]); |
| 19719 | return 0; |
| 19720 | } |
| 19721 | |
| 19722 | cmd = argv[1]; |
| 19723 | |
| 19724 | |
| 19725 | if (cmd->typePtr == &subcmdLookupObjType) { |
| 19726 | if (cmd->internalRep.ptrIntValue.ptr == command_table) { |
| 19727 | ct = command_table + cmd->internalRep.ptrIntValue.int1; |
| 19728 | goto found; |
| 19729 | } |
| 19730 | } |
| 19731 | |
| 19732 | |
| 19733 | if (Jim_CompareStringImmediate(interp, cmd, "-help")) { |
| 19734 | if (argc == 2) { |
| 19735 | |
| 19736 | show_cmd_usage(interp, command_table, argc, argv); |
| 19737 | return &dummy_subcmd; |
| 19738 | } |
| 19739 | help = 1; |
| 19740 | |
| 19741 | |
| 19742 | cmd = argv[2]; |
| 19743 | } |
| 19744 | |
| 19745 | |
| 19746 | if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { |
| 19747 | |
| 19748 | Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); |
| 19749 | add_commands(interp, command_table, " "); |
| 19750 | return &dummy_subcmd; |
| 19751 | } |
| 19752 | |
| 19753 | cmdstr = Jim_GetString(cmd, &cmdlen); |
| 19754 | |
| 19755 | for (ct = command_table; ct->cmd; ct++) { |
| 19756 | if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) { |
| 19757 | |
| 19758 | break; |
| 19759 | } |
| 19760 | if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) { |
| 19761 | if (partial) { |
| 19762 | |
| 19763 | if (help) { |
| 19764 | |
| 19765 | show_cmd_usage(interp, command_table, argc, argv); |
| 19766 | return &dummy_subcmd; |
| 19767 | } |
| 19768 | bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]); |
| 19769 | return 0; |
| @@ -19931,44 +19771,51 @@ | |
| 19771 | partial = ct; |
| 19772 | } |
| 19773 | continue; |
| 19774 | } |
| 19775 | |
| 19776 | |
| 19777 | if (partial && !ct->cmd) { |
| 19778 | ct = partial; |
| 19779 | } |
| 19780 | |
| 19781 | if (!ct->cmd) { |
| 19782 | |
| 19783 | if (help) { |
| 19784 | |
| 19785 | show_cmd_usage(interp, command_table, argc, argv); |
| 19786 | return &dummy_subcmd; |
| 19787 | } |
| 19788 | bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]); |
| 19789 | return 0; |
| 19790 | } |
| 19791 | |
| 19792 | if (help) { |
| 19793 | Jim_SetResultString(interp, "Usage: ", -1); |
| 19794 | |
| 19795 | add_cmd_usage(interp, ct, argv[0]); |
| 19796 | return &dummy_subcmd; |
| 19797 | } |
| 19798 | |
| 19799 | |
| 19800 | Jim_FreeIntRep(interp, cmd); |
| 19801 | cmd->typePtr = &subcmdLookupObjType; |
| 19802 | cmd->internalRep.ptrIntValue.ptr = (void *)command_table; |
| 19803 | cmd->internalRep.ptrIntValue.int1 = ct - command_table; |
| 19804 | |
| 19805 | found: |
| 19806 | |
| 19807 | if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { |
| 19808 | Jim_SetResultString(interp, "wrong # args: should be \"", -1); |
| 19809 | |
| 19810 | add_cmd_usage(interp, ct, argv[0]); |
| 19811 | Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); |
| 19812 | |
| 19813 | return 0; |
| 19814 | } |
| 19815 | |
| 19816 | |
| 19817 | return ct; |
| 19818 | } |
| 19819 | |
| 19820 | int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv) |
| 19821 | { |
| @@ -20019,11 +19866,11 @@ | |
| 19866 | *p++ = 0xe0 | ((uc & 0xf000) >> 12); |
| 19867 | *p++ = 0x80 | ((uc & 0xfc0) >> 6); |
| 19868 | *p = 0x80 | (uc & 0x3f); |
| 19869 | return 3; |
| 19870 | } |
| 19871 | |
| 19872 | else { |
| 19873 | *p++ = 0xf0 | ((uc & 0x1c0000) >> 18); |
| 19874 | *p++ = 0x80 | ((uc & 0x3f000) >> 12); |
| 19875 | *p++ = 0x80 | ((uc & 0xfc0) >> 6); |
| 19876 | *p = 0x80 | (uc & 0x3f); |
| @@ -20146,11 +19993,12 @@ | |
| 19993 | continue; |
| 19994 | } |
| 19995 | *p++ = ch; |
| 19996 | format += step; |
| 19997 | step = utf8_tounicode(format, &ch); |
| 19998 | |
| 19999 | } while (sawFlag && (p - spec <= 5)); |
| 20000 | |
| 20001 | |
| 20002 | width = 0; |
| 20003 | if (isdigit(ch)) { |
| 20004 | width = strtoul(format, &end, 10); |
| @@ -20210,11 +20058,11 @@ | |
| 20058 | if (ch == 'h') { |
| 20059 | useShort = 1; |
| 20060 | format += step; |
| 20061 | step = utf8_tounicode(format, &ch); |
| 20062 | } else if (ch == 'l') { |
| 20063 | |
| 20064 | format += step; |
| 20065 | step = utf8_tounicode(format, &ch); |
| 20066 | if (ch == 'l') { |
| 20067 | format += step; |
| 20068 | step = utf8_tounicode(format, &ch); |
| @@ -20237,11 +20085,11 @@ | |
| 20085 | goto errorMsg; |
| 20086 | case 's': { |
| 20087 | formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); |
| 20088 | formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); |
| 20089 | if (gotPrecision && (precision < formatted_chars)) { |
| 20090 | |
| 20091 | formatted_chars = precision; |
| 20092 | formatted_bytes = utf8_index(formatted_buf, precision); |
| 20093 | } |
| 20094 | break; |
| 20095 | } |
| @@ -20249,11 +20097,11 @@ | |
| 20097 | jim_wide code; |
| 20098 | |
| 20099 | if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { |
| 20100 | goto error; |
| 20101 | } |
| 20102 | |
| 20103 | formatted_bytes = utf8_getchars(spec, code); |
| 20104 | formatted_buf = spec; |
| 20105 | formatted_chars = 1; |
| 20106 | break; |
| 20107 | } |
| @@ -20267,11 +20115,11 @@ | |
| 20115 | goto error; |
| 20116 | } |
| 20117 | length = sizeof(w) * 8; |
| 20118 | |
| 20119 | |
| 20120 | |
| 20121 | if (num_buffer_size < length + 1) { |
| 20122 | num_buffer_size = length + 1; |
| 20123 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20124 | } |
| 20125 | |
| @@ -20295,29 +20143,29 @@ | |
| 20143 | case 'E': |
| 20144 | case 'f': |
| 20145 | case 'g': |
| 20146 | case 'G': |
| 20147 | doubleType = 1; |
| 20148 | |
| 20149 | case 'd': |
| 20150 | case 'u': |
| 20151 | case 'o': |
| 20152 | case 'x': |
| 20153 | case 'X': { |
| 20154 | jim_wide w; |
| 20155 | double d; |
| 20156 | int length; |
| 20157 | |
| 20158 | |
| 20159 | if (width) { |
| 20160 | p += sprintf(p, "%ld", width); |
| 20161 | } |
| 20162 | if (gotPrecision) { |
| 20163 | p += sprintf(p, ".%ld", precision); |
| 20164 | } |
| 20165 | |
| 20166 | |
| 20167 | if (doubleType) { |
| 20168 | if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { |
| 20169 | goto error; |
| 20170 | } |
| 20171 | length = MAX_FLOAT_WIDTH; |
| @@ -20344,19 +20192,26 @@ | |
| 20192 | } |
| 20193 | |
| 20194 | *p++ = (char) ch; |
| 20195 | *p = '\0'; |
| 20196 | |
| 20197 | |
| 20198 | if (width > 10000 || length > 10000 || precision > 10000) { |
| 20199 | Jim_SetResultString(interp, "format too long", -1); |
| 20200 | goto error; |
| 20201 | } |
| 20202 | |
| 20203 | |
| 20204 | |
| 20205 | if (width > length) { |
| 20206 | length = width; |
| 20207 | } |
| 20208 | if (gotPrecision) { |
| 20209 | length += precision; |
| 20210 | } |
| 20211 | |
| 20212 | |
| 20213 | if (num_buffer_size < length + 1) { |
| 20214 | num_buffer_size = length + 1; |
| 20215 | num_buffer = Jim_Realloc(num_buffer, num_buffer_size); |
| 20216 | } |
| 20217 | |
| @@ -20370,11 +20225,11 @@ | |
| 20225 | formatted_buf = num_buffer; |
| 20226 | break; |
| 20227 | } |
| 20228 | |
| 20229 | default: { |
| 20230 | |
| 20231 | spec[0] = ch; |
| 20232 | spec[1] = '\0'; |
| 20233 | Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); |
| 20234 | goto error; |
| 20235 | } |
| @@ -20422,37 +20277,37 @@ | |
| 20277 | |
| 20278 | #define REG_MAX_PAREN 100 |
| 20279 | |
| 20280 | |
| 20281 | |
| 20282 | #define END 0 |
| 20283 | #define BOL 1 |
| 20284 | #define EOL 2 |
| 20285 | #define ANY 3 |
| 20286 | #define ANYOF 4 |
| 20287 | #define ANYBUT 5 |
| 20288 | #define BRANCH 6 |
| 20289 | #define BACK 7 |
| 20290 | #define EXACTLY 8 |
| 20291 | #define NOTHING 9 |
| 20292 | #define REP 10 |
| 20293 | #define REPMIN 11 |
| 20294 | #define REPX 12 |
| 20295 | #define REPXMIN 13 |
| 20296 | #define BOLX 14 |
| 20297 | #define EOLX 15 |
| 20298 | #define WORDA 16 |
| 20299 | #define WORDZ 17 |
| 20300 | |
| 20301 | #define OPENNC 1000 |
| 20302 | #define OPEN 1001 |
| 20303 | |
| 20304 | |
| 20305 | |
| 20306 | |
| 20307 | #define CLOSENC 2000 |
| 20308 | #define CLOSE 2001 |
| 20309 | #define CLOSE_END (CLOSE+REG_MAX_PAREN) |
| 20310 | |
| 20311 | #define REG_MAGIC 0xFADED00D |
| 20312 | |
| 20313 | |
| @@ -20465,18 +20320,18 @@ | |
| 20320 | |
| 20321 | #define FAIL(R,M) { (R)->err = (M); return (M); } |
| 20322 | #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') |
| 20323 | #define META "^$.[()|?{+*" |
| 20324 | |
| 20325 | #define HASWIDTH 1 |
| 20326 | #define SIMPLE 2 |
| 20327 | #define SPSTART 4 |
| 20328 | #define WORST 0 |
| 20329 | |
| 20330 | #define MAX_REP_COUNT 1000000 |
| 20331 | |
| 20332 | static int reg(regex_t *preg, int paren, int *flagp ); |
| 20333 | static int regpiece(regex_t *preg, int *flagp ); |
| 20334 | static int regbranch(regex_t *preg, int *flagp ); |
| 20335 | static int regatom(regex_t *preg, int *flagp ); |
| 20336 | static int regnode(regex_t *preg, int op ); |
| 20337 | static int regnext(regex_t *preg, int p ); |
| @@ -20520,15 +20375,15 @@ | |
| 20375 | memset(preg, 0, sizeof(*preg)); |
| 20376 | |
| 20377 | if (exp == NULL) |
| 20378 | FAIL(preg, REG_ERR_NULL_ARGUMENT); |
| 20379 | |
| 20380 | |
| 20381 | preg->cflags = cflags; |
| 20382 | preg->regparse = exp; |
| 20383 | |
| 20384 | |
| 20385 | preg->proglen = (strlen(exp) + 1) * 5; |
| 20386 | preg->program = malloc(preg->proglen * sizeof(int)); |
| 20387 | if (preg->program == NULL) |
| 20388 | FAIL(preg, REG_ERR_NOMEM); |
| 20389 | |
| @@ -20535,24 +20390,24 @@ | |
| 20390 | regc(preg, REG_MAGIC); |
| 20391 | if (reg(preg, 0, &flags) == 0) { |
| 20392 | return preg->err; |
| 20393 | } |
| 20394 | |
| 20395 | |
| 20396 | if (preg->re_nsub >= REG_MAX_PAREN) |
| 20397 | FAIL(preg,REG_ERR_TOO_BIG); |
| 20398 | |
| 20399 | |
| 20400 | preg->regstart = 0; |
| 20401 | preg->reganch = 0; |
| 20402 | preg->regmust = 0; |
| 20403 | preg->regmlen = 0; |
| 20404 | scan = 1; |
| 20405 | if (OP(preg, regnext(preg, scan)) == END) { |
| 20406 | scan = OPERAND(scan); |
| 20407 | |
| 20408 | |
| 20409 | if (OP(preg, scan) == EXACTLY) { |
| 20410 | preg->regstart = preg->program[OPERAND(scan)]; |
| 20411 | } |
| 20412 | else if (OP(preg, scan) == BOL) |
| 20413 | preg->reganch++; |
| @@ -20579,24 +20434,24 @@ | |
| 20434 | #endif |
| 20435 | |
| 20436 | return 0; |
| 20437 | } |
| 20438 | |
| 20439 | static int reg(regex_t *preg, int paren, int *flagp ) |
| 20440 | { |
| 20441 | int ret; |
| 20442 | int br; |
| 20443 | int ender; |
| 20444 | int parno = 0; |
| 20445 | int flags; |
| 20446 | |
| 20447 | *flagp = HASWIDTH; |
| 20448 | |
| 20449 | |
| 20450 | if (paren) { |
| 20451 | if (preg->regparse[0] == '?' && preg->regparse[1] == ':') { |
| 20452 | |
| 20453 | preg->regparse += 2; |
| 20454 | parno = -1; |
| 20455 | } |
| 20456 | else { |
| 20457 | parno = ++preg->re_nsub; |
| @@ -20603,16 +20458,16 @@ | |
| 20458 | } |
| 20459 | ret = regnode(preg, OPEN+parno); |
| 20460 | } else |
| 20461 | ret = 0; |
| 20462 | |
| 20463 | |
| 20464 | br = regbranch(preg, &flags); |
| 20465 | if (br == 0) |
| 20466 | return 0; |
| 20467 | if (ret != 0) |
| 20468 | regtail(preg, ret, br); |
| 20469 | else |
| 20470 | ret = br; |
| 20471 | if (!(flags&HASWIDTH)) |
| 20472 | *flagp &= ~HASWIDTH; |
| 20473 | *flagp |= flags&SPSTART; |
| @@ -20619,25 +20474,25 @@ | |
| 20474 | while (*preg->regparse == '|') { |
| 20475 | preg->regparse++; |
| 20476 | br = regbranch(preg, &flags); |
| 20477 | if (br == 0) |
| 20478 | return 0; |
| 20479 | regtail(preg, ret, br); |
| 20480 | if (!(flags&HASWIDTH)) |
| 20481 | *flagp &= ~HASWIDTH; |
| 20482 | *flagp |= flags&SPSTART; |
| 20483 | } |
| 20484 | |
| 20485 | |
| 20486 | ender = regnode(preg, (paren) ? CLOSE+parno : END); |
| 20487 | regtail(preg, ret, ender); |
| 20488 | |
| 20489 | |
| 20490 | for (br = ret; br != 0; br = regnext(preg, br)) |
| 20491 | regoptail(preg, br, ender); |
| 20492 | |
| 20493 | |
| 20494 | if (paren && *preg->regparse++ != ')') { |
| 20495 | preg->err = REG_ERR_UNMATCHED_PAREN; |
| 20496 | return 0; |
| 20497 | } else if (!paren && *preg->regparse != '\0') { |
| 20498 | if (*preg->regparse == ')') { |
| @@ -20657,11 +20512,11 @@ | |
| 20512 | int ret; |
| 20513 | int chain; |
| 20514 | int latest; |
| 20515 | int flags; |
| 20516 | |
| 20517 | *flagp = WORST; |
| 20518 | |
| 20519 | ret = regnode(preg, BRANCH); |
| 20520 | chain = 0; |
| 20521 | while (*preg->regparse != '\0' && *preg->regparse != ')' && |
| 20522 | *preg->regparse != '|') { |
| @@ -20675,11 +20530,11 @@ | |
| 20530 | else { |
| 20531 | regtail(preg, chain, latest); |
| 20532 | } |
| 20533 | chain = latest; |
| 20534 | } |
| 20535 | if (chain == 0) |
| 20536 | (void) regnode(preg, NOTHING); |
| 20537 | |
| 20538 | return(ret); |
| 20539 | } |
| 20540 | |
| @@ -20705,11 +20560,11 @@ | |
| 20560 | if (!(flags&HASWIDTH) && op != '?') { |
| 20561 | preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY; |
| 20562 | return 0; |
| 20563 | } |
| 20564 | |
| 20565 | |
| 20566 | if (op == '{') { |
| 20567 | char *end; |
| 20568 | |
| 20569 | min = strtoul(preg->regparse + 1, &end, 10); |
| 20570 | if (end == preg->regparse + 1) { |
| @@ -20716,10 +20571,14 @@ | |
| 20571 | preg->err = REG_ERR_BAD_COUNT; |
| 20572 | return 0; |
| 20573 | } |
| 20574 | if (*end == '}') { |
| 20575 | max = min; |
| 20576 | } |
| 20577 | else if (*end == '\0') { |
| 20578 | preg->err = REG_ERR_UNMATCHED_BRACES; |
| 20579 | return 0; |
| 20580 | } |
| 20581 | else { |
| 20582 | preg->regparse = end; |
| 20583 | max = strtoul(preg->regparse + 1, &end, 10); |
| 20584 | if (*end != '}') { |
| @@ -20777,11 +20636,11 @@ | |
| 20636 | static void reg_addrange(regex_t *preg, int lower, int upper) |
| 20637 | { |
| 20638 | if (lower > upper) { |
| 20639 | reg_addrange(preg, upper, lower); |
| 20640 | } |
| 20641 | |
| 20642 | regc(preg, upper - lower + 1); |
| 20643 | regc(preg, lower); |
| 20644 | } |
| 20645 | |
| 20646 | static void reg_addrange_str(regex_t *preg, const char *str) |
| @@ -20845,17 +20704,17 @@ | |
| 20704 | case 'r': *ch = '\r'; break; |
| 20705 | case 't': *ch = '\t'; break; |
| 20706 | case 'v': *ch = '\v'; break; |
| 20707 | case 'u': |
| 20708 | if (*s == '{') { |
| 20709 | |
| 20710 | n = parse_hex(s + 1, 6, ch); |
| 20711 | if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) { |
| 20712 | s += n + 2; |
| 20713 | } |
| 20714 | else { |
| 20715 | |
| 20716 | *ch = 'u'; |
| 20717 | } |
| 20718 | } |
| 20719 | else if ((n = parse_hex(s, 4, ch)) > 0) { |
| 20720 | s += n; |
| @@ -20886,15 +20745,15 @@ | |
| 20745 | int nocase = (preg->cflags & REG_ICASE); |
| 20746 | |
| 20747 | int ch; |
| 20748 | int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase); |
| 20749 | |
| 20750 | *flagp = WORST; |
| 20751 | |
| 20752 | preg->regparse += n; |
| 20753 | switch (ch) { |
| 20754 | |
| 20755 | case '^': |
| 20756 | ret = regnode(preg, BOL); |
| 20757 | break; |
| 20758 | case '$': |
| 20759 | ret = regnode(preg, EOL); |
| @@ -20904,37 +20763,60 @@ | |
| 20763 | *flagp |= HASWIDTH|SIMPLE; |
| 20764 | break; |
| 20765 | case '[': { |
| 20766 | const char *pattern = preg->regparse; |
| 20767 | |
| 20768 | if (*pattern == '^') { |
| 20769 | ret = regnode(preg, ANYBUT); |
| 20770 | pattern++; |
| 20771 | } else |
| 20772 | ret = regnode(preg, ANYOF); |
| 20773 | |
| 20774 | |
| 20775 | if (*pattern == ']' || *pattern == '-') { |
| 20776 | reg_addrange(preg, *pattern, *pattern); |
| 20777 | pattern++; |
| 20778 | } |
| 20779 | |
| 20780 | while (*pattern && *pattern != ']') { |
| 20781 | |
| 20782 | int start; |
| 20783 | int end; |
| 20784 | |
| 20785 | enum { |
| 20786 | CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER, |
| 20787 | CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT, |
| 20788 | CC_NUM |
| 20789 | }; |
| 20790 | int cc; |
| 20791 | |
| 20792 | pattern += reg_utf8_tounicode_case(pattern, &start, nocase); |
| 20793 | if (start == '\\') { |
| 20794 | |
| 20795 | switch (*pattern) { |
| 20796 | case 's': |
| 20797 | pattern++; |
| 20798 | cc = CC_SPACE; |
| 20799 | goto cc_switch; |
| 20800 | case 'd': |
| 20801 | pattern++; |
| 20802 | cc = CC_DIGIT; |
| 20803 | goto cc_switch; |
| 20804 | case 'w': |
| 20805 | pattern++; |
| 20806 | reg_addrange(preg, '_', '_'); |
| 20807 | cc = CC_ALNUM; |
| 20808 | goto cc_switch; |
| 20809 | } |
| 20810 | pattern += reg_decode_escape(pattern, &start); |
| 20811 | if (start == 0) { |
| 20812 | preg->err = REG_ERR_NULL_CHAR; |
| 20813 | return 0; |
| 20814 | } |
| 20815 | } |
| 20816 | if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') { |
| 20817 | |
| 20818 | pattern += utf8_tounicode(pattern, &end); |
| 20819 | pattern += reg_utf8_tounicode_case(pattern, &end, nocase); |
| 20820 | if (end == '\\') { |
| 20821 | pattern += reg_decode_escape(pattern, &end); |
| 20822 | if (end == 0) { |
| @@ -20949,30 +20831,25 @@ | |
| 20831 | if (start == '[' && pattern[0] == ':') { |
| 20832 | static const char *character_class[] = { |
| 20833 | ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:", |
| 20834 | ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:", |
| 20835 | }; |
| 20836 | |
| 20837 | for (cc = 0; cc < CC_NUM; cc++) { |
| 20838 | n = strlen(character_class[cc]); |
| 20839 | if (strncmp(pattern, character_class[cc], n) == 0) { |
| 20840 | |
| 20841 | pattern += n + 1; |
| 20842 | break; |
| 20843 | } |
| 20844 | } |
| 20845 | if (cc != CC_NUM) { |
| 20846 | cc_switch: |
| 20847 | switch (cc) { |
| 20848 | case CC_ALNUM: |
| 20849 | reg_addrange(preg, '0', '9'); |
| 20850 | |
| 20851 | case CC_ALPHA: |
| 20852 | if ((preg->cflags & REG_ICASE) == 0) { |
| 20853 | reg_addrange(preg, 'a', 'z'); |
| 20854 | } |
| 20855 | reg_addrange(preg, 'A', 'Z'); |
| @@ -20990,11 +20867,11 @@ | |
| 20867 | reg_addrange(preg, 'a', 'z'); |
| 20868 | break; |
| 20869 | case CC_XDIGIT: |
| 20870 | reg_addrange(preg, 'a', 'f'); |
| 20871 | reg_addrange(preg, 'A', 'F'); |
| 20872 | |
| 20873 | case CC_DIGIT: |
| 20874 | reg_addrange(preg, '0', '9'); |
| 20875 | break; |
| 20876 | case CC_CNTRL: |
| 20877 | reg_addrange(preg, 0, 31); |
| @@ -21014,11 +20891,11 @@ | |
| 20891 | break; |
| 20892 | } |
| 20893 | continue; |
| 20894 | } |
| 20895 | } |
| 20896 | |
| 20897 | reg_addrange(preg, start, start); |
| 20898 | } |
| 20899 | regc(preg, '\0'); |
| 20900 | |
| 20901 | if (*pattern) { |
| @@ -21037,11 +20914,11 @@ | |
| 20914 | break; |
| 20915 | case '\0': |
| 20916 | case '|': |
| 20917 | case ')': |
| 20918 | preg->err = REG_ERR_INTERNAL; |
| 20919 | return 0; |
| 20920 | case '?': |
| 20921 | case '+': |
| 20922 | case '*': |
| 20923 | case '{': |
| 20924 | preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING; |
| @@ -21090,34 +20967,34 @@ | |
| 20967 | ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT); |
| 20968 | reg_addrange_str(preg," \t\r\n\f\v"); |
| 20969 | regc(preg, '\0'); |
| 20970 | *flagp |= HASWIDTH|SIMPLE; |
| 20971 | break; |
| 20972 | |
| 20973 | default: |
| 20974 | |
| 20975 | |
| 20976 | preg->regparse--; |
| 20977 | goto de_fault; |
| 20978 | } |
| 20979 | break; |
| 20980 | de_fault: |
| 20981 | default: { |
| 20982 | int added = 0; |
| 20983 | |
| 20984 | |
| 20985 | preg->regparse -= n; |
| 20986 | |
| 20987 | ret = regnode(preg, EXACTLY); |
| 20988 | |
| 20989 | |
| 20990 | |
| 20991 | while (*preg->regparse && strchr(META, *preg->regparse) == NULL) { |
| 20992 | n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE)); |
| 20993 | if (ch == '\\' && preg->regparse[n]) { |
| 20994 | if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) { |
| 20995 | |
| 20996 | break; |
| 20997 | } |
| 20998 | n += reg_decode_escape(preg->regparse + n, &ch); |
| 20999 | if (ch == 0) { |
| 21000 | preg->err = REG_ERR_NULL_CHAR; |
| @@ -21125,23 +21002,23 @@ | |
| 21002 | } |
| 21003 | } |
| 21004 | |
| 21005 | |
| 21006 | if (ISMULT(preg->regparse[n])) { |
| 21007 | |
| 21008 | if (added) { |
| 21009 | |
| 21010 | break; |
| 21011 | } |
| 21012 | |
| 21013 | regc(preg, ch); |
| 21014 | added++; |
| 21015 | preg->regparse += n; |
| 21016 | break; |
| 21017 | } |
| 21018 | |
| 21019 | |
| 21020 | regc(preg, ch); |
| 21021 | added++; |
| 21022 | preg->regparse += n; |
| 21023 | } |
| 21024 | regc(preg, '\0'); |
| @@ -21168,15 +21045,15 @@ | |
| 21045 | |
| 21046 | static int regnode(regex_t *preg, int op) |
| 21047 | { |
| 21048 | reg_grow(preg, 2); |
| 21049 | |
| 21050 | |
| 21051 | preg->program[preg->p++] = op; |
| 21052 | preg->program[preg->p++] = 0; |
| 21053 | |
| 21054 | |
| 21055 | return preg->p - 2; |
| 21056 | } |
| 21057 | |
| 21058 | static void regc(regex_t *preg, int b ) |
| 21059 | { |
| @@ -21186,13 +21063,13 @@ | |
| 21063 | |
| 21064 | static int reginsert(regex_t *preg, int op, int size, int opnd ) |
| 21065 | { |
| 21066 | reg_grow(preg, size); |
| 21067 | |
| 21068 | |
| 21069 | memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd)); |
| 21070 | |
| 21071 | memset(preg->program + opnd, 0, sizeof(int) * size); |
| 21072 | |
| 21073 | preg->program[opnd] = op; |
| 21074 | |
| 21075 | preg->p += size; |
| @@ -21204,11 +21081,11 @@ | |
| 21081 | { |
| 21082 | int scan; |
| 21083 | int temp; |
| 21084 | int offset; |
| 21085 | |
| 21086 | |
| 21087 | scan = p; |
| 21088 | for (;;) { |
| 21089 | temp = regnext(preg, scan); |
| 21090 | if (temp == 0) |
| 21091 | break; |
| @@ -21224,11 +21101,11 @@ | |
| 21101 | } |
| 21102 | |
| 21103 | |
| 21104 | static void regoptail(regex_t *preg, int p, int val ) |
| 21105 | { |
| 21106 | |
| 21107 | if (p != 0 && OP(preg, p) == BRANCH) { |
| 21108 | regtail(preg, OPERAND(p), val); |
| 21109 | } |
| 21110 | } |
| 21111 | |
| @@ -21240,16 +21117,16 @@ | |
| 21117 | int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) |
| 21118 | { |
| 21119 | const char *s; |
| 21120 | int scan; |
| 21121 | |
| 21122 | |
| 21123 | if (preg == NULL || preg->program == NULL || string == NULL) { |
| 21124 | return REG_ERR_NULL_ARGUMENT; |
| 21125 | } |
| 21126 | |
| 21127 | |
| 21128 | if (*preg->program != REG_MAGIC) { |
| 21129 | return REG_ERR_CORRUPTED; |
| 21130 | } |
| 21131 | |
| 21132 | #ifdef DEBUG |
| @@ -21258,51 +21135,51 @@ | |
| 21135 | #endif |
| 21136 | |
| 21137 | preg->eflags = eflags; |
| 21138 | preg->pmatch = pmatch; |
| 21139 | preg->nmatch = nmatch; |
| 21140 | preg->start = string; |
| 21141 | |
| 21142 | |
| 21143 | for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { |
| 21144 | int op = OP(preg, scan); |
| 21145 | if (op == END) |
| 21146 | break; |
| 21147 | if (op == REPX || op == REPXMIN) |
| 21148 | preg->program[scan + 4] = 0; |
| 21149 | } |
| 21150 | |
| 21151 | |
| 21152 | if (preg->regmust != 0) { |
| 21153 | s = string; |
| 21154 | while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) { |
| 21155 | if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) { |
| 21156 | break; |
| 21157 | } |
| 21158 | s++; |
| 21159 | } |
| 21160 | if (s == NULL) |
| 21161 | return REG_NOMATCH; |
| 21162 | } |
| 21163 | |
| 21164 | |
| 21165 | preg->regbol = string; |
| 21166 | |
| 21167 | |
| 21168 | if (preg->reganch) { |
| 21169 | if (eflags & REG_NOTBOL) { |
| 21170 | |
| 21171 | goto nextline; |
| 21172 | } |
| 21173 | while (1) { |
| 21174 | if (regtry(preg, string)) { |
| 21175 | return REG_NOERROR; |
| 21176 | } |
| 21177 | if (*string) { |
| 21178 | nextline: |
| 21179 | if (preg->cflags & REG_NEWLINE) { |
| 21180 | |
| 21181 | string = strchr(string, '\n'); |
| 21182 | if (string) { |
| 21183 | preg->regbol = ++string; |
| 21184 | continue; |
| 21185 | } |
| @@ -21310,22 +21187,22 @@ | |
| 21187 | } |
| 21188 | return REG_NOMATCH; |
| 21189 | } |
| 21190 | } |
| 21191 | |
| 21192 | |
| 21193 | s = string; |
| 21194 | if (preg->regstart != '\0') { |
| 21195 | |
| 21196 | while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) { |
| 21197 | if (regtry(preg, s)) |
| 21198 | return REG_NOERROR; |
| 21199 | s++; |
| 21200 | } |
| 21201 | } |
| 21202 | else |
| 21203 | |
| 21204 | while (1) { |
| 21205 | if (regtry(preg, s)) |
| 21206 | return REG_NOERROR; |
| 21207 | if (*s == '\0') { |
| 21208 | break; |
| @@ -21334,15 +21211,15 @@ | |
| 21211 | int c; |
| 21212 | s += utf8_tounicode(s, &c); |
| 21213 | } |
| 21214 | } |
| 21215 | |
| 21216 | |
| 21217 | return REG_NOMATCH; |
| 21218 | } |
| 21219 | |
| 21220 | |
| 21221 | static int regtry( regex_t *preg, const char *string ) |
| 21222 | { |
| 21223 | int i; |
| 21224 | |
| 21225 | preg->reginput = string; |
| @@ -21379,11 +21256,11 @@ | |
| 21256 | } |
| 21257 | |
| 21258 | static int reg_range_find(const int *range, int c) |
| 21259 | { |
| 21260 | while (*range) { |
| 21261 | |
| 21262 | if (c >= range[1] && c <= (range[0] + range[1] - 1)) { |
| 21263 | return 1; |
| 21264 | } |
| 21265 | range += 2; |
| 21266 | } |
| @@ -21391,11 +21268,11 @@ | |
| 21268 | } |
| 21269 | |
| 21270 | static const char *str_find(const char *string, int c, int nocase) |
| 21271 | { |
| 21272 | if (nocase) { |
| 21273 | |
| 21274 | c = utf8_upper(c); |
| 21275 | } |
| 21276 | while (*string) { |
| 21277 | int ch; |
| 21278 | int n = reg_utf8_tounicode_case(string, &ch, nocase); |
| @@ -21435,15 +21312,15 @@ | |
| 21312 | no = regrepeat(preg, scan + 5, max); |
| 21313 | if (no < min) { |
| 21314 | return 0; |
| 21315 | } |
| 21316 | if (matchmin) { |
| 21317 | |
| 21318 | max = no; |
| 21319 | no = min; |
| 21320 | } |
| 21321 | |
| 21322 | while (1) { |
| 21323 | if (matchmin) { |
| 21324 | if (no > max) { |
| 21325 | break; |
| 21326 | } |
| @@ -21453,22 +21330,22 @@ | |
| 21330 | break; |
| 21331 | } |
| 21332 | } |
| 21333 | preg->reginput = save + utf8_index(save, no); |
| 21334 | reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); |
| 21335 | |
| 21336 | if (reg_iseol(preg, nextch) || c == nextch) { |
| 21337 | if (regmatch(preg, next)) { |
| 21338 | return(1); |
| 21339 | } |
| 21340 | } |
| 21341 | if (matchmin) { |
| 21342 | |
| 21343 | no++; |
| 21344 | } |
| 21345 | else { |
| 21346 | |
| 21347 | no--; |
| 21348 | } |
| 21349 | } |
| 21350 | return(0); |
| 21351 | } |
| @@ -21478,13 +21355,13 @@ | |
| 21355 | int *scanpt = preg->program + scan; |
| 21356 | |
| 21357 | int max = scanpt[2]; |
| 21358 | int min = scanpt[3]; |
| 21359 | |
| 21360 | |
| 21361 | if (scanpt[4] < min) { |
| 21362 | |
| 21363 | scanpt[4]++; |
| 21364 | if (regmatch(preg, scan + 5)) { |
| 21365 | return 1; |
| 21366 | } |
| 21367 | scanpt[4]--; |
| @@ -21493,39 +21370,39 @@ | |
| 21370 | if (scanpt[4] > max) { |
| 21371 | return 0; |
| 21372 | } |
| 21373 | |
| 21374 | if (matchmin) { |
| 21375 | |
| 21376 | if (regmatch(preg, regnext(preg, scan))) { |
| 21377 | return 1; |
| 21378 | } |
| 21379 | |
| 21380 | scanpt[4]++; |
| 21381 | if (regmatch(preg, scan + 5)) { |
| 21382 | return 1; |
| 21383 | } |
| 21384 | scanpt[4]--; |
| 21385 | return 0; |
| 21386 | } |
| 21387 | |
| 21388 | if (scanpt[4] < max) { |
| 21389 | scanpt[4]++; |
| 21390 | if (regmatch(preg, scan + 5)) { |
| 21391 | return 1; |
| 21392 | } |
| 21393 | scanpt[4]--; |
| 21394 | } |
| 21395 | |
| 21396 | return regmatch(preg, regnext(preg, scan)); |
| 21397 | } |
| 21398 | |
| 21399 | |
| 21400 | static int regmatch(regex_t *preg, int prog) |
| 21401 | { |
| 21402 | int scan; |
| 21403 | int next; |
| 21404 | const char *save; |
| 21405 | |
| 21406 | scan = prog; |
| 21407 | |
| 21408 | #ifdef DEBUG |
| @@ -21535,11 +21412,11 @@ | |
| 21412 | while (scan != 0) { |
| 21413 | int n; |
| 21414 | int c; |
| 21415 | #ifdef DEBUG |
| 21416 | if (regnarrate) { |
| 21417 | fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); |
| 21418 | } |
| 21419 | #endif |
| 21420 | next = regnext(preg, scan); |
| 21421 | n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); |
| 21422 | |
| @@ -21546,49 +21423,49 @@ | |
| 21423 | switch (OP(preg, scan)) { |
| 21424 | case BOLX: |
| 21425 | if ((preg->eflags & REG_NOTBOL)) { |
| 21426 | return(0); |
| 21427 | } |
| 21428 | |
| 21429 | case BOL: |
| 21430 | if (preg->reginput != preg->regbol) { |
| 21431 | return(0); |
| 21432 | } |
| 21433 | break; |
| 21434 | case EOLX: |
| 21435 | if (c != 0) { |
| 21436 | |
| 21437 | return 0; |
| 21438 | } |
| 21439 | break; |
| 21440 | case EOL: |
| 21441 | if (!reg_iseol(preg, c)) { |
| 21442 | return(0); |
| 21443 | } |
| 21444 | break; |
| 21445 | case WORDA: |
| 21446 | |
| 21447 | if ((!isalnum(UCHAR(c))) && c != '_') |
| 21448 | return(0); |
| 21449 | |
| 21450 | if (preg->reginput > preg->regbol && |
| 21451 | (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_')) |
| 21452 | return(0); |
| 21453 | break; |
| 21454 | case WORDZ: |
| 21455 | |
| 21456 | if (preg->reginput > preg->regbol) { |
| 21457 | |
| 21458 | if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { |
| 21459 | c = preg->reginput[-1]; |
| 21460 | |
| 21461 | if (isalnum(UCHAR(c)) || c == '_') { |
| 21462 | break; |
| 21463 | } |
| 21464 | } |
| 21465 | } |
| 21466 | |
| 21467 | return(0); |
| 21468 | |
| 21469 | case ANY: |
| 21470 | if (reg_iseol(preg, c)) |
| 21471 | return 0; |
| @@ -21624,12 +21501,12 @@ | |
| 21501 | case NOTHING: |
| 21502 | break; |
| 21503 | case BACK: |
| 21504 | break; |
| 21505 | case BRANCH: |
| 21506 | if (OP(preg, next) != BRANCH) |
| 21507 | next = OPERAND(scan); |
| 21508 | else { |
| 21509 | do { |
| 21510 | save = preg->reginput; |
| 21511 | if (regmatch(preg, OPERAND(scan))) { |
| 21512 | return(1); |
| @@ -21636,11 +21513,11 @@ | |
| 21513 | } |
| 21514 | preg->reginput = save; |
| 21515 | scan = regnext(preg, scan); |
| 21516 | } while (scan != 0 && OP(preg, scan) == BRANCH); |
| 21517 | return(0); |
| 21518 | |
| 21519 | } |
| 21520 | break; |
| 21521 | case REP: |
| 21522 | case REPMIN: |
| 21523 | return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); |
| @@ -21648,11 +21525,11 @@ | |
| 21525 | case REPX: |
| 21526 | case REPXMIN: |
| 21527 | return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); |
| 21528 | |
| 21529 | case END: |
| 21530 | return 1; |
| 21531 | |
| 21532 | case OPENNC: |
| 21533 | case CLOSENC: |
| 21534 | return regmatch(preg, next); |
| 21535 | |
| @@ -21695,11 +21572,11 @@ | |
| 21572 | |
| 21573 | scan = preg->reginput; |
| 21574 | opnd = OPERAND(p); |
| 21575 | switch (OP(preg, p)) { |
| 21576 | case ANY: |
| 21577 | |
| 21578 | while (!reg_iseol(preg, *scan) && count < max) { |
| 21579 | count++; |
| 21580 | scan++; |
| 21581 | } |
| 21582 | break; |
| @@ -21731,13 +21608,13 @@ | |
| 21608 | } |
| 21609 | count++; |
| 21610 | scan += n; |
| 21611 | } |
| 21612 | break; |
| 21613 | default: |
| 21614 | preg->err = REG_ERR_INTERNAL; |
| 21615 | count = 0; |
| 21616 | break; |
| 21617 | } |
| 21618 | preg->reginput = scan; |
| 21619 | |
| 21620 | return(count); |
| @@ -21758,11 +21635,11 @@ | |
| 21635 | return(p+offset); |
| 21636 | } |
| 21637 | |
| 21638 | static int regopsize(regex_t *preg, int p ) |
| 21639 | { |
| 21640 | |
| 21641 | switch (OP(preg, p)) { |
| 21642 | case REP: |
| 21643 | case REPMIN: |
| 21644 | case REPX: |
| 21645 | case REPXMIN: |
| @@ -21818,10 +21695,223 @@ | |
| 21695 | |
| 21696 | void regfree(regex_t *preg) |
| 21697 | { |
| 21698 | free(preg->program); |
| 21699 | } |
| 21700 | |
| 21701 | #endif |
| 21702 | #include <string.h> |
| 21703 | |
| 21704 | void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) |
| 21705 | { |
| 21706 | Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno())); |
| 21707 | } |
| 21708 | |
| 21709 | #if defined(__MINGW32__) |
| 21710 | #include <sys/stat.h> |
| 21711 | |
| 21712 | int Jim_Errno(void) |
| 21713 | { |
| 21714 | switch (GetLastError()) { |
| 21715 | case ERROR_FILE_NOT_FOUND: return ENOENT; |
| 21716 | case ERROR_PATH_NOT_FOUND: return ENOENT; |
| 21717 | case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; |
| 21718 | case ERROR_ACCESS_DENIED: return EACCES; |
| 21719 | case ERROR_INVALID_HANDLE: return EBADF; |
| 21720 | case ERROR_BAD_ENVIRONMENT: return E2BIG; |
| 21721 | case ERROR_BAD_FORMAT: return ENOEXEC; |
| 21722 | case ERROR_INVALID_ACCESS: return EACCES; |
| 21723 | case ERROR_INVALID_DRIVE: return ENOENT; |
| 21724 | case ERROR_CURRENT_DIRECTORY: return EACCES; |
| 21725 | case ERROR_NOT_SAME_DEVICE: return EXDEV; |
| 21726 | case ERROR_NO_MORE_FILES: return ENOENT; |
| 21727 | case ERROR_WRITE_PROTECT: return EROFS; |
| 21728 | case ERROR_BAD_UNIT: return ENXIO; |
| 21729 | case ERROR_NOT_READY: return EBUSY; |
| 21730 | case ERROR_BAD_COMMAND: return EIO; |
| 21731 | case ERROR_CRC: return EIO; |
| 21732 | case ERROR_BAD_LENGTH: return EIO; |
| 21733 | case ERROR_SEEK: return EIO; |
| 21734 | case ERROR_WRITE_FAULT: return EIO; |
| 21735 | case ERROR_READ_FAULT: return EIO; |
| 21736 | case ERROR_GEN_FAILURE: return EIO; |
| 21737 | case ERROR_SHARING_VIOLATION: return EACCES; |
| 21738 | case ERROR_LOCK_VIOLATION: return EACCES; |
| 21739 | case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; |
| 21740 | case ERROR_HANDLE_DISK_FULL: return ENOSPC; |
| 21741 | case ERROR_NOT_SUPPORTED: return ENODEV; |
| 21742 | case ERROR_REM_NOT_LIST: return EBUSY; |
| 21743 | case ERROR_DUP_NAME: return EEXIST; |
| 21744 | case ERROR_BAD_NETPATH: return ENOENT; |
| 21745 | case ERROR_NETWORK_BUSY: return EBUSY; |
| 21746 | case ERROR_DEV_NOT_EXIST: return ENODEV; |
| 21747 | case ERROR_TOO_MANY_CMDS: return EAGAIN; |
| 21748 | case ERROR_ADAP_HDW_ERR: return EIO; |
| 21749 | case ERROR_BAD_NET_RESP: return EIO; |
| 21750 | case ERROR_UNEXP_NET_ERR: return EIO; |
| 21751 | case ERROR_NETNAME_DELETED: return ENOENT; |
| 21752 | case ERROR_NETWORK_ACCESS_DENIED: return EACCES; |
| 21753 | case ERROR_BAD_DEV_TYPE: return ENODEV; |
| 21754 | case ERROR_BAD_NET_NAME: return ENOENT; |
| 21755 | case ERROR_TOO_MANY_NAMES: return ENFILE; |
| 21756 | case ERROR_TOO_MANY_SESS: return EIO; |
| 21757 | case ERROR_SHARING_PAUSED: return EAGAIN; |
| 21758 | case ERROR_REDIR_PAUSED: return EAGAIN; |
| 21759 | case ERROR_FILE_EXISTS: return EEXIST; |
| 21760 | case ERROR_CANNOT_MAKE: return ENOSPC; |
| 21761 | case ERROR_OUT_OF_STRUCTURES: return ENFILE; |
| 21762 | case ERROR_ALREADY_ASSIGNED: return EEXIST; |
| 21763 | case ERROR_INVALID_PASSWORD: return EPERM; |
| 21764 | case ERROR_NET_WRITE_FAULT: return EIO; |
| 21765 | case ERROR_NO_PROC_SLOTS: return EAGAIN; |
| 21766 | case ERROR_DISK_CHANGE: return EXDEV; |
| 21767 | case ERROR_BROKEN_PIPE: return EPIPE; |
| 21768 | case ERROR_OPEN_FAILED: return ENOENT; |
| 21769 | case ERROR_DISK_FULL: return ENOSPC; |
| 21770 | case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; |
| 21771 | case ERROR_INVALID_TARGET_HANDLE: return EBADF; |
| 21772 | case ERROR_INVALID_NAME: return ENOENT; |
| 21773 | case ERROR_PROC_NOT_FOUND: return ESRCH; |
| 21774 | case ERROR_WAIT_NO_CHILDREN: return ECHILD; |
| 21775 | case ERROR_CHILD_NOT_COMPLETE: return ECHILD; |
| 21776 | case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; |
| 21777 | case ERROR_SEEK_ON_DEVICE: return ESPIPE; |
| 21778 | case ERROR_BUSY_DRIVE: return EAGAIN; |
| 21779 | case ERROR_DIR_NOT_EMPTY: return EEXIST; |
| 21780 | case ERROR_NOT_LOCKED: return EACCES; |
| 21781 | case ERROR_BAD_PATHNAME: return ENOENT; |
| 21782 | case ERROR_LOCK_FAILED: return EACCES; |
| 21783 | case ERROR_ALREADY_EXISTS: return EEXIST; |
| 21784 | case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; |
| 21785 | case ERROR_BAD_PIPE: return EPIPE; |
| 21786 | case ERROR_PIPE_BUSY: return EAGAIN; |
| 21787 | case ERROR_PIPE_NOT_CONNECTED: return EPIPE; |
| 21788 | case ERROR_DIRECTORY: return ENOTDIR; |
| 21789 | } |
| 21790 | return EINVAL; |
| 21791 | } |
| 21792 | |
| 21793 | pidtype waitpid(pidtype pid, int *status, int nohang) |
| 21794 | { |
| 21795 | DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); |
| 21796 | if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { |
| 21797 | |
| 21798 | return JIM_BAD_PID; |
| 21799 | } |
| 21800 | GetExitCodeProcess(pid, &ret); |
| 21801 | *status = ret; |
| 21802 | CloseHandle(pid); |
| 21803 | return pid; |
| 21804 | } |
| 21805 | |
| 21806 | int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file) |
| 21807 | { |
| 21808 | char name[MAX_PATH]; |
| 21809 | HANDLE handle; |
| 21810 | |
| 21811 | if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, filename_template ? filename_template : "JIM", 0, name)) { |
| 21812 | return -1; |
| 21813 | } |
| 21814 | |
| 21815 | handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, |
| 21816 | CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | (unlink_file ? FILE_FLAG_DELETE_ON_CLOSE : 0), |
| 21817 | NULL); |
| 21818 | |
| 21819 | if (handle == INVALID_HANDLE_VALUE) { |
| 21820 | goto error; |
| 21821 | } |
| 21822 | |
| 21823 | Jim_SetResultString(interp, name, -1); |
| 21824 | return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT); |
| 21825 | |
| 21826 | error: |
| 21827 | Jim_SetResultErrno(interp, name); |
| 21828 | DeleteFile(name); |
| 21829 | return -1; |
| 21830 | } |
| 21831 | |
| 21832 | int Jim_OpenForWrite(const char *filename, int append) |
| 21833 | { |
| 21834 | if (strcmp(filename, "/dev/null") == 0) { |
| 21835 | filename = "nul:"; |
| 21836 | } |
| 21837 | int fd = _open(filename, _O_WRONLY | _O_CREAT | _O_TEXT | (append ? _O_APPEND : _O_TRUNC), _S_IREAD | _S_IWRITE); |
| 21838 | if (fd >= 0 && append) { |
| 21839 | |
| 21840 | _lseek(fd, 0L, SEEK_END); |
| 21841 | } |
| 21842 | return fd; |
| 21843 | } |
| 21844 | |
| 21845 | int Jim_OpenForRead(const char *filename) |
| 21846 | { |
| 21847 | if (strcmp(filename, "/dev/null") == 0) { |
| 21848 | filename = "nul:"; |
| 21849 | } |
| 21850 | return _open(filename, _O_RDONLY | _O_TEXT, 0); |
| 21851 | } |
| 21852 | |
| 21853 | #elif defined(HAVE_UNISTD_H) |
| 21854 | |
| 21855 | |
| 21856 | |
| 21857 | int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file) |
| 21858 | { |
| 21859 | int fd; |
| 21860 | mode_t mask; |
| 21861 | Jim_Obj *filenameObj; |
| 21862 | |
| 21863 | if (filename_template == NULL) { |
| 21864 | const char *tmpdir = getenv("TMPDIR"); |
| 21865 | if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { |
| 21866 | tmpdir = "/tmp/"; |
| 21867 | } |
| 21868 | filenameObj = Jim_NewStringObj(interp, tmpdir, -1); |
| 21869 | if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { |
| 21870 | Jim_AppendString(interp, filenameObj, "/", 1); |
| 21871 | } |
| 21872 | Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); |
| 21873 | } |
| 21874 | else { |
| 21875 | filenameObj = Jim_NewStringObj(interp, filename_template, -1); |
| 21876 | } |
| 21877 | |
| 21878 | |
| 21879 | mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); |
| 21880 | #ifdef HAVE_MKSTEMP |
| 21881 | fd = mkstemp(filenameObj->bytes); |
| 21882 | #else |
| 21883 | if (mktemp(filenameObj->bytes) == NULL) { |
| 21884 | fd = -1; |
| 21885 | } |
| 21886 | else { |
| 21887 | fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC); |
| 21888 | } |
| 21889 | #endif |
| 21890 | umask(mask); |
| 21891 | if (fd < 0) { |
| 21892 | Jim_SetResultErrno(interp, Jim_String(filenameObj)); |
| 21893 | Jim_FreeNewObj(interp, filenameObj); |
| 21894 | return -1; |
| 21895 | } |
| 21896 | if (unlink_file) { |
| 21897 | remove(Jim_String(filenameObj)); |
| 21898 | } |
| 21899 | |
| 21900 | Jim_SetResult(interp, filenameObj); |
| 21901 | return fd; |
| 21902 | } |
| 21903 | |
| 21904 | int Jim_OpenForWrite(const char *filename, int append) |
| 21905 | { |
| 21906 | return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); |
| 21907 | } |
| 21908 | |
| 21909 | int Jim_OpenForRead(const char *filename) |
| 21910 | { |
| 21911 | return open(filename, O_RDONLY, 0); |
| 21912 | } |
| 21913 | |
| 21914 | #endif |
| 21915 | |
| 21916 | #if defined(_WIN32) || defined(WIN32) |
| 21917 | #ifndef STRICT |
| @@ -21879,26 +21969,26 @@ | |
| 21969 | { |
| 21970 | DIR *dir = 0; |
| 21971 | |
| 21972 | if (name && name[0]) { |
| 21973 | size_t base_length = strlen(name); |
| 21974 | const char *all = |
| 21975 | strchr("/\\", name[base_length - 1]) ? "*" : "/*"; |
| 21976 | |
| 21977 | if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 && |
| 21978 | (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) { |
| 21979 | strcat(strcpy(dir->name, name), all); |
| 21980 | |
| 21981 | if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1) |
| 21982 | dir->result.d_name = 0; |
| 21983 | else { |
| 21984 | Jim_Free(dir->name); |
| 21985 | Jim_Free(dir); |
| 21986 | dir = 0; |
| 21987 | } |
| 21988 | } |
| 21989 | else { |
| 21990 | Jim_Free(dir); |
| 21991 | dir = 0; |
| 21992 | errno = ENOMEM; |
| 21993 | } |
| 21994 | } |
| @@ -21916,11 +22006,11 @@ | |
| 22006 | if (dir->handle != -1) |
| 22007 | result = _findclose(dir->handle); |
| 22008 | Jim_Free(dir->name); |
| 22009 | Jim_Free(dir); |
| 22010 | } |
| 22011 | if (result == -1) |
| 22012 | errno = EBADF; |
| 22013 | return result; |
| 22014 | } |
| 22015 | |
| 22016 | struct dirent *readdir(DIR * dir) |
| @@ -21938,28 +22028,77 @@ | |
| 22028 | } |
| 22029 | return result; |
| 22030 | } |
| 22031 | #endif |
| 22032 | #endif |
| 22033 | #include <stdio.h> |
| 22034 | #include <signal.h> |
| 22035 | |
| 22036 | |
| 22037 | |
| 22038 | |
| 22039 | |
| 22040 | |
| 22041 | #ifndef SIGPIPE |
| 22042 | #define SIGPIPE 13 |
| 22043 | #endif |
| 22044 | #ifndef SIGINT |
| 22045 | #define SIGINT 2 |
| 22046 | #endif |
| 22047 | |
| 22048 | const char *Jim_SignalId(int sig) |
| 22049 | { |
| 22050 | static char buf[10]; |
| 22051 | switch (sig) { |
| 22052 | case SIGINT: return "SIGINT"; |
| 22053 | case SIGPIPE: return "SIGPIPE"; |
| 22054 | |
| 22055 | } |
| 22056 | snprintf(buf, sizeof(buf), "%d", sig); |
| 22057 | return buf; |
| 22058 | } |
| 22059 | #ifndef JIM_BOOTSTRAP_LIB_ONLY |
| 22060 | #include <errno.h> |
| 22061 | #include <string.h> |
| 22062 | |
| 22063 | |
| 22064 | #ifdef USE_LINENOISE |
| 22065 | #ifdef HAVE_UNISTD_H |
| 22066 | #include <unistd.h> |
| 22067 | #endif |
| 22068 | #ifdef HAVE_SYS_STAT_H |
| 22069 | #include <sys/stat.h> |
| 22070 | #endif |
| 22071 | #include "linenoise.h" |
| 22072 | #else |
| 22073 | #define MAX_LINE_LEN 512 |
| 22074 | #endif |
| 22075 | |
| 22076 | #ifdef USE_LINENOISE |
| 22077 | static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata); |
| 22078 | static const char completion_callback_assoc_key[] = "interactive-completion"; |
| 22079 | #endif |
| 22080 | |
| 22081 | char *Jim_HistoryGetline(Jim_Interp *interp, const char *prompt) |
| 22082 | { |
| 22083 | #ifdef USE_LINENOISE |
| 22084 | struct JimCompletionInfo *compinfo = Jim_GetAssocData(interp, completion_callback_assoc_key); |
| 22085 | char *result; |
| 22086 | Jim_Obj *objPtr; |
| 22087 | long mlmode = 0; |
| 22088 | if (compinfo) { |
| 22089 | linenoiseSetCompletionCallback(JimCompletionCallback, compinfo); |
| 22090 | } |
| 22091 | objPtr = Jim_GetVariableStr(interp, "history::multiline", JIM_NONE); |
| 22092 | if (objPtr && Jim_GetLong(interp, objPtr, &mlmode) == JIM_NONE) { |
| 22093 | linenoiseSetMultiLine(mlmode); |
| 22094 | } |
| 22095 | |
| 22096 | result = linenoise(prompt); |
| 22097 | |
| 22098 | linenoiseSetCompletionCallback(NULL, NULL); |
| 22099 | return result; |
| 22100 | #else |
| 22101 | int len; |
| 22102 | char *line = malloc(MAX_LINE_LEN); |
| 22103 | |
| 22104 | fputs(prompt, stdout); |
| @@ -21992,26 +22131,92 @@ | |
| 22131 | } |
| 22132 | |
| 22133 | void Jim_HistorySave(const char *filename) |
| 22134 | { |
| 22135 | #ifdef USE_LINENOISE |
| 22136 | #ifdef HAVE_UMASK |
| 22137 | mode_t mask; |
| 22138 | |
| 22139 | mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); |
| 22140 | #endif |
| 22141 | linenoiseHistorySave(filename); |
| 22142 | #ifdef HAVE_UMASK |
| 22143 | mask = umask(mask); |
| 22144 | #endif |
| 22145 | #endif |
| 22146 | } |
| 22147 | |
| 22148 | void Jim_HistoryShow(void) |
| 22149 | { |
| 22150 | #ifdef USE_LINENOISE |
| 22151 | |
| 22152 | int i; |
| 22153 | int len; |
| 22154 | char **history = linenoiseHistory(&len); |
| 22155 | for (i = 0; i < len; i++) { |
| 22156 | printf("%4d %s\n", i + 1, history[i]); |
| 22157 | } |
| 22158 | #endif |
| 22159 | } |
| 22160 | |
| 22161 | #ifdef USE_LINENOISE |
| 22162 | struct JimCompletionInfo { |
| 22163 | Jim_Interp *interp; |
| 22164 | Jim_Obj *command; |
| 22165 | }; |
| 22166 | |
| 22167 | static void JimCompletionCallback(const char *prefix, linenoiseCompletions *comp, void *userdata) |
| 22168 | { |
| 22169 | struct JimCompletionInfo *info = (struct JimCompletionInfo *)userdata; |
| 22170 | Jim_Obj *objv[2]; |
| 22171 | int ret; |
| 22172 | |
| 22173 | objv[0] = info->command; |
| 22174 | objv[1] = Jim_NewStringObj(info->interp, prefix, -1); |
| 22175 | |
| 22176 | ret = Jim_EvalObjVector(info->interp, 2, objv); |
| 22177 | |
| 22178 | |
| 22179 | if (ret == JIM_OK) { |
| 22180 | int i; |
| 22181 | Jim_Obj *listObj = Jim_GetResult(info->interp); |
| 22182 | int len = Jim_ListLength(info->interp, listObj); |
| 22183 | for (i = 0; i < len; i++) { |
| 22184 | linenoiseAddCompletion(comp, Jim_String(Jim_ListGetIndex(info->interp, listObj, i))); |
| 22185 | } |
| 22186 | } |
| 22187 | } |
| 22188 | |
| 22189 | static void JimHistoryFreeCompletion(Jim_Interp *interp, void *data) |
| 22190 | { |
| 22191 | struct JimCompletionInfo *compinfo = data; |
| 22192 | |
| 22193 | Jim_DecrRefCount(interp, compinfo->command); |
| 22194 | |
| 22195 | Jim_Free(compinfo); |
| 22196 | } |
| 22197 | #endif |
| 22198 | |
| 22199 | void Jim_HistorySetCompletion(Jim_Interp *interp, Jim_Obj *commandObj) |
| 22200 | { |
| 22201 | #ifdef USE_LINENOISE |
| 22202 | if (commandObj) { |
| 22203 | |
| 22204 | Jim_IncrRefCount(commandObj); |
| 22205 | } |
| 22206 | |
| 22207 | Jim_DeleteAssocData(interp, completion_callback_assoc_key); |
| 22208 | |
| 22209 | if (commandObj) { |
| 22210 | struct JimCompletionInfo *compinfo = Jim_Alloc(sizeof(*compinfo)); |
| 22211 | compinfo->interp = interp; |
| 22212 | compinfo->command = commandObj; |
| 22213 | |
| 22214 | Jim_SetAssocData(interp, completion_callback_assoc_key, JimHistoryFreeCompletion, compinfo); |
| 22215 | } |
| 22216 | #endif |
| 22217 | } |
| 22218 | |
| 22219 | int Jim_InteractivePrompt(Jim_Interp *interp) |
| 22220 | { |
| 22221 | int retcode = JIM_OK; |
| 22222 | char *history_file = NULL; |
| @@ -22023,10 +22228,12 @@ | |
| 22228 | int history_len = strlen(home) + sizeof("/.jim_history"); |
| 22229 | history_file = Jim_Alloc(history_len); |
| 22230 | snprintf(history_file, history_len, "%s/.jim_history", home); |
| 22231 | Jim_HistoryLoad(history_file); |
| 22232 | } |
| 22233 | |
| 22234 | Jim_HistorySetCompletion(interp, Jim_NewStringObj(interp, "tcl::autocomplete", -1)); |
| 22235 | #endif |
| 22236 | |
| 22237 | printf("Welcome to Jim version %d.%d\n", |
| 22238 | JIM_VERSION / 100, JIM_VERSION % 100); |
| 22239 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); |
| @@ -22055,21 +22262,21 @@ | |
| 22262 | Jim_IncrRefCount(scriptObjPtr); |
| 22263 | while (1) { |
| 22264 | char state; |
| 22265 | char *line; |
| 22266 | |
| 22267 | line = Jim_HistoryGetline(interp, prompt); |
| 22268 | if (line == NULL) { |
| 22269 | if (errno == EINTR) { |
| 22270 | continue; |
| 22271 | } |
| 22272 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 22273 | retcode = JIM_OK; |
| 22274 | goto out; |
| 22275 | } |
| 22276 | if (Jim_Length(scriptObjPtr) != 0) { |
| 22277 | |
| 22278 | Jim_AppendString(interp, scriptObjPtr, "\n", 1); |
| 22279 | } |
| 22280 | Jim_AppendString(interp, scriptObjPtr, line, -1); |
| 22281 | free(line); |
| 22282 | if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state)) |
| @@ -22077,11 +22284,11 @@ | |
| 22284 | |
| 22285 | snprintf(prompt, sizeof(prompt), "%c> ", state); |
| 22286 | } |
| 22287 | #ifdef USE_LINENOISE |
| 22288 | if (strcmp(Jim_String(scriptObjPtr), "h") == 0) { |
| 22289 | |
| 22290 | Jim_HistoryShow(); |
| 22291 | Jim_DecrRefCount(interp, scriptObjPtr); |
| 22292 | continue; |
| 22293 | } |
| 22294 | |
| @@ -22104,10 +22311,11 @@ | |
| 22311 | printf("%s\n", result); |
| 22312 | } |
| 22313 | } |
| 22314 | out: |
| 22315 | Jim_Free(history_file); |
| 22316 | |
| 22317 | return retcode; |
| 22318 | } |
| 22319 | |
| 22320 | #include <stdio.h> |
| 22321 | #include <stdlib.h> |
| @@ -22120,11 +22328,11 @@ | |
| 22328 | static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) |
| 22329 | { |
| 22330 | int n; |
| 22331 | Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); |
| 22332 | |
| 22333 | |
| 22334 | for (n = 0; n < argc; n++) { |
| 22335 | Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1); |
| 22336 | |
| 22337 | Jim_ListAppendElement(interp, listObj, obj); |
| 22338 | } |
| @@ -22146,71 +22354,75 @@ | |
| 22354 | printf("or : %s [options] [filename]\n", executable_name); |
| 22355 | printf("\n"); |
| 22356 | printf("Without options: Interactive mode\n"); |
| 22357 | printf("\n"); |
| 22358 | printf("Options:\n"); |
| 22359 | printf(" --version : prints the version string\n"); |
| 22360 | printf(" --help : prints this text\n"); |
| 22361 | printf(" -e CMD : executes command CMD\n"); |
| 22362 | printf(" NOTE: all subsequent options will be passed as arguments to the command\n"); |
| 22363 | printf(" [filename|-] : executes the script contained in the named file, or from stdin if \"-\"\n"); |
| 22364 | printf(" NOTE: all subsequent options will be passed to the script\n\n"); |
| 22365 | } |
| 22366 | |
| 22367 | int main(int argc, char *const argv[]) |
| 22368 | { |
| 22369 | int retcode; |
| 22370 | Jim_Interp *interp; |
| 22371 | char *const orig_argv0 = argv[0]; |
| 22372 | |
| 22373 | |
| 22374 | if (argc > 1 && strcmp(argv[1], "--version") == 0) { |
| 22375 | printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100); |
| 22376 | return 0; |
| 22377 | } |
| 22378 | else if (argc > 1 && strcmp(argv[1], "--help") == 0) { |
| 22379 | usage(argv[0]); |
| 22380 | return 0; |
| 22381 | } |
| 22382 | |
| 22383 | |
| 22384 | interp = Jim_CreateInterp(); |
| 22385 | Jim_RegisterCoreCommands(interp); |
| 22386 | |
| 22387 | |
| 22388 | if (Jim_InitStaticExtensions(interp) != JIM_OK) { |
| 22389 | JimPrintErrorMessage(interp); |
| 22390 | } |
| 22391 | |
| 22392 | Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0); |
| 22393 | Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); |
| 22394 | retcode = Jim_initjimshInit(interp); |
| 22395 | |
| 22396 | if (argc == 1) { |
| 22397 | |
| 22398 | if (retcode == JIM_ERR) { |
| 22399 | JimPrintErrorMessage(interp); |
| 22400 | } |
| 22401 | if (retcode != JIM_EXIT) { |
| 22402 | JimSetArgv(interp, 0, NULL); |
| 22403 | retcode = Jim_InteractivePrompt(interp); |
| 22404 | } |
| 22405 | } |
| 22406 | else { |
| 22407 | |
| 22408 | if (argc > 2 && strcmp(argv[1], "-e") == 0) { |
| 22409 | |
| 22410 | JimSetArgv(interp, argc - 3, argv + 3); |
| 22411 | retcode = Jim_Eval(interp, argv[2]); |
| 22412 | if (retcode != JIM_ERR) { |
| 22413 | printf("%s\n", Jim_String(Jim_GetResult(interp))); |
| 22414 | } |
| 22415 | } |
| 22416 | else { |
| 22417 | Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); |
| 22418 | JimSetArgv(interp, argc - 2, argv + 2); |
| 22419 | if (strcmp(argv[1], "-") == 0) { |
| 22420 | retcode = Jim_Eval(interp, "eval [info source [stdin read] stdin 1]"); |
| 22421 | } else { |
| 22422 | retcode = Jim_EvalFile(interp, argv[1]); |
| 22423 | } |
| 22424 | } |
| 22425 | if (retcode == JIM_ERR) { |
| 22426 | JimPrintErrorMessage(interp); |
| 22427 | } |
| 22428 | } |
| 22429 |