xref: /plan9/sys/src/cmd/gs/src/iapi.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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