Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1998 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gendev.c,v 1.7 2004/12/08 21:35:13 stefan Exp $ */
18
/* Generate .dev configuration files */
19
#include "stdpre.h"
20
#include <assert.h>
21
#include <ctype.h>
22
#include <stdio.h>
23
#include <stdlib.h>		/* for calloc */
24
#include <string.h>
25
 
26
/*
27
 * This program generates .dev configuration files.
28
 *
29
 * Usage:
30
 *      gendev [-Z] [-n [<name_prefix> | -]] [-C [<dir> | -]]
31
 *        (-d <devfile> | -m <modfile> | -a <modfile>)
32
 *        (-<category> | <item>)*
33
 *
34
 * The name_prefix is for device[2], font, init, and iodev resources.
35
 * ****** DOESN'T HANDLE -replace YET ******
36
 * ****** DOESN'T MERGE device AND device2 ******
37
 */
38
 
39
#define DEFAULT_NAME_PREFIX "gs_"
40
#define INITIAL_CATEGORY "obj"
41
 
42
typedef struct config_s {
43
    /* Set once */
44
    FILE *out;
45
    bool debug;
46
    const char *name_prefix;
47
    const char *file_prefix;
48
    ulong file_id;		/* for uniq_last detection */
49
    /* Updated dynamically */
50
#define ITEM_ID_BITS 5
51
    uint item_id;
52
    bool any_scan_items;
53
    bool in_res_scan;
54
    bool in_category;		/* in_category implies in_res_scan */
55
    const char *current_category;
56
} config;
57
static const config init_config =
58
{
59
    0,				/* out */
60
    0,				/* debug */
61
    DEFAULT_NAME_PREFIX,	/* name_prefix */
62
    "",				/* file_prefix */
63
    0,				/* file_id */
64
    0,				/* item_id */
65
    0,				/* any_scan_items */
66
    0,				/* in_res_scan */
67
    0,				/* in_category */
68
    ""				/* current_category */
69
};
70
 
71
static const char *indent_INCLUDED = "\t\t\t\t";
72
static const char *indent_RES_SCAN = "   ";
73
static const char *indent_category = "\t";
74
static const char *indent_SEEN = "\t    ";
75
static const char *indent_include = "   ";
76
static const char *indent_scan_item = "\t";
77
static const char *indent_item = "";
78
 
79
/* Forward definitions */
80
void add_entry(config *, const char *, const char *, bool);
81
 
