Example #1
0
static int
printf_string (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args)
{
  int len = 0, count_or_errorcode = SNV_OK;
  const char *p = NULL;

  return_val_if_fail (pinfo != NULL, SNV_ERROR);

  /* Read these now to advance the argument pointer appropriately */
  if (pinfo->prec == -1)
    pinfo->prec = 0;

  /* Check for valid pre-state. */
  if (pinfo->prec <= -1
     || pinfo->is_char || pinfo->is_short || pinfo->is_long
     || pinfo->is_long_double)
    {
      PRINTF_ERROR (pinfo, "invalid flags");
      return -1;
    }

  /* Extract the correct argument from the arg vector. */
  p = args->pa_string;

  /* Left pad to the width if the supplied argument is less than
     the width specifier.  */
  if (p != NULL)
    {
      len = strlen (p);
      if (pinfo->prec && pinfo->prec < len)
	len = pinfo->prec;
    }

  if ((len < pinfo->width) && !pinfo->left)
    {
      int padwidth = pinfo->width - len;
      while ((count_or_errorcode >= 0) && (count_or_errorcode < padwidth))
	SNV_EMIT (pinfo->pad, stream, count_or_errorcode);
    }

  /* Fill the buffer with as many characters from the format argument
     as possible without overflowing or exceeding the precision.  */
  if ((count_or_errorcode >= 0) && (p != NULL))
    {
      int mark = count_or_errorcode;
      while ((count_or_errorcode >= 0) && *p != '\0'
	     && ((pinfo->prec == 0) || (count_or_errorcode - mark < len)))
	SNV_EMIT (*p++, stream, count_or_errorcode);
    }

  /* Right pad to the width if we still didn't reach the specified
     width and the left justify flag was set.  */
  if ((count_or_errorcode < pinfo->width) && pinfo->left)
    while ((count_or_errorcode >= 0)
	   && (count_or_errorcode < pinfo->width))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Return the number of characters emitted. */
  return count_or_errorcode;
}
Example #2
0
static int
printf_char (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args)
{
  int count_or_errorcode = SNV_OK;
  char ch = '\0';

  return_val_if_fail (pinfo != NULL, SNV_ERROR);

  /* Check for valid pre-state. */
  if (pinfo->prec != -1
     || pinfo->is_char || pinfo->is_short || pinfo->is_long
     || pinfo->is_long_double || pinfo->pad == '0'
     || pinfo->alt || pinfo->space || pinfo->showsign)
    {
      PRINTF_ERROR (pinfo, "invalid flags");
      return -1;
    }

  /* Extract the correct argument from the arg vector. */
  ch = args->pa_char;

  /* Left pad to the width if the supplied argument is less than
     the width specifier.  */
  if ((pinfo->width > 1) && !pinfo->left)
    {
      int padwidth = pinfo->width - 1;

      while ((count_or_errorcode >= 0) && (count_or_errorcode < padwidth))
	SNV_EMIT (pinfo->pad, stream, count_or_errorcode);
    }

  /* Emit the character argument.  */
  SNV_EMIT (ch, stream, count_or_errorcode);

  /* Right pad to the width if we still didn't reach the specified
     width and the left justify flag was set.  */
  if ((count_or_errorcode < pinfo->width) && pinfo->left)
    while ((count_or_errorcode >= 0)
	   && (count_or_errorcode < pinfo->width))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Return the number of characters emitted. */
  return count_or_errorcode;
}
Example #3
0
static int
printf_pointer (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args)
{
  int count_or_errorcode = SNV_OK;

  return_val_if_fail (pinfo != NULL, SNV_ERROR);

  /* Read these now to advance the argument pointer appropriately */
  if (pinfo->prec == -1)
    pinfo->prec = 0;

  /* Check for valid pre-state. */
  if (pinfo->prec <= -1
     || pinfo->is_char || pinfo->is_short || pinfo->is_long
     || pinfo->is_long_double)
    {
      PRINTF_ERROR (pinfo, "invalid flags");
      return -1;
    }

  /* Always print 0x. */
  pinfo->alt = 1;
  pinfo->is_long = sizeof(long) == sizeof (char *);
  pinfo->is_long_double = sizeof(intmax_t) == sizeof (char *);

  /* Use the standard routine for numbers for the printing call,
     if the pointer is not NULL.  */

  if (args->pa_pointer != NULL)
    return printf_integer (stream, pinfo, args);

  /* Print a NULL pointer as (nil), appropriately padded.  */
  if ((pinfo->width > 5) && !pinfo->left)
    {
      int padwidth = pinfo->width - 5;
      while ((count_or_errorcode >= 0) && (count_or_errorcode < padwidth))
	SNV_EMIT (pinfo->pad, stream, count_or_errorcode);
    }

  SNV_EMIT ('(', stream, count_or_errorcode);
  SNV_EMIT ('n', stream, count_or_errorcode);
  SNV_EMIT ('i', stream, count_or_errorcode);
  SNV_EMIT ('l', stream, count_or_errorcode);
  SNV_EMIT (')', stream, count_or_errorcode);

  if ((pinfo->width > 5) && pinfo->left)
    while ((count_or_errorcode >= 0)
	   && (count_or_errorcode < pinfo->width))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  return count_or_errorcode;
}
Example #4
0
/**
 * printf_generic:
 * @stream: the stream (possibly a struct printfv_stream appropriately
 * cast) on which to write output.
 * @pinfo: the current state information for the format string parser.
 * @args: the pointer to the first argument to be read by the handler
 *
 * An example implementation of a %printf_function, used to provide easy
 * access to justification, width and precision options.
 *
 * Return value:
 * The number of characters output.
 **/
