geninit.c generares code that stresses gcc

Alex Cherepanov <[email protected]>
Newsgroups gmane.comp.printing.ghostscript.patches
Organization Coscript Software
Message-ID <[email protected]>
geninit.c generates an initialization list: {'a', 'b', ... }
which takes about 50x of memory to compile on GCC. The process
is slow and can run out of memory on small systems. Fortunately,
GCC tolerates 5 M of data in a single string.

Advice about better GCC detection and interaction with
autoconf are welcome.
geninit.c.diff (text/plain, 5.4 KB)
Index: gs/src/geninit.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/geninit.c,v
retrieving revision 1.8
diff -b -u -r1.8 geninit.c
--- gs/src/geninit.c	1 Jul 2003 04:37:20 -0000	1.8
+++ gs/src/geninit.c	11 Sep 2003 14:33:35 -0000
@@ -21,6 +21,10 @@
  *    geninit [-(I|i) <prefix>] <init-file.ps> <gconfig.h> <merged-init-file.ps>
  *    geninit [-(I|i) <prefix>] <init-file.ps> <gconfig.h> -c <merged-init-file.c>
  *
+ * GCC runs out of nemory on small systems when 5M string is initialized
+ * with a list initializer {'a', 'b', 'c', ...} but tolerates a single
+ * string. Generate a string initializer when this program is compiled with GCC.
+ *
  * The following special constructs are recognized in the input files:
  *	%% Replace[%| ]<#lines> (<psfile>)
  *	%% Replace[%| ]<#lines> INITFILES
@@ -41,10 +45,13 @@
 #include <string.h>
 #include <memory.h>
 
+/* output mode */
+typedef enum {k_ps=0, k_cc, k_gcc} to_c_t;
+
 /* Forward references */
 private FILE *prefix_open(const char *prefix, const char *inname);
 private void merge_to_c(const char *prefix, const char *inname, FILE * in,
-			FILE * config, FILE * out);
+			FILE * config, FILE * out, to_c_t to_c);
 private void merge_to_ps(const char *prefix, const char *inname, FILE * in,
 			 FILE * config, FILE * out);
 
@@ -62,7 +69,7 @@
     const char *fout;
     FILE *out;
     const char *prefix = "";
-    bool to_c = false;
+    to_c_t to_c = k_ps;
 
     if (arg_c >= 2 && (!strcmp(arg_v[1], "-I") || !strcmp(arg_v[1], "-i"))) {
 	prefix = arg_v[2];
@@ -71,12 +78,18 @@
     }
     if (arg_c == 4)
 	fin = arg_v[1], fconfig = arg_v[2], fout = arg_v[3];
-    else if (arg_c == 5 && !strcmp(arg_v[3], "-c"))
-	fin = arg_v[1], fconfig = arg_v[2], fout = arg_v[4], to_c = true;
-    else {
-	fprintf(stderr, "\
-Usage: geninit [-(I|i) lib/] gs_init.ps gconfig.h gs_xinit.ps\n\
-or     geninit [-(I|i) lib/] gs_init.ps gconfig.h -c gs_init.c\n");
+    else if (arg_c == 5 && !strcmp(arg_v[3], "-c")) {
+	fin = arg_v[1], fconfig = arg_v[2], fout = arg_v[4];
+#       ifdef __GNUC__
+	  to_c = k_gcc;
+#       else
+          to_c = k_cc;
+#       endif	  
+        
+    } else {
+	fprintf(stderr, 
+	  "Usage: geninit [-(I|i) lib/] gs_init.ps gconfig.h gs_xinit.ps\n"
+          "or     geninit [-(I|i) lib/] gs_init.ps gconfig.h -c gs_init.c\n");
 	exit(1);
     }
     in = prefix_open(prefix, fin);
@@ -96,7 +109,7 @@
 	exit(1);
     }
     if (to_c)
