Click here to Skip to main content
15,894,539 members
Articles / Desktop Programming / MFC

MsAccess MdbTools with MFC and .NET

Rate me:
Please Sign up or sign in to vote.
4.82/5 (9 votes)
13 Jan 2012LGPL310 min read 69.2K   9.9K   49  
Viewer of MsAccess databases directly from MFC and .NET - Repair corrupt databases
/* vsprintf with automatic memory allocation.
   Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU Library General Public License as published
   by the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
   USA.  */

#ifndef _WIN32
/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
   This must come before <config.h> because <config.h> may include
   <features.h>, and once <features.h> has been included, it's too late.  */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE    1
#endif
#endif

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "glib/galloca.h"

#include "g-gnulib.h"

/* Specification.  */
#include "vasnprintf.h"

#include <stdio.h>	/* snprintf(), sprintf() */
#include <stdlib.h>	/* abort(), malloc(), realloc(), free() */
#include <string.h>	/* memcpy(), strlen() */
#include <errno.h>	/* errno */
#include <limits.h>	/* CHAR_BIT */
#include <float.h>	/* DBL_MAX_EXP, LDBL_MAX_EXP */
#include "printf-parse.h"

#ifdef HAVE_WCHAR_T
# ifdef HAVE_WCSLEN
#  define local_wcslen wcslen
# else
   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
      a dependency towards this library, here is a local substitute.
      Define this substitute only once, even if this file is included
      twice in the same compilation unit.  */
#  ifndef local_wcslen_defined
#   define local_wcslen_defined 1
static size_t
local_wcslen (const wchar_t *s)
{
  const wchar_t *ptr;

  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
    ;
  return ptr - s;
}
#  endif
# endif
#endif

/* For those losing systems which don't have 'alloca' we have to add
   some additional code emulating it.  */ 
#ifdef HAVE_ALLOCA 
# define freea(p) /* nothing */
#else
# define alloca(n) malloc (n) 
# define freea(p) free (p) 
#endif

#ifndef HAVE_LONG_LONG_FORMAT
static int
print_long_long (char *buf, 
		 int len, 
		 int width,
		 int precision,
		 unsigned long flags,
		 char conversion,
		 unsigned long long number)
{
  int negative = FALSE;
  char buffer[128];
  char *bufferend;
  char *pointer;
  int base;
  static const char *upper = "0123456789ABCDEFX";
  static const char *lower = "0123456789abcdefx";
  const char *digits;
  int i;
  char *p;
  int count;

#define EMIT(c)           \
  if (p - buf == len - 1) \
    {                     \
      *p++ = '\0';        \
      return len;         \
    }                     \
  else                    \
    *p++ = c;
  
  p = buf;
  
  switch (conversion) 
    {
    case 'o':
      base = 8;
      digits = lower;
      negative = FALSE;
      break;
    case 'x':
      base = 16;
      digits = lower;
      negative = FALSE;
      break;
    case 'X':
      base = 16;
      digits = upper;
      negative = FALSE;
      break;
    default:
      base = 10;
      digits = lower;
      negative = (long long)number < 0;
      if (negative) 
	number = -((long long)number);
      break;
    }

  /* Build number */
  pointer = bufferend = &buffer[sizeof(buffer) - 1];
  *pointer-- = '\0';
  for (i = 1; i < (int)sizeof(buffer); i++)
    {
      *pointer-- = digits[number % base];
      number /= base;
      if (number == 0)
	break;
    }

  /* Adjust width */
  width -= (bufferend - pointer) - 1;

  /* Adjust precision */
  if (precision != -1)
    {
      precision -= (bufferend - pointer) - 1;
      if (precision < 0)
	precision = 0;
      flags |= FLAG_ZERO;
    }

  /* Adjust width further */
  if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE))
    width--;
  if (flags & FLAG_ALT)
    {
      switch (base)
	{
	case 16:
	  width -= 2;
	  break;
	case 8:
	  width--;
	  break;
        default:
	  break;
	}
    }

  /* Output prefixes spaces if needed */
  if (! ((flags & FLAG_LEFT) ||
	 ((flags & FLAG_ZERO) && (precision == -1))))
    {
      count = (precision == -1) ? 0 : precision;
      while (width-- > count)
	*p++ = ' ';
    }

  /* width has been adjusted for signs and alternatives */
  if (negative) 
    {
      EMIT ('-');
    }
  else if (flags & FLAG_SHOWSIGN) 
    {
      EMIT('+');
    }
  else if (flags & FLAG_SPACE) 
    {
      EMIT(' ');
    }
  
  if (flags & FLAG_ALT)
    {
      switch (base)
	{
	case 8:
	  EMIT('0');
	  break;
	case 16:
	  EMIT('0');
	  EMIT(digits[16]);
	  break;
	default:
	  break;
	} /* switch base */
    }
  
  /* Output prefixed zero padding if needed */
  if (flags & FLAG_ZERO)
    {
      if (precision == -1)
	precision = width;
      while (precision-- > 0)
	{
	  EMIT('0');
	  width--;
	}
    }
  
  /* Output the number itself */
  while (*(++pointer))
    {
      EMIT(*pointer);
    }
  
  /* Output trailing spaces if needed */
  if (flags & FLAG_LEFT)
    {
      while (width-- > 0)
	EMIT(' ');
    }
  
  EMIT('\0');
  
  return p - buf - 1;
}
#endif

