summaryrefslogtreecommitdiffstats
path: root/elftosb2/ElftosbLexer.cpp
blob: b1ba327c24a5a66f3d0cc45777a1eb719c89ed8a (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
/*
 * File:	ElftosbLexer.cpp
 *
 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
 * See included license file for license details.
 */
#include "ElftosbLexer.h"
#include <algorithm>
#include "HexValues.h"

using namespace elftosb;

ElftosbLexer::ElftosbLexer(istream & inputStream)
:	yyFlexLexer(&inputStream), m_line(1), m_blob(0), m_blobFirstLine(0)
{
}

void ElftosbLexer::getSymbolValue(YYSTYPE * value)
{
	if (!value)
	{
		return;
	}
	*value = m_symbolValue;
}

void ElftosbLexer::addSourceName(std::string * ident)
{
	m_sources.push_back(*ident);
}

bool ElftosbLexer::isSourceName(std::string * ident)
{
	string_vector_t::iterator it = find(m_sources.begin(), m_sources.end(), *ident);
	return it != m_sources.end();
}

void ElftosbLexer::LexerError(const char * msg)
{
	throw elftosb::lexical_error(msg);
}

//! Reads the \a in string and writes to the \a out string. These strings can be the same
//! string since the read head is always in front of the write head.
//!
//! \param[in] in Input string containing C-style escape sequences.
//! \param[out] out Output string. All escape sequences in the input string have been converted
//!		to the actual characters. May point to the same string as \a in.
//! \return The length of the resulting \a out string. This length is necessary because
//!		the string may have contained escape sequences that inserted null characters.
int ElftosbLexer::processStringEscapes(const char * in, char * out)
{
	int count = 0;
	while (*in)
	{
		switch (*in)
		{
			case '\\':
			{
				// start of an escape sequence
				char c = *++in;
				switch (c)
				{
					case 0:	// end of the string, bail
						break;
					case 'x':
					{
						// start of a hex char escape sequence
						
						// read high and low nibbles, checking for end of string
						char hi = *++in;
						if (hi == 0) break;
						char lo = *++in;
						if (lo == 0) break;
						
						if (isHexDigit(hi) && isHexDigit(lo))
						{
							if (hi >= '0' && hi <= '9')
								c = (hi - '0') << 4;
							else if (hi >= 'A' && hi <= 'F')
								c = (hi - 'A' + 10) << 4;
							else if (hi >= 'a' && hi <= 'f')
								c = (hi - 'a' + 10) << 4;
							
							if (lo >= '0' && lo <= '9')
								c |= lo - '0';
							else if (lo >= 'A' && lo <= 'F')
								c |= lo - 'A' + 10;
							else if (lo >= 'a' && lo <= 'f')
								c |= lo - 'a' + 10;
								
							*out++ = c;
							count++;
						}
						else
						{
							// not hex digits, the \x must have wanted an 'x' char
							*out++ = 'x';
							*out++ = hi;
							*out++ = lo;
							count += 3;
						}
						break;
					}
					case 'n':
						*out++ = '\n';
						count++;
						break;
					case 't':
						*out++ = '\t';
						count++;
						break;
					case 'r':
						*out++ = '\r';
						count++;
						break;
					case 'b':
						*out++ = '\b';
						count++;
						break;
					case 'f':
						*out++ = '\f';
						count++;
						break;
					case '0':
						*out++ = '\0';
						count++;
						break;
					default:
						*out++ = c;
						count++;
						break;
				}
				break;
			}
			
			default:
				// copy all other chars directly
				*out++ = *in++;
				count++;
		}
	}
	
	// place terminating null char on output
	*out = 0;
	return count;
}