00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef HAVE_CONFIG_H
00019 # include <config.h>
00020 #endif
00021
00022
00023 #if WIDE_CHAR_VERSION
00024 # include "wprintf-parse.h"
00025 #else
00026 # include "printf-parse.h"
00027 #endif
00028
00029
00030 #include <stddef.h>
00031
00032
00033 #if HAVE_STDINT_H_WITH_UINTMAX
00034 # include <stdint.h>
00035 #endif
00036 #if HAVE_INTTYPES_H_WITH_UINTMAX
00037 # include <inttypes.h>
00038 #endif
00039
00040
00041 #include <stdlib.h>
00042
00043
00044 #include "xsize.h"
00045
00046 #if WIDE_CHAR_VERSION
00047 # define PRINTF_PARSE wprintf_parse
00048 # define CHAR_T wchar_t
00049 # define DIRECTIVE wchar_t_directive
00050 # define DIRECTIVES wchar_t_directives
00051 #else
00052 # define PRINTF_PARSE printf_parse
00053 # define CHAR_T char
00054 # define DIRECTIVE char_directive
00055 # define DIRECTIVES char_directives
00056 #endif
00057
00058 #ifdef STATIC
00059 STATIC
00060 #endif
00061 int
00062 PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
00063 {
00064 const CHAR_T *cp = format;
00065 size_t arg_posn = 0;
00066 size_t d_allocated;
00067 size_t a_allocated;
00068 size_t max_width_length = 0;
00069 size_t max_precision_length = 0;
00070
00071 d->count = 0;
00072 d_allocated = 1;
00073 d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
00074 if (d->dir == NULL)
00075
00076 return -1;
00077
00078 a->count = 0;
00079 a_allocated = 0;
00080 a->arg = NULL;
00081
00082 #define REGISTER_ARG(_index_,_type_) \
00083 { \
00084 size_t n = (_index_); \
00085 if (n >= a_allocated) \
00086 { \
00087 size_t memory_size; \
00088 argument *memory; \
00089 \
00090 a_allocated = xtimes (a_allocated, 2); \
00091 if (a_allocated <= n) \
00092 a_allocated = xsum (n, 1); \
00093 memory_size = xtimes (a_allocated, sizeof (argument)); \
00094 if (size_overflow_p (memory_size)) \
00095 \
00096 goto error; \
00097 memory = (a->arg \
00098 ? realloc (a->arg, memory_size) \
00099 : malloc (memory_size)); \
00100 if (memory == NULL) \
00101 \
00102 goto error; \
00103 a->arg = memory; \
00104 } \
00105 while (a->count <= n) \
00106 a->arg[a->count++].type = TYPE_NONE; \
00107 if (a->arg[n].type == TYPE_NONE) \
00108 a->arg[n].type = (_type_); \
00109 else if (a->arg[n].type != (_type_)) \
00110 \
00111 goto error; \
00112 }
00113
00114 while (*cp != '\0')
00115 {
00116 CHAR_T c = *cp++;
00117 if (c == '%')
00118 {
00119 size_t arg_index = ARG_NONE;
00120 DIRECTIVE *dp = &d->dir[d->count];
00121
00122
00123 dp->dir_start = cp - 1;
00124 dp->flags = 0;
00125 dp->width_start = NULL;
00126 dp->width_end = NULL;
00127 dp->width_arg_index = ARG_NONE;
00128 dp->precision_start = NULL;
00129 dp->precision_end = NULL;
00130 dp->precision_arg_index = ARG_NONE;
00131 dp->arg_index = ARG_NONE;
00132
00133
00134 if (*cp >= '0' && *cp <= '9')
00135 {
00136 const CHAR_T *np;
00137
00138 for (np = cp; *np >= '0' && *np <= '9'; np++)
00139 ;
00140 if (*np == '$')
00141 {
00142 size_t n = 0;
00143
00144 for (np = cp; *np >= '0' && *np <= '9'; np++)
00145 n = xsum (xtimes (n, 10), *np - '0');
00146 if (n == 0)
00147
00148 goto error;
00149 if (size_overflow_p (n))
00150
00151 goto error;
00152 arg_index = n - 1;
00153 cp = np + 1;
00154 }
00155 }
00156
00157
00158 for (;;)
00159 {
00160 if (*cp == '\'')
00161 {
00162 dp->flags |= FLAG_GROUP;
00163 cp++;
00164 }
00165 else if (*cp == '-')
00166 {
00167 dp->flags |= FLAG_LEFT;
00168 cp++;
00169 }
00170 else if (*cp == '+')
00171 {
00172 dp->flags |= FLAG_SHOWSIGN;
00173 cp++;
00174 }
00175 else if (*cp == ' ')
00176 {
00177 dp->flags |= FLAG_SPACE;
00178 cp++;
00179 }
00180 else if (*cp == '#')
00181 {
00182 dp->flags |= FLAG_ALT;
00183 cp++;
00184 }
00185 else if (*cp == '0')
00186 {
00187 dp->flags |= FLAG_ZERO;
00188 cp++;
00189 }
00190 else
00191 break;
00192 }
00193
00194
00195 if (*cp == '*')
00196 {
00197 dp->width_start = cp;
00198 cp++;
00199 dp->width_end = cp;
00200 if (max_width_length < 1)
00201 max_width_length = 1;
00202
00203
00204 if (*cp >= '0' && *cp <= '9')
00205 {
00206 const CHAR_T *np;
00207
00208 for (np = cp; *np >= '0' && *np <= '9'; np++)
00209 ;
00210 if (*np == '$')
00211 {
00212 size_t n = 0;
00213
00214 for (np = cp; *np >= '0' && *np <= '9'; np++)
00215 n = xsum (xtimes (n, 10), *np - '0');
00216 if (n == 0)
00217
00218 goto error;
00219 if (size_overflow_p (n))
00220
00221 goto error;
00222 dp->width_arg_index = n - 1;
00223 cp = np + 1;
00224 }
00225 }
00226 if (dp->width_arg_index == ARG_NONE)
00227 {
00228 dp->width_arg_index = arg_posn++;
00229 if (dp->width_arg_index == ARG_NONE)
00230
00231 goto error;
00232 }
00233 REGISTER_ARG (dp->width_arg_index, TYPE_INT);
00234 }
00235 else if (*cp >= '0' && *cp <= '9')
00236 {
00237 size_t width_length;
00238
00239 dp->width_start = cp;
00240 for (; *cp >= '0' && *cp <= '9'; cp++)
00241 ;
00242 dp->width_end = cp;
00243 width_length = dp->width_end - dp->width_start;
00244 if (max_width_length < width_length)
00245 max_width_length = width_length;
00246 }
00247
00248
00249 if (*cp == '.')
00250 {
00251 cp++;
00252 if (*cp == '*')
00253 {
00254 dp->precision_start = cp - 1;
00255 cp++;
00256 dp->precision_end = cp;
00257 if (max_precision_length < 2)
00258 max_precision_length = 2;
00259
00260
00261 if (*cp >= '0' && *cp <= '9')
00262 {
00263 const CHAR_T *np;
00264
00265 for (np = cp; *np >= '0' && *np <= '9'; np++)
00266 ;
00267 if (*np == '$')
00268 {
00269 size_t n = 0;
00270
00271 for (np = cp; *np >= '0' && *np <= '9'; np++)
00272 n = xsum (xtimes (n, 10), *np - '0');
00273 if (n == 0)
00274
00275 goto error;
00276 if (size_overflow_p (n))
00277
00278
00279 goto error;
00280 dp->precision_arg_index = n - 1;
00281 cp = np + 1;
00282 }
00283 }
00284 if (dp->precision_arg_index == ARG_NONE)
00285 {
00286 dp->precision_arg_index = arg_posn++;
00287 if (dp->precision_arg_index == ARG_NONE)
00288
00289 goto error;
00290 }
00291 REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
00292 }
00293 else
00294 {
00295 size_t precision_length;
00296
00297 dp->precision_start = cp - 1;
00298 for (; *cp >= '0' && *cp <= '9'; cp++)
00299 ;
00300 dp->precision_end = cp;
00301 precision_length = dp->precision_end - dp->precision_start;
00302 if (max_precision_length < precision_length)
00303 max_precision_length = precision_length;
00304 }
00305 }
00306
00307 {
00308 arg_type type;
00309
00310
00311 {
00312 int flags = 0;
00313
00314 for (;;)
00315 {
00316 if (*cp == 'h')
00317 {
00318 flags |= (1 << (flags & 1));
00319 cp++;
00320 }
00321 else if (*cp == 'L')
00322 {
00323 flags |= 4;
00324 cp++;
00325 }
00326 else if (*cp == 'l')
00327 {
00328 flags += 8;
00329 cp++;
00330 }
00331 #ifdef HAVE_INTMAX_T
00332 else if (*cp == 'j')
00333 {
00334 if (sizeof (intmax_t) > sizeof (long))
00335 {
00336
00337 flags += 16;
00338 }
00339 else if (sizeof (intmax_t) > sizeof (int))
00340 {
00341
00342 flags += 8;
00343 }
00344 cp++;
00345 }
00346 #endif
00347 else if (*cp == 'z' || *cp == 'Z')
00348 {
00349
00350
00351
00352 if (sizeof (size_t) > sizeof (long))
00353 {
00354
00355 flags += 16;
00356 }
00357 else if (sizeof (size_t) > sizeof (int))
00358 {
00359
00360 flags += 8;
00361 }
00362 cp++;
00363 }
00364 else if (*cp == 't')
00365 {
00366 if (sizeof (ptrdiff_t) > sizeof (long))
00367 {
00368
00369 flags += 16;
00370 }
00371 else if (sizeof (ptrdiff_t) > sizeof (int))
00372 {
00373
00374 flags += 8;
00375 }
00376 cp++;
00377 }
00378 else
00379 break;
00380 }
00381
00382
00383 c = *cp++;
00384 switch (c)
00385 {
00386 case 'd': case 'i':
00387 #ifdef HAVE_LONG_LONG
00388 if (flags >= 16 || (flags & 4))
00389 type = TYPE_LONGLONGINT;
00390 else
00391 #endif
00392 if (flags >= 8)
00393 type = TYPE_LONGINT;
00394 else if (flags & 2)
00395 type = TYPE_SCHAR;
00396 else if (flags & 1)
00397 type = TYPE_SHORT;
00398 else
00399 type = TYPE_INT;
00400 break;
00401 case 'o': case 'u': case 'x': case 'X':
00402 #ifdef HAVE_LONG_LONG
00403 if (flags >= 16 || (flags & 4))
00404 type = TYPE_ULONGLONGINT;
00405 else
00406 #endif
00407 if (flags >= 8)
00408 type = TYPE_ULONGINT;
00409 else if (flags & 2)
00410 type = TYPE_UCHAR;
00411 else if (flags & 1)
00412 type = TYPE_USHORT;
00413 else
00414 type = TYPE_UINT;
00415 break;
00416 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
00417 case 'a': case 'A':
00418 #ifdef HAVE_LONG_DOUBLE
00419 if (flags >= 16 || (flags & 4))
00420 type = TYPE_LONGDOUBLE;
00421 else
00422 #endif
00423 type = TYPE_DOUBLE;
00424 break;
00425 case 'c':
00426 if (flags >= 8)
00427 #ifdef HAVE_WINT_T
00428 type = TYPE_WIDE_CHAR;
00429 #else
00430 goto error;
00431 #endif
00432 else
00433 type = TYPE_CHAR;
00434 break;
00435 #ifdef HAVE_WINT_T
00436 case 'C':
00437 type = TYPE_WIDE_CHAR;
00438 c = 'c';
00439 break;
00440 #endif
00441 case 's':
00442 if (flags >= 8)
00443 #ifdef HAVE_WCHAR_T
00444 type = TYPE_WIDE_STRING;
00445 #else
00446 goto error;
00447 #endif
00448 else
00449 type = TYPE_STRING;
00450 break;
00451 #ifdef HAVE_WCHAR_T
00452 case 'S':
00453 type = TYPE_WIDE_STRING;
00454 c = 's';
00455 break;
00456 #endif
00457 case 'p':
00458 type = TYPE_POINTER;
00459 break;
00460 case 'n':
00461 #ifdef HAVE_LONG_LONG
00462 if (flags >= 16 || (flags & 4))
00463 type = TYPE_COUNT_LONGLONGINT_POINTER;
00464 else
00465 #endif
00466 if (flags >= 8)
00467 type = TYPE_COUNT_LONGINT_POINTER;
00468 else if (flags & 2)
00469 type = TYPE_COUNT_SCHAR_POINTER;
00470 else if (flags & 1)
00471 type = TYPE_COUNT_SHORT_POINTER;
00472 else
00473 type = TYPE_COUNT_INT_POINTER;
00474 break;
00475 case '%':
00476 type = TYPE_NONE;
00477 break;
00478 default:
00479
00480 goto error;
00481 }
00482 }
00483
00484 if (type != TYPE_NONE)
00485 {
00486 dp->arg_index = arg_index;
00487 if (dp->arg_index == ARG_NONE)
00488 {
00489 dp->arg_index = arg_posn++;
00490 if (dp->arg_index == ARG_NONE)
00491
00492 goto error;
00493 }
00494 REGISTER_ARG (dp->arg_index, type);
00495 }
00496 dp->conversion = c;
00497 dp->dir_end = cp;
00498 }
00499
00500 d->count++;
00501 if (d->count >= d_allocated)
00502 {
00503 size_t memory_size;
00504 DIRECTIVE *memory;
00505
00506 d_allocated = xtimes (d_allocated, 2);
00507 memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
00508 if (size_overflow_p (memory_size))
00509
00510 goto error;
00511 memory = realloc (d->dir, memory_size);
00512 if (memory == NULL)
00513
00514 goto error;
00515 d->dir = memory;
00516 }
00517 }
00518 }
00519 d->dir[d->count].dir_start = cp;
00520
00521 d->max_width_length = max_width_length;
00522 d->max_precision_length = max_precision_length;
00523 return 0;
00524
00525 error:
00526 if (a->arg)
00527 free (a->arg);
00528 if (d->dir)
00529 free (d->dir);
00530 return -1;
00531 }
00532
00533 #undef DIRECTIVES
00534 #undef DIRECTIVE
00535 #undef CHAR_T
00536 #undef PRINTF_PARSE