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