summaryrefslogtreecommitdiff
path: root/snprintfv/printf.in
blob: 98ba99514fe78a8f1635a8c69b1a77bc8efe9d64 (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*  -*- Mode: C -*-  */

/* printf.in --- printf clone for argv arrays
 * Copyright (C) 1998, 1999, 2000, 2002 Gary V. Vaughan
 * Originally by Gary V. Vaughan, 1998
 * This file is part of Snprintfv
 *
 * Snprintfv is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * Snprintfv program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * As a special exception to the GNU General Public License, if you
 * distribute this file as part of a program that also links with and
 * uses the libopts library from AutoGen, you may include it under
 * the same distribution terms used by the libopts library.
 */

/* Code: */

#ifndef SNPRINTFV_SNPRINTFV_H
#define SNPRINTFV_SNPRINTFV_H 1

#include <snprintfv/compat.h>
#include <snprintfv/filament.h>
#include <snprintfv/stream.h>
#include <snprintfv/mem.h>

#ifdef __cplusplus
extern "C"
{
#endif

/* The type of each element in the table of printf specifiers. */
struct spec_entry;

typedef enum
{
  SNV_ERROR = -1,
  SNV_OK
}
snv_status;

/* Basic states required by the parser.  On initialisation the parser
   will be in SNV_STATE_BEGIN, and tokens will be parsed by the registered
   functions until the parser reached SNV_STATE_END. */
#define SNV_STATE_BEGIN		1
#define SNV_STATE_END		0

/* States needed to support:
   %[<number>$]<flags>[<width>|\*][.<precision>|\*]<modifiers><specifier> */
#define SNV_STATE_FLAG          (1 << 1)
#define SNV_STATE_WIDTH         (1 << 2)
#define SNV_STATE_PRECISION     (1 << 3)
#define SNV_STATE_MODIFIER      (1 << 4)
#define SNV_STATE_SPECIFIER     (1 << 5)

/* First state available to the user */
#define SNV_STATE_USER_FIRST    (1 << 8)

/* Mask for states available to the user */
#define SNV_STATE_USER_MASK     ~(SNV_STATE_USER_FIRST - 1)

typedef struct printf_info
{
  int count;			/* accumulated count, or SNV_ERROR */
  int state;			/* one of the defines above */
  Filament *error;		/* accumulated error details */

  const char *format;		/* pointer to format string */
  int argc;			/* number of arguments used by format */
  int argindex;			/* number of non-dollar arguments used so far */

  int dollar;			/* standard parser state, as in glibc */
  int prec;			/* from this field on, as in glibc */
  int width;

  snv_pointer extra;
  int type;

  char spec;
  char pad;
  unsigned is_long_double:1;
  unsigned is_char:1;
  unsigned is_short:1;
  unsigned is_long:1;
  unsigned alt:1;
  unsigned space:1;
  unsigned left:1;
  unsigned showsign:1;
  unsigned group:1;
  unsigned wide:1;

  const union printf_arg *args;
} printf_info;

/**
 * printf_arg:
 * @pa_char: an unsigned %char
 * @pa_wchar: a %wchar_t
 * @pa_short_int: a %short integer
 * @pa_int: an %int
 * @pa_long_int: a %long integer
 * @pa_long_long_int: the widest signed integer type in use on the host
 * @pa_u_short_int: an unsigned %short integer
 * @pa_u_int: an unsigned %int
 * @pa_u_long_int: an unsigned %long integer
 * @pa_u_long_long_int: the widest unsigned integer type in use on the host
 * @pa_float: a %float
 * @pa_double: a %double
 * @pa_long_double: a long %double, or a simple %double if it is the widest floating-point type in use on the host
 * @pa_string: a %const pointer to %char
 * @pa_wstring: a %const pointer to %wchar_t
 * @pa_pointer: a generic pointer
 *
 * The various kinds of arguments that can be passed to printf.
 */
typedef union printf_arg
{
  unsigned char pa_char;
  snv_wchar_t pa_wchar;
  short int pa_short_int;
  int pa_int;
  long int pa_long_int;
  intmax_t pa_long_long_int;
  unsigned short int pa_u_short_int;
  unsigned int pa_u_int;
  unsigned long int pa_u_long_int;
  uintmax_t pa_u_long_long_int;
  float pa_float;
  double pa_double;
  long double pa_long_double;
  const char *pa_string;
  const snv_wchar_t *pa_wstring;
  snv_constpointer pa_pointer;
} printf_arg;

/**
 * PRINTF_ERROR:
 * @pi: A pointer to the current state for the parser
 * @str: The error message
 *
 * Append an error that will be returned by printf_strerror.
 */
#define PRINTF_ERROR(pi, str)                                         \
        printf_error(pi, __FILE__, __LINE__, SNV_ASSERT_FCN, str);

typedef int printf_function (STREAM *stream, struct printf_info *pparser,
                             union printf_arg const * args);

typedef int printf_arginfo_function (struct printf_info *pparser, size_t n,
                                     int *argtypes);

/**
 * spec_entry:
 * @spec: the specifier character that was matched
 * @type: when @arg is NULL, the type of the only argument to the specifier
 * @fmt: the handler function to actually print the arguments to the specifier
 * @arg: the handler function to tell %printf about the types of the arguments to the specifier
 * @user: the user data for the specifier, accessible to the handler function
 *
 * This is returned by register_printf_function.
 */
typedef struct spec_entry
{
  unsigned int spec_key;
  int unused;  /* for binary compatibility */
  int type;
  printf_function *fmt;
  printf_arginfo_function *arg;
  snv_pointer user;
}
spec_entry;

/**
 * register_callback_function: printf.h
 * @spec: the character which will trigger the functions, cast to an unsigned int.
 * @fmt: the handler function to actually print the arguments to the specifier
 * @arg: the handler function to tell %printf about the types of the arguments to the specifier
 *
 * Register the pair made of @fmt and @arg, so that it is called
 * when @spec is encountered in a format string.  If you create
 * a shared library with an entry point named
 * %snv_register_printf_funcs, and put the library in the
 * search path given by the environment library %LTDL_LIBRARY_PATH,
 * that entry point will be called when %libsnprintfv is initialized,
 * passing a pointer to this kind of function (actually, a pointer
 * to %register_printf_function) to it.  This functionality is only
 * present when the library is installed, not when it is built as
 * a convenience library.
 *
 * Return value:
 * Returns %NULL if @func was not successfully registered, a
 * %spec_entry with the information on the function if it was.
 **/
typedef spec_entry *register_callback_function (unsigned spec, printf_function *func, printf_arginfo_function *arginfo);

/* Codes to determine basic types.

   These values cover all the standard format specifications.
   Users can add new values after PA_LAST for their own types.  */

enum
{
  PA_INT,			/* int */
  PA_CHAR,			/* int, cast to char */
  PA_WCHAR,			/* wide char */
  PA_STRING,			/* const char *, a '\0'-terminated string */
  PA_WSTRING,			/* const wchar_t *, wide character string */
  PA_POINTER,			/* void * */
  PA_FLOAT,			/* float */
  PA_DOUBLE,			/* double */
  PA_LAST,
  PA_UNKNOWN = -1
};

/* Flag bits that can be set in a type. */
#define PA_TYPE_MASK		0x00ff
#define	PA_FLAG_MASK		~SNV_TYPE_MASK

#define	PA_FLAG_LONG_LONG	(1 << 8)
#define	PA_FLAG_LONG_DOUBLE	PA_FLAG_LONG_LONG
#define	PA_FLAG_LONG		(1 << 9)
#define	PA_FLAG_SHORT		(1 << 10)
#define PA_FLAG_UNSIGNED	(1 << 11)
#define	PA_FLAG_CHAR		(1 << 12)
#define	PA_FLAG_PTR		(1 << 13)

/**
 * SNV_EMIT:
 * @ch: the character to be printed
 * @stream: the stream on which to print
 * @count: a variable to be updated with the count of printed
 * characters
 *
 * Maintain the count while putting @ch in @stream, also be careful about
 * handling %NULL stream if the handler is being called purely to count
 * output size.
 **/
#define SNV_EMIT(ch, stream, count) \
  SNV_STMT_START { \
    if ((stream)) \
      { \
	if ((count) >= 0) \
	  { \
	    int m_status = stream_put((unsigned char) (ch), (stream)); \
	    (count) = m_status < 0 ? m_status : (count) + m_status; \
	  } \
      } \
    else \
      { \
        (void)(ch); \
	(count)++; \
      } \
  } SNV_STMT_END

@protos format.c
@protos custom.c
@protos printf.c

/* If you don't want to use snprintfv functions for *all* of your string
   formatting API, then define COMPILING_SNPRINTFV_C and use the snv_
   prefix for the entry points below. */
#ifndef COMPILING_PRINTF_C
#undef printf
#undef vprintf
#undef dprintf
#undef vdprintf
#undef fprintf
#undef vfprintf
#undef sprintf
#undef vsprintf
#undef snprintf
#undef vsnprintf
#undef asprintf
#undef vasprintf
#undef asprintfv
#undef dprintfv
#undef fprintfv
#undef sprintfv
#undef printfv
#undef snprintfv

#define printf          snv_printf
#define vprintf         snv_vprintf
#define dprintf         snv_dprintf
#define vdprintf        snv_vdprintf
#define fprintf         snv_fprintf
#define vfprintf        snv_vfprintf
#define sprintf         snv_sprintf
#define vsprintf        snv_vsprintf
#define snprintf        snv_snprintf
#define vsnprintf       snv_vsnprintf
#define asprintf        snv_asprintf
#define vasprintf       snv_vasprintf
#define asprintfv       snv_asprintfv
#define dprintfv        snv_dprintfv
#define fprintfv        snv_fprintfv
#define sprintfv        snv_sprintfv
#define printfv         snv_printfv
#define snprintfv       snv_snprintfv
#endif				/* !COMPILING_SNPRINTFV_C */
#ifdef __cplusplus
}
#endif

#endif				/* SNPRINTFV_SNPRINTFV_H */

/* snprintfv.h ends here */