mailto_class)
+ {
+ err = string_appendf (out, "class=%s ", opts->mailto_class);
+ if (err) break;
+ }
+ err = string_append(out, "href=\"mailto:");
+ if (err) break;
err = string_appendn (out, src + x, parts[i].end - x);
if (err != STATUS_OK) break;
err = string_append (out, "\">");
@@ -448,21 +519,46 @@
NEOERR *convert_text_html_alloc (unsigned char *src, int slen, unsigned char **out)
{
+ return nerr_pass(convert_text_html_alloc_options(src, slen, out, NULL));
+}
+
+NEOERR *convert_text_html_alloc_options (unsigned char *src, int slen, unsigned char **out, HTML_CONVERT_OPTS *opts)
+{
NEOERR *err;
STRING out_s;
- int formatting;
+ int formatting = 0;
+ HTML_CONVERT_OPTS my_opts;
string_init(&out_s);
+ if (opts == NULL)
+ {
+ opts = &my_opts;
+ opts->bounce_url = NULL;
+ opts->url_class = NULL;
+ opts->url_target = "_blank";
+ opts->mailto_class = NULL;
+ opts->long_lines = 0;
+ opts->space_convert = 0;
+ opts->newlines_convert = 1;
+ opts->longline_width = 75; /* This hasn't been used in a while, actually */
+ opts->check_ascii_art = 1;
+ }
+
do
{
+ if (opts->check_ascii_art)
+ {
formatting = has_space_formatting (src, slen);
+ if (formatting) opts->space_convert = 1;
+ }
if (formatting == 2)
{
/* Do formatting */
+ opts->newlines_convert = 1;
err = string_append (&out_s, "");
if (err != STATUS_OK) break;
- err = split_and_convert(src, slen, &out_s, 1, 1);
+ err = split_and_convert(src, slen, &out_s, opts);
if (err != STATUS_OK) break;
err = string_append (&out_s, "");
if (err != STATUS_OK) break;
@@ -472,7 +568,7 @@
else
{
/* int nl = has_long_lines (src, slen); */
- err = split_and_convert(src, slen, &out_s, 1, formatting);
+ err = split_and_convert(src, slen, &out_s, opts);
}
} while (0);
if (err != STATUS_OK)
diff -Nbru clearsilver-0.9.3/cgi/html.h clearsilver-0.9.6/cgi/html.h
--- clearsilver-0.9.3/cgi/html.h Fri Mar 14 14:58:02 2003
+++ clearsilver-0.9.6/cgi/html.h Thu Sep 11 18:33:02 2003
@@ -17,7 +17,20 @@
__BEGIN_DECLS
+typedef struct _text_html_opts {
+ char *bounce_url;
+ char *url_class;
+ char *url_target;
+ char *mailto_class;
+ int long_lines;
+ int space_convert;
+ int newlines_convert;
+ int longline_width;
+ int check_ascii_art;
+} HTML_CONVERT_OPTS;
+
NEOERR *convert_text_html_alloc (unsigned char *src, int slen, unsigned char **out);
+NEOERR *convert_text_html_alloc_options (unsigned char *src, int slen, unsigned char **out, HTML_CONVERT_OPTS *opts);
NEOERR *html_escape_alloc (unsigned char *src, int slen, unsigned char **out);
NEOERR *html_strip_alloc(unsigned char *src, int slen, unsigned char **out);
diff -Nbru clearsilver-0.9.3/configure.in clearsilver-0.9.6/configure.in
--- clearsilver-0.9.3/configure.in Sun Aug 31 10:33:24 2003
+++ clearsilver-0.9.6/configure.in Mon Sep 22 19:09:38 2003
@@ -105,13 +105,13 @@
cs_cv_need_reentrant=yes
AC_MSG_RESULT(yes)],[
cs_cv_missing=yes
- AC_MSG_RESULT(no)])])])
+ AC_MSG_RESULT(no)])])], [cs_cv_missing=yes])
AC_CHECK_FUNCS(gmtime_r, [
AC_MSG_CHECKING(whether gmtime_r is declared)
AC_EGREP_CPP(gmtime_r,[
#include ],[
- AC_DEFINE(HAVE_LOCALTIME_R)
+ AC_DEFINE(HAVE_GMTIME_R)
AC_MSG_RESULT(yes)],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING(whether gmtime_r with -D_REENTRANT is declared)
@@ -121,13 +121,13 @@
cs_cv_need_reentrant=yes
AC_MSG_RESULT(yes)],[
cs_cv_missing=yes
- AC_MSG_RESULT(no)])])])
+ AC_MSG_RESULT(no)])])], [cs_cv_missing=yes])
AC_CHECK_FUNCS(strtok_r, [
AC_MSG_CHECKING(whether strtok_r is declared)
AC_EGREP_CPP(strtok_r,[
#include ],[
- AC_DEFINE(HAVE_LOCALTIME_R)
+ AC_DEFINE(HAVE_STRTOK_R)
AC_MSG_RESULT(yes)],[
AC_MSG_RESULT(no)
AC_MSG_CHECKING(whether strtok_r with -D_REENTRANT is declared)
@@ -137,7 +137,7 @@
cs_cv_need_reentrant=yes
AC_MSG_RESULT(yes)],[
cs_cv_missing=yes
- AC_MSG_RESULT(no)])])])
+ AC_MSG_RESULT(no)])])], [cs_cv_missing=yes])
AC_CHECK_FUNC(mkstemp, [AC_DEFINE(HAVE_MKSTEMP)], [cs_cv_missing=yes])
if test $cs_cv_missing = yes; then
diff -Nbru clearsilver-0.9.3/cs_config.h.in clearsilver-0.9.6/cs_config.h.in
--- clearsilver-0.9.3/cs_config.h.in Fri Aug 8 23:55:25 2003
+++ clearsilver-0.9.6/cs_config.h.in Mon Sep 22 20:49:34 2003
@@ -78,8 +78,14 @@
/* Does your system have the vsnprintf() call? */
#undef HAVE_VSNPRINTF
+/* Does your system have the strtok_r() call? */
+#undef HAVE_STRTOK_R
+
/* Does your system have the localtime_r() call? */
#undef HAVE_LOCALTIME_R
+
+/* Does your system have the gmtime_r() call? */
+#undef HAVE_GMTIME_R
/* Does your system have the mkstemp() call? */
#undef HAVE_MKSTEMP
diff -Nbru clearsilver-0.9.3/java-jni/Makefile clearsilver-0.9.6/java-jni/Makefile
--- clearsilver-0.9.3/java-jni/Makefile Mon Aug 18 13:09:20 2003
+++ clearsilver-0.9.6/java-jni/Makefile Wed Sep 3 15:38:47 2003
@@ -51,7 +51,7 @@
LD_LIBRARY_PATH=$(NEOTONIC_ROOT)/java-jni; export LD_LIBRARY_PATH; \
CLASSPATH=$(NEO_UTIL_JAVA_JAR):.; export CLASSPATH; \
$(JAVA_PATH)/bin/java CSTest > javatest.out; \
- diff -brief javatest.out javatest.gold 2>%1 > /dev/null; \
+ diff -brief javatest.out javatest.gold > /dev/null 2>&1; \
return_code=$$?; \
if [ $$return_code -ne 0 ]; then \
diff javatest.out javatest.gold > javatest.err; \
diff -Nbru clearsilver-0.9.3/ports/rpm/clearsilver.spec clearsilver-0.9.6/ports/rpm/clearsilver.spec
--- clearsilver-0.9.3/ports/rpm/clearsilver.spec Sun Aug 31 12:07:39 2003
+++ clearsilver-0.9.6/ports/rpm/clearsilver.spec Mon Oct 20 14:19:30 2003
@@ -53,11 +53,11 @@
Summary: Neotonic ClearSilver
Name: clearsilver
-Version: 0.9.3
+Version: 0.9.6
Release: 1
Copyright: Open Source - Neotonic ClearSilver License (Apache 1.1 based)
Group: Development/Libraries
-Source: http://www.clearsilver.net/downloads/clearsilver-0.9.3.tar.gz
+Source: http://www.clearsilver.net/downloads/clearsilver-0.9.5.tar.gz
URL: http://www.clearsilver.net/
Vendor: Neotonic Software Corporation, Inc.
Packager: Brandon Long
@@ -188,6 +188,7 @@
%{__prefix}/lib/libneo_utl.a
%{__prefix}/bin/static.cgi
%{__prefix}/bin/cstest
+%{__prefix}/man/man3
%if %{with_python_subpackage}
%files python
diff -Nbru clearsilver-0.9.3/python/Makefile clearsilver-0.9.6/python/Makefile
--- clearsilver-0.9.3/python/Makefile Thu Jul 24 11:36:50 2003
+++ clearsilver-0.9.6/python/Makefile Thu Sep 11 19:02:24 2003
@@ -23,7 +23,7 @@
all: $(TARGETS)
-$(NEO_UTIL_SO): setup.py
+$(NEO_UTIL_SO): setup.py $(NEO_UTIL_SRC) $(DEP_LIBS)
$(PYTHON) setup.py build_ext --inplace
OLD_NEO_UTIL_SO:
diff -Nbru clearsilver-0.9.3/python/examples/base/hdfhelp.py clearsilver-0.9.6/python/examples/base/hdfhelp.py
--- clearsilver-0.9.3/python/examples/base/hdfhelp.py Wed Aug 20 22:57:16 2003
+++ clearsilver-0.9.6/python/examples/base/hdfhelp.py Sat Sep 13 03:25:00 2003
@@ -33,7 +33,7 @@
# return hdfhelp.HdfItemList
#
-import string
+import string, os
import neo_cgi
import neo_cs
import neo_util
@@ -85,7 +85,10 @@
return time.strftime("%m/%d/%Y %I:%M%p",then_tuple)
class HdfRow(odb.Row):
- def hdfExport(self,prefix,hdf_dataset,skip_fields = None, translate_dict = None):
+ def hdfExport(self, prefix, hdf_dataset, *extra, **extranamed):
+ skip_fields = extranamed.get("skip_fields", None)
+ translate_dict = extranamed.get("translate_dict", None)
+ tz = extranamed.get("tz", "US/Pacific")
for col_name,value in self.items():
if skip_fields and (col_name in skip_fields):
@@ -96,27 +99,53 @@
col_type = odb.kVarString
col_options = {}
- if (col_name != "value") and (value is not None):
+ if (value is not None):
+ if col_options.get("no_export",0): continue
if type(value) in [ type(0), type(0L) ]:
hdf_dataset.setValue(prefix + "." + col_name,"%d" % value)
+ elif type(value) == type(1.0):
+ if int(value) == value:
+ hdf_dataset.setValue(prefix + "." + col_name,"%d" % value)
+ else:
+ hdf_dataset.setValue(prefix + "." + col_name,"%0.2f" % value)
else:
+ if col_type == odb.kReal:
+ log("why are we here with this value: %s" % value)
if translate_dict:
for k,v in translate_dict.items():
value = string.replace(value,k,v)
- hdf_dataset.setValue(prefix + "." + col_name,neo_cgi.htmlEscape(value))
+ hdf_dataset.setValue(prefix + "." + col_name,neo_cgi.htmlEscape(str(value)))
if col_options.get("int_date",0):
hdf_dataset.setValue(prefix + "." + col_name + ".string",renderDate(value))
hdf_dataset.setValue(prefix + "." + col_name + ".day_string",renderDate(value,day=1))
+ if value: neo_cgi.exportDate(hdf_dataset, "%s.%s" % (prefix, col_name), tz, value)
-
+ if col_options.has_key("enum_values"):
+ enum = col_options["enum_values"]
+ hdf_dataset.setValue(prefix + "." + col_name + ".enum",
+ str(enum.get(value,'')))
class HdfItemList(UserList.UserList):
def hdfExport(self,prefix,hdf_dataset,*extra,**extranamed):
+ export_by = extranamed.get("export_by", None)
n = 0
for row in self:
+ if export_by is not None:
+ n = row[export_by]
row.hdfExport("%s.%d" % (prefix,n),hdf_dataset,*extra,**extranamed)
n = n + 1
+def setList(hdf, prefix, lst):
+ hdf.setValue(prefix+".0", str(len(lst)))
+ for n in range(len(lst)):
+ hdf.setValue(prefix+".%d" %(n+1), lst[n]);
+
+def getList(hdf, name):
+ lst = []
+ for n in range(hdf.getIntValue(name,0)):
+ lst.append(hdf.getValue(name+".%d" %(n+1), ""))
+
+ return lst
def eval_cs(hdf,a_cs_string):
cs = neo_cs.CS(hdf)
diff -Nbru clearsilver-0.9.3/python/examples/base/odb.py clearsilver-0.9.6/python/examples/base/odb.py
--- clearsilver-0.9.3/python/examples/base/odb.py Wed Aug 20 22:57:16 2003
+++ clearsilver-0.9.6/python/examples/base/odb.py Thu Sep 11 03:09:47 2003
@@ -51,7 +51,6 @@
# list_rows = tbl.fetchRows( ('login', "foo") )
#
-import tstart
import string
import sys, zlib
@@ -361,7 +360,7 @@
def d_addColumn(self,col_name,ctype,size=None,primarykey = 0, notnull = 0,indexed=0,
default=None,unique=0,autoincrement=0,safeupdate=0,enum_values = None,
- relations=None,compress_ok=0,int_date=0):
+ relations=None,compress_ok=0,int_date=0,no_export=0):
self.__checkColumnLock()
@@ -381,6 +380,8 @@
options['notnull'] = notnull
if size:
options['size'] = size
+ if no_export:
+ options['no_export'] = no_export
if int_date:
if ctype != kInteger:
raise eInvalidData, "can't flag columns int_date unless they are kInteger"
diff -Nbru clearsilver-0.9.3/python/examples/base/wordwrap.py clearsilver-0.9.6/python/examples/base/wordwrap.py
--- clearsilver-0.9.3/python/examples/base/wordwrap.py Wed Dec 31 16:00:00 1969
+++ clearsilver-0.9.6/python/examples/base/wordwrap.py Fri Sep 12 16:05:57 2003
@@ -0,0 +1,50 @@
+"""
+WordWrapping
+"""
+
+
+import os, sys, string, time, getopt
+import re
+
+def WordWrap(text, cols=70, detect_paragraphs = 0, is_header = 0):
+ text = string.replace(text,"\r\n", "\n") # remove CRLF
+ def nlrepl(matchobj):
+ if matchobj.group(1) != ' ' and matchobj.group(2) != ' ':
+ repl_with = ' '
+ else:
+ repl_with = ''
+
+ return matchobj.group(1) + repl_with + matchobj.group(2)
+
+ if detect_paragraphs:
+ text = re.sub("([^\n])\n([^\n])",nlrepl,text)
+
+ body = []
+ i = 0
+ j = 0
+ ltext = len(text)
+
+ while i hdftest.out; \
- diff -brief hdftest.out hdftest.gold 2>%1 > /dev/null; \
+ diff --brief hdftest.out hdftest.gold > /dev/null 2>&1; \
return_code=$$?; \
if [ $$return_code -ne 0 ]; then \
diff hdftest.out hdftest.gold > hdftest.err; \
diff -Nbru clearsilver-0.9.3/util/filter.h clearsilver-0.9.6/util/filter.h
--- clearsilver-0.9.3/util/filter.h Fri May 10 17:41:07 2002
+++ clearsilver-0.9.6/util/filter.h Tue Sep 30 02:07:12 2003
@@ -19,8 +19,70 @@
#include "util/neo_misc.h"
#include "util/neo_err.h"
+/*
+ * Function: filter_wait - wrap waitpid to decode the exitcode and why
+ * your filter quit
+ * Description: filter_wait wraps the waitpid call and raises an error
+ * (with description) if the call failed. Note that if the
+ * ask for the exitcode and the process exited with a code
+ * other than zero, we don't raise an error. If you don't
+ * ask for the exitcode, and it is non-zero, we raise an
+ * error
+ * Input: pid -> the process identifier to wait for
+ * options -> the options to pass to waitpid (see wait(2))
+ * Output: exitcode -> the exitcode if the process existed normally
+ * Returns: NERR_SYSTEM, NERR_ASSERT
+ */
NEOERR *filter_wait(pid_t pid, int options, int *exitcode);
+
+/*
+ * Function: filter_create_fd - Create a sub process and return the
+ * requested pipes
+ * Description: filter_create_fd and filter_create_fp are what popen
+ * should have been: a mechanism to create sub processes
+ * and have pipes to all their input/output. The concept
+ * was taken from mutt, though python has something similar
+ * with popen3/popen4. You control which pipes the
+ * function returns by the fdin/fdout/fderr arguments. A
+ * NULL value means "don't create a pipe", a pointer to an
+ * int will cause the pipes to be created and the value
+ * of the file descriptor stored in the int. You will have
+ * to close(2) the file descriptors yourself.
+ * Input: cmd -> the sub command to execute. Will be executed with
+ * /bin/sh -c
+ * fdin -> pointer to return the stdin pipe, or NULL if you don't
+ * want the stdin pipe
+ * fdout -> pointer to return the stdout pipe, or NULL if you don't
+ * want the stdout pipe
+ * fderr -> pointer to return the stderr pipe, or NULL if you don't
+ * want the stderr pipe
+ * Output: fdin -> the stdin file descriptor of the sub process
+ * fdout -> the stdout file descriptor of the sub process
+ * fderr -> the stderr file descriptor of the sub process
+ * pid -> the pid of the sub process
+ * Returns: NERR_SYSTEM
+ */
NEOERR *filter_create_fd(char *cmd, int *fdin, int *fdout, int *fderr, pid_t *pid);
+
+/*
+ * Function: filter_create_fp - similar to filter_create_fd except with
+ * buffered FILE*
+ * Description: filter_create_fp is identical to filter_create_fd,
+ * except each of the pipes is wrapped in a buffered stdio FILE
+ * Input: cmd -> the sub command to execute. Will be executed with
+ * /bin/sh -c
+ * in -> pointer to return the stdin pipe, or NULL if you don't
+ * want the stdin pipe
+ * out -> pointer to return the stdout pipe, or NULL if you don't
+ * want the stdout pipe
+ * err -> pointer to return the stderr pipe, or NULL if you don't
+ * want the stderr pipe
+ * Output: in -> the stdin FILE of the sub process
+ * out -> the stdout FILE of the sub process
+ * err -> the stderr FILE of the sub process
+ * pid -> the pid of the sub process
+ * Returns: NERR_SYSTEM, NERR_IO
+ */
NEOERR *filter_create_fp(char *cmd, FILE **in, FILE **out, FILE **err, pid_t *pid);
__END_DECLS
diff -Nbru clearsilver-0.9.3/util/neo_err.c clearsilver-0.9.6/util/neo_err.c
--- clearsilver-0.9.3/util/neo_err.c Wed Apr 2 15:07:36 2003
+++ clearsilver-0.9.6/util/neo_err.c Tue Sep 16 16:37:42 2003
@@ -37,11 +37,18 @@
static ULIST *Errors = NULL;
static int Inited = 0;
+/* Set this to 1 to enable non-thread safe re-use of NEOERR data
+ * structures. This was a premature performance optimization that isn't
+ * thread safe, if we want it thread safe we need to add mutex code...
+ * which has its own performance penalties...
+ */
+static int UseFreeList = 0;
+
static NEOERR *_err_alloc(void)
{
NEOERR *err;
- if (FreeList == NULL)
+ if (!UseFreeList || FreeList == NULL)
{
err = (NEOERR *)calloc (1, sizeof (NEOERR));
if (err == NULL)
@@ -67,10 +74,17 @@
return 0;
if (err->next != NULL)
_err_free(err->next);
+ if (UseFreeList)
+ {
err->next = FreeList;
FreeList = err;
err->flags = 0;
err->desc[0] = '\0';
+ }
+ else
+ {
+ free(err);
+ }
return 0;
}
diff -Nbru clearsilver-0.9.3/util/neo_err.h clearsilver-0.9.6/util/neo_err.h
--- clearsilver-0.9.3/util/neo_err.h Wed Apr 2 15:07:36 2003
+++ clearsilver-0.9.6/util/neo_err.h Wed Sep 24 16:50:39 2003
@@ -109,7 +109,7 @@
*/
void nerr_log_error (NEOERR *err);
-#include "neo_str.h"
+#include "util/neo_str.h"
void nerr_error_string (NEOERR *err, STRING *str);
void nerr_error_traceback (NEOERR *err, STRING *str);
diff -Nbru clearsilver-0.9.3/util/neo_hdf.c clearsilver-0.9.6/util/neo_hdf.c
--- clearsilver-0.9.3/util/neo_hdf.c Tue Aug 26 17:55:49 2003
+++ clearsilver-0.9.6/util/neo_hdf.c Mon Oct 20 14:18:58 2003
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include "neo_misc.h"
#include "neo_err.h"
@@ -298,6 +299,33 @@
return defval;
}
+char* hdf_get_valuevf (HDF *hdf, char *namefmt, va_list ap)
+{
+ HDF *node;
+ char *name;
+
+ name = vsprintf_alloc(namefmt, ap);
+ if (name == NULL) return NULL;
+ if ((_walk_hdf(hdf, name, &node) == 0) && (node->value != NULL))
+ {
+ free(name);
+ return node->value;
+ }
+ free(name);
+ return NULL;
+}
+
+char* hdf_get_valuef (HDF *hdf, char *namefmt, ...)
+{
+ char *val;
+ va_list ap;
+
+ va_start(ap, namefmt);
+ val = hdf_get_valuevf(hdf, namefmt, ap);
+ va_end(ap);
+ return val;
+}
+
NEOERR* hdf_get_copy (HDF *hdf, char *name, char **value, char *defval)
{
HDF *node;
@@ -773,6 +801,41 @@
return nerr_pass(_set_value (hdf, dest, node->value, 0, 0, 0, NULL, NULL));
}
return nerr_raise (NERR_NOT_FOUND, "Unable to find %s", src);
+}
+
+NEOERR* hdf_set_valuevf (HDF *hdf, char *fmt, va_list ap)
+{
+ NEOERR *err;
+ char *k;
+ char *v;
+
+ k = vsprintf_alloc(fmt, ap);
+ if (k == NULL)
+ {
+ return nerr_raise(NERR_NOMEM, "Unable to allocate memory for format string");
+ }
+ v = strchr(k, '=');
+ if (v == NULL)
+ {
+ err = nerr_raise(NERR_ASSERT, "No equals found: %s", k);
+ free(k);
+ return err;
+ }
+ *v++ = '\0';
+ err = hdf_set_value(hdf, k, v);
+ free(k);
+ return nerr_pass(err);
+}
+
+NEOERR* hdf_set_valuef (HDF *hdf, char *fmt, ...)
+{
+ NEOERR *err;
+ va_list ap;
+
+ va_start(ap, fmt);
+ err = hdf_set_valuevf(hdf, fmt, ap);
+ va_end(ap);
+ return nerr_pass(err);
}
NEOERR* hdf_get_node (HDF *hdf, char *name, HDF **ret)
diff -Nbru clearsilver-0.9.3/util/neo_hdf.h clearsilver-0.9.6/util/neo_hdf.h
--- clearsilver-0.9.3/util/neo_hdf.h Mon Aug 18 13:40:03 2003
+++ clearsilver-0.9.6/util/neo_hdf.h Mon Oct 20 14:18:59 2003
@@ -14,9 +14,8 @@
__BEGIN_DECLS
#include
-#include "neo_err.h"
-#include "neo_hash.h"
-#include "ulist.h"
+#include "util/neo_err.h"
+#include "util/neo_hash.h"
#define FORCE_HASH_AT 10
@@ -50,62 +49,491 @@
struct _hdf *last_child;
} HDF;
+/*
+ * Function: hdf_init - Initialize an HDF data set
+ * Description: hdf_init initializes an HDF data set and returns the
+ * pointer to the top node in the data set.
+ * Input: hdf - pointer to an HDF pointer
+ * Output: hdf - allocated hdf node
+ * Returns: NERR_NOMEM - unable to allocate memory for dataset
+ */
NEOERR* hdf_init (HDF **hdf);
+
+/*
+ * Function: hdf_destroy - deallocate an HDF data set
+ * Description: hdf_destroy is used to deallocate all memory associated
+ * with an hdf data set. Although you can pass an HDF node
+ * as an argument to this function, you are likely to cause
+ * a segfault if you continue to access the data set. In
+ * the future, we may restrict hdf_destroy so it only works
+ * on the top level node.
+ * Input: hdf - pointer to an HDF data set allocated with hdf_init
+ * Output: None
+ * Returns: None
+ */
void hdf_destroy (HDF **hdf);
+/*
+ * Function: hdf_get_int_value - Return the integer value of a point in
+ * the data set
+ * Description: hdf_get_int_value walks the HDF data set pointed to by
+ * hdf to name, and returns the value of that node
+ * converted to an integer. If that node does not exist,
+ * or it does not contain a number, the defval is returned.
+ * Input: hdf -> a node in an HDF data set
+ * name -> the name of a node to walk to in the data set
+ * defval -> value to return in case of error or if the node
+ * doesn't exist
+ * Output: None
+ * Returns: The integer value of the node, or the defval
+ */
int hdf_get_int_value (HDF *hdf, char *name, int defval);
+
+/*
+ * Function: hdf_get_value - Return the value of a node in the data set
+ * Description: hdf_get_value walks the data set pointed to by hdf via
+ * name and returns the string value located there, or
+ * defval if the node doesn't exist
+ * Input: hdf -> the dataset node to start from
+ * name -> the name to walk the data set to
+ * defval -> the default value to return if the node doesn't
+ * exist
+ * Output: None
+ * Returns: A pointer to the string stored in the data set, or defval.
+ * The data set maintains ownership of the string, if you want
+ * a copy you either have to call strdup yourself, or use
+ * hdf_get_copy
+ */
char *hdf_get_value (HDF *hdf, char *name, char *defval);
+
+/*
+ * Function: hdf_get_valuevf - Return the value of a node in the data set
+ * Description: hdf_get_valuevf walks the data set pointed to by hdf via
+ * namefmt printf expanded with varargs ap, and returns the
+ * string value located there, or NULL if it doesn't exist.
+ * This differs from hdf_get_value in that there is no
+ * default value possible.
+ * Input: hdf -> the dataset node to start from
+ * namefmt -> the format string
+ * ap -> va_list of varargs
+ * Output: None
+ * Returns: A pointer to the string stored in the data set, or NULL.
+ * The data set maintains ownership of the string, if you want
+ * a copy you either have to call strdup yourself.
+ */
+char* hdf_get_valuevf (HDF *hdf, char *namefmt, va_list ap);
+
+/*
+ * Function: hdf_get_valuef - Return the value of a node in the data set
+ * Description: hdf_get_valuef walks the data set pointed to by hdf via
+ * namefmt printf expanded with varargs, and returns the
+ * string value located there, or NULL if it doesn't exist.
+ * This differs from hdf_get_value in that there is no
+ * default value possible.
+ * Input: hdf -> the dataset node to start from
+ * namefmt -> the printf-style format string
+ * ... -> arguments to fill out namefmt
+ * Output: None
+ * Returns: A pointer to the string stored in the data set, or NULL.
+ * The data set maintains ownership of the string, if you want
+ * a copy you either have to call strdup yourself.
+ */
+char* hdf_get_valuef (HDF *hdf, char *namefmt, ...);
+
+/*
+ * Function: hdf_get_copy - Returns a copy of a string in the HDF data set
+ * Description: hdf_get_copy is similar to hdf_get_value, except that it
+ * returns an malloc'd copy of the string.
+ * Input: hdf -> the dataset node to start from
+ * name -> the name to walk the data set to
+ * defval -> the default value to return if the node doesn't
+ * exist
+ * Output: value -> the allocated string (if defval = NULL, then value
+ * will be NULL if defval is used)
+ * Returns: NERR_NOMEM if unable to allocate the new copy
+ */
NEOERR* hdf_get_copy (HDF *hdf, char *name, char **value, char *defval);
+/*
+ * Function: hdf_get_obj - return the HDF data set node at a named location
+ * Description: hdf_get_obj walks the dataset given by hdf to the node
+ * named name, and then returns the pointer to that node
+ * Input: hdf -> the dataset node to start from
+ * name -> the name to walk to
+ * Output: None
+ * Returns: the pointer to the named node, or NULL if it doesn't exist
+ */
HDF* hdf_get_obj (HDF *hdf, char *name);
-/* Always returns the node (except on NOMEM error). Creates if
- * necessary */
+
+/*
+ * Function: hdf_get_node - Similar to hdf_get_obj except all the nodes
+ * are created if the don't exist.
+ * Description: hdf_get_node is similar to hdf_get_obj, except instead
+ * of stopping if it can't find a node in the tree, it will
+ * create all of the nodes necessary to hand you back the
+ * node you ask for. Nodes are created with no value.
+ * Input: hdf -> the dataset node to start from
+ * name -> the name to walk to
+ * Output: ret -> the dataset node you asked for
+ * Returns: NERR_NOMEM - unable to allocate new nodes
+ */
NEOERR * hdf_get_node (HDF *hdf, char *name, HDF **ret);
+
+/*
+ * Function: hdf_get_child - return the first child of the named node
+ * Description: hdf_get_child will walk the dataset starting at hdf to
+ * name, and return the first child of that node
+ * Input: hdf -> the dataset node to start from
+ * name -> the name to walk to
+ * Output: None
+ * Returns: The first child of the named dataset node or NULL if the
+ * node is not found (or it has no children)
+ */
HDF* hdf_get_child (HDF *hdf, char *name);
+
+/*
+ * Function: hdf_get_attr -
+ * Description:
+ * Input:
+ * Output:
+ * Returns:
+ */
HDF_ATTR* hdf_get_attr (HDF *hdf, char *name);
+
+/*
+ * Function: hdf_set_attr -
+ * Description:
+ * Input:
+ * Output:
+ * Returns:
+ */
NEOERR* hdf_set_attr (HDF *hdf, char *name, char *key, char *value);
+
+/*
+ * Function: hdf_obj_child - Return the first child of a dataset node
+ * Description: hdf_obj_child and the other hdf_obj_ functions are
+ * accessors to the HDF dataset. Although we do not
+ * currently "hide" the HDF struct implementation, we
+ * recommend you use the accessor functions instead of
+ * accessing the values directly.
+ * Input: hdf -> the hdf dataset node
+ * Output: None
+ * Returns: The pointer to the first child, or NULL if there is none
+ */
HDF* hdf_obj_child (HDF *hdf);
+
+/*
+ * Function: hdf_obj_next - Return the next node of a dataset level
+ * Description: hdf_obj_next is an accessor function for the HDF struct
+ * Input: hdf -> the hdf dataset node
+ * Output: None
+ * Returns: The pointer to the next node, or NULL if there is none
+ */
HDF* hdf_obj_next (HDF *hdf);
+
+/*
+ * Function: hdf_obj_top - Return the pointer to the top dataset node
+ * Description: hdf_obj_top is an accessor function which returns a
+ * pointer to the top of the dataset, the node which was
+ * returned by hdf_init. This is most useful for
+ * implementations of language wrappers where individual
+ * nodes are tied garbage colletion wise to the top node of
+ * the data set
+ * Input: hdf -> the hdf dataset node
+ * Output: None
+ * Returns: The pointer to the top node
+ */
HDF* hdf_obj_top (HDF *hdf);
+
+/*
+ * Function: hdf_obj_attr - Return the HDF Attributes for a node
+ * Description:
+ * Input:
+ * Output:
+ * Returns:
+ */
HDF_ATTR* hdf_obj_attr (HDF *hdf);
+
+/*
+ * Function: hdf_obj_name - Return the name of a node
+ * Description: hdf_obj_name is an accessor function for a datset node
+ * which returns the name of the node. This is just the
+ * local name, and not the full path.
+ * Input: hdf -> the hdf dataset node
+ * Output: None
+ * Returns: The name of the node. If this is the top node, the name is
+ * NULL.
+ */
char* hdf_obj_name (HDF *hdf);
+
+/*
+ * Function: hdf_obj_value - Return the value of a node
+ * Description: hdf_obj_value is an accessor function for a dataset node
+ * which returns the value of the node, or NULL if the node
+ * has no value. This is not a copy of the value, so the
+ * node retains ownership of the value
+ * Input: hdf -> the hdf dataset node
+ * Output: None
+ * Returns: The value of the node, or NULL if it has no value
+ */
char* hdf_obj_value (HDF *hdf);
+/*
+ * Function: hdf_set_value - Set the value of a named node
+ * Description: hdf_set_value will set the value of a named node. All
+ * of the interstitial nodes which don't exist will be
+ * created with a value of NULL. Existing nodes are not
+ * modified. New nodes are created at the end of the list.
+ * If a list of nodes exceeds FORCE_HASH_AT, then a HASH
+ * will be created at that level and all of the nodes will
+ * be added to the hash for faster lookup times.
+ * The copy of the value will be made which the dataset
+ * will own.
+ * Input: hdf -> the pointer to the hdf dataset
+ * name -> the named node to walk to
+ * value -> the value to set the node to
+ * Output: None
+ * Returns: NERR_NOMEM
+ */
NEOERR* hdf_set_value (HDF *hdf, char *name, char *value);
+
+/*
+ * Function: hdf_set_valuef - Set the value of a named node
+ * Description: hdf_set_valuef is a convenience function that wraps
+ * hdf_set_value. Due to limitations of C, the fmt is in
+ * the format "name=value", where we will first format the
+ * entire string, and then break it at the first (from the
+ * left) equal sign (=) and use the left portion as the
+ * name and the right portion as the value. This function
+ * is somewhat inefficient in that it first allocates the
+ * full name=value, and then the call to hdf_set_value
+ * duplicates the value portion, and then we free the
+ * name=value.
+ * Currently, we don't strip whitespace from the key or
+ * value. In the future, this function might work more
+ * like reading a single line of an HDF string or file,
+ * allowing for attributes and symlinks to be specified...
+ * maybe.
+ * Input: hdf -> the pointer to the hdf dataset
+ * fmt -> the name=value printf(3) format string
+ * Output: None
+ * Returns: NERR_NOMEM
+ */
+NEOERR* hdf_set_valuef (HDF *hdf, char *fmt, ...);
+NEOERR* hdf_set_valuevf (HDF *hdf, char *fmt, va_list ap);
+
+/*
+ * Function: hdf_set_int_value - Set the value of a named node to a number
+ * Description: hdf_set_int_value is a helper function that maps an
+ * integer to a string, and then calls hdf_set_value with
+ * that string
+ * Input: hdf -> the pointer to the hdf dataset
+ * name -> the named node to walk to
+ * value -> the value to set the node to
+ * Output: None
+ * Returns: NERR_NOMEM
+ */
NEOERR* hdf_set_int_value (HDF *hdf, char *name, int value);
+
+/*
+ * Function: hdf_set_copy -> Copy a value from one location in the
+ * dataset to another
+ * Description: hdf_set_copy first walks the hdf dataset to the named src
+ * node, and then copies that value to the named dest node.
+ * If the src node is not found, an error is raised.
+ * Input: hdf -> the pointer to the dataset node
+ * dest -> the name of the destination node
+ * src -> the name of the source node
+ * Output: None
+ * Returns: NERR_NOMEM, NERR_NOT_FOUND
+ */
NEOERR* hdf_set_copy (HDF *hdf, char *dest, char *src);
+
+/*
+ * Function: hdf_set_buf - Set the value of a node without duplicating
+ * the value
+ * Description: hdf_set_buf is similar to hdf_set_value, except the
+ * dataset takes ownership of the value instead of making a
+ * copy of it. The dataset assumes that value was
+ * malloc'd, since it will attempt to free it when
+ * hdf_destroy is called
+ * Input: hdf -> the hdf dataset node
+ * name -> the name to walk to
+ * value -> the malloc'd value
+ * Output: None
+ * Returns: NERR_NOMEM - unable to allocate a node
+ */
+
NEOERR* hdf_set_buf (HDF *hdf, char *name, char *value);
+/*
+ * Function: hdf_set_symlink - Set part of the tree to link to another
+ * Description: hdf_set_symlink creates a link between two sections of
+ * an HDF dataset. The link is "by name" hence the term
+ * "symlink". This means that the destination node does
+ * not need to exist. Any attempt to access the source
+ * node will cause the function to walk to the dest node,
+ * and then continue walking from there. Using symlinks
+ * can "hide" values in the dataset since you won't be able
+ * to access any children of the linked node directly,
+ * though dumps and other things which access the data
+ * structure directly will bypass the symlink. Use this
+ * feature sparingly as its likely to surprise you.
+ * Input: hdf -> the dataset node
+ * src -> the source node name
+ * dest -> the destination node name (from the top of the
+ * dataset, not relative names)
+ * Output: None
+ * Returns: NERR_NOMEM
+ */
NEOERR *hdf_set_symlink (HDF *hdf, char *src, char *dest);
/*
* Function: hdf_sort_obj - sort the children of an HDF node
* Description: hdf_sort_obj will sort the children of an HDF node,
* based on the given comparison function.
+ * This function works by creating an array of the pointers
+ * for each child object of h, using qsort to sort that
+ * array, and then re-ordering the linked list of children
+ * to the new order. The qsort compare function uses a
+ * pointer to the value in the array, which in our case is
+ * a pointer to an HDF struct, so your comparison function
+ * should work on HDF ** pointers.
* Input: h - HDF node
* compareFunc - function which returns 1,0,-1 depending on some
- * criteria. Given two children of h
+ * criteria. The arguments to this sort function
+ * are pointers to pointers to HDF elements. For
+ * example:
+ * int sortByName(const void *a, const void *b) {
+ * HDF **ha = (HDF **)a;
+ * HDF **hb = (HDF **)b;
+ *
+ * return strcasecmp(hdf_obj_name(*ha), hdf_obj_name(*hb));
+ * }
+ *
* Output: None (h children will be sorted)
- * Return: None
+ * Return: NERR_NOMEM
*/
NEOERR *hdf_sort_obj(HDF *h, int (*compareFunc)(const void *, const void *));
+/*
+ * Function: hdf_read_file - read an HDF data file
+ * Description:
+ * Input:
+ * Output:
+ * Returns: NERR_IO, NERR_NOMEM, NERR_PARSE
+ */
NEOERR* hdf_read_file (HDF *hdf, char *path);
+
+/*
+ * Function: hdf_write_file - write an HDF data file
+ * Description:
+ * Input:
+ * Output:
+ * Returns: NERR_IO
+ */
NEOERR* hdf_write_file (HDF *hdf, char *path);
+
+/*
+ * Function: hdf_write_file_atomic - write an HDF data file atomically
+ * Description: hdf_write_file_atomic is similar to hdf_write_file,
+ * except the new file is created with a unique name and
+ * then rename(2) is used to atomically replace the old
+ * file with the new file
+ * Input:
+ * Output:
+ * Returns: NERR_IO
+ */
NEOERR* hdf_write_file_atomic (HDF *hdf, char *path);
+/*
+ * Function: hdf_read_string - read an HDF string
+ * Description:
+ * Input:
+ * Output:
+ * Returns: NERR_NOMEM, NERR_PARSE
+ */
NEOERR* hdf_read_string (HDF *hdf, char *s);
+
+/*
+ * Function: hdf_read_string_ignore - Read an HDF string and ignore errors
+ * Description:
+ * Input:
+ * Output:
+ * Returns: NERR_NOMEM
+ */
NEOERR* hdf_read_string_ignore (HDF *hdf, char *s, int ignore);
+
+/*
+ * Function: hdf_write_string - serialize an HDF dataset to a string
+ * Description:
+ * Input:
+ * Output:
+ * Returns: NERR_NOMEM
+ */
NEOERR* hdf_write_string (HDF *hdf, char **s);
+/*
+ * Function: hdf_dump - dump an HDF dataset to stdout
+ * Description:
+ * Input:
+ * Output:
+ * Returns:
+ */
NEOERR* hdf_dump (HDF *hdf, char *prefix);
+
+/*
+ * Function: hdf_dump_format - dump an HDF dataset to FILE *fp
+ * Description:
+ * Input:
+ * Output:
+ * Returns:
+ */
NEOERR* hdf_dump_format (HDF *hdf, int lvl, FILE *fp);
+
+/*
+ * Function: hdf_dump_str - dump an HDF dataset to STRING
+ * Description:
+ * Input:
+ * Output:
+ * Returns:
+ */
NEOERR* hdf_dump_str(HDF *hdf, char *prefix, int compact, STRING *str);
+/*
+ * Function: hdf_remove_tree - delete a subtree of an HDF dataset
+ * Description:
+ * Input:
+ * Output:
+ * Returns:
+ */
NEOERR* hdf_remove_tree (HDF *hdf, char *name);
+
+/*
+ * Function: hdf_copy - copy part of an HDF dataset to another
+ * Description: hdf_copy is a deep copy of an HDF tree pointed to by
+ * src to the named node of dest. dest and src need not be
+ * part of the same data set
+ * Input: dest_hdf -> the destination dataset
+ * name -> the name of the destination node
+ * src -> the hdf dataset to copy to the destination
+ * Output: None
+ * Returns: NERR_NOMEM, NERR_NOT_FOUND
+ */
NEOERR* hdf_copy (HDF *dest_hdf, char *name, HDF *src);
-/* Utility function */
+/*
+ * Function: hdf_search_path - Find a file given a search path in HDF
+ * Description: hdf_search_path is a convenience/utility function that
+ * searches for relative filenames in a search path. The
+ * search path is the list given by the children of
+ * hdf.loadpaths.
+ * Input: hdf -> the hdf dataset to use
+ * path -> the relative path
+ * full -> a pointer to a _POSIX_PATH_MAX buffer
+ * Output: full -> the full path of the file
+ * Returns: NERR_NOT_FOUND if the file wasn't found in the search path
+ */
NEOERR* hdf_search_path (HDF *hdf, char *path, char *full);
__END_DECLS
diff -Nbru clearsilver-0.9.3/util/neo_str.c clearsilver-0.9.6/util/neo_str.c
--- clearsilver-0.9.3/util/neo_str.c Wed Apr 2 19:03:01 2003
+++ clearsilver-0.9.6/util/neo_str.c Wed Oct 8 16:43:02 2003
@@ -140,7 +140,7 @@
return STATUS_OK;
}
-/* currently, this requires a C99 compliant snprintf */
+/* this is much more efficient with C99 snprintfs... */
NEOERR *string_appendvf (STRING *str, char *fmt, va_list ap)
{
NEOERR *err;
@@ -151,14 +151,29 @@
va_copy(tmp, ap);
/* determine length */
size = sizeof (buf);
- bl = vsnprintf (buf, size, fmt, ap);
+ bl = vsnprintf (buf, size, fmt, tmp);
if (bl > -1 && bl < size)
return string_appendn (str, buf, bl);
+ /* Handle non-C99 snprintfs (requires extra malloc/free and copy) */
+ if (bl == -1)
+ {
+ char *a_buf;
+
+ va_copy(tmp, ap);
+ a_buf = vnsprintf_alloc(size*2, fmt, tmp);
+ if (a_buf == NULL)
+ return nerr_raise(NERR_NOMEM,
+ "Unable to allocate memory for formatted string");
+ err = string_append(str, a_buf);
+ free(a_buf);
+ return nerr_pass(err);
+ }
+
err = string_check_length (str, bl+1);
if (err != STATUS_OK) return nerr_pass (err);
- va_copy(ap, tmp);
- vsprintf (str->buf + str->len, fmt, ap);
+ va_copy(tmp, ap);
+ vsprintf (str->buf + str->len, fmt, tmp);
str->len += bl;
str->buf[str->len] = '\0';
@@ -252,12 +267,38 @@
arr->count = 0;
}
+/* Mostly used by vprintf_alloc for non-C99 compliant snprintfs,
+ * this is like vsprintf_alloc except it takes a "suggested" size */
+char *vnsprintf_alloc (int start_size, char *fmt, va_list ap)
+{
+ char *b = NULL;
+ int bl, size;
+ va_list tmp;
+
+ size = start_size;
+
+ b = (char *) malloc (size * sizeof(char));
+ if (b == NULL) return NULL;
+ while (1)
+ {
+ va_copy(tmp, ap);
+ bl = vsnprintf (b, size, fmt, tmp);
+ if (bl > -1 && bl < size)
+ return b;
+ if (bl > -1)
+ size = bl + 1;
+ else
+ size *= 2;
+ b = (char *) realloc (b, size * sizeof(char));
+ if (b == NULL) return NULL;
+ }
+}
+
/* This works better with a C99 compliant vsnprintf, but should work ok
* with versions that return a -1 if it overflows the buffer */
char *vsprintf_alloc (char *fmt, va_list ap)
{
char buf[4096];
- char *b = NULL;
int bl, size;
va_list tmp;
@@ -266,7 +307,7 @@
va_copy(tmp, ap);
size = sizeof (buf);
- bl = vsnprintf (buf, sizeof (buf), fmt, ap);
+ bl = vsnprintf (buf, sizeof (buf), fmt, tmp);
if (bl > -1 && bl < size)
return strdup (buf);
@@ -275,20 +316,10 @@
else
size *= 2;
- b = (char *) malloc (size * sizeof(char));
- if (b == NULL) return NULL;
- while (1)
- {
- va_copy(ap, tmp);
- bl = vsnprintf (b, size, fmt, ap);
- if (bl > -1 && bl < size)
- return b;
- size *= 2;
- b = (char *) realloc (b, size * sizeof(char));
- if (b == NULL) return NULL;
- }
+ return vnsprintf_alloc(size, fmt, ap);
}
+
char *sprintf_alloc (char *fmt, ...)
{
va_list ap;
@@ -296,6 +327,23 @@
va_start (ap, fmt);
r = vsprintf_alloc (fmt, ap);
+ va_end (ap);
+ return r;
+}
+
+/* This is mostly just here for completeness, I doubt anyone would use
+ * this (its more efficient (time-wise) if start_size is bigger than the
+ * resulting string. Its less efficient than sprintf_alloc if we have a
+ * C99 snprintf and it doesn't fit in start_size.
+ * BTW: If you are really worried about the efficiency of these
+ * functions, maybe you shouldn't be using them in the first place... */
+char *nsprintf_alloc (int start_size, char *fmt, ...)
+{
+ va_list ap;
+ char *r;
+
+ va_start (ap, fmt);
+ r = vnsprintf_alloc (start_size, fmt, ap);
va_end (ap);
return r;
}
diff -Nbru clearsilver-0.9.3/util/neo_str.h clearsilver-0.9.6/util/neo_str.h
--- clearsilver-0.9.3/util/neo_str.h Fri Aug 30 17:39:46 2002
+++ clearsilver-0.9.6/util/neo_str.h Wed Oct 8 16:43:02 2003
@@ -27,7 +27,9 @@
void neos_lower (char *s);
char *sprintf_alloc (char *fmt, ...);
+char *nsprintf_alloc (int start_size, char *fmt, ...);
char *vsprintf_alloc (char *fmt, va_list ap);
+char *vnsprintf_alloc (int start_size, char *fmt, va_list ap);
typedef struct _string
{
@@ -58,7 +60,7 @@
void string_clear (STRING *str);
/* typedef struct _ulist ULIST; */
-#include "ulist.h"
+#include "util/ulist.h"
NEOERR *string_array_split (ULIST **list, char *s, char *sep, int max);
BOOL reg_search (char *re, char *str);
diff -Nbru clearsilver-0.9.3/util/skiplist.h clearsilver-0.9.6/util/skiplist.h
--- clearsilver-0.9.3/util/skiplist.h Wed Apr 2 15:07:36 2003
+++ clearsilver-0.9.6/util/skiplist.h Wed Sep 24 16:50:39 2003
@@ -17,7 +17,7 @@
#ifndef __SKIPLIST_H_
#define __SKIPLIST_H_
-#include
+#include "util/neo_err.h"
__BEGIN_DECLS
diff -Nbru clearsilver-0.9.3/util/test/Makefile clearsilver-0.9.6/util/test/Makefile
--- clearsilver-0.9.3/util/test/Makefile Mon Mar 31 17:45:55 2003
+++ clearsilver-0.9.6/util/test/Makefile Wed Oct 8 16:46:26 2003
@@ -10,6 +10,10 @@
HDFTEST_SRC = hdftest.c
HDFTEST_OBJ = $(HDFTEST_SRC:%.c=%.o)
+HDFSORTTEST_EXE = hdf_sort_test
+HDFSORTTEST_SRC = hdf_sort_test.c
+HDFSORTTEST_OBJ = $(HDFSORTTEST_SRC:%.c=%.o)
+
HDFLOADTEST_EXE = hdfloadtest
HDFLOADTEST_SRC = hdfloadtest.c
HDFLOADTEST_OBJ = $(HDFLOADTEST_SRC:%.c=%.o)
@@ -38,6 +42,7 @@
LIBS += -L$(LIB_DIR) -lneo_utl
TARGETS = $(HDFTEST_EXE) $(LISTDIRTEST_EXE) $(HDFCOPYTEST_EXE) \
+ $(HDFSORTTEST_EXE) \
$(HDFLOADTEST_EXE) $(NETTEST_EXE) $(DATETEST_EXE) \
$(HASHTEST_EXE)
@@ -45,6 +50,9 @@
$(HDFTEST_EXE): $(HDFTEST_OBJ) $(NTR_LIB)
$(LD) $@ $(HDFTEST_OBJ) $(LIBS)
+
+$(HDFSORTTEST_EXE): $(HDFSORTTEST_OBJ) $(NTR_LIB)
+ $(LD) $@ $(HDFSORTTEST_OBJ) $(LIBS)
$(HDFLOADTEST_EXE): $(HDFLOADTEST_OBJ) $(NTR_LIB)
$(LD) $@ $(HDFLOADTEST_OBJ) $(LIBS) # -lefence
diff -Nbru clearsilver-0.9.3/util/test/hdf_sort_test.c clearsilver-0.9.6/util/test/hdf_sort_test.c
--- clearsilver-0.9.3/util/test/hdf_sort_test.c Wed Dec 31 16:00:00 1969
+++ clearsilver-0.9.6/util/test/hdf_sort_test.c Wed Oct 8 16:46:26 2003
@@ -0,0 +1,102 @@
+
+#include "cs_config.h"
+#include
+#include
+#include "util/neo_misc.h"
+#include "util/neo_hdf.h"
+#include "util/neo_rand.h"
+
+NEOERR* hdf_set_valuef(HDF *hdf, char *namefmt, char *valuefmt, ...)
+{
+ char newstr[2048];
+ char one[2];
+ va_list ap;
+ char *nametok;
+ char *valtok;
+
+ char newfmt[2048];
+
+
+ one[0]=(char)1;
+ one[1]=(char)0;
+
+ snprintf(newfmt,2048,"%s%s%s",namefmt,one,valuefmt);
+
+ va_start(ap, valuefmt);
+ vsnprintf (newstr, 1024, newfmt, ap);
+ va_end(ap);
+
+ /* split it at 1 */
+ nametok=strtok(newstr,one);
+ valtok=strtok(NULL,one);
+
+
+ return hdf_set_value(hdf,nametok,valtok);
+}
+
+
+int TestCompare(const void* pa, const void* pb)
+{
+ HDF **a = (HDF **)pa;
+ HDF **b = (HDF **)pb;
+ float aVal,bVal;
+
+ aVal = atof(hdf_get_value(*a,"val","0"));
+ bVal = atof(hdf_get_value(*b,"val","0"));
+
+ printf("TestCompare aVal=%f [%s] bVal=%f [%s]\n",aVal,hdf_get_value(*a,"name","?"),bVal,hdf_get_value(*b,"name","?"));
+
+ if (aVal
typedef struct _column