/[zanavi_public1]/navit/intl/printf-parse.c
ZANavi

Contents of /navit/intl/printf-parse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 11995 byte(s)
import files
1 zoff99 2 /* Formatted output to strings.
2     Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
3    
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU Library General Public License as published
6     by the Free Software Foundation; either version 2, or (at your option)
7     any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     Library General Public License for more details.
13    
14     You should have received a copy of the GNU Library General Public
15     License along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17     USA. */
18    
19     #ifdef HAVE_CONFIG_H
20     # include <config.h>
21     #endif
22    
23     /* Specification. */
24     #if WIDE_CHAR_VERSION
25     # include "wprintf-parse.h"
26     #else
27     # include "printf-parse.h"
28     #endif
29    
30     /* Get size_t, NULL. */
31     #include <stddef.h>
32    
33     /* Get intmax_t. */
34     #if HAVE_STDINT_H_WITH_UINTMAX
35     # include <stdint.h>
36     #endif
37     #if HAVE_INTTYPES_H_WITH_UINTMAX
38     # include <inttypes.h>
39     #endif
40    
41     /* malloc(), realloc(), free(). */
42     #include <stdlib.h>
43    
44     /* Checked size_t computations. */
45     #include "xsize.h"
46    
47     #if WIDE_CHAR_VERSION
48     # define PRINTF_PARSE wprintf_parse
49     # define CHAR_T wchar_t
50     # define DIRECTIVE wchar_t_directive
51     # define DIRECTIVES wchar_t_directives
52     #else
53     # define PRINTF_PARSE printf_parse
54     # define CHAR_T char
55     # define DIRECTIVE char_directive
56     # define DIRECTIVES char_directives
57     #endif
58    
59     #ifdef STATIC
60     STATIC
61     #endif
62     int
63     PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
64     {
65     const CHAR_T *cp = format; /* pointer into format */
66     size_t arg_posn = 0; /* number of regular arguments consumed */
67     size_t d_allocated; /* allocated elements of d->dir */
68     size_t a_allocated; /* allocated elements of a->arg */
69     size_t max_width_length = 0;
70     size_t max_precision_length = 0;
71    
72     d->count = 0;
73     d_allocated = 1;
74     d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
75     if (d->dir == NULL)
76     /* Out of memory. */
77     return -1;
78    
79     a->count = 0;
80     a_allocated = 0;
81     a->arg = NULL;
82    
83     #define REGISTER_ARG(_index_,_type_) \
84     { \
85     size_t n = (_index_); \
86     if (n >= a_allocated) \
87     { \
88     size_t memory_size; \
89     argument *memory; \
90     \
91     a_allocated = xtimes (a_allocated, 2); \
92     if (a_allocated <= n) \
93     a_allocated = xsum (n, 1); \
94     memory_size = xtimes (a_allocated, sizeof (argument)); \
95     if (size_overflow_p (memory_size)) \
96     /* Overflow, would lead to out of memory. */ \
97     goto error; \
98     memory = (a->arg \
99     ? realloc (a->arg, memory_size) \
100     : malloc (memory_size)); \
101     if (memory == NULL) \
102     /* Out of memory. */ \
103     goto error; \
104     a->arg = memory; \
105     } \
106     while (a->count <= n) \
107     a->arg[a->count++].type = TYPE_NONE; \
108     if (a->arg[n].type == TYPE_NONE) \
109     a->arg[n].type = (_type_); \
110     else if (a->arg[n].type != (_type_)) \
111     /* Ambiguous type for positional argument. */ \
112     goto error; \
113     }
114    
115     while (*cp != '\0')
116     {
117     CHAR_T c = *cp++;
118     if (c == '%')
119     {
120     size_t arg_index = ARG_NONE;
121     DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
122    
123     /* Initialize the next directive. */
124     dp->dir_start = cp - 1;
125     dp->flags = 0;
126     dp->width_start = NULL;
127     dp->width_end = NULL;
128     dp->width_arg_index = ARG_NONE;
129     dp->precision_start = NULL;
130     dp->precision_end = NULL;
131     dp->precision_arg_index = ARG_NONE;
132     dp->arg_index = ARG_NONE;
133    
134     /* Test for positional argument. */
135     if (*cp >= '0' && *cp <= '9')
136     {
137     const CHAR_T *np;
138    
139     for (np = cp; *np >= '0' && *np <= '9'; np++)
140     ;
141     if (*np == '$')
142     {
143     size_t n = 0;
144    
145     for (np = cp; *np >= '0' && *np <= '9'; np++)
146     n = xsum (xtimes (n, 10), *np - '0');
147     if (n == 0)
148     /* Positional argument 0. */
149     goto error;
150     if (size_overflow_p (n))
151     /* n too large, would lead to out of memory later. */
152     goto error;
153     arg_index = n - 1;
154     cp = np + 1;
155     }
156     }
157    
158     /* Read the flags. */
159     for (;;)
160     {
161     if (*cp == '\'')
162     {
163     dp->flags |= FLAG_GROUP;
164     cp++;
165     }
166     else if (*cp == '-')
167     {
168     dp->flags |= FLAG_LEFT;
169     cp++;
170     }
171     else if (*cp == '+')
172     {
173     dp->flags |= FLAG_SHOWSIGN;
174     cp++;
175     }
176     else if (*cp == ' ')
177     {
178     dp->flags |= FLAG_SPACE;
179     cp++;
180     }
181     else if (*cp == '#')
182     {
183     dp->flags |= FLAG_ALT;
184     cp++;
185     }
186     else if (*cp == '0')
187     {
188     dp->flags |= FLAG_ZERO;
189     cp++;
190     }
191     else
192     break;
193     }
194    
195     /* Parse the field width. */
196     if (*cp == '*')
197     {
198     dp->width_start = cp;
199     cp++;
200     dp->width_end = cp;
201     if (max_width_length < 1)
202     max_width_length = 1;
203    
204     /* Test for positional argument. */
205     if (*cp >= '0' && *cp <= '9')
206     {
207     const CHAR_T *np;
208    
209     for (np = cp; *np >= '0' && *np <= '9'; np++)
210     ;
211     if (*np == '$')
212     {
213     size_t n = 0;
214    
215     for (np = cp; *np >= '0' && *np <= '9'; np++)
216     n = xsum (xtimes (n, 10), *np - '0');
217     if (n == 0)
218     /* Positional argument 0. */
219     goto error;
220     if (size_overflow_p (n))
221     /* n too large, would lead to out of memory later. */
222     goto error;
223     dp->width_arg_index = n - 1;
224     cp = np + 1;
225     }
226     }
227     if (dp->width_arg_index == ARG_NONE)
228     {
229     dp->width_arg_index = arg_posn++;
230     if (dp->width_arg_index == ARG_NONE)
231     /* arg_posn wrapped around. */
232     goto error;
233     }
234     REGISTER_ARG (dp->width_arg_index, TYPE_INT);
235     }
236     else if (*cp >= '0' && *cp <= '9')
237     {
238     size_t width_length;
239    
240     dp->width_start = cp;
241     for (; *cp >= '0' && *cp <= '9'; cp++)
242     ;
243     dp->width_end = cp;
244     width_length = dp->width_end - dp->width_start;
245     if (max_width_length < width_length)
246     max_width_length = width_length;
247     }
248    
249     /* Parse the precision. */
250     if (*cp == '.')
251     {
252     cp++;
253     if (*cp == '*')
254     {
255     dp->precision_start = cp - 1;
256     cp++;
257     dp->precision_end = cp;
258     if (max_precision_length < 2)
259     max_precision_length = 2;
260    
261     /* Test for positional argument. */
262     if (*cp >= '0' && *cp <= '9')
263     {
264     const CHAR_T *np;
265    
266     for (np = cp; *np >= '0' && *np <= '9'; np++)
267     ;
268     if (*np == '$')
269     {
270     size_t n = 0;
271    
272     for (np = cp; *np >= '0' && *np <= '9'; np++)
273     n = xsum (xtimes (n, 10), *np - '0');
274     if (n == 0)
275     /* Positional argument 0. */
276     goto error;
277     if (size_overflow_p (n))
278     /* n too large, would lead to out of memory
279     later. */
280     goto error;
281     dp->precision_arg_index = n - 1;
282     cp = np + 1;
283     }
284     }
285     if (dp->precision_arg_index == ARG_NONE)
286     {
287     dp->precision_arg_index = arg_posn++;
288     if (dp->precision_arg_index == ARG_NONE)
289     /* arg_posn wrapped around. */
290     goto error;
291     }
292     REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
293     }
294     else
295     {
296     size_t precision_length;
297    
298     dp->precision_start = cp - 1;
299     for (; *cp >= '0' && *cp <= '9'; cp++)
300     ;
301     dp->precision_end = cp;
302     precision_length = dp->precision_end - dp->precision_start;
303     if (max_precision_length < precision_length)
304     max_precision_length = precision_length;
305     }
306     }
307    
308     {
309     arg_type type;
310    
311     /* Parse argument type/size specifiers. */
312     {
313     int flags = 0;
314    
315     for (;;)
316     {
317     if (*cp == 'h')
318     {
319     flags |= (1 << (flags & 1));
320     cp++;
321     }
322     else if (*cp == 'L')
323     {
324     flags |= 4;
325     cp++;
326     }
327     else if (*cp == 'l')
328     {
329     flags += 8;
330     cp++;
331     }
332     #ifdef HAVE_INTMAX_T
333     else if (*cp == 'j')
334     {
335     if (sizeof (intmax_t) > sizeof (long))
336     {
337     /* intmax_t = long long */
338     flags += 16;
339     }
340     else if (sizeof (intmax_t) > sizeof (int))
341     {
342     /* intmax_t = long */
343     flags += 8;
344     }
345     cp++;
346     }
347     #endif
348     else if (*cp == 'z' || *cp == 'Z')
349     {
350     /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
351     because the warning facility in gcc-2.95.2 understands
352     only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
353     if (sizeof (size_t) > sizeof (long))
354     {
355     /* size_t = long long */
356     flags += 16;
357     }
358     else if (sizeof (size_t) > sizeof (int))
359     {
360     /* size_t = long */
361     flags += 8;
362     }
363     cp++;
364     }
365     else if (*cp == 't')
366     {
367     if (sizeof (ptrdiff_t) > sizeof (long))
368     {
369     /* ptrdiff_t = long long */
370     flags += 16;
371     }
372     else if (sizeof (ptrdiff_t) > sizeof (int))
373     {
374     /* ptrdiff_t = long */
375     flags += 8;
376     }
377     cp++;
378     }
379     else
380     break;
381     }
382    
383     /* Read the conversion character. */
384     c = *cp++;
385     switch (c)
386     {
387     case 'd': case 'i':
388     #ifdef HAVE_LONG_LONG
389     if (flags >= 16 || (flags & 4))
390     type = TYPE_LONGLONGINT;
391     else
392     #endif
393     if (flags >= 8)
394     type = TYPE_LONGINT;
395     else if (flags & 2)
396     type = TYPE_SCHAR;
397     else if (flags & 1)
398     type = TYPE_SHORT;
399     else
400     type = TYPE_INT;
401     break;
402     case 'o': case 'u': case 'x': case 'X':
403     #ifdef HAVE_LONG_LONG
404     if (flags >= 16 || (flags & 4))
405     type = TYPE_ULONGLONGINT;
406     else
407     #endif
408     if (flags >= 8)
409     type = TYPE_ULONGINT;
410     else if (flags & 2)
411     type = TYPE_UCHAR;
412     else if (flags & 1)
413     type = TYPE_USHORT;
414     else
415     type = TYPE_UINT;
416     break;
417     case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
418     case 'a': case 'A':
419     #ifdef HAVE_LONG_DOUBLE
420     if (flags >= 16 || (flags & 4))
421     type = TYPE_LONGDOUBLE;
422     else
423     #endif
424     type = TYPE_DOUBLE;
425     break;
426     case 'c':
427     if (flags >= 8)
428     #ifdef HAVE_WINT_T
429     type = TYPE_WIDE_CHAR;
430     #else
431     goto error;
432     #endif
433     else
434     type = TYPE_CHAR;
435     break;
436     #ifdef HAVE_WINT_T
437     case 'C':
438     type = TYPE_WIDE_CHAR;
439     c = 'c';
440     break;
441     #endif
442     case 's':
443     if (flags >= 8)
444     #ifdef HAVE_WCHAR_T
445     type = TYPE_WIDE_STRING;
446     #else
447     goto error;
448     #endif
449     else
450     type = TYPE_STRING;
451     break;
452     #ifdef HAVE_WCHAR_T
453     case 'S':
454     type = TYPE_WIDE_STRING;
455     c = 's';
456     break;
457     #endif
458     case 'p':
459     type = TYPE_POINTER;
460     break;
461     case 'n':
462     #ifdef HAVE_LONG_LONG
463     if (flags >= 16 || (flags & 4))
464     type = TYPE_COUNT_LONGLONGINT_POINTER;
465     else
466     #endif
467     if (flags >= 8)
468     type = TYPE_COUNT_LONGINT_POINTER;
469     else if (flags & 2)
470     type = TYPE_COUNT_SCHAR_POINTER;
471     else if (flags & 1)
472     type = TYPE_COUNT_SHORT_POINTER;
473     else
474     type = TYPE_COUNT_INT_POINTER;
475     break;
476     case '%':
477     type = TYPE_NONE;
478     break;
479     default:
480     /* Unknown conversion character. */
481     goto error;
482     }
483     }
484    
485     if (type != TYPE_NONE)
486     {
487     dp->arg_index = arg_index;
488     if (dp->arg_index == ARG_NONE)
489     {
490     dp->arg_index = arg_posn++;
491     if (dp->arg_index == ARG_NONE)
492     /* arg_posn wrapped around. */
493     goto error;
494     }
495     REGISTER_ARG (dp->arg_index, type);
496     }
497     dp->conversion = c;
498     dp->dir_end = cp;
499     }
500    
501     d->count++;
502     if (d->count >= d_allocated)
503     {
504     size_t memory_size;
505     DIRECTIVE *memory;
506    
507     d_allocated = xtimes (d_allocated, 2);
508     memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
509     if (size_overflow_p (memory_size))
510     /* Overflow, would lead to out of memory. */
511     goto error;
512     memory = realloc (d->dir, memory_size);
513     if (memory == NULL)
514     /* Out of memory. */
515     goto error;
516     d->dir = memory;
517     }
518     }
519     }
520     d->dir[d->count].dir_start = cp;
521    
522     d->max_width_length = max_width_length;
523     d->max_precision_length = max_precision_length;
524     return 0;
525    
526     error:
527     if (a->arg)
528     free (a->arg);
529     if (d->dir)
530     free (d->dir);
531     return -1;
532     }
533    
534     #undef DIRECTIVES
535     #undef DIRECTIVE
536     #undef CHAR_T
537     #undef PRINTF_PARSE

   
Visit the ZANavi Wiki