Fossil SCM

Make sure that TH1 variables get removed from the call frame upon being unset.

mistachkin 2014-01-13 23:32 trunk merge
Commit 1ebe4b02e4266211745653283f8e997d906604bc
4 files changed +133 -129 +22 -22 +113 -113 +5
+133 -129
--- src/th.c
+++ src/th.c
@@ -1,8 +1,8 @@
11
22
/*
3
-** The implementation of the TH core. This file contains the parser, and
3
+** The implementation of the TH core. This file contains the parser, and
44
** the implementation of the interface in th.h.
55
*/
66
77
#include "config.h"
88
#include "th.h"
@@ -16,11 +16,11 @@
1616
/*
1717
** Interpreter structure.
1818
*/
1919
struct Th_Interp {
2020
Th_Vtab *pVtab; /* Copy of the argument passed to Th_CreateInterp() */
21
- char *zResult; /* Current interpreter result (Th_Malloc()ed) */
21
+ char *zResult; /* Current interpreter result (Th_Malloc()ed) */
2222
int nResult; /* number of bytes in zResult */
2323
Th_Hash *paCmd; /* Table of registered commands */
2424
Th_Frame *pFrame; /* Current execution frame */
2525
int isListMode; /* True if thSplitList() should operate in "list" mode */
2626
};
@@ -42,25 +42,25 @@
4242
** are stored in the Th_Frame.paVar hash table member of the associated
4343
** stack frame object.
4444
**
4545
** When an interpreter is created, a single Th_Frame structure is also
4646
** allocated - the global variable scope. Th_Interp.pFrame (the current
47
-** interpreter frame) is initialised to point to this Th_Frame. It is
48
-** not deleted for the lifetime of the interpreter (because the global
47
+** interpreter frame) is initialised to point to this Th_Frame. It is
48
+** not deleted for the lifetime of the interpreter (because the global
4949
** frame never goes out of scope).
5050
**
5151
** New stack frames are created by the Th_InFrame() function. Before
5252
** invoking its callback function, Th_InFrame() allocates a new Th_Frame
5353
** structure with pCaller set to the current frame (Th_Interp.pFrame),
5454
** and sets the current frame to the new frame object. After the callback
5555
** has been invoked, the allocated Th_Frame is deleted and the value
5656
** of the current frame pointer restored.
57
-**
58
-** By default, the Th_SetVar(), Th_UnsetVar() and Th_GetVar() functions
59
-** access variable values in the current frame. If they need to access
57
+**
58
+** By default, the Th_SetVar(), Th_UnsetVar() and Th_GetVar() functions
59
+** access variable values in the current frame. If they need to access
6060
** the global frame, they do so by traversing the pCaller pointer list.
61
-** Likewise, the Th_LinkVar() function uses the pCaller pointers to
61
+** Likewise, the Th_LinkVar() function uses the pCaller pointers to
6262
** link to variables located in the global or other stack frames.
6363
*/
6464
struct Th_Frame {
6565
Th_Hash *paVar; /* Variables defined in this scope */
6666
Th_Frame *pCaller; /* Calling frame */
@@ -84,11 +84,11 @@
8484
** value.
8585
*/
8686
struct Th_Variable {
8787
int nRef; /* Number of references to this structure */
8888
int nData; /* Number of bytes at Th_Variable.zData */
89
- char *zData; /* Data for scalar variables */
89
+ char *zData; /* Data for scalar variables */
9090
Th_Hash *pHash; /* Data for array variables */
9191
};
9292
9393
/*
9494
** Hash table API:
@@ -110,19 +110,19 @@
110110
static void thFreeVariable(Th_HashEntry*, void*);
111111
static void thFreeCommand(Th_HashEntry*, void*);
112112
113113
/*
114114
** The following are used by both the expression and language parsers.
115
-** Given that the start of the input string (z, n) is a language
115
+** Given that the start of the input string (z, n) is a language
116116
** construct of the relevant type (a command enclosed in [], an escape
117117
** sequence etc.), these functions determine the number of bytes
118118
** of the input consumed by the construct. For example:
119119
**
120120
** int nByte;
121121
** thNextCommand(interp, "[expr $a+1] $nIter", 18, &nByte);
122122
**
123
-** results in variable nByte being set to 11. Or,
123
+** results in variable nByte being set to 11. Or,
124124
**
125125
** thNextVarname(interp, "$a+1", 4, &nByte);
126126
**
127127
** results in nByte being set to 2.
128128
*/
@@ -132,24 +132,24 @@
132132
static int thNextNumber (Th_Interp*, const char *z, int n, int *pN);
133133
static int thNextSpace (Th_Interp*, const char *z, int n, int *pN);
134134
135135
/*
136136
** Given that the input string (z, n) contains a language construct of
137
-** the relevant type (a command enclosed in [], an escape sequence
137
+** the relevant type (a command enclosed in [], an escape sequence
138138
** like "\xFF" or a variable reference like "${varname}", perform
139139
** substitution on the string and store the resulting string in
140140
** the interpreter result.
141141
*/
142142
static int thSubstCommand(Th_Interp*, const char *z, int n);
143143
static int thSubstEscape (Th_Interp*, const char *z, int n);
144144
static int thSubstVarname(Th_Interp*, const char *z, int n);
145145
146146
/*
147
-** Given that there is a th1 word located at the start of the input
147
+** Given that there is a th1 word located at the start of the input
148148
** string (z, n), determine the length in bytes of that word. If the
149
-** isCmd argument is non-zero, then an unescaped ";" byte not
150
-** located inside of a block or quoted string is considered to mark
149
+** isCmd argument is non-zero, then an unescaped ";" byte not
150
+** located inside of a block or quoted string is considered to mark
151151
** the end of the word.
152152
*/
153153
static int thNextWord(Th_Interp*, const char *z, int n, int *pN, int isCmd);
154154
155155
/*
@@ -176,13 +176,13 @@
176176
** Append nAdd bytes of content copied from zAdd to the end of buffer
177177
** pBuffer. If there is not enough space currently allocated, resize
178178
** the allocation to make space.
179179
*/
180180
static int thBufferWrite(
181
- Th_Interp *interp,
182
- Buffer *pBuffer,
183
- const char *zAdd,
181
+ Th_Interp *interp,
182
+ Buffer *pBuffer,
183
+ const char *zAdd,
184184
int nAdd
185185
){
186186
int nReq;
187187
188188
if( nAdd<0 ){
@@ -311,19 +311,19 @@
311311
Th_HashDelete(interp, pFrame->paVar);
312312
interp->pFrame = pFrame->pCaller;
313313
}
314314
315315
/*
316
-** The first part of the string (zInput,nInput) contains an escape
316
+** The first part of the string (zInput,nInput) contains an escape
317317
** sequence. Set *pnEscape to the number of bytes in the escape sequence.
318318
** If there is a parse error, return TH_ERROR and set the interpreter
319319
** result to an error message. Otherwise return TH_OK.
320320
*/
321321
static int thNextEscape(
322322
Th_Interp *interp,
323
- const char *zInput,
324
- int nInput,
323
+ const char *zInput,
324
+ int nInput,
325325
int *pnEscape
326326
){
327327
int i = 2;
328328
329329
assert(nInput>0);
@@ -344,18 +344,18 @@
344344
return TH_OK;
345345
}
346346
347347
/*
348348
** The first part of the string (zInput,nInput) contains a variable
349
-** reference. Set *pnVarname to the number of bytes in the variable
350
-** reference. If there is a parse error, return TH_ERROR and set the
349
+** reference. Set *pnVarname to the number of bytes in the variable
350
+** reference. If there is a parse error, return TH_ERROR and set the
351351
** interpreter result to an error message. Otherwise return TH_OK.
352352
*/
353353
int thNextVarname(
354354
Th_Interp *interp,
355
- const char *zInput,
356
- int nInput,
355
+ const char *zInput,
356
+ int nInput,
357357
int *pnVarname
358358
){
359359
int i;
360360
361361
assert(nInput>0);
@@ -401,19 +401,19 @@
401401
return TH_OK;
402402
}
403403
404404
/*
405405
** The first part of the string (zInput,nInput) contains a command
406
-** enclosed in a "[]" block. Set *pnCommand to the number of bytes in
407
-** the variable reference. If there is a parse error, return TH_ERROR
408
-** and set the interpreter result to an error message. Otherwise return
406
+** enclosed in a "[]" block. Set *pnCommand to the number of bytes in
407
+** the variable reference. If there is a parse error, return TH_ERROR
408
+** and set the interpreter result to an error message. Otherwise return
409409
** TH_OK.
410410
*/
411411
int thNextCommand(
412412
Th_Interp *interp,
413
- const char *zInput,
414
- int nInput,
413
+ const char *zInput,
414
+ int nInput,
415415
int *pnCommand
416416
){
417417
int nBrace = 0;
418418
int nSquare = 0;
419419
int i;
@@ -438,17 +438,17 @@
438438
439439
return TH_OK;
440440
}
441441
442442
/*
443
-** Set *pnSpace to the number of whitespace bytes at the start of
443
+** Set *pnSpace to the number of whitespace bytes at the start of
444444
** input string (zInput, nInput). Always return TH_OK.
445445
*/
446446
int thNextSpace(
447447
Th_Interp *interp,
448
- const char *zInput,
449
- int nInput,
448
+ const char *zInput,
449
+ int nInput,
450450
int *pnSpace
451451
){
452452
int i;
453453
for(i=0; i<nInput && th_isspace(zInput[i]); i++);
454454
*pnSpace = i;
@@ -457,21 +457,21 @@
457457
458458
/*
459459
** The first byte of the string (zInput,nInput) is not white-space.
460460
** Set *pnWord to the number of bytes in the th1 word that starts
461461
** with this byte. If a complete word cannot be parsed or some other
462
-** error occurs, return TH_ERROR and set the interpreter result to
462
+** error occurs, return TH_ERROR and set the interpreter result to
463463
** an error message. Otherwise return TH_OK.
464464
**
465
-** If the isCmd argument is non-zero, then an unescaped ";" byte not
466
-** located inside of a block or quoted string is considered to mark
465
+** If the isCmd argument is non-zero, then an unescaped ";" byte not
466
+** located inside of a block or quoted string is considered to mark
467467
** the end of the word.
468468
*/
469469
static int thNextWord(
470470
Th_Interp *interp,
471
- const char *zInput,
472
- int nInput,
471
+ const char *zInput,
472
+ int nInput,
473473
int *pnWord,
474474
int isCmd
475475
){
476476
int iEnd = 0;
477477
@@ -531,12 +531,12 @@
531531
return thEvalLocal(interp, &zWord[1], nWord-2);
532532
}
533533
534534
/*
535535
** The input string (zWord, nWord) contains a th1 variable reference
536
-** (a '$' byte followed by a variable name). Perform substitution on
537
-** the input string and store the resulting string in the interpreter
536
+** (a '$' byte followed by a variable name). Perform substitution on
537
+** the input string and store the resulting string in the interpreter
538538
** result.
539539
*/
540540
static int thSubstVarname(
541541
Th_Interp *interp,
542542
const char *zWord,
@@ -572,11 +572,11 @@
572572
return Th_GetVar(interp, &zWord[1], nWord-1);
573573
}
574574
575575
/*
576576
** The input string (zWord, nWord) contains a th1 escape sequence.
577
-** Perform substitution on the input string and store the resulting
577
+** Perform substitution on the input string and store the resulting
578578
** string in the interpreter result.
579579
*/
580580
static int thSubstEscape(
581581
Th_Interp *interp,
582582
const char *zWord,
@@ -608,11 +608,11 @@
608608
return TH_OK;
609609
}
610610
611611
/*
612612
** The input string (zWord, nWord) contains a th1 word. Perform
613
-** substitution on the input string and store the resulting
613
+** substitution on the input string and store the resulting
614614
** string in the interpreter result.
615615
*/
616616
static int thSubstWord(
617617
Th_Interp *interp,
618618
const char *zWord,
@@ -640,20 +640,20 @@
640640
int (*xGet)(Th_Interp *, const char*, int, int *) = 0;
641641
int (*xSubst)(Th_Interp *, const char*, int) = 0;
642642
643643
switch( zWord[i] ){
644644
case '\\':
645
- xGet = thNextEscape; xSubst = thSubstEscape;
645
+ xGet = thNextEscape; xSubst = thSubstEscape;
646646
break;
647647
case '[':
648648
if( !interp->isListMode ){
649
- xGet = thNextCommand; xSubst = thSubstCommand;
649
+ xGet = thNextCommand; xSubst = thSubstCommand;
650650
break;
651651
}
652652
case '$':
653653
if( !interp->isListMode ){
654
- xGet = thNextVarname; xSubst = thSubstVarname;
654
+ xGet = thNextVarname; xSubst = thSubstVarname;
655655
break;
656656
}
657657
default: {
658658
thBufferWrite(interp, &output, &zWord[i], 1);
659659
continue; /* Go to the next iteration of the for(...) loop */
@@ -685,11 +685,11 @@
685685
** Return true if one of the following is true of the buffer pointed
686686
** to by zInput, length nInput:
687687
**
688688
** + It is empty, or
689689
** + It contains nothing but white-space, or
690
-** + It contains no non-white-space characters before the first
690
+** + It contains no non-white-space characters before the first
691691
** newline character.
692692
**
693693
** Otherwise return false.
694694
*/
695695
static int thEndOfLine(const char *zInput, int nInput){
@@ -725,16 +725,16 @@
725725
** // Free all memory allocated by Th_SplitList(). The arrays pointed
726726
** // to by argv and argl are invalidated by this call.
727727
** //
728728
** Th_Free(interp, argv);
729729
**
730
-*/
730
+*/
731731
static int thSplitList(
732732
Th_Interp *interp, /* Interpreter context */
733
- const char *zList, /* Pointer to buffer containing input list */
733
+ const char *zList, /* Pointer to buffer containing input list */
734734
int nList, /* Size of buffer pointed to by zList */
735
- char ***pazElem, /* OUT: Array of list elements */
735
+ char ***pazElem, /* OUT: Array of list elements */
736736
int **panElem, /* OUT: Lengths of each list element */
737737
int *pnCount /* OUT: Number of list elements */
738738
){
739739
int rc = TH_OK;
740740
@@ -774,14 +774,14 @@
774774
assert((lenbuf.nBuf/sizeof(int))==nCount);
775775
776776
assert((pazElem && panElem) || (!pazElem && !panElem));
777777
if( pazElem && rc==TH_OK ){
778778
int i;
779
- char *zElem;
779
+ char *zElem;
780780
int *anElem;
781781
char **azElem = Th_Malloc(interp,
782
- sizeof(char*) * nCount + /* azElem */
782
+ sizeof(char*) * nCount + /* azElem */
783783
sizeof(int) * nCount + /* anElem */
784784
strbuf.nBuf /* space for list element strings */
785785
);
786786
anElem = (int *)&azElem[nCount];
787787
zElem = (char *)&anElem[nCount];
@@ -795,11 +795,11 @@
795795
*panElem = anElem;
796796
}
797797
if( pnCount ){
798798
*pnCount = nCount;
799799
}
800
-
800
+
801801
finish:
802802
thBufferFree(interp, &strbuf);
803803
thBufferFree(interp, &lenbuf);
804804
return rc;
805805
}
@@ -876,18 +876,18 @@
876876
if( rc==TH_OK ){
877877
Th_Command *p = (Th_Command *)(pEntry->pData);
878878
const char **azArg = (const char **)argv;
879879
rc = p->xProc(interp, p->pContext, argc, azArg, argl);
880880
}
881
-
881
+
882882
/* If an error occurred, add this command to the stack trace report. */
883883
if( rc==TH_ERROR ){
884884
char *zRes;
885885
int nRes;
886886
char *zStack = 0;
887887
int nStack = 0;
888
-
888
+
889889
zRes = Th_TakeResult(interp, &nRes);
890890
if( TH_OK==Th_GetVar(interp, (char *)"::th_stack_trace", -1) ){
891891
zStack = Th_TakeResult(interp, &nStack);
892892
}
893893
Th_ListAppend(interp, &zStack, &nStack, zFirst, zInput-zFirst);
@@ -912,15 +912,15 @@
912912
**
913913
** Argument iFrame is interpreted as follows:
914914
**
915915
** * If iFrame is 0, this means the current frame.
916916
**
917
-** * If iFrame is negative, then the nth frame up the stack, where
918
-** n is the absolute value of iFrame. A value of -1 means the
917
+** * If iFrame is negative, then the nth frame up the stack, where
918
+** n is the absolute value of iFrame. A value of -1 means the
919919
** calling procedure.
920920
**
921
-** * If iFrame is +ve, then the nth frame from the bottom of the
921
+** * If iFrame is +ve, then the nth frame from the bottom of the
922922
** stack. An iFrame value of 1 means the toplevel (global) frame.
923923
*/
924924
static Th_Frame *getFrame(Th_Interp *interp, int iFrame){
925925
Th_Frame *p = interp->pFrame;
926926
int i;
@@ -948,28 +948,28 @@
948948
949949
950950
/*
951951
** Evaluate th1 script (zProgram, nProgram) in the frame identified by
952952
** argument iFrame. Leave either an error message or a result in the
953
-** interpreter result and return a th1 error code (TH_OK, TH_ERROR,
953
+** interpreter result and return a th1 error code (TH_OK, TH_ERROR,
954954
** TH_RETURN, TH_CONTINUE or TH_BREAK).
955955
*/
956956
int Th_Eval(Th_Interp *interp, int iFrame, const char *zProgram, int nProgram){
957957
int rc = TH_OK;
958958
Th_Frame *pSavedFrame = interp->pFrame;
959959
960
- /* Set Th_Interp.pFrame to the frame that this script is to be
960
+ /* Set Th_Interp.pFrame to the frame that this script is to be
961961
** evaluated in. The current frame is saved in pSavedFrame and will
962962
** be restored before this function returns.
963963
*/
964964
interp->pFrame = getFrame(interp, iFrame);
965965
966966
if( !interp->pFrame ){
967967
rc = TH_ERROR;
968968
}else{
969969
int nInput = nProgram;
970
-
970
+
971971
if( nInput<0 ){
972972
nInput = th_strlen(zProgram);
973973
}
974974
rc = thEvalLocal(interp, zProgram, nInput);
975975
}
@@ -995,13 +995,13 @@
995995
** array key name.
996996
*/
997997
static int thAnalyseVarname(
998998
const char *zVarname,
999999
int nVarname,
1000
- const char **pzOuter, /* OUT: Pointer to scalar/array name */
1000
+ const char **pzOuter, /* OUT: Pointer to scalar/array name */
10011001
int *pnOuter, /* OUT: Number of bytes at *pzOuter */
1002
- const char **pzInner, /* OUT: Pointer to array key (or null) */
1002
+ const char **pzInner, /* OUT: Pointer to array key (or null) */
10031003
int *pnInner, /* OUT: Number of bytes at *pzInner */
10041004
int *pisGlobal /* OUT: Set to true if this is a global ref */
10051005
){
10061006
const char *zOuter = zVarname;
10071007
int nOuter;
@@ -1044,11 +1044,11 @@
10441044
return TH_OK;
10451045
}
10461046
10471047
/*
10481048
** Input string (zVar, nVar) contains a variable name. This function locates
1049
-** the Th_Variable structure associated with the named variable. The
1049
+** the Th_Variable structure associated with the named variable. The
10501050
** variable name may be a global or local scalar or array variable
10511051
**
10521052
** If the create argument is non-zero and the named variable does not exist
10531053
** it is created. Otherwise, an error is left in the interpreter result
10541054
** and NULL returned.
@@ -1057,11 +1057,11 @@
10571057
** an error is left in the interpreter result and NULL returned. If
10581058
** arrayok is true an array name is Ok.
10591059
*/
10601060
static Th_Variable *thFindValue(
10611061
Th_Interp *interp,
1062
- const char *zVar, /* Pointer to variable name */
1062
+ const char *zVar, /* Pointer to variable name */
10631063
int nVar, /* Number of bytes at nVar */
10641064
int create, /* If true, create the variable if not found */
10651065
int arrayok, /* If true, an array is Ok. Otherwise array==error */
10661066
int noerror /* If false, set interpreter result to error message */
10671067
){
@@ -1079,11 +1079,11 @@
10791079
if( isGlobal ){
10801080
while( pFrame->pCaller ) pFrame = pFrame->pCaller;
10811081
}
10821082
10831083
pEntry = Th_HashFind(interp, pFrame->paVar, zOuter, nOuter, create);
1084
- assert(pEntry || !create);
1084
+ assert(pEntry || create<=0);
10851085
if( !pEntry ){
10861086
goto no_such_var;
10871087
}
10881088
10891089
pValue = (Th_Variable *)pEntry->pData;
@@ -1135,12 +1135,12 @@
11351135
}
11361136
return 0;
11371137
}
11381138
11391139
/*
1140
-** String (zVar, nVar) must contain the name of a scalar variable or
1141
-** array member. Look up the variable, store its current value in
1140
+** String (zVar, nVar) must contain the name of a scalar variable or
1141
+** array member. Look up the variable, store its current value in
11421142
** the interpreter result and return TH_OK.
11431143
**
11441144
** If the named variable does not exist, return TH_ERROR and leave
11451145
** an error message in the interpreter result.
11461146
*/
@@ -1174,12 +1174,12 @@
11741174
**
11751175
** If (zVar, nVar) refers to an existing array, TH_ERROR is returned
11761176
** and an error message left in the interpreter result.
11771177
*/
11781178
int Th_SetVar(
1179
- Th_Interp *interp,
1180
- const char *zVar,
1179
+ Th_Interp *interp,
1180
+ const char *zVar,
11811181
int nVar,
11821182
const char *zValue,
11831183
int nValue
11841184
){
11851185
Th_Variable *pValue;
@@ -1210,13 +1210,13 @@
12101210
** Create a variable link so that accessing variable (zLocal, nLocal) is
12111211
** the same as accessing variable (zLink, nLink) in stack frame iFrame.
12121212
*/
12131213
int Th_LinkVar(
12141214
Th_Interp *interp, /* Interpreter */
1215
- const char *zLocal, int nLocal, /* Local varname */
1215
+ const char *zLocal, int nLocal, /* Local varname */
12161216
int iFrame, /* Stack frame of linked var */
1217
- const char *zLink, int nLink /* Linked varname */
1217
+ const char *zLink, int nLink /* Linked varname */
12181218
){
12191219
Th_Frame *pSavedFrame = interp->pFrame;
12201220
Th_Frame *pFrame;
12211221
Th_HashEntry *pEntry;
12221222
Th_Variable *pValue;
@@ -1253,17 +1253,21 @@
12531253
pValue = thFindValue(interp, zVar, nVar, 0, 1, 0);
12541254
if( !pValue ){
12551255
return TH_ERROR;
12561256
}
12571257
1258
- Th_Free(interp, pValue->zData);
1259
- pValue->zData = 0;
1258
+ if( pValue->zData ){
1259
+ Th_Free(interp, pValue->zData);
1260
+ pValue->zData = 0;
1261
+ }
12601262
if( pValue->pHash ){
12611263
Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp);
12621264
Th_HashDelete(interp, pValue->pHash);
12631265
pValue->pHash = 0;
12641266
}
1267
+
1268
+ thFindValue(interp, zVar, nVar, -1, 1, 1); /* Finally, delete from frame */
12651269
return TH_OK;
12661270
}
12671271
12681272
/*
12691273
** Return an allocated buffer containing a copy of string (z, n). The
@@ -1299,11 +1303,11 @@
12991303
if( interp ){
13001304
char *zRes = 0;
13011305
int nRes = 0;
13021306
13031307
Th_SetVar(interp, (char *)"::th_stack_trace", -1, 0, 0);
1304
-
1308
+
13051309
Th_StringAppend(interp, &zRes, &nRes, zPre, -1);
13061310
if( zRes[nRes-1]=='"' ){
13071311
Th_StringAppend(interp, &zRes, &nRes, z, n);
13081312
Th_StringAppend(interp, &zRes, &nRes, (const char *)"\"", 1);
13091313
}else{
@@ -1381,12 +1385,12 @@
13811385
return (char *)Th_Malloc(pInterp, 1);
13821386
}
13831387
}
13841388
13851389
1386
-/*
1387
-** Wrappers around the supplied malloc() and free()
1390
+/*
1391
+** Wrappers around the supplied malloc() and free()
13881392
*/
13891393
void *Th_Malloc(Th_Interp *pInterp, int nByte){
13901394
void *p = pInterp->pVtab->xMalloc(nByte);
13911395
if( p ){
13921396
memset(p, 0, nByte);
@@ -1398,16 +1402,16 @@
13981402
pInterp->pVtab->xFree(z);
13991403
}
14001404
}
14011405
14021406
/*
1403
-** Install a new th1 command.
1407
+** Install a new th1 command.
14041408
**
14051409
** If a command of the same name already exists, it is deleted automatically.
14061410
*/
14071411
int Th_CreateCommand(
1408
- Th_Interp *interp,
1412
+ Th_Interp *interp,
14091413
const char *zName, /* New command name */
14101414
Th_CommandProc xProc, /* Command callback proc */
14111415
void *pContext, /* Value to pass as second arg to xProc */
14121416
void (*xDel)(Th_Interp *, void *) /* Command destructor callback */
14131417
){
@@ -1425,27 +1429,27 @@
14251429
}
14261430
pCommand->xProc = xProc;
14271431
pCommand->pContext = pContext;
14281432
pCommand->xDel = xDel;
14291433
pEntry->pData = (void *)pCommand;
1430
-
1434
+
14311435
return TH_OK;
14321436
}
14331437
14341438
/*
1435
-** Rename the existing command (zName, nName) to (zNew, nNew). If nNew is 0,
1439
+** Rename the existing command (zName, nName) to (zNew, nNew). If nNew is 0,
14361440
** the command is deleted instead of renamed.
14371441
**
14381442
** If successful, TH_OK is returned. If command zName does not exist, or
1439
-** if command zNew already exists, an error message is left in the
1443
+** if command zNew already exists, an error message is left in the
14401444
** interpreter result and TH_ERROR is returned.
14411445
*/
14421446
int Th_RenameCommand(
1443
- Th_Interp *interp,
1444
- const char *zName, /* Existing command name */
1447
+ Th_Interp *interp,
1448
+ const char *zName, /* Existing command name */
14451449
int nName, /* Number of bytes at zName */
1446
- const char *zNew, /* New command name */
1450
+ const char *zNew, /* New command name */
14471451
int nNew /* Number of bytes at zNew */
14481452
){
14491453
Th_HashEntry *pEntry;
14501454
Th_HashEntry *pNewEntry;
14511455
@@ -1499,11 +1503,11 @@
14991503
** If an error occurs (if (zList, nList) is not a valid list) an error
15001504
** message is left in the interpreter result and TH_ERROR returned.
15011505
**
15021506
** If successful, *pnCount is set to the number of elements in the list.
15031507
** panElem is set to point at an array of *pnCount integers - the lengths
1504
-** of the element values. *pazElem is set to point at an array of
1508
+** of the element values. *pazElem is set to point at an array of
15051509
** pointers to buffers containing the array element's data.
15061510
**
15071511
** To free the arrays allocated at *pazElem and *panElem, the caller
15081512
** should call Th_Free() on *pazElem only. Exactly one such call to
15091513
** Th_Free() must be made per call to Th_SplitList().
@@ -1525,13 +1529,13 @@
15251529
** Th_Free(interp, azElem);
15261530
**
15271531
*/
15281532
int Th_SplitList(
15291533
Th_Interp *interp,
1530
- const char *zList, /* Pointer to buffer containing list */
1534
+ const char *zList, /* Pointer to buffer containing list */
15311535
int nList, /* Number of bytes at zList */
1532
- char ***pazElem, /* OUT: Array of pointers to element data */
1536
+ char ***pazElem, /* OUT: Array of pointers to element data */
15331537
int **panElem, /* OUT: Array of element data lengths */
15341538
int *pnCount /* OUT: Number of elements in list */
15351539
){
15361540
int rc;
15371541
interp->isListMode = 1;
@@ -1542,16 +1546,16 @@
15421546
}
15431547
return rc;
15441548
}
15451549
15461550
/*
1547
-** Append a new element to an existing th1 list. The element to append
1551
+** Append a new element to an existing th1 list. The element to append
15481552
** to the list is (zElem, nElem).
15491553
**
15501554
** A pointer to the existing list must be stored at *pzList when this
1551
-** function is called. The length must be stored in *pnList. The value
1552
-** of *pzList must either be NULL (in which case *pnList must be 0), or
1555
+** function is called. The length must be stored in *pnList. The value
1556
+** of *pzList must either be NULL (in which case *pnList must be 0), or
15531557
** a pointer to memory obtained from Th_Malloc().
15541558
**
15551559
** This function calls Th_Free() to free the buffer at *pzList and sets
15561560
** *pzList to point to a new buffer containing the new list value. *pnList
15571561
** is similarly updated before returning. The return value is always TH_OK.
@@ -1568,13 +1572,13 @@
15681572
** Th_Free(interp, zList);
15691573
**
15701574
*/
15711575
int Th_ListAppend(
15721576
Th_Interp *interp, /* Interpreter context */
1573
- char **pzList, /* IN/OUT: Ptr to ptr to list */
1577
+ char **pzList, /* IN/OUT: Ptr to ptr to list */
15741578
int *pnList, /* IN/OUT: Current length of *pzList */
1575
- const char *zElem, /* Data to append */
1579
+ const char *zElem, /* Data to append */
15761580
int nElem /* Length of nElem */
15771581
){
15781582
Buffer output;
15791583
int i;
15801584
@@ -1623,13 +1627,13 @@
16231627
** Append a new element to an existing th1 string. This function uses
16241628
** the same interface as the Th_ListAppend() function.
16251629
*/
16261630
int Th_StringAppend(
16271631
Th_Interp *interp, /* Interpreter context */
1628
- char **pzStr, /* IN/OUT: Ptr to ptr to list */
1632
+ char **pzStr, /* IN/OUT: Ptr to ptr to list */
16291633
int *pnStr, /* IN/OUT: Current length of *pzStr */
1630
- const char *zElem, /* Data to append */
1634
+ const char *zElem, /* Data to append */
16311635
int nElem /* Length of nElem */
16321636
){
16331637
char *zNew;
16341638
int nNew;
16351639
@@ -1647,11 +1651,11 @@
16471651
*pnStr = nNew;
16481652
16491653
return TH_OK;
16501654
}
16511655
1652
-/*
1656
+/*
16531657
** Delete an interpreter.
16541658
*/
16551659
void Th_DeleteInterp(Th_Interp *interp){
16561660
assert(interp->pFrame);
16571661
assert(0==interp->pFrame->pCaller);
@@ -1668,11 +1672,11 @@
16681672
16691673
/* Delete the interpreter structure itself. */
16701674
Th_Free(interp, (void *)interp);
16711675
}
16721676
1673
-/*
1677
+/*
16741678
** Create a new interpreter.
16751679
*/
16761680
Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){
16771681
Th_Interp *p;
16781682
@@ -1702,11 +1706,11 @@
17021706
Operator *pOp;
17031707
Expr *pParent;
17041708
Expr *pLeft;
17051709
Expr *pRight;
17061710
1707
- char *zValue; /* Pointer to literal value */
1711
+ char *zValue; /* Pointer to literal value */
17081712
int nValue; /* Length of literal value buffer */
17091713
};
17101714
17111715
/* Unary operators */
17121716
#define OP_UNARY_MINUS 2
@@ -1758,11 +1762,11 @@
17581762
{"+", OP_UNARY_PLUS, 1, ARG_NUMBER},
17591763
{"~", OP_BITWISE_NOT, 1, ARG_INTEGER},
17601764
{"!", OP_LOGICAL_NOT, 1, ARG_INTEGER},
17611765
17621766
/* Binary operators. It is important to the parsing in Th_Expr() that
1763
- * the two-character symbols ("==") appear before the one-character
1767
+ * the two-character symbols ("==") appear before the one-character
17641768
* ones ("="). And that the priorities of all binary operators are
17651769
* integers between 2 and 12.
17661770
*/
17671771
{"<<", OP_LEFTSHIFT, 4, ARG_INTEGER},
17681772
{">>", OP_RIGHTSHIFT, 4, ARG_INTEGER},
@@ -1789,16 +1793,16 @@
17891793
{0,0,0,0}
17901794
};
17911795
17921796
/*
17931797
** The first part of the string (zInput,nInput) contains a number.
1794
-** Set *pnVarname to the number of bytes in the numeric string.
1798
+** Set *pnVarname to the number of bytes in the numeric string.
17951799
*/
17961800
static int thNextNumber(
1797
- Th_Interp *interp,
1798
- const char *zInput,
1799
- int nInput,
1801
+ Th_Interp *interp,
1802
+ const char *zInput,
1803
+ int nInput,
18001804
int *pnLiteral
18011805
){
18021806
int i;
18031807
int seenDot = 0;
18041808
for(i=0; i<nInput; i++){
@@ -1864,11 +1868,11 @@
18641868
if( eArgType==ARG_NUMBER ){
18651869
if( (zLeft==0 || TH_OK==Th_ToInt(0, zLeft, nLeft, &iLeft))
18661870
&& (zRight==0 || TH_OK==Th_ToInt(0, zRight, nRight, &iRight))
18671871
){
18681872
eArgType = ARG_INTEGER;
1869
- }else if(
1873
+ }else if(
18701874
(zLeft && TH_OK!=Th_ToDouble(interp, zLeft, nLeft, &fLeft)) ||
18711875
(zRight && TH_OK!=Th_ToDouble(interp, zRight, nRight, &fRight))
18721876
){
18731877
/* A type error. */
18741878
rc = TH_ERROR;
@@ -1876,11 +1880,11 @@
18761880
}else if( eArgType==ARG_INTEGER ){
18771881
rc = Th_ToInt(interp, zLeft, nLeft, &iLeft);
18781882
if( rc==TH_OK && zRight ){
18791883
rc = Th_ToInt(interp, zRight, nRight, &iRight);
18801884
}
1881
- }
1885
+ }
18821886
}
18831887
18841888
if( rc==TH_OK && eArgType==ARG_INTEGER ){
18851889
int iRes = 0;
18861890
switch( pExpr->pOp->eOp ) {
@@ -1978,11 +1982,11 @@
19781982
#define ISTERM(x) (apToken[x] && (!apToken[x]->pOp || apToken[x]->pLeft))
19791983
19801984
for(jj=0; jj<nToken; jj++){
19811985
if( apToken[jj]->pOp && apToken[jj]->pOp->eOp==OP_OPEN_BRACKET ){
19821986
int nNest = 1;
1983
- int iLeft = jj;
1987
+ int iLeft = jj;
19841988
19851989
for(jj++; jj<nToken; jj++){
19861990
Operator *pOp = apToken[jj]->pOp;
19871991
if( pOp && pOp->eOp==OP_OPEN_BRACKET ) nNest++;
19881992
if( pOp && pOp->eOp==OP_CLOSE_BRACKET ) nNest--;
@@ -2052,11 +2056,11 @@
20522056
/*
20532057
** Parse a string containing a TH expression to a list of tokens.
20542058
*/
20552059
static int exprParse(
20562060
Th_Interp *interp, /* Interpreter to leave error message in */
2057
- const char *zExpr, /* Pointer to input string */
2061
+ const char *zExpr, /* Pointer to input string */
20582062
int nExpr, /* Number of bytes at zExpr */
20592063
Expr ***papToken, /* OUT: Array of tokens. */
20602064
int *pnToken /* OUT: Size of token array */
20612065
){
20622066
int i;
@@ -2127,11 +2131,11 @@
21272131
memcpy(pNew->zValue, z, pNew->nValue);
21282132
i += pNew->nValue;
21292133
}
21302134
if( (nToken%16)==0 ){
21312135
/* Grow the apToken array. */
2132
- Expr **apTokenOld = apToken;
2136
+ Expr **apTokenOld = apToken;
21332137
apToken = Th_Malloc(interp, sizeof(Expr *)*(nToken+16));
21342138
memcpy(apToken, apTokenOld, sizeof(Expr *)*nToken);
21352139
}
21362140
21372141
/* Put the new token at the end of the apToken array */
@@ -2152,11 +2156,11 @@
21522156
/*
21532157
** Evaluate the string (zExpr, nExpr) as a Th expression. Store
21542158
** the result in the interpreter interp and return TH_OK if
21552159
** successful. If an error occurs, store an error message in
21562160
** the interpreter result and return an error code.
2157
-*/
2161
+*/
21582162
int Th_Expr(Th_Interp *interp, const char *zExpr, int nExpr){
21592163
int rc; /* Return Code */
21602164
int i; /* Loop counter */
21612165
21622166
int nToken = 0;
@@ -2169,11 +2173,11 @@
21692173
/* Parse the expression to a list of tokens. */
21702174
rc = exprParse(interp, zExpr, nExpr, &apToken, &nToken);
21712175
21722176
/* If the parsing was successful, create an expression tree from
21732177
** the parsed list of tokens. If successful, apToken[0] is set
2174
- ** to point to the root of the expression tree.
2178
+ ** to point to the root of the expression tree.
21752179
*/
21762180
if( rc==TH_OK ){
21772181
rc = exprMakeTree(interp, apToken, nToken);
21782182
}
21792183
@@ -2210,11 +2214,11 @@
22102214
** the callback function xCallback for each entry. The second argument
22112215
** passed to xCallback is a copy of the fourth argument passed to this
22122216
** function.
22132217
*/
22142218
void Th_HashIterate(
2215
- Th_Interp *interp,
2219
+ Th_Interp *interp,
22162220
Th_Hash *pHash,
22172221
void (*xCallback)(Th_HashEntry *pEntry, void *pContext),
22182222
void *pContext
22192223
){
22202224
int i;
@@ -2244,14 +2248,14 @@
22442248
Th_Free(interp, pHash);
22452249
}
22462250
}
22472251
22482252
/*
2249
-** This function is used to insert or delete hash table items, or to
2253
+** This function is used to insert or delete hash table items, or to
22502254
** query a hash table for an existing item.
22512255
**
2252
-** If parameter op is less than zero, then the hash-table element
2256
+** If parameter op is less than zero, then the hash-table element
22532257
** identified by (zKey, nKey) is removed from the hash-table if it
22542258
** exists. NULL is returned.
22552259
**
22562260
** Otherwise, if the hash-table contains an item with key (zKey, nKey),
22572261
** a pointer to the associated Th_HashEntry is returned. If parameter
@@ -2258,11 +2262,11 @@
22582262
** op is greater than zero, then a new entry is added if one cannot
22592263
** be found. If op is zero, then NULL is returned if the item is
22602264
** not already present in the hash-table.
22612265
*/
22622266
Th_HashEntry *Th_HashFind(
2263
- Th_Interp *interp,
2267
+ Th_Interp *interp,
22642268
Th_Hash *pHash,
22652269
const char *zKey,
22662270
int nKey,
22672271
int op /* -ve = delete, 0 = find, +ve = insert */
22682272
){
@@ -2326,11 +2330,11 @@
23262330
** '\f' 0x0C
23272331
** '\r' 0x0D
23282332
**
23292333
** Whitespace characters have the 0x01 flag set. Decimal digits have the
23302334
** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
2331
-** Alphabet characters have the 0x8 bit set.
2335
+** Alphabet characters have the 0x8 bit set.
23322336
**
23332337
** The special list characters have the 0x10 flag set
23342338
**
23352339
** { } [ ] \ ; ' "
23362340
**
@@ -2477,14 +2481,14 @@
24772481
return z - zBegin;
24782482
}
24792483
24802484
/*
24812485
** Try to convert the string passed as arguments (z, n) to an integer.
2482
-** If successful, store the result in *piOut and return TH_OK.
2486
+** If successful, store the result in *piOut and return TH_OK.
24832487
**
2484
-** If the string cannot be converted to an integer, return TH_ERROR.
2485
-** If the interp argument is not NULL, leave an error message in the
2488
+** If the string cannot be converted to an integer, return TH_ERROR.
2489
+** If the interp argument is not NULL, leave an error message in the
24862490
** interpreter result too.
24872491
*/
24882492
int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
24892493
int i = 0;
24902494
int iOut = 0;
@@ -2512,20 +2516,20 @@
25122516
return TH_OK;
25132517
}
25142518
25152519
/*
25162520
** Try to convert the string passed as arguments (z, n) to a double.
2517
-** If successful, store the result in *pfOut and return TH_OK.
2521
+** If successful, store the result in *pfOut and return TH_OK.
25182522
**
2519
-** If the string cannot be converted to a double, return TH_ERROR.
2520
-** If the interp argument is not NULL, leave an error message in the
2523
+** If the string cannot be converted to a double, return TH_ERROR.
2524
+** If the interp argument is not NULL, leave an error message in the
25212525
** interpreter result too.
25222526
*/
25232527
int Th_ToDouble(
2524
- Th_Interp *interp,
2525
- const char *z,
2526
- int n,
2528
+ Th_Interp *interp,
2529
+ const char *z,
2530
+ int n,
25272531
double *pfOut
25282532
){
25292533
if( !sqlite3IsNumber((const char *)z, 0) ){
25302534
Th_ErrorMessage(interp, "expected number, got: \"", z, n);
25312535
return TH_ERROR;
@@ -2566,33 +2570,33 @@
25662570
** the double fVal and return TH_OK.
25672571
*/
25682572
int Th_SetResultDouble(Th_Interp *interp, double fVal){
25692573
int i; /* Iterator variable */
25702574
double v = fVal; /* Input value */
2571
- char zBuf[128]; /* Output buffer */
2572
- char *z = zBuf; /* Output cursor */
2575
+ char zBuf[128]; /* Output buffer */
2576
+ char *z = zBuf; /* Output cursor */
25732577
int iDot = 0; /* Digit after which to place decimal point */
25742578
int iExp = 0; /* Exponent (NN in eNN) */
2575
- const char *zExp; /* String representation of iExp */
2579
+ const char *zExp; /* String representation of iExp */
25762580
25772581
/* Precision: */
25782582
#define INSIGNIFICANT 0.000000000001
25792583
#define ROUNDER 0.0000000000005
25802584
double insignificant = INSIGNIFICANT;
25812585
25822586
/* If the real value is negative, write a '-' character to the
25832587
* output and transform v to the corresponding positive number.
2584
- */
2588
+ */
25852589
if( v<0.0 ){
25862590
*z++ = '-';
25872591
v *= -1.0;
25882592
}
25892593
2590
- /* Normalize v to a value between 1.0 and 10.0. Integer
2594
+ /* Normalize v to a value between 1.0 and 10.0. Integer
25912595
* variable iExp is set to the exponent. i.e the original
25922596
* value is (v * 10^iExp) (or the negative thereof).
2593
- */
2597
+ */
25942598
if( v>0.0 ){
25952599
while( (v+ROUNDER)>=10.0 ) { iExp++; v *= 0.1; }
25962600
while( (v+ROUNDER)<1.0 ) { iExp--; v *= 10.0; }
25972601
}
25982602
v += ROUNDER;
25992603
--- src/th.c
+++ src/th.c
@@ -1,8 +1,8 @@
1
2 /*
3 ** The implementation of the TH core. This file contains the parser, and
4 ** the implementation of the interface in th.h.
5 */
6
7 #include "config.h"
8 #include "th.h"
@@ -16,11 +16,11 @@
16 /*
17 ** Interpreter structure.
18 */
19 struct Th_Interp {
20 Th_Vtab *pVtab; /* Copy of the argument passed to Th_CreateInterp() */
21 char *zResult; /* Current interpreter result (Th_Malloc()ed) */
22 int nResult; /* number of bytes in zResult */
23 Th_Hash *paCmd; /* Table of registered commands */
24 Th_Frame *pFrame; /* Current execution frame */
25 int isListMode; /* True if thSplitList() should operate in "list" mode */
26 };
@@ -42,25 +42,25 @@
42 ** are stored in the Th_Frame.paVar hash table member of the associated
43 ** stack frame object.
44 **
45 ** When an interpreter is created, a single Th_Frame structure is also
46 ** allocated - the global variable scope. Th_Interp.pFrame (the current
47 ** interpreter frame) is initialised to point to this Th_Frame. It is
48 ** not deleted for the lifetime of the interpreter (because the global
49 ** frame never goes out of scope).
50 **
51 ** New stack frames are created by the Th_InFrame() function. Before
52 ** invoking its callback function, Th_InFrame() allocates a new Th_Frame
53 ** structure with pCaller set to the current frame (Th_Interp.pFrame),
54 ** and sets the current frame to the new frame object. After the callback
55 ** has been invoked, the allocated Th_Frame is deleted and the value
56 ** of the current frame pointer restored.
57 **
58 ** By default, the Th_SetVar(), Th_UnsetVar() and Th_GetVar() functions
59 ** access variable values in the current frame. If they need to access
60 ** the global frame, they do so by traversing the pCaller pointer list.
61 ** Likewise, the Th_LinkVar() function uses the pCaller pointers to
62 ** link to variables located in the global or other stack frames.
63 */
64 struct Th_Frame {
65 Th_Hash *paVar; /* Variables defined in this scope */
66 Th_Frame *pCaller; /* Calling frame */
@@ -84,11 +84,11 @@
84 ** value.
85 */
86 struct Th_Variable {
87 int nRef; /* Number of references to this structure */
88 int nData; /* Number of bytes at Th_Variable.zData */
89 char *zData; /* Data for scalar variables */
90 Th_Hash *pHash; /* Data for array variables */
91 };
92
93 /*
94 ** Hash table API:
@@ -110,19 +110,19 @@
110 static void thFreeVariable(Th_HashEntry*, void*);
111 static void thFreeCommand(Th_HashEntry*, void*);
112
113 /*
114 ** The following are used by both the expression and language parsers.
115 ** Given that the start of the input string (z, n) is a language
116 ** construct of the relevant type (a command enclosed in [], an escape
117 ** sequence etc.), these functions determine the number of bytes
118 ** of the input consumed by the construct. For example:
119 **
120 ** int nByte;
121 ** thNextCommand(interp, "[expr $a+1] $nIter", 18, &nByte);
122 **
123 ** results in variable nByte being set to 11. Or,
124 **
125 ** thNextVarname(interp, "$a+1", 4, &nByte);
126 **
127 ** results in nByte being set to 2.
128 */
@@ -132,24 +132,24 @@
132 static int thNextNumber (Th_Interp*, const char *z, int n, int *pN);
133 static int thNextSpace (Th_Interp*, const char *z, int n, int *pN);
134
135 /*
136 ** Given that the input string (z, n) contains a language construct of
137 ** the relevant type (a command enclosed in [], an escape sequence
138 ** like "\xFF" or a variable reference like "${varname}", perform
139 ** substitution on the string and store the resulting string in
140 ** the interpreter result.
141 */
142 static int thSubstCommand(Th_Interp*, const char *z, int n);
143 static int thSubstEscape (Th_Interp*, const char *z, int n);
144 static int thSubstVarname(Th_Interp*, const char *z, int n);
145
146 /*
147 ** Given that there is a th1 word located at the start of the input
148 ** string (z, n), determine the length in bytes of that word. If the
149 ** isCmd argument is non-zero, then an unescaped ";" byte not
150 ** located inside of a block or quoted string is considered to mark
151 ** the end of the word.
152 */
153 static int thNextWord(Th_Interp*, const char *z, int n, int *pN, int isCmd);
154
155 /*
@@ -176,13 +176,13 @@
176 ** Append nAdd bytes of content copied from zAdd to the end of buffer
177 ** pBuffer. If there is not enough space currently allocated, resize
178 ** the allocation to make space.
179 */
180 static int thBufferWrite(
181 Th_Interp *interp,
182 Buffer *pBuffer,
183 const char *zAdd,
184 int nAdd
185 ){
186 int nReq;
187
188 if( nAdd<0 ){
@@ -311,19 +311,19 @@
311 Th_HashDelete(interp, pFrame->paVar);
312 interp->pFrame = pFrame->pCaller;
313 }
314
315 /*
316 ** The first part of the string (zInput,nInput) contains an escape
317 ** sequence. Set *pnEscape to the number of bytes in the escape sequence.
318 ** If there is a parse error, return TH_ERROR and set the interpreter
319 ** result to an error message. Otherwise return TH_OK.
320 */
321 static int thNextEscape(
322 Th_Interp *interp,
323 const char *zInput,
324 int nInput,
325 int *pnEscape
326 ){
327 int i = 2;
328
329 assert(nInput>0);
@@ -344,18 +344,18 @@
344 return TH_OK;
345 }
346
347 /*
348 ** The first part of the string (zInput,nInput) contains a variable
349 ** reference. Set *pnVarname to the number of bytes in the variable
350 ** reference. If there is a parse error, return TH_ERROR and set the
351 ** interpreter result to an error message. Otherwise return TH_OK.
352 */
353 int thNextVarname(
354 Th_Interp *interp,
355 const char *zInput,
356 int nInput,
357 int *pnVarname
358 ){
359 int i;
360
361 assert(nInput>0);
@@ -401,19 +401,19 @@
401 return TH_OK;
402 }
403
404 /*
405 ** The first part of the string (zInput,nInput) contains a command
406 ** enclosed in a "[]" block. Set *pnCommand to the number of bytes in
407 ** the variable reference. If there is a parse error, return TH_ERROR
408 ** and set the interpreter result to an error message. Otherwise return
409 ** TH_OK.
410 */
411 int thNextCommand(
412 Th_Interp *interp,
413 const char *zInput,
414 int nInput,
415 int *pnCommand
416 ){
417 int nBrace = 0;
418 int nSquare = 0;
419 int i;
@@ -438,17 +438,17 @@
438
439 return TH_OK;
440 }
441
442 /*
443 ** Set *pnSpace to the number of whitespace bytes at the start of
444 ** input string (zInput, nInput). Always return TH_OK.
445 */
446 int thNextSpace(
447 Th_Interp *interp,
448 const char *zInput,
449 int nInput,
450 int *pnSpace
451 ){
452 int i;
453 for(i=0; i<nInput && th_isspace(zInput[i]); i++);
454 *pnSpace = i;
@@ -457,21 +457,21 @@
457
458 /*
459 ** The first byte of the string (zInput,nInput) is not white-space.
460 ** Set *pnWord to the number of bytes in the th1 word that starts
461 ** with this byte. If a complete word cannot be parsed or some other
462 ** error occurs, return TH_ERROR and set the interpreter result to
463 ** an error message. Otherwise return TH_OK.
464 **
465 ** If the isCmd argument is non-zero, then an unescaped ";" byte not
466 ** located inside of a block or quoted string is considered to mark
467 ** the end of the word.
468 */
469 static int thNextWord(
470 Th_Interp *interp,
471 const char *zInput,
472 int nInput,
473 int *pnWord,
474 int isCmd
475 ){
476 int iEnd = 0;
477
@@ -531,12 +531,12 @@
531 return thEvalLocal(interp, &zWord[1], nWord-2);
532 }
533
534 /*
535 ** The input string (zWord, nWord) contains a th1 variable reference
536 ** (a '$' byte followed by a variable name). Perform substitution on
537 ** the input string and store the resulting string in the interpreter
538 ** result.
539 */
540 static int thSubstVarname(
541 Th_Interp *interp,
542 const char *zWord,
@@ -572,11 +572,11 @@
572 return Th_GetVar(interp, &zWord[1], nWord-1);
573 }
574
575 /*
576 ** The input string (zWord, nWord) contains a th1 escape sequence.
577 ** Perform substitution on the input string and store the resulting
578 ** string in the interpreter result.
579 */
580 static int thSubstEscape(
581 Th_Interp *interp,
582 const char *zWord,
@@ -608,11 +608,11 @@
608 return TH_OK;
609 }
610
611 /*
612 ** The input string (zWord, nWord) contains a th1 word. Perform
613 ** substitution on the input string and store the resulting
614 ** string in the interpreter result.
615 */
616 static int thSubstWord(
617 Th_Interp *interp,
618 const char *zWord,
@@ -640,20 +640,20 @@
640 int (*xGet)(Th_Interp *, const char*, int, int *) = 0;
641 int (*xSubst)(Th_Interp *, const char*, int) = 0;
642
643 switch( zWord[i] ){
644 case '\\':
645 xGet = thNextEscape; xSubst = thSubstEscape;
646 break;
647 case '[':
648 if( !interp->isListMode ){
649 xGet = thNextCommand; xSubst = thSubstCommand;
650 break;
651 }
652 case '$':
653 if( !interp->isListMode ){
654 xGet = thNextVarname; xSubst = thSubstVarname;
655 break;
656 }
657 default: {
658 thBufferWrite(interp, &output, &zWord[i], 1);
659 continue; /* Go to the next iteration of the for(...) loop */
@@ -685,11 +685,11 @@
685 ** Return true if one of the following is true of the buffer pointed
686 ** to by zInput, length nInput:
687 **
688 ** + It is empty, or
689 ** + It contains nothing but white-space, or
690 ** + It contains no non-white-space characters before the first
691 ** newline character.
692 **
693 ** Otherwise return false.
694 */
695 static int thEndOfLine(const char *zInput, int nInput){
@@ -725,16 +725,16 @@
725 ** // Free all memory allocated by Th_SplitList(). The arrays pointed
726 ** // to by argv and argl are invalidated by this call.
727 ** //
728 ** Th_Free(interp, argv);
729 **
730 */
731 static int thSplitList(
732 Th_Interp *interp, /* Interpreter context */
733 const char *zList, /* Pointer to buffer containing input list */
734 int nList, /* Size of buffer pointed to by zList */
735 char ***pazElem, /* OUT: Array of list elements */
736 int **panElem, /* OUT: Lengths of each list element */
737 int *pnCount /* OUT: Number of list elements */
738 ){
739 int rc = TH_OK;
740
@@ -774,14 +774,14 @@
774 assert((lenbuf.nBuf/sizeof(int))==nCount);
775
776 assert((pazElem && panElem) || (!pazElem && !panElem));
777 if( pazElem && rc==TH_OK ){
778 int i;
779 char *zElem;
780 int *anElem;
781 char **azElem = Th_Malloc(interp,
782 sizeof(char*) * nCount + /* azElem */
783 sizeof(int) * nCount + /* anElem */
784 strbuf.nBuf /* space for list element strings */
785 );
786 anElem = (int *)&azElem[nCount];
787 zElem = (char *)&anElem[nCount];
@@ -795,11 +795,11 @@
795 *panElem = anElem;
796 }
797 if( pnCount ){
798 *pnCount = nCount;
799 }
800
801 finish:
802 thBufferFree(interp, &strbuf);
803 thBufferFree(interp, &lenbuf);
804 return rc;
805 }
@@ -876,18 +876,18 @@
876 if( rc==TH_OK ){
877 Th_Command *p = (Th_Command *)(pEntry->pData);
878 const char **azArg = (const char **)argv;
879 rc = p->xProc(interp, p->pContext, argc, azArg, argl);
880 }
881
882 /* If an error occurred, add this command to the stack trace report. */
883 if( rc==TH_ERROR ){
884 char *zRes;
885 int nRes;
886 char *zStack = 0;
887 int nStack = 0;
888
889 zRes = Th_TakeResult(interp, &nRes);
890 if( TH_OK==Th_GetVar(interp, (char *)"::th_stack_trace", -1) ){
891 zStack = Th_TakeResult(interp, &nStack);
892 }
893 Th_ListAppend(interp, &zStack, &nStack, zFirst, zInput-zFirst);
@@ -912,15 +912,15 @@
912 **
913 ** Argument iFrame is interpreted as follows:
914 **
915 ** * If iFrame is 0, this means the current frame.
916 **
917 ** * If iFrame is negative, then the nth frame up the stack, where
918 ** n is the absolute value of iFrame. A value of -1 means the
919 ** calling procedure.
920 **
921 ** * If iFrame is +ve, then the nth frame from the bottom of the
922 ** stack. An iFrame value of 1 means the toplevel (global) frame.
923 */
924 static Th_Frame *getFrame(Th_Interp *interp, int iFrame){
925 Th_Frame *p = interp->pFrame;
926 int i;
@@ -948,28 +948,28 @@
948
949
950 /*
951 ** Evaluate th1 script (zProgram, nProgram) in the frame identified by
952 ** argument iFrame. Leave either an error message or a result in the
953 ** interpreter result and return a th1 error code (TH_OK, TH_ERROR,
954 ** TH_RETURN, TH_CONTINUE or TH_BREAK).
955 */
956 int Th_Eval(Th_Interp *interp, int iFrame, const char *zProgram, int nProgram){
957 int rc = TH_OK;
958 Th_Frame *pSavedFrame = interp->pFrame;
959
960 /* Set Th_Interp.pFrame to the frame that this script is to be
961 ** evaluated in. The current frame is saved in pSavedFrame and will
962 ** be restored before this function returns.
963 */
964 interp->pFrame = getFrame(interp, iFrame);
965
966 if( !interp->pFrame ){
967 rc = TH_ERROR;
968 }else{
969 int nInput = nProgram;
970
971 if( nInput<0 ){
972 nInput = th_strlen(zProgram);
973 }
974 rc = thEvalLocal(interp, zProgram, nInput);
975 }
@@ -995,13 +995,13 @@
995 ** array key name.
996 */
997 static int thAnalyseVarname(
998 const char *zVarname,
999 int nVarname,
1000 const char **pzOuter, /* OUT: Pointer to scalar/array name */
1001 int *pnOuter, /* OUT: Number of bytes at *pzOuter */
1002 const char **pzInner, /* OUT: Pointer to array key (or null) */
1003 int *pnInner, /* OUT: Number of bytes at *pzInner */
1004 int *pisGlobal /* OUT: Set to true if this is a global ref */
1005 ){
1006 const char *zOuter = zVarname;
1007 int nOuter;
@@ -1044,11 +1044,11 @@
1044 return TH_OK;
1045 }
1046
1047 /*
1048 ** Input string (zVar, nVar) contains a variable name. This function locates
1049 ** the Th_Variable structure associated with the named variable. The
1050 ** variable name may be a global or local scalar or array variable
1051 **
1052 ** If the create argument is non-zero and the named variable does not exist
1053 ** it is created. Otherwise, an error is left in the interpreter result
1054 ** and NULL returned.
@@ -1057,11 +1057,11 @@
1057 ** an error is left in the interpreter result and NULL returned. If
1058 ** arrayok is true an array name is Ok.
1059 */
1060 static Th_Variable *thFindValue(
1061 Th_Interp *interp,
1062 const char *zVar, /* Pointer to variable name */
1063 int nVar, /* Number of bytes at nVar */
1064 int create, /* If true, create the variable if not found */
1065 int arrayok, /* If true, an array is Ok. Otherwise array==error */
1066 int noerror /* If false, set interpreter result to error message */
1067 ){
@@ -1079,11 +1079,11 @@
1079 if( isGlobal ){
1080 while( pFrame->pCaller ) pFrame = pFrame->pCaller;
1081 }
1082
1083 pEntry = Th_HashFind(interp, pFrame->paVar, zOuter, nOuter, create);
1084 assert(pEntry || !create);
1085 if( !pEntry ){
1086 goto no_such_var;
1087 }
1088
1089 pValue = (Th_Variable *)pEntry->pData;
@@ -1135,12 +1135,12 @@
1135 }
1136 return 0;
1137 }
1138
1139 /*
1140 ** String (zVar, nVar) must contain the name of a scalar variable or
1141 ** array member. Look up the variable, store its current value in
1142 ** the interpreter result and return TH_OK.
1143 **
1144 ** If the named variable does not exist, return TH_ERROR and leave
1145 ** an error message in the interpreter result.
1146 */
@@ -1174,12 +1174,12 @@
1174 **
1175 ** If (zVar, nVar) refers to an existing array, TH_ERROR is returned
1176 ** and an error message left in the interpreter result.
1177 */
1178 int Th_SetVar(
1179 Th_Interp *interp,
1180 const char *zVar,
1181 int nVar,
1182 const char *zValue,
1183 int nValue
1184 ){
1185 Th_Variable *pValue;
@@ -1210,13 +1210,13 @@
1210 ** Create a variable link so that accessing variable (zLocal, nLocal) is
1211 ** the same as accessing variable (zLink, nLink) in stack frame iFrame.
1212 */
1213 int Th_LinkVar(
1214 Th_Interp *interp, /* Interpreter */
1215 const char *zLocal, int nLocal, /* Local varname */
1216 int iFrame, /* Stack frame of linked var */
1217 const char *zLink, int nLink /* Linked varname */
1218 ){
1219 Th_Frame *pSavedFrame = interp->pFrame;
1220 Th_Frame *pFrame;
1221 Th_HashEntry *pEntry;
1222 Th_Variable *pValue;
@@ -1253,17 +1253,21 @@
1253 pValue = thFindValue(interp, zVar, nVar, 0, 1, 0);
1254 if( !pValue ){
1255 return TH_ERROR;
1256 }
1257
1258 Th_Free(interp, pValue->zData);
1259 pValue->zData = 0;
 
 
1260 if( pValue->pHash ){
1261 Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp);
1262 Th_HashDelete(interp, pValue->pHash);
1263 pValue->pHash = 0;
1264 }
 
 
1265 return TH_OK;
1266 }
1267
1268 /*
1269 ** Return an allocated buffer containing a copy of string (z, n). The
@@ -1299,11 +1303,11 @@
1299 if( interp ){
1300 char *zRes = 0;
1301 int nRes = 0;
1302
1303 Th_SetVar(interp, (char *)"::th_stack_trace", -1, 0, 0);
1304
1305 Th_StringAppend(interp, &zRes, &nRes, zPre, -1);
1306 if( zRes[nRes-1]=='"' ){
1307 Th_StringAppend(interp, &zRes, &nRes, z, n);
1308 Th_StringAppend(interp, &zRes, &nRes, (const char *)"\"", 1);
1309 }else{
@@ -1381,12 +1385,12 @@
1381 return (char *)Th_Malloc(pInterp, 1);
1382 }
1383 }
1384
1385
1386 /*
1387 ** Wrappers around the supplied malloc() and free()
1388 */
1389 void *Th_Malloc(Th_Interp *pInterp, int nByte){
1390 void *p = pInterp->pVtab->xMalloc(nByte);
1391 if( p ){
1392 memset(p, 0, nByte);
@@ -1398,16 +1402,16 @@
1398 pInterp->pVtab->xFree(z);
1399 }
1400 }
1401
1402 /*
1403 ** Install a new th1 command.
1404 **
1405 ** If a command of the same name already exists, it is deleted automatically.
1406 */
1407 int Th_CreateCommand(
1408 Th_Interp *interp,
1409 const char *zName, /* New command name */
1410 Th_CommandProc xProc, /* Command callback proc */
1411 void *pContext, /* Value to pass as second arg to xProc */
1412 void (*xDel)(Th_Interp *, void *) /* Command destructor callback */
1413 ){
@@ -1425,27 +1429,27 @@
1425 }
1426 pCommand->xProc = xProc;
1427 pCommand->pContext = pContext;
1428 pCommand->xDel = xDel;
1429 pEntry->pData = (void *)pCommand;
1430
1431 return TH_OK;
1432 }
1433
1434 /*
1435 ** Rename the existing command (zName, nName) to (zNew, nNew). If nNew is 0,
1436 ** the command is deleted instead of renamed.
1437 **
1438 ** If successful, TH_OK is returned. If command zName does not exist, or
1439 ** if command zNew already exists, an error message is left in the
1440 ** interpreter result and TH_ERROR is returned.
1441 */
1442 int Th_RenameCommand(
1443 Th_Interp *interp,
1444 const char *zName, /* Existing command name */
1445 int nName, /* Number of bytes at zName */
1446 const char *zNew, /* New command name */
1447 int nNew /* Number of bytes at zNew */
1448 ){
1449 Th_HashEntry *pEntry;
1450 Th_HashEntry *pNewEntry;
1451
@@ -1499,11 +1503,11 @@
1499 ** If an error occurs (if (zList, nList) is not a valid list) an error
1500 ** message is left in the interpreter result and TH_ERROR returned.
1501 **
1502 ** If successful, *pnCount is set to the number of elements in the list.
1503 ** panElem is set to point at an array of *pnCount integers - the lengths
1504 ** of the element values. *pazElem is set to point at an array of
1505 ** pointers to buffers containing the array element's data.
1506 **
1507 ** To free the arrays allocated at *pazElem and *panElem, the caller
1508 ** should call Th_Free() on *pazElem only. Exactly one such call to
1509 ** Th_Free() must be made per call to Th_SplitList().
@@ -1525,13 +1529,13 @@
1525 ** Th_Free(interp, azElem);
1526 **
1527 */
1528 int Th_SplitList(
1529 Th_Interp *interp,
1530 const char *zList, /* Pointer to buffer containing list */
1531 int nList, /* Number of bytes at zList */
1532 char ***pazElem, /* OUT: Array of pointers to element data */
1533 int **panElem, /* OUT: Array of element data lengths */
1534 int *pnCount /* OUT: Number of elements in list */
1535 ){
1536 int rc;
1537 interp->isListMode = 1;
@@ -1542,16 +1546,16 @@
1542 }
1543 return rc;
1544 }
1545
1546 /*
1547 ** Append a new element to an existing th1 list. The element to append
1548 ** to the list is (zElem, nElem).
1549 **
1550 ** A pointer to the existing list must be stored at *pzList when this
1551 ** function is called. The length must be stored in *pnList. The value
1552 ** of *pzList must either be NULL (in which case *pnList must be 0), or
1553 ** a pointer to memory obtained from Th_Malloc().
1554 **
1555 ** This function calls Th_Free() to free the buffer at *pzList and sets
1556 ** *pzList to point to a new buffer containing the new list value. *pnList
1557 ** is similarly updated before returning. The return value is always TH_OK.
@@ -1568,13 +1572,13 @@
1568 ** Th_Free(interp, zList);
1569 **
1570 */
1571 int Th_ListAppend(
1572 Th_Interp *interp, /* Interpreter context */
1573 char **pzList, /* IN/OUT: Ptr to ptr to list */
1574 int *pnList, /* IN/OUT: Current length of *pzList */
1575 const char *zElem, /* Data to append */
1576 int nElem /* Length of nElem */
1577 ){
1578 Buffer output;
1579 int i;
1580
@@ -1623,13 +1627,13 @@
1623 ** Append a new element to an existing th1 string. This function uses
1624 ** the same interface as the Th_ListAppend() function.
1625 */
1626 int Th_StringAppend(
1627 Th_Interp *interp, /* Interpreter context */
1628 char **pzStr, /* IN/OUT: Ptr to ptr to list */
1629 int *pnStr, /* IN/OUT: Current length of *pzStr */
1630 const char *zElem, /* Data to append */
1631 int nElem /* Length of nElem */
1632 ){
1633 char *zNew;
1634 int nNew;
1635
@@ -1647,11 +1651,11 @@
1647 *pnStr = nNew;
1648
1649 return TH_OK;
1650 }
1651
1652 /*
1653 ** Delete an interpreter.
1654 */
1655 void Th_DeleteInterp(Th_Interp *interp){
1656 assert(interp->pFrame);
1657 assert(0==interp->pFrame->pCaller);
@@ -1668,11 +1672,11 @@
1668
1669 /* Delete the interpreter structure itself. */
1670 Th_Free(interp, (void *)interp);
1671 }
1672
1673 /*
1674 ** Create a new interpreter.
1675 */
1676 Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){
1677 Th_Interp *p;
1678
@@ -1702,11 +1706,11 @@
1702 Operator *pOp;
1703 Expr *pParent;
1704 Expr *pLeft;
1705 Expr *pRight;
1706
1707 char *zValue; /* Pointer to literal value */
1708 int nValue; /* Length of literal value buffer */
1709 };
1710
1711 /* Unary operators */
1712 #define OP_UNARY_MINUS 2
@@ -1758,11 +1762,11 @@
1758 {"+", OP_UNARY_PLUS, 1, ARG_NUMBER},
1759 {"~", OP_BITWISE_NOT, 1, ARG_INTEGER},
1760 {"!", OP_LOGICAL_NOT, 1, ARG_INTEGER},
1761
1762 /* Binary operators. It is important to the parsing in Th_Expr() that
1763 * the two-character symbols ("==") appear before the one-character
1764 * ones ("="). And that the priorities of all binary operators are
1765 * integers between 2 and 12.
1766 */
1767 {"<<", OP_LEFTSHIFT, 4, ARG_INTEGER},
1768 {">>", OP_RIGHTSHIFT, 4, ARG_INTEGER},
@@ -1789,16 +1793,16 @@
1789 {0,0,0,0}
1790 };
1791
1792 /*
1793 ** The first part of the string (zInput,nInput) contains a number.
1794 ** Set *pnVarname to the number of bytes in the numeric string.
1795 */
1796 static int thNextNumber(
1797 Th_Interp *interp,
1798 const char *zInput,
1799 int nInput,
1800 int *pnLiteral
1801 ){
1802 int i;
1803 int seenDot = 0;
1804 for(i=0; i<nInput; i++){
@@ -1864,11 +1868,11 @@
1864 if( eArgType==ARG_NUMBER ){
1865 if( (zLeft==0 || TH_OK==Th_ToInt(0, zLeft, nLeft, &iLeft))
1866 && (zRight==0 || TH_OK==Th_ToInt(0, zRight, nRight, &iRight))
1867 ){
1868 eArgType = ARG_INTEGER;
1869 }else if(
1870 (zLeft && TH_OK!=Th_ToDouble(interp, zLeft, nLeft, &fLeft)) ||
1871 (zRight && TH_OK!=Th_ToDouble(interp, zRight, nRight, &fRight))
1872 ){
1873 /* A type error. */
1874 rc = TH_ERROR;
@@ -1876,11 +1880,11 @@
1876 }else if( eArgType==ARG_INTEGER ){
1877 rc = Th_ToInt(interp, zLeft, nLeft, &iLeft);
1878 if( rc==TH_OK && zRight ){
1879 rc = Th_ToInt(interp, zRight, nRight, &iRight);
1880 }
1881 }
1882 }
1883
1884 if( rc==TH_OK && eArgType==ARG_INTEGER ){
1885 int iRes = 0;
1886 switch( pExpr->pOp->eOp ) {
@@ -1978,11 +1982,11 @@
1978 #define ISTERM(x) (apToken[x] && (!apToken[x]->pOp || apToken[x]->pLeft))
1979
1980 for(jj=0; jj<nToken; jj++){
1981 if( apToken[jj]->pOp && apToken[jj]->pOp->eOp==OP_OPEN_BRACKET ){
1982 int nNest = 1;
1983 int iLeft = jj;
1984
1985 for(jj++; jj<nToken; jj++){
1986 Operator *pOp = apToken[jj]->pOp;
1987 if( pOp && pOp->eOp==OP_OPEN_BRACKET ) nNest++;
1988 if( pOp && pOp->eOp==OP_CLOSE_BRACKET ) nNest--;
@@ -2052,11 +2056,11 @@
2052 /*
2053 ** Parse a string containing a TH expression to a list of tokens.
2054 */
2055 static int exprParse(
2056 Th_Interp *interp, /* Interpreter to leave error message in */
2057 const char *zExpr, /* Pointer to input string */
2058 int nExpr, /* Number of bytes at zExpr */
2059 Expr ***papToken, /* OUT: Array of tokens. */
2060 int *pnToken /* OUT: Size of token array */
2061 ){
2062 int i;
@@ -2127,11 +2131,11 @@
2127 memcpy(pNew->zValue, z, pNew->nValue);
2128 i += pNew->nValue;
2129 }
2130 if( (nToken%16)==0 ){
2131 /* Grow the apToken array. */
2132 Expr **apTokenOld = apToken;
2133 apToken = Th_Malloc(interp, sizeof(Expr *)*(nToken+16));
2134 memcpy(apToken, apTokenOld, sizeof(Expr *)*nToken);
2135 }
2136
2137 /* Put the new token at the end of the apToken array */
@@ -2152,11 +2156,11 @@
2152 /*
2153 ** Evaluate the string (zExpr, nExpr) as a Th expression. Store
2154 ** the result in the interpreter interp and return TH_OK if
2155 ** successful. If an error occurs, store an error message in
2156 ** the interpreter result and return an error code.
2157 */
2158 int Th_Expr(Th_Interp *interp, const char *zExpr, int nExpr){
2159 int rc; /* Return Code */
2160 int i; /* Loop counter */
2161
2162 int nToken = 0;
@@ -2169,11 +2173,11 @@
2169 /* Parse the expression to a list of tokens. */
2170 rc = exprParse(interp, zExpr, nExpr, &apToken, &nToken);
2171
2172 /* If the parsing was successful, create an expression tree from
2173 ** the parsed list of tokens. If successful, apToken[0] is set
2174 ** to point to the root of the expression tree.
2175 */
2176 if( rc==TH_OK ){
2177 rc = exprMakeTree(interp, apToken, nToken);
2178 }
2179
@@ -2210,11 +2214,11 @@
2210 ** the callback function xCallback for each entry. The second argument
2211 ** passed to xCallback is a copy of the fourth argument passed to this
2212 ** function.
2213 */
2214 void Th_HashIterate(
2215 Th_Interp *interp,
2216 Th_Hash *pHash,
2217 void (*xCallback)(Th_HashEntry *pEntry, void *pContext),
2218 void *pContext
2219 ){
2220 int i;
@@ -2244,14 +2248,14 @@
2244 Th_Free(interp, pHash);
2245 }
2246 }
2247
2248 /*
2249 ** This function is used to insert or delete hash table items, or to
2250 ** query a hash table for an existing item.
2251 **
2252 ** If parameter op is less than zero, then the hash-table element
2253 ** identified by (zKey, nKey) is removed from the hash-table if it
2254 ** exists. NULL is returned.
2255 **
2256 ** Otherwise, if the hash-table contains an item with key (zKey, nKey),
2257 ** a pointer to the associated Th_HashEntry is returned. If parameter
@@ -2258,11 +2262,11 @@
2258 ** op is greater than zero, then a new entry is added if one cannot
2259 ** be found. If op is zero, then NULL is returned if the item is
2260 ** not already present in the hash-table.
2261 */
2262 Th_HashEntry *Th_HashFind(
2263 Th_Interp *interp,
2264 Th_Hash *pHash,
2265 const char *zKey,
2266 int nKey,
2267 int op /* -ve = delete, 0 = find, +ve = insert */
2268 ){
@@ -2326,11 +2330,11 @@
2326 ** '\f' 0x0C
2327 ** '\r' 0x0D
2328 **
2329 ** Whitespace characters have the 0x01 flag set. Decimal digits have the
2330 ** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
2331 ** Alphabet characters have the 0x8 bit set.
2332 **
2333 ** The special list characters have the 0x10 flag set
2334 **
2335 ** { } [ ] \ ; ' "
2336 **
@@ -2477,14 +2481,14 @@
2477 return z - zBegin;
2478 }
2479
2480 /*
2481 ** Try to convert the string passed as arguments (z, n) to an integer.
2482 ** If successful, store the result in *piOut and return TH_OK.
2483 **
2484 ** If the string cannot be converted to an integer, return TH_ERROR.
2485 ** If the interp argument is not NULL, leave an error message in the
2486 ** interpreter result too.
2487 */
2488 int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
2489 int i = 0;
2490 int iOut = 0;
@@ -2512,20 +2516,20 @@
2512 return TH_OK;
2513 }
2514
2515 /*
2516 ** Try to convert the string passed as arguments (z, n) to a double.
2517 ** If successful, store the result in *pfOut and return TH_OK.
2518 **
2519 ** If the string cannot be converted to a double, return TH_ERROR.
2520 ** If the interp argument is not NULL, leave an error message in the
2521 ** interpreter result too.
2522 */
2523 int Th_ToDouble(
2524 Th_Interp *interp,
2525 const char *z,
2526 int n,
2527 double *pfOut
2528 ){
2529 if( !sqlite3IsNumber((const char *)z, 0) ){
2530 Th_ErrorMessage(interp, "expected number, got: \"", z, n);
2531 return TH_ERROR;
@@ -2566,33 +2570,33 @@
2566 ** the double fVal and return TH_OK.
2567 */
2568 int Th_SetResultDouble(Th_Interp *interp, double fVal){
2569 int i; /* Iterator variable */
2570 double v = fVal; /* Input value */
2571 char zBuf[128]; /* Output buffer */
2572 char *z = zBuf; /* Output cursor */
2573 int iDot = 0; /* Digit after which to place decimal point */
2574 int iExp = 0; /* Exponent (NN in eNN) */
2575 const char *zExp; /* String representation of iExp */
2576
2577 /* Precision: */
2578 #define INSIGNIFICANT 0.000000000001
2579 #define ROUNDER 0.0000000000005
2580 double insignificant = INSIGNIFICANT;
2581
2582 /* If the real value is negative, write a '-' character to the
2583 * output and transform v to the corresponding positive number.
2584 */
2585 if( v<0.0 ){
2586 *z++ = '-';
2587 v *= -1.0;
2588 }
2589
2590 /* Normalize v to a value between 1.0 and 10.0. Integer
2591 * variable iExp is set to the exponent. i.e the original
2592 * value is (v * 10^iExp) (or the negative thereof).
2593 */
2594 if( v>0.0 ){
2595 while( (v+ROUNDER)>=10.0 ) { iExp++; v *= 0.1; }
2596 while( (v+ROUNDER)<1.0 ) { iExp--; v *= 10.0; }
2597 }
2598 v += ROUNDER;
2599
--- src/th.c
+++ src/th.c
@@ -1,8 +1,8 @@
1
2 /*
3 ** The implementation of the TH core. This file contains the parser, and
4 ** the implementation of the interface in th.h.
5 */
6
7 #include "config.h"
8 #include "th.h"
@@ -16,11 +16,11 @@
16 /*
17 ** Interpreter structure.
18 */
19 struct Th_Interp {
20 Th_Vtab *pVtab; /* Copy of the argument passed to Th_CreateInterp() */
21 char *zResult; /* Current interpreter result (Th_Malloc()ed) */
22 int nResult; /* number of bytes in zResult */
23 Th_Hash *paCmd; /* Table of registered commands */
24 Th_Frame *pFrame; /* Current execution frame */
25 int isListMode; /* True if thSplitList() should operate in "list" mode */
26 };
@@ -42,25 +42,25 @@
42 ** are stored in the Th_Frame.paVar hash table member of the associated
43 ** stack frame object.
44 **
45 ** When an interpreter is created, a single Th_Frame structure is also
46 ** allocated - the global variable scope. Th_Interp.pFrame (the current
47 ** interpreter frame) is initialised to point to this Th_Frame. It is
48 ** not deleted for the lifetime of the interpreter (because the global
49 ** frame never goes out of scope).
50 **
51 ** New stack frames are created by the Th_InFrame() function. Before
52 ** invoking its callback function, Th_InFrame() allocates a new Th_Frame
53 ** structure with pCaller set to the current frame (Th_Interp.pFrame),
54 ** and sets the current frame to the new frame object. After the callback
55 ** has been invoked, the allocated Th_Frame is deleted and the value
56 ** of the current frame pointer restored.
57 **
58 ** By default, the Th_SetVar(), Th_UnsetVar() and Th_GetVar() functions
59 ** access variable values in the current frame. If they need to access
60 ** the global frame, they do so by traversing the pCaller pointer list.
61 ** Likewise, the Th_LinkVar() function uses the pCaller pointers to
62 ** link to variables located in the global or other stack frames.
63 */
64 struct Th_Frame {
65 Th_Hash *paVar; /* Variables defined in this scope */
66 Th_Frame *pCaller; /* Calling frame */
@@ -84,11 +84,11 @@
84 ** value.
85 */
86 struct Th_Variable {
87 int nRef; /* Number of references to this structure */
88 int nData; /* Number of bytes at Th_Variable.zData */
89 char *zData; /* Data for scalar variables */
90 Th_Hash *pHash; /* Data for array variables */
91 };
92
93 /*
94 ** Hash table API:
@@ -110,19 +110,19 @@
110 static void thFreeVariable(Th_HashEntry*, void*);
111 static void thFreeCommand(Th_HashEntry*, void*);
112
113 /*
114 ** The following are used by both the expression and language parsers.
115 ** Given that the start of the input string (z, n) is a language
116 ** construct of the relevant type (a command enclosed in [], an escape
117 ** sequence etc.), these functions determine the number of bytes
118 ** of the input consumed by the construct. For example:
119 **
120 ** int nByte;
121 ** thNextCommand(interp, "[expr $a+1] $nIter", 18, &nByte);
122 **
123 ** results in variable nByte being set to 11. Or,
124 **
125 ** thNextVarname(interp, "$a+1", 4, &nByte);
126 **
127 ** results in nByte being set to 2.
128 */
@@ -132,24 +132,24 @@
132 static int thNextNumber (Th_Interp*, const char *z, int n, int *pN);
133 static int thNextSpace (Th_Interp*, const char *z, int n, int *pN);
134
135 /*
136 ** Given that the input string (z, n) contains a language construct of
137 ** the relevant type (a command enclosed in [], an escape sequence
138 ** like "\xFF" or a variable reference like "${varname}", perform
139 ** substitution on the string and store the resulting string in
140 ** the interpreter result.
141 */
142 static int thSubstCommand(Th_Interp*, const char *z, int n);
143 static int thSubstEscape (Th_Interp*, const char *z, int n);
144 static int thSubstVarname(Th_Interp*, const char *z, int n);
145
146 /*
147 ** Given that there is a th1 word located at the start of the input
148 ** string (z, n), determine the length in bytes of that word. If the
149 ** isCmd argument is non-zero, then an unescaped ";" byte not
150 ** located inside of a block or quoted string is considered to mark
151 ** the end of the word.
152 */
153 static int thNextWord(Th_Interp*, const char *z, int n, int *pN, int isCmd);
154
155 /*
@@ -176,13 +176,13 @@
176 ** Append nAdd bytes of content copied from zAdd to the end of buffer
177 ** pBuffer. If there is not enough space currently allocated, resize
178 ** the allocation to make space.
179 */
180 static int thBufferWrite(
181 Th_Interp *interp,
182 Buffer *pBuffer,
183 const char *zAdd,
184 int nAdd
185 ){
186 int nReq;
187
188 if( nAdd<0 ){
@@ -311,19 +311,19 @@
311 Th_HashDelete(interp, pFrame->paVar);
312 interp->pFrame = pFrame->pCaller;
313 }
314
315 /*
316 ** The first part of the string (zInput,nInput) contains an escape
317 ** sequence. Set *pnEscape to the number of bytes in the escape sequence.
318 ** If there is a parse error, return TH_ERROR and set the interpreter
319 ** result to an error message. Otherwise return TH_OK.
320 */
321 static int thNextEscape(
322 Th_Interp *interp,
323 const char *zInput,
324 int nInput,
325 int *pnEscape
326 ){
327 int i = 2;
328
329 assert(nInput>0);
@@ -344,18 +344,18 @@
344 return TH_OK;
345 }
346
347 /*
348 ** The first part of the string (zInput,nInput) contains a variable
349 ** reference. Set *pnVarname to the number of bytes in the variable
350 ** reference. If there is a parse error, return TH_ERROR and set the
351 ** interpreter result to an error message. Otherwise return TH_OK.
352 */
353 int thNextVarname(
354 Th_Interp *interp,
355 const char *zInput,
356 int nInput,
357 int *pnVarname
358 ){
359 int i;
360
361 assert(nInput>0);
@@ -401,19 +401,19 @@
401 return TH_OK;
402 }
403
404 /*
405 ** The first part of the string (zInput,nInput) contains a command
406 ** enclosed in a "[]" block. Set *pnCommand to the number of bytes in
407 ** the variable reference. If there is a parse error, return TH_ERROR
408 ** and set the interpreter result to an error message. Otherwise return
409 ** TH_OK.
410 */
411 int thNextCommand(
412 Th_Interp *interp,
413 const char *zInput,
414 int nInput,
415 int *pnCommand
416 ){
417 int nBrace = 0;
418 int nSquare = 0;
419 int i;
@@ -438,17 +438,17 @@
438
439 return TH_OK;
440 }
441
442 /*
443 ** Set *pnSpace to the number of whitespace bytes at the start of
444 ** input string (zInput, nInput). Always return TH_OK.
445 */
446 int thNextSpace(
447 Th_Interp *interp,
448 const char *zInput,
449 int nInput,
450 int *pnSpace
451 ){
452 int i;
453 for(i=0; i<nInput && th_isspace(zInput[i]); i++);
454 *pnSpace = i;
@@ -457,21 +457,21 @@
457
458 /*
459 ** The first byte of the string (zInput,nInput) is not white-space.
460 ** Set *pnWord to the number of bytes in the th1 word that starts
461 ** with this byte. If a complete word cannot be parsed or some other
462 ** error occurs, return TH_ERROR and set the interpreter result to
463 ** an error message. Otherwise return TH_OK.
464 **
465 ** If the isCmd argument is non-zero, then an unescaped ";" byte not
466 ** located inside of a block or quoted string is considered to mark
467 ** the end of the word.
468 */
469 static int thNextWord(
470 Th_Interp *interp,
471 const char *zInput,
472 int nInput,
473 int *pnWord,
474 int isCmd
475 ){
476 int iEnd = 0;
477
@@ -531,12 +531,12 @@
531 return thEvalLocal(interp, &zWord[1], nWord-2);
532 }
533
534 /*
535 ** The input string (zWord, nWord) contains a th1 variable reference
536 ** (a '$' byte followed by a variable name). Perform substitution on
537 ** the input string and store the resulting string in the interpreter
538 ** result.
539 */
540 static int thSubstVarname(
541 Th_Interp *interp,
542 const char *zWord,
@@ -572,11 +572,11 @@
572 return Th_GetVar(interp, &zWord[1], nWord-1);
573 }
574
575 /*
576 ** The input string (zWord, nWord) contains a th1 escape sequence.
577 ** Perform substitution on the input string and store the resulting
578 ** string in the interpreter result.
579 */
580 static int thSubstEscape(
581 Th_Interp *interp,
582 const char *zWord,
@@ -608,11 +608,11 @@
608 return TH_OK;
609 }
610
611 /*
612 ** The input string (zWord, nWord) contains a th1 word. Perform
613 ** substitution on the input string and store the resulting
614 ** string in the interpreter result.
615 */
616 static int thSubstWord(
617 Th_Interp *interp,
618 const char *zWord,
@@ -640,20 +640,20 @@
640 int (*xGet)(Th_Interp *, const char*, int, int *) = 0;
641 int (*xSubst)(Th_Interp *, const char*, int) = 0;
642
643 switch( zWord[i] ){
644 case '\\':
645 xGet = thNextEscape; xSubst = thSubstEscape;
646 break;
647 case '[':
648 if( !interp->isListMode ){
649 xGet = thNextCommand; xSubst = thSubstCommand;
650 break;
651 }
652 case '$':
653 if( !interp->isListMode ){
654 xGet = thNextVarname; xSubst = thSubstVarname;
655 break;
656 }
657 default: {
658 thBufferWrite(interp, &output, &zWord[i], 1);
659 continue; /* Go to the next iteration of the for(...) loop */
@@ -685,11 +685,11 @@
685 ** Return true if one of the following is true of the buffer pointed
686 ** to by zInput, length nInput:
687 **
688 ** + It is empty, or
689 ** + It contains nothing but white-space, or
690 ** + It contains no non-white-space characters before the first
691 ** newline character.
692 **
693 ** Otherwise return false.
694 */
695 static int thEndOfLine(const char *zInput, int nInput){
@@ -725,16 +725,16 @@
725 ** // Free all memory allocated by Th_SplitList(). The arrays pointed
726 ** // to by argv and argl are invalidated by this call.
727 ** //
728 ** Th_Free(interp, argv);
729 **
730 */
731 static int thSplitList(
732 Th_Interp *interp, /* Interpreter context */
733 const char *zList, /* Pointer to buffer containing input list */
734 int nList, /* Size of buffer pointed to by zList */
735 char ***pazElem, /* OUT: Array of list elements */
736 int **panElem, /* OUT: Lengths of each list element */
737 int *pnCount /* OUT: Number of list elements */
738 ){
739 int rc = TH_OK;
740
@@ -774,14 +774,14 @@
774 assert((lenbuf.nBuf/sizeof(int))==nCount);
775
776 assert((pazElem && panElem) || (!pazElem && !panElem));
777 if( pazElem && rc==TH_OK ){
778 int i;
779 char *zElem;
780 int *anElem;
781 char **azElem = Th_Malloc(interp,
782 sizeof(char*) * nCount + /* azElem */
783 sizeof(int) * nCount + /* anElem */
784 strbuf.nBuf /* space for list element strings */
785 );
786 anElem = (int *)&azElem[nCount];
787 zElem = (char *)&anElem[nCount];
@@ -795,11 +795,11 @@
795 *panElem = anElem;
796 }
797 if( pnCount ){
798 *pnCount = nCount;
799 }
800
801 finish:
802 thBufferFree(interp, &strbuf);
803 thBufferFree(interp, &lenbuf);
804 return rc;
805 }
@@ -876,18 +876,18 @@
876 if( rc==TH_OK ){
877 Th_Command *p = (Th_Command *)(pEntry->pData);
878 const char **azArg = (const char **)argv;
879 rc = p->xProc(interp, p->pContext, argc, azArg, argl);
880 }
881
882 /* If an error occurred, add this command to the stack trace report. */
883 if( rc==TH_ERROR ){
884 char *zRes;
885 int nRes;
886 char *zStack = 0;
887 int nStack = 0;
888
889 zRes = Th_TakeResult(interp, &nRes);
890 if( TH_OK==Th_GetVar(interp, (char *)"::th_stack_trace", -1) ){
891 zStack = Th_TakeResult(interp, &nStack);
892 }
893 Th_ListAppend(interp, &zStack, &nStack, zFirst, zInput-zFirst);
@@ -912,15 +912,15 @@
912 **
913 ** Argument iFrame is interpreted as follows:
914 **
915 ** * If iFrame is 0, this means the current frame.
916 **
917 ** * If iFrame is negative, then the nth frame up the stack, where
918 ** n is the absolute value of iFrame. A value of -1 means the
919 ** calling procedure.
920 **
921 ** * If iFrame is +ve, then the nth frame from the bottom of the
922 ** stack. An iFrame value of 1 means the toplevel (global) frame.
923 */
924 static Th_Frame *getFrame(Th_Interp *interp, int iFrame){
925 Th_Frame *p = interp->pFrame;
926 int i;
@@ -948,28 +948,28 @@
948
949
950 /*
951 ** Evaluate th1 script (zProgram, nProgram) in the frame identified by
952 ** argument iFrame. Leave either an error message or a result in the
953 ** interpreter result and return a th1 error code (TH_OK, TH_ERROR,
954 ** TH_RETURN, TH_CONTINUE or TH_BREAK).
955 */
956 int Th_Eval(Th_Interp *interp, int iFrame, const char *zProgram, int nProgram){
957 int rc = TH_OK;
958 Th_Frame *pSavedFrame = interp->pFrame;
959
960 /* Set Th_Interp.pFrame to the frame that this script is to be
961 ** evaluated in. The current frame is saved in pSavedFrame and will
962 ** be restored before this function returns.
963 */
964 interp->pFrame = getFrame(interp, iFrame);
965
966 if( !interp->pFrame ){
967 rc = TH_ERROR;
968 }else{
969 int nInput = nProgram;
970
971 if( nInput<0 ){
972 nInput = th_strlen(zProgram);
973 }
974 rc = thEvalLocal(interp, zProgram, nInput);
975 }
@@ -995,13 +995,13 @@
995 ** array key name.
996 */
997 static int thAnalyseVarname(
998 const char *zVarname,
999 int nVarname,
1000 const char **pzOuter, /* OUT: Pointer to scalar/array name */
1001 int *pnOuter, /* OUT: Number of bytes at *pzOuter */
1002 const char **pzInner, /* OUT: Pointer to array key (or null) */
1003 int *pnInner, /* OUT: Number of bytes at *pzInner */
1004 int *pisGlobal /* OUT: Set to true if this is a global ref */
1005 ){
1006 const char *zOuter = zVarname;
1007 int nOuter;
@@ -1044,11 +1044,11 @@
1044 return TH_OK;
1045 }
1046
1047 /*
1048 ** Input string (zVar, nVar) contains a variable name. This function locates
1049 ** the Th_Variable structure associated with the named variable. The
1050 ** variable name may be a global or local scalar or array variable
1051 **
1052 ** If the create argument is non-zero and the named variable does not exist
1053 ** it is created. Otherwise, an error is left in the interpreter result
1054 ** and NULL returned.
@@ -1057,11 +1057,11 @@
1057 ** an error is left in the interpreter result and NULL returned. If
1058 ** arrayok is true an array name is Ok.
1059 */
1060 static Th_Variable *thFindValue(
1061 Th_Interp *interp,
1062 const char *zVar, /* Pointer to variable name */
1063 int nVar, /* Number of bytes at nVar */
1064 int create, /* If true, create the variable if not found */
1065 int arrayok, /* If true, an array is Ok. Otherwise array==error */
1066 int noerror /* If false, set interpreter result to error message */
1067 ){
@@ -1079,11 +1079,11 @@
1079 if( isGlobal ){
1080 while( pFrame->pCaller ) pFrame = pFrame->pCaller;
1081 }
1082
1083 pEntry = Th_HashFind(interp, pFrame->paVar, zOuter, nOuter, create);
1084 assert(pEntry || create<=0);
1085 if( !pEntry ){
1086 goto no_such_var;
1087 }
1088
1089 pValue = (Th_Variable *)pEntry->pData;
@@ -1135,12 +1135,12 @@
1135 }
1136 return 0;
1137 }
1138
1139 /*
1140 ** String (zVar, nVar) must contain the name of a scalar variable or
1141 ** array member. Look up the variable, store its current value in
1142 ** the interpreter result and return TH_OK.
1143 **
1144 ** If the named variable does not exist, return TH_ERROR and leave
1145 ** an error message in the interpreter result.
1146 */
@@ -1174,12 +1174,12 @@
1174 **
1175 ** If (zVar, nVar) refers to an existing array, TH_ERROR is returned
1176 ** and an error message left in the interpreter result.
1177 */
1178 int Th_SetVar(
1179 Th_Interp *interp,
1180 const char *zVar,
1181 int nVar,
1182 const char *zValue,
1183 int nValue
1184 ){
1185 Th_Variable *pValue;
@@ -1210,13 +1210,13 @@
1210 ** Create a variable link so that accessing variable (zLocal, nLocal) is
1211 ** the same as accessing variable (zLink, nLink) in stack frame iFrame.
1212 */
1213 int Th_LinkVar(
1214 Th_Interp *interp, /* Interpreter */
1215 const char *zLocal, int nLocal, /* Local varname */
1216 int iFrame, /* Stack frame of linked var */
1217 const char *zLink, int nLink /* Linked varname */
1218 ){
1219 Th_Frame *pSavedFrame = interp->pFrame;
1220 Th_Frame *pFrame;
1221 Th_HashEntry *pEntry;
1222 Th_Variable *pValue;
@@ -1253,17 +1253,21 @@
1253 pValue = thFindValue(interp, zVar, nVar, 0, 1, 0);
1254 if( !pValue ){
1255 return TH_ERROR;
1256 }
1257
1258 if( pValue->zData ){
1259 Th_Free(interp, pValue->zData);
1260 pValue->zData = 0;
1261 }
1262 if( pValue->pHash ){
1263 Th_HashIterate(interp, pValue->pHash, thFreeVariable, (void *)interp);
1264 Th_HashDelete(interp, pValue->pHash);
1265 pValue->pHash = 0;
1266 }
1267
1268 thFindValue(interp, zVar, nVar, -1, 1, 1); /* Finally, delete from frame */
1269 return TH_OK;
1270 }
1271
1272 /*
1273 ** Return an allocated buffer containing a copy of string (z, n). The
@@ -1299,11 +1303,11 @@
1303 if( interp ){
1304 char *zRes = 0;
1305 int nRes = 0;
1306
1307 Th_SetVar(interp, (char *)"::th_stack_trace", -1, 0, 0);
1308
1309 Th_StringAppend(interp, &zRes, &nRes, zPre, -1);
1310 if( zRes[nRes-1]=='"' ){
1311 Th_StringAppend(interp, &zRes, &nRes, z, n);
1312 Th_StringAppend(interp, &zRes, &nRes, (const char *)"\"", 1);
1313 }else{
@@ -1381,12 +1385,12 @@
1385 return (char *)Th_Malloc(pInterp, 1);
1386 }
1387 }
1388
1389
1390 /*
1391 ** Wrappers around the supplied malloc() and free()
1392 */
1393 void *Th_Malloc(Th_Interp *pInterp, int nByte){
1394 void *p = pInterp->pVtab->xMalloc(nByte);
1395 if( p ){
1396 memset(p, 0, nByte);
@@ -1398,16 +1402,16 @@
1402 pInterp->pVtab->xFree(z);
1403 }
1404 }
1405
1406 /*
1407 ** Install a new th1 command.
1408 **
1409 ** If a command of the same name already exists, it is deleted automatically.
1410 */
1411 int Th_CreateCommand(
1412 Th_Interp *interp,
1413 const char *zName, /* New command name */
1414 Th_CommandProc xProc, /* Command callback proc */
1415 void *pContext, /* Value to pass as second arg to xProc */
1416 void (*xDel)(Th_Interp *, void *) /* Command destructor callback */
1417 ){
@@ -1425,27 +1429,27 @@
1429 }
1430 pCommand->xProc = xProc;
1431 pCommand->pContext = pContext;
1432 pCommand->xDel = xDel;
1433 pEntry->pData = (void *)pCommand;
1434
1435 return TH_OK;
1436 }
1437
1438 /*
1439 ** Rename the existing command (zName, nName) to (zNew, nNew). If nNew is 0,
1440 ** the command is deleted instead of renamed.
1441 **
1442 ** If successful, TH_OK is returned. If command zName does not exist, or
1443 ** if command zNew already exists, an error message is left in the
1444 ** interpreter result and TH_ERROR is returned.
1445 */
1446 int Th_RenameCommand(
1447 Th_Interp *interp,
1448 const char *zName, /* Existing command name */
1449 int nName, /* Number of bytes at zName */
1450 const char *zNew, /* New command name */
1451 int nNew /* Number of bytes at zNew */
1452 ){
1453 Th_HashEntry *pEntry;
1454 Th_HashEntry *pNewEntry;
1455
@@ -1499,11 +1503,11 @@
1503 ** If an error occurs (if (zList, nList) is not a valid list) an error
1504 ** message is left in the interpreter result and TH_ERROR returned.
1505 **
1506 ** If successful, *pnCount is set to the number of elements in the list.
1507 ** panElem is set to point at an array of *pnCount integers - the lengths
1508 ** of the element values. *pazElem is set to point at an array of
1509 ** pointers to buffers containing the array element's data.
1510 **
1511 ** To free the arrays allocated at *pazElem and *panElem, the caller
1512 ** should call Th_Free() on *pazElem only. Exactly one such call to
1513 ** Th_Free() must be made per call to Th_SplitList().
@@ -1525,13 +1529,13 @@
1529 ** Th_Free(interp, azElem);
1530 **
1531 */
1532 int Th_SplitList(
1533 Th_Interp *interp,
1534 const char *zList, /* Pointer to buffer containing list */
1535 int nList, /* Number of bytes at zList */
1536 char ***pazElem, /* OUT: Array of pointers to element data */
1537 int **panElem, /* OUT: Array of element data lengths */
1538 int *pnCount /* OUT: Number of elements in list */
1539 ){
1540 int rc;
1541 interp->isListMode = 1;
@@ -1542,16 +1546,16 @@
1546 }
1547 return rc;
1548 }
1549
1550 /*
1551 ** Append a new element to an existing th1 list. The element to append
1552 ** to the list is (zElem, nElem).
1553 **
1554 ** A pointer to the existing list must be stored at *pzList when this
1555 ** function is called. The length must be stored in *pnList. The value
1556 ** of *pzList must either be NULL (in which case *pnList must be 0), or
1557 ** a pointer to memory obtained from Th_Malloc().
1558 **
1559 ** This function calls Th_Free() to free the buffer at *pzList and sets
1560 ** *pzList to point to a new buffer containing the new list value. *pnList
1561 ** is similarly updated before returning. The return value is always TH_OK.
@@ -1568,13 +1572,13 @@
1572 ** Th_Free(interp, zList);
1573 **
1574 */
1575 int Th_ListAppend(
1576 Th_Interp *interp, /* Interpreter context */
1577 char **pzList, /* IN/OUT: Ptr to ptr to list */
1578 int *pnList, /* IN/OUT: Current length of *pzList */
1579 const char *zElem, /* Data to append */
1580 int nElem /* Length of nElem */
1581 ){
1582 Buffer output;
1583 int i;
1584
@@ -1623,13 +1627,13 @@
1627 ** Append a new element to an existing th1 string. This function uses
1628 ** the same interface as the Th_ListAppend() function.
1629 */
1630 int Th_StringAppend(
1631 Th_Interp *interp, /* Interpreter context */
1632 char **pzStr, /* IN/OUT: Ptr to ptr to list */
1633 int *pnStr, /* IN/OUT: Current length of *pzStr */
1634 const char *zElem, /* Data to append */
1635 int nElem /* Length of nElem */
1636 ){
1637 char *zNew;
1638 int nNew;
1639
@@ -1647,11 +1651,11 @@
1651 *pnStr = nNew;
1652
1653 return TH_OK;
1654 }
1655
1656 /*
1657 ** Delete an interpreter.
1658 */
1659 void Th_DeleteInterp(Th_Interp *interp){
1660 assert(interp->pFrame);
1661 assert(0==interp->pFrame->pCaller);
@@ -1668,11 +1672,11 @@
1672
1673 /* Delete the interpreter structure itself. */
1674 Th_Free(interp, (void *)interp);
1675 }
1676
1677 /*
1678 ** Create a new interpreter.
1679 */
1680 Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){
1681 Th_Interp *p;
1682
@@ -1702,11 +1706,11 @@
1706 Operator *pOp;
1707 Expr *pParent;
1708 Expr *pLeft;
1709 Expr *pRight;
1710
1711 char *zValue; /* Pointer to literal value */
1712 int nValue; /* Length of literal value buffer */
1713 };
1714
1715 /* Unary operators */
1716 #define OP_UNARY_MINUS 2
@@ -1758,11 +1762,11 @@
1762 {"+", OP_UNARY_PLUS, 1, ARG_NUMBER},
1763 {"~", OP_BITWISE_NOT, 1, ARG_INTEGER},
1764 {"!", OP_LOGICAL_NOT, 1, ARG_INTEGER},
1765
1766 /* Binary operators. It is important to the parsing in Th_Expr() that
1767 * the two-character symbols ("==") appear before the one-character
1768 * ones ("="). And that the priorities of all binary operators are
1769 * integers between 2 and 12.
1770 */
1771 {"<<", OP_LEFTSHIFT, 4, ARG_INTEGER},
1772 {">>", OP_RIGHTSHIFT, 4, ARG_INTEGER},
@@ -1789,16 +1793,16 @@
1793 {0,0,0,0}
1794 };
1795
1796 /*
1797 ** The first part of the string (zInput,nInput) contains a number.
1798 ** Set *pnVarname to the number of bytes in the numeric string.
1799 */
1800 static int thNextNumber(
1801 Th_Interp *interp,
1802 const char *zInput,
1803 int nInput,
1804 int *pnLiteral
1805 ){
1806 int i;
1807 int seenDot = 0;
1808 for(i=0; i<nInput; i++){
@@ -1864,11 +1868,11 @@
1868 if( eArgType==ARG_NUMBER ){
1869 if( (zLeft==0 || TH_OK==Th_ToInt(0, zLeft, nLeft, &iLeft))
1870 && (zRight==0 || TH_OK==Th_ToInt(0, zRight, nRight, &iRight))
1871 ){
1872 eArgType = ARG_INTEGER;
1873 }else if(
1874 (zLeft && TH_OK!=Th_ToDouble(interp, zLeft, nLeft, &fLeft)) ||
1875 (zRight && TH_OK!=Th_ToDouble(interp, zRight, nRight, &fRight))
1876 ){
1877 /* A type error. */
1878 rc = TH_ERROR;
@@ -1876,11 +1880,11 @@
1880 }else if( eArgType==ARG_INTEGER ){
1881 rc = Th_ToInt(interp, zLeft, nLeft, &iLeft);
1882 if( rc==TH_OK && zRight ){
1883 rc = Th_ToInt(interp, zRight, nRight, &iRight);
1884 }
1885 }
1886 }
1887
1888 if( rc==TH_OK && eArgType==ARG_INTEGER ){
1889 int iRes = 0;
1890 switch( pExpr->pOp->eOp ) {
@@ -1978,11 +1982,11 @@
1982 #define ISTERM(x) (apToken[x] && (!apToken[x]->pOp || apToken[x]->pLeft))
1983
1984 for(jj=0; jj<nToken; jj++){
1985 if( apToken[jj]->pOp && apToken[jj]->pOp->eOp==OP_OPEN_BRACKET ){
1986 int nNest = 1;
1987 int iLeft = jj;
1988
1989 for(jj++; jj<nToken; jj++){
1990 Operator *pOp = apToken[jj]->pOp;
1991 if( pOp && pOp->eOp==OP_OPEN_BRACKET ) nNest++;
1992 if( pOp && pOp->eOp==OP_CLOSE_BRACKET ) nNest--;
@@ -2052,11 +2056,11 @@
2056 /*
2057 ** Parse a string containing a TH expression to a list of tokens.
2058 */
2059 static int exprParse(
2060 Th_Interp *interp, /* Interpreter to leave error message in */
2061 const char *zExpr, /* Pointer to input string */
2062 int nExpr, /* Number of bytes at zExpr */
2063 Expr ***papToken, /* OUT: Array of tokens. */
2064 int *pnToken /* OUT: Size of token array */
2065 ){
2066 int i;
@@ -2127,11 +2131,11 @@
2131 memcpy(pNew->zValue, z, pNew->nValue);
2132 i += pNew->nValue;
2133 }
2134 if( (nToken%16)==0 ){
2135 /* Grow the apToken array. */
2136 Expr **apTokenOld = apToken;
2137 apToken = Th_Malloc(interp, sizeof(Expr *)*(nToken+16));
2138 memcpy(apToken, apTokenOld, sizeof(Expr *)*nToken);
2139 }
2140
2141 /* Put the new token at the end of the apToken array */
@@ -2152,11 +2156,11 @@
2156 /*
2157 ** Evaluate the string (zExpr, nExpr) as a Th expression. Store
2158 ** the result in the interpreter interp and return TH_OK if
2159 ** successful. If an error occurs, store an error message in
2160 ** the interpreter result and return an error code.
2161 */
2162 int Th_Expr(Th_Interp *interp, const char *zExpr, int nExpr){
2163 int rc; /* Return Code */
2164 int i; /* Loop counter */
2165
2166 int nToken = 0;
@@ -2169,11 +2173,11 @@
2173 /* Parse the expression to a list of tokens. */
2174 rc = exprParse(interp, zExpr, nExpr, &apToken, &nToken);
2175
2176 /* If the parsing was successful, create an expression tree from
2177 ** the parsed list of tokens. If successful, apToken[0] is set
2178 ** to point to the root of the expression tree.
2179 */
2180 if( rc==TH_OK ){
2181 rc = exprMakeTree(interp, apToken, nToken);
2182 }
2183
@@ -2210,11 +2214,11 @@
2214 ** the callback function xCallback for each entry. The second argument
2215 ** passed to xCallback is a copy of the fourth argument passed to this
2216 ** function.
2217 */
2218 void Th_HashIterate(
2219 Th_Interp *interp,
2220 Th_Hash *pHash,
2221 void (*xCallback)(Th_HashEntry *pEntry, void *pContext),
2222 void *pContext
2223 ){
2224 int i;
@@ -2244,14 +2248,14 @@
2248 Th_Free(interp, pHash);
2249 }
2250 }
2251
2252 /*
2253 ** This function is used to insert or delete hash table items, or to
2254 ** query a hash table for an existing item.
2255 **
2256 ** If parameter op is less than zero, then the hash-table element
2257 ** identified by (zKey, nKey) is removed from the hash-table if it
2258 ** exists. NULL is returned.
2259 **
2260 ** Otherwise, if the hash-table contains an item with key (zKey, nKey),
2261 ** a pointer to the associated Th_HashEntry is returned. If parameter
@@ -2258,11 +2262,11 @@
2262 ** op is greater than zero, then a new entry is added if one cannot
2263 ** be found. If op is zero, then NULL is returned if the item is
2264 ** not already present in the hash-table.
2265 */
2266 Th_HashEntry *Th_HashFind(
2267 Th_Interp *interp,
2268 Th_Hash *pHash,
2269 const char *zKey,
2270 int nKey,
2271 int op /* -ve = delete, 0 = find, +ve = insert */
2272 ){
@@ -2326,11 +2330,11 @@
2330 ** '\f' 0x0C
2331 ** '\r' 0x0D
2332 **
2333 ** Whitespace characters have the 0x01 flag set. Decimal digits have the
2334 ** 0x2 flag set. Single byte printable characters have the 0x4 flag set.
2335 ** Alphabet characters have the 0x8 bit set.
2336 **
2337 ** The special list characters have the 0x10 flag set
2338 **
2339 ** { } [ ] \ ; ' "
2340 **
@@ -2477,14 +2481,14 @@
2481 return z - zBegin;
2482 }
2483
2484 /*
2485 ** Try to convert the string passed as arguments (z, n) to an integer.
2486 ** If successful, store the result in *piOut and return TH_OK.
2487 **
2488 ** If the string cannot be converted to an integer, return TH_ERROR.
2489 ** If the interp argument is not NULL, leave an error message in the
2490 ** interpreter result too.
2491 */
2492 int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
2493 int i = 0;
2494 int iOut = 0;
@@ -2512,20 +2516,20 @@
2516 return TH_OK;
2517 }
2518
2519 /*
2520 ** Try to convert the string passed as arguments (z, n) to a double.
2521 ** If successful, store the result in *pfOut and return TH_OK.
2522 **
2523 ** If the string cannot be converted to a double, return TH_ERROR.
2524 ** If the interp argument is not NULL, leave an error message in the
2525 ** interpreter result too.
2526 */
2527 int Th_ToDouble(
2528 Th_Interp *interp,
2529 const char *z,
2530 int n,
2531 double *pfOut
2532 ){
2533 if( !sqlite3IsNumber((const char *)z, 0) ){
2534 Th_ErrorMessage(interp, "expected number, got: \"", z, n);
2535 return TH_ERROR;
@@ -2566,33 +2570,33 @@
2570 ** the double fVal and return TH_OK.
2571 */
2572 int Th_SetResultDouble(Th_Interp *interp, double fVal){
2573 int i; /* Iterator variable */
2574 double v = fVal; /* Input value */
2575 char zBuf[128]; /* Output buffer */
2576 char *z = zBuf; /* Output cursor */
2577 int iDot = 0; /* Digit after which to place decimal point */
2578 int iExp = 0; /* Exponent (NN in eNN) */
2579 const char *zExp; /* String representation of iExp */
2580
2581 /* Precision: */
2582 #define INSIGNIFICANT 0.000000000001
2583 #define ROUNDER 0.0000000000005
2584 double insignificant = INSIGNIFICANT;
2585
2586 /* If the real value is negative, write a '-' character to the
2587 * output and transform v to the corresponding positive number.
2588 */
2589 if( v<0.0 ){
2590 *z++ = '-';
2591 v *= -1.0;
2592 }
2593
2594 /* Normalize v to a value between 1.0 and 10.0. Integer
2595 * variable iExp is set to the exponent. i.e the original
2596 * value is (v * 10^iExp) (or the negative thereof).
2597 */
2598 if( v>0.0 ){
2599 while( (v+ROUNDER)>=10.0 ) { iExp++; v *= 0.1; }
2600 while( (v+ROUNDER)<1.0 ) { iExp--; v *= 10.0; }
2601 }
2602 v += ROUNDER;
2603
+22 -22
--- src/th.h
+++ src/th.h
@@ -18,70 +18,70 @@
1818
/*
1919
** Opaque handle for interpeter.
2020
*/
2121
typedef struct Th_Interp Th_Interp;
2222
23
-/*
24
-** Create and delete interpreters.
23
+/*
24
+** Create and delete interpreters.
2525
*/
2626
Th_Interp * Th_CreateInterp(Th_Vtab *pVtab);
2727
void Th_DeleteInterp(Th_Interp *);
2828
29
-/*
29
+/*
3030
** Evaluate an TH program in the stack frame identified by parameter
3131
** iFrame, according to the following rules:
3232
**
3333
** * If iFrame is 0, this means the current frame.
3434
**
35
-** * If iFrame is negative, then the nth frame up the stack, where n is
35
+** * If iFrame is negative, then the nth frame up the stack, where n is
3636
** the absolute value of iFrame. A value of -1 means the calling
3737
** procedure.
3838
**
3939
** * If iFrame is +ve, then the nth frame from the bottom of the stack.
4040
** An iFrame value of 1 means the toplevel (global) frame.
4141
*/
4242
int Th_Eval(Th_Interp *interp, int iFrame, const char *zProg, int nProg);
4343
4444
/*
45
-** Evaluate a TH expression. The result is stored in the
45
+** Evaluate a TH expression. The result is stored in the
4646
** interpreter result.
4747
*/
4848
int Th_Expr(Th_Interp *interp, const char *, int);
4949
50
-/*
50
+/*
5151
** Access TH variables in the current stack frame. If the variable name
52
-** begins with "::", the lookup is in the top level (global) frame.
52
+** begins with "::", the lookup is in the top level (global) frame.
5353
*/
5454
int Th_ExistsVar(Th_Interp *, const char *, int);
5555
int Th_GetVar(Th_Interp *, const char *, int);
5656
int Th_SetVar(Th_Interp *, const char *, int, const char *, int);
5757
int Th_LinkVar(Th_Interp *, const char *, int, int, const char *, int);
5858
int Th_UnsetVar(Th_Interp *, const char *, int);
5959
6060
typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const char **, int *);
6161
62
-/*
63
-** Register new commands.
62
+/*
63
+** Register new commands.
6464
*/
6565
int Th_CreateCommand(
66
- Th_Interp *interp,
67
- const char *zName,
66
+ Th_Interp *interp,
67
+ const char *zName,
6868
/* int (*xProc)(Th_Interp *, void *, int, const char **, int *), */
6969
Th_CommandProc xProc,
7070
void *pContext,
7171
void (*xDel)(Th_Interp *, void *)
7272
);
7373
74
-/*
74
+/*
7575
** Delete or rename commands.
7676
*/
7777
int Th_RenameCommand(Th_Interp *, const char *, int, const char *, int);
7878
79
-/*
80
-** Push a new stack frame (local variable context) onto the interpreter
81
-** stack, call the function supplied as parameter xCall with the two
82
-** context arguments,
79
+/*
80
+** Push a new stack frame (local variable context) onto the interpreter
81
+** stack, call the function supplied as parameter xCall with the two
82
+** context arguments,
8383
**
8484
** xCall(interp, pContext1, pContext2)
8585
**
8686
** , then pop the frame off of the interpreter stack. The value returned
8787
** by the xCall() function is returned as the result of this function.
@@ -93,21 +93,21 @@
9393
int (*xCall)(Th_Interp *, void *pContext1, void *pContext2),
9494
void *pContext1,
9595
void *pContext2
9696
);
9797
98
-/*
98
+/*
9999
** Valid return codes for xProc callbacks.
100100
*/
101101
#define TH_OK 0
102102
#define TH_ERROR 1
103103
#define TH_BREAK 2
104104
#define TH_RETURN 3
105105
#define TH_CONTINUE 4
106106
107
-/*
108
-** Set and get the interpreter result.
107
+/*
108
+** Set and get the interpreter result.
109109
*/
110110
int Th_SetResult(Th_Interp *, const char *, int);
111111
const char *Th_GetResult(Th_Interp *, int *);
112112
char *Th_TakeResult(Th_Interp *, int *);
113113
@@ -115,26 +115,26 @@
115115
** Set an error message as the interpreter result. This also
116116
** sets the global stack-trace variable $::th_stack_trace.
117117
*/
118118
int Th_ErrorMessage(Th_Interp *, const char *, const char *, int);
119119
120
-/*
120
+/*
121121
** Access the memory management functions associated with the specified
122122
** interpreter.
123123
*/
124124
void *Th_Malloc(Th_Interp *, int);
125125
void Th_Free(Th_Interp *, void *);
126126
127
-/*
127
+/*
128128
** Functions for handling TH lists.
129129
*/
130130
int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
131131
int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
132132
133133
int Th_StringAppend(Th_Interp *, char **, int *, const char *, int);
134134
135
-/*
135
+/*
136136
** Functions for handling numbers and pointers.
137137
*/
138138
int Th_ToInt(Th_Interp *, const char *, int, int *);
139139
int Th_ToDouble(Th_Interp *, const char *, int, double *);
140140
int Th_SetResultInt(Th_Interp *, int);
141141
--- src/th.h
+++ src/th.h
@@ -18,70 +18,70 @@
18 /*
19 ** Opaque handle for interpeter.
20 */
21 typedef struct Th_Interp Th_Interp;
22
23 /*
24 ** Create and delete interpreters.
25 */
26 Th_Interp * Th_CreateInterp(Th_Vtab *pVtab);
27 void Th_DeleteInterp(Th_Interp *);
28
29 /*
30 ** Evaluate an TH program in the stack frame identified by parameter
31 ** iFrame, according to the following rules:
32 **
33 ** * If iFrame is 0, this means the current frame.
34 **
35 ** * If iFrame is negative, then the nth frame up the stack, where n is
36 ** the absolute value of iFrame. A value of -1 means the calling
37 ** procedure.
38 **
39 ** * If iFrame is +ve, then the nth frame from the bottom of the stack.
40 ** An iFrame value of 1 means the toplevel (global) frame.
41 */
42 int Th_Eval(Th_Interp *interp, int iFrame, const char *zProg, int nProg);
43
44 /*
45 ** Evaluate a TH expression. The result is stored in the
46 ** interpreter result.
47 */
48 int Th_Expr(Th_Interp *interp, const char *, int);
49
50 /*
51 ** Access TH variables in the current stack frame. If the variable name
52 ** begins with "::", the lookup is in the top level (global) frame.
53 */
54 int Th_ExistsVar(Th_Interp *, const char *, int);
55 int Th_GetVar(Th_Interp *, const char *, int);
56 int Th_SetVar(Th_Interp *, const char *, int, const char *, int);
57 int Th_LinkVar(Th_Interp *, const char *, int, int, const char *, int);
58 int Th_UnsetVar(Th_Interp *, const char *, int);
59
60 typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const char **, int *);
61
62 /*
63 ** Register new commands.
64 */
65 int Th_CreateCommand(
66 Th_Interp *interp,
67 const char *zName,
68 /* int (*xProc)(Th_Interp *, void *, int, const char **, int *), */
69 Th_CommandProc xProc,
70 void *pContext,
71 void (*xDel)(Th_Interp *, void *)
72 );
73
74 /*
75 ** Delete or rename commands.
76 */
77 int Th_RenameCommand(Th_Interp *, const char *, int, const char *, int);
78
79 /*
80 ** Push a new stack frame (local variable context) onto the interpreter
81 ** stack, call the function supplied as parameter xCall with the two
82 ** context arguments,
83 **
84 ** xCall(interp, pContext1, pContext2)
85 **
86 ** , then pop the frame off of the interpreter stack. The value returned
87 ** by the xCall() function is returned as the result of this function.
@@ -93,21 +93,21 @@
93 int (*xCall)(Th_Interp *, void *pContext1, void *pContext2),
94 void *pContext1,
95 void *pContext2
96 );
97
98 /*
99 ** Valid return codes for xProc callbacks.
100 */
101 #define TH_OK 0
102 #define TH_ERROR 1
103 #define TH_BREAK 2
104 #define TH_RETURN 3
105 #define TH_CONTINUE 4
106
107 /*
108 ** Set and get the interpreter result.
109 */
110 int Th_SetResult(Th_Interp *, const char *, int);
111 const char *Th_GetResult(Th_Interp *, int *);
112 char *Th_TakeResult(Th_Interp *, int *);
113
@@ -115,26 +115,26 @@
115 ** Set an error message as the interpreter result. This also
116 ** sets the global stack-trace variable $::th_stack_trace.
117 */
118 int Th_ErrorMessage(Th_Interp *, const char *, const char *, int);
119
120 /*
121 ** Access the memory management functions associated with the specified
122 ** interpreter.
123 */
124 void *Th_Malloc(Th_Interp *, int);
125 void Th_Free(Th_Interp *, void *);
126
127 /*
128 ** Functions for handling TH lists.
129 */
130 int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
131 int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
132
133 int Th_StringAppend(Th_Interp *, char **, int *, const char *, int);
134
135 /*
136 ** Functions for handling numbers and pointers.
137 */
138 int Th_ToInt(Th_Interp *, const char *, int, int *);
139 int Th_ToDouble(Th_Interp *, const char *, int, double *);
140 int Th_SetResultInt(Th_Interp *, int);
141
--- src/th.h
+++ src/th.h
@@ -18,70 +18,70 @@
18 /*
19 ** Opaque handle for interpeter.
20 */
21 typedef struct Th_Interp Th_Interp;
22
23 /*
24 ** Create and delete interpreters.
25 */
26 Th_Interp * Th_CreateInterp(Th_Vtab *pVtab);
27 void Th_DeleteInterp(Th_Interp *);
28
29 /*
30 ** Evaluate an TH program in the stack frame identified by parameter
31 ** iFrame, according to the following rules:
32 **
33 ** * If iFrame is 0, this means the current frame.
34 **
35 ** * If iFrame is negative, then the nth frame up the stack, where n is
36 ** the absolute value of iFrame. A value of -1 means the calling
37 ** procedure.
38 **
39 ** * If iFrame is +ve, then the nth frame from the bottom of the stack.
40 ** An iFrame value of 1 means the toplevel (global) frame.
41 */
42 int Th_Eval(Th_Interp *interp, int iFrame, const char *zProg, int nProg);
43
44 /*
45 ** Evaluate a TH expression. The result is stored in the
46 ** interpreter result.
47 */
48 int Th_Expr(Th_Interp *interp, const char *, int);
49
50 /*
51 ** Access TH variables in the current stack frame. If the variable name
52 ** begins with "::", the lookup is in the top level (global) frame.
53 */
54 int Th_ExistsVar(Th_Interp *, const char *, int);
55 int Th_GetVar(Th_Interp *, const char *, int);
56 int Th_SetVar(Th_Interp *, const char *, int, const char *, int);
57 int Th_LinkVar(Th_Interp *, const char *, int, int, const char *, int);
58 int Th_UnsetVar(Th_Interp *, const char *, int);
59
60 typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const char **, int *);
61
62 /*
63 ** Register new commands.
64 */
65 int Th_CreateCommand(
66 Th_Interp *interp,
67 const char *zName,
68 /* int (*xProc)(Th_Interp *, void *, int, const char **, int *), */
69 Th_CommandProc xProc,
70 void *pContext,
71 void (*xDel)(Th_Interp *, void *)
72 );
73
74 /*
75 ** Delete or rename commands.
76 */
77 int Th_RenameCommand(Th_Interp *, const char *, int, const char *, int);
78
79 /*
80 ** Push a new stack frame (local variable context) onto the interpreter
81 ** stack, call the function supplied as parameter xCall with the two
82 ** context arguments,
83 **
84 ** xCall(interp, pContext1, pContext2)
85 **
86 ** , then pop the frame off of the interpreter stack. The value returned
87 ** by the xCall() function is returned as the result of this function.
@@ -93,21 +93,21 @@
93 int (*xCall)(Th_Interp *, void *pContext1, void *pContext2),
94 void *pContext1,
95 void *pContext2
96 );
97
98 /*
99 ** Valid return codes for xProc callbacks.
100 */
101 #define TH_OK 0
102 #define TH_ERROR 1
103 #define TH_BREAK 2
104 #define TH_RETURN 3
105 #define TH_CONTINUE 4
106
107 /*
108 ** Set and get the interpreter result.
109 */
110 int Th_SetResult(Th_Interp *, const char *, int);
111 const char *Th_GetResult(Th_Interp *, int *);
112 char *Th_TakeResult(Th_Interp *, int *);
113
@@ -115,26 +115,26 @@
115 ** Set an error message as the interpreter result. This also
116 ** sets the global stack-trace variable $::th_stack_trace.
117 */
118 int Th_ErrorMessage(Th_Interp *, const char *, const char *, int);
119
120 /*
121 ** Access the memory management functions associated with the specified
122 ** interpreter.
123 */
124 void *Th_Malloc(Th_Interp *, int);
125 void Th_Free(Th_Interp *, void *);
126
127 /*
128 ** Functions for handling TH lists.
129 */
130 int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
131 int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
132
133 int Th_StringAppend(Th_Interp *, char **, int *, const char *, int);
134
135 /*
136 ** Functions for handling numbers and pointers.
137 */
138 int Th_ToInt(Th_Interp *, const char *, int, int *);
139 int Th_ToDouble(Th_Interp *, const char *, int, double *);
140 int Th_SetResultInt(Th_Interp *, int);
141
+113 -113
--- src/th_lang.c
+++ src/th_lang.c
@@ -1,12 +1,12 @@
11
22
/*
3
-** This file contains the implementation of all of the TH language
4
-** built-in commands.
3
+** This file contains the implementation of all of the TH language
4
+** built-in commands.
55
**
6
-** All built-in commands are implemented using the public interface
7
-** declared in th.h, so this file serves as both a part of the language
6
+** All built-in commands are implemented using the public interface
7
+** declared in th.h, so this file serves as both a part of the language
88
** implementation and an example of how to extend the language with
99
** new commands.
1010
*/
1111
1212
#include "config.h"
@@ -18,19 +18,19 @@
1818
Th_ErrorMessage(interp, "wrong # args: should be \"", zMsg, -1);
1919
return TH_ERROR;
2020
}
2121
2222
/*
23
-** Syntax:
23
+** Syntax:
2424
**
2525
** catch script ?varname?
2626
*/
2727
static int catch_command(
28
- Th_Interp *interp,
29
- void *ctx,
30
- int argc,
31
- const char **argv,
28
+ Th_Interp *interp,
29
+ void *ctx,
30
+ int argc,
31
+ const char **argv,
3232
int *argl
3333
){
3434
int rc;
3535
3636
if( argc!=2 && argc!=3 ){
@@ -47,19 +47,19 @@
4747
Th_SetResultInt(interp, rc);
4848
return TH_OK;
4949
}
5050
5151
/*
52
-** TH Syntax:
52
+** TH Syntax:
5353
**
5454
** if expr1 body1 ?elseif expr2 body2? ? ?else? bodyN?
5555
*/
5656
static int if_command(
57
- Th_Interp *interp,
58
- void *ctx,
59
- int argc,
60
- const char **argv,
57
+ Th_Interp *interp,
58
+ void *ctx,
59
+ int argc,
60
+ const char **argv,
6161
int *argl
6262
){
6363
int rc = TH_OK;
6464
6565
int iCond; /* Result of evaluating expression */
@@ -94,19 +94,19 @@
9494
wrong_args:
9595
return Th_WrongNumArgs(interp, "if ...");
9696
}
9797
9898
/*
99
-** TH Syntax:
99
+** TH Syntax:
100100
**
101101
** expr expr
102102
*/
103103
static int expr_command(
104
- Th_Interp *interp,
105
- void *ctx,
106
- int argc,
107
- const char **argv,
104
+ Th_Interp *interp,
105
+ void *ctx,
106
+ int argc,
107
+ const char **argv,
108108
int *argl
109109
){
110110
if( argc!=2 ){
111111
return Th_WrongNumArgs(interp, "expr expression");
112112
}
@@ -113,11 +113,11 @@
113113
114114
return Th_Expr(interp, argv[1], argl[1]);
115115
}
116116
117117
/*
118
-** Evaluate the th1 script (zBody, nBody) in the local stack frame.
118
+** Evaluate the th1 script (zBody, nBody) in the local stack frame.
119119
** Return the result of the evaluation, except if the result
120120
** is TH_CONTINUE, return TH_OK instead.
121121
*/
122122
static int eval_loopbody(Th_Interp *interp, const char *zBody, int nBody){
123123
int rc = Th_Eval(interp, 0, zBody, nBody);
@@ -126,19 +126,19 @@
126126
}
127127
return rc;
128128
}
129129
130130
/*
131
-** TH Syntax:
131
+** TH Syntax:
132132
**
133133
** for init condition incr script
134134
*/
135135
static int for_command(
136
- Th_Interp *interp,
137
- void *ctx,
138
- int argc,
139
- const char **argv,
136
+ Th_Interp *interp,
137
+ void *ctx,
138
+ int argc,
139
+ const char **argv,
140140
int *argl
141141
){
142142
int rc;
143143
int iCond;
144144
@@ -147,11 +147,11 @@
147147
}
148148
149149
/* Evaluate the 'init' script */
150150
rc = Th_Eval(interp, 0, argv[1], -1);
151151
152
- while( rc==TH_OK
152
+ while( rc==TH_OK
153153
&& TH_OK==(rc = Th_Expr(interp, argv[2], -1))
154154
&& TH_OK==(rc = Th_ToInt(interp, Th_GetResult(interp, 0), -1, &iCond))
155155
&& iCond
156156
&& TH_OK==(rc = eval_loopbody(interp, argv[4], argl[4]))
157157
){
@@ -161,45 +161,45 @@
161161
if( rc==TH_BREAK ) rc = TH_OK;
162162
return rc;
163163
}
164164
165165
/*
166
-** TH Syntax:
166
+** TH Syntax:
167167
**
168168
** list ?arg1 ?arg2? ...?
169169
*/
170170
static int list_command(
171
- Th_Interp *interp,
172
- void *ctx,
173
- int argc,
174
- const char **argv,
171
+ Th_Interp *interp,
172
+ void *ctx,
173
+ int argc,
174
+ const char **argv,
175175
int *argl
176176
){
177177
char *zList = 0;
178178
int nList = 0;
179179
int i;
180180
181181
for(i=1; i<argc; i++){
182182
Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]);
183183
}
184
-
184
+
185185
Th_SetResult(interp, zList, nList);
186186
Th_Free(interp, zList);
187187
188188
return TH_OK;
189189
}
190190
191191
/*
192
-** TH Syntax:
192
+** TH Syntax:
193193
**
194194
** lindex list index
195195
*/
196196
static int lindex_command(
197
- Th_Interp *interp,
198
- void *ctx,
199
- int argc,
200
- const char **argv,
197
+ Th_Interp *interp,
198
+ void *ctx,
199
+ int argc,
200
+ const char **argv,
201201
int *argl
202202
){
203203
int iElem;
204204
int rc;
205205
@@ -227,19 +227,19 @@
227227
228228
return rc;
229229
}
230230
231231
/*
232
-** TH Syntax:
232
+** TH Syntax:
233233
**
234234
** llength list
235235
*/
236236
static int llength_command(
237
- Th_Interp *interp,
238
- void *ctx,
239
- int argc,
240
- const char **argv,
237
+ Th_Interp *interp,
238
+ void *ctx,
239
+ int argc,
240
+ const char **argv,
241241
int *argl
242242
){
243243
int nElem;
244244
int rc;
245245
@@ -254,19 +254,19 @@
254254
255255
return rc;
256256
}
257257
258258
/*
259
-** TH Syntax:
259
+** TH Syntax:
260260
**
261261
** set varname ?value?
262262
*/
263263
static int set_command(
264
- Th_Interp *interp,
265
- void *ctx,
266
- int argc,
267
- const char **argv,
264
+ Th_Interp *interp,
265
+ void *ctx,
266
+ int argc,
267
+ const char **argv,
268268
int *argl
269269
){
270270
if( argc!=2 && argc!=3 ){
271271
return Th_WrongNumArgs(interp, "set varname ?value?");
272272
}
@@ -277,30 +277,30 @@
277277
return Th_GetVar(interp, argv[1], argl[1]);
278278
}
279279
280280
/*
281281
** When a new command is created using the built-in [proc] command, an
282
-** instance of the following structure is allocated and populated. A
283
-** pointer to the structure is passed as the context (second) argument
282
+** instance of the following structure is allocated and populated. A
283
+** pointer to the structure is passed as the context (second) argument
284284
** to function proc_call1() when the new command is executed.
285285
*/
286286
typedef struct ProcDefn ProcDefn;
287287
struct ProcDefn {
288288
int nParam; /* Number of formal (non "args") parameters */
289
- char **azParam; /* Parameter names */
289
+ char **azParam; /* Parameter names */
290290
int *anParam; /* Lengths of parameter names */
291
- char **azDefault; /* Default values */
291
+ char **azDefault; /* Default values */
292292
int *anDefault; /* Lengths of default values */
293293
int hasArgs; /* True if there is an "args" parameter */
294
- char *zProgram; /* Body of proc */
294
+ char *zProgram; /* Body of proc */
295295
int nProgram; /* Number of bytes at zProgram */
296
- char *zUsage; /* Usage message */
296
+ char *zUsage; /* Usage message */
297297
int nUsage; /* Number of bytes at zUsage */
298298
};
299299
300
-/* This structure is used to temporarily store arguments passed to an
301
-** invocation of a command created using [proc]. A pointer to an
300
+/* This structure is used to temporarily store arguments passed to an
301
+** invocation of a command created using [proc]. A pointer to an
302302
** instance is passed as the second argument to the proc_call2() function.
303303
*/
304304
typedef struct ProcArgs ProcArgs;
305305
struct ProcArgs {
306306
int argc;
@@ -323,11 +323,11 @@
323323
ProcArgs *pArgs = (ProcArgs *)pContext2;
324324
325325
/* Check if there are the right number of arguments. If there are
326326
** not, generate a usage message for the command.
327327
*/
328
- if( (pArgs->argc>(p->nParam+1) && !p->hasArgs)
328
+ if( (pArgs->argc>(p->nParam+1) && !p->hasArgs)
329329
|| (pArgs->argc<=(p->nParam) && !p->azDefault[pArgs->argc-1])
330330
){
331331
char *zUsage = 0;
332332
int nUsage = 0;
333333
Th_StringAppend(interp, &zUsage, &nUsage, pArgs->argv[0], pArgs->argl[0]);
@@ -374,12 +374,12 @@
374374
** created using the [proc] command. The second argument, pContext,
375375
** is a pointer to the associated ProcDefn structure.
376376
*/
377377
static int proc_call1(
378378
Th_Interp *interp,
379
- void *pContext,
380
- int argc,
379
+ void *pContext,
380
+ int argc,
381381
const char **argv,
382382
int *argl
383383
){
384384
int rc;
385385
@@ -400,32 +400,32 @@
400400
}
401401
return rc;
402402
}
403403
404404
/*
405
-** This function is registered as the delete callback for all commands
406
-** created using the built-in [proc] command. It is called automatically
407
-** when a command created using [proc] is deleted.
405
+** This function is registered as the delete callback for all commands
406
+** created using the built-in [proc] command. It is called automatically
407
+** when a command created using [proc] is deleted.
408408
**
409409
** It frees the ProcDefn structure allocated when the command was created.
410
-*/
410
+*/
411411
static void proc_del(Th_Interp *interp, void *pContext){
412412
ProcDefn *p = (ProcDefn *)pContext;
413413
Th_Free(interp, (void *)p->zUsage);
414414
Th_Free(interp, (void *)p);
415415
}
416416
417417
/*
418
-** TH Syntax:
418
+** TH Syntax:
419419
**
420420
** proc name arglist code
421421
*/
422422
static int proc_command(
423
- Th_Interp *interp,
424
- void *ctx,
423
+ Th_Interp *interp,
424
+ void *ctx,
425425
int argc,
426
- const char **argv,
426
+ const char **argv,
427427
int *argl
428428
){
429429
int rc;
430430
char *zName;
431431
@@ -436,11 +436,11 @@
436436
437437
char **azParam;
438438
int *anParam;
439439
int nParam;
440440
441
- char *zUsage = 0; /* Build up a usage message here */
441
+ char *zUsage = 0; /* Build up a usage message here */
442442
int nUsage = 0; /* Number of bytes at zUsage */
443443
444444
if( argc!=4 ){
445445
return Th_WrongNumArgs(interp, "proc name arglist code");
446446
}
@@ -448,14 +448,14 @@
448448
return TH_ERROR;
449449
}
450450
451451
/* Allocate the new ProcDefn structure. */
452452
nByte = sizeof(ProcDefn) + /* ProcDefn structure */
453
- (sizeof(char *) + sizeof(int)) * nParam + /* azParam, anParam */
454
- (sizeof(char *) + sizeof(int)) * nParam + /* azDefault, anDefault */
453
+ (sizeof(char *) + sizeof(int)) * nParam + /* azParam, anParam */
454
+ (sizeof(char *) + sizeof(int)) * nParam + /* azDefault, anDefault */
455455
argl[3] + /* zProgram */
456
- argl[2]; /* Space for copies of parameter names and default values */
456
+ argl[2]; /* Space for copies of parameter names and default values */
457457
p = (ProcDefn *)Th_Malloc(interp, nByte);
458458
459459
/* If the last parameter in the parameter list is "args", then set the
460460
** ProcDefn.hasArgs flag. The "args" parameter does not require an
461461
** entry in the ProcDefn.azParam[] or ProcDefn.azDefault[] arrays.
@@ -472,11 +472,11 @@
472472
p->anDefault = (int *)&p->azDefault[nParam];
473473
p->zProgram = (char *)&p->anDefault[nParam];
474474
memcpy(p->zProgram, argv[3], argl[3]);
475475
p->nProgram = argl[3];
476476
zSpace = &p->zProgram[p->nProgram];
477
-
477
+
478478
for(i=0; i<nParam; i++){
479479
char **az;
480480
int *an;
481481
int n;
482482
if( Th_SplitList(interp, azParam[i], anParam[i], &az, &an, &n) ){
@@ -537,40 +537,40 @@
537537
Th_Free(interp, zUsage);
538538
return TH_ERROR;
539539
}
540540
541541
/*
542
-** TH Syntax:
542
+** TH Syntax:
543543
**
544544
** rename oldcmd newcmd
545545
*/
546546
static int rename_command(
547
- Th_Interp *interp,
548
- void *ctx,
547
+ Th_Interp *interp,
548
+ void *ctx,
549549
int argc,
550
- const char **argv,
550
+ const char **argv,
551551
int *argl
552552
){
553553
if( argc!=3 ){
554554
return Th_WrongNumArgs(interp, "rename oldcmd newcmd");
555555
}
556556
return Th_RenameCommand(interp, argv[1], argl[1], argv[2], argl[2]);
557557
}
558558
559559
/*
560
-** TH Syntax:
560
+** TH Syntax:
561561
**
562562
** break ?value...?
563563
** continue ?value...?
564564
** ok ?value...?
565565
** error ?value...?
566566
*/
567567
static int simple_command(
568
- Th_Interp *interp,
569
- void *ctx,
570
- int argc,
571
- const char **argv,
568
+ Th_Interp *interp,
569
+ void *ctx,
570
+ int argc,
571
+ const char **argv,
572572
int *argl
573573
){
574574
if( argc!=1 && argc!=2 ){
575575
return Th_WrongNumArgs(interp, "return ?value?");
576576
}
@@ -579,19 +579,19 @@
579579
}
580580
return FOSSIL_PTR_TO_INT(ctx);
581581
}
582582
583583
/*
584
-** TH Syntax:
584
+** TH Syntax:
585585
**
586586
** return ?-code code? ?value?
587587
*/
588588
static int return_command(
589
- Th_Interp *interp,
590
- void *ctx,
591
- int argc,
592
- const char **argv,
589
+ Th_Interp *interp,
590
+ void *ctx,
591
+ int argc,
592
+ const char **argv,
593593
int *argl
594594
){
595595
int iCode = TH_RETURN;
596596
if( argc<1 || argc>4 ){
597597
return Th_WrongNumArgs(interp, "return ?-code code? ?value?");
@@ -638,11 +638,11 @@
638638
iRes = nLeft-nRight;
639639
}
640640
641641
if( iRes<0 ) iRes = -1;
642642
if( iRes>0 ) iRes = 1;
643
-
643
+
644644
return Th_SetResultInt(interp, iRes);
645645
}
646646
647647
/*
648648
** TH Syntax:
@@ -672,11 +672,11 @@
672672
if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){
673673
iRes = i;
674674
break;
675675
}
676676
}
677
-
677
+
678678
return Th_SetResultInt(interp, iRes);
679679
}
680680
681681
/*
682682
** TH Syntax:
@@ -733,11 +733,11 @@
733733
if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){
734734
iRes = i;
735735
break;
736736
}
737737
}
738
-
738
+
739739
return Th_SetResultInt(interp, iRes);
740740
}
741741
742742
/*
743743
** TH Syntax:
@@ -867,11 +867,11 @@
867867
** TH Syntax:
868868
**
869869
** unset VAR
870870
*/
871871
static int unset_command(
872
- Th_Interp *interp,
872
+ Th_Interp *interp,
873873
void *ctx,
874874
int argc,
875875
const char **argv,
876876
int *argl
877877
){
@@ -880,11 +880,11 @@
880880
}
881881
return Th_UnsetVar(interp, argv[1], argl[1]);
882882
}
883883
884884
int Th_CallSubCommand(
885
- Th_Interp *interp,
885
+ Th_Interp *interp,
886886
void *ctx,
887887
int argc,
888888
const char **argv,
889889
int *argl,
890890
Th_SubCommand *aSub
@@ -916,11 +916,11 @@
916916
** string length STRING
917917
** string range STRING FIRST LAST
918918
** string repeat STRING COUNT
919919
*/
920920
static int string_command(
921
- Th_Interp *interp,
921
+ Th_Interp *interp,
922922
void *ctx,
923923
int argc,
924924
const char **argv,
925925
int *argl
926926
){
@@ -944,11 +944,11 @@
944944
** TH Syntax:
945945
**
946946
** info exists VARNAME
947947
*/
948948
static int info_command(
949
- Th_Interp *interp,
949
+ Th_Interp *interp,
950950
void *ctx,
951951
int argc,
952952
const char **argv,
953953
int *argl
954954
){
@@ -958,20 +958,20 @@
958958
};
959959
return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
960960
}
961961
962962
/*
963
-** Convert the script level frame specification (used by the commands
964
-** [uplevel] and [upvar]) in (zFrame, nFrame) to an integer frame as
963
+** Convert the script level frame specification (used by the commands
964
+** [uplevel] and [upvar]) in (zFrame, nFrame) to an integer frame as
965965
** used by Th_LinkVar() and Th_Eval(). If successful, write the integer
966966
** frame level to *piFrame and return TH_OK. Otherwise, return TH_ERROR
967967
** and leave an error message in the interpreter result.
968968
*/
969969
static int thToFrame(
970
- Th_Interp *interp,
971
- const char *zFrame,
972
- int nFrame,
970
+ Th_Interp *interp,
971
+ const char *zFrame,
972
+ int nFrame,
973973
int *piFrame
974974
){
975975
int iFrame;
976976
if( th_isdigit(zFrame[0]) ){
977977
int rc = Th_ToInt(interp, zFrame, nFrame, &iFrame);
@@ -992,11 +992,11 @@
992992
** TH Syntax:
993993
**
994994
** uplevel ?LEVEL? SCRIPT
995995
*/
996996
static int uplevel_command(
997
- Th_Interp *interp,
997
+ Th_Interp *interp,
998998
void *ctx,
999999
int argc,
10001000
const char **argv,
10011001
int *argl
10021002
){
@@ -1010,19 +1010,19 @@
10101010
}
10111011
return Th_Eval(interp, iFrame, argv[argc-1], -1);
10121012
}
10131013
10141014
/*
1015
-** TH Syntax:
1015
+** TH Syntax:
10161016
**
10171017
** upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR ...?
10181018
*/
10191019
static int upvar_command(
1020
- Th_Interp *interp,
1021
- void *ctx,
1022
- int argc,
1023
- const char **argv,
1020
+ Th_Interp *interp,
1021
+ void *ctx,
1022
+ int argc,
1023
+ const char **argv,
10241024
int *argl
10251025
){
10261026
int iVar = 1;
10271027
int iFrame = -1;
10281028
int rc = TH_OK;
@@ -1030,32 +1030,32 @@
10301030
10311031
if( TH_OK==thToFrame(0, argv[1], argl[1], &iFrame) ){
10321032
iVar++;
10331033
}
10341034
if( argc==iVar || (argc-iVar)%2 ){
1035
- return Th_WrongNumArgs(interp,
1035
+ return Th_WrongNumArgs(interp,
10361036
"upvar frame othervar myvar ?othervar myvar...?");
10371037
}
10381038
for(i=iVar; rc==TH_OK && i<argc; i=i+2){
10391039
rc = Th_LinkVar(interp, argv[i+1], argl[i+1], iFrame, argv[i], argl[i]);
10401040
}
10411041
return rc;
10421042
}
10431043
10441044
/*
1045
-** TH Syntax:
1045
+** TH Syntax:
10461046
**
10471047
** breakpoint ARGS
10481048
**
10491049
** This command does nothing at all. Its purpose in life is to serve
10501050
** as a point for setting breakpoints in a debugger.
10511051
*/
10521052
static int breakpoint_command(
1053
- Th_Interp *interp,
1054
- void *ctx,
1055
- int argc,
1056
- const char **argv,
1053
+ Th_Interp *interp,
1054
+ void *ctx,
1055
+ int argc,
1056
+ const char **argv,
10571057
int *argl
10581058
){
10591059
int cnt = 0;
10601060
cnt++;
10611061
return TH_OK;
@@ -1078,11 +1078,11 @@
10781078
{"if", if_command, 0},
10791079
{"info", info_command, 0},
10801080
{"lindex", lindex_command, 0},
10811081
{"list", list_command, 0},
10821082
{"llength", llength_command, 0},
1083
- {"proc", proc_command, 0},
1083
+ {"proc", proc_command, 0},
10841084
{"rename", rename_command, 0},
10851085
{"set", set_command, 0},
10861086
{"string", string_command, 0},
10871087
{"unset", unset_command, 0},
10881088
{"uplevel", uplevel_command, 0},
@@ -1089,13 +1089,13 @@
10891089
{"upvar", upvar_command, 0},
10901090
10911091
{"breakpoint", breakpoint_command, 0},
10921092
10931093
{"return", return_command, 0},
1094
- {"break", simple_command, (void *)TH_BREAK},
1095
- {"continue", simple_command, (void *)TH_CONTINUE},
1096
- {"error", simple_command, (void *)TH_ERROR},
1094
+ {"break", simple_command, (void *)TH_BREAK},
1095
+ {"continue", simple_command, (void *)TH_CONTINUE},
1096
+ {"error", simple_command, (void *)TH_ERROR},
10971097
10981098
{0, 0, 0}
10991099
};
11001100
int i;
11011101
11021102
--- src/th_lang.c
+++ src/th_lang.c
@@ -1,12 +1,12 @@
1
2 /*
3 ** This file contains the implementation of all of the TH language
4 ** built-in commands.
5 **
6 ** All built-in commands are implemented using the public interface
7 ** declared in th.h, so this file serves as both a part of the language
8 ** implementation and an example of how to extend the language with
9 ** new commands.
10 */
11
12 #include "config.h"
@@ -18,19 +18,19 @@
18 Th_ErrorMessage(interp, "wrong # args: should be \"", zMsg, -1);
19 return TH_ERROR;
20 }
21
22 /*
23 ** Syntax:
24 **
25 ** catch script ?varname?
26 */
27 static int catch_command(
28 Th_Interp *interp,
29 void *ctx,
30 int argc,
31 const char **argv,
32 int *argl
33 ){
34 int rc;
35
36 if( argc!=2 && argc!=3 ){
@@ -47,19 +47,19 @@
47 Th_SetResultInt(interp, rc);
48 return TH_OK;
49 }
50
51 /*
52 ** TH Syntax:
53 **
54 ** if expr1 body1 ?elseif expr2 body2? ? ?else? bodyN?
55 */
56 static int if_command(
57 Th_Interp *interp,
58 void *ctx,
59 int argc,
60 const char **argv,
61 int *argl
62 ){
63 int rc = TH_OK;
64
65 int iCond; /* Result of evaluating expression */
@@ -94,19 +94,19 @@
94 wrong_args:
95 return Th_WrongNumArgs(interp, "if ...");
96 }
97
98 /*
99 ** TH Syntax:
100 **
101 ** expr expr
102 */
103 static int expr_command(
104 Th_Interp *interp,
105 void *ctx,
106 int argc,
107 const char **argv,
108 int *argl
109 ){
110 if( argc!=2 ){
111 return Th_WrongNumArgs(interp, "expr expression");
112 }
@@ -113,11 +113,11 @@
113
114 return Th_Expr(interp, argv[1], argl[1]);
115 }
116
117 /*
118 ** Evaluate the th1 script (zBody, nBody) in the local stack frame.
119 ** Return the result of the evaluation, except if the result
120 ** is TH_CONTINUE, return TH_OK instead.
121 */
122 static int eval_loopbody(Th_Interp *interp, const char *zBody, int nBody){
123 int rc = Th_Eval(interp, 0, zBody, nBody);
@@ -126,19 +126,19 @@
126 }
127 return rc;
128 }
129
130 /*
131 ** TH Syntax:
132 **
133 ** for init condition incr script
134 */
135 static int for_command(
136 Th_Interp *interp,
137 void *ctx,
138 int argc,
139 const char **argv,
140 int *argl
141 ){
142 int rc;
143 int iCond;
144
@@ -147,11 +147,11 @@
147 }
148
149 /* Evaluate the 'init' script */
150 rc = Th_Eval(interp, 0, argv[1], -1);
151
152 while( rc==TH_OK
153 && TH_OK==(rc = Th_Expr(interp, argv[2], -1))
154 && TH_OK==(rc = Th_ToInt(interp, Th_GetResult(interp, 0), -1, &iCond))
155 && iCond
156 && TH_OK==(rc = eval_loopbody(interp, argv[4], argl[4]))
157 ){
@@ -161,45 +161,45 @@
161 if( rc==TH_BREAK ) rc = TH_OK;
162 return rc;
163 }
164
165 /*
166 ** TH Syntax:
167 **
168 ** list ?arg1 ?arg2? ...?
169 */
170 static int list_command(
171 Th_Interp *interp,
172 void *ctx,
173 int argc,
174 const char **argv,
175 int *argl
176 ){
177 char *zList = 0;
178 int nList = 0;
179 int i;
180
181 for(i=1; i<argc; i++){
182 Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]);
183 }
184
185 Th_SetResult(interp, zList, nList);
186 Th_Free(interp, zList);
187
188 return TH_OK;
189 }
190
191 /*
192 ** TH Syntax:
193 **
194 ** lindex list index
195 */
196 static int lindex_command(
197 Th_Interp *interp,
198 void *ctx,
199 int argc,
200 const char **argv,
201 int *argl
202 ){
203 int iElem;
204 int rc;
205
@@ -227,19 +227,19 @@
227
228 return rc;
229 }
230
231 /*
232 ** TH Syntax:
233 **
234 ** llength list
235 */
236 static int llength_command(
237 Th_Interp *interp,
238 void *ctx,
239 int argc,
240 const char **argv,
241 int *argl
242 ){
243 int nElem;
244 int rc;
245
@@ -254,19 +254,19 @@
254
255 return rc;
256 }
257
258 /*
259 ** TH Syntax:
260 **
261 ** set varname ?value?
262 */
263 static int set_command(
264 Th_Interp *interp,
265 void *ctx,
266 int argc,
267 const char **argv,
268 int *argl
269 ){
270 if( argc!=2 && argc!=3 ){
271 return Th_WrongNumArgs(interp, "set varname ?value?");
272 }
@@ -277,30 +277,30 @@
277 return Th_GetVar(interp, argv[1], argl[1]);
278 }
279
280 /*
281 ** When a new command is created using the built-in [proc] command, an
282 ** instance of the following structure is allocated and populated. A
283 ** pointer to the structure is passed as the context (second) argument
284 ** to function proc_call1() when the new command is executed.
285 */
286 typedef struct ProcDefn ProcDefn;
287 struct ProcDefn {
288 int nParam; /* Number of formal (non "args") parameters */
289 char **azParam; /* Parameter names */
290 int *anParam; /* Lengths of parameter names */
291 char **azDefault; /* Default values */
292 int *anDefault; /* Lengths of default values */
293 int hasArgs; /* True if there is an "args" parameter */
294 char *zProgram; /* Body of proc */
295 int nProgram; /* Number of bytes at zProgram */
296 char *zUsage; /* Usage message */
297 int nUsage; /* Number of bytes at zUsage */
298 };
299
300 /* This structure is used to temporarily store arguments passed to an
301 ** invocation of a command created using [proc]. A pointer to an
302 ** instance is passed as the second argument to the proc_call2() function.
303 */
304 typedef struct ProcArgs ProcArgs;
305 struct ProcArgs {
306 int argc;
@@ -323,11 +323,11 @@
323 ProcArgs *pArgs = (ProcArgs *)pContext2;
324
325 /* Check if there are the right number of arguments. If there are
326 ** not, generate a usage message for the command.
327 */
328 if( (pArgs->argc>(p->nParam+1) && !p->hasArgs)
329 || (pArgs->argc<=(p->nParam) && !p->azDefault[pArgs->argc-1])
330 ){
331 char *zUsage = 0;
332 int nUsage = 0;
333 Th_StringAppend(interp, &zUsage, &nUsage, pArgs->argv[0], pArgs->argl[0]);
@@ -374,12 +374,12 @@
374 ** created using the [proc] command. The second argument, pContext,
375 ** is a pointer to the associated ProcDefn structure.
376 */
377 static int proc_call1(
378 Th_Interp *interp,
379 void *pContext,
380 int argc,
381 const char **argv,
382 int *argl
383 ){
384 int rc;
385
@@ -400,32 +400,32 @@
400 }
401 return rc;
402 }
403
404 /*
405 ** This function is registered as the delete callback for all commands
406 ** created using the built-in [proc] command. It is called automatically
407 ** when a command created using [proc] is deleted.
408 **
409 ** It frees the ProcDefn structure allocated when the command was created.
410 */
411 static void proc_del(Th_Interp *interp, void *pContext){
412 ProcDefn *p = (ProcDefn *)pContext;
413 Th_Free(interp, (void *)p->zUsage);
414 Th_Free(interp, (void *)p);
415 }
416
417 /*
418 ** TH Syntax:
419 **
420 ** proc name arglist code
421 */
422 static int proc_command(
423 Th_Interp *interp,
424 void *ctx,
425 int argc,
426 const char **argv,
427 int *argl
428 ){
429 int rc;
430 char *zName;
431
@@ -436,11 +436,11 @@
436
437 char **azParam;
438 int *anParam;
439 int nParam;
440
441 char *zUsage = 0; /* Build up a usage message here */
442 int nUsage = 0; /* Number of bytes at zUsage */
443
444 if( argc!=4 ){
445 return Th_WrongNumArgs(interp, "proc name arglist code");
446 }
@@ -448,14 +448,14 @@
448 return TH_ERROR;
449 }
450
451 /* Allocate the new ProcDefn structure. */
452 nByte = sizeof(ProcDefn) + /* ProcDefn structure */
453 (sizeof(char *) + sizeof(int)) * nParam + /* azParam, anParam */
454 (sizeof(char *) + sizeof(int)) * nParam + /* azDefault, anDefault */
455 argl[3] + /* zProgram */
456 argl[2]; /* Space for copies of parameter names and default values */
457 p = (ProcDefn *)Th_Malloc(interp, nByte);
458
459 /* If the last parameter in the parameter list is "args", then set the
460 ** ProcDefn.hasArgs flag. The "args" parameter does not require an
461 ** entry in the ProcDefn.azParam[] or ProcDefn.azDefault[] arrays.
@@ -472,11 +472,11 @@
472 p->anDefault = (int *)&p->azDefault[nParam];
473 p->zProgram = (char *)&p->anDefault[nParam];
474 memcpy(p->zProgram, argv[3], argl[3]);
475 p->nProgram = argl[3];
476 zSpace = &p->zProgram[p->nProgram];
477
478 for(i=0; i<nParam; i++){
479 char **az;
480 int *an;
481 int n;
482 if( Th_SplitList(interp, azParam[i], anParam[i], &az, &an, &n) ){
@@ -537,40 +537,40 @@
537 Th_Free(interp, zUsage);
538 return TH_ERROR;
539 }
540
541 /*
542 ** TH Syntax:
543 **
544 ** rename oldcmd newcmd
545 */
546 static int rename_command(
547 Th_Interp *interp,
548 void *ctx,
549 int argc,
550 const char **argv,
551 int *argl
552 ){
553 if( argc!=3 ){
554 return Th_WrongNumArgs(interp, "rename oldcmd newcmd");
555 }
556 return Th_RenameCommand(interp, argv[1], argl[1], argv[2], argl[2]);
557 }
558
559 /*
560 ** TH Syntax:
561 **
562 ** break ?value...?
563 ** continue ?value...?
564 ** ok ?value...?
565 ** error ?value...?
566 */
567 static int simple_command(
568 Th_Interp *interp,
569 void *ctx,
570 int argc,
571 const char **argv,
572 int *argl
573 ){
574 if( argc!=1 && argc!=2 ){
575 return Th_WrongNumArgs(interp, "return ?value?");
576 }
@@ -579,19 +579,19 @@
579 }
580 return FOSSIL_PTR_TO_INT(ctx);
581 }
582
583 /*
584 ** TH Syntax:
585 **
586 ** return ?-code code? ?value?
587 */
588 static int return_command(
589 Th_Interp *interp,
590 void *ctx,
591 int argc,
592 const char **argv,
593 int *argl
594 ){
595 int iCode = TH_RETURN;
596 if( argc<1 || argc>4 ){
597 return Th_WrongNumArgs(interp, "return ?-code code? ?value?");
@@ -638,11 +638,11 @@
638 iRes = nLeft-nRight;
639 }
640
641 if( iRes<0 ) iRes = -1;
642 if( iRes>0 ) iRes = 1;
643
644 return Th_SetResultInt(interp, iRes);
645 }
646
647 /*
648 ** TH Syntax:
@@ -672,11 +672,11 @@
672 if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){
673 iRes = i;
674 break;
675 }
676 }
677
678 return Th_SetResultInt(interp, iRes);
679 }
680
681 /*
682 ** TH Syntax:
@@ -733,11 +733,11 @@
733 if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){
734 iRes = i;
735 break;
736 }
737 }
738
739 return Th_SetResultInt(interp, iRes);
740 }
741
742 /*
743 ** TH Syntax:
@@ -867,11 +867,11 @@
867 ** TH Syntax:
868 **
869 ** unset VAR
870 */
871 static int unset_command(
872 Th_Interp *interp,
873 void *ctx,
874 int argc,
875 const char **argv,
876 int *argl
877 ){
@@ -880,11 +880,11 @@
880 }
881 return Th_UnsetVar(interp, argv[1], argl[1]);
882 }
883
884 int Th_CallSubCommand(
885 Th_Interp *interp,
886 void *ctx,
887 int argc,
888 const char **argv,
889 int *argl,
890 Th_SubCommand *aSub
@@ -916,11 +916,11 @@
916 ** string length STRING
917 ** string range STRING FIRST LAST
918 ** string repeat STRING COUNT
919 */
920 static int string_command(
921 Th_Interp *interp,
922 void *ctx,
923 int argc,
924 const char **argv,
925 int *argl
926 ){
@@ -944,11 +944,11 @@
944 ** TH Syntax:
945 **
946 ** info exists VARNAME
947 */
948 static int info_command(
949 Th_Interp *interp,
950 void *ctx,
951 int argc,
952 const char **argv,
953 int *argl
954 ){
@@ -958,20 +958,20 @@
958 };
959 return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
960 }
961
962 /*
963 ** Convert the script level frame specification (used by the commands
964 ** [uplevel] and [upvar]) in (zFrame, nFrame) to an integer frame as
965 ** used by Th_LinkVar() and Th_Eval(). If successful, write the integer
966 ** frame level to *piFrame and return TH_OK. Otherwise, return TH_ERROR
967 ** and leave an error message in the interpreter result.
968 */
969 static int thToFrame(
970 Th_Interp *interp,
971 const char *zFrame,
972 int nFrame,
973 int *piFrame
974 ){
975 int iFrame;
976 if( th_isdigit(zFrame[0]) ){
977 int rc = Th_ToInt(interp, zFrame, nFrame, &iFrame);
@@ -992,11 +992,11 @@
992 ** TH Syntax:
993 **
994 ** uplevel ?LEVEL? SCRIPT
995 */
996 static int uplevel_command(
997 Th_Interp *interp,
998 void *ctx,
999 int argc,
1000 const char **argv,
1001 int *argl
1002 ){
@@ -1010,19 +1010,19 @@
1010 }
1011 return Th_Eval(interp, iFrame, argv[argc-1], -1);
1012 }
1013
1014 /*
1015 ** TH Syntax:
1016 **
1017 ** upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR ...?
1018 */
1019 static int upvar_command(
1020 Th_Interp *interp,
1021 void *ctx,
1022 int argc,
1023 const char **argv,
1024 int *argl
1025 ){
1026 int iVar = 1;
1027 int iFrame = -1;
1028 int rc = TH_OK;
@@ -1030,32 +1030,32 @@
1030
1031 if( TH_OK==thToFrame(0, argv[1], argl[1], &iFrame) ){
1032 iVar++;
1033 }
1034 if( argc==iVar || (argc-iVar)%2 ){
1035 return Th_WrongNumArgs(interp,
1036 "upvar frame othervar myvar ?othervar myvar...?");
1037 }
1038 for(i=iVar; rc==TH_OK && i<argc; i=i+2){
1039 rc = Th_LinkVar(interp, argv[i+1], argl[i+1], iFrame, argv[i], argl[i]);
1040 }
1041 return rc;
1042 }
1043
1044 /*
1045 ** TH Syntax:
1046 **
1047 ** breakpoint ARGS
1048 **
1049 ** This command does nothing at all. Its purpose in life is to serve
1050 ** as a point for setting breakpoints in a debugger.
1051 */
1052 static int breakpoint_command(
1053 Th_Interp *interp,
1054 void *ctx,
1055 int argc,
1056 const char **argv,
1057 int *argl
1058 ){
1059 int cnt = 0;
1060 cnt++;
1061 return TH_OK;
@@ -1078,11 +1078,11 @@
1078 {"if", if_command, 0},
1079 {"info", info_command, 0},
1080 {"lindex", lindex_command, 0},
1081 {"list", list_command, 0},
1082 {"llength", llength_command, 0},
1083 {"proc", proc_command, 0},
1084 {"rename", rename_command, 0},
1085 {"set", set_command, 0},
1086 {"string", string_command, 0},
1087 {"unset", unset_command, 0},
1088 {"uplevel", uplevel_command, 0},
@@ -1089,13 +1089,13 @@
1089 {"upvar", upvar_command, 0},
1090
1091 {"breakpoint", breakpoint_command, 0},
1092
1093 {"return", return_command, 0},
1094 {"break", simple_command, (void *)TH_BREAK},
1095 {"continue", simple_command, (void *)TH_CONTINUE},
1096 {"error", simple_command, (void *)TH_ERROR},
1097
1098 {0, 0, 0}
1099 };
1100 int i;
1101
1102
--- src/th_lang.c
+++ src/th_lang.c
@@ -1,12 +1,12 @@
1
2 /*
3 ** This file contains the implementation of all of the TH language
4 ** built-in commands.
5 **
6 ** All built-in commands are implemented using the public interface
7 ** declared in th.h, so this file serves as both a part of the language
8 ** implementation and an example of how to extend the language with
9 ** new commands.
10 */
11
12 #include "config.h"
@@ -18,19 +18,19 @@
18 Th_ErrorMessage(interp, "wrong # args: should be \"", zMsg, -1);
19 return TH_ERROR;
20 }
21
22 /*
23 ** Syntax:
24 **
25 ** catch script ?varname?
26 */
27 static int catch_command(
28 Th_Interp *interp,
29 void *ctx,
30 int argc,
31 const char **argv,
32 int *argl
33 ){
34 int rc;
35
36 if( argc!=2 && argc!=3 ){
@@ -47,19 +47,19 @@
47 Th_SetResultInt(interp, rc);
48 return TH_OK;
49 }
50
51 /*
52 ** TH Syntax:
53 **
54 ** if expr1 body1 ?elseif expr2 body2? ? ?else? bodyN?
55 */
56 static int if_command(
57 Th_Interp *interp,
58 void *ctx,
59 int argc,
60 const char **argv,
61 int *argl
62 ){
63 int rc = TH_OK;
64
65 int iCond; /* Result of evaluating expression */
@@ -94,19 +94,19 @@
94 wrong_args:
95 return Th_WrongNumArgs(interp, "if ...");
96 }
97
98 /*
99 ** TH Syntax:
100 **
101 ** expr expr
102 */
103 static int expr_command(
104 Th_Interp *interp,
105 void *ctx,
106 int argc,
107 const char **argv,
108 int *argl
109 ){
110 if( argc!=2 ){
111 return Th_WrongNumArgs(interp, "expr expression");
112 }
@@ -113,11 +113,11 @@
113
114 return Th_Expr(interp, argv[1], argl[1]);
115 }
116
117 /*
118 ** Evaluate the th1 script (zBody, nBody) in the local stack frame.
119 ** Return the result of the evaluation, except if the result
120 ** is TH_CONTINUE, return TH_OK instead.
121 */
122 static int eval_loopbody(Th_Interp *interp, const char *zBody, int nBody){
123 int rc = Th_Eval(interp, 0, zBody, nBody);
@@ -126,19 +126,19 @@
126 }
127 return rc;
128 }
129
130 /*
131 ** TH Syntax:
132 **
133 ** for init condition incr script
134 */
135 static int for_command(
136 Th_Interp *interp,
137 void *ctx,
138 int argc,
139 const char **argv,
140 int *argl
141 ){
142 int rc;
143 int iCond;
144
@@ -147,11 +147,11 @@
147 }
148
149 /* Evaluate the 'init' script */
150 rc = Th_Eval(interp, 0, argv[1], -1);
151
152 while( rc==TH_OK
153 && TH_OK==(rc = Th_Expr(interp, argv[2], -1))
154 && TH_OK==(rc = Th_ToInt(interp, Th_GetResult(interp, 0), -1, &iCond))
155 && iCond
156 && TH_OK==(rc = eval_loopbody(interp, argv[4], argl[4]))
157 ){
@@ -161,45 +161,45 @@
161 if( rc==TH_BREAK ) rc = TH_OK;
162 return rc;
163 }
164
165 /*
166 ** TH Syntax:
167 **
168 ** list ?arg1 ?arg2? ...?
169 */
170 static int list_command(
171 Th_Interp *interp,
172 void *ctx,
173 int argc,
174 const char **argv,
175 int *argl
176 ){
177 char *zList = 0;
178 int nList = 0;
179 int i;
180
181 for(i=1; i<argc; i++){
182 Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]);
183 }
184
185 Th_SetResult(interp, zList, nList);
186 Th_Free(interp, zList);
187
188 return TH_OK;
189 }
190
191 /*
192 ** TH Syntax:
193 **
194 ** lindex list index
195 */
196 static int lindex_command(
197 Th_Interp *interp,
198 void *ctx,
199 int argc,
200 const char **argv,
201 int *argl
202 ){
203 int iElem;
204 int rc;
205
@@ -227,19 +227,19 @@
227
228 return rc;
229 }
230
231 /*
232 ** TH Syntax:
233 **
234 ** llength list
235 */
236 static int llength_command(
237 Th_Interp *interp,
238 void *ctx,
239 int argc,
240 const char **argv,
241 int *argl
242 ){
243 int nElem;
244 int rc;
245
@@ -254,19 +254,19 @@
254
255 return rc;
256 }
257
258 /*
259 ** TH Syntax:
260 **
261 ** set varname ?value?
262 */
263 static int set_command(
264 Th_Interp *interp,
265 void *ctx,
266 int argc,
267 const char **argv,
268 int *argl
269 ){
270 if( argc!=2 && argc!=3 ){
271 return Th_WrongNumArgs(interp, "set varname ?value?");
272 }
@@ -277,30 +277,30 @@
277 return Th_GetVar(interp, argv[1], argl[1]);
278 }
279
280 /*
281 ** When a new command is created using the built-in [proc] command, an
282 ** instance of the following structure is allocated and populated. A
283 ** pointer to the structure is passed as the context (second) argument
284 ** to function proc_call1() when the new command is executed.
285 */
286 typedef struct ProcDefn ProcDefn;
287 struct ProcDefn {
288 int nParam; /* Number of formal (non "args") parameters */
289 char **azParam; /* Parameter names */
290 int *anParam; /* Lengths of parameter names */
291 char **azDefault; /* Default values */
292 int *anDefault; /* Lengths of default values */
293 int hasArgs; /* True if there is an "args" parameter */
294 char *zProgram; /* Body of proc */
295 int nProgram; /* Number of bytes at zProgram */
296 char *zUsage; /* Usage message */
297 int nUsage; /* Number of bytes at zUsage */
298 };
299
300 /* This structure is used to temporarily store arguments passed to an
301 ** invocation of a command created using [proc]. A pointer to an
302 ** instance is passed as the second argument to the proc_call2() function.
303 */
304 typedef struct ProcArgs ProcArgs;
305 struct ProcArgs {
306 int argc;
@@ -323,11 +323,11 @@
323 ProcArgs *pArgs = (ProcArgs *)pContext2;
324
325 /* Check if there are the right number of arguments. If there are
326 ** not, generate a usage message for the command.
327 */
328 if( (pArgs->argc>(p->nParam+1) && !p->hasArgs)
329 || (pArgs->argc<=(p->nParam) && !p->azDefault[pArgs->argc-1])
330 ){
331 char *zUsage = 0;
332 int nUsage = 0;
333 Th_StringAppend(interp, &zUsage, &nUsage, pArgs->argv[0], pArgs->argl[0]);
@@ -374,12 +374,12 @@
374 ** created using the [proc] command. The second argument, pContext,
375 ** is a pointer to the associated ProcDefn structure.
376 */
377 static int proc_call1(
378 Th_Interp *interp,
379 void *pContext,
380 int argc,
381 const char **argv,
382 int *argl
383 ){
384 int rc;
385
@@ -400,32 +400,32 @@
400 }
401 return rc;
402 }
403
404 /*
405 ** This function is registered as the delete callback for all commands
406 ** created using the built-in [proc] command. It is called automatically
407 ** when a command created using [proc] is deleted.
408 **
409 ** It frees the ProcDefn structure allocated when the command was created.
410 */
411 static void proc_del(Th_Interp *interp, void *pContext){
412 ProcDefn *p = (ProcDefn *)pContext;
413 Th_Free(interp, (void *)p->zUsage);
414 Th_Free(interp, (void *)p);
415 }
416
417 /*
418 ** TH Syntax:
419 **
420 ** proc name arglist code
421 */
422 static int proc_command(
423 Th_Interp *interp,
424 void *ctx,
425 int argc,
426 const char **argv,
427 int *argl
428 ){
429 int rc;
430 char *zName;
431
@@ -436,11 +436,11 @@
436
437 char **azParam;
438 int *anParam;
439 int nParam;
440
441 char *zUsage = 0; /* Build up a usage message here */
442 int nUsage = 0; /* Number of bytes at zUsage */
443
444 if( argc!=4 ){
445 return Th_WrongNumArgs(interp, "proc name arglist code");
446 }
@@ -448,14 +448,14 @@
448 return TH_ERROR;
449 }
450
451 /* Allocate the new ProcDefn structure. */
452 nByte = sizeof(ProcDefn) + /* ProcDefn structure */
453 (sizeof(char *) + sizeof(int)) * nParam + /* azParam, anParam */
454 (sizeof(char *) + sizeof(int)) * nParam + /* azDefault, anDefault */
455 argl[3] + /* zProgram */
456 argl[2]; /* Space for copies of parameter names and default values */
457 p = (ProcDefn *)Th_Malloc(interp, nByte);
458
459 /* If the last parameter in the parameter list is "args", then set the
460 ** ProcDefn.hasArgs flag. The "args" parameter does not require an
461 ** entry in the ProcDefn.azParam[] or ProcDefn.azDefault[] arrays.
@@ -472,11 +472,11 @@
472 p->anDefault = (int *)&p->azDefault[nParam];
473 p->zProgram = (char *)&p->anDefault[nParam];
474 memcpy(p->zProgram, argv[3], argl[3]);
475 p->nProgram = argl[3];
476 zSpace = &p->zProgram[p->nProgram];
477
478 for(i=0; i<nParam; i++){
479 char **az;
480 int *an;
481 int n;
482 if( Th_SplitList(interp, azParam[i], anParam[i], &az, &an, &n) ){
@@ -537,40 +537,40 @@
537 Th_Free(interp, zUsage);
538 return TH_ERROR;
539 }
540
541 /*
542 ** TH Syntax:
543 **
544 ** rename oldcmd newcmd
545 */
546 static int rename_command(
547 Th_Interp *interp,
548 void *ctx,
549 int argc,
550 const char **argv,
551 int *argl
552 ){
553 if( argc!=3 ){
554 return Th_WrongNumArgs(interp, "rename oldcmd newcmd");
555 }
556 return Th_RenameCommand(interp, argv[1], argl[1], argv[2], argl[2]);
557 }
558
559 /*
560 ** TH Syntax:
561 **
562 ** break ?value...?
563 ** continue ?value...?
564 ** ok ?value...?
565 ** error ?value...?
566 */
567 static int simple_command(
568 Th_Interp *interp,
569 void *ctx,
570 int argc,
571 const char **argv,
572 int *argl
573 ){
574 if( argc!=1 && argc!=2 ){
575 return Th_WrongNumArgs(interp, "return ?value?");
576 }
@@ -579,19 +579,19 @@
579 }
580 return FOSSIL_PTR_TO_INT(ctx);
581 }
582
583 /*
584 ** TH Syntax:
585 **
586 ** return ?-code code? ?value?
587 */
588 static int return_command(
589 Th_Interp *interp,
590 void *ctx,
591 int argc,
592 const char **argv,
593 int *argl
594 ){
595 int iCode = TH_RETURN;
596 if( argc<1 || argc>4 ){
597 return Th_WrongNumArgs(interp, "return ?-code code? ?value?");
@@ -638,11 +638,11 @@
638 iRes = nLeft-nRight;
639 }
640
641 if( iRes<0 ) iRes = -1;
642 if( iRes>0 ) iRes = 1;
643
644 return Th_SetResultInt(interp, iRes);
645 }
646
647 /*
648 ** TH Syntax:
@@ -672,11 +672,11 @@
672 if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){
673 iRes = i;
674 break;
675 }
676 }
677
678 return Th_SetResultInt(interp, iRes);
679 }
680
681 /*
682 ** TH Syntax:
@@ -733,11 +733,11 @@
733 if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){
734 iRes = i;
735 break;
736 }
737 }
738
739 return Th_SetResultInt(interp, iRes);
740 }
741
742 /*
743 ** TH Syntax:
@@ -867,11 +867,11 @@
867 ** TH Syntax:
868 **
869 ** unset VAR
870 */
871 static int unset_command(
872 Th_Interp *interp,
873 void *ctx,
874 int argc,
875 const char **argv,
876 int *argl
877 ){
@@ -880,11 +880,11 @@
880 }
881 return Th_UnsetVar(interp, argv[1], argl[1]);
882 }
883
884 int Th_CallSubCommand(
885 Th_Interp *interp,
886 void *ctx,
887 int argc,
888 const char **argv,
889 int *argl,
890 Th_SubCommand *aSub
@@ -916,11 +916,11 @@
916 ** string length STRING
917 ** string range STRING FIRST LAST
918 ** string repeat STRING COUNT
919 */
920 static int string_command(
921 Th_Interp *interp,
922 void *ctx,
923 int argc,
924 const char **argv,
925 int *argl
926 ){
@@ -944,11 +944,11 @@
944 ** TH Syntax:
945 **
946 ** info exists VARNAME
947 */
948 static int info_command(
949 Th_Interp *interp,
950 void *ctx,
951 int argc,
952 const char **argv,
953 int *argl
954 ){
@@ -958,20 +958,20 @@
958 };
959 return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
960 }
961
962 /*
963 ** Convert the script level frame specification (used by the commands
964 ** [uplevel] and [upvar]) in (zFrame, nFrame) to an integer frame as
965 ** used by Th_LinkVar() and Th_Eval(). If successful, write the integer
966 ** frame level to *piFrame and return TH_OK. Otherwise, return TH_ERROR
967 ** and leave an error message in the interpreter result.
968 */
969 static int thToFrame(
970 Th_Interp *interp,
971 const char *zFrame,
972 int nFrame,
973 int *piFrame
974 ){
975 int iFrame;
976 if( th_isdigit(zFrame[0]) ){
977 int rc = Th_ToInt(interp, zFrame, nFrame, &iFrame);
@@ -992,11 +992,11 @@
992 ** TH Syntax:
993 **
994 ** uplevel ?LEVEL? SCRIPT
995 */
996 static int uplevel_command(
997 Th_Interp *interp,
998 void *ctx,
999 int argc,
1000 const char **argv,
1001 int *argl
1002 ){
@@ -1010,19 +1010,19 @@
1010 }
1011 return Th_Eval(interp, iFrame, argv[argc-1], -1);
1012 }
1013
1014 /*
1015 ** TH Syntax:
1016 **
1017 ** upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR ...?
1018 */
1019 static int upvar_command(
1020 Th_Interp *interp,
1021 void *ctx,
1022 int argc,
1023 const char **argv,
1024 int *argl
1025 ){
1026 int iVar = 1;
1027 int iFrame = -1;
1028 int rc = TH_OK;
@@ -1030,32 +1030,32 @@
1030
1031 if( TH_OK==thToFrame(0, argv[1], argl[1], &iFrame) ){
1032 iVar++;
1033 }
1034 if( argc==iVar || (argc-iVar)%2 ){
1035 return Th_WrongNumArgs(interp,
1036 "upvar frame othervar myvar ?othervar myvar...?");
1037 }
1038 for(i=iVar; rc==TH_OK && i<argc; i=i+2){
1039 rc = Th_LinkVar(interp, argv[i+1], argl[i+1], iFrame, argv[i], argl[i]);
1040 }
1041 return rc;
1042 }
1043
1044 /*
1045 ** TH Syntax:
1046 **
1047 ** breakpoint ARGS
1048 **
1049 ** This command does nothing at all. Its purpose in life is to serve
1050 ** as a point for setting breakpoints in a debugger.
1051 */
1052 static int breakpoint_command(
1053 Th_Interp *interp,
1054 void *ctx,
1055 int argc,
1056 const char **argv,
1057 int *argl
1058 ){
1059 int cnt = 0;
1060 cnt++;
1061 return TH_OK;
@@ -1078,11 +1078,11 @@
1078 {"if", if_command, 0},
1079 {"info", info_command, 0},
1080 {"lindex", lindex_command, 0},
1081 {"list", list_command, 0},
1082 {"llength", llength_command, 0},
1083 {"proc", proc_command, 0},
1084 {"rename", rename_command, 0},
1085 {"set", set_command, 0},
1086 {"string", string_command, 0},
1087 {"unset", unset_command, 0},
1088 {"uplevel", uplevel_command, 0},
@@ -1089,13 +1089,13 @@
1089 {"upvar", upvar_command, 0},
1090
1091 {"breakpoint", breakpoint_command, 0},
1092
1093 {"return", return_command, 0},
1094 {"break", simple_command, (void *)TH_BREAK},
1095 {"continue", simple_command, (void *)TH_CONTINUE},
1096 {"error", simple_command, (void *)TH_ERROR},
1097
1098 {0, 0, 0}
1099 };
1100 int i;
1101
1102
--- test/th1.test
+++ test/th1.test
@@ -147,5 +147,10 @@
147147
148148
###############################################################################
149149
150150
fossil test-th-eval "unset var"
151151
test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}}
152
+
153
+###############################################################################
154
+
155
+fossil test-th-eval "set var 1; unset var; unset var"
156
+test th1-unset-3 {$RESULT eq {TH_ERROR: no such variable: var}}
152157
--- test/th1.test
+++ test/th1.test
@@ -147,5 +147,10 @@
147
148 ###############################################################################
149
150 fossil test-th-eval "unset var"
151 test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}}
 
 
 
 
 
152
--- test/th1.test
+++ test/th1.test
@@ -147,5 +147,10 @@
147
148 ###############################################################################
149
150 fossil test-th-eval "unset var"
151 test th1-unset-2 {$RESULT eq {TH_ERROR: no such variable: var}}
152
153 ###############################################################################
154
155 fossil test-th-eval "set var 1; unset var; unset var"
156 test th1-unset-3 {$RESULT eq {TH_ERROR: no such variable: var}}
157

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button