1 /* Copyright (C) 1996-2001 Ghostgum Software Pty Ltd. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: iapi.c,v 1.12 2004/08/19 19:33:09 stefan Exp $ */
18
19 /* Public Application Programming Interface to Ghostscript interpreter */
20
21 #include "string_.h"
22 #include "ierrors.h"
23 #include "gscdefs.h"
24 #include "gstypes.h"
25 #include "iapi.h" /* Public API */
26 #include "iref.h"
27 #include "iminst.h"
28 #include "imain.h"
29 #include "imainarg.h"
30 #include "gsmemory.h"
31 #include "gsmalloc.h"
32 #include "gslibctx.h"
33
34 /* number of threads to allow per process
35 * currently more than 1 is guarenteed to fail
36 */
37 static int gsapi_instance_counter = 0;
38 static const int gsapi_instance_max = 1;
39
40 /* Return revision numbers and strings of Ghostscript. */
41 /* Used for determining if wrong GSDLL loaded. */
42 /* This may be called before any other function. */
43 GSDLLEXPORT int GSDLLAPI
gsapi_revision(gsapi_revision_t * pr,int rvsize)44 gsapi_revision(gsapi_revision_t *pr, int rvsize)
45 {
46 if (rvsize < sizeof(gsapi_revision_t))
47 return sizeof(gsapi_revision_t);
48 pr->product = gs_product;
49 pr->copyright = gs_copyright;
50 pr->revision = gs_revision;
51 pr->revisiondate = gs_revisiondate;
52 return 0;
53 }
54
55 /* Create a new instance of Ghostscript.
56 * First instance per process call with *pinstance == NULL
57 * next instance in a proces call with *pinstance == copy of valid_instance pointer
58 * *pinstance is set to a new instance pointer.
59 */
60 GSDLLEXPORT int GSDLLAPI
gsapi_new_instance(void ** pinstance,void * caller_handle)61 gsapi_new_instance(void **pinstance, void *caller_handle)
62 {
63 gs_memory_t *mem = NULL;
64 gs_main_instance *minst = NULL;
65
66 if (pinstance == NULL)
67 return e_Fatal;
68
69 /* limited to 1 instance, till it works :) */
70 if ( gsapi_instance_counter >= gsapi_instance_max )
71 return e_Fatal;
72 ++gsapi_instance_counter;
73
74 if (*pinstance == NULL)
75 /* first instance in this process */
76 mem = gs_malloc_init(NULL);
77 else {
78 /* nothing different for second thread initialization
79 * seperate memory, ids, only stdio is process shared.
80 */
81 mem = gs_malloc_init(NULL);
82
83 }
84 minst = gs_main_alloc_instance(mem);
85 mem->gs_lib_ctx->top_of_system = (void*) minst;
86 mem->gs_lib_ctx->caller_handle = caller_handle;
87 mem->gs_lib_ctx->stdin_fn = NULL;
88 mem->gs_lib_ctx->stdout_fn = NULL;
89 mem->gs_lib_ctx->stderr_fn = NULL;
90 mem->gs_lib_ctx->poll_fn = NULL;
91
92 *pinstance = (void*)(mem->gs_lib_ctx);
93 return 0;
94 }
95
96 /* Destroy an instance of Ghostscript */
97 /* We do not support multiple instances, so make sure
98 * we use the default instance only once.
99 */
100 GSDLLEXPORT void GSDLLAPI
gsapi_delete_instance(void * lib)101 gsapi_delete_instance(void *lib)
102 {
103 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
104 if ((ctx != NULL)) {
105 ctx->caller_handle = NULL;
106 ctx->stdin_fn = NULL;
107 ctx->stdout_fn = NULL;
108 ctx->stderr_fn = NULL;
109 ctx->poll_fn = NULL;
110 get_minst_from_memory(ctx->memory)->display = NULL;
111
112 /* NB: notice how no deletions are occuring, good bet this isn't thread ready
113 */
114
115 --gsapi_instance_counter;
116
117
118 }
119 }
120
121 /* Set the callback functions for stdio */
122 GSDLLEXPORT int GSDLLAPI
gsapi_set_stdio(void * lib,int (GSDLLCALL * stdin_fn)(void * caller_handle,char * buf,int len),int (GSDLLCALL * stdout_fn)(void * caller_handle,const char * str,int len),int (GSDLLCALL * stderr_fn)(void * caller_handle,const char * str,int len))123 gsapi_set_stdio(void *lib,
124 int(GSDLLCALL *stdin_fn)(void *caller_handle, char *buf, int len),
125 int(GSDLLCALL *stdout_fn)(void *caller_handle, const char *str, int len),
126 int(GSDLLCALL *stderr_fn)(void *caller_handle, const char *str, int len))
127 {
128 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
129 if (lib == NULL)
130 return e_Fatal;
131 ctx->stdin_fn = stdin_fn;
132 ctx->stdout_fn = stdout_fn;
133 ctx->stderr_fn = stderr_fn;
134 return 0;
135 }
136
137 /* Set the callback function for polling */
138 GSDLLEXPORT int GSDLLAPI
gsapi_set_poll(void * lib,int (GSDLLCALL * poll_fn)(void * caller_handle))139 gsapi_set_poll(void *lib,
140 int(GSDLLCALL *poll_fn)(void *caller_handle))
141 {
142 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
143 if (lib == NULL)
144 return e_Fatal;
145 ctx->poll_fn = poll_fn;
146 return 0;
147 }
148
149 /* Set the display callback structure */
150 GSDLLEXPORT int GSDLLAPI
gsapi_set_display_callback(void * lib,display_callback * callback)151 gsapi_set_display_callback(void *lib, display_callback *callback)
152 {
153 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
154 if (lib == NULL)
155 return e_Fatal;
156 get_minst_from_memory(ctx->memory)->display = callback;
157 /* not in a language switched build */
158 return 0;
159 }
160
161
162 /* Initialise the interpreter */
163 GSDLLEXPORT int GSDLLAPI
gsapi_init_with_args(void * lib,int argc,char ** argv)164 gsapi_init_with_args(void *lib, int argc, char **argv)
165 {
166 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
167 if (lib == NULL)
168 return e_Fatal;
169 return gs_main_init_with_args(get_minst_from_memory(ctx->memory), argc, argv);
170 }
171
172
173
174 /* The gsapi_run_* functions are like gs_main_run_* except
175 * that the error_object is omitted.
176 * An error object in minst is used instead.
177 */
178
179 /* Setup up a suspendable run_string */
180 GSDLLEXPORT int GSDLLAPI
gsapi_run_string_begin(void * lib,int user_errors,int * pexit_code)181 gsapi_run_string_begin(void *lib, int user_errors,
182 int *pexit_code)
183 {
184 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
185 if (lib == NULL)
186 return e_Fatal;
187
188 return gs_main_run_string_begin(get_minst_from_memory(ctx->memory),
189 user_errors, pexit_code,
190 &(get_minst_from_memory(ctx->memory)->error_object));
191 }
192
193
194 GSDLLEXPORT int GSDLLAPI
gsapi_run_string_continue(void * lib,const char * str,uint length,int user_errors,int * pexit_code)195 gsapi_run_string_continue(void *lib,
196 const char *str, uint length, int user_errors, int *pexit_code)
197 {
198 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
199 if (lib == NULL)
200 return e_Fatal;
201
202 return gs_main_run_string_continue(get_minst_from_memory(ctx->memory),
203 str, length, user_errors, pexit_code,
204 &(get_minst_from_memory(ctx->memory)->error_object));
205 }
206
207 GSDLLEXPORT int GSDLLAPI
gsapi_run_string_end(void * lib,int user_errors,int * pexit_code)208 gsapi_run_string_end(void *lib,
209 int user_errors, int *pexit_code)
210 {
211 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
212 if (lib == NULL)
213 return e_Fatal;
214
215 return gs_main_run_string_end(get_minst_from_memory(ctx->memory),
216 user_errors, pexit_code,
217 &(get_minst_from_memory(ctx->memory)->error_object));
218 }
219
220 GSDLLEXPORT int GSDLLAPI
gsapi_run_string_with_length(void * lib,const char * str,uint length,int user_errors,int * pexit_code)221 gsapi_run_string_with_length(void *lib,
222 const char *str, uint length, int user_errors, int *pexit_code)
223 {
224 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
225 if (lib == NULL)
226 return e_Fatal;
227
228 return gs_main_run_string_with_length(get_minst_from_memory(ctx->memory),
229 str, length, user_errors, pexit_code,
230 &(get_minst_from_memory(ctx->memory)->error_object));
231 }
232
233 GSDLLEXPORT int GSDLLAPI
gsapi_run_string(void * lib,const char * str,int user_errors,int * pexit_code)234 gsapi_run_string(void *lib,
235 const char *str, int user_errors, int *pexit_code)
236 {
237 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
238 return gsapi_run_string_with_length(get_minst_from_memory(ctx->memory),
239 str, (uint)strlen(str), user_errors, pexit_code);
240 }
241
242 GSDLLEXPORT int GSDLLAPI
gsapi_run_file(void * lib,const char * file_name,int user_errors,int * pexit_code)243 gsapi_run_file(void *lib, const char *file_name,
244 int user_errors, int *pexit_code)
245 {
246 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
247 if (lib == NULL)
248 return e_Fatal;
249
250 return gs_main_run_file(get_minst_from_memory(ctx->memory),
251 file_name, user_errors, pexit_code,
252 &(get_minst_from_memory(ctx->memory)->error_object));
253 }
254
255
256 /* Exit the interpreter */
257 GSDLLEXPORT int GSDLLAPI
gsapi_exit(void * lib)258 gsapi_exit(void *lib)
259 {
260 gs_lib_ctx_t *ctx = (gs_lib_ctx_t *)lib;
261 if (lib == NULL)
262 return e_Fatal;
263
264 gs_to_exit(ctx->memory, 0);
265 return 0;
266 }
267
268 /* Visual tracer : */
269 struct vd_trace_interface_s;
270 extern struct vd_trace_interface_s * vd_trace0;
271 GSDLLEXPORT void GSDLLAPI
gsapi_set_visual_tracer(struct vd_trace_interface_s * I)272 gsapi_set_visual_tracer(struct vd_trace_interface_s *I)
273 { vd_trace0 = I;
274 }
275
276 /* end of iapi.c */
277