Fossil

Check-in [3d243a56]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Minor cleanups. Made Th_Ob_Man opaque. Renamed TH_USE_xxx to TH_ENABLE_xxx.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | th1-query-api
Files: files | file ages | folders
SHA1: 3d243a5681fb177e124adbdc5e729248b1cff76c
User & Date: stephan 2012-07-15 13:14:37.412
Context
2012-07-15
14:31
th1 query API now accepts the statement ID as the first arg after the query command or later on after the subcommand, for all subcommands where this makes sense. ... (check-in: 09d7df15 user: stephan tags: th1-query-api)
13:14
Minor cleanups. Made Th_Ob_Man opaque. Renamed TH_USE_xxx to TH_ENABLE_xxx. ... (check-in: 3d243a56 user: stephan tags: th1-query-api)
12:52
Made a few more functions static. th1 ob doc additions. ... (check-in: 8027581c user: stephan tags: th1-query-api)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/th.c.
1
2
3
4
5
6
7
8
9
10

11











12
13
14
15
16
17
18

/*
** 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 */

#ifdef TH_USE_OUTBUF











#endif

extern void *fossil_realloc(void *p, size_t n);
static void * th_fossil_realloc(void *p, unsigned int n){
  return fossil_realloc( p, n );
}
static int Th_output_f_ob( char const * zData, int len, void * pState );










>
|
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

/*
** 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 */

#ifdef TH_ENABLE_OUTBUF
struct Th_Ob_Man {
  Blob ** aBuf;        /* Stack of Blobs */
  int nBuf;            /* Number of blobs */
  int cursor;          /* Current level (-1=not active) */
  Th_Interp * interp;  /* The associated interpreter */
  Th_Vtab_Output * aOutput
                       /* Stack of output routines corresponding
                          to the current buffering level.
                          Has nBuf entries.
                       */;
};
#endif

extern void *fossil_realloc(void *p, size_t n);
static void * th_fossil_realloc(void *p, unsigned int n){
  return fossil_realloc( p, n );
}
static int Th_output_f_ob( char const * zData, int len, void * pState );
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
    ? Th_HashFind(interp, interp->paGc, key, th_strlen(key), 0)
    : NULL;
  return e ? ((Th_GcEntry*)e->pData)->pData : NULL;
}



#ifdef TH_USE_OUTBUF
/* Reminder: the ob code "really" belongs in th_lang.c,
   but we need access to Th_Interp internals in order to
   swap out Th_Vtab parts for purposes of stacking layers
   of buffers.
*/
#define Th_Ob_Man_empty_m { \
  NULL/*aBuf*/,           \







|







2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
    ? Th_HashFind(interp, interp->paGc, key, th_strlen(key), 0)
    : NULL;
  return e ? ((Th_GcEntry*)e->pData)->pData : NULL;
}



#ifdef TH_ENABLE_OUTBUF
/* Reminder: the ob code "really" belongs in th_lang.c,
   but we need access to Th_Interp internals in order to
   swap out Th_Vtab parts for purposes of stacking layers
   of buffers.
*/
#define Th_Ob_Man_empty_m { \
  NULL/*aBuf*/,           \
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888

2889
2890
2891
2892
2893





2894
2895
2896
2897
2898
2899
2900
      assert(-1 == pMan->cursor);
    }
    /*printf( "post-pop: pMan->nBuf=%d, pMan->cursor=%d\n", pMan->nBuf, pMan->cursor);*/
    return rc;
  }
}

void Th_ob_cleanup( Th_Ob_Man * man ){
  Blob * b;
  while( (b = Th_ob_pop(man)) ){

    blob_reset(b);
    Th_Free( man->interp, b );
  }
}







/*
** TH Syntax:
**
** ob clean
**
** Erases any currently buffered contents but does not modify







|
|
|
>

|



>
>
>
>
>







2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
      assert(-1 == pMan->cursor);
    }
    /*printf( "post-pop: pMan->nBuf=%d, pMan->cursor=%d\n", pMan->nBuf, pMan->cursor);*/
    return rc;
  }
}

