|
Packit |
6c4009 |
/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
|
|
Packit |
6c4009 |
This file is part of the GNU C Library.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is free software; you can redistribute it and/or
|
|
Packit |
6c4009 |
modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License as published by the Free Software Foundation; either
|
|
Packit |
6c4009 |
version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
The GNU C Library is distributed in the hope that it will be useful,
|
|
Packit |
6c4009 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6c4009 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6c4009 |
Lesser General Public License for more details.
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6c4009 |
License along with the GNU C Library; if not, see
|
|
Packit |
6c4009 |
<http://www.gnu.org/licenses/>. */
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#include <stdio.h>
|
|
Packit |
6c4009 |
#include <printf.h>
|
|
Packit |
6c4009 |
#include <stdlib.h>
|
|
Packit |
6c4009 |
#include <string.h>
|
|
Packit |
6c4009 |
#include <wchar.h>
|
|
Packit |
6c4009 |
#include <sys/param.h>
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#include "../locale/localeinfo.h"
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#ifndef COMPILE_WPRINTF
|
|
Packit |
6c4009 |
# define CHAR_T char
|
|
Packit |
6c4009 |
# define UCHAR_T unsigned char
|
|
Packit |
6c4009 |
# define INT_T int
|
|
Packit |
6c4009 |
# define L_(Str) Str
|
|
Packit |
6c4009 |
# define ISDIGIT(Ch) isdigit (Ch)
|
|
Packit |
6c4009 |
# define ISASCII(Ch) isascii (Ch)
|
|
Packit |
6c4009 |
# define MBRLEN(Cp, L, St) __mbrlen (Cp, L, St)
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
# define PUT(F, S, N) _IO_sputn (F, S, N)
|
|
Packit |
6c4009 |
# define PAD(Padchar) \
|
|
Packit |
6c4009 |
if (width > 0) \
|
|
Packit |
6c4009 |
done += _IO_padn (s, Padchar, width)
|
|
Packit |
6c4009 |
#else
|
|
Packit |
6c4009 |
# define vfprintf vfwprintf
|
|
Packit |
6c4009 |
# define CHAR_T wchar_t
|
|
Packit |
6c4009 |
# define UCHAR_T uwchar_t
|
|
Packit |
6c4009 |
# define INT_T wint_t
|
|
Packit |
6c4009 |
# define L_(Str) L##Str
|
|
Packit |
6c4009 |
# define ISDIGIT(Ch) iswdigit (Ch)
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
# define PUT(F, S, N) _IO_sputn (F, S, N)
|
|
Packit |
6c4009 |
# define PAD(Padchar) \
|
|
Packit |
6c4009 |
if (width > 0) \
|
|
Packit |
6c4009 |
done += _IO_wpadn (s, Padchar, width)
|
|
Packit |
6c4009 |
#endif
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
#define DONT_NEED_READ_INT
|
|
Packit |
6c4009 |
#include "printf-parse.h"
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
size_t
|
|
Packit |
6c4009 |
parse_printf_format (const char *fmt, size_t n, int *argtypes)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
size_t nargs; /* Number of arguments. */
|
|
Packit |
6c4009 |
size_t max_ref_arg; /* Highest index used in a positional arg. */
|
|
Packit |
6c4009 |
struct printf_spec spec;
|
|
Packit |
6c4009 |
const unsigned char *f = (const unsigned char *) fmt;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
nargs = 0;
|
|
Packit |
6c4009 |
max_ref_arg = 0;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* Search for format specifications. */
|
|
Packit |
6c4009 |
for (f = __find_specmb (f); *f != '\0'; f = spec.next_fmt)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
/* Parse this spec. */
|
|
Packit |
6c4009 |
nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg);
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* If the width is determined by an argument this is an int. */
|
|
Packit |
6c4009 |
if (spec.width_arg != -1 && (size_t) spec.width_arg < n)
|
|
Packit |
6c4009 |
argtypes[spec.width_arg] = PA_INT;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
/* If the precision is determined by an argument this is an int. */
|
|
Packit |
6c4009 |
if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n)
|
|
Packit |
6c4009 |
argtypes[spec.prec_arg] = PA_INT;
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
if ((size_t) spec.data_arg < n)
|
|
Packit |
6c4009 |
switch (spec.ndata_args)
|
|
Packit |
6c4009 |
{
|
|
Packit |
6c4009 |
case 0: /* No arguments. */
|
|
Packit |
6c4009 |
break;
|
|
Packit |
6c4009 |
case 1: /* One argument; we already have the type. */
|
|
Packit |
6c4009 |
argtypes[spec.data_arg] = spec.data_arg_type;
|
|
Packit |
6c4009 |
break;
|
|
Packit |
6c4009 |
default:
|
|
Packit |
6c4009 |
/* We have more than one argument for this format spec. We must
|
|
Packit |
6c4009 |
call the arginfo function again to determine all the types. */
|
|
Packit |
6c4009 |
(void) (*__printf_arginfo_table[spec.info.spec])
|
|
Packit |
6c4009 |
(&spec.info, n - spec.data_arg, &argtypes[spec.data_arg],
|
|
Packit |
6c4009 |
&spec.size);
|
|
Packit |
6c4009 |
break;
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
}
|
|
Packit |
6c4009 |
|
|
Packit |
6c4009 |
return MAX (nargs, max_ref_arg);
|
|
Packit |
6c4009 |
}
|