1 /***************************************************************************
2  *   Copyright (C) 2005 by David Saxton                                    *
3  *   david@bluehaze.org                                                    *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  ***************************************************************************/
10 
11 #include "asmparser.h"
12 #include "config.h"
13 #include "gpsimprocessor.h"
14 
15 
16 #include <QDebug>
17 #include <QFile>
18 #include <QRegExp>
19 #include <QStringList>
20 
AsmParser(const QString & url)21 AsmParser::AsmParser( const QString &url )
22 	: m_url(url)
23 {
24 	m_bContainsRadix = false;
25 	m_type = Absolute;
26 }
27 
28 
~AsmParser()29 AsmParser::~AsmParser()
30 {
31 }
32 
33 
parse(GpsimDebugger * debugger)34 bool AsmParser::parse( GpsimDebugger * debugger )
35 {
36 	QFile file(m_url);
37 	if ( !file.open(QIODevice::ReadOnly) )
38 		return false;
39 
40 	QTextStream stream( &file );
41 
42 	m_type = Absolute;
43 	m_bContainsRadix = false;
44 	m_picID = QString::null;
45 
46 	//QStringList nonAbsoluteOps = QStringList::split( ",",
47 	//		"code,.def,.dim,.direct,endw,extern,.file,global,idata,.ident,.line,.type,udata,udata_acs,udata_ovr,udata_shr" );
48     QStringList nonAbsoluteOps = QString(
49         "code,.def,.dim,.direct,endw,extern,.file,global,idata,.ident,.line,.type,udata,udata_acs,udata_ovr,udata_shr")
50         .split(",");
51 
52 	unsigned inputAtLine = 0;
53 	while ( !stream.atEnd() ) {
54 		const QString line = stream.readLine().trimmed();
55 		if ( m_type != Relocatable ) {
56 			QString col0 = line.section( QRegExp("[; ]"), 0, 0 );
57 			col0 = col0.trimmed();
58 			if ( nonAbsoluteOps.contains(col0) )
59 				m_type = Relocatable;
60 		}
61 
62 		if ( !m_bContainsRadix ) {
63 			if ( line.contains( QRegExp("^RADIX[\\s]*") ) || line.contains( QRegExp("^radix[\\s]*") ) )
64 				m_bContainsRadix = true;
65 		}
66 
67 		if ( m_picID.isEmpty() ) {
68 			// We look for "list p = ", and "list p = picid ", and subtract the positions / lengths away from each other to get the picid text position
69 			QRegExp fullRegExp("[lL][iI][sS][tT][\\s]+[pP][\\s]*=[\\s]*[\\d\\w]+");
70 			QRegExp halfRegExp("[lL][iI][sS][tT][\\s]+[pP][\\s]*=[\\s]*");
71 
72 			int startPos = fullRegExp.indexIn(line);
73 			if ( (startPos != -1) && (startPos == halfRegExp.indexIn(line)) )
74 			{
75 				m_picID = line.mid( startPos + halfRegExp.matchedLength(), fullRegExp.matchedLength() - halfRegExp.matchedLength() );
76 				m_picID = m_picID.toUpper();
77 				if ( !m_picID.startsWith("P") )
78 					m_picID.prepend("P");
79 			}
80 		}
81 #ifndef NO_GPSIM
82 		if ( debugger && line.startsWith(";#CSRC\t") )
83 		{
84 			// Assembly file produced (by sdcc) from C, line is in format:
85 			// ;#CSRC\t[file-name] [file-line]
86 			// The filename can contain spaces.
87 			int fileLineAt = line.lastIndexOf(" ");
88 
89 			if ( fileLineAt == -1 )
90 				qWarning() << Q_FUNC_INFO << "Syntax error in line \"" << line << "\" while looking for file-line" << endl;
91 			else {
92 				// 7 = length_of(";#CSRC\t")
93 				QString fileName = line.mid( 7, fileLineAt-7 );
94 				QString fileLineString = line.mid( fileLineAt+1, line.length() - fileLineAt - 1 );
95 
96 				if ( fileName.startsWith("\"") ) {
97 					// Newer versions of SDCC insert " around the filename
98 					fileName.remove( 0, 1 ); // First "
99 					fileName.remove( fileName.length()-1, 1 ); // Last "
100 				}
101 
102 				bool ok;
103 				int fileLine = fileLineString.toInt(&ok) - 1;
104 				if ( ok && fileLine >= 0 )
105 					debugger->associateLine( fileName, fileLine, m_url, inputAtLine );
106 				else	qDebug() << Q_FUNC_INFO << "Not a valid line number: \"" << fileLineString << "\"" << endl;
107 			}
108 		}
109 
110 		if ( debugger && (line.startsWith(".line\t") || line.startsWith(";#MSRC") ) ) {
111 			// Assembly file produced by either sdcc or microbe, line is in format:
112 			// \t[".line"/"#MSRC"]\t[file-line]; [file-name]\t[c/microbe source code for that line]
113 			// We're screwed if the file name contains tabs, but hopefully not many do...
114 			//QStringList lineParts = QStringList::split( '\t', line ); // 2018.12.01
115             QStringList lineParts = line.split( '\t' , QString::SkipEmptyParts );
116 			if ( lineParts.size() < 2 )
117 				qWarning() << Q_FUNC_INFO << "Line is in wrong format for extracing source line and file: \""<<line<<"\""<<endl;
118 			else {
119 				const QString lineAndFile = lineParts[1];
120 				int lineFileSplit = lineAndFile.indexOf("; ");
121 				if ( lineFileSplit == -1 )
122 					qDebug() << Q_FUNC_INFO << "Could not find file / line split in \""<<lineAndFile<<"\""<<endl;
123 				else {
124 					QString fileName = lineAndFile.mid( lineFileSplit + 2 );
125 					QString fileLineString = lineAndFile.left( lineFileSplit );
126 
127 					if ( fileName.startsWith("\"") ) {
128 						// Newer versions of SDCC insert " around the filename
129 						fileName.remove( 0, 1 ); // First "
130 						fileName.remove( fileName.length()-1, 1 ); // Last "
131 					}
132 
133 					bool ok;
134 					int fileLine = fileLineString.toInt(&ok) - 1;
135 					if ( ok && fileLine >= 0 )
136 						debugger->associateLine( fileName, fileLine, m_url, inputAtLine );
137 					else qDebug() << Q_FUNC_INFO << "Not a valid line number: \"" << fileLineString << "\"" << endl;
138 				}
139 			}
140 		}
141 #endif // !NO_GPSIM
142 		inputAtLine++;
143 	}
144 
145 	return true;
146 }
147 
148