Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Cosmetics: removal of a useless comment I wrote in the previous commits
[simgrid.git] / src / xbt / snprintf.c
index a7acabc..89df5fb 100644 (file)
@@ -1,3 +1,8 @@
+/* Copyright (c) 2005-2010, 2012-2015. The SimGrid Team.
+ * All rights reserved.                                                     */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
 
 /*
  * snprintf.c - a portable implementation of snprintf
  *   http://www.ijs.si/software/snprintf/
  *
  * REVISION HISTORY
- * 1999-04     V0.9  Mark Martinec
- *             - initial version, some modifications after comparing printf
- *               man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10,
- *               and checking how Perl handles sprintf (differently!);
- * 1999-04-09  V1.0  Mark Martinec <mark.martinec@ijs.si>
- *             - added main test program, fixed remaining inconsistencies,
- *               added optional (long long int) support;
- * 1999-04-12  V1.1  Mark Martinec <mark.martinec@ijs.si>
- *             - support the 'p' conversion (pointer to void);
- *             - if a string precision is specified
- *               make sure the string beyond the specified precision
- *               will not be referenced (e.g. by strlen);
- * 1999-04-13  V1.2  Mark Martinec <mark.martinec@ijs.si>
- *             - support synonyms %D=%ld, %U=%lu, %O=%lo;
- *             - speed up the case of long format string with few conversions;
- * 1999-06-30  V1.3  Mark Martinec <mark.martinec@ijs.si>
- *             - fixed runaway loop (eventually crashing when str_l wraps
- *               beyond 2^31) while copying format string without
- *               conversion specifiers to a buffer that is too short
- *               (thanks to Edwin Young <edwiny@autonomy.com> for
- *               spotting the problem);
- *             - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR)
- *               to snprintf.h
- * 2000-02-14  V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
- *             - relaxed license terms: The Artistic License now applies.
- *               You may still apply the GNU GENERAL PUBLIC LICENSE
- *               as was distributed with previous versions, if you prefer;
- *             - changed REVISION HISTORY dates to use ISO 8601 date format;
- *             - added vsnprintf (patch also independently proposed by
- *               Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
- * 2000-06-27  V2.1  Mark Martinec <mark.martinec@ijs.si>
- *             - removed POSIX check for str_m<1; value 0 for str_m is
- *               allowed by ISO C99 (and GNU C library 2.1) - (pointed out
- *               on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie).
- *               Besides relaxed license this change in standards adherence
- *               is the main reason to bump up the major version number;
- *             - added nonstandard routines asnprintf, vasnprintf, asprintf,
- *               vasprintf that dynamically allocate storage for the
- *               resulting string; these routines are not compiled by default,
- *               see comments where NEED_V?ASN?PRINTF macros are defined;
- *             - autoconf contributed by Caolan McNamara
- * 2000-10-06  V2.2  Mark Martinec <mark.martinec@ijs.si>
- *             - BUG FIX: the %c conversion used a temporary variable
- *               that was no longer in scope when referenced,
- *               possibly causing incorrect resulting character;
- *             - BUG FIX: make precision and minimal field width unsigned
- *               to handle huge values (2^31 <= n < 2^32) correctly;
- *               also be more careful in the use of signed/unsigned/size_t
- *               internal variables - probably more careful than many
- *               vendor implementations, but there may still be a case
- *               where huge values of str_m, precision or minimal field
- *               could cause incorrect behaviour;
- *             - use separate variables for signed/unsigned arguments,
- *               and for short/int, long, and long long argument lengths
- *               to avoid possible incompatibilities on certain
- *               computer architectures. Also use separate variable
- *               arg_sign to hold sign of a numeric argument,
- *               to make code more transparent;
- *             - some fiddling with zero padding and "0x" to make it
- *               Linux compatible;
- *             - systematically use macros fast_memcpy and fast_memset
- *               instead of case-by-case hand optimization; determine some
- *               breakeven string lengths for different architectures;
- *             - terminology change: 'format' -> 'conversion specifier',
- *               'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")',
- *               'alternative form' -> 'alternate form',
- *               'data type modifier' -> 'length modifier';
- *             - several comments rephrased and new ones added;
- *             - make compiler not complain about 'credits' defined but
- *               not used;
+ * 1999-04  V0.9  Mark Martinec
+ *    - initial version, some modifications after comparing printf
+ *      man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10,
+ *      and checking how Perl handles sprintf (differently!);
+ * 1999-04-09  V1.0  Mark Martinec <mark.martinec@ijs.si>
+ *    - added main test program, fixed remaining inconsistencies,
+ *      added optional (long long int) support;
+ * 1999-04-12  V1.1  Mark Martinec <mark.martinec@ijs.si>
+ *    - support the 'p' conversion (pointer to void);
+ *    - if a string precision is specified
+ *      make sure the string beyond the specified precision
+ *      will not be referenced (e.g. by strlen);
+ * 1999-04-13  V1.2  Mark Martinec <mark.martinec@ijs.si>
+ *    - support synonyms %D=%ld, %U=%lu, %O=%lo;
+ *    - speed up the case of long format string with few conversions;
+ * 1999-06-30  V1.3  Mark Martinec <mark.martinec@ijs.si>
+ *    - fixed runaway loop (eventually crashing when str_l wraps
+ *      beyond 2^31) while copying format string without
+ *      conversion specifiers to a buffer that is too short
+ *      (thanks to Edwin Young <edwiny@autonomy.com> for
+ *      spotting the problem);
+ *    - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR)
+ *      to snprintf.h
+ * 2000-02-14  V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
+ *    - relaxed license terms: The Artistic License now applies.
+ *      You may still apply the GNU GENERAL PUBLIC LICENSE
+ *      as was distributed with previous versions, if you prefer;
+ *    - changed REVISION HISTORY dates to use ISO 8601 date format;
+ *    - added vsnprintf (patch also independently proposed by
+ *      Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
+ * 2000-06-27  V2.1  Mark Martinec <mark.martinec@ijs.si>
+ *    - removed POSIX check for str_m<1; value 0 for str_m is
+ *      allowed by ISO C99 (and GNU C library 2.1) - (pointed out
+ *      on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie).
+ *      Besides relaxed license this change in standards adherence
+ *      is the main reason to bump up the major version number;
+ *    - added nonstandard routines asnprintf, vasnprintf, asprintf,
+ *      vasprintf that dynamically allocate storage for the
+ *      resulting string; these routines are not compiled by default,
+ *      see comments where NEED_V?ASN?PRINTF macros are defined;
+ *    - autoconf contributed by Caolan McNamara
+ * 2000-10-06  V2.2  Mark Martinec <mark.martinec@ijs.si>
+ *    - BUG FIX: the %c conversion used a temporary variable
+ *      that was no longer in scope when referenced,
+ *      possibly causing incorrect resulting character;
+ *    - BUG FIX: make precision and minimal field width unsigned
+ *      to handle huge values (2^31 <= n < 2^32) correctly;
+ *      also be more careful in the use of signed/unsigned/size_t
+ *      internal variables - probably more careful than many
+ *      vendor implementations, but there may still be a case
+ *      where huge values of str_m, precision or minimal field
+ *      could cause incorrect behaviour;
+ *    - use separate variables for signed/unsigned arguments,
+ *      and for short/int, long, and long long argument lengths
+ *      to avoid possible incompatibilities on certain
+ *      computer architectures. Also use separate variable
+ *      arg_sign to hold sign of a numeric argument,
+ *      to make code more transparent;
+ *    - some fiddling with zero padding and "0x" to make it
+ *      Linux compatible;
+ *    - systematically use macros fast_memcpy and fast_memset
+ *      instead of case-by-case hand optimization; determine some
+ *      breakeven string lengths for different architectures;
+ *    - terminology change: 'format' -> 'conversion specifier',
+ *      'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")',
+ *      'alternative form' -> 'alternate form',
+ *      'data type modifier' -> 'length modifier';
+ *    - several comments rephrased and new ones added;
+ *    - make compiler not complain about 'credits' defined but
+ *      not used;
  */
 
 
 #define LINUX_COMPATIBLE
 #endif
 
