root/c/avmplus/avmshell.cpp

リビジョン 301, 35.2 kB (コミッタ: daoki2, コミット時期: 9 ヶ月 前)

First release

Line 
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is [Open Source Virtual Machine.].
15  *
16  * The Initial Developer of the Original Code is
17  * Adobe System Incorporated.
18  * Portions created by the Initial Developer are Copyright (C) 2004-2006
19  * the Initial Developer. All Rights Reserved.
20  *
21  * Contributor(s):
22  *   Adobe AS3 Team
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37
38
39 #include "avmshell.h"
40
41 #if defined(DARWIN) || defined(AVMPLUS_UNIX)
42 #include <sys/signal.h>
43 #include <unistd.h>
44 #endif
45
46 #if defined(DARWIN) || defined(AVMPLUS_INTERACTIVE)
47 #include <sys/stat.h>
48 #endif
49
50 #if defined(SOLARIS)
51 #include <ucontext.h>
52 extern "C" greg_t _getsp(void);
53 #endif
54
55 #ifdef WIN32
56 #pragma warning(disable: 4201)
57
58 #include <Mmsystem.h>
59 #include "dbghelp.h"
60 bool P4Available();
61 #elif defined AVMPLUS_UNIX
62 bool P4Available();
63 #endif
64
65 static MMgc::FixedMalloc* fm = NULL;
66
67 #ifndef OVERRIDE_GLOBAL_NEW
68 // Custom new and delete operators
69 // User-defined operator new.
70
71 void *operator new(size_t size)
72 {
73         // 10.5 calls new before main
74         if (!fm)
75         {
76                 MMgc::GCHeap::Init();
77                 MMgc::FixedMalloc::Init();
78
79                 fm = MMgc::FixedMalloc::GetInstance();
80         }
81
82     return fm->Alloc(size);
83 }
84
85 void *operator new[](size_t size)
86 {
87         // 10.5 calls new before main
88         if (!fm)
89         {
90                 MMgc::GCHeap::Init();
91                 MMgc::FixedMalloc::Init();
92
93                 fm = MMgc::FixedMalloc::GetInstance();
94         }
95
96     return fm->Alloc(size);
97 }
98
99 // User-defined operator delete.
100 #ifdef _MAC
101         // CW9 wants the C++ official prototype, which means we must have an empty exceptions list for throw.
102         // (The fact exceptions aren't on doesn't matter.) - mds, 02/05/04
103         void operator delete( void *p) throw()
104 #else
105         void operator delete( void *p)
106 #endif
107         {
108                 if (fm)
109                         fm->Free(p);
110         }
111
112 #ifdef _MAC
113     // CW9 wants the C++ official prototype, which means we must have an empty exceptions list for throw.
114     // (The fact exceptions aren't on doesn't matter.) - mds, 02/05/04
115     void operator delete[]( void *p) throw()
116 #else
117     void operator delete[]( void *p )
118 #endif
119     {
120                 if (fm)
121                         fm->Free(p);
122     }
123 #endif // OVERRIDE_GLOBAL_NEW
124
125
126 namespace avmshell
127 {
128         #include "toplevel.cpp"
129
130         const int kScriptTimeout = 15;
131         const int kScriptGracePeriod = 5;
132
133         BEGIN_NATIVE_CLASSES(Shell)
134                 NATIVE_CLASS(abcclass_avmplus_System,          SystemClass,        ScriptObject)
135                 NATIVE_CLASS(abcclass_avmplus_File,            FileClass,          ScriptObject)
136                 NATIVE_CLASS(abcclass_avmplus_Domain,          DomainClass,        DomainObject)
137                 NATIVE_CLASS(abcclass_avmplus_StringBuilder,   StringBuilderClass, StringBuilderObject)         
138                 NATIVE_CLASS(abcclass_avmplus_JObject,          JObjectClass,           JObject)
139                 NATIVE_CLASS(abcclass_flash_utils_ByteArray,    ByteArrayClass,     ByteArrayObject)           
140                 NATIVE_CLASS(abcclass_flash_utils_Dictionary,   DictionaryClass,    DictionaryObject)
141                 NATIVE_CLASS(abcclass_flash_sampler_Sample,     SampleClass,        SampleObject)
142                 NATIVE_CLASS(abcclass_flash_sampler_NewObjectSample, NewObjectSampleClass, NewObjectSampleObject)
143                 NATIVE_CLASS(abcclass_flash_sampler_DeleteObjectSample, SampleClass, SampleObject)
144                 NATIVE_CLASS(abcclass_flash_trace_Trace,                TraceClass,                     ScriptObject)
145         END_NATIVE_CLASSES()
146
147         BEGIN_NATIVE_SCRIPTS(Shell)
148                 NATIVE_SCRIPT(0/*abcscript_avmplus_debugger*/, AvmplusScript)
149                 NATIVE_SCRIPT(avmplus::NativeID::abcpackage_Sampler_as, SamplerScript)
150         END_NATIVE_SCRIPTS()
151
152         BEGIN_NATIVE_MAP(AvmplusScript)
153         END_NATIVE_MAP()
154
155         Shell *shell = NULL;
156         bool show_error = false;
157
158         #ifdef WIN32
159         void Shell::computeStackBase()
160         {
161 #ifdef AVMPLUS_AMD64
162                 const int kStackMargin = 262144;
163 #else
164                 const int kStackMargin = 131072;
165 #endif
166                
167                 SYSTEM_INFO sysinfo;
168                 GetSystemInfo(&sysinfo);
169
170                 int dummy;
171                 int sp = (int)(&dummy);
172                 sp &= ~(sysinfo.dwPageSize-1);
173
174                 MEMORY_BASIC_INFORMATION buf;
175                 if (VirtualQuery((void*)sp, &buf, sizeof(buf)) == sizeof(buf)) {
176                         minstack = (uint32)buf.AllocationBase + kStackMargin;
177                 }
178         }
179        
180         void CALLBACK TimeoutProc(UINT /*uTimerID*/,
181                                                           UINT /*uMsg*/,
182                                                           DWORD_PTR dwUser,
183                                                           DWORD_PTR /*dw1*/,
184                                                           DWORD_PTR /*dw2*/)
185         {
186                 AvmCore *core = (AvmCore*)dwUser;
187                 core->interrupted = true;
188         }
189         #else
190         void Shell::computeStackBase()
191         {
192                 const int kMaxAvmPlusStack = 512*1024;
193                 int sp;
194                 #ifdef AVMPLUS_PPC
195                 asm("mr %0,r1" : "=r" (sp));
196         #elif defined(AVMPLUS_ARM)
197                 asm("mov %0,sp" : "=r" (sp));
198                 #elif defined SOLARIS
199                 sp = _getsp();
200                 #else
201                 asm("movl %%esp,%0" : "=r" (sp));
202                 #endif
203                 minstack = sp-kMaxAvmPlusStack;
204         }
205        
206         void alarmProc(int /*signum*/)
207         {
208                 shell->interrupted = true;
209         }
210         #endif
211        
212         void Shell::usage()
213         {
214                 printf("avmplus shell " AVMPLUS_VERSION_USER " build " AVMPLUS_BUILD_CODE "\n\n");
215                 printf("usage: avmplus\n");
216                 #ifdef DEBUGGER
217                         printf("          [-d]          enter debugger on start\n");
218                 #endif
219                 #ifdef AVMPLUS_PROFILE
220                         printf("          [-Ddprofile]  dynamic instruction stats\n");
221                         printf("          [-Dsprofile]  show static instruction stats\n");
222                 #endif /* AVMPLUS_PROFILE */
223                 #ifdef _DEBUG
224                         printf("          [-Dgreedy]    collect before every allocation\n");
225                 #endif /* _DEBUG */
226                 #ifdef DEBUGGER
227                         printf("          [-Dnogc]      don't collect\n");
228                         printf("          [-Dgcstats]   generate statistics on gc\n");
229                         printf("          [-Dnoincgc]   don't use incremental collection\n");
230                         printf("          [-Dastrace N] display AS execution information, where N is [1..4]\n");
231                         printf("          [-Dlanguage l] localize runtime errors, languages are:\n");
232                         printf("                        en,de,es,fr,it,ja,ko,zh-CN,zh-TW\n");
233                 #endif
234
235                 #ifdef AVMPLUS_INTERP
236                         printf("          [-Dinterp]    do not generate machine code, interpret instead\n");
237                 #endif /* AVMPLUS_INTERP */
238
239                 #ifdef AVMPLUS_VERBOSE
240                         printf("          [-Dverbose]   trace every instruction (verbose!)\n");
241                         printf("          [-Dbbgraph]   output MIR basic block graphs for use with Graphviz\n");
242                 #endif
243
244     #ifdef AVMPLUS_MIR
245                 #ifdef AVMPLUS_INTERP
246                     printf("          [-Dforcemir]  use MIR always, never interp\n");
247         #endif /* AVMPLUS_INTERP */
248
249                 printf("          [-Dnodce]     disable DCE optimization \n");
250                 printf("          [-Dnocse]     disable CSE optimization \n");
251
252         #ifdef AVMPLUS_IA32
253             printf("          [-Dnosse]     use FPU stack instead of SSE2 instructions\n");
254         #endif /* AVMPLUS_IA32 */
255     #endif
256                
257                 #ifdef AVMPLUS_VERIFYALL
258                     printf("          [-Dverifyall] verify greedily instead of lazily\n");
259                 #endif
260
261                 printf("          [-Dtimeout]   enforce maximum 15 seconds execution\n");
262                 printf("          [-error]      crash opens debug dialog, instead of dumping\n");
263                 #ifdef AVMPLUS_INTERACTIVE
264                 printf("          [-i]          interactive mode\n");
265                 #endif //AVMPLUS_INTERACTIVE
266                 printf("          [-log]\n");
267                 printf("          [-- args]     args passed to AS3 program\n");
268                 printf("          [-jargs ... ;] args passed to Java runtime\n");
269                 printf("          filename.abc ...\n");
270                 printf("          [--] application args\n");
271                 exit(1);
272         }
273
274         void Shell::stackOverflow(MethodEnv *env)
275         {
276                 if (inStackOverflow)
277                 {
278                         // Already handling a stack overflow, so do not
279                         // re-enter handler.
280                         return;
281                 }
282                        
283                 // Temporarily disable stack overflow checks
284                 // so that we can construct an exception object.
285                 // There should be plenty of margin before the
286                 // actual stack bottom to do this.
287                 inStackOverflow = true;
288
289                 Toplevel *toplevel = env->vtable->toplevel;
290
291                 Stringp errorMessage = getErrorMessage(kStackOverflowError);
292                 Atom args[2] = { nullObjectAtom, errorMessage->atom() };
293                 Atom errorAtom = toplevel->errorClass()->construct(1, args);
294                 Exception *exception = new (GetGC()) Exception(errorAtom
295                                                   #ifdef DEBUGGER
296                                                                                                   ,this
297                                                   #endif
298                 );
299
300                 // Restore stack overflow checks
301                 inStackOverflow = false;
302
303                 // Throw the stack overflow exception
304                 throwException(exception);
305         }
306                
307         void Shell::interrupt(MethodEnv *env)
308         {
309                 interrupted = false;
310
311                 Toplevel *toplevel = env->vtable->toplevel;
312
313                 if (gracePeriod) {
314                         // This script has already had its chance; it violated
315                         // the grace period.
316                         // Throw an exception it cannot catch.
317                         Stringp errorMessage = getErrorMessage(kScriptTerminatedError);
318                         Atom args[2] = { nullObjectAtom, errorMessage->atom() };
319                         Atom errorAtom = toplevel->errorClass()->construct(1, args);
320                         Exception *exception = new (GetGC()) Exception(errorAtom
321                                                                                                           #ifdef DEBUGGER
322                                                                                                           ,this
323                                                                                                           #endif
324                                                                   );
325                         exception->flags |= Exception::EXIT_EXCEPTION;
326                         throwException(exception);
327                 }
328
329                 // Give the script an additional grace period to
330                 // clean up, and throw an exception.
331                 gracePeriod = true;
332
333                 #ifdef WIN32
334                 timeSetEvent(kScriptGracePeriod*1000,
335                                          kScriptGracePeriod*1000,
336                                          (LPTIMECALLBACK)TimeoutProc,
337                                          (DWORD_PTR)this,
338                                          TIME_ONESHOT);
339                 #else
340                 #ifndef AVMPLUS_ARM // TODO AVMPLUS_ARM
341                 alarm(kScriptGracePeriod);
342                 #endif
343                 #endif
344
345                 toplevel->throwError(kScriptTimeoutError);
346         }
347        
348         void Shell::initShellPool()
349         {
350                 AbstractFunction *nativeMethods[avmplus::NativeID::toplevel_abc_method_count];
351                 NativeClassInfo *nativeClasses[avmplus::NativeID::toplevel_abc_class_count];
352                 NativeScriptInfo *nativeScripts[avmplus::NativeID::toplevel_abc_script_count];
353
354                 memset(nativeMethods, 0, sizeof(AbstractFunction*)*avmplus::NativeID::toplevel_abc_method_count);
355                 memset(nativeClasses, 0, sizeof(NativeClassInfo*)*avmplus::NativeID::toplevel_abc_class_count);
356                 memset(nativeScripts, 0, sizeof(NativeScriptInfo*)*avmplus::NativeID::toplevel_abc_script_count);
357
358                 initNativeTables(classEntries, scriptEntries,
359                         nativeMethods, nativeClasses, nativeScripts);
360
361                 avmplus::ScriptBuffer code = newScriptBuffer(avmplus::NativeID::toplevel_abc_length);
362                 memcpy(code.getBuffer(), toplevel_abc_data, avmplus::NativeID::toplevel_abc_length);
363                 shellPool = parseActionBlock(code, 0, NULL, builtinDomain, nativeMethods, nativeClasses, nativeScripts);
364         }
365
366         Toplevel* Shell::initShellBuiltins()
367         {
368                 // Initialize a new Toplevel.  This will also create a new
369                 // DomainEnv based on the builtinDomain.
370                 Toplevel* toplevel = initTopLevel();
371
372                 // Initialize the shell builtins in the new Toplevel
373                 handleActionPool(shellPool,
374                                                  toplevel->domainEnv(),
375                                                  toplevel,
376                                                  NULL);
377
378                 return toplevel;
379         }
380        
381         Shell::Shell(MMgc::GC *gc) : AvmCore(gc)
382         {
383                 #ifdef DEBUGGER
384                 debugCLI = NULL;
385                 #endif
386
387                 systemClass = NULL;
388                
389                 gracePeriod = false;
390                 inStackOverflow = false;
391
392                 consoleOutputStream = new (gc) ConsoleOutputStream();
393                 setConsoleStream(consoleOutputStream);
394
395                 computeStackBase();
396         }
397
398         bool Shell::executeProjector(int argc, char *argv[], int& exitCode)
399         {
400                 TRY(this, kCatchAction_ReportAsError)
401                 {
402                         uint8 header[8];
403
404                         char executablePath[256];
405
406                         #ifdef WIN32
407                         GetModuleFileName(NULL, executablePath, sizeof(executablePath));
408                         #else
409                         strncpy(executablePath, argv[0], sizeof(executablePath));
410                         #endif
411                    
412                         FileInputStream file(executablePath);
413                         if (!file.valid())
414                         {
415                                 return false;
416                         }
417                        
418                         file.seek(file.length() - 8);
419                         file.read(header, 8);
420
421                         // Check the magic number
422                         if (header[0] != 0x56 ||
423                                 header[1] != 0x34 ||
424                                 header[2] != 0x12 ||
425                                 header[3] != 0xFA)
426                         {
427                                 return false;
428                         }
429
430                         int abcLength = (header[4]     |
431                                                          header[5]<<8  |
432                                                          header[6]<<16 |
433                                                          header[7]<<24);
434
435                         ScriptBuffer code = newScriptBuffer(abcLength);
436                         file.seek(file.length() - 8 - abcLength);
437                         file.read(code.getBuffer(), abcLength);
438                        
439                         initBuiltinPool();
440                         initShellPool();
441
442                         #ifdef DEBUGGER
443                         // Create the debugger
444                         debugCLI = new (GetGC()) DebugCLI(this);
445                         debugger = debugCLI;
446
447                         // Create the profiler
448                         profiler = new (GetGC()) Profiler(this);
449                         #endif
450
451                         SystemClass::user_argc = argc-1;
452                         SystemClass::user_argv = &argv[1];
453                
454                         // init toplevel internally
455                         Toplevel* toplevel = initShellBuiltins();
456
457                         // Create a new Domain for the user code
458                         Domain* domain = new (GetGC()) Domain(this,
459                                                                                          builtinDomain);
460
461                         // Return a new DomainEnv for the user code
462                         DomainEnv* domainEnv = new (GetGC()) DomainEnv(this,
463                                                                                                           domain,
464                                                                                                           toplevel->domainEnv());
465
466                         ShellCodeContext* codeContext = new (GetGC()) ShellCodeContext();
467                         codeContext->m_domainEnv = domainEnv;
468                                
469                         // parse new bytecode
470                         handleActionBlock(code, 0, domainEnv, toplevel, NULL, NULL, NULL, codeContext);
471
472                         #ifdef DEBUGGER
473                         delete profiler;
474                         #endif
475                 }
476                 CATCH(Exception *exception)
477                 {
478                         #ifdef DEBUGGER
479                         if (!(exception->flags & Exception::SEEN_BY_DEBUGGER))
480                         {
481                                 console << string(exception->atom) << "\n";
482                         }
483                         if (exception->getStackTrace()) {
484                                 console << exception->getStackTrace()->format(this) << '\n';
485                         }
486                         delete profiler;
487                         #else
488                         // [ed] always show error, even in release mode,
489                         // see bug #121382
490                         console << string(exception->atom) << "\n";
491                         #endif
492                         exit(1);
493                 }
494                 END_CATCH
495                 END_TRY
496                                
497                 #ifdef AVMPLUS_PROFILE
498                         dump();
499                 #endif
500
501                 exitCode = 0;
502                 return true;
503         }
504                
505         int Shell::main(int argc, char *argv[])
506         {
507                 TRY(this, kCatchAction_ReportAsError)
508                 {
509                     //#ifdef AVMPLUS_IA32
510                     //if (!P4Available()) {
511                     //  sse2 = false;
512                     //}
513                     //#endif
514
515                         int exitCode = 0;
516                         if (executeProjector(argc, argv, exitCode))
517                         {
518                                 return exitCode;
519                         }
520                                                
521                         if (argc < 2) {
522                                 usage();
523                         }
524
525                         int filenamesPos = -1;
526                         int endFilenamePos = -1;
527                         char *filename = NULL;
528                         bool do_log = false;
529 #ifdef DEBUGGER
530                         bool do_debugger = false;
531 #endif
532                         bool do_interactive = false;
533 #ifdef AVMPLUS_VERBOSE
534                         bool do_verbose = false;
535 #endif
536
537                         for (int i=1; i<argc; i++) {
538                                 char *arg = argv[i];
539                                 // options available to development builds.
540                                 if (arg[0] == '-')
541                                 {
542                                         if (arg[1] == 'D') {
543                                                 if (!strcmp(arg+2, "timeout")) {
544                                                         interrupts = true;
545
546                                                 #ifdef AVMPLUS_IA32
547                                                 } else if (!strcmp(arg+2, "nosse")) {
548                                                         sse2 = false;
549                                                 #endif
550
551                             #ifdef AVMPLUS_VERIFYALL
552                                                 } else if (!strcmp(arg+2, "verifyall")) {
553                                                         verifyall = true;
554                                 #endif /* AVMPLUS_VERIFYALL */
555
556                             #ifdef _DEBUG
557                                                 } else if (!strcmp(arg+2, "greedy")) {
558                                                         GetGC()->greedy = true;
559                                 #endif /* _DEBUG */
560
561                                                 #ifdef AVMPLUS_PROFILE
562                                                 } else if (!strcmp(arg+2, "dprofile")) {
563                                                         dprof.dprofile = true;
564                                                 } else if (!strcmp(arg+2, "sprofile")) {
565                                                         sprof.sprofile = true;
566                                                 #endif /* AVMPLUS_PROFILE */
567
568                             #ifdef DEBUGGER
569                                                 } else if (!strcmp(arg+2, "gcstats")) {
570                                                         GetGC()->gcstats = true;
571                                                 } else if (!strcmp(arg+2, "nogc")) {
572                                                         GetGC()->nogc = true;
573                                                 } else if (!strcmp(arg+2, "noincgc")) {
574                                                         GetGC()->incremental = false;
575                                                 } else if (!strcmp(arg+2, "astrace")) {
576                                                         avmplus::Debugger::astrace_console = (avmplus::Debugger::TraceLevel) strtol(argv[++i], 0, 10);
577                                                 } else if (!strcmp(arg+2, "language")) {
578                                                         langID=-1;
579                                                         for (int j=0;j<kLanguages;j++) {
580                                                                 if (!strcmp(argv[i+1],languageNames[j].str)) {
581                                                                         langID=j;
582                                                                         break;
583                                                                 }
584                                                         }
585                                                         if (langID==-1) {
586                                                                 langID = atoi(argv[i+1]);
587                                                         }
588                                                         i++;
589                         #endif /* DEBUGGER */
590                                                 #ifdef AVMPLUS_INTERP
591                                                 } else if (!strcmp(arg+2, "interp")) {
592                                                         turbo = false;
593                                 #endif /* AVMPLUS_INTERP */
594                                                 #ifdef AVMPLUS_VERBOSE
595                                                 } else if (!strcmp(arg+2, "verbose")) {
596                                                         do_verbose = true;
597                                                 #endif
598
599                         #ifdef AVMPLUS_MIR
600                                                 #ifdef AVMPLUS_INTERP
601                                                 } else if (!strcmp(arg+2, "forcemir")) {
602                                                         forcemir = true;
603                         #endif /* AVMPLUS_INTERP */
604
605                                                 } else if (!strcmp(arg+2, "nodce")) {
606                                                         dceopt = false;
607                                                        
608                                                 } else if (!strcmp(arg+2, "nocse")) {
609                                                         cseopt = false;
610
611                         #ifdef AVMPLUS_VERBOSE
612                                                 } else if (!strcmp(arg+2, "bbgraph")) {
613                                                         bbgraph = true;  // generate basic block graph (only valid with mir switch)
614                         #endif
615                     #endif /* AVMPLUS_MIR */
616
617                                                 } else {
618                                                         usage();
619                                                 }
620                                         } else if (!strcmp(arg, "-log")) {
621                                                 do_log = true;
622                                         #ifdef AVMPLUS_INTERACTIVE
623                                         } else if (!strcmp(arg, "-i")) {
624                                                 do_interactive = true;
625                                         #endif //AVMPLUS_INTERACTIVE
626                                         }
627                                         else if (!strcmp(arg, "-error")) {
628                                                 show_error = true;
629                                                 #ifdef WIN32
630                                                 SetErrorMode(0);  // set to default
631                                                 #endif // WIN32
632                                         }
633 #ifdef AVMPLUS_WITH_JNI
634                                         else if (!strcmp(arg, "-jargs")) {
635                                                 // all the following args until the semi colon is for java.
636                                                 //@todo fix up this hard limit
637                                                 bool first = true;
638                                                 Java::startup_options = new char[256];
639                                                 memset(Java::startup_options, 0, 256);
640
641                                                 for(i++; i<argc; i++)
642                                                 {
643                                                         if (*argv[i] == ';')
644                                                                 break;
645                                                         if (!first) strcat(Java::startup_options, " ");
646                                                         strcat(Java::startup_options, argv[i]);
647                                                         first = false;
648                                                 }
649                                                 AvmAssert(strlen(Java::startup_options) < 256);
650                                         }
651 #endif /* AVMPLUS_WITH_JNI */
652                                    
653                         #ifdef DEBUGGER
654                                         else if (!strcmp(arg, "-d")) {
655                                                 do_debugger = true;
656                                         }
657                             #endif /* DEBUGGER */
658
659                                         else if(arg[1] == '-' && arg[2] == 0) {
660                                                 endFilenamePos = i;
661                                         }
662                                         else {
663                                                 usage();
664                                         }
665                                 }
666                                 else
667                                 {
668                                         if (filenamesPos == -1)
669                                                 filenamesPos = i;
670                                         filename = arg;
671                                 }
672                         }
673                
674                         if (!filename && !do_interactive) {
675                                 usage();
676                         }
677
678                         if( do_log )
679                         {
680                                 // open logfile based on last filename
681                                 const char* dot = strrchr(filename, '.');
682                                 if (!dot)
683                                         dot = filename+strlen(filename);
684
685                                 char* logname = new char[dot-filename+5];  // free upon exit
686                                 strcpy(logname,filename);
687                                 strcpy(logname+(dot-filename),".log");
688                                 printf("%s\n",filename); // but first print name to default stdout
689                                 freopen(logname, "w", stdout);
690                                 delete [] logname;
691                         }
692
693                         initBuiltinPool();
694                         initShellPool();
695
696 #ifdef AVMPLUS_VERBOSE
697                         if (do_verbose)
698                                 verbose = true;
699 #endif
700
701                         #ifdef DEBUGGER
702                         // Create the debugger
703                         debugCLI = new (GetGC()) DebugCLI(this);
704                         debugger = debugCLI;
705
706                         // Create the profiler
707                         profiler = new (GetGC()) Profiler(this);
708
709                         if (do_debugger)
710                         {
711                                 // Activate the debug CLI and stop at
712                                 // start of program
713                                 debugCLI->activate();
714                                 debugCLI->stepInto();
715                         }
716                         #endif
717
718                         // start the 15 second timeout if applicable
719                         if (interrupts) {
720                                 #ifdef WIN32
721                                 timeSetEvent(kScriptTimeout*1000,
722                                                          kScriptTimeout*1000,
723                                                          (LPTIMECALLBACK)TimeoutProc,
724                                                          (DWORD_PTR)this,
725                                                          TIME_ONESHOT);
726                                 #else
727                                 #ifndef AVMPLUS_ARM // TODO AVMPLUS_ARM
728                                 signal(SIGALRM, alarmProc);
729                                 alarm(kScriptTimeout);
730                                 #endif
731                                 #endif
732                         }
733
734                         if(endFilenamePos == -1)
735                                 endFilenamePos = argc;
736                         SystemClass::user_argc = argc-endFilenamePos-1;
737                         SystemClass::user_argv = &argv[endFilenamePos+1];
738                
739                         // init toplevel internally
740                         Toplevel* toplevel = initShellBuiltins();
741
742                         // Create a new Domain for the user code
743                         Domain* domain = new (GetGC()) Domain(this,
744                                                                                          builtinDomain);
745
746                         // Return a new DomainEnv for the user code
747                         DomainEnv* domainEnv = new (GetGC()) DomainEnv(this,
748                                                                                                           domain,
749                                                                                                           toplevel->domainEnv());
750
751                         ShellCodeContext* lastCodeContext = 0;
752
753                         // execute each abc file
754                         for (int i=filenamesPos; filename && i < endFilenamePos; i++)
755                         {
756                                 filename = argv[i];
757
758                                 #ifdef AVMPLUS_VERBOSE
759                                 if (verbose) {
760                                         console << "run " << filename << "\n";
761                                 }
762                                 #endif
763
764                                 FileInputStream f(filename);
765                                 bool isValid = f.valid();
766                                 if (!isValid) {
767                                         fprintf(stderr, "cannot open file: %s\n", filename);
768                                         #ifdef DEBUGGER
769                                         delete profiler;
770                                         #endif
771                                         if (!do_interactive)
772                                                 return(1);
773                                 }
774
775                                 ShellCodeContext* codeContext = new (GetGC()) ShellCodeContext();
776                                 codeContext->m_domainEnv = domainEnv;
777                                
778                                 // parse new bytecode
779                                 if (isValid)
780                                 {
781                                         ScriptBuffer code = newScriptBuffer(f.available());
782                                         f.read(code.getBuffer(), f.available());
783                                         handleActionBlock(code, 0, domainEnv, toplevel, NULL, NULL, NULL, codeContext);
784           &n