Fossil SCM

Added push/pop as aliases for start/end in the ob API. Fixed a horrible size calculation bug which triggered an assert() for ob nesting levels deeper than 2.

stephan 2012-07-15 09:23 th1-query-api
Commit 9b3a11e16095e2ce9ab1db03d0ada3a02f5046a1
1 file changed +35 -11
+35 -11
--- src/th.c
+++ src/th.c
@@ -2798,13 +2798,17 @@
27982798
int x, i;
27992799
assert( NULL != pMan->interp );
28002800
pBlob = (Blob *)Th_Malloc(pMan->interp, sizeof(Blob));
28012801
*pBlob = empty_blob;
28022802
2803
- if( pMan->cursor <= pMan->nBuf ){
2803
+ if( pMan->cursor >= pMan->nBuf-2 ){
28042804
/* expand if needed */
2805
- x = (pMan->cursor>0 ? pMan->cursor : 1) * 2;
2805
+ x = pMan->nBuf + 5;
2806
+ if( pMan->cursor >= x ) {
2807
+ assert( 0 && "This really should not happen." );
2808
+ x = pMan->cursor + 5;
2809
+ }
28062810
/*fprintf(stderr,"OB EXPAND x=%d\n",x);*/
28072811
void * re = Th_Realloc( pMan->interp, pMan->aBuf, x * sizeof(Blob*) );
28082812
if(NULL==re){
28092813
goto error;
28102814
}
@@ -2877,12 +2881,13 @@
28772881
if(!b){
28782882
Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
28792883
return TH_ERROR;
28802884
}else{
28812885
blob_reset(b);
2886
+ Th_SetResultInt( interp, 0 );
2887
+ return TH_OK;
28822888
}
2883
- return TH_OK;
28842889
}
28852890
28862891
/*
28872892
** TH Syntax:
28882893
**
@@ -2901,31 +2906,33 @@
29012906
Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
29022907
return TH_ERROR;
29032908
}else{
29042909
blob_reset(b);
29052910
Th_Free( interp, b );
2911
+ Th_SetResultInt( interp, 0 );
2912
+ return TH_OK;
29062913
}
2907
- return TH_OK;
29082914
}
29092915
29102916
/*
29112917
** TH Syntax:
29122918
**
2913
-** ob flush
2914
-**
2915
-** UNTESTED! Maybe not needed.
2919
+** ob flush ?pop|end?
29162920
**
29172921
** Briefly reverts the output layer to the next-lower
29182922
** level, flushes the current buffer to that output layer,
29192923
** and clears out the current buffer. Does not change the
2920
-** buffering level.
2924
+** buffering level unless "end" is specified, in which case
2925
+** it behaves as if "ob end" had been called (after flushing
2926
+** the buffer).
29212927
*/
29222928
static int ob_flush_command( Th_Interp *interp, void *ctx,
29232929
int argc, const char **argv, int *argl ){
29242930
Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
29252931
Blob * b = NULL;
29262932
Th_Vtab * oldVtab;
2933
+ int rc = TH_OK;
29272934
assert( pMan && (interp == pMan->interp) );
29282935
b = Th_ob_current(pMan);
29292936
if( NULL == b ){
29302937
Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
29312938
return TH_ERROR;
@@ -2933,17 +2940,30 @@
29332940
oldVtab = interp->pVtab;
29342941
interp->pVtab = pMan->aVtab[pMan->cursor];
29352942
Th_output( interp, blob_str(b), b->nUsed );
29362943
interp->pVtab = oldVtab;
29372944
blob_reset(b);
2938
- return TH_OK;
2945
+
2946
+ if(!rc && argc>2){
2947
+ int argPos = 2;
2948
+ char const * sub = argv[argPos];
2949
+ int subL = argl[argPos];
2950
+ /* "flush end" */
2951
+ if(th_strlen(sub)==3 &&
2952
+ ((0==memcmp("end", sub, subL)
2953
+ || (0==memcmp("pop", sub, subL))))){
2954
+ rc |= ob_end_command(interp, ctx, argc-1, argv+1, argl+1);
2955
+ }
2956
+ }
2957
+ Th_SetResultInt( interp, 0 );
2958
+ return rc;
29392959
}
29402960
29412961
/*
29422962
** TH Syntax:
29432963
**
2944
-** ob get ?clean|end?
2964
+** ob get ?clean|end|pop?
29452965
**
29462966
** Fetches the contents of the current buffer level. If either
29472967
** 'clean' or 'end' are specified then the effect is as if "ob clean"
29482968
** or "ob end", respectively, are called after fetching the
29492969
** value. Calling "ob get end" is functionality equivalent to "ob get"
@@ -2969,11 +2989,13 @@
29692989
subL = argl[argPos];
29702990
/* "ob get clean" */
29712991
if(!rc && th_strlen(sub)==5 && 0==memcmp("clean", sub, subL)){
29722992
rc |= ob_clean_command(interp, ctx, argc-1, argv+1, argl+1);
29732993
}/* "ob get end" */
2974
- else if(!rc && th_strlen(sub)==3 && 0==memcmp("end", sub, subL)){
2994
+ else if(!rc && th_strlen(sub)==3 &&
2995
+ ((0==memcmp("end", sub, subL))
2996
+ || (0==memcmp("pop", sub, subL)))){
29752997
rc |= ob_end_command(interp, ctx, argc-1, argv+1, argl+1);
29762998
}
29772999
}
29783000
return rc;
29793001
}
@@ -3041,10 +3063,12 @@
30413063
{ "clean", ob_clean_command },
30423064
{ "end", ob_end_command },
30433065
{ "flush", ob_flush_command },
30443066
{ "get", ob_get_command },
30453067
{ "level", ob_level_command },
3068
+ { "pop", ob_end_command },
3069
+ { "push", ob_start_command },
30463070
{ "start", ob_start_command },
30473071
{ 0, 0 }
30483072
};
30493073
if(NULL == pMan->interp){
30503074
pMan->interp = interp;
30513075
--- src/th.c
+++ src/th.c
@@ -2798,13 +2798,17 @@
2798 int x, i;
2799 assert( NULL != pMan->interp );
2800 pBlob = (Blob *)Th_Malloc(pMan->interp, sizeof(Blob));
2801 *pBlob = empty_blob;
2802
2803 if( pMan->cursor <= pMan->nBuf ){
2804 /* expand if needed */
2805 x = (pMan->cursor>0 ? pMan->cursor : 1) * 2;
 
 
 
 
2806 /*fprintf(stderr,"OB EXPAND x=%d\n",x);*/
2807 void * re = Th_Realloc( pMan->interp, pMan->aBuf, x * sizeof(Blob*) );
2808 if(NULL==re){
2809 goto error;
2810 }
@@ -2877,12 +2881,13 @@
2877 if(!b){
2878 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2879 return TH_ERROR;
2880 }else{
2881 blob_reset(b);
 
 
2882 }
2883 return TH_OK;
2884 }
2885
2886 /*
2887 ** TH Syntax:
2888 **
@@ -2901,31 +2906,33 @@
2901 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2902 return TH_ERROR;
2903 }else{
2904 blob_reset(b);
2905 Th_Free( interp, b );
 
 
2906 }
2907 return TH_OK;
2908 }
2909
2910 /*
2911 ** TH Syntax:
2912 **
2913 ** ob flush
2914 **
2915 ** UNTESTED! Maybe not needed.
2916 **
2917 ** Briefly reverts the output layer to the next-lower
2918 ** level, flushes the current buffer to that output layer,
2919 ** and clears out the current buffer. Does not change the
2920 ** buffering level.
 
 
2921 */
2922 static int ob_flush_command( Th_Interp *interp, void *ctx,
2923 int argc, const char **argv, int *argl ){
2924 Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2925 Blob * b = NULL;
2926 Th_Vtab * oldVtab;
 
2927 assert( pMan && (interp == pMan->interp) );
2928 b = Th_ob_current(pMan);
2929 if( NULL == b ){
2930 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2931 return TH_ERROR;
@@ -2933,17 +2940,30 @@
2933 oldVtab = interp->pVtab;
2934 interp->pVtab = pMan->aVtab[pMan->cursor];
2935 Th_output( interp, blob_str(b), b->nUsed );
2936 interp->pVtab = oldVtab;
2937 blob_reset(b);
2938 return TH_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
2939 }
2940
2941 /*
2942 ** TH Syntax:
2943 **
2944 ** ob get ?clean|end?
2945 **
2946 ** Fetches the contents of the current buffer level. If either
2947 ** 'clean' or 'end' are specified then the effect is as if "ob clean"
2948 ** or "ob end", respectively, are called after fetching the
2949 ** value. Calling "ob get end" is functionality equivalent to "ob get"
@@ -2969,11 +2989,13 @@
2969 subL = argl[argPos];
2970 /* "ob get clean" */
2971 if(!rc && th_strlen(sub)==5 && 0==memcmp("clean", sub, subL)){
2972 rc |= ob_clean_command(interp, ctx, argc-1, argv+1, argl+1);
2973 }/* "ob get end" */
2974 else if(!rc && th_strlen(sub)==3 && 0==memcmp("end", sub, subL)){
 
 
2975 rc |= ob_end_command(interp, ctx, argc-1, argv+1, argl+1);
2976 }
2977 }
2978 return rc;
2979 }
@@ -3041,10 +3063,12 @@
3041 { "clean", ob_clean_command },
3042 { "end", ob_end_command },
3043 { "flush", ob_flush_command },
3044 { "get", ob_get_command },
3045 { "level", ob_level_command },
 
 
3046 { "start", ob_start_command },
3047 { 0, 0 }
3048 };
3049 if(NULL == pMan->interp){
3050 pMan->interp = interp;
3051
--- src/th.c
+++ src/th.c
@@ -2798,13 +2798,17 @@
2798 int x, i;
2799 assert( NULL != pMan->interp );
2800 pBlob = (Blob *)Th_Malloc(pMan->interp, sizeof(Blob));
2801 *pBlob = empty_blob;
2802
2803 if( pMan->cursor >= pMan->nBuf-2 ){
2804 /* expand if needed */
2805 x = pMan->nBuf + 5;
2806 if( pMan->cursor >= x ) {
2807 assert( 0 && "This really should not happen." );
2808 x = pMan->cursor + 5;
2809 }
2810 /*fprintf(stderr,"OB EXPAND x=%d\n",x);*/
2811 void * re = Th_Realloc( pMan->interp, pMan->aBuf, x * sizeof(Blob*) );
2812 if(NULL==re){
2813 goto error;
2814 }
@@ -2877,12 +2881,13 @@
2881 if(!b){
2882 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2883 return TH_ERROR;
2884 }else{
2885 blob_reset(b);
2886 Th_SetResultInt( interp, 0 );
2887 return TH_OK;
2888 }
 
2889 }
2890
2891 /*
2892 ** TH Syntax:
2893 **
@@ -2901,31 +2906,33 @@
2906 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2907 return TH_ERROR;
2908 }else{
2909 blob_reset(b);
2910 Th_Free( interp, b );
2911 Th_SetResultInt( interp, 0 );
2912 return TH_OK;
2913 }
 
2914 }
2915
2916 /*
2917 ** TH Syntax:
2918 **
2919 ** ob flush ?pop|end?
 
 
2920 **
2921 ** Briefly reverts the output layer to the next-lower
2922 ** level, flushes the current buffer to that output layer,
2923 ** and clears out the current buffer. Does not change the
2924 ** buffering level unless "end" is specified, in which case
2925 ** it behaves as if "ob end" had been called (after flushing
2926 ** the buffer).
2927 */
2928 static int ob_flush_command( Th_Interp *interp, void *ctx,
2929 int argc, const char **argv, int *argl ){
2930 Th_Ob_Man * pMan = (Th_Ob_Man *)ctx;
2931 Blob * b = NULL;
2932 Th_Vtab * oldVtab;
2933 int rc = TH_OK;
2934 assert( pMan && (interp == pMan->interp) );
2935 b = Th_ob_current(pMan);
2936 if( NULL == b ){
2937 Th_ErrorMessage( interp, "Not currently buffering.", NULL, 0 );
2938 return TH_ERROR;
@@ -2933,17 +2940,30 @@
2940 oldVtab = interp->pVtab;
2941 interp->pVtab = pMan->aVtab[pMan->cursor];
2942 Th_output( interp, blob_str(b), b->nUsed );
2943 interp->pVtab = oldVtab;
2944 blob_reset(b);
2945
2946 if(!rc && argc>2){
2947 int argPos = 2;
2948 char const * sub = argv[argPos];
2949 int subL = argl[argPos];
2950 /* "flush end" */
2951 if(th_strlen(sub)==3 &&
2952 ((0==memcmp("end", sub, subL)
2953 || (0==memcmp("pop", sub, subL))))){
2954 rc |= ob_end_command(interp, ctx, argc-1, argv+1, argl+1);
2955 }
2956 }
2957 Th_SetResultInt( interp, 0 );
2958 return rc;
2959 }
2960
2961 /*
2962 ** TH Syntax:
2963 **
2964 ** ob get ?clean|end|pop?
2965 **
2966 ** Fetches the contents of the current buffer level. If either
2967 ** 'clean' or 'end' are specified then the effect is as if "ob clean"
2968 ** or "ob end", respectively, are called after fetching the
2969 ** value. Calling "ob get end" is functionality equivalent to "ob get"
@@ -2969,11 +2989,13 @@
2989 subL = argl[argPos];
2990 /* "ob get clean" */
2991 if(!rc && th_strlen(sub)==5 && 0==memcmp("clean", sub, subL)){
2992 rc |= ob_clean_command(interp, ctx, argc-1, argv+1, argl+1);
2993 }/* "ob get end" */
2994 else if(!rc && th_strlen(sub)==3 &&
2995 ((0==memcmp("end", sub, subL))
2996 || (0==memcmp("pop", sub, subL)))){
2997 rc |= ob_end_command(interp, ctx, argc-1, argv+1, argl+1);
2998 }
2999 }
3000 return rc;
3001 }
@@ -3041,10 +3063,12 @@
3063 { "clean", ob_clean_command },
3064 { "end", ob_end_command },
3065 { "flush", ob_flush_command },
3066 { "get", ob_get_command },
3067 { "level", ob_level_command },
3068 { "pop", ob_end_command },
3069 { "push", ob_start_command },
3070 { "start", ob_start_command },
3071 { 0, 0 }
3072 };
3073 if(NULL == pMan->interp){
3074 pMan->interp = interp;
3075

Keyboard Shortcuts

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