1 /*
2  *  TurboXSL XML+XSLT processing library
3  *  Main include for internal use. Interface functions and types
4  *  are in global turboxsl.h include
5  *
6  *  (c) Egor Voznessenski, voznyak@mail.ru
7  *
8  *  $Id$
9  *
10 **/
11 
12 #ifndef LTR_XSL_H_
13 #define LTR_XSL_H_
14 
15 #include <stdio.h>
16 
17 #include "turboxsl.h"
18 #include "strings.h"
19 #include "xmldict.h"
20 #include "templates.h"
21 #include "threadpool.h"
22 #include "allocator.h"
23 #include "external_cache.h"
24 #include "concurrent_dictionary.h"
25 #include "shared_variable.h"
26 #include "logger.h"
27 
28 typedef enum {VAL_NULL=0, VAL_BOOL, VAL_INT, VAL_NUMBER, VAL_STRING, VAL_NODESET} RVALUE_TYPE;
29 
30 typedef struct _rval {
31   RVALUE_TYPE type;
32   union {
33     long integer;
34     double number;
35     char *string;
36     XMLNODE *nodeset;
37   } v;
38 } RVALUE;
39 
40 typedef XMLNODE XPATH_EXPR;
41 
42 typedef enum {XML_FLAG_CDATA=1,XML_FLAG_NOESCAPE=2,XML_FLAG_SORTNUMBER=4,XML_FLAG_DESCENDING=8,XML_FLAG_LOWER=16} XML_FLAG;
43 
44 typedef enum {EMPTY_NODE=0, ELEMENT_NODE, TEXT_NODE, ATTRIBUTE_NODE, PI_NODE, COMMENT_NODE, INFO_NODE, XPATH_NODE_VAR, XPATH_NODE_NOT,
45   XPATH_NODE_OR, XPATH_NODE_AND, XPATH_NODE_EQ, XPATH_NODE_NE, XPATH_NODE_LT, XPATH_NODE_GT, XPATH_NODE_CALL, KEY_NODE,
46   XPATH_NODE_LE, XPATH_NODE_GE, XPATH_NODE_ADD, XPATH_NODE_SUB, XPATH_NODE_MUL, XPATH_NODE_DIV, XPATH_NODE_MOD,
47   XPATH_NODE_FILTER, XPATH_NODE_ALL, XPATH_NODE_ATTR, XPATH_NODE_ROOT, XPATH_NODE_PARENT, XPATH_NODE_SELF, XPATH_NODE_ANCESTOR,
48   XPATH_NODE_FOLLOWING_SIBLING, XPATH_NODE_PRECEDING_SIBLING, XPATH_NODE_PRECEDING, XPATH_NODE_FOLLOWING, XPATH_NODE_SELECT,
49   XPATH_NODE_ATTR_ALL, XPATH_NODE_INT, XPATH_NODE_CONTEXT, XPATH_NODE_DESCENDANT, XPATH_NODE_DESCENDANT_OR_SELF,
50   XPATH_NODE_UNION, XPATH_NODE_ANCESTOR_OR_SELF
51 } NODETYPE;
52 
53 struct _xmlnode {
54   struct _xmlnode *parent;
55   struct _xmlnode *next;
56   struct _xmlnode *prev;
57   struct _xmlnode *children;
58   struct _xmlnode *attributes;
59   struct _xmlnode *original;
60   XML_FLAG flags;
61   unsigned position;
62   unsigned order;
63   void *uid;
64   XPATH_EXPR *compiled;
65   RVALUE extra;
66   unsigned line;
67   char *file;
68   XMLSTRING name;
69   XMLSTRING content;
70   NODETYPE type;
71   memory_allocator *allocator;
72 };
73 
74 typedef struct _cbt {
75     char *name;
76     void (*func)();
77 }CB_TABLE;
78 
79 typedef struct _var {
80   char *name;
81   RVALUE extra;
82 } XSL_VARIABLE;
83 
84 struct _globaldata {
85   memory_allocator *allocator;
86   concurrent_dictionary *urldict;
87   XMLDICT *revisions;
88   XMLDICT *group_rights;
89   CB_TABLE *perl_functions;  // linear search for functions - small number and sorted by usage statistics
90   unsigned perl_cb_max;
91   unsigned perl_cb_ptr;
92   char *(*perl_cb_dispatcher)(void *fun,char **args,void *interpreter);
93   void (*perl_urlcode)();
94   void *interpreter;
95   external_cache *cache;
96   XSL_VARIABLE *vars;
97   unsigned var_max;
98   unsigned var_pos;
99 };
100 
101 typedef enum {XSL_FLAG_OUTPUT=1, XSL_FLAG_OMIT_DESC=2, XSL_FLAG_STANDALONE=4, XSL_FLAG_INDENT=8, XSL_FLAG_MODE_SET=16} XSL_FLAG;
102 typedef enum {MODE_NONE=0, MODE_XML, MODE_HTML, MODE_TEXT} OUTPUT_MODE;
103 
104 struct _context {
105   XSLTGLOBALDATA *gctx;
106   threadpool *pool;
107   memory_allocator *allocator;
108   char *cache_key_prefix;
109   char *url_local_prefix;
110   XMLDICT *user_rights;
111   XMLDICT *parallel_instructions;
112   XMLDICT *url_code_parameters;
113   void *task_graph; // TODO fix dependency graph
114   template_map *templates;
115   XMLDICT *named_templ; // templates for call'ing
116   XMLNODE *root_node;
117   XMLNODE *stylesheet;
118   CB_TABLE *functions;  // linear search for functions - small number and sorted by usage statistics
119   unsigned cb_max;
120   unsigned cb_ptr;
121   XSL_FLAG flags;
122   unsigned rawout;
123   XSL_VARIABLE *vars;   // Global (per conversion context) variables
124   unsigned var_max;     // +
125   unsigned var_pos;     // +
126   concurrent_dictionary *expressions;
127   char **sort_keys;     // sort tables for reuse. XXX must be rewritten to avoid conflicts (currently works because of rare use)
128   XMLNODE **sort_nodes; // +
129   unsigned sort_size;   // +
130   char *charset;        // Just links to strings allocated and freed with global hash. No need to free
131   XMLSTRING doctype_public; // +
132   XMLSTRING doctype_system; // +
133   XMLSTRING media_type;     // +
134   XMLSTRING encoding;       // + -- This one is not really useful now since only UTF-8 is supported
135   XMLNODE *keys;        // xsl:key data
136   XMLNODE *formats;     // xsl:decimal-format data
137   pthread_mutex_t lock;
138   OUTPUT_MODE outmode;
139 };
140 
141 typedef enum {DEFAULT, DENY, SINGLE} TEMPLATE_TASK_MODE;
142 
143 typedef struct template_context_ {
144   TRANSFORM_CONTEXT *context;
145   XMLNODE *instruction;
146   XMLNODE *result;
147   XMLNODE *document_node;
148   XMLNODE *parameters;
149   XMLNODE *local_variables;
150   XMLSTRING mode;
151   shared_variable *workers;
152   TEMPLATE_TASK_MODE task_mode;
153 } template_context;
154 
155 XMLNODE *xml_parse_file(XSLTGLOBALDATA *gctx, char *file, int has_allocator);
156 XMLNODE *xml_parse_string(XSLTGLOBALDATA *gctx, char *string, int has_allocator);
157 
158 /********************** nodes.c -- nodes operations *****************/
159 void xml_unlink_node(XMLNODE *node);
160 XMLNODE *xml_new_node(TRANSFORM_CONTEXT *pctx, XMLSTRING name, NODETYPE type);
161 XMLNODE *xml_append_child(TRANSFORM_CONTEXT *pctx, XMLNODE *node, NODETYPE type);
162 void xml_add_child(XMLNODE *node,XMLNODE *child);
163 
164 int is_node_parallel(XMLNODE *node);
165 
166 /********************** transform.c -- XSLT mainloop ****************/
167 void apply_xslt_template(template_context *context);
168 void process_one_node(template_context *context);
169 
170 XMLNODE *find_first_node(XMLNODE *n);
171 XMLSTRING xml_eval_string(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *source, XMLNODE *foreval);
172 
173 void copy_node_to_result_rec(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *context, XMLNODE *parent, XMLNODE *src);
174 
175 XMLSTRING xml_get_attr(XMLNODE *node, XMLSTRING name);
176 char *get_absolute_path(XMLNODE *node, char *name);
177 
178 XMLNODE *find_template(TRANSFORM_CONTEXT *pctx, XMLNODE *source, XMLSTRING mode);
179 XMLNODE *template_byname(TRANSFORM_CONTEXT *pctx, XMLSTRING name);
180 void precompile_templates(TRANSFORM_CONTEXT *pctx, XMLNODE *node);
181 void precompile_variables(TRANSFORM_CONTEXT *pctx, XMLNODE *stylesheet, XMLNODE *doc);
182 void get_variable_rv(TRANSFORM_CONTEXT *pctx, XMLNODE *vars, XMLSTRING name, RVALUE *rv);
183 void free_variables(TRANSFORM_CONTEXT *pctx);
184 
185 void do_local_var(TRANSFORM_CONTEXT *pctx, XMLNODE *vars, XMLNODE *doc, XMLNODE *var);
186 void add_local_var(TRANSFORM_CONTEXT *pctx, XMLNODE *vars, XMLSTRING name, XMLNODE *params);
187 char *xsl_get_global_key(TRANSFORM_CONTEXT *pctx, char *first, char *second);
188 
189 XMLNODE *copy_variables(TRANSFORM_CONTEXT *context, XMLNODE *variables);
190 
191 /************************* xpath.c -- xpath compilator ************************/
192 void xpath_execute_scalar(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *etree, XMLNODE *current, RVALUE *res);
193 
194 void xpath_eval_expression(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *current, XMLSTRING expr, RVALUE *res);
195 int xpath_eval_boolean(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *current, XMLNODE *expr);
196 char *xpath_eval_string(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *current, XMLNODE *expr);
197 XMLNODE *xpath_eval_selection(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *current, XMLNODE *expr);
198 void xpath_eval_node(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *current, XMLSTRING expr, RVALUE *this);
199 
200 XMLNODE *xpath_find_expr(TRANSFORM_CONTEXT *pctx, XMLSTRING expr);
201 XMLNODE *xpath_sort_selection(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *selection, XMLNODE *sort);
202 XMLNODE *xpath_in_selection(XMLNODE *sel, XMLSTRING name);
203 void xpath_free_selection(TRANSFORM_CONTEXT *pctx, XMLNODE *sel);
204 XMLNODE *xpath_compile(TRANSFORM_CONTEXT *pctx, char *expr);
205 XMLNODE *xpath_filter(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *nodeset, XMLNODE *expr);
206 XMLNODE *add_to_selection(XMLNODE *prev, XMLNODE *src, unsigned int *position);
207 XMLNODE *xpath_nodeset_copy(TRANSFORM_CONTEXT *pctx, XMLNODE *src);
208 
209 XMLSTRING xml_process_string(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, XMLNODE *src, XMLSTRING s);
210 
211 
212 /************************* rvalue.c -- rvalues operations ************************/
213 void rval_init(RVALUE *rv);
214 void rval_free(RVALUE *rv);
215 int rval2bool(RVALUE *rv);
216 char *rval2string(RVALUE *rv);
217 double rval2number(RVALUE *rv);
218 int rval_equal(RVALUE *left, RVALUE *right, unsigned eq);
219 int rval_less(RVALUE *left, RVALUE *right);
220 int rval_less_or_equal(RVALUE *left, RVALUE *right);
221 int rval_greater(RVALUE *left, RVALUE *right);
222 int rval_greater_or_equal(RVALUE *left, RVALUE *right);
223 
224 int match(char **eptr, char *str);
225 int x_can_number(char *p);
226 int x_is_ws(char c);
227 int x_is_namechar(char c);
228 int x_is_selchar(char c);
229 int xml_strcmp(const char *l, const char *r);
230 int xml_strcasecmp(char *l, char *r);
231 char *xml_strdup(const char *s);
232 char *xml_new_string(const char *s, size_t length);
233 char *node2string(XMLNODE *node);
234 char *nodes2string(XMLNODE *node);
235 
236 void xmls_add_char(XMLSTRING s, char c); // appends a char to xmlstring
237 void xmls_add_utf(XMLSTRING s, unsigned u); // appends unicode value to xmlstring
238 void xmls_append(XMLSTRING s, XMLSTRING value);
239 void xmls_add_str(XMLSTRING s, const char *d); // appends a string to xmlstring
240 char *xmls_detach(XMLSTRING s); // frees xmlstring, returns content to be freed later
241 
242 short *utf2ws(char *s);
243 
244 void output_node_rec(XMLNODE *node, XMLSTRING rtext, TRANSFORM_CONTEXT *ctx);
245 
246 void xpath_setup_functions(TRANSFORM_CONTEXT *pctx);
247 void xpath_call_dispatcher(TRANSFORM_CONTEXT *pctx, XMLNODE *locals, char *fname, XMLNODE *args, XMLNODE *current, RVALUE *res);
248 
249 #endif