int Th_ob_pop_free( Th_Ob_Man * pMan ){
  Blob * b = Th_ob_pop( pMan );
  if(!b) return 1;
  else {
    blob_reset(b);
    Th_Free( pMan->interp, b );
  }
}


void Th_ob_cleanup( Th_Ob_Man * man ){
  while( 0 == Th_ob_pop_free(man) ){}
}


/*
** TH Syntax:
**
** ob clean
**
** Erases any currently buffered contents but does not modify
3141
3142
3143
3144
3145
3146
3147
3148
3149
  }
  return rc;
}

#undef Th_Ob_Man_empty_m
#undef Th_Ob_Man_KEY
#endif
/* end TH_USE_OUTBUF */








|

3159
3160
3161
3162
3163
3164
3165
3166
3167
  }
  return rc;
}

#undef Th_Ob_Man_empty_m
#undef Th_Ob_Man_KEY
#endif
/* end TH_ENABLE_OUTBUF */

Changes to src/th.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "config.h"

/*
** TH_USE_SQLITE, if defined, enables the "query" family of functions.
** They provide SELECT-only access to the repository db.
*/
#define TH_USE_SQLITE

/*
** TH_USE_OUTBUF, if defined, enables the "ob" family of functions.
** They are functionally similar to PHP's ob_start(), ob_end(), etc.
** family of functions, providing output capturing/buffering.
*/
#define TH_USE_OUTBUF

/*
** TH_USE_ARGV, if defined, enables the "argv" family of functions.
** They provide access to CLI arguments as well as GET/POST arguments.
** They do not provide access to POST data submitted in JSON mode.
*/
#define TH_USE_ARGV

#ifdef TH_USE_OUTBUF
#ifndef INTERFACE
#include "blob.h"
#endif
#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



|


|


|



|


|



|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "config.h"

/*
** TH_ENABLE_SQLITE, if defined, enables the "query" family of functions.
** They provide SELECT-only access to the repository db.
*/
#define TH_ENABLE_SQLITE

/*
** TH_ENABLE_OUTBUF, if defined, enables the "ob" family of functions.
** They are functionally similar to PHP's ob_start(), ob_end(), etc.
** family of functions, providing output capturing/buffering.
*/
#define TH_ENABLE_OUTBUF

/*
** TH_ENABLE_ARGV, if defined, enables the "argv" family of functions.
** They provide access to CLI arguments as well as GET/POST arguments.
** They do not provide access to POST data submitted in JSON mode.
*/
#define TH_ENABLE_ARGV

#ifdef TH_ENABLE_OUTBUF
#ifndef INTERFACE
#include "blob.h"
#endif
#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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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 */
int th_register_sqlite(Th_Interp *interp);              /* th_main.c */
int th_register_argv(Th_Interp *interp);                /* th_main.c */
int th_register_vfs(Th_Interp *interp);                 /* th_vfs.c */
int th_register_testvfs(Th_Interp *interp);             /* th_testvfs.c */
int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
int th_register_ob(Th_Interp * interp);                 /* th.c */
/*
** General purpose hash table from th_lang.c.







|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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 */
int th_register_query(Th_Interp *interp);              /* th_main.c */
int th_register_argv(Th_Interp *interp);                /* th_main.c */
int th_register_vfs(Th_Interp *interp);                 /* th_vfs.c */
int th_register_testvfs(Th_Interp *interp);             /* th_testvfs.c */
int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
int th_register_ob(Th_Interp * interp);                 /* th.c */
/*
** General purpose hash table from th_lang.c.
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337


338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

359
360
361
362
363






364
365
366
** pointer to an array of Th_Command_Reg objects, the last one of which MUST
** have a NULL zName field (that is the end-of-list marker).
** Returns TH_OK on success, "something else" on error.
*/
int Th_register_commands( Th_Interp * interp, Th_Command_Reg const * pList );


