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