Update.
[platform/upstream/glibc.git] / stdio-common / printf-prs.c
1 /* Copyright (C) 1991,92,95,96,99,2000,2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library 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    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <stdio.h>
20 #include <printf.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <wchar.h>
24 #include <sys/param.h>
25
26 #ifndef COMPILE_WPRINTF
27 # define CHAR_T         char
28 # define UCHAR_T        unsigned char
29 # define INT_T          int
30 # define L_(Str)        Str
31 # define ISDIGIT(Ch)    isdigit (Ch)
32 # define ISASCII(Ch)    isascii (Ch)
33 # define MBRLEN(Cp, L, St) __mbrlen (Cp, L, St)
34
35 # ifdef USE_IN_LIBIO
36 #  define PUT(F, S, N)  _IO_sputn (F, S, N)
37 #  define PAD(Padchar)                                                        \
38   if (width > 0)                                                              \
39     done += INTUSE(_IO_padn) (s, Padchar, width)
40 # else
41 #  define PUTC(C, F)    putc (C, F)
42 ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
43 # define PAD(Padchar)                                                         \
44   if (width > 0)                                                              \
45     { if (__printf_pad (s, Padchar, width) == -1)                             \
46         return -1; else done += width; }
47 # endif
48 #else
49 # define vfprintf       vfwprintf
50 # define CHAR_T         wchar_t
51 # define UCHAR_T        uwchar_t
52 # define INT_T          wint_t
53 # define L_(Str)        L##Str
54 # define ISDIGIT(Ch)    iswdigit (Ch)
55
56 # ifdef USE_IN_LIBIO
57 # define PUT(F, S, N)   _IO_sputn (F, S, N)
58 # define PAD(Padchar)                                                         \
59   if (width > 0)                                                              \
60     done += _IO_wpadn (s, Padchar, width)
61 # else
62 #  define PUTC(C, F)    wputc (C, F)
63 ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
64 # define PAD(Padchar)                                                         \
65   if (width > 0)                                                              \
66     { if (__wprintf_pad (s, Padchar, width) == -1)                            \
67         return -1; else done += width; }
68 # endif
69 #endif
70
71 #include "printf-parse.h"
72
73
74 size_t
75 parse_printf_format (fmt, n, argtypes)
76       const char *fmt;
77       size_t n;
78       int *argtypes;
79 {
80   size_t nargs;                 /* Number of arguments.  */
81   size_t max_ref_arg;           /* Highest index used in a positional arg.  */
82   struct printf_spec spec;
83   mbstate_t mbstate;
84
85   nargs = 0;
86   max_ref_arg = 0;
87
88   /* Search for format specifications.  */
89   for (fmt = find_spec (fmt, &mbstate); *fmt != '\0'; fmt = spec.next_fmt)
90     {
91       /* Parse this spec.  */
92       nargs += parse_one_spec (fmt, nargs, &spec, &max_ref_arg, &mbstate);
93
94       /* If the width is determined by an argument this is an int.  */
95       if (spec.width_arg != -1 && (size_t) spec.width_arg < n)
96         argtypes[spec.width_arg] = PA_INT;
97
98       /* If the precision is determined by an argument this is an int.  */
99       if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n)
100         argtypes[spec.prec_arg] = PA_INT;
101
102       if ((size_t) spec.data_arg < n)
103         switch (spec.ndata_args)
104           {
105           case 0:               /* No arguments.  */
106             break;
107           case 1:               /* One argument; we already have the type.  */
108             argtypes[spec.data_arg] = spec.data_arg_type;
109             break;
110           default:
111             /* We have more than one argument for this format spec.  We must
112                call the arginfo function again to determine all the types.  */
113             (void) (*__printf_arginfo_table[spec.info.spec])
114               (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg]);
115             break;
116           }
117     }
118
119   return MAX (nargs, max_ref_arg);
120 }