/* Copyright (C) 1996, 2000 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: zusparam.c,v 1.3.6.2.2.1 2003/01/17 00:49:06 giles Exp $ */ /* User and system parameter operators */ #include "memory_.h" #include "string_.h" #include "ghost.h" #include "oper.h" #include "gscdefs.h" #include "gsstruct.h" /* for gxht.h */ #include "gsfont.h" /* for user params */ #include "gxht.h" /* for user params */ #include "gsutil.h" #include "estack.h" #include "ialloc.h" /* for imemory for status */ #include "icontext.h" /* for set_user_params prototype */ #include "idict.h" #include "idparam.h" #include "iparam.h" #include "dstack.h" #include "iname.h" #include "itoken.h" #include "iutil2.h" #include "ivmem2.h" #include "store.h" /* The (global) font directory */ extern gs_font_dir *ifont_dir; /* in zfont.c */ /* Define an individual user or system parameter. */ /* Eventually this will be made public. */ #define param_def_common\ const char *pname typedef struct param_def_s { param_def_common; } param_def_t; typedef struct long_param_def_s { param_def_common; long min_value, max_value; long (*current)(P1(i_ctx_t *)); int (*set)(P2(i_ctx_t *, long)); } long_param_def_t; #if arch_sizeof_long > arch_sizeof_int # define MAX_UINT_PARAM max_uint #else # define MAX_UINT_PARAM max_long #endif typedef struct bool_param_def_s { param_def_common; bool (*current)(P1(i_ctx_t *)); int (*set)(P2(i_ctx_t *, bool)); } bool_param_def_t; typedef struct string_param_def_s { param_def_common; void (*current)(P2(i_ctx_t *, gs_param_string *)); int (*set)(P2(i_ctx_t *, gs_param_string *)); } string_param_def_t; /* Define a parameter set (user or system). */ typedef struct param_set_s { const long_param_def_t *long_defs; uint long_count; const bool_param_def_t *bool_defs; uint bool_count; const string_param_def_t *string_defs; uint string_count; } param_set; /* Forward references */ private int setparams(P3(i_ctx_t *, gs_param_list *, const param_set *)); private int currentparams(P2(i_ctx_t *, const param_set *)); private int currentparam1(P2(i_ctx_t *, const param_set *)); /* ------ Passwords ------ */ /* .checkpassword <0|1|2> */ private int zcheckpassword(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref params[2]; array_param_list list; gs_param_list *const plist = (gs_param_list *)&list; int result = 0; int code = name_ref((const byte *)"Password", 8, ¶ms[0], 0); password pass; if (code < 0) return code; params[1] = *op; array_param_list_read(&list, params, 2, NULL, false, iimemory); if (dict_read_password(&pass, systemdict, "StartJobPassword") >= 0 && param_check_password(plist, &pass) == 0 ) result = 1; if (dict_read_password(&pass, systemdict, "SystemParamsPassword") >= 0 && param_check_password(plist, &pass) == 0 ) result = 2; iparam_list_release(&list); make_int(op, result); return 0; } /* ------ System parameters ------ */ /* Integer values */ private long current_BuildTime(i_ctx_t *i_ctx_p) { return gs_buildtime; } private long current_MaxFontCache(i_ctx_t *i_ctx_p) { return gs_currentcachesize(ifont_dir); } private int set_MaxFontCache(i_ctx_t *i_ctx_p, long val) { return gs_setcachesize(ifont_dir, (uint)(val < 0 ? 0 : val > max_uint ? max_uint : val)); } private long current_CurFontCache(i_ctx_t *i_ctx_p) { uint cstat[7]; gs_cachestatus(ifont_dir, cstat); return cstat[0]; } private long current_MaxGlobalVM(i_ctx_t *i_ctx_p) { gs_memory_gc_status_t stat; gs_memory_gc_status(iimemory_global, &stat); return stat.max_vm; } private int set_MaxGlobalVM(i_ctx_t *i_ctx_p, long val) { gs_memory_gc_status_t stat; gs_memory_gc_status(iimemory_global, &stat); stat.max_vm = max(val, 0); gs_memory_set_gc_status(iimemory_global, &stat); return 0; } private long current_Revision(i_ctx_t *i_ctx_p) { return gs_revision; } private const long_param_def_t system_long_params[] = { {"BuildTime", min_long, max_long, current_BuildTime, NULL}, {"MaxFontCache", 0, MAX_UINT_PARAM, current_MaxFontCache, set_MaxFontCache}, {"CurFontCache", 0, MAX_UINT_PARAM, current_CurFontCache, NULL}, {"Revision", min_long, max_long, current_Revision, NULL}, /* Extensions */ {"MaxGlobalVM", 0, max_long, current_MaxGlobalVM, set_MaxGlobalVM} }; /* Boolean values */ private bool current_ByteOrder(i_ctx_t *i_ctx_p) { return !arch_is_big_endian; } private const bool_param_def_t system_bool_params[] = { {"ByteOrder", current_ByteOrder, NULL} }; /* String values */ private void current_RealFormat(i_ctx_t *i_ctx_p, gs_param_string * pval) { #if arch_floats_are_IEEE static const char *const rfs = "IEEE"; #else static const char *const rfs = "not IEEE"; #endif pval->data = (const byte *)rfs; pval->size = strlen(rfs); pval->persistent = true; } private const string_param_def_t system_string_params[] = { {"RealFormat", current_RealFormat, NULL} }; /* The system parameter set */ private const param_set system_param_set = { system_long_params, countof(system_long_params), system_bool_params, countof(system_bool_params), system_string_params, countof(system_string_params) }; /* .setsystemparams - */ private int zsetsystemparams(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; dict_param_list list; gs_param_list *const plist = (gs_param_list *)&list; password pass; check_type(*op, t_dictionary); code = dict_param_list_read(&list, op, NULL, false, iimemory); if (code < 0) return code; code = dict_read_password(&pass, systemdict, "SystemParamsPassword"); if (code < 0) return code; code = param_check_password(plist, &pass); if (code != 0) { if (code > 0) code = gs_note_error(e_invalidaccess); goto out; } code = param_read_password(plist, "StartJobPassword", &pass); switch (code) { default: /* invalid */ goto out; case 1: /* missing */ break; case 0: code = dict_write_password(&pass, systemdict, "StartJobPassword", ! i_ctx_p->LockFilePermissions); if (code < 0) goto out; } code = param_read_password(plist, "SystemParamsPassword", &pass); switch (code) { default: /* invalid */ goto out; case 1: /* missing */ break; case 0: code = dict_write_password(&pass, systemdict, "SystemParamsPassword", ! i_ctx_p->LockFilePermissions); if (code < 0) goto out; } code = setparams(i_ctx_p, plist, &system_param_set); out: iparam_list_release(&list); if (code < 0) return code; pop(1); return 0; } /* - .currentsystemparams ... */ private int zcurrentsystemparams(i_ctx_t *i_ctx_p) { return currentparams(i_ctx_p, &system_param_set); } /* .getsystemparam */ private int zgetsystemparam(i_ctx_t *i_ctx_p) { return currentparam1(i_ctx_p, &system_param_set); } /* ------ User parameters ------ */ /* Integer values */ private long current_JobTimeout(i_ctx_t *i_ctx_p) { return 0; } private int set_JobTimeout(i_ctx_t *i_ctx_p, long val) { return 0; } private long current_MaxFontItem(i_ctx_t *i_ctx_p) { return gs_currentcacheupper(ifont_dir); } private int set_MaxFontItem(i_ctx_t *i_ctx_p, long val) { return gs_setcacheupper(ifont_dir, val); } private long current_MinFontCompress(i_ctx_t *i_ctx_p) { return gs_currentcachelower(ifont_dir); } private int set_MinFontCompress(i_ctx_t *i_ctx_p, long val) { return gs_setcachelower(ifont_dir, val); } private long current_MaxOpStack(i_ctx_t *i_ctx_p) { return ref_stack_max_count(&o_stack); } private int set_MaxOpStack(i_ctx_t *i_ctx_p, long val) { return ref_stack_set_max_count(&o_stack, val); } private long current_MaxDictStack(i_ctx_t *i_ctx_p) { return ref_stack_max_count(&d_stack); } private int set_MaxDictStack(i_ctx_t *i_ctx_p, long val) { return ref_stack_set_max_count(&d_stack, val); } private long current_MaxExecStack(i_ctx_t *i_ctx_p) { return ref_stack_max_count(&e_stack); } private int set_MaxExecStack(i_ctx_t *i_ctx_p, long val) { return ref_stack_set_max_count(&e_stack, val); } private long current_MaxLocalVM(i_ctx_t *i_ctx_p) { gs_memory_gc_status_t stat; gs_memory_gc_status(iimemory_local, &stat); return stat.max_vm; } private int set_MaxLocalVM(i_ctx_t *i_ctx_p, long val) { gs_memory_gc_status_t stat; gs_memory_gc_status(iimemory_local, &stat); stat.max_vm = max(val, 0); gs_memory_set_gc_status(iimemory_local, &stat); return 0; } private long current_VMReclaim(i_ctx_t *i_ctx_p) { gs_memory_gc_status_t gstat, lstat; gs_memory_gc_status(iimemory_global, &gstat); gs_memory_gc_status(iimemory_local, &lstat); return (!gstat.enabled ? -2 : !lstat.enabled ? -1 : 0); } private long current_VMThreshold(i_ctx_t *i_ctx_p) { gs_memory_gc_status_t stat; gs_memory_gc_status(iimemory_local, &stat); return stat.vm_threshold; } private long current_WaitTimeout(i_ctx_t *i_ctx_p) { return 0; } private int set_WaitTimeout(i_ctx_t *i_ctx_p, long val) { return 0; } private long current_MinScreenLevels(i_ctx_t *i_ctx_p) { return gs_currentminscreenlevels(); } private int set_MinScreenLevels(i_ctx_t *i_ctx_p, long val) { gs_setminscreenlevels((uint) val); return 0; } private const long_param_def_t user_long_params[] = { {"JobTimeout", 0, MAX_UINT_PARAM, current_JobTimeout, set_JobTimeout}, {"MaxFontItem", 0, MAX_UINT_PARAM, current_MaxFontItem, set_MaxFontItem}, {"MinFontCompress", 0, MAX_UINT_PARAM, current_MinFontCompress, set_MinFontCompress}, {"MaxOpStack", 0, MAX_UINT_PARAM, current_MaxOpStack, set_MaxOpStack}, {"MaxDictStack", 0, MAX_UINT_PARAM, current_MaxDictStack, set_MaxDictStack}, {"MaxExecStack", 0, MAX_UINT_PARAM, current_MaxExecStack, set_MaxExecStack}, {"MaxLocalVM", 0, max_long, current_MaxLocalVM, set_MaxLocalVM}, {"VMReclaim", -2, 0, current_VMReclaim, set_vm_reclaim}, {"VMThreshold", -1, max_long, current_VMThreshold, set_vm_threshold}, {"WaitTimeout", 0, MAX_UINT_PARAM, current_WaitTimeout, set_WaitTimeout}, /* Extensions */ {"MinScreenLevels", 0, MAX_UINT_PARAM, current_MinScreenLevels, set_MinScreenLevels} }; /* Boolean values */ private bool current_AccurateScreens(i_ctx_t *i_ctx_p) { return gs_currentaccuratescreens(); } private int set_AccurateScreens(i_ctx_t *i_ctx_p, bool val) { gs_setaccuratescreens(val); return 0; } private bool current_LockFilePermissions(i_ctx_t *i_ctx_p) { return i_ctx_p->LockFilePermissions; } private int set_LockFilePermissions(i_ctx_t *i_ctx_p, bool val) { /* allow locking even if already locked */ if (i_ctx_p->LockFilePermissions && !val) return_error(e_invalidaccess); i_ctx_p->LockFilePermissions = val; return 0; } private const bool_param_def_t user_bool_params[] = { {"AccurateScreens", current_AccurateScreens, set_AccurateScreens}, {"LockFilePermissions", current_LockFilePermissions, set_LockFilePermissions} }; /* The user parameter set */ private const param_set user_param_set = { user_long_params, countof(user_long_params), user_bool_params, countof(user_bool_params), 0, 0 }; /* .setuserparams - */ /* We break this out for use when switching contexts. */ int set_user_params(i_ctx_t *i_ctx_p, const ref *paramdict) { dict_param_list list; int code; check_type(*paramdict, t_dictionary); code = dict_param_list_read(&list, paramdict, NULL, false, iimemory); if (code < 0) return code; code = setparams(i_ctx_p, (gs_param_list *)&list, &user_param_set); iparam_list_release(&list); return code; } private int zsetuserparams(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code = set_user_params(i_ctx_p, op); if (code >= 0) { /* Update cached scanner options. */ i_ctx_p->scanner_options = ztoken_scanner_options(op, i_ctx_p->scanner_options); pop(1); } return code; } /* - .currentuserparams ... */ private int zcurrentuserparams(i_ctx_t *i_ctx_p) { return currentparams(i_ctx_p, &user_param_set); } /* .getuserparam */ private int zgetuserparam(i_ctx_t *i_ctx_p) { return currentparam1(i_ctx_p, &user_param_set); } /* ------ Initialization procedure ------ */ const op_def zusparam_op_defs[] = { /* User and system parameters are accessible even in Level 1 */ /* (if this is a Level 2 system). */ {"0.currentsystemparams", zcurrentsystemparams}, {"0.currentuserparams", zcurrentuserparams}, {"1.getsystemparam", zgetsystemparam}, {"1.getuserparam", zgetuserparam}, {"1.setsystemparams", zsetsystemparams}, {"1.setuserparams", zsetuserparams}, /* The rest of the operators are defined only in Level 2. */ op_def_begin_level2(), {"1.checkpassword", zcheckpassword}, op_def_end(0) }; /* ------ Internal procedures ------ */ /* Set the values of a parameter set from a parameter list. */ /* We don't attempt to back out if anything fails. */ private int setparams(i_ctx_t *i_ctx_p, gs_param_list * plist, const param_set * pset) { int i, code; for (i = 0; i < pset->long_count; i++) { const long_param_def_t *pdef = &pset->long_defs[i]; long val; if (pdef->set == NULL) continue; code = param_read_long(plist, pdef->pname, &val); switch (code) { default: /* invalid */ return code; case 1: /* missing */ break; case 0: if (val < pdef->min_value || val > pdef->max_value) return_error(e_rangecheck); code = (*pdef->set)(i_ctx_p, val); if (code < 0) return code; } } for (i = 0; i < pset->bool_count; i++) { const bool_param_def_t *pdef = &pset->bool_defs[i]; bool val; if (pdef->set == NULL) continue; code = param_read_bool(plist, pdef->pname, &val); if (code == 0) code = (*pdef->set)(i_ctx_p, val); if (code < 0) return code; } /****** WE SHOULD DO STRINGS AND STRING ARRAYS, BUT WE DON'T YET ******/ return 0; } /* Get the current values of a parameter set to the stack. */ private bool pname_matches(const char *pname, const ref * psref) { return (psref == 0 || !bytes_compare((const byte *)pname, strlen(pname), psref->value.const_bytes, r_size(psref))); } private int current_param_list(i_ctx_t *i_ctx_p, const param_set * pset, const ref * psref /*t_string */ ) { stack_param_list list; gs_param_list *const plist = (gs_param_list *)&list; int i; stack_param_list_write(&list, &o_stack, NULL, iimemory); for (i = 0; i < pset->long_count; i++) { const char *pname = pset->long_defs[i].pname; if (pname_matches(pname, psref)) { long val = (*pset->long_defs[i].current)(i_ctx_p); int code = param_write_long(plist, pname, &val); if (code < 0) return code; } } for (i = 0; i < pset->bool_count; i++) { const char *pname = pset->bool_defs[i].pname; if (pname_matches(pname, psref)) { bool val = (*pset->bool_defs[i].current)(i_ctx_p); int code = param_write_bool(plist, pname, &val); if (code < 0) return code; } } for (i = 0; i < pset->string_count; i++) { const char *pname = pset->string_defs[i].pname; if (pname_matches(pname, psref)) { gs_param_string val; int code; (*pset->string_defs[i].current)(i_ctx_p, &val); code = param_write_string(plist, pname, &val); if (code < 0) return code; } } return 0; } /* Get the current values of a parameter set to the stack. */ private int currentparams(i_ctx_t *i_ctx_p, const param_set * pset) { return current_param_list(i_ctx_p, pset, NULL); } /* Get the value of a single parameter to the stack, or signal an error. */ private int currentparam1(i_ctx_t *i_ctx_p, const param_set * pset) { os_ptr op = osp; ref sref; int code; check_type(*op, t_name); check_ostack(2); name_string_ref((const ref *)op, &sref); code = current_param_list(i_ctx_p, pset, &sref); if (code < 0) return code; if (osp == op) return_error(e_undefined); /* We know osp == op + 2. */ ref_assign(op, op + 2); pop(2); return code; }