1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gendev.c 8368 2007-11-14 23:03:22Z giles $ */
15
/* Generate .dev configuration files */
19
#include <stdlib.h> /* for calloc */
23
* This program generates .dev configuration files.
26
* gendev [-Z] [-n [<name_prefix> | -]] [-C [<dir> | -]]
27
* (-d <devfile> | -m <modfile> | -a <modfile>)
28
* (-<category> | <item>)*
30
* The name_prefix is for device[2], font, init, and iodev resources.
31
* ****** DOESN'T HANDLE -replace YET ******
32
* ****** DOESN'T MERGE device AND device2 ******
35
#define DEFAULT_NAME_PREFIX "gs_"
36
#define INITIAL_CATEGORY "obj"
38
typedef struct config_s {
42
const char *name_prefix;
43
const char *file_prefix;
44
ulong file_id; /* for uniq_last detection */
45
/* Updated dynamically */
46
#define ITEM_ID_BITS 5
50
bool in_category; /* in_category implies in_res_scan */
51
const char *current_category;
53
static const config init_config =
57
DEFAULT_NAME_PREFIX, /* name_prefix */
61
0, /* any_scan_items */
64
"" /* current_category */
67
static const char *indent_INCLUDED = "\t\t\t\t";
68
static const char *indent_RES_SCAN = " ";
69
static const char *indent_category = "\t";
70
static const char *indent_SEEN = "\t ";
71
static const char *indent_include = " ";
72
static const char *indent_scan_item = "\t";
73
static const char *indent_item = "";
75
/* Forward definitions */
76
void add_entry(config *, const char *, const char *, bool);
78
main(int argc, char *argv[])
83
const char *category = INITIAL_CATEGORY;
89
/* Process command line arguments. */
90
for (i = 1; i < argc; i++) {
91
const char *arg = argv[i];
94
fprintf(stderr, "-d|m|a must precede non-switches.\n", arg);
98
case 'C': /* change directory, by analogy with make */
100
(argv[i + 1][0] == '-' ? "" : argv[i + 1]);
105
(argv[i + 1][0] == '-' ? "" : argv[i + 1]);
109
dev = false, append = true;
112
dev = true, append = false;
115
dev = false, append = false;
121
fprintf(stderr, "Unknown switch %s.\n", argv[i]);
127
fprintf(stderr, "No output file name given, last argument is %s.\n",
131
/* Must be the output file. */
136
strcpy(fname, fnarg);
137
strcat(fname, ".dev");
138
out = fopen(fname, (append ? "a" : "w"));
140
fprintf(stderr, "Can't open %s for output.\n", fname);
145
"/*\n * File %s created automatically by gendev.\n */\n",
150
/* We need a separate _INCLUDED flag for each batch of definitions. */
151
fprintf(out, "\n#%sifndef %s_%ld_INCLUDED\n",
152
indent_INCLUDED, fnarg, pos);
153
fprintf(out, "#%s define %s_%ld_INCLUDED\n",
154
indent_INCLUDED, fnarg, pos);
155
/* Create a "unique" hash for the output file. */
156
for (j = 0; fnarg[j] != 0; ++j)
157
conf.file_id = conf.file_id * 41 + fnarg[j];
158
conf.item_id <<= ITEM_ID_BITS;
159
/* Add the real entries. */
161
add_entry(&conf, "dev", fnarg, false);
162
for (j = i + 1; j < argc; ++j) {
163
const char *arg = argv[j];
168
add_entry(&conf, category, arg, false);
170
if (conf.in_category)
171
fprintf(out, "#%sendif /* -%s */\n",
172
indent_category, conf.current_category);
173
/* Add the scanning entries, if any. */
174
if (conf.any_scan_items) {
175
if (conf.in_res_scan)
176
fprintf(out, "#%selse /* RES_SCAN */\n", indent_RES_SCAN);
178
fprintf(out, "#%sifdef RES_SCAN\n", indent_RES_SCAN);
179
conf.in_res_scan = true;
180
category = INITIAL_CATEGORY;
182
for (j = i + 1; j < argc; ++j) {
183
const char *arg = argv[j];
188
add_entry(&conf, category, arg, true);
191
if (conf.in_res_scan)
192
fprintf(out, "#%sendif /* RES_SCAN */\n", indent_RES_SCAN);
193
fprintf(out, "#%sendif /* !%s_%ld_INCLUDED */\n",
194
indent_INCLUDED, fnarg, pos);
199
/* Add an entry to the output. */
206
write_item(config * pconf, const char *str, const char *category,
207
const char *item, uniq_mode mode)
209
FILE *out = pconf->out;
212
if (!pconf->in_res_scan) {
213
fprintf(out, "#%sifndef RES_SCAN\n", indent_RES_SCAN);
214
pconf->in_res_scan = true;
216
if (strcmp(pconf->current_category, category)) {
217
const char *paren = strchr(str, '(');
219
if (pconf->in_category)
220
fprintf(out, "#%sendif /* -%s */\n",
221
indent_category, pconf->current_category);
222
fprintf(out, "#%sifdef ", indent_category);
223
fwrite(str, sizeof(char), paren - str, out);
226
pconf->current_category = category;
227
pconf->in_category = true;
229
sprintf(cati, "%s_%s_", category, item);
232
fprintf(out, "%s%s\n", indent_item, str);
235
fprintf(out, "#%sifndef %sSEEN\n", indent_SEEN, cati);
236
fprintf(out, "#%s define %sSEEN\n", indent_SEEN, cati);
237
write_item(pconf, str, category, item, uniq_none);
238
fprintf(out, "#%sendif\n", indent_SEEN, cati);
241
fprintf(out, "#%sif %sSEEN == %lu\n", indent_SEEN, cati,
242
pconf->file_id + pconf->item_id++);
243
write_item(pconf, str, category, item, uniq_none);
244
fprintf(out, "#%sendif\n", indent_SEEN, cati);
245
pconf->any_scan_items = true;
250
write_scan_item(config * pconf, const char *str, const char *category,
251
const char *item, uniq_mode mode)
253
FILE *out = pconf->out;
256
sprintf(cati, "%s_%s_", category, item);
263
fprintf(out, "#%sundef %sSEEN\n", indent_scan_item, cati);
264
fprintf(out, "#%s define %sSEEN %lu\n", indent_scan_item, cati,
265
pconf->file_id + pconf->item_id++);
269
add_entry(config * pconf, const char *category, const char *item, bool scan)
272
uniq_mode mode = uniq_first;
274
if (pconf->debug && !scan)
275
printf("Adding %s %s;\n", category, item);
277
switch (category[0]) { /* just an accelerator */
278
#define is_cat(str) !strcmp(category, str)
281
sprintf(str, "device_(%s%s_device)\n",
282
pconf->name_prefix, item);
283
else if (is_cat("dev2"))
284
sprintf(str, "device2_(%s%s_device)\n",
285
pconf->name_prefix, item);
288
if (is_cat("emulator"))
289
sprintf(str, "emulator_(\"%s\",%d)",
294
sprintf(str, "font_(\"0.font_%s\",%sf_%s,zf_%s)",
295
item, pconf->name_prefix, item, item);
298
if (is_cat("include")) {
299
int len = strlen(item);
303
if (strcmp(pconf->current_category, category)) {
304
if (pconf->in_category) {
305
fprintf(pconf->out, "#%sendif /* -%s */\n",
306
indent_category, pconf->current_category);
307
pconf->in_category = false;
309
pconf->current_category = category;
311
if (pconf->in_res_scan) {
312
fprintf(pconf->out, "#%sendif /* RES_SCAN */\n",
314
pconf->in_res_scan = false;
316
if (len < 5 || strcmp(item + len - 4, ".dev"))
317
fprintf(pconf->out, "#%sinclude \"%s.dev\"\n",
318
indent_include, item);
320
fprintf(pconf->out, "#%sinclude \"%s\"\n",
321
indent_include, item);
323
} else if (is_cat("init"))
324
sprintf(str, "init_(%s%s_init)", pconf->name_prefix, item);
325
else if (is_cat("iodev"))
326
sprintf(str, "io_device_(%siodev_%s)", pconf->name_prefix, item);
330
sprintf(str, "lib_(%s)", item);
336
sprintf(str, "obj_(%s%s)", pconf->file_prefix, item);
337
else if (is_cat("oper"))
338
sprintf(str, "oper_(%s_op_defs)", item);
342
sprintf(str, "psfile_(\"%s.ps\",%d)",
343
item, strlen(item) + 3);
350
fprintf(stderr, "Unknown category %s.\n", category);
354
write_scan_item(pconf, str, category, item, mode);
356
write_item(pconf, str, category, item, mode);