1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/xexpr.c Wed Oct 10 22:58:21 2012 +0100
1.3 @@ -0,0 +1,193 @@
1.4 +#include <stdlib.h>
1.5 +#include <string.h>
1.6 +#include <math.h>
1.7 +#include <glib.h>
1.8 +#include <libxml/parser.h>
1.9 +#include <libxexpr/xexpr.h>
1.10 +
1.11 +gboolean dump_tree,dump_result,test_result,do_xinclude;
1.12 +gchar **files;
1.13 +
1.14 +gboolean trace_symbol(const gchar *option_name,const gchar *value,gpointer data,
1.15 + GError **err)
1.16 +{
1.17 + Xexpr *xexpr=data;
1.18 + xexpr_start_tracing(xexpr,value);
1.19 + return TRUE;
1.20 +}
1.21 +
1.22 +gboolean set_param(const gchar *option_name,const gchar *value,gpointer data,
1.23 + GError **err)
1.24 +{
1.25 + const char *s;
1.26 + char *endptr;
1.27 + double d,integer;
1.28 + gchar *name;
1.29 + XexprConstant *arg;
1.30 + Xexpr *xexpr=data;
1.31 + s=strchr(value,',');
1.32 + if (!s)
1.33 + {
1.34 + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
1.35 + "No comma found in --param argument \"%s\"",value);
1.36 + return FALSE;
1.37 + }
1.38 + name=g_strndup(value,s-value);
1.39 + d=strtod(s+1,&endptr);
1.40 + if (!d || *endptr)
1.41 + {
1.42 + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
1.43 + "Invalid number in --param argument: \"%s\"",s);
1.44 + return FALSE;
1.45 + }
1.46 + if (!modf(d,&integer))
1.47 + arg=xexpr_new_integer(integer);
1.48 + else
1.49 + arg=xexpr_new_number(d);
1.50 + xexpr_var_set(xexpr,name,arg);
1.51 + xexpr_constant_free(arg);
1.52 + return TRUE;
1.53 +}
1.54 +
1.55 +gboolean set_string_param(const gchar *option_name,const gchar *value,
1.56 + gpointer data,GError **err)
1.57 +{
1.58 + const char *s;
1.59 + char *endptr;
1.60 + double d,integer;
1.61 + gchar *name;
1.62 + XexprConstant *arg;
1.63 + Xexpr *xexpr=data;
1.64 + s=strchr(value,',');
1.65 + if (!s)
1.66 + {
1.67 + g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
1.68 + "No comma found in --stringparam argument \"%s\"",value);
1.69 + return FALSE;
1.70 + }
1.71 + name=g_strndup(value,s-value);
1.72 + arg=xexpr_new_string(s+1,-1);
1.73 + xexpr_var_set(xexpr,name,arg);
1.74 + xexpr_constant_free(arg);
1.75 + return TRUE;
1.76 +}
1.77 +
1.78 +static GOptionEntry entries[]={
1.79 + { "dump-tree",'d',0,G_OPTION_ARG_NONE,&dump_tree,"Dump parsed file",NULL },
1.80 + { "dump-result",'D',0,G_OPTION_ARG_NONE,&dump_result,"Dump result",NULL },
1.81 + { "test-result",'t',0,G_OPTION_ARG_NONE,&test_result,"Test result",NULL },
1.82 + { "trace",'T',0,G_OPTION_ARG_CALLBACK,trace_symbol,"Trace symbol",NULL },
1.83 + { G_OPTION_REMAINING,0,0,G_OPTION_ARG_FILENAME_ARRAY,&files,NULL,
1.84 + "[<input>]" },
1.85 + { "xinclude",0,0,G_OPTION_ARG_NONE,&do_xinclude,"Do XInclude processing",
1.86 + NULL },
1.87 + { "param",0,0,G_OPTION_ARG_CALLBACK,set_param,
1.88 + "Pass a (parameter,number) pair",NULL },
1.89 + { "stringparam",0,0,G_OPTION_ARG_CALLBACK,set_string_param,
1.90 + "Pass a (parameter,string) pair",NULL },
1.91 + { NULL }
1.92 +};
1.93 +
1.94 +gboolean set_variable(gpointer key,gpointer value,gpointer data)
1.95 +{
1.96 + xexpr_var_set(data,key,value);
1.97 + return FALSE;
1.98 +}
1.99 +
1.100 +gboolean run_xexpr(Xexpr *xexpr,xmlDocPtr doc,const char *filename)
1.101 +{
1.102 + gboolean retval=TRUE;
1.103 + GError *err=NULL;
1.104 + Xexpr *sub,*result;
1.105 + sub=xexpr_sub(xexpr);
1.106 + xexpr_environment_foreach(xexpr_get_environment(xexpr),set_variable,sub);
1.107 + if (!xexpr_parse_node(sub,xmlDocGetRootElement(doc),&err))
1.108 + {
1.109 + fprintf(stderr,"%s: %s\n",filename,err->message);
1.110 + exit(1);
1.111 + }
1.112 + if (dump_tree)
1.113 + {
1.114 + xexpr_dump(sub,stdout);
1.115 + putchar('\n');
1.116 + }
1.117 + else
1.118 + {
1.119 + result=xexpr_evaluate(sub,&err);
1.120 + if (err)
1.121 + {
1.122 + fprintf(stderr,"%s: %s\n",filename,err->message);
1.123 + g_clear_error(&err);
1.124 + xexpr_free(sub);
1.125 + return FALSE;
1.126 + }
1.127 + if (dump_result)
1.128 + {
1.129 + printf("\nResult: ");
1.130 + xexpr_dump(result,stdout);
1.131 + putchar('\n');
1.132 + }
1.133 + if (test_result)
1.134 + retval=xexpr_test(result,NULL);
1.135 + xexpr_free(result);
1.136 + }
1.137 + xexpr_free(sub);
1.138 + return retval;
1.139 +}
1.140 +
1.141 +int main(int argc,char **argv)
1.142 +{
1.143 + int i;
1.144 + xmlDocPtr doc;
1.145 + int xml_options=XML_PARSE_NOENT;
1.146 + gboolean result=TRUE;
1.147 + GError *err=NULL;
1.148 + GOptionGroup *group;
1.149 + GOptionContext *context;
1.150 + Xexpr *xexpr;
1.151 + xexpr=xexpr_new();
1.152 + context=g_option_context_new("- XEXPR interpreter");
1.153 + group=g_option_group_new(NULL,NULL,NULL,xexpr,NULL);
1.154 + g_option_group_add_entries(group,entries);
1.155 + g_option_context_set_main_group(context,group);
1.156 + if (!g_option_context_parse(context,&argc,&argv,&err))
1.157 + {
1.158 + fprintf(stderr,"%s\n",err->message);
1.159 + exit(1);
1.160 + }
1.161 + if (do_xinclude)
1.162 + xml_options|=XML_PARSE_XINCLUDE|XML_PARSE_NOXINCNODE;
1.163 + if (files && files[0])
1.164 + {
1.165 + for(i=0;files[i];i++)
1.166 + {
1.167 + doc=xmlReadFile(files[i],NULL,xml_options);
1.168 + if (!doc)
1.169 + result=FALSE;
1.170 + else
1.171 + {
1.172 + if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0)
1.173 + result=FALSE;
1.174 + else if (!run_xexpr(xexpr,doc,files[i]))
1.175 + result=FALSE;
1.176 + xmlFreeDoc(doc);
1.177 + }
1.178 + }
1.179 + }
1.180 + else
1.181 + {
1.182 + doc=xmlReadFd(0,NULL,NULL,xml_options);
1.183 + if (!doc)
1.184 + result=FALSE;
1.185 + else
1.186 + {
1.187 + if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0)
1.188 + result=FALSE;
1.189 + else if (!run_xexpr(xexpr,doc,"stdin"))
1.190 + result=FALSE;
1.191 + xmlFreeDoc(doc);
1.192 + }
1.193 + }
1.194 + xexpr_free(xexpr);
1.195 + exit(result?0:1);
1.196 +}