/*
* 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;
}