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 #include "../locale/localeinfo.h"
27
28 #ifndef COMPILE_WPRINTF
29 # define CHAR_T         char
30 # define UCHAR_T        unsigned char
31 # define INT_T          int
32 # define L_(Str)        Str
33 # define ISDIGIT(Ch)    isdigit (Ch)
34 # define ISASCII(Ch)    isascii (Ch)
35 # define MBRLEN(Cp, L, St) __mbrlen (Cp, L, St)
36
37 # ifdef USE_IN_LIBIO
38 #  define PUT(F, S, N)  _IO_sputn (F, S, N)
39 #  define PAD(Padchar)                                                        \
40   if (width > 0)                                                              \
41     done += INTUSE(_IO_padn) (s, Padchar, width)
42 # else
43 #  define PUTC(C, F)    putc (C, F)
44 ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
45 # define PAD(Padchar)                                                         \
46   if (width > 0)                                                              \
47     { if (__printf_pad (s, Padchar, width) == -1)                             \
48         return -1; else done += width; }
49 # endif
50 #else
51 # define vfprintf       vfwprintf
52 # define CHAR_T         wchar_t
53 # define UCHAR_T        uwchar_t
54 # define INT_T          wint_t
55 # define L_(Str)        L##Str
56 # define ISDIGIT(Ch)    iswdigit (Ch)
57
58 # ifdef USE_IN_LIBIO
59 # define PUT(F, S, N)   _IO_sputn (F, S, N)
60 # define PAD(Padchar)                                                         \
61   if (width > 0)                                                              \
62     done += _IO_wpadn (s, Padchar, width)
63 # else
64 #  define PUTC(C, F)    wputc (C, F)
65 ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
66 # define PAD(Padchar)                                                         \
67   if (width > 0)                                                              \
68     { if (__wprintf_pad (s, Padchar, width) == -1)                            \
69         return -1; else done += width; }
70 # endif
71 #endif
72
73 #include "printf-parse.h"
74
75
76 size_t
77 parse_printf_format (fmt, n, argtypes)
78       const char *fmt;
79       size_t n;
80       int *argtypes;
81 {
82   size_t nargs;                 /* Number of arguments.  */
83   size_t max_ref_arg;           /* Highest index used in a positional arg.  */
84   struct printf_spec spec;
85   mbstate_t mbstate;
86
87   nargs = 0;
88   max_ref_arg = 0;
89
90   /* Search for format specifications.  */
91   for (fmt = find_spec (fmt, &mbstate); *fmt != '\0'; fmt = spec.next_fmt)
92     {
93       /* Parse this spec.  */
94       nargs += parse_one_spec (fmt, nargs, &spec, &max_ref_arg, &mbstate);
95
96       /* If the width is determined by an argument this is an int.  */
97       if (spec.width_arg != -1 && (size_t) spec.width_arg < n)
98         argtypes[spec.width_arg] = PA_INT;
99
100       /* If the precision is determined by an argument this is an int.  */
101       if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n)
102         argtypes[spec.prec_arg] = PA_INT;
103
104       if ((size_t) spec.data_arg < n)
105         switch (spec.ndata_args)
106           {
107           case 0:               /* No arguments.  */
108             break;
109           case 1:               /* One argument; we already have the type.  */
110             argtypes[spec.data_arg] = spec.data_arg_type;
111             break;
112           default:
113             /* We have more than one argument for this format spec.  We must
114                call the arginfo function again to determine all the types.  */
115             (void) (*__printf_arginfo_table[spec.info.spec])
116               (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg]);
117             break;
118           }
119     }
120
121   return MAX (nargs, max_ref_arg);
122 }