char *
vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
{
  char_directives d;
  arguments a;

  if (printf_parse (format, &d, &a) < 0)
    {
      errno = EINVAL;
      return NULL;
    }

#define CLEANUP() \
  free (d.dir);								\
  if (a.arg)								\
    free (a.arg);

  if (printf_fetchargs (args, &a) < 0)
    {
      CLEANUP ();
      errno = EINVAL;
      return NULL;
    }

  {
    char *buf =
      (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
    const char *cp;
    unsigned int i;
    char_directive *dp;
    /* Output string accumulator.  */
    char *result;
    size_t allocated;
    size_t length;

    if (resultbuf != NULL)
      {
	result = resultbuf;
	allocated = *lengthp;
      }
    else
      {
	result = NULL;
	allocated = 0;
      }
    length = 0;
    /* Invariants:
       result is either == resultbuf or == NULL or malloc-allocated.
       If length > 0, then result != NULL.  */

#define ENSURE_ALLOCATION(needed) \
    if ((needed) > allocated)						\
      {									\
	char *memory;							\
									\
	allocated = (allocated > 0 ? 2 * allocated : 12);		\
	if ((needed) > allocated)					\
	  allocated = (needed);						\
	if (result == resultbuf || result == NULL)			\
	  memory = (char *) malloc (allocated);				\
	else								\
	  memory = (char *) realloc (result, allocated);		\
									\
	if (memory == NULL)						\
	  {								\
	    if (!(result == resultbuf || result == NULL))		\
	      free (result);						\
	    freea (buf);						\
	    CLEANUP ();							\
	    errno = ENOMEM;						\
	    return NULL;						\
	  }								\
	if (result == resultbuf && length > 0)				\
	  memcpy (memory, result, length);				\
	result = memory;						\
      }

    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
      {
	if (cp != dp->dir_start)
	  {
	    size_t n = dp->dir_start - cp;

	    ENSURE_ALLOCATION (length + n);
	    memcpy (result + length, cp, n);
	    length += n;
	  }
	if (i == d.count)
	  break;

	/* Execute a single directive.  */
	if (dp->conversion == '%')
	  {
	    if (!(dp->arg_index < 0))
	      abort ();
	    ENSURE_ALLOCATION (length + 1);
	    result[length] = '%';
	    length += 1;
	  }
	else
	  {
	    if (!(dp->arg_index >= 0))
	      abort ();

	    if (dp->conversion == 'n')
	      {
		switch (a.arg[dp->arg_index].type)
		  {
		  case TYPE_COUNT_SCHAR_POINTER:
		    *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
		    break;
		  case TYPE_COUNT_SHORT_POINTER:
		    *a.arg[dp->arg_index].a.a_count_short_pointer = length;
		    break;
		  case TYPE_COUNT_INT_POINTER:
		    *a.arg[dp->arg_index].a.a_count_int_pointer = length;
		    break;
		  case TYPE_COUNT_LONGINT_POINTER:
		    *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
		    break;
#ifdef HAVE_LONG_LONG
		  case TYPE_COUNT_LONGLONGINT_POINTER:
		    *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
		    break;
#endif
		  default:
		    abort ();
		  }
	      }
	    else
	      {
		arg_type type = a.arg[dp->arg_index].type;
		char *p;
		unsigned int prefix_count;
		int prefixes[2];
#if !HAVE_SNPRINTF
		unsigned int tmp_length;
		char tmpbuf[700];
		char *tmp;

		/* Allocate a temporary buffer of sufficient size for calling
		   sprintf.  */
		{
		  unsigned int width;
		  unsigned int precision;

		  width = 0;
		  if (dp->width_start != dp->width_end)
		    {
		      if (dp->width_arg_index >= 0)
			{
			  int arg;

			  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
			    abort ();
			  arg = a.arg[dp->width_arg_index].a.a_int;
			  width = (arg < 0 ? -arg : arg);
			}
		      else
			{
			  const char *digitp = dp->width_start;

			  do
			    width = width * 10 + (*digitp++ - '0');
			  while (digitp != dp->width_end);
			}
		    }

		  precision = 6;
		  if (dp->precision_start != dp->precision_end)
		    {
		      if (dp->precision_arg_index >= 0)
			{
			  int arg;

			  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
			    abort ();
			  arg = a.arg[dp->precision_arg_index].a.a_int;
			  precision = (arg < 0 ? 0 : arg);
			}
		      else
			{
			  const char *digitp = dp->precision_start + 1;

			  precision = 0;
			  while (digitp != dp->precision_end)
			    precision = precision * 10 + (*digitp++ - '0');
			}
		    }

		  switch (dp->conversion)
		    {
		    case 'd': case 'i': case 'u':
# ifdef HAVE_LONG_LONG
		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
			tmp_length =
			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
					  * 0.30103 /* binary -> decimal */
					  * 2 /* estimate for FLAG_GROUP */
					 )
			  + 1 /* turn floor into ceil */
			  + 1; /* account for leading sign */
		      else
# endif
		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
			tmp_length =
			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
					  * 0.30103 /* binary -> decimal */
					  * 2 /* estimate for FLAG_GROUP */
					 )
			  + 1 /* turn floor into ceil */
			  + 1; /* account for leading sign */
		      else
			tmp_length =
			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
					  * 0.30103 /* binary -> decimal */
					  * 2 /* estimate for FLAG_GROUP */
					 )
			  + 1 /* turn floor into ceil */
			  + 1; /* account for leading sign */
		      break;

		    case 'o':
# ifdef HAVE_LONG_LONG
		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
			tmp_length =
			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
					  * 0.333334 /* binary -> octal */
					 )
			  + 1 /* turn floor into ceil */
			  + 1; /* account for leading sign */
		      else
# endif
		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
			tmp_length =
			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
					  * 0.333334 /* binary -> octal */
					 )
			  + 1 /* turn floor into ceil */
			  + 1; /* account for leading sign */
		      else
			tmp_length =
			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
					  * 0.333334 /* binary -> octal */
					 )
			  + 1 /* turn floor into ceil */
			  + 1; /* account for leading sign */
		      break;

		    case 'x': case 'X':
# ifdef HAVE_LONG_LONG
		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
			tmp_length =
			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
					  * 0.25 /* binary -> hexadecimal */
					 )
			  + 1 /* turn floor into ceil */
			  + 2; /* account for leading sign or alternate form */
		      else
# endif
# ifdef HAVE_INT64_AND_I64
		      if (type == TYPE_INT64 || type == TYPE_UINT64)
			tmp_length =
			  (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT
					  * 0.25 /* binary -> hexadecimal */
					  )
			  + 1 /* turn floor into ceil */
			  + 2; /* account for leading sign or alternate form */
		      else
# endif
		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
			tmp_length =
			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
					  * 0.25 /* binary -> hexadecimal */
					 )
			  + 1 /* turn floor into ceil */
			  + 2; /* account for leading sign or alternate form */
		      else
			tmp_length =
			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
					  * 0.25 /* binary -> hexadecimal */
					 )
			  + 1 /* turn floor into ceil */
			  + 2; /* account for leading sign or alternate form */
		      break;

		    case 'f': case 'F':
