1 /*************************************************************************/
3 /* Objective Caml LablTk library */
5 /* Francois Rouaix, Francois Pessaux and Jun Furuse */
6 /* projet Cristal, INRIA Rocquencourt */
7 /* Jacques Garrigue, Kyoto University RIMS */
9 /* Copyright 1999 Institut National de Recherche en Informatique et */
10 /* en Automatique and Kyoto University. All rights reserved. */
11 /* This file is distributed under the terms of the GNU Library */
12 /* General Public License, with the special exception on linking */
13 /* described in file ../../../LICENSE. */
15 /*************************************************************************/
17 /* $Id: cltkDMain.c 8899 2008-07-01 09:55:52Z weis $ */
38 * Dealing with signals: when a signal handler is defined in Caml,
39 * the actual execution of the signal handler upon reception of the
40 * signal is delayed until we are sure we are out of the GC.
41 * If a signal occurs during the MainLoop, we would have to wait
42 * the next event for the handler to be invoked.
43 * The following function will invoke a pending signal handler if any,
44 * and we put in on a regular timer.
47 #define SIGNAL_INTERVAL 300
49 int signal_events = 0; /* do we have a pending timer */
51 void invoke_pending_caml_signals (clientdata)
52 ClientData clientdata;
55 enter_blocking_section(); /* triggers signal handling */
57 Tk_CreateTimerHandler(SIGNAL_INTERVAL, invoke_pending_caml_signals, NULL);
59 leave_blocking_section();
61 /* The following is taken from byterun/startup.c */
62 header_t atom_table[256];
66 static void init_atoms()
69 for(i = 0; i < 256; i++) atom_table[i] = Make_header(0, i, White);
72 static unsigned long read_size(p)
75 return ((unsigned long) p[0] << 24) + ((unsigned long) p[1] << 16) +
76 ((unsigned long) p[2] << 8) + p[3];
79 #define FILE_NOT_FOUND (-1)
80 #define TRUNCATED_FILE (-2)
81 #define BAD_MAGIC_NUM (-3)
83 static int read_trailer(fd, trail)
85 struct exec_trailer * trail;
87 char buffer[TRAILER_SIZE];
89 lseek(fd, (long) -TRAILER_SIZE, 2);
90 if (read(fd, buffer, TRAILER_SIZE) < TRAILER_SIZE) return TRUNCATED_FILE;
91 trail->code_size = read_size(buffer);
92 trail->data_size = read_size(buffer+4);
93 trail->symbol_size = read_size(buffer+8);
94 trail->debug_size = read_size(buffer+12);
95 if (strncmp(buffer + 16, EXEC_MAGIC, 12) == 0)
101 int attempt_open(name, trail, do_open_script)
103 struct exec_trailer * trail;
111 truename = searchpath(*name);
112 if (truename == 0) truename = *name; else *name = truename;
113 fd = open(truename, O_RDONLY | O_BINARY);
114 if (fd == -1) return FILE_NOT_FOUND;
115 if (!do_open_script){
116 err = read (fd, buf, 2);
117 if (err < 2) { close(fd); return TRUNCATED_FILE; }
118 if (buf [0] == '#' && buf [1] == '!') { close(fd); return BAD_MAGIC_NUM; }
120 err = read_trailer(fd, trail);
121 if (err != 0) { close(fd); return err; }
126 /* Command for loading the bytecode file */
127 int CamlRunCmd(dummy, interp, argc, argv)
128 ClientData dummy; /* Not used. */
129 Tcl_Interp *interp; /* Current interpreter. */
130 int argc; /* Number of arguments. */
131 char **argv; /* Argument strings. */
134 struct exec_trailer trail;
135 struct longjmp_buffer raise_buf;
136 struct channel * chan;
139 Tcl_AppendResult(interp, "wrong # args: should be \"",
140 argv[0], " foo.cmo args\"", (char *) NULL);
143 fd = attempt_open(&argv[1], &trail, 1);
147 fatal_error_arg("Fatal error: cannot find file %s\n", argv[1]);
152 "Fatal error: the file %s is not a bytecode executable file\n",
157 if (sigsetjmp(raise_buf.buf, 1) == 0) {
159 external_raise = &raise_buf;
161 lseek(fd, - (long) (TRAILER_SIZE + trail.code_size + trail.data_size
162 + trail.symbol_size + trail.debug_size), 2);
164 code_size = trail.code_size;
165 start_code = (code_t) stat_alloc(code_size);
166 if (read(fd, (char *) start_code, code_size) != code_size)
167 fatal_error("Fatal error: truncated bytecode file.\n");
169 #ifdef ARCH_BIG_ENDIAN
170 fixup_endianness(start_code, code_size);
173 chan = open_descr(fd);
174 global_data = input_value(chan);
176 /* Ensure that the globals are in the major heap. */
177 oldify(global_data, &global_data);
180 interprete(start_code, code_size);
183 Tcl_AppendResult(interp, "Caml program", argv[1], " raised exception \"",
184 String_val(Field(Field(exn_bucket, 0), 0)));
189 int CamlInvokeCmd(dummy
193 /* Now the real Tk stuff */
194 Tk_Window cltk_mainWindow;
196 #define RCNAME ".camltkrc"
197 #define CAMLCB "camlcb"
199 /* Initialisation of the dynamically loaded module */
200 int Caml_Init(interp)
203 cltclinterp = interp;
204 /* Create the camlcallback command */
205 Tcl_CreateCommand(cltclinterp,
207 (ClientData)NULL,(Tcl_CmdDeleteProc *)NULL);
209 /* This is required by "unknown" and thus autoload */
210 Tcl_SetVar(cltclinterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
211 /* Our hack for implementing break in callbacks */
212 Tcl_SetVar(cltclinterp, "BreakBindingsSequence", "0", TCL_GLOBAL_ONLY);
214 /* Load the traditional rc file */
216 char *home = getenv("HOME");
218 char *f = stat_alloc(strlen(home)+strlen(RCNAME)+2);
223 if (0 == access(f,R_OK))
224 if (TCL_OK != Tcl_EvalFile(cltclinterp,f)) {
226 tk_error(cltclinterp->result);
232 /* Initialisations from caml_main */
234 int verbose_init = 0,
235 percent_free_init = Percent_free_def;
236 long minor_heap_init = Minor_heap_def,
237 heap_chunk_init = Heap_chunk_def;
239 /* Machine-dependent initialization of the floating-point hardware
240 so that it behaves as much as possible as specified in IEEE */
242 init_gc (minor_heap_init, heap_chunk_init, percent_free_init,