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

  1. /* Copyright (C) 1989, 1992, 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. /* gsmain.c */
  20. /* Common support for Ghostscript front ends */
  21. #include "memory_.h"
  22. #include "string_.h"
  23. #include "ghost.h"
  24. #include "gp.h"
  25. #include "gsmatrix.h"            /* for gxdevice.h */
  26. #include "gxdevice.h"
  27. #include "errors.h"
  28. #include "oper.h"
  29. #include "idict.h"
  30. #include "iname.h"            /* for name_init */
  31. #include "dstack.h"
  32. #include "estack.h"
  33. #include "ostack.h"            /* put here for files.h */
  34. #include "stream.h"            /* for files.h */
  35. #include "files.h"
  36. #include "ialloc.h"
  37. #include "strimpl.h"        /* for sfilter.h */
  38. #include "sfilter.h"        /* for iscan.h */
  39. #include "iscan.h"
  40. #include "main.h"
  41. #include "store.h"
  42. #include "isave.h"        /* for prototypes */
  43. #include "interp.h"
  44.  
  45. /* ------ Exported data ------ */
  46.  
  47. /* The only reason we export gs_exit_status is so that window systems */
  48. /* with alert boxes can know whether to pause before exiting if */
  49. /* Ghostscript terminates with an error.  There must be a better way .... */
  50. uint gs_memory_chunk_size = 20000;
  51. int gs_exit_status;
  52. int gs_user_errors;
  53.  
  54. /* File name search paths */
  55. const char **gs_lib_paths;
  56. private int gs_lib_count;
  57. char *gs_lib_env_path;
  58.  
  59. /* Define whether or not to look in the current directory first. */
  60. /* This is wrong by any reasonable criterion, but users insist on it. */
  61. #define SEARCH_HERE_FIRST
  62.  
  63. /* ------ Imported data ------ */
  64.  
  65. /* Configuration information imported from gconfig.c. */
  66. extern gx_device *gx_device_list[];
  67. extern const char *gs_lib_default_path;
  68. extern const char *gs_init_file;
  69. extern ref gs_init_file_array[];
  70.  
  71. /* Imported from gsmisc.c */
  72. extern FILE *gs_debug_out;
  73.  
  74. /* Imported from gsmemory.c */
  75. void gs_malloc_init(P0());
  76. void gs_malloc_release(P0());
  77.  
  78. /* Imported operator procedures */
  79. int zflush(P1(os_ptr));
  80.  
  81. /* ------ Forward references ------ */
  82.  
  83. private int gs_run_init_file(P2(int *, ref *));
  84. private int gs_run_file_open(P2(const char *, ref *));
  85.  
  86. /* ------ Initialization ------ */
  87.  
  88. /* Remember how much initialization has been done. */
  89. private int init1_done, init2_done;
  90.  
  91. /* A handy way to declare and execute an initialization procedure: */
  92. #define call_init(proc)\
  93. { extern void proc(P0()); proc(); }
  94.  
  95. /* Initialization to be done before anything else. */
  96. void
  97. gs_init0(FILE *in, FILE *out, FILE *err, int max_lib_paths)
  98. {    /* Set the Ghostscript versions of stdin/out/err. */
  99.     gs_stdin = in;
  100.     gs_stdout = out;
  101.     gs_stderr = err;
  102.     gs_debug_out = gs_stdout;
  103.     /* Do platform-dependent initialization. */
  104.     /* We have to do this as the very first thing, */
  105.     /* because it detects attempts to run 80N86 executables (N>0) */
  106.     /* on incompatible processors. */
  107.     gp_init();
  108.     /* Initialize the file search paths */
  109.     gs_malloc_init();
  110.     gs_lib_env_path = 0;
  111.     gs_lib_paths =
  112.         (const char **)gs_malloc(max_lib_paths + 4, sizeof(char *),
  113.                      "gs_lib_paths array");
  114.     gs_lib_count = 0;
  115. #ifdef SEARCH_HERE_FIRST
  116.     gs_add_lib_path(gp_current_directory_name);
  117. #endif
  118.     gs_user_errors = 1;
  119.     gs_log_errors = 0;
  120.     /* Reset debugging flags */
  121.     memset(gs_debug, 0, 128);
  122.     init1_done = init2_done = 0;
  123. }
  124.  
  125. /* Initialization to be done before constructing any objects. */
  126. void
  127. gs_init1(void)
  128. {    if ( !init1_done )
  129.     {    {    extern bool gs_have_level2(P0());
  130.             ialloc_init(&gs_memory_default, gs_memory_chunk_size,
  131.                     gs_have_level2());
  132.             alloc_save_init(idmemory);
  133.         }
  134.         name_init(imemory_global);
  135.         call_init(obj_init)        /* requires name_init */
  136.         call_init(scan_init)        /* ditto */
  137.         init1_done = 1;
  138.     }
  139. }
  140.  
  141. /* Initialization to be done before running any files. */
  142. void
  143. gs_init2(void)
  144. {    gs_init1();
  145.     if ( !init2_done )
  146.        {    int code, exit_code;
  147.         ref error_object;
  148.         call_init(igs_init)
  149.         call_init(zop_init)
  150.         {    extern void gs_iodev_init(P1(gs_memory_t *));
  151.             gs_iodev_init(imemory);
  152.         }
  153.         call_init(op_init)    /* requires obj_init, scan_init */
  154.         /* Set up the array of additional initialization files. */
  155.         {    ref *ifp = gs_init_file_array;
  156.             ref ifa;
  157.             for ( ; ifp->value.bytes != 0; ifp++ )
  158.               r_set_size(ifp, strlen((const char *)ifp->value.bytes));
  159.             make_tasv(&ifa, t_array, a_readonly + a_foreign,
  160.                   ifp - gs_init_file_array, refs,
  161.                   gs_init_file_array);
  162.             initial_enter_name("INITFILES", &ifa);
  163.         }
  164.         /* Execute the standard initialization file. */
  165.         code = gs_run_init_file(&exit_code, &error_object);
  166.         if ( code < 0 )
  167.         {    if ( code != e_Fatal )
  168.                 gs_debug_dump_stack(code, &error_object);
  169.             gs_exit_with_code((exit_code ? exit_code : 2), code);
  170.         }
  171.         init2_done = 1;
  172.        }
  173.    }
  174.  
  175. /* Add a library search path to the list. */
  176. void
  177. gs_add_lib_path(const char *lpath)
  178. {    gs_lib_paths[gs_lib_count] = lpath;
  179.     gs_lib_count++;
  180.     gs_set_lib_paths();
  181. }
  182.  
  183. /* ------ Execution ------ */
  184.  
  185. /* Complete the list of library search paths. */
  186. void
  187. gs_set_lib_paths(void)
  188. {    const char **ppath = &gs_lib_paths[gs_lib_count];
  189.     if ( gs_lib_env_path != 0 ) *ppath++ = gs_lib_env_path;
  190.     if ( gs_lib_default_path != 0 ) *ppath++ = gs_lib_default_path;
  191.     *ppath = 0;
  192. }
  193.  
  194. /* Open a file, using the search paths. */
  195. int
  196. gs_lib_open(const char *file_name, ref *pfile)
  197. {    /* This is a separate procedure only to avoid tying up */
  198.     /* extra stack space while running the file. */
  199. #define maxfn 200
  200.     byte fn[maxfn];
  201.     uint len;
  202.     return lib_file_open(file_name, strlen(file_name), fn, maxfn,
  203.                  &len, pfile);
  204. }
  205.  
  206. /* Open and execute a file. */
  207. int
  208. gs_run_file(const char *file_name, int user_errors, int *pexit_code, ref *perror_object)
  209. {    ref initial_file;
  210.     int code = gs_run_file_open(file_name, &initial_file);
  211.     if ( code < 0 ) return code;
  212.     return gs_interpret(&initial_file, user_errors, pexit_code, perror_object);
  213. }
  214. private int
  215. gs_run_file_open(const char *file_name, ref *pfref)
  216. {    gs_set_lib_paths();
  217.     if ( gs_lib_open(file_name, pfref) < 0 )
  218.     {    eprintf1("Can't find initialization file %s.\n", file_name);
  219.         return_error(e_Fatal);
  220.     }
  221.     r_set_attrs(pfref, a_execute + a_executable);
  222.     return 0;
  223. }
  224.  
  225. /* Open and run the very first initialization file. */
  226. private int
  227. gs_run_init_file(int *pexit_code, ref *perror_object)
  228. {    ref *prinit;
  229.     ref ifile;
  230.     ref first_token;
  231.     int code;
  232.     scanner_state state;
  233.     /* We know that .initialfile is defined in systemdict */
  234.     /* as an operator, and that it pushes a file on the o-stack. */
  235.     dict_find_string(systemdict, ".initialfile", &prinit);
  236.     gs_set_lib_paths();
  237.     code = (*real_opproc(prinit))(osp);
  238.     if ( code < 0 )
  239.       {    *pexit_code = 255;
  240.         return code;
  241.       }
  242.     ifile = *osp--;
  243.     /* Check to make sure the first token is an integer */
  244.     /* (for the version number check.) */
  245.     scanner_state_init(&state, false);
  246.     code = scan_token(ifile.value.pfile, &first_token, &state);
  247.     if ( code != 0 || !r_has_type(&first_token, t_integer) )
  248.     {    eprintf1("Initialization file %s does not begin with an integer.\n", gs_init_file);
  249.         *pexit_code = 255;
  250.         return_error(e_Fatal);
  251.     }
  252.     *++osp = first_token;
  253.     r_set_attrs(&ifile, a_executable);
  254.     return gs_interpret(&ifile, gs_user_errors, pexit_code, perror_object);
  255. }
  256. /* Operator to open and return the initial file. */
  257. /* Precompiled initialization can redefine this. */
  258. private int
  259. zinitialfile(os_ptr op)
  260. {    int code = gs_run_file_open(gs_init_file, (ref *)(op + 1));
  261.     if ( code < 0 )
  262.         return code;
  263.     push(1);
  264.     return 0;
  265. }
  266.  
  267. /* Run a string. */
  268. int
  269. gs_run_string(const char *str, int user_errors,
  270.   int *pexit_code, ref *perror_object)
  271. {    return gs_run_string_with_length(str, (uint)strlen(str), user_errors,
  272.                      pexit_code, perror_object);
  273. }
  274. int
  275. gs_run_string_with_length(const char *str, uint length, int user_errors,
  276.   int *pexit_code, ref *perror_object)
  277. {    ref fref;
  278.     int code;
  279.     gs_set_lib_paths();
  280.     code = file_read_string((const byte *)str, length, &fref);
  281.     if ( code < 0 ) return code;
  282.     r_set_attrs(&fref, a_executable);
  283.     {    /* Register fref as a root, so we can know it will still */
  284.         /* be valid after the interpreter returns. */
  285.         ref *pfref = &fref;
  286.         gs_gc_root_t froot;
  287.         gs_memory_t *mem = imemory;    /* in case local mode changes */
  288.         gs_register_ref_root(mem, &froot, (void **)&pfref, "gs_run_string");
  289.         code = gs_interpret(&fref, user_errors, pexit_code, perror_object);
  290.         file_close(&fref);
  291.         gs_unregister_root(mem, &froot, "gs_run_string");
  292.     }
  293.     return code;
  294. }
  295.  
  296. /* ------ Termination ------ */
  297.  
  298. /* Free all resources and exit. */
  299. void
  300. gs_finit(int exit_status, int code)
  301. {    gx_device **pdev = gx_device_list;
  302.     gs_exit_status = exit_status;    /* see above */
  303.     fflush(stderr);            /* in case of error exit */
  304.     for ( ; *pdev != 0; pdev++ )
  305.     {    if ( (*pdev)->is_open )
  306.             gs_closedevice(*pdev);
  307.     }
  308.     /* Do the equivalent of a restore "past the bottom". */
  309.     /* This will release all memory, close all open files, etc. */
  310.     if ( init1_done )
  311.         alloc_restore_all(idmemory);
  312.     /* Do platform-specific cleanup. */
  313.     gp_exit(exit_status, code);
  314. }
  315. void
  316. gs_exit_with_code(int exit_status, int code)
  317. {    gs_finit(exit_status, code);
  318.     exit(exit_status);
  319. }
  320. void
  321. gs_exit(int exit_status)
  322. {    gs_exit_with_code(exit_status, 0);
  323. }
  324.  
  325. /* ------ Debugging ------ */
  326.  
  327. /* Debugging code */
  328. extern void debug_print_ref(P1(const ref *));
  329. extern void debug_dump_stack(P2(const ref_stack *, const char *));
  330.  
  331. /* Dump the stacks after interpretation */
  332. void
  333. gs_debug_dump_stack(int code, ref *perror_object)
  334. {    zflush(osp);    /* force out buffered output */
  335.     dprintf1("\nUnexpected interpreter error %d.\n", code);
  336.     if ( perror_object != 0 )
  337.     {    dputs("Error object: ");
  338.         debug_print_ref(perror_object);
  339.         dputc('\n');
  340.     }
  341.     debug_dump_stack(&o_stack, "Operand stack");
  342.     debug_dump_stack(&e_stack, "Execution stack");
  343. }
  344.  
  345. /* Log an error return.  We always include this, in case other */
  346. /* modules were compiled with DEBUG set. */
  347. #undef gs_log_error        /* in case DEBUG isn't set */
  348. int
  349. gs_log_error(int err, const char _ds *file, int line)
  350. {    if ( gs_log_errors )
  351.       { if ( file == NULL )
  352.           dprintf1("Returning error %d.\n", err);
  353.         else
  354.           dprintf3("%s(%d): Returning error %d.\n",
  355.                (char *)file, line, err);
  356.       }
  357.     return err;
  358. }
  359.  
  360. /* ------ "Operator" definition ------ */
  361.  
  362. op_def gsmain_op_defs[] = {
  363.     {"0.initialfile", zinitialfile},
  364.     op_def_end(0)
  365. };
  366.