]> git.sur5r.net Git - cc65/commitdiff
Use inttypes.h and the intmax_t/uintmax_t types
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 16 Dec 2004 22:38:07 +0000 (22:38 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 16 Dec 2004 22:38:07 +0000 (22:38 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@3332 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/common/xsprintf.c

index 0242542f7e2ccb677249b82a99265ef782f309f2..da4bcaa64868ae84b43131b79c7c459f639c82f7 100644 (file)
 #include <stdio.h>
 #include <stddef.h>
 #include <string.h>
+#include <limits.h>
 
+/* common */
 #include "chartype.h"
 #include "check.h"
+#include "inttypes.h"
 #include "xsprintf.h"
 
 
@@ -53,8 +56,8 @@
  * features only the basic format specifiers (especially the floating point
  * stuff is missing), but may be extended if required. Reason for supplying
  * my own implementation is that vsnprintf is standard but not implemented by
- * older compilers, and some that implement it in some way or the other, don't
- * adhere to the standard (for example Microsoft with its _vsnprintf).
+ * older compilers, and some that implement it, don't adhere to the standard
+ * (for example Microsoft with its _vsnprintf).
  */
 
 typedef struct {
@@ -104,13 +107,13 @@ typedef struct {
         lmShort,
         lmInt,
         lmLong,
+        lmIntMax,
         lmSizeT,
         lmPtrDiffT,
         lmLongDouble,
 
         /* Unsupported modifiers */
         lmLongLong = lmLong,
-        lmIntMax = lmLong,
 
         /* Default length is integer */
         lmDefault = lmInt
@@ -140,7 +143,7 @@ static void AddPadding (PrintfCtrl* P, char C, unsigned Count)
 
 
 
-static long NextIVal (PrintfCtrl*P)
+static intmax_t NextIVal (PrintfCtrl*P)
 /* Read the next integer value from the variable argument list */
 {
     switch (P->LengthMod) {
@@ -148,7 +151,8 @@ static long NextIVal (PrintfCtrl*P)
         case lmShort:       return (short) va_arg (P->ap, int);
         case lmInt:         return (int) va_arg (P->ap, int);
         case lmLong:        return (long) va_arg (P->ap, long);
-        case lmSizeT:       return (unsigned long) va_arg (P->ap, size_t);
+        case lmIntMax:      return va_arg (P->ap, intmax_t);
+        case lmSizeT:       return (uintmax_t) va_arg (P->ap, size_t);
         case lmPtrDiffT:    return (long) va_arg (P->ap, ptrdiff_t);
         default:            FAIL ("Invalid type size in NextIVal");
     }
@@ -156,23 +160,24 @@ static long NextIVal (PrintfCtrl*P)
 
 
 
-static unsigned long NextUVal (PrintfCtrl*P)
+static uintmax_t NextUVal (PrintfCtrl*P)
 /* Read the next unsigned integer value from the variable argument list */
 {
     switch (P->LengthMod) {
         case lmChar:        return (unsigned char) va_arg (P->ap, unsigned);
         case lmShort:       return (unsigned short) va_arg (P->ap, unsigned);
         case lmInt:         return (unsigned int) va_arg (P->ap, unsigned int);
-        case lmLong:        return va_arg (P->ap, unsigned long);
-        case lmSizeT:       return (unsigned long) va_arg (P->ap, size_t);
-        case lmPtrDiffT:    return (long) va_arg (P->ap, ptrdiff_t);
+        case lmLong:        return (unsigned long) va_arg (P->ap, unsigned long);
+        case lmIntMax:      return va_arg (P->ap, uintmax_t);
+        case lmSizeT:       return va_arg (P->ap, size_t);
+        case lmPtrDiffT:    return (intmax_t) va_arg (P->ap, ptrdiff_t);
         default:            FAIL ("Invalid type size in NextUVal");
     }
 }
 
 
 
-static void ToStr (PrintfCtrl* P, unsigned long Val)
+static void ToStr (PrintfCtrl* P, uintmax_t Val)
 /* Convert the given value to a (reversed) string */
 {
     char* S = P->ArgBuf;
@@ -185,7 +190,7 @@ static void ToStr (PrintfCtrl* P, unsigned long Val)
 
 
 
-static void FormatInt (PrintfCtrl* P, unsigned long Val)
+static void FormatInt (PrintfCtrl* P, uintmax_t Val)
 /* Convert the integer value */
 {
     char Lead[5];
@@ -199,8 +204,8 @@ static void FormatInt (PrintfCtrl* P, unsigned long Val)
     P->CharTable = (P->Flags & fUpcase)? "0123456789ABCDEF" : "0123456789abcedf";
 
     /* Check if the value is negative */
-    if ((P->Flags & fUnsigned) == 0 && ((long) Val) < 0) {
-        Val = -((long) Val);
+    if ((P->Flags & fUnsigned) == 0 && ((intmax_t) Val) < 0) {
+        Val = -((intmax_t) Val);
         Lead[LeadCount++] = '-';
     } else if ((P->Flags & fPlus) != 0) {
         Lead[LeadCount++] = '+';
@@ -212,7 +217,7 @@ static void FormatInt (PrintfCtrl* P, unsigned long Val)
     ToStr (P, Val);
 
     /* The default precision for all integer conversions is one. This means
-     * that the fPrec flag is always set and does not need to be checked 
+     * that the fPrec flag is always set and does not need to be checked
      * later on.
      */
     if ((P->Flags & fPrec) == 0) {
@@ -337,6 +342,23 @@ static void FormatStr (PrintfCtrl* P, const char* Val)
 
 
 
+static void StoreOffset (PrintfCtrl* P)
+/* Store the current output offset (%n format spec) */
+{
+    switch (P->LengthMod) {
+        case lmChar:     *va_arg (P->ap, int*)       = P->BufFill;
+        case lmShort:    *va_arg (P->ap, int*)       = P->BufFill;
+        case lmInt:      *va_arg (P->ap, int*)       = P->BufFill;
+        case lmLong:     *va_arg (P->ap, long*)      = P->BufFill;
+        case lmIntMax:   *va_arg (P->ap, intmax_t*)  = P->BufFill;
+        case lmSizeT:    *va_arg (P->ap, size_t*)    = P->BufFill;
+        case lmPtrDiffT: *va_arg (P->ap, ptrdiff_t*) = P->BufFill;
+        default: FAIL ("Invalid size modifier for %n format spec in xvsnprintf");
+    }
+}
+
+
+
 int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap)
 /* A basic vsnprintf implementation. Does currently only support integer
  * formats.
@@ -543,6 +565,18 @@ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap)
                 FormatStr (&P, SPtr);
                 break;
 
+            case 'p':
+                /* Use hex format for pointers */
+                P.Flags |= (fUnsigned | fPrec);
+                P.Prec = ((sizeof (void*) * CHAR_BIT) + 3) / 4;
+                P.Base = 16;
+                FormatInt (&P, (uintptr_t) va_arg (P.ap, void*));
+                break;
+
+            case 'n':
+                StoreOffset (&P);
+                break;
+
             default:
                 /* Invalid format spec */
                 FAIL ("Invalid format specifier in xvsnprintf");