-#include "portable.h"           /* to get a working stdarg.h */
+#include "src/portable.h"           /* to get a working stdarg.h */
 
 #include <sys/types.h>
 #include <string.h>
 #endif
 
 /* some other values of possible interest: */
-                                                                                                                                                                                                                                                                                                                                  /* #define breakeven_point  8 *//* VAX 4000          - vaxc */
-                                                                                                                                                                                                                                                                                                                                  /* #define breakeven_point 19 *//* VAX 4000          - gcc 2.7.0 */
+                                                                                                                                                                                                                                                                                                                                                                                                  /* #define breakeven_point  8 *//* VAX 4000          - vaxc */
+                                                                                                                                                                                                                                                                                                                                                                                                  /* #define breakeven_point 19 *//* VAX 4000          - gcc 2.7.0 */
 
 #ifndef breakeven_point
 #  define breakeven_point   6   /* some reasonable one-size-fits-all value */
 #endif
 
 #define fast_memcpy(d,s,n) \
-  { register size_t nn = (size_t)(n); \
+  { size_t nn = (size_t)(n); \
   if (nn >= breakeven_point) memcpy((d), (s), nn); \
   else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
-  register char *dd; register const char *ss; \
+  char *dd; const char *ss; \
   for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
 
 #define fast_memset(d,c,n) \
-  { register size_t nn = (size_t)(n); \
+  { size_t nn = (size_t)(n); \
   if (nn >= breakeven_point) memset((d), (int)(c), nn); \
   else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
-  register char *dd; register const int cc=(int)(c); \
+  char *dd; const int cc=(int)(c); \
   for (dd=(d); nn>0; nn--) *dd++ = cc; } }
 
 /* prototypes */
@@ -417,22 +422,22 @@ int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap);
 int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args */
                       ...);
 #if !defined(NEED_SNPRINTF_ONLY)
-int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap);
+int portable_vsnprintf(char *str, size_t str_m, const char *fmt,
+                       va_list ap);
 #endif
 #endif
 
