1 /* lstatslib.c
2
3 Copyright 2006-2011 Taco Hoekwater <taco@luatex.org>
4
5 This file is part of LuaTeX.
6
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.
11
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.
16
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/>. */
19
20
21 #include "ptexlib.h"
22 #include "lua/luatex-api.h"
23
24 typedef struct statistic {
25 const char *name;
26 char type;
27 void *value;
28 } statistic;
29
30 typedef const char *(*charfunc) (void);
31 typedef lua_Number(*numfunc) (void);
32 typedef int (*intfunc) (void);
33
34 const char *last_lua_error;
35
getbanner(void)36 static const char *getbanner(void)
37 {
38 return (const char *) luatex_banner;
39 }
40
getlogname(void)41 static const char *getlogname(void)
42 {
43 return (const char *) texmf_log_name;
44 }
45
46 /* Obsolete in 0.80.0 */
47 /* static const char *get_pdftex_banner(void) */
48 /* { */
49 /* return (const char *) pdftex_banner; */
50 /* } */
51
get_output_file_name(void)52 static const char *get_output_file_name(void)
53 {
54 if (static_pdf != NULL)
55 return (const char *) static_pdf->file_name;
56 return NULL;
57 }
58
getfilename(void)59 static const char *getfilename(void)
60 {
61 int t = 0;
62 int level = in_open;
63 while ((level > 0)) {
64 t = input_stack[level--].name_field;
65 if (t >= STRING_OFFSET)
66 return (const char *) str_string(t);
67 }
68 return "";
69 }
70
getlasterror(void)71 static const char *getlasterror(void)
72 {
73 return last_error;
74 }
75
getlastluaerror(void)76 static const char *getlastluaerror(void)
77 {
78 return last_lua_error;
79 }
80
81
82
luatexrevision(void)83 static const char *luatexrevision(void)
84 {
85 return (const char *) (strrchr(luatex_version_string, '.') + 1);
86 }
87
get_luatexhashchars(void)88 static lua_Number get_luatexhashchars(void)
89 {
90 return (lua_Number) LUAI_HASHLIMIT;
91 }
92
get_luatexhashtype(void)93 static const char *get_luatexhashtype(void)
94 {
95 #ifdef LuajitTeX
96 return (const char *)jithash_hashname;
97 #else
98 return "lua";
99 #endif
100 }
101
102
get_pdf_gone(void)103 static lua_Number get_pdf_gone(void)
104 {
105 if (static_pdf != NULL)
106 return (lua_Number) static_pdf->gone;
107 return (lua_Number) 0;
108 }
109
get_pdf_ptr(void)110 static lua_Number get_pdf_ptr(void)
111 {
112 if (static_pdf != NULL)
113 return (lua_Number) (static_pdf->buf->p - static_pdf->buf->data);
114 return (lua_Number) 0;
115 }
116
get_pdf_os_cntr(void)117 static lua_Number get_pdf_os_cntr(void)
118 {
119 if (static_pdf != NULL)
120 return (lua_Number) static_pdf->os->ostm_ctr;
121 return (lua_Number) 0;
122 }
123
get_pdf_os_objidx(void)124 static lua_Number get_pdf_os_objidx(void)
125 {
126 if (static_pdf != NULL)
127 return (lua_Number) static_pdf->os->idx;
128 return (lua_Number) 0;
129 }
130
get_pdf_mem_size(void)131 static lua_Number get_pdf_mem_size(void)
132 {
133 if (static_pdf != NULL)
134 return (lua_Number) static_pdf->mem_size;
135 return (lua_Number) 0;
136 }
137
get_pdf_mem_ptr(void)138 static lua_Number get_pdf_mem_ptr(void)
139 {
140 if (static_pdf != NULL)
141 return (lua_Number) static_pdf->mem_ptr;
142 return (lua_Number) 0;
143 }
144
145
get_obj_ptr(void)146 static lua_Number get_obj_ptr(void)
147 {
148 if (static_pdf != NULL)
149 return (lua_Number) static_pdf->obj_ptr;
150 return (lua_Number) 0;
151 }
152
get_obj_tab_size(void)153 static lua_Number get_obj_tab_size(void)
154 {
155 if (static_pdf != NULL)
156 return (lua_Number) static_pdf->obj_tab_size;
157 return (lua_Number) 0;
158 }
159
get_dest_names_size(void)160 static lua_Number get_dest_names_size(void)
161 {
162 if (static_pdf != NULL)
163 return (lua_Number) static_pdf->dest_names_size;
164 return (lua_Number) 0;
165 }
166
get_dest_names_ptr(void)167 static lua_Number get_dest_names_ptr(void)
168 {
169 if (static_pdf != NULL)
170 return (lua_Number) static_pdf->dest_names_ptr;
171 return (lua_Number) 0;
172 }
173
get_hash_size(void)174 static int get_hash_size(void)
175 {
176 return hash_size; /* is a #define */
177 }
178
179 static int luastate_max = 1; /* fixed value */
180
181 /* temp, for backward compat */
182 static int init_pool_ptr = 0;
183
184 static struct statistic stats[] = {
185
186 /* most likely accessed */
187
188 {"output_active", 'b', &output_active},
189 {"best_page_break", 'n', &best_page_break},
190
191 {"filename", 'S', (void *) &getfilename},
192 {"inputid", 'g', &(iname)},
193 {"linenumber", 'g', &line},
194
195 {"lasterrorstring", 'S', (void *) &getlasterror},
196 {"lastluaerrorstring", 'S', (void *) &getlastluaerror},
197
198 /* seldom or never accessed */
199
200 {"pdf_gone", 'N', &get_pdf_gone},
201 {"pdf_ptr", 'N', &get_pdf_ptr},
202 {"dvi_gone", 'g', &dvi_offset},
203 {"dvi_ptr", 'g', &dvi_ptr},
204 {"total_pages", 'g', &total_pages},
205 {"output_file_name", 'S', (void *) &get_output_file_name},
206 {"log_name", 'S', (void *) &getlogname},
207 {"banner", 'S', (void *) &getbanner},
208 {"pdftex_banner", 'S', (void *) &getbanner},
209 {"luatex_svn", 'G', &get_luatexsvn},
210 {"luatex_version", 'G', &get_luatexversion},
211 {"luatex_revision", 'S', (void *) &luatexrevision},
212 {"luatex_hashtype", 'S', (void *) &get_luatexhashtype},
213 {"luatex_hashchars", 'N', &get_luatexhashchars},
214
215 {"ini_version", 'b', &ini_version},
216 /*
217 * mem stat
218 */
219 {"var_used", 'g', &var_used},
220 {"dyn_used", 'g', &dyn_used},
221 /*
222 * traditional tex stats
223 */
224 {"str_ptr", 'g', &str_ptr},
225 {"init_str_ptr", 'g', &init_str_ptr},
226 {"max_strings", 'g', &max_strings},
227 {"pool_ptr", 'g', &pool_size},
228 {"init_pool_ptr", 'g', &init_pool_ptr},
229 {"pool_size", 'g', &pool_size},
230 {"var_mem_max", 'g', &var_mem_max},
231 {"node_mem_usage", 'S', &sprint_node_mem_usage},
232 {"fix_mem_max", 'g', &fix_mem_max},
233 {"fix_mem_min", 'g', &fix_mem_min},
234 {"fix_mem_end", 'g', &fix_mem_end},
235 {"cs_count", 'g', &cs_count},
236 {"hash_size", 'G', &get_hash_size},
237 {"hash_extra", 'g', &hash_extra},
238 {"font_ptr", 'G', &max_font_id},
239 {"max_in_stack", 'g', &max_in_stack},
240 {"max_nest_stack", 'g', &max_nest_stack},
241 {"max_param_stack", 'g', &max_param_stack},
242 {"max_buf_stack", 'g', &max_buf_stack},
243 {"max_save_stack", 'g', &max_save_stack},
244 {"stack_size", 'g', &stack_size},
245 {"nest_size", 'g', &nest_size},
246 {"param_size", 'g', ¶m_size},
247 {"buf_size", 'g', &buf_size},
248 {"save_size", 'g', &save_size},
249 /* pdf stats */
250 {"obj_ptr", 'N', &get_obj_ptr},
251 {"obj_tab_size", 'N', &get_obj_tab_size},
252 {"pdf_os_cntr", 'N', &get_pdf_os_cntr},
253 {"pdf_os_objidx", 'N', &get_pdf_os_objidx},
254 {"pdf_dest_names_ptr", 'N', &get_dest_names_ptr},
255 {"dest_names_size", 'N', &get_dest_names_size},
256 {"pdf_mem_ptr", 'N', &get_pdf_mem_ptr},
257 {"pdf_mem_size", 'N', &get_pdf_mem_size},
258
259 {"largest_used_mark", 'g', &biggest_used_mark},
260
261 {"luabytecodes", 'g', &luabytecode_max},
262 {"luabytecode_bytes", 'g', &luabytecode_bytes},
263 {"luastates", 'g', &luastate_max},
264 {"luastate_bytes", 'g', &luastate_bytes},
265 {"callbacks", 'g', &callback_count},
266 {"indirect_callbacks", 'g', &saved_callback_count},
267
268 {NULL, 0, 0}
269 };
270
stats_name_to_id(const char * name)271 static int stats_name_to_id(const char *name)
272 {
273 int i;
274 for (i = 0; stats[i].name != NULL; i++) {
275 if (strcmp(stats[i].name, name) == 0)
276 return i;
277 }
278 return -1;
279 }
280
do_getstat(lua_State * L,int i)281 static int do_getstat(lua_State * L, int i)
282 {
283 int t;
284 const char *st;
285 charfunc f;
286 intfunc g;
287 numfunc n;
288 int str;
289 t = stats[i].type;
290 switch (t) {
291 case 'S':
292 f = stats[i].value;
293 st = f();
294 lua_pushstring(L, st);
295 break;
296 case 's':
297 str = *(int *) (stats[i].value);
298 if (str) {
299 char *ss = makecstring(str);
300 lua_pushstring(L, ss);
301 free(ss);
302 } else {
303 lua_pushnil(L);
304 }
305 break;
306 case 'N':
307 n = stats[i].value;
308 lua_pushnumber(L, n());
309 break;
310 case 'G':
311 g = stats[i].value;
312 lua_pushnumber(L, g());
313 break;
314 case 'g':
315 lua_pushnumber(L, *(int *) (stats[i].value));
316 break;
317 case 'B':
318 g = stats[i].value;
319 lua_pushboolean(L, g());
320 break;
321 case 'n':
322 if (*(halfword *) (stats[i].value) != 0)
323 lua_nodelib_push_fast(L, *(halfword *) (stats[i].value));
324 else
325 lua_pushnil(L);
326 break;
327 case 'b':
328 lua_pushboolean(L, *(int *) (stats[i].value));
329 break;
330 default:
331 lua_pushnil(L);
332 }
333 return 1;
334 }
335
getstats(lua_State * L)336 static int getstats(lua_State * L)
337 {
338 const char *st;
339 int i;
340 if (lua_isstring(L, -1)) {
341 st = lua_tostring(L, -1);
342 i = stats_name_to_id(st);
343 if (i >= 0) {
344 return do_getstat(L, i);
345 }
346 }
347 return 0;
348 }
349
setstats(lua_State * L)350 static int setstats(lua_State * L)
351 {
352 (void) L;
353 return 0;
354 }
355
statslist(lua_State * L)356 static int statslist(lua_State * L)
357 {
358 int i;
359 luaL_checkstack(L, 1, "out of stack space");
360 lua_newtable(L);
361 for (i = 0; stats[i].name != NULL; i++) {
362 luaL_checkstack(L, 2, "out of stack space");
363 lua_pushstring(L, stats[i].name);
364 do_getstat(L, i);
365 lua_rawset(L, -3);
366 }
367 return 1;
368 }
369
370
371
372 static const struct luaL_Reg statslib[] = {
373 {"list", statslist},
374 {NULL, NULL} /* sentinel */
375 };
376
luaopen_stats(lua_State * L)377 int luaopen_stats(lua_State * L)
378 {
379 luaL_register(L, "status", statslib);
380 luaL_newmetatable(L, "tex.stats");
381 lua_pushstring(L, "__index");
382 lua_pushcfunction(L, getstats);
383 lua_settable(L, -3);
384 lua_pushstring(L, "__newindex");
385 lua_pushcfunction(L, setstats);
386 lua_settable(L, -3);
387 lua_setmetatable(L, -2); /* meta to itself */
388 return 1;
389 }
390