astyle port draft. TODO: utime, directory_iterator, is_absolute

This commit is contained in:
pvoid committed 2025-11-26 02:01:23 +03:00
1 parent e580a7eb6c
commit 8b731e941f
12 files changed
+22127

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
CXX:=kos32-g++
LD:=kos32-ld
SDK_DIR:=/home/pt/dev/kolibri/latest/contrib/sdk
CXXFLAGS:=-c -fno-ident -O2 -std=c++17 -fomit-frame-pointer -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -Wno-pointer-arith
#-c -m32 -march=native -mtune=generic -std=c99 -O2 -fomit-frame-pointer -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32
#LDFLAGS:=-static -nostdlib --subsystem native --image-base 0 -T $(SDK_DIR)/sources/newlib/static.lds -Map=$app_name.map
INCLUDE:=-I $(SDK_DIR)/sources/newlib/libc/include -I $(SDK_DIR)/sources/libstdc++-v3/include -I /usr/local/kos32/lib/gcc/mingw32/5.4.0/include/c++/experimental
LDFLAGS:=-static -S -Tapp-dynamic.lds --image-base 0
LIBPATH:=-L $(SDK_DIR)/lib -L /usr/local/kos32/lib
all: compile link make_iso copy_iso
compile:
$(CXX) $(CXXFLAGS) $(INCLUDE) -o main.o main.cpp
clean:
rm -f main.o main iso app.iso
link:
$(LD) $(LDFLAGS) $(LIBPATH) main.o -o main -lstdc++ -lsupc++ -lgcc -lc.dll
#-lc -lgcc -lstdc++ -lsupc++
kos32-strip -s main -o main
kos32-objcopy main -O binary
copy:
cp main /mnt/e/
make_iso:
rm -rf iso
mkdir -p iso
cp main iso/
mkisofs -appid KolibriTestApp -volid KolibriTestApp -XA -sysid KOLIBRI -publisher pvoid -volset-size 1 -volset-seqno 1 -iso-level 3 -J -o app.iso iso/main
rm -rf iso
copy_iso:
rm -f /mnt/e/app.iso
cp app.iso /mnt/e/
File diff suppressed because it is too large. Load diff
+775
View File
@@ -0,0 +1,775 @@
// ASEnhancer.cpp
// Copyright (c) 2025 The Artistic Style Authors.
// This code is licensed under the MIT License.
// License.md describes the conditions under which this software may be distributed.
//-----------------------------------------------------------------------------
// headers
//-----------------------------------------------------------------------------
#include "astyle.h"
#include <string_view>
//-----------------------------------------------------------------------------
// astyle namespace
//-----------------------------------------------------------------------------
namespace astyle {
//
//-----------------------------------------------------------------------------
// ASEnhancer class
//-----------------------------------------------------------------------------
/**
* initialize the ASEnhancer.
*
* init() is called each time an ASFormatter object is initialized.
*/
void ASEnhancer::init(int _fileType,
int _indentLength,
int _tabLength,
bool _useTabs,
bool _forceTab,
bool _namespaceIndent,
bool _caseIndent,
bool _preprocBlockIndent,
bool _preprocDefineIndent,
bool _emptyLineFill,
std::vector<const std::pair<const std::string, const std::string>* >* _indentableMacros)
{
// formatting variables from ASFormatter and ASBeautifier
ASBase::init(_fileType);
indentLength = _indentLength;
tabLength = _tabLength;
useTabs = _useTabs;
forceTab = _forceTab;
namespaceIndent = _namespaceIndent;
caseIndent = _caseIndent;
preprocBlockIndent = _preprocBlockIndent;
preprocDefineIndent = _preprocDefineIndent;
emptyLineFill = _emptyLineFill;
indentableMacros = _indentableMacros;
quoteChar = '\'';
// unindent variables
lineNumber = 0;
braceCount = 0;
isInComment = false;
isInQuote = false;
switchDepth = 0;
eventPreprocDepth = 0;
lookingForCaseBrace = false;
unindentNextLine = false;
shouldUnindentLine = false;
shouldUnindentComment = false;
// switch struct and vector
sw.switchBraceCount = 0;
sw.unindentDepth = 0;
sw.unindentCase = false;
switchStack.clear();
// other variables
nextLineIsEventIndent = false;
isInEventTable = false;
nextLineIsDeclareIndent = false;
isInDeclareSection = false;
}
/**
* additional formatting for line of source code.
* every line of source code in a source code file should be sent
* one after the other to this function.
* indents event tables
* unindents the case blocks
*
* @param line the original formatted line will be updated if necessary.
*/
void ASEnhancer::enhance(std::string& line, bool isInNamespace, bool isInPreprocessor, bool isInSQL)
{
shouldUnindentLine = true;
shouldUnindentComment = false;
lineNumber++;
// check for beginning of event table
if (nextLineIsEventIndent)
{
isInEventTable = true;
nextLineIsEventIndent = false;
}
// check for beginning of SQL declare section
if (nextLineIsDeclareIndent)
{
isInDeclareSection = true;
nextLineIsDeclareIndent = false;
}
if (line.empty()
&& !isInEventTable
&& !isInDeclareSection
&& !emptyLineFill)
return;
// test for unindent on attached braces
if (unindentNextLine)
{
sw.unindentDepth++;
sw.unindentCase = true;
unindentNextLine = false;
}
// parse characters in the current line
parseCurrentLine(line, isInPreprocessor, isInSQL);
// check for SQL indentable lines
if (isInDeclareSection)
{
size_t firstText = line.find_first_not_of(" \t");
if (firstText == std::string::npos || line[firstText] != '#')
indentLine(line, 1);
}
// check for event table indentable lines
if (isInEventTable
&& (eventPreprocDepth == 0
|| (namespaceIndent && isInNamespace)))
{
size_t firstText = line.find_first_not_of(" \t");
if (firstText == std::string::npos || line[firstText] != '#')
indentLine(line, 1);
}
if (shouldUnindentComment && sw.unindentDepth > 0)
unindentLine(line, sw.unindentDepth - 1);
else if (shouldUnindentLine && sw.unindentDepth > 0)
unindentLine(line, sw.unindentDepth);
}
/**
* convert a force-tab indent to spaces
*
* @param line a reference to the line that will be converted.
*/
void ASEnhancer::convertForceTabIndentToSpaces(std::string& line) const
{
// replace tab indents with spaces
for (size_t i = 0; i < line.length(); i++)
{
if (!std::isblank(line[i]))
break;
if (line[i] == '\t')
{
line.erase(i, 1);
line.insert(i, tabLength, ' ');
i += tabLength - 1;
}
}
}
/**
* convert a space indent to force-tab
*
* @param line a reference to the line that will be converted.
*/
void ASEnhancer::convertSpaceIndentToForceTab(std::string& line) const
{
assert(tabLength > 0);
// replace leading spaces with tab indents
size_t newSpaceIndentLength = line.find_first_not_of(" \t");
size_t tabCount = newSpaceIndentLength / tabLength; // truncate extra spaces
line.replace(0U, tabCount * tabLength, tabCount, '\t');
}
/**
* find the colon following a 'case' statement
*
* @param line a reference to the line.
* @param caseIndex the line index of the case statement.
* @return the line index of the colon.
*/
size_t ASEnhancer::findCaseColon(std::string_view line, size_t caseIndex) const
{
size_t i = caseIndex;
bool isInQuote_ = false;
char quoteChar_ = ' ';
for (; i < line.length(); i++)
{
if (isInQuote_)
{
if (line[i] == '\\')
{
i++;
continue;
}
if (line[i] == quoteChar_) // check ending quote
{
isInQuote_ = false;
quoteChar_ = ' ';
continue;
}
continue; // must close quote before continuing
}
if (line[i] == '"' // check opening quote
|| (line[i] == '\'' && !isDigitSeparator(line, i)))
{
isInQuote_ = true;
quoteChar_ = line[i];
continue;
}
if (line[i] == ':')
{
if ((i + 1 < line.length()) && (line[i + 1] == ':'))
i++; // bypass scope resolution operator
else
break; // found it
}
}
return i;
}
/**
* indent a line by a given number of tabsets
* by inserting leading whitespace to the line argument.
*
* @param line a reference to the line to indent.
* @param indent the number of tabsets to insert.
* @return the number of characters inserted.
*/
int ASEnhancer::indentLine(std::string& line, int indent) const
{
if (line.empty()
&& !emptyLineFill)
return 0;
size_t charsToInsert = 0;
if (forceTab && indentLength != tabLength)
{
// replace tab indents with spaces
convertForceTabIndentToSpaces(line);
// insert the space indents
charsToInsert = indent * indentLength;
line.insert(line.begin(), charsToInsert, ' ');
// replace leading spaces with tab indents
convertSpaceIndentToForceTab(line);
}
else if (useTabs)
{
charsToInsert = indent;
line.insert(line.begin(), charsToInsert, '\t');
}
else // spaces
{
charsToInsert = indent * indentLength;
line.insert(line.begin(), charsToInsert, ' ');
}
return charsToInsert;
}
/**
* check for SQL "BEGIN DECLARE SECTION".
* must compare case insensitive and allow any spacing between words.
*
* @param line a reference to the line to indent.
* @param index the current line index.
* @return true if a hit.
*/
bool ASEnhancer::isBeginDeclareSectionSQL(std::string_view line, size_t index) const
{
size_t hits = 0;
size_t i;
for (i = index; i < line.length(); i++)
{
i = line.find_first_not_of(" \t", i);
if (i == std::string::npos)
return false;
if (line[i] == ';')
break;
if (!isCharPotentialHeader(line, i))
continue;
std::string_view word = getCurrentWord(line, i);
for (char character : word)
character = (char) toupper(character);
if (word == "EXEC" || word == "SQL")
{
i += word.length() - 1;
continue;
}
if (word == "DECLARE" || word == "SECTION")
{
hits++;
i += word.length() - 1;
continue;
}
if (word == "BEGIN")
{
hits++;
i += word.length() - 1;
continue;
}
return false;
}
if (hits == 3)
return true;
return false;
}
/**
* check for SQL "END DECLARE SECTION".
* must compare case insensitive and allow any spacing between words.
*
* @param line a reference to the line to indent.
* @param index the current line index.
* @return true if a hit.
*/
bool ASEnhancer::isEndDeclareSectionSQL(std::string_view line, size_t index) const
{
size_t hits = 0;
size_t i;
for (i = index; i < line.length(); i++)
{
i = line.find_first_not_of(" \t", i);
if (i == std::string::npos)
return false;
if (line[i] == ';')
break;
if (!isCharPotentialHeader(line, i))
continue;
std::string_view word = getCurrentWord(line, i);
for (char character : word)
character = (char) toupper(character);
if (word == "EXEC" || word == "SQL")
{
i += word.length() - 1;
continue;
}
if (word == "DECLARE" || word == "SECTION")
{
hits++;
i += word.length() - 1;
continue;
}
if (word == "END")
{
hits++;
i += word.length() - 1;
continue;
}
return false;
}
if (hits == 3)
return true;
return false;
}
/**
* check if a one-line brace has been reached,
* i.e. if the currently reached '{' character is closed
* with a complimentary '}' elsewhere on the current line,
*.
* @return false = one-line brace has not been reached.
* true = one-line brace has been reached.
*/
bool ASEnhancer::isOneLineBlockReached(std::string_view line, int startChar) const
{
assert(line[startChar] == '{');
bool isInComment_ = false;
bool isInQuote_ = false;
int _braceCount = 1;
int lineLength = line.length();
char quoteChar_ = ' ';
char ch = ' ';
for (int i = startChar + 1; i < lineLength; ++i)
{
ch = line[i];
if (isInComment_)
{
if (line.compare(i, 2, "*/") == 0)
{
isInComment_ = false;
++i;
}
continue;
}
if (ch == '\\')
{
++i;
continue;
}
if (isInQuote_)
{
if (ch == quoteChar_)
isInQuote_ = false;
continue;
}
if (ch == '"'
|| (ch == '\'' && !isDigitSeparator(line, i)))
{
isInQuote_ = true;
quoteChar_ = ch;
continue;
}
if (line.compare(i, 2, "//") == 0)
break;
if (line.compare(i, 2, "/*") == 0)
{
isInComment_ = true;
++i;
continue;
}
if (ch == '{')
++_braceCount;
else if (ch == '}')
--_braceCount;
if (_braceCount == 0)
return true;
}
return false;
}
/**
* parse characters in the current line to determine if an indent
* or unindent is needed.
*/
void ASEnhancer::parseCurrentLine(std::string& line, bool isInPreprocessor, bool isInSQL)
{
bool isSpecialChar = false; // is a backslash escape character
for (size_t i = 0; i < line.length(); i++)
{
char ch = line[i];
// bypass whitespace
if (std::isblank(ch))
continue;
// handle special characters (i.e. backslash+character such as \n, \t, ...)
if (isSpecialChar)
{
isSpecialChar = false;
continue;
}
if (!(isInComment) && line.compare(i, 2, "\\\\") == 0)
{
i++;
continue;
}
if (!(isInComment) && ch == '\\')
{
isSpecialChar = true;
continue;
}
// handle quotes (such as 'x' and "Hello Dolly")
if (!isInComment
&& (ch == '"'
|| (ch == '\'' && !isDigitSeparator(line, i))))
{
if (!isInQuote)
{
quoteChar = ch;
isInQuote = true;
}
else if (quoteChar == ch)
{
isInQuote = false;
continue;
}
}
if (isInQuote)
continue;
// handle comments
if (!(isInComment) && line.compare(i, 2, "//") == 0)
{
// check for windows line markers
if (line.compare(i + 2, 1, "\xf0") > 0)
lineNumber--;
// unindent if not in case braces
if (line.find_first_not_of(" \t") == i
&& sw.switchBraceCount == 1
&& sw.unindentCase)
shouldUnindentComment = true;
break; // finished with the line
}
if (!(isInComment) && line.compare(i, 2, "/*") == 0)
{
// unindent if not in case braces
if (sw.switchBraceCount == 1 && sw.unindentCase)
shouldUnindentComment = true;
isInComment = true;
size_t commentEnd = line.find("*/", i);
if (commentEnd == std::string::npos)
i = line.length() - 1;
else
i = commentEnd - 1;
continue;
}
if ((isInComment) && line.compare(i, 2, "*/") == 0)
{
// unindent if not in case braces
if (sw.switchBraceCount == 1 && sw.unindentCase)
shouldUnindentComment = true;
isInComment = false;
i++;
continue;
}
if (isInComment)
{
// unindent if not in case braces
if (sw.switchBraceCount == 1 && sw.unindentCase)
shouldUnindentComment = true;
size_t commentEnd = line.find("*/", i);
if (commentEnd == std::string::npos)
i = line.length() - 1;
else
i = commentEnd - 1;
continue;
}
// if we have reached this far then we are NOT in a comment or string of special characters
if (line[i] == '{')
braceCount++;
if (line[i] == '}')
braceCount--;
// check for preprocessor within an event table
if (isInEventTable && line[i] == '#' && preprocBlockIndent)
{
std::string preproc;
preproc = line.substr(i + 1);
if (preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef)
eventPreprocDepth += 1;
if (preproc.substr(0, 5) == "endif" && eventPreprocDepth > 0)
eventPreprocDepth -= 1;
}
bool isPotentialKeyword = isCharPotentialHeader(line, i);
// ---------------- wxWidgets and MFC macros ----------------------------------
if (isPotentialKeyword)
{
for (const auto* indentableMacro : *indentableMacros)
{
// 'first' is the beginning macro
if (findKeyword(line, i, indentableMacro->first))
{
nextLineIsEventIndent = true;
break;
}
// 'second' is the ending macro
if (findKeyword(line, i, indentableMacro->second))
{
isInEventTable = false;
eventPreprocDepth = 0;
break;
}
}
}
// ---------------- process SQL -----------------------------------------------
if (isInSQL)
{
if (isBeginDeclareSectionSQL(line, i))
nextLineIsDeclareIndent = true;
if (isEndDeclareSectionSQL(line, i))
isInDeclareSection = false;
break;
}
// ---------------- process switch statements ---------------------------------
if (isPotentialKeyword && findKeyword(line, i, ASResource::AS_SWITCH))
{
switchDepth++;
switchStack.emplace_back(sw); // save current variables
sw.switchBraceCount = 0;
sw.unindentCase = false; // don't clear case until end of switch
i += 5; // bypass switch statement
continue;
}
// just want unindented case statements from this point
if (caseIndent
|| switchDepth == 0
|| (isInPreprocessor && !preprocDefineIndent))
{
// bypass the entire word
if (isPotentialKeyword)
{
std::string_view name = getCurrentWord(line, i);
i += name.length() - 1;
}
continue;
}
i = processSwitchBlock(line, i);
} // end of for loop * end of for loop * end of for loop * end of for loop
}
/**
* process the character at the current index in a switch block.
*
* @param line a reference to the line to indent.
* @param index the current line index.
* @return the new line index.
*/
size_t ASEnhancer::processSwitchBlock(std::string& line, size_t index)
{
size_t i = index;
bool isPotentialKeyword = isCharPotentialHeader(line, i);
if (line[i] == '{')
{
sw.switchBraceCount++;
if (lookingForCaseBrace) // if 1st after case statement
{
sw.unindentCase = true; // unindenting this case
sw.unindentDepth++;
lookingForCaseBrace = false; // not looking now
}
return i;
}
lookingForCaseBrace = false; // no opening brace, don't indent
if (line[i] == '}')
{
sw.switchBraceCount--;
if (sw.switchBraceCount == 0) // if end of switch statement
{
int lineUnindent = sw.unindentDepth;
if (line.find_first_not_of(" \t") == i
&& !switchStack.empty())
lineUnindent = switchStack[switchStack.size() - 1].unindentDepth;
if (shouldUnindentLine)
{
if (lineUnindent > 0)
i -= unindentLine(line, lineUnindent);
shouldUnindentLine = false;
}
switchDepth--;
sw = switchStack.back();
switchStack.pop_back();
}
return i;
}
if (isPotentialKeyword
&& (findKeyword(line, i, ASResource::AS_CASE)
|| findKeyword(line, i, ASResource::AS_DEFAULT)))
{
if (sw.unindentCase) // if unindented last case
{
sw.unindentCase = false; // stop unindenting previous case
sw.unindentDepth--;
}
i = findCaseColon(line, i);
i++;
for (; i < line.length(); i++) // bypass whitespace
{
if (!std::isblank(line[i]))
break;
}
if (i < line.length())
{
if (line[i] == '{')
{
braceCount++;
sw.switchBraceCount++;
if (!isOneLineBlockReached(line, i))
unindentNextLine = true;
return i;
}
}
lookingForCaseBrace = true;
i--; // need to process this char
return i;
}
if (isPotentialKeyword)
{
std::string_view name = getCurrentWord(line, i); // bypass the entire name
i += name.length() - 1;
}
return i;
}
/**
* unindent a line by a given number of tabsets
* by erasing the leading whitespace from the line argument.
*
* @param line a reference to the line to unindent.
* @param unindent the number of tabsets to erase.
* @return the number of characters erased.
*/
int ASEnhancer::unindentLine(std::string& line, int unindent) const
{
size_t whitespace = line.find_first_not_of(" \t");
if (whitespace == std::string::npos) // if line is blank
whitespace = line.length(); // must remove padding, if any
if (whitespace == 0)
return 0;
size_t charsToErase = 0;
if (forceTab && indentLength != tabLength)
{
// replace tab indents with spaces
convertForceTabIndentToSpaces(line);
// remove the space indents
size_t spaceIndentLength = line.find_first_not_of(" \t");
charsToErase = unindent * indentLength;
if (charsToErase <= spaceIndentLength)
line.erase(0, charsToErase);
else
charsToErase = 0;
// replace leading spaces with tab indents
convertSpaceIndentToForceTab(line);
}
else if (useTabs)
{
charsToErase = unindent;
if (charsToErase <= whitespace)
line.erase(0, charsToErase);
else
charsToErase = 0;
}
else // spaces
{
charsToErase = unindent * indentLength;
if (charsToErase <= whitespace)
line.erase(0, charsToErase);
else
charsToErase = 0;
}
return charsToErase;
}
} // end namespace astyle
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+170
View File
@@ -0,0 +1,170 @@
// ASLocalizer.h
// Copyright (c) 2025 The Artistic Style Authors.
// This code is licensed under the MIT License.
// License.md describes the conditions under which this software may be distributed.
#ifndef ASLOCALIZER_H
#define ASLOCALIZER_H
#include <string>
#include <vector>
// library builds do not need ASLocalizer
#ifdef ASTYLE_JNI
#ifndef ASTYLE_LIB // ASTYLE_LIB must be defined for ASTYLE_JNI
#define ASTYLE_LIB
#endif
#endif // ASTYLE_JNI
namespace astyle {
#ifndef ASTYLE_LIB
//-----------------------------------------------------------------------------
// ASLocalizer class for console build.
// This class encapsulates all language-dependent settings and is a
// generalization of the C locale concept.
//-----------------------------------------------------------------------------
class Translation;
class ASLocalizer
{
public: // functions
ASLocalizer();
virtual ~ASLocalizer();
std::string getLanguageID() const;
const Translation* getTranslationClass() const;
#ifdef _WIN32
void setLanguageFromLCID(size_t lcid);
#endif
void setLanguageFromName(const char* langID);
const char* settext(const char* textIn) const;
private: // functions
void setTranslationClass();
private: // variables
Translation* m_translationClass;// pointer to a polymorphic Translation class
std::string m_langID; // language identifier from the locale
std::string m_subLangID; // sub language identifier, if needed
#ifdef _WIN32
size_t m_lcid; // LCID of the user locale (Windows only)
size_t m_codepage; // active codepage, 65001 = utf-8
#endif
};
//----------------------------------------------------------------------------
// Translation base class.
//----------------------------------------------------------------------------
class Translation
// This base class is inherited by the language translation classes.
// Polymorphism is used to call the correct language translator.
// This class contains the translation std::vector and settext translation method.
// The language std::vector is built by the language sub classes.
// NOTE: This class must have virtual methods for typeid() to work.
// typeid() is used by AStyleTestI18n_Localizer.cpp.
{
public:
Translation();
virtual ~Translation() = default;
std::string convertToMultiByte(const std::wstring& wideStr) const;
std::string getTranslationString(size_t i) const;
size_t getTranslationVectorSize() const;
bool getWideTranslation(const std::string& stringIn, std::wstring& wideOut) const;
std::string& translate(const std::string& stringIn) const;
protected:
void addPair(const std::string& english, const std::wstring& translated);
// variables
std::vector<std::pair<std::string, std::wstring> > m_translationVector;
private:
// the number of translation pairs added a constructor
static const size_t translationElements = 30; // need static for vs2013
// the translated std::string
mutable std::string m_mbTranslation;
};
//----------------------------------------------------------------------------
// Translation classes
// One class for each language.
// These classes have only a constructor which builds the language std::vector.
//----------------------------------------------------------------------------
class Bulgarian : public Translation
{ public: Bulgarian(); };
class ChineseSimplified : public Translation
{ public: ChineseSimplified(); };
class ChineseTraditional : public Translation
{ public: ChineseTraditional(); };
class Dutch : public Translation
{ public: Dutch(); };
class English : public Translation
{ public: English(); };
class Estonian : public Translation
{ public: Estonian(); };
class Finnish : public Translation
{ public: Finnish(); };
class French : public Translation
{ public: French(); };
class German : public Translation
{ public: German(); };
class Greek : public Translation
{ public: Greek(); };
class Hindi : public Translation
{ public: Hindi(); };
class Hungarian : public Translation
{ public: Hungarian(); };
class Italian : public Translation
{ public: Italian(); };
class Japanese : public Translation
{ public: Japanese(); };
class Korean : public Translation
{ public: Korean(); };
class Norwegian : public Translation
{ public: Norwegian(); };
class Polish : public Translation
{ public: Polish(); };
class Portuguese : public Translation
{ public: Portuguese(); };
class Romanian : public Translation
{ public: Romanian(); };
class Russian : public Translation
{ public: Russian(); };
class Spanish : public Translation
{ public: Spanish(); };
class Swedish : public Translation
{ public: Swedish(); };
class Ukrainian : public Translation
{ public: Ukrainian(); };
#endif // ASTYLE_LIB
} // namespace astyle
#endif // ASLOCALIZER_H
+828
View File
@@ -0,0 +1,828 @@
// ASResource.cpp
// Copyright (c) 2025 The Artistic Style Authors.
// This code is licensed under the MIT License.
// License.md describes the conditions under which this software may be distributed.
//-----------------------------------------------------------------------------
// headers
//-----------------------------------------------------------------------------
#include "astyle.h"
#include <algorithm>
#include <string_view>
//-----------------------------------------------------------------------------
// astyle namespace
//-----------------------------------------------------------------------------
namespace astyle {
//
const std::string ASResource::_AS_EXCEPT = std::string("__except");
const std::string ASResource::_AS_FINALLY = std::string("__finally");
const std::string ASResource::_AS_TRY = std::string("__try");
const std::string ASResource::AS_ADD = std::string("add");
const std::string ASResource::AS_AUTO = std::string("auto");
const std::string ASResource::AS_AUTORELEASEPOOL = std::string("autoreleasepool");
const std::string ASResource::AS_CASE = std::string("case");
const std::string ASResource::AS_CATCH = std::string("catch");
const std::string ASResource::AS_CLASS = std::string("class");
const std::string ASResource::AS_CONST = std::string("const");
const std::string ASResource::AS_CONST_CAST = std::string("const_cast");
const std::string ASResource::AS_DEFAULT = std::string("default");
const std::string ASResource::AS_DELEGATE = std::string("delegate");
const std::string ASResource::AS_DELETE = std::string("delete");
const std::string ASResource::AS_DO = std::string("do");
const std::string ASResource::AS_DYNAMIC_CAST = std::string("dynamic_cast");
const std::string ASResource::AS_ELSE = std::string("else");
const std::string ASResource::AS_END = std::string("end");
const std::string ASResource::AS_ENUM = std::string("enum");
const std::string ASResource::AS_EXTERN = std::string("extern");
const std::string ASResource::AS_FINAL = std::string("final");
const std::string ASResource::AS_FINALLY = std::string("finally");
const std::string ASResource::AS_FIXED = std::string("fixed");
const std::string ASResource::AS_FOR = std::string("for");
const std::string ASResource::AS_FOREACH = std::string("foreach");
const std::string ASResource::AS_FOREVER = std::string("forever");
const std::string ASResource::AS_GET = std::string("get");
const std::string ASResource::AS_IF = std::string("if");
const std::string ASResource::AS_INTERFACE = std::string("interface");
const std::string ASResource::AS_INTERRUPT = std::string("interrupt");
const std::string ASResource::AS_LET = std::string("let");
const std::string ASResource::AS_LOCK = std::string("lock");
const std::string ASResource::AS_MODULE = std::string("module"); // CORBA IDL module definition
const std::string ASResource::AS_NAMESPACE = std::string("namespace");
const std::string ASResource::AS_NEW = std::string("new");
const std::string ASResource::AS_NOEXCEPT = std::string("noexcept");
const std::string ASResource::AS_NS_DURING = std::string("NS_DURING");
const std::string ASResource::AS_NS_HANDLER = std::string("NS_HANDLER");
const std::string ASResource::AS_OPERATOR = std::string("operator");
const std::string ASResource::AS_OVERRIDE = std::string("override");
const std::string ASResource::AS_PRIVATE = std::string("private");
const std::string ASResource::AS_PROTECTED = std::string("protected");
const std::string ASResource::AS_PUBLIC = std::string("public");
const std::string ASResource::AS_QFOREACH = std::string("Q_FOREACH");
const std::string ASResource::AS_QFOREVER = std::string("Q_FOREVER");
const std::string ASResource::AS_REINTERPRET_CAST = std::string("reinterpret_cast");
const std::string ASResource::AS_REMOVE = std::string("remove");
const std::string ASResource::AS_SEALED = std::string("sealed");
const std::string ASResource::AS_SELECTOR = std::string("selector");
const std::string ASResource::AS_SET = std::string("set");
const std::string ASResource::AS_STATIC = std::string("static");
const std::string ASResource::AS_STATIC_CAST = std::string("static_cast");
const std::string ASResource::AS_STRUCT = std::string("struct");
const std::string ASResource::AS_TYPEDEF_STRUCT = std::string("typedef struct");
const std::string ASResource::AS_SWITCH = std::string("switch");
const std::string ASResource::AS_SYNCHRONIZED = std::string("synchronized");
const std::string ASResource::AS_TEMPLATE = std::string("template");
const std::string ASResource::AS_THROW = std::string("throw");
const std::string ASResource::AS_THROWS = std::string("throws");
const std::string ASResource::AS_TRY = std::string("try");
const std::string ASResource::AS_UNCHECKED = std::string("unchecked");
const std::string ASResource::AS_UNION = std::string("union");
const std::string ASResource::AS_UNSAFE = std::string("unsafe");
const std::string ASResource::AS_USING = std::string("using");
const std::string ASResource::AS_VOLATILE = std::string("volatile");
const std::string ASResource::AS_WHERE = std::string("where");
const std::string ASResource::AS_WHILE = std::string("while");
const std::string ASResource::AS_ASM = std::string("asm");
const std::string ASResource::AS__ASM__ = std::string("__asm__");
const std::string ASResource::AS_MS_ASM = std::string("_asm");
const std::string ASResource::AS_MS__ASM = std::string("__asm");
const std::string ASResource::AS_BAR_DEFINE = std::string("#define");
const std::string ASResource::AS_BAR_INCLUDE = std::string("#include");
const std::string ASResource::AS_BAR_IF = std::string("#if");
const std::string ASResource::AS_BAR_EL = std::string("#el");
const std::string ASResource::AS_BAR_ENDIF = std::string("#endif");
const std::string ASResource::AS_OPEN_PAREN = std::string("(");
const std::string ASResource::AS_CLOSE_PAREN = std::string(")");
const std::string ASResource::AS_OPEN_BRACE = std::string("{");
const std::string ASResource::AS_CLOSE_BRACE = std::string("}");
const std::string ASResource::AS_OPEN_LINE_COMMENT = std::string("//");
const std::string ASResource::AS_OPEN_COMMENT = std::string("/*");
const std::string ASResource::AS_CLOSE_COMMENT = std::string("*/");
const std::string ASResource::AS_GSC_OPEN_COMMENT = std::string("/#");
const std::string ASResource::AS_GSC_CLOSE_COMMENT = std::string("#/");
const std::string ASResource::AS_OPEN_CONFLICT = std::string("<<<<<<<");
const std::string ASResource::AS_MIDDLE_CONFLICT = std::string("=======");
const std::string ASResource::AS_CLOSE_CONFLICT = std::string(">>>>>>>");
const std::string ASResource::AS_ASSIGN = std::string("=");
const std::string ASResource::AS_PLUS_ASSIGN = std::string("+=");
const std::string ASResource::AS_MINUS_ASSIGN = std::string("-=");
const std::string ASResource::AS_MULT_ASSIGN = std::string("*=");
const std::string ASResource::AS_DIV_ASSIGN = std::string("/=");
const std::string ASResource::AS_MOD_ASSIGN = std::string("%=");
const std::string ASResource::AS_OR_ASSIGN = std::string("|=");
const std::string ASResource::AS_AND_ASSIGN = std::string("&=");
const std::string ASResource::AS_XOR_ASSIGN = std::string("^=");
const std::string ASResource::AS_GR_GR_ASSIGN = std::string(">>=");
const std::string ASResource::AS_LS_LS_ASSIGN = std::string("<<=");
const std::string ASResource::AS_GR_GR_GR_ASSIGN = std::string(">>>=");
const std::string ASResource::AS_LS_LS_LS_ASSIGN = std::string("<<<=");
const std::string ASResource::AS_GCC_MIN_ASSIGN = std::string("<?");
const std::string ASResource::AS_GCC_MAX_ASSIGN = std::string(">?");
const std::string ASResource::AS_RETURN = std::string("return");
const std::string ASResource::AS_CIN = std::string("cin");
const std::string ASResource::AS_COUT = std::string("cout");
const std::string ASResource::AS_CERR = std::string("cerr");
const std::string ASResource::AS_EQUAL = std::string("==");
const std::string ASResource::AS_PLUS_PLUS = std::string("++");
const std::string ASResource::AS_MINUS_MINUS = std::string("--");
const std::string ASResource::AS_NOT_EQUAL = std::string("!=");
const std::string ASResource::AS_GR_EQUAL = std::string(">=");
const std::string ASResource::AS_GR_GR = std::string(">>");
const std::string ASResource::AS_GR_GR_GR = std::string(">>>");
const std::string ASResource::AS_LS_EQUAL = std::string("<=");
const std::string ASResource::AS_LS_LS = std::string("<<");
const std::string ASResource::AS_LS_LS_LS = std::string("<<<");
const std::string ASResource::AS_QUESTION_QUESTION = std::string("??");
const std::string ASResource::AS_LAMBDA = std::string("=>"); // C# lambda expression arrow
const std::string ASResource::AS_ARROW = std::string("->");
const std::string ASResource::AS_AND = std::string("&&");
const std::string ASResource::AS_OR = std::string("||");
const std::string ASResource::AS_SCOPE_RESOLUTION = std::string("::");
const std::string ASResource::AS_SPACESHIP = std::string("<=>");
const std::string ASResource::AS_EQUAL_JS = std::string("===");
const std::string ASResource::AS_COALESCE_CS = std::string("?" "?="); // Avoid trigraph
const std::string ASResource::AS_PLUS = std::string("+");
const std::string ASResource::AS_MINUS = std::string("-");
const std::string ASResource::AS_MULT = std::string("*");
const std::string ASResource::AS_DIV = std::string("/");
const std::string ASResource::AS_MOD = std::string("%");
const std::string ASResource::AS_GR = std::string(">");
const std::string ASResource::AS_LS = std::string("<");
const std::string ASResource::AS_NOT = std::string("!");
const std::string ASResource::AS_BIT_OR = std::string("|");
const std::string ASResource::AS_BIT_AND = std::string("&");
const std::string ASResource::AS_BIT_NOT = std::string("~");
const std::string ASResource::AS_BIT_XOR = std::string("^");
const std::string ASResource::AS_QUESTION = std::string("?");
const std::string ASResource::AS_COLON = std::string(":");
const std::string ASResource::AS_COMMA = std::string(",");
const std::string ASResource::AS_DOT = std::string(".");
const std::string ASResource::AS_SEMICOLON = std::string(";");
/**
* Sort comparison function.
* Compares the length of the value of pointers in the vectors.
* The LONGEST std::strings will be first in the vector.
*
* @param a and b, the std::string pointers to be compared.
*/
bool sortOnLength(const std::string* a, const std::string* b)
{
return (*a).length() > (*b).length();
}
/**
* Sort comparison function.
* Compares the value of pointers in the vectors.
*
* @param a and b, the std::string pointers to be compared.
*/
bool sortOnName(const std::string* a, const std::string* b)
{
return *a < *b;
}
/**
* Build the vector of assignment operators.
* Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
*
* @param assignmentOperators a reference to the vector to be built.
*/
void ASResource::buildAssignmentOperators(std::vector<const std::string*>* assignmentOperators)
{
const size_t elements = 15;
assignmentOperators->reserve(elements);
assignmentOperators->emplace_back(&AS_ASSIGN);
assignmentOperators->emplace_back(&AS_PLUS_ASSIGN);
assignmentOperators->emplace_back(&AS_MINUS_ASSIGN);
assignmentOperators->emplace_back(&AS_MULT_ASSIGN);
assignmentOperators->emplace_back(&AS_DIV_ASSIGN);
assignmentOperators->emplace_back(&AS_MOD_ASSIGN);
assignmentOperators->emplace_back(&AS_OR_ASSIGN);
assignmentOperators->emplace_back(&AS_AND_ASSIGN);
assignmentOperators->emplace_back(&AS_XOR_ASSIGN);
// Java
assignmentOperators->emplace_back(&AS_GR_GR_GR_ASSIGN);
assignmentOperators->emplace_back(&AS_GR_GR_ASSIGN);
assignmentOperators->emplace_back(&AS_LS_LS_ASSIGN);
// Unknown
assignmentOperators->emplace_back(&AS_LS_LS_LS_ASSIGN);
assert(assignmentOperators->size() < elements);
sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength);
}
/**
* Build the vector of C++ cast operators.
* Used by ONLY ASFormatter.cpp
*
* @param castOperators a reference to the vector to be built.
*/
void ASResource::buildCastOperators(std::vector<const std::string*>* castOperators)
{
const size_t elements = 5;
castOperators->reserve(elements);
castOperators->emplace_back(&AS_CONST_CAST);
castOperators->emplace_back(&AS_DYNAMIC_CAST);
castOperators->emplace_back(&AS_REINTERPRET_CAST);
castOperators->emplace_back(&AS_STATIC_CAST);
assert(castOperators->size() < elements);
sort(castOperators->begin(), castOperators->end(), sortOnName);
}
/**
* Build the vector of header words.
* Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
*
* @param headers a reference to the vector to be built.
*/
void ASResource::buildHeaders(std::vector<const std::string*>* headers, int fileType, bool beautifier)
{
const size_t elements = 25;
headers->reserve(elements);
headers->emplace_back(&AS_IF);
headers->emplace_back(&AS_ELSE);
headers->emplace_back(&AS_FOR);
headers->emplace_back(&AS_WHILE);
headers->emplace_back(&AS_DO);
headers->emplace_back(&AS_SWITCH);
headers->emplace_back(&AS_CASE);
headers->emplace_back(&AS_DEFAULT);
headers->emplace_back(&AS_TRY);
headers->emplace_back(&AS_CATCH);
headers->emplace_back(&AS_QFOREACH); // QT
headers->emplace_back(&AS_QFOREVER); // QT
headers->emplace_back(&AS_FOREACH); // QT & C#
headers->emplace_back(&AS_FOREVER); // Qt & Boost
if (fileType == C_TYPE || fileType == OBJC_TYPE)
{
headers->emplace_back(&_AS_TRY); // __try
headers->emplace_back(&_AS_FINALLY); // __finally
headers->emplace_back(&_AS_EXCEPT); // __except
}
if (fileType == JAVA_TYPE)
{
headers->emplace_back(&AS_FINALLY);
headers->emplace_back(&AS_SYNCHRONIZED);
}
if (fileType == SHARP_TYPE)
{
headers->emplace_back(&AS_FINALLY);
headers->emplace_back(&AS_LOCK);
headers->emplace_back(&AS_FIXED);
headers->emplace_back(&AS_GET);
headers->emplace_back(&AS_SET);
headers->emplace_back(&AS_ADD);
headers->emplace_back(&AS_REMOVE);
headers->emplace_back(&AS_USING);
}
if (beautifier)
{
if (fileType == C_TYPE || fileType == OBJC_TYPE)
{
headers->emplace_back(&AS_TEMPLATE);
}
if (fileType == JAVA_TYPE)
{
headers->emplace_back(&AS_STATIC); // for static constructor
}
}
assert(headers->size() < elements);
sort(headers->begin(), headers->end(), sortOnName);
}
/**
* Build the vector of indentable headers.
* Used by ONLY ASBeautifier.cpp
*
* @param indentableHeaders a reference to the vector to be built.
*/
void ASResource::buildIndentableHeaders(std::vector<const std::string*>* indentableHeaders)
{
indentableHeaders->emplace_back(&AS_RETURN);
}
/**
* Build the vector of indentable macros pairs.
* Initialized by ASFormatter, used by ONLY ASEnhancer.cpp
*
* @param indentableMacros a reference to the vector to be built.
*/
void ASResource::buildIndentableMacros(std::vector<const std::pair<const std::string, const std::string>* >* indentableMacros)
{
const size_t elements = 10;
indentableMacros->reserve(elements);
// the pairs must be retained in memory because of pair pointers
using macro_pair = std::pair<const std::string, const std::string>;
static const macro_pair macros[] =
{
// wxWidgets
macro_pair("BEGIN_EVENT_TABLE", "END_EVENT_TABLE"),
macro_pair("wxBEGIN_EVENT_TABLE", "wxEND_EVENT_TABLE"),
// MFC
macro_pair("BEGIN_DISPATCH_MAP", "END_DISPATCH_MAP"),
macro_pair("BEGIN_EVENT_MAP", "END_EVENT_MAP"),
macro_pair("BEGIN_MESSAGE_MAP", "END_MESSAGE_MAP"),
macro_pair("BEGIN_PROPPAGEIDS", "END_PROPPAGEIDS"),
};
for (const macro_pair& macro : macros)
indentableMacros->emplace_back(&macro);
assert(indentableMacros->size() < elements);
}
/**
* Build the vector of non-assignment operators.
* Used by ONLY ASBeautifier.cpp
*
* @param nonAssignmentOperators a reference to the vector to be built.
* @param fileType language identifier.
*
*/
void ASResource::buildNonAssignmentOperators(std::vector<const std::string*>* nonAssignmentOperators, int fileType)
{
const size_t elements = 16;
nonAssignmentOperators->reserve(elements);
nonAssignmentOperators->emplace_back(&AS_EQUAL);
nonAssignmentOperators->emplace_back(&AS_PLUS_PLUS);
nonAssignmentOperators->emplace_back(&AS_MINUS_MINUS);
nonAssignmentOperators->emplace_back(&AS_NOT_EQUAL);
nonAssignmentOperators->emplace_back(&AS_GR_EQUAL);
nonAssignmentOperators->emplace_back(&AS_GR_GR);
nonAssignmentOperators->emplace_back(&AS_LS_EQUAL);
nonAssignmentOperators->emplace_back(&AS_LS_LS);
nonAssignmentOperators->emplace_back(&AS_ARROW);
nonAssignmentOperators->emplace_back(&AS_AND);
nonAssignmentOperators->emplace_back(&AS_OR);
nonAssignmentOperators->emplace_back(&AS_LAMBDA);
nonAssignmentOperators->emplace_back(&AS_DOT);
if (fileType == JAVA_TYPE) {
nonAssignmentOperators->emplace_back(&AS_GR_GR_GR);
nonAssignmentOperators->emplace_back(&AS_LS_LS_LS);
}
assert(nonAssignmentOperators->size() < elements);
sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength);
}
/**
* Build the vector of header non-paren headers.
* Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
* NOTE: Non-paren headers should also be included in the headers vector.
*
* @param nonParenHeaders a reference to the std::vector to be built.
* @param fileType language identifier.
*
*/
void ASResource::buildNonParenHeaders(std::vector<const std::string*>* nonParenHeaders, int fileType, bool beautifier)
{
const size_t elements = 20;
nonParenHeaders->reserve(elements);
nonParenHeaders->emplace_back(&AS_ELSE);
nonParenHeaders->emplace_back(&AS_DO);
nonParenHeaders->emplace_back(&AS_TRY);
nonParenHeaders->emplace_back(&AS_CATCH); // can be paren or non-paren
nonParenHeaders->emplace_back(&AS_CASE); // can be paren or non-paren
nonParenHeaders->emplace_back(&AS_DEFAULT);
nonParenHeaders->emplace_back(&AS_QFOREVER); // QT
nonParenHeaders->emplace_back(&AS_FOREVER); // Boost
if (fileType == C_TYPE || fileType == OBJC_TYPE)
{
nonParenHeaders->emplace_back(&_AS_TRY); // __try
nonParenHeaders->emplace_back(&_AS_FINALLY); // __finally
}
if (fileType == JAVA_TYPE)
{
nonParenHeaders->emplace_back(&AS_FINALLY);
}
if (fileType == SHARP_TYPE)
{
nonParenHeaders->emplace_back(&AS_FINALLY);
nonParenHeaders->emplace_back(&AS_GET);
nonParenHeaders->emplace_back(&AS_SET);
nonParenHeaders->emplace_back(&AS_ADD);
nonParenHeaders->emplace_back(&AS_REMOVE);
}
if (beautifier)
{
if (fileType == C_TYPE)
{
nonParenHeaders->emplace_back(&AS_TEMPLATE);
}
if (fileType == JAVA_TYPE)
{
nonParenHeaders->emplace_back(&AS_STATIC);
}
}
assert(nonParenHeaders->size() < elements);
sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName);
}
/**
* Build the vector of operators.
* Used by ONLY ASFormatter.cpp
*
* @param operators a reference to the vector to be built.
*/
void ASResource::buildOperators(std::vector<const std::string*>* operators, int fileType)
{
const size_t elements = 50;
operators->reserve(elements);
operators->emplace_back(&AS_PLUS_ASSIGN);
operators->emplace_back(&AS_MINUS_ASSIGN);
operators->emplace_back(&AS_MULT_ASSIGN);
operators->emplace_back(&AS_DIV_ASSIGN);
operators->emplace_back(&AS_MOD_ASSIGN);
operators->emplace_back(&AS_OR_ASSIGN);
operators->emplace_back(&AS_AND_ASSIGN);
operators->emplace_back(&AS_XOR_ASSIGN);
operators->emplace_back(&AS_EQUAL);
operators->emplace_back(&AS_PLUS_PLUS);
operators->emplace_back(&AS_MINUS_MINUS);
operators->emplace_back(&AS_NOT_EQUAL);
operators->emplace_back(&AS_GR_EQUAL);
operators->emplace_back(&AS_GR_GR_GR_ASSIGN);
operators->emplace_back(&AS_GR_GR_ASSIGN);
operators->emplace_back(&AS_GR_GR_GR);
operators->emplace_back(&AS_GR_GR);
operators->emplace_back(&AS_LS_EQUAL);
operators->emplace_back(&AS_LS_LS_LS_ASSIGN);
operators->emplace_back(&AS_LS_LS_ASSIGN);
operators->emplace_back(&AS_LS_LS_LS);
operators->emplace_back(&AS_LS_LS);
operators->emplace_back(&AS_QUESTION_QUESTION);
operators->emplace_back(&AS_LAMBDA);
operators->emplace_back(&AS_ARROW);
operators->emplace_back(&AS_AND);
operators->emplace_back(&AS_OR);
operators->emplace_back(&AS_SCOPE_RESOLUTION);
operators->emplace_back(&AS_PLUS);
operators->emplace_back(&AS_MINUS);
operators->emplace_back(&AS_MULT);
operators->emplace_back(&AS_DIV);
operators->emplace_back(&AS_MOD);
operators->emplace_back(&AS_QUESTION);
operators->emplace_back(&AS_COLON);
operators->emplace_back(&AS_ASSIGN);
operators->emplace_back(&AS_LS);
operators->emplace_back(&AS_GR);
operators->emplace_back(&AS_NOT);
operators->emplace_back(&AS_BIT_OR);
operators->emplace_back(&AS_BIT_AND);
operators->emplace_back(&AS_BIT_NOT);
operators->emplace_back(&AS_BIT_XOR);
if (fileType == C_TYPE)
{
operators->emplace_back(&AS_GCC_MIN_ASSIGN);
operators->emplace_back(&AS_GCC_MAX_ASSIGN);
operators->emplace_back(&AS_SPACESHIP);
}
if (fileType == JS_TYPE)
{
operators->emplace_back(&AS_EQUAL_JS);
}
if (fileType == SHARP_TYPE)
{
operators->emplace_back(&AS_COALESCE_CS);
}
assert(operators->size() < elements);
sort(operators->begin(), operators->end(), sortOnLength);
}
/**
* Build the vector of pre-block statements.
* Used by ONLY ASBeautifier.cpp
* NOTE: Cannot be both a header and a preBlockStatement.
*
* @param preBlockStatements a reference to the vector to be built.
*/
void ASResource::buildPreBlockStatements(std::vector<const std::string*>* preBlockStatements, int fileType)
{
const size_t elements = 10;
preBlockStatements->reserve(elements);
preBlockStatements->emplace_back(&AS_CLASS);
if (fileType == C_TYPE || fileType == OBJC_TYPE)
{
preBlockStatements->emplace_back(&AS_STRUCT);
preBlockStatements->emplace_back(&AS_UNION);
preBlockStatements->emplace_back(&AS_NAMESPACE);
preBlockStatements->emplace_back(&AS_MODULE); // for CORBA IDL
preBlockStatements->emplace_back(&AS_INTERFACE); // for CORBA IDL
}
if (fileType == JAVA_TYPE)
{
preBlockStatements->emplace_back(&AS_INTERFACE);
preBlockStatements->emplace_back(&AS_THROWS);
}
if (fileType == SHARP_TYPE)
{
preBlockStatements->emplace_back(&AS_INTERFACE);
preBlockStatements->emplace_back(&AS_NAMESPACE);
preBlockStatements->emplace_back(&AS_WHERE);
preBlockStatements->emplace_back(&AS_STRUCT);
}
assert(preBlockStatements->size() < elements);
sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName);
}
/**
* Build the vector of pre-command headers.
* Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
* NOTE: Cannot be both a header and a preCommandHeader.
*
* A preCommandHeader is in a function definition between
* the closing paren and the opening brace.
* e.g. in "void foo() const {}", "const" is a preCommandHeader.
*/
void ASResource::buildPreCommandHeaders(std::vector<const std::string*>* preCommandHeaders, int fileType)
{
const size_t elements = 10;
preCommandHeaders->reserve(elements);
if (fileType == C_TYPE || fileType == OBJC_TYPE)
{
preCommandHeaders->emplace_back(&AS_CONST);
preCommandHeaders->emplace_back(&AS_FINAL);
preCommandHeaders->emplace_back(&AS_INTERRUPT);
preCommandHeaders->emplace_back(&AS_NOEXCEPT);
preCommandHeaders->emplace_back(&AS_OVERRIDE);
preCommandHeaders->emplace_back(&AS_VOLATILE);
preCommandHeaders->emplace_back(&AS_SEALED); // Visual C only
}
if (fileType == OBJC_TYPE)
{
preCommandHeaders->emplace_back(&AS_AUTORELEASEPOOL); // Obj-C only
}
if (fileType == JAVA_TYPE)
{
preCommandHeaders->emplace_back(&AS_THROWS);
}
if (fileType == SHARP_TYPE)
{
preCommandHeaders->emplace_back(&AS_WHERE);
}
assert(preCommandHeaders->size() < elements);
sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName);
}
/**
* Build the vector of pre-definition headers.
* Used by ONLY ASFormatter.cpp
* NOTE: Do NOT add 'enum' here. It is an array type brace.
* NOTE: Do NOT add 'extern' here. Do not want an extra indent.
*
* @param preDefinitionHeaders a reference to the vector to be built.
*/
void ASResource::buildPreDefinitionHeaders(std::vector<const std::string*>* preDefinitionHeaders, int fileType)
{
const size_t elements = 10;
preDefinitionHeaders->reserve(elements);
preDefinitionHeaders->emplace_back(&AS_CLASS);
if (fileType == C_TYPE || fileType == OBJC_TYPE)
{
preDefinitionHeaders->emplace_back(&AS_STRUCT);
preDefinitionHeaders->emplace_back(&AS_UNION);
preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
preDefinitionHeaders->emplace_back(&AS_MODULE); // for CORBA IDL
preDefinitionHeaders->emplace_back(&AS_INTERFACE); // for CORBA IDL
}
if (fileType == JAVA_TYPE)
{
preDefinitionHeaders->emplace_back(&AS_INTERFACE);
}
if (fileType == SHARP_TYPE)
{
preDefinitionHeaders->emplace_back(&AS_STRUCT);
preDefinitionHeaders->emplace_back(&AS_INTERFACE);
preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
}
assert(preDefinitionHeaders->size() < elements);
sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ASBase Functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// check if a specific line position contains a header.
const std::string* ASBase::findHeader(std::string_view line, int i,
const std::vector<const std::string*>* possibleHeaders) const
{
assert(isCharPotentialHeader(line, i));
// check the word
size_t maxHeaders = possibleHeaders->size();
for (size_t p = 0; p < maxHeaders; p++)
{
const std::string* header = (*possibleHeaders)[p];
const size_t wordEnd = i + header->length();
if (wordEnd > line.length())
continue;
int result = (line.compare(i, header->length(), *header));
if (result > 0)
continue;
if (result < 0)
break;
// check that this is not part of a longer word
if (wordEnd == line.length())
return header;
if (isLegalNameChar(line[wordEnd]))
continue;
const char peekChar = peekNextChar(line, wordEnd - 1);
// is not a header if part of a definition
if (peekChar == ',' || peekChar == ')')
break;
// the following accessor definitions are NOT headers
// goto default; is NOT a header
// default(int) keyword in C# is NOT a header
if ((header == &ASResource::AS_GET
|| header == &ASResource::AS_SET
|| header == &ASResource::AS_DEFAULT)
&& (peekChar == '.' || peekChar == ';' || peekChar == '(' || peekChar == '='))
break;
return header;
}
return nullptr;
}
// check if a specific line position contains a keyword.
bool ASBase::findKeyword(std::string_view line, int i, std::string_view keyword) const
{
assert(isCharPotentialHeader(line, i));
// check the word
const size_t keywordLength = keyword.length();
const size_t wordEnd = i + keywordLength;
if (wordEnd > line.length())
return false;
if (line.compare(i, keywordLength, keyword) != 0)
return false;
// check that this is not part of a longer word
if (wordEnd == line.length())
{
//std::cerr << "findKeyword t1 \n";
return true;
}
if (isLegalNameChar(line[wordEnd]))
return false;
// is not a keyword if part of a definition
const char peekChar = peekNextChar(line, (int) wordEnd - 1);
if (peekChar == ',' || peekChar == ')')
return false;
//std::cerr << "findKeyword t2 \n";
return true;
}
// check if a specific line position contains an operator.
const std::string* ASBase::findOperator(std::string_view line, int i,
const std::vector<const std::string*>* possibleOperators) const
{
assert(isCharPotentialOperator(line[i]));
// find the operator in the vector
// the vector contains the LONGEST operators first
// must loop thru the entire vector
size_t maxOperators = possibleOperators->size();
for (size_t p = 0; p < maxOperators; p++)
{
const size_t wordEnd = i + (*(*possibleOperators)[p]).length();
if (wordEnd > line.length())
continue;
if (line.compare(i, (*(*possibleOperators)[p]).length(), *(*possibleOperators)[p]) == 0)
return (*possibleOperators)[p];
}
return nullptr;
}
// get the current word on a line
// index must point to the beginning of the word
std::string_view ASBase::getCurrentWord(std::string_view line, size_t index) const
{
//assert(isCharPotentialHeader(line, index));
size_t lineLength = line.length();
size_t i;
for (i = index; i < lineLength; i++)
{
if (!isLegalNameChar(line[i])
|| ( (isCStyle() || isJavaStyle()) && i > index && line[i] == '.')
)
break;
}
return line.substr(index, i - index);
}
// check if a specific character can be used in a legal variable/method/class name
bool ASBase::isLegalNameChar(char ch) const
{
if (std::isblank(ch))
return false;
if ((unsigned char) ch > 127)
return false;
return (isalnum((unsigned char) ch)
|| ch == '_'
|| (!isSharpStyle() && ch == '.' )
|| (isJavaStyle() && ch == '$')
|| (isSharpStyle() && ch == '@')); // may be used as a prefix
}
// check if a specific character can be part of a header
bool ASBase::isCharPotentialHeader(std::string_view line, size_t i) const
{
assert(!std::isblank(line[i]));
char prevCh = ' ';
if (i > 0)
prevCh = line[i - 1];
if (i > 1 && line[i - 2] == '\\')
prevCh = ' ';
if (!isLegalNameChar(prevCh) && isLegalNameChar(line[i]))
return true;
return false;
}
// check if a specific character can be part of an operator
bool ASBase::isCharPotentialOperator(char ch) const
{
assert(!std::isblank(ch));
if ((unsigned) ch > 127)
return false;
return (ispunct((unsigned char) ch)
&& ch != '{' && ch != '}'
&& ch != '(' && ch != ')'
&& ch != '[' && ch != ']'
&& ch != ';' && ch != ','
&& ch != '#' && ch != '\\'
&& ch != '\'' && ch != '\"');
}
// check if a specific character is a digit
// NOTE: Visual C isdigit() gives assert error if char > 256
bool ASBase::isDigit(char ch) const
{
return (ch >= '0' && ch <= '9');
}
// check if a specific character is a digit separator
bool ASBase::isDigitSeparator(std::string_view line, int i) const
{
assert(line[i] == '\'');
// casting to (unsigned char) eliminates negative characters
// will get a "Debug Assertion Failed" if not cast
bool foundDigitSeparator = i > 0
&& isxdigit((unsigned char) line[i - 1])
&& i < (int) line.length() - 1
&& isxdigit((unsigned char) line[i + 1]);
return foundDigitSeparator;
}
// peek at the next unread character.
char ASBase::peekNextChar(std::string_view line, int i) const
{
char ch = ' ';
size_t peekNum = line.find_first_not_of(" \t", i + 1);
if (peekNum == std::string::npos)
return ch;
ch = line[peekNum];
return ch;
}
} // end namespace astyle
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+445
View File
@@ -0,0 +1,445 @@
// astyle_main.h
// Copyright (c) 2025 The Artistic Style Authors.
// This code is licensed under the MIT License.
// License.md describes the conditions under which this software may be distributed.
#ifndef ASTYLE_MAIN_H
#define ASTYLE_MAIN_H
//----------------------------------------------------------------------------
// headers
//----------------------------------------------------------------------------
#include "astyle.h"
#include <ctime>
#include <sstream>
#include <string_view>
#include "/home/pt/dev/kolibri/filesystem.h"
#if defined(__BORLANDC__) && __BORLANDC__ < 0x0650
// Embarcadero needs this for the following utime.h
// otherwise "struct utimbuf" gets an error on time_t
// 0x0650 for C++Builder XE3
using std::time_t;
#endif
#if defined(_MSC_VER)
#include <sys/stat.h>
#include <sys/utime.h>
#else
#include <sys/stat.h>
#include <utime.h>
#endif // end compiler checks
#ifdef ASTYLE_JNI
#include <jni.h>
#ifndef ASTYLE_LIB // ASTYLE_LIB must be defined for ASTYLE_JNI
#define ASTYLE_LIB
#endif
#endif // ASTYLE_JNI
#ifndef ASTYLE_LIB
// for console build only
#include "ASLocalizer.h"
#define _(a) localizer.settext(a)
#endif // ASTYLE_LIB
//-----------------------------------------------------------------------------
// declarations
//-----------------------------------------------------------------------------
// for getenv and localtime
#if defined(_MSC_VER)
#pragma warning(disable: 4996) // secure version deprecation warnings
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wdeprecated-declarations" // getenv, localtime
#pragma clang diagnostic ignored "-Wmissing-braces"
#endif
#ifdef ASTYLE_LIB
// define STDCALL and EXPORT for Windows
// MINGW defines STDCALL in Windows.h (actually windef.h)
// EXPORT has no value if ASTYLE_NO_EXPORT is defined
#ifdef _WIN32
#ifndef STDCALL
#define STDCALL __stdcall
#endif
// define this to prevent compiler warning and error messages
#ifdef ASTYLE_NO_EXPORT
#define EXPORT
#else
#define EXPORT __declspec(dllexport)
#endif
// define STDCALL and EXPORT for non-Windows
// visibility attribute allows "-fvisibility=hidden" compiler option
#else
#define STDCALL
#if __GNUC__ >= 4
#define EXPORT __attribute__ ((visibility ("default")))
#else
#define EXPORT
#endif
#endif // #ifdef _WIN32
// define pointers to callback error handler and memory allocation
typedef void (STDCALL* fpError)(int errorNumber, const char* errorMessage);
typedef char* (STDCALL* fpAlloc)(unsigned long memoryNeeded);
#endif // #ifdef ASTYLE_LIB
//----------------------------------------------------------------------------
// astyle namespace
//----------------------------------------------------------------------------
namespace astyle {
//
//----------------------------------------------------------------------------
// ASStreamIterator class
// typename will be stringstream for AStyle
// it could be istream for plug-ins
// ASSourceIterator is an inherited abstract class defined in astyle.h
//----------------------------------------------------------------------------
template<typename T>
class ASStreamIterator : public ASSourceIterator
{
public:
bool checkForEmptyLine;
public: // function declarations
explicit ASStreamIterator(T* in);
~ASStreamIterator() override;
int getStreamLength() const override;
std::string nextLine(bool emptyLineWasDeleted) override;
std::string peekNextLine() override;
void peekReset() override;
void saveLastInputLine();
std::streamoff tellg() override;
private:
T* inStream; // pointer to the input stream
std::string buffer; // current input line
std::string prevBuffer; // previous input line
std::string lastOutputEOL; // next output end of line char
std::streamoff streamLength; // length of the input file stream
std::streamoff peekStart; // starting position for peekNextLine
bool prevLineDeleted; // the previous input line was deleted
public: // inline functions
bool compareToInputBuffer(const std::string& nextLine_) const
{ return (nextLine_ == prevBuffer); }
const std::string& getLastOutputEOL() const { return lastOutputEOL; }
std::streamoff getPeekStart() const override { return peekStart; }
bool hasMoreLines() const override { return !inStream->eof(); }
};
//----------------------------------------------------------------------------
// ASEncoding class for utf8/16 conversions
// used by both console and library builds
//----------------------------------------------------------------------------
class ASEncoding
{
private:
using utf16 = char16_t; // 16 bits unsigned
using utf8 = unsigned char; // 8 bits
using ubyte = unsigned char; // 8 bits
enum { SURROGATE_LEAD_FIRST = 0xD800 };
enum { SURROGATE_LEAD_LAST = 0xDBFF };
enum { SURROGATE_TRAIL_FIRST = 0xDC00 };
enum { SURROGATE_TRAIL_LAST = 0xDFFF };
enum { SURROGATE_FIRST_VALUE = 0x10000 };
enum eState { eStart, eSecondOf4Bytes, ePenultimate, eFinal };
public:
bool getBigEndian() const;
int swap16bit(int value) const;
size_t utf16len(const utf16* utf16In) const;
size_t utf8LengthFromUtf16(const char* utf16In, size_t inLen, bool isBigEndian) const;
size_t utf8ToUtf16(char* utf8In, size_t inLen, bool isBigEndian, char* utf16Out) const;
size_t utf16LengthFromUtf8(const char* utf8In, size_t len) const;
size_t utf16ToUtf8(char* utf16In, size_t inLen, bool isBigEndian,
bool firstBlock, char* utf8Out) const;
};
//----------------------------------------------------------------------------
// ASOptions class for options processing
// used by both console and library builds
//----------------------------------------------------------------------------
class ASConsole;
class ASOptions
{
public:
#ifdef ASTYLE_LIB
ASOptions(ASFormatter& formatterArg);
#else
ASOptions(ASFormatter& formatterArg, ASConsole& consoleArg);
#endif
std::string getOptionErrors() const;
void importOptions(std::stringstream& in, std::vector<std::string>& optionsVector);
bool parseOptions(std::vector<std::string>& optionsVector);
private:
// variables
ASFormatter& formatter;
std::stringstream optionErrors; // option error messages
#ifndef ASTYLE_LIB
ASConsole& console; // DO NOT USE for ASTYLE_LIB
#endif
// functions
std::string getParam(const std::string& arg, const char* op);
std::string getParam(const std::string& arg, const char* op1, const char* op2);
bool isOption(const std::string& arg, const char* op);
bool isOption(const std::string& arg, const char* op1, const char* op2);
void isOptionError(const std::string& arg);
bool isParamOption(const std::string& arg, const char* option);
bool isParamOption(const std::string& arg, const char* option1, const char* option2);
void parseOption(const std::string& arg);
bool parseOptionContinued(const std::string& arg);
};
#ifndef ASTYLE_LIB
//----------------------------------------------------------------------------
// ASConsole class for console build
//----------------------------------------------------------------------------
class ASConsole
{
private: // variables
ASFormatter& formatter; // reference to the ASFormatter object
ASEncoding encode; // file encoding conversion
ASLocalizer localizer; // language translation
std::ostream* errorStream; // direct error messages to cerr or std::cout
// command line options
bool isRecursive; // recursive option
bool isDryRun; // dry-run option
bool noBackup; // suffix=none option
bool preserveDate; // preserve-date option
bool isVerbose; // verbose option
bool isQuiet; // quiet option
bool isFormattedOnly; // formatted lines only option
bool ignoreExcludeErrors; // don't abort on unmatched excludes
bool ignoreExcludeErrorsDisplay; // don't display unmatched excludes
bool useAscii; // ascii option
// other variables
bool bypassBrowserOpen; // don't open the browser on html options
bool hasWildcard; // file name includes a wildcard
size_t mainDirectoryLength; // directory length to be excluded in displays
bool filesAreIdentical; // input and output files are identical
bool acceptEmptyFileList; // empty input file list will not be reported as error
bool rejectDryRunWithFormat; // formatted files in dry run mode will be reported as error
int filesFormatted; // number of files formatted
int filesUnchanged; // number of files unchanged
int linesOut; // number of output lines
std::string outputEOL; // current line end
std::string astyleExePath; // absolute executable path and name from argv[0]
std::string optionFileName; // file path and name of the options file
std::string origSuffix; // suffix= option
std::string projectOptionFileName; // file path and name of the project options file
std::string stdPathIn; // path to input from stdin=
std::string stdPathOut; // path to output from stdout=
std::string targetDirectory; // path to the directory being processed
std::string targetFilename; // file name being processed
std::vector<std::string> excludeVector; // exclude from wildcard hits
std::vector<bool> excludeHitsVector; // exclude flags for error reporting
std::vector<std::string> fileNameVector; // file paths and names from the command line
std::vector<std::string> optionsVector; // options from the command line
std::vector<std::string> projectOptionsVector;// project options from the project options file
std::vector<std::string> fileOptionsVector; // options from the options file
std::vector<std::string> fileName; // files to be processed including path
public: // functions
explicit ASConsole(ASFormatter& formatterArg);
ASConsole(const ASConsole&) = delete;
ASConsole& operator=(ASConsole const&) = delete;
FileEncoding detectEncoding(const char* data, size_t dataSize) const;
void error() const;
void error(const char* why, const char* what) const;
void formatCinToCout();
std::vector<std::string> getArgvOptions(int argc, char** argv);
bool fileExists(const char* file) const;
bool fileNameVectorIsEmpty() const;
std::ostream* getErrorStream() const;
bool getFilesAreIdentical() const;
int getFilesFormatted() const;
bool getIgnoreExcludeErrors() const;
bool getIgnoreExcludeErrorsDisplay() const;
bool getIsDryRun() const;
bool getIsFormattedOnly() const;
bool getIsQuiet() const;
bool getIsRecursive() const;
bool getIsVerbose() const;
bool getLineEndsMixed() const;
bool getNoBackup() const;
bool getPreserveDate() const;
std::string getLanguageID() const;
std::string getNumberFormat(int num, size_t lcid = 0) const;
std::string getNumberFormat(int num, const char* groupingArg, const char* separator) const;
std::string getOptionFileName() const;
std::string getOrigSuffix() const;
std::string getProjectOptionFileName() const;
std::string getStdPathIn() const;
std::string getStdPathOut() const;
void getTargetFilenames(std::string& targetFilename_, std::vector<std::string>& targetFilenameVector) const;
void processFiles();
void processOptions(const std::vector<std::string>& argvOptions);
void setBypassBrowserOpen(bool state);
void setErrorStream(std::ostream* errStreamPtr);
void setIgnoreExcludeErrors(bool state);
void setIgnoreExcludeErrorsAndDisplay(bool state);
void setIsDryRun(bool state);
void setRejectFormatWithDryRun(bool state);
void setIsFormattedOnly(bool state);
void setIsQuiet(bool state);
void setIsRecursive(bool state);
void setIsVerbose(bool state);
void setNoBackup(bool state);
void setOptionFileName(const std::string& name);
void setOrigSuffix(const std::string& suffix);
void setPreserveDate(bool state);
void setProjectOptionFileName(const std::string& optfilepath);
void setStdPathIn(const std::string& path);
void setStdPathOut(const std::string& path);
void setAcceptEmptyInputFileList(bool state);
void standardizePath(std::string& path, bool removeBeginningSeparator = false) const;
bool stringEndsWith(std::string_view str, std::string_view suffix) const;
void updateExcludeVector(const std::string& suffixParam);
std::vector<std::string> getExcludeVector() const;
std::vector<bool> getExcludeHitsVector() const;
std::vector<std::string> getFileNameVector() const;
std::vector<std::string> getOptionsVector() const;
std::vector<std::string> getProjectOptionsVector() const;
std::vector<std::string> getFileOptionsVector() const;
std::vector<std::string> getFileName() const;
private: // functions
void formatFile(const std::string& fileName_);
std::string getParentDirectory(const std::string& absPath) const;
std::string findProjectOptionFilePath(const std::string& fileName_) const;
std::string getCurrentDirectory(const std::string& fileName_) const;
void getFileNames(const std::string& directory, const std::vector<std::string>& wildcards);
void getFilePaths(const std::string& filePath);
std::string getFullPathName(const std::string& relativePath) const;
std::string getHtmlInstallPrefix() const;
std::string getParam(const std::string& arg, const char* op);
bool isHomeOrInvalidAbsPath(const std::string& absPath) const;
bool isWriteable(const std::filesystem::path& path) const;
void initializeOutputEOL(LineEndFormat lineEndFormat);
bool isOption(const std::string& arg, const char* op);
bool isOption(const std::string& arg, const char* a, const char* b);
bool isParamOption(const std::string& arg, const char* option);
bool isPathExcluded(const std::string& subPath);
void launchDefaultBrowser(const char* filePathIn = nullptr) const;
void printHelp() const;
void printMsg(const char* msg, const std::string& data) const;
void printSeparatingLine() const;
void printVerboseHeader() const;
void printVerboseStats(clock_t startTime) const;
FileEncoding readFile(const std::string& fileName_, std::stringstream& in) const;
void removeFile(const char* fileName_, const char* errMsg) const;
void renameFile(const char* oldFileName, const char* newFileName, const char* errMsg) const;
void sleep(int seconds) const;
int waitForRemove(const char* newFileName) const;
int wildcmp(const char* wild, const char* data) const;
void writeFile(const std::string& fileName_, FileEncoding encoding, std::ostringstream& out) const;
#ifdef _WIN32
void displayLastError();
#endif
};
#else // ASTYLE_LIB
//----------------------------------------------------------------------------
// ASLibrary class for library build
//----------------------------------------------------------------------------
class ASLibrary
{
public:
ASLibrary() = default;
virtual ~ASLibrary() = default;
// virtual functions are mocked in testing
char16_t* formatUtf16(const char16_t*, const char16_t*, fpError, fpAlloc) const;
virtual char16_t* convertUtf8ToUtf16(const char* utf8In, fpAlloc fpMemoryAlloc) const;
virtual char* convertUtf16ToUtf8(const char16_t* utf16In) const;
private:
static char* STDCALL tempMemoryAllocation(unsigned long memoryNeeded);
private:
ASEncoding encode; // file encoding conversion
};
#endif // ASTYLE_LIB
//----------------------------------------------------------------------------
} // end of namespace astyle
//----------------------------------------------------------------------------
// declarations for java native interface (JNI) build
// they are called externally and are NOT part of the namespace
//----------------------------------------------------------------------------
#ifdef ASTYLE_JNI
void STDCALL javaErrorHandler(int errorNumber, const char* errorMessage);
char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded);
// the following function names are constructed from method names in the calling java program
extern "C" EXPORT
jstring STDCALL Java_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass);
extern "C" EXPORT
jstring STDCALL Java_AStyleInterface_AStyleMain(JNIEnv* env,
jobject obj,
jstring textInJava,
jstring optionsJava);
extern "C" EXPORT
jstring STDCALL Java_cc_arduino_packages_formatter_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass);
extern "C" EXPORT
jstring STDCALL Java_cc_arduino_packages_formatter_AStyleInterface_AStyleMain(JNIEnv* env,
jobject obj,
jstring textInJava,
jstring optionsJava);
#endif // ASTYLE_JNI
//----------------------------------------------------------------------------
// declarations for UTF-16 interface
// they are called externally and are NOT part of the namespace
//----------------------------------------------------------------------------
#ifdef ASTYLE_LIB
extern "C" EXPORT
char16_t* STDCALL AStyleMainUtf16(const char16_t* pSourceIn,
const char16_t* pOptions,
fpError fpErrorHandler,
fpAlloc fpMemoryAlloc);
#endif // ASTYLE_LIB
//-----------------------------------------------------------------------------
// declarations for standard DLL interface
// they are called externally and are NOT part of the namespace
//-----------------------------------------------------------------------------
#ifdef ASTYLE_LIB
extern "C" EXPORT char* STDCALL AStyleMain(const char* pSourceIn,
const char* pOptions,
fpError fpErrorHandler,
fpAlloc fpMemoryAlloc);
extern "C" EXPORT const char* STDCALL AStyleGetVersion(void);
#endif // ASTYLE_LIB
//-----------------------------------------------------------------------------
#endif // closes ASTYLE_MAIN_H
+184
View File
@@ -0,0 +1,184 @@
#ifndef __FILESYSTEM_H__
#define __FILESYSTEM_H__
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/stat.h>
namespace std
{
namespace filesystem
{
class path
{
public:
using value_type = char;
using string_type = std::basic_string< value_type >;
constexpr static size_t max_path = 256u;
constexpr static value_type preferred_separator = '/';
inline bool is_directory_separator(path::value_type c) noexcept
{
return c == preferred_separator;
}
template<class Char>
path(const std::basic_string<Char>& s) : m_pathname(s) {};
path() noexcept {}
path(path const& p) : m_pathname(p.m_pathname) {}
path(const value_type* s) : m_pathname(s) {}
path(path&& p) noexcept : m_pathname(static_cast< string_type&& >(p.m_pathname))
{
}
path& operator=(path&& p) noexcept
{
m_pathname = static_cast< string_type&& >(p.m_pathname);
return *this;
}
path& assign(path&& p) noexcept
{
m_pathname = static_cast< string_type&& >(p.m_pathname);
return *this;
}
path(string_type&& s) noexcept : m_pathname(static_cast< string_type&& >(s))
{
}
path& operator=(string_type&& p) noexcept
{
m_pathname = static_cast< string_type&& >(p);
return *this;
}
path& assign(string_type&& p) noexcept
{
m_pathname = static_cast< string_type&& >(p);
return *this;
}
path(const value_type* begin, const value_type* end) : m_pathname(begin, end) {}
path& assign(path const& p)
{
m_pathname = p.m_pathname;
return *this;
}
path& assign(const value_type* begin, const value_type* end)
{
m_pathname.assign(begin, end);
return *this;
}
path& operator+=(value_type c)
{
m_pathname.push_back(c);
return *this;
}
path& operator+=(const string_type& s)
{
m_pathname.append(s);
return *this;
}
path& concat(path const& p)
{
m_pathname.append(p.m_pathname);
return *this;
}
path& concat(const value_type* begin, const value_type* end)
{
m_pathname.append(begin, end);
return *this;
}
static string_type& quoted(const string_type& s, value_type q = '"')
{
return string_type{}.append(1,q).append(s).append(1,q);
}
string_type string() const
{
return m_pathname;
}
path& operator/= (const path& p)
{
m_pathname = m_pathname + preferred_separator + p.m_pathname;
return *this;
}
bool empty() const noexcept { return m_pathname.empty(); }
const value_type* c_str() const noexcept
{
return m_pathname.c_str();
}
private:
string_type m_pathname;
};
template< typename Char, typename Traits >
inline std::basic_ostream< Char, Traits >&
operator<<(std::basic_ostream< Char, Traits >& os, path const& p)
{
return os << path::quoted(p.string());
}
template< typename Char, typename Traits >
inline std::basic_istream< Char, Traits >&
operator>>(std::basic_istream< Char, Traits >& is, path& p)
{
std::basic_string< Char > str;
is >> path::quoted(p.string());
p = str;
return is;
}
path operator/(path lhs, path const& rhs)
{
return lhs.concat(path::string_type{path::preferred_separator}).concat(rhs);
}
path current_path()
{
char buf[path::max_path];
memset(buf, 0, path::max_path);
const auto rv = _ksys_getcwd(buf, path::max_path - 1u);
return (rv == NULL) ? path{} : path{buf};
}
inline bool is_directory(path const& p)
{
struct stat sb;
if (stat(p.string().c_str(), &sb) == 0 && S_ISDIR(sb.st_mode))
{
return true;
}
return false;
}
inline bool is_regular_file(path const& p)
{
struct stat sb;
if (stat(p.string().c_str(), &sb) == 0 && S_ISREG(sb.st_mode))
{
return true;
}
return false;
}
bool exists(path const& p)
{
return (is_regular_file(p) || is_directory(p));
}
path absolute(path const& p)
{
return p; // TODO
}
} // namespace filesystem
} // namespace std
#endif // ~__FILESYSTEM_H__
+55
View File
@@ -0,0 +1,55 @@
#include <iostream>
#include <map>
#include <string>
#include <string_view>
#include <fstream>
#include <dirent.h>
#include <unistd.h>
#include <cstring>
#include <iomanip>
#include <cctype>
#include "filesystem.h"
namespace fs = std::filesystem;
// add this to astyle.h to compile under toolchain
namespace std
{
using string_view=std::experimental::fundamentals_v1::string_view;
int isblank(int c){return ::isblank(c);}
}
void check_directory(const fs::path& p)
{
std::cout << "checking directory " << p << std::endl;
std::cout << std::boolalpha << "result : " << fs::is_directory(p) << std::endl;
}
void check_file(const fs::path& p)
{
std::cout << "checking file " << p << std::endl;
std::cout << std::boolalpha << "result : " << fs::is_regular_file(p) << std::endl;
}
int main(int argc, char** argv) {
const auto cwd = fs::current_path();
std::cout << "cwd = " << cwd << std::endl;
check_directory(cwd);
check_directory(cwd / "main");
check_directory("abcabc");
check_file(cwd);
check_file(cwd / "main");
check_file("abcabc");
std::isblank(15);
return 0;
}