File indexing completed on 2025-04-20 05:11:08
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 "processchain.h" 0012 #include "asmparser.h" 0013 #include "docmanager.h" 0014 #include "gplib.h" 0015 #include "ktechlab.h" 0016 #include "language.h" 0017 #include "languagemanager.h" 0018 #include "logview.h" 0019 #include "outputmethoddlg.h" 0020 #include "projectmanager.h" 0021 #include "textdocument.h" 0022 0023 #include "flowcode.h" 0024 #include "gpasm.h" 0025 #include "gpdasm.h" 0026 #include "gplink.h" 0027 #include "microbe.h" 0028 #include "picprogrammer.h" 0029 #include "sdcc.h" 0030 0031 #include <KLocalizedString> 0032 0033 #include <QDir> 0034 #include <QFile> 0035 #include <QTemporaryFile> 0036 #include <QTimer> 0037 0038 #include <ktlconfig.h> 0039 #include <ktechlab_debug.h> 0040 0041 // BEGIN class ProcessChain 0042 ProcessChain::ProcessChain(ProcessOptions options) 0043 : QObject(KTechlab::self()) 0044 { 0045 m_pFlowCode = nullptr; 0046 m_pGpasm = nullptr; 0047 m_pGpdasm = nullptr; 0048 m_pGplib = nullptr; 0049 m_pGplink = nullptr; 0050 m_pMicrobe = nullptr; 0051 m_pPicProgrammer = nullptr; 0052 m_pSDCC = nullptr; 0053 m_processOptions = options; 0054 0055 QString target; 0056 if (ProcessOptions::ProcessPath::to(options.processPath()) == ProcessOptions::ProcessPath::Pic) 0057 target = options.m_picID; 0058 else 0059 target = options.targetFile(); 0060 0061 LanguageManager::self()->logView()->addOutput(i18n("Building: %1", target), LogView::ot_important); 0062 QTimer::singleShot(0, this, SLOT(compile())); 0063 } 0064 0065 ProcessChain::~ProcessChain() 0066 { 0067 delete m_pFlowCode; 0068 delete m_pGpasm; 0069 delete m_pGpdasm; 0070 delete m_pGplib; 0071 delete m_pGplink; 0072 delete m_pMicrobe; 0073 delete m_pPicProgrammer; 0074 delete m_pSDCC; 0075 } 0076 0077 // void ProcessChain::compile( ProcessOptions * options ) 0078 void ProcessChain::compile() 0079 { 0080 // If the micro id in the options is empty, then attempt to get it from any 0081 // open project (it might not be necessarily...but won't hurt if it isn't). 0082 if (m_processOptions.m_picID.isEmpty()) { 0083 if (ProjectInfo *projectInfo = ProjectManager::self()->currentProject()) { 0084 ProjectItem *projectItem = projectInfo->findItem(QUrl::fromLocalFile(m_processOptions.inputFiles().first())); 0085 if (projectItem) 0086 m_processOptions.m_picID = projectItem->microID(); 0087 } 0088 } 0089 0090 switch (m_processOptions.processPath()) { 0091 #define DIRECT_PROCESS(path, processor) \ 0092 case ProcessOptions::ProcessPath::path: { \ 0093 processor()->processInput(m_processOptions); \ 0094 break; \ 0095 } 0096 #define INDIRECT_PROCESS(path, processor, extension) \ 0097 case ProcessOptions::ProcessPath::path: { \ 0098 QTemporaryFile *f = new QTemporaryFile(QDir::tempPath() + QLatin1String("/ktechlab_XXXXXX") + QLatin1String(extension), processor()); \ 0099 f->open(); \ 0100 f->close(); \ 0101 m_processOptions.setIntermediaryOutput(f->fileName()); \ 0102 processor()->processInput(m_processOptions); \ 0103 break; \ 0104 } 0105 0106 INDIRECT_PROCESS(AssemblyAbsolute_PIC, gpasm, ".hex") 0107 DIRECT_PROCESS(AssemblyAbsolute_Program, gpasm) 0108 INDIRECT_PROCESS(AssemblyRelocatable_Library, gpasm, ".o") 0109 DIRECT_PROCESS(AssemblyRelocatable_Object, gpasm) 0110 INDIRECT_PROCESS(AssemblyRelocatable_PIC, gpasm, ".o") 0111 INDIRECT_PROCESS(AssemblyRelocatable_Program, gpasm, ".o") 0112 DIRECT_PROCESS(C_AssemblyRelocatable, sdcc) 0113 INDIRECT_PROCESS(C_Library, sdcc, ".asm") 0114 INDIRECT_PROCESS(C_Object, sdcc, ".asm") 0115 INDIRECT_PROCESS(C_PIC, sdcc, ".asm") 0116 INDIRECT_PROCESS(C_Program, sdcc, ".asm") 0117 INDIRECT_PROCESS(FlowCode_AssemblyAbsolute, flowCode, ".microbe") 0118 DIRECT_PROCESS(FlowCode_Microbe, flowCode) 0119 INDIRECT_PROCESS(FlowCode_PIC, flowCode, ".microbe") 0120 INDIRECT_PROCESS(FlowCode_Program, flowCode, ".microbe") 0121 DIRECT_PROCESS(Microbe_AssemblyAbsolute, microbe) 0122 INDIRECT_PROCESS(Microbe_PIC, microbe, ".asm") 0123 INDIRECT_PROCESS(Microbe_Program, microbe, ".asm") 0124 DIRECT_PROCESS(Object_Disassembly, gpdasm) 0125 DIRECT_PROCESS(Object_Library, gplib) 0126 INDIRECT_PROCESS(Object_PIC, gplink, ".lib") 0127 DIRECT_PROCESS(Object_Program, gplink) 0128 DIRECT_PROCESS(PIC_AssemblyAbsolute, picProgrammer) 0129 DIRECT_PROCESS(Program_Disassembly, gpdasm) 0130 DIRECT_PROCESS(Program_PIC, picProgrammer) 0131 #undef DIRECT_PROCESS 0132 #undef INDIRECT_PROCESS 0133 0134 case ProcessOptions::ProcessPath::Invalid: 0135 qCWarning(KTL_LOG) << "Process path is invalid"; 0136 qCWarning(KTL_LOG) << "Nothing to do"; 0137 break; 0138 case ProcessOptions::ProcessPath::None: 0139 qCWarning(KTL_LOG) << "Nothing to do"; 0140 break; 0141 } 0142 } 0143 0144 void ProcessChain::slotFinishedCompile(Language *language) 0145 { 0146 ProcessOptions options = language->processOptions(); 0147 0148 if (options.b_addToProject && ProjectManager::self()->currentProject()) 0149 ProjectManager::self()->currentProject()->addFile(QUrl::fromLocalFile(options.targetFile())); 0150 0151 ProcessOptions::ProcessPath::MediaType typeTo = ProcessOptions::ProcessPath::to(m_processOptions.processPath()); 0152 0153 TextDocument *editor = nullptr; 0154 if (KTLConfig::reuseSameViewForOutput()) { 0155 editor = options.textOutputTarget(); 0156 if (editor && (!editor->url().isEmpty() || editor->isModified())) 0157 editor = nullptr; 0158 } 0159 0160 switch (typeTo) { 0161 case ProcessOptions::ProcessPath::AssemblyAbsolute: 0162 case ProcessOptions::ProcessPath::AssemblyRelocatable: 0163 case ProcessOptions::ProcessPath::C: 0164 case ProcessOptions::ProcessPath::Disassembly: 0165 case ProcessOptions::ProcessPath::Library: 0166 case ProcessOptions::ProcessPath::Microbe: 0167 case ProcessOptions::ProcessPath::Object: 0168 case ProcessOptions::ProcessPath::Program: { 0169 switch (options.method()) { 0170 case ProcessOptions::Method::LoadAsNew: { 0171 if (!editor) 0172 editor = DocManager::self()->createTextDocument(); 0173 0174 if (!editor) 0175 break; 0176 0177 QString text; 0178 QFile f(options.targetFile()); 0179 if (!f.open(QIODevice::ReadOnly)) { 0180 editor->deleteLater(); 0181 editor = nullptr; 0182 break; 0183 } 0184 0185 QTextStream stream(&f); 0186 0187 while (!stream.atEnd()) 0188 text += stream.readLine() + '\n'; 0189 0190 f.close(); 0191 0192 editor->setText(text, true); 0193 break; 0194 } 0195 0196 case ProcessOptions::Method::Load: { 0197 editor = dynamic_cast<TextDocument *>(DocManager::self()->openURL(QUrl::fromLocalFile(options.targetFile()))); 0198 break; 0199 } 0200 0201 case ProcessOptions::Method::Forget: 0202 break; 0203 } 0204 } 0205 0206 case ProcessOptions::ProcessPath::FlowCode: 0207 case ProcessOptions::ProcessPath::Pic: 0208 case ProcessOptions::ProcessPath::Unknown: 0209 break; 0210 } 0211 0212 if (editor) { 0213 switch (typeTo) { 0214 case ProcessOptions::ProcessPath::AssemblyAbsolute: 0215 case ProcessOptions::ProcessPath::AssemblyRelocatable: { 0216 if (KTLConfig::autoFormatMBOutput()) 0217 editor->formatAssembly(); 0218 editor->slotInitLanguage(TextDocument::ct_asm); 0219 break; 0220 } 0221 0222 case ProcessOptions::ProcessPath::C: 0223 editor->slotInitLanguage(TextDocument::ct_c); 0224 break; 0225 0226 case ProcessOptions::ProcessPath::Disassembly: 0227 break; 0228 0229 case ProcessOptions::ProcessPath::Library: 0230 case ProcessOptions::ProcessPath::Object: 0231 case ProcessOptions::ProcessPath::Program: 0232 editor->slotInitLanguage(TextDocument::ct_hex); 0233 break; 0234 0235 case ProcessOptions::ProcessPath::Microbe: 0236 editor->slotInitLanguage(TextDocument::ct_microbe); 0237 break; 0238 0239 case ProcessOptions::ProcessPath::FlowCode: 0240 case ProcessOptions::ProcessPath::Pic: 0241 case ProcessOptions::ProcessPath::Unknown: 0242 break; 0243 } 0244 0245 DocManager::self()->giveDocumentFocus(editor); 0246 } 0247 0248 options.setTextOutputtedTo(editor); 0249 0250 emit successful(options); 0251 emit successful(); 0252 } 0253 0254 #define LanguageFunction(a, b, c) \ 0255 a *ProcessChain::b() \ 0256 { \ 0257 if (!c) { \ 0258 c = new a(this); \ 0259 connect(c, SIGNAL(processSucceeded(Language *)), this, SLOT(slotFinishedCompile(Language *))); \ 0260 connect(c, SIGNAL(processFailed(Language *)), this, SIGNAL(failed())); \ 0261 } \ 0262 return c; \ 0263 } 0264 0265 LanguageFunction(FlowCode, flowCode, m_pFlowCode) LanguageFunction(Gpasm, gpasm, m_pGpasm) LanguageFunction(Gpdasm, gpdasm, m_pGpdasm) LanguageFunction(Gplib, gplib, m_pGplib) LanguageFunction(Gplink, gplink, m_pGplink) 0266 LanguageFunction(Microbe, microbe, m_pMicrobe) LanguageFunction(PicProgrammer, picProgrammer, m_pPicProgrammer) LanguageFunction(SDCC, sdcc, m_pSDCC) 0267 // END class ProcessChain 0268 0269 // BEGIN class ProcessListChain 0270 ProcessListChain::ProcessListChain(ProcessOptionsList pol) 0271 : QObject(KTechlab::self()) 0272 { 0273 m_processOptionsList = pol; 0274 0275 // Start us off... 0276 slotProcessChainSuccessful(); 0277 } 0278 0279 void ProcessListChain::slotProcessChainSuccessful() 0280 { 0281 if (m_processOptionsList.isEmpty()) { 0282 emit successful(); 0283 return; 0284 } 0285 0286 ProcessOptionsList::iterator it = m_processOptionsList.begin(); 0287 ProcessOptions po = *it; 0288 m_processOptionsList.erase(it); 0289 0290 ProcessChain *pc = LanguageManager::self()->compile(po); 0291 0292 connect(pc, SIGNAL(successful()), this, SLOT(slotProcessChainSuccessful())); 0293 connect(pc, SIGNAL(failed()), this, SLOT(slotProcessChainFailed())); 0294 } 0295 0296 void ProcessListChain::slotProcessChainFailed() 0297 { 0298 emit failed(); 0299 } 0300 // END class ProcessListChain 0301 0302 #include "moc_processchain.cpp"