1 /* main.c - contains main() and variables for the global options
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Reinhard Grafl
34 This module does the following tasks:
35 - Command line option handling
36 - Calling initialization routines
37 - Calling the class loader
38 - Running the main method
40 $Id: cacao.c 800 2003-12-16 22:47:59Z edwin $
56 #include "threads/thread.h"
57 #include "toolbox/loging.h"
58 #include "toolbox/memory.h"
59 #include "parseRTstats.h"
60 #include "typeinfo.h" /* XXX remove debug */
61 #include "nat/java_lang_Throwable.h"
64 /* command line option */
67 bool compileall = false;
68 bool runverbose = false;
69 bool collectverbose = false;
71 bool loadverbose = false;
72 bool linkverbose = false;
73 bool initverbose = false;
75 bool opt_rt = false; /* true if RTA parse should be used RT-CO */
76 bool opt_xta = false; /* true if XTA parse should be used XTA-CO */
77 bool opt_vta = false; /* true if VTA parse should be used VTA-CO */
79 bool showmethods = false;
80 bool showconstantpool = false;
83 bool compileverbose = false;
84 bool showstack = false;
85 bool showdisassemble = false;
86 bool showddatasegment = false;
87 bool showintermediate = false;
89 bool useinlining = false;
90 bool inlinevirtuals = false;
91 bool inlineexceptions = false;
92 bool inlineparamopt = false;
93 bool inlineoutsiders = false;
95 bool checkbounds = true;
96 bool checknull = true;
97 bool opt_noieee = false;
98 bool checksync = true;
99 bool opt_loops = false;
101 bool makeinitializations = true;
103 bool getloadingtime = false; /* to measure the runtime */
106 bool opt_verify = true; /* true if classfiles should be verified */
109 static classinfo *topclass;
112 void **stackbottom = 0;
116 /* internal function: get_opt *************************************************
118 decodes the next command line option
120 ******************************************************************************/
126 #define OPT_CLASSPATH 2
130 #define OPT_VERBOSE1 6
131 #define OPT_VERBOSE 7
132 #define OPT_VERBOSEGC 8
133 #define OPT_VERBOSECALL 9
134 #define OPT_NOIEEE 10
135 #define OPT_SOFTNULL 11
141 #define OPT_METHOD 17
142 #define OPT_SIGNATURE 18
146 #define OPT_INLINING 25
150 #define OPT_VERBOSETC 29
151 #define OPT_NOVERIFY 30
154 struct {char *name; bool arg; int value;} opts[] = {
155 {"classpath", true, OPT_CLASSPATH},
157 {"ms", true, OPT_MS},
158 {"mx", true, OPT_MX},
159 {"noasyncgc", false, OPT_IGNORE},
160 {"noverify", false, OPT_NOVERIFY},
161 {"oss", true, OPT_IGNORE},
162 {"ss", true, OPT_IGNORE},
163 {"v", false, OPT_VERBOSE1},
164 {"verbose", false, OPT_VERBOSE},
165 {"verbosegc", false, OPT_VERBOSEGC},
166 {"verbosecall", false, OPT_VERBOSECALL},
167 #ifdef TYPECHECK_VERBOSE
168 {"verbosetc", false, OPT_VERBOSETC},
170 #if defined(__ALPHA__)
171 {"noieee", false, OPT_NOIEEE},
173 {"softnull", false, OPT_SOFTNULL},
174 {"time", false, OPT_TIME},
175 {"stat", false, OPT_STAT},
176 {"log", true, OPT_LOG},
177 {"c", true, OPT_CHECK},
178 {"l", false, OPT_LOAD},
179 {"m", true, OPT_METHOD},
180 {"sig", true, OPT_SIGNATURE},
181 {"s", true, OPT_SHOW},
182 {"all", false, OPT_ALL},
183 {"oloop", false, OPT_OLOOP},
184 {"i", true, OPT_INLINING},
185 {"rt", false, OPT_RT},
186 {"xta", false, OPT_XTA},
187 {"vta", false, OPT_VTA},
191 static int opt_ind = 1;
192 static char *opt_arg;
195 static int get_opt(int argc, char **argv)
200 if (opt_ind >= argc) return OPT_DONE;
203 if (a[0] != '-') return OPT_DONE;
205 for (i = 0; opts[i].name; i++) {
207 if (strcmp(a + 1, opts[i].name) == 0) { /* boolean option found */
209 return opts[i].value;
213 if (strcmp(a + 1, opts[i].name) == 0) { /* parameter option found */
215 if (opt_ind < argc) {
216 opt_arg = argv[opt_ind];
218 return opts[i].value;
223 size_t l = strlen(opts[i].name);
224 if (strlen(a + 1) > l) {
225 if (memcmp(a + 1, opts[i].name, l) == 0) {
228 return opts[i].value;
241 /******************** interne Function: print_usage ************************
243 Prints the correct usage syntax to stdout.
245 ***************************************************************************/
247 static void print_usage()
249 printf("USAGE: cacao [options] classname [program arguments]\n");
250 printf("Options:\n");
251 printf(" -classpath path ...... specify a path to look for classes\n");
252 printf(" -Dpropertyname=value . add an entry to the property list\n");
253 printf(" -mx maxmem[k|m] ...... specify the size for the heap\n");
254 printf(" -ms initmem[k|m] ..... specify the initial size for the heap\n");
255 printf(" -v ................... write state-information\n");
256 printf(" -verbose ............. write more information\n");
257 printf(" -verbosegc ........... write message for each GC\n");
258 printf(" -verbosecall ......... write message for each call\n");
259 #ifdef TYPECHECK_VERBOSE
260 printf(" -verbosetc ........... write debug messages while typechecking\n");
262 #if defined(__ALPHA__)
263 printf(" -noieee .............. don't use ieee compliant arithmetic\n");
265 printf(" -noverify ............ don't verify classfiles\n");
266 printf(" -softnull ............ use software nullpointer check\n");
267 printf(" -time ................ measure the runtime\n");
268 printf(" -stat ................ detailed compiler statistics\n");
269 printf(" -log logfile ......... specify a name for the logfile\n");
270 printf(" -c(heck)b(ounds) ..... don't check array bounds\n");
271 printf(" s(ync) ....... don't check for synchronization\n");
272 printf(" -oloop ............... optimize array accesses in loops\n");
273 printf(" -l ................... don't start the class after loading\n");
274 printf(" -all ................. compile all methods, no execution\n");
275 printf(" -m ................... compile only a specific method\n");
276 printf(" -sig ................. specify signature for a specific method\n");
277 printf(" -s(how)a(ssembler) ... show disassembled listing\n");
278 printf(" c(onstants) ... show the constant pool\n");
279 printf(" d(atasegment).. show data segment listing\n");
280 printf(" i(ntermediate). show intermediate representation\n");
281 printf(" m(ethods)...... show class fields and methods\n");
282 printf(" u(tf) ......... show the utf - hash\n");
283 printf(" -i n ............. activate inlining\n");
284 printf(" v ............. inline virtual methods\n");
285 printf(" e ............. inline methods with exceptions\n");
286 printf(" p ............. optimize argument renaming\n");
287 printf(" o ............. inline methods of foreign classes\n");
288 printf(" -rt .................. use rapid type analysis\n");
289 printf(" -xta ................. use x type analysis\n");
290 printf(" -vta ................. use variable type analysis\n");
295 /***************************** Function: print_times *********************
297 Prints a summary of CPU time usage.
299 **************************************************************************/
301 static void print_times()
303 s8 totaltime = getcputime();
304 s8 runtime = totaltime - loadingtime - compilingtime;
305 char logtext[MAXLOGTEXT];
307 sprintf(logtext, "Time for loading classes: %lld secs, %lld millis",
308 loadingtime / 1000000, (loadingtime % 1000000) / 1000);
310 sprintf(logtext, "Time for compiling code: %lld secs, %lld millis",
311 compilingtime / 1000000, (compilingtime % 1000000) / 1000);
313 sprintf(logtext, "Time for running program: %lld secs, %lld millis",
314 runtime / 1000000, (runtime % 1000000) / 1000);
316 sprintf(logtext, "Total time: %lld secs, %lld millis",
317 totaltime / 1000000, (totaltime % 1000000) / 1000);
326 /***************************** Function: print_stats *********************
328 outputs detailed compiler statistics
330 **************************************************************************/
332 static void print_stats()
334 char logtext[MAXLOGTEXT];
336 sprintf(logtext, "Number of JitCompiler Calls: %d", count_jit_calls);
338 sprintf(logtext, "Number of compiled Methods: %d", count_methods);
340 sprintf(logtext, "Number of max basic blocks per method: %d", count_max_basic_blocks);
342 sprintf(logtext, "Number of compiled basic blocks: %d", count_basic_blocks);
344 sprintf(logtext, "Number of max JavaVM-Instructions per method: %d", count_max_javainstr);
346 sprintf(logtext, "Number of compiled JavaVM-Instructions: %d", count_javainstr);
348 sprintf(logtext, "Size of compiled JavaVM-Instructions: %d(%d)", count_javacodesize,
349 count_javacodesize - count_methods * 18);
351 sprintf(logtext, "Size of compiled Exception Tables: %d", count_javaexcsize);
353 sprintf(logtext, "Value of extended instruction set var: %d", has_ext_instr_set);
355 sprintf(logtext, "Number of Machine-Instructions: %d", count_code_len >> 2);
357 sprintf(logtext, "Number of Spills: %d", count_spills);
359 sprintf(logtext, "Number of Activ Pseudocommands: %5d", count_pcmd_activ);
361 sprintf(logtext, "Number of Drop Pseudocommands: %5d", count_pcmd_drop);
363 sprintf(logtext, "Number of Const Pseudocommands: %5d (zero:%5d)", count_pcmd_load, count_pcmd_zero);
365 sprintf(logtext, "Number of ConstAlu Pseudocommands: %5d (cmp: %5d, store:%5d)", count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
367 sprintf(logtext, "Number of Move Pseudocommands: %5d", count_pcmd_move);
369 sprintf(logtext, "Number of Load Pseudocommands: %5d", count_load_instruction);
371 sprintf(logtext, "Number of Store Pseudocommands: %5d (combined: %5d)", count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
373 sprintf(logtext, "Number of OP Pseudocommands: %5d", count_pcmd_op);
375 sprintf(logtext, "Number of DUP Pseudocommands: %5d", count_dup_instruction);
377 sprintf(logtext, "Number of Mem Pseudocommands: %5d", count_pcmd_mem);
379 sprintf(logtext, "Number of Method Pseudocommands: %5d", count_pcmd_met);
381 sprintf(logtext, "Number of Branch Pseudocommands: %5d (rets:%5d, Xrets: %5d)",
382 count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
384 sprintf(logtext, "Number of Table Pseudocommands: %5d", count_pcmd_table);
386 sprintf(logtext, "Number of Useful Pseudocommands: %5d", count_pcmd_table +
387 count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
389 sprintf(logtext, "Number of Null Pointer Checks: %5d", count_check_null);
391 sprintf(logtext, "Number of Array Bound Checks: %5d", count_check_bound);
393 sprintf(logtext, "Number of Try-Blocks: %d", count_tryblocks);
395 sprintf(logtext, "Maximal count of stack elements: %d", count_max_new_stack);
397 sprintf(logtext, "Upper bound of max stack elements: %d", count_upper_bound_new_stack);
399 sprintf(logtext, "Distribution of stack sizes at block boundary");
401 sprintf(logtext, " 0 1 2 3 4 5 6 7 8 9 >=10");
403 sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_block_stack[0],
404 count_block_stack[1], count_block_stack[2], count_block_stack[3], count_block_stack[4],
405 count_block_stack[5], count_block_stack[6], count_block_stack[7], count_block_stack[8],
406 count_block_stack[9], count_block_stack[10]);
408 sprintf(logtext, "Distribution of store stack depth");
410 sprintf(logtext, " 0 1 2 3 4 5 6 7 8 9 >=10");
412 sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_depth[0],
413 count_store_depth[1], count_store_depth[2], count_store_depth[3], count_store_depth[4],
414 count_store_depth[5], count_store_depth[6], count_store_depth[7], count_store_depth[8],
415 count_store_depth[9], count_store_depth[10]);
417 sprintf(logtext, "Distribution of store creator chains first part");
419 sprintf(logtext, " 0 1 2 3 4 5 6 7 8 9 ");
421 sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[0],
422 count_store_length[1], count_store_length[2], count_store_length[3], count_store_length[4],
423 count_store_length[5], count_store_length[6], count_store_length[7], count_store_length[8],
424 count_store_length[9]);
426 sprintf(logtext, "Distribution of store creator chains second part");
428 sprintf(logtext, " 10 11 12 13 14 15 16 17 18 19 >=20");
430 sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_store_length[10],
431 count_store_length[11], count_store_length[12], count_store_length[13], count_store_length[14],
432 count_store_length[15], count_store_length[16], count_store_length[17], count_store_length[18],
433 count_store_length[19], count_store_length[20]);
435 sprintf(logtext, "Distribution of analysis iterations");
437 sprintf(logtext, " 1 2 3 4 >=5");
439 sprintf(logtext, "%5d%5d%5d%5d%5d", count_analyse_iterations[0], count_analyse_iterations[1],
440 count_analyse_iterations[2], count_analyse_iterations[3], count_analyse_iterations[4]);
442 sprintf(logtext, "Distribution of basic blocks per method");
444 sprintf(logtext, " <= 5 <=10 <=15 <=20 <=30 <=40 <=50 <=75 >75");
446 sprintf(logtext, "%5d%5d%5d%5d%5d%5d%5d%5d%5d", count_method_bb_distribution[0],
447 count_method_bb_distribution[1], count_method_bb_distribution[2], count_method_bb_distribution[3],
448 count_method_bb_distribution[4], count_method_bb_distribution[5], count_method_bb_distribution[6],
449 count_method_bb_distribution[7], count_method_bb_distribution[8]);
451 sprintf(logtext, "Distribution of basic block sizes");
454 " 0 1 2 3 4 5 6 7 8 9 <13 <15 <17 <19 <21 <26 <31 >30");
456 sprintf(logtext, "%3d%5d%5d%5d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d%4d",
457 count_block_size_distribution[0], count_block_size_distribution[1], count_block_size_distribution[2],
458 count_block_size_distribution[3], count_block_size_distribution[4], count_block_size_distribution[5],
459 count_block_size_distribution[6], count_block_size_distribution[7], count_block_size_distribution[8],
460 count_block_size_distribution[9], count_block_size_distribution[10], count_block_size_distribution[11],
461 count_block_size_distribution[12], count_block_size_distribution[13], count_block_size_distribution[14],
462 count_block_size_distribution[15], count_block_size_distribution[16], count_block_size_distribution[17]);
464 sprintf(logtext, "Size of Code Area (Kb): %10.3f", (float) count_code_len / 1024);
466 sprintf(logtext, "Size of data Area (Kb): %10.3f", (float) count_data_len / 1024);
468 sprintf(logtext, "Size of Class Infos (Kb):%10.3f", (float) (count_class_infos) / 1024);
470 sprintf(logtext, "Size of Const Pool (Kb): %10.3f", (float) (count_const_pool_len + count_utf_len) / 1024);
472 sprintf(logtext, "Size of Vftbl (Kb): %10.3f", (float) count_vftbl_len / 1024);
474 sprintf(logtext, "Size of comp stub (Kb): %10.3f", (float) count_cstub_len / 1024);
476 sprintf(logtext, "Size of native stub (Kb):%10.3f", (float) count_nstub_len / 1024);
478 sprintf(logtext, "Size of Utf (Kb): %10.3f", (float) count_utf_len / 1024);
480 sprintf(logtext, "Size of VMCode (Kb): %10.3f(%d)", (float) count_vmcode_len / 1024,
481 count_vmcode_len - 18 * count_all_methods);
483 sprintf(logtext, "Size of ExTable (Kb): %10.3f", (float) count_extable_len / 1024);
485 sprintf(logtext, "Number of class loads: %d", count_class_loads);
487 sprintf(logtext, "Number of class inits: %d", count_class_inits);
489 sprintf(logtext, "Number of loaded Methods: %d\n\n", count_all_methods);
492 sprintf(logtext, "Calls of utf_new: %22d", count_utf_new);
494 sprintf(logtext, "Calls of utf_new (element found): %6d\n\n", count_utf_new_found);
500 /********** Function: class_compile_methods (debugging only) ********/
502 void class_compile_methods ()
508 c = list_first (&linkedclasses);
510 for (i = 0; i < c -> methodscount; i++) {
511 m = &(c->methods[i]);
513 (void) jit_compile(m);
516 c = list_next(&linkedclasses, c);
523 * void exit_handler(void)
524 * -----------------------
525 * The exit_handler function is called upon program termination to shutdown
526 * the various subsystems and release the resources allocated to the VM.
528 void exit_handler(void)
530 /********************* Print debug tables ************************/
532 if (showmethods) class_showmethods(topclass);
533 if (showconstantpool) class_showconstantpool(topclass);
534 if (showutf) utf_show();
537 clear_thread_flags(); /* restores standard file descriptor
541 /************************ Free all resources *******************/
543 heap_close(); /* must be called before compiler_close and
544 loader_close because finalization occurs
548 tables_close(literalstring_free);
550 if (verbose || getcompilingtime || statistics) {
551 log_text("CACAO terminated");
554 if (getcompilingtime)
561 /************************** Function: main *******************************
565 **************************************************************************/
567 int main(int argc, char **argv)
573 /********** interne (nur fuer main relevante Optionen) **************/
575 char logfilename[200] = "";
576 u4 heapsize = 64000000;
577 u4 heapstartsize = 200000;
578 char classpath[500] = ".:/usr/local/lib/java/classes";
580 char *specificmethodname = NULL;
581 char *specificsignature = NULL;
584 stackbottom = &dummy;
587 if (0 != atexit(exit_handler))
588 panic("unable to register exit_handler");
590 /************ Collect info from the environment ************************/
592 cp = getenv("CLASSPATH");
594 strcpy(classpath, cp);
597 /***************** Interpret the command line *****************/
602 while ((i = get_opt(argc, argv)) != OPT_DONE) {
604 case OPT_IGNORE: break;
607 strcpy(classpath + strlen(classpath), ":");
608 strcpy(classpath + strlen(classpath), opt_arg);
614 int l = strlen(opt_arg);
615 for (n = 0; n < l; n++) {
616 if (opt_arg[n] == '=') {
618 attach_property(opt_arg, opt_arg + n + 1);
631 if (opt_arg[strlen(opt_arg) - 1] == 'k') {
632 j = 1024 * atoi(opt_arg);
634 else if (opt_arg[strlen(opt_arg) - 1] == 'm') {
635 j = 1024 * 1024 * atoi(opt_arg);
637 else j = atoi(opt_arg);
639 if (i == OPT_MX) heapsize = j;
640 else heapstartsize = j;
651 compileverbose = true;
655 collectverbose = true;
658 #ifdef TYPECHECK_VERBOSE
660 typecheckverbose = true;
664 case OPT_VERBOSECALL:
681 getcompilingtime = true;
682 getloadingtime = true;
690 strcpy(logfilename, opt_arg);
694 for (j = 0; j < strlen(opt_arg); j++) {
695 switch (opt_arg[j]) {
711 makeinitializations = false;
716 specificmethodname = opt_arg;
717 makeinitializations = false;
721 specificsignature = opt_arg;
727 makeinitializations = false;
730 case OPT_SHOW: /* Display options */
731 for (j = 0; j < strlen(opt_arg); j++) {
732 switch (opt_arg[j]) {
734 showdisassemble = true;
738 showconstantpool = true;
741 showddatasegment = true;
744 showintermediate = true;
745 compileverbose = true;
765 for (j = 0; j < strlen(opt_arg); j++) {
766 switch (opt_arg[j]) {
771 inlinevirtuals = true;
774 inlineexceptions = true;
777 inlineparamopt = true;
780 inlineoutsiders = true;
794 opt_xta = false; /**not yet **/
798 /***opt_vta = true; not yet **/
808 if (opt_ind >= argc) {
814 /**************************** Program start *****************************/
816 log_init(logfilename);
818 log_text("CACAO started -------------------------------------------------------");
821 suck_init(classpath);
822 native_setclasspath(classpath);
825 heap_init(heapsize, heapstartsize, &dummy);
827 log_text("calling jit_init");
830 log_text("calling loader_init");
831 loader_init((u1 *) &dummy);
833 log_text("calling native_loadclasses");
834 native_loadclasses();
837 /*********************** Load JAVA classes ***************************/
839 cp = argv[opt_ind++];
840 for (i = strlen(cp) - 1; i >= 0; i--) { /* Transform dots into slashes */
841 if (cp[i] == '.') cp[i] = '/'; /* in the class name */
844 topclass = loader_load(utf_new_char(cp));
846 if (exceptionptr != 0) {
847 printf("Exception in thread \"main\" ");
848 utf_display(exceptionptr->vftbl->class->name);
850 utf_display(javastring_toutf(((java_lang_Throwable *) exceptionptr)->detailMessage, false));
857 /* should we print out something? we already have the exception */
861 /* initialize the garbage collector */
865 initThreads((u1*) &dummy);
869 /************************* Start worker routines ********************/
872 methodinfo *mainmethod;
875 /* heap_addreference((void**) &a); */
877 mainmethod = class_findmethod(topclass,
878 utf_new_char("main"),
879 utf_new_char("([Ljava/lang/String;)V")
882 /* there is no main method or it isn't static */
883 if (!mainmethod || !(mainmethod->flags & ACC_STATIC)) {
884 printf("Exception in thread \"main\" java.lang.NoSuchMethodError: main\n");
888 a = builtin_anewarray(argc - opt_ind, class_java_lang_String);
889 for (i = opt_ind; i < argc; i++) {
890 a->data[i - opt_ind] = javastring_new(utf_new_char(argv[i]));
893 #ifdef TYPEINFO_DEBUG_TEST
894 /* test the typeinfo system */
897 /*class_showmethods(currentThread->group->header.vftbl->class); */
900 asm_calljavafunction(mainmethod, a, NULL, NULL, NULL);
903 printf("Exception in thread \"main\" ");
904 utf_display(exceptionptr->vftbl->class->name);
906 /* do we have a detail message? */
907 if (((java_lang_Throwable *) exceptionptr)->detailMessage) {
909 utf_display(javastring_toutf(((java_lang_Throwable *) exceptionptr)->detailMessage, false));
915 killThread(currentThread);
917 fprintf(stderr, "still here\n");
920 /************* If requested, compile all methods ********************/
923 class_compile_methods();
927 /******** If requested, compile a specific method ***************/
929 if (specificmethodname) {
931 if (specificsignature) {
932 m = class_findmethod(topclass,
933 utf_new_char(specificmethodname),
934 utf_new_char(specificsignature));
936 m = class_findmethod(topclass,
937 utf_new_char(specificmethodname),
942 panic("Specific method not found");
952 /************************************ Shutdown function *********************************
954 Terminates the system immediately without freeing memory explicitly (to be
955 used only for abnormal termination)
957 *****************************************************************************************/
959 void cacao_shutdown(s4 status)
963 if (verbose || getcompilingtime || statistics) {
964 log_text ("CACAO terminated by shutdown");
967 if (getcompilingtime)
970 dolog("Exit status: %d\n", (int) status);
978 * These are local overrides for various environment variables in Emacs.
979 * Please do not remove this and leave it at the end of the file, where
980 * Emacs will automagically detect them.
981 * ---------------------------------------------------------------------
984 * indent-tabs-mode: t