Blame snprintfv/printf.c

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 */