Commit | Line | Data |
---|---|---|
e1765ea3 WJ |
1 | /* Copyright (C) 1991 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* packed.h */ | |
21 | /* Packed array format for Ghostscript */ | |
22 | ||
23 | /* | |
24 | ||
25 | Packed elements come in 2 different sizes, 2 bytes or 8 bytes. The | |
26 | top bits of the first 16-bit subelement distinguish the 2 forms. The | |
27 | 'size' of a packed array is the number of elements, not the number of | |
28 | bytes it occupies. The encoding: | |
29 | ||
30 | 00-ttttt texrwsnm full 8-byte object | |
31 | 010jjjjj jjjjjjjj executable operator (for bind) | |
32 | 011vvvvv vvvvvvvv integer (biased by packed_min_intval) | |
33 | 10iiiiii iiiiiiii literal name | |
34 | 11iiiiii iiiiiiii executable name | |
35 | ||
36 | The jjj index of executable operators is either the index of the | |
37 | operator in the op_def_table, if the index is less than op_def_count, | |
38 | or the index of the definition in the op_array_table (subtracting | |
39 | op_def_count first). | |
40 | ||
41 | The iii index of names is the one that the name machinery already | |
42 | maintains. A name whose index is larger than 16K must be represented | |
43 | as a full 8-byte element. | |
44 | ||
45 | There are actually two packed array types, t_mixedarray and | |
46 | t_shortarray. A t_mixedarray can have a mix of 2- and 8-bit | |
47 | elements; a t_shortarray has all 2-byte elements. In both cases, the | |
48 | `size' is the number of elements. | |
49 | ||
50 | Packed array elements can be distinguished from full-size elements, | |
51 | so we allow the interpreter to simply execute all the different kinds | |
52 | of arrays directly. In theory, this could lead to unaligned accesses | |
53 | to full-size (8-byte) refs. Some machines can't handle unaligned | |
54 | accesses of this kind. Rather than try to tailor the algorithms to | |
55 | the machine's capabilities, we guarantee that full-size elements in | |
56 | mixed arrays are always properly aligned. We do this by converting | |
57 | up to 3 preceding 2-byte elements into 8-byte elements so that the | |
58 | alignment is preserved. The only code this actually affects is in | |
59 | make_packed_array. However, the save/restore machinery in isave.c is | |
60 | sometimes used to save changes to packed arrays, and it currently | |
61 | only knows how to save full-size, aligned refs. | |
62 | ||
63 | Note that code in zpacked.c and interp.c knows more about the | |
64 | representation of packed elements than the definitions in this file | |
65 | would imply. Read the code carefully if you change the | |
66 | representation. | |
67 | ||
68 | */ | |
69 | ||
70 | typedef ushort ref_packed; | |
71 | ||
72 | #define packed_type_shift 13 | |
73 | typedef enum { | |
74 | pt_full_ref = 0, | |
75 | #define pt_min_packed 2 | |
76 | pt_executable_operator = 2, | |
77 | pt_integer = 3, | |
78 | pt_literal_name = 4, | |
79 | pt_executable_name = 6 | |
80 | } packed_type; | |
81 | #define pt_tag(pt) ((ref_packed)(pt) << packed_type_shift) | |
82 | #define r_is_packed(rp) (*(ref_packed *)(rp) >= pt_tag(pt_min_packed)) | |
83 | #define packed_ref_is_name(prp) (*(prp) >= pt_tag(pt_literal_name)) | |
84 | #define packed_max_full_ref ((2 << packed_type_shift) - 1) | |
85 | #define packed_min_intval (-(1 << (packed_type_shift - 1))) | |
86 | #define packed_max_intval ((1 << (packed_type_shift - 1)) - 1) | |
87 | #define packed_int_mask ((1 << packed_type_shift) - 1) | |
88 | #define packed_max_name_index ((1 << (packed_type_shift + 1)) - 1) | |
89 | ||
90 | /* Procedures implemented in zpacked.c */ | |
91 | #define packed_per_ref (sizeof(ref) / sizeof(ref_packed)) | |
92 | ||
93 | /* Make a packed array */ | |
94 | extern int make_packed_array(P4(ref *, uint, ref *, const char *)); | |
95 | ||
96 | /* Get an element from a packed array. */ | |
97 | extern void packed_get(P2(const ref_packed *, ref *)); | |
98 | /* Advance to the next element in a packed array. */ | |
99 | #define packed_next(packed)\ | |
100 | (*packed <= packed_max_full_ref ? packed + packed_per_ref : packed + 1) |