The attached patch adds string_nprintf, the last unimplemented
function listed in strings.pod as far as I can see.

It should cope with both the differences in return values for
vsnprintf between different versions of glibc but there are still
a few platforms which may have problems as they have a vsnprintf
which exhibits a third form of behaviour in the return value, namely
that they return the amount they did manage to produce on overflow.

I'm not sure there is a clean way to cope with that interface without
a configure test to detect it. Equally older systems may not have a
vsnprintf at all which leaves with a problem on those systems.

On a vaguely related note string_substr takes a STRING** for the
destination which seems redundant given than it returns the dest
string, and doesn't even fill in the argument if it does do the
allocation itself. I would suggest making it a STRING* which would
then be consistent with the nprintf interface.

Tom

-- 
Tom Hughes ([EMAIL PROTECTED])
http://www.compton.nu

? xxx
Index: parrot.h
===================================================================
RCS file: /home/perlcvs/parrot/parrot.h,v
retrieving revision 1.8
diff -u -r1.8 parrot.h
--- parrot.h    2001/09/16 22:05:21     1.8
+++ parrot.h    2001/09/17 08:20:49
@@ -43,6 +43,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <string.h>
+#include <stdarg.h>
 
 #define NUM_REGISTERS 32
 #define PARROT_MAGIC 0x13155a1
Index: string.c
===================================================================
RCS file: /home/perlcvs/parrot/string.c,v
retrieving revision 1.7
diff -u -r1.7 string.c
--- string.c    2001/09/16 01:45:51     1.7
+++ string.c    2001/09/17 08:20:49
@@ -139,6 +139,21 @@
     return (ENC_VTABLE(s)->chopn)(s, n);
 }
 
+/*=for api string string_nprintf
+ * format output into a string.
+ */
+STRING*
+string_nprintf(STRING* dest, IV len, char* format, ...) {
+    va_list ap;
+    if (!dest) {
+        dest = string_make(NULL, 0, enc_native, 0, 0);
+    }
+    va_start(ap, format);
+    dest = (ENC_VTABLE(dest)->nprintf)(dest, len, format, ap);
+    va_end(ap);
+    return dest;
+}
+
 /*
  * Local variables:
  * c-indentation-style: bsd
Index: string.h
===================================================================
RCS file: /home/perlcvs/parrot/string.h,v
retrieving revision 1.6
diff -u -r1.6 string.h
--- string.h    2001/09/16 01:45:51     1.6
+++ string.h    2001/09/17 08:20:49
@@ -32,6 +32,7 @@
 typedef STRING* (*string_iv_to_string_t)(STRING *, IV);
 typedef STRING* (*two_strings_iv_to_string_t)(STRING *, STRING *, IV);
 typedef STRING* (*substr_t)(STRING*, IV, IV, STRING*);
+typedef STRING* (*nprintf_t)(STRING*, IV, char*, va_list);
 typedef IV (*iv_to_iv_t)(IV);
 
 struct string_vtable {
@@ -41,6 +42,7 @@
     two_strings_iv_to_string_t concat;  /* Append string b to the end of string a */
     string_iv_to_string_t chopn;        /* Remove n characters from the end of a 
string */
     substr_t substr;                    /* Substring operation */
+    nprintf_t nprintf;                  /* Formatted output operation */
 };
 
 struct parrot_string {
@@ -67,6 +69,8 @@
 string_chopn(STRING*, IV);
 STRING*
 string_substr(STRING*, IV, IV, STRING**);
+STRING*
+string_nprintf(STRING*, IV, char*, ...);
 
 /* Declarations of other functions */
 IV
Index: strnative.c
===================================================================
RCS file: /home/perlcvs/parrot/strnative.c,v
retrieving revision 1.10
diff -u -r1.10 strnative.c
--- strnative.c 2001/09/16 01:45:51     1.10
+++ strnative.c 2001/09/17 08:20:49
@@ -80,6 +80,36 @@
     return dest;
 }
 
+/*=for api string_native string_native_nprintf
+   format output into a string.
+*/
+static STRING*
+string_native_nprintf(STRING* dest, IV len, char* format, va_list ap) {
+    if (len > 0) {
+        string_grow(dest, len);
+        len = vsnprintf(dest->bufstart, len, format, ap);
+        if (len > dest->buflen) {
+            len = dest->buflen;
+        }
+    }
+    else {
+        while (len == 0 || len > dest->buflen)
+        {
+            if (len < 0) {
+                string_grow(dest, dest->buflen * 2);
+            }
+            else if (len > dest->buflen) {
+                string_grow(dest, len);
+            }
+            len = vsnprintf(dest->bufstart, dest->buflen, format, ap);
+        }
+    }
+    
+    dest->strlen = dest->bufused = len;
+
+    return dest;
+}
+
 /*=for api string_native string_native_vtable
    return the vtable for the native string
 */
@@ -92,6 +122,7 @@
        string_native_concat,
        string_native_chopn,
        string_native_substr,
+        string_native_nprintf
     };
     return sv;
 }
Index: docs/strings.pod
===================================================================
RCS file: /home/perlcvs/parrot/docs/strings.pod,v
retrieving revision 1.3
diff -u -r1.3 strings.pod
--- docs/strings.pod    2001/09/13 08:39:49     1.3
+++ docs/strings.pod    2001/09/17 08:20:49
@@ -89,7 +89,6 @@
 C<*dest> is a null pointer, a new string structure is created with the
 same encoding as C<src>.)
 
-B<Not implemented>: 
 To format output into a string, use
 
     STRING* string_nprintf(STRING* dest, IV len, char* format, ...) 

Reply via email to