Jeroen Demeyer on Thu, 12 Jan 2017 10:55:38 +0100


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[PATCH] New function outString_printf


In order to implement SVG plotting, the outString machinery from src/language/es.c is very useful. It allows writing to a string in a way which is very analogous as writing to a file. Unfortunately, this is currently not exported. This patch makes the minimal changes needed to make the functionality available which is needed for SVG plotting.

Cheers,
Jeroen.
>From a9e68cebbf755eb3b8ccbc0e4042d3de67df238f Mon Sep 17 00:00:00 2001
From: Jeroen Demeyer <jdemeyer@cage.ugent.be>
Date: Thu, 12 Jan 2017 09:51:39 +0100
Subject: [PATCH 1/5] New function outString_printf

---
 src/headers/paripriv.h | 11 ++++++++++
 src/language/es.c      | 56 +++++++++++++++++++++++++++++---------------------
 2 files changed, 44 insertions(+), 23 deletions(-)

diff --git a/src/headers/paripriv.h b/src/headers/paripriv.h
index 71047c1..b0e6eb1 100644
--- a/src/headers/paripriv.h
+++ b/src/headers/paripriv.h
@@ -254,6 +254,17 @@ out_print_text(PariOUT *out, const char *s) { print_prefixed_text(out, s,NULL,NU
 INLINE long
 is_keyword_char(char c) { return (isalnum((int)c) || c=='_'); }
 
+typedef struct outString {
+  char *string; /* start of the output buffer */
+  char *end;    /* end of the output buffer */
+  char *cur;   /* current writing place in the output buffer */
+  size_t size; /* buffer size */
+  int use_stack; /* use stack_malloc instead of malloc ? */
+} outString;
+
+void outString_init(outString *S, int use_stack);
+void outString_printf(outString *S, const char *fmt, ...);
+
 /* Interfaces (GP, etc.) */
 hashtable *hash_from_link(GEN e, GEN names, int use_stack);
 void gen_relink(GEN x, hashtable *table);
diff --git a/src/language/es.c b/src/language/es.c
index 251717e..e413bd2 100644
--- a/src/language/es.c
+++ b/src/language/es.c
@@ -41,14 +41,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
 
 static const char esc = (0x1f & '['); /* C-[ = escape */
 
-typedef struct outString {
-  char *string; /* start of the output buffer */
-  char *end;    /* end of the output buffer */
-  char *cur;   /* current writing place in the output buffer */
-  size_t size; /* buffer size */
-  int use_stack; /* use stack_malloc instead of malloc ? */
-} outString;
-
 typedef void (*OUT_FUN)(GEN, pariout_t *, outString *);
 
 static void bruti_sign(GEN g, pariout_t *T, outString *S, int addsign);
@@ -908,8 +900,8 @@ str_putc(outString *S, char c) {
   if (S->cur == S->end) str_alloc0(S, S->size, S->size << 1);
 }
 
-static void
-str_init(outString *S, int use_stack)
+void
+outString_init(outString *S, int use_stack)
 {
   char *s;
   S->size = 1024;
@@ -918,6 +910,7 @@ str_init(outString *S, int use_stack)
     s = (char*)stack_malloc(S->size);
   else
     s = (char*)pari_malloc(S->size);
+  s[0] = '\0';
   S->string = S->cur = s;
   S->end = S->string + S->size;
 }
@@ -937,7 +930,7 @@ str_putscut(outString *S, const char *str, int cut)
 static char *
 stack_GENtostr_fun(GEN x, pariout_t *T, OUT_FUN out)
 {
-  outString S; str_init(&S, 1);
+  outString S; outString_init(&S, 1);
   out(x, T, &S); *S.cur = 0;
   return S.string;
 }
@@ -951,7 +944,7 @@ static char *
 GENtostr_fun(GEN x, pariout_t *T, OUT_FUN out)
 {
   pari_sp av = avma;
-  outString S; str_init(&S, 0);
+  outString S; outString_init(&S, 0);
   out(x, T, &S); *S.cur = 0;
   avma = av; return S.string;
 }
@@ -1283,12 +1276,16 @@ fmtreal(outString *S, GEN gvalue, int space, int signvalue, int FORMAT,
   outpad(S, buf, strlen(buf), signvalue, ljust, len, zpad);
   avma = av;
 }
+
 /* format handling "inspired" by the standard draft at
 -- http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf pages 274ff
  * fmt is a standard printf format, except 'P' is a "length modifier"
- * allowing GEN arguments. Use either the arg_vector or (if NULL) the va_list */
-static char *
-sm_dopr(const char *fmt, GEN arg_vector, va_list args)
+ * allowing GEN arguments. Use either the arg_vector or (if NULL) the va_list.
+ *
+ * We will append the output to the outString *S, which must be initialized.
+ */
+static void
+outString_arg_vprintf(outString *S, const char *fmt, GEN arg_vector, va_list args)
 {
   int GENflag = 0, longflag = 0, pointflag = 0;
   int print_plus, print_blank, with_sharp, ch, ljust, len, maxwidth, zpad;
@@ -1296,9 +1293,6 @@ sm_dopr(const char *fmt, GEN arg_vector, va_list args)
   int index = 1;
   GEN gvalue;
   const char *save_fmt = fmt;
-  outString __S, *S = &__S;
-
-  str_init(S, 0);
 
   while ((ch = *fmt++) != '\0') {
     switch(ch) {
@@ -1500,8 +1494,16 @@ nextch:
         break;
     } /* first switch on ch */
   } /* while loop on ch */
-  *S->cur = 0;
-  return S->string;
+  *S->cur = '\0';
+}
+
+static char *
+sm_dopr(const char *fmt, GEN arg_vector, va_list args)
+{
+  outString s;
+  outString_init(&s, 0);
+  outString_arg_vprintf(&s, fmt, arg_vector, args);
+  return s.string;
 }
 
 void
@@ -3062,7 +3064,7 @@ matbruti(GEN g, pariout_t *T, outString *S)
     outString scratchstr;
     pad = cgetg(l*r+1, t_VECSMALL); /* left on stack if (S->use_stack)*/
     av2 = avma;
-    str_init(&scratchstr, 1);
+    outString_init(&scratchstr, 1);
     for (j=1; j<r; j++)
     {
       GEN col = gel(g,j);
@@ -4533,7 +4535,7 @@ char *
 pari_sprint0(const char *s, GEN g, long flag)
 {
   outString S;
-  str_init(&S, 0);
+  outString_init(&S, 0);
   str_puts(&S, s);
   str_print0(&S, g, flag);
   return S.string;
@@ -4544,7 +4546,7 @@ print0_file(FILE *out, GEN g, long flag)
 {
   pari_sp av = avma;
   outString S;
-  str_init(&S, 1);
+  outString_init(&S, 1);
   str_print0(&S, g, flag);
   fputs(S.string, out);
   avma = av;
@@ -4660,6 +4662,14 @@ pari_fprintf(FILE *file, const char *fmt, ...)
   pari_vfprintf(file, fmt, ap); va_end(ap);
 }
 
+void
+outString_printf(outString *S, const char *fmt, ...)
+{
+  va_list ap; va_start(ap, fmt);
+  outString_arg_vprintf(S, fmt, NULL, ap);
+  va_end(ap);
+}
+
 void print   (GEN g) { print0(g, f_RAW);       pari_putc('\n'); pari_flush(); }
 void printtex(GEN g) { print0(g, f_TEX);       pari_putc('\n'); pari_flush(); }
 void print1  (GEN g) { print0(g, f_RAW);       pari_flush(); }
-- 
2.7.3