diff -Nru clearsilver-0.8.1/Makefile clearsilver-0.9.0/Makefile --- clearsilver-0.8.1/Makefile Thu Apr 3 17:39:49 2003 +++ clearsilver-0.9.0/Makefile Mon Apr 14 17:15:51 2003 @@ -31,7 +31,22 @@ if test -f $$mdir/Makefile.PL -a ! -f $$mdir/Makefile; then \ cd $$mdir; $(PERL) Makefile.PL; cd ..; \ fi; \ - $(MAKE) -C $$mdir; \ + $(MAKE) -C $$mdir PREFIX=$(prefix); \ + fi; \ + done + +install: all + ./mkinstalldirs $(DESTDIR)$(cs_includedir) + ./mkinstalldirs $(DESTDIR)$(bindir) + ./mkinstalldirs $(DESTDIR)$(libdir) + $(INSTALL) -m 644 ClearSilver.h $(DESTDIR)$(cs_includedir)/ + $(INSTALL) -m 644 cs_config.h $(DESTDIR)$(cs_includedir)/ + @for mdir in $(SUBDIRS); do \ + if test -d $$mdir; then \ + if test -f $$mdir/Makefile.PL -a ! -f $$mdir/Makefile; then \ + cd $$mdir; $(PERL) Makefile.PL; cd ..; \ + fi; \ + $(MAKE) -C $$mdir PREFIX=$(prefix) install; \ fi; \ done diff -Nru clearsilver-0.8.1/acconfig.h clearsilver-0.9.0/acconfig.h --- clearsilver-0.8.1/acconfig.h Wed Apr 2 15:07:26 2003 +++ clearsilver-0.9.0/acconfig.h Mon Apr 14 16:05:07 2003 @@ -50,6 +50,12 @@ /* Does your system have pthreads? */ #undef HAVE_PTHREADS +/* Does your system have lockf ? */ +#undef HAVE_LOCKF + +/* Does your system have Berkeley DB v2 ? */ +#undef HAVE_DB2 + @BOTTOM@ #endif /* __CS_CONFIG_H_ */ diff -Nru clearsilver-0.8.1/cgi/Makefile clearsilver-0.9.0/cgi/Makefile --- clearsilver-0.8.1/cgi/Makefile Wed Apr 2 16:26:48 2003 +++ clearsilver-0.9.0/cgi/Makefile Mon Apr 14 17:13:40 2003 @@ -31,6 +31,15 @@ $(STATIC_CSO): $(STATIC_OBJ) $(DEP_LIBS) $(LDSHARED) -o $@ $(STATIC_OBJ) $(LIBS) +install: all + $(NEOTONIC_ROOT)mkinstalldirs $(DESTDIR)$(cs_includedir)/cgi + $(INSTALL) -m 644 cgi.h $(DESTDIR)$(cs_includedir)/cgi + $(INSTALL) -m 644 cgiwrap.h $(DESTDIR)$(cs_includedir)/cgi + $(INSTALL) -m 644 date.h $(DESTDIR)$(cs_includedir)/cgi + $(INSTALL) -m 644 html.h $(DESTDIR)$(cs_includedir)/cgi + $(INSTALL) -m 644 $(CGI_LIB) $(DESTDIR)$(libdir) + $(INSTALL) $(STATIC_EXE) $(DESTDIR)$(bindir) + clean: $(RM) *.o diff -Nru clearsilver-0.8.1/cgi/cgi.c clearsilver-0.9.0/cgi/cgi.c --- clearsilver-0.8.1/cgi/cgi.c Wed Apr 2 15:07:27 2003 +++ clearsilver-0.9.0/cgi/cgi.c Sun Jun 29 22:32:58 2003 @@ -266,7 +266,7 @@ while (buf[l]) { - if (buf[l] == '/' || buf[l] == '&' || buf[l] == '"' || buf[l] == '\'' || + if (buf[l] == '/' || buf[l] == '"' || buf[l] == '\'' || buf[l] == '\\' || buf[l] == '>' || buf[l] == '<' || buf[l] < 32) { nl += 3; @@ -283,7 +283,7 @@ nl = 0; l = 0; while (buf[l]) { - if (buf[l] == '/' || buf[l] == '&' || buf[l] == '"' || buf[l] == '\'' || + if (buf[l] == '/' || buf[l] == '"' || buf[l] == '\'' || buf[l] == '\\' || buf[l] == '>' || buf[l] == '<' || buf[l] < 32) { s[nl++] = '\\'; @@ -314,7 +314,7 @@ while (buf[l]) { if (buf[l] == '/' || buf[l] == '+' || buf[l] == '=' || buf[l] == '&' || - buf[l] == '"' || buf[l] == '%' || buf[l] == '?' || + buf[l] == '"' || buf[l] == '%' || buf[l] == '?' || buf[l] == '#' || buf[l] < 32 || buf[l] > 122) { nl += 2; @@ -353,7 +353,7 @@ else { if (buf[l] == '/' || buf[l] == '+' || buf[l] == '=' || buf[l] == '&' || - buf[l] == '"' || buf[l] == '%' || buf[l] == '?' || + buf[l] == '"' || buf[l] == '%' || buf[l] == '?' || buf[l] == '#' || buf[l] < 32 || buf[l] > 122) { match = 1; @@ -407,7 +407,7 @@ k = strtok_r(query, "=", &l); while (k) { - if (*l == '&') + if (l != NULL && *l == '&') { l++; v = ""; @@ -418,7 +418,7 @@ } if (v == NULL) v = ""; snprintf(buf, sizeof(buf), "Query.%s", cgi_url_unescape(k)); - if (!(cgi->ignore_empty_form_vars && (v == NULL || *v == '\0'))) + if (!(cgi->ignore_empty_form_vars && (*v == '\0'))) { cgi_url_unescape(v); obj = hdf_get_obj (cgi->hdf, buf); @@ -977,7 +977,7 @@ o += l; i += l; } - else if (!strncasecmp(str->buf + i, "pre", 8)) + else if (!strncasecmp(str->buf + i, "pre", 3)) { ch = str->buf + i; do @@ -1069,7 +1069,7 @@ e = hdf_get_value (cgi->hdf, "Config.DebugPassword", NULL); if (s && e && !strcmp(s, e)) do_debug = 1; do_timefooter = hdf_get_int_value (cgi->hdf, "Config.TimeFooter", 1); - do_ws_strip = hdf_get_int_value (cgi->hdf, "Config.WhiteSpaceStrip", 0); + do_ws_strip = hdf_get_int_value (cgi->hdf, "Config.WhiteSpaceStrip", 1); dis = ne_timef(); if (err != STATUS_OK) return nerr_pass (err); diff -Nru clearsilver-0.8.1/cgi/static.c clearsilver-0.9.0/cgi/static.c --- clearsilver-0.8.1/cgi/static.c Wed Apr 2 15:07:28 2003 +++ clearsilver-0.9.0/cgi/static.c Mon Apr 14 16:05:09 2003 @@ -8,17 +8,13 @@ * Copyright (C) 2001 by Brandon Long */ -#include "cs_config.h" +#include "ClearSilver.h" #include #include #include #include #include -#include "util/neo_misc.h" -#include "util/neo_err.h" -#include "cgi/cgi.h" -#include "cgi/cgiwrap.h" int main (int argc, char **argv, char **envp) { diff -Nru clearsilver-0.8.1/configure.in clearsilver-0.9.0/configure.in --- clearsilver-0.8.1/configure.in Thu Apr 3 17:44:12 2003 +++ clearsilver-0.9.0/configure.in Tue Jun 17 14:20:40 2003 @@ -46,21 +46,24 @@ dnl Checks for libraries. EXTRA_UTL_OBJS= +EXTRA_UTL_SRC= cs_cv_wdb=no AC_SEARCH_LIBS(db_open, db db2, [cs_cv_wdb=yes]) if test $cs_cv_wdb = yes; then - EXTRA_UTL_OBJS="$EXTRA_UTL_OBJS wdb.o" + AC_DEFINE(HAVE_DB2) + EXTRA_UTL_SRC="$EXTRA_UTL_SRC wdb.c" fi dnl Check for locks AC_CHECK_FUNC(lockf, [ - EXTRA_UTL_OBJS="$EXTRA_UTL_OBJS ulocks.o rcfs.o" + AC_DEFINE(HAVE_LOCKF) + EXTRA_UTL_SRC="$EXTRA_UTL_SRC ulocks.c rcfs.c" cs_cv_pthread=no AC_CHECK_HEADER(pthread.h, [cs_cv_pthread=yes]) if test $cs_cv_pthread = yes; then AC_DEFINE(HAVE_PTHREADS) - EXTRA_UTL_OBJS="$EXTRA_UTL_OBJS skiplist.o dict.o" + EXTRA_UTL_SRC="$EXTRA_UTL_SRC skiplist.c dict.c" fi ]) @@ -69,7 +72,7 @@ CPPFLAGS="$CPPFLAGS -D__WINDOWS_GCC__" USE_MINGW32="USE_MINGW32 = 1" else - EXTRA_UTL_OBJS="$EXTRA_UTL_OBJS filter.o neo_net.o neo_server.o" + EXTRA_UTL_SRC="$EXTRA_UTL_SRC filter.c neo_net.c neo_server.c" fi dnl Check for snprintf and vsnprintf @@ -96,7 +99,7 @@ AC_CHECK_FUNC(regexec, [AC_DEFINE(HAVE_REGEX)], [cs_cv_regex=no]) if test $cs_cv_regex = no; then CPPFLAGS="$CPPFLAGS -I\$(NEOTONIC_ROOT)/util/regex" - EXTRA_UTL_OBJS="$EXTRA_UTL_OBJS regex/regex.o" + EXTRA_UTL_SRC="$EXTRA_UTL_SRC regex/regex.c" fi cs_cv_compression=yes @@ -195,6 +198,7 @@ if test -f $path/include/python$vers/Python.h; then python_inc=$path/include/python$vers python_lib="-L$path/lib/python$vers/config -lpython$vers" + python_site=$path/lib/python$vers/site-packages break 2 fi dnl This is currently special cased mostly for Windows @@ -202,6 +206,7 @@ if test -f $path/python$vers/include/Python.h; then python_inc=$path/python$vers/include python_lib="-L$path/python$vers/libs -lpython$vers" + python_site=$path/python$vers/lib/site-packages break 2 fi done @@ -211,10 +216,12 @@ AC_MSG_RESULT(not found) PYTHON_INC= PYTHON_LIB= + PYTHON_SITE= else AC_MSG_RESULT(found $python_inc) PYTHON_INC="-I$python_inc" PYTHON_LIB=$python_lib + PYTHON_SITE=$python_site BUILD_WRAPPERS="$BUILD_WRAPPERS python" fi fi @@ -255,6 +262,39 @@ fi fi +dnl Check for Ruby binary +cs_cv_ruby=yes +AC_ARG_ENABLE(ruby, [ --disable-ruby Disables building of ruby module], + [if test $enableval = no; then + cs_cv_ruby=no; + AC_MSG_RESULT(Disabling ruby module) + fi]) +AC_ARG_WITH(ruby, [ --with-ruby=path Set location of Ruby binary], [cs_cv_ruby_path="$withval"], [cs_cv_ruby_path=no]) + +if test $cs_cv_ruby = yes; then + AC_MSG_CHECKING(for ruby) + ruby_path=no + ruby_search_path="/neo/opt /usr/local /usr" + if test $cs_cv_ruby_path != "no" -a -x $cs_cv_ruby_path; then + ruby_path=$cs_cv_ruby_path + else + for path in $ruby_search_path; do + if test -x $path/bin/ruby; then + ruby_path=$path/bin/ruby + break + fi + done + fi + if test "x$ruby_path" = "xno"; then + AC_MSG_RESULT(not found) + RUBY= + else + AC_MSG_RESULT(found $ruby_path) + RUBY="$ruby_path" + BUILD_WRAPPERS="$BUILD_WRAPPERS ruby" + fi +fi + dnl Check for Java library/includes cs_cv_java=yes AC_ARG_ENABLE(java, [ --disable-java Disables building of java module], @@ -309,10 +349,13 @@ AC_SUBST(USE_MINGW32) AC_SUBST(APXS_PATH) AC_SUBST(PERL) +AC_SUBST(RUBY) AC_SUBST(BUILD_WRAPPERS) AC_SUBST(JAVA_PATH) AC_SUBST(PYTHON_INC) AC_SUBST(PYTHON_LIB) +AC_SUBST(PYTHON_SITE) +AC_SUBST(EXTRA_UTL_SRC) AC_SUBST(EXTRA_UTL_OBJS) AC_OUTPUT(rules.mk) diff -Nru clearsilver-0.8.1/cs/Makefile clearsilver-0.9.0/cs/Makefile --- clearsilver-0.8.1/cs/Makefile Wed Apr 2 19:03:02 2003 +++ clearsilver-0.9.0/cs/Makefile Wed Jul 2 17:40:06 2003 @@ -14,6 +14,10 @@ CSTEST_SRC = cstest.c CSTEST_OBJ = $(CSTEST_SRC:%.c=%.o) +CSR_EXE = cs +CSR_SRC = cs.c +CSR_OBJ = $(CSR_SRC:%.c=%.o) + CSDUMP_EXE = csdump CSDUMP_SRC = csdump.c CSDUMP_OBJ = $(CSDUMP_SRC:%.c=%.o) @@ -21,9 +25,9 @@ CFLAGS += -I$(NEOTONIC_ROOT) LIBS += -L$(LIB_DIR) -lneo_cs -lneo_utl # -lefence -TARGETS = $(CS_LIB) $(CSTEST_EXE) test +TARGETS = $(CS_LIB) $(CSTEST_EXE) $(CSR_EXE) test -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 +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 test_each_array.cs test_name.cs test_with.cs test_numbers.cs all: $(TARGETS) @@ -33,6 +37,9 @@ $(CSTEST_EXE): $(CSTEST_OBJ) $(CS_LIB) $(LD) $@ $(CSTEST_OBJ) $(LIBS) # -lefence +$(CSR_EXE): $(CSR_OBJ) $(CS_LIB) + $(LD) $@ $(CSR_OBJ) $(LIBS) # -lefence + $(CSDUMP_EXE): $(CSDUMP_OBJ) $(CS_LIB) $(LD) $@ $(CSDUMP_OBJ) $(LIBS) @@ -41,24 +48,42 @@ @for test in $(CS_TESTS); do \ rm -f $$test.gold; \ ./cstest test.hdf $$test > $$test.gold; \ - done + done; \ + ./cstest test_tag.hdf test_tag.cs > test_tag.cs.gold @echo "Generated Gold Files" test: $(CSTEST_EXE) $(CS_TESTS) @echo "Running cs regression tests" - @for test in $(CS_TESTS); do \ + @failed=0; \ + for test in $(CS_TESTS); do \ rm -f $$test.out; \ - ./cstest test.hdf $$test > $$test.out; \ + ./cstest test.hdf $$test > $$test.out 2>&1; \ diff --brief $$test.out $$test.gold; \ return_code=$$?; \ if [ $$return_code -ne 0 ]; then \ - echo "Failed Regression Test: $$test.out"; \ - exit 1; \ + echo "Failed Regression Test: $$test"; \ + failed=1; \ fi; \ - done + done; \ + rm -f test_tag.cs.out; \ + ./cstest test_tag.hdf test_tag.cs> test_tag.cs.out 2>&1; \ + diff --brief test_tag.cs.out test_tag.cs.gold; \ + return_code=$$?; \ + if [ $$return_code -ne 0 ]; then \ + echo "Failed Regression Test: test_tag.cs"; \ + failed=1; \ + fi; \ + if [ $$failed -eq 1 ]; then \ + exit 1; \ + fi; @touch test @echo "Passed" +install: all + $(NEOTONIC_ROOT)mkinstalldirs $(DESTDIR)$(cs_includedir)/cs + $(INSTALL) -m 644 cs.h $(DESTDIR)$(cs_includedir)/cs + $(INSTALL) -m 644 $(CS_LIB) $(DESTDIR)$(libdir) + $(INSTALL) $(CSTEST_EXE) $(DESTDIR)$(bindir) clean: $(RM) core *.o diff -Nru clearsilver-0.8.1/cs/cs.c clearsilver-0.9.0/cs/cs.c --- clearsilver-0.8.1/cs/cs.c Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/cs.c Tue Jun 17 14:25:09 2003 @@ -0,0 +1,105 @@ +/* + * Neotonic ClearSilver Templating System + * + * This code is made available under the terms of the + * Neotonic ClearSilver License. + * http://www.neotonic.com/clearsilver/license.hdf + * + * Copyright (C) 2001 by Brandon Long + */ + +#include +#include +#include + +#include "cs.h" +#include "util/neo_misc.h" +#include "util/neo_hdf.h" + +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; + char c; + + extern char *optarg; + + err = hdf_init(&hdf); + if (err != STATUS_OK) + { + nerr_log_error(err); + return -1; + } + + err = cs_init (&parse, hdf); + if (err != STATUS_OK) { + nerr_log_error(err); + return -1; + } + + while ((c = getopt(argc, argv, "Hvh:c:")) != EOF ) + + switch (c) { + case 'h': + hdf_file=optarg; + err = hdf_read_file(hdf, hdf_file); + if (err != STATUS_OK) { + nerr_log_error(err); + return -1; + } + break; + case 'c': + cs_file=optarg; + if ( verbose ) + printf ("Parsing %s\n", cs_file); + + err = cs_parse_file (parse, cs_file); + if (err != STATUS_OK) { + err = nerr_pass(err); + nerr_log_error(err); + return -1; + } + break; + case 'v': + verbose=1; + break; + case 'H': + fprintf(stderr, "Usage: %s [-v] [-h ] [-c ]\n", argv[0]); + fprintf(stderr, " -h load hdf file file.hdf (multiple allowed)\n"); + fprintf(stderr, " -c load cs file file.cs (multiple allowed)\n"); + fprintf(stderr, " -v verbose output\n"); + return -1; + break; + } + + + 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); + } + + return 0; +} diff -Nru clearsilver-0.8.1/cs/cs.h clearsilver-0.9.0/cs/cs.h --- clearsilver-0.8.1/cs/cs.h Wed Apr 2 15:07:29 2003 +++ clearsilver-0.9.0/cs/cs.h Wed Jun 25 20:11:36 2003 @@ -176,6 +176,9 @@ int in_file; /* Indicates if current context is a file */ int offset; + char *tag; /* Usually cs, but can be set via HDF Config.TagStart */ + int taglen; + ULIST *stack; ULIST *alloc; CSTREE *tree; diff -Nru clearsilver-0.8.1/cs/csparse.c clearsilver-0.9.0/cs/csparse.c --- clearsilver-0.8.1/cs/csparse.c Wed Apr 2 15:07:29 2003 +++ clearsilver-0.9.0/cs/csparse.c Wed Jul 2 18:04:16 2003 @@ -39,17 +39,18 @@ ST_IF = 1<<1, ST_ELSE = 1<<2, ST_EACH = 1<<3, - ST_POP = 1<<4, - ST_DEF = 1<<5, - ST_LOOP = 1<<6, - ST_ALT = 1<<7, + ST_WITH = 1<<4, + ST_POP = 1<<5, + ST_DEF = 1<<6, + ST_LOOP = 1<<7, + ST_ALT = 1<<8, } CS_STATE; -#define ST_ANYWHERE (ST_EACH | ST_ELSE | ST_IF | ST_GLOBAL | ST_DEF | ST_LOOP | ST_ALT) +#define ST_ANYWHERE (ST_EACH | ST_WITH | ST_ELSE | ST_IF | ST_GLOBAL | ST_DEF | ST_LOOP | ST_ALT) typedef struct _stack_entry { - int state; + CS_STATE state; CSTREE *tree; CSTREE *next_tree; int num_local; @@ -70,8 +71,9 @@ static NEOERR *else_parse (CSPARSE *parse, int cmd, char *arg); static NEOERR *elif_parse (CSPARSE *parse, int cmd, char *arg); static NEOERR *endif_parse (CSPARSE *parse, int cmd, char *arg); -static NEOERR *each_parse (CSPARSE *parse, int cmd, char *arg); +static NEOERR *each_with_parse (CSPARSE *parse, int cmd, char *arg); static NEOERR *each_eval (CSPARSE *parse, CSTREE *node, CSTREE **next); +static NEOERR *with_eval (CSPARSE *parse, CSTREE *node, CSTREE **next); static NEOERR *end_parse (CSPARSE *parse, int cmd, char *arg); static NEOERR *include_parse (CSPARSE *parse, int cmd, char *arg); static NEOERR *linclude_parse (CSPARSE *parse, int cmd, char *arg); @@ -93,8 +95,8 @@ { char *cmd; int cmdlen; - int allowed_state; - int next_state; + CS_STATE allowed_state; + CS_STATE next_state; NEOERR* (*parse_handler)(CSPARSE *parse, int cmd, char *arg); NEOERR* (*eval_handler)(CSPARSE *parse, CSTREE *node, CSTREE **next); int has_arg; @@ -122,9 +124,13 @@ {"/if", sizeof("/if")-1, ST_IF | ST_ELSE, ST_POP, endif_parse, skip_eval, 0}, {"each", sizeof("each")-1, ST_ANYWHERE, ST_EACH, - each_parse, each_eval, 1}, + each_with_parse, each_eval, 1}, {"/each", sizeof("/each")-1, ST_EACH, ST_POP, end_parse, skip_eval, 0}, + {"with", sizeof("each")-1, ST_ANYWHERE, ST_WITH, + each_with_parse, with_eval, 1}, + {"/with", sizeof("/with")-1, ST_WITH, ST_POP, + end_parse, skip_eval, 0}, {"include", sizeof("include")-1, ST_ANYWHERE, ST_SAME, include_parse, skip_eval, 1}, {"linclude", sizeof("linclude")-1, ST_ANYWHERE, ST_SAME, @@ -228,18 +234,23 @@ *csf = NULL; } -static int find_open_delim (char *buf, int x, int len) +static int find_open_delim (CSPARSE *parse, char *buf, int x, int len) { char *p; + int ws_index = 2+parse->taglen; while (x < len) { p = strchr (&(buf[x]), '<'); if (p == NULL) return -1; + if (p[1] == '?' && !strncasecmp(&p[2], parse->tag, parse->taglen) && + (p[ws_index] == ' ' || p[ws_index] == '\n' || p[ws_index] == '\t' || p[ws_index] == '\r')) + /* if (p[1] && p[1] == '?' && p[2] && (p[2] == 'C' || p[2] == 'c') && p[3] && (p[3] == 'S' || p[3] == 's') && p[4] && (p[4] == ' ' || p[4] == '\n' || p[4] == '\t' || p[4] == '\r')) + */ { return p - buf; } @@ -362,6 +373,8 @@ return "ELSE"; else if (state & ST_EACH) return "EACH"; + else if (state & ST_WITH) + return "WITH"; else if (state & ST_DEF) return "DEF"; else if (state & ST_LOOP) @@ -400,7 +413,7 @@ while (!done) { /* Stage 1: Find offset, ibuf_len); + i = find_open_delim (parse, ibuf, parse->offset, ibuf_len); if (i >= 0) { ibuf[i] = '\0'; @@ -408,7 +421,7 @@ /* ne_warn ("literal -> %d-%d", parse->offset, i); */ err = (*(Commands[0].parse_handler))(parse, 0, &(ibuf[parse->offset])); /* skip delim */ - token = &(ibuf[i+5]); + token = &(ibuf[i+3+parse->taglen]); while (*token && isspace(*token)) token++; p = strstr (token, "?>"); @@ -718,7 +731,8 @@ int ntokens = 0; int x; BOOL found; - char *p; + BOOL last_is_op = 1; + char *p, *p2; char *expr = arg; while (arg && *arg != '\0') @@ -727,20 +741,30 @@ if (*arg == '\0') break; x = 0; found = FALSE; - while ((found == FALSE) && SimpleTokens[x].token) - { - if (((SimpleTokens[x].two_chars == TRUE) && - (*arg == SimpleTokens[x].token[0]) && - (*(arg + 1) == SimpleTokens[x].token[1])) || - ((SimpleTokens[x].two_chars == FALSE) && - (*arg == SimpleTokens[x].token[0]))) - { - tokens[ntokens++].type = SimpleTokens[x].type; - found = TRUE; - arg++; - if (SimpleTokens[x].two_chars) arg++; - } - x++; + + /* If we already so an operator, and this is a +/-, assume its + * a number */ + if (!(last_is_op && (*arg == '+' || *arg == '-'))) + { + while ((found == FALSE) && SimpleTokens[x].token) + { + if (((SimpleTokens[x].two_chars == TRUE) && + (*arg == SimpleTokens[x].token[0]) && + (*(arg + 1) == SimpleTokens[x].token[1])) || + ((SimpleTokens[x].two_chars == FALSE) && + (*arg == SimpleTokens[x].token[0]))) + { + tokens[ntokens++].type = SimpleTokens[x].type; + found = TRUE; + arg++; + if (SimpleTokens[x].two_chars) arg++; + } + x++; + } + /* Another special case: RPAREN and RBRACKET can have another op + * after it */ + if (found && !(tokens[ntokens-1].type == CS_OP_RPAREN || tokens[ntokens-1].type == CS_OP_RBRACKET)) + last_is_op = 1; } if (found == FALSE) @@ -756,7 +780,7 @@ tokens[ntokens].type = CS_TYPE_VAR_NUM; p = strpbrk(arg, "\"?<>=!#-+|&,)*/%[]( \t\r\n"); if (p == arg) - return nerr_raise (NERR_PARSE, "%s Missing arg after #: %s", + return nerr_raise (NERR_PARSE, "%s Missing varname/number after #: %s", find_context(parse, -1, tmp, sizeof(tmp)), arg); } if (p == NULL) @@ -779,14 +803,27 @@ ntokens++; arg = p + 1; } - else + else if (*arg == '\'') + { + arg++; + tokens[ntokens].type = CS_TYPE_STRING; + tokens[ntokens].value = arg; + p = strchr (arg, '\''); + if (p == NULL) + return nerr_raise (NERR_PARSE, "%s Missing end of string: %s", + find_context(parse, -1, tmp, sizeof(tmp)), arg); + tokens[ntokens].len = p - arg; + ntokens++; + arg = p + 1; + } + else if (*arg == '$') { + arg++; tokens[ntokens].type = CS_TYPE_VAR; tokens[ntokens].value = arg; p = strpbrk(arg, "\"?<>=!#-+|&,)*/%[]( \t\r\n"); if (p == arg) - return nerr_raise (NERR_PARSE, - "%s Var arg specified with no varname: %s", + return nerr_raise (NERR_PARSE, "%s Missing varname after $: %s", find_context(parse, -1, tmp, sizeof(tmp)), arg); if (p == NULL) tokens[ntokens].len = strlen(arg); @@ -795,10 +832,41 @@ ntokens++; arg = p; } + else + { + tokens[ntokens].type = CS_TYPE_VAR; + tokens[ntokens].value = arg; + /* Special case for Dave: If this is entirely a number, treat it + * as one */ + strtol(arg, &p2, 0); + p = strpbrk(arg, "\"?<>=!#-+|&,)*/%[]( \t\r\n"); + /* This is complicated because +/- is valid in a number, but not + * in a varname */ + if (p2 != arg && (p <= p2 || (p == NULL && *p2 == '\0'))) + { + tokens[ntokens].type = CS_TYPE_NUM; + tokens[ntokens].len = p2 - arg; + arg = p2; + } + else + { + if (p == arg) + return nerr_raise (NERR_PARSE, + "%s Var arg specified with no varname: %s", + find_context(parse, -1, tmp, sizeof(tmp)), arg); + if (p == NULL) + tokens[ntokens].len = strlen(arg); + else + tokens[ntokens].len = p - arg; + arg = p; + } + ntokens++; + } + last_is_op = 0; } if (ntokens >= MAX_TOKENS) return nerr_raise (NERR_PARSE, - "%s Expression exceeds maximum number of tokens of %d: %s", + "%s Expression exceeds maximum number of tokens of %d: %s", find_context(parse, -1, tmp, sizeof(tmp)), MAX_TOKENS, expr); } *used_tokens = ntokens; @@ -865,12 +933,12 @@ { save = tokens[i].value[tokens[i].len]; tokens[i].value[tokens[i].len] = '\0'; - t = snprintf(p, buflen, " %d:%s:'%s'", i, expand_token_type(tokens[i].type, 0), tokens[i].value); + t = snprintf(p, buflen, "%s%d:%s:'%s'", i ? " ":"", i, expand_token_type(tokens[i].type, 0), tokens[i].value); tokens[i].value[tokens[i].len] = save; } else { - t = snprintf(p, buflen, " %d:%s", i, expand_token_type(tokens[i].type, 0)); + t = snprintf(p, buflen, "%s%d:%s", i ? " ":"", i, expand_token_type(tokens[i].type, 0)); } if (t == -1 || t >= buflen) return buf; buflen -= t; @@ -889,6 +957,7 @@ int m; #if DEBUG_EXPR_PARSE + fprintf(stderr, "%s\n", token_list(tokens, ntokens, tmp, sizeof(tmp))); for (x = 0; x < ntokens; x++) { fprintf (stderr, "%s ", expand_token_type(tokens[x].type, 0)); @@ -1414,6 +1483,7 @@ } } +/* This coerces everything to numbers */ long int arg_eval_num (CSPARSE *parse, CSARG *arg) { long int v = 0; @@ -1439,10 +1509,52 @@ return v; } +/* This is different from arg_eval_num because we don't force strings to + * numbers, a string is either a number (if it is all numeric) or we're + * testing existance. At least, that's what perl does and what dave + * wants */ +long int arg_eval_bool (CSPARSE *parse, CSARG *arg) +{ + long int v = 0; + char *s, *r; + + switch ((arg->op_type & CS_TYPES)) + { + case CS_TYPE_STRING: + case CS_TYPE_VAR: + if (arg->op_type == CS_TYPE_VAR) + s = var_lookup(parse, arg->s); + else + s = arg->s; + if (!s || *s == '\0') return 0; /* non existance or empty is false(0) */ + v = strtol(s, &r, 0); + if (*r == '\0') /* entire string converted, treat as number */ + return v; + /* if the entire string didn't convert, then its non-numeric and + * exists, so its true (1) */ + return 1; + case CS_TYPE_NUM: + return arg->n; + case CS_TYPE_VAR_NUM: /* this implies forced numeric evaluation */ + return var_int_lookup (parse, arg->s); + break; + default: + ne_warn ("Unsupported type %s in arg_eval_bool", expand_token_type(arg->op_type, 1)); + v = 0; + break; + } + return v; +} + #if DEBUG_EXPR_EVAL -static char *expand_arg (CSARG *arg) +static void expand_arg (CSPARSE *parse, int depth, char *where, CSARG *arg) { - fprintf(stderr, "op: %s alloc: %d value: ", expand_token_type(arg->op_type, 0), arg->alloc); + int x; + + for (x=0; xop_type, 0), arg->alloc); if (arg->op_type & CS_OP_NOT) fprintf(stderr, "!"); if (arg->op_type & CS_OP_NUM) @@ -1453,24 +1565,203 @@ fprintf(stderr, "#"); if (arg->op_type & CS_TYPE_NUM) fprintf(stderr, "%ld\n", arg->n); - else if (arg->op_type & (CS_TYPE_VAR_NUM | CS_TYPE_VAR | CS_TYPE_STRING)) - fprintf(stderr, "%s\n", arg->s); + else if (arg->op_type & CS_TYPE_STRING) + fprintf(stderr, "'%s'\n", arg->s); + else if (arg->op_type & CS_TYPE_VAR) + fprintf(stderr, "%s = %s\n", arg->s, var_lookup(parse, arg->s)); + else if (arg->op_type & CS_TYPE_VAR_NUM) + fprintf(stderr, "%s = %ld\n", arg->s, var_int_lookup(parse, arg->s)); else fprintf(stderr, "\n"); } #endif +static NEOERR *eval_expr_string(CSPARSE *parse, CSARG *arg1, CSARG *arg2, CSTOKEN_TYPE op, CSARG *result) +{ + char *s1, *s2; + int out; + + result->op_type = CS_TYPE_NUM; + s1 = arg_eval (parse, arg1); + s2 = arg_eval (parse, arg2); + + if ((s1 == NULL) || (s2 == NULL)) + { + switch (op) + { + case CS_OP_EQUAL: + result->n = (s1 == s2) ? 1 : 0; + break; + case CS_OP_NEQUAL: + result->n = (s1 != s2) ? 1 : 0; + break; + case CS_OP_LT: + result->n = ((s1 == NULL) && (s2 != NULL)) ? 1 : 0; + break; + case CS_OP_LTE: + result->n = (s1 == NULL) ? 1 : 0; + break; + case CS_OP_GT: + result->n = ((s1 != NULL) && (s2 == NULL)) ? 1 : 0; + break; + case CS_OP_GTE: + result->n = (s2 == NULL) ? 1 : 0; + break; + case CS_OP_ADD: + /* be sure to transfer ownership of the string here */ + result->op_type = CS_TYPE_STRING; + if (s1 == NULL) + { + result->s = s2; + result->alloc = arg2->alloc; + arg2->alloc = 0; + } + else + { + result->s = s1; + result->alloc = arg1->alloc; + arg1->alloc = 0; + } + break; + default: + ne_warn ("Unsupported op %s in eval_expr", expand_token_type(op, 1)); + break; + } + } + else + { + out = strcmp (s1, s2); + switch (op) + { + case CS_OP_EQUAL: + result->n = (!out) ? 1 : 0; + break; + case CS_OP_NEQUAL: + result->n = (out) ? 1 : 0; + break; + case CS_OP_LT: + result->n = (out < 0) ? 1 : 0; + break; + case CS_OP_LTE: + result->n = (out <= 0) ? 1 : 0; + break; + case CS_OP_GT: + result->n = (out > 0) ? 1 : 0; + break; + case CS_OP_GTE: + result->n = (out >= 0) ? 1 : 0; + break; + case CS_OP_ADD: + result->op_type = CS_TYPE_STRING; + result->alloc = 1; + result->s = (char *) calloc ((strlen(s1) + strlen(s2) + 1), sizeof(char)); + if (result->s == NULL) + return nerr_raise (NERR_NOMEM, "Unable to allocate memory to concatenate strings in expression: %s + %s", s1, s2); + strcpy(result->s, s1); + strcat(result->s, s2); + break; + default: + ne_warn ("Unsupported op %s in eval_expr_string", expand_token_type(op, 1)); + break; + } + } + return STATUS_OK; +} + +static NEOERR *eval_expr_num(CSPARSE *parse, CSARG *arg1, CSARG *arg2, CSTOKEN_TYPE op, CSARG *result) +{ + long int n1, n2; + + result->op_type = CS_TYPE_NUM; + n1 = arg_eval_num (parse, arg1); + n2 = arg_eval_num (parse, arg2); + + switch (op) + { + case CS_OP_EQUAL: + result->n = (n1 == n2) ? 1 : 0; + break; + case CS_OP_NEQUAL: + result->n = (n1 != n2) ? 1 : 0; + break; + case CS_OP_LT: + result->n = (n1 < n2) ? 1 : 0; + break; + case CS_OP_LTE: + result->n = (n1 <= n2) ? 1 : 0; + break; + case CS_OP_GT: + result->n = (n1 > n2) ? 1 : 0; + break; + case CS_OP_GTE: + result->n = (n1 >= n2) ? 1 : 0; + break; + case CS_OP_ADD: + result->n = (n1 + n2); + break; + case CS_OP_SUB: + result->n = (n1 - n2); + break; + case CS_OP_MULT: + result->n = (n1 * n2); + break; + case CS_OP_DIV: + if (n2 == 0) result->n = UINT_MAX; + else result->n = (n1 / n2); + break; + case CS_OP_MOD: + if (n2 == 0) result->n = 0; + else result->n = (n1 % n2); + break; + default: + ne_warn ("Unsupported op %s in eval_expr_num", expand_token_type(op, 1)); + break; + } + return STATUS_OK; +} + +static NEOERR *eval_expr_bool(CSPARSE *parse, CSARG *arg1, CSARG *arg2, CSTOKEN_TYPE op, CSARG *result) +{ + long int n1, n2; + + result->op_type = CS_TYPE_NUM; + n1 = arg_eval_bool (parse, arg1); + n2 = arg_eval_bool (parse, arg2); + + switch (op) + { + case CS_OP_AND: + result->n = (n1 && n2) ? 1 : 0; + break; + case CS_OP_OR: + result->n = (n1 || n2) ? 1 : 0; + break; + default: + ne_warn ("Unsupported op %s in eval_expr_bool", expand_token_type(op, 1)); + break; + } + return STATUS_OK; +} + +#if DEBUG_EXPR_EVAL +static int _depth = 0; +#endif + static NEOERR *eval_expr (CSPARSE *parse, CSARG *expr, CSARG *result) { CSARG arg1, arg2; NEOERR *err; - long int n1, n2; + long int n2; char *s1, *s2; - int out; + + if (expr == NULL) + return nerr_raise (NERR_ASSERT, "expr is NULL"); + if (result == NULL) + return nerr_raise (NERR_ASSERT, "result is NULL"); #if DEBUG_EXPR_EVAL - fprintf(stderr, "expr "); - expand_arg(expr); + _depth++; + expand_arg(parse, _depth, "expr", expr); #endif memset(result, 0, sizeof(CSARG)); @@ -1480,8 +1771,8 @@ /* we transfer ownership of the string here.. ugh */ if (expr->alloc) expr->alloc = 0; #if DEBUG_EXPR_EVAL - fprintf(stderr, "result "); - expand_arg(result); + expand_arg(parse, _depth, "result", result); + _depth--; #endif return STATUS_OK; } @@ -1490,8 +1781,7 @@ err = eval_expr (parse, expr->expr1, &arg1); if (err) return nerr_pass(err); #if DEBUG_EXPR_EVAL - fprintf(stderr, "arg1 "); - expand_arg(&arg1); + expand_arg(parse, _depth, "arg1", &arg1); #endif if (expr->op_type & CS_TYPE_FUNCTION) { @@ -1508,9 +1798,11 @@ result->op_type = CS_TYPE_NUM; switch (expr->op_type) { case CS_OP_NOT: + result->n = arg_eval_bool(parse, &arg1) ? 0 : 1; + /* if (arg1.op_type & CS_TYPE_VAR) { - /* This case is a "not exist" test */ + / * This case is a "not exist" test * / s1 = arg_eval (parse, &arg1); if (s1 == NULL || *s1 == '\0') result->n = 1; @@ -1522,6 +1814,7 @@ result->n = arg_eval_num (parse, &arg1); result->n = result->n ? 0 : 1; } + */ break; case CS_OP_EXISTS: if (arg1.op_type & (CS_TYPE_VAR | CS_TYPE_VAR_NUM)) @@ -1551,8 +1844,7 @@ { err = eval_expr (parse, expr->expr2, &arg2); #if DEBUG_EXPR_EVAL - fprintf(stderr, "arg2 "); - expand_arg(&arg2); + expand_arg(parse, _depth, "arg2", &arg2); #endif if (err) return nerr_pass(err); @@ -1625,150 +1917,22 @@ } } } + else if (expr->op_type & (CS_OP_AND | CS_OP_OR)) + { + /* eval as bool */ + err = eval_expr_bool (parse, &arg1, &arg2, expr->op_type, result); + } else if ((arg1.op_type & (CS_TYPE_NUM | CS_TYPE_VAR_NUM)) || (arg2.op_type & (CS_TYPE_NUM | CS_TYPE_VAR_NUM)) || (expr->op_type & (CS_OP_AND | CS_OP_OR | CS_OP_SUB | CS_OP_MULT | CS_OP_DIV | CS_OP_MOD))) { /* eval as num */ + err = eval_expr_num(parse, &arg1, &arg2, expr->op_type, result); - result->op_type = CS_TYPE_NUM; - n1 = arg_eval_num (parse, &arg1); - n2 = arg_eval_num (parse, &arg2); - - switch (expr->op_type) - { - case CS_OP_EQUAL: - result->n = (n1 == n2) ? 1 : 0; - break; - case CS_OP_NEQUAL: - result->n = (n1 != n2) ? 1 : 0; - break; - case CS_OP_LT: - result->n = (n1 < n2) ? 1 : 0; - break; - case CS_OP_LTE: - result->n = (n1 <= n2) ? 1 : 0; - break; - case CS_OP_GT: - result->n = (n1 > n2) ? 1 : 0; - break; - case CS_OP_GTE: - result->n = (n1 >= n2) ? 1 : 0; - break; - case CS_OP_AND: - result->n = (n1 && n2) ? 1 : 0; - break; - case CS_OP_OR: - result->n = (n1 || n2) ? 1 : 0; - break; - case CS_OP_ADD: - result->n = (n1 + n2); - break; - case CS_OP_SUB: - result->n = (n1 - n2); - break; - case CS_OP_MULT: - result->n = (n1 * n2); - break; - case CS_OP_DIV: - if (n2 == 0) result->n = UINT_MAX; - else result->n = (n1 / n2); - break; - case CS_OP_MOD: - if (n2 == 0) result->n = 0; - else result->n = (n1 % n2); - break; - default: - ne_warn ("Unsupported op %s in eval_expr", expand_token_type(expr->op_type, 1)); - break; - } } else /* eval as string */ { - result->op_type = CS_TYPE_NUM; - s1 = arg_eval (parse, &arg1); - s2 = arg_eval (parse, &arg2); - - if ((s1 == NULL) || (s2 == NULL)) - { - switch (expr->op_type) - { - case CS_OP_EQUAL: - result->n = (s1 == s2) ? 1 : 0; - break; - case CS_OP_NEQUAL: - result->n = (s1 != s2) ? 1 : 0; - break; - case CS_OP_LT: - result->n = ((s1 == NULL) && (s2 != NULL)) ? 1 : 0; - break; - case CS_OP_LTE: - result->n = (s1 == NULL) ? 1 : 0; - break; - case CS_OP_GT: - result->n = ((s1 != NULL) && (s2 == NULL)) ? 1 : 0; - break; - case CS_OP_GTE: - result->n = (s2 == NULL) ? 1 : 0; - break; - case CS_OP_ADD: - /* be sure to transfer ownership of the string here */ - result->op_type = CS_TYPE_STRING; - if (s1 == NULL) - { - result->s = s2; - result->alloc = arg2.alloc; - arg2.alloc = 0; - } - else - { - result->s = s1; - result->alloc = arg1.alloc; - arg1.alloc = 0; - } - break; - default: - ne_warn ("Unsupported op %s in eval_expr", expand_token_type(expr->op_type, 1)); - break; - } - } - else - { - out = strcmp (s1, s2); - switch (expr->op_type) - { - case CS_OP_EQUAL: - result->n = (!out) ? 1 : 0; - break; - case CS_OP_NEQUAL: - result->n = (out) ? 1 : 0; - break; - case CS_OP_LT: - result->n = (out < 0) ? 1 : 0; - break; - case CS_OP_LTE: - result->n = (out <= 0) ? 1 : 0; - break; - case CS_OP_GT: - result->n = (out > 0) ? 1 : 0; - break; - case CS_OP_GTE: - result->n = (out >= 0) ? 1 : 0; - break; - case CS_OP_ADD: - result->op_type = CS_TYPE_STRING; - result->alloc = 1; - result->s = (char *) calloc ((strlen(s1) + strlen(s2) + 1), sizeof(char)); - if (result->s == NULL) - return nerr_raise (NERR_NOMEM, "Unable to allocate memory to concatenate strings in expression: %s + %s", s1, s2); - strcpy(result->s, s1); - strcat(result->s, s2); - break; - default: - ne_warn ("Unsupported op %s in eval_expr", expand_token_type(expr->op_type, 1)); - break; - } - } + err = eval_expr_string(parse, &arg1, &arg2, expr->op_type, result); } if (arg1.alloc) free(arg1.s); @@ -1776,8 +1940,8 @@ } } #if DEBUG_EXPR_EVAL - fprintf(stderr, "result "); - expand_arg(result); + expand_arg(parse, _depth, "result", result); + _depth--; #endif return STATUS_OK; } @@ -1925,41 +2089,26 @@ err = eval_expr(parse, &(node->arg1), &val); if (err) return nerr_pass(err); - if (val.op_type & (CS_TYPE_NUM | CS_TYPE_VAR_NUM)) - { - char buf[256]; - long int n_val; + eval_true = arg_eval_bool(parse, &val); + if (eval_true) + { + if (val.op_type & (CS_TYPE_NUM | CS_TYPE_VAR_NUM)) + { + char buf[256]; + long int n_val; - n_val = arg_eval_num (parse, &val); - if (n_val) - { + n_val = arg_eval_num (parse, &val); snprintf (buf, sizeof(buf), "%ld", n_val); err = parse->output_cb (parse->output_ctx, buf); } else { - eval_true = 0; - } - } - else - { - char *s; - BOOL not = FALSE; - if (val.op_type & CS_OP_NOT) - { - not = TRUE; - val.op_type &= ~CS_OP_NOT; - } - s = arg_eval (parse, &val); - if (s == NULL || *s == '\0') - eval_true = 0; - - if (not == TRUE) - eval_true = !eval_true; - - if (eval_true && s) - { - err = parse->output_cb (parse->output_ctx, s); + char *s = arg_eval (parse, &val); + /* Do we set it to blank if s == NULL? */ + if (s) + { + err = parse->output_cb (parse->output_ctx, s); + } } } if (val.alloc) free(val.s); @@ -1982,6 +2131,8 @@ err = eval_expr(parse, &(node->arg1), &val); if (err) return nerr_pass (err); + eval_true = arg_eval_bool(parse, &val); + /* if (val.op_type & (CS_TYPE_NUM | CS_TYPE_VAR_NUM)) eval_true = arg_eval_num (parse, &val); else @@ -2002,6 +2153,7 @@ if (not == TRUE) eval_true = !eval_true; } + */ if (val.alloc) free(val.s); if (eval_true) @@ -2066,7 +2218,7 @@ return STATUS_OK; } -static NEOERR *each_parse (CSPARSE *parse, int cmd, char *arg) +static NEOERR *each_with_parse (CSPARSE *parse, int cmd, char *arg) { NEOERR *err; CSTREE *node; @@ -2087,8 +2239,8 @@ { dealloc_node(&node); return nerr_raise (NERR_PARSE, - "%s Improperly formatted each directive: %s", - find_context(parse, -1, tmp, sizeof(tmp)), arg); + "%s Improperly formatted %s directive: %s", + find_context(parse, -1, tmp, sizeof(tmp)), Commands[cmd].cmd, arg); } if (*p != '=') { @@ -2098,8 +2250,8 @@ { dealloc_node(&node); return nerr_raise (NERR_PARSE, - "%s Improperly formatted each directive: %s", - find_context(parse, -1, tmp, sizeof(tmp)), arg); + "%s Improperly formatted %s directive: %s", + find_context(parse, -1, tmp, sizeof(tmp)), Commands[cmd].cmd, arg); } p++; } @@ -2112,8 +2264,8 @@ { dealloc_node(&node); return nerr_raise (NERR_PARSE, - "%s Improperly formatted each directive: %s", - find_context(parse, -1, tmp, sizeof(tmp)), arg); + "%s Improperly formatted %s directive: %s", + find_context(parse, -1, tmp, sizeof(tmp)), Commands[cmd].cmd, arg); } node->arg1.op_type = CS_TYPE_VAR; node->arg1.s = lvar; @@ -2178,6 +2330,38 @@ return nerr_pass (err); } +static NEOERR *with_eval (CSPARSE *parse, CSTREE *node, CSTREE **next) +{ + NEOERR *err = STATUS_OK; + CS_LOCAL_MAP with_map; + CSARG val; + HDF *var; + + err = eval_expr(parse, &(node->arg2), &val); + if (err) return nerr_pass(err); + + if (val.op_type == CS_TYPE_VAR) + { + var = var_lookup_obj (parse, val.s); + + if (var != NULL) + { + /* Init and install local map */ + with_map.type = CS_TYPE_VAR; + with_map.name = node->arg1.s; + with_map.next = parse->locals; + with_map.value.h = var; + parse->locals = &with_map; + err = render_node (parse, node->case_0); + /* Remove local map */ + parse->locals = with_map.next; + } + } /* else WARNING */ + if (val.alloc) free(val.s); + + *next = node->next; + return nerr_pass (err); +} static NEOERR *end_parse (CSPARSE *parse, int cmd, char *arg) { NEOERR *err; @@ -2194,63 +2378,27 @@ static NEOERR *include_parse (CSPARSE *parse, int cmd, char *arg) { NEOERR *err; - CSTREE *node; - char *a, *s; - char tmp[256]; + char *s; + int flags = 0; + CSARG arg1, val; - err = alloc_node (&node); - if (err) return nerr_pass(err); - node->cmd = cmd; + memset(&arg1, 0, sizeof(CSARG)); if (arg[0] == '!') - node->flags |= CSF_REQUIRED; + flags |= CSF_REQUIRED; arg++; /* Validate arg is a var (regex /^[#" ]$/) */ - a = neos_strip(arg); + err = parse_expr (parse, arg, 0, &arg1); + if (err) return nerr_pass(err); /* ne_warn ("include: %s", a); */ - s = strpbrk(a, "# <>"); - if (s != NULL) - { - dealloc_node(&node); - return nerr_raise (NERR_PARSE, - "%s Invalid character in include argument %s: %c", - find_context(parse, -1, tmp, sizeof(tmp)), a, s[0]); - } - - /* Literal string or var */ - if (a[0] == '\"') - { - int l; - a++; - l = strlen(a); - - if (a[l - 1] == '\"') - { - a[l - 1] = '\0'; - } - node->arg1.op_type = CS_TYPE_STRING; - node->arg1.s = a; - s = a; - } - else - { - s = hdf_get_value (parse->hdf, a, NULL); - if (s == NULL) - { - dealloc_node(&node); - return nerr_raise (NERR_NOT_FOUND, - "%s Unable to include empty variable %s", - find_context(parse, -1, tmp, sizeof(tmp)), a); - } - node->arg1.op_type = CS_TYPE_VAR; - node->arg1.s = a; - } - *(parse->next) = node; - parse->next = &(node->next); - parse->current = node; + err = eval_expr(parse, &arg1, &val); + if (err) return nerr_pass(err); + s = arg_eval (parse, &val); + if (s == NULL && !(flags & CSF_REQUIRED)) + return STATUS_OK; err = cs_parse_file(parse, s); - if (!(node->flags & CSF_REQUIRED)) + if (!(flags & CSF_REQUIRED)) { nerr_handle(&err, NERR_NOT_FOUND); } @@ -3006,6 +3154,34 @@ return STATUS_OK; } +static NEOERR * _builtin_name(CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) +{ + HDF *obj; + + 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) + { + result->s = hdf_obj_name(obj); + } + else + { + result->s = ""; + } + } + else if (args->op_type & CS_TYPE_STRING) + { + result->s = args->s; + result->alloc = args->alloc; + args->alloc = 0; + } + return STATUS_OK; +} + static NEOERR * _str_func_wrapper (CSPARSE *parse, CS_FUNCTION *csf, CSARG *args, CSARG *result) { NEOERR *err; @@ -3106,6 +3282,14 @@ cs_destroy(&my_parse); return nerr_pass(err); } + err = _register_function(my_parse, "name", 1, _builtin_name); + if (err) + { + cs_destroy(&my_parse); + return nerr_pass(err); + } + my_parse->tag = hdf_get_value(hdf, "Config.TagStart", "cs"); + my_parse->taglen = strlen(my_parse->tag); my_parse->hdf = hdf; *parse = my_parse; diff -Nru clearsilver-0.8.1/cs/test.cs clearsilver-0.9.0/cs/test.cs --- clearsilver-0.8.1/cs/test.cs Thu Jun 21 14:56:01 2001 +++ clearsilver-0.9.0/cs/test.cs Wed Jul 2 18:04:16 2003 @@ -27,7 +27,8 @@ - + + x = diff -Nru clearsilver-0.8.1/cs/test.cs.gold clearsilver-0.9.0/cs/test.cs.gold --- clearsilver-0.8.1/cs/test.cs.gold Fri Sep 14 16:45:36 2001 +++ clearsilver-0.9.0/cs/test.cs.gold Wed Jul 2 18:04:16 2003 @@ -30,6 +30,12 @@ wow2 +I'm in test2.cs + + +wow2 + + x = zero x.num = #0 diff -Nru clearsilver-0.8.1/cs/test.hdf clearsilver-0.9.0/cs/test.hdf --- clearsilver-0.8.1/cs/test.hdf Mon Mar 17 21:59:49 2003 +++ clearsilver-0.9.0/cs/test.hdf Wed Jun 18 11:43:52 2003 @@ -133,3 +133,8 @@ C = / Biz.Address2 = addr +parent_id = -1 +faq.topic_id = 1 +Query.topic = -1 + +faq.sub_topic_id = -1 diff -Nru clearsilver-0.8.1/cs/test14.cs clearsilver-0.9.0/cs/test14.cs --- clearsilver-0.8.1/cs/test14.cs Mon Mar 31 23:26:57 2003 +++ clearsilver-0.9.0/cs/test14.cs Wed Jun 25 20:11:36 2003 @@ -58,7 +58,7 @@ ERROR - Not existence test, forced to numeric which evals to 0 + CORRECT boolean test, blooey doesn't exist, testif == 0 so its false @@ -81,7 +81,7 @@ Testing not one - + Testing not exist var one ERROR @@ -93,7 +93,7 @@ not expression existence test - + not expression test ERROR diff -Nru clearsilver-0.8.1/cs/test14.cs.gold clearsilver-0.9.0/cs/test14.cs.gold --- clearsilver-0.8.1/cs/test14.cs.gold Mon Mar 31 23:26:57 2003 +++ clearsilver-0.9.0/cs/test14.cs.gold Wed Jun 25 20:11:36 2003 @@ -39,7 +39,7 @@ - Not existence test, forced to numeric which evals to 0 + CORRECT boolean test, blooey doesn't exist, testif == 0 so its false diff -Nru clearsilver-0.8.1/cs/test18.cs clearsilver-0.9.0/cs/test18.cs --- clearsilver-0.8.1/cs/test18.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test18.cs Wed Jun 18 11:43:52 2003 @@ -0,0 +1,35 @@ + + + + + + + + +.... + + + +with whitespace + + +with extra variable + + +With whitespace in def... +.... + + + + + + + + + + + + + + + diff -Nru clearsilver-0.8.1/cs/test18.cs.gold clearsilver-0.9.0/cs/test18.cs.gold --- clearsilver-0.8.1/cs/test18.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test18.cs.gold Wed Jun 18 11:43:52 2003 @@ -0,0 +1,36 @@ +Parsing test18.cs + + + + + + + + + + +.... + +with whitespace +.... + +with extra variable + + +With whitespace in def... + + +.... + + + + + + + + + + + + + diff -Nru clearsilver-0.8.1/cs/test3.cs clearsilver-0.9.0/cs/test3.cs --- clearsilver-0.8.1/cs/test3.cs Wed Mar 27 16:47:28 2002 +++ clearsilver-0.9.0/cs/test3.cs Wed Jun 25 20:11:36 2003 @@ -24,7 +24,7 @@ - + before weekday diff -Nru clearsilver-0.8.1/cs/test4.cs clearsilver-0.9.0/cs/test4.cs --- clearsilver-0.8.1/cs/test4.cs Thu Mar 28 17:40:56 2002 +++ clearsilver-0.9.0/cs/test4.cs Wed Jun 25 20:11:36 2003 @@ -1,7 +1,7 @@ Testing cs set - + diff -Nru clearsilver-0.8.1/cs/test_chuck.cs clearsilver-0.9.0/cs/test_chuck.cs --- clearsilver-0.8.1/cs/test_chuck.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_chuck.cs Wed Jun 18 11:43:52 2003 @@ -0,0 +1,18 @@ +" + val + +"" +?> + + + +Biz.Address2 = +Biz.Address3 = + diff -Nru clearsilver-0.8.1/cs/test_chuck.cs.gold clearsilver-0.9.0/cs/test_chuck.cs.gold --- clearsilver-0.8.1/cs/test_chuck.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_chuck.cs.gold Wed Jun 18 11:43:52 2003 @@ -0,0 +1,8 @@ +Parsing test_chuck.cs + + + + +Biz.Address2 = addr +Biz.Address3 = + diff -Nru clearsilver-0.8.1/cs/test_each_array.cs clearsilver-0.9.0/cs/test_each_array.cs --- clearsilver-0.8.1/cs/test_each_array.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_each_array.cs Wed Jun 18 11:43:52 2003 @@ -0,0 +1,5 @@ + + + + + diff -Nru clearsilver-0.8.1/cs/test_each_array.cs.gold clearsilver-0.9.0/cs/test_each_array.cs.gold --- clearsilver-0.8.1/cs/test_each_array.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_each_array.cs.gold Wed Jun 18 11:43:52 2003 @@ -0,0 +1,12 @@ +Parsing test_each_array.cs + + + + zero + + one + + two + + three + diff -Nru clearsilver-0.8.1/cs/test_exists.cs clearsilver-0.9.0/cs/test_exists.cs --- clearsilver-0.8.1/cs/test_exists.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_exists.cs Wed Jun 18 11:43:52 2003 @@ -0,0 +1,7 @@ +array exists test + + + PASS + + ERROR + diff -Nru clearsilver-0.8.1/cs/test_iter.cs clearsilver-0.9.0/cs/test_iter.cs --- clearsilver-0.8.1/cs/test_iter.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_iter.cs Wed Jun 18 11:43:52 2003 @@ -0,0 +1,14 @@ + + + + + + + + + + #Query.start && #count < #next ?> + + + + diff -Nru clearsilver-0.8.1/cs/test_iter.cs.gold clearsilver-0.9.0/cs/test_iter.cs.gold --- clearsilver-0.8.1/cs/test_iter.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_iter.cs.gold Wed Jun 18 11:43:52 2003 @@ -0,0 +1,181 @@ +Parsing test_iter.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 11 + + + + + 12 + + + + + 13 + + + + + 14 + + + + + 15 + + + + + 16 + + + + + 17 + + + + + 18 + + + + + 19 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru clearsilver-0.8.1/cs/test_name.cs clearsilver-0.9.0/cs/test_name.cs --- clearsilver-0.8.1/cs/test_name.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_name.cs Wed Jun 18 11:43:52 2003 @@ -0,0 +1,7 @@ + + + + + + + diff -Nru clearsilver-0.8.1/cs/test_name.cs.gold clearsilver-0.9.0/cs/test_name.cs.gold --- clearsilver-0.8.1/cs/test_name.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_name.cs.gold Wed Jun 18 11:43:52 2003 @@ -0,0 +1,14 @@ +Parsing test_name.cs + + +Foo + + + 0 + + 1 + + 2 + + 3 + diff -Nru clearsilver-0.8.1/cs/test_numbers.cs clearsilver-0.9.0/cs/test_numbers.cs --- clearsilver-0.8.1/cs/test_numbers.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_numbers.cs Wed Jul 2 17:40:06 2003 @@ -0,0 +1,56 @@ + + + + + CORRECT: -1 == -1 + + ERROR: -1 should equal -1 + + + + CORRECT: -1 is boolean true + + ERROR : -1 should be boolean true + + + + CORRECT: #-1 is boolean true + + ERROR : #-1 should be boolean true + + + + ERROR: 0 should be boolean false + + CORRECT: 0 is boolean false + + + + ERROR: 00 should be boolean false + + CORRECT: 00 is boolean false + + + + CORRECT: 0x15 (hex) == 21 + + ERROR: 0x15 (hex) should equal 21 + + + + CORRECT: 0x15 is boolean true + + ERROR: 0x15 should be boolean true + + + + CORRECT: (3*2)+4 does equal 10 + + ERROR: (3*2)+4 should equal 10 + + + + CORRECT: 0 + 2 == 2 + + ERROR: 0 + 2 should equal 2 + diff -Nru clearsilver-0.8.1/cs/test_numbers.cs.gold clearsilver-0.9.0/cs/test_numbers.cs.gold --- clearsilver-0.8.1/cs/test_numbers.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_numbers.cs.gold Wed Jul 2 17:40:15 2003 @@ -0,0 +1,39 @@ +Parsing test_numbers.cs + +-1 + + + CORRECT: -1 == -1 + + + + CORRECT: -1 is boolean true + + + + CORRECT: #-1 is boolean true + + + + CORRECT: 0 is boolean false + + + + CORRECT: 00 is boolean false + + + + CORRECT: 0x15 (hex) == 21 + + + + CORRECT: 0x15 is boolean true + + + + CORRECT: (3*2)+4 does equal 10 + + + + CORRECT: 0 + 2 == 2 + diff -Nru clearsilver-0.8.1/cs/test_paren.cs clearsilver-0.9.0/cs/test_paren.cs --- clearsilver-0.8.1/cs/test_paren.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_paren.cs Wed Jun 18 11:28:32 2003 @@ -0,0 +1,5 @@ + +VALUE:: + + + diff -Nru clearsilver-0.8.1/cs/test_paren.cs.gold clearsilver-0.9.0/cs/test_paren.cs.gold --- clearsilver-0.8.1/cs/test_paren.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_paren.cs.gold Wed Jun 18 11:28:32 2003 @@ -0,0 +1,6 @@ +Parsing test_paren.cs + + +VALUE:HELLO(): + + diff -Nru clearsilver-0.8.1/cs/test_tag.cs clearsilver-0.9.0/cs/test_tag.cs --- clearsilver-0.8.1/cs/test_tag.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_tag.cs Wed Jun 25 20:11:36 2003 @@ -0,0 +1 @@ + diff -Nru clearsilver-0.8.1/cs/test_tag.cs.gold clearsilver-0.9.0/cs/test_tag.cs.gold --- clearsilver-0.8.1/cs/test_tag.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_tag.cs.gold Wed Jun 25 20:11:36 2003 @@ -0,0 +1,2 @@ +Parsing test_tag.cs +0 1 2 diff -Nru clearsilver-0.8.1/cs/test_tag.hdf clearsilver-0.9.0/cs/test_tag.hdf --- clearsilver-0.8.1/cs/test_tag.hdf Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_tag.hdf Wed Jun 25 20:11:36 2003 @@ -0,0 +1 @@ +Config.TagStart = int1 diff -Nru clearsilver-0.8.1/cs/test_trak1.cs clearsilver-0.9.0/cs/test_trak1.cs --- clearsilver-0.8.1/cs/test_trak1.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_trak1.cs Wed Jun 18 11:43:52 2003 @@ -0,0 +1,9 @@ + + matched + + + + + + + diff -Nru clearsilver-0.8.1/cs/test_trak1.cs.gold clearsilver-0.9.0/cs/test_trak1.cs.gold --- clearsilver-0.8.1/cs/test_trak1.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_trak1.cs.gold Wed Jun 18 11:43:52 2003 @@ -0,0 +1,8 @@ +Parsing test_trak1.cs + + + + + + 2 + diff -Nru clearsilver-0.8.1/cs/test_var.cs clearsilver-0.9.0/cs/test_var.cs --- clearsilver-0.8.1/cs/test_var.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_var.cs Wed Jun 18 11:28:32 2003 @@ -0,0 +1 @@ + diff -Nru clearsilver-0.8.1/cs/test_var.cs.gold clearsilver-0.9.0/cs/test_var.cs.gold --- clearsilver-0.8.1/cs/test_var.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_var.cs.gold Wed Jun 18 11:28:32 2003 @@ -0,0 +1,2 @@ +Parsing test_var.cs +wow diff -Nru clearsilver-0.8.1/cs/test_with.cs clearsilver-0.9.0/cs/test_with.cs --- clearsilver-0.8.1/cs/test_with.cs Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_with.cs Wed Jun 25 20:11:36 2003 @@ -0,0 +1,6 @@ + + + + - + + diff -Nru clearsilver-0.8.1/cs/test_with.cs.gold clearsilver-0.9.0/cs/test_with.cs.gold --- clearsilver-0.8.1/cs/test_with.cs.gold Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/cs/test_with.cs.gold Wed Jun 25 20:11:36 2003 @@ -0,0 +1,31 @@ +Parsing test_with.cs + + + + 0 - Mon + + + + 1 - Tues + + + + 2 - Wed + + + + 3 - Thur + + + + 4 - Fri + + + + 5 - Sat + + + + 6 - Sun + + diff -Nru clearsilver-0.8.1/cs_config.h.in clearsilver-0.9.0/cs_config.h.in --- clearsilver-0.8.1/cs_config.h.in Wed Apr 2 15:07:26 2003 +++ clearsilver-0.9.0/cs_config.h.in Mon Apr 14 16:05:07 2003 @@ -96,6 +96,12 @@ /* Does your system have pthreads? */ #undef HAVE_PTHREADS +/* Does your system have lockf ? */ +#undef HAVE_LOCKF + +/* Does your system have Berkeley DB v2 ? */ +#undef HAVE_DB2 + /* Define if you have the drand48 function. */ #undef HAVE_DRAND48 diff -Nru clearsilver-0.8.1/imd/imd.c clearsilver-0.9.0/imd/imd.c --- clearsilver-0.8.1/imd/imd.c Mon Feb 11 12:16:23 2002 +++ clearsilver-0.9.0/imd/imd.c Mon Apr 14 16:05:28 2003 @@ -24,9 +24,7 @@ #include #include -#include "cgi/cgi.h" -#include "cgi/cgiwrap.h" -#include "util/neo_misc.h" +#include "ClearSilver.h" /* from httpd util.c : made infamous with Roy owes Rob beer. */ static char *months[] = { diff -Nru clearsilver-0.8.1/java-jni/Makefile clearsilver-0.9.0/java-jni/Makefile --- clearsilver-0.8.1/java-jni/Makefile Wed Apr 2 16:26:22 2003 +++ clearsilver-0.9.0/java-jni/Makefile Mon Apr 14 17:13:42 2003 @@ -20,7 +20,7 @@ DLIBS += -lneo_cgi -lneo_cs -lneo_utl LIBS += -L$(LIB_DIR) $(DLIBS) -TARGETS = $(NEO_UTIL_SO) +TARGETS = org_clearsilver_HDF.h org_clearsilver_CS.h $(NEO_UTIL_SO) all: $(TARGETS) test @@ -48,6 +48,11 @@ $(NEO_UTIL_SO): $(NEO_UTIL_JAVA_JAR) $(NEO_UTIL_OBJ) $(DEP_LIBS) $(LDSHARED) -o $@ $(LDFLAGS) $(NEO_UTIL_OBJ) $(LIBS) + +# I guess we'll just stick the .jar file in the lib directory +install: all + $(INSTALL) $(NEO_UTIL_SO) $(DESTDIR)$(libdir) + $(INSTALL) $(NEO_UTIL_JAVA_JAR) $(DESTDIR)$(libdir) clean: $(RM) *.o *.so diff -Nru clearsilver-0.8.1/mod_ecs/Makefile clearsilver-0.9.0/mod_ecs/Makefile --- clearsilver-0.8.1/mod_ecs/Makefile Wed Apr 2 15:07:31 2003 +++ clearsilver-0.9.0/mod_ecs/Makefile Mon Apr 14 17:13:44 2003 @@ -19,6 +19,14 @@ $(MOD_ECS_SO): $(MOD_ECS_SRC) $(DEP_LIBS) $(APXS) -c -o $@ $(MOD_ECS_SRC) +install: all + $(NEOTONIC_ROOT)mkinstalldirs $(DESTDIR)$(libexecdir) + $(INSTALL) $(MOD_ECS_SO) $(DESTDIR)$(libexecdir) + +# Hmm, install it in the default apache place, or in with the +# rest of our stuff? +# $(APXS) -i $(MOD_ECS_SO) + clean: $(RM) *.o diff -Nru clearsilver-0.8.1/perl/ClearSilver.pm clearsilver-0.9.0/perl/ClearSilver.pm --- clearsilver-0.8.1/perl/ClearSilver.pm Wed Apr 2 15:07:32 2003 +++ clearsilver-0.9.0/perl/ClearSilver.pm Fri Apr 4 16:02:53 2003 @@ -1,6 +1,6 @@ package ClearSilver; -use 5.005; +use 5.006; use strict; use warnings; diff -Nru clearsilver-0.8.1/perl/ClearSilver.xs clearsilver-0.9.0/perl/ClearSilver.xs --- clearsilver-0.8.1/perl/ClearSilver.xs Wed Apr 2 15:07:32 2003 +++ clearsilver-0.9.0/perl/ClearSilver.xs Mon Apr 14 16:05:10 2003 @@ -2,9 +2,7 @@ #include "perl.h" #include "XSUB.h" -#include "cs_config.h" -#include "util/neo_hdf.h" -#include "cs/cs.h" +#include "ClearSilver.h" /* #define DEBUG_MODE 1 */ diff -Nru clearsilver-0.8.1/perl/Makefile.PL clearsilver-0.9.0/perl/Makefile.PL --- clearsilver-0.8.1/perl/Makefile.PL Wed Apr 2 15:07:32 2003 +++ clearsilver-0.9.0/perl/Makefile.PL Fri Apr 4 16:03:54 2003 @@ -5,9 +5,9 @@ 'NAME' => 'ClearSilver', 'VERSION_FROM' => 'ClearSilver.pm', # finds $VERSION 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 -# ($] >= 5.005 ? ## Add these new keywords supported since 5.005 -# (ABSTRACT_FROM => 'ClearSilver.pm', # retrieve abstract from module -# AUTHOR => 'A. U. Thor ') : ()), + ($] >= 5.005 ? ## Add these new keywords supported since 5.005 + (ABSTRACT_FROM => 'ClearSilver.pm', # retrieve abstract from module + AUTHOR => 'A. U. Thor ') : ()), 'LIBS' => ['-L../libs -lneo_cs -lneo_utl'], 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' # Insert -I. if you add *.h files later: diff -Nru clearsilver-0.8.1/python/Makefile clearsilver-0.9.0/python/Makefile --- clearsilver-0.8.1/python/Makefile Wed Apr 2 19:49:30 2003 +++ clearsilver-0.9.0/python/Makefile Mon Apr 14 17:13:45 2003 @@ -33,6 +33,10 @@ --target=i386-mingw32 \ $(PYTHON_LIB) $(LIBS) +install: all + $(NEOTONIC_ROOT)mkinstalldirs $(DESTDIR)$(PYTHON_SITE) + $(INSTALL) $(TARGETS) $(DESTDIR)$(PYTHON_SITE) + clean: $(RM) *.o diff -Nru clearsilver-0.8.1/python/examples/CSPage.py clearsilver-0.9.0/python/examples/CSPage.py --- clearsilver-0.8.1/python/examples/CSPage.py Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/python/examples/CSPage.py Sun Jun 15 18:54:49 2003 @@ -0,0 +1,209 @@ +#!/neo/opt/bin/python + +import neo_cgi +import sys, os, string +import time +from log import * + +# errors thrown... +NoPageName = "NoPageName" +NoDisplayMethod = "NoDisplayMethod" + +# errors signaled back to here +Redirected = "Redirected" +DisplayDone = "DisplayDone" +DisplayError = "DisplayError" + +class Context: + def __init__ (self): + self.argv = sys.argv + self.stdin = sys.stdin + self.stdout = sys.stdout + self.stderr = sys.stderr + self.environ = os.environ + +class CSPage: + def __init__(self, context, pagename=0,readDefaultHDF=1,israwpage=0): + if pagename == 0: + raise NoPageName, "missing pagename" + self.pagename = pagename + self.readDefaultHDF = readDefaultHDF + self._israwpage = israwpage + self.context = context + + self._error_template = None + + self.page_start_time = time.time() + neo_cgi.cgiWrap(context.stdin, context.stdout, context.environ) + neo_cgi.IgnoreEmptyFormVars(1) + self.ncgi = neo_cgi.CGI() + self.ncgi.parse() + self._path_num = 0 + domain = self.ncgi.hdf.getValue("CGI.ServerName","") + domain = self.ncgi.hdf.getValue("HTTP.Host", domain) + self.domain = domain + self.subclassinit() + self.setPaths([self.ncgi.hdf.getValue("CGI.DocumentRoot","")]) + + def subclassinit(self): + pass + + def setPaths(self, paths): + for path in paths: + self.ncgi.hdf.setValue("hdf.loadpaths.%d" % self._path_num, path) + self._path_num = self._path_num + 1 + + def redirectUri(self,redirectTo): + ncgi = self.ncgi + if ncgi.hdf.getIntValue("Cookie.debug",0) == 1: + ncgi.hdf.setValue("CGI.REDIRECT_TO",redirectTo) + ncgi.display("dbg/redirect.cs") + print "
"
+            print neo_cgi.htmlEscape(ncgi.hdf.dump())
+            print "
" + raise DisplayDone + + self.ncgi.redirectUri(redirectTo) + raise Redirected, "redirected To: %s" % redirectTo + + ## ---------------------------------- + ## methods to be overridden in subclass when necessary: + + def setup(self): + pass + + def display(self): + raise NoDisplayMethod, "no display method present in %s" % repr(self) + + def main(self): + self.setup() + self.handle_actions() + self.display() + + ## ---------------------------------- + + def handle_actions(self): + hdf = self.ncgi.hdf + hdfobj = hdf.getObj("Query.Action") + if hdfobj: + firstchild = hdfobj.child() + if firstchild: + action = firstchild.name() + if firstchild.next(): + raise "multiple actions present!!!" + + method_name = "Action_%s" % action + method = getattr(self,method_name) + apply(method,[]) + + def start(self): + SHOULD_DISPLAY = 1 + if self._israwpage: + SHOULD_DISPLAY = 0 + + ncgi = self.ncgi + + if self.readDefaultHDF: + try: + if not self.pagename is None: + ncgi.hdf.readFile("%s.hdf" % self.pagename) + except: + log("Error reading HDF file: %s.hdf" % (self.pagename)) + + DISPLAY_ERROR = 0 + ERROR_MESSAGE = "" + # call page main function! + try: + self.main() + except DisplayDone: + SHOULD_DISPLAY = 0 + except Redirected: + # catch redirect exceptions + SHOULD_DISPLAY = 0 + except DisplayError, num: + ncgi.hdf.setValue("Query.error", str(num)) + if self._error_template: + ncgi.hdf.setValue("Content", self._error_template) + else: + DISPLAY_ERROR = 1 + except: + SHOULD_DISPLAY = 0 + DISPLAY_ERROR = 1 + + import handle_error + handle_error.handleException("Display Failed!") + ERROR_MESSAGE = handle_error.exceptionString() + + if DISPLAY_ERROR: + print "Content-Type: text/html\n\n" + + # print the page + + print "