# ifdef HAVE_LONG_DOUBLE
		      if (type == TYPE_LONGDOUBLE)
			tmp_length =
			  (unsigned int) (LDBL_MAX_EXP
					  * 0.30103 /* binary -> decimal */
					  * 2 /* estimate for FLAG_GROUP */
					 )
			  + 1 /* turn floor into ceil */
			  + precision
			  + 10; /* sign, decimal point etc. */
		      else
# endif
			tmp_length =
			  (unsigned int) (DBL_MAX_EXP
					  * 0.30103 /* binary -> decimal */
					  * 2 /* estimate for FLAG_GROUP */
					 )
			  + 1 /* turn floor into ceil */
			  + precision
			  + 10; /* sign, decimal point etc. */
		      break;

		    case 'e': case 'E': case 'g': case 'G':
		    case 'a': case 'A':
		      tmp_length =
			precision
			+ 12; /* sign, decimal point, exponent etc. */
		      break;

		    case 'c':
# ifdef HAVE_WINT_T
		      if (type == TYPE_WIDE_CHAR)
			tmp_length = MB_CUR_MAX;
		      else
# endif
			tmp_length = 1;
		      break;

		    case 's':
# ifdef HAVE_WCHAR_T
		      if (type == TYPE_WIDE_STRING)
			tmp_length =
			  (a.arg[dp->arg_index].a.a_wide_string == NULL
			  ? 6 /* wcslen(L"(null)") */
			   : local_wcslen (a.arg[dp->arg_index].a.a_wide_string)) 
			  * MB_CUR_MAX;
		      else
