diff -Nrbu clearsilver-0.10.2/cgi/cgi_cstest.c clearsilver-0.10.3/cgi/cgi_cstest.c --- clearsilver-0.10.2/cgi/cgi_cstest.c 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cgi/cgi_cstest.c 2006-01-31 18:54:09.000000000 -0800 @@ -0,0 +1,114 @@ +/* + * Copyright 2001-2004 Brandon Long + * All Rights Reserved. + * + * ClearSilver Templating System + * + * This code is made available under the terms of the ClearSilver License. + * http://www.clearsilver.net/license.hdf + * + */ + +#include "ClearSilver.h" + +#include +#include + +static NEOERR *output (void *ctx, char *s) +{ + printf ("%s", s); + return STATUS_OK; +} + +int main (int argc, char *argv[]) +{ + NEOERR *err; + CSPARSE *parse; + HDF *hdf; + int verbose = 0; + char *hdf_file, *cs_file; + + if (argc < 3) + { + ne_warn ("Usage: cstest [-v] "); + return -1; + } + + if (!strcmp(argv[1], "-v")) + { + verbose = 1; + if (argc < 4) + { + ne_warn ("Usage: cstest [-v] "); + return -1; + } + hdf_file = argv[2]; + cs_file = argv[3]; + } + else + { + hdf_file = argv[1]; + cs_file = argv[2]; + } + + err = hdf_init(&hdf); + if (err != STATUS_OK) + { + nerr_log_error(err); + return -1; + } + err = hdf_read_file(hdf, hdf_file); + if (err != STATUS_OK) + { + nerr_log_error(err); + return -1; + } + + printf ("Parsing %s\n", cs_file); + err = cs_init (&parse, hdf); + if (err != STATUS_OK) + { + nerr_log_error(err); + return -1; + } + err = cgi_register_strfuncs(parse); + if (err != STATUS_OK) + { + nerr_log_error(err); + return -1; + } + + err = cs_parse_file (parse, cs_file); + if (err != STATUS_OK) + { + err = nerr_pass(err); + nerr_log_error(err); + return -1; + } + + err = cs_render(parse, NULL, output); + if (err != STATUS_OK) + { + err = nerr_pass(err); + nerr_log_error(err); + return -1; + } + + if (verbose) + { + printf ("\n-----------------------\nCS DUMP\n"); + err = cs_dump(parse, NULL, output); + } + + cs_destroy (&parse); + + if (verbose) + { + printf ("\n-----------------------\nHDF DUMP\n"); + hdf_dump (hdf, NULL); + } + hdf_destroy(&hdf); + + + return 0; +} diff -Nrbu clearsilver-0.10.2/cgi/cgiwrap.c clearsilver-0.10.3/cgi/cgiwrap.c --- clearsilver-0.10.2/cgi/cgiwrap.c 2005-06-30 18:20:21.000000000 -0700 +++ clearsilver-0.10.3/cgi/cgiwrap.c 2006-01-22 15:43:00.000000000 -0800 @@ -39,12 +39,22 @@ static CGIWRAPPER GlobalWrapper = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0}; -static void cgiwrap_init (void) +void cgiwrap_init_std (int argc, char **argv, char **envp) { - GlobalWrapper.argc = 0; - GlobalWrapper.argv = NULL; - GlobalWrapper.envp = NULL; + /* Allow setting of these even after cgiwrap_init_emu is called */ + GlobalWrapper.argc = argc; + GlobalWrapper.argv = argv; + GlobalWrapper.envp = envp; GlobalWrapper.env_count = 0; + while (envp[GlobalWrapper.env_count] != NULL) GlobalWrapper.env_count++; + + /* so you can compile the same code for embedded without mods. + * Note that this setting is global for the lifetime of the program, so + * you can never reset these values after calling cgiwrap_init_emu by + * calling cgiwrap_init_std, you'll have to call cgiwrap_init_emu with NULL + * values to reset */ + if (GlobalWrapper.emu_init) return; + GlobalWrapper.read_cb = NULL; GlobalWrapper.writef_cb = NULL; GlobalWrapper.write_cb = NULL; @@ -54,23 +64,14 @@ GlobalWrapper.data = NULL; } -void cgiwrap_init_std (int argc, char **argv, char **envp) -{ - /* so you can compile the same code for embedded without mods */ - if (GlobalWrapper.emu_init) return; - - cgiwrap_init(); - GlobalWrapper.argc = argc; - GlobalWrapper.argv = argv; - GlobalWrapper.envp = envp; - while (envp[GlobalWrapper.env_count] != NULL) GlobalWrapper.env_count++; -} - void cgiwrap_init_emu (void *data, READ_FUNC read_cb, WRITEF_FUNC writef_cb, WRITE_FUNC write_cb, GETENV_FUNC getenv_cb, PUTENV_FUNC putenv_cb, ITERENV_FUNC iterenv_cb) { - cgiwrap_init(); + /* leave argc, argv, envp, env_count alone since we either don't use them, or + * they are used by the default versions if any of these are passed as NULL. + * Note that means that if you pass NULL for anything here, you'd better + * have called cgiwrap_init_std first! */ GlobalWrapper.data = data; GlobalWrapper.read_cb = read_cb; GlobalWrapper.writef_cb = writef_cb; diff -Nrbu clearsilver-0.10.2/cgi/Makefile clearsilver-0.10.3/cgi/Makefile --- clearsilver-0.10.2/cgi/Makefile 2005-12-02 02:34:24.000000000 -0800 +++ clearsilver-0.10.3/cgi/Makefile 2006-01-31 18:53:23.000000000 -0800 @@ -15,9 +15,13 @@ STATIC_OBJ = $(STATIC_SRC:%.c=%.o) STATIC_CSO = $(STATIC_EXE:%.cgi=%.cso) +CGICSTEST_EXE = cgi_cstest +CGICSTEST_SRC = cgi_cstest.c +CGICSTEST_OBJ = $(CGICSTEST_SRC:%.c=%.o) + DLIBS += -lneo_cgi -lneo_cs -lneo_utl # -lefence -TARGETS = $(CGI_LIB) $(STATIC_EXE) $(STATIC_CSO) +TARGETS = $(CGI_LIB) $(STATIC_EXE) $(STATIC_CSO) $(CGICSTEST_EXE) all: $(TARGETS) @@ -31,6 +35,9 @@ $(STATIC_CSO): $(STATIC_OBJ) $(DEP_LIBS) $(LDSHARED) -o $@ $(STATIC_OBJ) -L$(LIB_DIR) $(DLIBS) $(LIBS) +$(CGICSTEST_EXE): $(CGICSTEST_OBJ) $(DEP_LIBS) + $(LD) $@ $(CGICSTEST_OBJ) -L$(LIB_DIR) $(DLIBS) $(LIBS) + install: all $(NEOTONIC_ROOT)/mkinstalldirs $(DESTDIR)$(cs_includedir)/cgi $(INSTALL) -m 644 cgi.h $(DESTDIR)$(cs_includedir)/cgi diff -Nrbu clearsilver-0.10.2/configure.in clearsilver-0.10.3/configure.in --- clearsilver-0.10.2/configure.in 2005-12-02 03:03:35.000000000 -0800 +++ clearsilver-0.10.3/configure.in 2006-03-12 16:05:26.000000000 -0800 @@ -245,6 +245,7 @@ if test $cs_cv_python = yes; then AC_MSG_CHECKING(for python includes) python_inc=no + python_lib=no python_search_path="/neo/opt /usr/local /usr /c" python_versions="2.4 2.3 2.2 2.1 2.0 1.5 24 23 22 21 20 15" if test $cs_cv_python_path != "no" -a -x $cs_cv_python_path; then @@ -259,12 +260,29 @@ for path in $python_search_path; do if test -x $path/bin/python$vers; then python_bin=$path/bin/python$vers + major_vers=`echo $vers | cut -b 1` + if test $major_vers -ge 2; then + python_base=`$python_bin -c "import sys, os; print os.path.dirname([[x for x in sys.path if x.find('site-packages') != -1]][[0]])"` + else + python_base=`$python_bin -c "import site, os; print os.path.dirname(site.sitedirs[[0]])"` + fi + if test -d $python_base; then + python_lib="-L$python_base/config -lpython$vers" + python_site=$python_base/site-packages + fi fi if test -f $path/include/python$vers/Python.h; then python_inc=$path/include/python$vers + fi + if test "x$python_lib" = "xno"; then + if test -d $path/lib/python$vers; then python_lib="-L$path/lib/python$vers/config -lpython$vers" python_site=$path/lib/python$vers/site-packages - break 2 + fi + if test -d $path/lib64/python$vers; then + python_lib="-L$path/lib64/python$vers/config -lpython$vers" + python_site=$path/lib64/python$vers/site-packages + fi fi dnl This is currently special cased mostly for Windows dnl installs, but we only use python_lib for windows anyways @@ -274,6 +292,9 @@ python_site=$path/python$vers/Lib/site-packages break 2 fi + if test "x$python_inc" != "xno" -a "x$python_lib" != "xno"; then + break 2 + fi done done fi @@ -288,7 +309,7 @@ PYTHON=$python_bin PYTHON_INC="-I$python_inc" PYTHON_LIB=$python_lib - if test ! $?PYTHON_SITE; then + if test "x$PYTHON_SITE" = "x"; then PYTHON_SITE=$python_site fi BUILD_WRAPPERS="$BUILD_WRAPPERS python" diff -Nrbu clearsilver-0.10.2/cs/cs.h clearsilver-0.10.3/cs/cs.h --- clearsilver-0.10.2/cs/cs.h 2005-11-30 19:58:44.000000000 -0800 +++ clearsilver-0.10.3/cs/cs.h 2006-02-02 18:17:49.000000000 -0800 @@ -92,7 +92,7 @@ CS_TYPE_FUNCTION = (1<<30) } CSTOKEN_TYPE; -#define CS_OPS_UNARY (CS_OP_EXISTS | CS_OP_NOT | CS_OP_NUM) +#define CS_OPS_UNARY (CS_OP_EXISTS | CS_OP_NOT | CS_OP_NUM | CS_OP_LPAREN) #define CS_TYPES (CS_TYPE_STRING | CS_TYPE_NUM | CS_TYPE_VAR | CS_TYPE_VAR_NUM) #define CS_OPS_LVALUE (CS_OP_DOT | CS_OP_LBRACKET | CS_TYPES) #define CS_TYPES_VAR (CS_TYPE_VAR | CS_TYPE_VAR_NUM) @@ -354,6 +354,13 @@ */ NEOERR *cs_register_strfunc(CSPARSE *parse, char *funcname, CSSTRFUNC str_func); +/* Testing functions for future function api. This api may change in the + * future. */ +NEOERR *cs_arg_parse(CSPARSE *parse, CSARG *args, const char *fmt, ...); +NEOERR *cs_arg_parsev(CSPARSE *parse, CSARG *args, const char *fmt, va_list ap); +NEOERR *cs_register_function(CSPARSE *parse, const char *funcname, + int n_args, CSFUNCTION function); + __END_DECLS #endif /* __CSHDF_H_ */ diff -Nrbu clearsilver-0.10.2/cs/csparse.c clearsilver-0.10.3/cs/csparse.c --- clearsilver-0.10.2/cs/csparse.c 2005-12-02 03:04:37.000000000 -0800 +++ clearsilver-0.10.3/cs/csparse.c 2006-02-02 18:17:41.000000000 -0800 @@ -621,11 +621,24 @@ { if (c == NULL) { + if (map->h == NULL) /* node didn't exist yet */ + return nerr_pass (hdf_set_value (parse->hdf, map->s, value)); + else return nerr_pass (hdf_set_value (map->h, NULL, value)); } else { *c = '.'; + if (map->h == NULL) /* node didn't exist yet */ + { + NEOERR *err; + char *mapped_name = sprintf_alloc("%s%s", map->s, c); + if (mapped_name == NULL) + return nerr_raise(NERR_NOMEM, "Unable to allocate memory to create mapped name"); + err = hdf_set_value(parse->hdf, mapped_name, value); + free(mapped_name); + return nerr_pass(err); + } return nerr_pass (hdf_set_value (map->h, c+1, value)); } } @@ -811,6 +824,7 @@ { if (*arg == '#') { + /* TODO: make # an operator and not syntax */ arg++; tokens[ntokens].type = CS_TYPE_NUM; tokens[ntokens].value = arg; @@ -858,6 +872,7 @@ } else if (*arg == '$') { + /* TODO: make $ an operator and not syntax */ arg++; tokens[ntokens].type = CS_TYPE_VAR; tokens[ntokens].value = arg; @@ -922,7 +937,7 @@ CS_OP_ADD | CS_OP_SUB, CS_OP_MULT | CS_OP_DIV | CS_OP_MOD, CS_OP_NOT | CS_OP_EXISTS, - CS_OP_LBRACKET | CS_OP_DOT, + CS_OP_LBRACKET | CS_OP_DOT | CS_OP_LPAREN, 0 }; @@ -1071,8 +1086,10 @@ return nerr_raise (NERR_PARSE, "%s Missing left parenthesis in expression", find_context(parse, -1, tmp, sizeof(tmp))); - if (x == 0) break; - x--; + /* if (x == 0) break; */ + /* x--; */ + /* we don't do an x-- here, because we are special casing the + * left bracket to be both an operator and an associative */ } if (tokens[x].type & CS_OP_RBRACKET) { @@ -1093,13 +1110,6 @@ /* we don't do an x-- here, because we are special casing the * left bracket to be both an operator and an associative */ } - else if (tokens[x].type & (CS_OP_LBRACKET | CS_OP_LPAREN)) - { - return nerr_raise (NERR_PARSE, - "%s Missing right %s in expression", - find_context(parse, -1, tmp, sizeof(tmp)), - (tokens[x].type == CS_OP_LBRACKET) ? "bracket" : "parenthesis"); - } if (lvalue && !(tokens[x].type & CS_OPS_LVALUE)) { return nerr_raise (NERR_PARSE, @@ -1109,7 +1119,7 @@ } if (tokens[x].type & OperatorOrder[op]) { - if (OperatorOrder[op] & CS_OPS_UNARY) + if (tokens[x].type & CS_OPS_UNARY) { if (x == 0) { @@ -1119,7 +1129,22 @@ return nerr_raise (NERR_NOMEM, "%s Unable to allocate memory for expression", find_context(parse, -1, tmp, sizeof(tmp))); + if (tokens[x].type & CS_OP_LPAREN) + { + if (!(tokens[ntokens-1].type & CS_OP_RPAREN)) + { + return nerr_raise (NERR_PARSE, + "%s Missing right parenthesis in expression", + find_context(parse, -1, tmp, sizeof(tmp))); + } + /* XXX: we might want to set lvalue to 0 here */ + /* -2 since we strip the RPAREN as well */ + err = parse_expr2(parse, tokens + 1, ntokens-2, lvalue, arg->expr1); + } + else + { err = parse_expr2(parse, tokens + 1, ntokens-1, lvalue, arg->expr1); + } return nerr_pass(err); } } @@ -1152,10 +1177,17 @@ return nerr_raise (NERR_NOMEM, "%s Unable to allocate memory for expression", find_context(parse, -1, tmp, sizeof(tmp))); - if (tokens[x].type == CS_OP_LBRACKET) + if (tokens[x].type & CS_OP_LBRACKET) + { + if (!(tokens[ntokens-1].type & CS_OP_RBRACKET)) { + return nerr_raise (NERR_PARSE, + "%s Missing right bracket in expression", + find_context(parse, -1, tmp, sizeof(tmp))); + } /* Inside of brackets, we don't limit to valid lvalue ops */ - err = parse_expr2(parse, tokens + x, ntokens-x, 0, arg->expr2); + /* -2 since we strip the RBRACKET as well */ + err = parse_expr2(parse, tokens + x + 1, ntokens-x-2, 0, arg->expr2); } else { @@ -1171,18 +1203,10 @@ } op++; } - /* ah, this expression just contains enclosing associatives, strip them */ - x = ntokens-1; - if ((tokens[0].type == CS_OP_LPAREN && tokens[x].type == CS_OP_RPAREN) || - (tokens[0].type == CS_OP_LBRACKET && tokens[x].type == CS_OP_RBRACKET)) - { - /* parens don't do anything, just strip them and pass */ - return nerr_pass(parse_expr2(parse, tokens + 1, ntokens-2, lvalue, arg)); - } /* Unary op against an entire expression */ if ((tokens[0].type & CS_OPS_UNARY) && tokens[1].type == CS_OP_LPAREN && - tokens[x].type == CS_OP_RPAREN) + tokens[ntokens-1].type == CS_OP_RPAREN) { arg->op_type = tokens[0].type; arg->expr1 = (CSARG *) calloc (1, sizeof (CSARG)); @@ -1207,7 +1231,7 @@ /* function call */ if ((tokens[0].type & CS_TYPE_VAR) && tokens[1].type == CS_OP_LPAREN && - tokens[x].type == CS_OP_RPAREN) + tokens[ntokens-1].type == CS_OP_RPAREN) { CS_FUNCTION *csf; int nargs; @@ -1851,19 +1875,13 @@ static NEOERR *eval_expr (CSPARSE *parse, CSARG *expr, CSARG *result) { - CSARG arg1, arg2; NEOERR *err; - long int n2; - char *s1, *s2; if (expr == NULL) return nerr_raise (NERR_ASSERT, "expr is NULL"); if (result == NULL) return nerr_raise (NERR_ASSERT, "result is NULL"); - arg1.alloc = 0; - arg2.alloc = 0; - #if DEBUG_EXPR_EVAL _depth++; expand_arg(parse, _depth, "expr", expr); @@ -1882,11 +1900,11 @@ return STATUS_OK; } - err = eval_expr (parse, expr->expr1, &arg1); - if (err) return nerr_pass(err); -#if DEBUG_EXPR_EVAL - expand_arg(parse, _depth, "arg1", &arg1); -#endif + if (expr->op_type & CS_OP_LPAREN) + { + /* lparen is a no-op, just skip */ + return nerr_pass(eval_expr(parse, expr->expr1, result)); + } if (expr->op_type & CS_TYPE_FUNCTION) { if (expr->function == NULL || expr->function->function == NULL) @@ -1894,10 +1912,23 @@ "Function is NULL in attempt to evaluate function call %s", (expr->function) ? expr->function->name : ""); - err = expr->function->function(parse, expr->function, &arg1, result); + /* The function evaluates all the arguments, so don't pre-evaluate + * argument1 */ + err = expr->function->function(parse, expr->function, expr->expr1, result); if (err) return nerr_pass(err); } - else if (expr->op_type & CS_OPS_UNARY) + else + { + CSARG arg1, arg2; + arg1.alloc = 0; + arg2.alloc = 0; + + err = eval_expr (parse, expr->expr1, &arg1); + if (err) return nerr_pass(err); +#if DEBUG_EXPR_EVAL + expand_arg(parse, _depth, "arg1", &arg1); +#endif + if (expr->op_type & CS_OPS_UNARY) { result->op_type = CS_TYPE_NUM; switch (expr->op_type) { @@ -1907,8 +1938,7 @@ case CS_OP_EXISTS: if (arg1.op_type & (CS_TYPE_VAR | CS_TYPE_VAR_NUM)) { - s1 = arg_eval (parse, &arg1); - if (s1 == NULL) + if (arg_eval(parse, &arg1) == NULL) result->n = 0; else result->n = 1; @@ -1922,6 +1952,8 @@ case CS_OP_NUM: result->n = arg_eval_num (parse, &arg1); break; + case CS_OP_LPAREN: + return nerr_raise(NERR_ASSERT, "LPAREN should be handled above"); default: result->n = 0; ne_warn ("Unsupported op %s in eval_expr", expand_token_type(expr->op_type, 1)); @@ -1967,14 +1999,14 @@ result->alloc = 1; if (arg2.op_type & (CS_TYPE_VAR_NUM | CS_TYPE_NUM)) { - n2 = arg_eval_num (parse, &arg2); + long int n2 = arg_eval_num (parse, &arg2); result->s = sprintf_alloc("%s.%d", arg1.s, n2); if (result->s == NULL) return nerr_raise (NERR_NOMEM, "Unable to allocate memory to concatenate varnames in expression: %s + %d", arg1.s, n2); } else { - s2 = arg_eval (parse, &arg2); + char *s2 = arg_eval (parse, &arg2); if (s2 && s2[0]) { result->s = sprintf_alloc("%s.%s", arg1.s, s2); @@ -2005,14 +2037,14 @@ { if (arg2.op_type & CS_TYPE_NUM) { - n2 = arg_eval_num (parse, &arg2); + long int n2 = arg_eval_num (parse, &arg2); result->s = sprintf_alloc("%s.%d", arg1.s, n2); if (result->s == NULL) return nerr_raise (NERR_NOMEM, "Unable to allocate memory to concatenate varnames in expression: %s + %d", arg1.s, n2); } else { - s2 = arg_eval (parse, &arg2); + char *s2 = arg_eval (parse, &arg2); if (s2 && s2[0]) { result->s = sprintf_alloc("%s.%s", arg1.s, s2); @@ -2039,16 +2071,15 @@ { /* eval as num */ err = eval_expr_num(parse, &arg1, &arg2, expr->op_type, result); - } else /* eval as string */ { err = eval_expr_string(parse, &arg1, &arg2, expr->op_type, result); } - } if (arg1.alloc) free(arg1.s); if (arg2.alloc) free(arg2.s); + } #if DEBUG_EXPR_EVAL expand_arg(parse, _depth, "result", result); @@ -2853,6 +2884,11 @@ var = var_lookup_obj (parse, val.s); map->h = var; map->type = CS_TYPE_VAR; + /* Bring across the name we're mapping to, in case h doesn't exist and + * we need to set it. */ + map->s = val.s; + map->map_alloc = val.alloc; + val.alloc = 0; } } else @@ -3199,7 +3235,7 @@ /* **** Functions ******************************************** */ -static NEOERR *_register_function(CSPARSE *parse, const char *funcname, +NEOERR *cs_register_function(CSPARSE *parse, const char *funcname, int n_args, CSFUNCTION function) { CS_FUNCTION *csf; @@ -3240,7 +3276,7 @@ * i - int * A - arg ptr (maybe later) */ -static NEOERR * cs_arg_parsev(CSPARSE *parse, CSARG *args, char *fmt, +NEOERR * cs_arg_parsev(CSPARSE *parse, CSARG *args, const char *fmt, va_list ap) { NEOERR *err = STATUS_OK; @@ -3287,7 +3323,7 @@ return STATUS_OK; } -static NEOERR * cs_arg_parse(CSPARSE *parse, CSARG *args, char *fmt, ...) +NEOERR * cs_arg_parse(CSPARSE *parse, CSARG *args, const char *fmt, ...) { NEOERR *err; va_list ap; @@ -3300,16 +3336,22 @@ static NEOERR * _builtin_subcount(CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { + NEOERR *err; HDF *obj; int count = 0; + CSARG val; + + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); /* default for non-vars is 0 children */ result->op_type = CS_TYPE_NUM; result->n = 0; - if (args->op_type & CS_TYPE_VAR) + if (val.op_type & CS_TYPE_VAR) { - obj = var_lookup_obj (parse, args->s); + obj = var_lookup_obj (parse, val.s); if (obj != NULL) { obj = hdf_obj_child(obj); @@ -3321,61 +3363,60 @@ } result->n = count; } + if (val.alloc) free(val.s); return STATUS_OK; } static NEOERR * _builtin_str_length(CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { - HDF *obj; + NEOERR *err; + CSARG val; + + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); /* non var/string objects have 0 length */ result->op_type = CS_TYPE_NUM; result->n = 0; - if (args->op_type & CS_TYPE_VAR) + if (val.op_type & (CS_TYPE_VAR | CS_TYPE_STRING)) { - obj = var_lookup_obj (parse, args->s); - if (obj) { - char *s = hdf_obj_value(obj); - if (s) { - result->n = strlen(s); - } - } - } - else if (args->op_type & CS_TYPE_STRING) - { - result->n = strlen(args->s); + char *s = arg_eval(parse, &val); + if (s) result->n = strlen(s); } + if (val.alloc) free(val.s); return STATUS_OK; } static NEOERR * _builtin_name(CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { + NEOERR *err; HDF *obj; + CSARG val; + + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); result->op_type = CS_TYPE_STRING; result->s = ""; - if (args->op_type & CS_TYPE_VAR) + if (val.op_type & CS_TYPE_VAR) { - obj = var_lookup_obj (parse, args->s); + obj = var_lookup_obj (parse, val.s); if (obj != NULL) - { result->s = hdf_obj_name(obj); } - else + else if (val.op_type & CS_TYPE_STRING) { - result->s = ""; - } - } - else if (args->op_type & CS_TYPE_STRING) - { - result->s = args->s; - result->alloc = args->alloc; - args->alloc = 0; + result->s = val.s; + result->alloc = val.alloc; + val.alloc = 0; } + if (val.alloc) free(val.s); return STATUS_OK; } @@ -3383,20 +3424,27 @@ static NEOERR * _builtin_first(CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { + NEOERR *err; CS_LOCAL_MAP *map; char *c; + CSARG val; + + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); /* default is "not first" */ result->op_type = CS_TYPE_NUM; result->n = 0; /* Only applies to possible local vars */ - if ((args->op_type & CS_TYPE_VAR) && !strchr(args->s, '.')) + if ((val.op_type & CS_TYPE_VAR) && !strchr(val.s, '.')) { - map = lookup_map (parse, args->s, &c); + map = lookup_map (parse, val.s, &c); if (map && map->first) result->n = 1; } + if (val.alloc) free(val.s); return STATUS_OK; } @@ -3405,17 +3453,23 @@ static NEOERR * _builtin_last(CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { + NEOERR *err; CS_LOCAL_MAP *map; char *c; + CSARG val; + + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); /* default is "not last" */ result->op_type = CS_TYPE_NUM; result->n = 0; /* Only applies to possible local vars */ - if ((args->op_type & CS_TYPE_VAR) && !strchr(args->s, '.')) + if ((val.op_type & CS_TYPE_VAR) && !strchr(val.s, '.')) { - map = lookup_map (parse, args->s, &c); + map = lookup_map (parse, val.s, &c); if (map) { if (map->last) { result->n = 1; @@ -3426,6 +3480,7 @@ } } } + if (val.alloc) free(val.s); return STATUS_OK; } @@ -3433,14 +3488,19 @@ static NEOERR * _builtin_abs (CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { + NEOERR *err; int n1 = 0; + CSARG val; - result->op_type = CS_TYPE_NUM; - result->n = 0; + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); - n1 = arg_eval_num(parse, args); + result->op_type = CS_TYPE_NUM; + n1 = arg_eval_num(parse, &val); result->n = abs(n1); + if (val.alloc) free(val.s); return STATUS_OK; } @@ -3531,29 +3591,26 @@ #ifdef ENABLE_GETTEXT static NEOERR * _builtin_gettext(CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { - HDF *obj; + NEOERR *err; + char *s; + CSARG val; + + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); result->op_type = CS_TYPE_STRING; result->s = ""; - if (args->op_type & CS_TYPE_VAR) - { - obj = var_lookup_obj (parse, args->s); - if (obj != NULL) + if (val.op_type & (CS_TYPE_VAR | CS_TYPE_STRING)) { - result->s = gettext(hdf_obj_value(obj)); - } - else + s = arg_eval(parse, &val); + if (s) { - result->s = ""; + result->s = gettext(s); } } - else if (args->op_type & CS_TYPE_STRING) - { - result->s = gettext(args->s); - result->alloc = args->alloc; - args->alloc = 0; - } + if (val.alloc) free(val.s); return STATUS_OK; } #endif @@ -3562,13 +3619,18 @@ { NEOERR *err; char *s; + CSARG val; + + memset(&val, 0, sizeof(val)); + err = eval_expr(parse, args, &val); + if (err) return nerr_pass(err); - if (args->op_type & (CS_TYPE_VAR | CS_TYPE_STRING)) + if (val.op_type & (CS_TYPE_VAR | CS_TYPE_STRING)) { result->op_type = CS_TYPE_STRING; result->n = 0; - s = arg_eval(parse, args); + s = arg_eval(parse, &val); if (s) { err = csf->str_func(s, &(result->s)); @@ -3578,12 +3640,13 @@ } else { - result->op_type = args->op_type; - result->n = args->n; - result->s = args->s; - result->alloc = args->alloc; - args->alloc = 0; + result->op_type = val.op_type; + result->n = val.n; + result->s = val.s; + result->alloc = val.alloc; + val.alloc = 0; } + if (val.alloc) free(val.s); return STATUS_OK; } @@ -3591,7 +3654,7 @@ { NEOERR *err; - err = _register_function(parse, funcname, 1, _str_func_wrapper); + err = cs_register_function(parse, funcname, 1, _str_func_wrapper); if (err) return nerr_pass(err); parse->functions->str_func = str_func; @@ -3682,7 +3745,7 @@ }; int x = 0; while (Builtins[x].name != NULL) { - err = _register_function(my_parse, Builtins[x].name, Builtins[x].nargs, + err = cs_register_function(my_parse, Builtins[x].name, Builtins[x].nargs, Builtins[x].function); if (err) { diff -Nrbu clearsilver-0.10.2/cs/cstest.c clearsilver-0.10.3/cs/cstest.c --- clearsilver-0.10.2/cs/cstest.c 2005-06-30 11:51:49.000000000 -0700 +++ clearsilver-0.10.3/cs/cstest.c 2006-03-12 15:54:15.000000000 -0800 @@ -13,6 +13,7 @@ #include #include +#include #include "util/neo_misc.h" #include "util/neo_hdf.h" #include "cs.h" @@ -23,6 +24,23 @@ return STATUS_OK; } +NEOERR *test_strfunc(const char *str, char **ret) +{ + char *s = strdup(str); + int x = 0; + + if (s == NULL) + return nerr_raise(NERR_NOMEM, "Unable to duplicate string in test_strfunc"); + + while (s[x]) { + s[x] = tolower(s[x]); + x++; + } + *ret = s; + return STATUS_OK; +} + + int main (int argc, char *argv[]) { NEOERR *err; @@ -75,6 +93,14 @@ return -1; } + /* register a test strfunc */ + err = cs_register_strfunc(parse, "test_strfunc", test_strfunc); + if (err != STATUS_OK) + { + nerr_log_error(err); + return -1; + } + err = cs_parse_file (parse, cs_file); if (err != STATUS_OK) { diff -Nrbu clearsilver-0.10.2/cs/Makefile clearsilver-0.10.3/cs/Makefile --- clearsilver-0.10.2/cs/Makefile 2005-12-02 02:34:47.000000000 -0800 +++ clearsilver-0.10.3/cs/Makefile 2006-02-01 18:20:49.000000000 -0800 @@ -28,10 +28,12 @@ CS_TESTS = test.cs test2.cs test3.cs test4.cs test5.cs test6.cs test7.cs \ test8.cs test9.cs test10.cs test11.cs test12.cs test13.cs \ - test14.cs test15.cs test16.cs test17.cs test18.cs test_var.cs \ - test_paren.cs test_chuck.cs test_trak1.cs test_iter.cs \ + test14.cs test15.cs test16.cs test17.cs test18.cs test19.cs \ + test_var.cs test_paren.cs test_chuck.cs test_trak1.cs test_iter.cs \ test_each_array.cs test_name.cs test_with.cs test_numbers.cs \ - test_splice.cs test_joo.cs test_first_last.cs test_abs_max_min.cs + test_splice.cs test_joo.cs test_first_last.cs test_abs_max_min.cs \ + test_comma.cs test_macro_set.cs test_func.cs + all: $(TARGETS) diff -Nrbu clearsilver-0.10.2/cs/test19.cs clearsilver-0.10.3/cs/test19.cs --- clearsilver-0.10.2/cs/test19.cs 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test19.cs 2006-01-04 16:36:39.000000000 -0800 @@ -0,0 +1,21 @@ + + + +a: b: + +!a || b: + +!(a || b): + + + + + Wow.Foo exists + + + + Wow.Bar exists + + +3: +2: diff -Nrbu clearsilver-0.10.2/cs/test19.cs.gold clearsilver-0.10.3/cs/test19.cs.gold --- clearsilver-0.10.2/cs/test19.cs.gold 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test19.cs.gold 2006-02-01 16:23:35.000000000 -0800 @@ -0,0 +1,40 @@ +Parsing test19.cs + + + +a: 0 b: 0 + +!a || b: 1 + +!(a || b): 1 + +a: 0 b: 1 + +!a || b: 1 + +!(a || b): 0 + + + +a: 1 b: 0 + +!a || b: 0 + +!(a || b): 0 + +a: 1 b: 1 + +!a || b: 1 + +!(a || b): 0 + + + + + Wow.Foo exists 3 + + + + +3: 3 +2: 2 diff -Nrbu clearsilver-0.10.2/cs/test_comma.cs clearsilver-0.10.3/cs/test_comma.cs --- clearsilver-0.10.2/cs/test_comma.cs 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test_comma.cs 2006-01-26 19:06:57.000000000 -0800 @@ -0,0 +1,11 @@ + +Comma tests, evalute both but pass right most as expression result + +4: + +also, "do nothing" lparen operator +4: + +2: + +3: diff -Nrbu clearsilver-0.10.2/cs/test_comma.cs.gold clearsilver-0.10.3/cs/test_comma.cs.gold --- clearsilver-0.10.2/cs/test_comma.cs.gold 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test_comma.cs.gold 2006-02-01 16:23:41.000000000 -0800 @@ -0,0 +1,12 @@ +Parsing test_comma.cs + +Comma tests, evalute both but pass right most as expression result + +4: 4 + +also, "do nothing" lparen operator +4: 4 + +2: 2 + +3: 3 diff -Nrbu clearsilver-0.10.2/cs/test_func.cs clearsilver-0.10.3/cs/test_func.cs --- clearsilver-0.10.2/cs/test_func.cs 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test_func.cs 2006-02-01 16:19:54.000000000 -0800 @@ -0,0 +1,30 @@ +testing func calls + +Testing register strfunc + + + + + + + +testing passing expressions to builtins + + + + +25: +15: + +6: + +25: + +4: +Baz: + +oba: + +first/last only run on local vars, which can't be created by expressions + + diff -Nrbu clearsilver-0.10.2/cs/test_func.cs.gold clearsilver-0.10.3/cs/test_func.cs.gold --- clearsilver-0.10.2/cs/test_func.cs.gold 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test_func.cs.gold 2006-02-01 16:23:41.000000000 -0800 @@ -0,0 +1,51 @@ +Parsing test_func.cs +testing func calls + +Testing register strfunc +worn out +fooworn out + + +2 +4 + +testing passing expressions to builtins + + 5 + + 3 + + 1 + + 1 + + 3 + + 5 + + 7 + + 9 + + 11 + + 13 + + 15 + + +25: 25 +15: 15 + +6: 6 + +25: 25 + +4: 4 +Baz: Baz + +oba: oba + +first/last only run on local vars, which can't be created by expressions + + diff -Nrbu clearsilver-0.10.2/cs/test_macro_set.cs clearsilver-0.10.3/cs/test_macro_set.cs --- clearsilver-0.10.2/cs/test_macro_set.cs 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test_macro_set.cs 2006-01-26 16:48:45.000000000 -0800 @@ -0,0 +1,22 @@ + + + + +Testing "pass by reference" to macro calls so they can "return" data + +Testing non-existant var + + + +Testing non-existant var sub var + + + +Testing non-existant sub var + + + +Testing existant var + + + diff -Nrbu clearsilver-0.10.2/cs/test_macro_set.cs.gold clearsilver-0.10.3/cs/test_macro_set.cs.gold --- clearsilver-0.10.2/cs/test_macro_set.cs.gold 1969-12-31 16:00:00.000000000 -0800 +++ clearsilver-0.10.3/cs/test_macro_set.cs.gold 2006-02-01 16:23:41.000000000 -0800 @@ -0,0 +1,29 @@ +Parsing test_macro_set.cs + + +Testing "pass by reference" to macro calls so they can "return" data + +Testing non-existant var + + + +style='width:100px;' + +Testing non-existant var sub var + + + +style='width:300px;' + +Testing non-existant sub var + + + +style='width:400px;' + +Testing existant var + + + + +style='width:200px;' Binary files clearsilver-0.10.2/java-jni/libclearsilver-jni.so and clearsilver-0.10.3/java-jni/libclearsilver-jni.so differ diff -Nrbu clearsilver-0.10.2/Makefile clearsilver-0.10.3/Makefile --- clearsilver-0.10.2/Makefile 2005-12-02 02:33:25.000000000 -0800 +++ clearsilver-0.10.3/Makefile 2006-03-12 15:42:06.000000000 -0800 @@ -108,8 +108,8 @@ mkdir -p $$mdir; \ done -CS_DISTDIR = clearsilver-0.10.2 -CS_LABEL = CLEARSILVER-0_10_2 +CS_DISTDIR = clearsilver-0.10.3 +CS_LABEL = CLEARSILVER-0_10_3 CS_FILES = README README.python INSTALL LICENSE CS_LICENSE rules.mk.in Makefile acconfig.h autogen.sh config.guess config.sub configure.in cs_config.h.in mkinstalldirs install-sh ClearSilver.h CS_DIRS = util cs cgi python scripts mod_ecs imd java-jni perl ruby dso csharp ports contrib m4 diff -Nrbu clearsilver-0.10.2/mod_ecs/mod_ecs.c clearsilver-0.10.3/mod_ecs/mod_ecs.c --- clearsilver-0.10.2/mod_ecs/mod_ecs.c 2005-07-02 17:17:45.000000000 -0700 +++ clearsilver-0.10.3/mod_ecs/mod_ecs.c 2006-03-12 16:08:07.000000000 -0800 @@ -104,7 +104,7 @@ request_rec *r; } WRAPPER_DATA; -static int buf_getline (char *idata, int ilen, char *odata, int olen, int *nonl) +static int buf_getline (const char *idata, int ilen, char *odata, int olen, int *nonl) { char *eol; int len; @@ -143,7 +143,7 @@ return ret; } -static int header_write (HEADER_BUF *hbuf, char *data, int dlen) +static int header_write (HEADER_BUF *hbuf, const char *data, int dlen) { char buf[1024]; int done, len; diff -Nrbu clearsilver-0.10.2/ports/rpm/clearsilver.spec clearsilver-0.10.3/ports/rpm/clearsilver.spec --- clearsilver-0.10.2/ports/rpm/clearsilver.spec 2005-10-21 16:03:41.000000000 -0700 +++ clearsilver-0.10.3/ports/rpm/clearsilver.spec 2006-03-12 15:43:17.000000000 -0800 @@ -53,11 +53,11 @@ Summary: Neotonic ClearSilver Name: clearsilver -Version: 0.10.2 +Version: 0.10.3 Release: 1 Copyright: Open Source - Neotonic ClearSilver License (Apache 1.1 based) Group: Development/Libraries -Source: http://www.clearsilver.net/downloads/clearsilver-0.10.2.tar.gz +Source: http://www.clearsilver.net/downloads/clearsilver-0.10.3.tar.gz URL: http://www.clearsilver.net/ Vendor: Neotonic Software Corporation, Inc. Packager: Brandon Long diff -Nrbu clearsilver-0.10.2/python/setup.py clearsilver-0.10.3/python/setup.py --- clearsilver-0.10.2/python/setup.py 2005-10-21 16:19:30.000000000 -0700 +++ clearsilver-0.10.3/python/setup.py 2006-03-12 16:15:48.000000000 -0800 @@ -1,9 +1,19 @@ import os, string, re, sys -from distutils.core import setup, Extension + +# Check to see if the Egg system is installed (ie, setuptools) +# See http://peak.telecommunity.com/DevCenter/PythonEggs +USE_EGGS=1 +try: + from setuptools import setup +except ImportError: + from distutils.core import setup + USE_EGGS=0 + +from distutils.core import Extension from distutils import sysconfig -VERSION = "0.10.2" +VERSION = "0.10.3" INC_DIRS = ["../"] LIBRARIES = ["neo_cgi", "neo_cs", "neo_utl"] LIB_DIRS = ["../libs"] @@ -95,17 +105,23 @@ except AttributeError: pass -setup(name="clearsilver", - version=VERSION, - description="Python ClearSilver Wrapper", - author="Brandon Long", - author_email="blong@fiction.net", - url="http://www.clearsilver.net/", - ext_modules=[Extension( +setup_args = { + 'name': "clearsilver", + 'version': VERSION, + 'description': "Python ClearSilver Wrapper", + 'author': "Brandon Long", + 'author_email': "blong@fiction.net", + 'url': "http://www.clearsilver.net/", + 'ext_modules': [Extension( name="neo_cgi", sources=["neo_cgi.c", "neo_cs.c", "neo_util.c"], include_dirs=INC_DIRS, library_dirs=LIB_DIRS, libraries=LIBRARIES, )] - ) + } + +if USE_EGGS: + setup_args['zip_safe'] = 0 + +apply(setup, [], setup_args) diff -Nrbu clearsilver-0.10.2/util/neo_date.c clearsilver-0.10.3/util/neo_date.c --- clearsilver-0.10.2/util/neo_date.c 2005-11-30 20:04:27.000000000 -0800 +++ clearsilver-0.10.3/util/neo_date.c 2006-03-12 15:35:17.000000000 -0800 @@ -32,20 +32,20 @@ * than this */ static char TzBuf[_POSIX_PATH_MAX + 4]; -static int time_set_tz (const char *timezone) +static int time_set_tz (const char *mytimezone) { - snprintf (TzBuf, sizeof(TzBuf), "TZ=%s", timezone); + snprintf (TzBuf, sizeof(TzBuf), "TZ=%s", mytimezone); putenv(TzBuf); tzset(); return 0; } -void neo_time_expand (const time_t tt, const char *timezone, struct tm *ttm) +void neo_time_expand (const time_t tt, const char *mytimezone, struct tm *ttm) { const char *cur_tz = getenv("TZ"); int change_back = 0; - if (cur_tz == NULL || strcmp(timezone, cur_tz)) { - time_set_tz (timezone); + if (cur_tz == NULL || strcmp(mytimezone, cur_tz)) { + time_set_tz (mytimezone); change_back = 1; } localtime_r (&tt, ttm); @@ -54,15 +54,15 @@ } } -time_t neo_time_compact (struct tm *ttm, const char *timezone) +time_t neo_time_compact (struct tm *ttm, const char *mytimezone) { time_t r; int save_isdst = ttm->tm_isdst; const char *cur_tz = getenv("TZ"); int change_back = 0; - if (cur_tz == NULL || strcmp(timezone, cur_tz)) { - time_set_tz (timezone); + if (cur_tz == NULL || strcmp(mytimezone, cur_tz)) { + time_set_tz (mytimezone); change_back = 1; } ttm->tm_isdst = -1; @@ -83,7 +83,11 @@ return ttm->tm_gmtoff; #elif defined(HAVE_TZNAME) long tz; +#ifndef __CYGWIN__ tz = - timezone; +#else + tz = - _timezone; +#endif if(ttm->tm_isdst) tz += 3600; return tz; diff -Nrbu clearsilver-0.10.2/util/neo_err.c clearsilver-0.10.3/util/neo_err.c --- clearsilver-0.10.2/util/neo_err.c 2005-06-30 11:51:59.000000000 -0700 +++ clearsilver-0.10.3/util/neo_err.c 2006-03-07 12:43:17.000000000 -0800 @@ -20,6 +20,7 @@ #include "neo_misc.h" #include "neo_err.h" #include "ulist.h" +#include "ulocks.h" int NERR_PASS = -1; int NERR_ASSERT = 0; @@ -37,6 +38,10 @@ static NEOERR *FreeList = NULL; static ULIST *Errors = NULL; static int Inited = 0; +#ifdef HAVE_PTHREADS +/* In multi-threaded environments, we have to init thread safely */ +static pthread_mutex_t InitLock = PTHREAD_MUTEX_INITIALIZER; +#endif /* Set this to 1 to enable non-thread safe re-use of NEOERR data * structures. This was a premature performance optimization that isn't @@ -420,6 +425,14 @@ if (Inited == 0) { +#ifdef HAVE_PTHREADS + /* In threaded environments, we have to mutex lock to do this init, but + * we don't want to use a mutex every time to check that it was Inited. + * So, we only lock if our first test of Inited was false */ + err = mLock(&InitLock); + if (err != STATUS_OK) return nerr_pass(err); + if (Inited == 0) { +#endif err = uListInit (&Errors, 10, 0); if (err != STATUS_OK) return nerr_pass(err); @@ -449,6 +462,11 @@ if (err != STATUS_OK) return nerr_pass(err); Inited = 1; +#ifdef HAVE_PTHREADS + } + err = mUnlock(&InitLock); + if (err != STATUS_OK) return nerr_pass(err); +#endif } return STATUS_OK; } diff -Nrbu clearsilver-0.10.2/util/neo_err.h clearsilver-0.10.3/util/neo_err.h --- clearsilver-0.10.2/util/neo_err.h 2005-11-21 18:51:19.000000000 -0800 +++ clearsilver-0.10.3/util/neo_err.h 2005-12-15 14:17:36.000000000 -0800 @@ -13,7 +13,7 @@ #define __NEO_ERR_H_ 1 /* For compilers (well, cpp actually) which don't define __PRETTY_FUNCTION__ */ -#ifndef __PRETTY_FUNCTION__ +#ifndef __GNUC__ #define __PRETTY_FUNCTION__ "unknown_function" #endif