diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 236a80cd..da093d2b 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -157,6 +157,7 @@ SOURCES += \ settingsdialog/environmentshortcutwidget.cpp \ settingsdialog/executorproblemsetwidget.cpp \ settingsdialog/formattergeneralwidget.cpp \ + settingsdialog/formatterpathwidget.cpp \ settingsdialog/languageasmgenerationwidget.cpp \ # settingsdialog/languagecformatwidget.cpp \ settingsdialog/projectcompileparamaterswidget.cpp \ @@ -291,6 +292,7 @@ HEADERS += \ settingsdialog/environmentshortcutwidget.h \ settingsdialog/executorproblemsetwidget.h \ settingsdialog/formattergeneralwidget.h \ + settingsdialog/formatterpathwidget.h \ settingsdialog/languageasmgenerationwidget.h \ # settingsdialog/languagecformatwidget.h \ settingsdialog/projectcompileparamaterswidget.h \ @@ -390,6 +392,7 @@ FORMS += \ settingsdialog/environmentshortcutwidget.ui \ settingsdialog/executorproblemsetwidget.ui \ settingsdialog/formattergeneralwidget.ui \ + settingsdialog/formatterpathwidget.ui \ settingsdialog/languageasmgenerationwidget.ui \ # settingsdialog/languagecformatwidget.ui \ settingsdialog/projectcompileparamaterswidget.ui \ @@ -520,17 +523,6 @@ win32: { settingsdialog/projectversioninfowidget.cpp } -unix: { - HEADERS += \ - settingsdialog/formatterpathwidget.h - - SOURCES += \ - settingsdialog/formatterpathwidget.cpp - - FORMS += \ - settingsdialog/formatterpathwidget.ui -} - linux: { # legacy glibc compatibility -- modern Unices have all components in `libc.so` LIBS += -lrt -ldl diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 3863c1b5..02091c91 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -5107,30 +5107,21 @@ void Editor::reformat(bool doReparse) { if (readOnly()) return; -#ifndef Q_OS_WIN if (!fileExists(pSettings->environment().AStylePath())) { QMessageBox::critical(this, tr("astyle not found"), tr("Can't find astyle in \"%1\".").arg(pSettings->environment().AStylePath())); return; } -#endif //we must remove all breakpoints and syntax issues // onLinesDeleted(1,lineCount()); QByteArray content = text().toUtf8(); QStringList args = pSettings->codeFormatter().getArguments(); //qDebug()<dirs().appDir(), - args, - content); -#else QByteArray newContent = runAndGetOutput(pSettings->environment().AStylePath(), extractFileDir(pSettings->environment().AStylePath()), args, content); -#endif if (newContent.isEmpty()) return; replaceContent(QString::fromUtf8(newContent), doReparse); diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index 73a0d9c8..95366d3e 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -3785,12 +3785,33 @@ void Settings::Environment::doLoad() // check saved terminal path mTerminalPath = stringValue("terminal_path", ""); // always do substitution for backward compatibility - mTerminalPath.replace("%*APP_DIR*%",pSettings->dirs().appDir()); + mTerminalPath = replacePrefix(mTerminalPath, "%*APP_DIR*%", pSettings->dirs().appDir()); mTerminalArgumentsPattern = stringValue("terminal_arguments_pattern", ""); checkAndSetTerminal(); - mAStylePath = includeTrailingPathDelimiter(pSettings->dirs().appLibexecDir())+"astyle"; + mAStylePath = stringValue("astyle_path",""); + if (mAStylePath.isEmpty()) { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + QString path = env.value("PATH"); + QStringList pathList = path.split(PATH_SEPARATOR); + pathList = QStringList{ + mSettings->dirs().appDir(), + mSettings->dirs().appLibexecDir(), + } + pathList; + + foreach (const QString& folder, pathList) { + QDir dir{folder}; + QFileInfo fileInfo{dir.absoluteFilePath(ASTYLE_PROGRAM)}; + if (fileInfo.exists()) { + mAStylePath = fileInfo.absoluteFilePath(); + break; + } + } + if (isGreenEdition()) + mAStylePath = replacePrefix(mAStylePath, pSettings->dirs().appDir() , "%*APP_DIR*%"); + } + mHideNonSupportFilesInFileView=boolValue("hide_non_support_files_file_view",true); mOpenFilesInSingleInstance = boolValue("open_files_in_single_instance",false); } @@ -3857,12 +3878,17 @@ void Settings::Environment::setTerminalPath(const QString &terminalPath) QString Settings::Environment::AStylePath() const { + if (isGreenEdition()) { + return replacePrefix(mAStylePath, "%*APP_DIR*%", pSettings->dirs().appDir()); + } return mAStylePath; } void Settings::Environment::setAStylePath(const QString &aStylePath) { mAStylePath = aStylePath; + if (isGreenEdition()) + mAStylePath = replacePrefix(mAStylePath, pSettings->dirs().appDir() , "%*APP_DIR*%"); } QString Settings::Environment::terminalArgumentsPattern() const @@ -3943,7 +3969,7 @@ void Settings::Environment::checkAndSetTerminal() QList terminalList = loadTerminalList(); for (const TerminalItem& termItem:terminalList) { QString term=termItem.terminal; - term.replace("%*APP_DIR*%",pSettings->dirs().appDir()); + term = replacePrefix(term, "%*APP_DIR*%", pSettings->dirs().appDir()); QFileInfo info{term}; QString absoluteTerminalPath; if (info.isAbsolute()) { @@ -4001,7 +4027,7 @@ QList Settings::Environment::loadTerminalLi QString termExecutable = QFileInfo(path).fileName(); QString pattern = terminal["argsPattern"].toString(); Settings::Environment::TerminalItem terminalItem; - path.replace("%*APP_DIR*%", pSettings->dirs().appDir()); + path = replacePrefix(path, "%*APP_DIR*%", pSettings->dirs().appDir()); terminalItem.terminal = path; terminalItem.param = pattern; result.append(terminalItem); @@ -4060,9 +4086,7 @@ void Settings::Environment::doSave() // APP_DIR trick for windows portable app // For non-portable app (other platform or Windows installer), multiple instances // share the same configuration and thus the trick may break terminal path - if (terminalPath.startsWith(pSettings->dirs().appDir())) { - terminalPath="%*APP_DIR*%"+terminalPath.mid(pSettings->dirs().appDir().length()); - } + terminalPath = replacePrefix(terminalPath, pSettings->dirs().appDir(), "%*APP_DIR*%"); } saveValue("terminal_path",terminalPath); @@ -4070,7 +4094,7 @@ void Settings::Environment::doSave() #ifdef Q_OS_WINDOWS saveValue("use_custom_terminal",mUseCustomTerminal); #endif - saveValue("asyle_path",mAStylePath); + saveValue("astyle_path",mAStylePath); saveValue("hide_non_support_files_file_view",mHideNonSupportFilesInFileView); saveValue("open_files_in_single_instance",mOpenFilesInSingleInstance); diff --git a/RedPandaIDE/settingsdialog/formattergeneralwidget.cpp b/RedPandaIDE/settingsdialog/formattergeneralwidget.cpp index c30604be..649e86b9 100644 --- a/RedPandaIDE/settingsdialog/formattergeneralwidget.cpp +++ b/RedPandaIDE/settingsdialog/formattergeneralwidget.cpp @@ -328,17 +328,10 @@ void FormatterGeneralWidget::updateDemo() Settings::CodeFormatter formatter(nullptr); updateCodeFormatter(formatter); -#ifdef Q_OS_WIN - QByteArray newContent = runAndGetOutput("astyle.exe", - pSettings->dirs().appDir(), - formatter.getArguments(), - content); -#else QByteArray newContent = runAndGetOutput(pSettings->environment().AStylePath(), extractFileDir(pSettings->environment().AStylePath()), formatter.getArguments(), content); -#endif ui->editDemo->document()->setText(newContent); } diff --git a/RedPandaIDE/settingsdialog/settingsdialog.cpp b/RedPandaIDE/settingsdialog/settingsdialog.cpp index 58ed1c8d..c071e1e9 100644 --- a/RedPandaIDE/settingsdialog/settingsdialog.cpp +++ b/RedPandaIDE/settingsdialog/settingsdialog.cpp @@ -41,6 +41,7 @@ #include "executorproblemsetwidget.h" #include "debuggeneralwidget.h" #include "formattergeneralwidget.h" +#include "formatterpathwidget.h" #include "languageasmgenerationwidget.h" #include "projectgeneralwidget.h" #include "projectfileswidget.h" @@ -59,9 +60,6 @@ #include "environmentfileassociationwidget.h" #include "projectversioninfowidget.h" #endif -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) // XDG desktop -#include "formatterpathwidget.h" -#endif #include #include #include @@ -228,10 +226,8 @@ PSettingsDialog SettingsDialog::optionDialog() widget = new FormatterGeneralWidget(tr("General"),tr("Code Formatter")); dialog->addWidget(widget); -#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) // XDG desktop widget = new FormatterPathWidget(tr("Program"),tr("Code Formatter")); dialog->addWidget(widget); -#endif widget = new ToolsGeneralWidget(tr("General"),tr("Tools")); dialog->addWidget(widget); diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h index e6225932..4b6d875b 100644 --- a/RedPandaIDE/systemconsts.h +++ b/RedPandaIDE/systemconsts.h @@ -40,6 +40,7 @@ #define SDCC_PROGRAM "sdcc.exe" #define PACKIHX_PROGRAM "packihx.exe" #define MAKEBIN_PROGRAM "makebin.exe" +#define ASTYLE_PROGRAM "astyle.exe" #else // Unix #define CONSOLE_PAUSER "consolepauser" #define GCC_PROGRAM "gcc" @@ -61,6 +62,7 @@ #define SDCC_PROGRAM "sdcc" #define PACKIHX_PROGRAM "packihx" #define MAKEBIN_PROGRAM "makebin" +#define ASTYLE_PROGRAM "astyle" #endif #define DEV_PROJECT_EXT "dev" diff --git a/Red_Panda_CPP.pro b/Red_Panda_CPP.pro index 9f98cd5b..ff4a6e5d 100644 --- a/Red_Panda_CPP.pro +++ b/Red_Panda_CPP.pro @@ -2,13 +2,11 @@ TEMPLATE = subdirs SUBDIRS += \ RedPandaIDE \ - astyle \ consolepauser \ redpanda_qt_utils \ qsynedit \ lua -astyle.subdir = tools/astyle consolepauser.subdir = tools/consolepauser redpanda_qt_utils.subdir = libs/redpanda_qt_utils qsynedit.subdir = libs/qsynedit @@ -16,7 +14,7 @@ lua.subdir = libs/lua # Add the dependencies so that the RedPandaIDE project can add the depended programs # into the main app bundle -RedPandaIDE.depends = astyle consolepauser qsynedit +RedPandaIDE.depends = consolepauser qsynedit qsynedit.depends = redpanda_qt_utils APP_NAME = RedPandaCPP @@ -28,7 +26,7 @@ include(version.inc) win32: { SUBDIRS += \ - redpanda-win-git-askpass + redpanda-win-git-askpass redpanda-win-git-askpass.subdir = tools/redpanda-win-git-askpass RedPandaIDE.depends += redpanda-win-git-askpass } diff --git a/libs/redpanda_qt_utils/qt_utils/utils.cpp b/libs/redpanda_qt_utils/qt_utils/utils.cpp index 9037cd28..7de27767 100644 --- a/libs/redpanda_qt_utils/qt_utils/utils.cpp +++ b/libs/redpanda_qt_utils/qt_utils/utils.cpp @@ -752,3 +752,12 @@ int compareFileModifiedTime(const QString &filename, qint64 timestamp) return -1; return 0; } + +QString replacePrefix(const QString &oldString, const QString &prefix, const QString &newPrefix) +{ + QString result = oldString; + if (oldString.startsWith(prefix)) { + result = newPrefix+oldString.mid(prefix.length()); + } + return result; +} diff --git a/libs/redpanda_qt_utils/qt_utils/utils.h b/libs/redpanda_qt_utils/qt_utils/utils.h index e95744d5..ca05b90a 100644 --- a/libs/redpanda_qt_utils/qt_utils/utils.h +++ b/libs/redpanda_qt_utils/qt_utils/utils.h @@ -143,6 +143,8 @@ QString generateAbsolutePath(const QString& dirPath, const QString& relativePath QStringList absolutePaths(const QString& dirPath, const QStringList& relativePaths); QString escapeSpacesInString(const QString& str); +QString replacePrefix(const QString& oldString, const QString& prefix, const QString& newPrefix); + bool isReadOnly(const QString& filename); diff --git a/packages/debian/control b/packages/debian/control index 83bd7bdc..4897c010 100644 --- a/packages/debian/control +++ b/packages/debian/control @@ -18,7 +18,8 @@ Depends: ${shlibs:Depends}, g++, make, gdb, - gdbserver + gdbserver, + astyle Recommends: qterminal | deepin-terminal | konsole | gnome-terminal | terminator | lxterminal | mate-terminal | terminology | xfce4-terminal | alacritty | cool-retro-term | kitty | sakura | termit | tilix Description: A lightweight but powerful C/C++ IDE Red Panda C++ (Old name Red Panda Dev-C++ 7) is a full featured C/C++ IDE. diff --git a/packages/msys/build-mingw.sh b/packages/msys/build-mingw.sh index ed965f53..52eb4556 100644 --- a/packages/msys/build-mingw.sh +++ b/packages/msys/build-mingw.sh @@ -121,6 +121,8 @@ while [[ $# -gt 0 ]]; do esac done +ASTYLE_BUILD_DIR="${TEMP}/astyle-build" +ASTYLE_VERSION_TAG="3.4.14" BUILD_DIR="${TEMP}/redpanda-mingw-${MSYSTEM}-build" PACKAGE_DIR="${TEMP}/redpanda-mingw-${MSYSTEM}-pkg" QMAKE="${MINGW_PREFIX}/qt5-static/bin/qmake" @@ -158,7 +160,7 @@ if [[ ${CHECK_DEPS} -eq 1 ]]; then ;; esac deps=( - ${MINGW_PACKAGE_PREFIX}-{$compiler,make,qt5-static,7zip} + ${MINGW_PACKAGE_PREFIX}-{$compiler,make,qt5-static,7zip,cmake} mingw-w64-i686-nsis git ) @@ -184,10 +186,23 @@ fi if [[ ${CLEAN} -eq 1 ]]; then rm -rf "${BUILD_DIR}" rm -rf "${PACKAGE_DIR}" + rm -rf "${ASTYLE_BUILD_DIR}" fi -mkdir -p "${BUILD_DIR}" "${PACKAGE_DIR}" "${TARGET_DIR}" +mkdir -p "${BUILD_DIR}" "${PACKAGE_DIR}" "${TARGET_DIR}" "${ASTYLE_BUILD_DIR}" ## build +fn_print_progress "Building astyle..." +pushd . +cd "${ASTYLE_BUILD_DIR}" +[[ -d "astyle" ]] || git clone --depth 1 --branch "${ASTYLE_VERSION_TAG}" "https://gitlab.com/saalen/astyle" +cd astyle +[[ ! -d "build" ]] || rm -rf "build" +mkdir build +cd build +cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS="-static" +mingw32-make -j$(nproc) +cp AStyle/AStyle.exe "${PACKAGE_DIR}/astyle.exe" +popd fn_print_progress "Building..." pushd . diff --git a/tools/astyle/ASBeautifier.cpp b/tools/astyle/ASBeautifier.cpp deleted file mode 100644 index 2c65eee0..00000000 --- a/tools/astyle/ASBeautifier.cpp +++ /dev/null @@ -1,3747 +0,0 @@ -// ASBeautifier.cpp -// Copyright (c) 2018 by Jim Pattee . -// 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 - -//----------------------------------------------------------------------------- -// astyle namespace -//----------------------------------------------------------------------------- - -namespace astyle { -// -// this must be global -static int g_preprocessorCppExternCBrace; - -//----------------------------------------------------------------------------- -// ASBeautifier class -//----------------------------------------------------------------------------- - -/** - * ASBeautifier's constructor - * This constructor is called only once for each source file. - * The cloned ASBeautifier objects are created with the copy constructor. - */ -ASBeautifier::ASBeautifier() -{ - waitingBeautifierStack = nullptr; - activeBeautifierStack = nullptr; - waitingBeautifierStackLengthStack = nullptr; - activeBeautifierStackLengthStack = nullptr; - - headerStack = nullptr; - tempStacks = nullptr; - parenDepthStack = nullptr; - blockStatementStack = nullptr; - parenStatementStack = nullptr; - braceBlockStateStack = nullptr; - continuationIndentStack = nullptr; - continuationIndentStackSizeStack = nullptr; - parenIndentStack = nullptr; - preprocIndentStack = nullptr; - sourceIterator = nullptr; - isModeManuallySet = false; - shouldForceTabIndentation = false; - setSpaceIndentation(4); - setContinuationIndentation(1); - setMinConditionalIndentOption(MINCOND_TWO); - setMaxContinuationIndentLength(40); - classInitializerIndents = 1; - tabLength = 0; - setClassIndent(false); - setModifierIndent(false); - setSwitchIndent(false); - setCaseIndent(false); - setBlockIndent(false); - setBraceIndent(false); - setBraceIndentVtk(false); - setNamespaceIndent(false); - setAfterParenIndent(false); - setLabelIndent(false); - setEmptyLineFill(false); - setCStyle(); - setPreprocDefineIndent(false); - setPreprocConditionalIndent(false); - setAlignMethodColon(false); - - // initialize ASBeautifier member vectors - beautifierFileType = 9; // reset to an invalid type - headers = new vector; - nonParenHeaders = new vector; - assignmentOperators = new vector; - nonAssignmentOperators = new vector; - preBlockStatements = new vector; - preCommandHeaders = new vector; - indentableHeaders = new vector; -} - -/** - * ASBeautifier's copy constructor - * Copy the vector objects to vectors in the new ASBeautifier - * object so the new object can be destroyed without deleting - * the vector objects in the copied vector. - * This is the reason a copy constructor is needed. - * - * Must explicitly call the base class copy constructor. - */ -ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other) -{ - // these don't need to copy the stack - waitingBeautifierStack = nullptr; - activeBeautifierStack = nullptr; - waitingBeautifierStackLengthStack = nullptr; - activeBeautifierStackLengthStack = nullptr; - - // vector '=' operator performs a DEEP copy of all elements in the vector - - headerStack = new vector; - *headerStack = *other.headerStack; - - tempStacks = copyTempStacks(other); - - parenDepthStack = new vector; - *parenDepthStack = *other.parenDepthStack; - - blockStatementStack = new vector; - *blockStatementStack = *other.blockStatementStack; - - parenStatementStack = new vector; - *parenStatementStack = *other.parenStatementStack; - - braceBlockStateStack = new vector; - *braceBlockStateStack = *other.braceBlockStateStack; - - continuationIndentStack = new vector; - *continuationIndentStack = *other.continuationIndentStack; - - continuationIndentStackSizeStack = new vector; - *continuationIndentStackSizeStack = *other.continuationIndentStackSizeStack; - - parenIndentStack = new vector; - *parenIndentStack = *other.parenIndentStack; - - preprocIndentStack = new vector >; - *preprocIndentStack = *other.preprocIndentStack; - - // Copy the pointers to vectors. - // This is ok because the original ASBeautifier object - // is not deleted until end of job. - beautifierFileType = other.beautifierFileType; - headers = other.headers; - nonParenHeaders = other.nonParenHeaders; - assignmentOperators = other.assignmentOperators; - nonAssignmentOperators = other.nonAssignmentOperators; - preBlockStatements = other.preBlockStatements; - preCommandHeaders = other.preCommandHeaders; - indentableHeaders = other.indentableHeaders; - - // protected variables - // variables set by ASFormatter - // must also be updated in activeBeautifierStack - inLineNumber = other.inLineNumber; - runInIndentContinuation = other.runInIndentContinuation; - nonInStatementBrace = other.nonInStatementBrace; - objCColonAlignSubsequent = other.objCColonAlignSubsequent; - lineCommentNoBeautify = other.lineCommentNoBeautify; - isElseHeaderIndent = other.isElseHeaderIndent; - isCaseHeaderCommentIndent = other.isCaseHeaderCommentIndent; - isNonInStatementArray = other.isNonInStatementArray; - isSharpAccessor = other.isSharpAccessor; - isSharpDelegate = other.isSharpDelegate; - isInExternC = other.isInExternC; - isInBeautifySQL = other.isInBeautifySQL; - isInIndentableStruct = other.isInIndentableStruct; - isInIndentablePreproc = other.isInIndentablePreproc; - - // private variables - sourceIterator = other.sourceIterator; - currentHeader = other.currentHeader; - previousLastLineHeader = other.previousLastLineHeader; - probationHeader = other.probationHeader; - lastLineHeader = other.lastLineHeader; - indentString = other.indentString; - verbatimDelimiter = other.verbatimDelimiter; - isInQuote = other.isInQuote; - isInVerbatimQuote = other.isInVerbatimQuote; - haveLineContinuationChar = other.haveLineContinuationChar; - isInAsm = other.isInAsm; - isInAsmOneLine = other.isInAsmOneLine; - isInAsmBlock = other.isInAsmBlock; - isInComment = other.isInComment; - isInPreprocessorComment = other.isInPreprocessorComment; - isInRunInComment = other.isInRunInComment; - isInCase = other.isInCase; - isInQuestion = other.isInQuestion; - isContinuation = other.isContinuation; - isInHeader = other.isInHeader; - isInTemplate = other.isInTemplate; - isInDefine = other.isInDefine; - isInDefineDefinition = other.isInDefineDefinition; - classIndent = other.classIndent; - isIndentModeOff = other.isIndentModeOff; - isInClassHeader = other.isInClassHeader; - isInClassHeaderTab = other.isInClassHeaderTab; - isInClassInitializer = other.isInClassInitializer; - isInClass = other.isInClass; - isInObjCMethodDefinition = other.isInObjCMethodDefinition; - isInObjCMethodCall = other.isInObjCMethodCall; - isInObjCMethodCallFirst = other.isInObjCMethodCallFirst; - isImmediatelyPostObjCMethodDefinition = other.isImmediatelyPostObjCMethodDefinition; - isImmediatelyPostObjCMethodCall = other.isImmediatelyPostObjCMethodCall; - isInIndentablePreprocBlock = other.isInIndentablePreprocBlock; - isInObjCInterface = other.isInObjCInterface; - isInEnum = other.isInEnum; - isInEnumTypeID = other.isInEnumTypeID; - isInLet = other.isInLet; - isInTrailingReturnType = other.isInTrailingReturnType; - modifierIndent = other.modifierIndent; - switchIndent = other.switchIndent; - caseIndent = other.caseIndent; - namespaceIndent = other.namespaceIndent; - braceIndent = other.braceIndent; - braceIndentVtk = other.braceIndentVtk; - blockIndent = other.blockIndent; - shouldIndentAfterParen = other.shouldIndentAfterParen; - labelIndent = other.labelIndent; - isInConditional = other.isInConditional; - isModeManuallySet = other.isModeManuallySet; - shouldForceTabIndentation = other.shouldForceTabIndentation; - emptyLineFill = other.emptyLineFill; - lineOpensWithLineComment = other.lineOpensWithLineComment; - lineOpensWithComment = other.lineOpensWithComment; - lineStartsInComment = other.lineStartsInComment; - backslashEndsPrevLine = other.backslashEndsPrevLine; - blockCommentNoIndent = other.blockCommentNoIndent; - blockCommentNoBeautify = other.blockCommentNoBeautify; - previousLineProbationTab = other.previousLineProbationTab; - lineBeginsWithOpenBrace = other.lineBeginsWithOpenBrace; - lineBeginsWithCloseBrace = other.lineBeginsWithCloseBrace; - lineBeginsWithComma = other.lineBeginsWithComma; - lineIsCommentOnly = other.lineIsCommentOnly; - lineIsLineCommentOnly = other.lineIsLineCommentOnly; - shouldIndentBracedLine = other.shouldIndentBracedLine; - isInSwitch = other.isInSwitch; - foundPreCommandHeader = other.foundPreCommandHeader; - foundPreCommandMacro = other.foundPreCommandMacro; - shouldAlignMethodColon = other.shouldAlignMethodColon; - shouldIndentPreprocDefine = other.shouldIndentPreprocDefine; - shouldIndentPreprocConditional = other.shouldIndentPreprocConditional; - indentCount = other.indentCount; - spaceIndentCount = other.spaceIndentCount; - spaceIndentObjCMethodAlignment = other.spaceIndentObjCMethodAlignment; - bracePosObjCMethodAlignment = other.bracePosObjCMethodAlignment; - colonIndentObjCMethodAlignment = other.colonIndentObjCMethodAlignment; - lineOpeningBlocksNum = other.lineOpeningBlocksNum; - lineClosingBlocksNum = other.lineClosingBlocksNum; - fileType = other.fileType; - minConditionalOption = other.minConditionalOption; - minConditionalIndent = other.minConditionalIndent; - parenDepth = other.parenDepth; - indentLength = other.indentLength; - tabLength = other.tabLength; - continuationIndent = other.continuationIndent; - blockTabCount = other.blockTabCount; - maxContinuationIndent = other.maxContinuationIndent; - classInitializerIndents = other.classInitializerIndents; - templateDepth = other.templateDepth; - squareBracketCount = other.squareBracketCount; - prevFinalLineSpaceIndentCount = other.prevFinalLineSpaceIndentCount; - prevFinalLineIndentCount = other.prevFinalLineIndentCount; - defineIndentCount = other.defineIndentCount; - preprocBlockIndent = other.preprocBlockIndent; - quoteChar = other.quoteChar; - prevNonSpaceCh = other.prevNonSpaceCh; - currentNonSpaceCh = other.currentNonSpaceCh; - currentNonLegalCh = other.currentNonLegalCh; - prevNonLegalCh = other.prevNonLegalCh; -} - -/** - * ASBeautifier's destructor - */ -ASBeautifier::~ASBeautifier() -{ - deleteBeautifierContainer(waitingBeautifierStack); - deleteBeautifierContainer(activeBeautifierStack); - deleteContainer(waitingBeautifierStackLengthStack); - deleteContainer(activeBeautifierStackLengthStack); - deleteContainer(headerStack); - deleteTempStacksContainer(tempStacks); - deleteContainer(parenDepthStack); - deleteContainer(blockStatementStack); - deleteContainer(parenStatementStack); - deleteContainer(braceBlockStateStack); - deleteContainer(continuationIndentStack); - deleteContainer(continuationIndentStackSizeStack); - deleteContainer(parenIndentStack); - deleteContainer(preprocIndentStack); -} - -/** - * initialize the ASBeautifier. - * - * This init() should be called every time a ABeautifier object is to start - * beautifying a NEW source file. - * It is called only when a new ASFormatter object is created. - * init() receives a pointer to a ASSourceIterator object that will be - * used to iterate through the source code. - * - * @param iter a pointer to the ASSourceIterator or ASStreamIterator object. - */ -void ASBeautifier::init(ASSourceIterator* iter) -{ - sourceIterator = iter; - initVectors(); - ASBase::init(getFileType()); - g_preprocessorCppExternCBrace = 0; - - initContainer(waitingBeautifierStack, new vector); - initContainer(activeBeautifierStack, new vector); - - initContainer(waitingBeautifierStackLengthStack, new vector); - initContainer(activeBeautifierStackLengthStack, new vector); - - initContainer(headerStack, new vector); - - initTempStacksContainer(tempStacks, new vector*>); - tempStacks->emplace_back(new vector); - - initContainer(parenDepthStack, new vector); - initContainer(blockStatementStack, new vector); - initContainer(parenStatementStack, new vector); - initContainer(braceBlockStateStack, new vector); - // do not use emplace_back on vector until supported by macOS - braceBlockStateStack->push_back(true); - initContainer(continuationIndentStack, new vector); - initContainer(continuationIndentStackSizeStack, new vector); - continuationIndentStackSizeStack->emplace_back(0); - initContainer(parenIndentStack, new vector); - initContainer(preprocIndentStack, new vector >); - - previousLastLineHeader = nullptr; - currentHeader = nullptr; - - isInQuote = false; - isInVerbatimQuote = false; - haveLineContinuationChar = false; - isInAsm = false; - isInAsmOneLine = false; - isInAsmBlock = false; - isInComment = false; - isInPreprocessorComment = false; - isInRunInComment = false; - isContinuation = false; - isInCase = false; - isInQuestion = false; - isIndentModeOff = false; - isInClassHeader = false; - isInClassHeaderTab = false; - isInClassInitializer = false; - isInClass = false; - isInObjCMethodDefinition = false; - isInObjCMethodCall = false; - isInObjCMethodCallFirst = false; - isImmediatelyPostObjCMethodDefinition = false; - isImmediatelyPostObjCMethodCall = false; - isInIndentablePreprocBlock = false; - isInObjCInterface = false; - isInEnum = false; - isInEnumTypeID = false; - isInLet = false; - isInHeader = false; - isInTemplate = false; - isInConditional = false; - isInTrailingReturnType = false; - - indentCount = 0; - spaceIndentCount = 0; - spaceIndentObjCMethodAlignment = 0; - bracePosObjCMethodAlignment = 0; - colonIndentObjCMethodAlignment = 0; - lineOpeningBlocksNum = 0; - lineClosingBlocksNum = 0; - templateDepth = 0; - squareBracketCount = 0; - parenDepth = 0; - blockTabCount = 0; - prevFinalLineSpaceIndentCount = 0; - prevFinalLineIndentCount = 0; - defineIndentCount = 0; - preprocBlockIndent = 0; - prevNonSpaceCh = '{'; - currentNonSpaceCh = '{'; - prevNonLegalCh = '{'; - currentNonLegalCh = '{'; - quoteChar = ' '; - probationHeader = nullptr; - lastLineHeader = nullptr; - backslashEndsPrevLine = false; - lineOpensWithLineComment = false; - lineOpensWithComment = false; - lineStartsInComment = false; - isInDefine = false; - isInDefineDefinition = false; - lineCommentNoBeautify = false; - isElseHeaderIndent = false; - isCaseHeaderCommentIndent = false; - blockCommentNoIndent = false; - blockCommentNoBeautify = false; - previousLineProbationTab = false; - lineBeginsWithOpenBrace = false; - lineBeginsWithCloseBrace = false; - lineBeginsWithComma = false; - lineIsCommentOnly = false; - lineIsLineCommentOnly = false; - shouldIndentBracedLine = true; - isInSwitch = false; - foundPreCommandHeader = false; - foundPreCommandMacro = false; - - isNonInStatementArray = false; - isSharpAccessor = false; - isSharpDelegate = false; - isInExternC = false; - isInBeautifySQL = false; - isInIndentableStruct = false; - isInIndentablePreproc = false; - inLineNumber = 0; - runInIndentContinuation = 0; - nonInStatementBrace = 0; - objCColonAlignSubsequent = 0; -} - -/* - * initialize the vectors - */ -void ASBeautifier::initVectors() -{ - if (fileType == beautifierFileType) // don't build unless necessary - return; - - beautifierFileType = fileType; - - headers->clear(); - nonParenHeaders->clear(); - assignmentOperators->clear(); - nonAssignmentOperators->clear(); - preBlockStatements->clear(); - preCommandHeaders->clear(); - indentableHeaders->clear(); - - ASResource::buildHeaders(headers, fileType, true); - ASResource::buildNonParenHeaders(nonParenHeaders, fileType, true); - ASResource::buildAssignmentOperators(assignmentOperators); - ASResource::buildNonAssignmentOperators(nonAssignmentOperators); - ASResource::buildPreBlockStatements(preBlockStatements, fileType); - ASResource::buildPreCommandHeaders(preCommandHeaders, fileType); - ASResource::buildIndentableHeaders(indentableHeaders); -} - -/** - * beautify a line of source code. - * every line of source code in a source code file should be sent - * one after the other to the beautify method. - * - * @return the indented line. - * @param originalLine the original unindented line. - */ -string ASBeautifier::beautify(const string& originalLine) -{ - string line; - bool isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar; - - currentHeader = nullptr; - lastLineHeader = nullptr; - blockCommentNoBeautify = blockCommentNoIndent; - isInClass = false; - isInSwitch = false; - lineBeginsWithOpenBrace = false; - lineBeginsWithCloseBrace = false; - lineBeginsWithComma = false; - lineIsCommentOnly = false; - lineIsLineCommentOnly = false; - shouldIndentBracedLine = true; - isInAsmOneLine = false; - lineOpensWithLineComment = false; - lineOpensWithComment = false; - lineStartsInComment = isInComment; - previousLineProbationTab = false; - lineOpeningBlocksNum = 0; - lineClosingBlocksNum = 0; - if (isImmediatelyPostObjCMethodDefinition) - clearObjCMethodDefinitionAlignment(); - if (isImmediatelyPostObjCMethodCall) - { - isImmediatelyPostObjCMethodCall = false; - isInObjCMethodCall = false; - objCColonAlignSubsequent = 0; - } - - // handle and remove white spaces around the line: - // If not in comment, first find out size of white space before line, - // so that possible comments starting in the line continue in - // relation to the preliminary white-space. - if (isInQuoteContinuation) - { - // trim a single space added by ASFormatter, otherwise leave it alone - if (!(originalLine.length() == 1 && originalLine[0] == ' ')) - line = originalLine; - } - else if (isInComment || isInBeautifySQL) - { - // trim the end of comment and SQL lines - line = originalLine; - size_t trimEnd = line.find_last_not_of(" \t"); - if (trimEnd == string::npos) - trimEnd = 0; - else - trimEnd++; - if (trimEnd < line.length()) - line.erase(trimEnd); - // does a brace open the line - size_t firstChar = line.find_first_not_of(" \t"); - if (firstChar != string::npos) - { - if (line[firstChar] == '{') - lineBeginsWithOpenBrace = true; - else if (line[firstChar] == '}') - lineBeginsWithCloseBrace = true; - else if (line[firstChar] == ',') - lineBeginsWithComma = true; - } - } - else - { - line = trim(originalLine); - if (line.length() > 0) - { - if (line[0] == '{') - lineBeginsWithOpenBrace = true; - else if (line[0] == '}') - lineBeginsWithCloseBrace = true; - else if (line[0] == ',') - lineBeginsWithComma = true; - else if (line.compare(0, 2, "//") == 0) - lineIsLineCommentOnly = true; - else if (line.compare(0, 2, "/*") == 0) - { - if (line.find("*/", 2) != string::npos) - lineIsCommentOnly = true; - } - } - - isInRunInComment = false; - size_t j = line.find_first_not_of(" \t{"); - if (j != string::npos && line.compare(j, 2, "//") == 0) - lineOpensWithLineComment = true; - if (j != string::npos && line.compare(j, 2, "/*") == 0) - { - lineOpensWithComment = true; - size_t k = line.find_first_not_of(" \t"); - if (k != string::npos && line.compare(k, 1, "{") == 0) - isInRunInComment = true; - } - } - - // When indent is OFF the lines must still be processed by ASBeautifier. - // Otherwise the lines immediately following may not be indented correctly. - if ((lineIsLineCommentOnly || lineIsCommentOnly) - && line.find("*INDENT-OFF*", 0) != string::npos) - isIndentModeOff = true; - - if (line.length() == 0) - { - if (backslashEndsPrevLine) - { - backslashEndsPrevLine = false; - // check if this line ends a multi-line #define - // if so, remove the #define's cloned beautifier from the active - // beautifier stack and delete it. - if (isInDefineDefinition && !isInDefine) - { - isInDefineDefinition = false; - if (!activeBeautifierStack->empty()) - { - ASBeautifier* defineBeautifier = activeBeautifierStack->back(); - activeBeautifierStack->pop_back(); - delete defineBeautifier; - } - } - } - if (emptyLineFill && !isInQuoteContinuation) - { - if (isInIndentablePreprocBlock) - return preLineWS(preprocBlockIndent, 0); - if (!headerStack->empty() || isInEnum) - return preLineWS(prevFinalLineIndentCount, prevFinalLineSpaceIndentCount); - // must fall thru here - } - else - return line; - } - - // handle preprocessor commands - if (isInIndentablePreprocBlock - && line.length() > 0 - && line[0] != '#') - { - string indentedLine; - if (isInClassHeaderTab || isInClassInitializer) - { - // parsing is turned off in ASFormatter by indent-off - // the originalLine will probably never be returned here - indentedLine = preLineWS(prevFinalLineIndentCount, prevFinalLineSpaceIndentCount) + line; - return getIndentedLineReturn(indentedLine, originalLine); - } - indentedLine = preLineWS(preprocBlockIndent, 0) + line; - return getIndentedLineReturn(indentedLine, originalLine); - } - - if (!isInComment - && !isInQuoteContinuation - && line.length() > 0 - && ((line[0] == '#' && !isIndentedPreprocessor(line, 0)) - || backslashEndsPrevLine)) - { - if (line[0] == '#' && !isInDefine) - { - string preproc = extractPreprocessorStatement(line); - processPreprocessor(preproc, line); - if (isInIndentablePreprocBlock || isInIndentablePreproc) - { - string indentedLine; - if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef - { - indentedLine = preLineWS(preprocBlockIndent, 0) + line; - preprocBlockIndent += 1; - isInIndentablePreprocBlock = true; - } - else if (preproc == "else" || preproc == "elif") - { - indentedLine = preLineWS(preprocBlockIndent - 1, 0) + line; - } - else if (preproc == "endif") - { - preprocBlockIndent -= 1; - indentedLine = preLineWS(preprocBlockIndent, 0) + line; - if (preprocBlockIndent == 0) - isInIndentablePreprocBlock = false; - } - else - indentedLine = preLineWS(preprocBlockIndent, 0) + line; - return getIndentedLineReturn(indentedLine, originalLine); - } - if (shouldIndentPreprocConditional && preproc.length() > 0) - { - string indentedLine; - if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef - { - pair entry; // indentCount, spaceIndentCount - if (!isInDefine && activeBeautifierStack != nullptr && !activeBeautifierStack->empty()) - entry = activeBeautifierStack->back()->computePreprocessorIndent(); - else - entry = computePreprocessorIndent(); - preprocIndentStack->emplace_back(entry); - indentedLine = preLineWS(preprocIndentStack->back().first, - preprocIndentStack->back().second) + line; - return getIndentedLineReturn(indentedLine, originalLine); - } - if (preproc == "else" || preproc == "elif") - { - if (!preprocIndentStack->empty()) // if no entry don't indent - { - indentedLine = preLineWS(preprocIndentStack->back().first, - preprocIndentStack->back().second) + line; - return getIndentedLineReturn(indentedLine, originalLine); - } - } - else if (preproc == "endif") - { - if (!preprocIndentStack->empty()) // if no entry don't indent - { - indentedLine = preLineWS(preprocIndentStack->back().first, - preprocIndentStack->back().second) + line; - preprocIndentStack->pop_back(); - return getIndentedLineReturn(indentedLine, originalLine); - } - } - } - } - - // check if the last char is a backslash - if (line.length() > 0) - backslashEndsPrevLine = (line[line.length() - 1] == '\\'); - // comments within the definition line can be continued without the backslash - if (isInPreprocessorUnterminatedComment(line)) - backslashEndsPrevLine = true; - - // check if this line ends a multi-line #define - // if so, use the #define's cloned beautifier for the line's indentation - // and then remove it from the active beautifier stack and delete it. - if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine) - { - isInDefineDefinition = false; - // this could happen with invalid input - if (activeBeautifierStack->empty()) - return originalLine; - ASBeautifier* defineBeautifier = activeBeautifierStack->back(); - activeBeautifierStack->pop_back(); - - string indentedLine = defineBeautifier->beautify(line); - delete defineBeautifier; - return getIndentedLineReturn(indentedLine, originalLine); - } - - // unless this is a multi-line #define, return this precompiler line as is. - if (!isInDefine && !isInDefineDefinition) - return originalLine; - } - - // if there exists any worker beautifier in the activeBeautifierStack, - // then use it instead of me to indent the current line. - // variables set by ASFormatter must be updated. - if (!isInDefine && activeBeautifierStack != nullptr && !activeBeautifierStack->empty()) - { - activeBeautifierStack->back()->inLineNumber = inLineNumber; - activeBeautifierStack->back()->runInIndentContinuation = runInIndentContinuation; - activeBeautifierStack->back()->nonInStatementBrace = nonInStatementBrace; - activeBeautifierStack->back()->objCColonAlignSubsequent = objCColonAlignSubsequent; - activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify; - activeBeautifierStack->back()->isElseHeaderIndent = isElseHeaderIndent; - activeBeautifierStack->back()->isCaseHeaderCommentIndent = isCaseHeaderCommentIndent; - activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray; - activeBeautifierStack->back()->isSharpAccessor = isSharpAccessor; - activeBeautifierStack->back()->isSharpDelegate = isSharpDelegate; - activeBeautifierStack->back()->isInExternC = isInExternC; - activeBeautifierStack->back()->isInBeautifySQL = isInBeautifySQL; - activeBeautifierStack->back()->isInIndentableStruct = isInIndentableStruct; - activeBeautifierStack->back()->isInIndentablePreproc = isInIndentablePreproc; - // must return originalLine not the trimmed line - return activeBeautifierStack->back()->beautify(originalLine); - } - - // Flag an indented header in case this line is a one-line block. - // The header in the header stack will be deleted by a one-line block. - bool isInExtraHeaderIndent = false; - if (!headerStack->empty() - && lineBeginsWithOpenBrace - && (headerStack->back() != &AS_OPEN_BRACE - || probationHeader != nullptr)) - isInExtraHeaderIndent = true; - - size_t iPrelim = headerStack->size(); - - // calculate preliminary indentation based on headerStack and data from past lines - computePreliminaryIndentation(); - - // parse characters in the current line. - parseCurrentLine(line); - - // handle special cases of indentation - adjustParsedLineIndentation(iPrelim, isInExtraHeaderIndent); - - if (isInObjCMethodDefinition) - adjustObjCMethodDefinitionIndentation(line); - - if (isInObjCMethodCall) - adjustObjCMethodCallIndentation(line); - - if (isInDefine) - { - if (line.length() > 0 && line[0] == '#') - { - // the 'define' does not have to be attached to the '#' - string preproc = trim(line.substr(1)); - if (preproc.compare(0, 6, "define") == 0) - { - if (!continuationIndentStack->empty() - && continuationIndentStack->back() > 0) - { - defineIndentCount = indentCount; - } - else - { - defineIndentCount = indentCount - 1; - --indentCount; - } - } - } - - indentCount -= defineIndentCount; - } - - if (indentCount < 0) - indentCount = 0; - - if (lineCommentNoBeautify || blockCommentNoBeautify || isInQuoteContinuation) - indentCount = spaceIndentCount = 0; - - // finally, insert indentations into beginning of line - - string indentedLine = preLineWS(indentCount, spaceIndentCount) + line; - indentedLine = getIndentedLineReturn(indentedLine, originalLine); - - prevFinalLineSpaceIndentCount = spaceIndentCount; - prevFinalLineIndentCount = indentCount; - - if (lastLineHeader != nullptr) - previousLastLineHeader = lastLineHeader; - - if ((lineIsLineCommentOnly || lineIsCommentOnly) - && line.find("*INDENT-ON*", 0) != string::npos) - isIndentModeOff = false; - - return indentedLine; -} - -/** - * set indentation style to C/C++. - */ -void ASBeautifier::setCStyle() -{ - fileType = C_TYPE; -} - -/** - * set indentation style to Java. - */ -void ASBeautifier::setJavaStyle() -{ - fileType = JAVA_TYPE; -} - -/** - * set indentation style to C#. - */ -void ASBeautifier::setSharpStyle() -{ - fileType = SHARP_TYPE; -} - -/** - * set mode manually set flag - */ -void ASBeautifier::setModeManuallySet(bool state) -{ - isModeManuallySet = state; -} - -/** - * set tabLength equal to indentLength. - * This is done when tabLength is not explicitly set by - * "indent=force-tab-x" - * - */ -void ASBeautifier::setDefaultTabLength() -{ - tabLength = indentLength; -} - -/** - * indent using a different tab setting for indent=force-tab - * - * @param length number of spaces per tab. - */ -void ASBeautifier::setForceTabXIndentation(int length) -{ - // set tabLength instead of indentLength - indentString = "\t"; - tabLength = length; - shouldForceTabIndentation = true; -} - -/** - * indent using one tab per indentation - */ -void ASBeautifier::setTabIndentation(int length, bool forceTabs) -{ - indentString = "\t"; - indentLength = length; - shouldForceTabIndentation = forceTabs; -} - -/** - * indent using a number of spaces per indentation. - * - * @param length number of spaces per indent. - */ -void ASBeautifier::setSpaceIndentation(int length) -{ - indentString = string(length, ' '); - indentLength = length; -} - -/** -* indent continuation lines using a number of indents. -* -* @param indent number of indents per line. -*/ -void ASBeautifier::setContinuationIndentation(int indent) -{ - continuationIndent = indent; -} - -/** - * set the maximum indentation between two lines in a multi-line statement. - * - * @param max maximum indentation length. - */ -void ASBeautifier::setMaxContinuationIndentLength(int max) -{ - maxContinuationIndent = max; -} - -// retained for compatibility with release 2.06 -// "MaxInStatementIndent" has been changed to "MaxContinuationIndent" in 3.0 -// it is referenced only by the old "MaxInStatementIndent" options -void ASBeautifier::setMaxInStatementIndentLength(int max) -{ - setMaxContinuationIndentLength(max); -} - -/** - * set the minimum conditional indentation option. - * - * @param min minimal indentation option. - */ -void ASBeautifier::setMinConditionalIndentOption(int min) -{ - minConditionalOption = min; -} - -/** - * set minConditionalIndent from the minConditionalOption. - */ -void ASBeautifier::setMinConditionalIndentLength() -{ - if (minConditionalOption == MINCOND_ZERO) - minConditionalIndent = 0; - else if (minConditionalOption == MINCOND_ONE) - minConditionalIndent = indentLength; - else if (minConditionalOption == MINCOND_ONEHALF) - minConditionalIndent = indentLength / 2; - // minConditionalOption = INDENT_TWO - else - minConditionalIndent = indentLength * 2; -} - -/** - * set the state of the brace indent option. If true, braces will - * be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setBraceIndent(bool state) -{ - braceIndent = state; -} - -/** -* set the state of the brace indent VTK option. If true, braces will -* be indented one additional indent, except for the opening brace. -* -* @param state state of option. -*/ -void ASBeautifier::setBraceIndentVtk(bool state) -{ - // need to set both of these - setBraceIndent(state); - braceIndentVtk = state; -} - -/** - * set the state of the block indentation option. If true, entire blocks - * will be indented one additional indent, similar to the GNU indent style. - * - * @param state state of option. - */ -void ASBeautifier::setBlockIndent(bool state) -{ - blockIndent = state; -} - -/** - * set the state of the class indentation option. If true, C++ class - * definitions will be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setClassIndent(bool state) -{ - classIndent = state; -} - -/** - * set the state of the modifier indentation option. If true, C++ class - * access modifiers will be indented one-half an indent. - * - * @param state state of option. - */ -void ASBeautifier::setModifierIndent(bool state) -{ - modifierIndent = state; -} - -/** - * set the state of the switch indentation option. If true, blocks of 'switch' - * statements will be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setSwitchIndent(bool state) -{ - switchIndent = state; -} - -/** - * set the state of the case indentation option. If true, lines of 'case' - * statements will be indented one additional indent. - * - * @param state state of option. - */ -void ASBeautifier::setCaseIndent(bool state) -{ - caseIndent = state; -} - -/** - * set the state of the namespace indentation option. - * If true, blocks of 'namespace' statements will be indented one - * additional indent. Otherwise, NO indentation will be added. - * - * @param state state of option. - */ -void ASBeautifier::setNamespaceIndent(bool state) -{ - namespaceIndent = state; -} - -/** -* set the state of the indent after parens option. -* -* @param state state of option. -*/ -void ASBeautifier::setAfterParenIndent(bool state) -{ - shouldIndentAfterParen = state; -} - -/** - * set the state of the label indentation option. - * If true, labels will be indented one indent LESS than the - * current indentation level. - * If false, labels will be flushed to the left with NO - * indent at all. - * - * @param state state of option. - */ -void ASBeautifier::setLabelIndent(bool state) -{ - labelIndent = state; -} - -/** - * set the state of the preprocessor indentation option. - * If true, multi-line #define statements will be indented. - * - * @param state state of option. - */ -void ASBeautifier::setPreprocDefineIndent(bool state) -{ - shouldIndentPreprocDefine = state; -} - -void ASBeautifier::setPreprocConditionalIndent(bool state) -{ - shouldIndentPreprocConditional = state; -} - -/** - * set the state of the empty line fill option. - * If true, empty lines will be filled with the whitespace. - * of their previous lines. - * If false, these lines will remain empty. - * - * @param state state of option. - */ -void ASBeautifier::setEmptyLineFill(bool state) -{ - emptyLineFill = state; -} - -void ASBeautifier::setAlignMethodColon(bool state) -{ - shouldAlignMethodColon = state; -} - -/** - * get the file type. - */ -int ASBeautifier::getFileType() const -{ - return fileType; -} - -/** - * get the number of spaces per indent - * - * @return value of indentLength option. - */ -int ASBeautifier::getIndentLength() const -{ - return indentLength; -} - -/** - * get the char used for indentation, space or tab - * - * @return the char used for indentation. - */ -string ASBeautifier::getIndentString() const -{ - return indentString; -} - -/** - * get mode manually set flag - */ -bool ASBeautifier::getModeManuallySet() const -{ - return isModeManuallySet; -} - -/** - * get the state of the force tab indentation option. - * - * @return state of force tab indentation. - */ -bool ASBeautifier::getForceTabIndentation() const -{ - return shouldForceTabIndentation; -} - -/** -* Get the state of the Objective-C align method colon option. -* -* @return state of shouldAlignMethodColon option. -*/ -bool ASBeautifier::getAlignMethodColon() const -{ - return shouldAlignMethodColon; -} - -/** - * get the state of the block indentation option. - * - * @return state of blockIndent option. - */ -bool ASBeautifier::getBlockIndent() const -{ - return blockIndent; -} - -/** - * get the state of the brace indentation option. - * - * @return state of braceIndent option. - */ -bool ASBeautifier::getBraceIndent() const -{ - return braceIndent; -} - -/** -* Get the state of the namespace indentation option. If true, blocks -* of the 'namespace' statement will be indented one additional indent. -* -* @return state of namespaceIndent option. -*/ -bool ASBeautifier::getNamespaceIndent() const -{ - return namespaceIndent; -} - -/** - * Get the state of the class indentation option. If true, blocks of - * the 'class' statement will be indented one additional indent. - * - * @return state of classIndent option. - */ -bool ASBeautifier::getClassIndent() const -{ - return classIndent; -} - -/** - * Get the state of the class access modifier indentation option. - * If true, the class access modifiers will be indented one-half indent. - * - * @return state of modifierIndent option. - */ -bool ASBeautifier::getModifierIndent() const -{ - return modifierIndent; -} - -/** - * get the state of the switch indentation option. If true, blocks of - * the 'switch' statement will be indented one additional indent. - * - * @return state of switchIndent option. - */ -bool ASBeautifier::getSwitchIndent() const -{ - return switchIndent; -} - -/** - * get the state of the case indentation option. If true, lines of 'case' - * statements will be indented one additional indent. - * - * @return state of caseIndent option. - */ -bool ASBeautifier::getCaseIndent() const -{ - return caseIndent; -} - -/** - * get the state of the empty line fill option. - * If true, empty lines will be filled with the whitespace. - * of their previous lines. - * If false, these lines will remain empty. - * - * @return state of emptyLineFill option. - */ -bool ASBeautifier::getEmptyLineFill() const -{ - return emptyLineFill; -} - -/** - * get the state of the preprocessor indentation option. - * If true, preprocessor "define" lines will be indented. - * If false, preprocessor "define" lines will be unchanged. - * - * @return state of shouldIndentPreprocDefine option. - */ -bool ASBeautifier::getPreprocDefineIndent() const -{ - return shouldIndentPreprocDefine; -} - -/** - * get the length of the tab indentation option. - * - * @return length of tab indent option. - */ -int ASBeautifier::getTabLength() const -{ - return tabLength; -} - -const string& ASBeautifier::getIndentedLineReturn(const string& newLine, const string& originalLine) const -{ - if (isIndentModeOff) - return originalLine; - return newLine; -} - -string ASBeautifier::preLineWS(int lineIndentCount, int lineSpaceIndentCount) const -{ - if (shouldForceTabIndentation) - { - if (tabLength != indentLength) - { - // adjust for different tab length - int indentCountOrig = lineIndentCount; - int spaceIndentCountOrig = lineSpaceIndentCount; - lineIndentCount = ((indentCountOrig * indentLength) + spaceIndentCountOrig) / tabLength; - lineSpaceIndentCount = ((indentCountOrig * indentLength) + spaceIndentCountOrig) % tabLength; - } - else - { - lineIndentCount += lineSpaceIndentCount / indentLength; - lineSpaceIndentCount = lineSpaceIndentCount % indentLength; - } - } - - string ws; - for (int i = 0; i < lineIndentCount; i++) - ws += indentString; - while ((lineSpaceIndentCount--) > 0) - ws += string(" "); - return ws; -} - -/** - * register a continuation indent. - */ -void ASBeautifier::registerContinuationIndent(const string& line, int i, int spaceIndentCount_, - int tabIncrementIn, int minIndent, bool updateParenStack) -{ - assert(i >= -1); - int remainingCharNum = line.length() - i; - int nextNonWSChar = getNextProgramCharDistance(line, i); - - // if indent is around the last char in the line OR indent-after-paren is requested, - // indent with the continuation indent - if (nextNonWSChar == remainingCharNum || shouldIndentAfterParen) - { - int previousIndent = spaceIndentCount_; - if (!continuationIndentStack->empty()) - previousIndent = continuationIndentStack->back(); - int currIndent = continuationIndent * indentLength + previousIndent; - if (currIndent > maxContinuationIndent && line[i] != '{') - currIndent = indentLength * 2 + spaceIndentCount_; - continuationIndentStack->emplace_back(currIndent); - if (updateParenStack) - parenIndentStack->emplace_back(previousIndent); - return; - } - - if (updateParenStack) - { - parenIndentStack->emplace_back(i + spaceIndentCount_ - runInIndentContinuation); - if (parenIndentStack->back() < 0) - parenIndentStack->back() = 0; - } - - int tabIncrement = tabIncrementIn; - - // check for following tabs - for (int j = i + 1; j < (i + nextNonWSChar); j++) - { - if (line[j] == '\t') - tabIncrement += convertTabToSpaces(j, tabIncrement); - } - - int continuationIndentCount = i + nextNonWSChar + spaceIndentCount_ + tabIncrement; - - // check for run-in statement - if (i > 0 && line[0] == '{') - continuationIndentCount -= indentLength; - - if (continuationIndentCount < minIndent) - continuationIndentCount = minIndent + spaceIndentCount_; - - // this is not done for an in-statement array - if (continuationIndentCount > maxContinuationIndent - && !(prevNonLegalCh == '=' && currentNonLegalCh == '{')) - continuationIndentCount = indentLength * 2 + spaceIndentCount_; - - if (!continuationIndentStack->empty() - && continuationIndentCount < continuationIndentStack->back()) - continuationIndentCount = continuationIndentStack->back(); - - // the block opener is not indented for a NonInStatementArray - if ((isNonInStatementArray && i >= 0 && line[i] == '{') - && !isInEnum && !braceBlockStateStack->empty() && braceBlockStateStack->back()) - continuationIndentCount = 0; - - continuationIndentStack->emplace_back(continuationIndentCount); -} - -/** -* Register a continuation indent for a class header or a class initializer colon. -*/ -void ASBeautifier::registerContinuationIndentColon(const string& line, int i, int tabIncrementIn) -{ - assert(line[i] == ':'); - assert(isInClassInitializer || isInClassHeaderTab); - - // register indent at first word after the colon - size_t firstChar = line.find_first_not_of(" \t"); - if (firstChar == (size_t) i) // firstChar is ':' - { - size_t firstWord = line.find_first_not_of(" \t", firstChar + 1); - if (firstWord != string::npos) - { - int continuationIndentCount = firstWord + spaceIndentCount + tabIncrementIn; - continuationIndentStack->emplace_back(continuationIndentCount); - isContinuation = true; - } - } -} - -/** - * Compute indentation for a preprocessor #if statement. - * This may be called for the activeBeautiferStack - * instead of the active ASBeautifier object. - */ -pair ASBeautifier::computePreprocessorIndent() -{ - computePreliminaryIndentation(); - pair entry(indentCount, spaceIndentCount); - if (!headerStack->empty() - && entry.first > 0 - && (headerStack->back() == &AS_IF - || headerStack->back() == &AS_ELSE - || headerStack->back() == &AS_FOR - || headerStack->back() == &AS_WHILE)) - --entry.first; - return entry; -} - -/** - * get distance to the next non-white space, non-comment character in the line. - * if no such character exists, return the length remaining to the end of the line. - */ -int ASBeautifier::getNextProgramCharDistance(const string& line, int i) const -{ - bool inComment = false; - int remainingCharNum = line.length() - i; - int charDistance; - char ch = ' '; - - for (charDistance = 1; charDistance < remainingCharNum; charDistance++) - { - ch = line[i + charDistance]; - if (inComment) - { - if (line.compare(i + charDistance, 2, "*/") == 0) - { - charDistance++; - inComment = false; - } - continue; - } - if (isWhiteSpace(ch)) - continue; - if (ch == '/') - { - if (line.compare(i + charDistance, 2, "//") == 0) - return remainingCharNum; - if (line.compare(i + charDistance, 2, "/*") == 0) - { - charDistance++; - inComment = true; - } - } - else - return charDistance; - } - - return charDistance; -} - -/** - * find the index number of a string element in a container of strings - * - * @return the index number of element in the container. -1 if element not found. - * @param container a vector of strings. - * @param element the element to find . - */ -int ASBeautifier::indexOf(const vector& container, const string* element) const -{ - vector::const_iterator where; - - where = find(container.begin(), container.end(), element); - if (where == container.end()) - return -1; - return (int) (where - container.begin()); -} - -/** - * convert tabs to spaces. - * i is the position of the character to convert to spaces. - * tabIncrementIn is the increment that must be added for tab indent characters - * to get the correct column for the current tab. - */ -int ASBeautifier::convertTabToSpaces(int i, int tabIncrementIn) const -{ - int tabToSpacesAdjustment = indentLength - 1 - ((tabIncrementIn + i) % indentLength); - return tabToSpacesAdjustment; -} - -/** - * trim removes the white space surrounding a line. - * - * @return the trimmed line. - * @param str the line to trim. - */ -string ASBeautifier::trim(const string& str) const -{ - int start = 0; - int end = str.length() - 1; - - while (start < end && isWhiteSpace(str[start])) - start++; - - while (start <= end && isWhiteSpace(str[end])) - end--; - - // don't trim if it ends in a continuation - if (end > -1 && str[end] == '\\') - end = str.length() - 1; - - string returnStr(str, start, end + 1 - start); - return returnStr; -} - -/** - * rtrim removes the white space from the end of a line. - * - * @return the trimmed line. - * @param str the line to trim. - */ -string ASBeautifier::rtrim(const string& str) const -{ - size_t len = str.length(); - size_t end = str.find_last_not_of(" \t"); - if (end == string::npos - || end == len - 1) - return str; - string returnStr(str, 0, end + 1); - return returnStr; -} - -/** - * Copy tempStacks for the copy constructor. - * The value of the vectors must also be copied. - */ -vector*>* ASBeautifier::copyTempStacks(const ASBeautifier& other) const -{ - vector*>* tempStacksNew = new vector*>; - vector*>::iterator iter; - for (iter = other.tempStacks->begin(); - iter != other.tempStacks->end(); - ++iter) - { - vector* newVec = new vector; - *newVec = **iter; - tempStacksNew->emplace_back(newVec); - } - return tempStacksNew; -} - -/** - * delete a member vectors to eliminate memory leak reporting - */ -void ASBeautifier::deleteBeautifierVectors() -{ - beautifierFileType = 9; // reset to an invalid type - delete headers; - delete nonParenHeaders; - delete preBlockStatements; - delete preCommandHeaders; - delete assignmentOperators; - delete nonAssignmentOperators; - delete indentableHeaders; -} - -/** - * delete a vector object - * T is the type of vector - * used for all vectors except tempStacks - */ -template -void ASBeautifier::deleteContainer(T& container) -{ - if (container != nullptr) - { - container->clear(); - delete (container); - container = nullptr; - } -} - -/** - * Delete the ASBeautifier vector object. - * This is a vector of pointers to ASBeautifier objects allocated with the 'new' operator. - * Therefore the ASBeautifier objects have to be deleted in addition to the - * ASBeautifier pointer entries. - */ -void ASBeautifier::deleteBeautifierContainer(vector*& container) -{ - if (container != nullptr) - { - vector::iterator iter = container->begin(); - while (iter < container->end()) - { - delete *iter; - ++iter; - } - container->clear(); - delete (container); - container = nullptr; - } -} - -/** - * Delete the tempStacks vector object. - * The tempStacks is a vector of pointers to strings allocated with the 'new' operator. - * Therefore the strings have to be deleted in addition to the tempStacks entries. - */ -void ASBeautifier::deleteTempStacksContainer(vector*>*& container) -{ - if (container != nullptr) - { - vector*>::iterator iter = container->begin(); - while (iter < container->end()) - { - delete *iter; - ++iter; - } - container->clear(); - delete (container); - container = nullptr; - } -} - -/** - * initialize a vector object - * T is the type of vector used for all vectors - */ -template -void ASBeautifier::initContainer(T& container, T value) -{ - // since the ASFormatter object is never deleted, - // the existing vectors must be deleted before creating new ones - if (container != nullptr) - deleteContainer(container); - container = value; -} - -/** - * Initialize the tempStacks vector object. - * The tempStacks is a vector of pointers to strings allocated with the 'new' operator. - * Any residual entries are deleted before the vector is initialized. - */ -void ASBeautifier::initTempStacksContainer(vector*>*& container, - vector*>* value) -{ - if (container != nullptr) - deleteTempStacksContainer(container); - container = value; -} - -/** - * Determine if an assignment statement ends with a comma - * that is not in a function argument. It ends with a - * comma if a comma is the last char on the line. - * - * @return true if line ends with a comma, otherwise false. - */ -bool ASBeautifier::statementEndsWithComma(const string& line, int index) const -{ - assert(line[index] == '='); - - bool isInComment_ = false; - bool isInQuote_ = false; - int parenCount = 0; - size_t lineLength = line.length(); - size_t i = 0; - char quoteChar_ = ' '; - - for (i = index + 1; i < lineLength; ++i) - { - char 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) - { - if (isLineEndComment(line, i)) - break; - isInComment_ = true; - ++i; - continue; - } - - if (ch == '(') - parenCount++; - if (ch == ')') - parenCount--; - } - if (isInComment_ - || isInQuote_ - || parenCount > 0) - return false; - - size_t lastChar = line.find_last_not_of(" \t", i - 1); - - if (lastChar == string::npos || line[lastChar] != ',') - return false; - - return true; -} - -/** - * check if current comment is a line-end comment - * - * @return is before a line-end comment. - */ -bool ASBeautifier::isLineEndComment(const string& line, int startPos) const -{ - assert(line.compare(startPos, 2, "/*") == 0); - - // comment must be closed on this line with nothing after it - size_t endNum = line.find("*/", startPos + 2); - if (endNum != string::npos) - { - size_t nextChar = line.find_first_not_of(" \t", endNum + 2); - if (nextChar == string::npos) - return true; - } - return false; -} - -/** - * get the previous word index for an assignment operator - * - * @return is the index to the previous word (the in statement indent). - */ -int ASBeautifier::getContinuationIndentAssign(const string& line, size_t currPos) const -{ - assert(line[currPos] == '='); - - if (currPos == 0) - return 0; - - // get the last legal word (may be a number) - size_t end = line.find_last_not_of(" \t", currPos - 1); - if (end == string::npos || !isLegalNameChar(line[end])) - return 0; - - int start; // start of the previous word - for (start = end; start > -1; start--) - { - if (!isLegalNameChar(line[start])) - break; - } - start++; - - return start; -} - -/** - * get the continuation indent for a comma - * - * @return is the indent to the second word on the line (the in statement indent). - */ -int ASBeautifier::getContinuationIndentComma(const string& line, size_t currPos) const -{ - assert(line[currPos] == ','); - - // get first word on a line - size_t indent = line.find_first_not_of(" \t"); - if (indent == string::npos || !isLegalNameChar(line[indent])) - return 0; - - // bypass first word - for (; indent < currPos; indent++) - { - if (!isLegalNameChar(line[indent])) - break; - } - indent++; - if (indent >= currPos || indent < 4) - return 0; - - // point to second word or assignment operator - indent = line.find_first_not_of(" \t", indent); - if (indent == string::npos || indent >= currPos) - return 0; - - return indent; -} - -/** - * get the next word on a line - * the argument 'currPos' must point to the current position. - * - * @return is the next word or an empty string if none found. - */ -string ASBeautifier::getNextWord(const string& line, size_t currPos) const -{ - size_t lineLength = line.length(); - // get the last legal word (may be a number) - if (currPos == lineLength - 1) - return string(); - - size_t start = line.find_first_not_of(" \t", currPos + 1); - if (start == string::npos || !isLegalNameChar(line[start])) - return string(); - - size_t end; // end of the current word - for (end = start + 1; end <= lineLength; end++) - { - if (!isLegalNameChar(line[end]) || line[end] == '.') - break; - } - - return line.substr(start, end - start); -} - -/** - * Check if a preprocessor directive is always indented. - * C# "region" and "endregion" are always indented. - * C/C++ "pragma omp" is always indented. - * - * @return is true or false. - */ -bool ASBeautifier::isIndentedPreprocessor(const string& line, size_t currPos) const -{ - assert(line[0] == '#'); - string nextWord = getNextWord(line, currPos); - if (nextWord == "region" || nextWord == "endregion") - return true; - // is it #pragma omp - if (nextWord == "pragma") - { - // find pragma - size_t start = line.find("pragma"); - if (start == string::npos || !isLegalNameChar(line[start])) - return false; - // bypass pragma - for (; start < line.length(); start++) - { - if (!isLegalNameChar(line[start])) - break; - } - start++; - if (start >= line.length()) - return false; - // point to start of second word - start = line.find_first_not_of(" \t", start); - if (start == string::npos) - return false; - // point to end of second word - size_t end; - for (end = start; end < line.length(); end++) - { - if (!isLegalNameChar(line[end])) - break; - } - // check for "pragma omp" - string word = line.substr(start, end - start); - if (word == "omp" || word == "region" || word == "endregion") - return true; - } - return false; -} - -/** - * Check if a preprocessor directive is checking for __cplusplus defined. - * - * @return is true or false. - */ -bool ASBeautifier::isPreprocessorConditionalCplusplus(const string& line) const -{ - string preproc = trim(line.substr(1)); - if (preproc.compare(0, 5, "ifdef") == 0 && getNextWord(preproc, 4) == "__cplusplus") - return true; - if (preproc.compare(0, 2, "if") == 0) - { - // check for " #if defined(__cplusplus)" - size_t charNum = 2; - charNum = preproc.find_first_not_of(" \t", charNum); - if (charNum != string::npos && preproc.compare(charNum, 7, "defined") == 0) - { - charNum += 7; - charNum = preproc.find_first_not_of(" \t", charNum); - if (charNum != string::npos && preproc.compare(charNum, 1, "(") == 0) - { - ++charNum; - charNum = preproc.find_first_not_of(" \t", charNum); - if (charNum != string::npos && preproc.compare(charNum, 11, "__cplusplus") == 0) - return true; - } - } - } - return false; -} - -/** - * Check if a preprocessor definition contains an unterminated comment. - * Comments within a preprocessor definition can be continued without the backslash. - * - * @return is true or false. - */ -bool ASBeautifier::isInPreprocessorUnterminatedComment(const string& line) -{ - if (!isInPreprocessorComment) - { - size_t startPos = line.find("/*"); - if (startPos == string::npos) - return false; - } - size_t endNum = line.find("*/"); - if (endNum != string::npos) - { - isInPreprocessorComment = false; - return false; - } - isInPreprocessorComment = true; - return true; -} - -void ASBeautifier::popLastContinuationIndent() -{ - assert(!continuationIndentStackSizeStack->empty()); - int previousIndentStackSize = continuationIndentStackSizeStack->back(); - if (continuationIndentStackSizeStack->size() > 1) - continuationIndentStackSizeStack->pop_back(); - while (previousIndentStackSize < (int) continuationIndentStack->size()) - continuationIndentStack->pop_back(); -} - -// for unit testing -int ASBeautifier::getBeautifierFileType() const -{ return beautifierFileType; } - -/** - * Process preprocessor statements and update the beautifier stacks. - */ -void ASBeautifier::processPreprocessor(const string& preproc, const string& line) -{ - // When finding a multi-lined #define statement, the original beautifier - // 1. sets its isInDefineDefinition flag - // 2. clones a new beautifier that will be used for the actual indentation - // of the #define. This clone is put into the activeBeautifierStack in order - // to be called for the actual indentation. - // The original beautifier will have isInDefineDefinition = true, isInDefine = false - // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true - if (shouldIndentPreprocDefine && preproc == "define" && line[line.length() - 1] == '\\') - { - if (!isInDefineDefinition) - { - // this is the original beautifier - isInDefineDefinition = true; - - // push a new beautifier into the active stack - // this beautifier will be used for the indentation of this define - ASBeautifier* defineBeautifier = new ASBeautifier(*this); - activeBeautifierStack->emplace_back(defineBeautifier); - } - else - { - // the is the cloned beautifier that is in charge of indenting the #define. - isInDefine = true; - } - } - else if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") - { - if (isPreprocessorConditionalCplusplus(line) && !g_preprocessorCppExternCBrace) - g_preprocessorCppExternCBrace = 1; - // push a new beautifier into the stack - waitingBeautifierStackLengthStack->emplace_back(waitingBeautifierStack->size()); - activeBeautifierStackLengthStack->emplace_back(activeBeautifierStack->size()); - if (activeBeautifierStackLengthStack->back() == 0) - waitingBeautifierStack->emplace_back(new ASBeautifier(*this)); - else - waitingBeautifierStack->emplace_back(new ASBeautifier(*activeBeautifierStack->back())); - } - else if (preproc == "else") - { - if ((waitingBeautifierStack != nullptr) && !waitingBeautifierStack->empty()) - { - // MOVE current waiting beautifier to active stack. - activeBeautifierStack->emplace_back(waitingBeautifierStack->back()); - waitingBeautifierStack->pop_back(); - } - } - else if (preproc == "elif") - { - if ((waitingBeautifierStack != nullptr) && !waitingBeautifierStack->empty()) - { - // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original. - activeBeautifierStack->emplace_back(new ASBeautifier(*(waitingBeautifierStack->back()))); - } - } - else if (preproc == "endif") - { - int stackLength = 0; - ASBeautifier* beautifier = nullptr; - - if (waitingBeautifierStackLengthStack != nullptr && !waitingBeautifierStackLengthStack->empty()) - { - stackLength = waitingBeautifierStackLengthStack->back(); - waitingBeautifierStackLengthStack->pop_back(); - while ((int) waitingBeautifierStack->size() > stackLength) - { - beautifier = waitingBeautifierStack->back(); - waitingBeautifierStack->pop_back(); - delete beautifier; - } - } - - if (!activeBeautifierStackLengthStack->empty()) - { - stackLength = activeBeautifierStackLengthStack->back(); - activeBeautifierStackLengthStack->pop_back(); - while ((int) activeBeautifierStack->size() > stackLength) - { - beautifier = activeBeautifierStack->back(); - activeBeautifierStack->pop_back(); - delete beautifier; - } - } - } -} - -// Compute the preliminary indentation based on data in the headerStack -// and data from previous lines. -// Update the class variable indentCount. -void ASBeautifier::computePreliminaryIndentation() -{ - indentCount = 0; - spaceIndentCount = 0; - isInClassHeaderTab = false; - - if (isInObjCMethodDefinition && !continuationIndentStack->empty()) - spaceIndentObjCMethodAlignment = continuationIndentStack->back(); - - if (!continuationIndentStack->empty()) - spaceIndentCount = continuationIndentStack->back(); - - for (size_t i = 0; i < headerStack->size(); i++) - { - isInClass = false; - - if (blockIndent) - { - // do NOT indent opening block for these headers - if (!((*headerStack)[i] == &AS_NAMESPACE - || (*headerStack)[i] == &AS_MODULE - || (*headerStack)[i] == &AS_CLASS - || (*headerStack)[i] == &AS_STRUCT - || (*headerStack)[i] == &AS_UNION - || (*headerStack)[i] == &AS_INTERFACE - || (*headerStack)[i] == &AS_THROWS - || (*headerStack)[i] == &AS_STATIC)) - ++indentCount; - } - else if (!(i > 0 && (*headerStack)[i - 1] != &AS_OPEN_BRACE - && (*headerStack)[i] == &AS_OPEN_BRACE)) - ++indentCount; - - if (!isJavaStyle() && !namespaceIndent && i > 0 - && ((*headerStack)[i - 1] == &AS_NAMESPACE - || (*headerStack)[i - 1] == &AS_MODULE) - && (*headerStack)[i] == &AS_OPEN_BRACE) - --indentCount; - - if (isCStyle() && i >= 1 - && (*headerStack)[i - 1] == &AS_CLASS - && (*headerStack)[i] == &AS_OPEN_BRACE) - { - if (classIndent) - ++indentCount; - isInClass = true; - } - - // is the switchIndent option is on, indent switch statements an additional indent. - else if (switchIndent && i > 1 - && (*headerStack)[i - 1] == &AS_SWITCH - && (*headerStack)[i] == &AS_OPEN_BRACE) - { - ++indentCount; - isInSwitch = true; - } - - } // end of for loop - - if (isInClassHeader) - { - if (!isJavaStyle()) - isInClassHeaderTab = true; - if (lineOpensWithLineComment || lineStartsInComment || lineOpensWithComment) - { - if (!lineBeginsWithOpenBrace) - --indentCount; - if (!continuationIndentStack->empty()) - spaceIndentCount -= continuationIndentStack->back(); - } - else if (blockIndent) - { - if (!lineBeginsWithOpenBrace) - ++indentCount; - } - } - - if (isInClassInitializer || isInEnumTypeID) - { - indentCount += classInitializerIndents; - } - - if (isInEnum && lineBeginsWithComma && !continuationIndentStack->empty()) - { - // unregister '=' indent from the previous line - continuationIndentStack->pop_back(); - isContinuation = false; - spaceIndentCount = 0; - } - - // Objective-C interface continuation line - if (isInObjCInterface) - ++indentCount; - - // unindent a class closing brace... - if (!lineStartsInComment - && isCStyle() - && isInClass - && classIndent - && headerStack->size() >= 2 - && (*headerStack)[headerStack->size() - 2] == &AS_CLASS - && (*headerStack)[headerStack->size() - 1] == &AS_OPEN_BRACE - && lineBeginsWithCloseBrace - && braceBlockStateStack->back()) - --indentCount; - - // unindent an indented switch closing brace... - else if (!lineStartsInComment - && isInSwitch - && switchIndent - && headerStack->size() >= 2 - && (*headerStack)[headerStack->size() - 2] == &AS_SWITCH - && (*headerStack)[headerStack->size() - 1] == &AS_OPEN_BRACE - && lineBeginsWithCloseBrace) - --indentCount; - - // handle special case of run-in comment in an indented class statement - if (isInClass - && classIndent - && isInRunInComment - && !lineOpensWithComment - && headerStack->size() > 1 - && (*headerStack)[headerStack->size() - 2] == &AS_CLASS) - --indentCount; - - if (isInConditional) - --indentCount; - if (g_preprocessorCppExternCBrace >= 4) - --indentCount; -} - -void ASBeautifier::adjustParsedLineIndentation(size_t iPrelim, bool isInExtraHeaderIndent) -{ - if (lineStartsInComment) - return; - - // unindent a one-line statement in a header indent - if (!blockIndent - && lineBeginsWithOpenBrace - && headerStack->size() < iPrelim - && isInExtraHeaderIndent - && (lineOpeningBlocksNum > 0 && lineOpeningBlocksNum <= lineClosingBlocksNum) - && shouldIndentBracedLine) - --indentCount; - - /* - * if '{' doesn't follow an immediately previous '{' in the headerStack - * (but rather another header such as "for" or "if", then unindent it - * by one indentation relative to its block. - */ - else if (!blockIndent - && lineBeginsWithOpenBrace - && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum <= lineClosingBlocksNum) - && (headerStack->size() > 1 && (*headerStack)[headerStack->size() - 2] != &AS_OPEN_BRACE) - && shouldIndentBracedLine) - --indentCount; - - // must check one less in headerStack if more than one header on a line (allow-addins)... - else if (headerStack->size() > iPrelim + 1 - && !blockIndent - && lineBeginsWithOpenBrace - && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum <= lineClosingBlocksNum) - && (headerStack->size() > 2 && (*headerStack)[headerStack->size() - 3] != &AS_OPEN_BRACE) - && shouldIndentBracedLine) - --indentCount; - - // unindent a closing brace... - else if (lineBeginsWithCloseBrace - && shouldIndentBracedLine) - --indentCount; - - // correctly indent one-line-blocks... - else if (lineOpeningBlocksNum > 0 - && lineOpeningBlocksNum == lineClosingBlocksNum - && previousLineProbationTab) - --indentCount; - - if (indentCount < 0) - indentCount = 0; - - // take care of extra brace indentation option... - if (!lineStartsInComment - && braceIndent - && shouldIndentBracedLine - && (lineBeginsWithOpenBrace || lineBeginsWithCloseBrace)) - { - if (!braceIndentVtk) - ++indentCount; - else - { - // determine if a style VTK brace is indented - bool haveUnindentedBrace = false; - for (size_t i = 0; i < headerStack->size(); i++) - { - if (((*headerStack)[i] == &AS_NAMESPACE - || (*headerStack)[i] == &AS_MODULE - || (*headerStack)[i] == &AS_CLASS - || (*headerStack)[i] == &AS_STRUCT) - && i + 1 < headerStack->size() - && (*headerStack)[i + 1] == &AS_OPEN_BRACE) - i++; - else if (lineBeginsWithOpenBrace) - { - // don't double count the current brace - if (i + 1 < headerStack->size() - && (*headerStack)[i] == &AS_OPEN_BRACE) - haveUnindentedBrace = true; - } - else if ((*headerStack)[i] == &AS_OPEN_BRACE) - haveUnindentedBrace = true; - } // end of for loop - if (haveUnindentedBrace) - ++indentCount; - } - } -} - -/** - * Compute indentCount adjustment when in a series of else-if statements - * and shouldBreakElseIfs is requested. - * It increments by one for each 'else' in the tempStack. - */ -int ASBeautifier::adjustIndentCountForBreakElseIfComments() const -{ - assert(isElseHeaderIndent && !tempStacks->empty()); - int indentCountIncrement = 0; - vector* lastTempStack = tempStacks->back(); - if (lastTempStack != nullptr) - { - for (const string* const lastTemp : *lastTempStack) - { - if (*lastTemp == AS_ELSE) - indentCountIncrement++; - } - } - return indentCountIncrement; -} - -/** - * Extract a preprocessor statement without the #. - * If a error occurs an empty string is returned. - */ -string ASBeautifier::extractPreprocessorStatement(const string& line) const -{ - string preproc; - size_t start = line.find_first_not_of("#/ \t"); - if (start == string::npos) - return preproc; - size_t end = line.find_first_of("/ \t", start); - if (end == string::npos) - end = line.length(); - preproc = line.substr(start, end - start); - return preproc; -} - -void ASBeautifier::adjustObjCMethodDefinitionIndentation(const string& line_) -{ - // register indent for Objective-C continuation line - if (line_.length() > 0 - && (line_[0] == '-' || line_[0] == '+')) - { - if (shouldAlignMethodColon && objCColonAlignSubsequent != -1) - { - string convertedLine = getIndentedSpaceEquivalent(line_); - colonIndentObjCMethodAlignment = findObjCColonAlignment(convertedLine); - int objCColonAlignSubsequentIndent = objCColonAlignSubsequent + indentLength; - if (objCColonAlignSubsequentIndent > colonIndentObjCMethodAlignment) - colonIndentObjCMethodAlignment = objCColonAlignSubsequentIndent; - } - else if (continuationIndentStack->empty() - || continuationIndentStack->back() == 0) - { - continuationIndentStack->emplace_back(indentLength); - isContinuation = true; - } - } - // set indent for last definition line - else if (!lineBeginsWithOpenBrace) - { - if (shouldAlignMethodColon) - spaceIndentCount = computeObjCColonAlignment(line_, colonIndentObjCMethodAlignment); - else if (continuationIndentStack->empty()) - spaceIndentCount = spaceIndentObjCMethodAlignment; - } -} - -void ASBeautifier::adjustObjCMethodCallIndentation(const string& line_) -{ - static int keywordIndentObjCMethodAlignment = 0; - if (shouldAlignMethodColon && objCColonAlignSubsequent != -1) - { - if (isInObjCMethodCallFirst) - { - isInObjCMethodCallFirst = false; - string convertedLine = getIndentedSpaceEquivalent(line_); - bracePosObjCMethodAlignment = convertedLine.find('['); - keywordIndentObjCMethodAlignment = - getObjCFollowingKeyword(convertedLine, bracePosObjCMethodAlignment); - colonIndentObjCMethodAlignment = findObjCColonAlignment(convertedLine); - if (colonIndentObjCMethodAlignment >= 0) - { - int objCColonAlignSubsequentIndent = objCColonAlignSubsequent + indentLength; - if (objCColonAlignSubsequentIndent > colonIndentObjCMethodAlignment) - colonIndentObjCMethodAlignment = objCColonAlignSubsequentIndent; - if (lineBeginsWithOpenBrace) - colonIndentObjCMethodAlignment -= indentLength; - } - } - else - { - if (findObjCColonAlignment(line_) != -1) - { - if (colonIndentObjCMethodAlignment < 0) - spaceIndentCount += computeObjCColonAlignment(line_, objCColonAlignSubsequent); - else if (objCColonAlignSubsequent > colonIndentObjCMethodAlignment) - spaceIndentCount = computeObjCColonAlignment(line_, objCColonAlignSubsequent); - else - spaceIndentCount = computeObjCColonAlignment(line_, colonIndentObjCMethodAlignment); - } - else - { - if (spaceIndentCount < colonIndentObjCMethodAlignment) - spaceIndentCount += keywordIndentObjCMethodAlignment; - } - } - } - else // align keywords instead of colons - { - if (isInObjCMethodCallFirst) - { - isInObjCMethodCallFirst = false; - string convertedLine = getIndentedSpaceEquivalent(line_); - bracePosObjCMethodAlignment = convertedLine.find('['); - keywordIndentObjCMethodAlignment = - getObjCFollowingKeyword(convertedLine, bracePosObjCMethodAlignment); - } - else - { - if (spaceIndentCount < keywordIndentObjCMethodAlignment + bracePosObjCMethodAlignment) - spaceIndentCount += keywordIndentObjCMethodAlignment; - } - } -} - -/** - * Clear the variables used to align the Objective-C method definitions. - */ -void ASBeautifier::clearObjCMethodDefinitionAlignment() -{ - assert(isImmediatelyPostObjCMethodDefinition); - spaceIndentCount = 0; - spaceIndentObjCMethodAlignment = 0; - colonIndentObjCMethodAlignment = 0; - isInObjCMethodDefinition = false; - isImmediatelyPostObjCMethodDefinition = false; - if (!continuationIndentStack->empty()) - continuationIndentStack->pop_back(); -} - -/** - * Find the first alignment colon on a line. - * Ternary operators (?) are bypassed. - */ -int ASBeautifier::findObjCColonAlignment(const string& line) const -{ - bool haveTernary = false; - for (size_t i = 0; i < line.length(); i++) - { - i = line.find_first_of(":?", i); - if (i == string::npos) - break; - - if (line[i] == '?') - { - haveTernary = true; - continue; - } - if (haveTernary) - { - haveTernary = false; - continue; - } - return i; - } - return -1; -} - -/** - * Compute the spaceIndentCount necessary to align the current line colon - * with the colon position in the argument. - * If it cannot be aligned indentLength is returned and a new colon - * position is calculated. - */ -int ASBeautifier::computeObjCColonAlignment(const string& line, int colonAlignPosition) const -{ - int colonPosition = findObjCColonAlignment(line); - if (colonPosition < 0 || colonPosition > colonAlignPosition) - return indentLength; - return (colonAlignPosition - colonPosition); -} - -/* - * Compute position of the keyword following the method call object. - * This is oversimplified to find unusual method calls. - * Use for now and see what happens. - * Most programmers will probably use align-method-colon anyway. - */ -int ASBeautifier::getObjCFollowingKeyword(const string& line, int bracePos) const -{ - assert(line[bracePos] == '['); - size_t firstText = line.find_first_not_of(" \t", bracePos + 1); - if (firstText == string::npos) - return -(indentCount * indentLength - 1); - size_t searchBeg = firstText; - size_t objectEnd = 0; // end of object text - if (line[searchBeg] == '[') - { - objectEnd = line.find(']', searchBeg + 1); - if (objectEnd == string::npos) - return 0; - } - else - { - if (line[searchBeg] == '(') - { - searchBeg = line.find(')', searchBeg + 1); - if (searchBeg == string::npos) - return 0; - } - // bypass the object name - objectEnd = line.find_first_of(" \t", searchBeg + 1); - if (objectEnd == string::npos) - return 0; - --objectEnd; - } - size_t keyPos = line.find_first_not_of(" \t", objectEnd + 1); - if (keyPos == string::npos) - return 0; - return keyPos - firstText; -} - -/** - * Get a line using the current space indent with all tabs replaced by spaces. - * The indentCount is NOT included - * Needed to compute an accurate alignment. - */ -string ASBeautifier::getIndentedSpaceEquivalent(const string& line_) const -{ - string spaceIndent; - spaceIndent.append(spaceIndentCount, ' '); - string convertedLine = spaceIndent + line_; - for (size_t i = spaceIndent.length(); i < convertedLine.length(); i++) - { - if (convertedLine[i] == '\t') - { - size_t numSpaces = indentLength - (i % indentLength); - convertedLine.replace(i, 1, numSpaces, ' '); - i += indentLength - 1; - } - } - return convertedLine; -} - -/** - * Determine if an item is at a top level. - */ -bool ASBeautifier::isTopLevel() const -{ - if (headerStack->empty()) - return true; - if (headerStack->back() == &AS_OPEN_BRACE - && headerStack->size() >= 2) - { - if ((*headerStack)[headerStack->size() - 2] == &AS_NAMESPACE - || (*headerStack)[headerStack->size() - 2] == &AS_MODULE - || (*headerStack)[headerStack->size() - 2] == &AS_CLASS - || (*headerStack)[headerStack->size() - 2] == &AS_INTERFACE - || (*headerStack)[headerStack->size() - 2] == &AS_STRUCT - || (*headerStack)[headerStack->size() - 2] == &AS_UNION) - return true; - } - if (headerStack->back() == &AS_NAMESPACE - || headerStack->back() == &AS_MODULE - || headerStack->back() == &AS_CLASS - || headerStack->back() == &AS_INTERFACE - || headerStack->back() == &AS_STRUCT - || headerStack->back() == &AS_UNION) - return true; - return false; -} - -/** - * Parse the current line to update indentCount and spaceIndentCount. - */ -void ASBeautifier::parseCurrentLine(const string& line) -{ - bool isInLineComment = false; - bool isInOperator = false; - bool isSpecialChar = false; - bool haveCaseIndent = false; - bool haveAssignmentThisLine = false; - bool closingBraceReached = false; - bool previousLineProbation = (probationHeader != nullptr); - char ch = ' '; - int tabIncrementIn = 0; - if (isInQuote - && !haveLineContinuationChar - && !isInVerbatimQuote - && !isInAsm) - isInQuote = false; // missing closing quote - haveLineContinuationChar = false; - - for (size_t i = 0; i < line.length(); i++) - { - ch = line[i]; - - if (isInBeautifySQL) - continue; - - // handle special characters (i.e. backslash+character such as \n, \t, ...) - if (isInQuote && !isInVerbatimQuote) - { - if (isSpecialChar) - { - isSpecialChar = false; - continue; - } - if (line.compare(i, 2, "\\\\") == 0) - { - i++; - continue; - } - if (ch == '\\') - { - if (peekNextChar(line, i) == ' ') // is this '\' at end of line - haveLineContinuationChar = true; - else - isSpecialChar = true; - continue; - } - } - else if (isInDefine && ch == '\\') - continue; - - // bypass whitespace here - if (isWhiteSpace(ch)) - { - if (ch == '\t') - tabIncrementIn += convertTabToSpaces(i, tabIncrementIn); - continue; - } - - // handle quotes (such as 'x' and "Hello Dolly") - if (!(isInComment || isInLineComment) - && (ch == '"' - || (ch == '\'' && !isDigitSeparator(line, i)))) - { - if (!isInQuote) - { - quoteChar = ch; - isInQuote = true; - char prevCh = i > 0 ? line[i - 1] : ' '; - if (isCStyle() && prevCh == 'R') - { - int parenPos = line.find('(', i); - if (parenPos != -1) - { - isInVerbatimQuote = true; - verbatimDelimiter = line.substr(i + 1, parenPos - i - 1); - } - } - else if (isSharpStyle() && prevCh == '@') - isInVerbatimQuote = true; - // check for "C" following "extern" - else if (g_preprocessorCppExternCBrace == 2 && line.compare(i, 3, "\"C\"") == 0) - ++g_preprocessorCppExternCBrace; - } - else if (isInVerbatimQuote && ch == '"') - { - if (isCStyle()) - { - string delim = ')' + verbatimDelimiter; - int delimStart = i - delim.length(); - if (delimStart >= 0 && line.substr(delimStart, delim.length()) == delim) - { - isInQuote = false; - isInVerbatimQuote = false; - } - } - else if (isSharpStyle()) - { - if (line.compare(i, 2, "\"\"") == 0) - i++; - else - { - isInQuote = false; - isInVerbatimQuote = false; - continue; - } - } - } - else if (quoteChar == ch) - { - isInQuote = false; - isContinuation = true; - continue; - } - } - if (isInQuote) - continue; - - // handle comments - - if (!(isInComment || isInLineComment) && line.compare(i, 2, "//") == 0) - { - // if there is a 'case' statement after these comments unindent by 1 - if (isCaseHeaderCommentIndent) - --indentCount; - // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested - // if there is an 'else' after these comments a tempStacks indent is required - if (isElseHeaderIndent && lineOpensWithLineComment && !tempStacks->empty()) - indentCount += adjustIndentCountForBreakElseIfComments(); - isInLineComment = true; - i++; - continue; - } - if (!(isInComment || isInLineComment) && line.compare(i, 2, "/*") == 0) - { - // if there is a 'case' statement after these comments unindent by 1 - if (isCaseHeaderCommentIndent && lineOpensWithComment) - --indentCount; - // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested - // if there is an 'else' after these comments a tempStacks indent is required - if (isElseHeaderIndent && lineOpensWithComment && !tempStacks->empty()) - indentCount += adjustIndentCountForBreakElseIfComments(); - isInComment = true; - i++; - if (!lineOpensWithComment) // does line start with comment? - blockCommentNoIndent = true; // if no, cannot indent continuation lines - continue; - } - if ((isInComment || isInLineComment) && line.compare(i, 2, "*/") == 0) - { - size_t firstText = line.find_first_not_of(" \t"); - // if there is a 'case' statement after these comments unindent by 1 - // only if the ending comment is the first entry on the line - if (isCaseHeaderCommentIndent && firstText == i) - --indentCount; - // if this comment close starts the line, must check for else-if indent - // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested - // if there is an 'else' after these comments a tempStacks indent is required - if (firstText == i) - { - if (isElseHeaderIndent && !lineOpensWithComment && !tempStacks->empty()) - indentCount += adjustIndentCountForBreakElseIfComments(); - } - isInComment = false; - i++; - blockCommentNoIndent = false; // ok to indent next comment - continue; - } - // treat indented preprocessor lines as a line comment - if (line[0] == '#' && isIndentedPreprocessor(line, i)) - { - isInLineComment = true; - } - - if (isInLineComment) - { - // bypass rest of the comment up to the comment end - while (i + 1 < line.length()) - i++; - - continue; - } - if (isInComment) - { - // if there is a 'case' statement after these comments unindent by 1 - if (!lineOpensWithComment && isCaseHeaderCommentIndent) - --indentCount; - // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested - // if there is an 'else' after these comments a tempStacks indent is required - if (!lineOpensWithComment && isElseHeaderIndent && !tempStacks->empty()) - indentCount += adjustIndentCountForBreakElseIfComments(); - // bypass rest of the comment up to the comment end - while (i + 1 < line.length() - && line.compare(i + 1, 2, "*/") != 0) - i++; - - continue; - } - - // if we have reached this far then we are NOT in a comment or string of special character... - - if (probationHeader != nullptr) - { - if ((probationHeader == &AS_STATIC && ch == '{') - || (probationHeader == &AS_SYNCHRONIZED && ch == '(')) - { - // insert the probation header as a new header - isInHeader = true; - headerStack->emplace_back(probationHeader); - - // handle the specific probation header - isInConditional = (probationHeader == &AS_SYNCHRONIZED); - - isContinuation = false; - // if the probation comes from the previous line, then indent by 1 tab count. - if (previousLineProbation - && ch == '{' - && !(blockIndent && probationHeader == &AS_STATIC)) - { - ++indentCount; - previousLineProbationTab = true; - } - previousLineProbation = false; - } - - // dismiss the probation header - probationHeader = nullptr; - } - - prevNonSpaceCh = currentNonSpaceCh; - currentNonSpaceCh = ch; - if (!isLegalNameChar(ch) && ch != ',' && ch != ';') - { - prevNonLegalCh = currentNonLegalCh; - currentNonLegalCh = ch; - } - - if (isInHeader) - { - isInHeader = false; - currentHeader = headerStack->back(); - } - else - currentHeader = nullptr; - - if (isCStyle() && isInTemplate - && (ch == '<' || ch == '>') - && !(line.length() > i + 1 && line.compare(i, 2, ">=") == 0)) - { - if (ch == '<') - { - ++templateDepth; - continuationIndentStackSizeStack->emplace_back(continuationIndentStack->size()); - registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true); - } - else if (ch == '>') - { - popLastContinuationIndent(); - if (--templateDepth <= 0) - { - ch = ';'; - isInTemplate = false; - templateDepth = 0; - } - } - } - - // handle parentheses - if (ch == '(' || ch == '[' || ch == ')' || ch == ']') - { - if (ch == '(' || ch == '[') - { - isInOperator = false; - // if have a struct header, this is a declaration not a definition - if (ch == '(' - && !headerStack->empty() - && headerStack->back() == &AS_STRUCT) - { - headerStack->pop_back(); - isInClassHeader = false; - if (line.find(AS_STRUCT, 0) > i) // if not on this line - indentCount -= classInitializerIndents; - if (indentCount < 0) - indentCount = 0; - } - - if (parenDepth == 0) - { - // do not use emplace_back on vector until supported by macOS - parenStatementStack->push_back(isContinuation); - isContinuation = true; - } - parenDepth++; - if (ch == '[') - { - ++squareBracketCount; - if (squareBracketCount == 1 && isCStyle()) - { - isInObjCMethodCall = true; - isInObjCMethodCallFirst = true; - } - } - - continuationIndentStackSizeStack->emplace_back(continuationIndentStack->size()); - - if (currentHeader != nullptr) - registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, minConditionalIndent, true); - else if (!isInObjCMethodDefinition) - registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true); - } - else if (ch == ')' || ch == ']') - { - if (ch == ']') - --squareBracketCount; - if (squareBracketCount <= 0) - { - squareBracketCount = 0; - if (isInObjCMethodCall) - isImmediatelyPostObjCMethodCall = true; - } - foundPreCommandHeader = false; - parenDepth--; - if (parenDepth == 0) - { - if (!parenStatementStack->empty()) // in case of unmatched closing parens - { - isContinuation = parenStatementStack->back(); - parenStatementStack->pop_back(); - } - isInAsm = false; - isInConditional = false; - } - - if (!continuationIndentStackSizeStack->empty()) - { - popLastContinuationIndent(); - - if (!parenIndentStack->empty()) - { - int poppedIndent = parenIndentStack->back(); - parenIndentStack->pop_back(); - - if (i == 0) - spaceIndentCount = poppedIndent; - } - } - } - continue; - } - - if (ch == '{') - { - // first, check if '{' is a block-opener or a static-array opener - bool isBlockOpener = ((prevNonSpaceCh == '{' && braceBlockStateStack->back()) - || prevNonSpaceCh == '}' - || prevNonSpaceCh == ')' - || prevNonSpaceCh == ';' - || peekNextChar(line, i) == '{' - || isInTrailingReturnType - || foundPreCommandHeader - || foundPreCommandMacro - || isInClassHeader - || (isInClassInitializer && !isLegalNameChar(prevNonSpaceCh)) - || isNonInStatementArray - || isInObjCMethodDefinition - || isInObjCInterface - || isSharpAccessor - || isSharpDelegate - || isInExternC - || isInAsmBlock - || getNextWord(line, i) == AS_NEW - || (isInDefine - && (prevNonSpaceCh == '(' - || isLegalNameChar(prevNonSpaceCh)))); - - if (isInObjCMethodDefinition) - { - objCColonAlignSubsequent = 0; - isImmediatelyPostObjCMethodDefinition = true; - if (lineBeginsWithOpenBrace) // for run-in braces - clearObjCMethodDefinitionAlignment(); - } - - if (!isBlockOpener && !isContinuation && !isInClassInitializer && !isInEnum) - { - if (isTopLevel()) - isBlockOpener = true; - } - - if (!isBlockOpener && currentHeader != nullptr) - { - for (const string* const nonParenHeader : *nonParenHeaders) - if (currentHeader == nonParenHeader) - { - isBlockOpener = true; - break; - } - } - - // do not use emplace_back on vector until supported by macOS - braceBlockStateStack->push_back(isBlockOpener); - - if (!isBlockOpener) - { - continuationIndentStackSizeStack->emplace_back(continuationIndentStack->size()); - registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true); - parenDepth++; - if (i == 0) - shouldIndentBracedLine = false; - isInEnumTypeID = false; - - continue; - } - - // this brace is a block opener... - - ++lineOpeningBlocksNum; - - if (isInClassInitializer || isInEnumTypeID) - { - // decrease tab count if brace is broken - if (lineBeginsWithOpenBrace) - { - indentCount -= classInitializerIndents; - // decrease one more if an empty class - if (!headerStack->empty() - && (*headerStack).back() == &AS_CLASS) - { - int nextChar = getNextProgramCharDistance(line, i); - if ((int) line.length() > nextChar && line[nextChar] == '}') - --indentCount; - } - } - } - - if (isInObjCInterface) - { - isInObjCInterface = false; - if (lineBeginsWithOpenBrace) - --indentCount; - } - - if (braceIndent && !namespaceIndent && !headerStack->empty() - && ((*headerStack).back() == &AS_NAMESPACE - || (*headerStack).back() == &AS_MODULE)) - { - shouldIndentBracedLine = false; - --indentCount; - } - - // an indentable struct is treated like a class in the header stack - if (!headerStack->empty() - && (*headerStack).back() == &AS_STRUCT - && isInIndentableStruct) - (*headerStack).back() = &AS_CLASS; - - // is a brace inside a paren? - parenDepthStack->emplace_back(parenDepth); - // do not use emplace_back on vector until supported by macOS - blockStatementStack->push_back(isContinuation); - - if (!continuationIndentStack->empty()) - { - // completely purge the continuationIndentStack - while (!continuationIndentStack->empty()) - popLastContinuationIndent(); - if (isInClassInitializer || isInClassHeaderTab) - { - if (lineBeginsWithOpenBrace || lineBeginsWithComma) - spaceIndentCount = 0; - } - else - spaceIndentCount = 0; - } - - blockTabCount += (isContinuation ? 1 : 0); - if (g_preprocessorCppExternCBrace == 3) - ++g_preprocessorCppExternCBrace; - parenDepth = 0; - isInTrailingReturnType = false; - isInClassHeader = false; - isInClassHeaderTab = false; - isInClassInitializer = false; - isInEnumTypeID = false; - isContinuation = false; - isInQuestion = false; - isInLet = false; - foundPreCommandHeader = false; - foundPreCommandMacro = false; - isInExternC = false; - - tempStacks->emplace_back(new vector); - headerStack->emplace_back(&AS_OPEN_BRACE); - lastLineHeader = &AS_OPEN_BRACE; - - continue; - } // end '{' - - //check if a header has been reached - bool isPotentialHeader = isCharPotentialHeader(line, i); - - if (isPotentialHeader && squareBracketCount == 0) - { - const string* newHeader = findHeader(line, i, headers); - - // java can have a 'default' not in a switch - if (newHeader == &AS_DEFAULT - && peekNextChar(line, (i + (*newHeader).length() - 1)) != ':') - newHeader = nullptr; - // Qt headers may be variables in C++ - if (isCStyle() - && (newHeader == &AS_FOREVER || newHeader == &AS_FOREACH)) - { - if (line.find_first_of("=;", i) != string::npos) - newHeader = nullptr; - } - else if (isSharpStyle() - && (newHeader == &AS_GET || newHeader == &AS_SET)) - { - if (getNextWord(line, i + (*newHeader).length()) == "is") - newHeader = nullptr; - } - else if (newHeader == &AS_USING - && peekNextChar(line, i + (*newHeader).length() - 1) != '(') - newHeader = nullptr; - - if (newHeader != nullptr) - { - // if we reached here, then this is a header... - bool isIndentableHeader = true; - - isInHeader = true; - - vector* lastTempStack = nullptr; - if (!tempStacks->empty()) - lastTempStack = tempStacks->back(); - - // if a new block is opened, push a new stack into tempStacks to hold the - // future list of headers in the new block. - - // take care of the special case: 'else if (...)' - if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE) - { - if (!headerStack->empty()) - headerStack->pop_back(); - } - - // take care of 'else' - else if (newHeader == &AS_ELSE) - { - if (lastTempStack != nullptr) - { - int indexOfIf = indexOf(*lastTempStack, &AS_IF); - if (indexOfIf != -1) - { - // recreate the header list in headerStack up to the previous 'if' - // from the temporary snapshot stored in lastTempStack. - int restackSize = lastTempStack->size() - indexOfIf - 1; - for (int r = 0; r < restackSize; r++) - { - headerStack->emplace_back(lastTempStack->back()); - lastTempStack->pop_back(); - } - if (!closingBraceReached) - indentCount += restackSize; - } - /* - * If the above if is not true, i.e. no 'if' before the 'else', - * then nothing beautiful will come out of this... - * I should think about inserting an Exception here to notify the caller of this... - */ - } - } - - // check if 'while' closes a previous 'do' - else if (newHeader == &AS_WHILE) - { - if (lastTempStack != nullptr) - { - int indexOfDo = indexOf(*lastTempStack, &AS_DO); - if (indexOfDo != -1) - { - // recreate the header list in headerStack up to the previous 'do' - // from the temporary snapshot stored in lastTempStack. - int restackSize = lastTempStack->size() - indexOfDo - 1; - for (int r = 0; r < restackSize; r++) - { - headerStack->emplace_back(lastTempStack->back()); - lastTempStack->pop_back(); - } - if (!closingBraceReached) - indentCount += restackSize; - } - } - } - // check if 'catch' closes a previous 'try' or 'catch' - else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY) - { - if (lastTempStack != nullptr) - { - int indexOfTry = indexOf(*lastTempStack, &AS_TRY); - if (indexOfTry == -1) - indexOfTry = indexOf(*lastTempStack, &AS_CATCH); - if (indexOfTry != -1) - { - // recreate the header list in headerStack up to the previous 'try' - // from the temporary snapshot stored in lastTempStack. - int restackSize = lastTempStack->size() - indexOfTry - 1; - for (int r = 0; r < restackSize; r++) - { - headerStack->emplace_back(lastTempStack->back()); - lastTempStack->pop_back(); - } - - if (!closingBraceReached) - indentCount += restackSize; - } - } - } - else if (newHeader == &AS_CASE) - { - isInCase = true; - if (!haveCaseIndent) - { - haveCaseIndent = true; - if (!lineBeginsWithOpenBrace) - --indentCount; - } - } - else if (newHeader == &AS_DEFAULT) - { - isInCase = true; - --indentCount; - } - else if (newHeader == &AS_STATIC - || newHeader == &AS_SYNCHRONIZED) - { - if (!headerStack->empty() - && (headerStack->back() == &AS_STATIC - || headerStack->back() == &AS_SYNCHRONIZED)) - { - isIndentableHeader = false; - } - else - { - isIndentableHeader = false; - probationHeader = newHeader; - } - } - else if (newHeader == &AS_TEMPLATE) - { - isInTemplate = true; - isIndentableHeader = false; - } - - if (isIndentableHeader) - { - headerStack->emplace_back(newHeader); - isContinuation = false; - if (indexOf(*nonParenHeaders, newHeader) == -1) - { - isInConditional = true; - } - lastLineHeader = newHeader; - } - else - isInHeader = false; - - i += newHeader->length() - 1; - - continue; - } // newHeader != nullptr - - if (findHeader(line, i, preCommandHeaders) != nullptr) - // must be after function arguments - if (prevNonSpaceCh == ')') - foundPreCommandHeader = true; - - // Objective-C NSException macros are preCommandHeaders - if (isCStyle() && findKeyword(line, i, AS_NS_DURING)) - foundPreCommandMacro = true; - if (isCStyle() && findKeyword(line, i, AS_NS_HANDLER)) - foundPreCommandMacro = true; - - if (parenDepth == 0 && findKeyword(line, i, AS_ENUM)) - isInEnum = true; - - if (isSharpStyle() && findKeyword(line, i, AS_LET)) - isInLet = true; - - } // isPotentialHeader - - if (ch == '?') - isInQuestion = true; - - // special handling of colons - if (ch == ':') - { - if (line.length() > i + 1 && line[i + 1] == ':') // look for :: - { - ++i; - continue; - } - else if (isInQuestion) // NOLINT - { - // do nothing special - } - else if (parenDepth > 0) - { - // found a 'for' loop or an objective-C statement - // so do nothing special - } - else if (isInEnum) - { - // found an enum with a base-type - isInEnumTypeID = true; - if (i == 0) - indentCount += classInitializerIndents; - } - else if ((isCStyle() || isSharpStyle()) - && !isInCase - && (prevNonSpaceCh == ')' || foundPreCommandHeader)) - { - // found a 'class' c'tor initializer - isInClassInitializer = true; - registerContinuationIndentColon(line, i, tabIncrementIn); - if (i == 0) - indentCount += classInitializerIndents; - } - else if (isInClassHeader || isInObjCInterface) - { - // is in a 'class A : public B' definition - isInClassHeaderTab = true; - registerContinuationIndentColon(line, i, tabIncrementIn); - } - else if (isInAsm || isInAsmOneLine || isInAsmBlock) - { - // do nothing special - } - else if (isDigit(peekNextChar(line, i))) - { - // found a bit field - do nothing special - } - else if (isCStyle() && isInClass && prevNonSpaceCh != ')') - { - // found a 'private:' or 'public:' inside a class definition - --indentCount; - if (modifierIndent) - spaceIndentCount += (indentLength / 2); - } - else if (isCStyle() && !isInClass - && headerStack->size() >= 2 - && (*headerStack)[headerStack->size() - 2] == &AS_CLASS - && (*headerStack)[headerStack->size() - 1] == &AS_OPEN_BRACE) - { - // found a 'private:' or 'public:' inside a class definition - // and on the same line as the class opening brace - // do nothing - } - else if (isJavaStyle() && lastLineHeader == &AS_FOR) - { - // found a java for-each statement - // so do nothing special - } - else - { - currentNonSpaceCh = ';'; // so that braces after the ':' will appear as block-openers - char peekedChar = peekNextChar(line, i); - if (isInCase) - { - isInCase = false; - ch = ';'; // from here on, treat char as ';' - } - else if (isCStyle() || (isSharpStyle() && peekedChar == ';')) - { - // is in a label (e.g. 'label1:') - if (labelIndent) - --indentCount; // unindent label by one indent - else if (!lineBeginsWithOpenBrace) - indentCount = 0; // completely flush indent to left - } - } - } - - if ((ch == ';' || (parenDepth > 0 && ch == ',')) && !continuationIndentStackSizeStack->empty()) - while ((int) continuationIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0) - < (int) continuationIndentStack->size()) - continuationIndentStack->pop_back(); - - else if (ch == ',' && isInEnum && isNonInStatementArray && !continuationIndentStack->empty()) - continuationIndentStack->pop_back(); - - // handle commas - // previous "isInStatement" will be from an assignment operator or class initializer - if (ch == ',' && parenDepth == 0 && !isContinuation && !isNonInStatementArray) - { - // is comma at end of line - size_t nextChar = line.find_first_not_of(" \t", i + 1); - if (nextChar != string::npos) - { - if (line.compare(nextChar, 2, "//") == 0 - || line.compare(nextChar, 2, "/*") == 0) - nextChar = string::npos; - } - // register indent - if (nextChar == string::npos) - { - // register indent at previous word - if (isJavaStyle() && isInClassHeader) - { - // do nothing for now - } - // register indent at second word on the line - else if (!isInTemplate && !isInClassHeaderTab && !isInClassInitializer) - { - int prevWord = getContinuationIndentComma(line, i); - int continuationIndentCount = prevWord + spaceIndentCount + tabIncrementIn; - continuationIndentStack->emplace_back(continuationIndentCount); - isContinuation = true; - } - } - } - // handle comma first initializers - if (ch == ',' && parenDepth == 0 && lineBeginsWithComma - && (isInClassInitializer || isInClassHeaderTab)) - spaceIndentCount = 0; - - // handle ends of statements - if ((ch == ';' && parenDepth == 0) || ch == '}') - { - if (ch == '}') - { - // first check if this '}' closes a previous block, or a static array... - if (braceBlockStateStack->size() > 1) - { - bool braceBlockState = braceBlockStateStack->back(); - braceBlockStateStack->pop_back(); - if (!braceBlockState) - { - if (!continuationIndentStackSizeStack->empty()) - { - // this brace is a static array - popLastContinuationIndent(); - parenDepth--; - if (i == 0) - shouldIndentBracedLine = false; - - if (!parenIndentStack->empty()) - { - int poppedIndent = parenIndentStack->back(); - parenIndentStack->pop_back(); - if (i == 0) - spaceIndentCount = poppedIndent; - } - } - continue; - } - } - - // this brace is block closer... - - ++lineClosingBlocksNum; - - if (!continuationIndentStackSizeStack->empty()) - popLastContinuationIndent(); - - if (!parenDepthStack->empty()) - { - parenDepth = parenDepthStack->back(); - parenDepthStack->pop_back(); - isContinuation = blockStatementStack->back(); - blockStatementStack->pop_back(); - - if (isContinuation) - blockTabCount--; - } - - closingBraceReached = true; - if (i == 0) - spaceIndentCount = 0; - isInAsmBlock = false; - isInAsm = isInAsmOneLine = isInQuote = false; // close these just in case - - int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACE); - if (headerPlace != -1) - { - const string* popped = headerStack->back(); - while (popped != &AS_OPEN_BRACE) - { - headerStack->pop_back(); - popped = headerStack->back(); - } - headerStack->pop_back(); - - if (headerStack->empty()) - g_preprocessorCppExternCBrace = 0; - - // do not indent namespace brace unless namespaces are indented - if (!namespaceIndent && !headerStack->empty() - && ((*headerStack).back() == &AS_NAMESPACE - || (*headerStack).back() == &AS_MODULE) - && i == 0) // must be the first brace on the line - shouldIndentBracedLine = false; - - if (!tempStacks->empty()) - { - vector* temp = tempStacks->back(); - tempStacks->pop_back(); - delete temp; - } - } - - ch = ' '; // needed due to cases such as '}else{', so that headers ('else' in this case) will be identified... - } // ch == '}' - - /* - * Create a temporary snapshot of the current block's header-list in the - * uppermost inner stack in tempStacks, and clear the headerStack up to - * the beginning of the block. - * Thus, the next future statement will think it comes one indent past - * the block's '{' unless it specifically checks for a companion-header - * (such as a previous 'if' for an 'else' header) within the tempStacks, - * and recreates the temporary snapshot by manipulating the tempStacks. - */ - if (!tempStacks->back()->empty()) - while (!tempStacks->back()->empty()) - tempStacks->back()->pop_back(); - while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACE) - { - tempStacks->back()->emplace_back(headerStack->back()); - headerStack->pop_back(); - } - - if (parenDepth == 0 && ch == ';') - { - isContinuation = false; - isInClassInitializer = false; - } - - if (isInObjCMethodDefinition) - { - objCColonAlignSubsequent = 0; - isImmediatelyPostObjCMethodDefinition = true; - } - - previousLastLineHeader = nullptr; - isInClassHeader = false; // for 'friend' class - isInEnum = false; - isInEnumTypeID = false; - isInQuestion = false; - isInTemplate = false; - isInObjCInterface = false; - foundPreCommandHeader = false; - foundPreCommandMacro = false; - squareBracketCount = 0; - - continue; - } - - if (isPotentialHeader) - { - // check for preBlockStatements in C/C++ ONLY if not within parentheses - // (otherwise 'struct XXX' statements would be wrongly interpreted...) - if (!isInTemplate && !(isCStyle() && parenDepth > 0)) - { - const string* newHeader = findHeader(line, i, preBlockStatements); - // CORBA IDL module - if (newHeader == &AS_MODULE) - { - char nextChar = peekNextChar(line, i + newHeader->length() - 1); - if (prevNonSpaceCh == ')' || !isalpha(nextChar)) - newHeader = nullptr; - } - if (newHeader != nullptr - && !(isCStyle() && newHeader == &AS_CLASS && isInEnum) // is not 'enum class' - && !(isCStyle() && newHeader == &AS_INTERFACE // CORBA IDL interface - && (headerStack->empty() - || headerStack->back() != &AS_OPEN_BRACE))) - { - if (!isSharpStyle()) - headerStack->emplace_back(newHeader); - // do not need 'where' in the headerStack - // do not need second 'class' statement in a row - else if (!(newHeader == &AS_WHERE - || ((newHeader == &AS_CLASS || newHeader == &AS_STRUCT) - && !headerStack->empty() - && (headerStack->back() == &AS_CLASS - || headerStack->back() == &AS_STRUCT)))) - headerStack->emplace_back(newHeader); - - if (!headerStack->empty()) - { - if ((*headerStack).back() == &AS_CLASS - || (*headerStack).back() == &AS_STRUCT - || (*headerStack).back() == &AS_INTERFACE) - { - isInClassHeader = true; - } - else if ((*headerStack).back() == &AS_NAMESPACE - || (*headerStack).back() == &AS_MODULE) - { - // remove continuationIndent from namespace - if (!continuationIndentStack->empty()) - continuationIndentStack->pop_back(); - isContinuation = false; - } - } - - i += newHeader->length() - 1; - continue; - } - } - const string* foundIndentableHeader = findHeader(line, i, indentableHeaders); - - if (foundIndentableHeader != nullptr) - { - // must bypass the header before registering the in statement - i += foundIndentableHeader->length() - 1; - if (!isInOperator && !isInTemplate && !isNonInStatementArray) - { - registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, false); - isContinuation = true; - } - continue; - } - - if (isCStyle() && findKeyword(line, i, AS_OPERATOR)) - isInOperator = true; - - if (g_preprocessorCppExternCBrace == 1 && findKeyword(line, i, AS_EXTERN)) - ++g_preprocessorCppExternCBrace; - - if (g_preprocessorCppExternCBrace == 3) // extern "C" is not followed by a '{' - g_preprocessorCppExternCBrace = 0; - - // "new" operator is a pointer, not a calculation - if (findKeyword(line, i, AS_NEW)) - { - if (isContinuation && !continuationIndentStack->empty() && prevNonSpaceCh == '=') - continuationIndentStack->back() = 0; - } - - if (isCStyle() && findKeyword(line, i, AS_AUTO) && isTopLevel()) - { - isInTrailingReturnType = true; - } - - if (isCStyle()) - { - if (findKeyword(line, i, AS_ASM) - || findKeyword(line, i, AS__ASM__)) - { - isInAsm = true; - } - else if (findKeyword(line, i, AS_MS_ASM) // microsoft specific - || findKeyword(line, i, AS_MS__ASM)) - { - int index = 4; - if (peekNextChar(line, i) == '_') // check for __asm - index = 5; - - char peekedChar = peekNextChar(line, i + index); - if (peekedChar == '{' || peekedChar == ' ') - isInAsmBlock = true; - else - isInAsmOneLine = true; - } - } - - // bypass the entire name for all others - string name = getCurrentWord(line, i); - i += name.length() - 1; - continue; - } - - // Handle Objective-C statements - - if (ch == '@' - && line.length() > i + 1 - && !isWhiteSpace(line[i + 1]) - && isCharPotentialHeader(line, i + 1)) - { - string curWord = getCurrentWord(line, i + 1); - if (curWord == AS_INTERFACE || curWord == AS_AUTORELEASEPOOL) - { - isInObjCInterface = true; - string name = '@' + curWord; - i += name.length() - 1; - continue; - } - - if (isInObjCInterface) - { - --indentCount; - isInObjCInterface = false; - } - - if (curWord == AS_PUBLIC - || curWord == AS_PRIVATE - || curWord == AS_PROTECTED) - { - --indentCount; - if (modifierIndent) - spaceIndentCount += (indentLength / 2); - string name = '@' + curWord; - i += name.length() - 1; - continue; - } - - if (curWord == AS_END) - { - popLastContinuationIndent(); - spaceIndentCount = 0; - isInObjCMethodDefinition = false; - string name = '@' + curWord; - i += name.length() - 1; - continue; - } - } - else if ((ch == '-' || ch == '+') - && (prevNonSpaceCh == ';' || prevNonSpaceCh == '{' - || headerStack->empty() || isInObjCInterface) - && ASBase::peekNextChar(line, i) != '-' - && ASBase::peekNextChar(line, i) != '+' - && line.find_first_not_of(" \t") == i) - { - if (isInObjCInterface) - --indentCount; - isInObjCInterface = false; - isInObjCMethodDefinition = true; - continue; - } - - // Handle operators - - bool isPotentialOperator = isCharPotentialOperator(ch); - - if (isPotentialOperator) - { - // Check if an operator has been reached. - const string* foundAssignmentOp = findOperator(line, i, assignmentOperators); - const string* foundNonAssignmentOp = findOperator(line, i, nonAssignmentOperators); - - if (foundNonAssignmentOp != nullptr) - { - if (foundNonAssignmentOp == &AS_LAMBDA) - foundPreCommandHeader = true; - if (isInTemplate && foundNonAssignmentOp == &AS_GR_GR) - foundNonAssignmentOp = nullptr; - } - - // Since findHeader's boundary checking was not used above, it is possible - // that both an assignment op and a non-assignment op where found, - // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the - // found operator. - if (foundAssignmentOp != nullptr && foundNonAssignmentOp != nullptr) - { - if (foundAssignmentOp->length() < foundNonAssignmentOp->length()) - foundAssignmentOp = nullptr; - else - foundNonAssignmentOp = nullptr; - } - - if (foundNonAssignmentOp != nullptr) - { - if (foundNonAssignmentOp->length() > 1) - i += foundNonAssignmentOp->length() - 1; - - // For C++ input/output, operator<< and >> should be - // aligned, if we are not in a statement already and - // also not in the "operator<<(...)" header line - if (!isInOperator - && continuationIndentStack->empty() - && isCStyle() - && (foundNonAssignmentOp == &AS_GR_GR - || foundNonAssignmentOp == &AS_LS_LS)) - { - // this will be true if the line begins with the operator - if (i < foundNonAssignmentOp->length() && spaceIndentCount == 0) - spaceIndentCount += 2 * indentLength; - // align to the beginning column of the operator - registerContinuationIndent(line, i - foundNonAssignmentOp->length(), spaceIndentCount, tabIncrementIn, 0, false); - } - } - - else if (foundAssignmentOp != nullptr) - { - foundPreCommandHeader = false; // clears this for array assignments - foundPreCommandMacro = false; - - if (foundAssignmentOp->length() > 1) - i += foundAssignmentOp->length() - 1; - - if (!isInOperator && !isInTemplate && (!isNonInStatementArray || isInEnum)) - { - // if multiple assignments, align on the previous word - if (foundAssignmentOp == &AS_ASSIGN - && prevNonSpaceCh != ']' // an array - && statementEndsWithComma(line, i)) - { - if (!haveAssignmentThisLine) // only one assignment indent per line - { - // register indent at previous word - haveAssignmentThisLine = true; - int prevWordIndex = getContinuationIndentAssign(line, i); - int continuationIndentCount = prevWordIndex + spaceIndentCount + tabIncrementIn; - continuationIndentStack->emplace_back(continuationIndentCount); - isContinuation = true; - } - } - // don't indent an assignment if 'let' - else if (isInLet) - { - isInLet = false; - } - else if (!lineBeginsWithComma) - { - if (i == 0 && spaceIndentCount == 0) - spaceIndentCount += indentLength; - registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, false); - isContinuation = true; - } - } - } - } - } // end of for loop * end of for loop * end of for loop * end of for loop * end of for loop * -} - -} // end namespace astyle diff --git a/tools/astyle/ASEnhancer.cpp b/tools/astyle/ASEnhancer.cpp deleted file mode 100644 index be5dba42..00000000 --- a/tools/astyle/ASEnhancer.cpp +++ /dev/null @@ -1,775 +0,0 @@ -// ASEnhancer.cpp -// Copyright (c) 2018 by Jim Pattee . -// This code is licensed under the MIT License. -// License.md describes the conditions under which this software may be distributed. - -//----------------------------------------------------------------------------- -// headers -//----------------------------------------------------------------------------- - -#include "astyle.h" - -//----------------------------------------------------------------------------- -// 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, - vector* >* _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(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.length() == 0 - && !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 == 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 == 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(string& line) const -{ - // replace tab indents with spaces - for (size_t i = 0; i < line.length(); i++) - { - if (!isWhiteSpace(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(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(const string& 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(string& line, int indent) const -{ - if (line.length() == 0 - && !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(const string& line, size_t index) const -{ - string word; - size_t hits = 0; - size_t i; - for (i = index; i < line.length(); i++) - { - i = line.find_first_not_of(" \t", i); - if (i == string::npos) - return false; - if (line[i] == ';') - break; - if (!isCharPotentialHeader(line, i)) - continue; - 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(const string& line, size_t index) const -{ - string word; - size_t hits = 0; - size_t i; - for (i = index; i < line.length(); i++) - { - i = line.find_first_not_of(" \t", i); - if (i == string::npos) - return false; - if (line[i] == ';') - break; - if (!isCharPotentialHeader(line, i)) - continue; - 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(const string& 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(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 (isWhiteSpace(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 == 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 == 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) - { - 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) - { - string 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(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 (!isWhiteSpace(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) - { - string 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(string& line, int unindent) const -{ - size_t whitespace = line.find_first_not_of(" \t"); - - if (whitespace == 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 diff --git a/tools/astyle/ASFormatter.cpp b/tools/astyle/ASFormatter.cpp deleted file mode 100644 index 96c69026..00000000 --- a/tools/astyle/ASFormatter.cpp +++ /dev/null @@ -1,8367 +0,0 @@ -// ASFormatter.cpp -// Copyright (c) 2018 by Jim Pattee . -// 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 -#include - -//----------------------------------------------------------------------------- -// astyle namespace -//----------------------------------------------------------------------------- - -namespace astyle { -// -//----------------------------------------------------------------------------- -// ASFormatter class -//----------------------------------------------------------------------------- - -/** - * Constructor of ASFormatter - */ -ASFormatter::ASFormatter() -{ - sourceIterator = nullptr; - enhancer = new ASEnhancer; - preBraceHeaderStack = nullptr; - braceTypeStack = nullptr; - parenStack = nullptr; - structStack = nullptr; - questionMarkStack = nullptr; - lineCommentNoIndent = false; - formattingStyle = STYLE_NONE; - braceFormatMode = NONE_MODE; - pointerAlignment = PTR_ALIGN_NONE; - referenceAlignment = REF_SAME_AS_PTR; - objCColonPadMode = COLON_PAD_NO_CHANGE; - lineEnd = LINEEND_DEFAULT; - maxCodeLength = string::npos; - shouldPadCommas = false; - shouldPadOperators = false; - shouldPadParensOutside = false; - shouldPadFirstParen = false; - shouldPadParensInside = false; - shouldPadHeader = false; - shouldStripCommentPrefix = false; - shouldUnPadParens = false; - attachClosingBraceMode = false; - shouldBreakOneLineBlocks = true; - shouldBreakOneLineHeaders = false; - shouldBreakOneLineStatements = true; - shouldConvertTabs = false; - shouldIndentCol1Comments = false; - shouldIndentPreprocBlock = false; - shouldCloseTemplates = false; - shouldAttachExternC = false; - shouldAttachNamespace = false; - shouldAttachClass = false; - shouldAttachClosingWhile = false; - shouldAttachInline = false; - shouldBreakBlocks = false; - shouldBreakClosingHeaderBlocks = false; - shouldBreakClosingHeaderBraces = false; - shouldDeleteEmptyLines = false; - shouldDeleteMultipleEmptyLines = false; - shouldBreakReturnType = false; - shouldBreakReturnTypeDecl = false; - shouldAttachReturnType = false; - shouldAttachReturnTypeDecl = false; - shouldBreakElseIfs = false; - shouldBreakLineAfterLogical = false; - shouldAddBraces = false; - shouldAddOneLineBraces = false; - shouldRemoveBraces = false; - shouldPadMethodColon = false; - shouldPadMethodPrefix = false; - shouldUnPadMethodPrefix = false; - shouldPadReturnType = false; - shouldUnPadReturnType = false; - shouldPadParamType = false; - shouldUnPadParamType = false; - - // initialize ASFormatter member vectors - formatterFileType = 9; // reset to an invalid type - headers = new vector; - nonParenHeaders = new vector; - preDefinitionHeaders = new vector; - preCommandHeaders = new vector; - operators = new vector; - assignmentOperators = new vector; - castOperators = new vector; - - // initialize ASEnhancer member vectors - indentableMacros = new vector* >; -} - -/** - * Destructor of ASFormatter - */ -ASFormatter::~ASFormatter() -{ - // delete ASFormatter stack vectors - deleteContainer(preBraceHeaderStack); - deleteContainer(braceTypeStack); - deleteContainer(parenStack); - deleteContainer(structStack); - deleteContainer(questionMarkStack); - - // delete ASFormatter member vectors - formatterFileType = 9; // reset to an invalid type - delete headers; - delete nonParenHeaders; - delete preDefinitionHeaders; - delete preCommandHeaders; - delete operators; - delete assignmentOperators; - delete castOperators; - - // delete ASEnhancer member vectors - delete indentableMacros; - - // must be done when the ASFormatter object is deleted (not ASBeautifier) - // delete ASBeautifier member vectors - ASBeautifier::deleteBeautifierVectors(); - - delete enhancer; -} - -/** - * initialize the ASFormatter. - * - * init() should be called every time a ASFormatter object is to start - * formatting a NEW source file. - * init() receives a pointer to a ASSourceIterator object that will be - * used to iterate through the source code. - * - * @param si a pointer to the ASSourceIterator or ASStreamIterator object. - */ -void ASFormatter::init(ASSourceIterator* si) -{ - buildLanguageVectors(); - fixOptionVariableConflicts(); - ASBeautifier::init(si); - sourceIterator = si; - - enhancer->init(getFileType(), - getIndentLength(), - getTabLength(), - getIndentString() == "\t", - getForceTabIndentation(), - getNamespaceIndent(), - getCaseIndent(), - shouldIndentPreprocBlock, - getPreprocDefineIndent(), - getEmptyLineFill(), - indentableMacros); - - initContainer(preBraceHeaderStack, new vector); - initContainer(parenStack, new vector); - initContainer(structStack, new vector); - initContainer(questionMarkStack, new vector); - parenStack->emplace_back(0); // parenStack must contain this default entry - initContainer(braceTypeStack, new vector); - braceTypeStack->emplace_back(NULL_TYPE); // braceTypeStack must contain this default entry - clearFormattedLineSplitPoints(); - - currentHeader = nullptr; - currentLine = ""; - readyFormattedLine = ""; - formattedLine = ""; - verbatimDelimiter = ""; - currentChar = ' '; - previousChar = ' '; - previousCommandChar = ' '; - previousNonWSChar = ','; // not a potential name or operator - quoteChar = '"'; - preprocBlockEnd = 0; - charNum = 0; - checksumIn = 0; - checksumOut = 0; - currentLineFirstBraceNum = string::npos; - formattedLineCommentNum = 0; - leadingSpaces = 0; - previousReadyFormattedLineLength = string::npos; - preprocBraceTypeStackSize = 0; - spacePadNum = 0; - methodAttachCharNum = string::npos; - methodAttachLineNum = 0; - methodBreakCharNum = string::npos; - methodBreakLineNum = 0; - nextLineSpacePadNum = 0; - objCColonAlign = 0; - templateDepth = 0; - squareBracketCount = 0; - runInIndentChars = 0; - tabIncrementIn = 0; - previousBraceType = NULL_TYPE; - - isVirgin = true; - isInVirginLine = true; - isInLineComment = false; - isInComment = false; - isInCommentStartLine = false; - noTrimCommentContinuation = false; - isInPreprocessor = false; - isInPreprocessorDefineDef = false; - isInPreprocessorBeautify = false; - isInPreprocessorInclude = false; - doesLineStartComment = false; - lineEndsInCommentOnly = false; - lineIsCommentOnly = false; - lineIsLineCommentOnly = false; - lineIsEmpty = false; - prevLineIsEmpty = false; - isImmediatelyPostCommentOnly = false; - isImmediatelyPostEmptyLine = false; - isInClassInitializer = false; - isInQuote = false; - isInVerbatimQuote = false; - haveLineContinuationChar = false; - isInQuoteContinuation = false; - isHeaderInMultiStatementLine = false; - isSpecialChar = false; - isNonParenHeader = false; - foundNamespaceHeader = false; - foundClassHeader = false; - foundStructHeader = false; - foundInterfaceHeader = false; - foundPreDefinitionHeader = false; - foundPreCommandHeader = false; - foundPreCommandMacro = false; - foundTrailingReturnType = false; - foundCastOperator = false; - foundQuestionMark = false; - isInLineBreak = false; - endOfAsmReached = false; - endOfCodeReached = false; - isFormattingModeOff = false; - isInEnum = false; - isInExecSQL = false; - isInAsm = false; - isInAsmOneLine = false; - isInAsmBlock = false; - isLineReady = false; - elseHeaderFollowsComments = false; - caseHeaderFollowsComments = false; - isPreviousBraceBlockRelated = false; - isInPotentialCalculation = false; - needHeaderOpeningBrace = false; - shouldBreakLineAtNextChar = false; - shouldKeepLineUnbroken = false; - shouldReparseCurrentChar = false; - passedSemicolon = false; - passedColon = false; - isImmediatelyPostNonInStmt = false; - isCharImmediatelyPostNonInStmt = false; - isInTemplate = false; - isImmediatelyPostComment = false; - isImmediatelyPostLineComment = false; - isImmediatelyPostEmptyBlock = false; - isImmediatelyPostObjCMethodPrefix = false; - isImmediatelyPostPreprocessor = false; - isImmediatelyPostReturn = false; - isImmediatelyPostThrow = false; - isImmediatelyPostNewDelete = false; - isImmediatelyPostOperator = false; - isImmediatelyPostTemplate = false; - isImmediatelyPostPointerOrReference = false; - isCharImmediatelyPostReturn = false; - isCharImmediatelyPostThrow = false; - isCharImmediatelyPostNewDelete = false; - isCharImmediatelyPostOperator = false; - isCharImmediatelyPostComment = false; - isPreviousCharPostComment = false; - isCharImmediatelyPostLineComment = false; - isCharImmediatelyPostOpenBlock = false; - isCharImmediatelyPostCloseBlock = false; - isCharImmediatelyPostTemplate = false; - isCharImmediatelyPostPointerOrReference = false; - isInObjCInterface = false; - isInObjCMethodDefinition = false; - isInObjCReturnType = false; - isInObjCParam = false; - isInObjCSelector = false; - breakCurrentOneLineBlock = false; - shouldRemoveNextClosingBrace = false; - isInBraceRunIn = false; - returnTypeChecked = false; - currentLineBeginsWithBrace = false; - isPrependPostBlockEmptyLineRequested = false; - isAppendPostBlockEmptyLineRequested = false; - isIndentableProprocessor = false; - isIndentableProprocessorBlock = false; - prependEmptyLine = false; - appendOpeningBrace = false; - foundClosingHeader = false; - isImmediatelyPostHeader = false; - isInHeader = false; - isInCase = false; - isFirstPreprocConditional = false; - processedFirstConditional = false; - isJavaStaticConstructor = false; -} - -/** - * build vectors for each programing language - * depending on the file extension. - */ -void ASFormatter::buildLanguageVectors() -{ - if (getFileType() == formatterFileType) // don't build unless necessary - return; - - formatterFileType = getFileType(); - - headers->clear(); - nonParenHeaders->clear(); - preDefinitionHeaders->clear(); - preCommandHeaders->clear(); - operators->clear(); - assignmentOperators->clear(); - castOperators->clear(); - indentableMacros->clear(); // ASEnhancer - - ASResource::buildHeaders(headers, getFileType()); - ASResource::buildNonParenHeaders(nonParenHeaders, getFileType()); - ASResource::buildPreDefinitionHeaders(preDefinitionHeaders, getFileType()); - ASResource::buildPreCommandHeaders(preCommandHeaders, getFileType()); - ASResource::buildOperators(operators, getFileType()); - ASResource::buildAssignmentOperators(assignmentOperators); - ASResource::buildCastOperators(castOperators); - ASResource::buildIndentableMacros(indentableMacros); //ASEnhancer -} - -/** - * set the variables for each predefined style. - * this will override any previous settings. - */ -void ASFormatter::fixOptionVariableConflicts() -{ - if (formattingStyle == STYLE_ALLMAN) - { - setBraceFormatMode(BREAK_MODE); - } - else if (formattingStyle == STYLE_JAVA) - { - setBraceFormatMode(ATTACH_MODE); - } - else if (formattingStyle == STYLE_KR) - { - setBraceFormatMode(LINUX_MODE); - } - else if (formattingStyle == STYLE_STROUSTRUP) - { - setBraceFormatMode(LINUX_MODE); - setBreakClosingHeaderBracesMode(true); - } - else if (formattingStyle == STYLE_WHITESMITH) - { - setBraceFormatMode(BREAK_MODE); - setBraceIndent(true); - setClassIndent(true); // avoid hanging indent with access modifiers - setSwitchIndent(true); // avoid hanging indent with case statements - } - else if (formattingStyle == STYLE_VTK) - { - // the unindented class brace does NOT cause a hanging indent like Whitesmith - setBraceFormatMode(BREAK_MODE); - setBraceIndentVtk(true); // sets both braceIndent and braceIndentVtk - setSwitchIndent(true); // avoid hanging indent with case statements - } - else if (formattingStyle == STYLE_RATLIFF) - { - // attached braces can have hanging indents with the closing brace - setBraceFormatMode(ATTACH_MODE); - setBraceIndent(true); - setClassIndent(true); // avoid hanging indent with access modifiers - setSwitchIndent(true); // avoid hanging indent with case statements - } - else if (formattingStyle == STYLE_GNU) - { - setBraceFormatMode(BREAK_MODE); - setBlockIndent(true); - } - else if (formattingStyle == STYLE_LINUX) - { - setBraceFormatMode(LINUX_MODE); - // always for Linux style - setMinConditionalIndentOption(MINCOND_ONEHALF); - } - else if (formattingStyle == STYLE_HORSTMANN) - { - setBraceFormatMode(RUN_IN_MODE); - setSwitchIndent(true); - } - else if (formattingStyle == STYLE_1TBS) - { - setBraceFormatMode(LINUX_MODE); - setAddBracesMode(true); - setRemoveBracesMode(false); - } - else if (formattingStyle == STYLE_GOOGLE) - { - setBraceFormatMode(ATTACH_MODE); - setModifierIndent(true); - setClassIndent(false); - } - else if (formattingStyle == STYLE_MOZILLA) - { - setBraceFormatMode(LINUX_MODE); - } - else if (formattingStyle == STYLE_WEBKIT) - { - setBraceFormatMode(LINUX_MODE); - } - else if (formattingStyle == STYLE_PICO) - { - setBraceFormatMode(RUN_IN_MODE); - setAttachClosingBraceMode(true); - setSwitchIndent(true); - setBreakOneLineBlocksMode(false); - setBreakOneLineStatementsMode(false); - // add-braces won't work for pico, but it could be fixed if necessary - // both options should be set to true - if (shouldAddBraces) - shouldAddOneLineBraces = true; - } - else if (formattingStyle == STYLE_LISP) - { - setBraceFormatMode(ATTACH_MODE); - setAttachClosingBraceMode(true); - setBreakOneLineStatementsMode(false); - // add-one-line-braces won't work for lisp - // only shouldAddBraces should be set to true - if (shouldAddOneLineBraces) - { - shouldAddBraces = true; - shouldAddOneLineBraces = false; - } - } - setMinConditionalIndentLength(); - // if not set by indent=force-tab-x set equal to indentLength - if (getTabLength() == 0) - setDefaultTabLength(); - // add-one-line-braces implies keep-one-line-blocks - if (shouldAddOneLineBraces) - setBreakOneLineBlocksMode(false); - // don't allow add-braces and remove-braces - if (shouldAddBraces || shouldAddOneLineBraces) - setRemoveBracesMode(false); - // don't allow break-return-type and attach-return-type - if (shouldBreakReturnType) - shouldAttachReturnType = false; - if (shouldBreakReturnTypeDecl) - shouldAttachReturnTypeDecl = false; - // don't allow indent-classes and indent-modifiers - if (getClassIndent()) - setModifierIndent(false); -} - -/** - * get the next formatted line. - * - * @return formatted line. - */ -string ASFormatter::nextLine() -{ - const string* newHeader = nullptr; - isInVirginLine = isVirgin; - isCharImmediatelyPostComment = false; - isPreviousCharPostComment = false; - isCharImmediatelyPostLineComment = false; - isCharImmediatelyPostOpenBlock = false; - isCharImmediatelyPostCloseBlock = false; - isCharImmediatelyPostTemplate = false; - - while (!isLineReady) - { - if (shouldReparseCurrentChar) - shouldReparseCurrentChar = false; - else if (!getNextChar()) - { - breakLine(); - continue; - } - else // stuff to do when reading a new character... - { - // make sure that a virgin '{' at the beginning of the file will be treated as a block... - if (isInVirginLine && currentChar == '{' - && currentLineBeginsWithBrace - && previousCommandChar == ' ') - previousCommandChar = '{'; - if (isInClassInitializer - && isBraceType(braceTypeStack->back(), COMMAND_TYPE)) - isInClassInitializer = false; - if (isInBraceRunIn) - isInLineBreak = false; - if (!isWhiteSpace(currentChar)) - isInBraceRunIn = false; - isPreviousCharPostComment = isCharImmediatelyPostComment; - isCharImmediatelyPostComment = false; - isCharImmediatelyPostTemplate = false; - isCharImmediatelyPostReturn = false; - isCharImmediatelyPostThrow = false; - isCharImmediatelyPostNewDelete = false; - isCharImmediatelyPostOperator = false; - isCharImmediatelyPostPointerOrReference = false; - isCharImmediatelyPostOpenBlock = false; - isCharImmediatelyPostCloseBlock = false; - } - - if ((lineIsLineCommentOnly || lineIsCommentOnly) - && currentLine.find("*INDENT-ON*", charNum) != string::npos - && isFormattingModeOff) - { - isFormattingModeOff = false; - breakLine(); - formattedLine = currentLine; - charNum = (int) currentLine.length() - 1; - continue; - } - if (isFormattingModeOff) - { - breakLine(); - formattedLine = currentLine; - charNum = (int) currentLine.length() - 1; - continue; - } - if ((lineIsLineCommentOnly || lineIsCommentOnly) - && currentLine.find("*INDENT-OFF*", charNum) != string::npos) - { - isFormattingModeOff = true; - if (isInLineBreak) // is true if not the first line - breakLine(); - formattedLine = currentLine; - charNum = (int) currentLine.length() - 1; - continue; - } - - if (shouldBreakLineAtNextChar) - { - if (isWhiteSpace(currentChar) && !lineIsEmpty) - continue; - isInLineBreak = true; - shouldBreakLineAtNextChar = false; - } - - if (isInExecSQL && !passedSemicolon) - { - if (currentChar == ';') - passedSemicolon = true; - appendCurrentChar(); - continue; - } - - if (isInLineComment) - { - formatLineCommentBody(); - continue; - } - - if (isInComment) - { - formatCommentBody(); - continue; - } - - if (isInQuote) - { - formatQuoteBody(); - continue; - } - - // not in quote or comment or line comment - - if (isSequenceReached("//")) - { - formatLineCommentOpener(); - testForTimeToSplitFormattedLine(); - continue; - } - if (isSequenceReached("/*")) - { - formatCommentOpener(); - testForTimeToSplitFormattedLine(); - continue; - } - if (currentChar == '"' - || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum))) - { - - if (isInPreprocessor && isInPreprocessorInclude && - currentChar=='\"') { - if (previousChar!=' ' && previousChar!='\t') - appendSpacePad(); - isInPreprocessorInclude=false; - } - formatQuoteOpener(); - testForTimeToSplitFormattedLine(); - continue; - } - // treat these preprocessor statements as a line comment - if (currentChar == '#' - && currentLine.find_first_not_of(" \t") == (size_t) charNum) - { - string preproc = trim(currentLine.c_str() + charNum + 1); - if (preproc.length() > 0 - && isCharPotentialHeader(preproc, 0) - && (findKeyword(preproc, 0, "region") - || findKeyword(preproc, 0, "endregion") - || findKeyword(preproc, 0, "error") - || findKeyword(preproc, 0, "warning") - || findKeyword(preproc, 0, "line"))) - { - currentLine = rtrim(currentLine); // trim the end only - // check for run-in - if (formattedLine.length() > 0 && formattedLine[0] == '{') - { - isInLineBreak = true; - isInBraceRunIn = false; - } - if (previousCommandChar == '}') - currentHeader = nullptr; - isInLineComment = true; - appendCurrentChar(); - continue; - } - } - - if (isInPreprocessor) - { - if (isInPreprocessorInclude && - (currentChar=='<' || currentChar=='\"')) { - if (previousChar!=' ' && previousChar!='\t') - appendSpacePad(); - isInPreprocessorInclude=false; - } - - appendCurrentChar(); - continue; - } - - - if (isInTemplate && shouldCloseTemplates) - { - if (previousNonWSChar == '>' && isWhiteSpace(currentChar) && peekNextChar() == '>') - continue; - } - - if (shouldRemoveNextClosingBrace && currentChar == '}') - { - currentLine[charNum] = currentChar = ' '; - shouldRemoveNextClosingBrace = false; - assert(adjustChecksumIn(-'}')); - if (isEmptyLine(currentLine)) - continue; - } - - // handle white space - needed to simplify the rest. - if (isWhiteSpace(currentChar)) - { - appendCurrentChar(); - continue; - } - - /* not in MIDDLE of quote or comment or SQL or white-space of any type ... */ - - // check if in preprocessor - // ** isInPreprocessor will be automatically reset at the beginning - // of a new line in getnextChar() - if (currentChar == '#' - && currentLine.find_first_not_of(" \t") == (size_t) charNum - && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)) - { - isInPreprocessor = true; - // check for run-in - if (formattedLine.length() > 0 && formattedLine[0] == '{') - { - isInLineBreak = true; - isInBraceRunIn = false; - } - processPreprocessor(); - // if top level it is potentially indentable - if (shouldIndentPreprocBlock - && (isBraceType(braceTypeStack->back(), NULL_TYPE) - || isBraceType(braceTypeStack->back(), NAMESPACE_TYPE)) - && !foundClassHeader - && !isInClassInitializer - && sourceIterator->tellg() > preprocBlockEnd) - { - // indent the #if preprocessor blocks - string preproc = ASBeautifier::extractPreprocessorStatement(currentLine); - if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef - { - if (isImmediatelyPostPreprocessor) - breakLine(); - isIndentableProprocessorBlock = isIndentablePreprocessorBlock(currentLine, charNum); - isIndentableProprocessor = isIndentableProprocessorBlock; - } - } - if (isIndentableProprocessorBlock - && charNum < (int) currentLine.length() - 1 - && isWhiteSpace(currentLine[charNum + 1])) - { - size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextText != string::npos) - currentLine.erase(charNum + 1, nextText - charNum - 1); - } - if (isIndentableProprocessorBlock - && sourceIterator->tellg() >= preprocBlockEnd) - isIndentableProprocessorBlock = false; - // need to fall thru here to reset the variables - } - - /* not in preprocessor ... */ - - if (isImmediatelyPostComment) - { - caseHeaderFollowsComments = false; - isImmediatelyPostComment = false; - isCharImmediatelyPostComment = true; - } - - if (isImmediatelyPostLineComment) - { - caseHeaderFollowsComments = false; - isImmediatelyPostLineComment = false; - isCharImmediatelyPostLineComment = true; - } - - if (isImmediatelyPostReturn) - { - isImmediatelyPostReturn = false; - isCharImmediatelyPostReturn = true; - } - - if (isImmediatelyPostThrow) - { - isImmediatelyPostThrow = false; - isCharImmediatelyPostThrow = true; - } - - if (isImmediatelyPostNewDelete) - { - isImmediatelyPostNewDelete = false; - isCharImmediatelyPostNewDelete = true; - } - - if (isImmediatelyPostOperator) - { - isImmediatelyPostOperator = false; - isCharImmediatelyPostOperator = true; - } - if (isImmediatelyPostTemplate) - { - isImmediatelyPostTemplate = false; - isCharImmediatelyPostTemplate = true; - } - if (isImmediatelyPostPointerOrReference) - { - isImmediatelyPostPointerOrReference = false; - isCharImmediatelyPostPointerOrReference = true; - } - - // reset isImmediatelyPostHeader information - if (isImmediatelyPostHeader) - { - // should braces be added - if (currentChar != '{' - && shouldAddBraces - && currentChar != '#' // don't add to preprocessor - && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine) - && isOkToBreakBlock(braceTypeStack->back())) - { - bool bracesAdded = addBracesToStatement(); - if (bracesAdded && !shouldAddOneLineBraces) - { - size_t firstText = currentLine.find_first_not_of(" \t"); - assert(firstText != string::npos); - if ((int) firstText == charNum || shouldBreakOneLineHeaders) - breakCurrentOneLineBlock = true; - } - } - // should braces be removed - else if (currentChar == '{' && shouldRemoveBraces) - { - bool bracesRemoved = removeBracesFromStatement(); - if (bracesRemoved) - { - shouldRemoveNextClosingBrace = true; - if (isBeforeAnyLineEndComment(charNum)) - spacePadNum--; - else if (shouldBreakOneLineBlocks - || (currentLineBeginsWithBrace - && currentLine.find_first_not_of(" \t") != string::npos)) - shouldBreakLineAtNextChar = true; - continue; - } - } - - // break 'else-if' if shouldBreakElseIfs is requested - if (shouldBreakElseIfs - && currentHeader == &AS_ELSE - && isOkToBreakBlock(braceTypeStack->back()) - && !isBeforeAnyComment() - && (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine)) - { - string nextText = peekNextText(currentLine.substr(charNum)); - if (nextText.length() > 0 - && isCharPotentialHeader(nextText, 0) - && ASBase::findHeader(nextText, 0, headers) == &AS_IF) - { - isInLineBreak = true; - } - } - - // break a header (e.g. if, while, else) from the following statement - if (shouldBreakOneLineHeaders - && peekNextChar() != ' ' - && (shouldBreakOneLineStatements - || (!isHeaderInMultiStatementLine - && !isMultiStatementLine())) - && isOkToBreakBlock(braceTypeStack->back()) - && !isBeforeAnyComment()) - { - if (currentChar == '{') - { - if (!currentLineBeginsWithBrace) - { - if (isOneLineBlockReached(currentLine, charNum) == 3) - isInLineBreak = false; - else - breakCurrentOneLineBlock = true; - } - } - else if (currentHeader == &AS_ELSE) - { - string nextText = peekNextText(currentLine.substr(charNum), true); - if (nextText.length() > 0 - && ((isCharPotentialHeader(nextText, 0) - && ASBase::findHeader(nextText, 0, headers) != &AS_IF) - || nextText[0] == '{')) - isInLineBreak = true; - } - else - { - isInLineBreak = true; - } - } - - isImmediatelyPostHeader = false; - } - - if (passedSemicolon) // need to break the formattedLine - { - passedSemicolon = false; - if (parenStack->back() == 0 && !isCharImmediatelyPostComment && currentChar != ';') // allow ;; - { - // does a one-line block have ending comments? - if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)) - { - size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACE); - assert(blockEnd != string::npos); - // move ending comments to this formattedLine - if (isBeforeAnyLineEndComment(blockEnd)) - { - size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1); - assert(commentStart != string::npos); - assert((currentLine.compare(commentStart, 2, "//") == 0) - || (currentLine.compare(commentStart, 2, "/*") == 0)); - formattedLine.append(getIndentLength() - 1, ' '); - // append comment - int charNumSave = charNum; - charNum = commentStart; - while (charNum < (int) currentLine.length()) - { - currentChar = currentLine[charNum]; - if (currentChar == '\t' && shouldConvertTabs) - convertTabToSpaces(); - formattedLine.append(1, currentChar); - ++charNum; - } - size_t commentLength = currentLine.length() - commentStart; - currentLine.erase(commentStart, commentLength); - charNum = charNumSave; - currentChar = currentLine[charNum]; - testForTimeToSplitFormattedLine(); - } - } - isInExecSQL = false; - shouldReparseCurrentChar = true; - if (formattedLine.find_first_not_of(" \t") != string::npos) - isInLineBreak = true; - if (needHeaderOpeningBrace) - { - isCharImmediatelyPostCloseBlock = true; - needHeaderOpeningBrace = false; - } - continue; - } - } - - if (passedColon) - { - passedColon = false; - if (parenStack->back() == 0 - && !isBeforeAnyComment() - && (formattedLine.find_first_not_of(" \t") != string::npos)) - { - shouldReparseCurrentChar = true; - isInLineBreak = true; - continue; - } - } - - // Check if in template declaration, e.g. foo or foo - if (!isInTemplate && currentChar == '<') - { - checkIfTemplateOpener(); - } - - // Check for break return type - if ((size_t) charNum >= methodBreakCharNum && methodBreakLineNum == 0) - { - if ((size_t) charNum == methodBreakCharNum) - isInLineBreak = true; - methodBreakCharNum = string::npos; - methodBreakLineNum = 0; - } - // Check for attach return type - if ((size_t) charNum >= methodAttachCharNum && methodAttachLineNum == 0) - { - if ((size_t) charNum == methodAttachCharNum) - { - int pa = pointerAlignment; - int ra = referenceAlignment; - int itemAlignment = (previousNonWSChar == '*' || previousNonWSChar == '^') - ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra); - isInLineBreak = false; - if (previousNonWSChar == '*' || previousNonWSChar == '&' || previousNonWSChar == '^') - { - if (itemAlignment == REF_ALIGN_TYPE) - { - if (formattedLine.length() > 0 - && !isWhiteSpace(formattedLine[formattedLine.length() - 1])) - formattedLine.append(1, ' '); - } - else if (itemAlignment == REF_ALIGN_MIDDLE) - { - if (formattedLine.length() > 0 - && !isWhiteSpace(formattedLine[formattedLine.length() - 1])) - formattedLine.append(1, ' '); - } - else if (itemAlignment == REF_ALIGN_NAME) - { - if (formattedLine.length() > 0 - && isWhiteSpace(formattedLine[formattedLine.length() - 1])) - formattedLine.erase(formattedLine.length() - 1); - } - else - { - if (formattedLine.length() > 1 - && !isWhiteSpace(formattedLine[formattedLine.length() - 2])) - formattedLine.append(1, ' '); - } - } - else - formattedLine.append(1, ' '); - } - methodAttachCharNum = string::npos; - methodAttachLineNum = 0; - } - - // handle parens - if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<')) - { - // do not use emplace_back on vector until supported by macOS - questionMarkStack->push_back(foundQuestionMark); - foundQuestionMark = false; - parenStack->back()++; - if (currentChar == '[') - { - ++squareBracketCount; - if (getAlignMethodColon() && squareBracketCount == 1 && isCStyle()) - objCColonAlign = findObjCColonAlignment(); - } - } - else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>')) - { - foundPreCommandHeader = false; - parenStack->back()--; - // this can happen in preprocessor directives - if (parenStack->back() < 0) - parenStack->back() = 0; - if (!questionMarkStack->empty()) - { - foundQuestionMark = questionMarkStack->back(); - questionMarkStack->pop_back(); - } - if (isInTemplate && currentChar == '>') - { - templateDepth--; - if (templateDepth == 0) - { - isInTemplate = false; - isImmediatelyPostTemplate = true; - } - } - - // check if this parenthesis closes a header, e.g. if (...), while (...) - if (isInHeader && parenStack->back() == 0) - { - isInHeader = false; - isImmediatelyPostHeader = true; - foundQuestionMark = false; - } - if (currentChar == ']') - { - --squareBracketCount; - if (squareBracketCount <= 0) - { - squareBracketCount = 0; - objCColonAlign = 0; - } - } - if (currentChar == ')') - { - foundCastOperator = false; - if (parenStack->back() == 0) - endOfAsmReached = true; - } - } - - // handle braces - if (currentChar == '{' || currentChar == '}') - { - // if appendOpeningBrace this was already done for the original brace - if (currentChar == '{' && !appendOpeningBrace) - { - BraceType newBraceType = getBraceType(); - breakCurrentOneLineBlock = false; - foundNamespaceHeader = false; - foundClassHeader = false; - foundStructHeader = false; - foundInterfaceHeader = false; - foundPreDefinitionHeader = false; - foundPreCommandHeader = false; - foundPreCommandMacro = false; - foundTrailingReturnType = false; - isInPotentialCalculation = false; - isInObjCMethodDefinition = false; - isImmediatelyPostObjCMethodPrefix = false; - isInObjCInterface = false; - isInEnum = false; - isJavaStaticConstructor = false; - isCharImmediatelyPostNonInStmt = false; - needHeaderOpeningBrace = false; - shouldKeepLineUnbroken = false; - returnTypeChecked = false; - objCColonAlign = 0; - //assert(methodBreakCharNum == string::npos); // comment out - //assert(methodBreakLineNum == 0); // comment out - methodBreakCharNum = string::npos; - methodBreakLineNum = 0; - methodAttachCharNum = string::npos; - methodAttachLineNum = 0; - - isPreviousBraceBlockRelated = !isBraceType(newBraceType, ARRAY_TYPE); - braceTypeStack->emplace_back(newBraceType); - preBraceHeaderStack->emplace_back(currentHeader); - currentHeader = nullptr; - // do not use emplace_back on vector until supported by macOS - structStack->push_back(isInIndentableStruct); - if (isBraceType(newBraceType, STRUCT_TYPE) && isCStyle()) - isInIndentableStruct = isStructAccessModified(currentLine, charNum); - else - isInIndentableStruct = false; - } - - // this must be done before the braceTypeStack is popped - BraceType braceType = braceTypeStack->back(); - bool isOpeningArrayBrace = (isBraceType(braceType, ARRAY_TYPE) - && braceTypeStack->size() >= 2 - && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2], ARRAY_TYPE) - ); - - if (currentChar == '}') - { - // if a request has been made to append a post block empty line, - // but the block exists immediately before a closing brace, - // then there is no need for the post block empty line. - isAppendPostBlockEmptyLineRequested = false; - if (isInAsm) - endOfAsmReached = true; - isInAsmOneLine = isInQuote = false; - shouldKeepLineUnbroken = false; - squareBracketCount = 0; - - if (braceTypeStack->size() > 1) - { - previousBraceType = braceTypeStack->back(); - braceTypeStack->pop_back(); - isPreviousBraceBlockRelated = !isBraceType(braceType, ARRAY_TYPE); - } - else - { - previousBraceType = NULL_TYPE; - isPreviousBraceBlockRelated = false; - } - - if (!preBraceHeaderStack->empty()) - { - currentHeader = preBraceHeaderStack->back(); - preBraceHeaderStack->pop_back(); - } - else - currentHeader = nullptr; - - if (!structStack->empty()) - { - isInIndentableStruct = structStack->back(); - structStack->pop_back(); - } - else - isInIndentableStruct = false; - - if (isNonInStatementArray - && (!isBraceType(braceTypeStack->back(), ARRAY_TYPE) // check previous brace - || peekNextChar() == ';')) // check for "};" added V2.01 - isImmediatelyPostNonInStmt = true; - - if (!shouldBreakOneLineStatements - && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE) - { - // handle special case of "else" at the end of line - size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1); - if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ') - shouldBreakLineAtNextChar = true; - } - } - - // format braces - appendOpeningBrace = false; - if (isBraceType(braceType, ARRAY_TYPE)) - { - formatArrayBraces(braceType, isOpeningArrayBrace); - } - else - { - if (currentChar == '{') - formatOpeningBrace(braceType); - else - formatClosingBrace(braceType); - } - continue; - } - - if ((((previousCommandChar == '{' && isPreviousBraceBlockRelated) - || ((previousCommandChar == '}' - && !isImmediatelyPostEmptyBlock - && isPreviousBraceBlockRelated - && !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments - && peekNextChar() != ' ' - && !isBraceType(previousBraceType, DEFINITION_TYPE)) - && !isBraceType(braceTypeStack->back(), DEFINITION_TYPE))) - && isOkToBreakBlock(braceTypeStack->back())) - // check for array - || (previousCommandChar == '{' // added 9/30/2010 - && isBraceType(braceTypeStack->back(), ARRAY_TYPE) - && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE) - && isNonInStatementArray) - // check for pico one line braces - || (formattingStyle == STYLE_PICO - && (previousCommandChar == '{' && isPreviousBraceBlockRelated) - && isBraceType(braceTypeStack->back(), COMMAND_TYPE) - && isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE) - && braceFormatMode == RUN_IN_MODE) - ) - { - isCharImmediatelyPostOpenBlock = (previousCommandChar == '{'); - isCharImmediatelyPostCloseBlock = (previousCommandChar == '}'); - - if (isCharImmediatelyPostOpenBlock - && !isCharImmediatelyPostComment - && !isCharImmediatelyPostLineComment) - { - previousCommandChar = ' '; - - if (braceFormatMode == NONE_MODE) - { - if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE) - && (isBraceType(braceTypeStack->back(), BREAK_BLOCK_TYPE) - || shouldBreakOneLineBlocks)) - isInLineBreak = true; - else if (currentLineBeginsWithBrace) - formatRunIn(); - else - breakLine(); - } - else if (braceFormatMode == RUN_IN_MODE - && currentChar != '#') - formatRunIn(); - else - isInLineBreak = true; - } - else if (isCharImmediatelyPostCloseBlock - && shouldBreakOneLineStatements - && !isCharImmediatelyPostComment - && ((isLegalNameChar(currentChar) && currentChar != '.') - || currentChar == '+' - || currentChar == '-' - || currentChar == '*' - || currentChar == '&' - || currentChar == '(')) - { - previousCommandChar = ' '; - isInLineBreak = true; - } - } - - // reset block handling flags - isImmediatelyPostEmptyBlock = false; - - // Objective-C method prefix with no return type - if (isImmediatelyPostObjCMethodPrefix && currentChar != '(') - { - if (shouldPadMethodPrefix || shouldUnPadMethodPrefix) - padObjCMethodPrefix(); - isImmediatelyPostObjCMethodPrefix = false; - } - - // look for headers - bool isPotentialHeader = isCharPotentialHeader(currentLine, charNum); - - if (isPotentialHeader && !isInTemplate && squareBracketCount == 0) - { - isNonParenHeader = false; - foundClosingHeader = false; - - newHeader = findHeader(headers); - - // java can have a 'default' not in a switch - if (newHeader == &AS_DEFAULT - && ASBeautifier::peekNextChar( - currentLine, charNum + (*newHeader).length() - 1) != ':') - newHeader = nullptr; - // Qt headers may be variables in C++ - if (isCStyle() - && (newHeader == &AS_FOREVER || newHeader == &AS_FOREACH)) - { - if (currentLine.find_first_of("=;", charNum) != string::npos) - newHeader = nullptr; - } - if (isJavaStyle() - && (newHeader == &AS_SYNCHRONIZED)) - { - // want synchronized statements not synchronized methods - if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE)) - newHeader = nullptr; - } - else if (newHeader == &AS_USING - && ASBeautifier::peekNextChar( - currentLine, charNum + (*newHeader).length() - 1) != '(') - newHeader = nullptr; - - if (newHeader != nullptr) - { - foundClosingHeader = isClosingHeader(newHeader); - - if (!foundClosingHeader) - { - // these are closing headers - if ((newHeader == &AS_WHILE && currentHeader == &AS_DO) - || (newHeader == &_AS_FINALLY && currentHeader == &_AS_TRY) - || (newHeader == &_AS_EXCEPT && currentHeader == &_AS_TRY)) - foundClosingHeader = true; - // don't append empty block for these related headers - else if (isSharpStyle() - && previousNonWSChar == '}' - && ((newHeader == &AS_SET && currentHeader == &AS_GET) - || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD)) - && isOkToBreakBlock(braceTypeStack->back())) - isAppendPostBlockEmptyLineRequested = false; - } - - const string* previousHeader = currentHeader; - currentHeader = newHeader; - needHeaderOpeningBrace = true; - - // is the previous statement on the same line? - if ((previousNonWSChar == ';' || previousNonWSChar == ':') - && !isInLineBreak - && isOkToBreakBlock(braceTypeStack->back())) - { - // if breaking lines, break the line at the header - // except for multiple 'case' statements on a line - if (maxCodeLength != string::npos - && previousHeader != &AS_CASE) - isInLineBreak = true; - else - isHeaderInMultiStatementLine = true; - } - - if (foundClosingHeader && previousNonWSChar == '}') - { - if (isOkToBreakBlock(braceTypeStack->back())) - isLineBreakBeforeClosingHeader(); - - // get the adjustment for a comment following the closing header - if (isInLineBreak) - nextLineSpacePadNum = getNextLineCommentAdjustment(); - else - spacePadNum = getCurrentLineCommentAdjustment(); - } - - // check if the found header is non-paren header - isNonParenHeader = findHeader(nonParenHeaders) != nullptr; - - if (isNonParenHeader - && (currentHeader == &AS_CATCH - || currentHeader == &AS_CASE)) - { - int startChar = charNum + currentHeader->length() - 1; - if (ASBeautifier::peekNextChar(currentLine, startChar) == '(') - isNonParenHeader = false; - } - - // join 'else if' statements - if (currentHeader == &AS_IF - && previousHeader == &AS_ELSE - && isInLineBreak - && !shouldBreakElseIfs - && !isCharImmediatelyPostLineComment - && !isImmediatelyPostPreprocessor) - { - // 'else' must be last thing on the line - size_t start = formattedLine.length() >= 6 ? formattedLine.length() - 6 : 0; - if (formattedLine.find(AS_ELSE, start) != string::npos) - { - appendSpacePad(); - isInLineBreak = false; - } - } - - appendSequence(*currentHeader); - goForward(currentHeader->length() - 1); - // if a paren-header is found add a space after it, if needed - // this checks currentLine, appendSpacePad() checks formattedLine - // in 'case' and C# 'catch' can be either a paren or non-paren header - if (shouldPadHeader - && !isNonParenHeader - && charNum < (int) currentLine.length() - 1 && !isWhiteSpace(currentLine[charNum + 1])) - appendSpacePad(); - - // Signal that a header has been reached - // *** But treat a closing while() (as in do...while) - // as if it were NOT a header since a closing while() - // should never have a block after it! - if (currentHeader != &AS_CASE && currentHeader != &AS_DEFAULT - && !(foundClosingHeader && currentHeader == &AS_WHILE)) - { - isInHeader = true; - - // in C# 'catch' and 'delegate' can be a paren or non-paren header - if (isNonParenHeader && !isSharpStyleWithParen(currentHeader)) - { - isImmediatelyPostHeader = true; - isInHeader = false; - } - } - - if (shouldBreakBlocks - && isOkToBreakBlock(braceTypeStack->back()) - && !isHeaderInMultiStatementLine) - { - if (previousHeader == nullptr - && !foundClosingHeader - && !isCharImmediatelyPostOpenBlock - && !isImmediatelyPostCommentOnly) - { - isPrependPostBlockEmptyLineRequested = true; - } - - if (isClosingHeader(currentHeader) - || foundClosingHeader) - { - isPrependPostBlockEmptyLineRequested = false; - } - - if (shouldBreakClosingHeaderBlocks - && isCharImmediatelyPostCloseBlock - && !isImmediatelyPostCommentOnly - && !(currentHeader == &AS_WHILE // do-while - && foundClosingHeader)) - { - isPrependPostBlockEmptyLineRequested = true; - } - } - - if (currentHeader == &AS_CASE - || currentHeader == &AS_DEFAULT) - isInCase = true; - - continue; - } - if ((newHeader = findHeader(preDefinitionHeaders)) != nullptr - && parenStack->back() == 0 - && !isInEnum) // not C++11 enum class - { - if (newHeader == &AS_NAMESPACE || newHeader == &AS_MODULE) - foundNamespaceHeader = true; - if (newHeader == &AS_CLASS) - foundClassHeader = true; - if (newHeader == &AS_STRUCT) - foundStructHeader = true; - if (newHeader == &AS_INTERFACE && !foundNamespaceHeader && !foundClassHeader) - foundInterfaceHeader = true; - foundPreDefinitionHeader = true; - appendSequence(*newHeader); - goForward(newHeader->length() - 1); - - continue; - } - if ((newHeader = findHeader(preCommandHeaders)) != nullptr) - { - // must be after function arguments - if (previousNonWSChar == ')') - foundPreCommandHeader = true; - } - else if ((newHeader = findHeader(castOperators)) != nullptr) - { - foundCastOperator = true; - appendSequence(*newHeader); - goForward(newHeader->length() - 1); - continue; - } - } // (isPotentialHeader && !isInTemplate) - - if (isInLineBreak) // OK to break line here - { - breakLine(); - if (isInVirginLine) // adjust for the first line - { - lineCommentNoBeautify = lineCommentNoIndent; - lineCommentNoIndent = false; - if (isImmediatelyPostPreprocessor) - { - isInIndentablePreproc = isIndentableProprocessor; - isIndentableProprocessor = false; - } - } - } - - if (previousNonWSChar == '}' || currentChar == ';') - { - if (currentChar == ';') - { - squareBracketCount = 0; - //assert(methodBreakCharNum == string::npos); // comment out - //assert(methodBreakLineNum == 0); // comment out - methodBreakCharNum = string::npos; - methodBreakLineNum = 0; - methodAttachCharNum = string::npos; - methodAttachLineNum = 0; - - if (((shouldBreakOneLineStatements - || isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)) - && isOkToBreakBlock(braceTypeStack->back())) - && !(attachClosingBraceMode && peekNextChar() == '}')) - { - passedSemicolon = true; - } - else if (!shouldBreakOneLineStatements - && ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE) - { - // handle special case of "else" at the end of line - size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1); - if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ') - passedSemicolon = true; - } - - if (shouldBreakBlocks - && currentHeader != nullptr - && currentHeader != &AS_CASE - && currentHeader != &AS_DEFAULT - && !isHeaderInMultiStatementLine - && parenStack->back() == 0) - { - isAppendPostBlockEmptyLineRequested = true; - } - } - if (currentChar != ';' - || (needHeaderOpeningBrace && parenStack->back() == 0)) - currentHeader = nullptr; - - resetEndOfStatement(); - } - - if (currentChar == ':' - && previousChar != ':' // not part of '::' - && peekNextChar() != ':') // not part of '::' - { - if (isInCase) - { - isInCase = false; - if (shouldBreakOneLineStatements) - passedColon = true; - } - else if (isCStyle() // for C/C++ only - && isOkToBreakBlock(braceTypeStack->back()) - && shouldBreakOneLineStatements - && !foundQuestionMark // not in a ?: sequence - && !foundPreDefinitionHeader // not in a definition block - && previousCommandChar != ')' // not after closing paren of a method header - && !foundPreCommandHeader // not after a 'noexcept' - && squareBracketCount == 0 // not in objC method call - && !isInObjCMethodDefinition // not objC '-' or '+' method - && !isInObjCInterface // not objC @interface - && !isInObjCSelector // not objC @selector - && !isDigit(peekNextChar()) // not a bit field - && !isInEnum // not an enum with a base type - && !isInAsm // not in extended assembler - && !isInAsmOneLine // not in extended assembler - && !isInAsmBlock) // not in extended assembler - { - passedColon = true; - } - - if (isCStyle() - && (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector) - && !foundQuestionMark) // not in a ?: sequence - { - isImmediatelyPostObjCMethodPrefix = false; - isInObjCReturnType = false; - isInObjCParam = true; - if (shouldPadMethodColon) - padObjCMethodColon(); - } - - if (isInObjCInterface) - { - appendSpacePad(); - if ((int) currentLine.length() > charNum + 1 - && !isWhiteSpace(currentLine[charNum + 1])) - currentLine.insert(charNum + 1, " "); - } - - if (isClassInitializer()) - isInClassInitializer = true; - } - - if (currentChar == '?') - foundQuestionMark = true; - - if (isPotentialHeader && !isInTemplate) - { - if (findKeyword(currentLine, charNum, AS_NEW) - || findKeyword(currentLine, charNum, AS_DELETE)) - { - isInPotentialCalculation = false; - isImmediatelyPostNewDelete = true; - } - - if (findKeyword(currentLine, charNum, AS_RETURN)) - { - isInPotentialCalculation = true; - isImmediatelyPostReturn = true; // return is the same as an = sign - } - - if (findKeyword(currentLine, charNum, AS_OPERATOR)) - isImmediatelyPostOperator = true; - - if (findKeyword(currentLine, charNum, AS_ENUM)) - { - size_t firstNum = currentLine.find_first_of("(){},/"); - if (firstNum == string::npos - || currentLine[firstNum] == '{' - || currentLine[firstNum] == '/') - isInEnum = true; - } - - if (isCStyle() - && findKeyword(currentLine, charNum, AS_THROW) - && previousCommandChar != ')' - && !foundPreCommandHeader) // 'const' throw() - isImmediatelyPostThrow = true; - - if (isCStyle() && findKeyword(currentLine, charNum, AS_EXTERN) && isExternC()) - isInExternC = true; - - if (isCStyle() && findKeyword(currentLine, charNum, AS_AUTO) - && (isBraceType(braceTypeStack->back(), NULL_TYPE) - || isBraceType(braceTypeStack->back(), DEFINITION_TYPE))) - foundTrailingReturnType = true; - - // check for break/attach return type - if (shouldBreakReturnType || shouldBreakReturnTypeDecl - || shouldAttachReturnType || shouldAttachReturnTypeDecl) - { - if ((isBraceType(braceTypeStack->back(), NULL_TYPE) - || isBraceType(braceTypeStack->back(), DEFINITION_TYPE)) - && !returnTypeChecked - && !foundNamespaceHeader - && !foundClassHeader - && !isInObjCMethodDefinition - // bypass objective-C and java @ character - && charNum == (int) currentLine.find_first_not_of(" \t") - && !(isCStyle() && isCharPotentialHeader(currentLine, charNum) - && (findKeyword(currentLine, charNum, AS_PUBLIC) - || findKeyword(currentLine, charNum, AS_PRIVATE) - || findKeyword(currentLine, charNum, AS_PROTECTED)))) - { - findReturnTypeSplitPoint(currentLine); - returnTypeChecked = true; - } - } - - // Objective-C NSException macros are preCommandHeaders - if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_DURING)) - foundPreCommandMacro = true; - if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_HANDLER)) - foundPreCommandMacro = true; - - if (isCStyle() && isExecSQL(currentLine, charNum)) - isInExecSQL = true; - - if (isCStyle()) - { - if (findKeyword(currentLine, charNum, AS_ASM) - || findKeyword(currentLine, charNum, AS__ASM__)) - { - isInAsm = true; - } - else if (findKeyword(currentLine, charNum, AS_MS_ASM) // microsoft specific - || findKeyword(currentLine, charNum, AS_MS__ASM)) - { - int index = 4; - if (peekNextChar() == '_') // check for __asm - index = 5; - - char peekedChar = ASBase::peekNextChar(currentLine, charNum + index); - if (peekedChar == '{' || peekedChar == ' ') - isInAsmBlock = true; - else - isInAsmOneLine = true; - } - } - - if (isJavaStyle() - && (findKeyword(currentLine, charNum, AS_STATIC) - && isNextCharOpeningBrace(charNum + 6))) - isJavaStaticConstructor = true; - - if (isSharpStyle() - && (findKeyword(currentLine, charNum, AS_DELEGATE) - || findKeyword(currentLine, charNum, AS_UNCHECKED))) - isSharpDelegate = true; - - // append the entire name - string name = getCurrentWord(currentLine, charNum); - // must pad the 'and' and 'or' operators if required - if (name == "and" || name == "or") - { - if (shouldPadOperators && previousNonWSChar != ':') - { - appendSpacePad(); - appendOperator(name); - goForward(name.length() - 1); - if (!isBeforeAnyComment() - && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0) - && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0)) - appendSpaceAfter(); - } - else - { - appendOperator(name); - goForward(name.length() - 1); - } - } - else - { - appendSequence(name); - goForward(name.length() - 1); - } - - continue; - - } // (isPotentialHeader && !isInTemplate) - - // determine if this is an Objective-C statement - - if (currentChar == '@' - && isCStyle() - && (int) currentLine.length() > charNum + 1 - && !isWhiteSpace(currentLine[charNum + 1]) - && isCharPotentialHeader(currentLine, charNum + 1) - && findKeyword(currentLine, charNum + 1, AS_INTERFACE) - && isBraceType(braceTypeStack->back(), NULL_TYPE)) - { - isInObjCInterface = true; - string name = '@' + AS_INTERFACE; - appendSequence(name); - goForward(name.length() - 1); - continue; - } - if (currentChar == '@' - && isCStyle() - && (int) currentLine.length() > charNum + 1 - && !isWhiteSpace(currentLine[charNum + 1]) - && isCharPotentialHeader(currentLine, charNum + 1) - && findKeyword(currentLine, charNum + 1, AS_SELECTOR)) - { - isInObjCSelector = true; - string name = '@' + AS_SELECTOR; - appendSequence(name); - goForward(name.length() - 1); - continue; - } - if ((currentChar == '-' || currentChar == '+') - && isCStyle() - && (int) currentLine.find_first_not_of(" \t") == charNum - && !isInPotentialCalculation - && !isInObjCMethodDefinition - && (isBraceType(braceTypeStack->back(), NULL_TYPE) - || (isBraceType(braceTypeStack->back(), EXTERN_TYPE)))) - { - isInObjCMethodDefinition = true; - isImmediatelyPostObjCMethodPrefix = true; - isInObjCParam = false; - isInObjCInterface = false; - if (getAlignMethodColon()) - objCColonAlign = findObjCColonAlignment(); - appendCurrentChar(); - continue; - } - - // determine if this is a potential calculation - - bool isPotentialOperator = isCharPotentialOperator(currentChar); - newHeader = nullptr; - - if (isPotentialOperator) - { - newHeader = findOperator(operators); - - // check for Java ? wildcard - if (newHeader != nullptr - && newHeader == &AS_GCC_MIN_ASSIGN - && isJavaStyle() - && isInTemplate) - newHeader = nullptr; - - if (newHeader != nullptr) - { - if (newHeader == &AS_LAMBDA) - foundPreCommandHeader = true; - - // correct mistake of two >> closing a template - if (isInTemplate && (newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR)) - newHeader = &AS_GR; - - if (!isInPotentialCalculation) - { - // must determine if newHeader is an assignment operator - // do NOT use findOperator - the length must be exact!!! - if (find(begin(*assignmentOperators), end(*assignmentOperators), newHeader) - != end(*assignmentOperators)) - { - foundPreCommandHeader = false; - char peekedChar = peekNextChar(); - isInPotentialCalculation = !(newHeader == &AS_EQUAL && peekedChar == '*') - && !(newHeader == &AS_EQUAL && peekedChar == '&') - && !isCharImmediatelyPostOperator; - } - } - } - } - - // process pointers and references - // check newHeader to eliminate things like '&&' sequence - if (newHeader != nullptr && !isJavaStyle() - && (newHeader == &AS_MULT - || newHeader == &AS_BIT_AND - || newHeader == &AS_BIT_XOR - || newHeader == &AS_AND) - && isPointerOrReference()) - { - if (!isDereferenceOrAddressOf() && !isOperatorPaddingDisabled()) - formatPointerOrReference(); - else - { - appendOperator(*newHeader); - goForward(newHeader->length() - 1); - } - isImmediatelyPostPointerOrReference = true; - continue; - } - - if (shouldPadOperators && newHeader != nullptr && !isOperatorPaddingDisabled()) - { - padOperators(newHeader); - continue; - } - - // remove spaces before commas - if (currentChar == ',') - { - const size_t len = formattedLine.length(); - size_t lastText = formattedLine.find_last_not_of(' '); - if (lastText != string::npos && lastText < len - 1) - { - formattedLine.resize(lastText + 1); - int size_diff = len - (lastText + 1); - spacePadNum -= size_diff; - } - } - - // pad commas and semi-colons - if (currentChar == ';' - || (currentChar == ',' && (shouldPadOperators || shouldPadCommas))) - { - char nextChar = ' '; - if (charNum + 1 < (int) currentLine.length()) - nextChar = currentLine[charNum + 1]; - if (!isWhiteSpace(nextChar) - && nextChar != '}' - && nextChar != ')' - && nextChar != ']' - && nextChar != '>' - && nextChar != ';' - && !isBeforeAnyComment() - /* && !(isBraceType(braceTypeStack->back(), ARRAY_TYPE)) */ - ) - { - appendCurrentChar(); - appendSpaceAfter(); - continue; - } - } - - // pad parens - if (currentChar == '(' || currentChar == ')') - { - if (currentChar == '(') - { - if (shouldPadHeader - && (isCharImmediatelyPostReturn - || isCharImmediatelyPostThrow - || isCharImmediatelyPostNewDelete)) - appendSpacePad(); - } - - if (shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen) - padParens(); - else - appendCurrentChar(); - - if (isInObjCMethodDefinition) - { - if (currentChar == '(' && isImmediatelyPostObjCMethodPrefix) - { - if (shouldPadMethodPrefix || shouldUnPadMethodPrefix) - padObjCMethodPrefix(); - isImmediatelyPostObjCMethodPrefix = false; - isInObjCReturnType = true; - } - else if (currentChar == ')' && isInObjCReturnType) - { - if (shouldPadReturnType || shouldUnPadReturnType) - padObjCReturnType(); - isInObjCReturnType = false; - } - else if (isInObjCParam - && (shouldPadParamType || shouldUnPadParamType)) - padObjCParamType(); - } - continue; - } - - // bypass the entire operator - if (newHeader != nullptr) - { - appendOperator(*newHeader); - goForward(newHeader->length() - 1); - continue; - } - - appendCurrentChar(); - - } // end of while loop * end of while loop * end of while loop * end of while loop - - // return a beautified (i.e. correctly indented) line. - - string beautifiedLine; - size_t readyFormattedLineLength = trim(readyFormattedLine).length(); - bool isInNamespace = isBraceType(braceTypeStack->back(), NAMESPACE_TYPE); - - if (prependEmptyLine // prepend a blank line before this formatted line - && readyFormattedLineLength > 0 - && previousReadyFormattedLineLength > 0) - { - isLineReady = true; // signal a waiting readyFormattedLine - beautifiedLine = beautify(""); - previousReadyFormattedLineLength = 0; - // call the enhancer for new empty lines - enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL); - } - else // format the current formatted line - { - isLineReady = false; - runInIndentContinuation = runInIndentChars; - beautifiedLine = beautify(readyFormattedLine); - previousReadyFormattedLineLength = readyFormattedLineLength; - // the enhancer is not called for no-indent line comments - if (!lineCommentNoBeautify && !isFormattingModeOff) - enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL); - runInIndentChars = 0; - lineCommentNoBeautify = lineCommentNoIndent; - lineCommentNoIndent = false; - isInIndentablePreproc = isIndentableProprocessor; - isIndentableProprocessor = false; - isElseHeaderIndent = elseHeaderFollowsComments; - isCaseHeaderCommentIndent = caseHeaderFollowsComments; - objCColonAlignSubsequent = objCColonAlign; - if (isCharImmediatelyPostNonInStmt) - { - isNonInStatementArray = false; - isCharImmediatelyPostNonInStmt = false; - } - isInPreprocessorBeautify = isInPreprocessor; // used by ASEnhancer - isInBeautifySQL = isInExecSQL; // used by ASEnhancer - } - - prependEmptyLine = false; - assert(computeChecksumOut(beautifiedLine)); - return beautifiedLine; -} - -/** - * check if there are any indented lines ready to be read by nextLine() - * - * @return are there any indented lines ready? - */ -bool ASFormatter::hasMoreLines() const -{ - return !endOfCodeReached; -} - -/** - * comparison function for BraceType enum - */ -bool ASFormatter::isBraceType(BraceType a, BraceType b) const -{ - if (a == NULL_TYPE || b == NULL_TYPE) - return (a == b); - return ((a & b) == b); -} - -/** - * set the formatting style. - * - * @param style the formatting style. - */ -void ASFormatter::setFormattingStyle(FormatStyle style) -{ - formattingStyle = style; -} - -/** - * set the add braces mode. - * options: - * true braces added to headers for single line statements. - * false braces NOT added to headers for single line statements. - * - * @param state the add braces state. - */ -void ASFormatter::setAddBracesMode(bool state) -{ - shouldAddBraces = state; -} - -/** - * set the add one line braces mode. - * options: - * true one line braces added to headers for single line statements. - * false one line braces NOT added to headers for single line statements. - * - * @param state the add one line braces state. - */ -void ASFormatter::setAddOneLineBracesMode(bool state) -{ - shouldAddBraces = state; - shouldAddOneLineBraces = state; -} - -/** - * set the remove braces mode. - * options: - * true braces removed from headers for single line statements. - * false braces NOT removed from headers for single line statements. - * - * @param state the remove braces state. - */ -void ASFormatter::setRemoveBracesMode(bool state) -{ - shouldRemoveBraces = state; -} - -// retained for compatibility with release 2.06 -// "Brackets" have been changed to "Braces" in 3.0 -// it is referenced only by the old "bracket" options -void ASFormatter::setAddBracketsMode(bool state) -{ - setAddBracesMode(state); -} - -// retained for compatibility with release 2.06 -// "Brackets" have been changed to "Braces" in 3.0 -// it is referenced only by the old "bracket" options -void ASFormatter::setAddOneLineBracketsMode(bool state) -{ - setAddOneLineBracesMode(state); -} - -// retained for compatibility with release 2.06 -// "Brackets" have been changed to "Braces" in 3.0 -// it is referenced only by the old "bracket" options -void ASFormatter::setRemoveBracketsMode(bool state) -{ - setRemoveBracesMode(state); -} - -// retained for compatibility with release 2.06 -// "Brackets" have been changed to "Braces" in 3.0 -// it is referenced only by the old "bracket" options -void ASFormatter::setBreakClosingHeaderBracketsMode(bool state) -{ - setBreakClosingHeaderBracesMode(state); -} - -/** - * set the brace formatting mode. - * options: - * - * @param mode the brace formatting mode. - */ -void ASFormatter::setBraceFormatMode(BraceMode mode) -{ - braceFormatMode = mode; -} - -/** - * set 'break after' mode for maximum code length - * - * @param state the 'break after' mode. - */ -void ASFormatter::setBreakAfterMode(bool state) -{ - shouldBreakLineAfterLogical = state; -} - -/** - * set closing header brace breaking mode - * options: - * true braces just before closing headers (e.g. 'else', 'catch') - * will be broken, even if standard braces are attached. - * false closing header braces will be treated as standard braces. - * - * @param state the closing header brace breaking mode. - */ -void ASFormatter::setBreakClosingHeaderBracesMode(bool state) -{ - shouldBreakClosingHeaderBraces = state; -} - -/** - * set 'else if()' breaking mode - * options: - * true 'else' headers will be broken from their succeeding 'if' headers. - * false 'else' headers will be attached to their succeeding 'if' headers. - * - * @param state the 'else if()' breaking mode. - */ -void ASFormatter::setBreakElseIfsMode(bool state) -{ - shouldBreakElseIfs = state; -} - -/** -* set comma padding mode. -* options: -* true statement commas and semicolons will be padded with spaces around them. -* false statement commas and semicolons will not be padded. -* -* @param state the padding mode. -*/ -void ASFormatter::setCommaPaddingMode(bool state) -{ - shouldPadCommas = state; -} - -/** - * set maximum code length - * - * @param max the maximum code length. - */ -void ASFormatter::setMaxCodeLength(int max) -{ - maxCodeLength = max; -} - -/** - * set operator padding mode. - * options: - * true statement operators will be padded with spaces around them. - * false statement operators will not be padded. - * - * @param state the padding mode. - */ -void ASFormatter::setOperatorPaddingMode(bool state) -{ - shouldPadOperators = state; -} - -/** - * set parenthesis outside padding mode. - * options: - * true statement parentheses will be padded with spaces around them. - * false statement parentheses will not be padded. - * - * @param state the padding mode. - */ -void ASFormatter::setParensOutsidePaddingMode(bool state) -{ - shouldPadParensOutside = state; -} - -/** - * set parenthesis inside padding mode. - * options: - * true statement parenthesis will be padded with spaces around them. - * false statement parenthesis will not be padded. - * - * @param state the padding mode. - */ -void ASFormatter::setParensInsidePaddingMode(bool state) -{ - shouldPadParensInside = state; -} - -/** - * set padding mode before one or more open parentheses. - * options: - * true first open parenthesis will be padded with a space before. - * false first open parenthesis will not be padded. - * - * @param state the padding mode. - */ -void ASFormatter::setParensFirstPaddingMode(bool state) -{ - shouldPadFirstParen = state; -} - -/** - * set header padding mode. - * options: - * true headers will be padded with spaces around them. - * false headers will not be padded. - * - * @param state the padding mode. - */ -void ASFormatter::setParensHeaderPaddingMode(bool state) -{ - shouldPadHeader = state; -} - -/** - * set parenthesis unpadding mode. - * options: - * true statement parenthesis will be unpadded with spaces removed around them. - * false statement parenthesis will not be unpadded. - * - * @param state the padding mode. - */ -void ASFormatter::setParensUnPaddingMode(bool state) -{ - shouldUnPadParens = state; -} - -/** -* set the state of the preprocessor indentation option. -* If true, #ifdef blocks at level 0 will be indented. -* -* @param state state of option. -*/ -void ASFormatter::setPreprocBlockIndent(bool state) -{ - shouldIndentPreprocBlock = state; -} - -/** - * Set strip comment prefix mode. - * options: - * true strip leading '*' in a comment. - * false leading '*' in a comment will be left unchanged. - * - * @param state the strip comment prefix mode. - */ -void ASFormatter::setStripCommentPrefix(bool state) -{ - shouldStripCommentPrefix = state; -} - -/** - * set objective-c '-' or '+' class prefix padding mode. - * options: - * true class prefix will be padded a spaces after them. - * false class prefix will be left unchanged. - * - * @param state the padding mode. - */ -void ASFormatter::setMethodPrefixPaddingMode(bool state) -{ - shouldPadMethodPrefix = state; -} - -/** - * set objective-c '-' or '+' class prefix unpadding mode. - * options: - * true class prefix will be unpadded with spaces after them removed. - * false class prefix will left unchanged. - * - * @param state the unpadding mode. - */ -void ASFormatter::setMethodPrefixUnPaddingMode(bool state) -{ - shouldUnPadMethodPrefix = state; -} - -// set objective-c '-' or '+' return type padding mode. -void ASFormatter::setReturnTypePaddingMode(bool state) -{ - shouldPadReturnType = state; -} - -// set objective-c '-' or '+' return type unpadding mode. -void ASFormatter::setReturnTypeUnPaddingMode(bool state) -{ - shouldUnPadReturnType = state; -} - -// set objective-c method parameter type padding mode. -void ASFormatter::setParamTypePaddingMode(bool state) -{ - shouldPadParamType = state; -} - -// set objective-c method parameter type unpadding mode. -void ASFormatter::setParamTypeUnPaddingMode(bool state) -{ - shouldUnPadParamType = state; -} - -/** - * set objective-c method colon padding mode. - * - * @param mode objective-c colon padding mode. - */ -void ASFormatter::setObjCColonPaddingMode(ObjCColonPad mode) -{ - shouldPadMethodColon = true; - objCColonPadMode = mode; -} - -/** - * set option to attach closing braces - * - * @param state true = attach, false = don't attach. - */ -void ASFormatter::setAttachClosingBraceMode(bool state) -{ - attachClosingBraceMode = state; -} - -/** - * set option to attach class braces - * - * @param state true = attach, false = use style default. - */ -void ASFormatter::setAttachClass(bool state) -{ - shouldAttachClass = state; -} - -/** - * set option to attach extern "C" braces - * - * @param state true = attach, false = use style default. - */ -void ASFormatter::setAttachExternC(bool state) -{ - shouldAttachExternC = state; -} - -/** - * set option to attach namespace braces - * - * @param state true = attach, false = use style default. - */ -void ASFormatter::setAttachNamespace(bool state) -{ - shouldAttachNamespace = state; -} - -/** - * set option to attach inline braces - * - * @param state true = attach, false = use style default. - */ -void ASFormatter::setAttachInline(bool state) -{ - shouldAttachInline = state; -} - -void ASFormatter::setAttachClosingWhile(bool state) -{ - shouldAttachClosingWhile = state; -} - -/** - * set option to break/not break one-line blocks - * - * @param state true = break, false = don't break. - */ -void ASFormatter::setBreakOneLineBlocksMode(bool state) -{ - shouldBreakOneLineBlocks = state; -} - -/** -* set one line headers breaking mode -*/ -void ASFormatter::setBreakOneLineHeadersMode(bool state) -{ - shouldBreakOneLineHeaders = state; -} - -/** -* set option to break/not break lines consisting of multiple statements. -* -* @param state true = break, false = don't break. -*/ -void ASFormatter::setBreakOneLineStatementsMode(bool state) -{ - shouldBreakOneLineStatements = state; -} - -void ASFormatter::setCloseTemplatesMode(bool state) -{ - shouldCloseTemplates = state; -} - -/** - * set option to convert tabs to spaces. - * - * @param state true = convert, false = don't convert. - */ -void ASFormatter::setTabSpaceConversionMode(bool state) -{ - shouldConvertTabs = state; -} - -/** - * set option to indent comments in column 1. - * - * @param state true = indent, false = don't indent. - */ -void ASFormatter::setIndentCol1CommentsMode(bool state) -{ - shouldIndentCol1Comments = state; -} - -/** - * set option to force all line ends to a particular style. - * - * @param fmt format enum value - */ -void ASFormatter::setLineEndFormat(LineEndFormat fmt) -{ - lineEnd = fmt; -} - -/** - * set option to break unrelated blocks of code with empty lines. - * - * @param state true = convert, false = don't convert. - */ -void ASFormatter::setBreakBlocksMode(bool state) -{ - shouldBreakBlocks = state; -} - -/** - * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines. - * - * @param state true = convert, false = don't convert. - */ -void ASFormatter::setBreakClosingHeaderBlocksMode(bool state) -{ - shouldBreakClosingHeaderBlocks = state; -} - -/** - * set option to delete empty lines. - * - * @param state true = delete, false = don't delete. - */ -void ASFormatter::setDeleteEmptyLinesMode(bool state) -{ - shouldDeleteEmptyLines = state; -} - -void ASFormatter::setDeleteMultipleEmptyLinesMode(bool state) -{ - shouldDeleteMultipleEmptyLines = state; -} - - -void ASFormatter::setBreakReturnType(bool state) -{ - shouldBreakReturnType = state; -} - -void ASFormatter::setBreakReturnTypeDecl(bool state) -{ - shouldBreakReturnTypeDecl = state; -} - -void ASFormatter::setAttachReturnType(bool state) -{ - shouldAttachReturnType = state; -} - -void ASFormatter::setAttachReturnTypeDecl(bool state) -{ - shouldAttachReturnTypeDecl = state; -} - -/** - * set the pointer alignment. - * - * @param alignment the pointer alignment. - */ -void ASFormatter::setPointerAlignment(PointerAlign alignment) -{ - pointerAlignment = alignment; -} - -void ASFormatter::setReferenceAlignment(ReferenceAlign alignment) -{ - referenceAlignment = alignment; -} - -/** - * jump over several characters. - * - * @param i the number of characters to jump over. - */ -void ASFormatter::goForward(int i) -{ - while (--i >= 0) - getNextChar(); -} - -/** - * peek at the next unread character. - * - * @return the next unread character. - */ -char ASFormatter::peekNextChar() const -{ - char ch = ' '; - size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1); - - if (peekNum == string::npos) - return ch; - - ch = currentLine[peekNum]; - - return ch; -} - -/** - * check if current placement is before a comment - * - * @return is before a comment. - */ -bool ASFormatter::isBeforeComment() const -{ - bool foundComment = false; - size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1); - - if (peekNum == string::npos) - return foundComment; - - foundComment = (currentLine.compare(peekNum, 2, "/*") == 0); - - return foundComment; -} - -/** - * check if current placement is before a comment or line-comment - * - * @return is before a comment or line-comment. - */ -bool ASFormatter::isBeforeAnyComment() const -{ - bool foundComment = false; - size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1); - - if (peekNum == string::npos) - return foundComment; - - foundComment = (currentLine.compare(peekNum, 2, "/*") == 0 - || currentLine.compare(peekNum, 2, "//") == 0); - - return foundComment; -} - -/** - * check if current placement is before a comment or line-comment - * if a block comment it must be at the end of the line - * - * @return is before a comment or line-comment. - */ -bool ASFormatter::isBeforeAnyLineEndComment(int startPos) const -{ - bool foundLineEndComment = false; - size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1); - - if (peekNum != string::npos) - { - if (currentLine.compare(peekNum, 2, "//") == 0) - foundLineEndComment = true; - else if (currentLine.compare(peekNum, 2, "/*") == 0) - { - // comment must be closed on this line with nothing after it - size_t endNum = currentLine.find("*/", peekNum + 2); - if (endNum != string::npos) - { - size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2); - if (nextChar == string::npos) - foundLineEndComment = true; - } - } - } - return foundLineEndComment; -} - -/** - * check if current placement is before a comment followed by a line-comment - * - * @return is before a multiple line-end comment. - */ -bool ASFormatter::isBeforeMultipleLineEndComments(int startPos) const -{ - bool foundMultipleLineEndComment = false; - size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1); - - if (peekNum != string::npos) - { - if (currentLine.compare(peekNum, 2, "/*") == 0) - { - // comment must be closed on this line with nothing after it - size_t endNum = currentLine.find("*/", peekNum + 2); - if (endNum != string::npos) - { - size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2); - if (nextChar != string::npos - && currentLine.compare(nextChar, 2, "//") == 0) - foundMultipleLineEndComment = true; - } - } - } - return foundMultipleLineEndComment; -} - -/** - * get the next character, increasing the current placement in the process. - * the new character is inserted into the variable currentChar. - * - * @return whether succeeded to receive the new character. - */ -bool ASFormatter::getNextChar() -{ - isInLineBreak = false; - previousChar = currentChar; - - if (!isWhiteSpace(currentChar)) - { - previousNonWSChar = currentChar; - if (!isInComment && !isInLineComment && !isInQuote - && !isImmediatelyPostComment - && !isImmediatelyPostLineComment - && !isInPreprocessor - && !isSequenceReached("/*") - && !isSequenceReached("//")) - previousCommandChar = currentChar; - } - - if (charNum + 1 < (int) currentLine.length() - && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment)) - { - currentChar = currentLine[++charNum]; - - if (currentChar == '\t' && shouldConvertTabs) - convertTabToSpaces(); - - return true; - } - - // end of line has been reached - return getNextLine(); -} - -/** - * get the next line of input, increasing the current placement in the process. - * - * @param emptyLineWasDeleted an empty line was deleted. - * @return whether succeeded in reading the next line. - */ -bool ASFormatter::getNextLine(bool emptyLineWasDeleted /*false*/) -{ - if (!sourceIterator->hasMoreLines()) - { - endOfCodeReached = true; - return false; - } - if (appendOpeningBrace) - currentLine = "{"; // append brace that was removed from the previous line - else - { - currentLine = sourceIterator->nextLine(emptyLineWasDeleted); - assert(computeChecksumIn(currentLine)); - } - // reset variables for new line - inLineNumber++; - if (endOfAsmReached) - endOfAsmReached = isInAsmBlock = isInAsm = false; - shouldKeepLineUnbroken = false; - isInCommentStartLine = false; - isInCase = false; - isInAsmOneLine = false; - isHeaderInMultiStatementLine = false; - isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar; - haveLineContinuationChar = false; - isImmediatelyPostEmptyLine = lineIsEmpty; - previousChar = ' '; - - if (currentLine.length() == 0) - currentLine = string(" "); // a null is inserted if this is not done - - if (methodBreakLineNum > 0) - --methodBreakLineNum; - if (methodAttachLineNum > 0) - --methodAttachLineNum; - - // unless reading in the first line of the file, break a new line. - if (!isVirgin) - isInLineBreak = true; - else - isVirgin = false; - - if (isImmediatelyPostNonInStmt) - { - isCharImmediatelyPostNonInStmt = true; - isImmediatelyPostNonInStmt = false; - } - - // check if is in preprocessor before line trimming - // a blank line after a \ will remove the flag - isImmediatelyPostPreprocessor = isInPreprocessor; - if (!isInComment - && (previousNonWSChar != '\\' - || isEmptyLine(currentLine))) - { - isInPreprocessorInclude = false; - isInPreprocessor = false; - isInPreprocessorDefineDef = false; - } - - if (passedSemicolon) - isInExecSQL = false; - initNewLine(); - - currentChar = currentLine[charNum]; - if (isInBraceRunIn && previousNonWSChar == '{' && !isInComment) - isInLineBreak = false; - isInBraceRunIn = false; - - if (currentChar == '\t' && shouldConvertTabs) - convertTabToSpaces(); - - - - // check for an empty line. - // if yes then read the next line (calls getNextLine recursively). - // must be after initNewLine. - if (shouldDeleteEmptyLines - && lineIsEmpty - ) - { - if (!shouldBreakBlocks || previousNonWSChar == '{' || !commentAndHeaderFollows()) - { - isInPreprocessor = isImmediatelyPostPreprocessor; // restore - //lineIsEmpty = false; - return getNextLine(true); - } - } else if (shouldDeleteMultipleEmptyLines - && lineIsEmpty - && prevLineIsEmpty - ) - { - if (!shouldBreakBlocks || previousNonWSChar == '{' || !commentAndHeaderFollows()) - { - isInPreprocessor = isImmediatelyPostPreprocessor; // restore - //lineIsEmpty = false; - return getNextLine(true); - } - } - return true; -} - -/** - * jump over the leading white space in the current line, - * IF the line does not begin a comment or is in a preprocessor definition. - */ -void ASFormatter::initNewLine() -{ - size_t len = currentLine.length(); - size_t tabSize = getTabLength(); - charNum = 0; - - // don't trim these - if (isInQuoteContinuation - || (isInPreprocessor && !getPreprocDefineIndent())) - return; - - // SQL continuation lines must be adjusted so the leading spaces - // is equivalent to the opening EXEC SQL - if (isInExecSQL) - { - // replace leading tabs with spaces - // so that continuation indent will be spaces - size_t tabCount_ = 0; - size_t i; - for (i = 0; i < currentLine.length(); i++) - { - if (!isWhiteSpace(currentLine[i])) // stop at first text - break; - if (currentLine[i] == '\t') - { - size_t numSpaces = tabSize - ((tabCount_ + i) % tabSize); - currentLine.replace(i, 1, numSpaces, ' '); - tabCount_++; - i += tabSize - 1; - } - } - // this will correct the format if EXEC SQL is not a hanging indent - trimContinuationLine(); - return; - } - - // comment continuation lines must be adjusted so the leading spaces - // is equivalent to the opening comment - if (isInComment) - { - if (noTrimCommentContinuation) - leadingSpaces = tabIncrementIn = 0; - trimContinuationLine(); - return; - } - - // compute leading spaces - isImmediatelyPostCommentOnly = lineIsLineCommentOnly || lineEndsInCommentOnly; - lineIsCommentOnly = false; - lineIsLineCommentOnly = false; - lineEndsInCommentOnly = false; - doesLineStartComment = false; - currentLineBeginsWithBrace = false; - prevLineIsEmpty = lineIsEmpty; - lineIsEmpty = false; - currentLineFirstBraceNum = string::npos; - tabIncrementIn = 0; - - // bypass whitespace at the start of a line - // preprocessor tabs are replaced later in the program - for (charNum = 0; isWhiteSpace(currentLine[charNum]) && charNum + 1 < (int) len; charNum++) - { - if (currentLine[charNum] == '\t' - && (!isInPreprocessor || isInPreprocessorDefineDef)) - tabIncrementIn += tabSize - 1 - ((tabIncrementIn + charNum) % tabSize); - } - leadingSpaces = charNum + tabIncrementIn; - - if (isSequenceReached("/*")) - { - doesLineStartComment = true; - if ((int) currentLine.length() > charNum + 2 - && currentLine.find("*/", charNum + 2) != string::npos) - lineIsCommentOnly = true; - } - else if (isSequenceReached("//")) - { - lineIsLineCommentOnly = true; - } - else if (isSequenceReached("{")) - { - currentLineBeginsWithBrace = true; - currentLineFirstBraceNum = charNum; - size_t firstText = currentLine.find_first_not_of(" \t", charNum + 1); - if (firstText != string::npos) - { - if (currentLine.compare(firstText, 2, "//") == 0) - lineIsLineCommentOnly = true; - else if (currentLine.compare(firstText, 2, "/*") == 0 - || isExecSQL(currentLine, firstText)) - { - // get the extra adjustment - size_t j; - for (j = charNum + 1; j < firstText && isWhiteSpace(currentLine[j]); j++) - { - if (currentLine[j] == '\t') - tabIncrementIn += tabSize - 1 - ((tabIncrementIn + j) % tabSize); - } - leadingSpaces = j + tabIncrementIn; - if (currentLine.compare(firstText, 2, "/*") == 0) - doesLineStartComment = true; - } - } - } - else if (isWhiteSpace(currentLine[charNum]) && !(charNum + 1 < (int) currentLine.length())) - { - lineIsEmpty = true; - } - - // do not trim indented preprocessor define (except for comment continuation lines) - if (isInPreprocessor) - { - if (!doesLineStartComment) - leadingSpaces = 0; - charNum = 0; - } -} - -/** - * Append a character to the current formatted line. - * The formattedLine split points are updated. - * - * @param ch the character to append. - * @param canBreakLine if true, a registered line-break - */ -void ASFormatter::appendChar(char ch, bool canBreakLine) -{ - if (canBreakLine && isInLineBreak) - breakLine(); - - formattedLine.append(1, ch); - isImmediatelyPostCommentOnly = false; - if (maxCodeLength != string::npos) - { - // These compares reduce the frequency of function calls. - if (isOkToSplitFormattedLine()) - updateFormattedLineSplitPoints(ch); - if (formattedLine.length() > maxCodeLength) - testForTimeToSplitFormattedLine(); - } -} - -/** - * Append a string sequence to the current formatted line. - * The formattedLine split points are NOT updated. - * But the formattedLine is checked for time to split. - * - * @param sequence the sequence to append. - * @param canBreakLine if true, a registered line-break - */ -void ASFormatter::appendSequence(const string& sequence, bool canBreakLine) -{ - if (canBreakLine && isInLineBreak) - breakLine(); - formattedLine.append(sequence); - if (formattedLine.length() > maxCodeLength) - testForTimeToSplitFormattedLine(); -} - -/** - * Append an operator sequence to the current formatted line. - * The formattedLine split points are updated. - * - * @param sequence the sequence to append. - * @param canBreakLine if true, a registered line-break - */ -void ASFormatter::appendOperator(const string& sequence, bool canBreakLine) -{ - if (canBreakLine && isInLineBreak) - breakLine(); - formattedLine.append(sequence); - if (maxCodeLength != string::npos) - { - // These compares reduce the frequency of function calls. - if (isOkToSplitFormattedLine()) - updateFormattedLineSplitPointsOperator(sequence); - if (formattedLine.length() > maxCodeLength) - testForTimeToSplitFormattedLine(); - } -} - -/** - * append a space to the current formattedline, UNLESS the - * last character is already a white-space character. - */ -void ASFormatter::appendSpacePad() -{ - int len = formattedLine.length(); - if (len > 0 && !isWhiteSpace(formattedLine[len - 1])) - { - formattedLine.append(1, ' '); - spacePadNum++; - if (maxCodeLength != string::npos) - { - // These compares reduce the frequency of function calls. - if (isOkToSplitFormattedLine()) - updateFormattedLineSplitPoints(' '); - if (formattedLine.length() > maxCodeLength) - testForTimeToSplitFormattedLine(); - } - } -} - -/** - * append a space to the current formattedline, UNLESS the - * next character is already a white-space character. - */ -void ASFormatter::appendSpaceAfter() -{ - int len = currentLine.length(); - if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum + 1])) - { - formattedLine.append(1, ' '); - spacePadNum++; - if (maxCodeLength != string::npos) - { - // These compares reduce the frequency of function calls. - if (isOkToSplitFormattedLine()) - updateFormattedLineSplitPoints(' '); - if (formattedLine.length() > maxCodeLength) - testForTimeToSplitFormattedLine(); - } - } -} - -/** - * register a line break for the formatted line. - */ -void ASFormatter::breakLine(bool isSplitLine /*false*/) -{ - isLineReady = true; - isInLineBreak = false; - spacePadNum = nextLineSpacePadNum; - nextLineSpacePadNum = 0; - readyFormattedLine = formattedLine; - formattedLine.erase(); - // queue an empty line prepend request if one exists - prependEmptyLine = isPrependPostBlockEmptyLineRequested; - - if (!isSplitLine) - { - formattedLineCommentNum = string::npos; - clearFormattedLineSplitPoints(); - - if (isAppendPostBlockEmptyLineRequested) - { - isAppendPostBlockEmptyLineRequested = false; - isPrependPostBlockEmptyLineRequested = true; - } - else - isPrependPostBlockEmptyLineRequested = false; - } -} - -/** - * check if the currently reached open-brace (i.e. '{') - * opens a: - * - a definition type block (such as a class or namespace), - * - a command block (such as a method block) - * - a static array - * this method takes for granted that the current character - * is an opening brace. - * - * @return the type of the opened block. - */ -BraceType ASFormatter::getBraceType() -{ - assert(currentChar == '{'); - - BraceType returnVal = NULL_TYPE; - - if ((previousNonWSChar == '=' - || isBraceType(braceTypeStack->back(), ARRAY_TYPE)) - && previousCommandChar != ')' - && !isNonParenHeader) - returnVal = ARRAY_TYPE; - else if (foundPreDefinitionHeader && previousCommandChar != ')') - { - returnVal = DEFINITION_TYPE; - if (foundNamespaceHeader) - returnVal = (BraceType)(returnVal | NAMESPACE_TYPE); - else if (foundClassHeader) - returnVal = (BraceType)(returnVal | CLASS_TYPE); - else if (foundStructHeader) - returnVal = (BraceType)(returnVal | STRUCT_TYPE); - else if (foundInterfaceHeader) - returnVal = (BraceType)(returnVal | INTERFACE_TYPE); - } - else if (isInEnum) - { - returnVal = (BraceType)(ARRAY_TYPE | ENUM_TYPE); - } - else - { - bool isCommandType = (foundPreCommandHeader - || foundPreCommandMacro - || (currentHeader != nullptr && isNonParenHeader) - || (previousCommandChar == ')') - || (previousCommandChar == ':' && !foundQuestionMark) - || (previousCommandChar == ';') - || ((previousCommandChar == '{' || previousCommandChar == '}') - && isPreviousBraceBlockRelated) - || (isInClassInitializer - && ((!isLegalNameChar(previousNonWSChar) && previousNonWSChar != '(') - || foundPreCommandHeader)) - || foundTrailingReturnType - || isInObjCMethodDefinition - || isInObjCInterface - || isJavaStaticConstructor - || isSharpDelegate); - - // C# methods containing 'get', 'set', 'add', and 'remove' do NOT end with parens - if (!isCommandType && isSharpStyle() && isNextWordSharpNonParenHeader(charNum + 1)) - { - isCommandType = true; - isSharpAccessor = true; - } - - if (isInExternC) - returnVal = (isCommandType ? COMMAND_TYPE : EXTERN_TYPE); - else - returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE); - } - - int foundOneLineBlock = isOneLineBlockReached(currentLine, charNum); - - if (foundOneLineBlock == 2 && returnVal == COMMAND_TYPE) - returnVal = ARRAY_TYPE; - - if (foundOneLineBlock > 0) - { - returnVal = (BraceType) (returnVal | SINGLE_LINE_TYPE); - if (breakCurrentOneLineBlock) - returnVal = (BraceType) (returnVal | BREAK_BLOCK_TYPE); - if (foundOneLineBlock == 3) - returnVal = (BraceType)(returnVal | EMPTY_BLOCK_TYPE); - } - - if (isBraceType(returnVal, ARRAY_TYPE)) - { - if (isNonInStatementArrayBrace()) - { - returnVal = (BraceType)(returnVal | ARRAY_NIS_TYPE); - isNonInStatementArray = true; - isImmediatelyPostNonInStmt = false; // in case of "},{" - nonInStatementBrace = formattedLine.length() - 1; - } - if (isUniformInitializerBrace()) - returnVal = (BraceType)(returnVal | INIT_TYPE); - } - - return returnVal; -} - -bool ASFormatter::isNumericVariable(const string& word) const -{ - if (word == "bool" - || word == "int" - || word == "void" - || word == "char" - || word == "long" - || word == "short" - || word == "double" - || word == "float" - || (word.length() >= 4 // check end of word for _t - && word.compare(word.length() - 2, 2, "_t") == 0) -// removed release 3.1 -// || word == "Int32" -// || word == "UInt32" -// || word == "Int64" -// || word == "UInt64" - || word == "BOOL" - || word == "DWORD" - || word == "HWND" - || word == "INT" - || word == "LPSTR" - || word == "VOID" - || word == "LPVOID" - || word == "wxFontEncoding" - ) - return true; - return false; -} - -/** -* check if a colon is a class initializer separator -* -* @return whether it is a class initializer separator -*/ -bool ASFormatter::isClassInitializer() const -{ - assert(currentChar == ':'); - assert(previousChar != ':' && peekNextChar() != ':'); // not part of '::' - - // this should be similar to ASBeautifier::parseCurrentLine() - bool foundClassInitializer = false; - - if (foundQuestionMark) - { - // do nothing special - } - else if (parenStack->back() > 0) - { - // found a 'for' loop or an objective-C statement - // so do nothing special - } - else if (isInEnum) - { - // found an enum with a base-type - } - else if (isCStyle() - && !isInCase - && (previousCommandChar == ')' || foundPreCommandHeader)) - { - // found a 'class' c'tor initializer - foundClassInitializer = true; - } - return foundClassInitializer; -} - -/** - * check if a line is empty - * - * @return whether line is empty - */ -bool ASFormatter::isEmptyLine(const string& line) const -{ - return line.find_first_not_of(" \t") == string::npos; -} - -/** - * Check if the following text is "C" as in extern "C". - * - * @return whether the statement is extern "C" - */ -bool ASFormatter::isExternC() const -{ - // charNum should be at 'extern' - assert(!isWhiteSpace(currentLine[charNum])); - size_t startQuote = currentLine.find_first_of(" \t\"", charNum); - if (startQuote == string::npos) - return false; - startQuote = currentLine.find_first_not_of(" \t", startQuote); - if (startQuote == string::npos) - return false; - if (currentLine.compare(startQuote, 3, "\"C\"") != 0) - return false; - return true; -} - -/** - * Check if the currently reached '*', '&' or '^' character is - * a pointer-or-reference symbol, or another operator. - * A pointer dereference (*) or an "address of" character (&) - * counts as a pointer or reference because it is not an - * arithmetic operator. - * - * @return whether current character is a reference-or-pointer - */ -bool ASFormatter::isPointerOrReference() const -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - - if (isJavaStyle()) - return false; - - if (isCharImmediatelyPostOperator) - return false; - - // get the last legal word (may be a number) - string lastWord = getPreviousWord(currentLine, charNum); - if (lastWord.empty()) - lastWord = " "; - - // check for preceding or following numeric values - string nextText = peekNextText(currentLine.substr(charNum + 1)); - if (nextText.length() == 0) - nextText = " "; - if (isDigit(lastWord[0]) - || isDigit(nextText[0]) - || nextText[0] == '!' - || nextText[0] == '~') - return false; - - // check for multiply then a dereference (a * *b) - char nextChar = peekNextChar(); - if (currentChar == '*' - && nextChar == '*' - && !isPointerToPointer(currentLine, charNum)) - return false; - - if ((foundCastOperator && nextChar == '>') - || isPointerOrReferenceVariable(lastWord)) - return true; - - if (isInClassInitializer - && previousNonWSChar != '(' - && previousNonWSChar != '{' - && previousCommandChar != ',' - && nextChar != ')' - && nextChar != '}') - return false; - - //check for rvalue reference - if (currentChar == '&' && nextChar == '&') - { - if (lastWord == AS_AUTO) - return true; - if (previousNonWSChar == '>') - return true; - string followingText; - if ((int) currentLine.length() > charNum + 2) - followingText = peekNextText(currentLine.substr(charNum + 2)); - if (followingText.length() > 0 && followingText[0] == ')') - return true; - if (currentHeader != nullptr || isInPotentialCalculation) - return false; - if (parenStack->back() > 0 && isBraceType(braceTypeStack->back(), COMMAND_TYPE)) - return false; - return true; - } - if (nextChar == '*' - || previousNonWSChar == '=' - || previousNonWSChar == '(' - || previousNonWSChar == '[' - || isCharImmediatelyPostReturn - || isInTemplate - || isCharImmediatelyPostTemplate - || currentHeader == &AS_CATCH - || currentHeader == &AS_FOREACH - || currentHeader == &AS_QFOREACH) - return true; - - if (isBraceType(braceTypeStack->back(), ARRAY_TYPE) - && isLegalNameChar(lastWord[0]) - && isLegalNameChar(nextChar) - && previousNonWSChar != ')') - { - if (isArrayOperator()) - return false; - } - - // checks on operators in parens - if (parenStack->back() > 0 - && isLegalNameChar(lastWord[0]) - && isLegalNameChar(nextChar)) - { - // if followed by an assignment it is a pointer or reference - // if followed by semicolon it is a pointer or reference in range-based for - const string* followingOperator = getFollowingOperator(); - if (followingOperator != nullptr - && followingOperator != &AS_MULT - && followingOperator != &AS_BIT_AND) - { - if (followingOperator == &AS_ASSIGN || followingOperator == &AS_COLON) - return true; - return false; - } - - if (isBraceType(braceTypeStack->back(), COMMAND_TYPE) - || squareBracketCount > 0) - return false; - return true; - } - - // checks on operators in parens with following '(' - if (parenStack->back() > 0 - && nextChar == '(' - && previousNonWSChar != ',' - && previousNonWSChar != '(' - && previousNonWSChar != '!' - && previousNonWSChar != '&' - && previousNonWSChar != '*' - && previousNonWSChar != '|') - return false; - - if (nextChar == '-' - || nextChar == '+') - { - size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextNum != string::npos) - { - if (currentLine.compare(nextNum, 2, "++") != 0 - && currentLine.compare(nextNum, 2, "--") != 0) - return false; - } - } - - bool isPR = (!isInPotentialCalculation - || (!isLegalNameChar(previousNonWSChar) - && !(previousNonWSChar == ')' && nextChar == '(') - && !(previousNonWSChar == ')' && currentChar == '*' && !isImmediatelyPostCast()) - && previousNonWSChar != ']') - || (!isWhiteSpace(nextChar) - && nextChar != '-' - && nextChar != '(' - && nextChar != '[' - && !isLegalNameChar(nextChar)) - ); - - return isPR; -} - -/** - * Check if the currently reached '*' or '&' character is - * a dereferenced pointer or "address of" symbol. - * NOTE: this MUST be a pointer or reference as determined by - * the function isPointerOrReference(). - * - * @return whether current character is a dereference or address of - */ -bool ASFormatter::isDereferenceOrAddressOf() const -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - - if (isCharImmediatelyPostTemplate) - return false; - - if (previousNonWSChar == '=' - || previousNonWSChar == ',' - || previousNonWSChar == '.' - || previousNonWSChar == '{' - || previousNonWSChar == '>' - || previousNonWSChar == '<' - || previousNonWSChar == '?' - || isCharImmediatelyPostLineComment - || isCharImmediatelyPostComment - || isCharImmediatelyPostReturn) - return true; - - char nextChar = peekNextChar(); - if (currentChar == '*' && nextChar == '*') - { - if (previousNonWSChar == '(') - return true; - if ((int) currentLine.length() < charNum + 2) - return true; - return false; - } - if (currentChar == '&' && nextChar == '&') - { - if (previousNonWSChar == '(' || isInTemplate) - return true; - if ((int) currentLine.length() < charNum + 2) - return true; - return false; - } - - // check first char on the line - if (charNum == (int) currentLine.find_first_not_of(" \t") - && (isBraceType(braceTypeStack->back(), COMMAND_TYPE) - || parenStack->back() != 0)) - return true; - - string nextText = peekNextText(currentLine.substr(charNum + 1)); - if (nextText.length() > 0) - { - if (nextText[0] == ')' || nextText[0] == '>' - || nextText[0] == ',' || nextText[0] == '=') - return false; - if (nextText[0] == ';') - return true; - } - - // check for reference to a pointer *& - if ((currentChar == '*' && nextChar == '&') - || (previousNonWSChar == '*' && currentChar == '&')) - return false; - - if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE) - && parenStack->back() == 0) - return false; - - string lastWord = getPreviousWord(currentLine, charNum); - if (lastWord == "else" || lastWord == "delete") - return true; - - if (isPointerOrReferenceVariable(lastWord)) - return false; - - bool isDA = (!(isLegalNameChar(previousNonWSChar) || previousNonWSChar == '>') - || (nextText.length() > 0 && !isLegalNameChar(nextText[0]) && nextText[0] != '/') - || (ispunct((unsigned char)previousNonWSChar) && previousNonWSChar != '.') - || isCharImmediatelyPostReturn); - - return isDA; -} - -/** - * Check if the currently reached '*' or '&' character is - * centered with one space on each side. - * Only spaces are checked, not tabs. - * If true then a space will be deleted on the output. - * - * @return whether current character is centered. - */ -bool ASFormatter::isPointerOrReferenceCentered() const -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - - int prNum = charNum; - int lineLength = (int) currentLine.length(); - - // check for end of line - if (peekNextChar() == ' ') - return false; - - // check space before - if (prNum < 1 - || currentLine[prNum - 1] != ' ') - return false; - - // check no space before that - if (prNum < 2 - || currentLine[prNum - 2] == ' ') - return false; - - // check for ** or && - if (prNum + 1 < lineLength - && (currentLine[prNum + 1] == '*' || currentLine[prNum + 1] == '&')) - prNum++; - - // check space after - if (prNum + 1 <= lineLength - && currentLine[prNum + 1] != ' ') - return false; - - // check no space after that - if (prNum + 2 < lineLength - && currentLine[prNum + 2] == ' ') - return false; - - return true; -} - -/** - * Check if a word is a pointer or reference variable type. - * - * @return whether word is a pointer or reference variable. - */ -bool ASFormatter::isPointerOrReferenceVariable(const string& word) const -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - bool retval = false; - if (word == "char" - || word == "string" - || word == "String" - || word == "NSString" - || word == "int" - || word == "void" - || (word.length() >= 6 // check end of word for _t - && word.compare(word.length() - 2, 2, "_t") == 0) - || word == "INT" - || word == "VOID") - retval = true; - // check for C# object type "x is string" - if (retval && isSharpStyle()) - { - // find the word previous to the 'word' parameter - string prevWord; - size_t wordStart = currentLine.rfind(word, charNum); - if (wordStart != string::npos) - prevWord = getPreviousWord(currentLine, wordStart); - if (prevWord == "is") - retval = false; - } - return retval; -} - -/** - * Check if * * is a pointer to a pointer or a multiply then a dereference. - * - * @return true if a pointer *. - */ -bool ASFormatter::isPointerToPointer(const string& line, int currPos) const -{ - assert(line[currPos] == '*' && peekNextChar() == '*'); - if ((int) line.length() > currPos + 1 && line[currPos + 1] == '*') - return true; - size_t nextText = line.find_first_not_of(" \t", currPos + 1); - if (nextText == string::npos || line[nextText] != '*') - return false; - size_t nextText2 = line.find_first_not_of(" \t", nextText + 1); - if (nextText == string::npos) - return false; - if (line[nextText2] == ')' || line[nextText2] == '*') - return true; - return false; -} - -/** - * check if the currently reached '+' or '-' character is a unary operator - * this method takes for granted that the current character - * is a '+' or '-'. - * - * @return whether the current '+' or '-' is a unary operator. - */ -bool ASFormatter::isUnaryOperator() const -{ - assert(currentChar == '+' || currentChar == '-'); - - // does a digit follow a c-style cast - if (previousCommandChar == ')') - { - if (!isdigit(peekNextChar())) - return false; - size_t end = currentLine.rfind(')', charNum); - if (end == string::npos) - return false; - size_t lastChar = currentLine.find_last_not_of(" \t", end - 1); - if (lastChar == string::npos) - return false; - if (currentLine[lastChar] == '*') - end = lastChar; - string prevWord = getPreviousWord(currentLine, end); - if (prevWord.empty()) - return false; - if (!isNumericVariable(prevWord)) - return false; - return true; - } - - return ((isCharImmediatelyPostReturn || !isLegalNameChar(previousCommandChar)) - && previousCommandChar != '.' - && previousCommandChar != '\"' - && previousCommandChar != '\'' - && previousCommandChar != ']'); -} - -/** - * check if the currently reached comment is in a 'switch' statement - * - * @return whether the current '+' or '-' is in an exponent. - */ -bool ASFormatter::isInSwitchStatement() const -{ - assert(isInLineComment || isInComment); - if (!preBraceHeaderStack->empty()) - for (size_t i = 1; i < preBraceHeaderStack->size(); i++) - if (preBraceHeaderStack->at(i) == &AS_SWITCH) - return true; - return false; -} - -/** - * check if the currently reached '+' or '-' character is - * part of an exponent, i.e. 0.2E-5. - * - * @return whether the current '+' or '-' is in an exponent. - */ -bool ASFormatter::isInExponent() const -{ - assert (currentChar == '+' || currentChar == '-'); - - if (charNum < 2) - return false; - - int i = charNum - 1; - unsigned char prevChar = currentLine[i]; - - if (prevChar == 'e' || prevChar == 'E') { - i--; - bool hasPoint = false; - int numCount = 0; - while (i >= 0) { - prevChar = currentLine[i]; - if (prevChar == '.') { - if (hasPoint) - return false; - hasPoint = true; - } else if (isDigit(prevChar)) { - numCount++; - } else { - if (isLetterOrUnderLine(prevChar) || prevChar == '$' - || prevChar>127) - return false; - break; - } - i--; - } - return numCount > 0; - } - - if (prevChar == 'p' || prevChar == 'P') { - i--; - bool hasPoint = false; - bool hasX = false; - int numCount = 0; - while (i >= 0) { - prevChar = currentLine[i]; - if (isHexDigit(prevChar)) { - if (hasX) - return false; - numCount++ ; - } else if (prevChar == '.') { - if (hasPoint || hasX) - return false; - hasPoint = true; - } else if ( prevChar == 'x' || prevChar =='X') { - if (hasX) - return false; - i--; - if (i<0) - return false; - if (currentLine[i]!='0') - return false; - hasX = true; - } else { - if (isLetterOrUnderLine(prevChar) || prevChar == '$' - || prevChar>127) - return false; - break; - } - i--; //XQ135 modify// Floating-point number supporting hexadecimal representation - } - return hasX && numCount > 0; - } - return false; -} - -/** - * check if an array brace should NOT have an in-statement indent - * - * @return the array is non in-statement - */ -bool ASFormatter::isNonInStatementArrayBrace() const -{ - bool returnVal = false; - char nextChar = peekNextChar(); - // if this opening brace begins the line there will be no inStatement indent - if (currentLineBeginsWithBrace - && (size_t) charNum == currentLineFirstBraceNum - && nextChar != '}') - returnVal = true; - // if an opening brace ends the line there will be no inStatement indent - if (isWhiteSpace(nextChar) - || isBeforeAnyLineEndComment(charNum) - || nextChar == '{') - returnVal = true; - - // Java "new Type [] {...}" IS an inStatement indent - if (isJavaStyle() && previousNonWSChar == ']') - returnVal = false; - - return returnVal; -} - -/** - * check if a one-line block has been reached, - * i.e. if the currently reached '{' character is closed - * with a complimentary '}' elsewhere on the current line, - *. - * @return 0 = one-line block has not been reached. - * 1 = one-line block has been reached. - * 2 = one-line block has been reached and is followed by a comma. - * 3 = one-line block has been reached and is an empty block. - */ -int ASFormatter::isOneLineBlockReached(const string& line, int startChar) const -{ - assert(line[startChar] == '{'); - - bool isInComment_ = false; - bool isInQuote_ = false; - bool hasText = false; - int braceCount = 0; - int lineLength = line.length(); - char quoteChar_ = ' '; - char ch = ' '; - char prevCh = ' '; - - for (int i = startChar; i < lineLength; ++i) - { - ch = line[i]; - - if (isInComment_) - { - if (line.compare(i, 2, "*/") == 0) - { - isInComment_ = false; - ++i; - } - continue; - } - - if (isInQuote_) - { - if (ch == '\\') - ++i; - else 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; - continue; - } - if (ch == '}') - { - --braceCount; - if (braceCount == 0) - { - // is this an array? - if (parenStack->back() == 0 && prevCh != '}') - { - size_t peekNum = line.find_first_not_of(" \t", i + 1); - if (peekNum != string::npos && line[peekNum] == ',') - return 2; - } - if (!hasText) - return 3; // is an empty block - return 1; - } - } - if (ch == ';') - continue; - if (!isWhiteSpace(ch)) - { - hasText = true; - prevCh = ch; - } - } - - return 0; -} - -/** - * peek at the next word to determine if it is a C# non-paren header. - * will look ahead in the input file if necessary. - * - * @param startChar position on currentLine to start the search - * @return true if the next word is get or set. - */ -bool ASFormatter::isNextWordSharpNonParenHeader(int startChar) const -{ - // look ahead to find the next non-comment text - string nextText = peekNextText(currentLine.substr(startChar)); - if (nextText.length() == 0) - return false; - if (nextText[0] == '[') - return true; - if (!isCharPotentialHeader(nextText, 0)) - return false; - if (findKeyword(nextText, 0, AS_GET) || findKeyword(nextText, 0, AS_SET) - || findKeyword(nextText, 0, AS_ADD) || findKeyword(nextText, 0, AS_REMOVE)) - return true; - return false; -} - -/** - * peek at the next char to determine if it is an opening brace. - * will look ahead in the input file if necessary. - * this determines a java static constructor. - * - * @param startChar position on currentLine to start the search - * @return true if the next word is an opening brace. - */ -bool ASFormatter::isNextCharOpeningBrace(int startChar) const -{ - bool retVal = false; - string nextText = peekNextText(currentLine.substr(startChar)); - if (nextText.length() > 0 - && nextText.compare(0, 1, "{") == 0) - retVal = true; - return retVal; -} - -/** -* Check if operator and, pointer, and reference padding is disabled. -* Disabling is done thru a NOPAD tag in an ending comment. -* -* @return true if the formatting on this line is disabled. -*/ -bool ASFormatter::isOperatorPaddingDisabled() const -{ - size_t commentStart = currentLine.find("//", charNum); - if (commentStart == string::npos) - { - commentStart = currentLine.find("/*", charNum); - // comment must end on this line - if (commentStart != string::npos) - { - size_t commentEnd = currentLine.find("*/", commentStart + 2); - if (commentEnd == string::npos) - commentStart = string::npos; - } - } - if (commentStart == string::npos) - return false; - size_t noPadStart = currentLine.find("*NOPAD*", commentStart); - if (noPadStart == string::npos) - return false; - return true; -} - -/** -* Determine if an opening array-type brace should have a leading space pad. -* This is to identify C++11 uniform initializers. -*/ -bool ASFormatter::isUniformInitializerBrace() const -{ - if (isCStyle() && !isInEnum && !isImmediatelyPostPreprocessor) - { - if (isInClassInitializer - || isLegalNameChar(previousNonWSChar) - || previousNonWSChar == '(') - return true; - } - return false; -} - -/** -* Determine if there is a following statement on the current line. -*/ -bool ASFormatter::isMultiStatementLine() const -{ - assert((isImmediatelyPostHeader || foundClosingHeader)); - bool isInComment_ = false; - bool isInQuote_ = false; - int semiCount_ = 0; - int parenCount_ = 0; - int braceCount_ = 0; - - for (size_t i = 0; i < currentLine.length(); i++) - { - if (isInComment_) - { - if (currentLine.compare(i, 2, "*/") == 0) - { - isInComment_ = false; - continue; - } - } - if (currentLine.compare(i, 2, "/*") == 0) - { - isInComment_ = true; - continue; - } - if (currentLine.compare(i, 2, "//") == 0) - return false; - if (isInQuote_) - { - if (currentLine[i] == '"' || currentLine[i] == '\'') - isInQuote_ = false; - continue; - } - if (currentLine[i] == '"' || currentLine[i] == '\'') - { - isInQuote_ = true; - continue; - } - if (currentLine[i] == '(') - { - ++parenCount_; - continue; - } - if (currentLine[i] == ')') - { - --parenCount_; - continue; - } - if (parenCount_ > 0) - continue; - if (currentLine[i] == '{') - { - ++braceCount_; - } - if (currentLine[i] == '}') - { - --braceCount_; - } - if (braceCount_ > 0) - continue; - if (currentLine[i] == ';') - { - ++semiCount_; - if (semiCount_ > 1) - return true; - continue; - } - } - return false; -} - -/** - * get the next non-whitespace substring on following lines, bypassing all comments. - * - * @param firstLine the first line to check - * @return the next non-whitespace substring. - */ -string ASFormatter::peekNextText(const string& firstLine, - bool endOnEmptyLine /*false*/, - const shared_ptr& streamArg /*nullptr*/) const -{ - assert(sourceIterator->getPeekStart() == 0 || streamArg != nullptr); // Borland may need != 0 - bool isFirstLine = true; - string nextLine_ = firstLine; - size_t firstChar = string::npos; - shared_ptr stream = streamArg; - if (stream == nullptr) // Borland may need == 0 - stream = make_shared(sourceIterator); - - // find the first non-blank text, bypassing all comments. - bool isInComment_ = false; - while (stream->hasMoreLines() || isFirstLine) - { - if (isFirstLine) - isFirstLine = false; - else - nextLine_ = stream->peekNextLine(); - - firstChar = nextLine_.find_first_not_of(" \t"); - if (firstChar == string::npos) - { - if (endOnEmptyLine && !isInComment_) - break; - continue; - } - - if (nextLine_.compare(firstChar, 2, "/*") == 0) - { - firstChar += 2; - isInComment_ = true; - } - - if (isInComment_) - { - firstChar = nextLine_.find("*/", firstChar); - if (firstChar == string::npos) - continue; - firstChar += 2; - isInComment_ = false; - firstChar = nextLine_.find_first_not_of(" \t", firstChar); - if (firstChar == string::npos) - continue; - } - - if (nextLine_.compare(firstChar, 2, "//") == 0) - continue; - - // found the next text - break; - } - - if (firstChar == string::npos) - nextLine_ = ""; - else - nextLine_ = nextLine_.substr(firstChar); - return nextLine_; -} - -/** - * adjust comment position because of adding or deleting spaces - * the spaces are added or deleted to formattedLine - * spacePadNum contains the adjustment - */ -void ASFormatter::adjustComments() -{ - assert(spacePadNum != 0); - assert(isSequenceReached("//") || isSequenceReached("/*")); - - // block comment must be closed on this line with nothing after it - if (isSequenceReached("/*")) - { - size_t endNum = currentLine.find("*/", charNum + 2); - if (endNum == string::npos) - return; - // following line comments may be a tag from AStyleWx //[[)> - size_t nextNum = currentLine.find_first_not_of(" \t", endNum + 2); - if (nextNum != string::npos - && currentLine.compare(nextNum, 2, "//") != 0) - return; - } - - size_t len = formattedLine.length(); - // don't adjust a tab - if (formattedLine[len - 1] == '\t') - return; - // if spaces were removed, need to add spaces before the comment - if (spacePadNum < 0) - { - int adjust = -spacePadNum; // make the number positive - formattedLine.append(adjust, ' '); - } - // if spaces were added, need to delete extra spaces before the comment - // if cannot be done put the comment one space after the last text - else if (spacePadNum > 0) - { - int adjust = spacePadNum; - size_t lastText = formattedLine.find_last_not_of(' '); - if (lastText != string::npos - && lastText < len - adjust - 1) - formattedLine.resize(len - adjust); - else if (len > lastText + 2) - formattedLine.resize(lastText + 2); - else if (len < lastText + 2) - formattedLine.append(len - lastText, ' '); - } -} - -/** - * append the current brace inside the end of line comments - * currentChar contains the brace, it will be appended to formattedLine - * formattedLineCommentNum is the comment location on formattedLine - */ -void ASFormatter::appendCharInsideComments() -{ - if (formattedLineCommentNum == string::npos // does the comment start on the previous line? - || formattedLineCommentNum == 0) - { - appendCurrentChar(); // don't attach - return; - } - assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0 - || formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0); - - // find the previous non space char - size_t end = formattedLineCommentNum; - size_t beg = formattedLine.find_last_not_of(" \t", end - 1); - if (beg == string::npos) - { - appendCurrentChar(); // don't attach - return; - } - beg++; - - // insert the brace - if (end - beg < 3) // is there room to insert? - formattedLine.insert(beg, 3 - end + beg, ' '); - if (formattedLine[beg] == '\t') // don't pad with a tab - formattedLine.insert(beg, 1, ' '); - formattedLine[beg + 1] = currentChar; - testForTimeToSplitFormattedLine(); - - if (isBeforeComment()) - breakLine(); - else if (isCharImmediatelyPostLineComment) - shouldBreakLineAtNextChar = true; -} - -/** - * add or remove space padding to operators - * the operators and necessary padding will be appended to formattedLine - * the calling function should have a continue statement after calling this method - * - * @param newOperator the operator to be padded - */ -void ASFormatter::padOperators(const string* newOperator) -{ - assert(shouldPadOperators); - assert(newOperator != nullptr); - - char nextNonWSChar = ASBase::peekNextChar(currentLine, charNum); - bool shouldPad = (newOperator != &AS_SCOPE_RESOLUTION - && newOperator != &AS_PLUS_PLUS - && newOperator != &AS_MINUS_MINUS - && newOperator != &AS_NOT - && newOperator != &AS_BIT_NOT - && newOperator != &AS_ARROW - && !(newOperator == &AS_COLON && !foundQuestionMark // objC methods - && (isInObjCMethodDefinition || isInObjCInterface - || isInObjCSelector || squareBracketCount != 0)) - && !(newOperator == &AS_MINUS && isInExponent()) - && !(newOperator == &AS_PLUS && isInExponent()) - && !((newOperator == &AS_PLUS || newOperator == &AS_MINUS) // check for unary plus or minus - && (previousNonWSChar == '(' - || previousNonWSChar == '[' - || previousNonWSChar == '=' - || previousNonWSChar == ',' - || previousNonWSChar == ':' - || previousNonWSChar == '{')) -//? // commented out in release 2.05.1 - doesn't seem to do anything??? -//x && !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND || newOperator == &AS_AND) -//x && isPointerOrReference()) - && !(newOperator == &AS_MULT - && (previousNonWSChar == '.' - || previousNonWSChar == '>')) // check for -> - && !(newOperator == &AS_MULT && peekNextChar() == '>') - && !((isInTemplate || isImmediatelyPostTemplate) - && (newOperator == &AS_LS || newOperator == &AS_GR)) - && !(newOperator == &AS_GCC_MIN_ASSIGN - && ASBase::peekNextChar(currentLine, charNum + 1) == '>') - && !(newOperator == &AS_GR && previousNonWSChar == '?') - && !(newOperator == &AS_QUESTION // check for Java wildcard - && isJavaStyle() - && (previousNonWSChar == '<' - || nextNonWSChar == '>' - || nextNonWSChar == '.')) - && !(newOperator == &AS_QUESTION // check for C# null conditional operator - && isSharpStyle() - && (nextNonWSChar == '.' - || nextNonWSChar == '[')) - && !isCharImmediatelyPostOperator - && !isInCase - && !isInAsm - && !isInAsmOneLine - && !isInAsmBlock - ); - - // pad before operator - if (shouldPad - && !(newOperator == &AS_COLON - && (!foundQuestionMark && !isInEnum) && currentHeader != &AS_FOR) - && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?) - && currentLine.find(':', charNum + 1) == string::npos) - ) - appendSpacePad(); - appendOperator(*newOperator); - goForward(newOperator->length() - 1); - - currentChar = (*newOperator)[newOperator->length() - 1]; - // pad after operator - // but do not pad after a '-' that is a unary-minus. - if (shouldPad - && !isBeforeAnyComment() - && !(newOperator == &AS_PLUS && isUnaryOperator()) - && !(newOperator == &AS_MINUS && isUnaryOperator()) - && !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0) - && !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0) - && !(peekNextChar() == ',') - && !(newOperator == &AS_QUESTION && isSharpStyle() // check for C# nullable type (e.g. int?) - && peekNextChar() == '[') - ) - appendSpaceAfter(); -} - -/** - * format pointer or reference - * currentChar contains the pointer or reference - * the symbol and necessary padding will be appended to formattedLine - * the calling function should have a continue statement after calling this method - * - * NOTE: Do NOT use appendCurrentChar() in this method. The line should not be - * broken once the calculation starts. - */ -void ASFormatter::formatPointerOrReference() -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - assert(!isJavaStyle()); - - int pa = pointerAlignment; - int ra = referenceAlignment; - int itemAlignment = (currentChar == '*' || currentChar == '^') - ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra); - - // check for ** and && - int ptrLength = 1; - char peekedChar = peekNextChar(); - if ((currentChar == '*' && peekedChar == '*') - || (currentChar == '&' && peekedChar == '&')) - { - ptrLength = 2; - size_t nextChar = currentLine.find_first_not_of(" \t", charNum + 2); - if (nextChar == string::npos) - peekedChar = ' '; - else - peekedChar = currentLine[nextChar]; - } - // check for cast - if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',') - { - formatPointerOrReferenceCast(); - return; - } - - // check for a padded space and remove it - if (charNum > 0 - && !isWhiteSpace(currentLine[charNum - 1]) - && formattedLine.length() > 0 - && isWhiteSpace(formattedLine[formattedLine.length() - 1])) - { - formattedLine.erase(formattedLine.length() - 1); - spacePadNum--; - } - - if (itemAlignment == PTR_ALIGN_TYPE) - { - formatPointerOrReferenceToType(); - } - else if (itemAlignment == PTR_ALIGN_MIDDLE) - { - formatPointerOrReferenceToMiddle(); - } - else if (itemAlignment == PTR_ALIGN_NAME) - { - formatPointerOrReferenceToName(); - } - else // pointerAlignment == PTR_ALIGN_NONE - { - formattedLine.append(currentLine.substr(charNum, ptrLength)); - if (ptrLength > 1) - goForward(ptrLength - 1); - } -} - -/** - * format pointer or reference with align to type - */ -void ASFormatter::formatPointerOrReferenceToType() -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - assert(!isJavaStyle()); - - // do this before bumping charNum - bool isOldPRCentered = isPointerOrReferenceCentered(); - string sequenceToInsert(1, currentChar); - // get the sequence - if (currentChar == peekNextChar()) - { - for (size_t i = charNum + 1; currentLine.length() > i; i++) - { - if (currentLine[i] == sequenceToInsert[0]) - { - sequenceToInsert.append(1, currentLine[i]); - goForward(1); - continue; - } - break; - } - } - // append the sequence - string charSave; - size_t prevCh = formattedLine.find_last_not_of(" \t"); - if (prevCh < formattedLine.length()) - { - charSave = formattedLine.substr(prevCh + 1); - formattedLine.resize(prevCh + 1); - } - formattedLine.append(sequenceToInsert); - if (peekNextChar() != ')') - formattedLine.append(charSave); - else - spacePadNum -= charSave.length(); - // if no space after then add one - if (charNum < (int) currentLine.length() - 1 - && !isWhiteSpace(currentLine[charNum + 1]) - && currentLine[charNum + 1] != ')') - appendSpacePad(); - // if old pointer or reference is centered, remove a space - if (isOldPRCentered - && isWhiteSpace(formattedLine[formattedLine.length() - 1])) - { - formattedLine.erase(formattedLine.length() - 1, 1); - spacePadNum--; - } - // update the formattedLine split point - if (maxCodeLength != string::npos && formattedLine.length() > 0) - { - size_t index = formattedLine.length() - 1; - if (isWhiteSpace(formattedLine[index])) - { - updateFormattedLineSplitPointsPointerOrReference(index); - testForTimeToSplitFormattedLine(); - } - } -} - -/** - * format pointer or reference with align in the middle - */ -void ASFormatter::formatPointerOrReferenceToMiddle() -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - assert(!isJavaStyle()); - - // compute current whitespace before - size_t wsBefore = currentLine.find_last_not_of(" \t", charNum - 1); - if (wsBefore == string::npos) - wsBefore = 0; - else - wsBefore = charNum - wsBefore - 1; - string sequenceToInsert(1, currentChar); - if (currentChar == peekNextChar()) - { - for (size_t i = charNum + 1; currentLine.length() > i; i++) - { - if (currentLine[i] == sequenceToInsert[0]) - { - sequenceToInsert.append(1, currentLine[i]); - goForward(1); - continue; - } - break; - } - } - // if reference to a pointer check for conflicting alignment - else if (currentChar == '*' && peekNextChar() == '&' - && (referenceAlignment == REF_ALIGN_TYPE - || referenceAlignment == REF_ALIGN_MIDDLE - || referenceAlignment == REF_SAME_AS_PTR)) - { - sequenceToInsert = "*&"; - goForward(1); - for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++) - goForward(1); - } - // if a comment follows don't align, just space pad - if (isBeforeAnyComment()) - { - appendSpacePad(); - formattedLine.append(sequenceToInsert); - appendSpaceAfter(); - return; - } - // do this before goForward() - bool isAfterScopeResolution = previousNonWSChar == ':'; - size_t charNumSave = charNum; - // if this is the last thing on the line - if (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos) - { - if (wsBefore == 0 && !isAfterScopeResolution) - formattedLine.append(1, ' '); - formattedLine.append(sequenceToInsert); - return; - } - // goForward() to convert tabs to spaces, if necessary, - // and move following characters to preceding characters - // this may not work every time with tab characters - for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++) - { - goForward(1); - if (formattedLine.length() > 0) - formattedLine.append(1, currentLine[i]); - else - spacePadNum--; - } - // find space padding after - size_t wsAfter = currentLine.find_first_not_of(" \t", charNumSave + 1); - if (wsAfter == string::npos || isBeforeAnyComment()) - wsAfter = 0; - else - wsAfter = wsAfter - charNumSave - 1; - // don't pad before scope resolution operator, but pad after - if (isAfterScopeResolution) - { - size_t lastText = formattedLine.find_last_not_of(" \t"); - formattedLine.insert(lastText + 1, sequenceToInsert); - appendSpacePad(); - } - else if (formattedLine.length() > 0) - { - // whitespace should be at least 2 chars to center - if (wsBefore + wsAfter < 2) - { - size_t charsToAppend = (2 - (wsBefore + wsAfter)); - formattedLine.append(charsToAppend, ' '); - spacePadNum += charsToAppend; - if (wsBefore == 0) - wsBefore++; - if (wsAfter == 0) - wsAfter++; - } - // insert the pointer or reference char - size_t padAfter = (wsBefore + wsAfter) / 2; - size_t index = formattedLine.length() - padAfter; - if (index < formattedLine.length()) - formattedLine.insert(index, sequenceToInsert); - else - formattedLine.append(sequenceToInsert); - } - else // formattedLine.length() == 0 - { - formattedLine.append(sequenceToInsert); - if (wsAfter == 0) - wsAfter++; - formattedLine.append(wsAfter, ' '); - spacePadNum += wsAfter; - } - // update the formattedLine split point after the pointer - if (maxCodeLength != string::npos && formattedLine.length() > 0) - { - size_t index = formattedLine.find_last_not_of(" \t"); - if (index != string::npos && (index < formattedLine.length() - 1)) - { - index++; - updateFormattedLineSplitPointsPointerOrReference(index); - testForTimeToSplitFormattedLine(); - } - } -} - -/** - * format pointer or reference with align to name - */ -void ASFormatter::formatPointerOrReferenceToName() -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - assert(!isJavaStyle()); - - // do this before bumping charNum - bool isOldPRCentered = isPointerOrReferenceCentered(); - - size_t startNum = formattedLine.find_last_not_of(" \t"); - if (startNum == string::npos) - startNum = 0; - string sequenceToInsert(1, currentChar); - if (currentChar == peekNextChar()) - { - for (size_t i = charNum + 1; currentLine.length() > i; i++) - { - if (currentLine[i] == sequenceToInsert[0]) - { - sequenceToInsert.append(1, currentLine[i]); - goForward(1); - continue; - } - break; - } - } - // if reference to a pointer align both to name - else if (currentChar == '*' && peekNextChar() == '&') - { - sequenceToInsert = "*&"; - goForward(1); - for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++) - goForward(1); - } - char peekedChar = peekNextChar(); - bool isAfterScopeResolution = previousNonWSChar == ':'; // check for :: - // if this is not the last thing on the line - if ((isLegalNameChar(peekedChar) || peekedChar == '(' || peekedChar == '[' || peekedChar == '=') - && (int) currentLine.find_first_not_of(" \t", charNum + 1) > charNum) - { - // goForward() to convert tabs to spaces, if necessary, - // and move following characters to preceding characters - // this may not work every time with tab characters - for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++) - { - // if a padded paren follows don't move - if (shouldPadParensOutside && peekedChar == '(' && !isOldPRCentered) - { - // empty parens don't count - size_t start = currentLine.find_first_not_of("( \t", i); - if (start != string::npos && currentLine[start] != ')') - break; - } - goForward(1); - if (formattedLine.length() > 0) - formattedLine.append(1, currentLine[charNum]); - else - spacePadNum--; - } - } - // don't pad before scope resolution operator - if (isAfterScopeResolution) - { - size_t lastText = formattedLine.find_last_not_of(" \t"); - if (lastText != string::npos && lastText + 1 < formattedLine.length()) - formattedLine.erase(lastText + 1); - } - // if no space before * then add one - else if (formattedLine.length() > 0 - && (formattedLine.length() <= startNum + 1 - || !isWhiteSpace(formattedLine[startNum + 1]))) - { - formattedLine.insert(startNum + 1, 1, ' '); - spacePadNum++; - } - appendSequence(sequenceToInsert, false); - // if old pointer or reference is centered, remove a space - if (isOldPRCentered - && formattedLine.length() > startNum + 1 - && isWhiteSpace(formattedLine[startNum + 1]) - && peekedChar != '*' // check for '* *' - && !isBeforeAnyComment()) - { - formattedLine.erase(startNum + 1, 1); - spacePadNum--; - } - // don't convert to *= or &= - if (peekedChar == '=') - { - appendSpaceAfter(); - // if more than one space before, delete one - if (formattedLine.length() > startNum - && isWhiteSpace(formattedLine[startNum + 1]) - && isWhiteSpace(formattedLine[startNum + 2])) - { - formattedLine.erase(startNum + 1, 1); - spacePadNum--; - } - } - // update the formattedLine split point - if (maxCodeLength != string::npos) - { - size_t index = formattedLine.find_last_of(" \t"); - if (index != string::npos - && index < formattedLine.length() - 1 - && (formattedLine[index + 1] == '*' - || formattedLine[index + 1] == '&' - || formattedLine[index + 1] == '^')) - { - updateFormattedLineSplitPointsPointerOrReference(index); - testForTimeToSplitFormattedLine(); - } - } -} - -/** - * format pointer or reference cast - * currentChar contains the pointer or reference - * NOTE: the pointers and references in function definitions - * are processed as a cast (e.g. void foo(void*, void*)) - * is processed here. - */ -void ASFormatter::formatPointerOrReferenceCast() -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - assert(!isJavaStyle()); - - int pa = pointerAlignment; - int ra = referenceAlignment; - int itemAlignment = (currentChar == '*' || currentChar == '^') - ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra); - - string sequenceToInsert(1, currentChar); - if (isSequenceReached("**") || isSequenceReached("&&")) - { - goForward(1); - sequenceToInsert.append(1, currentLine[charNum]); - } - if (itemAlignment == PTR_ALIGN_NONE) - { - appendSequence(sequenceToInsert, false); - return; - } - // remove preceding whitespace - char prevCh = ' '; - size_t prevNum = formattedLine.find_last_not_of(" \t"); - if (prevNum != string::npos) - { - prevCh = formattedLine[prevNum]; - if (itemAlignment == PTR_ALIGN_TYPE && currentChar == '*' && prevCh == '*') - { - // '* *' may be a multiply followed by a dereference - if (prevNum + 2 < formattedLine.length() - && isWhiteSpace(formattedLine[prevNum + 2])) - { - spacePadNum -= (formattedLine.length() - 2 - prevNum); - formattedLine.erase(prevNum + 2); - } - } - else if (prevNum + 1 < formattedLine.length() - && isWhiteSpace(formattedLine[prevNum + 1]) - && prevCh != '(') - { - spacePadNum -= (formattedLine.length() - 1 - prevNum); - formattedLine.erase(prevNum + 1); - } - } - bool isAfterScopeResolution = previousNonWSChar == ':'; - if ((itemAlignment == PTR_ALIGN_MIDDLE || itemAlignment == PTR_ALIGN_NAME) - && !isAfterScopeResolution && prevCh != '(') - { - appendSpacePad(); - // in this case appendSpacePad may or may not update the split point - if (maxCodeLength != string::npos && formattedLine.length() > 0) - updateFormattedLineSplitPointsPointerOrReference(formattedLine.length() - 1); - appendSequence(sequenceToInsert, false); - } - else - appendSequence(sequenceToInsert, false); -} - -/** - * add or remove space padding to parens - * currentChar contains the paren - * the parens and necessary padding will be appended to formattedLine - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::padParens() -{ - assert(currentChar == '(' || currentChar == ')'); - assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen); - - int spacesOutsideToDelete = 0; - int spacesInsideToDelete = 0; - - if (currentChar == '(') - { - spacesOutsideToDelete = formattedLine.length() - 1; - spacesInsideToDelete = 0; - - // compute spaces outside the opening paren to delete - if (shouldUnPadParens) - { - char lastChar = ' '; - bool prevIsParenHeader = false; - size_t i = formattedLine.find_last_not_of(" \t"); - if (i != string::npos) - { - // if last char is a brace the previous whitespace is an indent - if (formattedLine[i] == '{') - spacesOutsideToDelete = 0; - else if (isCharImmediatelyPostPointerOrReference) - spacesOutsideToDelete = 0; - else - { - spacesOutsideToDelete -= i; - lastChar = formattedLine[i]; - // if previous word is a header, it will be a paren header - string prevWord = getPreviousWord(formattedLine, formattedLine.length()); - const string* prevWordH = nullptr; - if (shouldPadHeader - && prevWord.length() > 0 - && isCharPotentialHeader(prevWord, 0)) - prevWordH = ASBase::findHeader(prevWord, 0, headers); - if (prevWordH != nullptr) - prevIsParenHeader = true; // don't unpad - else if (prevWord == AS_RETURN) - prevIsParenHeader = true; // don't unpad - else if ((prevWord == AS_NEW || prevWord == AS_DELETE) - && shouldPadHeader) - prevIsParenHeader = true; // don't unpad - else if (isCStyle() && prevWord == AS_THROW && shouldPadHeader) - prevIsParenHeader = true; // don't unpad - else if (prevWord == "and" || prevWord == "or" || prevWord == "in") - prevIsParenHeader = true; // don't unpad - // don't unpad variables - else if (isNumericVariable(prevWord)) - prevIsParenHeader = true; // don't unpad - } - } - // do not unpad operators, but leave them if already padded - if (shouldPadParensOutside || prevIsParenHeader) - spacesOutsideToDelete--; - else if (lastChar == '|' // check for || - || lastChar == '&' // check for && - || lastChar == ',' - || (lastChar == '(' && shouldPadParensInside) - || (lastChar == '>' && !foundCastOperator) - || lastChar == '<' - || lastChar == '?' - || lastChar == ':' - || lastChar == ';' - || lastChar == '=' - || lastChar == '+' - || lastChar == '-' - || lastChar == '*' - || lastChar == '/' - || lastChar == '%' - || lastChar == '^' - ) - spacesOutsideToDelete--; - - if (spacesOutsideToDelete > 0) - { - formattedLine.erase(i + 1, spacesOutsideToDelete); - spacePadNum -= spacesOutsideToDelete; - } - } - - // pad open paren outside - char peekedCharOutside = peekNextChar(); - if (shouldPadFirstParen && previousChar != '(' && peekedCharOutside != ')') - appendSpacePad(); - else if (shouldPadParensOutside) - { - if (!(currentChar == '(' && peekedCharOutside == ')')) - appendSpacePad(); - } - - appendCurrentChar(); - - // unpad open paren inside - if (shouldUnPadParens) - { - size_t j = currentLine.find_first_not_of(" \t", charNum + 1); - if (j != string::npos) - spacesInsideToDelete = j - charNum - 1; - if (shouldPadParensInside) - spacesInsideToDelete--; - if (spacesInsideToDelete > 0) - { - currentLine.erase(charNum + 1, spacesInsideToDelete); - spacePadNum -= spacesInsideToDelete; - } - // convert tab to space if requested - if (shouldConvertTabs - && (int) currentLine.length() > charNum + 1 - && currentLine[charNum + 1] == '\t') - currentLine[charNum + 1] = ' '; - } - - // pad open paren inside - char peekedCharInside = peekNextChar(); - if (shouldPadParensInside) - if (!(currentChar == '(' && peekedCharInside == ')')) - appendSpaceAfter(); - } - else if (currentChar == ')') - { - // unpad close paren inside - if (shouldUnPadParens) - { - spacesInsideToDelete = formattedLine.length(); - size_t i = formattedLine.find_last_not_of(" \t"); - if (i != string::npos) - spacesInsideToDelete = formattedLine.length() - 1 - i; - if (shouldPadParensInside) - spacesInsideToDelete--; - if (spacesInsideToDelete > 0) - { - formattedLine.erase(i + 1, spacesInsideToDelete); - spacePadNum -= spacesInsideToDelete; - } - } - - // pad close paren inside - if (shouldPadParensInside) - if (!(previousChar == '(' && currentChar == ')')) - appendSpacePad(); - - appendCurrentChar(); - - // unpad close paren outside - // close parens outside are left unchanged - if (shouldUnPadParens) - { - //spacesOutsideToDelete = 0; - //size_t j = currentLine.find_first_not_of(" \t", charNum + 1); - //if (j != string::npos) - // spacesOutsideToDelete = j - charNum - 1; - //if (shouldPadParensOutside) - // spacesOutsideToDelete--; - - //if (spacesOutsideToDelete > 0) - //{ - // currentLine.erase(charNum + 1, spacesOutsideToDelete); - // spacePadNum -= spacesOutsideToDelete; - //} - } - - // pad close paren outside - char peekedCharOutside = peekNextChar(); - if (shouldPadParensOutside) - if (peekedCharOutside != ';' - && peekedCharOutside != ',' - && peekedCharOutside != '.' - && peekedCharOutside != '+' // check for ++ - && peekedCharOutside != '-' // check for -- - && peekedCharOutside != ']') - appendSpaceAfter(); - } -} - -/** -* add or remove space padding to objective-c method prefix (- or +) -* if this is a '(' it begins a return type -* these options have precedence over the padParens methods -* the padParens method has already been called, this method adjusts -*/ -void ASFormatter::padObjCMethodPrefix() -{ - assert(isInObjCMethodDefinition && isImmediatelyPostObjCMethodPrefix); - assert(shouldPadMethodPrefix || shouldUnPadMethodPrefix); - - size_t prefix = formattedLine.find_first_of("+-"); - if (prefix == string::npos) - return; - size_t firstChar = formattedLine.find_first_not_of(" \t", prefix + 1); - if (firstChar == string::npos) - firstChar = formattedLine.length(); - int spaces = firstChar - prefix - 1; - - if (shouldPadMethodPrefix) - { - if (spaces == 0) - { - formattedLine.insert(prefix + 1, 1, ' '); - spacePadNum += 1; - } - else if (spaces > 1) - { - formattedLine.erase(prefix + 1, spaces - 1); - formattedLine[prefix + 1] = ' '; // convert any tab to space - spacePadNum -= spaces - 1; - } - } - // this option will be ignored if used with pad-method-prefix - else if (shouldUnPadMethodPrefix) - { - if (spaces > 0) - { - formattedLine.erase(prefix + 1, spaces); - spacePadNum -= spaces; - } - } -} - -/** -* add or remove space padding to objective-c parens -* these options have precedence over the padParens methods -* the padParens method has already been called, this method adjusts -*/ -void ASFormatter::padObjCReturnType() -{ - assert(currentChar == ')' && isInObjCReturnType); - assert(shouldPadReturnType || shouldUnPadReturnType); - - size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextText == string::npos) - return; - int spaces = nextText - charNum - 1; - - if (shouldPadReturnType) - { - if (spaces == 0) - { - // this will already be padded if pad-paren is used - if (formattedLine[formattedLine.length() - 1] != ' ') - { - formattedLine.append(" "); - spacePadNum += 1; - } - } - else if (spaces > 1) - { - // do not use goForward here - currentLine.erase(charNum + 1, spaces - 1); - currentLine[charNum + 1] = ' '; // convert any tab to space - spacePadNum -= spaces - 1; - } - } - // this option will be ignored if used with pad-return-type - else if (shouldUnPadReturnType) - { - // this will already be padded if pad-paren is used - if (formattedLine[formattedLine.length() - 1] == ' ') - { - int lastText = formattedLine.find_last_not_of(" \t"); - spacePadNum -= formattedLine.length() - lastText - 1; - formattedLine.resize(lastText + 1); - } - // do not use goForward here - currentLine.erase(charNum + 1, spaces); - spacePadNum -= spaces; - } -} - -/** -* add or remove space padding to objective-c parens -* these options have precedence over the padParens methods -* the padParens method has already been called, this method adjusts -*/ -void ASFormatter::padObjCParamType() -{ - assert((currentChar == '(' || currentChar == ')') && isInObjCMethodDefinition); - assert(!isImmediatelyPostObjCMethodPrefix && !isInObjCReturnType); - assert(shouldPadParamType || shouldUnPadParamType); - - if (currentChar == '(') - { - // open paren has already been attached to formattedLine by padParen - size_t paramOpen = formattedLine.rfind('('); - assert(paramOpen != string::npos); - size_t prevText = formattedLine.find_last_not_of(" \t", paramOpen - 1); - if (prevText == string::npos) - return; - int spaces = paramOpen - prevText - 1; - - if (shouldPadParamType - || objCColonPadMode == COLON_PAD_ALL - || objCColonPadMode == COLON_PAD_AFTER) - { - if (spaces == 0) - { - formattedLine.insert(paramOpen, 1, ' '); - spacePadNum += 1; - } - if (spaces > 1) - { - formattedLine.erase(prevText + 1, spaces - 1); - formattedLine[prevText + 1] = ' '; // convert any tab to space - spacePadNum -= spaces - 1; - } - } - // this option will be ignored if used with pad-param-type - else if (shouldUnPadParamType - || objCColonPadMode == COLON_PAD_NONE - || objCColonPadMode == COLON_PAD_BEFORE) - { - if (spaces > 0) - { - formattedLine.erase(prevText + 1, spaces); - spacePadNum -= spaces; - } - } - } - else if (currentChar == ')') - { - size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextText == string::npos) - return; - int spaces = nextText - charNum - 1; - - if (shouldPadParamType) - { - if (spaces == 0) - { - // this will already be padded if pad-paren is used - if (formattedLine[formattedLine.length() - 1] != ' ') - { - formattedLine.append(" "); - spacePadNum += 1; - } - } - else if (spaces > 1) - { - // do not use goForward here - currentLine.erase(charNum + 1, spaces - 1); - currentLine[charNum + 1] = ' '; // convert any tab to space - spacePadNum -= spaces - 1; - } - } - // this option will be ignored if used with pad-param-type - else if (shouldUnPadParamType) - { - // this will already be padded if pad-paren is used - if (formattedLine[formattedLine.length() - 1] == ' ') - { - spacePadNum -= 1; - int lastText = formattedLine.find_last_not_of(" \t"); - formattedLine.resize(lastText + 1); - } - if (spaces > 0) - { - // do not use goForward here - currentLine.erase(charNum + 1, spaces); - spacePadNum -= spaces; - } - } - } -} - -/** - * format opening brace as attached or broken - * currentChar contains the brace - * the braces will be appended to the current formattedLine or a new formattedLine as necessary - * the calling function should have a continue statement after calling this method - * - * @param braceType the type of brace to be formatted. - */ -void ASFormatter::formatOpeningBrace(BraceType braceType) -{ - assert(!isBraceType(braceType, ARRAY_TYPE)); - assert(currentChar == '{'); - - parenStack->emplace_back(0); - - bool breakBrace = isCurrentBraceBroken(); - - if (breakBrace) - { - if (isBeforeAnyComment() && isOkToBreakBlock(braceType) && sourceIterator->hasMoreLines()) - { - // if comment is at line end leave the comment on this line - if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace) - { - currentChar = ' '; // remove brace from current line - if (parenStack->size() > 1) - parenStack->pop_back(); - currentLine[charNum] = currentChar; - appendOpeningBrace = true; // append brace to following line - } - // else put comment after the brace - else if (!isBeforeMultipleLineEndComments(charNum)) - breakLine(); - } - else if (!isBraceType(braceType, SINGLE_LINE_TYPE)) - { - formattedLine = rtrim(formattedLine); - breakLine(); - } - else if ((shouldBreakOneLineBlocks || isBraceType(braceType, BREAK_BLOCK_TYPE)) - && !isBraceType(braceType, EMPTY_BLOCK_TYPE)) - breakLine(); - else if (!isInLineBreak) - appendSpacePad(); - - appendCurrentChar(); - - // should a following comment break from the brace? - // must break the line AFTER the brace - if (isBeforeComment() - && formattedLine.length() > 0 - && formattedLine[0] == '{' - && isOkToBreakBlock(braceType) - && (braceFormatMode == BREAK_MODE - || braceFormatMode == LINUX_MODE)) - { - shouldBreakLineAtNextChar = true; - } - } - else // attach brace - { - // are there comments before the brace? - if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment) - { - if (isOkToBreakBlock(braceType) - && !(isCharImmediatelyPostComment && isCharImmediatelyPostLineComment) // don't attach if two comments on the line - && !isImmediatelyPostPreprocessor -// && peekNextChar() != '}' // don't attach { } // removed release 2.03 - && previousCommandChar != '{' // don't attach { { - && previousCommandChar != '}' // don't attach } { - && previousCommandChar != ';') // don't attach ; { - { - appendCharInsideComments(); - } - else - { - appendCurrentChar(); // don't attach - } - } - else if (previousCommandChar == '{' - || (previousCommandChar == '}' && !isInClassInitializer) - || previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';' - { - appendCurrentChar(); // don't attach - } - else - { - // if a blank line precedes this don't attach - if (isEmptyLine(formattedLine)) - appendCurrentChar(); // don't attach - else if (isOkToBreakBlock(braceType) - && !(isImmediatelyPostPreprocessor - && currentLineBeginsWithBrace)) - { - if (!isBraceType(braceType, EMPTY_BLOCK_TYPE)) - { - appendSpacePad(); - appendCurrentChar(false); // OK to attach - testForTimeToSplitFormattedLine(); // line length will have changed - // should a following comment attach with the brace? - // insert spaces to reposition the comment - if (isBeforeComment() - && !isBeforeMultipleLineEndComments(charNum) - && (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace)) - { - shouldBreakLineAtNextChar = true; - currentLine.insert(charNum + 1, charNum + 1, ' '); - } - else if (!isBeforeAnyComment()) // added in release 2.03 - { - shouldBreakLineAtNextChar = true; - } - } - else - { - if (currentLineBeginsWithBrace && (size_t) charNum == currentLineFirstBraceNum) - { - appendSpacePad(); - appendCurrentChar(false); // attach - shouldBreakLineAtNextChar = true; - } - else - { - appendSpacePad(); - appendCurrentChar(); // don't attach - } - } - } - else - { - if (!isInLineBreak) - appendSpacePad(); - appendCurrentChar(); // don't attach - } - } - } -} - -/** - * format closing brace - * currentChar contains the brace - * the calling function should have a continue statement after calling this method - * - * @param braceType the type of the opening brace for this closing brace. - */ -void ASFormatter::formatClosingBrace(BraceType braceType) -{ - assert(!isBraceType(braceType, ARRAY_TYPE)); - assert(currentChar == '}'); - - // parenStack must contain one entry - if (parenStack->size() > 1) - parenStack->pop_back(); - - // mark state of immediately after empty block - // this state will be used for locating braces that appear immediately AFTER an empty block (e.g. '{} \n}'). - if (previousCommandChar == '{') - isImmediatelyPostEmptyBlock = true; - - if (attachClosingBraceMode) - { - // for now, namespaces and classes will be attached. Uncomment the lines below to break. - if ((isEmptyLine(formattedLine) // if a blank line precedes this - || isCharImmediatelyPostLineComment - || isCharImmediatelyPostComment - || (isImmediatelyPostPreprocessor && (int) currentLine.find_first_not_of(" \t") == charNum) -// || (isBraceType(braceType, CLASS_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{') -// || (isBraceType(braceType, NAMESPACE_TYPE) && isOkToBreakBlock(braceType) && previousNonWSChar != '{') - ) - && (!isBraceType(braceType, SINGLE_LINE_TYPE) || isOkToBreakBlock(braceType))) - { - breakLine(); - appendCurrentChar(); // don't attach - } - else - { - if (previousNonWSChar != '{' - && (!isBraceType(braceType, SINGLE_LINE_TYPE) - || isOkToBreakBlock(braceType))) - appendSpacePad(); - appendCurrentChar(false); // attach - } - } - else if (!isBraceType(braceType, EMPTY_BLOCK_TYPE) - && (isBraceType(braceType, BREAK_BLOCK_TYPE) - || isOkToBreakBlock(braceType))) - { - breakLine(); - appendCurrentChar(); - } - else - { - appendCurrentChar(); - } - - // if a declaration follows a definition, space pad - if (isLegalNameChar(peekNextChar())) - appendSpaceAfter(); - - if (shouldBreakBlocks - && currentHeader != nullptr - && !isHeaderInMultiStatementLine - && parenStack->back() == 0) - { - if (currentHeader == &AS_CASE || currentHeader == &AS_DEFAULT) - { - // do not yet insert a line if "break" statement is outside the braces - string nextText = peekNextText(currentLine.substr(charNum + 1)); - if (nextText.length() > 0 - && nextText.substr(0, 5) != "break") - isAppendPostBlockEmptyLineRequested = true; - } - else - isAppendPostBlockEmptyLineRequested = true; - } -} - -/** - * format array braces as attached or broken - * determine if the braces can have an inStatement indent - * currentChar contains the brace - * the braces will be appended to the current formattedLine or a new formattedLine as necessary - * the calling function should have a continue statement after calling this method - * - * @param braceType the type of brace to be formatted, must be an ARRAY_TYPE. - * @param isOpeningArrayBrace indicates if this is the opening brace for the array block. - */ -void ASFormatter::formatArrayBraces(BraceType braceType, bool isOpeningArrayBrace) -{ - assert(isBraceType(braceType, ARRAY_TYPE)); - assert(currentChar == '{' || currentChar == '}'); - - if (currentChar == '{') - { - // is this the first opening brace in the array? - if (isOpeningArrayBrace) - { - if (braceFormatMode == ATTACH_MODE - || braceFormatMode == LINUX_MODE) - { - // break an enum if mozilla - if (isBraceType(braceType, ENUM_TYPE) - && formattingStyle == STYLE_MOZILLA) - { - isInLineBreak = true; - appendCurrentChar(); // don't attach - } - // don't attach to a preprocessor directive or '\' line - else if ((isImmediatelyPostPreprocessor - || (formattedLine.length() > 0 - && formattedLine[formattedLine.length() - 1] == '\\')) - && currentLineBeginsWithBrace) - { - isInLineBreak = true; - appendCurrentChar(); // don't attach - } - else if (isCharImmediatelyPostComment) - { - // TODO: attach brace to line-end comment - appendCurrentChar(); // don't attach - } - else if (isCharImmediatelyPostLineComment && !isBraceType(braceType, SINGLE_LINE_TYPE)) - { - appendCharInsideComments(); - } - else - { - // if a blank line precedes this don't attach - if (isEmptyLine(formattedLine)) - appendCurrentChar(); // don't attach - else - { - // if brace is broken or not an assignment - if (currentLineBeginsWithBrace - && !isBraceType(braceType, SINGLE_LINE_TYPE)) - { - appendSpacePad(); - appendCurrentChar(false); // OK to attach - // TODO: debug the following line - testForTimeToSplitFormattedLine(); // line length will have changed - - if (currentLineBeginsWithBrace - && currentLineFirstBraceNum == (size_t) charNum) - shouldBreakLineAtNextChar = true; - } - else - { - if (previousNonWSChar != '(') - { - // don't space pad C++11 uniform initialization - if (!isBraceType(braceType, INIT_TYPE)) - appendSpacePad(); - } - appendCurrentChar(); - } - } - } - } - else if (braceFormatMode == BREAK_MODE) - { - if (isWhiteSpace(peekNextChar()) && !isInVirginLine) - breakLine(); - else if (isBeforeAnyComment() && sourceIterator->hasMoreLines()) - { - // do not break unless comment is at line end - if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace) - { - currentChar = ' '; // remove brace from current line - appendOpeningBrace = true; // append brace to following line - } - } - if (!isInLineBreak && previousNonWSChar != '(') - { - // don't space pad C++11 uniform initialization - if (!isBraceType(braceType, INIT_TYPE)) - appendSpacePad(); - } - appendCurrentChar(); - - if (currentLineBeginsWithBrace - && currentLineFirstBraceNum == (size_t) charNum - && !isBraceType(braceType, SINGLE_LINE_TYPE)) - shouldBreakLineAtNextChar = true; - } - else if (braceFormatMode == RUN_IN_MODE) - { - if (isWhiteSpace(peekNextChar()) && !isInVirginLine) - breakLine(); - else if (isBeforeAnyComment() && sourceIterator->hasMoreLines()) - { - // do not break unless comment is at line end - if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace) - { - currentChar = ' '; // remove brace from current line - appendOpeningBrace = true; // append brace to following line - } - } - if (!isInLineBreak && previousNonWSChar != '(') - { - // don't space pad C++11 uniform initialization - if (!isBraceType(braceType, INIT_TYPE)) - appendSpacePad(); - } - appendCurrentChar(); - } - else if (braceFormatMode == NONE_MODE) - { - if (currentLineBeginsWithBrace - && (size_t) charNum == currentLineFirstBraceNum) - { - appendCurrentChar(); // don't attach - } - else - { - if (previousNonWSChar != '(') - { - // don't space pad C++11 uniform initialization - if (!isBraceType(braceType, INIT_TYPE)) - appendSpacePad(); - } - appendCurrentChar(false); // OK to attach - } - } - } - else // not the first opening brace - { - if (braceFormatMode == RUN_IN_MODE) - { - if (previousNonWSChar == '{' - && braceTypeStack->size() > 2 - && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2], - SINGLE_LINE_TYPE)) - formatArrayRunIn(); - } - else if (!isInLineBreak - && !isWhiteSpace(peekNextChar()) - && previousNonWSChar == '{' - && braceTypeStack->size() > 2 - && !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2], - SINGLE_LINE_TYPE)) - formatArrayRunIn(); - - appendCurrentChar(); - } - } - else if (currentChar == '}') - { - if (attachClosingBraceMode) - { - if (isEmptyLine(formattedLine) // if a blank line precedes this - || isImmediatelyPostPreprocessor - || isCharImmediatelyPostLineComment - || isCharImmediatelyPostComment) - appendCurrentChar(); // don't attach - else - { - appendSpacePad(); - appendCurrentChar(false); // attach - } - } - else - { - // does this close the first opening brace in the array? - // must check if the block is still a single line because of anonymous statements - if (!isBraceType(braceType, INIT_TYPE) - && (!isBraceType(braceType, SINGLE_LINE_TYPE) - || formattedLine.find('{') == string::npos)) - breakLine(); - appendCurrentChar(); - } - - // if a declaration follows an enum definition, space pad - char peekedChar = peekNextChar(); - if ((isLegalNameChar(peekedChar) && peekedChar != '.') - || peekedChar == '[') - appendSpaceAfter(); - } -} - -/** - * determine if a run-in can be attached. - * if it can insert the indents in formattedLine and reset the current line break. - */ -void ASFormatter::formatRunIn() -{ - assert(braceFormatMode == RUN_IN_MODE || braceFormatMode == NONE_MODE); - - // keep one line blocks returns true without indenting the run-in - if (formattingStyle != STYLE_PICO - && !isOkToBreakBlock(braceTypeStack->back())) - return; // true; - - // make sure the line begins with a brace - size_t lastText = formattedLine.find_last_not_of(" \t"); - if (lastText == string::npos || formattedLine[lastText] != '{') - return; // false; - - // make sure the brace is broken - if (formattedLine.find_first_not_of(" \t{") != string::npos) - return; // false; - - if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE)) - return; // false; - - bool extraIndent = false; - bool extraHalfIndent = false; - isInLineBreak = true; - - // cannot attach a class modifier without indent-classes - if (isCStyle() - && isCharPotentialHeader(currentLine, charNum) - && (isBraceType(braceTypeStack->back(), CLASS_TYPE) - || (isBraceType(braceTypeStack->back(), STRUCT_TYPE) - && isInIndentableStruct))) - { - if (findKeyword(currentLine, charNum, AS_PUBLIC) - || findKeyword(currentLine, charNum, AS_PRIVATE) - || findKeyword(currentLine, charNum, AS_PROTECTED)) - { - if (getModifierIndent()) - extraHalfIndent = true; - else if (!getClassIndent()) - return; // false; - } - else if (getClassIndent()) - extraIndent = true; - } - - // cannot attach a 'case' statement without indent-switches - if (!getSwitchIndent() - && isCharPotentialHeader(currentLine, charNum) - && (findKeyword(currentLine, charNum, AS_CASE) - || findKeyword(currentLine, charNum, AS_DEFAULT))) - return; // false; - - // extra indent for switch statements - if (getSwitchIndent() - && !preBraceHeaderStack->empty() - && preBraceHeaderStack->back() == &AS_SWITCH - && (isLegalNameChar(currentChar) - && !findKeyword(currentLine, charNum, AS_CASE))) - extraIndent = true; - - isInLineBreak = false; - // remove for extra whitespace - if (formattedLine.length() > lastText + 1 - && formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos) - formattedLine.erase(lastText + 1); - - if (extraHalfIndent) - { - int indentLength_ = getIndentLength(); - runInIndentChars = indentLength_ / 2; - formattedLine.append(runInIndentChars - 1, ' '); - } - else if (getForceTabIndentation() && getIndentLength() != getTabLength()) - { - // insert the space indents - string indent; - int indentLength_ = getIndentLength(); - int tabLength_ = getTabLength(); - indent.append(indentLength_, ' '); - if (extraIndent) - indent.append(indentLength_, ' '); - // replace spaces indents with tab indents - size_t tabCount = indent.length() / tabLength_; // truncate extra spaces - indent.replace(0U, tabCount * tabLength_, tabCount, '\t'); - runInIndentChars = indentLength_; - if (indent[0] == ' ') // allow for brace - indent.erase(0, 1); - formattedLine.append(indent); - } - else if (getIndentString() == "\t") - { - appendChar('\t', false); - runInIndentChars = 2; // one for { and one for tab - if (extraIndent) - { - appendChar('\t', false); - runInIndentChars++; - } - } - else // spaces - { - int indentLength_ = getIndentLength(); - formattedLine.append(indentLength_ - 1, ' '); - runInIndentChars = indentLength_; - if (extraIndent) - { - formattedLine.append(indentLength_, ' '); - runInIndentChars += indentLength_; - } - } - isInBraceRunIn = true; -} - -/** - * remove whitespace and add indentation for an array run-in. - */ -void ASFormatter::formatArrayRunIn() -{ - assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE)); - - // make sure the brace is broken - if (formattedLine.find_first_not_of(" \t{") != string::npos) - return; - - size_t lastText = formattedLine.find_last_not_of(" \t"); - if (lastText == string::npos || formattedLine[lastText] != '{') - return; - - // check for extra whitespace - if (formattedLine.length() > lastText + 1 - && formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos) - formattedLine.erase(lastText + 1); - - if (getIndentString() == "\t") - { - appendChar('\t', false); - runInIndentChars = 2; // one for { and one for tab - } - else - { - int indent = getIndentLength(); - formattedLine.append(indent - 1, ' '); - runInIndentChars = indent; - } - isInBraceRunIn = true; - isInLineBreak = false; -} - -/** - * delete a braceTypeStack vector object - * BraceTypeStack did not work with the DeleteContainer template - */ -void ASFormatter::deleteContainer(vector*& container) -{ - if (container != nullptr) - { - container->clear(); - delete (container); - container = nullptr; - } -} - -/** - * delete a vector object - * T is the type of vector - * used for all vectors except braceTypeStack - */ -template -void ASFormatter::deleteContainer(T& container) -{ - if (container != nullptr) - { - container->clear(); - delete (container); - container = nullptr; - } -} - -/** - * initialize a braceType vector object - * braceType did not work with the DeleteContainer template - */ -void ASFormatter::initContainer(vector*& container, vector* value) -{ - if (container != nullptr) - deleteContainer(container); - container = value; -} - -/** - * initialize a vector object - * T is the type of vector - * used for all vectors except braceTypeStack - */ -template -void ASFormatter::initContainer(T& container, T value) -{ - // since the ASFormatter object is never deleted, - // the existing vectors must be deleted before creating new ones - if (container != nullptr) - deleteContainer(container); - container = value; -} - -/** - * convert a tab to spaces. - * charNum points to the current character to convert to spaces. - * tabIncrementIn is the increment that must be added for tab indent characters - * to get the correct column for the current tab. - * replaces the tab in currentLine with the required number of spaces. - * replaces the value of currentChar. - */ -void ASFormatter::convertTabToSpaces() -{ - assert(currentChar == '\t'); - - // do NOT replace if in quotes - if (isInQuote || isInQuoteContinuation) - return; - - size_t tabSize = getTabLength(); - size_t numSpaces = tabSize - ((tabIncrementIn + charNum) % tabSize); - currentLine.replace(charNum, 1, numSpaces, ' '); - currentChar = currentLine[charNum]; -} - -/** -* is it ok to break this block? -*/ -bool ASFormatter::isOkToBreakBlock(BraceType braceType) const -{ - // Actually, there should not be an ARRAY_TYPE brace here. - // But this will avoid breaking a one line block when there is. - // Otherwise they will be formatted differently on consecutive runs. - if (isBraceType(braceType, ARRAY_TYPE) - && isBraceType(braceType, SINGLE_LINE_TYPE)) - return false; - if (isBraceType(braceType, COMMAND_TYPE) - && isBraceType(braceType, EMPTY_BLOCK_TYPE)) - return false; - if (!isBraceType(braceType, SINGLE_LINE_TYPE) - || isBraceType(braceType, BREAK_BLOCK_TYPE) - || shouldBreakOneLineBlocks) - return true; - return false; -} - -/** -* check if a sharp header is a paren or non-paren header -*/ -bool ASFormatter::isSharpStyleWithParen(const string* header) const -{ - return (isSharpStyle() && peekNextChar() == '(' - && (header == &AS_CATCH - || header == &AS_DELEGATE)); -} - -/** - * Check for a following header when a comment is reached. - * firstLine must contain the start of the comment. - * return value is a pointer to the header or nullptr. - */ -const string* ASFormatter::checkForHeaderFollowingComment(const string& firstLine) const -{ - assert(isInComment || isInLineComment); - assert(shouldBreakElseIfs || shouldBreakBlocks || isInSwitchStatement()); - // look ahead to find the next non-comment text - bool endOnEmptyLine = (currentHeader == nullptr); - if (isInSwitchStatement()) - endOnEmptyLine = false; - string nextText = peekNextText(firstLine, endOnEmptyLine); - - if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0)) - return nullptr; - - return ASBase::findHeader(nextText, 0, headers); -} - -/** - * process preprocessor statements. - * charNum should be the index of the #. - * - * delete braceTypeStack entries added by #if if a #else is found. - * prevents double entries in the braceTypeStack. - */ -void ASFormatter::processPreprocessor() -{ - assert(currentChar == '#'); - - const size_t preproc = currentLine.find_first_not_of(" \t", charNum + 1); - - if (preproc == string::npos) - return; - - if (currentLine.compare(preproc, 2, "if") == 0) - { - preprocBraceTypeStackSize = braceTypeStack->size(); - } - else if (currentLine.compare(preproc, 4, "else") == 0) - { - // delete stack entries added in #if - // should be replaced by #else - if (preprocBraceTypeStackSize > 0) - { - int addedPreproc = braceTypeStack->size() - preprocBraceTypeStackSize; - for (int i = 0; i < addedPreproc; i++) - braceTypeStack->pop_back(); - } - } - else if (currentLine.compare(preproc, 7, "include") == 0) - { - isInPreprocessorInclude = true; - } - else if (currentLine.compare(preproc, 6, "define") == 0) - isInPreprocessorDefineDef = true; -} - -/** - * determine if the next line starts a comment - * and a header follows the comment or comments. - */ -bool ASFormatter::commentAndHeaderFollows() -{ - // called ONLY IF shouldDeleteEmptyLines and shouldBreakBlocks are TRUE. - assert(shouldDeleteEmptyLines && shouldBreakBlocks); - - // is the next line a comment - auto stream = make_shared(sourceIterator); - if (!stream->hasMoreLines()) - return false; - string nextLine_ = stream->peekNextLine(); - size_t firstChar = nextLine_.find_first_not_of(" \t"); - if (firstChar == string::npos - || !(nextLine_.compare(firstChar, 2, "//") == 0 - || nextLine_.compare(firstChar, 2, "/*") == 0)) - return false; - - // find the next non-comment text, and reset - string nextText = peekNextText(nextLine_, false, stream); - if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0)) - return false; - - const string* newHeader = ASBase::findHeader(nextText, 0, headers); - - if (newHeader == nullptr) - return false; - - // if a closing header, reset break unless break is requested - if (isClosingHeader(newHeader) && !shouldBreakClosingHeaderBlocks) - { - isAppendPostBlockEmptyLineRequested = false; - return false; - } - - return true; -} - -/** - * determine if a brace should be attached or broken - * uses braces in the braceTypeStack - * the last brace in the braceTypeStack is the one being formatted - * returns true if the brace should be broken - */ -bool ASFormatter::isCurrentBraceBroken() const -{ - assert(braceTypeStack->size() > 1); - - bool breakBrace = false; - size_t stackEnd = braceTypeStack->size() - 1; - - // check brace modifiers - if (shouldAttachExternC - && isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE)) - { - return false; - } - if (shouldAttachNamespace - && isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE)) - { - return false; - } - if (shouldAttachClass - && (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE) - || isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE))) - { - return false; - } - if (shouldAttachInline - && isCStyle() // for C++ only - && braceFormatMode != RUN_IN_MODE - && !(currentLineBeginsWithBrace && peekNextChar() == '/') - && isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE)) - { - size_t i; - for (i = 1; i < braceTypeStack->size(); i++) - if (isBraceType((*braceTypeStack)[i], CLASS_TYPE) - || isBraceType((*braceTypeStack)[i], STRUCT_TYPE)) - return false; - } - - // check braces - if (isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE)) - { - if (currentLineBeginsWithBrace - || braceFormatMode == RUN_IN_MODE) - breakBrace = true; - } - else if (braceFormatMode == NONE_MODE) - { - if (currentLineBeginsWithBrace - && currentLineFirstBraceNum == (size_t) charNum) - breakBrace = true; - } - else if (braceFormatMode == BREAK_MODE || braceFormatMode == RUN_IN_MODE) - { - breakBrace = true; - } - else if (braceFormatMode == LINUX_MODE) - { - // break a namespace - if (isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE)) - { - if (formattingStyle != STYLE_STROUSTRUP - && formattingStyle != STYLE_MOZILLA - && formattingStyle != STYLE_WEBKIT) - breakBrace = true; - } - // break a class or interface - else if (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE) - || isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE)) - { - if (formattingStyle != STYLE_STROUSTRUP - && formattingStyle != STYLE_WEBKIT) - breakBrace = true; - } - // break a struct if mozilla - an enum is processed as an array brace - else if (isBraceType((*braceTypeStack)[stackEnd], STRUCT_TYPE)) - { - if (formattingStyle == STYLE_MOZILLA) - breakBrace = true; - } - // break the first brace if a function - else if (isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE)) - { - if (stackEnd == 1) - { - breakBrace = true; - } - else if (stackEnd > 1) - { - // break the first brace after these if a function - if (isBraceType((*braceTypeStack)[stackEnd - 1], NAMESPACE_TYPE) - || isBraceType((*braceTypeStack)[stackEnd - 1], CLASS_TYPE) - || isBraceType((*braceTypeStack)[stackEnd - 1], ARRAY_TYPE) - || isBraceType((*braceTypeStack)[stackEnd - 1], STRUCT_TYPE) - || isBraceType((*braceTypeStack)[stackEnd - 1], EXTERN_TYPE)) - { - breakBrace = true; - } - } - } - } - return breakBrace; -} - -/** - * format comment body - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::formatCommentBody() -{ - assert(isInComment); - - // append the comment - while (charNum < (int) currentLine.length()) - { - currentChar = currentLine[charNum]; - if (isSequenceReached("*/")) - { - formatCommentCloser(); - break; - } - if (currentChar == '\t' && shouldConvertTabs) - convertTabToSpaces(); - appendCurrentChar(); - ++charNum; - } - if (shouldStripCommentPrefix) - stripCommentPrefix(); -} - -/** - * format a comment opener - * the comment opener will be appended to the current formattedLine or a new formattedLine as necessary - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::formatCommentOpener() -{ - assert(isSequenceReached("/*")); - - isInComment = isInCommentStartLine = true; - isImmediatelyPostLineComment = false; - if (previousNonWSChar == '}') - resetEndOfStatement(); - - // Check for a following header. - // For speed do not check multiple comment lines more than once. - // For speed do not check shouldBreakBlocks if previous line is empty, a comment, or a '{'. - const string* followingHeader = nullptr; - if ((doesLineStartComment - && !isImmediatelyPostCommentOnly - && isBraceType(braceTypeStack->back(), COMMAND_TYPE)) - && (shouldBreakElseIfs - || isInSwitchStatement() - || (shouldBreakBlocks - && !isImmediatelyPostEmptyLine - && previousCommandChar != '{'))) - followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum)); - - if (spacePadNum != 0 && !isInLineBreak) - adjustComments(); - formattedLineCommentNum = formattedLine.length(); - - // must be done BEFORE appendSequence - if (previousCommandChar == '{' - && !isImmediatelyPostComment - && !isImmediatelyPostLineComment) - { - if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE)) - { - // namespace run-in is always broken. - isInLineBreak = true; - } - else if (braceFormatMode == NONE_MODE) - { - // should a run-in statement be attached? - if (currentLineBeginsWithBrace) - formatRunIn(); - } - else if (braceFormatMode == ATTACH_MODE) - { - // if the brace was not attached? - if (formattedLine.length() > 0 && formattedLine[0] == '{' - && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)) - isInLineBreak = true; - } - else if (braceFormatMode == RUN_IN_MODE) - { - // should a run-in statement be attached? - if (formattedLine.length() > 0 && formattedLine[0] == '{') - formatRunIn(); - } - } - else if (!doesLineStartComment) - noTrimCommentContinuation = true; - - // ASBeautifier needs to know the following statements - if (shouldBreakElseIfs && followingHeader == &AS_ELSE) - elseHeaderFollowsComments = true; - if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT) - caseHeaderFollowsComments = true; - - // appendSequence will write the previous line - appendSequence(AS_OPEN_COMMENT); - goForward(1); - - // must be done AFTER appendSequence - - // Break before the comment if a header follows the line comment. - // But not break if previous line is empty, a comment, or a '{'. - if (shouldBreakBlocks - && followingHeader != nullptr - && !isImmediatelyPostEmptyLine - && previousCommandChar != '{') - { - if (isClosingHeader(followingHeader)) - { - if (!shouldBreakClosingHeaderBlocks) - isPrependPostBlockEmptyLineRequested = false; - } - // if an opening header, break before the comment - else - isPrependPostBlockEmptyLineRequested = true; - } - - if (previousCommandChar == '}') - currentHeader = nullptr; -} - -/** - * format a comment closer - * the comment closer will be appended to the current formattedLine - */ -void ASFormatter::formatCommentCloser() -{ - assert(isSequenceReached("*/")); - isInComment = false; - noTrimCommentContinuation = false; - isImmediatelyPostComment = true; - appendSequence(AS_CLOSE_COMMENT); - goForward(1); - if (doesLineStartComment - && (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos)) - lineEndsInCommentOnly = true; - if (peekNextChar() == '}' - && previousCommandChar != ';' - && !isBraceType(braceTypeStack->back(), ARRAY_TYPE) - && !isInPreprocessor - && isOkToBreakBlock(braceTypeStack->back())) - { - isInLineBreak = true; - shouldBreakLineAtNextChar = true; - } -} - -/** - * format a line comment body - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::formatLineCommentBody() -{ - assert(isInLineComment); - - // append the comment - while (charNum < (int) currentLine.length()) -// && !isLineReady // commented out in release 2.04, unnecessary - { - currentChar = currentLine[charNum]; - if (currentChar == '\t' && shouldConvertTabs) - convertTabToSpaces(); - appendCurrentChar(); - ++charNum; - } - - // explicitly break a line when a line comment's end is found. - if (charNum == (int) currentLine.length()) - { - isInLineBreak = true; - isInLineComment = false; - isImmediatelyPostLineComment = true; - currentChar = 0; //make sure it is a neutral char. - } -} - -/** - * format a line comment opener - * the line comment opener will be appended to the current formattedLine or a new formattedLine as necessary - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::formatLineCommentOpener() -{ - assert(isSequenceReached("//")); - - if ((int) currentLine.length() > charNum + 2 - && currentLine[charNum + 2] == '\xf2') // check for windows line marker - isAppendPostBlockEmptyLineRequested = false; - - isInLineComment = true; - isCharImmediatelyPostComment = false; - if (previousNonWSChar == '}') - resetEndOfStatement(); - - // Check for a following header. - // For speed do not check multiple comment lines more than once. - // For speed do not check shouldBreakBlocks if previous line is empty, a comment, or a '{'. - const string* followingHeader = nullptr; - if ((lineIsLineCommentOnly - && !isImmediatelyPostCommentOnly - && isBraceType(braceTypeStack->back(), COMMAND_TYPE)) - && (shouldBreakElseIfs - || isInSwitchStatement() - || (shouldBreakBlocks - && !isImmediatelyPostEmptyLine - && previousCommandChar != '{'))) - followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum)); - - // do not indent if in column 1 or 2 - // or in a namespace before the opening brace - if ((!shouldIndentCol1Comments && !lineCommentNoIndent) - || foundNamespaceHeader) - { - if (charNum == 0) - lineCommentNoIndent = true; - else if (charNum == 1 && currentLine[0] == ' ') - lineCommentNoIndent = true; - } - // move comment if spaces were added or deleted - if (!lineCommentNoIndent && spacePadNum != 0 && !isInLineBreak) - adjustComments(); - formattedLineCommentNum = formattedLine.length(); - - // must be done BEFORE appendSequence - // check for run-in statement - if (previousCommandChar == '{' - && !isImmediatelyPostComment - && !isImmediatelyPostLineComment) - { - if (braceFormatMode == NONE_MODE) - { - if (currentLineBeginsWithBrace) - formatRunIn(); - } - else if (braceFormatMode == RUN_IN_MODE) - { - if (!lineCommentNoIndent) - formatRunIn(); - else - isInLineBreak = true; - } - else if (braceFormatMode == BREAK_MODE) - { - if (formattedLine.length() > 0 && formattedLine[0] == '{') - isInLineBreak = true; - } - else - { - if (currentLineBeginsWithBrace) - isInLineBreak = true; - } - } - - // ASBeautifier needs to know the following statements - if (shouldBreakElseIfs && followingHeader == &AS_ELSE) - elseHeaderFollowsComments = true; - if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT) - caseHeaderFollowsComments = true; - - // appendSequence will write the previous line - appendSequence(AS_OPEN_LINE_COMMENT); - goForward(1); - - // must be done AFTER appendSequence - - // Break before the comment if a header follows the line comment. - // But do not break if previous line is empty, a comment, or a '{'. - if (shouldBreakBlocks - && followingHeader != nullptr - && !isImmediatelyPostEmptyLine - && previousCommandChar != '{') - { - if (isClosingHeader(followingHeader)) - { - if (!shouldBreakClosingHeaderBlocks) - isPrependPostBlockEmptyLineRequested = false; - } - // if an opening header, break before the comment - else - isPrependPostBlockEmptyLineRequested = true; - } - - if (previousCommandChar == '}') - currentHeader = nullptr; - - // if tabbed input don't convert the immediately following tabs to spaces - if (getIndentString() == "\t" && lineCommentNoIndent) - { - while (charNum + 1 < (int) currentLine.length() - && currentLine[charNum + 1] == '\t') - { - currentChar = currentLine[++charNum]; - appendCurrentChar(); - } - } - - // explicitly break a line when a line comment's end is found. - if (charNum + 1 == (int) currentLine.length()) - { - isInLineBreak = true; - isInLineComment = false; - isImmediatelyPostLineComment = true; - currentChar = 0; //make sure it is a neutral char. - } -} - -/** - * format quote body - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::formatQuoteBody() -{ - assert(isInQuote); - - if (isSpecialChar) - { - isSpecialChar = false; - } - else if (currentChar == '\\' && !isInVerbatimQuote) - { - if (peekNextChar() == ' ') // is this '\' at end of line - haveLineContinuationChar = true; - else - isSpecialChar = true; - } - else if (isInVerbatimQuote && currentChar == '"') - { - if (isCStyle()) - { - string delim = ')' + verbatimDelimiter; - int delimStart = charNum - delim.length(); - if (delimStart > 0 && currentLine.substr(delimStart, delim.length()) == delim) - { - isInQuote = false; - isInVerbatimQuote = false; - } - } - else if (isSharpStyle()) - { - if ((int) currentLine.length() > charNum + 1 - && currentLine[charNum + 1] == '"') // check consecutive quotes - { - appendSequence("\"\""); - goForward(1); - return; - } - isInQuote = false; - isInVerbatimQuote = false; - } - } - else if (quoteChar == currentChar) - { - isInQuote = false; - } - - appendCurrentChar(); - - // append the text to the ending quoteChar or an escape sequence - // tabs in quotes are NOT changed by convert-tabs - if (isInQuote && currentChar != '\\') - { - while (charNum + 1 < (int) currentLine.length() - && currentLine[charNum + 1] != quoteChar - && currentLine[charNum + 1] != '\\') - { - currentChar = currentLine[++charNum]; - appendCurrentChar(); - } - } - if (charNum + 1 >= (int) currentLine.length() - && currentChar != '\\' - && !isInVerbatimQuote) - isInQuote = false; // missing closing quote -} - -/** - * format a quote opener - * the quote opener will be appended to the current formattedLine or a new formattedLine as necessary - * the calling function should have a continue statement after calling this method - */ -void ASFormatter::formatQuoteOpener() -{ - assert(currentChar == '"' - || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum))); - - isInQuote = true; - quoteChar = currentChar; - if (isCStyle() && previousChar == 'R') - { - int parenPos = currentLine.find('(', charNum); - if (parenPos != -1) - { - isInVerbatimQuote = true; - verbatimDelimiter = currentLine.substr(charNum + 1, parenPos - charNum - 1); - } - } - else if (isSharpStyle() && previousChar == '@') - isInVerbatimQuote = true; - - // a quote following a brace is an array - if (previousCommandChar == '{' - && !isImmediatelyPostComment - && !isImmediatelyPostLineComment - && isNonInStatementArray - && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE) - && !isWhiteSpace(peekNextChar())) - { - if (braceFormatMode == NONE_MODE) - { - if (currentLineBeginsWithBrace) - formatRunIn(); - } - else if (braceFormatMode == RUN_IN_MODE) - { - formatRunIn(); - } - else if (braceFormatMode == BREAK_MODE) - { - if (formattedLine.length() > 0 && formattedLine[0] == '{') - isInLineBreak = true; - } - else - { - if (currentLineBeginsWithBrace) - isInLineBreak = true; - } - } - previousCommandChar = ' '; - appendCurrentChar(); -} - -/** - * get the next line comment adjustment that results from breaking a closing brace. - * the brace must be on the same line as the closing header. - * i.e "} else" changed to "} else". - */ -int ASFormatter::getNextLineCommentAdjustment() -{ - assert(foundClosingHeader && previousNonWSChar == '}'); - if (charNum < 1) // "else" is in column 1 - return 0; - size_t lastBrace = currentLine.rfind('}', charNum - 1); - if (lastBrace != string::npos) - return (lastBrace - charNum); // return a negative number - return 0; -} - -// for console build only -LineEndFormat ASFormatter::getLineEndFormat() const -{ - return lineEnd; -} - -/** - * get the current line comment adjustment that results from attaching - * a closing header to a closing brace. - * the brace must be on the line previous to the closing header. - * the adjustment is 2 chars, one for the brace and one for the space. - * i.e "} else" changed to "} else". - */ -int ASFormatter::getCurrentLineCommentAdjustment() -{ - assert(foundClosingHeader && previousNonWSChar == '}'); - if (charNum < 1) - return 2; - size_t lastBrace = currentLine.rfind('}', charNum - 1); - if (lastBrace == string::npos) - return 2; - return 0; -} - -/** - * get the previous word on a line - * the argument 'currPos' must point to the current position. - * - * @return is the previous word or an empty string if none found. - */ -string ASFormatter::getPreviousWord(const string& line, int currPos) const -{ - // get the last legal word (may be a number) - if (currPos == 0) - return string(); - - size_t end = line.find_last_not_of(" \t", currPos - 1); - if (end == string::npos || !isLegalNameChar(line[end])) - return string(); - - int start; // start of the previous word - for (start = end; start > -1; start--) - { - if (!isLegalNameChar(line[start]) || line[start] == '.') - break; - } - start++; - - return (line.substr(start, end - start + 1)); -} - -/** - * check if a line break is needed when a closing brace - * is followed by a closing header. - * the break depends on the braceFormatMode and other factors. - */ -void ASFormatter::isLineBreakBeforeClosingHeader() -{ - assert(foundClosingHeader && previousNonWSChar == '}'); - - if (currentHeader == &AS_WHILE && shouldAttachClosingWhile) - { - appendClosingHeader(); - return; - } - - if (braceFormatMode == BREAK_MODE - || braceFormatMode == RUN_IN_MODE - || attachClosingBraceMode) - { - isInLineBreak = true; - } - else if (braceFormatMode == NONE_MODE) - { - if (shouldBreakClosingHeaderBraces - || getBraceIndent() || getBlockIndent()) - { - isInLineBreak = true; - } - else - { - appendSpacePad(); - // is closing brace broken? - size_t i = currentLine.find_first_not_of(" \t"); - if (i != string::npos && currentLine[i] == '}') - isInLineBreak = false; - - if (shouldBreakBlocks) - isAppendPostBlockEmptyLineRequested = false; - } - } - // braceFormatMode == ATTACH_MODE, LINUX_MODE - else - { - if (shouldBreakClosingHeaderBraces - || getBraceIndent() || getBlockIndent()) - { - isInLineBreak = true; - } - else - { - appendClosingHeader(); - if (shouldBreakBlocks) - isAppendPostBlockEmptyLineRequested = false; - } - } -} - -/** - * Append a closing header to the previous closing brace, if possible - */ -void ASFormatter::appendClosingHeader() -{ - // if a blank line does not precede this - // or last line is not a one line block, attach header - bool previousLineIsEmpty = isEmptyLine(formattedLine); - int previousLineIsOneLineBlock = 0; - size_t firstBrace = findNextChar(formattedLine, '{'); - if (firstBrace != string::npos) - previousLineIsOneLineBlock = isOneLineBlockReached(formattedLine, firstBrace); - if (!previousLineIsEmpty - && previousLineIsOneLineBlock == 0) - { - isInLineBreak = false; - appendSpacePad(); - spacePadNum = 0; // don't count as comment padding - } -} - -/** - * Add braces to a single line statement following a header. - * braces are not added if the proper conditions are not met. - * braces are added to the currentLine. - */ -bool ASFormatter::addBracesToStatement() -{ - assert(isImmediatelyPostHeader); - - if (currentHeader != &AS_IF - && currentHeader != &AS_ELSE - && currentHeader != &AS_FOR - && currentHeader != &AS_WHILE - && currentHeader != &AS_DO - && currentHeader != &AS_FOREACH - && currentHeader != &AS_QFOREACH - && currentHeader != &AS_QFOREVER - && currentHeader != &AS_FOREVER) - return false; - - if (currentHeader == &AS_WHILE && foundClosingHeader) // do-while - return false; - - // do not brace an empty statement - if (currentChar == ';') - return false; - - // do not add if a header follows - if (isCharPotentialHeader(currentLine, charNum)) - if (findHeader(headers) != nullptr) - return false; - - // find the next semi-colon - size_t nextSemiColon = charNum; - if (currentChar != ';') - nextSemiColon = findNextChar(currentLine, ';', charNum + 1); - if (nextSemiColon == string::npos) - return false; - - // add closing brace before changing the line length - if (nextSemiColon == currentLine.length() - 1) - currentLine.append(" }"); - else - currentLine.insert(nextSemiColon + 1, " }"); - // add opening brace - currentLine.insert(charNum, "{ "); - assert(computeChecksumIn("{}")); - currentChar = '{'; - if ((int) currentLine.find_first_not_of(" \t") == charNum) - currentLineBeginsWithBrace = true; - // remove extra spaces - if (!shouldAddOneLineBraces) - { - size_t lastText = formattedLine.find_last_not_of(" \t"); - if ((formattedLine.length() - 1) - lastText > 1) - formattedLine.erase(lastText + 1); - } - return true; -} - -/** - * Remove braces from a single line statement following a header. - * braces are not removed if the proper conditions are not met. - * The first brace is replaced by a space. - */ -bool ASFormatter::removeBracesFromStatement() -{ - assert(isImmediatelyPostHeader); - assert(currentChar == '{'); - - if (currentHeader != &AS_IF - && currentHeader != &AS_ELSE - && currentHeader != &AS_FOR - && currentHeader != &AS_WHILE - && currentHeader != &AS_FOREACH) - return false; - - if (currentHeader == &AS_WHILE && foundClosingHeader) // do-while - return false; - - bool isFirstLine = true; - string nextLine_; - // leave nextLine_ empty if end of line comment follows - if (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace) - nextLine_ = currentLine.substr(charNum + 1); - size_t nextChar = 0; - - // find the first non-blank text - ASPeekStream stream(sourceIterator); - while (stream.hasMoreLines() || isFirstLine) - { - if (isFirstLine) - isFirstLine = false; - else - { - nextLine_ = stream.peekNextLine(); - nextChar = 0; - } - - nextChar = nextLine_.find_first_not_of(" \t", nextChar); - if (nextChar != string::npos) - break; - } - if (!stream.hasMoreLines()) - return false; - - // don't remove if comments or a header follow the brace - if ((nextLine_.compare(nextChar, 2, "/*") == 0) - || (nextLine_.compare(nextChar, 2, "//") == 0) - || (isCharPotentialHeader(nextLine_, nextChar) - && ASBase::findHeader(nextLine_, nextChar, headers) != nullptr)) - return false; - - // find the next semi-colon - size_t nextSemiColon = nextChar; - if (nextLine_[nextChar] != ';') - nextSemiColon = findNextChar(nextLine_, ';', nextChar + 1); - if (nextSemiColon == string::npos) - return false; - - // find the closing brace - isFirstLine = true; - nextChar = nextSemiColon + 1; - while (stream.hasMoreLines() || isFirstLine) - { - if (isFirstLine) - isFirstLine = false; - else - { - nextLine_ = stream.peekNextLine(); - nextChar = 0; - } - nextChar = nextLine_.find_first_not_of(" \t", nextChar); - if (nextChar != string::npos) - break; - } - if (nextLine_.length() == 0 || nextLine_[nextChar] != '}') - return false; - - // remove opening brace - currentLine[charNum] = currentChar = ' '; - assert(adjustChecksumIn(-'{')); - return true; -} - -/** - * Find the next character that is not in quotes or a comment. - * - * @param line the line to be searched. - * @param searchChar the char to find. - * @param searchStart the start position on the line (default is 0). - * @return the position on the line or string::npos if not found. - */ -size_t ASFormatter::findNextChar(const string& line, char searchChar, int searchStart /*0*/) const -{ - // find the next searchChar - size_t i; - for (i = searchStart; i < line.length(); i++) - { - if (line.compare(i, 2, "//") == 0) - return string::npos; - if (line.compare(i, 2, "/*") == 0) - { - size_t endComment = line.find("*/", i + 2); - if (endComment == string::npos) - return string::npos; - i = endComment + 2; - if (i >= line.length()) - return string::npos; - } - if (line[i] == '"' - || (line[i] == '\'' && !isDigitSeparator(line, i))) - { - char quote = line[i]; - while (i < line.length()) - { - size_t endQuote = line.find(quote, i + 1); - if (endQuote == string::npos) - return string::npos; - i = endQuote; - if (line[endQuote - 1] != '\\') // check for '\"' - break; - if (line[endQuote - 2] == '\\') // check for '\\' - break; - } - } - - if (line[i] == searchChar) - break; - - // for now don't process C# 'delegate' braces - // do this last in case the search char is a '{' - if (line[i] == '{') - return string::npos; - } - if (i >= line.length()) // didn't find searchChar - return string::npos; - - return i; -} - -/** - * Find split point for break/attach return type. - */ -void ASFormatter::findReturnTypeSplitPoint(const string& firstLine) -{ - assert((isBraceType(braceTypeStack->back(), NULL_TYPE) - || isBraceType(braceTypeStack->back(), DEFINITION_TYPE))); - assert(shouldBreakReturnType || shouldBreakReturnTypeDecl - || shouldAttachReturnType || shouldAttachReturnTypeDecl); - - bool isFirstLine = true; - bool isInComment_ = false; - bool isInQuote_ = false; - bool foundSplitPoint = false; - bool isAlreadyBroken = false; - char quoteChar_ = ' '; - char currNonWSChar = ' '; - char prevNonWSChar = ' '; - size_t parenCount = 0; - size_t squareCount = 0; - size_t angleCount = 0; - size_t breakLineNum = 0; - size_t breakCharNum = string::npos; - string line = firstLine; - - // Process the lines until a ';' or '{'. - ASPeekStream stream(sourceIterator); - while (stream.hasMoreLines() || isFirstLine) - { - if (isFirstLine) - isFirstLine = false; - else - { - if (isInQuote_) - return; - line = stream.peekNextLine(); - if (!foundSplitPoint) - ++breakLineNum; - } - size_t firstCharNum = line.find_first_not_of(" \t"); - if (firstCharNum == string::npos) - continue; - if (line[firstCharNum] == '#') - { - // don't attach to a preprocessor - if (shouldAttachReturnType || shouldAttachReturnTypeDecl) - return; - continue; - } - // parse the line - for (size_t i = 0; i < line.length(); i++) - { - if (!isWhiteSpace(line[i])) - { - prevNonWSChar = currNonWSChar; - currNonWSChar = line[i]; - } - else if (line[i] == '\t' && shouldConvertTabs) - { - size_t tabSize = getTabLength(); - size_t numSpaces = tabSize - ((tabIncrementIn + i) % tabSize); - line.replace(i, 1, numSpaces, ' '); - currentChar = line[i]; - } - if (line.compare(i, 2, "/*") == 0) - isInComment_ = true; - if (isInComment_) - { - if (line.compare(i, 2, "*/") == 0) - { - isInComment_ = false; - ++i; - } - continue; - } - if (line[i] == '\\') - { - ++i; - continue; - } - - if (isInQuote_) - { - if (line[i] == quoteChar_) - isInQuote_ = false; - continue; - } - - if (line[i] == '"' - || (line[i] == '\'' && !isDigitSeparator(line, i))) - { - isInQuote_ = true; - quoteChar_ = line[i]; - continue; - } - if (line.compare(i, 2, "//") == 0) - { - i = line.length(); - continue; - } - // not in quote or comment - if (!foundSplitPoint) - { - if (line[i] == '<') - { - ++angleCount; - continue; - } - if (line[i] == '>') - { - if (angleCount) - --angleCount; - if (!angleCount) - { - size_t nextCharNum = line.find_first_not_of(" \t*&", i + 1); - if (nextCharNum == string::npos) - { - breakCharNum = string::npos; - continue; - } - if (line[nextCharNum] != ':') // scope operator - breakCharNum = nextCharNum; - } - continue; - } - if (angleCount) - continue; - if (line[i] == '[') - { - ++squareCount; - continue; - } - if (line[i] == ']') - { - if (squareCount) - --squareCount; - continue; - } - // an assignment before the parens is not a function - if (line[i] == '=') - return; - if (isWhiteSpace(line[i]) || line[i] == '*' || line[i] == '&') - { - size_t nextNum = line.find_first_not_of(" \t", i + 1); - if (nextNum == string::npos) - breakCharNum = string::npos; - else - { - if (line.length() > nextNum + 1 - && line[nextNum] == ':' && line[nextNum + 1] == ':') - i = --nextNum; - else if (line[nextNum] != '(') - breakCharNum = string::npos; - } - continue; - } - if ((isLegalNameChar(line[i]) || line[i] == '~') - && breakCharNum == string::npos) - { - breakCharNum = i; - if (isLegalNameChar(line[i]) - && findKeyword(line, i, AS_OPERATOR)) - { - if (breakCharNum == firstCharNum) - isAlreadyBroken = true; - foundSplitPoint = true; - // find the operator, may be parens - size_t parenNum = - line.find_first_not_of(" \t", i + AS_OPERATOR.length()); - if (parenNum == string::npos) - return; - // find paren after the operator - parenNum = line.find('(', parenNum + 1); - if (parenNum == string::npos) - return; - i = --parenNum; - } - continue; - } - if (line[i] == ':' - && line.length() > i + 1 - && line[i + 1] == ':') - { - size_t nextCharNum = line.find_first_not_of(" \t:", i + 1); - if (nextCharNum == string::npos) - return; - - if (isLegalNameChar(line[nextCharNum]) - && findKeyword(line, nextCharNum, AS_OPERATOR)) - { - i = nextCharNum; - if (breakCharNum == firstCharNum) - isAlreadyBroken = true; - foundSplitPoint = true; - // find the operator, may be parens - size_t parenNum = - line.find_first_not_of(" \t", i + AS_OPERATOR.length()); - if (parenNum == string::npos) - return; - // find paren after the operator - parenNum = line.find('(', parenNum + 1); - if (parenNum == string::npos) - return; - i = --parenNum; - } - else - i = --nextCharNum; - continue; - } - if (line[i] == '(' && !squareCount) - { - // is line is already broken? - if (breakCharNum == firstCharNum && breakLineNum > 0) - isAlreadyBroken = true; - ++parenCount; - foundSplitPoint = true; - continue; - } - } - // end !foundSplitPoint - if (line[i] == '(') - { - // consecutive ')(' parens is probably a function pointer - if (prevNonWSChar == ')' && !parenCount) - return; - ++parenCount; - continue; - } - if (line[i] == ')') - { - if (parenCount) - --parenCount; - continue; - } - if (line[i] == '{') - { - if (shouldBreakReturnType && foundSplitPoint && !isAlreadyBroken) - { - methodBreakCharNum = breakCharNum; - methodBreakLineNum = breakLineNum; - } - if (shouldAttachReturnType && foundSplitPoint && isAlreadyBroken) - { - methodAttachCharNum = breakCharNum; - methodAttachLineNum = breakLineNum; - } - return; - } - if (line[i] == ';') - { - if (shouldBreakReturnTypeDecl && foundSplitPoint && !isAlreadyBroken) - { - methodBreakCharNum = breakCharNum; - methodBreakLineNum = breakLineNum; - } - if (shouldAttachReturnTypeDecl && foundSplitPoint && isAlreadyBroken) - { - methodAttachCharNum = breakCharNum; - methodAttachLineNum = breakLineNum; - } - return; - } - if (line[i] == '}') - return; - } // end of for loop - if (!foundSplitPoint) - breakCharNum = string::npos; - } // end of while loop -} - -/** - * Look ahead in the file to see if a struct has access modifiers. - * - * @param firstLine a reference to the line to indent. - * @param index the current line index. - * @return true if the struct has access modifiers. - */ -bool ASFormatter::isStructAccessModified(const string& firstLine, size_t index) const -{ - assert(firstLine[index] == '{'); - assert(isCStyle()); - - bool isFirstLine = true; - size_t braceCount = 1; - string nextLine_ = firstLine.substr(index + 1); - ASPeekStream stream(sourceIterator); - - // find the first non-blank text, bypassing all comments and quotes. - bool isInComment_ = false; - bool isInQuote_ = false; - char quoteChar_ = ' '; - while (stream.hasMoreLines() || isFirstLine) - { - if (isFirstLine) - isFirstLine = false; - else - nextLine_ = stream.peekNextLine(); - // parse the line - for (size_t i = 0; i < nextLine_.length(); i++) - { - if (isWhiteSpace(nextLine_[i])) - continue; - if (nextLine_.compare(i, 2, "/*") == 0) - isInComment_ = true; - if (isInComment_) - { - if (nextLine_.compare(i, 2, "*/") == 0) - { - isInComment_ = false; - ++i; - } - continue; - } - if (nextLine_[i] == '\\') - { - ++i; - continue; - } - - if (isInQuote_) - { - if (nextLine_[i] == quoteChar_) - isInQuote_ = false; - continue; - } - - if (nextLine_[i] == '"' - || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i))) - { - isInQuote_ = true; - quoteChar_ = nextLine_[i]; - continue; - } - if (nextLine_.compare(i, 2, "//") == 0) - { - i = nextLine_.length(); - continue; - } - // handle braces - if (nextLine_[i] == '{') - ++braceCount; - if (nextLine_[i] == '}') - --braceCount; - if (braceCount == 0) - return false; - // check for access modifiers - if (isCharPotentialHeader(nextLine_, i)) - { - if (findKeyword(nextLine_, i, AS_PUBLIC) - || findKeyword(nextLine_, i, AS_PRIVATE) - || findKeyword(nextLine_, i, AS_PROTECTED)) - return true; - string name = getCurrentWord(nextLine_, i); - i += name.length() - 1; - } - } // end of for loop - } // end of while loop - - return false; -} - -/** -* Look ahead in the file to see if a preprocessor block is indentable. -* -* @param firstLine a reference to the line to indent. -* @param index the current line index. -* @return true if the block is indentable. -*/ -bool ASFormatter::isIndentablePreprocessorBlock(const string& firstLine, size_t index) -{ - assert(firstLine[index] == '#'); - - bool isFirstLine = true; - bool isInIndentableBlock = false; - bool blockContainsBraces = false; - bool blockContainsDefineContinuation = false; - bool isInClassConstructor = false; - bool isPotentialHeaderGuard = false; // ifndef is first preproc statement - bool isPotentialHeaderGuard2 = false; // define is within the first preproc - int numBlockIndents = 0; - int lineParenCount = 0; - string nextLine_ = firstLine.substr(index); - auto stream = make_shared(sourceIterator); - - // find end of the block, bypassing all comments and quotes. - bool isInComment_ = false; - bool isInQuote_ = false; - char quoteChar_ = ' '; - while (stream->hasMoreLines() || isFirstLine) - { - if (isFirstLine) - isFirstLine = false; - else - nextLine_ = stream->peekNextLine(); - // parse the line - for (size_t i = 0; i < nextLine_.length(); i++) - { - if (isWhiteSpace(nextLine_[i])) - continue; - if (nextLine_.compare(i, 2, "/*") == 0) - isInComment_ = true; - if (isInComment_) - { - if (nextLine_.compare(i, 2, "*/") == 0) - { - isInComment_ = false; - ++i; - } - continue; - } - if (nextLine_[i] == '\\') - { - ++i; - continue; - } - if (isInQuote_) - { - if (nextLine_[i] == quoteChar_) - isInQuote_ = false; - continue; - } - - if (nextLine_[i] == '"' - || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i))) - { - isInQuote_ = true; - quoteChar_ = nextLine_[i]; - continue; - } - if (nextLine_.compare(i, 2, "//") == 0) - { - i = nextLine_.length(); - continue; - } - // handle preprocessor statement - if (nextLine_[i] == '#') - { - string preproc = ASBeautifier::extractPreprocessorStatement(nextLine_); - if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef - { - numBlockIndents += 1; - isInIndentableBlock = true; - // flag first preprocessor conditional for header include guard check - if (!processedFirstConditional) - { - processedFirstConditional = true; - isFirstPreprocConditional = true; - if (isNDefPreprocStatement(nextLine_, preproc)) - isPotentialHeaderGuard = true; - } - } - else if (preproc == "endif") - { - if (numBlockIndents > 0) - numBlockIndents -= 1; - // must exit BOTH loops - if (numBlockIndents == 0) - goto EndOfWhileLoop; - } - else if (preproc == "define") - { - if (nextLine_[nextLine_.length() - 1] == '\\') - blockContainsDefineContinuation = true; - // check for potential header include guards - else if (isPotentialHeaderGuard && numBlockIndents == 1) - isPotentialHeaderGuard2 = true; - } - i = nextLine_.length(); - continue; - } - // handle exceptions - if (nextLine_[i] == '{' || nextLine_[i] == '}') - blockContainsBraces = true; - else if (nextLine_[i] == '(') - ++lineParenCount; - else if (nextLine_[i] == ')') - --lineParenCount; - else if (nextLine_[i] == ':') - { - // check for '::' - if (nextLine_.length() > i + 1 && nextLine_[i + 1] == ':') - ++i; - else - isInClassConstructor = true; - } - // bypass unnecessary parsing - must exit BOTH loops - if (blockContainsBraces || isInClassConstructor || blockContainsDefineContinuation) - goto EndOfWhileLoop; - } // end of for loop, end of line - if (lineParenCount != 0) - break; - } // end of while loop -EndOfWhileLoop: - preprocBlockEnd = sourceIterator->tellg(); - if (preprocBlockEnd < 0) - preprocBlockEnd = sourceIterator->getStreamLength(); - if (blockContainsBraces - || isInClassConstructor - || blockContainsDefineContinuation - || lineParenCount != 0 - || numBlockIndents != 0) - isInIndentableBlock = false; - // find next executable instruction - // this WILL RESET the get pointer - string nextText = peekNextText("", false, stream); - // bypass header include guards - if (isFirstPreprocConditional) - { - isFirstPreprocConditional = false; - if (nextText.empty() && isPotentialHeaderGuard2) - { - isInIndentableBlock = false; - preprocBlockEnd = 0; - } - } - // this allows preprocessor blocks within this block to be indented - if (!isInIndentableBlock) - preprocBlockEnd = 0; - // peekReset() is done by previous peekNextText() - return isInIndentableBlock; -} - -bool ASFormatter::isNDefPreprocStatement(const string& nextLine_, const string& preproc) const -{ - if (preproc == "ifndef") - return true; - // check for '!defined' - if (preproc == "if") - { - size_t i = nextLine_.find('!'); - if (i == string::npos) - return false; - i = nextLine_.find_first_not_of(" \t", ++i); - if (i != string::npos && nextLine_.compare(i, 7, "defined") == 0) - return true; - } - return false; -} - -/** - * Check to see if this is an EXEC SQL statement. - * - * @param line a reference to the line to indent. - * @param index the current line index. - * @return true if the statement is EXEC SQL. - */ -bool ASFormatter::isExecSQL(const string& line, size_t index) const -{ - if (line[index] != 'e' && line[index] != 'E') // quick check to reject most - return false; - string word; - if (isCharPotentialHeader(line, index)) - word = getCurrentWord(line, index); - for (char& character : word) - character = (char) toupper(character); - if (word != "EXEC") - return false; - size_t index2 = index + word.length(); - index2 = line.find_first_not_of(" \t", index2); - if (index2 == string::npos) - return false; - word.erase(); - if (isCharPotentialHeader(line, index2)) - word = getCurrentWord(line, index2); - for (char& character : word) - character = (char) toupper(character); - if (word != "SQL") - return false; - return true; -} - -/** - * The continuation lines must be adjusted so the leading spaces - * is equivalent to the text on the opening line. - * - * Updates currentLine and charNum. - */ -void ASFormatter::trimContinuationLine() -{ - size_t len = currentLine.length(); - size_t tabSize = getTabLength(); - charNum = 0; - - if (leadingSpaces > 0 && len > 0) - { - size_t i; - size_t continuationIncrementIn = 0; - for (i = 0; (i < len) && (i + continuationIncrementIn < leadingSpaces); i++) - { - if (!isWhiteSpace(currentLine[i])) // don't delete any text - { - if (i < continuationIncrementIn) - leadingSpaces = i + tabIncrementIn; - continuationIncrementIn = tabIncrementIn; - break; - } - if (currentLine[i] == '\t') - continuationIncrementIn += tabSize - 1 - ((continuationIncrementIn + i) % tabSize); - } - - if ((int) continuationIncrementIn == tabIncrementIn) - charNum = i; - else - { - // build a new line with the equivalent leading chars - string newLine; - int leadingChars = 0; - if ((int) leadingSpaces > tabIncrementIn) - leadingChars = leadingSpaces - tabIncrementIn; - newLine.append(leadingChars, ' '); - newLine.append(currentLine, i, len - i); - currentLine = newLine; - charNum = leadingChars; - if (currentLine.length() == 0) - currentLine = string(" "); // a null is inserted if this is not done - } - if (i >= len) - charNum = 0; - } -} - -/** - * Determine if a header is a closing header - * - * @return true if the header is a closing header. - */ -bool ASFormatter::isClosingHeader(const string* header) const -{ - return (header == &AS_ELSE - || header == &AS_CATCH - || header == &AS_FINALLY); -} - -/** - * Determine if a * following a closing paren is immediately. - * after a cast. If so it is a deference and not a multiply. - * e.g. "(int*) *ptr" is a deference. - */ -bool ASFormatter::isImmediatelyPostCast() const -{ - assert(previousNonWSChar == ')' && currentChar == '*'); - // find preceding closing paren on currentLine or readyFormattedLine - string line; // currentLine or readyFormattedLine - size_t paren = currentLine.rfind(')', charNum); - if (paren != string::npos) - line = currentLine; - // if not on currentLine it must be on the previous line - else - { - line = readyFormattedLine; - paren = line.rfind(')'); - if (paren == string::npos) - return false; - } - if (paren == 0) - return false; - - // find character preceding the closing paren - size_t lastChar = line.find_last_not_of(" \t", paren - 1); - if (lastChar == string::npos) - return false; - // check for pointer cast - if (line[lastChar] == '*') - return true; - return false; -} - -/** - * Determine if a < is a template definition or instantiation. - * Sets the class variables isInTemplate and templateDepth. - */ -void ASFormatter::checkIfTemplateOpener() -{ - assert(!isInTemplate && currentChar == '<'); - - // find first char after the '<' operators - size_t firstChar = currentLine.find_first_not_of("< \t", charNum); - if (firstChar == string::npos - || currentLine[firstChar] == '=') - { - // this is not a template -> leave... - isInTemplate = false; - return; - } - - bool isFirstLine = true; - int parenDepth_ = 0; - int maxTemplateDepth = 0; - templateDepth = 0; - string nextLine_ = currentLine.substr(charNum); - ASPeekStream stream(sourceIterator); - - // find the angle braces, bypassing all comments and quotes. - bool isInComment_ = false; - bool isInQuote_ = false; - char quoteChar_ = ' '; - while (stream.hasMoreLines() || isFirstLine) - { - if (isFirstLine) - isFirstLine = false; - else - nextLine_ = stream.peekNextLine(); - // parse the line - for (size_t i = 0; i < nextLine_.length(); i++) - { - char currentChar_ = nextLine_[i]; - if (isWhiteSpace(currentChar_)) - continue; - if (nextLine_.compare(i, 2, "/*") == 0) - isInComment_ = true; - if (isInComment_) - { - if (nextLine_.compare(i, 2, "*/") == 0) - { - isInComment_ = false; - ++i; - } - continue; - } - if (currentChar_ == '\\') - { - ++i; - continue; - } - - if (isInQuote_) - { - if (currentChar_ == quoteChar_) - isInQuote_ = false; - continue; - } - - if (currentChar_ == '"' - || (currentChar_ == '\'' && !isDigitSeparator(nextLine_, i))) - { - isInQuote_ = true; - quoteChar_ = currentChar_; - continue; - } - if (nextLine_.compare(i, 2, "//") == 0) - { - i = nextLine_.length(); - continue; - } - - // not in a comment or quote - if (currentChar_ == '<') - { - ++templateDepth; - ++maxTemplateDepth; - continue; - } - if (currentChar_ == '>') - { - --templateDepth; - if (templateDepth == 0) - { - if (parenDepth_ == 0) - { - // this is a template! - isInTemplate = true; - templateDepth = maxTemplateDepth; - } - return; - } - continue; - } - if (currentChar_ == '(' || currentChar_ == ')') - { - if (currentChar_ == '(') - ++parenDepth_; - else - --parenDepth_; - if (parenDepth_ >= 0) - continue; - // this is not a template -> leave... - isInTemplate = false; - templateDepth = 0; - return; - } - if (nextLine_.compare(i, 2, AS_AND) == 0 - || nextLine_.compare(i, 2, AS_OR) == 0) - { - // this is not a template -> leave... - isInTemplate = false; - templateDepth = 0; - return; - } - if (currentChar_ == ',' // comma, e.g. A - || currentChar_ == '&' // reference, e.g. A - || currentChar_ == '*' // pointer, e.g. A - || currentChar_ == '^' // C++/CLI managed pointer, e.g. A - || currentChar_ == ':' // ::, e.g. std::string - || currentChar_ == '=' // assign e.g. default parameter - || currentChar_ == '[' // [] e.g. string[] - || currentChar_ == ']' // [] e.g. string[] - || currentChar_ == '(' // (...) e.g. function definition - || currentChar_ == ')' // (...) e.g. function definition - || (isJavaStyle() && currentChar_ == '?') // Java wildcard - ) - { - continue; - } - if (!isLegalNameChar(currentChar_)) - { - // this is not a template -> leave... - isInTemplate = false; - templateDepth = 0; - return; - } - string name = getCurrentWord(nextLine_, i); - i += name.length() - 1; - } // end for loop - } // end while loop -} - -void ASFormatter::updateFormattedLineSplitPoints(char appendedChar) -{ - assert(maxCodeLength != string::npos); - assert(formattedLine.length() > 0); - - if (!isOkToSplitFormattedLine()) - return; - - char nextChar = peekNextChar(); - - // don't split before an end of line comment - if (nextChar == '/') - return; - - // don't split before or after a brace - if (appendedChar == '{' || appendedChar == '}' - || previousNonWSChar == '{' || previousNonWSChar == '}' - || nextChar == '{' || nextChar == '}' - || currentChar == '{' || currentChar == '}') // currentChar tests for an appended brace - return; - - // don't split before or after a block paren - if (appendedChar == '[' || appendedChar == ']' - || previousNonWSChar == '[' - || nextChar == '[' || nextChar == ']') - return; - - if (isWhiteSpace(appendedChar)) - { - if (nextChar != ')' // space before a closing paren - && nextChar != '(' // space before an opening paren - && nextChar != '/' // space before a comment - && nextChar != ':' // space before a colon - && currentChar != ')' // appended space before and after a closing paren - && currentChar != '(' // appended space before and after a opening paren - && previousNonWSChar != '(' // decided at the '(' - // don't break before a pointer or reference aligned to type - && !(nextChar == '*' - && !isCharPotentialOperator(previousNonWSChar) - && pointerAlignment == PTR_ALIGN_TYPE) - && !(nextChar == '&' - && !isCharPotentialOperator(previousNonWSChar) - && (referenceAlignment == REF_ALIGN_TYPE - || (referenceAlignment == REF_SAME_AS_PTR && pointerAlignment == PTR_ALIGN_TYPE))) - ) - { - if (formattedLine.length() - 1 <= maxCodeLength) - maxWhiteSpace = formattedLine.length() - 1; - else - maxWhiteSpacePending = formattedLine.length() - 1; - } - } - // unpadded closing parens may split after the paren (counts as whitespace) - else if (appendedChar == ')') - { - if (nextChar != ')' - && nextChar != ' ' - && nextChar != ';' - && nextChar != ',' - && nextChar != '.' - && !(nextChar == '-' && pointerSymbolFollows())) // check for -> - { - if (formattedLine.length() <= maxCodeLength) - maxWhiteSpace = formattedLine.length(); - else - maxWhiteSpacePending = formattedLine.length(); - } - } - // unpadded commas may split after the comma - else if (appendedChar == ',') - { - if (formattedLine.length() <= maxCodeLength) - maxComma = formattedLine.length(); - else - maxCommaPending = formattedLine.length(); - } - else if (appendedChar == '(') - { - if (nextChar != ')' && nextChar != '(' && nextChar != '"' && nextChar != '\'') - { - // if follows an operator break before - size_t parenNum; - if (previousNonWSChar != ' ' && isCharPotentialOperator(previousNonWSChar)) - parenNum = formattedLine.length() - 1; - else - parenNum = formattedLine.length(); - if (formattedLine.length() <= maxCodeLength) - maxParen = parenNum; - else - maxParenPending = parenNum; - } - } - else if (appendedChar == ';') - { - if (nextChar != ' ' && nextChar != '}' && nextChar != '/') // check for following comment - { - if (formattedLine.length() <= maxCodeLength) - maxSemi = formattedLine.length(); - else - maxSemiPending = formattedLine.length(); - } - } -} - -void ASFormatter::updateFormattedLineSplitPointsOperator(const string& sequence) -{ - assert(maxCodeLength != string::npos); - assert(formattedLine.length() > 0); - - if (!isOkToSplitFormattedLine()) - return; - - char nextChar = peekNextChar(); - - // don't split before an end of line comment - if (nextChar == '/') - return; - - // check for logical conditional - if (sequence == "||" || sequence == "&&" || sequence == "or" || sequence == "and") - { - if (shouldBreakLineAfterLogical) - { - if (formattedLine.length() <= maxCodeLength) - maxAndOr = formattedLine.length(); - else - maxAndOrPending = formattedLine.length(); - } - else - { - // adjust for leading space in the sequence - size_t sequenceLength = sequence.length(); - if (formattedLine.length() > sequenceLength - && isWhiteSpace(formattedLine[formattedLine.length() - sequenceLength - 1])) - sequenceLength++; - if (formattedLine.length() - sequenceLength <= maxCodeLength) - maxAndOr = formattedLine.length() - sequenceLength; - else - maxAndOrPending = formattedLine.length() - sequenceLength; - } - } - // comparison operators will split after the operator (counts as whitespace) - else if (sequence == "==" || sequence == "!=" || sequence == ">=" || sequence == "<=") - { - if (formattedLine.length() <= maxCodeLength) - maxWhiteSpace = formattedLine.length(); - else - maxWhiteSpacePending = formattedLine.length(); - } - // unpadded operators that will split BEFORE the operator (counts as whitespace) - else if (sequence == "+" || sequence == "-" || sequence == "?") - { - if (charNum > 0 - && !(sequence == "+" && isInExponent()) - && !(sequence == "-" && isInExponent()) - && (isLegalNameChar(currentLine[charNum - 1]) - || currentLine[charNum - 1] == ')' - || currentLine[charNum - 1] == ']' - || currentLine[charNum - 1] == '\"')) - { - if (formattedLine.length() - 1 <= maxCodeLength) - maxWhiteSpace = formattedLine.length() - 1; - else - maxWhiteSpacePending = formattedLine.length() - 1; - } - } - // unpadded operators that will USUALLY split AFTER the operator (counts as whitespace) - else if (sequence == "=" || sequence == ":") - { - // split BEFORE if the line is too long - // do NOT use <= here, must allow for a brace attached to an array - size_t splitPoint = 0; - if (formattedLine.length() < maxCodeLength) - splitPoint = formattedLine.length(); - else - splitPoint = formattedLine.length() - 1; - // padded or unpadded arrays - if (previousNonWSChar == ']') - { - if (formattedLine.length() - 1 <= maxCodeLength) - maxWhiteSpace = splitPoint; - else - maxWhiteSpacePending = splitPoint; - } - else if (charNum > 0 - && (isLegalNameChar(currentLine[charNum - 1]) - || currentLine[charNum - 1] == ')' - || currentLine[charNum - 1] == ']')) - { - if (formattedLine.length() <= maxCodeLength) - maxWhiteSpace = splitPoint; - else - maxWhiteSpacePending = splitPoint; - } - } -} - -/** - * Update the split point when a pointer or reference is formatted. - * The argument is the maximum index of the last whitespace character. - */ -void ASFormatter::updateFormattedLineSplitPointsPointerOrReference(size_t index) -{ - assert(maxCodeLength != string::npos); - assert(formattedLine.length() > 0); - assert(index < formattedLine.length()); - - if (!isOkToSplitFormattedLine()) - return; - - if (index < maxWhiteSpace) // just in case - return; - - if (index <= maxCodeLength) - maxWhiteSpace = index; - else - maxWhiteSpacePending = index; -} - -bool ASFormatter::isOkToSplitFormattedLine() -{ - assert(maxCodeLength != string::npos); - // Is it OK to split the line? - if (shouldKeepLineUnbroken - || isInLineComment - || isInComment - || isInQuote - || isInCase - || isInPreprocessor - || isInExecSQL - || isInAsm || isInAsmOneLine || isInAsmBlock - || isInTemplate) - return false; - - if (!isOkToBreakBlock(braceTypeStack->back()) && currentChar != '{') - { - shouldKeepLineUnbroken = true; - clearFormattedLineSplitPoints(); - return false; - } - if (isBraceType(braceTypeStack->back(), ARRAY_TYPE)) - { - shouldKeepLineUnbroken = true; - if (!isBraceType(braceTypeStack->back(), ARRAY_NIS_TYPE)) - clearFormattedLineSplitPoints(); - return false; - } - return true; -} - -/* This is called if the option maxCodeLength is set. - */ -void ASFormatter::testForTimeToSplitFormattedLine() -{ - // DO NOT ASSERT maxCodeLength HERE - // should the line be split - if (formattedLine.length() > maxCodeLength && !isLineReady) - { - size_t splitPoint = findFormattedLineSplitPoint(); - if (splitPoint > 0 && splitPoint < formattedLine.length()) - { - string splitLine = formattedLine.substr(splitPoint); - formattedLine = formattedLine.substr(0, splitPoint); - breakLine(true); - formattedLine = splitLine; - // if break-blocks is requested and this is a one-line statement - string nextWord = ASBeautifier::getNextWord(currentLine, charNum - 1); - if (isAppendPostBlockEmptyLineRequested - && (nextWord == "break" || nextWord == "continue")) - { - isAppendPostBlockEmptyLineRequested = false; - isPrependPostBlockEmptyLineRequested = true; - } - else - isPrependPostBlockEmptyLineRequested = false; - // adjust max split points - maxAndOr = (maxAndOr > splitPoint) ? (maxAndOr - splitPoint) : 0; - maxSemi = (maxSemi > splitPoint) ? (maxSemi - splitPoint) : 0; - maxComma = (maxComma > splitPoint) ? (maxComma - splitPoint) : 0; - maxParen = (maxParen > splitPoint) ? (maxParen - splitPoint) : 0; - maxWhiteSpace = (maxWhiteSpace > splitPoint) ? (maxWhiteSpace - splitPoint) : 0; - if (maxSemiPending > 0) - { - maxSemi = (maxSemiPending > splitPoint) ? (maxSemiPending - splitPoint) : 0; - maxSemiPending = 0; - } - if (maxAndOrPending > 0) - { - maxAndOr = (maxAndOrPending > splitPoint) ? (maxAndOrPending - splitPoint) : 0; - maxAndOrPending = 0; - } - if (maxCommaPending > 0) - { - maxComma = (maxCommaPending > splitPoint) ? (maxCommaPending - splitPoint) : 0; - maxCommaPending = 0; - } - if (maxParenPending > 0) - { - maxParen = (maxParenPending > splitPoint) ? (maxParenPending - splitPoint) : 0; - maxParenPending = 0; - } - if (maxWhiteSpacePending > 0) - { - maxWhiteSpace = (maxWhiteSpacePending > splitPoint) ? (maxWhiteSpacePending - splitPoint) : 0; - maxWhiteSpacePending = 0; - } - // don't allow an empty formatted line - size_t firstText = formattedLine.find_first_not_of(" \t"); - if (firstText == string::npos && formattedLine.length() > 0) - { - formattedLine.erase(); - clearFormattedLineSplitPoints(); - if (isWhiteSpace(currentChar)) - for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++) - goForward(1); - } - else if (firstText > 0) - { - formattedLine.erase(0, firstText); - maxSemi = (maxSemi > firstText) ? (maxSemi - firstText) : 0; - maxAndOr = (maxAndOr > firstText) ? (maxAndOr - firstText) : 0; - maxComma = (maxComma > firstText) ? (maxComma - firstText) : 0; - maxParen = (maxParen > firstText) ? (maxParen - firstText) : 0; - maxWhiteSpace = (maxWhiteSpace > firstText) ? (maxWhiteSpace - firstText) : 0; - } - // reset formattedLineCommentNum - if (formattedLineCommentNum != string::npos) - { - formattedLineCommentNum = formattedLine.find("//"); - if (formattedLineCommentNum == string::npos) - formattedLineCommentNum = formattedLine.find("/*"); - } - } - } -} - -size_t ASFormatter::findFormattedLineSplitPoint() const -{ - assert(maxCodeLength != string::npos); - // determine where to split - size_t minCodeLength = 10; - size_t splitPoint = 0; - splitPoint = maxSemi; - if (maxAndOr >= minCodeLength) - splitPoint = maxAndOr; - if (splitPoint < minCodeLength) - { - splitPoint = maxWhiteSpace; - // use maxParen instead if it is long enough - if (maxParen > splitPoint - || maxParen >= maxCodeLength * .7) - splitPoint = maxParen; - // use maxComma instead if it is long enough - // increasing the multiplier causes more splits at whitespace - if (maxComma > splitPoint - || maxComma >= maxCodeLength * .3) - splitPoint = maxComma; - } - // replace split point with first available break point - if (splitPoint < minCodeLength) - { - splitPoint = string::npos; - if (maxSemiPending > 0 && maxSemiPending < splitPoint) - splitPoint = maxSemiPending; - if (maxAndOrPending > 0 && maxAndOrPending < splitPoint) - splitPoint = maxAndOrPending; - if (maxCommaPending > 0 && maxCommaPending < splitPoint) - splitPoint = maxCommaPending; - if (maxParenPending > 0 && maxParenPending < splitPoint) - splitPoint = maxParenPending; - if (maxWhiteSpacePending > 0 && maxWhiteSpacePending < splitPoint) - splitPoint = maxWhiteSpacePending; - if (splitPoint == string::npos) - splitPoint = 0; - } - // if remaining line after split is too long - else if (formattedLine.length() - splitPoint > maxCodeLength) - { - // if end of the currentLine, find a new split point - size_t newCharNum; - if (!isWhiteSpace(currentChar) && isCharPotentialHeader(currentLine, charNum)) - newCharNum = getCurrentWord(currentLine, charNum).length() + charNum; - else - newCharNum = charNum + 2; - if (newCharNum + 1 > currentLine.length()) - { - // don't move splitPoint from before a conditional to after - if (maxWhiteSpace > splitPoint + 3) - splitPoint = maxWhiteSpace; - if (maxParen > splitPoint) - splitPoint = maxParen; - } - } - - return splitPoint; -} - -void ASFormatter::clearFormattedLineSplitPoints() -{ - maxSemi = 0; - maxAndOr = 0; - maxComma = 0; - maxParen = 0; - maxWhiteSpace = 0; - maxSemiPending = 0; - maxAndOrPending = 0; - maxCommaPending = 0; - maxParenPending = 0; - maxWhiteSpacePending = 0; -} - -/** - * Check if a pointer symbol (->) follows on the currentLine. - */ -bool ASFormatter::pointerSymbolFollows() const -{ - size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1); - if (peekNum == string::npos || currentLine.compare(peekNum, 2, "->") != 0) - return false; - return true; -} - -/** - * Compute the input checksum. - * This is called as an assert so it for is debug config only - */ -bool ASFormatter::computeChecksumIn(const string& currentLine_) -{ - for (const char& character : currentLine_) - if (!isWhiteSpace(character)) - checksumIn += character; - return true; -} - -/** - * Adjust the input checksum for deleted chars. - * This is called as an assert so it for is debug config only - */ -bool ASFormatter::adjustChecksumIn(int adjustment) -{ - checksumIn += adjustment; - return true; -} - -/** - * get the value of checksumIn for unit testing - * - * @return checksumIn. - */ -size_t ASFormatter::getChecksumIn() const -{ - return checksumIn; -} - -/** - * Compute the output checksum. - * This is called as an assert so it is for debug config only - */ -bool ASFormatter::computeChecksumOut(const string& beautifiedLine) -{ - for (const char& character : beautifiedLine) - if (!isWhiteSpace(character)) - checksumOut += character; - return true; -} - -/** - * Return isLineReady for the final check at end of file. - */ -bool ASFormatter::getIsLineReady() const -{ - return isLineReady; -} - -/** - * get the value of checksumOut for unit testing - * - * @return checksumOut. - */ -size_t ASFormatter::getChecksumOut() const -{ - return checksumOut; -} - -/** - * Return the difference in checksums. - * If zero all is okay. - */ -int ASFormatter::getChecksumDiff() const -{ - return checksumOut - checksumIn; -} - -// for unit testing -int ASFormatter::getFormatterFileType() const -{ - return formatterFileType; -} - -// Check if an operator follows the next word. -// The next word must be a legal name. -const string* ASFormatter::getFollowingOperator() const -{ - // find next word - size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextNum == string::npos) - return nullptr; - - if (!isLegalNameChar(currentLine[nextNum])) - return nullptr; - - // bypass next word and following spaces - while (nextNum < currentLine.length()) - { - if (!isLegalNameChar(currentLine[nextNum]) - && !isWhiteSpace(currentLine[nextNum])) - break; - nextNum++; - } - - if (nextNum >= currentLine.length() - || !isCharPotentialOperator(currentLine[nextNum]) - || currentLine[nextNum] == '/') // comment - return nullptr; - - const string* newOperator = ASBase::findOperator(currentLine, nextNum, operators); - return newOperator; -} - -// Check following data to determine if the current character is an array operator. -bool ASFormatter::isArrayOperator() const -{ - assert(currentChar == '*' || currentChar == '&' || currentChar == '^'); - assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE)); - - // find next word - size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextNum == string::npos) - return false; - - if (!isLegalNameChar(currentLine[nextNum])) - return false; - - // bypass next word and following spaces - while (nextNum < currentLine.length()) - { - if (!isLegalNameChar(currentLine[nextNum]) - && !isWhiteSpace(currentLine[nextNum])) - break; - nextNum++; - } - - // check for characters that indicate an operator - if (currentLine[nextNum] == ',' - || currentLine[nextNum] == '}' - || currentLine[nextNum] == ')' - || currentLine[nextNum] == '(') - return true; - return false; -} - -// Reset the flags that indicate various statement information. -void ASFormatter::resetEndOfStatement() -{ - foundQuestionMark = false; - foundNamespaceHeader = false; - foundClassHeader = false; - foundStructHeader = false; - foundInterfaceHeader = false; - foundPreDefinitionHeader = false; - foundPreCommandHeader = false; - foundPreCommandMacro = false; - foundTrailingReturnType = false; - foundCastOperator = false; - isInPotentialCalculation = false; - isSharpAccessor = false; - isSharpDelegate = false; - isInObjCMethodDefinition = false; - isImmediatelyPostObjCMethodPrefix = false; - isInObjCReturnType = false; - isInObjCParam = false; - isInObjCInterface = false; - isInObjCSelector = false; - isInEnum = false; - isInExternC = false; - elseHeaderFollowsComments = false; - returnTypeChecked = false; - nonInStatementBrace = 0; - while (!questionMarkStack->empty()) - questionMarkStack->pop_back(); -} - -// Find the colon alignment for Objective-C method definitions and method calls. -int ASFormatter::findObjCColonAlignment() const -{ - assert(currentChar == '+' || currentChar == '-' || currentChar == '['); - assert(getAlignMethodColon()); - - bool isFirstLine = true; - bool haveFirstColon = false; - bool foundMethodColon = false; - bool isInComment_ = false; - bool isInQuote_ = false; - bool haveTernary = false; - char quoteChar_ = ' '; - int sqBracketCount = 0; - int colonAdjust = 0; - int colonAlign = 0; - string nextLine_ = currentLine; - ASPeekStream stream(sourceIterator); - - // peek next line - while (sourceIterator->hasMoreLines() || isFirstLine) - { - if (!isFirstLine) - nextLine_ = stream.peekNextLine(); - // parse the line - haveFirstColon = false; - nextLine_ = ASBeautifier::trim(nextLine_); - for (size_t i = 0; i < nextLine_.length(); i++) - { - if (isWhiteSpace(nextLine_[i])) - continue; - if (nextLine_.compare(i, 2, "/*") == 0) - isInComment_ = true; - if (isInComment_) - { - if (nextLine_.compare(i, 2, "*/") == 0) - { - isInComment_ = false; - ++i; - } - continue; - } - if (nextLine_[i] == '\\') - { - ++i; - continue; - } - if (isInQuote_) - { - if (nextLine_[i] == quoteChar_) - isInQuote_ = false; - continue; - } - - if (nextLine_[i] == '"' - || (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i))) - { - isInQuote_ = true; - quoteChar_ = nextLine_[i]; - continue; - } - if (nextLine_.compare(i, 2, "//") == 0) - { - i = nextLine_.length(); - continue; - } - // process the current char - if ((nextLine_[i] == '{' && (currentChar == '-' || currentChar == '+')) - || nextLine_[i] == ';') - goto EndOfWhileLoop; // end of method definition - if (nextLine_[i] == ']') - { - --sqBracketCount; - if (sqBracketCount == 0) - goto EndOfWhileLoop; // end of method call - } - if (nextLine_[i] == '[') - ++sqBracketCount; - if (isFirstLine) // colon align does not include the first line - continue; - if (sqBracketCount > 1) - continue; - if (haveFirstColon) // multiple colons per line - continue; - if (nextLine_[i] == '?') - { - haveTernary = true; - continue; - } - // compute colon adjustment - if (nextLine_[i] == ':') - { - if (haveTernary) - { - haveTernary = false; - continue; - } - haveFirstColon = true; - foundMethodColon = true; - if (shouldPadMethodColon) - { - int spacesStart; - for (spacesStart = i; spacesStart > 0; spacesStart--) - if (!isWhiteSpace(nextLine_[spacesStart - 1])) - break; - int spaces = i - spacesStart; - if (objCColonPadMode == COLON_PAD_ALL || objCColonPadMode == COLON_PAD_BEFORE) - colonAdjust = 1 - spaces; - else if (objCColonPadMode == COLON_PAD_NONE || objCColonPadMode == COLON_PAD_AFTER) - colonAdjust = 0 - spaces; - } - // compute alignment - int colonPosition = i + colonAdjust; - if (colonPosition > colonAlign) - colonAlign = colonPosition; - } - } // end of for loop - isFirstLine = false; - } // end of while loop -EndOfWhileLoop: - if (!foundMethodColon) - colonAlign = -1; - return colonAlign; -} - -// pad an Objective-C method colon -void ASFormatter::padObjCMethodColon() -{ - assert(currentChar == ':'); - int commentAdjust = 0; - char nextChar = peekNextChar(); - if (objCColonPadMode == COLON_PAD_NONE - || objCColonPadMode == COLON_PAD_AFTER - || nextChar == ')') - { - // remove spaces before - for (int i = formattedLine.length() - 1; (i > -1) && isWhiteSpace(formattedLine[i]); i--) - { - formattedLine.erase(i); - --commentAdjust; - } - } - else - { - // pad space before - for (int i = formattedLine.length() - 1; (i > 0) && isWhiteSpace(formattedLine[i]); i--) - if (isWhiteSpace(formattedLine[i - 1])) - { - formattedLine.erase(i); - --commentAdjust; - } - if (formattedLine.length() > 0) - { - appendSpacePad(); - formattedLine.back() = ' '; // convert any tab to space - } - } - if (objCColonPadMode == COLON_PAD_NONE - || objCColonPadMode == COLON_PAD_BEFORE - || nextChar == ')') - { - // remove spaces after - size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextText == string::npos) - nextText = currentLine.length(); - int spaces = nextText - charNum - 1; - if (spaces > 0) - { - // do not use goForward here - currentLine.erase(charNum + 1, spaces); - spacePadNum -= spaces; - } - } - else - { - // pad space after - size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1); - if (nextText == string::npos) - nextText = currentLine.length(); - int spaces = nextText - charNum - 1; - if (spaces == 0) - { - currentLine.insert(charNum + 1, 1, ' '); - spacePadNum += 1; - } - else if (spaces > 1) - { - // do not use goForward here - currentLine.erase(charNum + 1, spaces - 1); - currentLine[charNum + 1] = ' '; // convert any tab to space - spacePadNum -= spaces - 1; - } - } - spacePadNum += commentAdjust; -} - -// Remove the leading '*' from a comment line and indent to the next tab. -void ASFormatter::stripCommentPrefix() -{ - int firstChar = formattedLine.find_first_not_of(" \t"); - if (firstChar < 0) - return; - - if (isInCommentStartLine) - { - // comment opener must begin the line - if (formattedLine.compare(firstChar, 2, "/*") != 0) - return; - int commentOpener = firstChar; - // ignore single line comments - int commentEnd = formattedLine.find("*/", firstChar + 2); - if (commentEnd != -1) - return; - // first char after the comment opener must be at least one indent - int followingText = formattedLine.find_first_not_of(" \t", commentOpener + 2); - if (followingText < 0) - return; - if (formattedLine[followingText] == '*' || formattedLine[followingText] == '!') - followingText = formattedLine.find_first_not_of(" \t", followingText + 1); - if (followingText < 0) - return; - if (formattedLine[followingText] == '*') - return; - int indentLen = getIndentLength(); - int followingTextIndent = followingText - commentOpener; - if (followingTextIndent < indentLen) - { - string stringToInsert(indentLen - followingTextIndent, ' '); - formattedLine.insert(followingText, stringToInsert); - } - return; - } - // comment body including the closer - if (formattedLine[firstChar] == '*') - { - if (formattedLine.compare(firstChar, 2, "*/") == 0) - { - // line starts with an end comment - formattedLine = "*/"; - } - else - { - // build a new line with one indent - int secondChar = formattedLine.find_first_not_of(" \t", firstChar + 1); - if (secondChar < 0) - { - adjustChecksumIn(-'*'); - formattedLine.erase(); - return; - } - if (formattedLine[secondChar] == '*') - return; - // replace the leading '*' - int indentLen = getIndentLength(); - adjustChecksumIn(-'*'); - // second char must be at least one indent - if (formattedLine.substr(0, secondChar).find('\t') != string::npos) - { - formattedLine.erase(firstChar, 1); - } - else - { - int spacesToInsert = 0; - if (secondChar >= indentLen) - spacesToInsert = secondChar; - else - spacesToInsert = indentLen; - formattedLine = string(spacesToInsert, ' ') + formattedLine.substr(secondChar); - } - // remove a trailing '*' - int lastChar = formattedLine.find_last_not_of(" \t"); - if (lastChar > -1 && formattedLine[lastChar] == '*') - { - adjustChecksumIn(-'*'); - formattedLine[lastChar] = ' '; - } - } - } - else - { - // first char not a '*' - // first char must be at least one indent - if (formattedLine.substr(0, firstChar).find('\t') == string::npos) - { - int indentLen = getIndentLength(); - if (firstChar < indentLen) - { - string stringToInsert(indentLen, ' '); - formattedLine = stringToInsert + formattedLine.substr(firstChar); - } - } - } -} - -} // end namespace astyle diff --git a/tools/astyle/ASLocalizer.cpp b/tools/astyle/ASLocalizer.cpp deleted file mode 100644 index 0c521afd..00000000 --- a/tools/astyle/ASLocalizer.cpp +++ /dev/null @@ -1,1168 +0,0 @@ -// ASLocalizer.cpp -// Copyright (c) 2018 by Jim Pattee . -// This code is licensed under the MIT License. -// License.md describes the conditions under which this software may be distributed. -// -// File encoding for this file is UTF-8 WITHOUT a byte order mark (BOM). -// русский 中文(简体) 日本語 한국의 -// -// Windows: -// Add the required "Language" to the system. -// The settings do NOT need to be changed to the added language. -// Change the "Region" settings. -// Change both the "Format" and the "Current Language..." settings. -// A restart is required if the codepage has changed. -// Windows problems: -// Hindi - no available locale, language pack removed -// Japanese - language pack install error -// Ukrainian - displays a ? instead of i -// -// Linux: -// Change the LANG environment variable: LANG=fr_FR.UTF-8. -// setlocale() will use the LANG environment variable on Linux. -// -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * - * To add a new language to this source module: - * - * Add a new translation class to ASLocalizer.h. - * Update the WinLangCode array in ASLocalizer.cpp. - * Add the language code to setTranslationClass() in ASLocalizer.cpp. - * Add the English-Translation pair to the constructor in ASLocalizer.cpp. - * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - -//---------------------------------------------------------------------------- -// headers -//---------------------------------------------------------------------------- - -#include "ASLocalizer.h" - -#ifdef _WIN32 - #include -#endif - -#ifdef __VMS - #define __USE_STD_IOSTREAM 1 - #include -#else - #include -#endif - -#include // needed by some compilers -#include -#include -#include -#include - -#ifdef _MSC_VER - #pragma warning(disable: 4996) // secure version deprecation warnings -#endif - -#ifdef __BORLANDC__ - #pragma warn -8104 // Local Static with constructor dangerous for multi-threaded apps -#endif - -#ifdef __INTEL_COMPILER - // #pragma warning(disable: 383) // value copied to temporary, reference to temporary used - // #pragma warning(disable: 981) // operands are evaluated in unspecified order -#endif - -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wdeprecated-declarations" // wcstombs -#endif - -namespace astyle { - -#ifndef ASTYLE_LIB - -//---------------------------------------------------------------------------- -// ASLocalizer class methods. -//---------------------------------------------------------------------------- - -ASLocalizer::ASLocalizer() -// Set the locale information. -{ - // set language default values to english (ascii) - // this will be used if a locale or a language cannot be found - m_langID = "en"; - m_subLangID.clear(); - m_translationClass = nullptr; - - // Not all compilers support the C++ function locale::global(locale("")); - char* localeName = setlocale(LC_ALL, ""); - if (localeName == nullptr) // use the english (ascii) defaults - { - fprintf(stderr, "\n%s\n\n", "Cannot set native locale, reverting to English"); - setTranslationClass(); - return; - } - // set the class variables -#ifdef _WIN32 - size_t lcid = GetUserDefaultLCID(); - setLanguageFromLCID(lcid); - m_codepage = GetACP(); -#else - setLanguageFromName(localeName); -#endif -} - -ASLocalizer::~ASLocalizer() -// Delete dynamically allocated memory. -{ - delete m_translationClass; -} - -#ifdef _WIN32 - -struct WinLangCode -{ - size_t winLang; - char canonicalLang[3]; -}; - -static WinLangCode wlc[] = -// primary language identifier http://msdn.microsoft.com/en-us/library/aa912554.aspx -// sublanguage identifier http://msdn.microsoft.com/en-us/library/aa913256.aspx -// language ID http://msdn.microsoft.com/en-us/library/ee797784%28v=cs.20%29.aspx -{ - { LANG_BULGARIAN, "bg" }, // bg-BG 1251 - { LANG_CHINESE, "zh" }, // zh-CHS, zh-CHT - { LANG_DUTCH, "nl" }, // nl-NL 1252 - { LANG_ENGLISH, "en" }, // en-US 1252 - { LANG_ESTONIAN, "et" }, // et-EE - { LANG_FINNISH, "fi" }, // fi-FI 1252 - { LANG_FRENCH, "fr" }, // fr-FR 1252 - { LANG_GERMAN, "de" }, // de-DE 1252 - { LANG_GREEK, "el" }, // el-GR 1253 - { LANG_HINDI, "hi" }, // hi-IN - { LANG_HUNGARIAN, "hu" }, // hu-HU 1250 - { LANG_ITALIAN, "it" }, // it-IT 1252 - { LANG_JAPANESE, "ja" }, // ja-JP - { LANG_KOREAN, "ko" }, // ko-KR - { LANG_NORWEGIAN, "nn" }, // nn-NO 1252 - { LANG_POLISH, "pl" }, // pl-PL 1250 - { LANG_PORTUGUESE, "pt" }, // pt-PT 1252 - { LANG_ROMANIAN, "ro" }, // ro-RO 1250 - { LANG_RUSSIAN, "ru" }, // ru-RU 1251 - { LANG_SPANISH, "es" }, // es-ES 1252 - { LANG_SWEDISH, "sv" }, // sv-SE 1252 - { LANG_UKRAINIAN, "uk" }, // uk-UA 1251 -}; - -void ASLocalizer::setLanguageFromLCID(size_t lcid) -// Windows get the language to use from the user locale. -// NOTE: GetUserDefaultLocaleName() gets nearly the same name as Linux. -// But it needs Windows Vista or higher. -// Same with LCIDToLocaleName(). -{ - m_lcid = lcid; - m_langID = "en"; // default to english - - size_t lang = PRIMARYLANGID(LANGIDFROMLCID(m_lcid)); - size_t sublang = SUBLANGID(LANGIDFROMLCID(m_lcid)); - // find language in the wlc table - for (WinLangCode language : wlc) - { - if (language.winLang == lang) - { - m_langID = language.canonicalLang; - break; - } - } - if (m_langID == "zh") - { - if (sublang == SUBLANG_CHINESE_SIMPLIFIED || sublang == SUBLANG_CHINESE_SINGAPORE) - m_subLangID = "CHS"; - else - m_subLangID = "CHT"; // default - } - setTranslationClass(); -} - -#endif // _WIN32 - -string ASLocalizer::getLanguageID() const -// Returns the language ID in m_langID. -{ - return m_langID; -} - -const Translation* ASLocalizer::getTranslationClass() const -// Returns the name of the translation class in m_translation. Used for testing. -{ - assert(m_translationClass); - return m_translationClass; -} - -void ASLocalizer::setLanguageFromName(const char* langID) -// Linux set the language to use from the langID. -// -// the language string has the following form -// -// lang[_LANG][.encoding][@modifier] -// -// (see environ(5) in the Open Unix specification) -// -// where lang is the primary language, LANG is a sublang/territory, -// encoding is the charset to use and modifier "allows the user to select -// a specific instance of localization data within a single category" -// -// for example, the following strings are valid: -// fr -// fr_FR -// de_DE.iso88591 -// de_DE@euro -// de_DE.iso88591@euro -{ - // the constants describing the format of lang_LANG locale string - string langStr = langID; - m_langID = langStr.substr(0, 2); - - // need the sublang for chinese - if (m_langID == "zh" && langStr[2] == '_') - { - string subLang = langStr.substr(3, 2); - if (subLang == "CN" || subLang == "SG") - m_subLangID = "CHS"; - else - m_subLangID = "CHT"; // default - } - setTranslationClass(); -} - -const char* ASLocalizer::settext(const char* textIn) const -// Call the settext class and return the value. -{ - assert(m_translationClass); - const string stringIn = textIn; - return m_translationClass->translate(stringIn).c_str(); -} - -void ASLocalizer::setTranslationClass() -// Return the required translation class. -// Sets the class variable m_translationClass from the value of m_langID. -// Get the language ID at http://msdn.microsoft.com/en-us/library/ee797784%28v=cs.20%29.aspx -{ - assert(m_langID.length()); - // delete previously set (--ascii option) - if (m_translationClass != nullptr) - { - delete m_translationClass; - m_translationClass = nullptr; - } - if (m_langID == "bg") - m_translationClass = new Bulgarian; - else if (m_langID == "zh" && m_subLangID == "CHS") - m_translationClass = new ChineseSimplified; - else if (m_langID == "zh" && m_subLangID == "CHT") - m_translationClass = new ChineseTraditional; - else if (m_langID == "nl") - m_translationClass = new Dutch; - else if (m_langID == "en") - m_translationClass = new English; - else if (m_langID == "et") - m_translationClass = new Estonian; - else if (m_langID == "fi") - m_translationClass = new Finnish; - else if (m_langID == "fr") - m_translationClass = new French; - else if (m_langID == "de") - m_translationClass = new German; - else if (m_langID == "el") - m_translationClass = new Greek; - else if (m_langID == "hi") - m_translationClass = new Hindi; - else if (m_langID == "hu") - m_translationClass = new Hungarian; - else if (m_langID == "it") - m_translationClass = new Italian; - else if (m_langID == "ja") - m_translationClass = new Japanese; - else if (m_langID == "ko") - m_translationClass = new Korean; - else if (m_langID == "nn") - m_translationClass = new Norwegian; - else if (m_langID == "pl") - m_translationClass = new Polish; - else if (m_langID == "pt") - m_translationClass = new Portuguese; - else if (m_langID == "ro") - m_translationClass = new Romanian; - else if (m_langID == "ru") - m_translationClass = new Russian; - else if (m_langID == "es") - m_translationClass = new Spanish; - else if (m_langID == "sv") - m_translationClass = new Swedish; - else if (m_langID == "uk") - m_translationClass = new Ukrainian; - else // default - m_translationClass = new English; -} - -//---------------------------------------------------------------------------- -// Translation base class methods. -//---------------------------------------------------------------------------- - -Translation::Translation() -{ - m_translationVector.reserve(translationElements); -} - -void Translation::addPair(const string& english, const wstring& translated) -// Add a string pair to the translation vector. -{ - pair entry(english, translated); - m_translationVector.emplace_back(entry); - assert(m_translationVector.size() <= translationElements); -} - -string Translation::convertToMultiByte(const wstring& wideStr) const -// Convert wchar_t to a multibyte string using the currently assigned locale. -// Return an empty string if an error occurs. -{ - static bool msgDisplayed = false; - // get length of the output excluding the nullptr and validate the parameters - size_t mbLen = wcstombs(nullptr, wideStr.c_str(), 0); - if (mbLen == string::npos) - { - if (!msgDisplayed) - { - fprintf(stderr, "\n%s\n\n", "Cannot convert to multi-byte string, reverting to English"); - msgDisplayed = true; - } - return ""; - } - // convert the characters - char* mbStr = new (nothrow) char[mbLen + 1]; - if (mbStr == nullptr) - { - if (!msgDisplayed) - { - fprintf(stderr, "\n%s\n\n", "Bad memory alloc for multi-byte string, reverting to English"); - msgDisplayed = true; - } - return ""; - } - wcstombs(mbStr, wideStr.c_str(), mbLen + 1); - // return the string - string mbTranslation = mbStr; - delete[] mbStr; - return mbTranslation; -} - -string Translation::getTranslationString(size_t i) const -// Return the translation ascii value. Used for testing. -{ - if (i >= m_translationVector.size()) - return string(); - return m_translationVector[i].first; -} - -size_t Translation::getTranslationVectorSize() const -// Return the translation vector size. Used for testing. -{ - return m_translationVector.size(); -} - -bool Translation::getWideTranslation(const string& stringIn, wstring& wideOut) const -// Get the wide translation string. Used for testing. -{ - for (const pair& translation : m_translationVector) - { - if (translation.first == stringIn) - { - wideOut = translation.second; - return true; - } - } - // not found - wideOut = L""; - return false; -} - -string& Translation::translate(const string& stringIn) const -// Translate a string. -// Return a mutable string so the method can have a "const" designation. -// This allows "settext" to be called from a "const" method. -{ - m_mbTranslation.clear(); - for (const pair& translation : m_translationVector) - { - if (translation.first == stringIn) - { - m_mbTranslation = convertToMultiByte(translation.second); - break; - } - } - // not found, return english - if (m_mbTranslation.empty()) - m_mbTranslation = stringIn; - return m_mbTranslation; -} - -//---------------------------------------------------------------------------- -// Translation class methods. -// These classes have only a constructor which builds the language vector. -//---------------------------------------------------------------------------- - -Bulgarian::Bulgarian() // български -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Форматиран %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Непроменен %s\n"); // should align with formatted - addPair("Directory %s\n", L"директория %s\n"); - addPair("Default option file %s\n", L"Файл с опции по подразбиране %s\n"); - addPair("Project option file %s\n", L"Файл с опции за проекта %s\n"); - addPair("Exclude %s\n", L"Изключвам %s\n"); - addPair("Exclude (unmatched) %s\n", L"Изключване (несравнимо) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s форматиран %s hепроменен "); - addPair(" seconds ", L" секунди "); - addPair("%d min %d sec ", L"%d мин %d сек "); - addPair("%s lines\n", L"%s линии\n"); - addPair("Opening HTML documentation %s\n", L"Откриване HTML документация %s\n"); - addPair("Invalid default options:", L"Невалидни опции по подразбиране:"); - addPair("Invalid project options:", L"Невалидни опции за проекти:"); - addPair("Invalid command line options:", L"Невалидни опции за командния ред:"); - addPair("For help on options type 'astyle -h'", L"За помощ относно възможностите тип 'astyle -h'"); - addPair("Cannot open default option file", L"Не може да се отвори файлът с опции по подразбиране"); - addPair("Cannot open project option file", L"Не може да се отвори файла с опции за проекта"); - addPair("Cannot open directory", L"Не може да се отвори директория"); - addPair("Cannot open HTML file %s\n", L"Не може да се отвори HTML файл %s\n"); - addPair("Command execute failure", L"Command изпълни недостатъчност"); - addPair("Command is not installed", L"Command не е инсталиран"); - addPair("Missing filename in %s\n", L"Липсва името на файла в %s\n"); - addPair("Recursive option with no wildcard", L"Рекурсивно опция, без маска"); - addPair("Did you intend quote the filename", L"Знаете ли намерение да цитирам името на файла"); - addPair("No file to process %s\n", L"Не файл за обработка %s\n"); - addPair("Did you intend to use --recursive", L"Знаете ли възнамерявате да използвате --recursive"); - addPair("Cannot process UTF-32 encoding", L"Не може да са UTF-32 кодиране"); - addPair("Artistic Style has terminated\n", L"Artistic Style е прекратено\n"); -} - -ChineseSimplified::ChineseSimplified() // 中文(简体) -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"格式化 %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"未改变 %s\n"); // should align with formatted - addPair("Directory %s\n", L"目录 %s\n"); - addPair("Default option file %s\n", L"默认选项文件 %s\n"); - addPair("Project option file %s\n", L"项目选项文件 %s\n"); - addPair("Exclude %s\n", L"排除 %s\n"); - addPair("Exclude (unmatched) %s\n", L"排除(无匹配项) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s 格式化 %s 未改变 "); - addPair(" seconds ", L" 秒 "); - addPair("%d min %d sec ", L"%d 分 %d 秒 "); - addPair("%s lines\n", L"%s 行\n"); - addPair("Opening HTML documentation %s\n", L"打开HTML文档 %s\n"); - addPair("Invalid default options:", L"默认选项无效:"); - addPair("Invalid project options:", L"项目选项无效:"); - addPair("Invalid command line options:", L"无效的命令行选项:"); - addPair("For help on options type 'astyle -h'", L"输入 'astyle -h' 以获得有关命令行的帮助" ); - addPair("Cannot open default option file", L"无法打开默认选项文件"); - addPair("Cannot open project option file", L"无法打开项目选项文件"); - addPair("Cannot open directory", L"无法打开目录"); - addPair("Cannot open HTML file %s\n", L"无法打开HTML文件 %s\n"); - addPair("Command execute failure", L"执行命令失败"); - addPair("Command is not installed", L"未安装命令"); - addPair("Missing filename in %s\n", L"在%s缺少文件名\n"); - addPair("Recursive option with no wildcard", L"递归选项没有通配符"); - addPair("Did you intend quote the filename", L"你打算引用文件名"); - addPair("No file to process %s\n", L"没有文件可处理 %s\n"); - addPair("Did you intend to use --recursive", L"你打算使用 --recursive"); - addPair("Cannot process UTF-32 encoding", L"不能处理UTF-32编码"); - addPair("Artistic Style has terminated\n", L"Artistic Style 已经终止运行\n"); -} - -ChineseTraditional::ChineseTraditional() // 中文(繁體) -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"格式化 %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"未改變 %s\n"); // should align with formatted - addPair("Directory %s\n", L"目錄 %s\n"); - addPair("Default option file %s\n", L"默認選項文件 %s\n"); - addPair("Project option file %s\n", L"項目選項文件 %s\n"); - addPair("Exclude %s\n", L"排除 %s\n"); - addPair("Exclude (unmatched) %s\n", L"排除(無匹配項) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s 格式化 %s 未改變 "); - addPair(" seconds ", L" 秒 "); - addPair("%d min %d sec ", L"%d 分 %d 秒 "); - addPair("%s lines\n", L"%s 行\n"); - addPair("Opening HTML documentation %s\n", L"打開HTML文檔 %s\n"); - addPair("Invalid default options:", L"默認選項無效:"); - addPair("Invalid project options:", L"項目選項無效:"); - addPair("Invalid command line options:", L"無效的命令行選項:"); - addPair("For help on options type 'astyle -h'", L"輸入'astyle -h'以獲得有關命令行的幫助:"); - addPair("Cannot open default option file", L"無法打開默認選項文件"); - addPair("Cannot open project option file", L"無法打開項目選項文件"); - addPair("Cannot open directory", L"無法打開目錄"); - addPair("Cannot open HTML file %s\n", L"無法打開HTML文件 %s\n"); - addPair("Command execute failure", L"執行命令失敗"); - addPair("Command is not installed", L"未安裝命令"); - addPair("Missing filename in %s\n", L"在%s缺少文件名\n"); - addPair("Recursive option with no wildcard", L"遞歸選項沒有通配符"); - addPair("Did you intend quote the filename", L"你打算引用文件名"); - addPair("No file to process %s\n", L"沒有文件可處理 %s\n"); - addPair("Did you intend to use --recursive", L"你打算使用 --recursive"); - addPair("Cannot process UTF-32 encoding", L"不能處理UTF-32編碼"); - addPair("Artistic Style has terminated\n", L"Artistic Style 已經終止運行\n"); -} - -Dutch::Dutch() // Nederlandse -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Geformatteerd %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Onveranderd %s\n"); // should align with formatted - addPair("Directory %s\n", L"Directory %s\n"); - addPair("Default option file %s\n", L"Standaard optie bestand %s\n"); - addPair("Project option file %s\n", L"Project optie bestand %s\n"); - addPair("Exclude %s\n", L"Uitsluiten %s\n"); - addPair("Exclude (unmatched) %s\n", L"Uitgesloten (ongeëvenaarde) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s geformatteerd %s onveranderd "); - addPair(" seconds ", L" seconden "); - addPair("%d min %d sec ", L"%d min %d sec "); - addPair("%s lines\n", L"%s lijnen\n"); - addPair("Opening HTML documentation %s\n", L"Het openen van HTML-documentatie %s\n"); - addPair("Invalid default options:", L"Ongeldige standaardopties:"); - addPair("Invalid project options:", L"Ongeldige projectopties:"); - addPair("Invalid command line options:", L"Ongeldige command line opties:"); - addPair("For help on options type 'astyle -h'", L"Voor hulp bij 'astyle-h' opties het type"); - addPair("Cannot open default option file", L"Kan het standaardoptiesbestand niet openen"); - addPair("Cannot open project option file", L"Kan het project optie bestand niet openen"); - addPair("Cannot open directory", L"Kan niet open directory"); - addPair("Cannot open HTML file %s\n", L"Kan HTML-bestand niet openen %s\n"); - addPair("Command execute failure", L"Voeren commando falen"); - addPair("Command is not installed", L"Command is niet geïnstalleerd"); - addPair("Missing filename in %s\n", L"Ontbrekende bestandsnaam in %s\n"); - addPair("Recursive option with no wildcard", L"Recursieve optie met geen wildcard"); - addPair("Did you intend quote the filename", L"Heeft u van plan citaat van de bestandsnaam"); - addPair("No file to process %s\n", L"Geen bestand te verwerken %s\n"); - addPair("Did you intend to use --recursive", L"Hebt u van plan bent te gebruiken --recursive"); - addPair("Cannot process UTF-32 encoding", L"Kan niet verwerken UTF-32 codering"); - addPair("Artistic Style has terminated\n", L"Artistic Style heeft beëindigd\n"); -} - -English::English() = default; -// this class is NOT translated - -Estonian::Estonian() // Eesti -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formaadis %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Muutumatu %s\n"); // should align with formatted - addPair("Directory %s\n", L"Kataloog %s\n"); - addPair("Default option file %s\n", L"Vaikefunktsioonifail %s\n"); - addPair("Project option file %s\n", L"Projekti valiku fail %s\n"); - addPair("Exclude %s\n", L"Välista %s\n"); - addPair("Exclude (unmatched) %s\n", L"Välista (tasakaalustamata) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formaadis %s muutumatu "); - addPair(" seconds ", L" sekundit "); - addPair("%d min %d sec ", L"%d min %d sek "); - addPair("%s lines\n", L"%s read\n"); - addPair("Opening HTML documentation %s\n", L"Avamine HTML dokumentatsioon %s\n"); - addPair("Invalid default options:", L"Vaikevalikud on sobimatud:"); - addPair("Invalid project options:", L"Projekti valikud on sobimatud:"); - addPair("Invalid command line options:", L"Vale käsureavõtmetega:"); - addPair("For help on options type 'astyle -h'", L"Abiks võimaluste tüüp 'astyle -h'"); - addPair("Cannot open default option file", L"Vaikimisi valitud faili ei saa avada"); - addPair("Cannot open project option file", L"Projektivaliku faili ei saa avada"); - addPair("Cannot open directory", L"Ei saa avada kataloogi"); - addPair("Cannot open HTML file %s\n", L"Ei saa avada HTML-faili %s\n"); - addPair("Command execute failure", L"Käsk täita rike"); - addPair("Command is not installed", L"Käsk ei ole paigaldatud"); - addPair("Missing filename in %s\n", L"Kadunud failinimi %s\n"); - addPair("Recursive option with no wildcard", L"Rekursiivne võimalus ilma metamärgi"); - addPair("Did you intend quote the filename", L"Kas te kavatsete tsiteerida failinimi"); - addPair("No file to process %s\n", L"No faili töötlema %s\n"); - addPair("Did you intend to use --recursive", L"Kas te kavatsete kasutada --recursive"); - addPair("Cannot process UTF-32 encoding", L"Ei saa töödelda UTF-32 kodeeringus"); - addPair("Artistic Style has terminated\n", L"Artistic Style on lõpetatud\n"); -} - -Finnish::Finnish() // Suomeksi -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Muotoiltu %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Ennallaan %s\n"); // should align with formatted - addPair("Directory %s\n", L"Directory %s\n"); - addPair("Default option file %s\n", L"Oletusasetustiedosto %s\n"); - addPair("Project option file %s\n", L"Projektin valintatiedosto %s\n"); - addPair("Exclude %s\n", L"Sulkea %s\n"); - addPair("Exclude (unmatched) %s\n", L"Sulkea (verraton) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s muotoiltu %s ennallaan "); - addPair(" seconds ", L" sekuntia "); - addPair("%d min %d sec ", L"%d min %d sek "); - addPair("%s lines\n", L"%s linjat\n"); - addPair("Opening HTML documentation %s\n", L"Avaaminen HTML asiakirjat %s\n"); - addPair("Invalid default options:", L"Virheelliset oletusasetukset:"); - addPair("Invalid project options:", L"Virheelliset hankevalinnat:"); - addPair("Invalid command line options:", L"Virheellinen komentorivin:"); - addPair("For help on options type 'astyle -h'", L"Apua vaihtoehdoista tyyppi 'astyle -h'"); - addPair("Cannot open default option file", L"Et voi avata oletusasetustiedostoa"); - addPair("Cannot open project option file", L"Projektin asetustiedostoa ei voi avata"); - addPair("Cannot open directory", L"Ei Open Directory"); - addPair("Cannot open HTML file %s\n", L"Ei voi avata HTML-tiedoston %s\n"); - addPair("Command execute failure", L"Suorita komento vika"); - addPair("Command is not installed", L"Komento ei ole asennettu"); - addPair("Missing filename in %s\n", L"Puuttuvat tiedostonimi %s\n"); - addPair("Recursive option with no wildcard", L"Rekursiivinen vaihtoehto ilman wildcard"); - addPair("Did you intend quote the filename", L"Oletko aio lainata tiedostonimi"); - addPair("No file to process %s\n", L"Ei tiedostoa käsitellä %s\n"); - addPair("Did you intend to use --recursive", L"Oliko aiot käyttää --recursive"); - addPair("Cannot process UTF-32 encoding", L"Ei voi käsitellä UTF-32 koodausta"); - addPair("Artistic Style has terminated\n", L"Artistic Style on päättynyt\n"); -} - -French::French() // Française -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formaté %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Inchangée %s\n"); // should align with formatted - addPair("Directory %s\n", L"Répertoire %s\n"); - addPair("Default option file %s\n", L"Fichier d'option par défaut %s\n"); - addPair("Project option file %s\n", L"Fichier d'option de projet %s\n"); - addPair("Exclude %s\n", L"Exclure %s\n"); - addPair("Exclude (unmatched) %s\n", L"Exclure (non appariés) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formaté %s inchangée "); - addPair(" seconds ", L" seconde "); - addPair("%d min %d sec ", L"%d min %d sec "); - addPair("%s lines\n", L"%s lignes\n"); - addPair("Opening HTML documentation %s\n", L"Ouverture documentation HTML %s\n"); - addPair("Invalid default options:", L"Options par défaut invalides:"); - addPair("Invalid project options:", L"Options de projet non valides:"); - addPair("Invalid command line options:", L"Blancs options ligne de commande:"); - addPair("For help on options type 'astyle -h'", L"Pour de l'aide sur les options tapez 'astyle -h'"); - addPair("Cannot open default option file", L"Impossible d'ouvrir le fichier d'option par défaut"); - addPair("Cannot open project option file", L"Impossible d'ouvrir le fichier d'option de projet"); - addPair("Cannot open directory", L"Impossible d'ouvrir le répertoire"); - addPair("Cannot open HTML file %s\n", L"Impossible d'ouvrir le fichier HTML %s\n"); - addPair("Command execute failure", L"Exécuter échec de la commande"); - addPair("Command is not installed", L"Commande n'est pas installé"); - addPair("Missing filename in %s\n", L"Nom de fichier manquant dans %s\n"); - addPair("Recursive option with no wildcard", L"Option récursive sans joker"); - addPair("Did you intend quote the filename", L"Avez-vous l'intention de citer le nom de fichier"); - addPair("No file to process %s\n", L"Aucun fichier à traiter %s\n"); - addPair("Did you intend to use --recursive", L"Avez-vous l'intention d'utiliser --recursive"); - addPair("Cannot process UTF-32 encoding", L"Impossible de traiter codage UTF-32"); - addPair("Artistic Style has terminated\n", L"Artistic Style a mis fin\n"); -} - -German::German() // Deutsch -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formatiert %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Unverändert %s\n"); // should align with formatted - addPair("Directory %s\n", L"Verzeichnis %s\n"); - addPair("Default option file %s\n", L"Standard-Optionsdatei %s\n"); - addPair("Project option file %s\n", L"Projektoptionsdatei %s\n"); - addPair("Exclude %s\n", L"Ausschließen %s\n"); - addPair("Exclude (unmatched) %s\n", L"Ausschließen (unerreichte) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formatiert %s unverändert "); - addPair(" seconds ", L" sekunden "); - addPair("%d min %d sec ", L"%d min %d sek "); - addPair("%s lines\n", L"%s linien\n"); - addPair("Opening HTML documentation %s\n", L"Öffnen HTML-Dokumentation %s\n"); - addPair("Invalid default options:", L"Ungültige Standardoptionen:"); - addPair("Invalid project options:", L"Ungültige Projektoptionen:"); - addPair("Invalid command line options:", L"Ungültige Kommandozeilen-Optionen:"); - addPair("For help on options type 'astyle -h'", L"Für Hilfe zu den Optionen geben Sie 'astyle -h'"); - addPair("Cannot open default option file", L"Die Standardoptionsdatei kann nicht geöffnet werden"); - addPair("Cannot open project option file", L"Die Projektoptionsdatei kann nicht geöffnet werden"); - addPair("Cannot open directory", L"Kann nicht geöffnet werden Verzeichnis"); - addPair("Cannot open HTML file %s\n", L"Kann nicht öffnen HTML-Datei %s\n"); - addPair("Command execute failure", L"Execute Befehl Scheitern"); - addPair("Command is not installed", L"Befehl ist nicht installiert"); - addPair("Missing filename in %s\n", L"Missing in %s Dateiname\n"); - addPair("Recursive option with no wildcard", L"Rekursive Option ohne Wildcard"); - addPair("Did you intend quote the filename", L"Haben Sie die Absicht Inhalte der Dateiname"); - addPair("No file to process %s\n", L"Keine Datei zu verarbeiten %s\n"); - addPair("Did you intend to use --recursive", L"Haben Sie verwenden möchten --recursive"); - addPair("Cannot process UTF-32 encoding", L"Nicht verarbeiten kann UTF-32 Codierung"); - addPair("Artistic Style has terminated\n", L"Artistic Style ist beendet\n"); -} - -Greek::Greek() // ελληνικά -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Διαμορφωμένη %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Αμετάβλητος %s\n"); // should align with formatted - addPair("Directory %s\n", L"Κατάλογος %s\n"); - addPair("Default option file %s\n", L"Προεπιλεγμένο αρχείο επιλογών %s\n"); - addPair("Project option file %s\n", L"Αρχείο επιλογής έργου %s\n"); - addPair("Exclude %s\n", L"Αποκλείω %s\n"); - addPair("Exclude (unmatched) %s\n", L"Ausschließen (unerreichte) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s σχηματοποιημένη %s αμετάβλητες "); - addPair(" seconds ", L" δευτερόλεπτα "); - addPair("%d min %d sec ", L"%d λεπ %d δευ "); - addPair("%s lines\n", L"%s γραμμές\n"); - addPair("Opening HTML documentation %s\n", L"Εγκαίνια έγγραφα HTML %s\n"); - addPair("Invalid default options:", L"Μη έγκυρες επιλογές προεπιλογής:"); - addPair("Invalid project options:", L"Μη έγκυρες επιλογές έργου:"); - addPair("Invalid command line options:", L"Μη έγκυρη επιλογές γραμμής εντολών:"); - addPair("For help on options type 'astyle -h'", L"Για βοήθεια σχετικά με το είδος επιλογές 'astyle -h'"); - addPair("Cannot open default option file", L"Δεν είναι δυνατό να ανοίξει το προεπιλεγμένο αρχείο επιλογών"); - addPair("Cannot open project option file", L"Δεν είναι δυνατό να ανοίξει το αρχείο επιλογής έργου"); - addPair("Cannot open directory", L"Δεν μπορείτε να ανοίξετε τον κατάλογο"); - addPair("Cannot open HTML file %s\n", L"Δεν μπορείτε να ανοίξετε το αρχείο HTML %s\n"); - addPair("Command execute failure", L"Εντολή να εκτελέσει την αποτυχία"); - addPair("Command is not installed", L"Η εντολή δεν έχει εγκατασταθεί"); - addPair("Missing filename in %s\n", L"Λείπει το όνομα αρχείου σε %s\n"); - addPair("Recursive option with no wildcard", L"Αναδρομικές επιλογή χωρίς μπαλαντέρ"); - addPair("Did you intend quote the filename", L"Μήπως σκοπεύετε να αναφέρετε το όνομα του αρχείου"); - addPair("No file to process %s\n", L"Δεν υπάρχει αρχείο για την επεξεργασία %s\n"); - addPair("Did you intend to use --recursive", L"Μήπως σκοπεύετε να χρησιμοποιήσετε --recursive"); - addPair("Cannot process UTF-32 encoding", L"δεν μπορεί να επεξεργαστεί UTF-32 κωδικοποίηση"); - addPair("Artistic Style has terminated\n", L"Artistic Style έχει λήξει\n"); -} - -Hindi::Hindi() // हिन्दी -// build the translation vector in the Translation base class -{ - // NOTE: Scintilla based editors (CodeBlocks) cannot always edit Hindi. - // Use Visual Studio instead. - addPair("Formatted %s\n", L"स्वरूपित किया %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"अपरिवर्तित %s\n"); // should align with formatted - addPair("Directory %s\n", L"निर्देशिका %s\n"); - addPair("Default option file %s\n", L"डिफ़ॉल्ट विकल्प फ़ाइल %s\n"); - addPair("Project option file %s\n", L"प्रोजेक्ट विकल्प फ़ाइल %s\n"); - addPair("Exclude %s\n", L"निकालना %s\n"); - addPair("Exclude (unmatched) %s\n", L"अपवर्जित (बेजोड़) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s स्वरूपित किया %s अपरिवर्तित "); - addPair(" seconds ", L" सेकंड "); - addPair("%d min %d sec ", L"%d मिनट %d सेकंड "); - addPair("%s lines\n", L"%s लाइनों\n"); - addPair("Opening HTML documentation %s\n", L"एचटीएमएल प्रलेखन खोलना %s\n"); - addPair("Invalid default options:", L"अमान्य डिफ़ॉल्ट विकल्प:"); - addPair("Invalid project options:", L"अमान्य प्रोजेक्ट विकल्प:"); - addPair("Invalid command line options:", L"कमांड लाइन विकल्प अवैध:"); - addPair("For help on options type 'astyle -h'", L"विकल्पों पर मदद के लिए प्रकार 'astyle -h'"); - addPair("Cannot open default option file", L"डिफ़ॉल्ट विकल्प फ़ाइल नहीं खोल सकता"); - addPair("Cannot open project option file", L"परियोजना विकल्प फ़ाइल नहीं खोल सकता"); - addPair("Cannot open directory", L"निर्देशिका नहीं खोल सकता"); - addPair("Cannot open HTML file %s\n", L"HTML फ़ाइल नहीं खोल सकता %s\n"); - addPair("Command execute failure", L"आदेश विफलता निष्पादित"); - addPair("Command is not installed", L"कमान स्थापित नहीं है"); - addPair("Missing filename in %s\n", L"लापता में फ़ाइलनाम %s\n"); - addPair("Recursive option with no wildcard", L"कोई वाइल्डकार्ड साथ पुनरावर्ती विकल्प"); - addPair("Did you intend quote the filename", L"क्या आप बोली फ़ाइलनाम का इरादा"); - addPair("No file to process %s\n", L"कोई फ़ाइल %s प्रक्रिया के लिए\n"); - addPair("Did you intend to use --recursive", L"क्या आप उपयोग करना चाहते हैं --recursive"); - addPair("Cannot process UTF-32 encoding", L"UTF-32 कूटबन्धन प्रक्रिया नहीं कर सकते"); - addPair("Artistic Style has terminated\n", L"Artistic Style समाप्त किया है\n"); -} - -Hungarian::Hungarian() // Magyar -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formázott %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Változatlan %s\n"); // should align with formatted - addPair("Directory %s\n", L"Címjegyzék %s\n"); - addPair("Default option file %s\n", L"Alapértelmezett beállítási fájl %s\n"); - addPair("Project option file %s\n", L"Projekt opciófájl %s\n"); - addPair("Exclude %s\n", L"Kizár %s\n"); - addPair("Exclude (unmatched) %s\n", L"Escludere (senza pari) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formázott %s változatlan "); - addPair(" seconds ", L" másodperc "); - addPair("%d min %d sec ", L"%d jeg %d más "); - addPair("%s lines\n", L"%s vonalak\n"); - addPair("Opening HTML documentation %s\n", L"Nyitó HTML dokumentáció %s\n"); - addPair("Invalid default options:", L"Érvénytelen alapértelmezett beállítások:"); - addPair("Invalid project options:", L"Érvénytelen projektbeállítások:"); - addPair("Invalid command line options:", L"Érvénytelen parancssori opciók:"); - addPair("For help on options type 'astyle -h'", L"Ha segítségre van lehetőség típus 'astyle-h'"); - addPair("Cannot open default option file", L"Nem lehet megnyitni az alapértelmezett beállítási fájlt"); - addPair("Cannot open project option file", L"Nem lehet megnyitni a projekt opció fájlt"); - addPair("Cannot open directory", L"Nem lehet megnyitni könyvtár"); - addPair("Cannot open HTML file %s\n", L"Nem lehet megnyitni a HTML fájlt %s\n"); - addPair("Command execute failure", L"Command végre hiba"); - addPair("Command is not installed", L"Parancs nincs telepítve"); - addPair("Missing filename in %s\n", L"Hiányzó fájlnév %s\n"); - addPair("Recursive option with no wildcard", L"Rekurzív kapcsolót nem wildcard"); - addPair("Did you intend quote the filename", L"Esetleg kívánja idézni a fájlnév"); - addPair("No file to process %s\n", L"Nincs fájl feldolgozása %s\n"); - addPair("Did you intend to use --recursive", L"Esetleg a használni kívánt --recursive"); - addPair("Cannot process UTF-32 encoding", L"Nem tudja feldolgozni UTF-32 kódolással"); - addPair("Artistic Style has terminated\n", L"Artistic Style megszűnt\n"); -} - -Italian::Italian() // Italiano -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formattata %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Immutato %s\n"); // should align with formatted - addPair("Directory %s\n", L"Elenco %s\n"); - addPair("Default option file %s\n", L"File di opzione predefinito %s\n"); - addPair("Project option file %s\n", L"File di opzione del progetto %s\n"); - addPair("Exclude %s\n", L"Escludere %s\n"); - addPair("Exclude (unmatched) %s\n", L"Escludere (senza pari) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s ormattata %s immutato "); - addPair(" seconds ", L" secondo "); - addPair("%d min %d sec ", L"%d min %d seg "); - addPair("%s lines\n", L"%s linee\n"); - addPair("Opening HTML documentation %s\n", L"Apertura di documenti HTML %s\n"); - addPair("Invalid default options:", L"Opzioni di default non valide:"); - addPair("Invalid project options:", L"Opzioni di progetto non valide:"); - addPair("Invalid command line options:", L"Opzioni della riga di comando non valido:"); - addPair("For help on options type 'astyle -h'", L"Per informazioni sulle opzioni di tipo 'astyle-h'"); - addPair("Cannot open default option file", L"Impossibile aprire il file di opzione predefinito"); - addPair("Cannot open project option file", L"Impossibile aprire il file di opzione del progetto"); - addPair("Cannot open directory", L"Impossibile aprire la directory"); - addPair("Cannot open HTML file %s\n", L"Impossibile aprire il file HTML %s\n"); - addPair("Command execute failure", L"Esegui fallimento comando"); - addPair("Command is not installed", L"Il comando non è installato"); - addPair("Missing filename in %s\n", L"Nome del file mancante in %s\n"); - addPair("Recursive option with no wildcard", L"Opzione ricorsiva senza jolly"); - addPair("Did you intend quote the filename", L"Avete intenzione citare il nome del file"); - addPair("No file to process %s\n", L"Nessun file al processo %s\n"); - addPair("Did you intend to use --recursive", L"Hai intenzione di utilizzare --recursive"); - addPair("Cannot process UTF-32 encoding", L"Non è possibile processo di codifica UTF-32"); - addPair("Artistic Style has terminated\n", L"Artistic Style ha terminato\n"); -} - -Japanese::Japanese() // 日本語 -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"フォーマット済みの %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"変わりません %s\n"); // should align with formatted - addPair("Directory %s\n", L"ディレクトリ %s\n"); - addPair("Default option file %s\n", L"デフォルトオプションファイル %s\n"); - addPair("Project option file %s\n", L"プロジェクトオプションファイル %s\n"); - addPair("Exclude %s\n", L"除外する %s\n"); - addPair("Exclude (unmatched) %s\n", L"除外する(一致しません) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s フフォーマット済みの %s 変わりません "); - addPair(" seconds ", L" 秒 "); - addPair("%d min %d sec ", L"%d 分 %d 秒 "); - addPair("%s lines\n", L"%s ライン\n"); - addPair("Opening HTML documentation %s\n", L"オープニングHTMLドキュメント %s\n"); - addPair("Invalid default options:", L"無効なデフォルトオプション:"); - addPair("Invalid project options:", L"無効なプロジェクトオプション:"); - addPair("Invalid command line options:", L"無効なコマンドラインオプション:"); - addPair("For help on options type 'astyle -h'", L"コオプションの種類のヘルプについて'astyle- h'を入力してください"); - addPair("Cannot open default option file", L"デフォルトのオプションファイルを開くことができません"); - addPair("Cannot open project option file", L"プロジェクトオプションファイルを開くことができません"); - addPair("Cannot open directory", L"ディレクトリを開くことができません。"); - addPair("Cannot open HTML file %s\n", L"HTMLファイルを開くことができません %s\n"); - addPair("Command execute failure", L"コマンドが失敗を実行します"); - addPair("Command is not installed", L"コマンドがインストールされていません"); - addPair("Missing filename in %s\n", L"%s で、ファイル名がありません\n"); - addPair("Recursive option with no wildcard", L"無ワイルドカードを使用して再帰的なオプション"); - addPair("Did you intend quote the filename", L"あなたはファイル名を引用するつもりでした"); - addPair("No file to process %s\n", L"いいえファイルは処理しないように %s\n"); - addPair("Did you intend to use --recursive", L"あなたは--recursive使用するつもりでした"); - addPair("Cannot process UTF-32 encoding", L"UTF - 32エンコーディングを処理できません"); - addPair("Artistic Style has terminated\n", L"Artistic Style 終了しました\n"); -} - -Korean::Korean() // 한국의 -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"수정됨 %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"변경없음 %s\n"); // should align with formatted - addPair("Directory %s\n", L"디렉토리 %s\n"); - addPair("Default option file %s\n", L"기본 옵션 파일 %s\n"); - addPair("Project option file %s\n", L"프로젝트 옵션 파일 %s\n"); - addPair("Exclude %s\n", L"제외됨 %s\n"); - addPair("Exclude (unmatched) %s\n", L"제외 (NO 일치) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s 수정됨 %s 변경없음 "); - addPair(" seconds ", L" 초 "); - addPair("%d min %d sec ", L"%d 분 %d 초 "); - addPair("%s lines\n", L"%s 라인\n"); - addPair("Opening HTML documentation %s\n", L"HTML 문서를 열기 %s\n"); - addPair("Invalid default options:", L"잘못된 기본 옵션:"); - addPair("Invalid project options:", L"잘못된 프로젝트 옵션:"); - addPair("Invalid command line options:", L"잘못된 명령줄 옵션 :"); - addPair("For help on options type 'astyle -h'", L"도움말을 보려면 옵션 유형 'astyle - H'를 사용합니다"); - addPair("Cannot open default option file", L"기본 옵션 파일을 열 수 없습니다."); - addPair("Cannot open project option file", L"프로젝트 옵션 파일을 열 수 없습니다."); - addPair("Cannot open directory", L"디렉토리를 열지 못했습니다"); - addPair("Cannot open HTML file %s\n", L"HTML 파일을 열 수 없습니다 %s\n"); - addPair("Command execute failure", L"명령 실패를 실행"); - addPair("Command is not installed", L"명령이 설치되어 있지 않습니다"); - addPair("Missing filename in %s\n", L"%s 에서 누락된 파일 이름\n"); - addPair("Recursive option with no wildcard", L"와일드 카드없이 재귀 옵션"); - addPair("Did you intend quote the filename", L"당신은 파일 이름을 인용하고자하나요"); - addPair("No file to process %s\n", L"처리할 파일이 없습니다 %s\n"); - addPair("Did you intend to use --recursive", L"--recursive 를 사용하고자 하십니까"); - addPair("Cannot process UTF-32 encoding", L"UTF-32 인코딩을 처리할 수 없습니다"); - addPair("Artistic Style has terminated\n", L"Artistic Style를 종료합니다\n"); -} - -Norwegian::Norwegian() // Norsk -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formatert %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Uendret %s\n"); // should align with formatted - addPair("Directory %s\n", L"Katalog %s\n"); - addPair("Default option file %s\n", L"Standard alternativfil %s\n"); - addPair("Project option file %s\n", L"Prosjekt opsjonsfil %s\n"); - addPair("Exclude %s\n", L"Ekskluder %s\n"); - addPair("Exclude (unmatched) %s\n", L"Ekskluder (uovertruffen) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formatert %s uendret "); - addPair(" seconds ", L" sekunder "); - addPair("%d min %d sec ", L"%d min %d sek? "); - addPair("%s lines\n", L"%s linjer\n"); - addPair("Opening HTML documentation %s\n", L"Åpning HTML dokumentasjon %s\n"); - addPair("Invalid default options:", L"Ugyldige standardalternativer:"); - addPair("Invalid project options:", L"Ugyldige prosjektalternativer:"); - addPair("Invalid command line options:", L"Kommandolinjevalg Ugyldige:"); - addPair("For help on options type 'astyle -h'", L"For hjelp til alternativer type 'astyle -h'"); - addPair("Cannot open default option file", L"Kan ikke åpne standardvalgsfilen"); - addPair("Cannot open project option file", L"Kan ikke åpne prosjektvalgsfilen"); - addPair("Cannot open directory", L"Kan ikke åpne katalog"); - addPair("Cannot open HTML file %s\n", L"Kan ikke åpne HTML-fil %s\n"); - addPair("Command execute failure", L"Command utføre svikt"); - addPair("Command is not installed", L"Command er ikke installert"); - addPair("Missing filename in %s\n", L"Mangler filnavn i %s\n"); - addPair("Recursive option with no wildcard", L"Rekursiv alternativ uten wildcard"); - addPair("Did you intend quote the filename", L"Har du tenkt sitere filnavnet"); - addPair("No file to process %s\n", L"Ingen fil å behandle %s\n"); - addPair("Did you intend to use --recursive", L"Har du tenkt å bruke --recursive"); - addPair("Cannot process UTF-32 encoding", L"Kan ikke behandle UTF-32 koding"); - addPair("Artistic Style has terminated\n", L"Artistic Style har avsluttet\n"); -} - -Polish::Polish() // Polski -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Sformatowany %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Niezmienione %s\n"); // should align with formatted - addPair("Directory %s\n", L"Katalog %s\n"); - addPair("Default option file %s\n", L"Domyślny plik opcji %s\n"); - addPair("Project option file %s\n", L"Plik opcji projektu %s\n"); - addPair("Exclude %s\n", L"Wykluczać %s\n"); - addPair("Exclude (unmatched) %s\n", L"Wyklucz (niezrównany) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s sformatowany %s niezmienione "); - addPair(" seconds ", L" sekund "); - addPair("%d min %d sec ", L"%d min %d sek "); - addPair("%s lines\n", L"%s linii\n"); - addPair("Opening HTML documentation %s\n", L"Otwarcie dokumentacji HTML %s\n"); - addPair("Invalid default options:", L"Nieprawidłowe opcje domyślne:"); - addPair("Invalid project options:", L"Nieprawidłowe opcje projektu:"); - addPair("Invalid command line options:", L"Nieprawidłowe opcje wiersza polecenia:"); - addPair("For help on options type 'astyle -h'", L"Aby uzyskać pomoc od rodzaju opcji 'astyle -h'"); - addPair("Cannot open default option file", L"Nie można otworzyć pliku opcji domyślnych"); - addPair("Cannot open project option file", L"Nie można otworzyć pliku opcji projektu"); - addPair("Cannot open directory", L"Nie można otworzyć katalogu"); - addPair("Cannot open HTML file %s\n", L"Nie można otworzyć pliku HTML %s\n"); - addPair("Command execute failure", L"Wykonaj polecenia niepowodzenia"); - addPair("Command is not installed", L"Polecenie nie jest zainstalowany"); - addPair("Missing filename in %s\n", L"Brakuje pliku w %s\n"); - addPair("Recursive option with no wildcard", L"Rekurencyjne opcja bez symboli"); - addPair("Did you intend quote the filename", L"Czy zamierza Pan podać nazwę pliku"); - addPair("No file to process %s\n", L"Brak pliku do procesu %s\n"); - addPair("Did you intend to use --recursive", L"Czy masz zamiar używać --recursive"); - addPair("Cannot process UTF-32 encoding", L"Nie można procesu kodowania UTF-32"); - addPair("Artistic Style has terminated\n", L"Artistic Style został zakończony\n"); -} - -Portuguese::Portuguese() // Português -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formatado %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Inalterado %s\n"); // should align with formatted - addPair("Directory %s\n", L"Diretório %s\n"); - addPair("Default option file %s\n", L"Arquivo de opção padrão %s\n"); - addPair("Project option file %s\n", L"Arquivo de opção de projeto %s\n"); - addPair("Exclude %s\n", L"Excluir %s\n"); - addPair("Exclude (unmatched) %s\n", L"Excluir (incomparável) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formatado %s inalterado "); - addPair(" seconds ", L" segundo "); - addPair("%d min %d sec ", L"%d min %d seg "); - addPair("%s lines\n", L"%s linhas\n"); - addPair("Opening HTML documentation %s\n", L"Abrindo a documentação HTML %s\n"); - addPair("Invalid default options:", L"Opções padrão inválidas:"); - addPair("Invalid project options:", L"Opções de projeto inválidas:"); - addPair("Invalid command line options:", L"Opções de linha de comando inválida:"); - addPair("For help on options type 'astyle -h'", L"Para obter ajuda sobre as opções de tipo 'astyle -h'"); - addPair("Cannot open default option file", L"Não é possível abrir o arquivo de opção padrão"); - addPair("Cannot open project option file", L"Não é possível abrir o arquivo de opção do projeto"); - addPair("Cannot open directory", L"Não é possível abrir diretório"); - addPair("Cannot open HTML file %s\n", L"Não é possível abrir arquivo HTML %s\n"); - addPair("Command execute failure", L"Executar falha de comando"); - addPair("Command is not installed", L"Comando não está instalado"); - addPair("Missing filename in %s\n", L"Filename faltando em %s\n"); - addPair("Recursive option with no wildcard", L"Opção recursiva sem curinga"); - addPair("Did you intend quote the filename", L"Será que você pretende citar o nome do arquivo"); - addPair("No file to process %s\n", L"Nenhum arquivo para processar %s\n"); - addPair("Did you intend to use --recursive", L"Será que você pretende usar --recursive"); - addPair("Cannot process UTF-32 encoding", L"Não pode processar a codificação UTF-32"); - addPair("Artistic Style has terminated\n", L"Artistic Style terminou\n"); -} - -Romanian::Romanian() // Română -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formatat %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Neschimbat %s\n"); // should align with formatted - addPair("Directory %s\n", L"Director %s\n"); - addPair("Default option file %s\n", L"Fișier opțional implicit %s\n"); - addPair("Project option file %s\n", L"Fișier opțiune proiect %s\n"); - addPair("Exclude %s\n", L"Excludeți %s\n"); - addPair("Exclude (unmatched) %s\n", L"Excludeți (necompensată) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formatat %s neschimbat "); - addPair(" seconds ", L" secunde "); - addPair("%d min %d sec ", L"%d min %d sec "); - addPair("%s lines\n", L"%s linii\n"); - addPair("Opening HTML documentation %s\n", L"Documentație HTML deschidere %s\n"); - addPair("Invalid default options:", L"Opțiuni implicite nevalide:"); - addPair("Invalid project options:", L"Opțiunile de proiect nevalide:"); - addPair("Invalid command line options:", L"Opțiuni de linie de comandă nevalide:"); - addPair("For help on options type 'astyle -h'", L"Pentru ajutor cu privire la tipul de opțiuni 'astyle -h'"); - addPair("Cannot open default option file", L"Nu se poate deschide fișierul cu opțiuni implicite"); - addPair("Cannot open project option file", L"Nu se poate deschide fișierul cu opțiuni de proiect"); - addPair("Cannot open directory", L"Nu se poate deschide directorul"); - addPair("Cannot open HTML file %s\n", L"Nu se poate deschide fișierul HTML %s\n"); - addPair("Command execute failure", L"Comandă executa eșec"); - addPair("Command is not installed", L"Comanda nu este instalat"); - addPair("Missing filename in %s\n", L"Lipsă nume de fișier %s\n"); - addPair("Recursive option with no wildcard", L"Opțiunea recursiv cu nici un wildcard"); - addPair("Did you intend quote the filename", L"V-intentionati cita numele de fișier"); - addPair("No file to process %s\n", L"Nu există un fișier pentru a procesa %s\n"); - addPair("Did you intend to use --recursive", L"V-ați intenționați să utilizați --recursive"); - addPair("Cannot process UTF-32 encoding", L"Nu se poate procesa codificarea UTF-32"); - addPair("Artistic Style has terminated\n", L"Artistic Style a terminat\n"); -} - -Russian::Russian() // русский -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Форматированный %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"без изменений %s\n"); // should align with formatted - addPair("Directory %s\n", L"каталог %s\n"); - addPair("Default option file %s\n", L"Файл с опцией по умолчанию %s\n"); - addPair("Project option file %s\n", L"Файл опций проекта %s\n"); - addPair("Exclude %s\n", L"исключать %s\n"); - addPair("Exclude (unmatched) %s\n", L"Исключить (непревзойденный) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s Форматированный %s без изменений "); - addPair(" seconds ", L" секунды "); - addPair("%d min %d sec ", L"%d мин %d сек "); - addPair("%s lines\n", L"%s линий\n"); - addPair("Opening HTML documentation %s\n", L"Открытие HTML документации %s\n"); - addPair("Invalid default options:", L"Недействительные параметры по умолчанию:"); - addPair("Invalid project options:", L"Недопустимые параметры проекта:"); - addPair("Invalid command line options:", L"Недопустимые параметры командной строки:"); - addPair("For help on options type 'astyle -h'", L"Для получения справки по 'astyle -h' опций типа"); - addPair("Cannot open default option file", L"Не удается открыть файл параметров по умолчанию"); - addPair("Cannot open project option file", L"Не удается открыть файл опций проекта"); - addPair("Cannot open directory", L"Не могу открыть каталог"); - addPair("Cannot open HTML file %s\n", L"Не удается открыть файл HTML %s\n"); - addPair("Command execute failure", L"Выполнить команду недостаточности"); - addPair("Command is not installed", L"Не установлен Команда"); - addPair("Missing filename in %s\n", L"Отсутствует имя файла в %s\n"); - addPair("Recursive option with no wildcard", L"Рекурсивный вариант без каких-либо шаблона"); - addPair("Did you intend quote the filename", L"Вы намерены цитатой файла"); - addPair("No file to process %s\n", L"Нет файлов для обработки %s\n"); - addPair("Did you intend to use --recursive", L"Неужели вы собираетесь использовать --recursive"); - addPair("Cannot process UTF-32 encoding", L"Не удается обработать UTF-32 кодировке"); - addPair("Artistic Style has terminated\n", L"Artistic Style прекратил\n"); -} - -Spanish::Spanish() // Español -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formato %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Inalterado %s\n"); // should align with formatted - addPair("Directory %s\n", L"Directorio %s\n"); - addPair("Default option file %s\n", L"Archivo de opciones predeterminado %s\n"); - addPair("Project option file %s\n", L"Archivo de opciones del proyecto %s\n"); - addPair("Exclude %s\n", L"Excluir %s\n"); - addPair("Exclude (unmatched) %s\n", L"Excluir (incomparable) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formato %s inalterado "); - addPair(" seconds ", L" segundo "); - addPair("%d min %d sec ", L"%d min %d seg "); - addPair("%s lines\n", L"%s líneas\n"); - addPair("Opening HTML documentation %s\n", L"Apertura de documentación HTML %s\n"); - addPair("Invalid default options:", L"Opciones predeterminadas no válidas:"); - addPair("Invalid project options:", L"Opciones de proyecto no válidas:"); - addPair("Invalid command line options:", L"No válido opciones de línea de comando:"); - addPair("For help on options type 'astyle -h'", L"Para obtener ayuda sobre las opciones tipo 'astyle -h'"); - addPair("Cannot open default option file", L"No se puede abrir el archivo de opciones predeterminado"); - addPair("Cannot open project option file", L"No se puede abrir el archivo de opciones del proyecto"); - addPair("Cannot open directory", L"No se puede abrir el directorio"); - addPair("Cannot open HTML file %s\n", L"No se puede abrir el archivo HTML %s\n"); - addPair("Command execute failure", L"Ejecutar el fracaso de comandos"); - addPair("Command is not installed", L"El comando no está instalado"); - addPair("Missing filename in %s\n", L"Falta nombre del archivo en %s\n"); - addPair("Recursive option with no wildcard", L"Recursiva opción sin comodín"); - addPair("Did you intend quote the filename", L"Se tiene la intención de citar el nombre de archivo"); - addPair("No file to process %s\n", L"No existe el fichero a procesar %s\n"); - addPair("Did you intend to use --recursive", L"Se va a utilizar --recursive"); - addPair("Cannot process UTF-32 encoding", L"No se puede procesar la codificación UTF-32"); - addPair("Artistic Style has terminated\n", L"Artistic Style ha terminado\n"); -} - -Swedish::Swedish() // Svenska -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"Formaterade %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"Oförändrade %s\n"); // should align with formatted - addPair("Directory %s\n", L"Katalog %s\n"); - addPair("Default option file %s\n", L"Standardalternativsfil %s\n"); - addPair("Project option file %s\n", L"Projektalternativ fil %s\n"); - addPair("Exclude %s\n", L"Uteslut %s\n"); - addPair("Exclude (unmatched) %s\n", L"Uteslut (oöverträffad) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s formaterade %s oförändrade "); - addPair(" seconds ", L" sekunder "); - addPair("%d min %d sec ", L"%d min %d sek "); - addPair("%s lines\n", L"%s linjer\n"); - addPair("Opening HTML documentation %s\n", L"Öppna HTML-dokumentation %s\n"); - addPair("Invalid default options:", L"Ogiltiga standardalternativ:"); - addPair("Invalid project options:", L"Ogiltiga projektalternativ:"); - addPair("Invalid command line options:", L"Ogiltig kommandoraden alternativ:"); - addPair("For help on options type 'astyle -h'", L"För hjälp om alternativ typ 'astyle -h'"); - addPair("Cannot open default option file", L"Kan inte öppna standardalternativsfilen"); - addPair("Cannot open project option file", L"Kan inte öppna projektalternativsfilen"); - addPair("Cannot open directory", L"Kan inte öppna katalog"); - addPair("Cannot open HTML file %s\n", L"Kan inte öppna HTML-filen %s\n"); - addPair("Command execute failure", L"Utför kommando misslyckande"); - addPair("Command is not installed", L"Kommandot är inte installerat"); - addPair("Missing filename in %s\n", L"Saknade filnamn i %s\n"); - addPair("Recursive option with no wildcard", L"Rekursiva alternativ utan jokertecken"); - addPair("Did you intend quote the filename", L"Visste du tänker citera filnamnet"); - addPair("No file to process %s\n", L"Ingen fil att bearbeta %s\n"); - addPair("Did you intend to use --recursive", L"Har du för avsikt att använda --recursive"); - addPair("Cannot process UTF-32 encoding", L"Kan inte hantera UTF-32 kodning"); - addPair("Artistic Style has terminated\n", L"Artistic Style har upphört\n"); -} - -Ukrainian::Ukrainian() // Український -// build the translation vector in the Translation base class -{ - addPair("Formatted %s\n", L"форматований %s\n"); // should align with unchanged - addPair("Unchanged %s\n", L"без змін %s\n"); // should align with formatted - addPair("Directory %s\n", L"Каталог %s\n"); - addPair("Default option file %s\n", L"Файл параметра за замовчуванням %s\n"); - addPair("Project option file %s\n", L"Файл варіанту проекту %s\n"); - addPair("Exclude %s\n", L"Виключити %s\n"); - addPair("Exclude (unmatched) %s\n", L"Виключити (неперевершений) %s\n"); - addPair(" %s formatted %s unchanged ", L" %s відформатований %s без змін "); - addPair(" seconds ", L" секунди "); - addPair("%d min %d sec ", L"%d хви %d cek "); - addPair("%s lines\n", L"%s ліній\n"); - addPair("Opening HTML documentation %s\n", L"Відкриття HTML документації %s\n"); - addPair("Invalid default options:", L"Недійсні параметри за умовчанням:"); - addPair("Invalid project options:", L"Недійсні параметри проекту:"); - addPair("Invalid command line options:", L"Неприпустима параметри командного рядка:"); - addPair("For help on options type 'astyle -h'", L"Для отримання довідки по 'astyle -h' опцій типу"); - addPair("Cannot open default option file", L"Неможливо відкрити файл параметрів за замовчуванням"); - addPair("Cannot open project option file", L"Неможливо відкрити файл параметрів проекту"); - addPair("Cannot open directory", L"Не можу відкрити каталог"); - addPair("Cannot open HTML file %s\n", L"Не вдається відкрити файл HTML %s\n"); - addPair("Command execute failure", L"Виконати команду недостатності"); - addPair("Command is not installed", L"Не встановлений Команда"); - addPair("Missing filename in %s\n", L"Відсутня назва файлу в %s\n"); - addPair("Recursive option with no wildcard", L"Рекурсивний варіант без будь-яких шаблону"); - addPair("Did you intend quote the filename", L"Ви маєте намір цитатою файлу"); - addPair("No file to process %s\n", L"Немає файлів для обробки %s\n"); - addPair("Did you intend to use --recursive", L"Невже ви збираєтеся використовувати --recursive"); - addPair("Cannot process UTF-32 encoding", L"Не вдається обробити UTF-32 кодуванні"); - addPair("Artistic Style has terminated\n", L"Artistic Style припинив\n"); -} - - -#endif // ASTYLE_LIB - -} // end of namespace astyle - diff --git a/tools/astyle/ASLocalizer.h b/tools/astyle/ASLocalizer.h deleted file mode 100644 index 116369d9..00000000 --- a/tools/astyle/ASLocalizer.h +++ /dev/null @@ -1,172 +0,0 @@ -// ASLocalizer.h -// Copyright (c) 2018 by Jim Pattee . -// 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 -#include - -// 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 { - -using namespace std; - -#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(); - 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 - string m_langID; // language identifier from the locale - 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 vector and settext translation method. -// The language 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; - string convertToMultiByte(const wstring& wideStr) const; - string getTranslationString(size_t i) const; - size_t getTranslationVectorSize() const; - bool getWideTranslation(const string& stringIn, wstring& wideOut) const; - string& translate(const string& stringIn) const; - -protected: - void addPair(const string& english, const wstring& translated); - // variables - vector > m_translationVector; - -private: - // the number of translation pairs added a constructor - static const size_t translationElements = 30; // need static for vs2013 - // the translated string - mutable string m_mbTranslation; -}; - -//---------------------------------------------------------------------------- -// Translation classes -// One class for each language. -// These classes have only a constructor which builds the language 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 diff --git a/tools/astyle/ASResource.cpp b/tools/astyle/ASResource.cpp deleted file mode 100644 index a45ad784..00000000 --- a/tools/astyle/ASResource.cpp +++ /dev/null @@ -1,805 +0,0 @@ -// ASResource.cpp -// Copyright (c) 2018 by Jim Pattee . -// 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 - -//----------------------------------------------------------------------------- -// astyle namespace -//----------------------------------------------------------------------------- - -namespace astyle { -// -const string ASResource::_AS_EXCEPT = string("__except"); -const string ASResource::_AS_FINALLY = string("__finally"); -const string ASResource::_AS_TRY = string("__try"); -const string ASResource::AS_ADD = string("add"); -const string ASResource::AS_AUTO = string("auto"); -const string ASResource::AS_AUTORELEASEPOOL = string("autoreleasepool"); -const string ASResource::AS_CASE = string("case"); -const string ASResource::AS_CATCH = string("catch"); -const string ASResource::AS_CLASS = string("class"); -const string ASResource::AS_CONST = string("const"); -const string ASResource::AS_CONST_CAST = string("const_cast"); -const string ASResource::AS_DEFAULT = string("default"); -const string ASResource::AS_DELEGATE = string("delegate"); -const string ASResource::AS_DELETE = string("delete"); -const string ASResource::AS_DO = string("do"); -const string ASResource::AS_DYNAMIC_CAST = string("dynamic_cast"); -const string ASResource::AS_ELSE = string("else"); -const string ASResource::AS_END = string("end"); -const string ASResource::AS_ENUM = string("enum"); -const string ASResource::AS_EXTERN = string("extern"); -const string ASResource::AS_FINAL = string("final"); -const string ASResource::AS_FINALLY = string("finally"); -const string ASResource::AS_FIXED = string("fixed"); -const string ASResource::AS_FOR = string("for"); -const string ASResource::AS_FOREACH = string("foreach"); -const string ASResource::AS_FOREVER = string("forever"); -const string ASResource::AS_GET = string("get"); -const string ASResource::AS_IF = string("if"); -const string ASResource::AS_INTERFACE = string("interface"); -const string ASResource::AS_INTERRUPT = string("interrupt"); -const string ASResource::AS_LET = string("let"); -const string ASResource::AS_LOCK = string("lock"); -const string ASResource::AS_MODULE = string("module"); // CORBA IDL module definition -const string ASResource::AS_NAMESPACE = string("namespace"); -const string ASResource::AS_NEW = string("new"); -const string ASResource::AS_NOEXCEPT = string("noexcept"); -const string ASResource::AS_NS_DURING = string("NS_DURING"); -const string ASResource::AS_NS_HANDLER = string("NS_HANDLER"); -const string ASResource::AS_OPERATOR = string("operator"); -const string ASResource::AS_OVERRIDE = string("override"); -const string ASResource::AS_PRIVATE = string("private"); -const string ASResource::AS_PROTECTED = string("protected"); -const string ASResource::AS_PUBLIC = string("public"); -const string ASResource::AS_QFOREACH = string("Q_FOREACH"); -const string ASResource::AS_QFOREVER = string("Q_FOREVER"); -const string ASResource::AS_REINTERPRET_CAST = string("reinterpret_cast"); -const string ASResource::AS_REMOVE = string("remove"); -const string ASResource::AS_SEALED = string("sealed"); -const string ASResource::AS_SELECTOR = string("selector"); -const string ASResource::AS_SET = string("set"); -const string ASResource::AS_STATIC = string("static"); -const string ASResource::AS_STATIC_CAST = string("static_cast"); -const string ASResource::AS_STRUCT = string("struct"); -const string ASResource::AS_SWITCH = string("switch"); -const string ASResource::AS_SYNCHRONIZED = string("synchronized"); -const string ASResource::AS_TEMPLATE = string("template"); -const string ASResource::AS_THROW = string("throw"); -const string ASResource::AS_THROWS = string("throws"); -const string ASResource::AS_TRY = string("try"); -const string ASResource::AS_UNCHECKED = string("unchecked"); -const string ASResource::AS_UNION = string("union"); -const string ASResource::AS_UNSAFE = string("unsafe"); -const string ASResource::AS_USING = string("using"); -const string ASResource::AS_VOLATILE = string("volatile"); -const string ASResource::AS_WHERE = string("where"); -const string ASResource::AS_WHILE = string("while"); - -const string ASResource::AS_ASM = string("asm"); -const string ASResource::AS__ASM__ = string("__asm__"); -const string ASResource::AS_MS_ASM = string("_asm"); -const string ASResource::AS_MS__ASM = string("__asm"); - -const string ASResource::AS_BAR_DEFINE = string("#define"); -const string ASResource::AS_BAR_INCLUDE = string("#include"); -const string ASResource::AS_BAR_IF = string("#if"); -const string ASResource::AS_BAR_EL = string("#el"); -const string ASResource::AS_BAR_ENDIF = string("#endif"); - -const string ASResource::AS_OPEN_BRACE = string("{"); -const string ASResource::AS_CLOSE_BRACE = string("}"); -const string ASResource::AS_OPEN_LINE_COMMENT = string("//"); -const string ASResource::AS_OPEN_COMMENT = string("/*"); -const string ASResource::AS_CLOSE_COMMENT = string("*/"); - -const string ASResource::AS_ASSIGN = string("="); -const string ASResource::AS_PLUS_ASSIGN = string("+="); -const string ASResource::AS_MINUS_ASSIGN = string("-="); -const string ASResource::AS_MULT_ASSIGN = string("*="); -const string ASResource::AS_DIV_ASSIGN = string("/="); -const string ASResource::AS_MOD_ASSIGN = string("%="); -const string ASResource::AS_OR_ASSIGN = string("|="); -const string ASResource::AS_AND_ASSIGN = string("&="); -const string ASResource::AS_XOR_ASSIGN = string("^="); -const string ASResource::AS_GR_GR_ASSIGN = string(">>="); -const string ASResource::AS_LS_LS_ASSIGN = string("<<="); -const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>="); -const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<="); -const string ASResource::AS_GCC_MIN_ASSIGN = string("?"); - -const string ASResource::AS_RETURN = string("return"); -const string ASResource::AS_CIN = string("cin"); -const string ASResource::AS_COUT = string("cout"); -const string ASResource::AS_CERR = string("cerr"); - -const string ASResource::AS_EQUAL = string("=="); -const string ASResource::AS_PLUS_PLUS = string("++"); -const string ASResource::AS_MINUS_MINUS = string("--"); -const string ASResource::AS_NOT_EQUAL = string("!="); -const string ASResource::AS_GR_EQUAL = string(">="); -const string ASResource::AS_GR_GR = string(">>"); -const string ASResource::AS_GR_GR_GR = string(">>>"); -const string ASResource::AS_LS_EQUAL = string("<="); -const string ASResource::AS_LS_LS = string("<<"); -const string ASResource::AS_LS_LS_LS = string("<<<"); -const string ASResource::AS_THREEWAY_COMPARISION = string("<=>"); -const string ASResource::AS_QUESTION_QUESTION = string("??"); -const string ASResource::AS_LAMBDA = string("=>"); // C# lambda expression arrow -const string ASResource::AS_ARROW = string("->"); -const string ASResource::AS_AND = string("&&"); -const string ASResource::AS_OR = string("||"); -const string ASResource::AS_SCOPE_RESOLUTION = string("::"); - -const string ASResource::AS_PLUS = string("+"); -const string ASResource::AS_MINUS = string("-"); -const string ASResource::AS_MULT = string("*"); -const string ASResource::AS_DIV = string("/"); -const string ASResource::AS_MOD = string("%"); -const string ASResource::AS_GR = string(">"); -const string ASResource::AS_LS = string("<"); -const string ASResource::AS_NOT = string("!"); -const string ASResource::AS_BIT_OR = string("|"); -const string ASResource::AS_BIT_AND = string("&"); -const string ASResource::AS_BIT_NOT = string("~"); -const string ASResource::AS_BIT_XOR = string("^"); -const string ASResource::AS_QUESTION = string("?"); -const string ASResource::AS_COLON = string(":"); -const string ASResource::AS_COMMA = string(","); -const string ASResource::AS_SEMICOLON = string(";"); - -/** - * Sort comparison function. - * Compares the length of the value of pointers in the vectors. - * The LONGEST strings will be first in the vector. - * - * @param a and b, the string pointers to be compared. - */ -bool sortOnLength(const string* a, const string* b) -{ - return (*a).length() > (*b).length(); -} - -/** - * Sort comparison function. - * Compares the value of pointers in the vectors. - * - * @param a and b, the string pointers to be compared. - */ -bool sortOnName(const string* a, const 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(vector* 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(vector* 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(vector* 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) - { - 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) - { - 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(vector* indentableHeaders) -{ - indentableHeaders->emplace_back(&AS_RETURN); - -// sort(indentableHeaders->begin(), indentableHeaders->end(), sortOnName); -} - -/** -* 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(vector* >* indentableMacros) -{ - const size_t elements = 10; - indentableMacros->reserve(elements); - - // the pairs must be retained in memory because of pair pointers - using macro_pair = pair; - 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(¯o); - - 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. - */ -void ASResource::buildNonAssignmentOperators(vector* nonAssignmentOperators) -{ -// 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_GR); - nonAssignmentOperators->emplace_back(&AS_GR_GR); - nonAssignmentOperators->emplace_back(&AS_LS_EQUAL); - nonAssignmentOperators->emplace_back(&AS_LS_LS_LS); - 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_THREEWAY_COMPARISION); - -// 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 vector to be built. - */ -void ASResource::buildNonParenHeaders(vector* 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) - { - 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(vector* 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_THREEWAY_COMPARISION); - - 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); - } - - 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(vector* preBlockStatements, int fileType) -{ - const size_t elements = 10; - preBlockStatements->reserve(elements); - - preBlockStatements->emplace_back(&AS_CLASS); - if (fileType == C_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(vector* preCommandHeaders, int fileType) -{ - const size_t elements = 10; - preCommandHeaders->reserve(elements); - - if (fileType == C_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 - 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(vector* preDefinitionHeaders, int fileType) -{ - const size_t elements = 10; - preDefinitionHeaders->reserve(elements); - - preDefinitionHeaders->emplace_back(&AS_CLASS); - if (fileType == C_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 string* ASBase::findHeader(const string& line, int i, - const vector* possibleHeaders) const -{ - assert(isCharPotentialHeader(line, i)); - // check the word - size_t maxHeaders = possibleHeaders->size(); - for (size_t p = 0; p < maxHeaders; p++) - { - const 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 == &AS_GET - || header == &AS_SET - || header == &AS_DEFAULT) - && (peekChar == ';' || peekChar == '(' || peekChar == '=')) - break; - return header; - } - return nullptr; -} - -// check if a specific line position contains a keyword. -bool ASBase::findKeyword(const string& line, int i, const string& 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()) - 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; - return true; -} - -// check if a specific line position contains an operator. -const string* ASBase::findOperator(const string& line, int i, - const vector* 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 -string ASBase::getCurrentWord(const string& 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])) - 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 (isWhiteSpace(ch)) - return false; -// if ((unsigned char) ch > 127) -// return false; - if ((unsigned char) ch > 127) - return true; - return (isalnum((unsigned char) ch) - || ch == '.' || 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(const string& line, size_t i) const -{ - assert(!isWhiteSpace(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(!isWhiteSpace(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'); -} - -bool ASBase::isHexDigit(char ch) const -{ - return (ch >= '0' && ch <= '9') - || (ch >= 'a' && ch <= 'f') - || (ch >= 'A' && ch <= 'F'); -} - -bool ASBase::isLetterOrUnderLine(char ch) const -{ return (ch >= 'a' && ch <= 'z') - || (ch >= 'A' && ch <= 'Z') - || (ch == '_'); - -} - -// check if a specific character is a digit separator -bool ASBase::isDigitSeparator(const string& 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(const string& line, int i) const -{ - char ch = ' '; - size_t peekNum = line.find_first_not_of(" \t", i + 1); - if (peekNum == string::npos) - return ch; - ch = line[peekNum]; - return ch; -} - -} // end namespace astyle diff --git a/tools/astyle/astyle.h b/tools/astyle/astyle.h deleted file mode 100644 index cbe87bc1..00000000 --- a/tools/astyle/astyle.h +++ /dev/null @@ -1,1096 +0,0 @@ -// astyle.h -// Copyright (c) 2018 by Jim Pattee . -// This code is licensed under the MIT License. -// License.md describes the conditions under which this software may be distributed. - -#ifndef ASTYLE_H -#define ASTYLE_H - -//----------------------------------------------------------------------------- -// headers -//----------------------------------------------------------------------------- - -#ifdef __VMS - #define __USE_STD_IOSTREAM 1 - #include -#else - #include -#endif - -#include -#include // for cout -#include -#include -#include - -#ifdef __GNUC__ - #include // need both string and cstring for GCC -#endif - -//----------------------------------------------------------------------------- -// declarations -//----------------------------------------------------------------------------- - -#ifdef _MSC_VER - #pragma warning(disable: 4267) // conversion from size_t to int -#endif - -#ifdef __BORLANDC__ - #pragma warn -8004 // variable is assigned a value that is never used -#endif - -#ifdef __GNUC__ - #pragma GCC diagnostic ignored "-Wconversion" -#endif - -#ifdef __INTEL_COMPILER - // #pragma warning disable 383 // value copied to temporary, reference to temporary used - // #pragma warning disable 981 // operands are evaluated in unspecified order -#endif - -#ifdef __clang__ - #pragma clang diagnostic ignored "-Wshorten-64-to-32" -#endif - -//----------------------------------------------------------------------------- -// astyle namespace -//----------------------------------------------------------------------------- - -namespace astyle { -// -using namespace std; - -//---------------------------------------------------------------------------- -// definitions -//---------------------------------------------------------------------------- - -enum FileType { C_TYPE = 0, JAVA_TYPE = 1, SHARP_TYPE = 2 }; - -/* The enums below are not recognized by 'vectors' in Microsoft Visual C++ - V5 when they are part of a namespace!!! Use Visual C++ V6 or higher. -*/ -enum FormatStyle -{ - STYLE_NONE, - STYLE_ALLMAN, - STYLE_JAVA, - STYLE_KR, - STYLE_STROUSTRUP, - STYLE_WHITESMITH, - STYLE_VTK, - STYLE_RATLIFF, - STYLE_GNU, - STYLE_LINUX, - STYLE_HORSTMANN, - STYLE_1TBS, - STYLE_GOOGLE, - STYLE_MOZILLA, - STYLE_WEBKIT, - STYLE_PICO, - STYLE_LISP -}; - -enum BraceMode -{ - NONE_MODE, - ATTACH_MODE, - BREAK_MODE, - LINUX_MODE, - RUN_IN_MODE // broken braces -}; - -// maximum single value for size_t is 32,768 (total value of 65,535) -enum BraceType : size_t -{ - NULL_TYPE = 0, - NAMESPACE_TYPE = 1, // also a DEFINITION_TYPE - CLASS_TYPE = 2, // also a DEFINITION_TYPE - STRUCT_TYPE = 4, // also a DEFINITION_TYPE - INTERFACE_TYPE = 8, // also a DEFINITION_TYPE - DEFINITION_TYPE = 16, - COMMAND_TYPE = 32, - ARRAY_NIS_TYPE = 64, // also an ARRAY_TYPE - ENUM_TYPE = 128, // also an ARRAY_TYPE - INIT_TYPE = 256, // also an ARRAY_TYPE - ARRAY_TYPE = 512, - EXTERN_TYPE = 1024, // extern "C", not a command type extern - EMPTY_BLOCK_TYPE = 2048, // also a SINGLE_LINE_TYPE - BREAK_BLOCK_TYPE = 4096, // also a SINGLE_LINE_TYPE - SINGLE_LINE_TYPE = 8192 -}; - -enum MinConditional -{ - MINCOND_ZERO, - MINCOND_ONE, - MINCOND_TWO, - MINCOND_ONEHALF, - MINCOND_END -}; - -enum ObjCColonPad -{ - COLON_PAD_NO_CHANGE, - COLON_PAD_NONE, - COLON_PAD_ALL, - COLON_PAD_AFTER, - COLON_PAD_BEFORE -}; - -enum PointerAlign -{ - PTR_ALIGN_NONE, - PTR_ALIGN_TYPE, - PTR_ALIGN_MIDDLE, - PTR_ALIGN_NAME -}; - -enum ReferenceAlign -{ - REF_ALIGN_NONE = PTR_ALIGN_NONE, - REF_ALIGN_TYPE = PTR_ALIGN_TYPE, - REF_ALIGN_MIDDLE = PTR_ALIGN_MIDDLE, - REF_ALIGN_NAME = PTR_ALIGN_NAME, - REF_SAME_AS_PTR -}; - -enum FileEncoding -{ - ENCODING_8BIT, // includes UTF-8 without BOM - UTF_8BOM, // UTF-8 with BOM - UTF_16BE, - UTF_16LE, // Windows default - UTF_32BE, - UTF_32LE -}; - -enum LineEndFormat -{ - LINEEND_DEFAULT, // Use line break that matches most of the file - LINEEND_WINDOWS, - LINEEND_LINUX, - LINEEND_MACOLD, - LINEEND_CRLF = LINEEND_WINDOWS, - LINEEND_LF = LINEEND_LINUX, - LINEEND_CR = LINEEND_MACOLD -}; - -//----------------------------------------------------------------------------- -// Class ASSourceIterator -// A pure virtual class is used by ASFormatter and ASBeautifier instead of -// ASStreamIterator. This allows programs using AStyle as a plug-in to define -// their own ASStreamIterator. The ASStreamIterator class must inherit -// this class. -//----------------------------------------------------------------------------- - -class ASSourceIterator -{ -public: - ASSourceIterator() = default; - virtual ~ASSourceIterator() = default; - virtual streamoff getPeekStart() const = 0; - virtual int getStreamLength() const = 0; - virtual bool hasMoreLines() const = 0; - virtual string nextLine(bool emptyLineWasDeleted) = 0; - virtual string peekNextLine() = 0; - virtual void peekReset() = 0; - virtual streamoff tellg() = 0; -}; - -//----------------------------------------------------------------------------- -// Class ASPeekStream -// A small class using RAII to peek ahead in the ASSourceIterator stream -// and to reset the ASSourceIterator pointer in the destructor. -// It enables a return from anywhere in the method. -//----------------------------------------------------------------------------- - -class ASPeekStream -{ -private: - ASSourceIterator* sourceIterator; - bool needReset; // reset sourceIterator to the original position - -public: - explicit ASPeekStream(ASSourceIterator* sourceIterator_) - { sourceIterator = sourceIterator_; needReset = false; } - - ~ASPeekStream() - { if (needReset) sourceIterator->peekReset(); } - - bool hasMoreLines() const - { return sourceIterator->hasMoreLines(); } - - string peekNextLine() - { needReset = true; return sourceIterator->peekNextLine(); } -}; - - -//----------------------------------------------------------------------------- -// Class ASResource -//----------------------------------------------------------------------------- - -class ASResource -{ -public: - void buildAssignmentOperators(vector* assignmentOperators); - void buildCastOperators(vector* castOperators); - void buildHeaders(vector* headers, int fileType, bool beautifier = false); - void buildIndentableMacros(vector* >* indentableMacros); - void buildIndentableHeaders(vector* indentableHeaders); - void buildNonAssignmentOperators(vector* nonAssignmentOperators); - void buildNonParenHeaders(vector* nonParenHeaders, int fileType, bool beautifier = false); - void buildOperators(vector* operators, int fileType); - void buildPreBlockStatements(vector* preBlockStatements, int fileType); - void buildPreCommandHeaders(vector* preCommandHeaders, int fileType); - void buildPreDefinitionHeaders(vector* preDefinitionHeaders, int fileType); - -public: - static const string AS_IF, AS_ELSE; - static const string AS_DO, AS_WHILE; - static const string AS_FOR; - static const string AS_SWITCH, AS_CASE, AS_DEFAULT; - static const string AS_TRY, AS_CATCH, AS_THROW, AS_THROWS, AS_FINALLY, AS_USING; - static const string _AS_TRY, _AS_FINALLY, _AS_EXCEPT; - static const string AS_PUBLIC, AS_PROTECTED, AS_PRIVATE; - static const string AS_CLASS, AS_STRUCT, AS_UNION, AS_INTERFACE, AS_NAMESPACE; - static const string AS_MODULE; - static const string AS_END; - static const string AS_SELECTOR; - static const string AS_EXTERN, AS_ENUM; - static const string AS_FINAL, AS_OVERRIDE; - static const string AS_STATIC, AS_CONST, AS_SEALED, AS_VOLATILE, AS_NEW, AS_DELETE; - static const string AS_NOEXCEPT, AS_INTERRUPT, AS_AUTORELEASEPOOL; - static const string AS_WHERE, AS_LET, AS_SYNCHRONIZED; - static const string AS_OPERATOR, AS_TEMPLATE; - static const string AS_OPEN_BRACE, AS_CLOSE_BRACE; - static const string AS_OPEN_LINE_COMMENT, AS_OPEN_COMMENT, AS_CLOSE_COMMENT; - static const string AS_BAR_DEFINE, AS_BAR_INCLUDE, AS_BAR_IF, AS_BAR_EL, AS_BAR_ENDIF; - static const string AS_AUTO, AS_RETURN; - static const string AS_CIN, AS_COUT, AS_CERR; - static const string AS_ASSIGN, AS_PLUS_ASSIGN, AS_MINUS_ASSIGN, AS_MULT_ASSIGN; - static const string AS_DIV_ASSIGN, AS_MOD_ASSIGN, AS_XOR_ASSIGN, AS_OR_ASSIGN, AS_AND_ASSIGN; - static const string AS_GR_GR_ASSIGN, AS_LS_LS_ASSIGN, AS_GR_GR_GR_ASSIGN, AS_LS_LS_LS_ASSIGN; - static const string AS_GCC_MIN_ASSIGN, AS_GCC_MAX_ASSIGN; - static const string AS_EQUAL, AS_PLUS_PLUS, AS_MINUS_MINUS, AS_NOT_EQUAL, AS_GR_EQUAL; - static const string AS_LS_EQUAL, AS_LS_LS_LS, AS_LS_LS, AS_GR_GR_GR, AS_GR_GR; - static const string AS_THREEWAY_COMPARISION; - static const string AS_QUESTION_QUESTION, AS_LAMBDA; - static const string AS_ARROW, AS_AND, AS_OR; - static const string AS_SCOPE_RESOLUTION; - static const string AS_PLUS, AS_MINUS, AS_MULT, AS_DIV, AS_MOD, AS_GR, AS_LS; - static const string AS_NOT, AS_BIT_XOR, AS_BIT_OR, AS_BIT_AND, AS_BIT_NOT; - static const string AS_QUESTION, AS_COLON, AS_SEMICOLON, AS_COMMA; - static const string AS_ASM, AS__ASM__, AS_MS_ASM, AS_MS__ASM; - static const string AS_QFOREACH, AS_QFOREVER, AS_FOREVER; - static const string AS_FOREACH, AS_LOCK, AS_UNSAFE, AS_FIXED; - static const string AS_GET, AS_SET, AS_ADD, AS_REMOVE; - static const string AS_DELEGATE, AS_UNCHECKED; - static const string AS_CONST_CAST, AS_DYNAMIC_CAST, AS_REINTERPRET_CAST, AS_STATIC_CAST; - static const string AS_NS_DURING, AS_NS_HANDLER; -}; // Class ASResource - -//----------------------------------------------------------------------------- -// Class ASBase -// Functions definitions are at the end of ASResource.cpp. -//----------------------------------------------------------------------------- - -class ASBase : protected ASResource -{ -private: - // all variables should be set by the "init" function - int baseFileType = C_TYPE; // a value from enum FileType - -protected: - ASBase() = default; - -protected: // inline functions - void init(int fileTypeArg) { baseFileType = fileTypeArg; } - bool isCStyle() const { return (baseFileType == C_TYPE); } - bool isJavaStyle() const { return (baseFileType == JAVA_TYPE); } - bool isSharpStyle() const { return (baseFileType == SHARP_TYPE); } - bool isWhiteSpace(char ch) const { return (ch == ' ' || ch == '\t'); } - -protected: // functions definitions are at the end of ASResource.cpp - const string* findHeader(const string& line, int i, - const vector* possibleHeaders) const; - bool findKeyword(const string& line, int i, const string& keyword) const; - const string* findOperator(const string& line, int i, - const vector* possibleOperators) const; - string getCurrentWord(const string& line, size_t index) const; - bool isDigit(char ch) const; - bool isHexDigit(char ch) const; - bool isLetterOrUnderLine(char ch) const; - bool isLegalNameChar(char ch) const; - bool isCharPotentialHeader(const string& line, size_t i) const; - bool isCharPotentialOperator(char ch) const; - bool isDigitSeparator(const string& line, int i) const; - char peekNextChar(const string& line, int i) const; - -}; // Class ASBase - -//----------------------------------------------------------------------------- -// Class ASBeautifier -//----------------------------------------------------------------------------- - -class ASBeautifier : protected ASBase -{ -public: - ASBeautifier(); - virtual ~ASBeautifier(); - ASBeautifier(const ASBeautifier& other); - ASBeautifier& operator=(ASBeautifier const&) = delete; - ASBeautifier(ASBeautifier&&) = delete; - ASBeautifier& operator=(ASBeautifier&&) = delete; - virtual void init(ASSourceIterator* iter); - - virtual string beautify(const string& originalLine); - void setCaseIndent(bool state); - void setClassIndent(bool state); - void setContinuationIndentation(int indent = 1); - void setCStyle(); - void setDefaultTabLength(); - void setEmptyLineFill(bool state); - void setForceTabXIndentation(int length); - void setAfterParenIndent(bool state); - void setJavaStyle(); - void setLabelIndent(bool state); - void setMaxContinuationIndentLength(int max); - void setMaxInStatementIndentLength(int max); - void setMinConditionalIndentOption(int min); - void setMinConditionalIndentLength(); - void setModeManuallySet(bool state); - void setModifierIndent(bool state); - void setNamespaceIndent(bool state); - void setAlignMethodColon(bool state); - void setSharpStyle(); - void setSpaceIndentation(int length = 4); - void setSwitchIndent(bool state); - void setTabIndentation(int length = 4, bool forceTabs = false); - void setPreprocDefineIndent(bool state); - void setPreprocConditionalIndent(bool state); - int getBeautifierFileType() const; - int getFileType() const; - int getIndentLength() const; - int getTabLength() const; - string getIndentString() const; - string getNextWord(const string& line, size_t currPos) const; - bool getAlignMethodColon() const; - bool getBraceIndent() const; - bool getBlockIndent() const; - bool getCaseIndent() const; - bool getClassIndent() const; - bool getEmptyLineFill() const; - bool getForceTabIndentation() const; - bool getModeManuallySet() const; - bool getModifierIndent() const; - bool getNamespaceIndent() const; - bool getPreprocDefineIndent() const; - bool getSwitchIndent() const; - -protected: - void deleteBeautifierVectors(); - int getNextProgramCharDistance(const string& line, int i) const; - int indexOf(const vector& container, const string* element) const; - void setBlockIndent(bool state); - void setBraceIndent(bool state); - void setBraceIndentVtk(bool state); - string extractPreprocessorStatement(const string& line) const; - string trim(const string& str) const; - string rtrim(const string& str) const; - - // variables set by ASFormatter - must be updated in activeBeautifierStack - int inLineNumber; - int runInIndentContinuation; - int nonInStatementBrace; - int objCColonAlignSubsequent; // for subsequent lines not counting indent - bool lineCommentNoBeautify; - bool isElseHeaderIndent; - bool isCaseHeaderCommentIndent; - bool isNonInStatementArray; - bool isSharpAccessor; - bool isSharpDelegate; - bool isInExternC; - bool isInBeautifySQL; - bool isInIndentableStruct; - bool isInIndentablePreproc; - -private: // functions - void adjustObjCMethodDefinitionIndentation(const string& line_); - void adjustObjCMethodCallIndentation(const string& line_); - void adjustParsedLineIndentation(size_t iPrelim, bool isInExtraHeaderIndent); - void computePreliminaryIndentation(); - void parseCurrentLine(const string& line); - void popLastContinuationIndent(); - void processPreprocessor(const string& preproc, const string& line); - void registerContinuationIndent(const string& line, int i, int spaceIndentCount_, - int tabIncrementIn, int minIndent, bool updateParenStack); - void registerContinuationIndentColon(const string& line, int i, int tabIncrementIn); - void initVectors(); - void initTempStacksContainer(vector*>*& container, - vector*>* value); - void clearObjCMethodDefinitionAlignment(); - void deleteBeautifierContainer(vector*& container); - void deleteTempStacksContainer(vector*>*& container); - int adjustIndentCountForBreakElseIfComments() const; - int computeObjCColonAlignment(const string& line, int colonAlignPosition) const; - int convertTabToSpaces(int i, int tabIncrementIn) const; - int findObjCColonAlignment(const string& line) const; - int getContinuationIndentAssign(const string& line, size_t currPos) const; - int getContinuationIndentComma(const string& line, size_t currPos) const; - int getObjCFollowingKeyword(const string& line, int bracePos) const; - bool isIndentedPreprocessor(const string& line, size_t currPos) const; - bool isLineEndComment(const string& line, int startPos) const; - bool isPreprocessorConditionalCplusplus(const string& line) const; - bool isInPreprocessorUnterminatedComment(const string& line); - bool isTopLevel() const; - bool statementEndsWithComma(const string& line, int index) const; - const string& getIndentedLineReturn(const string& newLine, const string& originalLine) const; - string getIndentedSpaceEquivalent(const string& line_) const; - string preLineWS(int lineIndentCount, int lineSpaceIndentCount) const; - template void deleteContainer(T& container); - template void initContainer(T& container, T value); - vector*>* copyTempStacks(const ASBeautifier& other) const; - pair computePreprocessorIndent(); - -private: // variables - int beautifierFileType; - vector* headers; - vector* nonParenHeaders; - vector* preBlockStatements; - vector* preCommandHeaders; - vector* assignmentOperators; - vector* nonAssignmentOperators; - vector* indentableHeaders; - - vector* waitingBeautifierStack; - vector* activeBeautifierStack; - vector* waitingBeautifierStackLengthStack; - vector* activeBeautifierStackLengthStack; - vector* headerStack; - vector* >* tempStacks; - vector* parenDepthStack; - vector* blockStatementStack; - vector* parenStatementStack; - vector* braceBlockStateStack; - vector* continuationIndentStack; - vector* continuationIndentStackSizeStack; - vector* parenIndentStack; - vector >* preprocIndentStack; - - ASSourceIterator* sourceIterator; - const string* currentHeader; - const string* previousLastLineHeader; - const string* probationHeader; - const string* lastLineHeader; - string indentString; - string verbatimDelimiter; - bool isInQuote; - bool isInVerbatimQuote; - bool haveLineContinuationChar; - bool isInAsm; - bool isInAsmOneLine; - bool isInAsmBlock; - bool isInComment; - bool isInPreprocessorComment; - bool isInRunInComment; - bool isInCase; - bool isInQuestion; - bool isContinuation; - bool isInHeader; - bool isInTemplate; - bool isInDefine; - bool isInDefineDefinition; - bool classIndent; - bool isIndentModeOff; - bool isInClassHeader; // is in a class before the opening brace - bool isInClassHeaderTab; // is in an indentable class header line - bool isInClassInitializer; // is in a class after the ':' initializer - bool isInClass; // is in a class after the opening brace - bool isInObjCMethodDefinition; - bool isInObjCMethodCall; - bool isInObjCMethodCallFirst; - bool isImmediatelyPostObjCMethodDefinition; - bool isImmediatelyPostObjCMethodCall; - bool isInIndentablePreprocBlock; - bool isInObjCInterface; - bool isInEnum; - bool isInEnumTypeID; - bool isInLet; - bool isInTrailingReturnType; - bool modifierIndent; - bool switchIndent; - bool caseIndent; - bool namespaceIndent; - bool blockIndent; - bool braceIndent; - bool braceIndentVtk; - bool shouldIndentAfterParen; - bool labelIndent; - bool shouldIndentPreprocDefine; - bool isInConditional; - bool isModeManuallySet; - bool shouldForceTabIndentation; - bool emptyLineFill; - bool backslashEndsPrevLine; - bool lineOpensWithLineComment; - bool lineOpensWithComment; - bool lineStartsInComment; - bool blockCommentNoIndent; - bool blockCommentNoBeautify; - bool previousLineProbationTab; - bool lineBeginsWithOpenBrace; - bool lineBeginsWithCloseBrace; - bool lineBeginsWithComma; - bool lineIsCommentOnly; - bool lineIsLineCommentOnly; - bool shouldIndentBracedLine; - bool isInSwitch; - bool foundPreCommandHeader; - bool foundPreCommandMacro; - bool shouldAlignMethodColon; - bool shouldIndentPreprocConditional; - int indentCount; - int spaceIndentCount; - int spaceIndentObjCMethodAlignment; - int bracePosObjCMethodAlignment; - int colonIndentObjCMethodAlignment; - int lineOpeningBlocksNum; - int lineClosingBlocksNum; - int fileType; - int minConditionalOption; - int minConditionalIndent; - int parenDepth; - int indentLength; - int tabLength; - int continuationIndent; - int blockTabCount; - int maxContinuationIndent; - int classInitializerIndents; - int templateDepth; - int squareBracketCount; - int prevFinalLineSpaceIndentCount; - int prevFinalLineIndentCount; - int defineIndentCount; - int preprocBlockIndent; - char quoteChar; - char prevNonSpaceCh; - char currentNonSpaceCh; - char currentNonLegalCh; - char prevNonLegalCh; -}; // Class ASBeautifier - -//----------------------------------------------------------------------------- -// Class ASEnhancer -//----------------------------------------------------------------------------- - -class ASEnhancer : protected ASBase -{ -public: // functions - ASEnhancer() = default; - void init(int, int, int, bool, bool, bool, bool, bool, bool, bool, - vector* >*); - void enhance(string& line, bool isInNamespace, bool isInPreprocessor, bool isInSQL); - -private: // functions - void convertForceTabIndentToSpaces(string& line) const; - void convertSpaceIndentToForceTab(string& line) const; - size_t findCaseColon(const string& line, size_t caseIndex) const; - int indentLine(string& line, int indent) const; - bool isBeginDeclareSectionSQL(const string& line, size_t index) const; - bool isEndDeclareSectionSQL(const string& line, size_t index) const; - bool isOneLineBlockReached(const string& line, int startChar) const; - void parseCurrentLine(string& line, bool isInPreprocessor, bool isInSQL); - size_t processSwitchBlock(string& line, size_t index); - int unindentLine(string& line, int unindent) const; - -private: - // options from command line or options file - int indentLength; - int tabLength; - bool useTabs; - bool forceTab; - bool namespaceIndent; - bool caseIndent; - bool preprocBlockIndent; - bool preprocDefineIndent; - bool emptyLineFill; - - // parsing variables - int lineNumber; - bool isInQuote; - bool isInComment; - char quoteChar; - - // unindent variables - int braceCount; - int switchDepth; - int eventPreprocDepth; - bool lookingForCaseBrace; - bool unindentNextLine; - bool shouldUnindentLine; - bool shouldUnindentComment; - - // struct used by ParseFormattedLine function - // contains variables used to unindent the case blocks - struct SwitchVariables - { - int switchBraceCount; - int unindentDepth; - bool unindentCase; - }; - - SwitchVariables sw; // switch variables struct - vector switchStack; // stack vector of switch variables - - // event table variables - bool nextLineIsEventIndent; // begin event table indent is reached - bool isInEventTable; // need to indent an event table - vector* >* indentableMacros; - - // SQL variables - bool nextLineIsDeclareIndent; // begin declare section indent is reached - bool isInDeclareSection; // need to indent a declare section - -}; // Class ASEnhancer - -//----------------------------------------------------------------------------- -// Class ASFormatter -//----------------------------------------------------------------------------- - -class ASFormatter : public ASBeautifier -{ -public: // functions - ASFormatter(); - ~ASFormatter() override; - ASFormatter(const ASFormatter&) = delete; - ASFormatter& operator=(ASFormatter const&) = delete; - ASFormatter(ASFormatter&&) = delete; - ASFormatter& operator=(ASFormatter&&) = delete; - void init(ASSourceIterator* si) override; - - bool hasMoreLines() const; - string nextLine(); - LineEndFormat getLineEndFormat() const; - bool getIsLineReady() const; - void setFormattingStyle(FormatStyle style); - void setAddBracesMode(bool state); - void setAddOneLineBracesMode(bool state); - void setRemoveBracesMode(bool state); - void setAttachClass(bool state); - void setAttachClosingWhile(bool state); - void setAttachExternC(bool state); - void setAttachNamespace(bool state); - void setAttachInline(bool state); - void setBraceFormatMode(BraceMode mode); - void setBreakAfterMode(bool state); - void setBreakClosingHeaderBracesMode(bool state); - void setBreakBlocksMode(bool state); - void setBreakClosingHeaderBlocksMode(bool state); - void setBreakElseIfsMode(bool state); - void setBreakOneLineBlocksMode(bool state); - void setBreakOneLineHeadersMode(bool state); - void setBreakOneLineStatementsMode(bool state); - void setMethodPrefixPaddingMode(bool state); - void setMethodPrefixUnPaddingMode(bool state); - void setReturnTypePaddingMode(bool state); - void setReturnTypeUnPaddingMode(bool state); - void setParamTypePaddingMode(bool state); - void setParamTypeUnPaddingMode(bool state); - void setCloseTemplatesMode(bool state); - void setCommaPaddingMode(bool state); - void setDeleteEmptyLinesMode(bool state); - void setDeleteMultipleEmptyLinesMode(bool state); - void setBreakReturnType(bool state); - void setBreakReturnTypeDecl(bool state); - void setAttachReturnType(bool state); - void setAttachReturnTypeDecl(bool state); - void setIndentCol1CommentsMode(bool state); - void setLineEndFormat(LineEndFormat fmt); - void setMaxCodeLength(int max); - void setObjCColonPaddingMode(ObjCColonPad mode); - void setOperatorPaddingMode(bool state); - void setParensOutsidePaddingMode(bool state); - void setParensFirstPaddingMode(bool state); - void setParensInsidePaddingMode(bool state); - void setParensHeaderPaddingMode(bool state); - void setParensUnPaddingMode(bool state); - void setPointerAlignment(PointerAlign alignment); - void setPreprocBlockIndent(bool state); - void setReferenceAlignment(ReferenceAlign alignment); - void setStripCommentPrefix(bool state); - void setTabSpaceConversionMode(bool state); - size_t getChecksumIn() const; - size_t getChecksumOut() const; - int getChecksumDiff() const; - int getFormatterFileType() const; - // retained for compatibility with release 2.06 - // "Brackets" have been changed to "Braces" in 3.0 - // they are referenced only by the old "bracket" options - void setAddBracketsMode(bool state); - void setAddOneLineBracketsMode(bool state); - void setRemoveBracketsMode(bool state); - void setBreakClosingHeaderBracketsMode(bool state); - - -private: // functions - template void deleteContainer(T& container); - template void initContainer(T& container, T value); - char peekNextChar() const; - BraceType getBraceType(); - bool adjustChecksumIn(int adjustment); - bool computeChecksumIn(const string& currentLine_); - bool computeChecksumOut(const string& beautifiedLine); - bool addBracesToStatement(); - bool removeBracesFromStatement(); - bool commentAndHeaderFollows(); - bool getNextChar(); - bool getNextLine(bool emptyLineWasDeleted = false); - bool isArrayOperator() const; - bool isBeforeComment() const; - bool isBeforeAnyComment() const; - bool isBeforeAnyLineEndComment(int startPos) const; - bool isBeforeMultipleLineEndComments(int startPos) const; - bool isBraceType(BraceType a, BraceType b) const; - bool isClassInitializer() const; - bool isClosingHeader(const string* header) const; - bool isCurrentBraceBroken() const; - bool isDereferenceOrAddressOf() const; - bool isExecSQL(const string& line, size_t index) const; - bool isEmptyLine(const string& line) const; - bool isExternC() const; - bool isMultiStatementLine() const; - bool isNextWordSharpNonParenHeader(int startChar) const; - bool isNonInStatementArrayBrace() const; - bool isNumericVariable(const string& word) const; - bool isOkToSplitFormattedLine(); - bool isPointerOrReference() const; - bool isPointerOrReferenceCentered() const; - bool isPointerOrReferenceVariable(const string& word) const; - bool isPointerToPointer(const string& line, int currPos) const; - bool isSharpStyleWithParen(const string* header) const; - bool isStructAccessModified(const string& firstLine, size_t index) const; - bool isIndentablePreprocessorBlock(const string& firstLine, size_t index); - bool isNDefPreprocStatement(const string& nextLine_, const string& preproc) const; - bool isUnaryOperator() const; - bool isUniformInitializerBrace() const; - bool isImmediatelyPostCast() const; - bool isInExponent() const; - bool isInSwitchStatement() const; - bool isNextCharOpeningBrace(int startChar) const; - bool isOkToBreakBlock(BraceType braceType) const; - bool isOperatorPaddingDisabled() const; - bool pointerSymbolFollows() const; - int findObjCColonAlignment() const; - int getCurrentLineCommentAdjustment(); - int getNextLineCommentAdjustment(); - int isOneLineBlockReached(const string& line, int startChar) const; - void adjustComments(); - void appendChar(char ch, bool canBreakLine); - void appendCharInsideComments(); - void appendClosingHeader(); - void appendOperator(const string& sequence, bool canBreakLine = true); - void appendSequence(const string& sequence, bool canBreakLine = true); - void appendSpacePad(); - void appendSpaceAfter(); - void breakLine(bool isSplitLine = false); - void buildLanguageVectors(); - void updateFormattedLineSplitPoints(char appendedChar); - void updateFormattedLineSplitPointsOperator(const string& sequence); - void checkIfTemplateOpener(); - void clearFormattedLineSplitPoints(); - void convertTabToSpaces(); - void deleteContainer(vector*& container); - void findReturnTypeSplitPoint(const string& firstLine); - void formatArrayRunIn(); - void formatRunIn(); - void formatArrayBraces(BraceType braceType, bool isOpeningArrayBrace); - void formatClosingBrace(BraceType braceType); - void formatCommentBody(); - void formatCommentOpener(); - void formatCommentCloser(); - void formatLineCommentBody(); - void formatLineCommentOpener(); - void formatOpeningBrace(BraceType braceType); - void formatQuoteBody(); - void formatQuoteOpener(); - void formatPointerOrReference(); - void formatPointerOrReferenceCast(); - void formatPointerOrReferenceToMiddle(); - void formatPointerOrReferenceToName(); - void formatPointerOrReferenceToType(); - void fixOptionVariableConflicts(); - void goForward(int i); - void isLineBreakBeforeClosingHeader(); - void initContainer(vector*& container, vector* value); - void initNewLine(); - void padObjCMethodColon(); - void padObjCMethodPrefix(); - void padObjCParamType(); - void padObjCReturnType(); - void padOperators(const string* newOperator); - void padParens(); - void processPreprocessor(); - void resetEndOfStatement(); - void setAttachClosingBraceMode(bool state); - void stripCommentPrefix(); - void testForTimeToSplitFormattedLine(); - void trimContinuationLine(); - void updateFormattedLineSplitPointsPointerOrReference(size_t index); - size_t findFormattedLineSplitPoint() const; - size_t findNextChar(const string& line, char searchChar, int searchStart = 0) const; - const string* checkForHeaderFollowingComment(const string& firstLine) const; - const string* getFollowingOperator() const; - string getPreviousWord(const string& line, int currPos) const; - string peekNextText(const string& firstLine, - bool endOnEmptyLine = false, - const shared_ptr& streamArg = nullptr) const; - -private: // variables - int formatterFileType; - vector* headers; - vector* nonParenHeaders; - vector* preDefinitionHeaders; - vector* preCommandHeaders; - vector* operators; - vector* assignmentOperators; - vector* castOperators; - vector* >* indentableMacros; // for ASEnhancer - - ASSourceIterator* sourceIterator; - ASEnhancer* enhancer; - - vector* preBraceHeaderStack; - vector* braceTypeStack; - vector* parenStack; - vector* structStack; - vector* questionMarkStack; - - string currentLine; - string formattedLine; - string readyFormattedLine; - string verbatimDelimiter; - const string* currentHeader; - char currentChar; - char previousChar; - char previousNonWSChar; - char previousCommandChar; - char quoteChar; - streamoff preprocBlockEnd; - int charNum; - int runInIndentChars; - int nextLineSpacePadNum; - int objCColonAlign; - int preprocBraceTypeStackSize; - int spacePadNum; - int tabIncrementIn; - int templateDepth; - int squareBracketCount; - size_t checksumIn; - size_t checksumOut; - size_t currentLineFirstBraceNum; // first brace location on currentLine - size_t formattedLineCommentNum; // comment location on formattedLine - size_t leadingSpaces; - size_t maxCodeLength; - size_t methodAttachCharNum; - size_t methodAttachLineNum; - size_t methodBreakCharNum; - size_t methodBreakLineNum; - - // possible split points - size_t maxSemi; // probably a 'for' statement - size_t maxAndOr; // probably an 'if' statement - size_t maxComma; - size_t maxParen; - size_t maxWhiteSpace; - size_t maxSemiPending; - size_t maxAndOrPending; - size_t maxCommaPending; - size_t maxParenPending; - size_t maxWhiteSpacePending; - - size_t previousReadyFormattedLineLength; - FormatStyle formattingStyle; - BraceMode braceFormatMode; - BraceType previousBraceType; - PointerAlign pointerAlignment; - ReferenceAlign referenceAlignment; - ObjCColonPad objCColonPadMode; - LineEndFormat lineEnd; - bool isVirgin; - bool isInVirginLine; - bool shouldPadCommas; - bool shouldPadOperators; - bool shouldPadParensOutside; - bool shouldPadFirstParen; - bool shouldPadParensInside; - bool shouldPadHeader; - bool shouldStripCommentPrefix; - bool shouldUnPadParens; - bool shouldConvertTabs; - bool shouldIndentCol1Comments; - bool shouldIndentPreprocBlock; - bool shouldCloseTemplates; - bool shouldAttachExternC; - bool shouldAttachNamespace; - bool shouldAttachClass; - bool shouldAttachClosingWhile; - bool shouldAttachInline; - bool isInLineComment; - bool isInComment; - bool isInCommentStartLine; - bool noTrimCommentContinuation; - bool isInPreprocessor; - bool isInPreprocessorDefineDef; - bool isInPreprocessorBeautify; - bool isInPreprocessorInclude; - bool isInTemplate; - bool doesLineStartComment; - bool lineEndsInCommentOnly; - bool lineIsCommentOnly; - bool lineIsLineCommentOnly; - bool lineIsEmpty; - bool prevLineIsEmpty; - bool isImmediatelyPostCommentOnly; - bool isImmediatelyPostEmptyLine; - bool isInClassInitializer; - bool isInQuote; - bool isInVerbatimQuote; - bool haveLineContinuationChar; - bool isInQuoteContinuation; - bool isHeaderInMultiStatementLine; - bool isSpecialChar; - bool isNonParenHeader; - bool foundQuestionMark; - bool foundPreDefinitionHeader; - bool foundNamespaceHeader; - bool foundClassHeader; - bool foundStructHeader; - bool foundInterfaceHeader; - bool foundPreCommandHeader; - bool foundPreCommandMacro; - bool foundTrailingReturnType; - bool foundCastOperator; - bool isInLineBreak; - bool endOfAsmReached; - bool endOfCodeReached; - bool lineCommentNoIndent; - bool isFormattingModeOff; - bool isInEnum; - bool isInExecSQL; - bool isInAsm; - bool isInAsmOneLine; - bool isInAsmBlock; - bool isLineReady; - bool elseHeaderFollowsComments; - bool caseHeaderFollowsComments; - bool isPreviousBraceBlockRelated; - bool isInPotentialCalculation; - bool isCharImmediatelyPostComment; - bool isPreviousCharPostComment; - bool isCharImmediatelyPostLineComment; - bool isCharImmediatelyPostOpenBlock; - bool isCharImmediatelyPostCloseBlock; - bool isCharImmediatelyPostTemplate; - bool isCharImmediatelyPostReturn; - bool isCharImmediatelyPostThrow; - bool isCharImmediatelyPostNewDelete; - bool isCharImmediatelyPostOperator; - bool isCharImmediatelyPostPointerOrReference; - bool isInObjCMethodDefinition; - bool isInObjCInterface; - bool isInObjCReturnType; - bool isInObjCParam; - bool isInObjCSelector; - bool breakCurrentOneLineBlock; - bool shouldRemoveNextClosingBrace; - bool isInBraceRunIn; - bool returnTypeChecked; - bool currentLineBeginsWithBrace; - bool attachClosingBraceMode; - bool shouldBreakOneLineBlocks; - bool shouldBreakOneLineHeaders; - bool shouldBreakOneLineStatements; - bool shouldBreakClosingHeaderBraces; - bool shouldBreakElseIfs; - bool shouldBreakLineAfterLogical; - bool shouldAddBraces; - bool shouldAddOneLineBraces; - bool shouldRemoveBraces; - bool shouldPadMethodColon; - bool shouldPadMethodPrefix; - bool shouldReparseCurrentChar; - bool shouldUnPadMethodPrefix; - bool shouldPadReturnType; - bool shouldUnPadReturnType; - bool shouldPadParamType; - bool shouldUnPadParamType; - bool shouldDeleteEmptyLines; - bool shouldDeleteMultipleEmptyLines; - bool shouldBreakReturnType; - bool shouldBreakReturnTypeDecl; - bool shouldAttachReturnType; - bool shouldAttachReturnTypeDecl; - bool needHeaderOpeningBrace; - bool shouldBreakLineAtNextChar; - bool shouldKeepLineUnbroken; - bool passedSemicolon; - bool passedColon; - bool isImmediatelyPostNonInStmt; - bool isCharImmediatelyPostNonInStmt; - bool isImmediatelyPostComment; - bool isImmediatelyPostLineComment; - bool isImmediatelyPostEmptyBlock; - bool isImmediatelyPostObjCMethodPrefix; - bool isImmediatelyPostPreprocessor; - bool isImmediatelyPostReturn; - bool isImmediatelyPostThrow; - bool isImmediatelyPostNewDelete; - bool isImmediatelyPostOperator; - bool isImmediatelyPostTemplate; - bool isImmediatelyPostPointerOrReference; - bool shouldBreakBlocks; - bool shouldBreakClosingHeaderBlocks; - bool isPrependPostBlockEmptyLineRequested; - bool isAppendPostBlockEmptyLineRequested; - bool isIndentableProprocessor; - bool isIndentableProprocessorBlock; - bool prependEmptyLine; - bool appendOpeningBrace; - bool foundClosingHeader; - bool isInHeader; - bool isImmediatelyPostHeader; - bool isInCase; - bool isFirstPreprocConditional; - bool processedFirstConditional; - bool isJavaStaticConstructor; - -private: // inline functions - // append the CURRENT character (curentChar) to the current formatted line. - void appendCurrentChar(bool canBreakLine = true) - { appendChar(currentChar, canBreakLine); } - - // check if a specific sequence exists in the current placement of the current line - bool isSequenceReached(const char* sequence) const - { return currentLine.compare(charNum, strlen(sequence), sequence) == 0; } - - // call ASBase::findHeader for the current character - const string* findHeader(const vector* headers_) - { return ASBase::findHeader(currentLine, charNum, headers_); } - - // call ASBase::findOperator for the current character - const string* findOperator(const vector* operators_) - { return ASBase::findOperator(currentLine, charNum, operators_); } -}; // Class ASFormatter - -//----------------------------------------------------------------------------- -// astyle namespace global declarations -//----------------------------------------------------------------------------- -// sort comparison functions for ASResource -bool sortOnLength(const string* a, const string* b); -bool sortOnName(const string* a, const string* b); - -} // namespace astyle - -// end of astyle namespace -------------------------------------------------- - -#endif // closes ASTYLE_H diff --git a/tools/astyle/astyle.pro b/tools/astyle/astyle.pro deleted file mode 100644 index 95619018..00000000 --- a/tools/astyle/astyle.pro +++ /dev/null @@ -1,53 +0,0 @@ -QT -= gui - -isEmpty(APP_NAME) { - APP_NAME = RedPandaCPP -} - -CONFIG += c++11 console -CONFIG -= app_bundle - -msvc { -CONFIG += windows -} - -# You can make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -SOURCES += \ - ASBeautifier.cpp \ - ASEnhancer.cpp \ - ASFormatter.cpp \ - ASLocalizer.cpp \ - ASResource.cpp \ - astyle_main.cpp - -isEmpty(PREFIX) { - PREFIX = /usr/local -} -isEmpty(LIBEXECDIR) { - LIBEXECDIR = $${PREFIX}/libexec -} - -win32: { - !isEmpty(PREFIX) { - target.path = $${PREFIX} - } -} - -win32-msvc { -QMAKE_CFLAGS += /source-charset:utf-8 -QMAKE_CXXFLAGS += /source-charset:utf-8 -} - -# Default rules for deployment. -qnx: target.path = $${LIBEXECDIR}/$${APP_NAME} -else: unix:!android: target.path = $${LIBEXECDIR}/$${APP_NAME} - -!isEmpty(target.path): INSTALLS += target - -HEADERS += \ - ASLocalizer.h \ - astyle.h \ - astyle_main.h diff --git a/tools/astyle/astyle_main.cpp b/tools/astyle/astyle_main.cpp deleted file mode 100644 index 05f35f54..00000000 --- a/tools/astyle/astyle_main.cpp +++ /dev/null @@ -1,4360 +0,0 @@ -// astyle_main.cpp -// Copyright (c) 2018 by Jim Pattee . -// This code is licensed under the MIT License. -// License.md describes the conditions under which this software may be distributed. - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * AStyle_main source file map. - * This source file contains several classes. - * They are arranged as follows. - * --------------------------------------- - * namespace astyle { - * ASStreamIterator methods - * ASConsole methods - * // Windows specific - * // Linux specific - * ASLibrary methods - * // Windows specific - * // Linux specific - * ASOptions methods - * ASEncoding methods - * } // end of astyle namespace - * Global Area --------------------------- - * Java Native Interface functions - * AStyleMainUtf16 entry point - * AStyleMain entry point - * AStyleGetVersion entry point - * main entry point - * --------------------------------------- - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - */ - -//----------------------------------------------------------------------------- -// headers -//----------------------------------------------------------------------------- - -#include "astyle_main.h" - -#include -#include -#include // needed by some compilers -#include -#include -#include - -// includes for recursive getFileNames() function -#ifdef _WIN32 - #undef UNICODE // use ASCII windows functions - #include -#else - #include - #include - #include - #include - #ifdef __VMS - #include - #include - #include - #include - #include - #include - #endif /* __VMS */ -#endif - -//----------------------------------------------------------------------------- -// declarations -//----------------------------------------------------------------------------- - -// turn off MinGW automatic file globbing -// this CANNOT be in the astyle namespace -#ifndef ASTYLE_LIB - int _CRT_glob = 0; -#endif - -//---------------------------------------------------------------------------- -// astyle namespace -//---------------------------------------------------------------------------- - -namespace astyle { -// -// console build variables -#ifndef ASTYLE_LIB - #ifdef _WIN32 - char g_fileSeparator = '\\'; // Windows file separator - bool g_isCaseSensitive = false; // Windows IS NOT case sensitive - #else - char g_fileSeparator = '/'; // Linux file separator - bool g_isCaseSensitive = true; // Linux IS case sensitive - #endif // _WIN32 -#endif // ASTYLE_LIB - -// java library build variables -#ifdef ASTYLE_JNI - JNIEnv* g_env; - jobject g_obj; - jmethodID g_mid; -#endif - -const char* g_version = "3.2 beta"; - -//----------------------------------------------------------------------------- -// ASStreamIterator class -// typename will be stringstream for AStyle -// it could be istream or wxChar for plug-ins -//----------------------------------------------------------------------------- - -template -ASStreamIterator::ASStreamIterator(T* in) -{ - inStream = in; - buffer.reserve(200); - eolWindows = 0; - eolLinux = 0; - eolMacOld = 0; - peekStart = 0; - prevLineDeleted = false; - checkForEmptyLine = false; - // get length of stream - inStream->seekg(0, inStream->end); - streamLength = inStream->tellg(); - inStream->seekg(0, inStream->beg); -} - -template -ASStreamIterator::~ASStreamIterator() = default; - -/** -* get the length of the input stream. -* streamLength variable is set by the constructor. -* -* @return length of the input file stream, converted to an int. -*/ -template -int ASStreamIterator::getStreamLength() const -{ - return static_cast(streamLength); -} - -/** - * read the input stream, delete any end of line characters, - * and build a string that contains the input line. - * - * @return string containing the next input line minus any end of line characters - */ -template -string ASStreamIterator::nextLine(bool emptyLineWasDeleted) -{ - // verify that the current position is correct - assert(peekStart == 0); - - // a deleted line may be replaced if break-blocks is requested - // this sets up the compare to check for a replaced empty line - if (prevLineDeleted) - { - prevLineDeleted = false; - checkForEmptyLine = true; - } - if (!emptyLineWasDeleted) - prevBuffer = buffer; - else - prevLineDeleted = true; - - // read the next record - buffer.clear(); - char ch; - inStream->get(ch); - - while (!inStream->eof() && ch != '\n' && ch != '\r') - { - buffer.append(1, ch); - inStream->get(ch); - } - - if (inStream->eof()) - { - return buffer; - } - - int peekCh = inStream->peek(); - - // find input end-of-line characters - if (!inStream->eof()) - { - if (ch == '\r') // CR+LF is windows otherwise Mac OS 9 - { - if (peekCh == '\n') - { - inStream->get(); - eolWindows++; - } - else - eolMacOld++; - } - else // LF is Linux, allow for improbable LF/CR - { - if (peekCh == '\r') - { - inStream->get(); - eolWindows++; - } - else - eolLinux++; - } - } - else - { - inStream->clear(); - } - - // has not detected an input end of line - if (!eolWindows && !eolLinux && !eolMacOld) - { -#ifdef _WIN32 - eolWindows++; -#else - eolLinux++; -#endif - } - - // set output end of line characters - if (eolWindows >= eolLinux) - { - if (eolWindows >= eolMacOld) - outputEOL = "\r\n"; // Windows (CR+LF) - else - outputEOL = "\r"; // MacOld (CR) - } - else if (eolLinux >= eolMacOld) - outputEOL = "\n"; // Linux (LF) - else - outputEOL = "\r"; // MacOld (CR) - - return buffer; -} - -// save the current position and get the next line -// this can be called for multiple reads -// when finished peeking you MUST call peekReset() -// call this function from ASFormatter ONLY -template -string ASStreamIterator::peekNextLine() -{ - assert(hasMoreLines()); - string nextLine_; - char ch; - - if (!peekStart) - peekStart = inStream->tellg(); - - // read the next record - inStream->get(ch); - while (!inStream->eof() && ch != '\n' && ch != '\r') - { - nextLine_.append(1, ch); - inStream->get(ch); - } - - if (inStream->eof()) - { - return nextLine_; - } - - int peekCh = inStream->peek(); - - // remove end-of-line characters - if (!inStream->eof()) - { - if ((peekCh == '\n' || peekCh == '\r') && peekCh != ch) - inStream->get(); - } - - return nextLine_; -} - -// reset current position and EOF for peekNextLine() -template -void ASStreamIterator::peekReset() -{ - assert(peekStart != 0); - inStream->clear(); - inStream->seekg(peekStart); - peekStart = 0; -} - -// save the last input line after input has reached EOF -template -void ASStreamIterator::saveLastInputLine() -{ - assert(inStream->eof()); - prevBuffer = buffer; -} - -// return position of the get pointer -template -streamoff ASStreamIterator::tellg() -{ - return inStream->tellg(); -} - -// check for a change in line ends -template -bool ASStreamIterator::getLineEndChange(int lineEndFormat) const -{ - assert(lineEndFormat == LINEEND_DEFAULT - || lineEndFormat == LINEEND_WINDOWS - || lineEndFormat == LINEEND_LINUX - || lineEndFormat == LINEEND_MACOLD); - - bool lineEndChange = false; - if (lineEndFormat == LINEEND_WINDOWS) - lineEndChange = (eolLinux + eolMacOld != 0); - else if (lineEndFormat == LINEEND_LINUX) - lineEndChange = (eolWindows + eolMacOld != 0); - else if (lineEndFormat == LINEEND_MACOLD) - lineEndChange = (eolWindows + eolLinux != 0); - else - { - if (eolWindows > 0) - lineEndChange = (eolLinux + eolMacOld != 0); - else if (eolLinux > 0) - lineEndChange = (eolWindows + eolMacOld != 0); - else if (eolMacOld > 0) - lineEndChange = (eolWindows + eolLinux != 0); - } - return lineEndChange; -} - -//----------------------------------------------------------------------------- -// ASConsole class -// main function will be included only in the console build -//----------------------------------------------------------------------------- - -#ifndef ASTYLE_LIB - -ASConsole::ASConsole(ASFormatter& formatterArg) : formatter(formatterArg) -{ - errorStream = &cerr; - // command line options - isRecursive = false; - isDryRun = false; - noBackup = false; - preserveDate = false; - isVerbose = false; - isQuiet = false; - isFormattedOnly = false; - ignoreExcludeErrors = false; - ignoreExcludeErrorsDisplay = false; - useAscii = false; - // other variables - bypassBrowserOpen = false; - hasWildcard = false; - filesAreIdentical = true; - lineEndsMixed = false; - origSuffix = ".orig"; - mainDirectoryLength = 0; - filesFormatted = 0; - filesUnchanged = 0; - linesOut = 0; -} - -// rewrite a stringstream converting the line ends -void ASConsole::convertLineEnds(ostringstream& out, int lineEnd) -{ - assert(lineEnd == LINEEND_WINDOWS || lineEnd == LINEEND_LINUX || lineEnd == LINEEND_MACOLD); - const string& inStr = out.str(); // avoids strange looking syntax - string outStr; // the converted output - int inLength = (int) inStr.length(); - for (int pos = 0; pos < inLength; pos++) - { - if (inStr[pos] == '\r') - { - if (inStr[pos + 1] == '\n') - { - // CRLF - if (lineEnd == LINEEND_CR) - { - outStr += inStr[pos]; // Delete the LF - pos++; - continue; - } - if (lineEnd == LINEEND_LF) - { - outStr += inStr[pos + 1]; // Delete the CR - pos++; - continue; - } - outStr += inStr[pos]; // Do not change - outStr += inStr[pos + 1]; - pos++; - continue; - } - else // NOLINT - { - // CR - if (lineEnd == LINEEND_CRLF) - { - outStr += inStr[pos]; // Insert the CR - outStr += '\n'; // Insert the LF - continue; - } - if (lineEnd == LINEEND_LF) - { - outStr += '\n'; // Insert the LF - continue; - } - outStr += inStr[pos]; // Do not change - continue; - } - } - else if (inStr[pos] == '\n') - { - // LF - if (lineEnd == LINEEND_CRLF) - { - outStr += '\r'; // Insert the CR - outStr += inStr[pos]; // Insert the LF - continue; - } - if (lineEnd == LINEEND_CR) - { - outStr += '\r'; // Insert the CR - continue; - } - outStr += inStr[pos]; // Do not change - continue; - } - else - { - outStr += inStr[pos]; // Write the current char - } - } - // replace the stream - out.str(outStr); -} - -void ASConsole::correctMixedLineEnds(ostringstream& out) -{ - LineEndFormat lineEndFormat = LINEEND_DEFAULT; - if (outputEOL == "\r\n") - lineEndFormat = LINEEND_WINDOWS; - if (outputEOL == "\n") - lineEndFormat = LINEEND_LINUX; - if (outputEOL == "\r") - lineEndFormat = LINEEND_MACOLD; - convertLineEnds(out, lineEndFormat); -} - -// check files for 16 or 32 bit encoding -// the file must have a Byte Order Mark (BOM) -// NOTE: some string functions don't work with NULLs (e.g. length()) -FileEncoding ASConsole::detectEncoding(const char* data, size_t dataSize) const -{ - FileEncoding encoding = ENCODING_8BIT; - - if (dataSize >= 3 && memcmp(data, "\xEF\xBB\xBF", 3) == 0) - encoding = UTF_8BOM; - else if (dataSize >= 4 && memcmp(data, "\x00\x00\xFE\xFF", 4) == 0) - encoding = UTF_32BE; - else if (dataSize >= 4 && memcmp(data, "\xFF\xFE\x00\x00", 4) == 0) - encoding = UTF_32LE; - else if (dataSize >= 2 && memcmp(data, "\xFE\xFF", 2) == 0) - encoding = UTF_16BE; - else if (dataSize >= 2 && memcmp(data, "\xFF\xFE", 2) == 0) - encoding = UTF_16LE; - - return encoding; -} - -// error exit without a message -void ASConsole::error() const -{ - (*errorStream) << _("Artistic Style has terminated\n") << endl; - exit(EXIT_FAILURE); -} - -// error exit with a message -void ASConsole::error(const char* why, const char* what) const -{ - (*errorStream) << why << ' ' << what << endl; - error(); -} - -/** - * If no files have been given, use cin for input and cout for output. - * - * This is used to format text for text editors. - * Do NOT display any console messages when this function is used. - */ -void ASConsole::formatCinToCout() -{ - // check for files from --stdin= and --stdout= - if (!stdPathIn.empty()) - { - if (!freopen(stdPathIn.c_str(), "r", stdin)) - error("Cannot open input file", stdPathIn.c_str()); - } - if (!stdPathOut.empty()) - { - if (!freopen(stdPathOut.c_str(), "w", stdout)) - error("Cannot open output file", stdPathOut.c_str()); - - } - // Using cin.tellg() causes problems with both Windows and Linux. - // The Windows problem occurs when the input is not Windows line-ends. - // The tellg() will be out of sequence with the get() statements. - // The Linux cin.tellg() will return -1 (invalid). - // Copying the input sequentially to a stringstream before - // formatting solves the problem for both. - istream* inStream = &cin; - stringstream outStream; - char ch; - inStream->get(ch); - while (!inStream->eof() && !inStream->fail()) - { - outStream.put(ch); - inStream->get(ch); - } - ASStreamIterator streamIterator(&outStream); - // Windows pipe or redirection always outputs Windows line-ends. - // Linux pipe or redirection will output any line end. -#ifdef _WIN32 - LineEndFormat lineEndFormat = LINEEND_DEFAULT; -#else - LineEndFormat lineEndFormat = formatter.getLineEndFormat(); -#endif // _WIN32 - initializeOutputEOL(lineEndFormat); - formatter.init(&streamIterator); - - while (formatter.hasMoreLines()) - { - cout << formatter.nextLine(); - if (formatter.hasMoreLines()) - { - setOutputEOL(lineEndFormat, streamIterator.getOutputEOL()); - cout << outputEOL; - } - else - { - // this can happen if the file if missing a closing brace and break-blocks is requested - if (formatter.getIsLineReady()) - { - setOutputEOL(lineEndFormat, streamIterator.getOutputEOL()); - cout << outputEOL; - cout << formatter.nextLine(); - } - } - } - cout.flush(); -} - -/** - * Open input file, format it, and close the output. - * - * @param fileName_ The path and name of the file to be processed. - */ -void ASConsole::formatFile(const string& fileName_) -{ - stringstream in; - ostringstream out; - FileEncoding encoding = readFile(fileName_, in); - - // Unless a specific language mode has been set, set the language mode - // according to the file's suffix. - if (!formatter.getModeManuallySet()) - { - if (stringEndsWith(fileName_, string(".java"))) - formatter.setJavaStyle(); - else if (stringEndsWith(fileName_, string(".cs"))) - formatter.setSharpStyle(); - else - formatter.setCStyle(); - } - - // set line end format - string nextLine; // next output line - filesAreIdentical = true; // input and output files are identical - LineEndFormat lineEndFormat = formatter.getLineEndFormat(); - initializeOutputEOL(lineEndFormat); - // do this AFTER setting the file mode - ASStreamIterator streamIterator(&in); - formatter.init(&streamIterator); - - // format the file - while (formatter.hasMoreLines()) - { - nextLine = formatter.nextLine(); - out << nextLine; - linesOut++; - if (formatter.hasMoreLines()) - { - setOutputEOL(lineEndFormat, streamIterator.getOutputEOL()); - out << outputEOL; - } - else - { - streamIterator.saveLastInputLine(); // to compare the last input line - // this can happen if the file if missing a closing brace and break-blocks is requested - if (formatter.getIsLineReady()) - { - setOutputEOL(lineEndFormat, streamIterator.getOutputEOL()); - out << outputEOL; - nextLine = formatter.nextLine(); - out << nextLine; - linesOut++; - streamIterator.saveLastInputLine(); - } - } - - if (filesAreIdentical) - { - if (streamIterator.checkForEmptyLine) - { - if (nextLine.find_first_not_of(" \t") != string::npos) - filesAreIdentical = false; - } - else if (!streamIterator.compareToInputBuffer(nextLine)) - filesAreIdentical = false; - streamIterator.checkForEmptyLine = false; - } - } - // correct for mixed line ends - if (lineEndsMixed) - { - correctMixedLineEnds(out); - filesAreIdentical = false; - } - - // remove targetDirectory from filename if required by print - string displayName; - if (hasWildcard) - displayName = fileName_.substr(targetDirectory.length() + 1); - else - displayName = fileName_; - - // if file has changed, write the new file - if (!filesAreIdentical || streamIterator.getLineEndChange(lineEndFormat)) - { - if (!isDryRun) - writeFile(fileName_, encoding, out); - printMsg(_("Formatted %s\n"), displayName); - filesFormatted++; - } - else - { - if (!isFormattedOnly) - printMsg(_("Unchanged %s\n"), displayName); - filesUnchanged++; - } - - assert(formatter.getChecksumDiff() == 0); -} - -/** - * Searches for a file named fileName_ in the current directory. If it is not - * found, recursively searches for fileName_ in the current directory's parent - * directories, returning the location of the first instance of fileName_ - * found. If fileName_ is not found, an empty string is returned. - * - * @param fileName_ The filename the function should attempt to locate. - * @return The full path to fileName_ in the current directory or - * nearest parent directory if found, otherwise an empty - * string. - */ -string ASConsole::findProjectOptionFilePath(const string& fileName_) const -{ - string parent; - - if (!fileNameVector.empty()) - parent = getFullPathName(fileNameVector.front()); - else if (!stdPathIn.empty()) - parent = getFullPathName(stdPathIn); - else - parent = getFullPathName(getCurrentDirectory(fileName_)); - - // remove filename from path - size_t endPath = parent.find_last_of(g_fileSeparator); - if (endPath != string::npos) - parent = parent.substr(0, endPath + 1); - - while (!parent.empty()) - { - string filepath = parent + fileName_; - if (fileExists(filepath.c_str())) - return filepath; - if (fileName_ == ".astylerc") - { - filepath = parent + "_astylerc"; - if (fileExists(filepath.c_str())) - return filepath; - } - parent = getParentDirectory(parent); - } - return string(); -} - -// for unit testing -vector ASConsole::getExcludeHitsVector() const -{ return excludeHitsVector; } - -// for unit testing -vector ASConsole::getExcludeVector() const -{ return excludeVector; } - -// for unit testing -vector ASConsole::getFileName() const -{ return fileName; } - -// for unit testing -vector ASConsole::getFileNameVector() const -{ return fileNameVector; } - -// for unit testing -vector ASConsole::getFileOptionsVector() const -{ return fileOptionsVector; } - -// for unit testing -bool ASConsole::getFilesAreIdentical() const -{ return filesAreIdentical; } - -// for unit testing -int ASConsole::getFilesFormatted() const -{ return filesFormatted; } - -// for unit testing -bool ASConsole::getIgnoreExcludeErrors() const -{ return ignoreExcludeErrors; } - -// for unit testing -bool ASConsole::getIgnoreExcludeErrorsDisplay() const -{ return ignoreExcludeErrorsDisplay; } - -// for unit testing -bool ASConsole::getIsDryRun() const -{ return isDryRun; } - -// for unit testing -bool ASConsole::getIsFormattedOnly() const -{ return isFormattedOnly; } - -// for unit testing -string ASConsole::getLanguageID() const -{ return localizer.getLanguageID(); } - -// for unit testing -bool ASConsole::getIsQuiet() const -{ return isQuiet; } - -// for unit testing -bool ASConsole::getIsRecursive() const -{ return isRecursive; } - -// for unit testing -bool ASConsole::getIsVerbose() const -{ return isVerbose; } - -// for unit testing -bool ASConsole::getLineEndsMixed() const -{ return lineEndsMixed; } - -// for unit testing -bool ASConsole::getNoBackup() const -{ return noBackup; } - -// for unit testing -string ASConsole::getOptionFileName() const -{ return optionFileName; } - -// for unit testing -vector ASConsole::getOptionsVector() const -{ return optionsVector; } - -// for unit testing -string ASConsole::getOrigSuffix() const -{ return origSuffix; } - -// for unit testing -bool ASConsole::getPreserveDate() const -{ return preserveDate; } - -// for unit testing -string ASConsole::getProjectOptionFileName() const -{ - assert(projectOptionFileName.length() > 0); - // remove the directory path - size_t start = projectOptionFileName.find_last_of(g_fileSeparator); - if (start == string::npos) - start = 0; - return projectOptionFileName.substr(start + 1); -} - -// for unit testing -vector ASConsole::getProjectOptionsVector() const -{ return projectOptionsVector; } - -// for unit testing -string ASConsole::getStdPathIn() const -{ return stdPathIn; } - -// for unit testing -string ASConsole::getStdPathOut() const -{ return stdPathOut; } - -// for unit testing -void ASConsole::setBypassBrowserOpen(bool state) -{ bypassBrowserOpen = state; } - -// for unit testing -ostream* ASConsole::getErrorStream() const -{ - return errorStream; -} - -void ASConsole::setErrorStream(ostream* errStreamPtr) -{ - errorStream = errStreamPtr; -} - -// build a vector of argv options -// the program path argv[0] is excluded -vector ASConsole::getArgvOptions(int argc, char** argv) -{ - if (argc > 0) - astyleExePath = getFullPathName(argv[0]); - vector argvOptions; - for (int i = 1; i < argc; i++) - { - argvOptions.emplace_back(string(argv[i])); - } - return argvOptions; -} - -string ASConsole::getParam(const string& arg, const char* op) -{ - return arg.substr(strlen(op)); -} - -void ASConsole::getTargetFilenames(string& targetFilename_, - vector& targetFilenameVector) const -{ - size_t beg = 0; - size_t sep = 0; - while (beg < targetFilename_.length()) - { - // find next target - sep = targetFilename_.find_first_of(",;", beg); - if (sep == string::npos) - sep = targetFilename_.length(); - string fileExtension = targetFilename_.substr(beg, sep - beg); - beg = sep + 1; - // remove whitespace - while (fileExtension.length() > 0 - && (fileExtension[0] == ' ' || fileExtension[0] == '\t')) - fileExtension = fileExtension.erase(0, 1); - while (fileExtension.length() > 0 - && (fileExtension[fileExtension.length() - 1] == ' ' - || fileExtension[fileExtension.length() - 1] == '\t')) - fileExtension = fileExtension.erase(fileExtension.length() - 1, 1); - if (fileExtension.length() > 0) - targetFilenameVector.emplace_back(fileExtension); - } - if (targetFilenameVector.empty()) - { - fprintf(stderr, _("Missing filename in %s\n"), targetFilename_.c_str()); - error(); - } -} - -// initialize output end of line -void ASConsole::initializeOutputEOL(LineEndFormat lineEndFormat) -{ - assert(lineEndFormat == LINEEND_DEFAULT - || lineEndFormat == LINEEND_WINDOWS - || lineEndFormat == LINEEND_LINUX - || lineEndFormat == LINEEND_MACOLD); - - outputEOL.clear(); // current line end - prevEOL.clear(); // previous line end - lineEndsMixed = false; // output has mixed line ends, LINEEND_DEFAULT only - - if (lineEndFormat == LINEEND_WINDOWS) - outputEOL = "\r\n"; - else if (lineEndFormat == LINEEND_LINUX) - outputEOL = "\n"; - else if (lineEndFormat == LINEEND_MACOLD) - outputEOL = "\r"; - else - outputEOL.clear(); -} - -// read a file into the stringstream 'in' -FileEncoding ASConsole::readFile(const string& fileName_, stringstream& in) const -{ - const int blockSize = 65536; // 64 KB - ifstream fin(fileName_.c_str(), ios::binary); - if (!fin) - error("Cannot open file", fileName_.c_str()); - char* data = new (nothrow) char[blockSize]; - if (data == nullptr) - error("Cannot allocate memory to open file", fileName_.c_str()); - fin.read(data, blockSize); - if (fin.bad()) - error("Cannot read file", fileName_.c_str()); - size_t dataSize = static_cast(fin.gcount()); - FileEncoding encoding = detectEncoding(data, dataSize); - if (encoding == UTF_32BE || encoding == UTF_32LE) - error(_("Cannot process UTF-32 encoding"), fileName_.c_str()); - bool firstBlock = true; - bool isBigEndian = (encoding == UTF_16BE); - while (dataSize != 0) - { - if (encoding == UTF_16LE || encoding == UTF_16BE) - { - // convert utf-16 to utf-8 - size_t utf8Size = encode.utf8LengthFromUtf16(data, dataSize, isBigEndian); - char* utf8Out = new (nothrow) char[utf8Size]; - if (utf8Out == nullptr) - error("Cannot allocate memory for utf-8 conversion", fileName_.c_str()); - size_t utf8Len = encode.utf16ToUtf8(data, dataSize, isBigEndian, firstBlock, utf8Out); - assert(utf8Len <= utf8Size); - in << string(utf8Out, utf8Len); - delete[] utf8Out; - } - else - in << string(data, dataSize); - fin.read(data, blockSize); - if (fin.bad()) - error("Cannot read file", fileName_.c_str()); - dataSize = static_cast(fin.gcount()); - firstBlock = false; - } - fin.close(); - delete[] data; - return encoding; -} - -void ASConsole::setIgnoreExcludeErrors(bool state) -{ ignoreExcludeErrors = state; } - -void ASConsole::setIgnoreExcludeErrorsAndDisplay(bool state) -{ ignoreExcludeErrors = state; ignoreExcludeErrorsDisplay = state; } - -void ASConsole::setIsFormattedOnly(bool state) -{ isFormattedOnly = state; } - -void ASConsole::setIsQuiet(bool state) -{ isQuiet = state; } - -void ASConsole::setIsRecursive(bool state) -{ isRecursive = state; } - -void ASConsole::setIsDryRun(bool state) -{ isDryRun = state; } - -void ASConsole::setIsVerbose(bool state) -{ isVerbose = state; } - -void ASConsole::setNoBackup(bool state) -{ noBackup = state; } - -void ASConsole::setOptionFileName(const string& name) -{ optionFileName = name; } - -void ASConsole::setOrigSuffix(const string& suffix) -{ origSuffix = suffix; } - -void ASConsole::setPreserveDate(bool state) -{ preserveDate = state; } - -void ASConsole::setProjectOptionFileName(const string& optfilepath) -{ projectOptionFileName = optfilepath; } - -void ASConsole::setStdPathIn(const string& path) -{ stdPathIn = path; } - -void ASConsole::setStdPathOut(const string& path) -{ stdPathOut = path; } - -// set outputEOL variable -void ASConsole::setOutputEOL(LineEndFormat lineEndFormat, const string& currentEOL) -{ - if (lineEndFormat == LINEEND_DEFAULT) - { - outputEOL = currentEOL; - if (prevEOL.empty()) - prevEOL = outputEOL; - if (prevEOL != outputEOL) - { - lineEndsMixed = true; - filesAreIdentical = false; - prevEOL = outputEOL; - } - } - else - { - prevEOL = currentEOL; - if (prevEOL != outputEOL) - filesAreIdentical = false; - } -} - -#ifdef _WIN32 // Windows specific - -/** - * WINDOWS function to display the last system error. - */ -void ASConsole::displayLastError() -{ - LPSTR msgBuf; - DWORD lastError = GetLastError(); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - nullptr, - lastError, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPSTR) &msgBuf, - 0, - nullptr - ); - // Display the string. - (*errorStream) << "Error (" << lastError << ") " << msgBuf << endl; - // Free the buffer. - LocalFree(msgBuf); -} - -/** - * WINDOWS function to get the current directory. - * NOTE: getenv("CD") does not work for Windows Vista. - * The Windows function GetCurrentDirectory is used instead. - * - * @return The path of the current directory - */ -string ASConsole::getCurrentDirectory(const string& fileName_) const -{ - char currdir[MAX_PATH]; - currdir[0] = '\0'; - if (!GetCurrentDirectory(sizeof(currdir), currdir)) - error("Cannot find file", fileName_.c_str()); - return string(currdir); -} - -/** - * WINDOWS function to resolve wildcards and recurse into sub directories. - * The fileName vector is filled with the path and names of files to process. - * - * @param directory The path of the directory to be processed. - * @param wildcards A vector of wildcards to be processed (e.g. *.cpp). - */ -void ASConsole::getFileNames(const string& directory, const vector& wildcards) -{ - vector subDirectory; // sub directories of directory - WIN32_FIND_DATA findFileData; // for FindFirstFile and FindNextFile - - // Find the first file in the directory - // Find will get at least "." and "..". - string firstFile = directory + "\\*"; - HANDLE hFind = FindFirstFile(firstFile.c_str(), &findFileData); - - if (hFind == INVALID_HANDLE_VALUE) - { - // Error (3) The system cannot find the path specified. - // Error (123) The filename, directory name, or volume label syntax is incorrect. - // ::FindClose(hFind); before exiting - displayLastError(); - error(_("Cannot open directory"), directory.c_str()); - } - - // save files and sub directories - do - { - // skip hidden or read only - if (findFileData.cFileName[0] == '.' - || (findFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) - || (findFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) - continue; - - // is this a sub directory - if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (!isRecursive) - continue; - // if a sub directory and recursive, save sub directory - string subDirectoryPath = directory + g_fileSeparator + findFileData.cFileName; - if (isPathExclued(subDirectoryPath)) - printMsg(_("Exclude %s\n"), subDirectoryPath.substr(mainDirectoryLength)); - else - subDirectory.emplace_back(subDirectoryPath); - continue; - } - - string filePathName = directory + g_fileSeparator + findFileData.cFileName; - // check exclude before wildcmp to avoid "unmatched exclude" error - bool isExcluded = isPathExclued(filePathName); - // save file name if wildcard match - for (const string& wildcard : wildcards) - { - if (wildcmp(wildcard.c_str(), findFileData.cFileName)) - { - if (isExcluded) - printMsg(_("Exclude %s\n"), filePathName.substr(mainDirectoryLength)); - else - fileName.emplace_back(filePathName); - break; - } - } - } - while (FindNextFile(hFind, &findFileData) != 0); - - // check for processing error - ::FindClose(hFind); - DWORD dwError = GetLastError(); - if (dwError != ERROR_NO_MORE_FILES) - error("Error processing directory", directory.c_str()); - - // recurse into sub directories - // if not doing recursive subDirectory is empty - for (const string& subDirectoryName : subDirectory) - getFileNames(subDirectoryName, wildcards); -} - -// WINDOWS function to get the full path name from the relative path name -// Return the full path name or an empty string if failed. -string ASConsole::getFullPathName(const string& relativePath) const -{ - char fullPath[MAX_PATH]; - GetFullPathName(relativePath.c_str(), MAX_PATH, fullPath, nullptr); - return fullPath; -} - -/** - * WINDOWS function to format a number according to the current locale. - * This formats positive integers only, no float. - * - * @param num The number to be formatted. - * @param lcid The LCID of the locale to be used for testing. - * @return The formatted number. - */ -string ASConsole::getNumberFormat(int num, size_t lcid) const -{ -#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__) || defined(__GNUC__) - // Compilers that don't support C++ locales should still support this assert. - // The C locale should be set but not the C++. - // This function is not necessary if the C++ locale is set. - // The locale().name() return value is not portable to all compilers. - assert(locale().name() == "C"); -#endif - // convert num to a string - stringstream alphaNum; - alphaNum << num; - string number = alphaNum.str(); - if (useAscii) - return number; - - // format the number using the Windows API - if (lcid == 0) - lcid = LOCALE_USER_DEFAULT; - int outSize = ::GetNumberFormat(lcid, 0, number.c_str(), nullptr, nullptr, 0); - char* outBuf = new (nothrow) char[outSize]; - if (outBuf == nullptr) - return number; - ::GetNumberFormat(lcid, 0, number.c_str(), nullptr, outBuf, outSize); - string formattedNum(outBuf); - delete[] outBuf; - // remove the decimal - int decSize = ::GetLocaleInfo(lcid, LOCALE_SDECIMAL, nullptr, 0); - char* decBuf = new (nothrow) char[decSize]; - if (decBuf == nullptr) - return number; - ::GetLocaleInfo(lcid, LOCALE_SDECIMAL, decBuf, decSize); - size_t i = formattedNum.rfind(decBuf); - delete[] decBuf; - if (i != string::npos) - formattedNum.erase(i); - if (!formattedNum.length()) - formattedNum = "0"; - return formattedNum; -} - -/** - * WINDOWS function to check for a HOME directory - * - * @param absPath The path to be evaluated. - * @returns true if absPath is HOME or is an invalid absolute - * path, false otherwise. - */ -bool ASConsole::isHomeOrInvalidAbsPath(const string& absPath) const -{ - const char* const env = getenv("USERPROFILE"); - if (env == nullptr) - return true; - - if (absPath.c_str() == env) - return true; - - if (absPath.compare(0, strlen(env), env) != 0) - return true; - - return false; -} - -/** - * WINDOWS function to open a HTML file in the default browser. - */ -void ASConsole::launchDefaultBrowser(const char* filePathIn /*nullptr*/) const -{ - struct stat statbuf; - const char* envPaths[] = { "PROGRAMFILES(X86)", "PROGRAMFILES" }; - size_t pathsLen = sizeof(envPaths) / sizeof(envPaths[0]); - string htmlDefaultPath; - for (size_t i = 0; i < pathsLen; i++) - { - const char* const envPath = getenv(envPaths[i]); - if (envPath == nullptr) - continue; - htmlDefaultPath = envPath; - if (htmlDefaultPath.length() > 0 - && htmlDefaultPath[htmlDefaultPath.length() - 1] == g_fileSeparator) - htmlDefaultPath.erase(htmlDefaultPath.length() - 1); - htmlDefaultPath.append("\\AStyle\\doc"); - if (stat(htmlDefaultPath.c_str(), &statbuf) == 0 && statbuf.st_mode & S_IFDIR) - break; - } - htmlDefaultPath.append("\\"); - - // build file path - string htmlFilePath; - if (filePathIn == nullptr) - htmlFilePath = htmlDefaultPath + "astyle.html"; - else - { - if (strpbrk(filePathIn, "\\/") == nullptr) - htmlFilePath = htmlDefaultPath + filePathIn; - else - htmlFilePath = filePathIn; - } - standardizePath(htmlFilePath); - if (stat(htmlFilePath.c_str(), &statbuf) != 0 || !(statbuf.st_mode & S_IFREG)) - { - printf(_("Cannot open HTML file %s\n"), htmlFilePath.c_str()); - return; - } - - SHELLEXECUTEINFO sei = { sizeof(sei), {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} }; - sei.fMask = SEE_MASK_FLAG_NO_UI; - sei.lpVerb = "open"; - sei.lpFile = htmlFilePath.c_str(); - sei.nShow = SW_SHOWNORMAL; - - // browser open will be bypassed in test programs - printf(_("Opening HTML documentation %s\n"), htmlFilePath.c_str()); - if (!bypassBrowserOpen) - { - int ret = ShellExecuteEx(&sei); - if (!ret) - error(_("Command execute failure"), htmlFilePath.c_str()); - } -} - -#else // Linux specific - -/** - * LINUX function to get the current directory. - * This is done if the fileName does not contain a path. - * It is probably from an editor sending a single file. - * - * @param fileName_ The filename is used only for the error message. - * @return The path of the current directory - */ -string ASConsole::getCurrentDirectory(const string& fileName_) const -{ - const char* const currdir = getenv("PWD"); - if (currdir == nullptr) - error("Cannot find file", fileName_.c_str()); - return string(currdir); -} - -/** - * LINUX function to resolve wildcards and recurse into sub directories. - * The fileName vector is filled with the path and names of files to process. - * - * @param directory The path of the directory to be processed. - * @param wildcards A vector of wildcards to be processed (e.g. *.cpp). - */ -void ASConsole::getFileNames(const string& directory, const vector& wildcards) -{ - struct dirent* entry; // entry from readdir() - struct stat statbuf; // entry from stat() - vector subDirectory; // sub directories of this directory - - // errno is defined in and is set for errors in opendir, readdir, or stat - errno = 0; - - DIR* dp = opendir(directory.c_str()); - if (dp == nullptr) - error(_("Cannot open directory"), directory.c_str()); - - // save the first fileName entry for this recursion - const unsigned firstEntry = fileName.size(); - - // save files and sub directories - while ((entry = readdir(dp)) != nullptr) - { - // get file status - string entryFilepath = directory + g_fileSeparator + entry->d_name; - if (stat(entryFilepath.c_str(), &statbuf) != 0) - { - if (errno == EOVERFLOW) // file over 2 GB is OK - { - errno = 0; - continue; - } - perror("errno message"); - error("Error getting file status in directory", directory.c_str()); - } - // skip hidden or read only - if (entry->d_name[0] == '.' || !(statbuf.st_mode & S_IWUSR)) - continue; - // if a sub directory and recursive, save sub directory - if (S_ISDIR(statbuf.st_mode) && isRecursive) - { - if (isPathExclued(entryFilepath)) - printMsg(_("Exclude %s\n"), entryFilepath.substr(mainDirectoryLength)); - else - subDirectory.emplace_back(entryFilepath); - continue; - } - - // if a file, save file name - if (S_ISREG(statbuf.st_mode)) - { - // check exclude before wildcmp to avoid "unmatched exclude" error - bool isExcluded = isPathExclued(entryFilepath); - // save file name if wildcard match - for (const string& wildcard : wildcards) - { - if (wildcmp(wildcard.c_str(), entry->d_name) != 0) - { - if (isExcluded) - printMsg(_("Exclude %s\n"), entryFilepath.substr(mainDirectoryLength)); - else - fileName.emplace_back(entryFilepath); - break; - } - } - } - } - - if (closedir(dp) != 0) - { - perror("errno message"); - error("Error reading directory", directory.c_str()); - } - - // sort the current entries for fileName - if (firstEntry < fileName.size()) - sort(fileName.begin() + firstEntry, fileName.end()); - - // recurse into sub directories - // if not doing recursive, subDirectory is empty - if (subDirectory.size() > 1) - sort(subDirectory.begin(), subDirectory.end()); - for (unsigned i = 0; i < subDirectory.size(); i++) - { - getFileNames(subDirectory[i], wildcards); - } -} - -// LINUX function to get the full path name from the relative path name -// Return the full path name or an empty string if failed. -string ASConsole::getFullPathName(const string& relativePath) const -{ - // ignore realPath attribute warning, only with cmake -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-result" - char fullPath[PATH_MAX]; - fullPath[0] = '\0'; - realpath(relativePath.c_str(), fullPath); - return fullPath; -#pragma GCC diagnostic pop -} - -// LINUX function to get the documentation file path prefix -// from the executable file path. -// Return the documentation path prefix or an empty string if failed. -string ASConsole::getHtmlInstallPrefix() const -{ - string astyleHtmlPrefix = astyleExePath; - size_t end = astyleHtmlPrefix.find("/bin/"); - if (end == string::npos) - return ""; - astyleHtmlPrefix = astyleHtmlPrefix.substr(0, end); - return astyleHtmlPrefix; -} - -/** - * LINUX function to get locale information and call getNumberFormat. - * This formats positive integers only, no float. - * - * @param num The number to be formatted. - * size_t is for compatibility with the Windows function. - * @return The formatted number. - */ -string ASConsole::getNumberFormat(int num, size_t /*lcid*/) const -{ -#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__) || defined(__GNUC__) - // Compilers that don't support C++ locales should still support this assert. - // The C locale should be set but not the C++. - // This function is not necessary if the C++ locale is set. - // The locale().name() return value is not portable to all compilers. - assert(locale().name() == "C"); -#endif - - // get the locale info - struct lconv* lc; - lc = localeconv(); - - // format the number - return getNumberFormat(num, lc->grouping, lc->thousands_sep); -} - -/** - * LINUX function to format a number according to the current locale. - * This formats positive integers only, no float. - * - * @param num The number to be formatted. - * @param groupingArg The grouping string from the locale. - * @param separator The thousands group separator from the locale. - * @return The formatted number. - */ -string ASConsole::getNumberFormat(int num, const char* groupingArg, const char* separator) const -{ - // convert num to a string - stringstream alphaNum; - alphaNum << num; - string number = alphaNum.str(); - // format the number from right to left - string formattedNum; - size_t ig = 0; // grouping index - int grouping = groupingArg[ig]; - int i = number.length(); - // check for no grouping - if (grouping == 0) - grouping = number.length(); - while (i > 0) - { - // extract a group of numbers - string group; - if (i < grouping) - group = number; - else - group = number.substr(i - grouping); - // update formatted number - formattedNum.insert(0, group); - i -= grouping; - if (i < 0) - i = 0; - if (i > 0) - formattedNum.insert(0, separator); - number.erase(i); - // update grouping - if (groupingArg[ig] != '\0' - && groupingArg[ig + 1] != '\0') - grouping = groupingArg[++ig]; - } - return formattedNum; -} - -/** - * LINUX function to check for a HOME directory - * - * @param absPath The path to be evaluated. - * @returns true if absPath is HOME or is an invalid absolute - * path, false otherwise. - */ -bool ASConsole::isHomeOrInvalidAbsPath(const string& absPath) const -{ - const char* const env = getenv("HOME"); - if (env == nullptr) - return true; - - if (absPath.c_str() == env) - return true; - - if (absPath.compare(0, strlen(env), env) != 0) - return true; - - return false; -} - -/** - * LINUX function to open a HTML file in the default browser. - * Use xdg-open from freedesktop.org cross-desktop compatibility suite xdg-utils. - * see http://portland.freedesktop.org/wiki/ - * This is installed on most modern distributions. - */ -void ASConsole::launchDefaultBrowser(const char* filePathIn /*nullptr*/) const -{ -#ifdef __APPLE__ - string htmlDefaultPrefix = "/usr/local"; -#else - string htmlDefaultPrefix = "/usr"; -#endif - string htmlDefaultPath = htmlDefaultPrefix + "/share/doc/astyle/html/"; - string htmlDefaultFile = "astyle.html"; - string htmlFilePath; - struct stat statbuf; - - // build html path - if (filePathIn == nullptr) - { - string htmlPrefix = getHtmlInstallPrefix(); - if (htmlPrefix.empty()) - htmlFilePath = htmlDefaultPrefix + htmlDefaultPath + htmlDefaultFile; - else - htmlFilePath = htmlPrefix + htmlDefaultPath + htmlDefaultFile; - } - else - { - if (strpbrk(filePathIn, "\\/") == nullptr) - htmlFilePath = htmlDefaultPath + filePathIn; - else - htmlFilePath = filePathIn; - } - standardizePath(htmlFilePath); - if (stat(htmlFilePath.c_str(), &statbuf) != 0 || !(statbuf.st_mode & S_IFREG)) - { - printf(_("Cannot open HTML file %s\n"), htmlFilePath.c_str()); - return; - } - - // get search paths - const char* const envPaths = getenv("PATH"); - if (envPaths == nullptr) - error("Cannot read PATH environment variable", ""); - size_t envlen = strlen(envPaths); - char* paths = new char[envlen + 1]; - strcpy(paths, envPaths); - // find xdg-open (usually in /usr/bin) - // Mac uses open instead -#ifdef __APPLE__ - const char* fileOpen = "open"; -#else - const char* fileOpen = "xdg-open"; -#endif - string searchPath; - char* searchDir = strtok(paths, ":"); - while (searchDir != nullptr) - { - searchPath = searchDir; - if (searchPath.length() > 0 - && searchPath[searchPath.length() - 1] != g_fileSeparator) - searchPath.append(string(1, g_fileSeparator)); - searchPath.append(fileOpen); - if (stat(searchPath.c_str(), &statbuf) == 0 && (statbuf.st_mode & S_IFREG)) - break; - searchDir = strtok(nullptr, ":"); - } - delete[] paths; - if (searchDir == nullptr) - error(_("Command is not installed"), fileOpen); - - // browser open will be bypassed in test programs - printf(_("Opening HTML documentation %s\n"), htmlFilePath.c_str()); - if (!bypassBrowserOpen) - { - execlp(fileOpen, fileOpen, htmlFilePath.c_str(), nullptr); - // execlp will NOT return if successful - error(_("Command execute failure"), fileOpen); - } -} - -#endif // _WIN32 - -/** - * Returns the parent directory of absPath. If absPath is not a valid absolute - * path or if it does not have a parent, an empty string is returned. - * - * @param absPath The initial directory. - * @return The parent directory of absPath, or an empty string if - * one cannot be found. - */ -string ASConsole::getParentDirectory(const string& absPath) const -{ - if (isHomeOrInvalidAbsPath(absPath)) - { - return string(); - } - size_t offset = absPath.size() - 1; - if (absPath[absPath.size() - 1] == g_fileSeparator) - { - offset -= 1; - } - size_t idx = absPath.rfind(g_fileSeparator, offset); - if (idx == string::npos) - { - return string(); - } - string str = absPath.substr(0, idx + 1); - return str; -} - -// get individual file names from the command-line file path -void ASConsole::getFilePaths(const string& filePath) -{ - fileName.clear(); - targetDirectory = string(); - targetFilename = string(); - vector targetFilenameVector; - - // separate directory and file name - size_t separator = filePath.find_last_of(g_fileSeparator); - if (separator == string::npos) - { - // if no directory is present, use the currently active directory - targetDirectory = getCurrentDirectory(filePath); - targetFilename = filePath; - mainDirectoryLength = targetDirectory.length() + 1; // +1 includes trailing separator - } - else - { - targetDirectory = filePath.substr(0, separator); - targetFilename = filePath.substr(separator + 1); - mainDirectoryLength = targetDirectory.length() + 1; // +1 includes trailing separator - } - - if (targetFilename.length() == 0) - { - fprintf(stderr, _("Missing filename in %s\n"), filePath.c_str()); - error(); - } - - // check filename for wildcards - hasWildcard = false; - if (targetFilename.find_first_of("*?") != string::npos) - hasWildcard = true; - - // If the filename is not quoted on Linux, bash will replace the - // wildcard instead of passing it to the program. - if (isRecursive && !hasWildcard) - { - fprintf(stderr, "%s\n", _("Recursive option with no wildcard")); -#ifndef _WIN32 - fprintf(stderr, "%s\n", _("Did you intend quote the filename")); -#endif - error(); - } - - bool hasMultipleTargets = false; - if (targetFilename.find_first_of(",;") != string::npos) - hasMultipleTargets = true; - - // display directory name for wildcard processing - if (hasWildcard) - { - printSeparatingLine(); - printMsg(_("Directory %s\n"), targetDirectory + g_fileSeparator + targetFilename); - } - - // clear exclude hits vector - size_t excludeHitsVectorSize = excludeHitsVector.size(); - for (size_t ix = 0; ix < excludeHitsVectorSize; ix++) - excludeHitsVector[ix] = false; - - // create a vector of paths and file names to process - if (hasWildcard || isRecursive || hasMultipleTargets) - { - getTargetFilenames(targetFilename, targetFilenameVector); - getFileNames(targetDirectory, targetFilenameVector); - } - else - { - // verify a single file is not a directory (needed on Linux) - string entryFilepath = targetDirectory + g_fileSeparator + targetFilename; - struct stat statbuf; - if (stat(entryFilepath.c_str(), &statbuf) == 0 && (statbuf.st_mode & S_IFREG)) - fileName.emplace_back(entryFilepath); - } - - // check for unprocessed excludes - bool excludeErr = false; - for (size_t ix = 0; ix < excludeHitsVector.size(); ix++) - { - if (!excludeHitsVector[ix]) - { - excludeErr = true; - if (!ignoreExcludeErrorsDisplay) - { - if (ignoreExcludeErrors) - printMsg(_("Exclude (unmatched) %s\n"), excludeVector[ix]); - else - fprintf(stderr, _("Exclude (unmatched) %s\n"), excludeVector[ix].c_str()); - } - else - { - if (!ignoreExcludeErrors) - fprintf(stderr, _("Exclude (unmatched) %s\n"), excludeVector[ix].c_str()); - } - } - } - - if (excludeErr && !ignoreExcludeErrors) - { - if (hasWildcard && !isRecursive) - fprintf(stderr, "%s\n", _("Did you intend to use --recursive")); - error(); - } - - // check if files were found (probably an input error if not) - if (fileName.empty()) - { - fprintf(stderr, _("No file to process %s\n"), filePath.c_str()); - if (hasWildcard && !isRecursive) - fprintf(stderr, "%s\n", _("Did you intend to use --recursive")); - error(); - } - - if (hasWildcard) - printSeparatingLine(); -} - -// Check if a file exists -bool ASConsole::fileExists(const char* file) const -{ - struct stat buf; - return (stat(file, &buf) == 0); -} - -bool ASConsole::fileNameVectorIsEmpty() const -{ - return fileNameVector.empty(); -} - -bool ASConsole::isOption(const string& arg, const char* op) -{ - return arg == op; -} - -bool ASConsole::isOption(const string& arg, const char* a, const char* b) -{ - return (isOption(arg, a) || isOption(arg, b)); -} - -bool ASConsole::isParamOption(const string& arg, const char* option) -{ - bool retVal = arg.compare(0, strlen(option), option) == 0; - // if comparing for short option, 2nd char of arg must be numeric - if (retVal && strlen(option) == 1 && arg.length() > 1) - if (!isdigit((unsigned char) arg[1])) - retVal = false; - return retVal; -} - -// compare a path to the exclude vector -// used for both directories and filenames -// updates the g_excludeHitsVector -// return true if a match -bool ASConsole::isPathExclued(const string& subPath) -{ - bool retVal = false; - - // read the exclude vector checking for a match - for (size_t i = 0; i < excludeVector.size(); i++) - { - string exclude = excludeVector[i]; - - if (subPath.length() < exclude.length()) - continue; - - size_t compareStart = subPath.length() - exclude.length(); - // subPath compare must start with a directory name - if (compareStart > 0) - { - char lastPathChar = subPath[compareStart - 1]; - if (lastPathChar != g_fileSeparator) - continue; - } - - string compare = subPath.substr(compareStart); - if (!g_isCaseSensitive) - { - // make it case insensitive for Windows - for (size_t j = 0; j < compare.length(); j++) - compare[j] = (char) tolower(compare[j]); - for (size_t j = 0; j < exclude.length(); j++) - exclude[j] = (char) tolower(exclude[j]); - } - // compare sub directory to exclude data - must check them all - if (compare == exclude) - { - excludeHitsVector[i] = true; - retVal = true; - break; - } - } - return retVal; -} - -void ASConsole::printHelp() const -{ - cout << endl; - cout << " Artistic Style " << g_version << endl; - cout << " Maintained by: Jim Pattee\n"; - cout << " Original Author: Tal Davidson\n"; - cout << endl; - cout << "Usage:\n"; - cout << "------\n"; - cout << " astyle [OPTIONS] File1 File2 File3 [...]\n"; - cout << endl; - cout << " astyle [OPTIONS] < Original > Beautified\n"; - cout << endl; - cout << " When indenting a specific file, the resulting indented file RETAINS\n"; - cout << " the original file-name. The original pre-indented file is renamed,\n"; - cout << " with a suffix of \'.orig\' added to the original filename.\n"; - cout << endl; - cout << " Wildcards (* and ?) may be used in the filename.\n"; - cout << " A \'recursive\' option can process directories recursively.\n"; - cout << " Multiple file extensions may be separated by a comma.\n"; - cout << endl; - cout << " By default, astyle is set up to indent with four spaces per indent,\n"; - cout << " a maximal indentation of 40 spaces inside continuous statements,\n"; - cout << " a minimum indentation of eight spaces inside conditional statements,\n"; - cout << " and NO formatting options.\n"; - cout << endl; - cout << "Options:\n"; - cout << "--------\n"; - cout << " This program follows the usual GNU command line syntax.\n"; - cout << " Long options (starting with '--') must be written one at a time.\n"; - cout << " Short options (starting with '-') may be appended together.\n"; - cout << " Thus, -bps4 is the same as -b -p -s4.\n"; - cout << endl; - cout << "Option Files:\n"; - cout << "-------------\n"; - cout << " Artistic Style looks for a default option file and/or a project\n"; - cout << " option file in the following order:\n"; - cout << " 1. The command line options have precedence.\n"; - cout << " 2. The project option file has precedence over the default file\n"; - cout << " o the file name indicated by the --project= command line option.\n"; - cout << " o the file named .astylerc or _ astylerc.\n"; - cout << " o the file name identified by ARTISTIC_STYLE_PROJECT_OPTIONS.\n"; - cout << " o the file is disabled by --project=none on the command line.\n"; - cout << " 3. The default option file that can be used for all projects.\n"; - cout << " o the file path indicated by the --options= command line option.\n"; - cout << " o the file path indicated by ARTISTIC_STYLE_OPTIONS.\n"; - cout << " o the file named .astylerc in the HOME directory (for Linux).\n"; - cout << " o the file name astylerc in the APPDATA directory (for Windows).\n"; - cout << " o the file is disabled by --project=none on the command line.\n"; - cout << " Long options within the option files may be written without '--'.\n"; - cout << " Line-end comments begin with a '#'.\n"; - cout << endl; - cout << "Disable Formatting:\n"; - cout << "-------------------\n"; - cout << " Disable Block\n"; - cout << " Blocks of code can be disabled with the comment tags *INDENT-OFF*\n"; - cout << " and *INDENT-ON*. It must be contained in a one-line comment.\n"; - cout << endl; - cout << " Disable Line\n"; - cout << " Padding of operators can be disabled on a single line using the\n"; - cout << " comment tag *NOPAD*. It must be contained in a line-end comment.\n"; - cout << endl; - cout << "Brace Style Options:\n"; - cout << "--------------------\n"; - cout << " default brace style\n"; - cout << " If no brace style is requested, the opening braces will not be\n"; - cout << " changed and closing braces will be broken from the preceding line.\n"; - cout << endl; - cout << " --style=allman OR --style=bsd OR --style=break OR -A1\n"; - cout << " Allman style formatting/indenting.\n"; - cout << " Broken braces.\n"; - cout << endl; - cout << " --style=java OR --style=attach OR -A2\n"; - cout << " Java style formatting/indenting.\n"; - cout << " Attached braces.\n"; - cout << endl; - cout << " --style=kr OR --style=k&r OR --style=k/r OR -A3\n"; - cout << " Kernighan & Ritchie style formatting/indenting.\n"; - cout << " Linux braces.\n"; - cout << endl; - cout << " --style=stroustrup OR -A4\n"; - cout << " Stroustrup style formatting/indenting.\n"; - cout << " Linux braces, with broken closing headers.\n"; - cout << endl; - cout << " --style=whitesmith OR -A5\n"; - cout << " Whitesmith style formatting/indenting.\n"; - cout << " Broken, indented braces.\n"; - cout << " Indented class blocks and switch blocks.\n"; - cout << endl; - cout << " --style=vtk OR -A15\n"; - cout << " VTK style formatting/indenting.\n"; - cout << " Broken, indented braces except for the opening braces.\n"; - cout << endl; - cout << " --style=ratliff OR --style=banner OR -A6\n"; - cout << " Ratliff style formatting/indenting.\n"; - cout << " Attached, indented braces.\n"; - cout << endl; - cout << " --style=gnu OR -A7\n"; - cout << " GNU style formatting/indenting.\n"; - cout << " Broken braces, indented blocks.\n"; - cout << endl; - cout << " --style=linux OR --style=knf OR -A8\n"; - cout << " Linux style formatting/indenting.\n"; - cout << " Linux braces, minimum conditional indent is one-half indent.\n"; - cout << endl; - cout << " --style=horstmann OR --style=run-in OR -A9\n"; - cout << " Horstmann style formatting/indenting.\n"; - cout << " Run-in braces, indented switches.\n"; - cout << endl; - cout << " --style=1tbs OR --style=otbs OR -A10\n"; - cout << " One True Brace Style formatting/indenting.\n"; - cout << " Linux braces, add braces to all conditionals.\n"; - cout << endl; - cout << " --style=google OR -A14\n"; - cout << " Google style formatting/indenting.\n"; - cout << " Attached braces, indented class modifiers.\n"; - cout << endl; - cout << " --style=mozilla OR -A16\n"; - cout << " Mozilla style formatting/indenting.\n"; - cout << " Linux braces, with broken braces for structs and enums,\n"; - cout << " and attached braces for namespaces.\n"; - cout << endl; - cout << " --style=webkit OR -A17\n"; - cout << " WebKit style formatting/indenting.\n"; - cout << " Linux braces, with attached closing headers.\n"; - cout << endl; - cout << " --style=pico OR -A11\n"; - cout << " Pico style formatting/indenting.\n"; - cout << " Run-in opening braces and attached closing braces.\n"; - cout << " Uses keep one line blocks and keep one line statements.\n"; - cout << endl; - cout << " --style=lisp OR -A12\n"; - cout << " Lisp style formatting/indenting.\n"; - cout << " Attached opening braces and attached closing braces.\n"; - cout << " Uses keep one line statements.\n"; - cout << endl; - cout << "Tab Options:\n"; - cout << "------------\n"; - cout << " default indent option\n"; - cout << " If no indentation option is set, the default\n"; - cout << " option of 4 spaces per indent will be used.\n"; - cout << endl; - cout << " --indent=spaces=# OR -s#\n"; - cout << " Indent using # spaces per indent. Not specifying #\n"; - cout << " will result in a default of 4 spaces per indent.\n"; - cout << endl; - cout << " --indent=tab OR --indent=tab=# OR -t OR -t#\n"; - cout << " Indent using tab characters, assuming that each\n"; - cout << " indent is # spaces long. Not specifying # will result\n"; - cout << " in a default assumption of 4 spaces per indent.\n"; - cout << endl; - cout << " --indent=force-tab=# OR -T#\n"; - cout << " Indent using tab characters, assuming that each\n"; - cout << " indent is # spaces long. Force tabs to be used in areas\n"; - cout << " AStyle would prefer to use spaces.\n"; - cout << endl; - cout << " --indent=force-tab-x=# OR -xT#\n"; - cout << " Allows the tab length to be set to a length that is different\n"; - cout << " from the indent length. This may cause the indentation to be\n"; - cout << " a mix of both spaces and tabs. This option sets the tab length.\n"; - cout << endl; - cout << "Brace Modify Options:\n"; - cout << "---------------------\n"; - cout << " --attach-namespaces OR -xn\n"; - cout << " Attach braces to a namespace statement.\n"; - cout << endl; - cout << " --attach-classes OR -xc\n"; - cout << " Attach braces to a class statement.\n"; - cout << endl; - cout << " --attach-inlines OR -xl\n"; - cout << " Attach braces to class inline function definitions.\n"; - cout << endl; - cout << " --attach-extern-c OR -xk\n"; - cout << " Attach braces to an extern \"C\" statement.\n"; - cout << endl; - cout << " --attach-closing-while OR -xV\n"; - cout << " Attach closing while of do-while to the closing brace.\n"; - cout << endl; - cout << "Indentation Options:\n"; - cout << "--------------------\n"; - cout << " --indent-classes OR -C\n"; - cout << " Indent 'class' blocks so that the entire block is indented.\n"; - cout << endl; - cout << " --indent-modifiers OR -xG\n"; - cout << " Indent 'class' access modifiers, 'public:', 'protected:' or\n"; - cout << " 'private:', one half indent. The rest of the class is not\n"; - cout << " indented. \n"; - cout << endl; - cout << " --indent-switches OR -S\n"; - cout << " Indent 'switch' blocks, so that the inner 'case XXX:'\n"; - cout << " headers are indented in relation to the switch block.\n"; - cout << endl; - cout << " --indent-cases OR -K\n"; - cout << " Indent case blocks from the 'case XXX:' headers.\n"; - cout << " Case statements not enclosed in blocks are NOT indented.\n"; - cout << endl; - cout << " --indent-namespaces OR -N\n"; - cout << " Indent the contents of namespace blocks.\n"; - cout << endl; - cout << " --indent-after-parens OR -xU\n"; - cout << " Indent, instead of align, continuation lines following lines\n"; - cout << " that contain an opening paren '(' or an assignment '='. \n"; - cout << endl; - cout << " --indent-continuation=# OR -xt#\n"; - cout << " Indent continuation lines an additional # indents.\n"; - cout << " The valid values are 0 thru 4 indents.\n"; - cout << " The default value is 1 indent.\n"; - cout << endl; - cout << " --indent-labels OR -L\n"; - cout << " Indent labels so that they appear one indent less than\n"; - cout << " the current indentation level, rather than being\n"; - cout << " flushed completely to the left (which is the default).\n"; - cout << endl; - cout << " --indent-preproc-block OR -xW\n"; - cout << " Indent preprocessor blocks at brace level 0.\n"; - cout << " Without this option the preprocessor block is not indented.\n"; - cout << endl; - cout << " --indent-preproc-cond OR -xw\n"; - cout << " Indent preprocessor conditional statements #if/#else/#endif\n"; - cout << " to the same level as the source code.\n"; - cout << endl; - cout << " --indent-preproc-define OR -w\n"; - cout << " Indent multi-line preprocessor #define statements.\n"; - cout << endl; - cout << " --indent-col1-comments OR -Y\n"; - cout << " Indent line comments that start in column one.\n"; - cout << endl; - cout << " --min-conditional-indent=# OR -m#\n"; - cout << " Indent a minimal # spaces in a continuous conditional\n"; - cout << " belonging to a conditional header.\n"; - cout << " The valid values are:\n"; - cout << " 0 - no minimal indent.\n"; - cout << " 1 - indent at least one additional indent.\n"; - cout << " 2 - indent at least two additional indents.\n"; - cout << " 3 - indent at least one-half an additional indent.\n"; - cout << " The default value is 2, two additional indents.\n"; - cout << endl; - cout << " --max-continuation-indent=# OR -M#\n"; - cout << " Indent a maximal # spaces in a continuation line,\n"; - cout << " relative to the previous line.\n"; - cout << " The valid values are 40 thru 120.\n"; - cout << " The default value is 40.\n"; - cout << endl; - cout << "Padding Options:\n"; - cout << "----------------\n"; - cout << " --break-blocks OR -f\n"; - cout << " Insert empty lines around unrelated blocks, labels, classes, ...\n"; - cout << endl; - cout << " --break-blocks=all OR -F\n"; - cout << " Like --break-blocks, except also insert empty lines \n"; - cout << " around closing headers (e.g. 'else', 'catch', ...).\n"; - cout << endl; - cout << " --pad-oper OR -p\n"; - cout << " Insert space padding around operators.\n"; - cout << endl; - cout << " --pad-comma OR -xg\n"; - cout << " Insert space padding after commas.\n"; - cout << endl; - cout << " --pad-paren OR -P\n"; - cout << " Insert space padding around parenthesis on both the outside\n"; - cout << " and the inside.\n"; - cout << endl; - cout << " --pad-paren-out OR -d\n"; - cout << " Insert space padding around parenthesis on the outside only.\n"; - cout << endl; - cout << " --pad-first-paren-out OR -xd\n"; - cout << " Insert space padding around first parenthesis in a series on\n"; - cout << " the outside only.\n"; - cout << endl; - cout << " --pad-paren-in OR -D\n"; - cout << " Insert space padding around parenthesis on the inside only.\n"; - cout << endl; - cout << " --pad-header OR -H\n"; - cout << " Insert space padding after paren headers (e.g. 'if', 'for'...).\n"; - cout << endl; - cout << " --unpad-paren OR -U\n"; - cout << " Remove unnecessary space padding around parenthesis. This\n"; - cout << " can be used in combination with the 'pad' options above.\n"; - cout << endl; - cout << " --delete-empty-lines OR -xe\n"; - cout << " Delete empty lines.\n"; - cout << " It will NOT delete lines added by the break-blocks options.\n"; - cout << endl; - cout << " --delete-multiple-empty-lines OR -xm\n"; - cout << " Delete consecutive empty lines.\n"; - cout << " It will NOT delete lines added by the break-blocks options.\n"; - cout << endl; - cout << " --fill-empty-lines OR -E\n"; - cout << " Fill empty lines with the white space of their\n"; - cout << " previous lines.\n"; - cout << endl; - cout << " --align-pointer=type OR -k1\n"; - cout << " --align-pointer=middle OR -k2\n"; - cout << " --align-pointer=name OR -k3\n"; - cout << " Attach a pointer or reference operator (*, &, or ^) to either\n"; - cout << " the operator type (left), middle, or operator name (right).\n"; - cout << " To align the reference separately use --align-reference.\n"; - cout << endl; - cout << " --align-reference=none OR -W0\n"; - cout << " --align-reference=type OR -W1\n"; - cout << " --align-reference=middle OR -W2\n"; - cout << " --align-reference=name OR -W3\n"; - cout << " Attach a reference operator (&) to either\n"; - cout << " the operator type (left), middle, or operator name (right).\n"; - cout << " If not set, follow pointer alignment.\n"; - cout << endl; - cout << "Formatting Options:\n"; - cout << "-------------------\n"; - cout << " --break-closing-braces OR -y\n"; - cout << " Break braces before closing headers (e.g. 'else', 'catch', ...).\n"; - cout << " Use with --style=java, --style=kr, --style=stroustrup,\n"; - cout << " --style=linux, or --style=1tbs.\n"; - cout << endl; - cout << " --break-elseifs OR -e\n"; - cout << " Break 'else if()' statements into two different lines.\n"; - cout << endl; - cout << " --break-one-line-headers OR -xb\n"; - cout << " Break one line headers (e.g. 'if', 'while', 'else', ...) from a\n"; - cout << " statement residing on the same line.\n"; - cout << endl; - cout << " --add-braces OR -j\n"; - cout << " Add braces to unbraced one line conditional statements.\n"; - cout << endl; - cout << " --add-one-line-braces OR -J\n"; - cout << " Add one line braces to unbraced one line conditional\n"; - cout << " statements.\n"; - cout << endl; - cout << " --remove-braces OR -xj\n"; - cout << " Remove braces from a braced one line conditional statements.\n"; - cout << endl; - cout << " --break-return-type OR -xB\n"; - cout << " --break-return-type-decl OR -xD\n"; - cout << " Break the return type from the function name. Options are\n"; - cout << " for the function definitions and the function declarations.\n"; - cout << endl; - cout << " --attach-return-type OR -xf\n"; - cout << " --attach-return-type-decl OR -xh\n"; - cout << " Attach the return type to the function name. Options are\n"; - cout << " for the function definitions and the function declarations.\n"; - cout << endl; - cout << " --keep-one-line-blocks OR -O\n"; - cout << " Don't break blocks residing completely on one line.\n"; - cout << endl; - cout << " --keep-one-line-statements OR -o\n"; - cout << " Don't break lines containing multiple statements into\n"; - cout << " multiple single-statement lines.\n"; - cout << endl; - cout << " --convert-tabs OR -c\n"; - cout << " Convert tabs to the appropriate number of spaces.\n"; - cout << endl; - cout << " --close-templates OR -xy\n"; - cout << " Close ending angle brackets on template definitions.\n"; - cout << endl; - cout << " --remove-comment-prefix OR -xp\n"; - cout << " Remove the leading '*' prefix on multi-line comments and\n"; - cout << " indent the comment text one indent.\n"; - cout << endl; - cout << " --max-code-length=# OR -xC#\n"; - cout << " --break-after-logical OR -xL\n"; - cout << " max-code-length=# will break the line if it exceeds more than\n"; - cout << " # characters. The valid values are 50 thru 200.\n"; - cout << " If the line contains logical conditionals they will be placed\n"; - cout << " first on the new line. The option break-after-logical will\n"; - cout << " cause the logical conditional to be placed last on the\n"; - cout << " previous line.\n"; - cout << endl; - cout << " --mode=c\n"; - cout << " Indent a C or C++ source file (this is the default).\n"; - cout << endl; - cout << " --mode=java\n"; - cout << " Indent a Java source file.\n"; - cout << endl; - cout << " --mode=cs\n"; - cout << " Indent a C# source file.\n"; - cout << endl; - cout << "Objective-C Options:\n"; - cout << "--------------------\n"; - cout << " --pad-method-prefix OR -xQ\n"; - cout << " Insert space padding after the '-' or '+' Objective-C\n"; - cout << " method prefix.\n"; - cout << endl; - cout << " --unpad-method-prefix OR -xR\n"; - cout << " Remove all space padding after the '-' or '+' Objective-C\n"; - cout << " method prefix.\n"; - cout << endl; - cout << " --pad-return-type OR -xq\n"; - cout << " Insert space padding after the Objective-C return type.\n"; - cout << endl; - cout << " --unpad-return-type OR -xr\n"; - cout << " Remove all space padding after the Objective-C return type.\n"; - cout << endl; - cout << " --pad-param-type OR -xS\n"; - cout << " Insert space padding after the Objective-C return type.\n"; - cout << endl; - cout << " --unpad-param-type OR -xs\n"; - cout << " Remove all space padding after the Objective-C return type.\n"; - cout << endl; - cout << " --align-method-colon OR -xM\n"; - cout << " Align the colons in an Objective-C method definition.\n"; - cout << endl; - cout << " --pad-method-colon=none OR -xP\n"; - cout << " --pad-method-colon=all OR -xP1\n"; - cout << " --pad-method-colon=after OR -xP2\n"; - cout << " --pad-method-colon=before OR -xP3\n"; - cout << " Add or remove space padding before or after the colons in an\n"; - cout << " Objective-C method call.\n"; - cout << endl; - cout << "Other Options:\n"; - cout << "--------------\n"; - cout << " --suffix=####\n"; - cout << " Append the suffix #### instead of '.orig' to original filename.\n"; - cout << endl; - cout << " --suffix=none OR -n\n"; - cout << " Do not retain a backup of the original file.\n"; - cout << endl; - cout << " --recursive OR -r OR -R\n"; - cout << " Process subdirectories recursively.\n"; - cout << endl; - cout << " --dry-run\n"; - cout << " Perform a trial run with no changes made to check for formatting.\n"; - cout << endl; - cout << " --exclude=####\n"; - cout << " Specify a file or directory #### to be excluded from processing.\n"; - cout << endl; - cout << " --ignore-exclude-errors OR -i\n"; - cout << " Allow processing to continue if there are errors in the exclude=####\n"; - cout << " options. It will display the unmatched excludes.\n"; - cout << endl; - cout << " --ignore-exclude-errors-x OR -xi\n"; - cout << " Allow processing to continue if there are errors in the exclude=####\n"; - cout << " options. It will NOT display the unmatched excludes.\n"; - cout << endl; - cout << " --errors-to-stdout OR -X\n"; - cout << " Print errors and help information to standard-output rather than\n"; - cout << " to standard-error.\n"; - cout << endl; - cout << " --preserve-date OR -Z\n"; - cout << " Preserve the original file's date and time modified. The time\n"; - cout << " modified will be changed a few micro seconds to force a compile.\n"; - cout << endl; - cout << " --verbose OR -v\n"; - cout << " Verbose mode. Extra informational messages will be displayed.\n"; - cout << endl; - cout << " --formatted OR -Q\n"; - cout << " Formatted display mode. Display only the files that have been\n"; - cout << " formatted.\n"; - cout << endl; - cout << " --quiet OR -q\n"; - cout << " Quiet mode. Suppress all output except error messages.\n"; - cout << endl; - cout << " --lineend=windows OR -z1\n"; - cout << " --lineend=linux OR -z2\n"; - cout << " --lineend=macold OR -z3\n"; - cout << " Force use of the specified line end style. Valid options\n"; - cout << " are windows (CRLF), linux (LF), and macold (CR).\n"; - cout << endl; - cout << "Command Line Only:\n"; - cout << "------------------\n"; - cout << " --options=####\n"; - cout << " --options=none\n"; - cout << " Specify a default option file #### to read and use.\n"; - cout << " It must contain a file path and a file name.\n"; - cout << " 'none' disables the default option file.\n"; - cout << endl; - cout << " --project\n"; - cout << " --project=####\n"; - cout << " --project=none\n"; - cout << " Specify a project option file #### to read and use.\n"; - cout << " It must contain a file name only, without a directory path.\n"; - cout << " The file should be included in the project top-level directory.\n"; - cout << " The default file name is .astylerc or _astylerc.\n"; - cout << " 'none' disables the project or environment variable file.\n"; - cout << endl; - cout << " --ascii OR -I\n"; - cout << " The displayed output will be ascii characters only.\n"; - cout << endl; - cout << " --version OR -V\n"; - cout << " Print version number.\n"; - cout << endl; - cout << " --help OR -h OR -?\n"; - cout << " Print this help message.\n"; - cout << endl; - cout << " --html OR -!\n"; - cout << " Open the HTML help file \"astyle.html\" in the default browser.\n"; - cout << " The documentation must be installed in the standard install path.\n"; - cout << endl; - cout << " --html=####\n"; - cout << " Open a HTML help file in the default browser using the file path\n"; - cout << " ####. The path may include a directory path and a file name, or a\n"; - cout << " file name only. Paths containing spaces must be enclosed in quotes.\n"; - cout << endl; - cout << " --stdin=####\n"; - cout << " Use the file path #### as input to single file formatting.\n"; - cout << " This is a replacement for redirection.\n"; - cout << endl; - cout << " --stdout=####\n"; - cout << " Use the file path #### as output from single file formatting.\n"; - cout << " This is a replacement for redirection.\n"; - cout << endl; - cout << endl; -} - -/** - * Process files in the fileNameVector. - */ -void ASConsole::processFiles() -{ - if (isVerbose) - printVerboseHeader(); - - clock_t startTime = clock(); // start time of file formatting - - // loop thru input fileNameVector and process the files - for (const string& fileNameVectorName : fileNameVector) - { - getFilePaths(fileNameVectorName); - - // loop thru fileName vector formatting the files - for (const string& file : fileName) - formatFile(file); - } - - // files are processed, display stats - if (isVerbose) - printVerboseStats(startTime); -} - -// process options from the command line and option files -// build the vectors fileNameVector, excludeVector, optionsVector, -// projectOptionsVector and fileOptionsVector -void ASConsole::processOptions(const vector& argvOptions) -{ - bool ok = true; - bool optionFileRequired = false; - bool shouldParseOptionFile = true; - bool projectOptionFileRequired = false; - bool shouldParseProjectOptionFile = true; - string projectOptionArg; // save for display - - // get command line options - for (string arg : argvOptions) - { - if (isOption(arg, "-I") - || isOption(arg, "--ascii")) - { - useAscii = true; - setlocale(LC_ALL, "C"); // use English decimal indicator - localizer.setLanguageFromName("en"); - } - else if (isOption(arg, "--options=none")) - { - optionFileRequired = false; - shouldParseOptionFile = false; - optionFileName = ""; - } - else if (isParamOption(arg, "--options=")) - { - optionFileName = getParam(arg, "--options="); - standardizePath(optionFileName); - optionFileName = getFullPathName(optionFileName); - optionFileRequired = true; - } - else if (isOption(arg, "--project=none")) - { - projectOptionFileRequired = false; - shouldParseProjectOptionFile = false; - setProjectOptionFileName(""); - } - else if (isParamOption(arg, "--project=")) - { - projectOptionFileName = getParam(arg, "--project="); - standardizePath(projectOptionFileName); - projectOptionFileRequired = true; - shouldParseProjectOptionFile = false; - projectOptionArg = projectOptionFileName; - } - else if (isOption(arg, "--project")) - { - projectOptionFileName = ".astylerc"; - projectOptionFileRequired = true; - shouldParseProjectOptionFile = false; - projectOptionArg = projectOptionFileName; - } - else if (isOption(arg, "-h") - || isOption(arg, "--help") - || isOption(arg, "-?")) - { - printHelp(); - exit(EXIT_SUCCESS); - } - else if (isOption(arg, "-!") - || isOption(arg, "--html")) - { - launchDefaultBrowser(); - exit(EXIT_SUCCESS); - } - else if (isParamOption(arg, "--html=")) - { - string htmlFilePath = getParam(arg, "--html="); - launchDefaultBrowser(htmlFilePath.c_str()); - exit(EXIT_SUCCESS); - } - else if (isOption(arg, "-V") - || isOption(arg, "--version")) - { - printf("Artistic Style Version %s\n", g_version); - exit(EXIT_SUCCESS); - } - else if (isParamOption(arg, "--stdin=")) - { - string path = getParam(arg, "--stdin="); - standardizePath(path); - setStdPathIn(path); - } - else if (isParamOption(arg, "--stdout=")) - { - string path = getParam(arg, "--stdout="); - standardizePath(path); - setStdPathOut(path); - } - else if (arg[0] == '-') - { - optionsVector.emplace_back(arg); - } - else // file-name - { - standardizePath(arg); - fileNameVector.emplace_back(arg); - } - } - - // get option file path and name - if (shouldParseOptionFile) - { - if (optionFileName.empty()) - { - const char* const env = getenv("ARTISTIC_STYLE_OPTIONS"); - if (env != nullptr) - { - setOptionFileName(env); - standardizePath(optionFileName); - optionFileName = getFullPathName(optionFileName); - } - } - // for Linux - if (optionFileName.empty()) - { - const char* const env = getenv("HOME"); - if (env != nullptr) - { - string name = string(env) + "/.astylerc"; - if (fileExists(name.c_str())) - setOptionFileName(name); - } - } - // for Windows - if (optionFileName.empty()) - { - const char* const env = getenv("APPDATA"); - if (env != nullptr) - { - string name = string(env) + "\\astylerc"; - if (fileExists(name.c_str())) - setOptionFileName(name); - } - } - // for Windows - // NOTE: depreciated with release 3.1, remove when appropriate - // there is NO test data for this option - if (optionFileName.empty()) - { - const char* const env = getenv("USERPROFILE"); - if (env != nullptr) - { - string name = string(env) + "\\astylerc"; - if (fileExists(name.c_str())) - setOptionFileName(name); - } - } - } - - // find project option file - if (projectOptionFileRequired) - { - string optfilepath = findProjectOptionFilePath(projectOptionFileName); - if (optfilepath.empty() || projectOptionArg.empty()) - error(_("Cannot open project option file"), projectOptionArg.c_str()); - standardizePath(optfilepath); - setProjectOptionFileName(optfilepath); - } - if (shouldParseProjectOptionFile) - { - const char* const env = getenv("ARTISTIC_STYLE_PROJECT_OPTIONS"); - if (env != nullptr) - { - string optfilepath = findProjectOptionFilePath(env); - standardizePath(optfilepath); - setProjectOptionFileName(optfilepath); - } - } - - ASOptions options(formatter, *this); - if (!optionFileName.empty()) - { - stringstream optionsIn; - if (!fileExists(optionFileName.c_str())) - error(_("Cannot open default option file"), optionFileName.c_str()); - FileEncoding encoding = readFile(optionFileName, optionsIn); - // bypass a BOM, all BOMs have been converted to utf-8 - if (encoding == UTF_8BOM || encoding == UTF_16LE || encoding == UTF_16BE) - { - char buf[4]; - optionsIn.get(buf, 4); - assert(strcmp(buf, "\xEF\xBB\xBF") == 0); - } - options.importOptions(optionsIn, fileOptionsVector); - ok = options.parseOptions(fileOptionsVector, - string(_("Invalid default options:"))); - } - else if (optionFileRequired) - error(_("Cannot open default option file"), optionFileName.c_str()); - - if (!ok) - { - (*errorStream) << options.getOptionErrors(); - (*errorStream) << _("For help on options type 'astyle -h'") << endl; - error(); - } - - if (!projectOptionFileName.empty()) - { - stringstream projectOptionsIn; - if (!fileExists(projectOptionFileName.c_str())) - error(_("Cannot open project option file"), projectOptionFileName.c_str()); - FileEncoding encoding = readFile(projectOptionFileName, projectOptionsIn); - // bypass a BOM, all BOMs have been converted to utf-8 - if (encoding == UTF_8BOM || encoding == UTF_16LE || encoding == UTF_16BE) - { - char buf[4]; - projectOptionsIn.get(buf, 4); - assert(strcmp(buf, "\xEF\xBB\xBF") == 0); - } - options.importOptions(projectOptionsIn, projectOptionsVector); - ok = options.parseOptions(projectOptionsVector, - string(_("Invalid project options:"))); - } - - if (!ok) - { - (*errorStream) << options.getOptionErrors(); - (*errorStream) << _("For help on options type 'astyle -h'") << endl; - error(); - } - - // parse the command line options vector for errors - ok = options.parseOptions(optionsVector, - string(_("Invalid command line options:"))); - if (!ok) - { - (*errorStream) << options.getOptionErrors(); - (*errorStream) << _("For help on options type 'astyle -h'") << endl; - error(); - } -} - -// remove a file and check for an error -void ASConsole::removeFile(const char* fileName_, const char* errMsg) const -{ - if (remove(fileName_) != 0) - { - if (errno == ENOENT) // no file is OK - errno = 0; - if (errno) - { - perror("errno message"); - error(errMsg, fileName_); - } - } -} - -// rename a file and check for an error -void ASConsole::renameFile(const char* oldFileName, const char* newFileName, const char* errMsg) const -{ - int result = rename(oldFileName, newFileName); - if (result != 0) - { - // if file still exists the remove needs more time - retry - if (errno == EEXIST) - { - errno = 0; - waitForRemove(newFileName); - result = rename(oldFileName, newFileName); - } - if (result != 0) - { - perror("errno message"); - error(errMsg, oldFileName); - } - } -} - -// make sure file separators are correct type (Windows or Linux) -// remove ending file separator -// remove beginning file separator if requested and NOT a complete file path -void ASConsole::standardizePath(string& path, bool removeBeginningSeparator /*false*/) const -{ -#ifdef __VMS - struct FAB fab; - struct NAML naml; - char less[NAML$C_MAXRSS]; - char sess[NAM$C_MAXRSS]; - int r0_status; - - // If we are on a VMS system, translate VMS style filenames to unix - // style. - fab = cc$rms_fab; - fab.fab$l_fna = (char*) -1; - fab.fab$b_fns = 0; - fab.fab$l_naml = &naml; - naml = cc$rms_naml; - strcpy(sess, path.c_str()); - naml.naml$l_long_filename = (char*) sess; - naml.naml$l_long_filename_size = path.length(); - naml.naml$l_long_expand = less; - naml.naml$l_long_expand_alloc = sizeof(less); - naml.naml$l_esa = sess; - naml.naml$b_ess = sizeof(sess); - naml.naml$v_no_short_upcase = 1; - r0_status = sys$parse(&fab); - if (r0_status == RMS$_SYN) - { - error("File syntax error", path.c_str()); - } - else - { - if (!$VMS_STATUS_SUCCESS(r0_status)) - { - (void) lib$signal(r0_status); - } - } - less[naml.naml$l_long_expand_size - naml.naml$b_ver] = '\0'; - sess[naml.naml$b_esl - naml.naml$b_ver] = '\0'; - if (naml.naml$l_long_expand_size > naml.naml$b_esl) - { - path = decc$translate_vms(less); - } - else - { - path = decc$translate_vms(sess); - } -#endif /* __VMS */ - - // make sure separators are correct type (Windows or Linux) - for (size_t i = 0; i < path.length(); i++) - { - i = path.find_first_of("/\\", i); - if (i == string::npos) - break; - path[i] = g_fileSeparator; - } - // remove beginning separator if requested - if (removeBeginningSeparator && (path[0] == g_fileSeparator)) - path.erase(0, 1); -} - -void ASConsole::printMsg(const char* msg, const string& data) const -{ - if (isQuiet) - return; - printf(msg, data.c_str()); -} - -void ASConsole::printSeparatingLine() const -{ - string line; - for (size_t i = 0; i < 60; i++) - line.append("-"); - printMsg("%s\n", line); -} - -void ASConsole::printVerboseHeader() const -{ - assert(isVerbose); - if (isQuiet) - return; - // get the date - time_t lt; - char str[20]; - lt = time(nullptr); - struct tm* ptr = localtime(<); - strftime(str, 20, "%x", ptr); - // print the header - // 60 is the length of the separator in printSeparatingLine() - string header = "Artistic Style " + string(g_version); - size_t numSpaces = 60 - header.length() - strlen(str); - header.append(numSpaces, ' '); - header.append(str); - header.append("\n"); - printf("%s", header.c_str()); - // print option files - if (!optionFileName.empty()) - printf(_("Default option file %s\n"), optionFileName.c_str()); - // NOTE: depreciated with release 3.1, remove when appropriate - if (!optionFileName.empty()) - { - const char* const env = getenv("USERPROFILE"); - if (env != nullptr && optionFileName == string(env) + "\\astylerc") - printf("The above option file has been DEPRECIATED\n"); - } - // end depreciated - if (!projectOptionFileName.empty()) - printf(_("Project option file %s\n"), projectOptionFileName.c_str()); -} - -void ASConsole::printVerboseStats(clock_t startTime) const -{ - assert(isVerbose); - if (isQuiet) - return; - if (hasWildcard) - printSeparatingLine(); - string formatted = getNumberFormat(filesFormatted); - string unchanged = getNumberFormat(filesUnchanged); - printf(_(" %s formatted %s unchanged "), formatted.c_str(), unchanged.c_str()); - - // show processing time - clock_t stopTime = clock(); - double secs = (stopTime - startTime) / double(CLOCKS_PER_SEC); - if (secs < 60) - { - if (secs < 2.0) - printf("%.2f", secs); - else if (secs < 20.0) - printf("%.1f", secs); - else - printf("%.0f", secs); - printf("%s", _(" seconds ")); - } - else - { - // show minutes and seconds if time is greater than one minute - int min = (int) secs / 60; - secs -= min * 60; - // NOTE: lround is not supported by MinGW and Embarcadero - int minsec = int(secs + .5); - printf(_("%d min %d sec "), min, minsec); - } - - string lines = getNumberFormat(linesOut); - printf(_("%s lines\n"), lines.c_str()); - printf("\n"); -} - -void ASConsole::sleep(int seconds) const -{ - clock_t endwait; - endwait = clock_t(clock() + seconds * CLOCKS_PER_SEC); - while (clock() < endwait) {} -} - -bool ASConsole::stringEndsWith(const string& str, const string& suffix) const -{ - int strIndex = (int) str.length() - 1; - int suffixIndex = (int) suffix.length() - 1; - - while (strIndex >= 0 && suffixIndex >= 0) - { - if (tolower(str[strIndex]) != tolower(suffix[suffixIndex])) - return false; - - --strIndex; - --suffixIndex; - } - // suffix longer than string - if (strIndex < 0 && suffixIndex >= 0) - return false; - return true; -} - -void ASConsole::updateExcludeVector(const string& suffixParam) -{ - excludeVector.emplace_back(suffixParam); - standardizePath(excludeVector.back(), true); - // do not use emplace_back on vector until supported by macOS - excludeHitsVector.push_back(false); -} - -int ASConsole::waitForRemove(const char* newFileName) const -{ - struct stat stBuf; - int seconds; - // sleep a max of 20 seconds for the remove - for (seconds = 1; seconds <= 20; seconds++) - { - sleep(1); - if (stat(newFileName, &stBuf) != 0) - break; - } - errno = 0; - return seconds; -} - -// From The Code Project http://www.codeproject.com/string/wildcmp.asp -// Written by Jack Handy - jakkhandy@hotmail.com -// Modified to compare case insensitive for Windows -int ASConsole::wildcmp(const char* wild, const char* data) const -{ - const char* cp = nullptr; - const char* mp = nullptr; - bool cmpval; - - while ((*data) && (*wild != '*')) - { - if (!g_isCaseSensitive) - cmpval = (tolower(*wild) != tolower(*data)) && (*wild != '?'); - else - cmpval = (*wild != *data) && (*wild != '?'); - - if (cmpval) - { - return 0; - } - wild++; - data++; - } - - while (*data) - { - if (*wild == '*') - { - if (!*++wild) - { - return 1; - } - mp = wild; - cp = data + 1; - } - else - { - if (!g_isCaseSensitive) - cmpval = (tolower(*wild) == tolower(*data) || (*wild == '?')); - else - cmpval = (*wild == *data) || (*wild == '?'); - - if (cmpval) - { - wild++; - data++; - } - else - { - wild = mp; - data = cp++; - } - } - } - - while (*wild == '*') - { - wild++; - } - return !*wild; -} - -void ASConsole::writeFile(const string& fileName_, FileEncoding encoding, ostringstream& out) const -{ - // save date accessed and date modified of original file - struct stat stBuf; - bool statErr = false; - if (stat(fileName_.c_str(), &stBuf) == -1) - statErr = true; - - // create a backup - if (!noBackup) - { - string origFileName = fileName_ + origSuffix; - removeFile(origFileName.c_str(), "Cannot remove pre-existing backup file"); - renameFile(fileName_.c_str(), origFileName.c_str(), "Cannot create backup file"); - } - - // write the output file - ofstream fout(fileName_.c_str(), ios::binary | ios::trunc); - if (!fout) - error("Cannot open output file", fileName_.c_str()); - if (encoding == UTF_16LE || encoding == UTF_16BE) - { - // convert utf-8 to utf-16 - bool isBigEndian = (encoding == UTF_16BE); - size_t utf16Size = encode.utf16LengthFromUtf8(out.str().c_str(), out.str().length()); - char* utf16Out = new char[utf16Size]; - size_t utf16Len = encode.utf8ToUtf16(const_cast(out.str().c_str()), - out.str().length(), isBigEndian, utf16Out); - assert(utf16Len <= utf16Size); - fout << string(utf16Out, utf16Len); - delete[] utf16Out; - } - else - fout << out.str(); - - fout.close(); - - // change date modified to original file date - // Embarcadero must be linked with cw32mt not cw32 - if (preserveDate) - { - if (!statErr) - { - struct utimbuf outBuf; - outBuf.actime = stBuf.st_atime; - // add ticks so 'make' will recognize a change - // Visual Studio 2008 needs more than 1 - outBuf.modtime = stBuf.st_mtime + 10; - if (utime(fileName_.c_str(), &outBuf) == -1) - statErr = true; - } - if (statErr) - { - perror("errno message"); - (*errorStream) << "********* Cannot preserve file date" << endl; - } - } -} - -#else // ASTYLE_LIB - -//----------------------------------------------------------------------------- -// ASLibrary class -// used by shared object (DLL) calls -//----------------------------------------------------------------------------- - -char16_t* ASLibrary::formatUtf16(const char16_t* pSourceIn, // the source to be formatted - const char16_t* pOptions, // AStyle options - fpError fpErrorHandler, // error handler function - fpAlloc fpMemoryAlloc) const // memory allocation function) -{ - const char* utf8In = convertUtf16ToUtf8(pSourceIn); - if (utf8In == nullptr) - { - fpErrorHandler(121, "Cannot convert input utf-16 to utf-8."); - return nullptr; - } - const char* utf8Options = convertUtf16ToUtf8(pOptions); - if (utf8Options == nullptr) - { - delete[] utf8In; - fpErrorHandler(122, "Cannot convert options utf-16 to utf-8."); - return nullptr; - } - // call the Artistic Style formatting function - // cannot use the callers memory allocation here - char* utf8Out = AStyleMain(utf8In, - utf8Options, - fpErrorHandler, - ASLibrary::tempMemoryAllocation); - // finished with these - delete[] utf8In; - delete[] utf8Options; - utf8In = nullptr; - utf8Options = nullptr; - // AStyle error has already been sent - if (utf8Out == nullptr) - return nullptr; - // convert text to wide char and return it - char16_t* utf16Out = convertUtf8ToUtf16(utf8Out, fpMemoryAlloc); - delete[] utf8Out; - utf8Out = nullptr; - if (utf16Out == nullptr) - { - fpErrorHandler(123, "Cannot convert output utf-8 to utf-16."); - return nullptr; - } - return utf16Out; -} - -// STATIC method to allocate temporary memory for AStyle formatting. -// The data will be converted before being returned to the calling program. -char* STDCALL ASLibrary::tempMemoryAllocation(unsigned long memoryNeeded) -{ - char* buffer = new (nothrow) char[memoryNeeded]; - return buffer; -} - -/** - * Convert utf-8 strings to utf16 strings. - * Memory is allocated by the calling program memory allocation function. - * The calling function must check for errors. - */ -char16_t* ASLibrary::convertUtf8ToUtf16(const char* utf8In, fpAlloc fpMemoryAlloc) const -{ - if (utf8In == nullptr) - return nullptr; - char* data = const_cast(utf8In); - size_t dataSize = strlen(utf8In); - bool isBigEndian = encode.getBigEndian(); - // return size is in number of CHARs, not char16_t - size_t utf16Size = (encode.utf16LengthFromUtf8(data, dataSize) + sizeof(char16_t)); - char* utf16Out = fpMemoryAlloc((long) utf16Size); - if (utf16Out == nullptr) - return nullptr; -#ifdef NDEBUG - encode.utf8ToUtf16(data, dataSize + 1, isBigEndian, utf16Out); -#else - size_t utf16Len = encode.utf8ToUtf16(data, dataSize + 1, isBigEndian, utf16Out); - assert(utf16Len == utf16Size); -#endif - assert(utf16Size == (encode.utf16len(reinterpret_cast(utf16Out)) + 1) * sizeof(char16_t)); - return reinterpret_cast(utf16Out); -} - -/** - * Convert utf16 strings to utf-8. - * The calling function must check for errors and delete the - * allocated memory. - */ -char* ASLibrary::convertUtf16ToUtf8(const char16_t* utf16In) const -{ - if (utf16In == nullptr) - return nullptr; - char* data = reinterpret_cast(const_cast(utf16In)); - // size must be in chars - size_t dataSize = encode.utf16len(utf16In) * sizeof(char16_t); - bool isBigEndian = encode.getBigEndian(); - size_t utf8Size = encode.utf8LengthFromUtf16(data, dataSize, isBigEndian) + 1; - char* utf8Out = new (nothrow) char[utf8Size]; - if (utf8Out == nullptr) - return nullptr; -#ifdef NDEBUG - encode.utf16ToUtf8(data, dataSize + 1, isBigEndian, true, utf8Out); -#else - size_t utf8Len = encode.utf16ToUtf8(data, dataSize + 1, isBigEndian, true, utf8Out); - assert(utf8Len == utf8Size); -#endif - assert(utf8Size == strlen(utf8Out) + 1); - return utf8Out; -} - -#endif // ASTYLE_LIB - -//----------------------------------------------------------------------------- -// ASOptions class -// used by both console and library builds -//----------------------------------------------------------------------------- - -#ifdef ASTYLE_LIB -ASOptions::ASOptions(ASFormatter& formatterArg) - : formatter(formatterArg) -{ } -#else -ASOptions::ASOptions(ASFormatter& formatterArg, ASConsole& consoleArg) - : formatter(formatterArg), console(consoleArg) -{ } -#endif - -/** - * parse the options vector - * optionsVector can be either a fileOptionsVector (option file), - * a projectOptionsVector (project option file), - * or an optionsVector (command line) - * - * @return true if no errors, false if errors - */ -bool ASOptions::parseOptions(vector& optionsVector, const string& errorInfo) -{ - vector::iterator option; - string arg; - string subArg; - optionErrors.clear(); - - for (option = optionsVector.begin(); option != optionsVector.end(); ++option) - { - arg = *option; - - if (arg.compare(0, 2, "--") == 0) - parseOption(arg.substr(2), errorInfo); - else if (arg[0] == '-') - { - size_t i; - - for (i = 1; i < arg.length(); ++i) - { - if (i > 1 - && isalpha((unsigned char) arg[i]) - && arg[i - 1] != 'x') - { - // parse the previous option in subArg - parseOption(subArg, errorInfo); - subArg = ""; - } - // append the current option to subArg - subArg.append(1, arg[i]); - } - // parse the last option - parseOption(subArg, errorInfo); - subArg = ""; - } - else - { - parseOption(arg, errorInfo); - subArg = ""; - } - } - if (optionErrors.str().length() > 0) - return false; - return true; -} - -void ASOptions::parseOption(const string& arg, const string& errorInfo) -{ - if (isOption(arg, "A1", "style=allman") || isOption(arg, "style=bsd") || isOption(arg, "style=break")) - { - formatter.setFormattingStyle(STYLE_ALLMAN); - } - else if (isOption(arg, "A2", "style=java") || isOption(arg, "style=attach")) - { - formatter.setFormattingStyle(STYLE_JAVA); - } - else if (isOption(arg, "A3", "style=k&r") || isOption(arg, "style=kr") || isOption(arg, "style=k/r")) - { - formatter.setFormattingStyle(STYLE_KR); - } - else if (isOption(arg, "A4", "style=stroustrup")) - { - formatter.setFormattingStyle(STYLE_STROUSTRUP); - } - else if (isOption(arg, "A5", "style=whitesmith")) - { - formatter.setFormattingStyle(STYLE_WHITESMITH); - } - else if (isOption(arg, "A15", "style=vtk")) - { - formatter.setFormattingStyle(STYLE_VTK); - } - else if (isOption(arg, "A6", "style=ratliff") || isOption(arg, "style=banner")) - { - formatter.setFormattingStyle(STYLE_RATLIFF); - } - else if (isOption(arg, "A7", "style=gnu")) - { - formatter.setFormattingStyle(STYLE_GNU); - } - else if (isOption(arg, "A8", "style=linux") || isOption(arg, "style=knf")) - { - formatter.setFormattingStyle(STYLE_LINUX); - } - else if (isOption(arg, "A9", "style=horstmann") || isOption(arg, "style=run-in")) - { - formatter.setFormattingStyle(STYLE_HORSTMANN); - } - else if (isOption(arg, "A10", "style=1tbs") || isOption(arg, "style=otbs")) - { - formatter.setFormattingStyle(STYLE_1TBS); - } - else if (isOption(arg, "A14", "style=google")) - { - formatter.setFormattingStyle(STYLE_GOOGLE); - } - else if (isOption(arg, "A16", "style=mozilla")) - { - formatter.setFormattingStyle(STYLE_MOZILLA); - } - else if (isOption(arg, "A17", "style=webkit")) - { - formatter.setFormattingStyle(STYLE_WEBKIT); - } - else if (isOption(arg, "A11", "style=pico")) - { - formatter.setFormattingStyle(STYLE_PICO); - } - else if (isOption(arg, "A12", "style=lisp") || isOption(arg, "style=python")) - { - formatter.setFormattingStyle(STYLE_LISP); - } - // must check for mode=cs before mode=c !!! - else if (isOption(arg, "mode=cs")) - { - formatter.setSharpStyle(); - formatter.setModeManuallySet(true); - } - else if (isOption(arg, "mode=c")) - { - formatter.setCStyle(); - formatter.setModeManuallySet(true); - } - else if (isOption(arg, "mode=java")) - { - formatter.setJavaStyle(); - formatter.setModeManuallySet(true); - } - else if (isParamOption(arg, "t", "indent=tab=")) - { - int spaceNum = 4; - string spaceNumParam = getParam(arg, "t", "indent=tab="); - if (spaceNumParam.length() > 0) - spaceNum = atoi(spaceNumParam.c_str()); - if (spaceNum < 2 || spaceNum > 20) - isOptionError(arg, errorInfo); - else - { - formatter.setTabIndentation(spaceNum, false); - } - } - else if (isOption(arg, "indent=tab")) - { - formatter.setTabIndentation(4); - } - else if (isParamOption(arg, "T", "indent=force-tab=")) - { - int spaceNum = 4; - string spaceNumParam = getParam(arg, "T", "indent=force-tab="); - if (spaceNumParam.length() > 0) - spaceNum = atoi(spaceNumParam.c_str()); - if (spaceNum < 2 || spaceNum > 20) - isOptionError(arg, errorInfo); - else - { - formatter.setTabIndentation(spaceNum, true); - } - } - else if (isOption(arg, "indent=force-tab")) - { - formatter.setTabIndentation(4, true); - } - else if (isParamOption(arg, "xT", "indent=force-tab-x=")) - { - int tabNum = 8; - string tabNumParam = getParam(arg, "xT", "indent=force-tab-x="); - if (tabNumParam.length() > 0) - tabNum = atoi(tabNumParam.c_str()); - if (tabNum < 2 || tabNum > 20) - isOptionError(arg, errorInfo); - else - { - formatter.setForceTabXIndentation(tabNum); - } - } - else if (isOption(arg, "indent=force-tab-x")) - { - formatter.setForceTabXIndentation(8); - } - else if (isParamOption(arg, "s", "indent=spaces=")) - { - int spaceNum = 4; - string spaceNumParam = getParam(arg, "s", "indent=spaces="); - if (spaceNumParam.length() > 0) - spaceNum = atoi(spaceNumParam.c_str()); - if (spaceNum < 2 || spaceNum > 20) - isOptionError(arg, errorInfo); - else - { - formatter.setSpaceIndentation(spaceNum); - } - } - else if (isOption(arg, "indent=spaces")) - { - formatter.setSpaceIndentation(4); - } - else if (isParamOption(arg, "xt", "indent-continuation=")) - { - int contIndent = 1; - string contIndentParam = getParam(arg, "xt", "indent-continuation="); - if (contIndentParam.length() > 0) - contIndent = atoi(contIndentParam.c_str()); - if (contIndent < 0) - isOptionError(arg, errorInfo); - else if (contIndent > 4) - isOptionError(arg, errorInfo); - else - formatter.setContinuationIndentation(contIndent); - } - else if (isParamOption(arg, "m", "min-conditional-indent=")) - { - int minIndent = MINCOND_TWO; - string minIndentParam = getParam(arg, "m", "min-conditional-indent="); - if (minIndentParam.length() > 0) - minIndent = atoi(minIndentParam.c_str()); - if (minIndent >= MINCOND_END) - isOptionError(arg, errorInfo); - else - formatter.setMinConditionalIndentOption(minIndent); - } - else if (isParamOption(arg, "M", "max-continuation-indent=")) - { - int maxIndent = 40; - string maxIndentParam = getParam(arg, "M", "max-continuation-indent="); - if (maxIndentParam.length() > 0) - maxIndent = atoi(maxIndentParam.c_str()); - if (maxIndent < 40) - isOptionError(arg, errorInfo); - else if (maxIndent > 120) - isOptionError(arg, errorInfo); - else - formatter.setMaxContinuationIndentLength(maxIndent); - } - else if (isOption(arg, "N", "indent-namespaces")) - { - formatter.setNamespaceIndent(true); - } - else if (isOption(arg, "C", "indent-classes")) - { - formatter.setClassIndent(true); - } - else if (isOption(arg, "xG", "indent-modifiers")) - { - formatter.setModifierIndent(true); - } - else if (isOption(arg, "S", "indent-switches")) - { - formatter.setSwitchIndent(true); - } - else if (isOption(arg, "K", "indent-cases")) - { - formatter.setCaseIndent(true); - } - else if (isOption(arg, "xU", "indent-after-parens")) - { - formatter.setAfterParenIndent(true); - } - else if (isOption(arg, "L", "indent-labels")) - { - formatter.setLabelIndent(true); - } - else if (isOption(arg, "xW", "indent-preproc-block")) - { - formatter.setPreprocBlockIndent(true); - } - else if (isOption(arg, "w", "indent-preproc-define")) - { - formatter.setPreprocDefineIndent(true); - } - else if (isOption(arg, "xw", "indent-preproc-cond")) - { - formatter.setPreprocConditionalIndent(true); - } - else if (isOption(arg, "y", "break-closing-braces")) - { - formatter.setBreakClosingHeaderBracesMode(true); - } - else if (isOption(arg, "O", "keep-one-line-blocks")) - { - formatter.setBreakOneLineBlocksMode(false); - } - else if (isOption(arg, "o", "keep-one-line-statements")) - { - formatter.setBreakOneLineStatementsMode(false); - } - else if (isOption(arg, "P", "pad-paren")) - { - formatter.setParensOutsidePaddingMode(true); - formatter.setParensInsidePaddingMode(true); - } - else if (isOption(arg, "d", "pad-paren-out")) - { - formatter.setParensOutsidePaddingMode(true); - } - else if (isOption(arg, "xd", "pad-first-paren-out")) - { - formatter.setParensFirstPaddingMode(true); - } - else if (isOption(arg, "D", "pad-paren-in")) - { - formatter.setParensInsidePaddingMode(true); - } - else if (isOption(arg, "H", "pad-header")) - { - formatter.setParensHeaderPaddingMode(true); - } - else if (isOption(arg, "U", "unpad-paren")) - { - formatter.setParensUnPaddingMode(true); - } - else if (isOption(arg, "p", "pad-oper")) - { - formatter.setOperatorPaddingMode(true); - } - else if (isOption(arg, "xg", "pad-comma")) - { - formatter.setCommaPaddingMode(true); - } - else if (isOption(arg, "xe", "delete-empty-lines")) - { - formatter.setDeleteEmptyLinesMode(true); - } - else if (isOption(arg, "xm", "delete-multiple-empty-lines")) - { - formatter.setDeleteMultipleEmptyLinesMode(true); - } - else if (isOption(arg, "E", "fill-empty-lines")) - { - formatter.setEmptyLineFill(true); - } - else if (isOption(arg, "c", "convert-tabs")) - { - formatter.setTabSpaceConversionMode(true); - } - else if (isOption(arg, "xy", "close-templates")) - { - formatter.setCloseTemplatesMode(true); - } - else if (isOption(arg, "F", "break-blocks=all")) - { - formatter.setBreakBlocksMode(true); - formatter.setBreakClosingHeaderBlocksMode(true); - } - else if (isOption(arg, "f", "break-blocks")) - { - formatter.setBreakBlocksMode(true); - } - else if (isOption(arg, "e", "break-elseifs")) - { - formatter.setBreakElseIfsMode(true); - } - else if (isOption(arg, "xb", "break-one-line-headers")) - { - formatter.setBreakOneLineHeadersMode(true); - } - else if (isOption(arg, "j", "add-braces")) - { - formatter.setAddBracesMode(true); - } - else if (isOption(arg, "J", "add-one-line-braces")) - { - formatter.setAddOneLineBracesMode(true); - } - else if (isOption(arg, "xj", "remove-braces")) - { - formatter.setRemoveBracesMode(true); - } - else if (isOption(arg, "Y", "indent-col1-comments")) - { - formatter.setIndentCol1CommentsMode(true); - } - else if (isOption(arg, "align-pointer=type")) - { - formatter.setPointerAlignment(PTR_ALIGN_TYPE); - } - else if (isOption(arg, "align-pointer=middle")) - { - formatter.setPointerAlignment(PTR_ALIGN_MIDDLE); - } - else if (isOption(arg, "align-pointer=name")) - { - formatter.setPointerAlignment(PTR_ALIGN_NAME); - } - else if (isParamOption(arg, "k")) - { - int align = 0; - string styleParam = getParam(arg, "k"); - if (styleParam.length() > 0) - align = atoi(styleParam.c_str()); - if (align < 1 || align > 3) - isOptionError(arg, errorInfo); - else if (align == 1) - formatter.setPointerAlignment(PTR_ALIGN_TYPE); - else if (align == 2) - formatter.setPointerAlignment(PTR_ALIGN_MIDDLE); - else if (align == 3) - formatter.setPointerAlignment(PTR_ALIGN_NAME); - } - else if (isOption(arg, "align-reference=none")) - { - formatter.setReferenceAlignment(REF_ALIGN_NONE); - } - else if (isOption(arg, "align-reference=type")) - { - formatter.setReferenceAlignment(REF_ALIGN_TYPE); - } - else if (isOption(arg, "align-reference=middle")) - { - formatter.setReferenceAlignment(REF_ALIGN_MIDDLE); - } - else if (isOption(arg, "align-reference=name")) - { - formatter.setReferenceAlignment(REF_ALIGN_NAME); - } - else if (isParamOption(arg, "W")) - { - int align = 0; - string styleParam = getParam(arg, "W"); - if (styleParam.length() > 0) - align = atoi(styleParam.c_str()); - if (align < 0 || align > 3) - isOptionError(arg, errorInfo); - else if (align == 0) - formatter.setReferenceAlignment(REF_ALIGN_NONE); - else if (align == 1) - formatter.setReferenceAlignment(REF_ALIGN_TYPE); - else if (align == 2) - formatter.setReferenceAlignment(REF_ALIGN_MIDDLE); - else if (align == 3) - formatter.setReferenceAlignment(REF_ALIGN_NAME); - } - else if (isParamOption(arg, "max-code-length=")) - { - int maxLength = 50; - string maxLengthParam = getParam(arg, "max-code-length="); - if (maxLengthParam.length() > 0) - maxLength = atoi(maxLengthParam.c_str()); - if (maxLength < 50) - isOptionError(arg, errorInfo); - else if (maxLength > 200) - isOptionError(arg, errorInfo); - else - formatter.setMaxCodeLength(maxLength); - } - else if (isParamOption(arg, "xC")) - { - int maxLength = 50; - string maxLengthParam = getParam(arg, "xC"); - if (maxLengthParam.length() > 0) - maxLength = atoi(maxLengthParam.c_str()); - if (maxLength > 200) - isOptionError(arg, errorInfo); - else - formatter.setMaxCodeLength(maxLength); - } - else if (isOption(arg, "xL", "break-after-logical")) - { - formatter.setBreakAfterMode(true); - } - else if (isOption(arg, "xc", "attach-classes")) - { - formatter.setAttachClass(true); - } - else if (isOption(arg, "xV", "attach-closing-while")) - { - formatter.setAttachClosingWhile(true); - } - else if (isOption(arg, "xk", "attach-extern-c")) - { - formatter.setAttachExternC(true); - } - else if (isOption(arg, "xn", "attach-namespaces")) - { - formatter.setAttachNamespace(true); - } - else if (isOption(arg, "xl", "attach-inlines")) - { - formatter.setAttachInline(true); - } - else if (isOption(arg, "xp", "remove-comment-prefix")) - { - formatter.setStripCommentPrefix(true); - } - else if (isOption(arg, "xB", "break-return-type")) - { - formatter.setBreakReturnType(true); - } - else if (isOption(arg, "xD", "break-return-type-decl")) - { - formatter.setBreakReturnTypeDecl(true); - } - else if (isOption(arg, "xf", "attach-return-type")) - { - formatter.setAttachReturnType(true); - } - else if (isOption(arg, "xh", "attach-return-type-decl")) - { - formatter.setAttachReturnTypeDecl(true); - } - // To avoid compiler limit of blocks nested too deep. - else if (!parseOptionContinued(arg, errorInfo)) - { - isOptionError(arg, errorInfo); - } -} // End of parseOption function - -// Continuation of parseOption. -// To avoid compiler limit of blocks nested too deep. -// Return 'true' if the option was found and processed. -// Return 'false' if the option was not found. -bool ASOptions::parseOptionContinued(const string& arg, const string& errorInfo) -{ - // Objective-C options - if (isOption(arg, "xQ", "pad-method-prefix")) - { - formatter.setMethodPrefixPaddingMode(true); - } - else if (isOption(arg, "xR", "unpad-method-prefix")) - { - formatter.setMethodPrefixUnPaddingMode(true); - } - else if (isOption(arg, "xq", "pad-return-type")) - { - formatter.setReturnTypePaddingMode(true); - } - else if (isOption(arg, "xr", "unpad-return-type")) - { - formatter.setReturnTypeUnPaddingMode(true); - } - else if (isOption(arg, "xS", "pad-param-type")) - { - formatter.setParamTypePaddingMode(true); - } - else if (isOption(arg, "xs", "unpad-param-type")) - { - formatter.setParamTypeUnPaddingMode(true); - } - else if (isOption(arg, "xM", "align-method-colon")) - { - formatter.setAlignMethodColon(true); - } - else if (isOption(arg, "xP0", "pad-method-colon=none")) - { - formatter.setObjCColonPaddingMode(COLON_PAD_NONE); - } - else if (isOption(arg, "xP1", "pad-method-colon=all")) - { - formatter.setObjCColonPaddingMode(COLON_PAD_ALL); - } - else if (isOption(arg, "xP2", "pad-method-colon=after")) - { - formatter.setObjCColonPaddingMode(COLON_PAD_AFTER); - } - else if (isOption(arg, "xP3", "pad-method-colon=before")) - { - formatter.setObjCColonPaddingMode(COLON_PAD_BEFORE); - } - // NOTE: depreciated options - remove when appropriate - // depreciated options //////////////////////////////////////////////////////////////////////// - else if (isOption(arg, "indent-preprocessor")) // depreciated release 2.04 - { - formatter.setPreprocDefineIndent(true); - } - else if (isOption(arg, "style=ansi")) // depreciated release 2.05 - { - formatter.setFormattingStyle(STYLE_ALLMAN); - } - // depreciated in release 3.0 ///////////////////////////////////////////////////////////////// - else if (isOption(arg, "break-closing-brackets")) // depreciated release 3.0 - { - formatter.setBreakClosingHeaderBracketsMode(true); - } - else if (isOption(arg, "add-brackets")) // depreciated release 3.0 - { - formatter.setAddBracketsMode(true); - } - else if (isOption(arg, "add-one-line-brackets")) // depreciated release 3.0 - { - formatter.setAddOneLineBracketsMode(true); - } - else if (isOption(arg, "remove-brackets")) // depreciated release 3.0 - { - formatter.setRemoveBracketsMode(true); - } - else if (isParamOption(arg, "max-instatement-indent=")) // depreciated release 3.0 - { - int maxIndent = 40; - string maxIndentParam = getParam(arg, "max-instatement-indent="); - if (maxIndentParam.length() > 0) - maxIndent = atoi(maxIndentParam.c_str()); - if (maxIndent < 40) - isOptionError(arg, errorInfo); - else if (maxIndent > 120) - isOptionError(arg, errorInfo); - else - formatter.setMaxInStatementIndentLength(maxIndent); - } - // end depreciated options //////////////////////////////////////////////////////////////////// -#ifdef ASTYLE_LIB - // End of options used by GUI ///////////////////////////////////////////////////////////////// - else - { - return false; - } - return true; -#else - // Options used by only console /////////////////////////////////////////////////////////////// - else if (isOption(arg, "n", "suffix=none")) - { - console.setNoBackup(true); - } - else if (isParamOption(arg, "suffix=")) - { - string suffixParam = getParam(arg, "suffix="); - if (suffixParam.length() > 0) - { - console.setOrigSuffix(suffixParam); - } - } - else if (isParamOption(arg, "exclude=")) - { - string suffixParam = getParam(arg, "exclude="); - if (suffixParam.length() > 0) - console.updateExcludeVector(suffixParam); - } - else if (isOption(arg, "r", "R") || isOption(arg, "recursive")) - { - console.setIsRecursive(true); - } - else if (isOption(arg, "dry-run")) - { - console.setIsDryRun(true); - } - else if (isOption(arg, "Z", "preserve-date")) - { - console.setPreserveDate(true); - } - else if (isOption(arg, "v", "verbose")) - { - console.setIsVerbose(true); - } - else if (isOption(arg, "Q", "formatted")) - { - console.setIsFormattedOnly(true); - } - else if (isOption(arg, "q", "quiet")) - { - console.setIsQuiet(true); - } - else if (isOption(arg, "i", "ignore-exclude-errors")) - { - console.setIgnoreExcludeErrors(true); - } - else if (isOption(arg, "xi", "ignore-exclude-errors-x")) - { - console.setIgnoreExcludeErrorsAndDisplay(true); - } - else if (isOption(arg, "X", "errors-to-stdout")) - { - console.setErrorStream(&cout); - } - else if (isOption(arg, "lineend=windows")) - { - formatter.setLineEndFormat(LINEEND_WINDOWS); - } - else if (isOption(arg, "lineend=linux")) - { - formatter.setLineEndFormat(LINEEND_LINUX); - } - else if (isOption(arg, "lineend=macold")) - { - formatter.setLineEndFormat(LINEEND_MACOLD); - } - else if (isParamOption(arg, "z")) - { - int lineendType = 0; - string lineendParam = getParam(arg, "z"); - if (lineendParam.length() > 0) - lineendType = atoi(lineendParam.c_str()); - if (lineendType < 1 || lineendType > 3) - isOptionError(arg, errorInfo); - else if (lineendType == 1) - formatter.setLineEndFormat(LINEEND_WINDOWS); - else if (lineendType == 2) - formatter.setLineEndFormat(LINEEND_LINUX); - else if (lineendType == 3) - formatter.setLineEndFormat(LINEEND_MACOLD); - } - else - { - return false; - } - return true; -#endif -} // End of parseOptionContinued function - -// Parse options from the option file. -void ASOptions::importOptions(stringstream& in, vector& optionsVector) -{ - char ch; - bool isInQuote = false; - char quoteChar = ' '; - string currentToken; - - while (in) - { - currentToken = ""; - do - { - in.get(ch); - if (in.eof()) - break; - // treat '#' as line comments - if (ch == '#') - while (in) - { - in.get(ch); - if (ch == '\n' || ch == '\r') - break; - } - - // break options on new-lines, tabs, commas, or spaces - // remove quotes from output - if (in.eof() || ch == '\n' || ch == '\r' || ch == '\t' || ch == ',') - break; - if (ch == ' ' && !isInQuote) - break; - if (ch == quoteChar && isInQuote) - break; - if (ch == '"' || ch == '\'') - { - isInQuote = true; - quoteChar = ch; - continue; - } - currentToken.append(1, ch); - } - while (in); - - if (currentToken.length() != 0) - optionsVector.emplace_back(currentToken); - isInQuote = false; - } -} - -string ASOptions::getOptionErrors() const -{ - return optionErrors.str(); -} - -string ASOptions::getParam(const string& arg, const char* op) -{ - return arg.substr(strlen(op)); -} - -string ASOptions::getParam(const string& arg, const char* op1, const char* op2) -{ - return isParamOption(arg, op1) ? getParam(arg, op1) : getParam(arg, op2); -} - -bool ASOptions::isOption(const string& arg, const char* op) -{ - return arg == op; -} - -bool ASOptions::isOption(const string& arg, const char* op1, const char* op2) -{ - return (isOption(arg, op1) || isOption(arg, op2)); -} - -void ASOptions::isOptionError(const string& arg, const string& errorInfo) -{ - if (optionErrors.str().length() == 0) - optionErrors << errorInfo << endl; // need main error message - optionErrors << "\t" << arg << endl; -} - -bool ASOptions::isParamOption(const string& arg, const char* option) -{ - bool retVal = arg.compare(0, strlen(option), option) == 0; - // if comparing for short option, 2nd char of arg must be numeric - if (retVal && strlen(option) == 1 && arg.length() > 1) - if (!isdigit((unsigned char) arg[1])) - retVal = false; - return retVal; -} - -bool ASOptions::isParamOption(const string& arg, const char* option1, const char* option2) -{ - return isParamOption(arg, option1) || isParamOption(arg, option2); -} - -//---------------------------------------------------------------------------- -// ASEncoding class -//---------------------------------------------------------------------------- - -// Return true if an int is big endian. -bool ASEncoding::getBigEndian() const -{ - char16_t word = 0x0001; - char* byte = reinterpret_cast(&word); - return (byte[0] ? false : true); -} - -// Swap the two low order bytes of a 16 bit integer value. -int ASEncoding::swap16bit(int value) const -{ - return (((value & 0xff) << 8) | ((value & 0xff00) >> 8)); -} - -// Return the length of a utf-16 C string. -// The length is in number of char16_t. -size_t ASEncoding::utf16len(const utf16* utf16In) const -{ - size_t length = 0; - while (*utf16In++ != '\0') - length++; - return length; -} - -// Adapted from SciTE UniConversion.cxx. -// Copyright 1998-2001 by Neil Hodgson -// Modified for Artistic Style by Jim Pattee. -// Compute the length of an output utf-8 file given a utf-16 file. -// Input inLen is the size in BYTES (not wchar_t). -size_t ASEncoding::utf8LengthFromUtf16(const char* utf16In, size_t inLen, bool isBigEndian) const -{ - size_t len = 0; - size_t wcharLen = (inLen / 2) + (inLen % 2); - const char16_t* uptr = reinterpret_cast(utf16In); - for (size_t i = 0; i < wcharLen;) - { - size_t uch = isBigEndian ? swap16bit(uptr[i]) : uptr[i]; - if (uch < 0x80) - len++; - else if (uch < 0x800) - len += 2; - else if ((uch >= SURROGATE_LEAD_FIRST) && (uch <= SURROGATE_LEAD_LAST)) - { - len += 4; - i++; - } - else - len += 3; - i++; - } - return len; -} - -// Adapted from SciTE Utf8_16.cxx. -// Copyright (C) 2002 Scott Kirkwood. -// Modified for Artistic Style by Jim Pattee. -// Convert a utf-8 file to utf-16. -size_t ASEncoding::utf8ToUtf16(char* utf8In, size_t inLen, bool isBigEndian, char* utf16Out) const -{ - int nCur = 0; - ubyte* pRead = reinterpret_cast(utf8In); - utf16* pCur = reinterpret_cast(utf16Out); - const ubyte* pEnd = pRead + inLen; - const utf16* pCurStart = pCur; - eState state = eStart; - - // the BOM will automatically be converted to utf-16 - while (pRead < pEnd) - { - switch (state) - { - case eStart: - if ((0xF0 & *pRead) == 0xF0) - { - nCur = (0x7 & *pRead) << 18; - state = eSecondOf4Bytes; - } - else if ((0xE0 & *pRead) == 0xE0) - { - nCur = (~0xE0 & *pRead) << 12; - state = ePenultimate; - } - else if ((0xC0 & *pRead) == 0xC0) - { - nCur = (~0xC0 & *pRead) << 6; - state = eFinal; - } - else - { - nCur = *pRead; - state = eStart; - } - break; - case eSecondOf4Bytes: - nCur |= (0x3F & *pRead) << 12; - state = ePenultimate; - break; - case ePenultimate: - nCur |= (0x3F & *pRead) << 6; - state = eFinal; - break; - case eFinal: - nCur |= (0x3F & *pRead); - state = eStart; - break; - // no default case is needed - } - ++pRead; - - if (state == eStart) - { - int codePoint = nCur; - if (codePoint >= SURROGATE_FIRST_VALUE) - { - codePoint -= SURROGATE_FIRST_VALUE; - int lead = (codePoint >> 10) + SURROGATE_LEAD_FIRST; - *pCur++ = static_cast(isBigEndian ? swap16bit(lead) : lead); - int trail = (codePoint & 0x3ff) + SURROGATE_TRAIL_FIRST; - *pCur++ = static_cast(isBigEndian ? swap16bit(trail) : trail); - } - else - *pCur++ = static_cast(isBigEndian ? swap16bit(codePoint) : codePoint); - } - } - // return value is the output length in BYTES (not wchar_t) - return (pCur - pCurStart) * 2; -} - -// Adapted from SciTE UniConversion.cxx. -// Copyright 1998-2001 by Neil Hodgson -// Modified for Artistic Style by Jim Pattee. -// Compute the length of an output utf-16 file given a utf-8 file. -// Return value is the size in BYTES (not wchar_t). -size_t ASEncoding::utf16LengthFromUtf8(const char* utf8In, size_t len) const -{ - size_t ulen = 0; - size_t charLen; - for (size_t i = 0; i < len;) - { - unsigned char ch = static_cast(utf8In[i]); - if (ch < 0x80) - charLen = 1; - else if (ch < 0x80 + 0x40 + 0x20) - charLen = 2; - else if (ch < 0x80 + 0x40 + 0x20 + 0x10) - charLen = 3; - else - { - charLen = 4; - ulen++; - } - i += charLen; - ulen++; - } - // return value is the length in bytes (not wchar_t) - return ulen * 2; -} - -// Adapted from SciTE Utf8_16.cxx. -// Copyright (C) 2002 Scott Kirkwood. -// Modified for Artistic Style by Jim Pattee. -// Convert a utf-16 file to utf-8. -size_t ASEncoding::utf16ToUtf8(char* utf16In, size_t inLen, bool isBigEndian, - bool firstBlock, char* utf8Out) const -{ - int nCur16 = 0; - int nCur = 0; - ubyte* pRead = reinterpret_cast(utf16In); - ubyte* pCur = reinterpret_cast(utf8Out); - const ubyte* pEnd = pRead + inLen; - const ubyte* pCurStart = pCur; - static eState state = eStart; // state is retained for subsequent blocks - if (firstBlock) - state = eStart; - - // the BOM will automatically be converted to utf-8 - while (pRead < pEnd) - { - switch (state) - { - case eStart: - if (pRead >= pEnd) - { - ++pRead; - break; - } - if (isBigEndian) - { - nCur16 = static_cast(*pRead++ << 8); - nCur16 |= static_cast(*pRead); - } - else - { - nCur16 = *pRead++; - nCur16 |= static_cast(*pRead << 8); - } - if (nCur16 >= SURROGATE_LEAD_FIRST && nCur16 <= SURROGATE_LEAD_LAST) - { - ++pRead; - int trail; - if (isBigEndian) - { - trail = static_cast(*pRead++ << 8); - trail |= static_cast(*pRead); - } - else - { - trail = *pRead++; - trail |= static_cast(*pRead << 8); - } - nCur16 = (((nCur16 & 0x3ff) << 10) | (trail & 0x3ff)) + SURROGATE_FIRST_VALUE; - } - ++pRead; - - if (nCur16 < 0x80) - { - nCur = static_cast(nCur16 & 0xFF); - state = eStart; - } - else if (nCur16 < 0x800) - { - nCur = static_cast(0xC0 | (nCur16 >> 6)); - state = eFinal; - } - else if (nCur16 < SURROGATE_FIRST_VALUE) - { - nCur = static_cast(0xE0 | (nCur16 >> 12)); - state = ePenultimate; - } - else - { - nCur = static_cast(0xF0 | (nCur16 >> 18)); - state = eSecondOf4Bytes; - } - break; - case eSecondOf4Bytes: - nCur = static_cast(0x80 | ((nCur16 >> 12) & 0x3F)); - state = ePenultimate; - break; - case ePenultimate: - nCur = static_cast(0x80 | ((nCur16 >> 6) & 0x3F)); - state = eFinal; - break; - case eFinal: - nCur = static_cast(0x80 | (nCur16 & 0x3F)); - state = eStart; - break; - // no default case is needed - } - *pCur++ = static_cast(nCur); - } - return pCur - pCurStart; -} - -//---------------------------------------------------------------------------- - -} // namespace astyle - -//---------------------------------------------------------------------------- - -using namespace astyle; - -//---------------------------------------------------------------------------- -// ASTYLE_JNI functions for Java library builds -//---------------------------------------------------------------------------- - -#ifdef ASTYLE_JNI - -// called by a java program to get the version number -// the function name is constructed from method names in the calling java program -extern "C" EXPORT -jstring STDCALL Java_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass) -{ - return env->NewStringUTF(g_version); -} - -// called by a java program to format the source code -// the function name is constructed from method names in the calling java program -extern "C" EXPORT -jstring STDCALL Java_AStyleInterface_AStyleMain(JNIEnv* env, - jobject obj, - jstring textInJava, - jstring optionsJava) -{ - g_env = env; // make object available globally - g_obj = obj; // make object available globally - - jstring textErr = env->NewStringUTF(""); // zero length text returned if an error occurs - - // get the method ID - jclass cls = env->GetObjectClass(obj); - g_mid = env->GetMethodID(cls, "ErrorHandler", "(ILjava/lang/String;)V"); - if (g_mid == nullptr) - { - cout << "Cannot find java method ErrorHandler" << endl; - return textErr; - } - - // convert jstring to char* - const char* textIn = env->GetStringUTFChars(textInJava, nullptr); - const char* options = env->GetStringUTFChars(optionsJava, nullptr); - - // call the C++ formatting function - char* textOut = AStyleMain(textIn, options, javaErrorHandler, javaMemoryAlloc); - // if an error message occurred it was displayed by errorHandler - if (textOut == nullptr) - return textErr; - - // release memory - jstring textOutJava = env->NewStringUTF(textOut); - delete[] textOut; - env->ReleaseStringUTFChars(textInJava, textIn); - env->ReleaseStringUTFChars(optionsJava, options); - - return textOutJava; -} - -// Call the Java error handler -void STDCALL javaErrorHandler(int errorNumber, const char* errorMessage) -{ - jstring errorMessageJava = g_env->NewStringUTF(errorMessage); - g_env->CallVoidMethod(g_obj, g_mid, errorNumber, errorMessageJava); -} - -// Allocate memory for the formatted text -char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded) -{ - // error condition is checked after return from AStyleMain - char* buffer = new (nothrow) char[memoryNeeded]; - return buffer; -} - -#endif // ASTYLE_JNI - -//---------------------------------------------------------------------------- -// ASTYLE_LIB functions for library builds -//---------------------------------------------------------------------------- - -#ifdef ASTYLE_LIB - -//---------------------------------------------------------------------------- -// ASTYLE_LIB entry point for AStyleMainUtf16 library builds -//---------------------------------------------------------------------------- -/* -* IMPORTANT Visual C DLL linker for WIN32 must have the additional options: -* /EXPORT:AStyleMain=_AStyleMain@16 -* /EXPORT:AStyleMainUtf16=_AStyleMainUtf16@16 -* /EXPORT:AStyleGetVersion=_AStyleGetVersion@0 -* No /EXPORT is required for x64 -*/ -extern "C" EXPORT char16_t* STDCALL AStyleMainUtf16(const char16_t* pSourceIn, // the source to be formatted - const char16_t* pOptions, // AStyle options - fpError fpErrorHandler, // error handler function - fpAlloc fpMemoryAlloc) // memory allocation function -{ - if (fpErrorHandler == nullptr) // cannot display a message if no error handler - return nullptr; - - if (pSourceIn == nullptr) - { - fpErrorHandler(101, "No pointer to source input."); - return nullptr; - } - if (pOptions == nullptr) - { - fpErrorHandler(102, "No pointer to AStyle options."); - return nullptr; - } - if (fpMemoryAlloc == nullptr) - { - fpErrorHandler(103, "No pointer to memory allocation function."); - return nullptr; - } -#ifndef _WIN32 - // check size of char16_t on Linux - int sizeCheck = 2; - if (sizeof(char16_t) != sizeCheck) - { - fpErrorHandler(104, "char16_t is not the correct size."); - return nullptr; - } -#endif - - ASLibrary library; - char16_t* utf16Out = library.formatUtf16(pSourceIn, pOptions, fpErrorHandler, fpMemoryAlloc); - return utf16Out; -} - -//---------------------------------------------------------------------------- -// ASTYLE_LIB entry point for library builds -//---------------------------------------------------------------------------- -/* - * IMPORTANT Visual C DLL linker for WIN32 must have the additional options: - * /EXPORT:AStyleMain=_AStyleMain@16 - * /EXPORT:AStyleMainUtf16=_AStyleMainUtf16@16 - * /EXPORT:AStyleGetVersion=_AStyleGetVersion@0 - * No /EXPORT is required for x64 - */ -extern "C" EXPORT char* STDCALL AStyleMain(const char* pSourceIn, // the source to be formatted - const char* pOptions, // AStyle options - fpError fpErrorHandler, // error handler function - fpAlloc fpMemoryAlloc) // memory allocation function -{ - if (fpErrorHandler == nullptr) // cannot display a message if no error handler - return nullptr; - - if (pSourceIn == nullptr) - { - fpErrorHandler(101, "No pointer to source input."); - return nullptr; - } - if (pOptions == nullptr) - { - fpErrorHandler(102, "No pointer to AStyle options."); - return nullptr; - } - if (fpMemoryAlloc == nullptr) - { - fpErrorHandler(103, "No pointer to memory allocation function."); - return nullptr; - } - - ASFormatter formatter; - ASOptions options(formatter); - - vector optionsVector; - stringstream opt(pOptions); - - options.importOptions(opt, optionsVector); - - bool ok = options.parseOptions(optionsVector, "Invalid Artistic Style options:"); - if (!ok) - fpErrorHandler(130, options.getOptionErrors().c_str()); - - stringstream in(pSourceIn); - ASStreamIterator streamIterator(&in); - ostringstream out; - formatter.init(&streamIterator); - - while (formatter.hasMoreLines()) - { - out << formatter.nextLine(); - if (formatter.hasMoreLines()) - out << streamIterator.getOutputEOL(); - else - { - // this can happen if the file if missing a closing brace and break-blocks is requested - if (formatter.getIsLineReady()) - { - out << streamIterator.getOutputEOL(); - out << formatter.nextLine(); - } - } - } - - size_t textSizeOut = out.str().length(); - char* pTextOut = fpMemoryAlloc((long) textSizeOut + 1); // call memory allocation function - if (pTextOut == nullptr) - { - fpErrorHandler(120, "Allocation failure on output."); - return nullptr; - } - - strcpy(pTextOut, out.str().c_str()); -#ifndef NDEBUG - // The checksum is an assert in the console build and ASFormatter. - // This error returns the incorrectly formatted file to the editor. - // This is done to allow the file to be saved for debugging purposes. - if (formatter.getChecksumDiff() != 0) - fpErrorHandler(220, - "Checksum error.\n" - "The incorrectly formatted file will be returned for debugging."); -#endif - return pTextOut; -} - -extern "C" EXPORT const char* STDCALL AStyleGetVersion(void) -{ - return g_version; -} - -// ASTYLECON_LIB is defined to exclude "main" from the test programs -#elif !defined(ASTYLECON_LIB) - -//---------------------------------------------------------------------------- -// main function for ASConsole build -//---------------------------------------------------------------------------- - -int main(int argc, char** argv) -{ - // create objects - ASFormatter formatter; - unique_ptr console(new ASConsole(formatter)); - - // process command line and option files - // build the vectors fileNameVector, optionsVector, and fileOptionsVector - vector argvOptions; - argvOptions = console->getArgvOptions(argc, argv); - console->processOptions(argvOptions); - - // if no files have been given, use cin for input and cout for output - if (!console->fileNameVectorIsEmpty()) - console->processFiles(); - else - console->formatCinToCout(); - - return EXIT_SUCCESS; -} - -#endif // ASTYLE_LIB diff --git a/tools/astyle/astyle_main.h b/tools/astyle/astyle_main.h deleted file mode 100644 index c62e385e..00000000 --- a/tools/astyle/astyle_main.h +++ /dev/null @@ -1,429 +0,0 @@ -// astyle_main.h -// Copyright (c) 2018 by Jim Pattee . -// 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 -#include - -#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 - #include -#else - #include - #include -#endif // end compiler checks - -#ifdef ASTYLE_JNI - #include - #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 -class ASStreamIterator : public ASSourceIterator -{ -public: - bool checkForEmptyLine; - -public: // function declarations - explicit ASStreamIterator(T* in); - ~ASStreamIterator() override; - bool getLineEndChange(int lineEndFormat) const; - int getStreamLength() const override; - string nextLine(bool emptyLineWasDeleted) override; - string peekNextLine() override; - void peekReset() override; - void saveLastInputLine(); - streamoff tellg() override; - -private: - T* inStream; // pointer to the input stream - string buffer; // current input line - string prevBuffer; // previous input line - string outputEOL; // next output end of line char - int eolWindows; // number of Windows line endings, CRLF - int eolLinux; // number of Linux line endings, LF - int eolMacOld; // number of old Mac line endings. CR - streamoff streamLength; // length of the input file stream - streamoff peekStart; // starting position for peekNextLine - bool prevLineDeleted; // the previous input line was deleted - -public: // inline functions - bool compareToInputBuffer(const string& nextLine_) const - { return (nextLine_ == prevBuffer); } - const string& getOutputEOL() const { return outputEOL; } - 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 - string getOptionErrors() const; - void importOptions(stringstream& in, vector& optionsVector); - bool parseOptions(vector& optionsVector, const string& errorInfo); - -private: - // variables - ASFormatter& formatter; - stringstream optionErrors; // option error messages -#ifndef ASTYLE_LIB - ASConsole& console; // DO NOT USE for ASTYLE_LIB -#endif - - // functions - string getParam(const string& arg, const char* op); - string getParam(const string& arg, const char* op1, const char* op2); - bool isOption(const string& arg, const char* op); - bool isOption(const string& arg, const char* op1, const char* op2); - void isOptionError(const string& arg, const string& errorInfo); - bool isParamOption(const string& arg, const char* option); - bool isParamOption(const string& arg, const char* option1, const char* option2); - void parseOption(const string& arg, const string& errorInfo); - bool parseOptionContinued(const string& arg, const string& errorInfo); -}; - -#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 - ostream* errorStream; // direct error messages to cerr or 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 - int filesFormatted; // number of files formatted - int filesUnchanged; // number of files unchanged - bool lineEndsMixed; // output has mixed line ends - int linesOut; // number of output lines - - string outputEOL; // current line end - string prevEOL; // previous line end - string astyleExePath; // absolute executable path and name from argv[0] - string optionFileName; // file path and name of the options file - string origSuffix; // suffix= option - string projectOptionFileName; // file path and name of the project options file - string stdPathIn; // path to input from stdin= - string stdPathOut; // path to output from stdout= - string targetDirectory; // path to the directory being processed - string targetFilename; // file name being processed - - vector excludeVector; // exclude from wildcard hits - vector excludeHitsVector; // exclude flags for error reporting - vector fileNameVector; // file paths and names from the command line - vector optionsVector; // options from the command line - vector projectOptionsVector;// project options from the project options file - vector fileOptionsVector; // options from the options file - vector fileName; // files to be processed including path - -public: // functions - explicit ASConsole(ASFormatter& formatterArg); - ASConsole(const ASConsole&) = delete; - ASConsole& operator=(ASConsole const&) = delete; - void convertLineEnds(ostringstream& out, int lineEnd); - FileEncoding detectEncoding(const char* data, size_t dataSize) const; - void error() const; - void error(const char* why, const char* what) const; - void formatCinToCout(); - vector getArgvOptions(int argc, char** argv); - bool fileExists(const char* file) const; - bool fileNameVectorIsEmpty() const; - 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; - string getLanguageID() const; - string getNumberFormat(int num, size_t lcid = 0) const; - string getNumberFormat(int num, const char* groupingArg, const char* separator) const; - string getOptionFileName() const; - string getOrigSuffix() const; - string getProjectOptionFileName() const; - string getStdPathIn() const; - string getStdPathOut() const; - void getTargetFilenames(string& targetFilename_, vector& targetFilenameVector) const; - void processFiles(); - void processOptions(const vector& argvOptions); - void setBypassBrowserOpen(bool state); - void setErrorStream(ostream* errStreamPtr); - void setIgnoreExcludeErrors(bool state); - void setIgnoreExcludeErrorsAndDisplay(bool state); - void setIsDryRun(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 string& name); - void setOrigSuffix(const string& suffix); - void setPreserveDate(bool state); - void setProjectOptionFileName(const string& optfilepath); - void setStdPathIn(const string& path); - void setStdPathOut(const string& path); - void standardizePath(string& path, bool removeBeginningSeparator = false) const; - bool stringEndsWith(const string& str, const string& suffix) const; - void updateExcludeVector(const string& suffixParam); - vector getExcludeVector() const; - vector getExcludeHitsVector() const; - vector getFileNameVector() const; - vector getOptionsVector() const; - vector getProjectOptionsVector() const; - vector getFileOptionsVector() const; - vector getFileName() const; - -private: // functions - void correctMixedLineEnds(ostringstream& out); - void formatFile(const string& fileName_); - string getParentDirectory(const string& absPath) const; - string findProjectOptionFilePath(const string& fileName_) const; - string getCurrentDirectory(const string& fileName_) const; - void getFileNames(const string& directory, const vector& wildcards); - void getFilePaths(const string& filePath); - string getFullPathName(const string& relativePath) const; - string getHtmlInstallPrefix() const; - string getParam(const string& arg, const char* op); - bool isHomeOrInvalidAbsPath(const string& absPath) const; - void initializeOutputEOL(LineEndFormat lineEndFormat); - bool isOption(const string& arg, const char* op); - bool isOption(const string& arg, const char* a, const char* b); - bool isParamOption(const string& arg, const char* option); - bool isPathExclued(const string& subPath); - void launchDefaultBrowser(const char* filePathIn = nullptr) const; - void printHelp() const; - void printMsg(const char* msg, const string& data) const; - void printSeparatingLine() const; - void printVerboseHeader() const; - void printVerboseStats(clock_t startTime) const; - FileEncoding readFile(const string& fileName_, 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 setOutputEOL(LineEndFormat lineEndFormat, const string& currentEOL); - void sleep(int seconds) const; - int waitForRemove(const char* newFileName) const; - int wildcmp(const char* wild, const char* data) const; - void writeFile(const string& fileName_, FileEncoding encoding, 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); -#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 diff --git a/tools/astyle/xmake.lua b/tools/astyle/xmake.lua deleted file mode 100644 index 35f19d5a..00000000 --- a/tools/astyle/xmake.lua +++ /dev/null @@ -1,20 +0,0 @@ -target("astyle") - set_kind("binary") - - add_options("mingw-static") - - if is_os("windows") then - add_links("shell32") - end - - add_files( - "ASBeautifier.cpp", - "ASEnhancer.cpp", - "ASFormatter.cpp", - "ASLocalizer.cpp", - "ASResource.cpp", - "astyle_main.cpp") - - if is_xdg() then - on_install(install_libexec) - end