#ifdef TH_USE_OUTBUF
/*
** Manager of a stack of Blob objects for output buffering.
*/
struct Th_Ob_Man {
  Blob ** aBuf;        /* Stack of Blobs */
  int nBuf;            /* Number of blobs */
  int cursor;          /* Current level (-1=not active) */
  Th_Interp * interp;  /* The associated interpreter */
  Th_Vtab_Output * aOutput
                       /* Stack of output routines corresponding
                          to the current buffering level.
                          Has nBuf entries.
                       */;
};

typedef struct Th_Ob_Man Th_Ob_Man;

/*
** Returns the ob manager for the given interpreter.


*/
Th_Ob_Man * Th_ob_manager(Th_Interp *ignored);

/*
** Returns the top-most Blob in pMan's stack, or NULL
** if buffering is not active.
*/
Blob * Th_ob_current( Th_Ob_Man * pMan );

/*
** Pushes a new blob onto pMan's stack. On success
** returns TH_OK and assigns *pOut (if pOut is not NULL)
** to the new blob (which is owned by pMan). On error
** pOut is not modified and non-0 is returned.
*/
int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut );

/*
** Pops the top-most output buffer off the stack and returns
** it. Returns NULL if there is no current buffer.  When the last
** buffer is popped, pMan's internals are cleaned up.

**
** The caller owns the returned object and must eventually call
** blob_reset() on it and Th_Free() it.
*/
Blob * Th_ob_pop( Th_Ob_Man * pMan );







#endif
/* TH_USE_OUTBUF */







|


<
|
<
<
<
<
<
<
<
<
|
<
<



|
>
>



















|
|
>

|
|


>
>
>
>
>
>


|
311
312
313
314
315
316
317
318
319
320

321








322


323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
** pointer to an array of Th_Command_Reg objects, the last one of which MUST
** have a NULL zName field (that is the end-of-list marker).
** Returns TH_OK on success, "something else" on error.
*/
int Th_register_commands( Th_Interp * interp, Th_Command_Reg const * pList );


#ifdef TH_ENABLE_OUTBUF
/*
** Manager of a stack of Blob objects for output buffering.

** See Th_ob_manager().








*/


typedef struct Th_Ob_Man Th_Ob_Man;

/*
** Returns the ob manager for the given interpreter.  The manager gets
** installed by the th_register_ob(). In Fossil ob support is
** installed automatically if it is available at built time.
*/
Th_Ob_Man * Th_ob_manager(Th_Interp *ignored);

/*
** Returns the top-most Blob in pMan's stack, or NULL
** if buffering is not active.
*/
Blob * Th_ob_current( Th_Ob_Man * pMan );

/*
** Pushes a new blob onto pMan's stack. On success
** returns TH_OK and assigns *pOut (if pOut is not NULL)
** to the new blob (which is owned by pMan). On error
** pOut is not modified and non-0 is returned.
*/
int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut );

/*
** Pops the top-most output buffer off the stack and returns
** it. Returns NULL if there is no current buffer. When the last
** buffer is popped, pMan's internals are cleaned up (but pMan is not
** freed).
**
** The caller owns the returned object and must eventually clean it up
** by first passing it to blob_reset() and then Th_Free() it.
*/
Blob * Th_ob_pop( Th_Ob_Man * pMan );
/*
** Convenience form of Th_ob_pop() which pops and frees the
** top-most buffer. Returns 0 on success, non-0 if there is no
** stack to pop.
*/
int Th_ob_pop_free( Th_Ob_Man * pMan );

#endif
/* TH_ENABLE_OUTBUF */
Changes to src/th_lang.c.
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
  int *argl
){
  int cnt = 0;
  cnt++;
  return TH_OK;
}

static int call_command(
  Th_Interp *interp, 
  void *ctx, 
  int argc, 
  const char **argv, 
  int *argl
){
  if( argc<2 ){
    return Th_WrongNumArgs2(interp,
                            argv[0], argl[0],
                           "funcName ?args...?");
  }
  

}

