home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / program / gs300sr1 / gs300sr1.exe / IPARAM.C < prev    next >
C/C++ Source or Header  |  1994-07-27  |  17KB  |  554 lines

  1. /* Copyright (C) 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* iparam.c */
  20. /* Interpreter implementations of parameter dictionaries */
  21. #include "memory_.h"
  22. #include "string_.h"
  23. #include "ghost.h"
  24. #include "errors.h"
  25. #include "opcheck.h"
  26. #include "ialloc.h"
  27. #include "idict.h"
  28. #include "imemory.h"            /* for iutil.h */
  29. #include "iname.h"
  30. #include "istack.h"
  31. #include "iparam.h"
  32. #include "iutil.h"            /* for num_params */
  33. #include "store.h"
  34.  
  35. #define iplist ((iparam_list *)plist)
  36.  
  37. /* Generic routines for getting parameters and converting to refs. */
  38. private param_proc_xmit_null(ref_param_write_null);
  39. private param_proc_xmit_bool(ref_param_write_bool);
  40. private param_proc_xmit_int(ref_param_write_int);
  41. private param_proc_xmit_long(ref_param_write_long);
  42. private param_proc_xmit_float(ref_param_write_float);
  43. private param_proc_xmit_string(ref_param_write_string);
  44. private param_proc_xmit_name(ref_param_write_name);
  45. private param_proc_xmit_int_array(ref_param_write_int_array);
  46. private param_proc_xmit_float_array(ref_param_write_float_array);
  47. private const gs_param_list_procs ref_write_procs = {
  48.     ref_param_write_null,
  49.     ref_param_write_bool,
  50.     ref_param_write_int,
  51.     ref_param_write_long,
  52.     ref_param_write_float,
  53.     ref_param_write_string,
  54.     ref_param_write_name,
  55.     ref_param_write_int_array,
  56.     ref_param_write_float_array
  57. };
  58. private bool near ref_param_wanted(P2(const iparam_list *, gs_param_name));
  59. private int near ref_param_write(P3(iparam_list *, gs_param_name, ref *));
  60.  
  61. private int
  62. ref_param_write_null(gs_param_list *plist, gs_param_name pkey)
  63. {    ref value;
  64.     make_null(&value);
  65.     return ref_param_write(iplist, pkey, &value);
  66. }
  67. private int
  68. ref_param_write_bool(gs_param_list *plist, gs_param_name pkey, bool *pvalue)
  69. {    ref value;
  70.     make_bool(&value, *pvalue);
  71.     return ref_param_write(iplist, pkey, &value);
  72. }
  73. private int
  74. ref_param_write_int(gs_param_list *plist, gs_param_name pkey, int *pvalue)
  75. {    ref value;
  76.     make_int(&value, *pvalue);
  77.     return ref_param_write(iplist, pkey, &value);
  78. }
  79. private int
  80. ref_param_write_long(gs_param_list *plist, gs_param_name pkey, long *pvalue)
  81. {    ref value;
  82.     make_int(&value, *pvalue);
  83.     return ref_param_write(iplist, pkey, &value);
  84. }
  85. private int
  86. ref_param_write_float(gs_param_list *plist, gs_param_name pkey, float *pvalue)
  87. {    ref value;
  88.     make_real(&value, *pvalue);
  89.     return ref_param_write(iplist, pkey, &value);
  90. }
  91. private int
  92. ref_param_write_string(gs_param_list *plist, gs_param_name pkey,
  93.   gs_param_string *pvalue)
  94. {    ref value;
  95.     const byte *pdata = pvalue->data;
  96.     uint n = pvalue->size;
  97.     if ( !ref_param_wanted(iplist, pkey) )
  98.       return 0;
  99.     if ( pvalue->persistent )
  100.         make_const_string(&value, a_readonly | a_foreign, n, pdata);
  101.     else
  102.     {    byte *pstr = ialloc_bytes(n, "ref_write_string_param");
  103.         if ( pstr == 0 )
  104.             return_error(e_VMerror);
  105.         memcpy(pstr, pdata, n);
  106.         make_string(&value, a_all, n, pstr);
  107.     }
  108.     return ref_param_write(iplist, pkey, &value);
  109. }
  110. private int
  111. ref_param_write_name(gs_param_list *plist, gs_param_name pkey,
  112.   gs_param_string *pvalue)
  113. {    ref value;
  114.     int code;
  115.     if ( !ref_param_wanted(iplist, pkey) )
  116.       return 0;
  117.     code = name_ref(pvalue->data, pvalue->size, &value,
  118.             (pvalue->persistent ? 0 : 1));
  119.     if ( code < 0 )
  120.         return code;
  121.     return ref_param_write(iplist, pkey, &value);
  122. }
  123. private int
  124. ref_param_write_int_array(gs_param_list *plist, gs_param_name pkey,
  125.   gs_param_int_array *pvalue)
  126. {    ref value;
  127.     const int *pdata = pvalue->data;
  128.     uint n = pvalue->size;
  129.     ref *pe;
  130.     int code;
  131.     if ( !ref_param_wanted(iplist, pkey) )
  132.       return 0;
  133.     code = ialloc_ref_array(&value, a_all, n,
  134.                 "ref_write_int_array_param");
  135.     if ( code < 0 )
  136.       return code;
  137.     for ( pe = value.value.refs; n > 0; n--, pe++, pdata++ )
  138.       make_int(pe, *pdata);
  139.     return ref_param_write(iplist, pkey, &value);
  140. }
  141. private int
  142. ref_param_write_float_array(gs_param_list *plist, gs_param_name pkey,
  143.   gs_param_float_array *pvalue)
  144. {    ref value;
  145.     const float *pdata = pvalue->data;
  146.     uint n = pvalue->size;
  147.     int code;
  148.     ref *pe;
  149.     if ( !ref_param_wanted(iplist, pkey) )
  150.       return 0;
  151.     code = ialloc_ref_array(&value, a_all, n,
  152.                 "ref_write_float_array_param");
  153.     if ( code < 0 )
  154.       return code;
  155.     for ( pe = value.value.refs; n > 0; n--, pe++, pdata++ )
  156.       make_real(pe, *pdata);
  157.     return ref_param_write(iplist, pkey, &value);
  158. }
  159. /* Check whether a given parameter is wanted. */
  160. private bool near
  161. ref_param_wanted(const iparam_list *plist, gs_param_name pkey)
  162. {    ref *ignore_value;
  163.     return !(r_has_type(&plist->u.w.wanted, t_dictionary) &&
  164.          dict_find_string(&plist->u.w.wanted, pkey, &ignore_value) <= 0);
  165. }
  166. /* Generic routine for writing a ref parameter. */
  167. private int near
  168. ref_param_write(iparam_list *plist, gs_param_name pkey, ref *pvalue)
  169. {    ref nref;
  170.     int code;
  171.     if ( !ref_param_wanted(plist, pkey) )
  172.       return 0;
  173.     code = name_ref((const byte *)pkey, strlen(pkey), &nref, 0);
  174.     if ( code < 0 )
  175.       return code;
  176.     return (*plist->u.w.write)(plist, &nref, pvalue);
  177. }
  178. /* Initialize for writing parameters. */
  179. private void near
  180. ref_param_write_init(iparam_list *plist, const ref *pwanted)
  181. {    if ( pwanted == 0 )
  182.       make_null(&plist->u.w.wanted);
  183.     else
  184.       plist->u.w.wanted = *pwanted;
  185.     plist->results = 0;
  186. }
  187. /* Implementation for getting parameters to a stack. */
  188. private int
  189. stack_param_write(iparam_list *plist, const ref *pkey, ref *pvalue)
  190. {
  191. #define splist ((stack_param_list *)plist)
  192.     ref_stack *pstack = splist->pstack;
  193.     s_ptr p = pstack->p;
  194.     if ( pstack->top - p < 2 )
  195.       { int code = ref_stack_push(pstack, 2);
  196.         if ( code < 0 )
  197.           return code;
  198.         *ref_stack_index(pstack, 1) = *pkey;
  199.         p = pstack->p;
  200.       }
  201.     else
  202.       { pstack->p = p += 2;
  203.         p[-1] = *pkey;
  204.       }
  205.     *p = *pvalue;
  206.     splist->count++;
  207. #undef splist
  208.     return 0;
  209. }
  210. int
  211. stack_param_list_write(stack_param_list *plist, ref_stack *pstack,
  212.   const ref *pwanted)
  213. {    plist->procs = &ref_write_procs;
  214.     plist->u.w.write = stack_param_write;
  215.     ref_param_write_init((iparam_list *)plist, pwanted);
  216.     plist->pstack = pstack;
  217.     /* plist->skip not used */
  218.     plist->count = 0;
  219.     return 0;
  220. }    
  221. /* Implementation for getting parameters to a dictionary. */
  222. private int
  223. dict_param_write(iparam_list *plist, const ref *pkey, ref *pvalue)
  224. {    return dict_put(&((dict_param_list *)plist)->dict, pkey, pvalue);
  225. }
  226. int
  227. dict_param_list_write(dict_param_list *plist, ref *pdict,
  228.   const ref *pwanted)
  229. {    check_dict_write(*pdict);
  230.     plist->procs = &ref_write_procs;
  231.     plist->u.w.write = dict_param_write;
  232.     ref_param_write_init((iparam_list *)plist, pwanted);
  233.     plist->dict = *pdict;
  234.     return 0;
  235. }    
  236.  
  237. /* Generic routine for putting parameters converted from refs. */
  238. private param_proc_xmit_null(ref_param_read_null);
  239. private param_proc_xmit_bool(ref_param_read_bool);
  240. private param_proc_xmit_int(ref_param_read_int);
  241. private param_proc_xmit_long(ref_param_read_long);
  242. private param_proc_xmit_float(ref_param_read_float);
  243. private param_proc_xmit_string(ref_param_read_string);
  244. private param_proc_xmit_int_array(ref_param_read_int_array);
  245. private param_proc_xmit_float_array(ref_param_read_float_array);
  246. private param_proc_get_policy(ref_param_read_get_policy);
  247. private param_proc_signal_error(ref_param_read_signal_error);
  248. private const gs_param_list_procs ref_read_procs = {
  249.     ref_param_read_null,
  250.     ref_param_read_bool,
  251.     ref_param_read_int,
  252.     ref_param_read_long,
  253.     ref_param_read_float,
  254.     ref_param_read_string,
  255.     ref_param_read_string,        /* name = string */
  256.     ref_param_read_int_array,
  257.     ref_param_read_float_array,
  258.     ref_param_read_get_policy,
  259.     ref_param_read_signal_error
  260. };
  261. private int near ref_param_read(P3(iparam_list *, gs_param_name,
  262.   iparam_loc *));
  263. #define iparam_return_error(loc, code)\
  264.   return_error(*(loc).presult = code)
  265. #define iparam_check_type(loc, typ)\
  266.   if ( !r_has_type((loc).pvalue, typ) )\
  267.     iparam_return_error(loc, e_typecheck)
  268. #define iparam_check_read(loc)\
  269.   if ( !r_has_attr((loc).pvalue, a_read) )\
  270.     iparam_return_error(loc, e_invalidaccess)
  271.  
  272. private int
  273. ref_param_read_null(gs_param_list *plist, gs_param_name pkey)
  274. {    iparam_loc loc;
  275.     int code = ref_param_read(iplist, pkey, &loc);
  276.     if ( code != 0 )
  277.         return code;
  278.     iparam_check_type(loc, t_null);
  279.     return 0;
  280. }
  281. private int
  282. ref_param_read_bool(gs_param_list *plist, gs_param_name pkey, bool *pvalue)
  283. {    iparam_loc loc;
  284.     int code = ref_param_read(iplist, pkey, &loc);
  285.     if ( code != 0 )
  286.         return code;
  287.     iparam_check_type(loc, t_boolean);
  288.     *pvalue = loc.pvalue->value.boolval;
  289.     return 0;
  290. }
  291. private int
  292. ref_param_read_int(gs_param_list *plist, gs_param_name pkey, int *pvalue)
  293. {    iparam_loc loc;
  294.     int code = ref_param_read(iplist, pkey, &loc);
  295.     if ( code != 0 )
  296.         return code;
  297.     iparam_check_type(loc, t_integer);
  298. #if arch_sizeof_int < arch_sizeof_long
  299.     if ( loc.pvalue->value.intval != (int)loc.pvalue->value.intval )
  300.         return_error(e_rangecheck);
  301. #endif
  302.     *pvalue = (int)loc.pvalue->value.intval;
  303.     return 0;
  304. }
  305. private int
  306. ref_param_read_long(gs_param_list *plist, gs_param_name pkey, long *pvalue)
  307. {    iparam_loc loc;
  308.     int code = ref_param_read(iplist, pkey, &loc);
  309.     if ( code != 0 )
  310.         return code;
  311.     iparam_check_type(loc, t_integer);
  312.     *pvalue = loc.pvalue->value.intval;
  313.     return 0;
  314. }
  315. private int
  316. ref_param_read_float(gs_param_list *plist, gs_param_name pkey, float *pvalue)
  317. {    iparam_loc loc;
  318.     int code = ref_param_read(iplist, pkey, &loc);
  319.     if ( code != 0 )
  320.         return code;
  321.     switch ( r_type(loc.pvalue) )
  322.     {
  323.     case t_integer:
  324.         *pvalue = loc.pvalue->value.intval;
  325.         break;
  326.     case t_real:
  327.         *pvalue = loc.pvalue->value.realval;
  328.         break;
  329.     default:
  330.         iparam_return_error(loc, e_typecheck);
  331.     }
  332.     return 0;
  333. }
  334. private int
  335. ref_param_read_string(gs_param_list *plist, gs_param_name pkey,
  336.   gs_param_string *pvalue)
  337. {    iparam_loc loc;
  338.     ref nref;
  339.     int code = ref_param_read(iplist, pkey, &loc);
  340.     if ( code != 0 )
  341.         return code;
  342.     switch ( r_type(loc.pvalue) )
  343.     {
  344.     case t_name:
  345.         name_string_ref(loc.pvalue, &nref);
  346.         loc.pvalue = &nref;
  347.         pvalue->persistent = true;
  348.         goto s;
  349.     case t_string:
  350.         iparam_check_read(loc);
  351.         pvalue->persistent = false;
  352. s:        pvalue->data = loc.pvalue->value.const_bytes;
  353.         pvalue->size = r_size(loc.pvalue);
  354.         break;
  355.     default:
  356.         iparam_return_error(loc, e_typecheck);
  357.     }
  358.     return 0;
  359. }
  360. private int
  361. ref_param_read_int_array(gs_param_list *plist, gs_param_name pkey,
  362.   gs_param_int_array *pvalue)
  363. {    iparam_loc loc;
  364.     int code = ref_param_read(iplist, pkey, &loc);
  365.     int *piv;
  366.     uint size;
  367.     uint i;
  368.     if ( code != 0 )
  369.         return code;
  370.     if ( !r_is_array(loc.pvalue) )
  371.         iparam_return_error(loc, e_typecheck);
  372.     iparam_check_read(loc);
  373.     size = r_size(loc.pvalue);
  374.     piv = (int *)ialloc_byte_array(size, sizeof(int),
  375.                        "ref_read_int_array_param");
  376.     if ( piv == 0 )
  377.         return_error(e_VMerror);
  378.     for ( i = 0; i < size; i++ )
  379.     {    const ref *pe = loc.pvalue->value.const_refs + i;
  380.         if ( !r_has_type(pe, t_integer) )
  381.             iparam_return_error(loc, e_typecheck);
  382. #if arch_sizeof_int < arch_sizeof_long
  383.         if ( pe->value.intval != (int)pe->value.intval )
  384.             iparam_return_error(loc, e_rangecheck);
  385. #endif
  386.         piv[i] = (int)pe->value.intval;
  387.     }
  388.     pvalue->data = piv;
  389.     pvalue->size = size;
  390.     pvalue->persistent = true;
  391.     return 0;
  392. }
  393. private int
  394. ref_param_read_float_array(gs_param_list *plist, gs_param_name pkey,
  395.   gs_param_float_array *pvalue)
  396. {    iparam_loc loc;
  397.     int code = ref_param_read(iplist, pkey, &loc);
  398.     float *pfv;
  399.     uint size;
  400.     if ( code != 0 )
  401.         return code;
  402.     if ( !r_is_array(loc.pvalue) )
  403.         return_error(e_typecheck);
  404.     iparam_check_read(loc);
  405.     size = r_size(loc.pvalue);
  406.     pfv = (float *)ialloc_byte_array(size, sizeof(float),
  407.                      "ref_read_float_array_param");
  408.     if ( pfv == 0 )
  409.         return_error(e_VMerror);
  410.     code = num_params(loc.pvalue->value.const_refs + size - 1, size, pfv);
  411.     if ( code < 0 )
  412.     {    ifree_object(pfv, "ref_read_float_array_param");
  413.         return (*loc.presult = code);
  414.     }
  415.     pvalue->data = pfv;
  416.     pvalue->size = size;
  417.     pvalue->persistent = true;
  418.     return 0;
  419. }
  420. private int
  421. ref_param_read_get_policy(gs_param_list *plist, gs_param_name pkey)
  422. {    ref *pvalue;
  423.     if ( !(r_has_type(&iplist->u.r.policies, t_dictionary) &&
  424.            dict_find_string(&iplist->u.r.policies, pkey, &pvalue) <= 0 &&
  425.            r_has_type(pvalue, t_integer))
  426.        )
  427.       return gs_policy_ignore;
  428.     return (int)pvalue->value.intval;
  429. }
  430. private int
  431. ref_param_read_signal_error(gs_param_list *plist, gs_param_name pkey, int code)
  432. {    iparam_loc loc;
  433.     ref_param_read(iplist, pkey, &loc);    /* can't fail */
  434.     *loc.presult = code;
  435.     switch ( ref_param_read_get_policy(plist, pkey) )
  436.       {
  437.       case gs_policy_ignore:
  438.         return 0;
  439.       case gs_policy_consult_user:
  440.         return_error(e_configurationerror);
  441.       default:
  442.         return code;
  443.       }
  444. }
  445. /* Generic routine for reading a ref parameter. */
  446. private int near
  447. ref_param_read(iparam_list *plist, gs_param_name pkey, iparam_loc *ploc)
  448. {    ref nref;
  449.     int code = name_ref((const byte *)pkey, strlen(pkey), &nref, 0);
  450.     if ( code < 0 )
  451.         return code;
  452.     return (*plist->u.r.read)(iplist, &nref, ploc);
  453. }
  454. /* Initialize for reading parameters. */
  455. private int
  456. ref_param_read_init(iparam_list *plist, uint count, const ref *ppolicies)
  457. {    if ( ppolicies == 0 )
  458.       make_null(&plist->u.r.policies);
  459.     else
  460.       plist->u.r.policies = *ppolicies;
  461.     plist->count = count;
  462.     plist->results =
  463.       (int *)ialloc_byte_array(count, sizeof(int), "ref_param_read_init");
  464.     if ( plist->results == 0 )
  465.       return_error(e_VMerror);
  466.     memset(plist->results, 0, count * sizeof(int));
  467.     return 0;
  468. }
  469. /* Implementation for putting parameters from an array. */
  470. private int
  471. array_param_read(iparam_list *plist, const ref *pkey, iparam_loc *ploc)
  472. {    ref *bot = ((array_param_list *)plist)->bot;
  473.     ref *ptr = bot;
  474.     ref *top = ((array_param_list *)plist)->top;
  475.     for ( ; ptr < top; ptr += 2 )
  476.     {    if ( r_has_type(ptr, t_name) && name_eq(ptr, pkey) )
  477.         {    ploc->pvalue = ptr + 1;
  478.             ploc->presult = &plist->results[ptr - bot];
  479.             *ploc->presult = 1;
  480.             return 0;
  481.         }
  482.     }
  483.     return 1;
  484. }
  485. int
  486. array_param_list_read(array_param_list *plist, ref *bot, uint count,
  487.   const ref *ppolicies)
  488. {    if ( count & 1 )
  489.         return_error(e_rangecheck);
  490.     plist->procs = &ref_read_procs;
  491.     plist->u.r.read = array_param_read;
  492.     plist->bot = bot;
  493.     plist->top = bot + count;
  494.     return ref_param_read_init(iplist, count, ppolicies);
  495. }
  496. /* Implementation for putting parameters from a stack. */
  497. private int
  498. stack_param_read(iparam_list *plist, const ref *pkey, iparam_loc *ploc)
  499. {
  500. #define splist ((stack_param_list *)plist)
  501.     ref_stack *pstack = splist->pstack;
  502.     /* This implementation is slow, but it probably doesn't matter. */
  503.     uint index = splist->skip + 1;
  504.     uint count = splist->count;
  505.     for ( ; count; count--, index += 2 )
  506.       {    const ref *p = ref_stack_index(pstack, index);
  507.         if ( r_has_type(p, t_name) && name_eq(p, pkey) )
  508.           {    ploc->pvalue = ref_stack_index(pstack, index - 1);
  509.             ploc->presult = &plist->results[count - 1];
  510.             *ploc->presult = 1;
  511.             return 0;
  512.           }
  513.       }
  514. #undef splist
  515.     return 1;
  516. }
  517. int
  518. stack_param_list_read(stack_param_list *plist, ref_stack *pstack, uint skip,
  519.   const ref *ppolicies)
  520. {    uint count = ref_stack_counttomark(pstack);
  521.     if ( count == 0 )
  522.         return_error(e_unmatchedmark);
  523.     count -= skip + 1;
  524.     if ( count & 1 )
  525.         return_error(e_rangecheck);
  526.     plist->procs = &ref_read_procs;
  527.     plist->u.r.read = stack_param_read;
  528.     plist->pstack = pstack;
  529.     plist->skip = skip;
  530.     return ref_param_read_init(iplist, count >> 1, ppolicies);
  531. }    
  532. /* Implementation for putting parameters from a dictionary. */
  533. private int
  534. dict_param_read(iparam_list *plist, const ref *pkey, iparam_loc *ploc)
  535. {
  536. #define spdict (&((dict_param_list *)plist)->dict)
  537.     int code = dict_find(spdict, pkey, &ploc->pvalue);
  538.     if ( code != 1 )
  539.         return 1;
  540.     ploc->presult = &plist->results[dict_value_index(spdict, ploc->pvalue)];
  541. #undef spdict
  542.     *ploc->presult = 1;
  543.     return 0;
  544. }
  545. int
  546. dict_param_list_read(dict_param_list *plist, const ref *pdict,
  547.   const ref *ppolicies)
  548. {    check_dict_read(*pdict);
  549.     plist->procs = &ref_read_procs;
  550.     plist->u.r.read = dict_param_read;
  551.     plist->dict = *pdict;
  552.     return ref_param_read_init(iplist, dict_maxlength(pdict), ppolicies);
  553. }    
  554.