home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK5 / DOS_14 / GS252DVX.ZIP / GS.C < prev    next >
C/C++ Source or Header  |  1992-09-15  |  14KB  |  490 lines

  1. /* Copyright (C) 1989, 1992 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gs.c */
  21. /* Driver program for Ghostscript */
  22. /* We have to include std.h before any file that includes <sys/types.h>. */
  23. #include "std.h"
  24. #include <ctype.h>
  25. #include "memory_.h"
  26. #include "string_.h"
  27. /* Capture stdin/out/err before gs.h redefines them. */
  28. #include <stdio.h>
  29. static FILE *real_stdin, *real_stdout, *real_stderr;
  30. static void
  31. get_real()
  32. {    real_stdin = stdin, real_stdout = stdout, real_stderr = stderr;
  33. }
  34. /* Define PROGRAM_NAME before we include std.h */
  35. #ifndef PROGRAM_NAME
  36. #  define PROGRAM_NAME "Ghostscript"
  37. #endif
  38. #include "ghost.h"
  39. #include "gxdevice.h"
  40. #include "gxdevmem.h"
  41. #include "alloc.h"
  42. #include "errors.h"
  43. #include "estack.h"
  44. #include "main.h"
  45. #include "ostack.h"
  46. #include "store.h"
  47. #include "stream.h"
  48.   
  49. #ifndef GS_LIB
  50. #  define GS_LIB "GS_LIB"
  51. #endif
  52.  
  53. /* Library routines not declared in a standard header */
  54. extern char *getenv(P1(const char *));
  55. /* Note: sscanf incorrectly defines its first argument as char * */
  56. /* rather than const char *.  This accounts for the ugly casts below. */
  57.  
  58. /* Device procedures imported from gsdevice.c. */
  59. extern gx_device *gs_getdevice(P1(int));
  60. extern char *gs_devicename(P1(gx_device *));
  61.  
  62. /* Other imported data */
  63. extern int gs_alloc_debug;
  64. extern int gs_log_errors;
  65. extern gx_device *gx_device_list[];
  66. extern const int gs_revision;
  67. extern const char *gs_revisiondate;
  68.  
  69. /*
  70.  * Help strings.  We have to break them up into parts, because
  71.  * the Watcom compiler has a limit of 510 characters for a single token.
  72.  * For PC displays, we want to limit the strings to 24 lines.
  73.  */
  74. private const char *gs_help1 = "\
  75. Usage: gs [switches] [file1.ps file2.ps ...]\n\
  76.   or : gs [switches] [file1.ps ...] -- filen.ps arg1 arg2 ...\n\
  77. The latter passes arg1 ... to the program in filen.ps.\n\
  78. Available devices:\n   ";
  79. /* We have to break help2 up into parts, because  */
  80. private const char *gs_help2a = "\n\
  81. Switches: (you can use # in place of =)\n\
  82.     @<file>              treat file like part of the command line\n\
  83.                            (to get around DOS command line limit)\n\
  84.     -d<name>[=<token>]   define name as token, or null if no token given\n\
  85.     -f<file>             read this file even if its name begins with - or @\n";
  86. private const char *gs_help2b = "\
  87.     -g<width>x<height>   set width and height (`geometry'), in pixels\n\
  88.     -I<prefix>           add prefix to search path\n\
  89.     -q                   `quiet' mode, suppress most messages\n\
  90.     -r<res>              set resolution, in pixels per inch\n";
  91. private const char *gs_help2c = "\
  92.     -s<name>=<string>    define name as string\n\
  93.     -sDEVICE=<devname>   select initial device\n\
  94.     -sOutputFile=<file>  select output file: embed %d for page #,\n\
  95.                            - means stdout, use |command to pipe\n\
  96. `-' alone as a file name means read from stdin non-interactively.\n\
  97. For more information, please read the use.doc file.\n";
  98.  
  99. /* Forward references */
  100. private int swproc(P1(const char *));
  101. private void argproc(P1(const char *));
  102. private void cmdproc(P1(const char *));
  103. private void print_revision(P0());
  104. private int esc_strlen(P1(const char *));
  105. private void esc_strcat(P2(char *, const char *));
  106. private void runarg(P4(const char **, const char *, const char *, int));
  107. private void run_string(P1(const char *));
  108.  
  109. /* Parameters set by swproc */
  110. private int quiet;
  111. private int batch;
  112.  
  113. main(int argc, const char *argv[])
  114. {    int argi;
  115.     get_real();
  116.     gs_init0(real_stdin, real_stdout, real_stderr, argc);
  117.        {    char *lib = getenv(GS_LIB);
  118.         if ( lib != 0 ) 
  119.            {    int len = strlen(lib);
  120.             gs_lib_env_path = gs_malloc(len + 1, 1, "GS_LIB");
  121.             strcpy(gs_lib_env_path, lib);
  122.            }
  123.        }
  124.     /* Execute files named in the command line, */
  125.     /* processing options along the way. */
  126.     /* Wait until the first file name (or the end */
  127.     /* of the line) to finish initialization. */
  128.     batch = 0;
  129.     quiet = 0;
  130.     /* If debugging is enabled, trace the device calls. */
  131. #ifdef DEBUG
  132.        {    extern gx_device *gs_trace_device(P1(gx_device *));
  133.         extern const gx_device_memory
  134.             mem_mono_device, mem_mapped2_color_device,
  135.             mem_mapped4_color_device, mem_mapped8_color_device,
  136.             mem_true16_color_device,
  137.             mem_true24_color_device, mem_true32_color_device;
  138.         static const gx_device_memory *mdevs[8] =
  139.            {    &mem_mono_device, &mem_mapped2_color_device,
  140.             &mem_mapped4_color_device, &mem_mapped8_color_device,
  141.             &mem_true16_color_device,
  142.             &mem_true24_color_device, &mem_true32_color_device,
  143.             0
  144.            };
  145.         gx_device **pdevs[3];
  146.         gx_device ***ppdev;
  147.         gx_device **pdev;
  148.         pdevs[0] = gx_device_list;
  149.         pdevs[1] = (gx_device **)mdevs;
  150.         pdevs[2] = 0;
  151.         for ( ppdev = pdevs; *ppdev != 0; ppdev++ )
  152.          for ( pdev = *ppdev; *pdev != 0; pdev++ )
  153.            {
  154. /******
  155.             gx_device *tdev = gs_trace_device(*pdev);
  156.             if ( tdev == 0 )
  157.                {    lprintf("Can't allocate traced device!\n");
  158.                 gs_exit(1);
  159.                }
  160.             *pdev = tdev;
  161.  ******/
  162.            }
  163.        }
  164. #endif
  165.     for ( argi = 1; argi < argc; argi++ )
  166.        {    const char **argp = &argv[argi];
  167.         const char *arg = *argp;
  168.         switch ( *arg )
  169.         {
  170.         case '@':
  171.             cmdproc(arg);
  172.             break;
  173.         case '-':
  174.             if ( !strcmp(arg, "--") || !strcmp(arg, "-+") )
  175.             {    /* run with command line args */
  176.                 int nstrs = argc - argi - 2;
  177.                 if ( nstrs < 0 )    /* no file to run! */
  178.                 {    puts("Usage: gs ... -- file.ps arg1 ... argn");
  179.                     gs_exit(1);
  180.                 }
  181.                 runarg(argp + 1, "{userdict /ARGUMENTS [", "] put (", nstrs);
  182.                 gs_exit(0);
  183.             }
  184.             else
  185.             {    if ( swproc(arg) < 0 )
  186.                   fprintf(stdout, "Unknown switch %s - ignoring\n", arg);
  187.             }
  188.             break;
  189.         default:
  190.             argproc(arg);
  191.         }
  192.        }
  193.     gs_init2();
  194.     if ( !batch ) run_string("start");
  195.     gs_exit(0);
  196. }
  197.  
  198. /* Process switches */
  199. private int
  200. swproc(const char *arg)
  201. {    char sw = arg[1];
  202.     arg += 2;        /* skip - and letter */
  203.     switch ( sw )
  204.        {
  205.     default:
  206.         return -1;
  207.     case 0:                /* read stdin as a file */
  208.         batch = 1;
  209.         /* Set NOPAUSE so showpage won't try to read from stdin. */
  210.         swproc("-dNOPAUSE");
  211.         gs_init2();        /* Finish initialization */
  212.         run_string("(%stdin) (r) file cvx execute0");
  213.         break;
  214.     case 'A':            /* trace allocator */
  215.         gs_alloc_debug = 1; break;
  216.     case 'e':            /* log errors */
  217.         gs_log_errors = 1; break;
  218.     case 'E':            /* log errors */
  219.         gs_log_errors = 2; break;
  220.     case 'f':            /* run file of arbitrary name */
  221.         argproc(arg); break;
  222.     case 'h':            /* print help */
  223.     case '?':            /* ditto */
  224.         print_revision();
  225.         fputs(gs_help1, stdout);
  226.            {    int i;
  227.             gx_device *pdev;
  228.             for ( i = 0; (pdev = gs_getdevice(i)) != 0; i++ )
  229.                 fprintf(stdout, " %s", gs_devicename(pdev));
  230.            }
  231.         fputs(gs_help2a, stdout);
  232.         fputs(gs_help2b, stdout);
  233.         fputs(gs_help2c, stdout);
  234.         gs_exit(0);
  235.     case 'I':            /* specify search path */
  236.         gs_add_lib_path(arg);
  237.         break;
  238.     case 'q':            /* quiet startup */
  239.        {    ref vtrue;
  240.         quiet = 1;
  241.         gs_init1();
  242.         make_true(&vtrue);
  243.         initial_enter_name("QUIET", &vtrue);
  244.        }    break;
  245.     case 'D':            /* define name */
  246.     case 'd':
  247.     case 'S':            /* define name as string */
  248.     case 's':
  249.        {    char *eqp = strchr(arg, '=');
  250.         int isd = (sw == 'D' || sw == 'd');
  251.         ref value;
  252.         if ( eqp == NULL ) eqp = strchr(arg, '#');
  253.         /* Initialize the object memory, scanner, and */
  254.         /* name table now if needed. */
  255.         gs_init1();
  256.         if ( eqp == arg )
  257.            {    puts("Usage: -dname, -dname=token, -sname=string");
  258.             gs_exit(1);
  259.            }
  260.         if ( eqp == NULL )
  261.            {    if ( isd ) make_null(&value);
  262.             else make_tasv(&value, t_string, a_readonly,
  263.                        0, bytes, (byte *)"");
  264.            }
  265.         else
  266.            {    int code;
  267.             *eqp++ = 0;    /* delimit name */
  268.             if ( isd )
  269.                {    stream astream;
  270.                 sread_string(&astream,
  271.                          (byte *)eqp, strlen(eqp));
  272.                 code = scan_token(&astream, 0, &value);
  273.                 if ( code )
  274.                    {    puts("-dname= must be followed by a valid token");
  275.                     gs_exit(1);
  276.                    }
  277.                }
  278.             else
  279.                {    int len = strlen(eqp);
  280.                 char *str = gs_malloc((uint)len, 1, "-s");
  281.                 if ( str == 0 )
  282.                    {    lprintf("Out of memory!\n");
  283.                     gs_exit(1);
  284.                    }
  285.                 memcpy(str, eqp, len);
  286.                 make_tasv(&value, t_string, a_readonly,
  287.                       len, bytes, (byte *)str);
  288.                }
  289.            }
  290.         /* Enter the name in systemdict */
  291.         initial_enter_name(arg, &value);
  292.         break;
  293.        }
  294.     case 'g':            /* define device geometry */
  295.        {    long width, height;
  296.         ref value;
  297.         gs_init1();
  298.         if ( sscanf((char *)arg, "%ldx%ld", &width, &height) != 2 )
  299.            {    puts("-g must be followed by <width>x<height>");
  300.             gs_exit(1);
  301.            }
  302.         make_int(&value, width);
  303.         initial_enter_name("DEVICEWIDTH", &value);
  304.         make_int(&value, height);
  305.         initial_enter_name("DEVICEHEIGHT", &value);
  306.         break;
  307.        }
  308.     case 'M':            /* set memory allocation increment */
  309.        {    unsigned msize = 0;
  310.         sscanf((char *)arg, "%d", &msize);
  311.         if ( msize <= 0 || msize >= 64 )
  312.            {    puts("-M must be between 1 and 63");
  313.             gs_exit(1);
  314.            }
  315.         gs_memory_chunk_size = msize << 10;
  316.        }
  317.         break;
  318.     case 'r':            /* define device resolution */
  319.        {    float xres, yres;
  320.         ref value;
  321.         gs_init1();
  322.         switch ( sscanf((char *)arg, "%fx%f", &xres, &yres) )
  323.            {
  324.         default:
  325.             puts("-r must be followed by <res> or <xres>x<yres>");
  326.             gs_exit(1);
  327.         case 1:            /* -r<res> */
  328.             yres = xres;
  329.         case 2:            /* -r<xres>x<yres> */
  330.             make_real(&value, xres);
  331.             initial_enter_name("DEVICEXRESOLUTION", &value);
  332.             make_real(&value, yres);
  333.             initial_enter_name("DEVICEYRESOLUTION", &value);
  334.            }
  335.         break;
  336.        }
  337.     case 'v':            /* print revision */
  338.         print_revision();
  339.         gs_exit(0);
  340.     case 'Z':
  341.         if ( !*arg )
  342.            {    /* No options, set all flags */
  343.             memset(gs_debug, 0xff, 128);
  344.            }
  345.         else
  346.            {    while ( *arg )
  347.                 gs_debug[*arg++ & 127] = 0xff;
  348.            }
  349.         break;
  350.        }
  351.     return 0;
  352. }
  353.  
  354. /* Define versions of strlen and strcat that insert \ escapes */
  355. /* before \, (, and ). */
  356. #define needs_esc(ch) ((ch) == '(' || (ch) == ')' || (ch) == '\\')
  357. private int
  358. esc_strlen(const char *str)
  359. {    int n = strlen(str);
  360.     const char *p;
  361.     for ( p = str; *p; p++ ) if ( needs_esc(*p) ) n++;
  362.     return n;
  363. }
  364. private void
  365. esc_strcat(char *dest, const char *src)
  366. {    char *d = dest + strlen(dest);
  367.     const char *p;
  368.     for ( p = src; *p; p++ )
  369.        {    if ( needs_esc(*p) ) *d++ = '\\';
  370.         *d++ = *p;
  371.        }
  372.     *d = 0;
  373. }
  374.  
  375. /* Process file names */
  376. private void
  377. argproc(const char *arg)
  378. {    runarg(&arg, "{", "(", 0);
  379. }
  380. private void
  381. runarg(const char **argp, const char *pre, const char *post, int nstrs)
  382. {    const char *arg = *argp;
  383.     static const char *pex = ")run}execute";
  384.     int len = strlen(pre) + esc_strlen(arg) + nstrs * 2 + strlen(post) + strlen(pex) + 1;
  385.     char *line;
  386.     int i;
  387.     for ( i = 1; i <= nstrs; i++ )
  388.         len += esc_strlen(argp[i]) + 2;
  389.     gs_init2();    /* Finish initialization */
  390.     line = gs_malloc(len, 1, "argproc");
  391.     if ( line == 0 )
  392.     {    lprintf("Out of memory!\n");
  393.         gs_exit(1);
  394.     }
  395.     strcpy(line, pre);
  396.     for ( i = 1; i <= nstrs; i++ )
  397.        {    strcat(line, "(");
  398.         esc_strcat(line, argp[i]);
  399.         strcat(line, ")");
  400.        }
  401.     strcat(line, post);
  402.     esc_strcat(line, arg);
  403.     strcat(line, pex);
  404.     run_string(line);
  405. }
  406. private void
  407. run_string(const char *str)
  408. {    int exit_code;
  409.     ref error_object;
  410.     int code = gs_run_string(str, gs_user_errors, &exit_code, &error_object);
  411.     zflush((ref *)0);    /* flush stdout */
  412.     zflushpage((ref *)0); /* force display update */
  413.     switch ( code )
  414.     {
  415.     case 0:
  416.         break;
  417.     case e_Quit:
  418.         gs_exit(0);
  419.     case e_Fatal:
  420.         eprintf1("Unrecoverable error, exit code %d\n", exit_code);
  421.         gs_exit(exit_code);
  422.     default:
  423.         gs_debug_dump_stack(code, &error_object);
  424.         gs_exit(255);
  425.     }
  426. }
  427.  
  428. /* Process command line indirection. */
  429. private void
  430. cmdproc(const char *arg)
  431. {    FILE *f;
  432. #define cstr_max 128
  433.     char cstr[cstr_max + 1];
  434.     arg++;        /* skip over @ */
  435.     f = fopen(arg, "r");
  436.     if ( f == NULL )
  437.     {    fprintf(stdout, "Unable to open command line file %s\n", arg);
  438.         gs_exit(1);
  439.     }
  440.     while ( 1 )
  441.     {    register int c;
  442.         register int i;
  443.         while ( isspace(c = fgetc(f)) ) ;
  444.         if ( c == EOF ) break;
  445.         for ( i = 0; ; )
  446.         {    if ( i == cstr_max )
  447.             {    cstr[i] = 0;
  448.                 fprintf(stdout, "Command too long: %s\n", cstr);
  449.                 gs_exit(1);
  450.             }
  451.             cstr[i++] = c;
  452.             c = fgetc(f);
  453.             if ( c == EOF || isspace(c) )
  454.                 break;
  455.         }
  456.         cstr[i] = 0;
  457.         switch ( cstr[0] )
  458.         {
  459.         case '@':
  460.             cmdproc(cstr);
  461.             break;
  462.         case '-':
  463.         {    /* swproc wants strings to be in the heap! */
  464.             char *sstr = gs_malloc(i + 1, 1, "cmdproc");
  465.             if ( sstr == 0 )
  466.             {    lprintf("Out of memory!\n");
  467.                 gs_exit(1);
  468.             }
  469.             strcpy(sstr, cstr);
  470.             if ( swproc(sstr) < 0 )
  471.               fprintf(stdout, "Unknown switch %s - ignoring\n", sstr);
  472.         }
  473.             break;
  474.         default:
  475.             argproc(cstr);
  476.         }
  477.     }
  478.     fclose(f);
  479. }
  480.  
  481. /* Print the revision and revision date. */
  482. private void
  483. print_revision()
  484. {    int sub_rev = gs_revision % 10;
  485.     fprintf(stdout, "%s %d.%d", PROGRAM_NAME, gs_revision / 100,
  486.         (gs_revision / 10) % 10);
  487.     if ( sub_rev != 0 ) fprintf(stdout, ".%d", sub_rev);
  488.     fprintf(stdout, " (%s)\n", gs_revisiondate);
  489. }
  490.