/*
** Register the built-in th1 language commands with interpreter interp.
** Usually this is called soon after interpreter creation.
*/
int th_register_language(Th_Interp *interp){
  int rc;
  /* Array of built-in commands. */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1053
1054
1055
1056
1057
1058
1059
















1060
1061
1062
1063
1064
1065
1066
  int *argl
){
  int cnt = 0;
  cnt++;
  return TH_OK;
}

















/*
** Register the built-in th1 language commands with interpreter interp.
** Usually this is called soon after interpreter creation.
*/
int th_register_language(Th_Interp *interp){
  int rc;
  /* Array of built-in commands. */
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
    {"break",    simple_command, (void *)TH_BREAK}, 
    {"continue", simple_command, (void *)TH_CONTINUE}, 
    {"error",    simple_command, (void *)TH_ERROR}, 

    {0, 0, 0}
  };
  rc = Th_register_commands(interp, aCommand);
#ifdef TH_USE_OUTBUF
  rc |= th_register_ob(interp);
#endif
  return rc;
}







<
<
<


1087
1088
1089
1090
1091
1092
1093



1094
1095
    {"break",    simple_command, (void *)TH_BREAK}, 
    {"continue", simple_command, (void *)TH_CONTINUE}, 
    {"error",    simple_command, (void *)TH_ERROR}, 

    {0, 0, 0}
  };
  rc = Th_register_commands(interp, aCommand);



  return rc;
}
Changes to src/th_main.c.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
** (an independent project) and fossil.
*/
#include "config.h"
#include "th_main.h"
#ifndef INTERFACE
#include "blob.h"
#endif
#ifdef TH_USE_SQLITE
#include "sqlite3.h"
#endif

/*#include "th_main.h"*/
/*
** Global variable counting the number of outstanding calls to malloc()
** made by the th1 implementation. This is used to catch memory leaks







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
** (an independent project) and fossil.
*/
#include "config.h"
#include "th_main.h"
#ifndef INTERFACE
#include "blob.h"
#endif
#ifdef TH_ENABLE_SQLITE
#include "sqlite3.h"
#endif

/*#include "th_main.h"*/
/*
** Global variable counting the number of outstanding calls to malloc()
** made by the th1 implementation. This is used to catch memory leaks
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
    if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
  }
  Th_SetResult(interp, g.zRepositoryName, -1);
  return TH_OK;
}


#ifdef TH_USE_ARGV
extern const char *find_option(const char *zLong,
                               const char *zShort,
                               int hasArg) /* from main.c */;
/*
** TH Syntax:
**
** argv len







|







540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
    if( openRepository ) db_find_and_open_repository(OPEN_OK_NOT_FOUND, 0);
  }
  Th_SetResult(interp, g.zRepositoryName, -1);
  return TH_OK;
}


#ifdef TH_ENABLE_ARGV
extern const char *find_option(const char *zLong,
                               const char *zShort,
                               int hasArg) /* from main.c */;
/*
** TH Syntax:
**
** argv len
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
    {"argv",            argvTopLevelCmd, 0 },
    {0, 0, 0}
  };
  Th_register_commands( interp, aCommand );
}

#endif
/* end TH_USE_ARGV */

#ifdef TH_USE_SQLITE

/*
** Adds the given prepared statement to the interpreter. Returns the
** statements opaque identifier (a positive value). Ownerships of
** pStmt is transfered to interp and it must be cleaned up by the
** client by calling Th_FinalizeStmt(), passing it the value returned
** by this function.







|

|







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
    {"argv",            argvTopLevelCmd, 0 },
    {0, 0, 0}
  };
  Th_register_commands( interp, aCommand );
}

#endif
/* end TH_ENABLE_ARGV */

#ifdef TH_ENABLE_SQLITE