# endif
			tmp_length = a.arg[dp->arg_index].a.a_string == NULL
			  ? 6 /* strlen("(null)") */
			  : strlen (a.arg[dp->arg_index].a.a_string);
		      break;

		    case 'p':
		      tmp_length =
			(unsigned int) (sizeof (void *) * CHAR_BIT
					* 0.25 /* binary -> hexadecimal */
				       )
			  + 1 /* turn floor into ceil */
			  + 2; /* account for leading 0x */
		      break;

		    default:
		      abort ();
		    }

		  if (tmp_length < width)
		    tmp_length = width;

		  tmp_length++; /* account for trailing NUL */
		}

		if (tmp_length <= sizeof (tmpbuf))
		  tmp = tmpbuf;
		else
		  {
		    tmp = (char *) malloc (tmp_length);
		    if (tmp == NULL)
		      {
			/* Out of memory.  */
			if (!(result == resultbuf || result == NULL))
			  free (result);
			freea (buf);
			CLEANUP ();
			errno = ENOMEM;
			return NULL;
		      }
		  }
#endif

		/* Construct the format string for calling snprintf or
		   sprintf.  */
		p = buf;
		*p++ = '%';
		if (dp->flags & FLAG_GROUP)
		  *p++ = '\'';
		if (dp->flags & FLAG_LEFT)
		  *p++ = '-';
		if (dp->flags & FLAG_SHOWSIGN)
		  *p++ = '+';
		if (dp->flags & FLAG_SPACE)
		  *p++ = ' ';
		if (dp->flags & FLAG_ALT)
		  *p++ = '#';
		if (dp->flags & FLAG_ZERO)
		  *p++ = '0';
		if (dp->width_start != dp->width_end)
		  {
		    size_t n = dp->width_end - dp->width_start;
		    memcpy (p, dp->width_start, n);
		    p += n;
		  }
		if (dp->precision_start != dp->precision_end)
		  {
		    size_t n = dp->precision_end - dp->precision_start;
		    memcpy (p, dp->precision_start, n);
		    p += n;
		  }

		switch (type)
		  {
#ifdef HAVE_INT64_AND_I64
		  case TYPE_INT64:
		  case TYPE_UINT64:
		    *p++ = 'I';
		    *p++ = '6';
		    *p++ = '4';
		    break;
#endif
#ifdef HAVE_LONG_LONG
		  case TYPE_LONGLONGINT:
		  case TYPE_ULONGLONGINT:
#ifdef HAVE_INT64_AND_I64	/* The system (sn)printf uses %I64. Also assume
				 * that long long == __int64.
				 */
		    *p++ = 'I';
		    *p++ = '6';
		    *p++ = '4';
		    break;
#else
		    *p++ = 'l';
		    /*FALLTHROUGH*/
#endif
#endif
		  case TYPE_LONGINT:
		  case TYPE_ULONGINT:
#ifdef HAVE_WINT_T
		  case TYPE_WIDE_CHAR:
#endif
#ifdef HAVE_WCHAR_T
		  case TYPE_WIDE_STRING:
#endif
		    *p++ = 'l';
		    break;
#ifdef HAVE_LONG_DOUBLE
		  case TYPE_LONGDOUBLE:
		    *p++ = 'L';
		    break;
#endif
		  default:
		    break;
		  }
		*p = dp->conversion;
#if HAVE_SNPRINTF
		p[1] = '%';
		p[2] = 'n';
		p[3] = '\0';
#else
		p[1] = '\0';
#endif

		/* Construct the arguments for calling snprintf or sprintf.  */
		prefix_count = 0;
		if (dp->width_arg_index >= 0)
		  {
		    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
		      abort ();
		    prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
		  }
		if (dp->precision_arg_index >= 0)
		  {
		    if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
		      abort ();
		    prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
		  }