82
main(int argc, char *argv[])
83
{
84
    config conf;
85
    int i, j;
86
    bool dev, append;
87
    const char *category = INITIAL_CATEGORY;
88
    const char *fnarg;
89
    FILE *out;
90
    long pos;
91
 
92
    conf = init_config;
93
    /* Process command line arguments. */
94
    for (i = 1; i < argc; i++) {
95
	const char *arg = argv[i];
96
 
97
	if (*arg != '-') {
98
	    fprintf(stderr, "-d|m|a must precede non-switches.\n", arg);
99
	    exit(1);
100
	}
101
	switch (arg[1]) {
102
	    case 'C':		/* change directory, by analogy with make */
103
		conf.file_prefix =
104
		    (argv[i + 1][0] == '-' ? "" : argv[i + 1]);
105
		++i;
106
		continue;
107
	    case 'n':
108
		conf.name_prefix =
109
		    (argv[i + 1][0] == '-' ? "" : argv[i + 1]);
110
		++i;
111
		continue;
112
	    case 'a':
113
		dev = false, append = true;
114
		break;
115
	    case 'd':
116
		dev = true, append = false;
117
		break;
118
	    case 'm':
119
		dev = false, append = false;
120
		break;
121
	    case 'Z':
122
		conf.debug = true;
123
		continue;
124
	    default:
125
		fprintf(stderr, "Unknown switch %s.\n", argv[i]);
126
		exit(1);
127
	}
128
	break;
129
    }
130
    if (i == argc - 1) {
131
	fprintf(stderr, "No output file name given, last argument is %s.\n",
132
		argv[i]);
133
	exit(1);
134
    }
135
    /* Must be the output file. */
136
    fnarg = argv[++i];
137
    {
138
	char fname[100];
139
 
140
	strcpy(fname, fnarg);
141
	strcat(fname, ".dev");
142
	out = fopen(fname, (append ? "a" : "w"));
143
	if (out == 0) {
144
	    fprintf(stderr, "Can't open %s for output.\n", fname);
145
	    exit(1);
146
	}
147
	if (!append)
148
	    fprintf(out,
149
		    "/*\n * File %s created automatically by gendev.\n */\n",
150
		    fname);
151
    }
152
    conf.out = out;
153
    pos = ftell(out);
154
    /* We need a separate _INCLUDED flag for each batch of definitions. */
155
    fprintf(out, "\n#%sifndef %s_%ld_INCLUDED\n",
156
	    indent_INCLUDED, fnarg, pos);
157
    fprintf(out, "#%s  define %s_%ld_INCLUDED\n",
158
	    indent_INCLUDED, fnarg, pos);
159
    /* Create a "unique" hash for the output file. */
160
    for (j = 0; fnarg[j] != 0; ++j)
161
	conf.file_id = conf.file_id * 41 + fnarg[j];
162
    conf.item_id <<= ITEM_ID_BITS;
163
    /* Add the real entries. */
164
    if (dev)
165
	add_entry(&conf, "dev", fnarg, false);
166
    for (j = i + 1; j < argc; ++j) {
167
	const char *arg = argv[j];
168
 
169
	if (arg[0] == '-')
170
	    category = arg + 1;
171
	else
172
	    add_entry(&conf, category, arg, false);
173
    }
174
    if (conf.in_category)
175
	fprintf(out, "#%sendif /* -%s */\n",
176
		indent_category, conf.current_category);
177
    /* Add the scanning entries, if any. */
178
    if (conf.any_scan_items) {
179
	if (conf.in_res_scan)
180
	    fprintf(out, "#%selse /* RES_SCAN */\n", indent_RES_SCAN);
181
	else
182
	    fprintf(out, "#%sifdef RES_SCAN\n", indent_RES_SCAN);
183
	conf.in_res_scan = true;
184
	category = INITIAL_CATEGORY;
185
	conf.item_id = 0;
186
	for (j = i + 1; j < argc; ++j) {
187
	    const char *arg = argv[j];
188
 
189
	    if (arg[0] == '-')
190
		category = arg + 1;
191
	    else
192
		add_entry(&conf, category, arg, true);
193
	}
194
    }
195
    if (conf.in_res_scan)
196
	fprintf(out, "#%sendif /* RES_SCAN */\n", indent_RES_SCAN);
197
    fprintf(out, "#%sendif /* !%s_%ld_INCLUDED */\n",
198
	    indent_INCLUDED, fnarg, pos);
199
    fclose(out);
200
    exit(0);
201
}
202
 
203
/* Add an entry to the output. */
204
typedef enum {
205
    uniq_none = 0,
206
    uniq_first,
207
    uniq_last
208
} uniq_mode;
209
void
210
write_item(config * pconf, const char *str, const char *category,
211
	   const char *item, uniq_mode mode)
212
{
213
    FILE *out = pconf->out;
214
    char cati[80];
215
 
216
    if (!pconf->in_res_scan) {
217
	fprintf(out, "#%sifndef RES_SCAN\n", indent_RES_SCAN);
218
	pconf->in_res_scan = true;
219
    }
220
    if (strcmp(pconf->current_category, category)) {
221
	const char *paren = strchr(str, '(');
222
 
223
	if (pconf->in_category)
224
	    fprintf(out, "#%sendif /* -%s */\n",
225
		    indent_category, pconf->current_category);
226
	fprintf(out, "#%sifdef ", indent_category);
227
	fwrite(str, sizeof(char), paren - str, out);
228
 
229
	fprintf(out, "\n");
230
	pconf->current_category = category;
231
	pconf->in_category = true;
232
    }
233
    sprintf(cati, "%s_%s_", category, item);
234
    switch (mode) {
235
	case uniq_none:
236
	    fprintf(out, "%s%s\n", indent_item, str);
237
	    break;
238
	case uniq_first:
239
	    fprintf(out, "#%sifndef %sSEEN\n", indent_SEEN, cati);
240
	    fprintf(out, "#%s  define %sSEEN\n", indent_SEEN, cati);
241
	    write_item(pconf, str, category, item, uniq_none);
242
	    fprintf(out, "#%sendif\n", indent_SEEN, cati);
243
	    break;
244
	case uniq_last:
245
	    fprintf(out, "#%sif %sSEEN == %lu\n", indent_SEEN, cati,
246
		    pconf->file_id + pconf->item_id++);
247
	    write_item(pconf, str, category, item, uniq_none);
248
	    fprintf(out, "#%sendif\n", indent_SEEN, cati);
249
	    pconf->any_scan_items = true;
250
	    break;
251
    }
252
}
253
void
254
write_scan_item(config * pconf, const char *str, const char *category,
255
		const char *item, uniq_mode mode)
