source: webkit/trunk/Source/JavaScriptCore/jsc.cpp@ 121394

Last change on this file since 121394 was 121394, checked in by [email protected], 13 years ago

[Win] jscore-tests flakey
https://bugs.webkit.org/show_bug.cgi?id=88118

Reviewed by Jessie Berlin.

jsDriver.pl on windows intermittently doesn't get the returned value from jsc,
instead it gets 126. Added a new option to jsc (-x) which prints the exit
code before exiting. jsDriver.pl uses this option on Windows and parses the
exit code output for the exit code, removing it before comparing the actual
and expected outputs. Filed a follow on "FIXME" defect:
[WIN] Intermittent failure for jsc return value to propagate through jsDriver.pl
https://bugs.webkit.org/show_bug.cgi?id=90119

  • jsc.cpp:

(CommandLine::CommandLine):
(CommandLine):
(printUsageStatement):
(parseArguments):
(jscmain):

  • tests/mozilla/jsDriver.pl:

(execute_tests):

  • Property svn:eol-style set to native
File size: 23.5 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2006 Bjoern Graf ([email protected])
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24
25#include "BytecodeGenerator.h"
26#include "Completion.h"
27#include <wtf/CurrentTime.h>
28#include "ExceptionHelpers.h"
29#include "InitializeThreading.h"
30#include "Interpreter.h"
31#include "JSArray.h"
32#include "JSCTypedArrayStubs.h"
33#include "JSFunction.h"
34#include "JSLock.h"
35#include "JSString.h"
36#include <wtf/MainThread.h>
37#include "SamplingTool.h"
38#include <math.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43#if !OS(WINDOWS)
44#include <unistd.h>
45#endif
46
47#if HAVE(READLINE)
48// readline/history.h has a Function typedef which conflicts with the WTF::Function template from WTF/Forward.h
49// We #define it to something else to avoid this conflict.
50#define Function ReadlineFunction
51#include <readline/history.h>
52#include <readline/readline.h>
53#undef Function
54#endif
55
56#if HAVE(SYS_TIME_H)
57#include <sys/time.h>
58#endif
59
60#if HAVE(SIGNAL_H)
61#include <signal.h>
62#endif
63
64#if COMPILER(MSVC) && !OS(WINCE)
65#include <crtdbg.h>
66#include <mmsystem.h>
67#include <windows.h>
68#endif
69
70#if PLATFORM(QT)
71#include <QCoreApplication>
72#include <QDateTime>
73#endif
74
75#if PLATFORM(IOS)
76#include <fenv.h>
77#include <arm/arch.h>
78#endif
79
80using namespace JSC;
81using namespace WTF;
82
83static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
84
85static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
86static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
87static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*);
88static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
89#ifndef NDEBUG
90static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
91#endif
92static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
93static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
94static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
95static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
96static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
97static EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*);
98static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
99
100#if ENABLE(SAMPLING_FLAGS)
101static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
102static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
103#endif
104
105struct Script {
106 bool isFile;
107 char* argument;
108
109 Script(bool isFile, char *argument)
110 : isFile(isFile)
111 , argument(argument)
112 {
113 }
114};
115
116struct CommandLine {
117 CommandLine()
118 : interactive(false)
119 , dump(false)
120 , exitCode(false)
121 {
122 }
123
124 bool interactive;
125 bool dump;
126 bool exitCode;
127 Vector<Script> scripts;
128 Vector<UString> arguments;
129};
130
131static const char interactivePrompt[] = "> ";
132
133class StopWatch {
134public:
135 void start();
136 void stop();
137 long getElapsedMS(); // call stop() first
138
139private:
140 double m_startTime;
141 double m_stopTime;
142};
143
144void StopWatch::start()
145{
146 m_startTime = currentTime();
147}
148
149void StopWatch::stop()
150{
151 m_stopTime = currentTime();
152}
153
154long StopWatch::getElapsedMS()
155{
156 return static_cast<long>((m_stopTime - m_startTime) * 1000);
157}
158
159class GlobalObject : public JSGlobalObject {
160private:
161 GlobalObject(JSGlobalData&, Structure*);
162
163public:
164 typedef JSGlobalObject Base;
165
166 static GlobalObject* create(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
167 {
168 GlobalObject* object = new (NotNull, allocateCell<GlobalObject>(globalData.heap)) GlobalObject(globalData, structure);
169 object->finishCreation(globalData, arguments);
170 return object;
171 }
172
173 static const ClassInfo s_info;
174 static const GlobalObjectMethodTable s_globalObjectMethodTable;
175
176 static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
177 {
178 return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
179 }
180
181 static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return true; }
182
183protected:
184 void finishCreation(JSGlobalData& globalData, const Vector<UString>& arguments)
185 {
186 Base::finishCreation(globalData);
187
188 addFunction(globalData, "debug", functionDebug, 1);
189 addFunction(globalData, "print", functionPrint, 1);
190 addFunction(globalData, "quit", functionQuit, 0);
191 addFunction(globalData, "gc", functionGC, 0);
192#ifndef NDEBUG
193 addFunction(globalData, "releaseExecutableMemory", functionReleaseExecutableMemory, 0);
194#endif
195 addFunction(globalData, "version", functionVersion, 1);
196 addFunction(globalData, "run", functionRun, 1);
197 addFunction(globalData, "load", functionLoad, 1);
198 addFunction(globalData, "checkSyntax", functionCheckSyntax, 1);
199 addFunction(globalData, "jscStack", functionJSCStack, 1);
200 addFunction(globalData, "readline", functionReadline, 0);
201 addFunction(globalData, "preciseTime", functionPreciseTime, 0);
202#if ENABLE(SAMPLING_FLAGS)
203 addFunction(globalData, "setSamplingFlags", functionSetSamplingFlags, 1);
204 addFunction(globalData, "clearSamplingFlags", functionClearSamplingFlags, 1);
205#endif
206
207 addConstructableFunction(globalData, "Uint8Array", constructJSUint8Array, 1);
208 addConstructableFunction(globalData, "Uint8ClampedArray", constructJSUint8ClampedArray, 1);
209 addConstructableFunction(globalData, "Uint16Array", constructJSUint16Array, 1);
210 addConstructableFunction(globalData, "Uint32Array", constructJSUint32Array, 1);
211 addConstructableFunction(globalData, "Int8Array", constructJSInt8Array, 1);
212 addConstructableFunction(globalData, "Int16Array", constructJSInt16Array, 1);
213 addConstructableFunction(globalData, "Int32Array", constructJSInt32Array, 1);
214 addConstructableFunction(globalData, "Float32Array", constructJSFloat32Array, 1);
215 addConstructableFunction(globalData, "Float64Array", constructJSFloat64Array, 1);
216
217 JSArray* array = constructEmptyArray(globalExec());
218 for (size_t i = 0; i < arguments.size(); ++i)
219 array->putDirectIndex(globalExec(), i, jsString(globalExec(), arguments[i]), false);
220 putDirect(globalData, Identifier(globalExec(), "arguments"), array);
221 }
222
223 void addFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments)
224 {
225 Identifier identifier(globalExec(), name);
226 putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier.ustring(), function));
227 }
228
229 void addConstructableFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments)
230 {
231 Identifier identifier(globalExec(), name);
232 putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier.ustring(), function, NoIntrinsic, function));
233 }
234};
235COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
236ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
237
238const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(GlobalObject) };
239const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled };
240
241
242GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure)
243 : JSGlobalObject(globalData, structure, &s_globalObjectMethodTable)
244{
245}
246
247static inline SourceCode jscSource(const char* utf8, const UString& filename)
248{
249 // Find the the first non-ascii character, or nul.
250 const char* pos = utf8;
251 while (*pos > 0)
252 pos++;
253 size_t asciiLength = pos - utf8;
254
255 // Fast case - string is all ascii.
256 if (!*pos)
257 return makeSource(UString(utf8, asciiLength), filename);
258
259 // Slow case - contains non-ascii characters, use fromUTF8WithLatin1Fallback.
260 ASSERT(*pos < 0);
261 ASSERT(strlen(utf8) == asciiLength + strlen(pos));
262 String source = String::fromUTF8WithLatin1Fallback(utf8, asciiLength + strlen(pos));
263 return makeSource(source.impl(), filename);
264}
265
266EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
267{
268 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
269 if (i)
270 putchar(' ');
271
272 printf("%s", exec->argument(i).toString(exec)->value(exec).utf8().data());
273 }
274
275 putchar('\n');
276 fflush(stdout);
277 return JSValue::encode(jsUndefined());
278}
279
280EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
281{
282 fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data());
283 return JSValue::encode(jsUndefined());
284}
285
286EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec)
287{
288 String trace = "--> Stack trace:\n";
289 Vector<StackFrame> stackTrace;
290 Interpreter::getStackTrace(&exec->globalData(), stackTrace);
291 int i = 0;
292
293 for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) {
294 StackFrame level = *iter;
295 trace += String::format(" %i %s\n", i, level.toString(exec).utf8().data());
296 i++;
297 }
298 fprintf(stderr, "%s", trace.utf8().data());
299 return JSValue::encode(jsUndefined());
300}
301
302EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
303{
304 JSLockHolder lock(exec);
305 exec->heap()->collectAllGarbage();
306 return JSValue::encode(jsUndefined());
307}
308
309#ifndef NDEBUG
310EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
311{
312 JSLockHolder lock(exec);
313 exec->globalData().releaseExecutableMemory();
314 return JSValue::encode(jsUndefined());
315}
316#endif
317
318EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
319{
320 // We need this function for compatibility with the Mozilla JS tests but for now
321 // we don't actually do any version-specific handling
322 return JSValue::encode(jsUndefined());
323}
324
325EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
326{
327 UString fileName = exec->argument(0).toString(exec)->value(exec);
328 Vector<char> script;
329 if (!fillBufferWithContentsOfFile(fileName, script))
330 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
331
332 GlobalObject* globalObject = GlobalObject::create(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<UString>());
333
334 JSValue exception;
335 StopWatch stopWatch;
336 stopWatch.start();
337 evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script.data(), fileName), JSValue(), &exception);
338 stopWatch.stop();
339
340 if (!!exception) {
341 throwError(globalObject->globalExec(), exception);
342 return JSValue::encode(jsUndefined());
343 }
344
345 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
346}
347
348EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
349{
350 UString fileName = exec->argument(0).toString(exec)->value(exec);
351 Vector<char> script;
352 if (!fillBufferWithContentsOfFile(fileName, script))
353 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
354
355 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
356
357 JSValue evaluationException;
358 JSValue result = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script.data(), fileName), JSValue(), &evaluationException);
359 if (evaluationException)
360 throwError(exec, evaluationException);
361 return JSValue::encode(result);
362}
363
364EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
365{
366 UString fileName = exec->argument(0).toString(exec)->value(exec);
367 Vector<char> script;
368 if (!fillBufferWithContentsOfFile(fileName, script))
369 return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
370
371 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
372
373 StopWatch stopWatch;
374 stopWatch.start();
375
376 JSValue syntaxException;
377 bool validSyntax = checkSyntax(globalObject->globalExec(), jscSource(script.data(), fileName), &syntaxException);
378 stopWatch.stop();
379
380 if (!validSyntax)
381 throwError(exec, syntaxException);
382 return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
383}
384
385#if ENABLE(SAMPLING_FLAGS)
386EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
387{
388 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
389 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
390 if ((flag >= 1) && (flag <= 32))
391 SamplingFlags::setFlag(flag);
392 }
393 return JSValue::encode(jsNull());
394}
395
396EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
397{
398 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
399 unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
400 if ((flag >= 1) && (flag <= 32))
401 SamplingFlags::clearFlag(flag);
402 }
403 return JSValue::encode(jsNull());
404}
405#endif
406
407EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
408{
409 Vector<char, 256> line;
410 int c;
411 while ((c = getchar()) != EOF) {
412 // FIXME: Should we also break on \r?
413 if (c == '\n')
414 break;
415 line.append(c);
416 }
417 line.append('\0');
418 return JSValue::encode(jsString(exec, line.data()));
419}
420
421EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*)
422{
423 return JSValue::encode(jsNumber(currentTime()));
424}
425
426EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*)
427{
428 exit(EXIT_SUCCESS);
429
430#if COMPILER(MSVC) && OS(WINCE)
431 // Without this, Visual Studio will complain that this method does not return a value.
432 return JSValue::encode(jsUndefined());
433#endif
434}
435
436// Use SEH for Release builds only to get rid of the crash report dialog
437// (luckily the same tests fail in Release and Debug builds so far). Need to
438// be in a separate main function because the jscmain function requires object
439// unwinding.
440
441#if COMPILER(MSVC) && !COMPILER(INTEL) && !defined(_DEBUG) && !OS(WINCE)
442#define TRY __try {
443#define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
444#else
445#define TRY
446#define EXCEPT(x)
447#endif
448
449int jscmain(int argc, char** argv);
450
451int main(int argc, char** argv)
452{
453#if PLATFORM(IOS)
454 // Enabled IEEE754 denormal support.
455 fenv_t env;
456 fegetenv( &env );
457 env.__fpscr &= ~0x01000000u;
458 fesetenv( &env );
459#endif
460
461#if OS(WINDOWS)
462#if !OS(WINCE)
463 // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
464 // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
465 // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
466 ::SetErrorMode(0);
467#endif
468
469#if defined(_DEBUG)
470 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
471 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
472 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
473 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
474 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
475 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
476#endif
477
478 timeBeginPeriod(1);
479#endif
480
481#if PLATFORM(QT)
482 QCoreApplication app(argc, argv);
483#endif
484
485 // Initialize JSC before getting JSGlobalData.
486#if ENABLE(SAMPLING_REGIONS)
487 WTF::initializeMainThread();
488#endif
489 JSC::initializeThreading();
490
491 // We can't use destructors in the following code because it uses Windows
492 // Structured Exception Handling
493 int res = 0;
494 TRY
495 res = jscmain(argc, argv);
496 EXCEPT(res = 3)
497 return res;
498}
499
500static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump)
501{
502 const char* script;
503 UString fileName;
504 Vector<char> scriptBuffer;
505
506 if (dump)
507 BytecodeGenerator::setDumpsGeneratedCode(true);
508
509 JSGlobalData& globalData = globalObject->globalData();
510
511#if ENABLE(SAMPLING_FLAGS)
512 SamplingFlags::start();
513#endif
514
515 bool success = true;
516 for (size_t i = 0; i < scripts.size(); i++) {
517 if (scripts[i].isFile) {
518 fileName = scripts[i].argument;
519 if (!fillBufferWithContentsOfFile(fileName, scriptBuffer))
520 return false; // fail early so we can catch missing files
521 script = scriptBuffer.data();
522 } else {
523 script = scripts[i].argument;
524 fileName = "[Command Line]";
525 }
526
527 globalData.startSampling();
528
529 JSValue evaluationException;
530 JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script, fileName), JSValue(), &evaluationException);
531 success = success && !evaluationException;
532 if (dump && !evaluationException)
533 printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
534 if (evaluationException) {
535 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
536 Identifier stackID(globalObject->globalExec(), "stack");
537 JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID);
538 if (!stackValue.isUndefinedOrNull())
539 printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
540 }
541
542 globalData.stopSampling();
543 globalObject->globalExec()->clearException();
544 }
545
546#if ENABLE(SAMPLING_FLAGS)
547 SamplingFlags::stop();
548#endif
549#if ENABLE(SAMPLING_REGIONS)
550 SamplingRegion::dump();
551#endif
552 globalData.dumpSampleData(globalObject->globalExec());
553#if ENABLE(SAMPLING_COUNTERS)
554 AbstractSamplingCounter::dump();
555#endif
556#if ENABLE(REGEXP_TRACING)
557 globalData.dumpRegExpTrace();
558#endif
559 return success;
560}
561
562#define RUNNING_FROM_XCODE 0
563
564static void runInteractive(GlobalObject* globalObject)
565{
566 UString interpreterName("Interpreter");
567
568 while (true) {
569#if HAVE(READLINE) && !RUNNING_FROM_XCODE
570 char* line = readline(interactivePrompt);
571 if (!line)
572 break;
573 if (line[0])
574 add_history(line);
575 JSValue evaluationException;
576 JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(line, interpreterName), JSValue(), &evaluationException);
577 free(line);
578#else
579 printf("%s", interactivePrompt);
580 Vector<char, 256> line;
581 int c;
582 while ((c = getchar()) != EOF) {
583 // FIXME: Should we also break on \r?
584 if (c == '\n')
585 break;
586 line.append(c);
587 }
588 if (line.isEmpty())
589 break;
590 line.append('\0');
591
592 JSValue evaluationException;
593 JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(line.data(), interpreterName), JSValue(), &evaluationException);
594#endif
595 if (evaluationException)
596 printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
597 else
598 printf("%s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data());
599
600 globalObject->globalExec()->clearException();
601 }
602 printf("\n");
603}
604
605static NO_RETURN void printUsageStatement(bool help = false)
606{
607 fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n");
608 fprintf(stderr, " -d Dumps bytecode (debug builds only)\n");
609 fprintf(stderr, " -e Evaluate argument as script code\n");
610 fprintf(stderr, " -f Specifies a source file (deprecated)\n");
611 fprintf(stderr, " -h|--help Prints this help message\n");
612 fprintf(stderr, " -i Enables interactive mode (default if no files are specified)\n");
613#if HAVE(SIGNAL_H)
614 fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n");
615#endif
616 fprintf(stderr, " -x Output exit code before terminating\n");
617
618 exit(help ? EXIT_SUCCESS : EXIT_FAILURE);
619}
620
621static void parseArguments(int argc, char** argv, CommandLine& options)
622{
623 int i = 1;
624 for (; i < argc; ++i) {
625 const char* arg = argv[i];
626 if (!strcmp(arg, "-f")) {
627 if (++i == argc)
628 printUsageStatement();
629 options.scripts.append(Script(true, argv[i]));
630 continue;
631 }
632 if (!strcmp(arg, "-e")) {
633 if (++i == argc)
634 printUsageStatement();
635 options.scripts.append(Script(false, argv[i]));
636 continue;
637 }
638 if (!strcmp(arg, "-i")) {
639 options.interactive = true;
640 continue;
641 }
642 if (!strcmp(arg, "-d")) {
643 options.dump = true;
644 continue;
645 }
646 if (!strcmp(arg, "-s")) {
647#if HAVE(SIGNAL_H)
648 signal(SIGILL, _exit);
649 signal(SIGFPE, _exit);
650 signal(SIGBUS, _exit);
651 signal(SIGSEGV, _exit);
652#endif
653 continue;
654 }
655 if (!strcmp(arg, "-x")) {
656 options.exitCode = true;
657 continue;
658 }
659 if (!strcmp(arg, "--")) {
660 ++i;
661 break;
662 }
663 if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
664 printUsageStatement(true);
665 options.scripts.append(Script(true, argv[i]));
666 }
667
668 if (options.scripts.isEmpty())
669 options.interactive = true;
670
671 for (; i < argc; ++i)
672 options.arguments.append(argv[i]);
673}
674
675int jscmain(int argc, char** argv)
676{
677 RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
678 JSLockHolder lock(globalData.get());
679 int result;
680
681 CommandLine options;
682 parseArguments(argc, argv, options);
683
684 GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
685 bool success = runWithScripts(globalObject, options.scripts, options.dump);
686 if (options.interactive && success)
687 runInteractive(globalObject);
688
689 result = success ? 0 : 3;
690
691 if (options.exitCode)
692 printf("jsc exiting %d\n", result);
693
694 return result;
695}
696
697static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
698{
699 FILE* f = fopen(fileName.utf8().data(), "r");
700 if (!f) {
701 fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
702 return false;
703 }
704
705 size_t bufferSize = 0;
706 size_t bufferCapacity = 1024;
707
708 buffer.resize(bufferCapacity);
709
710 while (!feof(f) && !ferror(f)) {
711 bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f);
712 if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0'
713 bufferCapacity *= 2;
714 buffer.resize(bufferCapacity);
715 }
716 }
717 fclose(f);
718 buffer[bufferSize] = '\0';
719
720 if (buffer[0] == '#' && buffer[1] == '!')
721 buffer[0] = buffer[1] = '/';
722
723 return true;
724}
Note: See TracBrowser for help on using the repository browser.