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) 1989, 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: iscan.c,v 1.20 2005/04/25 12:28:49 igor Exp $ */
18
/* Token scanner for Ghostscript interpreter */
19
#include "ghost.h"
20
#include "memory_.h"
21
#include "stream.h"
22
#include "ierrors.h"
23
#include "btoken.h"		/* for ref_binary_object_format */
24
#include "files.h"		/* for fptr */
25
#include "ialloc.h"
26
#include "idict.h"		/* for //name lookup */
27
#include "dstack.h"		/* ditto */
28
#include "ilevel.h"
29
#include "iname.h"
30
#include "ipacked.h"
31
#include "iparray.h"
32
#include "strimpl.h"		/* for string decoding */
33
#include "sa85d.h"		/* ditto */
34
#include "sfilter.h"		/* ditto */
35
#include "ostack.h"		/* for accumulating proc bodies; */
36
					/* must precede iscan.h */
37
#include "iscan.h"		/* defines interface */
38
#include "iscanbin.h"
39
#include "iscannum.h"
40
#include "istream.h"
41
#include "istruct.h"		/* for RELOC_REF_VAR */
42
#include "iutil.h"
43
#include "ivmspace.h"
44
#include "store.h"
45
#include "scanchar.h"
46
 
47
#define recognize_btokens()\
48
  (ref_binary_object_format.value.intval != 0 && level2_enabled)
49
 
50
/* Procedure for handling DSC comments if desired. */
51
/* Set at initialization if a DSC handling module is included. */
52
int (*scan_dsc_proc) (const byte *, uint) = NULL;
53
 
54
/* Procedure for handling all comments if desired. */
55
/* Set at initialization if a comment handling module is included. */
56
/* If both scan_comment_proc and scan_dsc_proc are set, */
57
/* scan_comment_proc is called only for non-DSC comments. */
58
int (*scan_comment_proc) (const byte *, uint) = NULL;
59
 
60
/*
61
 * Level 2 includes some changes in the scanner:
62
 *      - \ is always recognized in strings, regardless of the data source;
63
 *      - << and >> are legal tokens;
64
 *      - <~ introduces an ASCII85 encoded string (terminated by ~>);
65
 *      - Character codes above 127 introduce binary objects.
66
 * We explicitly enable or disable these changes here.
67
 */
68
#define scan_enable_level2 level2_enabled	/* from ilevel.h */
69
 
70
/* ------ Dynamic strings ------ */
71
 
72
/* Begin collecting a dynamically allocated string. */
73
inline private void
74
dynamic_init(da_ptr pda, gs_memory_t *mem)
75
{
76
    pda->is_dynamic = false;
77
    pda->limit = pda->buf + da_buf_size;
78
    pda->next = pda->base = pda->buf;
79
    pda->memory = mem;
80
}
81
 
82
/* Free a dynamic string. */
83
private void
84
dynamic_free(da_ptr pda)
85
{
86
    if (pda->is_dynamic)
87
	gs_free_string(pda->memory, pda->base, da_size(pda), "scanner");
88
}
89
 
90
/* Resize a dynamic string. */
91
/* If the allocation fails, return e_VMerror; otherwise, return 0. */
92
private int
93
dynamic_resize(da_ptr pda, uint new_size)
94
{
95
    uint old_size = da_size(pda);
96
    uint pos = pda->next - pda->base;
97
    gs_memory_t *mem = pda->memory;
98
    byte *base;
99
 
100
    if (pda->is_dynamic) {
101
	base = gs_resize_string(mem, pda->base, old_size,
102
				new_size, "scanner");
103
	if (base == 0)
104
	    return_error(e_VMerror);
105
    } else {			/* switching from static to dynamic */
106
	base = gs_alloc_string(mem, new_size, "scanner");
107
	if (base == 0)
108
	    return_error(e_VMerror);
109
	memcpy(base, pda->base, min(old_size, new_size));
110
	pda->is_dynamic = true;
111
    }
112
    pda->base = base;
113
    pda->next = base + pos;
114
    pda->limit = base + new_size;
115
    return 0;
116
}
117
 
118
/* Grow a dynamic string. */
119
/* Return 0 if the allocation failed, the new 'next' ptr if OK. */
120
/* Return 0 or an error code, updating pda->next to point to the first */
121
/* available byte after growing. */
122
private int
123
dynamic_grow(da_ptr pda, byte * next, uint max_size)
124
{
125
    uint old_size = da_size(pda);
126
    uint new_size = (old_size < 10 ? 20 :
127
		     old_size >= (max_size >> 1) ? max_size :
128
		     old_size << 1);
129
    int code;
130
 
131
    pda->next = next;
132
    if (old_size == max_size)
133
	return_error(e_limitcheck);
134
    while ((code = dynamic_resize(pda, new_size)) < 0 &&
135
	   new_size > old_size
136
	) {			/* Try trimming down the requested new size. */
137
	new_size -= (new_size - old_size + 1) >> 1;
138
    }
139
    return code;
140
}
141
 
142
/* Ensure that a dynamic string is either on the heap or in the */
143
/* private buffer. */
144
private void
145
dynamic_save(da_ptr pda)
146
{
147
    if (!pda->is_dynamic && pda->base != pda->buf) {
148
	memcpy(pda->buf, pda->base, da_size(pda));
149
	pda->next = pda->buf + da_size(pda);
150
	pda->base = pda->buf;
151
    }
152
}
153
 
