diff --git a/.astyle.options b/.astyle.options new file mode 100644 index 0000000000000000000000000000000000000000..0a17526e3b244fb1a78380cd1479dc95b40fad54 --- /dev/null +++ b/.astyle.options @@ -0,0 +1 @@ +-n --indent=spaces=2 --keep-one-line-statements --keep-one-line-blocks diff --git a/.travis.yml b/.travis.yml index 55d22a7758ae1ba3444acd968c65790c500bd2de..298ddb7bddcdfd5dbf9bd20d014ebea5877b7a20 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ matrix: - os: linux dist: trusty sudo: required - env: CPPCHECK=yes CPPCHECK_VERSION=1.77 + env: CPPCHECK=yes CPPCHECK_VERSION=1.78 # then check with different optimization flags - os: linux dist: trusty @@ -104,22 +104,16 @@ install: # I do it only when LD_LIBRARY_PATH is non blank, since otherwise clang gives problems - if test -n "$LD_LIBRARY_PATH" ; then PLUMED_LDFLAGS="-Wl,-rpath,$LD_LIBRARY_PATH" ; fi # macports related stuff - - if test -n "$PLUMED_MACPORTS" ; then export COLUMNS=80 ; fi -# install macports from source: -# - if test -n "$PLUMED_MACPORTS" ; then wget https://distfiles.macports.org/MacPorts/MacPorts-2.3.4.tar.bz2 && tar xvfj MacPorts-2.3.4.tar.bz2 ; fi -# - if test -n "$PLUMED_MACPORTS" ; then cd MacPorts-2.3.4 && ./configure && sudo make install && cd - && sudo rm -fr MacPorts-2.3.4 ; fi -# install macports from binary (faster): - - if test -n "$PLUMED_MACPORTS" ; then OSX_VERSION="$(sw_vers -productVersion | sed 's/\.[^\.]*$//')" ; fi - - MACPORTS_PKG=MacPorts-2.4.1-10.11-ElCapitan.pkg - - if test "$OSX_VERSION" == 10.12 ; then MACPORTS_PKG=MacPorts-2.4.1-10.12-Sierra.pkg ; fi - - echo "$MACPORTS_PKG" - - if test -n "$PLUMED_MACPORTS" ; then wget https://distfiles.macports.org/MacPorts/$MACPORTS_PKG ; fi - - if test -n "$PLUMED_MACPORTS" ; then sudo installer -pkg $MACPORTS_PKG -target / ; fi - - if test -n "$PLUMED_MACPORTS" ; then export PATH=/opt/local/bin:$PATH ; fi - - if test -n "$PLUMED_MACPORTS" ; then sudo port -N -v selfupdate ; fi - - if test -n "$PLUMED_MACPORTS" ; then make macports ; fi - - if test -n "$PLUMED_MACPORTS" ; then ./.travis/config.macports.sh ; fi - +# configure macports + - if test -n "$PLUMED_MACPORTS" ; then + export COLUMNS=80 ; + wget https://raw.githubusercontent.com/GiovanniBussi/macports-ci/master/macports-ci ; + chmod +x ./macports-ci ; + ./macports-ci install ; + PATH="/opt/local/bin:$PATH" ; + make macports ; + ./macports-ci localports macports ; + fi script: # make sure all modules are enabled - CONFIG_FLAGS="$CONFIG_FLAGS --enable-modules=all" diff --git a/.travis/config.macports.sh b/.travis/config.macports.sh deleted file mode 100755 index b5cb3db113e931c65912ea1afdf1f5387006a244..0000000000000000000000000000000000000000 --- a/.travis/config.macports.sh +++ /dev/null @@ -1,16 +0,0 @@ -#! /bin/bash - -set -e -set -x - -cd macports - -cp /opt/local/etc/macports/sources.conf $$ -awk -v repo="file://$PWD" '{if($NF=="[default]") print repo; print}' $$ > $$.new -sudo mv -f $$.new /opt/local/etc/macports/sources.conf -echo "** NEW SOURCES" -cat /opt/local/etc/macports/sources.conf -echo "** END NEW SOURCES" -rm -f $$ -portindex - diff --git a/CHANGES/v2.3.txt b/CHANGES/v2.3.txt index 68d20fde5e0977f1b757d899d8503c818e070a5c..b8b36e4341ce2396cd0183370797b6cd2175b8ed 100644 --- a/CHANGES/v2.3.txt +++ b/CHANGES/v2.3.txt @@ -151,8 +151,14 @@ See branch \branch{v2.3} on git repository. with a package manager such as MacPorts. - Resolved problem with nan in \ref SMAC with SPECIESA and SPECIESB involving molecules that are the same - PDB reader is now able to read files with dos newlines (see \issue{223}). -- fix a bug in \ref CS2BACKBONE (v2.3.1) related to ring currents of HIS and TRP +- Fixed bug in \ref CS2BACKBONE (v2.3.1) related to ring currents of HIS and TRP - Fixed bug in if condition in \ref PCAVARS so that you can run with only one eigenvector defined in input +- Fixed bug with timers in \ref sum_hills \issue{194}. +- Fixed bug when using \ref MOVINGRESTRAINT with periodic variables such as \ref TORSION \issue{225}. +- Fixed bug in \ref HBONDS that used to apear when you used DONORNS and ACCEPTORS with same numbers of atoms +- Fixed bug in \ref DISTANCES that appears when using BETWEEN and link cells. +- Prevented users from causing segfaults by storing derivatives without LOWMEM flag. In these caess PLUMED crashes with meaningful errors. +- Fixed bug in \ref HISTOGRAM that causes nans when using KERNEL=DISCRETE option For developers: - plumedcheck validation has been made stricter. All the checks are now described in the developer manual. diff --git a/Makefile b/Makefile index 47ea922b1b57cd2496f5e75e2de1e5c522cb0e70..c7302fac59995188dcb9fc73a64754a16822d888 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,12 @@ endif SRCDIRS := src test -SUBDIRS := $(SRCDIRS) user-doc developer-doc regtest macports vim +SUBDIRS := $(SRCDIRS) user-doc developer-doc regtest macports vim astyle SUBDIRSCLEAN:=$(addsuffix .clean,$(SUBDIRS)) -.PHONY: all lib clean $(SRCDIRS) doc docclean check cppcheck distclean all_plus_docs macports codecheck plumedcheck +.PHONY: all lib clean $(SRCDIRS) doc docclean check cppcheck distclean all_plus_docs macports codecheck plumedcheck astyle # if machine dependent configuration has been found: ifdef GCCDEP @@ -111,5 +111,8 @@ stamp-h: sourceme.sh.in Makefile.conf.in config.status config.status: configure ./config.status --recheck +astyle: + $(MAKE) -C astyle + $(MAKE) -C src astyle diff --git a/astyle/.gitignore b/astyle/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..dbd60edda5c57a80c41481b0e4f5f3814c86e079 --- /dev/null +++ b/astyle/.gitignore @@ -0,0 +1 @@ +astyle diff --git a/astyle/LICENSE.md b/astyle/LICENSE.md new file mode 100755 index 0000000000000000000000000000000000000000..cb356f6404ddafeae5d2b87faf0c0ca837b4a9bc --- /dev/null +++ b/astyle/LICENSE.md @@ -0,0 +1,21 @@ +### MIT License + +Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/astyle/Makefile b/astyle/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cb01f9b336759eba1757fd0c936eb908f302fbc4 --- /dev/null +++ b/astyle/Makefile @@ -0,0 +1,9 @@ +.PHONY: astyle + +astyle: + $(MAKE) -C build/gcc + ln -fs build/gcc/bin/astyle . + +clean: + $(MAKE) -C build/gcc clean + rm -f astyle diff --git a/astyle/README.md b/astyle/README.md new file mode 100755 index 0000000000000000000000000000000000000000..98d8a6c776f6e841d7adf44c45cea359bb10650c --- /dev/null +++ b/astyle/README.md @@ -0,0 +1,9 @@ +Instructions for using Artistic Style are included in the *doc* directory. + +The file **install.html** contains instructions for compiling and +installing Artistic Style. + +The file **astyle.html**' contains information on using Artistic Style. + +The files **news.html** and **notes.html** contain information on changes +made to the various releases. diff --git a/astyle/build/cb-clang/Clang AStyle A.cbp b/astyle/build/cb-clang/Clang AStyle A.cbp new file mode 100755 index 0000000000000000000000000000000000000000..c1eedbc977f7ceb8f2d49c8a7475e36b61fa75b5 --- /dev/null +++ b/astyle/build/cb-clang/Clang AStyle A.cbp @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Clang AStyle A" /> + <Option pch_mode="2" /> + <Option compiler="clang" /> + <Build> + <Target title="Debug"> + <Option output="bin/astyled" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="objA/Debug/" /> + <Option type="2" /> + <Option compiler="clang" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + </Target> + <Target title="Release"> + <Option output="bin/astyle" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="objA/Release/" /> + <Option type="2" /> + <Option compiler="clang" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-O3" /> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + <Add option="-DNDEBUG" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <envvars /> + <debugger /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-clang/Clang AStyle All.workspace b/astyle/build/cb-clang/Clang AStyle All.workspace new file mode 100755 index 0000000000000000000000000000000000000000..1d53e7d08212231d758bd763e094d9843e61c252 --- /dev/null +++ b/astyle/build/cb-clang/Clang AStyle All.workspace @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_workspace_file> + <Workspace title="Clang (GCC) AStyle All"> + <Project filename="Clang AStyle.cbp" /> + <Project filename="Clang AStyle So.cbp" /> + <Project filename="Clang AStyle Java.cbp" /> + <Project filename="Clang AStyle A.cbp" /> + </Workspace> +</CodeBlocks_workspace_file> diff --git a/astyle/build/cb-clang/Clang AStyle Java.cbp b/astyle/build/cb-clang/Clang AStyle Java.cbp new file mode 100755 index 0000000000000000000000000000000000000000..a8029e29f20c3168c3b57f8922c7010c3479d34c --- /dev/null +++ b/astyle/build/cb-clang/Clang AStyle Java.cbp @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Clang AStyle Java" /> + <Option pch_mode="2" /> + <Option compiler="clang" /> + <Build> + <Target title="Debug"> + <Option output="bin/libastylejd.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objJ/Debug/" /> + <Option type="3" /> + <Option compiler="clang" /> + <Compiler> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-reserved-id-macro" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + <Add option="-Wno-unknown-warning-option" /> + <Add option="-DASTYLE_JNI" /> + <Add directory="/usr/lib/jvm/default-java/include" /> + <Add directory="/usr/lib/jvm/default-java/include/linux" /> + </Compiler> + <Linker> + <Add option="-Wl,-soname,libastylejd.so.$(MAJORVER)" /> + </Linker> + </Target> + <Target title="Release"> + <Option output="bin/libastylej.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objJ/Release/" /> + <Option type="3" /> + <Option compiler="clang" /> + <Compiler> + <Add option="-O3" /> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-reserved-id-macro" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + <Add option="-Wno-unknown-warning-option" /> + <Add option="-DASTYLE_JNI" /> + <Add option="-DNDEBUG" /> + <Add directory="/usr/lib/jvm/default-java/include" /> + <Add directory="/usr/lib/jvm/default-java/include/linux" /> + </Compiler> + <Linker> + <Add option="-s" /> + <Add option="-Wl,-soname,libastylej.so.$(MAJORVER)" /> + </Linker> + </Target> + <Environment> + <Variable name="MAJORVER" value="3" /> + <Variable name="MINORVER" value="0" /> + <Variable name="PATCHVER" value="0" /> + <Variable name="SOLIBVER" value="$(MAJORVER).$(MINORVER).$(PATCHVER)" /> + </Environment> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-clang/Clang AStyle So.cbp b/astyle/build/cb-clang/Clang AStyle So.cbp new file mode 100755 index 0000000000000000000000000000000000000000..3c8f7c5945e522348d5d028892953c89161c9d4f --- /dev/null +++ b/astyle/build/cb-clang/Clang AStyle So.cbp @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Clang AStyle So" /> + <Option pch_mode="2" /> + <Option compiler="clang" /> + <Build> + <Target title="Debug"> + <Option output="bin/libastyled.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objSo/Debug/" /> + <Option type="3" /> + <Option compiler="clang" /> + <Compiler> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + <Linker> + <Add option="-Wl,-soname,libastyled.so.$(MAJORVER)" /> + </Linker> + </Target> + <Target title="Release"> + <Option output="bin/libastyle.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objSo/Release/" /> + <Option type="3" /> + <Option compiler="clang" /> + <Compiler> + <Add option="-O3" /> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + <Add option="-DASTYLE_LIB" /> + <Add option="-DDNDEBUG" /> + </Compiler> + <Linker> + <Add option="-s" /> + <Add option="-Wl,-soname,libastyle.so.$(MAJORVER)" /> + </Linker> + </Target> + <Environment> + <Variable name="MAJORVER" value="3" /> + <Variable name="MINORVER" value="0" /> + <Variable name="PATCHVER" value="0" /> + <Variable name="SOLIBVER" value="$(MAJORVER).$(MINORVER).$(PATCHVER)" /> + </Environment> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-clang/Clang AStyle.cbp b/astyle/build/cb-clang/Clang AStyle.cbp new file mode 100755 index 0000000000000000000000000000000000000000..44d31b73f924de49f6fad9dbe3a3c3fab22b2f04 --- /dev/null +++ b/astyle/build/cb-clang/Clang AStyle.cbp @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Clang AStyle" /> + <Option pch_mode="2" /> + <Option compiler="clang" /> + <Build> + <Target title="Debug"> + <Option output="bin/astyled" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Debug/" /> + <Option type="1" /> + <Option compiler="clang" /> + <Option parameters=''"$HOME/Projects/AStyleDev/test-c/*.cpp"' '"$HOME/Projects/AStyleDev/test-c/*.h"' -vR' /> + <Option projectLinkerOptionsRelation="0" /> + <Option projectIncludeDirsRelation="0" /> + <Option projectResourceIncludeDirsRelation="0" /> + <Option projectLibDirsRelation="0" /> + <Compiler> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-disabled-macro-expansion" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-format-nonliteral" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-noreturn" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + </Compiler> + <MakeCommands> + <Build command="" /> + <CompileFile command="" /> + <Clean command="" /> + <DistClean command="" /> + <AskRebuildNeeded command="" /> + <SilentBuild command=" > $(CMD_NULL)" /> + </MakeCommands> + </Target> + <Target title="Release"> + <Option output="bin/astyle" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release/" /> + <Option type="1" /> + <Option compiler="clang" /> + <Option parameters=''"/home/jimp/Projects/AStyleDev/test-c/*.cpp"' -v --exclude=exclude.cpp ' /> + <Compiler> + <Add option="-O3" /> + <Add option="-Weverything" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-Wextra" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-Wno-c++98-compat" /> + <Add option="-Wno-disabled-macro-expansion" /> + <Add option="-Wno-exit-time-destructors" /> + <Add option="-Wno-format-nonliteral" /> + <Add option="-Wno-global-constructors" /> + <Add option="-Wno-missing-noreturn" /> + <Add option="-Wno-missing-variable-declarations" /> + <Add option="-Wno-old-style-cast" /> + <Add option="-Wno-padded" /> + <Add option="-Wno-shorten-64-to-32" /> + <Add option="-Wno-sign-conversion" /> + <Add option="-Wno-weak-vtables" /> + <Add option="-DNDEBUG" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASLocalizer.cpp" /> + <Unit filename="../../src/ASLocalizer.h" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-gcc/Gcc AStyle A.cbp b/astyle/build/cb-gcc/Gcc AStyle A.cbp new file mode 100755 index 0000000000000000000000000000000000000000..c2ea1dd98dcf005a594af4dfc9c5d058a653eadc --- /dev/null +++ b/astyle/build/cb-gcc/Gcc AStyle A.cbp @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Gcc AStyle A" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <Build> + <Target title="Debug"> + <Option output="bin/astyled" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="objA/Debug/" /> + <Option type="2" /> + <Option compiler="gcc" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + </Target> + <Target title="Release"> + <Option output="bin/astyle" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="objA/Release/" /> + <Option type="2" /> + <Option compiler="gcc" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-O3" /> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-DNDEBUG" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <envvars /> + <debugger /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-gcc/Gcc AStyle All.workspace b/astyle/build/cb-gcc/Gcc AStyle All.workspace new file mode 100755 index 0000000000000000000000000000000000000000..465d61ebec0ede0ee4be760a2977e2724a51b415 --- /dev/null +++ b/astyle/build/cb-gcc/Gcc AStyle All.workspace @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_workspace_file> + <Workspace title="Gcc AStyle All"> + <Project filename="Gcc AStyle.cbp" /> + <Project filename="Gcc AStyle So.cbp" /> + <Project filename="Gcc AStyle Java.cbp" /> + <Project filename="Gcc AStyle A.cbp" /> + </Workspace> +</CodeBlocks_workspace_file> diff --git a/astyle/build/cb-gcc/Gcc AStyle Java.cbp b/astyle/build/cb-gcc/Gcc AStyle Java.cbp new file mode 100755 index 0000000000000000000000000000000000000000..544b1bb413ebc2ab878fd1b7c09939e1eefcf2bf --- /dev/null +++ b/astyle/build/cb-gcc/Gcc AStyle Java.cbp @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Gcc AStyle Java" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <Build> + <Target title="Debug"> + <Option output="bin/libastylejd.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objJ/Debug/" /> + <Option type="3" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-DASTYLE_JNI" /> + <Add directory="/usr/lib/jvm/default-java/include" /> + <Add directory="/usr/lib/jvm/default-java/include/linux" /> + </Compiler> + <Linker> + <Add option="-Wl,-soname,libastylejd.so.$(MAJORVER)" /> + </Linker> + </Target> + <Target title="Release"> + <Option output="bin/libastylej.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objJ/Release/" /> + <Option type="3" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-O3" /> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-DASTYLE_JNI" /> + <Add option="-DNDEBUG" /> + <Add directory="/usr/lib/jvm/default-java/include" /> + <Add directory="/usr/lib/jvm/default-java/include/linux" /> + </Compiler> + <Linker> + <Add option="-s" /> + <Add option="-Wl,-soname,libastylej.so.$(MAJORVER)" /> + </Linker> + </Target> + <Environment> + <Variable name="MAJORVER" value="3" /> + <Variable name="MINORVER" value="0" /> + <Variable name="PATCHVER" value="0" /> + <Variable name="SOLIBVER" value="$(MAJORVER).$(MINORVER).$(PATCHVER)" /> + </Environment> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-gcc/Gcc AStyle So.cbp b/astyle/build/cb-gcc/Gcc AStyle So.cbp new file mode 100755 index 0000000000000000000000000000000000000000..36479823cfa726e90545bf55a3217080f0f79e58 --- /dev/null +++ b/astyle/build/cb-gcc/Gcc AStyle So.cbp @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Gcc AStyle So" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <Build> + <Target title="Debug"> + <Option output="bin/libastyled.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objSo/Debug/" /> + <Option type="3" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + <Linker> + <Add option="-Wl,-soname,libastyled.so.$(MAJORVER)" /> + </Linker> + </Target> + <Target title="Release"> + <Option output="bin/libastyle.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objSo/Release/" /> + <Option type="3" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-O3" /> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-DASTYLE_LIB" /> + <Add option="-DNDEBUG" /> + </Compiler> + <Linker> + <Add option="-s" /> + <Add option="-Wl,-soname,libastyle.so.$(MAJORVER)" /> + </Linker> + </Target> + <Environment> + <Variable name="MAJORVER" value="3" /> + <Variable name="MINORVER" value="0" /> + <Variable name="PATCHVER" value="0" /> + <Variable name="SOLIBVER" value="$(MAJORVER).$(MINORVER).$(PATCHVER)" /> + </Environment> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-gcc/Gcc AStyle.cbp b/astyle/build/cb-gcc/Gcc AStyle.cbp new file mode 100755 index 0000000000000000000000000000000000000000..cf6eae6fcf44b6bff0e5a300654372fc990c5856 --- /dev/null +++ b/astyle/build/cb-gcc/Gcc AStyle.cbp @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Gcc AStyle" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <Build> + <Target title="Debug"> + <Option output="bin/astyled" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Debug/" /> + <Option type="1" /> + <Option compiler="gcc" /> + <Option parameters=''"/home/jimp/Projects/AStyleDev/test-data/*.cpp"' -v' /> + <Compiler> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-g" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + </Compiler> + </Target> + <Target title="Release"> + <Option output="bin/astyle" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release/" /> + <Option type="1" /> + <Option compiler="gcc" /> + <Option parameters=''"/home/jimp/Projects/AStyleDev/test-data/*.cpp"' -v' /> + <Compiler> + <Add option="-O3" /> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-fno-rtti" /> + <Add option="-fno-exceptions" /> + <Add option="-DNDEBUG" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + <Target title="Lint"> + <Option output="bin/astylel" prefix_auto="0" extension_auto="0" /> + <Option object_output="obj/Lint/" /> + <Option type="1" /> + <Option compiler="gcc" /> + <Compiler> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wmain" /> + <Add option="-pedantic" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-Wint-to-pointer-cast" /> + <Add option="-Woverloaded-virtual" /> + <Add option="-Wwrite-strings" /> + <Add option="-Wno-switch-default" /> + <Add option="-fno-exceptions" /> + <Add option="-fno-rtti" /> + </Compiler> + </Target> + <Target title="Coverage"> + <Option output="bin/astylec" prefix_auto="0" extension_auto="1" /> + <Option object_output="obj/Coverage" /> + <Option type="1" /> + <Option compiler="gcc" /> + <Option parameters="-atOPR /home/jimp/Projects/TestData/CodeBlocks/*.cpp /home/jimp/Projects/TestData/CodeBlocks/*.h" /> + <Compiler> + <Add option="-Wnon-virtual-dtor" /> + <Add option="-Wshadow" /> + <Add option="-Winit-self" /> + <Add option="-Wredundant-decls" /> + <Add option="-Wcast-align" /> + <Add option="-Wundef" /> + <Add option="-Wfloat-equal" /> + <Add option="-Winline" /> + <Add option="-Wunreachable-code" /> + <Add option="-Wmissing-declarations" /> + <Add option="-Wmissing-include-dirs" /> + <Add option="-Wswitch-enum" /> + <Add option="-Wzero-as-null-pointer-constant" /> + <Add option="-Wmain" /> + <Add option="-Wextra" /> + <Add option="-Wall" /> + <Add option="-std=c++11" /> + <Add option="-pg" /> + <Add option="-g" /> + <Add option="-fprofile-arcs" /> + <Add option="-ftest-coverage" /> + <Add option="-DNDEBUG" /> + </Compiler> + <Linker> + <Add option="-pg" /> + <Add library="gcov" /> + </Linker> + </Target> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASLocalizer.cpp" /> + <Unit filename="../../src/ASLocalizer.h" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-intel/Intel AStyle A.cbp b/astyle/build/cb-intel/Intel AStyle A.cbp new file mode 100755 index 0000000000000000000000000000000000000000..5920416448e1ba200351c64a51b545866585336c --- /dev/null +++ b/astyle/build/cb-intel/Intel AStyle A.cbp @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Intel AStyle A" /> + <Option pch_mode="2" /> + <Option compiler="icc" /> + <Build> + <Target title="Debug"> + <Option output="bin/astyled" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="objA/Debug/" /> + <Option type="2" /> + <Option compiler="icc" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-Wall" /> + <Add option="-g" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + <Add option="-fno-exceptions" /> + <Add option="-std=c++11" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + </Target> + <Target title="Release"> + <Option output="bin/astyle" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="objA/Release/" /> + <Option type="2" /> + <Option compiler="icc" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-O3" /> + <Add option="-Wall" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + <Add option="-fno-exceptions" /> + <Add option="-std=c++11" /> + <Add option="-wd11074,11076" /> + <Add option="-DNDEBUG" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <envvars /> + <debugger /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-intel/Intel AStyle All.workspace b/astyle/build/cb-intel/Intel AStyle All.workspace new file mode 100755 index 0000000000000000000000000000000000000000..15630cd7219bfe3d174067ef47c55c3b94398d3a --- /dev/null +++ b/astyle/build/cb-intel/Intel AStyle All.workspace @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_workspace_file> + <Workspace title="Intel AStyle All"> + <Project filename="Intel AStyle.cbp" /> + <Project filename="Intel AStyle Java.cbp" /> + <Project filename="Intel AStyle So.cbp" /> + <Project filename="Intel AStyle A.cbp" /> + </Workspace> +</CodeBlocks_workspace_file> diff --git a/astyle/build/cb-intel/Intel AStyle Java.cbp b/astyle/build/cb-intel/Intel AStyle Java.cbp new file mode 100755 index 0000000000000000000000000000000000000000..4f1c9a3071effa47a5551610b39dcf40ffe03a69 --- /dev/null +++ b/astyle/build/cb-intel/Intel AStyle Java.cbp @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Intel AStyle Java" /> + <Option pch_mode="2" /> + <Option compiler="icc" /> + <Build> + <Target title="Debug"> + <Option output="bin/libastylejd.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objJ/Debug/" /> + <Option type="3" /> + <Option compiler="icc" /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-Wall" /> + <Add option="-g" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + <Add option="-std=c++11" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-DASTYLE_JNI" /> + <Add directory="/usr/lib/jvm/default-java/include" /> + <Add directory="/usr/lib/jvm/default-java/include/linux" /> + </Compiler> + <Linker> + <Add option="-static-intel" /> + <Add option="-Wl,-soname,libastylejd.so.$(MAJORVER)" /> + <Add option="-wd10237" /> + </Linker> + </Target> + <Target title="Release"> + <Option output="bin/libastylej.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objJ/Release/" /> + <Option type="3" /> + <Option compiler="icc" /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-O3" /> + <Add option="-Wall" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + <Add option="-std=c++11" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-wd11074,11076" /> + <Add option="-DASTYLE_JNI" /> + <Add option="-DNDEBUG" /> + <Add directory="/usr/lib/jvm/default-java/include" /> + <Add directory="/usr/lib/jvm/default-java/include/linux" /> + </Compiler> + <Linker> + <Add option="-s" /> + <Add option="-static-intel" /> + <Add option="-Wl,-soname,libastylej.so.$(MAJORVER)" /> + <Add option="-wd10237" /> + </Linker> + </Target> + <Environment> + <Variable name="MAJORVER" value="3" /> + <Variable name="MINORVER" value="0" /> + <Variable name="PATCHVER" value="0" /> + <Variable name="SOLIBVER" value="$(MAJORVER).$(MINORVER).$(PATCHVER)" /> + </Environment> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-intel/Intel AStyle So.cbp b/astyle/build/cb-intel/Intel AStyle So.cbp new file mode 100755 index 0000000000000000000000000000000000000000..d770bd87b433f746ed254f0728f863dbb9a6b5ff --- /dev/null +++ b/astyle/build/cb-intel/Intel AStyle So.cbp @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Intel AStyle So" /> + <Option pch_mode="2" /> + <Option compiler="icc" /> + <Build> + <Target title="Debug"> + <Option output="bin/libastyled.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objSo/Debug/" /> + <Option type="3" /> + <Option compiler="icc" /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-Wall" /> + <Add option="-g" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-std=c++11" /> + <Add option="-DASTYLE_LIB" /> + </Compiler> + <Linker> + <Add option="-static-intel" /> + <Add option="-Wl,-soname,libastyled.so.$(MAJORVER)" /> + <Add option="-wd10237" /> + </Linker> + </Target> + <Target title="Release"> + <Option output="bin/libastyle.so.$(SOLIBVER)" prefix_auto="0" extension_auto="0" /> + <Option object_output="objSo/Release/" /> + <Option type="3" /> + <Option compiler="icc" /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-O3" /> + <Add option="-Wall" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + <Add option="-fno-exceptions" /> + <Add option="-fPIC" /> + <Add option="-std=c++11" /> + <Add option="-wd11074,11076" /> + <Add option="-DASTYLE_LIB" /> + <Add option="-DDNDEBUG" /> + </Compiler> + <Linker> + <Add option="-s" /> + <Add option="-static-intel" /> + <Add option="-Wl,-soname,libastyle.so.$(MAJORVER)" /> + <Add option="-wd10237" /> + </Linker> + </Target> + <Environment> + <Variable name="MAJORVER" value="3" /> + <Variable name="MINORVER" value="0" /> + <Variable name="PATCHVER" value="0" /> + <Variable name="SOLIBVER" value="$(MAJORVER).$(MINORVER).$(PATCHVER)" /> + </Environment> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/cb-intel/Intel AStyle.cbp b/astyle/build/cb-intel/Intel AStyle.cbp new file mode 100755 index 0000000000000000000000000000000000000000..51154555b8378d66f30710a6649f4d4539bf0de8 --- /dev/null +++ b/astyle/build/cb-intel/Intel AStyle.cbp @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="Intel AStyle" /> + <Option pch_mode="2" /> + <Option compiler="icc" /> + <Build> + <Target title="Debug"> + <Option output="bin/astyled" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Debug/" /> + <Option type="1" /> + <Option compiler="icc" /> + <Option parameters=''"/home/jimp/Projects/AStyleDev/test-c/*.cpp"' -v --exclude=exclude.cpp ' /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-Wall" /> + <Add option="-g" /> + <Add option="-fno-exceptions" /> + <Add option="-std=c++11" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + </Compiler> + </Target> + <Target title="Release"> + <Option output="bin/astyle" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release/" /> + <Option type="1" /> + <Option compiler="icc" /> + <Option parameters=''"/home/jimp/Projects/AStyleDev/test-c/*.cpp"' -v --exclude=exclude.cpp ' /> + <Compiler> + <Add option="-fno-rtti" /> + <Add option="-O3" /> + <Add option="-Wall" /> + <Add option="-fno-exceptions" /> + <Add option="-std=c++11" /> + <Add option="-w3" /> + <Add option="-Wextra" /> + <Add option="-wd11074,11076" /> + <Add option="-DNDEBUG" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + </Build> + <Unit filename="../../src/ASBeautifier.cpp" /> + <Unit filename="../../src/ASEnhancer.cpp" /> + <Unit filename="../../src/ASFormatter.cpp" /> + <Unit filename="../../src/ASLocalizer.cpp" /> + <Unit filename="../../src/ASLocalizer.h" /> + <Unit filename="../../src/ASResource.cpp" /> + <Unit filename="../../src/astyle.h" /> + <Unit filename="../../src/astyle_main.cpp" /> + <Unit filename="../../src/astyle_main.h" /> + <Extensions> + <code_completion /> + <debugger /> + <envvars /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/astyle/build/clang/Makefile b/astyle/build/clang/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..bf14fe53305542f734b203370b4d516f7b2fb220 --- /dev/null +++ b/astyle/build/clang/Makefile @@ -0,0 +1,212 @@ +# Make file for GCC compiler on Linux or compatible OS + +# list of source files for astyle +SRC = astyle_main.cpp \ + ASBeautifier.cpp \ + ASFormatter.cpp \ + ASEnhancer.cpp \ + ASLocalizer.cpp \ + ASResource.cpp + +# list of source files for libraries without ASLocalizer +SRCx = astyle_main.cpp \ + ASBeautifier.cpp \ + ASFormatter.cpp \ + ASEnhancer.cpp \ + ASResource.cpp + +# source directories +vpath %.cpp ../../src +vpath %.h ../../src + +# NOTE for java compiles the environment variable $JAVA_HOME must be set +# example: export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.00 +ifndef JAVA_HOME + JAVA_HOME = /usr/lib/jvm/default-java +endif + +# set prefix if not defined on the command line +ifndef prefix + prefix=/usr +endif +SYSCONF_PATH=$(prefix)/share/doc/astyle + +# define macros +bindir = bin +objdir = obj +ipath=$(prefix)/bin +CBASEFLAGS = -Wall -Wextra -fno-rtti -fno-exceptions -std=c++11 +JAVAINCS = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux +CXX = clang++ +INSTALL=install -o $(USER) -g $(USER) + +# Library's major version number -- Increment in case of incompatible API +# change. +MAJORVER = 3 +# Library's minor version number -- Increment when functionnality is added in a +# backward-compatible manner; reset to 0 when major number changes. +MINORVER = 0 +# Library's patch version number -- Increment in case of backward-compatible +# bug fixes or refactoring; reset to 0 when minor number changes. +PATCHVER = 0 +# Library's full version number. +SOLIBVER = $(MAJORVER).$(MINORVER).$(PATCHVER) + +################################################## + +# define compile options for each build +ifdef CFLAGS + CFLAGSr = -DNDEBUG $(CBASEFLAGS) $(CFLAGS) + CFLAGSd = -g $(CBASEFLAGS) $(CFLAGS) +else + CFLAGSr = -DNDEBUG -O3 $(CBASEFLAGS) + CFLAGSd = -g $(CBASEFLAGS) +endif +CFLAGSs = -DASTYLE_LIB -fPIC $(CFLAGSr) +CFLAGSsd = -DASTYLE_LIB -fPIC $(CFLAGSd) +CFLAGSa = -DASTYLE_LIB $(CFLAGSr) +CFLAGSad = -DASTYLE_LIB $(CFLAGSd) +CFLAGSsj = -DASTYLE_JNI -fPIC $(CFLAGSr) $(JAVAINCS) +CFLAGSsjd = -DASTYLE_JNI -fPIC $(CFLAGSd) $(JAVAINCS) + +# define link options +ifdef LDFLAGS + LDFLAGSr = $(LDFLAGS) + LDFLAGSd = $(LDFLAGS) +else + LDFLAGSr = -s + LDFLAGSd = +endif + +# object files are built from the source list $(SRC) +# a suffix is added for each build +OBJ = $(patsubst %.cpp,$(objdir)/%.o,$(SRC)) +OBJd = $(patsubst %.cpp,$(objdir)/%_d.o,$(SRC)) +OBJs = $(patsubst %.cpp,$(objdir)/%_s.o,$(SRCx)) +OBJsd = $(patsubst %.cpp,$(objdir)/%_sd.o,$(SRCx)) +OBJa = $(patsubst %.cpp,$(objdir)/%_a.o,$(SRCx)) +OBJad = $(patsubst %.cpp,$(objdir)/%_ad.o,$(SRCx)) +OBJsj = $(patsubst %.cpp,$(objdir)/%_sj.o,$(SRCx)) +OBJsjd = $(patsubst %.cpp,$(objdir)/%_sjd.o,$(SRCx)) + +# define object file rule (with the suffix) for each build + +# OBJ +$(objdir)/%.o: %.cpp astyle.h astyle_main.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSr) -c $< -o $@ + +# OBJd +$(objdir)/%_d.o: %.cpp astyle.h astyle_main.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSd) -c $< -o $@ + +# OBJs +$(objdir)/%_s.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSs) -c $< -o $@ + +# OBJsd +$(objdir)/%_sd.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsd) -c $< -o $@ + +# OBJa +$(objdir)/%_a.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSa) -c $< -o $@ + +# OBJad +$(objdir)/%_ad.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSad) -c $< -o $@ + +# OBJsj +$(objdir)/%_sj.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsj) -c $< -o $@ + +# OBJsjd +$(objdir)/%_sjd.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsjd) -c $< -o $@ + +################################################## +# define build dependencies for each command + +release: astyle +astyle: $(OBJ) + @ mkdir -p $(bindir) + $(CXX) $(LDFLAGSr) -o $(bindir)/$@ $^ + @ echo + +debug: astyled +astyled: $(OBJd) + @ mkdir -p $(bindir) + $(CXX) $(LDFLAGSd) -o $(bindir)/$@ $^ + @ echo + +shared: libastyle.so +libastyle.so: $(OBJs) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastyle.so.$(MAJORVER) -o $(bindir)/libastyle.so.$(SOLIBVER) $^ + @ echo + +shareddebug: libastyled.so +libastyled.so: $(OBJsd) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSd) -Wl,-soname,libastyled.so.$(MAJORVER) -o $(bindir)/libastyled.so.$(SOLIBVER) $^ + @ echo + +static: libastyle.a +libastyle.a: $(OBJa) + @ mkdir -p $(bindir) + ar crs $(bindir)/$@ $^ + @ echo + +staticdebug: libastyled.a +libastyled.a: $(OBJad) + @ mkdir -p $(bindir) + ar crs $(bindir)/$@ $^ + @ echo + +java: libastylej.so +libastylej.so: $(OBJsj) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastylej.so.$(MAJORVER) -o $(bindir)/libastylej.so.$(SOLIBVER) $^ + @ echo + +javadebug: libastylejd.so +libastylejd.so: $(OBJsjd) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastylejd.so.$(MAJORVER) -o $(bindir)/libastylejd.so.$(SOLIBVER) $^ + @ echo + +all: release debug shared shareddebug static staticdebug + +javaall: java javadebug + +clean: + rm -f $(objdir)/*.o $(bindir)/*astyle* + +cleanobj: + rm -f $(objdir)/*.o + +install: + $(INSTALL) -m 755 -d $(ipath) + @$(INSTALL) -m 755 $(bindir)/astyle $(ipath) + + @if [ -d $(SYSCONF_PATH)/html ]; then \ + rm -rf $(SYSCONF_PATH)/html; \ + fi + + $(INSTALL) -m 755 -d $(SYSCONF_PATH) + @mkdir -p $(SYSCONF_PATH)/html; + @for files in ../../doc/*.html ../../doc/*.css; \ + do \ + $(INSTALL) -m 644 $$files $(SYSCONF_PATH)/html; \ + done + +uninstall: + rm -f $(ipath)/astyle + rm -rf $(SYSCONF_PATH) diff --git a/astyle/build/gcc/Makefile b/astyle/build/gcc/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..72151f80d3fea8fc5921bbed27069b6ee9df11b4 --- /dev/null +++ b/astyle/build/gcc/Makefile @@ -0,0 +1,212 @@ +# Make file for GCC compiler on Linux or compatible OS + +# list of source files for astyle +SRC = astyle_main.cpp \ + ASBeautifier.cpp \ + ASFormatter.cpp \ + ASEnhancer.cpp \ + ASLocalizer.cpp \ + ASResource.cpp + +# list of source files for libraries without ASLocalizer +SRCx = astyle_main.cpp \ + ASBeautifier.cpp \ + ASFormatter.cpp \ + ASEnhancer.cpp \ + ASResource.cpp + +# source directories +vpath %.cpp ../../src +vpath %.h ../../src + +# NOTE for java compiles the environment variable $JAVA_HOME must be set +# example: export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.00 +ifndef JAVA_HOME + JAVA_HOME = /usr/lib/jvm/default-java +endif + +# set prefix if not defined on the command line +ifndef prefix + prefix=/usr +endif +SYSCONF_PATH=$(prefix)/share/doc/astyle + +# define macros +bindir = bin +objdir = obj +ipath=$(prefix)/bin +CBASEFLAGS = -Wall -Wextra -fno-rtti -fno-exceptions -std=c++11 +JAVAINCS = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux +CXX = g++ +INSTALL=install -o $(USER) -g $(USER) + +# Library's major version number -- Increment in case of incompatible API +# change. +MAJORVER = 3 +# Library's minor version number -- Increment when functionnality is added in a +# backward-compatible manner; reset to 0 when major number changes. +MINORVER = 0 +# Library's patch version number -- Increment in case of backward-compatible +# bug fixes or refactoring; reset to 0 when minor number changes. +PATCHVER = 0 +# Library's full version number. +SOLIBVER = $(MAJORVER).$(MINORVER).$(PATCHVER) + +################################################## + +# define compile options for each build +ifdef CFLAGS + CFLAGSr = -DNDEBUG $(CBASEFLAGS) $(CFLAGS) + CFLAGSd = -g $(CBASEFLAGS) $(CFLAGS) +else + CFLAGSr = -DNDEBUG -O3 $(CBASEFLAGS) + CFLAGSd = -g $(CBASEFLAGS) +endif +CFLAGSs = -DASTYLE_LIB -fPIC $(CFLAGSr) +CFLAGSsd = -DASTYLE_LIB -fPIC $(CFLAGSd) +CFLAGSa = -DASTYLE_LIB $(CFLAGSr) +CFLAGSad = -DASTYLE_LIB $(CFLAGSd) +CFLAGSsj = -DASTYLE_JNI -fPIC $(CFLAGSr) $(JAVAINCS) +CFLAGSsjd = -DASTYLE_JNI -fPIC $(CFLAGSd) $(JAVAINCS) + +# define link options +ifdef LDFLAGS + LDFLAGSr = $(LDFLAGS) + LDFLAGSd = $(LDFLAGS) +else + LDFLAGSr = -s + LDFLAGSd = +endif + +# object files are built from the source list $(SRC) +# a suffix is added for each build +OBJ = $(patsubst %.cpp,$(objdir)/%.o,$(SRC)) +OBJd = $(patsubst %.cpp,$(objdir)/%_d.o,$(SRC)) +OBJs = $(patsubst %.cpp,$(objdir)/%_s.o,$(SRCx)) +OBJsd = $(patsubst %.cpp,$(objdir)/%_sd.o,$(SRCx)) +OBJa = $(patsubst %.cpp,$(objdir)/%_a.o,$(SRCx)) +OBJad = $(patsubst %.cpp,$(objdir)/%_ad.o,$(SRCx)) +OBJsj = $(patsubst %.cpp,$(objdir)/%_sj.o,$(SRCx)) +OBJsjd = $(patsubst %.cpp,$(objdir)/%_sjd.o,$(SRCx)) + +# define object file rule (with the suffix) for each build + +# OBJ +$(objdir)/%.o: %.cpp astyle.h astyle_main.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSr) -c $< -o $@ + +# OBJd +$(objdir)/%_d.o: %.cpp astyle.h astyle_main.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSd) -c $< -o $@ + +# OBJs +$(objdir)/%_s.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSs) -c $< -o $@ + +# OBJsd +$(objdir)/%_sd.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsd) -c $< -o $@ + +# OBJa +$(objdir)/%_a.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSa) -c $< -o $@ + +# OBJad +$(objdir)/%_ad.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSad) -c $< -o $@ + +# OBJsj +$(objdir)/%_sj.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsj) -c $< -o $@ + +# OBJsjd +$(objdir)/%_sjd.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsjd) -c $< -o $@ + +################################################## +# define build dependencies for each command + +release: astyle +astyle: $(OBJ) + @ mkdir -p $(bindir) + $(CXX) $(LDFLAGSr) -o $(bindir)/$@ $^ + @ echo + +debug: astyled +astyled: $(OBJd) + @ mkdir -p $(bindir) + $(CXX) $(LDFLAGSd) -o $(bindir)/$@ $^ + @ echo + +shared: libastyle.so +libastyle.so: $(OBJs) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastyle.so.$(MAJORVER) -o $(bindir)/libastyle.so.$(SOLIBVER) $^ + @ echo + +shareddebug: libastyled.so +libastyled.so: $(OBJsd) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSd) -Wl,-soname,libastyled.so.$(MAJORVER) -o $(bindir)/libastyled.so.$(SOLIBVER) $^ + @ echo + +static: libastyle.a +libastyle.a: $(OBJa) + @ mkdir -p $(bindir) + ar crs $(bindir)/$@ $^ + @ echo + +staticdebug: libastyled.a +libastyled.a: $(OBJad) + @ mkdir -p $(bindir) + ar crs $(bindir)/$@ $^ + @ echo + +java: libastylej.so +libastylej.so: $(OBJsj) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastylej.so.$(MAJORVER) -o $(bindir)/libastylej.so.$(SOLIBVER) $^ + @ echo + +javadebug: libastylejd.so +libastylejd.so: $(OBJsjd) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastylejd.so.$(MAJORVER) -o $(bindir)/libastylejd.so.$(SOLIBVER) $^ + @ echo + +all: release debug shared shareddebug static staticdebug + +javaall: java javadebug + +clean: + rm -f $(objdir)/*.o $(bindir)/*astyle* + +cleanobj: + rm -f $(objdir)/*.o + +install: + $(INSTALL) -m 755 -d $(ipath) + @$(INSTALL) -m 755 $(bindir)/astyle $(ipath) + + @if [ -d $(SYSCONF_PATH)/html ]; then \ + rm -rf $(SYSCONF_PATH)/html; \ + fi + + $(INSTALL) -m 755 -d $(SYSCONF_PATH) + @mkdir -p $(SYSCONF_PATH)/html; + @for files in ../../doc/*.html ../../doc/*.css; \ + do \ + $(INSTALL) -m 644 $$files $(SYSCONF_PATH)/html; \ + done + +uninstall: + rm -f $(ipath)/astyle + rm -rf $(SYSCONF_PATH) diff --git a/astyle/build/intel/Makefile b/astyle/build/intel/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..84eee05c7c3aabdedab3895012e9432feec2ab24 --- /dev/null +++ b/astyle/build/intel/Makefile @@ -0,0 +1,222 @@ +# Make file for Intel compiler on Linux or compatible OS + +# Before running "make" the COMPILER environment variables must be set. +# To set the environment variables "source" the compiler environment script: +# source /opt/intel/bin/compilervars.sh [ ia32 | intel64 ] +# Refer to the install instructions for details. +# If the environment variables are set, INTEL_LICENSE_FILE will be defined. +# NOTE: This does not work if 'sudo' is used, as in 'install' and 'uninstall'. +#ifndef INTEL_LICENSE_FILE +# $(error The compiler environment variables are not set) +#endif + +# list of source files for astyle +SRC = astyle_main.cpp \ + ASBeautifier.cpp \ + ASFormatter.cpp \ + ASEnhancer.cpp \ + ASLocalizer.cpp \ + ASResource.cpp + +# list of source files for libraries without ASLocalizer +SRCx = astyle_main.cpp \ + ASBeautifier.cpp \ + ASFormatter.cpp \ + ASEnhancer.cpp \ + ASResource.cpp + +# source directories +vpath %.cpp ../../src +vpath %.h ../../src + +# NOTE for java compiles the environment variable $JAVA_HOME must be set +# example: export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.00 +ifndef JAVA_HOME + JAVA_HOME = /usr/lib/jvm/default-java +endif + +# set prefix if not defined on the command line +ifndef prefix + prefix=/usr +endif +SYSCONF_PATH=$(prefix)/share/doc/astyle + +# define macros +bindir = bin +objdir = obj +ipath=$(prefix)/bin +CBASEFLAGS = -w3 -Wall -fno-rtti -fno-exceptions -std=c++11 +JAVAINCS = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux +CXX = icpc +INSTALL=install -o $(USER) -g $(USER) + +# Library's major version number -- Increment in case of incompatible API +# change. +MAJORVER = 3 +# Library's minor version number -- Increment when functionnality is added in a +# backward-compatible manner; reset to 0 when major number changes. +MINORVER = 0 +# Library's patch version number -- Increment in case of backward-compatible +# bug fixes or refactoring; reset to 0 when minor number changes. +PATCHVER = 0 +# Library's full version number. +SOLIBVER = $(MAJORVER).$(MINORVER).$(PATCHVER) + +################################################## + +# define compile options for each build +ifdef CFLAGS + CFLAGSr = -DNDEBUG $(CBASEFLAGS) $(CFLAGS) + CFLAGSd = -g $(CBASEFLAGS) $(CFLAGS) +else + CFLAGSr = -DNDEBUG -O3 $(CBASEFLAGS) + CFLAGSd = -g $(CBASEFLAGS) +endif +CFLAGSs = -DASTYLE_LIB -fPIC $(CFLAGSr) +CFLAGSsd = -DASTYLE_LIB -fPIC $(CFLAGSd) +CFLAGSa = -DASTYLE_LIB $(CFLAGSr) +CFLAGSad = -DASTYLE_LIB $(CFLAGSd) +CFLAGSsj = -DASTYLE_JNI -fPIC $(CFLAGSr) $(JAVAINCS) +CFLAGSsjd = -DASTYLE_JNI -fPIC $(CFLAGSd) $(JAVAINCS) + +# define link options +ifdef LDFLAGS + LDFLAGSr = $(LDFLAGS) + LDFLAGSd = $(LDFLAGS) +else + LDFLAGSr = -s + LDFLAGSd = +endif + +# object files are built from the source list $(SRC) +# a suffix is added for each build +OBJ = $(patsubst %.cpp,$(objdir)/%.o,$(SRC)) +OBJd = $(patsubst %.cpp,$(objdir)/%_d.o,$(SRC)) +OBJs = $(patsubst %.cpp,$(objdir)/%_s.o,$(SRCx)) +OBJsd = $(patsubst %.cpp,$(objdir)/%_sd.o,$(SRCx)) +OBJa = $(patsubst %.cpp,$(objdir)/%_a.o,$(SRCx)) +OBJad = $(patsubst %.cpp,$(objdir)/%_ad.o,$(SRCx)) +OBJsj = $(patsubst %.cpp,$(objdir)/%_sj.o,$(SRCx)) +OBJsjd = $(patsubst %.cpp,$(objdir)/%_sjd.o,$(SRCx)) + +# define object file rule (with the suffix) for each build + +# OBJ +$(objdir)/%.o: %.cpp astyle.h astyle_main.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSr) -c $< -o $@ + +# OBJd +$(objdir)/%_d.o: %.cpp astyle.h astyle_main.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSd) -c $< -o $@ + +# OBJs +$(objdir)/%_s.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSs) -c $< -o $@ + +# OBJsd +$(objdir)/%_sd.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsd) -c $< -o $@ + +# OBJa +$(objdir)/%_a.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSa) -c $< -o $@ + +# OBJad +$(objdir)/%_ad.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSad) -c $< -o $@ + +# OBJsj +$(objdir)/%_sj.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsj) -c $< -o $@ + +# OBJsjd +$(objdir)/%_sjd.o: %.cpp astyle.h + @ mkdir -p $(objdir) + $(CXX) $(CFLAGSsjd) -c $< -o $@ + +################################################## +# define build dependencies for each command + +release: astyle +astyle: $(OBJ) + @ mkdir -p $(bindir) + $(CXX) $(LDFLAGSr) -o $(bindir)/$@ $^ + @ echo + +debug: astyled +astyled: $(OBJd) + @ mkdir -p $(bindir) + $(CXX) $(LDFLAGSd) -o $(bindir)/$@ $^ + @ echo + +shared: libastyle.so +libastyle.so: $(OBJs) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastyle.so.$(MAJORVER) -o $(bindir)/libastyle.so.$(SOLIBVER) $^ + @ echo + +shareddebug: libastyled.so +libastyled.so: $(OBJsd) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSd) -Wl,-soname,libastyled.so.$(MAJORVER) -o $(bindir)/libastyled.so.$(SOLIBVER) $^ + @ echo + +static: libastyle.a +libastyle.a: $(OBJa) + @ mkdir -p $(bindir) + ar crs $(bindir)/$@ $^ + @ echo + +staticdebug: libastyled.a +libastyled.a: $(OBJad) + @ mkdir -p $(bindir) + ar crs $(bindir)/$@ $^ + @ echo + +java: libastylej.so +libastylej.so: $(OBJsj) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastylej.so.$(MAJORVER) -o $(bindir)/libastylej.so.$(SOLIBVER) $^ + @ echo + +javadebug: libastylejd.so +libastylejd.so: $(OBJsjd) + @ mkdir -p $(bindir) + $(CXX) -shared $(LDFLAGSr) -Wl,-soname,libastylejd.so.$(MAJORVER) -o $(bindir)/libastylejd.so.$(SOLIBVER) $^ + @ echo + +all: release debug shared shareddebug static staticdebug + +javaall: java javadebug + +clean: + rm -f $(objdir)/*.o $(bindir)/*astyle* + +cleanobj: + rm -f $(objdir)/*.o + +install: + $(INSTALL) -m 755 -d $(ipath) + @$(INSTALL) -m 755 $(bindir)/astyle $(ipath) + + @if [ -d $(SYSCONF_PATH)/html ]; then \ + rm -rf $(SYSCONF_PATH)/html; \ + fi + + $(INSTALL) -m 755 -d $(SYSCONF_PATH) + @mkdir -p $(SYSCONF_PATH)/html; + @for files in ../../doc/*.html ../../doc/*.css; \ + do \ + $(INSTALL) -m 644 $$files $(SYSCONF_PATH)/html; \ + done + +uninstall: + rm -f $(ipath)/astyle + rm -rf $(SYSCONF_PATH) diff --git a/astyle/doc/astyle.html b/astyle/doc/astyle.html new file mode 100755 index 0000000000000000000000000000000000000000..d3b656128d7d21fd0355aa412207f75deb4fd2b5 --- /dev/null +++ b/astyle/doc/astyle.html @@ -0,0 +1,2360 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> + +<head> + <title>Artistic Style</title> + <meta http-equiv="Content-Language" content="en-us" /> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /> + <meta name="description" content="Artistic Style is a source code indenter, source code formatter, and source code beautifier + for the C, C++, C# and Java programming languages." /> + <meta name="keywords" content="artistic style, astyle, source code indenter, source code formatter, source code beautifier" /> + <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" /> + <link href="styles.css" rel="stylesheet" type="text/css" /> + + <!-- the following styles are additions to styles.css --> + + <style type="text/css"> + hr { margin-left: -0.4in; } + /* the following styles are for formatting code samples */ + div.code { background: #D8D8FF; } + /* code */ + p.code { margin-left: 0.3in; } + code { color: navy; } + code.title { font-size: larger; font-weight: bold; } + /* spans */ + span.brace { color: red; } + span.comment { color: dimgray; font-style: italic; } + span.option { color: saddlebrown; font-weight: bold; } + </style> + +</head> + +<body> + + <h1>Artistic Style 3.0</h1> + + <h2> + A Free, Fast, and Small Automatic Formatter<br /> + for C, C++, C++/CLI, Objective‑C, C#, and Java Source Code + </h2> + + <h3 id="Contents">Contents</h3> + + <p class="contents1"> + <a class="contents" href="#_General_Information">General Information</a></p> + <p class="contents1"> + <a class="contents" href="#_Quick_Start">Quick Start</a></p> + <p class="contents1"> + <a class="contents" href="#_Usage">Usage</a></p> + <p class="contents1"> + <a class="contents" href="#_Options">Options</a></p> + <p class="contents1"> + <a class="contents" href="#_Options_File">Options File</a></p> + <p class="contents1"> + <a class="contents" href="#_Disable_Formatting">Disable Formatting</a></p> + <p class="contents1"> + <a class="contents" href="#_Basic_Brace_Styles">Basic Brace Styles</a></p> + <p class="contents1"> + <a class="contents" href="#_Brace_Style_Options">Brace Style Options</a></p> + <p class="contents2"> + <a class="contents" href="#_default_brace_style">default brace style</a> + <a class="contents" href="#_style=allman">style=allman</a> + <a class="contents" href="#_style=java">style=java</a> + <a class="contents" href="#_style=kr">style=kr</a> + <a class="contents" href="#_style=stroustrup">style=stroustrup</a> + <a class="contents" href="#_style=whitesmith">style=whitesmith</a> + <a class="contents" href="#_style=vtk">style=vtk</a> + <a class="contents" href="#_style=banner">style=banner</a> + <a class="contents" href="#_style=gnu">style=gnu</a> + <a class="contents" href="#_style=linux">style=linux</a> + <a class="contents" href="#_style=horstmann">style=horstmann</a> + <a class="contents" href="#_style=1tbs">style=1tbs</a> + <a class="contents" href="#_style=google">style=google</a> + <a class="contents" href="#_style=mozilla">style=mozilla</a> + <a class="contents" href="#_style=pico">style=pico</a> + <a class="contents" href="#_style=lisp">style=lisp</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Tab_Options">Tab Options</a></p> + <p class="contents2"> + <a class="contents" href="#_default_indent">default indent</a> + <a class="contents" href="#_indent=spaces">indent=spaces</a> + <a class="contents" href="#_indent=tab">indent=tab</a> + <a class="contents" href="#_indent=force-tab">indent=force‑tab</a> + <a class="contents" href="#_indent=force-tab-x">--indent=force‑tab‑x</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Brace_Modify_Options">Brace Modify Options</a></p> + <p class="contents2"> + <a class="contents" href="#_attach_namespaces">attach‑namespaces</a> + <a class="contents" href="#_attach_classes">attach‑classes</a> + <a class="contents" href="#_attach_inlines">attach‑inlines</a> + <a class="contents" href="#_attach-extern-c">attach‑extern‑c</a> + <a class="contents" href="#_attach-closing-while">attach‑closing‑while</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Indentation_Options">Indentation Options</a></p> + <p class="contents2"> + <a class="contents" href="#_indent-classes">indent‑classes</a> + <a class="contents" href="#_indent-modifiers">indent‑modifiers</a> + <a class="contents" href="#_indent-switches">indent‑switches</a> + <a class="contents" href="#_indent-cases">indent‑cases</a> + <a class="contents" href="#_indent-namespaces">indent‑namespaces</a> + <a class="contents" href="#_indent-after-parens">indent‑after‑parens</a> + <a class="contents" href="#_indent-continuation">indent‑continuation</a> + <a class="contents" href="#_indent-labels">indent‑labels</a> + <a class="contents" href="#_indent-preproc-block">indent‑preproc‑block</a> + <a class="contents" href="#_indent-preproc-define">indent‑preproc‑define</a> + <a class="contents" href="#_indent-preproc-cond">indent‑preproc‑cond</a> + <a class="contents" href="#_indent-col1-comments">indent‑col1‑comments</a> + <a class="contents" href="#_min-conditional-indent">min‑conditional‑indent</a> + <a class="contents" href="#_max-continuation-indent">max‑continuation‑indent</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Padding_Options">Padding Options</a></p> + <p class="contents2"> + <a class="contents" href="#_break-blocks">break‑blocks</a> + <a class="contents" href="#_break-blocks=all">break‑blocks=all</a> + <a class="contents" href="#_pad-oper">pad‑oper</a> + <a class="contents" href="#_pad-comma">pad‑comma</a> + <a class="contents" href="#_pad-paren">pad‑paren</a> + <a class="contents" href="#_pad-paren-out">pad‑paren‑out</a> + <a class="contents" href="#_pad-first-paren-out">pad‑first‑paren‑out</a> + <a class="contents" href="#_pad-paren-in">pad‑paren‑in</a> + <a class="contents" href="#_pad-header">pad‑header</a> + <a class="contents" href="#_unpad-paren">unpad‑paren</a> + <a class="contents" href="#_delete-empty-lines">delete‑empty‑lines</a> + <a class="contents" href="#_fill-empty-lines">fill‑empty‑lines</a> + <a class="contents" href="#_align-pointer">align‑pointer</a> + <a class="contents" href="#_align-reference">align‑reference</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Formatting_Options">Formatting Options</a></p> + <p class="contents2"> + <a class="contents" href="#_break-closing-braces">break‑closing‑braces</a> + <a class="contents" href="#_break-elseifs">break‑elseifs</a> + <a class="contents" href="#_break-one-line-headers">break‑one‑line‑headers</a> + <a class="contents" href="#_add-braces">add‑braces</a> + <a class="contents" href="#_add-one-line-braces">add‑one‑line‑braces</a> + <a class="contents" href="#_remove-braces">remove‑braces</a> + <a class="contents" href="#_keep-one-line-blocks">keep‑one‑line‑blocks</a> + <a class="contents" href="#_keep-one-line-statements">keep‑one‑line‑statements</a> + <a class="contents" href="#_convert-tabs">convert‑tabs</a> + <a class="contents" href="#_close-templates">close‑templates</a> + <a class="contents" href="#_remove-comment-prefix">remove‑comment‑prefix</a> + <a class="contents" href="#_max-code-length">max‑code‑length</a> + <a class="contents" href="#_max-code-length">break‑after‑logical</a> + <a class="contents" href="#_mode">mode</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Objective_C_Options">Objective‑C Options</a></p> + <p class="contents2"> + <a class="contents" href="#_pad-method-prefix">pad‑method‑prefix</a> + <a class="contents" href="#_unpad-method-prefix">unpad‑method‑prefix</a> + <a class="contents" href="#_pad-return-type">pad‑return‑type</a> + <a class="contents" href="#_unpad-return-type">unpad‑return‑type</a> + <a class="contents" href="#_pad-param-type">pad‑param‑type</a> + <a class="contents" href="#_unpad-param-type">unpad‑param‑type</a> + <a class="contents" href="#_align-method-colon">align‑method‑colon</a> + <a class="contents" href="#_pad-method-colon">pad‑method‑colon</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Other_Options">Other Options</a> </p> + <p class="contents2"> + <a class="contents" href="#_suffix">suffix</a> <a class="contents" href="#_suffix=none">suffix=none</a> + <a class="contents" href="#_recursive">recursive</a> + <a class="contents" href="#_dry-run">dry-run</a> + <a class="contents" href="#_exclude">exclude</a> + <a class="contents" href="#_ignore-exclude-errors">ignore‑exclude‑errors</a> + <a class="contents" href="#_ignore-exclude-errors-x">ignore‑exclude‑errors‑x</a> + <a class="contents" href="#_errors-to-stdout">errors‑to‑stdout</a> + <a class="contents" href="#_preserve-date">preserve‑date</a> + <a class="contents" href="#_verbose">verbose</a> + <a class="contents" href="#_formatted">formatted</a> + <a class="contents" href="#_quiet">quiet</a> + <a class="contents" href="#_lineend">lineend</a> + </p> + <p class="contents1"> + <a class="contents" href="#_Command_Line_Only">Command Line Only</a></p> + <p class="contents2"> + <a class="contents" href="#_options=">options</a> + <a class="contents" href="#_options=none">options=none</a> + <a class="contents" href="#_ascii">ascii</a> + <a class="contents" href="#_version">version</a> + <a class="contents" href="#_help">help</a> + <a class="contents" href="#_html">html</a> + <a class="contents" href="#_html=">html=</a> + <a class="contents" href="#_stdin=">stdin=</a> + <a class="contents" href="#_stdout=">stdout=</a> + </p> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * General Information< * * * * * * * * * * * * --> + + <h3 id="_General_Information">General Information</h3> + + <h4>Line Endings</h4> + + <p> + Line endings in the formatted file will be the same as the input file. If there are mixed line endings the most + frequent occurrence will be used. There is also an option to specify or change the line endings.</p> + + <h4>File Type</h4> + + <p> + Artistic Style will determine the file type from the file extension. The extension ".java" indicates a Java file, + and ".cs" indicates a C# file. Everything else is a C type file (C, C++, C++/CLI, or Objective-C). If you are + using a non-standard file extension for Java or C#, use one of the --mode= options.</p> + + <h4>Wildcards and Recursion</h4> + + <p> + Artistic Style can process directories recursively. Wildcards (such as "*.cpp" or "*.c??") are processed internally. + If a shell is used, it should pass the wildcards to Artistic Style instead of resolving them first. For Linux + use double quotes around paths whose file name contains wildcards. For Windows use double quotes around paths + whose file name contains spaces. The <a href="#_recursive">recursive</a> option in the + <a href="#_Other_Options">Other Options</a> section contains information on recursive processing.</p> + + <h4>File Names</h4> + + <p> + When a file is formatted, the newly indented file retains the original file name. A copy of the original file + is created with an <strong>.orig</strong> appended to the original file name. (This can be set to + a different string by the option --suffix=, or suppressed altogether by the options -n + or --suffix=none). Thus, after indenting <em>SourceFile.cpp</em> the indented file will + be named <em>SourceFile.cpp</em>, while the original pre-indented file will be renamed to + <em>SourceFile.cpp.orig</em>.</p> + + <h4>Internationalization</h4> + + <p> + Artistic Style has been internationalized to process files and directories in any language.</p> + <p> + It has also been translated into several languages. The translation to use is determined by the User Locale + for Windows and the LANG environment variable for other systems. The translation will be done automatically from + these settings. If no translation is available it will default to English. There is an "ascii" option to use English + instead of the system language.</p> + <p> + The source code for the translations is at the end of ASLocalizer.cpp in the form of an English‑Translation + pair. If you make corrections to a translation, send the source as a bug report and it will be included in the + next release.</p> + <p> + To add a new language, add a new translation class to ASLocalizer.h. Add the English‑Translation pair to + the constructor in ASLocalizer.cpp. Update the WinLangCode array and add the language code to the function setTranslationClass(). + The ASLocalizer.cpp program contains comments that give web pages for obtaining the LCIDs and language codes. + Send the source code as a bug report and it will be included in the next release.</p> + + <h4>Other Considerations</h4> + + <p> + The names of special characters used in programming vary by region. The terminology used by Artistic Style, + followed by other common names, is<strong>:</strong></p> + <blockquote> + braces or curly braces { } ‑ also called brackets, or curly brackets.<br /> + parens or round brackets ( ) ‑ also called parentheses, brackets, circle brackets, or soft brackets.<br /> + square brackets [ ] ‑ also called block parens, brackets, closed brackets, or hard brackets.<br /> + angle brackets < > ‑ also called brackets, pointy brackets, triangular brackets, diamond brackets, tuples, + or chevrons. + </blockquote> + <p> + Visual Studio, and possibly other development environments, has extensions that will align assignment operators + across multiple lines. There is an extension named "Code alignment" that will align the code on other items as + well. Formatting with these options and extensions can be used with Artistic Style. The space padding will be + maintained and the alignment will be preserved. </p> + <p> + Artistic Style can format standard class library statements such as Open GL, wxWidgets, Qt, and MFC.</p> + <p> + Embedded assembler language is formatted correctly. This includes extended assembly and Microsoft specific assembler + lines and blocks.</p> + <p> + Artistic Style can format embedded SQL statements. The SQL formatting will be maintained as long as the standard + hanging indent format is used. If the "exec sql" statement is indented more than the following statements, the + SQL will be aligned in a single column.</p> + <p> + Unicode files encoded as UTF‑16, both big and little endian, will be formatted. The files must begin with + a byte order mark (BOM) to be recognized. Files encoded as UTF‑32 will be rejected. Some compilers do not + support these encodings. These files can be converted to UTF‑8 encoding with the program "iconv". There + are Linux and Windows versions available (the Windows version does not seem to work for all encodings). Visual + Studio can convert the files from the "File > Advanced Save Options" menu. There are other development environments + and text editors, such as SciTE, that can convert files to UTF‑8.</p> + <p> + Embedded statements that are multiple-line and are NOT in a C-type format, such as Python, are usually mal-formatted + (a C-type format has blocks enclosed by braces and statements terminated by a semi-colon). Macros that define + functions may cause the following code to be mal-formatted because the macro is missing the braces and semi-colons + from the definition. If you have source code with these types of statements, exclude them with the + <a href="#_exclude">exclude=####</a> option described in the <a href="#_Other_Options">Other Options</a> + section.</p> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * * Quick Start * * * * * * * * * * * * * * --> + + <h3 id="_Quick_Start">Quick Start</h3> + + <p> + If you have never used Artistic Style, there are several of ways to get started.</p> + <p> + One is to run it with no options at all. This will use the <a href="#_default_brace_style">default brace + style</a>, 4 spaces per indent, and no formatting changes. This will break the braces for one + line blocks and will break one line statements. To change this, use the option <a href="#_keep-one-line-blocks">keep-one-line-blocks</a> + and/or <a href="#_keep-one-line-statements">keep-one-line-statements</a> described in the + <a href="#_Formatting_Options">Formatting Options</a> section.</p> + <p> + Another way is to use one of the brace styles described in the <a href="#_Brace_Style_Options">Brace Style + Options</a> section. Select one with a brace formatting style you like. If no indentation option is set, + the default option of 4 spaces will be used. These options also break one line blocks and one line statements + as described above.</p> + <p> + A third option is to use an options file from the "file" folder. If there is a coding style you want + to duplicate, input the appropriate <a href="#_Options_File">options file</a>. Use the option + <a href="#_options=">options=####</a> to specify the file to use. It must contain a path for the file, including + the file name. </p> + <p> + Once you are familiar with the options you can customize the format to your personal preference.</p> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * * * Usage * * * * * * * * * * * * * * * --> + + <h3 id="_Usage">Usage</h3> + + <p> + Artistic style is a console program that receives information from the command line.</p> + <div class="code"> + <p class="code"> + Command line format:</p> + <pre>astyle [OPTIONS] <em>SourceFile1 SourceFile2 SourceFile3 [ . . . ]</em></pre> + </div> + <p> + The square brackets [ ] indicate that more than one option or more than one file name can be entered. They are + NOT actually included in the command. For the options format refer to the following Options section.</p> + <div class="code"> + <p class="code"> + Example to format a single file:</p> + <pre>astyle --style=allman /home/user/project/foo.cpp +</pre> + <p class="code"> + Example to format all .cpp and .h files recursively:</p> + <pre>astyle --style=allman --recursive /home/user/project/*.cpp /home/user/project/*.h +</pre> + </div> + <p> + The < and > characters may be used to redirect the files into standard input (stdin) and out of standard output + (stdout) - don't forget them! With this option only one file at a time can be formatted. Wildcards are not + recognized, there are no console messages, and a backup is not created. On Windows the output will always have + Windows line ends. The options "stdin=" and "stdout=" can be used instead of redirection.</p> + <div class="code"> + <p class="code"> + Example of redirection option to format a single file and change the name:</p> + <pre>astyle --style=allman < <em>OriginalSourceFile</em> > <em>BeautifiedSourceFile</em> +</pre> + </div> + <div class="code"> + <p class="code"> + The redirection option may be used to display the formatted file without updating:</p> + <pre>astyle --style=allman < <em>OriginalSourceFile</em> | less +</pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * * * Options * * * * * * * * * * * * * * * --> + + <h3 id="_Options">Options</h3> + + <p> + Not specifying any options will result in the <a href="#_default_brace_style">default brace style</a>, + 4 spaces per indent, and no formatting changes.</p> + <p> + Options may be written in two different ways.</p> + + <h4>Long options</h4> + + <p> + These options start with '<strong>--</strong>', and must be written one at a time.<br /> + (Example: '--style=allman --indent=spaces=4')</p> + + <h4>Short Options</h4> + + <p> + These options start with a single '<strong>-</strong>', and may be concatenated together.<br /> + (Example: '-bps4' is the same as writing '-b -p -s4'.)</p> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * * Options File * * * * * * * * * * * * * * --> + + <h3 id="_Options_File">Options File</h3> + + <p> + An OPTIONAL, default options file may be used to supplement or replace the command line options. </p> + <ul> + <li>The command line options have precedence. If there is a conflict between a command line option and an option in + the default options file, the command line option will be used. + </li> + <li>Artistic Style looks for this file in the following locations (in order): + <ol> + <li>the file indicated by the --options= command line option;</li> + <li>the file and directory indicated by the environment variable ARTISTIC_STYLE_OPTIONS (if it exists);</li> + <li>the file named .astylerc in the directory pointed to by the HOME environment variable (e.g. "$HOME/.astylerc" + on Linux); + </li> + <li>the file named astylerc in the directory pointed to by the USERPROFILE environment variable (e.g. "%USERPROFILE%\astylerc" + on Windows). + </li> + </ol> + </li> + <li>This option file lookup can be disabled by specifying --options=none on the command line.</li> + <li>Options may be set apart by new-lines, tabs, commas, or spaces.</li> + <li>Long options in the options file may be written without the preceding '--'.</li> + <li>Lines within the options file that begin with '#' are considered line-comments.</li> + </ul> + <p> + Example of a default options file:</p> + <div class="code"> + <pre><span class="comment"># this line is a comment</span> +--style=allman <span class="comment"># this is a line-end comment</span> +<span class="comment"># long options can be written without the preceding '--'</span> +indent-switches <span class="comment"># cannot do this on the command line</span> +<span class="comment"># short options must have the preceding '-'</span> +-t -p +<span class="comment"># short options can be concatenated together</span> +-M60Ucv</pre> + </div> + <p> + </p> + + <hr /> + + <!-- * * * * * * * * * * * * * Disable Formatting * * * * * * * * * * * * * --> + + <h3 id="_Disable_Formatting">Disable Formatting</h3> + + <p> + Formatting and indenting can be disabled with comment tags inserted in the source code.</p> + + <h4>Disable Block</h4> + + <p> + Blocks of code can be disabled using "off" and "on" tags. The tags are included in the source + file as comments. The comment may be a C comment (/* ... */) or a C++ line comment (//). The tag must be included + in a single line comment. If the comment exceeds one line the indent tag will be ignored. Additional information + can be included with the tag.</p> + <p> + The beginning tag is "*INDENT-OFF*" and the ending tag is "*INDENT-ON*". + They may be used anywhere in the program with the condition that parsing is partially disabled between the + tags. Disabling partial statements may result in incorrect formatting after the ending tag. If this happens expand + the tags to include additional code.</p> + <div class="code"> + <p class="code"> + The following retains the format of a preprocessor define:</p> + <pre><span class="comment">// *INDENT-OFF*</span> +#define FOO_DECLARE_int32_(name) \ + FOO_API_ extern ::Int32 FOO_FLAG(name) +<span class="comment">// *INDENT-ON*</span></pre> + </div> + + <h4>Disable Line</h4> + + <p> + Artistic Style cannot always determine the usage of symbols with more than one meaning. For example an asterisk + (*) can be multiplication, a pointer, or a pointer dereference. The "&" and "&&" + symbols are a similar + problem.</p> + <p> + If a symbol is being padded incorrectly, padding it manually may fix the problem. If it is still being + padded incorrectly, then disabling the formatting may be necessary. To avoid having to use the "disable block" + tags above, a single line disable is available.</p> + <p> + A line-end comment tag "*NOPAD*" will disable the "pad-oper", "align-pointer", and + "align-reference" options. Parsing does NOT stop and all other formatting will be applied to the line. + The tag applies to the one line only.</p> + <div class="code"> + <p class="code"> + The following prevents the operator padding from changing:</p> + <pre>size_t foo = (unsigned int) -1; <span class="comment">// *NOPAD*</span></pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * Basic Brace Styles * * * * * * * * * * * * --> + + <h3 id="_Basic_Brace_Styles">Basic Brace Styles</h3> + + <p> + There are three basic brace styles.<br /> + Attached – The braces are attached to the end of + the last line of the previous block. (Java).<br /> + Broken – The braces are broken from the previous + block. (Allman).<br /> + Linux – The braces are attached except for the opening brace of a function, class, or namespace (K&R, + Linux).</p> + + <p> + Other brace styles are variations of these. Some will use variations on the placement of class, namespace, + or other braces. (Stroustrup, Google, One True Brace, Lisp). Others will indent the braces (Whitesmith, VTK, + Banner, and GNU). Still others will use run-in braces where the following statement is on the same line as the + brace (Horstmann and Pico).</p> + <p> + There are technical arguments for selecting one style over another. But the usual reason comes down to + personal preference. Some like broken braces with vertical whitespace that makes the code easy to read. + Others like attached braces with code that is more compact. Sometimes programmers just want a change. It is + easier to select a preference if you can see an entire file formatted in a certain brace style. With Artistic + Style you can easily modify source code to suit your + preference.</p> + + <p> + </p> + <hr /> + + + <!-- * * * * * * * * * * * * Brace Style Options * * * * * * * * * * * * --> + + <h3 id="_Brace_Style_Options">Brace Style Options</h3> + + <p> + Brace Style options define the brace style to use. All options default to 4 spaces per indent, indented with + spaces. By default, none of the styles indent namespaces. Other indentations are indicated in the individual style + description. All options will break the braces for one line blocks and will break one line statements. To change + this, use the option <a href="#_keep-one-line-blocks">keep-one-line-blocks</a> and/or <a href="#_keep-one-line-statements"> + keep-one-line-statements</a> described in the <a href="#_Formatting_Options">Formatting Options</a> + section.</p> + <p> + </p> + <p id="_default_brace_style"> + <code class="title">default brace style</code><br /> + If no brace style is requested, the default brace style will be used. The opening braces are not changed + and the closing braces will be broken from the preceding line. There are a few exceptions to this.</p> + <p> + </p> + <p id="_style=allman"> + <code class="title">--style=allman / --style=bsd / --style=break / -A1</code><br /> + Allman style uses broken braces.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isBar) + <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> + else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=java"> + <code class="title">--style=java / --style=attach / -A2</code><br /> + Java style uses attached braces.</p> + <div class="code"> + <pre>int Foo(bool isBar) <span class="brace">{</span> + if (isBar) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=kr"> + <code class="title">--style=kr / --style=k&r / --style=k/r / -A3</code><br /> + Kernighan & Ritchie style uses linux braces. Opening braces are broken from namespaces, classes, and function + definitions. The braces are attached to everything else, including arrays, structs, enums, and statements within + a function.</p> + <p> + Using the k&r option may cause problems because of the &. This can be resolved by enclosing the k&r + in quotes (e.g. ‑‑style="k&r") or by using one of the alternates ‑‑style=kr or + ‑‑style=k/r.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isBar) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=stroustrup"> + <code class="title">--style=stroustrup / -A4</code><br /> + Stroustrup style uses linux braces with closing headers broken from closing braces + (e.g. ‑‑break‑closing‑headers). Opening braces are broken from function definitions only. + The opening braces are attached to everything else, including namespaces, classes, arrays, structs, enums, and + statements within a function. This style frequently is used with "attach‑closing‑while", + tabbed indents, and an indent of 5 spaces per tab.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isBar) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> + else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=whitesmith"> + <code class="title">--style=whitesmith / -A5</code><br /> + Whitesmith style uses broken, indented braces. Switch blocks and class blocks are indented to prevent a 'hanging + indent' with the following case statements and C++ class modifiers (public, private, protected). </p> + <div class="code"> + <pre>int Foo(bool isBar) + <span class="brace">{</span> + if (isBar) + <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> + else + return 0; + <span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=vtk"> + <code class="title">--style=vtk / -A15</code><br /> + VTK (Visualization Toolkit) style uses broken, indented braces, except for the opening brace. Switch blocks + are indented to prevent a 'hanging indent' with following case statements. </p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isBar) + <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> + else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=banner"> + <code class="title">--style=banner / -A6</code><br /> + Banner style uses attached, indented braces. Switch blocks and class blocks are indented to prevent a 'hanging + indent' with following case statements and C++ class modifiers (public, private, protected). </p> + <div class="code"> + <pre>int Foo(bool isBar) <span class="brace">{</span> + if (isBar) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> + else + return 0; + <span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=gnu"> + <code class="title">--style=gnu / -A7</code><br /> + GNU style uses broken braces and indented blocks. Extra indentation is added to blocks <strong>within a + function</strong> only. Other braces and blocks are broken, but NOT indented. This style frequently is + used with an indent of 2 spaces.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isBar) + <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> + else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=linux"> + <code class="title">--style=linux / --style=knf / -A8</code><br /> + Linux style uses linux braces. Opening braces are broken from namespace, class, and function definitions. + The braces are attached to everything else, including arrays, structs, enums, and statements within a function. + The <strong>minimum conditional indent</strong> is one-half indent. If you want a different minimum conditional + indent, use the K&R style instead. This style works best with a large indent. It frequently is used with + an indent of 8 spaces.</p> + <p> + Also known as Kernel Normal Form (KNF) style, this is the style used in the Linux + BSD kernel.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isFoo) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=horstmann"> + <code class="title">--style=horstmann / --style=run-in / -A9</code><br /> + Horstmann style uses broken braces and run-in statements. Switches are indented to allow a run-in to the opening + switch block. This style frequently is used with an indent of 3 spaces.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> if (isBar) + <span class="brace">{</span> bar(); + return 1; + <span class="brace">}</span> + else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=1tbs"> + <code class="title">--style=1tbs / --style=otbs / -A10</code><br /> + "One True Brace Style" uses linux braces and adds braces to unbraced one line conditional statements. Opening + braces are broken from namespaces, classes, and function definitions. The braces are attached to everything + else, including arrays, structs, enums, and statements within a function. </p> + <p> + In the following example, braces have been added to the "return 0;" statement. The option + ‑‑add‑one‑line‑braces can also be used with this style.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isFoo) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> else <span class="brace">{</span> + return 0; + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=google"> + <code class="title">--style=google / -A14</code><br /> + Google style uses attached braces and indented class access modifiers. See the indent-modifiers + option for an example of the indented modifiers format. This is not actually a unique brace style, but + is Java style with a non-brace variation. This style frequently is used with an indent of 2 spaces.</p> + <div class="code"> + <pre>int Foo(bool isBar) <span class="brace">{</span> + if (isBar) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=mozilla"> + <code class="title">--style=mozilla / -A16</code><br /> + Mozilla style uses linux braces. Opening braces are broken from classes, structs, enums, and function + definitions. The braces are attached to everything else, including namespaces, arrays, and statements + within a function. This style frequently is used with an indent of 2 spaces.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> + if (isBar) <span class="brace">{</span> + bar(); + return 1; + <span class="brace">}</span> else + return 0; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=pico"> + <code class="title">--style=pico / -A11</code><br /> + Pico style uses broken braces and run-in statements with attached closing braces. The closing brace is attached + to the last line in the block. Switches are indented to allow a run-in to the opening switch block. The style + implies keep-one-line-blocks and keep-one-line-statements. If add-braces is used they will be added as one-line + braces. This style frequently is used with an indent of 2 spaces.</p> + <div class="code"> + <pre>int Foo(bool isBar) +<span class="brace">{</span> if (isBar) + <span class="brace">{</span> bar(); + return 1; <span class="brace">}</span> + else + return 0; <span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_style=lisp"> + <code class="title">--style=lisp / --style=python / -A12</code><br /> + Lisp style uses attached opening and closing braces. The closing brace is attached to the last line in the + block. The style implies keep-one-line-statements, but NOT keep-one-line-blocks. This style does not support one-line + braces. If add-one-line-braces is used they will be added as multiple-line braces.</p> + <div class="code"> + <pre>int Foo(bool isBar) <span class="brace">{</span> + if (isBar) <span class="brace">{ +</span> bar() + return 1; <span class="brace">} + </span> else + return 0; <span class="brace">}</span> +</pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * * * Tab Options * * * * * * * * * * * * * * * --> + + <h3 id="_Tab_Options">Tab Options</h3> + + <p> + The following examples show whitespace characters. A space is indicated with a <strong>.</strong> (dot), a tab + is indicated by a > (greater than).</p> + <p id="_default_indent"> + <code class="title">default indent</code><br /> + If no indentation option is set, the default option of 4 spaces will be used (e.g. -s<span class="option">4</span> + --indent=spaces=<span class="option">4</span>).</p> + <div class="code"> + <p class="code"> + with default values:</p> + <pre>void Foo() <span class="brace">{</span> +....if (isBar1 +............&& isBar2) <span class="comment">// indent of this line can be changed with min-conditional-indent</span> +........bar(); +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent=spaces"> + <code class="title">--indent=spaces / --indent=spaces=<span class="option">#</span> / -s<span class="option">#</span></code><br /> + Indent using # <strong>spaces</strong> per indent (e.g. -s<span class="option">3</span> --indent=spaces=<span + class="option">3</span>). # must be between 2 and 20. Not specifying # will result in a default of + 4 spaces per indent.</p> + <div class="code"> + <p class="code"> + with indent=spaces=3</p> + <pre>void Foo() <span class="brace">{</span> +...if (isBar1 +.........&& isBar2) <span class="comment">// indent of this line can be changed with min-conditional-indent</span> +......bar(); +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent=tab"> + <code class="title">--indent=tab / --indent=tab=<span class="option">#</span> / -t / -t<span class="option">#</span></code><br /> + Indent using <strong>tabs for indentation, and spaces for continuation line alignment</strong>. This ensures that + the code is displayed correctly regardless of the viewer’s tab size. Treat each indent as # spaces + (e.g. -t<span class="option">6</span> / --indent=tab=<span class="option">6</span>). + # must be between 2 and 20. If no # is set, treats indents as 4 spaces.</p> + <div class="code"> + <p class="code"> + with indent=tab:</p> + <pre>void Foo() <span class="brace">{</span> +> if (isBar1 +> ........&& isBar2) <span class="comment">// indent of this line can be changed with min-conditional-indent</span> +> > bar(); +<span class="brace">}</span> +</pre> + <p class="code"> + with style=linux, indent=tab=8:</p> + <pre>void Foo() +<span class="brace">{</span> +> if (isBar1 +> ....&& isBar2) <span class="comment">// indent of this line can NOT be changed with style=linux</span> +> > bar(); +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent=force-tab"> + <code class="title">--indent=force-tab / --indent=force-tab=<span class="option">#</span> / -T / -T<span class="option">#</span></code><br /> + Indent using <strong>all tab</strong> characters, if possible. If a continuation line is not an even number of + tabs, spaces will be added at the end. Treat each tab as # spaces (e.g. -T<span class="option">6</span> + / --indent=<span lang="en-us">force-</span>tab=<span class="option">6</span>). # must be between + 2 and 20. If no # is set, treats tabs as 4 spaces.</p> + <div class="code"> + <p class="code"> + with indent=force-tab:</p> + <pre>void Foo() <span class="brace">{</span> +> if (isBar1 +> > > && isBar2) <span class="comment">// indent of this line can be changed with min-conditional-indent</span> +> > bar(); +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent=force-tab-x"> + <code class="title">--indent=force-tab-x / --indent=force-tab-x=<span class="option">#</span> / -xT / -xT<span + class="option">#</span> + </code><br /> + This force-tab option allows the tab length to be set to a length that is different than the indent length. This + may cause the indentation to be <strong>a mix of both tabs and spaces.</strong> Tabs will be used to indent, if + possible. If a tab indent cannot be used, spaces will be used instead.</p> + <p> + This option sets the <strong>tab length.</strong> Treat each tab as # spaces (e.g. -xT<span class="option">6</span> + / --indent=<span lang="en-us">force-</span>tab-x=<span class="option">6</span>. # must be between + 2 and 20. If no # is set, treats tabs as 8 spaces. To change the <strong>indent length</strong> from the default + of 4 spaces the option "indent=force-tab" must also be used.</p> + <div class="code"> + <p class="code"> + with indent=force-tab-x (default tab length of 8 and default indent length of 4):</p> + <pre>void Foo() <span class="brace">{</span> +....if (isBar1 +> ....&& isBar2) <span class="comment">// indent of this line can be changed with min-conditional-indent</span> +> bar(); +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * Brace Modify Options * * * * * * * * * * * * --> + + <h3 id="_Brace_Modify_Options">Brace Modify Options</h3> + + <p id="_attach_namespaces"> + <code class="title">--attach-namespaces / -xn</code><br /> + Attach braces to a namespace statement. This is done regardless of the brace style being used. + It will also attach braces to CORBA IDL module statements.</p> + <div class="code"> + <p class="code"> + the brace is always attached to a namespace statement:</p> + <pre>namespace FooName <span class="brace">{</span> +... +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_attach_classes"> + <code class="title">--attach-classes / -xc</code><br /> + Attach braces to a class statement. This is done regardless of the brace style being used.</p> + <div class="code"> + <p class="code"> + the brace is always attached to a class statement:</p> + <pre>class FooClass <span class="brace">{</span> +... +<span class="brace">}</span>; +</pre> + </div> + <p> + </p> + <p id="_attach_inlines"> + <code class="title">--attach-inlines / -xl</code><br /> + Attach braces to class and struct inline function definitions. This option has precedence for all + styles except Horstmann and Pico (run-in styles). It is effective for C++ files only.</p> + <div class="code"> + <p class="code"> + all braces are attached to class and struct inline method definitions:</p> + <pre>class FooClass +<span class="brace">{</span> + void Foo() <span class="brace">{</span> + ... +<span class="brace"> }</span> +<span class="brace">}</span>; +</pre> + </div> + <p> + </p> + <p id="_attach-extern-c"> + <code class="title">--attach-extern-c / -xk</code><br /> + Attach braces to a braced extern "C" statement. This is done regardless of the brace style being used. + This option is effective for C++ files only.</p> + <p> + An extern "C" statement that is part of a function definition is formatted according to the requested brace + style. Braced extern "C" statements are unaffected by the brace style and this option is the only way to + change them.</p> + <div class="code"> + <p class="code"> + this option attaches braces to a braced extern "C" statement:</p> + <pre>#ifdef __cplusplus +extern "C" <span class="brace">{</span> +#endif +</pre> + <p class="code"> + but function definitions are formatted according to the requested brace style:</p> + <pre>extern "C" EXPORT void STDCALL Foo() +<span class="brace">{}</span> +</pre> + </div> + <p> + </p> + <p id="_attach-closing-while"> + <code class="title">--attach-closing-while / -xV</code><br /> + Attach the closing 'while' of a 'do-while' statement to the closing brace. This has precedence over both + the brace style and the break closing braces option.</p> + <div class="code"> + <pre>do +<span class="brace">{</span> + bar(); + ++x; +<span class="brace">}</span> +while x == 1; +</pre> + <p class="code"> + becomes:</p> + <pre>do +<span class="brace">{</span> + bar(); + ++x; +<span class="brace">}</span> while x == 1; +</pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * Indentation Options * * * * * * * * * * * * * --> + + <h3 id="_Indentation_Options">Indentation Options</h3> + + <p id="_indent-classes"> + <code class="title">--indent-classes / -C</code><br /> + Indent 'class' and 'struct' blocks so that the entire block is indented. The struct + blocks are indented only if an access modifier, 'public:', 'protected:' or 'private:', + is declared somewhere in the struct. This option is effective for C++ files only.</p> + <div class="code"> + <pre>class Foo +<span class="brace">{</span> +public: + Foo(); + virtual ~Foo(); +<span class="brace">}</span>; +</pre> + <p class="code"> + becomes:</p> + <pre>class Foo +<span class="brace">{</span> + public: + Foo(); + virtual ~Foo(); +<span class="brace">}</span>; +</pre> + </div> + <p> + </p> + <p id="_indent-modifiers"> + <code class="title">--indent-modifiers / -xG</code><br /> + Indent 'class ' and 'struct' access modifiers, 'public:', 'protected:' + and 'private:', one half indent. The rest of the class is not indented. This option is effective + for C++ files only. If used with indent‑classes this option will be ignored.</p> + <div class="code"> + <pre>class Foo +<span class="brace">{</span> +public: + Foo(); + virtual ~Foo(); +<span class="brace">}</span>; +</pre> + <p class="code"> + becomes:</p> + <pre>class Foo +<span class="brace">{</span> + public: + Foo(); + virtual ~Foo(); +<span class="brace">}</span>; +</pre> + </div> + <p> + </p> + <p id="_indent-switches"> + <code class="title">--indent-switches / -S</code><br /> + Indent 'switch' blocks so that the 'case X:' statements are indented in the switch block. The entire + case block is indented.</p> + <div class="code"> + <pre>switch (foo) +<span class="brace">{</span> +case 1: + a += 1; + break; + +case 2: +<span class="brace">{</span> + a += 2; + break; +<span class="brace">}</span> +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>switch (foo) +<span class="brace">{</span> + case 1: + a += 1; + break; + + case 2: + <span class="brace">{</span> + a += 2; + break; + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent-cases"> + <code class="title">--indent-cases / -K</code><br /> + Indent '<code>case X:</code>' blocks from the '<code>case X:</code>' headers. Case statements not enclosed in + blocks are NOT indented.</p> + <div class="code"> + <pre>switch (foo) +<span class="brace">{</span> + case 1: + a += 1; + break; + + case 2: + <span class="brace">{</span> + a += 2; + break; + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>switch (foo) +<span class="brace">{</span> + case 1: + a += 1; + break; + + case 2: + <span class="brace">{</span> + a += 2; + break; + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent-namespaces"> + <code class="title">--indent-namespaces / -N</code><br /> + Add extra indentation to namespace blocks. This option has no effect on Java files. It + will also indent CORBA IDL module statements.</p> + <div class="code"> + <pre>namespace foospace +<span class="brace">{</span> +class Foo +<span class="brace">{</span> + public: + Foo(); + virtual ~Foo(); +<span class="brace">}</span>; +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>namespace foospace +<span class="brace">{</span> + class Foo + <span class="brace">{</span> + public: + Foo(); + virtual ~Foo(); + <span class="brace">}</span>; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent-after-parens"> + <code class="title">--indent-after-parens / -xU</code><br /> + Indent, instead of align, continuation lines following lines that contain an opening paren '(' or an assignment + '='. This includes function definitions and declarations and return statements. The indentation can be modified + by using the following indent-continuation option. This option may be preferred for editors displaying proportional + fonts.</p> + <div class="code"> + <pre>void Foo(bool bar1, + bool bar2) +<span class="brace">{</span> + isLongFunction(bar1, + bar2); + + isLongVariable = foo1 + || foo2; +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>void Foo(bool bar1, + bool bar2) +<span class="brace">{</span> + isLongFunction(bar1, + bar2); + + isLongVariable = foo1 + || foo2; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_indent-continuation"> + <code class="title">--indent-continuation=<span class="option">#</span> / -xt<span class="option">#</span></code><br /> + Set the continuation indent for a line that ends with an opening paren '(' or an assignment '='. This includes + function definitions and declarations. It will also modify the previous indent-after-paren option. The value for + <span class="option">#</span> indicates a <strong>number of indents</strong>. The valid values are the integer + values from <strong>0 thru 4</strong>. If this option is not used, the default value of <strong>1</strong> is + used. </p> + <div class="code"> + <pre>isLongVariable = + foo1 || + foo2; + +isLongFunction( + bar1, + bar2); +</pre> + <p class="code"> + becomes (with indent-continuation=3):</p> + <pre>isLongVariable = + foo1 || + foo2; + +isLongFunction( + bar1, + bar2); +</pre> + </div> + <p> + </p> + <p id="_indent-labels"> + <code class="title">--indent-labels / -L</code><br /> + Add extra indentation to labels so they appear 1 indent less than the current indentation, rather than being flushed + to the left (the default).</p> + <div class="code"> + <pre>void Foo() <span class="brace">{</span> + while (isFoo) <span class="brace">{</span> + if (isFoo) + goto error; + ... +error: + ... + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + <p class="code"> + becomes (with indented 'error:'):</p> + <pre>void Foo() <span class="brace">{</span> + while (isFoo) <span class="brace">{</span> + if (isFoo) + goto error; + ... + error: + ... + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + + <p id="_indent-preproc-block"> + <code class="title">--indent-preproc-block / -xW</code><br /> + Indent preprocessor blocks at brace level zero and immediately within a namespace. There are restrictions on + what will be indented. Blocks within methods, classes, arrays, etc., will not be indented. Blocks containing braces + or multi-line define statements will not be indented. Without this option the preprocessor block is not + indented.</p> + <div class="code"> + <pre>#ifdef _WIN32 +#include <windows.h> +#ifndef NO_EXPORT +#define EXPORT +#endif +#endif +</pre> + <p class="code"> + becomes:</p> + <pre>#ifdef _WIN32 + #include <windows.h> + #ifndef NO_EXPORT + #define EXPORT + #endif +#endif +</pre> + </div> + <p> + </p> + <p id="_indent-preproc-define"> + <code class="title">--indent-preproc-define / -w</code><br /> + Indent multi-line preprocessor definitions ending with a backslash. Should be used with --convert-tabs for proper + results. Does a pretty good job, but cannot perform miracles in obfuscated preprocessor definitions. Without this + option the preprocessor statements remain unchanged.</p> + <div class="code"> + <pre>#define Is_Bar(arg,a,b) \ +(Is_Foo((arg), (a)) \ +|| Is_Foo((arg), (b))) +</pre> + <p class="code"> + becomes:</p> + <pre>#define Is_Bar(arg,a,b) \ + (Is_Foo((arg), (a)) \ + || Is_Foo((arg), (b))) +</pre> + </div> + <p> + </p> + <p id="_indent-preproc-cond"> + <code class="title">--indent-preproc-cond / -xw</code><br /> + Indent preprocessor conditional statements to the same level as the source code.</p> + <div class="code"> + <pre> isFoo = true; +#ifdef UNICODE + text = wideBuff; +#else + text = buff; +#endif</pre> + <p class="code"> + becomes:</p> + <pre> isFoo = true; + #ifdef UNICODE + text = wideBuff; + #else + text = buff; + #endif +</pre> + </div> + <p> + </p> + <p id="_indent-col1-comments"> + <code class="title">--indent-col1-comments / -Y</code><br /> + Indent C++ comments beginning in column one. By default C++ comments beginning in column one are + assumed to be commented‑out code and not indented. This option will allow the comments to be indented with + the code.</p> + <div class="code"> + <pre>void Foo()\n" +<span class="brace">{</span> +<span class="comment">// comment</span> + if (isFoo) + bar(); +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>void Foo()\n" +<span class="brace">{</span> + <span class="comment">// comment</span> + if (isFoo) + bar(); +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_min-conditional-indent"> + <code class="title">--min-conditional-indent=<span class="option">#</span> / -m<span class="option">#</span></code><br /> + Set the minimal indent that is added when a header is built of multiple lines. This indent helps to easily separate + the header from the command statements that follow. The value for <span class="option">#</span> + indicates a <strong>number of indents</strong> and is a minimum value. The indent may be greater to align with + the data on the previous line.<br /> + The valid values are:<br /> + 0 - no minimal indent. The lines will be aligned with the paren on the preceding line.<br /> + 1 - indent at least one additional indent.<br /> + 2 - indent at least two additional indents.<br /> + 3 - indent at least one-half an additional indent. This is intended for large indents (e.g. 8).<br /> + The default value is <strong>2</strong>, two additional indents.</p> + <div class="code"> + <pre><span class="comment">// default setting makes this non-braced code clear</span> +if (a < b + || c > d) + foo++; + +<span class="comment">// but creates an exaggerated indent in this braced code</span> +if (a < b + || c > d) +<span class="brace">{</span> + foo++; +<span class="brace">}</span> +</pre> + <p class="code"> + becomes (when setting + <strong><code>--min-conditional-indent=<span class="option">0</span></code></strong>):</p> + <pre><span class="comment">// setting makes this non-braced code less clear</span> +if (a < b + || c > d) + foo++; + +<span class="comment">// but makes this braced code clearer</span> +if (a < b + || c > d) +<span class="brace">{</span> + foo++; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_max-continuation-indent"> + <code class="title">--max-continuation-indent=<span class="option">#</span> / -M<span class="option">#</span></code><br /> + <code class="title">--max-instatement-indent=<span class="option">#</span> is depreciated</code><br /> + Set the maximum of <span class="option">#</span> spaces to indent a continuation line. The + <span class="option">#</span> indicates a number of columns and must not be less than <strong>40</strong> or + greater than <strong>120</strong>. If no value is set, the default value of <strong>40</strong> will be + used. This option will prevent continuation lines from extending too far to the right. Setting a larger value + will allow the code to be extended further to the right.</p> + <div class="code"> + <pre>fooArray[] = <span class="brace">{</span> red, + green, + blue <span class="brace">}</span>; + +fooFunction(barArg1, + barArg2, + barArg3); +</pre> + <p class="code"> + becomes (with larger value):</p> + <pre>fooArray[] = <span class="brace">{</span> red, + green, + blue <span class="brace">}</span>; + +fooFunction(barArg1, + barArg2, + barArg3); +</pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * Padding Options * * * * * * * * * * * * * --> + + <h3 id="_Padding_Options">Padding Options</h3> + + <p id="_break-blocks"> + <code class="title">--break-blocks / -f</code><br /> + Pad empty lines around header blocks (e.g. 'if', 'for', 'while'...).</p> + <div class="code"> + <pre>isFoo = true; +if (isFoo) <span class="brace">{</span> + bar(); +<span class="brace">}</span> else <span class="brace">{</span> + anotherBar(); +<span class="brace">}</span> +isBar = false; +</pre> + <p class="code"> + becomes:</p> + <pre>isFoo = true; + +if (isFoo) <span class="brace">{</span> + bar(); +<span class="brace">}</span> else <span class="brace">{</span> + anotherBar(); +<span class="brace">}</span> + +isBar = false; +</pre> + </div> + <p> + </p> + <p id="_break-blocks=all"> + <code class="title">--break-blocks=all / -F</code><br /> + Pad empty lines around header blocks (e.g. 'if', 'for', 'while'...). Treat + closing header blocks (e.g. 'else', 'catch') as stand-alone blocks.</p> + <div class="code"> + <pre>isFoo = true; +if (isFoo) <span class="brace">{</span> + bar(); +<span class="brace">}</span> else <span class="brace">{</span> + anotherBar(); +<span class="brace">}</span> +isBar = false; +</pre> + <p class="code"> + becomes:</p> + <pre>isFoo = true; + +if (isFoo) <span class="brace">{</span> + bar(); + +<span class="brace">}</span> else <span class="brace">{</span> + anotherBar(); +<span class="brace">}</span> + +isBar = false; +</pre> + </div> + <p> + </p> + <p id="_pad-oper"> + <code class="title">--pad-oper / -p </code><br /> + Insert space padding around operators. This will also pad commas. Any end of line comments will remain in the + original column, if possible. Note that there is no option to unpad. Once padded, they stay padded.</p> + <div class="code"> + <pre>if (foo==2) + a=bar((b-c)*a,d--); +</pre> + <p class="code"> + becomes:</p> + <pre>if (foo == 2) + a = bar((b - c) * a, d--); +</pre> + </div> + <p> + </p> + <p id="_pad-comma"> + <code class="title">--pad-comma / -xg </code><br /> + Insert space padding after commas. This is not needed if pad-oper is used. Any end of line comments will + remain in the original column, if possible. Note that there is no option to unpad. Once padded, they + stay padded.</p> + <div class="code"> + <pre>if (isFoo(a,b) + bar(a,b); +</pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo(a, b) + bar(a, b); +</pre> + </div> + <p> + </p> + <p id="_pad-paren"> + <code class="title">--pad-paren / -P </code> + <br /> + Insert space padding around parens on both the <strong>outside</strong> and the <strong>inside</strong>. + Any end of line comments will remain in the original column, if possible.</p> + <div class="code"> + <pre>if (isFoo((a+2), b)) + bar(a, b); +</pre> + <p class="code"> + becomes:</p> + <pre>if ( isFoo ( ( a+2 ), b ) ) + bar ( a, b ); +</pre> + </div> + <p> + </p> + <p id="_pad-paren-out"> + <code class="title">--pad-paren-out / -d </code> + <br /> + Insert space padding around parens on the <strong>outside</strong> only. Parens that are empty will + not be padded. Any end of line comments will remain in the original column, if possible. This can be used with + unpad-paren below to remove unwanted spaces.</p> + <div class="code"> + <pre>if (isFoo((a+2), b)) + bar(a, b); +</pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo ( (a+2), b) ) + bar (a, b); +</pre> + </div> + <p> + </p> + <p id="_pad-first-paren-out"> + <code class="title">--pad-first-paren-out / -xd </code> + <br /> + Insert space padding around the <strong>first</strong> paren in a series on the <strong>outside</strong> + only. Parens that are empty will not be padded. Any end of line comments will remain in the original column, + if possible. This can be used with unpad-paren below to remove unwanted spaces. If used with pad‑paren or + pad‑paren‑out, this option will be ignored. If used with pad‑paren‑in, the result will + be the same as pad‑paren.</p> + <div class="code"> + <pre>if (isFoo((a+2), b)) + bar(a, b); +</pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo ((a+2), b)) + bar (a, b); +</pre> + </div> + <p> + </p> + <p id="_pad-paren-in"> + <code class="title">--pad-paren-in / -D </code> + <br /> + Insert space padding around paren on the <strong>inside</strong> only. Any end of line comments will remain + in the original column, if possible. This can be used with unpad-paren below to remove unwanted spaces.</p> + <div class="code"> + <pre>if (isFoo((a+2), b)) + bar(a, b); +</pre> + <p class="code"> + becomes:</p> + <pre>if ( isFoo( ( a+2 ), b ) ) + bar( a, b ); +</pre> + </div> + <p> + </p> + <p id="_pad-header"> + <code class="title">--pad-header / -H </code> + <br /> + Insert space padding between a header (e.g. 'if', 'for', 'while'...) + and the following paren. Any end of line comments will remain in the original column, if possible. This can + be used with unpad-paren to remove unwanted spaces.</p> + <div class="code"> + <pre>if(isFoo((a+2), b)) + bar(a, b);</pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo((a+2), b)) + bar(a, b); +</pre> + </div> + <p> + </p> + <p id="_unpad-paren"> + <code class="title">--unpad-paren / -U </code> + <br /> + Remove extra space padding around parens on the inside and outside. Any end of line comments will remain + in the original column, if possible. This option can be used in combination with the paren padding options + pad‑paren, pad‑paren‑out, pad‑paren‑in, + and pad‑header above. Only padding that has not been requested by other options will be + removed.</p> + <p> + For example, if a source has parens padded on both the inside and outside, and you want inside only. You need + to use unpad-paren to remove the outside padding, and pad‑paren‑in to + retain the inside padding. Using only pad‑paren‑in> would not remove the outside + padding.</p> + <div class="code"> + <pre>if ( isFoo( ( a+2 ), b ) ) + bar ( a, b ); +</pre> + <p class="code"> + becomes (with no padding option requested):</p> + <pre>if(isFoo((a+2), b)) + bar(a, b); +</pre> + </div> + <p> + </p> + <p id="_delete-empty-lines"> + <code class="title">--delete-empty-lines / -xe</code><br /> + Delete empty lines within a function or method. Empty lines outside of functions or methods are NOT deleted. If + used with break-blocks or break-blocks=all it will delete all lines EXCEPT the lines added by the break-blocks + options.</p> + <div class="code"> + <pre>void Foo() +<span class="brace">{</span> + + foo1 = 1; + + foo2 = 2; + +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>void Foo() +<span class="brace">{</span> + foo1 = 1; + foo2 = 2; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_fill-empty-lines"> + <code class="title">--fill-empty-lines / -E</code><br /> + Fill empty lines with the white space of the previous line.</p> + <p> + </p> + <p id="_align-pointer"> + <code class="title">--align-pointer=type / -k1<br /> + --align-pointer=middle / -k2<br /> + --align-pointer=name / -k3 + </code><br /> + Attach a pointer or reference operator (*, &, or ^) to either the variable type (left) or variable name (right), + or place it between the type and name (middle). The spacing between the type and name will be preserved, if possible. + This option is for C/C++, C++/CLI, and C# files. To format references separately, use the following align-reference + option.</p> + <div class="code"> + <pre>char* foo1; +char & foo2; +String ^s1;</pre> + <p class="code"> + becomes (with align-pointer=type):</p> + <pre>char* foo1; +char& foo2; +String^ s1;</pre> + </div> + <div class="code"> + <pre>char* foo1; +char & foo2; +String ^s1;</pre> + <p class="code"> + becomes (with align-pointer=middle):</p> + <pre>char * foo1; +char & foo2; +String ^ s1;</pre> + </div> + <div class="code"> + <pre>char* foo1; +char & foo2; +String ^s1;</pre> + <p class="code"> + becomes (with align-pointer=name):</p> + <pre>char *foo1; +char &foo2; +String ^s1;</pre> + </div> + <p> + </p> + <p id="_align-reference"> + <code class="title">--align-reference=none / -W0<br /> + --align-reference=type / -W1<br /> + --align-reference=middle / -W2<br /> + --align-reference=name / -W3 + </code><br /> + This option will align references separate from pointers. Pointers are not changed by this option. If pointers + and references are to be aligned the same, use the previous align-pointer option. The option align-reference=none + will not change the reference alignment. The other options are the same as for align-pointer. This option is for + C/C++, C++/CLI, and C# files.</p> + <div class="code"> + <pre>char &foo1;</pre> + <p class="code"> + becomes (with align-reference=type):</p> + <pre>char& foo1;</pre> + </div> + <div class="code"> + <pre>char& foo2;</pre> + <p class="code"> + becomes (with align-reference=middle):</p> + <pre>char & foo2;</pre> + </div> + <div class="code"> + <pre>char& foo3;</pre> + <p class="code"> + becomes (with align-reference=name):</p> + <pre>char &foo3;</pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * Formatting Options * * * * * * * * * * * * * --> + + <h3 id="_Formatting_Options">Formatting Options</h3> + + <p id="_break-closing-braces"> + <code class="title">--break-closing-braces / -y<br /> + --break-closing-brackets is depreciated </code> + <br /> + When used with --style=java, --style=kr, --style=stroustrup, --style=linux, or --style=1tbs, this breaks closing + headers (e.g. 'else', 'catch', ...) from their immediately preceding closing braces. Closing header braces + are always broken with the other styles.</p> + <div class="code"> + <pre>void Foo(bool isFoo) <span class="brace">{</span> + if (isFoo) <span class="brace">{</span> + bar(); + <span class="brace">}</span> else <span class="brace">{</span> + anotherBar(); + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + <p class="code"> + becomes (a broken 'else'):</p> + <pre>void Foo(bool isFoo) <span class="brace">{</span> + if (isFoo) <span class="brace">{</span> + bar(); + <span class="brace">}</span> + else <span class="brace">{</span> + anotherBar(); + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_break-elseifs"> + <code class="title">--break-elseifs / -e</code><br /> + Break "else if" header combinations into separate lines. This option has no effect if keep-one-line-statements + is used, the "else if" statements will remain as they are.</p> + <p> + If this option is NOT used, "else if" header combinations will be placed on a single line.</p> + <div class="code"> + <pre>if (isFoo) <span class="brace">{</span> + bar(); +<span class="brace">}</span> +else if (isFoo1()) <span class="brace">{</span> + bar1(); +<span class="brace">}</span> +else if (isFoo2()) <span class="brace">{</span> + bar2; +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo) <span class="brace">{</span> + bar(); +<span class="brace">}</span> +else + if (isFoo1()) <span class="brace">{</span> + bar1(); + <span class="brace">}</span> + else + if (isFoo2()) <span class="brace">{</span> + bar2(); + <span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_break-one-line-headers"> + <code class="title">--break-one-line-headers / -xb </code> + <br /> + </p> + <p> + Break one line headers (e.g. 'if', 'while', 'else', ...) from a statement residing + on the same line. If the statement is enclosed in braces, the braces will be formatted according to the requested + brace style. </p> + <p> + A multi-statement line will NOT be broken if keep-one-line-statements is requested. One line blocks + will NOT be broken if keep-one-line-blocks is requested and the header is enclosed in the block. </p> + <div class="code"> + <pre>void Foo(bool isFoo) +<span class="brace">{</span> + if (isFoo1) bar1(); + + if (isFoo2) <span class="brace">{</span> bar2(); <span class="brace">}</span> +<span class="brace">}</span> +</pre> + <p class="code"> + becomes:</p> + <pre>void Foo(bool isFoo) +<span class="brace">{</span> + if (isFoo1) + bar1(); + + if (isFoo2) <span class="brace">{</span> + bar2(); + <span class="brace">}</span> +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_add-braces"> + <code class="title">--add-braces / -j <br /> + --add-brackets is depreciated </code> + <br /> + Add braces to unbraced one line conditional statements (e.g. 'if', 'for', 'while'...). The statement must + be on a single line. The braces will be added according to the requested brace style. If no style is requested + the braces will be attached. </p> + <p> + Braces will NOT be added to a multi-statement line if keep-one-line-statements is requested. Braces will + NOT be added to a one line block if keep-one-line-blocks is requested. If --add-one-line-braces is also + used, the result will be one line braces.</p> + <div class="code"> + <pre>if (isFoo) + isFoo = false; +</pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo) <span class="brace">{</span> + isFoo = false; +<span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_add-one-line-braces"> + <code class="title">--add-one-line-braces / -J <br /> + --add-one-line-brackets is depreciated </code> + <br /> + Add one line braces to unbraced one line conditional statements (e.g. 'if', 'for', + 'while'...). The statement must be on a single line. The option implies --keep-one-line-blocks and + will not break the one line blocks.</p> + <div class="code"> + <pre>if (isFoo) + isFoo = false; +</pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo) + <span class="brace">{</span> isFoo = false; <span class="brace">}</span> +</pre> + </div> + <p> + </p> + <p id="_remove-braces"> + <code class="title">--remove-braces / -xj <br /> + --remove-brackets is depreciated </code> + <br /> + Remove braces from conditional statements (e.g. 'if', 'for', 'while'...). + The statement must be a single statement on a single line. If --add-braces or --add-one-line-braces is also + used the result will be to add braces. Braces will not be removed from "One True Brace Style", + --style=1tbs.</p> + <div class="code"> + <pre>if (isFoo) +<span class="brace">{</span> + isFoo = false; +<span class="brace">}</span></pre> + <p class="code"> + becomes:</p> + <pre>if (isFoo) + isFoo = false; +</pre> + </div> + <p> + </p> + <p id="_keep-one-line-blocks"> + <code class="title">--keep-one-line-blocks / -O </code> + <br /> + Don't break one-line blocks.</p> + <div class="code"> + <pre>if (isFoo) +<span class="brace">{</span> isFoo = false; cout << isFoo << endl; <span class="brace">}</span> +</pre> + <p class="code"> + remains unchanged.</p> + </div> + <p> + </p> + <p id="_keep-one-line-statements"> + <code class="title">--keep-one-line-statements / -o </code> + <br /> + Don't break complex statements and multiple statements residing on a single line.</p> + <div class="code"> + <pre>if (isFoo) +<span class="brace">{</span> + isFoo = false; cout << isFoo << endl; +<span class="brace">}</span> +</pre> + <p class="code"> + remains unchanged.</p> + </div> + <p> + </p> + <p id="_convert-tabs"> + <code class="title">--convert-tabs / -c</code><br /> + Converts tabs into spaces in the non-indentation part of the + line. The number of spaces inserted will maintain the spacing of the tab. The current setting for spaces per tab + is used. It may not produce the expected results if convert-tabs is used when changing spaces per tab. Tabs are + not replaced within quotes.</p> + <p> + </p> + <p id="_close-templates"> + <code class="title">--close-templates / -xy</code><br /> + Closes whitespace between the ending angle brackets of template definitions. Closing the ending angle brackets + is now allowed by the C++11 standard. Be sure your compiler supports this before making the changes.</p> + <div class="code"> + <pre>Stack< int, List< int > > stack1;</pre> + <p class="code"> + becomes:</p> + <pre>Stack< int, List< int >> stack1;</pre> + </div> + <p> + </p> + <p id="_remove-comment-prefix"> + <code class="title">--remove-comment-prefix / -xp</code><br /> + Remove the preceding '*' in a multi-line comment that begins a line. A trailing '*', if present, is also removed. + Text that is less than one indent is indented to one indent. Text greater than one indent is not changed. Multi-line + comments that begin a line, but without the preceding '*', are indented to one indent for consistency. This can + slightly modify the indentation of commented out blocks of code. Lines containing all '*' are left unchanged. + Extra spacing is removed from the comment close '*/'.</p> + <div class="code"> + <pre><em>/* + * comment line 1 + * comment line 2 + */</em></pre> + <p class="code"> + becomes:</p> + <pre><em>/* + comment line 1 + comment line 2 +*/</em></pre> + </div> + <p> + </p> + <p id="_max-code-length"> + <code class="title">--max-code-length=<span class="option">#</span> / -xC<span class="option">#</span> + <br /> + --break-after-logical / -xL</code><br /> + The option max‑code‑length will break a line if the code exceeds <span class="option">#</span> + characters. The valid values are 50 thru 200. Lines without logical conditionals will break on a logical conditional + (||, &&, ...), comma, paren, semicolon, or space.</p> + <p> + Some code will not be broken, such as comments, quotes, and arrays. If used with keep‑one‑line‑blocks + or add-one-line-braces the blocks will NOT be broken. If used with keep‑one‑line‑statements + the statements will be broken at a semicolon if the line goes over the maximum length. If there is no available + break point within the max code length, the line will be broken at the first available break point after the max + code length.</p> + <p> + By default logical conditionals will be placed first in the new line. The option break‑after‑logical + will cause the logical conditionals to be placed last on the previous line. This option has no effect without + max‑code‑length.</p> + <div class="code"> + <pre>if (thisVariable1 == thatVariable1 || thisVariable2 == thatVariable2 || thisVariable3 == thatVariable3) + bar();</pre> + <p class="code"> + becomes:</p> + <pre>if (thisVariable1 == thatVariable1 + || thisVariable2 == thatVariable2 + || thisVariable3 == thatVariable3) + bar();</pre> + <p class="code"> + becomes (with break‑after‑logical):</p> + <pre>if (thisVariable1 == thatVariable1 || + thisVariable2 == thatVariable2 || + thisVariable3 == thatVariable3) + bar();</pre> + </div> + <p> + </p> + <p id="_mode"> + <code class="title">--mode=c</code><br /> + <code class="title">--mode=cs</code><br /> + <code class="title">--mode=java</code><br /> + Indent a C type, C#, or Java file. C type files are C, C++, C++/CLI, and Objective-C. The option is usually + set from the file extension for each file. You can override the setting with this entry. It will be used for all + files, regardless of the file extension. It allows the formatter to identify language specific syntax such as + C++ classes, templates, and keywords.</p> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * * Objective-C Options * * * * * * * * * * * * * --> + + <h3 id="_Objective_C_Options">Objective‑C Options</h3> + + <p> + These options are effective for Objective‑C files only. The paren padding options will still apply to the + Objective-C method prefix and return type unless overridden by the following options.</p> + <p> + Because of the longer indents sometimes needed for Objective‑C, the option "max-continuation-indent" may + need to be increased. If you are not getting the paren and square bracket alignment you want try increasing + this value. The option is described in the "Indentation Options" section.</p> + <p id="_pad-method-prefix"> + <code class="title">--pad-method-prefix / -xQ</code><br /> + Insert space padding <strong>after</strong> the '-' or '+' Objective‑C method prefix. This will add + exactly one space. Any additional spaces will be deleted.</p> + <div class="code"> + <pre>-(void)foo1; +- (void)foo2;</pre> + <p class="code"> + becomes:</p> + <pre>- (void)foo1; +- (void)foo2;</pre> + </div> + <p> + </p> + <p id="_unpad-method-prefix"> + <code class="title">--unpad-method-prefix / -xR</code><br /> + Remove all space padding <strong>after</strong> the '-' or '+' Objective‑C method prefix. + This option will be ignored if used with pad‑method‑prefix. This option takes precedence over the + pad paren outside option.</p> + <div class="code"> + <pre>- (void) foo1; +- (void) foo2;</pre> + <p class="code"> + becomes:</p> + <pre>-(void) foo1; +-(void) foo2;</pre> + </div> + <p> + </p> + <p id="_pad-return-type"> + <code class="title">--pad-return-type / -xq</code><br /> + Insert space padding <strong>after</strong> the Objective‑C return type. This will add exactly one + space. Any additional spaces will be deleted. </p> + <div class="code"> + <pre>-(void)foo1; +-(void) foo2;</pre> + <p class="code"> + becomes:</p> + <pre>-(void) foo1; +-(void) foo2;</pre> + </div> + <p> + </p> + <p id="_unpad-return-type"> + <code class="title">--unpad-return-type / -xr</code><br /> + Remove all space padding <strong>after</strong> the Objective‑C return type. This option + will be ignored if used with pad‑return‑type. This option takes precedence over the pad paren + outside option. </p> + <div class="code"> + <pre>-(void) foo1; +-(void) foo2;</pre> + <p class="code"> + becomes:</p> + <pre>-(void)foo1; +-(void)foo2;</pre> + </div> + <p> + </p> + <p id="_pad-param-type"> + <code class="title">--pad-param-type / -xS</code><br /> + Insert space padding around the Objective‑C parameter type. This will add exactly one space. Any additional + spaces will be deleted. This has precedence over the pad method colon option and will always cause space padding + after the method colon.</p> + <div class="code"> + <pre>-(void)foo1:(bool)barArg1; +-(void)foo2: (bool) barArg2;</pre> + <p class="code"> + becomes:</p> + <pre>-(void)foo1: (bool) barArg1; +-(void)foo2: (bool) barArg2;</pre> + </div> + <p> + </p> + <p id="_unpad-param-type"> + <code class="title">--unpad-param-type / -xs</code><br /> + Remove all space padding around the Objective‑C parameter type. This option takes precedence over the pad + paren outside option. The pad method colon option has precedence over the <strong>opening</strong> paren. The + closing paren will always be unpadded.</p> + <div class="code"> + <pre>-(void)foo1: (bool) barArg1; +-(void)foo2: (bool) barArg2;</pre> + <p class="code"> + becomes (with an unpadded method colon):</p> + <pre>-(void)foo1:(bool)barArg1; +-(void)foo2:(bool)barArg2;</pre> + <p class="code"> + becomes (with a padded method colon + after):</p> + <pre>-(void)foo1: (bool)barArg1; +-(void)foo2: (bool)barArg2;</pre> + </div> + <p> + </p> + <p id="_align-method-colon"> + <code class="title">--align-method-colon / -xM</code><br /> + Align the colons in Objective‑C method declarations + and method calls. If this option is not declared, method definitions will be indented uniformly, and method calls + will align with the first keyword.</p> + <div class="code"> + <pre>-(void)longKeyword: (ID)theArg1 + keyword: (int)theArg2 + error: (NSError*)theError +<span class="brace">{</span> + [myObj longKeyword: arg1 + keyword: arg2 + error: arg3]; +<span class="brace">}</span></pre> + <p class="code"> + becomes (with no option declared):</p> + <pre>-(void)longKeyword: (ID)theArg1 + keyword: (int)theArg2 + error: (NSError*)theError +<span class="brace">{</span> + [myObj longKeyword: arg1 + keyword: arg2 + error: arg3]; +<span class="brace">}</span></pre> + <p class="code"> + becomes (with + align-method-colon):</p> + <pre>-(void)longKeyword: (ID)theArg1 + keyword: (int)theArg2 + error: (NSError*)theError +<span class="brace">{</span> + [myObj longKeyword: arg1 + keyword: arg2 + error: arg3]; +<span class="brace">}</span></pre> + </div> + <p> + </p> + <p id="_pad-method-colon"> + <code class="title">--pad-method-colon=none / -xP0<br /> + --pad-method-colon=all / -xP1<br /> + --pad-method-colon=after / -xP2<br /> + --pad-method-colon=before / -xP3 + </code><br /> + Add or remove space padding before or after the colons in an Objective‑C method call. These options will + pad exactly one space. Any additional spaces will be deleted. The space padding after the method colon can be + overridden by pad-param-type.</p> + <div class="code"> + <p class="code"> + with pad-method-colon=none:</p> + <pre>-(void)insertKey:(id)key;</pre> + <p class="code"> + with pad-method-colon=all:</p> + <pre>-(void)insertKey : (id)key;</pre> + <p class="code"> + with pad-method-colon=after:</p> + <pre>-(void)insertKey: (id)key;</pre> + <p class="code"> + with pad-method-colon=before:</p> + <pre>-(void)insertKey :(id)key;</pre> + </div> + <p> + </p> + <hr /> + + <!-- * * * * * * * * * * * * Other Command Line Options * * * * * * * * * * * * --> + + <h3 id="_Other_Options">Other Options</h3> + + <p> + These are non-formatting options available for the command-line. They can also be included in an options + file.</p> + + <p id="_suffix"> + <code class="title">--suffix=<span class="option">####</span></code><br /> + Append the suffix #### instead of '.orig' to original file name (e.g. --suffix=<span class="option">.bak</span>. + If this is to be a file extension, the dot '.' must be included. Otherwise the suffix will be appended to the + current file extension.</p> + <p id="_suffix=none"> + <code class="title">--suffix=none / -n</code><br /> + Do not retain a backup of the original file. The original file is purged after it is formatted.</p> + <p id="_recursive"> + <code class="title">--recursive / -r / -R</code><br /> + For each directory in the command line, process all subdirectories recursively. When using the recursive option + the file name statement should contain a wildcard. Linux users should place the file path and name in double quotes + so the shell will not resolve the wildcards (e.g. "$HOME/src/*.cpp"). Windows users should place the file path + and name in double quotes if the path or name contains spaces.</p> + <p id="_dry-run"> + <code class="title">--dry-run</code><br /> + Perform a trial run with no changes made to the files. The report will be output as usual.</p> + <p id="_exclude"> + <code class="title">--exclude=<span class="option">####</span></code><br /> + Specify a file or subdirectory #### to be excluded from processing.</p> + <p> + Excludes are matched from the end of the file path. An exclude option of "templates" will exclude ALL directories + named "templates". An exclude option of "cpp/templates" will exclude ALL "cpp/templates" directories. You may + proceed backwards in the directory tree to exclude only the required directories.</p> + <p> + Specific files may be excluded in the same manner. An exclude option of "default.cpp" will exclude ALL files + named "default.cpp". An exclude option of "python/default.cpp" will exclude ALL files named "default.cpp" + contained in a "python" subdirectory. You may proceed backwards in the directory tree to exclude only the + required files.</p> + <p> + Wildcards are NOT allowed. There may be more than one exclude statement. The file path and name may be placed + in double quotes (e.g. ‑‑exclude="foo bar.cpp").</p> + <p id="_ignore-exclude-errors"> + <code class="title">--ignore-exclude-errors / -i</code><br /> + Allow processing to continue if there are errors in the "exclude=###" options.<br /> + This option lets the excludes for several projects be entered in a single option file. This option may be placed + in the same option file as the excludes. It will display the unmatched excludes. The following option will not + display the unmatched excludes.</p> + <p id="_ignore-exclude-errors-x"> + <code class="title">--ignore-exclude-errors-x / -xi</code><br /> + <code class="title"></code>Allow processing to continue if there are errors in the "exclude=###" options.<br /> + This option lets the excludes for several projects be entered in a single option file. This option may be placed + in the same option file as the excludes. It will NOT display the unmatched excludes. The preceding option will + display the unmatched excludes.</p> + <p id="_errors-to-stdout"> + <code class="title">--errors-to-stdout / -X</code><br /> + Print errors to standard-output rather than to standard-error.<br /> + This option should be helpful for systems/shells that do not have a separate output to standard-error, such as + in Windows95.</p> + <p id="_preserve-date"> + <code class="title">--preserve-date / -Z</code><br /> + Preserve the original file's date and time modified. The time modified will be changed a few microseconds to + force the changed files to compile. This option is not effective if redirection is used to rename the input + file.</p> + <p id="_verbose"> + <code class="title">--verbose / -v</code><br /> + Verbose display mode. Display optional information, such as release number, date, and statistical data.</p> + <p id="_formatted"> + <code class="title">--formatted / -Q</code><br /> + Formatted files display mode. Display only the files that have been formatted. Do not display files that + are unchanged.</p> + <p id="_quiet"> + <code class="title">--quiet / -q</code><br /> + Quiet display mode. Suppress all output except error messages.</p> + <p id="_lineend"> + <code class="title">--lineend=windows / -z1<br /> + --lineend=linux / -z2<br /> + --lineend=macold / -z3 + </code><br /> + Force use of the specified line end style. Valid options are windows (CRLF), linux (LF), and macold (CR). MacOld + style is the format for Mac OS 9 and earlier. OS X uses the Linux style. If one of these options + is not used, the line ends will be determined automatically from the input file.</p> + <p> + When <strong>redirection</strong> is used on Windows the output will always have Windows line ends. This option + will be ignored.</p> + <p> + </p> + <hr style="margin-left: -0.4in;" /> + + <!-- * * * * * * * * * * * * Command-Line Options * * * * * * * * * * * * --> + + <h3 id="_Command_Line_Only">Command Line Only</h3> + + <p>These options are available for the command-line only. They are NOT available in an options file.</p> + <p id="_options="> + <code class="title">--options=<span class="option">####</span></code><br /> + Specify an options file #### to read and use. It must contain a file path for the file. This will allow the file + name to be changed from astylerc or .astylerc.</p> + <p id="_options=none"> + <code class="title">--options=none</code><br /> + Disable the default options file. Only the command-line parameters will be used.</p> + <p id="_ascii"> + <code class="title">--ascii / -I</code><br /> + The displayed output will be ASCII characters only. The text will be displayed in English and numbers will not + be formatted. The short option must be by itself, it cannot be concatenated with other options.</p> + <p id="_version"> + <code class="title">--version / -V</code><br /> + Print version number and quit. The short option must be by itself, it cannot be concatenated with other + options.</p> + <p id="_help"> + <code class="title">--help / -h / -?</code><br /> + Print a help message and quit. The short option must be by itself, it cannot be concatenated with other + options.</p> + <p id="_html"> + <code class="title">--html / -!</code><br /> + Open the HTML help + file "astyle.html" in the default browser and quit. The short option must be by itself, it + cannot be concatenated with other options. The documentation must be installed in the standard install path (/usr/share/doc/astyle/html + for Linux or %PROGRAMFILES%\AStyle\doc for Windows). If installed to a different path use html=###.</p> + <p id="_html="> + <code class="title">--html=<span class="option">####</span></code><br /> + Open an HTML help file in the default browser using the file path #### and quit. An HTML file other than "astyle.help" + may be specified. The path may include a directory path and a file name, or a file name only (e.g. html=install.html). + If only a file name is used, it is assumed to be in the standard install path (/usr/share/doc/astyle/html + for Linux or %PROGRAMFILES%\AStyle\doc for Windows). In both cases the file name must include the html extension. + File paths containing spaces must be enclosed in quotes.</p> + <p> + On Linux the HTML file is opened using the script "xdg-open" from the install package "xdg-utils". This should + be installed by default on most distributions.</p> + <p> + Any HTML file can be opened by this option. The files you are likely to need are astyle.html (the default), install.html, + and index.html.</p> + <p id="_stdin="> + <code class="title">--stdin=<span class="option">####</span></code><br /> + Open a file using the file path #### as input to single file formatting. This is a replacement for redirection. + Do not use this with "<" redirection.</p> + <p id="_stdout="> + <code class="title">--stdout=<span class="option">####</span></code><br /> + Open a file using the file path #### as output to single file formatting. This is a replacement for redirection. + Do not use this with ">" redirection.</p> + <p> + </p> + <hr style="margin-left: -0.4in;" /> + + <p style="margin-left: -0.4in; text-align: center;"> + <a href="http://sourceforge.net/projects/astyle"> + <img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2319&type=16" alt="" /> + </a></p> + + <p> + </p> + <p> + </p> + +</body> + +</html> + diff --git a/astyle/doc/install.html b/astyle/doc/install.html new file mode 100755 index 0000000000000000000000000000000000000000..9b33c7addb4ff6a62ef6e249dbf1a617a35edaf3 --- /dev/null +++ b/astyle/doc/install.html @@ -0,0 +1,445 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> + +<head> + <title>Artistic Style - Install Information</title> + <meta http-equiv="Content-Language" content="en-us" /> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /> + <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" /> + <link href="styles.css" rel="stylesheet" type="text/css" /> +</head> + +<body> + + <h1>Artistic Style Install Information</h1> + + <p> + </p> + + <h3 id="Contents">Contents</h3> + + <p class="contents1"> + <a class="contents" href="#_Artistic_Style_Versions">Artistic Style Versions</a></p> + <p class="contents1"> + <a class="contents" href="#_Linux_Version">Linux Version</a></p> + <p class="contents2"> + <a class="contents" href="#_CodeBlocks_Linux">CodeBlocks Linux</a></p> + <p class="contents2"> + <a class="contents" href="#_GCC_Makefile">GCC Makefile</a></p> + <p class="contents2"> + <a class="contents" href="#_Clang_Makefile">Clang Makefile</a></p> + <p class="contents2"> + <a class="contents" href="#_Intel_Makefile">Intel Makefile</a></p> + <p class="contents2"> + <a class="contents" href="#_Other_Makefile_Targets">Other Makefile Targets</a></p> + <p class="contents1"> + <a class="contents" href="#_MacOS_Version">MacOS Version</a></p> + <p class="contents2"> + <a class="contents" href="#_Xcode">Xcode</a></p> + <p class="contents2"> + <a class="contents" href="#_MacOS_Makefile">MacOS Makefile</a></p> + <p class="contents1"> + <a class="contents" href="#_Windows_Version">Windows Version</a></p> + <p class="contents2"> + <a class="contents" href="#_Precompiled_Executable">Precompiled Executable</a></p> + <p class="contents2"> + <a class="contents" href="#_CodeBlocks_Windows">CodeBlocks Windows</a></p> + <p class="contents2"> + <a class="contents" href="#_Visual_Studio">Visual Studio</a></p> + <p class="contents1"> + <a class="contents" href="#_Other_Development_Environments">Other Development Environments</a></p> + <p class="contents1"> + <a class="contents" href="#_Compiler_Options">Compiler Options</a></p> + + <h3 id="_Artistic_Style_Versions">Artistic Style Versions</h3> + + <p> + astyle_x.x_linux.tar.gz is the <strong>Linux </strong>version of Artistic Style. It contains the source code, + documentation, and makefiles. The Linux Version compile instructions below give information for compiling the + source code.</p> + <p> + astyle_x.x_macos.tar.gz is the <strong>Mac OS </strong>version of Artistic Style. It contains the source code, + documentation, Xcode project files, and a makefile. The Mac OS Version compile instructions below give information + for compiling the source code.</p> + <p> + astyle_x.x_windows.zip is the <strong>Windows </strong>version of Artistic Style. It contains the source code, + documentation, Visual C project files, and an executable. The Windows Version compile instructions below give + information for compiling the source code.</p> + <p> + Only one platform is supported in each distribution package. If you use Artistic Style on more than one platform + you will need to download packages for each platform. The main difference in platforms is the build directories + and the line endings. Most compilers and development packages will accept any type of line ending. The source + code and documentation are the same for all distributions.</p> + + <h3 id="_Linux_Version">Linux Version</h3> + + <h4 id="_CodeBlocks_Linux">CodeBlocks Linux</h4> + + <p> + There are build folders for the following compilers. All compiler folders are in the "build" directory. + </p> + <ul> + <li><strong>cb-clang</strong> contains the workspace and project files for the Linux Clang Compiler.</li> + <li><strong>cb-gcc</strong> contains the workspace and project files for the Linux GCC Compiler.</li> + <li><strong>cb-intel</strong> contains the workspace and project files for the Linux Intel Compiler.</li> + </ul> + <p> + There are workspace and project files for each folder. All projects have at least Debug and Release + configurations. All output will be in the "bin" directory. </p> + <p> + The workspace contains the following projects.</p> + <ul> + <li><strong>AStyle </strong>builds the Artistic Style command line program (astyle). </li> + <li><strong>AStyle So </strong>builds the Artistic Style program as a shared object (libastyle.so). </li> + <li><strong>AStyle Java </strong>builds the Artistic Style program as a shared object (libastylej.so) that can + be called from a Java program. The Java Development Kit (JDK) is required for the project to compile. The + Project Properties must have an include path to the JDK include directories.</li> + <li><strong>AStyle A </strong>builds the Artistic Style program as a Static Library (libastyle.a). This can be + statically linked to a user program.</li> + </ul> + + <p> + For other Linux development environments, follow the instructions in <a href="#_Other_Development_Environments">Other + Development + Environments</a>. + </p> + + <h4 id="_GCC_Makefile">GCC Makefile</h4> + + <p> + To compile using the GCC compiler you must have GCC (3.1 or better) installed.</p> + <p> + The build has no autoconf dependency. To build the Artistic Style configurations, use the makefile located in + the astyle/build/gcc directory. The executables will be in the astyle/build/gcc/bin directory. To build the + command line configuration, enter the following:</p> + <pre>cd astyle/build/gcc<br />make +</pre> + <p> + To build the other astyle configurations, you can enter the file name or a symbolic name. Entering "make astyle" + or "make release" will build the command line configuration. Following are the symbolic names and file names (in + parens) of the various configurations:</p> + <ul> + <li><strong>release</strong> or <strong>astyle</strong> builds the Artistic Style command line program. This is the + default option. </li> + <li><strong>shared</strong> or <strong>libastyle.so</strong> builds the Artistic Style program as a shared + library. </li> + <li><strong>static</strong> or <strong>libastyle.a</strong> builds the Artistic Style program as a static + library. </li> + <li><strong>debug</strong> or <strong>astyled</strong> builds the Artistic Style command line program with debugging + information </li> + <li><strong>shareddebug</strong> or <strong>libastyled.so</strong> builds the Artistic Style program as a shared library + with debugging information. </li> + <li><strong>staticdebug</strong> or <strong>libastyled.a</strong> builds the Artistic Style program as a static library + with debugging information. </li> + <li><strong>all</strong> builds all the above configurations. + <p> + The following Java shared library builds are separate from the above. They include a Java Native Interface (JNI) + and require that the Java Development Kit (JDK) be installed. The environment variable JAVA_HOME should be defined. + It defines the install directory for the JDK. The makefile also has default install directories for Java 5 and + 6. If the compile cannot find the file jni.h, either set the variable or change the value in the + makefile.</p> + </li> + <li><strong>java </strong>builds the Artistic Style program as a shared library which includes the JNI (libastylej.so). + </li> + <li><strong>javadebug </strong>builds the Artistic Style program as a shared library which includes the JNI and debugging + information + (libastylejd.so).</li> + <li><strong>javaall </strong>builds all the above java configurations.</li> + </ul> + <p> + More than one configuration can be built at the same time. For example, to build all the release configurations + enter:</p> + <pre>cd astyle/build/gcc<br />make release shared static</pre> + <p> + The <a href="#_Other_Makefile_Targets">Other Makefile Targets</a> section contains additional target + options.</p> + + <h4 id="_Clang_Makefile">Clang Makefile</h4> + + <p> + Clang has a static analyzer that finds potential bugs in C/C++ and Objective-C programs. It can be run as a standalone + tool from the command-line, and runs in tandem with a build. There is a script file, analyze.sh, that will run + the analysis on Artistic Style.</p> + <p> + The build has no autoconf dependency. To build the Artistic Style configurations use the makefile located in the + astyle/build/clang directory. The executables will be in the astyle/build/clang/bin directory. To build the command + line configuration, enter the following:</p> + <pre>cd astyle/build/clang<br />make +</pre> + <p> + To build the other astyle configurations, you can enter the file name or a symbolic name. The configurations for + Clang are the same as for the <a href="#_GCC_Makefile">GCC Makefile</a>. More than one configuration can be + built at the same time. For example, to build all the release configurations enter:</p> + <pre>cd astyle/build/clang<br />make release shared static +</pre> + <p> + The <a href="#_Other_Makefile_Targets">Other Makefile Targets</a> section contains additional target + options.</p> + + <h4 id="_Intel_Makefile">Intel Makefile</h4> + + <p> + These procedures and the makefile are for recent versions of the compiler. They may not work for earlier versions. + Instructions for your compiler are in the compiler documentation file "get_started_lc.htm".</p> + <p> + To compile the source there are environment variables that must be set by running the compiler environment script + compilervars.sh (or compilervars.csh) with an argument that specifies the target architecture. If this has not + been done already enter: "<strong>source <install-dir>/bin/compilervars.sh <arg></strong>", + where <install-dir> is the directory where the compiler is installed and <arg> is <strong>ia32 </strong> + or <strong>intel64</strong>. If this is not done "make" will display an error message "*** The compiler environment + variables are not set." On an Intel x64 platform installed in the default directory the instruction would + be</p> + <pre>source /opt/intel/bin/compilervars.sh intel64</pre> + <p> + The build has no autoconf dependency. To build the Artistic Style configurations use the makefile located in the + astyle/build/intel directory. The output executables will be in the astyle/build/intel/bin directory. To build + the command line configuration, enter the following:</p> + <pre>cd astyle/build/intel<br />make</pre> + <p> + To build the other astyle configurations, you can enter the file name or a symbolic name. The configuration names + for Intel are the same as for the <a href="#_GCC_Makefile">GCC Makefile</a>. More than one configuration can be + built at the same time. For example, to build the entire debug configurations enter:</p> + <pre>cd astyle/build/intel<br />make debug shareddebug staticdebug</pre> + <p> + The <a href="#_Other_Makefile_Targets">Other Makefile Targets</a> section contains additional target + options.</p> + + <h4 id="_Other_Makefile_Targets">Other Makefile Targets</h4> + + <p> + The following makefile targets are available for GCC, Clang, Intel, and Mac.</p> + + <h5>clean</h5> + + <p> + Removes the object and executable files for all configurations.</p> + <p> + To remove the files for all configurations:</p> + <pre>make clean +</pre> + + <h5>cleanobj</h5> + + <p> + Removes the object files for all configurations. The executables will not be removed.</p> + <p> + To remove only the object files for all configurations:</p> + <pre>make cleanobj +</pre> + + <h5>install</h5> + + <p> + Installs the + astyle executable and documentation files. The default is /usr/bin for the executable and /usr/share/doc/astyle + for the documentation. You must have the appropriate permissions to use install.</p> + <p> + To install the astyle to the default directories:</p> + <pre>sudo make install +</pre> + <p> + To install astyle to a different bin directory set a value for the macro $(prefix). For example, to install the + executable to a user's home directory (/home/<i>user</i>/bin):</p> + <pre>sudo make prefix=$HOME install +</pre> + + <h5>uninstall</h5> + + <p> + Uninstalls the executable and documentation. You must have the appropriate permissions to use uninstall.</p> + <p> + To uninstall astyle from the default directories:</p> + <pre>sudo make uninstall +</pre> + <p> + To uninstall the files from a different directory set a value for the macro $(prefix). For example, to uninstall + the files from a user's home directory (/home/<i>user</i>):</p> + <pre> sudo make prefix=$HOME uninstall +</pre> + <p> + NOTE: The uninstall option will NOT remove the .astylerc files from the users' home directories. The files must + be removed individually for each user.</p> + + <h3 id="_MacOS_Version">MacOS Version</h3> + + <h4 id="_Xcode">Xcode</h4> + + <p> + Artistic Style workspace and project files for the Xcode development environment are available in the "build/xcode" + directory. A workspace can be used to build a single project or all the projects. The project files have Debug + and Release configurations. The following projects are available.</p> + <ul> + <li><strong>AStyle</strong> builds the Artistic Style command line program (astyle). </li> + <li><strong>AStyleA</strong> builds the Artistic Style program as a Static Library (libastyle.a). This can be statically + linked with an executable.</li> + <li><strong>AStyleDylib</strong> builds the Artistic Style program as a Dynamic Library (libastyle.dylib). It can + be used with C/C++, Objective C, C#, and Python programs.</li> + <li><strong>AStyleJava</strong> builds the Artistic Style program as a Dynamic Library (libastylej.dylib) that can + be called from a Java program. The Java Development (JDK) is required for the project to compile. The Project + Properties must have an include path to the JDK include directory. The output dylib can also be called from a + C++ or C# program.</li> + </ul> + + <h5>install</h5> + + <p> + Only the astyle executable is installed. The library project installs are sent to UninstalledProjects in + the Build directory. The following instructions are for the astyle executable and documentation files. The default + install directory is /usr/bin for the executable and /usr/share/doc/astyle for the documentation. You must have + the appropriate permissions to use install. If sudo is not used for the install, an error will occur during the + build.</p> + <p> + To install the astyle executable in the default directory:</p> + <pre>cd astyle/build/xcode +sudo xcodebuild install -project AStyle.xcodeproj +</pre> + <p> + A script is used to install the documentation + from the same directory.</p> + <pre>sudo bash install.sh +</pre> + + <h5>uninstall</h5> + + <p> + Uninstalls the executable and documentation. You must have the appropriate permissions to use uninstall.</p> + <p> + A script is used to uninstall astyle and the documentation:</p> + <pre>sudo bash uninstall.sh +</pre> + <p> + NOTE: The uninstall option will NOT remove the .astylerc files from the users' home directories. The files must + be removed individually for each user.</p> + + <h4 id="_MacOS_Makefile">MacOS Makefile</h4> + + <p> + The Artistic Style makefile compile uses the Mac OS "Command Line Tools". If you have Xcode 4.3 or newer + the command line tools, such as "make", are NOT installed by default. They must be downloaded and installed + separately. Once everything is successfully installed, you should see "make" and other command line + developer tools in /usr/bin.</p> + <p> + The build has no autoconf dependency. To build the Artistic Style configurations use the makefile located in the + astyle/build/mac directory. The executables will be in the astyle/build/mac/bin directory. To build the command + line configuration, enter the following:</p> + <pre>cd astyle/build/mac<br />make +</pre> + <p> + To build the other astyle configurations, you can enter the file name or a symbolic name. The configurations for + Mac are the same as for the <a href="#_GCC_Makefile">GCC Makefile</a>. More than one configuration can be + built at the same time. For example, to build all the release configurations enter:</p> + <pre>cd astyle/build/mac<br />make release shared static +</pre> + <p> + The <a href="#_Other_Makefile_Targets">Other Makefile Targets</a> section contains additional target + options.</p> + + <h3 id="_Windows_Version">Windows Version</h3> + + <h4 id="_Precompiled_Executable">Precompiled Executable</h4> + + <p> + In addition to the source files, the Windows distribution package contains an Artistic Style Win32 executable + (AStyle.exe). If you prefer to compile the executable yourself, pursue the following instructions.</p> + + <h4 id="_CodeBlocks_Windows">CodeBlocks Windows</h4> + + <p> + There are build folders for the following compilers. All compiler folders are in the "build" directory. + </p> + <ul> + <li><strong>cb-bcc32c</strong> contains the workspace and project files for the Embarcadero BCC32C Compiler.</li> + <li><strong>cb-mingw</strong> contains the workspace and project files for the MinGw or TDM_GCC Compilers.</li> + </ul> + + <p> + There are workspace and project files for each folder. All projects have at least Debug and Release configurations. + All output + will be in the "bin" directory.</p> + <p> + The workspace contains the following projects.</p> + <ul> + <li><strong>AStyle </strong>builds the Artistic Style command line program (AStyle.exe). </li> + <li><strong>AStyle Dll </strong>builds the Artistic Style program as a shared object (AStyle.dll). </li> + <li><strong>AStyle Java </strong>builds the Artistic Style program as a shared object AStylej.dll) that can + be called from a Java program. The Java Development Kit (JDK) is required for the project to compile. The + Project Properties must have an include path to the JDK include directories.</li> + <li><strong>AStyle Lib </strong>builds the Artistic Style program as a Static Library (astyle.lib). This can be + statically linked to a calling program.</li> + </ul> + <p> + For other development environments, follow the instructions in <a href="#_Other_Development_Environments">Other Development + Environments</a>. + </p> + + <h4 id="_Visual_Studio">Visual Studio</h4> + + <p> + There are solution and project files for several versions of Microsoft Visual Studio. Open an Artistic Style solution + file in the appropriate "build" directory. All projects have Debug, Release and Static configurations. + Debug file output will be in the "debug" directory. Release file output will be in the "bin" + directory. Static file output will be in the "binstatic" directory. The following solution files are + available.</p> + <ul> + <li><strong>All AStyle </strong>builds the release and the debug configurations for all the following. + </li> + <li><strong>AStyle </strong>builds the Artistic Style command line program (AStyle.exe). This project has an extra + "Static" option. It is the same as the "Release" build except that it is linked with a static runtime library. + This is needed if the executable is to be run on a system without Visual Studio installed. The builds for this + configuration are placed in a separate "binstatic" directory. </li> + <li><strong>AStyle Dll </strong>builds the Artistic Style program as a Dynamic Link Library (AStyle.dll). This will + also build an export library and a static library for linking the dll. </li> + <li><strong>AStyle Java </strong>builds the Artistic Style program as a Dynamic Link Library (AStylej.dll) that can + be called from a Java program. The Java Development (JDK) is required for the project to compile. The Project + Properties must have an include path to the JDK include and include/win32 directories. This is set in "Project + > Properties > C/C++ > General > Additional Include Directories". The default setting + is for the JDK to be installed in the default directory, but it may not be the most current release. The output + DLL can also be called from a C++ or C# program.</li> + <li><strong>AStyle Lib </strong>builds the Artistic Style program as a Static Library (libAStyle.lib). This can be + statically linked to a calling program.</li> + </ul> + + <h3 id="_Other_Development_Environments">Other Development Environments</h3> + + <p> + To use other development environments a project file must be built.</p> + <ul> + <li>Create a project using the development environment.</li> + <li>Add to the project all the .cpp and .h files in the "src" directory.</li> + <li>The Compiler Options section discusses the compiler options to use.</li> + <li>Compile.</li> + </ul> + + <h3 id="_Compiler_Options">Compiler Options</h3> + + <p> + No macro definitions are required to compile the executable. To compile as a static or shared (dynamic) library + define the macro ASTYLE_LIB. To compile a Java shared (dynamic) library define the macro ASTYLE_JNI. The + option ASTYLE_NO_EXPORTS is sometimes needed for static libraries to prevent compiler error and warning + messages. Use the appropriate compiler and linker options to compile the static or shared library. Add debug + options to compile the debug versions.</p> + <p> + Artistic Style is a small program and it is best to optimize for speed. The debug configurations are not usually + optimized. To optimize for speed in the release configurations, use the macro NDEBUG to remove asserts. If + necessary, use an option to activate the C++11 standards (-std=c++11 or -std=c++0x on most compilers). Use an + option that allows inline function expansion. Runtime Type Information (RTTI) is NOT needed and exceptions are + NOT used. Use whole program optimization if your compiler supports it. There may be other options you can use + depending on the compiler. </p> + <p> + </p> + + <p style="margin-left: -0.4in; text-align: center;"> + <a href="http://sourceforge.net/projects/astyle"> + <img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2319&type=16" alt="" /> + </a></p> + + <p> + </p> + <p> + </p> + +</body> + +</html> + diff --git a/astyle/doc/news.html b/astyle/doc/news.html new file mode 100755 index 0000000000000000000000000000000000000000..ebe7b948d3ba1abcb8662545a9b36b22a2c886ab --- /dev/null +++ b/astyle/doc/news.html @@ -0,0 +1,660 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> + +<head> + <title>Artistic Style - News</title> + <meta http-equiv="Content-Language" content="en-us" /> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /> + <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" /> + <link href="styles.css" rel="stylesheet" type="text/css" /> +</head> + +<body> + + <h1>Artistic Style News</h1> + + <p> + </p> + + <h3>Artistic Style 3.0 (April 2017)</h3> + + <p> + In the Artistic Style documentation, in General Information, Other Considerations, there is a list of + terminology used for special characters used in programming. The terms used by Artistic Style have been + different than is used by Visual Studio, Clang, and others. In this release the terms used by Artistic Style + have been changed to the ones most commonly used in programming documentation. The following chart indicates + the changes.</p> + + <center> + <table> + <thead> + <tr> + <td><strong>NEW</strong></td> + <td></td> + <td><strong>OLD</strong></td> + </tr> + </thead> + <tbody> + <tr> + <td>braces or curly braces</td> + <td> { } </td> + <td>brackets</td> + </tr> + <tr> + <td>parens or round brackets</td> + <td> ( ) </td> + <td>parens</td> + </tr> + <tr> + <td>square brackets</td> + <td> [ ] </td> + <td>block parens</td> + </tr> + <tr> + <td>angle brackets</td> + <td> < > </td> + <td>angle brackets</td> + </tr> + </tbody> + </table> + </center> + + <p> + Parens and angle brackets do not change. Brackets has been changed to braces. Block parens has been changed to + square brackets. Brackets can now collectively refer to the group containing round brackets (parens), square brackets, + and angle brackets. The documentation has been updated and the variable names in the source code have been + changed. </p> + <p> + There are four options affected by the change, "break-closing-brackets", "add-brackets", "add-one-line-brackets", + and "remove-brackets". These have been changed to the corresponding "break-closing-braces", + "add-braces", "add-one-line-braces", and "remove-braces". Also, the option "max-instatement-indent" + has been changed to "max-continuation-indent". The old options and method names have been depreciated, + but will continue to be accepted for the next several releases. </p> + <p> + The source code now uses the C++11 standard. Compilers that need a standard declared should use C++11. Visual + Studio 2010 is currently still currently supported. The classes were made independent of the containing + source code files (the source files contain multiple classes). The dependency on global variables in the console + build was removed. </p> + <p> + A new option, "indent-after-parens", will indent continuation lines following lines that contain an + opening paren '(' or an assignment '='. This includes function definitions and declarations + and return statements. This option may be preferred for editors displaying proportional fonts.</p> + <p> + A new option, "attach-closing-while", will attach the closing "while" of a + "do-while" statement to the closing brace. It has precedence over both the brace style and the break + closing braces option. </p> + <p> + The option "break-closing-braces" has been included in "style=stroustrup". This is the + correct style according to <a href="https://en.wikipedia.org/wiki/Indent_style#Variant:_Stroustrup" target="_blank" + title="open new window">Wikipedia</a>. The new option "attach-closing-while" is not included in + the style but can be used if you want. If there is a problem with the new format, change to the K&R style + using the same options as for Stroustrup.</p> + <p> + If you are using Windows XP, there is a download file available that has an XP compatible executable. Artistic + Style will still compile with Visual Studio 2010.</p> + <p> + Thanks to Jochen Tucht and Matthew Woehlke for their contributions.</p> + <p> + The following are additional topics.</p> + + <h4>Version 3</h4> + + <p> + Artistic Style was written in the 1990's when personal computers were much slower and compilers were not as + sophisticated as today. It used a lot of global variables instead of class members. In previous releases, classes + were created for the astyle_main.h source code. With this release, the classes have been made independent + of the source file containing them and the shared and global data has been eliminated. The classes could now be + separated into separate source files. They have not been actually separated because it seems more convenient + to leave them combined.</p> + <p> + As explained previously, the terminology for special characters has been changed to agree with various + development environments and compilers. The variable and method names in the source code were changed as well + as the documentation. This was a major renaming. If not for the "rename" refactoring feature in Visual + Studio, and the AStyleTest programs, it would probably not have been attempted.</p> + <p> + Artistic Style has also started using C++11. Older compiler versions and compilers without C++11support cannot + be used. If your compiler requires a compiler directive for C++, such as -std=c++11 or -std=c++0x, it will + need to be used. </p> + + <h4>Library File Names</h4> + + <p> + The shared library object (DLL) compile was originally intended to be a local library used by a single program. + Users could update the library at their convenience. Recently, it has started being distributed as a system library + for some distributions. In the past was not maintained for doing this. Since it is already being offered as + a distribution, the library soname on Linux has been standardized. </p> + <p> + It can still be used as a local or a static library if you want to control the changes. Or the system library + can be used. The system library version, of course, may change at any time. With this release the system + library will be available on Debian based systems, as well as possibly others.</p> + <p> + The Windows library name has been changed also. This Windows version is AStyle30.dll. The "30" refers + to the Artistic Style release number "3.0". The Linux library name is a soname version number, not the + Artistic Style release number.</p> + + <h4>Artistic Style Wx</h4> + + <p> + There is a new GUI test program AStyleWx that uses wxWidgets. This replaces the old AStyleWin program. AStyleWx + is multi-platform and has more features simply because they are easier to implement with wxWidgets.</p> + <p> + It has download files and a website in a new sub-project directory of Artistic Style. The downloads contain + source code, documentation, and scripts. The Windows download contains an executable. The needed Artistic Style + source files are included. </p> + <p> + It is licensed under the MIT license. The source code may be used and modified for any purpose you + choose. Developers using Artistic Style in another project may use any part of AStyleWx in their project. The + modified source code does NOT need to be made available to others.</p> + + <h4>Code::Blocks Support</h4> + + <p> + Code::Blocks is a free, open-source cross-platform IDE that supports multiple compilers. It currently gets over + 100,000 downloads per week. It is used by Artistic Style to test compilers on various systems. Code::Blocks build + files for several free compilers are now provided with the Artistic Style release. The "Install Information" + contains additional information.</p> + + <h4>Embarcadero Compiler</h4> + + <p> + Embarcadero is offering a new, free, BCC32C C++ compiler. It includes C++11 language support, the Dinkumware + Standard Template Library, and the Embarcadero Runtime Library. Included are a linker, a + resource compiler, and a number of command line tools. It is currently for Win32 only. There is more + information at their <a href="https://www.embarcadero.com/free-tools/ccompiler" target="_blank" + title="open new window">Free Tools</a> web page. They are also currently offering a free debugger and two + different + development environments.</p> + + <h4>Naming Conventions</h4> + + <p> + If you use cppcheck, it has an add-on to check naming standards for functions and variables by using regular + expressions. Cppcheck must be run first to generate ".dump" files. The Python program, naming.py, + can then be run to check the names. It is basically a shell that you will probably want to modify for regular + use. The add-ons must be installed with cppcheck for naming.py to be available.</p> + + <h4>WinMerge 2011</h4> + + <p> + WinMerge 2011 is a fork of the original WinMerge application published on SourceForge by Thingamahoochie + Software. It is has removed the ATL/MFC dependencies and added some useful features. It uses Artistic Style + to format the source code.</p> + + <h4>Whatstyle</h4> + + <p> + Whatstyle finds a code format style that fits given source files. This program looks at your source code and + generates a style definition that fits its original formatting style as closely as possible. + Several formatters and programming languages are supported. It is written in Python and has an interesting + method for finding the style options. + </p> + + <h3>Artistic Style 2.06 (December 2016)</h3> + + <p> + A new bracket style option, "style=mozilla", has been added. It uses linux brackets with + opening brackets broken from classes, structs, enums, and function definitions. Brackets are attached to everything + else, including namespaces, arrays, and statements within a function.</p> + <p> + A new option, "break-one-line-headers" will break a header (if, while, else, etc...) from a following + statement on the same line. There is more information in the "Formatting Options" section + of the documentation. + </p> + <p> + A new option, "pad-comma", will add a space following a comma. The option "pad-oper" + has not been changed and will also add a space following a comma.</p> + <p> + A new option, "indent-continuation", will add extra indents to continuation lines following a line that + ends with an opening paren '(' or an assignment '='. This includes function definitions and declarations. + There is more information in the "Indentation Options" section of the documentation.</p> + <p> + All spaces before a comma are now removed. Use the "disable formatting" comment tags if there are arrays + with vertical alignment where this is not wanted.</p> + <p> + A correction has been made to the Pico style indentation of one line blocks. And there is a fix to always compute + the indentation of a one line block. If you use Pico style with an indentation greater than 2, you may have a + lot of changes made to the code.</p> + <p> + New Objective-C options "pad-return-type" and "unpad-return-type" will add or remove space padding after + the Objective-C return type in a method definition. They are described in the "Objective-C" section of the + documentation.</p> + <p> + New Objective-C options "pad-param-type" and "unpad-param-type" will add or remove space padding after + the Objective-C parameter type in a method definition. They are described in the "Objective-C" section of the + documentation.</p> + <p> + The Objective-C "align-method-colon" option is now applied to Objective-C method calls in + addition to method declarations and definitions. The method call colons will be aligned, if possible. If this + option is not declared, the method calls will align on the first keyword. See the astyle documentation for an + example.</p> + <p> + The Objective-C "align-method-colon" has been changed for long keywords. + For multi-line arguments when the first keyword is shorter than the others the colons are aligned on the + longest line instead of the first line. The alignment includes room for the indentation. This aligns all colons + after the first line for a better appearance. Arguments that do not have a short keyword in the first line will + remain the same. This style conforms to the Google Objective-C style.</p> + <p> + Processing for C++14 single-quote digit separators has been added.</p> + <p> + Translations have been added for Bulgarian, Estonian, Greek, Hungarian, Norwegian, and Romanian. The translations + were done with an automated translation program, Google Translate, so they may not be the best translation possible. + The translations are at the end of ASLocalizer.cpp in the form of an English-Translation pair. If you correct + a translation, send the source as a bug report and it will be included in the next release. To add a language, + see "Internationalization" in the "General Information" section of the documentation.</p> + <p> + The C# example, in the Developer Information has been updated. Objects for the AStyle callback functions are no + longer required. These have been removed and the delegates used instead.</p> + <p> + There is a new C# example in the Developer Information, that loads the AStyle shared library using explicit linking. + This allows the shared library name to be dynamically changed so that a program compiled with "Any CPU" + can load + either a 32-bit or 64-bit shared library at run-time. It runs on both Windows and Linux.</p> + <p> + Visual Studio Code, the text editor from Microsoft, has an Artistic Style extension. The extension runs from the + Visual Studio Code menu and is controlled by entries in the User Settings file. It can be installed from Visual + Studio Code. There are links to the websites on the Artistic Style Links page. </p> + <p> + Thanks to David Faure for his contribution.</p> + <p> + The following are additional topics.</p> + + <h4>New Software License</h4> + + <p> + The Artistic Style software license has changed. It is now under the MIT license. This is a permissive license + which can be used in proprietary software and does NOT require modified Artistic Style source code be made available. + It is compatible with the GNU General Public License (GPL) and most other software licenses. The change was made + to remove restrictions on using the software and to make it available for any project that wants to + use it.</p> + + <h4>Visual Studio 2015 and 2017 UTF-8 Files</h4> + + <p> + In order to be used on both Linux and Windows, the ASLocalizer.cpp UTF-8 file in Artistic Style does not + contain a Byte Order Mark (BOM). With Visual Studio 2015 there has been a change in how UTF-8 files + without a BOM are processed. The new procedure is described + <a href="https://blogs.msdn.microsoft.com/vcblog/2016/02/22/new-options-for-managing-character-sets-in-the-microsoft-cc-compiler/" + target="_blank" title="open new window">here</a>. It affects only the language translations in the ".exe" + file. The shared libraries and static libraries are not affected. It is necessary only if you are using a translation + other than English.</p> + + <p> + In addition to the "auto detect" option in Tools > Options... > Text Editor > General, an + additional compiler option is required. The option "/source‑charset:utf‑8" must be added + to the project properties at C++ > Command Line > Additional Options. Since the non‑unicode files + in Artistic + Style are ASCII, the option can be applied to the entire project instead of just one file. This option has been + added in the files distributed with Artistic Style. There is also a new "/validate‑charset" option, + which gets turned on automatically with the above option. This switch enables the validation of the UTF-8 input + files.</p> + <p> + This compiler option was not available until Update 2 of Visual Studio. If you are using an earlier version of + 2015, a BOM should be added to the file using File > "Advanced Save Options". Change the encoding + to "Unicode (UTF-8 with signature) - Codepage 65001". </p> + <p> + In the above "Visual C++ Team Blog" Microsoft mentions that in a future major release of the compiler, + they would like to change the default handling of BOM-less files to assume UTF-8.</p> + + <h4>Assignment Operator Alignment</h4> + + <p> + Visual Studio 2013 and 2015 have an Edit option "Align Assignments" that will align assignment operators + across multiple lines. There is also an extension named "Code alignment" that will align the code on + other items as well. Other development environments may have something similar. These will selectively align the + data and allow for customization of the format.</p> + <p> + These options and extensions can be used with Artistic Style. If you choose to do this, the space padding will + be maintained and the alignment will be preserved.</p> + + <h4>Coding Styles</h4> + + <p> + Coding style, or programming style, is a set of rules or guidelines used when writing the source code. It is + often claimed that following a particular programming style will help in reading and understanding source code + conforming to the style, and help to avoid introducing errors.</p> + <p> + This Artistic Style distribution has a new "file" folder containing AStyle options files for various + coding styles. Using the option files will give approximately the indicated coding style. The files can be used + as they are, or modified as desired.</p> + + <h4>Artistic Style Wx</h4> + + <p> + There is a new GUI test program AStyleWx that uses wxWidgets. This replaces the old AStyleWin program. AStyleWx + is multi-platform and has more features simply because they are easier to implement with wxWidgets.</p> + <p> + It has download files and a website in a new sub-project directory of Artistic Style. The downloads contain + source code, documentation, and scripts. The Windows download contains an executable. The needed Artistic Style + source files are included. </p> + <p> + It is licensed under the MIT license. The source code may be used and modified for any purpose you + choose. Developers using Artistic Style in another project may use any part of AStyleWx in their project. The + modified source code does NOT need to be made available to others.</p> + + <h4>Windows XP</h4> + + <p> + The executable in the Windows distribution package is now compiled with a Visual Studio version that will no + longer work on Windows XP. Beginning with Visual Studio 2012, auto-vectorization tries to make loops run + faster by automatically vectorizing the code. Auto-vectorization is on by default, and there are no compiler + switches, #pragmas, or hints to disable it. It uses SSE instructions not available in Windows XP. Microsoft ended + support and updates for XP on April 8, 2014, and the usage share percentage continues to decrease.</p> + <p> + To compile on a non-XP machine for use on XP, using a compiler other than Visual Studio should always + produce an XP executable. Using Visual Studio 2010 or earlier should always produce an XP executable. If + you are using Visual Studio 2012, 2013, or 2015 on a non-XP machine, do the following for the Artistic Style + configuration you want to use:</p> + <ul> + <li>"Windows XP Support for C++" must be installed. It is available as an option in the Visual Studio install + and can be installed as a modification to the current install.</li> + <li>In the Artistic Style Properties, change General > Platform Toolset, to "Windows XP" for your Visual + Studio version.</li> + <li>In the Artistic Style Properties, change C/C++ > Preprocessor > Preprocessor Definitions to include + _USING_V110_SDK71_.</li> + <li>Change other Properties if you want, such as Output Directory or Target Name.</li> + <li>Compile. The output should be executable on Windows XP. It will also execute on the later versions of Windows. + </li> + </ul> + <p> + In newer releases of Visual Studio 2015, the "Universal CRT" files have been moved. There is a + notification <a href="https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/">here</a>. + To compile using XP there may need to be additional include and library directories added. If the compile gets + errors add the appropriate directories to the project properties.</p> + + <h3>Artistic Style 2.05 (November 2014)</h3> + + <p> + Release 2.05.1 (December 2014) is a maintenance release and no new features were added. A list of changes is in + the Release Notes. The following information is for the original 2.05 release.</p> + + <p> + A new bracket style option, "style=vtk", has been added. It uses indented brackets, like Whitesmith, + except opening brackets for classes, functions, and methods are not indented. A complete description of the VTK + style is available at the "Visualization Toolkit" website (http://www.vtk.org/).</p> + <p> + A new preprocessor indent option "indent-preproc-block" will indent preprocessor block statements one additional + indent. The block must be top-level, or included within a namespace, and there are restrictions on what can be + indented. + The option is described in the "Indentation Options" section of the documentation.</p> + <p> + A new option, "dry-run", will run Artistic Style without updating the files. The report will be output as + usual.</p> + <p> + Formatting of source code may now be disabled for portions of a program by embedding special comment tags in the + program. These are described in a new "Disable Formatting" section of the documentation. They work the + same as in other formatters. There are tags to disable formatting for a block of code, and a tag to disable formatting + of a single line. This should allow any custom formatting to be retained.</p> + <p> + The product version number has been added to the filename of shared library (DLL) compiles. This will allow multiple + versions of a shared library on the same system without conflicts.</p> + <p> + An attribute '__attribute__ ((visibility ("default")))' has been added to exported functions + on Linux shared libraries. This allows the option "-fvisibility=hidden" to be used on dynamic library + compiles. According to the GNU documentation, "Using this feature can very substantially improve linking + and load times of shared object libraries, produce more optimized code, provide near-perfect API export and prevent + symbol clashes. It is strongly recommended that you use this in any shared objects you distribute."</p> + <p> + Improvements have been made in the formatting of C++11 uniform initializers (enclosed by brackets). The opening + bracket will not be space padded unless it is padded initially. The closing bracket will not be broken from the + final line unless it is broken initially. And the known problems with uniform initializers in class constructors + have been fixed.</p> + <p> + The Windows compiler definition ASTYLE_NO_VCX (no Visual Studio exports) has been changed to ASTYLE_NO_EXPORTS. + It is sometimes needed for static libraries on other compilers to prevent error and warning messages.</p> + <p> + Qt and Boost macros foreach, forever, Q_FOREACH, and Q_FOREVER will now be recognized as headers.</p> + <p> + The main documentation for Artistic Style is in HTML format. Until now there has not been a way to display it + from the astyle console program. A new option, "html" or "-!" will display the help documentation in the default + browser. This documentation is more complete than the astyle "help" option. It includes examples, and has an index + for easier navigation. Since astyle is typically run from a script this should allow an easy way to access the + documentation. The option is available only from the command line.</p> + <p> + The new "html" option assumes the documentation is installed in the standard install path. This is /usr/share/doc/astyle/html + for Linux and the path %programfiles%\AStyle\doc for Windows. If it is installed to a different directory, use + the variation "html=<actual_install_path>astyle.html. This option can also be used to open other HTML files. + More information is in the "Command Line Only" section of the documentation.</p> + <p> + The "html" option on Linux uses the script "xdg-open" from the install package "xdg-utils" to find the default + browser. This should be available on most systems. If it is not available on your system you can file a + bug report requesting a change. It would be helpful if you could determine how it is done before filing the report. + You can also file a bug report if the documentation is not installed to the above "default" directories. The HTML + documentation takes quite a bit of effort to maintain and I would like to make it easily available.</p> + <p> + The "help" option has been changed to send the output to stdout instead of stderr. This will allow piping and + redirection of the output. A common way to use the option on Linux is "astyle --help | less", which + will page the display. The "version" option has also been changed to stdout.</p> + <p> + A shared library error handler argument has been changed from "char*" to "const char*". In + some cases this may cause compile errors in a user program until the references have been changed.</p> + <p> + The "Indent Style" topic on Wikipedia states that the "ANSI" style refers to K&R style brackets + and not Allman style as used by Artistic Style. The option "style=ansi" is therefore being deprecated and will + be removed in a future release. Use one of the other long options instead (style=allman, style=bsd, or + style=break).</p> + <p> + Some of the documentation has been removed from the distribution package. It still contains all files needed to + install and run Artistic Style. The included files can be used without an Internet connection.</p> + <p> + There are now build files available for Xcode on Mac. The makefile is still available for those who want it. Both + now use the LLVM Clang compiler. There has been a + change to the makefile debug locations to make them similar to Xcode. The "Install Instructions" have + been updated for both.</p> + <p> + The Python Example in the Developer Information now supports Iron Python. The + programming instructions are sometimes different since the ctypes module works differently. The example script + documents the differences. If you use Python Tools for Visual Studio, it now installs in the Express editions + (beginning with release 2.1). Node.js can also be installed in Visual Studio Express.</p> + <p> + The executable in the Windows distribution package is now compiled with Visual Studio 2013 and will no longer + work on XP. If you are using XP, Artistic Style will need to be recompiled on the XP machine.</p> + <p> + A new <a href="http://www.visualstudio.com/news/vs2013-community-vs" target="_blank" title="open new window">Visual + Studio Community Edition</a> has been released. It is free, combines all of the Express editions into a single + development environment, and allows the addition of Visual Studio extensions. There is an + <a href="https://visualstudiogallery.msdn.microsoft.com/2f3f04cd-2866-4e47-a671-d1cc9cc3fb02" target="_blank" + title="open new window">AStyle Extension</a> available for installation. It has a graphic interface, adds + menu entries, and can be used from within Visual Studio. To install it search the "Extensions and Updates", + "Online" entry for "astyle".</p> + <p> + Thanks to Peter A. Bigot, HyungKi Jeong, David Faure, and Carl Moore for their contributions.</p> + + <h3>Artistic Style 2.04 (November 2013)</h3> + + <p> + With a new Artistic Style release some unchanged source files will be formatted because of changes to Artistic + Style. You may want to format your source before making program changes in order to bring it up to date.</p> + <p> + A new programming language, Objective‑C, has been added to Artistic Style. Four new options, "align‑method‑colon", + "pad‑method‑colon=", "pad‑method‑prefix", and "unpad‑method‑prefix" have been + added to format the methods. The options are described in a new "Objective‑C" section in the documentation. + These new options affect only Objective‑C source code. They have no effect on the other programming + languages.</p> + <p> + Because of the longer continuation indents sometimes needed for Objective‑C, the option "max-instatement-indent" + may need to be increased. If you are not getting the paren and block paren alignment you want, try increasing + this value. The default minimum is 40 and the maximum is 120.</p> + <p> + A new bracket style option, "style=google", has been added. It uses attached brackets and indents the class access + modifiers one-half indent. A complete description of the Google style is available at the google‑styleguide + website (https://code.google.com/p/google-styleguide/). The website has standards for several programming languages + along with a python program to verify the style and an emacs script for using the style.</p> + <p> + A new indent option "indent-modifiers" will indent class access modifiers (public, protected, or 'private) one-half + indent. The rest of the class is not indented. It is described in the "Indentation Options" section of the + documentation.</p> + <p> + Four new bracket modify options, "attach-namespaces", "attach-classes", "attach-inlines", and "attach-extern-c", + can be used to modify your selected bracket style. They are described in a new "Bracket Modify Options" section + of the documentation.</p> + <p> + A new option, "remove-brackets", will remove brackets from conditional statements. The statement must be a single + statement on a single line. It is described in the "Formatting Options" section of the documentation.</p> + <p> + A new option, "indent-preproc-cond", will indent preprocessor conditional statements (#if #elif, #else, #endif). + It is described in the "Indentation Options" section of the documentation. The option "indent-preprocessor" has + been deprecated and will be removed in a future release. Use "indent-preproc-define" instead. The processing of + preprocessor #define statements has not changed.</p> + <p> + A new option, "remove-comment-prefix", will remove a leading '*' from multi-line comments. It is described in + the "Formatting Options" section of the documentation. With the syntax coloring of modern editors a leading '*' + for comment lines is not as useful as it once was. The current trend is toward code that is easier to maintain. + The idea is that a style that is hard to maintain will discourage modification and updating. The converted style + should retain most of the formatting within the comment and result in a comment that is easier to maintain. For + consistency the option also indents multi-line comments that are not preceded by the '*'. This may slightly modify + the indentation of any commented-out code.</p> + <p> + The option "pad-first-paren-out" was fixed to not pad if the following paren is empty. This makes the option consistent + with "pad-paren-out". To fix empty parens that have been padded run with the option "unpad-paren" in addition + to "pad-first-paren-out". This needs to be done only once.</p> + <p> + Processing of C++11 raw string literals has been added.</p> + <p> + The compiler definition ASTYLE_NO_VCX (no Visual Studio exports) has been changed to ASTYLE_NO_EXPORTS and can + be used with any Windows compiler. The Clang compiler needs this option to avoid errors on dynamic libraries. + It removes the "__declspec(dllexport)" + definition from exported functions. Linux compilers do not use this.</p> + <p> + A new shared object (DLL) entry point, AStyleMainUtf16, has been added for processing C# UTF-16 strings. C# does + not have built in functions for converting the UTF-16 strings to UTF-8. This entry point will accept UTF-16 strings, + format the source code, and return UTF-16 strings. The error handling function and version number still use UTF-8 + strings. The C# example program in the "Developer Information" shows the new calling procedure. Changes from the + previous release are marked in the example.</p> + <p> + C# strings are UTF-16 on both Windows and Linux. C# does not use the UTF-32 wchar_t strings on Linux. Qt also + uses UTF-16 on both Windows and Linux, but has built in UTF-8 conversion functions. Qt strings can be converted + to UTF-8 by Qt, or the new entry point can be used. There may be other "managed code" applications on Linux that + use UTF-16.</p> + <p> + The "Links" page has two new sections for links mentioned in previous versions of Artistic Style. It links to + free software and other information.</p> + <p> + The "Developer Information" section has a new example and download for calling Artistic Style from an Objective‑C + program. Since it is another "C" language the only thing needed is to link the program with a library build of + Artistic Style. The example was developed on Windows and Linux using the GNUstep project. Since the example is + a console program the problems with the GNUstep GUI have been avoided. It has not been tested on a Mac, but should + be close to working. The "Developer Information" section also has a new page for "Objective‑C on Windows + and Linux" which has information on compiling and running the example on those systems.</p> + <p> + The executable included in the Windows distribution was compiled with Visual Studio 2010 (platform toolset v100). + Higher releases contain dependencies on Windows API functions that exist only on Windows Vista, Windows 7, and + Windows 8. This means that applications built with a Visual Studio 2012 C++ compiler would fail to load and execute + on Windows XP.</p> + <p> + If you are using Windows Vista or higher, and have a Visual Studio 2012 or higher compiler available, recompiling + will probably result in faster execution. If you use a compiler other than Visual Studio, you can probably get + better execution by compiling using the C++11 standards. Artistic Style uses a lot of string vectors and the new + move semantics will probably result in faster execution.</p> + <p> + Thanks to Evmenov Georgiy, Matthew Woehlke, Jiang, Ruzzz, and beta100100 for their contributions.</p> + + <h3>Artistic Style 2.03 (April 2013)</h3> + + <p> + With a new Artistic Style release some unchanged source files will be formatted because of changes to Artistic + Style. You may want to format your source before making program changes in order to bring it up to date.</p> + <p> + A new option, "max-code-length=#" or "xC#", will limit the length of code on a line. A new option "break‑after‑logical", + or "xL", will modify a line break for conditionals. See the documentation for details.</p> + <p> + A new option, "pad-first-paren-out" or "xd", will pad only the first paren in a series on the outside. See the + documentation for details.</p> + <p> + A new option, "indent=force-tab-tab=#" or "xT#", will allow force tab indents with a tab length that is different + than the indent length. See the documentation for details.</p> + <p> + The short option for delete-empty-lines has changed from "xd" to "xe".</p> + <p> + The C++11 standard for range-based "for" loops, "enum" with a base type, and rvalue references is now supported. + The formatting of rvalue references is determined from the existing "align-pointer" and "align-reference" + options.</p> + <p> + Closing the ending angle brackets of templates is now allowed by the C++11 standard. A new option, "close-templates" + or "xy", will close the whitespace in the angle brackets of template definitions. Be sure your compiler supports + this before making the changes.</p> + <p> + The C/C++ keyword 'extern "C"' in a preprocessor no longer causes an extra indent.</p> + <p> + Formatting of C++/CLI managed pointers (the '^' character) has been added to the "align-pointer" + option.</p> + <p> + The breaking of switch "default" statements has been fixed. The "default" statements + that have been incorrectly broken will be fixed in this release.</p> + <p> + The byte order mark (BOM) has been removed from ASLocalizer.cpp for all platforms. The encoding of the file is + UTF-8. Many Windows editors can now recognize UTF-8 encoding without the BOM. Visual Studio has an option that + needs to be set. With others, such as CodeBlocks, identification is automatic. On Linux, UTF-8 is the default + encoding.</p> + <p> + Translations have been added for Dutch, Finnish, Italian, Japanese, Korean, Polish, Portuguese, Russian, Swedish, + and Ukrainian. The translations were done with an automated translation program, Google Translate, so they may + not be the best translation possible. The translations are at the end of ASLocalizer.cpp in the form of an English‑Translation + pair. If you correct a translation, send the source as a bug report and it will be included in the next release. + To add a language, see "Internationalization" in the "General Information" section of the documentation. Send + the addition as a bug report and it will be included in the next release.</p> + <p> + There is a new Linux makefile for the Clang Compiler. Clang is a free compiler can be installed as a package on + many Linux distributions. Some of its features are fast compiles, low memory use, expressive diagnostic messages, + and GCC compatibility. It includes a static analyzer tool that finds potential bugs in your source code. An experimental + version can be installed on a Windows platform. There is more information in the Install Information + documentation.</p> + <p> + Visual Studio automatically creates an import library and an export file when you link a program that contains + exports. It will do this for even a static library if it contains a __declspec(dllexport) definition. The Artistic + Style library (ASTYLE_LIB) build contains such exports, which causes an import library and export file to be created + when they may not be needed. A new preprocessor definition, ASTYLE_NO_VCX (no Visual Studio exports) can be declared + to eliminate the files from the output. Use this only for static libraries or when the AStyle source is included + in the compile. Do NOT use this when compiled as a shared (dynamic) library. It is effective only for Visual Studio + 2012. It will NOT work with previous versions. It has no effect with other compilers since they require a separate + option to create the import library and export files.</p> + <p> + The executable included in the Windows distribution was compiled with Visual Studio 2010 (platform toolset v100). + Visual Studio 2012 (platform toolset v110) contains dependencies on Windows API functions that exist only on Windows + Vista, Windows 7, and Windows 8. This means that applications built with a Visual Studio 2012 C++ compiler would + fail to load and execute on Windows XP. Artistic Style was therefore compiled with Visual Studio 2010 to work + on computers using Windows XP.</p> + <p> + If you are using Windows Vista or higher, and have the Visual Studio 2012 compiler available, recompiling with + Visual Studio 2012 will probably result in faster execution. The Windows distribution has Visual Studio 2012 project + files available.</p> + <p> + If you use a compiler other than Visual Studio, you can probably get better execution by compiling using the C++11 + standards. Artistic Style uses a lot of string vectors and the new move semantics will probably result in faster + execution. (To use C++11 on GCC and MinGW use the option --std=c++0x). This may change on future compiler + releases.</p> + <p> + The "Developer Information" page has a new example and download for calling Artistic Style from a Python script. + It will run with both Python 2 and Python 3. Using Python 3 shows an example of formatting a Unicode string with + Artistic Style. Unicode strings must be encoded to UTF-8 before formatting and decoded back to Unicode afterward. + The example script shows the technique for doing this. It also shows how to set up the function pointers and allocate + memory in Python.</p> + <p> + If you use Visual Studio on Windows, it can now be used for Python development. Python Tools for Visual Studio + (PTVS) is a free and open source plug-in for Visual Studio 2010 that supports Python and Iron Python. Other interpreters + such Jython can be added. It can be easily switched between Python versions or different interpreters. But the + best thing is the Visual Studio debugging support using the .NET debugger and the normal Visual Studio debugger. + It enables you to set break points, step through functions, change the current statement, inspect local variables, + and perform other operations while debugging. It is best to use it with a project file, a minor irritation for + single page scripts. And there are some minor bugs. But overall it works quite well.</p> + <p> + Thanks to Christopher Sean Morrison, Keith OHara, louis6g, and J for their contributions.</p> + <p> + </p> + <p> + <strong>Previous releases are available in the + <a href="http://astyle.sourceforge.net/newsArchives.html">News Archives</a>.</strong></p> + <p> + </p> + + <p style="margin-left: -0.4in; text-align: center;"> + <a href="http://sourceforge.net/projects/astyle"> + <img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2319&type=16" alt="" /></a></p> + + <p> + </p> + +</body> + +</html> + diff --git a/astyle/doc/notes.html b/astyle/doc/notes.html new file mode 100755 index 0000000000000000000000000000000000000000..7b3746baf0aeb3a58307fe326bf3e962b260aa6f --- /dev/null +++ b/astyle/doc/notes.html @@ -0,0 +1,345 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> + +<head> + <title>Artistic Style - Release Notes</title> + <meta http-equiv="Content-Language" content="en-us" /> + <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" /> + <link href="favicon.ico" rel="shortcut icon" type="image/x-icon" /> + <link href="styles.css" rel="stylesheet" type="text/css" /> +</head> + +<body> + + <h1>Artistic Style Release Notes</h1> + + <p> + </p> + + <h3>Artistic Style 3.0 (April 2017)</h3> + + <ul> + <li>Add new option "indent-after-parens" (#396, 152, 108, 79).</li> + <li>Add new option "attach-closing-while" (#177).</li> + <li>Add "style=run-in" as an alternative for "style=horstmann".</li> + <li>Add "break-closing-braces" to "style=stroustrup" (#267).</li> + <li>Add formatting for C++11 trailing return type methods.</li> + <li>Add new class ASPeekStream using RAII to allow early method returns.</li> + <li>Change affected variable names to new AStyle terminology.</li> + <li>Change some vector push_back() statements to emplace_back().</li> + <li>Fix memory leak when using "indent-preproc-define".</li> + <li>Fix sometimes splitting an r-value reference when "pad-oper" is used.</li> + <li>Fix in-statement-indent brace check not always checking a brace (#421).</li> + <li>Fix formatting of C# get/set and add/remove when braces are attached (#430).</li> + <li>Fix formatting of C# generic constraints (#430).</li> + <li>Fix padding of C# null conditional operator.</li> + <li>Fix attach-inlines to not attach a brace followed by a run-in comment.</li> + <li>Fix not always breaking lines after "add-braces" (#341).</li> + <li>Fix unpadding the "in" in a foreach statement (#386).</li> + <li>Fix boundary conditions discovered by <a href="http://lcamtuf.coredump.cx/afl/" target="_blank" + title="open new window">american fuzzy lop</a> fuzzer (#370).</li> + <li>Refactoring: + <ul> + <li>Replace NULL with C++11 nullptr.</li> + <li>Rename Utf8_16 class to ASEncoding.</li> + <li>Move ASConsole constructor and destructor from inline to non-inline.</li> + <li>Move console error stream (cerr) from global to ASConsole class.</li> + <li>Move ASConsole pointer in ASOptions from global to a class member.</li> + <li>Move findHeader and findOperator methods from ASBeautifier to ASBase.</li> + <li>Minor changes from PVS-Studio analyzer.</li> + <li>Minor changes from clang-tidy.</li> + </ul> + </li> + </ul> + + <h3>Artistic Style 2.06 (December 2016)</h3> + + <ul> + <li>Add new bracket style option "style=mozilla".</li> + <li>Add new option "break-one-line-headers" (#33, 64, 367).</li> + <li>Add new option "indent-continuation".</li> + <li>Add new option "pad-comma" (#100).</li> + <li>Add removing spaces before a comma (#100).</li> + <li>Add new Objective‑C options "pad-return-type" (-xq) and "unpad-return-type" (-xr).</li> + <li>Add new Objective‑C options "pad-param-type" (-xS) and "unpad-param-type" (-xs).</li> + <li>Add formatting of C++14 single-quote digit separators (#337).</li> + <li>Add indentation for CORBA IDL module statement (#414).</li> + <li>Add translations for Bulgarian, Estonian, Greek, Hungarian, Norwegian, and Romanian.</li> + <li>Remove lineend option from formatCinToCout function.</li> + <li>Improve align-method-colon and apply to Objective‑C method calls.</li> + <li>Improve recognition of header guards in preprocessor statements.</li> + <li>Improve recognition of C++11 uniform initializer brackets (#381, 411, 415).</li> + <li>Improve the processing of quoted strings and verbatim strings.</li> + <li>Change align-method-colon short first line to align on the longest line instead of the first line.</li> + <li>Change to not break empty one line brackets to support new "break-one-line-headers".</li> + <li>Change add-brackets to not add to one line blocks to support new "break-one-line-headers".</li> + <li>Change add-brackets to not add to one line statements in support new "break-one-line-headers".</li> + <li>Fix not recognizing an escaped space character within a quote (#403).</li> + <li>Fix not recognizing "else" brackets as COMMAND_TYPE (#400).</li> + <li>Fix attaching "if" statements to a #else preprocessor directive (#356).</li> + <li>Fix not clearing global variables for a new file (#364).</li> + <li>Fix not recognizing an rvalue reference in a template (#404).</li> + <li>Fix breaking a line when processing the first line of a file (#400).</li> + <li>Fix breaking a line in an exponential (#392).</li> + <li>Fix indentation of an "enum" without following brackets (#401, 384).</li> + <li>Fix indentation of arguments using preceding commas (#355).</li> + <li>Fix indentation of Pico style one line blocks.</li> + <li>Fix not padding header for "new" or "delete" followed by parens.</li> + <li>Fix template variable not being cleared at end of a statement (#380).</li> + <li>Fix "close-templates" to only close ending angle brackets (#375).</li> + <li>Fix pad-oper to not pad a + or - following an open bracket (#378).</li> + <li>Fix C# to recognize "using" as a header.</li> + <li>Fix C# to always recognize "forever" as a header.</li> + <li>Fix Pico style not always computing the indentation for one line blocks.</li> + <li>Fix indentation of Objective-C @interface statement (#333).</li> + <li>Fix assert error when Objective-C "@" is followed by whitespace.</li> + <li>Fix end of line comments for "pad-method-prefix" and "unpad-method-prefix".</li> + <li>Fix end of line comments for "pad-method-colon".</li> + <li>Refactoring: + <ul> + <li>Consolidate scattered ASFormatter conditional statements into a padParenObjC method.</li> + <li>Remove BracketMode STROUSTRUP_MODE and change it to LINUX_MODE.</li> + <li>Remove ASBase methods from being inlined as class definitions.</li> + <li>Replace C char arrays in astyle_main.cpp with C++ strings.</li> + <li>Return language translation as a mutable variable.</li> + <li>Portability changes for additional compiler support (#352).</li> + <li>Minor changes based on results of the Clang-Tidy. </li> + </ul> + </li> + </ul> + + <h3>Artistic Style 2.05.1 (December 2014)</h3> + + <ul> + <li>Fix incorrectly reporting files containing disabled formatting as being formatted.</li> + <li>Fix incorrect handling of quoted arguments in the options file (#321).</li> + <li>Fix error in identifying an enum return type as an enumeration (#322, 323).</li> + <li>Fix error in identifying an enum argument as an enumeration (#327).</li> + <li>Fix recognition of Qt keywords when used as variables in C++ (#329).</li> + <li>Fix recognition of a pointer in a C++ cast (#316).</li> + <li>Fix removing trailing whitespace after a changed pointer or reference cast.</li> + </ul> + + <h3>Artistic Style 2.05 (November 2014)</h3> + + <ul> + <li>Add new bracket style option "style=vtk" (#155).</li> + <li>Add new option "indent-preproc-block" to indent blocks of preprocessor directives (#21, #114, #229, + #242, #294).</li> + <li>Add new option, "dry-run", to run AStyle without updating the files (#184, #285).</li> + <li>Add new options, "html" (-!") and "html=###", to display the HTML help documentation in the default browser. + </li> + <li>Add tags "*INDENT-OFF*" and "*INDENT_ON*" to disable formatting of source code blocks + (#2, #47, #55, #78, #110, #176).</li> + <li>Add tag *NOPAD* to disable selected formatting on a single line.</li> + <li>Add '__attribute__ ((visibility ("default")))' to Linux exported functions.</li> + <li>Remove option "style=ansi" and make it depreciated (#146).</li> + <li>Remove fix for broken 'case' statements from release 2.02.1, Nov 21, 2011.</li> + <li>Improve Korean translation (#256).</li> + <li>Change shared libraries to include the version number as part of the file name (#264)</li> + <li>Change "help" display to stdout to allow piping and redirection (#63).</li> + <li>Change "version" display to stdout. </li> + <li>Change headers to include foreach, forever, Q_FOREACH, and Q_FOREVER (#98, #154).</li> + <li>Change compiler definition ASTYLE_NO_VCX (no Visual Studio exports) to ASTYLE_NO_EXPORTS.</li> + <li>Change shared library error handler argument from "char*" to "const char*".</li> + <li>Fix not recognizing noexcept, interrupt, and autoreleasepool as pre-command headers (#225, #259).</li> + <li>Fix formatting of C++11 uniform initializer brackets (#253, #257, #260, #284).</li> + <li>Fix to not automatically space pad C++11 uniform initializer brackets (#275).</li> + <li>Fix formatting of enums with leading commas (#159, #179, #270).</li> + <li>Fix formatting of logical && operator in class initializers (#290).</li> + <li>Fix flagging a 'const' variable as a 'const' method (#275).</li> + <li>Fix piping and redirection adding an extra character to the output (#245, #252, #305). </li> + <li>Fix "indent-modifiers" to attach class access modifiers to Horstmann style brackets. </li> + <li>Fix ASFormatter to correctly recognize the end of a C++ raw string literal (#261).</li> + <li>Fix to recognize C++11 "enum class" as an enum (#303).</li> + <li>Fix indent of C++11 "noexecpt" statements within a class (#260, #304).</li> + <li>Fix not resetting templateDepth when a template was not found (#295).</li> + <li>Fix formatting of multiplication in a block paren (#144).</li> + <li>Fix whitespace padding when formatting an rvalue references (#297).</li> + <li>Fix to recognize an rvalue reference without a name (#265).</li> + <li>Fix to not identify an operator overload method as a calculation (#296).</li> + <li>Fix concatenating multiplication with a pointer dereference (#291).</li> + <li>Fix recognition of a pointer dereference following a question mark (#213).</li> + <li>Fix extra space after a trailing reference type (#300).</li> + <li>Fix _asm blocks not being identified as a block opener and the variable not cleared on exit (#163).</li> + <li>Fix indentation of line comments before a "class" opening bracket.</li> + <li>Fix indentation of line comments before a "namespace" opening bracket.</li> + <li>Fix isBracketType() method to correctly process a NULL_TYPE.</li> + <li>Fix unpad-paren to recognize additional variables (#43, #132, #143). </li> + <li>Fix indentation of C# "let" statements.</li> + <li>Fix a few omissions with "fill-empty-lines".</li> + <li>Fix file read to read 64K blocks of data.</li> + <li>Refactor to un-obfuscate (clarify) the code, and improve design and decomposition: + <ul> + <li>Extract class Utf8_16 from ASConsole. </li> + <li>Replace Linux dependency on iconv with a Utf8_16 class for ASLibrary.</li> + <li>Move global "using" statements to the astyle namespace in astyle.h and ASLocalizer.h. </li> + <li>Move shared library declarations from astyle.h to astyle_main.h.</li> + <li>Move indentable macros from ASEnhancer to ASResource and create static pairs.</li> + <li>Simplify ASBeautifier procedure to identify the colon (:) type.</li> + <li>Major refactoring in ASBeautifier to create separate variables for an enum, a class statement and a class initializer.<br /> + This was needed to fix the processing of C++11 uniform initializers in a class initializer. + </li> + <li>Minor changes to ASFormatter and ASBeautifier based on results of the Clang analyzer. </li> + <li>Change several methods in astyle_main to "const".</li> + </ul> + </li> + </ul> + + <h3>Artistic Style 2.04 (November 2013)</h3> + + <ul> + <li>Add new programming language Objective‑C.</li> + <li>Add new bracket style option "style=google" (-A14). </li> + <li>Add new option "indent-preproc-cond" (xw) to indent preprocessor conditional statements (#118). </li> + <li>Add new bracket modify options "attach-namespaces", "attach-classes", "attach-inlines", and "attach-extern-c". + </li> + <li>Add new option "indent-modifiers" (-xG) to indent class access modifiers one-half indent (#130). </li> + <li>Add new option "remove-brackets" (-xj) to remove brackets from single line conditional statements.</li> + <li>Add new option "remove-comment-prefix" (-xp) to remove the leading '*' from multi-line comments. </li> + <li>Add new option "align-method-colon" (-xM) to align Objective‑C method colons. </li> + <li>Add new option "pad-method-colon=#" (-xP#) to space pad Objective‑C method colons. </li> + <li>Add new options "pad-method-prefix" (-xQ), and "unpad-method-prefix" (-xR) to pad the Objective‑C "-" and + "+" method prefix. </li> + <li>Add new dll entry point AStyleMainUtf16 for processing C# UTF-16 strings. </li> + <li>Add formatting of C++11 raw string literals (#222). </li> + <li>Add "style=knf" as an alternative to "style=linux".</li> + <li>Remove depreciated "bracket=" options.</li> + <li>Improve recognition and formatting of pointers and references (#174 and other changes). </li> + <li>Improve the recognition of block-opening brackets.</li> + <li>Improve code using a static code analyzer (#195).</li> + <li>Change "max-code-length" to include Objective‑C methods.</li> + <li>Change "indent-elseifs" and "break-blocks" to look ahead only if in command-type brackets (speed improvement). + </li> + <li>Fix linux bracket styles to break the opening bracket in inline function definitions (#185). </li> + <li>Fix indentation of switch block comments (#164). </li> + <li>Fix enums to indent with tabs when requested (#92, #121). </li> + <li>Fix formatting of rvalue reference without a name in a declaration (#219). </li> + <li>Fix "pad-first-paren-out" to not pad if the following parens are empty (#232). </li> + <li>Fix end-of-statement reset when comments follow closing bracket.</li> + <li>Fix the ASBeautifier active and waiting stacks to delete the ASBeautifier objects before deleting the pointers. + </li> + <li>Fix ASBeautifier "init" to delete the tempStack vectors before deleting the tempStack.</li> + <li>Fix Linux piping problem by changing "cin" input to build a stringstream before formatting. </li> + <li>Fix to identify the correct bracket type when 'extern "C"' is part of the enum definition. </li> + <li>Fix to clear 'extern "C"' variables when the block is closed. </li> + <li>Fix unindented 'extern "C"' to not indent when in a #else preprocessor directive.</li> + <li>Fix not always correctly formatting linux type brackets for enum blocks.</li> + <li>Fix align-pointer in a range-based for statement (#217).</li> + <li>Fix pointer-reference argument alignment to correctly position a following comment (#235).</li> + <li>Fix to not attach a bracket to a line ending in a backslash '\' (#186, #214, #220). </li> + <li>Fix to recognize templates using multiple lines (#85, #87, #136).</li> + <li>Fix formatting of template continuation lines (#85, #87, #136).</li> + <li>Fix to allow '^' as an array operator (#233). </li> + <li>Fix an "enum" argument being mistaken for an enumeration (#211).</li> + <li>Fix to recognize a non-instatement array after a "},{" sequence.</li> + <li>Fix "pad-oper" to not pad before a following comma. </li> + <li>Fix recognition of an operator when the calculation contains a bitwise "not" '~' (#166).</li> + <li>Fix to allow a preprocessor statement within a preprocessor define (#238).</li> + <li>Fix preprocessor comparison to check for whole words (#246).</li> + <li>Fix "add-brackets" when a line contains more than one paren pairs (#181).</li> + <li>Fix to allow Mac old CR line endings in the options file (#129).</li> + <li>Refactor to aid debugging and improve design and decomposition: + <ul> + <li>Move ALL preliminary indentation calculations to computePreliminaryIndentation() in ASBeautifier.</li> + <li>Move calculation of 'force tab' indents to preLineWS() in ASBeautifier. </li> + <li>Combine methods init() and init(ASSourceIterator*) in ASBeautifier.</li> + <li>Extract method adjustParsedLineIndentation() in ASBeautifier.</li> + <li>Extract method parseCurrentLine() in ASEnhancer. </li> + <li>Remove astyle_main.cpp unused functions getFilesUnchanged, getOptionsFileRequired, and setOptionsFileRequired. + </li> + </ul> + </li> + </ul> + + <h3>Artistic Style 2.03 (April 2013)</h3> + + <ul> + <li>Add new option "indent=force-tab-x=#" (-xT#) to allow a tab length that different from the indent length (3430662). + </li> + <li>Add new option, "pad-first-paren-out" (xd), to pad only the first paren in a series on the outside (3350356). + </li> + <li>Add new option "max-code-length=#" (-xC#) to limit the length of code on a line. </li> + <li>Add new option "break-after-logical" (-xL) to modify a "max-code-length" line break for conditionals. </li> + <li>Add new option "close-templates" (-xy) to close whitespace in the angle brackets ">" of template + definitions.</li> + <li>Add formatting of C++ rvalue references (&&) using the existing "align-pointer" and "align-reference" + options.</li> + <li>Add formatting of C++/CLI managed pointers (the "^" character) to the "align-pointer" option.</li> + <li>Add translations for Dutch, Finnish, Italian, Japanese, Korean, Polish, Portuguese, Russian, Swedish, and Ukrainian. + </li> + <li>Remove byte-order-mark from ASLocalizer.cpp.</li> + <li>Change the short option for delete-empty-lines from "xd" to "xe".</li> + <li>Change the ASTYLE_LIB option to remove __declspec for a Visual C static library when ASTYLE_NO_VCX is also declared. + </li> + <li>Change to remove any space padding in a pointer to pointer (**).</li> + <li>Fix "break-elseifs" to format one-line "if" and "else" statements the same as when the option is not used. + </li> + <li>Fix "break-elseifs" to break else-if statements when "keep-one-line-statements" also is requested. </li> + <li>Fix "break-elseifs" to correctly format comments preceding the else-if. </li> + <li>Fix C# not correctly identifying lambda expressions as a command-type bracket.</li> + <li>Fix C# preprocessor statements adding extra empty lines when "break-blocks" is used. </li> + <li>Fix C# padding "get" and "set" statements that are not headers when "break-blocks" is used. </li> + <li>Fix C# to recognize the "#line" statement. </li> + <li>Fix C++11 standard for range-based "for" loops (3458402, 3480095). </li> + <li>Fix C++11 standard for "enum" with a base type (3458402). </li> + <li>Fix C++11 standard for template closing angle brackets (no space required) (3495192). </li> + <li>Fix C/C++ keyword 'extern "C"' in a preprocessor causing an extra indent (1514844, 2953388, 2963382, 3093842, + <span>3467479)</span>. </li> + <li>Fix breaking after a switch "default" statement when "break-elseifs" is used without "keep-one-line-statements" + (<span>3559365</span>). </li> + <li>Fix in-statement arrays to indent correctly when they exceed the "max-instatement-indent". </li> + <li>Fix quote continuation sometimes being processed as a preprocessor directive (3445475).</li> + <li>Fix formatting of some conditional statements on a continuation-line.</li> + <li>Fix Java formatting of generics with wildcards (3428140).</li> + <li>Fix formatting of pointers and references to work with the new "max-code-length" option. </li> + <li>Fix formatting of pointers and references after a template close.</li> + <li>Fix formatting of empty attached brackets (3505002).</li> + <li>Fix C comments beginning a line breaking if they follow a semi-colon (3502700).</li> + <li>Fix "pad-header" not padding "return" and "throw" statements (3509134).</li> + <li>Fix recognition problems with templates.</li> + <li>Fix "struct" return type being mistaken for a struct.</li> + <li>Fix "pad-oper" in java for-each loop.</li> + <li>Fix recognition of a macro multi-line comment (3414970).</li> + <li>Fix bracketTypeStack entries added by #if and #else if the # is separated from the word. </li> + <li>Fix C++ breaking a line on an access modifier in a one-line block when "keep-one-line-blocks" is used. + </li> + <li>Fix memory leak when "ascii" option is used.</li> + <li>Fix memory leak when a preprocessor statement is used without a closing #endif.</li> + <li>Fix preprocessor directive to allow compiling with mingw-x64 compiler.</li> + <li>Fix redirection on Windows so it does not hang when Linux line ends are used (3514712).</li> + <li>Fix redirection on Linux to output the correct line ends (3514712).</li> + <li>Fix non-portable return value on locale name (3452574). </li> + <li>Fix assert errors caused by not checking the text length on the return from peekNextText().</li> + <li>Fix spelling of "depreciated" in help message (3454735).</li> + <li>Refactor to improve design and decomposition: + <ul> + <li>Fix warning messages from Visual Studio static code analysis.</li> + <li>Fix warning messages from cppcheck, except for constructor uninitialized variables (false positive). </li> + <li>Remove astyle_main.h dependency from ASLocalizer.h </li> + <li>Remove appendChar() from the inline functions.</li> + <li>Extract methods for pointer or reference alignment in ASFormatter. </li> + </ul> + </li> + </ul> + + <p> + </p> + <p> + <strong>Previous releases are available in the <a href="http://astyle.sourceforge.net/notesArchives.html">Release + Notes Archives</a>.</strong></p> + <p> + </p> + + <p style="margin-left: -0.4in; text-align: center;"> + <a href="http://sourceforge.net/projects/astyle"> + <img src="http://sflogo.sourceforge.net/sflogo.php?group_id=2319&type=16" alt="" /></a></p> + + <p> + </p> + +</body> + +</html> + diff --git a/astyle/doc/styles.css b/astyle/doc/styles.css new file mode 100755 index 0000000000000000000000000000000000000000..f486e1740d626a8982b5650a9ed2160bb1f6f58d --- /dev/null +++ b/astyle/doc/styles.css @@ -0,0 +1,36 @@ + +/* h1 is a title + * h2 is a subtitle + * h3 is a hanging text title + * h4 is a non-hanging text title + * p.noindent is non-hanging text (text without a title) + * p.contents entries are for the table of contents + * a.contents are table of contents links (not underlined) + * a.links are links (underlined) + * img does not have a border + * pre is a predefined format for formatting code + */ + +/* margin: [top] [right] [bottom] [left] */ + +body { background-color: white; margin: 0.5in 0.8in 0.5in 1.3in; } + +h1 { color: #0000A0; text-align: center; font-style: italic; margin-top: 0.4in; margin-left: -0.5in; } +/* h2.large { color: #0000A0; text-align: center; font-size: x-large; margin-top: 0.4in; margin-left: -0.5in; } */ +h2 { color: #0000A0; text-align: center; font-size: larger; margin-top: 0.4in; margin-left: -0.5in; } +h3 { color: #0000A0; margin-top: 0.4in; margin-left: -0.4in; } +h4 { color: #0000A0; margin-top: 0.3in; } + +/* paragraph classes */ +.noindent { margin-left: -0.4in; } +.contents1 { font-size: 105%; margin: 0; } +.contents2 { margin: 0 0.4in 0 0.4in; } + +a.contents:link, a.contents:visited { color: #0000A0; text-decoration: none; } +a.contents:hover { color: #F00000; text-decoration: none; } +a:link, a:visited { color: #0000A0; text-decoration: underline; } +a:hover { color: #F00000; text-decoration: underline; } + +img { border: none; } + +pre { margin-left: 0.3in; color: navy; font-weight: bold; } diff --git a/astyle/file/allman.ini b/astyle/file/allman.ini new file mode 100755 index 0000000000000000000000000000000000000000..35af58367511db54a3b1323a903059d206efab60 --- /dev/null +++ b/astyle/file/allman.ini @@ -0,0 +1,22 @@ +# Allman Coding Style Options +# Based on an old AStyle release. + +# braces and indent +style=allman +# indent=spaces # this is the default + +# indentation +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs diff --git a/astyle/file/astyle.ini b/astyle/file/astyle.ini new file mode 100755 index 0000000000000000000000000000000000000000..6f0283bb8ce37c7d5c13a02f40158efe75661666 --- /dev/null +++ b/astyle/file/astyle.ini @@ -0,0 +1,32 @@ +# astyle formatting options +# for all projects except AStyleDev example projects +# example projects use style=horstmann and indent=spaces (-A9s) +# for compatibility with Visual Studio: indent=force-tab, min-conditional-indent=0 (-Tm0) +# short options: -A1txn -SxWwM60 -pHk1 -xbO -xQxrxsxMxP2 + +# braces and indent +style=allman +indent=tab +attach-namespaces +# indentation +indent-switches +indent-preproc-block +indent-preproc-define +max-continuation-indent=60 +# padding +pad-oper +pad-header +align-pointer=type +# formatting +break-one-line-headers +keep-one-line-blocks +# objective-c +pad-method-prefix +unpad-return-type +unpad-param-type +align-method-colon +pad-method-colon=after +# other options +lineend=windows +# don't use "other options" (e.g. formatted) in this file +# send them as additional command line options diff --git a/astyle/file/chromium.ini b/astyle/file/chromium.ini new file mode 100755 index 0000000000000000000000000000000000000000..9603e1ba45682db60456fd97b2408c858192f5f9 --- /dev/null +++ b/astyle/file/chromium.ini @@ -0,0 +1,33 @@ +# Chromium Coding Style Options +# https://chromium.googlesource.com/chromium/src/+/master/styleguide/styleguide.md + +# braces and indent +style=google +indent=spaces=2 + +# indentation +indent-switches +indent-continuation=2 +indent-preproc-define +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs +#close-templates + +# objective-c +pad-method-prefix +unpad-return-type +unpad-param-type +align-method-colon +pad-method-colon=none diff --git a/astyle/file/gnu.ini b/astyle/file/gnu.ini new file mode 100755 index 0000000000000000000000000000000000000000..8b99d552cbba3e823b350847a434ecced3c0840d --- /dev/null +++ b/astyle/file/gnu.ini @@ -0,0 +1,23 @@ +# Gnu Coding Style Options +# https://www.gnu.org/prep/standards/html_node/Writing-C.html#Writing-C +# Based on an old AStyle release. + +# braces and indent +style=gnu +indent=spaces=2 + +# indentation +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs diff --git a/astyle/file/google.ini b/astyle/file/google.ini new file mode 100755 index 0000000000000000000000000000000000000000..a55ac8e6e2381c6a8078f61c316e473798f66f6b --- /dev/null +++ b/astyle/file/google.ini @@ -0,0 +1,35 @@ +# Google Coding Style Options +# C++ - https://google.github.io/styleguide/cppguide.html +# Java - https://google.github.io/styleguide/javaguide.html +# ObjC - https://google.github.io/styleguide/objcguide.xml + +# braces and indent +style=google +indent=spaces=2 + +# indentation +indent-switches +indent-continuation=2 +indent-preproc-define +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs +#close-templates + +# objective-c +pad-method-prefix +unpad-return-type +unpad-param-type +align-method-colon +pad-method-colon=none diff --git a/astyle/file/horstmann.ini b/astyle/file/horstmann.ini new file mode 100755 index 0000000000000000000000000000000000000000..30d9d858301367986a89e092177b2e63c9be6abb --- /dev/null +++ b/astyle/file/horstmann.ini @@ -0,0 +1,24 @@ +# Horstmann Coding Style Options +# Obtained from Horstmann source code. + +# braces and indent +style=horstmann +indent=spaces=3 + +# indentation +indent-modifiers +indent-switches +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tab diff --git a/astyle/file/java.ini b/astyle/file/java.ini new file mode 100755 index 0000000000000000000000000000000000000000..68644947f583187da4aa5e6de6fff4a3b6f4b20e --- /dev/null +++ b/astyle/file/java.ini @@ -0,0 +1,22 @@ +# Java Coding Style Options +# Obtained from Java source code. + +# braces and indent +style=java +# indent=spaces # this is the default + +# indentation +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tab diff --git a/astyle/file/linux.ini b/astyle/file/linux.ini new file mode 100755 index 0000000000000000000000000000000000000000..9071c2a8c184cd84b32a4deee1978250c4c066ca --- /dev/null +++ b/astyle/file/linux.ini @@ -0,0 +1,22 @@ +# Linux Coding Style Options +# Obtained from the Linux Kernel BSD. + +# braces and indent +style=linux +indent=tab=8 + +# indentation +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs diff --git a/astyle/file/llvm.ini b/astyle/file/llvm.ini new file mode 100755 index 0000000000000000000000000000000000000000..71d4de62ff96019686fc61e319687c8ca094710b --- /dev/null +++ b/astyle/file/llvm.ini @@ -0,0 +1,32 @@ +# LLVM Coding Style Options +# http://llvm.org/docs/CodingStandards.html + +# braces and indent +style=attach +indent=spaces=2 + +# indentation +indent-continuation=2 +indent-preproc-define +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=name + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs +close-templates + +# objective-c +pad-method-prefix +unpad-return-type +unpad-param-type +align-method-colon +pad-method-colon=none diff --git a/astyle/file/mozilla.ini b/astyle/file/mozilla.ini new file mode 100755 index 0000000000000000000000000000000000000000..f040100a707abf7f599322f1e56ca81f0dbc12fc --- /dev/null +++ b/astyle/file/mozilla.ini @@ -0,0 +1,36 @@ +# Mozilla Coding Style Options +# https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Coding_Style +# NOTE: Function return values should be on a separate line. +# The astyle option are: +# "AlwaysBreakAfterDefinitionReturnType: TopLevel" +# "AlwaysBreakAfterReturnType: TopLevelDefinitions" + +# braces and indent +style=mozilla +indent=spaces=2 + +# indentation +indent-switches +indent-preproc-define +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs +close-templates + +# objective-c +pad-method-prefix +unpad-return-type +unpad-param-type +align-method-colon +pad-method-colon=none diff --git a/astyle/file/stroustrup.ini b/astyle/file/stroustrup.ini new file mode 100755 index 0000000000000000000000000000000000000000..7bf6745367e3857160cb2408ed1d45f23c8ed25e --- /dev/null +++ b/astyle/file/stroustrup.ini @@ -0,0 +1,27 @@ +# Stroustrup Coding Style Options +# Obtained from http://www.stroustrup.com/Programming/PPP-style.pdf. + +# braces and indent +style=stroustrup +attach-closing-while +indent=spaces=5 + +# indentation +indent-modifiers +indent-switches +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +#break-closing-braces # now included in the style +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs + diff --git a/astyle/file/visualstudio.ini b/astyle/file/visualstudio.ini new file mode 100755 index 0000000000000000000000000000000000000000..a11f6305f38a3019f2f9803eac15ef8d3a3df08e --- /dev/null +++ b/astyle/file/visualstudio.ini @@ -0,0 +1,29 @@ +# Visual Studio Coding Style Options +# http://code.visualstudio.com/docs/languages/cpp#_code-formatting + +# braces and indent +style=allman +indent=force-tab-x + +# indentation +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=name + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs + +# objective-c +pad-method-prefix +unpad-return-type +unpad-param-type +align-method-colon +pad-method-colon=none diff --git a/astyle/file/webkit.ini b/astyle/file/webkit.ini new file mode 100755 index 0000000000000000000000000000000000000000..10f78a1c3ee118b0efa6dbf7196fbd094a4dfe16 --- /dev/null +++ b/astyle/file/webkit.ini @@ -0,0 +1,34 @@ +# WebKit Coding Style Options +# https://webkit.org/code-style-guidelines/ +# NOTE: Continuation lines should not be aligned with parens. +# The astyle option is indent-after-parens. + +# braces and indent +style=stroustrup +# indent=spaces # this is the default + +# indentation +indent-after-parens +indent-preproc-define +min-conditional-indent=0 +max-continuation-indent=80 + +# padding +pad-oper +pad-header +unpad-paren +align-pointer=type + +# formatting +break-one-line-headers +keep-one-line-blocks +keep-one-line-statements +convert-tabs +#close-templates + +# objective-c +pad-method-prefix +unpad-return-type +unpad-param-type +align-method-colon +pad-method-colon=none diff --git a/astyle/src/ASBeautifier.cpp b/astyle/src/ASBeautifier.cpp new file mode 100755 index 0000000000000000000000000000000000000000..25b2e53f3686e24a6b99e7b65f27414ec1180466 --- /dev/null +++ b/astyle/src/ASBeautifier.cpp @@ -0,0 +1,3659 @@ +// ASBeautifier.cpp +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// This code is licensed under the MIT License. +// License.md describes the conditions under which this software may be distributed. + +//----------------------------------------------------------------------------- +// headers +//----------------------------------------------------------------------------- + +#include "astyle.h" + +#include <algorithm> + +//----------------------------------------------------------------------------- +// 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; + squareBracketDepthStack = 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<const string*>; + nonParenHeaders = new vector<const string*>; + assignmentOperators = new vector<const string*>; + nonAssignmentOperators = new vector<const string*>; + preBlockStatements = new vector<const string*>; + preCommandHeaders = new vector<const string*>; + indentableHeaders = new vector<const string*>; +} + +/** + * 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<const string*>; + *headerStack = *other.headerStack; + + tempStacks = copyTempStacks(other); + + squareBracketDepthStack = new vector<int>; + *squareBracketDepthStack = *other.squareBracketDepthStack; + + blockStatementStack = new vector<bool>; + *blockStatementStack = *other.blockStatementStack; + + parenStatementStack = new vector<bool>; + *parenStatementStack = *other.parenStatementStack; + + braceBlockStateStack = new vector<bool>; + *braceBlockStateStack = *other.braceBlockStateStack; + + continuationIndentStack = new vector<int>; + *continuationIndentStack = *other.continuationIndentStack; + + continuationIndentStackSizeStack = new vector<int>; + *continuationIndentStackSizeStack = *other.continuationIndentStackSizeStack; + + parenIndentStack = new vector<int>; + *parenIndentStack = *other.parenIndentStack; + + preprocIndentStack = new vector<pair<int, int> >; + *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; + 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(squareBracketDepthStack); + 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<ASBeautifier*>); + initContainer(activeBeautifierStack, new vector<ASBeautifier*>); + + initContainer(waitingBeautifierStackLengthStack, new vector<int>); + initContainer(activeBeautifierStackLengthStack, new vector<int>); + + initContainer(headerStack, new vector<const string*>); + + initTempStacksContainer(tempStacks, new vector<vector<const string*>*>); + tempStacks->emplace_back(new vector<const string*>); + + initContainer(squareBracketDepthStack, new vector<int>); + initContainer(blockStatementStack, new vector<bool>); + initContainer(parenStatementStack, new vector<bool>); + initContainer(braceBlockStateStack, new vector<bool>); + braceBlockStateStack->push_back(true); + initContainer(continuationIndentStack, new vector<int>); + initContainer(continuationIndentStackSizeStack, new vector<int>); + continuationIndentStackSizeStack->emplace_back(0); + initContainer(parenIndentStack, new vector<int>); + initContainer(preprocIndentStack, new vector<pair<int, int> >); + + 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; + + 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); +} + +/** + * 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 compatability 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; +} + +/** + * 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; + 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<int, int> 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; + 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; +} + +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) +{ + 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); + + 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 && 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 (firstChar != 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<int, int> ASBeautifier::computePreprocessorIndent() +{ + computePreliminaryIndentation(); + pair<int, int> 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; + } + else if (isWhiteSpace(ch)) + continue; + else 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<const string*>& container, const string* element) const +{ + vector<const string*>::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<vector<const string*>*>* ASBeautifier::copyTempStacks(const ASBeautifier& other) const +{ + vector<vector<const string*>*>* tempStacksNew = new vector<vector<const string*>*>; + vector<vector<const string*>*>::iterator iter; + for (iter = other.tempStacks->begin(); + iter != other.tempStacks->end(); + ++iter) + { + vector<const string*>* newVec = new vector<const string*>; + *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<typename T> +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<ASBeautifier*>*& container) +{ + if (container != nullptr) + { + vector<ASBeautifier*>::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<vector<const string*>*>*& container) +{ + if (container != nullptr) + { + vector<vector<const string*>*>::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<typename T> +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<vector<const string*>*>*& container, + vector<vector<const string*>*>* 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; + else + { + 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]) || line[start] == '.') + break; + } + start++; + + return start; +} + +/** + * get the instatement 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 (preproc.compare(charNum, 1, "(") == 0) + { + ++charNum; + charNum = preproc.find_first_not_of(" \t", charNum); + if (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->push_back(waitingBeautifierStack->size()); + activeBeautifierStackLengthStack->push_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<const string*>* lastTempStack = tempStacks->back(); + if (lastTempStack != nullptr) + { + for (size_t i = 0; i < lastTempStack->size(); i++) + { + if (*lastTempStack->at(i) == 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 = convertedLine.find(':'); + 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 = convertedLine.find(':'); + if (colonIndentObjCMethodAlignment >= 0) + { + int objCColonAlignSubsequentIndent = objCColonAlignSubsequent + indentLength; + if (objCColonAlignSubsequentIndent > colonIndentObjCMethodAlignment) + colonIndentObjCMethodAlignment = objCColonAlignSubsequentIndent; + if (lineBeginsWithOpenBrace) + colonIndentObjCMethodAlignment -= indentLength; + } + } + else + { + if (line_.find(':') != string::npos) + { + 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(); +} + +/** + * 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 = line.find(':'); + if (colonPosition < 0 || colonPosition > colonAlignPosition) + return indentLength; + return (colonAlignPosition - colonPosition); +} + +/* + * Compute postition of the keyword following the method call object. + */ +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; +} + +/** + * 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; + } + else 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; + } + else 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 + else 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->push_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) + { + parenStatementStack->push_back(isContinuation); + isContinuation = true; + } + parenDepth++; + if (ch == '[') + { + ++squareBracketCount; + if (squareBracketCount == 1 && isCStyle()) + { + isInObjCMethodCall = true; + isInObjCMethodCallFirst = true; + } + } + + continuationIndentStackSizeStack->push_back(continuationIndentStack->size()); + + if (currentHeader != nullptr) + registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, minConditionalIndent, true); + else + 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) == '{' + || 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 (headerStack->empty()) + isBlockOpener = true; + else 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) + isBlockOpener = true; + } + else 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) + isBlockOpener = true; + } + + if (!isBlockOpener && currentHeader != nullptr) + { + for (size_t n = 0; n < nonParenHeaders->size(); n++) + if (currentHeader == (*nonParenHeaders)[n]) + { + isBlockOpener = true; + break; + } + } + + braceBlockStateStack->push_back(isBlockOpener); + + if (!isBlockOpener) + { + continuationIndentStackSizeStack->push_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; + + squareBracketDepthStack->emplace_back(parenDepth); + blockStatementStack->push_back(isContinuation); + + if (!continuationIndentStack->empty()) + { + // completely purge the inStatementIndentStack + 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; + 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<const string*>); + 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); + + // 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 (newHeader == &AS_USING + && ASBeautifier::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<const string*>* 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) + { + 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) + 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) + { + // 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() + && !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 (!squareBracketDepthStack->empty()) + { + parenDepth = squareBracketDepthStack->back(); + squareBracketDepthStack->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<const string*>* 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; + + 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); + // handle 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' + { + 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()) + { + 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 == '@' && !isWhiteSpace(line[i + 1]) + && isCharPotentialHeader(line, i + 1)) + { + string curWord = getCurrentWord(line, i + 1); + if (curWord == AS_INTERFACE && headerStack->empty()) + { + isInObjCInterface = true; + string name = '@' + curWord; + i += name.length() - 1; + continue; + } + else 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; + } + else if (curWord == AS_END) + { + popLastContinuationIndent(); + spaceIndentCount = 0; + isInObjCMethodDefinition = false; + string name = '@' + curWord; + i += name.length() - 1; + continue; + } + } + else if ((ch == '-' || ch == '+') + && peekNextChar(line, i) == '(' + && headerStack->empty() + && 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 < 2 && 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/astyle/src/ASEnhancer.cpp b/astyle/src/ASEnhancer.cpp new file mode 100755 index 0000000000000000000000000000000000000000..402aa16d4de4853fa1a3dc7cfa6c59e6353612fd --- /dev/null +++ b/astyle/src/ASEnhancer.cpp @@ -0,0 +1,797 @@ +// ASEnhancer.cpp +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// 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 +//----------------------------------------------------------------------------- + +/** + * ASEnhancer constructor + */ +ASEnhancer::ASEnhancer() +{ +} + +/** + * Destructor of ASEnhancer + */ +ASEnhancer::~ASEnhancer() +{ +} + +/** + * 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<const pair<const string, const string>* >* _indentableMacros) +{ + // formatting variables from ASFormatter and ASBeautifier + ASBase::init(_fileType); + indentLength = _indentLength; + tabLength = _tabLength; + useTabs = _useTabs; + forceTab = _forceTab; + namespaceIndent = _namespaceIndent; + caseIndent = _caseIndent; + preprocBlockIndent = _preprocBlockIndent; + preprocDefineIndent = _preprocDefineIndent; + emptyLineFill = _emptyLineFill; + indentableMacros = _indentableMacros; + quoteChar = '\''; + + // unindent variables + lineNumber = 0; + braceCount = 0; + isInComment = false; + isInQuote = false; + switchDepth = 0; + eventPreprocDepth = 0; + lookingForCaseBrace = false; + unindentNextLine = false; + shouldUnindentLine = false; + shouldUnindentComment = false; + + // switch struct and vector + sw.switchBraceCount = 0; + sw.unindentDepth = 0; + sw.unindentCase = false; + switchStack.clear(); + + // other variables + nextLineIsEventIndent = false; + isInEventTable = false; + nextLineIsDeclareIndent = false; + isInDeclareSection = false; +} + +/** + * additional formatting for line of source code. + * every line of source code in a source code file should be sent + * one after the other to this function. + * indents event tables + * unindents the case blocks + * + * @param line the original formatted line will be updated if necessary. + */ +void ASEnhancer::enhance(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; + } + else if (line[i] == quoteChar_) // check ending quote + { + isInQuote_ = false; + quoteChar_ = ' '; + continue; + } + else + { + 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 (size_t j = 0; j < word.length(); j++) + word[j] = (char) toupper(word[j]); + 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 (size_t j = 0; j < word.length(); j++) + word[j] = (char) toupper(word[j]); + 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 + } + else 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; + } + else 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 (size_t j = 0; j < indentableMacros->size(); j++) + { + // 'first' is the beginning macro + if (findKeyword(line, i, indentableMacros->at(j)->first)) + { + nextLineIsEventIndent = true; + break; + } + } + for (size_t j = 0; j < indentableMacros->size(); j++) + { + // 'second' is the ending macro + if (findKeyword(line, i, indentableMacros->at(j)->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--; + assert(sw.switchBraceCount <= braceCount); + 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/astyle/src/ASFormatter.cpp b/astyle/src/ASFormatter.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b292305ba1d5992e29c787fd26ec4fefca732dd6 --- /dev/null +++ b/astyle/src/ASFormatter.cpp @@ -0,0 +1,7714 @@ +// ASFormatter.cpp +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// This code is licensed under the MIT License. +// License.md describes the conditions under which this software may be distributed. + +//----------------------------------------------------------------------------- +// headers +//----------------------------------------------------------------------------- + +#include "astyle.h" + +#include <algorithm> +#include <fstream> + +//----------------------------------------------------------------------------- +// 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; + 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<const string*>; + nonParenHeaders = new vector<const string*>; + preDefinitionHeaders = new vector<const string*>; + preCommandHeaders = new vector<const string*>; + operators = new vector<const string*>; + assignmentOperators = new vector<const string*>; + castOperators = new vector<const string*>; + + // initialize ASEnhancer member vectors + indentableMacros = new vector<const pair<const string, const string>* >; +} + +/** + * 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<const string*>); + initContainer(parenStack, new vector<int>); + initContainer(structStack, new vector<bool>); + initContainer(questionMarkStack, new vector<bool>); + parenStack->emplace_back(0); // parenStack must contain this default entry + initContainer(braceTypeStack, new vector<BraceType>); + braceTypeStack->emplace_back(NULL_TYPE); // braceTypeStack must contain this default entry + clearFormattedLineSplitPoints(); + + currentHeader = nullptr; + currentLine = ""; + readyFormattedLine = ""; + formattedLine = ""; + verbatimDelimiter = ""; + currentChar = ' '; + previousChar = ' '; + previousCommandChar = ' '; + previousNonWSChar = ' '; + quoteChar = '"'; + preprocBlockEnd = 0; + charNum = 0; + checksumIn = 0; + checksumOut = 0; + currentLineFirstBraceNum = string::npos; + formattedLineCommentNum = 0; + leadingSpaces = 0; + previousReadyFormattedLineLength = string::npos; + preprocBraceTypeStackSize = 0; + spacePadNum = 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; + isInPreprocessorBeautify = false; + doesLineStartComment = false; + lineEndsInCommentOnly = false; + lineIsCommentOnly = false; + lineIsLineCommentOnly = false; + lineIsEmpty = 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; + isInObjCSelector = false; + breakCurrentOneLineBlock = false; + shouldRemoveNextClosingBrace = false; + isInBraceRunIn = 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_BANNER) + { + // 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_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 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; + } + else if (isInComment) + { + formatCommentBody(); + continue; + } + + else if (isInQuote) + { + formatQuoteBody(); + continue; + } + + // not in quote or comment or line comment + + if (isSequenceReached("//")) + { + formatLineCommentOpener(); + testForTimeToSplitFormattedLine(); + continue; + } + else if (isSequenceReached("/*")) + { + formatCommentOpener(); + testForTimeToSplitFormattedLine(); + continue; + } + else if (currentChar == '"' + || (currentChar == '\'' && !isDigitSeparator(currentLine, charNum))) + { + formatQuoteOpener(); + testForTimeToSplitFormattedLine(); + continue; + } + // treat these preprocessor statements as a line comment + else 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) + { + 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 == '#') + { + 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 + && (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<bar> or foo<bar,fig> + if (!isInTemplate && currentChar == '<') + { + checkIfTemplateOpener(); + } + + // handle parens + if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<')) + { + 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; + isInObjCInterface = false; + isInEnum = false; + isJavaStaticConstructor = false; + isCharImmediatelyPostNonInStmt = false; + needHeaderOpeningBrace = false; + shouldKeepLineUnbroken = false; + objCColonAlign = 0; + + isPreviousBraceBlockRelated = !isBraceType(newBraceType, ARRAY_TYPE); + braceTypeStack->emplace_back(newBraceType); + preBraceHeaderStack->emplace_back(currentHeader); + currentHeader = nullptr; + 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; + + // look for headers + bool isPotentialHeader = isCharPotentialHeader(currentLine, charNum); + + if (isPotentialHeader && !isInTemplate && squareBracketCount == 0) + { + isNonParenHeader = false; + foundClosingHeader = false; + + newHeader = findHeader(headers); + + // 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; + } + + // TODO: this can be removed in a future release + // version 3.0 - break erroneous attached header from previous versions + if (isSharpStyle() + && ((newHeader == &AS_SET && currentHeader == &AS_GET) + || (newHeader == &AS_REMOVE && currentHeader == &AS_ADD)) + && !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE) + && currentLine[currentLine.find_first_not_of(" \t")] == '}') + isInLineBreak = true; + // END TODO + + 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; + } + else 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) + foundInterfaceHeader = true; + foundPreDefinitionHeader = true; + appendSequence(*newHeader); + goForward(newHeader->length() - 1); + + continue; + } + else if ((newHeader = findHeader(preCommandHeaders)) != nullptr) + { + // a 'const' variable is not a preCommandHeader + 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; + + 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() + && shouldPadMethodColon + && (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector) + && !foundQuestionMark) // not in a ?: sequence + 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; // return is the same as an = sign + isImmediatelyPostReturn = true; + } + + 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(), NAMESPACE_TYPE) + || isBraceType(braceTypeStack->back(), CLASS_TYPE))) + foundTrailingReturnType = 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 == '@' + && 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; + } + else if (currentChar == '@' + && isCharPotentialHeader(currentLine, charNum + 1) + && findKeyword(currentLine, charNum + 1, AS_SELECTOR)) + { + isInObjCSelector = true; + string name = '@' + AS_SELECTOR; + appendSequence(name); + goForward(name.length() - 1); + continue; + } + else if ((currentChar == '-' || currentChar == '+') + && (int) currentLine.find_first_not_of(" \t") == charNum + && peekNextChar() == '(' + && isBraceType(braceTypeStack->back(), NULL_TYPE) + && !isInPotentialCalculation) + { + isInObjCMethodDefinition = true; + isImmediatelyPostObjCMethodPrefix = true; + 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 (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 compatability 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 compatability 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 compatability 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 compatability 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; +} + +/** + * 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 + + // 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))) + isInPreprocessor = 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 inside a command brace. + // if yes then read the next line (calls getNextLine recursively). + // must be after initNewLine. + if (shouldDeleteEmptyLines + && lineIsEmpty + && isBraceType((*braceTypeStack)[braceTypeStack->size() - 1], COMMAND_TYPE)) + { + 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; + 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) + 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) || 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; +} + +/** +* 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 = " "; + char nextChar = nextText[0]; + if (isDigit(lastWord[0]) + || isDigit(nextChar) + || nextChar == '!' + || nextChar == '~') + return false; + + // check for multiply then a dereference (a * *b) + if (currentChar == '*' + && charNum < (int) currentLine.length() - 1 + && isWhiteSpace(currentLine[charNum + 1]) + && nextChar == '*') + 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 (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 *& (cannot have &*) + 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 +{ + return (word == "char" + || 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"); +} + +/** + * 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 == '-'); + + return ((isCharImmediatelyPostReturn || !isLegalNameChar(previousCommandChar)) + && 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) + { + char prevPrevFormattedChar = currentLine[charNum - 2]; + char prevFormattedChar = currentLine[charNum - 1]; + return ((prevFormattedChar == 'e' || prevFormattedChar == 'E') + && (prevPrevFormattedChar == '.' || isDigit(prevPrevFormattedChar))); + } + 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 + && charNum == (int) 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 (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; + 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)) + 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*/, + shared_ptr<ASPeekStream> streamArg /*nullptr*/) const +{ + bool isFirstLine = true; + string nextLine_ = firstLine; + size_t firstChar = string::npos; + shared_ptr<ASPeekStream> stream = streamArg; + if (stream == nullptr) // Borland may need == 0 + stream = make_shared<ASPeekStream>(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; + if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos) + 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(ptrLength, currentChar); + 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(); + + size_t prevCh = formattedLine.find_last_not_of(" \t"); + if (prevCh == string::npos) + prevCh = 0; + if (formattedLine.length() == 0 || prevCh == formattedLine.length() - 1) + formattedLine.append(1, currentChar); + else + { + // exchange * or & with character following the type + // this may not work every time with a tab character + string charSave = formattedLine.substr(prevCh + 1, 1); + formattedLine[prevCh + 1] = currentChar; + formattedLine.append(charSave); + } + if (isSequenceReached("**") || isSequenceReached("&&")) + { + if (formattedLine.length() == 1) + formattedLine.append(1, currentChar); + else + formattedLine.insert(prevCh + 2, 1, currentChar); + goForward(1); + } + // 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) + { + 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 (isSequenceReached("**")) + { + sequenceToInsert = "**"; + goForward(1); + } + else if (isSequenceReached("&&")) + { + sequenceToInsert = "&&"; + goForward(1); + } + // 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; + formattedLine.insert(index, 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 (isSequenceReached("**")) + { + sequenceToInsert = "**"; + goForward(1); + } + else if (isSequenceReached("&&")) + { + sequenceToInsert = "&&"; + goForward(1); + } + // 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 (!isBeforeAnyComment() + && (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", charNum + 1); + if (start != string::npos && currentLine[start] != ')') + break; + } + goForward(1); + if (formattedLine.length() > 0) + formattedLine.append(1, currentLine[i]); + 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]) + && !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 (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; + else if (prevWord == AS_RETURN) // don't unpad + prevIsParenHeader = true; + else if ((prevWord == AS_NEW || prevWord == AS_DELETE) + && shouldPadHeader) // don't unpad + prevIsParenHeader = true; + else if (isCStyle() && prevWord == AS_THROW && shouldPadHeader) // don't unpad + prevIsParenHeader = true; + else if (prevWord == "and" || prevWord == "or" || prevWord == "in") // don't unpad + prevIsParenHeader = true; + // don't unpad variables + else if (prevWord == "bool" + || prevWord == "int" + || prevWord == "void" + || prevWord == "void*" + || prevWord == "char" + || prevWord == "char*" + || prevWord == "long" + || prevWord == "double" + || prevWord == "float" + || (prevWord.length() >= 4 // check end of word for _t + && prevWord.compare(prevWord.length() - 2, 2, "_t") == 0) + || prevWord == "Int32" + || prevWord == "UInt32" + || prevWord == "Int64" + || prevWord == "UInt64" + || prevWord == "BOOL" + || prevWord == "DWORD" + || prevWord == "HWND" + || prevWord == "INT" + || prevWord == "LPSTR" + || prevWord == "VOID" + || prevWord == "LPVOID" + ) + { + prevIsParenHeader = true; + } + } + } + // 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 parens +* these options have precedence over the padParens methods +* the padParens method has already been called, this method adjusts +*/ +void ASFormatter::padObjCMethodPrefix() +{ + assert(currentChar == '(' && isImmediatelyPostObjCMethodPrefix); + assert(shouldPadMethodPrefix || shouldUnPadMethodPrefix); + + size_t prefix = formattedLine.find_first_of("+-"); + if (prefix == string::npos) + return; + size_t paren = formattedLine.find_first_of('('); + if (paren == string::npos) + return; + int spaces = paren - prefix - 1; + + if (shouldPadMethodPrefix) + { + if (spaces == 0) + { + formattedLine.insert(prefix + 1, 1, ' '); + spacePadNum += 1; + } + else if (spaces > 1) + { + formattedLine.erase(prefix + 1, spaces - 1); + 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); + 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] == ' ') + { + spacePadNum -= formattedLine.length() - 1 - nextText; + 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; + } + } +} + +/** +* 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); + 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); + 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)) + { + // 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 && charNum == (int) 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 + && (int) currentLineFirstBraceNum == 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()) + { + // 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 + && (int) currentLineFirstBraceNum == charNum + && !isBraceType(braceType, SINGLE_LINE_TYPE)) + shouldBreakLineAtNextChar = true; + } + else if (braceFormatMode == RUN_IN_MODE) + { + if (isWhiteSpace(peekNextChar()) && !isInVirginLine) + breakLine(); + else if (isBeforeAnyComment()) + { + // 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 + && charNum == (int) 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 == '[') + 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<BraceType>*& 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<typename T> +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<BraceType>*& container, vector<BraceType>* 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<typename T> +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(); + } + } +} + +/** + * 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<ASPeekStream>(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 + && (int) currentLineFirstBraceNum == charNum) + breakBrace = true; + } + else if (braceFormatMode == BREAK_MODE || braceFormatMode == RUN_IN_MODE) + { + breakBrace = true; + } + else if (braceFormatMode == LINUX_MODE) + { + // break a namespace if NOT stroustrup or mozilla + if (isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE)) + { + if (formattingStyle != STYLE_STROUSTRUP + && formattingStyle != STYLE_MOZILLA) + breakBrace = true; + } + // break a class or interface if NOT stroustrup + else if (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE) + || isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE)) + { + if (formattingStyle != STYLE_STROUSTRUP) + 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 "} <NL> 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 "} <NL> 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; + } + + // 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; +} + +/** + * 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 proproc + int numBlockIndents = 0; + int lineParenCount = 0; + string nextLine_ = firstLine.substr(index); + auto stream = make_shared<ASPeekStream>(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 && 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 (size_t i = 0; i < word.length(); i++) + word[i] = (char) toupper(word[i]); + 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 (size_t i = 0; i < word.length(); i++) + word[i] = (char) toupper(word[i]); + 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; + } + else if (currentChar_ == '>') + { + --templateDepth; + if (templateDepth == 0) + { + if (parenDepth_ == 0) + { + // this is a template! + isInTemplate = true; + templateDepth = maxTemplateDepth; + } + return; + } + continue; + } + else if (currentChar_ == '(' || currentChar_ == ')') + { + if (currentChar_ == '(') + ++parenDepth_; + else + --parenDepth_; + if (parenDepth_ >= 0) + continue; + // this is not a template -> leave... + isInTemplate = false; + templateDepth = 0; + return; + } + else 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; + } + else if (currentChar_ == ',' // comma, e.g. A<int, char> + || currentChar_ == '&' // reference, e.g. A<int&> + || currentChar_ == '*' // pointer, e.g. A<int*> + || currentChar_ == '^' // C++/CLI managed pointer, e.g. A<int^> + || 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; + } + else 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 (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 (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 (size_t i = 0; i < currentLine_.length(); i++) + if (!isWhiteSpace(currentLine_[i])) + checksumIn += currentLine_[i]; + 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 (size_t i = 0; i < beautifiedLine.length(); i++) + if (!isWhiteSpace(beautifiedLine[i])) + checksumOut += beautifiedLine[i]; + 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; + isInObjCInterface = false; + isInObjCSelector = false; + isInEnum = false; + isInExternC = false; + elseHeaderFollowsComments = 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; + 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; + // compute colon adjustment + if (nextLine_[i] == ':') + { + 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; + } + appendSpacePad(); + } + if (objCColonPadMode == COLON_PAD_NONE + || objCColonPadMode == COLON_PAD_BEFORE + || nextChar == ')') + { + // remove spaces after + int nextText = currentLine.find_first_not_of(" \t", charNum + 1); + if (nextText == (int)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 + int nextText = currentLine.find_first_not_of(" \t", charNum + 1); + if (nextText == (int)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); + 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/astyle/src/ASLocalizer.cpp b/astyle/src/ASLocalizer.cpp new file mode 100755 index 0000000000000000000000000000000000000000..083f68a2bb359e09a4d6f5e736eae155bca8e3cb --- /dev/null +++ b/astyle/src/ASLocalizer.cpp @@ -0,0 +1,1092 @@ +// ASLocalizer.cpp +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// 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 +// Ukranian - 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 <windows.h> +#endif + +#ifdef __VMS + #define __USE_STD_IOSTREAM 1 + #include <assert> +#else + #include <cassert> +#endif + +#include <cstdio> +#include <iostream> +#include <clocale> // needed by some compilers +#include <cstdlib> +#include <typeinfo> + +#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_localeName = "UNKNOWN"; + m_langID = "en"; + m_lcid = 0; + m_subLangID.clear(); + m_translation = 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); +#else + setLanguageFromName(localeName); +#endif +} + +ASLocalizer::~ASLocalizer() +// Delete dynamically allocated memory. +{ + delete m_translation; +} + +#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 + size_t count = sizeof(wlc) / sizeof(wlc[0]); + for (size_t i = 0; i < count; i++) + { + if (wlc[i].winLang == lang) + { + m_langID = wlc[i].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_translation); + return m_translation; +} + +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 + m_lcid = 0; + 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_translation); + const string stringIn = textIn; + return m_translation->translate(stringIn).c_str(); +} + +void ASLocalizer::setTranslationClass() +// Return the required translation class. +// Sets the class variable m_translation 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_translation != nullptr) + { + delete m_translation; + m_translation = nullptr; + } + if (m_langID == "bg") + m_translation = new Bulgarian; + else if (m_langID == "zh" && m_subLangID == "CHS") + m_translation = new ChineseSimplified; + else if (m_langID == "zh" && m_subLangID == "CHT") + m_translation = new ChineseTraditional; + else if (m_langID == "nl") + m_translation = new Dutch; + else if (m_langID == "en") + m_translation = new English; + else if (m_langID == "et") + m_translation = new Estonian; + else if (m_langID == "fi") + m_translation = new Finnish; + else if (m_langID == "fr") + m_translation = new French; + else if (m_langID == "de") + m_translation = new German; + else if (m_langID == "el") + m_translation = new Greek; + else if (m_langID == "hi") + m_translation = new Hindi; + else if (m_langID == "hu") + m_translation = new Hungarian; + else if (m_langID == "it") + m_translation = new Italian; + else if (m_langID == "ja") + m_translation = new Japanese; + else if (m_langID == "ko") + m_translation = new Korean; + else if (m_langID == "nn") + m_translation = new Norwegian; + else if (m_langID == "pl") + m_translation = new Polish; + else if (m_langID == "pt") + m_translation = new Portuguese; + else if (m_langID == "ro") + m_translation = new Romanian; + else if (m_langID == "ru") + m_translation = new Russian; + else if (m_langID == "es") + m_translation = new Spanish; + else if (m_langID == "sv") + m_translation = new Swedish; + else if (m_langID == "uk") + m_translation = new Ukrainian; + else // default + m_translation = new English; +} + +//---------------------------------------------------------------------------- +// Translation base class methods. +//---------------------------------------------------------------------------- + +void Translation::addPair(const string& english, const wstring& translated) +// Add a string pair to the translation vector. +{ + pair<string, wstring> entry(english, translated); + m_translation.emplace_back(entry); +} + +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; +} + +size_t Translation::getTranslationVectorSize() const +// Return the translation vector size. Used for testing. +{ + return m_translation.size(); +} + +bool Translation::getWideTranslation(const string& stringIn, wstring& wideOut) const +// Get the wide translation string. Used for testing. +{ + for (size_t i = 0; i < m_translation.size(); i++) + { + if (m_translation[i].first == stringIn) + { + wideOut = m_translation[i].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 (size_t i = 0; i < m_translation.size(); i++) + { + if (m_translation[i].first == stringIn) + { + m_mbTranslation = convertToMultiByte(m_translation[i].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("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("Using default options file %s\n", L"Използване на файла възможноÑти по подразбиране %s\n"); + addPair("Opening HTML documentation %s\n", L"Откриване HTML Ð´Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ %s\n"); + addPair("Invalid option file options:", L"Ðевалидни опции Ð¾Ð¿Ñ†Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ðµ:"); + addPair("Invalid command line options:", L"Ðевалидни опции за ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¸Ñ Ñ€ÐµÐ´:"); + addPair("For help on options type 'astyle -h'", L"За помощ отноÑно възможноÑтите тип 'astyle -h'"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style е прекратено"); +} + +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("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("Using default options file %s\n", L"使用默认é…置文件 %s\n"); + addPair("Opening HTML documentation %s\n", L"打开HTML文档 %s\n"); + addPair("Invalid option file options:", L"æ— æ•ˆçš„é…置文件选项:"); + addPair("Invalid command line options:", L"æ— æ•ˆçš„å‘½ä»¤è¡Œé€‰é¡¹:"); + addPair("For help on options type 'astyle -h'", L"输入 'astyle -h' 以获得有关命令行的帮助"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style å·²ç»ç»ˆæ¢è¿è¡Œ"); +} + +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("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("Using default options file %s\n", L"使用默èªé…置文件 %s\n"); + addPair("Opening HTML documentation %s\n", L"打開HTML文檔 %s\n"); + addPair("Invalid option file options:", L"無效的é…置文件é¸é …:"); + addPair("Invalid command line options:", L"無效的命令行é¸é …:"); + addPair("For help on options type 'astyle -h'", L"輸入'astyle -h'以ç²å¾—有關命令行的幫助:"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style 已經終æ¢é‹è¡Œ"); +} + +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("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("Using default options file %s\n", L"Met behulp van standaard opties bestand %s\n"); + addPair("Opening HTML documentation %s\n", L"Het openen van HTML-documentatie %s\n"); + addPair("Invalid option file options:", L"Ongeldige optie file opties:"); + 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 options file", L"Kan niet worden geopend options bestand"); + 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("\nArtistic Style has terminated", L"\nArtistic Style heeft beëindigd"); +} + +English::English() +// 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("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("Using default options file %s\n", L"Kasutades selliseid vaikimisi valikuid faili %s\n"); + addPair("Opening HTML documentation %s\n", L"Avamine HTML dokumentatsioon %s\n"); + addPair("Invalid option file options:", L"Vale valik faili võimalusi:"); + 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 options file", L"Ei saa avada võimalusi faili"); + 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("\nArtistic Style has terminated", L"\nArtistic Style on lõpetatud"); +} + +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("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("Using default options file %s\n", L"Käyttämällä oletusasetuksia tiedosto %s\n"); + addPair("Opening HTML documentation %s\n", L"Avaaminen HTML asiakirjat %s\n"); + addPair("Invalid option file options:", L"Virheellinen vaihtoehto tiedosto vaihtoehtoja:"); + 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 options file", L"Ei voi avata vaihtoehtoja tiedostoa"); + 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("\nArtistic Style has terminated", L"\nArtistic Style on päättynyt"); +} + +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("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("Using default options file %s\n", L"Options par défaut utilisation du fichier %s\n"); + addPair("Opening HTML documentation %s\n", L"Ouverture documentation HTML %s\n"); + addPair("Invalid option file options:", L"Options Blancs option du fichier:"); + 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 options file", L"Impossible d'ouvrir le fichier d'options"); + 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("\nArtistic Style has terminated", L"\nArtistic Style a mis fin"); +} + +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("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("Using default options file %s\n", L"Mit Standard-Optionen Dat %s\n"); + addPair("Opening HTML documentation %s\n", L"Öffnen HTML-Dokumentation %s\n"); + addPair("Invalid option file options:", L"Ungültige Option Datei-Optionen:"); + 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 options file", L"Kann nicht geöffnet werden Optionsdatei"); + 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("\nArtistic Style has terminated", L"\nArtistic Style ist beendet"); +} + +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("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("Using default options file %s\n", L"ΧÏησιμοποιώντας το αÏχείο Ï€ÏοεπιλεγμÎνες επιλογÎÏ‚ %s\n"); + addPair("Opening HTML documentation %s\n", L"Εγκαίνια ÎγγÏαφα HTML %s\n"); + addPair("Invalid option file options:", L"Μη ÎγκυÏες επιλογÎÏ‚ αÏχείου επιλογή:"); + addPair("Invalid command line options:", L"Μη ÎγκυÏη επιλογÎÏ‚ γÏαμμής εντολών:"); + addPair("For help on options type 'astyle -h'", L"Για βοήθεια σχετικά με το είδος επιλογÎÏ‚ 'astyle -h'"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style Îχει λήξει"); +} + +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("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("Using default options file %s\n", L"डिफ़ॉलà¥à¤Ÿ विकलà¥à¤ª का उपयोग कर फ़ाइल %s\n"); + addPair("Opening HTML documentation %s\n", L"à¤à¤šà¤Ÿà¥€à¤à¤®à¤à¤² पà¥à¤°à¤²à¥‡à¤–न खोलना %s\n"); + addPair("Invalid option file options:", L"अवैध विकलà¥à¤ª फ़ाइल विकलà¥à¤ª हैं:"); + addPair("Invalid command line options:", L"कमांड लाइन विकलà¥à¤ª अवैध:"); + addPair("For help on options type 'astyle -h'", L"विकलà¥à¤ªà¥‹à¤‚ पर मदद के लिठपà¥à¤°à¤•à¤¾à¤° 'astyle -h'"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style समापà¥à¤¤ किया है"); +} + +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("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("Using default options file %s\n", L"Az alapértelmezett beállÃtások fájl %s\n"); + addPair("Opening HTML documentation %s\n", L"Nyitó HTML dokumentáció %s\n"); + addPair("Invalid option file options:", L"Érvénytelen opció fájlbeállÃtást:"); + 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 options file", L"Nem lehet megnyitni beállÃtási fájlban"); + 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("\nArtistic Style has terminated", L"\nArtistic Style megszűnt"); +} + +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("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("Using default options file %s\n", L"Utilizzando file delle opzioni di default %s\n"); + addPair("Opening HTML documentation %s\n", L"Apertura di documenti HTML %s\n"); + addPair("Invalid option file options:", L"Opzione non valida file delle opzioni:"); + 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 options file", L"Impossibile aprire il file opzioni"); + 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("\nArtistic Style has terminated", L"\nArtistic Style ha terminato"); +} + +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("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("Using default options file %s\n", L"デフォルトã®ã‚ªãƒ—ションファイルを使用ã—ã¦ã€ %s\n"); + addPair("Opening HTML documentation %s\n", L"オープニングHTMLドã‚ュメント %s\n"); + addPair("Invalid option file options:", L"無効ãªã‚ªãƒ—ションファイルã®ã‚ªãƒ—ション:"); + addPair("Invalid command line options:", L"無効ãªã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚ªãƒ—ション:"); + addPair("For help on options type 'astyle -h'", L"コオプションã®ç¨®é¡žã®ãƒ˜ãƒ«ãƒ—ã«ã¤ã„ã¦'astyle- h'を入力ã—ã¦ãã ã•ã„"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style 終了ã—ã¾ã—ãŸ"); +} + +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("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("Using default options file %s\n", L"기본 구성 파ì¼ì„ 사용 %s\n"); + addPair("Opening HTML documentation %s\n", L"HTML 문서를 열기 %s\n"); + addPair("Invalid option file options:", L"ìž˜ëª»ëœ êµ¬ì„± íŒŒì¼ ì˜µì…˜ :"); + addPair("Invalid command line options:", L"ìž˜ëª»ëœ ëª…ë ¹ì¤„ 옵션 :"); + addPair("For help on options type 'astyle -h'", L"ë„움ë§ì„ ë³´ë ¤ë©´ 옵션 ìœ í˜• 'astyle - H'를 사용합니다"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style를 종료합니다"); +} + +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("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("Using default options file %s\n", L"Ved hjelp av standardalternativer fil %s\n"); + addPair("Opening HTML documentation %s\n", L"Ã…pning HTML dokumentasjon %s\n"); + addPair("Invalid option file options:", L"Ugyldige alternativ filalternativer:"); + 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 options file", L"Kan ikke Ã¥pne alternativer fil"); + 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("\nArtistic Style has terminated", L"\nArtistic Style har avsluttet"); +} + +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("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("Using default options file %s\n", L"Korzystanie z domyÅ›lnej opcji %s plik\n"); + addPair("Opening HTML documentation %s\n", L"Otwarcie dokumentacji HTML %s\n"); + addPair("Invalid option file options:", L"NieprawidÅ‚owy opcji pliku opcji:"); + 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 options file", L"Nie można otworzyć pliku opcji"); + 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("\nArtistic Style has terminated", L"\nArtistic Style zostaÅ‚ zakoÅ„czony"); +} + +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("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("Using default options file %s\n", L"Usando o arquivo de opções padrão %s\n"); + addPair("Opening HTML documentation %s\n", L"Abrindo a documentação HTML %s\n"); + addPair("Invalid option file options:", L"Opções de arquivo inválido opção:"); + 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 options file", L"Não é possÃvel abrir arquivo de opções"); + 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("\nArtistic Style has terminated", L"\nArtistic Style terminou"); +} + +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("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("Using default options file %s\n", L"FiÈ™ier folosind opÈ›iunile implicite %s\n"); + addPair("Opening HTML documentation %s\n", L"DocumentaÈ›ie HTML deschidere %s\n"); + addPair("Invalid option file options:", L"OpÈ›iuni de opÈ›iune de fiÈ™ier 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 options file", L"Nu se poate deschide fiÈ™ierul de opÈ›iuni"); + 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("\nArtistic Style has terminated", L"\nArtistic Style a terminat"); +} + +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("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("Using default options file %s\n", L"ИÑпользование опции по умолчанию файл %s\n"); + addPair("Opening HTML documentation %s\n", L"Открытие HTML документации %s\n"); + addPair("Invalid option file options:", L"ÐедопуÑтимый файл опций опцию:"); + addPair("Invalid command line options:", L"ÐедопуÑтимые параметры командной Ñтроки:"); + addPair("For help on options type 'astyle -h'", L"Ð”Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ñправки по 'astyle -h' опций типа"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style прекратил"); +} + +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("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("Using default options file %s\n", L"Uso de las opciones por defecto del archivo %s\n"); + addPair("Opening HTML documentation %s\n", L"Apertura de documentación HTML %s\n"); + addPair("Invalid option file options:", L"Opción no válida opciones de archivo:"); + 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 options file", L"No se puede abrir el archivo de opciones"); + 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("\nArtistic Style has terminated", L"\nArtistic Style ha terminado"); +} + +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("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("Using default options file %s\n", L"Använda standardalternativ fil %s\n"); + addPair("Opening HTML documentation %s\n", L"Öppna HTML-dokumentation %s\n"); + addPair("Invalid option file options:", L"Ogiltigt alternativ fil alternativ:"); + 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 options file", L"Kan inte öppna inställningsfilen"); + 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("\nArtistic Style has terminated", L"\nArtistic Style har upphört"); +} + +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("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("Using default options file %s\n", L"ВикориÑÑ‚Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² опцій за замовчуваннÑм %s\n"); + addPair("Opening HTML documentation %s\n", L"Ð’Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ HTML документації %s\n"); + addPair("Invalid option file options:", L"ÐеприпуÑтимий файл опцій опцію:"); + addPair("Invalid command line options:", L"ÐеприпуÑтима параметри командного Ñ€Ñдка:"); + addPair("For help on options type 'astyle -h'", L"Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð²Ñ–Ð´ÐºÐ¸ по 'astyle -h' опцій типу"); + addPair("Cannot open options 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("\nArtistic Style has terminated", L"\nArtistic Style припинив"); +} + + +#endif // ASTYLE_LIB + +} // end of namespace astyle + diff --git a/astyle/src/ASLocalizer.h b/astyle/src/ASLocalizer.h new file mode 100755 index 0000000000000000000000000000000000000000..c62f3a1bf711f2e29466e0a7b7913d9ee0f0cac3 --- /dev/null +++ b/astyle/src/ASLocalizer.h @@ -0,0 +1,159 @@ +// ASLocalizer.h +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// This code is licensed under the MIT License. +// License.md describes the conditions under which this software may be distributed. + + +#ifndef ASLOCALIZER_H +#define ASLOCALIZER_H + +#include <string> +#include <vector> + +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_translation; // pointer to a polymorphic Translation class + string m_langID; // language identifier from the locale + string m_subLangID; // sub language identifier, if needed + string m_localeName; // name of the current locale (Linux only) + size_t m_lcid; // LCID of the user locale (Windows only) +}; + +//---------------------------------------------------------------------------- +// 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() {} + string convertToMultiByte(const wstring& wideStr) 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<pair<string, wstring> > m_translation; // translation vector + +private: + 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/astyle/src/ASResource.cpp b/astyle/src/ASResource.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f814bdf18ea287aea56e102be7dc56198dce385b --- /dev/null +++ b/astyle/src/ASResource.cpp @@ -0,0 +1,833 @@ +// ASResource.cpp +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// This code is licensed under the MIT License. +// License.md describes the conditions under which this software may be distributed. + +//----------------------------------------------------------------------------- +// headers +//----------------------------------------------------------------------------- + +#include "astyle.h" +#include <algorithm> + +//----------------------------------------------------------------------------- +// 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_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_GCC_MAX_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_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<const string*>* assignmentOperators) +{ + const size_t elements = 15; + static bool reserved = false; + if (!reserved) + { + assignmentOperators->reserve(elements); + reserved = true; + } + + 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<const string*>* castOperators) +{ + const size_t elements = 5; + static bool reserved = false; + if (!reserved) + { + castOperators->reserve(elements); + reserved = true; + } + + 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<const string*>* headers, int fileType, bool beautifier) +{ + const size_t elements = 25; + static bool reserved = false; + if (!reserved) + { + headers->reserve(elements); + reserved = true; + } + + 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<const string*>* 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<const pair<const string, const string>* >* indentableMacros) +{ + const size_t elements = 10; + static bool reserved = false; + if (!reserved) + { + indentableMacros->reserve(elements); + reserved = true; + } + + // the pairs must be retained in memory because of pair pointers + typedef pair<const string, const string> macro_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"), + }; + + size_t entries = sizeof(macros) / sizeof(macros[0]); + for (size_t i = 0; i < entries; i++) + indentableMacros->emplace_back(¯os[i]); + + 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<const string*>* nonAssignmentOperators) +{ + const size_t elements = 15; + static bool reserved = false; + if (!reserved) + { + nonAssignmentOperators->reserve(elements); + reserved = true; + } + + 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); + + 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<const string*>* nonParenHeaders, int fileType, bool beautifier) +{ + const size_t elements = 20; + static bool reserved = false; + if (!reserved) + { + nonParenHeaders->reserve(elements); + reserved = true; + } + + 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<const string*>* operators, int fileType) +{ + const size_t elements = 50; + static bool reserved = false; + if (!reserved) + { + operators->reserve(elements); + reserved = true; + } + + + operators->emplace_back(&AS_PLUS_ASSIGN); + operators->emplace_back(&AS_MINUS_ASSIGN); + operators->emplace_back(&AS_MULT_ASSIGN); + operators->emplace_back(&AS_DIV_ASSIGN); + operators->emplace_back(&AS_MOD_ASSIGN); + operators->emplace_back(&AS_OR_ASSIGN); + operators->emplace_back(&AS_AND_ASSIGN); + operators->emplace_back(&AS_XOR_ASSIGN); + operators->emplace_back(&AS_EQUAL); + operators->emplace_back(&AS_PLUS_PLUS); + operators->emplace_back(&AS_MINUS_MINUS); + operators->emplace_back(&AS_NOT_EQUAL); + operators->emplace_back(&AS_GR_EQUAL); + operators->emplace_back(&AS_GR_GR_GR_ASSIGN); + operators->emplace_back(&AS_GR_GR_ASSIGN); + operators->emplace_back(&AS_GR_GR_GR); + operators->emplace_back(&AS_GR_GR); + operators->emplace_back(&AS_LS_EQUAL); + operators->emplace_back(&AS_LS_LS_LS_ASSIGN); + operators->emplace_back(&AS_LS_LS_ASSIGN); + operators->emplace_back(&AS_LS_LS_LS); + operators->emplace_back(&AS_LS_LS); + operators->emplace_back(&AS_QUESTION_QUESTION); + operators->emplace_back(&AS_LAMBDA); + operators->emplace_back(&AS_ARROW); + operators->emplace_back(&AS_AND); + operators->emplace_back(&AS_OR); + operators->emplace_back(&AS_SCOPE_RESOLUTION); + operators->emplace_back(&AS_PLUS); + operators->emplace_back(&AS_MINUS); + operators->emplace_back(&AS_MULT); + operators->emplace_back(&AS_DIV); + operators->emplace_back(&AS_MOD); + operators->emplace_back(&AS_QUESTION); + operators->emplace_back(&AS_COLON); + operators->emplace_back(&AS_ASSIGN); + operators->emplace_back(&AS_LS); + operators->emplace_back(&AS_GR); + operators->emplace_back(&AS_NOT); + operators->emplace_back(&AS_BIT_OR); + operators->emplace_back(&AS_BIT_AND); + operators->emplace_back(&AS_BIT_NOT); + operators->emplace_back(&AS_BIT_XOR); + if (fileType == C_TYPE) + { + operators->emplace_back(&AS_GCC_MIN_ASSIGN); + operators->emplace_back(&AS_GCC_MAX_ASSIGN); + } + + 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<const string*>* preBlockStatements, int fileType) +{ + const size_t elements = 10; + static bool reserved = false; + if (!reserved) + { + preBlockStatements->reserve(elements); + reserved = true; + } + + 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<const string*>* preCommandHeaders, int fileType) +{ + const size_t elements = 10; + static bool reserved = false; + if (!reserved) + { + preCommandHeaders->reserve(elements); + reserved = true; + } + + if (fileType == C_TYPE) + { + preCommandHeaders->emplace_back(&AS_CONST); + preCommandHeaders->emplace_back(&AS_VOLATILE); + preCommandHeaders->emplace_back(&AS_INTERRUPT); + preCommandHeaders->emplace_back(&AS_NOEXCEPT); + preCommandHeaders->emplace_back(&AS_OVERRIDE); + 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<const string*>* preDefinitionHeaders, int fileType) +{ + const size_t elements = 10; + static bool reserved = false; + if (!reserved) + { + preDefinitionHeaders->reserve(elements); + reserved = true; + } + + 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<const string*>* 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 + else 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<const string*>* possibleOperators) const +{ + assert(isCharPotentialOperator(line[i])); + // find the operator in the vector + // the vector contains the LONGEST operators first + // must loop thru the entire vector + size_t maxOperators = possibleOperators->size(); + for (size_t p = 0; p < maxOperators; p++) + { + const size_t wordEnd = i + (*(*possibleOperators)[p]).length(); + if (wordEnd > line.length()) + continue; + if (line.compare(i, (*(*possibleOperators)[p]).length(), *(*possibleOperators)[p]) == 0) + return (*possibleOperators)[p]; + } + return nullptr; +} + +// get the current word on a line +// index must point to the beginning of the word +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; + 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 (!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'); +} + +// 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/astyle/src/astyle.h b/astyle/src/astyle.h new file mode 100755 index 0000000000000000000000000000000000000000..54ef227cc894f1c628ad80d13ceaa400cf46ece9 --- /dev/null +++ b/astyle/src/astyle.h @@ -0,0 +1,1056 @@ +// astyle.h +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// 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 <assert> +#else + #include <cassert> +#endif + +#include <cctype> +#include <iostream> // for cout +#include <memory> +#include <string> +#include <vector> + +#ifdef __GNUC__ + #include <cstring> // 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 __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_BANNER, + STYLE_GNU, + STYLE_LINUX, + STYLE_HORSTMANN, + STYLE_1TBS, + STYLE_GOOGLE, + STYLE_MOZILLA, + STYLE_PICO, + STYLE_LISP +}; + +enum BraceMode +{ + NONE_MODE, + ATTACH_MODE, + BREAK_MODE, + LINUX_MODE, + RUN_IN_MODE // broken braces +}; + +// maximun value for int is 16,384 (total value of 32,767) +enum BraceType +{ + 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, + 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() {} + virtual ~ASSourceIterator() {} + virtual int getStreamLength() const = 0; + virtual bool hasMoreLines() const = 0; + virtual string nextLine(bool emptyLineWasDeleted = false) = 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<const string*>* assignmentOperators); + void buildCastOperators(vector<const string*>* castOperators); + void buildHeaders(vector<const string*>* headers, int fileType, bool beautifier = false); + void buildIndentableMacros(vector<const pair<const string, const string>* >* indentableMacros); + void buildIndentableHeaders(vector<const string*>* indentableHeaders); + void buildNonAssignmentOperators(vector<const string*>* nonAssignmentOperators); + void buildNonParenHeaders(vector<const string*>* nonParenHeaders, int fileType, bool beautifier = false); + void buildOperators(vector<const string*>* operators, int fileType); + void buildPreBlockStatements(vector<const string*>* preBlockStatements, int fileType); + void buildPreCommandHeaders(vector<const string*>* preCommandHeaders, int fileType); + void buildPreDefinitionHeaders(vector<const string*>* 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_STATIC, AS_CONST, AS_SEALED, AS_OVERRIDE, 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_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; // a value from enum FileType + +protected: + ASBase() : baseFileType(C_TYPE) { } + +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<const string*>* possibleHeaders) const; + bool findKeyword(const string& line, int i, const string& keyword) const; + const string* findOperator(const string& line, int i, + const vector<const string*>* possibleOperators) const; + string getCurrentWord(const string& line, size_t index) const; + bool isDigit(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(); + 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<const string*>& 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 + ASBeautifier(const ASBeautifier& other); // inline functions + ASBeautifier& operator=(ASBeautifier&); // not to be implemented + + 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<vector<const string*>*>*& container, + vector<vector<const string*>*>* value); + void clearObjCMethodDefinitionAlignment(); + void deleteBeautifierContainer(vector<ASBeautifier*>*& container); + void deleteTempStacksContainer(vector<vector<const string*>*>*& container); + int adjustIndentCountForBreakElseIfComments() const; + int computeObjCColonAlignment(const string& line, int colonAlignPosition) const; + int convertTabToSpaces(int i, int tabIncrementIn) 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 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<typename T> void deleteContainer(T& container); + template<typename T> void initContainer(T& container, T value); + vector<vector<const string*>*>* copyTempStacks(const ASBeautifier& other) const; + pair<int, int> computePreprocessorIndent(); + +private: // variables + int beautifierFileType; + vector<const string*>* headers; + vector<const string*>* nonParenHeaders; + vector<const string*>* preBlockStatements; + vector<const string*>* preCommandHeaders; + vector<const string*>* assignmentOperators; + vector<const string*>* nonAssignmentOperators; + vector<const string*>* indentableHeaders; + + vector<ASBeautifier*>* waitingBeautifierStack; + vector<ASBeautifier*>* activeBeautifierStack; + vector<int>* waitingBeautifierStackLengthStack; + vector<int>* activeBeautifierStackLengthStack; + vector<const string*>* headerStack; + vector<vector<const string*>* >* tempStacks; + vector<int>* squareBracketDepthStack; + vector<bool>* blockStatementStack; + vector<bool>* parenStatementStack; + vector<bool>* braceBlockStateStack; + vector<int>* continuationIndentStack; + vector<int>* continuationIndentStackSizeStack; + vector<int>* parenIndentStack; + vector<pair<int, int> >* 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 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(); + virtual ~ASEnhancer(); + void init(int, int, int, bool, bool, bool, bool, bool, bool, bool, + vector<const pair<const string, const string>* >*); + 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<SwitchVariables> 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<const pair<const string, const string>* >* 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(); + virtual ~ASFormatter(); + virtual void init(ASSourceIterator* si); + virtual bool hasMoreLines() const; + virtual 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 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 compatability 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 + ASFormatter(const ASFormatter& copy); // not to be implemented + ASFormatter& operator=(ASFormatter&); // not to be implemented + template<typename T> void deleteContainer(T& container); + template<typename T> 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 isOkToSplitFormattedLine(); + bool isPointerOrReference() const; + bool isPointerOrReferenceCentered() const; + bool isPointerOrReferenceVariable(const string& word) 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<BraceType>*& container); + 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<BraceType>*& container, vector<BraceType>* 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, + shared_ptr<ASPeekStream> streamArg = nullptr) const; + +private: // variables + int formatterFileType; + vector<const string*>* headers; + vector<const string*>* nonParenHeaders; + vector<const string*>* preDefinitionHeaders; + vector<const string*>* preCommandHeaders; + vector<const string*>* operators; + vector<const string*>* assignmentOperators; + vector<const string*>* castOperators; + vector<const pair<const string, const string>* >* indentableMacros; // for ASEnhancer + + ASSourceIterator* sourceIterator; + ASEnhancer* enhancer; + + vector<const string*>* preBraceHeaderStack; + vector<BraceType>* braceTypeStack; + vector<int>* parenStack; + vector<bool>* structStack; + vector<bool>* 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; + + // 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 isInPreprocessorBeautify; + bool isInTemplate; + bool doesLineStartComment; + bool lineEndsInCommentOnly; + bool lineIsCommentOnly; + bool lineIsLineCommentOnly; + bool lineIsEmpty; + 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 isInObjCSelector; + bool breakCurrentOneLineBlock; + bool shouldRemoveNextClosingBrace; + bool isInBraceRunIn; + 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 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<const string*>* headers_) + { return ASBase::findHeader(currentLine, charNum, headers_); } + + // call ASBase::findOperator for the current character + const string* findOperator(const vector<const string*>* 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/astyle/src/astyle_main.cpp b/astyle/src/astyle_main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..e9d5c1a00d7902b4950ed51e6a63aa0cbfa475e4 --- /dev/null +++ b/astyle/src/astyle_main.cpp @@ -0,0 +1,3990 @@ +// astyle_main.cpp +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// 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 <algorithm> +#include <cerrno> +#include <clocale> // needed by some compilers +#include <cstdlib> +#include <fstream> +#include <sstream> + +// includes for recursive getFileNames() function +#ifdef _WIN32 + #undef UNICODE // use ASCII windows functions + #include <windows.h> +#else + #include <dirent.h> + #include <unistd.h> + #include <sys/stat.h> + #ifdef __VMS + #include <unixlib.h> + #include <rms.h> + #include <ssdef.h> + #include <stsdef.h> + #include <lib$routines.h> + #include <starlet.h> + #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.0"; + +//----------------------------------------------------------------------------- +// ASStreamIterator class +// typename will be istringstream for GUI and istream otherwise +//----------------------------------------------------------------------------- + +template<typename T> +ASStreamIterator<T>::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<typename T> +ASStreamIterator<T>::~ASStreamIterator() +{ +} + +/** +* 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<typename T> +int ASStreamIterator<T>::getStreamLength() const +{ + return static_cast<int>(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<typename T> +string ASStreamIterator<T>::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(); + } + + // 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<typename T> +string ASStreamIterator<T>::peekNextLine() +{ + assert(hasMoreLines()); + string nextLine_; + char ch; + + if (peekStart == 0) + 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<typename T> +void ASStreamIterator<T>::peekReset() +{ + assert(peekStart != 0); + inStream->clear(); + inStream->seekg(peekStart); + peekStart = 0; +} + +// save the last input line after input has reached EOF +template<typename T> +void ASStreamIterator<T>::saveLastInputLine() +{ + assert(inStream->eof()); + prevBuffer = buffer; +} + +// return position of the get pointer +template<typename T> +streamoff ASStreamIterator<T>::tellg() +{ + return inStream->tellg(); +} + +// check for a change in line ends +template<typename T> +bool ASStreamIterator<T>::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; + optionsFileRequired = false; + useAscii = false; + // other variables + bypassBrowserOpen = false; + hasWildcard = false; + filesAreIdentical = true; + lineEndsMixed = false; + origSuffix = ".orig"; + mainDirectoryLength = 0; + filesFormatted = 0; + filesUnchanged = 0; + linesOut = 0; +} + +ASConsole::~ASConsole() +{} + +// 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; + } + else if (lineEnd == LINEEND_LF) + { + outStr += inStr[pos + 1]; // Delete the CR + pos++; + continue; + } + else + { + outStr += inStr[pos]; // Do not change + outStr += inStr[pos + 1]; + pos++; + continue; + } + } + else + { + // CR + if (lineEnd == LINEEND_CRLF) + { + outStr += inStr[pos]; // Insert the CR + outStr += '\n'; // Insert the LF + continue; + } + else if (lineEnd == LINEEND_LF) + { + outStr += '\n'; // Insert the LF + continue; + } + else + { + 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; + } + else if (lineEnd == LINEEND_CR) + { + outStr += '\r'; // Insert the CR + continue; + } + else + { + 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 >= 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) << _("\nArtistic Style has terminated") << 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 like TextWrangler (Mac). + * 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<stringstream> 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<stringstream> 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); +} + +// build a vector of argv options +// the program path argv[0] is excluded +vector<string> ASConsole::getArgvOptions(int argc, char** argv) const +{ + vector<string> argvOptions; + for (int i = 1; i < argc; i++) + { + argvOptions.emplace_back(string(argv[i])); + } + return argvOptions; +} + +// for unit testing +vector<bool> ASConsole::getExcludeHitsVector() const +{ return excludeHitsVector; } + +// for unit testing +vector<string> ASConsole::getExcludeVector() const +{ return excludeVector; } + +// for unit testing +vector<string> ASConsole::getFileName() const +{ return fileName; } + +// for unit testing +vector<string> ASConsole::getFileNameVector() const +{ return fileNameVector; } + +// for unit testing +vector<string> 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::getOptionsFileName() const +{ return optionsFileName; } + +// for unit testing +vector<string> 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::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; +} + +string ASConsole::getParam(const string& arg, const char* op) +{ + return arg.substr(strlen(op)); +} + +// 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(); +} + +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 input file", fileName_.c_str()); + char* data = new (nothrow) char[blockSize]; + if (data == nullptr) + error("Cannot allocate memory for input file", fileName_.c_str()); + fin.read(data, blockSize); + if (fin.bad()) + error("Cannot read input file", fileName_.c_str()); + size_t dataSize = static_cast<size_t>(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 = utf8_16.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 = utf8_16.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 input file", fileName_.c_str()); + dataSize = static_cast<size_t>(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::setOptionsFileName(const string& name) +{ optionsFileName = name; } + +void ASConsole::setOrigSuffix(const string& suffix) +{ origSuffix = suffix; } + +void ASConsole::setPreserveDate(bool state) +{ preserveDate = state; } + +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 wildcard The wildcard to be processed (e.g. *.cpp). + */ +void ASConsole::getFileNames(const string& directory, const string& wildcard) +{ + vector<string> 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; + } + + // save the file name + 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 + if (wildcmp(wildcard.c_str(), findFileData.cFileName)) + { + if (isExcluded) + printMsg(_("Exclude %s\n"), filePathName.substr(mainDirectoryLength)); + else + fileName.emplace_back(filePathName); + } + } + 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 (unsigned i = 0; i < subDirectory.size(); i++) + getFileNames(subDirectory[i], wildcard); + + return; +} + +/** + * 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 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* 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), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + 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 +{ + char* 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 wildcard The wildcard to be processed (e.g. *.cpp). + */ +void ASConsole::getFileNames(const string& directory, const string& wildcard) +{ + struct dirent* entry; // entry from readdir() + struct stat statbuf; // entry from stat() + vector<string> subDirectory; // sub directories of this directory + + // errno is defined in <errno.h> 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 + if (wildcmp(wildcard.c_str(), entry->d_name) != 0) + { + if (isExcluded) + printMsg(_("Exclude %s\n"), entryFilepath.substr(mainDirectoryLength)); + else + fileName.emplace_back(entryFilepath); + } + } + } + + 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[firstEntry], &fileName[fileName.size()]); + + // 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], wildcard); + } +} + +/** + * 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 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 +{ + struct stat statbuf; + string htmlDefaultPath = "/usr/share/doc/astyle/html/"; + string htmlDefaultFile = "astyle.html"; + + // build file path + string htmlFilePath; + if (filePathIn == nullptr) + htmlFilePath = 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* envPaths = getenv("PATH"); + if (envPaths == nullptr) + envPaths = "?"; + 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 + +// get individual file names from the command-line file path +void ASConsole::getFilePaths(const string& filePath) +{ + fileName.clear(); + targetDirectory = string(); + targetFilename = string(); + + // 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; + + // clear exclude hits vector + size_t excludeHitsVectorSize = excludeHitsVector.size(); + for (size_t ix = 0; ix < excludeHitsVectorSize; ix++) + excludeHitsVector[ix] = false; + + // 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(); + } + + // display directory name for wildcard processing + if (hasWildcard) + { + printSeparatingLine(); + printMsg(_("Directory %s\n"), targetDirectory + g_fileSeparator + targetFilename); + } + + // create a vector of paths and file names to process + if (hasWildcard || isRecursive) + getFileNames(targetDirectory, targetFilename); + 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(); +} + +bool ASConsole::fileNameVectorIsEmpty() const +{ + return fileNameVector.empty(); +} + +bool ASConsole::isOption(const string& arg, const char* op) +{ + return arg.compare(op) == 0; +} + +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 << 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 << "Options File:\n"; + cout << "-------------\n"; + cout << " Artistic Style looks for a default options file in the\n"; + cout << " following order:\n"; + cout << " 1. The contents of the ARTISTIC_STYLE_OPTIONS environment\n"; + cout << " variable if it exists.\n"; + cout << " 2. The file called .astylerc in the directory pointed to by the\n"; + cout << " HOME environment variable ( i.e. $HOME/.astylerc ).\n"; + cout << " 3. The file called astylerc in the directory pointed to by the\n"; + cout << " USERPROFILE environment variable (i.e. %USERPROFILE%\\astylerc).\n"; + cout << " If a default options file is found, the options in this file will\n"; + cout << " be parsed BEFORE the command-line options.\n"; + cout << " Long options within the default option file may be written without\n"; + cout << " the preliminary '--'.\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.\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=banner OR -A6\n"; + cout << " Banner 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=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 -xd\n"; + cout << " Delete empty lines within a function or method.\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 << " --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 << " Specify an options file #### to read and use.\n"; + cout << endl; + cout << " --options=none\n"; + cout << " Disable the default options file.\n"; + cout << " Only the command-line parameters will be used.\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 << 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 (size_t i = 0; i < fileNameVector.size(); i++) + { + getFilePaths(fileNameVector[i]); + + // loop thru fileName vector formatting the files + for (size_t j = 0; j < fileName.size(); j++) + formatFile(fileName[j]); + } + + // files are processed, display stats + if (isVerbose) + printVerboseStats(startTime); +} + +// process options from the command line and options file +// build the vectors fileNameVector, excludeVector, optionsVector, and fileOptionsVector +void ASConsole::processOptions(const vector<string>& argvOptions) +{ + string arg; + bool ok = true; + bool shouldParseOptionsFile = true; + + // get command line options + for (size_t i = 0; i < argvOptions.size(); i++) + { + arg = argvOptions[i]; + + 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") ) + { + shouldParseOptionsFile = false; + } + else if ( isParamOption(arg, "--options=") ) + { + optionsFileName = getParam(arg, "--options="); + optionsFileRequired = true; + if (optionsFileName.empty()) + setOptionsFileName(" "); + } + 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 (arg[0] == '-') + { + optionsVector.emplace_back(arg); + } + else // file-name + { + standardizePath(arg); + fileNameVector.emplace_back(arg); + } + } + + // get options file path and name + if (shouldParseOptionsFile) + { + if (optionsFileName.empty()) + { + char* env = getenv("ARTISTIC_STYLE_OPTIONS"); + if (env != nullptr) + setOptionsFileName(env); + } + if (optionsFileName.empty()) + { + char* env = getenv("HOME"); + if (env != nullptr) + setOptionsFileName(string(env) + "/.astylerc"); + } + if (optionsFileName.empty()) + { + char* env = getenv("USERPROFILE"); + if (env != nullptr) + setOptionsFileName(string(env) + "/astylerc"); + } + if (!optionsFileName.empty()) + standardizePath(optionsFileName); + } + + // create the options file vector and parse the options for errors + ASOptions options(formatter, *this); + if (!optionsFileName.empty()) + { + ifstream optionsIn(optionsFileName.c_str()); + if (optionsIn) + { + options.importOptions(optionsIn, fileOptionsVector); + ok = options.parseOptions(fileOptionsVector, + string(_("Invalid option file options:"))); + } + else + { + if (optionsFileRequired) + error(_("Cannot open options file"), optionsFileName.c_str()); + optionsFileName.clear(); + } + optionsIn.close(); + } + if (!ok) + { + (*errorStream) << options.getOptionErrors() << endl; + (*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() << endl; + (*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; // *NOPAD* + 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 options file + if (!optionsFileName.empty()) + printf(_("Using default options file %s\n"), optionsFileName.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; + int minsec = int (secs + .5); + printf(_("%d min %d sec "), min, minsec); + } + + string lines = getNumberFormat(linesOut); + printf(_("%s lines\n"), lines.c_str()); +} + +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); + 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, *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 = utf8_16.utf16LengthFromUtf8(out.str().c_str(), out.str().length()); + char* utf16Out = new char[utf16Size]; + size_t utf16Len = utf8_16.utf8ToUtf16(const_cast<char*>(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 +//----------------------------------------------------------------------------- + +utf16_t* ASLibrary::formatUtf16(const utf16_t* pSourceIn, // the source to be formatted + const utf16_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 + utf16_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. + */ +utf16_t* ASLibrary::convertUtf8ToUtf16(const char* utf8In, fpAlloc fpMemoryAlloc) const +{ + if (utf8In == nullptr) + return nullptr; + char* data = const_cast<char*>(utf8In); + size_t dataSize = strlen(utf8In); + bool isBigEndian = utf8_16.getBigEndian(); + // return size is in number of CHARs, not utf16_t + size_t utf16Size = (utf8_16.utf16LengthFromUtf8(data, dataSize) + sizeof(utf16_t)); + char* utf16Out = fpMemoryAlloc((long)utf16Size); + if (utf16Out == nullptr) + return nullptr; +#ifdef NDEBUG + utf8_16.utf8ToUtf16(data, dataSize + 1, isBigEndian, utf16Out); +#else + size_t utf16Len = utf8_16.utf8ToUtf16(data, dataSize + 1, isBigEndian, utf16Out); + assert(utf16Len == utf16Size); +#endif + assert(utf16Size == (utf8_16.utf16len(reinterpret_cast<utf16_t*>(utf16Out)) + 1) * sizeof(utf16_t)); + return reinterpret_cast<utf16_t*>(utf16Out); +} + +/** + * Convert utf16 strings to utf-8. + * The calling function must check for errors and delete the + * allocated memory. + */ +char* ASLibrary::convertUtf16ToUtf8(const utf16_t* utf16In) const +{ + if (utf16In == nullptr) + return nullptr; + char* data = reinterpret_cast<char*>(const_cast<utf16_t*>(utf16In)); + // size must be in chars + size_t dataSize = utf8_16.utf16len(utf16In) * sizeof(utf16_t); + bool isBigEndian = utf8_16.getBigEndian(); + size_t utf8Size = utf8_16.utf8LengthFromUtf16(data, dataSize, isBigEndian) + 1; + char* utf8Out = new (nothrow) char[utf8Size]; + if (utf8Out == nullptr) + return nullptr; +#ifdef NDEBUG + utf8_16.utf16ToUtf8(data, dataSize + 1, isBigEndian, true, utf8Out); +#else + size_t utf8Len = utf8_16.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 (options file) or an optionsVector (command line) + * + * @return true if no errors, false if errors + */ +bool ASOptions::parseOptions(vector<string>& optionsVector, const string& errorInfo) +{ + vector<string>::iterator option; + string arg, 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, "style=allman") || isOption(arg, "style=bsd") || isOption(arg, "style=break") ) + { + formatter.setFormattingStyle(STYLE_ALLMAN); + } + else if ( isOption(arg, "style=java") || isOption(arg, "style=attach") ) + { + formatter.setFormattingStyle(STYLE_JAVA); + } + else if ( isOption(arg, "style=k&r") || isOption(arg, "style=kr") || isOption(arg, "style=k/r") ) + { + formatter.setFormattingStyle(STYLE_KR); + } + else if ( isOption(arg, "style=stroustrup") ) + { + formatter.setFormattingStyle(STYLE_STROUSTRUP); + } + else if ( isOption(arg, "style=whitesmith") ) + { + formatter.setFormattingStyle(STYLE_WHITESMITH); + } + else if ( isOption(arg, "style=vtk") ) + { + formatter.setFormattingStyle(STYLE_VTK); + } + else if ( isOption(arg, "style=banner") ) + { + formatter.setFormattingStyle(STYLE_BANNER); + } + else if ( isOption(arg, "style=gnu") ) + { + formatter.setFormattingStyle(STYLE_GNU); + } + else if ( isOption(arg, "style=linux") || isOption(arg, "style=knf") ) + { + formatter.setFormattingStyle(STYLE_LINUX); + } + else if ( isOption(arg, "style=horstmann") || isOption(arg, "style=run-in") ) + { + formatter.setFormattingStyle(STYLE_HORSTMANN); + } + else if ( isOption(arg, "style=1tbs") || isOption(arg, "style=otbs") ) + { + formatter.setFormattingStyle(STYLE_1TBS); + } + else if ( isOption(arg, "style=google") ) + { + formatter.setFormattingStyle(STYLE_GOOGLE); + } + else if (isOption(arg, "style=mozilla")) + { + formatter.setFormattingStyle(STYLE_MOZILLA); + } + else if ( isOption(arg, "style=pico") ) + { + formatter.setFormattingStyle(STYLE_PICO); + } + else if ( isOption(arg, "style=lisp") || isOption(arg, "style=python") ) + { + formatter.setFormattingStyle(STYLE_LISP); + } + else if ( isParamOption(arg, "A") ) + { + int style = 0; + string styleParam = getParam(arg, "A"); + if (styleParam.length() > 0) + style = atoi(styleParam.c_str()); + if (style == 1) + formatter.setFormattingStyle(STYLE_ALLMAN); + else if (style == 2) + formatter.setFormattingStyle(STYLE_JAVA); + else if (style == 3) + formatter.setFormattingStyle(STYLE_KR); + else if (style == 4) + formatter.setFormattingStyle(STYLE_STROUSTRUP); + else if (style == 5) + formatter.setFormattingStyle(STYLE_WHITESMITH); + else if (style == 6) + formatter.setFormattingStyle(STYLE_BANNER); + else if (style == 7) + formatter.setFormattingStyle(STYLE_GNU); + else if (style == 8) + formatter.setFormattingStyle(STYLE_LINUX); + else if (style == 9) + formatter.setFormattingStyle(STYLE_HORSTMANN); + else if (style == 10) + formatter.setFormattingStyle(STYLE_1TBS); + else if (style == 11) + formatter.setFormattingStyle(STYLE_PICO); + else if (style == 12) + formatter.setFormattingStyle(STYLE_LISP); + else if (style == 14) + formatter.setFormattingStyle(STYLE_GOOGLE); + else if (style == 15) + formatter.setFormattingStyle(STYLE_VTK); + else if (style == 16) + formatter.setFormattingStyle(STYLE_MOZILLA); + else + isOptionError(arg, errorInfo); + } + // 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, "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); + } + // Objective-C options + else 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); + } + // 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); + } +// NOTE: Removed in release 2.04. +// else if ( isOption(arg, "b", "brackets=break") ) +// { +// formatter.setBracketFormatMode(BREAK_MODE); +// } +// else if ( isOption(arg, "a", "brackets=attach") ) +// { +// formatter.setBracketFormatMode(ATTACH_MODE); +// } +// else if ( isOption(arg, "l", "brackets=linux") ) +// { +// formatter.setBracketFormatMode(LINUX_MODE); +// } +// else if ( isOption(arg, "u", "brackets=stroustrup") ) +// { +// formatter.setBracketFormatMode(STROUSTRUP_MODE); +// } +// else if ( isOption(arg, "g", "brackets=run-in") ) +// { +// formatter.setBracketFormatMode(RUN_IN_MODE); +// } + // end depreciated options //////////////////////////////////////////////////////////////////// +#ifdef ASTYLE_LIB + // End of options used by GUI ///////////////////////////////////////////////////////////////// + else + isOptionError(arg, errorInfo); +#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 if ( isParamOption(arg, "stdin=") ) + { + string path = getParam(arg, "stdin="); + console.standardizePath(path); + console.setStdPathIn(path); + } + else if ( isParamOption(arg, "stdout=") ) + { + string path = getParam(arg, "stdout="); + console.standardizePath(path); + console.setStdPathOut(path); + } + else + isOptionError(arg, errorInfo); +#endif +} // End of parseOption function + +// Parse options from the options file. +void ASOptions::importOptions(istream& in, vector<string>& 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.compare(op) == 0; +} + +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 << 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 +{ + short int word = 0x0001; + char* byte = (char*) &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 utf16_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 <neilh@scintilla.org> +// 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; + const short* uptr = reinterpret_cast<const short*>(utf16In); + for (size_t i = 0; i < wcharLen && uptr[i];) + { + 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_TRAIL_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<ubyte*>(utf8In); + utf16* pCur = reinterpret_cast<utf16*>(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<utf16>(isBigEndian ? swap16bit(lead) : lead); + int trail = (codePoint & 0x3ff) + SURROGATE_TRAIL_FIRST; + *pCur++ = static_cast<utf16>(isBigEndian ? swap16bit(trail) : trail); + } + else + *pCur++ = static_cast<utf16>(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 <neilh@scintilla.org> +// 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<unsigned char>(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<ubyte*>(utf16In); + ubyte* pCur = reinterpret_cast<ubyte*>(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<utf16>(*pRead++ << 8); + nCur16 |= static_cast<utf16>(*pRead); + } + else + { + nCur16 = *pRead++; + nCur16 |= static_cast<utf16>(*pRead << 8); + } + if (nCur16 >= SURROGATE_LEAD_FIRST && nCur16 <= SURROGATE_LEAD_LAST) + { + ++pRead; + int trail; + if (isBigEndian) + { + trail = static_cast<utf16>(*pRead++ << 8); + trail |= static_cast<utf16>(*pRead); + } + else + { + trail = *pRead++; + trail |= static_cast<utf16>(*pRead << 8); + } + nCur16 = (((nCur16 & 0x3ff) << 10) | (trail & 0x3ff)) + SURROGATE_FIRST_VALUE; + } + ++pRead; + + if (nCur16 < 0x80) + { + nCur = static_cast<ubyte>(nCur16 & 0xFF); + state = eStart; + } + else if (nCur16 < 0x800) + { + nCur = static_cast<ubyte>(0xC0 | (nCur16 >> 6)); + state = eFinal; + } + else if (nCur16 < SURROGATE_FIRST_VALUE) + { + nCur = static_cast<ubyte>(0xE0 | (nCur16 >> 12)); + state = ePenultimate; + } + else + { + nCur = static_cast<ubyte>(0xF0 | (nCur16 >> 18)); + state = eSecondOf4Bytes; + } + break; + case eSecondOf4Bytes: + nCur = static_cast<ubyte>(0x80 | ((nCur16 >> 12) & 0x3F)); + state = ePenultimate; + break; + case ePenultimate: + nCur = static_cast<ubyte>(0x80 | ((nCur16 >> 6) & 0x3F)); + state = eFinal; + break; + case eFinal: + nCur = static_cast<ubyte>(0x80 | (nCur16 & 0x3F)); + state = eStart; + break; + // no default case is needed + } + *pCur++ = static_cast<ubyte>(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 utf16_t* STDCALL AStyleMainUtf16(const utf16_t* pSourceIn, // the source to be formatted + const utf16_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 utf16_t on Linux + int sizeCheck = 2; + if (sizeof(utf16_t) != sizeCheck) + { + fpErrorHandler(104, "Unsigned short is not the correct size."); + return nullptr; + } +#endif + + ASLibrary library; + utf16_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<string> optionsVector; + istringstream opt(pOptions); + + options.importOptions(opt, optionsVector); + + bool ok = options.parseOptions(optionsVector, "Invalid Artistic Style options:"); + if (!ok) + fpErrorHandler(130, options.getOptionErrors().c_str()); + + istringstream in(pSourceIn); + ASStreamIterator<istringstream> 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; + auto console = make_shared<ASConsole>(formatter); + + // process command line and options file + // build the vectors fileNameVector, optionsVector, and fileOptionsVector + vector<string> 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/astyle/src/astyle_main.h b/astyle/src/astyle_main.h new file mode 100755 index 0000000000000000000000000000000000000000..057bd91de5b1e8be7556c6e0ebbf1798c086349b --- /dev/null +++ b/astyle/src/astyle_main.h @@ -0,0 +1,443 @@ +// astyle_main.h +// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>. +// 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 <sstream> +#include <ctime> + +#if defined(__BORLANDC__) && __BORLANDC__ < 0x0650 + // Embarcadero needs this for the following utime.h + // otherwise "struct utimbuf" gets an error on time_t + // 0x0650 for C++Builder XE3 + using std::time_t; +#endif + +#if defined(_MSC_VER) + #include <sys/utime.h> + #include <sys/stat.h> +#else + #include <utime.h> + #include <sys/stat.h> +#endif // end compiler checks + +#ifdef ASTYLE_JNI + #include <jni.h> + #ifndef ASTYLE_LIB // ASTYLE_LIB must be defined for ASTYLE_JNI + #define ASTYLE_LIB + #endif +#endif // ASTYLE_JNI + +#ifndef ASTYLE_LIB + // for console build only + #include "ASLocalizer.h" + #define _(a) localizer.settext(a) +#endif // ASTYLE_LIB + +//----------------------------------------------------------------------------- +// declarations +//----------------------------------------------------------------------------- + +// for G++ implementation of string.compare: +#if defined(__GNUC__) && __GNUC__ < 3 + #error - Use GNU C compiler release 3 or higher +#endif + +// for getenv and localtime +#if defined(_MSC_VER) + #pragma warning(disable: 4996) // secure version deprecation warnings +#endif + +// for namespace problem in version 5.0 +#if defined(_MSC_VER) && _MSC_VER < 1200 // check for V6.0 + #error - Use Microsoft compiler version 6 or higher +#endif + +#ifdef __clang__ + #pragma clang diagnostic ignored "-Wdeprecated-declarations" // getenv, localtime + #pragma clang diagnostic ignored "-Wmissing-braces" +#endif + +// for mingw BOM, UTF-16, and Unicode functions +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) + #if (__MINGW32_MAJOR_VERSION > 3) || \ + ((__MINGW32_MAJOR_VERSION == 3) && (__MINGW32_MINOR_VERSION < 16)) + #error - Use MinGW compiler version 4 or higher + #endif +#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 utf-16 bit text for the platform + typedef unsigned short utf16_t; + // 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 istringstream for GUI and istream otherwise +// ASSourceIterator is an abstract class defined in astyle.h +//---------------------------------------------------------------------------- + +template<typename T> +class ASStreamIterator : public ASSourceIterator +{ +public: + bool checkForEmptyLine; + + // function declarations + explicit ASStreamIterator(T* in); + virtual ~ASStreamIterator(); + bool getLineEndChange(int lineEndFormat) const; + int getStreamLength() const; + string nextLine(bool emptyLineWasDeleted); + string peekNextLine(); + void peekReset(); + void saveLastInputLine(); + streamoff tellg(); + +private: + ASStreamIterator(const ASStreamIterator& copy); // copy constructor not to be implemented + ASStreamIterator& operator=(ASStreamIterator&); // assignment operator not to be implemented + 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; } + bool hasMoreLines() const { return !inStream->eof(); } +}; + +//---------------------------------------------------------------------------- +// ASEncoding class for utf8/16 conversions +// used by both console and library builds +//---------------------------------------------------------------------------- + +class ASEncoding +{ +private: + typedef unsigned short utf16; // 16 bits + typedef unsigned char utf8; // 8 bits + typedef unsigned char ubyte; // 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(istream& in, vector<string>& optionsVector); + bool parseOptions(vector<string>& 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 + ASOptions(const ASOptions&); // copy constructor not to be implemented + ASOptions& operator=(ASOptions&); // assignment operator not to be implemented + 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); +}; + +#ifndef ASTYLE_LIB + +//---------------------------------------------------------------------------- +// ASConsole class for console build +//---------------------------------------------------------------------------- + +class ASConsole +{ +private: // variables + ASFormatter& formatter; // reference to the ASFormatter object + ASLocalizer localizer; // ASLocalizer object + 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 optionsFileRequired; // options= option + 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 + + ASEncoding utf8_16; // utf8/16 conversion methods + + string outputEOL; // current line end + string prevEOL; // previous line end + string optionsFileName; // file path and name of the options file to use + string origSuffix; // suffix= option + 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<string> excludeVector; // exclude from wildcard hits + vector<bool> excludeHitsVector; // exclude flags for error reporting + vector<string> fileNameVector; // file paths and names from the command line + vector<string> optionsVector; // options from the command line + vector<string> fileOptionsVector; // options from the options file + vector<string> fileName; // files to be processed including path + +public: // functions + explicit ASConsole(ASFormatter& formatterArg); + ~ASConsole(); + 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<string> getArgvOptions(int argc, char** argv) 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 getOptionsFileName() const; + string getOrigSuffix() const; + string getStdPathIn() const; + string getStdPathOut() const; + void processFiles(); + void processOptions(const vector<string>& 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 setOptionsFileName(const string& name); + void setOrigSuffix(const string& suffix); + void setPreserveDate(bool state); + 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<string> getExcludeVector() const; + vector<bool> getExcludeHitsVector() const; + vector<string> getFileNameVector() const; + vector<string> getOptionsVector() const; + vector<string> getFileOptionsVector() const; + vector<string> getFileName() const; + +private: // functions + ASConsole(const ASConsole&); // copy constructor not to be implemented + ASConsole& operator=(ASConsole&); // assignment operator not to be implemented + void correctMixedLineEnds(ostringstream& out); + void formatFile(const string& fileName_); + string getCurrentDirectory(const string& fileName_) const; + void getFileNames(const string& directory, const string& wildcard); + void getFilePaths(const string& filePath); + string getParam(const string& arg, const char* op); + 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() {} + virtual ~ASLibrary() {} + // virtual functions are mocked in testing + utf16_t* formatUtf16(const utf16_t*, const utf16_t*, fpError, fpAlloc) const; + virtual utf16_t* convertUtf8ToUtf16(const char* utf8In, fpAlloc fpMemoryAlloc) const; + virtual char* convertUtf16ToUtf8(const utf16_t* utf16In) const; + +private: + static char* STDCALL tempMemoryAllocation(unsigned long memoryNeeded); + +private: + ASEncoding utf8_16; // utf8/16 conversion methods +}; + +#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 +utf16_t* STDCALL AStyleMainUtf16(const utf16_t* pSourceIn, + const utf16_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/developer-doc/CodeFormatting.txt b/developer-doc/CodeFormatting.txt new file mode 100644 index 0000000000000000000000000000000000000000..4d6348976d51916b1797fe998c9f16a28a1b9f11 --- /dev/null +++ b/developer-doc/CodeFormatting.txt @@ -0,0 +1,59 @@ +// This document is formatted for Doxygen +/** + +\page CodeFormatting How to format code properly + +Since version 2.3.2, we format code using <a href="http://astyle.sourceforge.net/"> astyle </a>. +As a convention, we use `astyle` version 3.00, with the options that are +reported in the file `.astyle.options` located in the root directory of PLUMED. +You might want to automatize the application of `astyle` using those options. +As of now, you can use the following command from root PLUMED directory: +\verbatim +> make astyle +> git commit +\endverbatim +Notice that this command will both apply `astyle` to all the relevant files as well as +add them to the next git commit. After having inspected the changes, you can commit them. +Also notice that running this command from PLUMED root directory will also +compile the `astyle` version that is distributed with PLUMED. We decided to distribute +`astyle` within the PLUMED repository to make sure that everyone is using exactly the same version. +In addition, you can run `make astyle` directly within a module directory +so as to only reformat that specific module. + +Additional care must be used while merging branches. In this case, you should +make sure that both branches are formatted with `astyle` before merging them. +The procedure discussed below should be made once for each not-yet-formatted branch that you are maintaining. + +Let's say that you are working on a branch `feature` that is not yet formatted, and you +would like to merge changes from branch `v2.3` that is already formatted. +You should use the following list of commands +\verbatim +# Bring in all the changes in v2.3 up to astyle formatting (excluded): +> git merge astyle-v2.3~1 +# Notice that this will include the astyle scripts, but not +# the big commit formatting the whole code. + +# Mark the following commit (astyle-v2.3) as merged, even though +# it is completely ignored: +> git merge -s ours astyle-v2.3 +# This is necessary since this commit is too big to be really merged. + +# Indeed, instead of merging it, we apply directly astyle to the +# current branch: +> make astyle + +# Now the two branches are both formatted and can be merged one into the other. +# Merge all the newer commits on v2.3 +> git merge v2.3 +\endverbatim + +Notice that here `astyle-v2.3` is a tag that refers to the commit where we introduced +formatting in v2.3 branch. +In a similar way you can bring in any changes from another branch, just replace +`v2.3` with the proper name (e.g. `master`). +After merging, your branch will be also formatted correctly. +Notice that you cannot work it in the opposite direction (that is, unformat an already +formatted branch). Finally, consider that rebasing might be more complicated. +When all branches will be formatted this will not be an issue anymore. + +*/ diff --git a/developer-doc/Doxyfile b/developer-doc/Doxyfile index 74626d50a9a4ad0dbc425b217228fc43feff90c4..9e917ee1fd683e4c651d222727b43f6cc5a64f89 100644 --- a/developer-doc/Doxyfile +++ b/developer-doc/Doxyfile @@ -769,7 +769,8 @@ INPUT = ./Intro.txt \ ./AddingRegressionTests.txt \ ./HowToContributeToPlumed.txt \ ./intro-git.txt \ - ./plumedcheck.txt + ./plumedcheck.txt \ + ./CodeFormatting.txt # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/macports/Portfile.in b/macports/Portfile.in index e69f64383b915cd2567247e37e957bb3e3a11018..a7d36b833dd7060459e29d094ed1f21a0b21fa34 100644 --- a/macports/Portfile.in +++ b/macports/Portfile.in @@ -11,8 +11,12 @@ PortGroup cxx11 1.1 version @_VERSION_@ revision @_REVISION_@ categories science -license LGPL-3 -maintainers gmail.com:giovanni.bussi + +# Most of the PLUMED code is L-GPL3. However, PLUMED containts +# molfile plugins from VMD that are released with a BSD-like license +# http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/ +license LGPL-3 BSD +maintainers gmail.com:giovanni.bussi openmaintainer description PLUMED is a plugin for molecular dynamics long_description PLUMED is a plugin for molecular dynamics that can be used \ in combination with popular molecular dynamics codes to perform biased simulations. \ @@ -31,15 +35,17 @@ homepage http://www.plumed.org/ # - list their name here: # Disable additional features. -# they are then re-enabled when selecting proper variants +# They are then re-enabled when selecting proper variants # this is important for features that require an additional package to be # sure that even if the user has that package already installed plumed is # not going to use it. +# Also avoid searching for doxygen. configure.args-append \ + --disable-doc \ --disable-libsearch \ - --disable-molfile-plugins \ --disable-mpi + # Hardcode path for libplumedKernel.dylib. # This allows to patch MD codes using the --runtime option but using as # default kernel the installed one. In this way, MacPorts users @@ -54,56 +60,20 @@ if {[mpi_variant_isset]} { configure.args-replace --disable-mpi --enable-mpi } -variant matheval description {Enable libmatheval} { - configure.ldflags-append -lmatheval - depends_lib-append port:libmatheval -} - -variant xdrfile description {Enable xdrfile} { - configure.ldflags-append -lxdrfile - depends_lib-append port:xdrfile -} - -variant zlib description {Enable zlib} { - configure.ldflags-append -lz - depends_lib-append port:zlib -} +# libraries +configure.ldflags-append -lmatheval -lxdrfile -lz -lgsl +depends_lib-append port:libmatheval port:xdrfile port:zlib port:gsl -variant gsl description {Enable gsl} { - configure.ldflags-append -lgsl - depends_lib-append port:gsl +# This variant enables optional modules in PLUMED. +variant allmodules description {Enable all optional modules} { + configure.args-append --enable-modules=all } -variant molfile description {Enable molfile - includes some BSD code} { - license ${license} BSD - configure.args-replace --disable-molfile-plugins --enable-molfile-plugins -} - -variant doc description {Also compile documentation} { - depends_build-append port:doxygen - depends_build-append port:graphviz - build.target all_plus_docs -} - -# this is a tcl variable contains a concatenated list of modules -# to be activated - -set plumed_modules reset - -# this will automatically create variants for each optional module -@_MODULES_@ plumed_modules - pre-configure { # commands should be included in a pre-configure block to access tcl variables - configure.args-append --enable-modules=${plumed_modules} configure.ldflags-append ${linalglib} } -# Default variants include no optional modules. -# Additionally, the link libraries that are very useful (e.g. matheval of xdrfile) -# and quick to compile -default_variants +matheval +xdrfile +zlib +molfile - # This is required since PLUMED installation does not do it explicitly. # It might be removed when this will be incorporated upstream post-destroot { diff --git a/regtest/adjmat/rt-dfg-wcsurf/plumed.dat b/regtest/adjmat/rt-dfg-wcsurf/plumed.dat index 4c61916607c34404a7591d38ecff1cef1e4c69b6..f437edd08acb5ceae0db8e0ced6bb2aacba59e94 100644 --- a/regtest/adjmat/rt-dfg-wcsurf/plumed.dat +++ b/regtest/adjmat/rt-dfg-wcsurf/plumed.dat @@ -5,7 +5,7 @@ cf: MFILTER_MORE DATA=c1 SWITCH={RATIONAL D_0=2.0 R_0=0.1} LOWMEM # Build a contact matrix mat: CONTACT_MATRIX ATOMS=cf SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} # Find largest cluster -dfs: DFSCLUSTERING MATRIX=mat +dfs: DFSCLUSTERING MATRIX=mat LOWMEM clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 nat: CLUSTER_NATOMS CLUSTERS=dfs CLUSTER=1 diff --git a/regtest/adjmat/rt-topolog-deriv/plumed.dat b/regtest/adjmat/rt-topolog-deriv/plumed.dat index f3e1bc1bf64777f1c2e204ac7f8314652398c65e..bbb0e42bf1d2e3b9eebdac7e54652d38808a3ba3 100644 --- a/regtest/adjmat/rt-topolog-deriv/plumed.dat +++ b/regtest/adjmat/rt-topolog-deriv/plumed.dat @@ -8,7 +8,7 @@ TOPOLOGY_MATRIX ... LABEL=mat ... TOPOLOGY_MATRIX -dfs: DFSCLUSTERING MATRIX=mat +dfs: DFSCLUSTERING LOWMEM MATRIX=mat mm: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 SUM diff --git a/regtest/basic/rt-moving-restraint-pbc/COLVAR.reference b/regtest/basic/rt-moving-restraint-pbc/COLVAR.reference new file mode 100644 index 0000000000000000000000000000000000000000..d73576ec3cc5474b5f33c03b39ddf29eaaea9c21 --- /dev/null +++ b/regtest/basic/rt-moving-restraint-pbc/COLVAR.reference @@ -0,0 +1,13 @@ +#! FIELDS time t d @2.bias @2.force2 @2.t_cntr @2.t_work @2.t_kappa @2.d_cntr @2.d_work @2.d_kappa @2.work +#! SET min_t -pi +#! SET max_t pi + 0.000000 -1.571 1.000 3.777 7.553 2.827 0.000 1.000 3.000 0.000 1.000 0.000 + 1.000000 -1.571 1.000 2.536 5.073 2.897 -0.129 1.000 2.333 -1.111 1.000 -1.240 + 2.000000 -1.571 1.000 1.745 3.491 2.967 -0.253 1.000 1.667 -1.778 1.000 -2.031 + 3.000000 -1.571 1.000 1.404 2.807 3.037 -0.373 1.000 1.000 -2.000 1.000 -2.373 + 4.000000 -1.571 1.000 1.511 3.023 3.107 -0.487 1.000 0.333 -1.778 1.000 -2.265 + 5.000000 -1.571 1.000 2.068 4.137 3.176 -0.597 1.000 -0.333 -1.111 1.000 -1.708 + 6.000000 -1.571 1.000 3.075 6.149 3.246 -0.702 1.000 -1.000 0.000 1.000 -0.702 + 7.000000 -1.571 1.000 4.530 9.061 3.316 -0.802 1.000 -1.667 1.556 1.000 0.754 + 8.000000 -1.571 1.000 6.435 12.871 3.386 -0.897 1.000 -2.333 3.556 1.000 2.659 + 9.000000 -1.571 1.000 8.790 17.579 -2.827 7.128 1.000 -3.000 6.000 1.000 13.128 diff --git a/regtest/basic/rt-moving-restraint-pbc/Makefile b/regtest/basic/rt-moving-restraint-pbc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3703b27cea227aa053fb6d1d73f861e4384dbcee --- /dev/null +++ b/regtest/basic/rt-moving-restraint-pbc/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/basic/rt-moving-restraint-pbc/config b/regtest/basic/rt-moving-restraint-pbc/config new file mode 100644 index 0000000000000000000000000000000000000000..620081c889fb67d157409f9a25809d93bfca355b --- /dev/null +++ b/regtest/basic/rt-moving-restraint-pbc/config @@ -0,0 +1,3 @@ +type=driver +# this is to test a different name +arg="--plumed plumed.dat --ixyz traj.xyz --dump-forces forces --dump-forces-fmt=%8.4f" diff --git a/regtest/basic/rt-moving-restraint-pbc/plumed.dat b/regtest/basic/rt-moving-restraint-pbc/plumed.dat new file mode 100644 index 0000000000000000000000000000000000000000..bb96a9fe7af729e315a4578137921815f8a8146e --- /dev/null +++ b/regtest/basic/rt-moving-restraint-pbc/plumed.dat @@ -0,0 +1,10 @@ +t: TORSION ATOMS=1,2,3,4 +d: DISTANCE ATOMS=1,2 + +MOVINGRESTRAINT ... + ARG=t,d + AT0=0.9pi,3 STEP0=0 KAPPA0=1,1 + AT1=-0.9pi,-3 STEP1=9 KAPPA1=1,1 +... + +PRINT ARG=* FILE=COLVAR FMT=%6.3f diff --git a/regtest/basic/rt-moving-restraint-pbc/traj.xyz b/regtest/basic/rt-moving-restraint-pbc/traj.xyz new file mode 100644 index 0000000000000000000000000000000000000000..88a0b60aa8788e8f5924ede8a1bc2bd597354d3d --- /dev/null +++ b/regtest/basic/rt-moving-restraint-pbc/traj.xyz @@ -0,0 +1,60 @@ +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 +4 +0 0 0 +X 1 0 1 +X 0 0 1 +X 0 0 -1 +X 0 1 -1 diff --git a/src/.gitignore b/src/.gitignore index c2d5fc954681c807351df702343f179cf88d7707..92a799339f9d9dcf25db6d37227eb7df1a872946 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -16,8 +16,6 @@ !/function !/generic !/gridtools -!/header.sh -!/release.sh !/imd !/lapack !/lib @@ -34,6 +32,9 @@ !/vatom !/vesselbase !/wrapper +!/header.sh +!/release.sh +!/astyle.sh # And just ignore these files diff --git a/src/Makefile b/src/Makefile index 3a7e14bf2bd5ad10c3086ec0a5aa5514f3d2a05e..66b3159276b7be0fb0ab4715316582429c5c591f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ -.PHONY: all clean lib install uninstall install-html +.PHONY: all clean lib install uninstall install-html astyle # by default we compile the lib directory, which in turn requests all the needeed modules all: lib @@ -49,4 +49,8 @@ help: @echo " cppcheck: check source (requires cppcheck and gawk installed)" @echo " plumedcheck: check source (requires gawk installed)" +astyle: + $(MAKE) -C ../astyle + ./astyle.sh + diff --git a/src/adjmat/AdjacencyMatrixBase.cpp b/src/adjmat/AdjacencyMatrixBase.cpp index ab067b0cc7bd376685c1febffcf50aa0f2826723..4f9844f9bc36cc7190808f7bba8836df9028fc9f 100644 --- a/src/adjmat/AdjacencyMatrixBase.cpp +++ b/src/adjmat/AdjacencyMatrixBase.cpp @@ -149,8 +149,15 @@ void AdjacencyMatrixBase::retrieveTypeDimensions( unsigned& nrows, unsigned& nco void AdjacencyMatrixBase::finishMatrixSetup( const bool& symmetric, const std::vector<AtomNumber>& all_atoms ){ std::string param; if( symmetric && ablocks[0].size()==ablocks[1].size() ) param="SYMMETRIC"; - if( !symmetric && ablocks[0].size()==ablocks[1].size() ) param="HBONDS"; - + if( !symmetric ){ + bool usehbonds=( ablocks[0].size()==ablocks[1].size() ); + if( usehbonds ){ + for(unsigned i=0;i<ablocks[0].size();++i){ + if( ablocks[0][i]!=ablocks[1][i] ){ usehbonds = false; break; } + } + if( usehbonds ) param="HBONDS"; + } + } vesselbase::VesselOptions da("","",0,param,this); Keywords keys; AdjacencyMatrixVessel::registerKeywords( keys ); diff --git a/src/analysis/Histogram.cpp b/src/analysis/Histogram.cpp index d47743990056c84441ef76a18001962b7bc293f8..5a92cdaa0980b247ac0880bee2d85a868312ff33 100644 --- a/src/analysis/Histogram.cpp +++ b/src/analysis/Histogram.cpp @@ -368,7 +368,7 @@ void Histogram::prepareForAveraging(){ lockContributors(); } else { // This is used when we are not doing kernel density evaluation - mygrid->setGridElement( neighbors[0], 0, mygrid->getGridElement( neighbors[0], 0 ) + cweight ); + mygrid->addToGridElement( neighbors[0], 0, cweight ); } } } diff --git a/src/astyle.sh b/src/astyle.sh new file mode 100755 index 0000000000000000000000000000000000000000..7c0e30383fc5b3497e2825cff0e494a01d1b43c2 --- /dev/null +++ b/src/astyle.sh @@ -0,0 +1,47 @@ +#! /bin/bash + +DIRS=$1 + +# keep only dirname +DIRS=${DIRS##*/} +echo "$DIRS" + +test -z "$DIRS" && DIRS=* + +for dir in $DIRS +do +test -d "$dir" || continue + +test "$dir" = lapack && continue +test "$dir" = blas && continue +test "$dir" = molfile && continue + +cd $dir + + +for file in *.c *.cpp *.h *.inc.in +do + +test -f "$file" || continue + +echo -n "astyle $file" + +../../astyle/astyle --options=../../.astyle.options < $file > $file.tmp && { +if cmp -s $file $file.tmp ; then + echo +else + cp $file.tmp $file + echo " +++ PATCHED" + git add $file +fi +} + +rm $file.tmp + +done + +cd - + +done + + diff --git a/src/bias/MovingRestraint.cpp b/src/bias/MovingRestraint.cpp index 5de07d1078f0bed00a351c7adf1471b855d4382a..02c08fb4e9e4124501278582ac3d3ba0d5ef9182 100644 --- a/src/bias/MovingRestraint.cpp +++ b/src/bias/MovingRestraint.cpp @@ -230,7 +230,11 @@ void MovingRestraint::calculate(){ double c2=(now-step[i-1])/double(step[i]-step[i-1]); double c1=1.0-c2; for(unsigned j=0;j<narg;j++) kk[j]=(c1*kappa[i-1][j]+c2*kappa[i][j]); - for(unsigned j=0;j<narg;j++) aa[j]=(c1*at[i-1][j]+c2*at[i][j]); + for(unsigned j=0;j<narg;j++) { + const double a1=at[i-1][j]; + const double a2=at[i][j]; + aa[j]=(c1*a1+c2*(a1+difference(j,a1,a2))); + } } tot_work=0.0; for(unsigned i=0;i<narg;++i){ diff --git a/src/colvar/Gyration.cpp b/src/colvar/Gyration.cpp index e348b6b22a78b888b0a1e4a16bd36791da3145ba..9471593e9f7bac85928a5304d830af103d14e933 100644 --- a/src/colvar/Gyration.cpp +++ b/src/colvar/Gyration.cpp @@ -76,7 +76,6 @@ periodic image. The following input tells plumed to print the radius of gyration of the chain containing atoms 10 to 20. \verbatim -WHOLEMOLECULES ENTITY0=10-20 GYRATION TYPE=RADIUS ATOMS=10-20 LABEL=rg PRINT ARG=rg STRIDE=1 FILE=colvar \endverbatim diff --git a/src/crystallization/CubicHarmonicBase.cpp b/src/crystallization/CubicHarmonicBase.cpp index 562420760184f11514e14fa3a2a47c6917348f0e..3d793a0dc52ca93ba31b754cdf0f5cfda528c788 100644 --- a/src/crystallization/CubicHarmonicBase.cpp +++ b/src/crystallization/CubicHarmonicBase.cpp @@ -43,6 +43,7 @@ void CubicHarmonicBase::registerKeywords( Keywords& keys ){ keys.add("compulsory","PHI","0.0","The Euler rotational angle phi"); keys.add("compulsory","THETA","0.0","The Euler rotational angle theta"); keys.add("compulsory","PSI","0.0","The Euler rotational angle psi"); + keys.addFlag("UNORMALIZED",false,"calculate the sum of the components of the vector rather than the mean"); // Use actionWithDistributionKeywords keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("MAX"); keys.use("MIN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); @@ -83,6 +84,9 @@ MultiColvarBase(ao) log.printf(" measure crystallinity around central atom. Includes those atoms within %s\n",( switchingFunction.description() ).c_str() ); + parseFlag("UNORMALIZED",unormalized); + if( unormalized ) log.printf(" output sum of vector functions \n"); + else log.printf(" output mean of vector functions \n"); // Set the link cell cutoff rcut2 = switchingFunction.get_dmax()*switchingFunction.get_dmax(); setLinkCellCutoff( switchingFunction.get_dmax() ); @@ -135,7 +139,8 @@ double CubicHarmonicBase::compute( const unsigned& tindex, multicolvar::AtomValu } } // values -> der of... value [0], weight[1], x coord [2], y, z... [more magic] - updateActiveAtoms( myatoms ); myatoms.getUnderlyingMultiValue().quotientRule( 1, 1 ); + updateActiveAtoms( myatoms ); + if( !unormalized ) myatoms.getUnderlyingMultiValue().quotientRule( 1, 1 ); return myatoms.getValue(1); // this is equivalent to getting an "atomic" CV } diff --git a/src/crystallization/CubicHarmonicBase.h b/src/crystallization/CubicHarmonicBase.h index f6d5e5d1f7618aa1fc61415b55b0f8adc09b0ddc..8cc2408e8573d38448bdc8fbf779ad4e01083bea 100644 --- a/src/crystallization/CubicHarmonicBase.h +++ b/src/crystallization/CubicHarmonicBase.h @@ -34,7 +34,7 @@ private: // double nl_cut; double rcut2; double rotationmatrix[3][3]; - + bool unormalized; SwitchingFunction switchingFunction; public: static void registerKeywords( Keywords& keys ); diff --git a/src/function/FuncSumHills.cpp b/src/function/FuncSumHills.cpp index 25ed19207d65c136961d338ee9d9c7b5ec26763f..5231b0fdc9e3411abed14766d234604bb234cb4a 100644 --- a/src/function/FuncSumHills.cpp +++ b/src/function/FuncSumHills.cpp @@ -26,6 +26,7 @@ #include "tools/BiasRepresentation.h" #include "tools/File.h" #include "tools/Tools.h" +#include "tools/Stopwatch.h" #include <iostream> using namespace std; @@ -503,6 +504,10 @@ historep(NULL) if(integratehills) hillsHandler=new FilesHandler(hillsFiles,parallelread,*this, log); if(integratehisto) histoHandler=new FilesHandler(histoFiles,parallelread,*this, log); + Stopwatch sw; + + sw.start("0 Summing hills"); + // read a number of hills and put in the bias representation int nfiles=0; bool ibias=integratehills; bool ihisto=integratehisto; @@ -612,6 +617,10 @@ historep(NULL) nfiles++; } + sw.stop("0 Summing hills"); + + log<<sw; + return; } // just an initialization but you need to do something on the fly?: need to connect with a metad run and its grid representation diff --git a/src/gridtools/GridVessel.cpp b/src/gridtools/GridVessel.cpp index bed1d6ae07b907367808751d1899a7c7864c3fba..f09e3f21a8e836e2afc4df03faf504a347a64523 100644 --- a/src/gridtools/GridVessel.cpp +++ b/src/gridtools/GridVessel.cpp @@ -238,6 +238,11 @@ void GridVessel::setGridElement( const unsigned& ipoint, const unsigned& jelemen setDataElement( nper*ipoint + jelement, value ); } +void GridVessel::addToGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ){ + plumed_dbg_assert( bounds_set && ipoint<npoints && jelement<nper ); + addDataElement( nper*ipoint + jelement, value ); +} + void GridVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_list ) const { plumed_dbg_assert( myvals.getNumberOfValues()==(nper+1) ); for(unsigned i=0;i<nper;++i) buffer[bufstart + nper*current + i] += myvals.get(i+1); diff --git a/src/gridtools/GridVessel.h b/src/gridtools/GridVessel.h index 910545528ec62b08fe28dc9f3ebd65e3b2fa1268..b513322ff9926d8cd565ca98e733be7746d7490d 100644 --- a/src/gridtools/GridVessel.h +++ b/src/gridtools/GridVessel.h @@ -104,10 +104,10 @@ public: void getIndices( const unsigned& index, std::vector<unsigned>& indices ) const ; /// Get the indices of a particular point void getIndices( const std::vector<double>& point, std::vector<unsigned>& indices ) const ; - /// Operations on one of the elements of grid point i void setGridElement( const unsigned&, const unsigned&, const double& ); - +/// Add data to an element of the grid + void addToGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ); /// Operations on one of the elements of grid point specified by vector double getGridElement( const std::vector<unsigned>&, const unsigned& ) const ; void setGridElement( const std::vector<unsigned>&, const unsigned&, const double& ); diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp index 790bd81ed1bef554785cf51cccf4ada34b51b6f8..6fac76cd563c81bc7d7981cc514318013fe0f9c7 100644 --- a/src/gridtools/HistogramOnGrid.cpp +++ b/src/gridtools/HistogramOnGrid.cpp @@ -114,7 +114,7 @@ void HistogramOnGrid::calculate( const unsigned& current, MultiValue& myvals, st KernelFunctions* kernel=getKernelAndNeighbors( point, num_neigh, neighbors ); if( !kernel && getType()=="flat" ){ - plumed_dbg_assert( num_neigh==1 ); + plumed_dbg_assert( num_neigh==1 ); der.resize(0); accumulate( neighbors[0], weight, 1.0, der, buffer ); } else { double totwforce=0.0; diff --git a/src/maketools/make.module b/src/maketools/make.module index 1e7a9e54ab8ad051e95cf193ed3980f09a9aaa1e..6e846e04947f5fbcc668dbfeceda785aca474b93 100644 --- a/src/maketools/make.module +++ b/src/maketools/make.module @@ -86,6 +86,10 @@ plumedcheck: codecheck: ../maketools/codecheck --local +.PHONY: astyle +astyle: + cd ../ ; ./astyle.sh $(CURDIR) + # generic makefile rules diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp index 0ff7ab6d1a0871de08ab578ecd26c5af709ba403..4ea6d867e9569d52941149b3c1cff3711ae5acf2 100644 --- a/src/multicolvar/Distances.cpp +++ b/src/multicolvar/Distances.cpp @@ -174,7 +174,7 @@ MultiColvarBase(ao) use_link=true; rcut=lt->getCutoff(); } else { vesselbase::Between* bt=dynamic_cast<vesselbase::Between*>( getPntrToVessel(0) ); - if( bt ) use_link=true; rcut=bt->getCutoff(); + if( bt ){ use_link=true; rcut=bt->getCutoff(); } } if( use_link ){ for(unsigned i=1;i<getNumberOfVessels();++i){ diff --git a/src/tools/IFile.cpp b/src/tools/IFile.cpp index 6518eeb2463309c1a8b4bd380cafb49526a4fa12..c1334fb5cf2422242459a93dd41e6c7fbac727f4 100644 --- a/src/tools/IFile.cpp +++ b/src/tools/IFile.cpp @@ -28,6 +28,7 @@ #include "Tools.h" #include <cstdarg> #include <cstring> +#include <cmath> #include <iostream> #include <string> @@ -162,7 +163,8 @@ IFile& IFile::scanField(const std::string&name,int &x){ } IFile& IFile::scanField(Value* val){ - double ff; scanField( val->getName(), ff ); + double ff=NAN; // this is to be sure a NAN value is replaced upon failure + scanField( val->getName(), ff ); val->set( ff ); if( FieldExist("min_" + val->getName() ) ){ std::string min, max; diff --git a/src/vesselbase/StoreDataVessel.cpp b/src/vesselbase/StoreDataVessel.cpp index 76122a5f65fa061b1700692b64ffbd6008f4a24d..13f4c9ab6f88ccd77b2d9ac5c3b0382b76b9163a 100644 --- a/src/vesselbase/StoreDataVessel.cpp +++ b/src/vesselbase/StoreDataVessel.cpp @@ -51,6 +51,9 @@ void StoreDataVessel::resize(){ nspace = 1; active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); } else { + if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ){ + error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option"); + } nspace = 1 + getAction()->maxderivatives; active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); } diff --git a/user-doc/Syntax.txt b/user-doc/Syntax.txt index cfa5f902c1f160a8980fd8f66f6000c06a5c9223..47c73c1f2f6066f5bc66a2e5e6a282e57baee995 100644 --- a/user-doc/Syntax.txt +++ b/user-doc/Syntax.txt @@ -15,7 +15,10 @@ which provide PLUMED with more details as to how the action is to be performed. (in which they tell PLUMED to do the calculation in a particular way - for example NOPBC tells PLUMED to not use the periodic bounadry conditions when calculating a particular colvar) or they can be words followed by an equals sign and a comma separated list _with no spaces_ of numbers or characters (so for example ATOMS=1,2,3,4 tells PLUMED to use atom numbers 1,2,3 and 4 in -the calculation of a particular colvar). Space separated lists can be used instead of commma separated list if the entire list +the calculation of a particular colvar). +The reason why spaces are not admitted is that PLUMED should be able to understand when the list of atoms +ended and a new keyword should be expected. +Space separated lists can be used instead of commma separated list if the entire list is enclosed in curly braces (e.g. ATOMS={1 2 3 4}). Please note that you can split commands over multiple lines by using \ref ContinuationLines.