Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1994, 2000 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: ztoken.c,v 1.14 2004/08/04 19:36:13 stefan Exp $ */
18
/* Token reading operators */
19
#include "string_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "dstack.h"		/* for dict_find_name */
23
#include "estack.h"
24
#include "gsstruct.h"		/* for iscan.h */
25
#include "stream.h"
26
#include "files.h"
27
#include "store.h"
28
#include "strimpl.h"		/* for sfilter.h */
29
#include "sfilter.h"		/* for iscan.h */
30
#include "idict.h"
31
#include "iname.h"
32
#include "iscan.h"
33
#include "itoken.h"		/* for prototypes */
34
 
35
/* <file> token <obj> -true- */
36
/* <string> token <post> <obj> -true- */
37
/* <string|file> token -false- */
38
private int ztoken_continue(i_ctx_t *);
39
private int token_continue(i_ctx_t *, stream *, scanner_state *, bool);
40
int
41
ztoken(i_ctx_t *i_ctx_p)
42
{
43
    os_ptr op = osp;
44
 
45
    switch (r_type(op)) {
46
	default:
47
	    return_op_typecheck(op);
48
	case t_file: {
49
	    stream *s;
50
	    scanner_state state;
51
 
52
	    check_read_file(s, op);
53
	    check_ostack(1);
54
	    scanner_state_init(&state, false);
55
	    return token_continue(i_ctx_p, s, &state, true);
56
	}
57
	case t_string: {
58
	    ref token;
59
	    int orig_ostack_depth = ref_stack_count(&o_stack);
60
	    int code = scan_string_token(i_ctx_p, op, &token);
61
 
62
	    switch (code) {
63
	    case scan_EOF:	/* no tokens */
64
		make_false(op);
65
		return 0;
66
	    default:
67
		if (code < 0) {
68
		    /* Clear anything that may have been left on the ostack */
69
	    	    if (orig_ostack_depth < ref_stack_count(&o_stack))
70
	    		pop(ref_stack_count(&o_stack)- orig_ostack_depth);
71
		    return code;
72
		}
73
	    }
74
	    push(2);
75
	    op[-1] = token;
76
	    make_true(op);
77
	    return 0;
78
	}
79
    }
80
}
81
/* Continue reading a token after an interrupt or callout. */
82
/* *op is the scanner state; op[-1] is the file. */
83
private int
84
ztoken_continue(i_ctx_t *i_ctx_p)
85
{
86
    os_ptr op = osp;
87
    stream *s;
88
    scanner_state *pstate;
89
 
90
    check_read_file(s, op - 1);
91
    check_stype(*op, st_scanner_state);
92
    pstate = r_ptr(op, scanner_state);
93
    pop(1);
94
    return token_continue(i_ctx_p, s, pstate, false);
95
}
96
/* Common code for token reading. */
97
private int
98
token_continue(i_ctx_t *i_ctx_p, stream * s, scanner_state * pstate,
99
	       bool save)
100
{
101
    os_ptr op = osp;
102
    int code;
103
    ref token;
104
 
105
    /* Note that scan_token may change osp! */
106
    /* Also, we must temporarily remove the file from the o-stack */
107
    /* when calling scan_token, in case we are scanning a procedure. */
108
    ref fref;
109
 
110
    ref_assign(&fref, op);
111
again:
112
    pop(1);
113
    code = scan_token(i_ctx_p, s, &token, pstate);
114
    op = osp;
115
    switch (code) {
116
	default:		/* error */
117
	    if (code > 0)	/* comment, not possible */
118
		code = gs_note_error(e_syntaxerror);
119
	    push(1);
120
	    ref_assign(op, &fref);
121
	    break;
122
	case scan_BOS:
123
	    code = 0;
124
	case 0:		/* read a token */
125
	    push(2);
126
	    ref_assign(op - 1, &token);
127
	    make_true(op);
128
	    break;
129
	case scan_EOF:		/* no tokens */
130
	    push(1);
131
	    make_false(op);
132
	    code = 0;
133
	    break;
134
	case scan_Refill:	/* need more data */
135
	    push(1);
136
	    ref_assign(op, &fref);
137
	    code = scan_handle_refill(i_ctx_p, op, pstate, save, false,
138
				      ztoken_continue);
139
	    switch (code) {
140
		case 0:	/* state is not copied to the heap */
141
		    goto again;
142
		case o_push_estack:
143
		    return code;
144
	    }
145
	    break;		/* error */
146
    }
147
    if (code <= 0 && !save) {	/* Deallocate the scanner state record. */
148
	ifree_object(pstate, "token_continue");
149
    }
150
    return code;
151
}
152
 
