xref: /plan9/sys/src/cmd/gs/src/zmisc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1*593dc095SDavid du Colombier /* Copyright (C) 1989, 1995-2004 artofcode LLC. All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: zmisc.c,v 1.7 2004/08/04 19:36:13 stefan Exp $ */
187dd7cddfSDavid du Colombier /* Miscellaneous operators */
19*593dc095SDavid du Colombier 
207dd7cddfSDavid du Colombier #include "errno_.h"
217dd7cddfSDavid du Colombier #include "memory_.h"
227dd7cddfSDavid du Colombier #include "string_.h"
237dd7cddfSDavid du Colombier #include "ghost.h"
247dd7cddfSDavid du Colombier #include "gscdefs.h"		/* for gs_serialnumber */
257dd7cddfSDavid du Colombier #include "gp.h"
267dd7cddfSDavid du Colombier #include "oper.h"
277dd7cddfSDavid du Colombier #include "ialloc.h"
287dd7cddfSDavid du Colombier #include "idict.h"
297dd7cddfSDavid du Colombier #include "dstack.h"		/* for name lookup in bind */
307dd7cddfSDavid du Colombier #include "iname.h"
317dd7cddfSDavid du Colombier #include "ipacked.h"
327dd7cddfSDavid du Colombier #include "ivmspace.h"
337dd7cddfSDavid du Colombier #include "store.h"
347dd7cddfSDavid du Colombier 
357dd7cddfSDavid du Colombier /* <proc> bind <proc> */
367dd7cddfSDavid du Colombier inline private bool
r_is_ex_oper(const ref * rp)377dd7cddfSDavid du Colombier r_is_ex_oper(const ref *rp)
387dd7cddfSDavid du Colombier {
397dd7cddfSDavid du Colombier     return (r_has_attr(rp, a_executable) &&
407dd7cddfSDavid du Colombier 	    (r_btype(rp) == t_operator || r_type(rp) == t_oparray));
417dd7cddfSDavid du Colombier }
427dd7cddfSDavid du Colombier private int
zbind(i_ctx_t * i_ctx_p)437dd7cddfSDavid du Colombier zbind(i_ctx_t *i_ctx_p)
447dd7cddfSDavid du Colombier {
457dd7cddfSDavid du Colombier     os_ptr op = osp;
467dd7cddfSDavid du Colombier     uint depth = 1;
477dd7cddfSDavid du Colombier     ref defn;
487dd7cddfSDavid du Colombier     register os_ptr bsp;
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier     switch (r_type(op)) {
517dd7cddfSDavid du Colombier 	case t_array:
527dd7cddfSDavid du Colombier 	case t_mixedarray:
537dd7cddfSDavid du Colombier 	case t_shortarray:
547dd7cddfSDavid du Colombier 	    defn = *op;
557dd7cddfSDavid du Colombier 	    break;
567dd7cddfSDavid du Colombier 	case t_oparray:
577dd7cddfSDavid du Colombier 	    defn = *op->value.const_refs;
587dd7cddfSDavid du Colombier 	    break;
597dd7cddfSDavid du Colombier 	default:
607dd7cddfSDavid du Colombier 	    return_op_typecheck(op);
617dd7cddfSDavid du Colombier     }
627dd7cddfSDavid du Colombier     push(1);
637dd7cddfSDavid du Colombier     *op = defn;
647dd7cddfSDavid du Colombier     bsp = op;
657dd7cddfSDavid du Colombier     /*
667dd7cddfSDavid du Colombier      * We must not make the top-level procedure read-only,
677dd7cddfSDavid du Colombier      * but we must bind it even if it is read-only already.
687dd7cddfSDavid du Colombier      *
697dd7cddfSDavid du Colombier      * Here are the invariants for the following loop:
707dd7cddfSDavid du Colombier      *      `depth' elements have been pushed on the ostack;
717dd7cddfSDavid du Colombier      *      For i < depth, p = ref_stack_index(&o_stack, i):
727dd7cddfSDavid du Colombier      *        *p is an array (or packedarray) ref.
737dd7cddfSDavid du Colombier      */
747dd7cddfSDavid du Colombier     while (depth) {
757dd7cddfSDavid du Colombier 	while (r_size(bsp)) {
767dd7cddfSDavid du Colombier 	    ref_packed *const tpp = (ref_packed *)bsp->value.packed; /* break const */
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier 	    r_dec_size(bsp, 1);
797dd7cddfSDavid du Colombier 	    if (r_is_packed(tpp)) {
807dd7cddfSDavid du Colombier 		/* Check for a packed executable name */
817dd7cddfSDavid du Colombier 		ushort elt = *tpp;
827dd7cddfSDavid du Colombier 
837dd7cddfSDavid du Colombier 		if (r_packed_is_exec_name(&elt)) {
847dd7cddfSDavid du Colombier 		    ref nref;
857dd7cddfSDavid du Colombier 		    ref *pvalue;
867dd7cddfSDavid du Colombier 
87*593dc095SDavid du Colombier 		    name_index_ref(imemory, packed_name_index(&elt),
887dd7cddfSDavid du Colombier 				   &nref);
897dd7cddfSDavid du Colombier 		    if ((pvalue = dict_find_name(&nref)) != 0 &&
907dd7cddfSDavid du Colombier 			r_is_ex_oper(pvalue)
917dd7cddfSDavid du Colombier 			) {
927dd7cddfSDavid du Colombier 			store_check_dest(bsp, pvalue);
937dd7cddfSDavid du Colombier 			/*
947dd7cddfSDavid du Colombier 			 * Always save the change, since this can only
957dd7cddfSDavid du Colombier 			 * happen once.
967dd7cddfSDavid du Colombier 			 */
977dd7cddfSDavid du Colombier 			ref_do_save(bsp, tpp, "bind");
987dd7cddfSDavid du Colombier 			*tpp = pt_tag(pt_executable_operator) +
997dd7cddfSDavid du Colombier 			    op_index(pvalue);
1007dd7cddfSDavid du Colombier 		    }
1017dd7cddfSDavid du Colombier 		}
1027dd7cddfSDavid du Colombier 		bsp->value.packed = tpp + 1;
1037dd7cddfSDavid du Colombier 	    } else {
1047dd7cddfSDavid du Colombier 		ref *const tp = bsp->value.refs++;
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier 		switch (r_type(tp)) {
1077dd7cddfSDavid du Colombier 		    case t_name:	/* bind the name if an operator */
1087dd7cddfSDavid du Colombier 			if (r_has_attr(tp, a_executable)) {
1097dd7cddfSDavid du Colombier 			    ref *pvalue;
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier 			    if ((pvalue = dict_find_name(tp)) != 0 &&
1127dd7cddfSDavid du Colombier 				r_is_ex_oper(pvalue)
1137dd7cddfSDavid du Colombier 				) {
1147dd7cddfSDavid du Colombier 				store_check_dest(bsp, pvalue);
1157dd7cddfSDavid du Colombier 				ref_assign_old(bsp, tp, pvalue, "bind");
1167dd7cddfSDavid du Colombier 			    }
1177dd7cddfSDavid du Colombier 			}
1187dd7cddfSDavid du Colombier 			break;
1197dd7cddfSDavid du Colombier 		    case t_array:	/* push into array if writable */
1207dd7cddfSDavid du Colombier 			if (!r_has_attr(tp, a_write))
1217dd7cddfSDavid du Colombier 			    break;
1227dd7cddfSDavid du Colombier 		    case t_mixedarray:
1237dd7cddfSDavid du Colombier 		    case t_shortarray:
1247dd7cddfSDavid du Colombier 			if (r_has_attr(tp, a_executable)) {
1257dd7cddfSDavid du Colombier 			    /* Make reference read-only */
1267dd7cddfSDavid du Colombier 			    r_clear_attrs(tp, a_write);
1277dd7cddfSDavid du Colombier 			    if (bsp >= ostop) {
1287dd7cddfSDavid du Colombier 				/* Push a new stack block. */
1297dd7cddfSDavid du Colombier 				ref temp;
1307dd7cddfSDavid du Colombier 				int code;
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier 				temp = *tp;
1337dd7cddfSDavid du Colombier 				osp = bsp;
1347dd7cddfSDavid du Colombier 				code = ref_stack_push(&o_stack, 1);
1357dd7cddfSDavid du Colombier 				if (code < 0) {
1367dd7cddfSDavid du Colombier 				    ref_stack_pop(&o_stack, depth);
1377dd7cddfSDavid du Colombier 				    return_error(code);
1387dd7cddfSDavid du Colombier 				}
1397dd7cddfSDavid du Colombier 				bsp = osp;
1407dd7cddfSDavid du Colombier 				*bsp = temp;
1417dd7cddfSDavid du Colombier 			    } else
1427dd7cddfSDavid du Colombier 				*++bsp = *tp;
1437dd7cddfSDavid du Colombier 			    depth++;
1447dd7cddfSDavid du Colombier 			}
1457dd7cddfSDavid du Colombier 		}
1467dd7cddfSDavid du Colombier 	    }
1477dd7cddfSDavid du Colombier 	}
1487dd7cddfSDavid du Colombier 	bsp--;
1497dd7cddfSDavid du Colombier 	depth--;
1507dd7cddfSDavid du Colombier 	if (bsp < osbot) {	/* Pop back to the previous stack block. */
1517dd7cddfSDavid du Colombier 	    osp = bsp;
1527dd7cddfSDavid du Colombier 	    ref_stack_pop_block(&o_stack);
1537dd7cddfSDavid du Colombier 	    bsp = osp;
1547dd7cddfSDavid du Colombier 	}
1557dd7cddfSDavid du Colombier     }
1567dd7cddfSDavid du Colombier     osp = bsp;
1577dd7cddfSDavid du Colombier     return 0;
1587dd7cddfSDavid du Colombier }
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier /* - serialnumber <int> */
1617dd7cddfSDavid du Colombier private int
zserialnumber(i_ctx_t * i_ctx_p)1627dd7cddfSDavid du Colombier zserialnumber(i_ctx_t *i_ctx_p)
1637dd7cddfSDavid du Colombier {
1647dd7cddfSDavid du Colombier     os_ptr op = osp;
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier     push(1);
1677dd7cddfSDavid du Colombier     make_int(op, gs_serialnumber);
1687dd7cddfSDavid du Colombier     return 0;
1697dd7cddfSDavid du Colombier }
1707dd7cddfSDavid du Colombier 
171*593dc095SDavid du Colombier /* some FTS tests work better if realtime starts from 0 at boot time */
172*593dc095SDavid du Colombier private long    real_time_0[2];
173*593dc095SDavid du Colombier 
174*593dc095SDavid du Colombier private int
zmisc_init_realtime(i_ctx_t * i_ctx_p)175*593dc095SDavid du Colombier zmisc_init_realtime(i_ctx_t * i_ctx_p)
176*593dc095SDavid du Colombier {
177*593dc095SDavid du Colombier     gp_get_realtime(real_time_0);
178*593dc095SDavid du Colombier     return 0;
179*593dc095SDavid du Colombier }
180*593dc095SDavid du Colombier 
1817dd7cddfSDavid du Colombier /* - realtime <int> */
1827dd7cddfSDavid du Colombier private int
zrealtime(i_ctx_t * i_ctx_p)1837dd7cddfSDavid du Colombier zrealtime(i_ctx_t *i_ctx_p)
1847dd7cddfSDavid du Colombier {
1857dd7cddfSDavid du Colombier     os_ptr op = osp;
1867dd7cddfSDavid du Colombier     long secs_ns[2];
1877dd7cddfSDavid du Colombier 
1887dd7cddfSDavid du Colombier     gp_get_realtime(secs_ns);
189*593dc095SDavid du Colombier     secs_ns[1] -= real_time_0[1];
190*593dc095SDavid du Colombier     secs_ns[0] -= real_time_0[0];
1917dd7cddfSDavid du Colombier     push(1);
1927dd7cddfSDavid du Colombier     make_int(op, secs_ns[0] * 1000 + secs_ns[1] / 1000000);
1937dd7cddfSDavid du Colombier     return 0;
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier 
1967dd7cddfSDavid du Colombier /* - usertime <int> */
1977dd7cddfSDavid du Colombier private int
zusertime(i_ctx_t * i_ctx_p)1987dd7cddfSDavid du Colombier zusertime(i_ctx_t *i_ctx_p)
1997dd7cddfSDavid du Colombier {
2007dd7cddfSDavid du Colombier     os_ptr op = osp;
2017dd7cddfSDavid du Colombier     long secs_ns[2];
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier     gp_get_usertime(secs_ns);
2047dd7cddfSDavid du Colombier     push(1);
2057dd7cddfSDavid du Colombier     make_int(op, secs_ns[0] * 1000 + secs_ns[1] / 1000000);
2067dd7cddfSDavid du Colombier     return 0;
2077dd7cddfSDavid du Colombier }
2087dd7cddfSDavid du Colombier 
2097dd7cddfSDavid du Colombier /* ---------------- Non-standard operators ---------------- */
2107dd7cddfSDavid du Colombier 
2117dd7cddfSDavid du Colombier /* <string> getenv <value_string> true */
2127dd7cddfSDavid du Colombier /* <string> getenv false */
2137dd7cddfSDavid du Colombier private int
zgetenv(i_ctx_t * i_ctx_p)2147dd7cddfSDavid du Colombier zgetenv(i_ctx_t *i_ctx_p)
2157dd7cddfSDavid du Colombier {
2167dd7cddfSDavid du Colombier     os_ptr op = osp;
2177dd7cddfSDavid du Colombier     char *str;
2187dd7cddfSDavid du Colombier     byte *value;
2197dd7cddfSDavid du Colombier     int len = 0;
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier     check_read_type(*op, t_string);
2227dd7cddfSDavid du Colombier     str = ref_to_string(op, imemory, "getenv key");
2237dd7cddfSDavid du Colombier     if (str == 0)
2247dd7cddfSDavid du Colombier 	return_error(e_VMerror);
2257dd7cddfSDavid du Colombier     if (gp_getenv(str, (char *)0, &len) > 0) {	/* key missing */
2267dd7cddfSDavid du Colombier 	ifree_string((byte *) str, r_size(op) + 1, "getenv key");
2277dd7cddfSDavid du Colombier 	make_false(op);
2287dd7cddfSDavid du Colombier 	return 0;
2297dd7cddfSDavid du Colombier     }
2307dd7cddfSDavid du Colombier     value = ialloc_string(len, "getenv value");
2317dd7cddfSDavid du Colombier     if (value == 0) {
2327dd7cddfSDavid du Colombier 	ifree_string((byte *) str, r_size(op) + 1, "getenv key");
2337dd7cddfSDavid du Colombier 	return_error(e_VMerror);
2347dd7cddfSDavid du Colombier     }
2357dd7cddfSDavid du Colombier     DISCARD(gp_getenv(str, (char *)value, &len));	/* can't fail */
2367dd7cddfSDavid du Colombier     ifree_string((byte *) str, r_size(op) + 1, "getenv key");
2377dd7cddfSDavid du Colombier     /* Delete the stupid C string terminator. */
2387dd7cddfSDavid du Colombier     value = iresize_string(value, len, len - 1,
2397dd7cddfSDavid du Colombier 			   "getenv value");	/* can't fail */
2407dd7cddfSDavid du Colombier     push(1);
2417dd7cddfSDavid du Colombier     make_string(op - 1, a_all | icurrent_space, len - 1, value);
2427dd7cddfSDavid du Colombier     make_true(op);
2437dd7cddfSDavid du Colombier     return 0;
2447dd7cddfSDavid du Colombier }
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier /* <name> <proc> .makeoperator <oper> */
2477dd7cddfSDavid du Colombier private int
zmakeoperator(i_ctx_t * i_ctx_p)2487dd7cddfSDavid du Colombier zmakeoperator(i_ctx_t *i_ctx_p)
2497dd7cddfSDavid du Colombier {
2507dd7cddfSDavid du Colombier     os_ptr op = osp;
2517dd7cddfSDavid du Colombier     op_array_table *opt;
2527dd7cddfSDavid du Colombier     uint count;
2537dd7cddfSDavid du Colombier     ref *tab;
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier     check_type(op[-1], t_name);
2567dd7cddfSDavid du Colombier     check_proc(*op);
2577dd7cddfSDavid du Colombier     switch (r_space(op)) {
2587dd7cddfSDavid du Colombier 	case avm_global:
2597dd7cddfSDavid du Colombier 	    opt = &op_array_table_global;
2607dd7cddfSDavid du Colombier 	    break;
2617dd7cddfSDavid du Colombier 	case avm_local:
2627dd7cddfSDavid du Colombier 	    opt = &op_array_table_local;
2637dd7cddfSDavid du Colombier 	    break;
2647dd7cddfSDavid du Colombier 	default:
2657dd7cddfSDavid du Colombier 	    return_error(e_invalidaccess);
2667dd7cddfSDavid du Colombier     }
2677dd7cddfSDavid du Colombier     count = opt->count;
2687dd7cddfSDavid du Colombier     tab = opt->table.value.refs;
2697dd7cddfSDavid du Colombier     /*
2707dd7cddfSDavid du Colombier      * restore doesn't reset op_array_table.count, but it does
2717dd7cddfSDavid du Colombier      * remove entries from op_array_table.table.  Since we fill
2727dd7cddfSDavid du Colombier      * the table in order, we can detect that a restore has occurred
2737dd7cddfSDavid du Colombier      * by checking whether what should be the most recent entry
2747dd7cddfSDavid du Colombier      * is occupied.  If not, we scan backwards over the vacated entries
2757dd7cddfSDavid du Colombier      * to find the true end of the table.
2767dd7cddfSDavid du Colombier      */
2777dd7cddfSDavid du Colombier     while (count > 0 && r_has_type(&tab[count - 1], t_null))
2787dd7cddfSDavid du Colombier 	--count;
2797dd7cddfSDavid du Colombier     if (count == r_size(&opt->table))
2807dd7cddfSDavid du Colombier 	return_error(e_limitcheck);
2817dd7cddfSDavid du Colombier     ref_assign_old(&opt->table, &tab[count], op, "makeoperator");
282*593dc095SDavid du Colombier     opt->nx_table[count] = name_index(imemory, op - 1);
2837dd7cddfSDavid du Colombier     op_index_ref(opt->base_index + count, op - 1);
2847dd7cddfSDavid du Colombier     opt->count = count + 1;
2857dd7cddfSDavid du Colombier     pop(1);
2867dd7cddfSDavid du Colombier     return 0;
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier 
2897dd7cddfSDavid du Colombier /* - .oserrno <int> */
2907dd7cddfSDavid du Colombier private int
zoserrno(i_ctx_t * i_ctx_p)2917dd7cddfSDavid du Colombier zoserrno(i_ctx_t *i_ctx_p)
2927dd7cddfSDavid du Colombier {
2937dd7cddfSDavid du Colombier     os_ptr op = osp;
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier     push(1);
2967dd7cddfSDavid du Colombier     make_int(op, errno);
2977dd7cddfSDavid du Colombier     return 0;
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier /* <int> .setoserrno - */
3017dd7cddfSDavid du Colombier private int
zsetoserrno(i_ctx_t * i_ctx_p)3027dd7cddfSDavid du Colombier zsetoserrno(i_ctx_t *i_ctx_p)
3037dd7cddfSDavid du Colombier {
3047dd7cddfSDavid du Colombier     os_ptr op = osp;
3057dd7cddfSDavid du Colombier 
3067dd7cddfSDavid du Colombier     check_type(*op, t_integer);
3077dd7cddfSDavid du Colombier     errno = op->value.intval;
3087dd7cddfSDavid du Colombier     pop(1);
3097dd7cddfSDavid du Colombier     return 0;
3107dd7cddfSDavid du Colombier }
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier /* <int> .oserrorstring <string> true */
3137dd7cddfSDavid du Colombier /* <int> .oserrorstring false */
3147dd7cddfSDavid du Colombier private int
zoserrorstring(i_ctx_t * i_ctx_p)3157dd7cddfSDavid du Colombier zoserrorstring(i_ctx_t *i_ctx_p)
3167dd7cddfSDavid du Colombier {
3177dd7cddfSDavid du Colombier     os_ptr op = osp;
3187dd7cddfSDavid du Colombier     const char *str;
3197dd7cddfSDavid du Colombier     int code;
3207dd7cddfSDavid du Colombier     uint len;
3217dd7cddfSDavid du Colombier     byte ch;
3227dd7cddfSDavid du Colombier 
3237dd7cddfSDavid du Colombier     check_type(*op, t_integer);
3247dd7cddfSDavid du Colombier     str = gp_strerror((int)op->value.intval);
3257dd7cddfSDavid du Colombier     if (str == 0 || (len = strlen(str)) == 0) {
3267dd7cddfSDavid du Colombier 	make_false(op);
3277dd7cddfSDavid du Colombier 	return 0;
3287dd7cddfSDavid du Colombier     }
3297dd7cddfSDavid du Colombier     check_ostack(1);
3307dd7cddfSDavid du Colombier     code = string_to_ref(str, op, iimemory, ".oserrorstring");
3317dd7cddfSDavid du Colombier     if (code < 0)
3327dd7cddfSDavid du Colombier 	return code;
3337dd7cddfSDavid du Colombier     /* Strip trailing end-of-line characters. */
3347dd7cddfSDavid du Colombier     while ((len = r_size(op)) != 0 &&
3357dd7cddfSDavid du Colombier 	   ((ch = op->value.bytes[--len]) == '\r' || ch == '\n')
3367dd7cddfSDavid du Colombier 	)
3377dd7cddfSDavid du Colombier 	r_dec_size(op, 1);
3387dd7cddfSDavid du Colombier     push(1);
3397dd7cddfSDavid du Colombier     make_true(op);
3407dd7cddfSDavid du Colombier     return 0;
3417dd7cddfSDavid du Colombier }
3427dd7cddfSDavid du Colombier 
3437dd7cddfSDavid du Colombier /* <string> <bool> .setdebug - */
3447dd7cddfSDavid du Colombier private int
zsetdebug(i_ctx_t * i_ctx_p)3457dd7cddfSDavid du Colombier zsetdebug(i_ctx_t *i_ctx_p)
3467dd7cddfSDavid du Colombier {
3477dd7cddfSDavid du Colombier     os_ptr op = osp;
3487dd7cddfSDavid du Colombier     check_read_type(op[-1], t_string);
3497dd7cddfSDavid du Colombier     check_type(*op, t_boolean);
3507dd7cddfSDavid du Colombier     {
3517dd7cddfSDavid du Colombier 	int i;
3527dd7cddfSDavid du Colombier 
3537dd7cddfSDavid du Colombier 	for (i = 0; i < r_size(op - 1); i++)
3547dd7cddfSDavid du Colombier 	    gs_debug[op[-1].value.bytes[i] & 127] =
3557dd7cddfSDavid du Colombier 		op->value.boolval;
3567dd7cddfSDavid du Colombier     }
3577dd7cddfSDavid du Colombier     pop(2);
3587dd7cddfSDavid du Colombier     return 0;
3597dd7cddfSDavid du Colombier }
3607dd7cddfSDavid du Colombier 
361*593dc095SDavid du Colombier /* ------ gs persistent cache operators ------ */
362*593dc095SDavid du Colombier /* these are for testing only. they're disabled in the normal build
363*593dc095SDavid du Colombier  * to prevent access to the cache by malicious postscript files
364*593dc095SDavid du Colombier  *
365*593dc095SDavid du Colombier  * use something like this:
366*593dc095SDavid du Colombier  *   (value) (key) .pcacheinsert
367*593dc095SDavid du Colombier  *   (key) .pcachequery { (\n) concatstrings print } if
368*593dc095SDavid du Colombier  */
369*593dc095SDavid du Colombier 
370*593dc095SDavid du Colombier #ifdef DEBUG_CACHE
371*593dc095SDavid du Colombier 
372*593dc095SDavid du Colombier /* <string> <string> .pcacheinsert */
373*593dc095SDavid du Colombier private int
zpcacheinsert(i_ctx_t * i_ctx_p)374*593dc095SDavid du Colombier zpcacheinsert(i_ctx_t *i_ctx_p)
375*593dc095SDavid du Colombier {
376*593dc095SDavid du Colombier     os_ptr op = osp;
377*593dc095SDavid du Colombier     char *key, *buffer;
378*593dc095SDavid du Colombier     int keylen, buflen;
379*593dc095SDavid du Colombier     int code = 0;
380*593dc095SDavid du Colombier 
381*593dc095SDavid du Colombier     check_read_type(*op, t_string);
382*593dc095SDavid du Colombier     keylen = r_size(op);
383*593dc095SDavid du Colombier     key = op->value.bytes;
384*593dc095SDavid du Colombier     check_read_type(*(op - 1), t_string);
385*593dc095SDavid du Colombier     buflen = r_size(op - 1);
386*593dc095SDavid du Colombier     buffer = (op - 1)->value.bytes;
387*593dc095SDavid du Colombier 
388*593dc095SDavid du Colombier     code = gp_cache_insert(0, key, keylen, buffer, buflen);
389*593dc095SDavid du Colombier     if (code < 0)
390*593dc095SDavid du Colombier 		return code;
391*593dc095SDavid du Colombier 
392*593dc095SDavid du Colombier 	pop(2);
393*593dc095SDavid du Colombier 
394*593dc095SDavid du Colombier     return code;
395*593dc095SDavid du Colombier }
396*593dc095SDavid du Colombier 
397*593dc095SDavid du Colombier /* allocation callback for query result */
398*593dc095SDavid du Colombier private void *
pcache_alloc_callback(void * userdata,int bytes)399*593dc095SDavid du Colombier pcache_alloc_callback(void *userdata, int bytes)
400*593dc095SDavid du Colombier {
401*593dc095SDavid du Colombier     i_ctx_t *i_ctx_p = (i_ctx_t*)userdata;
402*593dc095SDavid du Colombier     return ialloc_string(bytes, "pcache buffer");
403*593dc095SDavid du Colombier }
404*593dc095SDavid du Colombier 
405*593dc095SDavid du Colombier /* <string> .pcachequery <string> true */
406*593dc095SDavid du Colombier /* <string> .pcachequery false */
407*593dc095SDavid du Colombier private int
zpcachequery(i_ctx_t * i_ctx_p)408*593dc095SDavid du Colombier zpcachequery(i_ctx_t *i_ctx_p)
409*593dc095SDavid du Colombier {
410*593dc095SDavid du Colombier 	os_ptr op = osp;
411*593dc095SDavid du Colombier 	int len;
412*593dc095SDavid du Colombier 	char *key;
413*593dc095SDavid du Colombier 	byte *string;
414*593dc095SDavid du Colombier 	int code = 0;
415*593dc095SDavid du Colombier 
416*593dc095SDavid du Colombier 	check_read_type(*op, t_string);
417*593dc095SDavid du Colombier 	len = r_size(op);
418*593dc095SDavid du Colombier 	key = op->value.bytes;
419*593dc095SDavid du Colombier 	len = gp_cache_query(GP_CACHE_TYPE_TEST, key, len, (void**)&string, &pcache_alloc_callback, i_ctx_p);
420*593dc095SDavid du Colombier 	if (len < 0) {
421*593dc095SDavid du Colombier 		make_false(op);
422*593dc095SDavid du Colombier 		return 0;
423*593dc095SDavid du Colombier 	}
424*593dc095SDavid du Colombier 	if (string == NULL)
425*593dc095SDavid du Colombier 		return_error(e_VMerror);
426*593dc095SDavid du Colombier 	make_string(op, a_all | icurrent_space, len, string);
427*593dc095SDavid du Colombier 
428*593dc095SDavid du Colombier 	push(1);
429*593dc095SDavid du Colombier 	make_true(op);
430*593dc095SDavid du Colombier 
431*593dc095SDavid du Colombier 	return code;
432*593dc095SDavid du Colombier }
433*593dc095SDavid du Colombier 
434*593dc095SDavid du Colombier #endif /* DEBUG_CACHE */
435*593dc095SDavid du Colombier 
4367dd7cddfSDavid du Colombier /* ------ Initialization procedure ------ */
4377dd7cddfSDavid du Colombier 
4387dd7cddfSDavid du Colombier const op_def zmisc_op_defs[] =
4397dd7cddfSDavid du Colombier {
4407dd7cddfSDavid du Colombier     {"1bind", zbind},
4417dd7cddfSDavid du Colombier     {"1getenv", zgetenv},
4427dd7cddfSDavid du Colombier     {"2.makeoperator", zmakeoperator},
4437dd7cddfSDavid du Colombier     {"0.oserrno", zoserrno},
4447dd7cddfSDavid du Colombier     {"1.oserrorstring", zoserrorstring},
4457dd7cddfSDavid du Colombier     {"0realtime", zrealtime},
4467dd7cddfSDavid du Colombier     {"1serialnumber", zserialnumber},
4477dd7cddfSDavid du Colombier     {"2.setdebug", zsetdebug},
4487dd7cddfSDavid du Colombier     {"1.setoserrno", zsetoserrno},
4497dd7cddfSDavid du Colombier     {"0usertime", zusertime},
450*593dc095SDavid du Colombier #ifdef DEBUG_CACHE
451*593dc095SDavid du Colombier 	/* pcache test */
452*593dc095SDavid du Colombier     {"2.pcacheinsert", zpcacheinsert},
453*593dc095SDavid du Colombier     {"1.pcachequery", zpcachequery},
454*593dc095SDavid du Colombier #endif
455*593dc095SDavid du Colombier     op_def_end(zmisc_init_realtime)
4567dd7cddfSDavid du Colombier };
457