-	merge_to_c(prefix, fin, in, config, out);
+	merge_to_c(prefix, fin, in, config, out, to_c);
     else
 	merge_to_ps(prefix, fin, in, config, out);
     fclose(out);
@@ -199,16 +212,46 @@
     if (n != 0)
 	fputc('\n', out);
 }
+/* Write input string as a single C sting. */
 private void
-ws(FILE * out, const byte *str, int len, bool to_c)
+wsg(FILE * out, const byte *str, int len)
 {
-    if (to_c)
-	wsc(out, str, len);
+    int i;
+    while (len > 0) { 
+        int max_sz = len < 80 ? len : 80;
+        for (i=0; i < max_sz; i++) {
+            char c=str[i];
+            if (c == '\\')
+	      fputs("\\\\", out);
+	    else if (c == '"')
+	      fputs("\\\"", out); 
+	    else if( c < 32 || c >= 127)
+              fprintf(out, "\\%03o", c);
     else
+              fputc(c, out);	
+        }
+        fputs("\\\n", out);
+	str += max_sz;
+	len -= max_sz;
+    }	
+}
+
+private void
+ws(FILE * out, const byte *str, int len, to_c_t to_c)
+{
+    switch(to_c) {
+      case k_gcc:
+        wsg(out, str, len);
+	break;
+      case k_cc:
+	wsc(out, str, len);
+	break;
+      default:	
 	fwrite(str, 1, len, out);
+    }	
 }
 private void
-wl(FILE * out, const char *str, bool to_c)
+wl(FILE * out, const char *str, to_c_t to_c)
 {
     ws(out, (const byte *)str, strlen(str), to_c);
     ws(out, (const byte *)"\n", 1, to_c);
@@ -339,7 +382,7 @@
 
 /* Merge a file from input to output. */
 private void
-flush_buf(FILE * out, char *buf, bool to_c)
+flush_buf(FILE * out, char *buf, to_c_t to_c)
 {
     if (buf[0] != 0) {
 	wl(out, buf, to_c);
@@ -348,7 +391,7 @@
 }
 private void
 mergefile(const char *prefix, const char *inname, FILE * in, FILE * config,
-	  FILE * out, bool to_c, bool intact)
+	  FILE * out, to_c_t to_c, bool intact)
 {
     char line[LINE_SIZE + 1];
     char buf[LINE_SIZE + 1];
@@ -449,7 +492,7 @@
 /* Merge and produce a C file. */
 private void
 merge_to_c(const char *prefix, const char *inname, FILE * in, FILE * config,
-	   FILE * out)
+	   FILE * out, to_c_t to_c)
 {
     char line[LINE_SIZE + 1];
 
@@ -460,10 +503,11 @@
     fputs("\n", out);
     fputs("/* Pre-compiled interpreter initialization string. */\n", out);
     fputs("\n", out);
-    fputs("const unsigned char gs_init_string[] = {\n", out);
-    mergefile(prefix, inname, in, config, out, true, false);
-    fputs("10};\n", out);
-    fputs("const unsigned int gs_init_string_sizeof = sizeof(gs_init_string);\n", out);
+    fprintf(out, "const unsigned char gs_init_string[] = {%s\n", (to_c == k_gcc) ? "\"\\" : "");
+    mergefile(prefix, inname, in, config, out, to_c, false);
+    fprintf(out, "%s};\n", (to_c == k_gcc) ? "\"" : "10" );
+    fprintf(out,"const unsigned int gs_init_string_sizeof = sizeof(gs_init_string)%s;\n",
+        (to_c == k_gcc) ? " - 1" : "");
 }
 
 /* Merge and produce a PostScript file. */
@@ -475,5 +519,5 @@
 
     while ((rl(in, line, LINE_SIZE), line[0]))
 	fprintf(out, "%s\n", line);
-    mergefile(prefix, inname, in, config, out, false, false);
+    mergefile(prefix, inname, in, config, out, k_ps, false);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.