diff -r 000000000000 -r bc8c9a11cbfc src/xexpr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/xexpr.c Wed Oct 10 22:58:21 2012 +0100 @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include + +gboolean dump_tree,dump_result,test_result,do_xinclude; +gchar **files; + +gboolean trace_symbol(const gchar *option_name,const gchar *value,gpointer data, + GError **err) +{ + Xexpr *xexpr=data; + xexpr_start_tracing(xexpr,value); + return TRUE; +} + +gboolean set_param(const gchar *option_name,const gchar *value,gpointer data, + GError **err) +{ + const char *s; + char *endptr; + double d,integer; + gchar *name; + XexprConstant *arg; + Xexpr *xexpr=data; + s=strchr(value,','); + if (!s) + { + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE, + "No comma found in --param argument \"%s\"",value); + return FALSE; + } + name=g_strndup(value,s-value); + d=strtod(s+1,&endptr); + if (!d || *endptr) + { + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE, + "Invalid number in --param argument: \"%s\"",s); + return FALSE; + } + if (!modf(d,&integer)) + arg=xexpr_new_integer(integer); + else + arg=xexpr_new_number(d); + xexpr_var_set(xexpr,name,arg); + xexpr_constant_free(arg); + return TRUE; +} + +gboolean set_string_param(const gchar *option_name,const gchar *value, + gpointer data,GError **err) +{ + const char *s; + char *endptr; + double d,integer; + gchar *name; + XexprConstant *arg; + Xexpr *xexpr=data; + s=strchr(value,','); + if (!s) + { + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE, + "No comma found in --stringparam argument \"%s\"",value); + return FALSE; + } + name=g_strndup(value,s-value); + arg=xexpr_new_string(s+1,-1); + xexpr_var_set(xexpr,name,arg); + xexpr_constant_free(arg); + return TRUE; +} + +static GOptionEntry entries[]={ + { "dump-tree",'d',0,G_OPTION_ARG_NONE,&dump_tree,"Dump parsed file",NULL }, + { "dump-result",'D',0,G_OPTION_ARG_NONE,&dump_result,"Dump result",NULL }, + { "test-result",'t',0,G_OPTION_ARG_NONE,&test_result,"Test result",NULL }, + { "trace",'T',0,G_OPTION_ARG_CALLBACK,trace_symbol,"Trace symbol",NULL }, + { G_OPTION_REMAINING,0,0,G_OPTION_ARG_FILENAME_ARRAY,&files,NULL, + "[]" }, + { "xinclude",0,0,G_OPTION_ARG_NONE,&do_xinclude,"Do XInclude processing", + NULL }, + { "param",0,0,G_OPTION_ARG_CALLBACK,set_param, + "Pass a (parameter,number) pair",NULL }, + { "stringparam",0,0,G_OPTION_ARG_CALLBACK,set_string_param, + "Pass a (parameter,string) pair",NULL }, + { NULL } +}; + +gboolean set_variable(gpointer key,gpointer value,gpointer data) +{ + xexpr_var_set(data,key,value); + return FALSE; +} + +gboolean run_xexpr(Xexpr *xexpr,xmlDocPtr doc,const char *filename) +{ + gboolean retval=TRUE; + GError *err=NULL; + Xexpr *sub,*result; + sub=xexpr_sub(xexpr); + xexpr_environment_foreach(xexpr_get_environment(xexpr),set_variable,sub); + if (!xexpr_parse_node(sub,xmlDocGetRootElement(doc),&err)) + { + fprintf(stderr,"%s: %s\n",filename,err->message); + exit(1); + } + if (dump_tree) + { + xexpr_dump(sub,stdout); + putchar('\n'); + } + else + { + result=xexpr_evaluate(sub,&err); + if (err) + { + fprintf(stderr,"%s: %s\n",filename,err->message); + g_clear_error(&err); + xexpr_free(sub); + return FALSE; + } + if (dump_result) + { + printf("\nResult: "); + xexpr_dump(result,stdout); + putchar('\n'); + } + if (test_result) + retval=xexpr_test(result,NULL); + xexpr_free(result); + } + xexpr_free(sub); + return retval; +} + +int main(int argc,char **argv) +{ + int i; + xmlDocPtr doc; + int xml_options=XML_PARSE_NOENT; + gboolean result=TRUE; + GError *err=NULL; + GOptionGroup *group; + GOptionContext *context; + Xexpr *xexpr; + xexpr=xexpr_new(); + context=g_option_context_new("- XEXPR interpreter"); + group=g_option_group_new(NULL,NULL,NULL,xexpr,NULL); + g_option_group_add_entries(group,entries); + g_option_context_set_main_group(context,group); + if (!g_option_context_parse(context,&argc,&argv,&err)) + { + fprintf(stderr,"%s\n",err->message); + exit(1); + } + if (do_xinclude) + xml_options|=XML_PARSE_XINCLUDE|XML_PARSE_NOXINCNODE; + if (files && files[0]) + { + for(i=0;files[i];i++) + { + doc=xmlReadFile(files[i],NULL,xml_options); + if (!doc) + result=FALSE; + else + { + if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0) + result=FALSE; + else if (!run_xexpr(xexpr,doc,files[i])) + result=FALSE; + xmlFreeDoc(doc); + } + } + } + else + { + doc=xmlReadFd(0,NULL,NULL,xml_options); + if (!doc) + result=FALSE; + else + { + if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0) + result=FALSE; + else if (!run_xexpr(xexpr,doc,"stdin")) + result=FALSE; + xmlFreeDoc(doc); + } + } + xexpr_free(xexpr); + exit(result?0:1); +}