home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gettext-0.10.24-src.tgz / tar.out / fsf / gettext / lib / vasprintf.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  4KB  |  194 lines

  1. /* Like vsprintf but provides a pointer to malloc'd storage, which must
  2.    be freed by the caller.
  3.    Copyright (C) 1994 Free Software Foundation, Inc.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  18.  
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25.  
  26. #if __STDC__
  27. # include <stdarg.h>
  28. #else
  29. # include <varargs.h>
  30. #endif
  31.  
  32. #ifdef TEST
  33. int global_total_width;
  34. #endif
  35.  
  36. unsigned long strtoul ();
  37. char *malloc ();
  38.  
  39. static int
  40. int_vasprintf (result, format, args)
  41.      char **result;
  42.      const char *format;
  43.      va_list *args;
  44. {
  45.   const char *p = format;
  46.   /* Add one to make sure that it is never zero, which might cause malloc
  47.      to return NULL.  */
  48.   int total_width = strlen (format) + 1;
  49.   va_list ap;
  50.  
  51.   memcpy (&ap, args, sizeof (va_list));
  52.  
  53.   while (*p != '\0')
  54.     {
  55.       if (*p++ == '%')
  56.     {
  57.       while (strchr ("-+ #0", *p))
  58.         ++p;
  59.       if (*p == '*')
  60.         {
  61.           ++p;
  62.           total_width += abs (va_arg (ap, int));
  63.         }
  64.       else
  65.         total_width += strtoul (p, &p, 10);
  66.       if (*p == '.')
  67.         {
  68.           ++p;
  69.           if (*p == '*')
  70.         {
  71.           ++p;
  72.           total_width += abs (va_arg (ap, int));
  73.         }
  74.           else
  75.         total_width += strtoul (p, &p, 10);
  76.         }
  77.       while (strchr ("hlL", *p))
  78.         ++p;
  79.       /* Should be big enough for any format specifier except %s.  */
  80.       total_width += 30;
  81.       switch (*p)
  82.         {
  83.         case 'd':
  84.         case 'i':
  85.         case 'o':
  86.         case 'u':
  87.         case 'x':
  88.         case 'X':
  89.         case 'c':
  90.           (void) va_arg (ap, int);
  91.           break;
  92.         case 'f':
  93.         case 'e':
  94.         case 'E':
  95.         case 'g':
  96.         case 'G':
  97.           (void) va_arg (ap, double);
  98.           break;
  99.         case 's':
  100.           total_width += strlen (va_arg (ap, char *));
  101.           break;
  102.         case 'p':
  103.         case 'n':
  104.           (void) va_arg (ap, char *);
  105.           break;
  106.         }
  107.     }
  108.     }
  109. #ifdef TEST
  110.   global_total_width = total_width;
  111. #endif
  112.   *result = malloc (total_width);
  113.   if (*result != NULL)
  114.     return vsprintf (*result, format, *args);
  115.   else
  116.     return 0;
  117. }
  118.  
  119. int
  120. vasprintf (result, format, args)
  121.      char **result;
  122.      const char *format;
  123.      va_list args;
  124. {
  125.   return int_vasprintf (result, format, &args);
  126. }
  127.  
  128. int
  129. asprintf
  130. #if __STDC__
  131.      (char **result, const char *format, ...)
  132. #else
  133.      (result, va_alist)
  134.      char **result;
  135.      va_dcl
  136. #endif
  137. {
  138.   va_list args;
  139.   int done;
  140.  
  141. #if __STDC__
  142.   va_start (args, format);
  143. #else
  144.   char *format;
  145.   va_start (args);
  146.   format = va_arg (args, char *);
  147. #endif
  148.   done = vasprintf (result, format, args);
  149.   va_end (args);
  150.  
  151.   return done;
  152.  
  153. #ifdef TEST
  154. void
  155. checkit
  156. #if __STDC__
  157.      (const char* format, ...)
  158. #else
  159.      (va_alist)
  160.      va_dcl
  161. #endif
  162. {
  163.   va_list args;
  164.   char *result;
  165.  
  166. #if __STDC__
  167.   va_start (args, format);
  168. #else
  169.   char *format;
  170.   va_start (args);
  171.   format = va_arg (args, char *);
  172. #endif
  173.   vasprintf (&result, format, args);
  174.   if (strlen (result) < global_total_width)
  175.     printf ("PASS: ");
  176.   else
  177.     printf ("FAIL: ");
  178.   printf ("%d %s\n", global_total_width, result);
  179. }
  180.  
  181. int
  182. main ()
  183. {
  184.   checkit ("%d", 0x12345678);
  185.   checkit ("%200d", 5);
  186.   checkit ("%.300d", 6);
  187.   checkit ("%100.150d", 7);
  188.   checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
  189. 777777777777777777333333333333366666666666622222222222777777777777733333");
  190.   checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
  191. }
  192. #endif /* TEST */
  193.