#if HAVE_SNPRINTF
		/* Prepare checking whether snprintf returns the count
		   via %n.  */
		ENSURE_ALLOCATION (length + 1);
		result[length] = '\0';
#endif

		for (;;)
		  {
		    size_t maxlen;
		    int count;
		    int retcount;

		    maxlen = allocated - length;
		    count = -1;
		    retcount = 0;

#if HAVE_SNPRINTF
#define SNPRINTF_BUF(arg) \
		    switch (prefix_count)				    \
		      {							    \
		      case 0:						    \
			retcount = snprintf (result + length, maxlen, buf,  \
					     arg, &count);		    \
			break;						    \
		      case 1:						    \
			retcount = snprintf (result + length, maxlen, buf,  \
					     prefixes[0], arg, &count);	    \
			break;						    \
		      case 2:						    \
			retcount = snprintf (result + length, maxlen, buf,  \
					     prefixes[0], prefixes[1], arg, \
					     &count);			    \
			break;						    \
		      default:						    \
			abort ();					    \
		      }
#else
#define SNPRINTF_BUF(arg) \
		    switch (prefix_count)				    \
		      {							    \
		      case 0:						    \
			count = sprintf (tmp, buf, arg);		    \
			break;						    \
		      case 1:						    \
			count = sprintf (tmp, buf, prefixes[0], arg);	    \
			break;						    \
		      case 2:						    \
			count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
					 arg);				    \
			break;						    \
		      default:						    \
			abort ();					    \
		      }
