xref: /plan9/sys/src/cmd/gs/src/genht.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: genht.c,v 1.5 2005/10/04 06:30:02 ray Exp $ */
187dd7cddfSDavid du Colombier /* Generate C code for compiling halftones into ROM. */
197dd7cddfSDavid du Colombier #include "malloc_.h"
207dd7cddfSDavid du Colombier #include "stdio_.h"
217dd7cddfSDavid du Colombier #include "string_.h"
227dd7cddfSDavid du Colombier #include "gscdefs.h"
237dd7cddfSDavid du Colombier #include "gsmemory.h"
247dd7cddfSDavid du Colombier #include "gxbitmap.h"
257dd7cddfSDavid du Colombier #include "gxhttile.h"
267dd7cddfSDavid du Colombier #include "gxtmap.h"
277dd7cddfSDavid du Colombier #include "gxdht.h"
287dd7cddfSDavid du Colombier #include "gxdhtres.h"
297dd7cddfSDavid du Colombier #include "strimpl.h"
307dd7cddfSDavid du Colombier #include "sstring.h"
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier /*
337dd7cddfSDavid du Colombier  * This program translates PostScript halftone resources into C data
347dd7cddfSDavid du Colombier  * structures that can then be compiled into executables and put in shared,
357dd7cddfSDavid du Colombier  * read-only memory.  The syntax of the resource file is a subset of
367dd7cddfSDavid du Colombier  * PostScript, tightly constrained so that it can be parsed easily.  Blank
377dd7cddfSDavid du Colombier  * lines and PostScript comments are ignored, but otherwise each halftone
387dd7cddfSDavid du Colombier  * in the file (there may be more than one) must follow this format,
397dd7cddfSDavid du Colombier  * where ... indicates arbitrary text:
407dd7cddfSDavid du Colombier     (optionally:)
417dd7cddfSDavid du Colombier 	/halftone_name ...
427dd7cddfSDavid du Colombier 	/HalftoneType 5
437dd7cddfSDavid du Colombier     (zero or more times:)
447dd7cddfSDavid du Colombier 	/halftone_name ...
457dd7cddfSDavid du Colombier 	/HalftoneType 3
467dd7cddfSDavid du Colombier 	/Width xxx
477dd7cddfSDavid du Colombier 	/Height xxx
487dd7cddfSDavid du Colombier 	/Thresholds ...
497dd7cddfSDavid du Colombier 	--hex data terminated by a >--
507dd7cddfSDavid du Colombier 	(zero or more times:)
517dd7cddfSDavid du Colombier 	    /halftone_name 1 index
527dd7cddfSDavid du Colombier     (finally)
537dd7cddfSDavid du Colombier     ... defineresource
547dd7cddfSDavid du Colombier  * Lines that don't follow the above syntax may appear anywhere in the file
557dd7cddfSDavid du Colombier  * except in the middle of the hex data.  Width and Height must precede
567dd7cddfSDavid du Colombier  * Thresholds, but otherwise the 4 parameters may appear in any order.
577dd7cddfSDavid du Colombier  * White space at the beginning or end of a line is ignored, and any
587dd7cddfSDavid du Colombier  * amount of white space may separate the parameter name from its value.
597dd7cddfSDavid du Colombier  *
607dd7cddfSDavid du Colombier  * We envision that this format will eventually be extended to cover
617dd7cddfSDavid du Colombier  * HalftoneType 16 halftones with a single rectangle, allowing 16-bit
627dd7cddfSDavid du Colombier  * threshold values.
637dd7cddfSDavid du Colombier  */
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier /* Read a source file into memory. */
667dd7cddfSDavid du Colombier private char *
read_file(FILE * in,char * cname)677dd7cddfSDavid du Colombier read_file(FILE *in, char *cname)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier     int len, nread;
707dd7cddfSDavid du Colombier     char *cont;
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier     fseek(in, 0L, 2 /*SEEK_END*/);
737dd7cddfSDavid du Colombier     len = ftell(in);
747dd7cddfSDavid du Colombier     cont = malloc(len + 1);
757dd7cddfSDavid du Colombier     if (cont == 0) {
767dd7cddfSDavid du Colombier 	fprintf(stderr, "Can't allocate %d bytes to read %s.\n",
777dd7cddfSDavid du Colombier 		len + 1, cname);
787dd7cddfSDavid du Colombier 	return 0;
797dd7cddfSDavid du Colombier     }
807dd7cddfSDavid du Colombier     rewind(in);
817dd7cddfSDavid du Colombier     nread = fread(cont, 1, len, in);
827dd7cddfSDavid du Colombier     cont[nread] = 0;
837dd7cddfSDavid du Colombier     return cont;
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier /* Parse a Halftone resource file into memory. */
877dd7cddfSDavid du Colombier private bool
parse_line(char ** pstr,char ** pline)887dd7cddfSDavid du Colombier parse_line(char **pstr, char **pline)
897dd7cddfSDavid du Colombier {
907dd7cddfSDavid du Colombier     char *str = *pstr;
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier top:
937dd7cddfSDavid du Colombier     while (*str && strchr(" \t\r\n", *str)) /* trim leading space */
947dd7cddfSDavid du Colombier 	++str;
957dd7cddfSDavid du Colombier     if (*str == 0) {
967dd7cddfSDavid du Colombier 	*pline = 0;
977dd7cddfSDavid du Colombier 	return false;
987dd7cddfSDavid du Colombier     }
997dd7cddfSDavid du Colombier     *pline = str;
1007dd7cddfSDavid du Colombier     while (*str && !strchr("\r\n", *str)) /* find EOL */
1017dd7cddfSDavid du Colombier 	++str;
1027dd7cddfSDavid du Colombier     while (str > *pline && strchr(" \t", str[-1])) /* trim trailing space */
1037dd7cddfSDavid du Colombier 	--str;
1047dd7cddfSDavid du Colombier     *str = 0;
1057dd7cddfSDavid du Colombier     *pstr = str + 1;
1067dd7cddfSDavid du Colombier     return true;
1077dd7cddfSDavid du Colombier }
108*593dc095SDavid du Colombier private int
parse_halftone(gx_device_halftone_resource_t * phtr,byte ** pThresholds,char ** pprefix,char ** pcont)1097dd7cddfSDavid du Colombier parse_halftone(gx_device_halftone_resource_t *phtr, byte **pThresholds,
1107dd7cddfSDavid du Colombier 	       char **pprefix, char **pcont)
1117dd7cddfSDavid du Colombier {
1127dd7cddfSDavid du Colombier     char *str;
1137dd7cddfSDavid du Colombier     char *line;
1147dd7cddfSDavid du Colombier     char *rname = 0;
1157dd7cddfSDavid du Colombier     int HalftoneType = -1;
1167dd7cddfSDavid du Colombier     int Width = -1, Height = -1;
1177dd7cddfSDavid du Colombier     byte *Thresholds = 0;
1187dd7cddfSDavid du Colombier     stream_AXD_state ss;
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier     /* Parse the file. */
1217dd7cddfSDavid du Colombier     for (str = *pcont; parse_line(&str, &line);) {
1227dd7cddfSDavid du Colombier 	char *end;
1237dd7cddfSDavid du Colombier 	char *prefix;
1247dd7cddfSDavid du Colombier 	char terminator;
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier 	if (line[0] == '%')
1277dd7cddfSDavid du Colombier 	    continue;
1287dd7cddfSDavid du Colombier 	if (strlen(line) >= 14 &&
1297dd7cddfSDavid du Colombier 	    !strcmp(line + strlen(line) - 14, "defineresource")
1307dd7cddfSDavid du Colombier 	    )
1317dd7cddfSDavid du Colombier 	    break;
1327dd7cddfSDavid du Colombier 	if (line[0] != '/')
1337dd7cddfSDavid du Colombier 	    continue;
1347dd7cddfSDavid du Colombier 	if (strlen(line) >= 8 &&
1357dd7cddfSDavid du Colombier 	    !strcmp(line + strlen(line) - 8, " 1 index")
1367dd7cddfSDavid du Colombier 	    )
1377dd7cddfSDavid du Colombier 	    continue;
1387dd7cddfSDavid du Colombier 	end = ++line;
1397dd7cddfSDavid du Colombier 	while (*end && !strchr(" \t<", *end)) /* find end of name */
1407dd7cddfSDavid du Colombier 	    ++end;
1417dd7cddfSDavid du Colombier 	terminator = *end;
1427dd7cddfSDavid du Colombier 	*end = 0;
1437dd7cddfSDavid du Colombier 	if (rname == 0) { /* first name is halftone name */
1447dd7cddfSDavid du Colombier 	    rname = malloc(strlen(line) + 1);
1457dd7cddfSDavid du Colombier 	    strcpy(rname, line);
1467dd7cddfSDavid du Colombier 	    continue;
1477dd7cddfSDavid du Colombier 	}
1487dd7cddfSDavid du Colombier 	if (terminator == 0)		/* name alone */
1497dd7cddfSDavid du Colombier 	    continue;
1507dd7cddfSDavid du Colombier 	++end;
1517dd7cddfSDavid du Colombier 	if (!strcmp(line, "HalftoneType")) {
1527dd7cddfSDavid du Colombier 	    if (sscanf(end, "%d", &HalftoneType) != 1) {
1537dd7cddfSDavid du Colombier 		fprintf(stderr, "Invalid HalftoneType syntax: %s\n", line - 1);
1547dd7cddfSDavid du Colombier 		return -1;
1557dd7cddfSDavid du Colombier 	    }
1567dd7cddfSDavid du Colombier 	    switch (HalftoneType) {
1577dd7cddfSDavid du Colombier 	    case 3:
1587dd7cddfSDavid du Colombier 		break;
1597dd7cddfSDavid du Colombier 	    case 5:
1607dd7cddfSDavid du Colombier 		if (*pprefix)
1617dd7cddfSDavid du Colombier 		    free(*pprefix);
1627dd7cddfSDavid du Colombier 		*pprefix = rname;
1637dd7cddfSDavid du Colombier 		rname = 0;
1647dd7cddfSDavid du Colombier 		break;
1657dd7cddfSDavid du Colombier 	    default:
1667dd7cddfSDavid du Colombier 		fprintf(stderr, "Invalid HalftoneType: %s\n", end);
1677dd7cddfSDavid du Colombier 		return -1;
1687dd7cddfSDavid du Colombier 	    }
1697dd7cddfSDavid du Colombier 	    continue;
1707dd7cddfSDavid du Colombier 	} else if (!strcmp(line, "Width")) {
1717dd7cddfSDavid du Colombier 	    if (sscanf(end, "%d", &Width) != 1 ||
1727dd7cddfSDavid du Colombier 		Width <= 0 || Width > 0x4000
1737dd7cddfSDavid du Colombier 		) {
1747dd7cddfSDavid du Colombier 		fprintf(stderr, "Invalid Width: %s\n", end);
1757dd7cddfSDavid du Colombier 		return -1;
1767dd7cddfSDavid du Colombier 	    }
1777dd7cddfSDavid du Colombier 	} else if (!strcmp(line, "Height")) {
1787dd7cddfSDavid du Colombier 	    if (sscanf(end, "%d", &Height) != 1 ||
1797dd7cddfSDavid du Colombier 		Height <= 0 || Height > 0x4000
1807dd7cddfSDavid du Colombier 		) {
1817dd7cddfSDavid du Colombier 		fprintf(stderr, "Invalid Height: %s\n", end);
1827dd7cddfSDavid du Colombier 		return -1;
1837dd7cddfSDavid du Colombier 	    }
1847dd7cddfSDavid du Colombier 	} else if (!strcmp(line, "Thresholds")) {
1857dd7cddfSDavid du Colombier 	    uint ignore;
1867dd7cddfSDavid du Colombier 	    uint num_levels = 256;
1877dd7cddfSDavid du Colombier 	    uint num_bits = Width * Height;
1887dd7cddfSDavid du Colombier 	    char *eol = end + strlen(end); /* skip rest of line */
1897dd7cddfSDavid du Colombier 	    stream_cursor_read r;
1907dd7cddfSDavid du Colombier 	    stream_cursor_write w;
1917dd7cddfSDavid du Colombier 
1927dd7cddfSDavid du Colombier 	    if (Width < 0 || Height < 0) {
1937dd7cddfSDavid du Colombier 		fprintf(stderr, "Width and Height must precede Thresholds.\n");
1947dd7cddfSDavid du Colombier 		return -1;
1957dd7cddfSDavid du Colombier 	    }
1967dd7cddfSDavid du Colombier 	    phtr->num_levels = num_levels;
1977dd7cddfSDavid du Colombier 	    phtr->levels =
1987dd7cddfSDavid du Colombier 		malloc(num_levels * sizeof(*phtr->levels));
1997dd7cddfSDavid du Colombier 	    phtr->bit_data =
2007dd7cddfSDavid du Colombier 		malloc(num_bits * sizeof(ushort));
2017dd7cddfSDavid du Colombier 	    Thresholds = malloc(num_bits);
2027dd7cddfSDavid du Colombier 	    s_AXD_init_inline(&ss);
2037dd7cddfSDavid du Colombier 	    r.ptr = (const byte *)eol;
2047dd7cddfSDavid du Colombier 	    r.limit = (const byte *)eol + strlen(eol + 1);
2057dd7cddfSDavid du Colombier 	    w.ptr = Thresholds - 1;
2067dd7cddfSDavid du Colombier 	    w.limit = w.ptr + num_bits;
2077dd7cddfSDavid du Colombier 	    s_AXD_template.process((stream_state *)&ss, &r, &w, true);
2087dd7cddfSDavid du Colombier 	    str = (char *)r.ptr + 1;
2097dd7cddfSDavid du Colombier 	    break;
2107dd7cddfSDavid du Colombier 	}
2117dd7cddfSDavid du Colombier     }
2127dd7cddfSDavid du Colombier 
2137dd7cddfSDavid du Colombier     /* Check for successful parsing. */
2147dd7cddfSDavid du Colombier     if (rname == 0)
2157dd7cddfSDavid du Colombier 	return 1;		/* end of definitions */
2167dd7cddfSDavid du Colombier     if (HalftoneType < 0)
2177dd7cddfSDavid du Colombier 	fprintf(stderr, "HalftoneType not found.\n");
2187dd7cddfSDavid du Colombier     if (Width < 0)
2197dd7cddfSDavid du Colombier 	fprintf(stderr, "Width not found.\n");
2207dd7cddfSDavid du Colombier     if (Height < 0)
2217dd7cddfSDavid du Colombier 	fprintf(stderr, "Height not found.\n");
2227dd7cddfSDavid du Colombier     if (Thresholds == 0)
2237dd7cddfSDavid du Colombier 	fprintf(stderr, "Thresholds not found.\n");
2247dd7cddfSDavid du Colombier     if (rname == 0 || Thresholds == 0)
2257dd7cddfSDavid du Colombier 	return -1;
2267dd7cddfSDavid du Colombier     phtr->rname = rname;
2277dd7cddfSDavid du Colombier     phtr->HalftoneType = HalftoneType;
2287dd7cddfSDavid du Colombier     phtr->Width = Width;
2297dd7cddfSDavid du Colombier     phtr->Height = Height;
2307dd7cddfSDavid du Colombier     *pThresholds = Thresholds;
2317dd7cddfSDavid du Colombier     *pcont = str;
2327dd7cddfSDavid du Colombier     return 0;
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier /* Write a halftone as a C procedure. */
236*593dc095SDavid du Colombier private int
write_halftone(FILE * out,gx_device_halftone_resource_t * phtr,const char * prefix,int index)2377dd7cddfSDavid du Colombier write_halftone(FILE *out, gx_device_halftone_resource_t *phtr,
2387dd7cddfSDavid du Colombier 	       const char *prefix, int index)
2397dd7cddfSDavid du Colombier {
2407dd7cddfSDavid du Colombier     int num_bits = phtr->Width * phtr->Height;
2417dd7cddfSDavid du Colombier     int i;
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier     /* Write the initial comment. */
2447dd7cddfSDavid du Colombier     fputs("\n/* ", out);
2457dd7cddfSDavid du Colombier     if (prefix)
2467dd7cddfSDavid du Colombier 	fprintf(out, "%s.", prefix);
2477dd7cddfSDavid du Colombier     fprintf(out, "%s */\n", phtr->rname);
2487dd7cddfSDavid du Colombier 
2497dd7cddfSDavid du Colombier     /* Write the levels array. */
2507dd7cddfSDavid du Colombier     fprintf(out, "static const unsigned int levels_%d[] = {", index);
2517dd7cddfSDavid du Colombier     for (i = 0; i < phtr->num_levels; ++i) {
2527dd7cddfSDavid du Colombier 	if (i % 10 == 0)
2537dd7cddfSDavid du Colombier 	    fputs("\n", out);
2547dd7cddfSDavid du Colombier 	fprintf(out, "%5u,", phtr->levels[i]);
2557dd7cddfSDavid du Colombier     }
2567dd7cddfSDavid du Colombier     fputs("\n0};\n", out);
2577dd7cddfSDavid du Colombier 
2587dd7cddfSDavid du Colombier     /* Write the bit_data array. */
2597dd7cddfSDavid du Colombier     fprintf(out, "static const unsigned short bit_data_%d[] = {", index);
2607dd7cddfSDavid du Colombier     for (i = 0; i < num_bits; ++i) {
2617dd7cddfSDavid du Colombier 	if (i % 10 == 0)
2627dd7cddfSDavid du Colombier 	    fputs("\n", out);
2637dd7cddfSDavid du Colombier 	fprintf(out, "%5u,", ((const ushort *)phtr->bit_data)[i]);
2647dd7cddfSDavid du Colombier     }
2657dd7cddfSDavid du Colombier     fputs("\n0};\n", out);
2667dd7cddfSDavid du Colombier 
2677dd7cddfSDavid du Colombier     /* Write the top-level structure. */
2687dd7cddfSDavid du Colombier     fprintf(out, "static const gx_device_halftone_resource_t res_%d = {\n    \"%s\", %d, %d, %d, %d, levels_%d, bit_data_%d, %u\n};\n",
2697dd7cddfSDavid du Colombier 	    index, phtr->rname, phtr->HalftoneType, phtr->Width, phtr->Height,
2707dd7cddfSDavid du Colombier 	    phtr->num_levels, index, index,
2717dd7cddfSDavid du Colombier 	    ht_order_procs_short.bit_data_elt_size);
272*593dc095SDavid du Colombier 
273*593dc095SDavid du Colombier     return 0;
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier /* Main program */
277*593dc095SDavid du Colombier int
main(int argc,char * argv[])2787dd7cddfSDavid du Colombier main(int argc, char *argv[])
2797dd7cddfSDavid du Colombier {
2807dd7cddfSDavid du Colombier     char *iname;
2817dd7cddfSDavid du Colombier     FILE *in;
2827dd7cddfSDavid du Colombier     char *oname;
2837dd7cddfSDavid du Colombier     FILE *out;
2847dd7cddfSDavid du Colombier     int code;
2857dd7cddfSDavid du Colombier     char *cont;
2867dd7cddfSDavid du Colombier     char *line;
2877dd7cddfSDavid du Colombier     gx_device_halftone_resource_t res;
2887dd7cddfSDavid du Colombier     char *prefix = 0;
2897dd7cddfSDavid du Colombier     byte *Thresholds;
2907dd7cddfSDavid du Colombier     gx_ht_order order;
2917dd7cddfSDavid du Colombier     int index, i;
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier     if (argc != 3) {
2947dd7cddfSDavid du Colombier 	fprintf(stderr, "Usage: genht ht_res.ps ht_data.c\n");
2957dd7cddfSDavid du Colombier 	exit(1);
2967dd7cddfSDavid du Colombier     }
2977dd7cddfSDavid du Colombier     iname = argv[1];
2987dd7cddfSDavid du Colombier     oname = argv[2];
2997dd7cddfSDavid du Colombier     in = fopen(iname, "rb");
3007dd7cddfSDavid du Colombier     if (in == 0) {
3017dd7cddfSDavid du Colombier 	in = fopen(iname, "r");
3027dd7cddfSDavid du Colombier 	if (in == 0) {
3037dd7cddfSDavid du Colombier 	    fprintf(stderr, "Can't read %s.\n", iname);
3047dd7cddfSDavid du Colombier 	    exit(1);
3057dd7cddfSDavid du Colombier 	}
3067dd7cddfSDavid du Colombier     }
3077dd7cddfSDavid du Colombier     cont = read_file(in, iname);
3087dd7cddfSDavid du Colombier     if (cont == 0)
3097dd7cddfSDavid du Colombier 	exit(1);
3107dd7cddfSDavid du Colombier     fclose(in);
3117dd7cddfSDavid du Colombier     out = fopen(oname, "w");
3127dd7cddfSDavid du Colombier     if (out == 0) {
3137dd7cddfSDavid du Colombier 	fprintf(stderr, "Can't open %s for output.\n", oname);
3147dd7cddfSDavid du Colombier 	exit(1);
3157dd7cddfSDavid du Colombier     }
3167dd7cddfSDavid du Colombier     fprintf(out, "/*\n * This file %s was generated from %s by genht.\n * Do not edit this file.\n *\n", oname, iname);
3177dd7cddfSDavid du Colombier     /* Copy initial comments from the input file. */
3187dd7cddfSDavid du Colombier     while (parse_line(&cont, &line) && line[0] == '%')
3197dd7cddfSDavid du Colombier 	if (line[1] != '!')
3207dd7cddfSDavid du Colombier 	    fprintf(out, " * %s\n", line + 1);
3217dd7cddfSDavid du Colombier     cont[-1] = '\n';
3227dd7cddfSDavid du Colombier     cont = line;
3237dd7cddfSDavid du Colombier     fputs(" */\n#include \"gxdhtres.h\"\n", out);
3247dd7cddfSDavid du Colombier     for (index = 0;
3257dd7cddfSDavid du Colombier 	 (code = parse_halftone(&res, &Thresholds, &prefix, &cont)) == 0;
3267dd7cddfSDavid du Colombier 	 ++index) {
3277dd7cddfSDavid du Colombier 	order.width = res.Width;
3287dd7cddfSDavid du Colombier 	order.num_levels = res.num_levels;
3297dd7cddfSDavid du Colombier 	order.levels = (uint *)res.levels;
3307dd7cddfSDavid du Colombier 	order.num_bits = res.Width * res.Height;
3317dd7cddfSDavid du Colombier 	order.bit_data = (void *)res.bit_data;
3327dd7cddfSDavid du Colombier 	ht_order_procs_short.construct_order(&order, Thresholds);
3337dd7cddfSDavid du Colombier 	write_halftone(out, &res, prefix, index);
3347dd7cddfSDavid du Colombier     }
3357dd7cddfSDavid du Colombier     if (prefix == 0)
3367dd7cddfSDavid du Colombier 	prefix = res.rname;
3377dd7cddfSDavid du Colombier     fputs("/* Check the prototype. */\n", out);
3387dd7cddfSDavid du Colombier     fprintf(out, "DEVICE_HALFTONE_RESOURCE_PROC(gs_dht_%s);\n", prefix);
3397dd7cddfSDavid du Colombier     fputs("\nconst gx_device_halftone_resource_t *const *\n", out);
3407dd7cddfSDavid du Colombier     fprintf(out, "gs_dht_%s(void)\n{\n    static const gx_device_halftone_resource_t *const res[] = {\n\t",
3417dd7cddfSDavid du Colombier 	    prefix);
3427dd7cddfSDavid du Colombier     for (i = 0; i < index; ++i)
3437dd7cddfSDavid du Colombier 	fprintf(out, "&res_%d, ", i);
3447dd7cddfSDavid du Colombier     fputs("0\n    };\n    return res;\n}\n", out);
3457dd7cddfSDavid du Colombier     fclose(out);
3467dd7cddfSDavid du Colombier     if (code < 0)
3477dd7cddfSDavid du Colombier 	exit(1);
3487dd7cddfSDavid du Colombier     return 0;
3497dd7cddfSDavid du Colombier }
3507dd7cddfSDavid du Colombier 
3517dd7cddfSDavid du Colombier /* Stubs */
ENUM_PTRS_BEGIN_PROC(gs_no_struct_enum_ptrs)3527dd7cddfSDavid du Colombier ENUM_PTRS_BEGIN_PROC(gs_no_struct_enum_ptrs)
3537dd7cddfSDavid du Colombier {
3547dd7cddfSDavid du Colombier     return 0;
3557dd7cddfSDavid du Colombier     ENUM_PTRS_END_PROC
3567dd7cddfSDavid du Colombier }
RELOC_PTRS_BEGIN(gs_no_struct_reloc_ptrs)3577dd7cddfSDavid du Colombier RELOC_PTRS_BEGIN(gs_no_struct_reloc_ptrs)
3587dd7cddfSDavid du Colombier {
3597dd7cddfSDavid du Colombier }
3607dd7cddfSDavid du Colombier RELOC_PTRS_END
3617dd7cddfSDavid du Colombier public_st_stream_state();
3627dd7cddfSDavid du Colombier void
gx_ht_complete_threshold_order(gx_ht_order * porder)3637dd7cddfSDavid du Colombier gx_ht_complete_threshold_order(gx_ht_order *porder)
3647dd7cddfSDavid du Colombier {
3657dd7cddfSDavid du Colombier }
3667dd7cddfSDavid du Colombier 
3677dd7cddfSDavid du Colombier /*
3687dd7cddfSDavid du Colombier  * In order to avoid a linking step, we #include the required files here
3697dd7cddfSDavid du Colombier  * rather than compiling them separately.
3707dd7cddfSDavid du Colombier  */
3717dd7cddfSDavid du Colombier #include "gxhtbit.c"
3727dd7cddfSDavid du Colombier #include "scantab.c"
3737dd7cddfSDavid du Colombier #include "sstring.c"
3747dd7cddfSDavid du Colombier 
3757dd7cddfSDavid du Colombier const gx_dht_proc gx_device_halftone_list[] = { 0 };
376