105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Formatted output to strings. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 1999-2000, 2002-2003, 2006-2012 Free Software Foundation, Inc. 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software; you can redistribute it and/or modify 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang it under the terms of the GNU General Public License as published by 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation; either version 3, or (at your option) 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang any later version. 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU General Public License for more details. 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License along 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang with this program; if not, see <http://www.gnu.org/licenses/>. */ 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* This file can be parametrized with the following macros: 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang CHAR_T The element type of the format string. 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang in the format string are ASCII. 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang DIRECTIVE Structure denoting a format directive. 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Depends on CHAR_T. 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang DIRECTIVES Structure denoting the set of format directives of a 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang format string. Depends on CHAR_T. 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang PRINTF_PARSE Function that parses a format string. 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang Depends on CHAR_T. 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang STATIC Set to 'static' to declare the function static. 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */ 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef PRINTF_PARSE 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <config.h> 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification. */ 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef PRINTF_PARSE 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "printf-parse.h" 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Default parameters. */ 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef PRINTF_PARSE 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define PRINTF_PARSE printf_parse 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define CHAR_T char 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define DIRECTIVE char_directive 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define DIRECTIVES char_directives 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Get size_t, NULL. */ 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stddef.h> 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Get intmax_t. */ 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined IN_LIBINTL || defined IN_LIBASPRINTF 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_STDINT_H_WITH_UINTMAX 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <stdint.h> 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_INTTYPES_H_WITH_UINTMAX 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <inttypes.h> 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <stdint.h> 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* malloc(), realloc(), free(). */ 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdlib.h> 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* memcpy(). */ 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <string.h> 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* errno. */ 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <errno.h> 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Checked size_t computations. */ 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "xsize.h" 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if CHAR_T_ONLY_ASCII 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* c_isascii(). */ 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "c-ctype.h" 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef STATIC 8005436638acc7c010349a69c3395f1a57c642dc62Ying WangSTATIC 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 8305436638acc7c010349a69c3395f1a57c642dc62Ying WangPRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang const CHAR_T *cp = format; /* pointer into format */ 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t arg_posn = 0; /* number of regular arguments consumed */ 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t d_allocated; /* allocated elements of d->dir */ 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t a_allocated; /* allocated elements of a->arg */ 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t max_width_length = 0; 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t max_precision_length = 0; 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang d->count = 0; 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang d_allocated = N_DIRECT_ALLOC_DIRECTIVES; 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang d->dir = d->direct_alloc_dir; 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang a->count = 0; 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang a_allocated = N_DIRECT_ALLOC_ARGUMENTS; 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang a->arg = a->direct_alloc_arg; 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define REGISTER_ARG(_index_,_type_) \ 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { \ 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t n = (_index_); \ 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (n >= a_allocated) \ 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { \ 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t memory_size; \ 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang argument *memory; \ 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang \ 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang a_allocated = xtimes (a_allocated, 2); \ 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (a_allocated <= n) \ 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang a_allocated = xsum (n, 1); \ 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang memory_size = xtimes (a_allocated, sizeof (argument)); \ 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (size_overflow_p (memory_size)) \ 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Overflow, would lead to out of memory. */ \ 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto out_of_memory; \ 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang memory = (argument *) (a->arg != a->direct_alloc_arg \ 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang ? realloc (a->arg, memory_size) \ 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang : malloc (memory_size)); \ 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (memory == NULL) \ 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Out of memory. */ \ 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto out_of_memory; \ 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (a->arg == a->direct_alloc_arg) \ 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang memcpy (memory, a->arg, a->count * sizeof (argument)); \ 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang a->arg = memory; \ 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } \ 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (a->count <= n) \ 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang a->arg[a->count++].type = TYPE_NONE; \ 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (a->arg[n].type == TYPE_NONE) \ 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang a->arg[n].type = (_type_); \ 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (a->arg[n].type != (_type_)) \ 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Ambiguous type for positional argument. */ \ 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; \ 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (*cp != '\0') 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang CHAR_T c = *cp++; 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (c == '%') 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t arg_index = ARG_NONE; 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */ 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Initialize the next directive. */ 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->dir_start = cp - 1; 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags = 0; 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_start = NULL; 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_end = NULL; 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_arg_index = ARG_NONE; 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_start = NULL; 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_end = NULL; 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_arg_index = ARG_NONE; 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->arg_index = ARG_NONE; 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Test for positional argument. */ 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp >= '0' && *cp <= '9') 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang const CHAR_T *np; 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (np = cp; *np >= '0' && *np <= '9'; np++) 15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang ; 16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*np == '$') 16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t n = 0; 16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (np = cp; *np >= '0' && *np <= '9'; np++) 16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang n = xsum (xtimes (n, 10), *np - '0'); 16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (n == 0) 16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Positional argument 0. */ 16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (size_overflow_p (n)) 17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* n too large, would lead to out of memory later. */ 17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang arg_index = n - 1; 17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = np + 1; 17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Read the flags. */ 17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (;;) 17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp == '\'') 18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags |= FLAG_GROUP; 18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == '-') 18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags |= FLAG_LEFT; 18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == '+') 19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags |= FLAG_SHOWSIGN; 19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == ' ') 19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags |= FLAG_SPACE; 19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == '#') 20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags |= FLAG_ALT; 20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == '0') 20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags |= FLAG_ZERO; 20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if __GLIBC__ >= 2 && !defined __UCLIBC__ 21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 'I') 21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->flags |= FLAG_LOCALIZED; 21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 21705436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Parse the field width. */ 22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp == '*') 22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_start = cp; 22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_end = cp; 22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (max_width_length < 1) 22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang max_width_length = 1; 22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Test for positional argument. */ 23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp >= '0' && *cp <= '9') 23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang const CHAR_T *np; 23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (np = cp; *np >= '0' && *np <= '9'; np++) 23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang ; 23705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*np == '$') 23805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t n = 0; 24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (np = cp; *np >= '0' && *np <= '9'; np++) 24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang n = xsum (xtimes (n, 10), *np - '0'); 24305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (n == 0) 24405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Positional argument 0. */ 24505436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 24605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (size_overflow_p (n)) 24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* n too large, would lead to out of memory later. */ 24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_arg_index = n - 1; 25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = np + 1; 25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dp->width_arg_index == ARG_NONE) 25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_arg_index = arg_posn++; 25605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dp->width_arg_index == ARG_NONE) 25705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* arg_posn wrapped around. */ 25805436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 25905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang REGISTER_ARG (dp->width_arg_index, TYPE_INT); 26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp >= '0' && *cp <= '9') 26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t width_length; 26505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 26605436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_start = cp; 26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (; *cp >= '0' && *cp <= '9'; cp++) 26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang ; 26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->width_end = cp; 27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang width_length = dp->width_end - dp->width_start; 27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (max_width_length < width_length) 27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang max_width_length = width_length; 27305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 27405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Parse the precision. */ 27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp == '.') 27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp == '*') 28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_start = cp - 1; 28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_end = cp; 28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (max_precision_length < 2) 28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang max_precision_length = 2; 28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 28705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Test for positional argument. */ 28805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp >= '0' && *cp <= '9') 28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang const CHAR_T *np; 29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (np = cp; *np >= '0' && *np <= '9'; np++) 29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang ; 29405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*np == '$') 29505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t n = 0; 29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (np = cp; *np >= '0' && *np <= '9'; np++) 29905436638acc7c010349a69c3395f1a57c642dc62Ying Wang n = xsum (xtimes (n, 10), *np - '0'); 30005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (n == 0) 30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Positional argument 0. */ 30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (size_overflow_p (n)) 30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* n too large, would lead to out of memory 30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang later. */ 30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_arg_index = n - 1; 30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp = np + 1; 30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 31005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dp->precision_arg_index == ARG_NONE) 31205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 31305436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_arg_index = arg_posn++; 31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dp->precision_arg_index == ARG_NONE) 31505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* arg_posn wrapped around. */ 31605436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang REGISTER_ARG (dp->precision_arg_index, TYPE_INT); 31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 32105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 32205436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t precision_length; 32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_start = cp - 1; 32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (; *cp >= '0' && *cp <= '9'; cp++) 32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang ; 32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->precision_end = cp; 32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang precision_length = dp->precision_end - dp->precision_start; 32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (max_precision_length < precision_length) 33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang max_precision_length = precision_length; 33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 33305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 33405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang arg_type type; 33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Parse argument type/size specifiers. */ 33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang int flags = 0; 34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (;;) 34205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 34305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*cp == 'h') 34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags |= (1 << (flags & 1)); 34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 'L') 34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags |= 4; 35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 'l') 35405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 8; 35605436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 35705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 35805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 'j') 35905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 36005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sizeof (intmax_t) > sizeof (long)) 36105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 36205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* intmax_t = long long */ 36305436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 16; 36405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 36505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (sizeof (intmax_t) > sizeof (int)) 36605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 36705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* intmax_t = long */ 36805436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 8; 36905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 37005436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 37105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 37205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 'z' || *cp == 'Z') 37305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 37405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* 'z' is standardized in ISO C 99, but glibc uses 'Z' 37505436638acc7c010349a69c3395f1a57c642dc62Ying Wang because the warning facility in gcc-2.95.2 understands 37605436638acc7c010349a69c3395f1a57c642dc62Ying Wang only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ 37705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sizeof (size_t) > sizeof (long)) 37805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 37905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* size_t = long long */ 38005436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 16; 38105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 38205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (sizeof (size_t) > sizeof (int)) 38305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 38405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* size_t = long */ 38505436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 8; 38605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 38705436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 38805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 38905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 't') 39005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 39105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sizeof (ptrdiff_t) > sizeof (long)) 39205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 39305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* ptrdiff_t = long long */ 39405436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 16; 39505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 39605436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (sizeof (ptrdiff_t) > sizeof (int)) 39705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 39805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* ptrdiff_t = long */ 39905436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 8; 40005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 40105436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 40205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 40305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if defined __APPLE__ && defined __MACH__ 40405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* On Mac OS X 10.3, PRIdMAX is defined as "qd". 40505436638acc7c010349a69c3395f1a57c642dc62Ying Wang We cannot change it to "lld" because PRIdMAX must also 40605436638acc7c010349a69c3395f1a57c642dc62Ying Wang be understood by the system's printf routines. */ 40705436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 'q') 40805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 40905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (64 / 8 > sizeof (long)) 41005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 41105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* int64_t = long long */ 41205436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 16; 41305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 41405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 41505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 41605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* int64_t = long */ 41705436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 8; 41805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 41905436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp++; 42005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 42105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 42205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 42305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* On native Windows, PRIdMAX is defined as "I64d". 42405436638acc7c010349a69c3395f1a57c642dc62Ying Wang We cannot change it to "lld" because PRIdMAX must also 42505436638acc7c010349a69c3395f1a57c642dc62Ying Wang be understood by the system's printf routines. */ 42605436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') 42705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 42805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (64 / 8 > sizeof (long)) 42905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 43005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* __int64 = long long */ 43105436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 16; 43205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 43305436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 43405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 43505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* __int64 = long */ 43605436638acc7c010349a69c3395f1a57c642dc62Ying Wang flags += 8; 43705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 43805436638acc7c010349a69c3395f1a57c642dc62Ying Wang cp += 3; 43905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 44005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 44105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 44205436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 44305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 44405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 44505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Read the conversion character. */ 44605436638acc7c010349a69c3395f1a57c642dc62Ying Wang c = *cp++; 44705436638acc7c010349a69c3395f1a57c642dc62Ying Wang switch (c) 44805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 44905436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'd': case 'i': 45005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT 45105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If 'long long' exists and is larger than 'long': */ 45205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 16 || (flags & 4)) 45305436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_LONGLONGINT; 45405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 45505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 45605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If 'long long' exists and is the same as 'long', we parse 45705436638acc7c010349a69c3395f1a57c642dc62Ying Wang "lld" into TYPE_LONGINT. */ 45805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 8) 45905436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_LONGINT; 46005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (flags & 2) 46105436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_SCHAR; 46205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (flags & 1) 46305436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_SHORT; 46405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 46505436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_INT; 46605436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 46705436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'o': case 'u': case 'x': case 'X': 46805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT 46905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If 'long long' exists and is larger than 'long': */ 47005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 16 || (flags & 4)) 47105436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_ULONGLONGINT; 47205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 47305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 47405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If 'unsigned long long' exists and is the same as 47505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 'unsigned long', we parse "llu" into TYPE_ULONGINT. */ 47605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 8) 47705436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_ULONGINT; 47805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (flags & 2) 47905436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_UCHAR; 48005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (flags & 1) 48105436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_USHORT; 48205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 48305436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_UINT; 48405436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 48505436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': 48605436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'a': case 'A': 48705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 16 || (flags & 4)) 48805436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_LONGDOUBLE; 48905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 49005436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_DOUBLE; 49105436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 49205436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'c': 49305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 8) 49405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WINT_T 49505436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_WIDE_CHAR; 49605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 49705436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 49805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 49905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 50005436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_CHAR; 50105436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 50205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WINT_T 50305436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'C': 50405436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_WIDE_CHAR; 50505436638acc7c010349a69c3395f1a57c642dc62Ying Wang c = 'c'; 50605436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 50705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 50805436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 's': 50905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 8) 51005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WCHAR_T 51105436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_WIDE_STRING; 51205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 51305436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 51405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 51505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 51605436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_STRING; 51705436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 51805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_WCHAR_T 51905436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'S': 52005436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_WIDE_STRING; 52105436638acc7c010349a69c3395f1a57c642dc62Ying Wang c = 's'; 52205436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 52305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 52405436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'p': 52505436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_POINTER; 52605436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 52705436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'n': 52805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_LONG_LONG_INT 52905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If 'long long' exists and is larger than 'long': */ 53005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 16 || (flags & 4)) 53105436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_COUNT_LONGLONGINT_POINTER; 53205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 53305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 53405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* If 'long long' exists and is the same as 'long', we parse 53505436638acc7c010349a69c3395f1a57c642dc62Ying Wang "lln" into TYPE_COUNT_LONGINT_POINTER. */ 53605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 8) 53705436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_COUNT_LONGINT_POINTER; 53805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (flags & 2) 53905436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_COUNT_SCHAR_POINTER; 54005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (flags & 1) 54105436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_COUNT_SHORT_POINTER; 54205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 54305436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_COUNT_INT_POINTER; 54405436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 54505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if ENABLE_UNISTDIO 54605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The unistdio extensions. */ 54705436638acc7c010349a69c3395f1a57c642dc62Ying Wang case 'U': 54805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (flags >= 16) 54905436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_U32_STRING; 55005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (flags >= 8) 55105436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_U16_STRING; 55205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 55305436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_U8_STRING; 55405436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 55505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 55605436638acc7c010349a69c3395f1a57c642dc62Ying Wang case '%': 55705436638acc7c010349a69c3395f1a57c642dc62Ying Wang type = TYPE_NONE; 55805436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 55905436638acc7c010349a69c3395f1a57c642dc62Ying Wang default: 56005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Unknown conversion character. */ 56105436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 56205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 56305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 56405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 56505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (type != TYPE_NONE) 56605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 56705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->arg_index = arg_index; 56805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dp->arg_index == ARG_NONE) 56905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 57005436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->arg_index = arg_posn++; 57105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (dp->arg_index == ARG_NONE) 57205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* arg_posn wrapped around. */ 57305436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 57405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 57505436638acc7c010349a69c3395f1a57c642dc62Ying Wang REGISTER_ARG (dp->arg_index, type); 57605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 57705436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->conversion = c; 57805436638acc7c010349a69c3395f1a57c642dc62Ying Wang dp->dir_end = cp; 57905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 58005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 58105436638acc7c010349a69c3395f1a57c642dc62Ying Wang d->count++; 58205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (d->count >= d_allocated) 58305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 58405436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t memory_size; 58505436638acc7c010349a69c3395f1a57c642dc62Ying Wang DIRECTIVE *memory; 58605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 58705436638acc7c010349a69c3395f1a57c642dc62Ying Wang d_allocated = xtimes (d_allocated, 2); 58805436638acc7c010349a69c3395f1a57c642dc62Ying Wang memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); 58905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (size_overflow_p (memory_size)) 59005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Overflow, would lead to out of memory. */ 59105436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto out_of_memory; 59205436638acc7c010349a69c3395f1a57c642dc62Ying Wang memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir 59305436638acc7c010349a69c3395f1a57c642dc62Ying Wang ? realloc (d->dir, memory_size) 59405436638acc7c010349a69c3395f1a57c642dc62Ying Wang : malloc (memory_size)); 59505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (memory == NULL) 59605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Out of memory. */ 59705436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto out_of_memory; 59805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (d->dir == d->direct_alloc_dir) 59905436638acc7c010349a69c3395f1a57c642dc62Ying Wang memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE)); 60005436638acc7c010349a69c3395f1a57c642dc62Ying Wang d->dir = memory; 60105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 60205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 60305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if CHAR_T_ONLY_ASCII 60405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (!c_isascii (c)) 60505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 60605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Non-ASCII character. Not supported. */ 60705436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto error; 60805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 60905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 61005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 61105436638acc7c010349a69c3395f1a57c642dc62Ying Wang d->dir[d->count].dir_start = cp; 61205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 61305436638acc7c010349a69c3395f1a57c642dc62Ying Wang d->max_width_length = max_width_length; 61405436638acc7c010349a69c3395f1a57c642dc62Ying Wang d->max_precision_length = max_precision_length; 61505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 61605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 61705436638acc7c010349a69c3395f1a57c642dc62Ying Wangerror: 61805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (a->arg != a->direct_alloc_arg) 61905436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (a->arg); 62005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (d->dir != d->direct_alloc_dir) 62105436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (d->dir); 62205436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EINVAL; 62305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 62405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 62505436638acc7c010349a69c3395f1a57c642dc62Ying Wangout_of_memory: 62605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (a->arg != a->direct_alloc_arg) 62705436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (a->arg); 62805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (d->dir != d->direct_alloc_dir) 62905436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (d->dir); 63005436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = ENOMEM; 63105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 63205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 63305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 63405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef PRINTF_PARSE 63505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DIRECTIVES 63605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef DIRECTIVE 63705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef CHAR_T_ONLY_ASCII 63805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef CHAR_T 639