@@ -61,8 +61,10 @@
#if INTERFACE
typedef struct Subscript Subscript;
#define SBS_OK 0
#define SBS_ERROR 1
+#define SBS_RETURN 2
+#define SBS_BREAK 3
#endif
/*
** Configuration constants
@@ -344,15 +346,23 @@
/*
** Set the error message for an interpreter. Verb implementations
** use this routine when they encounter an error.
*/
-void SbS_SetErrorMessage(struct Subscript *p, const char *zErr){
- int nErr = strlen(zErr);
+void SbS_SetErrorMessage(struct Subscript *p, const char *zErr, ...){
+ int nErr;
+ char *zMsg;
+ va_list ap;
+
+ va_start(ap, zErr);
+ zMsg = vmprintf(zErr, ap);
+ va_end(ap);
+ nErr = strlen(zMsg);
if( nErr>sizeof(p->zErrMsg)-1 ){
nErr = sizeof(p->zErrMsg)-1;
}
- memcpy(p->zErrMsg, zErr, nErr);
+ memcpy(p->zErrMsg, zMsg, nErr);
p->zErrMsg[nErr] = 0;
+ free(zMsg);
}
/*
** Return a pointer to the current error message for the
@@ -529,13 +539,14 @@
*/
const char *SbS_Fetch(
struct Subscript *p, /* The interpreter we are interrogating */
const char *zKey, /* Name of the variable. Case sensitive */
+ int nKey, /* Length of the key */
int *pLength /* Write the length here */
){
const SbSValue *pVal;
- pVal = sbs_fetch(&p->symTab, zKey, -1);
+ pVal = sbs_fetch(&p->symTab, zKey, nKey);
if( pVal==0 || (pVal->flags & SBSVAL_STR)==0 ){
*pLength = 0;
return 0;
}else{
@@ -710,8 +721,23 @@
return 0;
}
/*
+** Send text to the appropriate output: Either to the console
+** or to the CGI reply buffer.
+*/
+static void sendText(const char *z, int n){
+ if( enableOutput && n ){
+ if( n<0 ) n = strlen(z);
+ if( g.cgiPanic ){
+ cgi_append_content(z, n);
+ }else{
+ fwrite(z, 1, n, stdout);
+ }
+ }
+}
+
+/*
** Subscript command: STRING puts
** Subscript command: STRING html
**
** Output STRING as HTML (html) or unchanged (puts).
@@ -729,18 +755,81 @@
size = strlen(zOut);
}else{
zOut = (char*)z;
}
- if( g.cgiPanic ){
- cgi_append_content(zOut, size);
- }else{
- printf("%.*s", size, zOut);
- }
+ sendText(zOut, size);
if( pConvert ){
free(zOut);
}
}
SbS_Pop(p, 1);
+ return 0;
+}
+
+/*
+** Subscript command: STRING wiki
+**
+** Render the input string as wiki.
+*/
+static int wikiCmd(struct Subscript *p, void *pConvert){
+ int size;
+ const char *z;
+ if( SbS_RequireStack(p, 1, "wiki") ) return 1;
+ if( enableOutput ){
+ Blob src;
+ z = SbS_StackValue(p, 0, &size);
+ blob_init(&src, z, size);
+ wiki_convert(&src, 0, WIKI_INLINE);
+ blob_reset(&src);
+ }
+ SbS_Pop(p, 1);
+ return 0;
+}
+
+/*
+** Subscript command: NAME TEXT-LIST NUMLINES combobox
+**
+** Generate an HTML combobox. NAME is both the name of the
+** CGI parameter and the name of a variable that contains the
+** currently selected value. TEXT-LIST is a list of possible
+** values for the combobox. NUMLINES is 1 for a true combobox.
+** If NUMLINES is greater than one then the display is a listbox
+** with the number of lines given.
+*/
+static int comboboxCmd(struct Subscript *p, void *NotUsed){
+ if( SbS_RequireStack(p, 3, "combobox") ) return 1;
+ if( enableOutput ){
+ int height;
+ Blob list, elem;
+ char *zName, *zList;
+ int nName, nList, nValue;
+ const char *zValue;
+ char *z, *zH;
+
+ height = SbS_StackValueInt(p, 0);
+ zList = (char*)SbS_StackValue(p, 1, &nList);
+ blob_init(&list, zList, nList);
+ zName = (char*)SbS_StackValue(p, 2, &nName);
+ zValue = SbS_Fetch(p, zName, nName, &nValue);
+ z = mprintf("<select name=\"%.*h\" size=\"%d\">", nName, zName, height);
+ sendText(z, -1);
+ free(z);
+ while( blob_token(&list, &elem) ){
+ zH = mprintf("%.*h", blob_size(&elem), blob_buffer(&elem));
+ if( zValue && blob_size(&elem)==nValue
+ && memcmp(zValue, blob_buffer(&elem), nValue)==0 ){
+ z = mprintf("<option value=\"%s\" selected>%s</option>", zH, zH);
+ }else{
+ z = mprintf("<option value=\"%s\">%s</option>", zH, zH);
+ }
+ free(zH);
+ sendText(z, -1);
+ free(z);
+ }
+ sendText("</select>", -1);
+ blob_reset(&list);
+ }
+ SbS_Pop(p, 3);
return 0;
}
@@ -753,8 +842,9 @@
void *pArg;
} aBuiltin[] = {
{ "add", bopCmd, (void*)SBSOP_AND },
{ "and", bopCmd, (void*)SBSOP_AND },
+ { "combobox", comboboxCmd, 0, },
{ "div", bopCmd, (void*)SBSOP_DIV },
{ "enable_output", enableOutputCmd, 0 },
{ "exists", existsCmd, 0, },
{ "get", getCmd, 0, },
@@ -768,8 +858,9 @@
{ "or", bopCmd, (void*)SBSOP_OR },
{ "puts", putsCmd, 0 },
{ "set", setCmd, 0 },
{ "sub", bopCmd, (void*)SBSOP_SUB },
+ { "wiki", wikiCmd, 0, },
};
/*
@@ -861,8 +952,11 @@
}else{
lwr = i+1;
}
}
+ if( upr<lwr ){
+ SbS_SetErrorMessage(p, "unknown verb: %.*s", n, zScript);
+ }
}else if( pVal->flags & SBSVAL_VERB ){
rc = pVal->u.verb.xVerb(p, pVal->u.verb.pArg);
}else if( pVal->flags & SBSVAL_EXEC ){
rc = SbS_Eval(p, pVal->u.str.z, pVal->u.str.size);
@@ -888,15 +982,9 @@
int i = 0;
int rc = SBS_OK;
while( z[i] ){
if( z[i]=='[' ){
- if( enableOutput ){
- if( g.cgiPanic ){
- cgi_append_content(z, i);
- }else{
- fwrite(z, 1, i, stdout);
- }
- }
+ sendText(z, i);
z += i+1;
for(i=0; z[i] && z[i]!=']'; i++){}
rc = SbS_Eval(p, z, i);
if( rc!=SBS_OK ) break;
@@ -906,14 +994,14 @@
}else{
i++;
}
}
- if( i>0 && enableOutput ){
- if( g.cgiPanic ){
- cgi_append_content(z, i);
- }else{
- fwrite(z, 1, i, stdout);
- }
+ if( rc==SBS_ERROR ){
+ sendText("<hr><p><font color=\"red\"><b>ERROR: ", -1);
+ sendText(SbS_GetErrorMessage(p), -1);
+ sendText("</b></font></p>", -1);
+ }else{
+ sendText(z, i);
}
return rc;
}