153
/* <file> .tokenexec - */
154
/* Read a token and do what the interpreter would do with it. */
155
/* This is different from token + exec because literal procedures */
156
/* are not executed (although binary object sequences ARE executed). */
157
int ztokenexec_continue(i_ctx_t *);	/* export for interpreter */
158
private int tokenexec_continue(i_ctx_t *, stream *, scanner_state *, bool);
159
int
160
ztokenexec(i_ctx_t *i_ctx_p)
161
{
162
    os_ptr op = osp;
163
    stream *s;
164
    scanner_state state;
165
 
166
    check_read_file(s, op);
167
    check_estack(1);
168
    scanner_state_init(&state, false);
169
    return tokenexec_continue(i_ctx_p, s, &state, true);
170
}
171
/* Continue reading a token for execution after an interrupt or callout. */
172
/* *op is the scanner state; op[-1] is the file. */
173
/* We export this because this is how the interpreter handles a */
174
/* scan_Refill for an executable file. */
175
int
176
ztokenexec_continue(i_ctx_t *i_ctx_p)
177
{
178
    os_ptr op = osp;
179
    stream *s;
180
    scanner_state *pstate;
181
 
182
    check_read_file(s, op - 1);
183
    check_stype(*op, st_scanner_state);
184
    pstate = r_ptr(op, scanner_state);
185
    pop(1);
186
    return tokenexec_continue(i_ctx_p, s, pstate, false);
187
}
188
/* Common code for token reading + execution. */
189
private int
190
tokenexec_continue(i_ctx_t *i_ctx_p, stream * s, scanner_state * pstate,
191
		   bool save)
192
{
193
    os_ptr op = osp;
194
    int code;
195
    /* Note that scan_token may change osp! */
196
    /* Also, we must temporarily remove the file from the o-stack */
197
    /* when calling scan_token, in case we are scanning a procedure. */
198
    ref fref;
199
 
200
    ref_assign(&fref, op);
201
    pop(1);
202
again:
203
    check_estack(1);
204
    code = scan_token(i_ctx_p, s, (ref *) (esp + 1), pstate);
205
    op = osp;
206
    switch (code) {
207
	case 0:
208
	    if (r_is_proc(esp + 1)) {	/* Treat procedure as a literal. */
209
		push(1);
210
		ref_assign(op, esp + 1);
211
		code = 0;
212
		break;
213
	    }
214
	    /* falls through */
215
	case scan_BOS:
216
	    ++esp;
217
	    code = o_push_estack;
218
	    break;
219
	case scan_EOF:		/* no tokens */
220
	    code = 0;
221
	    break;
222
	case scan_Refill:	/* need more data */
223
	    code = scan_handle_refill(i_ctx_p, &fref, pstate, save, true,
224
				      ztokenexec_continue);
225
	    switch (code) {
226
		case 0:	/* state is not copied to the heap */
227
		    goto again;
228
		case o_push_estack:
229
		    return code;
230
	    }
231
	    break;		/* error */
232
	case scan_Comment:
233
	case scan_DSC_Comment:
234
	    return ztoken_handle_comment(i_ctx_p, &fref, pstate, esp + 1, code,
235
					 save, true, ztokenexec_continue);
236
	default:		/* error */
237
	    break;
238
    }
239
    if (code < 0) {		/* Push the operand back on the stack. */
240
	push(1);
241
	ref_assign(op, &fref);
242
    }
243
    if (!save) {		/* Deallocate the scanner state record. */
244
	ifree_object(pstate, "token_continue");
245
    }
246
    return code;
247
}
248
 
249
/*
250
 * Handle a scan_Comment or scan_DSC_Comment return from scan_token
251
 * (scan_code) by calling out to %Process[DSC]Comment.  The continuation
252
 * procedure expects the file and scanner state on the o-stack.
253
 */
254
int
255
ztoken_handle_comment(i_ctx_t *i_ctx_p, const ref *fop, scanner_state *sstate,
256
		      const ref *ptoken, int scan_code,
257
		      bool save, bool push_file, op_proc_t cont)
