|
Packit Service |
96b5d3 |
/* -*- Mode: C -*- */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* printf.c --- printf clone for argv arrays
|
|
Packit Service |
96b5d3 |
* Copyright (C) 1998, 1999, 2000, 2002 Gary V. Vaughan
|
|
Packit Service |
96b5d3 |
* Originally by Gary V. Vaughan, 1998
|
|
Packit Service |
96b5d3 |
* This file is part of Snprintfv
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Snprintfv is free software; you can redistribute it and/or
|
|
Packit Service |
96b5d3 |
* modify it under the terms of the GNU General Public License as
|
|
Packit Service |
96b5d3 |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit Service |
96b5d3 |
* License, or (at your option) any later version.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Snprintfv program is distributed in the hope that it will be useful,
|
|
Packit Service |
96b5d3 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
96b5d3 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
96b5d3 |
* General Public License for more details.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
96b5d3 |
* along with this program. If not, see <http://www.gnu.org/licenses>.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* As a special exception to the GNU General Public License, if you
|
|
Packit Service |
96b5d3 |
* distribute this file as part of a program that also links with and
|
|
Packit Service |
96b5d3 |
* uses the libopts library from AutoGen, you may include it under
|
|
Packit Service |
96b5d3 |
* the same distribution terms used by the libopts library.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Code: */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
96b5d3 |
# include <config.h>
|
|
Packit Service |
96b5d3 |
#endif
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#include <unistd.h> /* for the write(2) call */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#ifdef HAVE_ASSERT_H
|
|
Packit Service |
96b5d3 |
# include <assert.h>
|
|
Packit Service |
96b5d3 |
#else
|
|
Packit Service |
96b5d3 |
# define assert(_e)
|
|
Packit Service |
96b5d3 |
#endif
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#define COMPILING_PRINTF_C
|
|
Packit Service |
96b5d3 |
#include "printf.h"
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#ifdef WITH_DMALLOC
|
|
Packit Service |
96b5d3 |
#include <dmalloc.h>
|
|
Packit Service |
96b5d3 |
#endif
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#include "filament.h"
|
|
Packit Service |
96b5d3 |
#include "stream.h"
|
|
Packit Service |
96b5d3 |
#include "mem.h"
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#ifdef SNV_LIBRARY_BUILD
|
|
Packit Service |
96b5d3 |
# include "dl.h"
|
|
Packit Service |
96b5d3 |
#else
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
# ifndef HAVE_STRTOUL
|
|
Packit Service |
96b5d3 |
# include "strtoul.c"
|
|
Packit Service |
96b5d3 |
# endif
|
|
Packit Service |
96b5d3 |
#endif /* SNV_LIBRARY_BUILD */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#define EOS '\0'
|
|
Packit Service |
96b5d3 |
#define SNV_CHAR_SPEC '%'
|
|
Packit Service |
96b5d3 |
#define SNV_ESC_SPEC '\\'
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Functions to manage mapping of spec chars to handlers. */
|
|
Packit Service |
96b5d3 |
SNV_INLINE unsigned spec_hash (unsigned spec);
|
|
Packit Service |
96b5d3 |
SNV_INLINE void spec_init (void);
|
|
Packit Service |
96b5d3 |
SNV_INLINE spec_entry *spec_lookup (unsigned spec);
|
|
Packit Service |
96b5d3 |
static void spec_insert (spec_entry * pentry);
|
|
Packit Service |
96b5d3 |
static int do_printfv (STREAM *stream, const char *format,
|
|
Packit Service |
96b5d3 |
union printf_arg const args[]);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* FIXME: We are assuming an ASCII character set where all the
|
|
Packit Service |
96b5d3 |
printable characters are between SPACE and DEL. */
|
|
Packit Service |
96b5d3 |
#define ASCII_DEL (int)'\177'
|
|
Packit Service |
96b5d3 |
#define ASCII_SPACE (int)' '
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
#define IS_MODIFIER(spec) (!((spec)->fmt))
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* TODO: This is not thread-safe. Change the API to pass the spec_table
|
|
Packit Service |
96b5d3 |
in as the first parameter to the functions which use it? */
|
|
Packit Service |
96b5d3 |
static spec_entry *spec_table[ASCII_DEL - ASCII_SPACE];
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* TODO: This is not thread-safe as well. */
|
|
Packit Service |
96b5d3 |
static char *printf_last_error;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
SNV_INLINE unsigned
|
|
Packit Service |
96b5d3 |
spec_hash (unsigned spec)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
return (spec & ASCII_DEL) - ASCII_SPACE;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Register all of the functions in INIT_SPEC_TABLE. */
|
|
Packit Service |
96b5d3 |
static void
|
|
Packit Service |
96b5d3 |
spec_init (void)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
static bool is_init = false;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!is_init)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
extern spec_entry snv_default_spec_table[];
|
|
Packit Service |
96b5d3 |
unsigned ix;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
memset (spec_table, 0, sizeof (spec_table));
|
|
Packit Service |
96b5d3 |
for (ix = 0; snv_default_spec_table[ix].spec_key != EOS; ix++)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
unsigned hash = spec_hash (snv_default_spec_table[ix].spec_key);
|
|
Packit Service |
96b5d3 |
spec_table[hash] = snv_default_spec_table + ix;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
is_init = true;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Insert PENTRY, a new handler, into SPEC_TABLE. */
|
|
Packit Service |
96b5d3 |
SNV_INLINE void
|
|
Packit Service |
96b5d3 |
spec_insert (spec_entry *pentry)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
unsigned hash = spec_hash (pentry->spec_key);
|
|
Packit Service |
96b5d3 |
spec_init ();
|
|
Packit Service |
96b5d3 |
spec_table[hash] = pentry;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Lookup and return the SPEC_TABLE entry for SPEC. */
|
|
Packit Service |
96b5d3 |
SNV_INLINE spec_entry *
|
|
Packit Service |
96b5d3 |
spec_lookup (unsigned spec)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
unsigned hash = spec_hash (spec);
|
|
Packit Service |
96b5d3 |
spec_init ();
|
|
Packit Service |
96b5d3 |
return spec_table[hash];
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* register_printf_function: printf.h
|
|
Packit Service |
96b5d3 |
* @spec: the character which will trigger @func, cast to an unsigned int.
|
|
Packit Service |
96b5d3 |
* @fmt: the handler function to actually print the arguments to the specifier
|
|
Packit Service |
96b5d3 |
* @arg: the handler function to tell %printf about the types of the arguments
|
|
Packit Service |
96b5d3 |
* to the specifier
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Register the pair made of @fmt and @arg, so that it is called
|
|
Packit Service |
96b5d3 |
* when @spec is encountered in a format string.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* Returns %NULL if @func was not successfully registered, a
|
|
Packit Service |
96b5d3 |
* %spec_entry with the information on the function if it was.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
spec_entry *
|
|
Packit Service |
96b5d3 |
register_printf_function (unsigned spec, printf_function *fmt,
|
|
Packit Service |
96b5d3 |
printf_arginfo_function *arg)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
spec_entry *new, *old;
|
|
Packit Service |
96b5d3 |
old = spec_lookup (spec);
|
|
Packit Service |
96b5d3 |
if (old && IS_MODIFIER (old))
|
|
Packit Service |
96b5d3 |
return NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!fmt || !spec)
|
|
Packit Service |
96b5d3 |
return NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
new = snv_new (spec_entry, 1);
|
|
Packit Service |
96b5d3 |
new->spec_key = spec;
|
|
Packit Service |
96b5d3 |
new->fmt = fmt;
|
|
Packit Service |
96b5d3 |
new->arg = arg;
|
|
Packit Service |
96b5d3 |
new->user = NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
spec_insert (new);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return new;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
static int
|
|
Packit Service |
96b5d3 |
call_argtype_function (
|
|
Packit Service |
96b5d3 |
struct printf_info *const pinfo,
|
|
Packit Service |
96b5d3 |
int **argtypes,
|
|
Packit Service |
96b5d3 |
spec_entry *spec)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int n;
|
|
Packit Service |
96b5d3 |
int argindex = (pinfo->dollar && !IS_MODIFIER (spec))
|
|
Packit Service |
96b5d3 |
? pinfo->dollar - 1
|
|
Packit Service |
96b5d3 |
: pinfo->argindex;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
int save_argindex = pinfo->argindex;
|
|
Packit Service |
96b5d3 |
int save_state = pinfo->state;
|
|
Packit Service |
96b5d3 |
char const *save_format = pinfo->format;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!spec->arg)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
n = 1;
|
|
Packit Service |
96b5d3 |
if (pinfo->argc <= argindex)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* "argtypes" points to a pointer of an array of int values.
|
|
Packit Service |
96b5d3 |
* Here, we ensure that there are "argindex + 1" entries in
|
|
Packit Service |
96b5d3 |
* that array.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
*argtypes = snv_renew (int, *argtypes, (argindex + 1));
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* IF there are more entries that follow the current argument
|
|
Packit Service |
96b5d3 |
* index, then we will clobber all the entries that follow.
|
|
Packit Service |
96b5d3 |
* The size of these entries is the size of the array elements,
|
|
Packit Service |
96b5d3 |
* not the size of the pointer to the array elements.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
if (pinfo->argc < argindex)
|
|
Packit Service |
96b5d3 |
memset(*argtypes + pinfo->argc, PA_UNKNOWN,
|
|
Packit Service |
96b5d3 |
(size_t)(argindex - pinfo->argc) * sizeof(**argtypes));
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
pinfo->argc = argindex + 1;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
(*argtypes) [argindex] = spec->type;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
pinfo->spec = (unsigned)*(pinfo->format);
|
|
Packit Service |
96b5d3 |
pinfo->extra = spec->user;
|
|
Packit Service |
96b5d3 |
pinfo->type = spec->type;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (pinfo->argc > argindex)
|
|
Packit Service |
96b5d3 |
n = spec->arg(pinfo, (size_t) (pinfo->argc - argindex),
|
|
Packit Service |
96b5d3 |
*argtypes + argindex);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
n = spec->arg(pinfo, (size_t)0, NULL);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (n < 0)
|
|
Packit Service |
96b5d3 |
return n;
|
|
Packit Service |
96b5d3 |
if (argindex + n > pinfo->argc)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int new_ct = argindex + n;
|
|
Packit Service |
96b5d3 |
*argtypes = snv_renew (int, *argtypes, new_ct);
|
|
Packit Service |
96b5d3 |
memset(*argtypes + pinfo->argc, PA_UNKNOWN,
|
|
Packit Service |
96b5d3 |
(size_t)(new_ct - pinfo->argc) * sizeof(**argtypes));
|
|
Packit Service |
96b5d3 |
pinfo->argc = argindex + n;
|
|
Packit Service |
96b5d3 |
/* Call again... */
|
|
Packit Service |
96b5d3 |
pinfo->argindex = save_argindex;
|
|
Packit Service |
96b5d3 |
pinfo->format = save_format;
|
|
Packit Service |
96b5d3 |
pinfo->state = save_state;
|
|
Packit Service |
96b5d3 |
pinfo->spec = (unsigned)*(pinfo->format);
|
|
Packit Service |
96b5d3 |
pinfo->extra = spec->user;
|
|
Packit Service |
96b5d3 |
pinfo->type = spec->type;
|
|
Packit Service |
96b5d3 |
n = spec->arg(pinfo, (size_t)n, *argtypes + argindex);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!pinfo->dollar || !IS_MODIFIER (spec))
|
|
Packit Service |
96b5d3 |
pinfo->argindex += n;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return n;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* printf_strerror: printf.h
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Communicate information on the last error in a printf
|
|
Packit Service |
96b5d3 |
* format string.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* A string describing the last error which occurred during the
|
|
Packit Service |
96b5d3 |
* parsing of a printf format string. It is the responsibility
|
|
Packit Service |
96b5d3 |
* of the caller to free the string.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
char *
|
|
Packit Service |
96b5d3 |
printf_strerror (void)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
return snv_strdup(printf_last_error);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* (re)initialise the memory used by PPARSER. */
|
|
Packit Service |
96b5d3 |
static inline void
|
|
Packit Service |
96b5d3 |
parser_init (
|
|
Packit Service |
96b5d3 |
struct printf_info *pinfo,
|
|
Packit Service |
96b5d3 |
const char *format,
|
|
Packit Service |
96b5d3 |
const union printf_arg *args)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
memset (pinfo, 0, sizeof (struct printf_info));
|
|
Packit Service |
96b5d3 |
pinfo->format = format;
|
|
Packit Service |
96b5d3 |
pinfo->args = args;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
static inline struct printf_info *
|
|
Packit Service |
96b5d3 |
parser_reset (struct printf_info *pinfo)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
pinfo->is_long_double = pinfo->is_char = pinfo->is_short =
|
|
Packit Service |
96b5d3 |
pinfo->is_long = 0;
|
|
Packit Service |
96b5d3 |
pinfo->alt = 0;
|
|
Packit Service |
96b5d3 |
pinfo->left = 0;
|
|
Packit Service |
96b5d3 |
pinfo->showsign = 0;
|
|
Packit Service |
96b5d3 |
pinfo->group = 0;
|
|
Packit Service |
96b5d3 |
pinfo->wide = 0;
|
|
Packit Service |
96b5d3 |
pinfo->spec = 0;
|
|
Packit Service |
96b5d3 |
pinfo->width = 0;
|
|
Packit Service |
96b5d3 |
pinfo->space = 0;
|
|
Packit Service |
96b5d3 |
pinfo->state = SNV_STATE_BEGIN;
|
|
Packit Service |
96b5d3 |
pinfo->prec = -1;
|
|
Packit Service |
96b5d3 |
pinfo->dollar = 0;
|
|
Packit Service |
96b5d3 |
pinfo->pad = ' ';
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return pinfo;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* printf_error: printf.h
|
|
Packit Service |
96b5d3 |
* @pinfo: pointer to the current parser state.
|
|
Packit Service |
96b5d3 |
* @file: file where error was detected.
|
|
Packit Service |
96b5d3 |
* @line: line where error was detected.
|
|
Packit Service |
96b5d3 |
* @func1: " (" if function is supplied by compiler.
|
|
Packit Service |
96b5d3 |
* @func2: function where error was detected, if supplied by compiler.
|
|
Packit Service |
96b5d3 |
* @func3: ")" if function is supplied by compiler.
|
|
Packit Service |
96b5d3 |
* @error_message: new error message to append to @pinfo.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* The contents of @error_message are appended to the @pinfo internal
|
|
Packit Service |
96b5d3 |
* error string, so it is safe to pass static strings or recycle the
|
|
Packit Service |
96b5d3 |
* original when this function returns.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The address of the full accumulated error message in @pinfo is
|
|
Packit Service |
96b5d3 |
* returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
char *
|
|
Packit Service |
96b5d3 |
printf_error (struct printf_info *pinfo, const char *file, int line,
|
|
Packit Service |
96b5d3 |
const char *func1, const char *func2, const char *func3,
|
|
Packit Service |
96b5d3 |
const char *error_message)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int i;
|
|
Packit Service |
96b5d3 |
char *result;
|
|
Packit Service |
96b5d3 |
if (pinfo->error == NULL)
|
|
Packit Service |
96b5d3 |
pinfo->error = filnew (NULL, (size_t)0);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
filccat (pinfo->error, '\n');
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Cannot use printf because a bug in it might trigger another
|
|
Packit Service |
96b5d3 |
printf_error! */
|
|
Packit Service |
96b5d3 |
result = filcat (pinfo->error, "file ");
|
|
Packit Service |
96b5d3 |
filcat (pinfo->error, file);
|
|
Packit Service |
96b5d3 |
filcat (pinfo->error, ": line ");
|
|
Packit Service |
96b5d3 |
for (i = 10; i <= line; i *= 10);
|
|
Packit Service |
96b5d3 |
for (i /= 10; i >= 1; i /= 10)
|
|
Packit Service |
96b5d3 |
filccat (pinfo->error, '0' + (line / i) % 10);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
filcat (pinfo->error, func1);
|
|
Packit Service |
96b5d3 |
filcat (pinfo->error, func2);
|
|
Packit Service |
96b5d3 |
filcat (pinfo->error, func3);
|
|
Packit Service |
96b5d3 |
filcat (pinfo->error, ": ");
|
|
Packit Service |
96b5d3 |
filcat (pinfo->error, error_message);
|
|
Packit Service |
96b5d3 |
return result;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* parse_printf_format: printf.h
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @n: the size of the @argtypes vector
|
|
Packit Service |
96b5d3 |
* @argtypes: a vector of ints, to be filled with the argument types from @format
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Returns information about the number and types of
|
|
Packit Service |
96b5d3 |
* arguments expected by the template string @format.
|
|
Packit Service |
96b5d3 |
* The argument @n specifies the number of elements in the array
|
|
Packit Service |
96b5d3 |
* @argtypes. This is the maximum number of elements that
|
|
Packit Service |
96b5d3 |
* the function will try to write.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The total number of arguments required by @format. If this
|
|
Packit Service |
96b5d3 |
* number is greater than @n, then the information returned
|
|
Packit Service |
96b5d3 |
* describes only the first @n arguments. If you want information
|
|
Packit Service |
96b5d3 |
* about additional arguments, allocate a bigger array and call
|
|
Packit Service |
96b5d3 |
* this function again. If there is an error, then %SNV_ERROR
|
|
Packit Service |
96b5d3 |
* is returned instead.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
size_t
|
|
Packit Service |
96b5d3 |
parse_printf_format (const char *format, int n, int *argtypes)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
struct printf_info info;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return_val_if_fail (format != NULL, (size_t)-1);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
parser_init (&info, format, NULL);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
while (*info.format != EOS)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int ch = (int) *info.format++;
|
|
Packit Service |
96b5d3 |
spec_entry *spec;
|
|
Packit Service |
96b5d3 |
int status;
|
|
Packit Service |
96b5d3 |
int argindex;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (ch != SNV_CHAR_SPEC)
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (*info.format == SNV_CHAR_SPEC)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* An escaped CHAR_SPEC: ignore it (by falling through). */
|
|
Packit Service |
96b5d3 |
++info.format;
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* We found the start of a format specifier! */
|
|
Packit Service |
96b5d3 |
parser_reset (&info;;
|
|
Packit Service |
96b5d3 |
do
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* Until we fill the stream (or get some other
|
|
Packit Service |
96b5d3 |
exception) or one of the handlers tells us
|
|
Packit Service |
96b5d3 |
we have reached the end of the specifier... */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* ...lookup the handler associated with the char
|
|
Packit Service |
96b5d3 |
we are looking at in the format string... */
|
|
Packit Service |
96b5d3 |
spec = spec_lookup ((unsigned)*(info.format));
|
|
Packit Service |
96b5d3 |
if (spec == NULL)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "unregistered specifier");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!IS_MODIFIER (spec) &&
|
|
Packit Service |
96b5d3 |
!(info.state & (SNV_STATE_BEGIN | SNV_STATE_SPECIFIER)))
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "invalid combination of flags");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
argindex = info.dollar && !IS_MODIFIER (spec)
|
|
Packit Service |
96b5d3 |
? info.dollar - 1 : info.argindex;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* ...and call the relevant handler. */
|
|
Packit Service |
96b5d3 |
if (spec->arg)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
info.spec = (unsigned)*(info.format);
|
|
Packit Service |
96b5d3 |
info.extra = spec->user;
|
|
Packit Service |
96b5d3 |
info.type = spec->type;
|
|
Packit Service |
96b5d3 |
status = (*spec->arg) (&info, (size_t) (n - argindex),
|
|
Packit Service |
96b5d3 |
argtypes + argindex);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
status = 1;
|
|
Packit Service |
96b5d3 |
if (n > argindex)
|
|
Packit Service |
96b5d3 |
argtypes[argindex] = spec->type;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (status < 0)
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
info.argc = MAX (info.argc, argindex + status);
|
|
Packit Service |
96b5d3 |
if (!info.dollar || !IS_MODIFIER (spec))
|
|
Packit Service |
96b5d3 |
info.argindex += status;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
info.format++;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
while (IS_MODIFIER (spec));
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
error:
|
|
Packit Service |
96b5d3 |
/* Get here on error */
|
|
Packit Service |
96b5d3 |
info.argc = -1;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (printf_last_error)
|
|
Packit Service |
96b5d3 |
snv_delete (printf_last_error);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (info.error)
|
|
Packit Service |
96b5d3 |
printf_last_error = fildelete (info.error);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
printf_last_error = NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return (size_t)info.argc;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
static int
|
|
Packit Service |
96b5d3 |
do_printfv (STREAM *stream, const char *format, union printf_arg const args[])
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
struct printf_info info;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* This is the parser driver.
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
Here we scan through the format string and move bytes into the
|
|
Packit Service |
96b5d3 |
stream and call handlers based on the parser state. */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
parser_init (&info, format, args);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Keep going until the format string runs out! */
|
|
Packit Service |
96b5d3 |
while (*info.format != EOS)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int ch = (int) *info.format++;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
switch (ch)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
case SNV_CHAR_SPEC:
|
|
Packit Service |
96b5d3 |
if (*info.format != SNV_CHAR_SPEC)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* We found the start of a format specifier! */
|
|
Packit Service |
96b5d3 |
spec_entry *spec;
|
|
Packit Service |
96b5d3 |
int status;
|
|
Packit Service |
96b5d3 |
int argindex;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
parser_reset (&info;;
|
|
Packit Service |
96b5d3 |
do
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* Until we fill the stream (or get some other
|
|
Packit Service |
96b5d3 |
exception) or one of the handlers tells us
|
|
Packit Service |
96b5d3 |
we have reached the end of the specifier... */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* ...lookup the handler associated with the char
|
|
Packit Service |
96b5d3 |
we are looking at in the format string... */
|
|
Packit Service |
96b5d3 |
spec = spec_lookup ((unsigned)*(info.format));
|
|
Packit Service |
96b5d3 |
if (spec == NULL)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "unregistered specifier");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!IS_MODIFIER (spec) &&
|
|
Packit Service |
96b5d3 |
!(info.state & (SNV_STATE_BEGIN | SNV_STATE_SPECIFIER)))
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "invalid combination of flags");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* ...and call the relevant handler. */
|
|
Packit Service |
96b5d3 |
info.spec = (unsigned)*(info.format);
|
|
Packit Service |
96b5d3 |
info.extra = spec->user;
|
|
Packit Service |
96b5d3 |
info.type = spec->type;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
status = spec->arg ? (*spec->arg) (&info, (size_t)0, NULL) : 1;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (status < 0)
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
argindex = info.dollar && !IS_MODIFIER (spec)
|
|
Packit Service |
96b5d3 |
? info.dollar - 1 : info.argindex;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
info.format++;
|
|
Packit Service |
96b5d3 |
info.argc = MAX (info.argc, argindex + status);
|
|
Packit Service |
96b5d3 |
if (!info.dollar && !IS_MODIFIER (spec))
|
|
Packit Service |
96b5d3 |
info.argindex += status;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
while (info.count >= 0 && IS_MODIFIER (spec));
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
status = (*spec->fmt) (stream, &info, args + argindex);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (status < 0)
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
info.count += status;
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* An escaped CHAR_SPEC: ignore it (by falling through). */
|
|
Packit Service |
96b5d3 |
++info.format;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*FALLTHROUGH*/
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
default:
|
|
Packit Service |
96b5d3 |
/* Just a character: copy it. */
|
|
Packit Service |
96b5d3 |
SNV_EMIT (ch, stream, info.count);
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
error:
|
|
Packit Service |
96b5d3 |
/* Get here on error */
|
|
Packit Service |
96b5d3 |
info.count = -1;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (printf_last_error)
|
|
Packit Service |
96b5d3 |
snv_delete (printf_last_error);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (info.error)
|
|
Packit Service |
96b5d3 |
printf_last_error = fildelete (info.error);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
printf_last_error = NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return info.count;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* stream_printfv: printf.h
|
|
Packit Service |
96b5d3 |
* @stream: an initialised stream structure.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @args: a vector of argument addresses to match @format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @args according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to @stream. If @stream is %NULL, only count the
|
|
Packit Service |
96b5d3 |
* number of characters needed to output the format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
stream_printfv (STREAM *stream, const char *format, snv_constpointer const *ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
union printf_arg *args;
|
|
Packit Service |
96b5d3 |
struct printf_info info;
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
int *argtypes = NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return_val_if_fail (format != NULL, SNV_ERROR);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
parser_init (&info, format, NULL);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Keep going until the format string runs out! */
|
|
Packit Service |
96b5d3 |
while (*info.format != EOS)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int ch = (int) *info.format++;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
switch (ch)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
case SNV_CHAR_SPEC:
|
|
Packit Service |
96b5d3 |
if (*info.format != SNV_CHAR_SPEC)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* We found the start of a format specifier! */
|
|
Packit Service |
96b5d3 |
spec_entry *spec;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
parser_reset (&info;;
|
|
Packit Service |
96b5d3 |
do
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* Until we fill the stream (or get some other
|
|
Packit Service |
96b5d3 |
exception) or one of the handlers tells us
|
|
Packit Service |
96b5d3 |
we have reached the end of the specifier... */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* ...lookup the handler associated with the char
|
|
Packit Service |
96b5d3 |
we are looking at in the format string... */
|
|
Packit Service |
96b5d3 |
spec = spec_lookup ((unsigned)*(info.format));
|
|
Packit Service |
96b5d3 |
if (spec == NULL)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "unregistered specifier");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!IS_MODIFIER (spec) &&
|
|
Packit Service |
96b5d3 |
!(info.state & (SNV_STATE_BEGIN | SNV_STATE_SPECIFIER)))
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "invalid combination of flags");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* ...and call the relevant handler. */
|
|
Packit Service |
96b5d3 |
if (call_argtype_function (&info, &argtypes, spec) < 0)
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
info.format++;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
while (info.count >= 0 && IS_MODIFIER (spec));
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* An escaped CHAR_SPEC: ignore it (by falling through). */
|
|
Packit Service |
96b5d3 |
++info.format;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*FALLTHROUGH*/
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
default: /* Just a character: ignore it. */
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
error:
|
|
Packit Service |
96b5d3 |
/* Get here on error */
|
|
Packit Service |
96b5d3 |
info.argc = -1;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (info.argc == 0)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
args = NULL;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int idx;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
assert(argtypes != NULL);
|
|
Packit Service |
96b5d3 |
args = snv_new (union printf_arg, info.argc);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* We scanned the format string to find the type of the arguments,
|
|
Packit Service |
96b5d3 |
so we can now cast it and store it correctly. */
|
|
Packit Service |
96b5d3 |
for (idx = 0; idx < info.argc; idx++)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int tp = argtypes[idx];
|
|
Packit Service |
96b5d3 |
if ((tp & PA_TYPE_MASK) == PA_TYPE_MASK)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
if (idx + 1 == info.argc)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
info.argc--;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
continue; /* Ignore it. We allow skipping args, but the
|
|
Packit Service |
96b5d3 |
* user is responsible for ensuring a void* sized
|
|
Packit Service |
96b5d3 |
* spacer in the argument list.
|
|
Packit Service |
96b5d3 |
*/
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
switch (tp & ~PA_FLAG_UNSIGNED)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
case PA_CHAR:
|
|
Packit Service |
96b5d3 |
args[idx].pa_char = (unsigned char)*(const long int *)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_WCHAR:
|
|
Packit Service |
96b5d3 |
args[idx].pa_wchar =
|
|
Packit Service |
96b5d3 |
(snv_wchar_t) *(const long int *)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT|PA_FLAG_SHORT:
|
|
Packit Service |
96b5d3 |
args[idx].pa_short_int =
|
|
Packit Service |
96b5d3 |
(short int) *(const long int *)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT:
|
|
Packit Service |
96b5d3 |
args[idx].pa_int = (int) *(const long int *)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT|PA_FLAG_LONG:
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_int = *(const long int *)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT|PA_FLAG_LONG_LONG:
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_long_int = **(const intmax_t **)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_FLOAT:
|
|
Packit Service |
96b5d3 |
args[idx].pa_float = **(const float **)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
|
|
Packit Service |
96b5d3 |
#ifdef HAVE_LONG_DOUBLE
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_double = **(const long double **)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
#endif
|
|
Packit Service |
96b5d3 |
/* else fall through */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_DOUBLE:
|
|
Packit Service |
96b5d3 |
args[idx].pa_double = **(const double **)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Note that pointer types are dereferenced just once! */
|
|
Packit Service |
96b5d3 |
case PA_STRING:
|
|
Packit Service |
96b5d3 |
args[idx].pa_string = *(const char **)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_WSTRING:
|
|
Packit Service |
96b5d3 |
args[idx].pa_wstring = *(const snv_wchar_t **)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_POINTER:
|
|
Packit Service |
96b5d3 |
args[idx].pa_pointer = *(snv_constpointer *)(ap + idx);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
default:
|
|
Packit Service |
96b5d3 |
if (argtypes[idx] & PA_FLAG_PTR)
|
|
Packit Service |
96b5d3 |
args[idx].pa_pointer = *(snv_constpointer *)(ap + idx);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_double = 0.0;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (printf_last_error)
|
|
Packit Service |
96b5d3 |
snv_delete (printf_last_error);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (info.error)
|
|
Packit Service |
96b5d3 |
printf_last_error = fildelete (info.error);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
printf_last_error = NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
count_or_errorcode = do_printfv (stream, format, args);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
snv_delete (argtypes);
|
|
Packit Service |
96b5d3 |
if (info.argc > 0)
|
|
Packit Service |
96b5d3 |
snv_delete (args);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* stream_vprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @stream: an initialised stream structure.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @ap: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @ap according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to @stream. If @stream is %NULL, only count the
|
|
Packit Service |
96b5d3 |
* number of characters needed to output the format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
stream_vprintf (STREAM *stream, const char *format, va_list ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
union printf_arg *args = NULL;
|
|
Packit Service |
96b5d3 |
struct printf_info info;
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
int *argtypes = NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return_val_if_fail (format != NULL, SNV_ERROR);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
parser_init (&info, format, NULL);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Keep going until the format string runs out! */
|
|
Packit Service |
96b5d3 |
while (*info.format != EOS)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int ch = (int) *info.format++;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
switch (ch)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
case SNV_CHAR_SPEC:
|
|
Packit Service |
96b5d3 |
if (*info.format != SNV_CHAR_SPEC)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* We found the start of a format specifier! */
|
|
Packit Service |
96b5d3 |
spec_entry *spec;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
parser_reset (&info;;
|
|
Packit Service |
96b5d3 |
do
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
/* Until we fill the stream (or get some other
|
|
Packit Service |
96b5d3 |
exception) or one of the handlers tells us
|
|
Packit Service |
96b5d3 |
we have reached the end of the specifier... */
|
|
Packit Service |
96b5d3 |
/* ...lookup the handler associated with the char
|
|
Packit Service |
96b5d3 |
we are looking at in the format string... */
|
|
Packit Service |
96b5d3 |
spec = spec_lookup ((unsigned)*(info.format));
|
|
Packit Service |
96b5d3 |
if (spec == NULL)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "unregistered specifier");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (!IS_MODIFIER (spec) &&
|
|
Packit Service |
96b5d3 |
!(info.state & (SNV_STATE_BEGIN | SNV_STATE_SPECIFIER)))
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
PRINTF_ERROR (&info, "invalid combination of flags");
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* ...and call the relevant handler. */
|
|
Packit Service |
96b5d3 |
if (call_argtype_function (&info, &argtypes, spec) < 0)
|
|
Packit Service |
96b5d3 |
goto error;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
info.format++;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
while (info.count >= 0 && IS_MODIFIER (spec));
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
/* An escaped CHAR_SPEC: ignore it (by falling through). */
|
|
Packit Service |
96b5d3 |
++info.format;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*FALLTHROUGH*/
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
default: /* Just a character: ignore it. */
|
|
Packit Service |
96b5d3 |
continue;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
error:
|
|
Packit Service |
96b5d3 |
/* Get here on error */
|
|
Packit Service |
96b5d3 |
info.argc = -1;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (info.argc > 0)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int idx;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
assert(argtypes != NULL);
|
|
Packit Service |
96b5d3 |
args = snv_new (union printf_arg, info.argc);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Scan the format string to find the type of the argument
|
|
Packit Service |
96b5d3 |
so we can cast it and store it correctly.
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
Note that according to the ISO C standards, standard
|
|
Packit Service |
96b5d3 |
type promotion takes place on any variadic arguments as
|
|
Packit Service |
96b5d3 |
they are aligned on the call stack, and so it is these
|
|
Packit Service |
96b5d3 |
promoted types that we must extract with the va_arg()
|
|
Packit Service |
96b5d3 |
macro, or the alignment gets all messed up.
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
Thanks to Robert Lipe <robertlipe@usa.net> for explaining all
|
|
Packit Service |
96b5d3 |
this to me. */
|
|
Packit Service |
96b5d3 |
for (idx = 0; idx < info.argc; idx++)
|
|
Packit Service |
96b5d3 |
switch (argtypes[idx] & ~PA_FLAG_UNSIGNED)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
case PA_CHAR:
|
|
Packit Service |
96b5d3 |
args[idx].pa_char = (unsigned char)va_arg (ap, int); /* Promoted */
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_WCHAR:
|
|
Packit Service |
96b5d3 |
args[idx].pa_wchar = (snv_wchar_t)va_arg (ap, snv_wint_t);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT|PA_FLAG_SHORT:
|
|
Packit Service |
96b5d3 |
args[idx].pa_short_int = (short int)va_arg (ap, int);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT:
|
|
Packit Service |
96b5d3 |
args[idx].pa_int = va_arg (ap, int);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT|PA_FLAG_LONG:
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_int = va_arg (ap, long int);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_INT|PA_FLAG_LONG_LONG:
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_long_int = va_arg (ap, intmax_t);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_FLOAT:
|
|
Packit Service |
96b5d3 |
args[idx].pa_float = (float)va_arg (ap, double); /* Promoted. */
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_double = va_arg (ap, long double);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_DOUBLE:
|
|
Packit Service |
96b5d3 |
args[idx].pa_double = va_arg (ap, double);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_STRING:
|
|
Packit Service |
96b5d3 |
args[idx].pa_string = va_arg (ap, const char *);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_WSTRING:
|
|
Packit Service |
96b5d3 |
args[idx].pa_wstring = va_arg (ap, const snv_wchar_t *);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
case PA_POINTER:
|
|
Packit Service |
96b5d3 |
args[idx].pa_pointer = va_arg (ap, void *);
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
default:
|
|
Packit Service |
96b5d3 |
if (argtypes[idx] & PA_FLAG_PTR)
|
|
Packit Service |
96b5d3 |
args[idx].pa_pointer = va_arg (ap, void *);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
args[idx].pa_long_double = 0.0;
|
|
Packit Service |
96b5d3 |
break;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (printf_last_error)
|
|
Packit Service |
96b5d3 |
snv_delete (printf_last_error);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
if (info.error)
|
|
Packit Service |
96b5d3 |
printf_last_error = fildelete (info.error);
|
|
Packit Service |
96b5d3 |
else
|
|
Packit Service |
96b5d3 |
printf_last_error = NULL;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
count_or_errorcode = do_printfv (stream, format, args);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
snv_delete (argtypes);
|
|
Packit Service |
96b5d3 |
snv_delete (args);
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* stream_printf: printf.h
|
|
Packit Service |
96b5d3 |
* @stream: an initialised stream structure.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @va_alist: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @va_alist according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to @stream. If @stream is %NULL, only count the
|
|
Packit Service |
96b5d3 |
* number of characters needed to output the format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
stream_printf (STREAM * stream, const char *format, ...)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
va_list ap;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
va_start (ap, format);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = stream_vprintf (stream, format, ap);
|
|
Packit Service |
96b5d3 |
va_end (ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Finally... the main API implementation: */
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_fdputc: printf.h
|
|
Packit Service |
96b5d3 |
* @ch: A single character to be added to @stream.
|
|
Packit Service |
96b5d3 |
* @stream: The stream in which to write @ch.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* A StreamPut function for use in putting characters
|
|
Packit Service |
96b5d3 |
* into STREAMs holding a file descriptor.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The value of @ch that has been put in @stream, or -1 in case of
|
|
Packit Service |
96b5d3 |
* an error (errno will be set to indicate the type of error).
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_fdputc (int ch, STREAM *stream)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
static char buf[1] = { 0 };
|
|
Packit Service |
96b5d3 |
buf[0] = (char) ch;
|
|
Packit Service |
96b5d3 |
return
|
|
Packit Service |
96b5d3 |
write ((int) SNV_POINTER_TO_LONG (stream_details (stream)), buf, (size_t) 1)
|
|
Packit Service |
96b5d3 |
? ch : -1;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_dprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @fd: an open file descriptor.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @va_alist: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @va_alist according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the file descriptor @fd.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_dprintf (int fd, const char *format, ...)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
va_list ap;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
va_start (ap, format);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = snv_vdprintf (fd, format, ap);
|
|
Packit Service |
96b5d3 |
va_end (ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_vdprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @fd: an open file descriptor.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @ap: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @ap according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the file descriptor @fd.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_vdprintf (int fd, const char *format, va_list ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int result;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (SNV_LONG_TO_POINTER (fd),
|
|
Packit Service |
96b5d3 |
SNV_UNLIMITED, NULL, snv_fdputc);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
result = stream_vprintf (out, format, ap);
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return result;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_dprintfv: printf.h
|
|
Packit Service |
96b5d3 |
* @fd: an open file descriptor.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @args: a vector of argument addresses to match @format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @args according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to file descriptor @fd.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_dprintfv (int fd, const char *format, snv_constpointer const args[])
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int result;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (SNV_LONG_TO_POINTER (fd),
|
|
Packit Service |
96b5d3 |
SNV_UNLIMITED, NULL, snv_fdputc);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
result = stream_printfv (out, format, args);
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return result;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_fileputc: printf.h
|
|
Packit Service |
96b5d3 |
* @ch: A single character to be added to @stream.
|
|
Packit Service |
96b5d3 |
* @stream: The stream in which to write @ch.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* A StreamPut function for use in putting characters
|
|
Packit Service |
96b5d3 |
* into STREAMs holding a FILE*.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The value of @ch that has been put in @stream.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_fileputc (int ch, STREAM *stream)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
FILE *fp = (FILE *) stream_details (stream);
|
|
Packit Service |
96b5d3 |
return putc (ch, fp);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
static int
|
|
Packit Service |
96b5d3 |
snv_fileputc_unlocked (int ch, STREAM *stream)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
FILE *fp = (FILE *) stream_details (stream);
|
|
Packit Service |
96b5d3 |
return SNV_PUTC_UNLOCKED (ch, fp);
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_printf: printf.h
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @va_alist: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @va_alist according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the standard output stream.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_printf (const char *format, ...)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
va_list ap;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
va_start (ap, format);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = snv_vprintf (format, ap);
|
|
Packit Service |
96b5d3 |
va_end (ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_vprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @ap: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @ap according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the standard output stream.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_vprintf (const char *format, va_list ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int result;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (stdout, SNV_UNLIMITED, NULL, snv_fileputc_unlocked);
|
|
Packit Service |
96b5d3 |
int tmp;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
SNV_WITH_LOCKED_FP (stdout, tmp)
|
|
Packit Service |
96b5d3 |
result = stream_vprintf (out, format, ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return result;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_printfv: printf.h
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @args: a vector of argument addresses to match @format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @args according to the string @format,
|
|
Packit Service |
96b5d3 |
* and write the result to the standard output stream.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_printfv (const char *format, snv_constpointer const args[])
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int result;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (stdout, SNV_UNLIMITED, NULL, snv_fileputc_unlocked);
|
|
Packit Service |
96b5d3 |
int tmp;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
SNV_WITH_LOCKED_FP (stdout, tmp)
|
|
Packit Service |
96b5d3 |
result = stream_printfv (out, format, args);
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return result;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_fprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @file: a stdio.h FILE* stream.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @va_alist: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @va_alist according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the @file stream.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_fprintf (FILE * file, const char *format, ...)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
va_list ap;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
va_start (ap, format);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = snv_vfprintf (file, format, ap);
|
|
Packit Service |
96b5d3 |
va_end (ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_vfprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @file: a stdio.h FILE* stream.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @ap: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @ap according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the @file stream.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_vfprintf (FILE *file, const char *format, va_list ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int result;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (file, SNV_UNLIMITED, NULL, snv_fileputc_unlocked);
|
|
Packit Service |
96b5d3 |
int tmp;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
SNV_WITH_LOCKED_FP (file, tmp)
|
|
Packit Service |
96b5d3 |
result = stream_vprintf (out, format, ap);
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return result;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_fprintfv: printf.h
|
|
Packit Service |
96b5d3 |
* @file: a stdio.h FILE* stream.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @args: a vector of argument addresses to match @format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @args according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to @file.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_fprintfv (FILE *file, const char *format, snv_constpointer const args[])
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int result;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (file, SNV_UNLIMITED, NULL, snv_fileputc_unlocked);
|
|
Packit Service |
96b5d3 |
int tmp;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
SNV_WITH_LOCKED_FP (file, tmp)
|
|
Packit Service |
96b5d3 |
result = stream_printfv (out, format, args);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return result;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_bufputc: printf.h
|
|
Packit Service |
96b5d3 |
* @ch: A single character to be added to @stream.
|
|
Packit Service |
96b5d3 |
* @stream: The stream in which to write @ch.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* A StreamPut function for use in putting characters
|
|
Packit Service |
96b5d3 |
* into STREAMs holding a char buffer.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The value of @ch that has been put in @stream.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_bufputc (int ch, STREAM * stream)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
char **ppbuffer = (char **) stream_details (stream);
|
|
Packit Service |
96b5d3 |
**ppbuffer = (char) ch;
|
|
Packit Service |
96b5d3 |
(*ppbuffer)++;
|
|
Packit Service |
96b5d3 |
return ch;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_sprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @buffer: a preallocated char* buffer.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @va_alist: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @va_alist according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the string @buffer.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_sprintf (char buffer[], const char *format, ...)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
va_list ap;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
va_start (ap, format);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = snv_vsprintf (buffer, format, ap);
|
|
Packit Service |
96b5d3 |
va_end (ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_vsprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @buffer: a preallocated char* buffer.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @ap: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @ap according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the string @buffer.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_vsprintf (char buffer[], const char *format, va_list ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (&buffer, SNV_UNLIMITED, NULL, snv_bufputc);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = stream_vprintf (out, format, ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Terminate with an EOS without incrementing the counter. */
|
|
Packit Service |
96b5d3 |
stream_put (EOS, out);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_sprintfv: printf.h
|
|
Packit Service |
96b5d3 |
* @buffer: a preallocated char* buffer.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @args: a vector of argument addresses to match @format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @args according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the string @buffer.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_sprintfv (char buffer[], const char *format, snv_constpointer const args[])
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (&buffer, SNV_UNLIMITED, NULL, snv_bufputc);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = stream_printfv (out, format, args);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/* Terminate with an EOS without incrementing the counter. */
|
|
Packit Service |
96b5d3 |
stream_put (EOS, out);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_snprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @buffer: a preallocated char* buffer.
|
|
Packit Service |
96b5d3 |
* @limit: the maximum number of characters to write into @buffer.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @va_alist: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @va_alist according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the string @buffer, truncating the formatted string
|
|
Packit Service |
96b5d3 |
* if it reaches @limit characters in length.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_snprintf (char buffer[], unsigned long limit, const char *format, ...)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
va_list ap;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
va_start (ap, format);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = snv_vsnprintf (buffer, limit, format, ap);
|
|
Packit Service |
96b5d3 |
va_end (ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_vsnprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @buffer: a preallocated char* buffer.
|
|
Packit Service |
96b5d3 |
* @limit: the maximum number of characters to write into @buffer.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @ap: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @ap according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the string @buffer, truncating the formatted string
|
|
Packit Service |
96b5d3 |
* if it reaches @limit characters in length.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_vsnprintf (char buffer[], unsigned long limit, const char *format, va_list ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (&buffer, limit - 1, NULL, snv_bufputc);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = stream_vprintf (out, format, ap);
|
|
Packit Service |
96b5d3 |
*buffer = EOS;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_snprintfv: printf.h
|
|
Packit Service |
96b5d3 |
* @buffer: a preallocated char* buffer.
|
|
Packit Service |
96b5d3 |
* @limit: the maximum number of characters to write into @buffer.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @args: a vector of argument addresses to match @format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @args according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to the string @buffer, truncating the formatted string
|
|
Packit Service |
96b5d3 |
* if it reaches @limit characters in length.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_snprintfv (char buffer[], unsigned long limit, const char *format,
|
|
Packit Service |
96b5d3 |
snv_constpointer const args[])
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (&buffer, limit - 1, NULL, snv_bufputc);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = stream_printfv (out, format, args);
|
|
Packit Service |
96b5d3 |
*buffer = EOS;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_filputc: printf.h
|
|
Packit Service |
96b5d3 |
* @ch: A single character to be added to @stream.
|
|
Packit Service |
96b5d3 |
* @stream: The stream in which to write @ch.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* A StreamPut function for use in putting characters
|
|
Packit Service |
96b5d3 |
* into STREAMs holding a Filament*.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The value of @ch that has been put in @stream.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_filputc (int ch, STREAM * stream)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
return filccat ((Filament *) stream_details (stream), ch), ch;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_asprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @result: the address of a char * variable.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @va_alist: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @va_alist according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to an internally allocated buffer whose address is
|
|
Packit Service |
96b5d3 |
* stored in @result (and should be freed by the caller) unless
|
|
Packit Service |
96b5d3 |
* there is an error.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Yes, this interface is cumbersome and totally useless. It would
|
|
Packit Service |
96b5d3 |
* have been better to simply return the allocated address, but
|
|
Packit Service |
96b5d3 |
* it turns out that somebody wasn't thinking much when adding
|
|
Packit Service |
96b5d3 |
* asprintf to libiberty a few years ago.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_asprintf (char **result, const char *format, ...)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count;
|
|
Packit Service |
96b5d3 |
va_list ap;
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
va_start (ap, format);
|
|
Packit Service |
96b5d3 |
count = snv_vasprintf (result, format, ap);
|
|
Packit Service |
96b5d3 |
va_end (ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
return count;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_vasprintf: printf.h
|
|
Packit Service |
96b5d3 |
* @result: the address of a char * variable.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @ap: a varargs/stdargs va_list.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @ap according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to an internally allocated buffer whose address is
|
|
Packit Service |
96b5d3 |
* stored in @result (and should be freed by the caller) unless
|
|
Packit Service |
96b5d3 |
* there is an error.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Above moaning for asprintf applies here too.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_vasprintf (char **result, const char *format, va_list ap)
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
char *base;
|
|
Packit Service |
96b5d3 |
Filament *fil = filnew (NULL, (size_t)0);
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (fil, SNV_UNLIMITED, NULL, snv_filputc);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = stream_vprintf (out, format, ap);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
base = fildelete (fil);
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
*result = (count_or_errorcode < 0) ? NULL : base;
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/**
|
|
Packit Service |
96b5d3 |
* snv_asprintfv: printf.h
|
|
Packit Service |
96b5d3 |
* @result: the address of a char * variable.
|
|
Packit Service |
96b5d3 |
* @format: a % delimited format string.
|
|
Packit Service |
96b5d3 |
* @args: a vector of argument addresses to match @format.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Format the elements of @args according to @format, and write
|
|
Packit Service |
96b5d3 |
* the results to an internally allocated buffer whose address is
|
|
Packit Service |
96b5d3 |
* stored in @result (and should be freed by the caller) unless
|
|
Packit Service |
96b5d3 |
* there is an error.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Above moaning for asprintf applies here too.
|
|
Packit Service |
96b5d3 |
*
|
|
Packit Service |
96b5d3 |
* Return value:
|
|
Packit Service |
96b5d3 |
* The number of characters written is returned, unless there is
|
|
Packit Service |
96b5d3 |
* an error, when %SNV_ERROR is returned.
|
|
Packit Service |
96b5d3 |
**/
|
|
Packit Service |
96b5d3 |
int
|
|
Packit Service |
96b5d3 |
snv_asprintfv (char **result, const char *format, snv_constpointer const args[])
|
|
Packit Service |
96b5d3 |
{
|
|
Packit Service |
96b5d3 |
int count_or_errorcode;
|
|
Packit Service |
96b5d3 |
char *base;
|
|
Packit Service |
96b5d3 |
Filament *fil = filnew (NULL, (size_t)0);
|
|
Packit Service |
96b5d3 |
STREAM *out = stream_new (fil, SNV_UNLIMITED, NULL, snv_filputc);
|
|
Packit Service |
96b5d3 |
count_or_errorcode = stream_printfv (out, format, args);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
base = fildelete (fil);
|
|
Packit Service |
96b5d3 |
stream_delete (out);
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
*result = (count_or_errorcode < 0) ? NULL : base;
|
|
Packit Service |
96b5d3 |
return count_or_errorcode;
|
|
Packit Service |
96b5d3 |
}
|
|
Packit Service |
96b5d3 |
|
|
Packit Service |
96b5d3 |
/*
|
|
Packit Service |
96b5d3 |
* Local Variables:
|
|
Packit Service |
96b5d3 |
* mode: C
|
|
Packit Service |
96b5d3 |
* c-file-style: "gnu"
|
|
Packit Service |
96b5d3 |
* indent-tabs-mode: nil
|
|
Packit Service |
96b5d3 |
* End:
|
|
Packit Service |
96b5d3 |
* end of snprintfv/printfv.c */
|