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 "gplink.h"
0012 #include "languagemanager.h"
0013 #include "logview.h"
0014 #include "microinfo.h"
0015 #include "microlibrary.h"
0016 
0017 #include <KLocalizedString>
0018 #include <KMessageBox>
0019 #include <KProcess>
0020 
0021 #include <QDir>
0022 #include <QFile>
0023 
0024 #include <ktlconfig.h>
0025 #include <ktechlab_debug.h>
0026 
0027 Gplink::Gplink(ProcessChain *processChain)
0028     : ExternalLanguage(processChain, "Gpasm")
0029 {
0030     m_successfulMessage = i18n("*** Linking successful ***");
0031     m_failedMessage = i18n("*** Linking failed ***");
0032 
0033     // search for SDCC
0034 
0035     m_sdccLibDir = "";
0036 #define SEARCH_FOR_SDCC(dir)                                                                                                                                                                                                                   \
0037     {                                                                                                                                                                                                                                          \
0038         if (m_sdccLibDir.isEmpty()) {                                                                                                                                                                                                          \
0039             QFile f(dir);                                                                                                                                                                                                                      \
0040             qCDebug(KTL_LOG) << " SDCC lib testing " << dir;                                                                                                                                                                            \
0041             if (f.exists()) {                                                                                                                                                                                                                  \
0042                 qCDebug(KTL_LOG) << " SDCC lib found " << dir;                                                                                                                                                                          \
0043                 m_sdccLibDir = dir;                                                                                                                                                                                                            \
0044             }                                                                                                                                                                                                                                  \
0045         }                                                                                                                                                                                                                                      \
0046     }
0047 
0048     // consider adding more paths here, if necessary
0049     if (!KTLConfig::sDCC_install_prefix().isEmpty()) {
0050         SEARCH_FOR_SDCC(KTLConfig::sDCC_install_prefix().append("/share/sdcc/lib"));
0051     }
0052     SEARCH_FOR_SDCC("/usr/local/share/sdcc/lib")
0053     SEARCH_FOR_SDCC("/usr/share/sdcc/lib")
0054     SEARCH_FOR_SDCC("/usr/sdcc/lib")
0055     SEARCH_FOR_SDCC("/usr/sdcc/share/lib")
0056     SEARCH_FOR_SDCC("/opt/sdcc/lib")
0057     SEARCH_FOR_SDCC("/opt/sdcc/share/lib")
0058     SEARCH_FOR_SDCC(QDir::homePath() + "/share/sdcc/lib");
0059 #undef SEARCH_FOR_SDCC
0060     if (m_sdccLibDir == "") {
0061         qCWarning(KTL_LOG) << "SDCC lib not found. Expect linking errors";
0062     }
0063     {
0064         QFile f(m_sdccLibDir + "/../non-free/lib");
0065         if (!f.exists()) {
0066             qCWarning(KTL_LOG) << "SDCC non-free lib not found. Expect linking errors";
0067         }
0068     }
0069 }
0070 
0071 Gplink::~Gplink()
0072 {
0073 }
0074 
0075 void Gplink::processInput(ProcessOptions options)
0076 {
0077     resetLanguageProcess();
0078     m_processOptions = options;
0079 
0080     *m_languageProcess << ("gplink");
0081 
0082     // note: needed for newer GPUtils: relocate to shared memory if necessary
0083     *m_languageProcess << ("--use-shared");
0084 
0085     if (!options.m_hexFormat.isEmpty()) {
0086         *m_languageProcess << ("--hex-format");
0087         *m_languageProcess << (options.m_hexFormat);
0088     }
0089 
0090     if (options.m_bOutputMapFile)
0091         *m_languageProcess << ("--map");
0092 
0093     if (!options.m_libraryDir.isEmpty()) {
0094         *m_languageProcess << ("--include");
0095         *m_languageProcess << (options.m_libraryDir);
0096     }
0097 
0098     if (!options.m_linkerScript.isEmpty()) {
0099         *m_languageProcess << ("--script");
0100         *m_languageProcess << (options.m_linkerScript);
0101     }
0102 
0103     if (!options.m_linkOther.isEmpty())
0104         *m_languageProcess << (options.m_linkOther);
0105 
0106     // Output hex file
0107     *m_languageProcess << ("--output");
0108     *m_languageProcess << (options.intermediaryOutput());
0109 
0110     // Input object file
0111     const QStringList inputFiles = options.inputFiles();
0112     QStringList::const_iterator end = inputFiles.end();
0113     for (QStringList::const_iterator it = inputFiles.begin(); it != end; ++it)
0114         *m_languageProcess << (*it);
0115 
0116     // Other libraries
0117     end = options.m_linkLibraries.end();
0118     for (QStringList::const_iterator it = options.m_linkLibraries.begin(); it != end; ++it)
0119         *m_languageProcess << (*it);
0120 
0121     // if selected to automatically link to SDCC libraries, add some options.
0122     if (KTLConfig::gplink_link_shared()) {
0123         // set up the include directory
0124         MicroInfo *info = MicroLibrary::self()->microInfoWithID(options.m_picID);
0125         if (!info) {
0126             // be program won't link anyway, but the user can't say that the program didn't try
0127             qCCritical(KTL_LOG) << "Couldn't find the requested PIC" << options.m_picID;
0128             qCWarning(KTL_LOG) << "Supposing that the pic is pic12 or pic14";
0129             *m_languageProcess << "-I" << m_sdccLibDir + "/pic";
0130         } else {
0131             QString picLibSubdir;
0132             switch (info->instructionSet()->set()) {
0133             // note: is PIC12 supported by SDCC?
0134             case AsmInfo::PIC12:
0135                 picLibSubdir = "pic12";
0136                 break;
0137             case AsmInfo::PIC14:
0138                 picLibSubdir = "pic14";
0139                 break;
0140             case AsmInfo::PIC16:
0141                 picLibSubdir = "pic16";
0142                 break;
0143             default:
0144                 qCWarning(KTL_LOG) << "Inexpected instruction set: " << int(info->instructionSet()->set());
0145                 break;
0146             }
0147             *m_languageProcess << "-I" << m_sdccLibDir + "/" + picLibSubdir;
0148             // non-free libraries are needed; beware the Debian/Ubuntu/derivatives' packages
0149             *m_languageProcess << "-I" << m_sdccLibDir + "/../non-free/lib/" + picLibSubdir;
0150             // to pic to link against
0151             *m_languageProcess << options.m_picID.toLower().replace("p", "pic") + ".lib";
0152         }
0153         *m_languageProcess << "libsdcc.lib";
0154     }
0155 
0156     if (!start()) {
0157         KMessageBox::error(LanguageManager::self()->logView(), i18n("Linking failed. Please check you have gputils installed."));
0158         processInitFailed();
0159         return;
0160     }
0161 }
0162 
0163 bool Gplink::isError(const QString &message) const
0164 {
0165     return message.contains("Error", Qt::CaseInsensitive);
0166 }
0167 
0168 bool Gplink::isWarning(const QString &message) const
0169 {
0170     return message.contains("Warning", Qt::CaseInsensitive);
0171 }
0172 
0173 MessageInfo Gplink::extractMessageInfo(const QString &text)
0174 {
0175     if (text.length() < 5 || !text.startsWith("/"))
0176         return MessageInfo();
0177 #if 0   
0178     const int index = text.indexOf( ".asm", 0, Qt::CaseInsensitive )+4;
0179     if ( index == -1+4 )
0180         return MessageInfo();
0181     const QString fileName = text.left(index);
0182     
0183     // Extra line number
0184     const QString message = text.right(text.length()-index);
0185     const int linePos = message.indexOf( QRegExp(":[\\d]+") );
0186     int line = -1;
0187     if ( linePos != -1 )
0188     {
0189         const int linePosEnd = message.indexOf( ':', linePos+1 );
0190         if ( linePosEnd != -1 )
0191         {
0192             const QString number = message.mid( linePos+1, linePosEnd-linePos-1 ).trimmed();
0193             bool ok;
0194             line = number.toInt(&ok)-1;
0195             if (!ok) line = -1;
0196         }
0197     }
0198     return MessageInfo( fileName, line );
0199 #endif
0200     return MessageInfo();
0201 }
0202 
0203 ProcessOptions::ProcessPath::Path Gplink::outputPath(ProcessOptions::ProcessPath::Path inputPath) const
0204 {
0205     switch (inputPath) {
0206     case ProcessOptions::ProcessPath::Object_PIC:
0207         return ProcessOptions::ProcessPath::Program_PIC;
0208 
0209     case ProcessOptions::ProcessPath::Object_Program:
0210         return ProcessOptions::ProcessPath::None;
0211 
0212     case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
0213     case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
0214     case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
0215     case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
0216     case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
0217     case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
0218     case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
0219     case ProcessOptions::ProcessPath::C_Library:
0220     case ProcessOptions::ProcessPath::C_Object:
0221     case ProcessOptions::ProcessPath::C_PIC:
0222     case ProcessOptions::ProcessPath::C_Program:
0223     case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
0224     case ProcessOptions::ProcessPath::FlowCode_Microbe:
0225     case ProcessOptions::ProcessPath::FlowCode_PIC:
0226     case ProcessOptions::ProcessPath::FlowCode_Program:
0227     case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
0228     case ProcessOptions::ProcessPath::Microbe_PIC:
0229     case ProcessOptions::ProcessPath::Microbe_Program:
0230     case ProcessOptions::ProcessPath::Object_Disassembly:
0231     case ProcessOptions::ProcessPath::Object_Library:
0232     case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
0233     case ProcessOptions::ProcessPath::Program_Disassembly:
0234     case ProcessOptions::ProcessPath::Program_PIC:
0235     case ProcessOptions::ProcessPath::Invalid:
0236     case ProcessOptions::ProcessPath::None:
0237         return ProcessOptions::ProcessPath::Invalid;
0238     }
0239 
0240     return ProcessOptions::ProcessPath::Invalid;
0241 }