1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: icontext.c 9043 2008-08-28 22:48:19Z giles $ */
15
/* Context state operations */
17
#include "gsstruct.h" /* for gxalloc.h */
20
#include "stream.h" /* for files.h */
31
/* Declare the GC descriptors for embedded objects. */
32
extern_st(st_gs_dual_memory);
33
extern_st(st_ref_stack);
34
extern_st(st_dict_stack);
35
extern_st(st_exec_stack);
36
extern_st(st_op_stack);
40
CLEAR_MARKS_PROC(context_state_clear_marks)
42
gs_context_state_t *const pcst = vptr;
44
r_clear_attrs(&pcst->stdio[0], l_mark);
45
r_clear_attrs(&pcst->stdio[1], l_mark);
46
r_clear_attrs(&pcst->stdio[2], l_mark);
47
r_clear_attrs(&pcst->error_object, l_mark);
48
r_clear_attrs(&pcst->userparams, l_mark);
51
ENUM_PTRS_WITH(context_state_enum_ptrs, gs_context_state_t *pcst) {
53
if (index < st_gs_dual_memory_num_ptrs)
54
return ENUM_USING(st_gs_dual_memory, &pcst->memory,
55
sizeof(pcst->memory), index);
56
index -= st_gs_dual_memory_num_ptrs;
57
if (index < st_dict_stack_num_ptrs)
58
return ENUM_USING(st_dict_stack, &pcst->dict_stack,
59
sizeof(pcst->dict_stack), index);
60
index -= st_dict_stack_num_ptrs;
61
if (index < st_exec_stack_num_ptrs)
62
return ENUM_USING(st_exec_stack, &pcst->exec_stack,
63
sizeof(pcst->exec_stack), index);
64
index -= st_exec_stack_num_ptrs;
65
return ENUM_USING(st_op_stack, &pcst->op_stack,
66
sizeof(pcst->op_stack), index);
68
ENUM_PTR(0, gs_context_state_t, pgs);
69
case 1: ENUM_RETURN_REF(&pcst->stdio[0]);
70
case 2: ENUM_RETURN_REF(&pcst->stdio[1]);
71
case 3: ENUM_RETURN_REF(&pcst->stdio[2]);
72
case 4: ENUM_RETURN_REF(&pcst->error_object);
73
case 5: ENUM_RETURN_REF(&pcst->userparams);
75
static RELOC_PTRS_WITH(context_state_reloc_ptrs, gs_context_state_t *pcst);
76
RELOC_PTR(gs_context_state_t, pgs);
77
RELOC_USING(st_gs_dual_memory, &pcst->memory, sizeof(pcst->memory));
78
/******* WHY DON'T WE CLEAR THE l_mark OF stdio? ******/
79
RELOC_REF_VAR(pcst->stdio[0]);
80
RELOC_REF_VAR(pcst->stdio[1]);
81
RELOC_REF_VAR(pcst->stdio[2]);
82
RELOC_REF_VAR(pcst->error_object);
83
r_clear_attrs(&pcst->error_object, l_mark);
84
RELOC_REF_VAR(pcst->userparams);
85
r_clear_attrs(&pcst->userparams, l_mark);
86
RELOC_USING(st_dict_stack, &pcst->dict_stack, sizeof(pcst->dict_stack));
87
RELOC_USING(st_exec_stack, &pcst->exec_stack, sizeof(pcst->exec_stack));
88
RELOC_USING(st_op_stack, &pcst->op_stack, sizeof(pcst->op_stack));
90
public_st_context_state();
92
/* Allocate the state of a context. */
94
context_state_alloc(gs_context_state_t ** ppcst,
95
const ref *psystem_dict,
96
const gs_dual_memory_t * dmem)
98
gs_ref_memory_t *mem = dmem->space_local;
99
gs_context_state_t *pcst = *ppcst;
104
pcst = gs_alloc_struct((gs_memory_t *) mem, gs_context_state_t,
105
&st_context_state, "context_state_alloc");
107
return_error(e_VMerror);
109
code = gs_interp_alloc_stacks(mem, pcst);
113
* We have to initialize the dictionary stack early,
114
* for far-off references to systemdict.
116
pcst->dict_stack.system_dict = *psystem_dict;
117
pcst->dict_stack.min_size = 0;
118
pcst->dict_stack.userdict_index = 0;
119
pcst->pgs = int_gstate_alloc(dmem);
120
if (pcst->pgs == 0) {
121
code = gs_note_error(e_VMerror);
124
pcst->memory = *dmem;
125
pcst->language_level = 1;
126
make_false(&pcst->array_packing);
127
make_int(&pcst->binary_object_format, 0);
128
pcst->rand_state = rand_state_initial;
129
pcst->usertime_total = 0;
130
pcst->keep_usertime = false;
131
pcst->in_superexec = 0;
132
pcst->plugin_list = 0;
133
make_t(&pcst->error_object, t__invalid);
135
* Create an empty userparams dictionary of the right size.
136
* If we can't determine the size, pick an arbitrary one.
140
ref *system_dict = &pcst->dict_stack.system_dict;
142
if (dict_find_string(system_dict, "userparams", &puserparams) >= 0)
143
size = dict_length(puserparams);
146
code = dict_alloc(pcst->memory.space_local, size, &pcst->userparams);
149
/* PostScript code initializes the user parameters. */
151
pcst->scanner_options = 0;
152
pcst->LockFilePermissions = false;
153
pcst->starting_arg_file = false;
154
pcst->RenderTTNotdef = true;
155
/* The initial stdio values are bogus.... */
156
make_file(&pcst->stdio[0], a_readonly | avm_invalid_file_entry, 1,
158
make_file(&pcst->stdio[1], a_all | avm_invalid_file_entry, 1,
160
make_file(&pcst->stdio[2], a_all | avm_invalid_file_entry, 1,
162
for (i = countof(pcst->memory.spaces_indexed); --i >= 0;)
163
if (dmem->spaces_indexed[i] != 0)
164
++(dmem->spaces_indexed[i]->num_contexts);
167
x2:gs_state_free(pcst->pgs);
168
x1:gs_interp_free_stacks(mem, pcst);
170
gs_free_object((gs_memory_t *) mem, pcst, "context_state_alloc");
174
/* Load the interpreter state from a context. */
176
context_state_load(gs_context_state_t * i_ctx_p)
178
gs_ref_memory_t *lmem = iimemory_local;
179
ref *system_dict = systemdict;
180
uint space = r_space(system_dict);
181
dict_stack_t *dstack = &idict_stack;
185
* Disable save checking, and space check for systemdict, while
186
* copying dictionaries.
188
alloc_set_not_in_save(idmemory);
189
r_set_space(system_dict, avm_max);
191
* Switch references from systemdict to local objects.
192
* userdict.localdicts holds these objects. We could optimize this by
193
* only doing it if we're changing to a different local VM relative to
194
* the same global VM, but the cost is low enough relative to other
195
* things that we don't bother.
198
ref_stack_t *rdstack = &dstack->stack;
199
const ref *puserdict =
200
ref_stack_index(rdstack, ref_stack_count(rdstack) - 1 -
201
dstack->userdict_index);
204
if (dict_find_string(puserdict, "localdicts", &plocaldicts) > 0 &&
205
r_has_type(plocaldicts, t_dictionary)
207
dict_copy(plocaldicts, system_dict, dstack);
211
* Set systemdict.userparams to the saved copy, and then
212
* set the actual user parameters. Note that we must disable both
213
* space checking and save checking while doing this. Also,
214
* we must do this after copying localdicts (if required), because
215
* userparams also appears in localdicts.
217
code = dict_put_string(system_dict, "userparams", &i_ctx_p->userparams,
220
code = set_user_params(i_ctx_p, &i_ctx_p->userparams);
221
r_set_space(system_dict, space);
222
if (lmem->save_level > 0)
223
alloc_set_in_save(idmemory);
224
estack_clear_cache(&iexec_stack);
225
dstack_set_top(&idict_stack);
229
/* Store the interpreter state in a context. */
231
context_state_store(gs_context_state_t * pcst)
233
ref_stack_cleanup(&pcst->dict_stack.stack);
234
ref_stack_cleanup(&pcst->exec_stack.stack);
235
ref_stack_cleanup(&pcst->op_stack.stack);
237
* The user parameters in systemdict.userparams are kept
238
* up to date by PostScript code, but we still need to save
239
* systemdict.userparams to get the correct l_new flag.
243
/* We need i_ctx_p for access to the d_stack. */
244
i_ctx_t *i_ctx_p = pcst;
246
if (dict_find_string(systemdict, "userparams", &puserparams) < 0)
247
return_error(e_Fatal);
248
pcst->userparams = *puserparams;
253
/* Free the contents of the state of a context, always to its local VM. */
254
/* Return a mask of which of its VMs, if any, we freed. */
256
context_state_free(gs_context_state_t * pcst)
258
gs_ref_memory_t *mem = pcst->memory.space_local;
263
* If this context is the last one referencing a particular VM
264
* (local / global / system), free the entire VM space;
265
* otherwise, just free the context-related structures.
267
for (i = countof(pcst->memory.spaces_indexed); --i >= 0;) {
268
if (pcst->memory.spaces_indexed[i] != 0 &&
269
!--(pcst->memory.spaces_indexed[i]->num_contexts)
271
/****** FREE THE ENTIRE SPACE ******/
276
* If we freed any spaces at all, we must have freed the local
277
* VM where the context structure and its substructures were
283
gs_state *pgs = pcst->pgs;
286
/* Patch the saved pointer so we can do the last grestore. */
288
gs_state *saved = gs_state_saved(pgs);
290
gs_state_swap_saved(saved, saved);
293
gs_state_swap_saved(pgs, (gs_state *) 0);
296
/****** FREE USERPARAMS ******/
297
gs_interp_free_stacks(mem, pcst);