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);
}