Check-in [0c99a1554a]
Not logged in
Overview

SHA1 Hash:0c99a1554a22b74a881b2d6360c4ddd769aeaf23
Date: 2008-10-24 16:36:34
User: drh
Comment:Modify the TH1 script interperter to use native characters rather than unsigned characters. Fix a bug in the combobox extension command of TH1.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/th.c from [7781ea6ed2] to [05228f97bf].

@@ -15,11 +15,11 @@
 /*
 ** Interpreter structure.
 */
 struct Th_Interp {
   Th_Vtab *pVtab;     /* Copy of the argument passed to Th_CreateInterp() */
-  uchar *zResult;     /* Current interpreter result (Th_Malloc()ed) */
+  char *zResult;     /* Current interpreter result (Th_Malloc()ed) */
   int nResult;        /* number of bytes in zResult */
   Th_Hash *paCmd;     /* Table of registered commands */
   Th_Frame *pFrame;   /* Current execution frame */
   int isListMode;     /* True if thSplitList() should operate in "list" mode */
 };
@@ -28,11 +28,11 @@
 ** Each TH command registered using Th_CreateCommand() is represented
 ** by an instance of the following structure stored in the Th_Interp.paCmd
 ** hash-table.
 */
 struct Th_Command {
-  int (*xProc)(Th_Interp *, void *, int, const uchar **, int *);
+  int (*xProc)(Th_Interp *, void *, int, const char **, int *);
   void *pContext;
   void (*xDel)(Th_Interp *, void *);
 };
 
 /*
@@ -83,11 +83,11 @@
 ** value.
 */
 struct Th_Variable {
   int nRef;                   /* Number of references to this structure */
   int nData;                  /* Number of bytes at Th_Variable.zData */
-  uchar *zData;               /* Data for scalar variables */
+  char *zData;               /* Data for scalar variables */
   Th_Hash *pHash;             /* Data for array variables */
 };
 
 /*
 ** Hash table API:
@@ -95,15 +95,15 @@
 #define TH_HASHSIZE 257
 struct Th_Hash {
   Th_HashEntry *a[TH_HASHSIZE];
 };
 
-static int thEvalLocal(Th_Interp *, const uchar *, int);
-static int thSplitList(Th_Interp*, const uchar*, int, uchar***, int **, int*);
-
-static int thHexdigit(uchar c);
-static int thEndOfLine(const uchar *, int);
+static int thEvalLocal(Th_Interp *, const char *, int);
+static int thSplitList(Th_Interp*, const char*, int, char***, int **, int*);
+
+static int thHexdigit(char c);
+static int thEndOfLine(const char *, int);
 
 static int  thPushFrame(Th_Interp*, Th_Frame*);
 static void thPopFrame(Th_Interp*);
 
 static void thFreeVariable(Th_HashEntry*, void*);
@@ -123,53 +123,53 @@
 **
 **   thNextVarname(interp, "$a+1", 4, &nByte);
 **
 ** results in nByte being set to 2.
 */
-static int thNextCommand(Th_Interp*, const uchar *z, int n, int *pN);
-static int thNextEscape (Th_Interp*, const uchar *z, int n, int *pN);
-static int thNextVarname(Th_Interp*, const uchar *z, int n, int *pN);
-static int thNextNumber (Th_Interp*, const uchar *z, int n, int *pN);
-static int thNextSpace  (Th_Interp*, const uchar *z, int n, int *pN);
+static int thNextCommand(Th_Interp*, const char *z, int n, int *pN);
+static int thNextEscape (Th_Interp*, const char *z, int n, int *pN);
+static int thNextVarname(Th_Interp*, const char *z, int n, int *pN);
+static int thNextNumber (Th_Interp*, const char *z, int n, int *pN);
+static int thNextSpace  (Th_Interp*, const char *z, int n, int *pN);
 
 /*
 ** Given that the input string (z, n) contains a language construct of
 ** the relevant type (a command enclosed in [], an escape sequence
 ** like "\xFF" or a variable reference like "${varname}", perform
 ** substitution on the string and store the resulting string in
 ** the interpreter result.
 */
-static int thSubstCommand(Th_Interp*, const uchar *z, int n);
-static int thSubstEscape (Th_Interp*, const uchar *z, int n);
-static int thSubstVarname(Th_Interp*, const uchar *z, int n);
+static int thSubstCommand(Th_Interp*, const char *z, int n);
+static int thSubstEscape (Th_Interp*, const char *z, int n);
+static int thSubstVarname(Th_Interp*, const char *z, int n);
 
 /*
 ** Given that there is a th1 word located at the start of the input
 ** string (z, n), determine the length in bytes of that word. If the
 ** isCmd argument is non-zero, then an unescaped ";" byte not
 ** located inside of a block or quoted string is considered to mark
 ** the end of the word.
 */
-static int thNextWord(Th_Interp*, const uchar *z, int n, int *pN, int isCmd);
+static int thNextWord(Th_Interp*, const char *z, int n, int *pN, int isCmd);
 
 /*
 ** Perform substitution on the word contained in the input string (z, n).
 ** Store the resulting string in the interpreter result.
 */
-static int thSubstWord(Th_Interp*, const uchar *z, int n);
+static int thSubstWord(Th_Interp*, const char *z, int n);
 
 /*
 ** The Buffer structure and the thBufferXXX() functions are used to make
 ** memory allocation easier when building up a result.
 */
 struct Buffer {
-  uchar *zBuf;
+  char *zBuf;
   int nBuf;
   int nBufAlloc;
 };
 typedef struct Buffer Buffer;
-static int  thBufferWrite(Th_Interp *interp, Buffer *, const uchar *, int);
+static int  thBufferWrite(Th_Interp *interp, Buffer *, const char *, int);
 static void thBufferInit(Buffer *);
 static void thBufferFree(Th_Interp *interp, Buffer *);
 
 /*
 ** Append nAdd bytes of content copied from zAdd to the end of buffer
@@ -177,11 +177,11 @@
 ** the allocation to make space.
 */
 static int thBufferWrite(
   Th_Interp *interp,
   Buffer *pBuffer,
-  const uchar *zAdd,
+  const char *zAdd,
   int nAdd
 ){
   int nReq;
 
   if( nAdd<0 ){
@@ -188,15 +188,15 @@
     nAdd = th_strlen(zAdd);
   }
   nReq = pBuffer->nBuf+nAdd+1;
 
   if( nReq>pBuffer->nBufAlloc ){
-    uchar *zNew;
+    char *zNew;
     int nNew;
 
     nNew = nReq*2;
-    zNew = (uchar *)Th_Malloc(interp, nNew);
+    zNew = (char *)Th_Malloc(interp, nNew);
     memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf);
     Th_Free(interp, pBuffer->zBuf);
     pBuffer->nBufAlloc = nNew;
     pBuffer->zBuf = zNew;
   }
@@ -205,11 +205,11 @@
   pBuffer->nBuf += nAdd;
   pBuffer->zBuf[pBuffer->nBuf] = '\0';
 
   return TH_OK;
 }
