386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / zprops.c
CommitLineData
0efb8845
WJ
1/* Copyright (C) 1991, 1992 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/* zprops.c */
21/* Device property operators */
22#include "memory_.h"
23#include "ghost.h"
24#include "alloc.h"
25#include "dict.h"
26#include "errors.h"
27#include "oper.h"
28#include "name.h"
29#include "store.h"
30#include "gsprops.h"
31#include "gsmatrix.h" /* for gxdevice.h */
32#include "gxdevice.h"
33
34/* Imported procedures */
35extern int array_get(P3(ref *, long, ref *));
36
37/* Forward references */
38private int props_to_stack(P3(gs_prop_item *, os_ptr, int));
39private int props_from_stack(P3(gs_prop_item *, os_ptr, int));
40
41/* getdeviceprops */
42int
43zgetdeviceprops(os_ptr op)
44{ gx_device *dev;
45 gs_prop_item *plist;
46 int count;
47 int code;
48 check_type(*op, t_device);
49 dev = op->value.pdevice;
50 count = (*dev->procs->get_props)(dev, NULL);
51 plist = (gs_prop_item *)alloc(count, sizeof(gs_prop_item), "getdeviceprops");
52 if ( plist == 0 ) return_error(e_VMerror);
53 (*dev->procs->get_props)(dev, plist);
54 code = props_to_stack(plist, op + 1, count);
55 alloc_free((char *)plist, count, sizeof(gs_prop_item), "getdeviceprops");
56 if ( code >= 0 )
57 { make_mark(op);
58 push(code);
59 code = 0;
60 }
61 return code;
62}
63
64/* putdeviceprops */
65int
66zputdeviceprops(os_ptr op)
67{ gx_device *dev;
68 gs_prop_item *plist;
69 os_ptr mp;
70 int count, acount = 0;
71 int code;
72 check_type(*op, t_device);
73 dev = op->value.pdevice;
74 for ( mp = op - 1; !r_has_type(mp, t_mark); mp-- )
75 { if ( mp <= osbot ) return e_unmatchedmark;
76 switch ( r_type(mp) )
77 {
78 case t_array:
79 case t_mixedarray:
80 case t_shortarray:
81 acount += r_size(mp);
82 }
83 }
84 count = op - mp - 1;
85 if ( count & 1 ) return e_rangecheck;
86 count >>= 1;
87 plist = (gs_prop_item *)alloc(count + acount, sizeof(gs_prop_item), "putdeviceprops");
88 if ( plist == 0 ) return_error(e_VMerror);
89 code = props_from_stack(plist, mp + 1, count);
90 if ( code >= 0 )
91 code = (*dev->procs->put_props)(dev, plist, count + acount);
92 alloc_free((char *)plist, count + acount, sizeof(gs_prop_item), "putdeviceprops");
93 if ( code >= 0 )
94 { *mp = *op;
95 osp = op = mp;
96 }
97 return code;
98}
99
100/* ------ Initialization procedure ------ */
101
102op_def zprops_op_defs[] = {
103 {"1getdeviceprops", zgetdeviceprops},
104 {"2putdeviceprops", zputdeviceprops},
105 op_def_end(0)
106};
107
108/* ------ Internal routines ------ */
109
110/* Get properties from a property list to the stack. */
111private int
112props_to_stack(gs_prop_item *plist, os_ptr op0, int count)
113{ gs_prop_item *pi;
114 os_ptr op;
115 int i;
116 int code;
117 for ( op = op0, pi = plist, i = count; i != 0; pi++, i-- )
118 { ref value;
119 const char *nstr = pi->pname;
120 int nlen = pi->name_size;
121 if ( nstr == 0 ) continue; /* no name, skip */
122 if ( ostop - op < 2 ) return e_stackoverflow;
123 if ( nlen < 0 ) nlen = strlen(nstr);
124 code = name_ref((const byte *)nstr, nlen, op, 0);
125 if ( code < 0 ) return code;
126 switch ( pi->type )
127 {
128 case (int)prt_int:
129 make_int(&value, pi->value.i);
130 break;
131 case (int)prt_float:
132 make_real(&value, pi->value.f);
133 break;
134 case (int)prt_bool:
135 make_bool(&value, pi->value.b);
136 break;
137 case (int)prt_string:
138 { ushort size = pi->value.a.size;
139 char *str;
140 if ( size == (ushort)(-1) )
141 size = strlen(pi->value.a.p.s);
142 str = alloc(size, 1, "props_to_stack(string)");
143 if ( str == 0 ) return e_VMerror;
144 memcpy(str, pi->value.a.p.s, size);
145 make_tasv(&value, t_string, a_all, size, bytes, (byte *)str);
146 } break;
147 case (int)prt_int_array:
148 case (int)prt_float_array:
149 { uint size = pi->value.a.size;
150 ref *arefs = alloc_refs(size, "props_to_stack(array)");
151 uint j;
152 gs_prop_item *pv = pi->value.a.p.v;
153 if ( arefs == 0 ) return e_VMerror;
154 make_tasv_new(&value, t_array, a_all, size, refs, arefs);
155 for ( j = 0; j < size; j++, arefs++, pv++ )
156 if ( pi->type == prt_int_array )
157 make_int_new(arefs, pv->value.i);
158 else
159 make_real_new(arefs, pv->value.f);
160 } break;
161 default:
162 return e_typecheck;
163 }
164 ref_assign(op + 1, &value);
165 op += 2;
166 }
167 return op - op0;
168}
169
170/* Set properties from the stack. */
171/* Returns the number of elements copied. */
172/* Entries with non-name keys are not copied; */
173/* entries with invalid values are copied with status = pv_typecheck. */
174private int
175props_from_stack(gs_prop_item *plist /* [count + acount] */, os_ptr op0,
176 int count)
177{ gs_prop_item *pi = plist;
178 gs_prop_item *pai = plist + count;
179 os_ptr op = op0 + 1;
180 for ( ; count; op += 2, count-- )
181 { ref sref;
182 if ( !r_has_type(op - 1, t_name) ) return e_typecheck;
183 name_string_ref(op - 1, &sref);
184 pi->pname = (char *)sref.value.bytes;
185 pi->name_size = r_size(&sref);
186 pi->status = pv_set;
187 switch ( r_type(op) )
188 {
189 case t_null:
190 pi->type = prt_null;
191 break;
192 case t_integer:
193 pi->type = prt_int;
194 pi->value.i = op->value.intval;
195 break;
196 case t_real:
197 pi->type = prt_float;
198 pi->value.f = op->value.realval;
199 break;
200 case t_boolean:
201 pi->type = prt_bool;
202 pi->value.b = op->value.index;
203 break;
204 case t_name:
205 name_string_ref(op, &sref);
206 goto nst;
207 case t_string:
208 ref_assign(&sref, op);
209 pi->type = prt_string;
210 pi->value.a.p.s = (char *)op->value.bytes;
211nst: pi->value.a.size = r_size(&sref);
212 break;
213 case t_array:
214 case t_mixedarray:
215 case t_shortarray:
216 { uint size = r_size(op);
217 uint i;
218 gs_prop_item *pv;
219 gs_prop_type tv = prt_int;
220 pi->type = prt_int_array;
221 pi->value.a.p.v = pai;
222 pi->value.a.size = size;
223top: pv = pai;
224 for ( i = 0; i < size; i++ )
225 { ref rnum;
226 array_get(op, (long)i, &rnum);
227 pv->pname = 0;
228 pv->type = tv;
229 switch ( r_type(&rnum) )
230 {
231 case t_real:
232 if ( tv == prt_int )
233 { tv = prt_float;
234 pi->type = prt_float_array;
235 goto top;
236 }
237 pv++->value.f = rnum.value.realval;
238 break;
239 case t_integer:
240 if ( tv == prt_int )
241 pv++->value.i = rnum.value.intval;
242 else
243 pv++->value.f = rnum.value.intval;
244 break;
245 default:
246 pi->status = pv_typecheck;
247 }
248 }
249
250 pai = pv;
251 } break;
252 default:
253 pi->status = pv_typecheck;
254 }
255 pi++;
256 }
257 return 0;
258}