1 /* cacao/cacao.c - contains main() of cacao
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
33 This module does the following tasks:
34 - Command line option handling
35 - Calling initialization routines
36 - Calling the class loader
37 - Running the main method
39 $Id: cacao.c 1838 2005-01-04 11:15:21Z twisti $
47 #include "cacao/cacao.h"
49 #include "mm/memory.h"
50 #include "native/jni.h"
51 #include "native/native.h"
52 #include "toolbox/logging.h"
53 #include "vm/exceptions.h"
54 #include "vm/global.h"
55 #include "vm/loader.h"
56 #include "vm/options.h"
57 #include "vm/statistics.h"
58 #include "vm/tables.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/jit.h"
62 #ifdef TYPEINFO_DEBUG_TEST
63 #include "vm/jit/verify/typeinfo.h"
67 /* define heap sizes **********************************************************/
69 #define HEAP_MAXSIZE 64 * 1024 * 1024; /* default 64MB */
70 #define HEAP_STARTSIZE 2 * 1024 * 1024; /* default 2MB */
73 /* Invocation API variables ***************************************************/
75 JavaVM *jvm; /* denotes a Java VM */
76 JNIEnv *env; /* pointer to native method interface */
78 JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
81 bool cacao_initializing;
83 char *bootclasspath; /* contains the boot classpath */
84 char *classpath; /* contains the classpath */
87 static classinfo *mainclass;
89 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
90 void **stackbottom = 0;
94 /* define command line options ************************************************/
96 #define OPT_CLASSPATH 2
100 #define OPT_VERBOSE1 6
101 #define OPT_VERBOSE 7
102 #define OPT_VERBOSEGC 8
103 #define OPT_VERBOSECALL 9
104 #define OPT_NOIEEE 10
105 #define OPT_SOFTNULL 11
111 #define OPT_METHOD 17
112 #define OPT_SIGNATURE 18
116 #define OPT_INLINING 25
118 #if defined(STATIC_ANALYSIS)
122 #endif /* STATIC_ANALYSIS */
124 #define OPT_VERBOSETC 29
125 #define OPT_NOVERIFY 30
126 #define OPT_LIBERALUTF 31
127 #define OPT_VERBOSEEXCEPTION 32
135 #define OPT_BOOTCLASSPATH 36
136 #define OPT_BOOTCLASSPATH_A 37
137 #define OPT_BOOTCLASSPATH_P 38
140 opt_struct opts[] = {
141 { "classpath", true, OPT_CLASSPATH },
142 { "cp", true, OPT_CLASSPATH },
143 { "D", true, OPT_D },
144 { "Xms", true, OPT_MS },
145 { "Xmx", true, OPT_MX },
146 { "ms", true, OPT_MS },
147 { "mx", true, OPT_MX },
148 { "noasyncgc", false, OPT_IGNORE },
149 { "noverify", false, OPT_NOVERIFY },
150 { "liberalutf", false, OPT_LIBERALUTF },
151 { "oss", true, OPT_IGNORE },
152 { "ss", true, OPT_IGNORE },
153 { "v", false, OPT_VERBOSE1 },
154 { "verbose", false, OPT_VERBOSE },
155 { "verbosegc", false, OPT_VERBOSEGC },
156 { "verbosecall", false, OPT_VERBOSECALL },
157 { "verboseexception", false, OPT_VERBOSEEXCEPTION },
158 #ifdef TYPECHECK_VERBOSE
159 { "verbosetc", false, OPT_VERBOSETC },
161 #if defined(__ALPHA__)
162 { "noieee", false, OPT_NOIEEE },
164 { "softnull", false, OPT_SOFTNULL },
165 { "time", false, OPT_TIME },
166 { "stat", false, OPT_STAT },
167 { "log", true, OPT_LOG },
168 { "c", true, OPT_CHECK },
169 { "l", false, OPT_LOAD },
170 { "eager", false, OPT_EAGER },
171 { "m", true, OPT_METHOD },
172 { "sig", true, OPT_SIGNATURE },
173 { "s", true, OPT_SHOW },
174 { "all", false, OPT_ALL },
175 { "oloop", false, OPT_OLOOP },
176 { "i", true, OPT_INLINING },
177 #ifdef STATIC_ANALYSIS
178 { "rt", false, OPT_RT },
179 { "xta", false, OPT_XTA },
180 { "vta", false, OPT_VTA },
183 { "lsra", false, OPT_LSRA },
185 { "jar", false, OPT_JAR },
186 { "Xbootclasspath:", true, OPT_BOOTCLASSPATH },
187 { "Xbootclasspath/a:", true, OPT_BOOTCLASSPATH_A },
188 { "Xbootclasspath/p:", true, OPT_BOOTCLASSPATH_P },
193 /******************** interne Function: print_usage ************************
195 Prints the correct usage syntax to stdout.
197 ***************************************************************************/
201 printf("Usage: cacao [options] classname [program arguments]\n\n");
203 printf("Options:\n");
204 printf(" -cp <path> specify a path to look for classes\n");
205 printf(" -classpath <path> specify a path to look for classes\n");
206 printf(" -jar jarfile execute a jar file\n");
207 printf(" -D<name>=<value> add an entry to the property list\n");
208 printf(" -Xmx<size>[kK|mM] specify the size for the heap\n");
209 printf(" -Xms<size>[kK|mM] specify the initial size for the heap\n");
210 printf(" -mx<size>[kK|mM] specify the size for the heap\n");
211 printf(" -ms<size>[kK|mM] specify the initial size for the heap\n");
212 printf(" -Xbootclasspath:<path> set search path for bootstrap classes and resources\n");
213 printf(" -Xbootclasspath/a:<path> append to end of bootstrap class path\n");
214 printf(" -Xbootclasspath/p:<path> prepend in front of bootstrap class path\n");
215 printf(" -v ................... write state-information\n");
216 printf(" -verbose ............. write more information\n");
217 printf(" -verbosegc ........... write message for each GC\n");
218 printf(" -verbosecall ......... write message for each call\n");
219 printf(" -verboseexception .... write message for each step of stack unwinding\n");
220 #ifdef TYPECHECK_VERBOSE
221 printf(" -verbosetc ........... write debug messages while typechecking\n");
223 #if defined(__ALPHA__)
224 printf(" -noieee .............. don't use ieee compliant arithmetic\n");
226 printf(" -noverify ............ don't verify classfiles\n");
227 printf(" -liberalutf........... don't warn about overlong UTF-8 sequences\n");
228 printf(" -softnull ............ use software nullpointer check\n");
229 printf(" -time ................ measure the runtime\n");
230 printf(" -stat ................ detailed compiler statistics\n");
231 printf(" -log logfile ......... specify a name for the logfile\n");
232 printf(" -c(heck)b(ounds) ..... don't check array bounds\n");
233 printf(" s(ync) ....... don't check for synchronization\n");
234 printf(" -oloop ............... optimize array accesses in loops\n");
235 printf(" -l ................... don't start the class after loading\n");
236 printf(" -eager ............... perform eager class loading and linking\n");
237 printf(" -all ................. compile all methods, no execution\n");
238 printf(" -m ................... compile only a specific method\n");
239 printf(" -sig ................. specify signature for a specific method\n");
240 printf(" -s(how)a(ssembler) ... show disassembled listing\n");
241 printf(" c(onstants) ... show the constant pool\n");
242 printf(" d(atasegment).. show data segment listing\n");
243 printf(" i(ntermediate). show intermediate representation\n");
244 printf(" m(ethods)...... show class fields and methods\n");
245 printf(" u(tf) ......... show the utf - hash\n");
246 printf(" -i n ............. activate inlining\n");
247 printf(" v ............. inline virtual methods\n");
248 printf(" uses/turns rt option on\n");
249 printf(" e ............. inline methods with exceptions\n");
250 printf(" p ............. optimize argument renaming\n");
251 printf(" o ............. inline methods of foreign classes\n");
252 #ifdef STATIC_ANALYSIS
253 printf(" -rt .................. use rapid type analysis\n");
254 printf(" -xta ................. use x type analysis\n");
255 printf(" -vta ................. use variable type analysis\n");
258 printf(" -lsra ................ use linear scan register allocation\n");
261 /* exit with error code */
267 #ifdef TYPECHECK_STATISTICS
268 void typecheck_print_statistics(FILE *file);
273 /* getmainclassfromjar ************************************************************
275 gets the name of the main class form a jar's manifest file
277 **********************************************************************************/
279 char *getmainclassnamefromjar(JNIEnv *env, char *mainstring)
285 class = (*env)->FindClass(env, "java/util/jar/JarFile");
287 log_text("unable to find java.util.jar.JarFile");
288 throw_main_exception_exit();
291 mid = (*env)->GetMethodID(NULL, class, "<init>","(Ljava/lang/String;)V");
293 log_text("unable to find constructor in java.util.jar.JarFile");
298 obj = (*env)->NewObject(NULL,class,mid,((*env)->NewStringUTF(NULL,(char*)mainstring)));
299 if ((*env)->ExceptionOccurred(NULL) != NULL) {
300 (*env)->ExceptionDescribe(NULL);
304 mid = (*env)->GetMethodID(NULL, class, "getManifest","()Ljava/util/jar/Manifest;");
306 log_text("unable to find getMainfest method");
310 /* get manifest object */
311 obj = (*env)->CallObjectMethod(NULL,obj,mid);
312 if ((*env)->ExceptionOccurred(NULL) != NULL) {
313 (*env)->ExceptionDescribe(NULL);
317 mid = (*env)->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getMainAttributes","()Ljava/util/jar/Attributes;");
319 log_text("unable to find getMainAttributes method");
323 /* get Main Attributes */
324 obj = (*env)->CallObjectMethod(NULL,obj,mid);
325 if ((*env)->ExceptionOccurred(NULL) != NULL) {
326 (*env)->ExceptionDescribe(NULL);
331 mid = (*env)->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getValue","(Ljava/lang/String;)Ljava/lang/String;");
333 log_text("unable to find getValue method");
337 /* get property Main-Class */
338 obj = (*env)->CallObjectMethod(NULL,obj,mid,(*env)->NewStringUTF(NULL,"Main-Class"));
339 if ((*env)->ExceptionOccurred(NULL) != NULL) {
340 (*env)->ExceptionDescribe(NULL);
344 return javastring_tochar((java_objectheader *) obj);
349 * void exit_handler(void)
350 * -----------------------
351 * The exit_handler function is called upon program termination to shutdown
352 * the various subsystems and release the resources allocated to the VM.
354 void exit_handler(void)
356 /********************* Print debug tables ************************/
358 if (showmethods) class_showmethods(mainclass);
359 if (showconstantpool) class_showconstantpool(mainclass);
360 if (showutf) utf_show();
362 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
363 clear_thread_flags(); /* restores standard file descriptor
367 /************************ Free all resources *******************/
372 MFREE(classpath, u1, strlen(classpath));
374 if (opt_verbose || getcompilingtime || opt_stat) {
375 log_text("CACAO terminated");
378 #ifdef TYPECHECK_STATISTICS
379 typecheck_print_statistics(get_logfile());
382 if (getcompilingtime)
389 /************************** Function: main *******************************
393 **************************************************************************/
395 int main(int argc, char **argv)
400 /********** interne (nur fuer main relevante Optionen) **************/
402 char logfilename[200] = "";
408 char *specificmethodname = NULL;
409 char *specificsignature = NULL;
412 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
413 stackbottom = &dummy;
416 if (atexit(exit_handler))
417 throw_cacao_exception_exit(string_java_lang_InternalError,
418 "Unable to register exit_handler");
421 /************ Collect info from the environment ************************/
423 /* set the bootclasspath */
425 cp = getenv("BOOTCLASSPATH");
427 bootclasspath = MNEW(char, strlen(cp) + 1);
428 strcpy(bootclasspath, cp);
431 cplen = strlen(CACAO_INSTALL_PREFIX) + strlen(CACAO_RT_JAR_PATH);
433 bootclasspath = MNEW(char, cplen + 1);
434 strcpy(bootclasspath, CACAO_INSTALL_PREFIX);
435 strcat(bootclasspath, CACAO_RT_JAR_PATH);
439 /* set the classpath */
441 cp = getenv("CLASSPATH");
443 classpath = MNEW(char, strlen(cp) + 1);
444 strcat(classpath, cp);
447 classpath = MNEW(char, 2);
448 strcpy(classpath, ".");
452 /***************** Interpret the command line *****************/
457 heapmaxsize = HEAP_MAXSIZE;
458 heapstartsize = HEAP_STARTSIZE;
461 while ((i = get_opt(argc, argv, opts)) != OPT_DONE) {
466 case OPT_BOOTCLASSPATH:
467 /* Forget default bootclasspath and set the argument as new boot */
469 MFREE(bootclasspath, char, strlen(bootclasspath));
471 bootclasspath = MNEW(char, strlen(opt_arg) + 1);
472 strcpy(bootclasspath, opt_arg);
475 case OPT_BOOTCLASSPATH_A:
476 /* append to end of bootclasspath */
477 cplen = strlen(bootclasspath);
479 bootclasspath = MREALLOC(bootclasspath,
482 cplen + 1 + strlen(opt_arg) + 1);
484 strcat(bootclasspath, ":");
485 strcat(bootclasspath, opt_arg);
488 case OPT_BOOTCLASSPATH_P:
489 /* prepend in front of bootclasspath */
493 bootclasspath = MNEW(char, strlen(opt_arg) + 1 + cplen + 1);
495 strcpy(bootclasspath, opt_arg);
496 strcat(bootclasspath, ":");
497 strcat(bootclasspath, cp);
499 MFREE(cp, char, cplen);
503 /* forget old classpath and set the argument as new classpath */
504 MFREE(classpath, char, strlen(classpath));
506 classpath = MNEW(char, strlen(opt_arg) + 1);
507 strcpy(classpath, opt_arg);
517 int l = strlen(opt_arg);
518 for (n = 0; n < l; n++) {
519 if (opt_arg[n] == '=') {
521 create_property(opt_arg, opt_arg + n + 1);
535 c = opt_arg[strlen(opt_arg) - 1];
537 if (c == 'k' || c == 'K') {
538 j = 1024 * atoi(opt_arg);
540 } else if (c == 'm' || c == 'M') {
541 j = 1024 * 1024 * atoi(opt_arg);
543 } else j = atoi(opt_arg);
545 if (i == OPT_MX) heapmaxsize = j;
546 else heapstartsize = j;
559 compileverbose = true;
562 case OPT_VERBOSEEXCEPTION:
563 verboseexception = true;
567 collectverbose = true;
570 #ifdef TYPECHECK_VERBOSE
572 typecheckverbose = true;
576 case OPT_VERBOSECALL:
589 opt_liberalutf = true;
597 getcompilingtime = true;
598 getloadingtime = true;
606 strcpy(logfilename, opt_arg);
610 for (j = 0; j < strlen(opt_arg); j++) {
611 switch (opt_arg[j]) {
626 makeinitializations = false;
635 specificmethodname = opt_arg;
636 makeinitializations = false;
640 specificsignature = opt_arg;
646 makeinitializations = false;
649 case OPT_SHOW: /* Display options */
650 for (j = 0; j < strlen(opt_arg); j++) {
651 switch (opt_arg[j]) {
653 showdisassemble = true;
654 compileverbose = true;
657 showconstantpool = true;
660 showddatasegment = true;
663 showintermediate = true;
664 compileverbose = true;
683 for (j = 0; j < strlen(opt_arg); j++) {
684 switch (opt_arg[j]) {
686 /* define in options.h; Used in main.c, jit.c & inline.c */
695 inlinevirtuals = true;
699 inlineexceptions = true;
702 inlineparamopt = true;
705 inlineoutsiders = true;
713 #ifdef STATIC_ANALYSIS
719 opt_xta = false; /**not yet **/
723 /***opt_vta = true; not yet **/
729 #if defined(__I386__) || defined(__ALPHA__)
732 printf("LSRA not available for this architecture\n");
739 printf("Unknown option: %s\n", argv[opt_ind]);
748 /* transform dots into slashes in the class name */
750 mainstring = argv[opt_ind++];
752 /* do not mangle jar filename */
753 for (i = strlen(mainstring) - 1; i >= 0; i--) {
754 if (mainstring[i] == '.') mainstring[i] = '/';
758 /* put jarfile in classpath */
760 classpath = MNEW(char, strlen(mainstring) + 1 + strlen(classpath) + 1);
761 strcpy(classpath, mainstring);
762 strcat(classpath, ":");
763 strcat(classpath, cp);
765 MFREE(cp, char, strlen(cp));
768 /**************************** Program start *****************************/
770 log_init(logfilename);
772 log_text("CACAO started -------------------------------------------------------");
774 /* initialize JavaVM */
776 vm_args.version = 0x00010001; /* New in 1.1.2: VM version */
778 /* Get the default initialization arguments and set the class path */
780 JNI_GetDefaultJavaVMInitArgs(&vm_args);
781 vm_args.classpath = classpath;
783 /* load and initialize a Java VM, return a JNI interface pointer in env */
785 JNI_CreateJavaVM(&jvm, &env, &vm_args);
787 /* initialize the garbage collector */
789 gc_init(heapmaxsize, heapstartsize);
793 /* initialize the loader with bootclasspath and append classpath entries */
795 suck_init(bootclasspath);
796 suck_init(classpath);
798 cacao_initializing = true;
800 #if defined(USE_THREADS)
801 #if defined(NATIVE_THREADS)
807 /* install architecture dependent signal handler used for exceptions */
810 /* initializes jit compiler and codegen stuff */
813 loader_init((u1 *) &dummy);
815 /* initialize exceptions used in the system */
816 if (!init_system_exceptions())
817 throw_main_exception_exit();
819 native_loadclasses();
821 #if defined(USE_THREADS)
822 initThreads((u1 *) &dummy);
825 *threadrootmethod = NULL;
827 /*That's important, otherwise we get into trouble, if the Runtime static
828 initializer is called before (circular dependency. This is with
829 classpath 0.09. Another important thing is, that this has to happen
830 after initThreads!!! */
832 if (!class_init(class_new(utf_new_char("java/lang/System"))))
833 throw_main_exception_exit();
836 cacao_initializing = false;
839 /* start worker routines **************************************************/
842 classinfo *cl; /* java/lang/ClassLoader */
843 classinfo *mainclass; /* java/lang/Class */
848 /* set return value to OK */
853 /* open jar file with java.util.jar.JarFile */
854 mainstring = getmainclassnamefromjar((JNIEnv *) &env, mainstring);
857 /* get system classloader */
859 m = class_resolveclassmethod(class_java_lang_ClassLoader,
860 utf_new_char("getSystemClassLoader"),
861 utf_new_char("()Ljava/lang/ClassLoader;"),
862 class_java_lang_Object,
865 cl = (classinfo *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
867 /* get `loadClass' method */
869 m = class_resolveclassmethod(cl->header.vftbl->class,
870 utf_new_char("loadClass"),
871 utf_new_char("(Ljava/lang/String;)Ljava/lang/Class;"),
872 class_java_lang_Object,
875 /* load the main class */
878 (classinfo *) asm_calljavafunction(m,
880 javastring_new_char(mainstring),
884 /* error loading class, clear exceptionptr for new exception */
886 if (*exceptionptr || !mainclass) {
887 /* *exceptionptr = NULL; */
889 /* *exceptionptr = */
890 /* new_exception_message(string_java_lang_NoClassDefFoundError, */
892 throw_main_exception_exit();
895 /* find the `main' method of the main class */
897 m = class_resolveclassmethod(mainclass,
898 utf_new_char("main"),
899 utf_new_char("([Ljava/lang/String;)V"),
900 class_java_lang_Object,
903 /* there is no main method or it isn't static */
905 if (*exceptionptr || !m || !(m->flags & ACC_STATIC)) {
906 *exceptionptr = NULL;
909 new_exception_message(string_java_lang_NoSuchMethodError,
911 throw_main_exception_exit();
914 /* build argument array */
916 a = builtin_anewarray(argc - opt_ind, class_java_lang_String);
917 for (i = opt_ind; i < argc; i++) {
918 a->data[i - opt_ind] =
919 (java_objectheader *) javastring_new(utf_new_char(argv[i]));
922 #ifdef TYPEINFO_DEBUG_TEST
923 /* test the typeinfo system */
926 /*class_showmethods(currentThread->group->header.vftbl->class); */
928 *threadrootmethod = m;
932 asm_calljavafunction(m, a, NULL, NULL, NULL);
934 /* exception occurred? */
936 throw_main_exception();
940 #if defined(USE_THREADS)
941 #if defined(NATIVE_THREADS)
944 killThread(currentThread);
948 /* now exit the JavaVM */
953 /************* If requested, compile all methods ********************/
961 /* create all classes found in the classpath */
962 /* XXX currently only works with zip/jar's */
963 create_all_classes();
965 /* load and link all classes */
966 for (slot = 0; slot < class_hash.size; slot++) {
967 c = class_hash.ptr[slot];
972 throw_main_exception_exit();
976 throw_main_exception_exit();
978 /* compile all class methods */
979 for (i = 0; i < c->methodscount; i++) {
980 m = &(c->methods[i]);
982 (void) jit_compile(m);
992 /******** If requested, compile a specific method ***************/
994 if (specificmethodname) {
997 /* create, load and link the main class */
998 mainclass = class_new(utf_new_char(mainstring));
1000 if (!class_load(mainclass))
1001 throw_main_exception_exit();
1003 if (!class_link(mainclass))
1004 throw_main_exception_exit();
1006 if (specificsignature) {
1007 m = class_resolveclassmethod(mainclass,
1008 utf_new_char(specificmethodname),
1009 utf_new_char(specificsignature),
1013 m = class_resolveclassmethod(mainclass,
1014 utf_new_char(specificmethodname),
1021 char message[MAXLOGTEXT];
1022 sprintf(message, "%s%s", specificmethodname,
1023 specificsignature ? specificsignature : "");
1026 new_exception_message(string_java_lang_NoSuchMethodException,
1029 throw_main_exception_exit();
1037 /* keep compiler happy */
1043 /* cacao_exit ******************************************************************
1045 Calls java.lang.Runtime.exit(I)V to exit the JavaVM correctly.
1047 *******************************************************************************/
1049 void cacao_exit(s4 status)
1054 /* class should already be loaded, but who knows... */
1056 c = class_new(utf_new_char("java/lang/System"));
1059 throw_main_exception_exit();
1062 throw_main_exception_exit();
1064 /* call System.exit(I)V */
1066 m = class_resolveclassmethod(c,
1067 utf_new_char("exit"),
1068 utf_new_char("(I)V"),
1069 class_java_lang_Object,
1073 throw_main_exception_exit();
1075 /* call the exit function with passed exit status */
1077 /* both inlinevirtual and outsiders not allowed on exit */
1078 /* not sure if permanant or temp restriction */
1079 if (inlinevirtuals) inlineoutsiders = false;
1081 asm_calljavafunction(m, (void *) (ptrint) status, NULL, NULL, NULL);
1083 /* this should never happen */
1086 throw_exception_exit();
1088 throw_cacao_exception_exit(string_java_lang_InternalError,
1089 "System.exit(I)V returned without exception");
1093 /*************************** Shutdown function *********************************
1095 Terminates the system immediately without freeing memory explicitly (to be
1096 used only for abnormal termination)
1098 *******************************************************************************/
1100 void cacao_shutdown(s4 status)
1102 if (opt_verbose || getcompilingtime || opt_stat) {
1103 log_text("CACAO terminated by shutdown");
1104 dolog("Exit status: %d\n", (s4) status);
1112 * These are local overrides for various environment variables in Emacs.
1113 * Please do not remove this and leave it at the end of the file, where
1114 * Emacs will automagically detect them.
1115 * ---------------------------------------------------------------------
1118 * indent-tabs-mode: t