1 /*
2 * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it either under the terms of the GNU Lesser General Public
6 * License version 2.1 as published by the Free Software Foundation
7 * (the "LGPL") or, at your option, under the terms of the Mozilla
8 * Public License Version 1.1 (the "MPL"). If you do not alter this
9 * notice, a recipient may use your version of this file under either
10 * the MPL or the LGPL.
11 *
12 * You should have received a copy of the LGPL along with this library
13 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
15 * You should have received a copy of the MPL along with this library
16 * in the file COPYING-MPL-1.1
17 *
18 * The contents of this file are subject to the Mozilla Public License
19 * Version 1.1 (the "License"); you may not use this file except in
20 * compliance with the License. You may obtain a copy of the License at
21 * http://www.mozilla.org/MPL/
22 *
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
24 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
25 * the specific language governing rights and limitations.
26 *
27 * The Original Code is the cairo graphics library.
28 *
29 * The Initial Developer of the Original Code is Chris Wilson.
30 *
31 * Contributor(s):
32 * Chris Wilson <chris@chris-wilson.co.uk>
33 */
34
35 #include "config.h"
36
37 #include "cairo-script-private.h"
38
39 #include <limits.h> /* INT_MAX */
40 #include <math.h> /* pow */
41 #include <stdio.h> /* EOF */
42 #include <stdint.h> /* for {INT,UINT}*_{MIN,MAX} */
43 #include <stdlib.h> /* malloc/free */
44 #include <string.h> /* memset */
45 #include <assert.h>
46 #include <zlib.h>
47
48 #if HAVE_LZO
49 #include <lzo/lzo2a.h>
50 #endif
51
52 #define DEBUG_SCAN 0
53
54 #if WORDS_BIGENDIAN
55 #define le16(x) bswap_16 (x)
56 #define le32(x) bswap_32 (x)
57 #define be16(x) x
58 #define be32(x) x
59 #define to_be32(x) x
60 #else
61 #define le16(x) x
62 #define le32(x) x
63 #define be16(x) bswap_16 (x)
64 #define be32(x) bswap_32 (x)
65 #define to_be32(x) bswap_32 (x)
66 #endif
67
68 /*
69 * whitespace:
70 * 0 - nul
71 * 9 - tab
72 * A - LF
73 * C - FF
74 * D - CR
75 *
76 * syntax delimiters
77 * ( = 28, ) = 29 - literal strings
78 * < = 3C, > = 3E - hex/base85 strings, dictionary name
79 * [ = 5B, ] = 5D - array
80 * { = 7B, } = 7C - procedure
81 * / = 5C - literal marker
82 * % = 25 - comment
83 */
84
85 static void
fprintf_obj(FILE * stream,csi_t * ctx,const csi_object_t * obj)86 fprintf_obj (FILE *stream, csi_t *ctx, const csi_object_t *obj)
87 {
88 switch (csi_object_get_type (obj)) {
89 case CSI_OBJECT_TYPE_NULL:
90 fprintf (stream, "NULL\n");
91 break;
92
93 /* atomics */
94 case CSI_OBJECT_TYPE_BOOLEAN:
95 fprintf (stream, "boolean: %s\n",
96 obj->datum.boolean ? "true" : "false");
97 break;
98 case CSI_OBJECT_TYPE_INTEGER:
99 fprintf (stream, "integer: %ld\n", obj->datum.integer);
100 break;
101 case CSI_OBJECT_TYPE_MARK:
102 fprintf (stream, "mark\n");
103 break;
104 case CSI_OBJECT_TYPE_NAME:
105 fprintf (stream, "name: %s\n", (char *) obj->datum.name);
106 break;
107 case CSI_OBJECT_TYPE_OPERATOR:
108 fprintf (stream, "operator: %p\n", obj->datum.ptr);
109 break;
110 case CSI_OBJECT_TYPE_REAL:
111 fprintf (stream, "real: %g\n", obj->datum.real);
112 break;
113
114 /* compound */
115 case CSI_OBJECT_TYPE_ARRAY:
116 fprintf (stream, "array\n");
117 break;
118 case CSI_OBJECT_TYPE_DICTIONARY:
119 fprintf (stream, "dictionary\n");
120 break;
121 case CSI_OBJECT_TYPE_FILE:
122 fprintf (stream, "file\n");
123 break;
124 case CSI_OBJECT_TYPE_MATRIX:
125 fprintf (stream, "matrix: [%g %g %g %g %g %g]\n",
126 obj->datum.matrix->matrix.xx,
127 obj->datum.matrix->matrix.yx,
128 obj->datum.matrix->matrix.xy,
129 obj->datum.matrix->matrix.yy,
130 obj->datum.matrix->matrix.x0,
131 obj->datum.matrix->matrix.y0);
132 break;
133 case CSI_OBJECT_TYPE_STRING:
134 fprintf (stream, "string: len=%ld, defate=%ld, method=%d\n",
135 obj->datum.string->len, obj->datum.string->deflate, obj->datum.string->method);
136 break;
137
138 /* cairo */
139 case CSI_OBJECT_TYPE_CONTEXT:
140 fprintf (stream, "context\n");
141 break;
142 case CSI_OBJECT_TYPE_FONT:
143 fprintf (stream, "font\n");
144 break;
145 case CSI_OBJECT_TYPE_PATTERN:
146 fprintf (stream, "pattern\n");
147 break;
148 case CSI_OBJECT_TYPE_SCALED_FONT:
149 fprintf (stream, "scaled-font\n");
150 break;
151 case CSI_OBJECT_TYPE_SURFACE:
152 fprintf (stream, "surface\n");
153 break;
154 }
155 }
156
157 /* takes ownership of obj */
158 static inline csi_status_t
scan_push(csi_t * ctx,csi_object_t * obj)159 scan_push (csi_t *ctx, csi_object_t *obj)
160 {
161 return ctx->scanner.push (ctx, obj);
162 }
163
164 static inline csi_status_t
scan_execute(csi_t * ctx,csi_object_t * obj)165 scan_execute (csi_t *ctx, csi_object_t *obj)
166 {
167 return ctx->scanner.execute (ctx, obj);
168 }
169
170 static cairo_status_t
buffer_init(csi_t * ctx,csi_buffer_t * buffer)171 buffer_init (csi_t *ctx, csi_buffer_t *buffer)
172 {
173 cairo_status_t status = CSI_STATUS_SUCCESS;
174
175 buffer->size = 16384;
176 buffer->base = _csi_alloc (ctx, buffer->size);
177 if (_csi_unlikely (buffer->base == NULL)) {
178 status = _csi_error (CSI_STATUS_NO_MEMORY);
179 buffer->size = 0;
180 }
181
182 buffer->ptr = buffer->base;
183 buffer->end = buffer->base + buffer->size;
184
185 return status;
186 }
187
188 static void
buffer_fini(csi_t * ctx,csi_buffer_t * buffer)189 buffer_fini (csi_t *ctx, csi_buffer_t *buffer)
190 {
191 _csi_free (ctx, buffer->base);
192 }
193
194 static void
_buffer_grow(csi_t * ctx,csi_scanner_t * scan)195 _buffer_grow (csi_t *ctx, csi_scanner_t *scan)
196 {
197 int newsize;
198 int offset;
199 char *base;
200
201 if (_csi_unlikely (scan->buffer.size > INT_MAX / 2))
202 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_NO_MEMORY));
203
204 offset = scan->buffer.ptr - scan->buffer.base;
205 newsize = scan->buffer.size * 2;
206 base = _csi_realloc (ctx, scan->buffer.base, newsize);
207 if (_csi_unlikely (base == NULL))
208 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_NO_MEMORY));
209
210 scan->buffer.base = base;
211 scan->buffer.ptr = base + offset;
212 scan->buffer.end = base + newsize;
213 scan->buffer.size = newsize;
214 }
215
216 static inline void
buffer_check(csi_t * ctx,csi_scanner_t * scan,int count)217 buffer_check (csi_t *ctx, csi_scanner_t *scan, int count)
218 {
219 if (_csi_unlikely (scan->buffer.ptr + count > scan->buffer.end))
220 _buffer_grow (ctx, scan);
221 }
222
223 static inline void
buffer_add(csi_buffer_t * buffer,int c)224 buffer_add (csi_buffer_t *buffer, int c)
225 {
226 *buffer->ptr++ = c;
227 }
228
229 static inline void
buffer_reset(csi_buffer_t * buffer)230 buffer_reset (csi_buffer_t *buffer)
231 {
232 buffer->ptr = buffer->base;
233 }
234
235 static void
token_start(csi_scanner_t * scan)236 token_start (csi_scanner_t *scan)
237 {
238 buffer_reset (&scan->buffer);
239 }
240
241 static void
token_add(csi_t * ctx,csi_scanner_t * scan,int c)242 token_add (csi_t *ctx, csi_scanner_t *scan, int c)
243 {
244 buffer_check (ctx, scan, 1);
245 buffer_add (&scan->buffer, c);
246 }
247
248 static void
token_add_unchecked(csi_scanner_t * scan,int c)249 token_add_unchecked (csi_scanner_t *scan, int c)
250 {
251 buffer_add (&scan->buffer, c);
252 }
253
254 csi_boolean_t
_csi_parse_number(csi_object_t * obj,const char * s,int len)255 _csi_parse_number (csi_object_t *obj, const char *s, int len)
256 {
257 int radix = 0;
258 long long mantissa = 0;
259 int exponent = 0;
260 int sign = 1;
261 int decimal = -1;
262 int exponent_sign = 0;
263 const char * const end = s + len;
264
265 switch (*s) {
266 case '0':
267 case '1':
268 case '2':
269 case '3':
270 case '4':
271 case '5':
272 case '6':
273 case '7':
274 case '8':
275 case '9':
276 mantissa = *s - '0';
277 case '+':
278 break;
279 case '-':
280 sign = -1;
281 break;
282 case '.':
283 decimal = 0;
284 break;
285 default:
286 return FALSE;
287 }
288
289 while (++s < end) {
290 if (*s < '0') {
291 if (*s == '.') {
292 if (_csi_unlikely (radix))
293 return FALSE;
294 if (_csi_unlikely (decimal != -1))
295 return FALSE;
296 if (_csi_unlikely (exponent_sign))
297 return FALSE;
298
299 decimal = 0;
300 } else if (*s == '!') {
301 if (_csi_unlikely (radix))
302 return FALSE;
303 if (_csi_unlikely (decimal != -1))
304 return FALSE;
305 if (_csi_unlikely (exponent_sign))
306 return FALSE;
307
308 radix = mantissa;
309 mantissa = 0;
310
311 if (_csi_unlikely (radix < 2 || radix > 36))
312 return FALSE;
313 } else
314 return FALSE;
315 } else if (*s <= '9') {
316 int v = *s - '0';
317 if (_csi_unlikely (radix && v >= radix))
318 return FALSE;
319
320 if (exponent_sign) {
321 exponent = 10 * exponent + v;
322 } else {
323 if (radix)
324 mantissa = radix * mantissa + v;
325 else
326 mantissa = 10 * mantissa + v;
327 if (decimal != -1)
328 decimal++;
329 }
330 } else if (*s == 'E' || * s== 'e') {
331 if (radix == 0) {
332 if (_csi_unlikely (s + 1 == end))
333 return FALSE;
334
335 exponent_sign = 1;
336 if (s[1] == '-') {
337 exponent_sign = -1;
338 s++;
339 } else if (s[1] == '+')
340 s++;
341 } else {
342 int v = 0xe;
343
344 if (_csi_unlikely (v >= radix))
345 return FALSE;
346
347 mantissa = radix * mantissa + v;
348 }
349 } else if (*s < 'A') {
350 return FALSE;
351 } else if (*s <= 'Z') {
352 int v = *s - 'A' + 0xA;
353
354 if (_csi_unlikely (v >= radix))
355 return FALSE;
356
357 mantissa = radix * mantissa + v;
358 } else if (*s < 'a') {
359 return FALSE;
360 } else if (*s <= 'z') {
361 int v = *s - 'a' + 0xa;
362
363 if (_csi_unlikely (v >= radix))
364 return FALSE;
365
366 mantissa = radix * mantissa + v;
367 } else
368 return FALSE;
369 }
370
371 if (exponent_sign || decimal != -1) {
372 if (mantissa == 0) {
373 obj->type = CSI_OBJECT_TYPE_REAL;
374 obj->datum.real = 0.;
375 return TRUE;
376 } else {
377 int e;
378 double v;
379
380 v = mantissa;
381 e = exponent * exponent_sign;
382 if (decimal != -1)
383 e -= decimal;
384 switch (e) {
385 case -7: v *= 0.0000001; break;
386 case -6: v *= 0.000001; break;
387 case -5: v *= 0.00001; break;
388 case -4: v *= 0.0001; break;
389 case -3: v *= 0.001; break;
390 case -2: v *= 0.01; break;
391 case -1: v *= 0.1; break;
392 case 0: break;
393 case 1: v *= 10; break;
394 case 2: v *= 100; break;
395 case 3: v *= 1000; break;
396 case 4: v *= 10000; break;
397 case 5: v *= 100000; break;
398 case 6: v *= 1000000; break;
399 default:
400 v *= pow (10, e); /* XXX */
401 break;
402 }
403
404 obj->type = CSI_OBJECT_TYPE_REAL;
405 obj->datum.real = sign * v;
406 return TRUE;
407 }
408 } else {
409 obj->type = CSI_OBJECT_TYPE_INTEGER;
410 obj->datum.integer = sign * mantissa;
411 return TRUE;
412 }
413 }
414
415 static void
token_end(csi_t * ctx,csi_scanner_t * scan,csi_file_t * src)416 token_end (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
417 {
418 cairo_status_t status;
419 char *s;
420 csi_object_t obj;
421 int len;
422
423 /*
424 * Any token that consists entirely of regular characters and
425 * cannot be interpreted as a number is treated as a name object
426 * (more precisely, an executable name). All characters except
427 * delimiters and white-space characters can appear in names,
428 * including characters ordinarily considered to be punctuation.
429 */
430
431 if (_csi_unlikely (scan->buffer.ptr == scan->buffer.base))
432 return;
433
434 s = scan->buffer.base;
435 len = scan->buffer.ptr - scan->buffer.base;
436
437 if (_csi_likely (! scan->bind)) {
438 if (s[0] == '{') { /* special case procedures */
439 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
440 status = _csi_stack_push (ctx,
441 &scan->procedure_stack,
442 &scan->build_procedure);
443 if (_csi_unlikely (status))
444 longjmp (scan->jump_buffer, status);
445 }
446
447 status = csi_array_new (ctx, 0, &scan->build_procedure);
448 if (_csi_unlikely (status))
449 longjmp (scan->jump_buffer, status);
450
451 scan->build_procedure.type |= CSI_OBJECT_ATTR_EXECUTABLE;
452 return;
453 } else if (s[0] == '}') {
454 if (_csi_unlikely
455 (scan->build_procedure.type == CSI_OBJECT_TYPE_NULL))
456 {
457 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
458 }
459
460 if (scan->procedure_stack.len) {
461 csi_object_t *next;
462
463 next = _csi_stack_peek (&scan->procedure_stack, 0);
464 status = csi_array_append (ctx, next->datum.array,
465 &scan->build_procedure);
466 scan->build_procedure = *next;
467 scan->procedure_stack.len--;
468 } else {
469 status = scan_push (ctx, &scan->build_procedure);
470 scan->build_procedure.type = CSI_OBJECT_TYPE_NULL;
471 }
472 if (_csi_unlikely (status))
473 longjmp (scan->jump_buffer, status);
474
475 return;
476 }
477 }
478
479 if (s[0] == '/') {
480 if (len >= 2 && s[1] == '/') { /* substituted name */
481 status = csi_name_new (ctx, &obj, s + 2, len - 2);
482 if (_csi_unlikely (status))
483 longjmp (scan->jump_buffer, status);
484
485 status = _csi_name_lookup (ctx, obj.datum.name, &obj);
486 } else { /* literal name */
487 status = csi_name_new (ctx, &obj, s + 1, len - 1);
488 }
489 if (_csi_unlikely (status))
490 longjmp (scan->jump_buffer, status);
491 } else {
492 if (! _csi_parse_number (&obj, s, len)) {
493 status = csi_name_new (ctx, &obj, s, len);
494 if (_csi_unlikely (status))
495 longjmp (scan->jump_buffer, status);
496
497 obj.type |= CSI_OBJECT_ATTR_EXECUTABLE;
498 }
499 }
500
501 /* consume whitespace after token, before calling the interpreter */
502 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
503 status = csi_array_append (ctx,
504 scan->build_procedure.datum.array,
505 &obj);
506 } else if (obj.type & CSI_OBJECT_ATTR_EXECUTABLE) {
507 status = scan_execute (ctx, &obj);
508 csi_object_free (ctx, &obj);
509 } else {
510 status = scan_push (ctx, &obj);
511 }
512 if (_csi_unlikely (status))
513 longjmp (scan->jump_buffer, status);
514 }
515
516 static void
string_add(csi_t * ctx,csi_scanner_t * scan,int c)517 string_add (csi_t *ctx, csi_scanner_t *scan, int c)
518 {
519 buffer_check (ctx, scan, 1);
520 buffer_add (&scan->buffer, c);
521 }
522
523 static void
string_end(csi_t * ctx,csi_scanner_t * scan)524 string_end (csi_t *ctx, csi_scanner_t *scan)
525 {
526 csi_object_t obj;
527 cairo_status_t status;
528
529 status = csi_string_new (ctx,
530 &obj,
531 scan->buffer.base,
532 scan->buffer.ptr - scan->buffer.base);
533 if (_csi_unlikely (status))
534 longjmp (scan->jump_buffer, status);
535
536 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
537 status = csi_array_append (ctx,
538 scan->build_procedure.datum.array,
539 &obj);
540 else
541 status = scan_push (ctx, &obj);
542 if (_csi_unlikely (status))
543 longjmp (scan->jump_buffer, status);
544 }
545
546 static int
hex_value(int c)547 hex_value (int c)
548 {
549 if (c < '0')
550 return EOF;
551 if (c <= '9')
552 return c - '0';
553 c |= 32;
554 if (c < 'a')
555 return EOF;
556 if (c <= 'f')
557 return c - 'a' + 0xa;
558 return EOF;
559 }
560
561 static void
hex_add(csi_t * ctx,csi_scanner_t * scan,int c)562 hex_add (csi_t *ctx, csi_scanner_t *scan, int c)
563 {
564 if (scan->accumulator_count == 0) {
565 scan->accumulator |= hex_value (c) << 4;
566 scan->accumulator_count = 1;
567 } else {
568 scan->accumulator |= hex_value (c) << 0;
569 buffer_check (ctx, scan, 1);
570 buffer_add (&scan->buffer, scan->accumulator);
571
572 scan->accumulator = 0;
573 scan->accumulator_count = 0;
574 }
575 }
576
577 static void
hex_end(csi_t * ctx,csi_scanner_t * scan)578 hex_end (csi_t *ctx, csi_scanner_t *scan)
579 {
580 csi_object_t obj;
581 cairo_status_t status;
582
583 if (scan->accumulator_count)
584 hex_add (ctx, scan, '0');
585
586 status = csi_string_new (ctx,
587 &obj,
588 scan->buffer.base,
589 scan->buffer.ptr - scan->buffer.base);
590 if (_csi_unlikely (status))
591 longjmp (scan->jump_buffer, status);
592
593 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
594 status = csi_array_append (ctx,
595 scan->build_procedure.datum.array,
596 &obj);
597 else
598 status = scan_push (ctx, &obj);
599 if (_csi_unlikely (status))
600 longjmp (scan->jump_buffer, status);
601 }
602
603 static void
base85_add(csi_t * ctx,csi_scanner_t * scan,int c)604 base85_add (csi_t *ctx, csi_scanner_t *scan, int c)
605 {
606 if (c == 'z') {
607 if (_csi_unlikely (scan->accumulator_count != 0))
608 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
609
610 buffer_check (ctx, scan, 4);
611 buffer_add (&scan->buffer, 0);
612 buffer_add (&scan->buffer, 0);
613 buffer_add (&scan->buffer, 0);
614 buffer_add (&scan->buffer, 0);
615 } else if (_csi_unlikely (c < '!' || c > 'u')) {
616 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
617 } else {
618 scan->accumulator = scan->accumulator*85 + c - '!';
619 if (++scan->accumulator_count == 5) {
620 buffer_check (ctx, scan, 4);
621 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
622 buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
623 buffer_add (&scan->buffer, (scan->accumulator >> 8) & 0xff);
624 buffer_add (&scan->buffer, (scan->accumulator >> 0) & 0xff);
625
626 scan->accumulator = 0;
627 scan->accumulator_count = 0;
628 }
629 }
630 }
631
632 static void
base85_end(csi_t * ctx,csi_scanner_t * scan,cairo_bool_t deflate)633 base85_end (csi_t *ctx, csi_scanner_t *scan, cairo_bool_t deflate)
634 {
635 csi_object_t obj;
636 cairo_status_t status;
637
638 buffer_check (ctx, scan, 4);
639
640 switch (scan->accumulator_count) {
641 case 0:
642 break;
643 case 1:
644 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
645 break;
646
647 case 2:
648 scan->accumulator = scan->accumulator * (85*85*85) + 85*85*85 -1;
649 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
650 break;
651 case 3:
652 scan->accumulator = scan->accumulator * (85*85) + 85*85 -1;
653 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
654 buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
655 break;
656 case 4:
657 scan->accumulator = scan->accumulator * 85 + 84;
658 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
659 buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
660 buffer_add (&scan->buffer, (scan->accumulator >> 8) & 0xff);
661 break;
662 }
663
664 if (deflate) {
665 uLongf len = be32 (*(uint32_t *) scan->buffer.base);
666 Bytef *source = (Bytef *) (scan->buffer.base + sizeof (uint32_t));
667
668 status = csi_string_deflate_new (ctx, &obj,
669 source,
670 (Bytef *) scan->buffer.ptr - source,
671 len);
672 if (_csi_unlikely (status))
673 longjmp (scan->jump_buffer, status);
674 } else {
675 status = csi_string_new (ctx,
676 &obj,
677 scan->buffer.base,
678 scan->buffer.ptr - scan->buffer.base);
679 if (_csi_unlikely (status))
680 longjmp (scan->jump_buffer, status);
681 }
682
683 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
684 status = csi_array_append (ctx,
685 scan->build_procedure.datum.array,
686 &obj);
687 else
688 status = scan_push (ctx, &obj);
689 if (_csi_unlikely (status))
690 longjmp (scan->jump_buffer, status);
691 }
692
693 static void
base64_add(csi_t * ctx,csi_scanner_t * scan,int c)694 base64_add (csi_t *ctx, csi_scanner_t *scan, int c)
695 {
696 int val;
697
698 /* Convert Base64 character to its 6 bit nibble */
699 val = scan->accumulator;
700 if (c =='/') {
701 val = (val << 6) | 63;
702 } else if (c =='+') {
703 val = (val << 6) | 62;
704 } else if (c >='A' && c <='Z') {
705 val = (val << 6) | (c -'A');
706 } else if (c >='a' && c <='z') {
707 val = (val << 6) | (c -'a' + 26);
708 } else if (c >='0' && c <='9') {
709 val = (val << 6) | (c -'0' + 52);
710 }
711
712 buffer_check (ctx, scan, 1);
713 switch (scan->accumulator_count++) {
714 case 0:
715 break;
716
717 case 1:
718 buffer_add (&scan->buffer, (val >> 4) & 0xFF);
719 val &= 0xF;
720 break;
721
722 case 2:
723 buffer_add (&scan->buffer, (val >> 2) & 0xFF);
724 val &= 0x3;
725 break;
726
727 case 3:
728 buffer_add (&scan->buffer, (val >> 0) & 0xFF);
729 scan->accumulator_count = 0;
730 val = 0;
731 break;
732 }
733
734 if (c == '=') {
735 scan->accumulator_count = 0;
736 scan->accumulator = 0;
737 } else {
738 scan->accumulator = val;
739 }
740 }
741
742 static void
base64_end(csi_t * ctx,csi_scanner_t * scan)743 base64_end (csi_t *ctx, csi_scanner_t *scan)
744 {
745 csi_object_t obj;
746 cairo_status_t status;
747
748 switch (scan->accumulator_count) {
749 case 0:
750 break;
751 case 2:
752 base64_add (ctx, scan, (scan->accumulator << 2) & 0x3f);
753 base64_add (ctx, scan, '=');
754 break;
755 case 1:
756 base64_add (ctx, scan, (scan->accumulator << 4) & 0x3f);
757 base64_add (ctx, scan, '=');
758 base64_add (ctx, scan, '=');
759 break;
760 }
761
762 status = csi_string_new (ctx,
763 &obj,
764 scan->buffer.base,
765 scan->buffer.ptr - scan->buffer.base);
766 if (_csi_unlikely (status))
767 longjmp (scan->jump_buffer, status);
768
769 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
770 status = csi_array_append (ctx,
771 scan->build_procedure.datum.array,
772 &obj);
773 else
774 status = scan_push (ctx, &obj);
775 if (_csi_unlikely (status))
776 longjmp (scan->jump_buffer, status);
777 }
778
779 static void
scan_read(csi_scanner_t * scan,csi_file_t * src,void * ptr,int len)780 scan_read (csi_scanner_t *scan, csi_file_t *src, void *ptr, int len)
781 {
782 uint8_t *data = ptr;
783 do {
784 int ret = csi_file_read (src, data, len);
785 if (_csi_unlikely (ret == 0))
786 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_READ_ERROR));
787 data += ret;
788 len -= ret;
789 } while (_csi_unlikely (len));
790 }
791
792 static void
string_read(csi_t * ctx,csi_scanner_t * scan,csi_file_t * src,int len,int compressed,csi_object_t * obj)793 string_read (csi_t *ctx,
794 csi_scanner_t *scan,
795 csi_file_t *src,
796 int len,
797 int compressed,
798 csi_object_t *obj)
799 {
800 csi_status_t status;
801
802 status = csi_string_new (ctx, obj, NULL, len);
803 if (_csi_unlikely (status))
804 longjmp (scan->jump_buffer, status);
805
806 if (compressed) {
807 uint32_t u32;
808 scan_read (scan, src, &u32, 4);
809 obj->datum.string->deflate = be32 (u32);
810 obj->datum.string->method = compressed;
811 }
812
813 if (_csi_likely (len))
814 scan_read (scan, src, obj->datum.string->string, len);
815 obj->datum.string->string[len] = '\0';
816 }
817
818 static void
_scan_file(csi_t * ctx,csi_file_t * src)819 _scan_file (csi_t *ctx, csi_file_t *src)
820 {
821 csi_scanner_t *scan = &ctx->scanner;
822 int c, next;
823 union {
824 int8_t i8;
825 uint8_t u8;
826 int16_t i16;
827 uint16_t u16;
828 int32_t i32;
829 uint32_t u32;
830 float f;
831 } u;
832 int deflate = 0;
833 int string_p;
834
835 scan_none:
836 while ((c = csi_file_getc (src)) != EOF) {
837 csi_object_t obj = { CSI_OBJECT_TYPE_NULL };
838
839 switch (c) {
840 case 0xa:
841 scan->line_number++;
842 case 0x0:
843 case 0x9:
844 case 0xc:
845 case 0xd:
846 case 0x20: /* ignore whitespace */
847 break;
848
849 case '%':
850 goto scan_comment;
851
852 case '(':
853 goto scan_string;
854
855 case '[': /* needs special case */
856 case ']':
857 case '{':
858 case '}':
859 token_start (scan);
860 token_add_unchecked (scan, c);
861 token_end (ctx, scan, src);
862 goto scan_none;
863
864 case '<':
865 next = csi_file_getc (src);
866 switch (next) {
867 case EOF:
868 csi_file_putc (src, '<');
869 return;
870 case '<':
871 /* dictionary name */
872 token_start (scan);
873 token_add_unchecked (scan, '<');
874 token_add_unchecked (scan, '<');
875 token_end (ctx, scan, src);
876 goto scan_none;
877 case '|':
878 deflate = 1;
879 case '~':
880 goto scan_base85;
881 case '{':
882 goto scan_base64;
883 default:
884 csi_file_putc (src, next);
885 goto scan_hex;
886 }
887 break;
888
889 /* binary token */
890 #define MSB_INT8 128
891 #define MSB_UINT8 129
892 #define MSB_INT16 130
893 #define MSB_UINT16 131
894 #define MSB_INT32 132
895 #define LSB_INT8 MSB_INT8
896 #define LSB_UINT8 MSB_UINT8
897 #define LSB_INT16 133
898 #define LSB_UINT16 134
899 #define LSB_INT32 135
900 #define MSB_FLOAT32 140
901 #define LSB_FLOAT32 141
902 case MSB_INT8:
903 scan_read (scan, src, &u.i8, 1);
904 csi_integer_new (&obj, u.i8);
905 break;
906 case MSB_UINT8:
907 scan_read (scan, src, &u.u8, 1);
908 csi_integer_new (&obj, u.u8);
909 break;
910 case MSB_INT16:
911 scan_read (scan, src, &u.i16, 2);
912 csi_integer_new (&obj, be16 (u.i16));
913 break;
914 case LSB_INT16:
915 scan_read (scan, src, &u.i16, 2);
916 csi_integer_new (&obj, le16 (u.i16));
917 break;
918 case MSB_UINT16:
919 scan_read (scan, src, &u.u16, 2);
920 csi_integer_new (&obj, be16 (u.u16));
921 break;
922 case LSB_UINT16:
923 scan_read (scan, src, &u.u16, 2);
924 csi_integer_new (&obj, le16 (u.u16));
925 break;
926 case MSB_INT32:
927 scan_read (scan, src, &u.i32, 4);
928 csi_integer_new (&obj, be32 (u.i32));
929 break;
930 case LSB_INT32:
931 scan_read (scan, src, &u.i32, 4);
932 csi_integer_new (&obj, le32 (u.i32));
933 break;
934
935 case 136: /* 16.16 msb */
936 scan_read (scan, src, &u.i32, 4);
937 csi_real_new (&obj, be32 (u.i32) / 65536.);
938 break;
939 case 137: /* 16.16 lsb */
940 scan_read (scan, src, &u.i32, 4);
941 csi_real_new (&obj, le32 (u.i32) / 65536.);
942 break;
943 case 138: /* 24.8 msb */
944 scan_read (scan, src, &u.i32, 4);
945 csi_real_new (&obj, be32 (u.i32) / 256.);
946 break;
947 case 139: /* 24.8 lsb */
948 scan_read (scan, src, &u.i32, 4);
949 csi_real_new (&obj, le32 (u.i32) / 256.);
950 break;
951 case MSB_FLOAT32:
952 scan_read (scan, src, &u.i32, 4);
953 u.i32 = be32 (u.i32);
954 csi_real_new (&obj, u.f);
955 break;
956 case LSB_FLOAT32:
957 scan_read (scan, src, &u.i32, 4);
958 u.i32 = le32 (u.i32);
959 csi_real_new (&obj, u.f);
960 break;
961
962 #define STRING_1 142
963 #define STRING_2_MSB 144
964 #define STRING_2_LSB 146
965 #define STRING_4_MSB 148
966 #define STRING_4_LSB 150
967 #define STRING_DEFLATE 1
968 case STRING_1:
969 case STRING_1 | STRING_DEFLATE:
970 scan_read (scan, src, &u.u8, 1);
971 string_read (ctx, scan, src, u.u8, c & STRING_DEFLATE, &obj);
972 break;
973 case STRING_2_MSB:
974 case STRING_2_MSB | STRING_DEFLATE:
975 scan_read (scan, src, &u.u16, 2);
976 string_read (ctx, scan, src, be16 (u.u16), c & STRING_DEFLATE, &obj);
977 break;
978 case STRING_2_LSB:
979 case STRING_2_LSB | STRING_DEFLATE:
980 scan_read (scan, src, &u.u16, 2);
981 string_read (ctx, scan, src, le16 (u.u16), c & STRING_DEFLATE, &obj);
982 break;
983 case STRING_4_MSB:
984 case STRING_4_MSB | STRING_DEFLATE:
985 scan_read (scan, src, &u.u32, 4);
986 string_read (ctx, scan, src, be32 (u.u32), c & STRING_DEFLATE, &obj);
987 break;
988 case STRING_4_LSB:
989 case STRING_4_LSB | STRING_DEFLATE:
990 scan_read (scan, src, &u.u32, 4);
991 string_read (ctx, scan, src, le32 (u.u32), c & STRING_DEFLATE, &obj);
992 break;
993
994 #define OPCODE 152
995 case OPCODE:
996 scan_read (scan, src, &u.u8, 1);
997 csi_operator_new (&obj, ctx->opcode[u.u8]);
998 break;
999
1000 case OPCODE | 1:
1001 scan_read (scan, src, &u.u8, 1);
1002 csi_operator_new (&obj, ctx->opcode[u.u8]);
1003 obj.type &= ~CSI_OBJECT_ATTR_EXECUTABLE;
1004 break;
1005
1006 #define STRING_LZO 154
1007 case STRING_LZO:
1008 scan_read (scan, src, &u.u32, 4);
1009 string_read (ctx, scan, src, be32 (u.u32), LZO, &obj);
1010 break;
1011
1012 /* unassigned */
1013 case 155:
1014 case 156:
1015 case 157:
1016 case 158:
1017 case 159:
1018 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1019
1020 case '#': /* PDF 1.2 escape code */
1021 {
1022 int c_hi = csi_file_getc (src);
1023 int c_lo = csi_file_getc (src);
1024 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
1025 }
1026 /* fall-through */
1027 default:
1028 token_start (scan);
1029 token_add_unchecked (scan, c);
1030 goto scan_token;
1031 }
1032
1033 if (obj.type != CSI_OBJECT_TYPE_NULL) {
1034 cairo_status_t status;
1035
1036 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
1037 status = csi_array_append (ctx,
1038 scan->build_procedure.datum.array,
1039 &obj);
1040 } else if (obj.type & CSI_OBJECT_ATTR_EXECUTABLE) {
1041 status = scan_execute (ctx, &obj);
1042 csi_object_free (ctx, &obj);
1043 } else {
1044 status = scan_push (ctx, &obj);
1045 }
1046 if (_csi_unlikely (status))
1047 longjmp (scan->jump_buffer, status);
1048 }
1049 }
1050 return;
1051
1052 scan_token:
1053 while ((c = csi_file_getc (src)) != EOF) {
1054 switch (c) {
1055 case 0xa:
1056 scan->line_number++;
1057 /* fall through */
1058 case 0x0:
1059 case 0x9:
1060 case 0xc:
1061 case 0xd:
1062 case 0x20:
1063 token_end (ctx, scan, src);
1064 goto scan_none;
1065
1066 /* syntax delimiters */
1067 case '%':
1068 token_end (ctx, scan, src);
1069 goto scan_comment;
1070 /* syntax error? */
1071 case '(':
1072 token_end (ctx, scan, src);
1073 goto scan_string;
1074 /* XXX syntax error? */
1075 case ')':
1076 token_end (ctx, scan, src);
1077 goto scan_none;
1078 case '/':
1079 /* need to special case '^//?' */
1080 if (scan->buffer.ptr > scan->buffer.base+1 ||
1081 scan->buffer.base[0] != '/')
1082 {
1083 token_end (ctx, scan, src);
1084 token_start (scan);
1085 }
1086 token_add_unchecked (scan, '/');
1087 goto scan_token;
1088
1089 case '{':
1090 case '}':
1091 case ']':
1092 token_end (ctx, scan, src);
1093 token_start (scan);
1094 token_add_unchecked (scan, c);
1095 token_end (ctx, scan, src);
1096 goto scan_none;
1097
1098 case '<':
1099 csi_file_putc (src, '<');
1100 token_end (ctx, scan, src);
1101 goto scan_none;
1102
1103 case '#': /* PDF 1.2 escape code */
1104 {
1105 int c_hi = csi_file_getc (src);
1106 int c_lo = csi_file_getc (src);
1107 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
1108 }
1109 /* fall-through */
1110 default:
1111 token_add (ctx, scan, c);
1112 break;
1113 }
1114 }
1115 token_end (ctx, scan, src);
1116 return;
1117
1118 scan_comment:
1119 /* discard until newline */
1120 while ((c = csi_file_getc (src)) != EOF) {
1121 switch (c) {
1122 case 0xa:
1123 scan->line_number++;
1124 case 0xc:
1125 goto scan_none;
1126 }
1127 }
1128 return;
1129
1130 scan_string:
1131 buffer_reset (&scan->buffer);
1132 string_p = 1;
1133 while ((c = csi_file_getc (src)) != EOF) {
1134 switch (c) {
1135 case '\\': /* escape */
1136 next = csi_file_getc (src);
1137 switch (next) {
1138 case EOF:
1139 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1140
1141 case 'n':
1142 string_add (ctx, scan, '\n');
1143 break;
1144 case 'r':
1145 string_add (ctx, scan, '\r');
1146 break;
1147 case 't':
1148 string_add (ctx, scan, '\t');
1149 break;
1150 case 'b':
1151 string_add (ctx, scan, '\b');
1152 break;
1153 case 'f':
1154 string_add (ctx, scan, '\f');
1155 break;
1156 case '\\':
1157 string_add (ctx, scan, '\\');
1158 break;
1159 case '(':
1160 string_add (ctx, scan, '(');
1161 break;
1162 case ')':
1163 string_add (ctx, scan, ')');
1164 break;
1165
1166 case '0': case '1': case '2': case '3':
1167 case '4': case '5': case '6': case '7':
1168 { /* octal code: \d{1,3} */
1169 int i;
1170
1171 c = next - '0';
1172
1173 for (i = 0; i < 2; i++) {
1174 next = csi_file_getc (src);
1175 switch (next) {
1176 case EOF:
1177 return;
1178
1179 case '0': case '1': case '2': case '3':
1180 case '4': case '5': case '6': case '7':
1181 c = 8*c + next-'0';
1182 break;
1183
1184 default:
1185 csi_file_putc (src, next);
1186 goto octal_code_done;
1187 }
1188 }
1189 octal_code_done:
1190 string_add (ctx, scan, c);
1191 }
1192 break;
1193
1194 case 0xa:
1195 /* skip the newline */
1196 next = csi_file_getc (src); /* might be compound LFCR */
1197 switch (next) {
1198 case EOF:
1199 return;
1200 case 0xc:
1201 break;
1202 default:
1203 csi_file_putc (src, next);
1204 break;
1205 }
1206 scan->line_number++;
1207 break;
1208 case 0xc:
1209 break;
1210
1211 default:
1212 /* ignore the '\' */
1213 break;
1214 }
1215 break;
1216
1217 case '(':
1218 string_p++;
1219 string_add (ctx, scan, c);
1220 break;
1221
1222 case ')':
1223 if (--string_p == 0) {
1224 string_end (ctx, scan);
1225 goto scan_none;
1226 }
1227 /* fall through */
1228 default:
1229 string_add (ctx, scan, c);
1230 break;
1231 }
1232 }
1233 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1234
1235 scan_hex:
1236 buffer_reset (&scan->buffer);
1237 scan->accumulator_count = 0;
1238 scan->accumulator = 0;
1239 while ((c = csi_file_getc (src)) != EOF) {
1240 switch (c) {
1241 case 0xa:
1242 scan->line_number++;
1243 case 0x0:
1244 case 0x9:
1245 case 0xc:
1246 case 0xd:
1247 case 0x20: /* ignore whitespace */
1248 break;
1249
1250 case '>':
1251 hex_end (ctx, scan); /* fixup odd digit with '0' */
1252 goto scan_none;
1253
1254 case '0':
1255 case '1':
1256 case '2':
1257 case '3':
1258 case '4':
1259 case '5':
1260 case '6':
1261 case '7':
1262 case '8':
1263 case '9':
1264 case 'a':
1265 case 'b':
1266 case 'c':
1267 case 'd':
1268 case 'e':
1269 case 'f':
1270 case 'A':
1271 case 'B':
1272 case 'C':
1273 case 'D':
1274 case 'E':
1275 case 'F':
1276 hex_add (ctx, scan, c);
1277 break;
1278
1279 default:
1280 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1281 }
1282 }
1283 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1284
1285 scan_base85:
1286 buffer_reset (&scan->buffer);
1287 scan->accumulator = 0;
1288 scan->accumulator_count = 0;
1289 while ((c = csi_file_getc (src)) != EOF) {
1290 switch (c) {
1291 case '~':
1292 next = csi_file_getc (src);
1293 switch (next) {
1294 case EOF:
1295 return;
1296
1297 case '>':
1298 base85_end (ctx, scan, deflate);
1299 deflate = 0;
1300 goto scan_none;
1301 }
1302 csi_file_putc (src, next);
1303
1304 /* fall-through */
1305 default:
1306 base85_add (ctx, scan, c);
1307 break;
1308 }
1309 }
1310 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1311
1312 scan_base64:
1313 buffer_reset (&scan->buffer);
1314 scan->accumulator = 0;
1315 scan->accumulator_count = 0;
1316 while ((c = csi_file_getc (src)) != EOF) {
1317 switch (c) {
1318 case '}':
1319 next = csi_file_getc (src);
1320 switch (next) {
1321 case EOF:
1322 return;
1323
1324 case '>':
1325 base64_end (ctx, scan);
1326 goto scan_none;
1327 }
1328 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1329
1330 default:
1331 base64_add (ctx, scan, c);
1332 break;
1333 }
1334 }
1335 longjmp (scan->jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1336 }
1337
1338 static csi_status_t
_scan_push(csi_t * ctx,csi_object_t * obj)1339 _scan_push (csi_t *ctx, csi_object_t *obj)
1340 {
1341 if (DEBUG_SCAN) {
1342 fprintf (stderr, "push ");
1343 fprintf_obj (stderr, ctx, obj);
1344 }
1345 return _csi_push_ostack (ctx, obj);
1346 }
1347
1348 static csi_status_t
_scan_execute(csi_t * ctx,csi_object_t * obj)1349 _scan_execute (csi_t *ctx, csi_object_t *obj)
1350 {
1351 if (DEBUG_SCAN) {
1352 fprintf (stderr, "exec ");
1353 fprintf_obj (stderr, ctx, obj);
1354 }
1355 return csi_object_execute (ctx, obj);
1356 }
1357
1358 csi_status_t
_csi_scanner_init(csi_t * ctx,csi_scanner_t * scanner)1359 _csi_scanner_init (csi_t *ctx, csi_scanner_t *scanner)
1360 {
1361 csi_status_t status;
1362
1363 memset (scanner, 0, sizeof (csi_scanner_t));
1364
1365 status = buffer_init (ctx, &scanner->buffer);
1366 if (status)
1367 return status;
1368
1369 status = _csi_stack_init (ctx, &scanner->procedure_stack, 4);
1370 if (status)
1371 return status;
1372
1373 scanner->bind = 0;
1374 scanner->push = _scan_push;
1375 scanner->execute = _scan_execute;
1376
1377 return CSI_STATUS_SUCCESS;
1378 }
1379
1380 void
_csi_scanner_fini(csi_t * ctx,csi_scanner_t * scanner)1381 _csi_scanner_fini (csi_t *ctx, csi_scanner_t *scanner)
1382 {
1383 buffer_fini (ctx, &scanner->buffer);
1384 _csi_stack_fini (ctx, &scanner->procedure_stack);
1385 if (scanner->build_procedure.type != CSI_OBJECT_TYPE_NULL)
1386 csi_object_free (ctx, &scanner->build_procedure);
1387 }
1388
1389 csi_status_t
_csi_scan_file(csi_t * ctx,csi_file_t * src)1390 _csi_scan_file (csi_t *ctx, csi_file_t *src)
1391 {
1392 csi_status_t status;
1393 int old_line_number;
1394
1395 /* This function needs to be reentrant to handle recursive scanners.
1396 * i.e. one script executes a second.
1397 */
1398
1399 if (ctx->scanner.depth++ == 0) {
1400 if ((status = setjmp (ctx->scanner.jump_buffer))) {
1401 ctx->scanner.depth = 0;
1402 return status;
1403 }
1404 }
1405
1406 old_line_number = ctx->scanner.line_number;
1407 ctx->scanner.line_number = 0;
1408
1409 _scan_file (ctx, src);
1410
1411 ctx->scanner.line_number = old_line_number;
1412
1413 --ctx->scanner.depth;
1414 return CSI_STATUS_SUCCESS;
1415 }
1416
1417 struct _translate_closure {
1418 csi_dictionary_t *opcodes;
1419 cairo_write_func_t write_func;
1420 void *closure;
1421 };
1422
1423 static csi_status_t
_translate_name(csi_t * ctx,csi_name_t name,csi_boolean_t executable,struct _translate_closure * closure)1424 _translate_name (csi_t *ctx,
1425 csi_name_t name,
1426 csi_boolean_t executable,
1427 struct _translate_closure *closure)
1428 {
1429 if (executable) {
1430 csi_dictionary_entry_t *entry;
1431 uint16_t u16;
1432
1433 /* Bind executable names.
1434 * XXX This may break some scripts that overload system operators.
1435 */
1436 entry = _csi_hash_table_lookup (&closure->opcodes->hash_table,
1437 (csi_hash_entry_t *) &name);
1438 if (entry == NULL)
1439 goto STRING;
1440
1441 u16 = entry->value.datum.integer;
1442 u16 = be16 (u16);
1443 closure->write_func (closure->closure, (unsigned char *) &u16, 2);
1444 } else {
1445 closure->write_func (closure->closure, (unsigned char *) "/", 1);
1446 STRING:
1447 closure->write_func (closure->closure,
1448 (unsigned char *) name,
1449 strlen ((char *) name));
1450 closure->write_func (closure->closure, (unsigned char *) "\n", 1);
1451 }
1452
1453 return CSI_STATUS_SUCCESS;
1454 }
1455
1456 static csi_status_t
_translate_operator(csi_t * ctx,csi_operator_t op,csi_boolean_t executable,struct _translate_closure * closure)1457 _translate_operator (csi_t *ctx,
1458 csi_operator_t op,
1459 csi_boolean_t executable,
1460 struct _translate_closure *closure)
1461 {
1462 csi_dictionary_entry_t *entry;
1463 uint16_t u16;
1464
1465 entry = _csi_hash_table_lookup (&closure->opcodes->hash_table,
1466 (csi_hash_entry_t *) &op);
1467 if (entry == NULL)
1468 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
1469
1470 u16 = entry->value.datum.integer;
1471 if (! executable)
1472 u16 += 1 << 8;
1473 u16 = be16 (u16);
1474 closure->write_func (closure->closure, (unsigned char *) &u16, 2);
1475
1476 return CSI_STATUS_SUCCESS;
1477 }
1478
1479 static csi_status_t
_translate_integer(csi_t * ctx,csi_integer_t i,struct _translate_closure * closure)1480 _translate_integer (csi_t *ctx,
1481 csi_integer_t i,
1482 struct _translate_closure *closure)
1483 {
1484 uint8_t hdr;
1485 union {
1486 int8_t i8;
1487 uint8_t u8;
1488 int16_t i16;
1489 uint16_t u16;
1490 int32_t i32;
1491 uint32_t u32;
1492 } u;
1493 int len;
1494
1495 #if WORDS_BIGENDIAN
1496 if (i < INT16_MIN) {
1497 hdr = MSB_INT32;
1498 len = 4;
1499 u.i32 = i;
1500 } else if (i < INT8_MIN) {
1501 hdr = MSB_INT16;
1502 len = 2;
1503 u.i16 = i;
1504 } else if (i < 0) {
1505 hdr = MSB_INT8;
1506 len = 1;
1507 u.i8 = i;
1508 } else if (i <= UINT8_MAX) {
1509 hdr = MSB_UINT8;
1510 len = 1;
1511 u.u8 = i;
1512 } else if (i <= UINT16_MAX) {
1513 hdr = MSB_UINT16;
1514 len = 2;
1515 u.u16 = i;
1516 } else {
1517 hdr = MSB_INT32;
1518 len = 4;
1519 u.u32 = i;
1520 }
1521 #else
1522 if (i < INT16_MIN) {
1523 hdr = LSB_INT32;
1524 len = 4;
1525 u.i32 = i;
1526 } else if (i < INT8_MIN) {
1527 hdr = LSB_INT16;
1528 len = 2;
1529 u.i16 = i;
1530 } else if (i < 0) {
1531 hdr = LSB_INT8;
1532 len = 1;
1533 u.i8 = i;
1534 } else if (i <= UINT8_MAX) {
1535 hdr = LSB_UINT8;
1536 len = 1;
1537 u.u8 = i;
1538 } else if (i <= UINT16_MAX) {
1539 hdr = LSB_UINT16;
1540 len = 2;
1541 u.u16 = i;
1542 } else {
1543 hdr = LSB_INT32;
1544 len = 4;
1545 u.u32 = i;
1546 }
1547 #endif
1548
1549 closure->write_func (closure->closure, (unsigned char *) &hdr, 1);
1550 closure->write_func (closure->closure, (unsigned char *) &u, len);
1551
1552 return CSI_STATUS_SUCCESS;
1553 }
1554
1555 static csi_status_t
_translate_real(csi_t * ctx,csi_real_t real,struct _translate_closure * closure)1556 _translate_real (csi_t *ctx,
1557 csi_real_t real,
1558 struct _translate_closure *closure)
1559 {
1560 uint8_t hdr;
1561
1562 if (real >= INT32_MIN && real <= INT32_MAX && (int) real == real)
1563 return _translate_integer (ctx, real, closure);
1564
1565 #if WORDS_BIGENDIAN
1566 hdr = MSB_FLOAT32;
1567 #else
1568 hdr = LSB_FLOAT32;
1569 #endif
1570 closure->write_func (closure->closure, (unsigned char *) &hdr, 1);
1571 closure->write_func (closure->closure, (unsigned char *) &real, 4);
1572
1573 return CSI_STATUS_SUCCESS;
1574 }
1575
1576 static csi_status_t
_translate_string(csi_t * ctx,csi_string_t * string,struct _translate_closure * closure)1577 _translate_string (csi_t *ctx,
1578 csi_string_t *string,
1579 struct _translate_closure *closure)
1580 {
1581 uint8_t hdr;
1582 union {
1583 uint8_t u8;
1584 uint16_t u16;
1585 uint32_t u32;
1586 } u;
1587 void *buf;
1588 unsigned long hdr_len, buf_len, deflate;
1589 int method;
1590
1591 buf = string->string;
1592 buf_len = string->len;
1593 deflate = string->deflate;
1594 method = string->method;
1595
1596 #if HAVE_LZO
1597 if (method == NONE && buf_len > 16) {
1598 unsigned long mem_len = 2*string->len > LZO2A_999_MEM_COMPRESS ? 2*string->len : LZO2A_999_MEM_COMPRESS;
1599 void *mem = malloc (mem_len);
1600 void *work = malloc(LZO2A_999_MEM_COMPRESS);
1601
1602 if (lzo2a_999_compress ((lzo_bytep) buf, buf_len,
1603 (lzo_bytep) mem, &mem_len,
1604 work) == 0 &&
1605 8+2*mem_len < buf_len)
1606 {
1607 method = LZO;
1608 deflate = buf_len;
1609 buf_len = mem_len;
1610 buf = mem;
1611 }
1612 else
1613 {
1614 free (mem);
1615 }
1616
1617 free (work);
1618 }
1619 #if HAVE_ZLIB
1620 if (method == ZLIB) {
1621 buf_len = string->deflate;
1622 buf = malloc (string->deflate);
1623 if (uncompress ((Bytef *) buf, &buf_len,
1624 (Bytef *) string->string, string->len) == Z_OK)
1625 {
1626 assert(string->len > 0);
1627 if (buf_len <= 8 + 2*((unsigned long)string->len)) {
1628 method = NONE;
1629 deflate = 0;
1630 } else {
1631 unsigned long mem_len = 2*string->deflate;
1632 void *mem = malloc (mem_len);
1633 void *work = malloc(LZO2A_999_MEM_COMPRESS);
1634
1635 if (lzo2a_999_compress ((lzo_bytep) buf, buf_len,
1636 (lzo_bytep) mem, &mem_len,
1637 work) == 0)
1638 {
1639 if (8 + mem_len > buf_len) {
1640 method = NONE;
1641 deflate = 0;
1642 } else {
1643 free (buf);
1644 method = LZO;
1645 deflate = buf_len;
1646 buf_len = mem_len;
1647 buf = mem;
1648 assert(deflate);
1649 }
1650 }
1651 else
1652 {
1653 free (buf);
1654 buf = string->string;
1655 buf_len = string->len;
1656 }
1657
1658 free (work);
1659 }
1660 }
1661 else
1662 {
1663 free (buf);
1664 buf = string->string;
1665 buf_len = string->len;
1666 }
1667 }
1668 #endif
1669 #endif
1670
1671 if (method == LZO) {
1672 hdr = STRING_LZO;
1673 u.u32 = to_be32 (buf_len);
1674 hdr_len = 4;
1675 } else {
1676 #if WORDS_BIGENDIAN
1677 if (buf_len <= UINT8_MAX) {
1678 hdr = STRING_1;
1679 u.u8 = buf_len;
1680 hdr_len = 1;
1681 } else if (buf_len <= UINT16_MAX) {
1682 hdr = STRING_2_MSB;
1683 u.u16 = buf_len;
1684 hdr_len = 2;
1685 } else {
1686 hdr = STRING_4_MSB;
1687 u.u32 = buf_len;
1688 hdr_len = 4;
1689 }
1690 #else
1691 if (buf_len <= UINT8_MAX) {
1692 hdr = STRING_1;
1693 u.u8 = buf_len;
1694 hdr_len = 1;
1695 } else if (buf_len <= UINT16_MAX) {
1696 hdr = STRING_2_LSB;
1697 u.u16 = buf_len;
1698 hdr_len = 2;
1699 } else {
1700 hdr = STRING_4_LSB;
1701 u.u32 = buf_len;
1702 hdr_len = 4;
1703 }
1704 #endif
1705 if (deflate) {
1706 assert (method == ZLIB);
1707 hdr |= STRING_DEFLATE;
1708 }
1709 }
1710
1711 closure->write_func (closure->closure, (unsigned char *) &hdr, 1);
1712 closure->write_func (closure->closure, (unsigned char *) &u, hdr_len);
1713 if (deflate) {
1714 uint32_t u32 = to_be32 (deflate);
1715 closure->write_func (closure->closure, (unsigned char *) &u32, 4);
1716 }
1717 closure->write_func (closure->closure, (unsigned char *) buf, buf_len);
1718
1719 if (buf != string->string)
1720 free (buf);
1721
1722 return CSI_STATUS_SUCCESS;
1723 }
1724
1725 static csi_status_t
_translate_push(csi_t * ctx,csi_object_t * obj)1726 _translate_push (csi_t *ctx, csi_object_t *obj)
1727 {
1728 struct _translate_closure *closure = ctx->scanner.closure;
1729
1730 if (0) {
1731 fprintf (stderr, "push ");
1732 fprintf_obj (stderr, ctx, obj);
1733 }
1734
1735 switch (csi_object_get_type (obj)) {
1736 case CSI_OBJECT_TYPE_NAME:
1737 return _translate_name (ctx, obj->datum.name, FALSE, closure);
1738
1739 case CSI_OBJECT_TYPE_OPERATOR:
1740 return _translate_operator (ctx, obj->datum.op, FALSE, closure);
1741
1742 case CSI_OBJECT_TYPE_INTEGER:
1743 return _translate_integer (ctx, obj->datum.integer, closure);
1744
1745 case CSI_OBJECT_TYPE_REAL:
1746 return _translate_real (ctx, obj->datum.real, closure);
1747
1748 case CSI_OBJECT_TYPE_STRING:
1749 return _translate_string (ctx, obj->datum.string, closure);
1750
1751 case CSI_OBJECT_TYPE_NULL:
1752 case CSI_OBJECT_TYPE_BOOLEAN:
1753 case CSI_OBJECT_TYPE_MARK:
1754 case CSI_OBJECT_TYPE_ARRAY:
1755 case CSI_OBJECT_TYPE_DICTIONARY:
1756 case CSI_OBJECT_TYPE_FILE:
1757 case CSI_OBJECT_TYPE_MATRIX:
1758 case CSI_OBJECT_TYPE_CONTEXT:
1759 case CSI_OBJECT_TYPE_FONT:
1760 case CSI_OBJECT_TYPE_PATTERN:
1761 case CSI_OBJECT_TYPE_SCALED_FONT:
1762 case CSI_OBJECT_TYPE_SURFACE:
1763 longjmp (ctx->scanner.jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1764 break;
1765 }
1766
1767 csi_object_free (ctx, obj);
1768 return CSI_STATUS_SUCCESS;
1769 }
1770
1771 static csi_status_t
_translate_execute(csi_t * ctx,csi_object_t * obj)1772 _translate_execute (csi_t *ctx, csi_object_t *obj)
1773 {
1774 struct _translate_closure *closure = ctx->scanner.closure;
1775
1776 if (0) {
1777 fprintf (stderr, "exec ");
1778 fprintf_obj (stderr, ctx, obj);
1779 }
1780
1781 switch (csi_object_get_type (obj)) {
1782 case CSI_OBJECT_TYPE_NAME:
1783 return _translate_name (ctx, obj->datum.name, TRUE, closure);
1784
1785 case CSI_OBJECT_TYPE_OPERATOR:
1786 return _translate_operator (ctx, obj->datum.op, TRUE, closure);
1787
1788 case CSI_OBJECT_TYPE_INTEGER:
1789 return _translate_integer (ctx, obj->datum.integer, closure);
1790
1791 case CSI_OBJECT_TYPE_REAL:
1792 return _translate_real (ctx, obj->datum.real, closure);
1793
1794 case CSI_OBJECT_TYPE_STRING:
1795 return _translate_string (ctx, obj->datum.string, closure);
1796
1797 case CSI_OBJECT_TYPE_NULL:
1798 case CSI_OBJECT_TYPE_BOOLEAN:
1799 case CSI_OBJECT_TYPE_MARK:
1800 case CSI_OBJECT_TYPE_ARRAY:
1801 case CSI_OBJECT_TYPE_DICTIONARY:
1802 case CSI_OBJECT_TYPE_FILE:
1803 case CSI_OBJECT_TYPE_MATRIX:
1804 case CSI_OBJECT_TYPE_CONTEXT:
1805 case CSI_OBJECT_TYPE_FONT:
1806 case CSI_OBJECT_TYPE_PATTERN:
1807 case CSI_OBJECT_TYPE_SCALED_FONT:
1808 case CSI_OBJECT_TYPE_SURFACE:
1809 longjmp (ctx->scanner.jump_buffer, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1810 break;
1811 }
1812
1813 return CSI_STATUS_SUCCESS;
1814 }
1815
1816 static csi_status_t
build_opcodes(csi_t * ctx,csi_dictionary_t ** out)1817 build_opcodes (csi_t *ctx, csi_dictionary_t **out)
1818 {
1819 csi_object_t obj;
1820 csi_dictionary_t *dict;
1821 const csi_operator_def_t *def;
1822 csi_status_t status;
1823 int opcode = OPCODE << 8;
1824
1825 status = csi_dictionary_new (ctx, &obj);
1826 if (_csi_unlikely (status))
1827 return status;
1828
1829 dict = obj.datum.dictionary;
1830
1831 csi_integer_new (&obj, opcode++);
1832 status = csi_dictionary_put (ctx, dict, 0, &obj);
1833 if (_csi_unlikely (status))
1834 goto FAIL;
1835
1836 for (def = _csi_operators (); def->name != NULL; def++) {
1837 csi_object_t name;
1838 csi_dictionary_entry_t *entry;
1839 int code;
1840
1841 entry = _csi_hash_table_lookup (&dict->hash_table,
1842 (csi_hash_entry_t *) &def->op);
1843 if (entry == NULL) {
1844 code = opcode++;
1845 csi_integer_new (&obj, code);
1846 status = csi_dictionary_put (ctx, dict, (csi_name_t) def->op, &obj);
1847 if (_csi_unlikely (status))
1848 goto FAIL;
1849 } else {
1850 code = entry->value.datum.integer;
1851 csi_integer_new (&obj, code);
1852 }
1853 assert (ctx->opcode[code & 0xff] == def->op);
1854
1855 status = csi_name_new_static (ctx, &name, def->name);
1856 if (_csi_unlikely (status))
1857 goto FAIL;
1858
1859 status = csi_dictionary_put (ctx, dict, name.datum.name, &obj);
1860 if (_csi_unlikely (status))
1861 goto FAIL;
1862 }
1863
1864 *out = dict;
1865 return CSI_STATUS_SUCCESS;
1866
1867 FAIL:
1868 csi_dictionary_free (ctx, dict);
1869 return status;
1870 }
1871
1872 csi_status_t
_csi_translate_file(csi_t * ctx,csi_file_t * file,cairo_write_func_t write_func,void * closure)1873 _csi_translate_file (csi_t *ctx,
1874 csi_file_t *file,
1875 cairo_write_func_t write_func,
1876 void *closure)
1877 {
1878 csi_status_t status;
1879 struct _translate_closure translator;
1880
1881 if ((status = setjmp (ctx->scanner.jump_buffer)))
1882 return status;
1883
1884 status = build_opcodes (ctx, &translator.opcodes);
1885 if (_csi_unlikely (status))
1886 return status;
1887
1888 translator.write_func = write_func;
1889 translator.closure = closure;
1890 ctx->scanner.closure = &translator;
1891
1892 ctx->scanner.bind = 1;
1893 ctx->scanner.push = _translate_push;
1894 ctx->scanner.execute = _translate_execute;
1895
1896 _scan_file (ctx, file);
1897
1898 ctx->scanner.bind = 0;
1899 ctx->scanner.push = _scan_push;
1900 ctx->scanner.execute = _scan_execute;
1901
1902 csi_dictionary_free (ctx, translator.opcodes);
1903
1904 return CSI_STATUS_SUCCESS;
1905 }
1906