home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / iutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  22.7 KB  |  869 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: iutil.c,v 1.2 2000/09/19 19:00:46 lpd Exp $ */
  20. /* Utilities for Ghostscript interpreter */
  21. #include "math_.h"        /* for fabs */
  22. #include "memory_.h"
  23. #include "string_.h"
  24. #include "ghost.h"
  25. #include "errors.h"
  26. #include "gsccode.h"        /* for gxfont.h */
  27. #include "gsmatrix.h"
  28. #include "gsutil.h"
  29. #include "gxfont.h"
  30. #include "strimpl.h"
  31. #include "sstring.h"
  32. #include "idict.h"
  33. #include "imemory.h"
  34. #include "iname.h"
  35. #include "ipacked.h"        /* for array_get */
  36. #include "iutil.h"        /* for checking prototypes */
  37. #include "ivmspace.h"
  38. #include "oper.h"
  39. #include "store.h"
  40.  
  41. /*
  42.  * By design choice, none of the procedures in this file take a context
  43.  * pointer (i_ctx_p).  Since a number of them require a gs_dual_memory_t
  44.  * for store checking or save bookkeeping, we need to #undef idmemory.
  45.  */
  46. #undef idmemory
  47.  
  48. /* ------ Object utilities ------ */
  49.  
  50. /* Define the table of ref type properties. */
  51. const byte ref_type_properties[] = {
  52.     REF_TYPE_PROPERTIES_DATA
  53. };
  54.  
  55. /* Copy refs from one place to another. */
  56. int
  57. refcpy_to_old(ref * aref, uint index, const ref * from,
  58.           uint size, gs_dual_memory_t *idmemory, client_name_t cname)
  59. {
  60.     ref *to = aref->value.refs + index;
  61.     int code = refs_check_space(from, size, r_space(aref));
  62.  
  63.     if (code < 0)
  64.     return code;
  65.     /* We have to worry about aliasing.... */
  66.     if (to <= from || from + size <= to)
  67.     while (size--)
  68.         ref_assign_old(aref, to, from, cname), to++, from++;
  69.     else
  70.     for (from += size, to += size; size--;)
  71.         from--, to--, ref_assign_old(aref, to, from, cname);
  72.     return 0;
  73. }
  74. void
  75. refcpy_to_new(ref * to, const ref * from, uint size,
  76.           gs_dual_memory_t *idmemory)
  77. {
  78.     while (size--)
  79.     ref_assign_new(to, from), to++, from++;
  80. }
  81.  
  82. /* Fill a new object with nulls. */
  83. void
  84. refset_null_new(ref * to, uint size, uint new_mask)
  85. {
  86.     for (; size--; ++to)
  87.     make_ta(to, t_null, new_mask);
  88. }
  89.  
  90. /* Compare two objects for equality. */
  91. bool
  92. obj_eq(const ref * pref1, const ref * pref2)
  93. {
  94.     ref nref;
  95.  
  96.     if (r_type(pref1) != r_type(pref2)) {
  97.     /*
  98.      * Only a few cases need be considered here:
  99.      * integer/real (and vice versa), name/string (and vice versa),
  100.      * and extended operators.
  101.      */
  102.     switch (r_type(pref1)) {
  103.         case t_integer:
  104.         return (r_has_type(pref2, t_real) &&
  105.             pref2->value.realval == pref1->value.intval);
  106.         case t_real:
  107.         return (r_has_type(pref2, t_integer) &&
  108.             pref2->value.intval == pref1->value.realval);
  109.         case t_name:
  110.         if (!r_has_type(pref2, t_string))
  111.             return false;
  112.         name_string_ref(pref1, &nref);
  113.         pref1 = &nref;
  114.         break;
  115.         case t_string:
  116.         if (!r_has_type(pref2, t_name))
  117.             return false;
  118.         name_string_ref(pref2, &nref);
  119.         pref2 = &nref;
  120.         break;
  121.         default:
  122.         if (r_btype(pref1) != r_btype(pref2))
  123.             return false;
  124.     }
  125.     }
  126.     /*
  127.      * Now do a type-dependent comparison.  This would be very simple if we
  128.      * always filled in all the bytes of a ref, but we currently don't.
  129.      */
  130.     switch (r_btype(pref1)) {
  131.     case t_array:
  132.         return (pref1->value.refs == pref2->value.refs &&
  133.             r_size(pref1) == r_size(pref2));
  134.     case t_mixedarray:
  135.     case t_shortarray:
  136.         return (pref1->value.packed == pref2->value.packed &&
  137.             r_size(pref1) == r_size(pref2));
  138.     case t_boolean:
  139.         return (pref1->value.boolval == pref2->value.boolval);
  140.     case t_dictionary:
  141.         return (pref1->value.pdict == pref2->value.pdict);
  142.     case t_file:
  143.         return (pref1->value.pfile == pref2->value.pfile &&
  144.             r_size(pref1) == r_size(pref2));
  145.     case t_integer:
  146.         return (pref1->value.intval == pref2->value.intval);
  147.     case t_mark:
  148.     case t_null:
  149.         return true;
  150.     case t_name:
  151.         return (pref1->value.pname == pref2->value.pname);
  152.     case t_oparray:
  153.     case t_operator:
  154.         return (op_index(pref1) == op_index(pref2));
  155.     case t_real:
  156.         return (pref1->value.realval == pref2->value.realval);
  157.     case t_save:
  158.         return (pref2->value.saveid == pref1->value.saveid);
  159.     case t_string:
  160.         return (!bytes_compare(pref1->value.bytes, r_size(pref1),
  161.                    pref2->value.bytes, r_size(pref2)));
  162.     case t_device:
  163.         return (pref1->value.pdevice == pref2->value.pdevice);
  164.     case t_struct:
  165.     case t_astruct:
  166.         return (pref1->value.pstruct == pref2->value.pstruct);
  167.     case t_fontID:
  168.         {    /*
  169.          * In the Adobe implementations, different scalings of a
  170.          * font have "equal" FIDs, so we do the same.
  171.          */
  172.         const gs_font *pfont1 = r_ptr(pref1, gs_font);
  173.         const gs_font *pfont2 = r_ptr(pref2, gs_font);
  174.  
  175.         while (pfont1->base != pfont1)
  176.             pfont1 = pfont1->base;
  177.         while (pfont2->base != pfont2)
  178.             pfont2 = pfont2->base;
  179.         return (pfont1 == pfont2);
  180.         }
  181.     }
  182.     return false;        /* shouldn't happen! */
  183. }
  184.  
  185. /* Compare two objects for identity. */
  186. bool
  187. obj_ident_eq(const ref * pref1, const ref * pref2)
  188. {
  189.     if (r_type(pref1) != r_type(pref2))
  190.     return false;
  191.     if (r_has_type(pref1, t_string))
  192.     return (pref1->value.bytes == pref2->value.bytes &&
  193.         r_size(pref1) == r_size(pref2));
  194.     return obj_eq(pref1, pref2);
  195. }
  196.  
  197. /*
  198.  * Set *pchars and *plen to point to the data of a name or string, and
  199.  * return 0.  If the object isn't a name or string, return e_typecheck.
  200.  * If the object is a string without read access, return e_invalidaccess.
  201.  */
  202. int
  203. obj_string_data(const ref *op, const byte **pchars, uint *plen)
  204. {
  205.     switch (r_type(op)) {
  206.     case t_name: {
  207.     ref nref;
  208.  
  209.     name_string_ref(op, &nref);
  210.     *pchars = nref.value.bytes;
  211.     *plen = r_size(&nref);
  212.     return 0;
  213.     }
  214.     case t_string:
  215.     check_read(*op);
  216.     *pchars = op->value.bytes;
  217.     *plen = r_size(op);
  218.     return 0;
  219.     default:
  220.     return_error(e_typecheck);
  221.     }
  222. }
  223.  
  224. /*
  225.  * Create a printable representation of an object, a la cvs and =
  226.  * (full_print = 0), == (full_print = 1), or === (full_print = 2).  Return 0
  227.  * if OK, 1 if the destination wasn't large enough, e_invalidaccess if the
  228.  * object's contents weren't readable.  If the return value is 0 or 1,
  229.  * *prlen contains the amount of data returned.  start_pos is the starting
  230.  * output position -- the first start_pos bytes of output are discarded.
  231.  *
  232.  * The mem argument is only used for getting the type of structures,
  233.  * not for allocating; if it is NULL and full_print != 0, structures will
  234.  * print as --(struct)--.
  235.  *
  236.  * This rather complex API is needed so that a client can call obj_cvp
  237.  * repeatedly to print on a stream, which may require suspending at any
  238.  * point to handle stream callouts.
  239.  */
  240. private void ensure_dot(P1(char *));
  241. int
  242. obj_cvp(const ref * op, byte * str, uint len, uint * prlen,
  243.     int full_print, uint start_pos, gs_memory_t *mem)
  244. {
  245.     char buf[50];  /* big enough for any float, double, or struct name */
  246.     const byte *data = (const byte *)buf;
  247.     uint size;
  248.     int code;
  249.     ref nref;
  250.  
  251.     if (full_print) {
  252.     static const char * const type_strings[] = { REF_TYPE_PRINT_STRINGS };
  253.  
  254.     switch (r_btype(op)) {
  255.     case t_boolean:
  256.     case t_integer:
  257.         break;
  258.     case t_real: {
  259.         /*
  260.          * To get fully accurate output results for IEEE
  261.          * single-precision floats (24 bits of mantissa), the ANSI %g
  262.          * default of 6 digits is not enough; 9 are needed.
  263.          * Unfortunately, using %.9g for floats (as opposed to doubles)
  264.          * produces unfortunate artifacts such as 0.01 5 mul printing as
  265.          * 0.049999997.  Therefore, we print using %g, and if the result
  266.          * isn't accurate enough, print again using %.9g.
  267.          * Unfortunately, a few PostScript programs 'know' that the
  268.          * printed representation of floats fits into 6 digits (e.g.,
  269.          * with cvs).  We resolve this by letting cvs, cvrs, and = do
  270.          * what the Adobe interpreters appear to do (use %g), and only
  271.          * produce accurate output for ==, for which there is no
  272.          * analogue of cvs.  What a hack!
  273.          */
  274.         float value = op->value.realval;
  275.         float scanned;
  276.  
  277.         sprintf(buf, "%g", value);
  278.         sscanf(buf, "%f", &scanned);
  279.         if (scanned != value)
  280.         sprintf(buf, "%.9g", value);
  281.         ensure_dot(buf);
  282.         goto rs;
  283.     }
  284.     case t_operator:
  285.     case t_oparray:  
  286.         code = obj_cvp(op, (byte *)buf + 2, sizeof(buf) - 4, &size, 0, 0, mem);
  287.         if (code < 0) 
  288.         return code;
  289.         buf[0] = buf[1] = buf[size + 2] = buf[size + 3] = '-';
  290.         size += 4;
  291.         goto nl;
  292.     case t_name:     
  293.         if (r_has_attr(op, a_executable)) {
  294.         code = obj_string_data(op, &data, &size);
  295.         if (code < 0)
  296.             return code;
  297.         goto nl;
  298.         }
  299.         if (start_pos > 0)
  300.         return obj_cvp(op, str, len, prlen, 0, start_pos - 1, mem);
  301.         if (len < 1)
  302.         return_error(e_rangecheck);
  303.         code = obj_cvp(op, str + 1, len - 1, prlen, 0, 0, mem);
  304.         if (code < 0)
  305.         return code;
  306.         str[0] = '/';
  307.         ++*prlen;
  308.         return code;
  309.     case t_null:
  310.         data = (const byte *)"null";
  311.         goto rs;
  312.     case t_string:  
  313.         if (!r_has_attr(op, a_read))
  314.         goto other;
  315.         size = r_size(op);
  316.         {
  317.         bool truncate = (full_print == 1 && size > CVP_MAX_STRING);
  318.         stream_cursor_read r;
  319.         stream_cursor_write w;
  320.         uint skip;
  321.         byte *wstr;
  322.         uint len1;
  323.         int status = 1;
  324.  
  325.         if (start_pos == 0) {
  326.             if (len < 1)
  327.             return_error(e_rangecheck);
  328.             str[0] = '(';
  329.             skip = 0;
  330.             wstr = str + 1;
  331.         } else {
  332.             skip = start_pos - 1;
  333.             wstr = str;
  334.         }
  335.         len1 = len + (str - wstr);
  336.         r.ptr = op->value.const_bytes - 1;
  337.         r.limit = r.ptr + (truncate ? CVP_MAX_STRING : size);
  338.         while (skip && status == 1) {
  339.             uint written;
  340.  
  341.             w.ptr = (byte *)buf - 1;
  342.             w.limit = w.ptr + min(skip + len1, sizeof(buf));
  343.             status = s_PSSE_template.process(NULL, &r, &w, false);
  344.             written = w.ptr - ((byte *)buf - 1);
  345.             if (written > skip) {
  346.             written -= skip;
  347.             memcpy(wstr, buf + skip, written);
  348.             wstr += written;
  349.             skip = 0;
  350.             break;
  351.             }
  352.             skip -= written;
  353.         }
  354.         /*
  355.          * We can reach here with status == 0 (and skip != 0) if
  356.          * start_pos lies within the trailing ")" or  "...)".
  357.          */
  358.         if (status == 0) {
  359. #ifdef DEBUG
  360.             if (skip > (truncate ? 4 : 1)) {
  361.             return_error(e_Fatal);
  362.             }
  363. #endif
  364.         }
  365.         w.ptr = wstr - 1;
  366.         w.limit = str - 1 + len;
  367.         if (status == 1)
  368.             status = s_PSSE_template.process(NULL, &r, &w, false);
  369.         *prlen = w.ptr - (str - 1);
  370.         if (status != 0)
  371.             return 1;
  372.         if (truncate) {
  373.             if (len - *prlen < 4 - skip)
  374.             return 1;
  375.             memcpy(w.ptr + 1, "...)" + skip, 4 - skip);
  376.             *prlen += 4 - skip;
  377.         } else {
  378.             if (len - *prlen < 1 - skip)
  379.             return 1;
  380.             memcpy(w.ptr + 1, ")" + skip, 1 - skip);
  381.             *prlen += 1 - skip;
  382.         }
  383.         }
  384.         return 0;
  385.     case t_astruct:
  386.     case t_struct:    
  387.         if (r_is_foreign(op)) {
  388.         /* gs_object_type may not work. */
  389.         data = (const byte *)"-foreign-struct-";
  390.         goto rs;
  391.         }
  392.         if (!mem) {
  393.         data = (const byte *)"-(struct)-";
  394.         goto rs;
  395.         }
  396.         data = (const byte *)
  397.         gs_struct_type_name_string(
  398.             gs_object_type(mem,
  399.                    (const obj_header_t *)op->value.pstruct));
  400.         size = strlen((const char *)data);
  401.         if (size > 4 && !memcmp(data + size - 4, "type", 4))
  402.         size -= 4;
  403.         if (size > sizeof(buf) - 2)
  404.         return_error(e_rangecheck);
  405.         buf[0] = '-';
  406.         memcpy(buf + 1, data, size);
  407.         buf[size + 1] = '-';
  408.         size += 2;
  409.         data = (const byte *)buf;
  410.         goto nl;
  411.     default:
  412. other:
  413.         {
  414.         int rtype = r_btype(op);
  415.  
  416.         if (rtype > countof(type_strings))
  417.             return_error(e_rangecheck);
  418.         data = (const byte *)type_strings[rtype];
  419.         if (data == 0)
  420.             return_error(e_rangecheck);
  421.         }
  422.         goto rs;
  423.     }
  424.     }    
  425.     /* full_print = 0 */
  426.     switch (r_btype(op)) {
  427.     case t_boolean:
  428.     data = (const byte *)(op->value.boolval ? "true" : "false");
  429.     break;
  430.     case t_integer:
  431.     sprintf(buf, "%ld", op->value.intval);
  432.     break;
  433.     case t_string:
  434.     check_read(*op);
  435.     /* falls through */
  436.     case t_name:
  437.     code = obj_string_data(op, &data, &size);
  438.     if (code < 0)
  439.         return code;
  440.     goto nl;
  441.     case t_oparray: {
  442.     uint index = op_index(op);
  443.     const op_array_table *opt = op_index_op_array_table(index);
  444.  
  445.     name_index_ref(opt->nx_table[index - opt->base_index], &nref);
  446.     name_string_ref(&nref, &nref);
  447.     code = obj_string_data(&nref, &data, &size);
  448.     if (code < 0)
  449.         return code;
  450.     goto nl;
  451.     }
  452.     case t_operator: {
  453.     /* Recover the name from the initialization table. */
  454.     uint index = op_index(op);
  455.  
  456.     /*
  457.      * Check the validity of the index.  (An out-of-bounds index
  458.      * is only possible when examining an invalid object using
  459.      * the debugger.)
  460.      */
  461.     if (index > 0 && index < op_def_count) {
  462.         data = (const byte *)(op_index_def(index)->oname + 1);
  463.         break;
  464.     }
  465.     /* Internal operator, no name. */
  466.     sprintf(buf, "@0x%lx", (ulong) op->value.opproc);
  467.     break;
  468.     }
  469.     case t_real:
  470.     sprintf(buf, "%g", op->value.realval);
  471.     ensure_dot(buf);
  472.     break;
  473.     default:
  474.     data = (const byte *)"--nostringval--";
  475.     }
  476. rs: size = strlen((const char *)data);
  477. nl: if (size < start_pos)
  478.     return_error(e_rangecheck);
  479.     size -= start_pos;
  480.     *prlen = min(size, len);
  481.     memmove(str, data + start_pos, *prlen);
  482.     return (size > len);
  483. }
  484. /*
  485.  * Make sure the converted form of a real number has a decimal point.  This
  486.  * is needed for compatibility with Adobe (and other) interpreters.
  487.  */
  488. private void
  489. ensure_dot(char *buf)
  490. {
  491.     if (strchr(buf, '.') == NULL) {
  492.     char *ept = strchr(buf, 'e');
  493.  
  494.     if (ept == NULL)
  495.         strcat(buf, ".0");
  496.     else {
  497.         /* Insert the .0 before the exponent.  What a nuisance! */
  498.         char buf1[30];
  499.  
  500.         strcpy(buf1, ept);
  501.         strcpy(ept, ".0");
  502.         strcat(ept, buf1);
  503.     }
  504.     }
  505. }
  506.  
  507. /*
  508.  * Create a printable representation of an object, a la cvs and =.  Return 0
  509.  * if OK, e_rangecheck if the destination wasn't large enough,
  510.  * e_invalidaccess if the object's contents weren't readable.  If pchars !=
  511.  * NULL, then if the object was a string or name, store a pointer to its
  512.  * characters in *pchars even if it was too large; otherwise, set *pchars =
  513.  * str.  In any case, store the length in *prlen.
  514.  */
  515. int
  516. obj_cvs(const ref * op, byte * str, uint len, uint * prlen,
  517.     const byte ** pchars)
  518. {
  519.     int code = obj_cvp(op, str, len, prlen, 0, 0, NULL);
  520.  
  521.     if (code != 1 && pchars) {
  522.     *pchars = str;
  523.     return code;
  524.     }
  525.     code = obj_string_data(op, pchars, prlen);
  526.     return (code == e_typecheck ? gs_note_error(e_rangecheck) : code);
  527. }
  528.  
  529. /* Find the index of an operator that doesn't have one stored in it. */
  530. ushort
  531. op_find_index(const ref * pref /* t_operator */ )
  532. {
  533.     op_proc_t proc = real_opproc(pref);
  534.     const op_def *const *opp = op_defs_all;
  535.     const op_def *const *opend = opp + (op_def_count / OP_DEFS_MAX_SIZE);
  536.  
  537.     for (; opp < opend; ++opp) {
  538.     const op_def *def = *opp;
  539.  
  540.     for (; def->oname != 0; ++def)
  541.         if (def->proc == proc)
  542.         return (opp - op_defs_all) * OP_DEFS_MAX_SIZE + (def - *opp);
  543.     }
  544.     /* Lookup failed!  This isn't possible.... */
  545.     return 0;
  546. }
  547.  
  548. /*
  549.  * Convert an operator index to an operator or oparray ref.
  550.  * This is only used for debugging and for 'get' from packed arrays,
  551.  * so it doesn't have to be very fast.
  552.  */
  553. void
  554. op_index_ref(uint index, ref * pref)
  555. {
  556.     const op_array_table *opt;
  557.  
  558.     if (op_index_is_operator(index)) {
  559.     make_oper(pref, index, op_index_proc(index));
  560.     return;
  561.     }
  562.     opt = op_index_op_array_table(index);
  563.     make_tasv(pref, t_oparray, opt->attrs, index,
  564.           const_refs, (opt->table.value.const_refs
  565.                + index - opt->base_index));
  566. }
  567.  
  568. /* Get an element from an array of some kind. */
  569. /* This is also used to index into Encoding vectors, */
  570. /* the error name vector, etc. */
  571. int
  572. array_get(const ref * aref, long index_long, ref * pref)
  573. {
  574.     if ((ulong)index_long >= r_size(aref))
  575.     return_error(e_rangecheck);
  576.     switch (r_type(aref)) {
  577.     case t_array:
  578.         {
  579.         const ref *pvalue = aref->value.refs + index_long;
  580.  
  581.         ref_assign(pref, pvalue);
  582.         }
  583.         break;
  584.     case t_mixedarray:
  585.         {
  586.         const ref_packed *packed = aref->value.packed;
  587.         uint index = (uint)index_long;
  588.  
  589.         for (; index--;)
  590.             packed = packed_next(packed);
  591.         packed_get(packed, pref);
  592.         }
  593.         break;
  594.     case t_shortarray:
  595.         {
  596.         const ref_packed *packed = aref->value.packed + index_long;
  597.  
  598.         packed_get(packed, pref);
  599.         }
  600.         break;
  601.     default:
  602.         return_error(e_typecheck);
  603.     }
  604.     return 0;
  605. }
  606.  
  607. /* Get an element from a packed array. */
  608. /* (This works for ordinary arrays too.) */
  609. /* Source and destination are allowed to overlap if the source is packed, */
  610. /* or if they are identical. */
  611. void
  612. packed_get(const ref_packed * packed, ref * pref)
  613. {
  614.     const ref_packed elt = *packed;
  615.     uint value = elt & packed_value_mask;
  616.  
  617.     switch (elt >> r_packed_type_shift) {
  618.     default:        /* (shouldn't happen) */
  619.         make_null(pref);
  620.         break;
  621.     case pt_executable_operator:
  622.         op_index_ref(value, pref);
  623.         break;
  624.     case pt_integer:
  625.         make_int(pref, (int)value + packed_min_intval);
  626.         break;
  627.     case pt_literal_name:
  628.         name_index_ref(value, pref);
  629.         break;
  630.     case pt_executable_name:
  631.         name_index_ref(value, pref);
  632.         r_set_attrs(pref, a_executable);
  633.         break;
  634.     case pt_full_ref:
  635.     case pt_full_ref + 1:
  636.         ref_assign(pref, (const ref *)packed);
  637.     }
  638. }
  639.  
  640. /* Check to make sure an interval contains no object references */
  641. /* to a space younger than a given one. */
  642. /* Return 0 or e_invalidaccess. */
  643. int
  644. refs_check_space(const ref * bot, uint size, uint space)
  645. {
  646.     for (; size--; bot++)
  647.     store_check_space(space, bot);
  648.     return 0;
  649. }
  650.  
  651. /* ------ String utilities ------ */
  652.  
  653. /* Convert a C string to a Ghostscript string */
  654. int
  655. string_to_ref(const char *cstr, ref * pref, gs_ref_memory_t * mem,
  656.           client_name_t cname)
  657. {
  658.     uint size = strlen(cstr);
  659.     int code = gs_alloc_string_ref(mem, pref, a_all, size, cname);
  660.  
  661.     if (code < 0)
  662.     return code;
  663.     memcpy(pref->value.bytes, cstr, size);
  664.     return 0;
  665. }
  666.  
  667. /* Convert a Ghostscript string to a C string. */
  668. /* Return 0 iff the buffer can't be allocated. */
  669. char *
  670. ref_to_string(const ref * pref, gs_memory_t * mem, client_name_t cname)
  671. {
  672.     uint size = r_size(pref);
  673.     char *str = (char *)gs_alloc_string(mem, size + 1, cname);
  674.  
  675.     if (str == 0)
  676.     return 0;
  677.     memcpy(str, (const char *)pref->value.bytes, size);
  678.     str[size] = 0;
  679.     return str;
  680. }
  681.  
  682. /* ------ Operand utilities ------ */
  683.  
  684. /* Get N numeric operands from the stack or an array. */
  685. /* Return a bit-mask indicating which ones are integers, */
  686. /* or a (negative) error indication. */
  687. /* The 1-bit in the bit-mask refers to the first operand. */
  688. /* Store float versions of the operands at pval. */
  689. /* The stack underflow check (check for t__invalid) is harmless */
  690. /* if the operands come from somewhere other than the stack. */
  691. int
  692. num_params(const ref * op, int count, double *pval)
  693. {
  694.     int mask = 0;
  695.  
  696.     pval += count;
  697.     while (--count >= 0) {
  698.     mask <<= 1;
  699.     switch (r_type(op)) {
  700.         case t_real:
  701.         *--pval = op->value.realval;
  702.         break;
  703.         case t_integer:
  704.         *--pval = op->value.intval;
  705.         mask++;
  706.         break;
  707.         case t__invalid:
  708.         return_error(e_stackunderflow);
  709.         default:
  710.         return_error(e_typecheck);
  711.     }
  712.     op--;
  713.     }
  714.     /* If count is very large, mask might overflow. */
  715.     /* In this case we clearly don't care about the value of mask. */
  716.     return (mask < 0 ? 0 : mask);
  717. }
  718. /* float_params doesn't bother to keep track of the mask. */
  719. int
  720. float_params(const ref * op, int count, float *pval)
  721. {
  722.     for (pval += count; --count >= 0; --op)
  723.     switch (r_type(op)) {
  724.         case t_real:
  725.         *--pval = op->value.realval;
  726.         break;
  727.         case t_integer:
  728.         *--pval = op->value.intval;
  729.         break;
  730.         case t__invalid:
  731.         return_error(e_stackunderflow);
  732.         default:
  733.         return_error(e_typecheck);
  734.     }
  735.     return 0;
  736. }
  737.  
  738. /* Get a single real parameter. */
  739. /* The only possible error is e_typecheck. */
  740. /* If an error is returned, the return value is not updated. */
  741. int
  742. real_param(const ref * op, double *pparam)
  743. {
  744.     switch (r_type(op)) {
  745.     case t_integer:
  746.         *pparam = op->value.intval;
  747.         break;
  748.     case t_real:
  749.         *pparam = op->value.realval;
  750.         break;
  751.     default:
  752.         return_error(e_typecheck);
  753.     }
  754.     return 0;
  755. }
  756. int
  757. float_param(const ref * op, float *pparam)
  758. {
  759.     double dval;
  760.     int code = real_param(op, &dval);
  761.  
  762.     if (code >= 0)
  763.     *pparam = (float)dval;    /* can't overflow */
  764.     return code;
  765. }
  766.  
  767. /* Get an integer parameter in a given range. */
  768. int
  769. int_param(const ref * op, int max_value, int *pparam)
  770. {
  771.     check_int_leu(*op, max_value);
  772.     *pparam = (int)op->value.intval;
  773.     return 0;
  774. }
  775.  
  776. /* Make real values on the operand stack. */
  777. int
  778. make_reals(ref * op, const double *pval, int count)
  779. {
  780.     /* This should return e_limitcheck if any real is too large */
  781.     /* to fit into a float on the stack. */
  782.     for (; count--; op++, pval++)
  783.     make_real(op, *pval);
  784.     return 0;
  785. }
  786. int
  787. make_floats(ref * op, const float *pval, int count)
  788. {
  789.     /* This should return e_undefinedresult for infinities. */
  790.     for (; count--; op++, pval++)
  791.     make_real(op, *pval);
  792.     return 0;
  793. }
  794.  
  795. /* Compute the error code when check_proc fails. */
  796. /* Note that the client, not this procedure, uses return_error. */
  797. /* The stack underflow check is harmless in the off-stack case. */
  798. int
  799. check_proc_failed(const ref * pref)
  800. {
  801.     return (r_is_array(pref) ? e_invalidaccess :
  802.         r_has_type(pref, t__invalid) ? e_stackunderflow :
  803.         e_typecheck);
  804. }
  805.  
  806. /* Compute the error code when a type check on the stack fails. */
  807. /* Note that the client, not this procedure, uses return_error. */
  808. int
  809. check_type_failed(const ref * op)
  810. {
  811.     return (r_has_type(op, t__invalid) ? e_stackunderflow : e_typecheck);
  812. }
  813.  
  814. /* ------ Matrix utilities ------ */
  815.  
  816. /* Read a matrix operand. */
  817. /* Return 0 if OK, error code if not. */
  818. int
  819. read_matrix(const ref * op, gs_matrix * pmat)
  820. {
  821.     int code;
  822.     ref values[6];
  823.     const ref *pvalues;
  824.  
  825.     if (r_has_type(op, t_array))
  826.     pvalues = op->value.refs;
  827.     else {
  828.     int i;
  829.  
  830.     for (i = 0; i < 6; ++i) {
  831.         code = array_get(op, (long)i, &values[i]);
  832.         if (code < 0)
  833.         return code;
  834.     }
  835.     pvalues = values;
  836.     }
  837.     check_read(*op);
  838.     if (r_size(op) != 6)
  839.     return_error(e_rangecheck);
  840.     code = float_params(pvalues + 5, 6, (float *)pmat);
  841.     return (code < 0 ? code : 0);
  842. }
  843.  
  844. /* Write a matrix operand. */
  845. /* Return 0 if OK, error code if not. */
  846. int
  847. write_matrix_in(ref * op, const gs_matrix * pmat, gs_dual_memory_t *idmemory,
  848.         gs_ref_memory_t *imem)
  849. {
  850.     ref *aptr;
  851.     const float *pel;
  852.     int i;
  853.  
  854.     check_write_type(*op, t_array);
  855.     if (r_size(op) != 6)
  856.     return_error(e_rangecheck);
  857.     aptr = op->value.refs;
  858.     pel = (const float *)pmat;
  859.     for (i = 5; i >= 0; i--, aptr++, pel++) {
  860.     if (idmemory) {
  861.         ref_save(op, aptr, "write_matrix");
  862.         make_real_new(aptr, *pel);
  863.     } else {
  864.         make_tav(aptr, t_real, imemory_new_mask(imem), realval, *pel);
  865.     }
  866.     }
  867.     return 0;
  868. }
  869.