154
/* Finish collecting a dynamic string. */
155
private int
156
dynamic_make_string(i_ctx_t *i_ctx_p, ref * pref, da_ptr pda, byte * next)
157
{
158
    uint size = (pda->next = next) - pda->base;
159
    int code = dynamic_resize(pda, size);
160
 
161
    if (code < 0)
162
	return code;
163
    make_tasv_new(pref, t_string,
164
		  a_all | imemory_space((gs_ref_memory_t *) pda->memory),
165
		  size, bytes, pda->base);
166
    return 0;
167
}
168
 
169
/* ------ Main scanner ------ */
170
 
171
/* GC procedures */
172
#define ssarray ssptr->s_ss.binary.bin_array
173
private 
174
CLEAR_MARKS_PROC(scanner_clear_marks)
175
{
176
    scanner_state *const ssptr = vptr;
177
 
178
    r_clear_attrs(&ssarray, l_mark);
179
}
180
private 
181
ENUM_PTRS_WITH(scanner_enum_ptrs, scanner_state *ssptr) return 0;
182
case 0:
183
    if (ssptr->s_scan_type == scanning_none ||
184
	!ssptr->s_da.is_dynamic
185
	)
186
	ENUM_RETURN(0);
187
    return ENUM_STRING2(ssptr->s_da.base, da_size(&ssptr->s_da));
188
case 1:
189
    if (ssptr->s_scan_type != scanning_binary)
190
	return 0;
191
    ENUM_RETURN_REF(&ssarray);
192
ENUM_PTRS_END
193
private RELOC_PTRS_WITH(scanner_reloc_ptrs, scanner_state *ssptr)
194
{
195
    if (ssptr->s_scan_type != scanning_none && ssptr->s_da.is_dynamic) {
196
	gs_string sda;
197
 
198
	sda.data = ssptr->s_da.base;
199
	sda.size = da_size(&ssptr->s_da);
200
	RELOC_STRING_VAR(sda);
201
	ssptr->s_da.limit = sda.data + sda.size;
202
	ssptr->s_da.next = sda.data + (ssptr->s_da.next - ssptr->s_da.base);
203
	ssptr->s_da.base = sda.data;
204
    }
205
    if (ssptr->s_scan_type == scanning_binary) {
206
	RELOC_REF_VAR(ssarray);
207
	r_clear_attrs(&ssarray, l_mark);
208
    }
209
}
210
RELOC_PTRS_END
211
/* Structure type */
212
public_st_scanner_state();
213
 
214
/* Initialize a scanner. */
215
void
216
scanner_state_init_options(scanner_state *sstate, int options)
217
{
218
    sstate->s_scan_type = scanning_none;
219
    sstate->s_pstack = 0;
220
    sstate->s_options = options;
221
}
222
 
223
/* Handle a scan_Refill return from scan_token. */
224
/* This may return o_push_estack, 0 (meaning just call scan_token again), */
225
/* or an error code. */
226
int
227
scan_handle_refill(i_ctx_t *i_ctx_p, const ref * fop, scanner_state * sstate,
228
		   bool save, bool push_file, op_proc_t cont)
229
{
230
    stream *s = fptr(fop);
231
    uint avail = sbufavailable(s);
232
    int status;
233
 
234
    if (s->end_status == EOFC) {
235
	/* More data needed, but none available, so this is a syntax error. */
236
	return_error(e_syntaxerror);
237
    }
238
    status = s_process_read_buf(s);
239
    if (sbufavailable(s) > avail)
240
	return 0;
241
    if (status == 0)
242
	status = s->end_status;
243
    switch (status) {
244
	case EOFC:
245
	    /* We just discovered that we're at EOF. */
246
	    /* Let the caller find this out. */
247
	    return 0;
248
	case ERRC:
249
	    return_error(e_ioerror);
250
	case INTC:
251
	case CALLC:
252
	    {
253
		ref rstate[2];
254
		scanner_state *pstate;
255
		int nstate = (push_file ? 2 : 1);
256
 
257
		if (save) {
258
		    pstate =
259
			ialloc_struct(scanner_state, &st_scanner_state,
260
				      "scan_handle_refill");
261
		    if (pstate == 0)
262
			return_error(e_VMerror);
263
		    *pstate = *sstate;
264
		} else
265
		    pstate = sstate;
266
		/* If push_file is true, we want to push the file on the */
267
		/* o-stack before the state, for the continuation proc. */
268
		/* Since the refs passed to s_handle_read_exception */
269
		/* are pushed on the e-stack, we must ensure they are */
270
		/* literal, and also pass them in the opposite order! */
271
		make_istruct(&rstate[0], 0, pstate);
272
		rstate[1] = *fop;
273
		r_clear_attrs(&rstate[1], a_executable);
274
		return s_handle_read_exception(i_ctx_p, status, fop,
275
					       rstate, nstate, cont);
276
	    }
277
    }
278
    /* No more data available, but no exception.  How can this be? */
279
    lprintf("Can't refill scanner input buffer!");
280
    return_error(e_Fatal);
281
}
282
 
