- implemented bootclasspath usage
[cacao.git] / src / cacao / cacao.c
1 /* cacao/cacao.c - contains main() of cacao
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    Changes: Andi Krall
30             Mark Probst
31             Philipp Tomsich
32
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
38
39    $Id: cacao.c 1834 2004-12-29 15:00:25Z twisti $
40
41 */
42
43
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include "cacao/cacao.h"
48 #include "mm/boehm.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"
61
62 #ifdef TYPEINFO_DEBUG_TEST
63 #include "vm/jit/verify/typeinfo.h"
64 #endif
65
66
67 /* define heap sizes **********************************************************/
68
69 #define HEAP_MAXSIZE      64 * 1024 * 1024; /* default 64MB                   */
70 #define HEAP_STARTSIZE    2 * 1024 * 1024;  /* default 2MB                    */
71
72
73 bool cacao_initializing;
74
75 char *bootclasspath;                    /* contains the boot classpath        */
76 char *classpath;                        /* contains the classpath             */
77
78 char *mainstring;
79 static classinfo *mainclass;
80
81 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
82 void **stackbottom = 0;
83 #endif
84
85
86 /* define command line options ************************************************/
87
88 #define OPT_CLASSPATH        2
89 #define OPT_D                3
90 #define OPT_MS               4
91 #define OPT_MX               5
92 #define OPT_VERBOSE1         6
93 #define OPT_VERBOSE          7
94 #define OPT_VERBOSEGC        8
95 #define OPT_VERBOSECALL      9
96 #define OPT_NOIEEE           10
97 #define OPT_SOFTNULL         11
98 #define OPT_TIME             12
99 #define OPT_STAT             13
100 #define OPT_LOG              14
101 #define OPT_CHECK            15
102 #define OPT_LOAD             16
103 #define OPT_METHOD           17
104 #define OPT_SIGNATURE        18
105 #define OPT_SHOW             19
106 #define OPT_ALL              20
107 #define OPT_OLOOP            24
108 #define OPT_INLINING         25
109
110 #if defined(STATIC_ANALYSIS)
111 # define OPT_RT              26
112 # define OPT_XTA             27 
113 # define OPT_VTA             28
114 #endif /* STATIC_ANALYSIS */
115
116 #define OPT_VERBOSETC        29
117 #define OPT_NOVERIFY         30
118 #define OPT_LIBERALUTF       31
119 #define OPT_VERBOSEEXCEPTION 32
120 #define OPT_EAGER            33
121
122 #if defined(LSRA)
123 # define OPT_LSRA            34
124 #endif /* LSRA */
125
126 #define OPT_JAR              35
127 #define OPT_BOOTCLASSPATH    36
128 #define OPT_BOOTCLASSPATH_A  37
129 #define OPT_BOOTCLASSPATH_P  38
130
131
132 opt_struct opts[] = {
133         { "classpath",         true,  OPT_CLASSPATH },
134         { "cp",                true,  OPT_CLASSPATH },
135         { "D",                 true,  OPT_D },
136         { "Xms",               true,  OPT_MS },
137         { "Xmx",               true,  OPT_MX },
138         { "ms",                true,  OPT_MS },
139         { "mx",                true,  OPT_MX },
140         { "noasyncgc",         false, OPT_IGNORE },
141         { "noverify",          false, OPT_NOVERIFY },
142         { "liberalutf",        false, OPT_LIBERALUTF },
143         { "oss",               true,  OPT_IGNORE },
144         { "ss",                true,  OPT_IGNORE },
145         { "v",                 false, OPT_VERBOSE1 },
146         { "verbose",           false, OPT_VERBOSE },
147         { "verbosegc",         false, OPT_VERBOSEGC },
148         { "verbosecall",       false, OPT_VERBOSECALL },
149         { "verboseexception",  false, OPT_VERBOSEEXCEPTION },
150 #ifdef TYPECHECK_VERBOSE
151         { "verbosetc",         false, OPT_VERBOSETC },
152 #endif
153 #if defined(__ALPHA__)
154         { "noieee",            false, OPT_NOIEEE },
155 #endif
156         { "softnull",          false, OPT_SOFTNULL },
157         { "time",              false, OPT_TIME },
158         { "stat",              false, OPT_STAT },
159         { "log",               true,  OPT_LOG },
160         { "c",                 true,  OPT_CHECK },
161         { "l",                 false, OPT_LOAD },
162     { "eager",             false, OPT_EAGER },
163         { "m",                 true,  OPT_METHOD },
164         { "sig",               true,  OPT_SIGNATURE },
165         { "s",                 true,  OPT_SHOW },
166         { "all",               false, OPT_ALL },
167         { "oloop",             false, OPT_OLOOP },
168         { "i",                 true,  OPT_INLINING },
169 #ifdef STATIC_ANALYSIS
170         { "rt",                false, OPT_RT },
171         { "xta",               false, OPT_XTA },
172         { "vta",               false, OPT_VTA },
173 #endif
174 #ifdef LSRA
175         { "lsra",              false, OPT_LSRA },
176 #endif
177         { "jar",               false, OPT_JAR },
178         { "Xbootclasspath:",   true,  OPT_BOOTCLASSPATH },
179         { "Xbootclasspath/a:", true,  OPT_BOOTCLASSPATH_A },
180         { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
181         { NULL,                false, 0 }
182 };
183
184
185 /******************** interne Function: print_usage ************************
186
187 Prints the correct usage syntax to stdout.
188
189 ***************************************************************************/
190
191 static void usage()
192 {
193         printf("Usage: cacao [options] classname [program arguments]\n\n");
194
195         printf("Options:\n");
196         printf("    -cp <path>               specify a path to look for classes\n");
197         printf("    -classpath <path>        specify a path to look for classes\n");
198         printf("    -jar jarfile             execute a jar file\n");
199         printf("    -D<name>=<value>         add an entry to the property list\n");
200         printf("    -Xmx<size>[kK|mM]        specify the size for the heap\n");
201         printf("    -Xms<size>[kK|mM]        specify the initial size for the heap\n");
202         printf("    -mx<size>[kK|mM]         specify the size for the heap\n");
203         printf("    -ms<size>[kK|mM]         specify the initial size for the heap\n");
204         printf("    -Xbootclasspath:<path>   set search path for bootstrap classes and resources\n");
205         printf("    -Xbootclasspath/a:<path> append to end of bootstrap class path\n");
206         printf("    -Xbootclasspath/p:<path> prepend in front of bootstrap class path\n");
207         printf("          -v ................... write state-information\n");
208         printf("          -verbose ............. write more information\n");
209         printf("          -verbosegc ........... write message for each GC\n");
210         printf("          -verbosecall ......... write message for each call\n");
211         printf("          -verboseexception .... write message for each step of stack unwinding\n");
212 #ifdef TYPECHECK_VERBOSE
213         printf("          -verbosetc ........... write debug messages while typechecking\n");
214 #endif
215 #if defined(__ALPHA__)
216         printf("          -noieee .............. don't use ieee compliant arithmetic\n");
217 #endif
218         printf("          -noverify ............ don't verify classfiles\n");
219         printf("          -liberalutf........... don't warn about overlong UTF-8 sequences\n");
220         printf("          -softnull ............ use software nullpointer check\n");
221         printf("          -time ................ measure the runtime\n");
222         printf("          -stat ................ detailed compiler statistics\n");
223         printf("          -log logfile ......... specify a name for the logfile\n");
224         printf("          -c(heck)b(ounds) ..... don't check array bounds\n");
225         printf("                  s(ync) ....... don't check for synchronization\n");
226         printf("          -oloop ............... optimize array accesses in loops\n"); 
227         printf("          -l ................... don't start the class after loading\n");
228         printf("          -eager ............... perform eager class loading and linking\n");
229         printf("          -all ................. compile all methods, no execution\n");
230         printf("          -m ................... compile only a specific method\n");
231         printf("          -sig ................. specify signature for a specific method\n");
232         printf("          -s(how)a(ssembler) ... show disassembled listing\n");
233         printf("                 c(onstants) ... show the constant pool\n");
234         printf("                 d(atasegment).. show data segment listing\n");
235         printf("                 i(ntermediate). show intermediate representation\n");
236         printf("                 m(ethods)...... show class fields and methods\n");
237         printf("                 u(tf) ......... show the utf - hash\n");
238         printf("          -i     n ............. activate inlining\n");
239         printf("                 v ............. inline virtual methods\n");
240         printf("                                 uses/turns rt option on\n");
241         printf("                 e ............. inline methods with exceptions\n");
242         printf("                 p ............. optimize argument renaming\n");
243         printf("                 o ............. inline methods of foreign classes\n");
244 #ifdef STATIC_ANALYSIS
245         printf("          -rt .................. use rapid type analysis\n");
246         printf("          -xta ................. use x type analysis\n");
247         printf("          -vta ................. use variable type analysis\n");
248 #endif
249 #ifdef LSRA
250         printf("          -lsra ................ use linear scan register allocation\n");
251 #endif
252
253         /* exit with error code */
254
255         exit(1);
256 }   
257
258
259 #ifdef TYPECHECK_STATISTICS
260 void typecheck_print_statistics(FILE *file);
261 #endif
262
263
264
265 /******************** getmainclassfromjar ************************
266
267 gets the name of the main class form a jar's manifest file
268
269 ***************************************************************************/
270 char *getmainclassnamefromjar(mainstring)
271 {
272         jclass class;
273         jmethodID mid;
274         jobject obj;
275                 
276         class = env->FindClass(NULL, "java/util/jar/JarFile");
277         if (class == NULL) {
278                 log_text("unable to find java.util.jar.JarFile");
279                 throw_main_exception_exit();
280         }
281         
282         mid = env->GetMethodID(NULL, class, "<init>","(Ljava/lang/String;)V");
283         if (mid == NULL) {
284                 log_text("unable to find constructor in java.util.jar.JarFile");
285                 cacao_exit(1);
286         }
287
288         /* open jarfile */
289         obj = env->NewObject(NULL,class,mid,(env->NewStringUTF(NULL,(char*)mainstring)));
290         if (env->ExceptionOccurred(NULL) != NULL) {
291                 env->ExceptionDescribe(NULL);
292                 cacao_exit(1);
293         }
294         
295         mid = env->GetMethodID(NULL, class, "getManifest","()Ljava/util/jar/Manifest;");
296         if (mid == NULL) {
297                 log_text("unable to find getMainfest method");
298                 cacao_exit(1);
299         }
300
301         /* get manifest object */
302         obj = env->CallObjectMethod(NULL,obj,mid);
303         if (env->ExceptionOccurred(NULL) != NULL) {
304                 env->ExceptionDescribe(NULL);
305                 cacao_exit(1);
306         }
307
308         mid = env->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getMainAttributes","()Ljava/util/jar/Attributes;");
309         if (mid == NULL) {
310                 log_text("unable to find getMainAttributes method");
311                 cacao_exit(1);
312         }
313
314         /* get Main Attributes */
315         obj = env->CallObjectMethod(NULL,obj,mid);
316         if (env->ExceptionOccurred(NULL) != NULL) {
317                 env->ExceptionDescribe(NULL);
318                 cacao_exit(1);
319         }
320
321
322         mid = env->GetMethodID(NULL, (jclass)((java_objectheader*) obj)->vftbl->class, "getValue","(Ljava/lang/String;)Ljava/lang/String;");
323         if (mid == NULL) {
324                 log_text("unable to find getValue method");
325                 cacao_exit(1);
326         }
327
328         /* get property Main-Class */
329         obj = env->CallObjectMethod(NULL,obj,mid,env->NewStringUTF(NULL,"Main-Class"));
330         if (env->ExceptionOccurred(NULL) != NULL) {
331                 env->ExceptionDescribe(NULL);
332                 cacao_exit(1);
333         }
334         
335         return javastring_tochar((java_objectheader *) obj);
336 }
337
338
339 /*
340  * void exit_handler(void)
341  * -----------------------
342  * The exit_handler function is called upon program termination to shutdown
343  * the various subsystems and release the resources allocated to the VM.
344  */
345 void exit_handler(void)
346 {
347         /********************* Print debug tables ************************/
348                                 
349         if (showmethods) class_showmethods(mainclass);
350         if (showconstantpool) class_showconstantpool(mainclass);
351         if (showutf) utf_show();
352
353 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
354         clear_thread_flags();           /* restores standard file descriptor
355                                        flags */
356 #endif
357
358         /************************ Free all resources *******************/
359
360         loader_close();
361         tables_close();
362
363         MFREE(classpath, u1, strlen(classpath));
364
365         if (opt_verbose || getcompilingtime || opt_stat) {
366                 log_text("CACAO terminated");
367                 if (opt_stat) {
368                         print_stats();
369 #ifdef TYPECHECK_STATISTICS
370                         typecheck_print_statistics(get_logfile());
371 #endif
372                 }
373                 if (getcompilingtime)
374                         print_times();
375                 mem_usagelog(1);
376         }
377 }
378
379
380 /************************** Function: main *******************************
381
382    The main program.
383    
384 **************************************************************************/
385
386 int main(int argc, char **argv)
387 {
388         s4 i, j;
389         void *dummy;
390         
391         /********** interne (nur fuer main relevante Optionen) **************/
392    
393         char logfilename[200] = "";
394         u4 heapmaxsize;
395         u4 heapstartsize;
396         char *cp;
397         s4    cplen;
398         bool startit = true;
399         char *specificmethodname = NULL;
400         char *specificsignature = NULL;
401         bool jar = false;
402
403 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
404         stackbottom = &dummy;
405 #endif
406         
407         if (atexit(exit_handler))
408                 throw_cacao_exception_exit(string_java_lang_InternalError,
409                                                                    "Unable to register exit_handler");
410
411
412         /************ Collect info from the environment ************************/
413
414         /* set the bootclasspath */
415
416         cp = getenv("BOOTCLASSPATH");
417         if (cp) {
418                 bootclasspath = MNEW(char, strlen(cp) + 1);
419                 strcpy(bootclasspath, cp);
420
421         } else {
422                 cplen = strlen(INSTALL_PREFIX) + strlen(CACAO_RT_JAR_PATH);
423
424                 bootclasspath = MNEW(char, cplen + 1);
425                 strcpy(bootclasspath, INSTALL_PREFIX);
426                 strcat(bootclasspath, CACAO_RT_JAR_PATH);
427         }
428
429
430         /* set the classpath */
431
432         cp = getenv("CLASSPATH");
433         if (cp) {
434                 classpath = MNEW(char, strlen(cp) + 1);
435                 strcat(classpath, cp);
436
437         } else {
438                 classpath = MNEW(char, 2);
439                 strcpy(classpath, ".");
440         }
441
442
443         /***************** Interpret the command line *****************/
444    
445         checknull = false;
446         opt_noieee = false;
447
448         heapmaxsize = HEAP_MAXSIZE;
449         heapstartsize = HEAP_STARTSIZE;
450
451
452         while ((i = get_opt(argc, argv, opts)) != OPT_DONE) {
453                 switch (i) {
454                 case OPT_IGNORE:
455                         break;
456                         
457                 case OPT_BOOTCLASSPATH:
458                         /* Forget default bootclasspath and set the argument as new boot  */
459                         /* classpath.                                                     */
460                         MFREE(bootclasspath, char, strlen(bootclasspath));
461
462                         bootclasspath = MNEW(char, strlen(opt_arg) + 1);
463                         strcpy(bootclasspath, opt_arg);
464                         break;
465
466                 case OPT_BOOTCLASSPATH_A:
467                         /* append to end of bootclasspath */
468                         cplen = strlen(bootclasspath);
469
470                         bootclasspath = MREALLOC(bootclasspath,
471                                                                          char,
472                                                                          cplen,
473                                                                          cplen + 1 + strlen(opt_arg) + 1);
474
475                         strcat(bootclasspath, ":");
476                         strcat(bootclasspath, opt_arg);
477                         break;
478
479                 case OPT_BOOTCLASSPATH_P:
480                         /* prepend in front of bootclasspath */
481                         cp = bootclasspath;
482                         cplen = strlen(cp);
483
484                         bootclasspath = MNEW(char, strlen(opt_arg) + 1 + cplen + 1);
485
486                         strcpy(bootclasspath, opt_arg);
487                         strcat(bootclasspath, ":");
488                         strcat(bootclasspath, cp);
489
490                         MFREE(cp, char, cplen);
491                         break;
492
493                 case OPT_CLASSPATH:
494                         /* forget old classpath and set the argument as new classpath */
495                         MFREE(classpath, char, strlen(classpath));
496
497                         classpath = MNEW(char, strlen(opt_arg) + 1);
498                         strcpy(classpath, opt_arg);
499                         break;
500
501                 case OPT_JAR:
502                         jar = true;
503                         break;
504                         
505                 case OPT_D:
506                         {
507                                 int n;
508                                 int l = strlen(opt_arg);
509                                 for (n = 0; n < l; n++) {
510                                         if (opt_arg[n] == '=') {
511                                                 opt_arg[n] = '\0';
512                                                 create_property(opt_arg, opt_arg + n + 1);
513                                                 goto didit;
514                                         }
515                                 }
516                                 usage();
517                                         
518                         didit: ;
519                         }       
520                         break;
521
522                 case OPT_MS:
523                 case OPT_MX:
524                         {
525                                 char c;
526                                 c = opt_arg[strlen(opt_arg) - 1];
527
528                                 if (c == 'k' || c == 'K') {
529                                         j = 1024 * atoi(opt_arg);
530
531                                 } else if (c == 'm' || c == 'M') {
532                                         j = 1024 * 1024 * atoi(opt_arg);
533
534                                 } else j = atoi(opt_arg);
535
536                                 if (i == OPT_MX) heapmaxsize = j;
537                                 else heapstartsize = j;
538                         }
539                         break;
540
541                 case OPT_VERBOSE1:
542                         opt_verbose = true;
543                         break;
544
545                 case OPT_VERBOSE:
546                         opt_verbose = true;
547                         loadverbose = true;
548                         linkverbose = true;
549                         initverbose = true;
550                         compileverbose = true;
551                         break;
552
553                 case OPT_VERBOSEEXCEPTION:
554                         verboseexception = true;
555                         break;
556
557                 case OPT_VERBOSEGC:
558                         collectverbose = true;
559                         break;
560
561 #ifdef TYPECHECK_VERBOSE
562                 case OPT_VERBOSETC:
563                         typecheckverbose = true;
564                         break;
565 #endif
566                                 
567                 case OPT_VERBOSECALL:
568                         runverbose = true;
569                         break;
570                                 
571                 case OPT_NOIEEE:
572                         opt_noieee = true;
573                         break;
574
575                 case OPT_NOVERIFY:
576                         opt_verify = false;
577                         break;
578
579                 case OPT_LIBERALUTF:
580                         opt_liberalutf = true;
581                         break;
582
583                 case OPT_SOFTNULL:
584                         checknull = true;
585                         break;
586
587                 case OPT_TIME:
588                         getcompilingtime = true;
589                         getloadingtime = true;
590                         break;
591                                         
592                 case OPT_STAT:
593                         opt_stat = true;
594                         break;
595                                         
596                 case OPT_LOG:
597                         strcpy(logfilename, opt_arg);
598                         break;
599                         
600                 case OPT_CHECK:
601                         for (j = 0; j < strlen(opt_arg); j++) {
602                                 switch (opt_arg[j]) {
603                                 case 'b':
604                                         checkbounds = false;
605                                         break;
606                                 case 's':
607                                         checksync = false;
608                                         break;
609                                 default:
610                                         usage();
611                                 }
612                         }
613                         break;
614                         
615                 case OPT_LOAD:
616                         startit = false;
617                         makeinitializations = false;
618                         break;
619
620                 case OPT_EAGER:
621                         opt_eager = true;
622                         break;
623
624                 case OPT_METHOD:
625                         startit = false;
626                         specificmethodname = opt_arg;
627                         makeinitializations = false;
628                         break;
629                         
630                 case OPT_SIGNATURE:
631                         specificsignature = opt_arg;
632                         break;
633                         
634                 case OPT_ALL:
635                         compileall = true;
636                         startit = false;
637                         makeinitializations = false;
638                         break;
639                         
640                 case OPT_SHOW:       /* Display options */
641                         for (j = 0; j < strlen(opt_arg); j++) {         
642                                 switch (opt_arg[j]) {
643                                 case 'a':
644                                         showdisassemble = true;
645                                         compileverbose = true;
646                                         break;
647                                 case 'c':
648                                         showconstantpool = true;
649                                         break;
650                                 case 'd':
651                                         showddatasegment = true;
652                                         break;
653                                 case 'i':
654                                         showintermediate = true;
655                                         compileverbose = true;
656                                         break;
657                                 case 'm':
658                                         showmethods = true;
659                                         break;
660                                 case 'u':
661                                         showutf = true;
662                                         break;
663                                 default:
664                                         usage();
665                                 }
666                         }
667                         break;
668                         
669                 case OPT_OLOOP:
670                         opt_loops = true;
671                         break;
672
673                 case OPT_INLINING:
674                         for (j = 0; j < strlen(opt_arg); j++) {         
675                                 switch (opt_arg[j]) {
676                                 case 'n':
677                                      /* define in options.h; Used in main.c, jit.c & inline.c */
678                                      #ifdef INAFTERMAIN
679                                         useinliningm = true;
680                                         useinlining = false;
681                                      #else
682                                         useinlining = true;
683                                      #endif
684                                         break;
685                                 case 'v':
686                                         inlinevirtuals = true;
687                                         opt_rt = true;
688                                         break;
689                                 case 'e':
690                                         inlineexceptions = true;
691                                         break;
692                                 case 'p':
693                                         inlineparamopt = true;
694                                         break;
695                                 case 'o':
696                                         inlineoutsiders = true;
697                                         break;
698                                 default:
699                                         usage();
700                                 }
701                         }
702                         break;
703
704 #ifdef STATIC_ANALYSIS
705                 case OPT_RT:
706                         opt_rt = true;
707                         break;
708
709                 case OPT_XTA:
710                         opt_xta = false; /**not yet **/
711                         break;
712
713                 case OPT_VTA:
714                         /***opt_vta = true; not yet **/
715                         break;
716 #endif
717
718 #ifdef LSRA
719                 case OPT_LSRA:
720 #if defined(__I386__) || defined(__ALPHA__)
721                         opt_lsra = true;
722 #else
723                         printf("LSRA not available for this architecture\n");
724                         opt_lsra = false;
725 #endif
726                         break;
727 #endif
728
729                 default:
730                         printf("Unknown option: %s\n", argv[opt_ind]);
731                         usage();
732                 }
733         }
734
735         if (opt_ind >= argc)
736                 usage();
737
738
739         /* transform dots into slashes in the class name */
740
741         mainstring = argv[opt_ind++];
742         if (!jar) { 
743         /* do not mangle jar filename */
744                 for (i = strlen(mainstring) - 1; i >= 0; i--) {
745                         if (mainstring[i] == '.') mainstring[i] = '/';
746                 }
747
748         } else {
749                 /* put jarfile in classpath */
750                 cp = classpath;
751                 classpath = MNEW(char, strlen(mainstring) + strlen(classpath) + 1);
752                 strcpy(classpath, mainstring);
753                 strcat(classpath, ":");
754                 strcat(classpath, cp);
755                 
756                 MFREE(cp, char, strlen(cp));
757         }
758
759         /**************************** Program start *****************************/
760
761         log_init(logfilename);
762         if (opt_verbose)
763                 log_text("CACAO started -------------------------------------------------------");
764
765         /* initialize the garbage collector */
766
767         gc_init(heapmaxsize, heapstartsize);
768
769         tables_init();
770
771         /* initialize the loader with bootclasspath and append classpath entries */
772
773         suck_init(bootclasspath);
774         suck_init(classpath);
775
776         cacao_initializing = true;
777
778 #if defined(USE_THREADS)
779 #if defined(NATIVE_THREADS)
780         initThreadsEarly();
781 #endif
782         initLocks();
783 #endif
784
785         /* install architecture dependent signal handler used for exceptions */
786         init_exceptions();
787
788         /* initializes jit compiler and codegen stuff */
789         jit_init();
790
791         loader_init((u1 *) &dummy);
792
793         /* initialize exceptions used in the system */
794         if (!init_system_exceptions())
795                 throw_main_exception_exit();
796
797         native_loadclasses();
798
799 #if defined(USE_THREADS)
800         initThreads((u1 *) &dummy);
801 #endif
802
803         *threadrootmethod = NULL;
804
805         /*That's important, otherwise we get into trouble, if the Runtime static
806           initializer is called before (circular dependency. This is with
807           classpath 0.09. Another important thing is, that this has to happen
808           after initThreads!!! */
809
810         if (!class_init(class_new(utf_new_char("java/lang/System"))))
811                 throw_main_exception_exit();
812
813 /*        jni_init(); */
814         cacao_initializing = false;
815
816
817         /* start worker routines **************************************************/
818
819         if (startit) {
820                 classinfo        *cl;           /* java/lang/ClassLoader              */
821                 classinfo        *mainclass;    /* java/lang/Class                    */
822                 methodinfo       *m;
823                 java_objectarray *a; 
824                 s4                status;
825
826                 /* set return value to OK */
827
828                 status = 0;
829
830                 if (jar) {
831                         /* open jar file with java.util.jar.JarFile */
832                         mainstring = getmainclassnamefromjar(mainstring);
833                 }
834
835                 /* get system classloader */
836
837                 m = class_resolveclassmethod(class_java_lang_ClassLoader,
838                                                                          utf_new_char("getSystemClassLoader"),
839                                                                          utf_new_char("()Ljava/lang/ClassLoader;"),
840                                                                          class_java_lang_Object,
841                                                                          false);
842
843                 cl = (classinfo *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
844
845                 /* get `loadClass' method */
846
847                 m = class_resolveclassmethod(cl->header.vftbl->class,
848                                                                          utf_new_char("loadClass"),
849                                                                          utf_new_char("(Ljava/lang/String;)Ljava/lang/Class;"),
850                                                                          class_java_lang_Object,
851                                                                          false);
852
853                 /* load the main class */
854
855                 mainclass =
856                         (classinfo *) asm_calljavafunction(m,
857                                                                                            cl,
858                                                                                            javastring_new_char(mainstring),
859                                                                                            NULL,
860                                                                                            NULL);
861
862                 /* error loading class, clear exceptionptr for new exception */
863
864                 if (*exceptionptr || !mainclass) {
865                         *exceptionptr = NULL;
866
867                         *exceptionptr =
868                                 new_exception_message(string_java_lang_NoClassDefFoundError,
869                                                                           mainstring);
870                         throw_main_exception_exit();
871                 }
872
873                 /* find the `main' method of the main class */
874
875                 m = class_resolveclassmethod(mainclass,
876                                                                          utf_new_char("main"), 
877                                                                          utf_new_char("([Ljava/lang/String;)V"),
878                                                                          class_java_lang_Object,
879                                                                          false);
880
881                 /* there is no main method or it isn't static */
882
883                 if (*exceptionptr || !m || !(m->flags & ACC_STATIC)) {
884                         *exceptionptr = NULL;
885
886                         *exceptionptr =
887                                 new_exception_message(string_java_lang_NoSuchMethodError,
888                                                                           "main");
889                         throw_main_exception_exit();
890                 }
891
892                 /* build argument array */
893
894                 a = builtin_anewarray(argc - opt_ind, class_java_lang_String);
895                 for (i = opt_ind; i < argc; i++) {
896                         a->data[i - opt_ind] = 
897                                 (java_objectheader *) javastring_new(utf_new_char(argv[i]));
898                 }
899
900 #ifdef TYPEINFO_DEBUG_TEST
901                 /* test the typeinfo system */
902                 typeinfo_test();
903 #endif
904                 /*class_showmethods(currentThread->group->header.vftbl->class); */
905
906                 *threadrootmethod = m;
907
908                 /* here we go... */
909
910                 asm_calljavafunction(m, a, NULL, NULL, NULL);
911
912                 /* exception occurred? */
913                 if (*exceptionptr) {
914                         throw_main_exception();
915                         status = 1;
916                 }
917
918 #if defined(USE_THREADS)
919 #if defined(NATIVE_THREADS)
920                 joinAllThreads();
921 #else
922                 killThread(currentThread);
923 #endif
924 #endif
925
926                 /* now exit the JavaVM */
927
928                 cacao_exit(status);
929         }
930
931         /************* If requested, compile all methods ********************/
932
933         if (compileall) {
934                 classinfo *c;
935                 methodinfo *m;
936                 u4 slot;
937                 s4 i;
938
939                 /* create all classes found in the classpath */
940                 /* XXX currently only works with zip/jar's */
941                 create_all_classes();
942
943                 /* load and link all classes */
944                 for (slot = 0; slot < class_hash.size; slot++) {
945                         c = class_hash.ptr[slot];
946
947                         while (c) {
948                                 if (!c->loaded)
949                                         if (!class_load(c))
950                                                 throw_main_exception_exit();
951
952                                 if (!c->linked)
953                                         if (!class_link(c))
954                                                 throw_main_exception_exit();
955
956                                 /* compile all class methods */
957                                 for (i = 0; i < c->methodscount; i++) {
958                                         m = &(c->methods[i]);
959                                         if (m->jcode) {
960                                                 (void) jit_compile(m);
961                                         }
962                                 }
963
964                                 c = c->hashlink;
965                         }
966                 }
967         }
968
969
970         /******** If requested, compile a specific method ***************/
971
972         if (specificmethodname) {
973                 methodinfo *m;
974
975                 /* create, load and link the main class */
976                 mainclass = class_new(utf_new_char(mainstring));
977
978                 if (!class_load(mainclass))
979                         throw_main_exception_exit();
980
981                 if (!class_link(mainclass))
982                         throw_main_exception_exit();
983
984                 if (specificsignature) {
985                         m = class_resolveclassmethod(mainclass,
986                                                                                  utf_new_char(specificmethodname),
987                                                                                  utf_new_char(specificsignature),
988                                                                                  mainclass,
989                                                                                  false);
990                 } else {
991                         m = class_resolveclassmethod(mainclass,
992                                                                                  utf_new_char(specificmethodname),
993                                                                                  NULL,
994                                                                                  mainclass,
995                                                                                  false);
996                 }
997
998                 if (!m) {
999                         char message[MAXLOGTEXT];
1000                         sprintf(message, "%s%s", specificmethodname,
1001                                         specificsignature ? specificsignature : "");
1002
1003                         *exceptionptr =
1004                                 new_exception_message(string_java_lang_NoSuchMethodException,
1005                                                                           message);
1006                                                                                  
1007                         throw_main_exception_exit();
1008                 }
1009                 
1010                 jit_compile(m);
1011         }
1012
1013         cacao_shutdown(0);
1014
1015         /* keep compiler happy */
1016
1017         return 0;
1018 }
1019
1020
1021 /* cacao_exit ******************************************************************
1022
1023    Calls java.lang.Runtime.exit(I)V to exit the JavaVM correctly.
1024
1025 *******************************************************************************/
1026
1027 void cacao_exit(s4 status)
1028 {
1029         classinfo *c;
1030         methodinfo *m;
1031
1032         /* class should already be loaded, but who knows... */
1033
1034         c = class_new(utf_new_char("java/lang/System"));
1035
1036         if (!class_load(c))
1037                 throw_main_exception_exit();
1038
1039         if (!class_link(c))
1040                 throw_main_exception_exit();
1041
1042         /* call System.exit(I)V */
1043
1044         m = class_resolveclassmethod(c,
1045                                                                  utf_new_char("exit"),
1046                                                                  utf_new_char("(I)V"),
1047                                                                  class_java_lang_Object,
1048                                                                  true);
1049         
1050         if (!m)
1051                 throw_main_exception_exit();
1052
1053         /* call the exit function with passed exit status */
1054
1055         /* both inlinevirtual and outsiders not allowed on exit */
1056         /*   not sure if permanant or temp restriction          */
1057         if (inlinevirtuals) inlineoutsiders = false; 
1058
1059         asm_calljavafunction(m,
1060 #if POINTERSIZE == 8
1061                                                  (void *) (s8) status,
1062 #else
1063                                                  (void *) status,
1064 #endif
1065                                                  NULL,
1066                                                  NULL,
1067                                                  NULL);
1068
1069         /* this should never happen */
1070
1071         if (*exceptionptr)
1072                 throw_exception_exit();
1073
1074         throw_cacao_exception_exit(string_java_lang_InternalError,
1075                                                            "System.exit(I)V returned without exception");
1076 }
1077
1078
1079 /*************************** Shutdown function *********************************
1080
1081         Terminates the system immediately without freeing memory explicitly (to be
1082         used only for abnormal termination)
1083         
1084 *******************************************************************************/
1085
1086 void cacao_shutdown(s4 status)
1087 {
1088         if (opt_verbose || getcompilingtime || opt_stat) {
1089                 log_text("CACAO terminated by shutdown");
1090                 dolog("Exit status: %d\n", (s4) status);
1091         }
1092
1093         exit(status);
1094 }
1095
1096
1097 /*
1098  * These are local overrides for various environment variables in Emacs.
1099  * Please do not remove this and leave it at the end of the file, where
1100  * Emacs will automagically detect them.
1101  * ---------------------------------------------------------------------
1102  * Local variables:
1103  * mode: c
1104  * indent-tabs-mode: t
1105  * c-basic-offset: 4
1106  * tab-width: 4
1107  * End:
1108  */