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
dynamic_init(da_ptr pda,gs_memory_t * mem)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
dynamic_free(da_ptr pda)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
dynamic_resize(da_ptr pda,uint new_size)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
dynamic_grow(da_ptr pda,byte * next,uint max_size)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
dynamic_save(da_ptr pda)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
dynamic_make_string(i_ctx_t * i_ctx_p,ref * pref,da_ptr pda,byte * next)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
CLEAR_MARKS_PROC(scanner_clear_marks)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
RELOC_PTRS_WITH(scanner_reloc_ptrs,scanner_state * ssptr)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
scanner_state_init_options(scanner_state * sstate,int options)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
scan_handle_refill(i_ctx_t * i_ctx_p,const ref * fop,scanner_state * sstate,bool save,bool push_file,op_proc_t cont)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
scan_comment(i_ctx_t * i_ctx_p,ref * pref,scanner_state * pstate,const byte * base,const byte * end,bool saved)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
scan_string_token_options(i_ctx_t * i_ctx_p,ref * pstr,ref * pref,int options)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
scan_token(i_ctx_t * i_ctx_p,stream * s,ref * pref,scanner_state * pstate)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 }
1164