386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / packed.h
CommitLineData
e1765ea3
WJ
1/* Copyright (C) 1991 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* packed.h */
21/* Packed array format for Ghostscript */
22
23/*
24
25Packed elements come in 2 different sizes, 2 bytes or 8 bytes. The
26top 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
28bytes 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
36The jjj index of executable operators is either the index of the
37operator in the op_def_table, if the index is less than op_def_count,
38or the index of the definition in the op_array_table (subtracting
39op_def_count first).
40
41The iii index of names is the one that the name machinery already
42maintains. A name whose index is larger than 16K must be represented
43as a full 8-byte element.
44
45There are actually two packed array types, t_mixedarray and
46t_shortarray. A t_mixedarray can have a mix of 2- and 8-bit
47elements; a t_shortarray has all 2-byte elements. In both cases, the
48`size' is the number of elements.
49
50Packed array elements can be distinguished from full-size elements,
51so we allow the interpreter to simply execute all the different kinds
52of arrays directly. In theory, this could lead to unaligned accesses
53to full-size (8-byte) refs. Some machines can't handle unaligned
54accesses of this kind. Rather than try to tailor the algorithms to
55the machine's capabilities, we guarantee that full-size elements in
56mixed arrays are always properly aligned. We do this by converting
57up to 3 preceding 2-byte elements into 8-byte elements so that the
58alignment is preserved. The only code this actually affects is in
59make_packed_array. However, the save/restore machinery in isave.c is
60sometimes used to save changes to packed arrays, and it currently
61only knows how to save full-size, aligned refs.
62
63Note that code in zpacked.c and interp.c knows more about the
64representation of packed elements than the definitions in this file
65would imply. Read the code carefully if you change the
66representation.
67
68 */
69
70typedef ushort ref_packed;
71
72#define packed_type_shift 13
73typedef 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 */
94extern int make_packed_array(P4(ref *, uint, ref *, const char *));
95
96/* Get an element from a packed array. */
97extern 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)