386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / zvmem.c
CommitLineData
abc63828
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/* zvmem.c */
21/* "Virtual memory" operators for Ghostscript */
22#include "ghost.h"
23#include "errors.h"
24#include "oper.h"
25#include "alloc.h"
26#include "estack.h" /* for checking in restore */
27#include "dict.h" /* ditto */
28#include "dstack.h"
29#include "save.h"
30#include "state.h"
31#include "store.h"
32#include "gsmatrix.h" /* for gsstate.h */
33#include "gsstate.h"
34
35/* Imported operators */
36extern int zgsave(P1(os_ptr));
37extern int zgrestore(P1(os_ptr));
38
39/* Import the routine for setting the attributes of the identity matrix. */
40extern void init_identity_matrix(P0());
41
42/* 'Save' structure */
43typedef struct vm_save_s vm_save;
44struct vm_save_s {
45 alloc_save *asave; /* allocator save */
46 int_gstate isave; /* old interpreter state */
47 gs_state *gsave; /* old graphics state */
48};
49
50/* save */
51int
52zsave(register os_ptr op)
53{ vm_save *vmsave = (vm_save *)alloc(1, sizeof(vm_save), "zsave");
54 alloc_save *asave;
55 int code;
56 gs_state *prev, *prev2;
57 if ( vmsave == 0 ) return_error(e_VMerror);
58 asave = alloc_save_state();
59 if ( asave == 0 )
60 { alloc_free((char *)vmsave, 1, sizeof(vm_save), "zsave");
61 return_error(e_VMerror);
62 }
63 vmsave->asave = asave;
64 /* Save the old interpreter state, */
65 /* and cut the chains so we can't grestore past here. */
66 vmsave->isave = istate;
67 code = zgsave(op);
68 if ( code < 0 ) return code;
69 /* Swap the contents of the old and new states, */
70 /* so the new state points to the newly allocated components. */
71 prev = gs_state_swap_saved(igs, (gs_state *)0);
72 prev2 = gs_state_swap_saved(prev, (gs_state *)0);
73 gs_state_swap_saved(igs, prev2);
74 gs_state_swap(igs, prev);
75 vmsave->gsave = igs;
76 igs = prev;
77 istate.saved = 0;
78 push(1);
79 make_tv(op, t_save, psave, vmsave);
80 init_identity_matrix(); /* update l_new attribute */
81 return zgsave(op);
82}
83
84/* restore */
85private int restore_check_stack(P3(ref *, ref *, alloc_save *));
86private void restore_fix_stack(P3(ref *, ref *, alloc_save *));
87int
88zrestore(register os_ptr op)
89{ vm_save *vmsave;
90 alloc_save *asave;
91 check_type(*op, t_save);
92 vmsave = op->value.psave;
93 if ( vmsave == 0 ) /* invalidated save */
94 return_error(e_invalidrestore);
95 asave = vmsave->asave;
96 /* Check the contents of the stacks. */
97 { int code;
98 if ( (code = restore_check_stack(osbot, op, asave)) < 0 ||
99 (code = restore_check_stack(esbot, esp + 1, asave)) < 0 ||
100 (code = restore_check_stack(dstack, dsp + 1, asave)) < 0
101 )
102 return code;
103 }
104 if ( alloc_restore_state_check(asave) < 0 )
105 return_error(e_invalidrestore);
106 /* Invalidate any other copies of this save object on the stacks, */
107 /* and reset l_new in all stack entries if the new restore level */
108 /* is zero. */
109 restore_fix_stack(osbot, op, asave);
110 restore_fix_stack(esbot, esp + 1, asave);
111 restore_fix_stack(dstack, dsp + 1, asave);
112 /* Now it's safe to restore the state of memory. */
113 alloc_restore_state(asave);
114 /* Restore the interpreter and graphics state. */
115 istate = vmsave->isave;
116 igs = vmsave->gsave;
117 alloc_free((char *)vmsave, 1, sizeof(vm_save), "zrestore");
118 pop(1);
119 init_identity_matrix(); /* update l_new attribute */
120 return 0;
121}
122/* Check a stack to make sure all its elements are older than a save. */
123private int
124restore_check_stack(ref *bot, ref *top, alloc_save *asave)
125{ ref *stkp;
126 for ( stkp = bot; stkp < top; stkp++ )
127 { char *ptr;
128 switch ( r_type(stkp) )
129 {
130 case t_array: ptr = (char *)stkp->value.refs; break;
131 case t_condition: ptr = (char *)stkp->value.pcond; break;
132 case t_dictionary: ptr = (char *)stkp->value.pdict; break;
133 case t_fontID: ptr = (char *)stkp->value.pfont; break;
134 case t_gstate: ptr = (char *)stkp->value.pgstate; break;
135 /* case t_file: ****** WHAT? ****** */
136 case t_lock: ptr = (char *)stkp->value.plock; break;
137 case t_name:
138 /* Names are special because of how they are allocated. */
139 if ( alloc_name_is_since_save(stkp, asave) )
140 return_error(e_invalidrestore);
141 continue;
142 case t_save: ptr = (char *)stkp->value.psave; break;
143 case t_string: ptr = (char *)stkp->value.bytes; break;
144 case t_mixedarray: case t_shortarray:
145 ptr = (char *)stkp->value.packed; break;
146 case t_color: ptr = (char *)stkp->value.pcolor; break;
147 case t_device: ptr = (char *)stkp->value.pdevice; break;
148 default: continue;
149 }
150 if ( alloc_is_since_save(ptr, asave) )
151 return_error(e_invalidrestore);
152 }
153
154 return 0; /* OK */
155}
156/* Fix up the contents of a stack by invalidating */
157/* any save objects newer than the save being restored, */
158/* and, if the new save level is zero, clearing the l_new */
159/* bit in all the entries (since we can't tolerate values with */
160/* l_new set if the save level is zero). */
161private void
162restore_fix_stack(ref *bot, ref *top, alloc_save *asave)
163{ ref *stkp;
164 for ( stkp = bot; stkp < top; stkp++ )
165 { if ( r_type(stkp) == t_save &&
166 stkp->value.psave != 0 &&
167 (stkp->value.psave->asave == asave ||
168 alloc_is_since_save((char *)stkp->value.psave, asave))
169 )
170 stkp->value.psave = 0;
171 r_clear_attrs(stkp, l_new); /* always do it, no harm */
172 }
173}
174
175/* vmstatus */
176int
177zvmstatus(register os_ptr op)
178{ long used, total;
179 alloc_status(&used, &total);
180 push(3);
181 make_int(op - 2, alloc_save_level());
182 make_int(op - 1, used);
183 make_int(op, total);
184 return 0;
185}
186
187/* ------ Initialization procedure ------ */
188
189op_def zvmem_op_defs[] = {
190 {"1restore", zrestore},
191 {"0save", zsave},
192 {"0vmstatus", zvmstatus},
193 op_def_end(0)
194};