home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises. All rights reserved.
-
- This file is part of Aladdin Ghostscript.
-
- Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
- or distributor accepts any responsibility for the consequences of using it,
- or for whether it serves any particular purpose or works at all, unless he
- or she says so in writing. Refer to the Aladdin Ghostscript Free Public
- License (the "License") for full details.
-
- Every copy of Aladdin Ghostscript must include a copy of the License,
- normally in a plain ASCII text file named PUBLIC. The License grants you
- the right to copy, modify and redistribute Aladdin Ghostscript, but only
- under certain conditions described in the License. Among other things, the
- License requires that the copyright notice and this notice be preserved on
- all copies.
- */
-
- /* zvmem.c */
- /* "Virtual memory" operators */
- #include "ghost.h"
- #include "gsstruct.h"
- #include "errors.h"
- #include "oper.h"
- #include "estack.h" /* for checking in restore */
- #include "ialloc.h"
- #include "idict.h" /* ditto */
- #include "igstate.h"
- #include "isave.h"
- #include "dstack.h"
- #include "store.h"
- #include "gsmatrix.h" /* for gsstate.h */
- #include "gsstate.h"
-
- /* Imported operators */
- extern int zgsave(P1(os_ptr));
- extern int zgrestore(P1(os_ptr));
-
- /* 'Save' structure */
- typedef struct vm_save_s vm_save_t;
- struct vm_save_s {
- gs_state *gsave; /* old graphics state */
- };
- gs_private_st_ptrs1(st_vm_save, vm_save_t, "savetype",
- vm_save_enum_ptrs, vm_save_reloc_ptrs, gsave);
-
- /* - save <save> */
- int
- zsave(register os_ptr op)
- { vm_save_t *vmsave = ialloc_struct(vm_save_t, &st_vm_save, "zsave");
- ulong sid;
- int code;
- gs_state *prev;
- if ( vmsave == 0 )
- return_error(e_VMerror);
- sid = alloc_save_state(idmemory, vmsave);
- if ( sid == 0 )
- { ifree_object(vmsave, "zsave");
- return_error(e_VMerror);
- }
- code = zgsave(op);
- if ( code < 0 )
- return code;
- /* Cut the chain so we can't grestore past here. */
- prev = gs_state_swap_saved(igs, (gs_state *)0);
- code = zgsave(op);
- if ( code < 0 )
- return code;
- vmsave->gsave = prev;
- push(1);
- make_tav(op, t_save, 0, saveid, sid);
- return zgsave(op);
- }
-
- /* <save> restore - */
- private int restore_check_stack(P2(const ref_stack *, const alloc_save_t *));
- private void restore_fix_stack(P2(ref_stack *, const alloc_save_t *));
- int
- zrestore(register os_ptr op)
- { vm_save_t *vmsave;
- ulong sid;
- alloc_save_t *asave;
- gs_state *prev;
- check_type(*op, t_save);
- vmsave = r_ptr(op, vm_save_t);
- if ( vmsave == 0 ) /* invalidated save */
- return_error(e_invalidrestore);
- sid = op->value.saveid;
- asave = alloc_find_save(idmemory, sid);
- if ( asave == 0 )
- return_error(e_invalidrestore);
- vmsave = alloc_save_client_data(asave);
- /* Check the contents of the stacks. */
- osp--;
- { int code;
- if ( (code = restore_check_stack(&o_stack, asave)) < 0 ||
- (code = restore_check_stack(&e_stack, asave)) < 0 ||
- (code = restore_check_stack(&d_stack, asave)) < 0
- )
- { osp++;
- return code;
- }
- }
- /* Reset l_new in all stack entries if the new save level is zero. */
- restore_fix_stack(&o_stack, asave);
- restore_fix_stack(&e_stack, asave);
- restore_fix_stack(&d_stack, asave);
- /* Restore the graphics state. */
- gs_grestoreall(igs);
- prev = gs_state_swap_saved(igs, (gs_state *)0);
- gs_state_swap_saved(prev, vmsave->gsave);
- gs_state_swap_saved(igs, prev);
- gs_grestore(igs);
- gs_grestore(igs);
- /* Now it's safe to restore the state of memory. */
- alloc_restore_state(asave);
- ifree_object(vmsave, "zrestore");
- dict_set_top(); /* reload dict stack cache */
- return 0;
- }
- /* Check a stack to make sure all its elements are older than a save. */
- private int
- restore_check_stack(const ref_stack *pstack, const alloc_save_t *asave)
- { STACK_LOOP_BEGIN(pstack, bot, size)
- { const ref *stkp;
- for ( stkp = bot; size; stkp++, size-- )
- { char *ptr;
- switch ( r_type(stkp) )
- {
- case t_array:
- ptr = (char *)stkp->value.refs; break;
- case t_dictionary:
- ptr = (char *)stkp->value.pdict; break;
- /* case t_file: ****** WHAT? ****** */
- case t_name:
- /* Names are special because of how they are allocated. */
- if ( alloc_name_is_since_save(stkp, asave) )
- return_error(e_invalidrestore);
- continue;
- case t_string:
- ptr = (char *)stkp->value.bytes; break;
- case t_mixedarray: case t_shortarray:
- ptr = (char *)stkp->value.packed; break;
- case t_device:
- ptr = (char *)stkp->value.pdevice; break;
- case t_fontID:
- case t_struct:
- case t_astruct:
- ptr = (char *)stkp->value.pstruct; break;
- default:
- continue;
- }
- if ( alloc_is_since_save(ptr, asave) )
- return_error(e_invalidrestore);
- }
- }
- STACK_LOOP_END(bot, size)
- return 0; /* OK */
- }
- /*
- * If the new save level is zero, fix up the contents of a stack
- * by clearing the l_new bit in all the entries (since we can't tolerate
- * values with l_new set if the save level is zero).
- */
- private void
- restore_fix_stack(ref_stack *pstack, const alloc_save_t *asave)
- { STACK_LOOP_BEGIN(pstack, bot, size)
- { ref *stkp;
- for ( stkp = bot; size; stkp++, size-- )
- r_clear_attrs(stkp, l_new); /* always do it, no harm */
- }
- STACK_LOOP_END(bot, size)
- }
-
- /* - vmstatus <save_level> <vm_used> <vm_maximum> */
- int
- zvmstatus(register os_ptr op)
- { gs_memory_status_t mstat, dstat;
- gs_memory_status(imemory, &mstat);
- gs_memory_status(&gs_memory_default, &dstat);
- push(3);
- make_int(op - 2, alloc_save_level(idmemory));
- make_int(op - 1, mstat.used);
- make_int(op, mstat.allocated + dstat.allocated - dstat.used);
- return 0;
- }
-
- /* ------ Initialization procedure ------ */
-
- op_def zvmem_op_defs[] = {
- {"1restore", zrestore},
- {"0save", zsave},
- {"0vmstatus", zvmstatus},
- op_def_end(0)
- };
-