src/xexpr.c
author ali <ali@juiblex.co.uk>
Wed Oct 10 22:58:21 2012 +0100 (2012-10-10)
changeset 0 bc8c9a11cbfc
permissions -rw-r--r--
Initial version
     1 #include <stdlib.h>
     2 #include <string.h>
     3 #include <math.h>
     4 #include <glib.h>
     5 #include <libxml/parser.h>
     6 #include <libxexpr/xexpr.h>
     7 
     8 gboolean dump_tree,dump_result,test_result,do_xinclude;
     9 gchar **files;
    10 
    11 gboolean trace_symbol(const gchar *option_name,const gchar *value,gpointer data,
    12   GError **err)
    13 {
    14     Xexpr *xexpr=data;
    15     xexpr_start_tracing(xexpr,value);
    16     return TRUE;
    17 }
    18 
    19 gboolean set_param(const gchar *option_name,const gchar *value,gpointer data,
    20   GError **err)
    21 {
    22     const char *s;
    23     char *endptr;
    24     double d,integer;
    25     gchar *name;
    26     XexprConstant *arg;
    27     Xexpr *xexpr=data;
    28     s=strchr(value,',');
    29     if (!s)
    30     {
    31 	g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
    32 	  "No comma found in --param argument \"%s\"",value);
    33 	return FALSE;
    34     }
    35     name=g_strndup(value,s-value);
    36     d=strtod(s+1,&endptr);
    37     if (!d || *endptr)
    38     {
    39 	g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
    40 	  "Invalid number in --param argument: \"%s\"",s);
    41 	return FALSE;
    42     }
    43     if (!modf(d,&integer))
    44 	arg=xexpr_new_integer(integer);
    45     else
    46 	arg=xexpr_new_number(d);
    47     xexpr_var_set(xexpr,name,arg);
    48     xexpr_constant_free(arg);
    49     return TRUE;
    50 }
    51 
    52 gboolean set_string_param(const gchar *option_name,const gchar *value,
    53   gpointer data,GError **err)
    54 {
    55     const char *s;
    56     char *endptr;
    57     double d,integer;
    58     gchar *name;
    59     XexprConstant *arg;
    60     Xexpr *xexpr=data;
    61     s=strchr(value,',');
    62     if (!s)
    63     {
    64 	g_set_error(err,G_OPTION_ERROR,G_OPTION_ERROR_BAD_VALUE,
    65 	  "No comma found in --stringparam argument \"%s\"",value);
    66 	return FALSE;
    67     }
    68     name=g_strndup(value,s-value);
    69     arg=xexpr_new_string(s+1,-1);
    70     xexpr_var_set(xexpr,name,arg);
    71     xexpr_constant_free(arg);
    72     return TRUE;
    73 }
    74 
    75 static GOptionEntry entries[]={
    76     { "dump-tree",'d',0,G_OPTION_ARG_NONE,&dump_tree,"Dump parsed file",NULL },
    77     { "dump-result",'D',0,G_OPTION_ARG_NONE,&dump_result,"Dump result",NULL },
    78     { "test-result",'t',0,G_OPTION_ARG_NONE,&test_result,"Test result",NULL },
    79     { "trace",'T',0,G_OPTION_ARG_CALLBACK,trace_symbol,"Trace symbol",NULL },
    80     { G_OPTION_REMAINING,0,0,G_OPTION_ARG_FILENAME_ARRAY,&files,NULL,
    81       "[<input>]" },
    82     { "xinclude",0,0,G_OPTION_ARG_NONE,&do_xinclude,"Do XInclude processing",
    83       NULL },
    84     { "param",0,0,G_OPTION_ARG_CALLBACK,set_param,
    85       "Pass a (parameter,number) pair",NULL },
    86     { "stringparam",0,0,G_OPTION_ARG_CALLBACK,set_string_param,
    87       "Pass a (parameter,string) pair",NULL },
    88     { NULL }
    89 };
    90 
    91 gboolean set_variable(gpointer key,gpointer value,gpointer data)
    92 {
    93     xexpr_var_set(data,key,value);
    94     return FALSE;
    95 }
    96 
    97 gboolean run_xexpr(Xexpr *xexpr,xmlDocPtr doc,const char *filename)
    98 {
    99     gboolean retval=TRUE;
   100     GError *err=NULL;
   101     Xexpr *sub,*result;
   102     sub=xexpr_sub(xexpr);
   103     xexpr_environment_foreach(xexpr_get_environment(xexpr),set_variable,sub);
   104     if (!xexpr_parse_node(sub,xmlDocGetRootElement(doc),&err))
   105     {
   106 	fprintf(stderr,"%s: %s\n",filename,err->message);
   107 	exit(1);
   108     }
   109     if (dump_tree)
   110     {
   111 	xexpr_dump(sub,stdout);
   112 	putchar('\n');
   113     }
   114     else
   115     {
   116 	result=xexpr_evaluate(sub,&err);
   117 	if (err)
   118 	{
   119 	    fprintf(stderr,"%s: %s\n",filename,err->message);
   120 	    g_clear_error(&err);
   121 	    xexpr_free(sub);
   122 	    return FALSE;
   123 	}
   124 	if (dump_result)
   125 	{
   126 	    printf("\nResult: ");
   127 	    xexpr_dump(result,stdout);
   128 	    putchar('\n');
   129 	}
   130 	if (test_result)
   131 	    retval=xexpr_test(result,NULL);
   132 	xexpr_free(result);
   133     }
   134     xexpr_free(sub);
   135     return retval;
   136 }
   137 
   138 int main(int argc,char **argv)
   139 {
   140     int i;
   141     xmlDocPtr doc;
   142     int xml_options=XML_PARSE_NOENT;
   143     gboolean result=TRUE;
   144     GError *err=NULL;
   145     GOptionGroup *group;
   146     GOptionContext *context;
   147     Xexpr *xexpr;
   148     xexpr=xexpr_new();
   149     context=g_option_context_new("- XEXPR interpreter");
   150     group=g_option_group_new(NULL,NULL,NULL,xexpr,NULL);
   151     g_option_group_add_entries(group,entries);
   152     g_option_context_set_main_group(context,group);
   153     if (!g_option_context_parse(context,&argc,&argv,&err))
   154     {
   155 	fprintf(stderr,"%s\n",err->message);
   156 	exit(1);
   157     }
   158     if (do_xinclude)
   159 	xml_options|=XML_PARSE_XINCLUDE|XML_PARSE_NOXINCNODE;
   160     if (files && files[0])
   161     {
   162 	for(i=0;files[i];i++)
   163 	{
   164 	    doc=xmlReadFile(files[i],NULL,xml_options);
   165 	    if (!doc)
   166 		result=FALSE;
   167 	    else
   168 	    {
   169 		if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0)
   170 		    result=FALSE;
   171 		else if (!run_xexpr(xexpr,doc,files[i]))
   172 		    result=FALSE;
   173 		xmlFreeDoc(doc);
   174 	    }
   175 	}
   176     }
   177     else
   178     {
   179 	doc=xmlReadFd(0,NULL,NULL,xml_options);
   180 	if (!doc)
   181 	    result=FALSE;
   182 	else
   183 	{
   184 	    if (do_xinclude && xmlXIncludeProcessFlags(doc,xml_options)<0)
   185 		result=FALSE;
   186 	    else if (!run_xexpr(xexpr,doc,"stdin"))
   187 		result=FALSE;
   188 	    xmlFreeDoc(doc);
   189 	}
   190     }
   191     xexpr_free(xexpr);
   192     exit(result?0:1);
   193 }