/*
** Adds the given prepared statement to the interpreter. Returns the
** statements opaque identifier (a positive value). Ownerships of
** pStmt is transfered to interp and it must be cleaned up by the
** client by calling Th_FinalizeStmt(), passing it the value returned
** by this function.
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
    {0, 0}
  };
  assert( NULL != sq );
  Th_CallSubCommand2( interp, sq, argc, argv, argl, aSub );
}


int th_register_sqlite(Th_Interp *interp){
  enum { BufLen = 100 };
  char buf[BufLen];
  int i, l;
#define SET(K) l = snprintf(buf, BufLen, "%d", K);      \
  Th_SetVar( interp, #K, strlen(#K), buf, l );
  SET(SQLITE_BLOB);
  SET(SQLITE_DONE);







|







1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
    {0, 0}
  };
  assert( NULL != sq );
  Th_CallSubCommand2( interp, sq, argc, argv, argl, aSub );
}


int th_register_query(Th_Interp *interp){
  enum { BufLen = 100 };
  char buf[BufLen];
  int i, l;
#define SET(K) l = snprintf(buf, BufLen, "%d", K);      \
  Th_SetVar( interp, #K, strlen(#K), buf, l );
  SET(SQLITE_BLOB);
  SET(SQLITE_DONE);
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
      assert( sq == Th_sqlite_manager(interp) );
    }
  }
  return rc;
}

#endif
/* end TH_USE_SQLITE */

int Th_register_commands( Th_Interp * interp,
                           Th_Command_Reg const * aCommand ){
  int i;
  int rc = TH_OK;
  for(i=0; (TH_OK==rc) && aCommand[i].zName; ++i){
    if ( !aCommand[i].zName ) break;







|







1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
      assert( sq == Th_sqlite_manager(interp) );
    }
  }
  return rc;
}

#endif
/* end TH_ENABLE_SQLITE */

int Th_register_commands( Th_Interp * interp,
                           Th_Command_Reg const * aCommand ){
  int i;
  int rc = TH_OK;
  for(i=0; (TH_OK==rc) && aCommand[i].zName; ++i){
    if ( !aCommand[i].zName ) break;
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779



1780
1781
1782
1783
1784
1785
1786
1787
    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
#ifdef TH_USE_SQLITE
    th_register_sqlite(g.interp);
#endif



#ifdef TH_USE_ARGV
    th_register_argv(g.interp);
#endif
    Th_register_commands( g.interp, aCommand );
    Th_Eval( g.interp, 0, "proc incr {name {step 1}} {\n"
             "upvar $name x\n"
             "set x [expr $x+$step]\n"
             "}", -1 );







|
|

>
>
>
|







1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
    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
#ifdef TH_ENABLE_OUTBUF
    th_register_ob(g.interp);
#endif
#ifdef TH_ENABLE_SQLITE
    th_register_query(g.interp);
#endif
#ifdef TH_ENABLE_ARGV
    th_register_argv(g.interp);
#endif
    Th_register_commands( g.interp, aCommand );
    Th_Eval( g.interp, 0, "proc incr {name {step 1}} {\n"
             "upvar $name x\n"
             "set x [expr $x+$step]\n"
             "}", -1 );
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
  Blob in;
  if( g.argc<3 ){
    usage("FILE");
    assert(0 && "usage() does not return");
  }
  blob_zero(&in);
  db_open_config(0); /* Needed for global "tcl" setting. */
#ifdef TH_USE_SQLITE
  db_find_and_open_repository(OPEN_ANY_SCHEMA,0)
    /* required for th1 query API. */;
#endif
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in), Th_Render_Flags_DEFAULT);
}







|






1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
  Blob in;
  if( g.argc<3 ){
    usage("FILE");
    assert(0 && "usage() does not return");
  }
  blob_zero(&in);
  db_open_config(0); /* Needed for global "tcl" setting. */
#ifdef TH_ENABLE_SQLITE
  db_find_and_open_repository(OPEN_ANY_SCHEMA,0)
    /* required for th1 query API. */;
#endif
  blob_read_from_file(&in, g.argv[2]);
  Th_Render(blob_str(&in), Th_Render_Flags_DEFAULT);
}