1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: gs.c 9043 2008-08-28 22:48:19Z giles $ */
15 /* 'main' program for Ghostscript */
16 #include "ghost.h"
17 #include "imain.h"
18 #include "imainarg.h"
19 #include "iapi.h"
20 #include "iminst.h"
21 #include "ierrors.h"
22 #include "gsmalloc.h"
23
24 #ifdef __GNUC__
25 # if (__GNUC__ == 2 && __GNUC_MINOR__ == 96)
26 # define NEED_COMMIT_STACK 1
27 # endif
28 #endif
29
30
31 /* Define an optional array of strings for testing. */
32 /*#define RUN_STRINGS */
33 #ifdef RUN_STRINGS
34 static const char *run_strings[] =
35 {
36 "2 vmreclaim /SAVE save def 2 vmreclaim",
37 "(saved\n) print flush",
38 "SAVE restore (restored\n) print flush 2 vmreclaim",
39 "(done\n) print flush quit",
40 0
41 };
42
43 #endif
44
45 #ifdef NEED_COMMIT_STACK
46 /*
47 * It is well known that GCC 2.96 for x86 sometimes forgets to adjust $esp
48 * and leaves automatic variables at small distance below the stack pointer.
49 * Apparently, when the access to the automatic variable causes a page fault
50 * Linux sends a SEGV signal if the access happens below the stack pointer.
51 * Pre-loading the stack pages resolves the problem.
52 */
53 static void
commit_stack_pages(void)54 commit_stack_pages( void )
55 {
56 char buf[65536]; /* In most cases GS lives in 64K stack */
57 int i;
58 for ( i = 0; i < sizeof(buf) - 1; i += 1024)
59 buf[i] = 0;
60 }
61 #endif
62
63
64 int
main(int argc,char * argv[])65 main(int argc, char *argv[])
66 {
67 int exit_status, code;
68 gs_main_instance *minst;
69 gs_memory_t *mem;
70
71 #ifdef NEED_COMMIT_STACK /* hack for bug in gcc 2.96 */
72 commit_stack_pages();
73 #endif
74 exit_status = 0;
75 mem = gs_malloc_init(NULL);
76 minst = gs_main_alloc_instance(mem);
77 code = gs_main_init_with_args(minst, argc, argv);
78
79 #ifdef RUN_STRINGS
80 { /* Run a list of strings (for testing). */
81 const char **pstr = run_strings;
82
83 for (; *pstr; ++pstr) {
84 int exit_code;
85 ref error_object;
86 int code;
87
88 fprintf(stdout, "{%s} =>\n", *pstr);
89 fflush(stdout);
90 code = gs_main_run_string(minst, *pstr, 0,
91 &exit_code, &error_object);
92 zflush(osp);
93 fprintf(stdout, " => code = %d\n", code);
94 fflush(stdout);
95 if (code < 0) {
96 gs_to_exit(1);
97 return 1;
98 }
99 }
100 }
101 #endif
102
103 if (code >= 0)
104 code = gs_main_run_start(minst);
105
106 exit_status = 0;
107 switch (code) {
108 case 0:
109 case e_Info:
110 case e_Quit:
111 break;
112 case e_Fatal:
113 exit_status = 1;
114 break;
115 default:
116 exit_status = 255;
117 }
118
119 gs_to_exit_with_code(minst->heap, exit_status, code);
120 gs_malloc_release(mem);
121
122 switch (exit_status) {
123 case 0:
124 exit_status = exit_OK;
125 break;
126 case 1:
127 exit_status = exit_FAILED;
128 break;
129 }
130 return exit_status;
131 }
132