1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51
52#include <qscriptengine.h>
53
54#include <QtCore/QFile>
55#include <QtCore/QTextStream>
56#include <QtCore/QStringList>
57#include <QtWidgets/QApplication>
58
59#include <stdlib.h>
60
61#include "bytearrayclass.h"
62
63static bool wantsToQuit;
64
65static QScriptValue qtscript_quit(QScriptContext *ctx, QScriptEngine *eng)
66{
67 Q_UNUSED(ctx);
68 wantsToQuit = true;
69 return eng->undefinedValue();
70}
71
72static void interactive(QScriptEngine *eng)
73{
74 QScriptValue global = eng->globalObject();
75 QScriptValue quitFunction = eng->newFunction(signature: qtscript_quit);
76 if (!global.property(name: QLatin1String("exit")).isValid())
77 global.setProperty(name: QLatin1String("exit"), value: quitFunction);
78 if (!global.property(name: QLatin1String("quit")).isValid())
79 global.setProperty(name: QLatin1String("quit"), value: quitFunction);
80 wantsToQuit = false;
81
82 QTextStream qin(stdin, QFile::ReadOnly);
83
84 const char *qscript_prompt = "qs> ";
85 const char *dot_prompt = ".... ";
86 const char *prompt = qscript_prompt;
87
88 QString code;
89
90 forever {
91 QString line;
92
93 printf(format: "%s", prompt);
94 fflush(stdout);
95
96 line = qin.readLine();
97 if (line.isNull())
98 break;
99
100 code += line;
101 code += QLatin1Char('\n');
102
103 if (line.trimmed().isEmpty()) {
104 continue;
105
106 } else if (! eng->canEvaluate(program: code)) {
107 prompt = dot_prompt;
108
109 } else {
110 QScriptValue result = eng->evaluate(program: code, fileName: QLatin1String("typein"));
111
112 code.clear();
113 prompt = qscript_prompt;
114
115 if (! result.isUndefined())
116 fprintf(stderr, format: "%s\n", qPrintable(result.toString()));
117
118 if (wantsToQuit)
119 break;
120 }
121 }
122}
123
124static QScriptValue importExtension(QScriptContext *context, QScriptEngine *engine)
125{
126 return engine->importExtension(extension: context->argument(index: 0).toString());
127}
128
129static QScriptValue loadScripts(QScriptContext *context, QScriptEngine *engine)
130{
131 for (int i = 0; i < context->argumentCount(); ++i) {
132 QString fileName = context->argument(index: i).toString();
133 QFile file(fileName);
134 if (!file.open(flags: QIODevice::ReadOnly))
135 return context->throwError(text: QString::fromLatin1(str: "could not open %0 for reading").arg(a: fileName));
136 QTextStream ts(&file);
137 QString contents = ts.readAll();
138 file.close();
139 QScriptContext *pc = context->parentContext();
140 context->setActivationObject(pc->activationObject());
141 context->setThisObject(pc->thisObject());
142 QScriptValue ret = engine->evaluate(program: contents);
143 if (engine->hasUncaughtException())
144 return ret;
145 }
146 return engine->undefinedValue();
147}
148
149int main(int argc, char *argv[])
150{
151 QCoreApplication *app = new QCoreApplication(argc, argv);
152 QScriptEngine *eng = new QScriptEngine();
153
154 QScriptValue globalObject = eng->globalObject();
155
156 globalObject.setProperty(name: "load", value: eng->newFunction(signature: loadScripts, /*length=*/1));
157
158 {
159 if (!globalObject.property(name: "qt").isObject())
160 globalObject.setProperty(name: "qt", value: eng->newObject());
161 QScriptValue qscript = eng->newObject();
162 qscript.setProperty(name: "importExtension", value: eng->newFunction(signature: importExtension));
163 globalObject.property(name: "qt").setProperty(name: "script", value: qscript);
164 }
165
166 ByteArrayClass *byteArrayClass = new ByteArrayClass(eng);
167 globalObject.setProperty(name: "ByteArray", value: byteArrayClass->constructor());
168
169 if (! *++argv) {
170 interactive(eng);
171 return EXIT_SUCCESS;
172 }
173
174 while (const char *arg = *argv++) {
175 QString fn = QString::fromLocal8Bit(str: arg);
176
177 if (fn == QLatin1String("-i")) {
178 interactive(eng);
179 break;
180 }
181
182 QString contents;
183 int lineNumber = 1;
184
185 if (fn == QLatin1String("-")) {
186 QTextStream stream(stdin, QFile::ReadOnly);
187 contents = stream.readAll();
188 }
189
190 else {
191 QFile file(fn);
192
193 if (file.open(flags: QFile::ReadOnly)) {
194 QTextStream stream(&file);
195 contents = stream.readAll();
196 file.close();
197
198 // strip off #!/usr/bin/env qscript line
199 if (contents.startsWith(s: "#!")) {
200 contents.remove(i: 0, len: contents.indexOf(s: "\n"));
201 ++lineNumber;
202 }
203 }
204 }
205
206 if (contents.isEmpty())
207 continue;
208
209 QScriptValue r = eng->evaluate(program: contents, fileName: fn, lineNumber);
210 if (eng->hasUncaughtException()) {
211 QStringList backtrace = eng->uncaughtExceptionBacktrace();
212 fprintf (stderr, format: " %s\n%s\n\n", qPrintable(r.toString()),
213 qPrintable(backtrace.join("\n")));
214 return EXIT_FAILURE;
215 }
216 }
217
218 delete eng;
219 delete app;
220
221 return EXIT_SUCCESS;
222}
223

source code of qtscript/examples/script/qscript/main.cpp