258
{
259
    const char *proc_name;
260
    scanner_state *pstate;
261
    os_ptr op;
262
    ref *ppcproc;
263
    int code;
264
 
265
    switch (scan_code) {
266
    case scan_Comment:
267
	proc_name = "%ProcessComment";
268
	break;
269
    case scan_DSC_Comment:
270
	proc_name = "%ProcessDSCComment";
271
	break;
272
    default:
273
	return_error(e_Fatal);	/* can't happen */
274
    }
275
    /*
276
     * We can't use check_ostack here, because it returns on overflow.
277
     */
278
    /*check_ostack(2);*/
279
    if (ostop - osp < 2) {
280
	code = ref_stack_extend(&o_stack, 2);
281
	if (code < 0)
282
	    return code;
283
    }
284
    check_estack(4);
285
    code = name_enter_string(imemory, proc_name, esp + 4);
286
    if (code < 0)
287
	return code;
288
    if (save) {
289
	pstate = ialloc_struct(scanner_state, &st_scanner_state,
290
			       "ztoken_handle_comment");
291
	if (pstate == 0)
292
	    return_error(e_VMerror);
293
	*pstate = *sstate;
294
    } else
295
	pstate = sstate;
296
    /* Save the token now -- it might be on the e-stack. */
297
    if (!pstate->s_pstack)
298
	osp[2] = *ptoken;
299
    /*
300
     * Push the continuation, scanner state, file, and callout procedure
301
     * on the e-stack.
302
     */
303
    make_op_estack(esp + 1, cont);
304
    make_istruct(esp + 2, 0, pstate);
305
    esp[3] = *fop;
306
    r_clear_attrs(esp + 3, a_executable);
307
    ppcproc = dict_find_name(esp + 4);
308
    if (ppcproc == 0) {
309
	/*
310
	 * This can only happen during initialization.
311
	 * Pop the comment string from the o-stack if needed (see below).
312
	 */
313
	if (pstate->s_pstack)
314
	    --osp;
315
	esp += 3;		/* do run the continuation */
316
    } else {
317
	/*
318
	 * Push the file and comment string on the o-stack.
319
	 * If we were inside { }, the comment string is already on the stack.
320
	 */
321
	if (pstate->s_pstack) {
322
	    op = ++osp;
323
	    *op = op[-1];
324
	} else {
325
	    op = osp += 2;
326
	    /* *op = *ptoken; */	/* saved above */
327
	}
328
	op[-1] = *fop;
329
	esp[4] = *ppcproc;
330
	esp += 4;
331
    }
332
    return o_push_estack;
333
}
334
 
335
/*
336
 * Update the cached scanner_options in the context state after doing a
337
 * setuserparams.  (We might move this procedure somewhere else eventually.)
338
 */
339
int
340
ztoken_scanner_options(const ref *upref, int old_options)
341
{
342
    typedef struct named_scanner_option_s {
343
	const char *pname;
344
	int option;
345
    } named_scanner_option_t;
346
    static const named_scanner_option_t named_options[4] = {
347
	{"ProcessComment", SCAN_PROCESS_COMMENTS},
348
	{"ProcessDSCComment", SCAN_PROCESS_DSC_COMMENTS},
349
	{"PDFScanRules", SCAN_PDF_RULES},
350
	{"PDFScanInvNum", SCAN_PDF_INV_NUM}
351
    };
352
    int options = old_options;
353
    int i;
354
 
355
    for (i = 0; i < countof(named_options); ++i) {
356
	const named_scanner_option_t *pnso = &named_options[i];
357
	ref *ppcproc;
358
	int code = dict_find_string(upref, pnso->pname, &ppcproc);
359
 
360
	/* Update the options only if the parameter has changed. */
361
	if (code >= 0) {
362
	    if (r_has_type(ppcproc, t_null))
363
		options &= ~pnso->option;
364
	    else
365
		options |= pnso->option;
366
	}
367
    }
368
    return options;
369
}
370
 
371
/* ------ Initialization procedure ------ */
372
 
373
const op_def ztoken_op_defs[] =
374
{
375
    {"1token", ztoken},
376
    {"1.tokenexec", ztokenexec},
377
		/* Internal operators */
378
    {"2%ztokenexec_continue", ztokenexec_continue},
379
    op_def_end(0)
380
};