Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Refactored th1's output mechanism: moved output API to Th_Vtab to support arbitrary output destinations, the intention being to be able to support an output buffer stack analog to PHP's ob_start(), ob_get_clean() and friends. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | th1-query-api |
Files: | files | file ages | folders |
SHA1: |
3c0209f5dcdc4e7505d1fb072bded0ca |
User & Date: | stephan 2012-07-14 11:54:45.727 |
Context
2012-07-14
| ||
12:02 | Refactored sendText() to use the new output abstraction layer. ... (check-in: d3a62349 user: stephan tags: th1-query-api) | |
11:54 | Refactored th1's output mechanism: moved output API to Th_Vtab to support arbitrary output destinations, the intention being to be able to support an output buffer stack analog to PHP's ob_start(), ob_get_clean() and friends. ... (check-in: 3c0209f5 user: stephan tags: th1-query-api) | |
11:15 | Cleanups in the th1 query statement finalization. ... (check-in: 4fdf0ac2 user: stephan tags: th1-query-api) | |
Changes
Changes to src/th.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* ** The implementation of the TH core. This file contains the parser, and ** the implementation of the interface in th.h. */ #include "th.h" #include <string.h> #include <assert.h> typedef struct Th_Command Th_Command; typedef struct Th_Frame Th_Frame; typedef struct Th_Variable Th_Variable; /* ** Interpreter structure. | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /* ** The implementation of the TH core. This file contains the parser, and ** the implementation of the interface in th.h. */ #include "th.h" #include <string.h> #include <assert.h> #include <stdio.h> /* FILE class */ typedef struct Th_Command Th_Command; typedef struct Th_Frame Th_Frame; typedef struct Th_Variable Th_Variable; /* ** Interpreter structure. |
︙ | ︙ | |||
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 | } void Th_Free(Th_Interp *pInterp, void *z){ if( z ){ pInterp->pVtab->xFree(z); } } /* ** Install a new th1 command. ** ** If a command of the same name already exists, it is deleted automatically. */ int Th_CreateCommand( Th_Interp *interp, | > > > > > > > > > > > > > > > > > > > > > > > | 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 | } void Th_Free(Th_Interp *pInterp, void *z){ if( z ){ pInterp->pVtab->xFree(z); } } int Th_Vtab_output( Th_Vtab *vTab, char const * zData, int nData ){ if(!vTab->out.f){ return -1; }else if(!vTab->out.enabled){ return 0; }else{ return vTab->out.f( zData, nData, vTab->out.pState ); } } int Th_output( Th_Interp *pInterp, char const * zData, int nData ){ return Th_Vtab_output( pInterp->pVtab, zData, nData ); } int Th_output_f_FILE( char const * zData, int nData, void * pState ){ FILE * dest = pState ? (FILE*)pState : stdout; int rc = (int)fwrite(zData, 1, nData, dest); fflush(dest); return rc; } /* ** Install a new th1 command. ** ** If a command of the same name already exists, it is deleted automatically. */ int Th_CreateCommand( Th_Interp *interp, |
︙ | ︙ |
Changes to src/th.h.
︙ | ︙ | |||
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #endif /* This header file defines the external interface to the custom Scripting ** 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. */ struct Th_Vtab { void *(*xMalloc)(unsigned int); void (*xFree)(void *); }; typedef struct Th_Vtab Th_Vtab; /* ** Opaque handle for interpeter. */ typedef struct Th_Interp Th_Interp; /* ** Create and delete interpreters. */ Th_Interp * Th_CreateInterp(Th_Vtab *pVtab); void Th_DeleteInterp(Th_Interp *); | > > > > > > > > > > > > > > > > > > | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #endif /* This header file defines the external interface to the custom Scripting ** Language (TH) interpreter. TH is very similar to TCL but is not an ** exact clone. */ /* ** Th_output_f() specifies a generic output routine for use by Th_Vtab ** and friends. Its first argument is the data to write, the second is ** the number of bytes to write, and the 3rd is an ** implementation-specific state pointer (may be NULL, depending on ** the implementation). The return value is the number of bytes output ** (which may differ from len due to encoding and whatnot). On error ** a negative value must be returned. */ typedef int (*Th_output_f)( char const * zData, int len, void * pState ); /* ** 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. */ struct Th_Vtab { void *(*xMalloc)(unsigned int); void (*xFree)(void *); struct { Th_output_f f; /* output handler */ void * pState; /* final argument for xOut() */ char enabled; /* if 0, Th_output() does nothing. */ } out; }; typedef struct Th_Vtab Th_Vtab; /* ** Opaque handle for interpeter. */ typedef struct Th_Interp Th_Interp; /* ** Create and delete interpreters. */ Th_Interp * Th_CreateInterp(Th_Vtab *pVtab); void Th_DeleteInterp(Th_Interp *); |
︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 | /* ** 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 char**,int*,Th_SubCommand*); #ifdef TH_USE_SQLITE #include "stddef.h" /* size_t */ extern void *fossil_realloc(void *p, size_t n); /* ** Adds the given prepared statement to the interpreter. Returns the | > > > > > > > > > > > > > > > > > > > > > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | /* ** 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 char**,int*,Th_SubCommand*); /* ** Sends the given data through vTab->out.f() if vTab->out.enabled is ** true, otherwise this is a no-op. Returns 0 or higher on success, * ** a negative value if vTab->out.f is NULL. */ int Th_Vtab_output( Th_Vtab *vTab, char const * zData, int len ); /* ** Sends the given output through pInterp's v-table's output ** implementation. See Th_Vtab_output() for the argument and ** return value semantics. */ int Th_output( Th_Interp *pInterp, char const * zData, int len ); /* ** Th_output_f() implementation which sends its output to either pState ** (which must be NULL or a (FILE*)) or stdout (if pState is NULL). */ int Th_output_f_FILE( char const * zData, int len, void * pState ); #ifdef TH_USE_SQLITE #include "stddef.h" /* size_t */ extern void *fossil_realloc(void *p, size_t n); /* ** Adds the given prepared statement to the interpreter. Returns the |
︙ | ︙ |
Changes to src/th_main.c.
︙ | ︙ | |||
40 41 42 43 44 45 46 | } static void xFree(void *p){ if( p ){ nOutstandingMalloc--; } free(p); } | > > | > > > > > | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | } static void xFree(void *p){ if( p ){ nOutstandingMalloc--; } free(p); } static Th_Vtab vtab = { xMalloc, xFree, { Th_output_f_FILE, NULL, 1 } }; /* ** Generate a TH1 trace message if debugging is enabled. */ void Th_Trace(const char *zFormat, ...){ va_list ap; va_start(ap, zFormat); |
︙ | ︙ | |||
72 73 74 75 76 77 78 79 | void *p, int argc, const char **argv, int *argl ){ if( argc!=2 ){ return Th_WrongNumArgs(interp, "enable_output BOOLEAN"); } | > > > > > | > > > > | | < | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | void *p, int argc, const char **argv, int *argl ){ if( argc!=2 ){ return Th_WrongNumArgs(interp, "enable_output BOOLEAN"); }else{ int rc = Th_ToInt(interp, argv[1], argl[1], &enableOutput); vtab.out.enabled = enableOutput; return rc; } } int Th_output_f_cgi_content( char const * zData, int nData, void * pState ){ cgi_append_content(zData, nData); return nData; } /* ** Send text to the appropriate output: Either to the console ** or to the CGI reply buffer. */ static void sendText(const char *z, int n, int encode){ if( enableOutput && n ){ if( n<0 ) n = strlen(z); if( encode ){ z = htmlize(z, n); n = strlen(z); } if( g.cgiOutput ){ Th_output_f_cgi_content(z, n, NULL); }else{ Th_output_f_FILE( z, n, stdout ); } if( encode ) fossil_free((char*)z); } } struct PutsCmdData { char escapeHtml; |
︙ | ︙ | |||
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 | {"query_step", queryStepCmd, 0}, #endif {0, 0, 0} }; if( g.interp==0 ){ int i; g.interp = Th_CreateInterp(&vtab); th_register_language(g.interp); /* Basic scripting commands. */ #ifdef FOSSIL_ENABLE_TCL if( getenv("TH1_ENABLE_TCL")!=0 || db_get_boolean("tcl", 0) ){ th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */ } #endif | > > > > > > | 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 | {"query_step", queryStepCmd, 0}, #endif {0, 0, 0} }; if( g.interp==0 ){ int i; if(g.cgiOutput){ vtab.out.f = Th_output_f_cgi_content; }else{ vtab.out.f = Th_output_f_FILE; vtab.out.pState = stdout; } g.interp = Th_CreateInterp(&vtab); th_register_language(g.interp); /* Basic scripting commands. */ #ifdef FOSSIL_ENABLE_TCL if( getenv("TH1_ENABLE_TCL")!=0 || db_get_boolean("tcl", 0) ){ th_register_tcl(g.interp, &g.tcl); /* Tcl integration commands. */ } #endif |
︙ | ︙ |
Changes to test/th1-query-api-1.th1.
︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 140 141 142 143 | set exception 0 catch { argv_getint noSuchOptionAndNoDefault } exception puts exception = $exception "\n" proc multiStmt {} { set max 5 set i 0 set s(0) 0 for {set i 0} {$i < $max} {incr i} { set s($i) [query_prepare "SELECT $i"] | > | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | set exception 0 catch { argv_getint noSuchOptionAndNoDefault } exception puts exception = $exception "\n" enable_output 1 proc multiStmt {} { set max 5 set i 0 set s(0) 0 for {set i 0} {$i < $max} {incr i} { set s($i) [query_prepare "SELECT $i"] |
︙ | ︙ | |||
165 166 167 168 169 170 171 172 173 | for {set i 0} {$i < $max} {incr i} { puts "closing stmt $s($i)\n" query_finalize $s($i) } } multiStmt puts "If you got this far, you win!\n" </th1> | > | 166 167 168 169 170 171 172 173 174 175 | for {set i 0} {$i < $max} {incr i} { puts "closing stmt $s($i)\n" query_finalize $s($i) } } multiStmt enable_output 1 puts "If you got this far, you win!\n" </th1> |