int
printf_generic (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args)
{
  int len = 0, count_or_errorcode = SNV_OK;
  char *p = NULL;

  /* Used to interface to the custom function. */
  STREAM *out;
  Filament *fil;
  printf_function *user_func = (printf_function *) pinfo->extra;

  return_val_if_fail (pinfo != NULL, SNV_ERROR);

  /* Read these now to advance the argument pointer appropriately */
  if (pinfo->prec == -1)
    pinfo->prec = 0;

  /* Check for valid pre-state. */
  if (pinfo->prec <= -1)
    {
      PRINTF_ERROR (pinfo, "invalid flags");
      return -1;
    }

  /* Print to a stream using a user-supplied function. */
  fil = filnew (NULL, (size_t)0);
  out = stream_new (fil, SNV_UNLIMITED, NULL, snv_filputc);
  user_func (out, pinfo, args);
  stream_delete (out);
  len = (int)fillen (fil);
  p = fildelete (fil);

  /* Left pad to the width if the supplied argument is less than
     the width specifier.  */
  if (p != NULL && pinfo->prec && pinfo->prec < len)
    len = pinfo->prec;

  if ((len < pinfo->width) && !pinfo->left)
    {
      int padwidth = pinfo->width - len;
      while ((count_or_errorcode >= 0) && (count_or_errorcode < padwidth))
	SNV_EMIT (pinfo->pad, stream, count_or_errorcode);
    }

  /* Fill the buffer with as many characters from the format argument
   * as possible without overflowing or exceeding the precision.
   */
  if ((count_or_errorcode >= 0) && (p != NULL))
    {
      int mark = count_or_errorcode;
      while ((count_or_errorcode >= 0) && *p != '\0'
	     && ((pinfo->prec == 0) || (count_or_errorcode - mark < len)))
	SNV_EMIT (*p++, stream, count_or_errorcode);
    }

  /* Right pad to the width if we still didn't reach the specified
   * width and the left justify flag was set.
   */
  if ((count_or_errorcode < pinfo->width) && pinfo->left)
    while ((count_or_errorcode >= 0)
	   && (count_or_errorcode < pinfo->width))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Return the number of characters emitted. */
  return count_or_errorcode;
}
Example #5
0
static int
printf_integer (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args)
{
  static const char digits_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  static const char digits_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  const char *digits;

  unsigned base = SNV_POINTER_TO_UINT (pinfo->extra);
  uintmax_t value = 0L;
  int type, count_or_errorcode = SNV_OK;
  char buffer[256], *p, *end;
  boolean is_negative = FALSE;

  return_val_if_fail (pinfo != NULL, SNV_ERROR);

  /* Check for valid pre-state. */
  if (!(pinfo->state & (SNV_STATE_BEGIN | SNV_STATE_SPECIFIER)))
    {
      PRINTF_ERROR (pinfo, "out of range");
      return -1;
    }

  /* Upper or lower-case hex conversion? */
  digits = ((pinfo->spec >= 'a') && (pinfo->spec <= 'z'))
    ? digits_lower : digits_upper;

  if (pinfo->prec == -1)
    pinfo->prec = 0;

  /* Check for valid pre-state. */
  if (pinfo->prec < 0)
    {
      PRINTF_ERROR (pinfo, "invalid precision");
      return -1;
    }

  type = pinfo->type;

  /* Extract the correct argument from the arg vector. */
  if (type & PA_FLAG_UNSIGNED)
    {
      value = fetch_uintmax (pinfo, args);
      is_negative = FALSE;
      pinfo->showsign = pinfo->space = FALSE;
    }
  else
    {
      intmax_t svalue = 0L;
      svalue = fetch_intmax (pinfo, args);
      is_negative = (svalue < 0);
      value = (uintmax_t) ABS (svalue);
    }

  /* Convert the number into a string. */
  p = end = &buffer[sizeof (buffer) - 1];

  if (value == 0)
    *p-- = '0';

  else
    while (value > 0)
      {
	*p-- = digits[value % base];
	value /= base;
      }

  pinfo->width -= end - p;
  pinfo->prec -= end - p;

  /* Octal numbers have a leading zero in alterate form. */
  if (pinfo->alt && base == 8)
    {
      *p-- = '0';
      --pinfo->width;
    }

  /* Left pad with zeros to make up the precision. */
  if (pinfo->prec > 0)
    {
      pinfo->width -= pinfo->prec;
      while (pinfo->prec-- > 0)
	*p-- = '0';
    }

  /* Reserve room for leading `0x' for hexadecimal. */
  if (pinfo->alt && base == 16)
    pinfo->width -= 2;

  /* Reserve room for a sign character. */
  if (is_negative || pinfo->showsign || pinfo->space)
    --pinfo->width;

  /* Left pad to the remaining width if the supplied argument is less
   * than the width specifier, and the padding character is ' '.
   */
  if (pinfo->pad == ' ' && !pinfo->left)
    while ((count_or_errorcode >= 0) && (pinfo->width-- > 0))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Display any sign character. */
  if (count_or_errorcode >= 0)
    {
      if (is_negative)
	SNV_EMIT ('-', stream, count_or_errorcode);
      else if (pinfo->showsign)
	SNV_EMIT ('+', stream, count_or_errorcode);
      else if (pinfo->space)
	SNV_EMIT (' ', stream, count_or_errorcode);
    }

  /* Display `0x' for alternate hexadecimal specifier. */
  if ((count_or_errorcode >= 0) && (base == 16) && pinfo->alt)
    {
      SNV_EMIT ('0', stream, count_or_errorcode);
      SNV_EMIT (digits['X' - 'A' + 10], stream, count_or_errorcode);
    }

  /* Left pad to the remaining width if the supplied argument is less
   * than the width specifier, and the padding character is not ' '.
   */
  if (pinfo->pad != ' ' && !pinfo->left)
    while ((count_or_errorcode >= 0) && (pinfo->width-- > 0))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Fill the stream buffer with as many characters from the number
   * buffer as possible without overflowing.
   */
  while ((count_or_errorcode >= 0) && (++p < &buffer[sizeof (buffer)]))
    SNV_EMIT (*p, stream, count_or_errorcode);

  /* Right pad to the width if we still didn't reach the specified
   * width and the left justify flag was set.
   */
  if (pinfo->left)
    while ((count_or_errorcode >= 0) && (pinfo->width-- > 0))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Return the number of characters emitted. */
  return count_or_errorcode;
}
Example #6
0
static int
printf_float (STREAM *stream,
	      struct printf_info *const pinfo,
	      union printf_arg const *args)
{
  snv_long_double value = 0.0;
  int sign, len, count_or_errorcode = SNV_OK;
#ifdef HAVE_LONG_DOUBLE
  char buffer[LDBL_MAX_10_EXP * 2 + 20], *p = buffer;
#else
  char buffer[DBL_MAX_10_EXP * 2 + 20], *p = buffer;
#endif

