1
4
5# include "luametatex.h"
6# include "lmtoptional.h"
7
8# define GS_ARG_ENCODING_UTF8 1
9
10typedef struct gslib_state_info {
11
12 int initialized;
13 int padding;
14 luaL_Buffer outbuffer;
15 luaL_Buffer errbuffer;
16
17 int (*gsapi_new_instance) (
18 void **pinstance,
19 void *caller_handle
20 );
21
22 void (*gsapi_delete_instance) (
23 void * instance
24 );
25
26 int (*gsapi_set_arg_encoding) (
27 void *instance,
28 int encoding
29 );
30
31 int (*gsapi_init_with_args) (
32 void *instance,
33 int argc,
34 const char **argv
35 );
36
37 int (*gsapi_set_stdio) (
38 void *instance,
39 int (*stdin_fn )(void *caller_handle, char *buf, int len),
40 int (*stdout_fn)(void *caller_handle, const char *str, int len),
41 int (*stderr_fn)(void *caller_handle, const char *str, int len)
42 );
43
44
53
54} gslib_state_info;
55
56static gslib_state_info gslib_state = {
57
58 .initialized = 0,
59 .padding = 0,
60
61
62
63 .gsapi_new_instance = NULL,
64 .gsapi_delete_instance = NULL,
65 .gsapi_set_arg_encoding = NULL,
66 .gsapi_init_with_args = NULL,
67 .gsapi_set_stdio = NULL,
68
69};
70
71static int gslib_initialize(lua_State * L)
72{
73 if (! gslib_state.initialized) {
74 const char *filename = lua_tostring(L, 1);
75 if (filename) {
76
77 lmt_library lib = lmt_library_load(filename);
78
79 gslib_state.gsapi_new_instance = lmt_library_find(lib, "gsapi_new_instance");
80 gslib_state.gsapi_delete_instance = lmt_library_find(lib, "gsapi_delete_instance");
81 gslib_state.gsapi_set_arg_encoding = lmt_library_find(lib, "gsapi_set_arg_encoding");
82 gslib_state.gsapi_init_with_args = lmt_library_find(lib, "gsapi_init_with_args");
83 gslib_state.gsapi_set_stdio = lmt_library_find(lib, "gsapi_set_stdio");
84
85 gslib_state.initialized = lmt_library_okay(lib);
86 }
87 }
88 lua_pushboolean(L, gslib_state.initialized);
89 return 1;
90}
91
92
93
94static int gslib_stdout(void * caller_handle, const char *str, int len)
95{
96 (void)caller_handle;
97 luaL_addlstring(&gslib_state.outbuffer, str, len);
98 return len;
99}
100
101static int gslib_stderr(void * caller_handle, const char *str, int len)
102{
103 (void)caller_handle;
104 luaL_addlstring(&gslib_state.errbuffer, str, len);
105 return len;
106}
107
108static int gslib_execute(lua_State * L)
109{
110 if (gslib_state.initialized) {
111 if (lua_type(L, 1) == LUA_TTABLE) {
112 size_t n = (int) lua_rawlen(L, 1);
113 if (n > 0) {
114 void *instance = NULL;
115 int result = gslib_state.gsapi_new_instance(&instance, NULL);
116 if (result >= 0) {
117
122 const char** arguments = malloc((n + 2) * sizeof(char*));
123 if (arguments) {
124 int m = 1;
125
126 arguments[0] = "ghostscript";
127 luaL_buffinit(L, &gslib_state.outbuffer);
128 luaL_buffinit(L, &gslib_state.errbuffer);
129 gslib_state.gsapi_set_stdio(instance, NULL, &gslib_stdout, &gslib_stderr);
130 for (size_t i = 1; i <= n; i++) {
131 lua_rawgeti(L, 1, i);
132 switch (lua_type(L, -1)) {
133 case LUA_TSTRING:
134 case LUA_TNUMBER:
135 {
136 size_t l = 0;
137 const char *s = lua_tolstring(L, -1, &l);
138 if (l > 0) {
139 arguments[m] = s;
140 m += 1;
141 }
142 }
143 break;
144 }
145 lua_pop(L, 1);
146 }
147 arguments[m] = NULL;
148 result = gslib_state.gsapi_set_arg_encoding(instance, GS_ARG_ENCODING_UTF8);
149 result = gslib_state.gsapi_init_with_args(instance, m, arguments);
150 gslib_state.gsapi_delete_instance(instance);
151
152 free((void *) arguments);
153 lua_pushboolean(L, result >= 0);
154 luaL_pushresult(&gslib_state.outbuffer);
155 luaL_pushresult(&gslib_state.errbuffer);
156 return 3;
157 }
158 }
159 }
160 }
161 }
162 return 0;
163}
164
165static struct luaL_Reg gslib_function_list[] = {
166 { "initialize", gslib_initialize },
167 { "execute", gslib_execute },
168 { NULL, NULL },
169};
170
171int luaopen_ghostscript(lua_State * L)
172{
173 lmt_library_register(L, "ghostscript", gslib_function_list);
174 return 0;
175}
176 |