2 * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk>
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.
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
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/
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.
27 * The Original Code is the cairo graphics library.
29 * The Initial Developer of the Original Code is Chris Wilson.
32 * Chris Wilson <chris@chris-wilson.co.uk>
35 #include "cairo-script-private.h"
37 #include <limits.h> /* INT_MAX */
38 #include <math.h> /* pow */
39 #include <stdio.h> /* EOF */
40 #include <stdint.h> /* for {INT,UINT}*_{MIN,MAX} */
41 #include <string.h> /* memset */
48 #define le16(x) bswap_16 (x)
49 #define le32(x) bswap_32 (x)
56 #define be16(x) bswap_16 (x)
57 #define be32(x) bswap_32 (x)
58 #define to_be32(x) bswap_32 (x)
70 * ( = 28, ) = 29 - literal strings
71 * < = 3C, > = 3E - hex/base85 strings, dictionary name
72 * [ = 5B, ] = 5D - array
73 * { = 7B, } = 7C - procedure
74 * / = 5C - literal marker
79 fprintf_obj (FILE *stream, csi_t *ctx, const csi_object_t *obj)
81 switch (csi_object_get_type (obj)) {
82 case CSI_OBJECT_TYPE_NULL:
83 fprintf (stream, "NULL\n");
87 case CSI_OBJECT_TYPE_BOOLEAN:
88 fprintf (stream, "boolean: %s\n",
89 obj->datum.boolean ? "true" : "false");
91 case CSI_OBJECT_TYPE_INTEGER:
92 fprintf (stream, "integer: %ld\n", obj->datum.integer);
94 case CSI_OBJECT_TYPE_MARK:
95 fprintf (stream, "mark\n");
97 case CSI_OBJECT_TYPE_NAME:
98 fprintf (stream, "name: %s\n", (char *) obj->datum.name);
100 case CSI_OBJECT_TYPE_OPERATOR:
101 fprintf (stream, "operator: %p\n", obj->datum.ptr);
103 case CSI_OBJECT_TYPE_REAL:
104 fprintf (stream, "real: %g\n", obj->datum.real);
108 case CSI_OBJECT_TYPE_ARRAY:
109 fprintf (stream, "array\n");
111 case CSI_OBJECT_TYPE_DICTIONARY:
112 fprintf (stream, "dictionary\n");
114 case CSI_OBJECT_TYPE_FILE:
115 fprintf (stream, "file\n");
117 case CSI_OBJECT_TYPE_MATRIX:
118 fprintf (stream, "matrix: [%g %g %g %g %g %g]\n",
119 obj->datum.matrix->matrix.xx,
120 obj->datum.matrix->matrix.yx,
121 obj->datum.matrix->matrix.xy,
122 obj->datum.matrix->matrix.yy,
123 obj->datum.matrix->matrix.x0,
124 obj->datum.matrix->matrix.y0);
126 case CSI_OBJECT_TYPE_STRING:
127 fprintf (stream, "string: len=%ld\n", obj->datum.string->len);
131 case CSI_OBJECT_TYPE_CONTEXT:
132 fprintf (stream, "context\n");
134 case CSI_OBJECT_TYPE_FONT:
135 fprintf (stream, "font\n");
137 case CSI_OBJECT_TYPE_PATTERN:
138 fprintf (stream, "pattern\n");
140 case CSI_OBJECT_TYPE_SCALED_FONT:
141 fprintf (stream, "scaled-font\n");
143 case CSI_OBJECT_TYPE_SURFACE:
144 fprintf (stream, "surface\n");
149 /* takes ownership of obj */
150 static inline csi_status_t
151 scan_push (csi_t *ctx, csi_object_t *obj)
153 return ctx->scanner.push (ctx, obj);
156 static inline csi_status_t
157 scan_execute (csi_t *ctx, csi_object_t *obj)
159 return ctx->scanner.execute (ctx, obj);
162 static cairo_status_t
163 buffer_init (csi_t *ctx, csi_buffer_t *buffer)
165 cairo_status_t status = CSI_STATUS_SUCCESS;
167 buffer->size = 16384;
168 buffer->base = _csi_alloc (ctx, buffer->size);
169 if (_csi_unlikely (buffer->base == NULL)) {
170 status = _csi_error (CSI_STATUS_NO_MEMORY);
174 buffer->ptr = buffer->base;
175 buffer->end = buffer->base + buffer->size;
181 buffer_fini (csi_t *ctx, csi_buffer_t *buffer)
183 _csi_free (ctx, buffer->base);
187 _buffer_grow (csi_t *ctx, csi_scanner_t *scan)
193 if (_csi_unlikely (scan->buffer.size > INT_MAX / 2))
194 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_NO_MEMORY));
196 offset = scan->buffer.ptr - scan->buffer.base;
197 newsize = scan->buffer.size * 2;
198 base = _csi_realloc (ctx, scan->buffer.base, newsize);
199 if (_csi_unlikely (base == NULL))
200 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_NO_MEMORY));
202 scan->buffer.base = base;
203 scan->buffer.ptr = base + offset;
204 scan->buffer.end = base + newsize;
205 scan->buffer.size = newsize;
209 buffer_check (csi_t *ctx, csi_scanner_t *scan, int count)
211 if (_csi_unlikely (scan->buffer.ptr + count > scan->buffer.end))
212 _buffer_grow (ctx, scan);
216 buffer_add (csi_buffer_t *buffer, int c)
222 buffer_reset (csi_buffer_t *buffer)
224 buffer->ptr = buffer->base;
228 token_start (csi_scanner_t *scan)
230 buffer_reset (&scan->buffer);
234 token_add (csi_t *ctx, csi_scanner_t *scan, int c)
236 buffer_check (ctx, scan, 1);
237 buffer_add (&scan->buffer, c);
241 token_add_unchecked (csi_scanner_t *scan, int c)
243 buffer_add (&scan->buffer, c);
247 _csi_parse_number (csi_object_t *obj, const char *s, int len)
250 long long mantissa = 0;
254 int exponent_sign = 0;
255 const char * const end = s + len;
284 if (_csi_unlikely (radix))
286 if (_csi_unlikely (decimal != -1))
288 if (_csi_unlikely (exponent_sign))
292 } else if (*s == '!') {
293 if (_csi_unlikely (radix))
295 if (_csi_unlikely (decimal != -1))
297 if (_csi_unlikely (exponent_sign))
303 if (_csi_unlikely (radix < 2 || radix > 36))
307 } else if (*s <= '9') {
309 if (_csi_unlikely (radix && v >= radix))
313 exponent = 10 * exponent + v;
316 mantissa = radix * mantissa + v;
318 mantissa = 10 * mantissa + v;
322 } else if (*s == 'E' || * s== 'e') {
324 if (_csi_unlikely (s + 1 == end))
331 } else if (s[1] == '+')
336 if (_csi_unlikely (v >= radix))
339 mantissa = radix * mantissa + v;
341 } else if (*s < 'A') {
343 } else if (*s <= 'Z') {
344 int v = *s - 'A' + 0xA;
346 if (_csi_unlikely (v >= radix))
349 mantissa = radix * mantissa + v;
350 } else if (*s < 'a') {
352 } else if (*s <= 'z') {
353 int v = *s - 'a' + 0xa;
355 if (_csi_unlikely (v >= radix))
358 mantissa = radix * mantissa + v;
363 if (exponent_sign || decimal != -1) {
365 obj->type = CSI_OBJECT_TYPE_REAL;
366 obj->datum.real = 0.;
373 e = exponent * exponent_sign;
377 case -7: v *= 0.0000001; break;
378 case -6: v *= 0.000001; break;
379 case -5: v *= 0.00001; break;
380 case -4: v *= 0.0001; break;
381 case -3: v *= 0.001; break;
382 case -2: v *= 0.01; break;
383 case -1: v *= 0.1; break;
385 case 1: v *= 10; break;
386 case 2: v *= 100; break;
387 case 3: v *= 1000; break;
388 case 4: v *= 10000; break;
389 case 5: v *= 100000; break;
390 case 6: v *= 1000000; break;
392 v *= pow (10, e); /* XXX */
396 obj->type = CSI_OBJECT_TYPE_REAL;
397 obj->datum.real = sign * v;
401 obj->type = CSI_OBJECT_TYPE_INTEGER;
402 obj->datum.integer = sign * mantissa;
408 token_end (csi_t *ctx, csi_scanner_t *scan, csi_file_t *src)
410 cairo_status_t status;
416 * Any token that consists entirely of regular characters and
417 * cannot be interpreted as a number is treated as a name object
418 * (more precisely, an executable name). All characters except
419 * delimiters and white-space characters can appear in names,
420 * including characters ordinarily considered to be punctuation.
423 if (_csi_unlikely (scan->buffer.ptr == scan->buffer.base))
426 s = scan->buffer.base;
427 len = scan->buffer.ptr - scan->buffer.base;
429 if (_csi_likely (! scan->bind)) {
430 if (s[0] == '{') { /* special case procedures */
431 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
432 status = _csi_stack_push (ctx,
433 &scan->procedure_stack,
434 &scan->build_procedure);
435 if (_csi_unlikely (status))
436 longjmp (scan->jmpbuf, status);
439 status = csi_array_new (ctx, 0, &scan->build_procedure);
440 if (_csi_unlikely (status))
441 longjmp (scan->jmpbuf, status);
443 scan->build_procedure.type |= CSI_OBJECT_ATTR_EXECUTABLE;
445 } else if (s[0] == '}') {
447 (scan->build_procedure.type == CSI_OBJECT_TYPE_NULL))
449 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
452 if (scan->procedure_stack.len) {
455 next = _csi_stack_peek (&scan->procedure_stack, 0);
456 status = csi_array_append (ctx, next->datum.array,
457 &scan->build_procedure);
458 scan->build_procedure = *next;
459 scan->procedure_stack.len--;
461 status = scan_push (ctx, &scan->build_procedure);
462 scan->build_procedure.type = CSI_OBJECT_TYPE_NULL;
464 if (_csi_unlikely (status))
465 longjmp (scan->jmpbuf, status);
472 if (len >= 2 && s[1] == '/') { /* substituted name */
473 status = csi_name_new (ctx, &obj, s + 2, len - 2);
474 if (_csi_unlikely (status))
475 longjmp (scan->jmpbuf, status);
477 status = _csi_name_lookup (ctx, obj.datum.name, &obj);
478 } else { /* literal name */
479 status = csi_name_new (ctx, &obj, s + 1, len - 1);
481 if (_csi_unlikely (status))
482 longjmp (scan->jmpbuf, status);
484 if (! _csi_parse_number (&obj, s, len)) {
485 status = csi_name_new (ctx, &obj, s, len);
486 if (_csi_unlikely (status))
487 longjmp (scan->jmpbuf, status);
489 obj.type |= CSI_OBJECT_ATTR_EXECUTABLE;
493 /* consume whitespace after token, before calling the interpreter */
494 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
495 status = csi_array_append (ctx,
496 scan->build_procedure.datum.array,
498 } else if (obj.type & CSI_OBJECT_ATTR_EXECUTABLE) {
499 status = scan_execute (ctx, &obj);
500 csi_object_free (ctx, &obj);
502 status = scan_push (ctx, &obj);
504 if (_csi_unlikely (status))
505 longjmp (scan->jmpbuf, status);
509 string_add (csi_t *ctx, csi_scanner_t *scan, int c)
511 buffer_check (ctx, scan, 1);
512 buffer_add (&scan->buffer, c);
516 string_end (csi_t *ctx, csi_scanner_t *scan)
519 cairo_status_t status;
521 status = csi_string_new (ctx,
524 scan->buffer.ptr - scan->buffer.base);
525 if (_csi_unlikely (status))
526 longjmp (scan->jmpbuf, status);
528 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
529 status = csi_array_append (ctx,
530 scan->build_procedure.datum.array,
533 status = scan_push (ctx, &obj);
534 if (_csi_unlikely (status))
535 longjmp (scan->jmpbuf, status);
549 return c - 'a' + 0xa;
554 hex_add (csi_t *ctx, csi_scanner_t *scan, int c)
556 if (scan->accumulator_count == 0) {
557 scan->accumulator |= hex_value (c) << 4;
558 scan->accumulator_count = 1;
560 scan->accumulator |= hex_value (c) << 0;
561 buffer_check (ctx, scan, 1);
562 buffer_add (&scan->buffer, scan->accumulator);
564 scan->accumulator = 0;
565 scan->accumulator_count = 0;
570 hex_end (csi_t *ctx, csi_scanner_t *scan)
573 cairo_status_t status;
575 if (scan->accumulator_count)
576 hex_add (ctx, scan, '0');
578 status = csi_string_new (ctx,
581 scan->buffer.ptr - scan->buffer.base);
582 if (_csi_unlikely (status))
583 longjmp (scan->jmpbuf, status);
585 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
586 status = csi_array_append (ctx,
587 scan->build_procedure.datum.array,
590 status = scan_push (ctx, &obj);
591 if (_csi_unlikely (status))
592 longjmp (scan->jmpbuf, status);
596 base85_add (csi_t *ctx, csi_scanner_t *scan, int c)
599 if (_csi_unlikely (scan->accumulator_count != 0))
600 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
602 buffer_check (ctx, scan, 4);
603 buffer_add (&scan->buffer, 0);
604 buffer_add (&scan->buffer, 0);
605 buffer_add (&scan->buffer, 0);
606 buffer_add (&scan->buffer, 0);
607 } else if (_csi_unlikely (c < '!' || c > 'u')) {
608 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
610 scan->accumulator = scan->accumulator*85 + c - '!';
611 if (++scan->accumulator_count == 5) {
612 buffer_check (ctx, scan, 4);
613 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
614 buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
615 buffer_add (&scan->buffer, (scan->accumulator >> 8) & 0xff);
616 buffer_add (&scan->buffer, (scan->accumulator >> 0) & 0xff);
618 scan->accumulator = 0;
619 scan->accumulator_count = 0;
625 base85_end (csi_t *ctx, csi_scanner_t *scan, cairo_bool_t deflate)
628 cairo_status_t status;
630 buffer_check (ctx, scan, 4);
632 switch (scan->accumulator_count) {
636 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
640 scan->accumulator = scan->accumulator * (85*85*85) + 85*85*85 -1;
641 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
644 scan->accumulator = scan->accumulator * (85*85) + 85*85 -1;
645 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
646 buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
649 scan->accumulator = scan->accumulator * 85 + 84;
650 buffer_add (&scan->buffer, (scan->accumulator >> 24) & 0xff);
651 buffer_add (&scan->buffer, (scan->accumulator >> 16) & 0xff);
652 buffer_add (&scan->buffer, (scan->accumulator >> 8) & 0xff);
657 uLongf len = be32 (*(uint32_t *) scan->buffer.base);
658 Bytef *source = (Bytef *) (scan->buffer.base + sizeof (uint32_t));
660 status = csi_string_deflate_new (ctx, &obj,
662 (Bytef *) scan->buffer.ptr - source,
664 if (_csi_unlikely (status))
665 longjmp (scan->jmpbuf, status);
667 status = csi_string_new (ctx,
670 scan->buffer.ptr - scan->buffer.base);
671 if (_csi_unlikely (status))
672 longjmp (scan->jmpbuf, status);
675 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
676 status = csi_array_append (ctx,
677 scan->build_procedure.datum.array,
680 status = scan_push (ctx, &obj);
681 if (_csi_unlikely (status))
682 longjmp (scan->jmpbuf, status);
686 base64_add (csi_t *ctx, csi_scanner_t *scan, int c)
690 /* Convert Base64 character to its 6 bit nibble */
691 val = scan->accumulator;
693 val = (val << 6) | 63;
694 } else if (c =='+') {
695 val = (val << 6) | 62;
696 } else if (c >='A' && c <='Z') {
697 val = (val << 6) | (c -'A');
698 } else if (c >='a' && c <='z') {
699 val = (val << 6) | (c -'a' + 26);
700 } else if (c >='0' && c <='9') {
701 val = (val << 6) | (c -'0' + 52);
704 buffer_check (ctx, scan, 1);
705 switch (scan->accumulator_count++) {
710 buffer_add (&scan->buffer, (val >> 4) & 0xFF);
715 buffer_add (&scan->buffer, (val >> 2) & 0xFF);
720 buffer_add (&scan->buffer, (val >> 0) & 0xFF);
721 scan->accumulator_count = 0;
727 scan->accumulator_count = 0;
728 scan->accumulator = 0;
730 scan->accumulator = val;
735 base64_end (csi_t *ctx, csi_scanner_t *scan)
738 cairo_status_t status;
740 switch (scan->accumulator_count) {
744 base64_add (ctx, scan, (scan->accumulator << 2) & 0x3f);
745 base64_add (ctx, scan, '=');
748 base64_add (ctx, scan, (scan->accumulator << 4) & 0x3f);
749 base64_add (ctx, scan, '=');
750 base64_add (ctx, scan, '=');
754 status = csi_string_new (ctx,
757 scan->buffer.ptr - scan->buffer.base);
758 if (_csi_unlikely (status))
759 longjmp (scan->jmpbuf, status);
761 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL)
762 status = csi_array_append (ctx,
763 scan->build_procedure.datum.array,
766 status = scan_push (ctx, &obj);
767 if (_csi_unlikely (status))
768 longjmp (scan->jmpbuf, status);
772 scan_read (csi_scanner_t *scan, csi_file_t *src, void *ptr, int len)
776 int ret = csi_file_read (src, data, len);
777 if (_csi_unlikely (ret == 0))
778 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_READ_ERROR));
781 } while (_csi_unlikely (len));
785 string_read (csi_t *ctx,
794 status = csi_string_new (ctx, obj, NULL, len);
795 if (_csi_unlikely (status))
796 longjmp (scan->jmpbuf, status);
800 scan_read (scan, src, &u32, 4);
801 obj->datum.string->deflate = be32 (u32);
804 if (_csi_likely (len))
805 scan_read (scan, src, obj->datum.string->string, len);
806 obj->datum.string->string[len] = '\0';
810 _scan_file (csi_t *ctx, csi_file_t *src)
812 csi_scanner_t *scan = &ctx->scanner;
827 while ((c = csi_file_getc (src)) != EOF) {
828 csi_object_t obj = { CSI_OBJECT_TYPE_NULL };
837 case 0x20: /* ignore whitespace */
846 case '[': /* needs special case */
851 token_add_unchecked (scan, c);
852 token_end (ctx, scan, src);
856 next = csi_file_getc (src);
859 csi_file_putc (src, '<');
862 /* dictionary name */
864 token_add_unchecked (scan, '<');
865 token_add_unchecked (scan, '<');
866 token_end (ctx, scan, src);
875 csi_file_putc (src, next);
882 #define MSB_UINT8 129
883 #define MSB_INT16 130
884 #define MSB_UINT16 131
885 #define MSB_INT32 132
886 #define LSB_INT8 MSB_INT8
887 #define LSB_UINT8 MSB_UINT8
888 #define LSB_INT16 133
889 #define LSB_UINT16 134
890 #define LSB_INT32 135
891 #define MSB_FLOAT32 140
892 #define LSB_FLOAT32 141
894 scan_read (scan, src, &u.i8, 1);
895 csi_integer_new (&obj, u.i8);
898 scan_read (scan, src, &u.u8, 1);
899 csi_integer_new (&obj, u.u8);
902 scan_read (scan, src, &u.i16, 2);
903 csi_integer_new (&obj, be16 (u.i16));
906 scan_read (scan, src, &u.i16, 2);
907 csi_integer_new (&obj, le16 (u.i16));
910 scan_read (scan, src, &u.u16, 2);
911 csi_integer_new (&obj, be16 (u.u16));
914 scan_read (scan, src, &u.u16, 2);
915 csi_integer_new (&obj, le16 (u.u16));
918 scan_read (scan, src, &u.i32, 4);
919 csi_integer_new (&obj, be32 (u.i32));
922 scan_read (scan, src, &u.i32, 4);
923 csi_integer_new (&obj, le32 (u.i32));
926 case 136: /* 16.16 msb */
927 scan_read (scan, src, &u.i32, 4);
928 csi_real_new (&obj, be32 (u.i32) / 65536.);
930 case 137: /* 16.16 lsb */
931 scan_read (scan, src, &u.i32, 4);
932 csi_real_new (&obj, le32 (u.i32) / 65536.);
934 case 138: /* 24.8 msb */
935 scan_read (scan, src, &u.i32, 4);
936 csi_real_new (&obj, be32 (u.i32) / 256.);
938 case 139: /* 24.8 lsb */
939 scan_read (scan, src, &u.i32, 4);
940 csi_real_new (&obj, le32 (u.i32) / 256.);
943 scan_read (scan, src, &u.i32, 4);
944 u.i32 = be32 (u.i32);
945 csi_real_new (&obj, u.f);
948 scan_read (scan, src, &u.i32, 4);
949 u.i32 = le32 (u.i32);
950 csi_real_new (&obj, u.f);
954 #define STRING_2_MSB 144
955 #define STRING_2_LSB 146
956 #define STRING_4_MSB 148
957 #define STRING_4_LSB 150
958 #define STRING_DEFLATE 1
960 case STRING_1 | STRING_DEFLATE:
961 scan_read (scan, src, &u.u8, 1);
962 string_read (ctx, scan, src, u.u8, c & STRING_DEFLATE, &obj);
965 case STRING_2_MSB | STRING_DEFLATE:
966 scan_read (scan, src, &u.u16, 2);
967 string_read (ctx, scan, src, be16 (u.u16), c & STRING_DEFLATE, &obj);
970 case STRING_2_LSB | STRING_DEFLATE:
971 scan_read (scan, src, &u.u16, 2);
972 string_read (ctx, scan, src, le16 (u.u16), c & STRING_DEFLATE, &obj);
975 case STRING_4_MSB | STRING_DEFLATE:
976 scan_read (scan, src, &u.u32, 4);
977 string_read (ctx, scan, src, be32 (u.u32), c & STRING_DEFLATE, &obj);
980 case STRING_4_LSB | STRING_DEFLATE:
981 scan_read (scan, src, &u.u32, 4);
982 string_read (ctx, scan, src, le32 (u.u32), c & STRING_DEFLATE, &obj);
987 scan_read (scan, src, &u.u8, 1);
988 csi_operator_new (&obj, ctx->opcode[u.u8]);
992 scan_read (scan, src, &u.u8, 1);
993 csi_operator_new (&obj, ctx->opcode[u.u8]);
994 obj.type &= ~CSI_OBJECT_ATTR_EXECUTABLE;
1004 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1006 case '#': /* PDF 1.2 escape code */
1008 int c_hi = csi_file_getc (src);
1009 int c_lo = csi_file_getc (src);
1010 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
1015 token_add_unchecked (scan, c);
1019 if (obj.type != CSI_OBJECT_TYPE_NULL) {
1020 cairo_status_t status;
1022 if (scan->build_procedure.type != CSI_OBJECT_TYPE_NULL) {
1023 status = csi_array_append (ctx,
1024 scan->build_procedure.datum.array,
1026 } else if (obj.type & CSI_OBJECT_ATTR_EXECUTABLE) {
1027 status = scan_execute (ctx, &obj);
1028 csi_object_free (ctx, &obj);
1030 status = scan_push (ctx, &obj);
1032 if (_csi_unlikely (status))
1033 longjmp (scan->jmpbuf, status);
1039 while ((c = csi_file_getc (src)) != EOF) {
1042 scan->line_number++;
1048 token_end (ctx, scan, src);
1051 /* syntax delimiters */
1053 token_end (ctx, scan, src);
1057 token_end (ctx, scan, src);
1059 /* XXX syntax error? */
1061 token_end (ctx, scan, src);
1064 /* need to special case '^//?' */
1065 if (scan->buffer.ptr > scan->buffer.base+1 ||
1066 scan->buffer.base[0] != '/')
1068 token_end (ctx, scan, src);
1071 token_add_unchecked (scan, '/');
1077 token_end (ctx, scan, src);
1079 token_add_unchecked (scan, c);
1080 token_end (ctx, scan, src);
1084 csi_file_putc (src, '<');
1085 token_end (ctx, scan, src);
1088 case '#': /* PDF 1.2 escape code */
1090 int c_hi = csi_file_getc (src);
1091 int c_lo = csi_file_getc (src);
1092 c = (hex_value (c_hi) << 4) | hex_value (c_lo);
1096 token_add (ctx, scan, c);
1100 token_end (ctx, scan, src);
1104 /* discard until newline */
1105 while ((c = csi_file_getc (src)) != EOF) {
1108 scan->line_number++;
1116 buffer_reset (&scan->buffer);
1118 while ((c = csi_file_getc (src)) != EOF) {
1120 case '\\': /* escape */
1121 next = csi_file_getc (src);
1124 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1127 string_add (ctx, scan, '\n');
1130 string_add (ctx, scan, '\r');
1133 string_add (ctx, scan, '\t');
1136 string_add (ctx, scan, '\b');
1139 string_add (ctx, scan, '\f');
1142 string_add (ctx, scan, '\\');
1145 string_add (ctx, scan, '(');
1148 string_add (ctx, scan, ')');
1151 case '0': case '1': case '2': case '3':
1152 case '4': case '5': case '6': case '7':
1153 { /* octal code: \d{1,3} */
1158 for (i = 0; i < 2; i++) {
1159 next = csi_file_getc (src);
1164 case '0': case '1': case '2': case '3':
1165 case '4': case '5': case '6': case '7':
1170 csi_file_putc (src, next);
1171 goto octal_code_done;
1175 string_add (ctx, scan, c);
1180 /* skip the newline */
1181 next = csi_file_getc (src); /* might be compound LFCR */
1188 csi_file_putc (src, next);
1191 scan->line_number++;
1197 /* ignore the '\' */
1204 string_add (ctx, scan, c);
1208 if (--string_p == 0) {
1209 string_end (ctx, scan);
1214 string_add (ctx, scan, c);
1218 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1221 buffer_reset (&scan->buffer);
1222 scan->accumulator_count = 0;
1223 scan->accumulator = 0;
1224 while ((c = csi_file_getc (src)) != EOF) {
1227 scan->line_number++;
1232 case 0x20: /* ignore whitespace */
1236 hex_end (ctx, scan); /* fixup odd digit with '0' */
1261 hex_add (ctx, scan, c);
1265 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1268 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1271 buffer_reset (&scan->buffer);
1272 scan->accumulator = 0;
1273 scan->accumulator_count = 0;
1274 while ((c = csi_file_getc (src)) != EOF) {
1277 next = csi_file_getc (src);
1283 base85_end (ctx, scan, deflate);
1287 csi_file_putc (src, next);
1291 base85_add (ctx, scan, c);
1295 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1298 buffer_reset (&scan->buffer);
1299 scan->accumulator = 0;
1300 scan->accumulator_count = 0;
1301 while ((c = csi_file_getc (src)) != EOF) {
1304 next = csi_file_getc (src);
1310 base64_end (ctx, scan);
1313 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1316 base64_add (ctx, scan, c);
1320 longjmp (scan->jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1324 _scan_push (csi_t *ctx, csi_object_t *obj)
1327 fprintf (stderr, "push ");
1328 fprintf_obj (stderr, ctx, obj);
1330 return _csi_push_ostack (ctx, obj);
1334 _scan_execute (csi_t *ctx, csi_object_t *obj)
1337 fprintf (stderr, "exec ");
1338 fprintf_obj (stderr, ctx, obj);
1340 return csi_object_execute (ctx, obj);
1344 _csi_scanner_init (csi_t *ctx, csi_scanner_t *scanner)
1346 csi_status_t status;
1348 memset (scanner, 0, sizeof (csi_scanner_t));
1350 status = buffer_init (ctx, &scanner->buffer);
1354 status = _csi_stack_init (ctx, &scanner->procedure_stack, 4);
1359 scanner->push = _scan_push;
1360 scanner->execute = _scan_execute;
1362 return CSI_STATUS_SUCCESS;
1366 _csi_scanner_fini (csi_t *ctx, csi_scanner_t *scanner)
1368 buffer_fini (ctx, &scanner->buffer);
1369 _csi_stack_fini (ctx, &scanner->procedure_stack);
1370 if (scanner->build_procedure.type != CSI_OBJECT_TYPE_NULL)
1371 csi_object_free (ctx, &scanner->build_procedure);
1375 _csi_scan_file (csi_t *ctx, csi_file_t *src)
1377 csi_status_t status;
1378 int old_line_number;
1380 /* This function needs to be reentrant to handle recursive scanners.
1381 * i.e. one script executes a second.
1384 if (ctx->scanner.depth++ == 0) {
1385 if ((status = setjmp (ctx->scanner.jmpbuf))) {
1386 ctx->scanner.depth = 0;
1391 old_line_number = ctx->scanner.line_number;
1392 ctx->scanner.line_number = 0;
1394 _scan_file (ctx, src);
1396 ctx->scanner.line_number = old_line_number;
1398 --ctx->scanner.depth;
1399 return CSI_STATUS_SUCCESS;
1402 struct _translate_closure {
1403 csi_dictionary_t *opcodes;
1404 cairo_write_func_t write_func;
1409 _translate_name (csi_t *ctx,
1411 csi_boolean_t executable,
1412 struct _translate_closure *closure)
1415 csi_dictionary_entry_t *entry;
1418 /* Bind executable names.
1419 * XXX This may break some scripts that overload system operators.
1421 entry = _csi_hash_table_lookup (&closure->opcodes->hash_table,
1422 (csi_hash_entry_t *) &name);
1426 u16 = entry->value.datum.integer;
1428 closure->write_func (closure->closure, (unsigned char *) &u16, 2);
1430 closure->write_func (closure->closure, (unsigned char *) "/", 1);
1432 closure->write_func (closure->closure,
1433 (unsigned char *) name,
1434 strlen ((char *) name));
1435 closure->write_func (closure->closure, (unsigned char *) "\n", 1);
1438 return CSI_STATUS_SUCCESS;
1442 _translate_operator (csi_t *ctx,
1444 csi_boolean_t executable,
1445 struct _translate_closure *closure)
1447 csi_dictionary_entry_t *entry;
1450 entry = _csi_hash_table_lookup (&closure->opcodes->hash_table,
1451 (csi_hash_entry_t *) &op);
1453 return _csi_error (CSI_STATUS_INVALID_SCRIPT);
1455 u16 = entry->value.datum.integer;
1459 closure->write_func (closure->closure, (unsigned char *) &u16, 2);
1461 return CSI_STATUS_SUCCESS;
1465 _translate_integer (csi_t *ctx,
1467 struct _translate_closure *closure)
1481 if (i < INT16_MIN) {
1485 } else if (i < INT8_MIN) {
1493 } else if (i <= UINT8_MAX) {
1497 } else if (i <= UINT16_MAX) {
1507 if (i < INT16_MIN) {
1511 } else if (i < INT8_MIN) {
1519 } else if (i <= UINT8_MAX) {
1523 } else if (i <= UINT16_MAX) {
1534 closure->write_func (closure->closure, (unsigned char *) &hdr, 1);
1535 closure->write_func (closure->closure, (unsigned char *) &u, len);
1537 return CSI_STATUS_SUCCESS;
1541 _translate_real (csi_t *ctx,
1543 struct _translate_closure *closure)
1547 if (real >= INT32_MIN && real <= INT32_MAX && (int) real == real)
1548 return _translate_integer (ctx, real, closure);
1555 closure->write_func (closure->closure, (unsigned char *) &hdr, 1);
1556 closure->write_func (closure->closure, (unsigned char *) &real, 4);
1558 return CSI_STATUS_SUCCESS;
1562 _translate_string (csi_t *ctx,
1563 csi_string_t *string,
1564 struct _translate_closure *closure)
1575 if (string->len <= UINT8_MAX) {
1579 } else if (string->len <= UINT16_MAX) {
1581 u.u16 = string->len;
1585 u.u32 = string->len;
1589 if (string->len <= UINT8_MAX) {
1593 } else if (string->len <= UINT16_MAX) {
1595 u.u16 = string->len;
1599 u.u32 = string->len;
1603 if (string->deflate)
1604 hdr |= STRING_DEFLATE;
1606 closure->write_func (closure->closure,
1607 (unsigned char *) &hdr, 1);
1608 closure->write_func (closure->closure,
1609 (unsigned char *) &u, len);
1610 if (string->deflate) {
1611 uint32_t u32 = to_be32 (string->deflate);
1612 closure->write_func (closure->closure,
1613 (unsigned char *) &u32, 4);
1615 closure->write_func (closure->closure,
1616 (unsigned char *) string->string, string->len);
1618 return CSI_STATUS_SUCCESS;
1622 _translate_push (csi_t *ctx, csi_object_t *obj)
1624 struct _translate_closure *closure = ctx->scanner.closure;
1627 fprintf (stderr, "push ");
1628 fprintf_obj (stderr, ctx, obj);
1631 switch (csi_object_get_type (obj)) {
1632 case CSI_OBJECT_TYPE_NAME:
1633 return _translate_name (ctx, obj->datum.name, FALSE, closure);
1635 case CSI_OBJECT_TYPE_OPERATOR:
1636 return _translate_operator (ctx, obj->datum.op, FALSE, closure);
1638 case CSI_OBJECT_TYPE_INTEGER:
1639 return _translate_integer (ctx, obj->datum.integer, closure);
1641 case CSI_OBJECT_TYPE_REAL:
1642 return _translate_real (ctx, obj->datum.real, closure);
1644 case CSI_OBJECT_TYPE_STRING:
1645 return _translate_string (ctx, obj->datum.string, closure);
1647 case CSI_OBJECT_TYPE_NULL:
1648 case CSI_OBJECT_TYPE_BOOLEAN:
1649 case CSI_OBJECT_TYPE_MARK:
1650 case CSI_OBJECT_TYPE_ARRAY:
1651 case CSI_OBJECT_TYPE_DICTIONARY:
1652 case CSI_OBJECT_TYPE_FILE:
1653 case CSI_OBJECT_TYPE_MATRIX:
1654 case CSI_OBJECT_TYPE_CONTEXT:
1655 case CSI_OBJECT_TYPE_FONT:
1656 case CSI_OBJECT_TYPE_PATTERN:
1657 case CSI_OBJECT_TYPE_SCALED_FONT:
1658 case CSI_OBJECT_TYPE_SURFACE:
1659 longjmp (ctx->scanner.jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1663 csi_object_free (ctx, obj);
1664 return CSI_STATUS_SUCCESS;
1668 _translate_execute (csi_t *ctx, csi_object_t *obj)
1670 struct _translate_closure *closure = ctx->scanner.closure;
1673 fprintf (stderr, "exec ");
1674 fprintf_obj (stderr, ctx, obj);
1677 switch (csi_object_get_type (obj)) {
1678 case CSI_OBJECT_TYPE_NAME:
1679 return _translate_name (ctx, obj->datum.name, TRUE, closure);
1681 case CSI_OBJECT_TYPE_OPERATOR:
1682 return _translate_operator (ctx, obj->datum.op, TRUE, closure);
1684 case CSI_OBJECT_TYPE_INTEGER:
1685 return _translate_integer (ctx, obj->datum.integer, closure);
1687 case CSI_OBJECT_TYPE_REAL:
1688 return _translate_real (ctx, obj->datum.real, closure);
1690 case CSI_OBJECT_TYPE_STRING:
1691 return _translate_string (ctx, obj->datum.string, closure);
1693 case CSI_OBJECT_TYPE_NULL:
1694 case CSI_OBJECT_TYPE_BOOLEAN:
1695 case CSI_OBJECT_TYPE_MARK:
1696 case CSI_OBJECT_TYPE_ARRAY:
1697 case CSI_OBJECT_TYPE_DICTIONARY:
1698 case CSI_OBJECT_TYPE_FILE:
1699 case CSI_OBJECT_TYPE_MATRIX:
1700 case CSI_OBJECT_TYPE_CONTEXT:
1701 case CSI_OBJECT_TYPE_FONT:
1702 case CSI_OBJECT_TYPE_PATTERN:
1703 case CSI_OBJECT_TYPE_SCALED_FONT:
1704 case CSI_OBJECT_TYPE_SURFACE:
1705 longjmp (ctx->scanner.jmpbuf, _csi_error (CSI_STATUS_INVALID_SCRIPT));
1709 return CSI_STATUS_SUCCESS;
1713 build_opcodes (csi_t *ctx, csi_dictionary_t **out)
1716 csi_dictionary_t *dict;
1717 const csi_operator_def_t *def;
1718 csi_status_t status;
1719 int opcode = OPCODE << 8;
1721 status = csi_dictionary_new (ctx, &obj);
1722 if (_csi_unlikely (status))
1725 dict = obj.datum.dictionary;
1727 csi_integer_new (&obj, opcode++);
1728 status = csi_dictionary_put (ctx, dict, 0, &obj);
1729 if (_csi_unlikely (status))
1732 for (def = _csi_operators (); def->name != NULL; def++) {
1734 csi_dictionary_entry_t *entry;
1737 entry = _csi_hash_table_lookup (&dict->hash_table,
1738 (csi_hash_entry_t *) &def->op);
1739 if (entry == NULL) {
1741 csi_integer_new (&obj, code);
1742 status = csi_dictionary_put (ctx, dict, (csi_name_t) def->op, &obj);
1743 if (_csi_unlikely (status))
1746 code = entry->value.datum.integer;
1747 csi_integer_new (&obj, code);
1749 assert (ctx->opcode[code & 0xff] == def->op);
1751 status = csi_name_new_static (ctx, &name, def->name);
1752 if (_csi_unlikely (status))
1755 status = csi_dictionary_put (ctx, dict, name.datum.name, &obj);
1756 if (_csi_unlikely (status))
1761 return CSI_STATUS_SUCCESS;
1764 csi_dictionary_free (ctx, dict);
1769 _csi_translate_file (csi_t *ctx,
1771 cairo_write_func_t write_func,
1774 csi_status_t status;
1775 struct _translate_closure translator;
1777 if ((status = setjmp (ctx->scanner.jmpbuf)))
1780 status = build_opcodes (ctx, &translator.opcodes);
1781 if (_csi_unlikely (status))
1784 translator.write_func = write_func;
1785 translator.closure = closure;
1786 ctx->scanner.closure = &translator;
1788 ctx->scanner.bind = 1;
1789 ctx->scanner.push = _translate_push;
1790 ctx->scanner.execute = _translate_execute;
1792 _scan_file (ctx, file);
1794 ctx->scanner.bind = 0;
1795 ctx->scanner.push = _scan_push;
1796 ctx->scanner.execute = _scan_execute;
1798 csi_dictionary_free (ctx, translator.opcodes);
1800 return CSI_STATUS_SUCCESS;