File indexing completed on 2024-04-21 03:45:28

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