Hey guys:
Here is what I have so far of the string_nprintf function. As of now it
only handles C string backslash escape sequences and regular chars
from the format string. My primary concern is whether I am using
BUFFER_immobile_FLAG the correct way to protect myself from GC. I also
dont know if the syntax I am using to convert the format string is
correct (It seems like it should be). adding in the rest is only a matter
of time if this method works {btw, I appologize for not submitting a
complete function but I was concerned that I might be running down the
wrong road and wanted to check }
also I think
encoding_lookup() should accept an argument of "native".
Roman
Index: string.c
===================================================================
RCS file: /cvs/public/parrot/string.c,v
retrieving revision 1.67
diff -u -d -r1.67 string.c
--- string.c 9 Apr 2002 03:51:45 -0000 1.67
+++ string.c 10 Apr 2002 22:19:27 -0000
@@ -801,7 +801,148 @@
NULL, 0, NULL);
}
+/*=for api string_nprintf
+ * print formated output of len
+ * chars/glyphs to dest, allocating
+ * new string if dest is NULL, and
+ * mimicking sprintf if len == 0.
+ */
+
+
+STRING*
+string_nprintf(struct Parrot_Interp *interpreter, STRING* dest, UINTVAL len, const
+char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+
+ if(!dest)
+ dest = string_make(interpreter, NULL, len, NULL, 0, NULL);
+
+ return (string_vnprintf(interpreter, dest, len, format, ap));
+}
+
+/* for previous function */
+STRING*
+string_vnprintf(struct Parrot_Interp *interpreter, STRING* dest, UINTVAL len, const
+char *format, va_list ap)
+{
+ STRING *b_trans;
+ STRING *temp_str;
+ STRING** destp;
+
+ INTVAL grow_total;
+
+ unsigned char sprintf_emu, transcode;
+ char c, *cp;
+
+ transcode = 0;
+ sprintf_emu = (len ? 0 : 1);
+ grow_total = (sprintf_emu ? 0 : len);
+
+ destp = &dest;
+ cp = &c;
+
+ temp_str = string_make(interpreter, NULL, 0, dest->encoding,
+BUFFER_immobile_FLAG, dest->type);
+
+ /* test for native */
+ if(dest->encoding != encoding_lookup("singlebyte"))
+ transcode = 1;
+
+ for (; *format ; ++format) {
+ /* print reg reg chars */
+ if (*format != '\\' && *format != '%') {
+ if (sprintf_emu)
+ ++grow_total;
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, format, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans, transcode);
+ string_destroy(b_trans);
+ }
+ }
+ else if (*(format++) == '\\') {
+ if (sprintf_emu)
+ ++grow_total;
+ if (*format == 'n') {
+ c = '\n';
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, cp, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans,
+ transcode);
+ string_destroy(b_trans);
+ }
+ }
+ else if (*format == '\\') {
+ c = '\\';
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, cp, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans,
+ transcode);
+ string_destroy(b_trans);
+ }
+ }
+ else if (*format == 'r') {
+ c = '\r';
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, cp, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans,
+ transcode);
+ string_destroy(b_trans);
+ }
+ }
+ else if (*format == 'a') {
+ c = '\a';
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, cp, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans,
+ transcode);
+ string_destroy(b_trans);
+ }
+ }
+ else if (*format == 't') {
+ c = '\t';
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, cp, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans,
+ transcode);
+ string_destroy(b_trans);
+ }
+ }
+ else if (*format == '\'') {
+ c = '\'';
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, cp, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans,
+ transcode);
+ string_destroy(b_trans);
+ }
+ }
+ else if (*format == '\"') {
+ c = '\"';
+ if (sprintf_emu || (len-- != 0)) {
+ b_trans = string_make(interpreter, cp, 1, NULL,
+ BUFFER_immobile_FLAG, NULL);
+ (void)string_concat(interpreter, temp_str, b_trans,
+ transcode);
+ string_destroy(b_trans);
+ }
+ }
+ }
+ }
+ string_grow(interpreter, dest, grow_total);
+
+ dest = string_substr(interpreter, temp_str, 0, grow_total, destp);
+
+ return dest;
+}
+
+
/*
* Local variables:
* c-indentation-style: bsd