ReactOS  0.4.15-dev-506-ga3ec01c
attrvt.c
Go to the documentation of this file.
1 /*
2  * attrvt.c: Implementation of the XSL Transformation 1.0 engine
3  * attribute value template handling part.
4  *
5  * References:
6  * http://www.w3.org/TR/1999/REC-xslt-19991116
7  *
8  * Michael Kay "XSLT Programmer's Reference" pp 637-643
9  * Writing Multiple Output Files
10  *
11  * See Copyright for the status of this software.
12  *
13  * daniel@veillard.com
14  */
15 
16 #include "precomp.h"
17 
18 #ifdef WITH_XSLT_DEBUG
19 #define WITH_XSLT_DEBUG_AVT
20 #endif
21 
22 #define MAX_AVT_SEG 10
23 
24 typedef struct _xsltAttrVT xsltAttrVT;
26 struct _xsltAttrVT {
27  struct _xsltAttrVT *next; /* next xsltAttrVT */
28  int nb_seg; /* Number of segments */
29  int max_seg; /* max capacity before re-alloc needed */
30  int strstart; /* is the start a string */
31  /*
32  * the namespaces in scope
33  */
35  int nsNr;
36  /*
37  * the content is an alternate of string and xmlXPathCompExprPtr
38  */
39 #if __STDC_VERSION__ >= 199901L
40  /* Using a C99 flexible array member avoids false positives under UBSan */
41  void *segments[];
42 #else
43  void *segments[1];
44 #endif
45 };
46 
55 static xsltAttrVTPtr
57  xsltAttrVTPtr cur;
58  size_t size = sizeof(xsltAttrVT) + MAX_AVT_SEG * sizeof(void*);
59 
60  cur = (xsltAttrVTPtr) xmlMalloc(size);
61  if (cur == NULL) {
63  "xsltNewAttrVTPtr : malloc failed\n");
64  if (style != NULL) style->errors++;
65  return(NULL);
66  }
67  memset(cur, 0, size);
68 
69  cur->nb_seg = 0;
70  cur->max_seg = MAX_AVT_SEG;
71  cur->strstart = 0;
72  cur->next = style->attVTs;
73  /*
74  * Note: this pointer may be changed by a re-alloc within xsltCompileAttr,
75  * so that code may change the stylesheet pointer also!
76  */
77  style->attVTs = (xsltAttrVTPtr) cur;
78 
79  return(cur);
80 }
81 
88 static void
90  int i;
91 
92  if (avt == NULL) return;
93 
94  if (avt->strstart == 1) {
95  for (i = 0;i < avt->nb_seg; i += 2)
96  if (avt->segments[i] != NULL)
97  xmlFree((xmlChar *) avt->segments[i]);
98  for (i = 1;i < avt->nb_seg; i += 2)
99  xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
100  } else {
101  for (i = 0;i < avt->nb_seg; i += 2)
102  xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]);
103  for (i = 1;i < avt->nb_seg; i += 2)
104  if (avt->segments[i] != NULL)
105  xmlFree((xmlChar *) avt->segments[i]);
106  }
107  if (avt->nsList != NULL)
108  xmlFree(avt->nsList);
109  xmlFree(avt);
110 }
111 
118 void
119 xsltFreeAVTList(void *avt) {
120  xsltAttrVTPtr cur = (xsltAttrVTPtr) avt, next;
121 
122  while (cur != NULL) {
123  next = cur->next;
124  xsltFreeAttrVT(cur);
125  cur = next;
126  }
127 }
140 static xsltAttrVTPtr
142  if (avt->nb_seg >= avt->max_seg) {
143  size_t size = sizeof(xsltAttrVT) +
144  (avt->max_seg + MAX_AVT_SEG) * sizeof(void *);
146  if (tmp == NULL) {
147  xsltFreeAttrVT(avt);
148  return NULL;
149  }
150  avt = tmp;
151  memset(&avt->segments[avt->nb_seg], 0, MAX_AVT_SEG*sizeof(void *));
152  avt->max_seg += MAX_AVT_SEG;
153  }
154  avt->segments[avt->nb_seg++] = val;
155  return avt;
156 }
157 
167 void
169  const xmlChar *str;
170  const xmlChar *cur;
171  xmlChar *ret = NULL;
172  xmlChar *expr = NULL;
173  xsltAttrVTPtr avt;
174  int i = 0, lastavt = 0;
175 
176  if ((style == NULL) || (attr == NULL) || (attr->children == NULL))
177  return;
178  if ((attr->children->type != XML_TEXT_NODE) ||
179  (attr->children->next != NULL)) {
180  xsltTransformError(NULL, style, attr->parent,
181  "Attribute '%s': The content is expected to be a single text "
182  "node when compiling an AVT.\n", attr->name);
183  style->errors++;
184  return;
185  }
186  str = attr->children->content;
187  if ((xmlStrchr(str, '{') == NULL) &&
188  (xmlStrchr(str, '}') == NULL)) return;
189 
190 #ifdef WITH_XSLT_DEBUG_AVT
192  "Found AVT %s: %s\n", attr->name, str);
193 #endif
194  if (attr->psvi != NULL) {
195 #ifdef WITH_XSLT_DEBUG_AVT
197  "AVT %s: already compiled\n", attr->name);
198 #endif
199  return;
200  }
201  /*
202  * Create a new AVT object.
203  */
204  avt = xsltNewAttrVT(style);
205  if (avt == NULL)
206  return;
207  attr->psvi = avt;
208 
209  avt->nsList = xmlGetNsList(attr->doc, attr->parent);
210  if (avt->nsList != NULL) {
211  while (avt->nsList[i] != NULL)
212  i++;
213  }
214  avt->nsNr = i;
215 
216  cur = str;
217  while (*cur != 0) {
218  if (*cur == '{') {
219  if (*(cur+1) == '{') { /* escaped '{' */
220  cur++;
221  ret = xmlStrncat(ret, str, cur - str);
222  cur++;
223  str = cur;
224  continue;
225  }
226  if (*(cur+1) == '}') { /* skip empty AVT */
227  ret = xmlStrncat(ret, str, cur - str);
228  cur += 2;
229  str = cur;
230  continue;
231  }
232  if ((ret != NULL) || (cur - str > 0)) {
233  ret = xmlStrncat(ret, str, cur - str);
234  str = cur;
235  if (avt->nb_seg == 0)
236  avt->strstart = 1;
237  if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
238  goto error;
239  ret = NULL;
240  lastavt = 0;
241  }
242 
243  cur++;
244  while ((*cur != 0) && (*cur != '}')) {
245  /* Need to check for literal (bug539741) */
246  if ((*cur == '\'') || (*cur == '"')) {
247  char delim = *(cur++);
248  while ((*cur != 0) && (*cur != delim))
249  cur++;
250  if (*cur != 0)
251  cur++; /* skip the ending delimiter */
252  } else
253  cur++;
254  }
255  if (*cur == 0) {
256  xsltTransformError(NULL, style, attr->parent,
257  "Attribute '%s': The AVT has an unmatched '{'.\n",
258  attr->name);
259  style->errors++;
260  goto error;
261  }
262  str++;
263  expr = xmlStrndup(str, cur - str);
264  if (expr == NULL) {
265  /*
266  * TODO: What needs to be done here?
267  */
268  XSLT_TODO
269  goto error;
270  } else {
271  xmlXPathCompExprPtr comp;
272 
273  comp = xsltXPathCompile(style, expr);
274  if (comp == NULL) {
275  xsltTransformError(NULL, style, attr->parent,
276  "Attribute '%s': Failed to compile the expression "
277  "'%s' in the AVT.\n", attr->name, expr);
278  style->errors++;
279  goto error;
280  }
281  if (avt->nb_seg == 0)
282  avt->strstart = 0;
283  if (lastavt == 1) {
284  if ((avt = xsltSetAttrVTsegment(avt, NULL)) == NULL)
285  goto error;
286  }
287  if ((avt = xsltSetAttrVTsegment(avt, (void *) comp)) == NULL)
288  goto error;
289  lastavt = 1;
290  xmlFree(expr);
291  expr = NULL;
292  }
293  cur++;
294  str = cur;
295  } else if (*cur == '}') {
296  cur++;
297  if (*cur == '}') { /* escaped '}' */
298  ret = xmlStrncat(ret, str, cur - str);
299  cur++;
300  str = cur;
301  continue;
302  } else {
303  xsltTransformError(NULL, style, attr->parent,
304  "Attribute '%s': The AVT has an unmatched '}'.\n",
305  attr->name);
306  goto error;
307  }
308  } else
309  cur++;
310  }
311  if ((ret != NULL) || (cur - str > 0)) {
312  ret = xmlStrncat(ret, str, cur - str);
313  str = cur;
314  if (avt->nb_seg == 0)
315  avt->strstart = 1;
316  if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL)
317  goto error;
318  ret = NULL;
319  }
320 
321 error:
322  if (avt == NULL) {
323  xsltTransformError(NULL, style, attr->parent,
324  "xsltCompileAttr: malloc problem\n");
325  } else {
326  if (attr->psvi != avt) { /* may have changed from realloc */
327  attr->psvi = avt;
328  /*
329  * This is a "hack", but I can't see any clean method of
330  * doing it. If a re-alloc has taken place, then the pointer
331  * for this AVT may have changed. style->attVTs was set by
332  * xsltNewAttrVT, so it needs to be re-set to the new value!
333  */
334  style->attVTs = avt;
335  }
336  }
337  if (ret != NULL)
338  xmlFree(ret);
339  if (expr != NULL)
340  xmlFree(expr);
341 }
342 
343 
355 xmlChar *
357  xmlChar *ret = NULL, *tmp;
358  xmlXPathCompExprPtr comp;
359  xsltAttrVTPtr cur = (xsltAttrVTPtr) avt;
360  int i;
361  int str;
362 
363  if ((ctxt == NULL) || (avt == NULL) || (node == NULL))
364  return(NULL);
365  str = cur->strstart;
366  for (i = 0;i < cur->nb_seg;i++) {
367  if (str) {
368  ret = xmlStrcat(ret, (const xmlChar *) cur->segments[i]);
369  } else {
370  comp = (xmlXPathCompExprPtr) cur->segments[i];
371  tmp = xsltEvalXPathStringNs(ctxt, comp, cur->nsNr, cur->nsList);
372  if (tmp != NULL) {
373  if (ret != NULL) {
374  ret = xmlStrcat(ret, tmp);
375  xmlFree(tmp);
376  } else {
377  ret = tmp;
378  }
379  }
380  }
381  str = !str;
382  }
383  return(ret);
384 }
#define MAX_AVT_SEG
Definition: attrvt.c:22
#define error(str)
Definition: mkdosfs.c:1605
Definition: tree.h:389
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:41
struct _xsltAttrVT xsltAttrVT
Definition: attrvt.c:24
xmlXPathCompExprPtr xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str)
Definition: xsltutils.c:2319
struct _xsltAttrVT * next
Definition: attrvt.c:27
int nb_seg
Definition: attrvt.c:28
XMLPUBFUN const xmlChar *XMLCALL xmlStrchr(const xmlChar *str, xmlChar val)
Definition: xmlstring.c:321
Definition: query.h:86
int strstart
Definition: attrvt.c:30
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:526
xmlChar * xsltEvalAVT(xsltTransformContextPtr ctxt, void *avt, xmlNodePtr node)
Definition: attrvt.c:356
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
int max_seg
Definition: attrvt.c:29
XMLPUBVAR xmlReallocFunc xmlRealloc
Definition: globals.h:249
GLuint GLfloat * val
Definition: glext.h:7180
#define XSLT_TODO
Definition: xsltutils.h:34
void * xsltGenericDebugContext
Definition: xsltutils.c:549
GLsizeiptr size
Definition: glext.h:5919
XMLPUBFUN xmlChar *XMLCALL xmlStrncat(xmlChar *cur, const xmlChar *add, int len)
Definition: xmlstring.c:448
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
Definition: cookie.c:201
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
static void xsltFreeAttrVT(xsltAttrVTPtr avt)
Definition: attrvt.c:89
Definition: tree.h:489
int ret
static xsltAttrVTPtr xsltSetAttrVTsegment(xsltAttrVTPtr avt, void *val)
Definition: attrvt.c:141
unsigned char xmlChar
Definition: xmlstring.h:28
void * segments[1]
Definition: attrvt.c:43
xmlNsPtr * nsList
Definition: attrvt.c:34
static unsigned __int64 next
Definition: rand_nt.c:6
void xsltFreeAVTList(void *avt)
Definition: attrvt.c:119
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
Definition: tree.h:434
WCHAR * name
Definition: cookie.c:203
xmlChar * xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, int nsNr, xmlNsPtr *nsList)
Definition: templates.c:105
xsltAttrVT * xsltAttrVTPtr
Definition: attrvt.c:25
static xsltAttrVTPtr xsltNewAttrVT(xsltStylesheetPtr style)
Definition: attrvt.c:56
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
Arabic default style
Definition: afstyles.h:93
#define memset(x, y, z)
Definition: compat.h:39
int nsNr
Definition: attrvt.c:35
Definition: dlist.c:348
void xsltCompileAttr(xsltStylesheetPtr style, xmlAttrPtr attr)
Definition: attrvt.c:168