1 // -*- c-basic-offset: 2 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 2006 Harri Porten (porten@kde.org)
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.
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.
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.
24 #include "interpreter.h"
42 #include <kdeversion.h>
44 enum ExitCode
{ ErrorNone
,
55 static void printUsage(const char *app
)
59 " [ -h | -help | --help ]\n"
60 " [ -e <statement> | <script> ]\n"
61 " [-v | -version | --version]\n",
65 static UString
readFile(const char* fileName
)
67 int fd
= open(fileName
, O_RDONLY
);
69 fprintf(stderr
, "Error opening %s", fileName
);
73 if (fstat(fd
, &buf
) == -1) {
74 fprintf(stderr
, "Error stat'ing %s", fileName
);
78 int siz
= buf
.st_size
;
79 char* c
= new char[siz
+ 1];
80 int dataRead
= read(fd
, c
, siz
);
82 fprintf(stderr
, "Error reading from %s", fileName
);
93 static ExitCode
evaluateFile(Interpreter
*interp
, const char *fileName
);
95 class GlobalImp
: public JSGlobalObject
{
97 virtual UString
className() const { return "global"; }
100 class TestFunctionImp
: public JSObject
{
102 TestFunctionImp(int i
, int length
);
103 virtual bool implementsCall() const { return true; }
104 virtual JSValue
* callAsFunction(ExecState
* exec
,
105 JSObject
* thisObj
, const List
&args
);
106 enum { Print
, Quit
, Load
, GC
};
112 TestFunctionImp::TestFunctionImp(int i
, int length
)
115 putDirect(Identifier("length"), length
, DontDelete
| ReadOnly
| DontEnum
);
118 JSValue
* TestFunctionImp::callAsFunction(ExecState
* exec
,
119 JSObject
* /* thisObj */,
124 printf("%s\n", args
[0]->toString(exec
).UTF8String().c_str());
125 return jsUndefined();
129 while (Interpreter::collect()) {}
132 evaluateFile(exec
->dynamicInterpreter(), args
[0]->toString(exec
).UTF8String().c_str());
137 return jsUndefined();
140 static ExitCode
evaluateString(Interpreter
*interp
, const char *fileName
,
142 bool printResult
= false)
144 ExecState
*exec
= interp
->globalExec();
146 Completion res
= interp
->evaluate(fileName
, 0, code
);
148 if (res
.complType() == Throw
) {
149 CString msg
= res
.value()->toString(exec
).UTF8String();
150 JSObject
* resObj
= res
.value()->toObject(exec
);
151 CString message
= resObj
->toString(exec
).UTF8String();
152 int line
= resObj
->toObject(exec
)->get(exec
, "line")->toUInt32(exec
);
155 fprintf(stderr
, "%s (line %d): ", fileName
, line
);
156 fprintf(stderr
, "%s\n", msg
.c_str());
158 } else if (printResult
) {
159 if (res
.isValueCompletion() && !res
.value()->isUndefined()) {
160 CString s8
= res
.value()->toString(exec
).UTF8String();
162 fprintf(stdout
, "%s\n", s8
.c_str());
169 static ExitCode
evaluateFile(Interpreter
*interp
, const char *fileName
)
171 UString code
= readFile(fileName
);
173 return ErrorReadFile
;
175 return evaluateString(interp
, fileName
, code
);
178 // primitive readline-like function
179 static char *readLine(const char *prompt
)
182 fprintf(stdout
, "%s", prompt
);
184 const int bsize
= 2 << 10;
185 char *buffer
= static_cast<char*>(malloc(bsize
));
186 char *s
= fgets(buffer
, bsize
, stdin
);
189 fprintf(stdout
, "\n");
195 static ExitCode
evaluateInteractive(Interpreter
*interp
)
198 while ((line
= readLine("JS> ")) != 0) {
201 evaluateString(interp
, 0, code
, true);
207 static ExitCode
parseArgs(int argc
, char** argv
)
211 GlobalImp
* global
= new GlobalImp();
213 // create interpreter
214 RefPtr
<Interpreter
> interp
= new Interpreter(global
);
216 // add some global extension functions
217 ExecState
*gexec
= interp
->globalExec();
218 global
->put(gexec
, "print",
219 new TestFunctionImp(TestFunctionImp::Print
, 1));
220 global
->put(gexec
, "quit",
221 new TestFunctionImp(TestFunctionImp::Quit
, 0));
222 global
->put(gexec
, "load",
223 new TestFunctionImp(TestFunctionImp::Load
, 1));
224 global
->put(gexec
, "gc",
225 new TestFunctionImp(TestFunctionImp::GC
, 0));
227 // enable package support
228 StandardGlobalPackage package
;
229 interp
->setGlobalPackage(&package
);
231 const char *script
= 0, *command
= 0;
233 bool ranOtherScript
= false;
234 for (ai
= 1; ai
< argc
; ++ai
) {
235 const char* a
= argv
[ai
];
236 if (strcmp(a
, "-v" ) == 0 || strcmp(a
, "-version") == 0 ||
237 strcmp(a
, "--version") == 0) {
238 printf("KDE: %s\n", KDE_VERSION_STRING
);
240 } else if (strcmp(a
, "-h" ) == 0 || strcmp(a
, "-help") == 0 ||
241 strcmp(a
, "--help") == 0) {
244 } else if (strcmp(a
, "-e") == 0) {
247 fprintf(stderr
, "Missing -e argument.\n");
248 return ErrorMissingArg
;
253 } else if (strcmp(a
, "-f") == 0) { // Compatibility mode, for SunSpider
256 fprintf(stderr
, "Missing -f argument.\n");
257 return ErrorMissingArg
;
259 ExitCode result
= evaluateFile(interp
.get(), argv
[ai
]);
260 if (result
!= ErrorNone
)
262 ranOtherScript
= true;
263 } else if (a
[0] == '-') {
264 fprintf(stderr
, "Unknown switch %s.\n", a
);
265 return ErrorUnknownSwitch
;
275 fprintf(stderr
, "Warning: ignoring extra arguments\n");
278 return evaluateFile(interp
.get(), script
);
279 } else if (command
) {
280 return evaluateString(interp
.get(), "(eval)", command
);
281 } else if (!ranOtherScript
) {
282 return evaluateInteractive(interp
.get());
287 int main(int argc
, char** argv
)
289 return int(parseArgs(argc
, argv
));