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

  1. /* Copyright (C) 1989, 1995, 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: iinit.c,v 1.2 2000/09/19 19:00:44 lpd Exp $ */
  20. /* Initialize internally known objects for Ghostscript interpreter */
  21. #include "string_.h"
  22. #include "ghost.h"
  23. #include "gscdefs.h"
  24. #include "gsexit.h"
  25. #include "gsstruct.h"
  26. #include "errors.h"
  27. #include "ialloc.h"
  28. #include "iddict.h"
  29. #include "dstack.h"
  30. #include "ilevel.h"
  31. #include "iinit.h"
  32. #include "iname.h"
  33. #include "interp.h"
  34. #include "ipacked.h"
  35. #include "iparray.h"
  36. #include "iutil.h"
  37. #include "ivmspace.h"
  38. #include "opdef.h"
  39. #include "store.h"
  40.  
  41. /* Implementation parameters. */
  42. /*
  43.  * Define the (initial) sizes of the various system dictionaries.  We want
  44.  * the sizes to be prime numbers large enough to cover all the operators,
  45.  * plus everything in the init files, even if all the optional features are
  46.  * selected.  Note that these sizes must be large enough to get us through
  47.  * initialization, since we start up in Level 1 mode where dictionaries
  48.  * don't expand automatically.
  49.  */
  50. /* The size of systemdict can be set in the makefile. */
  51. #ifndef SYSTEMDICT_SIZE
  52. #  define SYSTEMDICT_SIZE 631
  53. #endif
  54. #ifndef SYSTEMDICT_LEVEL2_SIZE
  55. #  define SYSTEMDICT_LEVEL2_SIZE 983
  56. #endif
  57. /* The size of level2dict, if applicable, can be set in the makefile. */
  58. #ifndef LEVEL2DICT_SIZE
  59. #  define LEVEL2DICT_SIZE 233
  60. #endif
  61. /* Ditto the size of ll3dict. */
  62. #ifndef LL3DICT_SIZE
  63. #  define LL3DICT_SIZE 43
  64. #endif
  65. /* Ditto the size of filterdict. */
  66. #ifndef FILTERDICT_SIZE
  67. #  define FILTERDICT_SIZE 43
  68. #endif
  69. /* Define an arbitrary size for the operator procedure tables. */
  70. #ifndef OP_ARRAY_TABLE_SIZE
  71. #  define OP_ARRAY_TABLE_SIZE 180
  72. #endif
  73. #ifndef OP_ARRAY_TABLE_GLOBAL_SIZE
  74. #  define OP_ARRAY_TABLE_GLOBAL_SIZE OP_ARRAY_TABLE_SIZE
  75. #endif
  76. #ifndef OP_ARRAY_TABLE_LOCAL_SIZE
  77. #  define OP_ARRAY_TABLE_LOCAL_SIZE (OP_ARRAY_TABLE_SIZE / 2)
  78. #endif
  79. #define OP_ARRAY_TABLE_TOTAL_SIZE\
  80.   (OP_ARRAY_TABLE_GLOBAL_SIZE + OP_ARRAY_TABLE_LOCAL_SIZE)
  81.  
  82. /* Define the list of error names. */
  83. const char *const gs_error_names[] =
  84. {
  85.     ERROR_NAMES
  86. };
  87.  
  88. /* The operator tables */
  89. op_array_table op_array_table_global, op_array_table_local;    /* definitions of `operator' procedures */
  90.  
  91. /* Enter a name and value into a dictionary. */
  92. private int
  93. i_initial_enter_name_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr,
  94.             const ref * pref)
  95. {
  96.     int code = idict_put_string(pdict, nstr, pref);
  97.  
  98.     if (code < 0)
  99.     lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n",
  100.          code, nstr, dict_length(pdict), dict_maxlength(pdict));
  101.     return code;
  102. }
  103. int
  104. i_initial_enter_name(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref)
  105. {
  106.     return i_initial_enter_name_in(i_ctx_p, systemdict, nstr, pref);
  107. }
  108.  
  109. /* Remove a name from systemdict. */
  110. void
  111. i_initial_remove_name(i_ctx_t *i_ctx_p, const char *nstr)
  112. {
  113.     ref nref;
  114.  
  115.     if (name_ref((const byte *)nstr, strlen(nstr), &nref, -1) >= 0)
  116.     idict_undef(systemdict, &nref);
  117. }
  118.  
  119. /* Define the names and sizes of the initial dictionaries. */
  120. /* The names are used to create references in systemdict. */
  121. const struct {
  122.     const char *name;
  123.     uint size;
  124.     bool local;
  125. } initial_dictionaries[] = {
  126. #ifdef INITIAL_DICTIONARIES
  127.     INITIAL_DICTIONARIES
  128. #else
  129.     /* systemdict is created and named automagically */
  130.     {
  131.     "level2dict", LEVEL2DICT_SIZE, false
  132.     },
  133.     {
  134.     "ll3dict", LL3DICT_SIZE, false
  135.     },
  136.     {
  137.     "globaldict", 0, false
  138.     },
  139.     {
  140.     "userdict", 0, true
  141.     },
  142.     {
  143.     "filterdict", FILTERDICT_SIZE, false
  144.     },
  145. #endif
  146. };
  147. /* systemdict and globaldict are magically inserted at the bottom */
  148. const char *const initial_dstack[] =
  149. {
  150. #ifdef INITIAL_DSTACK
  151.     INITIAL_DSTACK
  152. #else
  153.     "userdict"
  154. #endif
  155. };
  156.  
  157. #define MIN_DSTACK_SIZE (countof(initial_dstack) + 1)    /* +1 for systemdict */
  158.  
  159.  
  160. /* Detect whether we have any Level 2 operators. */
  161. /* We export this for gs_init1 in imain.c. */
  162. /* This is very slow, but we only call it a couple of times. */
  163. bool
  164. gs_have_level2(void)
  165. {
  166.     const op_def *const *tptr;
  167.  
  168.     for (tptr = op_defs_all; *tptr != 0; ++tptr) {
  169.     const op_def *def;
  170.  
  171.     for (def = *tptr; def->oname != 0; ++def)
  172.         if (op_def_is_begin_dict(def) &&
  173.         !strcmp(def->oname, "level2dict")
  174.         )
  175.         return true;
  176.     }
  177.     return false;
  178. }
  179.  
  180. /* Create an initial dictionary if necessary. */
  181. private ref *
  182. make_initial_dict(i_ctx_t *i_ctx_p, const char *iname, ref idicts[])
  183. {
  184.     int i;
  185.  
  186.     /* systemdict was created specially. */
  187.     if (!strcmp(iname, "systemdict"))
  188.     return systemdict;
  189.     for (i = 0; i < countof(initial_dictionaries); i++) {
  190.     const char *dname = initial_dictionaries[i].name;
  191.     const int dsize = initial_dictionaries[i].size;
  192.  
  193.     if (!strcmp(iname, dname)) {
  194.         ref *dref = &idicts[i];
  195.  
  196.         if (r_has_type(dref, t_null)) {
  197.         gs_ref_memory_t *mem =
  198.             (initial_dictionaries[i].local ?
  199.              iimemory_local : iimemory_global);
  200.         int code = dict_alloc(mem, dsize, dref);
  201.  
  202.         if (code < 0)
  203.             return 0;    /* disaster */
  204.         }
  205.         return dref;
  206.     }
  207.     }
  208.  
  209.     /*
  210.      * Name mentioned in some op_def, but not in initial_dictionaries.
  211.      * Punt.
  212.      */
  213.     return 0;
  214. }
  215.  
  216. /* Initialize objects other than operators.  In particular, */
  217. /* initialize the dictionaries that hold operator definitions. */
  218. int
  219. obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
  220. {
  221.     bool level2 = gs_have_level2();
  222.     ref system_dict;
  223.     i_ctx_t *i_ctx_p;
  224.     int code;
  225.  
  226.     /*
  227.      * Create systemdict.  The context machinery requires that
  228.      * we do this before initializing the interpreter.
  229.      */
  230.     code = dict_alloc(idmem->space_global,
  231.               (level2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE),
  232.               &system_dict);
  233.     if (code < 0)
  234.     return code;
  235.  
  236.     /* Initialize the interpreter. */
  237.     code = gs_interp_init(pi_ctx_p, &system_dict, idmem);
  238.     if (code < 0)
  239.     return code;
  240.     i_ctx_p = *pi_ctx_p;
  241.  
  242.     {
  243. #define icount countof(initial_dictionaries)
  244.     ref idicts[icount];
  245.     int i;
  246.     const op_def *const *tptr;
  247.  
  248.     min_dstack_size = MIN_DSTACK_SIZE;
  249.  
  250.     refset_null(idicts, icount);
  251.  
  252.     /* Put systemdict on the dictionary stack. */
  253.     if (level2) {
  254.         dsp += 2;
  255.         /*
  256.          * For the moment, let globaldict be an alias for systemdict.
  257.          */
  258.         dsp[-1] = system_dict;
  259.         min_dstack_size++;
  260.     } else {
  261.         ++dsp;
  262.     }
  263.     *dsp = system_dict;
  264.  
  265.     /* Create dictionaries which are to be homes for operators. */
  266.     for (tptr = op_defs_all; *tptr != 0; tptr++) {
  267.         const op_def *def;
  268.  
  269.         for (def = *tptr; def->oname != 0; def++)
  270.         if (op_def_is_begin_dict(def)) {
  271.             if (make_initial_dict(i_ctx_p, def->oname, idicts) == 0)
  272.             return_error(e_VMerror);
  273.         }
  274.     }
  275.  
  276.     /* Set up the initial dstack. */
  277.     for (i = 0; i < countof(initial_dstack); i++) {
  278.         const char *dname = initial_dstack[i];
  279.  
  280.         ++dsp;
  281.         if (!strcmp(dname, "userdict"))
  282.         dstack_userdict_index = dsp - dsbot;
  283.         ref_assign(dsp, make_initial_dict(i_ctx_p, dname, idicts));
  284.     }
  285.  
  286.     /* Enter names of referenced initial dictionaries into systemdict. */
  287.     initial_enter_name("systemdict", systemdict);
  288.     for (i = 0; i < icount; i++) {
  289.         ref *idict = &idicts[i];
  290.  
  291.         if (!r_has_type(idict, t_null)) {
  292.         /*
  293.          * Note that we enter the dictionary in systemdict
  294.          * even if it is in local VM.  There is a special
  295.          * provision in the garbage collector for this:
  296.          * see ivmspace.h for more information.
  297.          * In order to do this, we must temporarily
  298.          * identify systemdict as local, so that the
  299.          * store check in dict_put won't fail.
  300.          */
  301.         uint save_space = r_space(systemdict);
  302.  
  303.         r_set_space(systemdict, avm_local);
  304.         code = initial_enter_name(initial_dictionaries[i].name,
  305.                       idict);
  306.         r_set_space(systemdict, save_space);
  307.         if (code < 0)
  308.             return code;
  309.         }
  310.     }
  311. #undef icount
  312.     }
  313.  
  314.     gs_interp_reset(i_ctx_p);
  315.  
  316.     {
  317.     ref vnull, vtrue, vfalse;
  318.  
  319.     make_null(&vnull);
  320.     make_true(&vtrue);
  321.     make_false(&vfalse);
  322.     if ((code = initial_enter_name("null", &vnull)) < 0 ||
  323.         (code = initial_enter_name("true", &vtrue)) < 0 ||
  324.         (code = initial_enter_name("false", &vfalse)) < 0
  325.         )
  326.         return code;
  327.     }
  328.  
  329.     /* Create the error name table */
  330.     {
  331.     int n = countof(gs_error_names) - 1;
  332.     int i;
  333.     ref era;
  334.  
  335.     code = ialloc_ref_array(&era, a_readonly, n, "ErrorNames");
  336.     if (code < 0)
  337.         return code;
  338.     for (i = 0; i < n; i++)
  339.         if ((code = name_enter_string((const char *)gs_error_names[i],
  340.                       era.value.refs + i)) < 0)
  341.         return code;
  342.     return initial_enter_name("ErrorNames", &era);
  343.     }
  344. }
  345.  
  346. /* Run the initialization procedures of the individual operator files. */
  347. int
  348. zop_init(i_ctx_t *i_ctx_p)
  349. {
  350.     const op_def *const *tptr;
  351.     int code;
  352.  
  353.     /* Because of a bug in Sun's SC1.0 compiler, */
  354.     /* we have to spell out the typedef for op_def_ptr here: */
  355.     const op_def *def;
  356.  
  357.     for (tptr = op_defs_all; *tptr != 0; tptr++) {
  358.     for (def = *tptr; def->oname != 0; def++)
  359.         DO_NOTHING;
  360.     if (def->proc != 0) {
  361.         code = def->proc(i_ctx_p);
  362.         if (code < 0) {
  363.         lprintf2("op_init proc 0x%lx returned error %d!\n",
  364.              (ulong)def->proc, code);
  365.         return code;
  366.         }
  367.     }
  368.     }
  369.  
  370.     /* Initialize the predefined names other than operators. */
  371.     /* Do this here in case op_init changed any of them. */
  372.     {
  373.     ref vcr, vpr, vpf, vre, vrd;
  374.  
  375.     make_const_string(&vcr, a_readonly | avm_foreign,
  376.               strlen(gs_copyright), (const byte *)gs_copyright);
  377.     make_const_string(&vpr, a_readonly | avm_foreign,
  378.               strlen(gs_product), (const byte *)gs_product);
  379.     make_const_string(&vpf, a_readonly | avm_foreign,
  380.               strlen(gs_productfamily),
  381.               (const byte *)gs_productfamily);
  382.     make_int(&vre, gs_revision);
  383.     make_int(&vrd, gs_revisiondate);
  384.     if ((code = initial_enter_name("copyright", &vcr)) < 0 ||
  385.         (code = initial_enter_name("product", &vpr)) < 0 ||
  386.         (code = initial_enter_name("productfamily", &vpf)) < 0 ||
  387.         (code = initial_enter_name("revision", &vre)) < 0 ||
  388.         (code = initial_enter_name("revisiondate", &vrd)) < 0)
  389.         return code;
  390.     }
  391.  
  392.     return 0;
  393. }
  394.  
  395. /* Create an op_array table. */
  396. private int
  397. alloc_op_array_table(i_ctx_t *i_ctx_p, uint size, uint space,
  398.              op_array_table *opt)
  399. {
  400.     uint save_space = ialloc_space(idmemory);
  401.     int code;
  402.  
  403.     ialloc_set_space(idmemory, space);
  404.     code = ialloc_ref_array(&opt->table, a_readonly, size,
  405.                 "op_array table");
  406.     ialloc_set_space(idmemory, save_space);
  407.     if (code < 0)
  408.     return code;
  409.     refset_null(opt->table.value.refs, size);
  410.     opt->nx_table =
  411.     (ushort *) ialloc_byte_array(size, sizeof(ushort),
  412.                      "op_array nx_table");
  413.     if (opt->nx_table == 0)
  414.     return_error(e_VMerror);
  415.     opt->count = 0;
  416.     opt->root_p = &opt->table;
  417.     opt->attrs = space | a_executable;
  418.     return 0;
  419. }
  420.  
  421. /* Initialize the operator table. */
  422. int
  423. op_init(i_ctx_t *i_ctx_p)
  424. {
  425.     const op_def *const *tptr;
  426.     int code;
  427.  
  428.     /* Enter each operator into the appropriate dictionary. */
  429.  
  430.     for (tptr = op_defs_all; *tptr != 0; tptr++) {
  431.     ref *pdict = systemdict;
  432.     const op_def *def;
  433.     const char *nstr;
  434.  
  435.     for (def = *tptr; (nstr = def->oname) != 0; def++)
  436.         if (op_def_is_begin_dict(def)) {
  437.         ref nref;
  438.  
  439.         code = name_ref((const byte *)nstr, strlen(nstr), &nref, -1);
  440.         if (code < 0)
  441.             return code;
  442.         if (!dict_find(systemdict, &nref, &pdict))
  443.             return_error(e_Fatal);
  444.         if (!r_has_type(pdict, t_dictionary))
  445.             return_error(e_Fatal);
  446.         } else {
  447.         ref oper;
  448.         uint index_in_table = def - *tptr;
  449.         uint opidx = (tptr - op_defs_all) * OP_DEFS_MAX_SIZE +
  450.             index_in_table;
  451.  
  452.         if (index_in_table >= OP_DEFS_MAX_SIZE)
  453.             dprintf1("opdef overrun: %s\n", def->oname);
  454.         gs_interp_make_oper(&oper, def->proc, opidx);
  455.         /* The first character of the name is a digit */
  456.         /* giving the minimum acceptable number of operands. */
  457.         /* Check to make sure it's within bounds. */
  458.         if (*nstr - '0' > gs_interp_max_op_num_args)
  459.             return_error(e_Fatal);
  460.         nstr++;
  461.         /*
  462.          * Skip internal operators, and the second occurrence of
  463.          * operators with special indices.
  464.          */
  465.         if (*nstr != '%' && r_size(&oper) == opidx) {
  466.             code =
  467.             i_initial_enter_name_in(i_ctx_p, pdict, nstr, &oper);
  468.             if (code < 0)
  469.             return code;
  470.         }
  471.         }
  472.     }
  473.     /* Allocate the tables for `operator' procedures. */
  474.     /* Make one of them local so we can have local operators. */
  475.  
  476.     if ((code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_GLOBAL_SIZE,
  477.                      avm_global, &op_array_table_global) < 0))
  478.     return code;
  479.     op_array_table_global.base_index = op_def_count;
  480.     if ((code = gs_register_ref_root(imemory, NULL,
  481.                      (void **)&op_array_table_global.root_p,
  482.                      "op_array_table(global)")) < 0 ||
  483.     (code = gs_register_struct_root(imemory, NULL,
  484.                 (void **)&op_array_table_global.nx_table,
  485.                     "op_array nx_table(global)")) < 0 ||
  486.     (code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_LOCAL_SIZE,
  487.                      avm_local, &op_array_table_local) < 0)
  488.     )
  489.     return code;
  490.     op_array_table_local.base_index =
  491.     op_array_table_global.base_index +
  492.     r_size(&op_array_table_global.table);
  493.     if ((code = gs_register_ref_root(imemory, NULL,
  494.                      (void **)&op_array_table_local.root_p,
  495.                      "op_array_table(local)")) < 0 ||
  496.     (code = gs_register_struct_root(imemory, NULL,
  497.                 (void **)&op_array_table_local.nx_table,
  498.                     "op_array nx_table(local)")) < 0
  499.     )
  500.     return code;
  501.  
  502.     return 0;
  503. }
  504.