1 /**************************************************************************/
2 /*                                                                        */
3 /*                                 OCaml                                  */
4 /*                                                                        */
5 /*          Xavier Leroy and Damien Doligez, INRIA Rocquencourt           */
6 /*                                                                        */
7 /*   Copyright 1996 Institut National de Recherche en Informatique et     */
8 /*     en Automatique.                                                    */
9 /*                                                                        */
10 /*   All rights reserved.  This file is distributed under the terms of    */
11 /*   the GNU Lesser General Public License version 2.1, with the          */
12 /*   special exception on linking described in the file LICENSE.          */
13 /*                                                                        */
14 /**************************************************************************/
15 
16 #define CAML_INTERNALS
17 
18 /* Start-up code */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include "caml/callback.h"
23 #include "caml/backtrace.h"
24 #include "caml/custom.h"
25 #include "caml/debugger.h"
26 #include "caml/fail.h"
27 #include "caml/freelist.h"
28 #include "caml/gc.h"
29 #include "caml/gc_ctrl.h"
30 #include "caml/intext.h"
31 #include "caml/memory.h"
32 #include "caml/misc.h"
33 #include "caml/mlvalues.h"
34 #include "caml/osdeps.h"
35 #include "caml/printexc.h"
36 #include "caml/stack.h"
37 #include "caml/startup_aux.h"
38 #include "caml/sys.h"
39 #ifdef WITH_SPACETIME
40 #include "caml/spacetime.h"
41 #endif
42 #ifdef HAS_UI
43 #include "caml/ui.h"
44 #endif
45 
46 extern int caml_parser_trace;
47 char * caml_code_area_start, * caml_code_area_end;
48 struct ext_table caml_code_fragments_table;
49 
50 /* Initialize the atom table and the static data and code area limits. */
51 
52 struct segment { char * begin; char * end; };
53 
init_static(void)54 static void init_static(void)
55 {
56   extern struct segment caml_data_segments[], caml_code_segments[];
57   int i;
58   struct code_fragment * cf;
59 
60   caml_init_atom_table ();
61 
62   for (i = 0; caml_data_segments[i].begin != 0; i++) {
63     /* PR#5509: we must include the zero word at end of data segment,
64        because pointers equal to caml_data_segments[i].end are static data. */
65     if (caml_page_table_add(In_static_data,
66                             caml_data_segments[i].begin,
67                             caml_data_segments[i].end + sizeof(value)) != 0)
68       caml_fatal_error("Fatal error: not enough memory for initial page table");
69   }
70 
71   caml_code_area_start = caml_code_segments[0].begin;
72   caml_code_area_end = caml_code_segments[0].end;
73   for (i = 1; caml_code_segments[i].begin != 0; i++) {
74     if (caml_code_segments[i].begin < caml_code_area_start)
75       caml_code_area_start = caml_code_segments[i].begin;
76     if (caml_code_segments[i].end > caml_code_area_end)
77       caml_code_area_end = caml_code_segments[i].end;
78   }
79   /* Register the code in the table of code fragments */
80   cf = caml_stat_alloc(sizeof(struct code_fragment));
81   cf->code_start = caml_code_area_start;
82   cf->code_end = caml_code_area_end;
83   cf->digest_computed = 0;
84   caml_ext_table_init(&caml_code_fragments_table, 8);
85   caml_ext_table_add(&caml_code_fragments_table, cf);
86 }
87 
88 /* These are termination hooks used by the systhreads library */
89 struct longjmp_buffer caml_termination_jmpbuf;
90 void (*caml_termination_hook)(void *) = NULL;
91 
92 extern value caml_start_program (void);
93 extern void caml_init_ieee_floats (void);
94 extern void caml_init_signals (void);
95 
96 #if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
97 
98 /* PR 4887: avoid crash box of windows runtime on some system calls */
99 extern void caml_install_invalid_parameter_handler();
100 
101 #endif
102 
caml_startup_exn(char ** argv)103 value caml_startup_exn(char **argv)
104 {
105   char * exe_name, * proc_self_exe;
106   char tos;
107 
108 #ifdef WITH_SPACETIME
109   caml_spacetime_initialize();
110 #endif
111   caml_init_frame_descriptors();
112   caml_init_ieee_floats();
113 #if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L
114   caml_install_invalid_parameter_handler();
115 #endif
116   caml_init_custom_operations();
117   caml_top_of_stack = &tos;
118 #ifdef DEBUG
119   caml_verb_gc = 0x3F;
120 #endif
121   caml_parse_ocamlrunparam();
122 #ifdef DEBUG
123   caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0);
124 #endif
125   caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz,
126                 caml_init_heap_chunk_sz, caml_init_percent_free,
127                 caml_init_max_percent_free, caml_init_major_window);
128   init_static();
129   caml_init_signals();
130   caml_init_backtrace();
131   caml_debugger_init (); /* force debugger.o stub to be linked */
132   exe_name = argv[0];
133   if (exe_name == NULL) exe_name = "";
134   proc_self_exe = caml_executable_name();
135   if (proc_self_exe != NULL)
136     exe_name = proc_self_exe;
137   else
138     exe_name = caml_search_exe_in_path(exe_name);
139   caml_sys_init(exe_name, argv);
140   if (sigsetjmp(caml_termination_jmpbuf.buf, 0)) {
141     if (caml_termination_hook != NULL) caml_termination_hook(NULL);
142     return Val_unit;
143   }
144   return caml_start_program();
145 }
146 
caml_startup(char ** argv)147 void caml_startup(char **argv)
148 {
149   value res = caml_startup_exn(argv);
150 
151   if (Is_exception_result(res)) {
152     caml_fatal_uncaught_exception(Extract_exception(res));
153   }
154 }
155 
caml_main(char ** argv)156 void caml_main(char **argv)
157 {
158   caml_startup(argv);
159 }
160