root/c/avmplus/avmshell.cpp

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

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                                 }
785
786                                 lastCodeContext = codeContext;
787                         }
788
789                         #ifdef MMGC_COUNTERS
790                         console << "\nGC stats\n";
791                         console << "mark item         " << MMgc::GC::MarkItemCount << "\n";
792                         console << "mark null ptr     " << MMgc::GC::marknullCount << "\n";
793                         console << "mark alloc        " << MMgc::GC::markallocCount << "\n";
794                         console << "mark large        " << MMgc::GC::marklargeCount << "\n";
795                         console << "mark skip         " << MMgc::GC::markskipCount << "\n";
796                         console << "TrapWriteCount    " << MMgc::GC::TrapWriteCount << "\n";
797
798                         console << "\nGCAlloc stats\n";
799                         console << "SweepBlockCount   " << MMgc::GCAlloc::SweepBlockCount << "\n";
800                         console << "AllocCount        " << MMgc::GCAlloc::AllocCount << "\n";
801                         console << "FreeItemCount     " << MMgc::GCAlloc::FreeItemCount << "\n";
802                         #endif
803
804                         #ifdef AVMPLUS_INTERACTIVE
805                         if (do_interactive)
806                         {
807                                 enum { kMaxCommandLine = 1024 };
808                                 char commandLine[kMaxCommandLine];
809                                 enum { kMaxFileName = 1024 };
810                                 char fileName[kMaxFileName];
811                                 char imports[kMaxCommandLine];
812                                 #ifdef DARWIN
813                                 char includes[kMaxCommandLine];
814                                 strcpy(includes, " ");
815                                 enum { kMaxProgramLine = 1024 * 10};
816                                 char programLine[kMaxProgramLine];
817                                 programLine[0] = '\0';
818                                 #endif
819                                 strcpy(imports, " ");
820
821                                 #ifdef WIN32
822                                 // some defaults
823                                 addToImports(imports, "C:\\src\\farm\\main\\as\\lib\\shell.abc");
824                                 addToImports(imports, "C:\\src\\farm\\main\\as\\lib\\global.abc");
825
826                                 STARTUPINFO si;
827                                 PROCESS_INFORMATION pi;
828                                 #endif
829
830                                 while(do_interactive)
831                                 {
832                                     #ifdef DARWIN
833                                     bool compile = true;
834                                     bool exec = true;
835                                     for(;;) {
836                                     #endif
837                                         console << "(avmplus) ";
838                                         fflush(stdout);
839                                         fgets(commandLine, kMaxCommandLine, stdin);
840
841                                         commandLine[strlen(commandLine)-1] = 0;
842
843                                         // build up the file that we are going to compile
844                                         #ifdef DARWIN
845                                         compile = true;
846                                         exec = true;
847                                         #else
848                                         bool compile = true;
849                                         bool exec = true;
850                                         #endif
851                                         fileName[0] = '\0';
852                                         if (strstr(commandLine, ".run ") == commandLine)
853                                         {
854                                                 // arg
855                                                 strcpy(fileName, &commandLine[5]);
856
857                                                 // search for .as extension
858                                                 const char* dotAt = strrchr(fileName, '.');
859                                                 bool fail = true;
860                                                 if (dotAt)
861                                                 {
862                                                         if (strcmp(dotAt, ".abc") == 0)
863                                                         {
864                                                                 compile = false;
865                                                                 fail = false;
866                                                         }
867                                                         else if (strcmp(dotAt, ".as") == 0)
868                                                         {
869                                                                 fail = false;
870                                                         }
871                                                 }
872
873                                                 if (fail)
874                                                 {
875                                                         console << "only .as and .abc files are supported \n";
876                                                         continue;
877                                                 }
878                                         }
879                                         else if (strstr(commandLine, ".import ") == commandLine)
880                                         {
881                                                 // add to the import list
882                                                 strcpy(fileName, &commandLine[8]);
883                                                 compile = false;
884                                                 exec = false;
885
886                                                 if (!addToImports(imports, fileName))
887                                                 {
888                                                         console << "file does not exist; not added to import list \n";
889                                                 }
890                                                 console << imports << "\n";
891                                         }
892                                         #ifdef DARWIN
893                                         else if (strstr(commandLine, ".in ") == commandLine)
894                                         {
895                                                 // add to the import list
896                                                 strcpy(fileName, &commandLine[4]);
897                                                 compile = false;
898                                                 exec = false;
899
900                                                 if (!addToIncludes(includes, fileName))
901                                                 {
902                                                         console << "file does not exist; not added to inclide list \n";
903                                                 }
904                                                 console << includes << "\n";
905                                         }
906                                         #endif
907                                         else if (strstr(commandLine, ".quit") == commandLine)
908                                         {
909                                                 return 0;
910                                         }
911                                         else if (commandLine[0] == '\0' ||  (strstr(commandLine, ".help") == commandLine) )
912                                         {
913                                                 console << "ActionScript source can be directly entered on the command line.\nIt will be compiled and executed once the enter key is pressed.\nThe following directives are also recognized\n" ;
914                                                 console << ".run [f.as|f.abc]   - runs f, compiles f.as first if required\n" ;
915                                                 console << ".import f           - add f to the -import list for compiling \n" ;
916                                                 #ifdef DARWIN
917                                                 console << ".in f               - add f to the -in list for compiling \n" ;
918                                                 console << ".exec               - execute the program\n";
919                                                 #endif
920                                                 console << ".quit               - exits this shell \n" ;
921                                                 console << ".help               - displays help information \n" ;
922                                                 continue;
923                                         }
924                                         #ifdef DARWIN
925                                         else if (strstr(commandLine, ".exec") == commandLine)
926                                         #else
927                                         else
928                                         #endif
929                                         {
930                                                 // put our command line contents in a file
931                                                 strcpy(fileName, "___file_for_io.as");
932                                                 FILE* f = fopen(fileName , "w");
933                                                 if (!f)
934                                                 {
935                                                         console << "i/o error \n";
936                                                         return 1;
937                                                 }                       
938                                                 #ifdef DARWIN
939                                                 fputs(programLine, f);
940                                                 #else
941                                                 fputs(commandLine, f);
942                                                 #endif
943                                                 fclose(f);
944                                                 #ifdef DARWIN
945                                                 break;
946                                                 #endif
947                                         }
948                                         #ifdef DARWIN
949                                         else {
950                                             strcat(programLine, commandLine);
951                                             strcat(programLine, "\n");
952                                         }
953                                         } //end for(;;)
954                                         #endif
955
956                                         // set up for the compile if needed
957                                         if (compile)
958                                         {
959                                                 #ifdef DARWIN
960                                                 // now compile and wait
961                                                 FILE* fp;
962                                                 commandLine[0] = '\0';
963                                                 strcpy(commandLine, "java -jar asc.jar -debug ");
964                                                 strcat(commandLine, imports);
965                                                 strcat(commandLine, includes);
966                                                 strcat(commandLine, fileName);
967                                                 strcat(commandLine, " 2>&1");
968                                                 if ((fp = popen(commandLine, "r")) == NULL) {
969                                                     console << "failed to compile";
970                                                     console << "\n";
971                                                     exec = false;
972                                                 }
973                                                 commandLine[0] = '\0';
974                                                 fgets(commandLine, kMaxCommandLine, fp); // read the first empty line
975                                                 fgets(commandLine, kMaxCommandLine, fp);
976                                                 if ( !strstr(commandLine, "bytes written")) {
977                                                     //failed compile
978                                                     console << "\n"; // add the first empty line
979                                                     console << commandLine;
980                                                     while(1) {
981                                                         fgets(commandLine, kMaxCommandLine, fp);
982                                                         if(feof(fp)) {
983                                                             break;
984                                                         }
985                                                         console << commandLine;
986                                                     }
987                                                     console << "\n";
988                                                     exec = false;
989                                                 }
990                                                 pclose(fp);
991                                                 #else
992                                                 // Set the bInheritHandle flag so pipe handles are inherited.
993                                                 SECURITY_ATTRIBUTES saAttr;
994                                                 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
995                                                 saAttr.bInheritHandle = TRUE;
996                                                 saAttr.lpSecurityDescriptor = NULL;
997
998                                                 HANDLE pRd, pWr;
999                                                 CreatePipe(&pRd, &pWr, &saAttr, 64*kMaxCommandLine);
1000                                                 SetHandleInformation( pRd, HANDLE_FLAG_INHERIT, 0);  // don't inherit read portion; only allow writes from child proc
1001                                                 SetHandleInformation( GetStdHandle(STD_INPUT_HANDLE), HANDLE_FLAG_INHERIT, 0);  // don't inherit stdin
1002
1003                                                 ZeroMemory( &si, sizeof(si) );
1004                                                 si.cb = sizeof(si);
1005                                                 ZeroMemory( &pi, sizeof(pi) );
1006                                                 si.hStdError = pWr;
1007                                                 si.hStdOutput = pWr;
1008                                                 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
1009                                                 si.dwFlags = STARTF_USESTDHANDLES;
1010
1011                                                 // now compile and wait
1012                                                 commandLine[0] = '\0';
1013                                                 strcpy(commandLine, "asc.exe -debug ");
1014                                                 strcat(commandLine, imports);
1015                                                 strcat(commandLine, fileName);
1016                                                 DWORD err = CreateProcess(0, commandLine, 0,0,TRUE,0,0,0, &si, &pi);
1017                                                 if (err)
1018                                                 {
1019                                                         // Wait until child process exits.
1020                                                         WaitForSingleObject( pi.hProcess, 20000 );
1021                                                 }
1022                                                 else
1023                                                 {
1024                                                         console << "failed to compile err=0x";
1025                                                         console.writeHexAddr(GetLastError());
1026                                                         console << "\n";
1027                                                         exec = false;
1028                                                 }
1029
1030                                                 // Close process and thread handles.
1031                                                 CloseHandle( pi.hProcess );
1032                                                 CloseHandle( pi.hThread );
1033
1034                                                 // now check the compile
1035                                                 CloseHandle(pWr);  // Close the write end of the pipe before reading from the read end of the pipe.
1036                                                 commandLine[0] = '\0';
1037                                                 DWORD dwRead = 0;
1038                                                 ReadFile( pRd, commandLine, kMaxCommandLine, &dwRead, NULL);
1039                                                 if (dwRead > 0) commandLine[dwRead] = '\0';
1040                                                 if ( !strstr(commandLine, "bytes written") )
1041                                                 {
1042                                                         // failed compile                                               
1043                                                         console << commandLine;
1044
1045                                                         // dump the rest of the message
1046                                                         for(;;)
1047                                                         {
1048                                                                 if (!ReadFile( pRd, commandLine, kMaxCommandLine, &dwRead, NULL) || dwRead == 0)
1049                                                                         break;
1050
1051                                                                 console << commandLine;
1052                                                         }
1053                                                         exec = false;
1054                                                         console << "\n";
1055                                                 }
1056                                                 #endif
1057                                                 // now run the abc
1058                                                 int afterDot = strlen(fileName) - 2;
1059                                                 strcpy(&fileName[afterDot], "abc");
1060                                         }
1061
1062                                         if (exec)
1063                                         {
1064                                                 #ifdef DARWIN
1065                                                 FILE *fp;
1066                                                 if ((fp = fopen(fileName, "r")) != NULL)
1067                                                 #else
1068                                                 FileInputStream fl(fileName);
1069                                                 bool isValid = fl.valid();
1070                                                 if (isValid)
1071                                                 #endif
1072                                                 {
1073                                                         TRY(this, kCatchAction_ReportAsError)
1074                                                         {
1075                                                                 #ifdef DARWIN
1076                                                                 struct stat buf;
1077                                                                 fstat(fileno(fp), &buf);
1078                                                                 ScriptBuffer code = newScriptBuffer(buf.st_size);
1079                                                                 fread(code.getBuffer(), buf.st_size, 1, fp);
1080                                                                 fclose(fp);
1081                                                                 #else
1082                                                                 ScriptBuffer code = newScriptBuffer(fl.available());
1083                                                                 fl.read(code.getBuffer(), fl.available());
1084                                                                 #endif
1085                                                                 handleActionBlock(code, 0, domainEnv, toplevel, NULL, NULL, NULL, lastCodeContext);
1086                                                         }
1087                                                         CATCH(Exception *exception)
1088                                                         {
1089                                                                 #ifdef DEBUGGER
1090                                                                 if (!(exception->flags & Exception::SEEN_BY_DEBUGGER))
1091                                                                 {
1092                                                                         console << string(exception->atom) << "\n";
1093                                                                 }
1094                                                                 if (exception->getStackTrace()) {
1095                                                                         console << exception->getStackTrace()->format(this) << '\n';
1096                                                                 }
1097                                                                 #else
1098                                                                 // [ed] always show error, even in release mode,
1099                                                                 // see bug #121382
1100                                                                 console << string(exception->atom) << "\n";
1101                                                                 #endif
1102                                                         }
1103                                                         END_CATCH
1104                                                         END_TRY
1105                                                 }
1106                                                 else
1107                                                 {
1108                                                         console << "can't find " << fileName << "\n";
1109                                                 }
1110                                         }
1111                                 }
1112                         }
1113                         #endif //AVMPLUS_INTERACTIVE
1114
1115                         #ifdef DEBUGGER
1116                         delete profiler;
1117                         #endif
1118                 }
1119                 CATCH(Exception *exception)
1120                 {
1121                         #ifdef DEBUGGER
1122                         if (!(exception->flags & Exception::SEEN_BY_DEBUGGER))
1123                         {
1124                                 console << string(exception->atom) << "\n";
1125                         }
1126                         if (exception->getStackTrace()) {
1127                                 console << exception->getStackTrace()->format(this) << '\n';
1128                         }
1129                         delete profiler;
1130                         #else
1131                         // [ed] always show error, even in release mode,
1132                         // see bug #121382
1133                         console << string(exception->atom) << "\n";
1134                         #endif
1135                         exit(1);
1136                 }
1137                 END_CATCH
1138                 END_TRY
1139                                
1140                 #ifdef AVMPLUS_PROFILE
1141                         dump();
1142                 #endif
1143 #ifdef AVMPLUS_WITH_JNI
1144                 if (Java::startup_options) delete Java::startup_options;
1145 #endif /* AVMPLUS_WITH_JNI */
1146                 return 0;
1147         }
1148
1149         #ifdef AVMPLUS_INTERACTIVE
1150         #ifdef DARWIN
1151         int Shell::addToIncludes(char* includes, char* addition)
1152         {
1153                 int worked = 0;
1154                 if (addition && addition[0] != '\0')
1155                 {
1156                         FILE* fp;
1157                         if ((fp = fopen(addition, "r")) != NULL)
1158                         {
1159                                 strcat(includes, " ");
1160                                 strcat(includes, " -in \"");
1161                                 strcat(includes, addition);
1162                                 strcat(includes, "\" ");
1163                                 worked = 1;
1164                                 fclose(fp);
1165                         }
1166                 }
1167                 return worked;
1168         }
1169         #endif
1170         int Shell::addToImports(char* imports, char* addition)
1171         {
1172                 int worked = 0;
1173                 if (addition && addition[0] != '\0')
1174                 {
1175                         #ifdef DARWIN
1176                         FILE* fp;
1177                         if ((fp = fopen(addition, "r")) != NULL)
1178                         #else
1179                         FileInputStream fl(addition);
1180                         if (fl.valid())
1181                         #endif
1182                         {
1183                                 strcat(imports, " ");
1184                                 strcat(imports, " -import \"");
1185                                 strcat(imports, addition);
1186                                 strcat(imports, "\" ");
1187                                 worked = 1;
1188                                 #ifdef DARWIN
1189                                 //fclose(fp);
1190                                 #endif
1191                         }
1192                 }
1193                 return worked;
1194         }
1195         #endif //AVMPLUS_INTERACTIVE
1196 }
1197
1198 int _main(int argc, char *argv[])
1199 {
1200         if (!fm)
1201         {
1202                 MMgc::GCHeap::Init();
1203                 MMgc::FixedMalloc::Init();
1204
1205                 fm = MMgc::FixedMalloc::GetInstance();
1206         }
1207        
1208         MMgc::GCHeap* heap = MMgc::GCHeap::GetGCHeap();
1209
1210         // memory zero'ing check
1211 /*      int *foo = new int[2];
1212         AvmAssert(memcmp(foo, "\0\0\0\0\0\0\0\0\0\0\0\0", 2*sizeof(int)) == 0);
1213         delete foo;*/
1214
1215         int exitCode = 0;
1216         {
1217                 MMgc::GC gc(heap);
1218                 avmshell::shell = new avmshell::Shell(&gc);
1219                 exitCode = avmshell::shell->main(argc, argv);
1220                 delete avmshell::shell;
1221         }
1222
1223         MMgc::FixedMalloc::Destroy();
1224         MMgc::GCHeap::Destroy();
1225         fm = 0;
1226         return exitCode;
1227 }
1228
1229 #ifdef AVMPLUS_WIN32
1230 unsigned long CrashFilter(LPEXCEPTION_POINTERS pException, int exceptionCode)
1231 {
1232         unsigned long result;
1233         if ((result = UnhandledExceptionFilter(pException)) != EXCEPTION_EXECUTE_HANDLER)
1234         {
1235                 return result;
1236         }
1237         else if (avmshell::show_error)
1238         {
1239                 // if -error option dont do a dump
1240                 return EXCEPTION_CONTINUE_SEARCH;
1241         }
1242
1243         printf("avmplus crash: exception 0x%08lX occurred\n", exceptionCode);
1244
1245         typedef BOOL (WINAPI *MINIDUMP_WRITE_DUMP)(
1246                 HANDLE hProcess,
1247                 DWORD ProcessId,
1248                 HANDLE hFile,
1249                 MINIDUMP_TYPE DumpType,
1250                 PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
1251                 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
1252                 PMINIDUMP_CALLBACK_INFORMATION CallbackParam
1253         );
1254
1255         HMODULE hDbgHelp = LoadLibrary("dbghelp.dll");
1256         MINIDUMP_WRITE_DUMP MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp,
1257                                                 "MiniDumpWriteDump");
1258
1259         if (MiniDumpWriteDump_)
1260         {
1261                 MINIDUMP_EXCEPTION_INFORMATION  M;
1262                 const char DumpPath[] = "avmplusCrash.dmp";
1263
1264                 M.ThreadId = GetCurrentThreadId();
1265                 M.ExceptionPointers = pException;
1266                 M.ClientPointers = 0;
1267
1268                 printf("Writing minidump crash log to %s\n", DumpPath);
1269
1270                 HANDLE hDumpFile = CreateFile(DumpPath, GENERIC_WRITE, 0,
1271                                                                   NULL, CREATE_ALWAYS,
1272                                                                       FILE_ATTRIBUTE_NORMAL, NULL);
1273
1274                 MiniDumpWriteDump_(GetCurrentProcess(),
1275                                                    GetCurrentProcessId(),
1276                                                    hDumpFile,
1277                                                    MiniDumpNormal,
1278                                                    (pException) ? &M : NULL, NULL, NULL);
1279
1280                 CloseHandle(hDumpFile);
1281         }
1282         else
1283         {
1284                 printf("minidump not available, no crash log written.\n");
1285         }
1286
1287         return result;
1288 }
1289
1290 int main(int argc, char *argv[])
1291 {
1292         SetErrorMode(SEM_NOGPFAULTERRORBOX);
1293         int code = 0;
1294         __try
1295         {
1296                 code = _main(argc, argv);
1297         }
1298         __except(CrashFilter(GetExceptionInformation(), GetExceptionCode()))
1299         {
1300                 code = -1;
1301         }
1302         if (avmshell::show_error) printf("error %d", code);
1303         return code;
1304 }
1305 #else
1306
1307 #ifdef AVMPLUS_ARM
1308 // TODO this is a hack until we learn how to determine stack top
1309 // in ARM
1310 int StackTop;
1311 #endif
1312
1313 int main(int argc, char *argv[])
1314 {
1315         #ifdef AVMPLUS_ARM
1316         int sp;
1317         asm("mov %0,sp" : "=r" (sp));
1318         StackTop = sp;
1319         #endif
1320
1321 #ifdef AVMPLUS_MACH_EXCEPTIONS
1322         GenericGuard::staticInit();
1323 #endif
1324         int code = _main(argc, argv);
1325         if (avmshell::show_error) printf("error %d", code);
1326        
1327 #ifdef AVMPLUS_MACH_EXCEPTIONS
1328         GenericGuard::staticDestroy();
1329 #endif 
1330
1331         return code;
1332 }
1333 #endif
1334
1335
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。