-#define thBufferWrite(a,b,c,d) thBufferWrite(a,b,(const uchar *)c,d)
+#define thBufferWrite(a,b,c,d) thBufferWrite(a,b,(const char *)c,d)
 
 /*
 ** Initialize the Buffer structure pointed to by pBuffer.
 */
 static void thBufferInit(Buffer *pBuffer){
@@ -228,11 +228,11 @@
 /*
 ** Assuming parameter c contains a hexadecimal digit character,
 ** return the corresponding value of that digit. If c is not
 ** a hexadecimal digit character, -1 is returned.
 */
-static int thHexdigit(uchar c){
+static int thHexdigit(char c){
   switch (c) {
     case '0': return 0;
     case '1': return 1;
     case '2': return 2;
     case '3': return 3;
@@ -317,11 +317,11 @@
 ** If there is a parse error, return TH_ERROR and set the interpreter
 ** result to an error message. Otherwise return TH_OK.
 */
 static int thNextEscape(
   Th_Interp *interp,
-  const uchar *zInput,
+  const char *zInput,
   int nInput,
   int *pnEscape
 ){
   int i = 2;
 
@@ -349,11 +349,11 @@
 ** reference. If there is a parse error, return TH_ERROR and set the
 ** interpreter result to an error message. Otherwise return TH_OK.
 */
 int thNextVarname(
   Th_Interp *interp,
-  const uchar *zInput,
+  const char *zInput,
   int nInput,
   int *pnVarname
 ){
   int i;
 
@@ -407,11 +407,11 @@
 ** and set the interpreter result to an error message. Otherwise return
 ** TH_OK.
 */
 int thNextCommand(
   Th_Interp *interp,
-  const uchar *zInput,
+  const char *zInput,
   int nInput,
   int *pnCommand
 ){
   int nBrace = 0;
   int nSquare = 0;
@@ -442,11 +442,11 @@
 ** Set *pnSpace to the number of whitespace bytes at the start of
 ** input string (zInput, nInput). Always return TH_OK.
 */
 int thNextSpace(
   Th_Interp *interp,
-  const uchar *zInput,
+  const char *zInput,
   int nInput,
   int *pnSpace
 ){
   int i;
   for(i=0; i<nInput && th_isspace(zInput[i]); i++);
@@ -465,11 +465,11 @@
 ** located inside of a block or quoted string is considered to mark
 ** the end of the word.
 */
 static int thNextWord(
   Th_Interp *interp,
-  const uchar *zInput,
+  const char *zInput,
   int nInput,
   int *pnWord,
   int isCmd
 ){
   int iEnd = 0;
@@ -520,11 +520,11 @@
 ** a [] block. Perform substitution on the input string and store the
 ** resulting string in the interpreter result.
 */
 static int thSubstCommand(
   Th_Interp *interp,
-  const uchar *zWord,
+  const char *zWord,
   int nWord
 ){
   assert(nWord>=2);
   assert(zWord[0]=='[' && zWord[nWord-1]==']');
   return thEvalLocal(interp, &zWord[1], nWord-2);
@@ -536,11 +536,11 @@
 ** the input string and store the resulting string in the interpreter
 ** result.
 */
 static int thSubstVarname(
   Th_Interp *interp,
-  const uchar *zWord,
+  const char *zWord,
   int nWord
 ){
   assert(nWord>=1);
   assert(zWord[0]=='$');
   assert(nWord==1 || zWord[1]!='{' || zWord[nWord-1]=='}');
@@ -551,11 +551,11 @@
     int i;
     for(i=1; i<nWord && zWord[i]!='('; i++);
     if( i<nWord ){
       Buffer varname;
       int nInner;
-      const uchar *zInner;
+      const char *zInner;
 
       int rc = thSubstWord(interp, &zWord[i+1], nWord-i-2);
       if( rc!=TH_OK ) return rc;
 
       zInner = Th_GetResult(interp, &nInner);
@@ -576,14 +576,14 @@
 ** Perform substitution on the input string and store the resulting
 ** string in the interpreter result.
 */
 static int thSubstEscape(
   Th_Interp *interp,
-  const uchar *zWord,
+  const char *zWord,
   int nWord
 ){
-  uchar c;
+  char c;
 
   assert(nWord>=2);
   assert(zWord[0]=='\\');
 
   switch( zWord[1] ){
@@ -612,11 +612,11 @@
 ** substitution on the input string and store the resulting
 ** string in the interpreter result.
 */
 static int thSubstWord(
   Th_Interp *interp,
-  const uchar *zWord,
+  const char *zWord,
   int nWord
 ){
   int rc = TH_OK;
   Buffer output;
   int i;
@@ -634,12 +634,12 @@
     }
 
     for(i=0; rc==TH_OK && i<nWord; i++){
       int nGet;
 
-      int (*xGet)(Th_Interp *, const uchar*, int, int *) = 0;
-      int (*xSubst)(Th_Interp *, const uchar*, int) = 0;
+      int (*xGet)(Th_Interp *, const char*, int, int *) = 0;
+      int (*xSubst)(Th_Interp *, const char*, int) = 0;
 
       switch( zWord[i] ){
         case '\\':
           xGet = thNextEscape; xSubst = thSubstEscape;
           break;
@@ -662,11 +662,11 @@
       rc = xGet(interp, &zWord[i], nWord-i, &nGet);
       if( rc==TH_OK ){
         rc = xSubst(interp, &zWord[i], nGet);
       }
       if( rc==TH_OK ){
-        const uchar *zRes;
+        const char *zRes;
         int nRes;
         zRes = Th_GetResult(interp, &nRes);
         rc = thBufferWrite(interp, &output, zRes, nRes);
         i += (nGet-1);
       }
@@ -689,11 +689,11 @@
 **   + It contains no non-white-space characters before the first
 **     newline character.
 **
 ** Otherwise return false.
 */
-static int thEndOfLine(const uchar *zInput, int nInput){
+static int thEndOfLine(const char *zInput, int nInput){
   int i;
   for(i=0; i<nInput && zInput[i]!='\n' && th_isspace(zInput[i]); i++);
   return ((i==nInput || zInput[i]=='\n')?1:0);
 }
 
@@ -710,11 +710,11 @@
 **
 ** If TH_OK is returned and pazElem is not NULL, the caller should free the
 ** pointer written to (*pazElem) using Th_Free(). This releases memory
 ** allocated for both the (*pazElem) and (*panElem) arrays. Example:
 **
-**     uchar **argv;
+**     char **argv;
 **     int *argl;
 **     int argc;
 **
 **     // After this call, argv and argl point to valid arrays. The
 **     // number of elements in each is argc.
@@ -727,30 +727,30 @@
 **     Th_Free(interp, argv);
 **
 */
 static int thSplitList(
   Th_Interp *interp,      /* Interpreter context */
-  const uchar *zList,     /* Pointer to buffer containing input list */
+  const char *zList,     /* Pointer to buffer containing input list */
   int nList,              /* Size of buffer pointed to by zList */
-  uchar ***pazElem,       /* OUT: Array of list elements */
+  char ***pazElem,       /* OUT: Array of list elements */
   int **panElem,          /* OUT: Lengths of each list element */
   int *pnCount            /* OUT: Number of list elements */
 ){
   int rc = TH_OK;
 
   Buffer strbuf;
   Buffer lenbuf;
   int nCount = 0;
 
-  const uchar *zInput = zList;
+  const char *zInput = zList;
   int nInput = nList;
 
   thBufferInit(&strbuf);
   thBufferInit(&lenbuf);
 
   while( nInput>0 ){
-    const uchar *zWord;
+    const char *zWord;
     int nWord;
 
     thNextSpace(interp, zInput, nInput, &nWord);
     zInput += nWord;
     nInput = nList-(zInput-zList);
@@ -773,19 +773,19 @@
   assert((lenbuf.nBuf/sizeof(int))==nCount);
 
   assert((pazElem && panElem) || (!pazElem && !panElem));
   if( pazElem && rc==TH_OK ){
     int i;
-    uchar *zElem;
+    char *zElem;
     int *anElem;
-    uchar **azElem = Th_Malloc(interp,
-      sizeof(uchar*) * nCount +      /* azElem */
+    char **azElem = Th_Malloc(interp,
+      sizeof(char*) * nCount +      /* azElem */
       sizeof(int) * nCount +         /* anElem */
       strbuf.nBuf                    /* space for list element strings */
     );
     anElem = (int *)&azElem[nCount];
-    zElem = (uchar *)&anElem[nCount];
+    zElem = (char *)&anElem[nCount];
     memcpy(anElem, lenbuf.zBuf, lenbuf.nBuf);
     memcpy(zElem, strbuf.zBuf, strbuf.nBuf);
     for(i=0; i<nCount;i++){
       azElem[i] = zElem;
       zElem += (anElem[i] + 1);
@@ -805,21 +805,21 @@
 
 /*
 ** Evaluate the th1 script contained in the string (zProgram, nProgram)
 ** in the current stack frame.
 */
-static int thEvalLocal(Th_Interp *interp, const uchar *zProgram, int nProgram){
+static int thEvalLocal(Th_Interp *interp, const char *zProgram, int nProgram){
   int rc = TH_OK;
-  const uchar *zInput = zProgram;
+  const char *zInput = zProgram;
   int nInput = nProgram;
 
   while( rc==TH_OK && nInput ){
     Th_HashEntry *pEntry;
     int nSpace;
-    const uchar *zFirst;
-
-    uchar **argv;
+    const char *zFirst;
+
+    char **argv;
     int *argl;
     int argc;
 
     assert(nInput>=0);
 
@@ -872,27 +872,27 @@
       }
 
       /* Call the command procedure. */
       if( rc==TH_OK ){
         Th_Command *p = (Th_Command *)(pEntry->pData);
-        const uchar **azArg = (const uchar **)argv;
+        const char **azArg = (const char **)argv;
         rc = p->xProc(interp, p->pContext, argc, azArg, argl);
       }
 
       /* If an error occured, add this command to the stack trace report. */
       if( rc==TH_ERROR ){
-        uchar *zRes;
+        char *zRes;
         int nRes;
-        uchar *zStack = 0;
+        char *zStack = 0;
         int nStack = 0;
 
         zRes = Th_TakeResult(interp, &nRes);
-        if( TH_OK==Th_GetVar(interp, (uchar *)"::th_stack_trace", -1) ){
+        if( TH_OK==Th_GetVar(interp, (char *)"::th_stack_trace", -1) ){
           zStack = Th_TakeResult(interp, &nStack);
         }
         Th_ListAppend(interp, &zStack, &nStack, zFirst, zInput-zFirst);
-        Th_SetVar(interp, (uchar *)"::th_stack_trace", -1, zStack, nStack);
+        Th_SetVar(interp, (char *)"::th_stack_trace", -1, zStack, nStack);
         Th_SetResult(interp, zRes, nRes);
         Th_Free(interp, zRes);
         Th_Free(interp, zStack);
       }
     }
@@ -933,11 +933,11 @@
   for(i=0; p && i<(iFrame*-1); i++){
     p = p->pCaller;
   }
 
   if( !p ){
-    uchar *zFrame;
+    char *zFrame;
     int nFrame;
     Th_SetResultInt(interp, iFrame);
     zFrame = Th_TakeResult(interp, &nFrame);
     Th_ErrorMessage(interp, "no such frame:", zFrame, nFrame);
     Th_Free(interp, zFrame);
@@ -950,11 +950,11 @@
 ** Evaluate th1 script (zProgram, nProgram) in the frame identified by
 ** argument iFrame. Leave either an error message or a result in the
 ** interpreter result and return a th1 error code (TH_OK, TH_ERROR,
 ** TH_RETURN, TH_CONTINUE or TH_BREAK).
 */
-int Th_Eval(Th_Interp *interp, int iFrame, const uchar *zProgram, int nProgram){
+int Th_Eval(Th_Interp *interp, int iFrame, const char *zProgram, int nProgram){
   int rc = TH_OK;
   Th_Frame *pSavedFrame = interp->pFrame;
 
   /* Set Th_Interp.pFrame to the frame that this script is to be
   ** evaluated in. The current frame is saved in pSavedFrame and will
@@ -992,21 +992,21 @@
 ** array variable. If the variable is a scalar, *pzInner is set to 0.
 ** If it is an array variable, (*pzInner, *pnInner) is set to the
 ** array key name.
 */
 static int thAnalyseVarname(
-  const uchar *zVarname,
+  const char *zVarname,
   int nVarname,
-  const uchar **pzOuter,     /* OUT: Pointer to scalar/array name */
+  const char **pzOuter,     /* OUT: Pointer to scalar/array name */
   int *pnOuter,              /* OUT: Number of bytes at *pzOuter */
-  const uchar **pzInner,     /* OUT: Pointer to array key (or null) */
+  const char **pzInner,     /* OUT: Pointer to array key (or null) */
   int *pnInner,              /* OUT: Number of bytes at *pzInner */
   int *pisGlobal             /* OUT: Set to true if this is a global ref */
 ){
-  const uchar *zOuter = zVarname;
+  const char *zOuter = zVarname;
   int nOuter;
-  const uchar *zInner = 0;
+  const char *zInner = 0;
   int nInner = 0;
   int isGlobal = 0;
   int i;
 
   if( nVarname<0 ){
@@ -1056,18 +1056,18 @@
 ** an error is left in the interpreter result and NULL returned. If
 ** arrayok is true an array name is Ok.
 */
 static Th_Variable *thFindValue(
   Th_Interp *interp,
-  const uchar *zVar,     /* Pointer to variable name */
+  const char *zVar,     /* Pointer to variable name */
   int nVar,              /* Number of bytes at nVar */
   int create,            /* If true, create the variable if not found */
   int arrayok            /* If true, an array is Ok. Othewise array==error */
 ){
-  const uchar *zOuter;
+  const char *zOuter;
   int nOuter;
-  const uchar *zInner;
+  const char *zInner;
   int nInner;
   int isGlobal;
 
   Th_HashEntry *pEntry;
   Th_Frame *pFrame = interp->pFrame;
@@ -1134,11 +1134,11 @@
 ** the interpreter result and return TH_OK.
 **
 ** If the named variable does not exist, return TH_ERROR and leave
 ** an error message in the interpreter result.
 */
-int Th_GetVar(Th_Interp *interp, const uchar *zVar, int nVar){
+int Th_GetVar(Th_Interp *interp, const char *zVar, int nVar){
   Th_Variable *pValue;
 
   pValue = thFindValue(interp, zVar, nVar, 0, 0);
   if( !pValue ){
     return TH_ERROR;
@@ -1159,13 +1159,13 @@
 ** If (zVar, nVar) refers to an existing array, TH_ERROR is returned
 ** and an error message left in the interpreter result.
 */
 int Th_SetVar(
   Th_Interp *interp,
-  const uchar *zVar,
+  const char *zVar,
   int nVar,
-  const uchar *zValue,
+  const char *zValue,
   int nValue
 ){
   Th_Variable *pValue;
 
   pValue = thFindValue(interp, zVar, nVar, 1, 0);
@@ -1194,13 +1194,13 @@
 ** Create a variable link so that accessing variable (zLocal, nLocal) is
 ** the same as accessing variable (zLink, nLink) in stack frame iFrame.
 */
 int Th_LinkVar(
   Th_Interp *interp,                 /* Interpreter */
-  const uchar *zLocal, int nLocal,   /* Local varname */
+  const char *zLocal, int nLocal,   /* Local varname */
   int iFrame,                        /* Stack frame of linked var */
-  const uchar *zLink, int nLink      /* Linked varname */
+  const char *zLink, int nLink      /* Linked varname */
 ){
   Th_Frame *pSavedFrame = interp->pFrame;
   Th_Frame *pFrame;
   Th_HashEntry *pEntry;
   Th_Variable *pValue;
@@ -1229,11 +1229,11 @@
 ** Input string (zVar, nVar) must contain the name of a scalar variable,
 ** an array, or an array member. If the identified variable exists, it
 ** is deleted and TH_OK returned. Otherwise, an error message is left
 ** in the interpreter result and TH_ERROR is returned.
 */
-int Th_UnsetVar(Th_Interp *interp, const uchar *zVar, int nVar){
+int Th_UnsetVar(Th_Interp *interp, const char *zVar, int nVar){
   Th_Variable *pValue;
 
   pValue = thFindValue(interp, zVar, nVar, 1, 1);
   if( !pValue ){
     return TH_ERROR;
@@ -1252,12 +1252,12 @@
 /*
 ** Return an allocated buffer containing a copy of string (z, n). The
 ** caller is responsible for eventually calling Th_Free() to free
 ** the returned buffer.
 */
-uchar *th_strdup(Th_Interp *interp, const uchar *z, int n){
-  uchar *zRes;
+char *th_strdup(Th_Interp *interp, const char *z, int n){
+  char *zRes;
   if( n<0 ){
     n = th_strlen(z);
   }
   zRes = Th_Malloc(interp, n+1);
   memcpy(zRes, z, n);
@@ -1277,24 +1277,23 @@
 ** Example:
 **
 **     Th_ErrorMessage(interp, "no such variable:", zVarname, nVarname);
 **
 */
-int Th_ErrorMessage(Th_Interp *interp, const char *zPre, const uchar *z, int n){
+int Th_ErrorMessage(Th_Interp *interp, const char *zPre, const char *z, int n){
   if( interp ){
-    uchar *zRes = 0;
+    char *zRes = 0;
     int nRes = 0;
-    int nPre = th_strlen(zPre);
-
-    Th_SetVar(interp, (uchar *)"::th_stack_trace", -1, 0, 0);
+
+    Th_SetVar(interp, (char *)"::th_stack_trace", -1, 0, 0);
 
     Th_StringAppend(interp, &zRes, &nRes, zPre, -1);
     if( zRes[nRes-1]=='"' ){
       Th_StringAppend(interp, &zRes, &nRes, z, n);
-      Th_StringAppend(interp, &zRes, &nRes, (const uchar *)"\"", 1);
+      Th_StringAppend(interp, &zRes, &nRes, (const char *)"\"", 1);
     }else{
-      Th_StringAppend(interp, &zRes, &nRes, (const uchar *)" ", 1);
+      Th_StringAppend(interp, &zRes, &nRes, (const char *)" ", 1);
       Th_StringAppend(interp, &zRes, &nRes, z, n);
     }
 
     Th_SetResult(interp, zRes, nRes);
     Th_Free(interp, zRes);
@@ -1305,11 +1304,11 @@
 
 /*
 ** Set the current interpreter result by taking a copy of the buffer
 ** pointed to by z, size n bytes. TH_OK is always returned.
 */
-int Th_SetResult(Th_Interp *pInterp, const uchar *z, int n){
+int Th_SetResult(Th_Interp *pInterp, const char *z, int n){
 
   /* Free the current result */
   Th_Free(pInterp, pInterp->zResult);
   pInterp->zResult = 0;
   pInterp->nResult = 0;
@@ -1317,11 +1316,11 @@
   if( n<0 ){
     n = th_strlen(z);
   }
 
   if( z && n>0 ){
-    uchar *zResult;
+    char *zResult;
     zResult = Th_Malloc(pInterp, n+1);
     memcpy(zResult, z, n);
     zResult[n] = '\0';
     pInterp->zResult = zResult;
     pInterp->nResult = n;
@@ -1333,16 +1332,16 @@
 /*
 ** Return a pointer to the buffer containing the current interpreter
 ** result. If pN is not NULL, set *pN to the size of the returned
 ** buffer.
 */
-const uchar *Th_GetResult(Th_Interp *pInterp, int *pN){
+const char *Th_GetResult(Th_Interp *pInterp, int *pN){
   assert(pInterp->zResult || pInterp->nResult==0);
   if( pN ){
     *pN = pInterp->nResult;
   }
-  return (pInterp->zResult ? pInterp->zResult : (const uchar *)"");
+  return (pInterp->zResult ? pInterp->zResult : (const char *)"");
 }
 
 /*
 ** Return a pointer to the buffer containing the current interpreter
 ** result. If pN is not NULL, set *pN to the size of the returned
@@ -1351,21 +1350,21 @@
 ** This function is the same as Th_GetResult() except that the
 ** caller is responsible for eventually calling Th_Free() on the
 ** returned buffer. The internal interpreter result is cleared
 ** after this function is called.
 */
-uchar *Th_TakeResult(Th_Interp *pInterp, int *pN){
+char *Th_TakeResult(Th_Interp *pInterp, int *pN){
   if( pN ){
     *pN = pInterp->nResult;
   }
   if( pInterp->zResult ){
-    uchar *zResult = pInterp->zResult;
+    char *zResult = pInterp->zResult;
     pInterp->zResult = 0;
     pInterp->nResult = 0;
     return zResult;
   }else{
-    return (uchar *)Th_Malloc(pInterp, 1);
+    return (char *)Th_Malloc(pInterp, 1);
   }
 }
 
 
 /*
@@ -1397,11 +1396,11 @@
   void (*xDel)(Th_Interp *, void *)  /* Command destructor callback */
 ){
   Th_HashEntry *pEntry;
   Th_Command *pCommand;
 
-  pEntry = Th_HashFind(interp, interp->paCmd, (const uchar *)zName, -1, 1);
+  pEntry = Th_HashFind(interp, interp->paCmd, (const char *)zName, -1, 1);
   if( pEntry->pData ){
     pCommand = pEntry->pData;
     if( pCommand->xDel ){
       pCommand->xDel(interp, pCommand->pContext);
     }
@@ -1424,13 +1423,13 @@
 ** if command zNew already exists, an error message is left in the
 ** interpreter result and TH_ERROR is returned.
 */
 int Th_RenameCommand(
   Th_Interp *interp,
-  const uchar *zName,            /* Existing command name */
+  const char *zName,            /* Existing command name */
   int nName,                     /* Number of bytes at zName */
-  const uchar *zNew,             /* New command name */
+  const char *zNew,             /* New command name */
   int nNew                       /* Number of bytes at zNew */
 ){
   Th_HashEntry *pEntry;
   Th_HashEntry *pNewEntry;
 
@@ -1495,28 +1494,28 @@
 **
 ** Example:
 **
 **     int nElem;
 **     int *anElem;
-**     uchar **azElem;
+**     char **azElem;
 **     int i;
 **
 **     Th_SplitList(interp, zList, nList, &azElem, &anElem, &nElem);
 **     for(i=0; i<nElem; i++){
 **       int nData = anElem[i];
-**       uchar *zData = azElem[i];
+**       char *zData = azElem[i];
 **       ...
 **     }
 **
 **     Th_Free(interp, azElem);
 **
 */
 int Th_SplitList(
   Th_Interp *interp,
-  const uchar *zList,             /* Pointer to buffer containing list */
+  const char *zList,             /* Pointer to buffer containing list */
   int nList,                      /* Number of bytes at zList */
-  uchar ***pazElem,               /* OUT: Array of pointers to element data */
+  char ***pazElem,               /* OUT: Array of pointers to element data */
   int **panElem,                  /* OUT: Array of element data lengths */
   int *pnCount                    /* OUT: Number of elements in list */
 ){
   int rc;
   interp->isListMode = 1;
@@ -1541,25 +1540,25 @@
 ** *pzList to point to a new buffer containing the new list value. *pnList
 ** is similarly updated before returning. The return value is always TH_OK.
 **
 ** Example:
 **
-**     uchar *zList = 0;
+**     char *zList = 0;
 **     int nList = 0;
 **     for (...) {
-**       uchar *zElem = <some expression>;
+**       char *zElem = <some expression>;
 **       Th_ListAppend(interp, &zList, &nList, zElem, -1);
 **     }
 **     Th_SetResult(interp, zList, nList);
 **     Th_Free(interp, zList);
 **
 */
 int Th_ListAppend(
   Th_Interp *interp,           /* Interpreter context */
-  uchar **pzList,              /* IN/OUT: Ptr to ptr to list */
+  char **pzList,              /* IN/OUT: Ptr to ptr to list */
   int *pnList,                 /* IN/OUT: Current length of *pzList */
-  const uchar *zElem,          /* Data to append */
+  const char *zElem,          /* Data to append */
   int nElem                    /* Length of nElem */
 ){
   Buffer output;
   int i;
 
@@ -1577,11 +1576,11 @@
   if( output.nBuf>0 ){
     thBufferWrite(interp, &output, " ", 1);
   }
 
   for(i=0; i<nElem; i++){
-    uchar c = zElem[i];
+    char c = zElem[i];
     if( th_isspecial(c) ) hasSpecialChar = 1;
     if( c=='\\' ) hasEscapeChar = 1;
     if( c=='{' ) nBrace++;
     if( c=='}' ) nBrace--;
   }
@@ -1590,11 +1589,11 @@
     thBufferWrite(interp, &output, "{", 1);
     thBufferWrite(interp, &output, zElem, nElem);
     thBufferWrite(interp, &output, "}", 1);
   }else{
     for(i=0; i<nElem; i++){
-      uchar c = zElem[i];
+      char c = zElem[i];
       if( th_isspecial(c) ) thBufferWrite(interp, &output, "\\", 1);
       thBufferWrite(interp, &output, &c, 1);
     }
   }
 
@@ -1608,16 +1607,16 @@
 ** Append a new element to an existing th1 string. This function uses
 ** the same interface as the Th_ListAppend() function.
 */
 int Th_StringAppend(
   Th_Interp *interp,           /* Interpreter context */
-  uchar **pzStr,               /* IN/OUT: Ptr to ptr to list */
+  char **pzStr,               /* IN/OUT: Ptr to ptr to list */
   int *pnStr,                  /* IN/OUT: Current length of *pzStr */
-  const uchar *zElem,          /* Data to append */
+  const char *zElem,          /* Data to append */
   int nElem                    /* Length of nElem */
 ){
-  uchar *zNew;
+  char *zNew;
   int nNew;
 
   if( nElem<0 ){
     nElem = th_strlen(zElem);
   }
@@ -1687,11 +1686,11 @@
   Operator *pOp;
   Expr *pParent;
   Expr *pLeft;
   Expr *pRight;
 
-  uchar *zValue;     /* Pointer to literal value */
+  char *zValue;     /* Pointer to literal value */
   int nValue;        /* Length of literal value buffer */
 };
 
 /* Unary operators */
 #define OP_UNARY_MINUS  2
@@ -1778,18 +1777,18 @@
 ** The first part of the string (zInput,nInput) contains a number.
 ** Set *pnVarname to the number of bytes in the numeric string.
 */
 static int thNextNumber(
   Th_Interp *interp,
-  const uchar *zInput,
+  const char *zInput,
   int nInput,
   int *pnLiteral
 ){
   int i;
   int seenDot = 0;
   for(i=0; i<nInput; i++){
-    uchar c = zInput[i];
+    char c = zInput[i];
     if( (seenDot || c!='.') && !th_isdigit(c) ) break;
     if( c=='.' ) seenDot = 1;
   }
   *pnLiteral = i;
   return TH_OK;
@@ -1824,12 +1823,12 @@
     int iRight;
     double fLeft;
     double fRight;
 
     /* Left and right arguments as strings */
-    uchar *zLeft = 0; int nLeft;
-    uchar *zRight = 0; int nRight;
+    char *zLeft = 0; int nLeft;
+    char *zRight = 0; int nRight;
 
     /* Evaluate left and right arguments, if they exist. */
     if( pExpr->pLeft ){
       rc = exprEval(interp, pExpr->pLeft);
       if( rc==TH_OK ){
@@ -2014,11 +2013,11 @@
 /*
 ** Parse a string containing a TH expression to a list of tokens.
 */
 static int exprParse(
   Th_Interp *interp,        /* Interpreter to leave error message in */
-  const uchar *zExpr,       /* Pointer to input string */
+  const char *zExpr,       /* Pointer to input string */
   int nExpr,                /* Number of bytes at zExpr */
   Expr ***papToken,         /* OUT: Array of tokens. */
   int *pnToken              /* OUT: Size of token array */
 ){
   int i;
@@ -2026,16 +2025,16 @@
   int rc = TH_OK;
   int nToken = 0;
   Expr **apToken = 0;
 
   for(i=0; rc==TH_OK && i<nExpr; ){
-    uchar c = zExpr[i];
+    char c = zExpr[i];
     if( th_isspace(c) ){                                /* White-space     */
       i++;
     }else{
       Expr *pNew = (Expr *)Th_Malloc(interp, sizeof(Expr));
-      const uchar *z = &zExpr[i];
+      const char *z = &zExpr[i];
 
       switch (c) {
         case '0': case '1': case '2': case '3': case '4':
         case '5': case '6': case '7': case '8': case '9':
           thNextNumber(interp, z, nExpr-i, &pNew->nValue);
@@ -2069,11 +2068,11 @@
               Expr *pPrev = apToken[nToken-1];
               if( !pPrev->pOp || pPrev->pOp->eOp==OP_CLOSE_BRACKET ){
                 continue;
               }
             }
-            nOp = th_strlen((const uchar *)aOperator[j].zOp);
+            nOp = th_strlen((const char *)aOperator[j].zOp);
             if( (nExpr-i)>=nOp && 0==memcmp(aOperator[j].zOp, &zExpr[i], nOp) ){
               pNew->pOp = &aOperator[j];
               i += nOp;
               break;
             }
@@ -2115,11 +2114,11 @@
 ** Evaluate the string (zExpr, nExpr) as a Th expression. Store
 ** the result in the interpreter interp and return TH_OK if
 ** successful. If an error occurs, store an error message in
 ** the interpreter result and return an error code.
 */
-int Th_Expr(Th_Interp *interp, const uchar *zExpr, int nExpr){
+int Th_Expr(Th_Interp *interp, const char *zExpr, int nExpr){
   int rc;                           /* Return Code */
   int i;                            /* Loop counter */
 
   int nToken = 0;
   Expr **apToken = 0;
@@ -2222,11 +2221,11 @@
 ** not already present in the hash-table.
 */
 Th_HashEntry *Th_HashFind(
   Th_Interp *interp,
   Th_Hash *pHash,
-  const uchar *zKey,
+  const char *zKey,
   int nKey,
   int op                      /* -ve = delete, 0 = find, +ve = insert */
 ){
   unsigned int iKey = 0;
   int i;
@@ -2254,11 +2253,11 @@
     pRet = 0;
   }
 
   if( op>0 && !pRet ){
     pRet = (Th_HashEntry *)Th_Malloc(interp, sizeof(Th_HashEntry) + nKey);
-    pRet->zKey = (uchar *)&pRet[1];
+    pRet->zKey = (char *)&pRet[1];
     pRet->nKey = nKey;
     memcpy(pRet->zKey, zKey, nKey);
     pRet->pNext = pHash->a[iKey];
     pHash->a[iKey] = pRet;
   }
@@ -2269,11 +2268,11 @@
 /*
 ** This function is the same as the standard strlen() function, except
 ** that it returns 0 (instead of being undefined) if the argument is
 ** a null pointer.
 */
-int th_strlen(const unsigned char *zStr){
+int th_strlen(const char *zStr){
   int n = 0;
   if( zStr ){
     while( zStr[n] ) n++;
   }
   return n;
@@ -2320,27 +2319,27 @@
 };
 
 /*
 ** Clone of the standard isspace() and isdigit function/macros.
 */
-int th_isspace(unsigned char c){
-  return (aCharProp[c] & 0x01);
+int th_isspace(char c){
+  return (aCharProp[(unsigned char)c] & 0x01);
+}
+int th_isdigit(char c){
+  return (aCharProp[(unsigned char)c] & 0x02);
 }
-int th_isdigit(unsigned char c){
-  return (aCharProp[c] & 0x02);
+int th_isspecial(char c){
+  return (aCharProp[(unsigned char)c] & 0x11);
 }
-int th_isspecial(unsigned char c){
-  return (aCharProp[c] & 0x11);
-}
-int th_isalnum(unsigned char c){
-  return (aCharProp[c] & 0x0A);
+int th_isalnum(char c){
+  return (aCharProp[(unsigned char)c] & 0x0A);
 }
 
 #ifndef LONGDOUBLE_TYPE
 # define LONGDOUBLE_TYPE long double
 #endif
-typedef uchar u8;
+typedef char u8;
 
 
 /*
 ** Return TRUE if z is a pure numeric string.  Return FALSE if the
 ** string contains any character which is not part of a number. If
@@ -2446,11 +2445,11 @@
 **
 ** If the string cannot be converted to an integer, return TH_ERROR.
 ** If the interp argument is not NULL, leave an error message in the
 ** interpreter result too.
 */
-int Th_ToInt(Th_Interp *interp, const uchar *z, int n, int *piOut){
+int Th_ToInt(Th_Interp *interp, const char *z, int n, int *piOut){
   int i = 0;
   int iOut = 0;
 
   if( n<0 ){
     n = th_strlen(z);
@@ -2483,11 +2482,11 @@
 ** If the interp argument is not NULL, leave an error message in the
 ** interpreter result too.
 */
 int Th_ToDouble(
   Th_Interp *interp,
-  const uchar *z,
+  const char *z,
   int n,
   double *pfOut
 ){
   if( !sqlite3IsNumber((const char *)z, 0) ){
     Th_ErrorMessage(interp, "expected number, got: \"", z, n);
@@ -2502,21 +2501,21 @@
 ** Set the result of the interpreter to the th1 representation of
 ** the integer iVal and return TH_OK.
 */
 int Th_SetResultInt(Th_Interp *interp, int iVal){
   int isNegative = 0;
-  uchar zBuf[32];
-  uchar *z = &zBuf[32];
+  char zBuf[32];
+  char *z = &zBuf[32];
 
   if( iVal<0 ){
     isNegative = 1;
     iVal = iVal * -1;
   }
   *(--z) = '\0';
-  *(--z) = (uchar)(48+(iVal%10));
+  *(--z) = (char)(48+(iVal%10));
   while( (iVal = (iVal/10))>0 ){
-    *(--z) = (uchar)(48+(iVal%10));
+    *(--z) = (char)(48+(iVal%10));
     assert(z>zBuf);
   }
   if( isNegative ){
     *(--z) = '-';
   }
@@ -2529,15 +2528,15 @@
 ** the double fVal and return TH_OK.
 */
 int Th_SetResultDouble(Th_Interp *interp, double fVal){
   int i;                /* Iterator variable */
   double v = fVal;      /* Input value */
-  uchar zBuf[128];      /* Output buffer */
-  uchar *z = zBuf;      /* Output cursor */
+  char zBuf[128];      /* Output buffer */
+  char *z = zBuf;      /* Output cursor */
   int iDot = 0;         /* Digit after which to place decimal point */
   int iExp = 0;         /* Exponent (NN in eNN) */
-  const uchar *zExp;    /* String representation of iExp */
+  const char *zExp;    /* String representation of iExp */
 
   /* Precision: */
   #define INSIGNIFICANT 0.000000000001
   #define ROUNDER       0.0000000000005
   double insignificant = INSIGNIFICANT;
@@ -2583,11 +2582,11 @@
 
   /* Output the digits in real value v. The value of iDot determines
    * where (if at all) the decimal point is placed.
    */
   for(i=0; i<=(iDot+1) || v>=insignificant; i++){
-    *z++ = (uchar)(48 + (int)v);
+    *z++ = (char)(48 + (int)v);
     v = (v - ((double)(int)v)) * 10.0;
     insignificant *= 10.0;
     if( iDot==i ){
       *z++ = '.';
     }
@@ -2605,69 +2604,6 @@
     }
   }
 
   *z = '\0';
   return Th_SetResult(interp, zBuf, -1);
-}
-
-/*
-** Set the result of the interpreter to the th1 representation of
-** the pointer p and return TH_OK. The th1 representation can be
-** converted back to a pointer using Th_ToPtr().
-*/
-int Th_SetResultPtr(Th_Interp *interp, void *p){
-  char zBuf[32];
-  char *z;
-  int i;
-  unsigned int v = (unsigned int)p;
-
-  const char zHex[16] = "0123456789ABCDEF";
-
-  assert( sizeof(unsigned int)==sizeof(void *) );
-
-  zBuf[31] = '\0';
-  z = &zBuf[30];
-
-  for(i=0; i<(sizeof(unsigned int)*2); i++){
-    *z-- = zHex[(v&0x0000000F)];
-    v = v>>4;
-  }
-
-  *z-- = 'x';
-  *z = '0';
-
-  return Th_SetResult(interp, (uchar *)z, -1);
-}
-
-/*
-** Convert input string (z, n) to a generic pointer. If the conversion
-** is successful, store the result in *pp and return TH_OK.
-**
-** If the string cannot be converted to a pointer, return TH_ERROR.
-** If the interp argument is not NULL, leave an error message in the
-** interpreter result too.
-*/
-int Th_ToPtr(Th_Interp *interp, const uchar *z, int n, void **pp){
-  unsigned int iPtr;
-  int i;
-  assert(sizeof(unsigned int)==sizeof(void *));
-
-  if( n<3 || z[0]!='0' || z[1]!='x' ){
-    goto error_out;
-  }
-
-  iPtr = 0;
-  for(i=2; i<n; i++){
-    int digit = thHexdigit(z[i]);
-    if( digit<0 ){
-      goto error_out;
-    }
-    iPtr = (iPtr<<4) + digit;
-  }
-
-  *pp = (void *)iPtr;
-  return TH_OK;
-
-error_out:
-  Th_ErrorMessage(interp, "expected pointer, got: \"", z, n);
-  return TH_ERROR;
 }

Modified src/th.h from [7d3866629e] to [ab705d6d8d].

@@ -1,12 +1,10 @@
 
 /* This header file defines the external interface to the custom Scripting
-** Language (TH) interpreter used to create test cases for SQLiteRT. The
-** interpreted language and API are both based on Tcl.
-*/
-
-typedef unsigned char uchar;
+** Language (TH) interpreter.  TH is very similar to TCL but is not an
+** exact clone.
+*/
 
 /*
 ** Before creating an interpreter, the application must allocate and
 ** populate an instance of the following structure. It must remain valid
 ** for the lifetime of the interpreter.
@@ -39,45 +37,45 @@
 **     procedure.
 **
 **   * If iFrame is +ve, then the nth frame from the bottom of the stack.
 **     An iFrame value of 1 means the toplevel (global) frame.
 */
-int Th_Eval(Th_Interp *interp, int iFrame, const uchar *zProg, int nProg);
+int Th_Eval(Th_Interp *interp, int iFrame, const char *zProg, int nProg);
 
 /*
 ** Evaluate a TH expression. The result is stored in the
 ** interpreter result.
 */
-int Th_Expr(Th_Interp *interp, const uchar *, int);
+int Th_Expr(Th_Interp *interp, const char *, int);
 
 /*
 ** Access TH variables in the current stack frame. If the variable name
 ** begins with "::", the lookup is in the top level (global) frame.
 */
-int Th_GetVar(Th_Interp *, const uchar *, int);
-int Th_SetVar(Th_Interp *, const uchar *, int, const uchar *, int);
-int Th_LinkVar(Th_Interp *, const uchar *, int, int, const uchar *, int);
-int Th_UnsetVar(Th_Interp *, const uchar *, int);
-
-typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const uchar **, int *);
+int Th_GetVar(Th_Interp *, const char *, int);
+int Th_SetVar(Th_Interp *, const char *, int, const char *, int);
+int Th_LinkVar(Th_Interp *, const char *, int, int, const char *, int);
+int Th_UnsetVar(Th_Interp *, const char *, int);
+
+typedef int (*Th_CommandProc)(Th_Interp *, void *, int, const char **, int *);
 
 /*
 ** Register new commands.
 */
 int Th_CreateCommand(
   Th_Interp *interp,
   const char *zName,
-  /* int (*xProc)(Th_Interp *, void *, int, const uchar **, int *), */
+  /* int (*xProc)(Th_Interp *, void *, int, const char **, int *), */
   Th_CommandProc xProc,
   void *pContext,
   void (*xDel)(Th_Interp *, void *)
 );
 
 /*
 ** Delete or rename commands.
 */
-int Th_RenameCommand(Th_Interp *, const uchar *, int, const uchar *, int);
+int Th_RenameCommand(Th_Interp *, const char *, int, const char *, int);
 
 /*
 ** Push a new stack frame (local variable context) onto the interpreter
 ** stack, call the function supplied as parameter xCall with the two
 ** context arguments,
@@ -106,19 +104,19 @@
 #define TH_CONTINUE 4
 
 /*
 ** Set and get the interpreter result.
 */
-int Th_SetResult(Th_Interp *, const uchar *, int);
-const uchar *Th_GetResult(Th_Interp *, int *);
-uchar *Th_TakeResult(Th_Interp *, int *);
+int Th_SetResult(Th_Interp *, const char *, int);
+const char *Th_GetResult(Th_Interp *, int *);
+char *Th_TakeResult(Th_Interp *, int *);
 
 /*
 ** Set an error message as the interpreter result. This also
 ** sets the global stack-trace variable $::th_stack_trace.
 */
-int Th_ErrorMessage(Th_Interp *, const char *, const uchar *, int);
+int Th_ErrorMessage(Th_Interp *, const char *, const char *, int);
 
 /*
 ** Access the memory management functions associated with the specified
 ** interpreter.
 */
@@ -126,34 +124,32 @@
 void Th_Free(Th_Interp *, void *);
 
 /*
 ** Functions for handling TH lists.
 */
-int Th_ListAppend(Th_Interp *, uchar **, int *, const uchar *, int);
-int Th_SplitList(Th_Interp *, const uchar *, int, uchar ***, int **, int *);
+int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
+int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
 
-int Th_StringAppend(Th_Interp *, uchar **, int *, const uchar *, int);
+int Th_StringAppend(Th_Interp *, char **, int *, const char *, int);
 
 /*
 ** Functions for handling numbers and pointers.
 */
-int Th_ToInt(Th_Interp *, const uchar *, int, int *);
-int Th_ToDouble(Th_Interp *, const uchar *, int, double *);
-int Th_ToPtr(Th_Interp *, const uchar *, int, void **);
+int Th_ToInt(Th_Interp *, const char *, int, int *);
+int Th_ToDouble(Th_Interp *, const char *, int, double *);
 int Th_SetResultInt(Th_Interp *, int);
 int Th_SetResultDouble(Th_Interp *, double);
-int Th_SetResultPtr(Th_Interp *, void *);
 
 /*
 ** Drop in replacements for the corresponding standard library functions.
 */
-int th_strlen(const unsigned char *);
-int th_isdigit(unsigned char);
-int th_isspace(unsigned char);
-int th_isalnum(unsigned char);
-int th_isspecial(unsigned char);
-uchar *th_strdup(Th_Interp *interp, const uchar *z, int n);
+int th_strlen(const char *);
+int th_isdigit(char);
+int th_isspace(char);
+int th_isalnum(char);
+int th_isspecial(char);
+char *th_strdup(Th_Interp *interp, const char *z, int n);
 
 /*
 ** Interfaces to register the language extensions.
 */
 int th_register_language(Th_Interp *interp);            /* th_lang.c */
@@ -166,21 +162,21 @@
 */
 typedef struct Th_Hash      Th_Hash;
 typedef struct Th_HashEntry Th_HashEntry;
 struct Th_HashEntry {
   void *pData;
-  uchar *zKey;
+  char *zKey;
   int nKey;
   Th_HashEntry *pNext;     /* Internal use only */
 };
 Th_Hash *Th_HashNew(Th_Interp *);
 void Th_HashDelete(Th_Interp *, Th_Hash *);
 void Th_HashIterate(Th_Interp*,Th_Hash*,void (*x)(Th_HashEntry*, void*),void*);
-Th_HashEntry *Th_HashFind(Th_Interp*, Th_Hash*, const uchar*, int, int);
+Th_HashEntry *Th_HashFind(Th_Interp*, Th_Hash*, const char*, int, int);
 
 /*
 ** Useful functions from th_lang.c.
 */
 int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg);
 
 typedef struct Th_SubCommand {char *zName; Th_CommandProc xProc;} Th_SubCommand;
-int Th_CallSubCommand(Th_Interp*,void*,int,const uchar**,int*,Th_SubCommand*);
+int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,Th_SubCommand*);

Modified src/th_lang.c from [1db6c88ca5] to [8af8d7380e].

@@ -12,13 +12,11 @@
 #include "th.h"
 #include <string.h>
 #include <assert.h>
 
 int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg){
-  Th_ErrorMessage(interp,
-      "wrong # args: should be \"", (const uchar*)zMsg, -1
-  );
+  Th_ErrorMessage(interp, "wrong # args: should be \"", zMsg, -1);
   return TH_ERROR;
 }
 
 /*
 ** Syntax:
@@ -27,11 +25,11 @@
 */
 static int catch_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int rc;
 
   if( argc!=2 && argc!=3 ){
@@ -39,11 +37,11 @@
   }
 
   rc = Th_Eval(interp, 0, argv[1], -1);
   if( argc==3 ){
     int nResult;
-    const uchar *zResult = Th_GetResult(interp, &nResult);
+    const char *zResult = Th_GetResult(interp, &nResult);
     Th_SetVar(interp, argv[2], argl[2], zResult, nResult);
   }
 
   Th_SetResultInt(interp, rc);
   return TH_OK;
@@ -56,19 +54,19 @@
 */
 static int if_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int rc = TH_OK;
 
   int iCond;           /* Result of evaluating expression */
   int i;
 
-  const uchar *zResult;
+  const char *zResult;
   int nResult;
 
   if( argc<3 ){
     goto wrong_args;
   }
@@ -103,11 +101,11 @@
 */
 static int expr_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=2 ){
     return Th_WrongNumArgs(interp, "expr expression");
   }
@@ -118,11 +116,11 @@
 /*
 ** Evaluate the th1 script (zBody, nBody) in the local stack frame.
 ** Return the result of the evaluation, except if the result
 ** is TH_CONTINUE, return TH_OK instead.
 */
-static int eval_loopbody(Th_Interp *interp, const uchar *zBody, int nBody){
+static int eval_loopbody(Th_Interp *interp, const char *zBody, int nBody){
   int rc = Th_Eval(interp, 0, zBody, nBody);
   if( rc==TH_CONTINUE ){
     rc = TH_OK;
   }
   return rc;
@@ -135,11 +133,11 @@
 */
 static int for_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int rc;
   int iCond;
 
@@ -170,14 +168,14 @@
 */
 static int list_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
-  int *argl
-){
-  uchar *zList = 0;
+  const char **argv,
+  int *argl
+){
+  char *zList = 0;
   int nList = 0;
   int i;
 
   for(i=1; i<argc; i++){
     Th_ListAppend(interp, &zList, &nList, argv[i], argl[i]);
@@ -196,17 +194,17 @@
 */
 static int lindex_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int iElem;
   int rc;
 
-  uchar **azElem;
+  char **azElem;
   int *anElem;
   int nCount;
 
   if( argc!=3 ){
     return Th_WrongNumArgs(interp, "lindex list index");
@@ -236,11 +234,11 @@
 */
 static int llength_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int nElem;
   int rc;
 
@@ -263,11 +261,11 @@
 */
 static int set_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=2 && argc!=3 ){
     return Th_WrongNumArgs(interp, "set varname ?value?");
   }
@@ -285,18 +283,18 @@
 ** to function proc_call1() when the new command is executed.
 */
 typedef struct ProcDefn ProcDefn;
 struct ProcDefn {
   int nParam;                /* Number of formal (non "args") parameters */
-  uchar **azParam;           /* Parameter names */
+  char **azParam;           /* Parameter names */
   int *anParam;              /* Lengths of parameter names */
-  uchar **azDefault;         /* Default values */
+  char **azDefault;         /* Default values */
   int *anDefault;            /* Lengths of default values */
   int hasArgs;               /* True if there is an "args" parameter */
-  uchar *zProgram;           /* Body of proc */
+  char *zProgram;           /* Body of proc */
   int nProgram;              /* Number of bytes at zProgram */
-  uchar *zUsage;             /* Usage message */
+  char *zUsage;             /* Usage message */
   int nUsage;                /* Number of bytes at zUsage */
 };
 
 /* This structure is used to temporarily store arguments passed to an
 ** invocation of a command created using [proc]. A pointer to an
@@ -303,11 +301,11 @@
 ** instance is passed as the second argument to the proc_call2() function.
 */
 typedef struct ProcArgs ProcArgs;
 struct ProcArgs {
   int argc;
-  const uchar **argv;
+  const char **argv;
   int *argl;
 };
 
 /*
 ** Each time a command created using [proc] is invoked, a new
@@ -327,23 +325,23 @@
   ** not, generate a usage message for the command.
   */
   if( (pArgs->argc>(p->nParam+1) && !p->hasArgs)
    || (pArgs->argc<=(p->nParam) && !p->azDefault[pArgs->argc-1])
   ){
-    uchar *zUsage = 0;
+    char *zUsage = 0;
     int nUsage = 0;
     Th_StringAppend(interp, &zUsage, &nUsage, pArgs->argv[0], pArgs->argl[0]);
     Th_StringAppend(interp, &zUsage, &nUsage, p->zUsage, p->nUsage);
-    Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)"", 1);
+    Th_StringAppend(interp, &zUsage, &nUsage, (const char *)"", 1);
     Th_WrongNumArgs(interp, zUsage);
     Th_Free(interp, zUsage);
     return TH_ERROR;
   }
 
   /* Populate the formal proc parameters. */
   for(i=0; i<p->nParam; i++){
-    const uchar *zVal;
+    const char *zVal;
     int nVal;
     if( pArgs->argc>(i+1) ){
       zVal = pArgs->argv[i+1];
       nVal = pArgs->argl[i+1];
     }else{
@@ -353,16 +351,16 @@
     Th_SetVar(interp, p->azParam[i], p->anParam[i], zVal, nVal);
   }
 
   /* Populate the "args" parameter, if it exists */
   if( p->hasArgs ){
-    uchar *zArgs = 0;
+    char *zArgs = 0;
     int nArgs = 0;
     for(i=p->nParam+1; i<pArgs->argc; i++){
       Th_ListAppend(interp, &zArgs, &nArgs, pArgs->argv[i], pArgs->argl[i]);
     }
-    Th_SetVar(interp, (const uchar *)"args", -1, zArgs, nArgs);
+    Th_SetVar(interp, (const char *)"args", -1, zArgs, nArgs);
   }
 
   Th_SetResult(interp, 0, 0);
   return Th_Eval(interp, 0, p->zProgram, p->nProgram);
 }
@@ -374,11 +372,11 @@
 */
 static int proc_call1(
   Th_Interp *interp,
   void *pContext,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int rc;
 
   ProcDefn *p = (ProcDefn *)pContext;
@@ -419,26 +417,26 @@
 */
 static int proc_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int rc;
   char *zName;
 
   ProcDefn *p;
   int nByte;
   int i;
-  uchar *zSpace;
-
-  uchar **azParam;
+  char *zSpace;
+
+  char **azParam;
   int *anParam;
   int nParam;
 
-  uchar *zUsage = 0;               /* Build up a usage message here */
+  char *zUsage = 0;               /* Build up a usage message here */
   int nUsage = 0;                  /* Number of bytes at zUsage */
 
   if( argc!=4 ){
     return Th_WrongNumArgs(interp, "proc name arglist code");
   }
@@ -446,12 +444,12 @@
     return TH_ERROR;
   }
 
   /* Allocate the new ProcDefn structure. */
   nByte = sizeof(ProcDefn) +                        /* ProcDefn structure */
-      (sizeof(uchar *) + sizeof(int)) * nParam +    /* azParam, anParam */
-      (sizeof(uchar *) + sizeof(int)) * nParam +    /* azDefault, anDefault */
+      (sizeof(char *) + sizeof(int)) * nParam +    /* azParam, anParam */
+      (sizeof(char *) + sizeof(int)) * nParam +    /* azDefault, anDefault */
       argl[3] +                                     /* zProgram */
       argl[2];     /* Space for copies of parameter names and default values */
   p = (ProcDefn *)Th_Malloc(interp, nByte);
 
   /* If the last parameter in the parameter list is "args", then set the
@@ -462,21 +460,21 @@
     p->hasArgs = 1;
     nParam--;
   }
 
   p->nParam    = nParam;
-  p->azParam   = (uchar **)&p[1];
+  p->azParam   = (char **)&p[1];
   p->anParam   = (int *)&p->azParam[nParam];
-  p->azDefault = (uchar **)&p->anParam[nParam];
+  p->azDefault = (char **)&p->anParam[nParam];
   p->anDefault = (int *)&p->azDefault[nParam];
-  p->zProgram = (uchar *)&p->anDefault[nParam];
+  p->zProgram = (char *)&p->anDefault[nParam];
   memcpy(p->zProgram, argv[3], argl[3]);
   p->nProgram = argl[3];
   zSpace = &p->zProgram[p->nProgram];
 
   for(i=0; i<nParam; i++){
-    uchar **az;
+    char **az;
     int *an;
     int n;
     if( Th_SplitList(interp, azParam[i], anParam[i], &az, &an, &n) ){
       goto error_out;
     }
@@ -495,29 +493,29 @@
       p->azDefault[i] = zSpace;
       memcpy(zSpace, az[1], an[1]);
       zSpace += an[1];
     }
 
-    Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)" ", 1);
+    Th_StringAppend(interp, &zUsage, &nUsage, (const char *)" ", 1);
     if( n==2 ){
-      Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)"?", 1);
+      Th_StringAppend(interp, &zUsage, &nUsage, (const char *)"?", 1);
       Th_StringAppend(interp, &zUsage, &nUsage, az[0], an[0]);
-      Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)"?", 1);
+      Th_StringAppend(interp, &zUsage, &nUsage, (const char *)"?", 1);
     }else{
       Th_StringAppend(interp, &zUsage, &nUsage, az[0], an[0]);
     }
 
     Th_Free(interp, az);
   }
-  assert( zSpace-(uchar *)p<=nByte );
+  assert( zSpace-(char *)p<=nByte );
 
   /* If there is an "args" parameter, append it to the end of the usage
   ** message. Set ProcDefn.zUsage to point at the usage message. It will
   ** be freed along with the rest of the proc-definition by proc_del().
   */
   if( p->hasArgs ){
-    Th_StringAppend(interp, &zUsage, &nUsage, (const uchar *)" ?args...?", -1);
+    Th_StringAppend(interp, &zUsage, &nUsage, (const char *)" ?args...?", -1);
   }
   p->zUsage = zUsage;
   p->nUsage = nUsage;
 
   /* Register the new command with the th1 interpreter. */
@@ -543,11 +541,11 @@
 */
 static int rename_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=3 ){
     return Th_WrongNumArgs(interp, "rename oldcmd newcmd");
   }
@@ -564,11 +562,11 @@
 */
 static int simple_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=1 && argc!=2 ){
     return Th_WrongNumArgs(interp, "return ?value?");
   }
@@ -585,11 +583,11 @@
 */
 static int return_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int iCode = TH_RETURN;
   if( argc<1 || argc>4 ){
     return Th_WrongNumArgs(interp, "return ?-code code? ?value?");
@@ -610,14 +608,14 @@
 ** TH Syntax:
 **
 **   string compare STRING1 STRING2
 */
 static int string_compare_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
-){
-  const uchar *zRight; int nRight;
-  const uchar *zLeft; int nLeft;
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
+){
+  const char *zRight; int nRight;
+  const char *zLeft; int nLeft;
 
   int i;
   int iRes = 0;
 
   if( argc!=4 ){
@@ -646,15 +644,15 @@
 ** TH Syntax:
 **
 **   string first NEEDLE HAYSTACK
 */
 static int string_first_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
-){
-  const uchar *zNeedle;
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
+){
+  const char *zNeedle;
   int nNeedle;
-  const uchar *zHaystack;
+  const char *zHaystack;
   int nHaystack;
   int i;
   int iRes;
 
   if( argc!=4 ){
@@ -680,11 +678,11 @@
 ** TH Syntax:
 **
 **   string is CLASS STRING
 */
 static int string_is_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
 ){
   int i;
   int iRes = 1;
   if( argc!=4 ){
     return Th_WrongNumArgs(interp, "string is class string");
@@ -707,15 +705,15 @@
 ** TH Syntax:
 **
 **   string last NEEDLE HAYSTACK
 */
 static int string_last_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
-){
-  const uchar *zNeedle;
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
+){
+  const char *zNeedle;
   int nNeedle;
-  const uchar *zHaystack;
+  const char *zHaystack;
   int nHaystack;
   int i;
   int iRes;
 
   if( argc!=4 ){
@@ -741,11 +739,11 @@
 ** TH Syntax:
 **
 **   string length STRING
 */
 static int string_length_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
 ){
   if( argc!=3 ){
     return Th_WrongNumArgs(interp, "string length string");
   }
   return Th_SetResultInt(interp, argl[2]);
@@ -755,11 +753,11 @@
 ** TH Syntax:
 **
 **   string range STRING FIRST LAST
 */
 static int string_range_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
 ){
   int iStart;
   int iEnd;
 
   if( argc!=5 ){
@@ -788,16 +786,16 @@
 ** TH Syntax:
 **
 **   string repeat STRING COUNT
 */
 static int string_repeat_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
 ){
   int n;
   int i;
   int nByte;
-  uchar *zByte;
+  char *zByte;
 
   if( argc!=4 ){
     return Th_WrongNumArgs(interp, "string repeat string n");
   }
   if( Th_ToInt(interp, argv[3], argl[3], &n) ){
@@ -819,11 +817,11 @@
 ** TH Syntax:
 **
 **   info exists VAR
 */
 static int info_exists_command(
-  Th_Interp *interp, void *ctx, int argc, const uchar **argv, int *argl
+  Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
 ){
   int rc;
 
   if( argc!=3 ){
     return Th_WrongNumArgs(interp, "info exists var");
@@ -840,11 +838,11 @@
 */
 static int unset_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=2 ){
     return Th_WrongNumArgs(interp, "unset var");
   }
@@ -853,17 +851,17 @@
 
 int Th_CallSubCommand(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl,
   Th_SubCommand *aSub
 ){
   int i;
   for(i=0; aSub[i].zName; i++){
-    uchar *zName = (uchar *)aSub[i].zName;
+    char *zName = (char *)aSub[i].zName;
     if( th_strlen(zName)==argl[1] && 0==memcmp(zName, argv[1], argl[1]) ){
       return aSub[i].xProc(interp, ctx, argc, argv, argl);
     }
   }
 
@@ -884,11 +882,11 @@
 */
 static int string_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   Th_SubCommand aSub[] = {
     { "compare", string_compare_command },
     { "first",   string_first_command },
@@ -909,11 +907,11 @@
 */
 static int info_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   Th_SubCommand aSub[] = {
     { "exists",  info_exists_command },
     { 0, 0 }
@@ -928,11 +926,11 @@
 ** frame level to *piFrame and return TH_OK. Otherwise, return TH_ERROR
 ** and leave an error message in the interpreter result.
 */
 static int thToFrame(
   Th_Interp *interp,
-  const uchar *zFrame,
+  const char *zFrame,
   int nFrame,
   int *piFrame
 ){
   int iFrame;
   if( th_isdigit(zFrame[0]) ){
@@ -957,11 +955,11 @@
 */
 static int uplevel_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int iFrame = -1;
 
   if( argc!=2 && argc!=3 ){
@@ -980,11 +978,11 @@
 */
 static int upvar_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int iVar = 1;
   int iFrame = -1;
   int rc = TH_OK;
@@ -1013,11 +1011,11 @@
 */
 static int breakpoint_command(
   Th_Interp *interp,
   void *ctx,
   int argc,
-  const uchar **argv,
+  const char **argv,
   int *argl
 ){
   int cnt = 0;
   cnt++;
   return TH_OK;

Modified src/th_main.c from [c828d14f02] to [a10cec9ea6].

@@ -65,11 +65,11 @@
 */
 static int enableOutputCmd(
   Th_Interp *interp,
   void *p,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=2 ){
     return Th_WrongNumArgs(interp, "enable_output BOOLEAN");
   }
@@ -104,11 +104,11 @@
 */
 static int putsCmd(
   Th_Interp *interp,
   void *pConvert,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=2 ){
     return Th_WrongNumArgs(interp, "puts STRING");
   }
@@ -123,11 +123,11 @@
 */
 static int wikiCmd(
   Th_Interp *interp,
   void *p,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=2 ){
     return Th_WrongNumArgs(interp, "wiki STRING");
   }
@@ -148,19 +148,19 @@
 */
 static int htmlizeCmd(
   Th_Interp *interp,
   void *p,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
   char *zOut;
   if( argc!=2 ){
     return Th_WrongNumArgs(interp, "htmlize STRING");
   }
   zOut = htmlize((char*)argv[1], argl[1]);
-  Th_SetResult(interp, (unsigned char*)zOut, -1);
+  Th_SetResult(interp, zOut, -1);
   free(zOut);
   return TH_OK;
 }
 
 /*
@@ -170,15 +170,15 @@
 */
 static int dateCmd(
   Th_Interp *interp,
   void *p,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
   char *zOut = db_text("??", "SELECT datetime('now')");
-  Th_SetResult(interp, (unsigned char*)zOut, -1);
+  Th_SetResult(interp, zOut, -1);
   free(zOut);
   return TH_OK;
 }
 
 /*
@@ -188,11 +188,11 @@
 */
 static int hascapCmd(
   Th_Interp *interp,
   void *p,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=2 ){
     return Th_WrongNumArgs(interp, "hascap STRING");
   }
@@ -212,46 +212,50 @@
 */
 static int comboboxCmd(
   Th_Interp *interp,
   void *p,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
   if( argc!=4 ){
     return Th_WrongNumArgs(interp, "combobox NAME TEXT-LIST NUMLINES");
   }
   if( enableOutput ){
     int height;
-    Blob list, elem, name;
+    Blob name;
     int nValue;
     const char *zValue;
     char *z, *zH;
+    int nElem;
+    int *aszElem;
+    char **azElem;
+    int i;
 
     if( Th_ToInt(interp, argv[3], argl[3], &height) ) return TH_ERROR;
-    blob_init(&list, (char*)argv[2], argl[2]);
+    Th_SplitList(interp, argv[2], argl[2], &azElem, &aszElem, &nElem);
     blob_init(&name, (char*)argv[1], argl[1]);
     zValue = Th_Fetch(blob_str(&name), &nValue);
     z = mprintf("<select name=\"%z\" size=\"%d\">",
                  htmlize(blob_buffer(&name), blob_size(&name)), height);
     sendText(z, -1, 0);
     free(z);
     blob_reset(&name);
-    while( blob_token(&list, &elem) ){
-      zH = htmlize(blob_buffer(&elem), blob_size(&elem));
-      if( zValue && blob_size(&elem)==nValue
-             && memcmp(zValue, blob_buffer(&elem), nValue)==0 ){
+    for(i=0; i<nElem; i++){
+      zH = htmlize((char*)azElem[i], aszElem[i]);
+      if( zValue && aszElem[i]==nValue
+             && memcmp(zValue, azElem[i], nValue)==0 ){
         z = mprintf("<option value=\"%s\" selected>%s</option>", zH, zH);
       }else{
         z = mprintf("<option value=\"%s\">%s</option>", zH, zH);
       }
       free(zH);
       sendText(z, -1, 0);
       free(z);
     }
     sendText("</select>", -1, 0);
-    blob_reset(&list);
+    Th_Free(interp, azElem);
   }
   return TH_OK;
 }
 
 /*
@@ -262,14 +266,14 @@
 */
 static int linecntCmd(
   Th_Interp *interp,
   void *p,
   int argc,
-  const unsigned char **argv,
+  const char **argv,
   int *argl
 ){
-  const uchar *z;
+  const char *z;
   int size, n, i;
   int iMin, iMax;
   if( argc!=4 ){
     return Th_WrongNumArgs(interp, "linecount STRING MAX MIN");
   }
@@ -323,20 +327,20 @@
 ** Store a string value in a variable in the interpreter.
 */
 void Th_Store(const char *zName, const char *zValue){
   Th_FossilInit();
   if( zValue ){
-    Th_SetVar(g.interp, (uchar*)zName, -1, (uchar*)zValue, strlen(zValue));
+    Th_SetVar(g.interp, (char*)zName, -1, (char*)zValue, strlen(zValue));
   }
 }
 
 /*
 ** Unset a variable.
 */
 void Th_Unstore(const char *zName){
   if( g.interp ){
-    Th_UnsetVar(g.interp, (uchar*)zName, -1);
+    Th_UnsetVar(g.interp, (char*)zName, -1);
   }
 }
 
 /*
 ** Retrieve a string value from the interpreter.  If no such
@@ -343,11 +347,11 @@
 ** variable exists, return NULL.
 */
 char *Th_Fetch(const char *zName, int *pSize){
   int rc;
   Th_FossilInit();
-  rc = Th_GetVar(g.interp, (uchar*)zName, -1);
+  rc = Th_GetVar(g.interp, (char*)zName, -1);
   if( rc==TH_OK ){
     return (char*)Th_GetResult(g.interp, pSize);
   }else{
     return 0;
   }
@@ -421,11 +425,11 @@
 */
 int Th_Render(const char *z){
   int i = 0;
   int n;
   int rc = TH_OK;
-  uchar *zResult;
+  char *zResult;
   Th_FossilInit();
   while( z[i] ){
     if( z[i]=='$' && (n = validVarName(&z[i+1]))>0 ){
       const char *zVar;
       int nVar;
@@ -437,20 +441,20 @@
       }else{
         /* Variables of the form $aaa */
         zVar = &z[i+1];
         nVar = n;
       }
-      rc = Th_GetVar(g.interp, (uchar*)zVar, nVar);
+      rc = Th_GetVar(g.interp, (char*)zVar, nVar);
       z += i+1+n;
       i = 0;
-      zResult = (uchar*)Th_GetResult(g.interp, &n);
+      zResult = (char*)Th_GetResult(g.interp, &n);
       sendText((char*)zResult, n, n>nVar);
     }else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){
       sendText(z, i, 0);
       z += i+5;
       for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){}
-      rc = Th_Eval(g.interp, 0, (const uchar*)z, i);
+      rc = Th_Eval(g.interp, 0, (const char*)z, i);
       if( rc!=TH_OK ) break;
       z += i;
       if( z[0] ){ z += 6; }
       i = 0;
     }else{
@@ -457,11 +461,11 @@
       i++;
     }
   }
   if( rc==TH_ERROR ){
     sendText("<hr><p><font color=\"red\"><b>ERROR: ", -1, 0);
-    zResult = (uchar*)Th_GetResult(g.interp, &n);
+    zResult = (char*)Th_GetResult(g.interp, &n);
     sendText((char*)zResult, n, 1);
     sendText("</b></font></p>", -1, 0);
   }else{
     sendText(z, i, 0);
   }

Modified src/tkt.c from [06773a209f] to [4d8a2f78f1].

@@ -270,11 +270,11 @@
 */
 void ticket_init(void){
   const char *zConfig;
   Th_FossilInit();
   zConfig = ticket_common_code();
-  Th_Eval(g.interp, 0, (const uchar*)zConfig, -1);
+  Th_Eval(g.interp, 0, zConfig, -1);
 }
 
 /*
 ** Recreate the ticket table.
 */