#endif

		    switch (type)
		      {
		      case TYPE_SCHAR:
			{
			  int arg = a.arg[dp->arg_index].a.a_schar;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_UCHAR:
			{
			  unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_SHORT:
			{
			  int arg = a.arg[dp->arg_index].a.a_short;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_USHORT:
			{
			  unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_INT:
			{
			  int arg = a.arg[dp->arg_index].a.a_int;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_UINT:
			{
			  unsigned int arg = a.arg[dp->arg_index].a.a_uint;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_LONGINT:
			{
			  long int arg = a.arg[dp->arg_index].a.a_longint;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_ULONGINT:
			{
			  unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
			  SNPRINTF_BUF (arg);
			}
			break;
#ifdef HAVE_INT64_AND_I64
		      case TYPE_INT64:
			{
			  __int64 arg = a.arg[dp->arg_index].a.a_int64;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_UINT64:
			{
			  unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64;
			  SNPRINTF_BUF (arg);
			}
			break;			
#endif
#ifdef HAVE_LONG_LONG
#ifndef HAVE_LONG_LONG_FORMAT
		      case TYPE_LONGLONGINT:
		      case TYPE_ULONGLONGINT:
			{
			  unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
			  int width;
			  int precision;

			  width = 0;
			  if (dp->width_start != dp->width_end)
			    {
			      if (dp->width_arg_index >= 0)
				{
				  int arg;
				  
				  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
				    abort ();
				  arg = a.arg[dp->width_arg_index].a.a_int;
				  width = (arg < 0 ? -arg : arg);
				}
			      else
				{
				  const char *digitp = dp->width_start;
				  
				  do
				    width = width * 10 + (*digitp++ - '0');
				  while (digitp != dp->width_end);
				}
			    }

			  precision = -1;
			  if (dp->precision_start != dp->precision_end)
			    {
			      if (dp->precision_arg_index >= 0)
				{
				  int arg;
				  
				  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
				    abort ();
				  arg = a.arg[dp->precision_arg_index].a.a_int;
				  precision = (arg < 0 ? 0 : arg);
				}
			      else
				{
				  const char *digitp = dp->precision_start + 1;
				  
				  precision = 0;
				  do
				    precision = precision * 10 + (*digitp++ - '0');
				  while (digitp != dp->precision_end);
				}
			    }
			  
#if HAVE_SNPRINTF
 			  count = print_long_long (result + length, maxlen,
 						   width, precision,
 						   dp->flags,
 						   dp->conversion,
 						   arg);
#else
			  count = print_long_long (tmp, tmp_length,
						   width, precision,
						   dp->flags,
						   dp->conversion,
						   arg);
#endif
			}
			break;
#else
		      case TYPE_LONGLONGINT:
			{
			  long long int arg = a.arg[dp->arg_index].a.a_longlongint;
			  SNPRINTF_BUF (arg);
			}
			break;
		      case TYPE_ULONGLONGINT:
			{
			  unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
			  SNPRINTF_BUF (arg);
			}
			break;
#endif
#endif
		      case TYPE_DOUBLE:
			{
			  double arg = a.arg[dp->arg_index].a.a_double;
			  SNPRINTF_BUF (arg);
			}
			break;
#ifdef HAVE_LONG_DOUBLE
		      case TYPE_LONGDOUBLE:
			{
			  long double arg = a.arg[dp->arg_index].a.a_longdouble;
			  SNPRINTF_BUF (arg);
			}
			break;
#endif
		      case TYPE_CHAR:
			{
			  int arg = a.arg[dp->arg_index].a.a_char;
			  SNPRINTF_BUF (arg);
			}
			break;
#ifdef HAVE_WINT_T
		      case TYPE_WIDE_CHAR:
			{
			  wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
			  SNPRINTF_BUF (arg);
			}
			break;
#endif
		      case TYPE_STRING:
			{
			  const char *arg = a.arg[dp->arg_index].a.a_string == NULL
			    ? "(null)"
			    : a.arg[dp->arg_index].a.a_string;
			  SNPRINTF_BUF (arg);
			}
			break;
#ifdef HAVE_WCHAR_T
		      case TYPE_WIDE_STRING:
			{
			  const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string == NULL
			    ? L"(null)"
			    : a.arg[dp->arg_index].a.a_wide_string;
			  SNPRINTF_BUF (arg);
			}
			break;
#endif
		      case TYPE_POINTER:
			{
			  void *arg = a.arg[dp->arg_index].a.a_pointer;
			  SNPRINTF_BUF (arg);
			}
			break;
		      default:
			abort ();
		      }

#if HAVE_SNPRINTF
		    /* Portability: Not all implementations of snprintf()
		       are ISO C 99 compliant.  Determine the number of
		       bytes that snprintf() has produced or would have
		       produced.  */
		    if (count >= 0)
		      {
			/* Verify that snprintf() has NUL-terminated its
			   result.  */
			if (count < maxlen && result[length + count] != '\0')
			  abort ();
			/* Portability hack.  */
			if (retcount > count)
			  count = retcount;
		      }
		    else
		      {
			/* snprintf() doesn't understand the '%n'
			   directive.  */
			if (p[1] != '\0')
			  {
			    /* Don't use the '%n' directive; instead, look
			       at the snprintf() return value.  */
			    p[1] = '\0';
			    continue;
			  }
			count = retcount;
		      }
#endif

		    /* Attempt to handle failure.  */
		    if (count < 0)
		      {
			if (!(result == resultbuf || result == NULL))
			  free (result);
			freea (buf);
			CLEANUP ();
			errno = EINVAL;
			return NULL;
		      }

#if !HAVE_SNPRINTF
		    if (count >= tmp_length)
		      /* tmp_length was incorrectly calculated - fix the
			 code above!  */
		      abort ();
#endif

		    /* Make room for the result.  */
		    if (count >= maxlen)
		      {
			/* Need at least count bytes.  But allocate
			   proportionally, to avoid looping eternally if
			   snprintf() reports a too small count.  */
			size_t n = length + count;

			if (n < 2 * allocated)
			  n = 2 * allocated;

			ENSURE_ALLOCATION (n);
#if HAVE_SNPRINTF
			continue;
#endif
		      }

#if HAVE_SNPRINTF
		    /* The snprintf() result did fit.  */
#else
		    /* Append the sprintf() result.  */
		    memcpy (result + length, tmp, count);
		    if (tmp != tmpbuf)
		      free (tmp);
#endif

		    length += count;
		    break;
		  }
	      }
	  }
      }

    /* Add the final NUL.  */
    ENSURE_ALLOCATION (length + 1);
    result[length] = '\0';

    if (result != resultbuf && length + 1 < allocated)
      {
	/* Shrink the allocated memory if possible.  */
	char *memory;

	memory = (char *) realloc (result, length + 1);
	if (memory != NULL)
	  result = memory;
      }

    freea (buf);
    CLEANUP ();
    *lengthp = length;
    return result;
  }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer
Argentina Argentina
System developer from Argentina.

Programmed in VB 5,6,.NET, C#, Java, PL-SQL, Transac-SQL, C, C++ and even some "calculator" language.

Love to build small, useful applications.
Usually building big and complicated apps based on solid, reliable components.

Hobbies: reading, photography, chess, paddle, running.

Comments and Discussions