Error in Page

" + print "A copy of this error report has been submitted to the developers. " + print "The details of the error report are below." + + + print "
"
+            print neo_cgi.htmlEscape(ERROR_MESSAGE)
+            print "
\n" + # print debug info always on page error... + print "
\n" + print "
"
+            print neo_cgi.htmlEscape(ncgi.hdf.dump())
+            print "
" + + + etime = time.time() - self.page_start_time + ncgi.hdf.setValue("CGI.debug.execute_time","%f" % (etime)) + + if SHOULD_DISPLAY and self.pagename: + debug_output = ncgi.hdf.getIntValue("page.debug",ncgi.hdf.getIntValue("Cookie.debug",0)) + + if not debug_output: + ncgi.hdf.setValue("Config.CompressionEnabled","1") + + # default display + template_name = ncgi.hdf.getValue("Content","%s.cs" % self.pagename) + # ncgi.hdf.setValue ("cgiout.charset", "utf-8"); + + ncgi.display(template_name) + + # debug output + if debug_output: + print "
\n" + print "Execution Time: %5.3f

" % (etime) + print "
"
+		print neo_cgi.htmlEscape(ncgi.hdf.dump())
+		print "
" + # ncgi.hdf.setValue("hdf.DEBUG",ncgi.hdf.dump()) + # ncgi.display("debug.cs") + + script_name = ncgi.hdf.getValue("CGI.ScriptName","") + if script_name: + script_name = string.split(script_name,"/")[-1] + + log ("[%s] etime/dtime: %5.3f/%5.3f %s (%s)" % (self.domain, etime, time.time() - etime - self.page_start_time, script_name, self.pagename)) + + # a protected output function to catch the output errors that occur when + # the server is either restarted or the user pushes the stop button on the + # browser + def output(self, str): + try: + self.context.stdout.write(str) + except IOError, reason: + log("IOError: %s" % (repr(reason))) + raise DisplayDone + + + def allQuery (self, s): + l = [] + if self.ncgi.hdf.getValue ("Query.%s.0" % s, ""): + obj = self.ncgi.hdf.getChild ("Query.%s" % s) + while obj: + l.append(obj.value()) + obj = obj.next() + else: + t = self.ncgi.hdf.getValue ("Query.%s" % s, "") + if t: l.append(t) + return l diff -Nru clearsilver-0.8.1/python/examples/handle_error.py clearsilver-0.9.0/python/examples/handle_error.py --- clearsilver-0.8.1/python/examples/handle_error.py Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/python/examples/handle_error.py Sun Jun 15 18:54:49 2003 @@ -0,0 +1,91 @@ + +import traceback, sys, string, time, socket, os +import who_calls + +DUMP_DIR = "/neo/data/bugs" + +Warning = "handle_error.Warning" + +# levels +LV_MESSAGE = "LV_MESSAGE" +LV_WARNING = "LV_WARNING" +LV_ERROR = "LV_ERROR" + +Count = 0 + +gErrorCount = 0 +DISABLE_DUMP = 0 + +def exceptionReason(): + return "%s.%s" % (str(sys.exc_type), str(sys.exc_value)) + +def exceptionString(): + tb_list = traceback.format_exception(sys.exc_type,sys.exc_value,sys.exc_traceback) + return string.join(tb_list,"") + + #### old way + import StringIO + ## get the traceback message + sfp = StringIO.StringIO() + traceback.print_exc(file=sfp) + exception = sfp.getvalue() + sfp.close() + + return exception + + +def handleException (msg=None, lvl=LV_ERROR, dump = 1): + global gErrorCount + gErrorCount = gErrorCount + 1 + + tb_list = traceback.format_exception(sys.exc_type,sys.exc_value,sys.exc_traceback) + if msg: + sys.stderr.write ("%s\n" % msg) + else: + msg = "Unhandled Exception" + + sys.stderr.write (string.join(tb_list,"")) + try: + if dump: dump_bug(lvl, "handleException", msg, string.join(tb_list, "")) + except: + handleException("Unable to dump_bug", dump = 0) + +def handleWarning (msg=""): + header = "*** handleWarning: %s\n" % msg + sys.stderr.write(header) + tb = who_calls.pretty_who_calls(strip=1) + "\n" + sys.stderr.write(tb) + + try: + dump_bug(LV_WARNING, "handleException", msg, tb) + except: + handleException("Unable to dump_bug", dump = 0) + +def dump_bug (level, etype, msg, location=None, nhdf=None): + global DISABLE_DUMP + if DISABLE_DUMP: return + + now = int(time.time()) + pid = os.getpid() + + import neo_cgi, neo_util + hdf = neo_util.HDF() + hdf.setValue("Required.Level", level) + hdf.setValue("Required.When", str(int(time.time()))) + hdf.setValue("Required.Type", etype) + hdf.setValue("Required.Title", msg) + hdf.setValue("Optional.Hostname", socket.gethostname()) + if location: + hdf.setValue("Optional.Location", location) + + for (key, value) in os.environ.items(): + hdf.setValue ("Environ.%s" % key, value) + + global Count + Count = Count + 1 + fname = "%d.%d_%d.%s" % (now, pid, Count, socket.gethostname()) + tpath = os.path.join (DUMP_DIR, "tmp", fname) + npath = os.path.join (DUMP_DIR, "new", fname) + hdf.writeFile(tpath) + os.rename(tpath, npath) + diff -Nru clearsilver-0.8.1/python/examples/log.py clearsilver-0.9.0/python/examples/log.py --- clearsilver-0.8.1/python/examples/log.py Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/python/examples/log.py Sun Jun 15 23:14:49 2003 @@ -0,0 +1,51 @@ +#!/neo/opt/bin/python + +# log.py + +import sys, time + +DEV = "development" +DEV_UPDATE = "update queries" +DEV_SELECT = "select queries" +DEV_REPORT = "report log" + +LOGGING_STATUS = { + DEV : 1, + DEV_UPDATE : 0, + DEV_SELECT : 0, + DEV_REPORT : 0} + +tstart = 0 + +def dlog(when,astr): + global LOGGING_STATUS + try: + if LOGGING_STATUS[when]: + log(astr) + except KeyError: + pass + +def tlog(astr): + global tstart + t = time.time() + if tstart == 0: + tstart = t + time_stamp = "%5.5f" % (t-tstart) + if len(astr): + if astr[-1] == "\n": + sys.stderr.write("[%s] %s" % (time_stamp, astr)) + else: + sys.stderr.write("[%s] %s\n" % (time_stamp, astr)) + +def log(astr): + if len(astr) > 1024: + astr = astr[:1024] + + t = time.time() + time_stamp = time.strftime("%m/%d %T", time.localtime(t)) + if len(astr): + if astr[-1] == "\n": + sys.stderr.write("[%s] %s" % (time_stamp, astr)) + else: + sys.stderr.write("[%s] %s\n" % (time_stamp, astr)) + # sys.stderr.flush() diff -Nru clearsilver-0.8.1/python/examples/who_calls.py clearsilver-0.9.0/python/examples/who_calls.py --- clearsilver-0.8.1/python/examples/who_calls.py Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/python/examples/who_calls.py Sun Jun 15 18:54:49 2003 @@ -0,0 +1,141 @@ + +# who_calls.py +# by Sam Rushing for Medusa + +import string +import sys + +from log import * + +whoCallsError = "whoCallsError" + +#-------------------------------------------------------------- +# Example use: +# +# import who_calls +# log(who_calls.pretty_who_calls()) +# +#-------------------------------------------------------------- + +def test(): + for i in range(1,1000): + pretty_who_calls() + + print_top_100() + +def who_calls_helper(): + tinfo = [] + exc_info = sys.exc_info() + + f = exc_info[2].tb_frame.f_back + while f: + tinfo.append ( ( + f.f_code.co_filename, + f.f_code.co_name, + f.f_lineno ) + ) + f = f.f_back + + del exc_info + return tinfo + + +def who_calls(): + try: + raise whoCallsError + except whoCallsError: + tinfo = who_calls_helper() + return tinfo + +def pretty_who_calls(strip=0): + info = who_calls() + buf = [] + + for file,function,line in info[1 + strip:]: + buf.append(" %s(%s): %s()" % (file,line,function)) + + return string.join(buf,"\n") + +# --------------------------------------------------------------------------- +# used for debugging. +# --------------------------------------------------------------------------- + +def compact_traceback (): + t,v,tb = sys.exc_info() + tbinfo = [] + if tb is None: + # this should never happen, but then again, lots of things + # should never happen but do. + return (('','',''), str(t), str(v), 'traceback is None!!!') + while 1: + tbinfo.append ( + tb.tb_frame.f_code.co_filename, + tb.tb_frame.f_code.co_name, + str(tb.tb_lineno) + ) + tb = tb.tb_next + if not tb: + break + + # just to be safe + del tb + + file, function, line = tbinfo[-1] + info = '[' + string.join ( + map ( + lambda x: string.join (x, '|'), + tbinfo + ), + '] [' + ) + ']' + + return (file, function, line), str(t), str(v), info + +## ---------------------------------------------------- +## Refcount printing + +import sys +import types + +def real_get_refcounts(base = None, set_base = 0): + d = {} + sys.modules + # collect all classes + for modname,m in sys.modules.items(): + for sym in dir(m): + o = getattr (m, sym) + if type(o) is types.ClassType: + name = "%s:%s" % (modname,o.__name__) + cnt = sys.getrefcount (o) + if base: + if set_base: + base[name] = cnt + elif cnt > base.get(name, 0): + d[name] = cnt - base.get(name, 0) + else: + d[name] = cnt + return d + +def get_refcounts(base=None): + d = real_get_refcounts(base = base) + # sort by refcount + pairs = map (lambda x: (x[1],x[0]), d.items()) + pairs.sort() + pairs.reverse() + return pairs + +REFCOUNTS = {} + +def set_refcount_base(): + global REFCOUNTS + real_get_refcounts(REFCOUNTS, set_base = 1) + +def print_top_100(): + print_top_N(100) + +def print_top_N(N): + global REFCOUNTS + for n, c in get_refcounts(REFCOUNTS)[:N]: + log('%10d %s' % (n, c)) + + diff -Nru clearsilver-0.8.1/python/neo_cgi.c clearsilver-0.9.0/python/neo_cgi.c --- clearsilver-0.8.1/python/neo_cgi.c Wed Apr 2 15:07:34 2003 +++ clearsilver-0.9.0/python/neo_cgi.c Mon Apr 14 16:05:11 2003 @@ -9,16 +9,7 @@ */ #include - -#include "cs_config.h" -#include "util/neo_err.h" -#include "util/neo_misc.h" -#include "util/neo_str.h" -#include "util/neo_hdf.h" -#include "cgi/cgi.h" -#include "cgi/cgiwrap.h" -#include "cgi/date.h" -#include "cgi/html.h" +#include "ClearSilver.h" #define NEO_CGI_MODULE #include "p_neo_util.h" diff -Nru clearsilver-0.8.1/python/neo_cs.c clearsilver-0.9.0/python/neo_cs.c --- clearsilver-0.8.1/python/neo_cs.c Wed Apr 2 15:07:34 2003 +++ clearsilver-0.9.0/python/neo_cs.c Mon Apr 14 16:05:11 2003 @@ -9,12 +9,7 @@ */ #include -#include "cs_config.h" -#include "util/neo_err.h" -#include "util/neo_misc.h" -#include "util/neo_str.h" -#include "util/neo_hdf.h" -#include "cs/cs.h" +#include "ClearSilver.h" #define NEO_CGI_MODULE #include "p_neo_util.h" diff -Nru clearsilver-0.8.1/python/neo_util.c clearsilver-0.9.0/python/neo_util.c --- clearsilver-0.8.1/python/neo_util.c Wed Apr 2 15:07:34 2003 +++ clearsilver-0.9.0/python/neo_util.c Mon Apr 14 16:05:11 2003 @@ -9,12 +9,7 @@ */ #include -#include "cs_config.h" -#include "util/neo_err.h" -#include "util/neo_misc.h" -#include "util/neo_str.h" -#include "util/neo_hdf.h" -#include "util/neo_date.h" +#include "ClearSilver.h" #define NEO_CGI_MODULE #include "p_neo_util.h" diff -Nru clearsilver-0.8.1/ruby/Makefile clearsilver-0.9.0/ruby/Makefile --- clearsilver-0.8.1/ruby/Makefile Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/Makefile Tue Jun 17 14:20:10 2003 @@ -0,0 +1,30 @@ + + +ifeq ($(NEOTONIC_ROOT),) +NEOTONIC_ROOT = ../ +endif + +include $(NEOTONIC_ROOT)rules.mk + +all: config.save ext/hdf/hdf.so test + +config.save: install.rb + $(RUBY) install.rb config + +ext/hdf/Makefile: + $(RUBY) install.rb config + +ext/hdf/hdf.so: config.save + $(RUBY) install.rb setup + +test: ext/hdf/hdf.so + $(RUBY) -Ilib -Iext/hdf test/hdftest.rb + +install: all + +clean: + $(RM) ext/hdf/*.o + +distclean: + $(RM) Makefile.depends config.save ext/hdf/hdf.so + $(RM) ext/hdf/Makefile ext/hdf/mkmf.log ext/hdf/*.o diff -Nru clearsilver-0.8.1/ruby/ext/hdf/MANIFEST clearsilver-0.9.0/ruby/ext/hdf/MANIFEST --- clearsilver-0.8.1/ruby/ext/hdf/MANIFEST Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/ext/hdf/MANIFEST Tue Jun 17 14:20:12 2003 @@ -0,0 +1,4 @@ +MANIFEST +extconf.rb +neo_cs.c +neo_util.c diff -Nru clearsilver-0.8.1/ruby/ext/hdf/extconf.rb clearsilver-0.9.0/ruby/ext/hdf/extconf.rb --- clearsilver-0.8.1/ruby/ext/hdf/extconf.rb Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/ext/hdf/extconf.rb Tue Jun 17 14:20:12 2003 @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby + +require 'mkmf' + +dir_config("hdf","../../..","../../../libs") + +if have_header("util/neo_hdf.h") && have_library("neo_utl","hdf_init") && have_library("neo_cs","cs_init") + create_makefile("hdf") +end diff -Nru clearsilver-0.8.1/ruby/ext/hdf/neo_cs.c clearsilver-0.9.0/ruby/ext/hdf/neo_cs.c --- clearsilver-0.8.1/ruby/ext/hdf/neo_cs.c Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/ext/hdf/neo_cs.c Tue Jun 17 14:20:12 2003 @@ -0,0 +1,116 @@ +/* + * Neotonic ClearSilver Templating System + * + * This code is made available under the terms of the + * Neotonic ClearSilver License. + * http://www.neotonic.com/clearsilver/license.hdf + * + * Copyright (C) 2001 by Brandon Long + */ + +#include +#include "ClearSilver.h" + +static VALUE cCs; +extern VALUE mNeotonic; +extern VALUE eHdfError; + +VALUE r_neo_error(NEOERR *err); + +static void c_free (CSPARSE *csd) { + if (csd) { + cs_destroy (&csd); + } +} + +static VALUE c_init (VALUE self) { + return self; +} + +VALUE c_new (VALUE class, VALUE oHdf) { + CSPARSE *cs = NULL; + NEOERR *err; + HDF *hdf; + VALUE r_cs; + + Data_Get_Struct(oHdf, HDF, hdf); + + if (hdf == NULL) rb_raise(eHdfError, "must include an Hdf object"); + + err = cs_init (&cs, hdf); + + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + r_cs = Data_Wrap_Struct(class, 0, c_free, cs); + rb_obj_call_init(r_cs, 0, NULL); + return r_cs; +} + +static VALUE c_parse_file (VALUE self, VALUE oPath) { + CSPARSE *cs = NULL; + NEOERR *err; + char *path; + + Data_Get_Struct(self, CSPARSE, cs); + path = STR2CSTR(oPath); + + err = cs_parse_file (cs, path); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE c_parse_str (VALUE self, VALUE oString) +{ + CSPARSE *cs = NULL; + NEOERR *err; + char *s, *ms; + int l; + + Data_Get_Struct(self, CSPARSE, cs); + s = rb_str2cstr(oString, &l); + + /* This should be changed to use memory from the gc */ + ms = strdup(s); + if (ms == NULL) rb_raise(rb_eNoMemError, "out of memory"); + + err = cs_parse_string (cs, ms, l); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static NEOERR *render_cb (void *ctx, char *buf) +{ + STRING *str= (STRING *)ctx; + + return nerr_pass(string_append(str, buf)); +} + +static VALUE c_render (VALUE self) +{ + CSPARSE *cs = NULL; + NEOERR *err; + STRING str; + VALUE rv; + + Data_Get_Struct(self, CSPARSE, cs); + + string_init(&str); + err = cs_render (cs, &str, render_cb); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + rv = rb_str_new2(str.buf); + string_clear (&str); + return rv; +} + +void Init_Cs() { + cCs = rb_define_class_under(mNeotonic, "Cs", rb_cObject); + rb_define_singleton_method(cCs, "new", c_new, 1); + + rb_define_method(cCs, "initialize", c_init, 0); + rb_define_method(cCs, "parse_file", c_parse_file, 1); + rb_define_method(cCs, "parse_string", c_parse_str, 1); + rb_define_method(cCs, "render", c_render, 0); +} diff -Nru clearsilver-0.8.1/ruby/ext/hdf/neo_util.c clearsilver-0.9.0/ruby/ext/hdf/neo_util.c --- clearsilver-0.8.1/ruby/ext/hdf/neo_util.c Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/ext/hdf/neo_util.c Tue Jun 17 14:20:12 2003 @@ -0,0 +1,522 @@ +/* + * Neotonic ClearSilver Templating System + * + * This code is made available under the terms of the + * Neotonic ClearSilver License. + * http://www.neotonic.com/clearsilver/license.hdf + * + * Copyright (C) 2001 by Brandon Long + */ + +#include +#include "ClearSilver.h" + +VALUE mNeotonic; +static VALUE cHdf; +VALUE eHdfError; + + +VALUE r_neo_error (NEOERR *err) +{ + STRING str; + VALUE errstr; + + string_init (&str); + if (nerr_match(err, NERR_PARSE)) { + nerr_error_string (err, &str); + errstr = rb_str_new2(str.buf); + string_clear(&str); + return errstr; + } + else { + nerr_error_traceback (err, &str); + errstr = rb_str_new2(str.buf); + string_clear(&str); + return errstr; + } + string_clear (&str); + return Qnil; +} + +static void h_free(void *p) { + hdf_destroy(p); +} + + +static VALUE h_init (VALUE self) +{ + return self; +} + +VALUE h_new(VALUE class) +{ + HDF *hdf = NULL; + NEOERR *err; + VALUE r_hdf; + + err = hdf_init (&hdf); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + r_hdf = Data_Wrap_Struct(class, 0, h_free, hdf); + rb_obj_call_init(r_hdf, 0, NULL); + return r_hdf; +} + +static VALUE h_get_attr (VALUE self, VALUE oName) +{ + HDF *hdf = NULL; + char *name; + HDF_ATTR *attr; + VALUE k,v; + VALUE rv; + + Data_Get_Struct(self, HDF, hdf); + name = STR2CSTR(oName); + + rv = rb_hash_new(); + + attr = hdf_get_attr(hdf, name); + while ( attr != NULL ) { + k=rb_str_new2(attr->key); + v=rb_str_new2(attr->value); + rb_hash_aset(rv, k, v); + attr = attr->next; + } + return rv; +} + +static VALUE h_set_attr(VALUE self, VALUE oName, VALUE oKey, VALUE oValue) +{ + HDF *hdf= NULL; + char *name, *key, *value; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + + name = STR2CSTR(oName); + key = STR2CSTR(oKey); + if ( NIL_P(oValue) ) + value = NULL; + else + value = STR2CSTR(oValue); + + err = hdf_set_attr(hdf, name, key, value); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_set_value (VALUE self, VALUE oName, VALUE oValue) +{ + HDF *hdf = NULL; + char *name, *value; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + + name=STR2CSTR(oName); + value=STR2CSTR(oValue); + + err = hdf_set_value (hdf, name, value); + + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_get_int_value (VALUE self, VALUE oName, VALUE oDefault) +{ + HDF *hdf = NULL; + char *name; + int r, d = 0; + VALUE rv; + + Data_Get_Struct(self, HDF, hdf); + name=STR2CSTR(oName); + d=NUM2INT(oDefault); + + r = hdf_get_int_value (hdf, name, d); + rv = INT2NUM(r); + return rv; +} + +static VALUE h_get_value (VALUE self, VALUE oName, VALUE oDefault) +{ + HDF *hdf = NULL; + char *name; + char *r, *d = NULL; + VALUE rv; + + Data_Get_Struct(self, HDF, hdf); + name=STR2CSTR(oName); + d=STR2CSTR(oDefault); + + r = hdf_get_value (hdf, name, d); + rv = rb_str_new2(r); + return rv; +} + +static VALUE h_get_child (VALUE self, VALUE oName) +{ + HDF *hdf = NULL; + HDF *r; + VALUE rv; + char *name; + + Data_Get_Struct(self, HDF, hdf); + name=STR2CSTR(oName); + + r = hdf_get_child (hdf, name); + if (r == NULL) { + return Qnil; + } + + rv = Data_Wrap_Struct(cHdf, 0, h_free, r); + return rv; +} + + +static VALUE h_obj_child (VALUE self) +{ + HDF *hdf = NULL; + HDF *r = NULL; + VALUE rv; + + Data_Get_Struct(self, HDF, hdf); + + r = hdf_obj_child (hdf); + if (r == NULL) { + return Qnil; + } + + rv = Data_Wrap_Struct(cHdf, 0, h_free, r); + return rv; +} + +static VALUE h_obj_next (VALUE self) +{ + HDF *hdf = NULL; + HDF *r = NULL; + VALUE rv; + + Data_Get_Struct(self, HDF, hdf); + + r = hdf_obj_next (hdf); + if (r == NULL) { + return Qnil; + } + + rv = Data_Wrap_Struct(cHdf, 0, h_free, r); + return rv; +} + +static VALUE h_obj_top (VALUE self) +{ + HDF *hdf = NULL; + HDF *r = NULL; + VALUE rv; + + Data_Get_Struct(self, HDF, hdf); + + r = hdf_obj_top (hdf); + if (r == NULL) { + return Qnil; + } + + rv = Data_Wrap_Struct(cHdf, 0, h_free, r); + return rv; +} + +static VALUE h_obj_name (VALUE self) +{ + HDF *hdf = NULL; + VALUE rv; + char *r; + + Data_Get_Struct(self, HDF, hdf); + + r = hdf_obj_name (hdf); + if (r == NULL) { + return Qnil; + } + + rv = rb_str_new2(r); + return rv; +} + +static VALUE h_obj_attr (VALUE self) +{ + HDF *hdf = NULL; + HDF_ATTR *attr; + VALUE k,v; + VALUE rv; + + Data_Get_Struct(self, HDF, hdf); + rv = rb_hash_new(); + + attr = hdf_obj_attr(hdf); + while ( attr != NULL ) { + k=rb_str_new2(attr->key); + v=rb_str_new2(attr->value); + rb_hash_aset(rv, k, v); + attr = attr->next; + } + return rv; +} + + +static VALUE h_obj_value (VALUE self) +{ + HDF *hdf = NULL; + VALUE rv; + char *r; + + Data_Get_Struct(self, HDF, hdf); + + r = hdf_obj_value (hdf); + if (r == NULL) { + return Qnil; + } + + rv = rb_str_new2(r); + return rv; +} + +static VALUE h_read_file (VALUE self, VALUE oPath) +{ + HDF *hdf = NULL; + char *path; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + + path=STR2CSTR(oPath); + + err = hdf_read_file (hdf, path); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_write_file (VALUE self, VALUE oPath) +{ + HDF *hdf = NULL; + char *path; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + + path=STR2CSTR(oPath); + + err = hdf_write_file (hdf, path); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_write_file_atomic (VALUE self, VALUE oPath) +{ + HDF *hdf = NULL; + char *path; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + + path=STR2CSTR(oPath); + + err = hdf_write_file_atomic (hdf, path); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_remove_tree (VALUE self, VALUE oName) +{ + HDF *hdf = NULL; + char *name; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + name = STR2CSTR(oName); + + err = hdf_remove_tree (hdf, name); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_dump (VALUE self) +{ + HDF *hdf = NULL; + VALUE rv; + NEOERR *err; + STRING str; + + string_init (&str); + + Data_Get_Struct(self, HDF, hdf); + + err = hdf_dump_str (hdf, NULL, 0, &str); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + rv = rb_str_new2(str.buf); + string_clear (&str); + return rv; +} + +static VALUE h_write_string (VALUE self) +{ + HDF *hdf = NULL; + VALUE rv; + NEOERR *err; + char *s = NULL; + + Data_Get_Struct(self, HDF, hdf); + + err = hdf_write_string (hdf, &s); + + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + rv = rb_str_new2(s); + if (s) free(s); + return rv; +} + +static VALUE h_read_string (VALUE self, VALUE oString, VALUE oIgnore) +{ + HDF *hdf = NULL; + NEOERR *err; + char *s = NULL; + int ignore = 0; + + Data_Get_Struct(self, HDF, hdf); + + s = STR2CSTR(oString); + ignore = NUM2INT(oIgnore); + + err = hdf_read_string_ignore (hdf, s, ignore); + + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_copy (VALUE self, VALUE oName, VALUE oHdfSrc) +{ + HDF *hdf = NULL; + HDF *src = NULL; + char *name; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + Data_Get_Struct(oHdfSrc, HDF, src); + + name = STR2CSTR(oName); + + if (src == NULL) rb_raise(eHdfError, "second argument must be an Hdf object"); + + err = hdf_copy (hdf, name, src); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_set_symlink (VALUE self, VALUE oSrc, VALUE oDest) +{ + HDF *hdf = NULL; + char *src; + char *dest; + NEOERR *err; + + Data_Get_Struct(self, HDF, hdf); + src = STR2CSTR(oSrc); + dest = STR2CSTR(oDest); + + err = hdf_set_symlink (hdf, src, dest); + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + return self; +} + +static VALUE h_escape (VALUE self, VALUE oString, VALUE oEsc_char, VALUE oEsc) +{ + VALUE rv; + char *s; + char *escape; + char *esc_char; + int buflen; + char *ret = NULL; + NEOERR *err; + + s = rb_str2cstr(oString,&buflen); + esc_char = STR2CSTR(oEsc_char); + escape = STR2CSTR(oEsc); + + err = neos_escape(s, buflen, esc_char[0], escape, &ret); + + if (err) rb_raise(eHdfError, "%s", r_neo_error(err)); + + rv = rb_str_new2(ret); + free(ret); + return rv; +} + +static VALUE h_unescape (VALUE self, VALUE oString, VALUE oEsc_char) +{ + VALUE rv; + char *s; + char *copy; + char *esc_char; + int buflen; + + s = rb_str2cstr(oString,&buflen); + esc_char = STR2CSTR(oEsc_char); + + /* This should be changed to use memory from the gc */ + copy = strdup(s); + if (copy == NULL) rb_raise(rb_eNoMemError, "out of memory"); + + neos_unescape(copy, buflen, esc_char[0]); + + rv = rb_str_new2(copy); + free(copy); + return rv; +} + +void Init_cs(); + +void Init_hdf() { + mNeotonic = rb_define_module("Neo"); + cHdf = rb_define_class_under(mNeotonic, "Hdf", rb_cObject); + + rb_define_singleton_method(cHdf, "new", h_new, 0); + rb_define_method(cHdf, "initialize", h_init, 0); + rb_define_method(cHdf, "get_attr", h_get_attr, 1); + rb_define_method(cHdf, "set_attr", h_set_attr, 3); + rb_define_method(cHdf, "set_value", h_set_value, 2); + rb_define_method(cHdf, "get_int_value", h_get_int_value, 2); + rb_define_method(cHdf, "get_value", h_get_value, 2); + rb_define_method(cHdf, "get_child", h_get_child, 1); + rb_define_method(cHdf, "obj_child", h_obj_child, 0); + rb_define_method(cHdf, "obj_next", h_obj_next, 0); + rb_define_method(cHdf, "obj_top", h_obj_top, 0); + rb_define_method(cHdf, "obj_name", h_obj_name, 0); + rb_define_method(cHdf, "obj_attr", h_obj_attr, 0); + rb_define_method(cHdf, "obj_value", h_obj_value, 0); + rb_define_method(cHdf, "read_file", h_read_file, 1); + rb_define_method(cHdf, "write_file", h_write_file, 1); + rb_define_method(cHdf, "write_file_atomic", h_write_file_atomic, 1); + rb_define_method(cHdf, "remove_tree", h_remove_tree, 1); + rb_define_method(cHdf, "dump", h_dump, 0); + rb_define_method(cHdf, "write_string", h_write_string, 0); + rb_define_method(cHdf, "read_string", h_read_string, 2); + rb_define_method(cHdf, "copy", h_copy, 2); + rb_define_method(cHdf, "set_symlink", h_set_symlink, 2); + + rb_define_singleton_method(cHdf, "escape", h_escape, 3); + rb_define_singleton_method(cHdf, "unescape", h_unescape, 3); + + eHdfError = rb_define_class_under(mNeotonic, "HdfError", rb_eException); + + Init_Cs(); +} diff -Nru clearsilver-0.8.1/ruby/install.rb clearsilver-0.9.0/ruby/install.rb --- clearsilver-0.8.1/ruby/install.rb Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/install.rb Tue Jun 17 14:20:10 2003 @@ -0,0 +1,1015 @@ +# +# This file is automatically generated. DO NOT MODIFY! +# +# install.rb +# +# Copyright (c) 2000-2002 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU Lesser General Public License version 2. +# + +### begin compat.rb + +unless Enumerable.instance_methods.include? 'inject' then +module Enumerable + def inject( result ) + each do |i| + result = yield(result, i) + end + result + end +end +end + +def File.read_all( fname ) + File.open(fname, 'rb') {|f| return f.read } +end + +def File.write( fname, str ) + File.open(fname, 'wb') {|f| f.write str } +end + +### end compat.rb +### begin config.rb + +if i = ARGV.index(/\A--rbconfig=/) then + file = $' + ARGV.delete_at(i) + require file +else + require 'rbconfig' +end + + +class ConfigTable + + c = ::Config::CONFIG + + rubypath = c['bindir'] + '/' + c['ruby_install_name'] + + major = c['MAJOR'].to_i + minor = c['MINOR'].to_i + teeny = c['TEENY'].to_i + version = "#{major}.#{minor}" + + # ruby ver. >= 1.4.4? + newpath_p = ((major >= 2) or + ((major == 1) and + ((minor >= 5) or + ((minor == 4) and (teeny >= 4))))) + + re = Regexp.new('\A' + Regexp.quote(c['prefix'])) + subprefix = lambda {|path| + re === path and path.sub(re, '$prefix') + } + + if c['rubylibdir'] then + # 1.6.3 < V + stdruby = subprefix.call(c['rubylibdir']) + siteruby = subprefix.call(c['sitedir']) + versite = subprefix.call(c['sitelibdir']) + sodir = subprefix.call(c['sitearchdir']) + elsif newpath_p then + # 1.4.4 <= V <= 1.6.3 + stdruby = "$prefix/lib/ruby/#{version}" + siteruby = subprefix.call(c['sitedir']) + versite = siteruby + '/' + version + sodir = "$site-ruby/#{c['arch']}" + else + # V < 1.4.4 + stdruby = "$prefix/lib/ruby/#{version}" + siteruby = "$prefix/lib/ruby/#{version}/site_ruby" + versite = siteruby + sodir = "$site-ruby/#{c['arch']}" + end + + DESCRIPTER = [ + [ 'prefix', [ c['prefix'], + 'path', + 'path prefix of target environment' ] ], + [ 'std-ruby', [ stdruby, + 'path', + 'the directory for standard ruby libraries' ] ], + [ 'site-ruby-common', [ siteruby, + 'path', + 'the directory for version-independent non-standard ruby libraries' ] ], + [ 'site-ruby', [ versite, + 'path', + 'the directory for non-standard ruby libraries' ] ], + [ 'bin-dir', [ '$prefix/bin', + 'path', + 'the directory for commands' ] ], + [ 'rb-dir', [ '$site-ruby', + 'path', + 'the directory for ruby scripts' ] ], + [ 'so-dir', [ sodir, + 'path', + 'the directory for ruby extentions' ] ], + [ 'data-dir', [ '$prefix/share', + 'path', + 'the directory for shared data' ] ], + [ 'ruby-path', [ rubypath, + 'path', + 'path to set to #! line' ] ], + [ 'ruby-prog', [ rubypath, + 'name', + 'the ruby program using for installation' ] ], + [ 'make-prog', [ 'make', + 'name', + 'the make program to compile ruby extentions' ] ], + [ 'without-ext', [ 'no', + 'yes/no', + 'does not compile/install ruby extentions' ] ] + ] + + SAVE_FILE = 'config.save' + + def ConfigTable.each_name( &block ) + keys().each( &block ) + end + + def ConfigTable.keys + DESCRIPTER.collect {|k,*dummy| k } + end + + def ConfigTable.each_definition( &block ) + DESCRIPTER.each( &block ) + end + + def ConfigTable.get_entry( name ) + name, ent = DESCRIPTER.assoc(name) + ent + end + + def ConfigTable.get_entry!( name ) + get_entry(name) or raise ArgumentError, "no such config: #{name}" + end + + def ConfigTable.add_entry( name, vals ) + ConfigTable::DESCRIPTER.push [name,vals] + end + + def ConfigTable.remove_entry( name ) + get_entry name or raise ArgumentError, "no such config: #{name}" + DESCRIPTER.delete_if {|n,arr| n == name } + end + + def ConfigTable.config_key?( name ) + get_entry(name) ? true : false + end + + def ConfigTable.bool_config?( name ) + ent = get_entry(name) or return false + ent[1] == 'yes/no' + end + + def ConfigTable.value_config?( name ) + ent = get_entry(name) or return false + ent[1] != 'yes/no' + end + + def ConfigTable.path_config?( name ) + ent = get_entry(name) or return false + ent[1] == 'path' + end + + + class << self + + alias newobj new + + def new + c = newobj() + c.__send__ :init + c + end + + def load + c = newobj() + File.file? SAVE_FILE or + raise InstallError, "#{File.basename $0} config first" + File.foreach( SAVE_FILE ) do |line| + k, v = line.split( '=', 2 ) + c.instance_eval { + @table[k] = v.strip + } + end + c + end + + end + + def initialize + @table = {} + end + + def init + DESCRIPTER.each do |k, (default, vname, desc, default2)| + @table[k] = default + end + end + private :init + + def save + File.open( SAVE_FILE, 'w' ) {|f| + @table.each do |k, v| + f.printf "%s=%s\n", k, v if v + end + } + end + + def []=( k, v ) + ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}" + if ConfigTable.path_config? k then + @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v + else + @table[k] = v + end + end + + def []( key ) + @table[key] or return nil + @table[key].gsub( %r<\$([^/]+)> ) { self[$1] } + end + + def set_raw( key, val ) + @table[key] = val + end + + def get_raw( key ) + @table[key] + end + +end + + +class MetaConfigEnvironment + + def self.eval_file( file ) + return unless File.file? file + new.instance_eval File.read_all(file), file, 1 + end + + private + + def config_names + ConfigTable.keys + end + + def config?( name ) + ConfigTable.config_key? name + end + + def bool_config?( name ) + ConfigTable.bool_config? name + end + + def value_config?( name ) + ConfigTable.value_config? name + end + + def path_config?( name ) + ConfigTable.path_config? name + end + + def add_config( name, argname, default, desc ) + ConfigTable.add_entry name,[default,argname,desc] + end + + def add_path_config( name, default, desc ) + add_config name, 'path', default, desc + end + + def add_bool_config( name, default, desc ) + add_config name, 'yes/no', default ? 'yes' : 'no', desc + end + + def set_config_default( name, default ) + if bool_config? name then + ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no' + else + ConfigTable.get_entry!(name)[0] = default + end + end + + def remove_config( name ) + ent = ConfigTable.get_entry(name) + ConfigTable.remove_entry name + ent + end + +end + +### end config.rb +### begin fileop.rb + +module FileOperations + + def mkdir_p( dname, prefix = nil ) + dname = prefix + dname if prefix + $stderr.puts "mkdir -p #{dname}" if verbose? + return if no_harm? + + # does not check '/'... it's too abnormal case + dirs = dname.split(%r_(?=/)_) + if /\A[a-z]:\z/i === dirs[0] then + disk = dirs.shift + dirs[0] = disk + dirs[0] + end + dirs.each_index do |idx| + path = dirs[0..idx].join('') + Dir.mkdir path unless dir? path + end + end + + def rm_f( fname ) + $stderr.puts "rm -f #{fname}" if verbose? + return if no_harm? + + if File.exist? fname or File.symlink? fname then + File.chmod 0777, fname + File.unlink fname + end + end + + def rm_rf( dn ) + $stderr.puts "rm -rf #{dn}" if verbose? + return if no_harm? + + Dir.chdir dn + Dir.foreach('.') do |fn| + next if fn == '.' + next if fn == '..' + if dir? fn then + verbose_off { + rm_rf fn + } + else + verbose_off { + rm_f fn + } + end + end + Dir.chdir '..' + Dir.rmdir dn + end + + def mv( src, dest ) + rm_f dest + begin + File.link src, dest + rescue + File.write dest, File.read_all(src) + File.chmod File.stat(src).mode, dest + end + rm_f src + end + + def install( from, dest, mode, prefix = nil ) + $stderr.puts "install #{from} #{dest}" if verbose? + return if no_harm? + + realdest = prefix + dest if prefix + if dir? realdest then + realdest += '/' + File.basename(from) + end + str = File.read_all(from) + if diff? str, realdest then + verbose_off { + rm_f realdest if File.exist? realdest + } + File.write realdest, str + File.chmod mode, realdest + + File.open( objdir + '/InstalledFiles', 'a' ) {|f| f.puts realdest } + end + end + + def diff?( orig, targ ) + return true unless File.exist? targ + orig != File.read_all(targ) + end + + def command( str ) + $stderr.puts str if verbose? + system str or raise RuntimeError, "'system #{str}' failed" + end + + def ruby( str ) + command config('ruby-prog') + ' ' + str + end + + def dir?( dname ) + # for corrupted windows stat() + File.directory?( (dname[-1,1] == '/') ? dname : dname + '/' ) + end + + def all_files( dname ) + Dir.open( dname ) {|d| + return d.find_all {|n| File.file? "#{dname}/#{n}" } + } + end + + def all_dirs( dname ) + Dir.open( dname ) {|d| + return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..) + } + end + +end + +### end fileop.rb +### begin base.rb + +class InstallError < StandardError; end + + +class Installer + + Version = '3.1.2' + Copyright = 'Copyright (c) 2000-2002 Minero Aoki' + + + @toplevel = nil + + def self.declear_toplevel_installer( inst ) + @toplevel and + raise ArgumentError, 'more than one toplevel installer decleared' + @toplevel = inst + end + + def self.toplevel_installer + @toplevel + end + + + FILETYPES = %w( bin lib ext data ) + + include FileOperations + + def initialize( config, opt, srcroot, objroot ) + @config = config + @options = opt + @srcdir = File.expand_path(srcroot) + @objdir = File.expand_path(objroot) + @currdir = '.' + end + + def inspect + "#<#{type} #{__id__}>" + end + + # + # configs/options + # + + def get_config( key ) + @config[key] + end + + alias config get_config + + def set_config( key, val ) + @config[key] = val + end + + def no_harm? + @options['no-harm'] + end + + def verbose? + @options['verbose'] + end + + def verbose_off + save, @options['verbose'] = @options['verbose'], false + yield + @options['verbose'] = save + end + + # + # srcdir/objdir + # + + attr_reader :srcdir + alias srcdir_root srcdir + alias package_root srcdir + + def curr_srcdir + "#{@srcdir}/#{@currdir}" + end + + attr_reader :objdir + alias objdir_root objdir + + def curr_objdir + "#{@objdir}/#{@currdir}" + end + + def srcfile( path ) + curr_srcdir + '/' + path + end + + def srcexist?( path ) + File.exist? srcfile(path) + end + + def srcdirectory?( path ) + dir? srcfile(path) + end + + def srcfile?( path ) + File.file? srcfile(path) + end + + def srcentries( path = '.' ) + Dir.open( curr_srcdir + '/' + path ) {|d| + return d.to_a - %w(. ..) - hookfilenames + } + end + + def srcfiles( path = '.' ) + srcentries(path).find_all {|fname| + File.file? File.join(curr_srcdir, path, fname) + } + end + + def srcdirectories( path = '.' ) + srcentries(path).find_all {|fname| + dir? File.join(curr_srcdir, path, fname) + } + end + + def dive_into( rel ) + return unless dir? "#{@srcdir}/#{rel}" + + dir = File.basename(rel) + Dir.mkdir dir unless dir? dir + save = Dir.pwd + Dir.chdir dir + $stderr.puts '---> ' + rel if verbose? + @currdir = rel + yield + Dir.chdir save + $stderr.puts '<--- ' + rel if verbose? + @currdir = File.dirname(rel) + end + + # + # config + # + + def exec_config + exec_task_traverse 'config' + end + + def config_dir_bin( rel ) + end + + def config_dir_lib( rel ) + end + + def config_dir_ext( rel ) + extconf if extdir? curr_srcdir + end + + def extconf + opt = @options['config-opt'].join(' ') + command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}" + end + + def config_dir_data( rel ) + end + + # + # setup + # + + def exec_setup + exec_task_traverse 'setup' + end + + def setup_dir_bin( relpath ) + all_files( curr_srcdir ).each do |fname| + add_rubypath "#{curr_srcdir}/#{fname}" + end + end + + SHEBANG_RE = /\A\#!\s*\S*ruby\S*/ + + def add_rubypath( path ) + $stderr.puts %Q if verbose? + return if no_harm? + + tmpfile = File.basename(path) + '.tmp' + begin + File.open( path ) {|r| + File.open( tmpfile, 'w' ) {|w| + first = r.gets + return unless SHEBANG_RE === first # reject '/usr/bin/env ruby' + + w.print first.sub( SHEBANG_RE, '#!' + config('ruby-path') ) + w.write r.read + } } + mv tmpfile, File.basename(path) + ensure + rm_f tmpfile if File.exist? tmpfile + end + end + + def setup_dir_lib( relpath ) + end + + def setup_dir_ext( relpath ) + if extdir? curr_srcdir then + make + end + end + + def make + command config('make-prog') + end + + def setup_dir_data( relpath ) + end + + # + # install + # + + def exec_install + exec_task_traverse 'install' + end + + def install_dir_bin( rel ) + install_files targfiles, config('bin-dir') + '/' + rel, 0755 + end + + def install_dir_lib( rel ) + install_files targfiles, config('rb-dir') + '/' + rel, 0644 + end + + def install_dir_ext( rel ) + if extdir? curr_srcdir then + install_dir_ext_main File.dirname(rel) + end + end + + def install_dir_ext_main( rel ) + install_files allext('.'), config('so-dir') + '/' + rel, 0555 + end + + def install_dir_data( rel ) + install_files targfiles, config('data-dir') + '/' + rel, 0644 + end + + def install_files( list, dest, mode ) + mkdir_p dest, @options['install-prefix'] + list.each do |fname| + install fname, dest, mode, @options['install-prefix'] + end + end + + def targfiles + (targfilenames() - hookfilenames()).collect {|fname| + File.exist?(fname) ? fname : File.join(curr_srcdir(), fname) + } + end + + def targfilenames + [ curr_srcdir(), '.' ].inject([]) {|ret, dir| + ret | all_files(dir) + } + end + + def hookfilenames + %w( pre-%s post-%s pre-%s.rb post-%s.rb ).collect {|fmt| + %w( config setup install clean ).collect {|t| sprintf fmt, t } + }.flatten + end + + def allext( dir ) + _allext(dir) or raise InstallError, + "no extention exists: Have you done 'ruby #{$0} setup' ?" + end + + DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/ + + def _allext( dir ) + Dir.open( dir ) {|d| + return d.find_all {|fname| DLEXT === fname } + } + end + + # + # clean + # + + def exec_clean + exec_task_traverse 'clean' + rm_f 'config.save' + rm_f 'InstalledFiles' + end + + def clean_dir_bin( rel ) + end + + def clean_dir_lib( rel ) + end + + def clean_dir_ext( rel ) + clean + end + + def clean + command config('make-prog') + ' clean' if File.file? 'Makefile' + end + + def clean_dir_data( rel ) + end + + # + # lib + # + + def exec_task_traverse( task ) + run_hook 'pre-' + task + FILETYPES.each do |type| + if config('without-ext') == 'yes' and type == 'ext' then + $stderr.puts 'skipping ext/* by user option' if verbose? + next + end + traverse task, type, task + '_dir_' + type + end + run_hook 'post-' + task + end + + def traverse( task, rel, mid ) + dive_into( rel ) { + run_hook 'pre-' + task + __send__ mid, rel.sub( %r_\A.*?(?:/|\z)_, '' ) + all_dirs( curr_srcdir ).each do |d| + traverse task, rel + '/' + d, mid + end + run_hook 'post-' + task + } + end + + def run_hook( name ) + try_run_hook curr_srcdir + '/' + name or + try_run_hook curr_srcdir + '/' + name + '.rb' + end + + def try_run_hook( fname ) + return false unless File.file? fname + + env = self.dup + begin + env.instance_eval File.read_all(fname), fname, 1 + rescue + raise InstallError, "hook #{fname} failed:\n" + $!.message + end + true + end + + def extdir?( dir ) + File.exist? dir + '/MANIFEST' + end + +end + +### end base.rb +### begin toplevel.rb + +class ToplevelInstaller < Installer + + TASKS = [ + [ 'config', 'saves your configurations' ], + [ 'show', 'shows current configuration' ], + [ 'setup', 'compiles extention or else' ], + [ 'install', 'installs files' ], + [ 'clean', "does `make clean' for each extention" ] + ] + + + def initialize( root ) + super nil, {'verbose' => true}, root, '.' + Installer.declear_toplevel_installer self + end + + + def execute + run_metaconfigs + + case task = parsearg_global() + when 'config' + @config = ConfigTable.new + else + @config = ConfigTable.load + end + parsearg_TASK task + + exectask task + end + + + def run_metaconfigs + MetaConfigEnvironment.eval_file "#{srcdir_root}/#{metaconfig}" + end + + def metaconfig + 'metaconfig' + end + + + def exectask( task ) + if task == 'show' then + exec_show + else + try task + end + end + + def try( task ) + $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose? + begin + __send__ 'exec_' + task + rescue + $stderr.printf "%s failed\n", task + raise + end + $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose? + end + + # + # processing arguments + # + + def parsearg_global + task_re = /\A(?:#{TASKS.collect {|i| i[0] }.join '|'})\z/ + + while arg = ARGV.shift do + case arg + when /\A\w+\z/ + task_re === arg or raise InstallError, "wrong task: #{arg}" + return arg + + when '-q', '--quiet' + @options['verbose'] = false + + when '--verbose' + @options['verbose'] = true + + when '-h', '--help' + print_usage $stdout + exit 0 + + when '-v', '--version' + puts "#{File.basename $0} version #{Version}" + exit 0 + + when '--copyright' + puts Copyright + exit 0 + + else + raise InstallError, "unknown global option '#{arg}'" + end + end + + raise InstallError, 'no task or global option given' + end + + + def parsearg_TASK( task ) + mid = "parsearg_#{task}" + if respond_to? mid, true then + __send__ mid + else + ARGV.empty? or + raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}" + end + end + + def parsearg_config + re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/ + @options['config-opt'] = [] + + while i = ARGV.shift do + if /\A--?\z/ === i then + @options['config-opt'] = ARGV.dup + break + end + m = re.match(i) or raise InstallError, "config: unknown option #{i}" + name, value = m.to_a[1,2] + if value then + if ConfigTable.bool_config?(name) then + /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument" + value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no' + end + else + ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument" + value = 'yes' + end + @config[name] = value + end + end + + def parsearg_install + @options['no-harm'] = false + @options['install-prefix'] = '' + while a = ARGV.shift do + case a + when /\A--no-harm\z/ + @options['no-harm'] = true + when /\A--prefix=(.*)\z/ + path = $1 + path = File.expand_path(path) unless path[0,1] == '/' + @options['install-prefix'] = path + else + raise InstallError, "install: unknown option #{a}" + end + end + end + + + def print_usage( out ) + out.puts + out.puts 'Usage:' + out.puts " ruby #{File.basename $0} " + out.puts " ruby #{File.basename $0} [] []" + + fmt = " %-20s %s\n" + out.puts + out.puts 'Global options:' + out.printf fmt, '-q,--quiet', 'suppress message outputs' + out.printf fmt, ' --verbose', 'output messages verbosely' + out.printf fmt, '-h,--help', 'print this message' + out.printf fmt, '-v,--version', 'print version and quit' + out.printf fmt, '--copyright', 'print copyright and quit' + + out.puts + out.puts 'Tasks:' + TASKS.each do |name, desc| + out.printf " %-10s %s\n", name, desc + end + + out.puts + out.puts 'Options for config:' + ConfigTable.each_definition do |name, (default, arg, desc, default2)| + out.printf " %-20s %s [%s]\n", + '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg), + desc, + default2 || default + end + out.printf " %-20s %s [%s]\n", + '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's" + + out.puts + out.puts 'Options for install:' + out.printf " %-20s %s [%s]\n", + '--no-harm', 'only display what to do if given', 'off' + + out.puts + end + + # + # config + # + + def exec_config + super + @config.save + end + + # + # show + # + + def exec_show + ConfigTable.each_name do |k| + v = @config.get_raw(k) + if not v or v.empty? then + v = '(not specified)' + end + printf "%-10s %s\n", k, v + end + end + +end + +### end toplevel.rb + +if $0 == __FILE__ then + begin + installer = ToplevelInstaller.new( File.dirname($0) ) + installer.execute + rescue + raise if $DEBUG + $stderr.puts $!.message + $stderr.puts "try 'ruby #{$0} --help' for usage" + exit 1 + end +end diff -Nru clearsilver-0.8.1/ruby/lib/neo.rb clearsilver-0.9.0/ruby/lib/neo.rb --- clearsilver-0.8.1/ruby/lib/neo.rb Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/lib/neo.rb Tue Jun 17 14:20:13 2003 @@ -0,0 +1,46 @@ +require 'hdf' + +module Clearsilver + + class Hdf < Neo::Hdf + + def initialize + super + @level=0 + @cpos="" + @position=[] + end + + attr_reader :position, :cpos + + def push name + @position.push(@cpos) + @cpos+=name+"." + + if block_given? + yield + @cpos=@position.pop + end + end + + def pop + @cpos=@position.pop + end + + def put name, value + value = value.to_s unless value.is_a?(String) + self.set_value(@cpos+(name.to_s),value) + end + + def get name + self.get_value(@cpos+name) + end + + end + + class Cs < Neo::Cs + + end +end + + diff -Nru clearsilver-0.8.1/ruby/test/hdftest.rb clearsilver-0.9.0/ruby/test/hdftest.rb --- clearsilver-0.8.1/ruby/test/hdftest.rb Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/ruby/test/hdftest.rb Tue Jun 17 14:20:14 2003 @@ -0,0 +1,40 @@ +#!/usr/bin/env ruby + +require 'neo' + +h=Neo::Hdf.new +h.set_value "1","farming" +h.set_value "2","sewing" +h.set_value "3","bowling" + +h.set_value "party.1","baloons" +h.set_value "party.2","noise makers" +h.set_value "party.3","telling long\nstories" + +h.set_attr "party.1", "Drool", "True" +h.set_attr "party.2", "Pink", "1" + +print h.dump + +q=Neo::Hdf.new + +q.copy "arf",h + +print q.dump + +h.get_attr("party.2").each_pair do |k,v| + print "party.2 attr (#{k}=#{v})\n" +end + + +s="This is a funny test. . + + +" + +c = Neo::Cs.new q + +c.parse_string(s) + +print c.render + diff -Nru clearsilver-0.8.1/rules.mk.in clearsilver-0.9.0/rules.mk.in --- clearsilver-0.8.1/rules.mk.in Thu Apr 3 16:32:23 2003 +++ clearsilver-0.9.0/rules.mk.in Tue Jun 17 14:20:40 2003 @@ -9,6 +9,29 @@ LIB_DIR = $(NEOTONIC_ROOT)libs/ +## Installation Directories +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ + +DESTDIR = + +cs_includedir = ${includedir}/ClearSilver + ## NOTE: The wdb code in util will tickle a bug in SleepyCat 2.4.5, ## which ships with various versions of Linux as part of glibc. If you ## are going to use that code, you should compile against SleepyCat @@ -23,6 +46,7 @@ PYTHON_INC = @PYTHON_INC@ PYTHON_LIB = @PYTHON_LIB@ +PYTHON_SITE = @PYTHON_SITE@ JAVA_PATH = @JAVA_PATH@ ## Programs @@ -37,6 +61,7 @@ JAR = $(JAVA_PATH)/bin/jar APXS = @APXS_PATH@ PERL = @PERL@ +RUBY = @RUBY@ CFLAGS = @CFLAGS@ -Wall -c -I$(NEOTONIC_ROOT) @CPPFLAGS@ CPPFLAGS = -I$(NEOTONIC_ROOT) @CPPFLAGS@ @@ -52,6 +77,7 @@ XARGS = xargs -i% BUILD_WRAPPERS = @BUILD_WRAPPERS@ EXTRA_UTL_OBJS = @EXTRA_UTL_OBJS@ +EXTRA_UTL_SRC = @EXTRA_UTL_SRC@ ## --------------win32 options diff -Nru clearsilver-0.8.1/scripts/cs_lint.py clearsilver-0.9.0/scripts/cs_lint.py --- clearsilver-0.8.1/scripts/cs_lint.py Wed Dec 31 16:00:00 1969 +++ clearsilver-0.9.0/scripts/cs_lint.py Wed Jul 2 18:06:12 2003 @@ -0,0 +1,283 @@ +#!/usr/bin/python +#!/neo/opt/bin/python + +import sys, string, os, getopt, signal, time +sys.path.append("../python") +import neo_cgi, neo_util +import cStringIO + +class ClearSilverChecker: + def __init__ (self): + self.context = "" + self.data = "" + self.at = 0 + self.cmd = "" + self.tokens = [] + + def error(self, s): + lineno = self.lineno(self.data, self.at) + print "-E- [%s:%d] %s" % (self.context, lineno, s) + if self.cmd: + print " Command is %s" % self.cmd + if self.tokens: + print " Tokens: %s" % repr(self.tokens) + + def warn(self, s): + lineno = self.lineno(self.data, self.at) + print "-W- [%s:%d] %s" % (self.context, lineno, s) + if self.cmd: + print " Command is %s" % self.cmd + if self.tokens: + print " Tokens: %s" % repr(self.tokens) + + def check_file(self, filename): + print "Checking file %s" % filename + self.context = filename + try: + self.run_neo_cgi(filename) + except neo_util.ParseError, reason: + print "-E- %s" % str(reason) + self.data = open(filename, "r").read() + self.parse() + + def run_neo_cgi(self, filename): + stdin = cStringIO.StringIO("") + stdout = cStringIO.StringIO() + neo_cgi.cgiWrap(stdin, stdout, {}) + neo_cgi.IgnoreEmptyFormVars(1) + ncgi = neo_cgi.CGI() + path = os.path.dirname(filename) + ncgi.hdf.setValue("hdf.loadpaths.path", path) + ncgi.display(filename) + return + + def lineno(self, data, i): + return len(string.split(data[:i], '\n')) + + def parse(self): + self.at = 0 + x = string.find(self.data[self.at:], '= 0: + self.at = x + self.at + ce = string.find(self.data[self.at:], '?>') + if ce == -1: + self.error("Missing ?> in expression") + else: + ce = ce + self.at + self.check_command(ce) + + # reset these class variables + self.cmd = "" + self.tokens = [] + self.at = self.at + 1 + x = string.find(self.data[self.at:], ' %s" % (cmd, args) + if cmd == "alt": + self.check_expression(args) + elif cmd == "if": + self.check_expression(args) + elif cmd == "elif": + self.check_expression(args) + elif cmd == "else": + pass + elif cmd == "include": + self.check_expression(args) + elif cmd == "linclude": + self.check_expression(args) + elif cmd == "name": + self.check_expression(args) + elif cmd == "var": + self.check_expression(args) + elif cmd == "evar": + self.check_expression(args) + elif cmd == "lvar": + self.check_expression(args) + elif cmd == "def": + macro, args = self.split_macro(args) + if macro: self.check_expression(macro, lvalue=1) + if args:self.check_expression(args) + elif cmd == "call": + macro, args = self.split_macro(args) + if macro: self.check_expression(macro, lvalue=1) + if args:self.check_expression(args) + elif cmd == "with": + varname, args = self.split_equals(args) + if varname: self.check_expression(varname, lvalue=1) + if args: self.check_expression(args) + elif cmd == "each": + varname, args = self.split_equals(args) + if varname: self.check_expression(varname, lvalue=1) + if args: self.check_expression(args) + elif cmd == "loop": + varname, args = self.split_equals(args) + if varname: self.check_expression(varname, lvalue=1) + if args: self.check_expression(args) + elif cmd == "set": + varname, args = self.split_equals(args) + if varname: self.check_expression(varname, lvalue=1) + if args: self.check_expression(args) + else: + self.error("Unrecognized command %s" % cmd) + + def split_equals(self, args): + x = string.find(args, '=') + if x == -1: + self.error("Missing equals") + return None, None + else: + return args[:x], args[x+1:] + + def split_macro(self, args): + b = string.find(args, '(') + e = string.rfind(args, ')') + if b == -1: + self.error("Missing opening parenthesis") + return None, None + if e == -1: + self.error("Missing closing parenthesis") + return None, None + macro_name = args[:b] + args = args[b+1:e] + return macro_name, args + + def check_expression(self, expr, lvalue=0): + tokens = self.tokenize_expression(expr) + #print repr(tokens) + if len(tokens) == 0: + self.error("Empty Expression") + + _OP = 1 + _VAR = 2 + _VARN = 3 + _STR = 4 + _NUM = 5 + + _TOKEN_SEP = "\"?<>=!#-+|&,)*/%[]( \t\r\n" + + def tokenize_expression(self, expr): + self.tokens = [] + while expr: + #print "expr: '%s'" % expr + expr = string.lstrip(expr) + len_expr = len(expr) + if len_expr == 0: break + if expr[:2] in ["<=", ">=", "==", "!=", "||", "&&"]: + self.tokens.append((ClearSilverChecker._OP, expr[:2])) + expr = expr[2:] + continue + elif expr[0] in ["!", "?", "<", ">", "+", "-", "*", "/", "%", "(", ")", "[", "]", ".", ',']: + self.tokens.append((ClearSilverChecker._OP, expr[0])) + expr = expr[1:] + continue + elif expr[0] in ["#", "$"]: + x = 1 + if expr[1] in ['+', '-']: x=2 + while len_expr > x and expr[x] not in ClearSilverChecker._TOKEN_SEP: x=x+1 + if x == 0: + self.error("[1] Zero length token, unexpected character %s" % expr[0]) + x = 1 + else: + token = expr[1:x] + if expr[0] == "#": + try: + n = int(token) + t_type = ClearSilverChecker._NUM + except ValueError: + t_type = ClearSilverChecker._VARN + else: + t_type = ClearSilverChecker._VAR + self.tokens.append((t_type, token)) + expr = expr[x:] + continue + elif expr[0] in ['"', "'"]: + x = string.find(expr[1:], expr[0]) + if x == -1: + self.error("Missing end of string %s " % expr) + break + else: + x = x + 1 + self.tokens.append((ClearSilverChecker._STR, expr[1:x])) + expr = expr[x+2:] + continue + else: + x = 0 + while len_expr > x and expr[x] not in ClearSilverChecker._TOKEN_SEP: x=x+1 + if x == 0: + self.error("[2] Zero length token, unexpected character %s" % expr[0]) + x = 1 + else: + token = expr[:x] + try: + n = int(token) + t_type = ClearSilverChecker._NUM + self.warn("This behavior changed in version 0.9: previously this was a variable name, now its a number: %s" % token) + except ValueError: + t_type = ClearSilverChecker._VAR + self.tokens.append((t_type, token)) + expr = expr[x:] + continue + return self.tokens + + # For version 0.9, we changed two things, we should check for them + # both + # - an all numeric expression element is now considered a number and + # not an HDF variable name + # - we now use boolean evaluation in places that used to use either a + # special case or a numeric evaluation + +def usage(argv0): + print "%s: usage info!!" % argv0 + +def main(argv): + alist, args = getopt.getopt(argv[1:], "", ["help"]) + + for (field, val) in alist: + if field == "--help": + usage(argv[0]) + sys.exit(-1) + + for file in args: + ClearSilverChecker().check_file(file) + +if __name__ == "__main__": + main(sys.argv) diff -Nru clearsilver-0.8.1/util/Makefile clearsilver-0.9.0/util/Makefile --- clearsilver-0.8.1/util/Makefile Wed Apr 2 15:07:36 2003 +++ clearsilver-0.9.0/util/Makefile Mon Apr 14 17:13:46 2003 @@ -8,9 +8,10 @@ UTL_LIB = $(LIB_DIR)libneo_utl.a UTL_SRC = neo_err.c neo_files.c neo_misc.c neo_rand.c ulist.c neo_hdf.c \ - neo_str.c neo_date.c wildmat.c neo_hash.c + neo_str.c neo_date.c wildmat.c neo_hash.c $(EXTRA_UTL_SRC) UTL_OBJ = $(UTL_SRC:%.c=%.o) $(EXTRA_UTL_OBJS) +UTL_HDR = $(UTL_SRC:%.c=%.h) TARGETS = $(UTL_LIB) @@ -18,6 +19,11 @@ $(UTL_LIB): $(UTL_OBJ) $(AR) $@ $(UTL_OBJ) + +install: all + $(NEOTONIC_ROOT)mkinstalldirs $(DESTDIR)$(cs_includedir)/util + $(INSTALL) -m 644 $(UTL_HDR) $(DESTDIR)$(cs_includedir)/util + $(INSTALL) -m 644 $(UTL_LIB) $(DESTDIR)$(libdir) clean: $(RM) *.o diff -Nru clearsilver-0.8.1/util/dict.c clearsilver-0.9.0/util/dict.c --- clearsilver-0.8.1/util/dict.c Wed Apr 2 15:07:36 2003 +++ clearsilver-0.9.0/util/dict.c Mon Apr 14 16:02:26 2003 @@ -51,7 +51,7 @@ typedef UINT32 (*dictHashFunc)(const char *str); typedef int (*dictCompFunc)(const char *s1, const char *s2); -struct dictCtx { +struct _dictCtx { pthread_mutex_t mList; /* list update mutex */ skipList list; /* skip list */ @@ -557,7 +557,7 @@ do { - if(! (dict = calloc(1, sizeof(struct dictCtx)))) + if(! (dict = calloc(1, sizeof(struct _dictCtx)))) return nerr_raise (NERR_NOMEM, "Unable to allocate memory for dictCtx"); dict->useCase = useCase; diff -Nru clearsilver-0.8.1/util/dict.h clearsilver-0.9.0/util/dict.h --- clearsilver-0.8.1/util/dict.h Wed Apr 2 15:07:36 2003 +++ clearsilver-0.9.0/util/dict.h Mon Apr 14 16:02:26 2003 @@ -14,7 +14,9 @@ #ifndef __DICT_H_ #define __DICT_H_ -typedef struct dictCtx *dictCtx; +__BEGIN_DECLS + +typedef struct _dictCtx *dictCtx; typedef BOOL (*dictCleanupFunc)(char *id, void *value, void *rock); typedef void (*dictFreeValueFunc)(void *value, void *rock); @@ -156,5 +158,7 @@ * Return: None. * MT-Level: Safe if thread-safe. */ + +__END_DECLS #endif /* __DICT_H_ */ diff -Nru clearsilver-0.8.1/util/neo_net.c clearsilver-0.9.0/util/neo_net.c --- clearsilver-0.8.1/util/neo_net.c Wed Apr 2 15:07:36 2003 +++ clearsilver-0.9.0/util/neo_net.c Thu May 22 19:32:19 2003 @@ -486,6 +486,7 @@ NEOERR *err; int x = 0; char buf[32]; + char *ep = NULL; while (x < sizeof(buf)) { @@ -506,7 +507,11 @@ return nerr_raise(NERR_PARSE, "Format error on stream, expected '%c'", end); buf[x] = '\0'; - *i = atoi(buf); + *i = strtol(buf, &ep, 10); + if (ep && *ep) + { + return nerr_raise(NERR_PARSE, "Format error on stream, expected number followed by '%c'", end); + } return STATUS_OK; }