Coverage Report

Created: 2026-10-17 07:00

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