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