#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); }