home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises. All rights reserved.
- Distributed by Free Software Foundation, Inc.
-
- This file is part of Ghostscript.
-
- Ghostscript is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
- to anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing. Refer
- to the Ghostscript General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Ghostscript, but only under the conditions described in the Ghostscript
- General Public License. A copy of this license is supposed to have been
- given to you along with Ghostscript so you can know your rights and
- responsibilities. It should be in a file named COPYING. Among other
- things, the copyright notice and this notice must be preserved on all
- copies. */
-
- /* gs.c */
- /* Driver program for Ghostscript */
- #include <stdio.h>
- #include "string_.h"
- #include "ghost.h"
- #include "alloc.h"
- #include "estack.h"
- #include "ostack.h"
- #include "store.h"
- #include "stream.h"
-
- /* Library routines not declared in a standard header */
- extern char *getenv(P1(const char *));
-
- /* Exported data */
- uint memory_chunk_size = 20000;
- /* File name search paths */
- char **gs_lib_paths;
- private int gs_lib_count;
- private char *gs_lib_env_path;
-
- /* Configuration information imported from gconfig.c. */
- extern char *gs_lib_default_path;
- extern char *gs_init_file;
-
- /* Device procedures imported from gsdevice.c. */
- typedef struct gx_device_s gx_device;
- extern gx_device *gs_getdevice(P1(int));
- extern char *gs_devicename(P1(gx_device *));
-
- /* Help string */
- private char *gs_help1 = "\
- Usage: gs [switches] [file1.ps file2.ps ...]\n\
- or gs [switches] [file1.ps ...] -- filen.ps arg1 arg2 ...\n\
- The latter passes arg1 ... to the program in filen.ps.\n\
- Available devices:";
- private char *gs_help2 = "\n\
- Switches:\n\
- -d<name>[=<token>] define name as token, or null if no token given\n\
- -D<name>[=<token>] same as -d\n\
- -g<width>x<height> set width and height (`geometry') for device\n\
- -I<prefix> add prefix to search path\n\
- -q `quiet' mode, suppress most messages\n\
- -s<name>=<string> define name as string\n\
- -S<name>=<string> same as -s\n\
- -sDEVICE=<devname> select initial device\n\
- `-' alone as a file name means read from stdin non-interactively.\n\
- For more information, please read the use.doc file.\n";
-
- /* Forward references */
- private void runarg(P4(char **, char *, char *, int));
- private void run_string(P1(char *));
- private void init1(), init2();
- private void set_lib_paths();
- private void run_file(P2(char *file_name, int user_errors));
- private void debug_dump_stack(P1(int code));
-
- /* Parameters set by swproc */
- private int user_errors;
- private int quiet;
- private int batch;
-
- /* Static versions of argc and argv (for -- only) */
- private int static_argc;
- private char **static_argv;
-
- main(int argc, char *argv[])
- { int num_files;
- int swproc(P2(char **, char *));
- void argproc(P2(char **, int));
- static_argc = argc;
- static_argv = argv;
- /* Do platform-dependent initialization. */
- /* We have to do this as the very first thing, */
- /* because it detects attempts to run 80N86 executables (N>0) */
- /* on incompatible processors. */
- gp_init();
- /* Initialize the file search paths */
- gs_lib_env_path = 0;
- { char *lib = getenv("GS_LIB");
- if ( lib != 0 )
- { int len = strlen(lib);
- gs_lib_env_path = gs_malloc(len + 1, 1, "GS_LIB");
- strcpy(gs_lib_env_path, lib);
- }
- }
- gs_lib_paths =
- (char **)gs_malloc(argc + 2, sizeof(char *), "-I array");
- gs_lib_count = 0;
- set_lib_paths();
- /* Execute files named in the command line, */
- /* processing options along the way. */
- /* Wait until the first file name (or the end */
- /* of the line) to finish initialization. */
- batch = 0;
- quiet = 0;
- user_errors = 1;
- num_files = gs_main(argc, argv, "GS.MAP", swproc, argproc);
- if ( num_files == 0 )
- { init2();
- }
- if ( !batch ) run_string("start");
- gs_exit(0);
- }
-
- /* Process switches */
- int
- swproc(char **swp, char *arg)
- { char sw = (*swp)[1];
- switch ( sw )
- {
- default:
- return -1;
- case 0: /* read stdin as a file */
- batch = 1;
- init2(); /* Finish initialization */
- run_string("(%stdin) (r) file cvx execute");
- break;
- case '-': /* run with command line args */
- runarg(swp + 1, "{userdict /ARGUMENTS [", "] put (",
- static_argv + static_argc - (swp + 2));
- gs_exit(0);
- case 'h': /* print help */
- case '?':
- fputs(gs_help1, stdout);
- { int i;
- gx_device *pdev;
- for ( i = 0; (pdev = gs_getdevice(i)) != 0; i++ )
- printf(" %s", gs_devicename(pdev));
- }
- fputs(gs_help2, stdout);
- gs_exit(0);
- case 'I': /* specify search path */
- gs_lib_paths[gs_lib_count] = arg;
- gs_lib_count++;
- set_lib_paths();
- break;
- case 'q': /* quiet startup */
- { ref vnull;
- quiet = 1;
- init1();
- make_null(&vnull);
- initial_enter_name("QUIET", &vnull);
- } break;
- case 'D': /* define name */
- case 'd':
- case 'S': /* define name as string */
- case 's':
- { char *eqp = strchr(arg, '=');
- ref value;
- /* Initialize the object memory, scanner, and */
- /* name table now if needed. */
- init1();
- if ( eqp == NULL )
- { make_null(&value);
- }
- else if ( eqp == arg )
- { printf("Usage: -dname, -dname=token, -sname=string");
- gs_exit(1);
- }
- else
- { int code;
- *eqp++ = 0; /* delimit name */
- if ( sw == 'D' || sw == 'd' )
- { stream astream;
- sread_string(&astream,
- (byte *)eqp, strlen(eqp));
- code = scan_token(&astream, 0, &value);
- if ( code )
- { printf("-dname= must be followed by a valid token");
- gs_exit(1);
- }
- }
- else
- { int len = strlen(eqp);
- char *str = gs_malloc((uint)len, 1, "-s");
- if ( str == 0 )
- { lprintf("Out of memory!\n");
- gs_exit(1);
- }
- strcpy(str, eqp);
- make_tasv(&value, t_string, a_read+a_execute,
- len, bytes, (byte *)str);
- }
- }
- /* Enter the name in systemdict */
- initial_enter_name(arg, &value);
- break;
- }
- case 'g': /* define device geometry */
- { long width, height;
- ref value;
- init1();
- if ( sscanf(arg, "%ldx%ld", &width, &height) != 2 )
- { printf("-g must be followed by <width>x<height>\n");
- gs_exit(1);
- }
- make_int(&value, width);
- initial_enter_name("DEVICEWIDTH", &value);
- make_int(&value, height);
- initial_enter_name("DEVICEHEIGHT", &value);
- break;
- }
- case 'M': /* set memory allocation increment */
- { unsigned msize = 0;
- sscanf(arg, "%d", &msize);
- if ( msize <= 0 || msize >= 64 )
- { printf("-M must be between 1 and 64");
- gs_exit(1);
- }
- memory_chunk_size = msize << 10;
- }
- break;
- }
- return 0;
- }
-
- /* Process file names */
- void
- argproc(char **argp, int index)
- { runarg(argp, "{", "(", 0);
- }
- private void
- runarg(char **argp, char *pre, char *post, int nstrs)
- { char *arg = *argp;
- static char *pex = ")run}execute";
- int len = strlen(pre) + strlen(arg) + strlen(post) + strlen(pex) + 1;
- char *line;
- int i;
- for ( i = 1; i <= nstrs; i++ )
- len += strlen(argp[i]) + 2;
- init2(); /* Finish initialization */
- line = gs_malloc(len, 1, "argproc");
- strcpy(line, pre);
- for ( i = 1; i <= nstrs; i++ )
- { strcat(line, "(");
- strcat(line, argp[i]);
- strcat(line, ")");
- }
- strcat(line, post);
- strcat(line, arg);
- strcat(line, pex);
- run_string(line);
- }
- private void
- run_string(char *str)
- { int code;
- ref stref;
- make_tasv(&stref, t_string, a_executable + a_read + a_execute,
- strlen(str), bytes, (byte *)str);
- code = interpret(&stref, user_errors);
- zflush((ref *)0); /* flush stdout */
- zflushpage((ref *)0); /* force display update */
- if ( code ) debug_dump_stack(code), gs_exit(2);
- }
-
- private int init1_done = 0, init2_done = 0;
- private void
- init1()
- { if ( !init1_done )
- { alloc_init(gs_malloc, gs_free, memory_chunk_size);
- name_init();
- obj_init(); /* requires name_init */
- scan_init(); /* ditto */
- init1_done = 1;
- }
- }
- private void
- init2()
- { init1();
- if ( !init2_done )
- { gs_init();
- zop_init();
- interp_init(1); /* requires obj_init */
- op_init(); /* requires obj_init, scan_init */
- /* Execute the standard initialization file. */
- run_file(gs_init_file, user_errors);
- init2_done = 1;
- }
- }
-
- /* Complete the list of library search paths. */
- private void
- set_lib_paths()
- { char **ppath = &gs_lib_paths[gs_lib_count];
- if ( gs_lib_env_path != 0 ) *ppath++ = gs_lib_env_path;
- if ( gs_lib_default_path != 0 ) *ppath++ = gs_lib_default_path;
- *ppath = 0;
- }
-
- /* Open and execute a file */
- private void
- run_file(char *file_name, int user_errors)
- { ref initial_file;
- int code;
- if ( lib_file_open(file_name, strlen(file_name), &initial_file) < 0 )
- { eprintf1("Can't find initialization file %s\n", file_name);
- gs_exit(1);
- }
- r_set_attrs(&initial_file, a_execute + a_executable);
- code = interpret(&initial_file, user_errors);
- if ( code < 0 )
- debug_dump_stack(code), gs_exit(1);
- }
-
- /* Debugging code */
- extern void debug_print_ref(P1(ref *));
- extern void debug_dump_refs(P3(ref *, ref *, char *));
- extern ref error_object;
-
- /* Dump the stacks after interpretation */
- private void
- debug_dump_stack(int code)
- { zflush(osp); /* force out buffered output */
- dprintf1("\nUnexpected interpreter error %d!\nError object: ", code);
- debug_print_ref(&error_object);
- dputc('\n');
- debug_dump_refs(osbot, osp + 1, "Operand stack");
- debug_dump_refs(esbot, esp + 1, "Execution stack");
- }
-