  return_val_if_fail (pinfo != NULL, SNV_ERROR);

  /* Check for valid pre-state */
  if (pinfo->prec == -1)
    pinfo->prec = SNV_POINTER_TO_INT (pinfo->extra);

  /* Check for valid pre-state. */
  if (pinfo->prec <= -1
     || pinfo->is_char || pinfo->is_short || pinfo->is_long)
    {
      PRINTF_ERROR (pinfo, "invalid flags");
      return -1;
    }

  /* Extract the correct argument from the arg vector. */
  value = fetch_double (pinfo, args);

  /* Convert the number into a string. */
  len = print_float (pinfo, buffer, buffer + sizeof (buffer), &sign, value);
  if (*buffer == '0')
    p++, len--;

  /* Compute the size of the padding.  */
  pinfo->width -= len;
  if (sign)
    pinfo->width--;

  /* Left pad to the remaining width if the supplied argument is less
     than the width specifier, and the padding character is ' '.  */
  if (pinfo->pad == ' ' && !pinfo->left)
    while ((count_or_errorcode >= 0) && (pinfo->width-- > 0))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Display any sign character. */
  if (count_or_errorcode >= 0 && sign)
    SNV_EMIT (sign, stream, count_or_errorcode);

  /* Left pad to the remaining width if the supplied argument is less
     than the width specifier, and the padding character is not ' '.  */
  if (pinfo->pad != ' ' && !pinfo->left)
    while ((count_or_errorcode >= 0) && (pinfo->width-- > 0))
	SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Fill the stream buffer with as many characters from the number
     buffer as possible without overflowing.  */
  while ((count_or_errorcode >= 0) && (len-- > 0))
    SNV_EMIT (*p++, stream, count_or_errorcode);

  /* Right pad to the width if we still didn't reach the specified
     width and the left justify flag was set.  */
  if (pinfo->left)
    while ((count_or_errorcode >= 0) && (pinfo->width-- > 0))
      SNV_EMIT (pinfo->pad, stream, count_or_errorcode);

  /* Return the number of characters emitted. */
  return count_or_errorcode;
}