256
{
257
    FILE *out = pconf->out;
258
    char cati[80];
259
 
260
    sprintf(cati, "%s_%s_", category, item);
261
    switch (mode) {
262
	case uniq_none:
263
	    break;
264
	case uniq_first:
265
	    break;
266
	case uniq_last:
267
	    fprintf(out, "#%sundef %sSEEN\n", indent_scan_item, cati);
268
	    fprintf(out, "#%s  define %sSEEN %lu\n", indent_scan_item, cati,
269
		    pconf->file_id + pconf->item_id++);
270
    }
271
}
272
void
273
add_entry(config * pconf, const char *category, const char *item, bool scan)
274
{
275
    char str[80];
276
    uniq_mode mode = uniq_first;
277
 
278
    if (pconf->debug && !scan)
279
	printf("Adding %s %s;\n", category, item);
280
    str[0] = 0;
281
    switch (category[0]) {	/* just an accelerator */
282
#define is_cat(str) !strcmp(category, str)
283
	case 'd':
284
	    if (is_cat("dev"))
285
		sprintf(str, "device_(%s%s_device)\n",
286
			pconf->name_prefix, item);
287
	    else if (is_cat("dev2"))
288
		sprintf(str, "device2_(%s%s_device)\n",
289
			pconf->name_prefix, item);
290
	    break;
291
	case 'e':
292
	    if (is_cat("emulator"))
293
		sprintf(str, "emulator_(\"%s\",%d)",
294
			item, strlen(item));
295
	    break;
296
	case 'f':
297
	    if (is_cat("font"))
298
		sprintf(str, "font_(\"0.font_%s\",%sf_%s,zf_%s)",
299
			item, pconf->name_prefix, item, item);
300
	    break;
301
	case 'i':
302
	    if (is_cat("include")) {
303
		int len = strlen(item);
304
 
305
		if (scan)
306
		    return;
307
		if (strcmp(pconf->current_category, category)) {
308
		    if (pconf->in_category) {
309
			fprintf(pconf->out, "#%sendif /* -%s */\n",
310
				indent_category, pconf->current_category);
311
			pconf->in_category = false;
312
		    }
313
		    pconf->current_category = category;
314
		}
315
		if (pconf->in_res_scan) {
316
		    fprintf(pconf->out, "#%sendif /* RES_SCAN */\n",
317
			    indent_RES_SCAN);
318
		    pconf->in_res_scan = false;
319
		}
320
		if (len < 5 || strcmp(item + len - 4, ".dev"))
321
		    fprintf(pconf->out, "#%sinclude \"%s.dev\"\n",
322
			    indent_include, item);
323
		else
324
		    fprintf(pconf->out, "#%sinclude \"%s\"\n",
325
			    indent_include, item);
326
		return;
327
	    } else if (is_cat("init"))
328
		sprintf(str, "init_(%s%s_init)", pconf->name_prefix, item);
329
	    else if (is_cat("iodev"))
330
		sprintf(str, "io_device_(%siodev_%s)", pconf->name_prefix, item);
331
	    break;
332
	case 'l':
333
	    if (is_cat("lib")) {
334
		sprintf(str, "lib_(%s)", item);
335
		mode = uniq_last;
336
	    }
337
	    break;
338
	case 'o':
339
	    if (is_cat("obj"))
340
		sprintf(str, "obj_(%s%s)", pconf->file_prefix, item);
341
	    else if (is_cat("oper"))
342
		sprintf(str, "oper_(%s_op_defs)", item);
343
	    break;
344
	case 'p':
345
	    if (is_cat("ps"))
346
		sprintf(str, "psfile_(\"%s.ps\",%d)",
347
			item, strlen(item) + 3);
348
	    break;
349
#undef is_cat
350
	default:
351
	    ;
352
    }
353
    if (str[0] == 0) {
354
	fprintf(stderr, "Unknown category %s.\n", category);
355
	exit(1);
356
    }
357
    if (scan)
358
	write_scan_item(pconf, str, category, item, mode);
359
    else
360
	write_item(pconf, str, category, item, mode);
361
}