summaryrefslogtreecommitdiffstats
path: root/src/languages/asmparser.cpp
blob: 94b01c0ef1575a9cc09de5dc16713c0cd90a9e45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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 <tqfile.h>
#include <tqregexp.h>

AsmParser::AsmParser( const TQString &url )
	: m_url(url)
{
	m_bContainsRadix = false;
	m_type = Absolute;
}


AsmParser::~AsmParser()
{
}


bool AsmParser::parse( GpsimDebugger * debugger )
{
	TQFile file(m_url);
	if ( !file.open(IO_ReadOnly) )
		return false;
	
	TQTextStream stream( &file );
	
	m_type = Absolute;
	m_bContainsRadix = false;
	m_picID = TQString();
	
	TQStringList nonAbsoluteOps = TQStringList::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 TQString line = stream.readLine().stripWhiteSpace();
		if ( m_type != Relocatable )
		{
			TQString col0 = line.section( TQRegExp("[; ]"), 0, 0 );
			col0 = col0.stripWhiteSpace();
			if ( nonAbsoluteOps.tqcontains(col0) )
				m_type = Relocatable;
		}
		if ( !m_bContainsRadix )
		{
			if ( line.tqcontains( TQRegExp("^RADIX[\\s]*") ) || line.tqcontains( TQRegExp("^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
			TQRegExp fullRegExp("[lL][iI][sS][tT][\\s]+[pP][\\s]*=[\\s]*[\\d\\w]+");
			TQRegExp 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.tqfindRev(" ");
			
			if ( fileLineAt == -1 )
				kdWarning() << k_funcinfo << "Syntax error in line \"" << line << "\" while looking for file-line" << endl;
			else
			{
				// 7 = length_of(";#CSRC\t")
				TQString fileName = line.mid( 7, fileLineAt-7 );
				TQString 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...
			TQStringList lineParts = TQStringList::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 TQString lineAndFile = lineParts[1];
				int lineFileSplit = lineAndFile.tqfind("; ");
				if ( lineFileSplit == -1 )
					kdDebug() << k_funcinfo << "Could not find file / line split in \""<<lineAndFile<<"\""<<endl;
				else
				{
					TQString fileName = lineAndFile.mid( lineFileSplit + 2 );
					TQString 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;
}