12 #include "mppsout.h" /* for mp_edge_object */
14 #define MPLIB_METATABLE "MPlib"
15 #define MPLIB_FIG_METATABLE "MPlib.fig"
16 #define MPLIB_GR_METATABLE "MPlib.gr"
18 #define xfree(A) if (A!=NULL) free(A)
20 #define is_mp(L,b) (MP *)luaL_checkudata(L,b,MPLIB_METATABLE)
21 #define is_fig(L,b) (struct mp_edge_object **)luaL_checkudata(L,b,MPLIB_FIG_METATABLE)
22 #define is_gr_object(L,b) (struct mp_graphic_object **)luaL_checkudata(L,b,MPLIB_GR_METATABLE)
25 P__ZERO, P_ERROR_LINE, P_HALF_LINE, P_MAX_LINE, P_MAIN_MEMORY,
26 P_HASH_SIZE, P_HASH_PRIME, P_PARAM_SIZE, P_IN_OPEN, P_RANDOM_SEED,
27 P_INTERACTION, P_INI_VERSION, P_TROFF_MODE, P_PRINT_NAMES, P_COMMAND_LINE,
28 P_MEM_NAME, P_JOB_NAME, P_FIND_FILE, P_OPEN_FILE, P_CLOSE_FILE,
29 P_EOF_FILE, P_FLUSH_FILE, P_WRITE_ASCII, P_READ_ASCII, P_WRITE_BINARY,
30 P_READ_BINARY, P_RUN_EDITOR, P_RUN_MAKEMPX, P_SHIPOUT, P__SENTINEL,
34 const char *name; /* parameter name */
35 parm_idx idx; /* parameter index */
36 int class; /* parameter class */
39 const char *interaction_options[] =
40 { "unknownmode","batchmode","nonstopmode","scrollmode","errorstopmode", NULL};
43 parm_struct img_parms[] = {
44 {NULL, P__ZERO, 0 }, /* dummy; lua indices run from 1 */
45 {"error_line", P_ERROR_LINE, 'i' },
46 {"half_error_line", P_HALF_LINE, 'i' },
47 {"max_print_line", P_MAX_LINE, 'i' },
48 {"main_memory", P_MAIN_MEMORY, 'i' },
49 {"hash_size", P_HASH_SIZE, 'i' },
50 {"hash_prime", P_HASH_PRIME, 'i' },
51 {"param_size", P_PARAM_SIZE, 'i' },
52 {"max_in_open", P_IN_OPEN, 'i' },
53 {"random_seed", P_RANDOM_SEED, 'i' },
54 {"interaction", P_INTERACTION, 'e' },
55 {"ini_version", P_INI_VERSION, 'b' },
56 {"troff_mode", P_TROFF_MODE, 'b' },
57 {"print_found_names", P_PRINT_NAMES, 'b' },
58 {"command_line", P_COMMAND_LINE,'s' },
59 {"mem_name", P_MEM_NAME, 's' },
60 {"job_name", P_JOB_NAME, 's' },
61 {"find_file", P_FIND_FILE, 'p' }, /* intercepted */
63 {"open_file", P_OPEN_FILE, 'p' },
64 {"close_file", P_CLOSE_FILE, 'p' },
65 {"eof_file", P_EOF_FILE, 'p' },
66 {"flush_file", P_FLUSH_FILE, 'p' },
67 {"write_ascii_file", P_WRITE_ASCII, 'p' },
68 {"read_ascii_file", P_READ_ASCII, 'p' },
69 {"write_binary_file", P_WRITE_BINARY,'p' },
70 {"read_binary_file", P_READ_BINARY, 'p' },
71 {"run_editor", P_RUN_EDITOR, 'p' },
72 {"run_make_mpx", P_RUN_MAKEMPX, 'p' },
73 {"shipout_backend", P_SHIPOUT, 'p' },
75 {NULL, P__SENTINEL, 0 }
78 typedef struct _FILE_ITEM {
82 typedef struct _FILE_ITEM File;
84 /* Start by defining all the callback routines for the library
85 * except |run_make_mpx| and |run_editor|.
88 char *mplib_filetype_names[] = {"term", "error", "mp", "log", "ps",
89 "mem", "tfm", "map", "pfb", "enc", NULL};
93 char *mplib_find_file (char *fname, char *fmode, int ftype) {
97 lua_getfield(L,LUA_REGISTRYINDEX,"mplib_file_finder");
98 if (lua_isfunction(L,-1)) {
99 char *s = NULL, *x = NULL;
100 lua_pushstring(L, fname);
101 lua_pushstring(L, fmode);
102 if (ftype >= mp_filetype_text) {
103 lua_pushnumber(L, ftype-mp_filetype_text);
105 lua_pushstring(L, mplib_filetype_names[ftype]);
107 if(lua_pcall(L,3,1,0) != 0) {
108 fprintf(stdout,"Error in mp.find_file: %s\n", (char *)lua_tostring(L,-1));
111 x = (char *)lua_tostring(L,-1);
114 lua_pop(L,1); /* pop the string */
120 if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) {
121 return strdup(fname);
127 mplib_find_file_function (lua_State *L) {
128 if (lua_isfunction(L,-1)) {
130 } else if (lua_isnil(L,-1)) {
133 return 1; /* error */
135 lua_pushstring(L, "mplib_file_finder");
137 lua_rawset(L,LUA_REGISTRYINDEX);
141 void *term_file_ptr = NULL;
142 void *err_file_ptr = NULL;
143 void *log_file_ptr = NULL;
144 void *ps_file_ptr = NULL;
146 void *mplib_open_file(char *fname, char *fmode, int ftype) {
147 File *ff = malloc(sizeof (File));
150 if (ftype==mp_filetype_terminal) {
151 if (fmode[0] == 'r') {
154 xfree(term_file_ptr);
156 term_file_ptr = ff->f;
158 } else if (ftype==mp_filetype_error) {
161 err_file_ptr = ff->f;
162 } else if (ftype == mp_filetype_log) {
165 log_file_ptr = ff->f;
166 } else if (ftype == mp_filetype_postscript) {
172 if (fmode[0] == 'r') {
173 f = mplib_find_file(fname,fmode,ftype);
177 ff->f = fopen(f, fmode);
178 if ((fmode[0] == 'r') && (ff->f == NULL)) {
188 static char * input_data = NULL;
189 static char * input_data_ptr = NULL;
190 static size_t input_data_len = 0;
192 #define GET_CHAR() do { \
193 if (f==stdin && input_data != NULL) { \
194 if (input_data_len==0) { \
195 if (input_data_ptr!=NULL) \
196 input_data_ptr = NULL; \
202 c = *input_data_ptr++; \
209 #define UNGET_CHAR() do { \
210 if (f==stdin && input_data != NULL) { \
211 input_data_len++; input_data_ptr--; \
218 char *mplib_read_ascii_file (void *ff, size_t *size) {
220 size_t len = 0, lim = 128;
223 FILE *f = ((File *)ff)->f;
231 if (s==NULL) return NULL;
232 while (c!=EOF && c!='\n' && c!='\r') {
234 s =realloc(s, (lim+(lim>>2)));
235 if (s==NULL) return NULL;
243 if (c!=EOF && c!='\n')
252 static char *term_out = NULL;
253 static char *error_out = NULL;
254 static char *log_out = NULL;
255 static char *ps_out = NULL;
257 #define APPEND_STRING(a,b) do { \
261 a = realloc(a, strlen(a)+strlen(b)+1); \
262 strcpy(a+strlen(a),b); \
266 void mplib_write_ascii_file (void *ff, char *s) {
268 void *f = ((File *)ff)->f;
270 if (f==term_file_ptr) {
271 APPEND_STRING(term_out,s);
272 } else if (f==err_file_ptr) {
273 APPEND_STRING(error_out,s);
274 } else if (f==log_file_ptr) {
275 APPEND_STRING(log_out,s);
276 } else if (f==ps_file_ptr) {
277 APPEND_STRING(ps_out,s);
279 fprintf((FILE *)f,s);
285 void mplib_read_binary_file (void *ff, void **data, size_t *size) {
288 FILE *f = ((File *)ff)->f;
290 len = fread(*data,1,*size,f);
295 void mplib_write_binary_file (void *ff, void *s, size_t size) {
297 FILE *f = ((File *)ff)->f;
304 void mplib_close_file (void *ff) {
306 void *f = ((File *)ff)->f;
307 if (f != NULL && f != term_file_ptr && f != err_file_ptr
308 && f != log_file_ptr && f != ps_file_ptr) {
315 int mplib_eof_file (void *ff) {
317 FILE *f = ((File *)ff)->f;
320 if (f==stdin && input_data != NULL) {
321 return (input_data_len==0);
328 void mplib_flush_file (void *ff) {
332 static struct mp_edge_object *edges = NULL;
334 #define APPEND_TO_EDGES(a) do { \
338 struct mp_edge_object *p = edges; \
339 while (p->_next!=NULL) { p = p->_next; } \
344 void mplib_shipout_backend (MP mp, int h) {
345 struct mp_edge_object *hh;
346 hh = mp_gr_export(mp, h);
354 mplib_setup_file_ops(struct MP_options * options) {
355 options->find_file = mplib_find_file;
356 options->open_file = mplib_open_file;
357 options->close_file = mplib_close_file;
358 options->eof_file = mplib_eof_file;
359 options->flush_file = mplib_flush_file;
360 options->write_ascii_file = mplib_write_ascii_file;
361 options->read_ascii_file = mplib_read_ascii_file;
362 options->write_binary_file = mplib_write_binary_file;
363 options->read_binary_file = mplib_read_binary_file;
364 options->shipout_backend = mplib_shipout_backend;
368 mplib_new (lua_State *L) {
371 struct MP_options * options; /* instance options */
372 mp_ptr = lua_newuserdata(L, sizeof(MP *));
374 options = mp_options();
375 mplib_setup_file_ops(options);
376 options->noninteractive = 1; /* required ! */
377 options->print_found_names = 0;
378 if (lua_type(L,1)==LUA_TTABLE) {
379 for (i=1;img_parms[i].name!=NULL;i++) {
380 lua_getfield(L,1,img_parms[i].name);
381 if (lua_isnil(L,-1)) {
383 continue; /* skip unset */
385 switch(img_parms[i].idx) {
387 options->error_line = lua_tointeger(L,-1);
390 options->half_error_line = lua_tointeger(L,-1);
393 options->max_print_line = lua_tointeger(L,-1);
396 options->main_memory = lua_tointeger(L,-1);
399 options->hash_size = lua_tointeger(L,-1);
402 options->hash_prime = lua_tointeger(L,-1);
405 options->param_size = lua_tointeger(L,-1);
408 options->max_in_open = lua_tointeger(L,-1);
411 options->random_seed = lua_tointeger(L,-1);
414 options->interaction = luaL_checkoption(L,-1,"errorstopmode", interaction_options);
417 options->ini_version = lua_toboolean(L,-1);
420 options->troff_mode = lua_toboolean(L,-1);
423 options->print_found_names = lua_toboolean(L,-1);
426 options->command_line = strdup((char *)lua_tostring(L,-1));
429 options->mem_name = strdup((char *)lua_tostring(L,-1));
432 options->job_name = strdup((char *)lua_tostring(L,-1));
435 if(mplib_find_file_function(L)) { /* error here */
436 fprintf(stdout,"Invalid arguments to mp.new({find_file=...})\n");
462 *mp_ptr = mp_new(options);
463 xfree(options->command_line);
464 xfree(options->mem_name);
465 xfree(options->job_name);
468 h = mp_initialize(*mp_ptr);
470 luaL_getmetatable(L,MPLIB_METATABLE);
471 lua_setmetatable(L,-2);
481 mplib_collect (lua_State *L) {
482 MP *mp_ptr = is_mp(L,1);
491 mplib_tostring (lua_State *L) {
492 MP *mp_ptr = is_mp(L,1);
494 lua_pushfstring(L,"<MP %p>",*mp_ptr);
501 mplib_run (lua_State *L) {
502 MP *mp_ptr = is_mp(L,1);
504 int h = mp_run(*mp_ptr);
513 mplib_wrapresults(lua_State *L,int h) {
516 if (term_out != NULL) {
517 lua_pushstring(L,term_out);
518 lua_setfield(L,-2,"term");
519 free(term_out); term_out = NULL;
521 if (error_out != NULL) {
522 lua_pushstring(L,error_out);
523 lua_setfield(L,-2,"error");
524 free(error_out); error_out = NULL;
526 if (log_out != NULL ) {
527 lua_pushstring(L,log_out);
528 lua_setfield(L,-2,"log");
529 free(log_out); log_out = NULL;
531 if (edges != NULL ) {
532 struct mp_edge_object **v;
533 struct mp_edge_object *p = edges;
537 v = lua_newuserdata (L, sizeof(struct mp_edge_object *));
539 luaL_getmetatable(L,MPLIB_FIG_METATABLE);
540 lua_setmetatable(L,-2);
541 lua_rawseti(L,-2,i); i++;
544 lua_setfield(L,-2,"fig");
548 lua_setfield(L,-2,"status");
553 mplib_execute (lua_State *L) {
554 MP *mp_ptr = is_mp(L,1);
555 if (*mp_ptr!=NULL && lua_isstring(L,2)) {
556 if (input_data_len>0) { /* this should NOT happen */
557 fprintf(stderr,"Can't do concurrency yet!\n");
559 input_data = (char *)lua_tolstring(L,2, &input_data_len);
560 input_data_ptr = input_data;
561 int h = mp_execute(*mp_ptr);
562 return mplib_wrapresults(L, h);
572 mplib_finish (lua_State *L) {
573 MP *mp_ptr = is_mp(L,1);
575 int h = mp_finish(*mp_ptr);
576 return mplib_wrapresults(L, h);
586 mplib_fig_collect (lua_State *L) {
587 struct mp_edge_object **hh = is_fig(L,1);
589 mp_gr_toss_objects (*hh);
596 mplib_fig_body (lua_State *L) {
597 struct mp_edge_object **hh = is_fig(L,1);
598 struct mp_graphic_object **v;
599 struct mp_graphic_object *p;
600 /* create a table from body */
607 (*hh)->body = NULL; /* prevent double free */
613 mplib_fig_tostring (lua_State *L) {
614 struct mp_edge_object **hh = is_fig(L,1);
615 lua_pushfstring(L,"<figure %p>",*hh);
622 mp_wrapped_shipout (struct mp_edge_object *hh, int prologues, int procset) {
624 if (setjmp(mp->jump_buf)) {
627 mp_gr_ship_out(hh,prologues,procset);
632 mplib_fig_postscript (lua_State *L) {
633 struct mp_edge_object **hh = is_fig(L,1);
634 int prologues = luaL_optnumber(L,2,-1);
635 int procset = luaL_optnumber(L,3,-1);
636 if (ps_out == NULL) {
637 if (mp_wrapped_shipout(*hh,prologues, procset)) {
639 lua_pushstring(L, ps_out);
640 free(ps_out); ps_out = NULL;
647 lua_pushstring(L,log_out);
648 free(ps_out); ps_out = NULL;
657 mplib_fig_bb (lua_State *L) {
658 struct mp_edge_object **hh = is_fig(L,1);
660 lua_pushnumber(L, (double)(*hh)->_minx/65536.0);
662 lua_pushnumber(L, (double)(*hh)->_miny/65536.0);
664 lua_pushnumber(L, (double)(*hh)->_maxx/65536.0);
666 lua_pushnumber(L, (double)(*hh)->_maxy/65536.0);
674 mplib_gr_collect (lua_State *L) {
675 struct mp_graphic_object **hh = is_gr_object(L,1);
677 mp_gr_toss_object(*hh);
684 mplib_gr_tostring (lua_State *L) {
685 struct mp_graphic_object **hh = is_gr_object(L,1);
686 lua_pushfstring(L,"<object %p>",*hh);
691 static const struct luaL_reg mplib_meta[] = {
692 {"__gc", mplib_collect},
693 {"__tostring", mplib_tostring},
694 {NULL, NULL} /* sentinel */
697 static const struct luaL_reg mplib_fig_meta[] = {
698 {"__gc", mplib_fig_collect},
699 {"__tostring", mplib_fig_tostring},
700 {"postscript", mplib_fig_postscript},
701 {"boundingbox", mplib_fig_bb},
702 {NULL, NULL} /* sentinel */
705 static const struct luaL_reg mplib_gr_meta[] = {
706 {"__gc", mplib_gr_collect},
707 {"__tostring", mplib_gr_tostring},
708 {NULL, NULL} /* sentinel */
712 static const struct luaL_reg mplib_d [] = {
714 {"execute", mplib_execute },
715 {"finish", mplib_finish },
716 {NULL, NULL} /* sentinel */
720 static const struct luaL_reg mplib_m[] = {
722 {NULL, NULL} /* sentinel */
727 luaopen_mp (lua_State *L) {
728 luaL_newmetatable(L,MPLIB_GR_METATABLE);
729 lua_pushvalue(L, -1); /* push metatable */
730 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
731 luaL_register(L, NULL, mplib_gr_meta); /* object meta methods */
734 luaL_newmetatable(L,MPLIB_FIG_METATABLE);
735 lua_pushvalue(L, -1); /* push metatable */
736 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
737 luaL_register(L, NULL, mplib_fig_meta); /* figure meta methods */
740 luaL_newmetatable(L,MPLIB_METATABLE);
741 lua_pushvalue(L, -1); /* push metatable */
742 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
743 luaL_register(L, NULL, mplib_meta); /* meta methods */
744 luaL_register(L, NULL, mplib_d); /* dict methods */
745 luaL_register(L, "mp", mplib_m); /* module functions */