283
/*
284
 * Handle a comment.  The 'saved' argument is needed only for
285
 * tracing printout.
286
 */
287
private int
288
scan_comment(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate,
289
	     const byte * base, const byte * end, bool saved)
290
{
291
    uint len = (uint) (end - base);
292
    int code;
293
#ifdef DEBUG
294
    const char *sstr = (saved ? ">" : "");
295
#endif
296
 
297
    if (len > 1 && (base[1] == '%' || base[1] == '!')) {
298
	/* Process as a DSC comment if requested. */
299
#ifdef DEBUG
300
	if (gs_debug_c('%')) {
301
	    dlprintf2("[%%%%%s%c]", sstr, (len >= 3 ? '+' : '-'));
302
	    debug_print_string(base, len);
303
	    dputs("\n");
304
	}
305
#endif
306
	if (scan_dsc_proc != NULL) {
307
	    code = scan_dsc_proc(base, len);
308
	    return (code < 0 ? code : 0);
309
	}
310
	if (pstate->s_options & SCAN_PROCESS_DSC_COMMENTS) {
311
	    code = scan_DSC_Comment;
312
	    goto comment;
313
	}
314
	/* Treat as an ordinary comment. */
315
    }
316
#ifdef DEBUG
317
    else {
318
	if (gs_debug_c('%')) {
319
	    dlprintf2("[%% %s%c]", sstr, (len >= 2 ? '+' : '-'));
320
	    debug_print_string(base, len);
321
	    dputs("\n");
322
	}
323
    }
324
#endif
325
    if (scan_comment_proc != NULL) {
326
	code = scan_comment_proc(base, len);
327
	return (code < 0 ? code : 0);
328
    }
329
    if (pstate->s_options & SCAN_PROCESS_COMMENTS) {
330
	code = scan_Comment;
331
	goto comment;
332
    }
333
    return 0;
334
 comment:
335
    {
336
	byte *cstr = ialloc_string(len, "scan_comment");
337
 
338
	if (cstr == 0)
339
	    return_error(e_VMerror);
340
	memcpy(cstr, base, len);
341
	make_string(pref, a_all | icurrent_space, len, cstr);
342
    }
343
    return code;
344
}
345
 
346
/* Read a token from a string. */
347
/* Update the string if succesful. */
348
int
349
scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref,
350
			  int options)
351
{
352
    stream st;
353
    stream *s = &st;
354
    scanner_state state;
355
    int code;
356
 
357
    if (!r_has_attr(pstr, a_read))
358
	return_error(e_invalidaccess);
359
    s_init(s, NULL);
360
    sread_string(s, pstr->value.bytes, r_size(pstr));
361
    scanner_state_init_options(&state, options | SCAN_FROM_STRING);
362
    switch (code = scan_token(i_ctx_p, s, pref, &state)) {
363
	default:		/* error or comment */
364
	    if (code < 0)
365
		break;
366
	    /* falls through */
367
	case 0:		/* read a token */
368
	case scan_BOS:
369
	    {
370
		uint pos = stell(s);
371
 
372
		pstr->value.bytes += pos;
373
		r_dec_size(pstr, pos);
374
	    }
375
	    break;
376
	case scan_Refill:	/* error */
377
	    code = gs_note_error(e_syntaxerror);
378
	case scan_EOF:
379
	    break;
380
    }
381
    return code;
382
}
383
 
384
/*
385
 * Read a token from a stream.  Return 0 if an ordinary token was read,
386
 * >0 for special situations (see iscan.h).
387
 * If the token required a terminating character (i.e., was a name or
388
 * number) and the next character was whitespace, read and discard
389
 * that character.  Note that the state is relevant for e_VMerror
390
 * as well as for scan_Refill.
391
 */
