File indexing completed on 2024-06-16 08:27:29

0001 /***************************************************************************
0002  *   Copyright (C) 2005 by David Saxton                                    *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #include "language.h"
0012 #include "asmparser.h"
0013 #include "ktechlab.h"
0014 #include "languagemanager.h"
0015 #include "logview.h"
0016 #include "outputmethoddlg.h"
0017 #include "processchain.h"
0018 #include "projectmanager.h"
0019 
0020 //#include <kio/netaccess.h>
0021 #include <KMessageBox>
0022 #include <KProcess>
0023 
0024 #include <QRegExp>
0025 #include <QTimer>
0026 
0027 #include <ktlconfig.h>
0028 #include <ktechlab_debug.h>
0029 
0030 // BEGIN class Language
0031 Language::Language(ProcessChain *processChain, const QString &name)
0032     : QObject(KTechlab::self() /*, name */)
0033 {
0034     setObjectName(name);
0035     p_processChain = processChain;
0036 }
0037 
0038 Language::~Language()
0039 {
0040 }
0041 
0042 void Language::outputMessage(const QString &message)
0043 {
0044     LanguageManager::self()->slotMessage(message, extractMessageInfo(message));
0045 }
0046 
0047 void Language::outputWarning(const QString &message)
0048 {
0049     LanguageManager::self()->slotWarning(message, extractMessageInfo(message));
0050 }
0051 
0052 void Language::outputError(const QString &message)
0053 {
0054     LanguageManager::self()->slotError(message, extractMessageInfo(message));
0055     m_errorCount++;
0056 }
0057 
0058 void Language::finish(bool successful)
0059 {
0060     if (successful) {
0061         outputMessage(m_successfulMessage + "\n");
0062         KTechlab::self()->slotChangeStatusbar(m_successfulMessage);
0063 
0064         ProcessOptions::ProcessPath::Path newPath = outputPath(m_processOptions.processPath());
0065 
0066         if (newPath == ProcessOptions::ProcessPath::None)
0067             emit processSucceeded(this);
0068 
0069         else if (p_processChain) {
0070             m_processOptions.setInputFiles(QStringList(m_processOptions.intermediaryOutput()));
0071             m_processOptions.setIntermediaryOutput(m_processOptions.targetFile());
0072             m_processOptions.setProcessPath(newPath);
0073             //          p_processChain->compile(m_processOptions);
0074             p_processChain->setProcessOptions(m_processOptions);
0075             p_processChain->compile();
0076         }
0077     } else {
0078         outputError(m_failedMessage + "\n");
0079         KTechlab::self()->slotChangeStatusbar(m_failedMessage);
0080         emit processFailed(this);
0081         return;
0082     }
0083 }
0084 
0085 void Language::reset()
0086 {
0087     m_errorCount = 0;
0088 }
0089 
0090 MessageInfo Language::extractMessageInfo(const QString &text)
0091 {
0092     if (!text.startsWith("/"))
0093         return MessageInfo();
0094 
0095     const int index = text.indexOf(":", 0, Qt::CaseInsensitive);
0096     if (index == -1)
0097         return MessageInfo();
0098     const QString fileName = text.left(index);
0099 
0100     // Extra line number
0101     const QString message = text.right(text.length() - index);
0102     const int linePos = message.indexOf(QRegExp(":[\\d]+"));
0103     int line = -1;
0104     if (linePos != -1) {
0105         const int linePosEnd = message.indexOf(':', linePos + 1);
0106         if (linePosEnd != -1) {
0107             const QString number = message.mid(linePos + 1, linePosEnd - linePos - 1).trimmed();
0108             bool ok;
0109             line = number.toInt(&ok) - 1;
0110             if (!ok)
0111                 line = -1;
0112         }
0113     }
0114     return MessageInfo(fileName, line);
0115 }
0116 // END class Language
0117 
0118 // BEGIN class ProcessOptionsSpecial
0119 ProcessOptionsSpecial::ProcessOptionsSpecial()
0120 {
0121     m_bOutputMapFile = true;
0122     b_forceList = true;
0123     b_addToProject = ProjectManager::self()->currentProject();
0124 
0125     p_flowCodeDocument = nullptr;
0126 
0127     switch (KTLConfig::hexFormat()) {
0128     case KTLConfig::EnumHexFormat::inhx8m:
0129         m_hexFormat = "inhx8m";
0130         break;
0131 
0132     case KTLConfig::EnumHexFormat::inhx8s:
0133         m_hexFormat = "inhx8s";
0134         break;
0135 
0136     case KTLConfig::EnumHexFormat::inhx16:
0137         m_hexFormat = "inhx16";
0138         break;
0139 
0140     case KTLConfig::EnumHexFormat::inhx32:
0141     default:
0142         m_hexFormat = "inhx32";
0143         break;
0144     }
0145 }
0146 // END class ProcessOptionsSpecial
0147 
0148 // BEGIN class ProcessOptions
0149 ProcessOptions::ProcessOptions()
0150 {
0151     m_pHelper = new ProcessOptionsHelper;
0152 
0153     b_targetFileSet = false;
0154     m_pTextOutputTarget = nullptr;
0155 }
0156 
0157 ProcessOptions::ProcessOptions(OutputMethodInfo info)
0158 {
0159     m_pHelper = new ProcessOptionsHelper;
0160 
0161     b_addToProject = info.addToProject();
0162     m_picID = info.picID();
0163     b_targetFileSet = false;
0164 
0165     setTargetFile(info.outputFile().toLocalFile());
0166 
0167     switch (info.method()) {
0168     case OutputMethodInfo::Method::Direct:
0169         m_method = Method::LoadAsNew;
0170         break;
0171 
0172     case OutputMethodInfo::Method::SaveAndForget:
0173         m_method = Method::Forget;
0174         break;
0175 
0176     case OutputMethodInfo::Method::SaveAndLoad:
0177         m_method = Method::Load;
0178         break;
0179     }
0180 }
0181 
0182 void ProcessOptions::setTextOutputTarget(TextDocument *target, QObject *receiver, const char *slot)
0183 {
0184     m_pTextOutputTarget = target;
0185     QObject::connect(m_pHelper, SIGNAL(textOutputtedTo(TextDocument *)), receiver, slot);
0186 }
0187 
0188 void ProcessOptions::setTextOutputtedTo(TextDocument *outputtedTo)
0189 {
0190     m_pTextOutputTarget = outputtedTo;
0191     emit m_pHelper->textOutputtedTo(m_pTextOutputTarget);
0192 }
0193 
0194 void ProcessOptions::setTargetFile(const QString &file)
0195 {
0196     if (b_targetFileSet) {
0197         qCWarning(KTL_LOG) << "Trying to reset target file!";
0198         return;
0199     }
0200     m_targetFile = file;
0201     m_intermediaryFile = file;
0202     b_targetFileSet = true;
0203 }
0204 
0205 ProcessOptions::ProcessPath::MediaType ProcessOptions::guessMediaType(const QString &url)
0206 {
0207     QString extension = url.right(url.length() - url.lastIndexOf('.') - 1);
0208     extension = extension.toLower();
0209 
0210     if (extension == "asm") {
0211         // We'll have to look at the file contents to determine its type...
0212         AsmParser p(url);
0213         p.parse();
0214         switch (p.type()) {
0215         case AsmParser::Relocatable:
0216             return ProcessPath::AssemblyRelocatable;
0217 
0218         case AsmParser::Absolute:
0219             return ProcessPath::AssemblyAbsolute;
0220         }
0221     }
0222 
0223     if (extension == "c")
0224         return ProcessPath::C;
0225 
0226     if (extension == "flowcode")
0227         return ProcessPath::FlowCode;
0228 
0229     if (extension == "a" || extension == "lib")
0230         return ProcessPath::Library;
0231 
0232     if (extension == "microbe" || extension == "basic")
0233         return ProcessPath::Microbe;
0234 
0235     if (extension == "o")
0236         return ProcessPath::Object;
0237 
0238     if (extension == "hex")
0239         return ProcessPath::Program;
0240 
0241     return ProcessPath::Unknown;
0242 }
0243 
0244 ProcessOptions::ProcessPath::Path ProcessOptions::ProcessPath::path(MediaType from, MediaType to)
0245 {
0246     switch (from) {
0247     case AssemblyAbsolute:
0248         switch (to) {
0249         case AssemblyAbsolute:
0250             return None;
0251         case Pic:
0252             return AssemblyAbsolute_PIC;
0253         case Program:
0254             return AssemblyAbsolute_Program;
0255 
0256         case AssemblyRelocatable:
0257         case C:
0258         case Disassembly:
0259         case FlowCode:
0260         case Library:
0261         case Microbe:
0262         case Object:
0263         case Unknown:
0264         default:
0265             return Invalid;
0266         }
0267 
0268     case AssemblyRelocatable:
0269         switch (to) {
0270         case Library:
0271             return AssemblyRelocatable_Library;
0272         case Object:
0273             return AssemblyRelocatable_Object;
0274         case Pic:
0275             return AssemblyRelocatable_PIC;
0276         case Program:
0277             return AssemblyRelocatable_Program;
0278 
0279         case AssemblyAbsolute:
0280         case AssemblyRelocatable:
0281         case C:
0282         case Disassembly:
0283         case FlowCode:
0284         case Microbe:
0285         case Unknown:
0286         default:
0287             return Invalid;
0288         }
0289 
0290     case C:
0291         switch (to) {
0292         case AssemblyRelocatable:
0293             return C_AssemblyRelocatable;
0294         case Library:
0295             return C_Library;
0296         case Object:
0297             return C_Object;
0298         case Pic:
0299             return C_PIC;
0300         case Program:
0301             return C_Program;
0302 
0303         case AssemblyAbsolute:
0304         case C:
0305         case Disassembly:
0306         case FlowCode:
0307         case Microbe:
0308         case Unknown:
0309         default:
0310             return Invalid;
0311         }
0312 
0313     case Disassembly:
0314         return Invalid;
0315 
0316     case FlowCode:
0317         switch (to) {
0318         case AssemblyAbsolute:
0319             return FlowCode_AssemblyAbsolute;
0320         case Microbe:
0321             return FlowCode_Microbe;
0322         case Pic:
0323             return FlowCode_PIC;
0324         case Program:
0325             return FlowCode_Program;
0326 
0327         case AssemblyRelocatable:
0328         case C:
0329         case Disassembly:
0330         case FlowCode:
0331         case Library:
0332         case Object:
0333         case Unknown:
0334         default:
0335             return Invalid;
0336         }
0337 
0338     case Library:
0339         return Invalid;
0340 
0341     case Microbe:
0342         switch (to) {
0343         case AssemblyAbsolute:
0344             return Microbe_AssemblyAbsolute;
0345         case Pic:
0346             return Microbe_PIC;
0347         case Program:
0348             return Microbe_Program;
0349 
0350         case AssemblyRelocatable:
0351         case C:
0352         case Disassembly:
0353         case FlowCode:
0354         case Library:
0355         case Microbe:
0356         case Object:
0357         case Unknown:
0358         default:
0359             return Invalid;
0360         }
0361 
0362     case Object:
0363         switch (to) {
0364         case Disassembly:
0365             return Object_Disassembly;
0366         case Library:
0367             return Object_Library;
0368         case Pic:
0369             return Object_PIC;
0370         case Program:
0371             return Object_Program;
0372 
0373         case AssemblyAbsolute:
0374         case AssemblyRelocatable:
0375         case C:
0376         case FlowCode:
0377         case Microbe:
0378         case Object:
0379         case Unknown:
0380         default:
0381             return Invalid;
0382         }
0383 
0384     case Pic:
0385         return Invalid;
0386 
0387     case Program:
0388         switch (to) {
0389         case Disassembly:
0390             return Program_Disassembly;
0391         case Pic:
0392             return Program_PIC;
0393 
0394         case AssemblyAbsolute:
0395         case AssemblyRelocatable:
0396         case C:
0397         case FlowCode:
0398         case Library:
0399         case Microbe:
0400         case Object:
0401         case Program:
0402         case Unknown:
0403         default:
0404             return Invalid;
0405         }
0406 
0407     case Unknown:
0408         return Invalid;
0409     }
0410 
0411     return Invalid;
0412 }
0413 
0414 ProcessOptions::ProcessPath::MediaType ProcessOptions::ProcessPath::from(Path path)
0415 {
0416     switch (path) {
0417     case ProcessPath::AssemblyAbsolute_PIC:
0418     case ProcessPath::AssemblyAbsolute_Program:
0419         return AssemblyAbsolute;
0420 
0421     case ProcessPath::AssemblyRelocatable_Library:
0422     case ProcessPath::AssemblyRelocatable_Object:
0423     case ProcessPath::AssemblyRelocatable_PIC:
0424     case ProcessPath::AssemblyRelocatable_Program:
0425         return AssemblyRelocatable;
0426 
0427     case ProcessPath::C_AssemblyRelocatable:
0428     case ProcessPath::C_Library:
0429     case ProcessPath::C_Object:
0430     case ProcessPath::C_PIC:
0431     case ProcessPath::C_Program:
0432         return C;
0433 
0434     case ProcessPath::FlowCode_AssemblyAbsolute:
0435     case ProcessPath::FlowCode_Microbe:
0436     case ProcessPath::FlowCode_PIC:
0437     case ProcessPath::FlowCode_Program:
0438         return FlowCode;
0439 
0440     case ProcessPath::Microbe_AssemblyAbsolute:
0441     case ProcessPath::Microbe_PIC:
0442     case ProcessPath::Microbe_Program:
0443         return Microbe;
0444 
0445     case ProcessPath::Object_Disassembly:
0446     case ProcessPath::Object_Library:
0447     case ProcessPath::Object_PIC:
0448     case ProcessPath::Object_Program:
0449         return Object;
0450 
0451     case ProcessPath::PIC_AssemblyAbsolute:
0452         return Pic;
0453 
0454     case ProcessPath::Program_Disassembly:
0455     case ProcessPath::Program_PIC:
0456         return Program;
0457 
0458     case ProcessPath::Invalid:
0459     case ProcessPath::None:
0460         return Unknown;
0461     }
0462 
0463     return Unknown;
0464 }
0465 
0466 ProcessOptions::ProcessPath::MediaType ProcessOptions::ProcessPath::to(Path path)
0467 {
0468     switch (path) {
0469     case ProcessPath::FlowCode_AssemblyAbsolute:
0470     case ProcessPath::Microbe_AssemblyAbsolute:
0471     case ProcessPath::PIC_AssemblyAbsolute:
0472         return AssemblyAbsolute;
0473 
0474     case ProcessPath::C_AssemblyRelocatable:
0475         return AssemblyRelocatable;
0476 
0477     case ProcessPath::Object_Disassembly:
0478     case ProcessPath::Program_Disassembly:
0479         return Disassembly;
0480 
0481     case ProcessPath::AssemblyRelocatable_Library:
0482     case ProcessPath::C_Library:
0483     case ProcessPath::Object_Library:
0484         return Library;
0485 
0486     case ProcessPath::FlowCode_Microbe:
0487         return Microbe;
0488 
0489     case ProcessPath::AssemblyRelocatable_Object:
0490     case ProcessPath::C_Object:
0491         return Object;
0492 
0493     case ProcessPath::AssemblyAbsolute_PIC:
0494     case ProcessPath::AssemblyRelocatable_PIC:
0495     case ProcessPath::C_PIC:
0496     case ProcessPath::FlowCode_PIC:
0497     case ProcessPath::Microbe_PIC:
0498     case ProcessPath::Object_PIC:
0499     case ProcessPath::Program_PIC:
0500         return Pic;
0501 
0502     case ProcessPath::AssemblyAbsolute_Program:
0503     case ProcessPath::AssemblyRelocatable_Program:
0504     case ProcessPath::C_Program:
0505     case ProcessPath::FlowCode_Program:
0506     case ProcessPath::Microbe_Program:
0507     case ProcessPath::Object_Program:
0508         return Program;
0509 
0510     case ProcessPath::Invalid:
0511     case ProcessPath::None:
0512         return Unknown;
0513     }
0514 
0515     return Unknown;
0516 }
0517 // END class ProcessOptions
0518 
0519 #include "moc_language.cpp"