summaryrefslogtreecommitdiffstats
path: root/src/languages
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 01:49:02 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 01:49:02 +0000
commit5de3dd4762ca33a0f92e79ffa4fe2ff67069d531 (patch)
treebad482b7afa4cdf47422d60a5dd2c61c7e333b09 /src/languages
downloadktechlab-5de3dd4762ca33a0f92e79ffa4fe2ff67069d531.tar.gz
ktechlab-5de3dd4762ca33a0f92e79ffa4fe2ff67069d531.zip
Added KDE3 version of ktechlab
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/ktechlab@1095338 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/languages')
-rw-r--r--src/languages/Makefile.am14
-rw-r--r--src/languages/asmparser.cpp150
-rw-r--r--src/languages/asmparser.h61
-rw-r--r--src/languages/externallanguage.cpp167
-rw-r--r--src/languages/externallanguage.h97
-rw-r--r--src/languages/flowcode.cpp496
-rw-r--r--src/languages/flowcode.h107
-rw-r--r--src/languages/gpasm.cpp187
-rw-r--r--src/languages/gpasm.h34
-rw-r--r--src/languages/gpdasm.cpp158
-rw-r--r--src/languages/gpdasm.h39
-rw-r--r--src/languages/gplib.cpp139
-rw-r--r--src/languages/gplib.h34
-rw-r--r--src/languages/gplink.cpp174
-rw-r--r--src/languages/gplink.h35
-rw-r--r--src/languages/language.cpp558
-rw-r--r--src/languages/language.h268
-rw-r--r--src/languages/languagemanager.cpp108
-rw-r--r--src/languages/languagemanager.h91
-rw-r--r--src/languages/microbe.cpp136
-rw-r--r--src/languages/microbe.h40
-rw-r--r--src/languages/picprogrammer.cpp456
-rw-r--r--src/languages/picprogrammer.h127
-rw-r--r--src/languages/processchain.cpp326
-rw-r--r--src/languages/processchain.h127
-rw-r--r--src/languages/sdcc.cpp205
-rw-r--r--src/languages/sdcc.h34
-rw-r--r--src/languages/sourceline.cpp42
-rw-r--r--src/languages/sourceline.h42
29 files changed, 4452 insertions, 0 deletions
diff --git a/src/languages/Makefile.am b/src/languages/Makefile.am
new file mode 100644
index 0000000..fef84e7
--- /dev/null
+++ b/src/languages/Makefile.am
@@ -0,0 +1,14 @@
+INCLUDES = -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/electronics -I$(top_srcdir)/src/electronics/components \
+ -I$(top_srcdir)/src/electronics/simulation -I$(top_srcdir)/src/flowparts -I$(top_srcdir)/src/gui \
+ -I$(top_srcdir)/src/languages -I$(top_srcdir)/src/mechanics -I$(top_srcdir)/src/micro -Igui \
+ $(all_includes)
+METASOURCES = AUTO
+noinst_LTLIBRARIES = liblanguages.la
+liblanguages_la_SOURCES = language.cpp languagemanager.cpp microbe.cpp \
+ externallanguage.cpp gpasm.cpp gpdasm.cpp processchain.cpp flowcode.cpp asmparser.cpp \
+ sdcc.cpp gplink.cpp gplib.cpp sourceline.cpp picprogrammer.cpp
+noinst_HEADERS = externallanguage.h gpasm.h gpdasm.h language.h \
+ languagemanager.h microbe.h processchain.h flowcode.h asmparser.h sdcc.h gplink.h gplib.h \
+ sourceline.h picprogrammer.h
+liblanguages_la_LIBADD = $(top_builddir)/src/gui/libgui.la
diff --git a/src/languages/asmparser.cpp b/src/languages/asmparser.cpp
new file mode 100644
index 0000000..eb4b7cd
--- /dev/null
+++ b/src/languages/asmparser.cpp
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "asmparser.h"
+#include "config.h"
+#include "gpsimprocessor.h"
+
+#include <kdebug.h>
+#include <qfile.h>
+#include <qregexp.h>
+
+AsmParser::AsmParser( const QString &url )
+ : m_url(url)
+{
+ m_bContainsRadix = false;
+ m_type = Absolute;
+}
+
+
+AsmParser::~AsmParser()
+{
+}
+
+
+bool AsmParser::parse( GpsimDebugger * debugger )
+{
+ QFile file(m_url);
+ if ( !file.open(IO_ReadOnly) )
+ return false;
+
+ QTextStream stream( &file );
+
+ m_type = Absolute;
+ m_bContainsRadix = false;
+ m_picID = QString::null;
+
+ QStringList nonAbsoluteOps = QStringList::split( ",",
+ "code,.def,.dim,.direct,endw,extern,.file,global,idata,.ident,.line,.type,udata,udata_acs,udata_ovr,udata_shr" );
+
+ unsigned inputAtLine = 0;
+ while ( !stream.atEnd() )
+ {
+ const QString line = stream.readLine().stripWhiteSpace();
+ if ( m_type != Relocatable )
+ {
+ QString col0 = line.section( QRegExp("[; ]"), 0, 0 );
+ col0 = col0.stripWhiteSpace();
+ if ( nonAbsoluteOps.contains(col0) )
+ m_type = Relocatable;
+ }
+ if ( !m_bContainsRadix )
+ {
+ if ( line.contains( QRegExp("^RADIX[\\s]*") ) || line.contains( QRegExp("^radix[\\s]*") ) )
+ m_bContainsRadix = true;
+ }
+ if ( m_picID.isEmpty() )
+ {
+ // We look for "list p = ", and "list p = picid ", and subtract the positions / lengths away from each other to get the picid text position
+ QRegExp fullRegExp("[lL][iI][sS][tT][\\s]+[pP][\\s]*=[\\s]*[\\d\\w]+");
+ QRegExp halfRegExp("[lL][iI][sS][tT][\\s]+[pP][\\s]*=[\\s]*");
+
+ int startPos = fullRegExp.search(line);
+ if ( (startPos != -1) && (startPos == halfRegExp.search(line)) )
+ {
+ m_picID = line.mid( startPos + halfRegExp.matchedLength(), fullRegExp.matchedLength() - halfRegExp.matchedLength() );
+ m_picID = m_picID.upper();
+ if ( !m_picID.startsWith("P") )
+ m_picID.prepend("P");
+ }
+ }
+#ifndef NO_GPSIM
+ if ( debugger && line.startsWith(";#CSRC\t") )
+ {
+ // Assembly file produced (by sdcc) from C, line is in format:
+ // ;#CSRC\t[file-name] [file-line]
+ // The filename can contain spaces.
+ int fileLineAt = line.findRev(" ");
+
+ if ( fileLineAt == -1 )
+ kdWarning() << k_funcinfo << "Syntax error in line \"" << line << "\" while looking for file-line" << endl;
+ else
+ {
+ // 7 = length_of(";#CSRC\t")
+ QString fileName = line.mid( 7, fileLineAt-7 );
+ QString fileLineString = line.mid( fileLineAt+1, line.length() - fileLineAt - 1 );
+
+ if ( fileName.startsWith("\"") )
+ {
+ // Newer versions of SDCC insert " around the filename
+ fileName.remove( 0, 1 ); // First "
+ fileName.remove( fileName.length()-1, 1 ); // Last "
+ }
+
+ bool ok;
+ int fileLine = fileLineString.toInt(&ok) - 1;
+ if ( ok && fileLine >= 0 )
+ debugger->associateLine( fileName, fileLine, m_url, inputAtLine );
+ else
+ kdDebug() << k_funcinfo << "Not a valid line number: \"" << fileLineString << "\"" << endl;
+ }
+ }
+ if ( debugger && (line.startsWith(".line\t") || line.startsWith(";#MSRC") ) )
+ {
+ // Assembly file produced by either sdcc or microbe, line is in format:
+ // \t[".line"/"#MSRC"]\t[file-line]; [file-name]\t[c/microbe source code for that line]
+ // We're screwed if the file name contains tabs, but hopefully not many do...
+ QStringList lineParts = QStringList::split( '\t', line );
+ if ( lineParts.size() < 2 )
+ kdWarning() << k_funcinfo << "Line is in wrong format for extracing source line and file: \""<<line<<"\""<<endl;
+ else
+ {
+ const QString lineAndFile = lineParts[1];
+ int lineFileSplit = lineAndFile.find("; ");
+ if ( lineFileSplit == -1 )
+ kdDebug() << k_funcinfo << "Could not find file / line split in \""<<lineAndFile<<"\""<<endl;
+ else
+ {
+ QString fileName = lineAndFile.mid( lineFileSplit + 2 );
+ QString fileLineString = lineAndFile.left( lineFileSplit );
+
+ if ( fileName.startsWith("\"") )
+ {
+ // Newer versions of SDCC insert " around the filename
+ fileName.remove( 0, 1 ); // First "
+ fileName.remove( fileName.length()-1, 1 ); // Last "
+ }
+
+ bool ok;
+ int fileLine = fileLineString.toInt(&ok) - 1;
+ if ( ok && fileLine >= 0 )
+ debugger->associateLine( fileName, fileLine, m_url, inputAtLine );
+ else
+ kdDebug() << k_funcinfo << "Not a valid line number: \"" << fileLineString << "\"" << endl;
+ }
+ }
+ }
+#endif // !NO_GPSIM
+ inputAtLine++;
+ }
+
+ return true;
+}
+
diff --git a/src/languages/asmparser.h b/src/languages/asmparser.h
new file mode 100644
index 0000000..ab21837
--- /dev/null
+++ b/src/languages/asmparser.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef ASMPARSER_H
+#define ASMPARSER_H
+
+#include <qstring.h>
+
+class GpsimDebugger;
+
+/**
+Reads in an assembly file, and extracts useful information from it, such as the
+PIC ID
+
+@author David Saxton
+*/
+class AsmParser
+{
+ public:
+ AsmParser( const QString &url );
+ ~AsmParser();
+
+ enum Type { Relocatable, Absolute };
+
+ /**
+ * Read in data from file, return success status.
+ * @param debugger if this is non-null, then source-line markers read
+ * from the assembly file (such as those beginning with ";#CSRC" will be
+ * passed to hllDebugger).
+ */
+ bool parse( GpsimDebugger * debugger = 0l );
+ /**
+ * Returns the PIC ID
+ */
+ QString picID() const { return m_picID; }
+ /**
+ * Returns whether or not the assembly file contained the "set radix"
+ * directive
+ */
+ bool containsRadix() const { return m_bContainsRadix; }
+ /**
+ * If the assembly file contains any of several key words that identify
+ * it as a relocatable object, then this will return Relocatable.
+ */
+ Type type() const { return m_type; }
+
+ protected:
+ const QString m_url;
+ QString m_picID;
+ bool m_bContainsRadix;
+ Type m_type;
+};
+
+#endif
diff --git a/src/languages/externallanguage.cpp b/src/languages/externallanguage.cpp
new file mode 100644
index 0000000..7297e63
--- /dev/null
+++ b/src/languages/externallanguage.cpp
@@ -0,0 +1,167 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "externallanguage.h"
+#include "languagemanager.h"
+#include "logview.h"
+
+#include <kdebug.h>
+#include <kprocess.h>
+#include <qregexp.h>
+#include <qtimer.h>
+
+ExternalLanguage::ExternalLanguage( ProcessChain *processChain, KTechlab *parent, const QString &name )
+ : Language( processChain, parent, name )
+{
+ m_languageProcess = 0l;
+}
+
+
+ExternalLanguage::~ExternalLanguage()
+{
+ deleteLanguageProcess();
+}
+
+
+void ExternalLanguage::deleteLanguageProcess()
+{
+ if (!m_languageProcess)
+ return;
+
+ // I'm not too sure if this combination of killing the process is the best way....
+// m_languageProcess->tryTerminate();
+// QTimer::singleShot( 5000, m_languageProcess, SLOT( kill() ) );
+// delete m_languageProcess;
+ m_languageProcess->kill();
+ m_languageProcess->deleteLater();
+
+ m_languageProcess = 0L;
+}
+
+
+void ExternalLanguage::receivedStdout( KProcess *, char * buffer, int buflen )
+{
+ QStringList lines = QStringList::split( '\n', QString::fromLocal8Bit( buffer, buflen ), false );
+ QStringList::iterator end = lines.end();
+
+ for ( QStringList::iterator it = lines.begin(); it != end; ++it )
+ {
+ if ( isError( *it ) )
+ {
+ outputError( *it );
+ outputtedError( *it );
+ }
+ else if ( isWarning( *it ) )
+ {
+ outputWarning( *it );
+ outputtedWarning( *it );
+ }
+ else
+ {
+ outputMessage( *it );
+ outputtedMessage( *it );
+ }
+ }
+}
+
+
+void ExternalLanguage::receivedStderr( KProcess *, char * buffer, int buflen )
+{
+ QStringList lines = QStringList::split( '\n', QString::fromLocal8Bit( buffer, buflen ), false );
+ QStringList::iterator end = lines.end();
+
+ for ( QStringList::iterator it = lines.begin(); it != end; ++it )
+ {
+ if ( isStderrOutputFatal( *it ) )
+ {
+ outputError( *it );
+ outputtedError( *it );
+ }
+ else
+ {
+ outputWarning( *it );
+ outputtedWarning( *it );
+ }
+ }
+}
+
+
+void ExternalLanguage::processExited( KProcess * )
+{
+ if ( !m_languageProcess )
+ return;
+ bool allOk = processExited( m_languageProcess->normalExit() && m_errorCount == 0 );
+ finish(allOk);
+ deleteLanguageProcess();
+}
+
+
+void ExternalLanguage::processInitFailed()
+{
+ finish(false);
+ deleteLanguageProcess();
+}
+
+
+bool ExternalLanguage::start()
+{
+ displayProcessCommand();
+
+ return m_languageProcess->start( KProcess::NotifyOnExit, KProcess::All );
+}
+
+
+void ExternalLanguage::resetLanguageProcess()
+{
+ reset();
+ deleteLanguageProcess();
+ m_errorCount = 0;
+
+ m_languageProcess = new KProcess(this);
+
+ connect( m_languageProcess, SIGNAL(receivedStdout( KProcess*, char*, int )),
+ this, SLOT(receivedStdout( KProcess*, char*, int )) );
+
+ connect( m_languageProcess, SIGNAL(receivedStderr( KProcess*, char*, int )),
+ this, SLOT(receivedStderr( KProcess*, char*, int )) );
+
+ connect( m_languageProcess, SIGNAL(processExited( KProcess* )),
+ this, SLOT(processExited( KProcess* )) );
+}
+
+
+void ExternalLanguage::displayProcessCommand()
+{
+ QStringList quotedArguments;
+ QValueList<QCString> arguments = m_languageProcess->args();
+
+ if ( arguments.size() == 1 )
+ quotedArguments << arguments[0];
+
+ else
+ {
+ QValueList<QCString>::const_iterator end = arguments.end();
+
+ for ( QValueList<QCString>::const_iterator it = arguments.begin(); it != end; ++it )
+ {
+ if ( (*it).isEmpty() || (*it).contains( QRegExp("[\\s]") ) )
+ quotedArguments << KProcess::quote( *it );
+ else
+ quotedArguments << *it;
+ }
+ }
+
+// outputMessage( "<i>" + quotedArguments.join(" ") + "</i>" );
+ outputMessage( quotedArguments.join(" ") );
+// LanguageManager::self()->logView()->addOutput( quotedArguments.join(" "), LogView::ot_info );
+}
+
+
+#include "externallanguage.moc"
diff --git a/src/languages/externallanguage.h b/src/languages/externallanguage.h
new file mode 100644
index 0000000..401c2b8
--- /dev/null
+++ b/src/languages/externallanguage.h
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef EXTERNALLANGUAGE_H
+#define EXTERNALLANGUAGE_H
+
+#include "language.h"
+
+class KProcess;
+
+/**
+Base class for Language support that relies on an external program; so this
+class provides functionality for dealing with external processes.
+
+@author Daniel Clarke
+@author David Saxton
+*/
+class ExternalLanguage : public Language
+{
+Q_OBJECT
+public:
+ ExternalLanguage( ProcessChain *processChain, KTechlab *parent, const QString &name );
+ ~ExternalLanguage();
+
+protected slots:
+ void receivedStdout( KProcess *, char * buffer, int buflen );
+ void receivedStderr( KProcess *, char * buffer, int buflen );
+ void processExited( KProcess * );
+
+protected:
+ /**
+ * Call this to start the language process. ExternalLanguage will ensure
+ * that communication et all is properly set up.
+ * @return true on success, false on error
+ */
+ bool start();
+ /**
+ * @returns whether the string outputted to stdout is an error or not
+ */
+ virtual bool isError( const QString &message ) const = 0;
+ /**
+ * @returns whether the string outputted to stderr is fatal (stopped compilation)
+ */
+ virtual bool isStderrOutputFatal( const QString & message ) const { Q_UNUSED(message); return true; }
+ /**
+ * @returns whether the string outputted to stdout is a warning or not
+ */
+ virtual bool isWarning( const QString &message ) const = 0;
+ /**
+ * Called when the process outputs a (non warning/error) message
+ */
+ virtual void outputtedMessage( const QString &/*message*/ ) {};
+ /**
+ * Called when the process outputs a warning
+ */
+ virtual void outputtedWarning( const QString &/*message*/ ) {};
+ /**
+ * Called when the process outputs an error
+ */
+ virtual void outputtedError( const QString &/*message*/ ) {};
+ /**
+ * Called when the process exits (called before any signals are emitted,
+ * etc). If you reinherit this function, you should return whether
+ * everything is OK.
+ */
+ virtual bool processExited( bool successfully ) { return successfully; }
+ /**
+ * Call this function if your process could not be started - the process
+ * will be deleted, and a failure signal emitted.
+ */
+ void processInitFailed();
+ /**
+ * Disconnects and deletes the language's process.
+ */
+ void deleteLanguageProcess();
+ /**
+ * Creates process and makes connections, ready for the derived class to
+ * add arguments and start the process.
+ */
+ void resetLanguageProcess();
+ /**
+ * Prints out the command used for running the process, with any arguments
+ * that contain spaces put into quotation marks.
+ */
+ void displayProcessCommand();
+
+ KProcess * m_languageProcess;
+};
+
+#endif
diff --git a/src/languages/flowcode.cpp b/src/languages/flowcode.cpp
new file mode 100644
index 0000000..d19d17e
--- /dev/null
+++ b/src/languages/flowcode.cpp
@@ -0,0 +1,496 @@
+/***************************************************************************
+ * Copyright (C) 2003-2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "flowcodedocument.h"
+#include "flowcode.h"
+#include "flowcontainer.h"
+#include "flowpart.h"
+#include "microsettings.h"
+#include "microinfo.h"
+#include "micropackage.h"
+#include "node.h"
+#include "pinmapping.h"
+
+#include <klocale.h>
+// #include <kmessagebox.h>
+#include <qfile.h>
+
+FlowCode::FlowCode( ProcessChain *processChain, KTechlab *parent )
+ : Language( processChain, parent, i18n("FlowCode") )
+{
+ m_successfulMessage = i18n("*** Microbe generation successful ***");
+ m_failedMessage = i18n("*** Microbe generation failed ***");
+ p_startPart = 0l;
+}
+
+FlowCode::~FlowCode()
+{
+}
+
+
+void FlowCode::processInput( ProcessOptions options )
+{
+ m_processOptions = options;
+
+ if ( !options.p_flowCodeDocument )
+ {
+ options.p_flowCodeDocument = new FlowCodeDocument( QString::null, 0l );
+ options.p_flowCodeDocument->openURL( options.inputFiles().first() );
+
+ connect( this, SIGNAL(processSucceeded( Language *)), options.p_flowCodeDocument, SLOT(deleteLater()) );
+ connect( this, SIGNAL(processFailed( Language *)), options.p_flowCodeDocument, SLOT(deleteLater()) );
+ }
+
+ if ( !options.p_flowCodeDocument->microSettings() )
+ {
+ finish(false);
+ return;
+ }
+
+ QFile file(options.intermediaryOutput());
+ if ( file.open(IO_WriteOnly | IO_ReadOnly) == false )
+ {
+ finish(false);
+ return;
+ }
+ file.close();
+
+ if ( file.open(IO_WriteOnly) == false )
+ {
+ finish(false);
+ return;
+ }
+
+ const QString code = generateMicrobe( options.p_flowCodeDocument->itemList(), options.p_flowCodeDocument->microSettings() );
+ if (code.isEmpty())
+ {
+ finish(false);
+ return;
+ }
+
+ QTextStream stream(&file);
+ stream << code;
+ file.close();
+ finish(true);
+}
+
+
+void FlowCode::setStartPart( FlowPart *startPart )
+{
+ p_startPart = startPart;
+}
+
+
+void FlowCode::addCode( const QString& code )
+{
+ m_code += code;
+ if ( !m_code.endsWith("\n") ) m_code += '\n';
+}
+
+bool FlowCode::isValidBranch( FlowPart *flowPart )
+{
+ return flowPart && (flowPart->level() >= m_curLevel) && !m_stopParts.contains(flowPart);
+}
+
+void FlowCode::addCodeBranch( FlowPart * flowPart )
+{
+ if (!flowPart)
+ return;
+
+ if ( !isValidBranch(flowPart) )
+ return;
+
+ if ( m_addedParts.contains(flowPart) )
+ {
+ const QString labelName = genLabel(flowPart->id());
+ addCode( "goto "+labelName );
+ m_gotos.append(labelName);
+ return;
+ }
+ else
+ {
+ m_addedParts.append(flowPart);
+ int prevLevel = m_curLevel;
+ m_curLevel = flowPart->level();
+
+ const QString labelName = genLabel(flowPart->id());
+ addCode(labelName+':');
+ m_labels.append(labelName);
+
+ flowPart->generateMicrobe(this);
+ m_curLevel = prevLevel;
+ }
+}
+
+QString FlowCode::genLabel( const QString &id )
+{
+ return "__label_"+id;
+}
+
+void FlowCode::addStopPart( FlowPart *part )
+{
+ if (part) m_stopParts.append(part);
+}
+
+void FlowCode::removeStopPart( FlowPart *part )
+{
+ if (!part) return;
+
+ // We only want to remove one instance of the FlowPart, in case it has been
+ // used as a StopPart for more than one FlowPart
+ FlowPartList::iterator it = m_stopParts.find(part);
+ if ( it != m_stopParts.end() ) m_stopParts.remove(it);
+}
+
+QString FlowCode::generateMicrobe( const ItemList &itemList, MicroSettings *settings )
+{
+ bool foundStart = false;
+ const ItemList::const_iterator end = itemList.end();
+ for ( ItemList::const_iterator it = itemList.begin(); it != end; ++it )
+ {
+ if (!*it)
+ continue;
+
+ FlowPart * startPart = dynamic_cast<FlowPart*>((Item*)*it);
+
+ if (!startPart)
+ continue;
+
+ // Check to see if we have any floating connections
+ const NodeMap nodeMap = startPart->nodeMap();
+ NodeMap::const_iterator nodeMapEnd = nodeMap.end();
+ for ( NodeMap::const_iterator nodeMapIt = nodeMap.begin(); nodeMapIt != nodeMapEnd; ++nodeMapIt )
+ {
+ Node * node = nodeMapIt.data().node;
+ if ( !node || (node->type() != Node::fp_out) )
+ continue;
+
+ if ( !startPart->outputPart( nodeMapIt.key() ) )
+ outputWarning( i18n("Warning: Floating connection for %1").arg( startPart->id() ) );
+ }
+
+ FlowContainer * fc = dynamic_cast<FlowContainer*>((Item*)*it);
+
+ if ( (*it)->id().startsWith("START") && startPart )
+ {
+ foundStart = true;
+ setStartPart(startPart);
+ }
+ else if ( ((*it)->id().startsWith("interrupt") || (*it)->id().startsWith("sub")) && fc )
+ {
+ addSubroutine(fc);
+ }
+ }
+
+ if (!foundStart)
+ {
+ outputError( i18n("KTechlab was unable to find the \"Start\" part.\nThis must be included as the starting point for your program.") );
+ return 0;
+ }
+
+ m_addedParts.clear();
+ m_stopParts.clear();
+ m_gotos.clear();
+ m_labels.clear();
+ m_code = QString::null;
+
+ // PIC type
+ {
+ const QString codeString = settings->microInfo()->id() + "\n";
+ addCode(codeString);
+ }
+
+ // Initial variables
+ {
+ QStringList vars = settings->variableNames();
+
+ // If "inited" is true at the end, we comment at the insertion point
+ bool inited = false;
+ const QString codeString = "// Initial variable values:\n";
+ addCode(codeString);
+
+ const QStringList::iterator end = vars.end();
+ for ( QStringList::iterator it = vars.begin(); it != end; ++it )
+ {
+ VariableInfo *info = settings->variableInfo(*it);
+ if ( info /*&& info->initAtStart*/ )
+ {
+ inited = true;
+ addCode(*it+" = "+info->valueAsString());
+ }
+ }
+ if (!inited) {
+ m_code.remove(codeString);
+ } else {
+ addCode("\n");
+ }
+ }
+
+ // Initial pin maps
+ {
+ const PinMappingMap pinMappings = settings->pinMappings();
+ PinMappingMap::const_iterator end = pinMappings.end();
+ for ( PinMappingMap::const_iterator it = pinMappings.begin(); it != end; ++it )
+ {
+ QString type;
+
+ switch ( it.data().type() )
+ {
+ case PinMapping::Keypad_4x3:
+ case PinMapping::Keypad_4x4:
+ type = "keypad";
+ break;
+
+ case PinMapping::SevenSegment:
+ type = "sevenseg";
+ break;
+
+ case PinMapping::Invalid:
+ break;
+ }
+
+ if ( type.isEmpty() )
+ continue;
+
+ addCode( QString("%1 %2 %3").arg( type ).arg( it.key() ).arg( it.data().pins().join(" ") ) );
+ }
+ }
+
+ // Initial port settings
+ {
+ QStringList portNames = settings->microInfo()->package()->portNames();
+ const QStringList::iterator end = portNames.end();
+
+ // TRIS registers (remember that this is set to ..11111 on all resets)
+ for ( QStringList::iterator it = portNames.begin(); it != end; ++it )
+ {
+ const int portType = settings->portType(*it);
+ const int pinCount = settings->microInfo()->package()->pinCount( 0, *it );
+
+ // We don't need to reset it if portType == 2^(pinCount-1)
+ if ( portType != (1<<pinCount)-1 )
+ {
+ QString name = *it;
+ name.replace("PORT","TRIS");
+ addCode( name+" = "+QString::number(portType) );
+ }
+ }
+
+ // PORT registers
+ for ( QStringList::iterator it = portNames.begin(); it != end; ++it )
+ {
+ const int portState = settings->portState(*it);
+ addCode( (*it)+" = "+QString::number(portState) );
+ }
+ }
+
+
+ m_curLevel = p_startPart->level();
+ addCodeBranch(p_startPart);
+ addCode("end");
+
+ {
+ const FlowPartList::iterator end = m_subroutines.end();
+ for ( FlowPartList::iterator it = m_subroutines.begin(); it != end; ++it )
+ {
+ m_curLevel = 0;
+ if (*it)
+ {
+ addCode("\n");
+ addCodeBranch(*it);
+ }
+ }
+ }
+
+ tidyCode();
+ return m_code;
+}
+
+void FlowCode::tidyCode()
+{
+ // First, get rid of the unused labels
+ const QStringList::iterator end = m_labels.end();
+ for ( QStringList::iterator it = m_labels.begin(); it != end; ++it )
+ {
+ if ( !m_gotos.contains(*it) ) m_code.remove(*it+':');
+ }
+
+
+ // And now on to handling indentation :-)
+
+ if ( !m_code.endsWith("\n") ) m_code.append("\n");
+ QString newCode;
+ bool multiLineComment = false; // For "/*"..."*/"
+ bool comment = false; // For "//"
+ bool asmEmbed = false;
+ bool asmEmbedAllowed = true;
+ bool asmKeyword = false;
+ int asmEmbedLevel = -1;
+ int level = 0;
+
+ int pos=-1;
+ const int length = m_code.length();
+ while ( ++pos<length )
+ {
+ switch ( m_code[pos].latin1() )
+ {
+ case '\n':
+ {
+ if (comment && !multiLineComment) comment = false;
+ newCode += '\n';
+ if ( !comment && !asmEmbed )
+ {
+ while ( pos+1<length && m_code[pos+1].isSpace() ) pos++;
+ bool closeBrace = false;
+ if ( pos+1<length && m_code[pos+1] == '}' )
+ {
+ level--;
+ pos++;
+ closeBrace = true;
+ }
+ for ( int i=0; i<level; i++ ) newCode += '\t';
+ if (closeBrace) newCode += '}';
+ asmEmbedAllowed = true;
+ }
+ break;
+ }
+ case '/':
+ {
+ newCode += '/';
+ if ( pos+1<length )
+ {
+ if ( m_code[pos+1] == '/' ) comment = true;
+ else if ( m_code[pos+1] == '*' ) multiLineComment = comment = true;
+ newCode += m_code[++pos];
+ }
+ asmEmbedAllowed = false;
+ asmKeyword = false;
+ break;
+ }
+ case '*':
+ {
+ newCode += '*';
+ if ( pos+1<length )
+ {
+ if ( m_code[pos++] == '/' && multiLineComment ) comment = multiLineComment = false;
+ newCode += m_code[pos];
+ }
+ asmEmbedAllowed = false;
+ asmKeyword = false;
+ break;
+ }
+ case '{':
+ {
+ if (asmKeyword) {
+ asmEmbed = true;
+ asmEmbedLevel = level;
+ }
+
+ if ( !comment ) level++;
+ newCode += '{';
+
+ asmEmbedAllowed = false;
+ asmKeyword = false;
+ break;
+ }
+ case '}':
+ {
+ if ( !comment ) level--;
+
+ if (asmEmbed && asmEmbedLevel == level)
+ {
+ asmEmbed = false;
+ newCode += "\n";
+ for ( int i=0; i<level; i++ ) newCode += '\t';
+ }
+ newCode += '}';
+
+ asmEmbedAllowed = true;
+ asmKeyword = false;
+ break;
+ }
+ case 'a':
+ {
+ newCode += m_code[pos];
+ if ( asmEmbedAllowed && !comment && pos+2<length )
+ {
+ if ( m_code[pos+1] == 's' && m_code[pos+2] == 'm' )
+ {
+ asmKeyword = true;
+ newCode += "sm";
+ pos += 2;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ asmEmbedAllowed = false;
+ asmKeyword = false;
+ newCode += m_code[pos];
+ break;
+ }
+ }
+ }
+ m_code = newCode;
+}
+
+void FlowCode::addSubroutine( FlowPart *part )
+{
+ if ( !part || m_subroutines.contains(part) || part->parentItem() || !dynamic_cast<FlowContainer*>(part) ) return;
+ m_subroutines.append(part);
+}
+
+
+ProcessOptions::ProcessPath::Path FlowCode::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ return ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute;
+
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ return ProcessOptions::ProcessPath::Microbe_PIC;
+
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ return ProcessOptions::ProcessPath::Microbe_Program;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C_Library:
+ case ProcessOptions::ProcessPath::C_Object:
+ case ProcessOptions::ProcessPath::C_PIC:
+ case ProcessOptions::ProcessPath::C_Program:
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Object_Library:
+ case ProcessOptions::ProcessPath::Object_PIC:
+ case ProcessOptions::ProcessPath::Object_Program:
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
+
diff --git a/src/languages/flowcode.h b/src/languages/flowcode.h
new file mode 100644
index 0000000..afa17db
--- /dev/null
+++ b/src/languages/flowcode.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * Copyright (C) 2003-2004 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef FLOWCODE_H
+#define FLOWCODE_H
+
+#include "language.h"
+
+#include <qguardedptr.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+
+class CNItem;
+class FlowPart;
+class Item;
+class MicroSettings;
+
+typedef QValueList<FlowPart*> FlowPartList;
+typedef QValueList<QGuardedPtr<Item> > ItemList;
+
+/**
+"FlowCode" can possibly be considered a misnomer, as the output is actually Microbe.
+However, the function of this class is to take a set of FlowParts, and generate the
+basic from the code that they create. The 3 simple steps for usage of this function:
+(1) Create an instance of this class, giving the Start point and setings
+(2) Add all the subroutines present using addSubroutine()
+(3) Call generateMicrobe() to get the Microbe code.
+@author David Saxton
+*/
+class FlowCode : public Language
+{
+public:
+ FlowCode( ProcessChain *processChain, KTechlab *parent );
+
+ virtual void processInput( ProcessOptions options );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+ /**
+ * You must set the start part
+ */
+ void setStartPart( FlowPart *startPart );
+ ~FlowCode();
+ /**
+ * You must add all top level subroutines using this function
+ */
+ void addSubroutine( FlowPart *part );
+ /**
+ * Adds code at the current insertion point
+ */
+ void addCode( const QString& code );
+ /**
+ * Adds a code branch to the current insertion point. This will stop when the level gets
+ * below the original starting level (so for insertion of the contents of a for loop,
+ * insertion will stop at the end of that for loop).
+ * @param flowPart The next FlowPart to get code from
+ */
+ void addCodeBranch( FlowPart *flowPart );
+ /**
+ * Designates a FlowPart as a stopping part (i.e. will refuse requests to addCodeBranch
+ * for that FlowPart until removeStopPart is called
+ */
+ void addStopPart( FlowPart *part );
+ /**
+ * Undesignates a FlowPart as a stopping part
+ */
+ void removeStopPart( FlowPart *part );
+ /**
+ * Generates and returns the microbe code
+ * @param nonVerbal if true then will not inform the user when something goes wrong
+ */
+ QString generateMicrobe( const ItemList &itemList, MicroSettings *settings );
+ /**
+ * Returns true if the FlowPart is a valid one for adding a branch
+ */
+ bool isValidBranch( FlowPart *flowPart );
+ /**
+ * Generates a nice label name from the string, e.g. genLabel("callsub")
+ * returns "__label_callsub".
+ */
+ static QString genLabel( const QString &id );
+
+protected:
+ /**
+ * Performs indenting, removal of unnecessary labels, etc.
+ */
+ void tidyCode();
+
+ QStringList m_gotos; // Gotos used
+ QStringList m_labels; // Labels used
+ FlowPartList m_subroutines;
+ FlowPartList m_addedParts;
+ FlowPartList m_stopParts;
+ FlowPart *p_startPart;
+ QString m_code;
+ int m_curLevel;
+};
+
+#endif
diff --git a/src/languages/gpasm.cpp b/src/languages/gpasm.cpp
new file mode 100644
index 0000000..447354e
--- /dev/null
+++ b/src/languages/gpasm.cpp
@@ -0,0 +1,187 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "asmparser.h"
+#include "docmanager.h"
+#include "gpasm.h"
+#include "logview.h"
+#include "languagemanager.h"
+#include "src/core/ktlconfig.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <qregexp.h>
+
+Gpasm::Gpasm( ProcessChain *processChain, KTechlab * parent )
+ : ExternalLanguage( processChain, parent, "Gpasm" )
+{
+ m_successfulMessage = i18n("*** Assembly successful ***");
+ m_failedMessage = i18n("*** Assembly failed ***");
+}
+
+
+Gpasm::~Gpasm()
+{
+}
+
+
+void Gpasm::processInput( ProcessOptions options )
+{
+ resetLanguageProcess();
+ m_processOptions = options;
+
+ AsmParser p( options.inputFiles().first() );
+ p.parse();
+
+ *m_languageProcess << ("gpasm");
+
+ if ( ProcessOptions::ProcessPath::from( options.processPath() ) == ProcessOptions::ProcessPath::AssemblyRelocatable )
+ *m_languageProcess << ("--object");
+
+// *m_languageProcess << ("--debug-info"); // Debug info
+
+ // Output filename
+ *m_languageProcess << ("--output");
+ *m_languageProcess << ( options.intermediaryOutput() );
+
+ if ( !options.m_hexFormat.isEmpty() )
+ {
+ *m_languageProcess << ("--hex-format");
+ *m_languageProcess << (options.m_hexFormat);
+ }
+
+ // Radix
+ if ( !p.containsRadix() )
+ {
+ *m_languageProcess << ("--radix");
+ switch( KTLConfig::radix() )
+ {
+ case KTLConfig::EnumRadix::Binary:
+ *m_languageProcess << ("BIN");
+ break;
+ case KTLConfig::EnumRadix::Octal:
+ *m_languageProcess << ("OCT");
+ break;
+ case KTLConfig::EnumRadix::Hexadecimal:
+ *m_languageProcess << ("HEX");
+ break;
+ case KTLConfig::EnumRadix::Decimal:
+ default:
+ *m_languageProcess << ("DEC");
+ break;
+ }
+ }
+
+ // Warning Level
+ *m_languageProcess << ("--warning");
+ switch( KTLConfig::gpasmWarningLevel() )
+ {
+ case KTLConfig::EnumGpasmWarningLevel::Warnings:
+ *m_languageProcess << ("1");
+ break;
+ case KTLConfig::EnumGpasmWarningLevel::Errors:
+ *m_languageProcess << ("2");
+ break;
+ default:
+ case KTLConfig::EnumGpasmWarningLevel::All:
+ *m_languageProcess << ("0");
+ break;
+ }
+
+ // Ignore case
+ if ( KTLConfig::ignoreCase() )
+ *m_languageProcess << ("--ignore-case");
+
+ // Dos formatting
+ if ( KTLConfig::dosFormat() )
+ *m_languageProcess << ("--dos");
+
+ // Force list
+ if ( options.b_forceList )
+ *m_languageProcess << ("--force-list");
+
+ // Other options
+ if ( !KTLConfig::miscGpasmOptions().isEmpty() )
+ *m_languageProcess << ( KTLConfig::miscGpasmOptions() );
+
+ // Input Asm file
+ *m_languageProcess << ( options.inputFiles().first() );
+
+ if ( !start() )
+ {
+ KMessageBox::sorry( LanguageManager::self()->logView(), i18n("Assembly failed. Please check you have gputils installed.") );
+ processInitFailed();
+ return;
+ }
+}
+
+
+bool Gpasm::isError( const QString &message ) const
+{
+ return message.contains( "Error", false );
+}
+
+
+bool Gpasm::isWarning( const QString &message ) const
+{
+ return message.contains( "Warning", false );
+}
+
+
+ProcessOptions::ProcessPath::Path Gpasm::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ return ProcessOptions::ProcessPath::Program_PIC;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ return ProcessOptions::ProcessPath::Object_Library;
+
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ return ProcessOptions::ProcessPath::Object_PIC;
+
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ return ProcessOptions::ProcessPath::Object_Program;
+
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C_Library:
+ case ProcessOptions::ProcessPath::C_Object:
+ case ProcessOptions::ProcessPath::C_PIC:
+ case ProcessOptions::ProcessPath::C_Program:
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Object_Library:
+ case ProcessOptions::ProcessPath::Object_PIC:
+ case ProcessOptions::ProcessPath::Object_Program:
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
+
diff --git a/src/languages/gpasm.h b/src/languages/gpasm.h
new file mode 100644
index 0000000..c92a969
--- /dev/null
+++ b/src/languages/gpasm.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef GPASM_H
+#define GPASM_H
+
+#include "externallanguage.h"
+
+/**
+@short Interface to the GNU PIC assembler
+@author David Saxton
+*/
+class Gpasm : public ExternalLanguage
+{
+ public:
+ Gpasm( ProcessChain *processChain, KTechlab *parent );
+ ~Gpasm();
+
+ virtual void processInput( ProcessOptions options );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+ protected:
+ virtual bool isError( const QString &message ) const;
+ virtual bool isWarning( const QString &message ) const;
+};
+
+#endif
diff --git a/src/languages/gpdasm.cpp b/src/languages/gpdasm.cpp
new file mode 100644
index 0000000..8c255d3
--- /dev/null
+++ b/src/languages/gpdasm.cpp
@@ -0,0 +1,158 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "docmanager.h"
+#include "gpdasm.h"
+#include "logview.h"
+#include "languagemanager.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <qfile.h>
+#include <qregexp.h>
+
+Gpdasm::Gpdasm( ProcessChain *processChain, KTechlab *parent )
+ : ExternalLanguage( processChain, parent, "Gpdasm" )
+{
+ m_successfulMessage = i18n("*** Disassembly successful ***");
+ m_failedMessage = i18n("*** Disassembly failed ***");
+}
+
+
+Gpdasm::~Gpdasm()
+{
+}
+
+
+void Gpdasm::processInput( ProcessOptions options )
+{
+ resetLanguageProcess();
+ m_asmOutput = "";
+ m_processOptions = options;;
+
+ *m_languageProcess << ("gpdasm");
+
+ *m_languageProcess << ("--processor");
+ *m_languageProcess << ( options.m_picID );
+ *m_languageProcess << ( options.inputFiles().first() );
+
+ if ( !start() )
+ {
+ KMessageBox::sorry( LanguageManager::self()->logView(), i18n("Disassembly failed. Please check you have gputils installed.") );
+ processInitFailed();
+ return;
+ }
+}
+
+
+void Gpdasm::outputtedMessage( const QString &message )
+{
+ m_asmOutput += message + "\n";
+}
+
+
+bool Gpdasm::processExited( bool successfully )
+{
+ if (!successfully)
+ return false;
+
+ QFile file(m_processOptions.intermediaryOutput());
+ if ( file.open(IO_WriteOnly) == false )
+ return false;
+
+ QTextStream stream(&file);
+ stream << m_asmOutput;
+ file.close();
+ return true;
+}
+
+
+bool Gpdasm::isError( const QString &message ) const
+{
+ return (message.find( "error", -1, false ) != -1);
+}
+
+
+bool Gpdasm::isWarning( const QString &message ) const
+{
+ return (message.find( "warning", -1, false ) != -1);
+}
+
+
+MessageInfo Gpdasm::extractMessageInfo( const QString &text )
+{
+ if ( text.length()<5 || !text.startsWith("/") )
+ return MessageInfo();
+
+ const int index = text.find( ".asm", 0, false )+4;
+ if ( index == -1+4 )
+ return MessageInfo();
+ const QString fileName = text.left(index);
+
+ // Extra line number
+ const QString message = text.right(text.length()-index);
+ const int linePos = message.find( QRegExp(":[\\d]+") );
+ int line = -1;
+ if ( linePos != -1 )
+ {
+ const int linePosEnd = message.find( ':', linePos+1 );
+ if ( linePosEnd != -1 )
+ {
+ const QString number = message.mid( linePos+1, linePosEnd-linePos-1 ).stripWhiteSpace();
+ bool ok;
+ line = number.toInt(&ok)-1;
+ if (!ok) line = -1;
+ }
+ }
+
+ return MessageInfo( fileName, line );
+}
+
+
+
+ProcessOptions::ProcessPath::Path Gpdasm::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C_Library:
+ case ProcessOptions::ProcessPath::C_Object:
+ case ProcessOptions::ProcessPath::C_PIC:
+ case ProcessOptions::ProcessPath::C_Program:
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ case ProcessOptions::ProcessPath::Object_Library:
+ case ProcessOptions::ProcessPath::Object_PIC:
+ case ProcessOptions::ProcessPath::Object_Program:
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
diff --git a/src/languages/gpdasm.h b/src/languages/gpdasm.h
new file mode 100644
index 0000000..149ed26
--- /dev/null
+++ b/src/languages/gpdasm.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef GPDASM_H
+#define GPDASM_H
+
+#include <externallanguage.h>
+
+/**
+Interface to the GNU Pic Disassembler
+@author David Saxton
+*/
+class Gpdasm : public ExternalLanguage
+{
+public:
+ Gpdasm( ProcessChain *processChain, KTechlab *parent );
+ ~Gpdasm();
+
+ virtual void processInput( ProcessOptions options );
+ virtual MessageInfo extractMessageInfo( const QString &text );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+protected:
+ virtual void outputtedMessage( const QString &message );
+ virtual bool isError( const QString &message ) const;
+ virtual bool isWarning( const QString &message ) const;
+ virtual bool processExited( bool successfully );
+
+ QString m_asmOutput; // Outputed by gpdasm
+};
+
+#endif
diff --git a/src/languages/gplib.cpp b/src/languages/gplib.cpp
new file mode 100644
index 0000000..db4a32b
--- /dev/null
+++ b/src/languages/gplib.cpp
@@ -0,0 +1,139 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "gplib.h"
+#include "languagemanager.h"
+#include "logview.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+
+Gplib::Gplib( ProcessChain *processChain, KTechlab * parent )
+ : ExternalLanguage( processChain, parent, "Gpasm" )
+{
+ m_successfulMessage = i18n("*** Archiving successful ***");
+ m_failedMessage = i18n("*** Archiving failed ***");
+}
+
+
+Gplib::~Gplib()
+{
+}
+
+
+void Gplib::processInput( ProcessOptions options )
+{
+ resetLanguageProcess();
+ m_processOptions = options;
+
+ *m_languageProcess << ("gplib");
+ *m_languageProcess << ("--create");
+
+ *m_languageProcess << ( options.intermediaryOutput() );
+
+ const QStringList inputFiles = options.inputFiles();
+ QStringList::const_iterator end = inputFiles.end();
+ for ( QStringList::const_iterator it = inputFiles.begin(); it != end; ++it )
+ *m_languageProcess << ( *it );
+
+ if ( !start() )
+ {
+ KMessageBox::sorry( LanguageManager::self()->logView(), i18n("Linking failed. Please check you have gputils installed.") );
+ processInitFailed();
+ return;
+ }
+}
+
+
+bool Gplib::isError( const QString &message ) const
+{
+ return message.contains( "Error", false );
+}
+
+
+bool Gplib::isWarning( const QString &message ) const
+{
+ return message.contains( "Warning", false );
+}
+
+
+MessageInfo Gplib::extractMessageInfo( const QString &text )
+{
+#if 0
+ if ( text.length()<5 || !text.startsWith("/") )
+ return MessageInfo();
+
+ const int index = text.find( ".asm", 0, false )+4;
+ if ( index == -1+4 )
+ return MessageInfo();
+ const QString fileName = text.left(index);
+
+ // Extra line number
+ const QString message = text.right(text.length()-index);
+ const int linePos = message.find( QRegExp(":[\\d]+") );
+ int line = -1;
+ if ( linePos != -1 )
+{
+ const int linePosEnd = message.find( ':', linePos+1 );
+ if ( linePosEnd != -1 )
+{
+ const QString number = message.mid( linePos+1, linePosEnd-linePos-1 ).stripWhiteSpace();
+ bool ok;
+ line = number.toInt(&ok)-1;
+ if (!ok) line = -1;
+}
+}
+ return MessageInfo( fileName, line );
+#endif
+ return MessageInfo();
+}
+
+
+
+
+ProcessOptions::ProcessPath::Path Gplib::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::Object_Library:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C_Library:
+ case ProcessOptions::ProcessPath::C_Object:
+ case ProcessOptions::ProcessPath::C_PIC:
+ case ProcessOptions::ProcessPath::C_Program:
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Object_PIC:
+ case ProcessOptions::ProcessPath::Object_Program:
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
diff --git a/src/languages/gplib.h b/src/languages/gplib.h
new file mode 100644
index 0000000..35cb1da
--- /dev/null
+++ b/src/languages/gplib.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef GPLIB_H
+#define GPLIB_H
+
+#include <externallanguage.h>
+
+/**
+@author David Saxton
+*/
+class Gplib : public ExternalLanguage
+{
+ public:
+ Gplib( ProcessChain *processChain, KTechlab *parent );
+ ~Gplib();
+
+ virtual void processInput( ProcessOptions options );
+ virtual MessageInfo extractMessageInfo( const QString &text );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+ protected:
+ virtual bool isError( const QString &message ) const;
+ virtual bool isWarning( const QString &message ) const;
+};
+
+#endif
diff --git a/src/languages/gplink.cpp b/src/languages/gplink.cpp
new file mode 100644
index 0000000..548449a
--- /dev/null
+++ b/src/languages/gplink.cpp
@@ -0,0 +1,174 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "gplink.h"
+#include "languagemanager.h"
+#include "logview.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+
+Gplink::Gplink( ProcessChain *processChain, KTechlab * parent )
+ : ExternalLanguage( processChain, parent, "Gpasm" )
+{
+ m_successfulMessage = i18n("*** Linking successful ***");
+ m_failedMessage = i18n("*** Linking failed ***");
+}
+
+
+Gplink::~Gplink()
+{
+}
+
+
+void Gplink::processInput( ProcessOptions options )
+{
+ resetLanguageProcess();
+ m_processOptions = options;
+
+ *m_languageProcess << ("gplink");
+
+ if ( !options.m_hexFormat.isEmpty() )
+ {
+ *m_languageProcess << ("--hex-format");
+ *m_languageProcess << (options.m_hexFormat);
+ }
+
+ if ( options.m_bOutputMapFile )
+ *m_languageProcess << ("--map");
+
+ if ( !options.m_libraryDir.isEmpty() )
+ {
+ *m_languageProcess << ("--include");
+ *m_languageProcess << ( options.m_libraryDir );
+ }
+
+ if ( !options.m_linkerScript.isEmpty() )
+ {
+ *m_languageProcess << ("--script");
+ *m_languageProcess << ( options.m_linkerScript );
+ }
+
+ if ( !options.m_linkOther.isEmpty() )
+ *m_languageProcess << (options.m_linkOther);
+
+ // Output hex file
+ *m_languageProcess << ("--output");
+ *m_languageProcess << ( options.intermediaryOutput() );
+
+ // Input object file
+ const QStringList inputFiles = options.inputFiles();
+ QStringList::const_iterator end = inputFiles.end();
+ for ( QStringList::const_iterator it = inputFiles.begin(); it != end; ++it )
+ *m_languageProcess << ( *it );
+
+ // Other libraries
+ end = options.m_linkLibraries.end();
+ for ( QStringList::const_iterator it = options.m_linkLibraries.begin(); it != end; ++it )
+ *m_languageProcess << ( *it );
+
+ if ( !start() )
+ {
+ KMessageBox::sorry( LanguageManager::self()->logView(), i18n("Linking failed. Please check you have gputils installed.") );
+ processInitFailed();
+ return;
+ }
+}
+
+
+bool Gplink::isError( const QString &message ) const
+{
+ return message.contains( "Error", false );
+}
+
+
+bool Gplink::isWarning( const QString &message ) const
+{
+ return message.contains( "Warning", false );
+}
+
+
+MessageInfo Gplink::extractMessageInfo( const QString &text )
+{
+#if 0
+ if ( text.length()<5 || !text.startsWith("/") )
+ return MessageInfo();
+
+ const int index = text.find( ".asm", 0, false )+4;
+ if ( index == -1+4 )
+ return MessageInfo();
+ const QString fileName = text.left(index);
+
+ // Extra line number
+ const QString message = text.right(text.length()-index);
+ const int linePos = message.find( QRegExp(":[\\d]+") );
+ int line = -1;
+ if ( linePos != -1 )
+ {
+ const int linePosEnd = message.find( ':', linePos+1 );
+ if ( linePosEnd != -1 )
+ {
+ const QString number = message.mid( linePos+1, linePosEnd-linePos-1 ).stripWhiteSpace();
+ bool ok;
+ line = number.toInt(&ok)-1;
+ if (!ok) line = -1;
+ }
+ }
+ return MessageInfo( fileName, line );
+#endif
+ return MessageInfo();
+}
+
+
+
+ProcessOptions::ProcessPath::Path Gplink::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::Object_PIC:
+ return ProcessOptions::ProcessPath::Program_PIC;
+
+ case ProcessOptions::ProcessPath::Object_Program:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C_Library:
+ case ProcessOptions::ProcessPath::C_Object:
+ case ProcessOptions::ProcessPath::C_PIC:
+ case ProcessOptions::ProcessPath::C_Program:
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Object_Library:
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
+
+
+
diff --git a/src/languages/gplink.h b/src/languages/gplink.h
new file mode 100644
index 0000000..c60f9f9
--- /dev/null
+++ b/src/languages/gplink.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef GPLINK_H
+#define GPLINK_H
+
+#include <externallanguage.h>
+
+/**
+@short Interface to the GNU PIC linker
+@author David Saxton
+*/
+class Gplink : public ExternalLanguage
+{
+ public:
+ Gplink( ProcessChain *processChain, KTechlab *parent );
+ ~Gplink();
+
+ virtual void processInput( ProcessOptions options );
+ virtual MessageInfo extractMessageInfo( const QString &text );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+ protected:
+ virtual bool isError( const QString &message ) const;
+ virtual bool isWarning( const QString &message ) const;
+};
+
+#endif
diff --git a/src/languages/language.cpp b/src/languages/language.cpp
new file mode 100644
index 0000000..e7ce759
--- /dev/null
+++ b/src/languages/language.cpp
@@ -0,0 +1,558 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "asmparser.h"
+#include "ktechlab.h"
+#include "language.h"
+#include "logview.h"
+#include "outputmethoddlg.h"
+#include "processchain.h"
+#include "projectmanager.h"
+#include "languagemanager.h"
+#include "src/core/ktlconfig.h"
+
+#include <kdebug.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <qregexp.h>
+#include <qtimer.h>
+
+//BEGIN class Language
+Language::Language( ProcessChain *processChain, KTechlab *parent, const QString &name )
+ : QObject(parent,name)
+{
+ p_ktechlab = parent;
+ p_processChain = processChain;
+}
+
+
+Language::~Language()
+{
+}
+
+
+void Language::outputMessage( const QString &message )
+{
+ LanguageManager::self()->slotMessage( message, extractMessageInfo(message) );
+}
+
+
+void Language::outputWarning( const QString &message )
+{
+ LanguageManager::self()->slotWarning( message, extractMessageInfo(message) );
+}
+
+
+void Language::outputError( const QString &message )
+{
+ LanguageManager::self()->slotError( message, extractMessageInfo(message) );
+ m_errorCount++;
+}
+
+
+void Language::finish( bool successful )
+{
+ if (successful)
+ {
+ outputMessage(m_successfulMessage + "\n");
+ p_ktechlab->slotChangeStatusbar(m_successfulMessage);
+
+ ProcessOptions::ProcessPath::Path newPath = outputPath( m_processOptions.processPath() );
+
+ if ( newPath == ProcessOptions::ProcessPath::None )
+ emit processSucceeded(this);
+
+ else if (p_processChain)
+ {
+ m_processOptions.setInputFiles( m_processOptions.intermediaryOutput() );
+ m_processOptions.setIntermediaryOutput( m_processOptions.targetFile() );
+ m_processOptions.setProcessPath(newPath);
+// p_processChain->compile(m_processOptions);
+ p_processChain->setProcessOptions(m_processOptions);
+ p_processChain->compile();
+ }
+ }
+ else
+ {
+ outputError(m_failedMessage + "\n");
+ p_ktechlab->slotChangeStatusbar(m_failedMessage);
+ emit processFailed(this);
+ return;
+ }
+}
+
+
+void Language::reset()
+{
+ m_errorCount = 0;
+}
+
+
+MessageInfo Language::extractMessageInfo( const QString &text )
+{
+ if ( !text.startsWith("/") )
+ return MessageInfo();
+
+ const int index = text.find( ":", 0, false );
+ if ( index == -1 )
+ return MessageInfo();
+ const QString fileName = text.left(index);
+
+ // Extra line number
+ const QString message = text.right(text.length()-index);
+ const int linePos = message.find( QRegExp(":[\\d]+") );
+ int line = -1;
+ if ( linePos != -1 )
+ {
+ const int linePosEnd = message.find( ':', linePos+1 );
+ if ( linePosEnd != -1 )
+ {
+ const QString number = message.mid( linePos+1, linePosEnd-linePos-1 ).stripWhiteSpace();
+ bool ok;
+ line = number.toInt(&ok)-1;
+ if (!ok) line = -1;
+ }
+ }
+ return MessageInfo( fileName, line );
+}
+//END class Language
+
+
+
+//BEGIN class ProcessOptionsSpecial
+ProcessOptionsSpecial::ProcessOptionsSpecial()
+{
+ m_bOutputMapFile = true;
+ b_forceList = true;
+ b_addToProject = ProjectManager::self()->currentProject();
+
+ p_flowCodeDocument = 0l;
+
+ switch ( KTLConfig::hexFormat() )
+ {
+ case KTLConfig::EnumHexFormat::inhx8m:
+ m_hexFormat = "inhx8m";
+ break;
+
+ case KTLConfig::EnumHexFormat::inhx8s:
+ m_hexFormat = "inhx8s";
+ break;
+
+ case KTLConfig::EnumHexFormat::inhx16:
+ m_hexFormat = "inhx16";
+ break;
+
+ case KTLConfig::EnumHexFormat::inhx32:
+ default:
+ m_hexFormat = "inhx32";
+ break;
+ }
+}
+//END class ProcessOptionsSpecial
+
+
+//BEGIN class ProcessOptions
+ProcessOptions::ProcessOptions()
+{
+ m_pHelper = new ProcessOptionsHelper;
+
+ b_targetFileSet = false;
+ m_pTextOutputTarget = 0l;
+}
+
+
+ProcessOptions::ProcessOptions( OutputMethodInfo info )
+{
+ m_pHelper = new ProcessOptionsHelper;
+
+ b_addToProject = info.addToProject();
+ m_picID = info.picID();
+ b_targetFileSet = false;
+
+ QString target;
+ if ( !KIO::NetAccess::download( info.outputFile(), target, 0l ) )
+ {
+ // If the file could not be downloaded, for example does not
+ // exist on disk, NetAccess will tell us what error to use
+ KMessageBox::error( 0l, KIO::NetAccess::lastErrorString() );
+
+ return;
+ }
+ setTargetFile(target);
+
+ switch ( info.method() )
+ {
+ case OutputMethodInfo::Method::Direct:
+ m_method = Method::LoadAsNew;
+ break;
+
+ case OutputMethodInfo::Method::SaveAndForget:
+ m_method = Method::Forget;
+ break;
+
+ case OutputMethodInfo::Method::SaveAndLoad:
+ m_method = Method::Load;
+ break;
+ }
+}
+
+
+void ProcessOptions::setTextOutputTarget( TextDocument * target, QObject * receiver, const char * slot )
+{
+ m_pTextOutputTarget = target;
+ QObject::connect( m_pHelper, SIGNAL(textOutputtedTo( TextDocument* )), receiver, slot );
+}
+
+
+void ProcessOptions::setTextOutputtedTo( TextDocument * outputtedTo )
+{
+ m_pTextOutputTarget = outputtedTo;
+ emit m_pHelper->textOutputtedTo( m_pTextOutputTarget );
+}
+
+
+void ProcessOptions::setTargetFile( const QString &file )
+{
+ if (b_targetFileSet)
+ {
+ kdWarning() << "Trying to reset target file!"<<endl;
+ return;
+ }
+ m_targetFile = file;
+ m_intermediaryFile = file;
+ b_targetFileSet = true;
+}
+
+
+ProcessOptions::ProcessPath::MediaType ProcessOptions::guessMediaType( const QString & url )
+{
+ QString extension = url.right( url.length() - url.findRev('.') - 1 );
+ extension = extension.lower();
+
+ if ( extension == "asm" )
+ {
+ // We'll have to look at the file contents to determine its type...
+ AsmParser p( url );
+ p.parse();
+ switch ( p.type() )
+ {
+ case AsmParser::Relocatable:
+ return ProcessPath::AssemblyRelocatable;
+
+ case AsmParser::Absolute:
+ return ProcessPath::AssemblyAbsolute;
+ }
+ }
+
+ if ( extension == "c" )
+ return ProcessPath::C;
+
+ if ( extension == "flowcode" )
+ return ProcessPath::FlowCode;
+
+ if ( extension == "a" || extension == "lib" )
+ return ProcessPath::Library;
+
+ if ( extension == "microbe" || extension == "basic" )
+ return ProcessPath::Microbe;
+
+ if ( extension == "o" )
+ return ProcessPath::Object;
+
+ if ( extension == "hex" )
+ return ProcessPath::Program;
+
+ return ProcessPath::Unknown;
+}
+
+
+ProcessOptions::ProcessPath::Path ProcessOptions::ProcessPath::path( MediaType from, MediaType to )
+{
+ switch (from)
+ {
+ case AssemblyAbsolute:
+ switch (to)
+ {
+ case AssemblyAbsolute:
+ return None;
+ case Pic:
+ return AssemblyAbsolute_PIC;
+ case Program:
+ return AssemblyAbsolute_Program;
+
+ case AssemblyRelocatable:
+ case C:
+ case Disassembly:
+ case FlowCode:
+ case Library:
+ case Microbe:
+ case Object:
+ case Unknown:
+ return Invalid;
+ }
+
+ case AssemblyRelocatable:
+ switch (to)
+ {
+ case Library:
+ return AssemblyRelocatable_Library;
+ case Object:
+ return AssemblyRelocatable_Object;
+ case Pic:
+ return AssemblyRelocatable_PIC;
+ case Program:
+ return AssemblyRelocatable_Program;
+
+ case AssemblyAbsolute:
+ case AssemblyRelocatable:
+ case C:
+ case Disassembly:
+ case FlowCode:
+ case Microbe:
+ case Unknown:
+ return Invalid;
+ }
+
+ case C:
+ switch (to)
+ {
+ case AssemblyRelocatable:
+ return C_AssemblyRelocatable;
+ case Library:
+ return C_Library;
+ case Object:
+ return C_Object;
+ case Pic:
+ return C_PIC;
+ case Program:
+ return C_Program;
+
+ case AssemblyAbsolute:
+ case C:
+ case Disassembly:
+ case FlowCode:
+ case Microbe:
+ case Unknown:
+ return Invalid;
+ }
+
+ case Disassembly:
+ return Invalid;
+
+ case FlowCode:
+ switch (to)
+ {
+ case AssemblyAbsolute:
+ return FlowCode_AssemblyAbsolute;
+ case Microbe:
+ return FlowCode_Microbe;
+ case Pic:
+ return FlowCode_PIC;
+ case Program:
+ return FlowCode_Program;
+
+ case AssemblyRelocatable:
+ case C:
+ case Disassembly:
+ case FlowCode:
+ case Library:
+ case Object:
+ case Unknown:
+ return Invalid;
+ }
+
+ case Library:
+ return Invalid;
+
+ case Microbe:
+ switch (to)
+ {
+ case AssemblyAbsolute:
+ return Microbe_AssemblyAbsolute;
+ case Pic:
+ return Microbe_PIC;
+ case Program:
+ return Microbe_Program;
+
+ case AssemblyRelocatable:
+ case C:
+ case Disassembly:
+ case FlowCode:
+ case Library:
+ case Microbe:
+ case Object:
+ case Unknown:
+ return Invalid;
+ }
+
+ case Object:
+ switch (to)
+ {
+ case Disassembly:
+ return Object_Disassembly;
+ case Library:
+ return Object_Library;
+ case Pic:
+ return Object_PIC;
+ case Program:
+ return Object_Program;
+
+ case AssemblyAbsolute:
+ case AssemblyRelocatable:
+ case C:
+ case FlowCode:
+ case Microbe:
+ case Object:
+ case Unknown:
+ return Invalid;
+ }
+
+ case Pic:
+ return Invalid;
+
+ case Program:
+ switch (to)
+ {
+ case Disassembly:
+ return Program_Disassembly;
+ case Pic:
+ return Program_PIC;
+
+ case AssemblyAbsolute:
+ case AssemblyRelocatable:
+ case C:
+ case FlowCode:
+ case Library:
+ case Microbe:
+ case Object:
+ case Program:
+ case Unknown:
+ return Invalid;
+ }
+
+ case Unknown:
+ return Invalid;
+ }
+
+ return Invalid;
+}
+
+
+ProcessOptions::ProcessPath::MediaType ProcessOptions::ProcessPath::from( Path path )
+{
+ switch (path)
+ {
+ case ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessPath::AssemblyAbsolute_Program:
+ return AssemblyAbsolute;
+
+ case ProcessPath::AssemblyRelocatable_Library:
+ case ProcessPath::AssemblyRelocatable_Object:
+ case ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessPath::AssemblyRelocatable_Program:
+ return AssemblyRelocatable;
+
+ case ProcessPath::C_AssemblyRelocatable:
+ case ProcessPath::C_Library:
+ case ProcessPath::C_Object:
+ case ProcessPath::C_PIC:
+ case ProcessPath::C_Program:
+ return C;
+
+ case ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessPath::FlowCode_Microbe:
+ case ProcessPath::FlowCode_PIC:
+ case ProcessPath::FlowCode_Program:
+ return FlowCode;
+
+ case ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessPath::Microbe_PIC:
+ case ProcessPath::Microbe_Program:
+ return Microbe;
+
+ case ProcessPath::Object_Disassembly:
+ case ProcessPath::Object_Library:
+ case ProcessPath::Object_PIC:
+ case ProcessPath::Object_Program:
+ return Object;
+
+ case ProcessPath::PIC_AssemblyAbsolute:
+ return Pic;
+
+ case ProcessPath::Program_Disassembly:
+ case ProcessPath::Program_PIC:
+ return Program;
+
+ case ProcessPath::Invalid:
+ case ProcessPath::None:
+ return Unknown;
+ }
+
+ return Unknown;
+}
+
+
+ProcessOptions::ProcessPath::MediaType ProcessOptions::ProcessPath::to( Path path )
+{
+ switch (path)
+ {
+ case ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessPath::PIC_AssemblyAbsolute:
+ return AssemblyAbsolute;
+
+ case ProcessPath::C_AssemblyRelocatable:
+ return AssemblyRelocatable;
+
+ case ProcessPath::Object_Disassembly:
+ case ProcessPath::Program_Disassembly:
+ return Disassembly;
+
+ case ProcessPath::AssemblyRelocatable_Library:
+ case ProcessPath::C_Library:
+ case ProcessPath::Object_Library:
+ return Library;
+
+ case ProcessPath::FlowCode_Microbe:
+ return Microbe;
+
+ case ProcessPath::AssemblyRelocatable_Object:
+ case ProcessPath::C_Object:
+ return Object;
+
+ case ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessPath::C_PIC:
+ case ProcessPath::FlowCode_PIC:
+ case ProcessPath::Microbe_PIC:
+ case ProcessPath::Object_PIC:
+ case ProcessPath::Program_PIC:
+ return Pic;
+
+ case ProcessPath::AssemblyAbsolute_Program:
+ case ProcessPath::AssemblyRelocatable_Program:
+ case ProcessPath::C_Program:
+ case ProcessPath::FlowCode_Program:
+ case ProcessPath::Microbe_Program:
+ case ProcessPath::Object_Program:
+ return Program;
+
+ case ProcessPath::Invalid:
+ case ProcessPath::None:
+ return Unknown;
+ }
+
+ return Unknown;
+}
+//END class ProcessOptions
+
+
+#include "language.moc"
diff --git a/src/languages/language.h b/src/languages/language.h
new file mode 100644
index 0000000..68ef187
--- /dev/null
+++ b/src/languages/language.h
@@ -0,0 +1,268 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef LANGUAGE_H
+#define LANGUAGE_H
+
+#include <qobject.h>
+#include <qstringlist.h>
+
+class FlowCodeDocument;
+class KTechlab;
+class LogView;
+class MessageInfo;
+class MicroSettings;
+class OutputMethodInfo;
+class ProcessChain;
+class ProcessOptions;
+class TextDocument;
+class QProcess;
+
+typedef QValueList<ProcessOptions> ProcessOptionsList;
+
+class ProcessOptionsSpecial
+{
+ public:
+ ProcessOptionsSpecial();
+
+ bool b_addToProject;
+ bool b_forceList;
+ QString m_picID;
+ FlowCodeDocument * p_flowCodeDocument;
+
+ // Linking
+ QString m_hexFormat;
+ bool m_bOutputMapFile;
+ QString m_libraryDir;
+ QString m_linkerScript;
+ QStringList m_linkLibraries;
+ QString m_linkOther;
+
+ // Programming
+ QString m_port;
+ QString m_program;
+};
+
+
+class ProcessOptionsHelper : public QObject
+{
+ Q_OBJECT
+#define protected public
+ signals:
+#undef protected
+ void textOutputtedTo( TextDocument * outputtedTo );
+};
+
+
+class ProcessOptions : public ProcessOptionsSpecial
+{
+ public:
+ ProcessOptions();
+ ProcessOptions( OutputMethodInfo info );
+
+ class ProcessPath { public:
+ enum MediaType
+ {
+ AssemblyAbsolute,
+ AssemblyRelocatable,
+ C,
+ Disassembly,
+ FlowCode,
+ Library,
+ Microbe,
+ Object,
+ Pic,
+ Program,
+
+ Unknown // Used for guessing the media type
+ };
+
+ enum Path // From_To // processor that will be invoked first
+ {
+ AssemblyAbsolute_PIC, // gpasm (indirect)
+ AssemblyAbsolute_Program, // gpasm (direct)
+
+ AssemblyRelocatable_Library, // gpasm (indirect)
+ AssemblyRelocatable_Object, // gpasm (direct)
+ AssemblyRelocatable_PIC, // gpasm (indirect)
+ AssemblyRelocatable_Program, // gpasm (indirect)
+
+ C_AssemblyRelocatable, // sdcc (direct)
+ C_Library, // sdcc (indirect)
+ C_Object, // sdcc (indirect)
+ C_PIC, // sdcc (indirect)
+ C_Program, // sdcc (indirect)
+
+ FlowCode_AssemblyAbsolute, // flowcode (indirect)
+ FlowCode_Microbe, // flowcode (direct)
+ FlowCode_PIC, // flowcode (indirect)
+ FlowCode_Program, // flowcode (indirect)
+
+ Microbe_AssemblyAbsolute, // microbe (direct)
+ Microbe_PIC, // microbe (indirect)
+ Microbe_Program, // microbe (indirect)
+
+ Object_Disassembly, // gpdasm (direct)
+ Object_Library, // gplib (direct)
+ Object_PIC, // gplink (indirect)
+ Object_Program, // gplink (direct)
+
+ PIC_AssemblyAbsolute, // download from pic (direct)
+
+ Program_Disassembly, // gpdasm (direct)
+ Program_PIC, // upload to pic (direct)
+
+ Invalid, // From and to types are incompatible
+ None // From and to types are the same
+ };
+
+ static Path path( MediaType from, MediaType to );
+ static MediaType from( Path path );
+ static MediaType to( Path path );
+ };
+
+ class Method
+ {
+ public: enum type
+ {
+ Forget, // Don't do anything after processing successfully
+ LoadAsNew, // Load the output as a new file
+ Load // Load the output file
+ };
+ };
+
+ /**
+ * Tries to guess the media type from the url (and possible the contents
+ * of the file as well).
+ */
+ static ProcessPath::MediaType guessMediaType( const QString & url );
+ /**
+ * The *final* target file (not any intermediatary ones)
+ */
+ QString targetFile() const { return m_targetFile; }
+ /**
+ * This sets the final target file, as well as the initial intermediatary one
+ */
+ void setTargetFile( const QString &file );
+
+ void setIntermediaryOutput( const QString &file ) { m_intermediaryFile = file; }
+ QString intermediaryOutput() const { return m_intermediaryFile; }
+
+ void setInputFiles( const QStringList & files ) { m_inputFiles = files; }
+ QStringList inputFiles() const { return m_inputFiles; }
+
+ void setMethod( Method::type method ) { m_method = method; }
+ Method::type method() const { return m_method; }
+
+ void setProcessPath( ProcessPath::Path path ) { m_processPath = path; }
+ ProcessPath::Path processPath() const { return m_processPath; }
+
+ /**
+ * If the output is text; If the user has selected (in config options)
+ * ReuseSameViewForOutput, then the given TextDocument will have its
+ * text set to the output if the TextDocument is not modified and has
+ * an empty url. Otherwise a new TextDocument will be created. Either
+ * way, once the the processing has finished, a signal will be emitted
+ * to the given receiver passing a TextDocument * as an argument. This
+ * is not to be confused with setTextOutputtedTo, which is called once
+ * the processing has finished, and will call-back to the slot given.
+ */
+ void setTextOutputTarget( TextDocument * target, QObject * receiver, const char * slot );
+ /**
+ * @see setTextOutputTarget
+ */
+ TextDocument * textOutputTarget() const { return m_pTextOutputTarget; }
+ /**
+ * @see setTextOuputTarget
+ */
+ void setTextOutputtedTo( TextDocument * outputtedTo );
+
+ protected:
+ TextDocument * m_pTextOutputTarget;
+ ProcessOptionsHelper * m_pHelper;
+ bool b_targetFileSet;
+ QStringList m_inputFiles;
+ QString m_targetFile;
+ QString m_intermediaryFile;
+ Method::type m_method;
+ ProcessPath::Path m_processPath;
+};
+
+
+/**
+@author Daniel Clarke
+@author David Saxton
+*/
+class Language : public QObject
+{
+ Q_OBJECT
+ public:
+ Language( ProcessChain *processChain, KTechlab *parent, const QString &name );
+ ~Language();
+
+ /**
+ * Compile / assemble / dissassembly / whatever the given input.
+ * @returns true if processing was started succesfully (this is different to finishing successfuly).
+ */
+ virtual void processInput( ProcessOptions options ) = 0;
+ /**
+ * Return the ProcessOptions object current state
+ */
+ ProcessOptions processOptions() const { return m_processOptions; }
+ /**
+ * Return the output path from the given input path. Will return None
+ * if we've done processing.
+ */
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const = 0;
+
+ signals:
+ /**
+ * Emitted when the processing was successful.
+ * @param language Pointer to this class
+ */
+ void processSucceeded( Language *language );
+ /**
+ * Emitted when the processing failed.
+ * @param language Pointer to this class
+ */
+ void processFailed( Language *language );
+
+ protected:
+ /**
+ * Examines the string for the line number if applicable, and creates a new
+ * MessageInfo for it.
+ */
+ virtual MessageInfo extractMessageInfo( const QString &text );
+
+ /**
+ * Reset the error count
+ */
+ void reset();
+ void outputMessage( const QString &message );
+ void outputWarning( const QString &message );
+ void outputError( const QString &error );
+ void finish( bool successful );
+
+ int m_errorCount;
+ KTechlab *p_ktechlab;
+ ProcessOptions m_processOptions;
+ ProcessChain *p_processChain;
+
+ /**
+ * A message appropriate to the language's success after compilation or similar.
+ */
+ QString m_successfulMessage;
+ /**
+ * A message appropriate to the language's failure after compilation or similar.
+ */
+ QString m_failedMessage;
+};
+
+#endif
diff --git a/src/languages/languagemanager.cpp b/src/languages/languagemanager.cpp
new file mode 100644
index 0000000..a6dddd8
--- /dev/null
+++ b/src/languages/languagemanager.cpp
@@ -0,0 +1,108 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "docmanager.h"
+#include "languagemanager.h"
+#include "logview.h"
+#include "ktechlab.h"
+#include "ktempfile.h"
+#include "src/core/ktlconfig.h"
+#include "outputmethoddlg.h"
+#include "processchain.h"
+#include "projectmanager.h"
+
+#include "microbe.h"
+#include "gpasm.h"
+#include "gpdasm.h"
+
+#include <kdockwidget.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <qwhatsthis.h>
+
+#include <assert.h>
+
+
+LanguageManager * LanguageManager::m_pSelf = 0l;
+
+
+LanguageManager * LanguageManager::self( KateMDI::ToolView * parent, KTechlab * ktl )
+{
+ if (!m_pSelf)
+ {
+ assert(parent);
+ assert(ktl);
+ m_pSelf = new LanguageManager( parent, ktl );
+ }
+ return m_pSelf;
+}
+
+
+LanguageManager::LanguageManager( KateMDI::ToolView * parent, KTechlab * ktl )
+ : QObject((QObject*)ktl)
+{
+ p_ktechlab = ktl;
+ m_logView = new LogView( parent, "LanguageManager LogView");
+
+ QWhatsThis::add( m_logView, i18n("These messages show the output of language-related functionality such as compiling and assembling.<br><br>For error messages, clicking on the line will automatically open up the file at the position of the error.") );
+ connect( m_logView, SIGNAL(paraClicked(const QString&, MessageInfo )), this, SLOT(slotParaClicked(const QString&, MessageInfo )) );
+ reset();
+}
+
+
+LanguageManager::~LanguageManager()
+{
+}
+
+
+void LanguageManager::reset()
+{
+ m_logView->clear();
+}
+
+
+ProcessChain * LanguageManager::compile( ProcessOptions options )
+{
+ if ( KTLConfig::raiseMessagesLog() )
+ p_ktechlab->showToolView( p_ktechlab->toolView( toolViewIdentifier() ) );
+
+ return new ProcessChain( options, p_ktechlab );
+}
+
+
+ProcessListChain * LanguageManager::compile( ProcessOptionsList pol )
+{
+ if ( KTLConfig::raiseMessagesLog() )
+ p_ktechlab->showToolView( p_ktechlab->toolView( toolViewIdentifier() ) );
+
+ return new ProcessListChain( pol, p_ktechlab );
+}
+
+
+void LanguageManager::slotError( const QString &error, MessageInfo messageInfo )
+{
+ m_logView->addOutput( error, LogView::ot_error, messageInfo );
+}
+void LanguageManager::slotWarning( const QString &error, MessageInfo messageInfo )
+{
+ m_logView->addOutput( error, LogView::ot_warning, messageInfo );
+}
+void LanguageManager::slotMessage( const QString &error, MessageInfo messageInfo )
+{
+ m_logView->addOutput( error, LogView::ot_message, messageInfo );
+}
+
+void LanguageManager::slotParaClicked( const QString& message, MessageInfo messageInfo )
+{
+ Q_UNUSED(message);
+ DocManager::self()->gotoTextLine( messageInfo.fileURL(), messageInfo.fileLine() );
+}
+
+#include "languagemanager.moc"
diff --git a/src/languages/languagemanager.h b/src/languages/languagemanager.h
new file mode 100644
index 0000000..c5bda98
--- /dev/null
+++ b/src/languages/languagemanager.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef LANGUAGEMANAGER_H
+#define LANGUAGEMANAGER_H
+
+#include <qobject.h>
+#include <qvaluelist.h>
+
+#include "language.h"
+
+class FlowCode;
+class Gpasm;
+class Gpdasm;
+class KTechlab;
+class Language;
+class LanguageManager;
+class LogView;
+class MessageInfo;
+class Microbe;
+class ProcessChain;
+class ProcessListChain;
+class ProcessOptions;
+namespace KateMDI { class ToolView; }
+
+/**
+@author David Saxton
+*/
+class LanguageManager : public QObject
+{
+ Q_OBJECT
+ public:
+ static LanguageManager * self( KateMDI::ToolView * parent = 0l, KTechlab * ktl = 0l );
+ static QString toolViewIdentifier() { return "LanguageManager"; }
+ ~LanguageManager();
+
+ /**
+ * Call to compile a file of one type all the way to another type, this can
+ * also be used in reverse to disassemble code. Connect to the returned
+ * ProcessChain for notification of compile success / failure
+ * @return Pointer to the ProcessChain used to compile
+ */
+ ProcessChain * compile( ProcessOptions options );
+ ProcessListChain * compile( ProcessOptionsList pol );
+ /**
+ * @return Pointer to the LogView that displays the output messages
+ */
+ LogView * logView() const { return m_logView; }
+ /**
+ * Clear any errors and clear the log view
+ */
+ void reset();
+
+ public slots:
+ /**
+ * Called when the user clicks on any text in the LogView
+ */
+ void slotParaClicked( const QString& message, MessageInfo messageInfo );
+ /**
+ * Called by languages to report an error message
+ * @param error Error message to report
+ */
+ void slotError( const QString &error, MessageInfo messageInfo );
+ /**
+ * Called by languages to report a warning message
+ * @param warning Warning message to report
+ */
+ void slotWarning( const QString &warning, MessageInfo messageInfo );
+ /**
+ * Called by languages to report a general message
+ * @param message General message to report
+ */
+ void slotMessage( const QString &message, MessageInfo messageInfo );
+
+ protected:
+ LanguageManager( KateMDI::ToolView * parent, KTechlab * ktl );
+
+ private:
+ LogView * m_logView;
+ static LanguageManager * m_pSelf;
+ KTechlab * p_ktechlab;
+};
+
+#endif
diff --git a/src/languages/microbe.cpp b/src/languages/microbe.cpp
new file mode 100644
index 0000000..628b3c1
--- /dev/null
+++ b/src/languages/microbe.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "contexthelp.h"
+#include "docmanager.h"
+#include "logview.h"
+#include "microbe.h"
+#include "languagemanager.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+
+#include <qfile.h>
+#include <kprocess.h>
+
+Microbe::Microbe( ProcessChain *processChain, KTechlab *parent )
+ : ExternalLanguage( processChain, parent, "Microbe" )
+{
+ m_failedMessage = i18n("*** Compilation failed ***");
+ m_successfulMessage = i18n("*** Compilation successful ***");
+
+ // Setup error messages list
+ QFile file( locate("appdata",i18n("error_messages_en_gb")) );
+ if ( file.open( IO_ReadOnly ) )
+ {
+ QTextStream stream( &file );
+ QString line;
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n'
+ if ( !line.isEmpty() )
+ {
+ bool ok;
+ const int pos = line.left( line.find("#") ).toInt(&ok);
+ if (ok) {
+ m_errorMessages[pos] = line.right(line.length()-line.find("#"));
+ } else {
+ kdError() << k_funcinfo << "Error parsing Microbe error-message file"<<endl;
+ }
+ }
+ }
+ file.close();
+ }
+}
+
+Microbe::~Microbe()
+{
+}
+
+
+void Microbe::processInput( ProcessOptions options )
+{
+ resetLanguageProcess();
+ m_processOptions = options;
+
+ *m_languageProcess << ("microbe");
+
+ // Input Asm file
+ *m_languageProcess << ( options.inputFiles().first() );
+
+ // Output filename
+ *m_languageProcess << ( options.intermediaryOutput() );
+
+ *m_languageProcess << ("--show-source");
+
+ if ( !start() )
+ {
+ KMessageBox::sorry( LanguageManager::self()->logView(), i18n("Assembly failed. Please check you have KTechlab installed properly (\"microbe\" could not be started).") );
+ processInitFailed();
+ return;
+ }
+}
+
+
+bool Microbe::isError( const QString &message ) const
+{
+ return message.contains( "Error", false );
+}
+
+bool Microbe::isWarning( const QString &message ) const
+{
+ return message.contains( "Warning", false );
+}
+
+
+ProcessOptions::ProcessPath::Path Microbe::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ return ProcessOptions::ProcessPath::AssemblyAbsolute_PIC;
+
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ return ProcessOptions::ProcessPath::AssemblyAbsolute_Program;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C_Library:
+ case ProcessOptions::ProcessPath::C_Object:
+ case ProcessOptions::ProcessPath::C_PIC:
+ case ProcessOptions::ProcessPath::C_Program:
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Object_Library:
+ case ProcessOptions::ProcessPath::Object_PIC:
+ case ProcessOptions::ProcessPath::Object_Program:
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
diff --git a/src/languages/microbe.h b/src/languages/microbe.h
new file mode 100644
index 0000000..568db4b
--- /dev/null
+++ b/src/languages/microbe.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef MICROBE_H
+#define MICROBE_H
+
+#include "externallanguage.h"
+
+#include <qmap.h>
+
+typedef QMap< int, QString > ErrorMap;
+
+/**
+@author Daniel Clarke
+@author David Saxton
+*/
+class Microbe : public ExternalLanguage
+{
+public:
+ Microbe( ProcessChain *processChain, KTechlab *parent );
+ ~Microbe();
+
+ virtual void processInput( ProcessOptions options );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+protected:
+ virtual bool isError( const QString &message ) const;
+ virtual bool isWarning( const QString &message ) const;
+
+ ErrorMap m_errorMessages;
+};
+
+#endif
diff --git a/src/languages/picprogrammer.cpp b/src/languages/picprogrammer.cpp
new file mode 100644
index 0000000..6f5e76f
--- /dev/null
+++ b/src/languages/picprogrammer.cpp
@@ -0,0 +1,456 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "languagemanager.h"
+#include "picprogrammer.h"
+#include "src/core/ktlconfig.h"
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+#include <qapplication.h>
+#include <qfile.h>
+#include <kprocess.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+#include <qdatetime.h>
+
+#include <stdio.h>
+
+//BEGIN class ProgrammerConfig
+ProgrammerConfig::ProgrammerConfig()
+{
+}
+
+
+void ProgrammerConfig::reset()
+{
+ initCommand = QString::null;
+ readCommand = QString::null;
+ writeCommand = QString::null;
+ verifyCommand = QString::null;
+ blankCheckCommand = QString::null;
+ eraseCommand = QString::null;
+}
+//END class ProgrammerConfig
+
+
+
+//BEGIN class PicProgrammerSettings
+bool PicProgrammerSettings::m_bDoneStaticConfigsInit = false;
+ProgrammerConfigMap PicProgrammerSettings::m_staticConfigs = ProgrammerConfigMap();
+
+
+PicProgrammerSettings::PicProgrammerSettings()
+{
+ if ( !m_bDoneStaticConfigsInit )
+ initStaticConfigs();
+}
+
+
+void PicProgrammerSettings::initStaticConfigs()
+{
+ m_bDoneStaticConfigsInit = true;
+ ProgrammerConfig config;
+
+ config.description = i18n("Supported programmers: %1").arg("JuPic, PICStart Plus, Warp-13");
+ config.description += i18n("<br>Interface: Serial Port");
+ config.initCommand = "";
+ config.readCommand = "picp %port %device -rp %file";
+ config.writeCommand = "picp %port %device -wp %file";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "picp %port %device -b";
+ config.eraseCommand = "picp %port %device -e";
+// config.executable = "picp";
+ m_staticConfigs[ "PICP" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("Epic Plus");
+ config.description += i18n("<br>Interface: Parallel Port");
+ config.initCommand = "odyssey init";
+ config.readCommand = "odyssey %device read %file";
+ config.writeCommand = "odyssey %device write %file";
+ config.verifyCommand = "odyssey %device verify %file";
+ config.blankCheckCommand = "odyssey %device blankcheck";
+ config.eraseCommand = "odyssey %device erase";
+// config.executable = "odyssey";
+ m_staticConfigs[ "Odyssey" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("JDM PIC-Programmer 2, PIC-PG2C");
+ config.description += i18n("<br>Interface: Serial Port");
+ config.initCommand = "";
+ config.readCommand = "picprog --output %file --pic %port";
+ config.writeCommand = "picprog --burn --input %file --pic %port --device %device";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "picprog --erase --pic %device";
+ m_staticConfigs[ "PICProg" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("Epic Plus");
+ config.description += i18n("<br>Interface: Parallel Port");
+ config.initCommand = "";
+ config.readCommand = "dump84 --dump-all --output=%file";
+ config.writeCommand = "prog84 --intel16=%file";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "prog84 --clear";
+ m_staticConfigs[ "prog84" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("Kit 149, Kit 150");
+ config.description += i18n("<br>Interface: USB Port");
+ config.initCommand = "";
+ config.readCommand = "pp -d %device -r %file";
+ config.writeCommand = "pp -d %device -w %file";
+ config.verifyCommand = "pp -d %device -v %file";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "pp -d %device -e";
+ m_staticConfigs[ "PP" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("Wisp628");
+ config.description += i18n("<br>Interface: Serial Port");
+ config.initCommand = "";
+ config.readCommand = "xwisp ID %device PORT %device DUMP";
+ config.writeCommand = "xwisp ID %device PORT %device WRITE %file";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "xwisp ID %device PORT %device ERASE";
+ m_staticConfigs[ "XWisp" ] = config;
+
+
+#if 0
+ config.description = i18n("Supported programmers: %1").arg("Epic Plus, JDM PIC-Programmer 2, PICCOLO, PICCOLO Grande, Trivial HVP Programmer");
+ config.description += i18n("<br>Interface: Serial Port and Parallel Port");
+ config.initCommand = "";
+ config.readCommand = "";
+ config.writeCommand = "";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "";
+ config.executable = "pkp";
+ m_staticConfigs[ "PiKdev" ] = config;
+ config.executable = "";
+
+
+ config.description = i18n("Supported programmers: %1").arg("Trivial LVP programmer, Trivial HVP Programmer");
+ config.description += i18n("<br>Interface: Parallel Port");
+ config.initCommand = "";
+ config.readCommand = "";
+ config.writeCommand = "";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "";
+ m_staticConfigs[ "PicPrg2" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("El Cheapo");
+ config.description += i18n("<br>Interface: Parallel Port");
+ config.initCommand = "";
+ config.readCommand = "";
+ config.writeCommand = "";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "";
+ m_staticConfigs[ "PP06" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("NOPPP");
+ config.description += i18n("<br>Interface: Parallel Port");
+ config.initCommand = "";
+ config.readCommand = "";
+ config.writeCommand = "";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "";
+ m_staticConfigs[ "NOPPP" ] = config;
+
+
+ config.description = i18n("Supported programmers: %1").arg("SNOPPP");
+ config.description += i18n("<br>Interface: Parallel Port");
+ config.initCommand = "";
+ config.readCommand = "";
+ config.writeCommand = "";
+ config.verifyCommand = "";
+ config.blankCheckCommand = "";
+ config.eraseCommand = "";
+ m_staticConfigs[ "SNOPPP" ] = config;
+#endif
+}
+
+
+void PicProgrammerSettings::load( KConfig * config )
+{
+ QStringList oldCustomProgrammers = config->groupList().grep("CustomProgrammer_");
+ QStringList::iterator ocpEnd = oldCustomProgrammers.end();
+ for ( QStringList::iterator it = oldCustomProgrammers.begin(); it != ocpEnd; ++it )
+ {
+ // The CustomProgrammer_ string we searched for might appear half way through... (don't want)
+ if ( (*it).startsWith("CustomProgrammer_") )
+ {
+ config->setGroup(*it);
+
+ ProgrammerConfig pc;
+ pc.initCommand = config->readEntry( "InitCommand" );
+ pc.readCommand = config->readEntry( "ReadCommand" );
+ pc.writeCommand = config->readEntry( "WriteCommand" );
+ pc.verifyCommand = config->readEntry( "VerifyCommand" );
+ pc.blankCheckCommand = config->readEntry( "BlankCheckCommand" );
+ pc.eraseCommand = config->readEntry( "EraseCommand" );
+
+ QString name = config->readEntry( "Name" );
+ m_customConfigs[name] = pc;
+ }
+ }
+}
+
+
+void PicProgrammerSettings::save( KConfig * config )
+{
+ QStringList oldCustomProgrammers = config->groupList().grep("CustomProgrammer_");
+ QStringList::iterator ocpEnd = oldCustomProgrammers.end();
+ for ( QStringList::iterator it = oldCustomProgrammers.begin(); it != ocpEnd; ++it )
+ {
+ // The CustomProgrammer_ string we searched for might appear half way through... (don't want)
+ if ( (*it).startsWith("CustomProgrammer_") )
+ config->deleteGroup(*it);
+ }
+
+ int at = 0;
+ ProgrammerConfigMap::iterator end = m_customConfigs.end();
+ for ( ProgrammerConfigMap::iterator it = m_customConfigs.begin(); it != end; ++it )
+ {
+ config->setGroup( QString("CustomProgrammer_%1").arg(at++) );
+
+ config->writeEntry( "Name", it.key() );
+ config->writeEntry( "InitCommand", it.data().initCommand );
+ config->writeEntry( "ReadCommand", it.data().readCommand );
+ config->writeEntry( "WriteCommand", it.data().writeCommand );
+ config->writeEntry( "VerifyCommand", it.data().verifyCommand );
+ config->writeEntry( "BlankCheckCommand", it.data().blankCheckCommand );
+ config->writeEntry( "EraseCommand", it.data().eraseCommand );
+ }
+}
+
+
+ProgrammerConfig PicProgrammerSettings::config( const QString & name )
+{
+ if ( name.isEmpty() )
+ return ProgrammerConfig();
+
+ QString l = name.lower();
+
+ ProgrammerConfigMap::const_iterator end = m_customConfigs.end();
+ for ( ProgrammerConfigMap::const_iterator it = m_customConfigs.begin(); it != end; ++it )
+ {
+ if ( it.key().lower() == l )
+ return *it;
+ }
+
+ end = m_staticConfigs.end();
+ for ( ProgrammerConfigMap::const_iterator it = m_staticConfigs.begin(); it != end; ++it )
+ {
+ if ( it.key().lower() == l )
+ return *it;
+ }
+
+ return m_customConfigs[ name ];
+}
+
+
+void PicProgrammerSettings::removeConfig( const QString & name )
+{
+ if ( isPredefined( name ) )
+ {
+ kdWarning() << k_funcinfo << "Cannot remove a predefined PIC programmer configuration." << endl;
+ return;
+ }
+
+ QString l = name.lower();
+
+ ProgrammerConfigMap::iterator end = m_customConfigs.end();
+ for ( ProgrammerConfigMap::iterator it = m_customConfigs.begin(); it != end; ++it )
+ {
+ if ( it.key().lower() == l )
+ {
+ m_customConfigs.remove( it );
+ return;
+ }
+ }
+}
+
+
+void PicProgrammerSettings::saveConfig( const QString & name, const ProgrammerConfig & config )
+{
+ if ( isPredefined( name ) )
+ {
+ kdWarning() << k_funcinfo << "Cannot save to a predefined PIC programmer configuration." << endl;
+ return;
+ }
+
+ QString l = name.lower();
+
+ ProgrammerConfigMap::iterator end = m_customConfigs.end();
+ for ( ProgrammerConfigMap::iterator it = m_customConfigs.begin(); it != end; ++it )
+ {
+ if ( it.key().lower() == l )
+ {
+ *it = config;
+ return;
+ }
+ }
+
+ m_customConfigs[ name ] = config;
+}
+
+
+QStringList PicProgrammerSettings::configNames( bool makeLowercase ) const
+{
+ if ( !makeLowercase )
+ return m_customConfigs.keys() + m_staticConfigs.keys();
+
+ QStringList names;
+
+ ProgrammerConfigMap::const_iterator end = m_customConfigs.end();
+ for ( ProgrammerConfigMap::const_iterator it = m_customConfigs.begin(); it != end; ++it )
+ names << it.key().lower();
+
+ end = m_staticConfigs.end();
+ for ( ProgrammerConfigMap::const_iterator it = m_staticConfigs.begin(); it != end; ++it )
+ names << it.key().lower();
+
+ return names;
+}
+
+
+bool PicProgrammerSettings::isPredefined( const QString & name ) const
+{
+ QString l = name.lower();
+
+ ProgrammerConfigMap::const_iterator end = m_staticConfigs.end();
+ for ( ProgrammerConfigMap::const_iterator it = m_staticConfigs.begin(); it != end; ++it )
+ {
+ if ( it.key().lower() == l )
+ return true;
+ }
+
+ return false;
+}
+//END class PicProgrammerSettings
+
+
+
+//BEGIN class PicProgrammer
+PicProgrammer::PicProgrammer( ProcessChain *processChain, KTechlab * parent )
+ : ExternalLanguage( processChain, parent, "PicProgrammer" )
+{
+ m_successfulMessage = i18n("*** Programming successful ***");
+ m_failedMessage = i18n("*** Programming failed ***");
+}
+
+
+PicProgrammer::~PicProgrammer()
+{
+}
+
+
+void PicProgrammer::processInput( ProcessOptions options )
+{
+ resetLanguageProcess();
+ m_processOptions = options;
+
+ PicProgrammerSettings settings;
+ settings.load( kapp->config() );
+
+ QString program = options.m_program;
+ if ( !settings.configNames( true ).contains( program.lower() ) )
+ {
+ kdError() << k_funcinfo << "Invalid program" << endl;
+ finish( false );
+ return;
+ }
+
+ ProgrammerConfig config = settings.config( program );
+
+ QString command = config.writeCommand;
+ command.replace( "%port", options.m_port );
+ command.replace( "%device", QString( options.m_picID ).remove("P") );
+ command.replace( "%file", KProcess::quote( options.inputFiles().first() ) );
+
+ m_languageProcess->setUseShell( true );
+ *m_languageProcess << command;
+
+ if ( !start() )
+ {
+// KMessageBox::sorry( LanguageManager::self()->logView(), i18n("Could not program PIC.") );
+ processInitFailed();
+ return;
+ }
+}
+
+
+bool PicProgrammer::isError( const QString &message ) const
+{
+ return message.contains( "Error", false );
+}
+
+
+bool PicProgrammer::isWarning( const QString &message ) const
+{
+ return message.contains( "Warning", false );
+}
+
+
+ProcessOptions::ProcessPath::Path PicProgrammer::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C_Library:
+ case ProcessOptions::ProcessPath::C_Object:
+ case ProcessOptions::ProcessPath::C_PIC:
+ case ProcessOptions::ProcessPath::C_Program:
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Object_Library:
+ case ProcessOptions::ProcessPath::Object_PIC:
+ case ProcessOptions::ProcessPath::Object_Program:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
+//END class PicProgrammer
+
+
diff --git a/src/languages/picprogrammer.h b/src/languages/picprogrammer.h
new file mode 100644
index 0000000..580cf6b
--- /dev/null
+++ b/src/languages/picprogrammer.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef PICPROGRAMMER_H
+#define PICPROGRAMMER_H
+
+#include "externallanguage.h"
+
+
+class KConfig;
+class KProcess;
+
+
+class ProgrammerConfig
+{
+ public:
+ ProgrammerConfig();
+
+ /**
+ * Clears the type and all commands.
+ */
+ void reset();
+
+ QString initCommand;
+ QString readCommand;
+ QString writeCommand;
+ QString verifyCommand;
+ QString blankCheckCommand;
+ QString eraseCommand;
+
+ QString description;
+ QString executable; // The name of the program executable
+};
+
+typedef QMap< QString, ProgrammerConfig > ProgrammerConfigMap;
+
+
+
+/**
+This class provides access to the PIC Programmer configurations. Several are
+predefinied; the rest can be read from and written to, and removed. Names are
+case insensitive.
+
+Each programmer configuration is in the form of the ProgrammerConfig struct.
+
+@author David Saxton
+*/
+class PicProgrammerSettings
+{
+ public:
+ PicProgrammerSettings();
+
+ /**
+ * Reads in custom ProgrammerConfigs from config. Any previously loaded
+ * configurations stored in this class will removed first.
+ */
+ void load( KConfig * config );
+ /**
+ * Saves the custom ProgrammConfigs to config.
+ */
+ void save( KConfig * config );
+ /**
+ * @return the ProgrammConfig for the programmer with the given name. If
+ * no such ProgrammerConfigs with the given name exist, then one will be
+ * created. The name is case insensitive (although the full case of the
+ * name will be stored if a new ProgrammerConfig is created).
+ */
+ ProgrammerConfig config( const QString & name );
+ /**
+ * Removes the config (if it is custom) with the give name.
+ */
+ void removeConfig( const QString & name );
+ /**
+ * Sets the ProgrammerConfig with the given name (or creates one if no
+ * such config exists). The name is case insensitive.
+ */
+ void saveConfig( const QString & name, const ProgrammerConfig & config );
+ /**
+ * @param makeLowercase whether the names should be converted to
+ * lowercase before returning.
+ * @return a list of names of the custom and predefined configs.
+ */
+ QStringList configNames( bool makeLowercase ) const;
+ /**
+ * @return whether the given config is predefined.
+ */
+ bool isPredefined( const QString & name ) const;
+
+ protected:
+ /**
+ * Called when a PicProgrammerSettings object is first created. Does
+ * initialization of the predefined configs.
+ */
+ void initStaticConfigs();
+
+ ProgrammerConfigMap m_customConfigs;
+
+ static bool m_bDoneStaticConfigsInit;
+ static ProgrammerConfigMap m_staticConfigs;
+};
+
+
+/**
+@author David Saxton
+*/
+class PicProgrammer : public ExternalLanguage
+{
+ public:
+ PicProgrammer( ProcessChain *processChain, KTechlab *parent );
+ ~PicProgrammer();
+
+ virtual void processInput( ProcessOptions options );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+ protected:
+ virtual bool isError( const QString &message ) const;
+ virtual bool isWarning( const QString &message ) const;
+};
+
+#endif
diff --git a/src/languages/processchain.cpp b/src/languages/processchain.cpp
new file mode 100644
index 0000000..e17c6ae
--- /dev/null
+++ b/src/languages/processchain.cpp
@@ -0,0 +1,326 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "asmparser.h"
+#include "docmanager.h"
+#include "gplib.h"
+#include "src/core/ktlconfig.h"
+#include "language.h"
+#include "languagemanager.h"
+#include "logview.h"
+#include "outputmethoddlg.h"
+#include "processchain.h"
+#include "projectmanager.h"
+#include "textdocument.h"
+
+#include "flowcode.h"
+#include "gpasm.h"
+#include "gpdasm.h"
+#include "gplink.h"
+#include "microbe.h"
+#include "picprogrammer.h"
+#include "sdcc.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <ktempfile.h>
+#include <qfile.h>
+#include <qtimer.h>
+
+
+//BEGIN class ProcessChain
+ProcessChain::ProcessChain( ProcessOptions options, KTechlab * ktechlab, const char *name )
+ : QObject( (QObject*)ktechlab, name)
+{
+ m_pKTechlab = ktechlab;
+ m_pFlowCode = 0l;
+ m_pGpasm = 0l;
+ m_pGpdasm = 0l;
+ m_pGplib = 0l;
+ m_pGplink = 0l;
+ m_pMicrobe = 0l;
+ m_pPicProgrammer = 0l;
+ m_pSDCC = 0l;
+ m_processOptions = options;
+
+ QString target;
+ if ( ProcessOptions::ProcessPath::to( options.processPath() ) == ProcessOptions::ProcessPath::Pic )
+ target = options.m_picID;
+ else
+ target = options.targetFile();
+
+ LanguageManager::self()->logView()->addOutput( i18n("Building: %1").arg( target ), LogView::ot_important );
+ QTimer::singleShot( 0, this, SLOT(compile()) );
+}
+
+
+ProcessChain::~ProcessChain()
+{
+ delete m_pFlowCode;
+ m_pFlowCode = 0l;
+ delete m_pGpasm;
+ m_pGpasm = 0l;
+ delete m_pGpdasm;
+ m_pGpdasm = 0l;
+ delete m_pGplib;
+ m_pGplib = 0l;
+ delete m_pGplink;
+ m_pGplink = 0l;
+ delete m_pMicrobe;
+ m_pMicrobe = 0l;
+ delete m_pPicProgrammer;
+ m_pPicProgrammer = 0l;
+ delete m_pSDCC;
+ m_pSDCC = 0l;
+}
+
+
+// void ProcessChain::compile( ProcessOptions * options )
+void ProcessChain::compile()
+{
+ // If the micro id in the options is empty, then attempt to get it from any
+ // open project (it might not be necessarily...but won't hurt if it isn't).
+ if ( m_processOptions.m_picID.isEmpty() )
+ {
+ if ( ProjectInfo * projectInfo = ProjectManager::self()->currentProject() )
+ {
+ ProjectItem * projectItem = projectInfo->findItem( m_processOptions.inputFiles().first() );
+ if (projectItem)
+ m_processOptions.m_picID = projectItem->microID();
+ }
+ }
+
+ switch ( m_processOptions.processPath() )
+ {
+#define DIRECT_PROCESS( path, processor ) case ProcessOptions::ProcessPath::path: { processor()->processInput(m_processOptions); break; }
+#define INDIRECT_PROCESS( path, processor, extension ) case ProcessOptions::ProcessPath::path: { KTempFile f( QString::null, extension ); f.close(); m_processOptions.setIntermediaryOutput( f.name() ); processor()->processInput(m_processOptions); break; }
+
+ INDIRECT_PROCESS( AssemblyAbsolute_PIC, gpasm, ".hex" )
+ DIRECT_PROCESS( AssemblyAbsolute_Program, gpasm )
+ INDIRECT_PROCESS( AssemblyRelocatable_Library, gpasm, ".o" )
+ DIRECT_PROCESS( AssemblyRelocatable_Object, gpasm )
+ INDIRECT_PROCESS( AssemblyRelocatable_PIC, gpasm, ".o" )
+ INDIRECT_PROCESS( AssemblyRelocatable_Program, gpasm, ".o" )
+ DIRECT_PROCESS( C_AssemblyRelocatable, sdcc )
+ INDIRECT_PROCESS( C_Library, sdcc, ".asm" )
+ INDIRECT_PROCESS( C_Object, sdcc, ".asm" )
+ INDIRECT_PROCESS( C_PIC, sdcc, ".asm" )
+ INDIRECT_PROCESS( C_Program, sdcc, ".asm" )
+ INDIRECT_PROCESS( FlowCode_AssemblyAbsolute, flowCode, ".microbe" )
+ DIRECT_PROCESS( FlowCode_Microbe, flowCode )
+ INDIRECT_PROCESS( FlowCode_PIC, flowCode, ".microbe" )
+ INDIRECT_PROCESS( FlowCode_Program, flowCode, ".microbe" )
+ DIRECT_PROCESS( Microbe_AssemblyAbsolute, microbe )
+ INDIRECT_PROCESS( Microbe_PIC, microbe, ".asm" )
+ INDIRECT_PROCESS( Microbe_Program, microbe, ".asm" )
+ DIRECT_PROCESS( Object_Disassembly, gpdasm )
+ DIRECT_PROCESS( Object_Library, gplib )
+ INDIRECT_PROCESS( Object_PIC, gplink, ".lib" )
+ DIRECT_PROCESS( Object_Program, gplink )
+ DIRECT_PROCESS( PIC_AssemblyAbsolute, picProgrammer )
+ DIRECT_PROCESS( Program_Disassembly, gpdasm )
+ DIRECT_PROCESS( Program_PIC, picProgrammer )
+#undef DIRECT_PROCESS
+#undef INDIRECT_PROCESS
+
+ case ProcessOptions::ProcessPath::Invalid:
+ kdWarning() << k_funcinfo << "Process path is invalid" << endl;
+
+ case ProcessOptions::ProcessPath::None:
+ kdWarning() << k_funcinfo << "Nothing to do" << endl;
+ break;
+ }
+}
+
+
+void ProcessChain::slotFinishedCompile(Language *language)
+{
+ ProcessOptions options = language->processOptions();
+
+ if ( options.b_addToProject && ProjectManager::self()->currentProject() )
+ ProjectManager::self()->currentProject()->addFile( KURL(options.targetFile()) );
+
+ ProcessOptions::ProcessPath::MediaType typeTo = ProcessOptions::ProcessPath::to( m_processOptions.processPath() );
+
+ TextDocument * editor = 0l;
+ if ( KTLConfig::reuseSameViewForOutput() )
+ {
+ editor = options.textOutputTarget();
+ if ( editor && (!editor->url().isEmpty() || editor->isModified()) )
+ editor = 0l;
+ }
+
+ switch (typeTo)
+ {
+ case ProcessOptions::ProcessPath::AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable:
+ case ProcessOptions::ProcessPath::C:
+ case ProcessOptions::ProcessPath::Disassembly:
+ case ProcessOptions::ProcessPath::Library:
+ case ProcessOptions::ProcessPath::Microbe:
+ case ProcessOptions::ProcessPath::Object:
+ case ProcessOptions::ProcessPath::Program:
+ {
+ switch ( options.method() )
+ {
+ case ProcessOptions::Method::LoadAsNew:
+ {
+ if ( !editor )
+ editor = DocManager::self()->createTextDocument();
+
+ if ( !editor )
+ break;
+
+ QString text;
+ QFile f( options.targetFile() );
+ if ( !f.open( IO_ReadOnly ) )
+ {
+ editor->deleteLater();
+ editor = 0l;
+ break;
+ }
+
+ QTextStream stream(&f);
+
+ while ( !stream.atEnd() )
+ text += stream.readLine()+'\n';
+
+ f.close();
+
+ editor->setText( text, true );
+ break;
+ }
+
+ case ProcessOptions::Method::Load:
+ {
+ editor = dynamic_cast<TextDocument*>( DocManager::self()->openURL(options.targetFile()) );
+ break;
+ }
+
+ case ProcessOptions::Method::Forget:
+ break;
+ }
+ }
+
+ case ProcessOptions::ProcessPath::FlowCode:
+ case ProcessOptions::ProcessPath::Pic:
+ case ProcessOptions::ProcessPath::Unknown:
+ break;
+ }
+
+
+ if (editor)
+ {
+ switch (typeTo)
+ {
+ case ProcessOptions::ProcessPath::AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable:
+ {
+ if ( KTLConfig::autoFormatMBOutput() )
+ editor->formatAssembly();
+ editor->slotInitLanguage( TextDocument::ct_asm );
+ break;
+ }
+
+ case ProcessOptions::ProcessPath::C:
+ editor->slotInitLanguage( TextDocument::ct_c );
+ break;
+
+ case ProcessOptions::ProcessPath::Disassembly:
+ break;
+
+ case ProcessOptions::ProcessPath::Library:
+ case ProcessOptions::ProcessPath::Object:
+ case ProcessOptions::ProcessPath::Program:
+ editor->slotInitLanguage( TextDocument::ct_hex );
+ break;
+
+ case ProcessOptions::ProcessPath::Microbe:
+ editor->slotInitLanguage( TextDocument::ct_microbe );
+ break;
+
+ case ProcessOptions::ProcessPath::FlowCode:
+ case ProcessOptions::ProcessPath::Pic:
+ case ProcessOptions::ProcessPath::Unknown:
+ break;
+ }
+
+ DocManager::self()->giveDocumentFocus( editor );
+ }
+
+ options.setTextOutputtedTo( editor );
+
+ emit successful(options);
+ emit successful();
+}
+
+#define LanguageFunction(a,b,c) \
+a * ProcessChain::b( ) \
+{ \
+ if ( !c ) \
+ { \
+ c = new a( this, m_pKTechlab ); \
+ connect( c, SIGNAL(processSucceeded(Language* )), this, SLOT(slotFinishedCompile(Language* )) ); \
+ connect( c, SIGNAL(processFailed(Language* )), this, SIGNAL(failed()) ); \
+ } \
+ return c; \
+}
+
+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 )
+LanguageFunction( Microbe, microbe, m_pMicrobe )
+LanguageFunction( PicProgrammer, picProgrammer, m_pPicProgrammer )
+LanguageFunction( SDCC, sdcc, m_pSDCC )
+//END class ProcessChain
+
+
+
+//BEGIN class ProcessListChain
+ProcessListChain::ProcessListChain( ProcessOptionsList pol, KTechlab * parent, const char * name )
+ : QObject( (QObject*)parent, name )
+{
+ m_processOptionsList = pol;
+ m_pKTechlab = parent;
+
+ // Start us off...
+ slotProcessChainSuccessful();
+}
+
+
+void ProcessListChain::slotProcessChainSuccessful()
+{
+ if ( m_processOptionsList.isEmpty() )
+ {
+ emit successful();
+ return;
+ }
+
+ ProcessOptionsList::iterator it = m_processOptionsList.begin();
+ ProcessOptions po = *it;
+ m_processOptionsList.remove(it);
+
+ ProcessChain * pc = LanguageManager::self()->compile(po);
+
+ connect( pc, SIGNAL(successful()), this, SLOT(slotProcessChainSuccessful()) );
+ connect( pc, SIGNAL(failed()), this, SLOT(slotProcessChainFailed()) );
+}
+
+
+void ProcessListChain::slotProcessChainFailed()
+{
+ emit failed();
+}
+//END class ProcessListChain
+
+
+#include "processchain.moc"
diff --git a/src/languages/processchain.h b/src/languages/processchain.h
new file mode 100644
index 0000000..90b871e
--- /dev/null
+++ b/src/languages/processchain.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef PROCESSCHAIN_H
+#define PROCESSCHAIN_H
+
+#include "language.h"
+#include <qobject.h>
+#include <qvaluelist.h>
+
+class FlowCode;
+class Gpasm;
+class Gpdasm;
+class Gplib;
+class Gplink;
+class KTechlab;
+class Microbe;
+class PicProgrammer;
+class ProcesOptions;
+class SDCC;
+
+typedef QValueList<ProcessOptions> ProcessOptionsList;
+
+/**
+@author Daniel Clarke
+@author David Saxton
+*/
+class ProcessChain : public QObject
+{
+ Q_OBJECT
+ public:
+ ProcessChain( ProcessOptions options, KTechlab *parent, const char *name = 0l );
+ ~ProcessChain();
+
+ void setProcessOptions( ProcessOptions options ) { m_processOptions = options; }
+
+ public slots:
+ /**
+ * Adds the output file to project if requested in the options, and opens
+ * the file in a code editor. Called to signal that a language in the last
+ * step of a compile has finished its compiling successfully.
+ */
+ void slotFinishedCompile( Language * language );
+ /**
+ * Call to compile a file of one type all the way to another type. This
+ * uses the ProcessOptions given in the constructor of this function, or
+ * later in setProcessOptions.
+ */
+ void compile();
+
+ signals:
+ /**
+ * Emitted when compiling has successfully gone all the way through to the
+ * specified 'typeTo'
+ * @param options The ProcessOptions holding the output filename
+ * @see compile
+ */
+ void successful(ProcessOptions options);
+ /**
+ * Convenience signal
+ */
+ void successful();
+ /**
+ * Emitted if not successful
+ */
+ void failed();
+
+ protected:
+ FlowCode * flowCode();
+ Gpasm * gpasm();
+ Gpdasm * gpdasm();
+ Gplib * gplib();
+ Gplink * gplink();
+ Microbe * microbe();
+ PicProgrammer * picProgrammer();
+ SDCC * sdcc();
+
+ int m_errorCount;
+ ProcessOptions m_processOptions;
+ KTechlab * m_pKTechlab;
+
+ private:
+ FlowCode * m_pFlowCode;
+ Microbe * m_pMicrobe;
+ Gpasm * m_pGpasm;
+ Gpdasm * m_pGpdasm;
+ Gplib * m_pGplib;
+ Gplink * m_pGplink;
+ PicProgrammer * m_pPicProgrammer;
+ SDCC * m_pSDCC;
+};
+
+
+class ProcessListChain : public QObject
+{
+ Q_OBJECT
+
+ public:
+ ProcessListChain( ProcessOptionsList pol, KTechlab *parent, const char *name = 0l );
+
+ signals:
+ /**
+ * Emitted if successful
+ */
+ void successful();
+ /**
+ * Emitted if not successful
+ */
+ void failed();
+
+ protected slots:
+ void slotProcessChainSuccessful();
+ void slotProcessChainFailed();
+
+ protected:
+ ProcessOptionsList m_processOptionsList;
+ KTechlab * m_pKTechlab;
+};
+
+#endif
diff --git a/src/languages/sdcc.cpp b/src/languages/sdcc.cpp
new file mode 100644
index 0000000..553e974
--- /dev/null
+++ b/src/languages/sdcc.cpp
@@ -0,0 +1,205 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "asminfo.h"
+#include "languagemanager.h"
+#include "logview.h"
+#include "microinfo.h"
+#include "microlibrary.h"
+#include "sdcc.h"
+#include "src/core/ktlconfig.h"
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+
+SDCC::SDCC( ProcessChain * processChain, KTechlab * parent )
+ : ExternalLanguage( processChain, parent, "SDCC" )
+{
+ m_successfulMessage = i18n("*** Compilation successful ***");
+ m_failedMessage = i18n("*** Compilation failed ***");
+}
+
+
+SDCC::~SDCC()
+{
+}
+
+
+void SDCC::processInput( ProcessOptions options )
+{
+ resetLanguageProcess();
+
+ MicroInfo * info = MicroLibrary::self()->microInfoWithID( options.m_picID );
+ if (!info)
+ {
+ outputError( i18n("Could not find PIC with ID \"%1\".").arg(options.m_picID) );
+ return;
+ }
+
+ m_processOptions = options;
+
+ *m_languageProcess << ("sdcc");
+
+
+ //BEGIN Pass custom sdcc options
+#define ARG(text,option) if ( KTLConfig::text() ) *m_languageProcess << ( QString("--%1").arg(option) );
+ // General
+ ARG( sDCC_nostdlib, "nostdlib" )
+ ARG( sDCC_nostdinc, "nostdinc" )
+ ARG( sDCC_less_pedantic, "less-pedantic" )
+ ARG( sDCC_std_c89, "std-c89" )
+ ARG( sDCC_std_c99, "std-c99" )
+
+ // Code generation
+ ARG( sDCC_stack_auto, "stack-auto" )
+ ARG( sDCC_int_long_reent, "int-long-reent" )
+ ARG( sDCC_float_reent, "float-reent" )
+ ARG( sDCC_fommit_frame_pointer, "fommit-frame-pointer" )
+ ARG( sDCC_no_xinit_opt, "no-xinit-opt" )
+ ARG( sDCC_all_callee_saves, "all-callee-saves" )
+
+ // Optimization
+ ARG( sDCC_nooverlay, "nooverlay" )
+ ARG( sDCC_nogcse, "nogcse" )
+ ARG( sDCC_nolabelopt, "nolabelopt" )
+ ARG( sDCC_noinvariant, "noinvariant" )
+ ARG( sDCC_noinduction, "noinduction" )
+ ARG( sDCC_no_peep, "no-peep" )
+ ARG( sDCC_noloopreverse, "noloopreverse" )
+ ARG( sDCC_opt_code_size, "opt-code-size" )
+ ARG( sDCC_opt_code_speed, "opt-code-speed" )
+ ARG( sDCC_peep_asm, "peep-asm" )
+ ARG( sDCC_nojtbound, "nojtbound" )
+
+ // PIC16 Specific
+ if ( info->instructionSet()->set() == AsmInfo::PIC16 )
+ {
+ ARG( sDCC_nodefaultlibs, "nodefaultlibs" )
+ ARG( sDCC_pno_banksel, "pno-banksel" )
+ ARG( sDCC_pstack_model_large, "pstack-model=large" )
+ ARG( sDCC_debug_xtra, "debug-xtra" )
+ ARG( sDCC_denable_peeps, "denable-peeps" )
+ ARG( sDCC_calltree, "calltree" )
+ ARG( sDCC_fstack, "fstack" )
+ ARG( sDCC_optimize_goto, "optimize-goto" )
+ ARG( sDCC_optimize_cmp, "optimize-cmp" )
+ ARG( sDCC_optimize_df, "optimize-df" )
+ }
+#undef ARG
+
+ if ( !KTLConfig::miscSDCCOptions().isEmpty() )
+ *m_languageProcess << ( KTLConfig::miscSDCCOptions() );
+ //END Pass custom sdcc options
+
+
+ *m_languageProcess << ("--debug"); // Enable debugging symbol output
+ *m_languageProcess << ("-S"); // Compile only; do not assemble or link
+
+ QString asmSwitch;
+ switch ( info->instructionSet()->set() )
+ {
+ case AsmInfo::PIC12:
+ // Last time I checked, SDCC doesn't support Pic12, and probably never will, but whatever...
+ asmSwitch = "-mpic12";
+ break;
+ case AsmInfo::PIC14:
+ asmSwitch = "-mpic14";
+ break;
+ case AsmInfo::PIC16:
+ asmSwitch = "-mpic16";
+ break;
+ }
+
+ *m_languageProcess << (asmSwitch);
+
+ *m_languageProcess << ( "-"+options.m_picID.lower() );
+
+ *m_languageProcess << ( options.inputFiles().first() );
+
+ *m_languageProcess << ("-o");
+ *m_languageProcess << ( options.intermediaryOutput() );
+
+ if ( !start() )
+ {
+ KMessageBox::sorry( LanguageManager::self()->logView(), i18n("Compilation failed. Please check you have sdcc installed.") );
+ processInitFailed();
+ return;
+ }
+}
+
+
+bool SDCC::isError( const QString &message ) const
+{
+ return false;
+}
+
+
+bool SDCC::isStderrOutputFatal( const QString & message ) const
+{
+ if ( message.startsWith("Processor:") )
+ return false;
+
+ return true;
+}
+
+
+bool SDCC::isWarning( const QString &message ) const
+{
+ return false;
+}
+
+
+ProcessOptions::ProcessPath::Path SDCC::outputPath( ProcessOptions::ProcessPath::Path inputPath ) const
+{
+ switch (inputPath)
+ {
+ case ProcessOptions::ProcessPath::C_AssemblyRelocatable:
+ return ProcessOptions::ProcessPath::None;
+
+ case ProcessOptions::ProcessPath::C_Library:
+ return ProcessOptions::ProcessPath::AssemblyRelocatable_Library;
+
+ case ProcessOptions::ProcessPath::C_Object:
+ return ProcessOptions::ProcessPath::AssemblyRelocatable_Object;
+
+ case ProcessOptions::ProcessPath::C_PIC:
+ return ProcessOptions::ProcessPath::AssemblyAbsolute_PIC;
+
+ case ProcessOptions::ProcessPath::C_Program:
+ return ProcessOptions::ProcessPath::AssemblyRelocatable_Program;
+
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_PIC:
+ case ProcessOptions::ProcessPath::AssemblyAbsolute_Program:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Library:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Object:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_PIC:
+ case ProcessOptions::ProcessPath::AssemblyRelocatable_Program:
+ case ProcessOptions::ProcessPath::FlowCode_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::FlowCode_Microbe:
+ case ProcessOptions::ProcessPath::FlowCode_PIC:
+ case ProcessOptions::ProcessPath::FlowCode_Program:
+ case ProcessOptions::ProcessPath::Microbe_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Microbe_PIC:
+ case ProcessOptions::ProcessPath::Microbe_Program:
+ case ProcessOptions::ProcessPath::Object_Disassembly:
+ case ProcessOptions::ProcessPath::Object_Library:
+ case ProcessOptions::ProcessPath::Object_PIC:
+ case ProcessOptions::ProcessPath::Object_Program:
+ case ProcessOptions::ProcessPath::PIC_AssemblyAbsolute:
+ case ProcessOptions::ProcessPath::Program_Disassembly:
+ case ProcessOptions::ProcessPath::Program_PIC:
+ case ProcessOptions::ProcessPath::Invalid:
+ case ProcessOptions::ProcessPath::None:
+ return ProcessOptions::ProcessPath::Invalid;
+ }
+
+ return ProcessOptions::ProcessPath::Invalid;
+}
diff --git a/src/languages/sdcc.h b/src/languages/sdcc.h
new file mode 100644
index 0000000..a6de933
--- /dev/null
+++ b/src/languages/sdcc.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef SDCC_H
+#define SDCC_H
+
+#include <externallanguage.h>
+
+/**
+@author David Saxton
+*/
+class SDCC : public ExternalLanguage
+{
+ public:
+ SDCC( ProcessChain * processChain, KTechlab * parent );
+ ~SDCC();
+
+ virtual void processInput( ProcessOptions options );
+ virtual ProcessOptions::ProcessPath::Path outputPath( ProcessOptions::ProcessPath::Path inputPath ) const;
+
+ protected:
+ virtual bool isError( const QString & message ) const;
+ virtual bool isWarning( const QString & message ) const;
+ virtual bool isStderrOutputFatal( const QString & message ) const;
+};
+
+#endif
diff --git a/src/languages/sourceline.cpp b/src/languages/sourceline.cpp
new file mode 100644
index 0000000..9ca89bb
--- /dev/null
+++ b/src/languages/sourceline.cpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#include "sourceline.h"
+
+
+//BEGIN class SourceLine
+SourceLine::SourceLine()
+ : m_line(-1)
+{
+}
+
+
+SourceLine::SourceLine( const QString & fileName, int line )
+ : m_fileName(fileName),
+ m_line(line)
+{
+}
+
+
+bool SourceLine::operator < ( const SourceLine & sourceLine ) const
+{
+ return (m_fileName < sourceLine.fileName()) ||
+ (m_fileName == sourceLine.fileName() && m_line < sourceLine.line());
+}
+
+
+bool SourceLine::operator == ( const SourceLine & sourceLine ) const
+{
+ return (sourceLine.fileName() == fileName()) &&
+ (sourceLine.line() == line());
+}
+//END class SourceLine
+
+
diff --git a/src/languages/sourceline.h b/src/languages/sourceline.h
new file mode 100644
index 0000000..d2e774d
--- /dev/null
+++ b/src/languages/sourceline.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2005 by David Saxton *
+ * david@bluehaze.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+#ifndef SOURCELINE_H
+#define SOURCELINE_H
+
+#include <qstring.h>
+
+/**
+@author David Saxton
+ */
+class SourceLine
+{
+ public:
+ /**
+ * Creates an invalid source line (line is negative).
+ */
+ SourceLine();
+ SourceLine( const QString & fileName, int line );
+
+ QString fileName() const { return m_fileName; }
+ int line() const { return m_line; }
+
+ bool isValid() const { return m_line >= 0; }
+
+ bool operator < ( const SourceLine & sourceLine ) const;
+ bool operator == ( const SourceLine & sourceLine ) const;
+
+ protected:
+ QString m_fileName;
+ int m_line;
+};
+
+
+#endif