File indexing completed on 2022-09-27 12:31:11

0001 /*
0002     SPDX-FileCopyrightText: 2003-2006 Cies Breijs <cies AT kde DOT nl>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 
0008 #include <iostream>
0009 
0010 #include <QFile>
0011 #include <QDebug>
0012 #include <QApplication>
0013 #include <KAboutData>
0014 #include <KCrash>
0015 #include <KLocalizedString>
0016 #include <QCommandLineParser>
0017 #include <QCommandLineOption>
0018 #include <Kdelibs4ConfigMigrator>
0019 
0020 #include "mainwindow.h"  // for gui mode
0021 
0022 #include "interpreter/interpreter.h"  // for non gui mode
0023 #include "interpreter/echoer.h"
0024 #include "interpreter/tokenizer.h"
0025 
0026 #include "kturtle_version.h"
0027 
0028 int main(int argc, char* argv[])
0029 {
0030     KLocalizedString::setApplicationDomain("kturtle");
0031 
0032     QApplication app(argc, argv);
0033 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0034     app.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
0035 #endif
0036     KCrash::initialize();
0037 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0038     /* for migration*/
0039     QStringList configFiles;
0040     configFiles << QStringLiteral("kturtlerc");
0041     Kdelibs4ConfigMigrator migrator(QStringLiteral("kturtle"));
0042     migrator.setConfigFiles(configFiles);
0043     migrator.setUiFiles(QStringList() << QStringLiteral("kturtleui.rc"));
0044     migrator.migrate();
0045 #endif
0046 
0047     KAboutData aboutData(QStringLiteral("kturtle"), i18n("KTurtle"), QLatin1String(KTURTLE_VERSION_STRING));
0048     aboutData.setLicense(KAboutLicense::GPL);
0049     aboutData.setHomepage(i18n("https://edu.kde.org/kturtle"));
0050     aboutData.setShortDescription(i18n("KTurtle is an educational programming environment that aims to make learning how to program as easy as possible. To achieve this KTurtle makes all programming tools available from the user interface. The programming language used is TurtleScript which allows its commands to be translated."));
0051     aboutData.setCopyrightStatement(i18n("(c) 2003-2009 Cies Breijs"));
0052 
0053     aboutData.addAuthor(i18n("Cies Breijs"), i18n("Initiator and core developer"), QStringLiteral("cies@kde.nl"));
0054     aboutData.addAuthor(i18n("Niels Slot"), i18n("Core developer"), QStringLiteral("nielsslot@gmail.com"));
0055     aboutData.addAuthor(i18n("Mauricio Piacentini"), i18n("Core developer"), QStringLiteral("piacentini@kde.org"));
0056 
0057     QCommandLineParser parser;
0058 
0059     KAboutData::setApplicationData(aboutData);
0060     aboutData.setupCommandLine(&parser);
0061 
0062     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("i") << QStringLiteral("input"), i18n("File or URL to open (in the GUI mode)"), QStringLiteral("URL or file")));
0063     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("d") << QStringLiteral("dbus"), i18n("Starts KTurtle in D-Bus mode (without a GUI), good for automated unit test scripts")));
0064     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("t") << QStringLiteral("test"), i18n("Starts KTurtle in testing mode (without a GUI), directly runs the specified local file"), QStringLiteral("file")));
0065     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("l") << QStringLiteral("lang"), i18n("Specifies the localization language by a language code, defaults to \"en_US\" (only works in testing mode)"), QStringLiteral("code")));
0066 //  parser.addOption(QCommandLineOption(QStringList() << QLatin1String("k") << QLatin1String("tokenize"), i18n("Only tokenizes the turtle code (only works in testing mode)")));
0067     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("p") << QStringLiteral("parse"), i18n("Translates turtle code to embeddable C++ example strings (for developers only)"), QStringLiteral("file")));
0068 
0069     parser.process(app);
0070     aboutData.processCommandLine(&parser);
0071 
0072     if (!parser.isSet(QStringLiteral("test")) && !parser.isSet(QStringLiteral("parse")) && !parser.isSet(QStringLiteral("dbus"))) {
0073 
0074         ///////////////// run in GUI mode /////////////////
0075         if (app.isSessionRestored()) {
0076                         kRestoreMainWindows<MainWindow>();
0077         } else {
0078             MainWindow* mainWindow = new MainWindow();
0079             mainWindow->show();
0080             if (parser.isSet(QStringLiteral("input"))) mainWindow->open(parser.value(QStringLiteral("input")));
0081         }
0082           // free some memory
0083         return app.exec();  // the mainwindow has WDestructiveClose flag; it will destroy itself.
0084 
0085     } else if (parser.isSet(QStringLiteral("dbus"))) {
0086 
0087         ///////////////// run in DBUS mode /////////////////
0088         Translator::instance()->setLanguage();
0089         new Interpreter(nullptr, true);
0090         
0091         return app.exec();
0092 
0093     } else if (parser.isSet(QStringLiteral("parse"))) {
0094 
0095         ///////////////// run in example PARSING mode /////////////////
0096         QFile inputFile(parser.value(QStringLiteral("parse")));
0097         if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
0098             std::cout << "Could not open file: " << qPrintable(parser.value(QStringLiteral("parse"))) << std::endl;
0099             std::cout << "Exiting..." << std::endl;
0100             return 1;
0101         }
0102         
0103         Translator::instance()->setLanguage();
0104 
0105         Tokenizer tokenizer;
0106         tokenizer.initialize(QString::fromUtf8(inputFile.readAll()));
0107         inputFile.close();
0108 
0109         const QStringList defaultLooks(Translator::instance()->allDefaultLooks());
0110         QString result;
0111         Token* t;
0112         while ((t = tokenizer.getToken())->type() != Token::EndOfInput) {
0113             if (defaultLooks.contains(t->look()))
0114                 result.append(QStringLiteral("@(%1)").arg(t->look()));
0115             else
0116                 result.append(t->look());
0117             if (t->type() == Token::EndOfLine) result.append(QLatin1Char('\n'));
0118         }
0119 
0120         const auto splitLst{result.split(QLatin1Char('\n'))};
0121         for (const QString &line : splitLst) std::cout << qPrintable(QStringLiteral("\"%1\"").arg(line)) << std::endl;
0122         std::cout << std::endl;
0123 
0124     } else {
0125 
0126         ///////////////// run without a gui /////////////////
0127         std::cout << "KTurtle's interpreter in command line mode (version " << KTURTLE_VERSION_STRING << ")" << std::endl;
0128         std::cout << "(c) 2003-2009 Cies Breijs" << std::endl << std::endl;
0129 
0130         QString fileString = parser.value(QStringLiteral("test"));
0131         QFile inputFile(fileString);
0132 
0133         if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
0134             std::cout << "Could not open input file: " << qPrintable(parser.value(QStringLiteral("test"))) << std::endl;
0135             std::cout << "Exiting..." << std::endl;
0136             return 1;
0137         }
0138 
0139         QTextStream in(&inputFile);
0140 
0141         // check for our magic identifier
0142         QString s;
0143         s = in.readLine();
0144         if (s != KTURTLE_MAGIC_1_0) {
0145             std::cout << "The file you try to open is not a valid KTurtle script, or is incompatible with this version of KTurtle.\n";
0146             return 1;
0147         }
0148 
0149         if (parser.isSet(QStringLiteral("lang"))) {
0150             if (Translator::instance()->setLanguage(parser.value(QStringLiteral("lang")))) {
0151                 std::cout << "Set localization to: " << parser.value(QStringLiteral("lang")).data() << std::endl;
0152             } else {
0153                 std::cout << "Could not set localization to:" << parser.value(QStringLiteral("lang")).data() << std::endl;
0154                 std::cout << "Exiting...\n";
0155                 return 1;
0156             }
0157         } else {
0158             Translator::instance()->setLanguage();
0159             std::cout << "Using the default (en_US) localization." << std::endl;
0160         }
0161 
0162         QString localizedScript;
0163         localizedScript = Translator::instance()->localizeScript(in.readAll());
0164 
0165 // /*       if (parser.isSet("tokenize")) {
0166 //          std::cout << "Tokenizing...\n" << std::endl;
0167 //          QString code = inputFile.readAll();
0168 // //           for (int i = 0; i < code.length(); i++) //qDebug() << code.at(i);
0169 //          Tokenizer tokenizer;
0170 //          tokenizer.initialize(code);
0171 //          Token* t;
0172 //          while ((t = tokenizer.getToken())->type() != Token::EndOfInput) {
0173 //              std::cout << "TOK> "
0174 //                        << qPrintable(QString("\"%1\"").arg(t->look()).leftJustified(15))
0175 //                        << qPrintable(QString("[%1]").arg(QString::number(t->type())).rightJustified(5))
0176 //                        << qPrintable(QString(" @ (%1,%2)").arg(t->startRow()).arg(t->startCol()))
0177 //                        << qPrintable(QString(" - (%1,%2)").arg(t->endRow()).arg(t->endCol()))
0178 //                        << std::endl;
0179 //          }
0180 //          return 0;
0181 //      }*/
0182 
0183           // free some memory
0184 
0185         // init the interpreter
0186         Interpreter* interpreter = new Interpreter(nullptr, true);  // set testing to true
0187         interpreter->initialize(localizedScript);
0188 
0189         // install the echoer
0190         (new Echoer())->connectAllSlots(interpreter->getExecuter());
0191 
0192         // the actual execution (limited to a certain amount of iterations to break endless loops)
0193         static const int MAX_ITERATION_STEPS = 20000;
0194         int i;
0195         for (i = 0;
0196              interpreter->state() != Interpreter::Finished &&
0197              interpreter->state() != Interpreter::Aborted  &&
0198              interpreter->getErrorList()->isEmpty() &&
0199              i < MAX_ITERATION_STEPS;
0200              i++)
0201             interpreter->interpret();
0202 
0203         if (i == MAX_ITERATION_STEPS)
0204             std::cout << "ERR> Iterated more than " << MAX_ITERATION_STEPS << " steps... Execution terminated." << std::endl;
0205 
0206     }
0207 
0208     return 0;
0209 }