1/*  -*- Mode: C -*-  */
2
3/* printf.in --- printf clone for argv arrays
4 * Copyright (C) 1998, 1999, 2000, 2002 Gary V. Vaughan
5 * Originally by Gary V. Vaughan, 1998
6 * This file is part of Snprintfv
7 *
8 * Snprintfv is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * Snprintfv program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program.  If not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 *
22 * As a special exception to the GNU General Public License, if you
23 * distribute this file as part of a program that also links with and
24 * uses the libopts library from AutoGen, you may include it under
25 * the same distribution terms used by the libopts library.
26 */
27
28/* Code: */
29
30#ifndef SNPRINTFV_SNPRINTFV_H
31#define SNPRINTFV_SNPRINTFV_H 1
32
33#include <snprintfv/compat.h>
34#include <snprintfv/filament.h>
35#include <snprintfv/stream.h>
36#include <snprintfv/mem.h>
37
38#ifdef HAVE_WCHAR_H
39#  include <wchar.h>
40#endif
41
42#ifdef __cplusplus
43extern "C"
44{
45#endif
46
47/* The type of each element in the table of printf specifiers. */
48struct spec_entry;
49
50typedef enum
51{
52  SNV_ERROR = -1,
53  SNV_OK
54}
55snv_status;
56
57/* Basic states required by the parser.  On initialisation the parser
58   will be in SNV_STATE_BEGIN, and tokens will be parsed by the registered
59   functions until the parser reached SNV_STATE_END. */
60#define SNV_STATE_BEGIN		1
61#define SNV_STATE_END		0
62
63/* States needed to support:
64   %[<number>$]<flags>[<width>|\*][.<precision>|\*]<modifiers><specifier> */
65#define SNV_STATE_FLAG          (1 << 1)
66#define SNV_STATE_WIDTH         (1 << 2)
67#define SNV_STATE_PRECISION     (1 << 3)
68#define SNV_STATE_MODIFIER      (1 << 4)
69#define SNV_STATE_SPECIFIER     (1 << 5)
70
71/* First state available to the user */
72#define SNV_STATE_USER_FIRST    (1 << 8)
73
74/* Mask for states available to the user */
75#define SNV_STATE_USER_MASK     ~(SNV_STATE_USER_FIRST - 1)
76
77typedef struct printf_info
78{
79  int count;			/* accumulated count, or SNV_ERROR */
80  int state;			/* one of the defines above */
81  Filament *error;		/* accumulated error details */
82
83  const char *format;		/* pointer to format string */
84  int argc;			/* number of arguments used by format */
85  int argindex;			/* number of non-dollar arguments used so far */
86
87  int dollar;			/* standard parser state, as in glibc */
88  int prec;			/* from this field on, as in glibc */
89  int width;
90
91  snv_pointer extra;
92  int type;
93
94  char spec;
95  char pad;
96  unsigned is_long_double:1;
97  unsigned is_char:1;
98  unsigned is_short:1;
99  unsigned is_long:1;
100  unsigned alt:1;
101  unsigned space:1;
102  unsigned left:1;
103  unsigned showsign:1;
104  unsigned group:1;
105  unsigned wide:1;
106
107  const union printf_arg *args;
108} printf_info;
109
110/**
111 * printf_arg:
112 * @pa_char: an unsigned %char
113 * @pa_wchar: a %wchar_t
114 * @pa_short_int: a %short integer
115 * @pa_int: an %int
116 * @pa_long_int: a %long integer
117 * @pa_long_long_int: the widest signed integer type in use on the host
118 * @pa_u_short_int: an unsigned %short integer
119 * @pa_u_int: an unsigned %int
120 * @pa_u_long_int: an unsigned %long integer
121 * @pa_u_long_long_int: the widest unsigned integer type in use on the host
122 * @pa_float: a %float
123 * @pa_double: a %double
124 * @pa_long_double: a long %double, or a simple %double if it is the widest floating-point type in use on the host
125 * @pa_string: a %const pointer to %char
126 * @pa_wstring: a %const pointer to %wchar_t
127 * @pa_pointer: a generic pointer
128 *
129 * The various kinds of arguments that can be passed to printf.
130 */
131typedef union printf_arg
132{
133  unsigned char pa_char;
134  snv_wchar_t pa_wchar;
135  short int pa_short_int;
136  int pa_int;
137  long int pa_long_int;
138  intmax_t pa_long_long_int;
139  unsigned short int pa_u_short_int;
140  unsigned int pa_u_int;
141  unsigned long int pa_u_long_int;
142  uintmax_t pa_u_long_long_int;
143  float pa_float;
144  double pa_double;
145  long double pa_long_double;
146  const char *pa_string;
147  const snv_wchar_t *pa_wstring;
148  snv_constpointer pa_pointer;
149} printf_arg;
150
151/**
152 * PRINTF_ERROR:
153 * @pi: A pointer to the current state for the parser
154 * @str: The error message
155 *
156 * Append an error that will be returned by printf_strerror.
157 */
158#define PRINTF_ERROR(pi, str)                                         \
159        printf_error(pi, __FILE__, __LINE__, SNV_ASSERT_FMT, str);
160
161typedef int printf_function (STREAM *stream, struct printf_info *pparser, union printf_arg const * args);
162
163typedef int printf_arginfo_function (struct printf_info *pparser, size_t n, int *argtypes);
164
165/**
166 * spec_entry:
167 * @spec: the specifier character that was matched
168 * @type: when @arg is NULL, the type of the only argument to the specifier
169 * @fmt: the handler function to actually print the arguments to the specifier
170 * @arg: the handler function to tell %printf about the types of the arguments to the specifier
171 * @user: the user data for the specifier, accessible to the handler function
172 *
173 * This is returned by register_printf_function.
174 */
175typedef struct spec_entry
176{
177  int spec;
178  int unused;  /* for binary compatibility */
179  int type;
180  printf_function *fmt;
181  printf_arginfo_function *arg;
182  snv_pointer user;
183}
184spec_entry;
185
186/**
187 * register_callback_function: printf.h
188 * @spec: the character which will trigger the functions, cast to an unsigned int.
189 * @fmt: the handler function to actually print the arguments to the specifier
190 * @arg: the handler function to tell %printf about the types of the arguments to the specifier
191 *
192 * Register the pair made of @fmt and @arg, so that it is called
193 * when @spec is encountered in a format string.  If you create
194 * a shared library with an entry point named
195 * %snv_register_printf_funcs, and put the library in the
196 * search path given by the environment library %LTDL_LIBRARY_PATH,
197 * that entry point will be called when %libsnprintfv is initialized,
198 * passing a pointer to this kind of function (actually, a pointer
199 * to %register_printf_function) to it.  This functionality is only
200 * present when the library is installed, not when it is built as
201 * a convenience library.
202 *
203 * Return value:
204 * Returns %NULL if @func was not successfully registered, a
205 * %spec_entry with the information on the function if it was.
206 **/
207typedef spec_entry *register_callback_function (unsigned spec, printf_function *func, printf_arginfo_function *arginfo);
208
209/* Codes to determine basic types.
210
211   These values cover all the standard format specifications.
212   Users can add new values after PA_LAST for their own types.  */
213
214enum
215{
216  PA_INT,			/* int */
217  PA_CHAR,			/* int, cast to char */
218  PA_WCHAR,			/* wide char */
219  PA_STRING,			/* const char *, a '\0'-terminated string */
220  PA_WSTRING,			/* const snv_wchar_t *, wide character string */
221  PA_POINTER,			/* void * */
222  PA_FLOAT,			/* float */
223  PA_DOUBLE,			/* double */
224  PA_LAST,
225  PA_UNKNOWN = -1
226};
227
228/* Flag bits that can be set in a type. */
229#define PA_TYPE_MASK		0x00ff
230#define	PA_FLAG_MASK		~SNV_TYPE_MASK
231
232#define	PA_FLAG_LONG_LONG	(1 << 8)
233#define	PA_FLAG_LONG_DOUBLE	PA_FLAG_LONG_LONG
234#define	PA_FLAG_LONG		(1 << 9)
235#define	PA_FLAG_SHORT		(1 << 10)
236#define PA_FLAG_UNSIGNED	(1 << 11)
237#define	PA_FLAG_CHAR		(1 << 12)
238#define	PA_FLAG_PTR		(1 << 13)
239
240/**
241 * SNV_EMIT:
242 * @ch: the character to be printed
243 * @stream: the stream on which to print
244 * @count: a variable to be updated with the count of printed
245 * characters
246 *
247 * Maintain the count while putting @ch in @stream, also be careful about
248 * handling %NULL stream if the handler is being called purely to count
249 * output size.
250 **/
251#define SNV_EMIT(ch, stream, count) \
252  SNV_STMT_START { \
253    if (stream) \
254      { \
255	if (count >= 0) \
256	  { \
257	    int m_status = stream_put((ch), stream); \
258	    count = m_status < 0 ? m_status : count + m_status; \
259	  } \
260      } \
261    else \
262      { \
263        (void)(ch); \
264	count++; \
265      } \
266  } SNV_STMT_END
267
268@protos format.c
269@protos custom.c
270@protos printf.c
271
272/* If you don't want to use snprintfv functions for *all* of your string
273   formatting API, then define COMPILING_SNPRINTFV_C and use the snv_
274   prefix for the entry points below. */
275#ifndef COMPILING_PRINTF_C
276#undef printf
277#undef vprintf
278#undef dprintf
279#undef vdprintf
280#undef fprintf
281#undef vfprintf
282#undef sprintf
283#undef vsprintf
284#undef snprintf
285#undef vsnprintf
286#undef asprintf
287#undef vasprintf
288#undef asprintfv
289#undef dprintfv
290#undef fprintfv
291#undef sprintfv
292#undef printfv
293#undef snprintfv
294#define printf          snv_printf
295#define vprintf         snv_vprintf
296#define dprintf         snv_dprintf
297#define vdprintf        snv_vdprintf
298#define fprintf         snv_fprintf
299#define vfprintf        snv_vfprintf
300#define sprintf         snv_sprintf
301#define vsprintf        snv_vsprintf
302#define snprintf        snv_snprintf
303#define vsnprintf       snv_vsnprintf
304#define asprintf        snv_asprintf
305#define vasprintf       snv_vasprintf
306#define asprintfv	snv_asprintfv
307#define dprintfv	snv_dprintfv
308#define fprintfv	snv_fprintfv
309#define sprintfv	snv_sprintfv
310#define printfv		snv_printfv
311#define snprintfv	snv_snprintfv
312#endif				/* !COMPILING_SNPRINTFV_C */
313#ifdef __cplusplus
314}
315#endif
316
317#endif				/* SNPRINTFV_SNPRINTFV_H */
318
319/* snprintfv.h ends here */
320