392
int
393
scan_token(i_ctx_t *i_ctx_p, stream * s, ref * pref, scanner_state * pstate)
394
{
395
    ref *myref = pref;
396
    int retcode = 0;
397
    int c;
398
 
399
    s_declare_inline(s, sptr, endptr);
400
#define scan_begin_inline() s_begin_inline(s, sptr, endptr)
401
#define scan_getc() sgetc_inline(s, sptr, endptr)
402
#define scan_putback() sputback_inline(s, sptr, endptr)
403
#define scan_end_inline() s_end_inline(s, sptr, endptr)
404
    const byte *newptr;
405
    byte *daptr;
406
 
407
#define sreturn(code)\
408
  { retcode = gs_note_error(code); goto sret; }
409
#define sreturn_no_error(code)\
410
  { scan_end_inline(); return(code); }
411
#define if_not_spush1()\
412
  if ( osp < ostop ) osp++;\
413
  else if ( (retcode = ref_stack_push(&o_stack, 1)) >= 0 )\
414
    ;\
415
  else
416
#define spop1()\
417
  if ( osp >= osbot ) osp--;\
418
  else ref_stack_pop(&o_stack, 1)
419
    int max_name_ctype =
420
    (recognize_btokens()? ctype_name : ctype_btoken);
421
 
422
#define scan_sign(sign, ptr)\
423
  switch ( *ptr ) {\
424
    case '-': sign = -1; ptr++; break;\
425
    case '+': sign = 1; ptr++; break;\
426
    default: sign = 0;\
427
  }
428
#define ensure2_back(styp,nback)\
429
  if ( sptr >= endptr ) { sptr -= nback; scan_type = styp; goto pause; }
430
#define ensure2(styp) ensure2_back(styp, 1)
431
    byte s1[2];
432
    const byte *const decoder = scan_char_decoder;
433
    int status;
434
    int sign;
435
    const bool check_only = (pstate->s_options & SCAN_CHECK_ONLY) != 0;
436
    const bool PDFScanRules = (i_ctx_p->scanner_options & SCAN_PDF_RULES) != 0;
437
    const bool PDFScanInvNum = (i_ctx_p->scanner_options & SCAN_PDF_INV_NUM) != 0;
438
    scanner_state sstate;
439
 
440
#define pstack sstate.s_pstack
441
#define pdepth sstate.s_pdepth
442
#define scan_type sstate.s_scan_type
443
#define da sstate.s_da
444
#define name_type sstate.s_ss.s_name.s_name_type
445
#define try_number sstate.s_ss.s_name.s_try_number
446
 
447
    sptr = endptr = NULL; /* Quiet compiler */
448
    if (pstate->s_pstack != 0) {
449
	if_not_spush1()
450
	    return retcode;
451
	myref = osp;
452
    }
453
    /* Check whether we are resuming after an interruption. */
454
    if (pstate->s_scan_type != scanning_none) {
455
	sstate = *pstate;
456
	if (!da.is_dynamic && da.base != da.buf) {
457
	    /* The da contains some self-referencing pointers. */
458
	    /* Fix them up now. */
459
	    uint next = da.next - da.base;
460
	    uint limit = da.limit - da.base;
461
 
462
	    da.base = da.buf;
463
	    da.next = da.buf + next;
464
	    da.limit = da.buf + limit;
465
	}
466
	daptr = da.next;
467
	switch (scan_type) {
468
	    case scanning_binary:
469
		retcode = (*sstate.s_ss.binary.cont)
470
		    (i_ctx_p, s, myref, &sstate);
471
		scan_begin_inline();
472
		if (retcode == scan_Refill)
473
		    goto pause;
474
		goto sret;
475
	    case scanning_comment:
476
		scan_begin_inline();
477
		goto cont_comment;
478
	    case scanning_name:
479
		goto cont_name;
480
	    case scanning_string:
481
		goto cont_string;
482
	    default:
483
		return_error(e_Fatal);
484
	}
485
    }
486
    /* Fetch any state variables that are relevant even if */
487
    /* scan_type == scanning_none. */
488
    pstack = pstate->s_pstack;
489
    pdepth = pstate->s_pdepth;
490
    sstate.s_options = pstate->s_options;
491
    scan_begin_inline();
492
    /*
493
     * Loop invariants:
494
     *      If pstack != 0, myref = osp, and *osp is a valid slot.
495
     */
496
  top:c = scan_getc();
497
    if_debug1('S', (c >= 32 && c <= 126 ? "`%c'" : c >= 0 ? "`\\%03o'" : "`%d'"), c);
498
    switch (c) {
499
	case ' ':
500
	case '\f':
501
	case '\t':
502
	case char_CR:
503
	case char_EOL:
504
	case char_NULL:
505
	    goto top;
506
        case 0x4:	/* ^D is a self-delimiting token */
507
	case '[':
508
	case ']':
509
	    s1[0] = (byte) c;
510
	    retcode = name_ref(imemory, s1, 1, myref, 1);	/* can't fail */
511
	    r_set_attrs(myref, a_executable);
512
	    break;
513
	case '<':
514
	    if (scan_enable_level2) {
515
		ensure2(scanning_none);
516
		c = scan_getc();
517
		switch (c) {
518
		    case '<':
519
			scan_putback();
520
			name_type = 0;
521
			try_number = false;
522
			goto try_funny_name;
523
		    case '~':
524
			s_A85D_init_inline(&sstate.s_ss.a85d);
525
			sstate.s_ss.st.template = &s_A85D_template;
526
			goto str;
527
		}
528
		scan_putback();
529
	    }
530
	    s_AXD_init_inline(&sstate.s_ss.axd);
531
	    sstate.s_ss.st.template = &s_AXD_template;
532
	  str:scan_end_inline();
533
	    dynamic_init(&da, imemory);
534
	  cont_string:for (;;) {
535
		stream_cursor_write w;
536
 
537
		w.ptr = da.next - 1;
538
		w.limit = da.limit - 1;
539
		status = (*sstate.s_ss.st.template->process)
540
		    (&sstate.s_ss.st, &s->cursor.r, &w,
541
		     s->end_status == EOFC);
542
		if (!check_only)
543
		    da.next = w.ptr + 1;
544
		switch (status) {
545
		    case 0:
546
			status = s->end_status;
547
			if (status < 0) {
548
			    if (status == EOFC) {
549
				if (check_only) {
550
				    retcode = scan_Refill;
551
				    scan_type = scanning_string;
552
				    goto suspend;
553
				} else
554
				    sreturn(e_syntaxerror);
555
			    }
556
			    break;
557
			}
558
			s_process_read_buf(s);
559
			continue;
560
		    case 1:
561
			if (!check_only) {
562
			    retcode = dynamic_grow(&da, da.next, max_string_size);
563
			    if (retcode == e_VMerror) {
564
				scan_type = scanning_string;
565
				goto suspend;
566
			    } else if (retcode < 0)
567
				sreturn(retcode);
568
			}
569
			continue;
570
		}
571
		break;
572
	    }
573
	    scan_begin_inline();
574
	    switch (status) {
575
		default:
576
		    /*case ERRC: */
577
		    sreturn(e_syntaxerror);
578
		case INTC:
579
		case CALLC:
580
		    scan_type = scanning_string;
581
		    goto pause;
582
		case EOFC:
583
		    ;
584
	    }
585
	    retcode = dynamic_make_string(i_ctx_p, myref, &da, da.next);
586
	    if (retcode < 0) {	/* VMerror */
587
		sputback(s);	/* rescan ) */
588
		scan_type = scanning_string;
589
		goto suspend;
590
	    }
591
	    break;
592
	case '(':
593
	    sstate.s_ss.pssd.from_string =
594
		((pstate->s_options & SCAN_FROM_STRING) != 0) &&
595
		!scan_enable_level2;
596
	    s_PSSD_partially_init_inline(&sstate.s_ss.pssd);
597
	    sstate.s_ss.st.template = &s_PSSD_template;
598
	    goto str;
599
	case '{':
600
	    if (pstack == 0) {	/* outermost procedure */
601
		if_not_spush1() {
602
		    scan_putback();
603
		    scan_type = scanning_none;
604
		    goto pause_ret;
605
		}
606
		pdepth = ref_stack_count_inline(&o_stack);
607
	    }
608
	    make_int(osp, pstack);
609
	    pstack = ref_stack_count_inline(&o_stack);
610
	    if_debug3('S', "[S{]d=%d, s=%d->%d\n",
611
		      pdepth, (int)osp->value.intval, pstack);
612
	    goto snext;
613
	case '>':
614
	    if (scan_enable_level2) {
615
		ensure2(scanning_none);
616
		name_type = 0;
617
		try_number = false;
618
		goto try_funny_name;
619
	    }
620
	    /* falls through */
621
	case ')':
622
	    sreturn(e_syntaxerror);
623
	case '}':
624
	    if (pstack == 0)
625
		sreturn(e_syntaxerror);
626
	    osp--;
627
	    {
628
		uint size = ref_stack_count_inline(&o_stack) - pstack;
629
		ref arr;
630
 
631
		if_debug4('S', "[S}]d=%d, s=%d->%ld, c=%d\n",
632
			  pdepth, pstack,
633
			  (pstack == pdepth ? 0 :
634
			   ref_stack_index(&o_stack, size)->value.intval),
635
			  size + pstack);
636
		myref = (pstack == pdepth ? pref : &arr);
637
		if (check_only) {
638
		    make_empty_array(myref, 0);
639
		    ref_stack_pop(&o_stack, size);
640
		} else if (ref_array_packing.value.boolval) {
641
		    retcode = make_packed_array(myref, &o_stack, size,
642
						idmemory, "scanner(packed)");
643
		    if (retcode < 0) {	/* must be VMerror */
644
			osp++;
645
			scan_putback();
646
			scan_type = scanning_none;
647
			goto pause_ret;
648
		    }
649
		    r_set_attrs(myref, a_executable);
650
		} else {
651
		    retcode = ialloc_ref_array(myref,
652
					       a_executable + a_all, size,
653
					       "scanner(proc)");
654
		    if (retcode < 0) {	/* must be VMerror */
655
			osp++;
656
			scan_putback();
657
			scan_type = scanning_none;
658
			goto pause_ret;
659
		    }
660
		    retcode = ref_stack_store(&o_stack, myref, size, 0, 1,
661
					      false, idmemory, "scanner");
662
		    if (retcode < 0) {
663
			ifree_ref_array(myref, "scanner(proc)");
664
			sreturn(retcode);
665
		    }
666
		    ref_stack_pop(&o_stack, size);
667
		}
668
		if (pstack == pdepth) {		/* This was the top-level procedure. */
669
		    spop1();
670
		    pstack = 0;
671
		} else {
672
		    if (osp < osbot)
673
			ref_stack_pop_block(&o_stack);
674
		    pstack = osp->value.intval;
675
		    *osp = arr;
676
		    goto snext;
677
		}
678
	    }
679
	    break;
680
	case '/':
681
	    ensure2(scanning_none);
682
	    c = scan_getc();
683
	    if (!PDFScanRules && (c == '/')) {
684
		name_type = 2;
685
		c = scan_getc();
686
	    } else
687
		name_type = 1;
688
	    try_number = false;
689
	    switch (decoder[c]) {
690
		case ctype_name:
691
		default:
692
		    goto do_name;
693
		case ctype_btoken:
694
		    if (!recognize_btokens())
695
			goto do_name;
696
		    /* otherwise, an empty name */
697
		case ctype_exception:
698
		case ctype_space:
699
		    /*
700
		     * Amazingly enough, the Adobe implementations don't accept
701
		     * / or // followed by [, ], <<, or >>, so we do the same.
702
		     * (Older versions of our code had a ctype_other case here
703
		     * that handled these specially.)
704
		     */
705
		case ctype_other:
706
		    da.base = da.limit = daptr = 0;
707
		    da.is_dynamic = false;
708
		    goto nx;
709
	    }
710
	case '%':
711
	    {			/* Scan as much as possible within the buffer. */
712
		const byte *base = sptr;
713
		const byte *end;
714
 
715
		while (++sptr < endptr)		/* stop 1 char early */
716
		    switch (*sptr) {
717
			case char_CR:
718
			    end = sptr;
719
			    if (sptr[1] == char_EOL)
720
				sptr++;
721
			  cend:	/* Check for externally processed comments. */
722
			    retcode = scan_comment(i_ctx_p, myref, &sstate,
723
						   base, end, false);
724
			    if (retcode != 0)
725
				goto comment;
726
			    goto top;
727
			case char_EOL:
728
			case '\f':
729
			    end = sptr;
730
			    goto cend;
731
		    }
732
		/*
733
		 * We got to the end of the buffer while inside a comment.
734
		 * If there is a possibility that we must pass the comment
735
		 * to an external procedure, move what we have collected
736
		 * so far into a private buffer now.
737
		 */
738
#define comment_line da.buf
739
		--sptr;
740
		comment_line[1] = 0;
741
		{
742
		    /* Could be an externally processable comment. */
743
		    uint len = sptr + 1 - base;
744
		    if (len > sizeof(comment_line))
745
			len = sizeof(comment_line);
746
 
747
		    memcpy(comment_line, base, len);
748
		    daptr = comment_line + len;
749
		}
750
		da.base = comment_line;
751
		da.is_dynamic = false;
752
	    }
753
	    /* Enter here to continue scanning a comment. */
754
	    /* daptr must be set. */
755
	  cont_comment:for (;;) {
756
		switch ((c = scan_getc())) {
757
		    default:
758
			if (c < 0)
759
			    switch (c) {
760
				case INTC:
761
				case CALLC:
762
				    da.next = daptr;
763
				    scan_type = scanning_comment;
764
				    goto pause;
765
				case EOFC:
766
				    /*
767
				     * One would think that an EOF in a comment
768
				     * should be a syntax error, but there are
769
				     * quite a number of files that end that way.
770
				     */
771
				    goto end_comment;
772
				default:
773
				    sreturn(e_syntaxerror);
774
			    }
775
			if (daptr < comment_line + max_comment_line)
776
			    *daptr++ = c;
777
			continue;
778
		    case char_CR:
779
		    case char_EOL:
780
		    case '\f':
781
		      end_comment:
782
			retcode = scan_comment(i_ctx_p, myref, &sstate,
783
					       comment_line, daptr, true);
784
			if (retcode != 0)
785
			    goto comment;
786
			goto top;
787
		}
788
	    }
789
#undef comment_line
790
	    /*NOTREACHED */
791
	case EOFC:
792
	    if (pstack != 0) {
793
		if (check_only)
794
		    goto pause;
795
		sreturn(e_syntaxerror);
796
	    }
797
	    retcode = scan_EOF;
798
	    break;
799
	case ERRC:
800
	    sreturn(e_ioerror);
801
 
802
	    /* Check for a Level 2 funny name (<< or >>). */
803
	    /* c is '<' or '>'.  We already did an ensure2. */
804
	  try_funny_name:
805
	    {
806
		int c1 = scan_getc();
807
 
808
		if (c1 == c) {
809
		    s1[0] = s1[1] = c;
810
		    name_ref(imemory, s1, 2, myref, 1);	/* can't fail */
811
		    goto have_name;
812
		}
813
		scan_putback();
814
	    }
815
	    sreturn(e_syntaxerror);
816
 
817
	    /* Handle separately the names that might be a number. */
818
	case '0':
819
	case '1':
820
	case '2':
821
	case '3':
822
	case '4':
823
	case '5':
824
	case '6':
825
	case '7':
826
	case '8':
827
	case '9':
828
	case '.':
829
	    sign = 0;
830
    nr:	    /*
831
	     * Skip a leading sign, if any, by conditionally passing
832
	     * sptr + 1 rather than sptr.  Also, if the last character
833
	     * in the buffer is a CR, we must stop the scan 1 character
834
	     * early, to be sure that we can test for CR+LF within the
835
	     * buffer, by passing endptr rather than endptr + 1.
836
	     */
837
	    retcode = scan_number(sptr + (sign & 1),
838
		    endptr /*(*endptr == char_CR ? endptr : endptr + 1) */ ,
839
				  sign, myref, &newptr, PDFScanInvNum);
840
	    if (retcode == 1 && decoder[newptr[-1]] == ctype_space) {
841
		sptr = newptr - 1;
842
		if (*sptr == char_CR && sptr[1] == char_EOL)
843
		    sptr++;
844
		retcode = 0;
845
		ref_mark_new(myref);
846
		break;
847
	    }
848
	    name_type = 0;
849
	    try_number = true;
850
	    goto do_name;
851
	case '+':
852
	    sign = 1;
853
	    goto nr;
854
	case '-':
855
	    sign = -1;
856
	    goto nr;
857
 
858
	    /* Check for a binary object */
859
#define case4(c) case c: case c+1: case c+2: case c+3
860
	  case4(128): case4(132): case4(136): case4(140):
861
	  case4(144): case4(148): case4(152): case4(156):
862
#undef case4
863
	    if (recognize_btokens()) {
864
		scan_end_inline();
865
		retcode = scan_binary_token(i_ctx_p, s, myref, &sstate);
866
		scan_begin_inline();
867
		if (retcode == scan_Refill)
868
		    goto pause;
869
		break;
870
	    }
871
	    /* Not a binary object, fall through. */
872
 
873
	    /* The default is a name. */
874
	default:
875
	    if (c < 0) {
876
		dynamic_init(&da, name_memory(imemory));	/* da state must be clean */
877
		scan_type = scanning_none;
878
		goto pause;
879
	    }
880
	    /* Populate the switch with enough cases to force */
881
	    /* simple compilers to use a dispatch rather than tests. */
882
	case '!':
883
	case '"':
884
	case '#':
885
	case '$':
886
	case '&':
887
	case '\'':
888
	case '*':
889
	case ',':
890
	case '=':
891
	case ':':
892
	case ';':
893
	case '?':
894
	case '@':
895
	case 'A':
896
	case 'B':
897
	case 'C':
898
	case 'D':
899
	case 'E':
900
	case 'F':
901
	case 'G':
902
	case 'H':
903
	case 'I':
904
	case 'J':
905
	case 'K':
906
	case 'L':
907
	case 'M':
908
	case 'N':
909
	case 'O':
910
	case 'P':
911
	case 'Q':
912
	case 'R':
913
	case 'S':
914
	case 'T':
915
	case 'U':
916
	case 'V':
917
	case 'W':
918
	case 'X':
919
	case 'Y':
920
	case 'Z':
921
	case '\\':
922
	case '^':
923
	case '_':
924
	case '`':
925
	case 'a':
926
	case 'b':
927
	case 'c':
928
	case 'd':
929
	case 'e':
930
	case 'f':
931
	case 'g':
932
	case 'h':
933
	case 'i':
934
	case 'j':
935
	case 'k':
936
	case 'l':
937
	case 'm':
938
	case 'n':
939
	case 'o':
940
	case 'p':
941
	case 'q':
942
	case 'r':
943
	case 's':
944
	case 't':
945
	case 'u':
946
	case 'v':
947
	case 'w':
948
	case 'x':
949
	case 'y':
950
	case 'z':
951
	case '|':
952
	case '~':
953
	    /* Common code for scanning a name. */
954
	    /* try_number and name_type are already set. */
955
	    /* We know c has ctype_name (or maybe ctype_btoken) */
956
	    /* or is a digit. */
957
	    name_type = 0;
958
	    try_number = false;
959
	  do_name:
960
	    /* Try to scan entirely within the stream buffer. */
961
	    /* We stop 1 character early, so we don't switch buffers */
962
	    /* looking ahead if the name is terminated by \r\n. */
963
	    da.base = (byte *) sptr;
964
	    da.is_dynamic = false;
965
	    {
966
		const byte *endp1 = endptr - 1;
967
 
968
		do {
969
		    if (sptr >= endp1)	/* stop 1 early! */
970
			goto dyn_name;
971
		}
972
		while (decoder[*++sptr] <= max_name_ctype);	/* digit or name */
973
	    }
974
	    /* Name ended within the buffer. */
975
	    daptr = (byte *) sptr;
976
	    c = *sptr;
977
	    goto nx;
978
	  dyn_name:		/* Name extended past end of buffer. */
979
	    scan_end_inline();
980
	    /* Initialize the dynamic area. */
981
	    /* We have to do this before the next */
982
	    /* sgetc, which will overwrite the buffer. */
983
	    da.limit = (byte *)++ sptr;
984
	    da.memory = name_memory(imemory);
985
	    retcode = dynamic_grow(&da, da.limit, name_max_string);
986
	    if (retcode < 0) {
987
		dynamic_save(&da);
988
		if (retcode != e_VMerror)
989
		    sreturn(retcode);
990
		scan_type = scanning_name;
991
		goto pause_ret;
992
	    }
993
	    daptr = da.next;
994
	    /* Enter here to continue scanning a name. */
995
	    /* daptr must be set. */
996
	  cont_name:scan_begin_inline();
997
	    while (decoder[c = scan_getc()] <= max_name_ctype) {
998
		if (daptr == da.limit) {
999
		    retcode = dynamic_grow(&da, daptr,
1000
					   name_max_string);
1001
		    if (retcode < 0) {
1002
			dynamic_save(&da);
1003
			if (retcode != e_VMerror)
1004
			    sreturn(retcode);
1005
			scan_putback();
1006
			scan_type = scanning_name;
1007
			goto pause_ret;
1008
		    }
1009
		    daptr = da.next;
1010
		}
1011
		*daptr++ = c;
1012
	    }
1013
	  nx:switch (decoder[c]) {
1014
		case ctype_btoken:
1015
		case ctype_other:
1016
		    scan_putback();
1017
		    break;
1018
		case ctype_space:
1019
		    /* Check for \r\n */
1020
		    if (c == char_CR) {
1021
			if (sptr >= endptr) {	/* ensure2 *//* We have to check specially for */
1022
			    /* the case where the very last */
1023
			    /* character of a file is a CR. */
1024
			    if (s->end_status != EOFC) {
1025
				sptr--;
1026
				goto pause_name;
1027
			    }
1028
			} else if (sptr[1] == char_EOL)
1029
			    sptr++;
1030
		    }
1031
		    break;
1032
		case ctype_exception:
1033
		    switch (c) {
1034
			case INTC:
1035
			case CALLC:
1036
			    goto pause_name;
1037
			case ERRC:
1038
			    sreturn(e_ioerror);
1039
			case EOFC:
1040
			    break;
1041
		    }
1042
	    }
1043
	    /* Check for a number */
1044
	    if (try_number) {
1045
		const byte *base = da.base;
1046
 
1047
		scan_sign(sign, base);
1048
		retcode = scan_number(base, daptr, sign, myref, &newptr, PDFScanInvNum);
1049
		if (retcode == 1) {
1050
		    ref_mark_new(myref);
1051
		    retcode = 0;
1052
		} else if (retcode != e_syntaxerror) {
1053
		    dynamic_free(&da);
1054
		    if (name_type == 2)
1055
			sreturn(e_syntaxerror);
1056
		    break;	/* might be e_limitcheck */
1057
		}
1058
	    }
1059
	    if (da.is_dynamic) {	/* We've already allocated the string on the heap. */
1060
		uint size = daptr - da.base;
1061
 
1062
		retcode = name_ref(imemory, da.base, size, myref, -1);
1063
		if (retcode >= 0) {
1064
		    dynamic_free(&da);
1065
		} else {
1066
		    retcode = dynamic_resize(&da, size);
1067
		    if (retcode < 0) {	/* VMerror */
1068
			if (c != EOFC)
1069
			    scan_putback();
1070
			scan_type = scanning_name;
1071
			goto pause_ret;
1072
		    }
1073
		    retcode = name_ref(imemory, da.base, size, myref, 2);
1074
		}
1075
	    } else {
1076
		retcode = name_ref(imemory, da.base, (uint) (daptr - da.base),
1077
				   myref, !s->foreign);
1078
	    }
1079
	    /* Done scanning.  Check for preceding /'s. */
1080
	    if (retcode < 0) {
1081
		if (retcode != e_VMerror)
1082
		    sreturn(retcode);
1083
		if (!da.is_dynamic) {
1084
		    da.next = daptr;
1085
		    dynamic_save(&da);
1086
		}
1087
		if (c != EOFC)
1088
		    scan_putback();
1089
		scan_type = scanning_name;
1090
		goto pause_ret;
1091
	    }
1092
	  have_name:switch (name_type) {
1093
		case 0:	/* ordinary executable name */
1094
		    if (r_has_type(myref, t_name))	/* i.e., not a number */
1095
			r_set_attrs(myref, a_executable);
1096
		case 1:	/* quoted name */
1097
		    break;
1098
		case 2:	/* immediate lookup */
1099
		    {
1100
			ref *pvalue;
1101
 
1102
			if (!r_has_type(myref, t_name))
1103
			    sreturn(e_undefined);
1104
			if ((pvalue = dict_find_name(myref)) == 0)
1105
			    sreturn(e_undefined);
1106
			if (pstack != 0 &&
1107
			    r_space(pvalue) > ialloc_space(idmemory)
1108
			    )
1109
			    sreturn(e_invalidaccess);
1110
			ref_assign_new(myref, pvalue);
1111
		    }
1112
	    }
1113
    }
1114
  sret:if (retcode < 0) {
1115
	scan_end_inline();
1116
	if (pstack != 0) {
1117
	    if (retcode == e_undefined)
1118
		*pref = *osp;	/* return undefined name as error token */
1119
	    ref_stack_pop(&o_stack,
1120
			  ref_stack_count(&o_stack) - (pdepth - 1));
1121
	}
1122
	return retcode;
1123
    }
1124
    /* If we are at the top level, return the object, */
1125
    /* otherwise keep going. */
1126
    if (pstack == 0) {
1127
	scan_end_inline();
1128
	return retcode;
1129
    }
1130
  snext:if_not_spush1() {
1131
	scan_end_inline();
1132
	scan_type = scanning_none;
1133
	goto save;
1134
    }
1135
    myref = osp;
1136
    goto top;
1137
 
1138
    /* Pause for an interrupt or callout. */
1139
  pause_name:
1140
    /* If we're still scanning within the stream buffer, */
1141
    /* move the characters to the private buffer (da.buf) now. */
1142
    da.next = daptr;
1143
    dynamic_save(&da);
1144
    scan_type = scanning_name;
1145
  pause:
1146
    retcode = scan_Refill;
1147
  pause_ret:
1148
    scan_end_inline();
1149
  suspend:
1150
    if (pstack != 0)
1151
	osp--;			/* myref */
1152
  save:
1153
    *pstate = sstate;
1154
    return retcode;
1155
 
1156
    /* Handle a scanned comment. */
1157
 comment:
1158
    if (retcode < 0)
1159
	goto sret;
1160
    scan_end_inline();
1161
    scan_type = scanning_none;
1162
    goto save;
1163
}