Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* Copyright (C) 2007, 2008 Eric Blake
  2.  * Permission to use, copy, modify, and distribute this software
  3.  * is freely granted, provided that this notice is preserved.
  4.  */
  5. /* This code was derived from asprintf.c */
  6. /* doc in sprintf.c */
  7.  
  8. #include <_ansi.h>
  9. #include <reent.h>
  10. #include <stdio.h>
  11. #include <stdarg.h>
  12. #include <limits.h>
  13. #include <errno.h>
  14. #include "local.h"
  15.  
  16. char *
  17. _DEFUN(_asnprintf_r, (ptr, buf, lenp, fmt),
  18.        struct _reent *__restrict ptr _AND
  19.        char *buf _AND
  20.        size_t *lenp _AND
  21.        const char *__restrict fmt _DOTS)
  22. {
  23.   int ret;
  24.   va_list ap;
  25.   FILE f;
  26.   size_t len = *lenp;
  27.  
  28.   if (buf && len)
  29.     {
  30.       /* mark an existing buffer, but allow allocation of larger string */
  31.       f._flags = __SWR | __SSTR | __SOPT;
  32.     }
  33.   else
  34.     {
  35.       /* mark a zero-length reallocatable buffer */
  36.       f._flags = __SWR | __SSTR | __SMBF;
  37.       len = 0;
  38.       buf = NULL;
  39.     }
  40.   f._bf._base = f._p = (unsigned char *) buf;
  41.   /* For now, inherit the 32-bit signed limit of FILE._bf._size.
  42.      FIXME - it would be nice to rewrite sys/reent.h to support size_t
  43.      for _size.  */
  44.   if (len > INT_MAX)
  45.     {
  46.       ptr->_errno = EOVERFLOW;
  47.       return NULL;
  48.     }
  49.   f._bf._size = f._w = len;
  50.   f._file = -1;  /* No file. */
  51.   va_start (ap, fmt);
  52.   ret = _svfprintf_r (ptr, &f, fmt, ap);
  53.   va_end (ap);
  54.   if (ret < 0)
  55.     return NULL;
  56.   *lenp = ret;
  57.   *f._p = '\0';
  58.   return (char *) f._bf._base;
  59. }
  60.  
  61. #ifndef _REENT_ONLY
  62.  
  63. char *
  64. _DEFUN(asnprintf, (buf, lenp, fmt),
  65.        char *__restrict buf _AND
  66.        size_t *__restrict lenp _AND
  67.        const char *__restrict fmt _DOTS)
  68. {
  69.   int ret;
  70.   va_list ap;
  71.   FILE f;
  72.   size_t len = *lenp;
  73.   struct _reent *ptr = _REENT;
  74.  
  75.   if (buf && len)
  76.     {
  77.       /* mark an existing buffer, but allow allocation of larger string */
  78.       f._flags = __SWR | __SSTR | __SOPT;
  79.     }
  80.   else
  81.     {
  82.       /* mark a zero-length reallocatable buffer */
  83.       f._flags = __SWR | __SSTR | __SMBF;
  84.       len = 0;
  85.       buf = NULL;
  86.     }
  87.   f._bf._base = f._p = (unsigned char *) buf;
  88.   /* For now, inherit the 32-bit signed limit of FILE._bf._size.
  89.      FIXME - it would be nice to rewrite sys/reent.h to support size_t
  90.      for _size.  */
  91.   if (len > INT_MAX)
  92.     {
  93.       ptr->_errno = EOVERFLOW;
  94.       return NULL;
  95.     }
  96.   f._bf._size = f._w = len;
  97.   f._file = -1;  /* No file. */
  98.   va_start (ap, fmt);
  99.   ret = _svfprintf_r (ptr, &f, fmt, ap);
  100.   va_end (ap);
  101.   if (ret < 0)
  102.     return NULL;
  103.   *lenp = ret;
  104.   *f._p = '\0';
  105.   return (char *) f._bf._base;
  106. }
  107.  
  108. #endif /* ! _REENT_ONLY */
  109.