| /**************************************************************************** |
| ** |
| ** Copyright (C) 2017 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the examples of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:BSD$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** BSD License Usage |
| ** Alternatively, you may use this file under the terms of the BSD license |
| ** as follows: |
| ** |
| ** "Redistribution and use in source and binary forms, with or without |
| ** modification, are permitted provided that the following conditions are |
| ** met: |
| ** * Redistributions of source code must retain the above copyright |
| ** notice, this list of conditions and the following disclaimer. |
| ** * Redistributions in binary form must reproduce the above copyright |
| ** notice, this list of conditions and the following disclaimer in |
| ** the documentation and/or other materials provided with the |
| ** distribution. |
| ** * Neither the name of The Qt Company Ltd nor the names of its |
| ** contributors may be used to endorse or promote products derived |
| ** from this software without specific prior written permission. |
| ** |
| ** |
| ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| |
| #include <qscriptengine.h> |
| |
| #include <QtCore/QFile> |
| #include <QtCore/QTextStream> |
| #include <QtCore/QStringList> |
| #include <QtWidgets/QApplication> |
| |
| #include <stdlib.h> |
| |
| #include "bytearrayclass.h" |
| |
| static bool wantsToQuit; |
| |
| static QScriptValue qtscript_quit(QScriptContext *ctx, QScriptEngine *eng) |
| { |
| Q_UNUSED(ctx); |
| wantsToQuit = true; |
| return eng->undefinedValue(); |
| } |
| |
| static void interactive(QScriptEngine *eng) |
| { |
| QScriptValue global = eng->globalObject(); |
| QScriptValue quitFunction = eng->newFunction(qtscript_quit); |
| if (!global.property(QLatin1String("exit")).isValid()) |
| global.setProperty(QLatin1String("exit"), quitFunction); |
| if (!global.property(QLatin1String("quit")).isValid()) |
| global.setProperty(QLatin1String("quit"), quitFunction); |
| wantsToQuit = false; |
| |
| QTextStream qin(stdin, QFile::ReadOnly); |
| |
| const char *qscript_prompt = "qs> "; |
| const char *dot_prompt = ".... "; |
| const char *prompt = qscript_prompt; |
| |
| QString code; |
| |
| forever { |
| QString line; |
| |
| printf("%s", prompt); |
| fflush(stdout); |
| |
| line = qin.readLine(); |
| if (line.isNull()) |
| break; |
| |
| code += line; |
| code += QLatin1Char('\n'); |
| |
| if (line.trimmed().isEmpty()) { |
| continue; |
| |
| } else if (! eng->canEvaluate(code)) { |
| prompt = dot_prompt; |
| |
| } else { |
| QScriptValue result = eng->evaluate(code, QLatin1String("typein")); |
| |
| code.clear(); |
| prompt = qscript_prompt; |
| |
| if (! result.isUndefined()) |
| fprintf(stderr, "%s\n", qPrintable(result.toString())); |
| |
| if (wantsToQuit) |
| break; |
| } |
| } |
| } |
| |
| static QScriptValue importExtension(QScriptContext *context, QScriptEngine *engine) |
| { |
| return engine->importExtension(context->argument(0).toString()); |
| } |
| |
| static QScriptValue loadScripts(QScriptContext *context, QScriptEngine *engine) |
| { |
| for (int i = 0; i < context->argumentCount(); ++i) { |
| QString fileName = context->argument(i).toString(); |
| QFile file(fileName); |
| if (!file.open(QIODevice::ReadOnly)) |
| return context->throwError(QString::fromLatin1("could not open %0 for reading").arg(fileName)); |
| QTextStream ts(&file); |
| QString contents = ts.readAll(); |
| file.close(); |
| QScriptContext *pc = context->parentContext(); |
| context->setActivationObject(pc->activationObject()); |
| context->setThisObject(pc->thisObject()); |
| QScriptValue ret = engine->evaluate(contents); |
| if (engine->hasUncaughtException()) |
| return ret; |
| } |
| return engine->undefinedValue(); |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| QCoreApplication *app = new QCoreApplication(argc, argv); |
| QScriptEngine *eng = new QScriptEngine(); |
| |
| QScriptValue globalObject = eng->globalObject(); |
| |
| globalObject.setProperty("load", eng->newFunction(loadScripts, /*length=*/1)); |
| |
| { |
| if (!globalObject.property("qt").isObject()) |
| globalObject.setProperty("qt", eng->newObject()); |
| QScriptValue qscript = eng->newObject(); |
| qscript.setProperty("importExtension", eng->newFunction(importExtension)); |
| globalObject.property("qt").setProperty("script", qscript); |
| } |
| |
| ByteArrayClass *byteArrayClass = new ByteArrayClass(eng); |
| globalObject.setProperty("ByteArray", byteArrayClass->constructor()); |
| |
| if (! *++argv) { |
| interactive(eng); |
| return EXIT_SUCCESS; |
| } |
| |
| while (const char *arg = *argv++) { |
| QString fn = QString::fromLocal8Bit(arg); |
| |
| if (fn == QLatin1String("-i")) { |
| interactive(eng); |
| break; |
| } |
| |
| QString contents; |
| int lineNumber = 1; |
| |
| if (fn == QLatin1String("-")) { |
| QTextStream stream(stdin, QFile::ReadOnly); |
| contents = stream.readAll(); |
| } |
| |
| else { |
| QFile file(fn); |
| |
| if (file.open(QFile::ReadOnly)) { |
| QTextStream stream(&file); |
| contents = stream.readAll(); |
| file.close(); |
| |
| // strip off #!/usr/bin/env qscript line |
| if (contents.startsWith("#!")) { |
| contents.remove(0, contents.indexOf("\n")); |
| ++lineNumber; |
| } |
| } |
| } |
| |
| if (contents.isEmpty()) |
| continue; |
| |
| QScriptValue r = eng->evaluate(contents, fn, lineNumber); |
| if (eng->hasUncaughtException()) { |
| QStringList backtrace = eng->uncaughtExceptionBacktrace(); |
| fprintf (stderr, " %s\n%s\n\n", qPrintable(r.toString()), |
| qPrintable(backtrace.join("\n"))); |
| return EXIT_FAILURE; |
| } |
| } |
| |
| delete eng; |
| delete app; |
| |
| return EXIT_SUCCESS; |
| } |