/* -*- 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, see <http://www.gnu.org/licenses>.
*
* 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
#line 266 "printf.in"
/**
* printf_generic_info:
* @pinfo: the current state information for the format
* string parser.
* @n: the number of available slots in the @argtypes array
* @argtypes: the pointer to the first slot to be filled by the
* function
*
* An example implementation of a %printf_arginfo_function, which
* takes the basic type from the type given in the %spec_entry
* and adds flags depending on what was parsed (e.g. %PA_FLAG_SHORT
* is %pparser->is_short and so on).
*
* Return value:
* Always 1.
*/
extern int
printf_generic_info (struct printf_info *const pinfo, size_t n, int *argtypes);
/**
* printf_generic:
* @stream: the stream (possibly a struct printfv_stream appropriately
* cast) on which to write output.
* @pinfo: the current state information for the format string parser.
* @args: the pointer to the first argument to be read by the handler
*
* An example implementation of a %printf_function, used to provide easy
* access to justification, width and precision options.
*
* Return value:
* The number of characters output.
**/
extern int
printf_generic (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args);
#line 267 "printf.in"
/**
* register_printf_function: printf.h
* @spec: the character which will trigger @func, 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.
*
* Return value:
* Returns %NULL if @func was not successfully registered, a
* %spec_entry with the information on the function if it was.
**/
extern spec_entry *
register_printf_function (unsigned spec, printf_function *fmt,
printf_arginfo_function *arg);
/**
* printf_strerror: printf.h
*
* Communicate information on the last error in a printf
* format string.
*
* Return value:
* A string describing the last error which occurred during the
* parsing of a printf format string. It is the responsibility
* of the caller to free the string.
*/
extern char *
printf_strerror (void);
/**
* printf_error: printf.h
* @pinfo: pointer to the current parser state.
* @file: file where error was detected.
* @line: line where error was detected.
* @func1: " (" if function is supplied by compiler.
* @func2: function where error was detected, if supplied by compiler.
* @func3: ")" if function is supplied by compiler.
* @error_message: new error message to append to @pinfo.
*
* The contents of @error_message are appended to the @pinfo internal
* error string, so it is safe to pass static strings or recycle the
* original when this function returns.
*
* Return value:
* The address of the full accumulated error message in @pinfo is
* returned.
**/
extern char *
printf_error (struct printf_info *pinfo, const char *file, int line,
const char *func1, const char *func2, const char *func3,
const char *error_message);
/**
* parse_printf_format: printf.h
* @format: a % delimited format string.
* @n: the size of the @argtypes vector
* @argtypes: a vector of ints, to be filled with the argument types from @format
*
* Returns information about the number and types of
* arguments expected by the template string @format.
* The argument @n specifies the number of elements in the array
* @argtypes. This is the maximum number of elements that
* the function will try to write.
*
* Return value:
* The total number of arguments required by @format. If this
* number is greater than @n, then the information returned
* describes only the first @n arguments. If you want information
* about additional arguments, allocate a bigger array and call
* this function again. If there is an error, then %SNV_ERROR
* is returned instead.
**/
extern size_t
parse_printf_format (const char *format, int n, int *argtypes);
/**
* stream_printfv: printf.h
* @stream: an initialised stream structure.
* @format: a % delimited format string.
* @args: a vector of argument addresses to match @format.
*
* Format the elements of @args according to @format, and write
* the results to @stream. If @stream is %NULL, only count the
* number of characters needed to output the format.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
stream_printfv (STREAM *stream, const char *format, snv_constpointer const *ap);
/**
* stream_vprintf: printf.h
* @stream: an initialised stream structure.
* @format: a % delimited format string.
* @ap: a varargs/stdargs va_list.
*
* Format the elements of @ap according to @format, and write
* the results to @stream. If @stream is %NULL, only count the
* number of characters needed to output the format.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
stream_vprintf (STREAM *stream, const char *format, va_list ap);
/**
* stream_printf: printf.h
* @stream: an initialised stream structure.
* @format: a % delimited format string.
* @va_alist: a varargs/stdargs va_list.
*
* Format the elements of @va_alist according to @format, and write
* the results to @stream. If @stream is %NULL, only count the
* number of characters needed to output the format.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
stream_printf (STREAM * stream, const char *format, ...);
/**
* snv_fdputc: printf.h
* @ch: A single character to be added to @stream.
* @stream: The stream in which to write @ch.
*
* A StreamPut function for use in putting characters
* into STREAMs holding a file descriptor.
*
* Return value:
* The value of @ch that has been put in @stream, or -1 in case of
* an error (errno will be set to indicate the type of error).
**/
extern int
snv_fdputc (int ch, STREAM *stream);
/**
* snv_dprintf: printf.h
* @fd: an open file descriptor.
* @format: a % delimited format string.
* @va_alist: a varargs/stdargs va_list.
*
* Format the elements of @va_alist according to @format, and write
* the results to the file descriptor @fd.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_dprintf (int fd, const char *format, ...);
/**
* snv_vdprintf: printf.h
* @fd: an open file descriptor.
* @format: a % delimited format string.
* @ap: a varargs/stdargs va_list.
*
* Format the elements of @ap according to @format, and write
* the results to the file descriptor @fd.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_vdprintf (int fd, const char *format, va_list ap);
/**
* snv_dprintfv: printf.h
* @fd: an open file descriptor.
* @format: a % delimited format string.
* @args: a vector of argument addresses to match @format.
*
* Format the elements of @args according to @format, and write
* the results to file descriptor @fd.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_dprintfv (int fd, const char *format, snv_constpointer const args[]);
/**
* snv_fileputc: printf.h
* @ch: A single character to be added to @stream.
* @stream: The stream in which to write @ch.
*
* A StreamPut function for use in putting characters
* into STREAMs holding a FILE*.
*
* Return value:
* The value of @ch that has been put in @stream.
**/
extern int
snv_fileputc (int ch, STREAM *stream);
/**
* snv_printf: printf.h
* @format: a % delimited format string.
* @va_alist: a varargs/stdargs va_list.
*
* Format the elements of @va_alist according to @format, and write
* the results to the standard output stream.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_printf (const char *format, ...);
/**
* snv_vprintf: printf.h
* @format: a % delimited format string.
* @ap: a varargs/stdargs va_list.
*
* Format the elements of @ap according to @format, and write
* the results to the standard output stream.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_vprintf (const char *format, va_list ap);
/**
* snv_printfv: printf.h
* @format: a % delimited format string.
* @args: a vector of argument addresses to match @format.
*
* Format the elements of @args according to the string @format,
* and write the result to the standard output stream.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_printfv (const char *format, snv_constpointer const args[]);
/**
* snv_fprintf: printf.h
* @file: a stdio.h FILE* stream.
* @format: a % delimited format string.
* @va_alist: a varargs/stdargs va_list.
*
* Format the elements of @va_alist according to @format, and write
* the results to the @file stream.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_fprintf (FILE * file, const char *format, ...);
/**
* snv_vfprintf: printf.h
* @file: a stdio.h FILE* stream.
* @format: a % delimited format string.
* @ap: a varargs/stdargs va_list.
*
* Format the elements of @ap according to @format, and write
* the results to the @file stream.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_vfprintf (FILE *file, const char *format, va_list ap);
/**
* snv_fprintfv: printf.h
* @file: a stdio.h FILE* stream.
* @format: a % delimited format string.
* @args: a vector of argument addresses to match @format.
*
* Format the elements of @args according to @format, and write
* the results to @file.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_fprintfv (FILE *file, const char *format, snv_constpointer const args[]);
/**
* snv_bufputc: printf.h
* @ch: A single character to be added to @stream.
* @stream: The stream in which to write @ch.
*
* A StreamPut function for use in putting characters
* into STREAMs holding a char buffer.
*
* Return value:
* The value of @ch that has been put in @stream.
**/
extern int
snv_bufputc (int ch, STREAM * stream);
/**
* snv_sprintf: printf.h
* @buffer: a preallocated char* buffer.
* @format: a % delimited format string.
* @va_alist: a varargs/stdargs va_list.
*
* Format the elements of @va_alist according to @format, and write
* the results to the string @buffer.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_sprintf (char buffer[], const char *format, ...);
/**
* snv_vsprintf: printf.h
* @buffer: a preallocated char* buffer.
* @format: a % delimited format string.
* @ap: a varargs/stdargs va_list.
*
* Format the elements of @ap according to @format, and write
* the results to the string @buffer.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_vsprintf (char buffer[], const char *format, va_list ap);
/**
* snv_sprintfv: printf.h
* @buffer: a preallocated char* buffer.
* @format: a % delimited format string.
* @args: a vector of argument addresses to match @format.
*
* Format the elements of @args according to @format, and write
* the results to the string @buffer.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_sprintfv (char buffer[], const char *format, snv_constpointer const args[]);
/**
* snv_snprintf: printf.h
* @buffer: a preallocated char* buffer.
* @limit: the maximum number of characters to write into @buffer.
* @format: a % delimited format string.
* @va_alist: a varargs/stdargs va_list.
*
* Format the elements of @va_alist according to @format, and write
* the results to the string @buffer, truncating the formatted string
* if it reaches @limit characters in length.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_snprintf (char buffer[], unsigned long limit, const char *format, ...);
/**
* snv_vsnprintf: printf.h
* @buffer: a preallocated char* buffer.
* @limit: the maximum number of characters to write into @buffer.
* @format: a % delimited format string.
* @ap: a varargs/stdargs va_list.
*
* Format the elements of @ap according to @format, and write
* the results to the string @buffer, truncating the formatted string
* if it reaches @limit characters in length.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_vsnprintf (char buffer[], unsigned long limit, const char *format, va_list ap);
/**
* snv_snprintfv: printf.h
* @buffer: a preallocated char* buffer.
* @limit: the maximum number of characters to write into @buffer.
* @format: a % delimited format string.
* @args: a vector of argument addresses to match @format.
*
* Format the elements of @args according to @format, and write
* the results to the string @buffer, truncating the formatted string
* if it reaches @limit characters in length.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_snprintfv (char buffer[], unsigned long limit, const char *format,
snv_constpointer const args[]);
/**
* snv_filputc: printf.h
* @ch: A single character to be added to @stream.
* @stream: The stream in which to write @ch.
*
* A StreamPut function for use in putting characters
* into STREAMs holding a Filament*.
*
* Return value:
* The value of @ch that has been put in @stream.
**/
extern int
snv_filputc (int ch, STREAM * stream);
/**
* snv_asprintf: printf.h
* @result: the address of a char * variable.
* @format: a % delimited format string.
* @va_alist: a varargs/stdargs va_list.
*
* Format the elements of @va_alist according to @format, and write
* the results to an internally allocated buffer whose address is
* stored in @result (and should be freed by the caller) unless
* there is an error.
*
* Yes, this interface is cumbersome and totally useless. It would
* have been better to simply return the allocated address, but
* it turns out that somebody wasn't thinking much when adding
* asprintf to libiberty a few years ago.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_asprintf (char **result, const char *format, ...);
/**
* snv_vasprintf: printf.h
* @result: the address of a char * variable.
* @format: a % delimited format string.
* @ap: a varargs/stdargs va_list.
*
* Format the elements of @ap according to @format, and write
* the results to an internally allocated buffer whose address is
* stored in @result (and should be freed by the caller) unless
* there is an error.
*
* Above moaning for asprintf applies here too.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_vasprintf (char **result, const char *format, va_list ap);
/**
* snv_asprintfv: printf.h
* @result: the address of a char * variable.
* @format: a % delimited format string.
* @args: a vector of argument addresses to match @format.
*
* Format the elements of @args according to @format, and write
* the results to an internally allocated buffer whose address is
* stored in @result (and should be freed by the caller) unless
* there is an error.
*
* Above moaning for asprintf applies here too.
*
* Return value:
* The number of characters written is returned, unless there is
* an error, when %SNV_ERROR is returned.
**/
extern int
snv_asprintfv (char **result, const char *format, snv_constpointer const args[]);
#line 268 "printf.in"
/* 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 */