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 #ifndef CAIRO_SCRIPT_PRIVATE_H
36 #define CAIRO_SCRIPT_PRIVATE_H
37 
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 
42 #include "cairo-script-interpreter.h"
43 
44 #include <setjmp.h>
45 
46 #ifdef _MSC_VER
47 #undef inline
48 #define inline __inline
49 #endif
50 
51 #ifndef FALSE
52 #define FALSE 0
53 #endif
54 
55 #ifndef TRUE
56 #define TRUE (!FALSE)
57 #endif
58 
59 #ifndef NULL
60 #define NULL (void *) 0
61 #endif
62 
63 #if   HAVE_STDINT_H
64 # include <stdint.h>
65 #elif HAVE_INTTYPES_H
66 # include <inttypes.h>
67 #elif HAVE_SYS_INT_TYPES_H
68 # include <sys/int_types.h>
69 #elif defined(_MSC_VER)
70   typedef __int8 int8_t;
71   typedef unsigned __int8 uint8_t;
72   typedef __int16 int16_t;
73   typedef unsigned __int16 uint16_t;
74   typedef __int32 int32_t;
75   typedef unsigned __int32 uint32_t;
76   typedef __int64 int64_t;
77   typedef unsigned __int64 uint64_t;
78 # ifndef HAVE_UINT64_T
79 #  define HAVE_UINT64_T 1
80 # endif
81 #else
82 #error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
83 #endif
84 
85 #if HAVE_BYTESWAP_H
86 # include <byteswap.h>
87 #endif
88 #ifndef bswap_16
89 # define bswap_16(p) \
90 	(((((uint16_t)(p)) & 0x00ff) << 8) | \
91 	  (((uint16_t)(p))           >> 8))
92 #endif
93 #ifndef bswap_32
94 # define bswap_32(p) \
95          (((((uint32_t)(p)) & 0x000000ff) << 24) | \
96 	  ((((uint32_t)(p)) & 0x0000ff00) << 8)  | \
97 	  ((((uint32_t)(p)) & 0x00ff0000) >> 8)  | \
98 	  ((((uint32_t)(p)))              >> 24))
99 #endif
100 
101 
102 #if __GNUC__ >= 3 && defined(__ELF__) && !defined(__sun)
103 # define slim_hidden_proto(name)		slim_hidden_proto1(name, slim_hidden_int_name(name)) csi_private
104 # define slim_hidden_proto_no_warn(name)	slim_hidden_proto1(name, slim_hidden_int_name(name)) csi_private_no_warn
105 # define slim_hidden_def(name)			slim_hidden_def1(name, slim_hidden_int_name(name))
106 # define slim_hidden_int_name(name) INT_##name
107 # define slim_hidden_proto1(name, internal)				\
108   extern __typeof (name) name						\
109 	__asm__ (slim_hidden_asmname (internal))
110 # define slim_hidden_def1(name, internal)				\
111   extern __typeof (name) EXT_##name __asm__(slim_hidden_asmname(name))	\
112 	__attribute__((__alias__(slim_hidden_asmname(internal))))
113 # define slim_hidden_ulp		slim_hidden_ulp1(__USER_LABEL_PREFIX__)
114 # define slim_hidden_ulp1(x)		slim_hidden_ulp2(x)
115 # define slim_hidden_ulp2(x)		#x
116 # define slim_hidden_asmname(name)	slim_hidden_asmname1(name)
117 # define slim_hidden_asmname1(name)	slim_hidden_ulp #name
118 #else
119 # define slim_hidden_proto(name)		int _csi_dummy_prototype(void)
120 # define slim_hidden_proto_no_warn(name)	int _csi_dummy_prototype(void)
121 # define slim_hidden_def(name)			int _csi_dummy_prototype(void)
122 #endif
123 
124 #if __GNUC__ >= 3
125 #define csi_pure __attribute__((pure))
126 #define csi_const __attribute__((const))
127 #else
128 #define csi_pure
129 #define csi_const
130 #endif
131 
132 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
133 #define _CSI_BOOLEAN_EXPR(expr)                   \
134  __extension__ ({                               \
135    int _csi_boolean_var_;                         \
136    if (expr)                                    \
137       _csi_boolean_var_ = 1;                      \
138    else                                         \
139       _csi_boolean_var_ = 0;                      \
140    _csi_boolean_var_;                             \
141 })
142 #define _csi_likely(expr) (__builtin_expect (_CSI_BOOLEAN_EXPR(expr), 1))
143 #define _csi_unlikely(expr) (__builtin_expect (_CSI_BOOLEAN_EXPR(expr), 0))
144 #else
145 #define _csi_likely(expr) (expr)
146 #define _csi_unlikely(expr) (expr)
147 #endif
148 
149 #ifdef __GNUC__
150 #ifndef offsetof
151 #define offsetof(type, member) \
152     ((char *) &((type *) 0)->member - (char *) 0)
153 #endif
154 #define csi_container_of(ptr, type, member) ({ \
155     const typeof(((type *) 0)->member) *mptr__ = (ptr); \
156     (type *) ((char *) mptr__ - offsetof (type, member)); \
157 })
158 #else
159 #define csi_container_of(ptr, type, member) \
160     (type *)((char *) (ptr) - (char *) &((type *)0)->member)
161 #endif
162 
163 /* slim_internal.h */
164 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun)
165 #define csi_private_no_warn	__attribute__((__visibility__("hidden")))
166 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
167 #define csi_private_no_warn	__hidden
168 #else /* not gcc >= 3.3 and not Sun Studio >= 8 */
169 #define csi_private_no_warn
170 #endif
171 
172 #undef  ARRAY_LENGTH
173 #define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
174 
175 #ifndef WARN_UNUSED_RESULT
176 #define WARN_UNUSED_RESULT
177 #endif
178 /* Add attribute(warn_unused_result) if supported */
179 #define csi_warn	    WARN_UNUSED_RESULT
180 #define csi_private	    csi_private_no_warn csi_warn
181 
182 #define CSI_BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16)
183 #ifdef WORDS_BIGENDIAN
184 #define CSI_BITSWAP8_IF_LITTLE_ENDIAN(c) (c)
185 #else
186 #define CSI_BITSWAP8_IF_LITTLE_ENDIAN(c) CSI_BITSWAP8(c)
187 #endif
188 
189 typedef enum _csi_status {
190     CSI_STATUS_SUCCESS = CAIRO_STATUS_SUCCESS,
191     CSI_STATUS_NO_MEMORY = CAIRO_STATUS_NO_MEMORY,
192     CSI_STATUS_INVALID_RESTORE = CAIRO_STATUS_INVALID_RESTORE,
193     CSI_STATUS_INVALID_POP_GROUP = CAIRO_STATUS_INVALID_POP_GROUP,
194     CSI_STATUS_NO_CURRENT_POINT = CAIRO_STATUS_NO_CURRENT_POINT,
195     CSI_STATUS_INVALID_MATRIX = CAIRO_STATUS_INVALID_MATRIX,
196     CSI_STATUS_INVALID_STATUS = CAIRO_STATUS_INVALID_STATUS,
197     CSI_STATUS_NULL_POINTER = CAIRO_STATUS_NULL_POINTER,
198     CSI_STATUS_INVALID_STRING = CAIRO_STATUS_INVALID_STRING,
199     CSI_STATUS_INVALID_PATH_DATA = CAIRO_STATUS_INVALID_PATH_DATA,
200     CSI_STATUS_READ_ERROR = CAIRO_STATUS_READ_ERROR,
201     CSI_STATUS_WRITE_ERROR = CAIRO_STATUS_WRITE_ERROR,
202     CSI_STATUS_SURFACE_FINISHED = CAIRO_STATUS_SURFACE_FINISHED,
203     CSI_STATUS_SURFACE_TYPE_MISMATCH = CAIRO_STATUS_SURFACE_TYPE_MISMATCH,
204     CSI_STATUS_PATTERN_TYPE_MISMATCH = CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
205     CSI_STATUS_INVALID_CONTENT = CAIRO_STATUS_INVALID_CONTENT,
206     CSI_STATUS_INVALID_FORMAT = CAIRO_STATUS_INVALID_FORMAT,
207     CSI_STATUS_INVALID_VISUAL = CAIRO_STATUS_INVALID_VISUAL,
208     CSI_STATUS_FILE_NOT_FOUND = CAIRO_STATUS_FILE_NOT_FOUND,
209     CSI_STATUS_INVALID_DASH = CAIRO_STATUS_INVALID_DASH,
210     CSI_STATUS_INVALID_DSC_COMMENT = CAIRO_STATUS_INVALID_DSC_COMMENT,
211     CSI_STATUS_INVALID_INDEX = CAIRO_STATUS_INVALID_INDEX,
212     CSI_STATUS_CLIP_NOT_REPRESENTABLE = CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
213     CSI_STATUS_TEMP_FILE_ERROR = CAIRO_STATUS_TEMP_FILE_ERROR,
214     CSI_STATUS_INVALID_STRIDE = CAIRO_STATUS_INVALID_STRIDE,
215     CSI_STATUS_FONT_TYPE_MISMATCH = CAIRO_STATUS_FONT_TYPE_MISMATCH,
216     CSI_STATUS_USER_FONT_IMMUTABLE = CAIRO_STATUS_USER_FONT_IMMUTABLE,
217     CSI_STATUS_USER_FONT_ERROR = CAIRO_STATUS_USER_FONT_ERROR,
218     CSI_STATUS_NEGATIVE_COUNT = CAIRO_STATUS_NEGATIVE_COUNT,
219     CSI_STATUS_INVALID_CLUSTERS = CAIRO_STATUS_INVALID_CLUSTERS,
220     CSI_STATUS_INVALID_SLANT = CAIRO_STATUS_INVALID_SLANT,
221     CSI_STATUS_INVALID_WEIGHT = CAIRO_STATUS_INVALID_WEIGHT,
222     CSI_STATUS_INVALID_SIZE = CAIRO_STATUS_INVALID_SIZE,
223     CSI_STATUS_USER_FONT_NOT_IMPLEMENTED = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED,
224     CSI_STATUS_DEVICE_TYPE_MISMATCH = CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
225     CSI_STATUS_DEVICE_ERROR = CAIRO_STATUS_DEVICE_ERROR,
226     CSI_STATUS_INVALID_MESH_CONSTRUCTION = CAIRO_STATUS_INVALID_MESH_CONSTRUCTION,
227     CSI_STATUS_DEVICE_FINISHED = CAIRO_STATUS_DEVICE_FINISHED,
228     CSI_STATUS_JBIG2_GLOBAL_MISSING = CAIRO_STATUS_JBIG2_GLOBAL_MISSING,
229     CSI_STATUS_PNG_ERROR = CAIRO_STATUS_PNG_ERROR,
230     CSI_STATUS_FREETYPE_ERROR = CAIRO_STATUS_FREETYPE_ERROR,
231     CSI_STATUS_WIN32_GDI_ERROR = CAIRO_STATUS_WIN32_GDI_ERROR,
232 
233     /* cairo-script-interpreter specific errors */
234 
235     CSI_STATUS_INVALID_SCRIPT,
236     CSI_STATUS_SCRIPT_INVALID_TYPE,
237     CSI_STATUS_SCRIPT_INVALID_INDEX,
238     CSI_STATUS_SCRIPT_UNDEFINED_NAME,
239     CSI_STATUS_INTERPRETER_FINISHED,
240 
241     _CSI_STATUS_SCRIPT_LAST_ERROR,
242     CSI_INT_STATUS_UNSUPPORTED
243 } csi_status_t;
244 
245 typedef enum {
246     CSI_OBJECT_TYPE_NULL = 0,
247 
248     /* atomics */
249     CSI_OBJECT_TYPE_BOOLEAN,
250     CSI_OBJECT_TYPE_INTEGER,
251     CSI_OBJECT_TYPE_MARK,
252     CSI_OBJECT_TYPE_NAME,
253     CSI_OBJECT_TYPE_OPERATOR,
254     CSI_OBJECT_TYPE_REAL,
255 
256     /* compound */
257     CSI_OBJECT_TYPE_ARRAY = 0x8,
258     CSI_OBJECT_TYPE_DICTIONARY,
259     CSI_OBJECT_TYPE_FILE,
260     CSI_OBJECT_TYPE_MATRIX,
261     CSI_OBJECT_TYPE_STRING,
262 
263     /* cairo */
264     CSI_OBJECT_TYPE_CONTEXT = 0x10,
265     CSI_OBJECT_TYPE_FONT,
266     CSI_OBJECT_TYPE_PATTERN,
267     CSI_OBJECT_TYPE_SCALED_FONT,
268     CSI_OBJECT_TYPE_SURFACE
269 } csi_object_type_t;
270 
271 #define CSI_OBJECT_IS_ATOM(OBJ) (((OBJ)->type & CSI_OBJECT_TYPE_MASK) < 0x08)
272 #define CSI_OBJECT_IS_COMPOUND(OBJ) ((OBJ)->type & 0x08)
273 #define CSI_OBJECT_IS_CAIRO(OBJ) ((OBJ)->type & 0x10)
274 
275 enum { /* attributes */
276     CSI_OBJECT_ATTR_EXECUTABLE = 1 << 6,
277     CSI_OBJECT_ATTR_WRITABLE   = 1 << 7
278 };
279 #define CSI_OBJECT_ATTR_MASK (CSI_OBJECT_ATTR_EXECUTABLE | \
280 			      CSI_OBJECT_ATTR_WRITABLE)
281 #define CSI_OBJECT_TYPE_MASK (~CSI_OBJECT_ATTR_MASK)
282 
283 typedef struct _cairo_script_interpreter csi_t;
284 
285 typedef cairo_bool_t csi_boolean_t;
286 typedef csi_status_t (*csi_operator_t) (csi_t *);
287 typedef float csi_real_t;
288 typedef long csi_integer_t;
289 typedef long csi_name_t;
290 typedef struct _csi_array csi_array_t;
291 typedef struct _csi_buffer csi_buffer_t;
292 typedef struct _csi_compound_object csi_compound_object_t;
293 typedef struct _csi_dictionary csi_dictionary_t;
294 typedef struct _csi_file csi_file_t;
295 typedef struct _csi_hash_entry csi_hash_entry_t;
296 typedef struct _csi_hash_table csi_hash_table_t;
297 typedef struct _csi_hash_table_arrangement csi_hash_table_arrangement_t;
298 typedef struct _csi_list csi_list_t;
299 typedef struct _csi_matrix csi_matrix_t;
300 typedef struct _csi_object csi_object_t;
301 typedef struct _csi_scanner csi_scanner_t;
302 typedef struct _csi_stack csi_stack_t;
303 typedef struct _csi_string csi_string_t;
304 
305 typedef cairo_bool_t
306 (*csi_hash_predicate_func_t) (void *entry);
307 
308 typedef void
309 (*csi_hash_callback_func_t) (void *entry,
310 			     void *closure);
311 
312 typedef cairo_bool_t
313 (*csi_hash_keys_equal_func_t) (const void *key_a, const void *key_b);
314 
315 struct _csi_object {
316     csi_object_type_t type;
317     union {
318 	cairo_t *cr;
319 	cairo_font_face_t *font_face;
320 	cairo_pattern_t *pattern;
321 	cairo_scaled_font_t *scaled_font;
322 	cairo_surface_t *surface;
323 	csi_array_t *array;
324 	csi_boolean_t boolean;
325 	csi_compound_object_t *object;
326 	csi_dictionary_t *dictionary;
327 	csi_file_t *file;
328 	csi_integer_t integer;
329 	csi_matrix_t *matrix;
330 	csi_operator_t op;
331 	csi_name_t name;
332 	csi_real_t real;
333 	csi_string_t *string;
334 	void *ptr;
335     } datum;
336 };
337 
338 struct _csi_compound_object {
339     csi_object_type_t type;
340     unsigned int ref;
341 };
342 
343 struct _csi_hash_entry {
344     unsigned long hash;
345 };
346 
347 struct _csi_hash_table_arrangement {
348     unsigned long high_water_mark;
349     unsigned long size;
350     unsigned long rehash;
351 };
352 
353 struct _csi_hash_table {
354     csi_hash_keys_equal_func_t keys_equal;
355 
356     const csi_hash_table_arrangement_t *arrangement;
357     csi_hash_entry_t **entries;
358 
359     unsigned long live_entries;
360     unsigned long used_entries;
361     unsigned long iterating;   /* Iterating, no insert, no resize */
362 };
363 
364 
365 /* simple, embedded doubly-linked links */
366 struct _csi_list {
367     struct _csi_list *next, *prev;
368 };
369 
370 struct _csi_buffer {
371     char *base, *ptr, *end;
372     unsigned int size;
373 };
374 
375 struct _csi_stack {
376     csi_object_t *objects;
377     csi_integer_t len;
378     csi_integer_t size;
379 };
380 
381 struct _csi_array {
382     csi_compound_object_t base;
383     csi_stack_t stack;
384 };
385 
386 typedef struct _csi_dictionary_entry {
387     csi_hash_entry_t hash_entry;
388     csi_object_t value;
389 } csi_dictionary_entry_t;
390 
391 struct _csi_dictionary {
392     csi_compound_object_t base;
393     csi_hash_table_t hash_table;
394 };
395 
396 struct _csi_matrix {
397     csi_compound_object_t base;
398     cairo_matrix_t matrix;
399 };
400 
401 struct _csi_string {
402     csi_compound_object_t base;
403     csi_integer_t len;
404     csi_integer_t deflate;
405     enum {
406 	NONE,
407 	ZLIB,
408 	LZO,
409     } method;
410     char *string;
411 };
412 
413 typedef struct _csi_filter_funcs {
414     int (*filter_getc) (csi_file_t *);
415     void (*filter_putc) (csi_file_t *, int);
416     int (*filter_read) (csi_file_t *, uint8_t *, int);
417     void (*filter_destroy) (csi_t *, void *);
418 } csi_filter_funcs_t;
419 
420 struct _csi_file {
421     csi_compound_object_t base;
422     enum {
423 	STDIO,
424 	BYTES,
425 	PROCEDURE,
426 	FILTER
427     } type;
428     unsigned int flags;
429     void *src;
430     void *data;
431     uint8_t *bp;
432     int rem;
433     const csi_filter_funcs_t *filter;
434 };
435 
436 union _csi_union_object {
437     void *ptr[2];
438     csi_stack_t stack;
439     csi_array_t arry;
440     csi_dictionary_t dictionary;
441     csi_matrix_t matrix;
442     csi_string_t string;
443     csi_file_t file;
444     csi_object_t object;
445 };
446 
447 struct _csi_scanner {
448     jmp_buf jump_buffer;
449     int depth;
450 
451     int bind;
452     csi_status_t (*push) (csi_t *ctx, csi_object_t *obj);
453     csi_status_t (*execute) (csi_t *ctx, csi_object_t *obj);
454     void *closure;
455 
456     csi_buffer_t buffer;
457     csi_stack_t procedure_stack;
458     csi_object_t build_procedure;
459 
460     unsigned int accumulator;
461     unsigned int accumulator_count;
462 
463     unsigned int line_number;
464 };
465 
466 typedef cairo_script_interpreter_hooks_t csi_hooks_t;
467 
468 typedef struct _csi_chunk {
469     struct _csi_chunk *next;
470     int rem;
471     char *ptr;
472 } csi_chunk_t;
473 
474 struct _cairo_script_interpreter {
475     int ref_count;
476     csi_status_t status;
477 
478     unsigned int finished : 1;
479 
480     csi_hooks_t hooks;
481 
482     csi_hash_table_t strings;
483 
484     csi_stack_t ostack;
485     csi_stack_t dstack;
486 
487     csi_scanner_t scanner;
488 
489     csi_chunk_t *perm_chunk;
490     struct {
491 	csi_chunk_t *chunk;
492 	void *free_list;
493     } slabs[16];
494     csi_array_t *free_array;
495     csi_dictionary_t *free_dictionary;
496     csi_string_t *free_string;
497 
498     csi_operator_t opcode[256];
499 
500     /* caches of live data */
501     csi_list_t *_images;
502     csi_list_t *_faces;
503 };
504 
505 typedef struct _csi_operator_def {
506     const char *name;
507     csi_operator_t op;
508 } csi_operator_def_t;
509 
510 typedef struct _csi_integer_constant_def {
511     const char *name;
512     csi_integer_t value;
513 } csi_integer_constant_def_t;
514 
515 typedef struct _csi_real_constant_def {
516     const char *name;
517     csi_real_t value;
518 } csi_real_constant_def_t;
519 
520 /* cairo-script-file.c */
521 
522 csi_private csi_status_t
523 csi_file_new (csi_t *ctx,
524 	      csi_object_t *obj,
525 	      const char *path, const char *mode);
526 
527 csi_private csi_status_t
528 csi_file_new_for_stream (csi_t *ctx,
529 	                 csi_object_t *obj,
530 			 FILE *stream);
531 
532 csi_private csi_status_t
533 csi_file_new_for_bytes (csi_t *ctx,
534 			csi_object_t *obj,
535 			const char *bytes,
536 			unsigned int length);
537 
538 csi_private csi_status_t
539 csi_file_new_from_string (csi_t *ctx,
540 			  csi_object_t *obj,
541 			  csi_string_t *src);
542 
543 csi_private csi_status_t
544 csi_file_new_ascii85_decode (csi_t *ctx,
545 			     csi_object_t *obj,
546 			     csi_dictionary_t *dict,
547 			     csi_object_t *src);
548 
549 csi_private csi_status_t
550 csi_file_new_deflate_decode (csi_t *ctx,
551 			     csi_object_t *obj,
552 			     csi_dictionary_t *dict,
553 			     csi_object_t *src);
554 
555 csi_private csi_status_t
556 _csi_file_execute (csi_t *ctx, csi_file_t *obj);
557 
558 csi_private int
559 csi_file_getc (csi_file_t *obj);
560 
561 csi_private int
562 csi_file_read (csi_file_t *obj, void *buf, int len);
563 
564 csi_private void
565 csi_file_putc (csi_file_t *obj, int c);
566 
567 csi_private void
568 csi_file_flush (csi_file_t *obj);
569 
570 csi_private void
571 csi_file_close (csi_t *ctx, csi_file_t *obj);
572 
573 csi_private void
574 _csi_file_free (csi_t *ctx, csi_file_t *obj);
575 
576 csi_private csi_status_t
577 _csi_file_as_string (csi_t *ctx,
578 		     csi_file_t *file,
579 		     csi_object_t *obj);
580 
581 /* cairo-script-hash.c */
582 
583 csi_private csi_status_t
584 _csi_hash_table_init (csi_hash_table_t *hash_table,
585 		      csi_hash_keys_equal_func_t keys_equal);
586 
587 csi_private void
588 _csi_hash_table_fini (csi_hash_table_t *hash_table);
589 
590 csi_private void *
591 _csi_hash_table_lookup (csi_hash_table_t  *hash_table,
592 			csi_hash_entry_t  *key);
593 
594 csi_private csi_status_t
595 _csi_hash_table_insert (csi_hash_table_t *hash_table,
596 			csi_hash_entry_t *entry);
597 
598 csi_private void
599 _csi_hash_table_remove (csi_hash_table_t *hash_table,
600 			csi_hash_entry_t *key);
601 
602 csi_private void
603 _csi_hash_table_foreach (csi_hash_table_t	      *hash_table,
604 			 csi_hash_callback_func_t  hash_callback,
605 			 void			      *closure);
606 
607 /* cairo-script-interpreter.c */
608 
609 csi_private void *
610 _csi_alloc (csi_t *ctx, int size);
611 
612 csi_private void *
613 _csi_alloc0 (csi_t *ctx, int size);
614 
615 csi_private void *
616 _csi_realloc (csi_t *ctx, void *ptr, int size);
617 
618 csi_private void
619 _csi_free (csi_t *ctx, void *ptr);
620 
621 csi_private void *
622 _csi_slab_alloc (csi_t *ctx, int size);
623 
624 csi_private void *
625 _csi_perm_alloc (csi_t *ctx, int size);
626 
627 csi_private void
628 _csi_slab_free (csi_t *ctx, void *ptr, int size);
629 
630 csi_private csi_status_t
631 csi_push_ostack (csi_t *ctx, csi_object_t *obj);
632 
633 csi_private csi_status_t
634 _csi_name_define (csi_t *ctx, csi_name_t name, csi_object_t *obj);
635 
636 csi_private csi_status_t
637 _csi_name_lookup (csi_t *ctx, csi_name_t name, csi_object_t *obj);
638 
639 csi_private csi_status_t
640 _csi_name_undefine (csi_t *ctx, csi_name_t name);
641 
642 csi_private csi_status_t
643 _csi_intern_string (csi_t *ctx, const char **str_inout, int len);
644 
645 csi_private csi_status_t
646 _csi_error (csi_status_t status);
647 
648 /* cairo-script-objects.c */
649 
650 csi_private csi_status_t
651 csi_array_new (csi_t *ctx,
652 	       csi_integer_t initial_size,
653 	       csi_object_t *obj);
654 
655 csi_private csi_status_t
656 _csi_array_execute (csi_t *ctx, csi_array_t *array);
657 
658 csi_private csi_status_t
659 csi_array_get (csi_t *ctx,
660 	       csi_array_t *array,
661 	       long elem,
662 	       csi_object_t *value);
663 
664 csi_private csi_status_t
665 csi_array_put (csi_t *ctx,
666 	       csi_array_t *array,
667 	       csi_integer_t elem,
668 	       csi_object_t *value);
669 
670 csi_private csi_status_t
671 csi_array_append (csi_t *ctx,
672 		  csi_array_t *array,
673 		  csi_object_t *obj);
674 
675 csi_private void
676 csi_array_free (csi_t *ctx, csi_array_t *array);
677 
678 static inline void
csi_boolean_new(csi_object_t * obj,csi_boolean_t v)679 csi_boolean_new (csi_object_t *obj,
680 		 csi_boolean_t v)
681 {
682     obj->type = CSI_OBJECT_TYPE_BOOLEAN;
683     obj->datum.boolean = v;
684 }
685 
686 csi_private csi_status_t
687 csi_dictionary_new (csi_t *ctx,
688 		    csi_object_t *obj);
689 
690 csi_private csi_status_t
691 csi_dictionary_put (csi_t *ctx,
692 		    csi_dictionary_t *dict,
693 		    csi_name_t name,
694 		    csi_object_t *value);
695 
696 csi_private csi_status_t
697 csi_dictionary_get (csi_t *ctx,
698 		    csi_dictionary_t *dict,
699 		    csi_name_t name,
700 		    csi_object_t *value);
701 
702 csi_private csi_boolean_t
703 csi_dictionary_has (csi_dictionary_t *dict,
704 		    csi_name_t name);
705 
706 csi_private void
707 csi_dictionary_remove (csi_t *ctx,
708 		       csi_dictionary_t *dict,
709 		       csi_name_t name);
710 
711 csi_private void
712 csi_dictionary_free (csi_t *ctx,
713 		     csi_dictionary_t *dict);
714 
715 static inline void
csi_integer_new(csi_object_t * obj,csi_integer_t v)716 csi_integer_new (csi_object_t *obj,
717 		 csi_integer_t v)
718 {
719     obj->type = CSI_OBJECT_TYPE_INTEGER;
720     obj->datum.integer = v;
721 }
722 
723 
724 csi_private csi_status_t
725 csi_matrix_new (csi_t *ctx,
726 		csi_object_t *obj);
727 
728 csi_private csi_status_t
729 csi_matrix_new_from_array (csi_t *ctx,
730 			   csi_object_t *obj,
731 			   csi_array_t *array);
732 
733 csi_private csi_status_t
734 csi_matrix_new_from_matrix (csi_t *ctx,
735 			    csi_object_t *obj,
736 			    const cairo_matrix_t *m);
737 
738 csi_private csi_status_t
739 csi_matrix_new_from_values (csi_t *ctx,
740 			    csi_object_t *obj,
741 			    double v[6]);
742 
743 csi_private void
744 csi_matrix_free (csi_t *ctx,
745 		 csi_matrix_t *obj);
746 
747 csi_private csi_status_t
748 csi_name_new (csi_t *ctx,
749 	      csi_object_t *obj,
750 	      const char *str,
751 	      int len);
752 
753 csi_private csi_status_t
754 csi_name_new_static (csi_t *ctx,
755 		     csi_object_t *obj,
756 		     const char *str);
757 
758 static inline void
csi_operator_new(csi_object_t * obj,csi_operator_t op)759 csi_operator_new (csi_object_t *obj,
760 		  csi_operator_t op)
761 {
762     obj->type = CSI_OBJECT_TYPE_OPERATOR | CSI_OBJECT_ATTR_EXECUTABLE;
763     obj->datum.op = op;
764 }
765 
766 static inline void
csi_real_new(csi_object_t * obj,csi_real_t v)767 csi_real_new (csi_object_t *obj,
768 	      csi_real_t v)
769 {
770     obj->type = CSI_OBJECT_TYPE_REAL;
771     obj->datum.real = v;
772 }
773 
774 csi_private csi_status_t
775 csi_string_new (csi_t *ctx,
776 		csi_object_t *obj,
777 		const char *str,
778 		int len);
779 
780 csi_private csi_status_t
781 csi_string_deflate_new (csi_t *ctx,
782 			csi_object_t *obj,
783 			void *bytes,
784 			int in_len,
785 			int out_len);
786 
787 csi_private csi_status_t
788 csi_string_new_from_bytes (csi_t *ctx,
789 	                   csi_object_t *obj,
790 			   char *bytes,
791 			   unsigned int len);
792 
793 csi_private void
794 csi_string_free (csi_t *ctx, csi_string_t *string);
795 
796 csi_private csi_status_t
797 csi_object_execute (csi_t *ctx, csi_object_t *obj);
798 
799 csi_private csi_object_t *
800 csi_object_reference (csi_object_t *obj);
801 
802 csi_private void
803 csi_object_free (csi_t *ctx,
804 		 csi_object_t *obj);
805 
806 csi_private csi_status_t
807 csi_object_as_file (csi_t *ctx,
808 		    csi_object_t *src,
809 		    csi_object_t *file);
810 
811 csi_private csi_boolean_t
812 csi_object_eq (csi_object_t *a,
813 	       csi_object_t *b);
814 
815 csi_private csi_status_t
816 csi_object_compare (csi_object_t *a,
817 		    csi_object_t *b,
818 		    int          *out_cmp);
819 
820 /* cairo-script-operators.c */
821 
822 csi_private const csi_operator_def_t *
823 _csi_operators (void);
824 
825 csi_private const csi_integer_constant_def_t *
826 _csi_integer_constants (void);
827 
828 csi_private const csi_real_constant_def_t *
829 _csi_real_constants (void);
830 
831 /* cairo-script-scanner.c */
832 
833 csi_private csi_status_t
834 _csi_scanner_init (csi_t *ctx, csi_scanner_t *scanner);
835 
836 csi_private csi_status_t
837 _csi_scan_file (csi_t *ctx, csi_file_t *src);
838 
839 csi_private csi_status_t
840 _csi_translate_file (csi_t *ctx,
841 	             csi_file_t *file,
842 		     cairo_write_func_t write_func,
843 		     void *closure);
844 
845 csi_private void
846 _csi_scanner_fini (csi_t *ctx, csi_scanner_t *scanner);
847 
848 csi_private csi_boolean_t
849 _csi_parse_number (csi_object_t *obj, const char *s, int len);
850 
851 /* cairo-script-stack.c */
852 
853 csi_private csi_status_t
854 _csi_stack_init (csi_t *ctx, csi_stack_t *stack, csi_integer_t size);
855 
856 csi_private void
857 _csi_stack_fini (csi_t *ctx, csi_stack_t *stack);
858 
859 csi_private csi_status_t
860 _csi_stack_roll (csi_t *ctx,
861 		 csi_stack_t *stack,
862 		 csi_integer_t mod,
863 		 csi_integer_t n);
864 
865 csi_private csi_status_t
866 _csi_stack_grow (csi_t *ctx, csi_stack_t *stack, csi_integer_t cnt);
867 
868 csi_private csi_status_t
869 _csi_stack_push_internal (csi_t *ctx, csi_stack_t *stack,
870 			  const csi_object_t *obj);
871 
872 csi_private csi_object_t *
873 _csi_stack_peek (csi_stack_t *stack, csi_integer_t i);
874 
875 csi_private void
876 _csi_stack_pop (csi_t *ctx, csi_stack_t *stack, csi_integer_t count);
877 
878 csi_private csi_status_t
879 _csi_stack_exch (csi_stack_t *stack);
880 
881 static inline csi_object_type_t
csi_object_get_type(const csi_object_t * obj)882 csi_object_get_type (const csi_object_t *obj)
883 {
884     return obj->type & CSI_OBJECT_TYPE_MASK;
885 }
886 
887 static inline csi_boolean_t
csi_object_is_procedure(const csi_object_t * obj)888 csi_object_is_procedure (const csi_object_t *obj)
889 {
890     return obj->type == (CSI_OBJECT_TYPE_ARRAY | CSI_OBJECT_ATTR_EXECUTABLE);
891 }
892 
893 static inline csi_boolean_t
csi_object_is_number(const csi_object_t * obj)894 csi_object_is_number (const csi_object_t *obj)
895 {
896     int type = csi_object_get_type (obj);
897     switch (type) {
898     case CSI_OBJECT_TYPE_BOOLEAN:
899     case CSI_OBJECT_TYPE_INTEGER:
900     case CSI_OBJECT_TYPE_REAL:
901 	return 1;
902     default:
903 	return 0;
904     }
905 }
906 
907 static inline double
csi_number_get_value(const csi_object_t * obj)908 csi_number_get_value (const csi_object_t *obj)
909 {
910     int type = csi_object_get_type (obj);
911     switch (type) {
912     case CSI_OBJECT_TYPE_BOOLEAN: return obj->datum.boolean;
913     case CSI_OBJECT_TYPE_INTEGER: return obj->datum.integer;
914     case CSI_OBJECT_TYPE_REAL: return obj->datum.real;
915     default: return 0.;
916     }
917 }
918 
919 csi_status_t
920 _csi_stack_push (csi_t *ctx, csi_stack_t *stack,
921 		 const csi_object_t *obj);
922 
923 static inline csi_boolean_t
_csi_check_ostack(csi_t * ctx,csi_integer_t count)924 _csi_check_ostack (csi_t *ctx, csi_integer_t count)
925 {
926     return ctx->ostack.len >= count;
927 }
928 
929 static inline csi_object_t *
_csi_peek_ostack(csi_t * ctx,csi_integer_t i)930 _csi_peek_ostack (csi_t *ctx, csi_integer_t i)
931 {
932     return &ctx->ostack.objects[ctx->ostack.len - i -1];
933 }
934 
935 static inline void
_csi_pop_ostack(csi_t * ctx,csi_integer_t count)936 _csi_pop_ostack (csi_t *ctx, csi_integer_t count)
937 {
938     do
939 	csi_object_free (ctx, &ctx->ostack.objects[--ctx->ostack.len]);
940     while (--count);
941 }
942 
943 static inline csi_status_t
_csi_push_ostack_copy(csi_t * ctx,csi_object_t * obj)944 _csi_push_ostack_copy (csi_t *ctx, csi_object_t *obj)
945 {
946     return _csi_stack_push (ctx, &ctx->ostack, csi_object_reference (obj));
947 }
948 
949 static inline csi_status_t
_csi_push_ostack(csi_t * ctx,csi_object_t * obj)950 _csi_push_ostack (csi_t *ctx, csi_object_t *obj)
951 {
952     return _csi_stack_push (ctx, &ctx->ostack, obj);
953 }
954 
955 static inline csi_status_t
_csi_push_ostack_boolean(csi_t * ctx,csi_boolean_t v)956 _csi_push_ostack_boolean (csi_t *ctx, csi_boolean_t v)
957 {
958     csi_object_t obj;
959     obj.type = CSI_OBJECT_TYPE_BOOLEAN;
960     obj.datum.boolean = v;
961     return _csi_stack_push (ctx, &ctx->ostack, &obj);
962 }
963 static inline csi_status_t
_csi_push_ostack_integer(csi_t * ctx,csi_integer_t v)964 _csi_push_ostack_integer (csi_t *ctx, csi_integer_t v)
965 {
966     csi_object_t obj;
967     obj.type = CSI_OBJECT_TYPE_INTEGER;
968     obj.datum.integer = v;
969     return _csi_stack_push (ctx, &ctx->ostack, &obj);
970 }
971 static inline csi_status_t
_csi_push_ostack_mark(csi_t * ctx)972 _csi_push_ostack_mark (csi_t *ctx)
973 {
974     csi_object_t obj;
975     obj.type = CSI_OBJECT_TYPE_MARK;
976     return _csi_stack_push (ctx, &ctx->ostack, &obj);
977 }
978 static inline csi_status_t
_csi_push_ostack_null(csi_t * ctx)979 _csi_push_ostack_null (csi_t *ctx)
980 {
981     csi_object_t obj;
982     obj.type = CSI_OBJECT_TYPE_NULL;
983     return _csi_stack_push (ctx, &ctx->ostack, &obj);
984 }
985 static inline csi_status_t
_csi_push_ostack_real(csi_t * ctx,csi_real_t v)986 _csi_push_ostack_real (csi_t *ctx, csi_real_t v)
987 {
988     csi_object_t obj;
989     obj.type = CSI_OBJECT_TYPE_REAL;
990     obj.datum.real = v;
991     return _csi_stack_push (ctx, &ctx->ostack, &obj);
992 }
993 
994 slim_hidden_proto_no_warn (cairo_script_interpreter_destroy);
995 slim_hidden_proto_no_warn (cairo_script_interpreter_reference);
996 
997 #endif /* CAIRO_SCRIPT_PRIVATE_H */
998