summaryrefslogtreecommitdiff
path: root/stdio-common/printf-parse.h
blob: f6ad71cd3badcd32be5d25bd7d8a09d00ff4553f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* Internal header for parsing printf format strings.
   Copyright (C) 1995-1999, 2000, 2002, 2003, 2007
   Free Software Foundation, Inc.
   This file is part of th GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#include <printf.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <wchar.h>


struct printf_spec
  {
    /* Information parsed from the format spec.  */
    struct printf_info info;

    /* Pointers into the format string for the end of this format
       spec and the next (or to the end of the string if no more).  */
    const UCHAR_T *end_of_fmt, *next_fmt;

    /* Position of arguments for precision and width, or -1 if `info' has
       the constant value.  */
    int prec_arg, width_arg;

    int data_arg;		/* Position of data argument.  */
    int data_arg_type;		/* Type of first argument.  */
    /* Number of arguments consumed by this format specifier.  */
    size_t ndata_args;
  };


/* The various kinds off arguments that can be passed to printf.  */
union printf_arg
  {
    wchar_t pa_wchar;
    int pa_int;
    long int pa_long_int;
    long long int pa_long_long_int;
    unsigned int pa_u_int;
    unsigned long int pa_u_long_int;
    unsigned long long int pa_u_long_long_int;
    double pa_double;
    long double pa_long_double;
    const char *pa_string;
    const wchar_t *pa_wstring;
    void *pa_pointer;
  };


#ifndef DONT_NEED_READ_INT
/* Read a simple integer from a string and update the string pointer.
   It is assumed that the first character is a digit.  */
static unsigned int
read_int (const UCHAR_T * *pstr)
{
  unsigned int retval = **pstr - L_('0');

  while (ISDIGIT (*++(*pstr)))
    {
      retval *= 10;
      retval += **pstr - L_('0');
    }

  return retval;
}
#endif


/* These are defined in reg-printf.c.  */
extern printf_arginfo_function **__printf_arginfo_table attribute_hidden;
extern printf_function **__printf_function_table attribute_hidden;


/* Find the next spec in FORMAT, or the end of the string.  Returns
   a pointer into FORMAT, to a '%' or a '\0'.  */
__extern_always_inline const unsigned char *
__find_specmb (const unsigned char *format)
{
  return (const unsigned char *) __strchrnul ((const char *) format, '%');
}

__extern_always_inline const unsigned int *
__find_specwc (const unsigned int *format)
{
  return (const unsigned int *) __wcschrnul ((const wchar_t *) format, L'%');
}


/* FORMAT must point to a '%' at the beginning of a spec.  Fills in *SPEC
   with the parsed details.  POSN is the number of arguments already
   consumed.  At most MAXTYPES - POSN types are filled in TYPES.  Return
   the number of args consumed by this spec; *MAX_REF_ARG is updated so it
   remains the highest argument index used.  */
extern size_t __parse_one_specmb (const unsigned char *format, size_t posn,
				  struct printf_spec *spec,
				  size_t *max_ref_arg) attribute_hidden;

extern size_t __parse_one_specwc (const unsigned int *format, size_t posn,
				  struct printf_spec *spec,
				  size_t *max_ref_arg) attribute_hidden;