/src/ghostpdl/psi/iscan.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2022 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Token scanner for Ghostscript interpreter */ |
18 | | #include "ghost.h" |
19 | | #include "memory_.h" |
20 | | #include "string_.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 | | /* |
48 | | * Level 2 includes some changes in the scanner: |
49 | | * - \ is always recognized in strings, regardless of the data source; |
50 | | * - << and >> are legal tokens; |
51 | | * - <~ introduces an ASCII85 encoded string (terminated by ~>); |
52 | | * - Character codes above 127 introduce binary objects. |
53 | | * We explicitly enable or disable these changes based on level2_enabled. |
54 | | */ |
55 | | |
56 | | /* ------ Dynamic strings ------ */ |
57 | | |
58 | | /* Begin collecting a dynamically allocated string. */ |
59 | | static inline void |
60 | | dynamic_init(da_ptr pda, gs_memory_t *mem) |
61 | 1.28M | { |
62 | 1.28M | pda->is_dynamic = false; |
63 | 1.28M | pda->limit = pda->buf + sizeof(pda->buf); |
64 | 1.28M | pda->next = pda->base = pda->buf; |
65 | 1.28M | pda->memory = mem; |
66 | 1.28M | } |
67 | | |
68 | | /* Free a dynamic string. */ |
69 | | static void |
70 | | dynamic_free(da_ptr pda) |
71 | 5.96M | { |
72 | 5.96M | if (pda->is_dynamic) |
73 | 31.8k | gs_free_string(pda->memory, pda->base, da_size(pda), "scanner"); |
74 | 5.96M | } |
75 | | |
76 | | /* Resize a dynamic string. */ |
77 | | /* If the allocation fails, return gs_error_VMerror; otherwise, return 0. */ |
78 | | static int |
79 | | dynamic_resize(da_ptr pda, uint new_size) |
80 | 1.32M | { |
81 | 1.32M | uint old_size = da_size(pda); |
82 | 1.32M | uint pos = pda->next - pda->base; |
83 | 1.32M | gs_memory_t *mem = pda->memory; |
84 | 1.32M | byte *base; |
85 | | |
86 | 1.32M | if (pda->is_dynamic) { |
87 | 4.87k | base = gs_resize_string(mem, pda->base, old_size, |
88 | 4.87k | new_size, "scanner"); |
89 | 4.87k | if (base == 0) |
90 | 0 | return_error(gs_error_VMerror); |
91 | 1.31M | } else { /* switching from static to dynamic */ |
92 | 1.31M | base = gs_alloc_string(mem, new_size, "scanner"); |
93 | 1.31M | if (base == 0) |
94 | 0 | return_error(gs_error_VMerror); |
95 | 1.31M | memcpy(base, pda->base, min(old_size, new_size)); |
96 | 1.31M | pda->is_dynamic = true; |
97 | 1.31M | } |
98 | 1.32M | pda->base = base; |
99 | 1.32M | pda->next = base + pos; |
100 | 1.32M | pda->limit = base + new_size; |
101 | 1.32M | return 0; |
102 | 1.32M | } |
103 | | |
104 | | /* Grow a dynamic string. */ |
105 | | /* Return 0 if the allocation failed, the new 'next' ptr if OK. */ |
106 | | /* Return 0 or an error code, updating pda->next to point to the first */ |
107 | | /* available byte after growing. */ |
108 | | static int |
109 | | dynamic_grow(da_ptr pda, byte * next, uint max_size) |
110 | 36.7k | { |
111 | 36.7k | uint old_size = da_size(pda); |
112 | 36.7k | uint new_size = (old_size < 10 ? 20 : |
113 | 36.7k | old_size >= (max_size >> 1) ? max_size : |
114 | 10.4k | old_size << 1); |
115 | 36.7k | int code; |
116 | | |
117 | 36.7k | pda->next = next; |
118 | 36.7k | if (old_size >= max_size) |
119 | 1 | return_error(gs_error_limitcheck); |
120 | 36.7k | while ((code = dynamic_resize(pda, new_size)) < 0) { |
121 | | /* Try trimming down the requested new size. */ |
122 | 0 | new_size -= (new_size - old_size + 1) >> 1; |
123 | 0 | if (new_size <= old_size) |
124 | 0 | break; |
125 | 0 | } |
126 | 36.7k | return code; |
127 | 36.7k | } |
128 | | |
129 | | /* Ensure that a dynamic string is either on the heap or in the */ |
130 | | /* private buffer. */ |
131 | | static void |
132 | | dynamic_save(da_ptr pda) |
133 | 2.73k | { |
134 | 2.73k | if (!pda->is_dynamic && pda->base != pda->buf) { |
135 | 0 | int len = da_size(pda); |
136 | |
|
137 | 0 | if (len > sizeof(pda->buf)) |
138 | 0 | len = sizeof(pda->buf); |
139 | 0 | memcpy(pda->buf, pda->base, len); |
140 | 0 | pda->next = pda->buf + len; |
141 | 0 | pda->base = pda->buf; |
142 | 0 | } |
143 | 2.73k | } |
144 | | |
145 | | /* Finish collecting a dynamic string. */ |
146 | | static int |
147 | | dynamic_make_string(i_ctx_t *i_ctx_p, ref * pref, da_ptr pda, byte * next) |
148 | 1.27M | { |
149 | 1.27M | uint size = (pda->next = next) - pda->base; |
150 | 1.27M | int code = dynamic_resize(pda, size); |
151 | | |
152 | 1.27M | if (code < 0) |
153 | 0 | return code; |
154 | 1.27M | make_tasv_new(pref, t_string, |
155 | 1.27M | a_all | imemory_space((gs_ref_memory_t *) pda->memory), |
156 | 1.27M | size, bytes, pda->base); |
157 | 1.27M | return 0; |
158 | 1.27M | } |
159 | | |
160 | | /* ------ Main scanner ------ */ |
161 | | |
162 | | /* GC procedures */ |
163 | | static |
164 | | CLEAR_MARKS_PROC(scanner_clear_marks) |
165 | 0 | { |
166 | 0 | scanner_state *const ssptr = vptr; |
167 | |
|
168 | 0 | r_clear_attrs(&ssptr->s_file, l_mark); |
169 | 0 | r_clear_attrs(&ssptr->s_ss.binary.bin_array, l_mark); |
170 | 0 | r_clear_attrs(&ssptr->s_error.object, l_mark); |
171 | 0 | } |
172 | | static |
173 | 0 | ENUM_PTRS_WITH(scanner_enum_ptrs, scanner_state *ssptr) return 0; |
174 | 0 | case 0: |
175 | 0 | ENUM_RETURN_REF(&ssptr->s_file); |
176 | 0 | case 1: |
177 | 0 | ENUM_RETURN_REF(&ssptr->s_error.object); |
178 | 0 | case 2: |
179 | 0 | if (ssptr->s_scan_type == scanning_none || |
180 | 0 | !ssptr->s_da.is_dynamic |
181 | 0 | ) |
182 | 0 | ENUM_RETURN(0); |
183 | 0 | return ENUM_STRING2(ssptr->s_da.base, da_size(&ssptr->s_da)); |
184 | 0 | case 3: |
185 | 0 | if (ssptr->s_scan_type != scanning_binary) |
186 | 0 | return 0; |
187 | 0 | ENUM_RETURN_REF(&ssptr->s_ss.binary.bin_array); |
188 | 0 | ENUM_PTRS_END |
189 | 0 | static RELOC_PTRS_WITH(scanner_reloc_ptrs, scanner_state *ssptr) |
190 | 0 | { |
191 | 0 | RELOC_REF_VAR(ssptr->s_file); |
192 | 0 | r_clear_attrs(&ssptr->s_file, l_mark); |
193 | 0 | if (ssptr->s_scan_type != scanning_none && ssptr->s_da.is_dynamic) { |
194 | 0 | gs_string sda; |
195 | |
|
196 | 0 | sda.data = ssptr->s_da.base; |
197 | 0 | sda.size = da_size(&ssptr->s_da); |
198 | 0 | RELOC_STRING_VAR(sda); |
199 | 0 | ssptr->s_da.limit = sda.data + sda.size; |
200 | 0 | ssptr->s_da.next = sda.data + (ssptr->s_da.next - ssptr->s_da.base); |
201 | 0 | ssptr->s_da.base = sda.data; |
202 | 0 | } |
203 | 0 | if (ssptr->s_scan_type == scanning_binary) { |
204 | 0 | RELOC_REF_VAR(ssptr->s_ss.binary.bin_array); |
205 | 0 | r_clear_attrs(&ssptr->s_ss.binary.bin_array, l_mark); |
206 | 0 | } |
207 | 0 | RELOC_REF_VAR(ssptr->s_error.object); |
208 | 0 | r_clear_attrs(&ssptr->s_error.object, l_mark); |
209 | 0 | } |
210 | 0 | RELOC_PTRS_END |
211 | | /* Structure type */ |
212 | | public_st_scanner_state_dynamic(); |
213 | | |
214 | | /* Initialize a scanner. */ |
215 | | void |
216 | | gs_scanner_init_options(scanner_state *sstate, const ref *fop, int options) |
217 | 28.4M | { |
218 | 28.4M | ref_assign(&sstate->s_file, fop); |
219 | 28.4M | sstate->s_scan_type = scanning_none; |
220 | 28.4M | sstate->s_pstack = 0; |
221 | 28.4M | sstate->s_options = options; |
222 | 28.4M | SCAN_INIT_ERROR(sstate); |
223 | 28.4M | } |
224 | | void gs_scanner_init_stream_options(scanner_state *sstate, stream *s, |
225 | | int options) |
226 | 3.43k | { |
227 | | /* |
228 | | * The file 'object' will never be accessed, but it must be in correct |
229 | | * form for the GC. |
230 | | */ |
231 | 3.43k | ref fobj; |
232 | | |
233 | 3.43k | make_file(&fobj, a_read, 0, s); |
234 | 3.43k | gs_scanner_init_options(sstate, &fobj, options); |
235 | 3.43k | } |
236 | | |
237 | | /* |
238 | | * Return the "error object" to be stored in $error.command instead of |
239 | | * --token--, if any, or <0 if no special error object is available. |
240 | | */ |
241 | | int |
242 | | gs_scanner_error_object(i_ctx_t *i_ctx_p, const scanner_state *pstate, |
243 | | ref *pseo) |
244 | 7 | { |
245 | 7 | if (!r_has_type(&pstate->s_error.object, t__invalid)) { |
246 | 0 | ref_assign(pseo, &pstate->s_error.object); |
247 | 0 | return 0; |
248 | 0 | } |
249 | 7 | if (pstate->s_error.string[0]) { |
250 | 0 | int len = strlen(pstate->s_error.string); |
251 | |
|
252 | 0 | if (pstate->s_error.is_name) { |
253 | 0 | int code = name_ref(imemory, (const byte *)pstate->s_error.string, len, pseo, 1); |
254 | |
|
255 | 0 | if (code < 0) |
256 | 0 | return code; |
257 | 0 | r_set_attrs(pseo, a_executable); /* Adobe compatibility */ |
258 | 0 | return 0; |
259 | 0 | } else { |
260 | 0 | byte *estr = ialloc_string(len, "gs_scanner_error_object"); |
261 | |
|
262 | 0 | if (estr == 0) |
263 | 0 | return -1; /* VMerror */ |
264 | 0 | memcpy(estr, (const byte *)pstate->s_error.string, len); |
265 | 0 | make_string(pseo, a_all | icurrent_space, len, estr); |
266 | 0 | return 0; |
267 | 0 | } |
268 | 0 | } |
269 | 7 | return -1; /* no error object */ |
270 | 7 | } |
271 | | |
272 | | /* Handle a scan_Refill return from gs_scan_token. */ |
273 | | /* This may return o_push_estack, 0 (meaning just call gs_scan_token */ |
274 | | /* again), or an error code. */ |
275 | | int |
276 | | gs_scan_handle_refill(i_ctx_t *i_ctx_p, scanner_state * sstate, |
277 | | bool save, op_proc_t cont) |
278 | 6.17k | { |
279 | 6.17k | const ref *const fop = &sstate->s_file; |
280 | 6.17k | stream *s = fptr(fop); |
281 | 6.17k | uint avail = sbufavailable(s); |
282 | 6.17k | int status; |
283 | | |
284 | 6.17k | if (s->end_status == EOFC) { |
285 | | /* More data needed, but none available, so this is a syntax error. */ |
286 | 0 | return_error(gs_error_syntaxerror); |
287 | 0 | } |
288 | 6.17k | status = s_process_read_buf(s); |
289 | 6.17k | if (sbufavailable(s) > avail) |
290 | 27 | return 0; |
291 | 6.14k | if (status == 0) |
292 | 6.14k | status = s->end_status; |
293 | 6.14k | switch (status) { |
294 | 0 | case EOFC: |
295 | | /* We just discovered that we're at EOF. */ |
296 | | /* Let the caller find this out. */ |
297 | 0 | return 0; |
298 | 0 | case ERRC: |
299 | 0 | return_error(gs_error_ioerror); |
300 | 0 | case INTC: |
301 | 6.14k | case CALLC: |
302 | 6.14k | { |
303 | 6.14k | ref rstate[1]; |
304 | 6.14k | scanner_state *pstate; |
305 | | |
306 | 6.14k | if (save) { |
307 | 5.46k | pstate = (scanner_state *) |
308 | 5.46k | ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, |
309 | 5.46k | "gs_scan_handle_refill"); |
310 | 5.46k | if (pstate == 0) |
311 | 0 | return_error(gs_error_VMerror); |
312 | 5.46k | ((scanner_state_dynamic *)pstate)->mem = imemory; |
313 | 5.46k | *pstate = *sstate; |
314 | 5.46k | } else |
315 | 683 | pstate = sstate; |
316 | 6.14k | make_istruct(&rstate[0], 0, pstate); |
317 | 6.14k | return s_handle_read_exception(i_ctx_p, status, fop, |
318 | 6.14k | rstate, 1, cont); |
319 | 6.14k | } |
320 | 6.14k | } |
321 | | /* No more data available, but no exception. */ |
322 | | /* A filter is consuming headers but returns nothing. */ |
323 | 0 | return 0; |
324 | 6.14k | } |
325 | | |
326 | | /* |
327 | | * Handle a comment. The 'saved' argument is needed only for |
328 | | * tracing printout. |
329 | | */ |
330 | | static int |
331 | | scan_comment(i_ctx_t *i_ctx_p, ref *pref, scanner_state *pstate, |
332 | | const byte * base, const byte * end, bool saved) |
333 | 6.74k | { |
334 | 6.74k | uint len = (uint) (end - base); |
335 | 6.74k | int code; |
336 | | #ifdef DEBUG |
337 | | const char *sstr = (saved ? ">" : ""); |
338 | | #endif |
339 | | |
340 | 6.74k | if (len > 1 && (base[1] == '%' || base[1] == '!')) { |
341 | | /* Process as a DSC comment if requested. */ |
342 | | #ifdef DEBUG |
343 | | if (gs_debug_c('%')) { |
344 | | dmlprintf2(imemory, "[%%%%%s%c]", sstr, (len >= 3 ? '+' : '-')); |
345 | | debug_print_string(imemory, base, len); |
346 | | dmputs(imemory, "\n"); |
347 | | } |
348 | | #endif |
349 | 44 | if (pstate->s_options & SCAN_PROCESS_DSC_COMMENTS) { |
350 | 44 | code = scan_DSC_Comment; |
351 | 44 | goto comment; |
352 | 44 | } |
353 | | /* Treat as an ordinary comment. */ |
354 | 44 | } |
355 | | #ifdef DEBUG |
356 | | else { |
357 | | if (gs_debug_c('%')) { |
358 | | dmlprintf2(imemory, "[%% %s%c]", sstr, (len >= 2 ? '+' : '-')); |
359 | | debug_print_string(imemory, base, len); |
360 | | dmputs(imemory, "\n"); |
361 | | } |
362 | | } |
363 | | #endif |
364 | 6.70k | if (pstate->s_options & SCAN_PROCESS_COMMENTS) { |
365 | 0 | code = scan_Comment; |
366 | 0 | goto comment; |
367 | 0 | } |
368 | 6.70k | return 0; |
369 | 44 | comment: |
370 | 44 | { |
371 | 44 | byte *cstr = ialloc_string(len, "scan_comment"); |
372 | | |
373 | 44 | if (cstr == 0) |
374 | 0 | return_error(gs_error_VMerror); |
375 | 44 | memcpy(cstr, base, len); |
376 | 44 | make_string(pref, a_all | icurrent_space, len, cstr); |
377 | 44 | } |
378 | 0 | return code; |
379 | 44 | } |
380 | | |
381 | | /* Read a token from a string. */ |
382 | | /* Update the string if succesful. */ |
383 | | /* Store the error object in i_ctx_p->error_object if not. */ |
384 | | int |
385 | | gs_scan_string_token_options(i_ctx_t *i_ctx_p, ref * pstr, ref * pref, |
386 | | int options) |
387 | 16 | { |
388 | 16 | stream st; |
389 | 16 | stream *s = &st; |
390 | 16 | scanner_state state; |
391 | 16 | int code; |
392 | | |
393 | 16 | if (!r_has_attr(pstr, a_read)) |
394 | 0 | return_error(gs_error_invalidaccess); |
395 | 16 | s_init(s, NULL); |
396 | 16 | sread_string(s, pstr->value.bytes, r_size(pstr)); |
397 | 16 | gs_scanner_init_stream_options(&state, s, options | SCAN_FROM_STRING); |
398 | 16 | switch (code = gs_scan_token(i_ctx_p, pref, &state)) { |
399 | 0 | default: /* error or comment */ |
400 | 0 | if (code < 0) |
401 | 0 | break; |
402 | | /* falls through */ |
403 | 16 | case 0: /* read a token */ |
404 | 16 | case scan_BOS: |
405 | 16 | { |
406 | 16 | uint pos = stell(s); |
407 | | |
408 | 16 | pstr->value.bytes += pos; |
409 | 16 | r_dec_size(pstr, pos); |
410 | 16 | } |
411 | 16 | break; |
412 | 0 | case scan_Refill: /* error */ |
413 | 0 | code = gs_note_error(gs_error_syntaxerror); |
414 | 0 | case scan_EOF: |
415 | 0 | break; |
416 | 16 | } |
417 | 16 | if (code < 0) |
418 | 0 | gs_scanner_error_object(i_ctx_p, &state, &i_ctx_p->error_object); |
419 | 16 | return code; |
420 | 16 | } |
421 | | |
422 | | /* |
423 | | * Read a token from a stream. Return 0 if an ordinary token was read, |
424 | | * >0 for special situations (see iscan.h). |
425 | | * If the token required a terminating character (i.e., was a name or |
426 | | * number) and the next character was whitespace, read and discard |
427 | | * that character. Note that the state is relevant for gs_error_VMerror |
428 | | * as well as for scan_Refill. |
429 | | */ |
430 | | int |
431 | | gs_scan_token(i_ctx_t *i_ctx_p, ref * pref, scanner_state * pstate) /* lgtm [cpp/use-of-goto] */ |
432 | 28.4M | { |
433 | 28.4M | stream *const s = pstate->s_file.value.pfile; |
434 | 28.4M | ref *myref = pref; |
435 | 28.4M | int retcode = 0; |
436 | 28.4M | int c; |
437 | | |
438 | 28.4M | s_declare_inline(s, sptr, endptr); |
439 | 28.4M | const byte *newptr; |
440 | 28.4M | byte *daptr; |
441 | | |
442 | 28.4M | #define sreturn(code)\ |
443 | 28.4M | { retcode = gs_note_error(code); goto sret; } |
444 | 28.4M | #define if_not_spush1()\ |
445 | 54.5M | if ( osp < ostop ) osp++;\ |
446 | 54.5M | else if ( (retcode = ref_stack_push(&o_stack, 1)) >= 0 )\ |
447 | 3 | ;\ |
448 | 3 | else |
449 | 28.4M | #define spop1()\ |
450 | 28.4M | if ( osp >= osbot ) osp--;\ |
451 | 1.37M | else ref_stack_pop(&o_stack, 1) |
452 | 28.4M | int max_name_ctype = |
453 | 28.4M | ((ref_binary_object_format.value.intval != 0 && level2_enabled)? ctype_name : ctype_btoken); |
454 | | |
455 | 28.4M | #define scan_sign(sign, ptr)\ |
456 | 28.4M | switch ( *ptr ) {\ |
457 | 15.7k | case '-': sign = -1; ptr++; break;\ |
458 | 0 | case '+': sign = 1; ptr++; break;\ |
459 | 7.90M | default: sign = 0;\ |
460 | 7.91M | } |
461 | 28.4M | #define refill2_back(styp,nback)\ |
462 | 28.4M | BEGIN sptr -= nback; sstate.s_scan_type = styp; goto pause; END |
463 | 28.4M | #define ensure2_back(styp,nback)\ |
464 | 28.4M | if ( sptr >= endptr ) refill2_back(styp,nback) |
465 | 28.4M | #define ensure2(styp) ensure2_back(styp, 1) |
466 | 28.4M | #define refill2(styp) refill2_back(styp, 1) |
467 | 28.4M | byte s1[2]; |
468 | 28.4M | const byte *const decoder = scan_char_decoder; |
469 | 28.4M | int status; |
470 | 28.4M | int sign; |
471 | 28.4M | const bool check_only = (pstate->s_options & SCAN_CHECK_ONLY) != 0; |
472 | 28.4M | const bool PDFScanRules = (i_ctx_p->scanner_options & SCAN_PDF_RULES) != 0; |
473 | | /* |
474 | | * The following is a hack so that ^D will be self-delimiting in PS files |
475 | | * (to compensate for bugs in some PostScript-generating applications) |
476 | | * but not in strings (to match CPSI on the CET) or PDF. |
477 | | */ |
478 | 28.4M | const int ctrld = (pstate->s_options & SCAN_FROM_STRING || |
479 | 28.4M | PDFScanRules ? 0x04 : 0xffff); |
480 | 28.4M | scanner_state sstate; |
481 | | |
482 | 28.4M | sptr = endptr = NULL; /* Quiet compiler */ |
483 | 28.4M | if (pstate->s_pstack != 0) { |
484 | 0 | if_not_spush1() |
485 | 0 | return retcode; |
486 | 0 | myref = osp; |
487 | 0 | } |
488 | | /* Check whether we are resuming after an interruption. */ |
489 | 28.4M | if (pstate->s_scan_type != scanning_none) { |
490 | 2.73k | sstate = *pstate; |
491 | 2.73k | if (!sstate.s_da.is_dynamic && sstate.s_da.base != sstate.s_da.buf) { |
492 | | /* The sstate.s_da contains some self-referencing pointers. */ |
493 | | /* Fix them up now. */ |
494 | 0 | uint next = sstate.s_da.next - sstate.s_da.base; |
495 | 0 | uint limit = sstate.s_da.limit - sstate.s_da.base; |
496 | |
|
497 | 0 | sstate.s_da.base = sstate.s_da.buf; |
498 | 0 | sstate.s_da.next = sstate.s_da.buf + next; |
499 | 0 | sstate.s_da.limit = sstate.s_da.buf + limit; |
500 | 0 | } |
501 | 2.73k | daptr = sstate.s_da.next; |
502 | 2.73k | switch (sstate.s_scan_type) { |
503 | 0 | case scanning_binary: |
504 | 0 | retcode = (*sstate.s_ss.binary.cont) |
505 | 0 | (i_ctx_p, myref, &sstate); |
506 | 0 | s_begin_inline(s, sptr, endptr); |
507 | 0 | if (retcode == scan_Refill) |
508 | 0 | goto pause; |
509 | 0 | goto sret; |
510 | 0 | case scanning_comment: |
511 | 0 | s_begin_inline(s, sptr, endptr); |
512 | 0 | goto cont_comment; |
513 | 2.73k | case scanning_name: |
514 | 2.73k | goto cont_name; |
515 | 0 | case scanning_string: |
516 | 0 | goto cont_string; |
517 | 0 | default: |
518 | 0 | return_error(gs_error_Fatal); |
519 | 2.73k | } |
520 | 2.73k | } |
521 | 28.4M | else { |
522 | | /* We *may* use these in the event of returning to this function after |
523 | | * a interruption, but not every code path below sets them. Set them |
524 | | * to sane values here for safety. We can write the contents of sstate |
525 | | * (back) to pstate before returning. |
526 | | */ |
527 | 28.4M | sstate.s_da.base = sstate.s_da.next = &(sstate.s_da.buf[0]); |
528 | 28.4M | sstate.s_da.limit = sstate.s_da.next; |
529 | 28.4M | sstate.s_da.is_dynamic = false; |
530 | 28.4M | } |
531 | | /* Fetch any state variables that are relevant even if */ |
532 | | /* sstate.s_scan_type == scanning_none. */ |
533 | 28.4M | sstate.s_pstack = pstate->s_pstack; |
534 | 28.4M | sstate.s_pdepth = pstate->s_pdepth; |
535 | 28.4M | ref_assign(&sstate.s_file, &pstate->s_file); |
536 | 28.4M | sstate.s_options = pstate->s_options; |
537 | 28.4M | SCAN_INIT_ERROR(&sstate); |
538 | 28.4M | s_begin_inline(s, sptr, endptr); |
539 | | /* |
540 | | * Loop invariants: |
541 | | * If sstate.s_pstack != 0, myref = osp, and *osp is a valid slot. |
542 | | */ |
543 | 81.7M | top:c = sgetc_inline(s, sptr, endptr); |
544 | 81.7M | if_debug1m('S', imemory, (c >= 32 && c <= 126 ? "`%c'" : c >= 0 ? "`\\%03o'" : "`%d'"), c); |
545 | 81.7M | switch (c) { |
546 | 125k | case ' ': |
547 | 125k | case '\f': |
548 | 125k | case '\t': |
549 | 126k | case char_CR: |
550 | 129k | case char_EOL: |
551 | 129k | case char_NULL: |
552 | 129k | goto top; |
553 | 0 | case 0x04: /* see ctrld above */ |
554 | 0 | if (c == ctrld) /* treat as ordinary name char */ |
555 | 0 | goto begin_name; |
556 | | /* fall through */ |
557 | 3.45M | case '[': |
558 | 6.31M | case ']': |
559 | 6.31M | s1[0] = (byte) c; |
560 | 6.31M | retcode = name_ref(imemory, s1, 1, myref, 1); /* can't fail */ |
561 | 6.31M | r_set_attrs(myref, a_executable); |
562 | 6.31M | break; |
563 | 109k | case '<': |
564 | 109k | if (level2_enabled) { |
565 | 96.3k | ensure2(scanning_none); |
566 | 96.3k | c = sgetc_inline(s, sptr, endptr); |
567 | 96.3k | switch (c) { |
568 | 68.9k | case '<': |
569 | 68.9k | sputback_inline(s, sptr, endptr); |
570 | 68.9k | sstate.s_ss.s_name.s_name_type = 0; |
571 | 68.9k | sstate.s_ss.s_name.s_try_number = false; |
572 | 68.9k | goto try_funny_name; |
573 | 0 | case '~': |
574 | 0 | s_A85D_init_inline(&sstate.s_ss.a85d); |
575 | 0 | sstate.s_ss.st.templat = &s_A85D_template; |
576 | 0 | sstate.s_ss.a85d.require_eod = true; |
577 | | /* If this is an inline ASCII string, interpret it normally, throw an error |
578 | | * if it fails rather than ignoring it as PDF (Acrobat) does. |
579 | | */ |
580 | 0 | sstate.s_ss.a85d.pdf_rules = false; |
581 | 0 | goto str; |
582 | 96.3k | } |
583 | 27.3k | sputback_inline(s, sptr, endptr); |
584 | 27.3k | } |
585 | 40.9k | (void)s_AXD_init_inline(&sstate.s_ss.axd); |
586 | 40.9k | sstate.s_ss.st.templat = &s_AXD_template; |
587 | 1.27M | str:s_end_inline(s, sptr, endptr); |
588 | 1.27M | dynamic_init(&sstate.s_da, imemory); |
589 | 1.28M | cont_string:for (;;) { |
590 | 1.28M | stream_cursor_write w; |
591 | | |
592 | 1.28M | w.ptr = sstate.s_da.next - 1; |
593 | 1.28M | w.limit = sstate.s_da.limit - 1; |
594 | 1.28M | status = (*sstate.s_ss.st.templat->process) |
595 | 1.28M | (&sstate.s_ss.st, &s->cursor.r, &w, |
596 | 1.28M | s->end_status == EOFC); |
597 | 1.28M | if (!check_only) |
598 | 1.28M | sstate.s_da.next = w.ptr + 1; |
599 | 1.28M | switch (status) { |
600 | 4.16k | case 0: |
601 | 4.16k | status = s->end_status; |
602 | 4.16k | if (status < 0) { |
603 | 4 | if (status == EOFC) { |
604 | 4 | if (check_only) { |
605 | 0 | retcode = scan_Refill; |
606 | 0 | sstate.s_scan_type = scanning_string; |
607 | 0 | goto suspend; |
608 | 0 | } else |
609 | 4 | sreturn(gs_error_syntaxerror); |
610 | 0 | } |
611 | 0 | break; |
612 | 4 | } |
613 | 4.16k | s_process_read_buf(s); |
614 | 4.16k | continue; |
615 | 43 | case 1: |
616 | 43 | if (!check_only) { |
617 | 43 | retcode = dynamic_grow(&sstate.s_da, sstate.s_da.next, max_string_size); |
618 | 43 | if (retcode == gs_error_VMerror) { |
619 | 0 | sstate.s_scan_type = scanning_string; |
620 | 0 | goto suspend; |
621 | 43 | } else if (retcode < 0) |
622 | 43 | sreturn(retcode); |
623 | 43 | } |
624 | 43 | continue; |
625 | 1.28M | } |
626 | 1.27M | break; |
627 | 1.28M | } |
628 | 1.27M | s_begin_inline(s, sptr, endptr); |
629 | 1.27M | switch (status) { |
630 | 2 | default: |
631 | | /*case ERRC: */ |
632 | 2 | sreturn(gs_error_syntaxerror); |
633 | 0 | case INTC: |
634 | 0 | case CALLC: |
635 | 0 | sstate.s_scan_type = scanning_string; |
636 | 0 | goto pause; |
637 | 1.27M | case EOFC: |
638 | 1.27M | ; |
639 | 1.27M | } |
640 | 1.27M | retcode = dynamic_make_string(i_ctx_p, myref, &sstate.s_da, sstate.s_da.next); |
641 | 1.27M | if (retcode < 0) { /* VMerror */ |
642 | 0 | sputback(s); /* rescan ) */ |
643 | 0 | sstate.s_scan_type = scanning_string; |
644 | 0 | goto suspend; |
645 | 0 | } |
646 | 1.27M | break; |
647 | 1.27M | case '(': |
648 | 1.23M | sstate.s_ss.pssd.from_string = |
649 | 1.23M | ((pstate->s_options & SCAN_FROM_STRING) != 0) && |
650 | 1.23M | !level2_enabled; |
651 | 1.23M | s_PSSD_partially_init_inline(&sstate.s_ss.pssd); |
652 | 1.23M | sstate.s_ss.st.templat = &s_PSSD_template; |
653 | 1.23M | goto str; |
654 | 6.34M | case '{': |
655 | 6.34M | if (sstate.s_pstack == 0) { /* outermost procedure */ |
656 | 1.37M | if_not_spush1() { |
657 | 0 | sputback_inline(s, sptr, endptr); |
658 | 0 | sstate.s_scan_type = scanning_none; |
659 | 0 | goto pause_ret; |
660 | 0 | } |
661 | 1.37M | sstate.s_pdepth = ref_stack_count_inline(&o_stack); |
662 | 1.37M | } |
663 | 6.34M | make_int(osp, sstate.s_pstack); |
664 | 6.34M | sstate.s_pstack = ref_stack_count_inline(&o_stack); |
665 | 6.34M | if_debug3m('S', imemory, "[S{]d=%d, s=%d->%d\n", |
666 | 6.34M | sstate.s_pdepth, (int)osp->value.intval, sstate.s_pstack); |
667 | 6.34M | goto snext; |
668 | 68.9k | case '>': |
669 | 68.9k | if (level2_enabled) { |
670 | 68.9k | ensure2(scanning_none); |
671 | 68.9k | sstate.s_ss.s_name.s_name_type = 0; |
672 | 68.9k | sstate.s_ss.s_name.s_try_number = false; |
673 | 68.9k | goto try_funny_name; |
674 | 68.9k | } |
675 | | /* falls through */ |
676 | 0 | case ')': |
677 | 0 | sreturn(gs_error_syntaxerror); |
678 | 6.34M | case '}': |
679 | 6.34M | if (sstate.s_pstack == 0) |
680 | 6.34M | sreturn(gs_error_syntaxerror); |
681 | 6.34M | osp--; |
682 | 6.34M | { |
683 | 6.34M | uint size = ref_stack_count_inline(&o_stack) - sstate.s_pstack; |
684 | 6.34M | ref arr; |
685 | | |
686 | 6.34M | if_debug4m('S', imemory, "[S}]d=%"PRIu32", s=%"PRIu32"->%"PRIpsint", c=%"PRIu32"\n", |
687 | 6.34M | sstate.s_pdepth, sstate.s_pstack, |
688 | 6.34M | (sstate.s_pstack == sstate.s_pdepth ? 0 : |
689 | 6.34M | ref_stack_index(&o_stack, size)->value.intval), |
690 | 6.34M | size + sstate.s_pstack); |
691 | 6.34M | if (size > max_array_size) |
692 | 6.34M | sreturn(gs_error_limitcheck); |
693 | 6.34M | myref = (sstate.s_pstack == sstate.s_pdepth ? pref : &arr); |
694 | 6.34M | if (check_only) { |
695 | 0 | make_empty_array(myref, 0); |
696 | 0 | ref_stack_pop(&o_stack, size); |
697 | 6.34M | } else if (ref_array_packing.value.boolval) { |
698 | 6.25M | retcode = make_packed_array(myref, &o_stack, size, |
699 | 6.25M | idmemory, "scanner(packed)"); |
700 | 6.25M | if (retcode < 0) { /* must be VMerror */ |
701 | 0 | osp++; |
702 | 0 | sputback_inline(s, sptr, endptr); |
703 | 0 | sstate.s_scan_type = scanning_none; |
704 | 0 | goto pause_ret; |
705 | 0 | } |
706 | 6.25M | r_set_attrs(myref, a_executable); |
707 | 6.25M | } else { |
708 | 81.4k | retcode = ialloc_ref_array(myref, |
709 | 81.4k | a_executable + a_all, size, |
710 | 81.4k | "scanner(proc)"); |
711 | 81.4k | if (retcode < 0) { /* must be VMerror */ |
712 | 0 | osp++; |
713 | 0 | sputback_inline(s, sptr, endptr); |
714 | 0 | sstate.s_scan_type = scanning_none; |
715 | 0 | goto pause_ret; |
716 | 0 | } |
717 | 81.4k | retcode = ref_stack_store(&o_stack, myref, size, 0, 1, |
718 | 81.4k | false, idmemory, "scanner"); |
719 | 81.4k | if (retcode < 0) { |
720 | 0 | ifree_ref_array(myref, "scanner(proc)"); |
721 | 0 | sreturn(retcode); |
722 | 0 | } |
723 | 81.4k | ref_stack_pop(&o_stack, size); |
724 | 81.4k | } |
725 | 6.34M | if (sstate.s_pstack == sstate.s_pdepth) { /* This was the top-level procedure. */ |
726 | 1.37M | spop1(); |
727 | 1.37M | sstate.s_pstack = 0; |
728 | 4.96M | } else { |
729 | 4.96M | if (osp < osbot) |
730 | 0 | ref_stack_pop_block(&o_stack); |
731 | 4.96M | sstate.s_pstack = osp->value.intval; |
732 | 4.96M | *osp = arr; |
733 | 4.96M | goto snext; |
734 | 4.96M | } |
735 | 6.34M | } |
736 | 1.37M | break; |
737 | 15.3M | case '/': |
738 | | /* |
739 | | * If the last thing in the input is a '/', don't try to read |
740 | | * any more data. |
741 | | */ |
742 | 15.3M | if (sptr >= endptr && s->end_status != EOFC) { |
743 | 27 | refill2(scanning_none); |
744 | 27 | } |
745 | 15.3M | c = sgetc_inline(s, sptr, endptr); |
746 | 15.3M | if (!PDFScanRules && (c == '/')) { |
747 | 1.90M | sstate.s_ss.s_name.s_name_type = 2; |
748 | 1.90M | c = sgetc_inline(s, sptr, endptr); |
749 | 1.90M | } else |
750 | 13.4M | sstate.s_ss.s_name.s_name_type = 1; |
751 | 15.3M | sstate.s_ss.s_name.s_try_number = false; |
752 | 15.3M | switch (decoder[c]) { |
753 | 1.49M | case ctype_name: |
754 | 15.3M | default: |
755 | 15.3M | goto do_name; |
756 | 15.3M | case ctype_btoken: |
757 | 0 | if (!(ref_binary_object_format.value.intval != 0 && level2_enabled)) |
758 | 0 | goto do_name; |
759 | | /* otherwise, an empty name */ |
760 | 0 | case ctype_exception: |
761 | 683 | case ctype_space: |
762 | | /* |
763 | | * Amazingly enough, the Adobe implementations don't accept |
764 | | * / or // followed by [, ], <<, or >>, so we do the same. |
765 | | * (Older versions of our code had a ctype_other case here |
766 | | * that handled these specially.) |
767 | | */ |
768 | 683 | case ctype_other: |
769 | 683 | if (c == ctrld) /* see above */ |
770 | 0 | goto do_name; |
771 | 683 | sstate.s_da.base = sstate.s_da.limit = daptr = 0; |
772 | 683 | sstate.s_da.is_dynamic = false; |
773 | 683 | goto nx; |
774 | 15.3M | } |
775 | 6.74k | case '%': |
776 | 6.74k | { /* Scan as much as possible within the buffer. */ |
777 | 6.74k | const byte *base = sptr; |
778 | 6.74k | const byte *end; |
779 | | |
780 | 108k | while (++sptr < endptr) /* stop 1 char early */ |
781 | 108k | switch (*sptr) { |
782 | 563 | case char_CR: |
783 | 563 | end = sptr; |
784 | 563 | if (sptr[1] == char_EOL) |
785 | 563 | sptr++; |
786 | 6.72k | cend: /* Check for externally processed comments. */ |
787 | 6.72k | retcode = scan_comment(i_ctx_p, myref, &sstate, |
788 | 6.72k | base, end, false); |
789 | 6.72k | if (retcode != 0) |
790 | 42 | goto comment; |
791 | 6.68k | goto top; |
792 | 6.68k | case char_EOL: |
793 | 6.16k | case '\f': |
794 | 6.16k | end = sptr; |
795 | 6.16k | goto cend; |
796 | 108k | } |
797 | | /* |
798 | | * We got to the end of the buffer while inside a comment. |
799 | | * If there is a possibility that we must pass the comment |
800 | | * to an external procedure, move what we have collected |
801 | | * so far into a private buffer now. |
802 | | */ |
803 | 20 | --sptr; |
804 | 20 | sstate.s_da.buf[1] = 0; |
805 | 20 | { |
806 | | /* Could be an externally processable comment. */ |
807 | 20 | uint len = sptr + 1 - base; |
808 | 20 | if (len > sizeof(sstate.s_da.buf)) |
809 | 0 | len = sizeof(sstate.s_da.buf); |
810 | | |
811 | 20 | memcpy(sstate.s_da.buf, base, len); |
812 | 20 | daptr = sstate.s_da.buf + len; |
813 | 20 | } |
814 | 20 | sstate.s_da.base = sstate.s_da.buf; |
815 | 20 | sstate.s_da.is_dynamic = false; |
816 | 20 | } |
817 | | /* Enter here to continue scanning a comment. */ |
818 | | /* daptr must be set. */ |
819 | 590 | cont_comment:for (;;) { |
820 | 590 | switch ((c = sgetc_inline(s, sptr, endptr))) { |
821 | 570 | default: |
822 | 570 | if (c < 0) |
823 | 0 | switch (c) { |
824 | 0 | case INTC: |
825 | 0 | case CALLC: |
826 | 0 | sstate.s_da.next = daptr; |
827 | 0 | sstate.s_scan_type = scanning_comment; |
828 | 0 | goto pause; |
829 | 0 | case EOFC: |
830 | | /* |
831 | | * One would think that an EOF in a comment |
832 | | * should be a syntax error, but there are |
833 | | * quite a number of files that end that way. |
834 | | */ |
835 | 0 | goto end_comment; |
836 | 0 | default: |
837 | 0 | sreturn(gs_error_syntaxerror); |
838 | 0 | } |
839 | 570 | if (daptr < sstate.s_da.buf + max_comment_line) |
840 | 570 | *daptr++ = c; |
841 | 570 | continue; |
842 | 18 | case char_CR: |
843 | 20 | case char_EOL: |
844 | 20 | case '\f': |
845 | 20 | end_comment: |
846 | 20 | retcode = scan_comment(i_ctx_p, myref, &sstate, |
847 | 20 | sstate.s_da.buf, daptr, true); |
848 | 20 | if (retcode != 0) |
849 | 2 | goto comment; |
850 | 18 | goto top; |
851 | 590 | } |
852 | 590 | } |
853 | | /*NOTREACHED */ |
854 | 6.82k | case EOFC: |
855 | 6.82k | if (sstate.s_pstack != 0) { |
856 | 0 | if (check_only) |
857 | 0 | goto pause; |
858 | 0 | sreturn(gs_error_syntaxerror); |
859 | 0 | } |
860 | 6.82k | retcode = scan_EOF; |
861 | 6.82k | break; |
862 | 0 | case ERRC: |
863 | 0 | sreturn(gs_error_ioerror); |
864 | | |
865 | | /* Check for a Level 2 funny name (<< or >>). */ |
866 | | /* c is '<' or '>'. We already did an ensure2. */ |
867 | 137k | try_funny_name: |
868 | 137k | { |
869 | 137k | int c1 = sgetc_inline(s, sptr, endptr); |
870 | | |
871 | 137k | if (c1 == c) { |
872 | 137k | s1[0] = s1[1] = c; |
873 | 137k | name_ref(imemory, s1, 2, myref, 1); /* can't fail */ |
874 | 137k | goto have_name; |
875 | 137k | } |
876 | 0 | sputback_inline(s, sptr, endptr); |
877 | 0 | } |
878 | 0 | sreturn(gs_error_syntaxerror); |
879 | | |
880 | | /* Handle separately the names that might be a number. */ |
881 | 1.21M | case '0': |
882 | 8.61M | case '1': |
883 | 9.73M | case '2': |
884 | 10.6M | case '3': |
885 | 11.1M | case '4': |
886 | 11.3M | case '5': |
887 | 11.5M | case '6': |
888 | 11.6M | case '7': |
889 | 11.7M | case '8': |
890 | 11.7M | case '9': |
891 | 13.7M | case '.': |
892 | 13.7M | sign = 0; |
893 | 14.2M | nr: /* |
894 | | * Skip a leading sign, if any, by conditionally passing |
895 | | * sptr + 1 rather than sptr. Also, if the last character |
896 | | * in the buffer is a CR, we must stop the scan 1 character |
897 | | * early, to be sure that we can test for CR+LF within the |
898 | | * buffer, by passing endptr rather than endptr + 1. |
899 | | */ |
900 | 14.2M | retcode = scan_number(sptr + (sign & 1), |
901 | 14.2M | endptr /*(*endptr == char_CR ? endptr : endptr + 1) */ , |
902 | 14.2M | sign, myref, &newptr, i_ctx_p->scanner_options); |
903 | 14.2M | if (retcode == 1 && decoder[newptr[-1]] == ctype_space) { |
904 | 6.30M | sptr = newptr - 1; |
905 | 6.30M | if (*sptr == char_CR && sptr[1] == char_EOL) |
906 | 0 | sptr++; |
907 | 6.30M | retcode = 0; |
908 | 6.30M | ref_mark_new(myref); |
909 | 6.30M | break; |
910 | 6.30M | } |
911 | 7.91M | sstate.s_ss.s_name.s_name_type = 0; |
912 | 7.91M | sstate.s_ss.s_name.s_try_number = true; |
913 | 7.91M | goto do_name; |
914 | 0 | case '+': |
915 | 0 | sign = 1; |
916 | 0 | goto nr; |
917 | 437k | case '-': |
918 | 437k | sign = -1; |
919 | 437k | if(i_ctx_p->scanner_options & SCAN_PDF_INV_NUM) { |
920 | 0 | const byte *osptr = sptr; |
921 | 0 | do { |
922 | | /* This is slightly unpleasant: we have to bounds check the buffer, |
923 | | rather than just incrementing the point until we find a non '-' character. |
924 | | But we cannot differentiate between multiple '-' characters that |
925 | | straddle a buffer boundary, or a token that is only one or more '-' characters. |
926 | | Handling this relies on the fact that the Postscript-based PDF interpreter |
927 | | always uses the "token" operator to tokenize a stream, thus we can assume |
928 | | here that the current buffer contains the entire token. So if we reach |
929 | | the end of the buffer without hitting a character taht is not a '-', we'll reset |
930 | | the buffer pointer, and retry, treating it as a name object. |
931 | | */ |
932 | 0 | if (sptr + 1 > endptr) { |
933 | 0 | sptr = osptr; |
934 | 0 | sstate.s_ss.s_name.s_name_type = 0; |
935 | 0 | sstate.s_ss.s_name.s_try_number = true; |
936 | 0 | goto do_name; |
937 | 0 | } |
938 | 0 | if (*(sptr + 1) == '-') { |
939 | 0 | sptr++; |
940 | 0 | } else |
941 | 0 | break; |
942 | 0 | } while (1); |
943 | 0 | } |
944 | 437k | goto nr; |
945 | | |
946 | | /* Check for a binary object */ |
947 | 437k | case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: |
948 | 0 | case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: |
949 | 0 | case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: |
950 | 0 | case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: |
951 | 0 | if ((ref_binary_object_format.value.intval != 0 && level2_enabled)) { |
952 | 0 | s_end_inline(s, sptr, endptr); |
953 | 0 | retcode = scan_binary_token(i_ctx_p, myref, &sstate); |
954 | 0 | s_begin_inline(s, sptr, endptr); |
955 | 0 | if (retcode == scan_Refill) |
956 | 0 | goto pause; |
957 | 0 | break; |
958 | 0 | } |
959 | | /* Not a binary object, fall through. */ |
960 | | |
961 | | /* The default is a name. */ |
962 | 3.41k | default: |
963 | 3.41k | if (c < 0) { |
964 | 3.41k | dynamic_init(&sstate.s_da, name_memory(imemory)); /* sstate.s_da state must be clean */ |
965 | 3.41k | sstate.s_scan_type = scanning_none; |
966 | 3.41k | goto pause; |
967 | 3.41k | } |
968 | | /* Populate the switch with enough cases to force */ |
969 | | /* simple compilers to use a dispatch rather than tests. */ |
970 | 4 | case '!': |
971 | 871 | case '"': |
972 | 1.55k | case '#': |
973 | 88.2k | case '$': |
974 | 88.2k | case '&': |
975 | 88.9k | case '\'': |
976 | 88.9k | case '*': |
977 | 89.0k | case ',': |
978 | 330k | case '=': |
979 | 330k | case ':': |
980 | 466k | case ';': |
981 | 466k | case '?': |
982 | 466k | case '@': |
983 | 473k | case 'A': |
984 | 494k | case 'B': |
985 | 557k | case 'C': |
986 | 598k | case 'D': |
987 | 629k | case 'E': |
988 | 675k | case 'F': |
989 | 699k | case 'G': |
990 | 716k | case 'H': |
991 | 744k | case 'I': |
992 | 747k | case 'J': |
993 | 748k | case 'K': |
994 | 759k | case 'L': |
995 | 782k | case 'M': |
996 | 801k | case 'N': |
997 | 854k | case 'O': |
998 | 1.10M | case 'P': |
999 | 1.14M | case 'Q': |
1000 | 1.18M | case 'R': |
1001 | 1.24M | case 'S': |
1002 | 1.36M | case 'T': |
1003 | 1.37M | case 'U': |
1004 | 1.40M | case 'V': |
1005 | 1.42M | case 'W': |
1006 | 1.42M | case 'X': |
1007 | 1.42M | case 'Y': |
1008 | 1.42M | case 'Z': |
1009 | 1.42M | case '\\': |
1010 | 1.42M | case '^': |
1011 | 1.42M | case '_': |
1012 | 1.42M | case '`': |
1013 | 2.34M | case 'a': |
1014 | 3.57M | case 'b': |
1015 | 5.24M | case 'c': |
1016 | 9.58M | case 'd': |
1017 | 14.1M | case 'e': |
1018 | 14.9M | case 'f': |
1019 | 16.3M | case 'g': |
1020 | 16.3M | case 'h': |
1021 | 20.7M | case 'i': |
1022 | 20.8M | case 'j': |
1023 | 21.3M | case 'k': |
1024 | 22.1M | case 'l': |
1025 | 22.6M | case 'm': |
1026 | 23.5M | case 'n': |
1027 | 23.9M | case 'o': |
1028 | 27.8M | case 'p': |
1029 | 27.8M | case 'q': |
1030 | 29.1M | case 'r': |
1031 | 30.8M | case 's': |
1032 | 31.2M | case 't': |
1033 | 31.3M | case 'u': |
1034 | 31.3M | case 'v': |
1035 | 31.5M | case 'w': |
1036 | 31.6M | case 'x': |
1037 | 31.6M | case 'y': |
1038 | 31.6M | case 'z': |
1039 | 31.6M | case '|': |
1040 | 31.6M | case '~': |
1041 | 31.6M | begin_name: |
1042 | | /* Common code for scanning a name. */ |
1043 | | /* sstate.s_ss.s_name.s_try_number and sstate.s_ss.s_name.s_name_type are already set. */ |
1044 | | /* We know c has ctype_name (or maybe ctype_btoken, */ |
1045 | | /* or is ^D) or is a digit. */ |
1046 | 31.6M | sstate.s_ss.s_name.s_name_type = 0; |
1047 | 31.6M | sstate.s_ss.s_name.s_try_number = false; |
1048 | 54.8M | do_name: |
1049 | | /* Try to scan entirely within the stream buffer. */ |
1050 | | /* We stop 1 character early, so we don't switch buffers */ |
1051 | | /* looking ahead if the name is terminated by \r\n. */ |
1052 | 54.8M | sstate.s_da.base = (byte *) sptr; |
1053 | 54.8M | sstate.s_da.is_dynamic = false; |
1054 | 54.8M | { |
1055 | 54.8M | const byte *endp1 = endptr - 1; |
1056 | | |
1057 | 377M | do { |
1058 | 377M | if (sptr >= endp1) /* stop 1 early! */ |
1059 | 35.9k | goto dyn_name; |
1060 | 377M | } |
1061 | 377M | while (decoder[*++sptr] <= max_name_ctype || *sptr == ctrld); /* digit or name */ |
1062 | 54.8M | } |
1063 | | /* Name ended within the buffer. */ |
1064 | 54.8M | daptr = (byte *) sptr; |
1065 | 54.8M | c = *sptr; |
1066 | 54.8M | goto nx; |
1067 | 35.9k | dyn_name: /* Name extended past end of buffer. */ |
1068 | 35.9k | s_end_inline(s, sptr, endptr); |
1069 | | /* Initialize the dynamic area. */ |
1070 | | /* We have to do this before the next */ |
1071 | | /* sgetc, which will overwrite the buffer. */ |
1072 | 35.9k | sstate.s_da.limit = (byte *)++ sptr; |
1073 | 35.9k | sstate.s_da.memory = name_memory(imemory); |
1074 | 35.9k | retcode = dynamic_grow(&sstate.s_da, sstate.s_da.limit, name_max_string); |
1075 | 35.9k | if (retcode < 0) { |
1076 | 0 | dynamic_save(&sstate.s_da); |
1077 | 0 | if (retcode != gs_error_VMerror) |
1078 | 0 | sreturn(retcode); |
1079 | 0 | sstate.s_scan_type = scanning_name; |
1080 | 0 | goto pause_ret; |
1081 | 0 | } |
1082 | 35.9k | daptr = sstate.s_da.next; |
1083 | | /* Enter here to continue scanning a name. */ |
1084 | | /* daptr must be set. */ |
1085 | 38.6k | cont_name:s_begin_inline(s, sptr, endptr); |
1086 | 192k | while (decoder[c = sgetc_inline(s, sptr, endptr)] <= max_name_ctype || c == ctrld) { |
1087 | 153k | if (daptr == sstate.s_da.limit) { |
1088 | 725 | retcode = dynamic_grow(&sstate.s_da, daptr, |
1089 | 725 | name_max_string); |
1090 | 725 | if (retcode < 0) { |
1091 | 1 | dynamic_save(&sstate.s_da); |
1092 | 1 | if (retcode != gs_error_VMerror) |
1093 | 1 | sreturn(retcode); |
1094 | 0 | sputback_inline(s, sptr, endptr); |
1095 | 0 | sstate.s_scan_type = scanning_name; |
1096 | 0 | goto pause_ret; |
1097 | 1 | } |
1098 | 724 | daptr = sstate.s_da.next; |
1099 | 724 | } |
1100 | 153k | *daptr++ = c; |
1101 | 153k | } |
1102 | 54.8M | nx:switch (decoder[c]) { |
1103 | 28.6M | case ctype_other: |
1104 | 28.6M | if (c == ctrld) /* see above */ |
1105 | 0 | break; |
1106 | 28.6M | case ctype_btoken: |
1107 | 28.6M | sputback_inline(s, sptr, endptr); |
1108 | 28.6M | break; |
1109 | 26.2M | case ctype_space: |
1110 | | /* Check for \r\n */ |
1111 | 26.2M | if (c == char_CR) { |
1112 | 1.65k | if (sptr >= endptr) { /* ensure2 *//* We have to check specially for */ |
1113 | | /* the case where the very last */ |
1114 | | /* character of a file is a CR. */ |
1115 | 0 | if (s->end_status != EOFC) { |
1116 | 0 | sptr--; |
1117 | 0 | goto pause_name; |
1118 | 0 | } |
1119 | 1.65k | } else if (sptr[1] == char_EOL) |
1120 | 210 | sptr++; |
1121 | 1.65k | } |
1122 | 26.2M | break; |
1123 | 26.2M | case ctype_exception: |
1124 | 12.2k | switch (c) { |
1125 | 0 | case INTC: |
1126 | 2.73k | case CALLC: |
1127 | 2.73k | goto pause_name; |
1128 | 0 | case ERRC: |
1129 | 0 | sreturn(gs_error_ioerror); |
1130 | 9.56k | case EOFC: |
1131 | 9.56k | break; |
1132 | 12.2k | } |
1133 | 54.8M | } |
1134 | | /* Check for a number */ |
1135 | 54.8M | if (sstate.s_ss.s_name.s_try_number) { |
1136 | 7.91M | const byte *base = sstate.s_da.base; |
1137 | | |
1138 | 7.91M | scan_sign(sign, base); |
1139 | 7.91M | retcode = scan_number(base, daptr, sign, myref, &newptr, i_ctx_p->scanner_options); |
1140 | 7.91M | if (retcode == 1) { |
1141 | 3.36k | ref_mark_new(myref); |
1142 | 3.36k | retcode = 0; |
1143 | 7.91M | } else if (retcode != gs_error_syntaxerror) { |
1144 | 5.93M | dynamic_free(&sstate.s_da); |
1145 | 5.93M | if (sstate.s_ss.s_name.s_name_type == 2) |
1146 | 5.93M | sreturn(gs_error_syntaxerror); |
1147 | 5.93M | break; /* might be gs_error_limitcheck */ |
1148 | 5.93M | } |
1149 | 7.91M | } |
1150 | 48.9M | if (sstate.s_da.is_dynamic) { /* We've already allocated the string on the heap. */ |
1151 | 33.7k | uint size = daptr - sstate.s_da.base; |
1152 | | |
1153 | 33.7k | retcode = name_ref(imemory, sstate.s_da.base, size, myref, -1); |
1154 | 33.7k | if (retcode >= 0) { |
1155 | 29.6k | dynamic_free(&sstate.s_da); |
1156 | 29.6k | } else { |
1157 | 4.10k | retcode = dynamic_resize(&sstate.s_da, size); |
1158 | 4.10k | if (retcode < 0) { /* VMerror */ |
1159 | 0 | if (c != EOFC) |
1160 | 0 | sputback_inline(s, sptr, endptr); |
1161 | 0 | sstate.s_scan_type = scanning_name; |
1162 | 0 | goto pause_ret; |
1163 | 0 | } |
1164 | 4.10k | retcode = name_ref(imemory, sstate.s_da.base, size, myref, 2); |
1165 | 4.10k | } |
1166 | 48.8M | } else { |
1167 | 48.8M | retcode = name_ref(imemory, sstate.s_da.base, (uint) (daptr - sstate.s_da.base), |
1168 | 48.8M | myref, !s->foreign); |
1169 | 48.8M | } |
1170 | | /* Done scanning. Check for preceding /'s. */ |
1171 | 48.9M | if (retcode < 0) { |
1172 | 0 | if (retcode != gs_error_VMerror) |
1173 | 0 | sreturn(retcode); |
1174 | 0 | if (!sstate.s_da.is_dynamic) { |
1175 | 0 | sstate.s_da.next = daptr; |
1176 | 0 | dynamic_save(&sstate.s_da); |
1177 | 0 | } |
1178 | 0 | if (c != EOFC) |
1179 | 0 | sputback_inline(s, sptr, endptr); |
1180 | 0 | sstate.s_scan_type = scanning_name; |
1181 | 0 | goto pause_ret; |
1182 | 0 | } |
1183 | 49.0M | have_name:switch (sstate.s_ss.s_name.s_name_type) { |
1184 | 33.7M | case 0: /* ordinary executable name */ |
1185 | 33.7M | if (r_has_type(myref, t_name)) /* i.e., not a number */ |
1186 | 33.7M | r_set_attrs(myref, a_executable); |
1187 | 47.1M | case 1: /* quoted name */ |
1188 | 47.1M | break; |
1189 | 1.90M | case 2: /* immediate lookup */ |
1190 | 1.90M | { |
1191 | 1.90M | ref *pvalue; |
1192 | | |
1193 | 1.90M | if (!r_has_type(myref, t_name) || |
1194 | 1.90M | (pvalue = dict_find_name(myref)) == 0) { |
1195 | 0 | ref_assign(&sstate.s_error.object, myref); |
1196 | 0 | r_set_attrs(&sstate.s_error.object, |
1197 | 0 | a_executable); /* Adobe compatibility */ |
1198 | 0 | sreturn(gs_error_undefined); |
1199 | 0 | } |
1200 | 1.90M | if (sstate.s_pstack != 0 && |
1201 | 1.90M | r_space(pvalue) > ialloc_space(idmemory) |
1202 | 1.90M | ) |
1203 | 1.90M | sreturn(gs_error_invalidaccess); |
1204 | 1.90M | ref_assign_new(myref, pvalue); |
1205 | 1.90M | } |
1206 | 49.0M | } |
1207 | 81.7M | } |
1208 | 70.2M | sret:if (retcode < 0) { |
1209 | 7 | s_end_inline(s, sptr, endptr); |
1210 | 7 | pstate->s_error = sstate.s_error; |
1211 | 7 | if (sstate.s_pstack != 0) { |
1212 | 3 | if (retcode == gs_error_undefined) |
1213 | 0 | *pref = *osp; /* return undefined name as error token */ |
1214 | 3 | ref_stack_pop(&o_stack, |
1215 | 3 | ref_stack_count(&o_stack) - (sstate.s_pdepth - 1)); |
1216 | 3 | } |
1217 | 7 | return retcode; |
1218 | 7 | } |
1219 | | /* If we are at the top level, return the object, */ |
1220 | | /* otherwise keep going. */ |
1221 | 70.2M | if (sstate.s_pstack == 0) { |
1222 | 28.4M | s_end_inline(s, sptr, endptr); |
1223 | 28.4M | return retcode; |
1224 | 28.4M | } |
1225 | 53.1M | snext:if_not_spush1() { |
1226 | 0 | s_end_inline(s, sptr, endptr); |
1227 | 0 | sstate.s_scan_type = scanning_none; |
1228 | 0 | goto save; |
1229 | 0 | } |
1230 | 53.1M | myref = osp; |
1231 | 53.1M | goto top; |
1232 | | |
1233 | | /* Pause for an interrupt or callout. */ |
1234 | 2.73k | pause_name: |
1235 | | /* If we're still scanning within the stream buffer, */ |
1236 | | /* move the characters to the private buffer (sstate.s_da.buf) now. */ |
1237 | 2.73k | sstate.s_da.next = daptr; |
1238 | 2.73k | dynamic_save(&sstate.s_da); |
1239 | 2.73k | sstate.s_scan_type = scanning_name; |
1240 | 6.17k | pause: |
1241 | 6.17k | retcode = scan_Refill; |
1242 | 6.17k | pause_ret: |
1243 | 6.17k | s_end_inline(s, sptr, endptr); |
1244 | 6.17k | suspend: |
1245 | 6.17k | if (sstate.s_pstack != 0) |
1246 | 0 | osp--; /* myref */ |
1247 | 6.21k | save: |
1248 | 6.21k | *pstate = sstate; |
1249 | 6.21k | return retcode; |
1250 | | |
1251 | | /* Handle a scanned comment. */ |
1252 | 44 | comment: |
1253 | 44 | if (retcode < 0) |
1254 | 0 | goto sret; |
1255 | 44 | s_end_inline(s, sptr, endptr); |
1256 | 44 | sstate.s_scan_type = scanning_none; |
1257 | 44 | goto save; |
1258 | 44 | } |