Commit | Line | Data |
---|---|---|
5aa04bbc WJ |
1 | /* Copyright (C) 1989, 1992 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 | /* idebug.c */ | |
21 | /* Debugging support for Ghostscript interpreter */ | |
22 | #include "string_.h" | |
23 | #include "ghost.h" | |
24 | #include "iutil.h" | |
25 | #include "dict.h" | |
26 | #include "name.h" | |
27 | #include "ostack.h" /* for opdef.h */ | |
28 | #include "opdef.h" | |
29 | #include "packed.h" | |
30 | #include "store.h" /* for make_oper for opdef.h */ | |
31 | ||
32 | /* Forward references */ | |
33 | void debug_print_string(P2(const byte *, ushort)); | |
34 | #define debug_print_name(pnref)\ | |
35 | debug_print_string((pnref)->value.pname->string_bytes,\ | |
36 | (pnref)->value.pname->string_size) | |
37 | ||
38 | /* Table of type name strings */ | |
39 | static const char *type_strings[] = { type_print_strings }; | |
40 | ||
41 | /* Print a ref */ | |
42 | void debug_print_ref(P1(const ref *)); | |
43 | void | |
44 | debug_print_full_ref(const ref *pref) | |
45 | { unsigned size = r_size(pref); | |
46 | ref nref; | |
47 | dprintf1("(%x)", r_type_attrs(pref)); | |
48 | switch ( r_type(pref) ) | |
49 | { | |
50 | case t_array: | |
51 | dprintf2("array(%u)0x%lx", size, (ulong)pref->value.refs); break; | |
52 | case t_boolean: | |
53 | dprintf1("boolean %x", pref->value.index); break; | |
54 | case t_color: | |
55 | dprintf1("color 0x%lx", (ulong)pref->value.pcolor); break; | |
56 | case t_condition: | |
57 | dprintf1("condition 0x%lx", (ulong)pref->value.pcond); break; | |
58 | case t_device: | |
59 | dprintf1("device 0x%lx", (ulong)pref->value.pdevice); break; | |
60 | case t_dictionary: | |
61 | dprintf3("dict(%u/%u)0x%lx", | |
62 | dict_length(pref), dict_maxlength(pref), | |
63 | (ulong)pref->value.pdict); | |
64 | break; | |
65 | case t_file: | |
66 | dprintf1("file 0x%lx", (ulong)pref->value.pfile); break; | |
67 | case t_gstate: | |
68 | dprintf1("gstate 0x%lx", (ulong)pref->value.pgstate); break; | |
69 | case t_integer: dprintf1("int %ld", pref->value.intval); break; | |
70 | case t_lock: | |
71 | dprintf1("lock 0x%lx", (ulong)pref->value.plock); break; | |
72 | case t_mark: dprintf("mark"); break; | |
73 | case t_mixedarray: | |
74 | dprintf2("mixed packedarray(%u)0x%lx", size, | |
75 | (ulong)pref->value.packed); break; | |
76 | case t_name: | |
77 | dprintf2("name(0x%lx#%x)", (ulong)pref->value.pname, | |
78 | pref->value.pname->index); | |
79 | debug_print_name(pref); | |
80 | break; | |
81 | case t_null: dprintf("null"); break; | |
82 | case t_oparray: | |
83 | dprintf1("op_array(0x%x)", size); | |
84 | name_index_ref(op_array_nx_table[size - op_def_count], &nref); | |
85 | debug_print_name(&nref); | |
86 | break; | |
87 | case t_operator: | |
88 | dprintf1("op(0x%x", size); | |
89 | if ( size ) | |
90 | dprintf1(":%s", (const char *)(op_def_table[size]->oname + 1)); | |
91 | dprintf1(")0x%lx", (ulong)pref->value.opproc); | |
92 | break; | |
93 | case t_real: dprintf1("real %f", pref->value.realval); break; | |
94 | case t_shortarray: | |
95 | dprintf2("short packedarray(%u)0x%lx", size, | |
96 | (ulong)pref->value.packed); break; | |
97 | case t_string: | |
98 | dprintf2("string(%u)0x%lx", size, (ulong)pref->value.bytes); break; | |
99 | default: dprintf1("type 0x%x", r_type(pref)); | |
100 | } | |
101 | } | |
102 | void | |
103 | debug_print_packed_ref(const ref_packed *pref) | |
104 | { ushort elt = *pref; | |
105 | ref nref; | |
106 | switch ( elt >> packed_type_shift ) | |
107 | { | |
108 | case pt_executable_operator: | |
109 | dprintf("<op_name>"); | |
110 | elt &= packed_int_mask; | |
111 | op_index_ref(elt, &nref); | |
112 | debug_print_ref(&nref); | |
113 | break; | |
114 | case pt_integer: | |
115 | dprintf1("<int> %d", (elt & packed_int_mask) + packed_min_intval); | |
116 | break; | |
117 | case pt_literal_name: case pt_literal_name+1: | |
118 | dprintf("<lit_name>"); elt &= packed_max_name_index; goto ptn; | |
119 | case pt_executable_name: case pt_executable_name+1: | |
120 | dprintf("<exec_name>"); elt &= packed_max_name_index; | |
121 | ptn: name_index_ref(elt, &nref); | |
122 | dprintf2("(0x%lx#%x)", (ulong)nref.value.pname, elt); | |
123 | debug_print_name(&nref); | |
124 | break; | |
125 | } | |
126 | } | |
127 | void | |
128 | debug_print_ref(const ref *pref) | |
129 | { if ( r_is_packed(pref) ) | |
130 | debug_print_packed_ref((const ref_packed *)pref); | |
131 | else | |
132 | debug_print_full_ref(pref); | |
133 | } | |
134 | ||
135 | /* Print a string */ | |
136 | void | |
137 | debug_print_string(const byte *chrs, ushort len) | |
138 | { ushort i; | |
139 | for ( i = 0; i < len; i++ ) | |
140 | dputc(chrs[i]); | |
141 | } | |
142 | ||
143 | /* Dump one ref */ | |
144 | void | |
145 | debug_dump_one_ref(const ref *p) | |
146 | { uint attrs = r_type_attrs(p); | |
147 | uint btype = r_btype(p); | |
148 | static const char *as = attr_print_string; | |
149 | const char *ap = as; | |
150 | #define buf_size 30 | |
151 | char buf[buf_size + 1]; | |
152 | uint plen; | |
153 | if ( btype >= t_next_index ) | |
154 | dprintf1("0x%02x?? ", btype); | |
155 | else | |
156 | dprintf1("%s ", type_strings[btype]); | |
157 | for ( ; *ap; ap++, attrs >>= 1 ) | |
158 | if ( *ap != '.' ) | |
159 | dputc(((attrs & 1) ? *ap : '-')); | |
160 | dprintf2(" 0x%04x 0x%08lx", r_size(p), *(const ulong *)&p->value); | |
161 | if ( obj_cvs(p, (byte *)buf, buf_size, &plen) >= 0 && | |
162 | ((buf[plen] = 0), strcmp(buf, "--nostringval--")) | |
163 | ) | |
164 | dprintf1(" = %s", buf); | |
165 | } | |
166 | ||
167 | /* Dump a region of memory containing refs */ | |
168 | void | |
169 | debug_dump_refs(const ref *from, uint size, const char *msg) | |
170 | { const ref *p = from; | |
171 | uint count = size; | |
172 | if ( size && msg ) | |
173 | dprintf2("%s at 0x%lx:\n", msg, (ulong)from); | |
174 | while ( count-- ) | |
175 | { dprintf2("..%04x: 0x%02x ", (uint)p & 0xffff, r_type(p)); | |
176 | debug_dump_one_ref(p); | |
177 | dputc('\n'); | |
178 | p++; | |
179 | } | |
180 | } | |
181 | ||
182 | /* Dump a region of memory */ | |
183 | void | |
184 | debug_dump_bytes(const byte *from, const byte *to, const char *msg) | |
185 | { const byte *p = from; | |
186 | if ( from < to && msg ) | |
187 | dprintf1("%s:\n", msg); | |
188 | while ( p != to ) | |
189 | { const byte *q = min(p + 16, to); | |
190 | dprintf1("%lx:", (ulong)p); | |
191 | while ( p != q ) dprintf1(" %02x", *p++); | |
192 | dputc('\n'); | |
193 | } | |
194 | } | |
195 | ||
196 | /* Dump an array. */ | |
197 | void | |
198 | debug_dump_array(const ref *array) | |
199 | { const ref_packed *pp; | |
200 | unsigned int type = r_type(array); | |
201 | uint len; | |
202 | ||
203 | switch (type) | |
204 | { | |
205 | default: | |
206 | dprintf2 ("%s at 0x%lx isn't an array.\n", | |
207 | (type < countof(type_strings) ? | |
208 | type_strings[type] : "????"), | |
209 | (ulong)array); | |
210 | return; | |
211 | case t_oparray: | |
212 | /* This isn't really an array, but we'd like to see */ | |
213 | /* its contents anyway. */ | |
214 | debug_dump_array(op_array_table.value.refs + op_index(array) - | |
215 | op_def_count); | |
216 | return; | |
217 | case t_array: | |
218 | case t_mixedarray: | |
219 | case t_shortarray: | |
220 | ; | |
221 | } | |
222 | ||
223 | /* This "packed" loop works for all array-types. */ | |
224 | for ( len = r_size (array), pp = array->value.packed; | |
225 | len > 0; | |
226 | len--, pp = packed_next(pp)) | |
227 | { ref temp; | |
228 | packed_get(pp, &temp); | |
229 | dprintf3("..%04x%c 0x%02x ", | |
230 | (uint)pp & 0xffff, | |
231 | ((r_is_packed(pp)) ? '*' : ':'), | |
232 | r_type(&temp)); | |
233 | debug_dump_one_ref(&temp); | |
234 | dputc ('\n'); | |
235 | } | |
236 | } |