Fossil SCM
Added flags arg to Th_Render to allow us to eventually customize its output a bit.
Commit
3ab06e8962024e0457ceb9f3c1ca73a9c493313e
Parent
6e2f9edc29c86c0…
7 files changed
+2
-1
+4
-4
+6
-39
+63
+16
+77
-16
+3
-3
+2
-1
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -19,10 +19,11 @@ | ||
| 19 | 19 | */ |
| 20 | 20 | #include "config.h" |
| 21 | 21 | #include <time.h> |
| 22 | 22 | #include "report.h" |
| 23 | 23 | #include <assert.h> |
| 24 | +#include "th.h" | |
| 24 | 25 | |
| 25 | 26 | /* Forward references to static routines */ |
| 26 | 27 | static void report_format_hints(void); |
| 27 | 28 | |
| 28 | 29 | /* |
| @@ -81,11 +82,11 @@ | ||
| 81 | 82 | blob_appendf(&ril, "</li>\n"); |
| 82 | 83 | } |
| 83 | 84 | |
| 84 | 85 | Th_Store("report_items", blob_str(&ril)); |
| 85 | 86 | |
| 86 | - Th_Render(zScript); | |
| 87 | + Th_Render(zScript, Th_Render_Flags_DEFAULT); | |
| 87 | 88 | |
| 88 | 89 | blob_reset(&ril); |
| 89 | 90 | if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1); |
| 90 | 91 | |
| 91 | 92 | style_footer(); |
| 92 | 93 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -19,10 +19,11 @@ | |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include <time.h> |
| 22 | #include "report.h" |
| 23 | #include <assert.h> |
| 24 | |
| 25 | /* Forward references to static routines */ |
| 26 | static void report_format_hints(void); |
| 27 | |
| 28 | /* |
| @@ -81,11 +82,11 @@ | |
| 81 | blob_appendf(&ril, "</li>\n"); |
| 82 | } |
| 83 | |
| 84 | Th_Store("report_items", blob_str(&ril)); |
| 85 | |
| 86 | Th_Render(zScript); |
| 87 | |
| 88 | blob_reset(&ril); |
| 89 | if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1); |
| 90 | |
| 91 | style_footer(); |
| 92 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -19,10 +19,11 @@ | |
| 19 | */ |
| 20 | #include "config.h" |
| 21 | #include <time.h> |
| 22 | #include "report.h" |
| 23 | #include <assert.h> |
| 24 | #include "th.h" |
| 25 | |
| 26 | /* Forward references to static routines */ |
| 27 | static void report_format_hints(void); |
| 28 | |
| 29 | /* |
| @@ -81,11 +82,11 @@ | |
| 82 | blob_appendf(&ril, "</li>\n"); |
| 83 | } |
| 84 | |
| 85 | Th_Store("report_items", blob_str(&ril)); |
| 86 | |
| 87 | Th_Render(zScript, Th_Render_Flags_DEFAULT); |
| 88 | |
| 89 | blob_reset(&ril); |
| 90 | if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1); |
| 91 | |
| 92 | style_footer(); |
| 93 |
+4
-4
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -18,11 +18,11 @@ | ||
| 18 | 18 | ** This file contains code to implement the basic web page look and feel. |
| 19 | 19 | ** |
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include "style.h" |
| 23 | - | |
| 23 | +#include "th.h" | |
| 24 | 24 | |
| 25 | 25 | /* |
| 26 | 26 | ** Elements of the submenu are collected into the following |
| 27 | 27 | ** structure and displayed below the main menu by style_header(). |
| 28 | 28 | ** |
| @@ -193,11 +193,11 @@ | ||
| 193 | 193 | Th_Store("compiler_name", COMPILER_NAME); |
| 194 | 194 | if( g.zLogin ){ |
| 195 | 195 | Th_Store("login", g.zLogin); |
| 196 | 196 | } |
| 197 | 197 | if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT<br />\n", -1); |
| 198 | - Th_Render(zHeader); | |
| 198 | + Th_Render(zHeader, Th_Render_Flags_DEFAULT); | |
| 199 | 199 | if( g.thTrace ) Th_Trace("END_HEADER<br />\n", -1); |
| 200 | 200 | Th_Unstore("title"); /* Avoid collisions with ticket field names */ |
| 201 | 201 | cgi_destination(CGI_BODY); |
| 202 | 202 | g.cgiOutput = 1; |
| 203 | 203 | headerHasBeenGenerated = 1; |
| @@ -264,11 +264,11 @@ | ||
| 264 | 264 | ** the footer will be generating </html> */ |
| 265 | 265 | style_resolve_href(); |
| 266 | 266 | |
| 267 | 267 | zFooter = db_get("footer", (char*)zDefaultFooter); |
| 268 | 268 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| 269 | - Th_Render(zFooter); | |
| 269 | + Th_Render(zFooter, Th_Render_Flags_DEFAULT); | |
| 270 | 270 | if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); |
| 271 | 271 | |
| 272 | 272 | /* Render trace log if TH1 tracing is enabled. */ |
| 273 | 273 | if( g.thTrace ){ |
| 274 | 274 | cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); |
| @@ -943,11 +943,11 @@ | ||
| 943 | 943 | /* Process through TH1 in order to give an opportunity to substitute |
| 944 | 944 | ** variables such as $baseurl. |
| 945 | 945 | */ |
| 946 | 946 | Th_Store("baseurl", g.zBaseURL); |
| 947 | 947 | Th_Store("home", g.zTop); |
| 948 | - Th_Render(blob_str(&css)); | |
| 948 | + Th_Render(blob_str(&css), Th_Render_Flags_DEFAULT); | |
| 949 | 949 | |
| 950 | 950 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 951 | 951 | g.isConst = 1; |
| 952 | 952 | } |
| 953 | 953 | |
| 954 | 954 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -18,11 +18,11 @@ | |
| 18 | ** This file contains code to implement the basic web page look and feel. |
| 19 | ** |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "style.h" |
| 23 | |
| 24 | |
| 25 | /* |
| 26 | ** Elements of the submenu are collected into the following |
| 27 | ** structure and displayed below the main menu by style_header(). |
| 28 | ** |
| @@ -193,11 +193,11 @@ | |
| 193 | Th_Store("compiler_name", COMPILER_NAME); |
| 194 | if( g.zLogin ){ |
| 195 | Th_Store("login", g.zLogin); |
| 196 | } |
| 197 | if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT<br />\n", -1); |
| 198 | Th_Render(zHeader); |
| 199 | if( g.thTrace ) Th_Trace("END_HEADER<br />\n", -1); |
| 200 | Th_Unstore("title"); /* Avoid collisions with ticket field names */ |
| 201 | cgi_destination(CGI_BODY); |
| 202 | g.cgiOutput = 1; |
| 203 | headerHasBeenGenerated = 1; |
| @@ -264,11 +264,11 @@ | |
| 264 | ** the footer will be generating </html> */ |
| 265 | style_resolve_href(); |
| 266 | |
| 267 | zFooter = db_get("footer", (char*)zDefaultFooter); |
| 268 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| 269 | Th_Render(zFooter); |
| 270 | if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); |
| 271 | |
| 272 | /* Render trace log if TH1 tracing is enabled. */ |
| 273 | if( g.thTrace ){ |
| 274 | cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); |
| @@ -943,11 +943,11 @@ | |
| 943 | /* Process through TH1 in order to give an opportunity to substitute |
| 944 | ** variables such as $baseurl. |
| 945 | */ |
| 946 | Th_Store("baseurl", g.zBaseURL); |
| 947 | Th_Store("home", g.zTop); |
| 948 | Th_Render(blob_str(&css)); |
| 949 | |
| 950 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 951 | g.isConst = 1; |
| 952 | } |
| 953 | |
| 954 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -18,11 +18,11 @@ | |
| 18 | ** This file contains code to implement the basic web page look and feel. |
| 19 | ** |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "style.h" |
| 23 | #include "th.h" |
| 24 | |
| 25 | /* |
| 26 | ** Elements of the submenu are collected into the following |
| 27 | ** structure and displayed below the main menu by style_header(). |
| 28 | ** |
| @@ -193,11 +193,11 @@ | |
| 193 | Th_Store("compiler_name", COMPILER_NAME); |
| 194 | if( g.zLogin ){ |
| 195 | Th_Store("login", g.zLogin); |
| 196 | } |
| 197 | if( g.thTrace ) Th_Trace("BEGIN_HEADER_SCRIPT<br />\n", -1); |
| 198 | Th_Render(zHeader, Th_Render_Flags_DEFAULT); |
| 199 | if( g.thTrace ) Th_Trace("END_HEADER<br />\n", -1); |
| 200 | Th_Unstore("title"); /* Avoid collisions with ticket field names */ |
| 201 | cgi_destination(CGI_BODY); |
| 202 | g.cgiOutput = 1; |
| 203 | headerHasBeenGenerated = 1; |
| @@ -264,11 +264,11 @@ | |
| 264 | ** the footer will be generating </html> */ |
| 265 | style_resolve_href(); |
| 266 | |
| 267 | zFooter = db_get("footer", (char*)zDefaultFooter); |
| 268 | if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); |
| 269 | Th_Render(zFooter, Th_Render_Flags_DEFAULT); |
| 270 | if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); |
| 271 | |
| 272 | /* Render trace log if TH1 tracing is enabled. */ |
| 273 | if( g.thTrace ){ |
| 274 | cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); |
| @@ -943,11 +943,11 @@ | |
| 943 | /* Process through TH1 in order to give an opportunity to substitute |
| 944 | ** variables such as $baseurl. |
| 945 | */ |
| 946 | Th_Store("baseurl", g.zBaseURL); |
| 947 | Th_Store("home", g.zTop); |
| 948 | Th_Render(blob_str(&css), Th_Render_Flags_DEFAULT); |
| 949 | |
| 950 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 951 | g.isConst = 1; |
| 952 | } |
| 953 | |
| 954 |
M
src/th.c
+6
-39
| --- src/th.c | ||
| +++ src/th.c | ||
| @@ -7,13 +7,10 @@ | ||
| 7 | 7 | #include "th.h" |
| 8 | 8 | #include <string.h> |
| 9 | 9 | #include <assert.h> |
| 10 | 10 | #include <stdio.h> /* FILE class */ |
| 11 | 11 | #ifdef TH_USE_OUTBUF |
| 12 | -#ifndef INTERFACE | |
| 13 | -#include "blob.h" | |
| 14 | -#endif | |
| 15 | 12 | #endif |
| 16 | 13 | |
| 17 | 14 | extern void *fossil_realloc(void *p, size_t n); |
| 18 | 15 | static void * th_fossil_realloc(void *p, unsigned int n){ |
| 19 | 16 | return fossil_realloc( p, n ); |
| @@ -2756,36 +2753,20 @@ | ||
| 2756 | 2753 | /* Reminder: the ob code "really" belongs in th_lang.c, |
| 2757 | 2754 | but we need access to Th_Interp internals in order to |
| 2758 | 2755 | swap out Th_Vtab parts for purposes of stacking layers |
| 2759 | 2756 | of buffers. |
| 2760 | 2757 | */ |
| 2761 | -/* | |
| 2762 | -** Manager of a stack of Blob objects for output buffering. | |
| 2763 | -*/ | |
| 2764 | -struct Th_Ob_Man { | |
| 2765 | - Blob ** aBuf; /* Stack of Blobs */ | |
| 2766 | - int nBuf; /* Number of blobs */ | |
| 2767 | - int cursor; /* Current level (-1=not active) */ | |
| 2768 | - Th_Interp * interp; /* The associated interpreter */ | |
| 2769 | - Th_Vtab ** aVtab; /* Stack of Vtabs (they get restored | |
| 2770 | - when a buffering level is popped). | |
| 2771 | - Has nBuf entries. | |
| 2772 | - | |
| 2773 | - FIXME? Only swap out the "out" members? | |
| 2774 | - */ | |
| 2775 | -}; | |
| 2776 | - | |
| 2777 | -typedef struct Th_Ob_Man Th_Ob_Man; | |
| 2778 | 2758 | #define Th_Ob_Man_empty_m { NULL, 0, -1, NULL, NULL } |
| 2779 | 2759 | static const Th_Ob_Man Th_Ob_Man_empty = Th_Ob_Man_empty_m; |
| 2780 | 2760 | static Th_Ob_Man Th_Ob_Man_instance = Th_Ob_Man_empty_m; |
| 2781 | 2761 | |
| 2782 | -/* | |
| 2783 | -** Returns the top-most Blob in pMan's stack, or NULL | |
| 2784 | -** if buffering is not active. | |
| 2785 | -*/ | |
| 2786 | -static Blob * Th_ob_current( Th_Ob_Man * pMan ){ | |
| 2762 | +Th_Ob_Man * Th_ob_manager(Th_Interp *ignored){ | |
| 2763 | + return &Th_Ob_Man_instance; | |
| 2764 | +} | |
| 2765 | + | |
| 2766 | + | |
| 2767 | +Blob * Th_ob_current( Th_Ob_Man * pMan ){ | |
| 2787 | 2768 | return pMan->nBuf>0 ? pMan->aBuf[pMan->cursor] : 0; |
| 2788 | 2769 | } |
| 2789 | 2770 | |
| 2790 | 2771 | |
| 2791 | 2772 | /* |
| @@ -2810,16 +2791,10 @@ | ||
| 2810 | 2791 | NULL, |
| 2811 | 2792 | 1 |
| 2812 | 2793 | } |
| 2813 | 2794 | }; |
| 2814 | 2795 | |
| 2815 | -/* | |
| 2816 | -** Pushes a new blob onto pMan's stack. On success | |
| 2817 | -** returns TH_OK and assigns *pOut (if pOut is not NULL) | |
| 2818 | -** to the new blob (which is owned by pMan). On error | |
| 2819 | -** pOut is not modified and non-0 is returned. | |
| 2820 | -*/ | |
| 2821 | 2796 | int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut ){ |
| 2822 | 2797 | Blob * pBlob; |
| 2823 | 2798 | int x, i; |
| 2824 | 2799 | assert( NULL != pMan->interp ); |
| 2825 | 2800 | pBlob = (Blob *)Th_Malloc(pMan->interp, sizeof(Blob)); |
| @@ -2862,18 +2837,10 @@ | ||
| 2862 | 2837 | Th_Free( pMan->interp, pBlob ); |
| 2863 | 2838 | } |
| 2864 | 2839 | return TH_ERROR; |
| 2865 | 2840 | } |
| 2866 | 2841 | |
| 2867 | -/* | |
| 2868 | -** Pops the top-most output buffer off the stack and returns | |
| 2869 | -** it. Returns NULL if there is no current buffer. When the last | |
| 2870 | -** buffer is popped, pMan's internals are cleaned up. | |
| 2871 | -** | |
| 2872 | -** The caller owns the returned object and must eventually call | |
| 2873 | -** blob_reset() on it. | |
| 2874 | -*/ | |
| 2875 | 2842 | Blob * Th_ob_pop( Th_Ob_Man * pMan ){ |
| 2876 | 2843 | if( pMan->cursor < 0 ){ |
| 2877 | 2844 | return NULL; |
| 2878 | 2845 | }else{ |
| 2879 | 2846 | Blob * rc; |
| 2880 | 2847 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -7,13 +7,10 @@ | |
| 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 ); |
| @@ -2756,36 +2753,20 @@ | |
| 2756 | /* Reminder: the ob code "really" belongs in th_lang.c, |
| 2757 | but we need access to Th_Interp internals in order to |
| 2758 | swap out Th_Vtab parts for purposes of stacking layers |
| 2759 | of buffers. |
| 2760 | */ |
| 2761 | /* |
| 2762 | ** Manager of a stack of Blob objects for output buffering. |
| 2763 | */ |
| 2764 | struct Th_Ob_Man { |
| 2765 | Blob ** aBuf; /* Stack of Blobs */ |
| 2766 | int nBuf; /* Number of blobs */ |
| 2767 | int cursor; /* Current level (-1=not active) */ |
| 2768 | Th_Interp * interp; /* The associated interpreter */ |
| 2769 | Th_Vtab ** aVtab; /* Stack of Vtabs (they get restored |
| 2770 | when a buffering level is popped). |
| 2771 | Has nBuf entries. |
| 2772 | |
| 2773 | FIXME? Only swap out the "out" members? |
| 2774 | */ |
| 2775 | }; |
| 2776 | |
| 2777 | typedef struct Th_Ob_Man Th_Ob_Man; |
| 2778 | #define Th_Ob_Man_empty_m { NULL, 0, -1, NULL, NULL } |
| 2779 | static const Th_Ob_Man Th_Ob_Man_empty = Th_Ob_Man_empty_m; |
| 2780 | static Th_Ob_Man Th_Ob_Man_instance = Th_Ob_Man_empty_m; |
| 2781 | |
| 2782 | /* |
| 2783 | ** Returns the top-most Blob in pMan's stack, or NULL |
| 2784 | ** if buffering is not active. |
| 2785 | */ |
| 2786 | static Blob * Th_ob_current( Th_Ob_Man * pMan ){ |
| 2787 | return pMan->nBuf>0 ? pMan->aBuf[pMan->cursor] : 0; |
| 2788 | } |
| 2789 | |
| 2790 | |
| 2791 | /* |
| @@ -2810,16 +2791,10 @@ | |
| 2810 | NULL, |
| 2811 | 1 |
| 2812 | } |
| 2813 | }; |
| 2814 | |
| 2815 | /* |
| 2816 | ** Pushes a new blob onto pMan's stack. On success |
| 2817 | ** returns TH_OK and assigns *pOut (if pOut is not NULL) |
| 2818 | ** to the new blob (which is owned by pMan). On error |
| 2819 | ** pOut is not modified and non-0 is returned. |
| 2820 | */ |
| 2821 | int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut ){ |
| 2822 | Blob * pBlob; |
| 2823 | int x, i; |
| 2824 | assert( NULL != pMan->interp ); |
| 2825 | pBlob = (Blob *)Th_Malloc(pMan->interp, sizeof(Blob)); |
| @@ -2862,18 +2837,10 @@ | |
| 2862 | Th_Free( pMan->interp, pBlob ); |
| 2863 | } |
| 2864 | return TH_ERROR; |
| 2865 | } |
| 2866 | |
| 2867 | /* |
| 2868 | ** Pops the top-most output buffer off the stack and returns |
| 2869 | ** it. Returns NULL if there is no current buffer. When the last |
| 2870 | ** buffer is popped, pMan's internals are cleaned up. |
| 2871 | ** |
| 2872 | ** The caller owns the returned object and must eventually call |
| 2873 | ** blob_reset() on it. |
| 2874 | */ |
| 2875 | Blob * Th_ob_pop( Th_Ob_Man * pMan ){ |
| 2876 | if( pMan->cursor < 0 ){ |
| 2877 | return NULL; |
| 2878 | }else{ |
| 2879 | Blob * rc; |
| 2880 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -7,13 +7,10 @@ | |
| 7 | #include "th.h" |
| 8 | #include <string.h> |
| 9 | #include <assert.h> |
| 10 | #include <stdio.h> /* FILE class */ |
| 11 | #ifdef TH_USE_OUTBUF |
| 12 | #endif |
| 13 | |
| 14 | extern void *fossil_realloc(void *p, size_t n); |
| 15 | static void * th_fossil_realloc(void *p, unsigned int n){ |
| 16 | return fossil_realloc( p, n ); |
| @@ -2756,36 +2753,20 @@ | |
| 2753 | /* Reminder: the ob code "really" belongs in th_lang.c, |
| 2754 | but we need access to Th_Interp internals in order to |
| 2755 | swap out Th_Vtab parts for purposes of stacking layers |
| 2756 | of buffers. |
| 2757 | */ |
| 2758 | #define Th_Ob_Man_empty_m { NULL, 0, -1, NULL, NULL } |
| 2759 | static const Th_Ob_Man Th_Ob_Man_empty = Th_Ob_Man_empty_m; |
| 2760 | static Th_Ob_Man Th_Ob_Man_instance = Th_Ob_Man_empty_m; |
| 2761 | |
| 2762 | Th_Ob_Man * Th_ob_manager(Th_Interp *ignored){ |
| 2763 | return &Th_Ob_Man_instance; |
| 2764 | } |
| 2765 | |
| 2766 | |
| 2767 | Blob * Th_ob_current( Th_Ob_Man * pMan ){ |
| 2768 | return pMan->nBuf>0 ? pMan->aBuf[pMan->cursor] : 0; |
| 2769 | } |
| 2770 | |
| 2771 | |
| 2772 | /* |
| @@ -2810,16 +2791,10 @@ | |
| 2791 | NULL, |
| 2792 | 1 |
| 2793 | } |
| 2794 | }; |
| 2795 | |
| 2796 | int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut ){ |
| 2797 | Blob * pBlob; |
| 2798 | int x, i; |
| 2799 | assert( NULL != pMan->interp ); |
| 2800 | pBlob = (Blob *)Th_Malloc(pMan->interp, sizeof(Blob)); |
| @@ -2862,18 +2837,10 @@ | |
| 2837 | Th_Free( pMan->interp, pBlob ); |
| 2838 | } |
| 2839 | return TH_ERROR; |
| 2840 | } |
| 2841 | |
| 2842 | Blob * Th_ob_pop( Th_Ob_Man * pMan ){ |
| 2843 | if( pMan->cursor < 0 ){ |
| 2844 | return NULL; |
| 2845 | }else{ |
| 2846 | Blob * rc; |
| 2847 |
M
src/th.h
+63
| --- src/th.h | ||
| +++ src/th.h | ||
| @@ -10,10 +10,13 @@ | ||
| 10 | 10 | ** They are functionally similar to PHP's ob_start(), ob_end(), etc. |
| 11 | 11 | ** family of functions, providing output capturing/buffering. |
| 12 | 12 | */ |
| 13 | 13 | #define TH_USE_OUTBUF |
| 14 | 14 | /*#undef TH_USE_OUTBUF*/ |
| 15 | +#ifndef INTERFACE | |
| 16 | +#include "blob.h" | |
| 17 | +#endif | |
| 15 | 18 | |
| 16 | 19 | |
| 17 | 20 | /* This header file defines the external interface to the custom Scripting |
| 18 | 21 | ** Language (TH) interpreter. TH is very similar to TCL but is not an |
| 19 | 22 | ** exact clone. |
| @@ -260,10 +263,17 @@ | ||
| 260 | 263 | const char *zName; /* Function name. */ |
| 261 | 264 | Th_CommandProc xProc; /* Callback function */ |
| 262 | 265 | void *pContext; /* Arbitrary data for the callback. */ |
| 263 | 266 | }; |
| 264 | 267 | |
| 268 | +/* mkindex cannot do enums enum Th_Render_Flags { */ | |
| 269 | +#define Th_Render_Flags_DEFAULT 0 | |
| 270 | +#define Th_Render_Flags_NO_DOLLAR_DEREF (1 << 1) | |
| 271 | +/*};*/ | |
| 272 | + | |
| 273 | +int Th_Render(const char *z, int flags); | |
| 274 | + | |
| 265 | 275 | /* |
| 266 | 276 | ** Registers a list of commands with the interpreter. pList must be a non-NULL |
| 267 | 277 | ** pointer to an array of Th_Command_Reg objects, the last one of which MUST |
| 268 | 278 | ** have a NULL zName field (that is the end-of-list marker). |
| 269 | 279 | ** Returns TH_OK on success, "something else" on error. |
| @@ -299,5 +309,58 @@ | ||
| 299 | 309 | ** refers) to a statement added via Th_AddStmt(). |
| 300 | 310 | */ |
| 301 | 311 | sqlite3_stmt * Th_GetStmt(Th_Interp *interp, int stmtId); |
| 302 | 312 | #endif |
| 303 | 313 | |
| 314 | +#ifdef TH_USE_OUTBUF | |
| 315 | +/* | |
| 316 | +** Manager of a stack of Blob objects for output buffering. | |
| 317 | +*/ | |
| 318 | +struct Th_Ob_Man { | |
| 319 | + Blob ** aBuf; /* Stack of Blobs */ | |
| 320 | + int nBuf; /* Number of blobs */ | |
| 321 | + int cursor; /* Current level (-1=not active) */ | |
| 322 | + Th_Interp * interp; /* The associated interpreter */ | |
| 323 | + Th_Vtab ** aVtab; /* Stack of Vtabs (they get restored | |
| 324 | + when a buffering level is popped). | |
| 325 | + Has nBuf entries. | |
| 326 | + | |
| 327 | + FIXME? Only swap out the "out" members, and | |
| 328 | + not xRealloc (that could get us into | |
| 329 | + trouble, but we currently only use one | |
| 330 | + realloc impl). | |
| 331 | + */ | |
| 332 | +}; | |
| 333 | + | |
| 334 | +typedef struct Th_Ob_Man Th_Ob_Man; | |
| 335 | + | |
| 336 | +/* | |
| 337 | +** Returns the ob manager for the given interpreter. | |
| 338 | +*/ | |
| 339 | +Th_Ob_Man * Th_ob_manager(Th_Interp *ignored); | |
| 340 | + | |
| 341 | +/* | |
| 342 | +** Returns the top-most Blob in pMan's stack, or NULL | |
| 343 | +** if buffering is not active. | |
| 344 | +*/ | |
| 345 | +Blob * Th_ob_current( Th_Ob_Man * pMan ); | |
| 346 | + | |
| 347 | +/* | |
| 348 | +** Pushes a new blob onto pMan's stack. On success | |
| 349 | +** returns TH_OK and assigns *pOut (if pOut is not NULL) | |
| 350 | +** to the new blob (which is owned by pMan). On error | |
| 351 | +** pOut is not modified and non-0 is returned. | |
| 352 | +*/ | |
| 353 | +int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut ); | |
| 354 | + | |
| 355 | +/* | |
| 356 | +** Pops the top-most output buffer off the stack and returns | |
| 357 | +** it. Returns NULL if there is no current buffer. When the last | |
| 358 | +** buffer is popped, pMan's internals are cleaned up. | |
| 359 | +** | |
| 360 | +** The caller owns the returned object and must eventually call | |
| 361 | +** blob_reset() on it and Th_Free() it. | |
| 362 | +*/ | |
| 363 | +Blob * Th_ob_pop( Th_Ob_Man * pMan ); | |
| 364 | + | |
| 365 | +#endif | |
| 366 | +/* TH_USE_OUTBUF */ | |
| 304 | 367 |
| --- src/th.h | |
| +++ src/th.h | |
| @@ -10,10 +10,13 @@ | |
| 10 | ** They are functionally similar to PHP's ob_start(), ob_end(), etc. |
| 11 | ** family of functions, providing output capturing/buffering. |
| 12 | */ |
| 13 | #define TH_USE_OUTBUF |
| 14 | /*#undef TH_USE_OUTBUF*/ |
| 15 | |
| 16 | |
| 17 | /* This header file defines the external interface to the custom Scripting |
| 18 | ** Language (TH) interpreter. TH is very similar to TCL but is not an |
| 19 | ** exact clone. |
| @@ -260,10 +263,17 @@ | |
| 260 | const char *zName; /* Function name. */ |
| 261 | Th_CommandProc xProc; /* Callback function */ |
| 262 | void *pContext; /* Arbitrary data for the callback. */ |
| 263 | }; |
| 264 | |
| 265 | /* |
| 266 | ** Registers a list of commands with the interpreter. pList must be a non-NULL |
| 267 | ** pointer to an array of Th_Command_Reg objects, the last one of which MUST |
| 268 | ** have a NULL zName field (that is the end-of-list marker). |
| 269 | ** Returns TH_OK on success, "something else" on error. |
| @@ -299,5 +309,58 @@ | |
| 299 | ** refers) to a statement added via Th_AddStmt(). |
| 300 | */ |
| 301 | sqlite3_stmt * Th_GetStmt(Th_Interp *interp, int stmtId); |
| 302 | #endif |
| 303 | |
| 304 |
| --- src/th.h | |
| +++ src/th.h | |
| @@ -10,10 +10,13 @@ | |
| 10 | ** They are functionally similar to PHP's ob_start(), ob_end(), etc. |
| 11 | ** family of functions, providing output capturing/buffering. |
| 12 | */ |
| 13 | #define TH_USE_OUTBUF |
| 14 | /*#undef TH_USE_OUTBUF*/ |
| 15 | #ifndef INTERFACE |
| 16 | #include "blob.h" |
| 17 | #endif |
| 18 | |
| 19 | |
| 20 | /* This header file defines the external interface to the custom Scripting |
| 21 | ** Language (TH) interpreter. TH is very similar to TCL but is not an |
| 22 | ** exact clone. |
| @@ -260,10 +263,17 @@ | |
| 263 | const char *zName; /* Function name. */ |
| 264 | Th_CommandProc xProc; /* Callback function */ |
| 265 | void *pContext; /* Arbitrary data for the callback. */ |
| 266 | }; |
| 267 | |
| 268 | /* mkindex cannot do enums enum Th_Render_Flags { */ |
| 269 | #define Th_Render_Flags_DEFAULT 0 |
| 270 | #define Th_Render_Flags_NO_DOLLAR_DEREF (1 << 1) |
| 271 | /*};*/ |
| 272 | |
| 273 | int Th_Render(const char *z, int flags); |
| 274 | |
| 275 | /* |
| 276 | ** Registers a list of commands with the interpreter. pList must be a non-NULL |
| 277 | ** pointer to an array of Th_Command_Reg objects, the last one of which MUST |
| 278 | ** have a NULL zName field (that is the end-of-list marker). |
| 279 | ** Returns TH_OK on success, "something else" on error. |
| @@ -299,5 +309,58 @@ | |
| 309 | ** refers) to a statement added via Th_AddStmt(). |
| 310 | */ |
| 311 | sqlite3_stmt * Th_GetStmt(Th_Interp *interp, int stmtId); |
| 312 | #endif |
| 313 | |
| 314 | #ifdef TH_USE_OUTBUF |
| 315 | /* |
| 316 | ** Manager of a stack of Blob objects for output buffering. |
| 317 | */ |
| 318 | struct Th_Ob_Man { |
| 319 | Blob ** aBuf; /* Stack of Blobs */ |
| 320 | int nBuf; /* Number of blobs */ |
| 321 | int cursor; /* Current level (-1=not active) */ |
| 322 | Th_Interp * interp; /* The associated interpreter */ |
| 323 | Th_Vtab ** aVtab; /* Stack of Vtabs (they get restored |
| 324 | when a buffering level is popped). |
| 325 | Has nBuf entries. |
| 326 | |
| 327 | FIXME? Only swap out the "out" members, and |
| 328 | not xRealloc (that could get us into |
| 329 | trouble, but we currently only use one |
| 330 | realloc impl). |
| 331 | */ |
| 332 | }; |
| 333 | |
| 334 | typedef struct Th_Ob_Man Th_Ob_Man; |
| 335 | |
| 336 | /* |
| 337 | ** Returns the ob manager for the given interpreter. |
| 338 | */ |
| 339 | Th_Ob_Man * Th_ob_manager(Th_Interp *ignored); |
| 340 | |
| 341 | /* |
| 342 | ** Returns the top-most Blob in pMan's stack, or NULL |
| 343 | ** if buffering is not active. |
| 344 | */ |
| 345 | Blob * Th_ob_current( Th_Ob_Man * pMan ); |
| 346 | |
| 347 | /* |
| 348 | ** Pushes a new blob onto pMan's stack. On success |
| 349 | ** returns TH_OK and assigns *pOut (if pOut is not NULL) |
| 350 | ** to the new blob (which is owned by pMan). On error |
| 351 | ** pOut is not modified and non-0 is returned. |
| 352 | */ |
| 353 | int Th_ob_push( Th_Ob_Man * pMan, Blob ** pOut ); |
| 354 | |
| 355 | /* |
| 356 | ** Pops the top-most output buffer off the stack and returns |
| 357 | ** it. Returns NULL if there is no current buffer. When the last |
| 358 | ** buffer is popped, pMan's internals are cleaned up. |
| 359 | ** |
| 360 | ** The caller owns the returned object and must eventually call |
| 361 | ** blob_reset() on it and Th_Free() it. |
| 362 | */ |
| 363 | Blob * Th_ob_pop( Th_Ob_Man * pMan ); |
| 364 | |
| 365 | #endif |
| 366 | /* TH_USE_OUTBUF */ |
| 367 |
+16
| --- src/th_lang.c | ||
| +++ src/th_lang.c | ||
| @@ -1052,10 +1052,26 @@ | ||
| 1052 | 1052 | int *argl |
| 1053 | 1053 | ){ |
| 1054 | 1054 | int cnt = 0; |
| 1055 | 1055 | cnt++; |
| 1056 | 1056 | return TH_OK; |
| 1057 | +} | |
| 1058 | + | |
| 1059 | +static int call_command( | |
| 1060 | + Th_Interp *interp, | |
| 1061 | + void *ctx, | |
| 1062 | + int argc, | |
| 1063 | + const char **argv, | |
| 1064 | + int *argl | |
| 1065 | +){ | |
| 1066 | + if( argc<2 ){ | |
| 1067 | + return Th_WrongNumArgs2(interp, | |
| 1068 | + argv[0], argl[0], | |
| 1069 | + "funcName ?args...?"); | |
| 1070 | + } | |
| 1071 | + | |
| 1072 | + | |
| 1057 | 1073 | } |
| 1058 | 1074 | |
| 1059 | 1075 | /* |
| 1060 | 1076 | ** Register the built-in th1 language commands with interpreter interp. |
| 1061 | 1077 | ** Usually this is called soon after interpreter creation. |
| 1062 | 1078 |
| --- src/th_lang.c | |
| +++ src/th_lang.c | |
| @@ -1052,10 +1052,26 @@ | |
| 1052 | int *argl |
| 1053 | ){ |
| 1054 | int cnt = 0; |
| 1055 | cnt++; |
| 1056 | return TH_OK; |
| 1057 | } |
| 1058 | |
| 1059 | /* |
| 1060 | ** Register the built-in th1 language commands with interpreter interp. |
| 1061 | ** Usually this is called soon after interpreter creation. |
| 1062 |
| --- src/th_lang.c | |
| +++ src/th_lang.c | |
| @@ -1052,10 +1052,26 @@ | |
| 1052 | int *argl |
| 1053 | ){ |
| 1054 | int cnt = 0; |
| 1055 | cnt++; |
| 1056 | return TH_OK; |
| 1057 | } |
| 1058 | |
| 1059 | static int call_command( |
| 1060 | Th_Interp *interp, |
| 1061 | void *ctx, |
| 1062 | int argc, |
| 1063 | const char **argv, |
| 1064 | int *argl |
| 1065 | ){ |
| 1066 | if( argc<2 ){ |
| 1067 | return Th_WrongNumArgs2(interp, |
| 1068 | argv[0], argl[0], |
| 1069 | "funcName ?args...?"); |
| 1070 | } |
| 1071 | |
| 1072 | |
| 1073 | } |
| 1074 | |
| 1075 | /* |
| 1076 | ** Register the built-in th1 language commands with interpreter interp. |
| 1077 | ** Usually this is called soon after interpreter creation. |
| 1078 |
+77
-16
| --- src/th_main.c | ||
| +++ src/th_main.c | ||
| @@ -17,12 +17,14 @@ | ||
| 17 | 17 | ** |
| 18 | 18 | ** This file contains an interface between the TH scripting language |
| 19 | 19 | ** (an independent project) and fossil. |
| 20 | 20 | */ |
| 21 | 21 | #include "config.h" |
| 22 | + | |
| 22 | 23 | #include "th_main.h" |
| 23 | 24 | |
| 25 | +/*#include "th_main.h"*/ | |
| 24 | 26 | /* |
| 25 | 27 | ** Global variable counting the number of outstanding calls to malloc() |
| 26 | 28 | ** made by the th1 implementation. This is used to catch memory leaks |
| 27 | 29 | ** in the interpreter. Obviously, it also means th1 is not threadsafe. |
| 28 | 30 | */ |
| @@ -220,10 +222,63 @@ | ||
| 220 | 222 | Th_SetResult(interp, zOut, -1); |
| 221 | 223 | free(zOut); |
| 222 | 224 | return TH_OK; |
| 223 | 225 | } |
| 224 | 226 | |
| 227 | +#if 0 | |
| 228 | +/* i'm not sure we need this */ | |
| 229 | +/* | |
| 230 | +** TH command: render STRING | |
| 231 | +** | |
| 232 | +** Render the input string as TH1. | |
| 233 | +*/ | |
| 234 | +static int renderCmd( | |
| 235 | + Th_Interp *interp, | |
| 236 | + void *p, | |
| 237 | + int argc, | |
| 238 | + const char **argv, | |
| 239 | + int *argl | |
| 240 | +){ | |
| 241 | + if( argc<2 ){ | |
| 242 | + return Th_WrongNumArgs2(interp, | |
| 243 | + argv[0], argl[0], | |
| 244 | + "STRING ?STRING...?"); | |
| 245 | + }else{ | |
| 246 | + Th_Ob_Man * man = Th_ob_manager(interp); | |
| 247 | + Blob * b = NULL; | |
| 248 | + Blob buf = empty_blob; | |
| 249 | + int rc, i; | |
| 250 | + /*FIXME: assert(NULL != man && man->interp==interp);*/ | |
| 251 | + man->interp = interp; | |
| 252 | + /* Combine all inputs into one buffer so that we can use that to | |
| 253 | + embed TH1 tags across argument boundaries. | |
| 254 | + | |
| 255 | + FIX:E optimize away buf for the 1-arg case. | |
| 256 | + */ | |
| 257 | + for( i = 1; TH_OK==rc && i < argc; ++i ){ | |
| 258 | + char const * str = argv[i]; | |
| 259 | + blob_append( &buf, str, argl[i] ); | |
| 260 | + /*rc = Th_Render( str, Th_Render_Flags_NO_DOLLAR_DEREF );*/ | |
| 261 | + } | |
| 262 | + rc = Th_ob_push( man, &b ); | |
| 263 | + if(rc){ | |
| 264 | + blob_reset( &buf ); | |
| 265 | + return rc; | |
| 266 | + } | |
| 267 | + rc = Th_Render( buf.aData, Th_Render_Flags_DEFAULT ); | |
| 268 | + blob_reset(&buf); | |
| 269 | + b = Th_ob_pop( man ); | |
| 270 | + if(TH_OK==rc){ | |
| 271 | + Th_SetResult( interp, b->aData, b->nUsed ); | |
| 272 | + } | |
| 273 | + blob_reset( b ); | |
| 274 | + Th_Free( interp, b ); | |
| 275 | + return rc; | |
| 276 | + } | |
| 277 | +}/* renderCmd() */ | |
| 278 | +#endif | |
| 279 | + | |
| 225 | 280 | /* |
| 226 | 281 | ** TH command: date |
| 227 | 282 | ** |
| 228 | 283 | ** Return a string which is the current time and date. If the |
| 229 | 284 | ** -local option is used, the date appears using localtime instead |
| @@ -1571,20 +1626,23 @@ | ||
| 1571 | 1626 | static PutsCmdData puts_Html = {0, 0, 0}; |
| 1572 | 1627 | static PutsCmdData puts_Normal = {1, 0, 0}; |
| 1573 | 1628 | static Th_Command_Reg aCommand[] = { |
| 1574 | 1629 | {"anycap", anycapCmd, 0}, |
| 1575 | 1630 | {"combobox", comboboxCmd, 0}, |
| 1631 | + {"date", dateCmd, 0}, | |
| 1576 | 1632 | {"enable_output", enableOutputCmd, 0}, |
| 1577 | - {"linecount", linecntCmd, 0}, | |
| 1578 | 1633 | {"hascap", hascapCmd, 0}, |
| 1579 | 1634 | {"hasfeature", hasfeatureCmd, 0}, |
| 1635 | + {"html", putsCmd, &puts_Html}, | |
| 1580 | 1636 | {"htmlize", htmlizeCmd, 0}, |
| 1581 | - {"date", dateCmd, 0}, | |
| 1582 | - {"html", putsCmd, &puts_Html}, | |
| 1637 | + {"linecount", linecntCmd, 0}, | |
| 1583 | 1638 | {"puts", putsCmd, &puts_Normal}, |
| 1584 | - {"wiki", wikiCmd, 0}, | |
| 1639 | +#if 0 | |
| 1640 | + {"render", renderCmd, 0}, | |
| 1641 | +#endif | |
| 1585 | 1642 | {"repository", repositoryCmd, 0}, |
| 1643 | + {"wiki", wikiCmd, 0}, | |
| 1586 | 1644 | |
| 1587 | 1645 | {0, 0, 0} |
| 1588 | 1646 | }; |
| 1589 | 1647 | if( g.interp==0 ){ |
| 1590 | 1648 | int i; |
| @@ -1705,26 +1763,29 @@ | ||
| 1705 | 1763 | return i; |
| 1706 | 1764 | } |
| 1707 | 1765 | |
| 1708 | 1766 | /* |
| 1709 | 1767 | ** The z[] input contains text mixed with TH1 scripts. |
| 1710 | -** The TH1 scripts are contained within <th1>...</th1>. | |
| 1711 | -** TH1 variables are $aaa or $<aaa>. The first form of | |
| 1712 | -** variable is literal. The second is run through htmlize | |
| 1713 | -** before being inserted. | |
| 1768 | +** The TH1 scripts are contained within <th1>...</th1>. | |
| 1769 | +** | |
| 1770 | +** If flags does NOT contain the Th_Render_Flags_NO_DOLLAR_DEREF bit | |
| 1771 | +** then TH1 variables are $aaa or $<aaa>. The first form of variable | |
| 1772 | +** is literal. The second is run through htmlize before being | |
| 1773 | +** inserted. | |
| 1714 | 1774 | ** |
| 1715 | 1775 | ** This routine processes the template and writes the results |
| 1716 | -** on either stdout or into CGI. | |
| 1776 | +** via Th_output(). | |
| 1717 | 1777 | */ |
| 1718 | -int Th_Render(const char *z){ | |
| 1778 | +int Th_Render(const char *z, int flags){ | |
| 1719 | 1779 | int i = 0; |
| 1720 | 1780 | int n; |
| 1721 | 1781 | int rc = TH_OK; |
| 1722 | - char *zResult; | |
| 1782 | + char const *zResult; | |
| 1783 | + char doDollar = !(flags & Th_Render_Flags_NO_DOLLAR_DEREF); | |
| 1723 | 1784 | Th_FossilInit(); |
| 1724 | 1785 | while( z[i] ){ |
| 1725 | - if( z[i]=='$' && (n = validVarName(&z[i+1]))>0 ){ | |
| 1786 | + if( doDollar && z[i]=='$' && (n = validVarName(&z[i+1]))>0 ){ | |
| 1726 | 1787 | const char *zVar; |
| 1727 | 1788 | int nVar; |
| 1728 | 1789 | int encode = 1; |
| 1729 | 1790 | sendText(g.interp, z, i, 0); |
| 1730 | 1791 | if( z[i+1]=='<' ){ |
| @@ -1735,15 +1796,15 @@ | ||
| 1735 | 1796 | /* Variables of the form $aaa are output raw */ |
| 1736 | 1797 | zVar = &z[i+1]; |
| 1737 | 1798 | nVar = n; |
| 1738 | 1799 | encode = 0; |
| 1739 | 1800 | } |
| 1740 | - rc = Th_GetVar(g.interp, (char*)zVar, nVar); | |
| 1801 | + rc = Th_GetVar(g.interp, zVar, nVar); | |
| 1741 | 1802 | z += i+1+n; |
| 1742 | 1803 | i = 0; |
| 1743 | - zResult = (char*)Th_GetResult(g.interp, &n); | |
| 1744 | - sendText(g.interp, (char*)zResult, n, encode); | |
| 1804 | + zResult = Th_GetResult(g.interp, &n); | |
| 1805 | + sendText(g.interp, zResult, n, encode); | |
| 1745 | 1806 | }else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){ |
| 1746 | 1807 | sendText(g.interp, z, i, 0); |
| 1747 | 1808 | z += i+5; |
| 1748 | 1809 | for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){} |
| 1749 | 1810 | rc = Th_Eval(g.interp, 0, (const char*)z, i); |
| @@ -1787,7 +1848,7 @@ | ||
| 1787 | 1848 | db_open_config(0); /* Needed for global "tcl" setting. */ |
| 1788 | 1849 | #ifdef TH_USE_SQLITE |
| 1789 | 1850 | db_find_and_open_repository(OPEN_ANY_SCHEMA,0) /* for query_xxx API. */; |
| 1790 | 1851 | #endif |
| 1791 | 1852 | blob_read_from_file(&in, g.argv[2]); |
| 1792 | - Th_Render(blob_str(&in)); | |
| 1853 | + Th_Render(blob_str(&in), Th_Render_Flags_DEFAULT); | |
| 1793 | 1854 | } |
| 1794 | 1855 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -17,12 +17,14 @@ | |
| 17 | ** |
| 18 | ** This file contains an interface between the TH scripting language |
| 19 | ** (an independent project) and fossil. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "th_main.h" |
| 23 | |
| 24 | /* |
| 25 | ** Global variable counting the number of outstanding calls to malloc() |
| 26 | ** made by the th1 implementation. This is used to catch memory leaks |
| 27 | ** in the interpreter. Obviously, it also means th1 is not threadsafe. |
| 28 | */ |
| @@ -220,10 +222,63 @@ | |
| 220 | Th_SetResult(interp, zOut, -1); |
| 221 | free(zOut); |
| 222 | return TH_OK; |
| 223 | } |
| 224 | |
| 225 | /* |
| 226 | ** TH command: date |
| 227 | ** |
| 228 | ** Return a string which is the current time and date. If the |
| 229 | ** -local option is used, the date appears using localtime instead |
| @@ -1571,20 +1626,23 @@ | |
| 1571 | static PutsCmdData puts_Html = {0, 0, 0}; |
| 1572 | static PutsCmdData puts_Normal = {1, 0, 0}; |
| 1573 | static Th_Command_Reg aCommand[] = { |
| 1574 | {"anycap", anycapCmd, 0}, |
| 1575 | {"combobox", comboboxCmd, 0}, |
| 1576 | {"enable_output", enableOutputCmd, 0}, |
| 1577 | {"linecount", linecntCmd, 0}, |
| 1578 | {"hascap", hascapCmd, 0}, |
| 1579 | {"hasfeature", hasfeatureCmd, 0}, |
| 1580 | {"htmlize", htmlizeCmd, 0}, |
| 1581 | {"date", dateCmd, 0}, |
| 1582 | {"html", putsCmd, &puts_Html}, |
| 1583 | {"puts", putsCmd, &puts_Normal}, |
| 1584 | {"wiki", wikiCmd, 0}, |
| 1585 | {"repository", repositoryCmd, 0}, |
| 1586 | |
| 1587 | {0, 0, 0} |
| 1588 | }; |
| 1589 | if( g.interp==0 ){ |
| 1590 | int i; |
| @@ -1705,26 +1763,29 @@ | |
| 1705 | return i; |
| 1706 | } |
| 1707 | |
| 1708 | /* |
| 1709 | ** The z[] input contains text mixed with TH1 scripts. |
| 1710 | ** The TH1 scripts are contained within <th1>...</th1>. |
| 1711 | ** TH1 variables are $aaa or $<aaa>. The first form of |
| 1712 | ** variable is literal. The second is run through htmlize |
| 1713 | ** before being inserted. |
| 1714 | ** |
| 1715 | ** This routine processes the template and writes the results |
| 1716 | ** on either stdout or into CGI. |
| 1717 | */ |
| 1718 | int Th_Render(const char *z){ |
| 1719 | int i = 0; |
| 1720 | int n; |
| 1721 | int rc = TH_OK; |
| 1722 | char *zResult; |
| 1723 | Th_FossilInit(); |
| 1724 | while( z[i] ){ |
| 1725 | if( z[i]=='$' && (n = validVarName(&z[i+1]))>0 ){ |
| 1726 | const char *zVar; |
| 1727 | int nVar; |
| 1728 | int encode = 1; |
| 1729 | sendText(g.interp, z, i, 0); |
| 1730 | if( z[i+1]=='<' ){ |
| @@ -1735,15 +1796,15 @@ | |
| 1735 | /* Variables of the form $aaa are output raw */ |
| 1736 | zVar = &z[i+1]; |
| 1737 | nVar = n; |
| 1738 | encode = 0; |
| 1739 | } |
| 1740 | rc = Th_GetVar(g.interp, (char*)zVar, nVar); |
| 1741 | z += i+1+n; |
| 1742 | i = 0; |
| 1743 | zResult = (char*)Th_GetResult(g.interp, &n); |
| 1744 | sendText(g.interp, (char*)zResult, n, encode); |
| 1745 | }else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){ |
| 1746 | sendText(g.interp, z, i, 0); |
| 1747 | z += i+5; |
| 1748 | for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){} |
| 1749 | rc = Th_Eval(g.interp, 0, (const char*)z, i); |
| @@ -1787,7 +1848,7 @@ | |
| 1787 | db_open_config(0); /* Needed for global "tcl" setting. */ |
| 1788 | #ifdef TH_USE_SQLITE |
| 1789 | db_find_and_open_repository(OPEN_ANY_SCHEMA,0) /* for query_xxx API. */; |
| 1790 | #endif |
| 1791 | blob_read_from_file(&in, g.argv[2]); |
| 1792 | Th_Render(blob_str(&in)); |
| 1793 | } |
| 1794 |
| --- src/th_main.c | |
| +++ src/th_main.c | |
| @@ -17,12 +17,14 @@ | |
| 17 | ** |
| 18 | ** This file contains an interface between the TH scripting language |
| 19 | ** (an independent project) and fossil. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | |
| 23 | #include "th_main.h" |
| 24 | |
| 25 | /*#include "th_main.h"*/ |
| 26 | /* |
| 27 | ** Global variable counting the number of outstanding calls to malloc() |
| 28 | ** made by the th1 implementation. This is used to catch memory leaks |
| 29 | ** in the interpreter. Obviously, it also means th1 is not threadsafe. |
| 30 | */ |
| @@ -220,10 +222,63 @@ | |
| 222 | Th_SetResult(interp, zOut, -1); |
| 223 | free(zOut); |
| 224 | return TH_OK; |
| 225 | } |
| 226 | |
| 227 | #if 0 |
| 228 | /* i'm not sure we need this */ |
| 229 | /* |
| 230 | ** TH command: render STRING |
| 231 | ** |
| 232 | ** Render the input string as TH1. |
| 233 | */ |
| 234 | static int renderCmd( |
| 235 | Th_Interp *interp, |
| 236 | void *p, |
| 237 | int argc, |
| 238 | const char **argv, |
| 239 | int *argl |
| 240 | ){ |
| 241 | if( argc<2 ){ |
| 242 | return Th_WrongNumArgs2(interp, |
| 243 | argv[0], argl[0], |
| 244 | "STRING ?STRING...?"); |
| 245 | }else{ |
| 246 | Th_Ob_Man * man = Th_ob_manager(interp); |
| 247 | Blob * b = NULL; |
| 248 | Blob buf = empty_blob; |
| 249 | int rc, i; |
| 250 | /*FIXME: assert(NULL != man && man->interp==interp);*/ |
| 251 | man->interp = interp; |
| 252 | /* Combine all inputs into one buffer so that we can use that to |
| 253 | embed TH1 tags across argument boundaries. |
| 254 | |
| 255 | FIX:E optimize away buf for the 1-arg case. |
| 256 | */ |
| 257 | for( i = 1; TH_OK==rc && i < argc; ++i ){ |
| 258 | char const * str = argv[i]; |
| 259 | blob_append( &buf, str, argl[i] ); |
| 260 | /*rc = Th_Render( str, Th_Render_Flags_NO_DOLLAR_DEREF );*/ |
| 261 | } |
| 262 | rc = Th_ob_push( man, &b ); |
| 263 | if(rc){ |
| 264 | blob_reset( &buf ); |
| 265 | return rc; |
| 266 | } |
| 267 | rc = Th_Render( buf.aData, Th_Render_Flags_DEFAULT ); |
| 268 | blob_reset(&buf); |
| 269 | b = Th_ob_pop( man ); |
| 270 | if(TH_OK==rc){ |
| 271 | Th_SetResult( interp, b->aData, b->nUsed ); |
| 272 | } |
| 273 | blob_reset( b ); |
| 274 | Th_Free( interp, b ); |
| 275 | return rc; |
| 276 | } |
| 277 | }/* renderCmd() */ |
| 278 | #endif |
| 279 | |
| 280 | /* |
| 281 | ** TH command: date |
| 282 | ** |
| 283 | ** Return a string which is the current time and date. If the |
| 284 | ** -local option is used, the date appears using localtime instead |
| @@ -1571,20 +1626,23 @@ | |
| 1626 | static PutsCmdData puts_Html = {0, 0, 0}; |
| 1627 | static PutsCmdData puts_Normal = {1, 0, 0}; |
| 1628 | static Th_Command_Reg aCommand[] = { |
| 1629 | {"anycap", anycapCmd, 0}, |
| 1630 | {"combobox", comboboxCmd, 0}, |
| 1631 | {"date", dateCmd, 0}, |
| 1632 | {"enable_output", enableOutputCmd, 0}, |
| 1633 | {"hascap", hascapCmd, 0}, |
| 1634 | {"hasfeature", hasfeatureCmd, 0}, |
| 1635 | {"html", putsCmd, &puts_Html}, |
| 1636 | {"htmlize", htmlizeCmd, 0}, |
| 1637 | {"linecount", linecntCmd, 0}, |
| 1638 | {"puts", putsCmd, &puts_Normal}, |
| 1639 | #if 0 |
| 1640 | {"render", renderCmd, 0}, |
| 1641 | #endif |
| 1642 | {"repository", repositoryCmd, 0}, |
| 1643 | {"wiki", wikiCmd, 0}, |
| 1644 | |
| 1645 | {0, 0, 0} |
| 1646 | }; |
| 1647 | if( g.interp==0 ){ |
| 1648 | int i; |
| @@ -1705,26 +1763,29 @@ | |
| 1763 | return i; |
| 1764 | } |
| 1765 | |
| 1766 | /* |
| 1767 | ** The z[] input contains text mixed with TH1 scripts. |
| 1768 | ** The TH1 scripts are contained within <th1>...</th1>. |
| 1769 | ** |
| 1770 | ** If flags does NOT contain the Th_Render_Flags_NO_DOLLAR_DEREF bit |
| 1771 | ** then TH1 variables are $aaa or $<aaa>. The first form of variable |
| 1772 | ** is literal. The second is run through htmlize before being |
| 1773 | ** inserted. |
| 1774 | ** |
| 1775 | ** This routine processes the template and writes the results |
| 1776 | ** via Th_output(). |
| 1777 | */ |
| 1778 | int Th_Render(const char *z, int flags){ |
| 1779 | int i = 0; |
| 1780 | int n; |
| 1781 | int rc = TH_OK; |
| 1782 | char const *zResult; |
| 1783 | char doDollar = !(flags & Th_Render_Flags_NO_DOLLAR_DEREF); |
| 1784 | Th_FossilInit(); |
| 1785 | while( z[i] ){ |
| 1786 | if( doDollar && z[i]=='$' && (n = validVarName(&z[i+1]))>0 ){ |
| 1787 | const char *zVar; |
| 1788 | int nVar; |
| 1789 | int encode = 1; |
| 1790 | sendText(g.interp, z, i, 0); |
| 1791 | if( z[i+1]=='<' ){ |
| @@ -1735,15 +1796,15 @@ | |
| 1796 | /* Variables of the form $aaa are output raw */ |
| 1797 | zVar = &z[i+1]; |
| 1798 | nVar = n; |
| 1799 | encode = 0; |
| 1800 | } |
| 1801 | rc = Th_GetVar(g.interp, zVar, nVar); |
| 1802 | z += i+1+n; |
| 1803 | i = 0; |
| 1804 | zResult = Th_GetResult(g.interp, &n); |
| 1805 | sendText(g.interp, zResult, n, encode); |
| 1806 | }else if( z[i]=='<' && isBeginScriptTag(&z[i]) ){ |
| 1807 | sendText(g.interp, z, i, 0); |
| 1808 | z += i+5; |
| 1809 | for(i=0; z[i] && (z[i]!='<' || !isEndScriptTag(&z[i])); i++){} |
| 1810 | rc = Th_Eval(g.interp, 0, (const char*)z, i); |
| @@ -1787,7 +1848,7 @@ | |
| 1848 | db_open_config(0); /* Needed for global "tcl" setting. */ |
| 1849 | #ifdef TH_USE_SQLITE |
| 1850 | db_find_and_open_repository(OPEN_ANY_SCHEMA,0) /* for query_xxx API. */; |
| 1851 | #endif |
| 1852 | blob_read_from_file(&in, g.argv[2]); |
| 1853 | Th_Render(blob_str(&in), Th_Render_Flags_DEFAULT); |
| 1854 | } |
| 1855 |
+3
-3
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -328,11 +328,11 @@ | ||
| 328 | 328 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 329 | 329 | ticket_init(); |
| 330 | 330 | initializeVariablesFromDb(); |
| 331 | 331 | zScript = ticket_viewpage_code(); |
| 332 | 332 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1); |
| 333 | - Th_Render(zScript); | |
| 333 | + Th_Render(zScript, Th_Render_Flags_DEFAULT ); | |
| 334 | 334 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 335 | 335 | |
| 336 | 336 | zFullName = db_text(0, |
| 337 | 337 | "SELECT tkt_uuid FROM ticket" |
| 338 | 338 | " WHERE tkt_uuid GLOB '%q*'", zUuid); |
| @@ -540,11 +540,11 @@ | ||
| 540 | 540 | Th_Store("login", g.zLogin); |
| 541 | 541 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 542 | 542 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 543 | 543 | (void*)&zNewUuid, 0); |
| 544 | 544 | if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); |
| 545 | - if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){ | |
| 545 | + if( Th_Render(zScript, Th_Render_Flags_DEFAULT)==TH_RETURN && !g.thTrace && zNewUuid ){ | |
| 546 | 546 | cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid)); |
| 547 | 547 | return; |
| 548 | 548 | } |
| 549 | 549 | @ </form> |
| 550 | 550 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| @@ -607,11 +607,11 @@ | ||
| 607 | 607 | Th_Store("login", g.zLogin); |
| 608 | 608 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 609 | 609 | Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); |
| 610 | 610 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); |
| 611 | 611 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1); |
| 612 | - if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){ | |
| 612 | + if( Th_Render(zScript, Th_Render_Flags_DEFAULT)==TH_RETURN && !g.thTrace && zName ){ | |
| 613 | 613 | cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName)); |
| 614 | 614 | return; |
| 615 | 615 | } |
| 616 | 616 | @ </form> |
| 617 | 617 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 618 | 618 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -328,11 +328,11 @@ | |
| 328 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 329 | ticket_init(); |
| 330 | initializeVariablesFromDb(); |
| 331 | zScript = ticket_viewpage_code(); |
| 332 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1); |
| 333 | Th_Render(zScript); |
| 334 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 335 | |
| 336 | zFullName = db_text(0, |
| 337 | "SELECT tkt_uuid FROM ticket" |
| 338 | " WHERE tkt_uuid GLOB '%q*'", zUuid); |
| @@ -540,11 +540,11 @@ | |
| 540 | Th_Store("login", g.zLogin); |
| 541 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 542 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 543 | (void*)&zNewUuid, 0); |
| 544 | if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); |
| 545 | if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zNewUuid ){ |
| 546 | cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid)); |
| 547 | return; |
| 548 | } |
| 549 | @ </form> |
| 550 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| @@ -607,11 +607,11 @@ | |
| 607 | Th_Store("login", g.zLogin); |
| 608 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 609 | Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); |
| 610 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); |
| 611 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1); |
| 612 | if( Th_Render(zScript)==TH_RETURN && !g.thTrace && zName ){ |
| 613 | cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName)); |
| 614 | return; |
| 615 | } |
| 616 | @ </form> |
| 617 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 618 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -328,11 +328,11 @@ | |
| 328 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 329 | ticket_init(); |
| 330 | initializeVariablesFromDb(); |
| 331 | zScript = ticket_viewpage_code(); |
| 332 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW_SCRIPT<br />\n", -1); |
| 333 | Th_Render(zScript, Th_Render_Flags_DEFAULT ); |
| 334 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| 335 | |
| 336 | zFullName = db_text(0, |
| 337 | "SELECT tkt_uuid FROM ticket" |
| 338 | " WHERE tkt_uuid GLOB '%q*'", zUuid); |
| @@ -540,11 +540,11 @@ | |
| 540 | Th_Store("login", g.zLogin); |
| 541 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 542 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, |
| 543 | (void*)&zNewUuid, 0); |
| 544 | if( g.thTrace ) Th_Trace("BEGIN_TKTNEW_SCRIPT<br />\n", -1); |
| 545 | if( Th_Render(zScript, Th_Render_Flags_DEFAULT)==TH_RETURN && !g.thTrace && zNewUuid ){ |
| 546 | cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zNewUuid)); |
| 547 | return; |
| 548 | } |
| 549 | @ </form> |
| 550 | if( g.thTrace ) Th_Trace("END_TKTVIEW<br />\n", -1); |
| @@ -607,11 +607,11 @@ | |
| 607 | Th_Store("login", g.zLogin); |
| 608 | Th_Store("date", db_text(0, "SELECT datetime('now')")); |
| 609 | Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); |
| 610 | Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); |
| 611 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT_SCRIPT<br />\n", -1); |
| 612 | if( Th_Render(zScript, Th_Render_Flags_DEFAULT)==TH_RETURN && !g.thTrace && zName ){ |
| 613 | cgi_redirect(mprintf("%s/tktview/%s", g.zTop, zName)); |
| 614 | return; |
| 615 | } |
| 616 | @ </form> |
| 617 | if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); |
| 618 |