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) 1997, 1998, 1999 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: gsargs.c,v 1.9 2004/08/04 23:33:29 stefan Exp $ */
18
/* Command line argument list management */
19
#include "ctype_.h"
20
#include "stdio_.h"
21
#include "string_.h"
22
#include "gsexit.h"
23
#include "gsmemory.h"
24
#include "gsargs.h"
25
#include "gserrors.h"
26
 
27
/* Initialize an arg list. */
28
void
29
arg_init(arg_list * pal, const char **argv, int argc,
30
	 FILE * (*arg_fopen) (const char *fname, void *fopen_data),
31
	 void *fopen_data)
32
{
33
    pal->expand_ats = true;
34
    pal->arg_fopen = arg_fopen;
35
    pal->fopen_data = fopen_data;
36
    pal->argp = argv + 1;
37
    pal->argn = argc - 1;
38
    pal->depth = 0;
39
}
40
 
41
/* Push a string onto an arg list. */
42
int
43
arg_push_memory_string(arg_list * pal, char *str, gs_memory_t * mem)
44
{
45
    arg_source *pas;
46
 
47
    if (pal->depth == arg_depth_max) {
48
	lprintf("Too much nesting of @-files.\n");
49
	return 1;
50
    }
51
    pas = &pal->sources[pal->depth];
52
    pas->is_file = false;
53
    pas->u.s.chars = str;
54
    pas->u.s.memory = mem;
55
    pas->u.s.str = str;
56
    pal->depth++;
57
    return 0;
58
}
59
 
60
/* Clean up an arg list. */
61
void
62
arg_finit(arg_list * pal)
63
{
64
    while (pal->depth) {
65
	arg_source *pas = &pal->sources[--(pal->depth)];
66
 
67
	if (pas->is_file)
68
	    fclose(pas->u.file);
69
	else if (pas->u.s.memory)
70
	    gs_free_object(pas->u.s.memory, pas->u.s.chars, "arg_finit");
71
    }
72
}
73
 
74
/* Get the next arg from a list. */
75
/* Note that these are not copied to the heap. */
76
const char *
77
arg_next(arg_list * pal, int *code)
78
{
79
    arg_source *pas;
80
    FILE *f;
81
    const char *astr = 0;	/* initialized only to pacify gcc */
82
    char *cstr;
83
    const char *result;
84
    int endc;
85
    int c, i;
86
    bool in_quote, eol;
87
 
88
  top:pas = &pal->sources[pal->depth - 1];
89
    if (pal->depth == 0) {
90
	if (pal->argn <= 0)	/* all done */
91
	    return 0;
92
	pal->argn--;
93
	result = *(pal->argp++);
94
	goto at;
95
    }
96
    if (pas->is_file)
97
	f = pas->u.file, endc = EOF;
98
    else
99
	astr = pas->u.s.str, f = NULL, endc = 0;
100
    result = cstr = pal->cstr;
101
#define cfsgetc() (f == NULL ? (*astr ? *astr++ : 0) : fgetc(f))
102
#define is_eol(c) (c == '\r' || c == '\n')
103
    i = 0;
104
    in_quote = false;
105
    eol = true;
106
    c = cfsgetc();
107
    for (i = 0;;) {
108
	if (c == endc) {
109
	    if (in_quote) {
110
		cstr[i] = 0;
111
		errprintf("Unterminated quote in @-file: %s\n", cstr);
112
		*code = gs_error_Fatal;
113
		return NULL;
114
	    }
115
	    if (i == 0) {
116
		/* EOF before any argument characters. */
117
		if (f != NULL)
118
		    fclose(f);
119
		else if (pas->u.s.memory)
120
		    gs_free_object(pas->u.s.memory, pas->u.s.chars,
121
				   "arg_next");
122
		pal->depth--;
123
		goto top;
124
	    }
125
	    break;
126
	}
127
	/* c != endc */
128
	if (isspace(c)) {
129
	    if (i == 0) {
130
		c = cfsgetc();
131
		continue;
132
	    }
133
	    if (!in_quote)
134
		break;
135
	}
136
	/* c isn't leading or terminating whitespace. */
137
	if (c == '#' && eol) {
138
	    /* Skip a comment. */
139
	    do {
140
		c = cfsgetc();
141
	    } while (!(c == endc || is_eol(c)));
142
	    if (c == '\r')
143
		c = cfsgetc();
144
	    if (c == '\n')
145
		c = cfsgetc();
146
	    continue;
147
	}
148
	if (c == '\\') {
149
	    /* Check for \ followed by newline. */
150
	    c = cfsgetc();
151
	    if (is_eol(c)) {
152
		if (c == '\r')
153
		    c = cfsgetc();
154
		if (c == '\n')
155
		    c = cfsgetc();
156
		eol = true;
157
		continue;
158
	    }
159
	    /* \ anywhere else is treated as a printing character. */
160
	    /* This is different from the Unix shells. */
161
	    if (i == arg_str_max - 1) {
162
		cstr[i] = 0;
163
		errprintf("Command too long: %s\n", cstr);
164
		*code = gs_error_Fatal;
165
		return NULL;
166
	    }
167
	    cstr[i++] = '\\';
168
	    eol = false;
169
	    continue;
170
	}
171
	/* c will become part of the argument */
172
	if (i == arg_str_max - 1) {
173
	    cstr[i] = 0;
174
	    errprintf("Command too long: %s\n", cstr);
175
	    *code = gs_error_Fatal;
176
	    return NULL;
177
	}
178
	/* If input is coming from an @-file, allow quotes */
179
	/* to protect whitespace. */
180
	if (c == '"' && f != NULL)
181
	    in_quote = !in_quote;
182
	else
183
	    cstr[i++] = c;
184
	eol = is_eol(c);
185
	c = cfsgetc();
186
    }
187
    cstr[i] = 0;
188
    if (f == NULL)
189
	pas->u.s.str = astr;
190
  at:if (pal->expand_ats && result[0] == '@') {
191
	if (pal->depth == arg_depth_max) {
192
	    lprintf("Too much nesting of @-files.\n");
193
	    *code = gs_error_Fatal;
194
	    return NULL;
195
	}
196
	result++;		/* skip @ */
197
	f = (*pal->arg_fopen) (result, pal->fopen_data);
198
	if (f == NULL) {
199
	    errprintf("Unable to open command line file %s\n", result);
200
	    *code = gs_error_Fatal;
201
	    return NULL;
202
	}
203
	pal->depth++;
204
	pas++;
205
	pas->is_file = true;
206
	pas->u.file = f;
207
	goto top;
208
    }
209
    return result;
210
}
211
 
212
/* Copy an argument string to the heap. */
213
char *
214
arg_copy(const char *str, gs_memory_t * mem)
215
{
216
    char *sstr = (char *)gs_alloc_bytes(mem, strlen(str) + 1, "arg_copy");
217
 
218
    if (sstr == 0) {
219
	lprintf("Out of memory!\n");
220
	return NULL;
221
    }
222
    strcpy(sstr, str);
223
    return sstr;
224
}