The attached patch implements a Parrot_sprintf function.  It doesn't do
quite what you think--it just wraps the system sprintf.  However, it
provides I and F sizes and is designed to interact with STRINGs.  For
example:

        FLOATVAL f;
        INTVAL i;
        STRING *str;

        Parrot_sprintf(&str, "Decimal: %Id\nOctal: %Io\nDecimal: %Ff\nExponent:
%Fe", i, i, f, f);

It keeps away from messing up flags--%+3.2Ff will do what it should.
However, it has one big weakness.  Currently, you'll get a buffer
overflow if the resulting string is greater than 1024 characters.

The patch doesn't actually change anything to use Parrot_sprintf; it
just defines the function and the Configure machinery needed to support
it.  It's currently in string.[hc]; I'm not sure if this is the right
place.  I won't be surprised if this isn't high-quality enough to
actually be applied.

--Brent Dax
[EMAIL PROTECTED]
Configure pumpking for Perl 6

"Nothing important happened today."
    --George III of England's diary entry for 4-Jul-1776
--- ..\..\parrot-cvs\parrot\string.c    Thu Dec 20 01:09:02 2001
+++ string.c    Thu Dec 20 21:05:10 2001
@@ -331,6 +331,117 @@
     return cmp;
 }
 
+/* XXX do these really belong here? */
+
+static void
+vsprintf_munge_size(char *patstart, char *patcur, char type);
+
+/*
+=for api string Parrot_sprintf
+
+A thin wrapper around Parrot_vsprintf() which takes varargs instead of a varargs 
+list.  
+See L</Parrot_vsprintf> for more information.
+
+=cut
+*/
+
+
+INTVAL
+Parrot_sprintf(struct Parrot_Interp *interpreter, STRING **targ, char *pat, ...) {
+       va_list list;
+       INTVAL ret;
+       va_start(list, pat);
+
+       ret=Parrot_vsprintf(interpreter, targ, pat, list);
+
+       va_end(list);
+       return ret;
+}
+
+/* 
+=for api string Parrot_vsprintf
+
+A thin wrapper around vsprintf(); it implements %Ix and %Fx, sizes which correspond 
+to 
+INTVAL and FLOATVAL respectively.  It also puts its output in a STRING instead of a 
+char *.
+Note: it has a buffer overflow if the resulting string is over 1024 characters.
+
+Parrot_vsprintf(interpreter, &ptr_to_string, "pattern", va_list)
+
+=cut
+*/
+
+INTVAL
+Parrot_vsprintf(struct Parrot_Interp *interpreter, STRING ** targ, char *pat, va_list 
+list) {
+       BOOL percent=0;
+       char *virttarg;
+       char *pat2;
+       INTVAL retval;
+
+       /* we can't modify strings in the constant table */
+       pat=strcpy(mem_sys_allocate(strlen(pat)+1), pat);
+
+       for(pat2=pat; *pat2; pat2++) {
+
+               if(*pat2=='%') {
+                       percent=!percent;
+               }
+               else if(percent) {
+                       switch(*pat2) {
+                               case 'I':
+                                       vsprintf_munge_size(pat, pat2, 
+PRINTF_INTVAL_PATTERN);
+                                       percent=0;
+                                       break;
+                               case 'O':
+                                       vsprintf_munge_size(pat, pat2, 
+PRINTF_OPCODE_T_PATTERN);
+                                       percent=0;
+                                       break;
+                               case 'F':
+                                       vsprintf_munge_size(pat, pat2, 
+PRINTF_FLOATVAL_PATTERN);
+                                       percent=0;
+                                       break;
+                               default:
+                                       /* if this was a letter, we should assume we 
+don't have to munge this pattern */
+                                       if((*pat2 >= 'a' && *pat2 <= 'z') || (*pat2 >= 
+'A' && *pat2 <= 'Z')) {
+                                               percent=0;
+                                       }
+                       }
+               }
+       }
+
+       virttarg=mem_sys_allocate(1024);        /* XXX dangerous! */
+
+       retval=(INTVAL)vsprintf(virttarg, pat, list);
+       *targ=string_make(interpreter, virttarg, strlen(virttarg), 0, 0, 0);
+
+       mem_sys_free(virttarg);
+       mem_sys_free(pat);
+
+       return retval;
+}
+
+
+/* these aren't the droids you're looking for--move along! */
+static void
+vsprintf_munge_size(char *patstart, char *patcur, char type) {
+       *patcur=type;
+
+       if(type==0) {
+               strcat(patstart, patcur+1);     
+               /* do I get the "most interesting mis-use of a standard library 
+function" award for this? */
+
+               /* Okay, that deserves some explanation.  Let's say we're handling 
+%Io.       *
+                * If INTVAL==long, we'll want to transmogrify that into %lo, so       
+       *
+                * PRINTF_INTVAL_PATTERN is set to 'l'.  However, if INTVAL==int, we   
+       *
+                * don't want anything there.  When we don't want anything, we set     
+       *
+                * PRINTF_INTVAL_PATTERN to null.  That means we get the pattern       
+       *
+                * %\0o.  Obviously, that has the problem of horribly confusing 
+vsprintf.     *
+                * To get rid of that null, we concatenate the front of the pattern    
+       *
+                * with everything after the null.  This gets rid of the null 
+completely.     *
+                * No memory reallocation is necessary because we can only shrink the 
+string. */
+       }
+}
+
+
 /* A number is such that:
   sign           =  '+' | '-'
   digit          =  '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
--- ..\..\parrot-cvs\parrot\include\parrot\string.h     Thu Dec 20 01:09:06 2001
+++ include\parrot\string.h     Thu Dec 20 01:18:38 2001
@@ -64,6 +64,13 @@
 void
 string_init(void);
 
+/* XXX do these really belong here? */
+
+INTVAL
+Parrot_sprintf(struct Parrot_Interp *interpreter, STRING **targ, char *pat, ...);
+INTVAL
+Parrot_vsprintf(struct Parrot_Interp *interpreter, STRING ** targ, char *pat, va_list 
+list);
+
 #endif
 
 /*
--- ..\..\parrot-cvs\parrot\Configure.pl        Thu Dec 20 21:58:20 2001
+++ Configure.pl        Thu Dec 20 20:59:20 2001
@@ -20,7 +20,7 @@
 );
 
 if($opt_version) {
-       print '$Id: Configure.pl,v 1.42 2001/12/20 21:28:45 gregor Exp $' . "\n";
+       print '$Id: Configure.pl,v 1.41 2001/12/20 13:10:01 gregor Exp $' . "\n";
        exit;
 }
 
@@ -70,7 +70,7 @@
 
 $jitarchname              =  $archname;
 $jitarchname              =~ s/-(net|free|open)bsd$/-bsd/i;
-$jitarchname              =  'i386-nojit' unless -e "Parrot/Jit/$jitarchname.pm";
+$jitarchname              =  'i386-nojit' unless -e "Parrot/Jit/$archname.pm";
 
 ($jitcpuarch, $jitosname) =  split('-', $jitarchname);
 
@@ -192,8 +192,8 @@
 
 print <<"END";
 
-Done. Now I'm figuring out what formats to pass to pack() for the
-various Parrot internal types.
+Done. Now I'm figuring out what formats to pass to pack() and 
+sprintf() for the various Parrot internal types.
 END
 
 
@@ -215,6 +215,39 @@
     }
 }
 
+#figure out patterns for Parrot_sprintf
+#NOTE: '\0' is in single quotes on purpose
+for($c{iv}) {
+       $c{intval_pattern}=do {
+               /long long/             && '?'  #XXX what should this be?
+                                               ||
+               /long/                  && 'l'
+                                               ||
+               /int/                   && '\0'
+                       || die "I'm confoosed about what $_ should map to!"
+       };
+}
+
+for($c{opcode_t}) {
+       $c{opcode_t_pattern}=do {
+               /long long/             && '?'  #XXX what should this be?
+                                               ||
+               /long/                  && 'l'
+                                               ||
+               /int/                   && '\0'
+                       || die "I'm confoosed about what $_ should map to!"
+       };
+}
+
+for($c{nv}) {
+       $c{floatval_pattern}=do {
+               /long double/   && '?'  #XXX what should this be?
+                                               ||
+               /double/                && '\0'
+                       || die "I'm confoosed about what $_ should map to!";
+       };
+}
+
 $c{packtype_n} = 'd';
 
 print <<"END";
--- ..\..\parrot-cvs\parrot\config_h.in Wed Oct 24 13:08:38 2001
+++ config_h.in Thu Dec 20 20:59:38 2001
@@ -32,6 +32,9 @@
 #define MASK_STR_CHUNK_LOW_BITS ${strlow}
 #define MASK_PMC_CHUNK_LOW_BITS ${pmclow}
 
+#define PRINTF_INTVAL_PATTERN   '${intval_pattern}'
+#define PRINTF_FLOATVAL_PATTERN '${floatval_pattern}'
+#define PRINTF_OPCODE_T_PATTERN '${opcode_t_pattern}'
 
 ${headers}
 

Reply via email to