4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** This file contains the implementation of all of the TH language 4ee9e31a2d 2008-02-13 drh: ** built-in commands. 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** All built-in commands are implemented using the public interface 4ee9e31a2d 2008-02-13 drh: ** declared in th.h, so this file serves as both a part of the language 4ee9e31a2d 2008-02-13 drh: ** implementation and an example of how to extend the language with 4ee9e31a2d 2008-02-13 drh: ** new commands. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: #include "th.h" 4ee9e31a2d 2008-02-13 drh: #include <string.h> 4ee9e31a2d 2008-02-13 drh: #include <assert.h> 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg){ 4ee9e31a2d 2008-02-13 drh: Th_ErrorMessage(interp, 4ee9e31a2d 2008-02-13 drh: "wrong # args: should be \"", (const uchar*)zMsg, -1 4ee9e31a2d 2008-02-13 drh: ); 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** catch script ?varname? 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int catch_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int rc; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=2 && argc!=3 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "catch script ?varname?"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: rc = Th_Eval(interp, 0, argv[1], -1); 4ee9e31a2d 2008-02-13 drh: if( argc==3 ){ 4ee9e31a2d 2008-02-13 drh: int nResult; 4ee9e31a2d 2008-02-13 drh: const uchar *zResult = Th_GetResult(interp, &nResult); 4ee9e31a2d 2008-02-13 drh: Th_SetVar(interp, argv[2], argl[2], zResult, nResult); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_SetResultInt(interp, rc); 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** if expr1 body1 ?elseif expr2 body2? ? ?else? bodyN? 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int if_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int rc = TH_OK; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: int iCond; /* Result of evaluating expression */ 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: const uchar *zResult; 4ee9e31a2d 2008-02-13 drh: int nResult; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc<3 ){ 4ee9e31a2d 2008-02-13 drh: goto wrong_args; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: for(i=0; i<argc && rc==TH_OK; i+=3){ 4ee9e31a2d 2008-02-13 drh: if( i>argc-3 ){ 4ee9e31a2d 2008-02-13 drh: i = argc-3; 4ee9e31a2d 2008-02-13 drh: iCond = 1; 4ee9e31a2d 2008-02-13 drh: }else{ 4ee9e31a2d 2008-02-13 drh: if( TH_OK!=Th_Expr(interp, argv[i+1], argl[i+1]) ){ 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: zResult = Th_GetResult(interp, &nResult); 4ee9e31a2d 2008-02-13 drh: rc = Th_ToInt(interp, zResult, nResult, &iCond); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( iCond && rc==TH_OK ){ 4ee9e31a2d 2008-02-13 drh: rc = Th_Eval(interp, 0, argv[i+2], -1); 4ee9e31a2d 2008-02-13 drh: break; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: wrong_args: 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "if ..."); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** expr expr 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int expr_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: if( argc!=2 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "expr expression"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return Th_Expr(interp, argv[1], argl[1]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** Evaluate the th1 script (zBody, nBody) in the local stack frame. 4ee9e31a2d 2008-02-13 drh: ** Return the result of the evaluation, except if the result 4ee9e31a2d 2008-02-13 drh: ** is TH_CONTINUE, return TH_OK instead. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int eval_loopbody(Th_Interp *interp, const uchar *zBody, int nBody){ 4ee9e31a2d 2008-02-13 drh: int rc = Th_Eval(interp, 0, zBody, nBody); 4ee9e31a2d 2008-02-13 drh: if( rc==TH_CONTINUE ){ 4ee9e31a2d 2008-02-13 drh: rc = TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** for init condition incr script 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int for_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int rc; 4ee9e31a2d 2008-02-13 drh: int iCond; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=5 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "for init condition incr script"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Evaluate the 'init' script */ 4ee9e31a2d 2008-02-13 drh: rc = Th_Eval(interp, 0, argv[1], -1); 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: while( rc==TH_OK 4ee9e31a2d 2008-02-13 drh: && TH_OK==(rc = Th_Expr(interp, argv[2], -1)) 4ee9e31a2d 2008-02-13 drh: && TH_OK==(rc = Th_ToInt(interp, Th_GetResult(interp, 0), -1, &iCond)) 4ee9e31a2d 2008-02-13 drh: && iCond 4ee9e31a2d 2008-02-13 drh: && TH_OK==(rc = eval_loopbody(interp, argv[4], argl[4])) 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: rc = Th_Eval(interp, 0, argv[3], -1); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( rc==TH_BREAK ) rc = TH_OK; 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** list ?arg1 ?arg2? ...? 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int list_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: uchar *zList = 0; 4ee9e31a2d 2008-02-13 drh: int nList = 0; 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: for(i=1; i<argc; i++){ 4ee9e31a2d 2008-02-13 drh: Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, zList, nList); 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, zList); 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** lindex list index 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int lindex_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int iElem; 4ee9e31a2d 2008-02-13 drh: int rc; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: uchar **azElem; 4ee9e31a2d 2008-02-13 drh: int *anElem; 4ee9e31a2d 2008-02-13 drh: int nCount; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=3 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "lindex list index"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( TH_OK!=Th_ToInt(interp, argv[2], argl[2], &iElem) ){ 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: rc = Th_SplitList(interp, argv[1], argl[1], &azElem, &anElem, &nCount); 4ee9e31a2d 2008-02-13 drh: if( rc==TH_OK ){ 4ee9e31a2d 2008-02-13 drh: if( iElem<nCount && iElem>=0 ){ 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, azElem[iElem], anElem[iElem]); 4ee9e31a2d 2008-02-13 drh: }else{ 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, 0, 0); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, azElem); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** llength list 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int llength_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int nElem; 4ee9e31a2d 2008-02-13 drh: int rc; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=2 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "llength list"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: rc = Th_SplitList(interp, argv[1], argl[1], 0, 0, &nElem); 4ee9e31a2d 2008-02-13 drh: if( rc==TH_OK ){ 4ee9e31a2d 2008-02-13 drh: Th_SetResultInt(interp, nElem); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** set varname ?value? 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int set_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: if( argc!=2 && argc!=3 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "set varname ?value?"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc==3 ){ 4ee9e31a2d 2008-02-13 drh: Th_SetVar(interp, argv[1], argl[1], argv[2], argl[2]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return Th_GetVar(interp, argv[1], argl[1]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** When a new command is created using the built-in [proc] command, an 4ee9e31a2d 2008-02-13 drh: ** instance of the following structure is allocated and populated. A 4ee9e31a2d 2008-02-13 drh: ** pointer to the structure is passed as the context (second) argument 4ee9e31a2d 2008-02-13 drh: ** to function proc_call1() when the new command is executed. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: typedef struct ProcDefn ProcDefn; 4ee9e31a2d 2008-02-13 drh: struct ProcDefn { 4ee9e31a2d 2008-02-13 drh: int nParam; /* Number of formal (non "args") parameters */ 4ee9e31a2d 2008-02-13 drh: uchar **azParam; /* Parameter names */ 4ee9e31a2d 2008-02-13 drh: int *anParam; /* Lengths of parameter names */ 4ee9e31a2d 2008-02-13 drh: uchar **azDefault; /* Default values */ 4ee9e31a2d 2008-02-13 drh: int *anDefault; /* Lengths of default values */ 4ee9e31a2d 2008-02-13 drh: int hasArgs; /* True if there is an "args" parameter */ 4ee9e31a2d 2008-02-13 drh: uchar *zProgram; /* Body of proc */ 4ee9e31a2d 2008-02-13 drh: int nProgram; /* Number of bytes at zProgram */ 4ee9e31a2d 2008-02-13 drh: uchar *zUsage; /* Usage message */ 4ee9e31a2d 2008-02-13 drh: int nUsage; /* Number of bytes at zUsage */ 4ee9e31a2d 2008-02-13 drh: }; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* This structure is used to temporarily store arguments passed to an 4ee9e31a2d 2008-02-13 drh: ** invocation of a command created using [proc]. A pointer to an 4ee9e31a2d 2008-02-13 drh: ** instance is passed as the second argument to the proc_call2() function. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: typedef struct ProcArgs ProcArgs; 4ee9e31a2d 2008-02-13 drh: struct ProcArgs { 4ee9e31a2d 2008-02-13 drh: int argc; 4ee9e31a2d 2008-02-13 drh: const uchar **argv; 4ee9e31a2d 2008-02-13 drh: int *argl; 4ee9e31a2d 2008-02-13 drh: }; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** Each time a command created using [proc] is invoked, a new 4ee9e31a2d 2008-02-13 drh: ** th1 stack frame is allocated (for the proc's local variables) and 4ee9e31a2d 2008-02-13 drh: ** this function invoked. 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** Argument pContext1 points to the associated ProcDefn structure. 4ee9e31a2d 2008-02-13 drh: ** Argument pContext2 points to a ProcArgs structure that contains 4ee9e31a2d 2008-02-13 drh: ** the arguments passed to this specific invocation of the proc. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int proc_call2(Th_Interp *interp, void *pContext1, void *pContext2){ 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: ProcDefn *p = (ProcDefn *)pContext1; 4ee9e31a2d 2008-02-13 drh: ProcArgs *pArgs = (ProcArgs *)pContext2; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Check if there are the right number of arguments. If there are 4ee9e31a2d 2008-02-13 drh: ** not, generate a usage message for the command. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: if( (pArgs->argc>(p->nParam+1) && !p->hasArgs) 4ee9e31a2d 2008-02-13 drh: || (pArgs->argc<=(p->nParam) && !p->azDefault[pArgs->argc-1]) 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: uchar *zUsage = 0; 4ee9e31a2d 2008-02-13 drh: int nUsage = 0; 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, pArgs->argv[0], pArgs->argl[0]); 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, p->zUsage, p->nUsage); 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)"", 1); 4ee9e31a2d 2008-02-13 drh: Th_WrongNumArgs(interp, zUsage); 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, zUsage); 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Populate the formal proc parameters. */ 4ee9e31a2d 2008-02-13 drh: for(i=0; i<p->nParam; i++){ 4ee9e31a2d 2008-02-13 drh: const uchar *zVal; 4ee9e31a2d 2008-02-13 drh: int nVal; 4ee9e31a2d 2008-02-13 drh: if( pArgs->argc>(i+1) ){ 4ee9e31a2d 2008-02-13 drh: zVal = pArgs->argv[i+1]; 4ee9e31a2d 2008-02-13 drh: nVal = pArgs->argl[i+1]; 4ee9e31a2d 2008-02-13 drh: }else{ 4ee9e31a2d 2008-02-13 drh: zVal = p->azDefault[i]; 4ee9e31a2d 2008-02-13 drh: nVal = p->anDefault[i]; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: Th_SetVar(interp, p->azParam[i], p->anParam[i], zVal, nVal); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Populate the "args" parameter, if it exists */ 4ee9e31a2d 2008-02-13 drh: if( p->hasArgs ){ 4ee9e31a2d 2008-02-13 drh: uchar *zArgs = 0; 4ee9e31a2d 2008-02-13 drh: int nArgs = 0; 4ee9e31a2d 2008-02-13 drh: for(i=p->nParam+1; i<pArgs->argc; i++){ 4ee9e31a2d 2008-02-13 drh: Th_ListAppend(interp, &zArgs, &nArgs, pArgs->argv[i], pArgs->argl[i]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: Th_SetVar(interp, (const uchar *)"args", -1, zArgs, nArgs); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, 0, 0); 4ee9e31a2d 2008-02-13 drh: return Th_Eval(interp, 0, p->zProgram, p->nProgram); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** This function is the command callback registered for all commands 4ee9e31a2d 2008-02-13 drh: ** created using the [proc] command. The second argument, pContext, 4ee9e31a2d 2008-02-13 drh: ** is a pointer to the associated ProcDefn structure. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int proc_call1( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *pContext, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int rc; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: ProcDefn *p = (ProcDefn *)pContext; 4ee9e31a2d 2008-02-13 drh: ProcArgs procargs; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Call function proc_call2(), which will call Th_Eval() to evaluate 4ee9e31a2d 2008-02-13 drh: ** the body of the [proc], in a new Th stack frame. This is so that 4ee9e31a2d 2008-02-13 drh: ** the proc body has its own local variable context. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: procargs.argc = argc; 4ee9e31a2d 2008-02-13 drh: procargs.argv = argv; 4ee9e31a2d 2008-02-13 drh: procargs.argl = argl; 4ee9e31a2d 2008-02-13 drh: rc = Th_InFrame(interp, proc_call2, (void *)p, (void *)&procargs); 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( rc==TH_RETURN ){ 4ee9e31a2d 2008-02-13 drh: rc = TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** This function is registered as the delete callback for all commands 4ee9e31a2d 2008-02-13 drh: ** created using the built-in [proc] command. It is called automatically 4ee9e31a2d 2008-02-13 drh: ** when a command created using [proc] is deleted. 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** It frees the ProcDefn structure allocated when the command was created. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static void proc_del(Th_Interp *interp, void *pContext){ 4ee9e31a2d 2008-02-13 drh: ProcDefn *p = (ProcDefn *)pContext; 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, (void *)p->zUsage); 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, (void *)p); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** proc name arglist code 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int proc_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int rc; 4ee9e31a2d 2008-02-13 drh: char *zName; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: ProcDefn *p; 4ee9e31a2d 2008-02-13 drh: int nByte; 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: uchar *zSpace; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: uchar **azParam; 4ee9e31a2d 2008-02-13 drh: int *anParam; 4ee9e31a2d 2008-02-13 drh: int nParam; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: uchar *zUsage = 0; /* Build up a usage message here */ 4ee9e31a2d 2008-02-13 drh: int nUsage = 0; /* Number of bytes at zUsage */ 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=4 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "proc name arglist code"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( Th_SplitList(interp, argv[2], argl[2], &azParam, &anParam, &nParam) ){ 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Allocate the new ProcDefn structure. */ 4ee9e31a2d 2008-02-13 drh: nByte = sizeof(ProcDefn) + /* ProcDefn structure */ 4ee9e31a2d 2008-02-13 drh: (sizeof(uchar *) + sizeof(int)) * nParam + /* azParam, anParam */ 4ee9e31a2d 2008-02-13 drh: (sizeof(uchar *) + sizeof(int)) * nParam + /* azDefault, anDefault */ 4ee9e31a2d 2008-02-13 drh: argl[3] + /* zProgram */ 4ee9e31a2d 2008-02-13 drh: argl[2]; /* Space for copies of parameter names and default values */ 4ee9e31a2d 2008-02-13 drh: p = (ProcDefn *)Th_Malloc(interp, nByte); 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* If the last parameter in the parameter list is "args", then set the 4ee9e31a2d 2008-02-13 drh: ** ProcDefn.hasArgs flag. The "args" parameter does not require an 4ee9e31a2d 2008-02-13 drh: ** entry in the ProcDefn.azParam[] or ProcDefn.azDefault[] arrays. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: if( anParam[nParam-1]==4 && 0==memcmp(azParam[nParam-1], "args", 4) ){ 4ee9e31a2d 2008-02-13 drh: p->hasArgs = 1; 4ee9e31a2d 2008-02-13 drh: nParam--; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: p->nParam = nParam; 4ee9e31a2d 2008-02-13 drh: p->azParam = (uchar **)&p[1]; 4ee9e31a2d 2008-02-13 drh: p->anParam = (int *)&p->azParam[nParam]; 4ee9e31a2d 2008-02-13 drh: p->azDefault = (uchar **)&p->anParam[nParam]; 4ee9e31a2d 2008-02-13 drh: p->anDefault = (int *)&p->azDefault[nParam]; 4ee9e31a2d 2008-02-13 drh: p->zProgram = (uchar *)&p->anDefault[nParam]; 4ee9e31a2d 2008-02-13 drh: memcpy(p->zProgram, argv[3], argl[3]); 4ee9e31a2d 2008-02-13 drh: p->nProgram = argl[3]; 4ee9e31a2d 2008-02-13 drh: zSpace = &p->zProgram[p->nProgram]; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: for(i=0; i<nParam; i++){ 4ee9e31a2d 2008-02-13 drh: uchar **az; 4ee9e31a2d 2008-02-13 drh: int *an; 4ee9e31a2d 2008-02-13 drh: int n; 4ee9e31a2d 2008-02-13 drh: if( Th_SplitList(interp, azParam[i], anParam[i], &az, &an, &n) ){ 4ee9e31a2d 2008-02-13 drh: goto error_out; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( n<1 || n>2 ){ 4ee9e31a2d 2008-02-13 drh: const char expected[] = "expected parameter, got \""; 4ee9e31a2d 2008-02-13 drh: Th_ErrorMessage(interp, expected, azParam[i], anParam[i]); 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, az); 4ee9e31a2d 2008-02-13 drh: goto error_out; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: p->anParam[i] = an[0]; 4ee9e31a2d 2008-02-13 drh: p->azParam[i] = zSpace; 4ee9e31a2d 2008-02-13 drh: memcpy(zSpace, az[0], an[0]); 4ee9e31a2d 2008-02-13 drh: zSpace += an[0]; 4ee9e31a2d 2008-02-13 drh: if( n==2 ){ 4ee9e31a2d 2008-02-13 drh: p->anDefault[i] = an[1]; 4ee9e31a2d 2008-02-13 drh: p->azDefault[i] = zSpace; 4ee9e31a2d 2008-02-13 drh: memcpy(zSpace, az[1], an[1]); 4ee9e31a2d 2008-02-13 drh: zSpace += an[1]; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)" ", 1); 4ee9e31a2d 2008-02-13 drh: if( n==2 ){ 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)"?", 1); 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, az[0], an[0]); 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)"?", 1); 4ee9e31a2d 2008-02-13 drh: }else{ 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, az[0], an[0]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, az); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: assert( zSpace-(uchar *)p<=nByte ); 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* If there is an "args" parameter, append it to the end of the usage 4ee9e31a2d 2008-02-13 drh: ** message. Set ProcDefn.zUsage to point at the usage message. It will 4ee9e31a2d 2008-02-13 drh: ** be freed along with the rest of the proc-definition by proc_del(). 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: if( p->hasArgs ){ 4ee9e31a2d 2008-02-13 drh: Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)" ?args...?", -1); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: p->zUsage = zUsage; 4ee9e31a2d 2008-02-13 drh: p->nUsage = nUsage; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Register the new command with the th1 interpreter. */ 4ee9e31a2d 2008-02-13 drh: zName = (char *)argv[1]; 4ee9e31a2d 2008-02-13 drh: rc = Th_CreateCommand(interp, zName, proc_call1, (void *)p, proc_del); 4ee9e31a2d 2008-02-13 drh: if( rc==TH_OK ){ 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, 0, 0); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, azParam); 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: error_out: 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, azParam); 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, zUsage); 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** rename oldcmd newcmd 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int rename_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: if( argc!=3 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "rename oldcmd newcmd"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return Th_RenameCommand(interp, argv[1], argl[1], argv[2], argl[2]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** break ?value...? 4ee9e31a2d 2008-02-13 drh: ** continue ?value...? 4ee9e31a2d 2008-02-13 drh: ** ok ?value...? 4ee9e31a2d 2008-02-13 drh: ** error ?value...? 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int simple_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: if( argc!=1 && argc!=2 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "return ?value?"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( argc==2 ){ 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, argv[1], argl[1]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return (int)ctx; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** return ?-code code? ?value? 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int return_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int iCode = TH_RETURN; 4ee9e31a2d 2008-02-13 drh: if( argc<1 || argc>4 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "return ?-code code? ?value?"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( argc>2 ){ 4ee9e31a2d 2008-02-13 drh: int rc = Th_ToInt(interp, argv[2], argl[2], &iCode); 4ee9e31a2d 2008-02-13 drh: if( rc!=TH_OK ){ 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( argc==2 || argc==4 ){ 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, argv[argc-1], argl[argc-1]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return iCode; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string compare STRING1 STRING2 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_compare_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: const uchar *zRight; int nRight; 4ee9e31a2d 2008-02-13 drh: const uchar *zLeft; int nLeft; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: int iRes = 0; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=4 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "string compare str1 str2"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: zLeft = argv[2]; 4ee9e31a2d 2008-02-13 drh: nLeft = argl[2]; 4ee9e31a2d 2008-02-13 drh: zRight = argv[3]; 4ee9e31a2d 2008-02-13 drh: nRight = argl[3]; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: for(i=0; iRes==0 && i<nLeft && i<nRight; i++){ 4ee9e31a2d 2008-02-13 drh: iRes = zLeft[i]-zRight[i]; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( iRes==0 ){ 4ee9e31a2d 2008-02-13 drh: iRes = nLeft-nRight; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( iRes<0 ) iRes = -1; 4ee9e31a2d 2008-02-13 drh: if( iRes>0 ) iRes = 1; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return Th_SetResultInt(interp, iRes); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string first NEEDLE HAYSTACK 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_first_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: const uchar *zNeedle; 4ee9e31a2d 2008-02-13 drh: int nNeedle; 4ee9e31a2d 2008-02-13 drh: const uchar *zHaystack; 4ee9e31a2d 2008-02-13 drh: int nHaystack; 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: int iRes; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=4 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "string first needle haystack"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: zNeedle = argv[2]; 4ee9e31a2d 2008-02-13 drh: nNeedle = argl[2]; 4ee9e31a2d 2008-02-13 drh: zHaystack = argv[3]; 4ee9e31a2d 2008-02-13 drh: nHaystack = argl[3]; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: for(i=0; i<(nHaystack-nNeedle); i++){ 4ee9e31a2d 2008-02-13 drh: if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ 4ee9e31a2d 2008-02-13 drh: iRes = i; 4ee9e31a2d 2008-02-13 drh: break; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return Th_SetResultInt(interp, iRes); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string is CLASS STRING 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_is_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: int iRes = 1; 4ee9e31a2d 2008-02-13 drh: if( argc!=4 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "string is class string"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( argl[2]!=5 || 0!=memcmp(argv[2], "alnum", 5) ){ 4ee9e31a2d 2008-02-13 drh: Th_ErrorMessage(interp, "Expected alnum, got: ", argv[2], argl[2]); 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: for(i=0; i<argl[3]; i++){ 4ee9e31a2d 2008-02-13 drh: if( !th_isalnum(argv[3][i]) ){ 4ee9e31a2d 2008-02-13 drh: iRes = 0; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return Th_SetResultInt(interp, iRes); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string last NEEDLE HAYSTACK 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_last_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: const uchar *zNeedle; 4ee9e31a2d 2008-02-13 drh: int nNeedle; 4ee9e31a2d 2008-02-13 drh: const uchar *zHaystack; 4ee9e31a2d 2008-02-13 drh: int nHaystack; 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: int iRes; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=4 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "string first needle haystack"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: zNeedle = argv[2]; 4ee9e31a2d 2008-02-13 drh: nNeedle = argl[2]; 4ee9e31a2d 2008-02-13 drh: zHaystack = argv[3]; 4ee9e31a2d 2008-02-13 drh: nHaystack = argl[3]; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: for(i=nHaystack-nNeedle-1; i>=0; i--){ 4ee9e31a2d 2008-02-13 drh: if( 0==memcmp(zNeedle, &zHaystack[i], nNeedle) ){ 4ee9e31a2d 2008-02-13 drh: iRes = i; 4ee9e31a2d 2008-02-13 drh: break; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return Th_SetResultInt(interp, iRes); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string length STRING 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_length_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: if( argc!=3 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "string length string"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return Th_SetResultInt(interp, argl[2]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string range STRING FIRST LAST 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_range_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int iStart; 4ee9e31a2d 2008-02-13 drh: int iEnd; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=5 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "string range string first last"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argl[4]==3 && 0==memcmp("end", argv[4], 3) ){ 4ee9e31a2d 2008-02-13 drh: iEnd = argl[2]; 4ee9e31a2d 2008-02-13 drh: }else if( Th_ToInt(interp, argv[4], argl[4], &iEnd) ){ 4ee9e31a2d 2008-02-13 drh: Th_ErrorMessage( 4ee9e31a2d 2008-02-13 drh: interp, "Expected \"end\" or integer, got:", argv[4], argl[4]); 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( Th_ToInt(interp, argv[3], argl[3], &iStart) ){ 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( iStart<0 ) iStart = 0; 4ee9e31a2d 2008-02-13 drh: if( iEnd>=argl[2] ) iEnd = argl[2]-1; 4ee9e31a2d 2008-02-13 drh: if( iStart>iEnd ) iEnd = iStart-1; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return Th_SetResult(interp, &argv[2][iStart], iEnd-iStart+1); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string repeat STRING COUNT 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_repeat_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int n; 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: int nByte; 4ee9e31a2d 2008-02-13 drh: uchar *zByte; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=4 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "string repeat string n"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( Th_ToInt(interp, argv[3], argl[3], &n) ){ 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: nByte = argl[2] * n; 4ee9e31a2d 2008-02-13 drh: zByte = Th_Malloc(interp, nByte+1); 4ee9e31a2d 2008-02-13 drh: for(i=0; i<nByte; i+=argl[2]){ 4ee9e31a2d 2008-02-13 drh: memcpy(&zByte[i], argv[2], argl[2]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_SetResult(interp, zByte, nByte); 4ee9e31a2d 2008-02-13 drh: Th_Free(interp, zByte); 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** info exists VAR 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int info_exists_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int rc; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=3 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "info exists var"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: rc = Th_GetVar(interp, argv[2], argl[2]); 4ee9e31a2d 2008-02-13 drh: Th_SetResultInt(interp, rc?0:1); 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** unset VAR 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int unset_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: if( argc!=2 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "unset var"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return Th_UnsetVar(interp, argv[1], argl[1]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: int Th_CallSubCommand( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl, 4ee9e31a2d 2008-02-13 drh: Th_SubCommand *aSub 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: for(i=0; aSub[i].zName; i++){ 4ee9e31a2d 2008-02-13 drh: uchar *zName = (uchar *)aSub[i].zName; 4ee9e31a2d 2008-02-13 drh: if( th_strlen(zName)==argl[1] && 0==memcmp(zName, argv[1], argl[1]) ){ 4ee9e31a2d 2008-02-13 drh: return aSub[i].xProc(interp, ctx, argc, argv, argl); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: Th_ErrorMessage(interp, "Expected sub-command, got:", argv[1], argl[1]); 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** string compare STR1 STR2 4ee9e31a2d 2008-02-13 drh: ** string first NEEDLE HAYSTACK ?STARTINDEX? 4ee9e31a2d 2008-02-13 drh: ** string is CLASS STRING 4ee9e31a2d 2008-02-13 drh: ** string last NEEDLE HAYSTACK ?STARTINDEX? 4ee9e31a2d 2008-02-13 drh: ** string length STRING 4ee9e31a2d 2008-02-13 drh: ** string range STRING FIRST LAST 4ee9e31a2d 2008-02-13 drh: ** string repeat STRING COUNT 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int string_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: Th_SubCommand aSub[] = { 4ee9e31a2d 2008-02-13 drh: { "compare", string_compare_command }, 4ee9e31a2d 2008-02-13 drh: { "first", string_first_command }, 4ee9e31a2d 2008-02-13 drh: { "is", string_is_command }, 4ee9e31a2d 2008-02-13 drh: { "last", string_last_command }, 4ee9e31a2d 2008-02-13 drh: { "length", string_length_command }, 4ee9e31a2d 2008-02-13 drh: { "range", string_range_command }, 4ee9e31a2d 2008-02-13 drh: { "repeat", string_repeat_command }, 4ee9e31a2d 2008-02-13 drh: { 0, 0 } 4ee9e31a2d 2008-02-13 drh: }; 4ee9e31a2d 2008-02-13 drh: return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** info exists VARNAME 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int info_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: Th_SubCommand aSub[] = { 4ee9e31a2d 2008-02-13 drh: { "exists", info_exists_command }, 4ee9e31a2d 2008-02-13 drh: { 0, 0 } 4ee9e31a2d 2008-02-13 drh: }; 4ee9e31a2d 2008-02-13 drh: return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** Convert the script level frame specification (used by the commands 4ee9e31a2d 2008-02-13 drh: ** [uplevel] and [upvar]) in (zFrame, nFrame) to an integer frame as 4ee9e31a2d 2008-02-13 drh: ** used by Th_LinkVar() and Th_Eval(). If successful, write the integer 4ee9e31a2d 2008-02-13 drh: ** frame level to *piFrame and return TH_OK. Otherwise, return TH_ERROR 4ee9e31a2d 2008-02-13 drh: ** and leave an error message in the interpreter result. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int thToFrame( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: const uchar *zFrame, 4ee9e31a2d 2008-02-13 drh: int nFrame, 4ee9e31a2d 2008-02-13 drh: int *piFrame 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int iFrame; 4ee9e31a2d 2008-02-13 drh: if( th_isdigit(zFrame[0]) ){ 4ee9e31a2d 2008-02-13 drh: int rc = Th_ToInt(interp, zFrame, nFrame, &iFrame); 4ee9e31a2d 2008-02-13 drh: if( rc!=TH_OK ) return rc; 4ee9e31a2d 2008-02-13 drh: iFrame = iFrame * -1; 4ee9e31a2d 2008-02-13 drh: }else if( zFrame[0]=='#' ){ 4ee9e31a2d 2008-02-13 drh: int rc = Th_ToInt(interp, &zFrame[1], nFrame-1, &iFrame); 4ee9e31a2d 2008-02-13 drh: if( rc!=TH_OK ) return rc; 4ee9e31a2d 2008-02-13 drh: iFrame = iFrame + 1; 4ee9e31a2d 2008-02-13 drh: }else{ 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: *piFrame = iFrame; 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** uplevel ?LEVEL? SCRIPT 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int uplevel_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int iFrame = -1; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( argc!=2 && argc!=3 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, "uplevel ?level? script..."); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( argc==3 && TH_OK!=thToFrame(interp, argv[1], argl[1], &iFrame) ){ 4ee9e31a2d 2008-02-13 drh: return TH_ERROR; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return Th_Eval(interp, iFrame, argv[argc-1], -1); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR ...? 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int upvar_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int iVar = 1; 4ee9e31a2d 2008-02-13 drh: int iFrame = -1; 4ee9e31a2d 2008-02-13 drh: int rc = TH_OK; 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: if( TH_OK==thToFrame(0, argv[1], argl[1], &iFrame) ){ 4ee9e31a2d 2008-02-13 drh: iVar++; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: if( argc==iVar || (argc-iVar)%2 ){ 4ee9e31a2d 2008-02-13 drh: return Th_WrongNumArgs(interp, 4ee9e31a2d 2008-02-13 drh: "upvar frame othervar myvar ?othervar myvar...?"); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: for(i=iVar; rc==TH_OK && i<argc; i=i+2){ 4ee9e31a2d 2008-02-13 drh: rc = Th_LinkVar(interp, argv[i+1], argl[i+1], iFrame, argv[i], argl[i]); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: return rc; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** TH Syntax: 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** breakpoint ARGS 4ee9e31a2d 2008-02-13 drh: ** 4ee9e31a2d 2008-02-13 drh: ** This command does nothing at all. Its purpose in life is to serve 4ee9e31a2d 2008-02-13 drh: ** as a point for setting breakpoints in a debugger. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: static int breakpoint_command( 4ee9e31a2d 2008-02-13 drh: Th_Interp *interp, 4ee9e31a2d 2008-02-13 drh: void *ctx, 4ee9e31a2d 2008-02-13 drh: int argc, 4ee9e31a2d 2008-02-13 drh: const uchar **argv, 4ee9e31a2d 2008-02-13 drh: int *argl 4ee9e31a2d 2008-02-13 drh: ){ 4ee9e31a2d 2008-02-13 drh: int cnt = 0; 4ee9e31a2d 2008-02-13 drh: cnt++; 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* 4ee9e31a2d 2008-02-13 drh: ** Register the built-in th1 language commands with interpreter interp. 4ee9e31a2d 2008-02-13 drh: ** Usually this is called soon after interpreter creation. 4ee9e31a2d 2008-02-13 drh: */ 4ee9e31a2d 2008-02-13 drh: int th_register_language(Th_Interp *interp){ 4ee9e31a2d 2008-02-13 drh: /* Array of built-in commands. */ 4ee9e31a2d 2008-02-13 drh: struct _Command { 4ee9e31a2d 2008-02-13 drh: const char *zName; 4ee9e31a2d 2008-02-13 drh: Th_CommandProc xProc; 4ee9e31a2d 2008-02-13 drh: void *pContext; 4ee9e31a2d 2008-02-13 drh: } aCommand[] = { 4ee9e31a2d 2008-02-13 drh: {"catch", catch_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"expr", expr_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"for", for_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"if", if_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"info", info_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"lindex", lindex_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"list", list_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"llength", llength_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"proc", proc_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"rename", rename_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"set", set_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"string", string_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"unset", unset_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"uplevel", uplevel_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"upvar", upvar_command, 0}, 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: {"breakpoint", breakpoint_command, 0}, 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: {"return", return_command, 0}, 4ee9e31a2d 2008-02-13 drh: {"break", simple_command, (void *)TH_BREAK}, 4ee9e31a2d 2008-02-13 drh: {"continue", simple_command, (void *)TH_CONTINUE}, 4ee9e31a2d 2008-02-13 drh: {"error", simple_command, (void *)TH_ERROR}, 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: {0, 0} 4ee9e31a2d 2008-02-13 drh: }; 4ee9e31a2d 2008-02-13 drh: int i; 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: /* Add the language commands. */ 4ee9e31a2d 2008-02-13 drh: for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){ 4ee9e31a2d 2008-02-13 drh: void *ctx = aCommand[i].pContext; 4ee9e31a2d 2008-02-13 drh: Th_CreateCommand(interp, aCommand[i].zName, aCommand[i].xProc, ctx, 0); 4ee9e31a2d 2008-02-13 drh: } 4ee9e31a2d 2008-02-13 drh: 4ee9e31a2d 2008-02-13 drh: return TH_OK; 4ee9e31a2d 2008-02-13 drh: }