beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / lua / lcallbacklib.c
blob3abe333ec60454ce4a67dc6c3ad64dc38fab153e
1 /* lcallbacklib.c
3 Copyright 2006-2008 Taco Hoekwater <taco@luatex.org>
5 This file is part of LuaTeX.
7 LuaTeX is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version.
12 LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License along
18 with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
20 #include "ptexlib.h"
21 #include "lua/luatex-api.h"
23 int callback_count = 0;
24 int saved_callback_count = 0;
26 int callback_set[total_callbacks] = { 0 };
28 /* See also callback_callback_type in luatexcallbackids.h: they must have the same order ! */
30 static const char *const callbacknames[] = {
31 "", /* empty on purpose */
32 "find_write_file",
33 "find_output_file",
34 "find_image_file",
35 "find_format_file",
36 "find_read_file", "open_read_file",
37 "find_vf_file", "read_vf_file",
38 "find_data_file", "read_data_file",
39 "find_font_file", "read_font_file",
40 "find_map_file", "read_map_file",
41 "find_enc_file", "read_enc_file",
42 "find_type1_file", "read_type1_file",
43 "find_truetype_file", "read_truetype_file",
44 "find_opentype_file", "read_opentype_file",
45 "find_sfd_file", "read_sfd_file",
46 "find_cidmap_file", "read_cidmap_file",
47 "find_pk_file", "read_pk_file",
48 "show_error_hook",
49 "process_input_buffer", "process_output_buffer",
50 "process_jobname",
51 "start_page_number", "stop_page_number",
52 "start_run", "stop_run",
53 "define_font",
54 "pre_output_filter",
55 "buildpage_filter",
56 "hpack_filter", "vpack_filter",
57 "char_exists",
58 "hyphenate",
59 "ligaturing",
60 "kerning",
61 "pre_linebreak_filter",
62 "linebreak_filter",
63 "post_linebreak_filter",
64 "append_to_vlist_filter",
65 "mlist_to_hlist",
66 "finish_pdffile",
67 "finish_pdfpage",
68 "pre_dump","start_file", "stop_file",
69 "show_error_message","show_lua_error_hook",
70 "show_warning_message",
71 "hpack_quality", "vpack_quality",
72 "process_rule",
73 NULL
76 int callback_callbacks_id = 0;
78 int debug_callback_defined(int i)
80 printf ("callback_defined(%s)\n", callbacknames[i]);
81 return callback_set[i];
84 void get_lua_boolean(const char *table, const char *name, boolean * target)
86 int stacktop = lua_gettop(Luas);
87 luaL_checkstack(Luas, 2, "out of stack space");
88 lua_getglobal(Luas, table);
89 if (lua_istable(Luas, -1)) {
90 int t;
91 lua_getfield(Luas, -1, name);
92 t = lua_type(Luas, -1);
93 if (t == LUA_TBOOLEAN) {
94 *target = (boolean) (lua_toboolean(Luas, -1));
95 } else if (t == LUA_TNUMBER) {
96 *target = (boolean) (lua_tointeger(Luas, -1) == 0 ? 0 : 1);
99 lua_settop(Luas, stacktop);
100 return;
103 void get_saved_lua_boolean(int r, const char *name, boolean * target)
105 int stacktop = lua_gettop(Luas);
106 luaL_checkstack(Luas, 2, "out of stack space");
107 lua_rawgeti(Luas, LUA_REGISTRYINDEX, r);
108 if (lua_istable(Luas, -1)) {
109 int t;
110 lua_getfield(Luas, -1, name);
111 t = lua_type(Luas, -1);
112 if (t == LUA_TBOOLEAN) {
113 *target = (boolean) lua_toboolean(Luas, -1);
114 } else if (t == LUA_TNUMBER) {
115 *target = (boolean) (lua_tointeger(Luas, -1) == 0 ? 0 : 1);
118 lua_settop(Luas, stacktop);
119 return;
122 void get_lua_number(const char *table, const char *name, int *target)
124 int stacktop = lua_gettop(Luas);
125 luaL_checkstack(Luas, 2, "out of stack space");
126 lua_getglobal(Luas, table);
127 if (lua_istable(Luas, -1)) {
128 lua_getfield(Luas, -1, name);
129 if (lua_type(Luas, -1) == LUA_TNUMBER) {
130 *target = (int) lua_tointeger(Luas, -1);
133 lua_settop(Luas, stacktop);
134 return;
137 void get_saved_lua_number(int r, const char *name, int *target)
139 int stacktop = lua_gettop(Luas);
140 luaL_checkstack(Luas, 2, "out of stack space");
141 lua_rawgeti(Luas, LUA_REGISTRYINDEX, r);
142 if (lua_istable(Luas, -1)) {
143 lua_getfield(Luas, -1, name);
144 if (lua_type(Luas, -1) == LUA_TNUMBER) {
145 *target = (int) lua_tointeger(Luas, -1);
148 lua_settop(Luas, stacktop);
149 return;
152 void get_lua_string(const char *table, const char *name, char **target)
154 int stacktop = lua_gettop(Luas);
155 luaL_checkstack(Luas, 2, "out of stack space");
156 lua_getglobal(Luas, table);
157 if (lua_type(Luas, -1) == LUA_TTABLE) {
158 lua_getfield(Luas, -1, name);
159 if (lua_type(Luas, -1) == LUA_TSTRING) {
160 *target = xstrdup(lua_tostring(Luas, -1));
163 lua_settop(Luas, stacktop);
164 return;
167 void get_saved_lua_string(int r, const char *name, char **target)
169 int stacktop = lua_gettop(Luas);
170 luaL_checkstack(Luas, 2, "out of stack space");
171 lua_rawgeti(Luas, LUA_REGISTRYINDEX, r);
172 if (lua_type(Luas, -1) == LUA_TTABLE) {
173 lua_getfield(Luas, -1, name);
174 if (lua_type(Luas, -1) == LUA_TSTRING) {
175 *target = xstrdup(lua_tostring(Luas, -1));
178 lua_settop(Luas, stacktop);
179 return;
182 #define CALLBACK_BOOLEAN 'b'
183 #define CALLBACK_INTEGER 'd'
184 #define CALLBACK_LINE 'l'
185 #define CALLBACK_STRNUMBER 's'
186 #define CALLBACK_STRING 'S'
187 #define CALLBACK_RESULT 'R' /* a string but nil is also ok */
188 #define CALLBACK_CHARNUM 'c'
189 #define CALLBACK_LSTRING 'L'
190 #define CALLBACK_NODE 'N'
191 #define CALLBACK_DIR 'D'
193 int run_saved_callback(int r, const char *name, const char *values, ...)
195 va_list args;
196 int ret = 0;
197 lua_State *L = Luas;
198 int stacktop = lua_gettop(L);
199 va_start(args, values);
200 luaL_checkstack(L, 2, "out of stack space");
201 lua_rawgeti(L, LUA_REGISTRYINDEX, r);
202 lua_pushstring(L, name);
203 lua_rawget(L, -2);
204 if (lua_isfunction(L, -1)) {
205 saved_callback_count++;
206 callback_count++;
207 ret = do_run_callback(2, values, args);
209 va_end(args);
210 lua_settop(L, stacktop);
211 return ret;
214 boolean get_callback(lua_State * L, int i)
216 luaL_checkstack(L, 2, "out of stack space");
217 lua_rawgeti(L, LUA_REGISTRYINDEX, callback_callbacks_id);
218 lua_rawgeti(L, -1, i);
219 if (lua_isfunction(L, -1)) {
220 callback_count++;
221 return true;
222 } else {
223 return false;
227 int run_and_save_callback(int i, const char *values, ...)
229 va_list args;
230 int ret = 0;
231 lua_State *L = Luas;
232 int stacktop = lua_gettop(L);
233 va_start(args, values);
234 if (get_callback(L, i)) {
235 ret = do_run_callback(1, values, args);
237 va_end(args);
238 if (ret > 0) {
239 ret = luaL_ref(L, LUA_REGISTRYINDEX);
241 lua_settop(L, stacktop);
242 return ret;
245 int run_callback(int i, const char *values, ...)
247 va_list args;
248 int ret = 0;
249 lua_State *L = Luas;
250 int stacktop = lua_gettop(L);
251 va_start(args, values);
252 if (get_callback(L, i)) {
253 ret = do_run_callback(0, values, args);
255 va_end(args);
256 lua_settop(L, stacktop);
257 return ret;
260 int do_run_callback(int special, const char *values, va_list vl)
262 int ret;
263 size_t len;
264 int narg, nres;
265 const char *s;
266 lstring *lstr;
267 char cs;
268 int *bufloc;
269 char *ss = NULL;
270 int retval = 0;
271 lua_State *L = Luas;
272 if (special == 2) { /* copy the enclosing table */
273 luaL_checkstack(L, 1, "out of stack space");
274 lua_pushvalue(L, -2);
276 ss = strchr(values, '>');
277 luaL_checkstack(L, (int) (ss - values + 1), "out of stack space");
278 ss = NULL;
279 for (narg = 0; *values; narg++) {
280 switch (*values++) {
281 case CALLBACK_CHARNUM: /* an ascii char! */
282 cs = (char) va_arg(vl, int);
283 lua_pushlstring(L, &cs, 1);
284 break;
285 case CALLBACK_STRING: /* C string */
286 s = va_arg(vl, char *);
287 lua_pushstring(L, s);
288 break;
289 case CALLBACK_LSTRING: /* 'lstring' */
290 lstr = va_arg(vl, lstring *);
291 lua_pushlstring(L, (const char *)lstr->s, lstr->l);
292 break;
293 case CALLBACK_INTEGER: /* int */
294 lua_pushinteger(L, va_arg(vl, int));
295 break;
296 case CALLBACK_STRNUMBER: /* TeX string */
297 s = makeclstring(va_arg(vl, int), &len);
298 lua_pushlstring(L, s, len);
299 break;
300 case CALLBACK_BOOLEAN: /* boolean */
301 lua_pushboolean(L, va_arg(vl, int));
302 break;
303 case CALLBACK_LINE: /* a buffer section, with implied start */
304 lua_pushlstring(L, (char *) (buffer + first), (size_t) va_arg(vl, int));
305 break;
306 case CALLBACK_NODE:
307 lua_nodelib_push_fast(L,va_arg(vl, int));
308 break;
309 case CALLBACK_DIR:
310 lua_push_dir_par(L,va_arg(vl, int));
311 break;
312 case '-':
313 narg--;
314 break;
315 case '>':
316 goto ENDARGS;
317 default:
321 ENDARGS:
322 nres = (int) strlen(values);
323 if (special == 1) {
324 nres++;
326 if (special == 2) {
327 narg++;
330 int i;
331 lua_active++;
332 i = lua_pcall(L, narg, nres, 0);
333 lua_active--;
334 /* lua_remove(L, base); *//* remove traceback function */
335 if (i != 0) {
336 /* Can't be more precise here, could be called before
337 * TeX initialization is complete
339 if (!log_opened_global) {
340 fprintf(stderr, "error in callback: %s\n", lua_tostring(L, -1));
341 error();
342 } else {
343 lua_gc(L, LUA_GCCOLLECT, 0);
344 luatex_error(L, (i == LUA_ERRRUN ? 0 : 1));
346 return 0;
349 if (nres == 0) {
350 return 1;
352 nres = -nres;
353 while (*values) {
354 int b, t;
355 halfword p;
356 t = lua_type(L, nres);
357 switch (*values++) {
358 case CALLBACK_BOOLEAN:
359 if (t == LUA_TNIL) {
360 b = 0;
361 } else if (t != LUA_TBOOLEAN) {
362 fprintf(stderr, "callback should return a boolean, not: %s\n", lua_typename(L, t));
363 goto EXIT;
364 } else {
365 b = lua_toboolean(L, nres);
367 *va_arg(vl, boolean *) = (boolean) b;
368 break;
369 case CALLBACK_INTEGER:
370 if (t != LUA_TNUMBER) {
371 fprintf(stderr, "callback should return a number, not: %s\n", lua_typename(L, t));
372 goto EXIT;
374 b = lua_tointeger(L, nres);
375 *va_arg(vl, int *) = b;
376 break;
377 case CALLBACK_LINE: /* TeX line ... happens frequently when we have a plug-in */
378 if (t == LUA_TNIL) {
379 bufloc = 0;
380 goto EXIT;
381 } else if (t == LUA_TSTRING) {
382 s = lua_tolstring(L, nres, &len);
383 if (s == NULL) { /* |len| can be zero */
384 bufloc = 0;
385 } else if (len == 0) {
386 bufloc = 0;
387 } else {
388 bufloc = va_arg(vl, int *);
389 ret = *bufloc;
390 check_buffer_overflow(ret + (int) len);
391 strncpy((char *) (buffer + ret), s, len);
392 *bufloc += (int) len;
393 /* while (len--) { buffer[(*bufloc)++] = *s++; } */
394 while ((*bufloc) - 1 > ret && buffer[(*bufloc) - 1] == ' ')
395 (*bufloc)--;
397 } else {
398 fprintf(stderr, "callback should return a string, not: %s\n", lua_typename(L, t));
399 goto EXIT;
401 break;
402 case CALLBACK_STRNUMBER: /* TeX string */
403 if (t != LUA_TSTRING) {
404 fprintf(stderr, "callback should return a string, not: %s\n", lua_typename(L, t));
405 goto EXIT;
407 s = lua_tolstring(L, nres, &len);
408 if (s == NULL) /* |len| can be zero */
409 *va_arg(vl, int *) = 0;
410 else {
411 *va_arg(vl, int *) = maketexlstring(s, len);
413 break;
414 case CALLBACK_STRING: /* C string aka buffer */
415 if (t != LUA_TSTRING) {
416 fprintf(stderr, "callback should return a string, not: %s\n", lua_typename(L, t));
417 goto EXIT;
419 s = lua_tolstring(L, nres, &len);
420 if (s == NULL) /* |len| can be zero */
421 *va_arg(vl, int *) = 0;
422 else {
423 ss = xmalloc((unsigned) (len + 1));
424 (void) memcpy(ss, s, (len + 1));
425 *va_arg(vl, char **) = ss;
427 break;
428 case CALLBACK_RESULT: /* C string aka buffer */
429 if (t == LUA_TNIL) {
430 *va_arg(vl, int *) = 0;
431 } else if (t == LUA_TBOOLEAN) {
432 b = lua_toboolean(L, nres);
433 if (b == 0) {
434 *va_arg(vl, int *) = 0;
435 } else {
436 fprintf(stderr, "callback should return a string, false or nil, not: %s\n", lua_typename(L, t));
437 goto EXIT;
439 } else if (t != LUA_TSTRING) {
440 fprintf(stderr, "callback should return a string, false or nil, not: %s\n", lua_typename(L, t));
441 goto EXIT;
442 } else {
443 s = lua_tolstring(L, nres, &len);
444 if (s == NULL) /* |len| can be zero */
445 *va_arg(vl, int *) = 0;
446 else {
447 ss = xmalloc((unsigned) (len + 1));
448 (void) memcpy(ss, s, (len + 1));
449 *va_arg(vl, char **) = ss;
452 break;
453 case CALLBACK_LSTRING: /* lstring */
454 if (t != LUA_TSTRING) {
455 fprintf(stderr, "callback should return a string, not: %s\n", lua_typename(L, t));
456 goto EXIT;
458 s = lua_tolstring(L, nres, &len);
459 if (s == NULL) /* |len| can be zero */
460 *va_arg(vl, int *) = 0;
461 else {
462 lstring *ret = xmalloc(sizeof(lstring));
463 ret->s = xmalloc((unsigned) (len + 1));
464 (void) memcpy(ret->s, s, (len + 1));
465 ret->l = len;
466 *va_arg(vl, lstring **) = ret;
468 break;
469 case CALLBACK_NODE:
470 if (t == LUA_TNIL) {
471 p = null;
472 } else {
473 p = *check_isnode(L,nres);
475 *va_arg(vl, int *) = p;
476 break;
477 default:
478 fprintf(stdout, "callback returned an invalid value type");
479 goto EXIT;
481 nres++;
483 retval = 1;
484 EXIT:
485 return retval;
488 void destroy_saved_callback(int i)
490 luaL_unref(Luas, LUA_REGISTRYINDEX, i);
493 static int callback_register(lua_State * L)
495 int cb;
496 const char *s;
497 int t1 = lua_type(L,1);
498 int t2 = lua_type(L,2);
499 if (t1 != LUA_TSTRING) {
500 lua_pushnil(L);
501 lua_pushstring(L, "Invalid arguments to callback.register, first argument must be string.");
502 return 2;
504 if ((t2 != LUA_TFUNCTION) && (t2 != LUA_TNIL) && ((t2 != LUA_TBOOLEAN) && (lua_toboolean(L, 2) == 0))) {
505 lua_pushnil(L);
506 lua_pushstring(L, "Invalid arguments to callback.register.");
507 return 2;
509 s = lua_tostring(L, 1);
510 for (cb = 0; cb < total_callbacks; cb++) {
511 if (strcmp(callbacknames[cb], s) == 0)
512 break;
514 if (cb == total_callbacks) {
515 lua_pushnil(L);
516 lua_pushstring(L, "No such callback exists.");
517 return 2;
519 if (t2 == LUA_TFUNCTION) {
520 callback_set[cb] = cb;
521 } else if (t2 == LUA_TBOOLEAN) {
522 callback_set[cb] = -1;
523 } else {
524 callback_set[cb] = 0;
526 luaL_checkstack(L, 2, "out of stack space");
527 lua_rawgeti(L, LUA_REGISTRYINDEX, callback_callbacks_id); /* push the table */
528 lua_pushvalue(L, 2); /* the function or nil */
529 lua_rawseti(L, -2, cb);
530 lua_rawseti(L, LUA_REGISTRYINDEX, callback_callbacks_id);
531 lua_pushinteger(L, cb);
532 return 1;
535 static int callback_find(lua_State * L)
537 int cb;
538 const char *s;
539 if (lua_type(L, 1) != LUA_TSTRING) {
540 lua_pushnil(L);
541 lua_pushstring(L, "Invalid arguments to callback.find.");
542 return 2;
544 s = lua_tostring(L, 1);
545 for (cb = 0; cb < total_callbacks; cb++) {
546 if (strcmp(callbacknames[cb], s) == 0)
547 break;
549 if (cb == total_callbacks) {
550 lua_pushnil(L);
551 lua_pushstring(L, "No such callback exists.");
552 return 2;
554 luaL_checkstack(L, 2, "out of stack space");
555 lua_rawgeti(L, LUA_REGISTRYINDEX, callback_callbacks_id); /* push the table */
556 lua_rawgeti(L, -1, cb);
557 return 1;
560 static int callback_listf(lua_State * L)
562 int i;
563 luaL_checkstack(L, 3, "out of stack space");
564 lua_newtable(L);
565 for (i = 1; callbacknames[i]; i++) {
566 lua_pushstring(L, callbacknames[i]);
567 if (callback_defined(i)) {
568 lua_pushboolean(L, 1);
569 } else {
570 lua_pushboolean(L, 0);
572 lua_rawset(L, -3);
574 return 1;
577 static const struct luaL_Reg callbacklib[] = {
578 {"find", callback_find},
579 {"register", callback_register},
580 {"list", callback_listf},
581 {NULL, NULL} /* sentinel */
584 int luaopen_callback(lua_State * L)
586 luaL_register(L, "callback", callbacklib);
587 luaL_checkstack(L, 1, "out of stack space");
588 lua_newtable(L);
589 callback_callbacks_id = luaL_ref(L, LUA_REGISTRYINDEX);
590 return 1;