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 /* Implementation of FunctionType 4 (PostScript Calculator) Functions */
18 #include "math_.h"
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gsdsrc.h"
23 #include "gsfunc4.h"
24 #include "gxfarith.h"
25 #include "gxfunc.h"
26 #include "stream.h"
27 #include "strimpl.h"
28 #include "sfilter.h"		/* for SubFileDecode */
29 #include "spprint.h"
30 #include "stream.h"
31 
32 typedef struct gs_function_PtCr_s {
33     gs_function_head_t head;
34     gs_function_PtCr_params_t params;
35     /* Define a bogus DataSource for get_function_info. */
36     gs_data_source_t data_source;
37 } gs_function_PtCr_t;
38 
39 /* GC descriptor */
40 private_st_function_PtCr();
41 
42 /* Define the maximum stack depth. */
43 #define MAX_VSTACK 256		/* Max 100 is enough per PDF spec, but we use this
44                                  * for DeviceN handling. Must be at least as large
45                                  * as the number of components
46                                  */
47 
48 /* Define the structure of values on the stack. */
49 typedef enum {
50     CVT_NONE = 0,	/* empty stack slot */
51     CVT_BOOL,
52     CVT_INT,
53     CVT_FLOAT
54 } calc_value_type_t;
55 typedef struct calc_value_s {
56     calc_value_type_t type;
57     union {
58         int i;			/* also used for Boolean */
59         float f;
60     } value;
61 } calc_value_t;
62 
63 /* Store a float. */
64 static inline void
store_float(calc_value_t * vsp,double f)65 store_float(calc_value_t *vsp, double f)
66 {
67     vsp->value.f = f;
68     vsp->type = CVT_FLOAT;
69 }
70 
71 /*
72  * Define extended opcodes with typed operands.  We use the original
73  * opcodes for the floating-point case.
74  */
75 typedef enum {
76 
77         /* Typed variants */
78 
79     PtCr_abs_int = PtCr_NUM_OPCODES,
80     PtCr_add_int,
81     PtCr_mul_int,
82     PtCr_neg_int,
83     PtCr_not_bool,		/* default is int */
84     PtCr_sub_int,
85     PtCr_eq_int,
86     PtCr_ge_int,
87     PtCr_gt_int,
88     PtCr_le_int,
89     PtCr_lt_int,
90     PtCr_ne_int,
91 
92         /* Coerce and re-dispatch */
93 
94     PtCr_int_to_float,
95     PtCr_2nd_int_to_float,
96     PtCr_int2_to_float,
97 
98         /* Miscellaneous */
99 
100     PtCr_no_op,
101     PtCr_typecheck
102 
103 } gs_PtCr_typed_opcode_t;
104 
105 /* Evaluate a PostScript Calculator function. */
106 static int
fn_PtCr_evaluate(const gs_function_t * pfn_common,const float * in,float * out)107 fn_PtCr_evaluate(const gs_function_t *pfn_common, const float *in, float *out)
108 {
109     const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110     calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111     calc_value_t *vstack = &vstack_buf[1];
112     calc_value_t *vsp = vstack + pfn->params.m;
113     const byte *p = pfn->params.ops.data;
114     int repeat_count[MAX_PSC_FUNCTION_NESTING];
115     int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116     int repeat_nesting_level = -1;
117     int i;
118 
119     /*
120      * Define the table for mapping explicit opcodes to typed opcodes.
121      * We index this table with the opcode and the types of the top 2
122      * values on the stack.
123      */
124     static const struct op_defn_s {
125         byte opcode[16];	/* 4 * type[-1] + type[0] */
126     } op_defn_table[] = {
127         /* Keep this consistent with opcodes in gsfunc4.h! */
128 
129 #define O4(op) op,op,op,op
130 #define E PtCr_typecheck
131 #define E4 O4(E)
132 #define N PtCr_no_op
133         /* 0-operand operators */
134 #define OP_NONE(op)\
135   {{O4(op), O4(op), O4(op), O4(op)}}
136         /* 1-operand operators */
137 #define OP1(b, i, f)\
138   {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139 #define OP_NUM1(i, f)\
140   OP1(E, i, f)
141 #define OP_MATH1(f)\
142   OP1(E, PtCr_int_to_float, f)
143 #define OP_ANY1(op)\
144   OP1(op, op, op)
145         /* 2-operand operators */
146 #define OP_NUM2(i, f)\
147   {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148 #define OP_INT_BOOL2(i)\
149   {{E4, E,i,i,E, E,i,i,E, E4}}
150 #define OP_MATH2(f)\
151   {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152     E,E,PtCr_int_to_float,f}}
153 #define OP_INT2(i)\
154   {{E4, E4, E,E,i,E, E4}}
155 #define OP_REL2(i, f)\
156   {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157 #define OP_ANY2(op)\
158   {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159 
160     /* Arithmetic operators */
161 
162         OP_NUM1(PtCr_abs_int, PtCr_abs),	/* abs */
163         OP_NUM2(PtCr_add_int, PtCr_add),	/* add */
164         OP_INT_BOOL2(PtCr_and),  /* and */
165         OP_MATH2(PtCr_atan),	/* atan */
166         OP_INT2(PtCr_bitshift),	/* bitshift */
167         OP_NUM1(N, PtCr_ceiling),	/* ceiling */
168         OP_MATH1(PtCr_cos),	/* cos */
169         OP_NUM1(N, PtCr_cvi),	/* cvi */
170         OP_NUM1(PtCr_int_to_float, N),	/* cvr */
171         OP_MATH2(PtCr_div),	/* div */
172         OP_MATH2(PtCr_exp),	/* exp */
173         OP_NUM1(N, PtCr_floor),	/* floor */
174         OP_INT2(PtCr_idiv),	/* idiv */
175         OP_MATH1(PtCr_ln),	/* ln */
176         OP_MATH1(PtCr_log),	/* log */
177         OP_INT2(PtCr_mod),	/* mod */
178         OP_NUM2(PtCr_mul_int, PtCr_mul),	/* mul */
179         OP_NUM1(PtCr_neg_int, PtCr_neg),	/* neg */
180         OP1(PtCr_not, PtCr_not, E),	/* not */
181         OP_INT_BOOL2(PtCr_or),  /* or */
182         OP_NUM1(N, PtCr_round),	/* round */
183         OP_MATH1(PtCr_sin),	/* sin */
184         OP_MATH1(PtCr_sqrt),	/* sqrt */
185         OP_NUM2(PtCr_sub_int, PtCr_sub),	/* sub */
186         OP_NUM1(N, PtCr_truncate),	/* truncate */
187         OP_INT_BOOL2(PtCr_xor),  /* xor */
188 
189     /* Comparison operators */
190 
191         OP_REL2(PtCr_eq_int, PtCr_eq),	/* eq */
192         OP_NUM2(PtCr_ge_int, PtCr_ge),	/* ge */
193         OP_NUM2(PtCr_gt_int, PtCr_gt),	/* gt */
194         OP_NUM2(PtCr_le_int, PtCr_le),	/* le */
195         OP_NUM2(PtCr_lt_int, PtCr_lt),	/* lt */
196         OP_REL2(PtCr_ne_int, PtCr_ne),	/* ne */
197 
198     /* Stack operators */
199 
200         OP1(E, PtCr_copy, E),	/* copy */
201         OP_ANY1(PtCr_dup),	/* dup */
202         OP_ANY2(PtCr_exch),	/* exch */
203         OP1(E, PtCr_index, E),	/* index */
204         OP_ANY1(PtCr_pop),	/* pop */
205         OP_INT2(PtCr_roll),	/* roll */
206 
207     /* Constants */
208 
209         OP_NONE(PtCr_byte),		/* byte */
210         OP_NONE(PtCr_int),		/* int */
211         OP_NONE(PtCr_float),		/* float */
212         OP_NONE(PtCr_true),		/* true */
213         OP_NONE(PtCr_false),		/* false */
214 
215     /* Special */
216 
217         OP1(PtCr_if, E, E),		/* if */
218         OP_NONE(PtCr_else),		/* else */
219         OP_NONE(PtCr_return),		/* return */
220         OP1(E, PtCr_repeat, E),		/* repeat */
221         OP_NONE(PtCr_repeat_end)	/* repeat_end */
222     };
223 
224     memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225     memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226 
227     vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228     vstack[0].type = CVT_NONE;	/* catch underflow */
229     for (i = 0; i < pfn->params.m; ++i)
230         store_float(&vstack[i + 1], in[i]);
231 
232     for (; ; ) {
233         int code, n;
234 
235     sw:
236         switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
237 
238             /* Miscellaneous */
239 
240         case PtCr_no_op:
241             continue;
242         case PtCr_typecheck:
243             return_error(gs_error_typecheck);
244 
245             /* Coerce and re-dispatch */
246 
247         case PtCr_int_to_float:
248             store_float(vsp, (double)vsp->value.i);
249             --p; goto sw;
250         case PtCr_int2_to_float:
251             store_float(vsp, (double)vsp->value.i);
252             /* fall through */
253         case PtCr_2nd_int_to_float:
254             store_float(vsp - 1, (double)vsp[-1].value.i);
255             --p; goto sw;
256 
257             /* Arithmetic operators */
258 
259         case PtCr_abs_int:
260             if (vsp->value.i < 0)
261                 goto neg_int;
262             continue;
263         case PtCr_abs:
264             vsp->value.f = fabs(vsp->value.f);
265             continue;
266         case PtCr_add_int: {
267             int int1 = vsp[-1].value.i, int2 = vsp->value.i;
268 
269             if ((int1 ^ int2) >= 0 && ((int1 + int2) ^ int1) < 0)
270                 store_float(vsp - 1, (double)int1 + int2);
271             else
272                 vsp[-1].value.i = int1 + int2;
273             --vsp; continue;
274         }
275         case PtCr_add:
276             vsp[-1].value.f += vsp->value.f;
277             --vsp; continue;
278         case PtCr_and:
279             vsp[-1].value.i &= vsp->value.i;
280             --vsp; continue;
281         case PtCr_atan: {
282             double result;
283 
284             code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
285                                     &result);
286             if (code < 0)
287                 return code;
288             vsp[-1].value.f = result;
289             --vsp; continue;
290         }
291         case PtCr_bitshift:
292 #define MAX_SHIFT (ARCH_SIZEOF_INT * 8 - 1)
293             if (vsp->value.i < -MAX_SHIFT || vsp->value.i > MAX_SHIFT)
294                 vsp[-1].value.i = 0;
295 #undef MAX_SHIFT
296             else if ((n = vsp->value.i) < 0)
297                 vsp[-1].value.i = ((uint)(vsp[-1].value.i)) >> -n;
298             else
299                 vsp[-1].value.i <<= n;
300             --vsp; continue;
301         case PtCr_ceiling:
302             vsp->value.f = ceil(vsp->value.f);
303             continue;
304         case PtCr_cos:
305             vsp->value.f = gs_cos_degrees(vsp->value.f);
306             continue;
307         case PtCr_cvi:
308         {
309            /* Strictly speaking assigning one element of union
310             * to another, overlapping element of a different size is
311             * undefined behavior, hence assign to an intermediate variable
312             */
313             int int1 = (int)(vsp->value.f);
314             vsp->value.i = int1;
315             vsp->type = CVT_INT;
316             continue;
317         }
318         case PtCr_cvr:
319             continue;	/* prepare handled it */
320         case PtCr_div:
321             if (vsp->value.f == 0)
322                 return_error(gs_error_undefinedresult);
323             vsp[-1].value.f /= vsp->value.f;
324             --vsp; continue;
325         case PtCr_exp:
326             vsp[-1].value.f = pow(vsp[-1].value.f, vsp->value.f);
327             --vsp; continue;
328         case PtCr_floor:
329             vsp->value.f = floor(vsp->value.f);
330             continue;
331         case PtCr_idiv:
332             if (vsp->value.i == 0)
333                 return_error(gs_error_undefinedresult);
334             if ((vsp[-1].value.i /= vsp->value.i) == min_int &&
335                 vsp->value.i == -1)  /* anomalous boundary case, fail */
336                 return_error(gs_error_rangecheck);
337             --vsp; continue;
338         case PtCr_ln:
339             vsp->value.f = log(vsp->value.f);
340             continue;
341         case PtCr_log:
342             vsp->value.f = log10(vsp->value.f);
343             continue;
344         case PtCr_mod:
345             if (vsp->value.i == 0)
346                 return_error(gs_error_undefinedresult);
347             vsp[-1].value.i %= vsp->value.i;
348             --vsp; continue;
349         case PtCr_mul_int: {
350             /* We don't bother to optimize this. */
351             double prod = (double)vsp[-1].value.i * vsp->value.i;
352 
353             if (prod < min_int || prod > max_int)
354                 store_float(vsp - 1, prod);
355             else
356                 vsp[-1].value.i = (int)prod;
357             --vsp; continue;
358         }
359         case PtCr_mul:
360             vsp[-1].value.f *= vsp->value.f;
361             --vsp; continue;
362         case PtCr_neg_int:
363         neg_int:
364             if (vsp->value.i == min_int)
365                 store_float(vsp, (double)vsp->value.i); /* =self negated */
366             else
367                 vsp->value.i = -vsp->value.i;
368             continue;
369         case PtCr_neg:
370             vsp->value.f = -vsp->value.f;
371             continue;
372         case PtCr_not_bool:
373             vsp->value.i = !vsp->value.i;
374             continue;
375         case PtCr_not:
376             vsp->value.i = ~vsp->value.i;
377             continue;
378         case PtCr_or:
379             vsp[-1].value.i |= vsp->value.i;
380             --vsp; continue;
381         case PtCr_round:
382             vsp->value.f = floor(vsp->value.f + 0.5);
383             continue;
384         case PtCr_sin:
385             vsp->value.f = gs_sin_degrees(vsp->value.f);
386             continue;
387         case PtCr_sqrt:
388             vsp->value.f = sqrt(vsp->value.f);
389             continue;
390         case PtCr_sub_int: {
391             int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392 
393             if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394                 store_float(vsp - 1, (double)int1 - int2);
395             else
396                 vsp[-1].value.i = int1 - int2;
397             --vsp; continue;
398         }
399         case PtCr_sub:
400             vsp[-1].value.f -= vsp->value.f;
401             --vsp; continue;
402         case PtCr_truncate:
403             vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
404                             floor(vsp->value.f));
405             continue;
406         case PtCr_xor:
407             vsp[-1].value.i ^= vsp->value.i;
408             --vsp; continue;
409 
410             /* Boolean operators */
411 
412 #define DO_REL(rel, m)\
413   vsp[-1].value.i = vsp[-1].value.m rel vsp->value.m
414 
415         case PtCr_eq_int:
416             DO_REL(==, i);
417             goto rel;
418         case PtCr_eq:
419             DO_REL(==, f);
420         rel:
421             vsp[-1].type = CVT_BOOL;
422             --vsp; continue;
423         case PtCr_ge_int:
424             DO_REL(>=, i);
425             goto rel;
426         case PtCr_ge:
427             DO_REL(>=, f);
428             goto rel;
429         case PtCr_gt_int:
430             DO_REL(>, i);
431             goto rel;
432         case PtCr_gt:
433             DO_REL(>, f);
434             goto rel;
435         case PtCr_le_int:
436             DO_REL(<=, i);
437             goto rel;
438         case PtCr_le:
439             DO_REL(<=, f);
440             goto rel;
441         case PtCr_lt_int:
442             DO_REL(<, i);
443             goto rel;
444         case PtCr_lt:
445             DO_REL(<, f);
446             goto rel;
447         case PtCr_ne_int:
448             DO_REL(!=, i);
449             goto rel;
450         case PtCr_ne:
451             DO_REL(!=, f);
452             goto rel;
453 
454 #undef DO_REL
455 
456             /* Stack operators */
457 
458         case PtCr_copy:
459             i = vsp->value.i;
460             n = vsp - vstack;
461             if (i < 0 || i >= n)
462                 return_error(gs_error_rangecheck);
463             if (i > MAX_VSTACK - (n - 1))
464                 return_error(gs_error_limitcheck);
465             memcpy(vsp, vsp - i, i * sizeof(*vsp));
466             vsp += i - 1;
467             continue;
468         case PtCr_dup:
469             vsp[1] = *vsp;
470             goto push;
471         case PtCr_exch:
472             vstack[MAX_VSTACK] = *vsp;
473             *vsp = vsp[-1];
474             vsp[-1] = vstack[MAX_VSTACK];
475             continue;
476         case PtCr_index:
477             i = vsp->value.i;
478             if (i < 0 || i >= vsp - vstack - 1)
479                 return_error(gs_error_rangecheck);
480             *vsp = vsp[-i - 1];
481             continue;
482         case PtCr_pop:
483             --vsp;
484             continue;
485         case PtCr_roll:
486             n = vsp[-1].value.i;
487             i = vsp->value.i;
488             if (n < 0 || n > vsp - vstack - 2)
489                 return_error(gs_error_rangecheck);
490             /* We don't bother to do this efficiently. */
491             for (; i > 0; i--) {
492                 memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493                 vsp[-(n + 1)] = vsp[-1];
494             }
495             for (; i < 0; i++) {
496                 vsp[-1] = vsp[-(n + 1)];
497                 memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498             }
499             vsp -= 2;
500             continue;
501 
502             /* Constants */
503 
504         case PtCr_byte:
505             vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506             goto push;
507         case PtCr_int /* native */:
508             memcpy(&vsp[1].value.i, p, sizeof(int));
509             vsp[1].type = CVT_INT;
510             p += sizeof(int);
511             goto push;
512         case PtCr_float /* native */:
513             memcpy(&vsp[1].value.f, p, sizeof(float));
514             vsp[1].type = CVT_FLOAT;
515             p += sizeof(float);
516             goto push;
517         case PtCr_true:
518             vsp[1].value.i = true, vsp[1].type = CVT_BOOL;
519             goto push;
520         case PtCr_false:
521             vsp[1].value.i = false, vsp[1].type = CVT_BOOL;
522         push:
523             if (vsp == &vstack[MAX_VSTACK])
524                 return_error(gs_error_limitcheck);
525             ++vsp;
526             continue;
527 
528             /* Special */
529 
530         case PtCr_if:
531             if ((vsp--)->value.i) {	/* value is true, execute body */
532                 p += 2;
533                 continue;
534             }
535             /* falls through */
536         case PtCr_else:
537             p += 2 + (p[0] << 8) + p[1];	/* skip the past body */
538             continue;
539         case PtCr_return:
540             goto fin;
541         case PtCr_repeat:
542             repeat_nesting_level++;
543             repeat_count[repeat_nesting_level] = vsp->value.i;
544             repeat_proc_size[repeat_nesting_level] = 1 + (p[0] << 8) + p[1];	/* body size */
545             --vsp;		/* pop the counter */
546             p += 3 + (p[0] <<8) + p[1];		    /* advance just past the repeat_end */
547             /* falls through */
548         case PtCr_repeat_end:
549             if (repeat_nesting_level < 0)
550                 return_error(gs_error_rangecheck);
551 
552             if ((repeat_count[repeat_nesting_level])-- <= 0)
553                 repeat_nesting_level--;
554             else
555                 p -= repeat_proc_size[repeat_nesting_level];
556             continue;
557         }
558     }
559  fin:
560 
561     if (vsp != vstack + pfn->params.n)
562         return_error(gs_error_rangecheck);
563     for (i = 0; i < pfn->params.n; ++i) {
564         switch (vstack[i + 1].type) {
565         case CVT_INT:
566             out[i] = (float)vstack[i + 1].value.i;
567             break;
568         case CVT_FLOAT:
569             out[i] = vstack[i + 1].value.f;
570             break;
571         default:
572             return_error(gs_error_typecheck);
573         }
574     }
575     return 0;
576 }
577 
578 /* Test whether a PostScript Calculator function is monotonic. */
579 static int
fn_PtCr_is_monotonic(const gs_function_t * pfn_common,const float * lower,const float * upper,uint * mask)580 fn_PtCr_is_monotonic(const gs_function_t * pfn_common,
581                      const float *lower, const float *upper, uint *mask)
582 {
583     /*
584      * No reasonable way to tell.  Eventually we should check for
585      * functions consisting of only stack-manipulating operations,
586      * since these may be common for DeviceN color spaces and *are*
587      * monotonic.
588      */
589     *mask = 0x49249249;
590     return 0;
591 }
592 
593 /* Write the function definition in symbolic form on a stream. */
594 static int
calc_put_ops(stream * s,const byte * ops,uint size)595 calc_put_ops(stream *s, const byte *ops, uint size)
596 {
597     const byte *p;
598 
599     spputc(s, '{');
600     for (p = ops; p < ops + size; )
601         switch (*p++) {
602         case PtCr_byte:
603             pprintd1(s, "%d ", *p++);
604             break;
605         case PtCr_int: {
606             int i;
607 
608             memcpy(&i, p, sizeof(int));
609             pprintd1(s, "%d ", i);
610             p += sizeof(int);
611             break;
612         }
613         case PtCr_float: {
614             float f;
615 
616             memcpy(&f, p, sizeof(float));
617             pprintg1(s, "%g ", f);
618             p += sizeof(float);
619             break;
620         }
621         case PtCr_true:
622             stream_puts(s, "true ");
623             break;
624         case PtCr_false:
625             stream_puts(s, "false ");
626             break;
627         case PtCr_if: {
628             int skip = (p[0] << 8) + p[1];
629             int code;
630 
631             code = calc_put_ops(s, p += 2, skip);
632             p += skip;
633             if (code < 0)
634                 return code;
635             if (code > 0) {	/* else */
636                 skip = (p[-2] << 8) + p[-1];
637                 code = calc_put_ops(s, p, skip);
638                 p += skip;
639                 if (code < 0)
640                     return code;
641                 stream_puts(s, " ifelse ");
642             } else
643                 stream_puts(s, " if ");
644             break;
645         }
646         case PtCr_else:
647             if (p != ops + size - 2)
648                 return_error(gs_error_rangecheck);
649             spputc(s, '}');
650             return 1;
651         /*case PtCr_return:*/	/* not possible */
652         case PtCr_repeat:		/* We shouldn't encounter this, but just in case */
653         case PtCr_repeat_end:
654             return_error(gs_error_rangecheck);
655         default: {		/* must be < PtCr_NUM_OPS */
656                 static const char *const op_names[] = {
657                     /* Keep this consistent with opcodes in gsfunc4.h! */
658                     "abs", "add", "and", "atan", "bitshift",
659                     "ceiling", "cos", "cvi", "cvr", "div", "exp",
660                     "floor", "idiv", "ln", "log", "mod", "mul",
661                     "neg", "not", "or", "round", "sin", "sqrt", "sub",
662                     "truncate", "xor",
663                     "eq", "ge", "gt", "le", "lt", "ne",
664                     "copy", "dup", "exch", "index", "pop", "roll"
665                 };
666 
667                 pprints1(s, "%s ", op_names[p[-1]]);
668             }
669         }
670     spputc(s, '}');
671     return 0;
672 }
673 static int
calc_put(stream * s,const gs_function_PtCr_t * pfn)674 calc_put(stream *s, const gs_function_PtCr_t *pfn)
675 {
676     calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
677     return 0;
678 }
679 
680 /* Access the symbolic definition as a DataSource. */
681 static int
calc_access(const gs_data_source_t * psrc,ulong start,uint length,byte * buf,const byte ** ptr)682 calc_access(const gs_data_source_t *psrc, ulong start, uint length,
683             byte *buf, const byte **ptr)
684 {
685     const gs_function_PtCr_t *const pfn =
686         (const gs_function_PtCr_t *)
687           ((const char *)psrc - offset_of(gs_function_PtCr_t, data_source));
688     /*
689      * The caller wants a specific substring of the symbolic definition.
690      * Generate the entire definition, using a SubFileDecode filter (in an
691      * output pipeline!) to extract the substring.  This is very
692      * inefficient, but this code is rarely used, and almost never actually
693      * has to break up the definition into pieces to fit in the caller's
694      * buffer.
695      */
696     stream_SFD_state st;
697     stream ds, bs;
698     byte dbuf[200];		/* arbitrary */
699     const stream_template *const templat = &s_SFD_template;
700 
701     /* Set up the stream that writes into the buffer. */
702     s_init(&bs, NULL);
703     swrite_string(&bs, buf, length);
704     /* Set up the SubFileDecode stream. */
705     s_init(&ds, NULL);
706     s_init_state((stream_state *)&st, templat, NULL);
707     templat->set_defaults((stream_state *)&st);
708     st.skip_count = start;
709     s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
710     calc_put(&ds, pfn);
711     sclose(&ds);
712     if (ptr)
713         *ptr = buf;
714     return 0;
715 }
716 
717 /* Return PostScript Calculator function information. */
718 static void
fn_PtCr_get_info(const gs_function_t * pfn_common,gs_function_info_t * pfi)719 fn_PtCr_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
720 {
721     const gs_function_PtCr_t *const pfn =
722         (const gs_function_PtCr_t *)pfn_common;
723 
724     gs_function_get_info_default(pfn_common, pfi);
725     pfi->DataSource = &pfn->data_source;
726     {
727         stream s;
728 
729         s_init(&s, NULL);
730         swrite_position_only(&s);
731         calc_put(&s, pfn);
732         pfi->data_size = stell(&s);
733     }
734 }
735 
736 /* Make a scaled copy of a PostScript Calculator function. */
737 static int
fn_PtCr_make_scaled(const gs_function_PtCr_t * pfn,gs_function_PtCr_t ** ppsfn,const gs_range_t * pranges,gs_memory_t * mem)738 fn_PtCr_make_scaled(const gs_function_PtCr_t *pfn, gs_function_PtCr_t **ppsfn,
739                     const gs_range_t *pranges, gs_memory_t *mem)
740 {
741     gs_function_PtCr_t *psfn =
742         gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
743                         "fn_PtCr_make_scaled");
744     /* We are adding {<int> 1 roll <float> mul <float> add} for each output. */
745     int n = pfn->params.n;
746     uint opsize = pfn->params.ops.size + (9 + 2 * sizeof(float)) * n;
747     byte *ops = gs_alloc_string(mem, opsize, "fn_PtCr_make_scaled(ops)");
748     byte *p;
749     int code, i;
750 
751     if (psfn == 0 || ops == 0) {
752         gs_free_string(mem, ops, opsize, "fn_PtCr_make_scaled(ops)");
753         gs_free_object(mem, psfn, "fn_PtCr_make_scaled");
754         return_error(gs_error_VMerror);
755     }
756     psfn->params = pfn->params;
757     psfn->params.ops.data = ops;
758     psfn->params.ops.size = opsize;
759     psfn->data_source = pfn->data_source;
760     code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn,
761                            pranges, mem);
762     if (code < 0) {
763         gs_function_free((gs_function_t *)psfn, true, mem);
764         return code;
765     }
766     memcpy(ops, pfn->params.ops.data, pfn->params.ops.size - 1); /* minus return */
767     p = ops + pfn->params.ops.size - 1;
768     for (i = n; --i >= 0; ) {
769         float base = pranges[i].rmin;
770         float factor = pranges[i].rmax - base;
771 
772         if (factor != 1) {
773             p[0] = PtCr_float; memcpy(p + 1, &factor, sizeof(float));
774             p += 1 + sizeof(float);
775             *p++ = PtCr_mul;
776         }
777         if (base != 0) {
778             p[0] = PtCr_float; memcpy(p + 1, &base, sizeof(float));
779             p += 1 + sizeof(float);
780             *p++ = PtCr_add;
781         }
782         if (n != 1) {
783             p[0] = PtCr_byte; p[1] = (byte)n;
784             p[2] = PtCr_byte; p[3] = 1;
785             p[4] = PtCr_roll;
786             p += 5;
787         }
788     }
789     *p++ = PtCr_return;
790     psfn->params.ops.size = p - ops;
791     psfn->params.ops.data =
792         gs_resize_string(mem, ops, opsize, psfn->params.ops.size,
793                          "fn_PtCr_make_scaled");
794     *ppsfn = psfn;
795     return 0;
796 }
797 
798 /* Free the parameters of a PostScript Calculator function. */
799 void
gs_function_PtCr_free_params(gs_function_PtCr_params_t * params,gs_memory_t * mem)800 gs_function_PtCr_free_params(gs_function_PtCr_params_t * params, gs_memory_t * mem)
801 {
802     gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
803     params->ops.data = NULL;
804     params->ops.size = 0;
805     fn_common_free_params((gs_function_params_t *) params, mem);
806 }
807 
808 /* Serialize. */
809 static int
gs_function_PtCr_serialize(const gs_function_t * pfn,stream * s)810 gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
811 {
812     uint n;
813     const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
814     int code = fn_common_serialize(pfn, s);
815 
816     if (code < 0)
817         return code;
818     code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
819     if (code < 0)
820         return code;
821     return sputs(s, p->ops.data, p->ops.size, &n);
822 }
823 
824 /* Allocate and initialize a PostScript Calculator function. */
825 int
gs_function_PtCr_init(gs_function_t ** ppfn,const gs_function_PtCr_params_t * params,gs_memory_t * mem)826 gs_function_PtCr_init(gs_function_t ** ppfn,
827                   const gs_function_PtCr_params_t * params, gs_memory_t * mem)
828 {
829     static const gs_function_head_t function_PtCr_head = {
830         function_type_PostScript_Calculator,
831         {
832             (fn_evaluate_proc_t) fn_PtCr_evaluate,
833             (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
834             (fn_get_info_proc_t) fn_PtCr_get_info,
835             fn_common_get_params,
836             (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
837             (fn_free_params_proc_t) gs_function_PtCr_free_params,
838             fn_common_free,
839             (fn_serialize_proc_t) gs_function_PtCr_serialize,
840         }
841     };
842     int code;
843 
844     *ppfn = 0;			/* in case of error */
845     code = fn_check_mnDR((const gs_function_params_t *)params,
846                          params->m, params->n);
847     if (code < 0)
848         return code;
849     if (params->m > MAX_VSTACK || params->n > MAX_VSTACK)
850         return_error(gs_error_limitcheck);
851     /*
852      * Pre-validate the operation string to reduce evaluation overhead.
853      */
854     {
855         const byte *p = params->ops.data;
856 
857         for (; *p != PtCr_return; ++p)
858             switch ((gs_PtCr_opcode_t)*p) {
859             case PtCr_byte:
860                 ++p; break;
861             case PtCr_int:
862                 p += sizeof(int); break;
863             case PtCr_float:
864                 p += sizeof(float); break;
865             case PtCr_repeat:
866             case PtCr_if:
867             case PtCr_else:
868                 p += 2;
869             case PtCr_repeat_end:
870             case PtCr_true:
871             case PtCr_false:
872                 break;
873             default:
874                 if (*p >= PtCr_NUM_OPS)
875                     return_error(gs_error_rangecheck);
876             }
877         if (p != params->ops.data + params->ops.size - 1)
878             return_error(gs_error_rangecheck);
879     }
880     {
881         gs_function_PtCr_t *pfn =
882             gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
883                             "gs_function_PtCr_init");
884 
885         if (pfn == 0)
886             return_error(gs_error_VMerror);
887         pfn->params = *params;
888         /*
889          * We claim to have a DataSource, in order to write the function
890          * definition in symbolic form for embedding in PDF files.
891          * ****** THIS IS A HACK. ******
892          */
893         data_source_init_string2(&pfn->data_source, NULL, 0);
894         pfn->data_source.access = calc_access;
895         pfn->head = function_PtCr_head;
896         *ppfn = (gs_function_t *) pfn;
897     }
898     return 0;
899 }
900