ReactOS  r76032
numbers.c
Go to the documentation of this file.
1 /*
2  * numbers.c: Implementation of the XSLT number functions
3  *
4  * Reference:
5  * http://www.w3.org/TR/1999/REC-xslt-19991116
6  *
7  * See Copyright for the status of this software.
8  *
9  * daniel@veillard.com
10  * Bjorn Reese <breese@users.sourceforge.net>
11  */
12 
13 #include "precomp.h"
14 
15 #ifndef FALSE
16 # define FALSE (0 == 1)
17 # define TRUE (1 == 1)
18 #endif
19 
20 #define SYMBOL_QUOTE ((xmlChar)'\'')
21 
22 #define DEFAULT_TOKEN (xmlChar)'0'
23 #define DEFAULT_SEPARATOR "."
24 
25 #define MAX_TOKENS 1024
26 
32  int width;
33 };
34 
35 typedef struct _xsltFormat xsltFormat;
37 struct _xsltFormat {
40  int nTokens;
42 };
43 
44 static char alpha_upper_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
45 static char alpha_lower_list[] = "abcdefghijklmnopqrstuvwxyz";
47 
48 /*
49  * **** Start temp insert ****
50  *
51  * The following two routines (xsltUTF8Size and xsltUTF8Charcmp)
52  * will be replaced with calls to the corresponding libxml routines
53  * at a later date (when other inter-library dependencies require it)
54  */
55 
62 static int
64  xmlChar mask;
65  int len;
66 
67  if (utf == NULL)
68  return -1;
69  if (*utf < 0x80)
70  return 1;
71  /* check valid UTF8 character */
72  if (!(*utf & 0x40))
73  return -1;
74  /* determine number of bytes in char */
75  len = 2;
76  for (mask=0x20; mask != 0; mask>>=1) {
77  if (!(*utf & mask))
78  return len;
79  len++;
80  }
81  return -1;
82 }
83 
92 static int
94 
95  if (utf1 == NULL ) {
96  if (utf2 == NULL)
97  return 0;
98  return -1;
99  }
100  return xmlStrncmp(utf1, utf2, xsltUTF8Size(utf1));
101 }
102 
103 /***** Stop temp insert *****/
104 /************************************************************************
105  * *
106  * Utility functions *
107  * *
108  ************************************************************************/
109 
110 #define IS_SPECIAL(self,letter) \
111  ((xsltUTF8Charcmp((letter), (self)->zeroDigit) == 0) || \
112  (xsltUTF8Charcmp((letter), (self)->digit) == 0) || \
113  (xsltUTF8Charcmp((letter), (self)->decimalPoint) == 0) || \
114  (xsltUTF8Charcmp((letter), (self)->grouping) == 0) || \
115  (xsltUTF8Charcmp((letter), (self)->patternSeparator) == 0))
116 
117 #define IS_DIGIT_ZERO(x) xsltIsDigitZero(x)
118 #define IS_DIGIT_ONE(x) xsltIsDigitZero((xmlChar)(x)-1)
119 
120 static int
121 xsltIsDigitZero(unsigned int ch)
122 {
123  /*
124  * Reference: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
125  */
126  switch (ch) {
127  case 0x0030: case 0x0660: case 0x06F0: case 0x0966:
128  case 0x09E6: case 0x0A66: case 0x0AE6: case 0x0B66:
129  case 0x0C66: case 0x0CE6: case 0x0D66: case 0x0E50:
130  case 0x0E60: case 0x0F20: case 0x1040: case 0x17E0:
131  case 0x1810: case 0xFF10:
132  return TRUE;
133  default:
134  return FALSE;
135  }
136 }
137 
138 static void
140  double number,
141  int digit_zero,
142  int width,
143  int digitsPerGroup,
144  int groupingCharacter,
145  int groupingCharacterLen)
146 {
147  /*
148  * This used to be
149  * xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 4];
150  * which would be length 68 on x86 arch. It was changed to be a longer,
151  * fixed length in order to try to cater for (reasonable) UTF8
152  * separators and numeric characters. The max UTF8 char size will be
153  * 6 or less, so the value used [500] should be *much* larger than needed
154  */
155  xmlChar temp_string[500];
156  xmlChar *pointer;
157  xmlChar temp_char[6];
158  int i;
159  int val;
160  int len;
161 
162  /* Build buffer from back */
163  pointer = &temp_string[sizeof(temp_string)] - 1; /* last char */
164  *pointer = 0;
165  i = 0;
166  while (pointer > temp_string) {
167  if ((i >= width) && (fabs(number) < 1.0))
168  break; /* for */
169  if ((i > 0) && (groupingCharacter != 0) &&
170  (digitsPerGroup > 0) &&
171  ((i % digitsPerGroup) == 0)) {
172  if (pointer - groupingCharacterLen < temp_string) {
173  i = -1; /* flag error */
174  break;
175  }
176  pointer -= groupingCharacterLen;
177  xmlCopyCharMultiByte(pointer, groupingCharacter);
178  }
179 
180  val = digit_zero + (int)fmod(number, 10.0);
181  if (val < 0x80) { /* shortcut if ASCII */
182  if (pointer <= temp_string) { /* Check enough room */
183  i = -1;
184  break;
185  }
186  *(--pointer) = val;
187  }
188  else {
189  /*
190  * Here we have a multibyte character. It's a little messy,
191  * because until we generate the char we don't know how long
192  * it is. So, we generate it into the buffer temp_char, then
193  * copy from there into temp_string.
194  */
195  len = xmlCopyCharMultiByte(temp_char, val);
196  if ( (pointer - len) < temp_string ) {
197  i = -1;
198  break;
199  }
200  pointer -= len;
201  memcpy(pointer, temp_char, len);
202  }
203  number /= 10.0;
204  ++i;
205  }
206  if (i < 0)
208  "xsltNumberFormatDecimal: Internal buffer size exceeded");
209  xmlBufferCat(buffer, pointer);
210 }
211 
212 static void
215  double number,
216  int is_upper)
217 {
218  char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1];
219  char *pointer;
220  int i;
221  char *alpha_list;
222  double alpha_size = (double)(sizeof(alpha_upper_list) - 1);
223 
224  /*
225  * XSLT 1.0 isn't clear on how to handle zero, but XSLT 2.0 says:
226  *
227  * For all format tokens other than the first kind above (one that
228  * consists of decimal digits), there may be implementation-defined
229  * lower and upper bounds on the range of numbers that can be
230  * formatted using this format token; indeed, for some numbering
231  * sequences there may be intrinsic limits. [...] Numbers that fall
232  * outside this range must be formatted using the format token 1.
233  *
234  * The "a" token has an intrinsic lower limit of 1.
235  */
236  if (number < 1.0) {
237  xsltNumberFormatDecimal(buffer, number, '0', 1,
238  data->digitsPerGroup,
239  data->groupingCharacter,
240  data->groupingCharacterLen);
241  return;
242  }
243 
244  /* Build buffer from back */
245  pointer = &temp_string[sizeof(temp_string)];
246  *(--pointer) = 0;
247  alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list;
248 
249  for (i = 1; i < (int)sizeof(temp_string); i++) {
250  number--;
251  *(--pointer) = alpha_list[((int)fmod(number, alpha_size))];
252  number /= alpha_size;
253  if (number < 1.0)
254  break; /* for */
255  }
256  xmlBufferCCat(buffer, pointer);
257 }
258 
259 static void
262  double number,
263  int is_upper)
264 {
265  /*
266  * See discussion in xsltNumberFormatAlpha. Also use a reasonable upper
267  * bound to avoid denial of service.
268  */
269  if (number < 1.0 || number > 5000.0) {
270  xsltNumberFormatDecimal(buffer, number, '0', 1,
271  data->digitsPerGroup,
272  data->groupingCharacter,
273  data->groupingCharacterLen);
274  return;
275  }
276 
277  /*
278  * Based on an example by Jim Walsh
279  */
280  while (number >= 1000.0) {
281  xmlBufferCCat(buffer, (is_upper) ? "M" : "m");
282  number -= 1000.0;
283  }
284  if (number >= 900.0) {
285  xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm");
286  number -= 900.0;
287  }
288  while (number >= 500.0) {
289  xmlBufferCCat(buffer, (is_upper) ? "D" : "d");
290  number -= 500.0;
291  }
292  if (number >= 400.0) {
293  xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd");
294  number -= 400.0;
295  }
296  while (number >= 100.0) {
297  xmlBufferCCat(buffer, (is_upper) ? "C" : "c");
298  number -= 100.0;
299  }
300  if (number >= 90.0) {
301  xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc");
302  number -= 90.0;
303  }
304  while (number >= 50.0) {
305  xmlBufferCCat(buffer, (is_upper) ? "L" : "l");
306  number -= 50.0;
307  }
308  if (number >= 40.0) {
309  xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl");
310  number -= 40.0;
311  }
312  while (number >= 10.0) {
313  xmlBufferCCat(buffer, (is_upper) ? "X" : "x");
314  number -= 10.0;
315  }
316  if (number >= 9.0) {
317  xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix");
318  number -= 9.0;
319  }
320  while (number >= 5.0) {
321  xmlBufferCCat(buffer, (is_upper) ? "V" : "v");
322  number -= 5.0;
323  }
324  if (number >= 4.0) {
325  xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv");
326  number -= 4.0;
327  }
328  while (number >= 1.0) {
329  xmlBufferCCat(buffer, (is_upper) ? "I" : "i");
330  number--;
331  }
332 }
333 
334 static void
336  xsltFormatPtr tokens)
337 {
338  int ix = 0;
339  int j;
340  int val;
341  int len;
342 
343  default_token.token = DEFAULT_TOKEN;
344  default_token.width = 1;
345  default_token.separator = BAD_CAST(DEFAULT_SEPARATOR);
346 
347 
348  tokens->start = NULL;
349  tokens->tokens[0].separator = NULL;
350  tokens->end = NULL;
351 
352  /*
353  * Insert initial non-alphanumeric token.
354  * There is always such a token in the list, even if NULL
355  */
356  while (! (IS_LETTER(val=xmlStringCurrentChar(NULL, format+ix, &len)) ||
357  IS_DIGIT(val)) ) {
358  if (format[ix] == 0) /* if end of format string */
359  break; /* while */
360  ix += len;
361  }
362  if (ix > 0)
363  tokens->start = xmlStrndup(format, ix);
364 
365 
366  for (tokens->nTokens = 0; tokens->nTokens < MAX_TOKENS;
367  tokens->nTokens++) {
368  if (format[ix] == 0)
369  break; /* for */
370 
371  /*
372  * separator has already been parsed (except for the first
373  * number) in tokens->end, recover it.
374  */
375  if (tokens->nTokens > 0) {
376  tokens->tokens[tokens->nTokens].separator = tokens->end;
377  tokens->end = NULL;
378  }
379 
380  val = xmlStringCurrentChar(NULL, format+ix, &len);
381  if (IS_DIGIT_ONE(val) ||
382  IS_DIGIT_ZERO(val)) {
383  tokens->tokens[tokens->nTokens].width = 1;
384  while (IS_DIGIT_ZERO(val)) {
385  tokens->tokens[tokens->nTokens].width++;
386  ix += len;
387  val = xmlStringCurrentChar(NULL, format+ix, &len);
388  }
389  if (IS_DIGIT_ONE(val)) {
390  tokens->tokens[tokens->nTokens].token = val - 1;
391  ix += len;
392  val = xmlStringCurrentChar(NULL, format+ix, &len);
393  }
394  } else if ( (val == (xmlChar)'A') ||
395  (val == (xmlChar)'a') ||
396  (val == (xmlChar)'I') ||
397  (val == (xmlChar)'i') ) {
398  tokens->tokens[tokens->nTokens].token = val;
399  ix += len;
400  val = xmlStringCurrentChar(NULL, format+ix, &len);
401  } else {
402  /* XSLT section 7.7
403  * "Any other format token indicates a numbering sequence
404  * that starts with that token. If an implementation does
405  * not support a numbering sequence that starts with that
406  * token, it must use a format token of 1."
407  */
408  tokens->tokens[tokens->nTokens].token = (xmlChar)'0';
409  tokens->tokens[tokens->nTokens].width = 1;
410  }
411  /*
412  * Skip over remaining alphanumeric characters from the Nd
413  * (Number, decimal digit), Nl (Number, letter), No (Number,
414  * other), Lu (Letter, uppercase), Ll (Letter, lowercase), Lt
415  * (Letters, titlecase), Lm (Letters, modifiers), and Lo
416  * (Letters, other (uncased)) Unicode categories. This happens
417  * to correspond to the Letter and Digit classes from XML (and
418  * one wonders why XSLT doesn't refer to these instead).
419  */
420  while (IS_LETTER(val) || IS_DIGIT(val)) {
421  ix += len;
422  val = xmlStringCurrentChar(NULL, format+ix, &len);
423  }
424 
425  /*
426  * Insert temporary non-alphanumeric final tooken.
427  */
428  j = ix;
429  while (! (IS_LETTER(val) || IS_DIGIT(val))) {
430  if (val == 0)
431  break; /* while */
432  ix += len;
433  val = xmlStringCurrentChar(NULL, format+ix, &len);
434  }
435  if (ix > j)
436  tokens->end = xmlStrndup(&format[j], ix - j);
437  }
438 }
439 
440 static void
442  double *numbers,
443  int numbers_max,
444  xsltFormatPtr tokens,
446 {
447  int i = 0;
448  double number;
450 
451  /*
452  * Handle initial non-alphanumeric token
453  */
454  if (tokens->start != NULL)
455  xmlBufferCat(buffer, tokens->start);
456 
457  for (i = 0; i < numbers_max; i++) {
458  /* Insert number */
459  number = numbers[(numbers_max - 1) - i];
460  /* Round to nearest like XSLT 2.0 */
461  number = floor(number + 0.5);
462  /*
463  * XSLT 1.0 isn't clear on how to handle negative numbers, but XSLT
464  * 2.0 says:
465  *
466  * It is a non-recoverable dynamic error if any undiscarded item
467  * in the atomized sequence supplied as the value of the value
468  * attribute of xsl:number cannot be converted to an integer, or
469  * if the resulting integer is less than 0 (zero).
470  */
471  if (number < 0.0) {
473  "xsl-number : negative value\n");
474  /* Recover by treating negative values as zero. */
475  number = 0.0;
476  }
477  if (i < tokens->nTokens) {
478  /*
479  * The "n"th format token will be used to format the "n"th
480  * number in the list
481  */
482  token = &(tokens->tokens[i]);
483  } else if (tokens->nTokens > 0) {
484  /*
485  * If there are more numbers than format tokens, then the
486  * last format token will be used to format the remaining
487  * numbers.
488  */
489  token = &(tokens->tokens[tokens->nTokens - 1]);
490  } else {
491  /*
492  * If there are no format tokens, then a format token of
493  * 1 is used to format all numbers.
494  */
495  token = &default_token;
496  }
497 
498  /* Print separator, except for the first number */
499  if (i > 0) {
500  if (token->separator != NULL)
501  xmlBufferCat(buffer, token->separator);
502  else
504  }
505 
506  switch (xmlXPathIsInf(number)) {
507  case -1:
508  xmlBufferCCat(buffer, "-Infinity");
509  break;
510  case 1:
511  xmlBufferCCat(buffer, "Infinity");
512  break;
513  default:
514  if (xmlXPathIsNaN(number)) {
515  xmlBufferCCat(buffer, "NaN");
516  } else {
517 
518  switch (token->token) {
519  case 'A':
520  xsltNumberFormatAlpha(data, buffer, number, TRUE);
521  break;
522  case 'a':
523  xsltNumberFormatAlpha(data, buffer, number, FALSE);
524  break;
525  case 'I':
526  xsltNumberFormatRoman(data, buffer, number, TRUE);
527  break;
528  case 'i':
529  xsltNumberFormatRoman(data, buffer, number, FALSE);
530  break;
531  default:
532  if (IS_DIGIT_ZERO(token->token)) {
534  number,
535  token->token,
536  token->width,
537  data->digitsPerGroup,
538  data->groupingCharacter,
539  data->groupingCharacterLen);
540  }
541  break;
542  }
543  }
544 
545  }
546  }
547 
548  /*
549  * Handle final non-alphanumeric token
550  */
551  if (tokens->end != NULL)
552  xmlBufferCat(buffer, tokens->end);
553 
554 }
555 
556 static int
559  xsltCompMatchPtr countPat,
560  xmlNodePtr cur)
561 {
562  if (countPat != NULL) {
563  return xsltTestCompMatchList(context, node, countPat);
564  }
565  else {
566  /*
567  * 7.7 Numbering
568  *
569  * If count attribute is not specified, then it defaults to the
570  * pattern that matches any node with the same node type as the
571  * current node and, if the current node has an expanded-name, with
572  * the same expanded-name as the current node.
573  */
574  if (node->type != cur->type)
575  return 0;
576  if (node->type == XML_NAMESPACE_DECL)
577  /*
578  * Namespace nodes have no preceding siblings and no parents
579  * that are namespace nodes. This means that node == cur.
580  */
581  return 1;
582  /* TODO: Skip node types without expanded names like text nodes. */
583  if (!xmlStrEqual(node->name, cur->name))
584  return 0;
585  if (node->ns == cur->ns)
586  return 1;
587  if ((node->ns == NULL) || (cur->ns == NULL))
588  return 0;
589  return (xmlStrEqual(node->ns->href, cur->ns->href));
590  }
591 }
592 
593 static int
596  xsltCompMatchPtr countPat,
597  xsltCompMatchPtr fromPat,
598  double *array)
599 {
600  int amount = 0;
601  int cnt = 0;
602  xmlNodePtr cur;
603 
604  /* select the starting node */
605  switch (node->type) {
606  case XML_ELEMENT_NODE:
607  cur = node;
608  break;
609  case XML_ATTRIBUTE_NODE:
610  cur = ((xmlAttrPtr) node)->parent;
611  break;
612  case XML_TEXT_NODE:
613  case XML_PI_NODE:
614  case XML_COMMENT_NODE:
615  cur = node->parent;
616  break;
617  default:
618  cur = NULL;
619  break;
620  }
621 
622  while (cur != NULL) {
623  /* process current node */
624  if (xsltTestCompMatchCount(context, cur, countPat, node))
625  cnt++;
626  if ((fromPat != NULL) &&
627  xsltTestCompMatchList(context, cur, fromPat)) {
628  break; /* while */
629  }
630 
631  /* Skip to next preceding or ancestor */
632  if ((cur->type == XML_DOCUMENT_NODE) ||
633 #ifdef LIBXML_DOCB_ENABLED
634  (cur->type == XML_DOCB_DOCUMENT_NODE) ||
635 #endif
636  (cur->type == XML_HTML_DOCUMENT_NODE))
637  break; /* while */
638 
639  while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
640  (cur->prev->type == XML_XINCLUDE_START) ||
641  (cur->prev->type == XML_XINCLUDE_END)))
642  cur = cur->prev;
643  if (cur->prev != NULL) {
644  for (cur = cur->prev; cur->last != NULL; cur = cur->last);
645  } else {
646  cur = cur->parent;
647  }
648 
649  }
650 
651  array[amount++] = (double) cnt;
652 
653  return(amount);
654 }
655 
656 static int
659  xsltCompMatchPtr countPat,
660  xsltCompMatchPtr fromPat,
661  double *array,
662  int max)
663 {
664  int amount = 0;
665  int cnt;
666  xmlNodePtr ancestor;
667  xmlNodePtr preceding;
668  xmlXPathParserContextPtr parser;
669 
670  context->xpathCtxt->node = node;
671  parser = xmlXPathNewParserContext(NULL, context->xpathCtxt);
672  if (parser) {
673  /* ancestor-or-self::*[count] */
674  for (ancestor = node;
675  (ancestor != NULL) && (ancestor->type != XML_DOCUMENT_NODE);
676  ancestor = xmlXPathNextAncestor(parser, ancestor)) {
677 
678  if ((fromPat != NULL) &&
679  xsltTestCompMatchList(context, ancestor, fromPat))
680  break; /* for */
681 
682  if (xsltTestCompMatchCount(context, ancestor, countPat, node)) {
683  /* count(preceding-sibling::*) */
684  cnt = 1;
685  for (preceding =
686  xmlXPathNextPrecedingSibling(parser, ancestor);
687  preceding != NULL;
688  preceding =
689  xmlXPathNextPrecedingSibling(parser, preceding)) {
690 
691  if (xsltTestCompMatchCount(context, preceding, countPat,
692  node))
693  cnt++;
694  }
695  array[amount++] = (double)cnt;
696  if (amount >= max)
697  break; /* for */
698  }
699  }
700  xmlXPathFreeParserContext(parser);
701  }
702  return amount;
703 }
704 
705 static int
708  const xmlChar *value,
709  double *number)
710 {
711  int amount = 0;
713  xmlXPathObjectPtr obj;
714 
715  pattern = xmlBufferCreate();
716  if (pattern != NULL) {
717  xmlBufferCCat(pattern, "number(");
718  xmlBufferCat(pattern, value);
719  xmlBufferCCat(pattern, ")");
720  context->node = node;
721  obj = xmlXPathEvalExpression(xmlBufferContent(pattern),
722  context);
723  if (obj != NULL) {
724  *number = obj->floatval;
725  amount++;
726  xmlXPathFreeObject(obj);
727  }
728  xmlBufferFree(pattern);
729  }
730  return amount;
731 }
732 
741 void
745 {
747  int amount, i;
748  double number;
749  xsltFormat tokens;
750 
751  if (data->format != NULL) {
752  xsltNumberFormatTokenize(data->format, &tokens);
753  }
754  else {
755  xmlChar *format;
756 
757  /* The format needs to be recomputed each time */
758  if (data->has_format == 0)
759  return;
760  format = xsltEvalAttrValueTemplate(ctxt, data->node,
761  (const xmlChar *) "format",
763  if (format == NULL)
764  return;
765  xsltNumberFormatTokenize(format, &tokens);
766  xmlFree(format);
767  }
768 
769  output = xmlBufferCreate();
770  if (output == NULL)
771  goto XSLT_NUMBER_FORMAT_END;
772 
773  /*
774  * Evaluate the XPath expression to find the value(s)
775  */
776  if (data->value) {
777  amount = xsltNumberFormatGetValue(ctxt->xpathCtxt,
778  node,
779  data->value,
780  &number);
781  if (amount == 1) {
783  &number,
784  1,
785  &tokens,
786  output);
787  }
788 
789  } else if (data->level) {
790 
791  if (xmlStrEqual(data->level, (const xmlChar *) "single")) {
792  amount = xsltNumberFormatGetMultipleLevel(ctxt,
793  node,
794  data->countPat,
795  data->fromPat,
796  &number,
797  1);
798  if (amount == 1) {
800  &number,
801  1,
802  &tokens,
803  output);
804  }
805  } else if (xmlStrEqual(data->level, (const xmlChar *) "multiple")) {
806  double numarray[1024];
807  int max = sizeof(numarray)/sizeof(numarray[0]);
808  amount = xsltNumberFormatGetMultipleLevel(ctxt,
809  node,
810  data->countPat,
811  data->fromPat,
812  numarray,
813  max);
814  if (amount > 0) {
816  numarray,
817  amount,
818  &tokens,
819  output);
820  }
821  } else if (xmlStrEqual(data->level, (const xmlChar *) "any")) {
822  amount = xsltNumberFormatGetAnyLevel(ctxt,
823  node,
824  data->countPat,
825  data->fromPat,
826  &number);
827  if (amount > 0) {
829  &number,
830  1,
831  &tokens,
832  output);
833  }
834  }
835  }
836  /* Insert number as text node */
837  xsltCopyTextString(ctxt, ctxt->insert, xmlBufferContent(output), 0);
838 
839  xmlBufferFree(output);
840 
841 XSLT_NUMBER_FORMAT_END:
842  if (tokens.start != NULL)
843  xmlFree(tokens.start);
844  if (tokens.end != NULL)
845  xmlFree(tokens.end);
846  for (i = 0;i < tokens.nTokens;i++) {
847  if (tokens.tokens[i].separator != NULL)
848  xmlFree(tokens.tokens[i].separator);
849  }
850 }
851 
852 static int
854 {
855  int count=0; /* will hold total length of prefix/suffix */
856  int len;
857 
858  while (1) {
859  /*
860  * prefix / suffix ends at end of string or at
861  * first 'special' character
862  */
863  if (**format == 0)
864  return count;
865  /* if next character 'escaped' just count it */
866  if (**format == SYMBOL_QUOTE) {
867  if (*++(*format) == 0)
868  return -1;
869  }
870  else if (IS_SPECIAL(self, *format))
871  return count;
872  /*
873  * else treat percent/per-mille as special cases,
874  * depending on whether +ve or -ve
875  */
876  else {
877  /*
878  * for +ve prefix/suffix, allow only a
879  * single occurence of either
880  */
881  if (xsltUTF8Charcmp(*format, self->percent) == 0) {
882  if (info->is_multiplier_set)
883  return -1;
884  info->multiplier = 100;
885  info->is_multiplier_set = TRUE;
886  } else if (xsltUTF8Charcmp(*format, self->permille) == 0) {
887  if (info->is_multiplier_set)
888  return -1;
889  info->multiplier = 1000;
890  info->is_multiplier_set = TRUE;
891  }
892  }
893 
894  if ((len=xsltUTF8Size(*format)) < 1)
895  return -1;
896  count += len;
897  *format += len;
898  }
899 }
900 
943 xmlXPathError
945  xmlChar *format,
946  double number,
947  xmlChar **result)
948 {
949  xmlXPathError status = XPATH_EXPRESSION_OK;
951  xmlChar *the_format, *prefix = NULL, *suffix = NULL;
952  xmlChar *nprefix, *nsuffix = NULL;
953  xmlChar pchar;
954  int prefix_length, suffix_length = 0, nprefix_length, nsuffix_length;
955  double scale;
956  int j, len;
957  int self_grouping_len;
959  /*
960  * delayed_multiplier allows a 'trailing' percent or
961  * permille to be treated as suffix
962  */
963  int delayed_multiplier = 0;
964  /* flag to show no -ve format present for -ve number */
965  char default_sign = 0;
966  /* flag to show error found, should use default format */
967  char found_error = 0;
968 
969  if (xmlStrlen(format) <= 0) {
971  "xsltFormatNumberConversion : "
972  "Invalid format (0-length)\n");
973  }
974  *result = NULL;
975  switch (xmlXPathIsInf(number)) {
976  case -1:
977  if (self->minusSign == NULL)
978  *result = xmlStrdup(BAD_CAST "-");
979  else
980  *result = xmlStrdup(self->minusSign);
981  /* no-break on purpose */
982  case 1:
983  if ((self == NULL) || (self->infinity == NULL))
984  *result = xmlStrcat(*result, BAD_CAST "Infinity");
985  else
986  *result = xmlStrcat(*result, self->infinity);
987  return(status);
988  default:
989  if (xmlXPathIsNaN(number)) {
990  if ((self == NULL) || (self->noNumber == NULL))
991  *result = xmlStrdup(BAD_CAST "NaN");
992  else
993  *result = xmlStrdup(self->noNumber);
994  return(status);
995  }
996  }
997 
998  buffer = xmlBufferCreate();
999  if (buffer == NULL) {
1000  return XPATH_MEMORY_ERROR;
1001  }
1002 
1003  format_info.integer_hash = 0;
1004  format_info.integer_digits = 0;
1005  format_info.frac_digits = 0;
1006  format_info.frac_hash = 0;
1007  format_info.group = -1;
1008  format_info.multiplier = 1;
1009  format_info.add_decimal = FALSE;
1010  format_info.is_multiplier_set = FALSE;
1011  format_info.is_negative_pattern = FALSE;
1012 
1013  the_format = format;
1014 
1015  /*
1016  * First we process the +ve pattern to get percent / permille,
1017  * as well as main format
1018  */
1019  prefix = the_format;
1020  prefix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
1021  if (prefix_length < 0) {
1022  found_error = 1;
1023  goto OUTPUT_NUMBER;
1024  }
1025 
1026  /*
1027  * Here we process the "number" part of the format. It gets
1028  * a little messy because of the percent/per-mille - if that
1029  * appears at the end, it may be part of the suffix instead
1030  * of part of the number, so the variable delayed_multiplier
1031  * is used to handle it
1032  */
1033  self_grouping_len = xmlStrlen(self->grouping);
1034  while ((*the_format != 0) &&
1035  (xsltUTF8Charcmp(the_format, self->decimalPoint) != 0) &&
1036  (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) {
1037 
1038  if (delayed_multiplier != 0) {
1039  format_info.multiplier = delayed_multiplier;
1040  format_info.is_multiplier_set = TRUE;
1041  delayed_multiplier = 0;
1042  }
1043  if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
1044  if (format_info.integer_digits > 0) {
1045  found_error = 1;
1046  goto OUTPUT_NUMBER;
1047  }
1048  format_info.integer_hash++;
1049  if (format_info.group >= 0)
1050  format_info.group++;
1051  } else if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
1052  format_info.integer_digits++;
1053  if (format_info.group >= 0)
1054  format_info.group++;
1055  } else if ((self_grouping_len > 0) &&
1056  (!xmlStrncmp(the_format, self->grouping, self_grouping_len))) {
1057  /* Reset group count */
1058  format_info.group = 0;
1059  the_format += self_grouping_len;
1060  continue;
1061  } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
1062  if (format_info.is_multiplier_set) {
1063  found_error = 1;
1064  goto OUTPUT_NUMBER;
1065  }
1066  delayed_multiplier = 100;
1067  } else if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
1068  if (format_info.is_multiplier_set) {
1069  found_error = 1;
1070  goto OUTPUT_NUMBER;
1071  }
1072  delayed_multiplier = 1000;
1073  } else
1074  break; /* while */
1075 
1076  if ((len=xsltUTF8Size(the_format)) < 1) {
1077  found_error = 1;
1078  goto OUTPUT_NUMBER;
1079  }
1080  the_format += len;
1081 
1082  }
1083 
1084  /* We have finished the integer part, now work on fraction */
1085  if (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) {
1086  format_info.add_decimal = TRUE;
1087  the_format += xsltUTF8Size(the_format); /* Skip over the decimal */
1088  }
1089 
1090  while (*the_format != 0) {
1091 
1092  if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
1093  if (format_info.frac_hash != 0) {
1094  found_error = 1;
1095  goto OUTPUT_NUMBER;
1096  }
1097  format_info.frac_digits++;
1098  } else if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
1099  format_info.frac_hash++;
1100  } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
1101  if (format_info.is_multiplier_set) {
1102  found_error = 1;
1103  goto OUTPUT_NUMBER;
1104  }
1105  delayed_multiplier = 100;
1106  if ((len = xsltUTF8Size(the_format)) < 1) {
1107  found_error = 1;
1108  goto OUTPUT_NUMBER;
1109  }
1110  the_format += len;
1111  continue; /* while */
1112  } else if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
1113  if (format_info.is_multiplier_set) {
1114  found_error = 1;
1115  goto OUTPUT_NUMBER;
1116  }
1117  delayed_multiplier = 1000;
1118  if ((len = xsltUTF8Size(the_format)) < 1) {
1119  found_error = 1;
1120  goto OUTPUT_NUMBER;
1121  }
1122  the_format += len;
1123  continue; /* while */
1124  } else if (xsltUTF8Charcmp(the_format, self->grouping) != 0) {
1125  break; /* while */
1126  }
1127  if ((len = xsltUTF8Size(the_format)) < 1) {
1128  found_error = 1;
1129  goto OUTPUT_NUMBER;
1130  }
1131  the_format += len;
1132  if (delayed_multiplier != 0) {
1133  format_info.multiplier = delayed_multiplier;
1134  delayed_multiplier = 0;
1135  format_info.is_multiplier_set = TRUE;
1136  }
1137  }
1138 
1139  /*
1140  * If delayed_multiplier is set after processing the
1141  * "number" part, should be in suffix
1142  */
1143  if (delayed_multiplier != 0) {
1144  the_format -= len;
1145  delayed_multiplier = 0;
1146  }
1147 
1148  suffix = the_format;
1149  suffix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
1150  if ( (suffix_length < 0) ||
1151  ((*the_format != 0) &&
1152  (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) ) {
1153  found_error = 1;
1154  goto OUTPUT_NUMBER;
1155  }
1156 
1157  /*
1158  * We have processed the +ve prefix, number part and +ve suffix.
1159  * If the number is -ve, we must substitute the -ve prefix / suffix
1160  */
1161  if (number < 0) {
1162  /*
1163  * Note that j is the number of UTF8 chars before the separator,
1164  * not the number of bytes! (bug 151975)
1165  */
1166  j = xmlUTF8Strloc(format, self->patternSeparator);
1167  if (j < 0) {
1168  /* No -ve pattern present, so use default signing */
1169  default_sign = 1;
1170  }
1171  else {
1172  /* Skip over pattern separator (accounting for UTF8) */
1173  the_format = (xmlChar *)xmlUTF8Strpos(format, j + 1);
1174  /*
1175  * Flag changes interpretation of percent/permille
1176  * in -ve pattern
1177  */
1178  format_info.is_negative_pattern = TRUE;
1179  format_info.is_multiplier_set = FALSE;
1180 
1181  /* First do the -ve prefix */
1182  nprefix = the_format;
1183  nprefix_length = xsltFormatNumberPreSuffix(self,
1184  &the_format, &format_info);
1185  if (nprefix_length<0) {
1186  found_error = 1;
1187  goto OUTPUT_NUMBER;
1188  }
1189 
1190  while (*the_format != 0) {
1191  if ( (xsltUTF8Charcmp(the_format, (self)->percent) == 0) ||
1192  (xsltUTF8Charcmp(the_format, (self)->permille)== 0) ) {
1193  if (format_info.is_multiplier_set) {
1194  found_error = 1;
1195  goto OUTPUT_NUMBER;
1196  }
1197  format_info.is_multiplier_set = TRUE;
1198  delayed_multiplier = 1;
1199  }
1200  else if (IS_SPECIAL(self, the_format))
1201  delayed_multiplier = 0;
1202  else
1203  break; /* while */
1204  if ((len = xsltUTF8Size(the_format)) < 1) {
1205  found_error = 1;
1206  goto OUTPUT_NUMBER;
1207  }
1208  the_format += len;
1209  }
1210  if (delayed_multiplier != 0) {
1211  format_info.is_multiplier_set = FALSE;
1212  the_format -= len;
1213  }
1214 
1215  /* Finally do the -ve suffix */
1216  if (*the_format != 0) {
1217  nsuffix = the_format;
1218  nsuffix_length = xsltFormatNumberPreSuffix(self,
1219  &the_format, &format_info);
1220  if (nsuffix_length < 0) {
1221  found_error = 1;
1222  goto OUTPUT_NUMBER;
1223  }
1224  }
1225  else
1226  nsuffix_length = 0;
1227  if (*the_format != 0) {
1228  found_error = 1;
1229  goto OUTPUT_NUMBER;
1230  }
1231  /*
1232  * Here's another Java peculiarity:
1233  * if -ve prefix/suffix == +ve ones, discard & use default
1234  */
1235  if ((nprefix_length != prefix_length) ||
1236  (nsuffix_length != suffix_length) ||
1237  ((nprefix_length > 0) &&
1238  (xmlStrncmp(nprefix, prefix, prefix_length) !=0 )) ||
1239  ((nsuffix_length > 0) &&
1240  (xmlStrncmp(nsuffix, suffix, suffix_length) !=0 ))) {
1241  prefix = nprefix;
1242  prefix_length = nprefix_length;
1243  suffix = nsuffix;
1244  suffix_length = nsuffix_length;
1245  } /* else {
1246  default_sign = 1;
1247  }
1248  */
1249  }
1250  }
1251 
1252 OUTPUT_NUMBER:
1253  if (found_error != 0) {
1255  "xsltFormatNumberConversion : "
1256  "error in format string '%s', using default\n", format);
1257  default_sign = (number < 0.0) ? 1 : 0;
1258  prefix_length = suffix_length = 0;
1259  format_info.integer_hash = 0;
1260  format_info.integer_digits = 1;
1261  format_info.frac_digits = 1;
1262  format_info.frac_hash = 4;
1263  format_info.group = -1;
1264  format_info.multiplier = 1;
1265  format_info.add_decimal = TRUE;
1266  }
1267 
1268  /* Ready to output our number. First see if "default sign" is required */
1269  if (default_sign != 0)
1270  xmlBufferAdd(buffer, self->minusSign, xsltUTF8Size(self->minusSign));
1271 
1272  /* Put the prefix into the buffer */
1273  for (j = 0; j < prefix_length; j++) {
1274  if ((pchar = *prefix++) == SYMBOL_QUOTE) {
1275  len = xsltUTF8Size(prefix);
1276  xmlBufferAdd(buffer, prefix, len);
1277  prefix += len;
1278  j += len - 1; /* length of symbol less length of quote */
1279  } else
1280  xmlBufferAdd(buffer, &pchar, 1);
1281  }
1282 
1283  /* Next do the integer part of the number */
1284  number = fabs(number) * (double)format_info.multiplier;
1285  scale = pow(10.0, (double)(format_info.frac_digits + format_info.frac_hash));
1286  number = floor((scale * number + 0.5)) / scale;
1287  if ((self->grouping != NULL) &&
1288  (self->grouping[0] != 0)) {
1289 
1290  len = xmlStrlen(self->grouping);
1291  pchar = xsltGetUTF8Char(self->grouping, &len);
1292  xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
1293  format_info.integer_digits,
1294  format_info.group,
1295  pchar, len);
1296  } else
1297  xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
1298  format_info.integer_digits,
1299  format_info.group,
1300  ',', 1);
1301 
1302  /* Special case: java treats '.#' like '.0', '.##' like '.0#', etc. */
1303  if ((format_info.integer_digits + format_info.integer_hash +
1304  format_info.frac_digits == 0) && (format_info.frac_hash > 0)) {
1305  ++format_info.frac_digits;
1306  --format_info.frac_hash;
1307  }
1308 
1309  /* Add leading zero, if required */
1310  if ((floor(number) == 0) &&
1311  (format_info.integer_digits + format_info.frac_digits == 0)) {
1312  xmlBufferAdd(buffer, self->zeroDigit, xsltUTF8Size(self->zeroDigit));
1313  }
1314 
1315  /* Next the fractional part, if required */
1316  if (format_info.frac_digits + format_info.frac_hash == 0) {
1317  if (format_info.add_decimal)
1318  xmlBufferAdd(buffer, self->decimalPoint,
1319  xsltUTF8Size(self->decimalPoint));
1320  }
1321  else {
1322  number -= floor(number);
1323  if ((number != 0) || (format_info.frac_digits != 0)) {
1324  xmlBufferAdd(buffer, self->decimalPoint,
1325  xsltUTF8Size(self->decimalPoint));
1326  number = floor(scale * number + 0.5);
1327  for (j = format_info.frac_hash; j > 0; j--) {
1328  if (fmod(number, 10.0) >= 1.0)
1329  break; /* for */
1330  number /= 10.0;
1331  }
1332  xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
1333  format_info.frac_digits + j,
1334  0, 0, 0);
1335  }
1336  }
1337  /* Put the suffix into the buffer */
1338  for (j = 0; j < suffix_length; j++) {
1339  if ((pchar = *suffix++) == SYMBOL_QUOTE) {
1340  len = xsltUTF8Size(suffix);
1341  xmlBufferAdd(buffer, suffix, len);
1342  suffix += len;
1343  j += len - 1; /* length of symbol less length of escape */
1344  } else
1345  xmlBufferAdd(buffer, &pchar, 1);
1346  }
1347 
1348  *result = xmlStrdup(xmlBufferContent(buffer));
1349  xmlBufferFree(buffer);
1350  return status;
1351 }
1352 
xsltFormat * xsltFormatPtr
Definition: numbers.c:36
#define IS_DIGIT_ZERO(x)
Definition: numbers.c:117
static int xsltNumberFormatGetValue(xmlXPathContextPtr context, xmlNodePtr node, const xmlChar *value, double *number)
Definition: numbers.c:706
#define MAX_TOKENS
Definition: numbers.c:25
#define SYMBOL_QUOTE
Definition: numbers.c:20
Definition: graphics.c:176
#define max(a, b)
Definition: svc.c:63
static void xsltNumberFormatInsertNumbers(xsltNumberDataPtr data, double *numbers, int numbers_max, xsltFormatPtr tokens, xmlBufferPtr buffer)
Definition: numbers.c:441
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
Definition: get.c:139
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
XMLPUBFUN const xmlChar *XMLCALL xmlBufferContent(const xmlBuffer *buf)
static int xsltTestCompMatchCount(xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xmlNodePtr cur)
Definition: numbers.c:557
struct _xmlNode * prev
Definition: tree.h:497
XMLPUBFUN int XMLCALL xmlCopyCharMultiByte(xmlChar *out, int val)
const xmlChar * name
Definition: tree.h:492
Definition: http.c:6587
xmlChar * separator
Definition: numbers.c:30
GLsizei const GLvoid * pointer
Definition: glext.h:5848
#define DEFAULT_TOKEN
Definition: numbers.c:22
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:41
static int xsltUTF8Charcmp(xmlChar *utf1, xmlChar *utf2)
Definition: numbers.c:93
XMLPUBFUN const xmlChar *XMLCALL xmlUTF8Strpos(const xmlChar *utf, int pos)
Definition: xmlstring.c:894
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:422
XMLPUBFUN void XMLCALL xmlBufferFree(xmlBufferPtr buf)
xmlChar * start
Definition: numbers.c:38
#define TRUE
Definition: numbers.c:17
struct _xsltCompMatch * countPat
static int xsltIsDigitZero(unsigned int ch)
Definition: numbers.c:121
GLuint buffer
Definition: glext.h:5915
#define CHAR_BIT
Definition: urlcache.c:34
xmlChar token
Definition: numbers.c:31
#define XSLT_NAMESPACE
Definition: xslt.h:46
Definition: compobj.c:613
XMLPUBFUN int XMLCALL xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len)
static xsltFormatToken default_token
Definition: numbers.c:46
GLuint const GLubyte mask[]
Definition: s_context.h:57
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate(void)
xmlChar * xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst, const xmlChar *name, const xmlChar *ns)
Definition: templates.c:371
GLsizei GLsizei GLuint * obj
Definition: glext.h:6042
format_info
GLfloat scale
Definition: m_xform.h:122
struct node node
XMLPUBFUN int XMLCALL xmlBufferCCat(xmlBufferPtr buf, const char *str)
const xmlChar * level
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static int xsltUTF8Size(xmlChar *utf)
Definition: numbers.c:63
static void xsltNumberFormatAlpha(xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper)
Definition: numbers.c:213
int xsltGetUTF8Char(const unsigned char *utf, int *len)
Definition: xsltutils.c:234
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:510
float pow(float __x, int __y)
Definition: _cmath.h:458
static size_t double number
Definition: printf.c:64
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:525
const xmlChar * format
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:79
static int xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xsltCompMatchPtr fromPat, double *array, int max)
Definition: numbers.c:657
struct _xmlNode * last
Definition: tree.h:494
smooth NULL
Definition: ftsmooth.c:557
xmlNodePtr xsltCopyTextString(xsltTransformContextPtr ctxt, xmlNodePtr target, const xmlChar *string, int noescape)
Definition: transform.c:830
void xsltNumberFormat(xsltTransformContextPtr ctxt, xsltNumberDataPtr data, xmlNodePtr node)
Definition: numbers.c:742
#define BAD_CAST
Definition: xmlstring.h:35
const xmlChar * value
xmlXPathContextPtr xpathCtxt
xmlChar * end
Definition: numbers.c:41
xsltFormatToken * xsltFormatTokenPtr
Definition: numbers.c:28
GLuint GLfloat * val
Definition: glext.h:7180
struct _xmlNode * parent
Definition: tree.h:495
XMLPUBFUN int XMLCALL xmlBufferCat(xmlBufferPtr buf, const xmlChar *str)
XMLPUBFUN int XMLCALL xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar)
Definition: xmlstring.c:926
#define DEFAULT_SEPARATOR
Definition: numbers.c:23
int token
Definition: lex.c:57
int xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltCompMatchPtr comp)
Definition: pattern.c:1202
_Check_return_ double __cdecl fmod(_In_ double x, _In_ double y)
GLint GLint GLsizei width
Definition: gl.h:1546
if(!(yy_init))
Definition: macro.lex.yy.c:704
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
XMLPUBFUN int XMLCALL xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len)
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
void * xsltGenericErrorContext
Definition: xsltutils.c:511
xsltFormatToken tokens[MAX_TOKENS]
Definition: numbers.c:39
Definition: tree.h:489
static void xsltNumberFormatDecimal(xmlBufferPtr buffer, double number, int digit_zero, int width, int digitsPerGroup, int groupingCharacter, int groupingCharacterLen)
Definition: numbers.c:139
xmlAttr * xmlAttrPtr
Definition: tree.h:433
const XML_Char * prefix
Definition: expat.h:380
unsigned char xmlChar
Definition: xmlstring.h:28
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
XMLPUBFUN int XMLCALL xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:206
GLenum GLsizei len
Definition: glext.h:6722
xmlElementType type
Definition: tree.h:491
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
#define is_upper(c)
Definition: astoll.c:45
#define IS_DIGIT_ONE(x)
Definition: numbers.c:118
#define IS_LETTER(c)
static int xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltFormatNumberInfoPtr info)
Definition: numbers.c:853
static void xsltNumberFormatRoman(xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper)
Definition: numbers.c:260
xmlXPathError xsltFormatNumberConversion(xsltDecimalFormatPtr self, xmlChar *format, double number, xmlChar **result)
Definition: numbers.c:944
static char alpha_upper_list[]
Definition: numbers.c:44
int nTokens
Definition: numbers.c:40
#define IS_DIGIT(c)
Definition: import.c:85
struct _xsltCompMatch * fromPat
#define FALSE
Definition: numbers.c:16
static char alpha_lower_list[]
Definition: numbers.c:45
static void xsltNumberFormatTokenize(const xmlChar *format, xsltFormatPtr tokens)
Definition: numbers.c:335
xmlNs * ns
Definition: tree.h:501
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:157
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:685
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
static int xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xsltCompMatchPtr fromPat, double *array)
Definition: numbers.c:594
const xmlChar * href
Definition: tree.h:392
GLuint64EXT * result
Definition: glext.h:11304
#define IS_SPECIAL(self, letter)
Definition: numbers.c:110
static SERVICE_STATUS status
Definition: service.c:26
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
GLubyte * pattern
Definition: glext.h:7787
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29
Definition: ps.c:97