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/>. */
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 */
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",
49 "process_input_buffer", "process_output_buffer",
51 "start_page_number", "stop_page_number",
52 "start_run", "stop_run",
56 "hpack_filter", "vpack_filter",
61 "pre_linebreak_filter",
63 "post_linebreak_filter",
64 "append_to_vlist_filter",
68 "pre_dump","start_file", "stop_file",
69 "show_error_message","show_lua_error_hook",
70 "show_warning_message",
71 "hpack_quality", "vpack_quality",
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)) {
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
);
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)) {
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
);
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
);
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
);
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
);
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
);
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
, ...)
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
);
204 if (lua_isfunction(L
, -1)) {
205 saved_callback_count
++;
207 ret
= do_run_callback(2, values
, args
);
210 lua_settop(L
, stacktop
);
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)) {
227 int run_and_save_callback(int i
, const char *values
, ...)
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
);
239 ret
= luaL_ref(L
, LUA_REGISTRYINDEX
);
241 lua_settop(L
, stacktop
);
245 int run_callback(int i
, const char *values
, ...)
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
);
256 lua_settop(L
, stacktop
);
260 int do_run_callback(int special
, const char *values
, va_list vl
)
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");
279 for (narg
= 0; *values
; narg
++) {
281 case CALLBACK_CHARNUM
: /* an ascii char! */
282 cs
= (char) va_arg(vl
, int);
283 lua_pushlstring(L
, &cs
, 1);
285 case CALLBACK_STRING
: /* C string */
286 s
= va_arg(vl
, char *);
287 lua_pushstring(L
, s
);
289 case CALLBACK_LSTRING
: /* 'lstring' */
290 lstr
= va_arg(vl
, lstring
*);
291 lua_pushlstring(L
, (const char *)lstr
->s
, lstr
->l
);
293 case CALLBACK_INTEGER
: /* int */
294 lua_pushinteger(L
, va_arg(vl
, int));
296 case CALLBACK_STRNUMBER
: /* TeX string */
297 s
= makeclstring(va_arg(vl
, int), &len
);
298 lua_pushlstring(L
, s
, len
);
300 case CALLBACK_BOOLEAN
: /* boolean */
301 lua_pushboolean(L
, va_arg(vl
, int));
303 case CALLBACK_LINE
: /* a buffer section, with implied start */
304 lua_pushlstring(L
, (char *) (buffer
+ first
), (size_t) va_arg(vl
, int));
307 lua_nodelib_push_fast(L
,va_arg(vl
, int));
310 lua_push_dir_par(L
,va_arg(vl
, int));
322 nres
= (int) strlen(values
);
332 i
= lua_pcall(L
, narg
, nres
, 0);
334 /* lua_remove(L, base); *//* remove traceback function */
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));
343 lua_gc(L
, LUA_GCCOLLECT
, 0);
344 luatex_error(L
, (i
== LUA_ERRRUN
? 0 : 1));
356 t
= lua_type(L
, nres
);
358 case CALLBACK_BOOLEAN
:
361 } else if (t
!= LUA_TBOOLEAN
) {
362 fprintf(stderr
, "callback should return a boolean, not: %s\n", lua_typename(L
, t
));
365 b
= lua_toboolean(L
, nres
);
367 *va_arg(vl
, boolean
*) = (boolean
) b
;
369 case CALLBACK_INTEGER
:
370 if (t
!= LUA_TNUMBER
) {
371 fprintf(stderr
, "callback should return a number, not: %s\n", lua_typename(L
, t
));
374 b
= lua_tointeger(L
, nres
);
375 *va_arg(vl
, int *) = b
;
377 case CALLBACK_LINE
: /* TeX line ... happens frequently when we have a plug-in */
381 } else if (t
== LUA_TSTRING
) {
382 s
= lua_tolstring(L
, nres
, &len
);
383 if (s
== NULL
) { /* |len| can be zero */
385 } else if (len
== 0) {
388 bufloc
= va_arg(vl
, int *);
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] == ' ')
398 fprintf(stderr
, "callback should return a string, not: %s\n", lua_typename(L
, t
));
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
));
407 s
= lua_tolstring(L
, nres
, &len
);
408 if (s
== NULL
) /* |len| can be zero */
409 *va_arg(vl
, int *) = 0;
411 *va_arg(vl
, int *) = maketexlstring(s
, len
);
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
));
419 s
= lua_tolstring(L
, nres
, &len
);
420 if (s
== NULL
) /* |len| can be zero */
421 *va_arg(vl
, int *) = 0;
423 ss
= xmalloc((unsigned) (len
+ 1));
424 (void) memcpy(ss
, s
, (len
+ 1));
425 *va_arg(vl
, char **) = ss
;
428 case CALLBACK_RESULT
: /* C string aka buffer */
430 *va_arg(vl
, int *) = 0;
431 } else if (t
== LUA_TBOOLEAN
) {
432 b
= lua_toboolean(L
, nres
);
434 *va_arg(vl
, int *) = 0;
436 fprintf(stderr
, "callback should return a string, false or nil, not: %s\n", lua_typename(L
, t
));
439 } else if (t
!= LUA_TSTRING
) {
440 fprintf(stderr
, "callback should return a string, false or nil, not: %s\n", lua_typename(L
, t
));
443 s
= lua_tolstring(L
, nres
, &len
);
444 if (s
== NULL
) /* |len| can be zero */
445 *va_arg(vl
, int *) = 0;
447 ss
= xmalloc((unsigned) (len
+ 1));
448 (void) memcpy(ss
, s
, (len
+ 1));
449 *va_arg(vl
, char **) = ss
;
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
));
458 s
= lua_tolstring(L
, nres
, &len
);
459 if (s
== NULL
) /* |len| can be zero */
460 *va_arg(vl
, int *) = 0;
462 lstring
*ret
= xmalloc(sizeof(lstring
));
463 ret
->s
= xmalloc((unsigned) (len
+ 1));
464 (void) memcpy(ret
->s
, s
, (len
+ 1));
466 *va_arg(vl
, lstring
**) = ret
;
473 p
= *check_isnode(L
,nres
);
475 *va_arg(vl
, int *) = p
;
478 fprintf(stdout
, "callback returned an invalid value type");
488 void destroy_saved_callback(int i
)
490 luaL_unref(Luas
, LUA_REGISTRYINDEX
, i
);
493 static int callback_register(lua_State
* L
)
497 int t1
= lua_type(L
,1);
498 int t2
= lua_type(L
,2);
499 if (t1
!= LUA_TSTRING
) {
501 lua_pushstring(L
, "Invalid arguments to callback.register, first argument must be string.");
504 if ((t2
!= LUA_TFUNCTION
) && (t2
!= LUA_TNIL
) && ((t2
!= LUA_TBOOLEAN
) && (lua_toboolean(L
, 2) == 0))) {
506 lua_pushstring(L
, "Invalid arguments to callback.register.");
509 s
= lua_tostring(L
, 1);
510 for (cb
= 0; cb
< total_callbacks
; cb
++) {
511 if (strcmp(callbacknames
[cb
], s
) == 0)
514 if (cb
== total_callbacks
) {
516 lua_pushstring(L
, "No such callback exists.");
519 if (t2
== LUA_TFUNCTION
) {
520 callback_set
[cb
] = cb
;
521 } else if (t2
== LUA_TBOOLEAN
) {
522 callback_set
[cb
] = -1;
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
);
535 static int callback_find(lua_State
* L
)
539 if (lua_type(L
, 1) != LUA_TSTRING
) {
541 lua_pushstring(L
, "Invalid arguments to callback.find.");
544 s
= lua_tostring(L
, 1);
545 for (cb
= 0; cb
< total_callbacks
; cb
++) {
546 if (strcmp(callbacknames
[cb
], s
) == 0)
549 if (cb
== total_callbacks
) {
551 lua_pushstring(L
, "No such callback exists.");
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
);
560 static int callback_listf(lua_State
* L
)
563 luaL_checkstack(L
, 3, "out of stack space");
565 for (i
= 1; callbacknames
[i
]; i
++) {
566 lua_pushstring(L
, callbacknames
[i
]);
567 if (callback_defined(i
)) {
568 lua_pushboolean(L
, 1);
570 lua_pushboolean(L
, 0);
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");
589 callback_callbacks_id
= luaL_ref(L
, LUA_REGISTRYINDEX
);