/*
* simplecpp - A simple and high-fidelity C/C++ preprocessor library
* Copyright (C) 2016 Daniel Marjamki.
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*/
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
#define NOMINMAX
#endif
#include "simplecpp.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
#include
#undef ERROR
#undef TRUE
#define SIMPLECPP_WINDOWS
#endif
static bool isHex(const std::string &s)
{
return s.size()>2 && (s.compare(0,2,"0x")==0 || s.compare(0,2,"0X")==0);
}
static const simplecpp::TokenString DEFINE("define");
static const simplecpp::TokenString UNDEF("undef");
static const simplecpp::TokenString INCLUDE("include");
static const simplecpp::TokenString ERROR("error");
static const simplecpp::TokenString WARNING("warning");
static const simplecpp::TokenString IF("if");
static const simplecpp::TokenString IFDEF("ifdef");
static const simplecpp::TokenString IFNDEF("ifndef");
static const simplecpp::TokenString DEFINED("defined");
static const simplecpp::TokenString ELSE("else");
static const simplecpp::TokenString ELIF("elif");
static const simplecpp::TokenString ENDIF("endif");
static const simplecpp::TokenString PRAGMA("pragma");
static const simplecpp::TokenString ONCE("once");
template static std::string toString(T t)
{
std::ostringstream ostr;
ostr > std::hex;
istr >> ret;
return ret;
}
static unsigned long long stringToULL(const std::string &s)
{
unsigned long long ret;
const bool hex = isHex(s);
std::istringstream istr(hex ? s.substr(2) : s);
if (hex)
istr >> std::hex;
istr >> ret;
return ret;
}
static bool startsWith(const std::string &str, const std::string &s)
{
return (str.size() >= s.size() && str.compare(0, s.size(), s) == 0);
}
static bool endsWith(const std::string &s, const std::string &e)
{
return (s.size() >= e.size() && s.compare(s.size() - e.size(), e.size(), e) == 0);
}
static bool sameline(const simplecpp::Token *tok1, const simplecpp::Token *tok2)
{
return tok1 && tok2 && tok1->location.sameline(tok2->location);
}
static bool isAlternativeBinaryOp(const simplecpp::Token *tok, const std::string &alt)
{
return (tok->name &&
tok->str == alt &&
tok->previous &&
tok->next &&
(tok->previous->number || tok->previous->name || tok->previous->op == ')') &&
(tok->next->number || tok->next->name || tok->next->op == '('));
}
static bool isAlternativeUnaryOp(const simplecpp::Token *tok, const std::string &alt)
{
return ((tok->name && tok->str == alt) &&
(!tok->previous || tok->previous->op == '(') &&
(tok->next && (tok->next->name || tok->next->number)));
}
void simplecpp::Location::adjust(const std::string &str)
{
if (str.find_first_of("\r\n") == std::string::npos) {
col += str.size();
return;
}
for (std::size_t i = 0U; i < str.size(); ++i) {
col++;
if (str[i] == '\n' || str[i] == '\r') {
col = 1;
line++;
if (str[i] == '\r' && (i+1)previous)
tok = tok->previous;
for (; tok; tok = tok->next) {
if (tok->previous) {
std::cout previous) ? ' ' : '\n');
}
std::cout str;
}
std::cout next) {
if (tok != this) {
std::cout previous) ? ' ' : '\n');
}
std::cout str;
}
std::cout next)
push_back(new Token(*tok));
sizeOfType = other.sizeOfType;
}
void simplecpp::TokenList::clear()
{
backToken = NULL;
while (frontToken) {
Token *next = frontToken->next;
delete frontToken;
frontToken = next;
}
sizeOfType.clear();
}
void simplecpp::TokenList::push_back(Token *tok)
{
if (!frontToken)
frontToken = tok;
else
backToken->next = tok;
tok->previous = backToken;
backToken = tok;
}
void simplecpp::TokenList::dump() const
{
std::cout location.line < loc.line || tok->location.fileIndex != loc.fileIndex) {
ret location;
}
while (tok->location.line > loc.line) {
ret previous, tok))
ret str);
}
return ret.str();
}
static unsigned char readChar(std::istream &istr, unsigned int bom)
{
unsigned char ch = (unsigned char)istr.get();
// For UTF-16 encoded files the BOM is 0xfeff/0xfffe. If the
// character is non-ASCII character then replace it with 0xff
if (bom == 0xfeff || bom == 0xfffe) {
const unsigned char ch2 = (unsigned char)istr.get();
const int ch16 = (bom == 0xfeff) ? (chop == 'R') {
std::string delim;
ch = readChar(istr,bom);
while (istr.good() && ch != '(' && ch != '\n') {
delim += ch;
ch = readChar(istr,bom);
}
if (!istr.good() || ch == '\n')
// TODO report
return;
currentToken = '\"';
const std::string endOfRawString(')' + delim + '\"');
while (istr.good() && !endsWith(currentToken, endOfRawString))
currentToken += readChar(istr,bom);
if (!endsWith(currentToken, endOfRawString))
// TODO report
return;
currentToken.erase(currentToken.size() - endOfRawString.size(), endOfRawString.size() - 1U);
back()->setstr(escapeString(currentToken));
location.adjust(currentToken);
if (currentToken.find_first_of("\r\n") == std::string::npos)
location.col += 2 + 2 * delim.size();
else
location.col += 1 + delim.size();
continue;
}
currentToken = readUntil(istr,location,ch,ch,outputList);
if (currentToken.size() < 2U)
// TODO report
return;
std::string s = currentToken;
std::string::size_type pos;
while ((pos = s.find_first_of("\r\n")) != std::string::npos) {
s.erase(pos,1);
}
push_back(new Token(s, location)); // push string without newlines
location.adjust(currentToken);
continue;
}
else {
currentToken += ch;
}
if (currentToken == "")
result = (stringToLL(tok->previous->str) > stringToLL(tok->next->str));
else if (tok->str == ">=")
result = (stringToLL(tok->previous->str) >= stringToLL(tok->next->str));
else if (tok->str == "