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