386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / zmisc.c
CommitLineData
f6912cbd
WJ
1/* Copyright (C) 1989, 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/* zmisc.c */
21/* Miscellaneous operators for Ghostscript */
22#include "memory_.h"
23#include "string_.h"
24#include "ghost.h"
25#include "gp.h"
26#include "errors.h"
27#include "oper.h"
28#include "alloc.h"
29#include "dict.h"
30#include "dstack.h" /* for name lookup in bind */
31#include "name.h"
32#include "packed.h"
33#include "store.h"
34#include "gxfixed.h" /* for gstype1.h */
35#include "gstype1.h"
36
37/* Import the C getenv function */
38extern char *getenv(P1(char *));
39
40/* bind */
41int
42zbind(register os_ptr op)
43{ os_ptr bsp = op; /* bottom of stack */
44 ref *defp = op;
45 switch ( r_type(op) )
46 {
47 case t_array:
48 case t_mixedarray:
49 case t_shortarray:
50 break;
51 case t_oparray:
52 defp = &op_array_table.value.refs[op_index(op) - op_def_count];
53 break;
54 default:
55 return e_typecheck;
56 }
57 ++bsp;
58 /* We must not make the top-level procedure read-only, */
59 /* but we must bind it even if it is read-only already. */
60 *bsp = *defp;
61 /* Here are the invariants for the following loop: */
62 /* op < bsp <= ostop; */
63 /* for every pointer p such that op < p <= bsp, */
64 /* *p is an array (or packedarray) ref. */
65#define r_is_ex_oper(rp)\
66 ((r_btype(rp) == t_operator || r_type(rp) == t_oparray) &&\
67 r_has_attr(rp, a_executable))
68 while ( bsp > op )
69 { while ( r_size(bsp) )
70 { ref *tp = bsp->value.refs;
71 r_inc_size(bsp, -1);
72 if ( *(ushort *)tp > packed_max_full_ref )
73 { /* Check for a packed executable name */
74 ushort elt = *(ushort *)tp;
75 if ( (elt & ~(ushort)packed_max_name_index) ==
76 pt_tag(pt_executable_name) )
77 { ref nref;
78 ref *pvalue;
79 name_index_ref(elt & packed_max_name_index,
80 &nref);
81 if ( (pvalue = dict_find_name(&nref)) != 0 &&
82 r_is_ex_oper(pvalue)
83 )
84 /* Note: can't undo this by restore! */
85 *(ushort *)tp =
86 pt_tag(pt_executable_operator) +
87 op_index(pvalue);
88 }
89 bsp->value.refs = (ref *)((ushort *)tp + 1);
90 }
91 else
92 switch ( bsp->value.refs++, r_type(tp) )
93 {
94 case t_name: /* bind the name if an operator */
95 if ( r_has_attr(tp, a_executable) )
96 { ref *pvalue;
97 if ( (pvalue = dict_find_name(tp)) != 0 &&
98 r_is_ex_oper(pvalue)
99 )
100 ref_assign_old(tp, pvalue, "bind");
101 }
102 break;
103 case t_array: /* push into array if procedure */
104 if ( !r_has_attr(tp, a_write) ) break;
105 case t_mixedarray:
106 case t_shortarray:
107 if ( r_has_attr(tp, a_executable) && bsp < ostop )
108 { /* Make reference read-only */
109 r_clear_attrs(tp, a_write);
110 *++bsp = *tp;
111 }
112 }
113 }
114 bsp--;
115 }
116 return 0;
117}
118
119/* currenttime */
120int
121zcurrenttime(register os_ptr op)
122{ long date_time[2];
123 gp_get_clock(date_time);
124 push(1);
125 make_real(op, date_time[0] * 1440.0 + date_time[1] / 60000.0);
126 return 0;
127}
128
129/* getenv */
130int
131zgetenv(register os_ptr op)
132{ char *str, *value;
133 int code;
134 check_read_type(*op, t_string);
135 str = ref_to_string(op, "getenv name");
136 if ( str == 0 ) return e_VMerror;
137 value = getenv(str);
138 alloc_free(str, r_size(op) + 1, 1, "getenv name");
139 if ( value == 0 ) /* not found */
140 { make_bool(op, 0);
141 return 0;
142 }
143 code = string_to_ref(value, op, "getenv value");
144 if ( code < 0 ) return code;
145 push(1);
146 make_bool(op, 1);
147 return 0;
148}
149
150/* makeoperator */
151int
152zmakeoperator(register os_ptr op)
153{ check_type(op[-1], t_name);
154 check_proc(*op);
155 if ( op_array_count == r_size(&op_array_table) )
156 return e_limitcheck;
157 ref_assign_old(&op_array_table.value.refs[op_array_count],
158 op, "makeoperator");
159 op_array_nx_table[op_array_count] = name_index(op - 1);
160 r_set_type_attrs(op - 1, t_oparray, a_executable);
161 r_set_size(op - 1, op_def_count + op_array_count);
162 op_array_count++;
163 pop(1);
164 return 0;
165}
166
167/* setdebug */
168int
169zsetdebug(register os_ptr op)
170{ check_read_type(op[-1], t_string);
171 check_type(*op, t_boolean);
172#ifdef DEBUG
173 { int i;
174 for ( i = 0; i < r_size(op - 1); i++ )
175 gs_debug[op[-1].value.bytes[i] & 127] =
176 op->value.index;
177 }
178#endif
179 pop(2);
180 return 0;
181}
182
183/* type1encrypt, type1decrypt */
184private int type1crypt(P2(os_ptr,
185 int (*)(P4(byte *, byte *, uint, ushort *))));
186int
187ztype1encrypt(os_ptr op)
188{ return type1crypt(op, gs_type1_encrypt);
189}
190int
191ztype1decrypt(os_ptr op)
192{ return type1crypt(op, gs_type1_decrypt);
193}
194private int
195type1crypt(register os_ptr op, int (*proc)(P4(byte *, byte *, uint, ushort *)))
196{ crypt_state state;
197 uint ssize;
198 check_type(op[-2], t_integer);
199 state = op[-2].value.intval;
200 if ( op[-2].value.intval != state )
201 return e_rangecheck; /* state value was truncated */
202 check_read_type(op[-1], t_string);
203 check_write_type(*op, t_string);
204 ssize = r_size(op - 1);
205 if ( r_size(op) < ssize )
206 return e_rangecheck;
207 (void) (*proc)(op->value.bytes, op[-1].value.bytes, ssize,
208 &state); /* can't fail */
209 op[-2].value.intval = state;
210 op[-1] = *op;
211 r_set_size(op - 1, ssize);
212 pop(1);
213 return 0;
214}
215
216/* usertime */
217int
218zusertime(register os_ptr op)
219{ long date_time[2];
220 gp_get_clock(date_time);
221 push(1);
222 make_int(op, date_time[0] * 86400000L + date_time[1]);
223 return 0;
224}
225
226/* ------ Initialization procedure ------ */
227
228op_def zmisc_op_defs[] = {
229 {"1bind", zbind},
230 {"0currenttime", zcurrenttime},
231 {"1getenv", zgetenv},
232 {"2makeoperator", zmakeoperator},
233 {"2setdebug", zsetdebug},
234 {"3type1encrypt", ztype1encrypt},
235 {"3type1decrypt", ztype1decrypt},
236 {"0usertime", zusertime},
237 op_def_end(0)
238};