-/* declarations */
+  /* FIXME: better place */
+#include "xbt/sysdep.h"
 
-static char credits[] = "\n\
-  @(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\
-  @(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\
-  @(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
+/* declarations */
 
-static void __foo__(void)
-{
-  printf("%s", credits);
-  __foo__();
-}
+/*
+    Old copyright
+    snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>
+    snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.
+    snprintf.c, v2.2: http://www.ijs.si/software/snprintf
+*/
 
 #if defined(NEED_ASPRINTF)
 int asprintf(char **ptr, const char *fmt, /*args */ ...)
@@ -446,7 +451,7 @@ int asprintf(char **ptr, const char *fmt, /*args */ ...)
   str_l = portable_vsnprintf(NULL, (size_t) 0, fmt, ap);
   va_end(ap);
   assert(str_l >= 0);           /* possible integer overflow if str_m > INT_MAX */
-  *ptr = (char *) malloc(str_m = (size_t) str_l + 1);
+  *ptr = (char *) xbt_malloc(str_m = (size_t) str_l + 1);
   if (*ptr == NULL) {
     errno = ENOMEM;
     str_l = -1;
@@ -475,7 +480,7 @@ int vasprintf(char **ptr, const char *fmt, va_list ap)
     va_end(ap2);
   }
   assert(str_l >= 0);           /* possible integer overflow if str_m > INT_MAX */
-  *ptr = (char *) malloc(str_m = (size_t) str_l + 1);
+  *ptr = (char *) xbt_malloc(str_m = (size_t) str_l + 1);
   if (*ptr == NULL) {
     errno = ENOMEM;
     str_l = -1;
@@ -503,7 +508,7 @@ int asnprintf(char **ptr, size_t str_m, const char *fmt, /*args */ ...)
   /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
   if (str_m == 0) {             /* not interested in resulting string, just return size */
   } else {
-    *ptr = (char *) malloc(str_m);
+    *ptr = (char *) xbt_malloc(str_m);
     if (*ptr == NULL) {
       errno = ENOMEM;
       str_l = -1;
@@ -537,7 +542,7 @@ int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap)
   /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */
   if (str_m == 0) {             /* not interested in resulting string, just return size */
   } else {
-    *ptr = (char *) malloc(str_m);
+    *ptr = (char *) xbt_malloc(str_m);
     if (*ptr == NULL) {
       errno = ENOMEM;
       str_l = -1;
@@ -557,7 +562,8 @@ int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap)
 #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
 
 #if !defined(NEED_SNPRINTF_ONLY)
-int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args */ ...)
+int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args */
+                      ...)
 {
   va_list ap;
   int str_l;
@@ -570,10 +576,12 @@ int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args */ ...)
 #endif
 
 #if defined(NEED_SNPRINTF_ONLY)
-int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args */ ...)
+int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args */
+                      ...)
 {
 #else
-int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap)
+int portable_vsnprintf(char *str, size_t str_m, const char *fmt,
+                       va_list ap)
 {
 #endif
 
@@ -937,7 +945,7 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap)
                      /* Actually it uses 0x prefix even for a zero value. */
                      && arg_sign != 0
 #endif
-              ) {
+                ) {
               tmp[str_arg_l++] = '0';
               tmp[str_arg_l++] = 'x';
             }
@@ -953,7 +961,7 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap)
                * converting a zero value with a precision of zero is a null string.
                * Actually HP returns all zeroes, and Linux returns "(nil)". */
 #endif
-            ) {
+              ) {
             /* converted to null string */
             /* When zero value is formatted with an explicit precision 0,
                the resulting formatted string is empty (d, i, u, o, x, X, p).   */
@@ -1027,7 +1035,7 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap)
                 && !(zero_padding_insertion_ind < str_arg_l
                      && tmp[zero_padding_insertion_ind] == '0')
 #endif
-              ) {               /* assure leading zero for alternate-form octal numbers */
+                ) {             /* assure leading zero for alternate-form octal numbers */
               if (!precision_specified || precision < num_of_digits + 1) {
                 /* precision is increased to force the first character to be zero,
                    except if a zero value is formatted with an explicit precision
@@ -1161,19 +1169,26 @@ int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap)
 #endif
 
 
-  /* FIXME: better place */
-#include "xbt/sysdep.h"
+char *bvprintf(const char *fmt, va_list ap)
+{
+  char *res;
+
+  if (vasprintf(&res, fmt, ap) < 0) {
+    /* Do not want to use xbt_die() here, as it uses the logging
+     * infrastucture and may fail to allocate memory too. */
+    fprintf(stderr, "bprintf: vasprintf failed. Aborting.\n");
+    xbt_abort();
+  }
+  return res;
+}
 
 char *bprintf(const char *fmt, ...)
 {
   va_list ap;
   char *res;
-  int len;
 
   va_start(ap, fmt);
-
-  len = vasprintf(&res, fmt, ap);
-
+  res = bvprintf(fmt, ap);
   va_end(ap);
   return res;
 }