Fossil SCM

Added PHP-like "ob" (output buffering) API to th1. Refactred Th_Vtab allocator to use a single realloc()-like interface.

stephan 2012-07-14 18:32 th1-query-api
Commit b7930639549f7bcc987799e7f77e94035b477cb0
+1 -2
--- src/blob.c
+++ src/blob.c
@@ -19,12 +19,12 @@
1919
** or binary data.
2020
*/
2121
#include "config.h"
2222
#include <zlib.h>
2323
#include "blob.h"
24
-
2524
#if INTERFACE
25
+typedef struct Blob Blob;
2626
/*
2727
** A Blob can hold a string or a binary object of arbitrary size. The
2828
** size changes as necessary.
2929
*/
3030
struct Blob {
@@ -49,11 +49,10 @@
4949
** Seek whence parameter values
5050
*/
5151
#define BLOB_SEEK_SET 1
5252
#define BLOB_SEEK_CUR 2
5353
#define BLOB_SEEK_END 3
54
-
5554
#endif /* INTERFACE */
5655
5756
/*
5857
** Make sure a blob is initialized
5958
*/
6059
--- src/blob.c
+++ src/blob.c
@@ -19,12 +19,12 @@
19 ** or binary data.
20 */
21 #include "config.h"
22 #include <zlib.h>
23 #include "blob.h"
24
25 #if INTERFACE
 
26 /*
27 ** A Blob can hold a string or a binary object of arbitrary size. The
28 ** size changes as necessary.
29 */
30 struct Blob {
@@ -49,11 +49,10 @@
49 ** Seek whence parameter values
50 */
51 #define BLOB_SEEK_SET 1
52 #define BLOB_SEEK_CUR 2
53 #define BLOB_SEEK_END 3
54
55 #endif /* INTERFACE */
56
57 /*
58 ** Make sure a blob is initialized
59 */
60
--- src/blob.c
+++ src/blob.c
@@ -19,12 +19,12 @@
19 ** or binary data.
20 */
21 #include "config.h"
22 #include <zlib.h>
23 #include "blob.h"
 
24 #if INTERFACE
25 typedef struct Blob Blob;
26 /*
27 ** A Blob can hold a string or a binary object of arbitrary size. The
28 ** size changes as necessary.
29 */
30 struct Blob {
@@ -49,11 +49,10 @@
49 ** Seek whence parameter values
50 */
51 #define BLOB_SEEK_SET 1
52 #define BLOB_SEEK_CUR 2
53 #define BLOB_SEEK_END 3
 
54 #endif /* INTERFACE */
55
56 /*
57 ** Make sure a blob is initialized
58 */
59
+3 -3
--- src/main.c
+++ src/main.c
@@ -679,13 +679,13 @@
679679
}
680680
void fossil_free(void *p){
681681
free(p);
682682
}
683683
void *fossil_realloc(void *p, size_t n){
684
- p = realloc(p, n);
685
- if( p==0 ) fossil_panic("out of memory");
686
- return p;
684
+ void * re = realloc(p, n);
685
+ if( re==0 && n>0 ) fossil_panic("out of memory");
686
+ return (n > 0) ? re : 0;
687687
}
688688
689689
/*
690690
** This function implements a cross-platform "system()" interface.
691691
*/
692692
--- src/main.c
+++ src/main.c
@@ -679,13 +679,13 @@
679 }
680 void fossil_free(void *p){
681 free(p);
682 }
683 void *fossil_realloc(void *p, size_t n){
684 p = realloc(p, n);
685 if( p==0 ) fossil_panic("out of memory");
686 return p;
687 }
688
689 /*
690 ** This function implements a cross-platform "system()" interface.
691 */
692
--- src/main.c
+++ src/main.c
@@ -679,13 +679,13 @@
679 }
680 void fossil_free(void *p){
681 free(p);
682 }
683 void *fossil_realloc(void *p, size_t n){
684 void * re = realloc(p, n);
685 if( re==0 && n>0 ) fossil_panic("out of memory");
686 return (n > 0) ? re : 0;
687 }
688
689 /*
690 ** This function implements a cross-platform "system()" interface.
691 */
692
+272 -5
--- src/th.c
+++ src/th.c
@@ -6,10 +6,20 @@
66
77
#include "th.h"
88
#include <string.h>
99
#include <assert.h>
1010
#include <stdio.h> /* FILE class */
11
+#ifdef TH_USE_OUTBUF
12
+#ifndef INTERFACE
13
+#include "blob.h"
14
+#endif
15
+#endif
16
+
17
+extern void *fossil_realloc(void *p, size_t n);
18
+static void * th_fossil_realloc(void *p, unsigned int n){
19
+ return fossil_realloc( p, n );
20
+}
1121
1222
typedef struct Th_Command Th_Command;
1323
typedef struct Th_Frame Th_Frame;
1424
typedef struct Th_Variable Th_Variable;
1525
@@ -1377,20 +1387,26 @@
13771387
13781388
/*
13791389
** Wrappers around the supplied malloc() and free()
13801390
*/
13811391
void *Th_Malloc(Th_Interp *pInterp, int nByte){
1382
- void *p = pInterp->pVtab->xMalloc(nByte);
1392
+ void * p = pInterp->pVtab->xRealloc(NULL, nByte);
13831393
if( p ){
13841394
memset(p, 0, nByte);
1395
+ }else{
1396
+ assert( 0 == nByte );
13851397
}
13861398
return p;
13871399
}
13881400
void Th_Free(Th_Interp *pInterp, void *z){
13891401
if( z ){
1390
- pInterp->pVtab->xFree(z);
1402
+ pInterp->pVtab->xRealloc(z, 0);
13911403
}
1404
+}
1405
+void *Th_Realloc(Th_Interp *pInterp, void *z, int nByte){
1406
+ void *p = pInterp->pVtab->xRealloc(z, nByte);
1407
+ return p;
13921408
}
13931409
13941410
13951411
int Th_Vtab_output( Th_Vtab *vTab, char const * zData, int nData ){
13961412
if(!vTab->out.f){
@@ -1707,11 +1723,11 @@
17071723
*/
17081724
Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){
17091725
Th_Interp *p;
17101726
17111727
/* Allocate and initialise the interpreter and the global frame */
1712
- p = pVtab->xMalloc(sizeof(Th_Interp) + sizeof(Th_Frame));
1728
+ p = pVtab->xRealloc(NULL, sizeof(Th_Interp) + sizeof(Th_Frame));
17131729
memset(p, 0, sizeof(Th_Interp));
17141730
p->pVtab = pVtab;
17151731
p->paCmd = Th_HashNew(p);
17161732
thPushFrame(p, (Th_Frame *)&p[1]);
17171733
@@ -2383,11 +2399,11 @@
23832399
}
23842400
23852401
#ifndef LONGDOUBLE_TYPE
23862402
# define LONGDOUBLE_TYPE long double
23872403
#endif
2388
-typedef char u8;
2404
+/*typedef char u8;*/
23892405
23902406
23912407
/*
23922408
** Return TRUE if z is a pure numeric string. Return FALSE if the
23932409
** string contains any character which is not part of a number. If
@@ -2686,11 +2702,10 @@
26862702
return Th_SetResult(interp, zBuf, -1);
26872703
}
26882704
26892705
26902706
#ifdef TH_USE_SQLITE
2691
-extern void *fossil_realloc(void *p, size_t n);
26922707
int Th_AddStmt(Th_Interp *interp, sqlite3_stmt * pStmt){
26932708
int i, x;
26942709
sqlite3_stmt * s;
26952710
sqlite3_stmt ** list = interp->stmt.aStmt;
26962711
for( i = 0; i < interp->stmt.nStmt; ++i ){
@@ -2733,5 +2748,257 @@
27332748
: interp->stmt.aStmt[stmtId-1];
27342749
}
27352750
27362751
#endif
27372752
/* end TH_USE_SQLITE */
2753
+
2754
+
2755
+#ifdef TH_USE_OUTBUF
2756
+struct Th_Ob_Man {
2757
+ Blob ** aBuf;
2758
+ int nBuf;
2759
+ int cursor;
2760
+ Th_Interp * interp;
2761
+ Th_Vtab ** aVtab;
2762
+};
2763
+
2764
+typedef struct Th_Ob_Man Th_Ob_Man;
2765
+#define Th_Ob_Man_empty_m { NULL, 0, -1, NULL, NULL }
2766
+static const Th_Ob_Man Th_Ob_Man_empty = Th_Ob_Man_empty_m;
2767
+static Th_Ob_Man Th_Ob_Man_instance = Th_Ob_Man_empty_m;
2768
+
2769
+static Blob * Th_ob_current( Th_Ob_Man * pMan ){
2770
+ return pMan->nBuf>0 ? pMan->aBuf[pMan->cursor] : 0;
2771
+}
2772
+
2773
+
2774
+static int Th_output_ob( char const * zData, int len, void * pState ){
2775
+ Th_Ob_Man * pMan = (Th_Ob_Man*)pState;
2776
+ Blob * b = Th_ob_current( pMan );
2777
+ assert( NULL != pMan );
2778
+ assert( b );
2779
+ blob_append( b, zData, len );
2780
+ return len;
2781
+}
2782
+
2783
+static Th_Vtab Th_Vtab_Ob = { th_fossil_realloc,
2784
+ {
2785
+ Th_output_ob,
2786
+ NULL,
2787
+ 1
2788
+ }
2789
+};
2790
+
2791
+#if 0
2792
+#define OB_MALLOC(I,N) malloc((N))
2793
+#define OB_REALLOC(I,P,N) realloc((P),(N))
2794
+#define OB_FREE(I,P) free((P))
2795
+#else
2796
+#define OB_MALLOC(I,N) Th_Malloc((I),(N))
2797
+#define OB_REALLOC(I,P,N) Th_Realloc((I),(P),(N))
2798
+#define OB_FREE(I,P) Th_Free((I),(P))
2799
+#endif
2800
+int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut ){
2801
+ Blob * pBlob;
2802
+ int x, i;
2803
+ assert( NULL != pMan->interp );
2804
+ pBlob = (Blob *)OB_MALLOC(pMan->interp, sizeof(Blob));
2805
+ *pBlob = empty_blob;
2806
+
2807
+ if( pMan->cursor <= pMan->nBuf ){
2808
+ /* expand if needed */
2809
+ x = (pMan->cursor>0 ? pMan->cursor : 1) * 2;
2810
+ /*fprintf(stderr,"OB EXPAND x=%d\n",x);*/
2811
+ void * re = OB_REALLOC( pMan->interp, pMan->aBuf, x * sizeof(Blob*) );
2812
+ if(NULL==re){
2813
+ goto error;
2814
+ }
2815
+ pMan->aBuf = (Blob **)re;
2816
+ re = OB_REALLOC( pMan->interp, pMan->aVtab, x * sizeof(Th_Vtab*) );
2817
+ if(NULL==re){
2818
+ goto error;
2819
+ }
2820
+ pMan->aVtab = (Th_Vtab**)re;
2821
+ for( i = pMan->nBuf; i < x; ++i ){
2822
+ pMan->aVtab[i] = NULL;
2823
+ pMan->aBuf[i] = NULL;
2824
+ }
2825
+ pMan->nBuf = x;
2826
+ }
2827
+ assert( pMan->nBuf > pMan->cursor );
2828
+ assert( pMan->cursor >= -1 );
2829
+ ++pMan->cursor;
2830
+ pMan->aBuf[pMan->cursor] = pBlob;
2831
+ pMan->aVtab[pMan->cursor] = pMan->interp->pVtab;
2832
+ pMan->interp->pVtab = &Th_Vtab_Ob;
2833
+ Th_Vtab_Ob.out.pState = pMan;
2834
+ if( pOut ){
2835
+ *pOut = pBlob;
2836
+ }
2837
+ /*fprintf(stderr,"OB PUSH: %p\n", pBlob);*/
2838
+ return TH_OK;
2839
+ error:
2840
+ if( pBlob ){
2841
+ OB_FREE( pMan->interp, pBlob );
2842
+ }
2843
+ return TH_ERROR;
2844
+}
2845
+
2846
+Blob * Th_ob_pop( Th_Ob_Man * pMan ){
2847
+ if( pMan->cursor < 0 ){
2848
+ return NULL;
2849
+ }else{
2850
+ Blob * rc;
2851
+ assert( pMan->nBuf > pMan->cursor );
2852
+ rc = pMan->aBuf[pMan->cursor];
2853
+ pMan->aBuf[pMan->cursor] = NULL;
2854
+ pMan->interp->pVtab = pMan->aVtab[pMan->cursor];
2855
+ pMan->aVtab[pMan->cursor] = NULL;
2856
+ if(-1 == --pMan->cursor){
2857
+ OB_FREE( pMan->interp, pMan->aBuf );
2858
+ OB_FREE( pMan->interp, pMan->aVtab );
2859
+ *pMan = Th_Ob_Man_empty;
2860
+ }
2861
+ /*fprintf(stderr,"OB pop: %p level=%d\n", rc, pMan->cursor-1);*/
2862
+ return rc;
2863
+ }
2864
+}
2865
+
2866
+static int ob_clean_command( Th_Interp *interp, void *ctx,
2867
+ int argc, const char **argv, int *argl
2868
+){
2869
+ Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2870
+ Blob * b;
2871
+ assert( pMan && (interp == pMan->interp) );
2872
+ b = pMan ? Th_ob_current(pMan) : NULL;
2873
+ if(!b){
2874
+ Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2875
+ return TH_ERROR;
2876
+ }else{
2877
+ blob_reset(b);
2878
+ }
2879
+ return TH_OK;
2880
+}
2881
+
2882
+static int ob_end_command( Th_Interp *interp, void *ctx,
2883
+ int argc, const char **argv, int *argl ){
2884
+ Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2885
+ Blob * b;
2886
+ assert( pMan && (interp == pMan->interp) );
2887
+ b = Th_ob_pop(pMan);
2888
+ if(!b){
2889
+ Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2890
+ return TH_ERROR;
2891
+ }else{
2892
+ blob_reset(b);
2893
+ OB_FREE( interp, b );
2894
+ }
2895
+ return TH_OK;
2896
+}
2897
+
2898
+static int ob_flush_command( Th_Interp *interp, void *ctx,
2899
+ int argc, const char **argv, int *argl ){
2900
+ Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2901
+ Blob * b = NULL;
2902
+ Th_Vtab * oldVtab;
2903
+ assert( pMan && (interp == pMan->interp) );
2904
+ b = Th_ob_current(pMan);
2905
+ if( NULL == b ){
2906
+ Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2907
+ return TH_ERROR;
2908
+ }
2909
+ oldVtab = interp->pVtab;
2910
+ interp->pVtab = pMan->aVtab[pMan->cursor];
2911
+ Th_output( interp, blob_str(b), b->nUsed );
2912
+ interp->pVtab = oldVtab;
2913
+ blob_reset(b);
2914
+ return TH_OK;
2915
+}
2916
+
2917
+static int ob_get_command( Th_Interp *interp, void *ctx,
2918
+ int argc, const char **argv, int *argl){
2919
+ Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2920
+ Blob * b = NULL;
2921
+ assert( pMan && (interp == pMan->interp) );
2922
+ b = Th_ob_current(pMan);
2923
+ if( NULL == b ){
2924
+ Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2925
+ return TH_ERROR;
2926
+ }else{
2927
+ int argPos = 2;
2928
+ char const * sub;
2929
+ int subL;
2930
+ int rc = TH_OK;
2931
+ Th_SetResult( interp, blob_str(b), b->nUsed );
2932
+ if(argc>=argPos){
2933
+ sub = argv[argPos];
2934
+ subL = argl[argPos];
2935
+ /* "ob get clean" */
2936
+ if(!rc && th_strlen(sub)==5 && 0==memcmp("clean", sub, subL)){
2937
+ rc |= ob_clean_command(interp, ctx, argc-1, argv+1, argl+1);
2938
+ }/* "ob get end" */
2939
+ else if(!rc && th_strlen(sub)==3 && 0==memcmp("end", sub, subL)){
2940
+ rc |= ob_end_command(interp, ctx, argc-1, argv+1, argl+1);
2941
+ }
2942
+ }
2943
+ return rc;
2944
+ }
2945
+}
2946
+
2947
+static int ob_start_command( Th_Interp *interp, void *ctx,
2948
+ int argc, const char **argv, int *argl
2949
+){
2950
+ Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2951
+ Blob * b = NULL;
2952
+ int rc;
2953
+ assert( pMan && (interp == pMan->interp) );
2954
+ rc = Th_ob_push(pMan, &b);
2955
+ if( TH_OK != rc ){
2956
+ assert( NULL == b );
2957
+ return rc;
2958
+ }
2959
+ assert( NULL != b );
2960
+ /*fprintf(stderr,"OB STARTED: %p level=%d\n", b, pMan->cursor);*/
2961
+ Th_SetResultInt( interp, pMan->cursor );
2962
+ return TH_OK;
2963
+}
2964
+
2965
+static int ob_cmd(
2966
+ Th_Interp *interp,
2967
+ void *ignored,
2968
+ int argc,
2969
+ const char **argv,
2970
+ int *argl
2971
+){
2972
+ static Th_Ob_Man * pMan = &Th_Ob_Man_instance;
2973
+ Th_SubCommand aSub[] = {
2974
+ { "clean", ob_clean_command },
2975
+ { "end", ob_end_command },
2976
+ { "flush", ob_flush_command },
2977
+ { "get", ob_get_command },
2978
+ { "start", ob_start_command },
2979
+ { 0, 0 }
2980
+ };
2981
+ if(NULL == pMan->interp){
2982
+ pMan->interp = interp;
2983
+ /*
2984
+ FIXME: add rudamentary at-finalization GC to Th_Interp and clean
2985
+ this up there.
2986
+ */
2987
+ }
2988
+ return Th_CallSubCommand(interp, pMan, argc, argv, argl, aSub);
2989
+
2990
+}
2991
+
2992
+int th_register_ob(Th_Interp * interp){
2993
+ static Th_Command_Reg aCommand[] = {
2994
+ {"ob", ob_cmd, 0},
2995
+ {0,0,0}
2996
+ };
2997
+ return Th_register_commands( interp, aCommand );
2998
+}
2999
+#undef OB_MALLOC
3000
+#undef OB_REALLOC
3001
+#undef OB_FREE
3002
+#endif
3003
+/* end TH_USE_OUTBUF */
3004
+
27383005
--- src/th.c
+++ src/th.c
@@ -6,10 +6,20 @@
6
7 #include "th.h"
8 #include <string.h>
9 #include <assert.h>
10 #include <stdio.h> /* FILE class */
 
 
 
 
 
 
 
 
 
 
11
12 typedef struct Th_Command Th_Command;
13 typedef struct Th_Frame Th_Frame;
14 typedef struct Th_Variable Th_Variable;
15
@@ -1377,20 +1387,26 @@
1377
1378 /*
1379 ** Wrappers around the supplied malloc() and free()
1380 */
1381 void *Th_Malloc(Th_Interp *pInterp, int nByte){
1382 void *p = pInterp->pVtab->xMalloc(nByte);
1383 if( p ){
1384 memset(p, 0, nByte);
 
 
1385 }
1386 return p;
1387 }
1388 void Th_Free(Th_Interp *pInterp, void *z){
1389 if( z ){
1390 pInterp->pVtab->xFree(z);
1391 }
 
 
 
 
1392 }
1393
1394
1395 int Th_Vtab_output( Th_Vtab *vTab, char const * zData, int nData ){
1396 if(!vTab->out.f){
@@ -1707,11 +1723,11 @@
1707 */
1708 Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){
1709 Th_Interp *p;
1710
1711 /* Allocate and initialise the interpreter and the global frame */
1712 p = pVtab->xMalloc(sizeof(Th_Interp) + sizeof(Th_Frame));
1713 memset(p, 0, sizeof(Th_Interp));
1714 p->pVtab = pVtab;
1715 p->paCmd = Th_HashNew(p);
1716 thPushFrame(p, (Th_Frame *)&p[1]);
1717
@@ -2383,11 +2399,11 @@
2383 }
2384
2385 #ifndef LONGDOUBLE_TYPE
2386 # define LONGDOUBLE_TYPE long double
2387 #endif
2388 typedef char u8;
2389
2390
2391 /*
2392 ** Return TRUE if z is a pure numeric string. Return FALSE if the
2393 ** string contains any character which is not part of a number. If
@@ -2686,11 +2702,10 @@
2686 return Th_SetResult(interp, zBuf, -1);
2687 }
2688
2689
2690 #ifdef TH_USE_SQLITE
2691 extern void *fossil_realloc(void *p, size_t n);
2692 int Th_AddStmt(Th_Interp *interp, sqlite3_stmt * pStmt){
2693 int i, x;
2694 sqlite3_stmt * s;
2695 sqlite3_stmt ** list = interp->stmt.aStmt;
2696 for( i = 0; i < interp->stmt.nStmt; ++i ){
@@ -2733,5 +2748,257 @@
2733 : interp->stmt.aStmt[stmtId-1];
2734 }
2735
2736 #endif
2737 /* end TH_USE_SQLITE */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2738
--- src/th.c
+++ src/th.c
@@ -6,10 +6,20 @@
6
7 #include "th.h"
8 #include <string.h>
9 #include <assert.h>
10 #include <stdio.h> /* FILE class */
11 #ifdef TH_USE_OUTBUF
12 #ifndef INTERFACE
13 #include "blob.h"
14 #endif
15 #endif
16
17 extern void *fossil_realloc(void *p, size_t n);
18 static void * th_fossil_realloc(void *p, unsigned int n){
19 return fossil_realloc( p, n );
20 }
21
22 typedef struct Th_Command Th_Command;
23 typedef struct Th_Frame Th_Frame;
24 typedef struct Th_Variable Th_Variable;
25
@@ -1377,20 +1387,26 @@
1387
1388 /*
1389 ** Wrappers around the supplied malloc() and free()
1390 */
1391 void *Th_Malloc(Th_Interp *pInterp, int nByte){
1392 void * p = pInterp->pVtab->xRealloc(NULL, nByte);
1393 if( p ){
1394 memset(p, 0, nByte);
1395 }else{
1396 assert( 0 == nByte );
1397 }
1398 return p;
1399 }
1400 void Th_Free(Th_Interp *pInterp, void *z){
1401 if( z ){
1402 pInterp->pVtab->xRealloc(z, 0);
1403 }
1404 }
1405 void *Th_Realloc(Th_Interp *pInterp, void *z, int nByte){
1406 void *p = pInterp->pVtab->xRealloc(z, nByte);
1407 return p;
1408 }
1409
1410
1411 int Th_Vtab_output( Th_Vtab *vTab, char const * zData, int nData ){
1412 if(!vTab->out.f){
@@ -1707,11 +1723,11 @@
1723 */
1724 Th_Interp * Th_CreateInterp(Th_Vtab *pVtab){
1725 Th_Interp *p;
1726
1727 /* Allocate and initialise the interpreter and the global frame */
1728 p = pVtab->xRealloc(NULL, sizeof(Th_Interp) + sizeof(Th_Frame));
1729 memset(p, 0, sizeof(Th_Interp));
1730 p->pVtab = pVtab;
1731 p->paCmd = Th_HashNew(p);
1732 thPushFrame(p, (Th_Frame *)&p[1]);
1733
@@ -2383,11 +2399,11 @@
2399 }
2400
2401 #ifndef LONGDOUBLE_TYPE
2402 # define LONGDOUBLE_TYPE long double
2403 #endif
2404 /*typedef char u8;*/
2405
2406
2407 /*
2408 ** Return TRUE if z is a pure numeric string. Return FALSE if the
2409 ** string contains any character which is not part of a number. If
@@ -2686,11 +2702,10 @@
2702 return Th_SetResult(interp, zBuf, -1);
2703 }
2704
2705
2706 #ifdef TH_USE_SQLITE
 
2707 int Th_AddStmt(Th_Interp *interp, sqlite3_stmt * pStmt){
2708 int i, x;
2709 sqlite3_stmt * s;
2710 sqlite3_stmt ** list = interp->stmt.aStmt;
2711 for( i = 0; i < interp->stmt.nStmt; ++i ){
@@ -2733,5 +2748,257 @@
2748 : interp->stmt.aStmt[stmtId-1];
2749 }
2750
2751 #endif
2752 /* end TH_USE_SQLITE */
2753
2754
2755 #ifdef TH_USE_OUTBUF
2756 struct Th_Ob_Man {
2757 Blob ** aBuf;
2758 int nBuf;
2759 int cursor;
2760 Th_Interp * interp;
2761 Th_Vtab ** aVtab;
2762 };
2763
2764 typedef struct Th_Ob_Man Th_Ob_Man;
2765 #define Th_Ob_Man_empty_m { NULL, 0, -1, NULL, NULL }
2766 static const Th_Ob_Man Th_Ob_Man_empty = Th_Ob_Man_empty_m;
2767 static Th_Ob_Man Th_Ob_Man_instance = Th_Ob_Man_empty_m;
2768
2769 static Blob * Th_ob_current( Th_Ob_Man * pMan ){
2770 return pMan->nBuf>0 ? pMan->aBuf[pMan->cursor] : 0;
2771 }
2772
2773
2774 static int Th_output_ob( char const * zData, int len, void * pState ){
2775 Th_Ob_Man * pMan = (Th_Ob_Man*)pState;
2776 Blob * b = Th_ob_current( pMan );
2777 assert( NULL != pMan );
2778 assert( b );
2779 blob_append( b, zData, len );
2780 return len;
2781 }
2782
2783 static Th_Vtab Th_Vtab_Ob = { th_fossil_realloc,
2784 {
2785 Th_output_ob,
2786 NULL,
2787 1
2788 }
2789 };
2790
2791 #if 0
2792 #define OB_MALLOC(I,N) malloc((N))
2793 #define OB_REALLOC(I,P,N) realloc((P),(N))
2794 #define OB_FREE(I,P) free((P))
2795 #else
2796 #define OB_MALLOC(I,N) Th_Malloc((I),(N))
2797 #define OB_REALLOC(I,P,N) Th_Realloc((I),(P),(N))
2798 #define OB_FREE(I,P) Th_Free((I),(P))
2799 #endif
2800 int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut ){
2801 Blob * pBlob;
2802 int x, i;
2803 assert( NULL != pMan->interp );
2804 pBlob = (Blob *)OB_MALLOC(pMan->interp, sizeof(Blob));
2805 *pBlob = empty_blob;
2806
2807 if( pMan->cursor <= pMan->nBuf ){
2808 /* expand if needed */
2809 x = (pMan->cursor>0 ? pMan->cursor : 1) * 2;
2810 /*fprintf(stderr,"OB EXPAND x=%d\n",x);*/
2811 void * re = OB_REALLOC( pMan->interp, pMan->aBuf, x * sizeof(Blob*) );
2812 if(NULL==re){
2813 goto error;
2814 }
2815 pMan->aBuf = (Blob **)re;
2816 re = OB_REALLOC( pMan->interp, pMan->aVtab, x * sizeof(Th_Vtab*) );
2817 if(NULL==re){
2818 goto error;
2819 }
2820 pMan->aVtab = (Th_Vtab**)re;
2821 for( i = pMan->nBuf; i < x; ++i ){
2822 pMan->aVtab[i] = NULL;
2823 pMan->aBuf[i] = NULL;
2824 }
2825 pMan->nBuf = x;
2826 }
2827 assert( pMan->nBuf > pMan->cursor );
2828 assert( pMan->cursor >= -1 );
2829 ++pMan->cursor;
2830 pMan->aBuf[pMan->cursor] = pBlob;
2831 pMan->aVtab[pMan->cursor] = pMan->interp->pVtab;
2832 pMan->interp->pVtab = &Th_Vtab_Ob;
2833 Th_Vtab_Ob.out.pState = pMan;
2834 if( pOut ){
2835 *pOut = pBlob;
2836 }
2837 /*fprintf(stderr,"OB PUSH: %p\n", pBlob);*/
2838 return TH_OK;
2839 error:
2840 if( pBlob ){
2841 OB_FREE( pMan->interp, pBlob );
2842 }
2843 return TH_ERROR;
2844 }
2845
2846 Blob * Th_ob_pop( Th_Ob_Man * pMan ){
2847 if( pMan->cursor < 0 ){
2848 return NULL;
2849 }else{
2850 Blob * rc;
2851 assert( pMan->nBuf > pMan->cursor );
2852 rc = pMan->aBuf[pMan->cursor];
2853 pMan->aBuf[pMan->cursor] = NULL;
2854 pMan->interp->pVtab = pMan->aVtab[pMan->cursor];
2855 pMan->aVtab[pMan->cursor] = NULL;
2856 if(-1 == --pMan->cursor){
2857 OB_FREE( pMan->interp, pMan->aBuf );
2858 OB_FREE( pMan->interp, pMan->aVtab );
2859 *pMan = Th_Ob_Man_empty;
2860 }
2861 /*fprintf(stderr,"OB pop: %p level=%d\n", rc, pMan->cursor-1);*/
2862 return rc;
2863 }
2864 }
2865
2866 static int ob_clean_command( Th_Interp *interp, void *ctx,
2867 int argc, const char **argv, int *argl
2868 ){
2869 Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2870 Blob * b;
2871 assert( pMan && (interp == pMan->interp) );
2872 b = pMan ? Th_ob_current(pMan) : NULL;
2873 if(!b){
2874 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2875 return TH_ERROR;
2876 }else{
2877 blob_reset(b);
2878 }
2879 return TH_OK;
2880 }
2881
2882 static int ob_end_command( Th_Interp *interp, void *ctx,
2883 int argc, const char **argv, int *argl ){
2884 Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2885 Blob * b;
2886 assert( pMan && (interp == pMan->interp) );
2887 b = Th_ob_pop(pMan);
2888 if(!b){
2889 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2890 return TH_ERROR;
2891 }else{
2892 blob_reset(b);
2893 OB_FREE( interp, b );
2894 }
2895 return TH_OK;
2896 }
2897
2898 static int ob_flush_command( Th_Interp *interp, void *ctx,
2899 int argc, const char **argv, int *argl ){
2900 Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2901 Blob * b = NULL;
2902 Th_Vtab * oldVtab;
2903 assert( pMan && (interp == pMan->interp) );
2904 b = Th_ob_current(pMan);
2905 if( NULL == b ){
2906 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2907 return TH_ERROR;
2908 }
2909 oldVtab = interp->pVtab;
2910 interp->pVtab = pMan->aVtab[pMan->cursor];
2911 Th_output( interp, blob_str(b), b->nUsed );
2912 interp->pVtab = oldVtab;
2913 blob_reset(b);
2914 return TH_OK;
2915 }
2916
2917 static int ob_get_command( Th_Interp *interp, void *ctx,
2918 int argc, const char **argv, int *argl){
2919 Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2920 Blob * b = NULL;
2921 assert( pMan && (interp == pMan->interp) );
2922 b = Th_ob_current(pMan);
2923 if( NULL == b ){
2924 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2925 return TH_ERROR;
2926 }else{
2927 int argPos = 2;
2928 char const * sub;
2929 int subL;
2930 int rc = TH_OK;
2931 Th_SetResult( interp, blob_str(b), b->nUsed );
2932 if(argc>=argPos){
2933 sub = argv[argPos];
2934 subL = argl[argPos];
2935 /* "ob get clean" */
2936 if(!rc && th_strlen(sub)==5 && 0==memcmp("clean", sub, subL)){
2937 rc |= ob_clean_command(interp, ctx, argc-1, argv+1, argl+1);
2938 }/* "ob get end" */
2939 else if(!rc && th_strlen(sub)==3 && 0==memcmp("end", sub, subL)){
2940 rc |= ob_end_command(interp, ctx, argc-1, argv+1, argl+1);
2941 }
2942 }
2943 return rc;
2944 }
2945 }
2946
2947 static int ob_start_command( Th_Interp *interp, void *ctx,
2948 int argc, const char **argv, int *argl
2949 ){
2950 Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2951 Blob * b = NULL;
2952 int rc;
2953 assert( pMan && (interp == pMan->interp) );
2954 rc = Th_ob_push(pMan, &b);
2955 if( TH_OK != rc ){
2956 assert( NULL == b );
2957 return rc;
2958 }
2959 assert( NULL != b );
2960 /*fprintf(stderr,"OB STARTED: %p level=%d\n", b, pMan->cursor);*/
2961 Th_SetResultInt( interp, pMan->cursor );
2962 return TH_OK;
2963 }
2964
2965 static int ob_cmd(
2966 Th_Interp *interp,
2967 void *ignored,
2968 int argc,
2969 const char **argv,
2970 int *argl
2971 ){
2972 static Th_Ob_Man * pMan = &Th_Ob_Man_instance;
2973 Th_SubCommand aSub[] = {
2974 { "clean", ob_clean_command },
2975 { "end", ob_end_command },
2976 { "flush", ob_flush_command },
2977 { "get", ob_get_command },
2978 { "start", ob_start_command },
2979 { 0, 0 }
2980 };
2981 if(NULL == pMan->interp){
2982 pMan->interp = interp;
2983 /*
2984 FIXME: add rudamentary at-finalization GC to Th_Interp and clean
2985 this up there.
2986 */
2987 }
2988 return Th_CallSubCommand(interp, pMan, argc, argv, argl, aSub);
2989
2990 }
2991
2992 int th_register_ob(Th_Interp * interp){
2993 static Th_Command_Reg aCommand[] = {
2994 {"ob", ob_cmd, 0},
2995 {0,0,0}
2996 };
2997 return Th_register_commands( interp, aCommand );
2998 }
2999 #undef OB_MALLOC
3000 #undef OB_REALLOC
3001 #undef OB_FREE
3002 #endif
3003 /* end TH_USE_OUTBUF */
3004
3005
+11 -11
--- src/th.h
+++ src/th.h
@@ -1,15 +1,18 @@
1
+#include "config.h"
12
2
-#ifdef TH_USE_SQLITE
3
-#if 0==TH_USE_SQLITE
4
-#undef TH_USE_SQLITE
5
-#endif
6
-#endif
73
#define TH_USE_SQLITE
84
#ifdef TH_USE_SQLITE
95
#include "sqlite3.h"
106
#endif
7
+
8
+/*
9
+** TH_USE_OUTBUF, if defined, enables the "ob" family of functions.
10
+*/
11
+#define TH_USE_OUTBUF
12
+/*#undef TH_USE_OUTBUF*/
13
+
1114
1215
/* This header file defines the external interface to the custom Scripting
1316
** Language (TH) interpreter. TH is very similar to TCL but is not an
1417
** exact clone.
1518
*/
@@ -36,12 +39,11 @@
3639
** Before creating an interpreter, the application must allocate and
3740
** populate an instance of the following structure. It must remain valid
3841
** for the lifetime of the interpreter.
3942
*/
4043
struct Th_Vtab {
41
- void *(*xMalloc)(unsigned int);
42
- void (*xFree)(void *);
44
+ void *(*xRealloc)(void *, unsigned int);
4345
Th_Vtab_Output out;
4446
};
4547
typedef struct Th_Vtab Th_Vtab;
4648
4749
@@ -151,11 +153,11 @@
151153
** Access the memory management functions associated with the specified
152154
** interpreter.
153155
*/
154156
void *Th_Malloc(Th_Interp *, int);
155157
void Th_Free(Th_Interp *, void *);
156
-
158
+void *Th_Realloc(Th_Interp *, void *, int);
157159
/*
158160
** Functions for handling TH lists.
159161
*/
160162
int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
161163
int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
@@ -189,11 +191,11 @@
189191
int th_register_sqlite(Th_Interp *interp); /* th_main.c */
190192
int th_register_argv(Th_Interp *interp); /* th_main.c */
191193
int th_register_vfs(Th_Interp *interp); /* th_vfs.c */
192194
int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */
193195
int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
194
-
196
+int th_register_ob(Th_Interp * interp); /* th.c */
195197
/*
196198
** General purpose hash table from th_lang.c.
197199
*/
198200
typedef struct Th_Hash Th_Hash;
199201
typedef struct Th_HashEntry Th_HashEntry;
@@ -261,12 +263,10 @@
261263
** Returns TH_OK on success, "something else" on error.
262264
*/
263265
int Th_register_commands( Th_Interp * interp, Th_Command_Reg const * pList );
264266
265267
#ifdef TH_USE_SQLITE
266
-#include "stddef.h" /* size_t */
267
-extern void *fossil_realloc(void *p, size_t n);
268268
269269
/*
270270
** Adds the given prepared statement to the interpreter. Returns the
271271
** statements opaque identifier (a positive value). Ownerships of
272272
** pStmt is transfered to interp and it must be cleaned up by the
273273
--- src/th.h
+++ src/th.h
@@ -1,15 +1,18 @@
 
1
2 #ifdef TH_USE_SQLITE
3 #if 0==TH_USE_SQLITE
4 #undef TH_USE_SQLITE
5 #endif
6 #endif
7 #define TH_USE_SQLITE
8 #ifdef TH_USE_SQLITE
9 #include "sqlite3.h"
10 #endif
 
 
 
 
 
 
 
11
12 /* This header file defines the external interface to the custom Scripting
13 ** Language (TH) interpreter. TH is very similar to TCL but is not an
14 ** exact clone.
15 */
@@ -36,12 +39,11 @@
36 ** Before creating an interpreter, the application must allocate and
37 ** populate an instance of the following structure. It must remain valid
38 ** for the lifetime of the interpreter.
39 */
40 struct Th_Vtab {
41 void *(*xMalloc)(unsigned int);
42 void (*xFree)(void *);
43 Th_Vtab_Output out;
44 };
45 typedef struct Th_Vtab Th_Vtab;
46
47
@@ -151,11 +153,11 @@
151 ** Access the memory management functions associated with the specified
152 ** interpreter.
153 */
154 void *Th_Malloc(Th_Interp *, int);
155 void Th_Free(Th_Interp *, void *);
156
157 /*
158 ** Functions for handling TH lists.
159 */
160 int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
161 int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
@@ -189,11 +191,11 @@
189 int th_register_sqlite(Th_Interp *interp); /* th_main.c */
190 int th_register_argv(Th_Interp *interp); /* th_main.c */
191 int th_register_vfs(Th_Interp *interp); /* th_vfs.c */
192 int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */
193 int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
194
195 /*
196 ** General purpose hash table from th_lang.c.
197 */
198 typedef struct Th_Hash Th_Hash;
199 typedef struct Th_HashEntry Th_HashEntry;
@@ -261,12 +263,10 @@
261 ** Returns TH_OK on success, "something else" on error.
262 */
263 int Th_register_commands( Th_Interp * interp, Th_Command_Reg const * pList );
264
265 #ifdef TH_USE_SQLITE
266 #include "stddef.h" /* size_t */
267 extern void *fossil_realloc(void *p, size_t n);
268
269 /*
270 ** Adds the given prepared statement to the interpreter. Returns the
271 ** statements opaque identifier (a positive value). Ownerships of
272 ** pStmt is transfered to interp and it must be cleaned up by the
273
--- src/th.h
+++ src/th.h
@@ -1,15 +1,18 @@
1 #include "config.h"
2
 
 
 
 
 
3 #define TH_USE_SQLITE
4 #ifdef TH_USE_SQLITE
5 #include "sqlite3.h"
6 #endif
7
8 /*
9 ** TH_USE_OUTBUF, if defined, enables the "ob" family of functions.
10 */
11 #define TH_USE_OUTBUF
12 /*#undef TH_USE_OUTBUF*/
13
14
15 /* This header file defines the external interface to the custom Scripting
16 ** Language (TH) interpreter. TH is very similar to TCL but is not an
17 ** exact clone.
18 */
@@ -36,12 +39,11 @@
39 ** Before creating an interpreter, the application must allocate and
40 ** populate an instance of the following structure. It must remain valid
41 ** for the lifetime of the interpreter.
42 */
43 struct Th_Vtab {
44 void *(*xRealloc)(void *, unsigned int);
 
45 Th_Vtab_Output out;
46 };
47 typedef struct Th_Vtab Th_Vtab;
48
49
@@ -151,11 +153,11 @@
153 ** Access the memory management functions associated with the specified
154 ** interpreter.
155 */
156 void *Th_Malloc(Th_Interp *, int);
157 void Th_Free(Th_Interp *, void *);
158 void *Th_Realloc(Th_Interp *, void *, int);
159 /*
160 ** Functions for handling TH lists.
161 */
162 int Th_ListAppend(Th_Interp *, char **, int *, const char *, int);
163 int Th_SplitList(Th_Interp *, const char *, int, char ***, int **, int *);
@@ -189,11 +191,11 @@
191 int th_register_sqlite(Th_Interp *interp); /* th_main.c */
192 int th_register_argv(Th_Interp *interp); /* th_main.c */
193 int th_register_vfs(Th_Interp *interp); /* th_vfs.c */
194 int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */
195 int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
196 int th_register_ob(Th_Interp * interp); /* th.c */
197 /*
198 ** General purpose hash table from th_lang.c.
199 */
200 typedef struct Th_Hash Th_Hash;
201 typedef struct Th_HashEntry Th_HashEntry;
@@ -261,12 +263,10 @@
263 ** Returns TH_OK on success, "something else" on error.
264 */
265 int Th_register_commands( Th_Interp * interp, Th_Command_Reg const * pList );
266
267 #ifdef TH_USE_SQLITE
 
 
268
269 /*
270 ** Adds the given prepared statement to the interpreter. Returns the
271 ** statements opaque identifier (a positive value). Ownerships of
272 ** pStmt is transfered to interp and it must be cleaned up by the
273
+6 -1
--- src/th_lang.c
+++ src/th_lang.c
@@ -1037,10 +1037,11 @@
10371037
/*
10381038
** Register the built-in th1 language commands with interpreter interp.
10391039
** Usually this is called soon after interpreter creation.
10401040
*/
10411041
int th_register_language(Th_Interp *interp){
1042
+ int rc;
10421043
/* Array of built-in commands. */
10431044
struct Th_Command_Reg aCommand[] = {
10441045
{"catch", catch_command, 0},
10451046
{"expr", expr_command, 0},
10461047
{"for", for_command, 0},
@@ -1064,7 +1065,11 @@
10641065
{"continue", simple_command, (void *)TH_CONTINUE},
10651066
{"error", simple_command, (void *)TH_ERROR},
10661067
10671068
{0, 0, 0}
10681069
};
1069
- return Th_register_commands(interp, aCommand);
1070
+ rc = Th_register_commands(interp, aCommand);
1071
+#ifdef TH_USE_OUTBUF
1072
+ rc |= th_register_ob(interp);
1073
+#endif
1074
+ return rc;
10701075
}
10711076
--- src/th_lang.c
+++ src/th_lang.c
@@ -1037,10 +1037,11 @@
1037 /*
1038 ** Register the built-in th1 language commands with interpreter interp.
1039 ** Usually this is called soon after interpreter creation.
1040 */
1041 int th_register_language(Th_Interp *interp){
 
1042 /* Array of built-in commands. */
1043 struct Th_Command_Reg aCommand[] = {
1044 {"catch", catch_command, 0},
1045 {"expr", expr_command, 0},
1046 {"for", for_command, 0},
@@ -1064,7 +1065,11 @@
1064 {"continue", simple_command, (void *)TH_CONTINUE},
1065 {"error", simple_command, (void *)TH_ERROR},
1066
1067 {0, 0, 0}
1068 };
1069 return Th_register_commands(interp, aCommand);
 
 
 
 
1070 }
1071
--- src/th_lang.c
+++ src/th_lang.c
@@ -1037,10 +1037,11 @@
1037 /*
1038 ** Register the built-in th1 language commands with interpreter interp.
1039 ** Usually this is called soon after interpreter creation.
1040 */
1041 int th_register_language(Th_Interp *interp){
1042 int rc;
1043 /* Array of built-in commands. */
1044 struct Th_Command_Reg aCommand[] = {
1045 {"catch", catch_command, 0},
1046 {"expr", expr_command, 0},
1047 {"for", for_command, 0},
@@ -1064,7 +1065,11 @@
1065 {"continue", simple_command, (void *)TH_CONTINUE},
1066 {"error", simple_command, (void *)TH_ERROR},
1067
1068 {0, 0, 0}
1069 };
1070 rc = Th_register_commands(interp, aCommand);
1071 #ifdef TH_USE_OUTBUF
1072 rc |= th_register_ob(interp);
1073 #endif
1074 return rc;
1075 }
1076
+20 -5
--- src/th_main.c
+++ src/th_main.c
@@ -40,17 +40,31 @@
4040
}
4141
static void xFree(void *p){
4242
if( p ){
4343
nOutstandingMalloc--;
4444
}
45
- free(p);
45
+ fossil_free(p);
46
+}
47
+
48
+static void *xRealloc(void * p, unsigned int n){
49
+ if(0 == n){
50
+ xFree(p);
51
+ return NULL;
52
+ }else if(NULL == p){
53
+ return xMalloc(n);
54
+ }else{
55
+ return fossil_realloc(p, n)
56
+ /* FIXME: try to find some reasonable nOutstandingMalloc
57
+ heuristics, e.g. if !p then ++, if !n then --, etc.
58
+ */;
59
+ }
4660
}
4761
48
-static Th_Vtab vtab = { xMalloc, xFree, {
49
- NULL,
50
- NULL,
51
- 1
62
+static Th_Vtab vtab = { xRealloc, {
63
+ NULL,
64
+ NULL,
65
+ 1
5266
}
5367
};
5468
5569
/*
5670
** Generate a TH1 trace message if debugging is enabled.
@@ -727,10 +741,11 @@
727741
728742
#endif
729743
/* end TH_USE_ARGV */
730744
731745
#ifdef TH_USE_SQLITE
746
+
732747
/*
733748
** TH Syntax:
734749
**
735750
** query_prepare SQL
736751
**
737752
--- src/th_main.c
+++ src/th_main.c
@@ -40,17 +40,31 @@
40 }
41 static void xFree(void *p){
42 if( p ){
43 nOutstandingMalloc--;
44 }
45 free(p);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46 }
47
48 static Th_Vtab vtab = { xMalloc, xFree, {
49 NULL,
50 NULL,
51 1
52 }
53 };
54
55 /*
56 ** Generate a TH1 trace message if debugging is enabled.
@@ -727,10 +741,11 @@
727
728 #endif
729 /* end TH_USE_ARGV */
730
731 #ifdef TH_USE_SQLITE
 
732 /*
733 ** TH Syntax:
734 **
735 ** query_prepare SQL
736 **
737
--- src/th_main.c
+++ src/th_main.c
@@ -40,17 +40,31 @@
40 }
41 static void xFree(void *p){
42 if( p ){
43 nOutstandingMalloc--;
44 }
45 fossil_free(p);
46 }
47
48 static void *xRealloc(void * p, unsigned int n){
49 if(0 == n){
50 xFree(p);
51 return NULL;
52 }else if(NULL == p){
53 return xMalloc(n);
54 }else{
55 return fossil_realloc(p, n)
56 /* FIXME: try to find some reasonable nOutstandingMalloc
57 heuristics, e.g. if !p then ++, if !n then --, etc.
58 */;
59 }
60 }
61
62 static Th_Vtab vtab = { xRealloc, {
63 NULL,
64 NULL,
65 1
66 }
67 };
68
69 /*
70 ** Generate a TH1 trace message if debugging is enabled.
@@ -727,10 +741,11 @@
741
742 #endif
743 /* end TH_USE_ARGV */
744
745 #ifdef TH_USE_SQLITE
746
747 /*
748 ** TH Syntax:
749 **
750 ** query_prepare SQL
751 **
752

Keyboard Shortcuts

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