summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src
diff options
context:
space:
mode:
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src')
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/.kateconfig1
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.cpp120
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.h123
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.cpp2919
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.h497
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ListManager.h260
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.cpp347
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.h99
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/add_space_table.h296
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.cpp231
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.cpp58
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.cpp62
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.h25
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.cpp305
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.h25
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.cpp167
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.cpp121
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.h14
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.cpp188
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.h19
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.cpp227
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.cpp202
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.h49
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.cpp134
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.cpp31
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.cpp64
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.h33
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.cpp90
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.cpp182
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.cpp37
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.cpp110
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.cpp283
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.h22
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.cpp667
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.h154
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.cpp34
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.cpp39
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.h23
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.cpp187
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.h48
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.cpp237
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.h46
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.cpp65
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.h25
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.cpp352
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.h22
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.cpp228
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.h122
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.cpp165
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.h63
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/base_types.h53
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.cpp1506
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.h23
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.cpp1700
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.h33
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.cpp199
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/char_table.h81
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp1167
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h1262
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.cpp4018
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.h77
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.cpp2617
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.h196
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.cpp443
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.cpp352
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.h169
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.cpp570
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.h85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat.h26
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_posix.cpp39
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_win32.cpp82
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/config.h.in97
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.cpp20
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.cpp439
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.cpp96
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_flags.h120
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/error_types.h53
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.cpp110
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.h25
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.cpp46
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.h20
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.cpp72
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.h28
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.cpp345
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.h40
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.cpp4776
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.h59
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.cpp670
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.h85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.cpp540
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.h49
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.cpp17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_levels.h138
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.cpp80
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.h49
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.cpp336
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.h166
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.cpp142
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.h103
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.cpp308
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.h85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.cpp6721
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.h206
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.cpp1275
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.h365
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.cpp.in24
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.h.in17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.cpp.in26
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.h4189
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.cpp126
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.h29
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.cpp3422
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.h50
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.cpp67
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.h15
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.cpp349
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.h24
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.cpp54
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.cpp105
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.h96
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/prototypes.h64
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.cpp85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.h52
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.cpp53
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.cpp94
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.h20
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.cpp84
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.cpp125
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.h26
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.cpp700
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.h24
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.cpp3841
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.h45
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/symbols_table.h146
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/token_enum.h399
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.cpp2855
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.h55
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.cpp1766
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.h31
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_ctype.h106
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.cpp759
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.h196
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.cpp496
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.h46
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.cpp2708
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.h99
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_emscripten.cpp1218
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_limits.h19
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.cpp88
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.h284
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_version.h.in18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.cpp580
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.h34
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.cpp372
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.cpp923
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/windows_compat.h97
178 files changed, 69695 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/.kateconfig b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/.kateconfig
new file mode 100644
index 00000000..4d9024f0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/.kateconfig
@@ -0,0 +1 @@
+kate: indent-width 3;
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.cpp
new file mode 100644
index 00000000..dfa0f888
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.cpp
@@ -0,0 +1,120 @@
+/**
+ * @file ChunkStack.cpp
+ * Manages a chunk stack
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "ChunkStack.h"
+
+
+void ChunkStack::Set(const ChunkStack &cs)
+{
+ m_cse.resize(cs.m_cse.size());
+
+ for (size_t idx = 0; idx < m_cse.size(); idx++)
+ {
+ m_cse[idx].m_pc = cs.m_cse[idx].m_pc;
+ m_cse[idx].m_seqnum = cs.m_cse[idx].m_seqnum;
+ }
+
+ m_seqnum = cs.m_seqnum;
+}
+
+
+const ChunkStack::Entry *ChunkStack::Top() const
+{
+ if (!m_cse.empty())
+ {
+ return(&m_cse[m_cse.size() - 1]);
+ }
+ return(nullptr);
+}
+
+
+const ChunkStack::Entry *ChunkStack::Get(size_t idx) const
+{
+ if (idx < m_cse.size())
+ {
+ return(&m_cse[idx]);
+ }
+ return(nullptr);
+}
+
+
+Chunk *ChunkStack::GetChunk(size_t idx) const
+{
+ if (idx < m_cse.size())
+ {
+ return(m_cse[idx].m_pc);
+ }
+ return(nullptr);
+}
+
+
+Chunk *ChunkStack::Pop_Front()
+{
+ Chunk *pc = nullptr;
+
+ if (!m_cse.empty())
+ {
+ pc = m_cse[0].m_pc;
+ m_cse.pop_front();
+ }
+ return(pc);
+}
+
+
+Chunk *ChunkStack::Pop_Back()
+{
+ Chunk *pc = nullptr;
+
+ if (!m_cse.empty())
+ {
+ pc = m_cse[m_cse.size() - 1].m_pc;
+ m_cse.pop_back();
+ }
+ return(pc);
+}
+
+
+void ChunkStack::Push_Back(Chunk *pc, size_t seqnum)
+{
+ m_cse.push_back(Entry(seqnum, pc));
+
+ if (m_seqnum < seqnum)
+ {
+ m_seqnum = seqnum;
+ }
+}
+
+
+void ChunkStack::Zap(size_t idx)
+{
+ if (idx < m_cse.size())
+ {
+ m_cse[idx].m_pc = nullptr;
+ }
+}
+
+
+void ChunkStack::Collapse()
+{
+ size_t wr_idx = 0;
+
+ for (size_t rd_idx = 0; rd_idx < m_cse.size(); rd_idx++)
+ {
+ if (m_cse[rd_idx].m_pc != nullptr)
+ {
+ if (rd_idx != wr_idx)
+ {
+ m_cse[wr_idx].m_pc = m_cse[rd_idx].m_pc;
+ m_cse[wr_idx].m_seqnum = m_cse[rd_idx].m_seqnum;
+ }
+ wr_idx++;
+ }
+ }
+
+ m_cse.resize(wr_idx);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.h
new file mode 100644
index 00000000..b33e1dd5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ChunkStack.h
@@ -0,0 +1,123 @@
+/**
+ * @file ChunkStack.h
+ * Manages a simple stack of chunks
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef CHUNKSTACK_H_INCLUDED
+#define CHUNKSTACK_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+class ChunkStack
+{
+public:
+ struct Entry
+ {
+ Entry()
+ : m_seqnum(0)
+ , m_pc(0)
+ {
+ }
+
+
+ Entry(const Entry &ref)
+ : m_seqnum(ref.m_seqnum)
+ , m_pc(ref.m_pc)
+ {
+ }
+
+
+ Entry(size_t sn, Chunk *pc)
+ : m_seqnum(sn)
+ , m_pc(pc)
+ {
+ }
+
+
+ size_t m_seqnum;
+ Chunk *m_pc;
+ };
+
+protected:
+ std::deque<Entry> m_cse;
+ size_t m_seqnum; //! current sequence number
+
+public:
+ ChunkStack()
+ : m_seqnum(0)
+ {
+ }
+
+
+ ChunkStack(const ChunkStack &cs)
+ {
+ Set(cs);
+ }
+
+
+ virtual ~ChunkStack()
+ {
+ }
+
+
+ void Set(const ChunkStack &cs);
+
+
+ void Push_Back(Chunk *pc)
+ {
+ Push_Back(pc, ++m_seqnum);
+ }
+
+
+ bool Empty() const
+ {
+ return(m_cse.empty());
+ }
+
+
+ size_t Len() const
+ {
+ return(m_cse.size());
+ }
+
+
+ const Entry *Top() const;
+
+
+ const Entry *Get(size_t idx) const;
+
+
+ Chunk *GetChunk(size_t idx) const;
+
+
+ Chunk *Pop_Back();
+
+
+ void Push_Back(Chunk *pc, size_t seqnum);
+
+
+ Chunk *Pop_Front();
+
+
+ void Reset()
+ {
+ m_cse.clear();
+ }
+
+
+ /**
+ * Mark an entry to be removed by Collapse()
+ *
+ * @param idx The item to remove
+ */
+ void Zap(size_t idx);
+
+
+ //! Compresses down the stack by removing dead entries
+ void Collapse();
+};
+
+
+#endif /* CHUNKSTACK_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.cpp
new file mode 100644
index 00000000..02536aa4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.cpp
@@ -0,0 +1,2919 @@
+/**
+ * @file EnumStructUnionParser.cpp
+ *
+ * @author
+ * @license GPL v2+
+ */
+
+#include "EnumStructUnionParser.h"
+
+#include "combine_fix_mark.h"
+#include "combine_skip.h"
+#include "combine_tools.h"
+#include "flag_parens.h"
+#include "lang_pawn.h"
+
+
+/**
+ * Extern declarations
+ */
+extern const char *get_token_name(E_Token);
+extern void log_pcf_flags(log_sev_t, pcf_flags_t);
+
+
+/**
+ * Forward declarations
+ */
+static std::pair<Chunk *, Chunk *> match_variable_end(Chunk *, std::size_t);
+static std::pair<Chunk *, Chunk *> match_variable_start(Chunk *, std::size_t);
+static Chunk *skip_scope_resolution_and_nested_name_specifiers(Chunk *);
+static Chunk *skip_scope_resolution_and_nested_name_specifiers_rev(Chunk *);
+
+
+/**
+ * Returns true if two adjacent chunks potentially match a pattern consistent
+ * with that of a qualified identifier
+ */
+static bool adj_tokens_match_qualified_identifier_pattern(Chunk *prev, Chunk *next)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( prev != nullptr
+ && next != nullptr)
+ {
+ auto prev_token_type = prev->type;
+ auto next_token_type = next->type;
+
+ switch (prev_token_type)
+ {
+ case CT_ANGLE_CLOSE:
+ /**
+ * assuming the previous token is possibly the closing angle of a
+ * templated type, the next token may be a scope resolution operator ("::")
+ */
+ return(next_token_type == CT_DC_MEMBER);
+
+ case CT_ANGLE_OPEN:
+ /**
+ * assuming the previous token is possibly the opening angle of a
+ * templated type, just check to see if there's a matching closing
+ * angle
+ */
+ return(chunk_skip_to_match(prev, E_Scope::PREPROC) != nullptr);
+
+ case CT_DC_MEMBER:
+ /**
+ * if the previous token is a double colon ("::"), it is likely part
+ * of a chain of scope-resolution qualifications preceding a word or
+ * type
+ */
+ return( next_token_type == CT_TYPE
+ || next_token_type == CT_WORD);
+
+ case CT_TYPE:
+ case CT_WORD:
+ /**
+ * if the previous token is an identifier, the next token may be
+ * one of the following:
+ * - an opening angle, which may indicate a templated type as part of a
+ * scope resolution preceding the actual variable identifier
+ * - a double colon ("::")
+ */
+ return( next_token_type == CT_ANGLE_OPEN
+ || next_token_type == CT_DC_MEMBER);
+
+ default:
+ // do nothing
+ break;
+ } // switch
+ }
+ return(false);
+} // adj_tokens_match_qualified_identifier_pattern
+
+
+/**
+ * Returns true if two adjacent chunks potentially match a pattern consistent
+ * with that of a variable definition
+ */
+static bool adj_tokens_match_var_def_pattern(Chunk *prev, Chunk *next)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( prev != nullptr
+ && next != nullptr)
+ {
+ auto prev_token_type = prev->type;
+ auto next_token_type = next->type;
+
+ switch (prev_token_type)
+ {
+ case CT_ANGLE_CLOSE:
+ /**
+ * assuming the previous token is possibly the closing angle of a
+ * templated type, the next token may be one of the following:
+ * - a pointer symbol ('*', '^')
+ * - a double colon ("::")
+ * - a reference symbol ('&')
+ * - a qualifier (const, etc.)
+ * - an identifier
+ */
+ return( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_DC_MEMBER
+ || next_token_type == CT_QUALIFIER
+ || next_token_type == CT_WORD);
+
+
+ case CT_ANGLE_OPEN:
+ /**
+ * assuming the previous token is possibly the opening angle of a
+ * templated type, just check to see if there's a matching closing
+ * angle
+ */
+ return(chunk_skip_to_match(prev, E_Scope::PREPROC) != nullptr);
+
+ case CT_BRACE_CLOSE:
+ /**
+ * assuming the previous token is possibly the closing brace of a
+ * class/enum/struct/union definition, one or more inline variable
+ * definitions may follow; in that case, the next token may be one of
+ * the following:
+ * - a pointer symbol ('*', '^')
+ * - a reference symbol ('&')
+ * - a qualifier (const, etc.)
+ * - an identifier
+ */
+ return( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_QUALIFIER
+ || next_token_type == CT_WORD);
+
+ case CT_BRACE_OPEN:
+ /**
+ * if the previous token is an opening brace, it may indicate the
+ * start of a braced initializer list - skip ahead to find a matching
+ * closing brace
+ */
+ return(chunk_skip_to_match(prev, E_Scope::PREPROC) != nullptr);
+
+ case CT_BYREF:
+ /**
+ * if the previous token is a reference symbol ('&'), the next token
+ * may be an identifier
+ */
+ return(next_token_type == CT_WORD);
+
+ case CT_CARET:
+ /**
+ * if the previous token is a managed C++/CLI pointer symbol ('^'),
+ * the next token may be one of the following:
+ * - a pointer symbol ('*', '^')
+ * - a reference symbol ('&')
+ * - a qualifier (const, etc.)
+ * - an identifier
+ */
+ return( language_is_set(LANG_CPP)
+ && ( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_QUALIFIER
+ || next_token_type == CT_WORD));
+
+ case CT_COMMA:
+ /**
+ * if the previous token is a comma, this may indicate a variable
+ * declaration trailing a prior declaration; in that case, the next
+ * token may be one of the following:
+ * - a pointer symbol ('*', '^')
+ * - a reference symbol ('&')
+ * - an identifier
+ */
+ return( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_WORD);
+
+ case CT_DC_MEMBER:
+ /**
+ * if the previous token is a double colon ("::"), it is likely part
+ * of a chain of scope-resolution qualifications preceding a word or
+ * type
+ */
+ return( next_token_type == CT_TYPE
+ || next_token_type == CT_WORD);
+
+ case CT_PAREN_OPEN:
+ /**
+ * if the previous token is an opening paren, it may indicate the
+ * start of a constructor call parameter list - skip ahead to find a
+ * matching closing paren
+ */
+ next = chunk_skip_to_match(prev, E_Scope::PREPROC);
+
+ if (next != nullptr)
+ {
+ next_token_type = next->type;
+ }
+ return(next_token_type == CT_PAREN_CLOSE);
+
+ case CT_PTR_TYPE:
+ /**
+ * if the previous token is a pointer type, ('*', '^'), the next token
+ * may be one of the following:
+ * - another pointer symbol ('*', '^')
+ * - a reference symbol ('&')
+ * - a qualifier (const, etc.)
+ * - an identifier
+ */
+ return( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_QUALIFIER
+ || next_token_type == CT_WORD);
+
+ case CT_QUALIFIER:
+ /**
+ * if the previous token is a qualifier (const, etc.), the next token
+ * may be one of the following:
+ * - a pointer symbol ('*', '^')
+ * - a reference symbol ('&')
+ * - another qualifier
+ * - an identifier
+ */
+ return( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_QUALIFIER
+ || next_token_type == CT_WORD);
+
+ case CT_SQUARE_CLOSE:
+ /**
+ * if the previous token is a closing bracket, the next token may be
+ * an assignment following an array variable declaration
+ */
+ return(next_token_type == CT_ASSIGN);
+
+ case CT_SQUARE_OPEN:
+ /**
+ * if the previous token is an opening bracket, it may indicate an
+ * array declaration - skip ahead to find a matching closing bracket
+ */
+ return(chunk_skip_to_match(prev, E_Scope::PREPROC) != nullptr);
+
+ case CT_STAR:
+ /**
+ * if the previous token is a pointer symbol, ('*'), the next token
+ * may be one of the following:
+ * - another pointer symbol ('*', '^')
+ * - a reference symbol ('&')
+ * - a qualifier (const, etc.)
+ * - an identifier
+ */
+ return( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_QUALIFIER
+ || next_token_type == CT_WORD);
+
+ case CT_TSQUARE:
+ /**
+ * if the previous token is a set of brackets, the next token may be
+ * an assignment following an array variable declaration
+ */
+ return(next_token_type == CT_ASSIGN);
+
+ case CT_TYPE:
+ /**
+ * if the previous token is marked as a type, the next token may be
+ * one of the following:
+ * - a pointer symbol ('*', '^')
+ * - a reference symbol ('&')
+ * - an opening angle, which may indicate a templated type as part of a
+ * scope resolution preceding the actual variable identifier
+ * - a double colon ("::")
+ * - a qualifier (const, etc.)
+ * - an identifier
+ */
+ return( chunk_is_pointer_or_reference(next)
+ || next_token_type == CT_ANGLE_OPEN
+ || next_token_type == CT_DC_MEMBER
+ || next_token_type == CT_QUALIFIER
+ || next_token_type == CT_WORD);
+
+ case CT_WORD:
+ /**
+ * if the previous token is an identifier, the next token may be one
+ * of the following:
+ * - an assignment symbol ('=')
+ * - an opening angle, which may indicate a templated type as part of a
+ * scope resolution preceding the actual variable identifier
+ * - an opening brace, which may indicate a braced-initializer list
+ * - a double colon ("::")
+ * - an opening paren, which may indicate a constructor call parameter
+ * list
+ * - an opening square bracket, which may indicate an array variable
+ * - an set of empty square brackets, which also may indicate an array
+ * variable
+ */
+ return( next_token_type == CT_ANGLE_OPEN
+ || next_token_type == CT_ASSIGN
+ || next_token_type == CT_BRACE_OPEN
+ || next_token_type == CT_DC_MEMBER
+ || next_token_type == CT_PAREN_OPEN
+ || next_token_type == CT_SQUARE_OPEN
+ || next_token_type == CT_TSQUARE);
+
+ default:
+ // do nothing
+ break;
+ } // switch
+ }
+ return(false);
+} // adj_tokens_match_var_def_pattern
+
+
+/**
+ * Returns true if the first chunk occurs AFTER the second chunk in the argument
+ * list
+ * @param pc points to the first chunk
+ * @param after points to the second chunk
+ * @param test_equal if true, returns true when both chunks refer to the same chunk
+ */
+static bool chunk_is_after(Chunk *pc, Chunk *after, bool test_equal = true)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ if ( test_equal
+ && pc == after)
+ {
+ return(true);
+ }
+ else if (after != nullptr)
+ {
+ auto pc_column = pc->orig_col;
+ auto pc_line = pc->orig_line;
+ auto after_column = after->orig_col;
+ auto after_line = after->orig_line;
+
+ return( pc_line > after_line
+ || ( pc_line == after_line
+ && pc_column > after_column));
+ }
+ }
+ return(false);
+} // chunk_is_after
+
+
+/**
+ * Returns true if the first chunk occurs BEFORE the second chunk in the argument
+ * list
+ * @param pc points to the first chunk
+ * @param before points to the second chunk
+ * @param test_equal if true, returns true when both chunks refer to the same chunk
+ */
+static bool chunk_is_before(Chunk *pc, Chunk *before, bool test_equal = true)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ if ( test_equal
+ && pc == before)
+ {
+ return(true);
+ }
+ else if (before != nullptr)
+ {
+ auto pc_column = pc->orig_col;
+ auto pc_line = pc->orig_line;
+ auto before_column = before->orig_col;
+ auto before_line = before->orig_line;
+
+ return( pc_line < before_line
+ || ( pc_line == before_line
+ && pc_column < before_column));
+ }
+ }
+ return(false);
+} // chunk_is_before
+
+
+/**
+ * Returns true if the first chunk occurs both AFTER and BEFORE
+ * the second and third chunks, respectively, in the argument list
+ * @param pc points to the first chunk
+ * @param after points to the second chunk
+ * @param before points to the third chunk
+ * @param test_equal if true, returns true when the first chunk tests equal to
+ * either the second or third chunk
+ */
+static bool chunk_is_between(Chunk *pc, Chunk *after, Chunk *before, bool test_equal = true)
+{
+ LOG_FUNC_ENTRY();
+
+ return( chunk_is_before(pc, before, test_equal)
+ && chunk_is_after(pc, after, test_equal));
+} // chunk_is_between
+
+
+/**
+ * Returns true if the chunk under test is a reference to a macro defined elsewhere in
+ * the source file currently being processed. Note that a macro may be defined in
+ * another source or header file, for which this function does not currently account
+ */
+static bool chunk_is_macro_reference(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *next = Chunk::GetHead();
+
+ if ( ( language_is_set(LANG_CPP)
+ || language_is_set(LANG_C))
+ && chunk_is_token(pc, CT_WORD)
+ && !pc->flags.test(PCF_IN_PREPROC))
+ {
+ while ( next != nullptr
+ && next->IsNotNullChunk())
+ {
+ if ( next->flags.test(PCF_IN_PREPROC)
+ && std::strcmp(pc->str.c_str(), next->str.c_str()) == 0)
+ {
+ return(true);
+ }
+ next = chunk_search_next_cat(next, CT_MACRO);
+ }
+ }
+ return(false);
+} // chunk_is_macro_reference
+
+
+/**
+ * Returns true if the input chunk is a pointer/reference operator or a
+ * qualifier
+ */
+static bool chunk_is_pointer_reference_or_qualifier(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ return( chunk_is_pointer_or_reference(pc)
+ || ( chunk_is_token(pc, CT_QUALIFIER)
+ && !chunk_is_cpp_inheritance_access_specifier(pc)));
+} // chunk_is_pointer_reference_or_qualifier
+
+
+/**
+ * This function attempts to match the starting and ending chunks of a qualified
+ * identifier, which consists of one or more scope resolution operator(s) and
+ * zero or more nested name specifiers
+ * specifiers
+ * @param pc the starting chunk
+ * @return an std::pair, where the first chunk indicates the starting chunk of the
+ * match and second indicates the ending chunk. Upon finding a successful
+ * match, the starting chunk may consist of an identifier or a scope
+ * resolution operator, while the ending chunk may consist of identifier
+ * or the closing angle bracket of a template. If no match is found, a
+ * pair of null chunks is returned
+ */
+static std::pair<Chunk *, Chunk *> match_qualified_identifier(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ auto *end = skip_scope_resolution_and_nested_name_specifiers(pc);
+ auto *start = skip_scope_resolution_and_nested_name_specifiers_rev(pc);
+
+ if ( end != nullptr
+ && start != nullptr)
+ {
+ auto *double_colon = chunk_search_next_cat(start, CT_DC_MEMBER);
+
+ if ( double_colon != nullptr
+ && chunk_is_between(double_colon, start, end))
+ {
+ return(std::make_pair(start, end));
+ }
+ }
+ return(std::make_pair(nullptr, nullptr));
+} // match_qualified_identifier
+
+
+/**
+ * Starting from the input chunk, this function attempts to match a variable
+ * declaration/definition in both the forward and reverse directions; each pair of
+ * consecutive chunks is tested to determine if a potential match is satisfied.
+ * @param pc the starting chunk
+ * @param level the brace level
+ * @return upon successful match, function returns an std::tuple, where the
+ * first chunk indicates the starting chunk, the second chunk indicates
+ * the identifier name, and the third chunk indicates the end associated
+ * with the variable declaration/definition
+ */
+static std::tuple<Chunk *, Chunk *, Chunk *> match_variable(Chunk *pc, std::size_t level)
+{
+ LOG_FUNC_ENTRY();
+
+ auto identifier_end_pair = match_variable_end(pc, level);
+ auto start_identifier_pair = match_variable_start(pc, level);
+ auto *end = identifier_end_pair.second;
+ auto *identifier = identifier_end_pair.first != nullptr ? identifier_end_pair.first : start_identifier_pair.second;
+ auto *start = start_identifier_pair.first;
+
+ /**
+ * a forward search starting at the chunk under test will fail if two consecutive chunks marked as CT_WORD
+ * are encountered; in that case, it's likely that the preceding chunk indicates a type and the subsequent
+ * chunk indicates a variable declaration/definition
+ */
+
+ if ( identifier->IsNotNullChunk()
+ && start->IsNotNullChunk()
+ && ( end != nullptr
+ || chunk_is_token(identifier->GetPrevNcNnlNi(), CT_WORD)))
+ {
+ return(std::make_tuple(start, identifier, end));
+ }
+ return(std::make_tuple(nullptr, nullptr, nullptr));
+} // match_variable
+
+
+/**
+ * Starting from the input chunk, this function attempts to match a variable in the
+ * forward direction, and tests each pair of consecutive chunks to determine if a
+ * potential variable declaration/definition match is satisfied. Secondly, the
+ * function attempts to identify the end chunk associated with the candidate variable
+ * match. For scalar variables (simply declared and not defined), both the end chunk
+ * and identifier chunk should be one in the same
+ * @param pc the starting chunk
+ * @param level the brace level
+ * @return an std::pair, where the first chunk indicates the identifier
+ * (if non-null) and the second chunk indicates the end associated with
+ * the variable declaration/definition; assuming a valid match, the first
+ * chunk may be null if the function is called with a starting chunk
+ * that occurs after the identifier
+ */
+static std::pair<Chunk *, Chunk *> match_variable_end(Chunk *pc, std::size_t level)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *identifier = nullptr;
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ /**
+ * skip any right-hand side assignments
+ */
+ Chunk *rhs_exp_end = nullptr;
+
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ /**
+ * store a pointer to the end chunk of the rhs expression;
+ * use it later to test against setting the identifier
+ */
+ rhs_exp_end = skip_to_expression_end(pc);
+ pc = rhs_exp_end;
+ }
+
+ /**
+ * skip current and preceding chunks if at a higher brace level
+ */
+ while ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && pc->level > level)
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ /**
+ * skip to any following match for angle brackets, braces, parens,
+ * or square brackets
+ */
+ if ( chunk_is_token(pc, CT_ANGLE_OPEN)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_paren_open(pc)
+ || chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ pc = chunk_skip_to_match(pc, E_Scope::PREPROC);
+ }
+ /**
+ * call a separate function to validate adjacent tokens as potentially
+ * matching a variable declaration/definition
+ */
+
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( chunk_is_not_token(next, CT_COMMA)
+ && chunk_is_not_token(next, CT_FPAREN_CLOSE)
+ && !chunk_is_semicolon(next)
+ && !adj_tokens_match_var_def_pattern(pc, next))
+ {
+ /**
+ * error, pattern is not consistent with a variable declaration/definition
+ */
+
+ break;
+ }
+
+ if ( chunk_is_token(pc, CT_WORD)
+ && pc != rhs_exp_end)
+ {
+ /**
+ * we've encountered a candidate for the variable name
+ */
+
+ identifier = pc;
+ }
+
+ /**
+ * we're done searching if we've previously identified a variable name
+ * and then encounter a comma or semicolon
+ */
+ if ( chunk_is_token(next, CT_COMMA)
+ || chunk_is_token(next, CT_FPAREN_CLOSE)
+ || chunk_is_semicolon(next))
+ {
+ return(std::make_pair(identifier, pc));
+ }
+ pc = next;
+ }
+ return(std::make_pair(nullptr, nullptr));
+} // match_variable_end
+
+
+/**
+ * Starting from the input chunk, this function attempts to match a variable in the
+ * reverse direction, and tests each pair of consecutive chunks to determine if a
+ * potential variable declaration/definition match is satisfied. Secondly, the
+ * function attempts to identify the starting chunk associated with the candidate
+ * variable match. The start and identifier chunks may refer to each other in cases
+ * where the identifier is not preceded by pointer or reference operators or qualifiers,
+ * etc.
+ * @param pc the starting chunk
+ * @param level the brace level
+ * @return an std::pair, where the first chunk indicates the starting chunk and
+ * the second chunk indicates the identifier associated with the variable
+ * match; assuming a valid match, the second chunk may be null if the
+ * function is called with a starting chunk that occurs before the
+ * identifier
+ */
+static std::pair<Chunk *, Chunk *> match_variable_start(Chunk *pc, std::size_t level)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *identifier = Chunk::NullChunkPtr;
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ while (pc->IsNotNullChunk())
+ {
+ /**
+ * skip any right-hand side assignments
+ */
+ Chunk *before_rhs_exp_start = skip_expression_rev(pc);
+ Chunk *prev = Chunk::NullChunkPtr;
+ Chunk *next = pc;
+
+ while ( chunk_is_after(next, before_rhs_exp_start)
+ && pc != prev)
+ {
+ next = prev;
+ prev = next->GetPrevNcNnlNi();
+
+ if (chunk_is_token(next, CT_ASSIGN))
+ {
+ pc = prev;
+ }
+ }
+ /**
+ * skip current and preceding chunks if at a higher brace level
+ */
+
+ while ( pc->IsNotNullChunk()
+ && pc->level > level)
+ {
+ pc = pc->GetPrevNcNnlNi();
+ }
+
+ /**
+ * skip to any preceding match for angle brackets, braces, parens,
+ * or square brackets
+ */
+ if ( chunk_is_token(pc, CT_ANGLE_CLOSE)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_paren_close(pc)
+ || chunk_is_token(pc, CT_SQUARE_CLOSE))
+ {
+ pc = chunk_skip_to_match_rev(pc, E_Scope::PREPROC);
+ }
+ /**
+ * call a separate function to validate adjacent tokens as potentially
+ * matching a variable declaration/definition
+ */
+
+ prev = pc->GetPrevNcNnlNi();
+
+ if (!adj_tokens_match_var_def_pattern(prev, pc))
+ {
+ /**
+ * perhaps the previous chunk possibly indicates a type that yet to be
+ * marked? if not, then break
+ */
+ if ( chunk_is_not_token(prev, CT_WORD)
+ || ( !chunk_is_pointer_or_reference(pc)
+ && chunk_is_not_token(pc, CT_WORD)))
+ {
+ /**
+ * error, pattern is not consistent with a variable declaration/definition
+ */
+
+ break;
+ }
+ }
+
+ if ( identifier->IsNullChunk()
+ && chunk_is_token(pc, CT_WORD))
+ {
+ /**
+ * we've encountered a candidate for the variable name
+ */
+
+ identifier = pc;
+ }
+
+ /**
+ * we're done searching if we've previously identified a variable name
+ * and then encounter another identifier, or we encounter a closing
+ * brace (which would likely indicate an inline variable definition)
+ */
+ if ( chunk_is_token(prev, CT_ANGLE_CLOSE)
+ || chunk_is_token(prev, CT_BRACE_CLOSE)
+ || chunk_is_token(prev, CT_COMMA)
+ || chunk_is_token(prev, CT_TYPE)
+ || chunk_is_token(prev, CT_WORD))
+ {
+ return(std::make_pair(pc, identifier));
+ }
+ pc = prev;
+ }
+ return(std::make_pair(Chunk::NullChunkPtr, Chunk::NullChunkPtr));
+} // match_variable_start
+
+
+/**
+ * Skip forward past any scope resolution operators and nested name specifiers and return
+ * just the qualified identifier name; while similar to the existing skip_dc_member()
+ * function, this function also takes into account templates that may comprise any
+ * nested name specifiers
+ */
+static Chunk *skip_scope_resolution_and_nested_name_specifiers(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( ( pc != nullptr
+ && pc->flags.test(PCF_IN_TEMPLATE))
+ || chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_WORD))
+ {
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ /**
+ * skip to any following match for angle brackets
+ */
+ if (chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ pc = chunk_skip_to_match(pc, E_Scope::PREPROC);
+ }
+ Chunk *next = pc->GetNextNcNnl();
+
+ /**
+ * call a separate function to validate adjacent tokens as potentially
+ * matching a qualified identifier
+ */
+ if (!adj_tokens_match_qualified_identifier_pattern(pc, next))
+ {
+ break;
+ }
+ pc = next;
+ }
+ }
+ return(pc);
+} // skip_scope_resolution_and_nested_name_specifiers
+
+
+/**
+ * Skip in reverse to the beginning chunk of a qualified identifier; while similar to
+ * the existing skip_dc_member_rev() function, this function also takes into account
+ * templates that may comprise any nested name specifiers
+ */
+static Chunk *skip_scope_resolution_and_nested_name_specifiers_rev(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ if ( ( pc->IsNotNullChunk()
+ && pc->flags.test(PCF_IN_TEMPLATE))
+ || chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_WORD))
+ {
+ while (pc->IsNotNullChunk())
+ {
+ /**
+ * skip to any preceding match for angle brackets
+ */
+ if (chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ pc = chunk_skip_to_match_rev(pc, E_Scope::PREPROC);
+ }
+ Chunk *prev = pc->GetPrevNcNnlNi();
+
+ /**
+ * call a separate function to validate adjacent tokens as potentially
+ * matching a qualified identifier
+ */
+ if (!adj_tokens_match_qualified_identifier_pattern(prev, pc))
+ {
+ break;
+ }
+ pc = prev;
+ }
+ }
+ return(pc);
+} // skip_scope_resolution_and_nested_name_specifiers_rev
+
+
+EnumStructUnionParser::EnumStructUnionParser()
+ : m_end(nullptr)
+ , m_parse_error(false)
+ , m_start(nullptr)
+ , m_type(nullptr)
+{
+} // EnumStructUnionParser::EnumStructUnionParser
+
+
+EnumStructUnionParser::~EnumStructUnionParser()
+{
+} // EnumStructUnionParser::~EnumStructUnionParser
+
+
+void EnumStructUnionParser::analyze_identifiers()
+{
+ LOG_FUNC_ENTRY();
+
+ /**
+ * the enum (and variable declarations thereof) could be of
+ * the following forms:
+ *
+ * "enum type [: integral_type] { ... } [x, ...]"
+ * "enum type : integral_type"
+ * "enum type x, ..."
+ * "enum class type [: integral_type] { ... } [x, ...]"
+ * "enum class type [: integral_type]"
+ * "enum [: integral_type] { ... } x, ..."
+ */
+
+ /**
+ * the class/struct (and variable declarations thereof) could be of
+ * the following forms:
+ *
+ * "template<...> class/struct[<...>] [macros/attributes ...] type [: bases ...] { }"
+ * "template<...> class/struct[<...>] [macros/attributes ...] type"
+ * "class/struct [macros/attributes ...] type [: bases ...] { } [x, ...]"
+ * "class/struct [macros/attributes ...] type [x, ...]"
+ * "class/struct [macros/attributes ...] [: bases] { } x, ..."
+ */
+
+ Chunk *template_end = get_template_end();
+ auto *body_end = get_body_end();
+ auto *body_start = get_body_start();
+ pcf_flags_t flags = PCF_VAR_1ST_DEF;
+ auto *inheritance_start = get_inheritance_start();
+ Chunk *pc = body_end ? body_end : m_start;
+
+ /**
+ * first, try a simple approach to identify any associated type
+ */
+ if (try_pre_identify_type())
+ {
+ /**
+ * a type was identified, meaning a pair of braces, angle brackets, or
+ * a colon was found; if a colon was found, then there should be a
+ * balanced set of braces that follow; therefore, start the search for
+ * variable identifiers after the closing brace or close angle bracket
+ */
+
+ if (body_end != nullptr)
+ {
+ pc = body_end;
+ }
+ else if (template_end != nullptr)
+ {
+ pc = template_end;
+ }
+ }
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ if (pc->GetNextNcNnl() == m_end)
+ {
+ /**
+ * we're likely at the end of a class/enum/struct/union body which lacks
+ * any trailing inline definitions
+ */
+
+ pc = m_end->GetNextNcNnl();
+ }
+
+ if ( type_identified()
+ || chunk_is_class_enum_struct_union(pc)
+ || pc == m_end)
+ {
+ /**
+ * in case we're pointing at the end chunk, advance the chunk pointer
+ * by one more so that we don't perform a variable identifier search
+ * below
+ */
+ pc = pc->GetNextNcNnl();
+ }
+
+ if (body_end != nullptr)
+ {
+ /**
+ * a closing brace was found, so any identifiers trailing the closing
+ * brace are probably inline variable declarations following a
+ * class/enum/struct/union definition
+ */
+ flags |= PCF_VAR_INLINE;
+ }
+ else if (!type_identified())
+ {
+ /**
+ * skip any chain of one or more function-like macro calls,
+ * declspecs, and attributes
+ */
+
+ Chunk *tmp = pc;
+
+ do
+ {
+ pc = tmp;
+ tmp = skip_attribute_next(tmp);
+ tmp = skip_declspec_next(tmp);
+ } while (tmp != pc);
+ }
+ /**
+ * try to match some variable identifiers in the loop below
+ */
+
+ while (chunk_is_between(pc, m_start, m_end, false))
+ {
+ auto match = match_variable(pc, m_start->level);
+ auto *start = std::get<0>(match);
+ auto *identifier = std::get<1>(match);
+ auto *end = std::get<2>(match);
+
+ if ( start != nullptr
+ && identifier != nullptr)
+ {
+ if (end != nullptr)
+ {
+ mark_variable(identifier, flags);
+
+ if (flags & PCF_VAR_1ST)
+ {
+ flags &= ~PCF_VAR_1ST; // clear the first flag for the next items
+ }
+ }
+ }
+
+ if (end != nullptr)
+ {
+ pc = end;
+ }
+ pc = pc->GetNextNcNnl();
+
+ /**
+ * skip any right-hand side assignments
+ */
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ pc = skip_to_expression_end(pc);
+ }
+
+ /**
+ * if we're sitting at a comma or semicolon, skip it
+ */
+ if ( chunk_is_semicolon(pc)
+ || ( chunk_is_token(pc, CT_COMMA)
+ && !pc->flags.test_any(PCF_IN_FCN_DEF | PCF_IN_FCN_CALL | PCF_IN_TEMPLATE)
+ && !chunk_is_between(pc, inheritance_start, body_start)))
+ {
+ pc = pc->GetNextNcNnl();
+ }
+ }
+ /**
+ * if we still haven't identified a type, try doing so now that the
+ * variables, if any, have been marked
+ */
+ try_post_identify_type();
+
+ /**
+ * identify possible macros preceding the type name
+ */
+ try_post_identify_macro_calls();
+
+ if ( chunk_is_class_or_struct(m_start)
+ && ( chunk_is_not_token(m_start, CT_STRUCT)
+ || !language_is_set(LANG_C)))
+ {
+ /**
+ * if a type has been identified, mark any constructor matching constructor
+ * declarations/definitions
+ */
+ mark_constructors();
+ }
+
+ if (type_identified())
+ {
+ if (~flags & PCF_VAR_1ST)
+ {
+ /**
+ * PCF_VAR_1ST was cleared and a type was identified; therefore, set
+ * PCF_VAR_TYPE for the identified type
+ */
+ chunk_flags_set(m_type, PCF_VAR_TYPE);
+ }
+ else if (~flags & PCF_VAR_INLINE)
+ {
+ /**
+ * if a type was identified but no braced-enclosed body was found and no
+ * identifiers were marked as variables, then we're likely we're likely
+ * dealing with a forward declaration
+ */
+ flag_series(m_start, m_type, PCF_INCOMPLETE);
+ }
+ }
+} // EnumStructUnionParser::analyze_identifiers
+
+
+bool EnumStructUnionParser::body_detected() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto *body_end = get_body_end();
+ auto *body_start = get_body_start();
+
+ return( body_end != nullptr
+ && body_start != nullptr);
+} // EnumStructUnionParser::body_detected
+
+
+bool EnumStructUnionParser::comma_separated_values_detected() const
+{
+ LOG_FUNC_ENTRY();
+
+ return(!get_top_level_commas().empty());
+} // EnumStructUnionParser::comma_separated_values_detected
+
+
+bool EnumStructUnionParser::enum_base_detected() const
+{
+ LOG_FUNC_ENTRY();
+
+ return(m_chunk_map.find(CT_BIT_COLON) != m_chunk_map.cend());
+} // EnumStructUnionParser::enum_base_detected
+
+
+Chunk *EnumStructUnionParser::get_body_end() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_BRACE_CLOSE);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_body_end
+
+
+Chunk *EnumStructUnionParser::get_body_start() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_BRACE_OPEN);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_body_start
+
+
+Chunk *EnumStructUnionParser::get_enum_base_start() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_BIT_COLON);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_enum_base_start
+
+
+Chunk *EnumStructUnionParser::get_first_top_level_comma() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_COMMA);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_first_top_level_comma
+
+
+Chunk *EnumStructUnionParser::get_inheritance_end() const
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *brace_open = nullptr;
+ auto *inheritance_start = get_inheritance_start();
+
+ if (inheritance_start != nullptr)
+ {
+ brace_open = get_body_start();
+
+ if (brace_open == nullptr)
+ {
+ brace_open = inheritance_start->GetNextType(CT_BRACE_OPEN, m_start->level, E_Scope::ALL);
+ }
+ }
+ return(brace_open);
+} // EnumStructUnionParser::get_inheritance_end
+
+
+Chunk *EnumStructUnionParser::get_inheritance_start() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_COLON);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_inheritance_start
+
+
+std::map<std::size_t, Chunk *> EnumStructUnionParser::get_question_operators() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_QUESTION);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second);
+ }
+ return(std::map<std::size_t, Chunk *>());
+} // EnumStructUnionParser::get_question_operators
+
+
+Chunk *EnumStructUnionParser::get_template_end() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_ANGLE_CLOSE);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_template_end
+
+
+Chunk *EnumStructUnionParser::get_template_start() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_ANGLE_OPEN);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_template_start
+
+
+std::map<std::size_t, Chunk *> EnumStructUnionParser::get_top_level_commas() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_COMMA);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second);
+ }
+ return(std::map<std::size_t, Chunk *>());
+} // EnumStructUnionParser::get_top_level_commas
+
+
+Chunk *EnumStructUnionParser::get_where_end() const
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *brace_open = nullptr;
+ auto *where_start = get_where_start();
+
+ if (where_start != nullptr)
+ {
+ brace_open = get_body_start();
+
+ if (brace_open == nullptr)
+ {
+ brace_open = where_start->GetNextType(CT_BRACE_OPEN, m_start->level, E_Scope::ALL);
+ }
+ }
+ return(brace_open);
+} // EnumStructUnionParser::get_where_end
+
+
+Chunk *EnumStructUnionParser::get_where_start() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto &&it_token_chunk_map_pair = m_chunk_map.find(CT_WHERE);
+
+ if (it_token_chunk_map_pair != m_chunk_map.cend())
+ {
+ return(it_token_chunk_map_pair->second.at(0));
+ }
+ return(nullptr);
+} // EnumStructUnionParser::get_where_start
+
+
+bool EnumStructUnionParser::inheritance_detected() const
+{
+ LOG_FUNC_ENTRY();
+
+ return(m_chunk_map.find(CT_COLON) != m_chunk_map.cend());
+} // EnumStructUnionParser::inheritance_detected
+
+
+void EnumStructUnionParser::initialize(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ parse_error_detected(false);
+ m_chunk_map.clear();
+
+ m_start = pc;
+ m_type = nullptr;
+ pc = try_find_end_chunk(pc);
+ m_end = refine_end_chunk(pc);
+} // EnumStructUnionParser::initialize
+
+
+bool EnumStructUnionParser::is_potential_end_chunk(Chunk *pc) const
+{
+ LOG_FUNC_ENTRY();
+
+ /**
+ * test for a semicolon or closing brace at the level of the starting chunk
+ */
+ if ( pc == nullptr
+ || parse_error_detected()
+ || ( ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_BRACE_CLOSE))
+ && pc->level == m_start->level))
+ {
+ return(true);
+ }
+ /**
+ * check for the following:
+ * 1) did we encounter a closing paren, which may indicate the end of cast?
+ * 2) did we cross a preprocessor boundary?
+ * 3) did we cross the closing paren of a function signature?
+ */
+
+ auto const pc_in_funcdef = pc->flags & PCF_IN_FCN_DEF;
+ auto const pc_in_preproc = pc->flags & PCF_IN_PREPROC;
+ auto const start_in_funcdef = m_start->flags & PCF_IN_FCN_DEF;
+ auto const start_in_preproc = m_start->flags & PCF_IN_PREPROC;
+
+ /**
+ * the following may identify cases where we've reached the
+ * end of a cast terminated by a closing paren
+ */
+ if ( ( chunk_is_paren_close(pc) // Issue #3538
+ && pc->level < m_start->level)
+ || (start_in_funcdef ^ pc_in_funcdef).test_any()
+ || (start_in_preproc ^ pc_in_preproc).test_any())
+ {
+ return(true);
+ }
+ /**
+ * check whether the current chunk's nest level is less than that
+ * of the starting chunk
+ */
+
+ std::size_t pc_template_nest = get_cpp_template_angle_nest_level(pc);
+ std::size_t start_template_nest = get_cpp_template_angle_nest_level(m_start);
+
+ if (start_template_nest > pc_template_nest)
+ {
+ return(true);
+ }
+ /**
+ * assuming the chunk is within a function call/definition, check the following:
+ * 1) chunk is a closing function paren at a lower level than the starting chunk
+ * 2) chunk is an assignment ('=') or comma at the level of the starting chunk
+ */
+
+ auto const pc_in_funccall = pc->flags & PCF_IN_FCN_CALL;
+ auto const start_in_funccall = m_start->flags & PCF_IN_FCN_CALL;
+
+ if ( ( pc_in_funccall.test_any()
+ && start_in_funccall.test_any()
+ && chunk_is_token(pc, CT_COMMA)
+ && pc->level == m_start->level)
+ || ( pc_in_funcdef.test_any()
+ && ( ( chunk_is_token(pc, CT_FPAREN_CLOSE)
+ && pc->level < m_start->level)
+ || ( ( chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_COMMA))
+ && pc->level == m_start->level))))
+ {
+ return(true);
+ }
+ return(false);
+} // EnumStructUnionParser::is_potential_end_chunk
+
+
+bool EnumStructUnionParser::is_within_conditional(Chunk *pc) const
+{
+ LOG_FUNC_ENTRY();
+
+ auto question_operators = get_question_operators();
+
+ if (!question_operators.empty())
+ {
+ auto &&it_token_chunk_pair = question_operators.cbegin();
+
+ while (it_token_chunk_pair != question_operators.cend())
+ {
+ auto *question = it_token_chunk_pair->second;
+ auto *end = skip_to_expression_end(question);
+ auto *start = skip_to_expression_start(question);
+
+ if (chunk_is_between(pc, start, end))
+ {
+ return(true);
+ }
+ ++it_token_chunk_pair;
+ }
+ }
+ return(false);
+} // EnumStructUnionParser::is_within_conditional
+
+
+bool EnumStructUnionParser::is_within_inheritance_list(Chunk *pc) const
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc != nullptr
+ && pc->flags.test(PCF_IN_CLASS_BASE))
+ {
+ return(true);
+ }
+ auto *inheritance_end = get_inheritance_end();
+ auto *inheritance_start = get_inheritance_start();
+
+ if ( inheritance_end != nullptr
+ && inheritance_start != nullptr)
+ {
+ return(chunk_is_between(pc, inheritance_start, inheritance_end));
+ }
+ return(false);
+} // EnumStructUnionParser::is_within_inheritance_list
+
+
+bool EnumStructUnionParser::is_within_where_clause(Chunk *pc) const
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc != nullptr
+ && pc->flags.test(PCF_IN_WHERE_SPEC))
+ {
+ return(true);
+ }
+ auto *where_end = get_where_end();
+ auto *where_start = get_where_start();
+
+ if ( where_end != nullptr
+ && where_start != nullptr)
+ {
+ return(chunk_is_between(pc, where_start, where_end));
+ }
+ return(false);
+} // EnumStructUnionParser::is_within_where_clause
+
+
+void EnumStructUnionParser::mark_base_classes(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ pcf_flags_t flags = PCF_VAR_1ST_DEF;
+
+ while (pc != nullptr)
+ {
+ chunk_flags_set(pc, PCF_IN_CLASS_BASE);
+ /**
+ * clear the PCF_VAR_TYPE flag for all chunks within the inheritance list
+ * TODO: this may not be necessary in the future once code outside this
+ * class is improved such that PCF_VAR_TYPE is not set for these chunks
+ */
+ pc->flags &= ~PCF_VAR_TYPE;
+
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (chunk_is_token(next, CT_DC_MEMBER))
+ {
+ /**
+ * just in case it's a templated type
+ */
+ pc = skip_template_prev(pc);
+
+ if (chunk_is_token(pc, CT_WORD))
+ {
+ /**
+ * TODO:
+ * To comply with conventions used elsewhere in the code, we're going
+ * to change chunks marked CT_WORD to CT_TYPE if followed by a scope-
+ * resolution operator; if a chunk marked CT_WORD is followed by a set
+ * of angle brackets, then it's obviously a templated type. However,
+ * in the absence of a pair trailing angle brackets, the chunk may be
+ * a namespace rather than a type. Need to revisit this!
+ */
+ set_chunk_type(pc, CT_TYPE);
+ }
+ }
+ else if ( ( chunk_is_token(next, CT_BRACE_OPEN)
+ || ( chunk_is_token(next, CT_COMMA)
+ && !is_within_where_clause(next)))
+ && next->level == m_start->level)
+ {
+ /**
+ * just in case it's a templated type
+ */
+ pc = skip_template_prev(pc);
+
+ if (chunk_is_token(pc, CT_WORD))
+ {
+ chunk_flags_set(pc, flags);
+
+ if (flags & PCF_VAR_1ST)
+ {
+ flags &= ~PCF_VAR_1ST; // clear the first flag for the next items
+ }
+ }
+
+ if (chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ break;
+ }
+ }
+ pc = next;
+ }
+ chunk_flags_set(pc, PCF_IN_CLASS_BASE);
+} // EnumStructUnionParser::mark_base_classes
+
+
+void EnumStructUnionParser::mark_braces(Chunk *brace_open)
+{
+ LOG_FUNC_ENTRY();
+
+ pcf_flags_t flags = PCF_NONE;
+
+ if (chunk_is_token(m_start, CT_CLASS))
+ {
+ flags = PCF_IN_CLASS;
+ }
+ else if (chunk_is_enum(m_start))
+ {
+ flags = PCF_IN_ENUM;
+ }
+ else if (chunk_is_token(m_start, CT_STRUCT))
+ {
+ flags = PCF_IN_STRUCT;
+ }
+ /**
+ * TODO: why does flag_parens() flag the closing paren,
+ * but it doesn't flag the opening paren?
+ */
+
+ flag_parens(brace_open,
+ flags,
+ CT_NONE,
+ CT_NONE,
+ false);
+
+ if (chunk_is_class_struct_union(m_start))
+ {
+ mark_struct_union_body(brace_open);
+
+ auto *inheritance_start = get_inheritance_start();
+
+ if (inheritance_start != nullptr)
+ {
+ /**
+ * the class/struct/union is a derived class; mark the base
+ * classes between the colon/java "implements" keyword and the
+ * opening brace
+ */
+
+ mark_base_classes(inheritance_start);
+ }
+ }
+ set_chunk_parent(brace_open, m_start->type);
+
+ auto *brace_close = chunk_skip_to_match(brace_open, E_Scope::PREPROC);
+
+ if (brace_close != nullptr)
+ {
+ set_chunk_parent(brace_close, m_start->type);
+ }
+} // EnumStructUnionParser::mark_braces
+
+
+void EnumStructUnionParser::mark_class_colon(Chunk *colon)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LFTOR,
+ "%s(%d): Class colon detected: orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ colon->orig_line,
+ colon->orig_col);
+
+ set_chunk_type(colon, CT_CLASS_COLON);
+ set_chunk_parent(colon, m_start->type);
+} // EnumStructUnionParser::mark_class_colon
+
+
+void EnumStructUnionParser::mark_conditional_colon(Chunk *colon)
+{
+ set_chunk_type(colon, CT_COND_COLON);
+} // EnumStructUnionParser::mark_conditional_colon
+
+
+void EnumStructUnionParser::mark_constructors()
+{
+ LOG_FUNC_ENTRY();
+
+ /**
+ * if a type was previously identified, then look for
+ * class/struct constructors in the body
+ */
+ if ( body_detected()
+ && type_identified()
+ && chunk_is_class_or_struct(m_start))
+ {
+ LOG_FMT(LFTOR,
+ "%s(%d): orig_line is %zu, orig_col is %zu, start is '%s', parent_type is %s\n",
+ __unqualified_func__,
+ __LINE__,
+ m_start->orig_line,
+ m_start->orig_col,
+ m_start->Text(),
+ get_token_name(get_chunk_parent_type(m_start)));
+
+ log_pcf_flags(LFTOR, m_start->flags);
+
+ /**
+ * get the name of the type
+ */
+ auto *body_end = get_body_end();
+ auto *body_start = get_body_start();
+ auto *name = m_type->Text();
+
+ LOG_FMT(LFTOR,
+ "%s(%d): Name of type is '%s'\n",
+ __unqualified_func__,
+ __LINE__,
+ name);
+ log_pcf_flags(LFTOR, m_type->flags);
+
+ Chunk *next = Chunk::NullChunkPtr;
+ std::size_t level = m_type->brace_level + 1;
+
+ for (auto *prev = body_start; next != body_end; prev = next)
+ {
+ chunk_flags_set(prev, PCF_IN_CLASS);
+
+ next = skip_template_next(prev->GetNextNcNnl(E_Scope::PREPROC)); // Issue #3368
+
+ /**
+ * find a chunk within the class/struct body that
+ */
+ if ( prev->IsNotNullChunk()
+ && std::strcmp(prev->Text(), name) == 0
+ && prev->level == level
+ && chunk_is_paren_open(next))
+ {
+ set_chunk_type(prev, CT_FUNC_CLASS_DEF);
+
+ LOG_FMT(LFTOR,
+ "%s(%d): Constructor/destructor detected: '%s' at orig_line is %zu, orig_col is %zu, type is %s\n",
+ __unqualified_func__,
+ __LINE__,
+ name,
+ prev->orig_line,
+ prev->orig_col,
+ get_token_name(prev->type));
+
+ mark_cpp_constructor(prev);
+ }
+ }
+
+ chunk_flags_set(next, PCF_IN_CLASS);
+ }
+} // EnumStructUnionParser::mark_constructor
+
+
+void EnumStructUnionParser::mark_enum_integral_type(Chunk *colon)
+{
+ LOG_FUNC_ENTRY();
+
+ set_chunk_type(colon, CT_BIT_COLON);
+ set_chunk_parent(colon, m_start->type);
+
+ auto *body_start = get_body_start();
+ auto *pc = colon->GetNextNcNnl();
+
+ /**
+ * the chunk(s) between the colon and opening
+ * brace (if present) should specify the enum's
+ * integral type
+ */
+
+ while ( chunk_is_between(pc, m_start, m_end)
+ && pc != body_start
+ && chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && !chunk_is_semicolon(pc))
+ {
+ /**
+ * clear the PCF_VAR_TYPE flag for all chunks within the enum integral base
+ * TODO: this may not be necessary in the future once code outside this
+ * class is improved such that PCF_VAR_TYPE is not set for these chunks
+ */
+ if (chunk_is_not_token(pc, CT_DC_MEMBER)) // Issue #3198
+ {
+ pc->flags &= ~PCF_VAR_TYPE;
+ set_chunk_type(pc, CT_TYPE);
+ set_chunk_parent(pc, colon->type);
+ }
+ pc = pc->GetNextNcNnl();
+ }
+} // EnumStructUnionParser::mark_enum_integral_type
+
+
+void EnumStructUnionParser::mark_extracorporeal_lvalues()
+{
+ /**
+ * clear the PCF_LVALUE flag for all chunks outside the body definition,
+ * as this flag may have been set elsewhere by code outside this class
+ * TODO: the mark_lvalue() function needs some improvement so that the
+ * following isn't necessary
+ */
+ Chunk *next = m_start;
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ /**
+ * if the class is a template, go the extra step and correct the
+ * erroneously marked chunks - as previously mentioned, this likely
+ * won't be necessary with improvements to the mark_lvalue() function
+ */
+ if (get_chunk_parent_type(next) == CT_TEMPLATE)
+ {
+ while (true)
+ {
+ prev = next->GetPrevNcNnlNi();
+
+ if ( prev->IsNullChunk()
+ || ( !prev->flags.test(PCF_IN_TEMPLATE)
+ && chunk_is_not_token(prev, CT_TEMPLATE)))
+ {
+ break;
+ }
+ next = prev;
+ }
+ }
+ Chunk *body_end = get_body_end();
+ Chunk *body_start = get_body_start();
+
+ while (next != m_end)
+ {
+ if ( !chunk_is_between(next, body_start, body_end)
+ && next->flags.test(PCF_LVALUE))
+ {
+ next->flags &= ~PCF_LVALUE;
+ }
+ else if ( ( chunk_is_token(next, CT_ASSIGN)
+ || chunk_is_token(next, CT_BRACE_OPEN))
+ && chunk_is_token(prev, CT_WORD)
+ && prev->flags.test_any(PCF_VAR_DEF | PCF_VAR_1ST | PCF_VAR_INLINE))
+ {
+ chunk_flags_set(prev, PCF_LVALUE);
+ }
+ prev = next;
+ next = next->GetNextNcNnl();
+ }
+} // EnumStructUnionParser::mark_extracorporeal_lavlues
+
+
+void EnumStructUnionParser::mark_nested_name_specifiers(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ auto start_end_pair = match_qualified_identifier(pc);
+ auto start = start_end_pair.first;
+ auto end = start_end_pair.second;
+
+ for (pc = start; chunk_is_between(pc, start, end); pc = pc->GetNextNcNnl())
+ {
+ if (chunk_is_token(pc, CT_WORD))
+ {
+ /**
+ * if the next token is an opening angle, then we can safely
+ * mark the current identifier as a type
+ */
+ auto *next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_ANGLE_OPEN))
+ {
+ /**
+ * the template may have already been previously marked elsewhere...
+ */
+ auto *angle_open = next;
+ auto *angle_close = chunk_skip_to_match(angle_open, E_Scope::PREPROC);
+
+ if (angle_close == nullptr)
+ {
+ // parse error
+ parse_error_detected(true);
+
+ // TODO: should this be just a warning or an error (with exit condition?)
+ LOG_FMT(LWARN,
+ "%s(%d): Unmatched '<' at orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ angle_open->orig_line,
+ angle_open->orig_col);
+
+ break;
+ }
+ set_chunk_type(pc, CT_TYPE);
+ mark_template(next);
+ pc = angle_close;
+ }
+ else if ( is_within_inheritance_list(pc)
+ && ( chunk_is_token(next, CT_COMMA)
+ || chunk_is_token(next, CT_BRACE_OPEN)))
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ }
+ }
+} // EnumStructUnionParser::mark_nested_name_specifiers
+
+
+void EnumStructUnionParser::mark_pointer_types(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(pc, CT_WORD))
+ {
+ do
+ {
+ // TODO: should there be a CT_BYREF_TYPE?
+ pc = pc->GetPrevNcNnlNi();
+
+ if (chunk_is_ptr_operator(pc))
+ {
+ set_chunk_parent(pc, m_start->type);
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ } while (chunk_is_pointer_reference_or_qualifier(pc));
+ }
+} // EnumStructUnionParser::mark_pointer_types
+
+
+void EnumStructUnionParser::mark_template(Chunk *start) const
+{
+ LOG_FUNC_ENTRY();
+
+ if (start != nullptr)
+ {
+ LOG_FMT(LTEMPL,
+ "%s(%d): Template detected: '%s' at orig_line %zu, orig_col %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ start->Text(),
+ start->orig_line,
+ start->orig_col);
+ }
+ set_chunk_parent(start, CT_TEMPLATE);
+
+ auto *end = chunk_skip_to_match(start, E_Scope::PREPROC);
+
+ if (end != nullptr)
+ {
+ set_chunk_parent(end, CT_TEMPLATE);
+
+ mark_template_args(start, end);
+ }
+} // EnumStructUnionParser::mark_template
+
+
+void EnumStructUnionParser::mark_template_args(Chunk *start, Chunk *end) const
+{
+ LOG_FUNC_ENTRY();
+
+ if ( end != nullptr
+ && start != nullptr)
+ {
+ LOG_FMT(LTEMPL,
+ "%s(%d): Start of template detected: '%s' at orig_line %zu, orig_col %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ start->Text(),
+ start->orig_line,
+ start->orig_col);
+
+ pcf_flags_t flags = PCF_IN_TEMPLATE;
+ Chunk *next = start;
+
+ /**
+ * TODO: for now, just mark the chunks within the template as PCF_IN_TEMPLATE;
+ * we probably need to create a TemplateParser class to handle all
+ * things template-related
+ */
+
+ while (true)
+ {
+ next = next->GetNextNcNnl();
+
+ if (next == end)
+ {
+ break;
+ }
+ chunk_flags_set(next, flags);
+ }
+ LOG_FMT(LTEMPL,
+ "%s(%d): End of template detected: '%s' at orig_line %zu, orig_col %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ end->Text(),
+ end->orig_line,
+ end->orig_col);
+ }
+} // EnumStructUnionParser::mark_template_args
+
+
+void EnumStructUnionParser::mark_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc != nullptr)
+ {
+ m_type = pc;
+
+ do
+ {
+ make_type(pc);
+ set_chunk_parent(pc, m_start->type);
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ } while (chunk_is_pointer_or_reference(pc));
+ }
+} // EnumStructUnionParser::mark_type
+
+
+void EnumStructUnionParser::mark_variable(Chunk *variable, pcf_flags_t flags)
+{
+ LOG_FUNC_ENTRY();
+
+ if (variable != nullptr)
+ {
+ LOG_FMT(LVARDEF,
+ "%s(%d): Variable definition detected: '%s' at orig_line is %zu, orig_col is %zu, set %s\n",
+ __unqualified_func__,
+ __LINE__,
+ variable->Text(),
+ variable->orig_line,
+ variable->orig_col,
+ flags & PCF_VAR_1ST_DEF ? "PCF_VAR_1ST_DEF" : "PCF_VAR_1ST");
+
+ chunk_flags_set(variable, flags);
+ set_chunk_type(variable, CT_WORD);
+ mark_pointer_types(variable);
+ }
+} // EnumStructUnionParser::mark_variable
+
+
+void EnumStructUnionParser::mark_where_clause(Chunk *where)
+{
+ LOG_FUNC_ENTRY();
+
+ if (where != nullptr)
+ {
+ LOG_FMT(LFTOR,
+ "%s(%d): Where clause detected: orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ where->orig_line,
+ where->orig_col);
+ }
+ set_where_start(where);
+
+ auto *where_end = get_where_end();
+ auto *where_start = get_where_start();
+
+ set_where_end(where_end);
+
+ pcf_flags_t flags;
+
+ for (auto *pc = where_start; pc != where_end; pc = pc->GetNextNcNnl())
+ {
+ flags = mark_where_chunk(pc, m_start->type, flags);
+ }
+} // EnumStructUnionParser::mark_where_clause
+
+
+void EnumStructUnionParser::mark_where_colon(Chunk *colon)
+{
+ LOG_FUNC_ENTRY();
+
+ if (colon != nullptr)
+ {
+ LOG_FMT(LFTOR,
+ "%s(%d): Where colon detected: orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ colon->orig_line,
+ colon->orig_col);
+ }
+ set_chunk_type(colon, CT_WHERE_COLON);
+ set_chunk_parent(colon, m_start->type);
+} // EnumStructUnionParser::mark_where_colon
+
+
+void EnumStructUnionParser::parse(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ initialize(pc);
+
+ /**
+ * make sure this wasn't a cast, and also make sure we're
+ * actually dealing with a class/enum/struct/union type
+ */
+ if ( get_chunk_parent_type(m_start) == CT_C_CAST
+ || !chunk_is_class_enum_struct_union(m_start))
+ {
+ return;
+ }
+ Chunk *prev = m_start;
+ Chunk *next = prev->GetNextNcNnl();
+
+ /**
+ * the enum-key might be enum, enum class or enum struct
+ */
+ if (chunk_is_enum(next))
+ {
+ prev = next;
+ next = prev->GetNextNcNnl();
+ }
+ else if (chunk_is_enum(prev))
+ {
+ auto *prev_prev = prev->GetPrevNcNnlNi();
+
+ if ( chunk_is_enum(prev_prev)
+ && chunk_is_enum(prev))
+ {
+ m_start = prev_prev;
+ }
+ }
+ /**
+ * pre-process all chunks between the starting and ending chunks identified
+ * in the initial pass
+ */
+
+ while (chunk_is_between(next, m_start, m_end))
+ {
+ /**
+ * skip attributes
+ */
+ next = skip_attribute(next);
+
+ /**
+ * skip declspec
+ */
+ next = skip_declspec(next);
+
+ /**
+ * skip any right-hand side assignments
+ */
+ if (chunk_is_token(next, CT_ASSIGN))
+ {
+ next = skip_to_expression_end(next);
+ }
+
+ if ( chunk_is_token(next, CT_ANGLE_OPEN)
+ && !template_detected())
+ {
+ next = parse_angles(next);
+ }
+ else if ( chunk_is_token(next, CT_BRACE_OPEN)
+ && !body_detected())
+ {
+ next = parse_braces(next);
+ }
+ else if (chunk_is_colon(next))
+ {
+ parse_colon(next);
+ }
+ else if (chunk_is_token(next, CT_COMMA))
+ {
+ record_top_level_comma(next);
+ }
+ else if (chunk_is_token(next, CT_DC_MEMBER))
+ {
+ next = parse_double_colon(next);
+ }
+ else if ( chunk_is_paren_open(next)
+ && ( language_is_set(LANG_D)
+ || ( language_is_set(LANG_PAWN)
+ && chunk_is_enum(m_start))))
+ {
+ set_paren_parent(next, m_start->type);
+
+ if ( chunk_is_token(prev, CT_WORD)
+ && language_is_set(LANG_D))
+ {
+ mark_template(next);
+ }
+ next = chunk_skip_to_match(next, E_Scope::PREPROC);
+ }
+ else if ( chunk_is_token(next, CT_QUALIFIER)
+ && language_is_set(LANG_JAVA)
+ && std::strncmp(next->str.c_str(), "implements", 10) == 0)
+ {
+ mark_base_classes(next);
+ }
+ else if (chunk_is_token(next, CT_QUESTION))
+ {
+ record_question_operator(next);
+ }
+ else if ( chunk_is_token(next, CT_WHERE)
+ && !where_clause_detected())
+ {
+ mark_where_clause(next);
+ }
+ prev = next;
+
+ do
+ {
+ next = next->GetNextNcNnl();
+ } while ( next->IsNotNullChunk()
+ && next->level > m_start->level);
+ }
+ /**
+ * identify the type and/or variable(s)
+ */
+ analyze_identifiers();
+
+ /**
+ * identify and mark lvalues occurring outside the body definition
+ */
+ mark_extracorporeal_lvalues();
+
+ if ( prev != nullptr
+ && chunk_is_semicolon(prev)
+ && prev->level == m_start->level
+ && !prev->flags.test(PCF_IN_FOR))
+ {
+ set_chunk_parent(prev, m_start->type);
+ }
+} // EnumStructUnionParser::parse
+
+
+Chunk *EnumStructUnionParser::parse_angles(Chunk *angle_open)
+{
+ LOG_FUNC_ENTRY();
+
+ /**
+ * first check to see if the open angle occurs within an inheritance list
+ */
+ auto *pc = angle_open;
+
+ if (!is_within_inheritance_list(pc))
+ {
+ /**
+ * check to see if there's a matching closing angle bracket
+ */
+ auto *angle_close = chunk_skip_to_match(angle_open, E_Scope::PREPROC);
+
+ if (angle_close == nullptr)
+ {
+ // parse error
+ parse_error_detected(true);
+
+ // TODO: should this be just a warning or an error (with exit condition?)
+ LOG_FMT(LWARN,
+ "%s(%d): Unmatched '<' at orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ angle_open->orig_line,
+ angle_open->orig_col);
+ }
+ else
+ {
+ /**
+ * check to make sure that the template is the final chunk in a list
+ * of scope-resolution qualifications
+ */
+ auto *next = angle_close->GetNextNcNnl();
+
+ if (chunk_is_not_token(next, CT_DC_MEMBER))
+ {
+ set_template_start(angle_open);
+
+ /**
+ * we could be dealing with a template type; if so, the opening angle
+ * bracket should be preceded by a CT_WORD token and we should have
+ * found a closing angle bracket
+ */
+ auto *prev = angle_open->GetPrevNcNnlNi();
+
+ if (chunk_is_not_token(prev, CT_WORD))
+ {
+ // parse error
+ parse_error_detected(true);
+
+ // TODO: should this be just a warning or an error (with exit condition?)
+ LOG_FMT(LWARN,
+ "%s(%d): Identifier missing before '<' at orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ angle_open->orig_line,
+ angle_open->orig_col);
+ }
+ else
+ {
+ set_template_end(angle_close);
+ mark_template(angle_open);
+ }
+ }
+ /**
+ * update input argument to point to the closing angle bracket
+ */
+ pc = angle_close;
+ }
+ }
+ return(pc);
+} // EnumStructUnionParser::parse_angles
+
+
+Chunk *EnumStructUnionParser::parse_braces(Chunk *brace_open)
+{
+ LOG_FUNC_ENTRY();
+
+ /**
+ * check to see if there's a matching closing brace
+ */
+
+ auto *pc = brace_open;
+ auto *brace_close = chunk_skip_to_match(pc, E_Scope::PREPROC);
+
+ if (brace_close != nullptr)
+ {
+ /**
+ * we could be dealing with a variable definition preceded by
+ * the class/struct keyword. It's possible that the variable is
+ * assigned via direct-list initialization, hence the open brace
+ * is NOT part of a class/struct type definition.
+ */
+ auto *first_comma = get_first_top_level_comma();
+
+ if (chunk_is_after(pc, first_comma))
+ {
+ /**
+ * the open brace occurs after a top-level comma was encountered, which
+ * likely implies a direct-initialization or braced initializer list in
+ * the midst of a list of variable definitions
+ */
+
+ return(pc);
+ }
+ set_body_end(brace_close);
+ set_body_start(brace_open);
+
+ auto *enum_base_start = get_enum_base_start();
+ auto *inheritance_start = get_inheritance_start();
+ auto *prev = pc->GetPrevNcNnlNi();
+
+ /**
+ * check to see if the open brace was preceded by a closing paren;
+ * it could possibly be a function-like macro call preceding the
+ * open brace, but it's more likely that we're dealing with a
+ * signature associated with a function definition
+ */
+ bool is_potential_function_definition = false;
+
+ if ( ( language_is_set(LANG_C)
+ || language_is_set(LANG_CPP))
+ && chunk_is_paren_close(prev))
+ {
+ /**
+ * we may be dealing with a c/cpp function definition, where the 'struct'
+ * or 'class' keywords appear as the return type preceding a pair of braces
+ * and therefore may be associated with a function definition body
+ */
+ auto *paren_close = prev;
+
+ // skip in reverse to the matching open paren
+ auto *paren_open = chunk_skip_to_match_rev(paren_close);
+
+ if (paren_open != nullptr)
+ {
+ /**
+ * determine if there's an identifier preceding the open paren;
+ * if so, the identifier is very likely to be associated with
+ * a function definition
+ */
+ auto *type = m_start->GetNextNcNnl();
+ auto *identifier = paren_open->GetPrevNcNnlNi(E_Scope::PREPROC);
+ is_potential_function_definition = ( ( chunk_is_token(identifier, CT_FUNCTION)
+ || chunk_is_token(identifier, CT_FUNC_DEF)
+ || chunk_is_token(identifier, CT_WORD))
+ && type != identifier);
+ }
+ }
+
+ if ( language_is_set(LANG_D)
+ || language_is_set(LANG_PAWN)
+ || !chunk_is_paren_close(prev)
+ || is_potential_function_definition
+ || chunk_is_between(prev, enum_base_start, brace_open)
+ || chunk_is_between(prev, inheritance_start, brace_open))
+ {
+ mark_braces(brace_open);
+
+ /**
+ * D does not require a semicolon after an enum, but we add one to make
+ * other code happy.
+ */
+ if ( language_is_set(LANG_D)
+ && chunk_is_enum(m_start))
+ {
+ pawn_add_vsemi_after(brace_close); // Issue #2279
+ }
+ pc = brace_close;
+ }
+ else
+ {
+ // TODO: should this be just a warning or an error (with exit condition?)
+ LOG_FMT(LWARN,
+ "%s(%d): Parsing error precedes start of body '{' at orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ brace_open->orig_line,
+ brace_open->orig_col);
+
+ // parse error
+ parse_error_detected(true);
+ }
+ }
+ return(pc);
+} // EnumStructUnionParser::parse_braces
+
+
+void EnumStructUnionParser::parse_colon(Chunk *colon)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(m_start, CT_UNION))
+ {
+ /**
+ * unions do not implement inheritance
+ */
+
+ // TODO: should this be just a warning or an error (with exit condition?)
+ LOG_FMT(LWARN,
+ "%s(%d): Colon follows union declaration at orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ colon->orig_line,
+ colon->orig_col);
+
+ // parse error
+ parse_error_detected(true);
+ }
+ else if (is_within_conditional(colon))
+ {
+ mark_conditional_colon(colon);
+ }
+ else if (is_within_where_clause(colon))
+ {
+ mark_where_colon(colon);
+ }
+ else if (!inheritance_detected())
+ {
+ if (chunk_is_class_or_struct(m_start))
+ {
+ /**
+ * the colon likely specifies an inheritance list for a struct
+ * or class type
+ */
+
+ set_inheritance_start(colon);
+ mark_class_colon(colon);
+ }
+ else if (chunk_is_enum(m_start))
+ {
+ set_enum_base_start(colon);
+ mark_enum_integral_type(colon);
+ }
+ }
+} // EnumStructUnionParser::parse_colon
+
+
+Chunk *EnumStructUnionParser::parse_double_colon(Chunk *double_colon)
+{
+ LOG_FUNC_ENTRY();
+
+ auto *pc = double_colon;
+
+ if ( language_is_set(LANG_CPP)
+ && chunk_is_token(pc, CT_DC_MEMBER))
+ {
+ mark_nested_name_specifiers(pc);
+ pc = skip_scope_resolution_and_nested_name_specifiers(pc);
+ }
+ return(pc);
+} // EnumStructUnionParser::parse_double_colon
+
+
+bool EnumStructUnionParser::parse_error_detected() const
+{
+ LOG_FUNC_ENTRY();
+
+ return(m_parse_error);
+} // EnumStructUnionParser::parse_error_detected
+
+
+void EnumStructUnionParser::parse_error_detected(bool status)
+{
+ LOG_FUNC_ENTRY();
+
+ m_parse_error = status;
+} // EnumStructUnionParser::parse_error_detected
+
+
+void EnumStructUnionParser::record_question_operator(Chunk *question)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(question, CT_QUESTION))
+ {
+ std::size_t index = m_chunk_map[CT_QUESTION].size();
+
+ m_chunk_map[CT_QUESTION][index] = question;
+ }
+} // EnumStructUnionParser::record_question_operator
+
+
+void EnumStructUnionParser::record_top_level_comma(Chunk *comma)
+{
+ if ( comma != nullptr
+ && comma->level == m_start->level
+ && !is_within_conditional(comma)
+ && !is_within_inheritance_list(comma))
+ {
+ std::size_t index = m_chunk_map[CT_COMMA].size();
+
+ m_chunk_map[CT_COMMA][index] = comma;
+ }
+} // EnumStructUnionParser::record_top_level_comma
+
+
+Chunk *EnumStructUnionParser::refine_end_chunk(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( ( language_is_set(LANG_C)
+ || language_is_set(LANG_CPP))
+ && chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ /**
+ * if dealing with C/C++, one or more trailing variable definitions may
+ * follow the closing brace; a semi-colon should've been good enough to
+ * indicate the terminating condition, however some of the classes defined
+ * in the input tests cases for Continuous Integration DO NOT correctly
+ * terminate classes/struct with a semicolon (which is compilation error).
+ * As a consequence, more checks must be performed to determine where
+ * the terminating chunk is located. For instance, see operator.cpp and
+ * enum_comma.h for examples of offenders
+ */
+ auto *next = pc->GetNextNcNnl();
+
+ while (true)
+ {
+ if (chunk_is_semicolon(next))
+ {
+ pc = next;
+
+ break;
+ }
+ else
+ {
+ /**
+ * if we're sitting at a comma, skip it
+ */
+ if (chunk_is_token(next, CT_COMMA))
+ {
+ next = next->GetNextNcNnl();
+ }
+ auto match = match_variable(next, m_start->level);
+ auto *start = std::get<0>(match);
+ auto *identifier = std::get<1>(match);
+ auto *end = std::get<2>(match);
+
+ if ( end == nullptr
+ || identifier == nullptr
+ || start == nullptr)
+ {
+ break;
+ }
+ else
+ {
+ pc = end->GetNextNcNnl();
+
+ /**
+ * skip any right-hand side assignments
+ */
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ pc = skip_to_expression_end(pc);
+ }
+ next = pc;
+ }
+ }
+ }
+ }
+ return(pc);
+} // EnumStructUnionParser::refine_end_chunk
+
+
+void EnumStructUnionParser::set_body_end(Chunk *body_end)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(body_end, CT_BRACE_CLOSE))
+ {
+ m_chunk_map[CT_BRACE_CLOSE][0] = body_end;
+ }
+} // EnumStructUnionParser::set_body_end
+
+
+void EnumStructUnionParser::set_body_start(Chunk *body_start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(body_start, CT_BRACE_OPEN))
+ {
+ m_chunk_map[CT_BRACE_OPEN][0] = body_start;
+ }
+} // EnumStructUnionParser::set_body_start
+
+
+void EnumStructUnionParser::set_enum_base_start(Chunk *enum_base_start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_colon(enum_base_start))
+ {
+ m_chunk_map[CT_BIT_COLON][0] = enum_base_start;
+ }
+} // EnumStructUnionParser::set_enum_base_start
+
+
+void EnumStructUnionParser::set_inheritance_start(Chunk *inheritance_start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_colon(inheritance_start))
+ {
+ m_chunk_map[CT_COLON][0] = inheritance_start;
+ }
+} // EnumStructUnionParser::set_inheritance_start
+
+
+void EnumStructUnionParser::set_template_end(Chunk *template_end)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(template_end, CT_ANGLE_CLOSE))
+ {
+ m_chunk_map[CT_ANGLE_CLOSE][0] = template_end;
+ }
+} // EnumStructUnionParser::set_template_end
+
+
+void EnumStructUnionParser::set_template_start(Chunk *template_start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(template_start, CT_ANGLE_OPEN))
+ {
+ m_chunk_map[CT_ANGLE_OPEN][0] = template_start;
+ }
+} // EnumStructUnionParser::set_template_start
+
+
+void EnumStructUnionParser::set_where_end(Chunk *where_end)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(where_end, CT_BRACE_OPEN))
+ {
+ m_chunk_map[CT_WHERE][0] = where_end;
+ }
+} // EnumStructUnionParser::set_where_end
+
+
+void EnumStructUnionParser::set_where_start(Chunk *where_start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(where_start, CT_WHERE))
+ {
+ m_chunk_map[CT_WHERE][0] = where_start;
+ }
+} // EnumStructUnionParser::set_where_start
+
+
+bool EnumStructUnionParser::template_detected() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto *template_end = get_template_end();
+ auto *template_start = get_template_start();
+
+ return( template_end != nullptr
+ && template_start != nullptr);
+} // EnumStructUnionParser::template_detected
+
+
+Chunk *EnumStructUnionParser::try_find_end_chunk(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ do
+ {
+ /**
+ * clear some previously marked token types, some of which have likely
+ * been erroneously marked up to this point; a good example of this
+ * arises when macro variables and/or macro function calls follow the
+ * class/enum/struct/union keyword and precede the actual type name
+ */
+ if ( chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_WORD))
+ {
+ set_chunk_type(pc, CT_WORD);
+ set_chunk_parent(pc, CT_NONE);
+ }
+
+ do
+ {
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ } while ( pc->IsNotNullChunk()
+ && pc->level > m_start->level);
+ } while (!is_potential_end_chunk(pc));
+
+ /**
+ * perform a second pass for c++ that
+ */
+ pc = refine_end_chunk(pc);
+
+ return(pc);
+} // EnumStructUnionParser::try_find_end_chunk
+
+
+void EnumStructUnionParser::try_post_identify_macro_calls()
+{
+ LOG_FUNC_ENTRY();
+
+ if ( language_is_set(LANG_CPP)
+ && type_identified())
+ {
+ /**
+ * for all chunks at class/enum/struct/union level, identify function-like
+ * macro calls and mark them as CT_MACRO_FUNC_CALL. The reason for doing
+ * so is to avoid mis-interpretation by code executed at a later time
+ */
+
+ auto *body_start = get_body_start();
+ auto *inheritance_start = get_inheritance_start();
+ Chunk *pc = m_start;
+ Chunk *prev = nullptr;
+
+ do
+ {
+ if ( !chunk_is_between(prev, inheritance_start, body_start)
+ && ( chunk_is_token(prev, CT_WORD)
+ || chunk_is_token(prev, CT_FUNCTION)
+ || chunk_is_token(prev, CT_FUNC_DEF))
+ && !prev->flags.test_any(PCF_VAR_DEF | PCF_VAR_1ST | PCF_VAR_INLINE)
+ && prev->level == m_start->level)
+ {
+ if (chunk_is_paren_open(pc))
+ {
+ auto *paren_open = pc;
+ auto *paren_close = chunk_skip_to_match(paren_open, E_Scope::PREPROC);
+
+ if (paren_close != nullptr)
+ {
+ set_chunk_type(paren_open, CT_FPAREN_OPEN);
+ set_chunk_parent(paren_open, CT_MACRO_FUNC_CALL);
+ set_chunk_type(paren_close, CT_FPAREN_CLOSE);
+ set_chunk_parent(paren_close, CT_MACRO_FUNC_CALL);
+ set_chunk_type(prev, CT_MACRO_FUNC_CALL);
+ }
+ }
+ }
+ prev = pc;
+ pc = prev->GetNextNcNnl();
+ } while (chunk_is_between(pc, m_start, m_end));
+ }
+} // EnumStructUnionParser::try_post_identify_macro_calls
+
+
+void EnumStructUnionParser::try_post_identify_type()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *body_end = get_body_end();
+
+ if ( !type_identified()
+ && body_end == nullptr)
+ {
+ /**
+ * a type wasn't identified and no closing brace is present; we're
+ * likely not dealing with an anonymous enum/class/struct
+ */
+
+ /**
+ * a type has yet to be identified, so search for the last word
+ * that hasn't been marked as a variable
+ */
+ Chunk *type = nullptr;
+ Chunk *pc = m_start;
+
+ do
+ {
+ /**
+ * in case it's a qualified identifier, skip scope-resolution and
+ * nested name specifiers and return just the qualified identifier name
+ */
+ pc = skip_scope_resolution_and_nested_name_specifiers(pc);
+
+ if (pc->flags.test_any(PCF_VAR_DEF | PCF_VAR_1ST | PCF_VAR_INLINE))
+ {
+ break;
+ }
+ else if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ type = skip_template_prev(pc);
+ }
+ pc = pc->GetNextNcNnl();
+ } while (chunk_is_between(pc, m_start, m_end));
+
+ if (type != nullptr)
+ {
+ mark_type(type);
+ }
+ }
+} // EnumStructUnionParser::try_post_identify_type
+
+
+bool EnumStructUnionParser::try_pre_identify_type()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = get_body_start();
+
+ if ( language_is_set(LANG_PAWN)
+ && chunk_is_enum(m_start))
+ {
+ set_paren_parent(pc, m_start->type);
+ }
+ else if (template_detected())
+ {
+ pc = get_template_start();
+ }
+ else if (enum_base_detected())
+ {
+ pc = get_enum_base_start();
+ }
+ else if (inheritance_detected())
+ {
+ pc = get_inheritance_start();
+
+ if (chunk_is_token(m_start, CT_UNION))
+ {
+ /**
+ * unions do not implement inheritance
+ */
+
+ // TODO: should this be just a warning or an error (with exit condition?)
+ LOG_FMT(LWARN,
+ "%s(%d): Bad union declaration detected at orig_line is %zu, orig_col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ m_start->orig_line,
+ m_start->orig_col);
+
+ parse_error_detected(true);
+
+ return(false);
+ }
+ }
+
+ if (pc == nullptr)
+ {
+ Chunk *next = m_start->GetNextNcNnl();
+
+ /**
+ * in case it's a qualified identifier, skip scope-resolution and
+ * nested name specifiers and return just the qualified identifier name
+ */
+ next = skip_scope_resolution_and_nested_name_specifiers(next);
+
+ Chunk *next_next = next->GetNextNcNnl();
+
+ /**
+ * in case it's a qualified identifier, skip scope-resolution and
+ * nested name specifiers and return just the qualified identifier name
+ */
+ next_next = skip_scope_resolution_and_nested_name_specifiers(next_next);
+
+ /**
+ * if there is one word between the start and end chunks, then we've likely
+ * identified the type; if there are two words, then the first is likely a
+ * type and the second is an instantiation thereof; however, it is possible
+ * that the first word is actually a reference to a macro definition, in which
+ * the second word would be the type
+ */
+ if (next_next == m_end)
+ {
+ pc = next_next;
+ }
+ else if ( next->IsNotNullChunk()
+ && chunk_is_token(next, CT_WORD)
+ && chunk_is_token(next_next, CT_WORD)
+ && m_end->GetPrevNcNnlNi() == next_next)
+ {
+ /**
+ * check to see if we've got a macro reference preceding the last word chunk;
+ * this won't work in all cases, because a macro may be defined in another header
+ * file, but this is an attempt to increase the chances of identifying the correct
+ * chunk as the type
+ */
+ if ( chunk_is_macro_reference(next)
+ || get_chunk_parent_type(m_start) == CT_TEMPLATE)
+ {
+ pc = m_end;
+ }
+ else
+ {
+ pc = next_next;
+ }
+ }
+ else
+ {
+ /**
+ * search for some common patterns that may indicate a type
+ */
+ Chunk *prev = m_start;
+
+ while ( chunk_is_between(next, m_start, m_end)
+ && ( ( chunk_is_not_token(next, CT_ASSIGN)
+ && chunk_is_not_token(next, CT_COMMA))
+ || next->level != m_start->level)
+ && !chunk_is_semicolon(next))
+ {
+ prev = next;
+ next = next->GetNextNcNnl();
+
+ /**
+ * in case it's a qualified identifier, skip scope-resolution and
+ * nested name specifiers and return just the qualified identifier name
+ */
+ next = skip_scope_resolution_and_nested_name_specifiers(next);
+
+ /**
+ * skip array brackets, as the type cannot be located within;
+ * also skip a set of parens - there may be a type embedded within,
+ * but it's not the type with which we're concerned
+ */
+ if ( next->IsSquareBracket() // Issue #3601
+ || chunk_is_paren_open(next))
+ {
+ prev = chunk_skip_to_match(next, E_Scope::PREPROC);
+ next = prev->GetNextNcNnl(E_Scope::PREPROC);
+ }
+
+ if ( chunk_is_token(prev, CT_WORD)
+ && chunk_is_pointer_or_reference(next))
+ {
+ pc = next;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ /**
+ * the chunk preceding the previously selected chunk should indicate the type
+ */
+
+ pc = pc->GetPrevNcNnlNi(E_Scope::PREPROC);
+
+ if ( chunk_is_token(pc, CT_QUALIFIER)
+ && std::strncmp(pc->str.c_str(), "final", 5) == 0)
+ {
+ pc = pc->GetPrevNcNnlNi(E_Scope::PREPROC);
+ }
+
+ if ( language_is_set(LANG_D)
+ && chunk_is_paren_close(pc))
+ {
+ pc = chunk_skip_to_match_rev(pc);
+ pc = pc->GetPrevNcNnlNi();
+ }
+
+ if (chunk_is_token(pc, CT_WORD))
+ {
+ mark_type(pc);
+
+ return(true);
+ }
+ }
+ return(false);
+} // EnumStructUnionParser::try_pre_identify_type
+
+
+bool EnumStructUnionParser::type_identified() const
+{
+ LOG_FUNC_ENTRY();
+
+ return(m_type != nullptr);
+} // EnumStructUnionParser::type_identified
+
+
+/**
+ * Returns true if a where clause was detected during parsing
+ */
+bool EnumStructUnionParser::where_clause_detected() const
+{
+ LOG_FUNC_ENTRY();
+
+ auto *where_end = get_where_end();
+ auto *where_start = get_where_start();
+
+ return( where_end != nullptr
+ && where_start != nullptr);
+} // EnumStructUnionParser::where_clause_detected
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.h
new file mode 100644
index 00000000..422662da
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/EnumStructUnionParser.h
@@ -0,0 +1,497 @@
+/**
+ * @file combine_fix_mark_enum_struct_union.h
+ *
+ * @author
+ * @license GPL v2+
+ * extract from combine_fix_mark.h
+ */
+
+#ifndef ENUM_STRUCT_UNION_PARSER_H_INCLUDED
+#define ENUM_STRUCT_UNION_PARSER_H_INCLUDED
+
+#include "pcf_flags.h"
+#include "token_enum.h"
+#include "uncrustify_types.h"
+#include <map>
+
+
+/**
+ * Class EnumStructUnionParser : This class facilitates the parsing and interpretation
+ * of ALL instances of the class, enum, union, and
+ * struct keywords, including user-defined types with
+ * a body {} and any trailing inline variable declarations
+ * that may follow the definition (as permitted by
+ * the coding language in question). The class also
+ * interprets variable declarations preceded by one
+ * of those keywords, as well as any C/C++ forward
+ * declarations
+ */
+class EnumStructUnionParser
+{
+public:
+ /**
+ * Constructor
+ */
+ EnumStructUnionParser();
+
+
+ /**
+ * Destructor
+ */
+ ~EnumStructUnionParser();
+
+
+private:
+ /**
+ * Analyzes all identifiers (marked as CT_WORD) between the starting and
+ * ending chunks and changes CT_WORD to one of CT_TYPE, CT_MACRO_FUNC_CALL,
+ * etc. and sets flags (PCF_VAR_1ST, PCF_VAR_1ST_DEF, PCF_VAR_INLINE, etc.)
+ * for variable identifiers accordingly. Flags C++ forward declarations as
+ * PCF_INCOMPLETE
+ */
+ void analyze_identifiers();
+
+
+ /**
+ * Returns true if a pair of braces were both detected AND determined to be
+ * part of a class/enum/struct/union body
+ */
+ bool body_detected() const;
+
+
+ /**
+ * Returns true if comma-separated values were detected during parsing
+ */
+ bool comma_separated_values_detected() const;
+
+
+ /**
+ * Returns true if an enumerated integral type was detected during parsing
+ */
+ bool enum_base_detected() const;
+
+
+ /**
+ * Returns the end chunk of a class/enum/struct/union body, if detected
+ * during parsing
+ */
+ Chunk *get_body_end() const;
+
+
+ /**
+ * Returns the starting chunk of a class/enum/struct/union body, if detected
+ * during parsing
+ */
+ Chunk *get_body_start() const;
+
+
+ /**
+ * Returns the starting chunk associated with an enumerated type's base
+ * specifier statement, if detected during parsing
+ */
+ Chunk *get_enum_base_start() const;
+
+
+ /**
+ * Returns the first comma encountered at the level of the starting chunk,
+ * if detected during parsing
+ */
+ Chunk *get_first_top_level_comma() const;
+
+
+ /**
+ * Returns the ending chunk associated with an class/struct inheritance
+ * list, if detected during parsing
+ */
+ Chunk *get_inheritance_end() const;
+
+
+ /**
+ * Returns the starting chunk associated with an class/struct inheritance
+ * list, if detected during parsing
+ */
+ Chunk *get_inheritance_start() const;
+
+
+ /**
+ * Returns a numerically-indexed map of all question operators encountered
+ * during parsing
+ */
+ std::map<std::size_t, Chunk *> get_question_operators() const;
+
+
+ /**
+ * Returns the end chunk associated with a template parameter list, if
+ * detected during parsing
+ */
+ Chunk *get_template_end() const;
+
+
+ /**
+ * Return the starting chunk associated with a template parameter list, if
+ * detected during parsing
+ */
+ Chunk *get_template_start() const;
+
+
+ /**
+ * Returns a numerically-indexed map of all top-level commas encountered
+ * during parsing
+ */
+ std::map<std::size_t, Chunk *> get_top_level_commas() const;
+
+
+ /**
+ * Return the starting chunk associated with a where clause, if
+ * detected during parsing
+ */
+ Chunk *get_where_end() const;
+
+
+ /**
+ * Return the starting chunk associated with a where clause, if
+ * detected during parsing
+ */
+ Chunk *get_where_start() const;
+
+
+ /**
+ * Returns true if an inheritance list associated with a class or struct was
+ * discovered during parsing
+ */
+ bool inheritance_detected() const;
+
+
+public:
+ /**
+ * Performs object initialization prior to parsing
+ */
+ void initialize(Chunk *pc);
+
+
+private:
+ /**
+ * Returns true if the chunk under test represents a potential end chunk past
+ * which further parsing is not likely warranted
+ */
+ bool is_potential_end_chunk(Chunk *pc) const;
+
+
+ /**
+ * Returns true if the chunk under test is deemed to be located within a
+ * conditional/ternary statement
+ */
+ bool is_within_conditional(Chunk *pc) const;
+
+
+ /**
+ * Returns true if the chunk under test is deemed to be located within an
+ * inheritance list
+ */
+ bool is_within_inheritance_list(Chunk *pc) const;
+
+
+ /**
+ * Returns true if the chunk under test is deemed to be located within a
+ * where clause
+ */
+ bool is_within_where_clause(Chunk *pc) const;
+
+
+ /**
+ * Marks all base classes that appear as part of an inheritance list
+ */
+ void mark_base_classes(Chunk *pc);
+
+
+ /**
+ * Marks pairs of braces associated with the body of a class/enum/struct/union,
+ * and additionally calls a separate routine to mark any base classes for that
+ * may precede the opening brace
+ */
+ void mark_braces(Chunk *start);
+
+
+ /**
+ * Marks the beginning chunk of an inheritance list
+ */
+ void mark_class_colon(Chunk *colon);
+
+
+ /**
+ * Mark a colon as a conditional
+ */
+ void mark_conditional_colon(Chunk *colon);
+
+
+ /**
+ * Mark any struct/class constructor declarations/definitions
+ */
+ void mark_constructors();
+
+
+ /**
+ * Marks the beginning chunk of an enumerated integral type specification
+ */
+ void mark_enum_integral_type(Chunk *colon);
+
+
+ /**
+ * Scan chunks outside the definition body and mark lvalues accordingly
+ */
+ void mark_extracorporeal_lvalues();
+
+
+ /**
+ * Mark nested name specifiers preceding qualified identifiers
+ */
+ void mark_nested_name_specifiers(Chunk *pc);
+
+
+ /**
+ * Marks pointer operators preceding a variable identifier
+ */
+ void mark_pointer_types(Chunk *pc);
+
+
+ /**
+ * Marks the beginning and ending chunks associated with a template
+ * (templates may appear after the identifier type name as part of a class
+ * specialization)
+ */
+ void mark_template(Chunk *start) const;
+
+
+ /**
+ * Marks the arguments within a template argument list bounded by the
+ * starting and ending chunks
+ */
+ void mark_template_args(Chunk *start, Chunk *end) const;
+
+
+ /**
+ * Marks the type identifier associated with the class/enum/struct/union,
+ * if not anonymously defined
+ */
+ void mark_type(Chunk *pc);
+
+
+ /**
+ * Marks all variable identifiers associated with the class/enum/struct/union
+ */
+ void mark_variable(Chunk *variable, pcf_flags_t flags);
+
+
+ /**
+ * Marks all chunks belonging to a c# where clause
+ */
+ void mark_where_clause(Chunk *where);
+
+
+ /**
+ * Marks the beginning of a where clause
+ */
+ void mark_where_colon(Chunk *colon);
+
+
+public:
+ /**
+ * Parses the class/enum/struct/union and all associated chunks
+ */
+ void parse(Chunk *pc);
+
+
+private:
+ /**
+ * Parses closing and opening angle brackets
+ */
+ Chunk *parse_angles(Chunk *angle_open);
+
+
+ /**
+ * Parses closing and opening braces
+ */
+ Chunk *parse_braces(Chunk *brace_open);
+
+
+ /**
+ * Parses a single colon, which may precede an inheritance list or
+ * enumerated integral type specification
+ */
+ void parse_colon(Chunk *colon);
+
+
+ /**
+ * Parses a double colon, which may indicate a scope resolution chain
+ */
+ Chunk *parse_double_colon(Chunk *double_colon);
+
+
+ /**
+ * Returns the parsing error status
+ */
+ bool parse_error_detected() const;
+
+
+ /**
+ * Sets the parsing error status
+ */
+ void parse_error_detected(bool status);
+
+
+ /**
+ * Records all question operators encountered during parsing
+ */
+ void record_question_operator(Chunk *question);
+
+
+ /**
+ * Records a comma chunk given one the following conditions are satisfied:
+ * 1) it is encountered at the level of the starting chunk
+ * 2) it is not part of a right-hand side assignment
+ * 3) it is not part of an inheritance list
+ * 4) it is not part of a conditional/ternary expression
+ */
+ void record_top_level_comma(Chunk *comma);
+
+
+ /**
+ * Adjusts the end chunk returned by the try_find_end_chunk() function
+ * for any potential trailing inline variable declarations that may follow
+ * the body of a class/enum/struct/union definition
+ */
+ Chunk *refine_end_chunk(Chunk *pc);
+
+
+ /**
+ * Sets the chunk associated with the end of a class/enum/struct/union
+ * body
+ */
+ void set_body_end(Chunk *body_end);
+
+
+ /**
+ * Sets the chunk associated with the start of a class/enum/struct/union
+ * body
+ */
+ void set_body_start(Chunk *body_start);
+
+
+ /**
+ * Sets the chunk associated with the start of an enumerated integral
+ * base type specification
+ */
+ void set_enum_base_start(Chunk *enum_base_start);
+
+
+ /**
+ * Sets the chunk associated with the start of an inheritance list
+ */
+ void set_inheritance_start(Chunk *inheritance_start);
+
+
+ /**
+ * Sets the chunk associated with the end of a template
+ */
+ void set_template_end(Chunk *template_end);
+
+
+ /**
+ * Sets the chunk associated with the start of a template
+ */
+ void set_template_start(Chunk *template_start);
+
+
+ /**
+ * Return the ending chunk associated with a where clause, if
+ * detected during parsing
+ */
+ void set_where_end(Chunk *where_end);
+
+
+ /**
+ * Return the starting chunk associated with a where clause, if
+ * detected during parsing
+ */
+ void set_where_start(Chunk *where_start);
+
+
+ /**
+ * Returns true if a template was detected during parsing
+ */
+ bool template_detected() const;
+
+
+ /**
+ * Attempts to find the last chunk associated with the class/enum/struct/union
+ */
+ Chunk *try_find_end_chunk(Chunk *pc);
+
+
+ /**
+ * Attempts to identify any function-like macro calls which may precede the
+ * actual type identifier
+ */
+ void try_post_identify_macro_calls();
+
+
+ /**
+ * Attempts to find the identifier type name (if not anonymously-defined) post
+ * variable identifier interpretation
+ */
+ void try_post_identify_type();
+
+
+ /**
+ * Attempts to find the identifier type name prior to variable identifier
+ * interpretation
+ */
+ bool try_pre_identify_type();
+
+
+ /**
+ * Returns true if a corresponding type was identified for the class/enum/struct/union
+ */
+ bool type_identified() const;
+
+
+ /**
+ * Returns true if a where clause was detected during parsing
+ */
+ bool where_clause_detected() const;
+
+
+ /**
+ * Map of token-type, chunk pairs
+ */
+ std::map<E_Token, std::map<std::size_t, Chunk *> > m_chunk_map;
+
+
+ /**
+ * Indicates the last chunk associated with the class/enum/struct/union keyword
+ */
+ Chunk *m_end;
+
+
+ /**
+ * Indicates whether or not a parse error has occurred
+ */
+ bool m_parse_error;
+
+
+ /**
+ * Stores a pointer to the class/enum/struct/union keyword chunk with which the
+ * parse() routine was invoked
+ */
+ Chunk *m_start;
+
+
+ /**
+ * Stores a pointer to the type identifier associated with the class/enum/struct/union,
+ * if not anonymously defined
+ */
+ Chunk *m_type;
+};
+
+
+#endif
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ListManager.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ListManager.h
new file mode 100644
index 00000000..f9e928c8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ListManager.h
@@ -0,0 +1,260 @@
+/**
+ * @file ListManager.h
+ * Template class that manages items in a double-linked list.
+ * If C++ could do it, this would just be a class that worked on an interface.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef LIST_MANAGER_H_INCLUDED
+#define LIST_MANAGER_H_INCLUDED
+
+/*
+ * TODO: why do we provide this template class? can't we use
+ * a double linked list std::deque from the standard library ?
+ */
+/**
+ * A simple list manager for a double-linked list.
+ * Class T must define 'next' and 'prev', which must be pointers to type T.
+ */
+template<class T>
+class ListManager
+{
+protected:
+ T *first; //! pointer to the head of list
+ T *last; //! pointer to tail of list
+
+private:
+ // Hide copy constructor
+ ListManager(const ListManager &ref)
+ {
+ first = nullptr;
+ last = nullptr;
+ }
+
+public:
+ ListManager()
+ {
+ first = nullptr;
+ last = nullptr;
+ }
+
+
+ /**
+ * @brief return the first element of the linked list
+ *
+ * @return pointer to first element or nullptr if list is empty
+ */
+ T *GetHead() const
+ {
+ return(first);
+ }
+
+
+ /**
+ * @brief return the last element of the linked list
+ *
+ * @return pointer to last element or nullptr if list is empty
+ */
+ T *GetTail() const
+ {
+ return(last);
+ }
+
+
+ /**
+ * @brief return the next element of the linked list
+ *
+ * @param[in] ref pointer to current list element
+ *
+ * @return pointer to next element or nullptr if no next element exists
+ */
+ T *GetNext(const T *ref) const
+ {
+ return((ref != nullptr) ? ref->next : nullptr);
+ }
+
+
+ /**
+ * @brief return the previous element of the linked list
+ *
+ * @param[in] ref pointer to current list element
+ *
+ * @return pointer to previous element or nullptr if no previous element exists
+ */
+ T *GetPrev(const T *ref) const
+ {
+ return((ref != nullptr) ? ref->prev : nullptr);
+ }
+
+
+ /**
+ * @brief remove an element from a linked list
+ *
+ * @param[in] obj list element to remove
+ */
+ void Pop(T *obj)
+ {
+ if (obj != nullptr)
+ {
+ if (first == obj)
+ {
+ first = obj->next;
+ }
+
+ if (last == obj)
+ {
+ last = obj->prev;
+ }
+
+ if (obj->next != nullptr)
+ {
+ obj->next->prev = obj->prev;
+ }
+
+ if (obj->prev != nullptr)
+ {
+ obj->prev->next = obj->next;
+ }
+ obj->next = nullptr;
+ obj->prev = nullptr;
+ }
+ }
+
+
+ //! swap two elements of a list
+ void Swap(T *obj1, T *obj2)
+ {
+ if ( obj1 != nullptr
+ && obj2 != nullptr)
+ {
+ if (obj1->prev == obj2)
+ {
+ Pop(obj1);
+ AddBefore(obj1, obj2);
+ }
+ else if (obj2->prev == obj1)
+ {
+ Pop(obj2);
+ AddBefore(obj2, obj1);
+ }
+ else
+ {
+ T *prev1 = obj1->prev;
+ Pop(obj1);
+
+ T *prev2 = obj2->prev;
+ Pop(obj2);
+
+ AddAfter(obj1, prev2);
+ AddAfter(obj2, prev1);
+ }
+ }
+ }
+
+
+ /**
+ * @brief add a new element after a reference position in a list
+ *
+ * @param obj new element to add to list
+ * @param ref chunk after which to insert new object
+ */
+ void AddAfter(T *obj, T *ref)
+ {
+ if ( obj != nullptr
+ && ref != nullptr)
+ {
+ Pop(obj); // TODO: is this necessary?
+ obj->next = ref->next;
+ obj->prev = ref;
+
+ if (ref->next != nullptr)
+ {
+ ref->next->prev = obj;
+ }
+ else
+ {
+ last = obj;
+ }
+ ref->next = obj;
+ }
+ }
+
+
+ /**
+ * @brief add a new element before a reference position in a list
+ *
+ * @param obj new element to add to list
+ * @param ref chunk before to insert new object
+ */
+ void AddBefore(T *obj, T *ref)
+ {
+ if ( obj != nullptr
+ && ref != nullptr)
+ {
+ Pop(obj);
+ obj->next = ref;
+ obj->prev = ref->prev;
+
+ if (ref->prev != nullptr)
+ {
+ ref->prev->next = obj;
+ }
+ else
+ {
+ first = obj;
+ }
+ ref->prev = obj;
+ }
+ }
+
+
+ /**
+ * @brief add a new element to the tail of a lis
+ *
+ * @param obj new element to add to the list
+ */
+ void AddTail(T *obj)
+ {
+ obj->next = nullptr;
+ obj->prev = last;
+
+ if (last == nullptr)
+ {
+ last = obj;
+ first = obj;
+ }
+ else
+ {
+ last->next = obj;
+ }
+ last = obj;
+ }
+
+
+ /**
+ * @brief add a new element to the head of a list
+ *
+ * @param obj new element to add to the list
+ */
+ void AddHead(T *obj)
+ {
+ obj->next = first;
+ obj->prev = nullptr;
+
+ if (first == nullptr)
+ {
+ last = obj;
+ first = obj;
+ }
+ else
+ {
+ first->prev = obj;
+ }
+ first = obj;
+ }
+};
+
+
+#endif /* LIST_MANAGER_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.cpp
new file mode 100644
index 00000000..dc742741
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.cpp
@@ -0,0 +1,347 @@
+/**
+ * @file ParseFrame.cpp
+ *
+ * Container that holds data needed for indenting and brace parsing
+ *
+ * @author Daniel Chumak
+ * @license GPL v2+
+ */
+
+#include "ParseFrame.h"
+
+#include "chunk.h"
+#include "uncrustify.h"
+
+#include <stdexcept> // to get std::logic_error
+
+
+using std::string;
+using std::to_string;
+using std::logic_error;
+using std::invalid_argument;
+
+using ContainerType = paren_stack_entry_t;
+using Container = std::vector<ContainerType>;
+
+
+//! amount of elements for which memory is going to be pre-initialized
+static constexpr const int CONTAINER_INIT_SIZE = 16;
+
+
+static ContainerType genDummy()
+{
+ ContainerType tmp_dummy{};
+
+ tmp_dummy.indent = 1;
+ tmp_dummy.indent_tmp = 1;
+ tmp_dummy.indent_tab = 1;
+ tmp_dummy.type = CT_EOF;
+
+ return(tmp_dummy);
+}
+
+
+void ParseFrame::clear()
+{
+ last_poped = genDummy();
+
+ pse = Container{};
+ pse.reserve(CONTAINER_INIT_SIZE);
+ pse.push_back(genDummy());
+
+ ref_no = 0;
+ level = 0;
+ brace_level = 0;
+ pp_level = 0;
+ sparen_count = 0;
+ paren_count = 0;
+ in_ifdef = E_Token::CT_NONE;
+ stmt_count = 0;
+ expr_count = 0;
+}
+
+
+ParseFrame::ParseFrame()
+{
+ ParseFrame::clear();
+}
+
+
+bool ParseFrame::empty() const
+{
+ // always at least one (dummy) element inside pse guaranteed
+ return(false);
+// return(pse.empty());
+}
+
+
+ContainerType &ParseFrame::at(size_t idx)
+{
+ return(pse.at(idx));
+}
+
+
+const ContainerType &ParseFrame::at(size_t idx) const
+{
+ return(pse.at(idx));
+}
+
+
+ContainerType &ParseFrame::prev(size_t idx)
+{
+ LOG_FUNC_ENTRY();
+
+ if (idx == 0)
+ {
+ throw invalid_argument(string(__FILE__) + ":" + to_string(__LINE__)
+ + " idx can't be zero");
+ }
+
+ if (idx >= pse.size())
+ {
+ LOG_FMT(LINDPSE, "%s(%d): idx is %zu, size is %zu\n",
+ __func__, __LINE__, idx, pse.size());
+ throw invalid_argument(string(__FILE__) + ":" + to_string(__LINE__)
+ + " idx can't be >= size()");
+ }
+ return(*std::prev(std::end(pse), idx + 1));
+}
+
+
+const ContainerType &ParseFrame::prev(size_t idx) const
+{
+ LOG_FUNC_ENTRY();
+
+ if ( idx == 0
+ || idx >= pse.size())
+ {
+ throw invalid_argument(string(__FILE__) + ":" + to_string(__LINE__)
+ + " idx can't be zero or >= size()");
+ }
+ return(*std::prev(std::end(pse), idx + 1));
+}
+
+
+ContainerType &ParseFrame::top()
+{
+ // always at least one (dummy) element inside pse guaranteed
+// if (pse.empty())
+// {
+// throw logic_error(string(__FILE__) + ":" + to_string(__LINE__)
+// + " called top on an empty stack");
+// }
+ return(*std::prev(std::end(pse)));
+}
+
+
+const ContainerType &ParseFrame::top() const
+{
+ // always at least one (dummy) element inside pse guaranteed
+// if (pse.empty())
+// {
+// throw logic_error(string(__FILE__) + ":" + to_string(__LINE__)
+// + " called top on an empty stack");
+// }
+ return(*std::prev(std::end(pse)));
+}
+
+
+void ParseFrame::push(std::nullptr_t, brace_stage_e stage)
+{
+ static Chunk dummy;
+
+ push(&dummy, __func__, __LINE__, stage);
+ top().pc = nullptr;
+}
+
+
+void ParseFrame::push(Chunk *pc, const char *func, int line, brace_stage_e stage)
+{
+ LOG_FUNC_ENTRY();
+
+ ContainerType new_entry = {};
+
+ new_entry.type = pc->type;
+ new_entry.level = pc->level;
+ new_entry.open_line = pc->orig_line;
+ new_entry.open_colu = pc->orig_col;
+ new_entry.pc = pc;
+
+ new_entry.indent_tab = top().indent_tab;
+ new_entry.indent_cont = top().indent_cont;
+ new_entry.stage = stage;
+
+ new_entry.in_preproc = pc->flags.test(PCF_IN_PREPROC);
+ new_entry.non_vardef = false;
+ new_entry.ip = top().ip;
+ new_entry.pop_pc = nullptr;
+
+ pse.push_back(new_entry);
+
+// uncomment the line below to get the address of the pse
+// #define DEBUG_PUSH_POP
+#ifdef DEBUG_PUSH_POP
+ LOG_FMT(LINDPSE, "ParseFrame::push(%s:%d) Add is %4zu: orig_line is %4zu, orig_col is %4zu, type is %12s, "
+ "brace_level is %2zu, level is %2zu, pse_tos: %2zu -> %2zu\n",
+ func, line, (size_t)this, pc->orig_line, pc->orig_col,
+ get_token_name(pc->type), pc->brace_level, pc->level,
+ (pse.size() - 2), (pse.size() - 1));
+#else /* DEBUG_PUSH_POP */
+ LOG_FMT(LINDPSE, "ParseFrame::push(%s:%d): orig_line is %4zu, orig_col is %4zu, type is %12s, "
+ "brace_level is %2zu, level is %2zu, pse_tos: %2zu -> %2zu\n",
+ func, line, pc->orig_line, pc->orig_col,
+ get_token_name(pc->type), pc->brace_level, pc->level,
+ (pse.size() - 2), (pse.size() - 1));
+#endif /* DEBUG_PUSH_POP */
+}
+
+
+void ParseFrame::pop(const char *func, int line, Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ // always at least one (dummy) element inside pse guaranteed
+// if (pse.empty())
+// {
+// throw logic_error(string(__FILE__) + ":" + to_string(__LINE__)
+// + "the stack index is already zero");
+// }
+
+ if ( pc->type == CT_PAREN_CLOSE
+ || pc->type == CT_BRACE_CLOSE
+ || pc->type == CT_VBRACE_CLOSE
+ || pc->type == CT_FPAREN_CLOSE
+ || pc->type == CT_LPAREN_CLOSE
+ || pc->type == CT_SPAREN_CLOSE
+ || pc->type == CT_CLASS_COLON
+ || pc->type == CT_ANGLE_CLOSE
+ || pc->type == CT_SEMICOLON
+ || pc->type == CT_SQUARE_CLOSE)
+ {
+ LOG_FMT(LINDPSE, "ParseFrame::pop (%s:%d): orig_line is %4zu, orig_col is %4zu, type is %12s, pushed with\n",
+ func, line, pc->orig_line, pc->orig_col, get_token_name(pc->type));
+ }
+ else if ( pc->type == CT_ACCESS
+ || pc->type == CT_ASSIGN
+ || pc->type == CT_BRACE_OPEN
+ || pc->type == CT_BOOL
+ || pc->type == CT_CASE
+ || pc->type == CT_COMMA
+ || pc->type == CT_COMMENT
+ || pc->type == CT_COMMENT_CPP
+ || pc->type == CT_COMMENT_MULTI
+ || pc->type == CT_COND_COLON
+ || pc->type == CT_FPAREN_OPEN
+ || pc->type == CT_PAREN_OPEN
+ || pc->type == CT_TPAREN_OPEN
+ || pc->type == CT_MACRO_CLOSE
+ || pc->type == CT_MACRO_OPEN
+ || pc->type == CT_NEWLINE
+ || pc->type == CT_NONE
+ || pc->type == CT_OC_END
+ || pc->type == CT_OC_MSG_NAME
+ || pc->type == CT_OC_SCOPE
+ || pc->type == CT_PREPROC
+ || pc->type == CT_SQUARE_OPEN
+ || pc->type == CT_SQL_END
+ || pc->type == CT_TYPEDEF
+ || pc->type == CT_VSEMICOLON
+ || pc->type == CT_WORD)
+ {
+ LOG_FMT(LINDPSE, "ParseFrame::pop (%s:%d): orig_line is %4zu, orig_col is %4zu, type is %12s, ++++++++++++++++++++++++++\n",
+ func, line, pc->orig_line, pc->orig_col, get_token_name(pc->type));
+ }
+ else
+ {
+ LOG_FMT(LINDPSE, "ParseFrame::pop (%s:%d): orig_line is %4zu, orig_col is %4zu, type is %12s, *** Software error ***\n",
+ func, line, pc->orig_line, pc->orig_col, get_token_name(pc->type));
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+#ifdef DEBUG_PUSH_POP
+ LOG_FMT(LINDPSE, "ParseFrame::pop (%s:%d) Add is %4zu: open_line is %4zu, clos_col is %4zu, type is %12s, "
+ "cpd.level is %2d, level is %2zu, pse_tos: %2zu -> %2zu\n",
+ func, line, (size_t)this, pse.back().open_line, pse.back().open_colu,
+ get_token_name(pse.back().type), cpd.pp_level, pse.back().level,
+ (pse.size() - 1), (pse.size() - 2));
+#else /* DEBUG_PUSH_POP */
+ LOG_FMT(LINDPSE, "ParseFrame::pop (%s:%d): open_line is %4zu, clos_col is %4zu, type is %12s, "
+ "cpd.level is %2d, level is %2zu, pse_tos: %2zu -> %2zu\n",
+ func, line, pse.back().open_line, pse.back().open_colu,
+ get_token_name(pse.back().type), cpd.pp_level, pse.back().level,
+ (pse.size() - 1), (pse.size() - 2));
+#endif /* DEBUG_PUSH_POP */
+
+ last_poped = *std::prev(std::end(pse));
+
+ if (pse.size() == 1)
+ {
+ *std::begin(pse) = genDummy();
+ }
+ else
+ {
+ pse.pop_back();
+ }
+} // ParseFrame::pop
+
+
+size_t ParseFrame::size() const
+{
+ // always at least one (dummy) element inside pse guaranteed
+ return(pse.size());
+}
+
+
+const paren_stack_entry_t &ParseFrame::poped() const
+{
+ return(last_poped);
+}
+
+
+// TODO C++14: see abstract versions: std::rend, std::cend, std::crend ...
+ParseFrame::iterator ParseFrame::begin()
+{
+ return(std::begin(pse));
+}
+
+
+ParseFrame::const_iterator ParseFrame::begin() const
+{
+ return(std::begin(pse));
+}
+
+
+ParseFrame::reverse_iterator ParseFrame::rbegin()
+{
+ return(pse.rbegin());
+}
+
+
+ParseFrame::const_reverse_iterator ParseFrame::rbegin() const
+{
+ return(pse.rbegin());
+}
+
+
+ParseFrame::iterator ParseFrame::end()
+{
+ return(std::end(pse));
+}
+
+
+ParseFrame::const_iterator ParseFrame::end() const
+{
+ return(std::end(pse));
+}
+
+
+ParseFrame::reverse_iterator ParseFrame::rend()
+{
+ return(pse.rend());
+}
+
+
+ParseFrame::const_reverse_iterator ParseFrame::rend() const
+{
+ return(pse.rend());
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.h
new file mode 100644
index 00000000..59d1090e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/ParseFrame.h
@@ -0,0 +1,99 @@
+/**
+ * @file ParseFrame.h
+ *
+ * Container that holds data needed for indenting and brace parsing
+ *
+ * @author Daniel Chumak
+ * @license GPL v2+
+ */
+
+#ifndef SRC_PARSEFRAME_H_
+#define SRC_PARSEFRAME_H_
+
+#include "uncrustify_types.h"
+
+#include <memory>
+
+
+//! Structure for counting nested level
+struct paren_stack_entry_t
+{
+ E_Token type; //! the type that opened the entry
+ size_t level; //! Level of opening type
+ size_t open_line; //! line that open symbol is on, only for logging purposes
+ size_t open_colu; //! column that open symbol is on, only for logging purposes
+ Chunk *pc; //! Chunk that opened the level, TODO: make const
+ size_t brace_indent; //! indent for braces - may not relate to indent
+ size_t indent; //! indent level (depends on use)
+ size_t indent_tmp; //! temporary indent level (depends on use)
+ size_t indent_tab; //! the 'tab' indent (always <= real column)
+ bool indent_cont; //! indent_continue was applied
+ E_Token parent; //! if, for, function, etc
+ brace_stage_e stage; //! used to check progression of complex statements.
+ bool in_preproc; //! whether this was created in a preprocessor
+ size_t ns_cnt; //! Number of consecutive namespace levels
+ bool non_vardef; //! Hit a non-vardef line
+ indent_ptr_t ip;
+ Chunk *pop_pc;
+};
+
+class ParseFrame
+{
+private:
+ std::vector<paren_stack_entry_t> pse;
+ paren_stack_entry_t last_poped;
+
+ void clear();
+
+public:
+ size_t ref_no;
+ size_t level; //! level of parens/square/angle/brace
+ size_t brace_level; //! level of brace/vbrace
+ size_t pp_level; //! level of preproc #if stuff
+ size_t sparen_count;
+ size_t paren_count;
+ E_Token in_ifdef;
+ size_t stmt_count;
+ size_t expr_count;
+
+
+ ParseFrame();
+ virtual ~ParseFrame() = default;
+
+ bool empty() const;
+
+ paren_stack_entry_t &at(size_t idx);
+ const paren_stack_entry_t &at(size_t idx) const;
+
+ paren_stack_entry_t &prev(size_t idx = 1);
+ const paren_stack_entry_t &prev(size_t idx = 1) const;
+
+ paren_stack_entry_t &top();
+ const paren_stack_entry_t &top() const;
+
+ const paren_stack_entry_t &poped() const;
+
+ void push(Chunk *pc, const char *func, int line, brace_stage_e stage = brace_stage_e::NONE);
+ void push(std::nullptr_t, brace_stage_e stage = brace_stage_e::NONE);
+ void pop(const char *func, int line, Chunk *pc);
+
+ size_t size() const;
+
+ using iterator = std::vector<paren_stack_entry_t>::iterator;
+ iterator begin();
+ iterator end();
+
+ using const_iterator = std::vector<paren_stack_entry_t>::const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ using reverse_iterator = std::vector<paren_stack_entry_t>::reverse_iterator;
+ reverse_iterator rbegin();
+ reverse_iterator rend();
+
+ using const_reverse_iterator = std::vector<paren_stack_entry_t>::const_reverse_iterator;
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+};
+
+#endif /* SRC_PARSEFRAME_H_ */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/add_space_table.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/add_space_table.h
new file mode 100644
index 00000000..cb664d2d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/add_space_table.h
@@ -0,0 +1,296 @@
+// *INDENT-OFF*
+ { CT_ACCESS, CT_TYPE },
+ { CT_ACCESS, CT_WORD },
+ { CT_ALIGN, CT_PAREN_OPEN },
+ { CT_AMP, CT_WORD },
+ { CT_ANGLE_CLOSE, CT_BRACE_OPEN },
+ { CT_ANNOTATION, CT_ANNOTATION },
+ { CT_ANNOTATION, CT_TYPE },
+ { CT_ASM_COLON, CT_ASM_COLON },
+ { CT_ASM_COLON, CT_STRING },
+ { CT_ASM, CT_FUNC_CALL },
+ { CT_ASM, CT_PAREN_OPEN },
+ { CT_ASM, CT_QUALIFIER },
+ { CT_ASSERT, CT_PAREN_OPEN },
+ { CT_ASSIGN_FUNC_PROTO, CT_DEFAULT },
+ { CT_ASSIGN_FUNC_PROTO, CT_DELETE },
+ { CT_ASSIGN_FUNC_PROTO, CT_NUMBER },
+ { CT_ATTRIBUTE, CT_ATTRIBUTE },
+ { CT_ATTRIBUTE, CT_BRACE_OPEN },
+ { CT_ATTRIBUTE, CT_CASE },
+ { CT_ATTRIBUTE, CT_QUALIFIER },
+ { CT_ATTRIBUTE, CT_TYPE },
+ { CT_ATTRIBUTE, CT_WORD },
+ { CT_AUTORELEASEPOOL, CT_BRACE_OPEN },
+ { CT_BIT_COLON, CT_NUMBER },
+ { CT_BIT_COLON, CT_SIZEOF },
+ { CT_BIT_COLON, CT_TYPE },
+ { CT_BIT_COLON, CT_WORD },
+ { CT_BODY, CT_BRACE_OPEN },
+ { CT_BRACE_CLOSE, CT_BRACE_OPEN },
+ { CT_BRACE_CLOSE, CT_CLASS },
+ { CT_BRACE_CLOSE, CT_FUNC_CALL },
+ { CT_BRACE_CLOSE, CT_GETSET },
+ { CT_BRACE_CLOSE, CT_IF },
+ { CT_BRACE_CLOSE, CT_OC_MSG_NAME },
+ { CT_BRACE_CLOSE, CT_PAREN_OPEN },
+ { CT_BRACE_CLOSE, CT_QUALIFIER },
+ { CT_BRACE_CLOSE, CT_RETURN },
+ { CT_BRACE_CLOSE, CT_TYPE },
+ { CT_BRACE_CLOSE, CT_WORD },
+ { CT_BREAK, CT_WORD },
+ { CT_BYREF, CT_INV },
+ { CT_CASE_COLON, CT_ATTRIBUTE },
+ { CT_CASE_COLON, CT_BRACE_OPEN },
+ { CT_CASE_COLON, CT_BREAK },
+ { CT_CASE_COLON, CT_RETURN },
+ { CT_CASE_COLON, CT_WORD },
+ { CT_CASE, CT_NEG },
+ { CT_CASE, CT_PAREN_OPEN },
+ { CT_CASE, CT_STRING },
+ { CT_CATCH, CT_FUNC_CALL },
+ { CT_CLASS_COLON, CT_FUNC_CALL },
+ { CT_CLASS_COLON, CT_QUALIFIER },
+ { CT_CLASS_COLON, CT_TYPE },
+ { CT_CLASS_COLON, CT_WORD },
+ { CT_COLON, CT_COLON },
+ { CT_COLON, CT_NUMBER },
+ { CT_COLON, CT_QUALIFIER },
+ { CT_COLON, CT_STRING },
+ { CT_COLON, CT_TYPE },
+ { CT_COLON, CT_WORD },
+ { CT_COMMENT_EMBED, CT_FUNC_CLASS_PROTO },
+ { CT_COMMENT_MULTI, CT_ELSE },
+ { CT_CONCAT, CT_STRING },
+ { CT_CONCAT, CT_WORD },
+ { CT_COND_COLON, CT_FUNC_CALL },
+ { CT_COND_COLON, CT_STRING },
+ { CT_COND_COLON, CT_WORD },
+ { CT_CONSTRUCT, CT_TYPE },
+ { CT_CONTINUE, CT_WORD },
+ { CT_CS_PROPERTY, CT_BRACE_OPEN },
+ { CT_DEFAULT, CT_STRING },
+ { CT_DEFAULT, CT_WORD },
+ { CT_DELEGATE, CT_BRACE_OPEN },
+ { CT_D_MODULE, CT_WORD },
+ { CT_ELLIPSIS, CT_NUMBER },
+ { CT_ELSE, CT_FOR },
+ { CT_ELSE, CT_IF },
+ { CT_ELSE, CT_PAREN_OPEN },
+ { CT_ELSE, CT_WORD },
+ { CT_ELSEIF, CT_CONSTEXPR },
+ { CT_ENUM_CLASS, CT_ATTRIBUTE },
+ { CT_ENUM_CLASS, CT_TYPE },
+ { CT_ENUM, CT_ATTRIBUTE },
+ { CT_ENUM, CT_BIT_COLON },
+ { CT_ENUM, CT_BRACE_OPEN },
+ { CT_ENUM, CT_ENUM_CLASS },
+ { CT_ENUM, CT_FPAREN_OPEN },
+ { CT_ENUM, CT_FUNCTION },
+ { CT_ENUM, CT_TYPE },
+ { CT_ENUM, CT_WORD },
+ { CT_EXECUTION_CONTEXT, CT_EXECUTION_CONTEXT },
+ { CT_EXECUTION_CONTEXT, CT_FPAREN_OPEN },
+ { CT_EXTERN, CT_STRING },
+ { CT_FPAREN_CLOSE, CT_ASSIGN_FUNC_PROTO },
+ { CT_FPAREN_CLOSE, CT_ATTRIBUTE },
+ { CT_FPAREN_CLOSE, CT_CLASS_COLON },
+ { CT_FPAREN_CLOSE, CT_COND_COLON },
+ { CT_FPAREN_CLOSE, CT_DEFAULT },
+ { CT_FPAREN_CLOSE, CT_FUNC_CALL },
+ { CT_FPAREN_CLOSE, CT_NEG },
+ { CT_FPAREN_CLOSE, CT_NOT },
+ { CT_FPAREN_CLOSE, CT_OC_MSG_NAME },
+ { CT_FPAREN_CLOSE, CT_QUESTION },
+ { CT_FPAREN_CLOSE, CT_STRING },
+ { CT_FPAREN_CLOSE, CT_THROW },
+ { CT_FPAREN_CLOSE, CT_TYPE },
+ { CT_FPAREN_CLOSE, CT_WHERE_SPEC },
+ { CT_FPAREN_CLOSE, CT_WORD },
+ { CT_FRIEND, CT_CLASS },
+ { CT_FRIEND, CT_STRUCT },
+ { CT_FRIEND, CT_TYPE },
+ { CT_FUNCTION, CT_PAREN_OPEN },
+ { CT_FUNC_VAR, CT_PPAREN_CLOSE },
+ { CT_GOTO, CT_WORD },
+ { CT_IF, CT_CONSTEXPR },
+ { CT_IMPORT, CT_WORD },
+ { CT_INCDEC_AFTER, CT_DEREF },
+ { CT_IN, CT_TYPE },
+ { CT_IN, CT_WORD },
+ { CT_LABEL_COLON, CT_CS_PROPERTY },
+ { CT_LABEL_COLON, CT_FUNC_CALL },
+ { CT_LABEL_COLON, CT_NEW },
+ { CT_LABEL_COLON, CT_PAREN_OPEN },
+ { CT_LABEL_COLON, CT_RETURN },
+ { CT_LABEL_COLON, CT_STRING },
+ { CT_LABEL_COLON, CT_TYPE },
+ { CT_LABEL_COLON, CT_WORD },
+ { CT_LOCK, CT_PAREN_OPEN },
+ { CT_NAMESPACE, CT_BRACE_OPEN },
+ { CT_NAMESPACE, CT_TYPE },
+ { CT_NAMESPACE, CT_WORD },
+ { CT_NATIVE, CT_TAG },
+ { CT_NUMBER, CT_CHAR },
+ { CT_NUMBER, CT_COLON },
+ { CT_NUMBER, CT_ELLIPSIS },
+ { CT_NUMBER, CT_OC_MSG_NAME },
+ { CT_NUMBER, CT_PAREN_OPEN },
+ { CT_NUMBER, CT_WORD },
+ { CT_NUMBER_FP, CT_NUMBER },
+ { CT_NUMBER_FP, CT_OC_MSG_NAME },
+ { CT_NUMBER_FP, CT_WORD },
+ { CT_OC_CLASS, CT_CLASS_COLON },
+ { CT_OC_CLASS, CT_PAREN_OPEN },
+ { CT_OC_DYNAMIC, CT_WORD },
+ { CT_OC_IMPL, CT_OC_CLASS },
+ { CT_OC_INTF, CT_OC_CLASS },
+ { CT_OC_MSG_DECL, CT_BRACE_OPEN },
+ { CT_OC_PROTOCOL, CT_OC_CLASS },
+ { CT_PACKAGE, CT_WORD },
+ { CT_PAREN_CLOSE, CT_ASM_COLON },
+ { CT_PAREN_CLOSE, CT_COLON },
+ { CT_PAREN_CLOSE, CT_COND_COLON },
+ { CT_PAREN_CLOSE, CT_CS_PROPERTY },
+ { CT_PAREN_CLOSE, CT_DEREF },
+ { CT_PAREN_CLOSE, CT_NOT },
+ { CT_PAREN_CLOSE, CT_NUMBER },
+ { CT_PAREN_CLOSE, CT_OC_MSG_NAME },
+ { CT_PAREN_CLOSE, CT_POS },
+ { CT_PAREN_CLOSE, CT_QUALIFIER },
+ { CT_PAREN_CLOSE, CT_TYPE },
+ { CT_PP_DEFINE, CT_MACRO },
+ { CT_PP_DEFINE, CT_MACRO_FUNC },
+ { CT_PP_DEFINE, CT_NUMBER },
+ { CT_PP_DEFINE, CT_PP_IGNORE },
+ { CT_PP_DEFINED, CT_TYPE },
+ { CT_PP_DEFINED, CT_WORD },
+ { CT_PP_ELSE, CT_FUNC_CALL },
+ { CT_PP_ELSE, CT_NOT },
+ { CT_PP_ELSE, CT_NUMBER },
+ { CT_PP_ELSE, CT_PAREN_OPEN },
+ { CT_PP_ELSE, CT_PP_DEFINED },
+ { CT_PP_ELSE, CT_WORD },
+ { CT_PP_EMIT, CT_MACRO },
+ { CT_PP_ENDIF, CT_WORD },
+ { CT_PP_ENDREGION, CT_PREPROC_BODY },
+ { CT_PP_IF, CT_CNG_HASINC },
+ { CT_PP_IF, CT_FUNC_CALL },
+ { CT_PP_IF, CT_NOT },
+ { CT_PP_IF, CT_NUMBER },
+ { CT_PP_IF, CT_PAREN_OPEN },
+ { CT_PP_IF, CT_PP_ASM },
+ { CT_PP_IF, CT_PP_DEFINE },
+ { CT_PP_IF, CT_PP_DEFINED },
+ { CT_PP_IF, CT_TYPE },
+ { CT_PP_IF, CT_WORD },
+ { CT_PP_INCLUDE, CT_STRING },
+ { CT_PP_INCLUDE, CT_WORD },
+ { CT_PP_OTHER, CT_PREPROC_BODY },
+ { CT_PP_PROPERTY, CT_WORD },
+ { CT_PP_REGION, CT_PREPROC_BODY },
+ { CT_PP_UNDEF, CT_TYPE },
+ { CT_PP_UNDEF, CT_WORD },
+ { CT_Q_EMIT, CT_FUNC_CALL },
+ { CT_Q_FOREVER, CT_BRACE_OPEN },
+ { CT_QUESTION, CT_FUNC_CALL },
+ { CT_QUESTION, CT_PAREN_OPEN },
+ { CT_QUESTION, CT_STRING },
+ { CT_QUESTION, CT_WORD },
+ { CT_SBOOL, CT_TYPE },
+ { CT_SCOMPARE, CT_WORD },
+ { CT_SPAREN_CLOSE, CT_ATTRIBUTE },
+ { CT_SPAREN_CLOSE, CT_AUTORELEASEPOOL },
+ { CT_SPAREN_CLOSE, CT_BRACE_OPEN },
+ { CT_SPAREN_CLOSE, CT_FUNC_CALL },
+ { CT_SPAREN_CLOSE, CT_WORD },
+ { CT_SQL_ASSIGN, CT_FUNC_CALL },
+ { CT_SQL_ASSIGN, CT_WORD },
+ { CT_SQL_BEGIN, CT_SQL_WORD },
+ { CT_SQL_END, CT_SQL_WORD },
+ { CT_SQL_EXEC, CT_SQL_WORD },
+ { CT_SQL_WORD, CT_COLON },
+ { CT_SQL_WORD, CT_PAREN_OPEN },
+ { CT_SQL_WORD, CT_SQL_WORD },
+ { CT_SQUARE_CLOSE, CT_ATTRIBUTE },
+ { CT_SQUARE_CLOSE, CT_BRACE_OPEN },
+ { CT_SQUARE_CLOSE, CT_COLON },
+ { CT_SQUARE_CLOSE, CT_EXECUTION_CONTEXT },
+ { CT_SQUARE_CLOSE, CT_OC_MSG_NAME },
+ { CT_SQUARE_CLOSE, CT_STRING },
+ { CT_SQUARE_CLOSE, CT_WORD },
+ { CT_STATE, CT_TYPE },
+ { CT_STOCK, CT_QUALIFIER },
+ { CT_STOCK, CT_TAG },
+ { CT_STRING, CT_ATTRIBUTE },
+ { CT_STRING, CT_BRACE_OPEN },
+ { CT_STRING, CT_COLON },
+ { CT_STRING, CT_CONCAT },
+ { CT_STRING, CT_OC_MSG_NAME },
+ { CT_STRING, CT_PAREN_OPEN },
+ { CT_STRING, CT_STRING },
+ { CT_STRING, CT_STRUCT },
+ { CT_STRING, CT_TYPE },
+ { CT_STRING, CT_WORD },
+ { CT_STRUCT, CT_BRACE_OPEN },
+ { CT_STRUCT, CT_CLASS_COLON },
+ { CT_STRUCT, CT_MACRO_FUNC_CALL },
+ { CT_STRUCT, CT_TYPE },
+ { CT_STRUCT, CT_WORD },
+ { CT_TEMPLATE, CT_CLASS },
+ { CT_TEMPLATE, CT_TYPE },
+ { CT_THIS, CT_OC_MSG_NAME },
+ { CT_THIS, CT_TYPE },
+ { CT_TSQUARE, CT_BRACE_OPEN },
+ { CT_TSQUARE, CT_PAREN_OPEN },
+ { CT_TSQUARE, CT_WORD },
+ { CT_TYPEDEF, CT_ENUM },
+ { CT_TYPEDEF, CT_FUNC_TYPE },
+ { CT_TYPEDEF, CT_PAREN_OPEN },
+ { CT_TYPEDEF, CT_QUALIFIER },
+ { CT_TYPEDEF, CT_STRUCT },
+ { CT_TYPEDEF, CT_TYPE },
+ { CT_TYPEDEF, CT_TYPENAME },
+ { CT_TYPEDEF, CT_UNION },
+ { CT_TYPENAME, CT_ELLIPSIS },
+ { CT_TYPENAME, CT_WORD },
+ { CT_UNION, CT_BRACE_OPEN },
+ { CT_UNION, CT_TYPE },
+ { CT_UNION, CT_WORD },
+ { CT_USING, CT_NAMESPACE },
+ { CT_USING, CT_TYPE },
+ { CT_USING, CT_WORD },
+ { CT_USING_STMT, CT_PAREN_OPEN },
+ { CT_VOLATILE, CT_BRACE_OPEN },
+ { CT_WHERE_COLON, CT_CS_PROPERTY },
+ { CT_WHERE_COLON, CT_NEW },
+ { CT_WHERE_COLON, CT_TYPE },
+ { CT_WHERE_COLON, CT_WORD },
+ { CT_WHERE_SPEC, CT_WORD },
+ { CT_WORD, CT_ATTRIBUTE },
+ { CT_WORD, CT_BIT_COLON },
+ { CT_WORD, CT_BRACE_OPEN },
+ { CT_WORD, CT_CLASS_COLON },
+ { CT_WORD, CT_COLON },
+ { CT_WORD, CT_COMMENT_CPP },
+ { CT_WORD, CT_CONCAT },
+ { CT_WORD, CT_ELLIPSIS },
+ { CT_WORD, CT_IN },
+ { CT_WORD, CT_NEW },
+ { CT_WORD, CT_NOT },
+ { CT_WORD, CT_NUMBER },
+ { CT_WORD, CT_NUMBER_FP },
+ { CT_WORD, CT_OPERATOR },
+ { CT_WORD, CT_QUALIFIER },
+ { CT_WORD, CT_QUESTION },
+ { CT_WORD, CT_SCOMPARE },
+ { CT_WORD, CT_SQL_ASSIGN },
+ { CT_WORD, CT_STRING },
+ { CT_WORD, CT_STRUCT },
+ { CT_WORD, CT_TYPE },
+ { CT_WORD, CT_TYPE_CAST },
+ { CT_WORD, CT_TYPEDEF },
+ { CT_WORD, CT_WHERE_COLON },
+ { CT_WORD, CT_WHERE_SPEC },
+ { CT_WORD, CT_WORD },
+// *INDENT-ON*
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.cpp
new file mode 100644
index 00000000..3ea306ed
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.cpp
@@ -0,0 +1,231 @@
+/**
+ * @file align.cpp
+ * Does all the aligning stuff.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * October 2015, 2016
+ * @license GPL v2+
+ */
+
+#include "align.h"
+
+#include "align_asm_colon.h"
+#include "align_assign.h"
+#include "align_braced_init_list.h"
+#include "align_eigen_comma_init.h"
+#include "align_func_params.h"
+#include "align_func_proto.h"
+#include "align_init_brace.h"
+#include "align_left_shift.h"
+#include "align_oc_decl_colon.h"
+#include "align_oc_msg_colons.h"
+#include "align_oc_msg_spec.h"
+#include "align_preprocessor.h"
+#include "align_same_func_call_params.h"
+#include "align_stack.h"
+#include "align_struct_initializers.h"
+#include "align_trailing_comments.h"
+#include "align_typedefs.h"
+#include "align_var_def_brace.h"
+#include "log_rules.h"
+#include "quick_align_again.h"
+
+constexpr static auto LCURRENT = LALIGN;
+
+using namespace uncrustify;
+
+
+/*
+ * Here are the items aligned:
+ *
+ * - enum value assignments
+ * enum {
+ * cat = 1,
+ * fred = 2,
+ * };
+ *
+ * - struct/union variable & bit definitions
+ * struct foo {
+ * char cat;
+ * int id : 5;
+ * int name_len : 6;
+ * int height : 12;
+ * };
+ *
+ * - variable definitions & assignments in normal code
+ * const char *cat = "feline";
+ * int id = 4;
+ * a = 5;
+ * bat = 14;
+ *
+ * - simple array initializers
+ * int a[] = {
+ * 1, 2, 3, 4, 5,
+ * 6, 7, 8, 9, 10
+ * };
+ *
+ * - c99 array initializers
+ * const char *name[] = {
+ * [FRED] = "fred",
+ * [JOE] = "joe",
+ * [PETER] = "peter",
+ * };
+ * struct foo b[] = {
+ * { .id = 1, .name = "text 1" },
+ * { .id = 567, .name = "text 2" },
+ * };
+ * struct foo_t bars[] =
+ * {
+ * [0] = { .name = "bar",
+ * .age = 21 },
+ * [1] = { .name = "barley",
+ * .age = 55 },
+ * };
+ *
+ * - compact array initializers
+ * struct foo b[] = {
+ * { 3, "dog" }, { 6, "spider" },
+ * { 8, "elephant" }, { 3, "cat" },
+ * };
+ *
+ * - multiline array initializers (2nd line indented, not aligned)
+ * struct foo b[] = {
+ * { AD_NOT_ALLOWED, "Sorry, you failed to guess the password.",
+ * "Try again?", "Yes", "No" },
+ * { AD_SW_ERROR, "A software error has occured.", "Bye!", NULL, NULL },
+ * };
+ *
+ * - Trailing comments
+ *
+ * - Back-slash newline groups
+ *
+ * - Function prototypes
+ * int foo();
+ * void bar();
+ *
+ * - Preprocessors
+ * #define FOO_VAL 15
+ * #define MAX_TIMEOUT 60
+ * #define FOO(x) ((x) * 65)
+ *
+ * - typedefs
+ * typedef uint8_t BYTE;
+ * typedef int32_t INT32;
+ * typedef uint32_t UINT32;
+ */
+void align_all(void)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("align_typedef_span");
+
+ if (options::align_typedef_span() > 0)
+ {
+ align_typedefs(options::align_typedef_span());
+ }
+ log_rule_B("align_left_shift");
+
+ if (options::align_left_shift())
+ {
+ align_left_shift();
+ }
+ log_rule_B("align_eigen_comma_init");
+
+ if (options::align_eigen_comma_init())
+ {
+ align_eigen_comma_init();
+ }
+ log_rule_B("align_oc_msg_colon_span");
+
+ if (options::align_oc_msg_colon_span() > 0)
+ {
+ align_oc_msg_colons();
+ }
+ // Align variable definitions
+ log_rule_B("align_var_def_span");
+ log_rule_B("align_var_struct_span");
+ log_rule_B("align_var_class_span");
+
+ if ( (options::align_var_def_span() > 0)
+ || (options::align_var_struct_span() > 0)
+ || (options::align_var_class_span() > 0))
+ {
+ align_var_def_brace(Chunk::GetHead(), options::align_var_def_span(), nullptr);
+ }
+ // Align assignments
+ log_rule_B("align_enum_equ_span");
+ log_rule_B("align_assign_span");
+ log_rule_B("align_assign_thresh");
+
+ if ( (options::align_enum_equ_span() > 0)
+ || (options::align_assign_span() > 0))
+ {
+ align_assign(Chunk::GetHead(),
+ options::align_assign_span(),
+ options::align_assign_thresh(),
+ nullptr);
+ }
+
+ if ( (options::align_braced_init_list_span() > 0) // Issue #750
+ || (options::align_braced_init_list_thresh() > 0))
+ {
+ align_braced_init_list(Chunk::GetHead(),
+ options::align_braced_init_list_span(),
+ options::align_braced_init_list_thresh(),
+ nullptr);
+ }
+ // Align structure initializers
+ log_rule_B("align_struct_init_span");
+
+ if (options::align_struct_init_span() > 0)
+ {
+ align_struct_initializers();
+ }
+ // Align function prototypes
+ log_rule_B("align_func_proto_span");
+ log_rule_B("align_mix_var_proto");
+
+ if ( (options::align_func_proto_span() > 0)
+ && !options::align_mix_var_proto())
+ {
+ align_func_proto(options::align_func_proto_span());
+ }
+ // Align function prototypes
+ log_rule_B("align_oc_msg_spec_span");
+
+ if (options::align_oc_msg_spec_span() > 0)
+ {
+ align_oc_msg_spec(options::align_oc_msg_spec_span());
+ }
+ // Align OC colons
+ log_rule_B("align_oc_decl_colon");
+
+ if (options::align_oc_decl_colon())
+ {
+ align_oc_decl_colon();
+ }
+ log_rule_B("align_asm_colon");
+
+ if (options::align_asm_colon())
+ {
+ align_asm_colon();
+ }
+ // Align variable definitions in function prototypes
+ log_rule_B("align_func_params");
+ log_rule_B("align_func_params_span");
+
+ if ( options::align_func_params()
+ || options::align_func_params_span() > 0)
+ {
+ align_func_params();
+ }
+ log_rule_B("align_same_func_call_params");
+
+ if (options::align_same_func_call_params())
+ {
+ align_same_func_call_params();
+ }
+ // Just in case something was aligned out of order... do it again
+ quick_align_again();
+} // align_all
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.h
new file mode 100644
index 00000000..110a2c86
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align.h
@@ -0,0 +1,16 @@
+/**
+ * @file align.h
+ * prototypes for align.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef ALIGN_H_INCLUDED
+#define ALIGN_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+void align_all(void);
+
+#endif /* ALIGN_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.cpp
new file mode 100644
index 00000000..6fe3191d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.cpp
@@ -0,0 +1,58 @@
+/**
+ * @file align_add.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_add.h"
+#include "uncrustify.h"
+
+
+void align_add(ChunkStack &cs, Chunk *pc, size_t &max_col)
+{
+ LOG_FUNC_ENTRY();
+
+ size_t min_col;
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ if (pc != nullptr)
+ {
+ prev = pc->GetPrev();
+ }
+
+ if ( prev->IsNullChunk()
+ || chunk_is_newline(prev))
+ {
+ min_col = 1;
+ LOG_FMT(LALADD, "%s(%d): pc->orig_line=%zu, pc->col=%zu max_col=%zu min_col=%zu\n",
+ __func__, __LINE__, pc->orig_line, pc->column, max_col, min_col);
+ }
+ else
+ {
+ if (chunk_is_token(prev, CT_COMMENT_MULTI))
+ {
+ min_col = prev->orig_col_end + 1;
+ }
+ else
+ {
+ min_col = prev->column + prev->Len() + 1;
+ }
+ LOG_FMT(LALADD, "%s(%d): pc->orig_line=%zu, pc->col=%zu max_col=%zu min_col=%zu multi:%s prev->col=%zu prev->Len()=%zu %s\n",
+ __func__, __LINE__, pc->orig_line, pc->column, max_col, min_col, (chunk_is_token(prev, CT_COMMENT_MULTI)) ? "Y" : "N",
+ (chunk_is_token(prev, CT_COMMENT_MULTI)) ? prev->orig_col_end : (UINT32)prev->column, prev->Len(), get_token_name(prev->type));
+ }
+
+ if (cs.Empty())
+ {
+ max_col = 0;
+ }
+ cs.Push_Back(pc);
+
+ if (min_col > max_col)
+ {
+ max_col = min_col;
+ }
+} // align_add
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.h
new file mode 100644
index 00000000..e178b5bd
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_add.h
@@ -0,0 +1,18 @@
+/**
+ * @file align_add.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_ADD_H_INCLUDED
+#define ALIGN_ADD_H_INCLUDED
+
+#include "chunk.h"
+#include "ChunkStack.h"
+
+void align_add(ChunkStack &cs, Chunk *pc, size_t &max_col);
+
+#endif /* ALIGN_ADD_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.cpp
new file mode 100644
index 00000000..a04121b2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.cpp
@@ -0,0 +1,62 @@
+/**
+ * @file align_asm_colon.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_asm_colon.h"
+
+#include "align_stack.h"
+#include "chunk.h"
+
+
+void align_asm_colon(void)
+{
+ LOG_FUNC_ENTRY();
+
+ bool did_nl;
+ AlignStack cas; // for the colons
+
+ cas.Start(4);
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_not_token(pc, CT_ASM_COLON))
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+ cas.Reset();
+
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ size_t level = pc ? pc->level : 0;
+ did_nl = true;
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= level)
+ {
+ if (chunk_is_newline(pc))
+ {
+ cas.NewLines(pc->nl_count);
+ did_nl = true;
+ }
+ else if (chunk_is_token(pc, CT_ASM_COLON))
+ {
+ cas.Flush();
+ did_nl = true;
+ }
+ else if (did_nl)
+ {
+ did_nl = false;
+ cas.Add(pc);
+ }
+ pc = pc->GetNextNc(E_Scope::PREPROC);
+ }
+ cas.End();
+ }
+} // align_asm_colon
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.h
new file mode 100644
index 00000000..25704404
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_asm_colon.h
@@ -0,0 +1,25 @@
+/**
+ * @file align_asm_colon.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_ASM_COLON_H_INCLUDED
+#define ALIGN_ASM_COLON_H_INCLUDED
+
+
+/**
+ * Aligns asm declarations on the colon
+ * asm volatile (
+ * "xxx"
+ * : "x"(h),
+ * "y"(l),
+ * : "z"(h)
+ * );
+ */
+void align_asm_colon(void);
+
+#endif /* ALIGN_ASM_COLON_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.cpp
new file mode 100644
index 00000000..cd08e53f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.cpp
@@ -0,0 +1,305 @@
+/**
+ * @file align_assign.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_assign.h"
+
+#include "align_stack.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALASS;
+
+using namespace uncrustify;
+
+
+Chunk *align_assign(Chunk *first, size_t span, size_t thresh, size_t *p_nl_count)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( first == nullptr
+ || first->IsNullChunk())
+ {
+ // coveralls will complain here. There are no example for that.
+ // see https://en.wikipedia.org/wiki/Robustness_principle
+ return(nullptr);
+ }
+ size_t my_level = first->level;
+
+ char copy[1000];
+
+ LOG_FMT(LALASS, "%s(%d): [my_level is %zu]: start checking with '%s', on orig_line %zu, span is %zu, thresh is %zu\n",
+ __func__, __LINE__, my_level, first->ElidedText(copy), first->orig_line, span, thresh);
+
+ // If we are aligning on a tabstop, we shouldn't right-align
+ AlignStack as; // regular assigns
+
+ as.Start(span, thresh);
+ log_rule_B("align_on_tabstop");
+ as.m_right_align = !options::align_on_tabstop();
+
+ AlignStack vdas; // variable def assigns
+
+ vdas.Start(span, thresh);
+ vdas.m_right_align = as.m_right_align;
+
+ std::deque<AlignStack> fcnDefault(1);
+
+ fcnDefault.back().Start(span, thresh);
+ fcnDefault.back().m_right_align = as.m_right_align;
+
+ AlignStack fcnProto;
+
+ fcnProto.Start(span, thresh);
+ fcnProto.m_right_align = as.m_right_align;
+
+ size_t var_def_cnt = 0;
+ size_t equ_count = 0;
+ size_t fcn_idx = 0;
+ size_t tmp;
+ Chunk *pc = first;
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): orig_line is %zu, check pc->Text() '%s', type is %s, parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->ElidedText(copy), get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)));
+
+ // Don't check inside SPAREN, PAREN or SQUARE groups
+ if ( chunk_is_token(pc, CT_SPAREN_OPEN)
+ // || chunk_is_token(pc, CT_FPAREN_OPEN) Issue #1340
+ || chunk_is_token(pc, CT_SQUARE_OPEN)
+ || chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ LOG_FMT(LALASS, "%s(%d): Don't check inside SPAREN, PAREN or SQUARE groups, type is %s\n",
+ __func__, __LINE__, get_token_name(pc->type));
+ tmp = pc->orig_line;
+ pc = chunk_skip_to_match(pc);
+
+ if (pc != nullptr)
+ {
+ as.NewLines(pc->orig_line - tmp);
+ vdas.NewLines(pc->orig_line - tmp);
+
+ if (pc->orig_line != tmp)
+ {
+ fcn_idx = 0;
+
+ for (auto &fcn : fcnDefault)
+ {
+ fcn.NewLines(pc->orig_line - tmp);
+ }
+ }
+ fcnProto.NewLines(pc->orig_line - tmp);
+ }
+ continue;
+ }
+
+ // Recurse if a brace set is found
+ if ( ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_OPEN))
+ && !(get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST))
+ {
+ size_t myspan;
+ size_t mythresh;
+
+ size_t sub_nl_count = 0;
+
+ if (get_chunk_parent_type(pc) == CT_ENUM)
+ {
+ log_rule_B("align_enum_equ_span");
+ myspan = options::align_enum_equ_span();
+ log_rule_B("align_enum_equ_thresh");
+ mythresh = options::align_enum_equ_thresh();
+ }
+ else
+ {
+ log_rule_B("align_assign_span");
+ myspan = options::align_assign_span();
+ log_rule_B("align_assign_thresh");
+ mythresh = options::align_assign_thresh();
+ }
+ pc = align_assign(pc->GetNextNcNnl(), myspan, mythresh, &sub_nl_count);
+
+ if (sub_nl_count > 0)
+ {
+ as.NewLines(sub_nl_count);
+ vdas.NewLines(sub_nl_count);
+ fcn_idx = 0;
+
+ for (auto &fcn : fcnDefault)
+ {
+ fcn.NewLines(sub_nl_count);
+ }
+
+ fcnProto.NewLines(sub_nl_count);
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += sub_nl_count;
+ }
+ }
+ continue;
+ }
+
+ // Done with this brace set?
+ if ( ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE))
+ && !(get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST))
+ {
+ pc = pc->GetNext();
+ break;
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ as.NewLines(pc->nl_count);
+ vdas.NewLines(pc->nl_count);
+ fcn_idx = 0;
+
+ for (auto &fcn : fcnDefault)
+ {
+ fcn.NewLines(pc->nl_count);
+ }
+
+ fcnProto.NewLines(pc->nl_count);
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += pc->nl_count;
+ }
+ var_def_cnt = 0;
+ equ_count = 0;
+ }
+ else if ( pc->flags.test(PCF_VAR_DEF)
+ && !pc->flags.test(PCF_IN_CONST_ARGS) // Issue #1717
+ && !pc->flags.test(PCF_IN_FCN_DEF) // Issue #1717
+ && !pc->flags.test(PCF_IN_FCN_CALL)) // Issue #1717
+ {
+ // produces much more log output. Use it only debugging purpose
+ //LOG_FMT(LALASS, "%s(%d): log_pcf_flags pc->flags:\n ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->flags);
+ var_def_cnt++;
+ }
+ else if ( var_def_cnt > 1
+ && !options::align_assign_on_multi_var_defs())
+ {
+ // we hit the second variable def and align was not requested - don't look for assigns, don't align
+ LOG_FMT(LALASS, "%s(%d): multiple var defs found and alignment was not requested\n",
+ __func__, __LINE__);
+ vdas.Reset();
+ }
+ else if ( equ_count == 0 // indent only if first '=' in line
+ && !pc->flags.test(PCF_IN_TEMPLATE) // and it is not inside a template #999
+ && ( chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_ASSIGN_DEFAULT_ARG)
+ || chunk_is_token(pc, CT_ASSIGN_FUNC_PROTO)))
+ {
+ if (chunk_is_token(pc, CT_ASSIGN)) // Issue #2236
+ {
+ equ_count++;
+ }
+ LOG_FMT(LALASS, "%s(%d): align_assign_decl_func() is %d\n",
+ __func__, __LINE__, options::align_assign_decl_func());
+ // produces much more log output. Use it only debugging purpose
+ //LOG_FMT(LALASS, "%s(%d): log_pcf_flags pc->flags: ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->flags);
+
+ log_rule_B("align_assign_decl_func");
+
+ if ( options::align_assign_decl_func() == 0 // Align with other assignments (default)
+ && ( chunk_is_token(pc, CT_ASSIGN_DEFAULT_ARG) // Foo( int bar = 777 );
+ || chunk_is_token(pc, CT_ASSIGN_FUNC_PROTO))) // Foo( const Foo & ) = delete;
+ {
+ LOG_FMT(LALASS, "%s(%d): fcnDefault[%zu].Add on '%s' on orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, fcn_idx, pc->Text(), pc->orig_line, pc->orig_col);
+
+ if (++fcn_idx == fcnDefault.size())
+ {
+ fcnDefault.emplace_back();
+ fcnDefault.back().Start(span, thresh);
+ fcnDefault.back().m_right_align = as.m_right_align;
+ }
+ fcnDefault[fcn_idx].Add(pc);
+ }
+ else if (options::align_assign_decl_func() == 1) // Align with each other
+ {
+ log_rule_B("align_assign_decl_func");
+
+ if (chunk_is_token(pc, CT_ASSIGN_DEFAULT_ARG)) // Foo( int bar = 777 );
+ {
+ LOG_FMT(LALASS, "%s(%d): default: fcnDefault[%zu].Add on '%s' on orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, fcn_idx, pc->Text(), pc->orig_line, pc->orig_col);
+
+ if (++fcn_idx == fcnDefault.size())
+ {
+ fcnDefault.emplace_back();
+ fcnDefault.back().Start(span, thresh);
+ fcnDefault.back().m_right_align = as.m_right_align;
+ }
+ fcnDefault[fcn_idx].Add(pc);
+ }
+ else if (chunk_is_token(pc, CT_ASSIGN_FUNC_PROTO)) // Foo( const Foo & ) = delete;
+ {
+ LOG_FMT(LALASS, "%s(%d): proto: fcnProto.Add on '%s' on orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ fcnProto.Add(pc);
+ }
+ else if (chunk_is_token(pc, CT_ASSIGN)) // Issue #2197
+ {
+ LOG_FMT(LALASS, "%s(%d): vdas.Add on '%s' on orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ vdas.Add(pc);
+ }
+ }
+ else if ( options::align_assign_decl_func() == 2 // Don't align
+ && ( chunk_is_token(pc, CT_ASSIGN_DEFAULT_ARG) // Foo( int bar = 777 );
+ || chunk_is_token(pc, CT_ASSIGN_FUNC_PROTO))) // Foo( const Foo & ) = delete;
+ {
+ log_rule_B("align_assign_decl_func");
+ LOG_FMT(LALASS, "%s(%d): Don't align\n", // Issue #2236
+ __func__, __LINE__);
+ }
+ else if (var_def_cnt != 0)
+ {
+ LOG_FMT(LALASS, "%s(%d): vdas.Add on '%s' on orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ vdas.Add(pc);
+ }
+ else
+ {
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ LOG_FMT(LALASS, "%s(%d): as.Add on '%s' on orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ as.Add(pc);
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+ as.End();
+ vdas.End();
+
+ for (auto &fcn : fcnDefault)
+ {
+ fcn.End();
+ }
+
+ fcnProto.End();
+
+ if (pc != nullptr)
+ {
+ LOG_FMT(LALASS, "%s(%d): done on '%s' on orig_line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ }
+ else
+ {
+ LOG_FMT(LALASS, "%s(%d): done on NULL\n", __func__, __LINE__);
+ }
+ return(pc);
+} // align_assign
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.h
new file mode 100644
index 00000000..8a23d0d5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_assign.h
@@ -0,0 +1,25 @@
+/**
+ * @file align_assign.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_ASSIGN_H_INCLUDED
+#define ALIGN_ASSIGN_H_INCLUDED
+
+#include "chunk.h"
+
+/**
+ * Aligns all assignment operators on the same level as first, starting with
+ * first.
+ * For variable definitions, only consider the '=' for the first variable.
+ * Otherwise, only look at the first '=' on the line.
+ *
+ * @param first chunk pointing to the first assignment
+ */
+Chunk *align_assign(Chunk *first, size_t span, size_t thresh, size_t *p_nl_count);
+
+#endif /* ALIGN_ASSIGN_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.cpp
new file mode 100644
index 00000000..3fd21394
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.cpp
@@ -0,0 +1,167 @@
+/**
+ * @file align_braced_init_list.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "align_braced_init_list.h"
+
+#include "align_stack.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALASS;
+
+using namespace uncrustify;
+
+
+Chunk *align_braced_init_list(Chunk *first, size_t span, size_t thresh, size_t *p_nl_count)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( first == nullptr
+ || first->IsNullChunk())
+ {
+ // coveralls will complain here. There are no example for that.
+ // see https://en.wikipedia.org/wiki/Robustness_principle
+ return(nullptr);
+ }
+ size_t my_level = first->level;
+
+ char copy[1000];
+
+ LOG_FMT(LALASS, "%s(%d): [my_level is %zu]: start checking with '%s', on orig_line %zu, span is %zu, thresh is %zu\n",
+ __func__, __LINE__, my_level, first->ElidedText(copy), first->orig_line, span, thresh);
+
+ // If we are aligning on a tabstop, we shouldn't right-align
+
+ AlignStack vdas; // variable def assigns
+
+ vdas.Start(span, thresh);
+ vdas.m_right_align = !options::align_on_tabstop();
+
+ size_t var_def_cnt = 0;
+ size_t equ_count = 0;
+ size_t tmp;
+ Chunk *pc = first;
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): orig_line is %zu, check pc->Text() '%s', type is %s, parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->ElidedText(copy), get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)));
+
+ // Don't check inside SPAREN, PAREN or SQUARE groups
+ if ( chunk_is_token(pc, CT_SPAREN_OPEN)
+ || chunk_is_token(pc, CT_SQUARE_OPEN)
+ || chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ LOG_FMT(LALASS, "%s(%d)OK: Don't check inside SPAREN, PAREN or SQUARE groups, type is %s\n",
+ __func__, __LINE__, get_token_name(pc->type));
+ tmp = pc->orig_line;
+ pc = chunk_skip_to_match(pc);
+
+ if (pc != nullptr)
+ {
+ vdas.NewLines(pc->orig_line - tmp);
+ }
+ continue;
+ }
+
+ // Recurse if a brace set is found
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && !(get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST))
+ {
+ size_t myspan;
+ size_t mythresh;
+
+ size_t sub_nl_count = 0;
+
+ log_rule_B("align_braced_init_list_span");
+ myspan = options::align_braced_init_list_span();
+ log_rule_B("align_braced_init_list_thresh");
+ mythresh = options::align_braced_init_list_thresh();
+ pc = align_braced_init_list(pc->GetNextNcNnl(), myspan, mythresh, &sub_nl_count);
+
+ if (sub_nl_count > 0)
+ {
+ vdas.NewLines(sub_nl_count);
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += sub_nl_count;
+ }
+ }
+ continue;
+ }
+
+ // Done with this brace set?
+ if ( ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE))
+ && !(get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST))
+ {
+ pc = pc->GetNext();
+ break;
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ vdas.NewLines(pc->nl_count);
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += pc->nl_count;
+ }
+ var_def_cnt = 0;
+ equ_count = 0;
+ }
+ else if ( pc->flags.test(PCF_VAR_DEF)
+ && !pc->flags.test(PCF_IN_CONST_ARGS) // Issue #1717
+ && !pc->flags.test(PCF_IN_FCN_DEF) // Issue #1717
+ && !pc->flags.test(PCF_IN_FCN_CALL)) // Issue #1717
+ {
+ // produces much more log output. Use it only debugging purpose
+ //LOG_FMT(LALASS, "%s(%d): log_pcf_flags pc->flags:\n ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->flags);
+ var_def_cnt++;
+ }
+ else if (var_def_cnt > 1)
+ {
+ // we hit the second variable def - don't look, don't align
+ vdas.Reset();
+ }
+ else if ( equ_count == 0
+ && !pc->flags.test(PCF_IN_TEMPLATE)
+ && chunk_is_token(pc, CT_BRACE_OPEN)
+ && (get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST))
+
+ {
+ equ_count++;
+ LOG_FMT(LALASS, "%s(%d)OK: align_braced_init_list_span() is %d\n",
+ __func__, __LINE__, options::align_braced_init_list_span());
+ // produces much more log output. Use it only debugging purpose
+ //LOG_FMT(LALASS, "%s(%d): log_pcf_flags pc->flags: ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->flags);
+
+ if (var_def_cnt != 0)
+ {
+ LOG_FMT(LALASS, "%s(%d)OK: vdas.Add on '%s' on orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ vdas.Add(pc);
+ }
+ }
+ pc = pc->GetNext();
+ }
+ vdas.End();
+
+ if (pc != nullptr)
+ {
+ LOG_FMT(LALASS, "%s(%d): done on '%s' on orig_line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ }
+ else
+ {
+ LOG_FMT(LALASS, "%s(%d): done on NULL\n", __func__, __LINE__);
+ }
+ return(pc);
+} // align_braced_init_list
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.h
new file mode 100644
index 00000000..e29868e0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_braced_init_list.h
@@ -0,0 +1,21 @@
+/**
+ * @file align_braced_init_list.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_BRACED_INIT_LIST_H_INCLUDED
+#define ALIGN_BRACED_INIT_LIST_H_INCLUDED
+
+#include "chunk.h"
+
+/**
+ * Aligns all braced init list operators on the same level as first, starting with
+ * first.
+ *
+ * @param first chunk pointing to the first braced init list
+ */
+Chunk *align_braced_init_list(Chunk *first, size_t span, size_t thresh, size_t *p_nl_count);
+
+#endif /* ALIGN_BRACED_INIT_LIST_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.cpp
new file mode 100644
index 00000000..19b114d6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.cpp
@@ -0,0 +1,121 @@
+/**
+ * @file align_eigen_comma_init.cpp
+ *
+ * @author Matthew Woehlke
+ * copied/adapted from align_left_shift.cpp
+ * @author Guy Maurel
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_eigen_comma_init.h"
+
+#include "align_stack.h"
+#include "indent.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALIGN;
+
+using namespace uncrustify;
+
+
+void align_eigen_comma_init(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *start = Chunk::NullChunkPtr;
+ AlignStack as;
+
+ as.Start(255);
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_newline(pc))
+ {
+ LOG_FMT(LALIGN, "%s(%d): orig_line is %zu, <Newline>\n", __func__, __LINE__, pc->orig_line);
+ }
+ else
+ {
+ LOG_FMT(LALIGN, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ }
+
+ if ( start->IsNotNullChunk()
+ && ((pc->flags & PCF_IN_PREPROC) != (start->flags & PCF_IN_PREPROC)))
+ {
+ // a change in preproc status restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if (chunk_is_newline(pc))
+ {
+ as.NewLines(pc->nl_count);
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->level < start->level)
+ {
+ // A drop in level restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->level > start->level)
+ {
+ // Ignore any deeper levels when aligning
+ }
+ else if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ // A semicolon at the same level flushes
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( !pc->flags.test(PCF_IN_ENUM)
+ && !pc->flags.test(PCF_IN_TYPEDEF)
+ && chunk_is_str(pc, "<<"))
+ {
+ if (get_chunk_parent_type(pc) == CT_OPERATOR)
+ {
+ // Ignore operator<<
+ }
+ else
+ {
+ /*
+ * check if the first one is actually on a blank line and then
+ * indent it. Eg:
+ *
+ * cout
+ * << "something";
+ */
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->IsNotNullChunk()
+ && chunk_is_newline(prev))
+ {
+ log_rule_B("indent_columns");
+ indent_to_column(pc, pc->column_indent + options::indent_columns());
+ pc->column_indent = pc->column;
+ chunk_flags_set(pc, PCF_DONT_INDENT);
+ }
+ // Restart alignment
+ as.Flush();
+ as.Add(pc->GetNext());
+ start = pc;
+ }
+ }
+ else if (!as.m_aligned.Empty())
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( chunk_is_newline(prev)
+ && chunk_is_token(pc->GetPrevNcNnl(), CT_COMMA))
+ {
+ log_rule_B("align_eigen_comma_init");
+ as.Add(pc);
+ }
+ }
+ pc = pc->GetNext();
+ }
+ as.End();
+} // align_left_shift
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.h
new file mode 100644
index 00000000..8f8ce34b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_eigen_comma_init.h
@@ -0,0 +1,14 @@
+/**
+ * @file align_left_shift.h
+ *
+ * @author Matthew Woehlke
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_EIGEN_COMMA_INIT_H_INCLUDED
+#define ALIGN_EIGEN_COMMA_INIT_H_INCLUDED
+
+//! Align comma-separated expressions following left shift operator '<<'
+void align_eigen_comma_init(void);
+
+#endif /* ALIGN_EIGEN_COMMA_INIT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.cpp
new file mode 100644
index 00000000..fe488a10
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.cpp
@@ -0,0 +1,188 @@
+/**
+ * @file align_func_params.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_func_params.h"
+
+#include "align_stack.h"
+#include "log_rules.h"
+
+#include <algorithm> // to get max
+
+constexpr static auto LCURRENT = LALIGN;
+
+using namespace uncrustify;
+
+
+Chunk *align_func_param(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LAS, "AlignStack::%s(%d): Candidate is '%s': orig_line is %zu, column is %zu, type is %s, level is %zu\n",
+ __func__, __LINE__, start->Text(), start->orig_line, start->column,
+ get_token_name(start->type), start->level);
+ // Defaults, if the align_func_params = true
+ size_t myspan = 2;
+ size_t mythresh = 0;
+ size_t mygap = 0;
+
+ // Override, if the align_func_params_span > 0
+ log_rule_B("align_func_params_span");
+
+ if (options::align_func_params_span() > 0)
+ {
+ myspan = options::align_func_params_span();
+ log_rule_B("align_func_params_thresh");
+ mythresh = options::align_func_params_thresh();
+ log_rule_B("align_func_params_gap");
+ mygap = options::align_func_params_gap();
+ }
+ const size_t HOW_MANY_AS = 16; // Issue #2921
+ AlignStack many_as[HOW_MANY_AS + 1];
+
+ size_t max_level_is = 0;
+
+ log_rule_B("align_var_def_star_style");
+ log_rule_B("align_var_def_amp_style");
+
+ for (size_t idx = 0; idx <= HOW_MANY_AS; idx++)
+ {
+ many_as[idx].Start(myspan, mythresh);
+ many_as[idx].m_gap = mygap;
+ many_as[idx].m_star_style = static_cast<AlignStack::StarStyle>(options::align_var_def_star_style());
+ many_as[idx].m_amp_style = static_cast<AlignStack::StarStyle>(options::align_var_def_amp_style());
+ }
+
+ size_t comma_count = 0;
+ size_t chunk_count = 0;
+ Chunk *pc = start;
+
+ while ((pc = pc->GetNext())->IsNotNullChunk())
+ {
+ chunk_count++;
+ LOG_FMT(LFLPAREN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ get_token_name(pc->type));
+
+ if (chunk_is_token(pc, CT_FUNC_VAR)) // Issue #2278
+ {
+ // look after 'protect parenthesis'
+ Chunk *after = pc->GetNextNc();
+
+ if (chunk_is_token(after, CT_PAREN_CLOSE))
+ {
+ Chunk *before = after->GetPrevType(CT_PAREN_OPEN, after->level);
+
+ if (before->IsNotNullChunk())
+ {
+ // these are 'protect parenthesis'
+ // change the types and the level
+ set_chunk_type(before, CT_PPAREN_OPEN);
+ set_chunk_type(after, CT_PPAREN_CLOSE);
+ pc->level = before->level;
+ Chunk *tmp = pc->GetPrevNc();
+
+ if (chunk_is_token(tmp, CT_PTR_TYPE))
+ {
+ tmp->level = before->level;
+ }
+ }
+ }
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ comma_count = 0;
+ chunk_count = 0;
+ many_as[pc->level].NewLines(pc->nl_count);
+ }
+ else if (pc->level <= start->level)
+ {
+ break;
+ }
+ else if (pc->flags.test(PCF_VAR_DEF))
+ {
+ if (chunk_count > 1)
+ {
+ if (pc->level > HOW_MANY_AS)
+ {
+ fprintf(stderr, "%s(%d): Not enought memory for Stack\n",
+ __func__, __LINE__);
+ fprintf(stderr, "%s(%d): the current maximum is %zu\n",
+ __func__, __LINE__, HOW_MANY_AS);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ max_level_is = max(max_level_is, pc->level);
+ many_as[pc->level].Add(pc);
+ }
+ }
+ else if (comma_count > 0)
+ {
+ if (!pc->IsComment())
+ {
+ comma_count = 2;
+ break;
+ }
+ }
+ else if (chunk_is_token(pc, CT_COMMA))
+ {
+ if (pc->flags.test(PCF_IN_TEMPLATE)) // Issue #2757
+ {
+ LOG_FMT(LFLPAREN, "%s(%d): comma is in template\n",
+ __func__, __LINE__);
+ }
+ else
+ {
+ Chunk *tmp_prev = pc->GetPrevNc();
+
+ if (!chunk_is_newline(tmp_prev)) // don't count leading commas
+ {
+ comma_count++;
+ LOG_FMT(LFLPAREN, "%s(%d): comma_count is %zu\n",
+ __func__, __LINE__, comma_count);
+ }
+ }
+ }
+ }
+
+ if (comma_count <= 1)
+ {
+ for (size_t idx = 1; idx <= max_level_is; idx++)
+ {
+ many_as[idx].End();
+ }
+ }
+ return(pc);
+} // align_func_param
+
+
+void align_func_params(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::GetHead();
+
+ while ((pc = pc->GetNext())->IsNotNullChunk())
+ {
+ LOG_FMT(LFLPAREN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', parent_type is %s, parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ get_token_name(pc->type), get_token_name(pc->parent_type));
+
+ if ( chunk_is_not_token(pc, CT_FPAREN_OPEN)
+ || ( get_chunk_parent_type(pc) != CT_FUNC_PROTO
+ && get_chunk_parent_type(pc) != CT_FUNC_DEF
+ && get_chunk_parent_type(pc) != CT_FUNC_CLASS_PROTO
+ && get_chunk_parent_type(pc) != CT_FUNC_CLASS_DEF
+ && get_chunk_parent_type(pc) != CT_TYPEDEF))
+ {
+ continue;
+ }
+ // We are on a open parenthesis of a prototype
+ pc = align_func_param(pc);
+ }
+} // void align_func_params
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.h
new file mode 100644
index 00000000..e2fbc42a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_params.h
@@ -0,0 +1,19 @@
+/**
+ * @file align_func_params.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_FUNC_PARAMS_H_INCLUDED
+#define ALIGN_FUNC_PARAMS_H_INCLUDED
+
+#include "chunk.h"
+
+void align_func_params(void);
+
+Chunk *align_func_param(Chunk *start);
+
+#endif /* ALIGN_FUNC_PARAMS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.cpp
new file mode 100644
index 00000000..c4c9fa0e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.cpp
@@ -0,0 +1,227 @@
+/**
+ * @file align_func_proto.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_func_proto.h"
+
+#include "align_stack.h"
+#include "align_tools.h"
+#include "log_rules.h"
+
+#include <algorithm> // to get max
+
+constexpr static auto LCURRENT = LALPROTO;
+
+using namespace uncrustify;
+
+
+void align_func_proto(size_t span)
+{
+ LOG_FUNC_ENTRY();
+
+ size_t myspan = span;
+ size_t mythresh = 0;
+
+ log_rule_B("align_func_proto_gap");
+ size_t mygap = options::align_func_proto_gap();
+
+ log_rule_B("align_func_proto_thresh");
+ mythresh = options::align_func_proto_thresh();
+
+ // Issue #2771
+ // we align token-1 and token-2 if:
+ // token-1->level == token-2->level
+ // and
+ // token-1->brace_level == token-2->brace_level
+ // we don't check if token-1 and token-2 are in the same block
+
+ log_rule_B("align_func_proto_star_style");
+ size_t mystar_style = options::align_func_proto_star_style();
+
+ log_rule_B("align_func_proto_amp_style");
+ size_t myamp_style = options::align_func_proto_amp_style();
+
+
+ size_t num_of_column = 1;
+ size_t num_of_row = 1;
+ AlignStack *stack_init_value = nullptr;
+
+
+ // Issue #2984
+ vector<vector<AlignStack *> > many_as;
+ // Issue #2771
+ vector<vector<AlignStack *> > many_as_brace;
+
+ // init the vector ...
+ many_as.resize(num_of_column, vector<AlignStack *>(num_of_row, stack_init_value));
+ many_as_brace.resize(num_of_column, vector<AlignStack *>(num_of_row, stack_init_value));
+
+ log_rule_B("align_single_line_brace_gap");
+ size_t mybr_gap = options::align_single_line_brace_gap();
+
+
+ bool look_bro = false;
+ Chunk *toadd;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ char copy[1000];
+ LOG_FMT(LAS, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s, level is %zu, brace_level is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy),
+ get_token_name(pc->type), pc->level, pc->brace_level);
+
+ // make the vector larger if necessary
+ if ( pc->level >= num_of_column // Issue #2960
+ || pc->brace_level >= num_of_row)
+ {
+ num_of_column = pc->level + 1;
+ num_of_row = pc->brace_level + 1;
+
+ many_as.resize(num_of_column);
+ many_as_brace.resize(num_of_column);
+
+ for (size_t i = 0; i < num_of_column; ++i)
+ {
+ many_as[i].resize(num_of_row);
+ many_as_brace[i].resize(num_of_row);
+ }
+ }
+
+ if ( chunk_is_newline(pc)
+ && !pc->flags.test(PCF_IN_FCN_CALL)) // Issue #2831
+ {
+ look_bro = false;
+ AlignStack *stack_at_l_bl = many_as.at(pc->level).at(pc->brace_level);
+
+ if (stack_at_l_bl == nullptr)
+ {
+ // get a Stack
+ stack_at_l_bl = new AlignStack();
+ // start it
+ stack_at_l_bl->Start(myspan, mythresh);
+ stack_at_l_bl->m_gap = mygap;
+ stack_at_l_bl->m_star_style = static_cast<AlignStack::StarStyle>(mystar_style);
+ stack_at_l_bl->m_amp_style = static_cast<AlignStack::StarStyle>(myamp_style);
+ // store
+ many_as.at(pc->level).at(pc->brace_level) = stack_at_l_bl;
+ }
+ stack_at_l_bl->Debug();
+
+ for (size_t idx = 0; idx < num_of_column; idx++)
+ {
+ for (size_t idx_brace = 0; idx_brace < num_of_row; idx_brace++)
+ {
+ stack_at_l_bl = many_as.at(idx).at(idx_brace);
+
+ if (stack_at_l_bl != nullptr)
+ {
+ stack_at_l_bl->NewLines(pc->nl_count);
+ }
+ }
+ }
+
+ AlignStack *stack_at_l_bl_brace = many_as_brace.at(pc->level).at(pc->brace_level);
+
+ if (stack_at_l_bl_brace == nullptr)
+ {
+ // get a Stack
+ stack_at_l_bl_brace = new AlignStack();
+ // start it
+ stack_at_l_bl_brace->Start(myspan, mythresh);
+ stack_at_l_bl_brace->m_gap = mybr_gap;
+ // store
+ many_as_brace.at(pc->level).at(pc->brace_level) = stack_at_l_bl_brace;
+ }
+ stack_at_l_bl_brace->Debug();
+ stack_at_l_bl_brace->NewLines(pc->nl_count);
+ }
+ else if ( chunk_is_token(pc, CT_FUNC_PROTO)
+ || ( chunk_is_token(pc, CT_FUNC_DEF)
+ && options::align_single_line_func()))
+ {
+ log_rule_B("align_single_line_func");
+ log_rule_B("align_on_operator");
+
+ if ( get_chunk_parent_type(pc) == CT_OPERATOR
+ && options::align_on_operator())
+ {
+ toadd = pc->GetPrevNcNnl();
+ }
+ else
+ {
+ toadd = pc;
+ }
+ Chunk *tmp = step_back_over_member(toadd);
+ LOG_FMT(LAS, "%s(%d): tmp->Text() is '%s', orig_line is %zu, orig_col is %zu, level is %zu, brace_level is %zu\n",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line, tmp->orig_col,
+ tmp->level, tmp->brace_level);
+ // test the Stack
+ AlignStack *stack_at_l_bl = many_as.at(pc->level).at(pc->brace_level);
+
+ if (stack_at_l_bl == nullptr)
+ {
+ // get a Stack
+ stack_at_l_bl = new AlignStack();
+ // start it
+ stack_at_l_bl->Start(myspan, mythresh);
+ stack_at_l_bl->m_gap = mygap;
+ stack_at_l_bl->m_star_style = static_cast<AlignStack::StarStyle>(mystar_style);
+ stack_at_l_bl->m_amp_style = static_cast<AlignStack::StarStyle>(myamp_style);
+ // store
+ many_as.at(pc->level).at(pc->brace_level) = stack_at_l_bl;
+ }
+ stack_at_l_bl->Add(tmp);
+ log_rule_B("align_single_line_brace");
+ look_bro = (chunk_is_token(pc, CT_FUNC_DEF))
+ && options::align_single_line_brace();
+ }
+ else if ( look_bro
+ && chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->flags.test(PCF_ONE_LINER))
+ {
+ AlignStack *stack_at_l_bl_brace = many_as_brace.at(pc->level).at(pc->brace_level);
+
+ if (stack_at_l_bl_brace == nullptr)
+ {
+ stack_at_l_bl_brace = new AlignStack();
+ stack_at_l_bl_brace->Start(myspan, mythresh);
+ stack_at_l_bl_brace->m_gap = mybr_gap;
+ many_as_brace.at(pc->level).at(pc->brace_level) = stack_at_l_bl_brace;
+ }
+ stack_at_l_bl_brace->Debug();
+ stack_at_l_bl_brace->Add(pc);
+ look_bro = false;
+ }
+ }
+
+ LOG_FMT(LAS, "%s(%d): as\n", __func__, __LINE__);
+
+ // purge
+ for (size_t idx = 0; idx < num_of_column; idx++)
+ {
+ for (size_t idx_brace = 0; idx_brace < num_of_row; idx_brace++)
+ {
+ AlignStack *stack_at_l_bl = many_as.at(idx).at(idx_brace);
+
+ if (stack_at_l_bl != nullptr)
+ {
+ stack_at_l_bl->End();
+ delete stack_at_l_bl;
+ stack_at_l_bl = nullptr;
+ }
+ AlignStack *stack_at_l_bl_brace = many_as_brace.at(idx).at(idx_brace);
+
+ if (stack_at_l_bl_brace != nullptr)
+ {
+ stack_at_l_bl_brace->End();
+ delete stack_at_l_bl_brace;
+ stack_at_l_bl_brace = nullptr;
+ }
+ }
+ }
+} // align_func_proto
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.h
new file mode 100644
index 00000000..811020e0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_func_proto.h
@@ -0,0 +1,18 @@
+/**
+ * @file align_func_proto.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_FUNC_PROTO_H_INCLUDED
+#define ALIGN_FUNC_PROTO_H_INCLUDED
+
+#include "chunk.h"
+
+//! Aligns all function prototypes in the file.
+void align_func_proto(size_t span);
+
+#endif /* ALIGN_FUNC_PROTO_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.cpp
new file mode 100644
index 00000000..ed1d2d39
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.cpp
@@ -0,0 +1,202 @@
+/**
+ * @file align_init_brace.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_init_brace.h"
+
+#include "align_log_al.h"
+#include "align_tab_column.h"
+#include "align_tools.h"
+#include "indent.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALBR;
+
+using namespace uncrustify;
+
+
+void align_init_brace(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *num_token = nullptr;
+
+ cpd.al_cnt = 0;
+ cpd.al_c99_array = false;
+
+ LOG_FMT(LALBR, "%s(%d): start @ orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, start->orig_line, start->orig_col);
+
+ Chunk *pc = start->GetNextNcNnl();
+ Chunk *pcSingle = scan_ib_line(pc, true);
+
+ if ( pcSingle == nullptr
+ || ( chunk_is_token(pcSingle, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(pcSingle) == CT_ASSIGN))
+ {
+ // single line - nothing to do
+ LOG_FMT(LALBR, "%s(%d): single line - nothing to do\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LALBR, "%s(%d): is not a single line\n", __func__, __LINE__);
+
+ do
+ {
+ pc = scan_ib_line(pc, false);
+
+ // debug dump the current frame
+ LOG_FMT(LALBR, "%s(%d): debug dump after, orig_line is %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ align_log_al(LALBR, pc->orig_line);
+
+ while (chunk_is_newline(pc))
+ {
+ pc = pc->GetNext();
+ }
+ } while ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && pc->level > start->level);
+
+ // debug dump the current frame
+ align_log_al(LALBR, start->orig_line);
+
+ log_rule_B("align_on_tabstop");
+
+ if ( options::align_on_tabstop()
+ && cpd.al_cnt >= 1
+ && (cpd.al[0].type == CT_ASSIGN))
+ {
+ cpd.al[0].col = align_tab_column(cpd.al[0].col);
+ }
+ pc = start->GetNext();
+ size_t idx = 0;
+
+ do
+ {
+ Chunk *tmp;
+
+ if ( idx == 0
+ && ((tmp = skip_c99_array(pc)) != nullptr))
+ {
+ pc = tmp;
+
+ LOG_FMT(LALBR, " -%zu- skipped '[] =' to %s\n",
+ pc->orig_line, get_token_name(pc->type));
+ continue;
+ }
+ Chunk *next = pc;
+
+ if (idx < cpd.al_cnt)
+ {
+ LOG_FMT(LALBR, " (%zu) check %s vs %s -- ",
+ idx, get_token_name(pc->type), get_token_name(cpd.al[idx].type));
+
+ if (chunk_is_token(pc, cpd.al[idx].type))
+ {
+ if ( idx == 0
+ && cpd.al_c99_array)
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if (chunk_is_newline(prev))
+ {
+ chunk_flags_set(pc, PCF_DONT_INDENT);
+ }
+ }
+ LOG_FMT(LALBR, " [%s] to col %zu\n", pc->Text(), cpd.al[idx].col);
+
+ if (num_token != nullptr)
+ {
+ int col_diff = pc->column - num_token->column;
+
+ reindent_line(num_token, cpd.al[idx].col - col_diff);
+ //LOG_FMT(LSYS, "-= %zu =- NUM indent [%s] col=%d diff=%d\n",
+ // num_token->orig_line,
+ // num_token->Text(), cpd.al[idx - 1].col, col_diff);
+
+ chunk_flags_set(num_token, PCF_WAS_ALIGNED);
+ num_token = nullptr;
+ }
+
+ // Comma's need to 'fall back' to the previous token
+ if (chunk_is_token(pc, CT_COMMA))
+ {
+ next = pc->GetNext();
+
+ if (!chunk_is_newline(next))
+ {
+ //LOG_FMT(LSYS, "-= %zu =- indent [%s] col=%d len=%d\n",
+ // next->orig_line,
+ // next->Text(), cpd.al[idx].col, cpd.al[idx].len);
+
+ log_rule_B("align_number_right");
+
+ if ( (idx < (cpd.al_cnt - 1))
+ && options::align_number_right()
+ && ( chunk_is_token(next, CT_NUMBER_FP)
+ || chunk_is_token(next, CT_NUMBER)
+ || chunk_is_token(next, CT_POS)
+ || chunk_is_token(next, CT_NEG)))
+ {
+ // Need to wait until the next match to indent numbers
+ num_token = next;
+ }
+ else if (idx < (cpd.al_cnt - 1))
+ {
+ LOG_FMT(LALBR, "%s(%d): idx is %zu, al_cnt is %zu, cpd.al[%zu].col is %zu, cpd.al[%zu].len is %zu\n",
+ __func__, __LINE__, idx, cpd.al_cnt, idx, cpd.al[idx].col, idx, cpd.al[idx].len);
+ reindent_line(next, cpd.al[idx].col + cpd.al[idx].len);
+ chunk_flags_set(next, PCF_WAS_ALIGNED);
+ }
+ }
+ }
+ else
+ {
+ // first item on the line
+ LOG_FMT(LALBR, "%s(%d): idx is %zu, cpd.al[%zu].col is %zu\n",
+ __func__, __LINE__, idx, idx, cpd.al[idx].col);
+ reindent_line(pc, cpd.al[idx].col);
+ chunk_flags_set(pc, PCF_WAS_ALIGNED);
+
+ // see if we need to right-align a number
+ log_rule_B("align_number_right");
+
+ if ( (idx < (cpd.al_cnt - 1))
+ && options::align_number_right())
+ {
+ next = pc->GetNext();
+
+ if ( !chunk_is_newline(next)
+ && ( chunk_is_token(next, CT_NUMBER_FP)
+ || chunk_is_token(next, CT_NUMBER)
+ || chunk_is_token(next, CT_POS)
+ || chunk_is_token(next, CT_NEG)))
+ {
+ // Need to wait until the next match to indent numbers
+ num_token = next;
+ }
+ }
+ }
+ idx++;
+ }
+ else
+ {
+ LOG_FMT(LALBR, " no match\n");
+ }
+ }
+
+ if ( chunk_is_newline(pc)
+ || chunk_is_newline(next))
+ {
+ idx = 0;
+ }
+ pc = pc->GetNext();
+ } while ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && pc->level > start->level);
+} // align_init_brace
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.h
new file mode 100644
index 00000000..c749eb54
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_init_brace.h
@@ -0,0 +1,49 @@
+/**
+ * @file align_init_brace.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_INIT_BRACE_H_INCLUDED
+#define ALIGN_INIT_BRACE_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+/**
+ * Generically aligns on '=', '{', '(' and item after ','
+ * It scans the first line and picks up the location of those tags.
+ * It then scans subsequent lines and adjusts the column.
+ * Finally it does a second pass to align everything.
+ *
+ * Aligns all the '=' signs in structure assignments.
+ * a = {
+ * .a = 1;
+ * .type = fast;
+ * };
+ *
+ * And aligns on '{', numbers, strings, words.
+ * colors[] = {
+ * {"red", {255, 0, 0}}, {"blue", { 0, 255, 0}},
+ * {"green", { 0, 0, 255}}, {"purple", {255, 255, 0}},
+ * };
+ *
+ * For the C99 indexed array assignment, the leading []= is skipped (no aligning)
+ * struct foo_t bars[] =
+ * {
+ * [0] = { .name = "bar",
+ * .age = 21 },
+ * [1] = { .name = "barley",
+ * .age = 55 },
+ * };
+ *
+ * NOTE: this assumes that spacing is at the minimum correct spacing (ie force)
+ * if it isn't, some extra spaces will be inserted.
+ *
+ * @param start Points to the open brace chunk
+ */
+void align_init_brace(Chunk *start);
+
+#endif /* ALIGN_INIT_BRACE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.cpp
new file mode 100644
index 00000000..21ef4ba6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.cpp
@@ -0,0 +1,134 @@
+/**
+ * @file align_left_shift.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_left_shift.h"
+
+#include "align_stack.h"
+#include "indent.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALIGN;
+
+using namespace uncrustify;
+
+
+void align_left_shift(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *start = Chunk::NullChunkPtr;
+ AlignStack as;
+
+ as.Start(255);
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_newline(pc))
+ {
+ LOG_FMT(LALIGN, "%s(%d): orig_line is %zu, <Newline>\n", __func__, __LINE__, pc->orig_line);
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LALIGN, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy));
+ }
+
+ if ( start->IsNotNullChunk()
+ && ((pc->flags & PCF_IN_PREPROC) != (start->flags & PCF_IN_PREPROC)))
+ {
+ // a change in preproc status restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if (chunk_is_newline(pc))
+ {
+ as.NewLines(pc->nl_count);
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->level < start->level)
+ {
+ // A drop in level restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->level > start->level)
+ {
+ // Ignore any deeper levels when aligning
+ }
+ else if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ // A semicolon at the same level flushes
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( !pc->flags.test(PCF_IN_ENUM)
+ && !pc->flags.test(PCF_IN_TYPEDEF)
+ && chunk_is_str(pc, "<<"))
+ {
+ if (get_chunk_parent_type(pc) == CT_OPERATOR)
+ {
+ // Ignore operator<<
+ }
+ else if (as.m_aligned.Empty())
+ {
+ /*
+ * check if the first one is actually on a blank line and then
+ * indent it. Eg:
+ *
+ * cout
+ * << "something";
+ */
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->IsNotNullChunk()
+ && chunk_is_newline(prev))
+ {
+ log_rule_B("indent_columns");
+ indent_to_column(pc, pc->column_indent + options::indent_columns());
+ pc->column_indent = pc->column;
+ chunk_flags_set(pc, PCF_DONT_INDENT);
+ }
+ // first one can be anywhere
+ as.Add(pc);
+ start = pc;
+ }
+ else if (chunk_is_newline(pc->GetPrev()))
+ {
+ // subsequent ones must be after a newline
+ as.Add(pc);
+ }
+ }
+ else if (!as.m_aligned.Empty())
+ {
+ /*
+ * check if the given statement is on a line of its own, immediately following <<
+ * and then it. Eg:
+ *
+ * cout <<
+ * "something";
+ */
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->IsNotNullChunk()
+ && chunk_is_newline(prev))
+ {
+ log_rule_B("indent_columns");
+ indent_to_column(pc, pc->column_indent + options::indent_columns());
+ pc->column_indent = pc->column;
+ chunk_flags_set(pc, PCF_DONT_INDENT);
+ }
+ }
+ pc = pc->GetNext();
+ }
+ as.End();
+} // align_left_shift
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.h
new file mode 100644
index 00000000..47d9eb81
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_left_shift.h
@@ -0,0 +1,16 @@
+/**
+ * @file align_left_shift.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_LEFT_SHIFT_H_INCLUDED
+#define ALIGN_LEFT_SHIFT_H_INCLUDED
+
+//! Align left shift operators '<<' (CT_SHIFT)
+void align_left_shift(void);
+
+#endif /* ALIGN_LEFT_SHIFT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.cpp
new file mode 100644
index 00000000..802b0280
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.cpp
@@ -0,0 +1,31 @@
+/**
+ * @file align_log_al.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_log_al.h"
+
+#include "uncrustify.h"
+
+
+void align_log_al(log_sev_t sev, size_t line)
+{
+ if (log_sev_on(sev))
+ {
+ log_fmt(sev, "%s(%d): line %zu, cpd.al_cnt is %zu\n",
+ __func__, __LINE__, line, cpd.al_cnt);
+
+ for (size_t idx = 0; idx < cpd.al_cnt; idx++)
+ {
+ log_fmt(sev, " cpd.al[%2.1zu].col is %2.1zu, cpd.al[%2.1zu].len is %zu, type is %s\n",
+ idx, cpd.al[idx].col, idx, cpd.al[idx].len,
+ get_token_name(cpd.al[idx].type));
+ }
+
+ log_fmt(sev, "\n");
+ }
+} // align_log_al
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.h
new file mode 100644
index 00000000..8cb2ece8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_log_al.h
@@ -0,0 +1,17 @@
+/**
+ * @file align_log_al.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_LOG_AL_H_INCLUDED
+#define ALIGN_LOG_AL_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+void align_log_al(log_sev_t sev, size_t line);
+
+#endif /* ALIGN_LOG_AL_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.cpp
new file mode 100644
index 00000000..4a3fd689
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.cpp
@@ -0,0 +1,64 @@
+/**
+ * @file align_nl_cont.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_nl_cont.h"
+
+#include "align_add.h"
+#include "uncrustify.h"
+
+
+Chunk *align_nl_cont(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LALNLC, "%s(%d): start on [%s] on line %zu\n",
+ __func__, __LINE__, get_token_name(start->type), start->orig_line);
+
+ // Find the max column
+ ChunkStack cs;
+ size_t max_col = 0;
+ Chunk *pc = start;
+
+ while ( pc->IsNotNullChunk()
+ && chunk_is_not_token(pc, CT_NEWLINE)
+ && chunk_is_not_token(pc, CT_COMMENT_MULTI))
+ {
+ if (chunk_is_token(pc, CT_NL_CONT))
+ {
+ align_add(cs, pc, max_col);
+ }
+ pc = pc->GetNext();
+ }
+ // NL_CONT is always the last thing on a line
+ Chunk *tmp;
+
+ while ((tmp = cs.Pop_Back()) != nullptr)
+ {
+ chunk_flags_set(tmp, PCF_WAS_ALIGNED);
+ tmp->column = max_col;
+ }
+ return(pc);
+} // align_nl_cont
+
+
+void align_backslash_newline(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_not_token(pc, CT_NL_CONT))
+ {
+ pc = pc->GetNextType(CT_NL_CONT, -1);
+ continue;
+ }
+ pc = align_nl_cont(pc);
+ }
+} // align_backslash_newline
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.h
new file mode 100644
index 00000000..7db6bad6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_nl_cont.h
@@ -0,0 +1,33 @@
+/**
+ * @file align_nl_cont.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_NL_COUNT_H_INCLUDED
+#define ALIGN_NL_COUNT_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+#include "chunk.h"
+
+/**
+ * For a series of lines ending in backslash-newline, align them.
+ * The series ends when a newline or multi-line C comment is encountered.
+ *
+ * @param start Start point
+ *
+ * @return pointer the last item looked at (nullptr/newline/comment)
+ */
+Chunk *align_nl_cont(Chunk *start);
+
+/**
+ * Aligns all backslash-newline combos in the file.
+ * This should be done LAST.
+ */
+void align_backslash_newline(void);
+
+#endif /* ALIGN_NL_COUNT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.cpp
new file mode 100644
index 00000000..8c0bc078
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.cpp
@@ -0,0 +1,90 @@
+/**
+ * @file align_oc_decl_colon.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_oc_decl_colon.h"
+
+#include "align_stack.h"
+#include "chunk.h"
+
+
+using namespace uncrustify;
+
+
+void align_oc_decl_colon(void)
+{
+ LOG_FUNC_ENTRY();
+
+ bool did_line;
+ AlignStack cas; // for the colons
+ AlignStack nas; // for the parameter label
+
+ cas.Start(4);
+ nas.Start(4);
+ nas.m_right_align = !options::align_on_tabstop();
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_not_token(pc, CT_OC_SCOPE))
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+ nas.Reset();
+ cas.Reset();
+
+ size_t level = pc->level;
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ did_line = false;
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= level)
+ {
+ // The declaration ends with an open brace or semicolon
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_semicolon(pc))
+ {
+ break;
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ nas.NewLines(pc->nl_count);
+ cas.NewLines(pc->nl_count);
+ did_line = false;
+ }
+ else if ( !did_line
+ && chunk_is_token(pc, CT_OC_COLON))
+ {
+ cas.Add(pc);
+
+ Chunk *tmp = pc->GetPrev(E_Scope::PREPROC);
+ Chunk *tmp2 = tmp->GetPrevNcNnl(E_Scope::PREPROC);
+
+ // Check for an un-labeled parameter
+ if ( ( chunk_is_token(tmp, CT_WORD)
+ || chunk_is_token(tmp, CT_TYPE)
+ || chunk_is_token(tmp, CT_OC_MSG_DECL)
+ || chunk_is_token(tmp, CT_OC_MSG_SPEC))
+ && ( chunk_is_token(tmp2, CT_WORD)
+ || chunk_is_token(tmp2, CT_TYPE)
+ || chunk_is_token(tmp2, CT_PAREN_CLOSE)))
+ {
+ nas.Add(tmp);
+ }
+ did_line = true;
+ }
+ pc = pc->GetNext(E_Scope::PREPROC);
+ }
+ nas.End();
+ cas.End();
+ }
+} // align_oc_decl_colon
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.h
new file mode 100644
index 00000000..370ee655
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_decl_colon.h
@@ -0,0 +1,21 @@
+/**
+ * @file align_oc_decl_colon.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_OC_DECL_COLON_H_INCLUDED
+#define ALIGN_OC_DECL_COLON_H_INCLUDED
+
+
+/**
+ * Aligns OC declarations on the colon
+ * -(void) doSomething: (NSString*) param1
+ * with: (NSString*) param2
+ */
+void align_oc_decl_colon(void);
+
+#endif /* ALIGN_OC_DECL_COLON_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.cpp
new file mode 100644
index 00000000..7357bb18
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.cpp
@@ -0,0 +1,182 @@
+/**
+ * @file align_oc_msg_colons.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "align_oc_msg_colons.h"
+
+#include "align_stack.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LOCMSG;
+
+using namespace uncrustify;
+
+
+void align_oc_msg_colon(Chunk *so)
+{
+ LOG_FUNC_ENTRY();
+
+ AlignStack nas; // for the parameter tag
+
+ nas.Start(1);
+ nas.Reset();
+ log_rule_B("align_on_tabstop");
+ nas.m_right_align = !options::align_on_tabstop();
+
+ AlignStack cas; // for the colons
+
+ log_rule_B("align_oc_msg_colon_span");
+ size_t span = options::align_oc_msg_colon_span();
+
+ cas.Start(span);
+
+ size_t level = so->level;
+ Chunk *pc = so->GetNextNcNnl(E_Scope::PREPROC);
+
+ bool did_line = false;
+ bool has_colon = false;
+ size_t lcnt = 0; // line count with no colon for span
+ bool first_line = true;
+
+ while ( pc->IsNotNullChunk()
+ && pc->level > level)
+ {
+ if (pc->level > (level + 1))
+ {
+ // do nothing
+ }
+ else if (chunk_is_newline(pc))
+ {
+ if (!has_colon)
+ {
+ ++lcnt;
+ }
+ did_line = false;
+
+ log_rule_B("align_oc_msg_colon_xcode_like");
+
+ if ( options::align_oc_msg_colon_xcode_like()
+ && first_line
+ && !has_colon)
+ {
+ span = 0;
+ }
+ has_colon = !has_colon;
+ first_line = false;
+ }
+ else if ( !did_line
+ && (lcnt < span + 1)
+ && chunk_is_token(pc, CT_OC_COLON))
+ {
+ has_colon = true;
+ cas.Add(pc);
+ Chunk *tmp = pc->GetPrev();
+
+ if ( tmp->IsNotNullChunk()
+ && ( chunk_is_token(tmp, CT_OC_MSG_FUNC)
+ || chunk_is_token(tmp, CT_OC_MSG_NAME)))
+ {
+ nas.Add(tmp);
+ chunk_flags_set(tmp, PCF_DONT_INDENT);
+ }
+ did_line = true;
+ }
+ pc = pc->GetNext(E_Scope::PREPROC);
+ }
+ log_rule_B("align_oc_msg_colon_first");
+ nas.m_skip_first = !options::align_oc_msg_colon_first();
+ cas.m_skip_first = !options::align_oc_msg_colon_first();
+
+ // find the longest args that isn't the first one
+ size_t first_len = 0;
+ size_t mlen = 0;
+ Chunk *longest = nullptr;
+
+ size_t len = nas.m_aligned.Len();
+
+ for (size_t idx = 0; idx < len; idx++)
+ {
+ Chunk *tmp = nas.m_aligned.GetChunk(idx);
+
+ if (tmp != nullptr)
+ {
+ size_t tlen = tmp->str.size();
+
+ if (tlen > mlen)
+ {
+ mlen = tlen;
+
+ if (idx != 0)
+ {
+ longest = tmp;
+ }
+ }
+
+ if (idx == 0)
+ {
+ first_len = tlen + 1;
+ }
+ }
+ }
+
+ // add spaces before the longest arg
+ log_rule_B("indent_oc_msg_colon");
+ len = options::indent_oc_msg_colon();
+ size_t len_diff = mlen - first_len;
+
+ log_rule_B("indent_columns");
+ size_t indent_size = options::indent_columns();
+
+ // Align with first colon if possible by removing spaces
+ log_rule_B("indent_oc_msg_prioritize_first_colon");
+
+ if ( longest != nullptr
+ && options::indent_oc_msg_prioritize_first_colon()
+ && len_diff > 0
+ && ( (longest->column >= len_diff)
+ && (longest->column - len_diff) > (longest->brace_level * indent_size)))
+ {
+ longest->column -= len_diff;
+ }
+ else if ( longest != nullptr
+ && len > 0)
+ {
+ Chunk chunk;
+
+ set_chunk_type(&chunk, CT_SPACE);
+ set_chunk_parent(&chunk, CT_NONE);
+ chunk.orig_line = longest->orig_line;
+ chunk.orig_col = longest->orig_col;
+ chunk.level = longest->level;
+ chunk.brace_level = longest->brace_level;
+ chunk.flags = longest->flags & PCF_COPY_FLAGS;
+
+ // start at one since we already indent for the '['
+ for (size_t idx = 1; idx < len; idx++)
+ {
+ chunk.str.append(' ');
+ }
+
+ chunk_add_before(&chunk, longest);
+ }
+ nas.End();
+ cas.End();
+} // align_oc_msg_colon
+
+
+void align_oc_msg_colons(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(pc) == CT_OC_MSG)
+ {
+ align_oc_msg_colon(pc);
+ }
+ }
+} // align_oc_msg_colons
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.h
new file mode 100644
index 00000000..4d8ea07d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_colons.h
@@ -0,0 +1,16 @@
+/**
+ * @file align_oc_msg_colons.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_OC_MSG_COLONS_H_INCLUDED
+#define ALIGN_OC_MSG_COLONS_H_INCLUDED
+
+//! Aligns OC messages
+void align_oc_msg_colons(void);
+
+#endif /* ALIGN_OC_MSG_COLONS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.cpp
new file mode 100644
index 00000000..4c7a2dd5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.cpp
@@ -0,0 +1,37 @@
+/**
+ * @file align_oc_msg_spec.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_oc_msg_spec.h"
+
+#include "align_assign.h"
+#include "align_stack.h"
+
+
+void align_oc_msg_spec(size_t span)
+{
+ LOG_FUNC_ENTRY();
+
+ AlignStack as;
+
+ as.Start(span, 0);
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (chunk_is_newline(pc))
+ {
+ as.NewLines(pc->nl_count);
+ }
+ else if (chunk_is_token(pc, CT_OC_MSG_SPEC))
+ {
+ as.Add(pc);
+ }
+ }
+
+ as.End();
+} // void align_oc_msg_spec
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.h
new file mode 100644
index 00000000..b6500a6e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_oc_msg_spec.h
@@ -0,0 +1,18 @@
+/**
+ * @file align_oc_msg_spec.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_OC_MSG_SPEC_H_INCLUDED
+#define ALIGN_OC_MSG_SPEC_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+//! Aligns all function prototypes in the file.
+void align_oc_msg_spec(size_t span);
+
+#endif /* ALIGN_OC_MSG_SPEC_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.cpp
new file mode 100644
index 00000000..b05c0dd9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.cpp
@@ -0,0 +1,110 @@
+/**
+ * @file align_preprocessor.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_preprocessor.h"
+
+#include "align_stack.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALPP;
+
+using namespace uncrustify;
+
+
+void align_preprocessor(void)
+{
+ LOG_FUNC_ENTRY();
+
+ AlignStack as; // value macros
+
+ log_rule_B("align_pp_define_span");
+ as.Start(options::align_pp_define_span());
+ log_rule_B("align_pp_define_gap");
+ as.m_gap = options::align_pp_define_gap();
+ AlignStack *cur_as = &as;
+
+ AlignStack asf; // function macros
+
+ log_rule_B("align_pp_define_span");
+ asf.Start(options::align_pp_define_span());
+ log_rule_B("align_pp_define_gap");
+ asf.m_gap = options::align_pp_define_gap();
+
+ Chunk *pc = Chunk::GetHead();
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ // Note: not counting back-slash newline combos
+ if (chunk_is_token(pc, CT_NEWLINE)) // mind the gap: chunk_is_newline(pc) is NOT the same!
+ {
+ as.NewLines(pc->nl_count);
+ asf.NewLines(pc->nl_count);
+ }
+
+ // If we aren't on a 'define', then skip to the next non-comment
+ if (chunk_is_not_token(pc, CT_PP_DEFINE))
+ {
+ pc = pc->GetNextNc();
+ continue;
+ }
+ // step past the 'define'
+ pc = pc->GetNextNc();
+
+ if (pc->IsNullChunk())
+ {
+ // coveralls will complain here. There are no example for that.
+ // see https://en.wikipedia.org/wiki/Robustness_principle
+ break;
+ }
+ LOG_FMT(LALPP, "%s(%d): define (%s) on line %zu col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+
+ cur_as = &as;
+
+ if (chunk_is_token(pc, CT_MACRO_FUNC))
+ {
+ log_rule_B("align_pp_define_together");
+
+ if (!options::align_pp_define_together())
+ {
+ cur_as = &asf;
+ }
+ // Skip to the close parenthesis
+ pc = pc->GetNextNc(); // point to open (
+ pc = pc->GetNextType(CT_FPAREN_CLOSE, pc->level);
+
+ LOG_FMT(LALPP, "%s(%d): jumped to (%s) on line %zu col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ }
+ // step to the value past the close parenthesis or the macro name
+ pc = pc->GetNext();
+
+ if (pc->IsNullChunk())
+ {
+ // coveralls will complain here. There are no example for that.
+ // see https://en.wikipedia.org/wiki/Robustness_principle
+ break;
+ }
+
+ /*
+ * don't align anything if the first line ends with a newline before
+ * a value is given
+ */
+ if (!chunk_is_newline(pc))
+ {
+ LOG_FMT(LALPP, "%s(%d): align on '%s', line %zu col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+
+ cur_as->Add(pc);
+ }
+ }
+ as.End();
+ asf.End();
+} // align_preprocessor
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.h
new file mode 100644
index 00000000..ec944587
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_preprocessor.h
@@ -0,0 +1,18 @@
+/**
+ * @file align_preprocessor.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_PREPROCESSOR_H_INCLUDED
+#define ALIGN_PREPROCESSOR_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+//! Scans the whole file for #defines. Aligns all within X lines of each other
+void align_preprocessor(void);
+
+#endif /* ALIGN_PREPROCESSOR_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.cpp
new file mode 100644
index 00000000..588195da
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.cpp
@@ -0,0 +1,283 @@
+/**
+ * @file align_same_func_call_params.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_same_func_call_params.h"
+
+#include "align_stack.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LASFCP;
+
+using namespace uncrustify;
+
+
+void align_same_func_call_params(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc;
+ Chunk *align_root = Chunk::NullChunkPtr;
+ Chunk *align_cur = Chunk::NullChunkPtr;
+ size_t align_len = 0;
+ size_t span = 3;
+ size_t thresh;
+ Chunk *align_fcn;
+ unc_text align_fcn_name;
+ unc_text align_root_name;
+ deque<Chunk *> chunks;
+ deque<AlignStack> array_of_AlignStack;
+ AlignStack fcn_as;
+ const char *add_str;
+
+ // Default span is 3 if align_same_func_call_params is true
+ log_rule_B("align_same_func_call_params_span");
+
+ if (options::align_same_func_call_params_span() > 0)
+ {
+ span = options::align_same_func_call_params_span();
+ }
+ log_rule_B("align_same_func_call_params_thresh");
+ thresh = options::align_same_func_call_params_thresh();
+
+ fcn_as.Start(span, thresh);
+ LOG_FMT(LAS, "%s(%d): (3): span is %zu, thresh is %zu\n",
+ __func__, __LINE__, span, thresh);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (chunk_is_newline(pc))
+ {
+ LOG_FMT(LAS, "%s(%d): orig_line is %zu, <Newline>\n", __func__, __LINE__, pc->orig_line);
+ }
+ else
+ {
+ LOG_FMT(LAS, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ }
+
+ if (chunk_is_not_token(pc, CT_FUNC_CALL))
+ {
+ if (chunk_is_newline(pc))
+ {
+ for (auto &as_v : array_of_AlignStack)
+ {
+ as_v.NewLines(pc->nl_count);
+ }
+
+ fcn_as.NewLines(pc->nl_count);
+ }
+ else
+ {
+ // if we drop below the brace level that started it, we are done
+ if ( align_root->IsNotNullChunk()
+ && align_root->brace_level > pc->brace_level)
+ {
+ LOG_FMT(LASFCP, " ++ (drop) Ended with %zu fcns\n", align_len);
+
+ // Flush it all!
+ fcn_as.Flush();
+
+ for (auto &as_v : array_of_AlignStack)
+ {
+ as_v.Flush();
+ }
+
+ align_root = Chunk::NullChunkPtr;
+ }
+ }
+ continue;
+ }
+ // Only align function calls that are right after a newline
+ Chunk *prev = pc->GetPrev();
+
+ while ( chunk_is_token(prev, CT_MEMBER)
+ || chunk_is_token(prev, CT_DC_MEMBER))
+ {
+ Chunk *tprev = prev->GetPrev();
+
+ if (chunk_is_not_token(tprev, CT_TYPE))
+ {
+ prev = tprev;
+ break;
+ }
+ prev = tprev->GetPrev();
+ }
+
+ if (!chunk_is_newline(prev))
+ {
+ continue;
+ }
+ prev = prev->GetNext();
+ align_fcn = prev;
+ align_fcn_name.clear();
+ LOG_FMT(LASFCP, "%s(%d):\n", __func__, __LINE__);
+
+ while (prev != pc)
+ {
+ align_fcn_name += prev->str;
+ prev = prev->GetNext();
+ }
+ align_fcn_name += pc->str;
+ LOG_FMT(LASFCP, "%s(%d): Func Call found at orig_line is %zu, orig_col is %zu, c_str() '%s'\n",
+ __func__, __LINE__, align_fcn->orig_line,
+ align_fcn->orig_col,
+ align_fcn_name.c_str());
+
+ add_str = nullptr;
+
+ if (align_root->IsNotNullChunk())
+ {
+ // Issue # 1395
+ // can only align functions on the same brace level
+ // and on the same level
+ LOG_FMT(LASFCP, "%s(%d):align_root is not nullptr\n", __func__, __LINE__);
+
+ if ( align_root->brace_level == pc->brace_level
+ && align_root->level == pc->level
+ && align_fcn_name.equals(align_root_name))
+ {
+ fcn_as.Add(pc);
+ align_cur->align.next = pc;
+ align_cur = pc;
+ align_len++;
+ add_str = " Add";
+ }
+ else
+ {
+ LOG_FMT(LASFCP, " ++ Ended with %zu fcns\n", align_len);
+
+ // Flush it all!
+ fcn_as.Flush();
+
+ for (auto &as_v : array_of_AlignStack)
+ {
+ as_v.Flush();
+ }
+
+ align_root = Chunk::NullChunkPtr;
+ }
+ }
+ LOG_FMT(LASFCP, "%s(%d):\n", __func__, __LINE__);
+
+ if (align_root->IsNullChunk())
+ {
+ LOG_FMT(LASFCP, "%s(%d):align_root is null chunk, Add pc '%s'\n", __func__, __LINE__, pc->Text());
+ fcn_as.Add(pc);
+ align_root = align_fcn;
+ align_root_name = align_fcn_name;
+ align_cur = pc;
+ align_len = 1;
+ add_str = "Start";
+ }
+ LOG_FMT(LASFCP, "%s(%d):\n", __func__, __LINE__);
+
+ if (add_str != nullptr)
+ {
+ LOG_FMT(LASFCP, "%s(%d): %s with function '%s', on orig_line %zu, ",
+ __func__, __LINE__, add_str, align_fcn_name.c_str(), pc->orig_line);
+ align_params(pc, chunks);
+ LOG_FMT(LASFCP, "%zu items:", chunks.size());
+
+ for (size_t idx = 0; idx < chunks.size(); idx++)
+ {
+ // show the chunk(s)
+ LOG_FMT(LASFCP, " [%s]", chunks[idx]->Text());
+
+ if (idx < chunks.size() - 1)
+ {
+ LOG_FMT(LASFCP, ",");
+ }
+ }
+
+ LOG_FMT(LASFCP, "\n");
+
+ for (size_t idx = 0; idx < chunks.size(); idx++)
+ {
+ LOG_FMT(LASFCP, "%s(%d): chunks[%zu] is [%s]\n", __func__, __LINE__, idx, chunks[idx]->Text());
+ // Issue #2368
+
+ if (array_of_AlignStack.size() > idx)
+ {
+ // Issue #2368
+ array_of_AlignStack[idx].m_right_align = false;
+ }
+
+ if (idx >= array_of_AlignStack.size())
+ {
+ LOG_FMT(LASFCP, "%s(%d): resize with %zu\n", __func__, __LINE__, idx + 1);
+ array_of_AlignStack.resize(idx + 1);
+ LOG_FMT(LASFCP, "%s(%d): Start for the new\n", __func__, __LINE__);
+ array_of_AlignStack[idx].Start(span, thresh);
+
+ log_rule_B("align_number_right");
+
+ if (!options::align_number_right())
+ {
+ if ( chunk_is_token(chunks[idx], CT_NUMBER_FP)
+ || chunk_is_token(chunks[idx], CT_NUMBER)
+ || chunk_is_token(chunks[idx], CT_POS)
+ || chunk_is_token(chunks[idx], CT_NEG))
+ {
+ log_rule_B("align_on_tabstop");
+ array_of_AlignStack[idx].m_right_align = !options::align_on_tabstop();
+ }
+ }
+ }
+ LOG_FMT(LASFCP, "%s(%d): save the chunk %s\n", __func__, __LINE__, chunks[idx]->Text());
+ array_of_AlignStack[idx].Add(chunks[idx]);
+ }
+ }
+ }
+
+ if (align_len > 1)
+ {
+ LOG_FMT(LASFCP, " ++ Ended with %zu fcns\n", align_len);
+ fcn_as.End();
+
+ for (auto &as_v : array_of_AlignStack)
+ {
+ as_v.End();
+ }
+ }
+} // align_same_func_call_params
+
+
+void align_params(Chunk *start, deque<Chunk *> &chunks)
+{
+ LOG_FUNC_ENTRY();
+
+ chunks.clear();
+
+ bool hit_comma = true;
+ Chunk *pc = start->GetNextType(CT_FPAREN_OPEN, start->level);
+
+ while ((pc = pc->GetNext())->IsNotNullChunk())
+ {
+ if ( chunk_is_newline(pc)
+ || chunk_is_token(pc, CT_SEMICOLON)
+ || ( chunk_is_token(pc, CT_FPAREN_CLOSE)
+ && pc->level == start->level))
+ {
+ break;
+ }
+
+ if (pc->level == (start->level + 1))
+ {
+ if (hit_comma)
+ {
+ chunks.push_back(pc);
+ hit_comma = false;
+ }
+ else if (chunk_is_token(pc, CT_COMMA))
+ {
+ hit_comma = true;
+ }
+ }
+ }
+} // void align_params
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.h
new file mode 100644
index 00000000..73420292
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_same_func_call_params.h
@@ -0,0 +1,22 @@
+/**
+ * @file align_same_func_call_params.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_SAME_FUNC_CALL_PARAMS_H_INCLUDED
+#define ALIGN_SAME_FUNC_CALL_PARAMS_H_INCLUDED
+
+#include "ChunkStack.h"
+#include <deque>
+
+using namespace std;
+
+void align_params(Chunk *start, deque<Chunk *> &chunks);
+
+void align_same_func_call_params(void);
+
+#endif /* ALIGN_SAME_FUNC_CALL_PARAMS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.cpp
new file mode 100644
index 00000000..e03ca3df
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.cpp
@@ -0,0 +1,667 @@
+/**
+ * @file align_stack.cpp
+ * Manages an align stack, which is just a pair of chunk stacks.
+ * There can be at most 1 item per line in the stack.
+ * The seqnum is actually a line counter.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_stack.h"
+
+#include "align_tab_column.h"
+#include "indent.h"
+#include "space.h"
+#include "unc_tools.h" // to get stackID and get_A_Number()
+
+
+constexpr static auto LCURRENT = LAS;
+
+using namespace uncrustify;
+
+using std::numeric_limits;
+
+
+void AlignStack::Start(size_t span, int thresh)
+{
+ stackID = get_A_Number(); // for debugging purpose only
+
+ // produces much more log output. Use it only debugging purpose
+ //WITH_STACKID_DEBUG;
+
+ //LOG_FMT(LAS, "AlignStack::Start(%d):m_aligned.Reset()\n", __LINE__);
+ m_aligned.Reset();
+ //LOG_FMT(LAS, "AlignStack::Start(%d):m_skipped.Reset()\n", __LINE__);
+ m_skipped.Reset();
+
+ if (thresh > 0)
+ {
+ m_absolute_thresh = false;
+ m_thresh = thresh;
+ }
+ else
+ {
+ m_absolute_thresh = true;
+ m_thresh = -thresh;
+ }
+ m_span = span;
+ m_min_col = numeric_limits<size_t>::max();
+ m_max_col = 0;
+ m_nl_seqnum = 0;
+ m_seqnum = 0;
+ m_gap = 0;
+ m_right_align = false;
+ m_star_style = SS_IGNORE;
+ m_amp_style = SS_IGNORE;
+}
+
+
+void AlignStack::ReAddSkipped()
+{
+ // produces much more log output. Use it only debugging purpose
+ //WITH_STACKID_DEBUG;
+
+ if (m_skipped.Empty())
+ {
+ return;
+ }
+ // Make a copy of the ChunkStack and clear m_skipped
+ m_scratch.Set(m_skipped);
+ //LOG_FMT(LAS, "AlignStack::ReAddSkipped(%d):m_skipped.Reset()\n", __LINE__);
+ m_skipped.Reset();
+
+ // Need to add them in order so that m_nl_seqnum is correct
+ for (size_t idx = 0; idx < m_scratch.Len(); idx++)
+ {
+ const ChunkStack::Entry *ce = m_scratch.Get(idx);
+ LOG_FMT(LAS, "AlignStack::ReAddSkipped [%zu] - ", ce->m_seqnum);
+ Add(ce->m_pc, ce->m_seqnum);
+ }
+
+ NewLines(0); // Check to see if we need to flush right away
+}
+
+
+void AlignStack::Add(Chunk *start, size_t seqnum)
+{
+ // produces much more log output. Use it only debugging purpose
+ //WITH_STACKID_DEBUG;
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LAS, "AlignStack::%s(%d): Candidate is '%s': orig_line is %zu, column is %zu, type is %s, level is %zu\n",
+ __func__, __LINE__, start->Text(), start->orig_line, start->column, get_token_name(start->type), start->level);
+ LOG_FMT(LAS, "AlignStack::%s(%d): seqnum is %zu\n", __func__, __LINE__, seqnum);
+
+ // Assign a seqnum if needed
+ if (seqnum == 0)
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): m_seqnum is %zu\n", __func__, __LINE__, m_seqnum);
+ seqnum = m_seqnum;
+ LOG_FMT(LAS, "AlignStack::%s(%d): seqnum is %zu\n", __func__, __LINE__, seqnum);
+ }
+ m_last_added = 0;
+
+ // Threshold check should begin after
+ // tighten down the spacing between ref and start
+
+ /*
+ * SS_IGNORE: no special handling of '*' or '&', only 'foo' is aligned
+ * void foo; // gap=5, 'foo' is aligned
+ * char * foo; // gap=3, 'foo' is aligned
+ * foomatic foo; // gap=1, 'foo' is aligned
+ * The gap is the columns between 'foo' and the previous token.
+ * [void - foo], ['*' - foo], etc
+ *
+ * SS_INCLUDE: - space between variable and '*' or '&' is eaten
+ * void foo; // gap=5, 'foo' is aligned
+ * char *foo; // gap=5, '*' is aligned
+ * foomatic foo; // gap=1, 'foo' is aligned
+ * The gap is the columns between the first '*' or '&' before foo
+ * and the previous token. [void - foo], [char - '*'], etc
+ *
+ * SS_DANGLE: - space between variable and '*' or '&' is eaten
+ * void foo; // gap=5
+ * char *bar; // gap=5, as the '*' doesn't count
+ * foomatic foo; // gap=1
+ * The gap is the columns between 'foo' and the chunk before the first
+ * '*' or '&'. [void - foo], [char - bar], etc
+ *
+ * If the gap < m_gap, then the column is bumped out by the difference.
+ * So, if m_gap is 2, then the above would be:
+ * SS_IGNORE:
+ * void foo; // gap=6
+ * char * foo; // gap=4
+ * foomatic foo; // gap=2
+ * SS_INCLUDE:
+ * void foo; // gap=6
+ * char *foo; // gap=6
+ * foomatic foo; // gap=2
+ * SS_DANGLE:
+ * void foo; // gap=6
+ * char *bar; // gap=6, as the '*' doesn't count
+ * foomatic foo; // gap=2
+ * Right aligned numbers:
+ * #define A -1
+ * #define B 631
+ * #define C 3
+ * Left aligned numbers:
+ * #define A -1
+ * #define B 631
+ * #define C 3
+ *
+ * In the code below, pc is set to the item that is aligned.
+ * In the above examples, that is 'foo', '*', '-', or 63.
+ *
+ * Ref is set to the last part of the type.
+ * In the above examples, that is 'void', 'char', 'foomatic', 'A', or 'B'.
+ *
+ * The '*' and '&' can float between the two.
+ *
+ * If align_on_tabstop=true, then SS_DANGLE is changed to SS_INCLUDE.
+ */
+ log_rule_B("align_on_tabstop");
+
+ if ( options::align_on_tabstop()
+ && m_star_style == SS_DANGLE)
+ {
+ m_star_style = SS_INCLUDE;
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%d): m_star_style is %s\n",
+ __func__, __LINE__, get_StarStyle_name(m_star_style));
+ // Find ref. Back up to the real item that is aligned.
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ if (start != nullptr)
+ {
+ prev = start;
+ }
+
+ while ( (prev = prev->GetPrev()) != nullptr
+ && prev->IsNotNullChunk()
+ && ( chunk_is_ptr_operator(prev)
+ || chunk_is_token(prev, CT_TPAREN_OPEN)))
+ {
+ // do nothing - we want prev when this exits
+ }
+
+ if (prev == nullptr)
+ {
+ return;
+ }
+ Chunk *ref = prev;
+
+ if (chunk_is_newline(ref))
+ {
+ ref = ref->GetNext();
+ }
+ // Find the item that we are going to align.
+ Chunk *ali = Chunk::NullChunkPtr;
+
+ if (start != nullptr)
+ {
+ ali = start;
+ }
+
+ if (m_star_style != SS_IGNORE)
+ {
+ // back up to the first '*' or '^' preceding the token
+ Chunk *tmp_prev = ali->GetPrev();
+
+ while ( tmp_prev->IsStar()
+ || chunk_is_msref(tmp_prev))
+ {
+ ali = tmp_prev;
+ tmp_prev = ali->GetPrev();
+ }
+
+ if (chunk_is_token(tmp_prev, CT_TPAREN_OPEN))
+ {
+ ali = tmp_prev;
+ tmp_prev = ali->GetPrev();
+ // this is correct, even Coverity says:
+ // CID 76021 (#1 of 1): Unused value (UNUSED_VALUE)returned_pointer: Assigning value from
+ // ali->GetPrev(nav_e::ALL) to prev here, but that stored value is overwritten before it can be used.
+ }
+ }
+
+ if (m_amp_style != SS_IGNORE)
+ {
+ // back up to the first '&' preceding the token
+ Chunk *tmp_prev = ali->GetPrev();
+
+ while (chunk_is_addr(tmp_prev))
+ {
+ ali = tmp_prev;
+ tmp_prev = ali->GetPrev();
+ }
+ }
+ log_rule_B("align_keep_extra_space");
+
+ // Tighten down the spacing between ref and start
+ if (!options::align_keep_extra_space())
+ {
+ size_t tmp_col = ref->column;
+ Chunk *tmp = ref;
+ LOG_FMT(LAS, "AlignStack::%s(%d): tmp_col is %zu\n",
+ __func__, __LINE__, tmp_col);
+
+ while ( tmp->IsNotNullChunk()
+ && tmp != start)
+ {
+ Chunk *next = tmp->GetNext();
+
+ if (next->IsNotNullChunk())
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): next->orig_line is %zu, orig_col is %zu, Text() '%s', level is %zu, type is %s\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, next->Text(), next->level, get_token_name(next->type));
+ tmp_col += space_col_align(tmp, next);
+ LOG_FMT(LAS, "AlignStack::%s(%d): next->column is %zu, level is %zu, tmp_col is %zu\n",
+ __func__, __LINE__, next->column, next->level, tmp_col);
+
+ if (next->column != tmp_col)
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): Call align_to_column\n", __func__, __LINE__);
+ align_to_column(next, tmp_col);
+ }
+ }
+ tmp = next;
+ }
+ }
+
+ // Check threshold limits
+ if ( m_max_col == 0
+ || m_thresh == 0
+ || ( ((start->column + m_gap) <= (m_thresh + (m_absolute_thresh ? m_min_col : m_max_col))) // don't use subtraction here to prevent underflow
+ && ( (start->column + m_gap + m_thresh) >= m_max_col // change the expression to mind negative expression
+ || start->column >= m_min_col)))
+ {
+ // we are adding it, so update the newline seqnum
+ if (seqnum > m_nl_seqnum)
+ {
+ m_nl_seqnum = seqnum;
+ }
+ // Set the column adjust and gap
+ size_t col_adj = 0; // Amount the column is shifted for 'dangle' mode
+ size_t gap = 0;
+
+ if (ref != ali)
+ {
+ gap = ali->column - (ref->column + ref->Len());
+ }
+ Chunk *tmp = ali;
+
+ if (chunk_is_token(tmp, CT_TPAREN_OPEN))
+ {
+ tmp = tmp->GetNext();
+ }
+
+ if ( ( tmp->IsStar()
+ && m_star_style == SS_DANGLE)
+ || ( chunk_is_addr(tmp)
+ && m_amp_style == SS_DANGLE)
+ || ( chunk_is_nullable(tmp)
+ && (m_star_style == SS_DANGLE))
+ || ( chunk_is_msref(tmp)
+ && m_star_style == SS_DANGLE)) // TODO: add m_msref_style
+ {
+ col_adj = start->column - ali->column;
+ gap = start->column - (ref->column + ref->Len());
+ }
+ // See if this pushes out the max_col
+ const size_t endcol = ali->column + col_adj
+ + (gap < m_gap ? m_gap - gap : 0);
+
+ ali->align.col_adj = col_adj;
+ ali->align.ref = ref;
+ ali->align.start = start;
+ m_aligned.Push_Back(ali, seqnum);
+ m_last_added = 1;
+
+ // Issue #2278
+ if (chunk_is_token(ali, CT_PTR_TYPE))
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): Add-[%s][%s]: ali->orig_line is %zu, column is %zu, type is %s, level is %zu\n",
+ __func__, __LINE__, ali->Text(), start->Text(), ali->orig_line, ali->column, get_token_name(ali->type), ali->level);
+ }
+ else
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): Add-[%s]: ali->orig_line is %zu, column is %zu, type is %s, level is %zu\n",
+ __func__, __LINE__, ali->Text(), ali->orig_line, ali->column, get_token_name(ali->type), ali->level);
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%d): ali->align.col_adj is %d, ref '%s', endcol is %zu\n",
+ __func__, __LINE__, ali->align.col_adj, ref->Text(), endcol);
+
+ if (m_min_col > endcol)
+ {
+ m_min_col = endcol;
+ }
+
+ if (endcol > m_max_col)
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): Add-aligned: seqnum is %zu, m_nl_seqnum is %zu, m_seqnum is %zu\n",
+ __func__, __LINE__, seqnum, m_nl_seqnum, m_seqnum);
+ LOG_FMT(LAS, "AlignStack::%s(%d): ali->orig_line is %zu, ali->column is %zu, max_col old is %zu, new is %zu, m_min_col is %zu\n",
+ __func__, __LINE__, ali->orig_line, ali->column, m_max_col, endcol, m_min_col);
+ m_max_col = endcol;
+
+ /*
+ * If there were any entries that were skipped, re-add them as they
+ * may now be within the threshold
+ */
+ if (!m_skipped.Empty())
+ {
+ ReAddSkipped();
+ }
+ }
+ else
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): Add-aligned: seqnum is %zu, m_nl_seqnum is %zu, m_seqnum is %zu\n",
+ __func__, __LINE__, seqnum, m_nl_seqnum, m_seqnum);
+ LOG_FMT(LAS, "AlignStack::%s(%d): ali->orig_line is %zu, ali->column is %zu, max_col old is %zu, new is %zu, m_min_col is %zu\n",
+ __func__, __LINE__, ali->orig_line, ali->column, m_max_col, endcol, m_min_col);
+ }
+ }
+ else
+ {
+ // The threshold check failed, so add it to the skipped list
+ m_skipped.Push_Back(start, seqnum);
+ m_last_added = 2;
+
+ LOG_FMT(LAS, "AlignStack::Add-skipped [%zu/%zu/%zu]: line %zu, col %zu <= %zu + %zu\n",
+ seqnum, m_nl_seqnum, m_seqnum,
+ start->orig_line, start->column, m_max_col, m_thresh);
+ }
+ // produces much more log output. Use it only debugging purpose
+ //WITH_STACKID_DEBUG;
+} // AlignStack::Add
+
+
+void AlignStack::NewLines(size_t cnt)
+{
+ // produces much more log output. Use it only debugging purpose
+ //WITH_STACKID_DEBUG;
+
+ if (m_aligned.Empty())
+ {
+ //LOG_FMT(LAS, "AlignStack::Newlines(%d): nothing to do, is empty\n", __LINE__);
+ return;
+ }
+ LOG_FMT(LAS, "AlignStack::Newlines(%d): cnt is %zu\n", __LINE__, cnt);
+ m_seqnum += cnt;
+ LOG_FMT(LAS, "AlignStack::Newlines(%d): m_seqnum is %zu, m_nl_seqnum is %zu, m_span is %zu\n",
+ __LINE__, m_seqnum, m_nl_seqnum, m_span);
+
+ if (m_seqnum > (m_nl_seqnum + m_span))
+ {
+ LOG_FMT(LAS, "AlignStack::Newlines(%d): cnt is %zu\n", __LINE__, cnt);
+ Flush();
+ }
+}
+
+
+void AlignStack::Flush()
+{
+ // produces much more log output. Use it only debugging purpose
+ //WITH_STACKID_DEBUG;
+
+ LOG_FMT(LAS, "AlignStack::%s(%d): Len() is %zu\n",
+ __func__, __LINE__, Len());
+
+ if (Len() > 0)
+ {
+ LOG_FMT(LAS, " (min is %zu, max is %zu)\n",
+ m_min_col, m_max_col);
+ }
+
+ if (Len() == 1)
+ {
+ // check if we have *one* typedef in the line
+ Chunk *pc = m_aligned.Get(0)->m_pc;
+ Chunk *temp = pc->GetPrevType(CT_TYPEDEF, pc->level);
+
+ if (temp->IsNotNullChunk())
+ {
+ if (pc->orig_line == temp->orig_line)
+ {
+ // reset the gap only for *this* stack
+ m_gap = 1;
+ }
+ }
+ }
+ m_last_added = 0;
+ m_max_col = 0;
+
+ // produces much more log output. Use it only debugging purpose
+ //WITH_STACKID_DEBUG;
+ LOG_FMT(LAS, "AlignStack::%s(%d): Debug the stack, Len is %zu\n",
+ __func__, __LINE__, Len());
+
+ for (size_t idx = 0; idx < Len(); idx++)
+ {
+ Chunk *pc = m_aligned.Get(idx)->m_pc;
+ LOG_FMT(LAS, "AlignStack::%s(%d): idx is %zu, pc->Text() is '%s', pc->align.col_adj is %d\n",
+ __func__, __LINE__, idx, pc->Text(), pc->align.col_adj);
+ }
+
+ // Recalculate the max_col - it may have shifted since the last Add()
+ for (size_t idx = 0; idx < Len(); idx++)
+ {
+ Chunk *pc = m_aligned.Get(idx)->m_pc;
+
+ // Set the column adjust and gap
+ size_t col_adj = 0;
+ size_t gap = 0;
+
+ if (pc != pc->align.ref)
+ {
+ gap = pc->column - (pc->align.ref->column + pc->align.ref->Len());
+ }
+
+ if (m_star_style == SS_DANGLE)
+ {
+ Chunk *tmp = (chunk_is_token(pc, CT_TPAREN_OPEN)) ? pc->GetNext() : pc;
+
+ if (chunk_is_ptr_operator(tmp))
+ {
+ col_adj = pc->align.start->column - pc->column;
+ gap = pc->align.start->column - (pc->align.ref->column + pc->align.ref->Len());
+ }
+ }
+
+ if (m_right_align)
+ {
+ // Adjust the width for signed numbers
+ if (pc->align.start != nullptr)
+ {
+ size_t start_len = pc->align.start->Len();
+
+ if (pc->align.start->type == CT_NEG)
+ {
+ Chunk *next = pc->align.start->GetNext();
+
+ if (chunk_is_token(next, CT_NUMBER))
+ {
+ start_len += next->Len();
+ }
+ }
+ col_adj += start_len;
+ }
+ }
+ pc->align.col_adj = col_adj;
+
+ // See if this pushes out the max_col
+ const size_t endcol = pc->column + col_adj
+ + (gap < m_gap ? m_gap - gap : 0);
+
+ if (endcol > m_max_col)
+ {
+ m_max_col = endcol;
+ }
+ }
+
+ log_rule_B("align_on_tabstop");
+
+ if ( options::align_on_tabstop()
+ && Len() > 1)
+ {
+ m_max_col = align_tab_column(m_max_col);
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%d): Len() is %zu\n",
+ __func__, __LINE__, Len());
+
+ const ChunkStack::Entry *ce = nullptr;
+
+ for (size_t idx = 0; idx < Len(); idx++)
+ {
+ ce = m_aligned.Get(idx);
+ LOG_FMT(LAS, "AlignStack::%s(%d): idx is %zu, ce->m_pc->Text() is '%s', orig_line is %zu, orig_col is %zu, align.col_adj is %d\n",
+ __func__, __LINE__, idx, ce->m_pc->Text(), ce->m_pc->orig_line, ce->m_pc->orig_col, ce->m_pc->align.col_adj);
+ }
+
+ for (size_t idx = 0; idx < Len(); idx++)
+ {
+ ce = m_aligned.Get(idx);
+ Chunk *pc = ce->m_pc;
+
+ const size_t tmp_col = m_max_col - pc->align.col_adj;
+
+ if (idx == 0)
+ {
+ if ( m_skip_first
+ && pc->column != tmp_col)
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): orig_line is %zu, orig_col is %zu, dropping first item due to skip_first\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ m_skip_first = false;
+ m_aligned.Pop_Front();
+ Flush();
+ m_skip_first = true;
+ return;
+ }
+ chunk_flags_set(pc, PCF_ALIGN_START);
+
+ pc->align.right_align = m_right_align;
+ pc->align.amp_style = m_amp_style;
+ pc->align.star_style = m_star_style;
+ }
+ pc->align.gap = m_gap;
+ pc->align.next = m_aligned.GetChunk(idx + 1);
+
+ // Indent the token, taking col_adj into account
+ LOG_FMT(LAS, "AlignStack::%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', set to col %zu (adj is %d)\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), tmp_col, pc->align.col_adj);
+ align_to_column(pc, tmp_col);
+ }
+
+ size_t last_seqnum = 0;
+
+ if (ce != nullptr)
+ {
+ last_seqnum = ce->m_seqnum;
+ //LOG_FMT(LAS, "AlignStack::Flush(%d):m_aligned.Reset()\n", __LINE__);
+ m_aligned.Reset();
+ }
+ m_min_col = numeric_limits<size_t>::max(); // use unrealistic high numbers
+ m_max_col = 0; // as start value
+
+ if (m_skipped.Empty())
+ {
+ // Nothing was skipped, sync the sequence numbers
+ m_nl_seqnum = m_seqnum;
+ }
+ else
+ {
+ // Remove all items with seqnum < last_seqnum
+ for (size_t idx = 0; idx < m_skipped.Len(); idx++)
+ {
+ if (m_skipped.Get(idx)->m_seqnum < last_seqnum)
+ {
+ m_skipped.Zap(idx);
+ }
+ }
+
+ m_skipped.Collapse();
+
+ ReAddSkipped(); // Add all items from the skipped list
+ }
+} // AlignStack::Flush
+
+
+void AlignStack::Reset()
+{
+ //WITH_STACKID_DEBUG;
+ //LOG_FMT(LAS, "AlignStack::Reset(%d):m_aligned.Reset()\n", __LINE__);
+ m_aligned.Reset();
+ //LOG_FMT(LAS, "AlignStack::Reset(%d):m_skipped.Reset()\n", __LINE__);
+ m_skipped.Reset();
+}
+
+
+void AlignStack::End()
+{
+ //WITH_STACKID_DEBUG;
+
+ if (!m_aligned.Empty())
+ {
+ //LOG_FMT(LAS, "AlignStack::End(%d):\n", __LINE__);
+ Flush();
+ }
+ //LOG_FMT(LAS, "AlignStack::End(%d):m_aligned.Reset()\n", __LINE__);
+ m_aligned.Reset();
+ //LOG_FMT(LAS, "AlignStack::End(%d):m_skipped.Reset()\n", __LINE__);
+ m_skipped.Reset();
+}
+
+
+size_t AlignStack::Len()
+{
+ return(m_aligned.Len());
+}
+
+
+void AlignStack::Debug()
+{
+ //WITH_STACKID_DEBUG;
+
+ size_t length = Len();
+
+ if (length > 0)
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): Debug the stack, Len is %zu\n",
+ __func__, __LINE__, Len());
+
+ for (size_t idx = 0; idx < length; idx++)
+ {
+ Chunk *pc = m_aligned.Get(idx)->m_pc;
+
+ if (chunk_is_token(pc, CT_PTR_TYPE))
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): idx is %zu, [%s][%s]: orig_line is %zu, orig_col is %zu, type is %s, level is %zu, brace_level is %zu\n",
+ __func__, __LINE__, idx, pc->Text(), pc->next->Text(), pc->orig_line, pc->orig_col, get_token_name(pc->type), pc->level, pc->brace_level);
+ }
+ else
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): idx is %zu, [%s]: orig_line is %zu, orig_col is %zu, type is %s, level is %zu, brace_level is %zu\n",
+ __func__, __LINE__, idx, pc->Text(), pc->orig_line, pc->orig_col, get_token_name(pc->type), pc->level, pc->brace_level);
+ }
+ }
+ }
+}
+
+
+const char *AlignStack::get_StarStyle_name(StarStyle star_style)
+{
+ switch (star_style)
+ {
+ case StarStyle::SS_IGNORE:
+ return("SS_IGNORE");
+
+ case StarStyle::SS_INCLUDE:
+ return("SS_INCLUDE");
+
+ case StarStyle::SS_DANGLE:
+ return("SS_DANGLE");
+ }
+ return("?????");
+} // get_StarStyle_name
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.h
new file mode 100644
index 00000000..0aeefd48
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_stack.h
@@ -0,0 +1,154 @@
+/**
+ * @file align_stack.h
+ * Manages an align stack, which is just a pair of chunk stacks with a few
+ * fancy functions.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_STACK_H_INCLUDED
+#define ALIGN_STACK_H_INCLUDED
+
+#include "ChunkStack.h"
+
+#include <limits>
+
+class AlignStack
+{
+public:
+ enum StarStyle
+ {
+ SS_IGNORE, //! don't look for prev stars
+ SS_INCLUDE, //! include prev * before add
+ SS_DANGLE //! include prev * after add
+ };
+
+ ChunkStack m_aligned; //! contains the tokens that are aligned
+ ChunkStack m_skipped; //! contains the tokens sent to Add()
+ size_t m_max_col;
+ size_t m_min_col;
+ size_t m_span;
+ size_t m_thresh;
+ size_t m_seqnum;
+ size_t m_nl_seqnum;
+ size_t m_gap;
+ bool m_right_align;
+ bool m_absolute_thresh;
+ StarStyle m_star_style;
+ StarStyle m_amp_style;
+ bool m_skip_first; //! do not include the first item if it causes it to be indented
+ size_t stackID; //! for debugging purpose only
+
+
+ AlignStack()
+ : m_max_col(0)
+ , m_min_col(0)
+ , m_span(0)
+ , m_thresh(0)
+ , m_seqnum(0)
+ , m_nl_seqnum(0)
+ , m_gap(0)
+ , m_right_align(false)
+ , m_absolute_thresh(false)
+ , m_star_style(SS_IGNORE)
+ , m_amp_style(SS_IGNORE)
+ , m_skip_first(false)
+ , stackID(std::numeric_limits<std::size_t>::max()) // under linux 64 bits: 18446744073709551615
+ , m_last_added(0)
+ {
+ }
+
+
+ AlignStack(const AlignStack &ref)
+ : m_aligned(ref.m_aligned)
+ , m_skipped(ref.m_skipped)
+ , m_max_col(ref.m_max_col)
+ , m_min_col(ref.m_min_col)
+ , m_span(ref.m_span)
+ , m_thresh(ref.m_thresh)
+ , m_seqnum(ref.m_seqnum)
+ , m_nl_seqnum(ref.m_nl_seqnum)
+ , m_gap(ref.m_gap)
+ , m_right_align(ref.m_right_align)
+ , m_absolute_thresh(ref.m_absolute_thresh)
+ , m_star_style(ref.m_star_style)
+ , m_amp_style(ref.m_amp_style)
+ , m_skip_first(ref.m_skip_first)
+ , m_last_added(ref.m_last_added)
+ {
+ }
+
+
+ ~AlignStack()
+ {
+ }
+
+ /**
+ * Resets the two ChunkLists and zeroes local vars.
+ *
+ * @param span The row span limit
+ * @param threshold The column threshold
+ */
+ void Start(size_t span, int threshold = 0);
+
+
+ /**
+ * Adds an entry to the appropriate stack.
+ *
+ * @param pc the chunk
+ * @param seqnum optional sequence number (0=assign one)
+ */
+ void Add(Chunk *pc, size_t seqnum = 0);
+
+
+ //! Adds some newline and calls Flush() if needed
+ void NewLines(size_t cnt);
+
+
+ /**
+ * Aligns all the stuff in m_aligned.
+ * Re-adds 'newer' items in m_skipped.
+ */
+ void Flush();
+
+
+ //! Resets the stack, discarding anything that was previously added
+ void Reset();
+
+
+ //! Aligns everything else and resets the lists.
+ void End();
+
+
+ //! the size of the lists.
+ size_t Len();
+
+
+ //! for debuging purpose only
+ void Debug();
+
+
+ const char *get_StarStyle_name(StarStyle star_style);
+
+protected:
+ size_t m_last_added; //! 0=none, 1=aligned, 2=skipped
+ ChunkStack m_scratch; //! used in ReAddSkipped()
+
+ //! Calls Add on all the skipped items
+ void ReAddSkipped();
+};
+
+#define WITH_STACKID_DEBUG \
+ if (stackID == std::numeric_limits<std::size_t>::max()) \
+ { \
+ fprintf(stderr, "AlignStack::%s(%d): the stack is not ready, Start is missed\n", __func__, __LINE__); \
+ log_flush(true); \
+ exit(EX_SOFTWARE); \
+ } \
+ else \
+ { \
+ LOG_FMT(LAS, "AlignStack::%s(%d): stackID is %zu\n", __func__, __LINE__, stackID); \
+ }
+
+#endif /* ALIGN_STACK_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.cpp
new file mode 100644
index 00000000..9085b9ac
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.cpp
@@ -0,0 +1,34 @@
+/**
+ * @file align_struct_initializers.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_struct_initializers.h"
+
+#include "align_init_brace.h"
+#include "chunk.h"
+
+
+void align_struct_initializers(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if ( chunk_is_token(prev, CT_ASSIGN)
+ && ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || ( language_is_set(LANG_D)
+ && chunk_is_token(pc, CT_SQUARE_OPEN))))
+ {
+ align_init_brace(pc);
+ }
+ pc = pc->GetNextType(CT_BRACE_OPEN, -1);
+ }
+} // align_struct_initializers
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.h
new file mode 100644
index 00000000..1c71d5af
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_struct_initializers.h
@@ -0,0 +1,18 @@
+/**
+ * @file align_struct_initializers.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_STRUCT_INITIALIZERS_H_INCLUDED
+#define ALIGN_STRUCT_INITIALIZERS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+//! Aligns stuff inside a multi-line "= { ... }" sequence.
+void align_struct_initializers(void);
+
+#endif /* ALIGN_STRUCT_INITIALIZERS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.cpp
new file mode 100644
index 00000000..8d91b0ff
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.cpp
@@ -0,0 +1,39 @@
+/**
+ * @file align_tab_column.cpp
+ *
+ * @author Guy Maurel
+ * split from prototypes.h
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_tab_column.h"
+
+#include "prototypes.h"
+
+constexpr static auto LCURRENT = LALIGN;
+
+using namespace uncrustify;
+
+
+/**
+ * Advances to the next tab stop if not currently on one.
+ *
+ * @param col The current column
+ * @return the next tabstop column
+ */
+size_t align_tab_column(size_t col)
+{
+ //if (col <= 0)
+ if (col == 0)
+ {
+ col = 1;
+ }
+ log_rule_B("output_tab_size");
+
+ if ((col % uncrustify::options::output_tab_size()) != 1)
+ {
+ col = next_tab_column(col);
+ }
+ return(col);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.h
new file mode 100644
index 00000000..9e57baa0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tab_column.h
@@ -0,0 +1,23 @@
+/**
+ * @file align_tab_column.h
+ *
+ * @author Guy Maurel
+ * split from prototypes.h
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_TAB_COLUMN_H_INCLUDED
+#define ALIGN_TAB_COLUMN_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+/**
+ * Advances to the next tab stop if not currently on one.
+ *
+ * @param col The current column
+ * @return the next tabstop column
+ */
+size_t align_tab_column(size_t col);
+
+#endif /* ALIGN_TAB_COLUMN_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.cpp
new file mode 100644
index 00000000..5cfd64e5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.cpp
@@ -0,0 +1,187 @@
+/**
+ * @file align_tools.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_tools.h"
+
+#include "space.h"
+#include "uncrustify.h"
+
+
+Chunk *skip_c99_array(Chunk *sq_open)
+{
+ if (chunk_is_token(sq_open, CT_SQUARE_OPEN))
+ {
+ Chunk *tmp = chunk_skip_to_match(sq_open);
+
+ if (tmp == nullptr)
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+ tmp = tmp->GetNextNc();
+
+ if (chunk_is_token(tmp, CT_ASSIGN))
+ {
+ return(tmp->GetNextNc());
+ }
+ }
+ return(nullptr);
+} // skip_c99_array
+
+
+Chunk *scan_ib_line(Chunk *start, bool first_pass)
+{
+ UNUSED(first_pass);
+ LOG_FUNC_ENTRY();
+ Chunk *prev_match = nullptr;
+ size_t idx = 0;
+
+ // Skip past C99 "[xx] =" stuff
+ Chunk *tmp = skip_c99_array(start);
+
+ if (tmp != nullptr)
+ {
+ set_chunk_parent(start, CT_TSQUARE);
+ start = tmp;
+ cpd.al_c99_array = true;
+ }
+ Chunk *pc = start;
+
+ if (pc != nullptr)
+ {
+ LOG_FMT(LSIB, "%s(%d): start: orig_line is %zu, orig_col is %zu, column is %zu, type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->column, get_token_name(pc->type));
+ }
+ else
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ while ( pc->IsNotNullChunk()
+ && !chunk_is_newline(pc)
+ && pc->level >= start->level)
+ {
+ //LOG_FMT(LSIB, "%s: '%s' col %d/%d line %zu\n", __func__,
+ // pc->Text(), pc->column, pc->orig_col, pc->orig_line);
+
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNullChunk()
+ || next->IsComment())
+ {
+ // do nothing
+ }
+ else if ( chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_COMMA))
+ {
+ size_t token_width = space_col_align(pc, next);
+
+ // TODO: need to handle missing structure defs? ie NULL vs { ... } ??
+
+ // Is this a new entry?
+ if (idx >= cpd.al_cnt)
+ {
+ if (idx == 0)
+ {
+ LOG_FMT(LSIB, "%s(%d): Prepare the 'idx's\n", __func__, __LINE__);
+ }
+ LOG_FMT(LSIB, "%s(%d): New idx is %2.1zu, pc->column is %2.1zu, Text() '%s', token_width is %zu, type is %s\n",
+ __func__, __LINE__, idx, pc->column, pc->Text(), token_width, get_token_name(pc->type));
+ cpd.al[cpd.al_cnt].type = pc->type;
+ cpd.al[cpd.al_cnt].col = pc->column;
+ cpd.al[cpd.al_cnt].len = token_width;
+ cpd.al_cnt++;
+
+ if (cpd.al_cnt == uncrustify::limits::AL_SIZE)
+ {
+ fprintf(stderr, "Number of 'entry' to be aligned is too big for the current value %d,\n",
+ uncrustify::limits::AL_SIZE);
+ fprintf(stderr, "at line %zu, column %zu.\n",
+ pc->orig_line, pc->orig_col);
+ fprintf(stderr, "Please make a report.\n");
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ idx++;
+ }
+ else
+ {
+ // expect to match stuff
+ if (cpd.al[idx].type == pc->type)
+ {
+ LOG_FMT(LSIB, "%s(%d): Match? idx is %2.1zu, orig_line is %2.1zu, column is %2.1zu, token_width is %zu, type is %s\n",
+ __func__, __LINE__, idx, pc->orig_line, pc->column, token_width, get_token_name(pc->type));
+
+ // Shift out based on column
+ if (prev_match == nullptr)
+ {
+ if (pc->column > cpd.al[idx].col)
+ {
+ LOG_FMT(LSIB, "%s(%d): [ pc->column (%zu) > cpd.al[%zu].col(%zu) ] \n",
+ __func__, __LINE__, pc->column, idx, cpd.al[idx].col);
+
+ ib_shift_out(idx, pc->column - cpd.al[idx].col);
+ cpd.al[idx].col = pc->column;
+ }
+ }
+ else if (idx > 0)
+ {
+ LOG_FMT(LSIB, "%s(%d): prev_match '%s', prev_match->orig_line is %zu, prev_match->orig_col is %zu\n",
+ __func__, __LINE__, prev_match->Text(), prev_match->orig_line, prev_match->orig_col);
+ int min_col_diff = pc->column - prev_match->column;
+ int cur_col_diff = cpd.al[idx].col - cpd.al[idx - 1].col;
+
+ if (cur_col_diff < min_col_diff)
+ {
+ LOG_FMT(LSIB, "%s(%d): pc->orig_line is %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ ib_shift_out(idx, min_col_diff - cur_col_diff);
+ }
+ }
+ LOG_FMT(LSIB, "%s(%d): at ende of the loop: now is col %zu, len is %zu\n",
+ __func__, __LINE__, cpd.al[idx].col, cpd.al[idx].len);
+ idx++;
+ }
+ }
+ prev_match = pc;
+ }
+ pc = pc->GetNextNc();
+ }
+ return(pc);
+} // scan_ib_line
+
+
+void ib_shift_out(size_t idx, size_t num)
+{
+ while (idx < cpd.al_cnt)
+ {
+ cpd.al[idx].col += num;
+ idx++;
+ }
+} // ib_shift_out
+
+
+Chunk *step_back_over_member(Chunk *pc)
+{
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ Chunk *tmp = pc->GetPrevNcNnl();
+
+ // Skip over any class stuff: bool CFoo::bar()
+ while ( tmp->IsNotNullChunk()
+ && chunk_is_token(tmp, CT_DC_MEMBER))
+ {
+ pc = tmp->GetPrevNcNnl();
+ tmp = pc->GetPrevNcNnl();
+ }
+ return(pc);
+} // step_back_over_member
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.h
new file mode 100644
index 00000000..fe059dd5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_tools.h
@@ -0,0 +1,48 @@
+/**
+ * @file align_tools.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_TOOLS_H_INCLUDED
+#define ALIGN_TOOLS_H_INCLUDED
+
+#include "chunk.h"
+#include "uncrustify_types.h"
+
+
+/**
+ * @brief return the chunk the follows after a C array
+ *
+ * The provided chunk is considered an array if it is an opening square
+ * (CT_SQUARE_OPEN) and the matching close is followed by an equal sign '='
+ *
+ * Example: array[25] = 12;
+ * /|\ /|\
+ * | |
+ * provided chunk has to point to [ |
+ * returned chunk points to 12
+ *
+ * @param chunk chunk to operate on
+ *
+ * @return the chunk after the '=' if the check succeeds
+ * @return nullptr in all other cases
+ */
+Chunk *skip_c99_array(Chunk *sq_open);
+
+/**
+ * Scans a line for stuff to align on.
+ *
+ * We trigger on BRACE_OPEN, FPAREN_OPEN, ASSIGN, and COMMA.
+ * We want to align the NEXT item.
+ */
+Chunk *scan_ib_line(Chunk *start, bool first_pass);
+
+void ib_shift_out(size_t idx, size_t num);
+
+Chunk *step_back_over_member(Chunk *pc);
+
+#endif /* ALIGN_TOOLS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.cpp
new file mode 100644
index 00000000..7da86018
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.cpp
@@ -0,0 +1,237 @@
+/**
+ * @file align_trailing_comments.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_trailing_comments.h"
+
+#include "align_add.h"
+#include "align_tab_column.h"
+#include "indent.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALTC;
+
+using namespace uncrustify;
+
+
+void align_stack(ChunkStack &cs, size_t col, bool align_single, log_sev_t sev)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("align_on_tabstop");
+
+ if (options::align_on_tabstop())
+ {
+ col = align_tab_column(col);
+ }
+
+ if ( (cs.Len() > 1)
+ || ( align_single
+ && (cs.Len() == 1)))
+ {
+ LOG_FMT(sev, "%s(%d): max_col=%zu\n", __func__, __LINE__, col);
+ Chunk *pc;
+
+ while ((pc = cs.Pop_Back()) != nullptr)
+ {
+ align_to_column(pc, col);
+ chunk_flags_set(pc, PCF_WAS_ALIGNED);
+
+ LOG_FMT(sev, "%s(%d): indented [%s] on line %zu to %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->column);
+ }
+ }
+ cs.Reset();
+} // align_stack
+
+
+Chunk *align_trailing_comments(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ size_t min_col = 0;
+ size_t min_orig = 0;
+ Chunk *pc = start;
+ const size_t lvl = start->brace_level;
+ size_t nl_count = 0;
+ ChunkStack cs;
+ size_t col;
+
+ log_rule_B("align_right_cmt_at_col");
+ size_t intended_col = options::align_right_cmt_at_col();
+
+ log_rule_B("align_right_cmt_same_level");
+ const bool same_level = options::align_right_cmt_same_level();
+ comment_align_e cmt_type_cur;
+ comment_align_e cmt_type_start = get_comment_align_type(pc);
+
+ LOG_FMT(LALADD, "%s(%d): start on line=%zu\n",
+ __func__, __LINE__, pc->orig_line);
+
+ // Find the max column
+ log_rule_B("align_right_cmt_span");
+
+ while ( pc->IsNotNullChunk()
+ && (nl_count < options::align_right_cmt_span()))
+ {
+ if ( pc->flags.test(PCF_RIGHT_COMMENT)
+ && pc->column > 1)
+ {
+ if ( same_level
+ && pc->brace_level != lvl)
+ {
+ pc = pc->GetPrev();
+ break;
+ }
+ cmt_type_cur = get_comment_align_type(pc);
+
+ if (cmt_type_cur == cmt_type_start)
+ {
+ LOG_FMT(LALADD, "%s(%d): line=%zu min_col=%zu pc->col=%zu pc->len=%zu %s\n",
+ __func__, __LINE__, pc->orig_line, min_col, pc->column, pc->Len(),
+ get_token_name(pc->type));
+
+ if ( min_orig == 0
+ || min_orig > pc->column)
+ {
+ min_orig = pc->column;
+ }
+ align_add(cs, pc, min_col); // (intended_col < col));
+ nl_count = 0;
+ }
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ nl_count += pc->nl_count;
+ }
+ pc = pc->GetNext();
+ }
+ // Start with the minimum original column
+ col = min_orig;
+
+ // fall back to the intended column
+ if ( intended_col > 0
+ && col > intended_col)
+ {
+ col = intended_col;
+ }
+
+ // if less than allowed, bump it out
+ if (col < min_col)
+ {
+ col = min_col;
+ }
+
+ // bump out to the intended column
+ if (col < intended_col)
+ {
+ col = intended_col;
+ }
+ LOG_FMT(LALADD, "%s(%d): -- min_orig=%zu intended_col=%zu min_allowed=%zu ==> col=%zu\n",
+ __func__, __LINE__, min_orig, intended_col, min_col, col);
+
+ if ( cpd.frag_cols > 0
+ && cpd.frag_cols <= col)
+ {
+ col -= cpd.frag_cols;
+ }
+ align_stack(cs, col, (intended_col != 0), LALTC);
+
+ return(pc->GetNext());
+} // align_trailing_comments
+
+
+comment_align_e get_comment_align_type(Chunk *cmt)
+{
+ Chunk *prev;
+ comment_align_e cmt_type = comment_align_e::REGULAR;
+
+ log_rule_B("align_right_cmt_mix");
+
+ if ( !options::align_right_cmt_mix()
+ && cmt != nullptr
+ && ((prev = cmt->GetPrev())->IsNotNullChunk()))
+ {
+ if ( chunk_is_token(prev, CT_PP_ENDIF)
+ || chunk_is_token(prev, CT_PP_ELSE)
+ || chunk_is_token(prev, CT_ELSE)
+ || chunk_is_token(prev, CT_BRACE_CLOSE))
+ {
+ // TODO: make the magic 3 configurable
+ if ((cmt->column - (prev->column + prev->Len())) < 3)
+ {
+ cmt_type = (chunk_is_token(prev, CT_PP_ENDIF)) ? comment_align_e::ENDIF : comment_align_e::BRACE;
+ }
+ }
+ }
+ return(cmt_type);
+} // get_comment_align_type
+
+
+void align_right_comments(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( chunk_is_token(pc, CT_COMMENT)
+ || chunk_is_token(pc, CT_COMMENT_CPP)
+ || chunk_is_token(pc, CT_COMMENT_MULTI))
+ {
+ if (get_chunk_parent_type(pc) == CT_COMMENT_END)
+ {
+ Chunk *prev = pc->GetPrev();
+
+ log_rule_B("align_right_cmt_gap");
+
+ if (pc->orig_col < prev->orig_col_end + options::align_right_cmt_gap())
+ {
+ LOG_FMT(LALTC, "NOT changing END comment on line %zu (%zu <= %zu + %u)\n",
+ pc->orig_line, pc->orig_col, prev->orig_col_end,
+ options::align_right_cmt_gap());
+ }
+ else
+ {
+ LOG_FMT(LALTC, "Changing END comment on line %zu into a RIGHT-comment\n",
+ pc->orig_line);
+ chunk_flags_set(pc, PCF_RIGHT_COMMENT);
+ }
+ }
+
+ // Change certain WHOLE comments into RIGHT-alignable comments
+ if (get_chunk_parent_type(pc) == CT_COMMENT_WHOLE)
+ {
+ log_rule_B("input_tab_size");
+ size_t max_col = pc->column_indent + options::input_tab_size();
+
+ // If the comment is further right than the brace level...
+ if (pc->column >= max_col)
+ {
+ LOG_FMT(LALTC, "Changing WHOLE comment on line %zu into a RIGHT-comment (col=%zu col_ind=%zu max_col=%zu)\n",
+ pc->orig_line, pc->column, pc->column_indent, max_col);
+
+ chunk_flags_set(pc, PCF_RIGHT_COMMENT);
+ }
+ }
+ }
+ }
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->flags.test(PCF_RIGHT_COMMENT))
+ {
+ pc = align_trailing_comments(pc);
+ }
+ else
+ {
+ pc = pc->GetNext();
+ }
+ }
+} // align_right_comments
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.h
new file mode 100644
index 00000000..d85c07d0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_trailing_comments.h
@@ -0,0 +1,46 @@
+/**
+ * @file align_trailing_comments.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_TRAILING_COMMENTS_H_INCLUDED
+#define ALIGN_TRAILING_COMMENTS_H_INCLUDED
+
+#include "chunk.h"
+#include "ChunkStack.h"
+
+enum class comment_align_e : unsigned int
+{
+ REGULAR,
+ BRACE,
+ ENDIF,
+};
+
+/**
+ * For a series of lines ending in a comment, align them.
+ * The series ends when more than align_right_cmt_span newlines are found.
+ *
+ * Interesting info:
+ * - least physically allowed column
+ * - intended column
+ * - least original cmt column
+ *
+ * min_col is the minimum allowed column (based on prev token col/size)
+ * cmt_col less than
+ *
+ * @param start Start point
+ * @return pointer the last item looked at
+ */
+Chunk *align_trailing_comments(Chunk *start);
+
+comment_align_e get_comment_align_type(Chunk *cmt);
+
+void align_stack(ChunkStack &cs, size_t col, bool align_single, log_sev_t sev);
+
+void align_right_comments(void);
+
+#endif /* ALIGN_TRAILING_COMMENTS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.cpp
new file mode 100644
index 00000000..56fc30a0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.cpp
@@ -0,0 +1,65 @@
+/**
+ * @file align_typedefs.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_typedefs.h"
+
+#include "align_stack.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LALTD;
+
+using namespace uncrustify;
+
+
+void align_typedefs(size_t span)
+{
+ LOG_FUNC_ENTRY();
+
+ AlignStack as;
+
+ as.Start(span);
+ log_rule_B("align_typedef_gap");
+ as.m_gap = options::align_typedef_gap();
+ log_rule_B("align_typedef_star_style");
+ as.m_star_style = static_cast<AlignStack::StarStyle>(options::align_typedef_star_style());
+ log_rule_B("align_typedef_amp_style");
+ as.m_amp_style = static_cast<AlignStack::StarStyle>(options::align_typedef_amp_style());
+
+ Chunk *c_typedef = Chunk::NullChunkPtr;
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_newline(pc))
+ {
+ as.NewLines(pc->nl_count);
+ c_typedef = Chunk::NullChunkPtr;
+ }
+ else if (c_typedef->IsNotNullChunk())
+ {
+ if (pc->flags.test(PCF_ANCHOR))
+ {
+ as.Add(pc);
+ LOG_FMT(LALTD, "%s(%d): typedef @ %zu:%zu, tag '%s' @ %zu:%zu\n",
+ __func__, __LINE__, c_typedef->orig_line, c_typedef->orig_col,
+ pc->Text(), pc->orig_line, pc->orig_col);
+ c_typedef = Chunk::NullChunkPtr;
+ }
+ }
+ else
+ {
+ if (chunk_is_token(pc, CT_TYPEDEF))
+ {
+ c_typedef = pc;
+ }
+ }
+ pc = pc->GetNext();
+ }
+ as.End();
+} // align_typedefs
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.h
new file mode 100644
index 00000000..2902d0d2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_typedefs.h
@@ -0,0 +1,25 @@
+/**
+ * @file align_typedefs.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_TYPEDEFS_H_INCLUDED
+#define ALIGN_TYPEDEFS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+/**
+ * Aligns simple typedefs that are contained on a single line each.
+ * This should be called after the typedef target is marked as a type.
+ *
+ * typedef int foo_t;
+ * typedef char bar_t;
+ * typedef const char cc_t;
+ */
+void align_typedefs(size_t span);
+
+#endif /* ALIGN_TYPEDEFS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.cpp
new file mode 100644
index 00000000..adbc5daf
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.cpp
@@ -0,0 +1,352 @@
+/**
+ * @file align_var_def_brace.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "align_var_def_brace.h"
+
+#include "align_stack.h"
+#include "align_tools.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LAVDB;
+
+using namespace uncrustify;
+
+
+Chunk *align_var_def_brace(Chunk *start, size_t span, size_t *p_nl_count)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start->IsNullChunk())
+ {
+ return(nullptr);
+ }
+ Chunk *next;
+ size_t myspan = span;
+ size_t mythresh = 0;
+ size_t mygap = 0;
+
+ // Override the span, if this is a struct/union
+ if ( get_chunk_parent_type(start) == CT_STRUCT
+ || get_chunk_parent_type(start) == CT_UNION)
+ {
+ log_rule_B("align_var_struct_span");
+ myspan = options::align_var_struct_span();
+ log_rule_B("align_var_struct_thresh");
+ mythresh = options::align_var_struct_thresh();
+ log_rule_B("align_var_struct_gap");
+ mygap = options::align_var_struct_gap();
+ }
+ else if (get_chunk_parent_type(start) == CT_CLASS)
+ {
+ log_rule_B("align_var_class_span");
+ myspan = options::align_var_class_span();
+ log_rule_B("align_var_class_thresh");
+ mythresh = options::align_var_class_thresh();
+ log_rule_B("align_var_class_gap");
+ mygap = options::align_var_class_gap();
+ }
+ else
+ {
+ log_rule_B("align_var_def_thresh");
+ mythresh = options::align_var_def_thresh();
+ log_rule_B("align_var_def_gap");
+ mygap = options::align_var_def_gap();
+ }
+ // can't be any variable definitions in a "= {" block
+ Chunk *prev = start->GetPrevNcNnl();
+
+ if (chunk_is_token(prev, CT_ASSIGN))
+ {
+ LOG_FMT(LAVDB, "%s(%d): start->Text() '%s', type is %s, on orig_line %zu (abort due to assign)\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->type), start->orig_line);
+
+ Chunk *pc = start->GetNextType(CT_BRACE_CLOSE, start->level);
+ return(pc->GetNextNcNnl());
+ }
+ char copy[1000];
+
+ LOG_FMT(LAVDB, "%s(%d): start->Text() '%s', type is %s, on orig_line %zu\n",
+ __func__, __LINE__, start->ElidedText(copy), get_token_name(start->type), start->orig_line);
+
+ log_rule_B("align_var_def_inline");
+ auto const align_mask =
+ PCF_IN_FCN_DEF | PCF_VAR_1ST |
+ (options::align_var_def_inline() ? PCF_NONE : PCF_VAR_INLINE);
+
+ // Set up the variable/prototype/definition aligner
+ AlignStack as;
+
+ as.Start(myspan, mythresh);
+ as.m_gap = mygap;
+ log_rule_B("align_var_def_star_style");
+ as.m_star_style = static_cast<AlignStack::StarStyle>(options::align_var_def_star_style());
+ log_rule_B("align_var_def_amp_style");
+ as.m_amp_style = static_cast<AlignStack::StarStyle>(options::align_var_def_amp_style());
+
+ // Set up the bit colon aligner
+ AlignStack as_bc;
+
+ as_bc.Start(myspan, 0);
+ log_rule_B("align_var_def_colon_gap");
+ as_bc.m_gap = options::align_var_def_colon_gap();
+
+ AlignStack as_at; // attribute
+
+ as_at.Start(myspan, 0);
+
+ // Set up the brace open aligner
+ AlignStack as_br;
+
+ as_br.Start(myspan, mythresh);
+ log_rule_B("align_single_line_brace_gap");
+ as_br.m_gap = options::align_single_line_brace_gap();
+
+ bool fp_look_bro = false;
+ bool did_this_line = false;
+
+ log_rule_B("align_mix_var_proto");
+ bool fp_active = options::align_mix_var_proto();
+ Chunk *pc = start->GetNext();
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && ( pc->level >= start->level
+ || pc->level == 0))
+ {
+ if (chunk_is_newline(pc))
+ {
+ LOG_FMT(LAVDB, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LAVDB, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ }
+
+ if (pc->IsComment())
+ {
+ if (pc->nl_count > 0)
+ {
+ as.NewLines(pc->nl_count);
+ as_bc.NewLines(pc->nl_count);
+ as_at.NewLines(pc->nl_count);
+ as_br.NewLines(pc->nl_count);
+ }
+ pc = pc->GetNext();
+ continue;
+ }
+
+ if ( fp_active
+ && !pc->flags.test(PCF_IN_CLASS_BASE))
+ {
+ // WARNING: Duplicate from the align_func_proto()
+ log_rule_B("align_single_line_func");
+
+ if ( chunk_is_token(pc, CT_FUNC_PROTO)
+ || ( chunk_is_token(pc, CT_FUNC_DEF)
+ && options::align_single_line_func()))
+ {
+ LOG_FMT(LAVDB, "%s(%d): add = '%s', orig_line is %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+
+ Chunk *toadd;
+
+ log_rule_B("align_on_operator");
+
+ if ( get_chunk_parent_type(pc) == CT_OPERATOR
+ && options::align_on_operator())
+ {
+ toadd = pc->GetPrevNcNnl();
+ }
+ else
+ {
+ toadd = pc;
+ }
+ as.Add(step_back_over_member(toadd));
+ log_rule_B("align_single_line_brace");
+ fp_look_bro = (chunk_is_token(pc, CT_FUNC_DEF))
+ && options::align_single_line_brace();
+ }
+ else if ( fp_look_bro
+ && chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->flags.test(PCF_ONE_LINER))
+ {
+ as_br.Add(pc);
+ fp_look_bro = false;
+ }
+ }
+
+ // process nested braces
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ size_t sub_nl_count = 0;
+
+ pc = align_var_def_brace(pc, span, &sub_nl_count);
+
+ if (sub_nl_count > 0)
+ {
+ fp_look_bro = false;
+ did_this_line = false;
+ as.NewLines(sub_nl_count);
+ as_bc.NewLines(sub_nl_count);
+ as_at.NewLines(sub_nl_count);
+ as_br.NewLines(sub_nl_count);
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += sub_nl_count;
+ }
+ }
+ continue;
+ }
+
+ // Done with this brace set?
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ pc = pc->GetNext();
+ break;
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ fp_look_bro = false;
+ did_this_line = false;
+ as.NewLines(pc->nl_count);
+ as_bc.NewLines(pc->nl_count);
+ as_at.NewLines(pc->nl_count);
+ as_br.NewLines(pc->nl_count);
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += pc->nl_count;
+ }
+ }
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, pc->brace_level is %zu\n",
+ __func__, __LINE__, chunk_is_newline(pc) ? "Newline" : pc->Text(), pc->level, pc->brace_level);
+
+ if (!chunk_is_newline(pc))
+ {
+ LOG_FMT(LAVDB, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+
+ if (chunk_is_not_token(pc, CT_IGNORED))
+ {
+ LOG_FMT(LAVDB, " ");
+ log_pcf_flags(LAVDB, pc->flags);
+ }
+ }
+
+ // don't align stuff inside parenthesis/squares/angles
+ if (pc->level > pc->brace_level)
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+
+ // If this is a variable def, update the max_col
+ if ( !pc->flags.test(PCF_IN_CLASS_BASE)
+ && chunk_is_not_token(pc, CT_FUNC_CLASS_DEF)
+ && chunk_is_not_token(pc, CT_FUNC_CLASS_PROTO)
+ && ((pc->flags & align_mask) == PCF_VAR_1ST)
+ && chunk_is_not_token(pc, CT_FUNC_DEF) // Issue 1452
+ && ( (pc->level == (start->level + 1))
+ || pc->level == 0)
+ && pc->prev != nullptr
+ && pc->prev->type != CT_MEMBER)
+ {
+ LOG_FMT(LAVDB, "%s(%d): a-did_this_line is %s\n",
+ __func__, __LINE__, did_this_line ? "TRUE" : "FALSE");
+ LOG_FMT(LAVDB, "%s(%d): Text() is '%s', orig_line is %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+
+ if (!did_this_line)
+ {
+ if ( get_chunk_parent_type(start) == CT_STRUCT
+ && (as.m_star_style == AlignStack::SS_INCLUDE))
+ {
+ // we must look after the previous token
+ Chunk *prev_local = pc->prev;
+
+ while ( chunk_is_token(prev_local, CT_PTR_TYPE)
+ || chunk_is_token(prev_local, CT_ADDR))
+ {
+ LOG_FMT(LAVDB, "%s(%d): prev_local '%s', prev_local->type %s\n",
+ __func__, __LINE__, prev_local->Text(), get_token_name(prev_local->type));
+ prev_local = prev_local->prev;
+ }
+ pc = prev_local->next;
+ }
+ // we must look after the previous token
+ Chunk *prev_local = pc->prev;
+
+ if (chunk_is_not_token(prev_local, CT_DEREF)) // Issue #2971
+ {
+ LOG_FMT(LAVDB, "%s(%d): add = '%s', orig_line is %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+
+ as.Add(step_back_over_member(pc));
+ }
+ log_rule_B("align_var_def_colon");
+
+ if (options::align_var_def_colon())
+ {
+ next = pc->GetNextNc();
+
+ if (chunk_is_token(next, CT_BIT_COLON))
+ {
+ as_bc.Add(next);
+ }
+ }
+ log_rule_B("align_var_def_attribute");
+
+ if (options::align_var_def_attribute())
+ {
+ next = pc;
+
+ while ((next = next->GetNextNc())->IsNotNullChunk())
+ {
+ if (chunk_is_token(next, CT_ATTRIBUTE))
+ {
+ as_at.Add(next);
+ break;
+ }
+
+ if ( chunk_is_token(next, CT_SEMICOLON)
+ || chunk_is_newline(next))
+ {
+ break;
+ }
+ }
+ }
+ }
+ did_this_line = true;
+ }
+ else if (chunk_is_token(pc, CT_BIT_COLON))
+ {
+ if (!did_this_line)
+ {
+ as_bc.Add(pc);
+ did_this_line = true;
+ }
+ }
+ else
+ {
+ LOG_FMT(LAVDB, "%s(%d): b-did_this_line is %s\n",
+ __func__, __LINE__, did_this_line ? "TRUE" : "FALSE");
+ }
+ pc = pc->GetNext();
+ }
+ as.End();
+ as_bc.End();
+ as_at.End();
+ as_br.End();
+
+ return(pc);
+} // align_var_def_brace
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.h
new file mode 100644
index 00000000..6d06adf9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/align_var_def_brace.h
@@ -0,0 +1,22 @@
+/**
+ * @file align_var_def_brace.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef ALIGN_VAR_DEF_BRACE_H_INCLUDED
+#define ALIGN_VAR_DEF_BRACE_H_INCLUDED
+
+#include "chunk.h"
+
+/**
+ * Scan everything at the current level until the close brace and find the
+ * variable def align column. Also aligns bit-colons, but that assumes that
+ * bit-types are the same! But that should always be the case...
+ */
+Chunk *align_var_def_brace(Chunk *pc, size_t span, size_t *nl_count);
+
+#endif /* ALIGN_VAR_DEF_BRACE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.cpp
new file mode 100644
index 00000000..a03bbe00
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.cpp
@@ -0,0 +1,228 @@
+/**
+ * @file args.cpp
+ * Parses command line arguments.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "args.h"
+
+#include "unc_ctype.h"
+
+#include <cstring>
+
+Args::Args(int argc, char **argv)
+{
+ m_count = argc;
+ m_values = argv;
+ size_t len = (argc >> 3) + 1;
+
+ m_used = new UINT8[len];
+
+ if (m_used != nullptr)
+ {
+ memset(m_used, 0, len);
+ }
+}
+
+
+Args::~Args()
+{
+ if (m_used != nullptr)
+ {
+ delete[] m_used;
+ m_used = nullptr;
+ }
+ m_count = 0;
+}
+
+
+bool Args::Present(const char *token)
+{
+ if (token != nullptr)
+ {
+ for (size_t idx = 0; idx < m_count; idx++)
+ {
+ if (strcmp(token, m_values[idx]) == 0)
+ {
+ SetUsed(idx);
+ return(true);
+ }
+ }
+ }
+ return(false);
+}
+
+
+const char *Args::Param(const char *token)
+{
+ size_t idx = 0;
+
+ return(Params(token, idx));
+}
+
+
+const char *Args::Params(const char *token, size_t &index)
+{
+ if (token == nullptr)
+ {
+ // coveralls will complain
+ // can only occur with a call such as: arg.Param(nullptr)
+ return(nullptr);
+ }
+ size_t token_len = strlen(token);
+
+ for (size_t idx = index; idx < m_count; idx++)
+ {
+ size_t arg_len = strlen(m_values[idx]);
+
+ if ( arg_len >= token_len
+ && (memcmp(token, m_values[idx], token_len) == 0))
+ {
+ SetUsed(idx);
+
+ if (arg_len > token_len)
+ {
+ if (m_values[idx][token_len] == '=')
+ {
+ token_len++;
+ }
+ index = idx + 1;
+ return(&m_values[idx][token_len]);
+ }
+ idx++;
+ index = idx + 1;
+
+ if (idx < m_count)
+ {
+ SetUsed(idx);
+ return(m_values[idx]);
+ }
+ return(nullptr);
+ }
+ }
+
+ return(nullptr);
+} // Args::Params
+
+
+bool Args::GetUsed(size_t idx)
+{
+ if ( m_used != nullptr
+ && idx > 0
+ && idx < m_count)
+ {
+ return((m_used[idx >> 3] & (1 << (idx & 0x07))) != 0);
+ }
+ return(false);
+}
+
+
+void Args::SetUsed(size_t idx)
+{
+ if ( m_used != nullptr
+ && idx > 0
+ && idx < m_count)
+ {
+ m_used[idx >> 3] |= (1 << (idx & 0x07));
+ }
+}
+
+
+const char *Args::Unused(size_t &index)
+{
+ if (m_used == nullptr)
+ {
+ return(nullptr);
+ }
+
+ for (size_t idx = index; idx < m_count; idx++)
+ {
+ if (!GetUsed(idx))
+ {
+ index = idx + 1;
+ return(m_values[idx]);
+ }
+ }
+
+ index = m_count;
+ return(nullptr);
+}
+
+
+size_t Args::SplitLine(char *text, char *args[], size_t num_args)
+{
+ if ( text == nullptr
+ || num_args == 0)
+ {
+ return(0);
+ }
+ char cur_quote = 0;
+ bool in_backslash = false;
+ bool in_arg = false;
+ size_t argc = 0;
+ char *dest = text;
+
+ while ( argc <= num_args // maximal number of arguments not reached yet
+ && *text != 0) // end of string not reached yet
+ {
+ // Detect the start of an arg
+ if ( !in_arg
+ && !unc_isspace(*text))
+ {
+ in_arg = true;
+ args[argc] = dest;
+ argc++;
+ }
+
+ if (in_arg)
+ {
+ if (in_backslash)
+ {
+ in_backslash = false;
+ *dest = *text;
+ dest++;
+ }
+ else if (*text == '\\')
+ {
+ in_backslash = true;
+ }
+ else if (*text == cur_quote)
+ {
+ cur_quote = 0;
+ }
+ else if ( (*text == '\'')
+ || (*text == '"')
+ || (*text == '`'))
+ {
+ cur_quote = *text;
+ }
+ else if (cur_quote != 0)
+ {
+ *dest = *text;
+ dest++;
+ }
+ else if (unc_isspace(*text))
+ {
+ *dest = 0;
+ dest++;
+ in_arg = false;
+
+ if (argc == num_args)
+ {
+ break; // all arguments found, we can stop
+ }
+ }
+ else
+ {
+ *dest = *text;
+ dest++;
+ }
+ }
+ text++; // go on with next character
+ }
+ *dest = 0;
+
+ return(argc);
+} // Args::SplitLine
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.h
new file mode 100644
index 00000000..712fbd59
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/args.h
@@ -0,0 +1,122 @@
+/**
+ * @file args.h
+ * Parses command line arguments.
+ *
+ * This differs from the GNU/getopt way in that:
+ * - parameters cannot mixed "-e -f" is not the same as "-ef"
+ * - knowledge of the complete set of parameters is not required
+ * - this means you can handle args in multiple spots
+ * - it is more portable
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef ARGS_H_INCLUDED
+#define ARGS_H_INCLUDED
+
+#include "base_types.h"
+
+class Args
+{
+protected:
+ size_t m_count; //! number of command line arguments
+ char **m_values; //! pointer array to each argument
+ UINT8 *m_used; //! bit array with one flag per argument
+
+public:
+ /**
+ * Initializes the argument library.
+ * Store the values and allocates enough memory for the 'used' flags.
+ * This keeps a reference to argv, so don't change it.
+ *
+ * @param argc number of command line parameter passed to main()
+ * @param argv pointer array to command line parameters
+ */
+ Args(int argc, char **argv);
+
+ //! Standard destructor
+ ~Args();
+
+ /**
+ * Checks to see if an arg w/o a value is present.
+ * Scans the args looking for an exact match.
+ *
+ * "-c" matches "-c", but not "-call" or "-ec"
+ *
+ * @param token The token string to match
+ *
+ * @return true/false -- Whether the argument was present
+ */
+ bool Present(const char *token);
+
+ /**
+ * Calls Args::Params() with index 0
+ *
+ * @param token The token string to match
+ *
+ * @return nullptr or the pointer to the string
+ */
+ const char *Param(const char *token);
+
+ /**
+ * Check for an arg with a value.
+ * Returns only the first match.
+ *
+ * Assuming the token "-c"...
+ * "-call" returns "all"
+ * "-c=all" returns "all"
+ * "-c", "all" returns "all"
+ * "-c=", "all" returns ""
+ *
+ * @param token the token string to match
+ * @param[in, out] index search start position, in case that something is
+ * found, it will get the succeeding position number
+ * assigned
+ *
+ * @return nullptr or the pointer to the string
+ */
+ const char *Params(const char *token, size_t &index);
+
+ /**
+ * Marks an argument as being used.
+ *
+ * @param idx The index of the argument
+ */
+ void SetUsed(size_t idx);
+
+ /**
+ * Gets whether an argument has been used, by index.
+ *
+ * @param idx The index of the argument
+ */
+ bool GetUsed(size_t idx);
+
+ /**
+ * This function retrieves all unused parameters.
+ * You must set the index before the first call.
+ * Set the index to 1 to skip argv[0].
+ *
+ * @param idx Pointer to the index
+ *
+ * @return nullptr (done) or the pointer to the string
+ */
+ const char *Unused(size_t &idx);
+
+ /**
+ * Takes text and splits it into arguments.
+ * args is an array of char pointers that will get populated.
+ * num_args is the maximum number of args split off.
+ * If there are more than num_args, the remaining text is ignored.
+ * Note that text is modified (zeroes are inserted)
+ *
+ * @param text the text to split (modified)
+ * @param[out] args array of pointers to be populated
+ * @param num_args number of items in input string
+ *
+ * @return The number of arguments parsed (always <= num_args)
+ */
+ static size_t SplitLine(char *text, char *args[], size_t num_args);
+};
+
+
+#endif /* ARGS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.cpp
new file mode 100644
index 00000000..e85ecf97
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.cpp
@@ -0,0 +1,165 @@
+/**
+ * @file backup.cpp
+ * Make a backup of a source file
+ * The current plans are to use two files.
+ *
+ * - A '.unc-backup~' file that contains the original contents
+ * - A '.unc-backup-md5~' file that contains the MD5 over the last output
+ * that uncrustify generated
+ *
+ * The logic goes like this:
+ * 1. If there isn't a .backup-md5 or the md5 over the input file doesn't
+ * match what is in .backup-md5, then copy the source file to .backup.
+ *
+ * 2. Create the output file.
+ *
+ * 3. Calculate the md5 over the output file.
+ * Create the .backup-md5 file.
+ *
+ * This will let you run uncrustify multiple times over the same file without
+ * losing the original file. If you edit the file, then a new backup is made.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "prototypes.h"
+
+#include "backup.h"
+#include "md5.h"
+#include "unc_ctype.h"
+
+#include <cerrno>
+
+using namespace std;
+
+
+int backup_copy_file(const char *filename, const vector<UINT8> &data)
+{
+ char newpath[1024];
+ char md5_str_in[33];
+ char md5_str[34];
+ UINT8 dig[16];
+
+ md5_str_in[0] = 0;
+
+ MD5::Calc(data.data(), data.size(), dig);
+ snprintf(md5_str, sizeof(md5_str),
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ dig[0], dig[1], dig[2], dig[3],
+ dig[4], dig[5], dig[6], dig[7],
+ dig[8], dig[9], dig[10], dig[11],
+ dig[12], dig[13], dig[14], dig[15]);
+
+ // Create the backup-md5 filename, open it and read the md5
+ snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_MD5_SUFFIX);
+
+ FILE *thefile = fopen(newpath, "rb");
+
+ if (thefile != nullptr)
+ {
+ char buffer[128];
+
+ if (fgets(buffer, sizeof(buffer), thefile) != nullptr)
+ {
+ for (int i = 0; buffer[i] != 0; i++)
+ {
+ if (unc_isxdigit(buffer[i]))
+ {
+ md5_str_in[i] = unc_tolower(buffer[i]);
+ }
+ else
+ {
+ md5_str_in[i] = 0;
+ break;
+ }
+ }
+ }
+ fclose(thefile);
+ }
+
+ // if the MD5s match, then there is no need to back up the file
+ if (memcmp(md5_str, md5_str_in, 32) == 0)
+ {
+ LOG_FMT(LNOTE, "%s: MD5 match for %s\n", __func__, filename);
+ return(EX_OK);
+ }
+ LOG_FMT(LNOTE, "%s: MD5 mismatch - backing up %s\n", __func__, filename);
+
+ // Create the backup file
+ snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_SUFFIX);
+
+ thefile = fopen(newpath, "wb");
+
+ if (thefile != nullptr)
+ {
+ size_t retval = fwrite(data.data(), data.size(), 1, thefile);
+ int my_errno = errno;
+
+ fclose(thefile);
+
+ if ( retval == 1
+ || data.empty())
+ {
+ return(EX_OK);
+ }
+ LOG_FMT(LERR, "fwrite(%s) failed: %s (%d)\n",
+ newpath, strerror(my_errno), my_errno);
+ cpd.error_count++;
+ }
+ else
+ {
+ LOG_FMT(LERR, "fopen(%s) failed: %s (%d)\n",
+ newpath, strerror(errno), errno);
+ cpd.error_count++;
+ }
+ return(EX_IOERR);
+} // backup_copy_file
+
+
+void backup_create_md5_file(const char *filename)
+{
+ UINT8 dig[16];
+ MD5 md5;
+ FILE *thefile;
+ UINT8 buf[4096];
+ size_t len;
+ char newpath[1024];
+
+ md5.Init();
+
+ thefile = fopen(filename, "rb");
+
+ if (thefile == nullptr)
+ {
+ LOG_FMT(LERR, "%s: fopen(%s) failed: %s (%d)\n",
+ __func__, filename, strerror(errno), errno);
+ cpd.error_count++;
+ return;
+ }
+
+ // read file chunk by chunk and calculate its MD5 checksum
+ while ((len = fread(buf, 1, sizeof(buf), thefile)) > 0)
+ {
+ md5.Update(buf, len);
+ }
+ fclose(thefile);
+ md5.Final(dig);
+
+ snprintf(newpath, sizeof(newpath), "%s%s", filename, UNC_BACKUP_MD5_SUFFIX);
+
+ thefile = fopen(newpath, "wb");
+
+ if (thefile != nullptr)
+ {
+ fprintf(thefile,
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
+ dig[0], dig[1], dig[2], dig[3],
+ dig[4], dig[5], dig[6], dig[7],
+ dig[8], dig[9], dig[10], dig[11],
+ dig[12], dig[13], dig[14], dig[15],
+ path_basename(filename));
+
+ fclose(thefile);
+ }
+} // backup_create_md5_file
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.h
new file mode 100644
index 00000000..3e51f863
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/backup.h
@@ -0,0 +1,63 @@
+/**
+ * @file backup.h
+ * Handles backing up file data.
+ *
+ * It works like this:
+ *
+ * 1. Read in the file data
+ *
+ * 2. Call backup_copy_file() to create a backup of the input, if needed
+ *
+ * 3. Do the uncrustify magic and write the output file
+ *
+ * 4. Call backup_create_md5_file()
+ *
+ * This will let you run uncrustify multiple times over the same file without
+ * losing the original file. If you edit the file, then a new backup is made.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef BACKUP_H_INCLUDED
+#define BACKUP_H_INCLUDED
+
+#define UNC_BACKUP_SUFFIX ".unc-backup~"
+#define UNC_BACKUP_MD5_SUFFIX ".unc-backup.md5~"
+
+
+/**
+ * @brief Check the backup-md5 file and copy the input file to a backup if needed.
+ *
+ * If there isn't a FILENAME+UNC_BACKUP_MD5_SUFFIX or the md5 over the data
+ * doesn't match what is in FILENAME+UNC_BACKUP_MD5_SUFFIX, then write the
+ * data to FILENAME+UNC_BACKUP_SUFFIX.
+ *
+ * Note that if this fails, we shouldn't overwrite to original file with the
+ * output.
+ *
+ * @param filename The file that was read (full path)
+ * @param file_data The file data
+ * @param file_len The file length
+ *
+ * @retval EX_OK successfully created backup file
+ * @retval EX_IOERR could not create backup file
+ */
+int backup_copy_file(const char *filename, const std::vector<UINT8> &data);
+
+
+/**
+ * This calculates the MD5 over the file and writes the MD5 to
+ * FILENAME+UNC_BACKUP_MD5_SUFFIX.*
+ * This should be called after the file was written to disk.
+ * We really don't care if it fails, as the MD5 just prevents us from backing
+ * up a file that uncrustify created.
+ *
+ * This should be called after the file was written to disk.
+ * It will be read back and an md5 will be calculated over it.
+ *
+ * @param filename The file that was written (full path)
+ */
+void backup_create_md5_file(const char *filename);
+
+
+#endif /* BACKUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/base_types.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/base_types.h
new file mode 100644
index 00000000..1e98b0ac
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/base_types.h
@@ -0,0 +1,53 @@
+/**
+ * @file base_types.h
+ *
+ * Defines some base types, includes config.h
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef BASE_TYPES_H_INCLUDED
+#define BASE_TYPES_H_INCLUDED
+
+#include "error_types.h"
+
+#ifdef WIN32
+
+#include "windows_compat.h"
+
+#else // not WIN32
+
+#include "config.h"
+
+#define PATH_SEP '/'
+
+#define __STDC_FORMAT_MACROS
+
+#if defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#error "Don't know where int8_t is defined"
+#endif
+
+
+// some of my favorite aliases
+
+typedef char CHAR;
+
+typedef int8_t INT8;
+typedef int16_t INT16;
+typedef int32_t INT32;
+
+typedef uint8_t UINT8;
+typedef uint16_t UINT16;
+typedef uint32_t UINT32;
+typedef uint64_t UINT64;
+#endif /* ifdef WIN32 */
+
+// and the ever-so-important array size macro
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+
+#endif /* BASE_TYPES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.cpp
new file mode 100644
index 00000000..5462b480
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.cpp
@@ -0,0 +1,1506 @@
+/**
+ * @file brace_cleanup.cpp
+ * Determines the brace level and paren level.
+ * Inserts virtual braces as needed.
+ * Handles all that preprocessor stuff.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "brace_cleanup.h"
+
+#include "flag_parens.h"
+#include "frame_list.h"
+#include "keywords.h"
+#include "lang_pawn.h"
+#include "prototypes.h"
+
+#include <stdexcept> // to get std::invalid_argument
+
+constexpr static auto LCURRENT = LBC;
+
+using namespace uncrustify;
+
+using std::invalid_argument;
+using std::string;
+using std::to_string;
+using std::stringstream;
+
+
+/*
+ * abbreviations used:
+ * - sparen = tbd
+ * - PS = Parenthesis Stack
+ * - pse = Parenthesis Stack
+ */
+
+
+struct BraceState
+{
+ std::vector<ParseFrame> frames = {};
+ E_Token in_preproc = CT_NONE;
+ int pp_level = 0;
+ bool consumed = false;
+};
+
+/**
+ * Called when a statement was just closed and the pse_tos was just
+ * decremented.
+ *
+ * - if the TOS is now VBRACE, insert a CT_VBRACE_CLOSE and recurse.
+ * - if the TOS is a complex statement, call handle_complex_close()
+ *
+ * @retval true done with this chunk
+ * @retval false keep processing
+ */
+static bool close_statement(ParseFrame &frm, Chunk *pc, const BraceState &braceState);
+
+
+static size_t preproc_start(BraceState &braceState, ParseFrame &frm, Chunk *pc);
+
+
+static void print_stack(log_sev_t logsev, const char *str, const ParseFrame &frm);
+
+
+/**
+ * pc is a CT_WHILE.
+ * Scan backwards to see if we find a brace/vbrace with the parent set to CT_DO
+ */
+static bool maybe_while_of_do(Chunk *pc);
+
+
+/**
+ * @param after determines: true - insert_vbrace_close_after(pc, frm)
+ * false - insert_vbrace_open_before(pc, frm)
+ */
+static Chunk *insert_vbrace(Chunk *pc, bool after, const ParseFrame &frm);
+
+#define insert_vbrace_close_after(pc, frm) insert_vbrace(pc, true, frm)
+#define insert_vbrace_open_before(pc, frm) insert_vbrace(pc, false, frm)
+
+static void parse_cleanup(BraceState &braceState, ParseFrame &frm, Chunk *pc);
+
+
+/**
+ * Checks the progression of complex statements.
+ * - checks for else after if
+ * - checks for if after else
+ * - checks for while after do
+ * - checks for open brace in BRACE2 and BRACE_DO stages, inserts open VBRACE
+ * - checks for open paren in PAREN1 and BRACE2 stages, complains
+ *
+ * @param frm The parse frame
+ * @param pc The current chunk
+ *
+ * @return true - done with this chunk, false - keep processing
+ */
+static bool check_complex_statements(ParseFrame &frm, Chunk *pc, const BraceState &braceState);
+
+
+/**
+ * Handles a close paren or brace - just progress the stage, if the end
+ * of the statement is hit, call close_statement()
+ *
+ * @param frm The parse frame
+ * @param pc The current chunk
+ *
+ * @return true - done with this chunk, false - keep processing
+ */
+static bool handle_complex_close(ParseFrame &frm, Chunk *pc, const BraceState &braceState);
+
+
+//! We're on a 'namespace' skip the word and then set the parent of the braces.
+static void mark_namespace(Chunk *pns);
+
+
+static size_t preproc_start(BraceState &braceState, ParseFrame &frm, Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ const size_t pp_level = braceState.pp_level;
+
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ return(pp_level);
+ }
+ // Get the type of preprocessor and handle it
+ braceState.in_preproc = next->type;
+
+ // If we are not in a define, check for #if, #else, #endif, etc
+ if (braceState.in_preproc != CT_PP_DEFINE)
+ {
+ int pp_indent = fl_check(braceState.frames, frm, braceState.pp_level, pc);
+ return(pp_indent);
+ }
+ // else push the frame stack
+ fl_push(braceState.frames, frm);
+
+ // a preproc body starts a new, blank frame
+ frm = {};
+ frm.level = 1;
+ frm.brace_level = 1;
+
+ // TODO: not sure about the next 3 lines
+ frm.push(nullptr);
+ frm.top().type = CT_PP_DEFINE;
+
+ return(pp_level);
+}
+
+
+static void print_stack(log_sev_t logsev, const char *str,
+ const ParseFrame &frm)
+{
+ LOG_FUNC_ENTRY();
+
+ if (!log_sev_on(logsev))
+ {
+ return;
+ }
+ log_fmt(logsev, "%s(%d): str is '%s'", __func__, __LINE__, str);
+
+ for (size_t idx = 1; idx < frm.size(); idx++)
+ {
+ if (frm.at(idx).stage != brace_stage_e::NONE)
+ {
+ LOG_FMT(logsev, " [%s - %u]", get_token_name(frm.at(idx).type),
+ (unsigned int)frm.at(idx).stage);
+ }
+ else
+ {
+ LOG_FMT(logsev, " [%s]", get_token_name(frm.at(idx).type));
+ }
+ }
+
+ log_fmt(logsev, "\n");
+}
+
+
+//TODO: This can be cleaned up and simplified - we can look both forward and backward!
+void brace_cleanup(void)
+{
+ LOG_FUNC_ENTRY();
+
+ BraceState braceState;
+ ParseFrame frm{};
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ // Check for leaving a #define body
+ if ( braceState.in_preproc != CT_NONE
+ && !pc->flags.test(PCF_IN_PREPROC))
+ {
+ if (braceState.in_preproc == CT_PP_DEFINE)
+ {
+ // out of the #define body, restore the frame
+ size_t brace_level = frm.brace_level;
+
+ if ( options::pp_warn_unbalanced_if()
+ && brace_level != 1)
+ {
+ LOG_FMT(LWARN, "%s(%d): orig_line is %zu, unbalanced #define block braces, out-level is %zu\n",
+ __func__, __LINE__, pc->orig_line, brace_level);
+ }
+ fl_pop(braceState.frames, frm);
+ }
+ braceState.in_preproc = CT_NONE;
+ }
+ // Check for a preprocessor start
+ size_t pp_level;
+
+ if (chunk_is_token(pc, CT_PREPROC))
+ {
+ pp_level = preproc_start(braceState, frm, pc);
+ }
+ else
+ {
+ pp_level = braceState.pp_level;
+ }
+ LOG_FMT(LTOK, "%s(%d): pp_level is %zu\n",
+ __func__, __LINE__, pp_level);
+
+ // Do before assigning stuff from the frame
+ if ( language_is_set(LANG_PAWN)
+ && frm.top().type == CT_VBRACE_OPEN
+ && chunk_is_token(pc, CT_NEWLINE))
+ {
+ pc = pawn_check_vsemicolon(pc);
+
+ if (pc == nullptr)
+ {
+ return;
+ }
+ }
+
+ // Issue #1813
+ if (chunk_is_token(pc, CT_NAMESPACE))
+ {
+ mark_namespace(pc);
+ }
+ // Assume the level won't change
+ pc->level = frm.level;
+ pc->brace_level = frm.brace_level;
+ pc->pp_level = pp_level;
+
+ /*
+ * #define bodies get the full formatting treatment
+ * Also need to pass in the initial '#' to close out any virtual braces.
+ */
+ if ( !pc->IsComment()
+ && !chunk_is_newline(pc)
+ && !chunk_is_token(pc, CT_ATTRIBUTE)
+ && !chunk_is_token(pc, CT_IGNORED) // Issue #2279
+ && ( braceState.in_preproc == CT_PP_DEFINE
+ || braceState.in_preproc == CT_NONE))
+ {
+ braceState.consumed = false;
+ parse_cleanup(braceState, frm, pc);
+ print_stack(LBCSAFTER, (chunk_is_token(pc, CT_VBRACE_CLOSE)) ? "Virt-}\n" : pc->str.c_str(), frm);
+ }
+ pc = pc->GetNext();
+ }
+// pc = Chunk::GetHead();
+//
+// while (pc->IsNotNullChunk())
+// {
+// LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+// __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+//
+// // look for template
+// if (chunk_is_token(pc, CT_TEMPLATE)) // Issue #3309
+// {
+// Chunk *template_end = pc->GetNextType(CT_SEMICOLON, pc->level);
+//
+// // look for a parameter pack
+// while (pc->IsNotNullChunk())
+// {
+// LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+// __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+//
+// if (chunk_is_token(pc, CT_PARAMETER_PACK))
+// {
+// Chunk *parameter_pack = pc;
+//
+// // look for a token with the same text
+// while (pc->IsNotNullChunk())
+// {
+// LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+// __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+// pc = pc->GetNext();
+//
+// if (pc == template_end)
+// {
+// break;
+// }
+//
+// if (strcmp(pc->Text(), parameter_pack->Text()) == 0)
+// {
+// set_chunk_type(pc, CT_PARAMETER_PACK);
+// }
+// }
+// }
+// pc = pc->GetNext();
+//
+// if (pc == template_end)
+// {
+// break;
+// }
+// }
+// }
+// pc = pc->GetNext();
+// }
+} // brace_cleanup
+
+
+static bool maybe_while_of_do(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if ( prev->IsNullChunk()
+ || !prev->flags.test(PCF_IN_PREPROC))
+ {
+ return(false);
+ }
+
+ // Find the chunk before the preprocessor
+ while ( prev->IsNullChunk()
+ && prev->flags.test(PCF_IN_PREPROC))
+ {
+ prev = prev->GetPrevNcNnl();
+ }
+
+ if ( ( chunk_is_token(prev, CT_VBRACE_CLOSE)
+ || chunk_is_token(prev, CT_BRACE_CLOSE))
+ && get_chunk_parent_type(prev) == CT_DO)
+ {
+ return(true);
+ }
+ return(false);
+}
+
+
+/**
+ * At the heart of this algorithm are two stacks.
+ * There is the Paren Stack (PS) and the Frame stack.
+ *
+ * The PS (pse in the code) keeps track of braces, parens,
+ * if/else/switch/do/while/etc items -- anything that is nestable.
+ * Complex statements go through stages.
+ * Take this simple if statement as an example:
+ * if ( x ) { x--; }
+ *
+ * The stack would change like so: 'token' stack afterwards
+ * 'if' [IF - 1]
+ * '(' [IF - 1] [PAREN OPEN]
+ * 'x' [IF - 1] [PAREN OPEN]
+ * ')' [IF - 2] <- note that the state was incremented
+ * '{' [IF - 2] [BRACE OPEN]
+ * 'x' [IF - 2] [BRACE OPEN]
+ * '--' [IF - 2] [BRACE OPEN]
+ * ';' [IF - 2] [BRACE OPEN]
+ * '}' [IF - 3]
+ * <- lack of else kills the IF, closes statement
+ *
+ * Virtual braces example:
+ * if ( x ) x--; else x++;
+ *
+ * 'if' [IF - 1]
+ * '(' [IF - 1] [PAREN OPEN]
+ * 'x' [IF - 1] [PAREN OPEN]
+ * ')' [IF - 2]
+ * 'x' [IF - 2] [VBRACE OPEN] <- VBrace open inserted before because '{' was not next
+ * '--' [IF - 2] [VBRACE OPEN]
+ * ';' [IF - 3] <- VBrace close inserted after semicolon
+ * 'else' [ELSE - 0] <- IF changed into ELSE
+ * 'x' [ELSE - 0] [VBRACE OPEN] <- lack of '{' -> VBrace
+ * '++' [ELSE - 0] [VBRACE OPEN]
+ * ';' [ELSE - 0] <- VBrace close inserted after semicolon
+ * <- ELSE removed after statement close
+ *
+ * The pse stack is kept on a frame stack.
+ * The frame stack is need for languages that support preprocessors (C, C++, C#)
+ * that can arbitrarily change code flow. It also isolates #define macros so
+ * that they are indented independently and do not affect the rest of the program.
+ *
+ * When an #if is hit, a copy of the current frame is push on the frame stack.
+ * When an #else/#elif is hit, a copy of the current stack is pushed under the
+ * #if frame and the original (pre-#if) frame is copied to the current frame.
+ * When #endif is hit, the top frame is popped.
+ * This has the following effects:
+ * - a simple #if / #endif does not affect program flow
+ * - #if / #else /#endif - continues from the #if clause
+ *
+ * When a #define is entered, the current frame is pushed and cleared.
+ * When a #define is exited, the frame is popped.
+ */
+static void parse_cleanup(BraceState &braceState, ParseFrame &frm, Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, type is %s, tos is %zu, TOS.type is %s, TOS.stage is %s, ",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, get_token_name(pc->type),
+ frm.size() - 1, get_token_name(frm.top().type),
+ get_brace_stage_name(frm.top().stage));
+ log_pcf_flags(LTOK, pc->flags);
+
+ // Mark statement starts
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, type is %s, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, get_token_name(pc->type), pc->Text());
+ LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n",
+ __func__, __LINE__, frm.stmt_count, frm.expr_count);
+
+ if ( ( frm.stmt_count == 0
+ || frm.expr_count == 0)
+ && !chunk_is_semicolon(pc)
+ && chunk_is_not_token(pc, CT_BRACE_CLOSE)
+ && chunk_is_not_token(pc, CT_VBRACE_CLOSE)
+ && !chunk_is_str(pc, ")")
+ && !chunk_is_str(pc, "]"))
+ {
+ chunk_flags_set(pc, PCF_EXPR_START | ((frm.stmt_count == 0) ? PCF_STMT_START : PCF_NONE));
+ LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, 1.marked '%s' as %s, start stmt_count is %zu, expr_count is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->Text(),
+ pc->flags.test(PCF_STMT_START) ? "stmt" : "expr", frm.stmt_count,
+ frm.expr_count);
+ }
+ frm.stmt_count++;
+ frm.expr_count++;
+ LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n",
+ __func__, __LINE__, frm.stmt_count, frm.expr_count);
+
+ if (frm.sparen_count > 0)
+ {
+ chunk_flags_set(pc, PCF_IN_SPAREN);
+
+ // Mark everything in the for statement
+ for (int tmp = static_cast<int>(frm.size()) - 2; tmp >= 0; tmp--)
+ {
+ if (frm.at(tmp).type == CT_FOR)
+ {
+ chunk_flags_set(pc, PCF_IN_FOR);
+ break;
+ }
+ }
+
+ // Mark the parent on semicolons in for() statements
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ && frm.size() > 2
+ && frm.prev().type == CT_FOR)
+ {
+ set_chunk_parent(pc, CT_FOR);
+ }
+ }
+
+ // Check the progression of complex statements
+ if ( frm.top().stage != brace_stage_e::NONE
+ && !chunk_is_token(pc, CT_AUTORELEASEPOOL)
+ && check_complex_statements(frm, pc, braceState))
+ {
+ return;
+ }
+
+ /*
+ * Check for a virtual brace statement close due to a semicolon.
+ * The virtual brace will get handled the next time through.
+ * The semicolon isn't handled at all.
+ * TODO: may need to float VBRACE past comments until newline?
+ */
+ if (frm.top().type == CT_VBRACE_OPEN)
+ {
+ if (chunk_is_semicolon(pc))
+ {
+ braceState.consumed = true;
+ close_statement(frm, pc, braceState);
+ }
+ else if ( language_is_set(LANG_PAWN)
+ && chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ close_statement(frm, pc, braceState);
+ }
+ else if ( language_is_set(LANG_D)
+ && chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ close_statement(frm, pc, braceState);
+ }
+ }
+
+ // Handle close parenthesis, vbrace, brace, and square
+ if ( chunk_is_token(pc, CT_PAREN_CLOSE)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE)
+ || chunk_is_token(pc, CT_MACRO_CLOSE)
+ || chunk_is_token(pc, CT_SQUARE_CLOSE))
+ {
+ // Change CT_PAREN_CLOSE into CT_SPAREN_CLOSE or CT_FPAREN_CLOSE
+ if ( chunk_is_token(pc, CT_PAREN_CLOSE)
+ && ( (frm.top().type == CT_FPAREN_OPEN)
+ || (frm.top().type == CT_SPAREN_OPEN)))
+ {
+ // TODO: fix enum hack
+ set_chunk_type(pc, static_cast<E_Token>(frm.top().type + 1));
+
+ if (chunk_is_token(pc, CT_SPAREN_CLOSE))
+ {
+ frm.sparen_count--;
+ chunk_flags_clr(pc, PCF_IN_SPAREN);
+ }
+ }
+
+ // Make sure the open / close match
+ if (chunk_is_not_token(pc, (E_Token)(frm.top().type + 1)))
+ {
+ if (pc->flags.test(PCF_IN_PREPROC)) // Issue #3113, #3283
+ {
+ // do nothing
+ }
+ else
+ {
+ LOG_FMT(LWARN, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ paren_stack_entry_t AA = frm.top(); // Issue #3055
+
+ if (AA.type != CT_EOF)
+ {
+ LOG_FMT(LWARN, "%s(%d): (frm.top().type + 1) is %s\n",
+ __func__, __LINE__, get_token_name((E_Token)(frm.top().type + 1)));
+ }
+
+ if ( frm.top().type != CT_EOF
+ && frm.top().type != CT_PP_DEFINE)
+ {
+ LOG_FMT(LWARN, "%s(%d): File: %s, orig_line is %zu, orig_col is %zu, Error: Unexpected '%s' for '%s', which was on line %zu\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, pc->orig_col,
+ pc->Text(), get_token_name(frm.top().pc->type),
+ frm.top().pc->orig_line);
+ print_stack(LBCSPOP, "=Error ", frm);
+ cpd.error_count++;
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ else
+ {
+ braceState.consumed = true;
+
+ // Copy the parent, update the parenthesis/brace levels
+ set_chunk_parent(pc, frm.top().parent);
+ frm.level--;
+
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE)
+ || chunk_is_token(pc, CT_MACRO_CLOSE))
+ {
+ frm.brace_level--;
+ LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level decreased to %zu",
+ __func__, __LINE__, frm.brace_level);
+ log_pcf_flags(LBCSPOP, pc->flags);
+ }
+ pc->level = frm.level;
+ pc->brace_level = frm.brace_level;
+
+ // Pop the entry
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-Close ", frm);
+
+ if ( frm.top().stage == brace_stage_e::NONE
+ && ( chunk_is_token(pc, CT_VBRACE_CLOSE)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_SEMICOLON))
+ && chunk_is_token(frm.top().pc, CT_VBRACE_OPEN))
+ {
+ // frames for functions are not created as they are for an if
+ // this here is a hackish solution to close a vbrace of a block that
+ // contains the function
+ frm.push(nullptr); // <- dummy frame for the function
+ frm.top().stage = brace_stage_e::BRACE2;
+ }
+
+ // See if we are in a complex statement
+ if (frm.top().stage != brace_stage_e::NONE)
+ {
+ handle_complex_close(frm, pc, braceState);
+ }
+ }
+ }
+
+ /*
+ * In this state, we expect a semicolon, but we'll also hit the closing
+ * sparen, so we need to check braceState.consumed to see if the close sparen
+ * was aleady handled.
+ */
+ if (frm.top().stage == brace_stage_e::WOD_SEMI)
+ {
+ if (braceState.consumed)
+ {
+ /*
+ * If consumed, then we are on the close sparen.
+ * PAWN: Check the next chunk for a semicolon. If it isn't, then
+ * add a virtual semicolon, which will get handled on the next pass.
+ */
+ if (language_is_set(LANG_PAWN))
+ {
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if ( chunk_is_not_token(tmp, CT_SEMICOLON)
+ && chunk_is_not_token(tmp, CT_VSEMICOLON))
+ {
+ pawn_add_vsemi_after(pc);
+ }
+ }
+ }
+ else
+ {
+ // Complain if this ISN'T a semicolon, but close out WHILE_OF_DO anyway
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ || chunk_is_token(pc, CT_VSEMICOLON))
+ {
+ braceState.consumed = true;
+ set_chunk_parent(pc, CT_WHILE_OF_DO);
+ }
+ else
+ {
+ LOG_FMT(LWARN, "%s: %s(%d): %zu: Error: Expected a semicolon for WHILE_OF_DO, but got '%s'\n",
+ cpd.filename.c_str(), __func__, __LINE__, pc->orig_line,
+ get_token_name(pc->type));
+ cpd.error_count++;
+ }
+ handle_complex_close(frm, pc, braceState);
+ }
+ }
+ // Get the parent type for brace and parenthesis open
+ E_Token parent = get_chunk_parent_type(pc);
+
+ if ( chunk_is_token(pc, CT_PAREN_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_SPAREN_OPEN)
+ || chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if (prev->IsNotNullChunk())
+ {
+ if ( chunk_is_token(pc, CT_PAREN_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_SPAREN_OPEN))
+ {
+ // Set the parent for parenthesis and change parenthesis type
+ if ( chunk_is_token(prev, CT_IF)
+ || chunk_is_token(prev, CT_CONSTEXPR)
+ || chunk_is_token(prev, CT_ELSEIF)
+ || chunk_is_token(prev, CT_WHILE)
+ || chunk_is_token(prev, CT_WHILE_OF_DO)
+ || chunk_is_token(prev, CT_DO)
+ || chunk_is_token(prev, CT_FOR)
+ || chunk_is_token(prev, CT_SWITCH)
+ || chunk_is_token(prev, CT_CATCH)
+ || chunk_is_token(prev, CT_SYNCHRONIZED)
+ || chunk_is_token(prev, CT_D_VERSION)
+ || chunk_is_token(prev, CT_D_VERSION_IF)
+ || chunk_is_token(prev, CT_D_SCOPE)
+ || chunk_is_token(prev, CT_D_SCOPE_IF))
+ {
+ set_chunk_type(pc, CT_SPAREN_OPEN);
+ parent = frm.top().type;
+ frm.sparen_count++;
+ }
+ else if (chunk_is_token(prev, CT_FUNCTION))
+ {
+ set_chunk_type(pc, CT_FPAREN_OPEN);
+ parent = CT_FUNCTION;
+ }
+ // NS_ENUM and NS_OPTIONS are followed by a (type, name) pair
+ else if ( chunk_is_token(prev, CT_ENUM)
+ && language_is_set(LANG_OC))
+ {
+ // Treat both as CT_ENUM since the syntax is identical
+ set_chunk_type(pc, CT_FPAREN_OPEN);
+ parent = CT_ENUM;
+ }
+ else if (chunk_is_token(prev, CT_DECLSPEC)) // Issue 1289
+ {
+ parent = CT_DECLSPEC;
+ }
+ // else: no need to set parent
+ }
+ else // must be CT_BRACE_OPEN
+ {
+ // Set the parent for open braces
+ if (frm.top().stage != brace_stage_e::NONE)
+ {
+ parent = frm.top().type;
+ }
+ else if ( chunk_is_token(prev, CT_ASSIGN)
+ && (prev->str[0] == '='))
+ {
+ parent = CT_ASSIGN;
+ }
+ else if ( chunk_is_token(prev, CT_RETURN)
+ && language_is_set(LANG_CPP))
+ {
+ parent = CT_RETURN;
+ }
+ // Carry through CT_ENUM parent in NS_ENUM (type, name) {
+ // only to help the vim command }
+ else if ( chunk_is_token(prev, CT_FPAREN_CLOSE)
+ && language_is_set(LANG_OC)
+ && get_chunk_parent_type(prev) == CT_ENUM)
+ {
+ parent = CT_ENUM;
+ }
+ else if (chunk_is_token(prev, CT_FPAREN_CLOSE))
+ {
+ parent = CT_FUNCTION;
+ }
+ // else: no need to set parent
+ }
+ }
+ }
+
+ /*
+ * Adjust the level for opens & create a stack entry
+ * Note that CT_VBRACE_OPEN has already been handled.
+ */
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_PAREN_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_SPAREN_OPEN)
+ || chunk_is_token(pc, CT_ANGLE_OPEN)
+ || chunk_is_token(pc, CT_MACRO_OPEN)
+ || chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ frm.level++;
+
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_MACRO_OPEN))
+ {
+ // Issue #1813
+ bool single = false;
+
+ if (get_chunk_parent_type(pc) == CT_NAMESPACE)
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): parent_type is NAMESPACE\n",
+ __func__, __LINE__);
+ Chunk *tmp = frm.top().pc;
+
+ if ( tmp != nullptr
+ && get_chunk_parent_type(tmp) == CT_NAMESPACE)
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): tmp->parent_type is NAMESPACE\n",
+ __func__, __LINE__);
+
+ log_rule_B("indent_namespace");
+ log_rule_B("indent_namespace_single_indent");
+
+ if ( options::indent_namespace()
+ && options::indent_namespace_single_indent())
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): Options are SINGLE\n",
+ __func__, __LINE__);
+ single = true;
+ }
+ }
+ }
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s, parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)));
+
+ if (!single)
+ {
+ frm.brace_level++;
+ LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level increased to %zu\n",
+ __func__, __LINE__, frm.brace_level);
+ }
+ }
+ frm.push(pc, __func__, __LINE__);
+ frm.top().parent = parent;
+ // set parent type
+ set_chunk_parent(pc, parent);
+ }
+ // Issue #2281
+
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->parent_type == CT_SWITCH)
+ {
+ size_t idx = frm.size();
+ LOG_FMT(LBCSPOP, "%s(%d): idx is %zu\n",
+ __func__, __LINE__, idx);
+ Chunk *saved = frm.at(idx - 2).pc;
+
+ if (saved != nullptr)
+ {
+ // set parent member
+ chunk_set_parent(pc, saved);
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_CASE)
+ || chunk_is_token(pc, CT_DEFAULT))
+ {
+ Chunk *prev = pc->GetPrevNcNnl(); // Issue #3176
+
+ if ( chunk_is_token(pc, CT_CASE)
+ || ( chunk_is_token(pc, CT_DEFAULT)
+ && chunk_is_not_token(prev, CT_ASSIGN)))
+ {
+ // it is a CT_DEFAULT from a switch
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ set_chunk_parent(pc, CT_SWITCH);
+ size_t idx = frm.size();
+ LOG_FMT(LBCSPOP, "%s(%d): idx is %zu\n",
+ __func__, __LINE__, idx);
+ Chunk *saved = frm.at(idx - 2).pc;
+
+ if (saved != nullptr)
+ {
+ // set parent member
+ chunk_set_parent(pc, saved);
+ }
+ }
+ }
+
+ if (chunk_is_token(pc, CT_BREAK))
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ size_t idx = frm.size();
+ LOG_FMT(LBCSPOP, "%s(%d): idx is %zu\n",
+ __func__, __LINE__, idx);
+ Chunk *saved = frm.at(idx - 2).pc;
+
+ if (saved != nullptr)
+ {
+ // set parent member
+ chunk_set_parent(pc, saved);
+ }
+ }
+ const pattern_class_e patcls = get_token_pattern_class(pc->type);
+
+ /*
+ * Create a stack entry for complex statements:
+ * if, elseif, switch, for, while, synchronized, using, lock, with,
+ * version, CT_D_SCOPE_IF
+ */
+ if (patcls == pattern_class_e::BRACED)
+ {
+ frm.push(pc, __func__, __LINE__, (chunk_is_token(pc, CT_DO) ? brace_stage_e::BRACE_DO
+ : brace_stage_e::BRACE2));
+ // "+ComplexBraced"
+ }
+ else if (patcls == pattern_class_e::PBRACED)
+ {
+ brace_stage_e bs = brace_stage_e::PAREN1;
+
+ if ( chunk_is_token(pc, CT_WHILE)
+ && maybe_while_of_do(pc))
+ {
+ set_chunk_type(pc, CT_WHILE_OF_DO);
+ bs = brace_stage_e::WOD_PAREN;
+ }
+ frm.push(pc, __func__, __LINE__, bs);
+ // "+ComplexParenBraced"
+ }
+ else if (patcls == pattern_class_e::OPBRACED)
+ {
+ frm.push(pc, __func__, __LINE__, brace_stage_e::OP_PAREN1);
+ // "+ComplexOpParenBraced");
+ }
+ else if (patcls == pattern_class_e::ELSE)
+ {
+ frm.push(pc, __func__, __LINE__, brace_stage_e::ELSEIF);
+ // "+ComplexElse");
+ }
+
+ /*
+ * Mark simple statement/expression starts
+ * - after { or }
+ * - after ';', but not if the paren stack top is a paren
+ * - after '(' that has a parent type of CT_FOR
+ */
+ if ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && get_chunk_parent_type(pc) != CT_ASSIGN)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE)
+ || ( chunk_is_token(pc, CT_SPAREN_OPEN)
+ && get_chunk_parent_type(pc) == CT_FOR)
+ || chunk_is_token(pc, CT_COLON)
+ || chunk_is_token(pc, CT_OC_END)
+ || ( chunk_is_semicolon(pc)
+ && frm.top().type != CT_PAREN_OPEN
+ && frm.top().type != CT_FPAREN_OPEN
+ && frm.top().type != CT_SPAREN_OPEN)
+ || chunk_is_token(pc, CT_MACRO)) // Issue #2742
+ {
+ LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, reset1 stmt on '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->Text());
+ frm.stmt_count = 0;
+ frm.expr_count = 0;
+ LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n",
+ __func__, __LINE__, frm.stmt_count, frm.expr_count);
+ }
+ // Mark expression starts
+ LOG_FMT(LSTMT, "%s(%d): Mark expression starts: orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if ( chunk_is_token(pc, CT_ARITH)
+ || chunk_is_token(pc, CT_SHIFT)
+ || chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_CASE)
+ || chunk_is_token(pc, CT_COMPARE)
+ || ( chunk_is_token(pc, CT_STAR)
+ && chunk_is_not_token(tmp, CT_STAR))
+ || chunk_is_token(pc, CT_BOOL)
+ || chunk_is_token(pc, CT_MINUS)
+ || chunk_is_token(pc, CT_PLUS)
+ || chunk_is_token(pc, CT_CARET)
+ || chunk_is_token(pc, CT_ANGLE_OPEN)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE)
+ || chunk_is_token(pc, CT_RETURN)
+ || chunk_is_token(pc, CT_THROW)
+ || chunk_is_token(pc, CT_GOTO)
+ || chunk_is_token(pc, CT_CONTINUE)
+ || chunk_is_token(pc, CT_PAREN_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_SPAREN_OPEN)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_NOT)
+ || chunk_is_token(pc, CT_INV)
+ || chunk_is_token(pc, CT_COLON)
+ || chunk_is_token(pc, CT_QUESTION))
+ {
+ frm.expr_count = 0;
+ LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, orig_col is %zu, reset expr on '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ }
+} // parse_cleanup
+
+
+static bool check_complex_statements(ParseFrame &frm, Chunk *pc, const BraceState &braceState)
+{
+ LOG_FUNC_ENTRY();
+
+ brace_stage_e atest = frm.top().stage;
+
+ LOG_FMT(LBCSPOP, "%s(%d): atest is %s\n",
+ __func__, __LINE__, get_brace_stage_name(atest));
+
+ // Turn an optional parenthesis into either a real parenthesis or a brace
+ if (frm.top().stage == brace_stage_e::OP_PAREN1)
+ {
+ frm.top().stage = (chunk_is_not_token(pc, CT_PAREN_OPEN))
+ ? brace_stage_e::BRACE2
+ : brace_stage_e::PAREN1;
+ LOG_FMT(LBCSPOP, "%s(%d): frm.top().stage is now %s\n",
+ __func__, __LINE__, get_brace_stage_name(frm.top().stage));
+ }
+
+ // Check for CT_ELSE after CT_IF
+ while (frm.top().stage == brace_stage_e::ELSE)
+ {
+ if (chunk_is_token(pc, CT_ELSE))
+ {
+ // Replace CT_IF with CT_ELSE on the stack & we are done
+ frm.top().type = CT_ELSE;
+ frm.top().stage = brace_stage_e::ELSEIF;
+ print_stack(LBCSSWAP, "=Swap ", frm);
+
+ return(true);
+ }
+ // Remove the CT_IF and close the statement
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-IF-CCS ", frm);
+
+ if (close_statement(frm, pc, braceState))
+ {
+ return(true);
+ }
+ }
+
+ // Check for CT_IF after CT_ELSE
+ if (frm.top().stage == brace_stage_e::ELSEIF)
+ {
+ log_rule_B("indent_else_if");
+
+ if ( chunk_is_token(pc, CT_IF)
+ && ( !options::indent_else_if()
+ || !chunk_is_newline(pc->GetPrevNc())))
+ {
+ // Replace CT_ELSE with CT_IF
+ set_chunk_type(pc, CT_ELSEIF);
+ frm.top().type = CT_ELSEIF;
+ frm.top().stage = brace_stage_e::PAREN1;
+ return(true);
+ }
+ // Jump to the 'expecting brace' stage
+ frm.top().stage = brace_stage_e::BRACE2;
+ }
+
+ // Check for CT_CATCH or CT_FINALLY after CT_TRY or CT_CATCH
+ while (frm.top().stage == brace_stage_e::CATCH)
+ {
+ if ( chunk_is_token(pc, CT_CATCH)
+ || chunk_is_token(pc, CT_FINALLY))
+ {
+ // Replace CT_TRY with CT_CATCH or CT_FINALLY on the stack & we are done
+ frm.top().type = pc->type;
+
+ if (language_is_set(LANG_CS))
+ {
+ frm.top().stage = (chunk_is_token(pc, CT_CATCH)) ? brace_stage_e::CATCH_WHEN : brace_stage_e::BRACE2;
+ }
+ else
+ {
+ // historically this used OP_PAREN1; however, to my knowledge the expression after a catch clause
+ // is only optional for C# which has been handled above; therefore, this should now always expect
+ // a parenthetical expression after the catch keyword and brace after the finally keyword
+ frm.top().stage = (chunk_is_token(pc, CT_CATCH)) ? brace_stage_e::PAREN1 : brace_stage_e::BRACE2;
+ }
+ print_stack(LBCSSWAP, "=Swap ", frm);
+
+ return(true);
+ }
+ // Remove the CT_TRY and close the statement
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-TRY-CCS ", frm);
+
+ if (close_statement(frm, pc, braceState))
+ {
+ return(true);
+ }
+ }
+
+ // Check for optional parenthesis and optional CT_WHEN after CT_CATCH
+ if (frm.top().stage == brace_stage_e::CATCH_WHEN)
+ {
+ if (chunk_is_token(pc, CT_PAREN_OPEN)) // this is for the paren after "catch"
+ {
+ // Replace CT_PAREN_OPEN with CT_SPAREN_OPEN
+ set_chunk_type(pc, CT_SPAREN_OPEN);
+ frm.top().type = pc->type;
+ frm.top().stage = brace_stage_e::PAREN1;
+
+ return(false);
+ }
+
+ if (chunk_is_token(pc, CT_WHEN))
+ {
+ frm.top().type = pc->type;
+ frm.top().stage = brace_stage_e::OP_PAREN1;
+
+ return(true);
+ }
+
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ frm.top().stage = brace_stage_e::BRACE2;
+
+ return(false);
+ }
+ }
+
+ // Check for CT_WHILE after the CT_DO
+ if (frm.top().stage == brace_stage_e::WHILE)
+ {
+ if (chunk_is_token(pc, CT_WHILE))
+ {
+ set_chunk_type(pc, CT_WHILE_OF_DO);
+ frm.top().type = CT_WHILE_OF_DO; //CT_WHILE;
+ frm.top().stage = brace_stage_e::WOD_PAREN;
+
+ return(true);
+ }
+ LOG_FMT(LWARN, "%s(%d): %s, orig_line is %zu, Error: Expected 'while', got '%s'\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc->orig_line,
+ pc->Text());
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-Error ", frm);
+ cpd.error_count++;
+ }
+ // Insert a CT_VBRACE_OPEN, if needed
+ // but not in a preprocessor
+ atest = frm.top().stage;
+
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && !pc->flags.test(PCF_IN_PREPROC)
+ && ( (frm.top().stage == brace_stage_e::BRACE2)
+ || (frm.top().stage == brace_stage_e::BRACE_DO)))
+ {
+ log_rule_B("indent_using_block");
+
+ if ( language_is_set(LANG_CS)
+ && chunk_is_token(pc, CT_USING_STMT)
+ && (!options::indent_using_block()))
+ {
+ // don't indent the using block
+ }
+ else
+ {
+ const E_Token parent = frm.top().type;
+
+ Chunk *vbrace = insert_vbrace_open_before(pc, frm);
+ set_chunk_parent(vbrace, parent);
+
+ frm.level++;
+ frm.brace_level++;
+ LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level increased to %zu\n",
+ __func__, __LINE__, frm.brace_level);
+ log_pcf_flags(LBCSPOP, pc->flags);
+
+ frm.push(vbrace, __func__, __LINE__, brace_stage_e::NONE);
+ // "+VBrace");
+
+ frm.top().parent = parent;
+
+ // update the level of pc
+ pc->level = frm.level;
+ pc->brace_level = frm.brace_level;
+
+ // Mark as a start of a statement
+ frm.stmt_count = 0;
+ frm.expr_count = 0;
+ LOG_FMT(LTOK, "%s(%d): frm.stmt_count is %zu, frm.expr_count is %zu\n",
+ __func__, __LINE__, frm.stmt_count, frm.expr_count);
+ chunk_flags_set(pc, PCF_STMT_START | PCF_EXPR_START);
+ frm.stmt_count = 1;
+ frm.expr_count = 1;
+ LOG_FMT(LSTMT, "%s(%d): orig_line is %zu, 2.marked '%s' as stmt start\n",
+ __func__, __LINE__, pc->orig_line, pc->Text());
+ }
+ }
+
+ // Check for "constexpr" after CT_IF or CT_ELSEIF
+ if ( frm.top().stage == brace_stage_e::PAREN1
+ && ( frm.top().type == CT_IF
+ || frm.top().type == CT_ELSEIF)
+ && chunk_is_token(pc, CT_CONSTEXPR))
+ {
+ return(false);
+ }
+
+ // Verify open parenthesis in complex statement
+ if ( chunk_is_not_token(pc, CT_PAREN_OPEN)
+ && ( (frm.top().stage == brace_stage_e::PAREN1)
+ || (frm.top().stage == brace_stage_e::WOD_PAREN)))
+ {
+ LOG_FMT(LWARN, "%s(%d): %s, orig_line is %zu, Error: Expected '(', got '%s' for '%s'\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, pc->Text(),
+ get_token_name(frm.top().type));
+
+ // Throw out the complex statement
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-Error ", frm);
+ cpd.error_count++;
+ }
+ return(false);
+} // check_complex_statements
+
+
+static bool handle_complex_close(ParseFrame &frm, Chunk *pc, const BraceState &braceState)
+{
+ LOG_FUNC_ENTRY();
+
+ if (frm.top().stage == brace_stage_e::PAREN1)
+ {
+ if ( pc->next != nullptr
+ && pc->next->type == CT_WHEN)
+ {
+ frm.top().type = pc->type;
+ frm.top().stage = brace_stage_e::CATCH_WHEN;
+
+ return(true);
+ }
+ // PAREN1 always => BRACE2
+ frm.top().stage = brace_stage_e::BRACE2;
+ }
+ else if (frm.top().stage == brace_stage_e::BRACE2)
+ {
+ // BRACE2: IF => ELSE, anything else => close
+ if ( (frm.top().type == CT_IF)
+ || (frm.top().type == CT_ELSEIF))
+ {
+ frm.top().stage = brace_stage_e::ELSE;
+
+ // If the next chunk isn't CT_ELSE, close the statement
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( next->IsNullChunk()
+ || chunk_is_not_token(next, CT_ELSE))
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): no CT_ELSE, pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-IF-HCS ", frm);
+
+ return(close_statement(frm, pc, braceState));
+ }
+ }
+ else if ( (frm.top().type == CT_TRY)
+ || (frm.top().type == CT_CATCH))
+ {
+ frm.top().stage = brace_stage_e::CATCH;
+
+ // If the next chunk isn't CT_CATCH or CT_FINALLY, close the statement
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( chunk_is_not_token(next, CT_CATCH)
+ && chunk_is_not_token(next, CT_FINALLY))
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-TRY-HCS ", frm);
+
+ return(close_statement(frm, pc, braceState));
+ }
+ }
+ else
+ {
+ LOG_FMT(LNOTE, "%s(%d): close_statement on %s brace_stage_e::BRACE2\n",
+ __func__, __LINE__, get_token_name(frm.top().type));
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-HCC B2 ", frm);
+
+ return(close_statement(frm, pc, braceState));
+ }
+ }
+ else if (frm.top().stage == brace_stage_e::BRACE_DO)
+ {
+ frm.top().stage = brace_stage_e::WHILE;
+ }
+ else if (frm.top().stage == brace_stage_e::WOD_PAREN)
+ {
+ LOG_FMT(LNOTE, "%s(%d): close_statement on %s brace_stage_e::WOD_PAREN\n",
+ __func__, __LINE__, get_token_name(frm.top().type));
+ frm.top().stage = brace_stage_e::WOD_SEMI;
+ print_stack(LBCSPOP, "-HCC WoDP ", frm);
+ }
+ else if (frm.top().stage == brace_stage_e::WOD_SEMI)
+ {
+ LOG_FMT(LNOTE, "%s(%d): close_statement on %s brace_stage_e::WOD_SEMI\n",
+ __func__, __LINE__, get_token_name(frm.top().type));
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-HCC WoDS ", frm);
+
+ return(close_statement(frm, pc, braceState));
+ }
+ else
+ {
+ // PROBLEM
+ LOG_FMT(LWARN, "%s(%d): %s:%zu Error: TOS.type='%s' TOS.stage=%u\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc->orig_line,
+ get_token_name(frm.top().type),
+ (unsigned int)frm.top().stage);
+ cpd.error_count++;
+ }
+ return(false);
+} // handle_complex_close
+
+
+static void mark_namespace(Chunk *pns)
+{
+ LOG_FUNC_ENTRY();
+ // Issue #1813
+ Chunk *br_close;
+ bool is_using = false;
+
+ Chunk *pc = pns->GetPrevNcNnl();
+
+ if (chunk_is_token(pc, CT_USING))
+ {
+ is_using = true;
+ set_chunk_parent(pns, CT_USING);
+ }
+ pc = pns->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ set_chunk_parent(pc, CT_NAMESPACE);
+
+ if (chunk_is_not_token(pc, CT_BRACE_OPEN))
+ {
+ if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ if (is_using)
+ {
+ set_chunk_parent(pc, CT_USING);
+ }
+ return;
+ }
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+ log_rule_B("indent_namespace_limit");
+
+ if ( (options::indent_namespace_limit() > 0)
+ && ((br_close = chunk_skip_to_match(pc)) != nullptr))
+ {
+ // br_close->orig_line is always >= pc->orig_line;
+ size_t numberOfLines = br_close->orig_line - pc->orig_line - 1; // Issue #2345
+ LOG_FMT(LTOK, "%s(%d): br_close->orig_line is %zu, pc->orig_line is %zu\n",
+ __func__, __LINE__, br_close->orig_line, pc->orig_line);
+ LOG_FMT(LTOK, "%s(%d): numberOfLines is %zu, indent_namespace_limit() is %d\n",
+ __func__, __LINE__, numberOfLines, options::indent_namespace_limit());
+
+ log_rule_B("indent_namespace_limit");
+
+ if (numberOfLines > options::indent_namespace_limit())
+ {
+ LOG_FMT(LTOK, "%s(%d): PCF_LONG_BLOCK is set\n", __func__, __LINE__);
+ chunk_flags_set(pc, PCF_LONG_BLOCK);
+ chunk_flags_set(br_close, PCF_LONG_BLOCK);
+ }
+ }
+ flag_parens(pc, PCF_IN_NAMESPACE, CT_NONE, CT_NAMESPACE, false);
+ return;
+ }
+} // mark_namespace
+
+
+static Chunk *insert_vbrace(Chunk *pc, bool after, const ParseFrame &frm)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk chunk;
+
+ set_chunk_parent(&chunk, frm.top().type);
+ chunk.orig_line = pc->orig_line;
+ chunk.level = frm.level;
+ chunk.pp_level = frm.pp_level;
+ chunk.brace_level = frm.brace_level;
+ chunk.flags = pc->flags & PCF_COPY_FLAGS;
+ chunk.str = "";
+
+ if (after)
+ {
+ chunk.orig_col = pc->orig_col;
+ set_chunk_type(&chunk, CT_VBRACE_CLOSE);
+ return(chunk_add_after(&chunk, pc));
+ }
+ Chunk *ref = pc->GetPrev();
+
+ if (ref->IsNullChunk())
+ {
+ return(nullptr);
+ }
+
+ if (!ref->flags.test(PCF_IN_PREPROC))
+ {
+ chunk.flags &= ~PCF_IN_PREPROC;
+ }
+ bool ref_is_comment = ref->IsComment(); // Issue #3351
+
+ while ( chunk_is_newline(ref)
+ || ref->IsComment())
+ {
+ ref->level++;
+ ref->brace_level++;
+ ref = ref->GetPrev();
+ }
+
+ if (ref->IsNullChunk())
+ {
+ return(nullptr);
+ }
+
+ // Don't back into a preprocessor
+ if ( !pc->flags.test(PCF_IN_PREPROC)
+ && ref->flags.test(PCF_IN_PREPROC))
+ {
+ if (chunk_is_token(ref, CT_PREPROC_BODY))
+ {
+ while ( ref->IsNotNullChunk()
+ && ref->flags.test(PCF_IN_PREPROC))
+ {
+ ref = ref->GetPrev();
+ }
+ }
+ else
+ {
+ ref = ref->GetNext();
+
+ if (chunk_is_token(ref, CT_COMMENT)) // Issue #3034
+ {
+ ref = ref->GetNextNc();
+ }
+ }
+ }
+
+ if (ref_is_comment) // Issue #3351
+ {
+ ref = ref->GetNext();
+ }
+
+ if (ref->IsNullChunk())
+ {
+ return(nullptr);
+ }
+ chunk.orig_line = ref->orig_line;
+ chunk.orig_col = ref->orig_col;
+ chunk.column = ref->column + ref->Len() + 1;
+ chunk.pp_level = ref->pp_level; // Issue #3055
+ set_chunk_type(&chunk, CT_VBRACE_OPEN);
+
+ return(chunk_add_after(&chunk, ref));
+} // insert_vbrace
+
+
+bool close_statement(ParseFrame &frm, Chunk *pc, const BraceState &braceState)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ throw invalid_argument(string(__func__) + ":" + to_string(__LINE__)
+ + "args cannot be nullptr");
+ }
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, type is %s, '%s' type is %s, stage is %u\n",
+ __func__, __LINE__, pc->orig_line,
+ get_token_name(pc->type), pc->Text(),
+ get_token_name(frm.top().type),
+ (unsigned int)frm.top().stage);
+
+ if (braceState.consumed)
+ {
+ frm.stmt_count = 0;
+ frm.expr_count = 0;
+ LOG_FMT(LSTMT, "%s(%d): orig_line is %zu> reset2 stmt on '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->Text());
+ }
+ /*
+ * Insert a CT_VBRACE_CLOSE, if needed:
+ * If we are in a virtual brace and we are not ON a CT_VBRACE_CLOSE add one
+ */
+ Chunk *vbc = pc;
+
+ if (frm.top().type == CT_VBRACE_OPEN)
+ {
+ // If the current token has already been consumed, then add after it
+ if (braceState.consumed)
+ {
+ insert_vbrace_close_after(pc, frm);
+ }
+ else
+ {
+ // otherwise, add before it and consume the vbrace
+ vbc = pc->GetPrevNcNnl();
+
+ frm.level--;
+ frm.brace_level--;
+ vbc = insert_vbrace_close_after(vbc, frm);
+ set_chunk_parent(vbc, frm.top().parent);
+
+ LOG_FMT(LBCSPOP, "%s(%d): frm.brace_level decreased to %zu\n",
+ __func__, __LINE__, frm.brace_level);
+ log_pcf_flags(LBCSPOP, pc->flags);
+ LOG_FMT(LBCSPOP, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+
+ // Update the token level
+ pc->level = frm.level;
+ pc->brace_level = frm.brace_level;
+
+ print_stack(LBCSPOP, "-CS VB ", frm);
+
+ // And repeat the close
+ close_statement(frm, pc, braceState);
+ return(true);
+ }
+ }
+
+ // See if we are done with a complex statement
+ if (frm.top().stage != brace_stage_e::NONE)
+ {
+ if (handle_complex_close(frm, vbc, braceState))
+ {
+ return(true);
+ }
+ }
+ return(false);
+} // close_statement
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.h
new file mode 100644
index 00000000..4b2cfbba
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/brace_cleanup.h
@@ -0,0 +1,23 @@
+/**
+ * @file brace_cleanup.h
+ * prototypes for brace_cleanup.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef BRACE_CLEANUP_H_INCLUDED
+#define BRACE_CLEANUP_H_INCLUDED
+
+#include "uncrustify_types.h"
+// necessary to not sort
+#include "ParseFrame.h"
+
+/**
+ * Scans through the whole list and does stuff.
+ * It has to do some tricks to parse preprocessors.
+ */
+void brace_cleanup(void);
+
+
+#endif /* BRACE_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.cpp
new file mode 100644
index 00000000..0f88354c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.cpp
@@ -0,0 +1,1700 @@
+/**
+ * @file braces.cpp
+ * Adds or removes braces.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "braces.h"
+
+#include "calculate_closing_brace_position.h"
+#include "combine_tools.h"
+#include "newlines.h"
+#include "prototypes.h"
+
+constexpr static auto LCURRENT = LBR;
+
+using namespace uncrustify;
+
+using std::vector;
+
+
+//! Converts a single brace into a virtual brace
+static void convert_brace(Chunk *br);
+
+
+//! Converts a single virtual brace into a real brace
+static void convert_vbrace(Chunk *br);
+
+
+static void convert_vbrace_to_brace(void);
+
+
+//! Go backwards to honor brace newline removal limits
+static void examine_braces(void);
+
+
+/**
+ * Step forward and count the number of semi colons at the current level.
+ * Abort if more than 1 or if we enter a preprocessor
+ */
+static void examine_brace(Chunk *bopen);
+
+
+static void move_case_break(void);
+
+
+static void move_case_return(void);
+
+
+static void mod_case_brace(void);
+
+
+static void mod_full_brace_if_chain(void);
+
+
+/**
+ * Checks to see if the braces can be removed.
+ * - less than a certain length
+ * - doesn't mess up if/else stuff
+ */
+static bool can_remove_braces(Chunk *bopen);
+
+
+/**
+ * Checks to see if the virtual braces should be converted to real braces.
+ * - over a certain length
+ *
+ * @param vbopen Virtual Brace Open chunk
+ *
+ * @return true (convert to real braces) or false (leave alone)
+ */
+static bool should_add_braces(Chunk *vbopen);
+
+
+/**
+ * Collect the text into txt that contains the full tag name.
+ * Mainly for collecting namespace 'a.b.c' or function 'foo::bar()' names.
+ */
+static void append_tag_name(unc_text &txt, Chunk *pc);
+
+
+//! Remove the case brace, if allowable.
+static Chunk *mod_case_brace_remove(Chunk *br_open);
+
+
+//! Add the case brace, if allowable.
+static Chunk *mod_case_brace_add(Chunk *cl_colon);
+
+
+/**
+ * Traverse the if chain and see if all can be removed
+ *
+ * @param br_start chunk pointing to opening brace of if clause
+ */
+static void process_if_chain(Chunk *br_start);
+
+
+/**
+ * Check if parenthesis pair that comes before a brace spans multiple lines
+ *
+ *
+ * @param brace the brace chunk whose predecessing parenthesis will be checked
+ *
+ * @pre the brace chunk cannot be a nullptr,
+ * it needs to be of type CT_BRACE_OPEN or CT_BRACE_CLOSE,
+ * its parent type needs to be one of this types:
+ * CT_IF, CT_ELSEIF, CT_FOR, CT_USING_STMT, CT_WHILE,
+ * CT_FUNC_CLASS_DEF, CT_FUNC_DEF
+ *
+ * @return false: if preconditions are not met,
+ * if an error occurs while counting the newline between the
+ * parenthesis or
+ * when no newlines are found between the parenthesis
+ */
+static bool paren_multiline_before_brace(Chunk *brace)
+{
+ if ( brace == nullptr
+ || ( chunk_is_not_token(brace, CT_BRACE_OPEN)
+ && chunk_is_not_token(brace, CT_BRACE_CLOSE))
+ || ( get_chunk_parent_type(brace) != CT_IF
+ && get_chunk_parent_type(brace) != CT_ELSEIF
+ && get_chunk_parent_type(brace) != CT_FOR
+ && get_chunk_parent_type(brace) != CT_USING_STMT
+ && get_chunk_parent_type(brace) != CT_WHILE
+ && get_chunk_parent_type(brace) != CT_FUNC_CLASS_DEF
+ && get_chunk_parent_type(brace) != CT_FUNC_DEF))
+ {
+ return(false);
+ }
+ const auto paren_t = CT_SPAREN_CLOSE;
+
+ // find parenthesis pair of the if/for/while/...
+ auto paren_close = brace->GetPrevType(paren_t, brace->level, E_Scope::ALL);
+ auto paren_open = chunk_skip_to_match_rev(paren_close, E_Scope::ALL);
+
+ if ( paren_close->IsNullChunk()
+ || paren_open->IsNullChunk()
+ || paren_close == brace
+ || paren_open == paren_close)
+ {
+ return(false);
+ }
+ // determine number of lines in the parenthesis pair spans
+ auto nl_count = size_t{};
+ const auto ret_flag = newlines_between(paren_open, paren_close, nl_count);
+
+ if (!ret_flag)
+ {
+ LOG_FMT(LERR, "%s(%d): newlines_between error\n", __func__, __LINE__);
+ return(false);
+ }
+ // nl_count = 0 -> 1 line
+ return(nl_count > 0);
+}
+
+
+void do_braces(void)
+{
+ LOG_FUNC_ENTRY();
+ // Mark one-liners
+ // Issue #2232 put this at the beginning
+ Chunk *pc = Chunk::GetHead()->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && chunk_is_not_token(pc, CT_VBRACE_OPEN))
+ {
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+ Chunk *br_open = pc;
+ const E_Token brc_type = E_Token(pc->type + 1); // corresponds to closing type
+ // Detect empty bodies
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (chunk_is_token(tmp, brc_type))
+ {
+ chunk_flags_set(br_open, PCF_EMPTY_BODY);
+ chunk_flags_set(tmp, PCF_EMPTY_BODY);
+ }
+ // Scan for the brace close or a newline
+ tmp = br_open->GetNextNc();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if (chunk_is_newline(tmp))
+ {
+ break;
+ }
+
+ if ( chunk_is_token(tmp, brc_type)
+ && br_open->level == tmp->level)
+ {
+ flag_series(br_open, tmp, PCF_ONE_LINER);
+ break;
+ }
+ tmp = tmp->GetNextNc();
+ }
+ pc = pc->GetNextNcNnl();
+ }
+ log_rule_B("mod_full_brace_if_chain");
+ log_rule_B("mod_full_brace_if_chain_only");
+
+ if ( options::mod_full_brace_if_chain()
+ || options::mod_full_brace_if_chain_only())
+ {
+ mod_full_brace_if_chain();
+ }
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_while");
+
+ if ((options::mod_full_brace_if() |
+ options::mod_full_brace_do() |
+ options::mod_full_brace_for() |
+ options::mod_full_brace_using() |
+ options::mod_full_brace_while()) & IARF_REMOVE)
+ {
+ examine_braces();
+ }
+ // convert vbraces if needed
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_function");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_while");
+
+ if ((options::mod_full_brace_if() |
+ options::mod_full_brace_do() |
+ options::mod_full_brace_for() |
+ options::mod_full_brace_function() |
+ options::mod_full_brace_using() |
+ options::mod_full_brace_while()) & IARF_ADD)
+ {
+ convert_vbrace_to_brace();
+ }
+ log_rule_B("mod_case_brace");
+
+ if (options::mod_case_brace() != IARF_IGNORE)
+ {
+ mod_case_brace();
+ }
+ log_rule_B("mod_move_case_break");
+
+ if (options::mod_move_case_break())
+ {
+ move_case_break();
+ }
+ log_rule_B("mod_move_case_return");
+
+ if (options::mod_move_case_return())
+ {
+ move_case_return();
+ }
+} // do_braces
+
+
+static void examine_braces(void)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_full_brace_nl_block_rem_mlcond");
+ const auto multiline_block = options::mod_full_brace_nl_block_rem_mlcond();
+
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_while");
+
+ for (Chunk *pc = Chunk::GetTail(); pc->IsNotNullChunk();)
+ {
+ Chunk *prev = pc->GetPrevType(CT_BRACE_OPEN, -1);
+
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && !pc->flags.test(PCF_IN_PREPROC)
+ && ( ( ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSE
+ || get_chunk_parent_type(pc) == CT_ELSEIF)
+ && options::mod_full_brace_if() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_DO
+ && options::mod_full_brace_do() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_FOR
+ && options::mod_full_brace_for() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_USING_STMT
+ && options::mod_full_brace_using() == IARF_REMOVE)
+ || ( get_chunk_parent_type(pc) == CT_WHILE
+ && options::mod_full_brace_while() == IARF_REMOVE)))
+ {
+ if ( multiline_block
+ && paren_multiline_before_brace(pc))
+ {
+ pc = prev;
+ continue;
+ }
+ examine_brace(pc);
+ }
+ pc = prev;
+ }
+} // examine_braces
+
+
+static bool should_add_braces(Chunk *vbopen)
+{
+ LOG_FUNC_ENTRY();
+ log_rule_B("mod_full_brace_nl");
+ const size_t nl_max = options::mod_full_brace_nl();
+
+ if (nl_max == 0)
+ {
+ return(false);
+ }
+ LOG_FMT(LBRDEL, "%s(%d): start on %zu:\n",
+ __func__, __LINE__, vbopen->orig_line);
+
+ size_t nl_count = 0;
+
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ for (pc = vbopen->GetNextNc(E_Scope::PREPROC);
+ (pc->IsNotNullChunk() && pc->level > vbopen->level);
+ pc = pc->GetNextNc(E_Scope::PREPROC))
+ {
+ if (chunk_is_newline(pc))
+ {
+ nl_count += pc->nl_count;
+ }
+ }
+
+ if ( pc->IsNotNullChunk()
+ && nl_count > nl_max
+ && vbopen->pp_level == pc->pp_level)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
+ __func__, __LINE__, nl_max);
+ return(true);
+ }
+ return(false);
+}
+
+
+static bool can_remove_braces(Chunk *bopen)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LBRDEL, "%s(%d): start on line %zu:\n",
+ __func__, __LINE__, bopen->orig_line);
+
+ // Cannot remove braces inside a preprocessor
+ if (bopen->flags.test(PCF_IN_PREPROC))
+ {
+ return(false);
+ }
+ Chunk *pc = bopen->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ // Can't remove empty statement
+ return(false);
+ }
+ const size_t level = bopen->level + 1;
+
+ log_rule_B("mod_full_brace_nl");
+ const size_t nl_max = options::mod_full_brace_nl();
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ size_t semi_count = 0;
+ bool hit_semi = false;
+ size_t nl_count = 0;
+ size_t if_count = 0;
+ int br_count = 0;
+
+ pc = bopen->GetNextNc(E_Scope::ALL);
+ LOG_FMT(LBRDEL, "%s(%d): - begin with token '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= level)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): test token '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ // Cannot remove braces that contain a preprocessor
+ return(false);
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ nl_count += pc->nl_count;
+
+ if ( nl_max > 0
+ && nl_count > nl_max)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
+ __func__, __LINE__, nl_max);
+ return(false);
+ }
+ }
+ else
+ {
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ br_count++;
+ }
+ else if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ if (br_count == 0)
+ {
+ fprintf(stderr, "%s(%d): br_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ br_count--;
+
+ if (pc->level == level)
+ {
+ // mean a statement in a braces { stmt; }
+ // as a statement with a semicolon { stmt; };
+ ++semi_count;
+ hit_semi = true;
+ }
+ }
+ else if ( ( chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF))
+ && br_count == 0)
+ {
+ if_count++;
+ }
+
+ if (pc->level == level)
+ {
+ if ( semi_count > 0
+ && hit_semi)
+ {
+ // should have bailed due to close brace level drop
+ LOG_FMT(LBRDEL, "%s(%d): no close brace\n", __func__, __LINE__);
+ return(false);
+ }
+ LOG_FMT(LBRDEL, "%s(%d): Text() '%s', orig_line is %zu, semi_count is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, semi_count);
+
+ if (chunk_is_token(pc, CT_ELSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ return(false);
+ }
+
+ if ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF)
+ || chunk_is_token(pc, CT_FOR)
+ || chunk_is_token(pc, CT_DO)
+ || chunk_is_token(pc, CT_WHILE)
+ || chunk_is_token(pc, CT_USING_STMT)
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && chunk_is_token(prev, CT_FPAREN_CLOSE)))
+ {
+ hit_semi |= chunk_is_semicolon(pc);
+
+ if (++semi_count > 1)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on %zu because of '%s' on line %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->Text(), pc->orig_line);
+ return(false);
+ }
+ }
+ }
+ }
+ prev = pc;
+ pc = pc->GetNextNc();
+ }
+
+ if (pc->IsNullChunk())
+ {
+ LOG_FMT(LBRDEL, "%s(%d): pc is null chunk\n", __func__, __LINE__);
+ return(false);
+ }
+
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_IF)
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+ Chunk *tmp_prev = pc->GetPrevNcNnl(E_Scope::PREPROC);
+
+ if ( chunk_is_token(next, CT_ELSE)
+ && ( chunk_is_token(tmp_prev, CT_BRACE_CLOSE)
+ || chunk_is_token(tmp_prev, CT_VBRACE_CLOSE))
+ && get_chunk_parent_type(tmp_prev) == CT_IF)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): - bailed on '%s'[%s] on line %zu due to 'if' and 'else' sequence\n",
+ __func__, __LINE__, get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)),
+ pc->orig_line);
+ return(false);
+ }
+ }
+ LOG_FMT(LBRDEL, "%s(%d): - end on '%s' on line %zu. if_count is %zu semi_count is %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), pc->orig_line, if_count, semi_count);
+
+ return( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && pc->pp_level == bopen->pp_level);
+} // can_remove_braces
+
+
+static void examine_brace(Chunk *bopen)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LBRDEL, "%s(%d): start on orig_line %zu, bopen->level is %zu\n",
+ __func__, __LINE__, bopen->orig_line, bopen->level);
+
+ const size_t level = bopen->level + 1;
+
+ log_rule_B("mod_full_brace_nl");
+ const size_t nl_max = options::mod_full_brace_nl();
+
+ Chunk *prev = Chunk::NullChunkPtr;
+ size_t semi_count = 0;
+ bool hit_semi = false;
+ size_t nl_count = 0;
+ size_t if_count = 0;
+ int br_count = 0;
+
+ Chunk *pc = bopen->GetNextNc();
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= level)
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ }
+
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ // Cannot remove braces that contain a preprocessor
+ LOG_FMT(LBRDEL, "%s(%d): PREPROC\n", __func__, __LINE__);
+ return;
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ nl_count += pc->nl_count;
+
+ if ( nl_max > 0
+ && nl_count > nl_max)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
+ __func__, __LINE__, nl_max);
+ return;
+ }
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): for pc->Text() '%s', pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->level, bopen->level);
+
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->level == bopen->level)
+ {
+ br_count++;
+ LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, br_count, pc->level, bopen->level);
+ }
+ else if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && pc->level == bopen->level)
+ {
+ if (br_count == 0)
+ {
+ fprintf(stderr, "%s(%d): br_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ br_count--;
+ LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, br_count, pc->level, bopen->level);
+
+ if (br_count == 0)
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( next->IsNullChunk()
+ || chunk_is_not_token(next, CT_BRACE_CLOSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): junk after close brace\n", __func__, __LINE__);
+ return;
+ }
+ }
+ }
+ else if ( ( chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF))
+ && br_count == 0)
+ {
+ if_count++;
+ }
+ LOG_FMT(LBRDEL, "%s(%d): pc->level is %zu, level is %zu\n",
+ __func__, __LINE__, pc->level, level);
+
+ if (pc->level == level)
+ {
+ if ( semi_count > 0
+ && hit_semi)
+ {
+ // should have bailed due to close brace level drop
+ LOG_FMT(LBRDEL, "%s(%d): no close brace\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LBRDEL, "%s(%d): Text() '%s', orig_line is %zu, semi_count is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, semi_count);
+
+ if (chunk_is_token(pc, CT_ELSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ return;
+ }
+
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', prev->Text '%s', prev->type %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), prev->Text(), get_token_name(prev->type));
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', prev is a null chunk\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ }
+ LOG_FMT(LBRDEL, "%s(%d): for pc->Text() '%s', pc->level is %zu, bopen->level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->level, bopen->level);
+
+ if ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSEIF)
+ || chunk_is_token(pc, CT_FOR)
+ || chunk_is_token(pc, CT_DO)
+ || chunk_is_token(pc, CT_WHILE)
+ || chunk_is_token(pc, CT_SWITCH)
+ || chunk_is_token(pc, CT_USING_STMT)
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->level == bopen->level)) // Issue #1758
+ {
+ LOG_FMT(LBRDEL, "%s(%d): pc->Text() '%s', orig_line is %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+ hit_semi |= chunk_is_semicolon(pc);
+ semi_count++;
+ LOG_FMT(LBRDEL, "%s(%d): semi_count is %zu\n",
+ __func__, __LINE__, semi_count);
+
+ if (semi_count > 1)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on %zu because of '%s' on line %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->Text(), pc->orig_line);
+ return;
+ }
+ }
+ }
+ }
+ prev = pc;
+ pc = pc->GetNext(); // Issue #1907
+ }
+
+ if (pc == nullptr)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): pc is nullptr\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LBRDEL, "%s(%d): - end on '%s' on line %zu. if_count is %zu, semi_count is %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), pc->orig_line, if_count, semi_count);
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNotNullChunk())
+ {
+ while (chunk_is_token(next, CT_VBRACE_CLOSE))
+ {
+ next = next->GetNextNcNnl();
+ }
+
+ if (next->IsNotNullChunk())
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, next is '%s'\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, get_token_name(next->type));
+ }
+
+ if ( if_count > 0
+ && ( chunk_is_token(next, CT_ELSE)
+ || chunk_is_token(next, CT_ELSEIF)))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on because 'else' is next and %zu ifs\n",
+ __func__, __LINE__, if_count);
+ return;
+ }
+ }
+ LOG_FMT(LBRDEL, "%s(%d): semi_count is %zu\n",
+ __func__, __LINE__, semi_count);
+
+ if (semi_count > 0)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bopen->parent_type is %s\n",
+ __func__, __LINE__, get_token_name(get_chunk_parent_type(bopen)));
+
+ if (get_chunk_parent_type(bopen) == CT_ELSE)
+ {
+ Chunk *tmp_next = bopen->GetNextNcNnl();
+
+ if (chunk_is_token(tmp_next, CT_IF))
+ {
+ Chunk *tmp_prev = bopen->GetPrevNcNnl();
+ LOG_FMT(LBRDEL, "%s(%d): else-if removing braces on line %zu and %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->orig_line);
+
+ chunk_del(bopen);
+ chunk_del(pc);
+ newline_del_between(tmp_prev, tmp_next);
+
+ log_rule_B("nl_else_if");
+
+ if (options::nl_else_if() & IARF_ADD)
+ {
+ newline_add_between(tmp_prev, tmp_next);
+ }
+ return;
+ }
+ }
+ // we have a pair of braces with only 1 statement inside
+ LOG_FMT(LBRDEL, "%s(%d): we have a pair of braces with only 1 statement inside\n",
+ __func__, __LINE__);
+ LOG_FMT(LBRDEL, "%s(%d): removing braces on line %zu and %zu\n",
+ __func__, __LINE__, bopen->orig_line, pc->orig_line);
+ convert_brace(bopen);
+ convert_brace(pc);
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): empty statement\n", __func__, __LINE__);
+ }
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): not a close brace? - '%s'\n",
+ __func__, __LINE__, pc->Text());
+ }
+} // examine_brace
+
+
+static void convert_brace(Chunk *br)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( br == nullptr
+ || br->flags.test(PCF_KEEP_BRACE))
+ {
+ return;
+ }
+ Chunk *tmp;
+
+ if (chunk_is_token(br, CT_BRACE_OPEN))
+ {
+ set_chunk_type(br, CT_VBRACE_OPEN);
+ br->str.clear();
+ tmp = br->GetPrev();
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+ }
+ else if (chunk_is_token(br, CT_BRACE_CLOSE))
+ {
+ set_chunk_type(br, CT_VBRACE_CLOSE);
+ br->str.clear();
+ tmp = br->GetNext();
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ if (chunk_is_newline(tmp))
+ {
+ if (tmp->nl_count > 1)
+ {
+ if (!br->flags.test(PCF_ONE_LINER)) // Issue #2232
+ {
+ tmp->nl_count--;
+ LOG_FMT(LBRDEL, "%s(%d): tmp->nl_count is %zu\n",
+ __func__, __LINE__, tmp->nl_count);
+ }
+ }
+ else
+ {
+ // Issue #2219
+ // look for opening brace
+ Chunk *brace = Chunk::NullChunkPtr;
+
+ if (chunk_is_token(br, CT_VBRACE_OPEN))
+ {
+ brace = tmp;
+ }
+ else if (chunk_is_token(br, CT_VBRACE_CLOSE))
+ {
+ brace = chunk_skip_to_match_rev(br);
+
+ if (brace->IsNullChunk())
+ {
+ brace = br->GetPrevType(CT_BRACE_OPEN, br->level);
+ }
+ }
+
+ if ( chunk_is_token(br, CT_VBRACE_OPEN)
+ || ( chunk_is_token(br, CT_VBRACE_CLOSE)
+ && brace->orig_line < tmp->orig_line))
+ {
+ if (chunk_safe_to_del_nl(tmp))
+ {
+ chunk_del(tmp);
+ }
+ }
+ }
+ }
+} // convert_brace
+
+
+static void convert_vbrace(Chunk *vbr)
+{
+ LOG_FUNC_ENTRY();
+
+ if (vbr == nullptr)
+ {
+ return;
+ }
+
+ if (chunk_is_token(vbr, CT_VBRACE_OPEN))
+ {
+ set_chunk_type(vbr, CT_BRACE_OPEN);
+ vbr->str = "{";
+
+ /*
+ * If the next chunk is a preprocessor, then move the open brace after the
+ * preprocessor.
+ */
+ Chunk *tmp = vbr->GetNext();
+
+ if (chunk_is_token(tmp, CT_PREPROC))
+ {
+ tmp = vbr->GetNext(E_Scope::PREPROC);
+ chunk_move_after(vbr, tmp);
+ newline_add_after(vbr);
+ }
+ }
+ else if (chunk_is_token(vbr, CT_VBRACE_CLOSE))
+ {
+ set_chunk_type(vbr, CT_BRACE_CLOSE);
+ vbr->str = "}";
+
+ /*
+ * If the next chunk is a comment, followed by a newline, then
+ * move the brace after the newline and add another newline after
+ * the close brace.
+ */
+ Chunk *tmp = vbr->GetNext();
+
+ if (tmp->IsComment())
+ {
+ tmp = tmp->GetNext();
+
+ if (chunk_is_newline(tmp))
+ {
+ chunk_move_after(vbr, tmp);
+ newline_add_after(vbr);
+ }
+ }
+ }
+} // convert_vbrace
+
+
+static void convert_vbrace_to_brace(void)
+{
+ LOG_FUNC_ENTRY();
+
+ // Find every vbrace open
+ log_rule_B("mod_full_brace_if");
+ log_rule_B("mod_full_brace_if_chain");
+ log_rule_B("mod_full_brace_for");
+ log_rule_B("mod_full_brace_do");
+ log_rule_B("mod_full_brace_while");
+ log_rule_B("mod_full_brace_using");
+ log_rule_B("mod_full_brace_function");
+
+ for (Chunk *pc = Chunk::GetHead(); pc != nullptr && pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (chunk_is_not_token(pc, CT_VBRACE_OPEN))
+ {
+ continue;
+ }
+ auto const in_preproc = pc->flags.test(PCF_IN_PREPROC);
+
+ if ( ( ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSE
+ || get_chunk_parent_type(pc) == CT_ELSEIF)
+ && (options::mod_full_brace_if() & IARF_ADD)
+ && !options::mod_full_brace_if_chain())
+ || ( get_chunk_parent_type(pc) == CT_FOR
+ && (options::mod_full_brace_for() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_DO
+ && (options::mod_full_brace_do() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_WHILE
+ && (options::mod_full_brace_while() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_USING_STMT
+ && (options::mod_full_brace_using() & IARF_ADD))
+ || ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ && (options::mod_full_brace_function() & IARF_ADD)))
+ {
+ // Find the matching vbrace close
+ Chunk *vbc = Chunk::NullChunkPtr;
+ Chunk *tmp = pc->GetNext();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( in_preproc
+ && !tmp->flags.test(PCF_IN_PREPROC))
+ {
+ // Can't leave a preprocessor
+ break;
+ }
+
+ if ( pc->brace_level == tmp->brace_level
+ && chunk_is_token(tmp, CT_VBRACE_CLOSE)
+ && get_chunk_parent_type(pc) == get_chunk_parent_type(tmp)
+ && ((tmp->flags & PCF_IN_PREPROC) == (pc->flags & PCF_IN_PREPROC)))
+ {
+ vbc = tmp;
+ break;
+ }
+ tmp = tmp->GetNext();
+ }
+
+ if (vbc->IsNullChunk())
+ {
+ continue;
+ }
+ // if we found a corresponding virtual closing brace
+ convert_vbrace(pc); // convert both the opening
+ convert_vbrace(vbc); // and closing brace
+ }
+ }
+} // convert_vbrace_to_brace
+
+
+Chunk *insert_comment_after(Chunk *ref, E_Token cmt_type,
+ const unc_text &cmt_text)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk new_cmt = *ref;
+
+ new_cmt.prev = nullptr;
+ new_cmt.next = nullptr;
+ new_cmt.flags = (ref->flags & PCF_COPY_FLAGS);
+ set_chunk_type(&new_cmt, cmt_type);
+ new_cmt.str.clear();
+
+ if (cmt_type == CT_COMMENT_CPP)
+ {
+ new_cmt.str.append("// ");
+ new_cmt.str.append(cmt_text);
+ }
+ else
+ {
+ if (chunk_is_token(ref, CT_PP_ELSE))
+ { // make test c/ 02501 stable
+ new_cmt.str.append(" ");
+ }
+ new_cmt.str.append("/* ");
+ new_cmt.str.append(cmt_text);
+ new_cmt.str.append(" */");
+ }
+ // TODO: expand comment type to cover other comment styles?
+
+ new_cmt.column = ref->column + ref->Len() + 1;
+ new_cmt.orig_col = new_cmt.column;
+
+ return(chunk_add_after(&new_cmt, ref));
+}
+
+
+static void append_tag_name(unc_text &txt, Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *tmp = pc->GetPrevNcNnl();
+
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+
+ // step backwards over all a::b stuff
+ while (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_not_token(tmp, CT_DC_MEMBER)
+ && chunk_is_not_token(tmp, CT_MEMBER))
+ {
+ break;
+ }
+ tmp = tmp->GetPrevNcNnl();
+ pc = tmp;
+
+ if (!chunk_is_word(tmp))
+ {
+ break;
+ }
+ }
+ txt += pc->str;
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+
+ pc = pc->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( chunk_is_not_token(pc, CT_DC_MEMBER)
+ && chunk_is_not_token(pc, CT_MEMBER))
+ {
+ break;
+ }
+ txt += pc->str;
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNotNullChunk())
+ {
+ txt += pc->str;
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+ }
+ pc = pc->GetNextNcNnl();
+ }
+} // append_tag_name
+
+
+void add_long_closebrace_comment(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *fcn_pc = Chunk::NullChunkPtr;
+ Chunk *sw_pc = Chunk::NullChunkPtr;
+ Chunk *ns_pc = Chunk::NullChunkPtr;
+ Chunk *cl_pc = Chunk::NullChunkPtr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc, CT_FUNC_DEF)
+ || chunk_is_token(pc, CT_OC_MSG_DECL))
+ {
+ fcn_pc = pc;
+ }
+ else if (chunk_is_token(pc, CT_SWITCH))
+ {
+ // pointless, since it always has the text "switch"
+ sw_pc = pc;
+ }
+ else if (chunk_is_token(pc, CT_NAMESPACE))
+ {
+ ns_pc = pc;
+ }
+ else if (chunk_is_token(pc, CT_CLASS))
+ {
+ cl_pc = pc;
+ }
+
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ || pc->flags.test(PCF_IN_PREPROC))
+ {
+ continue;
+ }
+ Chunk *br_open = pc;
+ size_t nl_count = 0;
+
+ Chunk *tmp = pc;
+
+ while ((tmp = tmp->GetNext(E_Scope::PREPROC))->IsNotNullChunk())
+ {
+ if (chunk_is_newline(tmp))
+ {
+ nl_count += tmp->nl_count;
+ continue;
+ }
+
+ // handle only matching closing braces, skip other chunks
+ if ( tmp->level != br_open->level
+ || chunk_is_not_token(tmp, CT_BRACE_CLOSE))
+ {
+ continue;
+ }
+ Chunk *br_close = tmp;
+
+ tmp = tmp->GetNext();
+
+ // check for a possible end semicolon
+ if (chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ // set br_close to the semi token,
+ // as br_close is used to add the coment after it
+ br_close = tmp;
+ tmp = tmp->GetNext();
+ }
+
+ // make sure a newline follows in order to not overwrite an already
+ // existring comment
+ if ( tmp->IsNotNullChunk()
+ && !chunk_is_newline(tmp))
+ {
+ break;
+ }
+ size_t nl_min = 0;
+ Chunk *tag_pc = Chunk::NullChunkPtr;
+ unc_text xstr;
+
+ if ( get_chunk_parent_type(br_open) == CT_FUNC_DEF
+ || get_chunk_parent_type(br_open) == CT_OC_MSG_DECL)
+ {
+ log_rule_B("mod_add_long_function_closebrace_comment");
+ nl_min = options::mod_add_long_function_closebrace_comment();
+ tag_pc = fcn_pc;
+
+ if (tag_pc->IsNotNullChunk())
+ {
+ append_tag_name(xstr, tag_pc);
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ }
+ else if ( get_chunk_parent_type(br_open) == CT_SWITCH
+ && sw_pc != nullptr)
+ {
+ log_rule_B("mod_add_long_switch_closebrace_comment");
+ nl_min = options::mod_add_long_switch_closebrace_comment();
+ tag_pc = sw_pc;
+ xstr = sw_pc->str;
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ else if ( get_chunk_parent_type(br_open) == CT_NAMESPACE
+ && ns_pc != nullptr)
+ {
+ log_rule_B("mod_add_long_namespace_closebrace_comment");
+ nl_min = options::mod_add_long_namespace_closebrace_comment();
+ tag_pc = ns_pc;
+ xstr = tag_pc->str; // add 'namespace' to the string
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+
+ // next chunk, normally is going to be the namespace name
+ // append it with a space to generate "namespace xyz"
+ Chunk *tmp_next = tag_pc->GetNextNcNnl();
+
+ if (chunk_is_not_token(tmp_next, CT_BRACE_OPEN)) // anonymous namespace -> ignore
+ {
+ xstr.append(" ");
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ append_tag_name(xstr, tmp_next);
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ }
+ else if ( get_chunk_parent_type(br_open) == CT_CLASS
+ && cl_pc->IsNotNullChunk()
+ && ( !language_is_set(LANG_CPP) // proceed if not C++
+ || chunk_is_token(br_close, CT_SEMICOLON))) // else a C++ class needs to end with a semicolon
+ {
+ log_rule_B("mod_add_long_class_closebrace_comment");
+ nl_min = options::mod_add_long_class_closebrace_comment();
+ tag_pc = cl_pc;
+ xstr = tag_pc->str;
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+
+ Chunk *tmp_next = cl_pc->GetNext();
+
+ if (tag_pc->IsNotNullChunk())
+ {
+ xstr.append(" ");
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ append_tag_name(xstr, tmp_next);
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ }
+
+ if ( nl_min > 0
+ && nl_count >= nl_min
+ && tag_pc->IsNotNullChunk())
+ {
+ // use the comment style that fits to the selected language
+ const E_Token style = language_is_set(LANG_CPP | LANG_CS)
+ ? CT_COMMENT_CPP : CT_COMMENT;
+
+ // Add a comment after the close brace
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ insert_comment_after(br_close, style, xstr);
+ }
+ break;
+ }
+ }
+} // add_long_closebrace_comment
+
+
+static void move_case_break(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc, CT_BREAK)
+ && chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_CASE
+ && chunk_is_newline(pc->GetPrev())
+ && chunk_is_newline(prev->GetPrev()))
+ {
+ chunk_swap_lines(prev, pc);
+ }
+ prev = pc;
+ }
+}
+
+
+static void move_case_return(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc, CT_RETURN)
+ && chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_CASE
+ && chunk_is_newline(pc->GetPrev())
+ && chunk_is_newline(prev->GetPrev()))
+ {
+ // Find the end of the return statement
+ while (chunk_is_not_token(pc, CT_SEMICOLON))
+ {
+ if ( chunk_is_token(pc, CT_CASE)
+ || chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ // This may indicate a semicolon was missing in the code to format.
+ // Avoid moving the return statement to prevent potential unwanted erros.
+ pc = Chunk::NullChunkPtr;
+ break;
+ }
+ pc = pc->GetNext();
+ }
+ pc = pc->GetNextNl();
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNotNullChunk())
+ {
+ // Swap all lines between brace close and current token
+ LOG_FMT(LMCB, "%s(%d): move line %zu before line %zu\n",
+ __func__, __LINE__, prev->orig_line, pc->orig_line);
+ Chunk *curr = prev->GetNextNcNnl();
+
+ while (curr != pc)
+ {
+ chunk_swap_lines(prev, curr);
+ curr = prev->GetNextNcNnl();
+ }
+ }
+ }
+ prev = pc;
+ }
+} // move_case_return
+
+
+static Chunk *mod_case_brace_remove(Chunk *br_open)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LMCB, "%s(%d): line %zu",
+ __func__, __LINE__, br_open->orig_line);
+
+ // Find the matching brace close
+ Chunk *next = br_open->GetNextNcNnl(E_Scope::PREPROC);
+ Chunk *br_close = br_open->GetNextType(CT_BRACE_CLOSE, br_open->level, E_Scope::PREPROC);
+
+ if (br_close->IsNullChunk())
+ {
+ LOG_FMT(LMCB, "%s(%d): - no close\n", __func__, __LINE__);
+ return(next);
+ }
+ // Make sure 'break', 'return', 'goto', 'case' or '}' is after the close brace
+ Chunk *pc = br_close->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( pc->IsNullChunk()
+ || ( chunk_is_not_token(pc, CT_BREAK)
+ && chunk_is_not_token(pc, CT_RETURN)
+ && chunk_is_not_token(pc, CT_CASE)
+ && chunk_is_not_token(pc, CT_GOTO)
+ && chunk_is_not_token(pc, CT_BRACE_CLOSE)))
+ {
+ LOG_FMT(LMCB, "%s(%d): - after '%s'\n",
+ __func__, __LINE__, (pc == nullptr) ? "<null>" : get_token_name(pc->type));
+ return(next);
+ }
+
+ // scan to make sure there are no definitions at brace level between braces
+ for (Chunk *tmp_pc = br_open;
+ tmp_pc != br_close;
+ tmp_pc = tmp_pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ if ( tmp_pc->level == (br_open->level + 1)
+ && tmp_pc->flags.test(PCF_VAR_DEF))
+ {
+ LOG_FMT(LMCB, "%s(%d): - vardef on line %zu: '%s'\n",
+ __func__, __LINE__, tmp_pc->orig_line, pc->Text());
+ return(next);
+ }
+ }
+
+ LOG_FMT(LMCB, "%s(%d): - removing braces on lines %zu and %zu\n",
+ __func__, __LINE__, br_open->orig_line, br_close->orig_line);
+
+ for (Chunk *tmp_pc = br_open;
+ tmp_pc != br_close;
+ tmp_pc = tmp_pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ if (tmp_pc->brace_level == 0)
+ {
+ fprintf(stderr, "%s(%d): tmp_pc->brace_level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp_pc->orig_line, tmp_pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ tmp_pc->brace_level--;
+
+ if (tmp_pc->level == 0)
+ {
+ fprintf(stderr, "%s(%d): tmp_pc->level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp_pc->orig_line, tmp_pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ tmp_pc->level--;
+ }
+
+ next = br_open->GetPrev(E_Scope::PREPROC);
+
+ chunk_del(br_open);
+ chunk_del(br_close);
+
+ return(next->GetNext(E_Scope::PREPROC));
+} // mod_case_brace_remove
+
+
+static Chunk *mod_case_brace_add(Chunk *cl_colon)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LMCB, "%s(%d): orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, cl_colon->orig_line, cl_colon->orig_col);
+
+ Chunk *pc = cl_colon;
+ Chunk *last = Chunk::NullChunkPtr;
+ // look for the case token to the colon
+ Chunk *cas_ = cl_colon->GetPrevType(CT_CASE, cl_colon->level);
+ // look for the parent
+ Chunk *swit = cas_->parent;
+ // look for the opening brace of the switch
+ Chunk *open = swit->GetNextType(CT_BRACE_OPEN, swit->level);
+ // look for the closing brace of the switch
+ Chunk *clos = chunk_skip_to_match(open);
+
+ // find the end of the case-block
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig_line %zu, orig_col is %zu, pp_level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, pc->pp_level);
+
+ if (pc->level == cl_colon->level)
+ {
+ if (chunk_is_token(pc, CT_CASE))
+ {
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ last = calculate_closing_brace_position(cl_colon, pc);
+ break;
+ }
+ }
+ else if (pc->level == cl_colon->level - 1)
+ {
+ if (pc == clos)
+ {
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ // end of switch is reached
+ last = calculate_closing_brace_position(cl_colon, pc);
+ LOG_FMT(LMCB, "%s(%d): last->Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->Text(), last->orig_line, last->orig_col);
+ break;
+ }
+ }
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ }
+
+ if (last->IsNullChunk())
+ {
+ LOG_FMT(LMCB, "%s(%d): - last is null chunk\n", __func__, __LINE__);
+ Chunk *next = cl_colon->GetNextNcNnl(E_Scope::PREPROC);
+ return(next);
+ }
+ LOG_FMT(LMCB, "%s(%d): last->Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->Text(), last->orig_line, last->orig_col);
+ LOG_FMT(LMCB, "%s(%d): adding braces after '%s' on line %zu\n",
+ __func__, __LINE__, cl_colon->Text(), cl_colon->orig_line);
+
+ Chunk chunk;
+
+ set_chunk_type(&chunk, CT_BRACE_OPEN);
+ set_chunk_parent(&chunk, CT_CASE);
+ chunk.orig_line = cl_colon->orig_line;
+ chunk.orig_col = cl_colon->orig_col;
+ chunk.level = cl_colon->level;
+ chunk.pp_level = cl_colon->pp_level;
+ chunk.brace_level = cl_colon->brace_level;
+ chunk.flags = pc->flags & PCF_COPY_FLAGS;
+ chunk.str = "{";
+ Chunk *br_open = chunk_add_after(&chunk, cl_colon);
+
+ set_chunk_type(&chunk, CT_BRACE_CLOSE);
+ chunk.orig_line = last->orig_line;
+ chunk.orig_col = last->orig_col;
+ chunk.str = "}";
+ Chunk *br_close = chunk_add_after(&chunk, last);
+
+ for (pc = br_open->GetNext(E_Scope::PREPROC);
+ pc != br_close;
+ pc = pc->GetNext(E_Scope::PREPROC))
+ {
+ pc->level++;
+ pc->brace_level++;
+ }
+
+ return(br_open);
+} // mod_case_brace_add
+
+
+static void mod_case_brace(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+
+ // Make sure to start outside of a preprocessor line (see issue #3366)
+ if (pc->IsPreproc())
+ {
+ pc = pc->GetNextNcNnlNpp();
+ }
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ log_rule_B("mod_case_brace");
+
+ if ( options::mod_case_brace() == IARF_REMOVE
+ && chunk_is_token(pc, CT_BRACE_OPEN)
+ && get_chunk_parent_type(pc) == CT_CASE)
+ {
+ log_rule_B("mod_case_brace - add");
+ pc = mod_case_brace_remove(pc);
+ }
+ else if ( (options::mod_case_brace() & IARF_ADD)
+ && chunk_is_token(pc, CT_CASE_COLON)
+ && chunk_is_not_token(next, CT_BRACE_OPEN)
+ && chunk_is_not_token(next, CT_BRACE_CLOSE)
+ && chunk_is_not_token(next, CT_CASE))
+ {
+ log_rule_B("mod_case_brace - remove");
+ pc = mod_case_brace_add(pc);
+ }
+ else
+ {
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ }
+ }
+} // mod_case_brace
+
+
+static void process_if_chain(Chunk *br_start)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LBRCH, "%s(%d): if starts on line %zu, orig_col is %zu.\n",
+ __func__, __LINE__, br_start->orig_line, br_start->orig_col);
+
+ vector<Chunk *> braces;
+
+ braces.reserve(16);
+
+ bool must_have_braces = false;
+ bool has_unbraced_block = false;
+
+ Chunk *pc = br_start;
+
+ while (pc != nullptr)
+ {
+ LOG_FMT(LBRCH, "%s(%d): pc->Text() is '%s', orig_line is %zu, orig_col is %zu.\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ const bool tmp = can_remove_braces(pc);
+ LOG_FMT(LBRCH, "%s(%d): braces.size() is %zu, line is %zu, - can%s remove %s\n",
+ __func__, __LINE__, braces.size(), pc->orig_line, tmp ? "" : "not",
+ get_token_name(pc->type));
+
+ if ( !tmp
+ || options::mod_full_brace_if_chain() == 2)
+ {
+ must_have_braces = true;
+ }
+ }
+ else
+ {
+ const bool tmp = should_add_braces(pc);
+
+ if (tmp)
+ {
+ must_have_braces = true;
+ }
+ LOG_FMT(LBRCH, "%s(%d): braces.size() is %zu, line is %zu, - %s %s\n",
+ __func__, __LINE__, braces.size(), pc->orig_line, tmp ? "should add" : "ignore",
+ get_token_name(pc->type));
+
+ has_unbraced_block = true;
+ }
+
+ if ( options::mod_full_brace_if_chain() == 3
+ && !has_unbraced_block)
+ {
+ must_have_braces = true;
+ }
+ braces.push_back(pc);
+ Chunk *br_close = chunk_skip_to_match(pc, E_Scope::PREPROC);
+
+ if (br_close == nullptr)
+ {
+ break;
+ }
+ braces.push_back(br_close);
+
+ pc = br_close->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( pc->IsNullChunk()
+ || chunk_is_not_token(pc, CT_ELSE))
+ {
+ break;
+ }
+ log_rule_B("mod_full_brace_if_chain_only");
+
+ if (options::mod_full_brace_if_chain_only())
+ {
+ // There is an 'else' - we want full braces.
+ must_have_braces = true;
+ }
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (chunk_is_token(pc, CT_ELSEIF))
+ {
+ while ( chunk_is_not_token(pc, CT_VBRACE_OPEN)
+ && chunk_is_not_token(pc, CT_BRACE_OPEN))
+ {
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ }
+ }
+
+ if (pc->IsNullChunk())
+ {
+ break;
+ }
+
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && chunk_is_not_token(pc, CT_VBRACE_OPEN))
+ {
+ break;
+ }
+ }
+
+ if (must_have_braces)
+ {
+ LOG_FMT(LBRCH, "%s(%d): add braces on lines[%zu]:",
+ __func__, __LINE__, braces.size());
+
+ const auto ite = braces.rend();
+
+ for (auto itc = braces.rbegin(); itc != ite; ++itc)
+ {
+ const auto brace = *itc;
+
+ chunk_flags_set(brace, PCF_KEEP_BRACE);
+
+ if ( chunk_is_token(brace, CT_VBRACE_OPEN)
+ || chunk_is_token(brace, CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LBRCH, "%s(%d): %zu",
+ __func__, __LINE__, brace->orig_line);
+ convert_vbrace(brace);
+ }
+ else
+ {
+ LOG_FMT(LBRCH, "%s(%d): {%zu}",
+ __func__, __LINE__, brace->orig_line);
+ }
+ }
+
+ LOG_FMT(LBRCH, "\n");
+ }
+ else if (options::mod_full_brace_if_chain())
+ {
+ log_rule_B("mod_full_brace_if_chain");
+ LOG_FMT(LBRCH, "%s(%d): remove braces on lines[%zu]:\n",
+ __func__, __LINE__, braces.size());
+
+ /*
+ * This might run because either
+ * mod_full_brace_if_chain or mod_full_brace_if_chain_only
+ * is used.
+ * We only want to remove braces if the first one is active.
+ */
+ log_rule_B("mod_full_brace_nl_block_rem_mlcond");
+ const auto multiline_block = options::mod_full_brace_nl_block_rem_mlcond();
+
+ LOG_FMT(LBRCH, "%s(%d): remove braces on lines:\n", __func__, __LINE__);
+
+ // Issue #2229
+ const auto ite = braces.end();
+
+ for (auto itc = braces.begin(); itc != ite; ++itc)
+ {
+ const auto brace = *itc;
+
+ if ( ( chunk_is_token(brace, CT_BRACE_OPEN)
+ || chunk_is_token(brace, CT_BRACE_CLOSE))
+ && (get_chunk_parent_type(brace) != CT_BRACED_INIT_LIST)
+ && (multiline_block ? !paren_multiline_before_brace(brace) : true))
+ {
+ LOG_FMT(LBRCH, "%s(%d): brace->orig_line is %zu, brace->orig_col is %zu\n",
+ __func__, __LINE__, brace->orig_line, brace->orig_col);
+ convert_brace(brace);
+ }
+ else
+ {
+ LOG_FMT(LBRCH, "%s(%d): brace->orig_line is %zu, brace->orig_col is %zu\n",
+ __func__, __LINE__, brace->orig_line, brace->orig_col);
+ }
+ }
+ }
+} // process_if_chain
+
+
+static void mod_full_brace_if_chain(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_OPEN))
+ && get_chunk_parent_type(pc) == CT_IF)
+ {
+ process_if_chain(pc);
+ }
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.h
new file mode 100644
index 00000000..c9695bbe
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/braces.h
@@ -0,0 +1,33 @@
+/**
+ * @file braces.h
+ * prototypes for braces.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef BRACES_H_INCLUDED
+#define BRACES_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+//! Change virtual braces into real braces
+void do_braces(void);
+
+/**
+ * See the preprocessor counterpart:
+ * add_long_preprocessor_conditional_block_comment
+ * in output.cpp
+ */
+void add_long_closebrace_comment(void);
+
+
+/**
+ * Adds a comment after the ref chunk
+ * Returns the added chunk or nullptr
+ */
+Chunk *insert_comment_after(Chunk *ref, E_Token cmt_type, const unc_text &cmt_text);
+
+
+#endif /* BRACES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.cpp
new file mode 100644
index 00000000..30865900
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.cpp
@@ -0,0 +1,199 @@
+/**
+ * @file calculate_closing_brace_position.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "calculate_closing_brace_position.h"
+
+#include "chunk.h"
+
+using namespace uncrustify;
+
+
+Chunk *calculate_closing_brace_position(const Chunk *cl_colon, Chunk *pc)
+{
+ LOG_FMT(LMCB, "%s(%d): cl_colon->Text() is '%s', orig_line %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, cl_colon->Text(), cl_colon->orig_line, cl_colon->orig_col, cl_colon->level);
+ LOG_FMT(LMCB, "%s(%d): pc->Text() is '%s', orig_line %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+ // end of block is reached
+ // look back over newline, preprocessor BUT NOT #endif
+
+ // Issue #3058
+
+ // examine going back the tokens: look for a "brace closing" or a "semi colon" until the colon
+ // look back over comment, newline, preprocessor BUT NOT #endif
+
+ size_t check_level = 0;
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ check_level = pc->level + 1;
+ }
+ else
+ {
+ check_level = pc->level;
+ }
+ size_t erst_found = 0;
+ Chunk *is_brace_close = Chunk::NullChunkPtr;
+ Chunk *is_semicolon = Chunk::NullChunkPtr;
+ Chunk *is_comment = Chunk::NullChunkPtr;
+ Chunk *back = pc->GetPrevNnl();
+
+ while (back->IsNotNullChunk())
+ {
+ if (back == cl_colon)
+ {
+ break;
+ }
+
+ if (erst_found != 0)
+ {
+ break;
+ }
+
+ if (back->level == check_level)
+ {
+ if ( chunk_is_token(back, CT_BRACE_CLOSE)
+ || chunk_is_token(back, CT_VBRACE_CLOSE))
+ {
+ // brace_close found
+ is_brace_close = back;
+ LOG_FMT(LMCB, "%s(%d): BRACE_CLOSE: line is %zu, col is %zu, level is %zu\n",
+ __func__, __LINE__, is_brace_close->orig_line, is_brace_close->orig_col, is_brace_close->level);
+ erst_found = 3;
+ }
+
+ if (chunk_is_token(back, CT_SEMICOLON))
+ {
+ // semicolon found
+ is_semicolon = back;
+ LOG_FMT(LMCB, "%s(%d): SEMICOLON: line is %zu, col is %zu, level is %zu\n",
+ __func__, __LINE__, is_semicolon->orig_line, is_semicolon->orig_col, is_semicolon->level);
+ erst_found = 4;
+ }
+
+ if (back->IsComment())
+ {
+ // comment found
+ is_comment = back;
+ LOG_FMT(LMCB, "%s(%d): COMMENT: line is %zu, col is %zu, level is %zu\n",
+ __func__, __LINE__, back->orig_line, back->orig_col, back->level);
+ }
+ }
+ back = back->GetPrev();
+ }
+ LOG_FMT(LMCB, "%s(%d): erst_found is %zu\n",
+ __func__, __LINE__, erst_found);
+ Chunk *last = Chunk::NullChunkPtr;
+
+ if ( erst_found == 3
+ || erst_found == 4)
+ {
+ if (is_comment->IsNotNullChunk())
+ {
+ Chunk *second = Chunk::NullChunkPtr;
+
+ if (erst_found == 3)
+ {
+ second = is_brace_close;
+ }
+ else
+ {
+ // erst_found == 4
+ second = is_semicolon;
+ }
+
+ if (second->IsNotNullChunk())
+ {
+ if (is_comment->orig_line == second->orig_line)
+ {
+ last = is_comment;
+
+ if (cl_colon->orig_line == is_comment->orig_line)
+ {
+ last = is_comment->GetNext();
+ }
+ }
+ else
+ {
+ last = pc->GetPrevNcNnl();
+ }
+ }
+ else
+ {
+ LOG_FMT(LMCB, "\n\n%s(%d):\n", __func__, __LINE__);
+ fprintf(stderr, "FATAL: second is nullptr\n");
+ fprintf(stderr, "Please make a report.\n");
+ exit(EX_SOFTWARE);
+ }
+ }
+ else
+ {
+ last = pc->GetPrevNcNnl();
+ }
+ }
+ else
+ {
+ LOG_FMT(LMCB, "\n\n%s(%d):\n", __func__, __LINE__);
+ fprintf(stderr, "FATAL: erst_found is not 3 or 4\n");
+ fprintf(stderr, "Please make a report.\n");
+ exit(EX_SOFTWARE);
+ }
+
+ if (chunk_is_token(last, CT_COMMENT_CPP)) // Issue #3058
+ {
+ last = last->GetNext();
+ }
+ LOG_FMT(LMCB, "%s(%d): last->Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->Text(), last->orig_line, last->orig_col);
+
+ if (last->IsPreproc())
+ {
+ // we have a preprocessor token
+ while (last->IsNotNullChunk())
+ {
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->Text(), last->orig_line, last->orig_col);
+
+ if (chunk_is_token(last, CT_PP_ENDIF))
+ {
+ // look for the parent
+ Chunk *parent_last = last->parent;
+ // compare the positions
+ int comp = chunk_compare_position(parent_last, cl_colon);
+ LOG_FMT(LMCB, "%s(%d): comp is %d\n",
+ __func__, __LINE__, comp);
+
+ if (comp == -1)
+ {
+ // cl_colon is after parent_last ==>
+ // the closing brace will be set before #endif
+ Chunk *pp_start = chunk_get_pp_start(last);
+ last = pp_start->GetPrevNnl();
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->Text(), last->orig_line, last->orig_col);
+ }
+ else if (comp == 1)
+ {
+ // cl_colon is before parent_last ==>
+ // the closing brace will be set after #endif
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->Text(), last->orig_line, last->orig_col);
+ }
+ break;
+ }
+ last = last->GetPrevNcNnl();
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, last->Text(), last->orig_line, last->orig_col);
+
+ if (!last->IsPreproc())
+ {
+ break;
+ }
+ }
+ }
+ return(last);
+} // calculate_closing_brace_position
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.h
new file mode 100644
index 00000000..6d2b0f06
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/calculate_closing_brace_position.h
@@ -0,0 +1,18 @@
+/**
+ * @file calculate_closing_brace_position.h
+ * prototype for calculate_closing_brace_position.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef CALCULATE_CLOSING_BRACE_POSITION_H_INCLUDED
+#define CALCULATE_CLOSING_BRACE_POSITION_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+Chunk *calculate_closing_brace_position(const Chunk *cl_colon, Chunk *pc);
+
+
+#endif /* CALCULATE_CLOSING_BRACE_POSITION_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/char_table.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/char_table.h
new file mode 100644
index 00000000..3fa23a54
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/char_table.h
@@ -0,0 +1,81 @@
+/**
+ * @file char_table.h
+ * A simple table to help tokenize stuff.
+ * Used to parse strings (paired char) and words.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef CHAR_TABLE_H_INCLUDED
+#define CHAR_TABLE_H_INCLUDED
+
+/**
+ * bit0-7 = paired char
+ * bit8 = OK for keyword 1st char
+ * bit9 = OK for keyword 2+ char
+ */
+struct CharTable
+{
+ static size_t chars[128];
+
+ enum
+ {
+ KW1 = 0x0100,
+ KW2 = 0x0200,
+ };
+
+
+ static inline size_t Get(size_t ch)
+ {
+ if (ch < ARRAY_SIZE(chars))
+ {
+ return(chars[ch]);
+ }
+ /*
+ * HACK: If the top bit is set, then we are likely dealing with UTF-8,
+ * and since that is only allowed in identifiers, then assume that is
+ * what this is. This only prevents corruption, it does not properly
+ * handle UTF-8 because the byte length and screen size are assumed to be
+ * the same.
+ */
+ return(KW1 | KW2);
+ }
+
+
+ static inline bool IsKw1(size_t ch)
+ {
+ return((Get(ch) & KW1) != 0);
+ }
+
+
+ static inline bool IsKw2(size_t ch)
+ {
+ return((Get(ch) & KW2) != 0);
+ }
+};
+
+#ifdef DEFINE_CHAR_TABLE
+size_t CharTable::chars[128] =
+{
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, // [........]
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, // [........]
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, // [........]
+ 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, // [........]
+ 0x000, 0x000, 0x022, 0x000, 0x300, 0x000, 0x000, 0x027, // [ !"#$%&']
+ 0x029, 0x028, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, // [()*+,-./]
+ 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, 0x200, // [01234567]
+ 0x200, 0x200, 0x000, 0x000, 0x03e, 0x000, 0x03c, 0x000, // [89:;<=>?]
+ 0x200, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, // [@ABCDEFG]
+ 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, // [HIJKLMNO]
+ 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, // [PQRSTUVW]
+ 0x300, 0x300, 0x300, 0x05d, 0x000, 0x05b, 0x000, 0x300, // [XYZ[\]^_]
+ 0x060, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, // [`abcdefg]
+ 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, // [hijklmno]
+ 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, 0x300, // [pqrstuvw]
+ 0x300, 0x300, 0x300, 0x07d, 0x000, 0x07b, 0x000, 0x000, // [xyz{|}~.]
+};
+#endif /* DEFINE_CHAR_TABLE */
+
+
+#endif /* CHAR_TABLE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp
new file mode 100644
index 00000000..0ad879b4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.cpp
@@ -0,0 +1,1167 @@
+/**
+ * @file chunk.cpp
+ * Manages and navigates the list of chunks.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "chunk.h"
+
+#include "ListManager.h"
+#include "prototypes.h"
+#include "space.h"
+
+typedef ListManager<Chunk> ChunkList_t;
+
+
+ChunkList_t g_cl; //! global chunk list
+
+
+/*
+ * Chunk class methods
+ */
+
+// Null Chunk
+Chunk Chunk::NullChunk(true);
+Chunk *const Chunk::NullChunkPtr(&Chunk::NullChunk);
+
+
+Chunk::Chunk(bool null_c)
+ : null_chunk(null_c)
+{
+ Reset();
+}
+
+
+Chunk::Chunk(const Chunk &o)
+ : null_chunk(o.null_chunk)
+{
+ copyFrom(o);
+}
+
+
+Chunk &Chunk::operator=(const Chunk &o)
+{
+ if (this != &o)
+ {
+ copyFrom(o);
+ }
+ return(*this);
+}
+
+
+void Chunk::copyFrom(const Chunk &o)
+{
+ next = nullptr;
+ prev = nullptr;
+ parent = nullptr;
+ align = o.align;
+ indent = o.indent;
+ type = o.type;
+ parent_type = o.parent_type;
+
+ orig_line = o.orig_line;
+ orig_col = o.orig_col;
+ orig_col_end = o.orig_col_end;
+ orig_prev_sp = o.orig_prev_sp;
+ flags = o.flags;
+ column = o.column;
+ column_indent = o.column_indent;
+
+ nl_count = o.nl_count;
+ nl_column = o.nl_column;
+ level = o.level;
+
+ brace_level = o.brace_level;
+ pp_level = o.pp_level;
+ after_tab = o.after_tab;
+ str = o.str;
+
+ tracking = o.tracking;
+}
+
+
+void Chunk::Reset()
+{
+ memset(&align, 0, sizeof(align));
+ memset(&indent, 0, sizeof(indent));
+ next = nullptr;
+ prev = nullptr;
+ parent = nullptr;
+ type = CT_NONE;
+ parent_type = CT_NONE;
+ orig_line = 0;
+ orig_col = 0;
+ orig_col_end = 0;
+ orig_prev_sp = 0;
+ flags = PCF_NONE;
+ column = 0;
+ column_indent = 0;
+ nl_count = 0;
+ nl_column = 0;
+ level = 0;
+ brace_level = 0;
+ pp_level = 999; // use a big value to find some errors
+ after_tab = false;
+ // for debugging purpose only
+ tracking = nullptr;
+ str.clear();
+}
+
+
+size_t Chunk::Len() const
+{
+ return(str.size());
+}
+
+
+const char *Chunk::Text() const
+{
+ return(str.c_str());
+}
+
+
+const char *Chunk::ElidedText(char *for_the_copy) const
+{
+ const char *test_it = Text();
+ size_t test_it_length = strlen(test_it);
+
+ size_t truncate_value = uncrustify::options::debug_truncate();
+
+ if (truncate_value != 0)
+ {
+ if (test_it_length > truncate_value)
+ {
+ memset(for_the_copy, 0, 1000);
+
+ if (test_it_length < truncate_value + 30)
+ {
+ strncpy(for_the_copy, test_it, truncate_value - 30);
+ for_the_copy[truncate_value - 30] = 0;
+ }
+ else
+ {
+ strncpy(for_the_copy, test_it, truncate_value);
+ for_the_copy[truncate_value] = 0;
+ }
+ char *message = strcat(for_the_copy, " ... <The string is truncated>");
+
+ return(message);
+ }
+ else
+ {
+ return(test_it);
+ }
+ }
+ return(test_it);
+}
+
+
+Chunk *Chunk::GetNext(const E_Scope scope) const
+{
+ if (IsNullChunk())
+ {
+ return(NullChunkPtr);
+ }
+ Chunk *pc = g_cl.GetNext(this);
+
+ if ( pc == nullptr
+ || pc->IsNullChunk())
+ {
+ return(NullChunkPtr);
+ }
+
+ if (scope == E_Scope::ALL)
+ {
+ return(pc);
+ }
+
+ if (flags.test(PCF_IN_PREPROC))
+ {
+ // If in a preproc, return a null chunk if trying to leave
+ if (!pc->flags.test(PCF_IN_PREPROC))
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+ }
+
+ // Not in a preproc, skip any preproc
+ while ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && pc->flags.test(PCF_IN_PREPROC))
+ {
+ pc = g_cl.GetNext(pc);
+ }
+
+ if ( pc == nullptr
+ || pc->IsNullChunk())
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+} // Chunk::GetNext
+
+
+Chunk *Chunk::GetPrev(const E_Scope scope) const
+{
+ if (IsNullChunk())
+ {
+ return(NullChunkPtr);
+ }
+ Chunk *pc = g_cl.GetPrev(this);
+
+ if ( pc == nullptr
+ || pc->IsNullChunk())
+ {
+ return(NullChunkPtr);
+ }
+
+ if (scope == E_Scope::ALL)
+ {
+ return(pc);
+ }
+
+ if (flags.test(PCF_IN_PREPROC))
+ {
+ // If in a preproc, return a null chunk if trying to leave
+ if (!pc->flags.test(PCF_IN_PREPROC))
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+ }
+
+ // Not in a preproc, skip any preproc
+ while ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && pc->flags.test(PCF_IN_PREPROC))
+ {
+ pc = g_cl.GetPrev(pc);
+ }
+
+ if ( pc == nullptr
+ || pc->IsNullChunk())
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+} // Chunk::GetPrev
+
+
+static void chunk_log(Chunk *pc, const char *text);
+
+
+/*
+ * TODO: if we use C++ we can overload the following two functions
+ * and thus name them equally
+ */
+
+/**
+ * @brief search a chunk of a given category in a chunk list
+ *
+ * traverses a chunk list either in forward or backward direction.
+ * The traversal continues until a chunk of a given category is found.
+ *
+ * This function is a specialization of Chunk::Search.
+ *
+ * @param cur chunk to start search at
+ * @param type category to search for
+ * @param scope code parts to consider for search
+ * @param dir search direction
+ *
+ * @retval nullptr no chunk found or invalid parameters provided
+ * @retval Chunk pointer to the found chunk
+ */
+static Chunk *chunk_search_type(Chunk *cur, const E_Token type, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD);
+
+
+/**
+ * @brief Add a new chunk before/after the given position in a chunk list
+ *
+ * If ref is nullptr, add either at the head or tail based on the specified pos
+ *
+ * @param pc_in chunk to add to list
+ * @param ref insert position in list
+ * @param pos insert before or after
+ *
+ * @return Chunk pointer to the added chunk
+ */
+static Chunk *chunk_add(const Chunk *pc_in, Chunk *ref, const E_Direction pos = E_Direction::FORWARD);
+
+
+Chunk *Chunk::GetHead(void)
+{
+ Chunk *ret = g_cl.GetHead();
+
+ if (ret == nullptr)
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ return(ret);
+}
+
+
+Chunk *Chunk::GetTail(void)
+{
+ Chunk *ret = g_cl.GetTail();
+
+ if (ret == nullptr)
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ return(ret);
+}
+
+
+Chunk::T_SearchFnPtr Chunk::GetSearchFn(const E_Direction dir)
+{
+ return((dir == E_Direction::FORWARD) ? &Chunk::GetNext : &Chunk::GetPrev);
+}
+
+
+Chunk *Chunk::Search(const T_CheckFnPtr checkFn, const E_Scope scope,
+ const E_Direction dir, const bool cond) const
+{
+ T_SearchFnPtr searchFnPtr = GetSearchFn(dir);
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ do // loop over the chunk list
+ {
+ pc = (pc->*searchFnPtr)(scope); // in either direction while
+ } while ( pc->IsNotNullChunk() // the end of the list was not reached yet
+ && ((pc->*checkFn)() != cond)); // and the demanded chunk was not found either
+
+ return(pc); // the latest chunk is the searched one
+}
+
+
+Chunk *chunk_search_prev_cat(Chunk *pc, const E_Token cat)
+{
+ return(chunk_search_type(pc, cat, E_Scope::ALL, E_Direction::BACKWARD));
+}
+
+
+Chunk *chunk_search_next_cat(Chunk *pc, const E_Token cat)
+{
+ return(chunk_search_type(pc, cat, E_Scope::ALL, E_Direction::FORWARD));
+}
+
+
+bool are_chunks_in_same_line(Chunk *start, Chunk *end)
+{
+ if (start == nullptr)
+ {
+ return(false);
+ }
+ Chunk *tmp = start->GetNext();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp != end)
+ {
+ if (chunk_is_token(tmp, CT_NEWLINE))
+ {
+ return(false);
+ }
+ tmp = tmp->GetNext();
+ }
+ return(true);
+}
+
+
+static Chunk *chunk_search_type(Chunk *cur, const E_Token type,
+ const E_Scope scope, const E_Direction dir)
+{
+ /*
+ * Depending on the parameter dir the search function searches
+ * in forward or backward direction
+ */
+ Chunk::T_SearchFnPtr search_function = Chunk::GetSearchFn(dir);
+ Chunk *pc = cur;
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ do // loop over the chunk list
+ {
+ pc = (pc->*search_function)(scope); // in either direction while
+ } while ( pc->IsNotNullChunk() // the end of the list was not reached yet
+ && pc->type != type); // and the demanded chunk was not found either
+
+ if (pc->IsNullChunk())
+ {
+ pc = nullptr;
+ }
+ return(pc); // the latest chunk is the searched one
+}
+
+
+Chunk *Chunk::SearchTypeLevel(const E_Token cType, const E_Scope scope,
+ const E_Direction dir, const int cLevel) const
+{
+ T_SearchFnPtr searchFnPtr = GetSearchFn(dir);
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ do // loop over the chunk list
+ {
+ pc = (pc->*searchFnPtr)(scope); // in either direction while
+ } while ( pc->IsNotNullChunk() // the end of the list was not reached yet
+ && (!pc->IsTypeAndLevel(cType, cLevel))); // and the chunk was not found either
+
+ return(pc); // the latest chunk is the searched one
+}
+
+
+Chunk *Chunk::SearchStringLevel(const char *cStr, const size_t len, int cLevel,
+ const E_Scope scope, const E_Direction dir) const
+{
+ T_SearchFnPtr searchFnPtr = GetSearchFn(dir);
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ do // loop over the chunk list
+ {
+ pc = (pc->*searchFnPtr)(scope); // in either direction while
+ } while ( pc->IsNotNullChunk() // the end of the list was not reached yet
+ && !pc->IsStringAndLevel(cStr, len, cLevel)); // and the demanded chunk was not found either
+
+ return(pc); // the latest chunk is the searched one
+}
+
+
+Chunk *Chunk::SearchPpa(const T_CheckFnPtr checkFn, const bool cond) const
+{
+ if (!flags.test(PCF_IN_PREPROC))
+ {
+ // if not in preprocessor, do a regular search
+ return(Search(checkFn, E_Scope::ALL, E_Direction::FORWARD, cond));
+ }
+ Chunk *pc = GetNext();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (!pc->flags.test(PCF_IN_PREPROC))
+ {
+ // Bail if we run off the end of the preprocessor directive, but return
+ // the token because the caller may need to know where the search ended
+ assert(chunk_is_token(pc, CT_NEWLINE));
+ return(pc);
+ }
+
+ if (chunk_is_token(pc, CT_NL_CONT))
+ {
+ // Skip line continuation
+ pc = pc->GetNext();
+ continue;
+ }
+
+ if ((pc->*checkFn)() == cond)
+ {
+ // Requested token was found
+ return(pc);
+ }
+ pc = pc->GetNext();
+ }
+ // Ran out of tokens
+ return(Chunk::NullChunkPtr);
+}
+
+
+static void chunk_log_msg(Chunk *chunk, const log_sev_t log, const char *str)
+{
+ LOG_FMT(log, "%s orig_line is %zu, orig_col is %zu, ",
+ str, chunk->orig_line, chunk->orig_col);
+
+ if (chunk_is_token(chunk, CT_NEWLINE))
+ {
+ LOG_FMT(log, "<Newline>,\n");
+ }
+ else if (chunk_is_token(chunk, CT_VBRACE_OPEN))
+ {
+ LOG_FMT(log, "<VBRACE_OPEN>,\n");
+ }
+ else if (chunk_is_token(chunk, CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(log, "<VBRACE_CLOSE>,\n");
+ }
+ else
+ {
+ LOG_FMT(log, "Text() is '%s', type is %s,\n", chunk->Text(), get_token_name(chunk->type));
+ }
+}
+
+
+static void chunk_log(Chunk *pc, const char *text)
+{
+ if ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && (cpd.unc_stage != unc_stage_e::TOKENIZE)
+ && (cpd.unc_stage != unc_stage_e::CLEANUP))
+ {
+ const log_sev_t log = LCHUNK;
+ Chunk *prev = pc->GetPrev();
+ Chunk *next = pc->GetNext();
+
+ chunk_log_msg(pc, log, text);
+
+ if ( prev->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ chunk_log_msg(prev, log, " @ between");
+ chunk_log_msg(next, log, " and");
+ }
+ else if (next->IsNotNullChunk())
+ {
+ chunk_log_msg(next, log, " @ before");
+ }
+ else if (prev->IsNotNullChunk())
+ {
+ chunk_log_msg(prev, log, " @ after");
+ }
+ LOG_FMT(log, " stage is %s", // Issue #3034
+ get_unc_stage_name(cpd.unc_stage));
+ log_func_stack_inline(log);
+ }
+}
+
+
+Chunk *chunk_add_after(const Chunk *pc_in, Chunk *ref)
+{
+ return(chunk_add(pc_in, ref, E_Direction::FORWARD));
+}
+
+
+Chunk *chunk_add_before(const Chunk *pc_in, Chunk *ref)
+{
+ return(chunk_add(pc_in, ref, E_Direction::BACKWARD));
+}
+
+
+void chunk_del(Chunk * &pc)
+{
+ g_cl.Pop(pc);
+ delete pc;
+ pc = nullptr;
+}
+
+
+void chunk_move_after(Chunk *pc_in, Chunk *ref)
+{
+ LOG_FUNC_ENTRY();
+ g_cl.Pop(pc_in);
+ g_cl.AddAfter(pc_in, ref);
+
+ // HACK: Adjust the original column
+ pc_in->column = ref->column + space_col_align(ref, pc_in);
+ pc_in->orig_col = pc_in->column;
+ pc_in->orig_col_end = pc_in->orig_col + pc_in->Len();
+}
+
+
+Chunk *Chunk::GetNextNl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::FORWARD, true));
+}
+
+
+Chunk *Chunk::GetPrevNl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::BACKWARD, true));
+}
+
+
+Chunk *Chunk::GetNextNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::BACKWARD, false));
+}
+
+
+Chunk *Chunk::GetNextNc(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsComment, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNc(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsComment, scope, E_Direction::BACKWARD, false));
+}
+
+
+Chunk *Chunk::GetNextNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewline, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewline, scope, E_Direction::BACKWARD, false));
+}
+
+
+Chunk *Chunk::GetNextNcNnlNpp(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrPreproc, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNcNnlNpp(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrPreproc, scope, E_Direction::BACKWARD, false));
+}
+
+
+Chunk *Chunk::GetNextNppOrNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewlineInPreproc, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNppOrNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewlineInPreproc, scope, E_Direction::BACKWARD, false));
+}
+
+
+Chunk *Chunk::PpaGetNextNcNnl() const
+{
+ return(SearchPpa(&Chunk::IsCommentOrNewline, false));
+}
+
+
+Chunk *Chunk::GetNextNcNnlNet(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrEmptyText, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNcNnlNet(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrEmptyText, scope, E_Direction::BACKWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNcNnlNi(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrIgnored, scope, E_Direction::BACKWARD, false));
+}
+
+
+Chunk *Chunk::GetNextNisq(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsSquareBracket, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetNextType(const E_Token cType, const int cLevel, const E_Scope scope) const
+{
+ return(SearchTypeLevel(cType, scope, E_Direction::FORWARD, cLevel));
+}
+
+
+Chunk *Chunk::GetPrevType(const E_Token cType, const int cLevel, const E_Scope scope) const
+{
+ return(SearchTypeLevel(cType, scope, E_Direction::BACKWARD, cLevel));
+}
+
+
+Chunk *Chunk::GetNextString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope) const
+{
+ return(SearchStringLevel(cStr, len, cLevel, scope, E_Direction::FORWARD));
+}
+
+
+Chunk *Chunk::GetPrevString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope) const
+{
+ return(SearchStringLevel(cStr, len, cLevel, scope, E_Direction::BACKWARD));
+}
+
+
+bool chunk_is_newline_between(Chunk *start, Chunk *end)
+{
+ for (Chunk *pc = start; pc != nullptr && pc != end; pc = pc->GetNext())
+ {
+ if (chunk_is_newline(pc))
+ {
+ return(true);
+ }
+ }
+
+ return(false);
+}
+
+
+void chunk_swap(Chunk *pc1, Chunk *pc2)
+{
+ g_cl.Swap(pc1, pc2);
+}
+
+
+// TODO: the following function shall be made similar to the search functions
+Chunk *chunk_first_on_line(Chunk *pc)
+{
+ if ( pc == nullptr
+ || pc->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ Chunk *first = pc;
+
+ while ( (pc = pc->GetPrev())->IsNotNullChunk()
+ && !chunk_is_newline(pc))
+ {
+ first = pc;
+ }
+ return(first);
+}
+
+
+bool chunk_is_last_on_line(Chunk *pc) //TODO: pc should be const here
+{
+ // check if pc is the very last chunk of the file
+ const Chunk *end = Chunk::GetTail();
+
+ if (pc == end)
+ {
+ return(true);
+ }
+ // if the next chunk is a newline then pc is the last chunk on its line
+ const Chunk *next = pc->GetNext();
+
+ if (chunk_is_token(next, CT_NEWLINE))
+ {
+ return(true);
+ }
+ return(false);
+}
+
+
+// TODO: this function needs some cleanup
+void chunk_swap_lines(Chunk *pc1, Chunk *pc2)
+{
+ // to swap lines we need to find the first chunk of the lines
+ pc1 = chunk_first_on_line(pc1);
+ pc2 = chunk_first_on_line(pc2);
+
+ if ( pc1->IsNullChunk()
+ || pc2->IsNullChunk()
+ || pc1 == pc2)
+ {
+ return;
+ }
+ /*
+ * Example start:
+ * ? - start1 - a1 - b1 - nl1 - ? - ref2 - start2 - a2 - b2 - nl2 - ?
+ * ^- pc1 ^- pc2
+ */
+ Chunk *ref2 = pc2->GetPrev();
+
+ // Move the line started at pc2 before pc1
+ while ( pc2->IsNotNullChunk()
+ && !chunk_is_newline(pc2))
+ {
+ Chunk *tmp = pc2->GetNext();
+ g_cl.Pop(pc2);
+ g_cl.AddBefore(pc2, pc1);
+ pc2 = tmp;
+ }
+ /*
+ * Should now be:
+ * ? - start2 - a2 - b2 - start1 - a1 - b1 - nl1 - ? - ref2 - nl2 - ?
+ * ^- pc1 ^- pc2
+ */
+
+ // Now move the line started at pc1 after ref2
+ while ( pc1->IsNotNullChunk()
+ && !chunk_is_newline(pc1))
+ {
+ Chunk *tmp = pc1->GetNext();
+ g_cl.Pop(pc1);
+
+ if (ref2->IsNotNullChunk())
+ {
+ g_cl.AddAfter(pc1, ref2);
+ }
+ else
+ {
+ g_cl.AddHead(pc1);
+ }
+ ref2 = pc1;
+ pc1 = tmp;
+ }
+ /*
+ * Should now be:
+ * ? - start2 - a2 - b2 - nl1 - ? - ref2 - start1 - a1 - b1 - nl2 - ?
+ * ^- pc1 ^- pc2
+ */
+
+ /*
+ * pc1 and pc2 should be the newlines for their lines.
+ * swap the chunks and the nl_count so that the spacing remains the same.
+ */
+ if ( pc1->IsNotNullChunk()
+ && pc2->IsNotNullChunk())
+ {
+ size_t nl_count = pc1->nl_count;
+
+ pc1->nl_count = pc2->nl_count;
+ pc2->nl_count = nl_count;
+
+ chunk_swap(pc1, pc2);
+ }
+} // chunk_swap_lines
+
+
+Chunk *Chunk::GetNextNvb(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsVBrace, scope, E_Direction::FORWARD, false));
+}
+
+
+Chunk *Chunk::GetPrevNvb(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsVBrace, scope, E_Direction::BACKWARD, false));
+}
+
+
+void chunk_flags_set_real(Chunk *pc, pcf_flags_t clr_bits, pcf_flags_t set_bits)
+{
+ if ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ LOG_FUNC_ENTRY();
+ auto const nflags = (pc->flags & ~clr_bits) | set_bits;
+
+ if (pc->flags != nflags)
+ {
+ LOG_FMT(LSETFLG,
+ "%s(%d): %016llx^%016llx=%016llx\n"
+ " orig_line is %zu, orig_col is %zu, Text() '%s', type is %s,",
+ __func__, __LINE__,
+ static_cast<pcf_flags_t::int_t>(pc->flags),
+ static_cast<pcf_flags_t::int_t>(pc->flags ^ nflags),
+ static_cast<pcf_flags_t::int_t>(nflags),
+ pc->orig_line, pc->orig_col, pc->Text(),
+ get_token_name(pc->type));
+ LOG_FMT(LSETFLG, " parent_type is %s,\n ",
+ get_token_name(get_chunk_parent_type(pc)));
+ log_func_stack_inline(LSETFLG);
+ pc->flags = nflags;
+ }
+ }
+}
+
+
+void set_chunk_type_real(Chunk *pc, E_Token token, const char *func, int line)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc == nullptr
+ || pc->IsNullChunk()
+ || pc->type == token)
+ {
+ return;
+ }
+ LOG_FMT(LSETTYP, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() ",
+ func, line, pc->orig_line, pc->orig_col);
+
+ if (token == CT_NEWLINE)
+ {
+ LOG_FMT(LSETTYP, "<Newline>\n");
+ }
+ else
+ {
+ LOG_FMT(LSETTYP, "'%s'\n", pc->Text());
+ }
+ LOG_FMT(LSETTYP, " pc->type is %s, pc->parent_type is %s => *type is %s, *parent_type is %s\n",
+ get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)),
+ get_token_name(token), get_token_name(get_chunk_parent_type(pc)));
+ pc->type = token;
+} // set_chunk_type_real
+
+
+void set_chunk_parent_real(Chunk *pc, E_Token token, const char *func, int line)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc == nullptr
+ || pc->IsNullChunk()
+ || get_chunk_parent_type(pc) == token)
+ {
+ return;
+ }
+ LOG_FMT(LSETPAR, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() ",
+ func, line, pc->orig_line, pc->orig_col);
+
+ if (token == CT_NEWLINE)
+ {
+ LOG_FMT(LSETPAR, "<Newline>\n");
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LSETPAR, "'%s'\n", pc->ElidedText(copy));
+ }
+ LOG_FMT(LSETPAR, " pc->type is %s, pc->parent_type is %s => *type is %s, *parent_type is %s\n",
+ get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)),
+ get_token_name(token), get_token_name(get_chunk_parent_type(pc)));
+ pc->parent_type = token;
+} // set_chunk_parent_real
+
+
+E_Token get_chunk_parent_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return(CT_NONE);
+ }
+ return(pc->parent_type);
+} // get_chunk_parent_type
+
+
+static Chunk *chunk_add(const Chunk *pc_in, Chunk *ref, const E_Direction pos)
+{
+#ifdef DEBUG
+ // test if the pc_in chunk is properly set
+ if (pc_in->pp_level == 999)
+ {
+ fprintf(stderr, "%s(%d): pp_level is not set\n", __func__, __LINE__);
+ log_func_stack_inline(LSETFLG);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+
+ if (pc_in->orig_line == 0)
+ {
+ fprintf(stderr, "%s(%d): no line number\n", __func__, __LINE__);
+ log_func_stack_inline(LSETFLG);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+
+ if (pc_in->orig_col == 0)
+ {
+ fprintf(stderr, "%s(%d): no column number\n", __func__, __LINE__);
+ log_func_stack_inline(LSETFLG);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+#endif /* DEBUG */
+
+ Chunk *pc = new Chunk(*pc_in);
+
+ if (pc != nullptr)
+ {
+ if (ref != nullptr) // ref is a valid chunk
+ {
+ (pos == E_Direction::FORWARD) ? g_cl.AddAfter(pc, ref) : g_cl.AddBefore(pc, ref);
+ }
+ else // ref == NULL
+ {
+ (pos == E_Direction::FORWARD) ? g_cl.AddHead(pc) : g_cl.AddTail(pc);
+ }
+ chunk_log(pc, "chunk_add(A):");
+ }
+ return(pc);
+} // chunk_add
+
+
+Chunk *chunk_get_next_ssq(Chunk *cur)
+{
+ while ( chunk_is_token(cur, CT_TSQUARE)
+ || chunk_is_token(cur, CT_SQUARE_OPEN))
+ {
+ if (chunk_is_token(cur, CT_SQUARE_OPEN))
+ {
+ cur = chunk_skip_to_match(cur);
+ }
+ cur = cur->GetNextNcNnl();
+ }
+ return(cur);
+}
+
+
+Chunk *chunk_get_prev_ssq(Chunk *cur)
+{
+ while ( chunk_is_token(cur, CT_TSQUARE)
+ || chunk_is_token(cur, CT_SQUARE_CLOSE))
+ {
+ if (chunk_is_token(cur, CT_SQUARE_CLOSE))
+ {
+ cur = chunk_skip_to_match_rev(cur);
+ }
+ cur = cur->GetPrevNcNnl();
+ }
+ return(cur);
+}
+
+
+Chunk *chunk_get_pp_start(Chunk *cur)
+{
+ if (!cur->IsPreproc())
+ {
+ return(nullptr);
+ }
+
+ while (!chunk_is_token(cur, CT_PREPROC))
+ {
+ cur = cur->GetPrev(E_Scope::PREPROC);
+ }
+ return(cur);
+}
+
+
+//! skip to the final word/type in a :: chain
+static Chunk *chunk_skip_dc_member(Chunk *start, E_Scope scope, E_Direction dir)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start == nullptr)
+ {
+ return(nullptr);
+ }
+ const auto step_fcn = (dir == E_Direction::FORWARD)
+ ? &Chunk::GetNextNcNnl : &Chunk::GetPrevNcNnl;
+
+ Chunk *pc = start;
+ Chunk *next = chunk_is_token(pc, CT_DC_MEMBER) ? pc : (pc->*step_fcn)(scope);
+
+ while (chunk_is_token(next, CT_DC_MEMBER))
+ {
+ pc = (next->*step_fcn)(scope);
+
+ if (pc->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ next = (pc->*step_fcn)(scope);
+ }
+ return(pc);
+}
+
+
+Chunk *chunk_skip_dc_member(Chunk *start, E_Scope scope)
+{
+ return(chunk_skip_dc_member(start, scope, E_Direction::FORWARD));
+}
+
+
+Chunk *chunk_skip_dc_member_rev(Chunk *start, E_Scope scope)
+{
+ return(chunk_skip_dc_member(start, scope, E_Direction::BACKWARD));
+}
+
+
+// set parent member
+void chunk_set_parent(Chunk *pc, Chunk *parent)
+{
+ if (pc == nullptr)
+ {
+ return;
+ }
+
+ if (parent == nullptr)
+ {
+ return;
+ }
+
+ if (pc == parent)
+ {
+ return;
+ }
+ pc->parent = parent;
+}
+
+
+E_Token get_type_of_the_parent(Chunk *pc)
+{
+ if (pc == nullptr)
+ {
+ return(CT_UNKNOWN);
+ }
+
+ if (pc->parent == nullptr)
+ {
+ return(CT_PARENT_NOT_SET);
+ }
+ return(pc->parent->type);
+}
+
+
+bool chunk_is_attribute_or_declspec(Chunk *pc)
+{
+ return( language_is_set(LANG_CPP)
+ && ( chunk_is_token(pc, CT_ATTRIBUTE)
+ || chunk_is_token(pc, CT_DECLSPEC)));
+}
+
+
+bool chunk_is_class_enum_struct_union(Chunk *pc)
+{
+ return( chunk_is_class_or_struct(pc)
+ || chunk_is_enum(pc)
+ || chunk_is_token(pc, CT_UNION));
+}
+
+
+bool chunk_is_class_or_struct(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_CLASS)
+ || chunk_is_token(pc, CT_STRUCT));
+}
+
+
+bool chunk_is_class_struct_union(Chunk *pc)
+{
+ return( chunk_is_class_or_struct(pc)
+ || chunk_is_token(pc, CT_UNION));
+}
+
+
+bool chunk_is_enum(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_ENUM)
+ || chunk_is_token(pc, CT_ENUM_CLASS));
+}
+
+
+int chunk_compare_position(const Chunk *A_token, const Chunk *B_token)
+{
+ if (A_token == nullptr)
+ {
+ assert(A_token);
+ }
+
+ if (B_token == nullptr)
+ {
+ assert(B_token);
+ }
+
+ if (A_token->orig_line < B_token->orig_line)
+ {
+ return(-1);
+ }
+ else if (A_token->orig_line == B_token->orig_line)
+ {
+ if (A_token->orig_col < B_token->orig_col)
+ {
+ return(-1);
+ }
+ else if (A_token->orig_col == B_token->orig_col)
+ {
+ return(0);
+ }
+ }
+ return(1);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h
new file mode 100644
index 00000000..cf3b987f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h
@@ -0,0 +1,1262 @@
+/**
+ * @file chunk.h
+ * Manages and navigates the list of chunks.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef CHUNK_LIST_H_INCLUDED
+#define CHUNK_LIST_H_INCLUDED
+
+#include "uncrustify_types.h"
+// necessary to not sort it
+#include "char_table.h"
+#include "language_tools.h"
+
+
+/*
+ * TODO: better use a namespace for all chunk related operations.
+ * The function "chunk_is_comment()" would for instance
+ * become "chunk::is_comment()". This makes the usage of the chunks easier
+ * and more intuitive.
+ */
+
+
+static constexpr int ANY_LEVEL = -1;
+
+
+/**
+ * Specifies which chunks should/should not be found.
+ * ALL (default)
+ * - return the true next/prev
+ *
+ * PREPROC
+ * - If not in a preprocessor, skip over any encountered preprocessor stuff
+ * - If in a preprocessor, fail to leave (return nullptr)
+ */
+enum class E_Scope : unsigned int
+{
+ ALL, //! search in all kind of chunks
+ PREPROC, //! search only in preprocessor chunks
+};
+
+
+/**
+ * Specifies which direction or location an operation shall be performed.
+ */
+enum class E_Direction : unsigned int
+{
+ FORWARD,
+ BACKWARD
+};
+
+
+/**
+ * Temporary internal typedef. Will be progressively be replaced by Chunk::CheckFnPtr.
+ *
+ * @brief prototype for a function that checks a chunk to have a given type
+ *
+ * @note this typedef defines the function type "check_t"
+ * for a function pointer of type
+ * bool function(Chunk *pc)
+ */
+// TODO remove when finished
+typedef bool (*check_t)(Chunk *pc);
+
+
+// This is the main type of this program
+class Chunk
+{
+public:
+ static Chunk NullChunk; // Null Chunk
+ static Chunk *const NullChunkPtr; // Pointer to the Null Chunk
+
+ //! constructors
+ Chunk(bool null_c = false); // default
+ Chunk(const Chunk &o); // !!! partial copy: chunk is not linked to others
+
+ Chunk &operator=(const Chunk &o); // !!! partial copy: chunk is not linked to others
+
+ //! whether this is a null Chunk or not
+ bool IsNullChunk() const { return(null_chunk); }
+ bool IsNotNullChunk() const { return(!null_chunk); }
+
+ //! sets all elements of the struct to their default value
+ void Reset();
+
+ //! provides the number of characters of string
+ size_t Len() const;
+
+ //! provides the content of a string a zero terminated character pointer
+ const char *Text() const;
+
+ // Issue #2984, fill up, if necessary, a copy of the first chars of the Text() string
+ const char *ElidedText(char *for_the_copy) const;
+
+
+ // --------- Get* chunk functions
+
+ /**
+ * @brief returns the head of the chunk list
+ * @return pointer to the first chunk
+ */
+ static Chunk *GetHead(void);
+
+ /**
+ * @brief returns the tail of the chunk list
+ * @return pointer to the last chunk
+ */
+ static Chunk *GetTail(void);
+
+ /**
+ * @brief returns the next chunk in a list of chunks
+ * @param scope code region to search in
+ * @return pointer to next chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNext(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the previous chunk in a list of chunks
+ * @param scope code region to search in
+ * @return pointer to previous chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrev(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next newline chunk
+ * @param scope code region to search in
+ * @return pointer to next newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev newline chunk
+ * @param scope code region to search in
+ * @return pointer to prev newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next non-newline chunk
+ * @param scope code region to search in
+ * @return pointer to next non-newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNnl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev non-newline chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNnl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next non-comment chunk
+ * @param scope code region to search in
+ * @return pointer to next non-comment chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNc(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev non-comment chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-comment chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNc(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next non-comment and non-newline chunk
+ * @param scope code region to search in
+ * @return pointer to next non-comment and non-newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNcNnl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev non-comment and non-newline chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-comment and non-newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNcNnl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next non-comment, non-newline, non-preprocessor chunk
+ * @param scope code region to search in
+ * @return pointer to next non-comment, non-newline, non-preprocessor chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNcNnlNpp(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev non-comment, non-newline, non-preprocessor chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-comment, non-newline, non-preprocessor chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNcNnlNpp(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next non-preprocessor or non-comment, non-newline chunk
+ * @param scope code region to search in
+ * @return pointer to next non-preprocessor or non-comment, non-newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNppOrNcNnl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev non-preprocessor or non-comment, non-newline chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-preprocessor or non-comment, non-newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNppOrNcNnl(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next preprocessor aware non-comment and non-newline chunk
+ * Unlike Chunk::GetNextNcNnl, this will also ignore a line continuation if
+ * the starting chunk is in a preprocessor directive, and may return a newline
+ * if the search reaches the end of a preprocessor directive.
+ * @return pointer to next preprocessor aware non-comment and non-newline chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *PpaGetNextNcNnl() const;
+
+ /**
+ * @brief returns the next non-comment, non-newline, non-empty text chunk
+ * @param scope code region to search in
+ * @return pointer to next non-comment, non-newline, non-empty text chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNcNnlNet(const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev non-comment, non-newline, non-empty text chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-comment, non-newline, non-empty text chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNcNnlNet(const E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the prev non-comment, non-newline, non-ignored chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-comment, non-newline, non-ignored chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNcNnlNi(const E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the next chunk not in or part of balanced square
+ * brackets. This handles stacked [] instances to accommodate
+ * multi-dimensional array declarations
+ * @param scope code region to search in
+ * @return nullptr or the next chunk not in or part of square brackets
+ */
+ Chunk *GetNextNisq(const E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the next non-virtual brace chunk
+ * @param scope code region to search in
+ * @return pointer to next non-virtual brace chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNvb(const E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the prev non-virtual brace chunk
+ * @param scope code region to search in
+ * @return pointer to prev non-virtual brace chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNvb(const E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the next chunk of the given type at the level.
+ * @param cType the type to look for
+ * @param cLevel the level to match, -1 or ANY_LEVEL (any level)
+ * @param scope code region to search in
+ * @return pointer to the next matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextType(const E_Token cType, const int cLevel, const E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the prev chunk of the given type at the level.
+ * @param cType the type to look for
+ * @param cLevel the level to match, -1 or ANY_LEVEL (any level)
+ * @param scope code region to search in
+ * @return pointer to the prev matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevType(const E_Token type, int level, E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the next chunk that holds a given string at a given level.
+ * @param cStr string to search for
+ * @param len length of string
+ * @param cLevel -1 or ANY_LEVEL (any level) or the level to match
+ * @param scope code region to search in
+ * @return pointer to the next matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope = E_Scope::ALL) const;
+
+
+ /**
+ * @brief returns the prev chunk that holds a given string at a given level.
+ * @param cStr string to search for
+ * @param len length of string
+ * @param cLevel -1 or ANY_LEVEL (any level) or the level to match
+ * @param scope code region to search in
+ * @return pointer to the prev matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope = E_Scope::ALL) const;
+
+
+ // --------- Search functions
+
+ /**
+ * @brief defines a member function pointer for a function of type
+ * Chunk *Chunk::function(const E_Scope scope)
+ * that will search for a new chunk
+ */
+ typedef Chunk *(Chunk::*T_SearchFnPtr)(const E_Scope scope) const;
+
+ /**
+ * @brief defines a member function pointer for a function of type
+ * bool Chunk::function() const;
+ * that checks whether a chunk satisty a specific condition
+ */
+ typedef bool (Chunk::*T_CheckFnPtr)() const;
+
+ /**
+ * @brief determines the search direction to use and returns a pointer
+ * to the corresponding search function.
+ * @param dir search direction
+ * @return pointer to search function
+ */
+ static T_SearchFnPtr GetSearchFn(const E_Direction dir = E_Direction::FORWARD);
+
+ /**
+ * @brief search for a chunk that satisfies a condition in a chunk list
+ *
+ * A generic function that traverses a chunks list either
+ * in forward or reverse direction. The traversal continues until a
+ * chunk satisfies the condition defined by the compare function.
+ * Depending on the parameter cond the condition will either be
+ * checked to be true or false.
+ *
+ * @param checkFn compare function
+ * @param scope code parts to consider for search
+ * @param dir search direction (forward or backward)
+ * @param cond success condition
+ *
+ * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *Search(const T_CheckFnPtr checkFn, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD, const bool cond = true) const;
+
+ /**
+ * @brief search for a chunk that satisfies a condition in a chunk list,
+ * but being aware of preprocessor chucks.
+ *
+ * This function is similar to Search, except that it is tweaked to
+ * handle searches inside of preprocessor directives. Specifically, if the
+ * starting token is inside a preprocessor directive, it will ignore a line
+ * continuation, and will abort the search if it reaches the end of the
+ * directive. This function only searches forward.
+ *
+ * @param checkFn compare function
+ * @param cond success condition
+ *
+ * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *SearchPpa(const T_CheckFnPtr checkFn, const bool cond = true) const;
+
+ /**
+ * @brief search a chunk of a given type and level. Traverses a chunk list in the
+ * specified direction until a chunk of a given type is found.
+ *
+ * This function is a specialization of Chunk::Search.
+ *
+ * @param cType category to search for
+ * @param scope code parts to consider for search
+ * @param dir search direction
+ * @param cLevel nesting level to match or -1 / ANY_LEVEL
+ *
+ * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *SearchTypeLevel(const E_Token cType, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD, const int cLevel = -1) const;
+
+
+ /**
+ * @brief searches a chunk that holds a specific string
+ *
+ * Traverses a chunk list either in forward or backward direction until a chunk
+ * with the provided string was found. Additionally a nesting level can be
+ * provided to narrow down the search.
+ *
+ * @param cStr string that searched chunk needs to have
+ * @param len length of the string
+ * @param cLevel nesting level of the searched chunk, ignored when negative
+ * @param scope code parts to consider for search
+ * @param dir search direction
+ *
+ * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *SearchStringLevel(const char *cStr, const size_t len, const int cLevel, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD) const;
+
+
+ // --------- Is* functions
+
+ /**
+ * @brief checks whether the chunk is a specific token
+ * @token the token to check for
+ * @return true if the chunk type matches the specified token, false otherwise
+ */
+ bool Is(E_Token token) const;
+
+ /**
+ * @brief checks whether the chunk is not a specific token
+ * @token the token to check for
+ * @return true if the chunk type does not matches the specified token, false otherwise
+ */
+ bool IsNot(E_Token token) const;
+
+ /**
+ * @brief checks whether the chunk is a newline
+ * @return true if the chunk is a newline, false otherwise
+ */
+ bool IsNewline() const;
+
+ /**
+ * @brief checks whether the chunk is a comment
+ * This means any kind of:
+ * - single line comment
+ * - multiline comment
+ * - C comment
+ * - C++ comment
+ */
+ bool IsComment() const;
+
+ /**
+ * @brief checks whether the chunk is valid and has an empty text
+ * @return true if the chunk is valid and has an empty text
+ */
+ bool IsEmptyText() const;
+
+ /**
+ * @brief checks whether the chunk is a preprocessor
+ * @return true if the chunk is a preprocessor, false otherwise
+ */
+ bool IsPreproc() const;
+
+ /**
+ * @brief checks whether the chunk is either a comment or a newline
+ * @return true if the chunk is either a comment or a newline, false otherwise
+ */
+ bool IsCommentOrNewline() const;
+
+ /**
+ * @brief checks whether the chunk is either a comment, a newline or ignored
+ * @return true if the chunk is either a comment, a newline or ignored, false otherwise
+ */
+ bool IsCommentNewlineOrIgnored() const;
+
+ /**
+ * @brief checks whether the chunk is a comment, a newline or a preprocessor
+ * @return true if the chunk is a comment, a newline or a preprocessor, false otherwise
+ */
+ bool IsCommentNewlineOrPreproc() const;
+
+ /**
+ * @brief checks whether the chunk is a preprocessor and either a comment or a newline
+ * @return true if the chunk is a preprocessor and either a comment or a newline, false otherwise
+ */
+ bool IsCommentOrNewlineInPreproc() const;
+
+ /**
+ * @brief checks whether the chunk is a comment, a newline or has an empty text
+ * @return true if the chunk is a comment, a newline or has an empty text
+ */
+ bool IsCommentNewlineOrEmptyText() const;
+
+ /**
+ * @brief checks whether the chunk is a square bracket
+ * @return true if the chunk is a square bracket
+ */
+ bool IsSquareBracket() const;
+
+ /**
+ * @brief checks whether the chunk is a virtual brace
+ * @return true if the chunk is a virtual brace
+ */
+ bool IsVBrace() const;
+
+ /**
+ * @brief checks whether the chunk matches a given type and level
+ * @param type category to search for
+ * @param level nesting level to match
+ * @return true if the chunk matches a given type and level
+ */
+ bool IsTypeAndLevel(const E_Token cType, const int cLevel) const;
+
+
+ /**
+ * @brief checks whether the chunk matches a given string and level
+ * @param cStr the expected string
+ * @param len length of the string
+ * @param cLevel nesting level of the searched chunk, ignored when negative
+ * @return true if the chunk matches a given string and level
+ */
+ bool IsStringAndLevel(const char *cStr, const size_t len, const int cLevel) const;
+
+
+ /**
+ * @brief checks whether the chunk is a star/asterisk
+ * @return true if the chunk is a star/asterisk
+ */
+ bool IsStar() const;
+
+
+ // --------- Data members
+
+ Chunk *next; //! pointer to next chunk in list
+ Chunk *prev; //! pointer to previous chunk in list
+ Chunk *parent; //! pointer to parent chunk(not always set)
+
+ align_ptr_t align;
+ indent_ptr_t indent;
+ E_Token type; //! type of the chunk itself
+ E_Token parent_type; //! type of the parent chunk usually CT_NONE
+ //! might be different from parent->parent_type (above)
+ size_t orig_line; //! line number of chunk in input file
+ size_t orig_col; //! column where chunk started in the input file, is always > 0
+ size_t orig_col_end; //! column where chunk ended in the input file, is always > 1
+ UINT32 orig_prev_sp; //! whitespace before this token
+ pcf_flags_t flags; //! see PCF_xxx
+ size_t column; //! column of chunk
+ size_t column_indent; /** if 1st on a line, set to the 'indent'
+ * column, which may be less than the real
+ * column used to indent with tabs */
+ size_t nl_count; //! number of newlines in CT_NEWLINE
+ size_t nl_column; //! column of the subsequent newline entries(all of them should have the same column)
+ size_t level; /** nest level in {, (, or [
+ * only to help vim command } */
+ size_t brace_level; //! nest level in braces only
+ size_t pp_level; //! nest level in preprocessor
+ bool after_tab; //! whether this token was after a tab
+ unc_text str; //! the token text
+
+ // for debugging purpose only
+ track_list *tracking;
+
+private:
+ void copyFrom(const Chunk &o); // !!! partial copy: chunk is not linked to others
+
+ const bool null_chunk; //! true for null chunks
+};
+
+
+/**
+ * @brief Add a copy of a chunk to a chunk list after the given position.
+ *
+ * @note If ref is nullptr, add at the tail of the chunk list
+ *
+ * @todo is ref=nullptr really useful ?
+ *
+ * @param pc_in pointer to chunk to add to list
+ * @param ref position where insertion takes place
+ *
+ * @return pointer to the added chunk
+ */
+Chunk *chunk_add_after(const Chunk *pc_in, Chunk *ref);
+
+
+/**
+ * @brief Add a copy of a chunk to a chunk list before the given position
+ *
+ * @note If ref is nullptr, add at the head of the chunk list
+ *
+ * @todo is ref=nullptr really useful ?
+ *
+ * \bug code adds it before the tail, either code or comment is wrong
+ *
+ * @param pc_in pointer to chunk to add to list
+ * @param ref position where insertion takes place
+ *
+ * @retval pointer to the added chunk
+ */
+Chunk *chunk_add_before(const Chunk *pc_in, Chunk *ref);
+
+
+/**
+ * delete a chunk from a chunk list
+ *
+ * @param pc chunk to delete
+ */
+void chunk_del(Chunk * &pc);
+
+
+/**
+ * move a chunk to after the reference position in a chunk list
+ *
+ * @param pc_in chunk to move
+ * @param ref chunk after which to move
+ */
+void chunk_move_after(Chunk *pc_in, Chunk *ref);
+
+
+/**
+ * Swaps two chunks
+ *
+ * @param pc1 The first chunk
+ * @param pc2 The second chunk
+ */
+void chunk_swap(Chunk *pc1, Chunk *pc2);
+
+
+/**
+ * Swaps two lines that are started with the specified chunks.
+ *
+ * @param pc1 The first chunk of line 1
+ * @param pc2 The first chunk of line 2
+ */
+void chunk_swap_lines(Chunk *pc1, Chunk *pc2);
+
+
+/**
+ * Finds the first chunk on the line that pc is on.
+ * This just backs up until a newline or nullptr is hit.
+ *
+ * given: [ a - b - c - n1 - d - e - n2 ]
+ * input: [ a | b | c | n1 ] => a
+ * input: [ d | e | n2 ] => d
+ *
+ * @param pc chunk to start with
+ */
+Chunk *chunk_first_on_line(Chunk *pc);
+
+
+//! check if a given chunk is the last on its line
+bool chunk_is_last_on_line(Chunk *pc);
+
+
+/**
+ * Gets the next chunk not in or part of balanced square
+ * brackets.This handles stacked[] instances to accommodate
+ * multi - dimensional array declarations
+ *
+ * @param cur chunk to use as start point
+ *
+ * @return nullptr or the next chunk not in or part of square brackets
+ */
+Chunk *chunk_get_next_ssq(Chunk *cur);
+
+/**
+ * Gets the prev chunk not in or part of balanced square
+ * brackets.This handles stacked[] instances to accommodate
+ * multi - dimensional array declarations
+ *
+ * @param cur chunk to use as start point
+ *
+ * @return nullptr or the prev chunk not in or part of square brackets
+ */
+Chunk *chunk_get_prev_ssq(Chunk *cur);
+
+
+/**
+ * Gets the corresponding start chunk if the given chunk is within a
+ * preprocessor directive, or nullptr otherwise.
+ *
+ * @param cur chunk to use as start point
+ *
+ * @return nullptr or start chunk of the preprocessor directive
+ */
+Chunk *chunk_get_pp_start(Chunk *cur);
+
+
+/**
+ * @brief reverse search a chunk of a given category in a chunk list
+ *
+ * @param pc chunk list to search in
+ * @param cat category to search for
+ *
+ * @retval nullptr no object found, or invalid parameters provided
+ * @retval Chunk pointer to the found object
+ */
+Chunk *chunk_search_prev_cat(Chunk *pc, const E_Token cat);
+
+
+/**
+ * @brief forward search a chunk of a given category in a chunk list
+ *
+ * @param pc chunk list to search in
+ * @param cat category to search for
+ *
+ * @retval nullptr no object found, or invalid parameters provided
+ * @retval Chunk pointer to the found object
+ */
+Chunk *chunk_search_next_cat(Chunk *pc, const E_Token cat);
+
+
+/**
+ * @brief checks wether two chunks are in same line
+ *
+ * @param start
+ * @param end
+ *
+ * @return true if there is no newline between start and end chunks
+ */
+bool are_chunks_in_same_line(Chunk *start, Chunk *end);
+
+
+inline bool Chunk::IsTypeAndLevel(const E_Token cType, const int cLevel) const
+{
+ return( ( cLevel < 0
+ || level == static_cast<size_t>(cLevel))
+ && type == cType);
+}
+
+
+inline bool Chunk::IsStringAndLevel(const char *cStr, const size_t len, const int cLevel) const
+{
+ return( ( cLevel < 0
+ || level == static_cast<size_t>(cLevel))
+ && Len() == len // the length is as expected
+ && memcmp(cStr, Text(), len) == 0); // the strings are equal
+}
+
+
+inline bool Chunk::Is(E_Token token) const
+{
+ return( IsNotNullChunk()
+ && type == token);
+}
+
+
+inline bool Chunk::IsNot(E_Token token) const
+{
+ return(!Is(token));
+}
+
+
+inline bool Chunk::IsNewline() const
+{
+ return( Is(CT_NEWLINE)
+ || Is(CT_NL_CONT));
+}
+
+
+inline bool Chunk::IsComment() const
+{
+ return( Is(CT_COMMENT)
+ || Is(CT_COMMENT_MULTI)
+ || Is(CT_COMMENT_CPP));
+}
+
+
+inline bool Chunk::IsEmptyText() const
+{
+ return( IsNotNullChunk()
+ && Len() == 0);
+}
+
+
+inline bool Chunk::IsPreproc() const
+{
+ return( IsNotNullChunk()
+ && flags.test(PCF_IN_PREPROC));
+}
+
+
+inline bool Chunk::IsCommentOrNewline() const
+{
+ return( IsComment()
+ || IsNewline());
+}
+
+
+inline bool Chunk::IsCommentNewlineOrPreproc() const
+{
+ return( IsComment()
+ || IsNewline()
+ || IsPreproc());
+}
+
+
+inline bool Chunk::IsCommentOrNewlineInPreproc() const
+{
+ return( IsPreproc()
+ && ( IsComment()
+ || IsNewline()));
+}
+
+
+inline bool Chunk::IsCommentNewlineOrEmptyText() const
+{
+ return( IsComment()
+ || IsNewline()
+ || IsEmptyText());
+}
+
+
+inline bool Chunk::IsCommentNewlineOrIgnored() const
+{
+ return( IsComment()
+ || IsNewline()
+ || Is(CT_IGNORED));
+}
+
+
+inline bool Chunk::IsSquareBracket() const
+{
+ return( Is(CT_SQUARE_OPEN)
+ || Is(CT_TSQUARE)
+ || Is(CT_SQUARE_CLOSE));
+}
+
+
+inline bool Chunk::IsVBrace() const
+{
+ return( Is(CT_VBRACE_OPEN)
+ || Is(CT_VBRACE_CLOSE));
+}
+
+
+inline bool Chunk::IsStar() const
+{
+ return( Len() == 1
+ && str[0] == '*'
+ && IsNot(CT_OPERATOR_VAL));
+}
+
+
+// TODO remove when possible
+static inline bool chunk_is_token(const Chunk *pc, E_Token c_token)
+{
+ return( pc != nullptr
+ && pc->IsNotNullChunk()
+ && pc->type == c_token);
+}
+
+
+// TODO remove when possible
+static inline bool chunk_is_not_token(const Chunk *pc, E_Token c_token)
+{
+ return( pc != nullptr
+ && pc->IsNotNullChunk()
+ && pc->type != c_token);
+}
+
+
+/**
+ * Skips to the closing match for the current paren/brace/square.
+ *
+ * @param cur The opening or closing paren/brace/square
+ * @param scope chunk section to consider
+ *
+ * @return nullptr or the matching paren/brace/square
+ */
+static inline Chunk *chunk_skip_to_match(Chunk *cur, E_Scope scope = E_Scope::ALL)
+{
+ if ( cur != nullptr
+ && ( chunk_is_token(cur, CT_PAREN_OPEN)
+ || chunk_is_token(cur, CT_SPAREN_OPEN)
+ || chunk_is_token(cur, CT_FPAREN_OPEN)
+ || chunk_is_token(cur, CT_TPAREN_OPEN)
+ || chunk_is_token(cur, CT_BRACE_OPEN)
+ || chunk_is_token(cur, CT_VBRACE_OPEN)
+ || chunk_is_token(cur, CT_ANGLE_OPEN)
+ || chunk_is_token(cur, CT_SQUARE_OPEN)))
+ {
+ return(cur->GetNextType((E_Token)(cur->type + 1), cur->level, scope));
+ }
+ return(cur);
+}
+
+
+static inline Chunk *chunk_skip_to_match_rev(Chunk *cur, E_Scope scope = E_Scope::ALL)
+{
+ if ( cur != nullptr
+ && ( chunk_is_token(cur, CT_PAREN_CLOSE)
+ || chunk_is_token(cur, CT_SPAREN_CLOSE)
+ || chunk_is_token(cur, CT_FPAREN_CLOSE)
+ || chunk_is_token(cur, CT_TPAREN_CLOSE)
+ || chunk_is_token(cur, CT_BRACE_CLOSE)
+ || chunk_is_token(cur, CT_VBRACE_CLOSE)
+ || chunk_is_token(cur, CT_ANGLE_CLOSE)
+ || chunk_is_token(cur, CT_SQUARE_CLOSE)))
+ {
+ return(cur->GetPrevType((E_Token)(cur->type - 1), cur->level, scope));
+ }
+ return(cur);
+}
+
+
+//! skip to the final word/type in a :: chain
+Chunk *chunk_skip_dc_member(Chunk *start, E_Scope scope = E_Scope::ALL);
+Chunk *chunk_skip_dc_member_rev(Chunk *start, E_Scope scope = E_Scope::ALL);
+
+
+/**
+ * Returns true if the chunk under test is an inheritance access specifier
+ */
+static inline bool chunk_is_cpp_inheritance_access_specifier(Chunk *pc)
+{
+ return( language_is_set(LANG_CPP)
+ && pc != nullptr
+ && pc->IsNotNullChunk()
+ && ( chunk_is_token(pc, CT_ACCESS)
+ || chunk_is_token(pc, CT_QUALIFIER))
+ && ( std::strncmp(pc->str.c_str(), "private", 7) == 0
+ || std::strncmp(pc->str.c_str(), "protected", 9) == 0
+ || std::strncmp(pc->str.c_str(), "public", 6) == 0));
+} // chunk_is_cpp_inheritance_access_specifier
+
+
+static inline bool chunk_is_colon(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_ACCESS_COLON)
+ || chunk_is_token(pc, CT_ASM_COLON)
+ || chunk_is_token(pc, CT_BIT_COLON)
+ || chunk_is_token(pc, CT_CASE_COLON)
+ || chunk_is_token(pc, CT_CLASS_COLON)
+ || chunk_is_token(pc, CT_COLON)
+ || chunk_is_token(pc, CT_COND_COLON)
+ || chunk_is_token(pc, CT_CONSTR_COLON)
+ || chunk_is_token(pc, CT_CS_SQ_COLON)
+ || chunk_is_token(pc, CT_D_ARRAY_COLON)
+ || chunk_is_token(pc, CT_FOR_COLON)
+ || chunk_is_token(pc, CT_LABEL_COLON)
+ || chunk_is_token(pc, CT_OC_COLON)
+ || chunk_is_token(pc, CT_OC_DICT_COLON)
+ || chunk_is_token(pc, CT_TAG_COLON)
+ || chunk_is_token(pc, CT_WHERE_COLON));
+}
+
+
+static inline bool chunk_is_single_line_comment(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_COMMENT)
+ || chunk_is_token(pc, CT_COMMENT_CPP));
+}
+
+
+// TODO remove when possible
+static inline bool chunk_is_newline(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_NEWLINE)
+ || chunk_is_token(pc, CT_NL_CONT));
+}
+
+
+static inline bool chunk_is_semicolon(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_SEMICOLON)
+ || chunk_is_token(pc, CT_VSEMICOLON));
+}
+
+
+static inline bool chunk_is_Doxygen_comment(Chunk *pc)
+{
+ if ( pc == nullptr
+ || !pc->IsComment())
+ {
+ return(false);
+ }
+ // check the third character
+ const char *sComment = pc->Text();
+ const size_t len = strlen(sComment);
+
+ if (len < 3)
+ {
+ return(false);
+ }
+ return( (sComment[2] == '/')
+ || (sComment[2] == '!')
+ || (sComment[2] == '@'));
+}
+
+
+static inline bool chunk_is_type(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_PTR_TYPE)
+ || chunk_is_token(pc, CT_BYREF)
+ || chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_QUALIFIER)
+ || chunk_is_token(pc, CT_STRUCT)
+ || chunk_is_token(pc, CT_ENUM)
+ || chunk_is_token(pc, CT_UNION));
+}
+
+
+static inline bool chunk_is_str(Chunk *pc, const char *str)
+{
+ size_t len = strlen(str);
+
+ return( pc != nullptr // valid pc pointer
+ && (pc->Len() == len) // token size equals size parameter
+ && (memcmp(pc->Text(), str, len) == 0)); // token name is the same as str parameter
+
+ /*
+ * TODO: possible access beyond array for memcmp, check this
+ * why not use strncmp here?
+ */
+}
+
+
+static inline bool chunk_is_str_case(Chunk *pc, const char *str, size_t len)
+{
+ return( pc != nullptr
+ && (pc->Len() == len)
+ && (strncasecmp(pc->Text(), str, len) == 0));
+}
+
+
+static inline bool chunk_is_word(Chunk *pc)
+{
+ return( pc != nullptr
+ && (pc->Len() >= 1)
+ && CharTable::IsKw1(pc->str[0]));
+}
+
+
+static inline bool chunk_is_nullable(Chunk *pc)
+{
+ return( language_is_set(LANG_CS | LANG_VALA)
+ && (pc != nullptr)
+ && (pc->Len() == 1)
+ && (pc->str[0] == '?'));
+}
+
+
+static inline bool chunk_is_addr(Chunk *pc)
+{
+ if ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && ( chunk_is_token(pc, CT_BYREF)
+ || ( (pc->Len() == 1)
+ && (pc->str[0] == '&')
+ && pc->type != CT_OPERATOR_VAL)))
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( pc->flags.test(PCF_IN_TEMPLATE)
+ && ( chunk_is_token(prev, CT_COMMA)
+ || chunk_is_token(prev, CT_ANGLE_OPEN)))
+ {
+ return(false);
+ }
+ return(true);
+ }
+ return(false);
+}
+
+
+static inline bool chunk_is_msref(Chunk *pc) // ms compilers for C++/CLI and WinRT use '^' instead of '*' for marking up reference types vs pointer types
+{
+ return( language_is_set(LANG_CPP)
+ && ( pc != nullptr
+ && (pc->Len() == 1)
+ && (pc->str[0] == '^')
+ && pc->type != CT_OPERATOR_VAL));
+}
+
+
+static inline bool chunk_is_ptr_operator(Chunk *pc)
+{
+ return( pc != nullptr
+ && ( ( pc->IsStar()
+ || chunk_is_addr(pc)
+ || chunk_is_msref(pc))
+ || chunk_is_nullable(pc)));
+}
+
+
+static inline bool chunk_is_pointer_or_reference(Chunk *pc)
+{
+ return( chunk_is_ptr_operator(pc)
+ || chunk_is_token(pc, CT_BYREF));
+}
+
+
+//! Check to see if there is a newline between the two chunks
+bool chunk_is_newline_between(Chunk *start, Chunk *end);
+
+
+static inline bool chunk_is_closing_brace(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE));
+}
+
+
+static inline bool chunk_is_opening_brace(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_OPEN));
+}
+
+
+static inline bool chunk_is_paren_open(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_PAREN_OPEN)
+ || chunk_is_token(pc, CT_SPAREN_OPEN)
+ || chunk_is_token(pc, CT_TPAREN_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_LPAREN_OPEN));
+}
+
+
+static inline bool chunk_is_paren_close(Chunk *pc)
+{
+ return( chunk_is_token(pc, CT_PAREN_CLOSE)
+ || chunk_is_token(pc, CT_SPAREN_CLOSE)
+ || chunk_is_token(pc, CT_TPAREN_CLOSE)
+ || chunk_is_token(pc, CT_FPAREN_CLOSE));
+}
+
+
+/**
+ * Returns true if either chunk is null or both have the same preproc flags.
+ * If this is true, you can remove a newline/nl_cont between the two.
+ */
+static inline bool chunk_same_preproc(Chunk *pc1, Chunk *pc2)
+{
+ return( pc1 == nullptr
+ || pc1->IsNullChunk()
+ || pc2 == nullptr
+ || pc2->IsNullChunk()
+ || ((pc1->flags & PCF_IN_PREPROC) == (pc2->flags & PCF_IN_PREPROC)));
+}
+
+
+/**
+ * Returns true if it is safe to delete the newline token.
+ * The prev and next chunks must have the same PCF_IN_PREPROC flag AND
+ * the newline can't be after a C++ comment.
+ */
+static inline bool chunk_safe_to_del_nl(Chunk *nl)
+{
+ if (nl == nullptr)
+ {
+ nl = Chunk::NullChunkPtr;
+ }
+ Chunk *tmp = nl->GetPrev();
+
+ if (chunk_is_token(tmp, CT_COMMENT_CPP))
+ {
+ return(false);
+ }
+ return(chunk_same_preproc(tmp, nl->GetNext()));
+}
+
+
+/**
+ * Checks if a chunk points to the opening parenthese of a
+ * for(...in...) loop in Objective-C.
+ *
+ * @return true - the chunk is the opening parentheses of a for in loop
+ */
+static inline bool chunk_is_forin(Chunk *pc)
+{
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(pc, CT_SPAREN_OPEN))
+ {
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if (chunk_is_token(prev, CT_FOR))
+ {
+ Chunk *next = pc;
+
+ while ( next != nullptr
+ && next->type != CT_SPAREN_CLOSE
+ && next->type != CT_IN)
+ {
+ next = next->GetNextNcNnl();
+ }
+
+ if (chunk_is_token(next, CT_IN))
+ {
+ return(true);
+ }
+ }
+ }
+ return(false);
+}
+
+
+/**
+ * Returns true if pc is an CT_ATTRIBUTE or CT_DECLSPEC
+ */
+bool chunk_is_attribute_or_declspec(Chunk *pc);
+
+
+/**
+ * Returns true if pc is one of CT_CLASS, CT_ENUM, CT_ENUM_CLASS, CT_STRUCT or CT_UNION
+ */
+bool chunk_is_class_enum_struct_union(Chunk *pc);
+
+
+/**
+ * Returns true if pc is a CT_CLASS or CT_STRUCT
+ */
+bool chunk_is_class_or_struct(Chunk *pc);
+
+
+/**
+ * Returns true if pc is one of CT_CLASS, CT_STRUCT or CT_UNION
+ */
+bool chunk_is_class_struct_union(Chunk *pc);
+
+
+/**
+ * Returns true if pc is a CT_ENUM or CT_ENUM_CLASS
+ */
+bool chunk_is_enum(Chunk *pc);
+
+
+void set_chunk_type_real(Chunk *pc, E_Token tt, const char *func, int line);
+
+
+void set_chunk_parent_real(Chunk *pc, E_Token tt, const char *func, int line);
+
+
+#define set_chunk_type(pc, tt) set_chunk_type_real((pc), (tt), __unqualified_func__, __LINE__)
+
+
+#define set_chunk_parent(pc, tt) set_chunk_parent_real((pc), (tt), __unqualified_func__, __LINE__)
+
+
+E_Token get_chunk_parent_type(Chunk *pc);
+
+
+void chunk_flags_set_real(Chunk *pc, pcf_flags_t clr_bits, pcf_flags_t set_bits);
+
+
+#define chunk_flags_upd(pc, cc, ss) chunk_flags_set_real((pc), (cc), (ss))
+
+
+#define chunk_flags_set(pc, ss) chunk_flags_set_real((pc), {}, (ss))
+
+
+#define chunk_flags_clr(pc, cc) chunk_flags_set_real((pc), (cc), {})
+
+
+void chunk_set_parent(Chunk *pc, Chunk *parent);
+
+
+E_Token get_type_of_the_parent(Chunk *pc);
+
+
+/**
+ * @brief compare the positions of two tokens in a file.
+ *
+ * The function compares the two positions of two tokens.
+ *
+ * @param A_token
+ * @param B_token
+ *
+ * @return returns an integer less than, equal to, or greater than zero
+ * if A_token is found, respectively, to be less/before than, to
+ * match, or be greater/after than B_token.
+ */
+int chunk_compare_position(const Chunk *A_token, const Chunk *B_token);
+
+
+#endif /* CHUNK_LIST_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.cpp
new file mode 100644
index 00000000..f21d106c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.cpp
@@ -0,0 +1,4018 @@
+/**
+ * @file combine.cpp
+ * Labels the chunks as needed.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "combine.h"
+
+#include "combine_fix_mark.h"
+#include "combine_skip.h"
+#include "combine_tools.h"
+#include "EnumStructUnionParser.h"
+#include "flag_braced_init_list.h"
+#include "flag_parens.h"
+#include "lang_pawn.h"
+#include "newlines.h"
+#include "prototypes.h"
+#include "tokenize_cleanup.h"
+
+#include <limits>
+
+constexpr static auto LCURRENT = LCOMBINE;
+
+using namespace std;
+using namespace uncrustify;
+
+
+/**
+ * Mark the parens and colons in:
+ * asm volatile ( "xx" : "xx" (l), "yy"(h) : ... );
+ *
+ * @param pc the CT_ASM item
+ */
+static void flag_asm(Chunk *pc);
+
+
+/**
+ * Skips the list of class/struct parent types.
+ */
+Chunk *skip_parent_types(Chunk *colon);
+
+
+/**
+ * Combines two tokens into {{ and }} if inside parens and nothing is between
+ * either pair.
+ */
+static void check_double_brace_init(Chunk *bo1);
+
+
+static void process_returns(void);
+
+
+/**
+ * Processes a return statement, labeling the parens and marking the parent.
+ * May remove or add parens around the return statement
+ *
+ * @param pc Pointer to the return chunk
+ */
+static Chunk *process_return(Chunk *pc);
+
+
+/**
+ * Process an ObjC 'class'
+ * pc is the chunk after '@implementation' or '@interface' or '@protocol'.
+ * Change colons, etc. Processes stuff until '@end'.
+ * Skips anything in braces.
+ */
+static void handle_oc_class(Chunk *pc);
+
+
+/**
+ * Mark Objective-C blocks (aka lambdas or closures)
+ * The syntax and usage is exactly like C function pointers
+ * but instead of an asterisk they have a caret as pointer symbol.
+ * Although it may look expensive this functions is only triggered
+ * on appearance of an OC_BLOCK_CARET for LANG_OC.
+ * repeat(10, ^{ putc('0'+d); });
+ * typedef void (^workBlk_t)(void);
+ *
+ * @param pc points to the '^'
+ */
+static void handle_oc_block_literal(Chunk *pc);
+
+
+/**
+ * Mark Objective-C block types.
+ * The syntax and usage is exactly like C function pointers
+ * but instead of an asterisk they have a caret as pointer symbol.
+ * typedef void (^workBlk_t)(void);
+ * const char * (^workVar)(void);
+ * -(void)Foo:(void(^)())blk { }
+ *
+ * This is triggered when the sequence '(' '^' is found.
+ *
+ * @param pc points to the '^'
+ */
+static void handle_oc_block_type(Chunk *pc);
+
+
+/**
+ * Process an ObjC message spec/dec
+ *
+ * Specs:
+ * -(void) foo ARGS;
+ *
+ * Declaration:
+ * -(void) foo ARGS { }
+ *
+ * LABEL : (ARGTYPE) ARGNAME
+ *
+ * ARGS is ': (ARGTYPE) ARGNAME [MOREARGS...]'
+ * MOREARGS is ' [ LABEL] : (ARGTYPE) ARGNAME '
+ * -(void) foo: (int) arg: { }
+ * -(void) foo: (int) arg: { }
+ * -(void) insertObject:(id)anObject atIndex:(int)index
+ */
+static void handle_oc_message_decl(Chunk *pc);
+
+
+/**
+ * Process an ObjC message send statement:
+ * [ class func: val1 name2: val2 name3: val3] ; // named params
+ * [ class func: val1 : val2 : val3] ; // unnamed params
+ * [ class <proto> self method ] ; // with protocol
+ * [[NSMutableString alloc] initWithString: @"" ] // class from msg
+ * [func(a,b,c) lastObject ] // class from func
+ *
+ * Mainly find the matching ']' and ';' and mark the colons.
+ *
+ * @param pc points to the open square '['
+ */
+static void handle_oc_message_send(Chunk *pc);
+
+
+//! Process @Property values and re-arrange them if necessary
+static void handle_oc_property_decl(Chunk *pc);
+
+//! Process @available annotation
+static void handle_oc_available(Chunk *pc);
+
+/**
+ * Process a type that is enclosed in parens in message declarations.
+ * TODO: handle block types, which get special formatting
+ *
+ * @param pc points to the open paren
+ *
+ * @return the chunk after the type
+ */
+static Chunk *handle_oc_md_type(Chunk *paren_open, E_Token ptype, pcf_flags_t flags, bool &did_it);
+
+/**
+ * Process an C# [] thingy:
+ * [assembly: xxx]
+ * [AttributeUsage()]
+ * [@X]
+ *
+ * Set the next chunk to a statement start after the close ']'
+ *
+ * @param pc points to the open square '['
+ */
+static void handle_cs_square_stmt(Chunk *pc);
+
+
+/**
+ * We are on a brace open that is preceded by a word or square close.
+ * Set the brace parent to CT_CS_PROPERTY and find the first item in the
+ * property and set its parent, too.
+ */
+static void handle_cs_property(Chunk *pc);
+
+
+/**
+ * We hit a ']' followed by a WORD. This may be a multidimensional array type.
+ * Example: int[,,] x;
+ * If there is nothing but commas between the open and close, then mark it.
+ */
+static void handle_cs_array_type(Chunk *pc);
+
+
+/**
+ * We are on the C++ 'template' keyword.
+ * What follows should be the following:
+ *
+ * template <class identifier> function_declaration;
+ * template <typename identifier> function_declaration;
+ * template <class identifier> class class_declaration;
+ * template <typename identifier> class class_declaration;
+ *
+ * Change the 'class' inside the <> to CT_TYPE.
+ * Set the parent to the class after the <> to CT_TEMPLATE.
+ * Set the parent of the semicolon to CT_TEMPLATE.
+ */
+static void handle_cpp_template(Chunk *pc);
+
+
+/**
+ * Verify and then mark C++ lambda expressions.
+ * The expected format is '[...](...){...}' or '[...](...) -> type {...}'
+ * sq_o is '[' CT_SQUARE_OPEN or '[]' CT_TSQUARE
+ * Split the '[]' so we can control the space
+ */
+static void handle_cpp_lambda(Chunk *pc);
+
+
+/**
+ * We are on the D 'template' keyword.
+ * What follows should be the following:
+ *
+ * template NAME ( TYPELIST ) { BODY }
+ *
+ * Set the parent of NAME to template, change NAME to CT_TYPE.
+ * Set the parent of the parens and braces to CT_TEMPLATE.
+ * Scan the body for each type in TYPELIST and change the type to CT_TYPE.
+ */
+static void handle_d_template(Chunk *pc);
+
+
+/**
+ * A func wrap chunk and what follows should be treated as a function name.
+ * Create new text for the chunk and call it a CT_FUNCTION.
+ *
+ * A type wrap chunk and what follows should be treated as a simple type.
+ * Create new text for the chunk and call it a CT_TYPE.
+ */
+static void handle_wrap(Chunk *pc);
+
+
+/**
+ * A proto wrap chunk and what follows should be treated as a function proto.
+ *
+ * RETTYPE PROTO_WRAP( NAME, PARAMS ); or RETTYPE PROTO_WRAP( NAME, (PARAMS) );
+ * RETTYPE gets changed with make_type().
+ * PROTO_WRAP is marked as CT_FUNC_PROTO or CT_FUNC_DEF.
+ * NAME is marked as CT_WORD.
+ * PARAMS is all marked as prototype parameters.
+ */
+static void handle_proto_wrap(Chunk *pc);
+
+
+static bool is_oc_block(Chunk *pc);
+
+
+/**
+ * Java assert statements are: "assert EXP1 [: EXP2] ;"
+ * Mark the parent of the colon and semicolon
+ */
+static void handle_java_assert(Chunk *pc);
+
+
+static void flag_asm(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *tmp = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (chunk_is_not_token(tmp, CT_QUALIFIER))
+ {
+ return;
+ }
+ Chunk *po = tmp->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (!chunk_is_paren_open(po))
+ {
+ return;
+ }
+ Chunk *end = chunk_skip_to_match(po, E_Scope::PREPROC);
+
+ if (end == nullptr)
+ {
+ return;
+ }
+ set_chunk_parent(po, CT_ASM);
+ set_chunk_parent(end, CT_ASM);
+
+ for ( tmp = po->GetNextNcNnl(E_Scope::PREPROC);
+ tmp->IsNotNullChunk()
+ && tmp != end;
+ tmp = tmp->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ if (chunk_is_token(tmp, CT_COLON))
+ {
+ set_chunk_type(tmp, CT_ASM_COLON);
+ }
+ else if (chunk_is_token(tmp, CT_DC_MEMBER))
+ {
+ // if there is a string on both sides, then this is two ASM_COLONs
+ if ( chunk_is_token(tmp->GetNextNcNnl(E_Scope::PREPROC), CT_STRING)
+ && chunk_is_token(tmp->GetPrevNcNnlNi(E_Scope::PREPROC), CT_STRING)) // Issue #2279
+ {
+ Chunk nc;
+
+ nc = *tmp;
+
+ tmp->str.resize(1);
+ tmp->orig_col_end = tmp->orig_col + 1;
+ set_chunk_type(tmp, CT_ASM_COLON);
+
+ set_chunk_type(&nc, tmp->type);
+ nc.str.pop_front();
+ nc.orig_col++;
+ nc.column++;
+ chunk_add_after(&nc, tmp);
+ }
+ }
+ }
+
+ tmp = end->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ set_chunk_parent(tmp, CT_ASM);
+ }
+} // flag_asm
+
+
+void do_symbol_check(Chunk *prev, Chunk *pc, Chunk *next)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LFCNR, "%s(%d): prev is '%s' %s\n",
+ __func__, __LINE__,
+ prev->Text(), get_token_name(prev->type));
+ log_pcf_flags(LFCNR, prev->flags);
+ LOG_FMT(LFCNR, "%s(%d): pc is '%s' %s\n",
+ __func__, __LINE__,
+ pc->Text(), get_token_name(pc->type));
+ log_pcf_flags(LFCNR, pc->flags);
+ LOG_FMT(LFCNR, "%s(%d): next is '%s' %s\n",
+ __func__, __LINE__,
+ next->Text(), get_token_name(next->type));
+ log_pcf_flags(LFCNR, next->flags);
+
+ if ( chunk_is_token(pc, CT_NOEXCEPT) // Issue #3284
+ && chunk_is_token(next, CT_ASSIGN)) // skip over noexcept
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ pc = next;
+ next = pc->GetNext();
+ }
+
+ // separate the uses of CT_ASSIGN sign '='
+ // into CT_ASSIGN_DEFAULT_ARG, CT_ASSIGN_FUNC_PROTO
+ if ( chunk_is_token(pc, CT_ASSIGN)
+ && get_chunk_parent_type(pc) == CT_FUNC_PROTO
+ && ( pc->flags.test(PCF_IN_FCN_DEF) // Issue #2236
+ || pc->flags.test(PCF_IN_CONST_ARGS)))
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ log_pcf_flags(LFCNR, pc->flags);
+ set_chunk_type(pc, CT_ASSIGN_DEFAULT_ARG);
+ return;
+ }
+
+ if ( ( chunk_is_token(prev, CT_FPAREN_CLOSE)
+ || ( ( chunk_is_str(prev, "const")
+ || chunk_is_str(prev, "override"))
+ && chunk_is_token(prev->prev, CT_FPAREN_CLOSE)))
+ && chunk_is_token(pc, CT_ASSIGN)
+ && ( chunk_is_token(next, CT_DEFAULT)
+ || chunk_is_token(next, CT_DELETE)
+ || chunk_is_str(next, "0")))
+ {
+ set_chunk_type(pc, CT_ASSIGN_FUNC_PROTO);
+ return; // cpp 30031
+ }
+
+ if (chunk_is_token(pc, CT_OC_AT))
+ {
+ if ( chunk_is_token(next, CT_PAREN_OPEN)
+ || chunk_is_token(next, CT_BRACE_OPEN)
+ || chunk_is_token(next, CT_SQUARE_OPEN))
+ {
+ flag_parens(next, PCF_OC_BOXED, next->type, CT_OC_AT, false);
+ }
+ else
+ {
+ set_chunk_parent(next, CT_OC_AT);
+ return; // objective-c_50095
+ }
+ }
+
+ // D stuff
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(pc, CT_QUALIFIER)
+ && chunk_is_str(pc, "const")
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_D_CAST);
+ set_paren_parent(next, pc->type);
+ return; // d_40061
+ }
+
+ if ( chunk_is_token(next, CT_PAREN_OPEN)
+ && ( chunk_is_token(pc, CT_D_CAST)
+ || chunk_is_token(pc, CT_DELEGATE)
+ || chunk_is_token(pc, CT_ALIGN)))
+ {
+ // mark the parenthesis parent
+ Chunk *tmp = set_paren_parent(next, pc->type);
+
+ // For a D cast - convert the next item
+ if ( chunk_is_token(pc, CT_D_CAST)
+ && tmp != nullptr)
+ {
+ if (chunk_is_token(tmp, CT_STAR))
+ {
+ set_chunk_type(tmp, CT_DEREF);
+ return; // d_40006
+ }
+ else if (chunk_is_token(tmp, CT_AMP))
+ {
+ set_chunk_type(tmp, CT_ADDR);
+ return; // d_40060
+ }
+ else if (chunk_is_token(tmp, CT_MINUS))
+ {
+ set_chunk_type(tmp, CT_NEG);
+ return; // d_40060
+ }
+ else if (chunk_is_token(tmp, CT_PLUS))
+ {
+ set_chunk_type(tmp, CT_POS);
+ return; // d_40060
+ }
+ }
+
+ /*
+ * For a delegate, mark previous words as types and the item after the
+ * close paren as a variable def
+ */
+ if (chunk_is_token(pc, CT_DELEGATE))
+ {
+ if (tmp != nullptr)
+ {
+ set_chunk_parent(tmp, CT_DELEGATE);
+
+ if (tmp->level == tmp->brace_level)
+ {
+ chunk_flags_set(tmp, PCF_VAR_1ST_DEF);
+ }
+ }
+
+ for (tmp = pc->GetPrevNcNnlNi(); tmp->IsNotNullChunk(); tmp = tmp->GetPrevNcNnlNi()) // Issue #2279
+ {
+ if ( chunk_is_semicolon(tmp)
+ || chunk_is_token(tmp, CT_BRACE_OPEN)
+ || chunk_is_token(tmp, CT_VBRACE_OPEN))
+ {
+ break;
+ }
+ make_type(tmp);
+ }
+
+ return; // c-sharp_10160
+ }
+
+ if ( chunk_is_token(pc, CT_ALIGN)
+ && tmp != nullptr)
+ {
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ set_paren_parent(tmp, pc->type);
+ return; // d_40024
+ }
+ else if (chunk_is_token(tmp, CT_COLON))
+ {
+ set_chunk_parent(tmp, pc->type);
+ return; // d_40024
+ }
+ }
+ } // paren open + cast/align/delegate
+
+ if (chunk_is_token(pc, CT_INVARIANT))
+ {
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_parent(next, pc->type);
+ Chunk *tmp = next->GetNext();
+
+ if (tmp == nullptr)
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+
+ while (tmp->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ set_chunk_parent(tmp, pc->type);
+ break;
+ }
+ make_type(tmp);
+ tmp = tmp->GetNext();
+ }
+ return; // d_40100
+ }
+ else
+ {
+ set_chunk_type(pc, CT_QUALIFIER);
+ return;
+ }
+ }
+
+ if ( chunk_is_token(prev, CT_BRACE_OPEN)
+ && get_chunk_parent_type(prev) != CT_CS_PROPERTY
+ && ( chunk_is_token(pc, CT_GETSET)
+ || chunk_is_token(pc, CT_GETSET_EMPTY)))
+ {
+ flag_parens(prev, PCF_NONE, CT_NONE, CT_GETSET, false);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_ASM))
+ {
+ flag_asm(pc);
+ return;
+ }
+
+ // clang stuff - A new derived type is introduced to C and, by extension, Objective-C, C++, and Objective-C++
+ if (language_is_set(LANG_C | LANG_CPP | LANG_OC))
+ {
+ if (chunk_is_token(pc, CT_CARET))
+ {
+ if ( pc->flags.test(PCF_EXPR_START)
+ || pc->flags.test(PCF_IN_PREPROC))
+ {
+ handle_oc_block_literal(pc);
+ return;
+ }
+ }
+ }
+
+ // Objective C stuff
+ if (language_is_set(LANG_OC))
+ {
+ // Check for message declarations
+ if (pc->flags.test(PCF_STMT_START))
+ {
+ if ( ( chunk_is_str(pc, "-")
+ || chunk_is_str(pc, "+"))
+ && chunk_is_str(next, "("))
+ {
+ handle_oc_message_decl(pc);
+ return;
+ }
+ }
+
+ if ( pc->flags.test(PCF_EXPR_START)
+ || pc->flags.test(PCF_IN_PREPROC))
+ {
+ if (chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ handle_oc_message_send(pc);
+ return; // objective-c_50003
+ }
+ }
+
+ if (chunk_is_token(pc, CT_OC_PROPERTY))
+ {
+ handle_oc_property_decl(pc);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_OC_AVAILABLE))
+ {
+ handle_oc_available(pc);
+ return;
+ }
+ }
+
+ // C# stuff
+ if (language_is_set(LANG_CS))
+ {
+ // '[assembly: xxx]' stuff
+ if ( pc->flags.test(PCF_EXPR_START)
+ && chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ handle_cs_square_stmt(pc);
+ return;
+ }
+
+ if ( chunk_is_token(next, CT_BRACE_OPEN)
+ && get_chunk_parent_type(next) == CT_NONE
+ && ( chunk_is_token(pc, CT_SQUARE_CLOSE)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE)
+ || chunk_is_token(pc, CT_WORD)))
+ {
+ handle_cs_property(next);
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_SQUARE_CLOSE)
+ && chunk_is_token(next, CT_WORD))
+ {
+ handle_cs_array_type(pc);
+ return;
+ }
+
+ if ( ( chunk_is_token(pc, CT_LAMBDA)
+ || chunk_is_token(pc, CT_DELEGATE))
+ && chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ set_paren_parent(next, pc->type);
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_WHEN)
+ && pc->GetNext()->IsNotNullChunk()
+ && pc->GetNext()->type != CT_SPAREN_OPEN)
+ {
+ set_chunk_type(pc, CT_WORD);
+ return;
+ }
+ }
+
+ if ( language_is_set(LANG_JAVA)
+ && chunk_is_token(pc, CT_LAMBDA)
+ && chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ set_paren_parent(next, pc->type);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_NEW))
+ {
+ Chunk *ts = nullptr;
+ Chunk *tmp = next;
+
+ if (chunk_is_token(tmp, CT_TSQUARE))
+ {
+ ts = tmp;
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if ( chunk_is_token(tmp, CT_BRACE_OPEN)
+ || chunk_is_token(tmp, CT_PAREN_OPEN))
+ {
+ set_paren_parent(tmp, pc->type);
+
+ if (ts != nullptr)
+ {
+ set_chunk_parent(ts, pc->type);
+ }
+ }
+ return;
+ }
+
+ // C++11 Lambda stuff
+ if ( language_is_set(LANG_CPP)
+ && ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ || chunk_is_token(pc, CT_TSQUARE)))
+ {
+ handle_cpp_lambda(pc);
+ }
+
+ // FIXME: which language does this apply to?
+ // Issue #2432
+ if (!language_is_set(LANG_OC))
+ {
+ if ( chunk_is_token(pc, CT_ASSIGN)
+ && chunk_is_token(next, CT_SQUARE_OPEN))
+ {
+ set_paren_parent(next, CT_ASSIGN);
+
+ // Mark one-liner assignment
+ Chunk *tmp = next;
+
+ while ((tmp = tmp->GetNextNc())->IsNotNullChunk())
+ {
+ if (chunk_is_newline(tmp))
+ {
+ break;
+ }
+
+ if ( chunk_is_token(tmp, CT_SQUARE_CLOSE)
+ && next->level == tmp->level)
+ {
+ chunk_flags_set(tmp, PCF_ONE_LINER);
+ chunk_flags_set(next, PCF_ONE_LINER);
+ break;
+ }
+ }
+ return;
+ }
+ }
+
+ if (chunk_is_token(pc, CT_ASSERT))
+ {
+ handle_java_assert(pc);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_ANNOTATION))
+ {
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (chunk_is_paren_open(tmp))
+ {
+ set_paren_parent(tmp, CT_ANNOTATION);
+ }
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_SIZEOF)
+ && language_is_set(LANG_ALLC))
+ {
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (chunk_is_token(tmp, CT_ELLIPSIS))
+ {
+ set_chunk_parent(tmp, CT_SIZEOF);
+ }
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_DECLTYPE)
+ && pc->parent_type != CT_FUNC_DEF)
+ {
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (chunk_is_paren_open(tmp))
+ {
+ // decltype may be followed by a braced-init-list
+ tmp = set_paren_parent(tmp, CT_DECLTYPE);
+
+ if (chunk_is_opening_brace(tmp) && !pc->flags.test(PCF_IN_LAMBDA))
+ {
+ tmp = set_paren_parent(tmp, CT_BRACED_INIT_LIST);
+
+ if (tmp)
+ {
+ chunk_flags_clr(tmp, PCF_EXPR_START | PCF_STMT_START);
+ }
+ }
+ else
+ {
+ if (chunk_is_token(tmp, CT_WORD))
+ {
+ chunk_flags_set(tmp, PCF_VAR_1ST_DEF);
+ }
+ }
+ }
+ return;
+ }
+
+ // A [] in C# and D only follows a type
+ if ( chunk_is_token(pc, CT_TSQUARE)
+ && language_is_set(LANG_D | LANG_CS | LANG_VALA))
+ {
+ if (chunk_is_token(prev, CT_WORD))
+ {
+ set_chunk_type(prev, CT_TYPE);
+ }
+
+ if (chunk_is_token(next, CT_WORD))
+ {
+ chunk_flags_set(next, PCF_VAR_1ST_DEF);
+ }
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_SQL_EXEC)
+ || chunk_is_token(pc, CT_SQL_BEGIN)
+ || chunk_is_token(pc, CT_SQL_END))
+ {
+ mark_exec_sql(pc);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_PROTO_WRAP))
+ {
+ handle_proto_wrap(pc);
+ return;
+ }
+
+ // Handle the typedef
+ if (chunk_is_token(pc, CT_TYPEDEF))
+ {
+ fix_typedef(pc);
+ return;
+ }
+
+ if ( chunk_is_class_enum_struct_union(pc)
+ && chunk_is_not_token(prev, CT_TYPEDEF))
+ {
+ EnumStructUnionParser parser;
+ parser.parse(pc);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_EXTERN))
+ {
+ if (chunk_is_paren_open(next))
+ {
+ Chunk *tmp = flag_parens(next, PCF_NONE, CT_NONE, CT_EXTERN, true);
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ set_paren_parent(tmp, CT_EXTERN);
+ }
+ }
+ else
+ {
+ // next likely is a string (see tokenize_cleanup.cpp)
+ set_chunk_parent(next, CT_EXTERN);
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ set_paren_parent(tmp, CT_EXTERN);
+ }
+ }
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_TEMPLATE))
+ {
+ if (language_is_set(LANG_D))
+ {
+ handle_d_template(pc);
+ }
+ else
+ {
+ handle_cpp_template(pc);
+ }
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_WORD)
+ && chunk_is_token(next, CT_ANGLE_OPEN)
+ && get_chunk_parent_type(next) == CT_TEMPLATE)
+ {
+ mark_template_func(pc, next);
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_SQUARE_CLOSE)
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_NONE, false);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_TYPE_CAST))
+ {
+ fix_type_cast(pc);
+ return;
+ }
+
+ if ( get_chunk_parent_type(pc) == CT_ASSIGN
+ && ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_SQUARE_OPEN)))
+ {
+ // Mark everything in here as in assign
+ flag_parens(pc, PCF_IN_ARRAY_ASSIGN, pc->type, CT_NONE, false);
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_D_TEMPLATE))
+ {
+ set_paren_parent(next, pc->type);
+ return;
+ }
+
+ /*
+ * A word before an open paren is a function call or definition.
+ * CT_WORD => CT_FUNC_CALL or CT_FUNC_DEF
+ */
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if ( language_is_set(LANG_C | LANG_CPP | LANG_OC)
+ && chunk_is_token(tmp, CT_CARET))
+ {
+ handle_oc_block_type(tmp);
+
+ // This is the case where a block literal is passed as the first argument of a C-style method invocation.
+ if ( ( chunk_is_token(tmp, CT_OC_BLOCK_CARET)
+ || chunk_is_token(tmp, CT_CARET))
+ && chunk_is_token(pc, CT_WORD))
+ {
+ LOG_FMT(LFCN, "%s(%d): (1) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ }
+ }
+ else if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_OPERATOR_VAL))
+ {
+ set_chunk_type(pc, CT_FUNCTION);
+ }
+ else if (chunk_is_token(pc, CT_FIXED))
+ {
+ set_chunk_type(pc, CT_FUNCTION);
+ set_chunk_parent(pc, CT_FIXED);
+ }
+ else if (chunk_is_token(pc, CT_TYPE))
+ {
+ /*
+ * If we are on a type, then we are either on a C++ style cast, an
+ * array reference, a function or we are on a function type.
+ * The only way to tell for sure is to find the close paren and see
+ * if it is followed by an open paren.
+ * "int(5.6)"
+ * "int()"
+ * "int(foo)(void)"
+ *
+ * FIXME: this check can be done better...
+ */
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ bool is_byref_array = false;
+
+ if (language_is_set(LANG_CPP))
+ {
+ // If the open paren is followed by an ampersand, an optional word,
+ // a close parenthesis, and an open square bracket, then it is an
+ // array being passed by reference, not a cast
+ tmp = next->GetNextNcNnl();
+
+ if (chunk_is_token(tmp, CT_AMP))
+ {
+ auto tmp2 = tmp->GetNextNcNnl();
+
+ if (chunk_is_token(tmp2, CT_WORD))
+ {
+ tmp2 = tmp2->GetNextNcNnl();
+ }
+
+ if (chunk_is_token(tmp2, CT_PAREN_CLOSE))
+ {
+ tmp2 = tmp2->GetNextNcNnl();
+
+ if (chunk_is_token(tmp2, CT_SQUARE_OPEN))
+ {
+ is_byref_array = true;
+ set_chunk_type(tmp, CT_BYREF);
+ }
+ }
+ }
+ }
+
+ if (!is_byref_array)
+ {
+ tmp = next->GetNextType(CT_PAREN_CLOSE, next->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = tmp->GetNext();
+
+ if (chunk_is_token(tmp, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_FUNCTION);
+ }
+ else
+ {
+ if ( get_chunk_parent_type(pc) == CT_NONE
+ && !pc->flags.test(PCF_IN_TYPEDEF))
+ {
+ tmp = next->GetNextNcNnl();
+
+ if (chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ // we have TYPE()
+ set_chunk_type(pc, CT_FUNCTION);
+ }
+ else
+ {
+ // we have TYPE(...)
+ set_chunk_type(pc, CT_CPP_CAST);
+ set_paren_parent(next, CT_CPP_CAST);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (language_is_set(LANG_PAWN))
+ {
+ if ( chunk_is_token(pc, CT_FUNCTION)
+ && pc->brace_level > 0)
+ {
+ LOG_FMT(LFCN, "%s(%d): (2) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ }
+
+ if ( chunk_is_token(pc, CT_STATE)
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_paren_parent(next, pc->type);
+ }
+ }
+ else
+ {
+ if ( ( chunk_is_token(pc, CT_FUNCTION)
+ || chunk_is_token(pc, CT_FUNC_DEF))
+ && ( (get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR)
+ || !is_oc_block(pc)))
+ {
+ mark_function(pc);
+ }
+ }
+
+ // Detect C99 member stuff
+ if ( chunk_is_token(pc, CT_MEMBER)
+ && ( chunk_is_token(prev, CT_COMMA)
+ || chunk_is_token(prev, CT_BRACE_OPEN)))
+ {
+ set_chunk_type(pc, CT_C99_MEMBER);
+ set_chunk_parent(next, CT_C99_MEMBER);
+ return;
+ }
+
+ // Mark function parens and braces
+ if ( chunk_is_token(pc, CT_FUNC_DEF)
+ || chunk_is_token(pc, CT_FUNC_CALL)
+ || chunk_is_token(pc, CT_FUNC_CALL_USER)
+ || chunk_is_token(pc, CT_FUNC_PROTO))
+ {
+ Chunk *tmp = next;
+
+ if (chunk_is_token(tmp, CT_SQUARE_OPEN))
+ {
+ tmp = set_paren_parent(tmp, pc->type);
+ }
+ else if ( chunk_is_token(tmp, CT_TSQUARE)
+ || get_chunk_parent_type(tmp) == CT_OPERATOR)
+ {
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if ( tmp != nullptr
+ && tmp->IsNotNullChunk())
+ {
+ if (chunk_is_paren_open(tmp))
+ {
+ tmp = flag_parens(tmp, PCF_NONE, CT_FPAREN_OPEN, pc->type, false);
+
+ if ( tmp != nullptr
+ && tmp->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ if ( get_chunk_parent_type(tmp) != CT_DOUBLE_BRACE
+ && !pc->flags.test(PCF_IN_CONST_ARGS))
+ {
+ set_paren_parent(tmp, pc->type);
+ }
+ }
+ else if ( chunk_is_semicolon(tmp)
+ && chunk_is_token(pc, CT_FUNC_PROTO))
+ {
+ set_chunk_parent(tmp, pc->type);
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ // Mark the parameters in catch()
+ if ( chunk_is_token(pc, CT_CATCH)
+ && chunk_is_token(next, CT_SPAREN_OPEN))
+ {
+ fix_fcn_def_params(next);
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_THROW)
+ && chunk_is_token(prev, CT_FPAREN_CLOSE))
+ {
+ set_chunk_parent(pc, get_chunk_parent_type(prev));
+
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_paren_parent(next, CT_THROW);
+ }
+ return;
+ }
+
+ // Mark the braces in: "for_each_entry(xxx) { }"
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && get_chunk_parent_type(pc) != CT_DOUBLE_BRACE
+ && chunk_is_token(prev, CT_FPAREN_CLOSE)
+ && ( get_chunk_parent_type(prev) == CT_FUNC_CALL
+ || get_chunk_parent_type(prev) == CT_FUNC_CALL_USER)
+ && !pc->flags.test(PCF_IN_CONST_ARGS))
+ {
+ LOG_FMT(LFCN, "%s(%d): (3) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_paren_parent(pc, CT_FUNC_CALL);
+ return;
+ }
+
+ /*
+ * Check for a close parenthesis followed by an open parenthesis,
+ * which means that we are on a function type declaration (C/C++ only?).
+ * Note that typedefs are already taken care of.
+ */
+ if ( !pc->flags.test(PCF_IN_TEMPLATE) // Issue #3252
+ && get_chunk_parent_type(pc) != CT_CPP_CAST
+ && get_chunk_parent_type(pc) != CT_C_CAST
+ && !pc->flags.test(PCF_IN_PREPROC)
+ && !is_oc_block(pc)
+ && get_chunk_parent_type(pc) != CT_OC_MSG_DECL
+ && get_chunk_parent_type(pc) != CT_OC_MSG_SPEC
+ && chunk_is_str(pc, ")")
+ && chunk_is_str(next, "("))
+ {
+ if (language_is_set(LANG_D))
+ {
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
+ }
+ else
+ {
+ mark_function_type(pc);
+ }
+ return;
+ }
+
+ if (chunk_is_token(pc, CT_OC_CLASS))
+ {
+ handle_oc_class(pc);
+ return;
+ }
+ // TODO: Check for stuff that can only occur at the start of an statement
+
+ if (!language_is_set(LANG_D))
+ {
+ /*
+ * Check a parenthesis pair to see if it is a cast.
+ * Note that SPAREN and FPAREN have already been marked.
+ */
+ if ( chunk_is_token(pc, CT_PAREN_OPEN)
+ && ( get_chunk_parent_type(pc) == CT_NONE
+ || get_chunk_parent_type(pc) == CT_OC_MSG
+ || get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR
+ || get_chunk_parent_type(pc) == CT_CS_SQ_STMT) // Issue # 1256
+ && ( chunk_is_token(next, CT_WORD)
+ || chunk_is_token(next, CT_TYPE)
+ || chunk_is_token(next, CT_STRUCT)
+ || chunk_is_token(next, CT_QUALIFIER)
+ || chunk_is_token(next, CT_MEMBER)
+ || chunk_is_token(next, CT_DC_MEMBER)
+ || chunk_is_token(next, CT_ENUM)
+ || chunk_is_token(next, CT_UNION))
+ && chunk_is_not_token(prev, CT_DECLTYPE)
+ && chunk_is_not_token(prev, CT_SIZEOF)
+ && get_chunk_parent_type(prev) != CT_SIZEOF
+ && get_chunk_parent_type(prev) != CT_OPERATOR
+ && !pc->flags.test(PCF_IN_TYPEDEF))
+ {
+ fix_casts(pc);
+ return;
+ }
+ }
+
+ if (language_is_set(LANG_CPP))
+ {
+ Chunk *nnext = next->GetNextNcNnl();
+
+ // handle parent_type of assigns in special functions (ro5 + pure virtual)
+ if ( pc->flags.test_any(PCF_IN_STRUCT | PCF_IN_CLASS)
+ && chunk_is_token(pc, CT_ASSIGN)
+ && chunk_is_token(nnext, CT_SEMICOLON)
+ && ( chunk_is_token(next, CT_DEFAULT)
+ || chunk_is_token(next, CT_DELETE)
+ || ( chunk_is_token(next, CT_NUMBER)
+ && chunk_is_str(next, "0"))))
+ {
+ const size_t level = pc->level;
+ bool found_status = false;
+ Chunk *pprev = pc->GetPrev();
+
+ for ( ; ( pprev->IsNotNullChunk()
+ && pprev->level >= level
+ && chunk_is_not_token(pprev, CT_SEMICOLON)
+ && chunk_is_not_token(pprev, CT_ACCESS_COLON))
+ ; pprev = pprev->GetPrev())
+ {
+ if (pprev->level != level)
+ {
+ continue;
+ }
+
+ if (chunk_is_token(next, CT_NUMBER))
+ {
+ if ( chunk_is_token(pprev, CT_QUALIFIER)
+ && chunk_is_str(pprev, "virtual"))
+ {
+ found_status = true;
+ break;
+ }
+ }
+ else
+ {
+ if ( chunk_is_token(pprev, CT_FUNC_CLASS_PROTO) // ctor/dtor
+ || chunk_is_token(pprev, CT_FUNC_PROTO)) // normal function
+ {
+ found_status = true;
+ break;
+ }
+ }
+ }
+
+ if (found_status)
+ {
+ set_chunk_parent(pc, pprev->type);
+ }
+ }
+
+ if (detect_cpp_braced_init_list(pc, next))
+ {
+ flag_cpp_braced_init_list(pc, next);
+ }
+ }
+
+ // Check for stuff that can only occur at the start of an expression
+ if ( pc->flags.test(PCF_EXPR_START)
+ || ( prev->flags.test(PCF_EXPR_START)
+ && get_chunk_parent_type(pc) == CT_OC_AT))
+ {
+ // Change STAR, MINUS, and PLUS in the easy cases
+ if (chunk_is_token(pc, CT_STAR))
+ {
+ // issue #596
+ // [0x100062020:IN_SPAREN,IN_FOR,STMT_START,EXPR_START,PUNCTUATOR]
+ // prev->type is CT_COLON ==> CT_DEREF
+ if (chunk_is_token(prev, CT_ANGLE_CLOSE))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if (chunk_is_token(prev, CT_COLON))
+ {
+ set_chunk_type(pc, CT_DEREF);
+ }
+ else
+ {
+ set_chunk_type(pc, CT_DEREF);
+ }
+ }
+
+ if ( language_is_set(LANG_CPP)
+ && chunk_is_token(pc, CT_CARET)
+ && chunk_is_token(prev, CT_ANGLE_CLOSE))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+
+ if ( language_is_set(LANG_CS | LANG_VALA)
+ && chunk_is_token(pc, CT_QUESTION)
+ && chunk_is_token(prev, CT_ANGLE_CLOSE))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+
+ else if (chunk_is_token(pc, CT_MINUS))
+ {
+ set_chunk_type(pc, CT_NEG);
+ }
+
+ else if (chunk_is_token(pc, CT_PLUS))
+ {
+ set_chunk_type(pc, CT_POS);
+ }
+
+ else if (chunk_is_token(pc, CT_INCDEC_AFTER))
+ {
+ set_chunk_type(pc, CT_INCDEC_BEFORE);
+ }
+
+ else if (chunk_is_token(pc, CT_AMP))
+ {
+ if (chunk_is_token(prev, CT_ANGLE_CLOSE)) // Issue #2324
+ {
+ set_chunk_type(pc, CT_BYREF);
+ }
+ else
+ {
+ set_chunk_type(pc, CT_ADDR);
+ }
+ }
+
+ else if (chunk_is_token(pc, CT_CARET))
+ {
+ if (language_is_set(LANG_C | LANG_CPP | LANG_OC))
+ {
+ // This is likely the start of a block literal
+ handle_oc_block_literal(pc);
+ }
+ }
+ }
+
+ /*
+ * Change the parenthesis pair after a function/macro-function
+ * CT_PAREN_OPEN => CT_FPAREN_OPEN
+ */
+ if (chunk_is_token(pc, CT_MACRO_FUNC))
+ {
+ flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_MACRO_FUNC, false);
+ }
+
+ if ( chunk_is_token(pc, CT_MACRO_OPEN)
+ || chunk_is_token(pc, CT_MACRO_ELSE)
+ || chunk_is_token(pc, CT_MACRO_CLOSE))
+ {
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, pc->type, false);
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_DELETE)
+ && chunk_is_token(next, CT_TSQUARE))
+ {
+ set_chunk_parent(next, CT_DELETE);
+ }
+
+ // Change CT_STAR to CT_PTR_TYPE or CT_ARITH or CT_DEREF
+ if ( chunk_is_token(pc, CT_STAR)
+ || ( language_is_set(LANG_CPP)
+ && chunk_is_token(pc, CT_CARET)))
+ {
+ if ( chunk_is_paren_close(next)
+ || chunk_is_token(next, CT_COMMA))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if ( language_is_set(LANG_OC)
+ && chunk_is_token(next, CT_STAR))
+ {
+ /*
+ * Change pointer-to-pointer types in OC_MSG_DECLs
+ * from ARITH <===> DEREF to PTR_TYPE <===> PTR_TYPE
+ */
+ set_chunk_type(pc, CT_PTR_TYPE);
+ set_chunk_parent(pc, get_chunk_parent_type(prev));
+
+ set_chunk_type(next, CT_PTR_TYPE);
+ set_chunk_parent(next, get_chunk_parent_type(pc));
+ }
+ else if ( chunk_is_token(pc, CT_STAR)
+ && ( chunk_is_token(prev, CT_DECLTYPE)
+ || chunk_is_token(prev, CT_SIZEOF)
+ || chunk_is_token(prev, CT_DELETE)
+ || get_chunk_parent_type(pc) == CT_SIZEOF))
+ {
+ set_chunk_type(pc, CT_DEREF);
+ }
+ else if ( ( chunk_is_token(prev, CT_WORD)
+ && chunk_ends_type(prev)
+ && !prev->flags.test(PCF_IN_FCN_CTOR)
+ && !prev->flags.test(PCF_IN_ARRAY_ASSIGN)) // Issue #3345
+ || chunk_is_token(prev, CT_DC_MEMBER)
+ || chunk_is_token(prev, CT_PTR_TYPE))
+ {
+ LOG_FMT(LFCNR, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n ",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ log_pcf_flags(LFCNR, pc->flags);
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if ( chunk_is_token(next, CT_SQUARE_OPEN)
+ && !language_is_set(LANG_OC)) // Issue #408
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if (chunk_is_token(pc, CT_STAR))
+ {
+ // Add check for CT_DC_MEMBER CT_WORD CT_STAR sequence
+ // to convert CT_WORD into CT_TYPE
+ // and CT_STAR into CT_PTR_TYPE
+ // look for an assign backward, fuction call, return to distinguish between
+ // double result = Constants::PI * factor;
+ // and
+ // ::some::name * foo;
+ if ( chunk_is_token(prev, CT_WORD)
+ && chunk_is_token(prev->prev, CT_DC_MEMBER)
+ && language_is_set(LANG_CPP))
+ {
+ // Issue 1402
+ bool is_multiplication = false;
+ Chunk *tmp = pc;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_SEMICOLON)
+ || get_chunk_parent_type(tmp) == CT_CLASS)
+ {
+ break;
+ }
+ else if ( chunk_is_token(tmp, CT_ASSIGN)
+ || chunk_is_token(tmp, CT_FUNC_CALL)
+ || chunk_is_token(tmp, CT_RETURN))
+ {
+ is_multiplication = true;
+ break;
+ }
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ if (is_multiplication)
+ {
+ // double result = Constants::PI * factor;
+ set_chunk_type(pc, CT_ARITH);
+ }
+ else
+ {
+ // ::some::name * foo;
+ set_chunk_type(prev, CT_TYPE);
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ }
+
+ /*
+ * A star can have three meanings
+ * 1. CT_DEREF = pointer dereferencing
+ * 2. CT_PTR_TYPE = pointer definition
+ * 3. CT_ARITH = arithmetic multiplication
+ *
+ * most PCF_PUNCTUATOR chunks except a paren close would make this
+ * a deref. A paren close may end a cast or may be part of a macro fcn.
+ */
+ if (chunk_is_token(prev, CT_TYPE))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if ( chunk_is_token(pc->next, CT_SEMICOLON) // Issue #2319
+ || ( chunk_is_token(pc->next, CT_STAR)
+ && chunk_is_token(pc->next->next, CT_SEMICOLON)))
+ {
+ // example:
+ // using AbstractLinkPtr = AbstractLink*;
+ // using AbstractLinkPtrPtr = AbstractLink**;
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if ( ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ && ( chunk_is_opening_brace(next)
+ || pc->GetNext()->IsStar()))
+ || chunk_is_token(next, CT_QUALIFIER)) // Issue #2648
+ {
+ // example:
+ // auto getComponent(Color *color) -> Component * {
+ // auto getComponent(Color *color) -> Component ** {
+ // auto getComponent(Color *color) -> Component * _Nonnull
+ // only to help the vim command }}
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if ( chunk_is_token(pc->next, CT_SEMICOLON) // Issue #2319
+ || ( chunk_is_token(pc->next, CT_STAR)
+ && chunk_is_token(pc->next->next, CT_STAR)))
+ {
+ // more pointers are NOT yet possible
+ fprintf(stderr, "Too many pointers: the maximum level of pointer indirection is 3 (i.e., ***p)\n");
+ fprintf(stderr, "at line %zu, column %zu.\n", pc->orig_line, pc->orig_col);
+ fprintf(stderr, "Please make a report.\n");
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ else
+ {
+ // Issue 1402
+ set_chunk_type(pc,
+ ( prev->flags.test(PCF_PUNCTUATOR)
+ && ( !chunk_is_paren_close(prev)
+ || chunk_is_token(prev, CT_SPAREN_CLOSE)
+ || get_chunk_parent_type(prev) == CT_MACRO_FUNC)
+ && chunk_is_not_token(prev, CT_SQUARE_CLOSE)
+ && chunk_is_not_token(prev, CT_DC_MEMBER)) ? CT_DEREF : CT_ARITH);
+ }
+
+ if (pc->flags.test(PCF_IN_TYPEDEF)) // Issue #1255/#633
+ {
+ Chunk *tmp = pc;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_SEMICOLON)
+ || chunk_is_token(tmp, CT_BRACE_OPEN)
+ || chunk_is_token(tmp, CT_SQUARE_OPEN)) // Issue #3342
+ {
+ break;
+ }
+ else if (chunk_is_token(tmp, CT_TYPEDEF))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+ }
+ }
+ }
+ }
+
+ if (chunk_is_token(pc, CT_AMP))
+ {
+ if (chunk_is_token(prev, CT_DELETE))
+ {
+ set_chunk_type(pc, CT_ADDR);
+ }
+ else if ( chunk_is_token(prev, CT_TYPE)
+ || chunk_is_token(prev, CT_QUALIFIER))
+ {
+ set_chunk_type(pc, CT_BYREF);
+ }
+ else if ( chunk_is_token(prev, CT_WORD) // Issue #3204
+ && chunk_is_token(next, CT_OPERATOR))
+ {
+ set_chunk_type(pc, CT_BYREF);
+ }
+ else if ( chunk_is_token(next, CT_FPAREN_CLOSE)
+ || chunk_is_token(next, CT_COMMA))
+ {
+ // fix the bug #654
+ // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &)));
+ set_chunk_type(pc, CT_BYREF);
+ }
+ else if (get_chunk_parent_type(pc) == CT_USING_ALIAS)
+ {
+ // fix the Issue # 1689
+ // using reference = value_type &;
+ set_chunk_type(pc->prev, CT_TYPE);
+ set_chunk_type(pc, CT_BYREF);
+ }
+ else
+ {
+ // Issue # 1398
+ if ( pc->flags.test(PCF_IN_FCN_DEF)
+ && chunk_is_token(prev, CT_WORD)
+ && chunk_is_token(pc, CT_AMP)
+ && chunk_is_token(next, CT_WORD))
+ {
+ /*
+ * Change CT_WORD before CT_AMP before CT_WORD to CT_TYPE
+ */
+ set_chunk_type(prev, CT_TYPE);
+ }
+ else
+ {
+ set_chunk_type(pc, CT_ARITH);
+
+ if ( chunk_is_token(prev, CT_WORD)
+ && !chunk_is_token(next, CT_NUMBER)) // Issue #3407
+ {
+ Chunk *tmp = prev->GetPrevNcNnlNi(); // Issue #2279
+
+ if (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_semicolon(tmp)
+ || chunk_is_token(tmp, CT_BRACE_OPEN)
+ || chunk_is_token(tmp, CT_QUALIFIER))
+ {
+ set_chunk_type(pc, CT_BYREF);
+ set_chunk_type(prev, CT_TYPE);
+
+ if (!( chunk_is_token(next, CT_OPERATOR)
+ || chunk_is_token(next, CT_TYPE)
+ || chunk_is_token(next, CT_DC_MEMBER)))
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', set PCF_VAR_1ST\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ chunk_flags_set(next, PCF_VAR_1ST);
+ }
+ }
+ else if (chunk_is_token(tmp, CT_DC_MEMBER))
+ {
+ set_chunk_type(prev, CT_TYPE);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_MINUS)
+ || chunk_is_token(pc, CT_PLUS))
+ {
+ if ( chunk_is_token(prev, CT_POS)
+ || chunk_is_token(prev, CT_NEG)
+ || chunk_is_token(prev, CT_ARITH)
+ || chunk_is_token(prev, CT_SHIFT))
+ {
+ set_chunk_type(pc, chunk_is_token(pc, CT_MINUS) ? CT_NEG : CT_POS);
+ }
+ else if (chunk_is_token(prev, CT_OC_CLASS))
+ {
+ set_chunk_type(pc, (chunk_is_token(pc, CT_MINUS)) ? CT_NEG : CT_POS);
+ }
+ else
+ {
+ set_chunk_type(pc, CT_ARITH);
+ }
+ }
+
+ /*
+ * Bug # 634
+ * Check for extern "C" NSString* i;
+ * NSString is a type
+ * change CT_WORD => CT_TYPE for pc
+ * change CT_STAR => CT_PTR_TYPE for pc-next
+ */
+ if (chunk_is_token(pc, CT_WORD)) // here NSString
+ {
+ if (pc->next != nullptr) // here *
+ {
+ if (pc->next->type == CT_STAR) // here *
+ {
+ // compare text with "C" to find extern "C" instructions
+ if (pc->prev != nullptr)
+ {
+ if (pc->prev->type == CT_STRING)
+ {
+ if (unc_text::compare(pc->prev->Text(), "\"C\"") == 0)
+ {
+ if (pc->prev->prev->type == CT_EXTERN)
+ {
+ set_chunk_type(pc, CT_TYPE); // change CT_WORD => CT_TYPE
+ set_chunk_type(pc->next, CT_PTR_TYPE); // change CT_STAR => CT_PTR_TYPE
+ }
+ }
+ }
+ }
+
+ // Issue #322 STDMETHOD(GetValues)(BSTR bsName, REFDATA** pData);
+ if ( (pc->next->next != nullptr)
+ && pc->next->next->type == CT_STAR
+ && pc->flags.test(PCF_IN_CONST_ARGS))
+ {
+ // change CT_STAR => CT_PTR_TYPE
+ set_chunk_type(pc->next, CT_PTR_TYPE);
+ set_chunk_type(pc->next->next, CT_PTR_TYPE);
+ }
+
+ // Issue #222 whatever3 *(func_ptr)( whatever4 *foo2, ...
+ if ( (pc->next->next != nullptr)
+ && pc->next->next->type == CT_WORD
+ && pc->flags.test(PCF_IN_FCN_DEF))
+ {
+ // look for the opening parenthesis
+ // Issue 1403
+ Chunk *tmp = pc->GetPrevType(CT_FPAREN_OPEN, pc->level - 1);
+
+ if ( tmp->IsNotNullChunk()
+ && get_chunk_parent_type(tmp) != CT_FUNC_CTOR_VAR)
+ {
+ set_chunk_type(pc->next, CT_PTR_TYPE);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Bug # 634
+ * Check for __attribute__((visibility ("default"))) NSString* i;
+ * NSString is a type
+ * change CT_WORD => CT_TYPE for pc
+ * change CT_STAR => CT_PTR_TYPE for pc-next
+ */
+ if (chunk_is_token(pc, CT_WORD)) // here NSString
+ {
+ if (pc->next != nullptr) // here *
+ {
+ if (pc->next->type == CT_STAR) // here *
+ {
+ Chunk *tmp = pc;
+
+ while ( tmp != nullptr
+ && tmp->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_ATTRIBUTE))
+ {
+ LOG_FMT(LFCNR, "%s(%d): ATTRIBUTE found, type is %s, Text() '%s'\n",
+ __func__, __LINE__, get_token_name(tmp->type), tmp->Text());
+ LOG_FMT(LFCNR, "for token, type is %s, Text() '%s'\n", get_token_name(pc->type), pc->Text());
+ // change CT_WORD => CT_TYPE
+ set_chunk_type(pc, CT_TYPE);
+ // change CT_STAR => CT_PTR_TYPE
+ set_chunk_type(pc->next, CT_PTR_TYPE);
+ }
+
+ if (tmp->flags.test(PCF_STMT_START))
+ {
+ // we are at beginning of the line
+ break;
+ }
+ tmp = tmp->GetPrev();
+ }
+ }
+ }
+ }
+
+ /*
+ * Issue # 1689
+ * Check for using reference = value_type&;
+ * is it a Type alias, alias template?
+ */
+ if (chunk_is_token(pc, CT_USING))
+ {
+ // look for CT_ASSIGN before CT_SEMICOLON at the end of the statement
+
+ bool is_preproc = pc->flags.test(PCF_IN_PREPROC);
+
+ auto const search_assign = [&pc, &is_preproc]()
+ {
+ for (Chunk *temp = pc; temp->IsNotNullChunk(); temp = temp->GetNextNcNnl())
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, temp->orig_line, temp->orig_col,
+ temp->Text(), get_token_name(temp->type));
+
+ if (chunk_is_token(temp, CT_ASSIGN))
+ {
+ return(true);
+ }
+
+ if ( chunk_is_token(temp, CT_SEMICOLON)
+ || ( is_preproc
+ && ( !temp->flags.test(PCF_IN_PREPROC)
+ || chunk_is_token(temp, CT_PREPROC))))
+ {
+ return(false);
+ }
+ }
+
+ return(false);
+ };
+
+ const bool assign_found = language_is_set(LANG_D) || search_assign();
+
+ if (assign_found)
+ {
+ // it is a Type alias, alias template
+ for (Chunk *temp = pc; temp->IsNotNullChunk(); temp = temp->GetNextNcNnl())
+ {
+ if (get_chunk_parent_type(temp) == CT_NONE)
+ {
+ set_chunk_parent(temp, CT_USING_ALIAS);
+ }
+
+ if ( chunk_is_token(temp, CT_SEMICOLON)
+ || ( is_preproc
+ && ( !temp->flags.test(PCF_IN_PREPROC)
+ || chunk_is_token(temp, CT_PREPROC))))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ // Issue #548: inline T && someFunc(foo * *p, bar && q) { }
+ if ( chunk_is_token(pc, CT_BOOL)
+ && !pc->flags.test(PCF_IN_PREPROC)
+ && chunk_is_str(pc, "&&")
+ && chunk_ends_type(pc->prev))
+ {
+ Chunk *tmp = pc->GetPrev(); // Issue #2688
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col,
+ tmp->Text(), get_token_name(tmp->type));
+ log_pcf_flags(LFCNR, tmp->flags);
+ // look for a type
+
+ if (chunk_is_token(tmp, CT_TYPE))
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col,
+ pc->Text(), get_token_name(pc->type));
+ log_pcf_flags(LFCNR, pc->flags);
+ set_chunk_type(pc, CT_BYREF);
+ }
+ // look next, is there a "assign" before the ";"
+ Chunk *semi = pc->GetNextType(CT_SEMICOLON, pc->level); // Issue #2688
+
+ if (semi->IsNotNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, semi->orig_line, semi->orig_col,
+ semi->Text(), get_token_name(semi->type));
+
+ for (Chunk *test_it = pc; test_it != semi; test_it = test_it->GetNext())
+ {
+ LOG_FMT(LFCNR, "%s(%d): test_it->orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, test_it->orig_line, test_it->orig_col,
+ test_it->Text(), get_token_name(test_it->type));
+
+ if (chunk_is_token(test_it, CT_ASSIGN))
+ {
+ // the statement is an assigment
+ // && is before assign
+ set_chunk_type(pc, CT_BYREF);
+ break;
+ }
+ }
+ }
+ }
+
+ // Issue #1704
+ if ( chunk_is_token(pc, CT_INCDEC_AFTER)
+ && pc->flags.test(PCF_IN_PREPROC))
+ {
+ Chunk *tmp_2 = pc->GetNext();
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col,
+ pc->Text(), get_token_name(pc->type));
+ log_pcf_flags(LFTYPE, pc->flags);
+
+ if (chunk_is_token(tmp_2, CT_WORD))
+ {
+ set_chunk_type(pc, CT_INCDEC_BEFORE);
+ }
+ }
+} // do_symbol_check
+
+
+static void check_double_brace_init(Chunk *bo1)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LJDBI, "%s(%d): orig_line is %zu, orig_col is %zu", __func__, __LINE__, bo1->orig_line, bo1->orig_col);
+ Chunk *pc = bo1->GetPrevNcNnlNi(); // Issue #2279
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_paren_close(pc))
+ {
+ Chunk *bo2 = bo1->GetNext();
+
+ if (bo2->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_token(bo2, CT_BRACE_OPEN))
+ {
+ // found a potential double brace
+ Chunk *bc2 = chunk_skip_to_match(bo2);
+
+ if (bc2 == nullptr)
+ {
+ return;
+ }
+ Chunk *bc1 = bc2->GetNext();
+
+ if (bc1->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_token(bc1, CT_BRACE_CLOSE))
+ {
+ LOG_FMT(LJDBI, " - end, orig_line is %zu, orig_col is %zu\n", bc2->orig_line, bc2->orig_col);
+ // delete bo2 and bc1
+ bo1->str += bo2->str;
+ bo1->orig_col_end = bo2->orig_col_end;
+ chunk_del(bo2);
+ set_chunk_parent(bo1, CT_DOUBLE_BRACE);
+
+ bc2->str += bc1->str;
+ bc2->orig_col_end = bc1->orig_col_end;
+ chunk_del(bc1);
+ set_chunk_parent(bc2, CT_DOUBLE_BRACE);
+ return;
+ }
+ }
+ }
+ LOG_FMT(LJDBI, " - no\n");
+} // check_double_brace_init
+
+
+void fix_symbols(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc;
+ Chunk dummy;
+
+ cpd.unc_stage = unc_stage_e::FIX_SYMBOLS;
+
+ mark_define_expressions();
+
+ bool is_cpp = language_is_set(LANG_CPP);
+ bool is_java = language_is_set(LANG_JAVA);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc, CT_FUNC_WRAP)
+ || chunk_is_token(pc, CT_TYPE_WRAP))
+ {
+ handle_wrap(pc);
+ }
+
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ mark_lvalue(pc);
+ }
+ // a brace immediately preceded by word in C++11 is an initializer list though it may also
+ // by a type casting initializer list if the word is really a type; sadly uncrustify knows
+ // only built-in types and knows nothing of user-defined types
+ Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( is_cpp
+ && chunk_is_token(pc, CT_BRACE_OPEN)
+ && ( chunk_is_token(prev, CT_WORD)
+ || chunk_is_token(prev, CT_TYPE)))
+ {
+ mark_lvalue(pc);
+ }
+
+ if ( is_java
+ && chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ check_double_brace_init(pc);
+ }
+
+ if (chunk_is_token(pc, CT_ATTRIBUTE))
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( next->IsNotNullChunk()
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_ATTRIBUTE, false);
+ }
+ }
+ }
+
+ pc = Chunk::GetHead();
+
+ if (pc->IsCommentOrNewline())
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_IGNORED))
+ {
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+ LOG_FMT(LFCNR, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ Chunk *prev = pc->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #2279
+
+ if (chunk_is_token(prev, CT_QUALIFIER))
+ {
+ prev = prev->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #3513
+ }
+
+ if (prev->IsNullChunk())
+ {
+ prev = &dummy;
+ }
+ else
+ {
+ // Issue #2279
+ LOG_FMT(LFCNR, "%s(%d): prev(ni)->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text(), get_token_name(prev->type));
+ }
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->IsNullChunk())
+ {
+ next = &dummy;
+ }
+ else
+ {
+ // Issue #2279
+ LOG_FMT(LFCNR, "%s(%d): next->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, next->Text(), get_token_name(next->type));
+ }
+ LOG_FMT(LFCNR, "%s(%d): do_symbol_check(%s, %s, %s)\n",
+ __func__, __LINE__, prev->Text(), pc->Text(), next->Text());
+ do_symbol_check(prev, pc, next);
+ pc = pc->GetNextNcNnl();
+ }
+ pawn_add_virtual_semicolons();
+ process_returns();
+
+ /*
+ * 2nd pass - handle variable definitions
+ * REVISIT: We need function params marked to do this (?)
+ */
+ pc = Chunk::GetHead();
+ int square_level = -1;
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ char copy[1000];
+ LOG_FMT(LFCNR, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s, parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy), get_token_name(pc->type), get_token_name(pc->parent_type));
+
+ // Can't have a variable definition inside [ ]
+ if (square_level < 0)
+ {
+ if (chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ square_level = pc->level;
+ }
+ }
+ else
+ {
+ if (pc->level <= static_cast<size_t>(square_level))
+ {
+ square_level = -1;
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_EXTERN)
+ && language_is_set(LANG_ALLC))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_STRING))
+ {
+ Chunk *tmp = next->GetNextNcNnl();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_TYPE)
+ || chunk_is_token(tmp, CT_BRACE_OPEN)
+ || chunk_is_token(tmp, CT_ATTRIBUTE))
+ {
+ break;
+ }
+
+ if (chunk_is_token(tmp, CT_WORD))
+ {
+ chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);
+ break;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_ATTRIBUTE)
+ && language_is_set(LANG_ALLC))
+ {
+ Chunk *tmp = skip_attribute_next(pc);
+
+ if (chunk_is_token(tmp, CT_WORD))
+ {
+ chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_BRACE_OPEN) // Issue #2332
+ && get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST)
+ {
+ LOG_FMT(LFCNR, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', look for CT_BRACE_OPEN\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ pc = pc->GetNextType(CT_BRACE_CLOSE, pc->level);
+ }
+ /*
+ * A variable definition is possible after at the start of a statement
+ * that starts with: DC_MEMBER, QUALIFIER, TYPE, or WORD
+ */
+ // Issue #2279
+ // Issue #2478
+ LOG_FMT(LFCNR, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s, parent_type is %s\n ",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy), get_token_name(pc->type), get_token_name(pc->parent_type));
+ log_pcf_flags(LFCNR, pc->flags);
+
+ if ( (square_level < 0)
+ && pc->flags.test(PCF_STMT_START)
+ && ( chunk_is_token(pc, CT_QUALIFIER)
+ || chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_TYPENAME)
+ || chunk_is_token(pc, CT_DC_MEMBER) // Issue #2478
+ || chunk_is_token(pc, CT_WORD))
+ && get_chunk_parent_type(pc) != CT_BIT_COLON
+ && get_chunk_parent_type(pc) != CT_ENUM
+ && !pc->flags.test(PCF_IN_CLASS_BASE)
+ && !pc->flags.test(PCF_IN_ENUM))
+ {
+ pc = fix_variable_definition(pc);
+ }
+ else
+ {
+ pc = pc->GetNextNcNnl();
+ }
+ }
+} // fix_symbols
+
+
+static void process_returns(void)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc;
+
+ pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_not_token(pc, CT_RETURN))
+ {
+ pc = pc->GetNextType(CT_RETURN, -1);
+ continue;
+ }
+ pc = process_return(pc);
+ }
+}
+
+
+static Chunk *process_return(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *next;
+ Chunk *temp;
+ Chunk *semi;
+ Chunk *cpar;
+ Chunk chunk;
+
+ // grab next and bail if it is a semicolon
+ next = pc->PpaGetNextNcNnl();
+
+ if ( next->IsNullChunk()
+ || chunk_is_semicolon(next)
+ || chunk_is_token(next, CT_NEWLINE))
+ {
+ return(next);
+ }
+ log_rule_B("nl_return_expr");
+
+ if ( options::nl_return_expr() != IARF_IGNORE
+ && !pc->flags.test(PCF_IN_PREPROC))
+ {
+ newline_iarf(pc, options::nl_return_expr());
+ }
+
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ // See if the return is fully paren'd
+ cpar = next->GetNextType(CT_PAREN_CLOSE, next->level);
+
+ if (cpar->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ semi = cpar->PpaGetNextNcNnl();
+
+ if (semi->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+
+ if ( chunk_is_token(semi, CT_NEWLINE)
+ || chunk_is_semicolon(semi))
+ {
+ log_rule_B("mod_paren_on_return");
+
+ if (options::mod_paren_on_return() == IARF_REMOVE)
+ {
+ LOG_FMT(LRETURN, "%s(%d): removing parens on orig_line %zu\n",
+ __func__, __LINE__, pc->orig_line);
+
+ // lower the level of everything
+ for (temp = next; temp != cpar; temp = temp->GetNext())
+ {
+ if (temp->level == 0)
+ {
+ fprintf(stderr, "%s(%d): temp->level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, temp->orig_line, temp->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ temp->level--;
+ }
+
+ // delete the parenthesis
+ chunk_del(next);
+ chunk_del(cpar);
+
+ // back up following chunks
+ temp = semi;
+
+ while ( temp->IsNotNullChunk()
+ && chunk_is_not_token(temp, CT_NEWLINE))
+ {
+ temp->column = temp->column - 2;
+ temp->orig_col = temp->orig_col - 2;
+ temp->orig_col_end = temp->orig_col_end - 2;
+ temp = temp->GetNext();
+ }
+ }
+ else
+ {
+ LOG_FMT(LRETURN, "%s(%d): keeping parens on orig_line %zu\n",
+ __func__, __LINE__, pc->orig_line);
+
+ // mark & keep them
+ set_chunk_parent(next, CT_RETURN);
+ set_chunk_parent(cpar, CT_RETURN);
+ }
+ return(semi);
+ }
+ }
+ // We don't have a fully paren'd return. Should we add some?
+ log_rule_B("mod_paren_on_return");
+
+ if (!(options::mod_paren_on_return() & IARF_ADD))
+ {
+ return(next);
+ }
+
+ // Issue #1917
+ // Never add parens to a braced init list; that breaks the code
+ // return {args...}; // C++11 type elision; okay
+ // return ({args...}); // ill-formed
+ if ( language_is_set(LANG_CPP)
+ && chunk_is_token(next, CT_BRACE_OPEN)
+ && get_chunk_parent_type(next) == CT_BRACED_INIT_LIST)
+ {
+ LOG_FMT(LRETURN, "%s(%d): not adding parens around braced initializer"
+ " on orig_line %zd\n",
+ __func__, __LINE__, pc->orig_line);
+ return(next);
+ }
+ // find the next semicolon on the same level
+ semi = next;
+
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ while ((semi = semi->GetNext())->IsNotNullChunk())
+ {
+ if (!semi->flags.test(PCF_IN_PREPROC))
+ {
+ break;
+ }
+
+ if (semi->level < pc->level)
+ {
+ return(semi);
+ }
+
+ if ( chunk_is_semicolon(semi)
+ && pc->level == semi->level)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ while ((semi = semi->GetNext())->IsNotNullChunk())
+ {
+ if (semi->level < pc->level)
+ {
+ return(semi);
+ }
+
+ if ( chunk_is_semicolon(semi)
+ && pc->level == semi->level)
+ {
+ break;
+ }
+ }
+ }
+
+ if (semi)
+ {
+ // add the parenthesis
+ set_chunk_type(&chunk, CT_PAREN_OPEN);
+ set_chunk_parent(&chunk, CT_RETURN);
+ chunk.str = "(";
+ chunk.level = pc->level;
+ chunk.pp_level = pc->pp_level;
+ chunk.brace_level = pc->brace_level;
+ chunk.orig_line = pc->orig_line;
+ chunk.orig_col = next->orig_col - 1;
+ chunk.flags = pc->flags & PCF_COPY_FLAGS;
+ chunk_add_before(&chunk, next);
+
+ set_chunk_type(&chunk, CT_PAREN_CLOSE);
+ chunk.str = ")";
+ chunk.orig_line = semi->orig_line;
+ chunk.orig_col = semi->orig_col - 1;
+ cpar = chunk_add_before(&chunk, semi);
+
+ LOG_FMT(LRETURN, "%s(%d): added parens on orig_line %zu\n",
+ __func__, __LINE__, pc->orig_line);
+
+ for (temp = next; temp != cpar; temp = temp->GetNext())
+ {
+ temp->level++;
+ }
+ }
+ return(semi);
+} // process_return
+
+
+static bool is_oc_block(Chunk *pc)
+{
+ return( pc != nullptr
+ && ( get_chunk_parent_type(pc) == CT_OC_BLOCK_TYPE
+ || get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR
+ || get_chunk_parent_type(pc) == CT_OC_BLOCK_ARG
+ || get_chunk_parent_type(pc) == CT_OC_BLOCK
+ || chunk_is_token(pc, CT_OC_BLOCK_CARET)
+ || ( pc->next != nullptr
+ && pc->next->type == CT_OC_BLOCK_CARET)
+ || ( pc->prev != nullptr
+ && pc->prev->type == CT_OC_BLOCK_CARET)));
+}
+
+
+void mark_comments(void)
+{
+ LOG_FUNC_ENTRY();
+
+ cpd.unc_stage = unc_stage_e::MARK_COMMENTS;
+
+ bool prev_nl = true;
+ Chunk *cur = Chunk::GetHead();
+
+ while (cur->IsNotNullChunk())
+ {
+ Chunk *next = cur->GetNextNvb();
+ bool next_nl = next->IsNullChunk() || chunk_is_newline(next);
+
+ if (cur->IsComment())
+ {
+ if ( next_nl
+ && prev_nl)
+ {
+ set_chunk_parent(cur, CT_COMMENT_WHOLE);
+ }
+ else if (next_nl)
+ {
+ set_chunk_parent(cur, CT_COMMENT_END);
+ }
+ else if (prev_nl)
+ {
+ set_chunk_parent(cur, CT_COMMENT_START);
+ }
+ else
+ {
+ set_chunk_parent(cur, CT_COMMENT_EMBED);
+ }
+ }
+ prev_nl = chunk_is_newline(cur);
+ cur = next;
+ }
+}
+
+
+static void handle_cpp_template(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (chunk_is_not_token(tmp, CT_ANGLE_OPEN))
+ {
+ return;
+ }
+ set_chunk_parent(tmp, CT_TEMPLATE);
+
+ size_t level = tmp->level;
+
+ tmp = tmp->GetNext();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_CLASS)
+ || chunk_is_token(tmp, CT_STRUCT))
+ {
+ set_chunk_type(tmp, CT_TYPE);
+ }
+ else if ( chunk_is_token(tmp, CT_ANGLE_CLOSE)
+ && tmp->level == level)
+ {
+ set_chunk_parent(tmp, CT_TEMPLATE);
+ break;
+ }
+ tmp = tmp->GetNext();
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = tmp->GetNextNcNnl();
+
+ if (chunk_is_token(tmp, CT_FRIEND))
+ {
+ // Account for a template friend declaration
+ set_chunk_parent(tmp, CT_TEMPLATE);
+
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if ( chunk_is_token(tmp, CT_CLASS)
+ || chunk_is_token(tmp, CT_STRUCT))
+ {
+ set_chunk_parent(tmp, CT_TEMPLATE);
+
+ // REVISIT: This may be a bit risky - might need to track the { };
+ tmp = tmp->GetNextType(CT_SEMICOLON, tmp->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_parent(tmp, CT_TEMPLATE);
+ }
+ }
+ }
+} // handle_cpp_template
+
+
+static void handle_cpp_lambda(Chunk *sq_o)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *ret = Chunk::NullChunkPtr;
+
+ // abort if type of the previous token is not contained in this whitelist
+ Chunk *prev = sq_o->GetPrevNcNnlNi(); // Issue #2279
+
+ if (prev->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): prev is nullptr\n", __func__, __LINE__);
+ }
+
+ if ( prev->IsNullChunk()
+ || ( chunk_is_not_token(prev, CT_ASSIGN)
+ && chunk_is_not_token(prev, CT_COMMA)
+ && chunk_is_not_token(prev, CT_PAREN_OPEN) // allow Js like self invoking lambda syntax: ([](){})();
+ && chunk_is_not_token(prev, CT_FPAREN_OPEN)
+ && chunk_is_not_token(prev, CT_SQUARE_OPEN)
+ && chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && chunk_is_not_token(prev, CT_SEMICOLON)
+ && chunk_is_not_token(prev, CT_RETURN)))
+ {
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+ Chunk *sq_c = sq_o; // assuming '[]'
+
+ if (chunk_is_token(sq_o, CT_SQUARE_OPEN))
+ {
+ // make sure there is a ']'
+ sq_c = chunk_skip_to_match(sq_o);
+
+ if (sq_c == nullptr)
+ {
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+ }
+ Chunk *pa_o = sq_c->GetNextNcNnl();
+
+ // check to see if there is a lambda-specifier in the pa_o chunk;
+ // assuming chunk is CT_EXECUTION_CONTEXT, ignore lambda-specifier
+ while (chunk_is_token(pa_o, CT_EXECUTION_CONTEXT))
+ {
+ // set pa_o to next chunk after this specifier
+ pa_o = pa_o->GetNextNcNnl();
+ }
+
+ if (pa_o->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+ Chunk *pa_c = Chunk::NullChunkPtr;
+
+ // lambda-declarator '( params )' is optional
+ if (chunk_is_token(pa_o, CT_PAREN_OPEN))
+ {
+ // and now find the ')'
+ pa_c = chunk_skip_to_match(pa_o);
+
+ if (pa_c->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+ }
+ // Check for 'mutable' keyword: '[]() mutable {}' or []() mutable -> ret {}
+ Chunk *br_o = pa_c->IsNotNullChunk() ? pa_c->GetNextNcNnl() : pa_o;
+
+ if (chunk_is_str(br_o, "mutable"))
+ {
+ br_o = br_o->GetNextNcNnl();
+ }
+ //TODO: also check for exception and attribute between [] ... {}
+
+ // skip possible arrow syntax: '-> ret'
+ if (chunk_is_str(br_o, "->"))
+ {
+ ret = br_o;
+ // REVISIT: really should check the stuff we are skipping
+ br_o = br_o->GetNextType(CT_BRACE_OPEN, br_o->level);
+ }
+
+ // skip possible CT_NOEXCEPT
+ if (chunk_is_token(br_o, CT_NOEXCEPT)) // Issue #3321
+ {
+ ret = br_o;
+ // REVISIT: really should check the stuff we are skipping
+ br_o = br_o->GetNextType(CT_BRACE_OPEN, br_o->level);
+ }
+
+ if (br_o->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): br_o is null. Return\n", __func__, __LINE__);
+ return;
+ }
+
+ if (chunk_is_not_token(br_o, CT_BRACE_OPEN))
+ {
+ LOG_FMT(LFCNR, "%s(%d): br_o is '%s'/%s\n",
+ __func__, __LINE__,
+ br_o->Text(), get_token_name(br_o->type));
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+ // and now find the '}'
+ Chunk *br_c = chunk_skip_to_match(br_o);
+
+ if (br_c->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+
+ // This looks like a lambda expression
+ if (chunk_is_token(sq_o, CT_TSQUARE))
+ {
+ // split into two chunks
+ Chunk nc;
+
+ nc = *sq_o;
+ set_chunk_type(sq_o, CT_SQUARE_OPEN);
+ sq_o->str.resize(1);
+ /*
+ * bug # 664
+ *
+ * The original orig_col of CT_SQUARE_CLOSE is stored at orig_col_end
+ * of CT_TSQUARE. CT_SQUARE_CLOSE orig_col and orig_col_end values
+ * are calculate from orig_col_end of CT_TSQUARE.
+ */
+ nc.orig_col = sq_o->orig_col_end - 1;
+ nc.column = static_cast<int>(nc.orig_col);
+ nc.orig_col_end = sq_o->orig_col_end;
+ sq_o->orig_col_end = sq_o->orig_col + 1;
+
+ set_chunk_type(&nc, CT_SQUARE_CLOSE);
+ nc.str.pop_front();
+ sq_c = chunk_add_after(&nc, sq_o);
+ }
+ set_chunk_parent(sq_o, CT_CPP_LAMBDA);
+ set_chunk_parent(sq_c, CT_CPP_LAMBDA);
+
+ if (pa_c->IsNotNullChunk())
+ {
+ set_chunk_type(pa_o, CT_LPAREN_OPEN); // Issue #3054
+ set_chunk_parent(pa_o, CT_CPP_LAMBDA);
+ chunk_set_parent(pa_o, sq_o);
+ chunk_set_parent(br_o, sq_o);
+ set_chunk_type(pa_c, CT_LPAREN_CLOSE);
+ set_chunk_parent(pa_c, CT_CPP_LAMBDA);
+ chunk_set_parent(pa_c, sq_o);
+ chunk_set_parent(br_c, sq_o);
+ }
+ set_chunk_parent(br_o, CT_CPP_LAMBDA);
+ set_chunk_parent(br_c, CT_CPP_LAMBDA);
+
+ if (ret->IsNotNullChunk())
+ {
+ set_chunk_type(ret, CT_CPP_LAMBDA_RET);
+ ret = ret->GetNextNcNnl();
+
+ while (ret != br_o)
+ {
+ make_type(ret);
+ ret = ret->GetNextNcNnl();
+ }
+ }
+
+ if (pa_c->IsNotNullChunk())
+ {
+ fix_fcn_def_params(pa_o);
+ }
+ //handle self calling lambda paren
+ Chunk *call_pa_o = br_c->GetNextNcNnl();
+
+ if (chunk_is_token(call_pa_o, CT_PAREN_OPEN))
+ {
+ Chunk *call_pa_c = chunk_skip_to_match(call_pa_o);
+
+ if (call_pa_c->IsNotNullChunk())
+ {
+ set_chunk_type(call_pa_o, CT_FPAREN_OPEN);
+ set_chunk_parent(call_pa_o, CT_FUNC_CALL);
+ set_chunk_type(call_pa_c, CT_FPAREN_CLOSE);
+ set_chunk_parent(call_pa_c, CT_FUNC_CALL);
+ }
+ }
+ mark_cpp_lambda(sq_o);
+} // handle_cpp_lambda
+
+
+static void handle_d_template(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *name = pc->GetNextNcNnl();
+ Chunk *po = name->GetNextNcNnl();
+
+ //if (!name || (name->type != CT_WORD && name->type != CT_WORD)) Coverity CID 76000 Same on both sides, 2016-03-16
+ if ( name->IsNullChunk()
+ || chunk_is_not_token(name, CT_WORD))
+ {
+ // TODO: log an error, expected NAME
+ return;
+ }
+
+ if ( po->IsNullChunk()
+ || chunk_is_not_token(po, CT_PAREN_OPEN))
+ {
+ // TODO: log an error, expected '('
+ return;
+ }
+ set_chunk_type(name, CT_TYPE);
+ set_chunk_parent(name, CT_TEMPLATE);
+ set_chunk_parent(po, CT_TEMPLATE);
+
+ ChunkStack cs;
+ Chunk *tmp = get_d_template_types(cs, po);
+
+ if ( tmp == nullptr
+ || chunk_is_not_token(tmp, CT_PAREN_CLOSE))
+ {
+ // TODO: log an error, expected ')'
+ return;
+ }
+ set_chunk_parent(tmp, CT_TEMPLATE);
+
+ tmp = tmp->GetNextNcNnl();
+
+ if (chunk_is_not_token(tmp, CT_BRACE_OPEN))
+ {
+ // TODO: log an error, expected '{'
+ return;
+ }
+ set_chunk_parent(tmp, CT_TEMPLATE);
+ po = tmp;
+ tmp = tmp->GetNextNcNnl();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->level > po->level)
+ {
+ if ( chunk_is_token(tmp, CT_WORD)
+ && chunkstack_match(cs, tmp))
+ {
+ set_chunk_type(tmp, CT_TYPE);
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+// if (!chunk_is_token(tmp, CT_BRACE_CLOSE))
+// {
+// // TODO: log an error, expected '}'
+// }
+ set_chunk_parent(tmp, CT_TEMPLATE);
+} // handle_d_template
+
+
+Chunk *skip_template_next(Chunk *ang_open)
+{
+ if (ang_open == nullptr)
+ {
+ return(Chunk::NullChunkPtr);
+ }
+
+ if (chunk_is_token(ang_open, CT_ANGLE_OPEN))
+ {
+ Chunk *pc = ang_open->GetNextType(CT_ANGLE_CLOSE, ang_open->level);
+
+ if (pc->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ return(pc->GetNextNcNnl());
+ }
+ return(ang_open);
+}
+
+
+static void handle_oc_class(Chunk *pc)
+{
+ enum class angle_state_e : unsigned int
+ {
+ NONE = 0,
+ OPEN = 1, // '<' found
+ CLOSE = 2, // '>' found
+ };
+
+ LOG_FUNC_ENTRY();
+ Chunk *tmp;
+ bool hit_scope = false;
+ bool passed_name = false; // Did we pass the name of the class and now there can be only protocols, not generics
+ int generic_level = 0; // level of depth of generic
+ angle_state_e as = angle_state_e::NONE;
+
+ LOG_FMT(LOCCLASS, "%s(%d): start [%s] [%s] line %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(get_chunk_parent_type(pc)), pc->orig_line);
+
+ if (get_chunk_parent_type(pc) == CT_OC_PROTOCOL)
+ {
+ tmp = pc->GetNextNcNnl();
+
+ if (chunk_is_semicolon(tmp))
+ {
+ set_chunk_parent(tmp, get_chunk_parent_type(pc));
+ LOG_FMT(LOCCLASS, "%s(%d): bail on semicolon\n", __func__, __LINE__);
+ return;
+ }
+ }
+ tmp = pc;
+
+ while ( (tmp = tmp->GetNextNnl()) != nullptr
+ && tmp->IsNotNullChunk())
+ {
+ LOG_FMT(LOCCLASS, "%s(%d): orig_line is %zu, [%s]\n",
+ __func__, __LINE__, tmp->orig_line, tmp->Text());
+
+ if (chunk_is_token(tmp, CT_OC_END))
+ {
+ break;
+ }
+
+ if (chunk_is_token(tmp, CT_PAREN_OPEN))
+ {
+ passed_name = true;
+ }
+
+ if (chunk_is_str(tmp, "<"))
+ {
+ set_chunk_type(tmp, CT_ANGLE_OPEN);
+
+ if (passed_name)
+ {
+ set_chunk_parent(tmp, CT_OC_PROTO_LIST);
+ }
+ else
+ {
+ set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
+ generic_level++;
+ }
+ as = angle_state_e::OPEN;
+ }
+
+ if (chunk_is_str(tmp, ">"))
+ {
+ set_chunk_type(tmp, CT_ANGLE_CLOSE);
+
+ if (passed_name)
+ {
+ set_chunk_parent(tmp, CT_OC_PROTO_LIST);
+ as = angle_state_e::CLOSE;
+ }
+ else
+ {
+ set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
+
+ if (generic_level == 0)
+ {
+ fprintf(stderr, "%s(%d): generic_level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ generic_level--;
+
+ if (generic_level == 0)
+ {
+ as = angle_state_e::CLOSE;
+ }
+ }
+ }
+
+ if (chunk_is_str(tmp, ">>"))
+ {
+ set_chunk_type(tmp, CT_ANGLE_CLOSE);
+ set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
+ split_off_angle_close(tmp);
+ generic_level -= 1;
+
+ if (generic_level == 0)
+ {
+ as = angle_state_e::CLOSE;
+ }
+ }
+
+ if ( chunk_is_token(tmp, CT_BRACE_OPEN)
+ && get_chunk_parent_type(tmp) != CT_ASSIGN)
+ {
+ as = angle_state_e::CLOSE;
+ set_chunk_parent(tmp, CT_OC_CLASS);
+ tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->level);
+
+ if ( tmp->IsNotNullChunk()
+ && get_chunk_parent_type(tmp) != CT_ASSIGN)
+ {
+ set_chunk_parent(tmp, CT_OC_CLASS);
+ }
+ }
+ else if (chunk_is_token(tmp, CT_COLON))
+ {
+ if (as != angle_state_e::OPEN)
+ {
+ passed_name = true;
+ }
+ set_chunk_type(tmp, hit_scope ? CT_OC_COLON : CT_CLASS_COLON);
+
+ if (chunk_is_token(tmp, CT_CLASS_COLON))
+ {
+ set_chunk_parent(tmp, CT_OC_CLASS);
+ }
+ }
+ else if ( chunk_is_str(tmp, "-")
+ || chunk_is_str(tmp, "+"))
+ {
+ as = angle_state_e::CLOSE;
+
+ if (chunk_is_newline(tmp->GetPrev()))
+ {
+ set_chunk_type(tmp, CT_OC_SCOPE);
+ chunk_flags_set(tmp, PCF_STMT_START);
+ hit_scope = true;
+ }
+ }
+
+ if (as == angle_state_e::OPEN)
+ {
+ if (passed_name)
+ {
+ set_chunk_parent(tmp, CT_OC_PROTO_LIST);
+ }
+ else
+ {
+ set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
+ }
+ }
+ }
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_parent(tmp, CT_OC_CLASS);
+ }
+ }
+} // handle_oc_class
+
+
+static void handle_oc_block_literal(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return; // let's be paranoid
+ }
+ Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( prev->IsNullChunk()
+ || next->IsNullChunk())
+ {
+ return; // let's be paranoid
+ }
+ /*
+ * block literal: '^ RTYPE ( ARGS ) { }'
+ * RTYPE and ARGS are optional
+ */
+ LOG_FMT(LOCBLK, "%s(%d): block literal @ orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+
+ Chunk *apo = Chunk::NullChunkPtr; // arg paren open
+ Chunk *bbo = Chunk::NullChunkPtr; // block brace open
+ Chunk *bbc; // block brace close
+
+ LOG_FMT(LOCBLK, "%s(%d): + scan", __func__, __LINE__);
+ Chunk *tmp;
+
+ for (tmp = next; tmp->IsNotNullChunk(); tmp = tmp->GetNextNcNnl())
+ {
+ /* handle '< protocol >' */
+ if (chunk_is_str(tmp, "<"))
+ {
+ Chunk *ao = tmp;
+ Chunk *ac = ao->GetNextString(">", 1, ao->level);
+
+ if (ac->IsNotNullChunk())
+ {
+ set_chunk_type(ao, CT_ANGLE_OPEN);
+ set_chunk_parent(ao, CT_OC_PROTO_LIST);
+ set_chunk_type(ac, CT_ANGLE_CLOSE);
+ set_chunk_parent(ac, CT_OC_PROTO_LIST);
+
+ for (tmp = ao->GetNext(); tmp != ac; tmp = tmp->GetNext())
+ {
+ tmp->level += 1;
+ set_chunk_parent(tmp, CT_OC_PROTO_LIST);
+ }
+
+ tmp = ac->GetNextNcNnl();
+ }
+ else
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+ }
+ LOG_FMT(LOCBLK, " '%s'", tmp->Text());
+
+ if ( tmp->level < pc->level
+ || chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ LOG_FMT(LOCBLK, "[DONE]");
+ break;
+ }
+
+ if (tmp->level == pc->level)
+ {
+ if (chunk_is_paren_open(tmp))
+ {
+ apo = tmp;
+ LOG_FMT(LOCBLK, "[PAREN]");
+ }
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ LOG_FMT(LOCBLK, "[BRACE]");
+ bbo = tmp;
+ break;
+ }
+ }
+ }
+
+ // make sure we have braces
+ bbc = chunk_skip_to_match(bbo);
+
+ if ( bbo->IsNullChunk()
+ || bbc == nullptr
+ || bbc->IsNullChunk())
+ {
+ LOG_FMT(LOCBLK, " -- no braces found\n");
+ return;
+ }
+ LOG_FMT(LOCBLK, "\n");
+
+ // we are on a block literal for sure
+ set_chunk_type(pc, CT_OC_BLOCK_CARET);
+ set_chunk_parent(pc, CT_OC_BLOCK_EXPR);
+
+ // handle the optional args
+ Chunk *lbp; // last before paren - end of return type, if any
+
+ if (apo->IsNotNullChunk())
+ {
+ Chunk *apc = chunk_skip_to_match(apo); // arg parenthesis close
+
+ if (chunk_is_paren_close(apc))
+ {
+ LOG_FMT(LOCBLK, " -- marking parens @ apo->orig_line is %zu, apo->orig_col is %zu and apc->orig_line is %zu, apc->orig_col is %zu\n",
+ apo->orig_line, apo->orig_col, apc->orig_line, apc->orig_col);
+ flag_parens(apo, PCF_OC_ATYPE, CT_FPAREN_OPEN, CT_OC_BLOCK_EXPR, true);
+ fix_fcn_def_params(apo);
+ }
+ lbp = apo->GetPrevNcNnlNi(); // Issue #2279
+ }
+ else
+ {
+ lbp = bbo->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ // mark the return type, if any
+ while (lbp != pc)
+ {
+ LOG_FMT(LOCBLK, " -- lbp %s[%s]\n", lbp->Text(), get_token_name(lbp->type));
+ make_type(lbp);
+ chunk_flags_set(lbp, PCF_OC_RTYPE);
+ set_chunk_parent(lbp, CT_OC_BLOCK_EXPR);
+ lbp = lbp->GetPrevNcNnlNi(); // Issue #2279
+ }
+ // mark the braces
+ set_chunk_parent(bbo, CT_OC_BLOCK_EXPR);
+ set_chunk_parent(bbc, CT_OC_BLOCK_EXPR);
+} // handle_oc_block_literal
+
+
+static void handle_oc_block_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return;
+ }
+
+ if (pc->flags.test(PCF_IN_TYPEDEF))
+ {
+ LOG_FMT(LOCBLK, "%s(%d): skip block type @ orig_line is %zu, orig_col is %zu, -- in typedef\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ return;
+ }
+ // make sure we have '( ^'
+ Chunk *tpo = pc->GetPrevNcNnlNi(); // type paren open Issue #2279
+
+ if (chunk_is_paren_open(tpo))
+ {
+ /*
+ * block type: 'RTYPE (^LABEL)(ARGS)'
+ * LABEL is optional.
+ */
+ Chunk *tpc = chunk_skip_to_match(tpo); // type close paren (after '^')
+ Chunk *nam = tpc->GetPrevNcNnlNi(); // name (if any) or '^' Issue #2279
+ Chunk *apo = tpc->GetNextNcNnl(); // arg open paren
+ Chunk *apc = chunk_skip_to_match(apo); // arg close paren
+
+ /*
+ * If this is a block literal instead of a block type, 'nam'
+ * will actually be the closing bracket of the block. We run into
+ * this situation if a block literal is enclosed in parentheses.
+ */
+ if (chunk_is_closing_brace(nam))
+ {
+ return(handle_oc_block_literal(pc));
+ }
+
+ // Check apo is '(' or else this might be a block literal. Issue 2643.
+ if (!chunk_is_paren_open(apo))
+ {
+ return(handle_oc_block_literal(pc));
+ }
+
+ if (chunk_is_paren_close(apc))
+ {
+ Chunk *aft = apc->GetNextNcNnl();
+ E_Token pt;
+
+ if (chunk_is_str(nam, "^"))
+ {
+ set_chunk_type(nam, CT_PTR_TYPE);
+ pt = CT_FUNC_TYPE;
+ }
+ else if ( chunk_is_token(aft, CT_ASSIGN)
+ || chunk_is_token(aft, CT_SEMICOLON))
+ {
+ set_chunk_type(nam, CT_FUNC_VAR);
+ pt = CT_FUNC_VAR;
+ }
+ else
+ {
+ set_chunk_type(nam, CT_FUNC_TYPE);
+ pt = CT_FUNC_TYPE;
+ }
+ LOG_FMT(LOCBLK, "%s(%d): block type @ orig_line is %zu, orig_col is %zu, Text() '%s'[%s]\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, nam->Text(), get_token_name(nam->type));
+ set_chunk_type(pc, CT_PTR_TYPE);
+ set_chunk_parent(pc, pt); //CT_OC_BLOCK_TYPE;
+ set_chunk_type(tpo, CT_TPAREN_OPEN);
+ set_chunk_parent(tpo, pt); //CT_OC_BLOCK_TYPE;
+ set_chunk_type(tpc, CT_TPAREN_CLOSE);
+ set_chunk_parent(tpc, pt); //CT_OC_BLOCK_TYPE;
+ set_chunk_type(apo, CT_FPAREN_OPEN);
+ set_chunk_parent(apo, CT_FUNC_PROTO);
+ set_chunk_type(apc, CT_FPAREN_CLOSE);
+ set_chunk_parent(apc, CT_FUNC_PROTO);
+ fix_fcn_def_params(apo);
+ mark_function_return_type(nam, tpo->GetPrevNcNnlNi(), pt); // Issue #2279
+ }
+ }
+} // handle_oc_block_type
+
+
+static Chunk *handle_oc_md_type(Chunk *paren_open, E_Token ptype, pcf_flags_t flags, bool &did_it)
+{
+ Chunk *paren_close;
+
+ if ( !chunk_is_paren_open(paren_open)
+ || ((paren_close = chunk_skip_to_match(paren_open)) == nullptr))
+ {
+ did_it = false;
+ return(paren_open);
+ }
+ did_it = true;
+
+ set_chunk_parent(paren_open, ptype);
+ chunk_flags_set(paren_open, flags);
+ set_chunk_parent(paren_close, ptype);
+ chunk_flags_set(paren_close, flags);
+
+ for (Chunk *cur = paren_open->GetNextNcNnl();
+ cur != paren_close;
+ cur = cur->GetNextNcNnl())
+ {
+ LOG_FMT(LOCMSGD, " <%s|%s>", cur->Text(), get_token_name(cur->type));
+ chunk_flags_set(cur, flags);
+ make_type(cur);
+ }
+
+ // returning the chunk after the paren close
+ return(paren_close->GetNextNcNnl());
+}
+
+
+static void handle_oc_message_decl(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ bool did_it;
+ //bool in_paren = false;
+ //int paren_cnt = 0;
+ //int arg_cnt = 0;
+
+ // Figure out if this is a spec or decl
+ Chunk *tmp = pc;
+
+ if (tmp == nullptr)
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if (tmp->level < pc->level)
+ {
+ // should not happen
+ return;
+ }
+
+ if ( chunk_is_token(tmp, CT_SEMICOLON)
+ || chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ break;
+ }
+ }
+
+ if (tmp == nullptr)
+ {
+ return;
+ }
+ E_Token pt = chunk_is_token(tmp, CT_SEMICOLON) ? CT_OC_MSG_SPEC : CT_OC_MSG_DECL;
+
+ set_chunk_type(pc, CT_OC_SCOPE);
+ set_chunk_parent(pc, pt);
+
+ LOG_FMT(LOCMSGD, "%s(%d): %s @ orig_line is %zu, orig_col is %zu -",
+ __func__, __LINE__, get_token_name(pt), pc->orig_line, pc->orig_col);
+
+ // format: -(TYPE) NAME [: (TYPE)NAME
+
+ // handle the return type
+ tmp = handle_oc_md_type(pc->GetNextNcNnl(), pt, PCF_OC_RTYPE, did_it);
+
+ if (!did_it)
+ {
+ LOG_FMT(LOCMSGD, " -- missing type parens\n");
+ return;
+ }
+
+ // expect the method name/label
+ if (chunk_is_not_token(tmp, CT_WORD))
+ {
+ LOG_FMT(LOCMSGD, " -- missing method name\n");
+ return;
+ } // expect the method name/label
+
+ Chunk *label = tmp;
+
+ set_chunk_type(tmp, pt);
+ set_chunk_parent(tmp, pt);
+ pc = tmp->GetNextNcNnl();
+
+ LOG_FMT(LOCMSGD, " [%s]%s", pc->Text(), get_token_name(pc->type));
+
+ // if we have a colon next, we have args
+ if ( chunk_is_token(pc, CT_COLON)
+ || chunk_is_token(pc, CT_OC_COLON))
+ {
+ pc = label;
+
+ while (true)
+ {
+ // skip optional label
+ if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, pt))
+ {
+ set_chunk_parent(pc, pt);
+ pc = pc->GetNextNcNnl();
+ }
+
+ // a colon must be next
+ if (!chunk_is_str(pc, ":"))
+ {
+ break;
+ }
+ set_chunk_type(pc, CT_OC_COLON);
+ set_chunk_parent(pc, pt);
+ pc = pc->GetNextNcNnl();
+
+ // next is the type in parens
+ LOG_FMT(LOCMSGD, " (%s)", pc->Text());
+ tmp = handle_oc_md_type(pc, pt, PCF_OC_ATYPE, did_it);
+
+ if (!did_it)
+ {
+ LOG_FMT(LWARN, "%s(%d): orig_line is %zu, orig_col is %zu expected type\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ break;
+ }
+ // attributes for a method parameter sit between the parameter type and the parameter name
+ pc = skip_attribute_next(tmp);
+ // we should now be on the arg name
+ chunk_flags_set(pc, PCF_VAR_DEF);
+ LOG_FMT(LOCMSGD, " arg[%s]", pc->Text());
+ pc = pc->GetNextNcNnl();
+ }
+ }
+ LOG_FMT(LOCMSGD, " end[%s]", pc->Text());
+
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ set_chunk_parent(pc, pt);
+ pc = chunk_skip_to_match(pc);
+
+ if (pc != nullptr)
+ {
+ set_chunk_parent(pc, pt);
+ }
+ }
+ else if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ set_chunk_parent(pc, pt);
+ }
+ LOG_FMT(LOCMSGD, "\n");
+} // handle_oc_message_decl
+
+
+static void handle_oc_message_send(Chunk *os)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *cs = Chunk::NullChunkPtr;
+
+ if (os != nullptr)
+ {
+ cs = os->GetNext();
+ }
+
+ while ( cs->IsNotNullChunk()
+ && cs->level > os->level)
+ {
+ cs = cs->GetNext();
+ }
+
+ if ( cs->IsNullChunk()
+ || chunk_is_not_token(cs, CT_SQUARE_CLOSE))
+ {
+ return;
+ }
+ LOG_FMT(LOCMSG, "%s(%d): orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, os->orig_line, os->orig_col);
+
+ Chunk *tmp = cs->GetNextNcNnl();
+
+ if (chunk_is_semicolon(tmp))
+ {
+ set_chunk_parent(tmp, CT_OC_MSG);
+ }
+ // expect a word first thing or [...]
+ tmp = Chunk::NullChunkPtr;
+
+ if (os != nullptr)
+ {
+ tmp = os->GetNextNcNnl();
+ }
+
+ if ( chunk_is_token(tmp, CT_SQUARE_OPEN)
+ || chunk_is_token(tmp, CT_PAREN_OPEN)
+ || chunk_is_token(tmp, CT_OC_AT))
+ {
+ Chunk *tt = tmp->GetNextNcNnl();
+
+ if ( chunk_is_token(tmp, CT_OC_AT)
+ && tt->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tt, CT_PAREN_OPEN)
+ || chunk_is_token(tt, CT_BRACE_OPEN)
+ || chunk_is_token(tt, CT_SQUARE_OPEN))
+ {
+ tmp = tt;
+ }
+ else
+ {
+ LOG_FMT(LOCMSG, "%s(%d): tmp->orig_line is %zu, tmp->orig_col is %zu, expected identifier, not '%s' [%s]\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col,
+ tmp->Text(), get_token_name(tmp->type));
+ return;
+ }
+ }
+ tmp = chunk_skip_to_match(tmp);
+ }
+ else if ( chunk_is_not_token(tmp, CT_WORD)
+ && chunk_is_not_token(tmp, CT_TYPE)
+ && chunk_is_not_token(tmp, CT_THIS)
+ && chunk_is_not_token(tmp, CT_STAR)
+ && chunk_is_not_token(tmp, CT_STRING))
+ {
+ LOG_FMT(LOCMSG, "%s(%d): orig_line is %zu, orig_col is %zu, expected identifier, not '%s' [%s]\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col,
+ tmp->Text(), get_token_name(tmp->type));
+ return;
+ }
+ else
+ {
+ if (tmp->IsStar()) // Issue #2722
+ {
+ set_chunk_type(tmp, CT_PTR_TYPE);
+ tmp = tmp->GetNextNcNnl();
+ }
+ Chunk *tt = tmp->GetNextNcNnl();
+
+ if (chunk_is_paren_open(tt))
+ {
+ LOG_FMT(LFCN, "%s(%d): (18) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+ set_chunk_type(tmp, CT_FUNC_CALL);
+ tmp = set_paren_parent(tt, CT_FUNC_CALL)->GetPrevNcNnlNi(); // Issue #2279
+ }
+ else
+ {
+ set_chunk_type(tmp, CT_OC_MSG_CLASS);
+ }
+ }
+ set_chunk_parent(os, CT_OC_MSG);
+ chunk_flags_set(os, PCF_IN_OC_MSG);
+ set_chunk_parent(cs, CT_OC_MSG);
+ chunk_flags_set(cs, PCF_IN_OC_MSG);
+
+ // handle '< protocol >'
+ tmp = tmp->GetNextNcNnl();
+
+ if (chunk_is_str(tmp, "<"))
+ {
+ Chunk *ao = tmp;
+ Chunk *ac = ao->GetNextString(">", 1, ao->level);
+
+ if (ac->IsNotNullChunk())
+ {
+ set_chunk_type(ao, CT_ANGLE_OPEN);
+ set_chunk_parent(ao, CT_OC_PROTO_LIST);
+ set_chunk_type(ac, CT_ANGLE_CLOSE);
+ set_chunk_parent(ac, CT_OC_PROTO_LIST);
+
+ for (tmp = ao->GetNext(); tmp != ac; tmp = tmp->GetNext())
+ {
+ tmp->level += 1;
+ set_chunk_parent(tmp, CT_OC_PROTO_LIST);
+ }
+
+ tmp = ac->GetNextNcNnl();
+ }
+ else
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+ }
+ // handle 'object.property' and 'collection[index]'
+ else
+ {
+ while (tmp->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_MEMBER)) // move past [object.prop1.prop2
+ {
+ Chunk *typ = tmp->GetNextNcNnl();
+
+ if ( chunk_is_token(typ, CT_WORD)
+ || chunk_is_token(typ, CT_TYPE))
+ {
+ tmp = typ->GetNextNcNnl();
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if (chunk_is_token(tmp, CT_SQUARE_OPEN)) // move past [collection[index]
+ {
+ Chunk *tcs = tmp->GetNextNcNnl();
+
+ while ( tcs->IsNotNullChunk()
+ && tcs->level > tmp->level)
+ {
+ tcs = tcs->GetNextNcNnl();
+ }
+
+ if (chunk_is_token(tcs, CT_SQUARE_CLOSE))
+ {
+ tmp = tcs->GetNextNcNnl();
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ // [(self.foo.bar) method]
+ if (chunk_is_paren_open(tmp))
+ {
+ tmp = chunk_skip_to_match(tmp)->GetNextNcNnl();
+ }
+
+ if ( chunk_is_token(tmp, CT_WORD)
+ || chunk_is_token(tmp, CT_TYPE))
+ {
+ set_chunk_type(tmp, CT_OC_MSG_FUNC);
+ }
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ for (tmp = os->GetNext(); tmp != cs; tmp = tmp->GetNext())
+ {
+ chunk_flags_set(tmp, PCF_IN_OC_MSG);
+
+ if (tmp->level == cs->level + 1)
+ {
+ if (chunk_is_token(tmp, CT_COLON))
+ {
+ set_chunk_type(tmp, CT_OC_COLON);
+
+ if ( chunk_is_token(prev, CT_WORD)
+ || chunk_is_token(prev, CT_TYPE))
+ {
+ // Might be a named param, check previous block
+ Chunk *pp = prev->GetPrev();
+
+ if ( pp->IsNotNullChunk()
+ && chunk_is_not_token(pp, CT_OC_COLON)
+ && chunk_is_not_token(pp, CT_ARITH)
+ && chunk_is_not_token(pp, CT_SHIFT)
+ && chunk_is_not_token(pp, CT_CARET))
+ {
+ set_chunk_type(prev, CT_OC_MSG_NAME);
+ set_chunk_parent(tmp, CT_OC_MSG_NAME);
+ }
+ }
+ }
+ }
+ prev = tmp;
+ }
+} // handle_oc_message_send
+
+
+static void handle_oc_available(Chunk *os)
+{
+ if (os != nullptr)
+ {
+ os = os->GetNext();
+ }
+ else
+ {
+ os = Chunk::NullChunkPtr;
+ }
+
+ while (os->IsNotNullChunk())
+ {
+ E_Token origType = os->type;
+ set_chunk_type(os, CT_OC_AVAILABLE_VALUE);
+
+ if (origType == CT_PAREN_CLOSE)
+ {
+ break;
+ }
+ os = os->GetNext();
+ }
+}
+
+
+static void handle_oc_property_decl(Chunk *os)
+{
+ log_rule_B("mod_sort_oc_properties");
+
+ if (options::mod_sort_oc_properties())
+ {
+ typedef std::vector<Chunk *> ChunkGroup;
+
+ Chunk *next = Chunk::NullChunkPtr;
+
+ if (os != nullptr)
+ {
+ next = os->GetNext();
+ }
+ Chunk *open_paren = nullptr;
+
+ std::vector<ChunkGroup> class_chunks; // class
+ std::vector<ChunkGroup> thread_chunks; // atomic, nonatomic
+ std::vector<ChunkGroup> readwrite_chunks; // readwrite, readonly
+ std::vector<ChunkGroup> ref_chunks; // retain, copy, assign, weak, strong, unsafe_unretained
+ std::vector<ChunkGroup> getter_chunks; // getter
+ std::vector<ChunkGroup> setter_chunks; // setter
+ std::vector<ChunkGroup> nullability_chunks; // nonnull, nullable, null_unspecified, null_resettable
+ std::vector<ChunkGroup> other_chunks; // any words other than above
+
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ open_paren = next;
+ next = next->GetNext();
+
+ /*
+ * Determine location of the property attributes
+ * NOTE: Did not do this in the combine.cpp do_symbol_check as
+ * I was not sure what the ramifications of adding a new type
+ * for each of the below types would be. It did break some items
+ * when I attempted to add them so this is my hack for now.
+ */
+ while ( next->IsNotNullChunk()
+ && chunk_is_not_token(next, CT_PAREN_CLOSE))
+ {
+ if (chunk_is_token(next, CT_OC_PROPERTY_ATTR))
+ {
+ if ( chunk_is_str(next, "atomic")
+ || chunk_is_str(next, "nonatomic"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ thread_chunks.push_back(chunkGroup);
+ }
+ else if ( chunk_is_str(next, "readonly")
+ || chunk_is_str(next, "readwrite"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ readwrite_chunks.push_back(chunkGroup);
+ }
+ else if ( chunk_is_str(next, "assign")
+ || chunk_is_str(next, "retain")
+ || chunk_is_str(next, "copy")
+ || chunk_is_str(next, "strong")
+ || chunk_is_str(next, "weak")
+ || chunk_is_str(next, "unsafe_unretained"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ ref_chunks.push_back(chunkGroup);
+ }
+ else if (chunk_is_str(next, "getter"))
+ {
+ ChunkGroup chunkGroup;
+
+ do
+ {
+ chunkGroup.push_back(next);
+ next = next->GetNext();
+ } while ( next->IsNotNullChunk()
+ && chunk_is_not_token(next, CT_COMMA)
+ && chunk_is_not_token(next, CT_PAREN_CLOSE));
+
+ next = next->GetPrev();
+
+ // coverity CID 160946
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ getter_chunks.push_back(chunkGroup);
+ }
+ else if (chunk_is_str(next, "setter"))
+ {
+ ChunkGroup chunkGroup;
+
+ do
+ {
+ chunkGroup.push_back(next);
+ next = next->GetNext();
+ } while ( next->IsNotNullChunk()
+ && chunk_is_not_token(next, CT_COMMA)
+ && chunk_is_not_token(next, CT_PAREN_CLOSE));
+
+ if (next->IsNotNullChunk())
+ {
+ next = next->GetPrev();
+ }
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ setter_chunks.push_back(chunkGroup);
+ }
+ else if ( chunk_is_str(next, "nullable")
+ || chunk_is_str(next, "nonnull")
+ || chunk_is_str(next, "null_resettable")
+ || chunk_is_str(next, "null_unspecified"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ nullability_chunks.push_back(chunkGroup);
+ }
+ else if (chunk_is_str(next, "class"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ class_chunks.push_back(chunkGroup);
+ }
+ else
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ other_chunks.push_back(chunkGroup);
+ }
+ }
+ else if (chunk_is_word(next))
+ {
+ if (chunk_is_str(next, "class"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ class_chunks.push_back(chunkGroup);
+ }
+ else
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ other_chunks.push_back(chunkGroup);
+ }
+ }
+ next = next->GetNext();
+ }
+ log_rule_B("mod_sort_oc_property_class_weight");
+ int class_w = options::mod_sort_oc_property_class_weight();
+ log_rule_B("mod_sort_oc_property_thread_safe_weight");
+ int thread_w = options::mod_sort_oc_property_thread_safe_weight();
+ log_rule_B("mod_sort_oc_property_readwrite_weight");
+ int readwrite_w = options::mod_sort_oc_property_readwrite_weight();
+ log_rule_B("mod_sort_oc_property_reference_weight");
+ int ref_w = options::mod_sort_oc_property_reference_weight();
+ log_rule_B("mod_sort_oc_property_getter_weight");
+ int getter_w = options::mod_sort_oc_property_getter_weight();
+ log_rule_B("mod_sort_oc_property_setter_weight");
+ int setter_w = options::mod_sort_oc_property_setter_weight();
+ log_rule_B("mod_sort_oc_property_nullability_weight");
+ int nullability_w = options::mod_sort_oc_property_nullability_weight();
+
+ //
+ std::multimap<int, std::vector<ChunkGroup> > sorted_chunk_map;
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(class_w, class_chunks));
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(thread_w, thread_chunks));
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(readwrite_w, readwrite_chunks));
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(ref_w, ref_chunks));
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(getter_w, getter_chunks));
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(setter_w, setter_chunks));
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(nullability_w, nullability_chunks));
+ sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(std::numeric_limits<int>::min(), other_chunks));
+
+ Chunk *curr_chunk = open_paren;
+
+ for (multimap<int, std::vector<ChunkGroup> >::reverse_iterator it = sorted_chunk_map.rbegin(); it != sorted_chunk_map.rend(); ++it)
+ {
+ std::vector<ChunkGroup> chunk_groups = (*it).second;
+
+ for (auto chunk_group : chunk_groups)
+ {
+ for (auto chunk : chunk_group)
+ {
+ chunk->orig_prev_sp = 0;
+
+ if (chunk != curr_chunk)
+ {
+ chunk_move_after(chunk, curr_chunk);
+ curr_chunk = chunk;
+ }
+ else
+ {
+ curr_chunk = curr_chunk->GetNext();
+ }
+ }
+
+ // add the parenthesis
+ Chunk endchunk;
+ set_chunk_type(&endchunk, CT_COMMA);
+ set_chunk_parent(&endchunk, get_chunk_parent_type(curr_chunk));
+ endchunk.str = ",";
+ endchunk.level = curr_chunk->level;
+ endchunk.pp_level = curr_chunk->pp_level;
+ endchunk.brace_level = curr_chunk->brace_level;
+ endchunk.orig_line = curr_chunk->orig_line;
+ endchunk.orig_col = curr_chunk->orig_col;
+ endchunk.column = curr_chunk->orig_col_end + 1;
+ endchunk.flags = curr_chunk->flags & PCF_COPY_FLAGS;
+ chunk_add_after(&endchunk, curr_chunk);
+ curr_chunk = curr_chunk->GetNext();
+ }
+ }
+
+ // Remove the extra comma's that we did not move
+ while ( curr_chunk != nullptr
+ && curr_chunk->IsNotNullChunk()
+ && chunk_is_not_token(curr_chunk, CT_PAREN_CLOSE))
+ {
+ Chunk *rm_chunk = curr_chunk;
+ curr_chunk = curr_chunk->GetNext();
+ chunk_del(rm_chunk);
+ }
+ }
+ }
+ Chunk *tmp = Chunk::NullChunkPtr;
+
+ if (os != nullptr)
+ {
+ tmp = os->GetNextNcNnl();
+ }
+
+ if (chunk_is_paren_open(tmp))
+ {
+ tmp = chunk_skip_to_match(tmp)->GetNextNcNnl();
+ }
+ fix_variable_definition(tmp);
+} // handle_oc_property_decl
+
+
+static void handle_cs_square_stmt(Chunk *os)
+{
+ LOG_FUNC_ENTRY();
+
+ if (os == nullptr)
+ {
+ os = Chunk::NullChunkPtr;
+ }
+ Chunk *cs = os->GetNext();
+
+ while ( cs->IsNotNullChunk()
+ && cs->level > os->level)
+ {
+ cs = cs->GetNext();
+ }
+
+ if ( cs->IsNullChunk()
+ || chunk_is_not_token(cs, CT_SQUARE_CLOSE))
+ {
+ return;
+ }
+ set_chunk_parent(os, CT_CS_SQ_STMT);
+ set_chunk_parent(cs, CT_CS_SQ_STMT);
+
+ Chunk *tmp;
+
+ for (tmp = os->GetNext(); tmp != cs; tmp = tmp->GetNext())
+ {
+ set_chunk_parent(tmp, CT_CS_SQ_STMT);
+
+ if (chunk_is_token(tmp, CT_COLON))
+ {
+ set_chunk_type(tmp, CT_CS_SQ_COLON);
+ }
+ }
+
+ tmp = cs->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);
+ }
+} // handle_cs_square_stmt
+
+
+static void handle_cs_property(Chunk *bro)
+{
+ LOG_FUNC_ENTRY();
+
+ set_paren_parent(bro, CT_CS_PROPERTY);
+
+ bool did_prop = false;
+ Chunk *pc = bro;
+
+ while ((pc = pc->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ if (pc->level == bro->level)
+ {
+ //prevent scanning back past 'new' in expressions like new List<int> {1,2,3}
+ // Issue # 1620, UNI-24090.cs
+ if (chunk_is_token(pc, CT_NEW))
+ {
+ break;
+ }
+
+ if ( !did_prop
+ && ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_THIS)))
+ {
+ set_chunk_type(pc, CT_CS_PROPERTY);
+ did_prop = true;
+ }
+ else
+ {
+ set_chunk_parent(pc, CT_CS_PROPERTY);
+ make_type(pc);
+ }
+
+ if (pc->flags.test(PCF_STMT_START))
+ {
+ break;
+ }
+ }
+ }
+}
+
+
+static void handle_cs_array_type(Chunk *pc)
+{
+ if ( pc == nullptr
+ || pc->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *prev = pc->GetPrev();
+
+ for ( ;
+ chunk_is_token(prev, CT_COMMA);
+ prev = prev->GetPrev())
+ {
+ // empty
+ }
+
+ if (chunk_is_token(prev, CT_SQUARE_OPEN))
+ {
+ while (pc != prev)
+ {
+ set_chunk_parent(pc, CT_TYPE);
+ pc = pc->GetPrev();
+ }
+ set_chunk_parent(prev, CT_TYPE);
+ }
+}
+
+
+static void handle_wrap(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *opp = Chunk::NullChunkPtr;
+
+ if (pc != nullptr)
+ {
+ opp = pc->GetNext();
+ }
+ Chunk *name = opp->GetNext();
+ Chunk *clp = name->GetNext();
+
+ log_rule_B("sp_func_call_paren");
+ log_rule_B("sp_cpp_cast_paren");
+ iarf_e pav = chunk_is_token(pc, CT_FUNC_WRAP) ?
+ options::sp_func_call_paren() :
+ options::sp_cpp_cast_paren();
+
+ log_rule_B("sp_inside_fparen");
+ log_rule_B("sp_inside_paren_cast");
+ iarf_e av = chunk_is_token(pc, CT_FUNC_WRAP) ?
+ options::sp_inside_fparen() :
+ options::sp_inside_paren_cast();
+
+ if ( chunk_is_token(clp, CT_PAREN_CLOSE)
+ && chunk_is_token(opp, CT_PAREN_OPEN)
+ && ( chunk_is_token(name, CT_WORD)
+ || chunk_is_token(name, CT_TYPE)))
+ {
+ const char *psp = (pav & IARF_ADD) ? " " : "";
+ const char *fsp = (av & IARF_ADD) ? " " : "";
+
+ pc->str.append(psp);
+ pc->str.append("(");
+ pc->str.append(fsp);
+ pc->str.append(name->str);
+ pc->str.append(fsp);
+ pc->str.append(")");
+
+ set_chunk_type(pc, chunk_is_token(pc, CT_FUNC_WRAP) ? CT_FUNCTION : CT_TYPE);
+
+ pc->orig_col_end = pc->orig_col + pc->Len();
+
+ chunk_del(opp);
+ chunk_del(name);
+ chunk_del(clp);
+ }
+} // handle_wrap
+
+
+static void handle_proto_wrap(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *opp = pc->GetNextNcNnl();
+ Chunk *name = opp->GetNextNcNnl();
+ Chunk *tmp = name->GetNextNcNnl()->GetNextNcNnl();
+ Chunk *clp = chunk_skip_to_match(opp);
+ Chunk *cma = clp->GetNextNcNnl();
+
+ if ( opp->IsNullChunk()
+ || name->IsNullChunk()
+ || tmp->IsNullChunk()
+ || clp == nullptr
+ || cma->IsNullChunk()
+ || ( chunk_is_not_token(name, CT_WORD)
+ && chunk_is_not_token(name, CT_TYPE))
+ || chunk_is_not_token(opp, CT_PAREN_OPEN))
+ {
+ return;
+ }
+
+ if (chunk_is_token(cma, CT_SEMICOLON))
+ {
+ set_chunk_type(pc, CT_FUNC_PROTO);
+ }
+ else if (chunk_is_token(cma, CT_BRACE_OPEN))
+ {
+ LOG_FMT(LFCN, "%s(%d): (19) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_DEF);
+ }
+ else
+ {
+ return;
+ }
+ set_chunk_parent(opp, pc->type);
+ set_chunk_parent(clp, pc->type);
+
+ set_chunk_parent(tmp, CT_PROTO_WRAP);
+
+ if (chunk_is_token(tmp, CT_PAREN_OPEN))
+ {
+ fix_fcn_def_params(tmp);
+ }
+ else
+ {
+ fix_fcn_def_params(opp);
+ set_chunk_type(name, CT_WORD);
+ }
+ tmp = chunk_skip_to_match(tmp);
+
+ if (tmp)
+ {
+ set_chunk_parent(tmp, CT_PROTO_WRAP);
+ }
+ // Mark return type (TODO: move to own function)
+ tmp = pc;
+
+ while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ if ( !chunk_is_type(tmp)
+ && chunk_is_not_token(tmp, CT_OPERATOR)
+ && chunk_is_not_token(tmp, CT_WORD)
+ && chunk_is_not_token(tmp, CT_ADDR))
+ {
+ break;
+ }
+ set_chunk_parent(tmp, pc->type);
+ make_type(tmp);
+ }
+} // handle_proto_wrap
+
+
+/**
+ * Java assert statements are: "assert EXP1 [: EXP2] ;"
+ * Mark the parent of the colon and semicolon
+ */
+static void handle_java_assert(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ bool did_colon = false;
+ Chunk *tmp = pc;
+
+ if (tmp == nullptr)
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if (tmp->level == pc->level)
+ {
+ if ( !did_colon
+ && chunk_is_token(tmp, CT_COLON))
+ {
+ did_colon = true;
+ set_chunk_parent(tmp, pc->type);
+ }
+
+ if (chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ set_chunk_parent(tmp, pc->type);
+ break;
+ }
+ }
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.h
new file mode 100644
index 00000000..4d17706d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine.h
@@ -0,0 +1,77 @@
+/**
+ * @file combine.h
+ * prototypes for combine.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef COMBINE_H_INCLUDED
+#define COMBINE_H_INCLUDED
+
+#include "chunk.h"
+#include "uncrustify_types.h"
+
+
+/**
+ * Change CT_INCDEC_AFTER + WORD to CT_INCDEC_BEFORE
+ * Change number/word + CT_ADDR to CT_ARITH
+ * Change number/word + CT_STAR to CT_ARITH
+ * Change number/word + CT_NEG to CT_ARITH
+ * Change word + ( to a CT_FUNCTION
+ * Change struct/union/enum + CT_WORD => CT_TYPE
+ * Force parens on return.
+ *
+ * TODO: This could be done earlier.
+ *
+ * Patterns detected:
+ * STRUCT/ENUM/UNION + WORD :: WORD => TYPE
+ * WORD + '(' :: WORD => FUNCTION
+ */
+void fix_symbols(void);
+
+
+/**
+ * Examines the whole file and changes CT_COLON to
+ * CT_Q_COLON, CT_LABEL_COLON, or CT_CASE_COLON.
+ * It also changes the CT_WORD before CT_LABEL_COLON into CT_LABEL.
+ */
+void combine_labels(void);
+
+
+//! help function for mark_variable_definition...
+bool go_on(Chunk *pc, Chunk *start);
+
+
+//! Sets the parent for comments.
+void mark_comments(void);
+
+
+void make_type(Chunk *pc);
+
+
+/**
+ * Sets the parent of the open paren/brace/square/angle and the closing.
+ * Note - it is assumed that pc really does point to an open item and the
+ * close must be open + 1.
+ *
+ * @param start The open paren
+ * @param parent The type to assign as the parent
+ *
+ * @return The chunk after the close paren
+ */
+Chunk *set_paren_parent(Chunk *start, E_Token parent);
+
+
+/**
+ * This is called on every chunk.
+ * First on all non-preprocessor chunks and then on each preprocessor chunk.
+ * It does all the detection and classifying.
+ * This is only called by fix_symbols.
+ * The three parameters never get the value nullptr.
+ * it is not necessary to test.
+ */
+void do_symbol_check(Chunk *prev, Chunk *pc, Chunk *next);
+
+
+#endif /* COMBINE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.cpp
new file mode 100644
index 00000000..7c6ce813
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.cpp
@@ -0,0 +1,2617 @@
+/**
+ * @file combine_fix_mark.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract fom combine.cpp
+ */
+
+#include "combine_fix_mark.h"
+
+#include "combine_skip.h"
+#include "combine_tools.h"
+#include "flag_parens.h"
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LCOMBINE;
+
+
+void fix_casts(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc;
+ Chunk *prev;
+ Chunk *first;
+ Chunk *after;
+ Chunk *last = nullptr;
+ Chunk *paren_close;
+ const char *verb = "likely";
+ const char *detail = "";
+ size_t count = 0;
+ int word_count = 0;
+ bool nope;
+ bool doubtful_cast = false;
+
+
+ LOG_FMT(LCASTS, "%s(%d): start->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, start->Text(), start->orig_line, start->orig_col);
+
+ prev = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_token(prev, CT_PP_DEFINED))
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - after defined\n",
+ __func__, __LINE__);
+ return;
+ }
+
+ if (chunk_is_token(prev, CT_ANGLE_CLOSE))
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - after > (template)\n",
+ __func__, __LINE__);
+ return;
+ }
+ // Make sure there is only WORD, TYPE, and '*' or '^' before the close paren
+ pc = start->GetNextNcNnl();
+ first = pc;
+
+ while ( pc->IsNotNullChunk()
+ && ( chunk_is_type(pc)
+ || chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_QUALIFIER)
+ || chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_PP)
+ || chunk_is_token(pc, CT_STAR)
+ || chunk_is_token(pc, CT_QUESTION)
+ || chunk_is_token(pc, CT_CARET)
+ || chunk_is_token(pc, CT_TSQUARE)
+ || ( ( chunk_is_token(pc, CT_ANGLE_OPEN)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE))
+ && language_is_set(LANG_OC | LANG_JAVA | LANG_CS | LANG_VALA | LANG_CPP))
+ || ( ( chunk_is_token(pc, CT_QUESTION)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_MEMBER))
+ && language_is_set(LANG_JAVA | LANG_CS | LANG_VALA))
+ || ( chunk_is_token(pc, CT_COMMA)
+ && language_is_set(LANG_CPP))
+ || chunk_is_token(pc, CT_AMP)))
+ {
+ LOG_FMT(LCASTS, "%s(%d): pc->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, get_token_name(pc->type));
+
+ if ( chunk_is_token(pc, CT_WORD)
+ || ( chunk_is_token(last, CT_ANGLE_CLOSE)
+ && chunk_is_token(pc, CT_DC_MEMBER)))
+ {
+ word_count++;
+ }
+ else if ( chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_MEMBER)
+ || chunk_is_token(pc, CT_PP))
+ {
+ // might be negativ, such as with:
+ // a = val + (CFoo::bar_t)7;
+ word_count--;
+ }
+ last = pc;
+ pc = pc->GetNextNcNnl();
+ count++;
+ }
+
+ if ( pc->IsNullChunk()
+ || chunk_is_not_token(pc, CT_PAREN_CLOSE)
+ || chunk_is_token(prev, CT_OC_CLASS))
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast, hit type is %s\n",
+ __func__, __LINE__, pc->IsNullChunk() ? "Null chunk" : get_token_name(pc->type));
+ return;
+ }
+
+ if (word_count > 1)
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- too many words: %d\n",
+ __func__, __LINE__, word_count);
+ return;
+ }
+ paren_close = pc;
+
+ // If last is a type or star/caret, we have a cast for sure
+ if ( chunk_is_token(last, CT_STAR)
+ || chunk_is_token(last, CT_CARET)
+ || chunk_is_token(last, CT_PTR_TYPE)
+ || chunk_is_token(last, CT_TYPE)
+ || ( chunk_is_token(last, CT_ANGLE_CLOSE)
+ && language_is_set(LANG_OC | LANG_JAVA | LANG_CS | LANG_VALA | LANG_CPP)))
+ {
+ verb = "for sure";
+ }
+ else if (count == 1)
+ {
+ /*
+ * We are on a potential cast of the form "(word)".
+ * We don't know if the word is a type. So lets guess based on some
+ * simple rules:
+ * - if all caps, likely a type
+ * - if it ends in _t, likely a type
+ * - if it's objective-c and the type is id, likely valid
+ */
+ verb = "guessed";
+
+ if ( (last->Len() > 3)
+ && (last->str[last->Len() - 2] == '_')
+ && (last->str[last->Len() - 1] == 't'))
+ {
+ detail = " -- '_t'";
+ }
+ else if (is_ucase_str(last->Text(), last->Len()))
+ {
+ detail = " -- upper case";
+ }
+ else if ( language_is_set(LANG_OC)
+ && chunk_is_str(last, "id"))
+ {
+ detail = " -- Objective-C id";
+ }
+ else
+ {
+ // If we can't tell for sure whether this is a cast, decide against it
+ detail = " -- mixed case";
+ doubtful_cast = true;
+ }
+ /*
+ * If the next item is a * or &, the next item after that can't be a
+ * number or string.
+ *
+ * If the next item is a +, the next item has to be a number.
+ *
+ * If the next item is a -, the next item can't be a string.
+ *
+ * For this to be a cast, the close paren must be followed by:
+ * - constant (number or string)
+ * - paren open
+ * - word
+ *
+ * Find the next non-open paren item.
+ */
+ pc = paren_close->GetNextNcNnl();
+ after = pc;
+
+ do
+ {
+ after = after->GetNextNcNnl();
+ } while (chunk_is_token(after, CT_PAREN_OPEN));
+
+ if (after->IsNullChunk())
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - hit null chunk\n",
+ __func__, __LINE__);
+ return;
+ }
+ nope = false;
+
+ if (chunk_is_ptr_operator(pc))
+ {
+ // star (*) and address (&) are ambiguous
+ if ( chunk_is_token(after, CT_NUMBER_FP)
+ || chunk_is_token(after, CT_NUMBER)
+ || chunk_is_token(after, CT_STRING)
+ || doubtful_cast)
+ {
+ nope = true;
+ }
+ }
+ else if (chunk_is_token(pc, CT_MINUS))
+ {
+ // (UINT8)-1 or (foo)-1 or (FOO)-'a'
+ if ( chunk_is_token(after, CT_STRING)
+ || doubtful_cast)
+ {
+ nope = true;
+ }
+ }
+ else if (chunk_is_token(pc, CT_PLUS))
+ {
+ // (UINT8)+1 or (foo)+1
+ if ( ( chunk_is_not_token(after, CT_NUMBER)
+ && chunk_is_not_token(after, CT_NUMBER_FP))
+ || doubtful_cast)
+ {
+ nope = true;
+ }
+ }
+ else if ( chunk_is_not_token(pc, CT_NUMBER_FP)
+ && chunk_is_not_token(pc, CT_NUMBER)
+ && chunk_is_not_token(pc, CT_WORD)
+ && chunk_is_not_token(pc, CT_THIS)
+ && chunk_is_not_token(pc, CT_TYPE)
+ && chunk_is_not_token(pc, CT_PAREN_OPEN)
+ && chunk_is_not_token(pc, CT_STRING)
+ && chunk_is_not_token(pc, CT_DECLTYPE)
+ && chunk_is_not_token(pc, CT_SIZEOF)
+ && get_chunk_parent_type(pc) != CT_SIZEOF
+ && chunk_is_not_token(pc, CT_FUNC_CALL)
+ && chunk_is_not_token(pc, CT_FUNC_CALL_USER)
+ && chunk_is_not_token(pc, CT_FUNCTION)
+ && chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && (!( chunk_is_token(pc, CT_SQUARE_OPEN)
+ && language_is_set(LANG_OC))))
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - followed by Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+ return;
+ }
+
+ if (nope)
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - Text() '%s' followed by type %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(after->type));
+ return;
+ }
+ }
+ // if the 'cast' is followed by a semicolon, comma, bool or close parenthesis, it isn't
+ pc = paren_close->GetNextNcNnl();
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+
+ if ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_BOOL) // Issue #2151
+ || chunk_is_paren_close(pc))
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - followed by type %s\n",
+ __func__, __LINE__, get_token_name(pc->type));
+ return;
+ }
+ set_chunk_parent(start, CT_C_CAST);
+ set_chunk_parent(paren_close, CT_C_CAST);
+
+ LOG_FMT(LCASTS, "%s(%d): -- %s c-cast: (",
+ __func__, __LINE__, verb);
+
+ for (pc = first;
+ pc->IsNotNullChunk() && pc != paren_close;
+ pc = pc->GetNextNcNnl())
+ {
+ set_chunk_parent(pc, CT_C_CAST);
+ make_type(pc);
+ LOG_FMT(LCASTS, " %s", pc->Text());
+ }
+
+ LOG_FMT(LCASTS, " )%s\n", detail);
+
+ // Mark the next item as an expression start
+ pc = paren_close->GetNextNcNnl();
+
+ if (pc->IsNotNullChunk())
+ {
+ chunk_flags_set(pc, PCF_EXPR_START);
+
+ if (chunk_is_opening_brace(pc))
+ {
+ set_paren_parent(pc, get_chunk_parent_type(start));
+ }
+ }
+} // fix_casts
+
+
+void fix_fcn_def_params(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start == nullptr)
+ {
+ return;
+ }
+ LOG_FMT(LFCNP, "%s(%d): Text() '%s', type is %s, on orig_line %zu, level is %zu\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->type), start->orig_line, start->level);
+
+ while ( start->IsNotNullChunk()
+ && !chunk_is_paren_open(start))
+ {
+ start = start->GetNextNcNnl();
+ }
+
+ if (start->IsNullChunk()) // Coverity CID 76003, 1100782
+ {
+ return;
+ }
+ // ensure start chunk holds a single '(' character
+ assert( (start->Len() == 1)
+ && (start->str[0] == '('));
+
+ ChunkStack cs;
+ size_t level = start->level + 1;
+ Chunk *pc = start->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( ( (start->Len() == 1)
+ && (start->str[0] == ')'))
+ || pc->level < level)
+ {
+ LOG_FMT(LFCNP, "%s(%d): bailed on Text() '%s', on orig_line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ break;
+ }
+ LOG_FMT(LFCNP, "%s(%d): %s, Text() '%s' on orig_line %zu, level %zu\n",
+ __func__, __LINE__, (pc->level > level) ? "skipping" : "looking at",
+ pc->Text(), pc->orig_line, pc->level);
+
+ if (pc->level > level)
+ {
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+
+ if ( pc->IsStar()
+ || chunk_is_msref(pc)
+ || chunk_is_nullable(pc))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ cs.Push_Back(pc);
+ }
+ else if ( chunk_is_token(pc, CT_AMP)
+ || ( language_is_set(LANG_CPP)
+ && chunk_is_str(pc, "&&")))
+ {
+ set_chunk_type(pc, CT_BYREF);
+ cs.Push_Back(pc);
+ }
+ else if (chunk_is_token(pc, CT_TYPE_WRAP))
+ {
+ cs.Push_Back(pc);
+ }
+ else if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_TYPE))
+ {
+ cs.Push_Back(pc);
+ }
+ else if ( chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_ASSIGN))
+ {
+ mark_variable_stack(cs, LFCNP);
+
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ // Mark assignment for default param spacing
+ set_chunk_parent(pc, CT_FUNC_PROTO);
+ }
+ }
+ pc = pc->GetNextNcNnl();
+ }
+ mark_variable_stack(cs, LFCNP);
+} // fix_fcn_def_params
+
+
+void fix_type_cast(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start == nullptr)
+ {
+ return;
+ }
+ Chunk *pc = start->GetNextNcNnl();
+
+ if ( pc->IsNullChunk()
+ || chunk_is_not_token(pc, CT_ANGLE_OPEN))
+ {
+ return;
+ }
+ pc = pc->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= start->level)
+ {
+ if ( pc->level == start->level
+ && chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_str(pc, "("))
+ {
+ set_paren_parent(pc, CT_TYPE_CAST);
+ }
+ return;
+ }
+ make_type(pc);
+ pc = pc->GetNextNcNnl();
+ }
+} // fix_type_cast
+
+
+void fix_typedef(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start == nullptr)
+ {
+ return;
+ }
+ LOG_FMT(LTYPEDEF, "%s(%d): typedef @ orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, start->orig_line, start->orig_col);
+
+ Chunk *the_type = Chunk::NullChunkPtr;
+ Chunk *last_op = Chunk::NullChunkPtr;
+
+ /*
+ * Mark everything in the typedef and scan for ")(", which makes it a
+ * function type
+ */
+ for (Chunk *next = start->GetNextNcNnl(E_Scope::PREPROC)
+ ; next->IsNotNullChunk() && next->level >= start->level
+ ; next = next->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ chunk_flags_set(next, PCF_IN_TYPEDEF);
+
+ if (start->level == next->level)
+ {
+ if (chunk_is_semicolon(next))
+ {
+ set_chunk_parent(next, CT_TYPEDEF);
+ break;
+ }
+
+ if (chunk_is_token(next, CT_ATTRIBUTE))
+ {
+ break;
+ }
+
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(next, CT_ASSIGN))
+ {
+ set_chunk_parent(next, CT_TYPEDEF);
+ break;
+ }
+ make_type(next);
+
+ if (chunk_is_token(next, CT_TYPE))
+ {
+ the_type = next;
+ }
+ chunk_flags_clr(next, PCF_VAR_1ST_DEF);
+
+ if (*next->str.c_str() == '(')
+ {
+ last_op = next;
+ }
+ }
+ }
+
+ // avoid interpreting typedef NS_ENUM (NSInteger, MyEnum) as a function def
+ if ( last_op->IsNotNullChunk()
+ && !( language_is_set(LANG_OC)
+ && get_chunk_parent_type(last_op) == CT_ENUM))
+ {
+ flag_parens(last_op, PCF_NONE, CT_FPAREN_OPEN, CT_TYPEDEF, false);
+ fix_fcn_def_params(last_op);
+
+ the_type = last_op->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #2279
+
+ if (the_type->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *open_paren = nullptr;
+
+ if (chunk_is_paren_close(the_type))
+ {
+ open_paren = chunk_skip_to_match_rev(the_type);
+ mark_function_type(the_type);
+ the_type = the_type->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #2279
+
+ if (the_type->IsNullChunk())
+ {
+ return;
+ }
+ }
+ else
+ {
+ // must be: "typedef <return type>func(params);"
+ set_chunk_type(the_type, CT_FUNC_TYPE);
+ }
+ set_chunk_parent(the_type, CT_TYPEDEF);
+
+ LOG_FMT(LTYPEDEF, "%s(%d): fcn typedef Text() '%s', on orig_line %zu\n",
+ __func__, __LINE__, the_type->Text(), the_type->orig_line);
+
+ // If we are aligning on the open parenthesis, grab that instead
+ log_rule_B("align_typedef_func");
+
+ if ( open_paren != nullptr
+ && options::align_typedef_func() == 1)
+ {
+ the_type = open_paren;
+ }
+ log_rule_B("align_typedef_func");
+
+ if (options::align_typedef_func() != 0)
+ {
+ LOG_FMT(LTYPEDEF, "%s(%d): -- align anchor on Text() %s, @ orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, the_type->Text(), the_type->orig_line, the_type->orig_col);
+ chunk_flags_set(the_type, PCF_ANCHOR);
+ }
+ // already did everything we need to do
+ return;
+ }
+ /*
+ * Skip over enum/struct/union stuff, as we know it isn't a return type
+ * for a function type
+ */
+ Chunk *after = start->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (after->IsNullChunk())
+ {
+ return;
+ }
+
+ if ( chunk_is_not_token(after, CT_ENUM)
+ && chunk_is_not_token(after, CT_STRUCT)
+ && chunk_is_not_token(after, CT_UNION))
+ {
+ if ( the_type != nullptr
+ && the_type->IsNotNullChunk())
+ {
+ // We have just a regular typedef
+ LOG_FMT(LTYPEDEF, "%s(%d): regular typedef Text() %s, on orig_line %zu\n",
+ __func__, __LINE__, the_type->Text(), the_type->orig_line);
+ chunk_flags_set(the_type, PCF_ANCHOR);
+ }
+ return;
+ }
+ // We have a struct/union/enum, next should be either a type or {
+ Chunk *next = after->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_token(next, CT_TYPE))
+ {
+ next = next->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ }
+
+ if (chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ // Skip to the closing brace
+ Chunk *br_c = next->GetNextType(CT_BRACE_CLOSE, next->level, E_Scope::PREPROC);
+
+ if (br_c->IsNotNullChunk())
+ {
+ const E_Token tag = after->type;
+ set_chunk_parent(next, tag);
+ set_chunk_parent(br_c, tag);
+
+ if (tag == CT_ENUM)
+ {
+ flag_series(after, br_c, PCF_IN_ENUM);
+ }
+ else if (tag == CT_STRUCT)
+ {
+ flag_series(after, br_c, PCF_IN_STRUCT);
+ }
+ }
+ }
+
+ if ( the_type != nullptr
+ && the_type->IsNotNullChunk())
+ {
+ LOG_FMT(LTYPEDEF, "%s(%d): %s typedef Text() %s, on orig_line %zu\n",
+ __func__, __LINE__, get_token_name(after->type), the_type->Text(),
+ the_type->orig_line);
+ chunk_flags_set(the_type, PCF_ANCHOR);
+ }
+} // fix_typedef
+
+
+Chunk *fix_variable_definition(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = start;
+ Chunk *end;
+ Chunk *tmp_pc;
+ ChunkStack cs;
+ int idx;
+ int ref_idx;
+
+ LOG_FMT(LFVD, "%s(%d): start at pc->orig_line is %zu, pc->orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+
+ // Scan for words and types and stars oh my!
+ while ( chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_QUALIFIER)
+ || chunk_is_token(pc, CT_TYPENAME)
+ || chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_MEMBER)
+ || chunk_is_token(pc, CT_PP) // Issue #3169
+ || chunk_is_ptr_operator(pc))
+ {
+ LOG_FMT(LFVD, "%s(%d): 1:pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+ cs.Push_Back(pc);
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNullChunk())
+ {
+ LOG_FMT(LFVD, "%s(%d): pc is null chunk\n", __func__, __LINE__);
+ return(Chunk::NullChunkPtr);
+ }
+ LOG_FMT(LFVD, "%s(%d): 2:pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+
+ // Skip templates and attributes
+ pc = skip_template_next(pc);
+
+ if (pc->IsNullChunk())
+ {
+ LOG_FMT(LFVD, "%s(%d): pc is null chunk\n", __func__, __LINE__);
+ return(Chunk::NullChunkPtr);
+ }
+ LOG_FMT(LFVD, "%s(%d): 3:pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+
+ pc = skip_attribute_next(pc);
+
+ if (pc->IsNullChunk())
+ {
+ LOG_FMT(LFVD, "%s(%d): pc is null chunk\n", __func__, __LINE__);
+ return(Chunk::NullChunkPtr);
+ }
+ LOG_FMT(LFVD, "%s(%d): 4:pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+
+ if (language_is_set(LANG_JAVA))
+ {
+ pc = skip_tsquare_next(pc);
+
+ if (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LFVD, "%s(%d): 5:pc->Text() '%s', type is %s\n", __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+ }
+ else
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ }
+ }
+ end = pc;
+
+ if (end->IsNullChunk())
+ {
+ LOG_FMT(LFVD, "%s(%d): end is null chunk\n", __func__, __LINE__);
+ return(nullptr);
+ }
+ LOG_FMT(LFVD, "%s(%d): end->type is %s\n", __func__, __LINE__, get_token_name(end->type));
+
+ if (chunk_is_token(end, CT_FUNC_CTOR_VAR)) // Issue #3010
+ {
+ return(end);
+ }
+
+ if ( cs.Len() == 1
+ && chunk_is_token(end, CT_BRACE_OPEN)
+ && get_chunk_parent_type(end) == CT_BRACED_INIT_LIST)
+ {
+ set_chunk_type(cs.Get(0)->m_pc, CT_TYPE);
+ }
+
+ // Function defs are handled elsewhere
+ if ( (cs.Len() <= 1)
+ || chunk_is_token(end, CT_FUNC_DEF)
+ || chunk_is_token(end, CT_FUNC_PROTO)
+ || chunk_is_token(end, CT_FUNC_CLASS_DEF)
+ || chunk_is_token(end, CT_FUNC_CLASS_PROTO)
+ || chunk_is_token(end, CT_OPERATOR))
+ {
+ return(skip_to_next_statement(end));
+ }
+ // ref_idx points to the alignable part of the variable definition
+ ref_idx = cs.Len() - 1;
+
+ // Check for the '::' stuff: "char *Engine::name"
+ if ( (cs.Len() >= 3)
+ && ( (cs.Get(cs.Len() - 2)->m_pc->type == CT_MEMBER)
+ || (cs.Get(cs.Len() - 2)->m_pc->type == CT_DC_MEMBER)))
+ {
+ idx = cs.Len() - 2;
+
+ while (idx > 0)
+ {
+ tmp_pc = cs.Get(idx)->m_pc;
+
+ if ( chunk_is_not_token(tmp_pc, CT_DC_MEMBER)
+ && chunk_is_not_token(tmp_pc, CT_MEMBER))
+ {
+ break;
+ }
+ idx--;
+ tmp_pc = cs.Get(idx)->m_pc;
+
+ if ( chunk_is_not_token(tmp_pc, CT_WORD)
+ && chunk_is_not_token(tmp_pc, CT_TYPE))
+ {
+ break;
+ }
+ make_type(tmp_pc);
+ idx--;
+ }
+ ref_idx = idx + 1;
+ }
+ tmp_pc = cs.Get(ref_idx)->m_pc;
+ LOG_FMT(LFVD, "%s(%d): ref_idx(%d) is '%s'\n", __func__, __LINE__, ref_idx, tmp_pc->Text());
+
+ // No type part found!
+ if (ref_idx <= 0)
+ {
+ return(skip_to_next_statement(end));
+ }
+ LOG_FMT(LFVD2, "%s(%d): orig_line is %zu, TYPE : ", __func__, __LINE__, start->orig_line);
+
+ for (size_t idxForCs = 0; idxForCs < cs.Len() - 1; idxForCs++)
+ {
+ tmp_pc = cs.Get(idxForCs)->m_pc;
+ make_type(tmp_pc);
+ chunk_flags_set(tmp_pc, PCF_VAR_TYPE);
+ LOG_FMT(LFVD2, " Text() is '%s', type is %s", tmp_pc->Text(), get_token_name(tmp_pc->type));
+ }
+
+ LOG_FMT(LFVD2, "\n");
+
+ // OK we have two or more items, mark types up to the end.
+ LOG_FMT(LFVD, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ mark_variable_definition(cs.Get(cs.Len() - 1)->m_pc);
+
+ if (chunk_is_token(end, CT_COMMA))
+ {
+ return(end->GetNextNcNnl());
+ }
+ return(skip_to_next_statement(end));
+} // fix_variable_definition
+
+
+void mark_cpp_constructor(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *paren_open;
+ Chunk *tmp;
+ Chunk *after;
+ Chunk *var;
+ bool is_destr = false;
+
+ tmp = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( chunk_is_token(tmp, CT_INV)
+ || chunk_is_token(tmp, CT_DESTRUCTOR))
+ {
+ set_chunk_type(tmp, CT_DESTRUCTOR);
+ set_chunk_parent(pc, CT_DESTRUCTOR);
+ is_destr = true;
+ }
+ LOG_FMT(LFTOR, "%s(%d): orig_line is %zu, orig_col is %zu, FOUND %sSTRUCTOR for '%s'[%s] prev '%s'[%s]\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col,
+ is_destr ? "DE" : "CON",
+ pc->Text(), get_token_name(pc->type),
+ tmp->Text(), get_token_name(tmp->type));
+
+ paren_open = skip_template_next(pc->GetNextNcNnl());
+
+ if (!chunk_is_str(paren_open, "("))
+ {
+ LOG_FMT(LWARN, "%s:%zu Expected '(', got: [%s]\n",
+ cpd.filename.c_str(), paren_open->orig_line,
+ paren_open->Text());
+ return;
+ }
+ // Mark parameters
+ fix_fcn_def_params(paren_open);
+ after = flag_parens(paren_open, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CLASS_PROTO, false);
+
+ LOG_FMT(LFTOR, "%s(%d): Text() '%s'\n", __func__, __LINE__, after->Text());
+
+ // Scan until the brace open, mark everything
+ tmp = paren_open;
+ bool hit_colon = false;
+
+ while ( tmp->IsNotNullChunk()
+ && ( chunk_is_not_token(tmp, CT_BRACE_OPEN)
+ || tmp->level != paren_open->level)
+ && !chunk_is_semicolon(tmp))
+ {
+ LOG_FMT(LFTOR, "%s(%d): tmp is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line, tmp->orig_col);
+ chunk_flags_set(tmp, PCF_IN_CONST_ARGS);
+ tmp = tmp->GetNextNcNnl();
+
+ if ( chunk_is_str(tmp, ":")
+ && tmp->level == paren_open->level)
+ {
+ set_chunk_type(tmp, CT_CONSTR_COLON);
+ hit_colon = true;
+ }
+
+ if ( hit_colon
+ && ( chunk_is_paren_open(tmp)
+ || chunk_is_opening_brace(tmp))
+ && tmp->level == paren_open->level)
+ {
+ var = skip_template_prev(tmp->GetPrevNcNnlNi()); // Issue #2279
+
+ if ( chunk_is_token(var, CT_TYPE)
+ || chunk_is_token(var, CT_WORD))
+ {
+ set_chunk_type(var, CT_FUNC_CTOR_VAR);
+ flag_parens(tmp, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CTOR_VAR, false);
+ }
+ }
+ }
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ set_paren_parent(paren_open, CT_FUNC_CLASS_DEF);
+ set_paren_parent(tmp, CT_FUNC_CLASS_DEF);
+ LOG_FMT(LFCN, "%s(%d): Marked '%s' as FUNC_CLASS_DEF on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ set_chunk_parent(tmp, CT_FUNC_CLASS_PROTO);
+ set_chunk_type(pc, CT_FUNC_CLASS_PROTO);
+ LOG_FMT(LFCN, "%s(%d): Marked '%s' as FUNC_CLASS_PROTO on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ }
+ tmp = pc->GetPrevNcNnlNi(); // Issue #2907
+
+ if (chunk_is_token(tmp, CT_DESTRUCTOR))
+ {
+ set_chunk_parent(tmp, pc->type);
+ tmp = tmp->GetPrevNcNnlNi();
+ }
+
+ while (chunk_is_token(tmp, CT_QUALIFIER))
+ {
+ set_chunk_parent(tmp, pc->type);
+ tmp = tmp->GetPrevNcNnlNi();
+ }
+} // mark_cpp_constructor
+
+
+void mark_cpp_lambda(Chunk *square_open)
+{
+ if ( chunk_is_token(square_open, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(square_open) == CT_CPP_LAMBDA)
+ {
+ auto *brace_close = square_open->GetNextType(CT_BRACE_CLOSE, square_open->level);
+
+ if (get_chunk_parent_type(brace_close) == CT_CPP_LAMBDA)
+ {
+ for (auto *pc = square_open; pc != brace_close; pc = pc->GetNextNcNnl())
+ {
+ chunk_flags_set(pc, PCF_IN_LAMBDA);
+ }
+ }
+ }
+} // mark_cpp_lambda
+
+
+void mark_define_expressions(void)
+{
+ LOG_FUNC_ENTRY();
+
+ bool in_define = false;
+ bool first = true;
+ Chunk *pc = Chunk::GetHead();
+ Chunk *prev = pc;
+
+ while (pc->IsNotNullChunk())
+ {
+ if (!in_define)
+ {
+ if ( chunk_is_token(pc, CT_PP_DEFINE)
+ || chunk_is_token(pc, CT_PP_IF)
+ || chunk_is_token(pc, CT_PP_ELSE))
+ {
+ in_define = true;
+ first = true;
+ }
+ }
+ else
+ {
+ if ( !pc->flags.test(PCF_IN_PREPROC)
+ || chunk_is_token(pc, CT_PREPROC))
+ {
+ in_define = false;
+ }
+ else
+ {
+ if ( chunk_is_not_token(pc, CT_MACRO)
+ && ( first
+ || chunk_is_token(prev, CT_PAREN_OPEN)
+ || chunk_is_token(prev, CT_ARITH)
+ || chunk_is_token(prev, CT_SHIFT)
+ || chunk_is_token(prev, CT_CARET)
+ || chunk_is_token(prev, CT_ASSIGN)
+ || chunk_is_token(prev, CT_COMPARE)
+ || chunk_is_token(prev, CT_RETURN)
+ || chunk_is_token(prev, CT_GOTO)
+ || chunk_is_token(prev, CT_CONTINUE)
+ || chunk_is_token(prev, CT_FPAREN_OPEN)
+ || chunk_is_token(prev, CT_SPAREN_OPEN)
+ || chunk_is_token(prev, CT_BRACE_OPEN)
+ || chunk_is_semicolon(prev)
+ || chunk_is_token(prev, CT_COMMA)
+ || chunk_is_token(prev, CT_COLON)
+ || chunk_is_token(prev, CT_QUESTION)))
+ {
+ chunk_flags_set(pc, PCF_EXPR_START);
+ first = false;
+ }
+ }
+ }
+ prev = pc;
+ pc = pc->GetNext();
+ }
+} // mark_define_expressions
+
+
+void mark_exec_sql(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *tmp;
+
+ // Change CT_WORD to CT_SQL_WORD
+ for (tmp = pc->GetNext(); tmp != nullptr && tmp->IsNotNullChunk(); tmp = tmp->GetNext())
+ {
+ set_chunk_parent(tmp, pc->type);
+
+ if (chunk_is_token(tmp, CT_WORD))
+ {
+ set_chunk_type(tmp, CT_SQL_WORD);
+ }
+
+ if (chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ break;
+ }
+ }
+
+ if ( chunk_is_not_token(pc, CT_SQL_BEGIN)
+ || tmp->IsNullChunk()
+ || chunk_is_not_token(tmp, CT_SEMICOLON))
+ {
+ return;
+ }
+
+ for (tmp = tmp->GetNext();
+ tmp->IsNotNullChunk() && chunk_is_not_token(tmp, CT_SQL_END);
+ tmp = tmp->GetNext())
+ {
+ tmp->level++;
+ }
+} // mark_exec_sql
+
+
+void mark_function_return_type(Chunk *fname, Chunk *start, E_Token parent_type)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = start;
+
+ if (pc != nullptr)
+ {
+ // Step backwards from pc and mark the parent of the return type
+ LOG_FMT(LFCNR, "%s(%d): (backwards) return type for '%s' @ orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, fname->Text(), fname->orig_line, fname->orig_col);
+
+ Chunk *first = pc;
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s, ",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ log_pcf_flags(LFCNR, pc->flags);
+
+ if (chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ pc = skip_template_prev(pc);
+
+ if ( pc->IsNullChunk()
+ || chunk_is_token(pc, CT_TEMPLATE))
+ {
+ //either expression is not complete or this is smth like 'template<T> void func()'
+ // - we are not interested in 'template<T>' part
+ break;
+ }
+ else
+ {
+ //this is smth like 'vector<int> func()' and 'pc' is currently on 'vector' - just proceed
+ }
+ }
+
+ if ( ( !chunk_is_type(pc)
+ && chunk_is_not_token(pc, CT_OPERATOR)
+ && chunk_is_not_token(pc, CT_WORD)
+ && chunk_is_not_token(pc, CT_ADDR))
+ || pc->flags.test(PCF_IN_PREPROC))
+ {
+ break;
+ }
+
+ if (!chunk_is_ptr_operator(pc))
+ {
+ first = pc;
+ }
+ pc = pc->GetPrevNcNnlNi(); // Issue #2279
+ }
+ LOG_FMT(LFCNR, "%s(%d): marking returns...", __func__, __LINE__);
+
+ // Changing words to types into tuple return types in CS.
+ bool is_return_tuple = false;
+
+ if ( chunk_is_token(pc, CT_PAREN_CLOSE)
+ && !pc->flags.test(PCF_IN_PREPROC))
+ {
+ first = chunk_skip_to_match_rev(pc);
+ is_return_tuple = true;
+ }
+ pc = first;
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LFCNR, " Text() '%s', type is %s", pc->Text(), get_token_name(pc->type));
+
+ if (parent_type != CT_NONE)
+ {
+ set_chunk_parent(pc, parent_type);
+ }
+ Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( !is_return_tuple
+ || chunk_is_not_token(pc, CT_WORD)
+ || ( prev->IsNullChunk()
+ && chunk_is_not_token(prev, CT_TYPE)))
+ {
+ make_type(pc);
+ }
+
+ if (pc == start)
+ {
+ break;
+ }
+ pc = pc->GetNextNcNnl();
+
+ //template angles should keep parent type CT_TEMPLATE
+ if (chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ pc = pc->GetNextType(CT_ANGLE_CLOSE, pc->level);
+
+ if (pc == start)
+ {
+ break;
+ }
+ pc = pc->GetNextNcNnl();
+ }
+ }
+ LOG_FMT(LFCNR, "\n");
+
+ // Back up and mark parent type on friend declarations
+ if ( parent_type != CT_NONE
+ && first
+ && first->flags.test(PCF_IN_CLASS))
+ {
+ pc = first->GetPrevNcNnlNi(); // Issue #2279
+
+ if (chunk_is_token(pc, CT_FRIEND))
+ {
+ LOG_FMT(LFCNR, "%s(%d): marking friend\n", __func__, __LINE__);
+ set_chunk_parent(pc, parent_type);
+ // A friend might be preceded by a template specification, as in:
+ // template <...> friend type func(...);
+ // If so, we need to mark that also
+ pc = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if (chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ pc = skip_template_prev(pc);
+
+ if (chunk_is_token(pc, CT_TEMPLATE))
+ {
+ LOG_FMT(LFCNR, "%s(%d): marking friend template\n",
+ __func__, __LINE__);
+ set_chunk_parent(pc, parent_type);
+ }
+ }
+ }
+ }
+ }
+} // mark_function_return_type
+
+
+void mark_function(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return;
+ }
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279
+ Chunk *next = pc->GetNextNppOrNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *tmp;
+ Chunk *semi = nullptr;
+ Chunk *paren_open;
+ Chunk *paren_close;
+
+ // Find out what is before the operator
+ if (get_chunk_parent_type(pc) == CT_OPERATOR)
+ {
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ log_pcf_flags(LGUY, pc->flags);
+ Chunk *pc_op = pc->GetPrevType(CT_OPERATOR, pc->level);
+
+ if ( pc_op->IsNotNullChunk()
+ && pc_op->flags.test(PCF_EXPR_START))
+ {
+ LOG_FMT(LFCN, "%s(%d): (4) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ }
+
+ if (language_is_set(LANG_CPP))
+ {
+ tmp = pc;
+
+ while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ if ( chunk_is_token(tmp, CT_BRACE_CLOSE)
+ || chunk_is_token(tmp, CT_BRACE_OPEN) // Issue 575
+ || chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if ( chunk_is_paren_open(tmp)
+ && !pc->flags.test(PCF_IN_PREPROC)) // Issue #2703
+ {
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+ LOG_FMT(LFCN, "%s(%d): (5) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ break;
+ }
+
+ if (chunk_is_token(tmp, CT_ASSIGN))
+ {
+ LOG_FMT(LFCN, "%s(%d): (6) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ break;
+ }
+
+ if (chunk_is_token(tmp, CT_TEMPLATE))
+ {
+ LOG_FMT(LFCN, "%s(%d): (7) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_DEF);
+ break;
+ }
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ if (get_chunk_parent_type(tmp) == CT_FUNC_DEF)
+ {
+ LOG_FMT(LFCN, "%s(%d): (8) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ }
+
+ if ( get_chunk_parent_type(tmp) == CT_CLASS
+ || get_chunk_parent_type(tmp) == CT_STRUCT)
+ {
+ LOG_FMT(LFCN, "%s(%d): (9) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_DEF);
+ }
+ break;
+ }
+ }
+
+ if ( tmp != nullptr
+ && chunk_is_not_token(pc, CT_FUNC_CALL))
+ {
+ // Mark the return type
+ tmp = tmp->GetNextNcNnl();
+
+ while ( tmp != pc
+ && tmp->IsNotNullChunk())
+ {
+ make_type(tmp); // Mark the return type
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+ }
+ }
+
+ if ( chunk_is_ptr_operator(next)
+ || chunk_is_newline(next))
+ {
+ next = next->GetNextNppOrNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ }
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s, type is %s, parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)));
+ LOG_FMT(LFCN, " level is %zu, brace_level is %zu, next->Text() '%s', next->type is %s, next->level is %zu\n",
+ pc->level, pc->brace_level,
+ next->Text(), get_token_name(next->type), next->level);
+
+ if (pc->flags.test(PCF_IN_CONST_ARGS))
+ {
+ set_chunk_type(pc, CT_FUNC_CTOR_VAR);
+ LOG_FMT(LFCN, "%s(%d): 1) Marked [%s] as FUNC_CTOR_VAR on line %zu col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ next = skip_template_next(next);
+
+ if (next == nullptr)
+ {
+ return;
+ }
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, pc->type, true);
+ return;
+ }
+ // Skip over any template and attribute madness
+ next = skip_template_next(next);
+
+ if (next == nullptr)
+ {
+ return;
+ }
+ next = skip_attribute_next(next);
+
+ if (next == nullptr)
+ {
+ return;
+ }
+ // Find the open and close parenthesis
+ paren_open = pc->GetNextString("(", 1, pc->level);
+ paren_close = paren_open->GetNextString(")", 1, pc->level);
+
+ if ( paren_open->IsNullChunk()
+ || paren_close->IsNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): No parens found for [%s] on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ return;
+ }
+ /*
+ * This part detects either chained function calls or a function ptr definition.
+ * MYTYPE (*func)(void);
+ * mWriter( "class Clst_"c )( somestr.getText() )( " : Cluster {"c ).newline;
+ *
+ * For it to be a function variable def, there must be a '*' followed by a
+ * single word.
+ *
+ * Otherwise, it must be chained function calls.
+ */
+ tmp = paren_close->GetNextNcNnl();
+
+ if ( tmp->IsNotNullChunk()
+ && chunk_is_str(tmp, "("))
+ {
+ Chunk *tmp1;
+ Chunk *tmp2;
+ Chunk *tmp3;
+
+ // skip over any leading class/namespace in: "T(F::*A)();"
+ tmp1 = next->GetNextNcNnl();
+
+ while (tmp1->IsNotNullChunk())
+ {
+ tmp2 = tmp1->GetNextNcNnl();
+
+ if ( !chunk_is_word(tmp1)
+ || chunk_is_not_token(tmp2, CT_DC_MEMBER))
+ {
+ break;
+ }
+ tmp1 = tmp2->GetNextNcNnl();
+ }
+ tmp2 = tmp1->GetNextNcNnl();
+
+ if (chunk_is_str(tmp2, ")"))
+ {
+ tmp3 = tmp2;
+ tmp2 = Chunk::NullChunkPtr;
+ }
+ else
+ {
+ tmp3 = tmp2->GetNextNcNnl();
+ }
+ tmp3 = chunk_get_next_ssq(tmp3);
+
+ if ( chunk_is_str(tmp3, ")")
+ && ( tmp1->IsStar()
+ || chunk_is_msref(tmp1)
+ || ( language_is_set(LANG_OC)
+ && chunk_is_token(tmp1, CT_CARET)))
+ && ( tmp2->IsNullChunk()
+ || chunk_is_token(tmp2, CT_WORD)))
+ {
+ if (tmp2->IsNotNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, function variable '%s', changing '%s' into a type\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, tmp2->Text(), pc->Text());
+ set_chunk_type(tmp2, CT_FUNC_VAR);
+ flag_parens(paren_open, PCF_NONE, CT_PAREN_OPEN, CT_FUNC_VAR, false);
+
+ LOG_FMT(LFCN, "%s(%d): paren open @ orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, paren_open->orig_line, paren_open->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, function type, changing '%s' into a type\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ if (tmp2)
+ {
+ set_chunk_type(tmp2, CT_FUNC_TYPE);
+ }
+ flag_parens(paren_open, PCF_NONE, CT_PAREN_OPEN, CT_FUNC_TYPE, false);
+ }
+ set_chunk_type(pc, CT_TYPE);
+ set_chunk_type(tmp1, CT_PTR_TYPE);
+ chunk_flags_clr(pc, PCF_VAR_1ST_DEF);
+
+ if (tmp2->IsNotNullChunk())
+ {
+ chunk_flags_set(tmp2, PCF_VAR_1ST_DEF);
+ }
+ flag_parens(tmp, PCF_NONE, CT_FPAREN_OPEN, CT_FUNC_PROTO, false);
+ fix_fcn_def_params(tmp);
+ return;
+ }
+ LOG_FMT(LFCN, "%s(%d): chained function calls? Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ }
+
+ // Assume it is a function call if not already labeled
+ if (chunk_is_token(pc, CT_FUNCTION))
+ {
+ LOG_FMT(LFCN, "%s(%d): examine: Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, get_token_name(pc->type));
+ // look for an assigment. Issue #575
+ Chunk *temp = pc->GetNextType(CT_ASSIGN, pc->level);
+
+ if (temp->IsNotNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): assigment found, orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, temp->orig_line, temp->orig_col, temp->Text());
+ LOG_FMT(LFCN, "%s(%d): (10) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): (11) SET TO %s: orig_line is %zu, orig_col is %zu, Text() '%s'",
+ __func__, __LINE__, (get_chunk_parent_type(pc) == CT_OPERATOR) ? "CT_FUNC_DEF" : "CT_FUNC_CALL",
+ pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, (get_chunk_parent_type(pc) == CT_OPERATOR) ? CT_FUNC_DEF : CT_FUNC_CALL);
+ }
+ }
+ LOG_FMT(LFCN, "%s(%d): Check for C++ function def, Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, get_token_name(pc->type));
+
+ if (prev != nullptr)
+ {
+ LOG_FMT(LFCN, "%s(%d): prev->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col, get_token_name(prev->type));
+ }
+ else
+ {
+ prev = Chunk::NullChunkPtr;
+ }
+
+ // Check for C++ function def
+ if ( chunk_is_token(pc, CT_FUNC_CLASS_DEF)
+ || ( prev->IsNotNullChunk()
+ && ( chunk_is_token(prev, CT_INV)
+ || chunk_is_token(prev, CT_DC_MEMBER))))
+ {
+ Chunk *destr = Chunk::NullChunkPtr;
+
+ if (chunk_is_token(prev, CT_INV))
+ {
+ // TODO: do we care that this is the destructor?
+ set_chunk_type(prev, CT_DESTRUCTOR);
+ set_chunk_type(pc, CT_FUNC_CLASS_DEF);
+
+ set_chunk_parent(pc, CT_DESTRUCTOR);
+
+ destr = prev;
+ // Point to the item previous to the class name
+ prev = prev->GetPrevNcNnlNpp();
+ }
+
+ if (chunk_is_token(prev, CT_DC_MEMBER))
+ {
+ prev = prev->GetPrevNcNnlNpp();
+
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): prev->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col,
+ get_token_name(prev->type));
+ prev = skip_template_prev(prev);
+ LOG_FMT(LFCN, "%s(%d): prev->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col,
+ get_token_name(prev->type));
+ prev = skip_attribute_prev(prev);
+ LOG_FMT(LFCN, "%s(%d): prev->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col,
+ get_token_name(prev->type));
+ }
+
+ if ( chunk_is_token(prev, CT_WORD)
+ || chunk_is_token(prev, CT_TYPE))
+ {
+ if (pc->str.equals(prev->str))
+ {
+ LOG_FMT(LFCN, "%s(%d): pc->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col,
+ get_token_name(prev->type));
+ set_chunk_type(pc, CT_FUNC_CLASS_DEF);
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu - FOUND %sSTRUCTOR for '%s', type is %s\n",
+ __func__, __LINE__,
+ prev->orig_line, prev->orig_col,
+ (destr->IsNotNullChunk()) ? "DE" : "CON",
+ prev->Text(), get_token_name(prev->type));
+
+ mark_cpp_constructor(pc);
+ return;
+ }
+ // Point to the item previous to the class name
+ prev = prev->GetPrevNcNnlNpp();
+ }
+ }
+ }
+
+ /*
+ * Determine if this is a function call or a function def/proto
+ * We check for level==1 to allow the case that a function prototype is
+ * wrapped in a macro: "MACRO(void foo(void));"
+ */
+ if ( chunk_is_token(pc, CT_FUNC_CALL)
+ && ( pc->level == pc->brace_level
+ || pc->level == 1)
+ && !pc->flags.test(PCF_IN_ARRAY_ASSIGN))
+ {
+ bool isa_def = false;
+ bool hit_star = false;
+ LOG_FMT(LFCN, "%s(%d): pc->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col,
+ get_token_name(pc->type));
+
+ if (prev->IsNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): Checking func call: prev is null chunk\n",
+ __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): Checking func call: prev->Text() '%s', prev->type is %s\n",
+ __func__, __LINE__, prev->Text(), get_token_name(prev->type));
+ }
+ // if (!chunk_ends_type(prev))
+ // {
+ // goto bad_ret_type;
+ // }
+
+ /*
+ * REVISIT:
+ * a function def can only occur at brace level, but not inside an
+ * assignment, structure, enum, or union.
+ * The close paren must be followed by an open brace, with an optional
+ * qualifier (const) in between.
+ * There can be all sorts of template stuff and/or '[]' in the type.
+ * This hack mostly checks that.
+ *
+ * Examples:
+ * foo->bar(maid); -- fcn call
+ * FOO * bar(); -- fcn proto or class variable
+ * FOO foo(); -- fcn proto or class variable
+ * FOO foo(1); -- class variable
+ * a = FOO * bar(); -- fcn call
+ * a.y = foo() * bar(); -- fcn call
+ * static const char * const fizz(); -- fcn def
+ */
+ while (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): next step with: prev->orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text());
+
+ if (get_chunk_parent_type(pc) == CT_FIXED)
+ {
+ isa_def = true;
+ }
+
+ if (prev->flags.test(PCF_IN_PREPROC))
+ {
+ prev = prev->GetPrevNcNnlNpp();
+ continue;
+ }
+
+ // Some code slips an attribute between the type and function
+ if ( chunk_is_token(prev, CT_FPAREN_CLOSE)
+ && get_chunk_parent_type(prev) == CT_ATTRIBUTE)
+ {
+ prev = skip_attribute_prev(prev);
+ continue;
+ }
+
+ // skip const(TYPE)
+ if ( chunk_is_token(prev, CT_PAREN_CLOSE)
+ && get_chunk_parent_type(prev) == CT_D_CAST)
+ {
+ LOG_FMT(LFCN, "%s(%d): --> For sure a prototype or definition\n",
+ __func__, __LINE__);
+ isa_def = true;
+ break;
+ }
+
+ if (get_chunk_parent_type(prev) == CT_DECLSPEC) // Issue 1289
+ {
+ prev = chunk_skip_to_match_rev(prev);
+
+ if (prev != nullptr)
+ {
+ prev = prev->GetPrev();
+ }
+
+ if (chunk_is_token(prev, CT_DECLSPEC))
+ {
+ if ( prev != nullptr
+ && prev->IsNotNullChunk())
+ {
+ prev = prev->GetPrev();
+ }
+ }
+ }
+
+ // if it was determined that this could be a function definition
+ // but one of the preceding tokens is a CT_MEMBER than this is not a
+ // fcn def, issue #1466
+ if ( isa_def
+ && chunk_is_token(prev, CT_MEMBER))
+ {
+ isa_def = false;
+ }
+
+ // get first chunk before: A::B::pc | this.B.pc | this->B->pc
+ if ( chunk_is_token(prev, CT_DC_MEMBER)
+ || chunk_is_token(prev, CT_MEMBER))
+ {
+ while ( chunk_is_token(prev, CT_DC_MEMBER)
+ || chunk_is_token(prev, CT_MEMBER))
+ {
+ prev = prev->GetPrevNcNnlNpp();
+
+ if ( prev->IsNullChunk()
+ || ( chunk_is_not_token(prev, CT_WORD)
+ && chunk_is_not_token(prev, CT_TYPE)
+ && chunk_is_not_token(prev, CT_THIS)))
+ {
+ LOG_FMT(LFCN, "%s(%d): --? skipped MEMBER and landed on %s\n",
+ __func__, __LINE__, (prev->IsNullChunk()) ? "<null chunk>" : get_token_name(prev->type));
+ break;
+ }
+ LOG_FMT(LFCN, "%s(%d): <skip> '%s'\n",
+ __func__, __LINE__, prev->Text());
+
+ // Issue #1112
+ // clarification: this will skip the CT_WORD, CT_TYPE or CT_THIS landing on either
+ // another CT_DC_MEMBER or CT_MEMBER or a token that indicates the context of the
+ // token in question; therefore, exit loop when not a CT_DC_MEMBER or CT_MEMBER
+ prev = prev->GetPrevNcNnlNpp();
+
+ if (prev->IsNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): prev is null chunk\n",
+ __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text());
+ }
+ }
+
+ if (prev->IsNullChunk())
+ {
+ break;
+ }
+ }
+
+ // If we are on a TYPE or WORD, then this could be a proto or def
+ if ( chunk_is_token(prev, CT_TYPE)
+ || chunk_is_token(prev, CT_WORD))
+ {
+ if (!hit_star)
+ {
+ LOG_FMT(LFCN, "%s(%d): --> For sure a prototype or definition\n",
+ __func__, __LINE__);
+ isa_def = true;
+ break;
+ }
+ Chunk *prev_prev = prev->GetPrevNcNnlNpp();
+
+ if (!chunk_is_token(prev_prev, CT_QUESTION)) // Issue #1753
+ {
+ LOG_FMT(LFCN, "%s(%d): --> maybe a proto/def\n",
+ __func__, __LINE__);
+
+ LOG_FMT(LFCN, "%s(%d): prev is '%s', orig_line is %zu, orig_col is %zu, type is %s, parent_type is %s\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col,
+ get_token_name(prev->type), get_token_name(get_chunk_parent_type(prev)));
+ log_pcf_flags(LFCN, pc->flags);
+ isa_def = true;
+ }
+ }
+
+ if (chunk_is_ptr_operator(prev))
+ {
+ hit_star = true;
+ }
+
+ if ( chunk_is_not_token(prev, CT_OPERATOR)
+ && chunk_is_not_token(prev, CT_TSQUARE)
+ && chunk_is_not_token(prev, CT_ANGLE_CLOSE)
+ && chunk_is_not_token(prev, CT_QUALIFIER)
+ && chunk_is_not_token(prev, CT_TYPE)
+ && chunk_is_not_token(prev, CT_WORD)
+ && !chunk_is_ptr_operator(prev))
+ {
+ LOG_FMT(LFCN, "%s(%d): --> Stopping on prev is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col, get_token_name(prev->type));
+
+ // certain tokens are unlikely to precede a prototype or definition
+ if ( chunk_is_token(prev, CT_ARITH)
+ || chunk_is_token(prev, CT_SHIFT)
+ || chunk_is_token(prev, CT_ASSIGN)
+ || chunk_is_token(prev, CT_COMMA)
+ || ( chunk_is_token(prev, CT_STRING)
+ && get_chunk_parent_type(prev) != CT_EXTERN) // fixes issue 1259
+ || chunk_is_token(prev, CT_STRING_MULTI)
+ || chunk_is_token(prev, CT_NUMBER)
+ || chunk_is_token(prev, CT_NUMBER_FP)
+ || chunk_is_token(prev, CT_FPAREN_OPEN)) // issue #1464
+ {
+ isa_def = false;
+ }
+ break;
+ }
+
+ // Skip over template and attribute stuff
+ if (chunk_is_token(prev, CT_ANGLE_CLOSE))
+ {
+ prev = skip_template_prev(prev);
+ }
+ else
+ {
+ prev = prev->GetPrevNcNnlNpp();
+ }
+ }
+ //LOG_FMT(LFCN, " -- stopped on %s [%s]\n",
+ // prev->Text(), get_token_name(prev->type));
+
+ // Fixes issue #1634
+ if (chunk_is_paren_close(prev))
+ {
+ Chunk *preproc = prev->GetNextNcNnl();
+
+ if (chunk_is_token(preproc, CT_PREPROC))
+ {
+ size_t pp_level = preproc->pp_level;
+
+ if (chunk_is_token(preproc->GetNextNcNnl(), CT_PP_ELSE))
+ {
+ do
+ {
+ preproc = preproc->GetPrevNcNnlNi(); // Issue #2279
+
+ if (chunk_is_token(preproc, CT_PP_IF))
+ {
+ preproc = preproc->GetPrevNcNnlNi(); // Issue #2279
+
+ if (preproc->pp_level == pp_level)
+ {
+ prev = preproc->GetPrevNcNnlNpp();
+ break;
+ }
+ }
+ } while (preproc->IsNotNullChunk());
+ }
+ }
+ }
+
+ if ( isa_def
+ && prev != nullptr
+ && prev->IsNotNullChunk()
+ && ( ( chunk_is_paren_close(prev)
+ && get_chunk_parent_type(prev) != CT_D_CAST
+ && get_chunk_parent_type(prev) != CT_MACRO_OPEN // Issue #2726
+ && get_chunk_parent_type(prev) != CT_MACRO_CLOSE)
+ || chunk_is_token(prev, CT_ASSIGN)
+ || chunk_is_token(prev, CT_RETURN)))
+ {
+ LOG_FMT(LFCN, "%s(%d): -- overriding DEF due to prev is '%s', type is %s\n",
+ __func__, __LINE__, prev->Text(), get_token_name(prev->type));
+ isa_def = false;
+ }
+
+ // Fixes issue #1266, identification of a tuple return type in CS.
+ if ( !isa_def
+ && chunk_is_token(prev, CT_PAREN_CLOSE)
+ && prev->GetNextNcNnl() == pc)
+ {
+ tmp = chunk_skip_to_match_rev(prev);
+
+ if (tmp == nullptr)
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+
+ while ( tmp->IsNotNullChunk() // Issue #2315
+ && tmp != prev)
+ {
+ if ( chunk_is_token(tmp, CT_COMMA)
+ && tmp->level == prev->level + 1)
+ {
+ LOG_FMT(LFCN, "%s(%d): -- overriding call due to tuple return type -- prev is '%s', type is %s\n",
+ __func__, __LINE__, prev->Text(), get_token_name(prev->type));
+ isa_def = true;
+ break;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+
+ if (isa_def)
+ {
+ LOG_FMT(LFCN, "%s(%d): pc is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, get_token_name(pc->type));
+ LOG_FMT(LFCN, "%s(%d): (12) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_DEF);
+
+ if ( prev == nullptr
+ || prev->IsNullChunk())
+ {
+ prev = Chunk::GetHead();
+ }
+
+ for (tmp = prev; tmp->IsNotNullChunk() && tmp != pc; tmp = tmp->GetNextNcNnlNpp())
+ {
+ LOG_FMT(LFCN, "%s(%d): Text() is '%s', type is %s\n",
+ __func__, __LINE__, tmp->Text(), get_token_name(tmp->type));
+ make_type(tmp);
+ }
+ }
+ }
+
+ if (chunk_is_not_token(pc, CT_FUNC_DEF))
+ {
+ LOG_FMT(LFCN, "%s(%d): Detected type %s, Text() is '%s', on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, get_token_name(pc->type),
+ pc->Text(), pc->orig_line, pc->orig_col);
+
+ tmp = flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
+
+ if ( chunk_is_token(tmp, CT_BRACE_OPEN)
+ && get_chunk_parent_type(tmp) != CT_DOUBLE_BRACE)
+ {
+ set_paren_parent(tmp, pc->type);
+ }
+ return;
+ }
+ /*
+ * We have a function definition or prototype
+ * Look for a semicolon or a brace open after the close parenthesis to figure
+ * out whether this is a prototype or definition
+ */
+
+ // See if this is a prototype or implementation
+
+ // FIXME: this doesn't take the old K&R parameter definitions into account
+
+ // Scan tokens until we hit a brace open (def) or semicolon (proto)
+ tmp = paren_close->GetNextNcNnl();
+
+ while (tmp->IsNotNullChunk())
+ {
+ // Only care about brace or semicolon on the same level
+ if (tmp->level < pc->level)
+ {
+ // No semicolon - guess that it is a prototype
+ chunk_flags_clr(pc, PCF_VAR_1ST_DEF);
+ set_chunk_type(pc, CT_FUNC_PROTO);
+ break;
+ }
+ else if (tmp->level == pc->level)
+ {
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ // its a function def for sure
+ break;
+ }
+ else if (chunk_is_semicolon(tmp))
+ {
+ // Set the parent for the semicolon for later
+ semi = tmp;
+ chunk_flags_clr(pc, PCF_VAR_1ST_DEF);
+ set_chunk_type(pc, CT_FUNC_PROTO);
+ LOG_FMT(LFCN, "%s(%d): 2) Marked Text() is '%s', as FUNC_PROTO on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ break;
+ }
+ else if (chunk_is_token(pc, CT_COMMA))
+ {
+ set_chunk_type(pc, CT_FUNC_CTOR_VAR);
+ LOG_FMT(LFCN, "%s(%d): 2) Marked Text() is '%s', as FUNC_CTOR_VAR on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ break;
+ }
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ /*
+ * C++ syntax is wacky. We need to check to see if a prototype is really a
+ * variable definition with parameters passed into the constructor.
+ * Unfortunately, without being able to accurately determine if an
+ * identifier is a type (which would require us to more or less be a full
+ * compiler), the only mostly reliable way to do so is to guess that it is
+ * a constructor variable if inside a function body and scan the 'parameter
+ * list' for items that are not allowed in a prototype. We search backwards
+ * and checking the parent of the containing open braces. If the parent is a
+ * class or namespace, then it probably is a prototype.
+ */
+ if ( language_is_set(LANG_CPP)
+ && chunk_is_token(pc, CT_FUNC_PROTO)
+ && get_chunk_parent_type(pc) != CT_OPERATOR)
+ {
+ LOG_FMT(LFPARAM, "%s(%d):", __func__, __LINE__);
+ LOG_FMT(LFPARAM, " checking '%s' for constructor variable %s %s\n",
+ pc->Text(),
+ get_token_name(paren_open->type),
+ get_token_name(paren_close->type));
+
+ /*
+ * Check the token at the start of the statement. If it's 'extern', we
+ * definitely have a function prototype.
+ */
+ tmp = pc;
+
+ while ( tmp->IsNotNullChunk()
+ && !tmp->flags.test(PCF_STMT_START))
+ {
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+ }
+ const bool is_extern = ( tmp->IsNotNullChunk()
+ && tmp->str.equals("extern"));
+
+ /*
+ * Scan the parameters looking for:
+ * - constant strings
+ * - numbers
+ * - non-type fields
+ * - function calls
+ */
+ Chunk *ref = paren_open->GetNextNcNnl();
+ Chunk *tmp2;
+ bool is_param = true;
+ tmp = ref;
+
+ while (tmp != paren_close)
+ {
+ tmp2 = tmp->GetNextNcNnl();
+
+ if ( chunk_is_token(tmp, CT_COMMA)
+ && (tmp->level == (paren_open->level + 1)))
+ {
+ if (!can_be_full_param(ref, tmp))
+ {
+ is_param = false;
+ break;
+ }
+ ref = tmp2;
+ }
+ tmp = tmp2;
+ }
+
+ if ( !is_extern
+ && is_param
+ && ref != tmp)
+ {
+ if (!can_be_full_param(ref, tmp))
+ {
+ is_param = false;
+ }
+ }
+
+ if ( !is_extern
+ && !is_param)
+ {
+ set_chunk_type(pc, CT_FUNC_CTOR_VAR);
+ LOG_FMT(LFCN, "%s(%d): 3) Marked Text() '%s' as FUNC_CTOR_VAR on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ }
+ else if (pc->brace_level > 0)
+ {
+ Chunk *br_open = pc->GetPrevType(CT_BRACE_OPEN, pc->brace_level - 1);
+
+ if ( br_open->IsNotNullChunk()
+ && get_chunk_parent_type(br_open) != CT_EXTERN
+ && get_chunk_parent_type(br_open) != CT_NAMESPACE)
+ {
+ // Do a check to see if the level is right
+ prev = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( !chunk_is_str(prev, "*")
+ && !chunk_is_str(prev, "&"))
+ {
+ Chunk *p_op = pc->GetPrevType(CT_BRACE_OPEN, pc->brace_level - 1);
+
+ if ( p_op->IsNotNullChunk()
+ && get_chunk_parent_type(p_op) != CT_CLASS
+ && get_chunk_parent_type(p_op) != CT_STRUCT
+ && get_chunk_parent_type(p_op) != CT_NAMESPACE)
+ {
+ set_chunk_type(pc, CT_FUNC_CTOR_VAR);
+ LOG_FMT(LFCN, "%s(%d): 4) Marked Text() is'%s', as FUNC_CTOR_VAR on orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ }
+ }
+ }
+ }
+ }
+
+ if (semi != nullptr)
+ {
+ set_chunk_parent(semi, pc->type);
+ }
+
+ // Issue # 1403, 2152
+ if (chunk_is_token(paren_open->prev, CT_FUNC_CTOR_VAR))
+ {
+ flag_parens(paren_open, PCF_IN_FCN_CTOR, CT_FPAREN_OPEN, pc->type, false);
+ }
+ else
+ {
+ flag_parens(paren_open, PCF_IN_FCN_DEF, CT_FPAREN_OPEN, pc->type, false);
+ }
+ //flag_parens(paren_open, PCF_IN_FCN_DEF, CT_FPAREN_OPEN, pc->type, true);
+
+ if (chunk_is_token(pc, CT_FUNC_CTOR_VAR))
+ {
+ chunk_flags_set(pc, PCF_VAR_1ST_DEF);
+ return;
+ }
+
+ if (chunk_is_token(next, CT_TSQUARE))
+ {
+ next = next->GetNextNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ }
+ // Mark parameters and return type
+ fix_fcn_def_params(next);
+ mark_function_return_type(pc, pc->GetPrevNcNnlNi(), pc->type); // Issue #2279
+
+ /* mark C# where chunk */
+ if ( language_is_set(LANG_CS)
+ && ( (chunk_is_token(pc, CT_FUNC_DEF))
+ || (chunk_is_token(pc, CT_FUNC_PROTO))))
+ {
+ tmp = paren_close->GetNextNcNnl();
+ pcf_flags_t in_where_spec_flags = PCF_NONE;
+
+ while ( tmp->IsNotNullChunk()
+ && chunk_is_not_token(tmp, CT_BRACE_OPEN)
+ && chunk_is_not_token(tmp, CT_SEMICOLON))
+ {
+ mark_where_chunk(tmp, pc->type, tmp->flags | in_where_spec_flags);
+ in_where_spec_flags = tmp->flags & PCF_IN_WHERE_SPEC;
+
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+
+ // Find the brace pair and set the parent
+ if (chunk_is_token(pc, CT_FUNC_DEF))
+ {
+ tmp = paren_close->GetNextNcNnl();
+
+ while ( tmp->IsNotNullChunk()
+ && chunk_is_not_token(tmp, CT_BRACE_OPEN))
+ {
+ LOG_FMT(LFCN, "%s(%d): (13) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+ set_chunk_parent(tmp, CT_FUNC_DEF);
+
+ if (!chunk_is_semicolon(tmp))
+ {
+ chunk_flags_set(tmp, PCF_OLD_FCN_PARAMS);
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ LOG_FMT(LFCN, "%s(%d): (14) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+ set_chunk_parent(tmp, CT_FUNC_DEF);
+ tmp = chunk_skip_to_match(tmp);
+
+ if (tmp != nullptr)
+ {
+ LOG_FMT(LFCN, "%s(%d): (15) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+ set_chunk_parent(tmp, CT_FUNC_DEF);
+ }
+ }
+ }
+} // mark_function
+
+
+bool mark_function_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LFTYPE, "%s(%d): type is %s, Text() '%s' @ orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), pc->Text(),
+ pc->orig_line, pc->orig_col);
+
+ size_t star_count = 0;
+ size_t word_count = 0;
+ Chunk *ptrcnk = nullptr;
+ Chunk *tmp;
+ Chunk *apo;
+ Chunk *apc;
+ Chunk *aft;
+ bool anon = false;
+ E_Token pt, ptp;
+
+ // Scan backwards across the name, which can only be a word and single star
+ Chunk *varcnk = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ varcnk = chunk_get_prev_ssq(varcnk);
+
+ if ( varcnk->IsNotNullChunk()
+ && !chunk_is_word(varcnk))
+ {
+ if ( language_is_set(LANG_OC)
+ && chunk_is_str(varcnk, "^")
+ && chunk_is_paren_open(varcnk->GetPrevNcNnlNi())) // Issue #2279
+ {
+ // anonymous ObjC block type -- RTYPE (^)(ARGS)
+ anon = true;
+ }
+ else
+ {
+ LOG_FMT(LFTYPE, "%s(%d): not a word: Text() '%s', type is %s, @ orig_line is %zu:, orig_col is %zu\n",
+ __func__, __LINE__, varcnk->Text(), get_token_name(varcnk->type),
+ varcnk->orig_line, varcnk->orig_col);
+ goto nogo_exit;
+ }
+ }
+ apo = pc->GetNextNcNnl();
+
+ if (apo->IsNullChunk())
+ {
+ return(false);
+ }
+ apc = chunk_skip_to_match(apo);
+
+ if ( apc != nullptr
+ && ( !chunk_is_paren_open(apo)
+ || ((apc = chunk_skip_to_match(apo)) == nullptr)))
+ {
+ LOG_FMT(LFTYPE, "%s(%d): not followed by parens\n", __func__, __LINE__);
+ goto nogo_exit;
+ }
+ aft = apc->GetNextNcNnl();
+
+ if (chunk_is_token(aft, CT_BRACE_OPEN))
+ {
+ pt = CT_FUNC_DEF;
+ }
+ else if ( chunk_is_token(aft, CT_SEMICOLON)
+ || chunk_is_token(aft, CT_ASSIGN))
+ {
+ pt = CT_FUNC_PROTO;
+ }
+ else
+ {
+ LOG_FMT(LFTYPE, "%s(%d): not followed by '{' or ';'\n", __func__, __LINE__);
+ goto nogo_exit;
+ }
+ ptp = pc->flags.test(PCF_IN_TYPEDEF) ? CT_FUNC_TYPE : CT_FUNC_VAR;
+
+ tmp = pc;
+
+ while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ tmp = chunk_get_prev_ssq(tmp);
+
+ LOG_FMT(LFTYPE, " -- type is %s, %s on orig_line %zu, orig_col is %zu",
+ get_token_name(tmp->type), tmp->Text(),
+ tmp->orig_line, tmp->orig_col);
+
+ if ( tmp->IsStar()
+ || chunk_is_token(tmp, CT_PTR_TYPE)
+ || chunk_is_token(tmp, CT_CARET))
+ {
+ star_count++;
+ ptrcnk = tmp;
+ LOG_FMT(LFTYPE, " -- PTR_TYPE\n");
+ }
+ else if ( chunk_is_word(tmp)
+ || chunk_is_token(tmp, CT_WORD)
+ || chunk_is_token(tmp, CT_TYPE))
+ {
+ word_count++;
+ LOG_FMT(LFTYPE, " -- TYPE(%s)\n", tmp->Text());
+ }
+ else if (chunk_is_token(tmp, CT_DC_MEMBER))
+ {
+ word_count = 0;
+ LOG_FMT(LFTYPE, " -- :: reset word_count\n");
+ }
+ else if (chunk_is_str(tmp, "("))
+ {
+ LOG_FMT(LFTYPE, " -- open paren (break)\n");
+ break;
+ }
+ else
+ {
+ LOG_FMT(LFTYPE, " -- unexpected token: type is %s, Text() '%s', on orig_line %zu, orig_col %zu\n",
+ get_token_name(tmp->type), tmp->Text(),
+ tmp->orig_line, tmp->orig_col);
+ goto nogo_exit;
+ }
+ }
+
+ // Fixes #issue 1577
+ // Allow word count 2 incase of function pointer declaration.
+ // Ex: bool (__stdcall* funcptr)(int, int);
+ if ( star_count > 1
+ || ( word_count > 1
+ && !( word_count == 2
+ && ptp == CT_FUNC_VAR))
+ || ((star_count + word_count) == 0))
+ {
+ LOG_FMT(LFTYPE, "%s(%d): bad counts word: %zu, star: %zu\n",
+ __func__, __LINE__, word_count, star_count);
+ goto nogo_exit;
+ }
+
+ // make sure what appears before the first open paren can be a return type
+ if (!chunk_ends_type(tmp->GetPrevNcNnlNi())) // Issue #2279
+ {
+ goto nogo_exit;
+ }
+
+ if (ptrcnk)
+ {
+ set_chunk_type(ptrcnk, CT_PTR_TYPE);
+ }
+
+ if (!anon)
+ {
+ if (pc->flags.test(PCF_IN_TYPEDEF))
+ {
+ set_chunk_type(varcnk, CT_FUNC_TYPE); // Issue #3402
+ }
+ else
+ {
+ set_chunk_type(varcnk, CT_FUNC_VAR);
+ chunk_flags_set(varcnk, PCF_VAR_1ST_DEF);
+ }
+ }
+ set_chunk_type(pc, CT_TPAREN_CLOSE);
+ set_chunk_parent(pc, ptp);
+
+ set_chunk_type(apo, CT_FPAREN_OPEN);
+ set_chunk_parent(apo, pt);
+ set_chunk_type(apc, CT_FPAREN_CLOSE);
+ set_chunk_parent(apc, pt);
+ fix_fcn_def_params(apo);
+
+ if (chunk_is_semicolon(aft))
+ {
+ set_chunk_parent(aft, aft->flags.test(PCF_IN_TYPEDEF) ? CT_TYPEDEF : CT_FUNC_VAR);
+ }
+ else if (chunk_is_token(aft, CT_BRACE_OPEN))
+ {
+ flag_parens(aft, PCF_NONE, CT_NONE, pt, false);
+ }
+ // Step backwards to the previous open paren and mark everything a
+ tmp = pc;
+
+ while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ LOG_FMT(LFTYPE, " ++ type is %s, Text() '%s', on orig_line %zu, orig_col %zu\n",
+ get_token_name(tmp->type), tmp->Text(),
+ tmp->orig_line, tmp->orig_col);
+
+ if (*tmp->str.c_str() == '(')
+ {
+ if (!pc->flags.test(PCF_IN_TYPEDEF))
+ {
+ chunk_flags_set(tmp, PCF_VAR_1ST_DEF);
+ }
+ set_chunk_type(tmp, CT_TPAREN_OPEN);
+ set_chunk_parent(tmp, ptp);
+
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( chunk_is_token(tmp, CT_FUNCTION)
+ || chunk_is_token(tmp, CT_FUNC_CALL)
+ || chunk_is_token(tmp, CT_FUNC_CALL_USER)
+ || chunk_is_token(tmp, CT_FUNC_DEF)
+ || chunk_is_token(tmp, CT_FUNC_PROTO))
+ {
+ set_chunk_type(tmp, CT_TYPE);
+ chunk_flags_clr(tmp, PCF_VAR_1ST_DEF);
+ }
+ mark_function_return_type(varcnk, tmp, ptp);
+ break;
+ }
+ }
+ return(true);
+
+nogo_exit:
+ tmp = pc->GetNextNcNnl();
+
+ if (chunk_is_paren_open(tmp))
+ {
+ LOG_FMT(LFTYPE, "%s(%d): setting FUNC_CALL on orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col);
+ flag_parens(tmp, PCF_NONE, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
+ }
+ return(false);
+} // mark_function_type
+
+
+void mark_lvalue(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *prev;
+
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ return;
+ }
+
+ for (prev = pc->GetPrevNcNnlNi(); // Issue #2279
+ prev->IsNotNullChunk();
+ prev = prev->GetPrevNcNnlNi()) // Issue #2279
+ {
+ if ( prev->level < pc->level
+ || chunk_is_token(prev, CT_ACCESS_COLON)
+ || chunk_is_token(prev, CT_ASSIGN)
+ || chunk_is_token(prev, CT_BOOL)
+ || chunk_is_token(prev, CT_COMMA)
+ || chunk_is_cpp_inheritance_access_specifier(prev)
+ || chunk_is_semicolon(prev)
+ || chunk_is_str(prev, "(")
+ || chunk_is_str(prev, "{")
+ || chunk_is_str(prev, "[")
+ || prev->flags.test(PCF_IN_PREPROC)
+ || get_chunk_parent_type(prev) == CT_NAMESPACE
+ || get_chunk_parent_type(prev) == CT_TEMPLATE)
+ {
+ break;
+ }
+ chunk_flags_set(prev, PCF_LVALUE);
+
+ if ( prev->level == pc->level
+ && chunk_is_str(prev, "&"))
+ {
+ make_type(prev);
+ }
+ }
+} // mark_lvalue
+
+
+void mark_struct_union_body(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = start;
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= start->level
+ && !( pc->level == start->level
+ && chunk_is_token(pc, CT_BRACE_CLOSE)))
+ {
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_SEMICOLON))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNullChunk())
+ {
+ break;
+ }
+ }
+
+ if (chunk_is_token(pc, CT_ALIGN))
+ {
+ pc = skip_align(pc); // "align(x)" or "align(x):"
+
+ if (pc->IsNullChunk())
+ {
+ break;
+ }
+ }
+ else if (chunk_is_token(pc, CT_AMP))
+ {
+ pc = skip_expression(pc);
+ }
+ else
+ {
+ pc = fix_variable_definition(pc);
+
+ if (pc->IsNullChunk())
+ {
+ break;
+ }
+ }
+ }
+} // mark_struct_union_body
+
+
+void mark_template_func(Chunk *pc, Chunk *pc_next)
+{
+ LOG_FUNC_ENTRY();
+
+ // We know angle_close must be there...
+ Chunk *angle_close = pc_next->GetNextType(CT_ANGLE_CLOSE, pc->level);
+ Chunk *after = angle_close->GetNextNcNnl();
+
+ if (after->IsNotNullChunk())
+ {
+ if (chunk_is_str(after, "("))
+ {
+ if (angle_close->flags.test(PCF_IN_FCN_CALL))
+ {
+ LOG_FMT(LTEMPFUNC, "%s(%d): marking '%s' in line %zu as a FUNC_CALL\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ LOG_FMT(LFCN, "%s(%d): (16) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ flag_parens(after, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
+ }
+ else
+ {
+ /*
+ * Might be a function def. Must check what is before the template:
+ * Func call:
+ * BTree.Insert(std::pair<int, double>(*it, double(*it) + 1.0));
+ * a = Test<int>(j);
+ * std::pair<int, double>(*it, double(*it) + 1.0));
+ */
+
+ LOG_FMT(LTEMPFUNC, "%s(%d): marking '%s' in line %zu as a FUNC_CALL 2\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ // its a function!!!
+ LOG_FMT(LFCN, "%s(%d): (17) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ set_chunk_type(pc, CT_FUNC_CALL);
+ mark_function(pc);
+ }
+ }
+ else if (chunk_is_token(after, CT_WORD))
+ {
+ // its a type!
+ set_chunk_type(pc, CT_TYPE);
+ chunk_flags_set(pc, PCF_VAR_TYPE);
+ chunk_flags_set(after, PCF_VAR_DEF);
+ }
+ }
+} // mark_template_func
+
+
+Chunk *mark_variable_definition(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start == nullptr)
+ {
+ return(nullptr);
+ }
+ Chunk *pc = start;
+ pcf_flags_t flags = PCF_VAR_1ST_DEF;
+
+ LOG_FMT(LVARDEF, "%s(%d): orig_line %zu, orig_col %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ get_token_name(pc->type));
+
+ // Issue #596
+ bool bit_field_colon_is_present = false;
+
+ while (go_on(pc, start))
+ {
+ if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_FUNC_CTOR_VAR))
+ {
+ auto const orig_flags = pc->flags;
+
+ if (!pc->flags.test(PCF_IN_ENUM))
+ {
+ chunk_flags_set(pc, flags);
+ }
+ flags &= ~PCF_VAR_1ST;
+ LOG_FMT(LVARDEF, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', set PCF_VAR_1ST\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ LOG_FMT(LVARDEF,
+ "%s(%d): orig_line is %zu, marked Text() '%s'[%s]\n"
+ " in orig_col %zu, flags: %s -> %s\n",
+ __func__, __LINE__, pc->orig_line, pc->Text(),
+ get_token_name(pc->type), pc->orig_col,
+ pcf_flags_str(orig_flags).c_str(),
+ pcf_flags_str(pc->flags).c_str());
+ }
+ else if ( !bit_field_colon_is_present // Issue #2689
+ && ( pc->IsStar()
+ || chunk_is_msref(pc)))
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if (chunk_is_addr(pc))
+ {
+ set_chunk_type(pc, CT_BYREF);
+ }
+ else if ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ || chunk_is_token(pc, CT_ASSIGN))
+ {
+ pc = skip_expression(pc);
+ continue;
+ }
+ else if (chunk_is_token(pc, CT_COLON))
+ {
+ bit_field_colon_is_present = true; // Issue #2689
+ }
+ pc = pc->GetNextNcNnl();
+ }
+ return(pc);
+} // mark_variable_definition
+
+
+void mark_variable_stack(ChunkStack &cs, log_sev_t sev)
+{
+ UNUSED(sev);
+ LOG_FUNC_ENTRY();
+
+ // throw out the last word and mark the rest
+ Chunk *var_name = cs.Pop_Back();
+
+ if ( var_name != nullptr
+ && var_name->GetPrev()->IsNotNullChunk()
+ && var_name->GetPrev()->type == CT_DC_MEMBER)
+ {
+ cs.Push_Back(var_name);
+ }
+
+ if (var_name != nullptr)
+ {
+ LOG_FMT(LFCNP, "%s(%d): parameter on orig_line %zu, orig_col %zu:\n",
+ __func__, __LINE__, var_name->orig_line, var_name->orig_col);
+
+ size_t word_cnt = 0;
+ Chunk *word_type;
+
+ while ((word_type = cs.Pop_Back()) != nullptr)
+ {
+ if ( chunk_is_token(word_type, CT_WORD)
+ || chunk_is_token(word_type, CT_TYPE))
+ {
+ LOG_FMT(LFCNP, "%s(%d): parameter on orig_line %zu, orig_col %zu: <%s> as TYPE\n",
+ __func__, __LINE__, var_name->orig_line, var_name->orig_col, word_type->Text());
+ set_chunk_type(word_type, CT_TYPE);
+ chunk_flags_set(word_type, PCF_VAR_TYPE);
+ }
+ word_cnt++;
+ }
+
+ if (chunk_is_token(var_name, CT_WORD))
+ {
+ if (word_cnt > 0)
+ {
+ LOG_FMT(LFCNP, "%s(%d): parameter on orig_line %zu, orig_col %zu: <%s> as VAR\n",
+ __func__, __LINE__, var_name->orig_line, var_name->orig_col, var_name->Text());
+ chunk_flags_set(var_name, PCF_VAR_DEF);
+ }
+ else
+ {
+ LOG_FMT(LFCNP, "%s(%d): parameter on orig_line %zu, orig_col %zu: <%s> as TYPE\n",
+ __func__, __LINE__, var_name->orig_line, var_name->orig_col, var_name->Text());
+ set_chunk_type(var_name, CT_TYPE);
+ chunk_flags_set(var_name, PCF_VAR_TYPE);
+ }
+ }
+ }
+} // mark_variable_stack
+
+
+pcf_flags_t mark_where_chunk(Chunk *pc, E_Token parent_type, pcf_flags_t flags)
+{
+ /* TODO: should have options to control spacing around the ':' as well as newline ability for the
+ * constraint clauses (should it break up a 'where A : B where C : D' on the same line? wrap? etc.) */
+
+ if (chunk_is_token(pc, CT_WHERE))
+ {
+ set_chunk_type(pc, CT_WHERE_SPEC);
+ set_chunk_parent(pc, parent_type);
+ flags |= PCF_IN_WHERE_SPEC;
+ LOG_FMT(LFTOR, "%s: where-spec on line %zu\n",
+ __func__, pc->orig_line);
+ }
+ else if (flags.test(PCF_IN_WHERE_SPEC))
+ {
+ if (chunk_is_str(pc, ":"))
+ {
+ set_chunk_type(pc, CT_WHERE_COLON);
+ LOG_FMT(LFTOR, "%s: where-spec colon on line %zu\n",
+ __func__, pc->orig_line);
+ }
+ else if ( (chunk_is_token(pc, CT_STRUCT))
+ || (chunk_is_token(pc, CT_CLASS)))
+ {
+ /* class/struct inside of a where-clause confuses parser for indentation; set it as a word so it looks like the rest */
+ set_chunk_type(pc, CT_WORD);
+ }
+ }
+
+ if (flags.test(PCF_IN_WHERE_SPEC))
+ {
+ chunk_flags_set(pc, PCF_IN_WHERE_SPEC);
+ }
+ return(flags);
+} // mark_where_chunk
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.h
new file mode 100644
index 00000000..4671fbb3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_fix_mark.h
@@ -0,0 +1,196 @@
+/**
+ * @file combine_fix_mark.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#ifndef COMBINE_FIX_MARK_H_INCLUDED
+#define COMBINE_FIX_MARK_H_INCLUDED
+
+#include "ChunkStack.h"
+
+
+/**
+ * Checks to see if the current paren is part of a cast.
+ * We already verified that this doesn't follow function, TYPE, IF, FOR,
+ * SWITCH, or WHILE and is followed by WORD, TYPE, STRUCT, ENUM, or UNION.
+ *
+ * @param start Pointer to the open paren
+ */
+void fix_casts(Chunk *start);
+
+
+/**
+ * Simply change any STAR to PTR_TYPE and WORD to TYPE
+ *
+ * @param start points to the open paren
+ */
+void fix_fcn_def_params(Chunk *start);
+
+
+/**
+ * CT_TYPE_CAST follows this pattern:
+ * dynamic_cast<...>(...)
+ *
+ * Mark everything between the <> as a type and set the paren parent
+ */
+void fix_type_cast(Chunk *start);
+
+
+/**
+ * We are on a typedef.
+ * If the next word is not enum/union/struct, then the last word before the
+ * next ',' or ';' or '__attribute__' is a type.
+ *
+ * typedef [type...] [*] type [, [*]type] ;
+ * typedef <return type>([*]func)();
+ * typedef <return type>([*]func)(params);
+ * typedef <return type>(__stdcall *func)(); Bug # 633 MS-specific extension
+ * include the config-file "test/config/MS-calling_conventions.cfg"
+ * typedef <return type>func(params);
+ * typedef <enum/struct/union> [type] [*] type [, [*]type] ;
+ * typedef <enum/struct/union> [type] { ... } [*] type [, [*]type] ;
+ */
+void fix_typedef(Chunk *start);
+
+
+/**
+ * We are on the start of a sequence that could be a variable definition
+ * - FPAREN_OPEN (parent == CT_FOR)
+ * - BRACE_OPEN
+ * - SEMICOLON
+ */
+Chunk *fix_variable_definition(Chunk *start);
+
+
+void mark_cpp_constructor(Chunk *pc);
+
+
+/**
+ * Mark all chunks belonging to a C++ lambda expression
+ *
+ * @param square_open points to a chunk of type CT_SQUARE_OPEN, and the parent type is
+ * assumed to have already been assigned the value CT_CPP_LAMBDA;
+ * under this assumption, the function marks all chunks as PCF_IN_LAMBDA
+ * until the corresponding closing CT_BRACE_CLOSE (with parent type
+ * CT_CPP_LAMBDA) is encountered
+ */
+void mark_cpp_lambda(Chunk *square_open);
+
+
+/**
+ * Marks statement starts in a macro body.
+ * REVISIT: this may already be done
+ */
+void mark_define_expressions(void);
+
+
+/**
+ * Just mark every CT_WORD until a semicolon as CT_SQL_WORD.
+ * Adjust the levels if pc is CT_SQL_BEGIN
+ */
+void mark_exec_sql(Chunk *pc);
+
+
+/**
+ * Changes the return type to type and set the parent.
+ *
+ * @param pc the last chunk of the return type
+ * @param parent_type CT_NONE (no change) or the new parent type
+ */
+void mark_function_return_type(Chunk *fname, Chunk *start, E_Token parent_type);
+
+
+/**
+ * We are on a function word. we need to:
+ * - find out if this is a call or prototype or implementation
+ * - mark return type
+ * - mark parameter types
+ * - mark brace pair
+ *
+ * REVISIT:
+ * This whole function is a mess.
+ * It needs to be reworked to eliminate duplicate logic and determine the
+ * function type more directly.
+ * 1. Skip to the close paren and see what is after.
+ * a. semicolon - function call or function proto
+ * b. open brace - function call (ie, list_for_each) or function def
+ * c. open paren - function type or chained function call
+ * d. qualifier - function def or proto, continue to semicolon or open brace
+ * 2. Examine the 'parameters' to see if it can be a proto/def
+ * 3. Examine what is before the function name to see if it is a proto or call
+ * Constructor/destructor detection should have already been done when the
+ * 'class' token was encountered (see mark_class_ctor).
+ */
+void mark_function(Chunk *pc);
+
+
+/**
+ * Process a function type that is not in a typedef.
+ * pc points to the first close paren.
+ *
+ * void (*func)(params);
+ * const char * (*func)(params);
+ * const char * (^func)(params); -- Objective C
+ *
+ * @param pc Points to the first closing paren
+ *
+ * @return whether a function type was processed
+ */
+bool mark_function_type(Chunk *pc);
+
+
+/**
+ * Just hit an assign. Go backwards until we hit an open brace/paren/square or
+ * semicolon (TODO: other limiter?) and mark as a LValue.
+ */
+void mark_lvalue(Chunk *pc);
+
+
+/**
+ * Examines the stuff between braces { }.
+ * There should only be variable definitions and methods.
+ * Skip the methods, as they will get handled elsewhere.
+ */
+void mark_struct_union_body(Chunk *start);
+
+
+/**
+ * We are on a word followed by a angle open which is part of a template.
+ * If the angle close is followed by a open paren, then we are on a template
+ * function def or a template function call:
+ * Vector2<float>(...) [: ...[, ...]] { ... }
+ * Or we could be on a variable def if it's followed by a word:
+ * Renderer<rgb32> rend;
+ */
+void mark_template_func(Chunk *pc, Chunk *pc_next);
+
+
+/**
+ * We are on the first word of a variable definition.
+ * Mark all the variable names with PCF_VAR_1ST and PCF_VAR_DEF as appropriate.
+ * Also mark any '*' encountered as a CT_PTR_TYPE.
+ * Skip over []. Go until a ';' is hit.
+ *
+ * Example input:
+ * int a = 3, b, c = 2; ## called with 'a'
+ * foo_t f = {1, 2, 3}, g = {5, 6, 7}; ## called with 'f'
+ * struct {...} *a, *b; ## called with 'a' or '*'
+ * myclass a(4);
+ */
+Chunk *mark_variable_definition(Chunk *start);
+
+
+void mark_variable_stack(ChunkStack &cs, log_sev_t sev);
+
+
+/**
+ * TODO: add doc cmt
+ *
+ */
+pcf_flags_t mark_where_chunk(Chunk *pc, E_Token parent_type, pcf_flags_t flags);
+
+
+#endif /* COMBINE_FIX_MARK_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.cpp
new file mode 100644
index 00000000..72e91b1a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.cpp
@@ -0,0 +1,443 @@
+/**
+ * @file combine_labels.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.h
+ */
+
+#include "combine_labels.h"
+
+#include "chunk.h"
+#include "cs_top_is_question.h"
+#include "uncrustify.h"
+
+
+Chunk *chunk_get_next_local(Chunk *pc, E_Scope scope = E_Scope::ALL)
+{
+ Chunk *tmp = pc;
+
+ if (tmp == nullptr)
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+
+ do
+ {
+ tmp = tmp->GetNext(scope);
+ } while ( tmp->IsNotNullChunk()
+ && ( tmp->IsComment()
+ || chunk_is_token(tmp, CT_NOEXCEPT)));
+
+ return(tmp);
+}
+
+
+Chunk *chunk_get_prev_local(Chunk *pc, E_Scope scope = E_Scope::ALL)
+{
+ Chunk *tmp = pc;
+
+ if (tmp == nullptr)
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+
+ do
+ {
+ tmp = tmp->GetPrev(scope);
+ } while ( tmp->IsNotNullChunk()
+ && ( tmp->IsComment()
+ || chunk_is_newline(tmp)
+ || chunk_is_token(tmp, CT_NOEXCEPT)));
+
+ return(tmp);
+}
+
+
+void combine_labels(void)
+{
+ LOG_FUNC_ENTRY();
+ bool hit_case = false;
+ bool hit_class = false;
+
+ cpd.unc_stage = unc_stage_e::COMBINE_LABELS;
+
+ // stack to handle nesting inside of OC messages, which reset the scope
+ ChunkStack cs;
+
+ Chunk *prev = Chunk::GetHead();
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *cur = prev->GetNextNc();
+
+ if (cur->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *next = cur->GetNextNc();
+
+ // unlikely that the file will start with a label...
+ // prev cur next
+ while ( next != nullptr
+ && next->IsNotNullChunk())
+ {
+ if (chunk_is_token(next, CT_NEWLINE))
+ {
+ LOG_FMT(LFCN, "%s(%d): next->orig_line is %zu, next->orig_col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, next->nl_count);
+ }
+ else if (chunk_is_token(next, CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LFCN, "%s(%d): next->orig_line is %zu, next->orig_col is %zu, VBRACE_OPEN\n",
+ __func__, __LINE__, next->orig_line, next->orig_col);
+ }
+ else if (chunk_is_token(next, CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LFCN, "%s(%d): next->orig_line is %zu, next->orig_col is %zu, VBRACE_CLOSE\n",
+ __func__, __LINE__, next->orig_line, next->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): next->orig_line is %zu, next->orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, next->Text());
+ }
+
+ if ( !next->flags.test(PCF_IN_OC_MSG) // filter OC case of [self class] msg send
+ && ( chunk_is_token(next, CT_CLASS)
+ || chunk_is_token(next, CT_OC_CLASS)
+ || chunk_is_token(next, CT_TEMPLATE)))
+ {
+ hit_class = true;
+ }
+
+ if ( chunk_is_semicolon(next)
+ || chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ hit_class = false;
+ }
+
+ if ( chunk_is_token(prev, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(prev) == CT_OC_MSG)
+ {
+ cs.Push_Back(prev);
+ }
+ else if ( chunk_is_token(next, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(next) == CT_OC_MSG)
+ {
+ // pop until we hit '['
+ while (!cs.Empty())
+ {
+ Chunk *t2 = cs.Top()->m_pc;
+ cs.Pop_Back();
+
+ if (chunk_is_token(t2, CT_SQUARE_OPEN))
+ {
+ break;
+ }
+ }
+ }
+
+ if ( chunk_is_token(next, CT_QUESTION)
+ && !next->flags.test(PCF_IN_TEMPLATE))
+ {
+ cs.Push_Back(next);
+ }
+ else if (chunk_is_token(next, CT_CASE))
+ {
+ if (chunk_is_token(cur, CT_GOTO))
+ {
+ // handle "goto case x;"
+ set_chunk_type(next, CT_QUALIFIER);
+ }
+ else
+ {
+ hit_case = true;
+ }
+ }
+ else if ( chunk_is_token(next, CT_COLON)
+ || ( chunk_is_token(next, CT_OC_COLON)
+ && cs_top_is_question(cs, next->level)))
+ {
+ if (chunk_is_token(cur, CT_DEFAULT))
+ {
+ set_chunk_type(cur, CT_CASE);
+ hit_case = true;
+ }
+
+ if (cs_top_is_question(cs, next->level))
+ {
+ set_chunk_type(next, CT_COND_COLON);
+ cs.Pop_Back();
+ }
+ else if (hit_case)
+ {
+ hit_case = false;
+ set_chunk_type(next, CT_CASE_COLON);
+ Chunk *tmp = next->GetNextNcNnlNpp(); // Issue #2150
+
+ if (chunk_is_token(tmp, CT_BRACE_OPEN))
+ {
+ set_chunk_parent(tmp, CT_CASE);
+ tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_parent(tmp, CT_CASE);
+ }
+ }
+
+ if ( chunk_is_token(cur, CT_NUMBER)
+ && chunk_is_token(prev, CT_ELLIPSIS))
+ {
+ Chunk *pre_elipsis = prev->GetPrevNcNnlNpp();
+
+ if (chunk_is_token(pre_elipsis, CT_NUMBER))
+ {
+ set_chunk_type(prev, CT_CASE_ELLIPSIS);
+ }
+ }
+ }
+ else if (cur->flags.test(PCF_IN_WHERE_SPEC))
+ {
+ /* leave colons in where-constraint clauses alone */
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): prev->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col);
+ LOG_FMT(LFCN, "%s(%d): cur->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, cur->Text(), cur->orig_line, cur->orig_col);
+ LOG_FMT(LFCN, "%s(%d): next->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, next->Text(), next->orig_line, next->orig_col);
+ Chunk *nextprev = chunk_get_prev_local(next); // Issue #2279
+
+ if (nextprev == nullptr)
+ {
+ return;
+ }
+
+ if (language_is_set(LANG_PAWN))
+ {
+ if ( chunk_is_token(cur, CT_WORD)
+ || chunk_is_token(cur, CT_BRACE_CLOSE))
+ {
+ E_Token new_type = CT_TAG;
+
+ Chunk *tmp = next->GetNextNc();
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+
+ if ( chunk_is_newline(prev)
+ && chunk_is_newline(tmp))
+ {
+ new_type = CT_LABEL;
+ set_chunk_type(next, CT_LABEL_COLON);
+ }
+ else
+ {
+ set_chunk_type(next, CT_TAG_COLON);
+ }
+
+ if (chunk_is_token(cur, CT_WORD))
+ {
+ set_chunk_type(cur, new_type);
+ }
+ }
+ }
+ else if (next->flags.test(PCF_IN_ARRAY_ASSIGN))
+ {
+ set_chunk_type(next, CT_D_ARRAY_COLON);
+ }
+ else if (next->flags.test(PCF_IN_FOR))
+ {
+ set_chunk_type(next, CT_FOR_COLON);
+ }
+ else if (next->flags.test(PCF_OC_BOXED))
+ {
+ set_chunk_type(next, CT_OC_DICT_COLON);
+ }
+ else if (chunk_is_token(cur, CT_WORD))
+ {
+ Chunk *tmp = next->GetNextNc(E_Scope::PREPROC);
+
+ // Issue #1187
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LFCN, "%s(%d): orig_line is %zu, orig_col is %zu, tmp '%s': ",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col,
+ (chunk_is_token(tmp, CT_NEWLINE)) ? "<Newline>" : tmp->Text());
+ log_pcf_flags(LGUY, tmp->flags);
+
+ if (next->flags.test(PCF_IN_FCN_CALL))
+ {
+ // Must be a macro thingy, assume some sort of label
+ set_chunk_type(next, CT_LABEL_COLON);
+ }
+ else if ( tmp->IsNullChunk()
+ || ( chunk_is_not_token(tmp, CT_NUMBER)
+ && chunk_is_not_token(tmp, CT_DECLTYPE)
+ && chunk_is_not_token(tmp, CT_SIZEOF)
+ && get_chunk_parent_type(tmp) != CT_SIZEOF
+ && !tmp->flags.test_any(PCF_IN_STRUCT | PCF_IN_CLASS))
+ || chunk_is_token(tmp, CT_NEWLINE))
+ {
+ /*
+ * the CT_SIZEOF isn't great - test 31720 happens to use a sizeof expr,
+ * but this really should be able to handle any constant expr
+ */
+ // Fix for #1242
+ // For MIDL_INTERFACE classes class name is tokenized as Label.
+ // Corrected the identification of Label in c style languages.
+ if ( language_is_set(LANG_C | LANG_CPP | LANG_CS)
+ && (!language_is_set(LANG_OC)))
+ {
+ Chunk *labelPrev = prev;
+
+ if (chunk_is_token(labelPrev, CT_NEWLINE))
+ {
+ labelPrev = prev->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ if ( labelPrev->IsNotNullChunk()
+ && chunk_is_not_token(labelPrev, CT_FPAREN_CLOSE))
+ {
+ set_chunk_type(cur, CT_LABEL);
+ set_chunk_type(next, CT_LABEL_COLON);
+ }
+ }
+ else
+ {
+ set_chunk_type(cur, CT_LABEL);
+ set_chunk_type(next, CT_LABEL_COLON);
+ }
+ }
+ else if (next->flags.test_any(PCF_IN_STRUCT | PCF_IN_CLASS | PCF_IN_TYPEDEF))
+ {
+ set_chunk_type(next, CT_BIT_COLON);
+
+ Chunk *nnext = next->GetNext();
+
+ if (nnext->IsNullChunk())
+ {
+ return;
+ }
+
+ while ((nnext = nnext->GetNext())->IsNotNullChunk())
+ {
+ if (chunk_is_token(nnext, CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if (chunk_is_token(nnext, CT_COLON))
+ {
+ set_chunk_type(nnext, CT_BIT_COLON);
+ }
+ }
+ }
+ }
+ else if (chunk_is_token(nextprev, CT_FPAREN_CLOSE))
+ {
+ LOG_FMT(LFCN, "%s(%d): nextprev->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, nextprev->Text(), nextprev->orig_line, nextprev->orig_col,
+ get_token_name(nextprev->type));
+ LOG_FMT(LFCN, "%s(%d): next->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, next->Text(), next->orig_line, next->orig_col,
+ get_token_name(next->type));
+
+ // Issue #2172
+ if (get_chunk_parent_type(next) == CT_FUNC_DEF)
+ {
+ LOG_FMT(LFCN, "%s(%d): it's a construct colon\n", __func__, __LINE__);
+ // it's a construct colon
+ set_chunk_type(next, CT_CONSTR_COLON);
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): it's a class colon\n", __func__, __LINE__);
+ // it's a class colon
+ set_chunk_type(next, CT_CLASS_COLON);
+ }
+ }
+ else if (next->level > next->brace_level)
+ {
+ // ignore it, as it is inside a paren
+ }
+ else if ( chunk_is_token(cur, CT_TYPE)
+ || chunk_is_token(cur, CT_ENUM) // Issue #2584
+ || chunk_is_token(nextprev, CT_TYPE)
+ || chunk_is_token(nextprev, CT_ENUM)) // Issue #2584
+ {
+ set_chunk_type(next, CT_BIT_COLON);
+ }
+ else if ( chunk_is_token(cur, CT_ENUM)
+ || chunk_is_token(cur, CT_ACCESS)
+ || chunk_is_token(cur, CT_QUALIFIER)
+ || get_chunk_parent_type(cur) == CT_ALIGN)
+ {
+ // ignore it - bit field, align or public/private, etc
+ }
+ else if ( chunk_is_token(cur, CT_ANGLE_CLOSE)
+ || hit_class)
+ {
+ // ignore it - template thingy
+ }
+ else if (get_chunk_parent_type(cur) == CT_SQL_EXEC)
+ {
+ // ignore it - SQL variable name
+ }
+ else if (get_chunk_parent_type(next) == CT_ASSERT)
+ {
+ // ignore it - Java assert thing
+ }
+ else if (get_chunk_parent_type(next) == CT_STRUCT)
+ {
+ // ignore it
+ }
+ else
+ {
+ Chunk *tmp = next->GetNextNcNnl();
+
+ //tmp = chunk_get_next_local(next);
+ if (tmp->IsNotNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): tmp->Text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line, tmp->orig_col,
+ get_token_name(tmp->type));
+
+ if ( chunk_is_token(tmp, CT_BASE)
+ || chunk_is_token(tmp, CT_THIS))
+ {
+ // ignore it, as it is a C# base thingy
+ }
+ else if (language_is_set(LANG_CS | LANG_D))
+ {
+ // there should be a better solution for that
+ }
+ else
+ {
+ LOG_FMT(LWARN, "%s(%d): %s:%zu unexpected colon in col %zu n-parent=%s c-parent=%s l=%zu bl=%zu\n",
+ __func__, __LINE__,
+ cpd.filename.c_str(), next->orig_line, next->orig_col,
+ get_token_name(get_chunk_parent_type(next)),
+ get_token_name(get_chunk_parent_type(cur)),
+ next->level, next->brace_level);
+ cpd.error_count++;
+ }
+ }
+ }
+ }
+ }
+ prev = cur;
+ cur = next;
+ next = chunk_get_next_local(next);
+ }
+} // combine_labels
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.h
new file mode 100644
index 00000000..4a273d0b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_labels.h
@@ -0,0 +1,21 @@
+/**
+ * @file combine_labels.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.h
+ */
+
+#ifndef COMBINE_LABELS_H_INCLUDED
+#define COMBINE_LABELS_H_INCLUDED
+
+
+/**
+ * Examines the whole file and changes CT_COLON to
+ * CT_Q_COLON, CT_LABEL_COLON, or CT_CASE_COLON.
+ * It also changes the CT_WORD before CT_LABEL_COLON into CT_LABEL.
+ */
+void combine_labels(void);
+
+
+#endif /* COMBINE_LABELS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.cpp
new file mode 100644
index 00000000..2567470f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.cpp
@@ -0,0 +1,352 @@
+/**
+ * @file combine_skip.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#include "combine_skip.h"
+
+#include "combine_tools.h"
+
+
+Chunk *skip_align(Chunk *start)
+{
+ Chunk *pc = start;
+
+ if (chunk_is_token(pc, CT_ALIGN))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ pc = pc->GetNextType(CT_PAREN_CLOSE, pc->level);
+
+ if (pc->IsNotNullChunk())
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ if (chunk_is_token(pc, CT_COLON))
+ {
+ pc = pc->GetNextNcNnl();
+ }
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_expression(Chunk *pc)
+{
+ return(skip_to_expression_end(pc)->GetNextNcNnl());
+}
+
+
+Chunk *skip_expression_rev(Chunk *pc)
+{
+ return(skip_to_expression_start(pc)->GetPrevNcNnlNi());
+}
+
+
+static Chunk *skip_to_expression_edge(Chunk *pc, Chunk *(Chunk::*GetNextFn)(E_Scope scope)const)
+{
+ Chunk *prev = pc;
+
+ if (prev == nullptr)
+ {
+ prev = Chunk::NullChunkPtr;
+ }
+
+ if (prev->IsNotNullChunk())
+ {
+ std::size_t level = prev->level;
+ Chunk *next = prev;
+ std::size_t template_nest = get_cpp_template_angle_nest_level(prev);
+
+ while ( next->IsNotNullChunk()
+ && next->level >= level)
+ {
+ /**
+ * if we encounter a comma or semicolon at the level of the starting chunk,
+ * return the current chunk
+ */
+ if ( next->level == level
+ && ( chunk_is_token(next, CT_COMMA)
+ || chunk_is_semicolon(next)))
+ {
+ break;
+ }
+ /**
+ * check the template nest level; if the current chunk's nest level
+ * is less than that of the starting chunk, return the current chunk
+ */
+ auto next_template_nest = get_cpp_template_angle_nest_level(next);
+
+ if (template_nest > next_template_nest)
+ {
+ break;
+ }
+ prev = next;
+ next = (next->*GetNextFn)(E_Scope::PREPROC);
+ }
+ }
+ return(prev);
+}
+
+
+Chunk *skip_to_expression_end(Chunk *pc)
+{
+ return(skip_to_expression_edge(pc, &Chunk::GetNextNcNnl));
+}
+
+
+Chunk *skip_to_expression_start(Chunk *pc)
+{
+ return(skip_to_expression_edge(pc, &Chunk::GetPrevNcNnlNi));
+}
+
+
+Chunk *skip_to_next_statement(Chunk *pc)
+{
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ while ( pc->IsNotNullChunk()
+ && !chunk_is_semicolon(pc)
+ && chunk_is_not_token(pc, CT_BRACE_OPEN)
+ && chunk_is_not_token(pc, CT_BRACE_CLOSE))
+ {
+ pc = pc->GetNextNcNnl();
+ }
+ return(pc);
+}
+
+
+Chunk *skip_parent_types(Chunk *colon)
+{
+ Chunk *pc = colon->GetNextNcNnlNpp();
+
+ while (pc)
+ {
+ // Skip access specifier
+ if (chunk_is_token(pc, CT_ACCESS))
+ {
+ pc = pc->GetNextNcNnlNpp();
+ continue;
+ }
+
+ // Check for a type name
+ if (!( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_TYPE)))
+ {
+ LOG_FMT(LPCU,
+ "%s is confused; expected a word at %zu:%zu "
+ "following type list at %zu:%zu\n", __func__,
+ colon->orig_line, colon->orig_col,
+ pc->orig_line, pc->orig_col);
+ return(colon);
+ }
+ // Get next token
+ Chunk *next = skip_template_next(pc->GetNextNcNnlNpp());
+
+ if ( chunk_is_token(next, CT_DC_MEMBER)
+ || chunk_is_token(next, CT_COMMA))
+ {
+ pc = next->GetNextNcNnlNpp();
+ }
+ else if (next != nullptr)
+ {
+ LOG_FMT(LPCU, "%s -> %zu:%zu ('%s')\n", __func__,
+ next->orig_line, next->orig_col, next->Text());
+ return(next);
+ }
+ else
+ {
+ break;
+ }
+ }
+ LOG_FMT(LPCU, "%s: did not find end of type list (start was %zu:%zu)\n",
+ __func__, colon->orig_line, colon->orig_col);
+ return(colon);
+} // skip_parent_types
+
+
+Chunk *skip_template_prev(Chunk *ang_close)
+{
+ if (chunk_is_token(ang_close, CT_ANGLE_CLOSE))
+ {
+ Chunk *pc = ang_close->GetPrevType(CT_ANGLE_OPEN, ang_close->level);
+ return(pc->GetPrevNcNnlNi()); // Issue #2279
+ }
+ return(ang_close);
+}
+
+
+Chunk *skip_tsquare_next(Chunk *ary_def)
+{
+ if (ary_def == nullptr)
+ {
+ return(Chunk::NullChunkPtr);
+ }
+
+ if ( chunk_is_token(ary_def, CT_SQUARE_OPEN)
+ || chunk_is_token(ary_def, CT_TSQUARE))
+ {
+ return(ary_def->GetNextNisq());
+ }
+ return(ary_def);
+}
+
+
+Chunk *skip_attribute(Chunk *attr)
+{
+ Chunk *pc = attr;
+
+ while (chunk_is_token(pc, CT_ATTRIBUTE))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (chunk_is_token(pc, CT_FPAREN_OPEN))
+ {
+ pc = pc->GetNextType(CT_FPAREN_CLOSE, pc->level);
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_attribute_next(Chunk *attr)
+{
+ Chunk *next = skip_attribute(attr);
+
+ if ( next != attr
+ && chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ attr = next->GetNextNcNnl();
+ }
+
+ if (attr == nullptr)
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ return(attr);
+}
+
+
+Chunk *skip_attribute_prev(Chunk *fp_close)
+{
+ Chunk *pc = fp_close;
+
+ while (true)
+ {
+ if ( chunk_is_token(pc, CT_FPAREN_CLOSE)
+ && get_chunk_parent_type(pc) == CT_ATTRIBUTE)
+ {
+ pc = pc->GetPrevType(CT_ATTRIBUTE, pc->level);
+ }
+ else if (chunk_is_not_token(pc, CT_ATTRIBUTE))
+ {
+ break;
+ }
+ pc = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if (pc->IsNullChunk()) // Issue #3356
+ {
+ break;
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_declspec(Chunk *pc)
+{
+ if (chunk_is_token(pc, CT_DECLSPEC))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ pc = chunk_skip_to_match(pc);
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_declspec_next(Chunk *pc)
+{
+ Chunk *next = skip_declspec(pc);
+
+ if ( next != pc
+ && chunk_is_token(next, CT_PAREN_CLOSE))
+ {
+ pc = next->GetNextNcNnl();
+ }
+ return(pc);
+}
+
+
+Chunk *skip_declspec_prev(Chunk *pc)
+{
+ if ( chunk_is_token(pc, CT_PAREN_CLOSE)
+ && get_chunk_parent_type(pc) == CT_DECLSPEC)
+ {
+ pc = chunk_skip_to_match_rev(pc);
+ pc = pc->GetPrevNcNnlNi();
+
+ if (chunk_is_token(pc, CT_DECLSPEC))
+ {
+ pc = pc->GetPrevNcNnlNi();
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_matching_brace_bracket_paren_next(Chunk *pc)
+{
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_PAREN_OPEN)
+ || chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ pc = chunk_skip_to_match(pc);
+
+ if (pc != nullptr)
+ {
+ /**
+ * a matching brace, square bracket, or paren was found;
+ * retrieve the subsequent chunk
+ */
+
+ pc = pc->GetNextNcNnl();
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_to_chunk_before_matching_brace_bracket_paren_rev(Chunk *pc)
+{
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_PAREN_CLOSE)
+ || chunk_is_token(pc, CT_SQUARE_CLOSE))
+ {
+ pc = chunk_skip_to_match_rev(pc);
+
+ if (pc != nullptr)
+ {
+ /**
+ * a matching brace, square bracket, or paren was found;
+ * retrieve the preceding chunk
+ */
+
+ pc = pc->GetPrevNcNnlNi();
+ }
+ }
+ return(pc);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.h
new file mode 100644
index 00000000..b1595647
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_skip.h
@@ -0,0 +1,169 @@
+/**
+ * @file combine_skip.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#ifndef COMBINE_SKIP_H_INCLUDED
+#define COMBINE_SKIP_H_INCLUDED
+
+#include "chunk.h"
+
+
+/**
+ * Skips the D 'align()' statement and the colon, if present.
+ * align(2) int foo; -- returns 'int'
+ * align(4): -- returns 'int'
+ * int bar;
+ */
+Chunk *skip_align(Chunk *start);
+
+
+/**
+ * Skips chunks in the forward direction and attempts to find the
+ * chunk associated with the end of the current expression; returns
+ * the first chunk to satisfy one of the following:
+ * 1) Chunk is a comma or semicolon at the level of the starting chunk
+ * 2) Preceding chunk is at higher template nest level relative to the
+ * current chunk under test
+ */
+Chunk *skip_expression(Chunk *pc);
+
+
+/**
+ * Skips chunks in the reverse direction and attempts to find the
+ * chunk associated with the start of the current expression; returns
+ * the first chunk to satisfy one of the following:
+ * 1) Chunk is a comma or semicolon at the level of the starting chunk
+ * 2) Preceding chunk is at lower template nest level relative to the
+ * current chunk under test
+ */
+Chunk *skip_expression_rev(Chunk *pc);
+
+
+/**
+ * Skips chunks in the forward direction and attempts to find the
+ * chunk associated with the end of the current expression; specifically,
+ * the function returns that which immediately precedes a chunk
+ * satisfying one of the following:
+ * 1) Next chunk is a comma or semicolon at the level of the starting chunk
+ * 2) Preceding chunk is at a higher template nest level relative to the
+ * subsequent chunk
+ */
+Chunk *skip_to_expression_end(Chunk *pc);
+
+
+/**
+ * Skips chunks in the reverse direction and attempts to find the chunk
+ * associated with the start of the current expression; specifically,
+ * the function returns that which immediately follows a chunk
+ * satisfying one of the following:
+ * 1) Prior chunk is a comma or semicolon at the level of the starting chunk
+ * 2) Preceding chunk is at a lower template nest level relative to the
+ * subsequent chunk
+ */
+Chunk *skip_to_expression_start(Chunk *pc);
+
+
+/**
+ * Skips the list of class/struct parent types.
+ */
+Chunk *skip_parent_types(Chunk *colon);
+
+
+/**
+ * Skips over the rest of the template if ang_open is indeed a CT_ANGLE_OPEN.
+ * Points to the chunk after the CT_ANGLE_CLOSE.
+ * If the chunk isn't an CT_ANGLE_OPEN, then it is returned.
+ */
+Chunk *skip_template_next(Chunk *ang_open);
+
+
+/**
+ * Skips over the rest of the template if ang_close is indeed a CT_ANGLE_CLOSE.
+ * Points to the chunk before the CT_ANGLE_OPEN
+ * If the chunk isn't an CT_ANGLE_CLOSE, then it is returned.
+ */
+Chunk *skip_template_prev(Chunk *ang_close);
+
+
+//! Skips to the start of the next statement.
+Chunk *skip_to_next_statement(Chunk *pc);
+
+
+/**
+ * Skips the rest of the array definitions if ary_def is indeed a
+ * CT_TSQUARE or CT_SQUARE_OPEN
+ */
+Chunk *skip_tsquare_next(Chunk *ary_def);
+
+
+/**
+ * If pc is CT_ATTRIBUTE, then skip it and everything preceding the closing
+ * paren; return the chunk marked CT_FPAREN_CLOSE
+ * If the chunk isn't a CT_ATTRIBUTE, then it is returned.
+ */
+Chunk *skip_attribute(Chunk *attr);
+
+
+/**
+ * If attr is CT_ATTRIBUTE, then skip it and the parens and return the chunk
+ * after the CT_FPAREN_CLOSE.
+ * If the chunk isn't an CT_ATTRIBUTE, then it is returned.
+ */
+Chunk *skip_attribute_next(Chunk *attr);
+
+
+/**
+ * If fp_close is a CT_FPAREN_CLOSE with a parent of CT_ATTRIBUTE, then skip it
+ * and the '__attribute__' thingy and return the chunk before CT_ATTRIBUTE.
+ * Otherwise return fp_close.
+ */
+Chunk *skip_attribute_prev(Chunk *fp_close);
+
+
+/**
+ * If pc is CT_DECLSPEC, then skip it and everything preceding the closing
+ * paren; return the chunk marked CT_FPAREN_CLOSE
+ * If the chunk isn't a CT_DECLSPEC, then it is returned.
+ */
+Chunk *skip_declspec(Chunk *pc);
+
+
+/**
+ * If pc is CT_DECLSPEC, then skip it and the parens and return the chunk
+ * after the CT_FPAREN_CLOSE.
+ * If the chunk isn't a CT_DECLSPEC, then it is returned.
+ */
+Chunk *skip_declspec_next(Chunk *pc);
+
+
+/**
+ * If pc is a CT_FPAREN_CLOSE with a parent of CT_DECLSPEC, then skip it
+ * and the '__declspec' keyword and return the chunk before CT_DECLSPEC.
+ * Otherwise return pc.
+ */
+Chunk *skip_declspec_prev(Chunk *pc);
+
+
+/**
+ * If pc is a CT_BRACE_OPEN, CT_PAREN_OPEN or CT_SQUARE_OPEN, then skip
+ * forward to the next non-comment/non-newline chunk following the matching
+ * CT_BRACE_CLOSE, CT_PAREN_CLOSE or CT_SQUARE_CLOSE; if pc is none of these
+ * upon calling this function, then pc is returned.
+ */
+Chunk *skip_matching_brace_bracket_paren_next(Chunk *pc);
+
+
+/**
+ * If pc is a CT_BRACE_CLOSE, CT_PAREN_CLOSE or CT_SQUARE_CLOSE, then skip
+ * in reverse to the first non-comment/non-newline chunk preceding the matching
+ * CT_BRACE_OPEN, CT_PAREN_OPEN or CT_SQUARE_OPEN; if pc is none of these upon
+ * calling this function, then pc is returned.
+ */
+Chunk *skip_to_chunk_before_matching_brace_bracket_paren_rev(Chunk *pc);
+
+
+#endif /* COMBINE_SKIP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.cpp
new file mode 100644
index 00000000..b6866e00
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.cpp
@@ -0,0 +1,570 @@
+/**
+ * @file combine_tools.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#include "combine_tools.h"
+
+#include "unc_ctype.h"
+#include "uncrustify.h"
+
+
+bool can_be_full_param(Chunk *start, Chunk *end)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LFPARAM, "%s(%d): start->Text() is '%s', type is %s\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->type));
+ LOG_FMT(LFPARAM, "%s(%d): end->Text() is '%s', type is %s\n",
+ __func__, __LINE__, end->Text(), get_token_name(end->type));
+
+ int word_count = 0;
+ int type_count = 0;
+ Chunk *pc = nullptr;
+ Chunk *first_word = nullptr;
+ bool first_word_set = false;
+
+ for (pc = start;
+ pc != nullptr && pc->IsNotNullChunk() && pc != end;
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+
+ if ( chunk_is_token(pc, CT_QUALIFIER)
+ || chunk_is_token(pc, CT_STRUCT)
+ || chunk_is_token(pc, CT_ENUM)
+ || chunk_is_token(pc, CT_UNION)
+ || chunk_is_token(pc, CT_TYPENAME))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== %s! (yes)\n",
+ __func__, __LINE__, get_token_name(pc->type));
+ return(true);
+ }
+
+ if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_TYPE))
+ {
+ ++word_count;
+
+ if (!first_word_set)
+ {
+ first_word = pc;
+ first_word_set = true;
+ }
+
+ if (chunk_is_token(pc, CT_TYPE))
+ {
+ ++type_count;
+ }
+ }
+ else if ( chunk_is_token(pc, CT_MEMBER)
+ || chunk_is_token(pc, CT_DC_MEMBER))
+ {
+ if (word_count > 0)
+ {
+ --word_count;
+ }
+ }
+ else if ( pc != start
+ && chunk_is_ptr_operator(pc))
+ {
+ // chunk is OK
+ }
+ else if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ // chunk is OK (default values)
+ break;
+ }
+ else if (chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== template\n",
+ __func__, __LINE__);
+
+ return(true);
+ }
+ else if (chunk_is_token(pc, CT_ELLIPSIS))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== elipses\n",
+ __func__, __LINE__);
+
+ return(true);
+ }
+ else if ( word_count == 0
+ && chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ // Check for old-school func proto param '(type)'
+ Chunk *tmp1 = chunk_skip_to_match(pc, E_Scope::PREPROC);
+
+ if (tmp1 == nullptr)
+ {
+ return(false);
+ }
+ Chunk *tmp2 = tmp1->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp2->IsNullChunk())
+ {
+ return(false);
+ }
+
+ if ( chunk_is_token(tmp2, CT_COMMA)
+ || chunk_is_paren_close(tmp2))
+ {
+ do
+ {
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (pc->IsNullChunk())
+ {
+ return(false);
+ }
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+ } while (pc != tmp1);
+
+ // reset some vars to allow [] after parens
+ word_count = 1;
+ type_count = 1;
+ }
+ else
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== '%s' not fcn type!\n",
+ __func__, __LINE__, get_token_name(pc->type));
+ return(false);
+ }
+ }
+ else if ( ( word_count == 1
+ || (word_count == type_count))
+ && chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ // Check for func proto param 'void (*name)' or 'void (*name)(params)' or 'void (^name)(params)'
+ // <name> can be optional
+ Chunk *tmp1 = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp1->IsNullChunk())
+ {
+ return(false);
+ }
+ Chunk *tmp2 = tmp1->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp2->IsNullChunk())
+ {
+ return(false);
+ }
+ Chunk *tmp3 = (chunk_is_str(tmp2, ")")) ? tmp2 : tmp2->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp3->IsNullChunk())
+ {
+ return(false);
+ }
+
+ if ( !chunk_is_str(tmp3, ")")
+ || !( chunk_is_str(tmp1, "*")
+ || chunk_is_str(tmp1, "^")) // Issue #2656
+ || !( tmp2->type == CT_WORD
+ || chunk_is_str(tmp2, ")")))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== '%s' not fcn type!\n",
+ __func__, __LINE__, get_token_name(pc->type));
+ return(false);
+ }
+ LOG_FMT(LFPARAM, "%s(%d): <skip fcn type>\n",
+ __func__, __LINE__);
+
+ tmp1 = tmp3->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp1->IsNullChunk())
+ {
+ return(false);
+ }
+
+ if (chunk_is_str(tmp1, "("))
+ {
+ tmp3 = chunk_skip_to_match(tmp1, E_Scope::PREPROC);
+ }
+ pc = tmp3;
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+
+ // reset some vars to allow [] after parens
+ word_count = 1;
+ type_count = 1;
+ }
+ else if (chunk_is_token(pc, CT_TSQUARE))
+ {
+ // ignore it
+ }
+ else if ( word_count == 1
+ && chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ // skip over any array stuff
+ pc = chunk_skip_to_match(pc, E_Scope::PREPROC);
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+ }
+ else if ( word_count == 2
+ && chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ // Bug #671: is it such as: bool foo[FOO_MAX]
+ pc = chunk_skip_to_match(pc, E_Scope::PREPROC);
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+ }
+ else if ( word_count == 1
+ && language_is_set(LANG_CPP)
+ && chunk_is_str(pc, "&&"))
+ {
+ // ignore possible 'move' operator
+ }
+ else
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== type is %s, no way!, type count is %d, word count is %d\n",
+ __func__, __LINE__, get_token_name(pc->type), type_count, word_count);
+ return(false);
+ }
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+ }
+
+ Chunk *last = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ LOG_FMT(LFPARAM, "%s(%d): last->Text() is '%s', type is %s\n",
+ __func__, __LINE__, last->Text(), get_token_name(last->type));
+
+ if (chunk_is_ptr_operator(last))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== type is %s, sure!\n",
+ __func__, __LINE__, get_token_name(last->type));
+ return(true);
+ }
+
+ if ( word_count < 2
+ && type_count < 1
+ && start->brace_level > 0)
+ {
+ LOG_FMT(LFPARAM, "%s(%d): !MVP!\n",
+ __func__, __LINE__);
+ // Oh, joy, we are in Most Vexing Parse territory
+ Chunk *brace =
+ start->GetPrevType(CT_BRACE_OPEN, start->brace_level - 1);
+
+ if (brace->IsNotNullChunk())
+ {
+ LOG_FMT(LFPARAM, "%s(%d): (matching %s brace at orig_line %zu, orig_col is %zu)",
+ __func__, __LINE__,
+ get_token_name(get_chunk_parent_type(brace)), brace->orig_line, brace->orig_col);
+ }
+
+ if ( brace->IsNotNullChunk()
+ && ( get_chunk_parent_type(brace) == CT_CLASS
+ || get_chunk_parent_type(brace) == CT_STRUCT))
+ {
+ // A Most Vexing Parse variable declaration cannot occur in the body
+ // of a struct/class, so we probably have a function prototype
+ LOG_FMT(LFPARAM, "%s(%d): <== type is %s, Likely!\n",
+ __func__, __LINE__, (pc == nullptr ? "nullptr" : get_token_name(pc->type)));
+ return(true);
+ }
+ }
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', word_count is %d, type_count is %d\n",
+ __func__, __LINE__, pc->Text(), word_count, type_count);
+
+ if (first_word != nullptr)
+ {
+ LOG_FMT(LFPARAM, "%s(%d): first_word->Text() is '%s'\n",
+ __func__, __LINE__, first_word->Text());
+ }
+ bool ret = ( word_count >= 2
+ || ( word_count == 1
+ && type_count == 1));
+
+ LOG_FMT(LFPARAM, "%s(%d): ret is %s\n",
+ __func__, __LINE__, ret ? "TRUE" : "FALSE");
+
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', ",
+ __func__, __LINE__, pc->Text());
+ LOG_FMT(LFPARAM, "<== type is %s, ",
+ (pc == nullptr ? "nullptr" : get_token_name(pc->type)));
+
+ if (ret)
+ {
+ LOG_FMT(LFPARAM, "Yup!\n");
+ }
+ else
+ {
+ LOG_FMT(LFPARAM, "Unlikely!\n");
+ }
+ return(ret);
+} // can_be_full_param
+
+
+bool chunk_ends_type(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = start;
+ bool ret = false;
+ size_t cnt = 0;
+ bool last_expr = false;
+ bool last_lval = false;
+
+ bool a = pc->flags.test(PCF_IN_FCN_CTOR);
+
+ if (a)
+ {
+ return(false);
+ }
+
+ for ( ; pc->IsNotNullChunk(); pc = pc->GetPrevNcNnlNi()) // Issue #2279
+ {
+ LOG_FMT(LFTYPE, "%s(%d): type is %s, Text() '%s', orig_line %zu, orig_col %zu\n ",
+ __func__, __LINE__, get_token_name(pc->type), pc->Text(),
+ pc->orig_line, pc->orig_col);
+ log_pcf_flags(LFTYPE, pc->flags);
+
+ if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_PTR_TYPE)
+ || chunk_is_token(pc, CT_STAR)
+ || chunk_is_token(pc, CT_STRUCT)
+ || chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_PP)
+ || chunk_is_token(pc, CT_QUALIFIER)
+ || ( language_is_set(LANG_CPP | LANG_OC) // Issue #2727
+ && get_chunk_parent_type(pc) == CT_TEMPLATE
+ && ( chunk_is_token(pc, CT_ANGLE_OPEN)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE)))
+ || ( language_is_set(LANG_CS | LANG_VALA)
+ && (chunk_is_token(pc, CT_MEMBER))))
+ {
+ cnt++;
+ last_expr = pc->flags.test(PCF_EXPR_START)
+ && !pc->flags.test(PCF_IN_FCN_CALL);
+ last_lval = pc->flags.test(PCF_LVALUE);
+ continue;
+ }
+ /* If a comma is encountered within a template, it must be
+ * considered within the context of its immediate parent
+ * template (i.e. argument list nest level)
+ */
+
+ if ( ( chunk_is_semicolon(pc)
+ && !pc->flags.test(PCF_IN_FOR))
+ || chunk_is_token(pc, CT_TYPEDEF)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE)
+ || chunk_is_token(pc, CT_FPAREN_CLOSE)
+ || chunk_is_forin(pc)
+ || chunk_is_token(pc, CT_MACRO)
+ || chunk_is_token(pc, CT_PP_IF)
+ || chunk_is_token(pc, CT_PP_ELSE)
+ || chunk_is_token(pc, CT_PP_ENDIF)
+ || get_chunk_parent_type(pc) == CT_PP_INCLUDE // Issue #3233
+ || ( ( chunk_is_token(pc, CT_COMMA)
+ && !pc->flags.test(PCF_IN_FCN_CALL)
+ && get_cpp_template_angle_nest_level(start) ==
+ get_cpp_template_angle_nest_level(pc))
+ && last_expr)
+ || ( chunk_is_token(pc, CT_SPAREN_OPEN)
+ && last_lval))
+ {
+ ret = cnt > 0;
+ }
+ break;
+ }
+
+ if (pc->IsNullChunk())
+ {
+ // first token
+ ret = true;
+ }
+ LOG_FMT(LFTYPE, "%s(%d): first token verdict: %s\n",
+ __func__, __LINE__, ret ? "yes" : "no");
+
+ return(ret);
+} // chunk_ends_type
+
+
+bool chunkstack_match(ChunkStack &cs, Chunk *pc)
+{
+ for (size_t idx = 0; idx < cs.Len(); idx++)
+ {
+ Chunk *tmp = cs.GetChunk(idx);
+
+ if (pc->str.equals(tmp->str))
+ {
+ return(true);
+ }
+ }
+
+ return(false);
+} // chunkstack_match
+
+
+void flag_series(Chunk *start, Chunk *end, pcf_flags_t set_flags, pcf_flags_t clr_flags, E_Scope nav)
+{
+ LOG_FUNC_ENTRY();
+
+ while ( start != nullptr
+ && start->IsNotNullChunk()
+ && start != end)
+ {
+ chunk_flags_upd(start, clr_flags, set_flags);
+
+ start = start->GetNext(nav);
+
+ if (start->IsNullChunk())
+ {
+ return;
+ }
+ }
+
+ if ( end != nullptr
+ && end->IsNotNullChunk())
+ {
+ chunk_flags_upd(end, clr_flags, set_flags);
+ }
+} // flag_series
+
+
+size_t get_cpp_template_angle_nest_level(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ int nestLevel = 0;
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ while ( pc->IsNotNullChunk()
+ && pc->flags.test(PCF_IN_TEMPLATE))
+ {
+ if ( chunk_is_token(pc, CT_ANGLE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_TEMPLATE)
+ {
+ --nestLevel;
+ }
+ else if ( chunk_is_token(pc, CT_ANGLE_OPEN)
+ && get_chunk_parent_type(pc) == CT_TEMPLATE)
+ {
+ ++nestLevel;
+ }
+ pc = pc->GetPrevNcNnlNi();
+ }
+ return(nestLevel <= 0 ? 0 : size_t(nestLevel));
+}
+
+
+Chunk *get_d_template_types(ChunkStack &cs, Chunk *open_paren)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *tmp = open_paren->GetNextNcNnl();
+ bool maybe_type = true;
+
+ while ( tmp->IsNullChunk()
+ && tmp->level > open_paren->level)
+ {
+ if ( chunk_is_token(tmp, CT_TYPE)
+ || chunk_is_token(tmp, CT_WORD))
+ {
+ if (maybe_type)
+ {
+ make_type(tmp);
+ cs.Push_Back(tmp);
+ }
+ maybe_type = false;
+ }
+ else if (chunk_is_token(tmp, CT_COMMA))
+ {
+ maybe_type = true;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ return(tmp);
+} // get_d_template_types
+
+
+bool go_on(Chunk *pc, Chunk *start)
+{
+ if ( pc == nullptr
+ || pc->IsNullChunk()
+ || pc->level != start->level)
+ {
+ return(false);
+ }
+
+ if (pc->flags.test(PCF_IN_FOR))
+ {
+ return( (!chunk_is_semicolon(pc))
+ && (!(chunk_is_token(pc, CT_COLON))));
+ }
+ return(!chunk_is_semicolon(pc));
+} // go_on
+
+
+bool is_ucase_str(const char *str, size_t len)
+{
+ while (len-- > 0)
+ {
+ if (unc_toupper(*str) != *str)
+ {
+ return(false);
+ }
+ str++;
+ }
+ return(true);
+} // is_ucase_str
+
+
+void make_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc != nullptr)
+ {
+ if (chunk_is_token(pc, CT_WORD))
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ else if ( ( pc->IsStar()
+ || chunk_is_msref(pc)
+ || chunk_is_nullable(pc))
+ && chunk_is_type(pc->prev)) // Issue # 2640
+ {
+ set_chunk_type(pc, CT_PTR_TYPE);
+ }
+ else if ( chunk_is_addr(pc)
+ && !chunk_is_token(pc->prev, CT_SQUARE_OPEN)) // Issue # 2166
+ {
+ set_chunk_type(pc, CT_BYREF);
+ }
+ }
+} // make_type
+
+
+Chunk *set_paren_parent(Chunk *start, E_Token parent)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *end;
+
+ end = chunk_skip_to_match(start, E_Scope::PREPROC);
+
+ if (end != nullptr)
+ {
+ LOG_FMT(LFLPAREN, "%s(%d): %zu:%zu '%s' and %zu:%zu '%s' type is %s, parent_type is %s",
+ __func__, __LINE__, start->orig_line, start->orig_col, start->Text(),
+ end->orig_line, end->orig_col, end->Text(),
+ get_token_name(start->type), get_token_name(parent));
+ log_func_stack_inline(LFLPAREN);
+ set_chunk_parent(start, parent);
+ set_chunk_parent(end, parent);
+ LOG_FMT(LFLPAREN, "%s(%d):\n", __func__, __LINE__);
+ return(end->GetNextNcNnl(E_Scope::PREPROC));
+ }
+ LOG_FMT(LFLPAREN, "%s(%d):\n", __func__, __LINE__);
+ return(nullptr);
+} // set_paren_parent
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.h
new file mode 100644
index 00000000..40ea915f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/combine_tools.h
@@ -0,0 +1,85 @@
+/**
+ * @file combine_tools.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#ifndef COMBINE_TOOLS_H_INCLUDED
+#define COMBINE_TOOLS_H_INCLUDED
+
+#include "chunk.h"
+#include "ChunkStack.h"
+
+/**
+ * Checks to see if a series of chunks could be a C++ parameter
+ * FOO foo(5, &val);
+ *
+ * WORD means CT_WORD or CT_TYPE
+ *
+ * "WORD WORD" ==> true
+ * "QUALIFIER ??" ==> true
+ * "TYPE" ==> true
+ * "WORD" ==> true
+ * "WORD.WORD" ==> true
+ * "WORD::WORD" ==> true
+ * "WORD * WORD" ==> true
+ * "WORD & WORD" ==> true
+ * "NUMBER" ==> false
+ * "STRING" ==> false
+ * "OPEN PAREN" ==> false
+ *
+ * @param start the first chunk to look at
+ * @param end the chunk after the last one to look at
+ */
+bool can_be_full_param(Chunk *start, Chunk *end);
+
+
+//! Scan backwards to see if we might be on a type declaration
+bool chunk_ends_type(Chunk *start);
+
+
+bool chunkstack_match(ChunkStack &cs, Chunk *pc);
+
+
+///**
+// * Simply change any STAR to PTR_TYPE and WORD to TYPE
+// *
+// * @param start points to the open paren
+// */
+void fix_fcn_def_params(Chunk *pc);
+
+
+void flag_series(Chunk *start, Chunk *end, pcf_flags_t set_flags, pcf_flags_t clr_flags = {}, E_Scope nav = E_Scope::ALL);
+
+
+/*
+ * Checks whether or not a given chunk has a parent cpp template,
+ * and if so returns the associated angle bracket nest level
+ * with respect to the root parent template; returns 0 if
+ * the chunk is not part of a template parameter list
+ */
+size_t get_cpp_template_angle_nest_level(Chunk *pc);
+
+
+/**
+ * Parse off the types in the D template args, adds to cs
+ * returns the close_paren
+ */
+Chunk *get_d_template_types(ChunkStack &cs, Chunk *open_paren);
+
+
+//! help function for mark_variable_definition...
+bool go_on(Chunk *pc, Chunk *start);
+
+
+bool is_ucase_str(const char *str, size_t len);
+
+
+void make_type(Chunk *pc);
+
+Chunk *set_paren_parent(Chunk *start, E_Token parent);
+
+
+#endif /* COMBINE_TOOLS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat.h
new file mode 100644
index 00000000..32fce459
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat.h
@@ -0,0 +1,26 @@
+/**
+ * @file compat.h
+ * prototypes for compat_xxx.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef COMPAT_H_INCLUDED
+#define COMPAT_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+bool unc_getenv(const char *name, std::string &str);
+
+
+bool unc_homedir(std::string &home);
+
+
+/*
+ * even if we prefer the format %zu, we have to change to %lu
+ * to be runable under Windows
+ */
+void convert_log_zu2lu(char *buf);
+
+#endif /* COMPAT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_posix.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_posix.cpp
new file mode 100644
index 00000000..c77c7a89
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_posix.cpp
@@ -0,0 +1,39 @@
+/**
+ * @file compat_posix.cpp
+ * Compatibility functions for POSIX
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef WIN32
+
+#include "uncrustify_types.h"
+
+
+bool unc_getenv(const char *name, std::string &str)
+{
+ const char *val = getenv(name);
+
+ if (val != nullptr)
+ {
+ str = val;
+ return(true);
+ }
+ return(false);
+}
+
+
+bool unc_homedir(std::string &home)
+{
+ return(unc_getenv("HOME", home));
+}
+
+
+void convert_log_zu2lu(char *fmt)
+{
+ UNUSED(fmt);
+ // nothing to do
+}
+
+#endif /* ifndef WIN32 */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_win32.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_win32.cpp
new file mode 100644
index 00000000..e1617876
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/compat_win32.cpp
@@ -0,0 +1,82 @@
+/**
+ * @file compat_win32.cpp
+ * Compatibility functions for win32
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#if defined (_WIN32) \
+ && !defined (__CYGWIN__)
+
+#include "windows_compat.h"
+
+#include <cstdio>
+#include <string>
+
+
+bool unc_getenv(const char *name, std::string &str)
+{
+ DWORD len = GetEnvironmentVariableA(name, NULL, 0);
+ char *buf;
+
+ if (len == 0)
+ {
+ if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+ {
+ return(false);
+ }
+ }
+ buf = (char *)malloc(len);
+
+ if (buf)
+ {
+ len = GetEnvironmentVariableA(name, buf, len);
+ }
+ buf[len] = 0;
+
+ str = buf;
+ //printf("%s: name=%s len=%zu value=%s\n", __func__, name, len, str.c_str());
+ free(buf);
+
+ return(true);
+}
+
+
+bool unc_homedir(std::string &home)
+{
+ if (unc_getenv("HOME", home))
+ {
+ return(true);
+ }
+
+ if (unc_getenv("USERPROFILE", home))
+ {
+ return(true);
+ }
+ std::string hd, hp;
+
+ if ( unc_getenv("HOMEDRIVE", hd)
+ && unc_getenv("HOMEPATH", hp))
+ {
+ home = hd + hp;
+ return(true);
+ }
+ return(false);
+}
+
+
+void convert_log_zu2lu(char *fmt)
+{
+ for (size_t i = 0; i < strlen(fmt); i++)
+ {
+ if ( (fmt[i] == '%')
+ && (fmt[i + 1] == 'z')
+ && (fmt[i + 2] == 'u'))
+ {
+ fmt[i + 1] = 'l';
+ }
+ }
+}
+
+#endif /* if defined(_WIN32) && !defined(__CYGWIN__) */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/config.h.in b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/config.h.in
new file mode 100644
index 00000000..4270a733
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/config.h.in
@@ -0,0 +1,97 @@
+// Used by CMake to generate config.h.
+
+// Define to 1 if you have the <inttypes.h> header file.
+#cmakedefine HAVE_INTTYPES_H 1
+
+// Define to 1 if you have the <memory.h> header file.
+#cmakedefine HAVE_MEMORY_H 1
+
+// Define to 1 if you have the `memset' function.
+#cmakedefine HAVE_MEMSET 1
+
+// Define to 1 if stdbool.h conforms to C99.
+#cmakedefine HAVE_STDBOOL_H 1
+
+// Define to 1 if you have the <stdint.h> header file.
+#cmakedefine HAVE_STDINT_H 1
+
+// Define to 1 if you have the <stdlib.h> header file.
+#cmakedefine HAVE_STDLIB_H 1
+
+// Define to 1 if you have the `strcasecmp' function.
+#cmakedefine HAVE_STRCASECMP 1
+
+// Define to 1 if you have the `strchr' function.
+#cmakedefine HAVE_STRCHR 1
+
+// Define to 1 if you have the `strdup' function.
+#cmakedefine HAVE_STRDUP 1
+
+// Define to 1 if you have the `strerror' function.
+#cmakedefine HAVE_STRERROR 1
+
+// Define to 1 if you have the <strings.h> header file.
+#cmakedefine HAVE_STRINGS_H 1
+
+// Define to 1 if you have the <string.h> header file.
+#cmakedefine HAVE_STRING_H 1
+
+// Define to 1 if you have the `strtol' function.
+#cmakedefine HAVE_STRTOL 1
+
+// Define to 1 if you have the `strtoul' function.
+#cmakedefine HAVE_STRTOUL 1
+
+// Define to 1 if you have the <sys/stat.h> header file.
+#cmakedefine HAVE_SYS_STAT_H 1
+
+// Define to 1 if you have the <sys/types.h> header file.
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+// Define to 1 if you have the <unistd.h> header file.
+#cmakedefine HAVE_UNISTD_H 1
+
+// Define to 1 if you have the <utime.h> header file.
+#cmakedefine HAVE_UTIME_H 1
+
+// Define to 1 if the system has the type `_Bool'.
+#cmakedefine HAVE__BOOL 1
+
+// Name of package
+#cmakedefine PACKAGE "@PACKAGE@"
+
+// Define to the address where bug reports for this package should be sent.
+#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
+
+// Define to the full name of this package.
+#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
+
+// Define to the full name and version of this package.
+#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
+
+// Define to the one symbol short name of this package.
+#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@"
+
+// Define to the home page for this package.
+#cmakedefine PACKAGE_URL "@PACKAGE_URL@"
+
+// Define to the version of this package.
+#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
+
+// Define to 1 if you have the ANSI C header files.
+#cmakedefine STDC_HEADERS 1
+
+// Version number of package
+#cmakedefine VERSION "@VERSION@"
+
+/* Define to appropriate substitue if compiler doesnt have __func__ */
+/* #undef __func__ */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ * calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.cpp
new file mode 100644
index 00000000..4fd2fd66
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.cpp
@@ -0,0 +1,20 @@
+/**
+ * @file cs_top_is_question.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#include "cs_top_is_question.h"
+
+#include "chunk.h"
+
+
+bool cs_top_is_question(ChunkStack &cs, size_t level)
+{
+ Chunk *pc = cs.Empty() ? nullptr : cs.Top()->m_pc;
+
+ return( chunk_is_token(pc, CT_QUESTION)
+ && pc->level == level);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.h
new file mode 100644
index 00000000..de6ace3e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/cs_top_is_question.h
@@ -0,0 +1,18 @@
+/**
+ * @file cs_top_is_question.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#ifndef CS_TOP_IS_QUESTION_H_INCLUDED
+#define CS_TOP_IS_QUESTION_H_INCLUDED
+
+#include "ChunkStack.h"
+
+
+bool cs_top_is_question(ChunkStack &cs, size_t level);
+
+
+#endif /* CS_TOP_IS_QUESTION_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.cpp
new file mode 100644
index 00000000..b7fc17ca
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.cpp
@@ -0,0 +1,439 @@
+/**
+ * @file detect.cpp
+ * Scans the parsed file and tries to determine options.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "detect.h"
+
+#include "prototypes.h"
+
+
+using namespace uncrustify;
+
+
+//! Detect spacing options
+static void detect_space_options(void);
+
+
+class sp_votes
+{
+protected:
+ size_t m_add = 0;
+ size_t m_remove = 0;
+ size_t m_force = 0;
+ Option<iarf_e> &m_option;
+
+public:
+ sp_votes(Option<iarf_e> &opt)
+ : m_option(opt)
+ {}
+
+ //! Figure out the result of the vote and maybe update *m_av
+ ~sp_votes();
+
+ void vote(Chunk *first, Chunk *second);
+};
+
+
+void sp_votes::vote(Chunk *first, Chunk *second)
+{
+ if ( first == nullptr
+ || chunk_is_newline(first)
+ || second == nullptr
+ || chunk_is_newline(second))
+ {
+ return;
+ }
+ int col_dif = second->column - (first->column + first->Len());
+
+ if (col_dif == 0)
+ {
+ m_remove++;
+ }
+ else if (col_dif == 1)
+ {
+ m_force++;
+ }
+ else
+ {
+ m_add++;
+ }
+}
+
+
+//! Figure out the result of the vote and maybe update *m_av
+sp_votes::~sp_votes()
+{
+ // no change if no items were added
+ if ( m_remove == 0
+ && m_add == 0
+ && m_force == 0)
+ {
+ return;
+ }
+
+ if (m_remove == 0)
+ {
+ m_option = (m_force > m_add) ? IARF_FORCE : IARF_ADD;
+ }
+ else if ( m_force == 0
+ && m_add == 0)
+ {
+ m_option = IARF_REMOVE;
+ }
+ else
+ {
+ // nothing conclusive. do not alter.
+ }
+}
+
+
+// generates "vote_sp_xxx" variable name from uncrustify option name "UO_xxx"
+#define SP_VOTE_VAR(x) sp_votes vote_ ## x(options::x)
+
+
+static void detect_space_options(void)
+{
+ SP_VOTE_VAR(sp_arith);
+ SP_VOTE_VAR(sp_before_assign);
+ SP_VOTE_VAR(sp_after_assign);
+ SP_VOTE_VAR(sp_enum_before_assign);
+ SP_VOTE_VAR(sp_enum_after_assign);
+ SP_VOTE_VAR(sp_bool);
+ SP_VOTE_VAR(sp_compare);
+ SP_VOTE_VAR(sp_inside_paren);
+ SP_VOTE_VAR(sp_paren_paren);
+ SP_VOTE_VAR(sp_paren_brace);
+ SP_VOTE_VAR(sp_before_ptr_star);
+ SP_VOTE_VAR(sp_before_unnamed_ptr_star);
+ SP_VOTE_VAR(sp_between_ptr_star);
+ SP_VOTE_VAR(sp_after_ptr_star);
+ SP_VOTE_VAR(sp_after_byref);
+ SP_VOTE_VAR(sp_before_byref);
+ SP_VOTE_VAR(sp_before_unnamed_byref);
+ SP_VOTE_VAR(sp_after_type);
+ SP_VOTE_VAR(sp_template_angle);
+ SP_VOTE_VAR(sp_before_angle);
+ SP_VOTE_VAR(sp_inside_angle);
+ SP_VOTE_VAR(sp_after_angle);
+ SP_VOTE_VAR(sp_angle_paren);
+ SP_VOTE_VAR(sp_angle_word);
+ SP_VOTE_VAR(sp_before_square);
+ SP_VOTE_VAR(sp_before_squares);
+ SP_VOTE_VAR(sp_inside_square);
+ SP_VOTE_VAR(sp_before_sparen);
+ SP_VOTE_VAR(sp_inside_sparen);
+ SP_VOTE_VAR(sp_after_sparen);
+ SP_VOTE_VAR(sp_sparen_brace);
+ SP_VOTE_VAR(sp_special_semi);
+ SP_VOTE_VAR(sp_before_semi);
+ SP_VOTE_VAR(sp_before_semi_for);
+ SP_VOTE_VAR(sp_before_semi_for_empty);
+ SP_VOTE_VAR(sp_after_semi_for_empty);
+ SP_VOTE_VAR(sp_after_comma);
+ SP_VOTE_VAR(sp_before_comma);
+ SP_VOTE_VAR(sp_after_class_colon);
+ SP_VOTE_VAR(sp_before_class_colon);
+ SP_VOTE_VAR(sp_inside_braces);
+ SP_VOTE_VAR(sp_inside_braces_empty);
+ SP_VOTE_VAR(sp_else_brace);
+ SP_VOTE_VAR(sp_brace_else);
+ SP_VOTE_VAR(sp_catch_brace);
+ SP_VOTE_VAR(sp_brace_catch);
+ SP_VOTE_VAR(sp_finally_brace);
+ SP_VOTE_VAR(sp_brace_finally);
+ SP_VOTE_VAR(sp_try_brace);
+ SP_VOTE_VAR(sp_getset_brace);
+
+ Chunk *prev = Chunk::GetHead();
+ Chunk *pc = prev->GetNext();
+ Chunk *next;
+
+ while (pc->IsNotNullChunk())
+ {
+ next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+
+ if ( chunk_is_token(pc, CT_ARITH)
+ || chunk_is_token(pc, CT_SHIFT))
+ {
+ vote_sp_arith.vote(pc, next);
+ vote_sp_arith.vote(prev, pc);
+ }
+
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ if (!pc->flags.test(PCF_IN_ENUM))
+ {
+ vote_sp_before_assign.vote(prev, pc);
+ vote_sp_after_assign.vote(pc, next);
+ }
+ else
+ {
+ vote_sp_enum_before_assign.vote(prev, pc);
+ vote_sp_enum_after_assign.vote(pc, next);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ vote_sp_before_square.vote(prev, pc);
+ vote_sp_inside_square.vote(pc, next);
+ }
+
+ if (chunk_is_token(pc, CT_SQUARE_CLOSE))
+ {
+ vote_sp_inside_square.vote(prev, pc);
+ }
+
+ if (chunk_is_token(pc, CT_TSQUARE))
+ {
+ vote_sp_before_squares.vote(prev, pc);
+ }
+
+ if (chunk_is_token(pc, CT_BOOL))
+ {
+ vote_sp_bool.vote(prev, pc);
+ vote_sp_bool.vote(pc, next);
+ }
+
+ if (chunk_is_token(pc, CT_COMPARE))
+ {
+ vote_sp_compare.vote(prev, pc);
+ vote_sp_compare.vote(pc, next);
+ }
+
+ if (chunk_is_token(pc, CT_PAREN_CLOSE))
+ {
+ vote_sp_inside_paren.vote(prev, pc);
+ }
+
+ if (chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ vote_sp_inside_paren.vote(pc, next);
+ }
+
+ if ( ( chunk_is_paren_open(pc)
+ && chunk_is_paren_open(next))
+ || ( chunk_is_paren_close(pc)
+ && chunk_is_paren_close(next)))
+ {
+ vote_sp_paren_paren.vote(pc, next);
+ }
+
+ if ( chunk_is_paren_close(pc)
+ && chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ vote_sp_paren_brace.vote(pc, next);
+ }
+
+ if (chunk_is_token(pc, CT_PTR_TYPE))
+ {
+ if (chunk_is_token(prev, CT_PTR_TYPE))
+ {
+ vote_sp_between_ptr_star.vote(prev, pc);
+ }
+ else if (next->type != CT_WORD)
+ {
+ vote_sp_before_unnamed_ptr_star.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_before_ptr_star.vote(prev, pc);
+ }
+
+ if (CharTable::IsKw1(next->str[0]))
+ {
+ vote_sp_after_ptr_star.vote(pc, next);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_BYREF))
+ {
+ if (next->type != CT_WORD)
+ {
+ vote_sp_before_unnamed_byref.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_before_byref.vote(prev, pc);
+ }
+ vote_sp_after_byref.vote(pc, next);
+ }
+
+ if ( pc->type != CT_PTR_TYPE
+ && ( chunk_is_token(prev, CT_QUALIFIER)
+ || chunk_is_token(prev, CT_TYPE)))
+ {
+ vote_sp_after_type.vote(prev, pc);
+ }
+
+ if (chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ vote_sp_inside_angle.vote(pc, next);
+
+ if (chunk_is_token(prev, CT_TEMPLATE))
+ {
+ vote_sp_template_angle.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_before_angle.vote(prev, pc);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ vote_sp_inside_angle.vote(prev, pc);
+
+ if (chunk_is_paren_open(next))
+ {
+ vote_sp_angle_paren.vote(prev, pc);
+ }
+ else if ( chunk_is_token(next, CT_WORD)
+ || CharTable::IsKw1(next->str[0]))
+ {
+ vote_sp_angle_word.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_after_angle.vote(pc, next);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_SPAREN_OPEN))
+ {
+ vote_sp_before_sparen.vote(prev, pc);
+ vote_sp_inside_sparen.vote(pc, next);
+ }
+
+ if (chunk_is_token(pc, CT_SPAREN_CLOSE))
+ {
+ vote_sp_inside_sparen.vote(prev, pc);
+
+ if (chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ vote_sp_sparen_brace.vote(pc, next);
+ }
+ else
+ {
+ vote_sp_after_sparen.vote(pc, next);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ if (get_chunk_parent_type(pc) == CT_FOR)
+ {
+ if (chunk_is_token(prev, CT_SPAREN_OPEN))
+ {
+ // empty, ie for (;;)
+ // ^ is prev
+ // ^ is pc
+ vote_sp_before_semi_for_empty.vote(prev, pc);
+ }
+ else if (chunk_is_token(next, CT_SPAREN_CLOSE))
+ {
+ // empty, ie for (;;)
+ // ^ is pc
+ // ^ is next
+ vote_sp_after_semi_for_empty.vote(pc, next);
+ }
+ else if (prev->type != CT_SEMICOLON)
+ {
+ // empty, ie for (; i < 8;)
+ // ^ is pc
+ // or
+ // ^ is prev
+ vote_sp_before_semi_for.vote(prev, pc);
+ }
+ }
+ else if (chunk_is_token(prev, CT_VBRACE_OPEN))
+ {
+ vote_sp_special_semi.vote(prev->GetPrev(), pc);
+ }
+ else
+ {
+ vote_sp_before_semi.vote(prev, pc);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_COMMA))
+ {
+ vote_sp_before_comma.vote(prev, pc);
+ vote_sp_after_comma.vote(pc, next);
+ }
+
+ if (chunk_is_token(pc, CT_CLASS_COLON))
+ {
+ vote_sp_before_class_colon.vote(prev, pc);
+ vote_sp_after_class_colon.vote(pc, next);
+ }
+
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ if (chunk_is_token(prev, CT_ELSE))
+ {
+ vote_sp_else_brace.vote(prev, pc);
+ }
+ else if (chunk_is_token(prev, CT_CATCH))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+ else if (chunk_is_token(prev, CT_FINALLY))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+ else if (chunk_is_token(prev, CT_TRY))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+ else if (chunk_is_token(prev, CT_GETSET))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+
+ if (chunk_is_token(next, CT_BRACE_CLOSE))
+ {
+ vote_sp_inside_braces_empty.vote(pc, next);
+ }
+ else
+ {
+ vote_sp_inside_braces.vote(pc, next);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ vote_sp_inside_braces.vote(prev, pc);
+
+ if (chunk_is_token(next, CT_ELSE))
+ {
+ vote_sp_brace_else.vote(pc, next);
+ }
+ else if (chunk_is_token(next, CT_CATCH))
+ {
+ vote_sp_brace_catch.vote(pc, next);
+ }
+ else if (chunk_is_token(next, CT_FINALLY))
+ {
+ vote_sp_brace_finally.vote(pc, next);
+ }
+ }
+ prev = pc;
+ pc = next;
+ }
+} // detect_space_options
+
+
+void detect_options(void)
+{
+ detect_space_options();
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.h
new file mode 100644
index 00000000..5c6ec1e2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/detect.h
@@ -0,0 +1,16 @@
+/**
+ * @file detect.h
+ * prototypes for detect.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef DETECT_H_INCLUDED
+#define DETECT_H_INCLUDED
+
+
+//! Call all the detect_xxxx() functions
+void detect_options(void);
+
+
+#endif /* DETECT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.cpp
new file mode 100644
index 00000000..f91a1a2a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.cpp
@@ -0,0 +1,96 @@
+/**
+ * @file enum_cleanup.cpp
+ * works on the last comma withing enum
+ *
+ * @author Guy Maurel Juli 2018
+ * @license GPL v2+
+ */
+
+#include "enum_cleanup.h"
+
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LTOK;
+
+using namespace uncrustify;
+
+
+void enum_cleanup(void)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_enum_last_comma");
+
+ if (options::mod_enum_last_comma() == IARF_IGNORE)
+ {
+ // nothing to do
+ return;
+ }
+ Chunk *pc = Chunk::GetHead(); // Issue #858
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( get_chunk_parent_type(pc) == CT_ENUM
+ && chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, type is %s\n",
+ __func__, __LINE__, pc->orig_line, get_token_name(pc->type));
+ Chunk *prev = pc->GetPrevNcNnl(); // Issue #3604
+
+ if ( prev != nullptr
+ && prev->IsNotNullChunk())
+ {
+ if (chunk_is_token(prev, CT_COMMA))
+ {
+ log_rule_B("mod_enum_last_comma");
+
+ if (options::mod_enum_last_comma() == IARF_REMOVE)
+ {
+ chunk_del(prev);
+ }
+ }
+ else
+ {
+ if (chunk_is_token(prev, CT_BRACE_OPEN)) // Issue #2902
+ {
+ // nothing between CT_BRACE_OPEN and CT_BRACE_CLOSE
+ }
+ else
+ {
+ log_rule_B("mod_enum_last_comma");
+
+ if ( options::mod_enum_last_comma() == IARF_ADD
+ || options::mod_enum_last_comma() == IARF_FORCE)
+ {
+ // create a comma
+ Chunk comma;
+ set_chunk_type(&comma, CT_COMMA);
+ comma.orig_line = prev->orig_line;
+ comma.orig_col = prev->orig_col + 1;
+ comma.nl_count = 0;
+ comma.pp_level = 0;
+ comma.flags = PCF_NONE;
+ comma.str = ",";
+
+ if (chunk_is_token(prev, CT_PP_ENDIF)) // Issue #3604
+ {
+ prev = prev->GetPrevNcNnlNpp();
+ }
+
+ if (chunk_is_token(prev, CT_COMMA)) // Issue #3604
+ {
+ // nothing to do
+ }
+ else
+ {
+ chunk_add_after(&comma, prev);
+ }
+ pc = pc->GetNext();
+ }
+ }
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+} // enum_cleanup
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.h
new file mode 100644
index 00000000..3853c8ea
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_cleanup.h
@@ -0,0 +1,16 @@
+/**
+ * @file enum_cleanup.h
+ *
+ * @author Guy Maurel Juli 2018
+ * @license GPL v2+
+ */
+#ifndef ENUM_CLEANUP_H_INCLUDED
+#define ENUM_CLEANUP_H_INCLUDED
+
+/**
+ * Scans through the whole list and does stuff.
+ * works on the last comma withing enum
+ */
+void enum_cleanup(void);
+
+#endif /* ENUM_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_flags.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_flags.h
new file mode 100644
index 00000000..badd8226
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/enum_flags.h
@@ -0,0 +1,120 @@
+/**
+ * @file enum_flags.h
+ * Operators for working with bit-flag enumerators.
+ *
+ * @author Matthew Woehlke (but mostly "borrowed" from Qt)
+ * @license GPL v2+
+ */
+
+#ifndef ENUM_FLAGS_H_INCLUDED
+#define ENUM_FLAGS_H_INCLUDED
+
+#include <type_traits>
+
+#if __GNUC__ == 4 && !defined (__clang__)
+#pragma GCC diagnostic push
+#if __GNUC_MINOR__ < 9 || __GNUC_PATCHLEVEL__ < 2
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59624
+#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
+#endif
+#endif
+
+#define UNC_DECLARE_FLAGS(flag_type, enum_type) \
+ using flag_type = ::uncrustify::flags<enum_type>
+
+#define UNC_DECLARE_OPERATORS_FOR_FLAGS(flag_type) \
+ inline flag_type operator&(flag_type::enum_t f1, flag_type::enum_t f2) \
+ { return(flag_type{ f1 } & f2); } \
+ inline flag_type operator|(flag_type::enum_t f1, flag_type::enum_t f2) \
+ { return(flag_type{ f1 } | f2); } \
+ inline flag_type operator|(flag_type::enum_t f1, flag_type f2) \
+ { return(f2 | f1); } \
+ inline void operator|(flag_type::enum_t f1, int f2) = delete
+
+namespace uncrustify
+{
+
+//-----------------------------------------------------------------------------
+template<typename Enum>
+class flags
+{
+public:
+ using enum_t = Enum;
+ using int_t = typename std::underlying_type<enum_t>::type;
+
+ template<typename T> using integral =
+ typename std::enable_if<std::is_integral<T>::value, bool>::type;
+
+ inline flags() = default;
+ inline flags(Enum flag)
+ : m_i{static_cast<int_t>(flag)}
+ {}
+
+ inline bool operator==(Enum const &other)
+ { return(m_i == static_cast<int_t>(other)); }
+ inline bool operator==(flags const &other)
+ { return(m_i == other.m_i); }
+ inline bool operator!=(Enum const &other)
+ { return(m_i != static_cast<int_t>(other)); }
+ inline bool operator!=(flags const &other)
+ { return(m_i != other.m_i); }
+
+ template<typename T, integral<T> = true>
+ inline flags &operator&=(T mask)
+ { m_i &= static_cast<int_t>(mask); return(*this); }
+
+ inline flags &operator|=(flags f)
+ { m_i |= f.m_i; return(*this); }
+ inline flags &operator|=(Enum f)
+ { m_i |= f; return(*this); }
+
+ inline flags &operator^=(flags f)
+ { m_i ^= f.m_i; return(*this); }
+ inline flags &operator^=(Enum f)
+ { m_i ^= f; return(*this); }
+
+ inline operator int_t() const { return(m_i); }
+ inline operator enum_t() const { return(static_cast<enum_t>(m_i)); }
+
+ inline flags operator&(Enum f) const
+ { flags g; g.m_i = m_i & static_cast<int_t>(f); return(g); }
+ inline flags operator&(flags f) const
+ { flags g; g.m_i = m_i & static_cast<int_t>(f); return(g); }
+
+ template<typename T, integral<T> = true>
+ inline flags operator&(T mask) const
+ { flags g; g.m_i = m_i & static_cast<int_t>(mask); return(g); }
+
+ inline flags operator|(flags f) const
+ { flags g; g.m_i = m_i | f.m_i; return(g); }
+ inline flags operator|(Enum f) const
+ { flags g; g.m_i = m_i | static_cast<int_t>(f); return(g); }
+
+ inline flags operator^(flags f) const
+ { flags g; g.m_i = m_i ^ f.m_i; return(g); }
+ inline flags operator^(Enum f) const
+ { flags g; g.m_i = m_i ^ static_cast<int_t>(f); return(g); }
+
+ inline int_t operator~() const
+ { return(~m_i); }
+
+ inline operator bool() const { return(!!m_i); }
+ inline bool operator!() const { return(!m_i); }
+
+ inline bool test(flags f) const { return((*this & f) == f); }
+ inline bool test(Enum f) const { return((*this & f) == f); }
+
+ inline bool test_any() const { return(m_i != 0); }
+ inline bool test_any(flags f) const { return((*this & f).test_any()); }
+
+protected:
+ int_t m_i = 0;
+};
+
+} // namespace uncrustify
+
+#if __GNUC__ == 4 && !defined (__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/error_types.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/error_types.h
new file mode 100644
index 00000000..4b162768
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/error_types.h
@@ -0,0 +1,53 @@
+/**
+ * @file error_types.h
+ *
+ * Defines the error codes that are used throughout uncrustify
+ *
+ * @license GPL v2+
+ */
+#ifndef ERROR_TYPES_H_INCLUDED
+#define ERROR_TYPES_H_INCLUDED
+
+#if 1
+#include <stdlib.h> // provides EXIT_SUCCESS and EXIT FAILURE
+
+// TODO: if we decided to only use EX_OK and EX_xxx we can avoid including stdlib.h here
+
+#else
+// TODO: I left this to show my modifications remove it after the PR was reviewed
+
+// the good old SUCCESS/FAILURE
+#define SUCCESS 0 //! same as EX_OK */
+#define FAILURE -1 //! incompatible to EXIT_FAILURE
+#endif
+
+
+#if defined (WIN32) || defined (__QNXNTO__)
+// Windows does not know sysexists.h. Thus define the error codes
+
+#define EX_OK 0 //! successful termination
+#define EX__BASE 64 //! base value for error messages
+#define EX_USAGE 64 //! command line usage error
+#define EX_DATAERR 65 //! data format error
+#define EX_NOINPUT 66 //! cannot open input
+#define EX_NOUSER 67 //! addressee unknown
+#define EX_NOHOST 68 //! host name unknown
+#define EX_UNAVAILABLE 69 //! service unavailable
+#define EX_SOFTWARE 70 //! internal software error
+#define EX_OSERR 71 //! system error (e.g., can't fork)
+#define EX_OSFILE 72 //! critical OS file missing
+#define EX_CANTCREAT 73 //! can't create (user) output file
+#define EX_IOERR 74 //! input/output error
+#define EX_TEMPFAIL 75 //! temp failure; user is invited to retry
+#define EX_PROTOCOL 76 //! remote error in protocol
+#define EX_NOPERM 77 //! permission denied
+#define EX_CONFIG 78 //! configuration error
+#define EX__MAX 78 //! maximum listed value
+
+#else // not WIN32 or not __QNXNTO__
+// TODO: do all non windows systems know sysexits.h?
+// Linux knows: /usr/include/sysexits.h
+#include "sysexits.h" // comes from BSD
+#endif
+
+#endif /* ERROR_TYPES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.cpp
new file mode 100644
index 00000000..8a5cbf3f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.cpp
@@ -0,0 +1,110 @@
+/**
+ * @file flag_braced_init_list.cpp
+ *
+ * @license GPL v2+
+ */
+
+#include "chunk.h"
+
+#include "flag_braced_init_list.h"
+
+#include "uncrustify.h"
+
+
+bool detect_cpp_braced_init_list(Chunk *pc, Chunk *next)
+{
+ LOG_FUNC_ENTRY();
+ // Issue #2332
+ bool we_have_a_case_before = false;
+
+ if (chunk_is_token(pc, CT_COLON))
+ {
+ // check if we have a case before
+ Chunk *switch_before = pc->GetPrevType(CT_CASE, pc->level);
+
+ if (switch_before->IsNotNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): switch_before->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, switch_before->orig_line, switch_before->orig_col,
+ switch_before->Text(), get_token_name(switch_before->type));
+ we_have_a_case_before = true;
+ }
+ }
+
+ // Detect a braced-init-list
+ if ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_RETURN)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE)
+ || chunk_is_token(pc, CT_SQUARE_CLOSE)
+ || chunk_is_token(pc, CT_TSQUARE)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_QUESTION)
+ || ( chunk_is_token(pc, CT_COLON)
+ && !we_have_a_case_before)
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && ( get_chunk_parent_type(pc) == CT_NONE
+ || get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST)))
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n ",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ log_pcf_flags(LFCNR, pc->flags);
+ auto brace_open = pc->GetNextNcNnl();
+
+ if ( chunk_is_token(brace_open, CT_BRACE_OPEN)
+ && ( get_chunk_parent_type(brace_open) == CT_NONE
+ || get_chunk_parent_type(brace_open) == CT_ASSIGN
+ || get_chunk_parent_type(brace_open) == CT_RETURN
+ || get_chunk_parent_type(brace_open) == CT_BRACED_INIT_LIST))
+ {
+ log_pcf_flags(LFCNR, brace_open->flags);
+ auto brace_close = chunk_skip_to_match(next);
+
+ if (chunk_is_token(brace_close, CT_BRACE_CLOSE))
+ {
+ return(true);
+ }
+ }
+ }
+ return(false);
+} // detect_cpp_braced_init_list
+
+
+void flag_cpp_braced_init_list(Chunk *pc, Chunk *next)
+{
+ auto brace_open = pc->GetNextNcNnl();
+ auto brace_close = chunk_skip_to_match(next);
+
+ set_chunk_parent(brace_open, CT_BRACED_INIT_LIST);
+ set_chunk_parent(brace_close, CT_BRACED_INIT_LIST);
+
+ auto *tmp = brace_close->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ chunk_flags_clr(tmp, PCF_EXPR_START | PCF_STMT_START);
+
+ // Flag call operator
+ if (chunk_is_token(tmp, CT_PAREN_OPEN))
+ {
+ if (auto *const c = chunk_skip_to_match(tmp))
+ {
+ set_chunk_type(tmp, CT_FPAREN_OPEN);
+ set_chunk_parent(tmp, CT_FUNC_CALL);
+ set_chunk_type(c, CT_FPAREN_CLOSE);
+ set_chunk_parent(c, CT_FUNC_CALL);
+ }
+ }
+ }
+ // TODO: Change pc->type CT_WORD -> CT_TYPE
+ // for the case CT_ASSIGN (and others).
+
+ // TODO: Move this block to the fix_fcn_call_args function.
+ if ( chunk_is_token(pc, CT_WORD)
+ && pc->flags.test(PCF_IN_FCN_CALL))
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+} // flag_cpp_braced_init_list
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.h
new file mode 100644
index 00000000..8d89dd08
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_braced_init_list.h
@@ -0,0 +1,25 @@
+/**
+ * @file flag_braced_init_list.h
+ *
+ * @license GPL v2+
+ */
+
+#ifndef FLAG_BRACED_INIT_LIST_INCLUDED
+#define FLAG_BRACED_INIT_LIST_INCLUDED
+
+
+/**
+ * Detect a cpp braced init list
+ */
+bool detect_cpp_braced_init_list(Chunk *pc, Chunk *next);
+
+
+/**
+ * Flags the opening and closing braces of an expression deemed to be
+ * a cpp braced initializer list; a call to detect_cpp_braced_init_list()
+ * should first be made prior to calling this function
+ */
+void flag_cpp_braced_init_list(Chunk *pc, Chunk *next);
+
+
+#endif
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.cpp
new file mode 100644
index 00000000..a3036f81
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.cpp
@@ -0,0 +1,46 @@
+/**
+ * @file flag_decltype.cpp
+ *
+ * @license GPL v2+
+ */
+
+#include "chunk.h"
+
+
+bool flag_cpp_decltype(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (chunk_is_token(pc, CT_DECLTYPE))
+ {
+ auto paren_open = pc->GetNextNcNnl();
+
+ if (chunk_is_token(paren_open, CT_PAREN_OPEN))
+ {
+ // We would like to simply call chunk_skip_to_match(), but it finds
+ // a match based on level, and the level is 0 for all chunks in some
+ // cases, like the following example.
+ //
+ // template <typename T>
+ // decltype(std::declval<T &>().put(foo), std::true_type())
+ // has_something(Tag<2>);
+ //
+ // This means that IN_DECLTYPE is only set for tokens through the
+ // closing parenthesis right before ".put" in the above example.
+ //
+ // So, we will manually look for the matching closing parenthesis.
+ chunk_flags_set(paren_open, PCF_IN_DECLTYPE);
+ pc = paren_open->GetNextNcNnl();
+
+ for (int level = 1; pc->IsNotNullChunk() && level > 0; pc = pc->GetNextNcNnl())
+ {
+ level += chunk_is_token(pc, CT_PAREN_OPEN);
+ level -= chunk_is_token(pc, CT_PAREN_CLOSE);
+ chunk_flags_set(pc, PCF_IN_DECLTYPE);
+ }
+
+ return(pc->IsNotNullChunk());
+ }
+ }
+ return(false);
+} // mark_cpp_decltype
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.h
new file mode 100644
index 00000000..80677c8e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_decltype.h
@@ -0,0 +1,20 @@
+/**
+ * @file flag_decltype.h
+ *
+ * @license GPL v2+
+ */
+
+#ifndef FLAG_DECLTYPE_INCLUDED
+#define FLAG_DECLTYPE_INCLUDED
+
+
+/**
+ * Flags all chunks within a cpp decltype expression from the opening
+ * brace to the closing brace
+ *
+ * @return Returns true if expression is a valid decltype expression
+ */
+bool flag_cpp_decltype(Chunk *pc);
+
+
+#endif
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.cpp
new file mode 100644
index 00000000..0f881553
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.cpp
@@ -0,0 +1,72 @@
+/**
+ * @file flag_parens.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "flag_parens.h"
+
+#include "uncrustify.h"
+
+
+Chunk *flag_parens(Chunk *po, pcf_flags_t flags, E_Token opentype, E_Token parenttype, bool parent_all)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *paren_close;
+
+ paren_close = chunk_skip_to_match(po, E_Scope::PREPROC);
+
+ if (paren_close == nullptr)
+ {
+ LOG_FMT(LERR, "%s(%d): no match for '%s' at [%zu:%zu]",
+ __func__, __LINE__, po->Text(), po->orig_line, po->orig_col);
+ log_func_stack_inline(LERR);
+ cpd.error_count++;
+ return(nullptr);
+ }
+ LOG_FMT(LFLPAREN, "%s(%d): between po is '%s', orig_line is %zu, orig_col is %zu, and\n",
+ __func__, __LINE__, po->Text(), po->orig_line, po->orig_col);
+ LOG_FMT(LFLPAREN, "%s(%d): paren_close is '%s', orig_line is %zu, orig_col is %zu, type is %s, parent_type is %s\n",
+ __func__, __LINE__, paren_close->Text(), paren_close->orig_line, paren_close->orig_col,
+ get_token_name(opentype), get_token_name(parenttype));
+ log_func_stack_inline(LFLPAREN);
+
+ // the last chunk must be also modified. Issue #2149
+ Chunk *after_paren_close = paren_close->GetNext();
+
+ if (po != paren_close)
+ {
+ if ( flags != PCF_NONE
+ || ( parent_all
+ && parenttype != CT_NONE))
+ {
+ Chunk *pc;
+
+ for (pc = po->GetNext(E_Scope::PREPROC);
+ pc != nullptr && pc->IsNotNullChunk() && pc != after_paren_close;
+ pc = pc->GetNext(E_Scope::PREPROC))
+ {
+ chunk_flags_set(pc, flags);
+
+ if (parent_all)
+ {
+ set_chunk_parent(pc, parenttype);
+ }
+ }
+ }
+
+ if (opentype != CT_NONE)
+ {
+ set_chunk_type(po, opentype);
+ set_chunk_type(paren_close, (E_Token)(opentype + 1));
+ }
+
+ if (parenttype != CT_NONE)
+ {
+ set_chunk_parent(po, parenttype);
+ set_chunk_parent(paren_close, parenttype);
+ }
+ }
+ return(paren_close->GetNextNcNnl(E_Scope::PREPROC));
+} // flag_parens
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.h
new file mode 100644
index 00000000..a093886c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/flag_parens.h
@@ -0,0 +1,28 @@
+/**
+ * @file flag_parens.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef FLAG_PARENS_H_INCLUDED
+#define FLAG_PARENS_H_INCLUDED
+
+#include "chunk.h"
+
+
+/**
+ * Flags everything from the open paren to the close paren.
+ *
+ * @param po Pointer to the open parenthesis
+ * @param flags flags to add
+ * @param opentype
+ * @param parenttype
+ * @param parent_all
+ *
+ * @return The token after the close paren
+ */
+Chunk *flag_parens(Chunk *po, pcf_flags_t flags, E_Token opentype, E_Token parenttype, bool parent_all);
+
+
+#endif /* FLAG_PARENS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.cpp
new file mode 100644
index 00000000..36c11020
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.cpp
@@ -0,0 +1,345 @@
+/**
+ * @file frame_list.cpp
+ * mainly used to handle preprocessor stuff
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "frame_list.h"
+
+#include "prototypes.h"
+
+
+namespace
+{
+
+void fl_log_frms(log_sev_t logsev, const char *txt, const ParseFrame &frm, const std::vector<ParseFrame> &frames);
+
+
+//! Logs the entire parse frame stack
+void fl_log_all(log_sev_t logsev, const std::vector<ParseFrame> &frames);
+
+
+/**
+ * Copy the top element of the frame list into the ParseFrame.
+ *
+ * If the frame list is empty nothing happens.
+ *
+ * This is called on #else and #elif.
+ */
+void fl_copy_tos(ParseFrame &pf, const std::vector<ParseFrame> &frames);
+
+
+/**
+ * Copy the 2nd top element off the list into the ParseFrame.
+ * This is called on #else and #elif.
+ * The stack contains [...] [base] [if] at this point.
+ * We want to copy [base].
+ */
+void fl_copy_2nd_tos(ParseFrame &pf, const std::vector<ParseFrame> &frames);
+
+
+//! Deletes the top element from the list.
+void fl_trash_tos(std::vector<ParseFrame> &frames);
+
+
+//! Logs one parse frame
+void fl_log(log_sev_t logsev, const ParseFrame &frm)
+{
+ LOG_FMT(logsev, "[%s] BrLevel=%zu Level=%zu PseTos=%zu\n",
+ get_token_name(frm.in_ifdef), frm.brace_level, frm.level, frm.size() - 1);
+
+ LOG_FMT(logsev, " *");
+
+ for (size_t idx = 1; idx < frm.size(); idx++)
+ {
+ LOG_FMT(logsev, " [%s-%s]", get_token_name(frm.at(idx).type),
+ get_brace_stage_name(frm.at(idx).stage));
+ }
+
+ LOG_FMT(logsev, "\n");
+}
+
+
+void fl_log_frms(log_sev_t logsev,
+ const char *txt,
+ const ParseFrame &frm,
+ const std::vector<ParseFrame> &frames)
+{
+ LOG_FMT(logsev, "%s Parse Frames(%zu):", txt, frames.size());
+
+ for (size_t idx = 0; idx < frames.size(); idx++)
+ {
+ LOG_FMT(logsev, " [%s-%zu]", get_token_name(frames.at(idx).in_ifdef),
+ frames.at(idx).ref_no);
+ }
+
+ LOG_FMT(logsev, "-[%s-%zu]\n", get_token_name(frm.in_ifdef), frm.ref_no);
+}
+
+
+void fl_log_all(log_sev_t logsev, const std::vector<ParseFrame> &frames)
+{
+ LOG_FMT(logsev, "##=- Parse Frame : %zu entries\n", frames.size());
+
+ for (size_t idx = 0; idx < frames.size(); idx++)
+ {
+ LOG_FMT(logsev, "## idx is %zu, ", idx);
+
+ fl_log(logsev, frames.at(idx));
+ }
+
+ LOG_FMT(logsev, "##=-\n");
+}
+
+
+void fl_copy_tos(ParseFrame &pf, const std::vector<ParseFrame> &frames)
+{
+ if (!frames.empty())
+ {
+ pf = *std::prev(std::end(frames));
+ }
+ LOG_FMT(LPF, "%s(%d): frame_count is %zu\n", __func__, __LINE__, frames.size());
+}
+
+
+void fl_copy_2nd_tos(ParseFrame &pf, const std::vector<ParseFrame> &frames)
+{
+ if (frames.size() > 1)
+ {
+ pf = *std::prev(std::end(frames), 2);
+ }
+ LOG_FMT(LPF, "%s(%d): frame_count is %zu\n", __func__, __LINE__, frames.size());
+}
+
+
+void fl_trash_tos(std::vector<ParseFrame> &frames)
+{
+ if (!frames.empty())
+ {
+ frames.pop_back();
+ }
+ LOG_FMT(LPF, "%s(%d): frame_count is %zu\n", __func__, __LINE__, frames.size());
+}
+
+} // namespace
+
+
+void fl_push(std::vector<ParseFrame> &frames, ParseFrame &frm)
+{
+ static int ref_no = 1;
+
+ frames.push_back(frm);
+ frm.ref_no = ref_no++;
+
+ LOG_FMT(LPF, "%s(%d): frame_count is %zu\n", __func__, __LINE__, frames.size());
+}
+
+
+void fl_pop(std::vector<ParseFrame> &frames, ParseFrame &pf)
+{
+ if (frames.empty())
+ {
+ return;
+ }
+ fl_copy_tos(pf, frames);
+ fl_trash_tos(frames);
+}
+
+
+int fl_check(std::vector<ParseFrame> &frames, ParseFrame &frm, int &pp_level, Chunk *pc)
+{
+ if (pc->type != CT_PREPROC)
+ {
+ return(pp_level);
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ return(pp_level);
+ }
+
+ if (get_chunk_parent_type(pc) != next->type)
+ {
+ LOG_FMT(LNOTE, "%s(%d): Preproc parent not set correctly on orig_line %zu: got %s expected %s\n",
+ __func__, __LINE__, pc->orig_line, get_token_name(get_chunk_parent_type(pc)),
+ get_token_name(next->type));
+ set_chunk_parent(pc, next->type);
+ }
+ LOG_FMT(LPFCHK, "%s(%d): orig_line is %zu, %s\n",
+ __func__, __LINE__, pc->orig_line, get_token_name(get_chunk_parent_type(pc)));
+ fl_log_frms(LPFCHK, "TOP", frm, frames);
+
+
+ int out_pp_level = pp_level;
+ const E_Token in_ifdef = frm.in_ifdef;
+ const size_t b4_cnt = frames.size();
+
+ const char *txt = nullptr;
+
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ LOG_FMT(LPF, " <In> ");
+ fl_log(LPF, frm);
+
+ if (get_chunk_parent_type(pc) == CT_PP_IF)
+ {
+ // An #if pushes a copy of the current frame on the stack
+ pp_level++;
+ fl_push(frames, frm);
+ frm.in_ifdef = CT_PP_IF;
+ txt = "if-push";
+ }
+ else if (get_chunk_parent_type(pc) == CT_PP_ELSE)
+ {
+ if (out_pp_level == 0)
+ {
+ fprintf(stderr, "%s(%d): pp_level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ out_pp_level--;
+
+ /*
+ * For #else of #elif, we want to keep the #if part and throw out the
+ * else parts.
+ * We check to see what the top type is to see if we just push or
+ * pop and then push.
+ * We need to use the copy right before the if.
+ */
+ bool if_block = false;
+
+ if (frm.in_ifdef == CT_PP_IF)
+ {
+ // we have [...] [base]-[if], so push an [else]
+ fl_push(frames, frm);
+ frm.in_ifdef = CT_PP_ELSE;
+ if_block = true;
+ }
+ size_t brace_level = frm.brace_level;
+ // we have [...] [base] [if]-[else], copy [base] over [else]
+ fl_copy_2nd_tos(frm, frames);
+ frm.in_ifdef = CT_PP_ELSE;
+
+ if (if_block)
+ {
+ // check if #if block was unbalanced
+ size_t base_brace_level = frames[frames.size() - 2].brace_level;
+
+ if ( options::pp_warn_unbalanced_if()
+ && brace_level != base_brace_level)
+ {
+ LOG_FMT(LWARN, "%s(%d): orig_line is %zu, unbalanced #if block braces (1), in-level is %zu, out-level is %zu\n",
+ __func__, __LINE__, pc->orig_line, base_brace_level, brace_level);
+ }
+ }
+ else
+ {
+ // check if previous #else block has a different indentation than the corresponding #if block
+ size_t if_brace_level = frames[frames.size() - 1].brace_level;
+
+ if ( options::pp_warn_unbalanced_if()
+ && brace_level != if_brace_level)
+ {
+ LOG_FMT(LWARN, "%s(%d): orig_line is %zu, unbalanced #if-#else block braces (1), #else out-level is %zu, #if out-level is %zu\n",
+ __func__, __LINE__, pc->orig_line, brace_level, if_brace_level);
+ }
+ }
+ txt = "else-push";
+ }
+ else if (get_chunk_parent_type(pc) == CT_PP_ENDIF)
+ {
+ /*
+ * we may have [...] [base] [if]-[else] or [...] [base]-[if].
+ * Throw out the [else].
+ */
+ if (pp_level == 0)
+ {
+ // cpd.pp_level is ZERO, cannot be decremented.
+ fprintf(stderr, "%s(%d): #endif found, at line %zu, column %zu, without corresponding #if\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ pp_level--;
+
+ if (out_pp_level == 0)
+ {
+ fprintf(stderr, "%s(%d): pp_level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ out_pp_level--;
+
+ if (frm.in_ifdef == CT_PP_ELSE)
+ {
+ size_t brace_level = frm.brace_level; // brace level or current #else block
+ /*
+ * We have: [...] [base] [if]-[else]
+ * We want: [...]-[if]
+ */
+ fl_copy_tos(frm, frames); // [...] [base] [if]-[if]
+
+ if ( options::pp_warn_unbalanced_if()
+ && brace_level != frm.brace_level)
+ {
+ LOG_FMT(LWARN, "%s(%d): orig_line is %zu, unbalanced #if-#else block braces (2), #else out-level is %zu, #if out-level is %zu\n",
+ __func__, __LINE__, pc->orig_line, brace_level, frm.brace_level);
+ }
+
+ if (frames.size() < 2)
+ {
+ fprintf(stderr, "Number of 'frame' is too small.\n");
+ fprintf(stderr, "Please make a report.\n");
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ frm.in_ifdef = frames[frames.size() - 2].in_ifdef;
+ fl_trash_tos(frames); // [...] [base]-[if]
+ fl_trash_tos(frames); // [...]-[if]
+
+ txt = "endif-trash/pop";
+ }
+ else if (frm.in_ifdef == CT_PP_IF)
+ {
+ /*
+ * We have: [...] [base] [if]
+ * We want: [...] [base]
+ */
+ // check if #if block was unbalanced
+ size_t brace_level = frm.brace_level;
+ fl_pop(frames, frm);
+
+ if ( options::pp_warn_unbalanced_if()
+ && brace_level != frm.brace_level)
+ {
+ LOG_FMT(LWARN, "%s(%d): orig_line is %zu, unbalanced #if block braces (2), in-level is %zu, out-level is %zu\n",
+ __func__, __LINE__, pc->orig_line, frm.brace_level, brace_level);
+ }
+ txt = "endif-pop";
+ }
+ else
+ {
+ txt = "???";
+ }
+ }
+ }
+
+ if (txt != nullptr)
+ {
+ LOG_FMT(LPF, "%s(%d): orig_line is %zu, type is %s: %s in_ifdef is %s/%s, counts is %zu, frame_count is %zu\n",
+ __func__, __LINE__, pc->orig_line,
+ get_token_name(get_chunk_parent_type(pc)), txt, get_token_name(in_ifdef),
+ get_token_name(frm.in_ifdef), b4_cnt, frames.size());
+ fl_log_all(LPF, frames);
+ LOG_FMT(LPF, " <Out>");
+ fl_log(LPF, frm);
+ }
+ fl_log_frms(LPFCHK, "END", frm, frames);
+
+ return(out_pp_level);
+} // fl_check
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.h
new file mode 100644
index 00000000..5fd09a52
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/frame_list.h
@@ -0,0 +1,40 @@
+/**
+ * @file frame_list.h
+ * mainly used to handle preprocessor stuff
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef PARSE_FRAME_H_INCLUDED
+#define PARSE_FRAME_H_INCLUDED
+
+#include "ParseFrame.h"
+#include "uncrustify_types.h"
+
+
+/**
+ * Push a copy of a ParseFrame onto the frames list.
+ * This is called on #if and #ifdef.
+ */
+void fl_push(std::vector<ParseFrame> &frames, ParseFrame &frm);
+
+
+/**
+ * Pop the top element off the frame list and copy it into the ParseFrame.
+ *
+ * Does nothing if the frame list is empty.
+ *
+ * This is called on #endif
+ */
+void fl_pop(std::vector<ParseFrame> &frames, ParseFrame &pf);
+
+
+// TODO: this name is dumb:
+// - what is it checking?
+// - why does is much more than simple checks, it allters kinds of stuff
+//! Returns the pp_indent to use for this line
+int fl_check(std::vector<ParseFrame> &frames, ParseFrame &frm, int &pp_level, Chunk *pc);
+
+
+#endif /* PARSE_FRAME_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.cpp
new file mode 100644
index 00000000..e23dc25c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.cpp
@@ -0,0 +1,4776 @@
+/**
+ * @file indent.cpp
+ * Does all the indenting stuff.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel October 2015- 2021
+ * @license GPL v2+
+ */
+
+#include "indent.h"
+
+#include "align.h"
+#include "frame_list.h"
+#include "options_for_QT.h"
+#include "prototypes.h"
+#include "quick_align_again.h"
+#include "space.h"
+
+#ifdef WIN32
+#include <algorithm> // to get max
+#endif // ifdef WIN32
+
+#ifdef IGNORE // WinBase.h
+#undef IGNORE
+#endif
+
+
+constexpr static auto LCURRENT = LINDENT;
+
+using namespace std;
+using namespace uncrustify;
+
+
+/**
+ * General indenting approach:
+ * Indenting levels are put into a stack.
+ *
+ * The stack entries contain:
+ * - opening type
+ * - brace column
+ * - continuation column
+ *
+ * Items that start a new stack item:
+ * - preprocessor (new parse frame)
+ * - Brace Open (Virtual brace also)
+ * - Paren, Square, Angle open
+ * - Assignments
+ * - C++ '<<' operator (ie, cout << "blah")
+ * - case
+ * - class colon
+ * - return
+ * - types
+ * - any other continued statement
+ *
+ * Note that the column of items marked 'PCF_WAS_ALIGNED' is not changed.
+ *
+ * For an open brace:
+ * - indent increases by indent_columns
+ * - if part of if/else/do/while/switch/etc, an extra indent may be applied
+ * - if in a paren, then cont-col is set to column + 1, ie "({ some code })"
+ *
+ * Open paren/square/angle:
+ * cont-col is set to the column of the item after the open paren, unless
+ * followed by a newline, then it is set to (brace-col + indent_columns).
+ * Examples:
+ * a_really_long_funcion_name(
+ * param1, param2);
+ * a_really_long_funcion_name(param1,
+ * param2);
+ *
+ * Assignments:
+ * Assignments are continued aligned with the first item after the assignment,
+ * unless the assign is followed by a newline.
+ * Examples:
+ * some.variable = asdf + asdf +
+ * asdf;
+ * some.variable =
+ * asdf + asdf + asdf;
+ *
+ * C++ << operator:
+ * Handled the same as assignment.
+ * Examples:
+ * cout << "this is test number: "
+ * << test_number;
+ *
+ * case:
+ * Started with case or default.
+ * Terminated with close brace at level or another case or default.
+ * Special indenting according to various rules.
+ * - indent of case label
+ * - indent of case body
+ * - how to handle optional braces
+ * Examples:
+ * {
+ * case x: {
+ * a++;
+ * break;
+ * }
+ * case y:
+ * b--;
+ * break;
+ * default:
+ * c++;
+ * break;
+ * }
+ *
+ * Class colon:
+ * Indent continuation by indent_columns:
+ * class my_class :
+ * baseclass1,
+ * baseclass2
+ * {
+ *
+ * Return: same as assignments
+ * If the return statement is not fully paren'd, then the indent continues at
+ * the column of the item after the return. If it is paren'd, then the paren
+ * rules apply.
+ * return somevalue +
+ * othervalue;
+ *
+ * Type: pretty much the same as assignments
+ * Examples:
+ * int foo,
+ * bar,
+ * baz;
+ *
+ * Any other continued item:
+ * There shouldn't be anything not covered by the above cases, but any other
+ * continued item is indented by indent_columns:
+ * Example:
+ * somereallycrazylongname.with[lotsoflongstuff].
+ * thatreallyannoysme.whenIhavetomaintain[thecode] = 3;
+ */
+
+/**
+ * REVISIT: This needs to be re-checked, maybe cleaned up
+ *
+ * Indents comments in a (hopefully) smart manner.
+ *
+ * There are two type of comments that get indented:
+ * - stand alone (ie, no tokens on the line before the comment)
+ * - trailing comments (last token on the line apart from a linefeed)
+ * + note that a stand-alone comment is a special case of a trailing
+ *
+ * The stand alone comments will get indented in one of three ways:
+ * - column 1:
+ * + There is an empty line before the comment AND the indent level is 0
+ * + The comment was originally in column 1
+ *
+ * - Same column as trailing comment on previous line (ie, aligned)
+ * + if originally within TBD (3) columns of the previous comment
+ *
+ * - syntax indent level
+ * + doesn't fit in the previous categories
+ *
+ * Options modify this behavior:
+ * - keep original column (don't move the comment, if possible)
+ * - keep relative column (move out the same amount as first item on line)
+ * - fix trailing comment in column TBD
+ *
+ * @param pc The comment, which is the first item on a line
+ * @param col The column if this is to be put at indent level
+ */
+static void indent_comment(Chunk *pc, size_t col);
+
+
+static size_t token_indent(E_Token type);
+
+
+static size_t calc_indent_continue(const ParseFrame &frm, size_t pse_tos);
+
+/**
+ * Get candidate chunk first on line to which OC blocks can be indented against.
+ */
+static Chunk *candidate_chunk_first_on_line(Chunk *pc);
+
+/**
+ * We are on a '{' that has parent = OC_BLOCK_EXPR
+ * find the column of the param tag
+ */
+static Chunk *oc_msg_block_indent(Chunk *pc, bool from_brace, bool from_caret, bool from_colon, bool from_keyword);
+
+
+/**
+ * returns true if forward or reverse scan reveals only single newlines or comments
+ * stops when hits code
+ * false if next thing hit is a closing brace, also if 2 newlines in a row
+ */
+static bool single_line_comment_indent_rule_applies(Chunk *start, bool forward);
+
+/**
+ * returns true if semicolon on the same level ends any assign operations
+ * false if next thing hit is not the end of an assign operation
+ */
+static bool is_end_of_assignment(Chunk *pc, const ParseFrame &frm);
+
+
+void indent_to_column(Chunk *pc, size_t column)
+{
+ LOG_FUNC_ENTRY();
+
+ if (column < pc->column)
+ {
+ column = pc->column;
+ }
+ reindent_line(pc, column);
+}
+
+
+enum class align_mode_e : unsigned int
+{
+ SHIFT, //! shift relative to the current column
+ KEEP_ABS, //! try to keep the original absolute column
+ KEEP_REL, //! try to keep the original gap
+};
+
+
+enum class indent_mode_e : int
+{
+ INDENT = 0, //! indent by one level
+ ALIGN = 1, //! align under the open brace/parenthesis
+ IGNORE = -1, //! preserve original indentation
+};
+
+
+void align_to_column(Chunk *pc, size_t column)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc == nullptr
+ || column == pc->column)
+ {
+ return;
+ }
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s => column is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->column, pc->Text(),
+ get_token_name(pc->type), column);
+
+ const auto col_delta = static_cast<int>(column) - static_cast<int>(pc->column);
+ size_t min_col = column;
+
+ pc->column = column;
+
+ do
+ {
+ auto *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ const size_t min_delta = space_col_align(pc, next);
+ min_col += min_delta;
+
+ const auto *prev = pc;
+ pc = next;
+
+ auto almod = align_mode_e::SHIFT;
+
+ if ( pc->IsComment()
+ && get_chunk_parent_type(pc) != CT_COMMENT_EMBED)
+ {
+ log_rule_B("indent_relative_single_line_comments");
+ almod = ( chunk_is_single_line_comment(pc)
+ && options::indent_relative_single_line_comments())
+ ? align_mode_e::KEEP_REL : align_mode_e::KEEP_ABS;
+ }
+
+ if (almod == align_mode_e::KEEP_ABS)
+ {
+ // Keep same absolute column
+ pc->column = max(pc->orig_col, min_col);
+ }
+ else if (almod == align_mode_e::KEEP_REL)
+ {
+ // Keep same relative column
+ auto orig_delta = static_cast<int>(pc->orig_col) - static_cast<int>(prev->orig_col);
+ orig_delta = max<int>(orig_delta, min_delta); // keeps orig_delta positive
+
+ pc->column = prev->column + static_cast<size_t>(orig_delta);
+ }
+ else // SHIFT
+ {
+ // Shift by the same amount, keep above negative values
+ pc->column = ( col_delta >= 0
+ || cast_abs(pc->column, col_delta) < pc->column)
+ ? pc->column + col_delta : 0;
+ pc->column = max(pc->column, min_col);
+ }
+ LOG_FMT(LINDLINED, "%s(%d): %s set column of '%s', type is %s, orig_line is %zu, to col %zu (orig_col was %zu)\n",
+ __func__, __LINE__,
+ (almod == align_mode_e::KEEP_ABS) ? "abs" :
+ (almod == align_mode_e::KEEP_REL) ? "rel" : "sft",
+ pc->Text(), get_token_name(pc->type), pc->orig_line, pc->column, pc->orig_col);
+ } while ( pc->IsNotNullChunk()
+ && pc->nl_count == 0);
+} // align_to_column
+
+
+void reindent_line(Chunk *pc, size_t column)
+{
+ LOG_FUNC_ENTRY();
+ char copy[1000];
+
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, on '%s' [%s/%s] => %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy),
+ get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)),
+ column);
+ log_func_stack_inline(LINDLINE);
+
+ if (column == pc->column)
+ {
+ return;
+ }
+ auto col_delta = static_cast<int>(column) - static_cast<int>(pc->column);
+ auto min_col = column;
+
+ pc->column = column;
+
+ do
+ {
+ if (QT_SIGNAL_SLOT_found)
+ {
+ // fix the bug #654
+ // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &)));
+ // look for end of SIGNAL/SLOT block
+ if (!pc->flags.test(PCF_IN_QT_MACRO))
+ {
+ LOG_FMT(LINDLINE, "FLAGS is NOT set: PCF_IN_QT_MACRO\n");
+ restore_options_for_QT();
+ }
+ }
+ else
+ {
+ // look for begin of SIGNAL/SLOT block
+ if (pc->flags.test(PCF_IN_QT_MACRO))
+ {
+ LOG_FMT(LINDLINE, "FLAGS is set: PCF_IN_QT_MACRO\n");
+ save_set_options_for_QT(pc->level);
+ }
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+
+ if (pc->nl_count)
+ {
+ min_col = 0;
+ col_delta = 0;
+ }
+ min_col += space_col_align(pc, next);
+ pc = next;
+
+ const bool is_comment = pc->IsComment();
+ log_rule_B("indent_relative_single_line_comments");
+ const bool keep = ( is_comment
+ && chunk_is_single_line_comment(pc)
+ && options::indent_relative_single_line_comments());
+
+ if ( is_comment
+ && get_chunk_parent_type(pc) != CT_COMMENT_EMBED
+ && !keep)
+ {
+ pc->column = max(pc->orig_col, min_col);
+ LOG_FMT(LINDLINE, "%s(%d): set comment on line %zu to col %zu (orig %zu)\n",
+ __func__, __LINE__, pc->orig_line, pc->column, pc->orig_col);
+ }
+ else
+ {
+ const auto tmp_col = static_cast<int>(pc->column) + col_delta;
+ pc->column = max(tmp_col, static_cast<int>(min_col));
+
+ LOG_FMT(LINDLINED, "%s(%d): set column of ", __func__, __LINE__);
+
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LINDLINED, "<Newline>");
+ }
+ else
+ {
+ LOG_FMT(LINDLINED, "'%s'", pc->Text());
+ }
+ LOG_FMT(LINDLINED, " to %zu (orig %zu)\n", pc->column, pc->orig_col);
+ }
+ } while ( pc->IsNotNullChunk()
+ && pc->nl_count == 0);
+} // reindent_line
+
+
+static size_t token_indent(E_Token type)
+{
+ switch (type)
+ {
+ case CT_IF:
+ case CT_DO:
+ return(3);
+
+ case CT_FOR:
+ case CT_ELSE: // wacky, but that's what is wanted
+ return(4);
+
+ case CT_WHILE:
+ case CT_USING_STMT:
+ return(6);
+
+ case CT_SWITCH:
+ return(7);
+
+ case CT_ELSEIF:
+ return(8);
+
+ case CT_SYNCHRONIZED:
+ return(13);
+
+ default:
+ return(0);
+ }
+}
+
+
+#define indent_column_set(X) \
+ do { \
+ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, indent_column changed from %zu to %zu\n", \
+ __func__, __LINE__, pc->orig_line, indent_column, (size_t)X); \
+ indent_column = (X); \
+ } while (false)
+
+
+static size_t get_indent_first_continue(Chunk *pc)
+{
+ log_rule_B("indent_ignore_first_continue");
+ Chunk *continuation = pc->GetNextType(CT_NEWLINE, pc->level);
+
+ if (continuation->IsNotNullChunk())
+ {
+ continuation = continuation->GetNext();
+
+ if (continuation->IsNotNullChunk())
+ {
+ return(continuation->orig_col);
+ }
+ }
+ return(0);
+}
+
+
+static size_t calc_indent_continue(const ParseFrame &frm, size_t pse_tos)
+{
+ log_rule_B("indent_continue");
+ const int ic = options::indent_continue();
+
+ if ( ic < 0
+ && frm.at(pse_tos).indent_cont)
+ {
+ return(frm.at(pse_tos).indent);
+ }
+ return(frm.at(pse_tos).indent + abs(ic));
+}
+
+
+static size_t calc_indent_continue(const ParseFrame &frm)
+{
+ return(calc_indent_continue(frm, frm.size() - 1));
+}
+
+
+static Chunk *candidate_chunk_first_on_line(Chunk *pc)
+{
+ Chunk *first = chunk_first_on_line(pc);
+
+ log_rule_B("indent_inside_ternary_operator");
+
+ if ( options::indent_inside_ternary_operator()
+ && ( chunk_is_token(first, CT_QUESTION)
+ || chunk_is_token(first, CT_COND_COLON)))
+ {
+ return(first->GetNextNcNnl());
+ }
+ else
+ {
+ return(first);
+ }
+}
+
+
+static Chunk *oc_msg_block_indent(Chunk *pc, bool from_brace,
+ bool from_caret, bool from_colon,
+ bool from_keyword)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *tmp = Chunk::NullChunkPtr;
+
+ if (pc != nullptr)
+ {
+ tmp = pc->GetPrevNc();
+ }
+
+ if (from_brace)
+ {
+ return(pc);
+ }
+
+ // Skip to open paren in ':^TYPE *(ARGS) {'
+ if (chunk_is_paren_close(tmp))
+ {
+ tmp = chunk_skip_to_match_rev(tmp)->GetPrevNc();
+ }
+
+ // // Check for star in ':^TYPE *(ARGS) {'. Issue 2477
+ if (chunk_is_token(tmp, CT_PTR_TYPE))
+ {
+ tmp = tmp->GetPrevNc();
+ }
+
+ // Check for type in ':^TYPE *(ARGS) {'. Issue 2482
+ if (chunk_is_token(tmp, CT_TYPE))
+ {
+ tmp = tmp->GetPrevNc();
+ }
+ // Check for caret in ':^TYPE *(ARGS) {'
+ // Store the caret position
+ Chunk *caret_tmp = Chunk::NullChunkPtr;
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->type == CT_OC_BLOCK_CARET)
+ {
+ caret_tmp = tmp;
+ }
+ else
+ {
+ caret_tmp = tmp->GetPrevType(CT_OC_BLOCK_CARET, -1);
+ tmp = caret_tmp;
+ }
+
+ // If we still cannot find caret then return first chunk on the line
+ if ( tmp->IsNullChunk()
+ || tmp->type != CT_OC_BLOCK_CARET)
+ {
+ return(candidate_chunk_first_on_line(pc));
+ }
+
+ if (from_caret)
+ {
+ return(tmp);
+ }
+ tmp = tmp->GetPrevNc();
+
+ // Check for colon in ':^TYPE *(ARGS) {'
+ if (from_colon)
+ {
+ if ( tmp->IsNullChunk()
+ || tmp->type != CT_OC_COLON)
+ {
+ return(candidate_chunk_first_on_line(pc));
+ }
+ else
+ {
+ return(tmp);
+ }
+ }
+ tmp = tmp->GetPrevNc();
+
+ if (from_keyword)
+ {
+ if ( tmp->IsNullChunk()
+ || ( tmp->type != CT_OC_MSG_NAME
+ && tmp->type != CT_OC_MSG_FUNC))
+ {
+ return(candidate_chunk_first_on_line(pc));
+ }
+ else
+ {
+ return(tmp);
+ }
+ }
+ // In almost all the cases, its better to return the first chunk on the line than not indenting at all.
+ tmp = candidate_chunk_first_on_line(pc);
+ return(tmp);
+} // oc_msg_block_indent
+
+
+#define log_indent() \
+ do { _log_indent(__func__, __LINE__, frm); \
+ } while (false)
+
+
+static void _log_indent(const char *func, const uint32_t line, const ParseFrame &frm)
+{
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ...indent is %zu\n",
+ func, line, frm.size() - 1, frm.top().indent);
+}
+
+
+#define log_prev_indent() \
+ do { _log_prev_indent(__func__, __LINE__, frm); \
+ } while (false)
+
+
+static void _log_prev_indent(const char *func, const uint32_t line, const ParseFrame &frm)
+{
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, prev....indent is %zu\n",
+ func, line, frm.size() - 1, frm.prev().indent);
+}
+
+
+#define log_indent_tmp() \
+ do { _log_indent_tmp(__func__, __LINE__, frm); \
+ } while (false)
+
+
+static void _log_indent_tmp(const char *func, const uint32_t line, const ParseFrame &frm)
+{
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ...indent_tmp is %zu\n",
+ func, line, frm.size() - 1, frm.top().indent_tmp);
+}
+
+
+static void quick_indent_again(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->indent.ref == nullptr)
+ {
+ continue;
+ }
+ Chunk *tmp = pc->GetPrev();
+
+ if (!chunk_is_newline(tmp))
+ {
+ continue;
+ }
+ const size_t col = pc->indent.ref->column + pc->indent.delta;
+ indent_to_column(pc, col);
+
+ LOG_FMT(LINDENTAG, "%s(%d): [%zu] indent [%s] to %zu based on [%s] @ %zu:%zu\n",
+ __func__, __LINE__, pc->orig_line, pc->Text(), col,
+ pc->indent.ref->Text(), pc->indent.ref->orig_line,
+ pc->indent.ref->column);
+ }
+}
+
+
+void indent_text(void)
+{
+ LOG_FUNC_ENTRY();
+ bool did_newline = true;
+ size_t vardefcol = 0;
+
+ log_rule_B("indent_columns");
+ const size_t indent_size = options::indent_columns();
+ size_t indent_column = 0;
+ int xml_indent = 0;
+ size_t sql_col = 0;
+ size_t sql_orig_col = 0;
+ bool in_func_def = false;
+
+
+ std::vector<ParseFrame> frames;
+ ParseFrame frm{};
+
+
+ Chunk *pc = Chunk::GetHead();
+ bool classFound = false; // Issue #672
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, for '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ // forces string literal to column-1 [Fix for 1246]
+ log_rule_B("indent_col1_multi_string_literal");
+
+ if ( (pc->type == CT_STRING_MULTI)
+ && !(cpd.lang_flags & LANG_OC) // Issue #1795
+ && options::indent_col1_multi_string_literal())
+ {
+ string str = pc->Text();
+
+ if ( (str[0] == '@')
+ && (pc->GetPrev()->type == CT_NEWLINE))
+ {
+ indent_column_set(1);
+ reindent_line(pc, indent_column);
+ pc = pc->GetNext();
+ did_newline = false;
+ }
+ }
+
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, <Newline>\n",
+ __func__, __LINE__, pc->orig_line);
+ }
+ else if (chunk_is_token(pc, CT_NL_CONT))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, CT_NL_CONT\n",
+ __func__, __LINE__, pc->orig_line);
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, column is %zu, for '%s'\n ",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->column, pc->ElidedText(copy));
+ log_pcf_flags(LINDLINE, pc->flags);
+ }
+ log_rule_B("use_options_overriding_for_qt_macros");
+
+ if ( options::use_options_overriding_for_qt_macros()
+ && ( strcmp(pc->Text(), "SIGNAL") == 0
+ || strcmp(pc->Text(), "SLOT") == 0))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): orig_line=%zu: type %s SIGNAL/SLOT found\n",
+ __func__, __LINE__, pc->orig_line, get_token_name(pc->type));
+ }
+ // Handle preprocessor transitions
+ log_rule_B("indent_brace_parent");
+ const size_t parent_token_indent = (options::indent_brace_parent())
+ ? token_indent(get_chunk_parent_type(pc)) : 0;
+
+ // Handle "force indentation of function definition to start in column 1"
+ log_rule_B("indent_func_def_force_col1");
+
+ if (options::indent_func_def_force_col1())
+ {
+ if (!in_func_def)
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || ( chunk_is_token(pc, CT_COMMENT)
+ && next->IsNotNullChunk()
+ && get_chunk_parent_type(next) == CT_FUNC_DEF))
+ {
+ in_func_def = true;
+ frm.push(pc, __func__, __LINE__);
+ frm.top().indent_tmp = 1;
+ frm.top().indent = 1;
+ frm.top().indent_tab = 1;
+ }
+ }
+ else
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_FUNC_DEF)
+ {
+ in_func_def = false;
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ }
+ // Clean up after a #define, etc
+ const bool in_preproc = pc->flags.test(PCF_IN_PREPROC);
+
+ if (!in_preproc)
+ {
+ while ( !frm.empty()
+ && frm.top().in_preproc)
+ {
+ const E_Token type = frm.top().type;
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+
+ /*
+ * If we just removed an #endregion, then check to see if a
+ * PP_REGION_INDENT entry is right below it
+ */
+ if ( type == CT_PP_ENDREGION
+ && frm.top().type == CT_PP_REGION_INDENT)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_PREPROC)) // #
+ {
+ // Close out PP_IF_INDENT before playing with the parse frames
+ if ( frm.top().type == CT_PP_IF_INDENT
+ && ( get_chunk_parent_type(pc) == CT_PP_ENDIF
+ || get_chunk_parent_type(pc) == CT_PP_ELSE))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ ParseFrame frmbkup = frm;
+ fl_check(frames, frm, cpd.pp_level, pc);
+
+ // Indent the body of a #region here
+ log_rule_B("pp_region_indent_code");
+
+ if ( options::pp_region_indent_code()
+ && get_chunk_parent_type(pc) == CT_PP_REGION)
+ {
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ // Hack to get the logs to look right
+ set_chunk_type(next, CT_PP_REGION_INDENT);
+ frm.push(next, __func__, __LINE__);
+ set_chunk_type(next, CT_PP_REGION);
+
+ // Indent one level
+ frm.top().indent = frm.prev().indent + indent_size;
+ log_indent();
+
+ frm.top().indent_tab = frm.prev().indent_tab + indent_size;
+ frm.top().indent_tmp = frm.top().indent;
+ frm.top().in_preproc = false;
+ log_indent_tmp();
+ }
+ // If option set, remove indent inside switch statement
+ log_rule_B("indent_switch_pp");
+
+ if ( frm.top().type == CT_CASE
+ && !options::indent_switch_pp())
+ {
+ frm.push(pc, __func__, __LINE__);
+ LOG_FMT(LINDPC, "%s(%d): frm.top().indent is %zu, indent_size is %zu\n",
+ __func__, __LINE__, frm.top().indent, indent_size);
+
+ if (frm.top().indent >= indent_size)
+ {
+ frm.prev().indent = frm.top().indent - indent_size;
+ }
+ log_prev_indent();
+ }
+ // Indent the body of a #if here
+ log_rule_B("pp_if_indent_code");
+
+ if ( options::pp_if_indent_code()
+ && ( get_chunk_parent_type(pc) == CT_PP_IF
+ || get_chunk_parent_type(pc) == CT_PP_ELSE))
+ {
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ int should_indent_preproc = true;
+ int should_ignore_preproc = false;
+ Chunk *preproc_next = pc->GetNextNl();
+ preproc_next = preproc_next->GetNextNcNnlNet();
+
+ /* Look ahead at what's on the line after the #if */
+ log_rule_B("pp_indent_brace");
+ log_rule_B("pp_indent_func_def");
+ log_rule_B("pp_indent_case");
+ log_rule_B("pp_indent_extern");
+
+ while ( preproc_next->IsNotNullChunk()
+ && preproc_next->type != CT_NEWLINE)
+ {
+ if ( (chunk_is_token(preproc_next, CT_BRACE_OPEN))
+ || (chunk_is_token(preproc_next, CT_BRACE_CLOSE)))
+ {
+ if (options::pp_indent_brace() == 0)
+ {
+ should_indent_preproc = false;
+ break;
+ }
+ else if (options::pp_indent_brace() == -1)
+ {
+ should_ignore_preproc = true;
+ break;
+ }
+ }
+ else if ( ( chunk_is_token(preproc_next, CT_FUNC_DEF)
+ && !options::pp_indent_func_def())
+ || ( chunk_is_token(preproc_next, CT_CASE)
+ && !options::pp_indent_case())
+ || ( chunk_is_token(preproc_next, CT_EXTERN)
+ && !options::pp_indent_extern()))
+ {
+ should_indent_preproc = false;
+ break;
+ }
+ preproc_next = preproc_next->GetNext();
+ }
+
+ if (should_indent_preproc)
+ {
+ // Hack to get the logs to look right
+
+ const E_Token memtype = next->type;
+ set_chunk_type(next, CT_PP_IF_INDENT);
+ frm.push(next, __func__, __LINE__);
+ set_chunk_type(next, memtype);
+
+ if (should_ignore_preproc)
+ {
+ // Preserve original indentation
+ frm.top().indent = pc->GetNextNl()->GetNext()->orig_col;
+ log_indent();
+ }
+ else
+ {
+ // Indent one level except if the #if is a #include guard
+ size_t extra = ( pc->pp_level == 0
+ && ifdef_over_whole_file())
+ ? 0 : indent_size;
+
+ frm.top().indent = frm.prev().indent + extra;
+ log_indent();
+
+ frm.top().indent_tab = frm.prev().indent_tab + extra;
+ }
+ frm.top().indent_tmp = frm.top().indent;
+ frm.top().in_preproc = false;
+ log_indent_tmp();
+ }
+ }
+ log_rule_B("indent_member_single");
+
+ if (options::indent_member_single())
+ {
+ if (get_chunk_parent_type(pc) == CT_PP_IF)
+ {
+ // do nothing
+ }
+ else if (get_chunk_parent_type(pc) == CT_PP_ELSE)
+ {
+ if ( frm.top().type == CT_MEMBER
+ && frm.top().pop_pc != nullptr
+ && frm.top().pc != frmbkup.top().pc)
+ {
+ Chunk *tmp = pc->GetNextNcNnlNpp();
+
+ if (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_WORD)
+ || chunk_is_token(tmp, CT_TYPE))
+ {
+ tmp = pc->GetNextNcNnlNpp();
+ }
+ else if ( chunk_is_token(tmp, CT_FUNC_CALL)
+ || chunk_is_token(tmp, CT_FPAREN_OPEN))
+ {
+ tmp = tmp->GetNextType(CT_FPAREN_CLOSE, tmp->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = pc->GetNextNcNnlNpp();
+ }
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ frm.top().pop_pc = tmp;
+ }
+ }
+ }
+ }
+ else if (get_chunk_parent_type(pc) == CT_PP_ENDIF)
+ {
+ if ( frmbkup.top().type == CT_MEMBER
+ && frm.top().type == CT_MEMBER)
+ {
+ frm.top().pop_pc = frmbkup.top().pop_pc;
+ }
+ }
+ }
+ // Transition into a preproc by creating a dummy indent
+ Chunk *pp_next = pc->GetNext();
+
+ if (pp_next->IsNullChunk())
+ {
+ return;
+ }
+ frm.push(pp_next, __func__, __LINE__);
+
+ if ( get_chunk_parent_type(pc) == CT_PP_DEFINE
+ || get_chunk_parent_type(pc) == CT_PP_UNDEF)
+ {
+ log_rule_B("pp_define_at_level");
+ frm.top().indent_tmp = options::pp_define_at_level()
+ ? frm.prev().indent_tmp : 1;
+ frm.top().indent = frm.top().indent_tmp + indent_size;
+ log_indent();
+
+ frm.top().indent_tab = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if ( ( get_chunk_parent_type(pc) == CT_PP_PRAGMA
+ || get_chunk_parent_type(pc) == CT_PP_OTHER)
+ && options::pp_define_at_level())
+ {
+ log_rule_B("pp_define_at_level");
+ frm.top().indent_tmp = frm.prev().indent_tmp;
+ frm.top().indent = frm.top().indent_tmp + indent_size;
+ log_indent();
+
+ frm.top().indent_tab = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if ( get_chunk_parent_type(pc) == CT_PP_INCLUDE
+ && options::pp_include_at_level())
+ {
+ log_rule_B("pp_include_at_level");
+ frm.top().indent_tmp = frm.prev().indent_tmp;
+ frm.top().indent = frm.top().indent_tmp + indent_size;
+ log_indent();
+
+ frm.top().indent_tab = frm.top().indent;
+ log_indent_tmp();
+ }
+ else
+ {
+ if ( (frm.prev().type == CT_PP_REGION_INDENT)
+ || ( (frm.prev().type == CT_PP_IF_INDENT)
+ && (frm.top().type != CT_PP_ENDIF)))
+ {
+ frm.top().indent = frm.prev(2).indent;
+ log_indent();
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent;
+ log_indent();
+ }
+ log_indent();
+
+
+ auto val = 0;
+
+ if ( get_chunk_parent_type(pc) == CT_PP_REGION
+ || get_chunk_parent_type(pc) == CT_PP_ENDREGION)
+ {
+ log_rule_B("pp_indent_region");
+ val = options::pp_indent_region();
+ log_indent();
+ }
+ else if ( get_chunk_parent_type(pc) == CT_PP_IF
+ || get_chunk_parent_type(pc) == CT_PP_ELSE
+ || get_chunk_parent_type(pc) == CT_PP_ENDIF)
+ {
+ log_rule_B("pp_indent_if");
+ val = options::pp_indent_if();
+ log_indent();
+ }
+
+ if (val != 0)
+ {
+ auto &indent = frm.top().indent;
+
+ indent = (val > 0) ? val // reassign if positive val,
+ : (cast_abs(indent, val) < indent) // else if no underflow
+ ? (indent + val) : 0; // reduce, else 0
+ }
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ }
+ // Check for close XML tags "</..."
+ log_rule_B("indent_xml_string");
+
+ if (options::indent_xml_string() > 0)
+ {
+ if (chunk_is_token(pc, CT_STRING))
+ {
+ if ( pc->Len() > 4
+ && xml_indent > 0
+ && pc->str[1] == '<'
+ && pc->str[2] == '/')
+ {
+ log_rule_B("indent_xml_string");
+ xml_indent -= options::indent_xml_string();
+ }
+ }
+ else if ( !pc->IsComment()
+ && !chunk_is_newline(pc))
+ {
+ xml_indent = 0;
+ }
+ }
+ // Handle non-brace closures
+ log_indent_tmp();
+
+ bool token_used = false;
+ size_t old_frm_size;
+
+ do
+ {
+ old_frm_size = frm.size();
+
+ // End anything that drops a level
+ if ( !chunk_is_newline(pc)
+ && !pc->IsComment()
+ && frm.top().level > pc->level)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (frm.top().level >= pc->level)
+ {
+ // process virtual braces closes (no text output)
+ if ( chunk_is_token(pc, CT_VBRACE_CLOSE)
+ && frm.top().type == CT_VBRACE_OPEN)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ pc = pc->GetNext();
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+
+ if (pc->IsNullChunk())
+ {
+ // need to break out of both the do and while loops
+ goto null_pc;
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_ENUM)
+ {
+ Chunk *prev_ncnl = pc->GetPrevNcNnl();
+ LOG_FMT(LINDLINE, "%s(%d): prev_ncnl is '%s', prev_ncnl->orig_line is %zu, prev_ncnl->orig_col is %zu\n",
+ __func__, __LINE__, prev_ncnl->Text(), prev_ncnl->orig_line, prev_ncnl->orig_col);
+
+ if (chunk_is_token(prev_ncnl, CT_COMMA))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): prev_ncnl is comma\n", __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LINDLINE, "%s(%d): prev_ncnl is NOT comma\n", __func__, __LINE__);
+ }
+ }
+
+ // End any assign operations with a semicolon on the same level
+ if (is_end_of_assignment(pc, frm))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ // Pop Colon from stack in ternary operator
+ // a
+ // ? b
+ // : e/*top*/;/*pc*/
+ log_rule_B("indent_inside_ternary_operator");
+
+ if ( options::indent_inside_ternary_operator()
+ && (frm.top().type == CT_COND_COLON)
+ && ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_OC_MSG_NAME)
+ || chunk_is_token(pc, CT_SPAREN_CLOSE))) // Issue #1130, #1715
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End any assign operations with a semicolon on the same level
+ if ( chunk_is_semicolon(pc)
+ && ( (frm.top().type == CT_IMPORT)
+ || (frm.top().type == CT_USING)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End any custom macro-based open/closes
+ if ( !token_used
+ && (frm.top().type == CT_MACRO_OPEN)
+ && chunk_is_token(pc, CT_MACRO_CLOSE))
+ {
+ token_used = true;
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End any CPP/ObjC class colon stuff
+ if ( ( (frm.top().type == CT_CLASS_COLON)
+ || (frm.top().type == CT_CONSTR_COLON))
+ && ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_OC_END)
+ || chunk_is_token(pc, CT_OC_SCOPE)
+ || chunk_is_token(pc, CT_OC_PROPERTY)
+ || chunk_is_token(pc, CT_TYPEDEF) // Issue #2675
+ || chunk_is_token(pc, CT_MACRO_OPEN)
+ || chunk_is_token(pc, CT_MACRO_CLOSE)
+ || ( language_is_set(LANG_OC)
+ && pc->IsComment()
+ && get_chunk_parent_type(pc) == CT_COMMENT_WHOLE) // Issue #2675
+ || chunk_is_semicolon(pc)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End ObjC class colon stuff inside of generic definition (like Test<T1: id<T3>>)
+ if ( (frm.top().type == CT_CLASS_COLON)
+ && chunk_is_token(pc, CT_ANGLE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_OC_GENERIC_SPEC)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End Objc nested message and boxed array
+ // TODO: ideally formatting would know which opens occurred on a line and group closes in the same manor
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(pc, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_OC_AT
+ && frm.top().level >= pc->level)
+ {
+ size_t count = 1;
+ Chunk *next = pc->GetNextNc();
+
+ while ( next->IsNotNullChunk()
+ && ( ( chunk_is_token(next, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(next) == CT_OC_AT)
+ || ( chunk_is_token(next, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(next) == CT_OC_AT)
+ || ( chunk_is_token(next, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(next) == CT_OC_MSG)))
+ {
+ count++;
+ next = next->GetNextNc();
+ }
+ count = std::min(count, frm.size());
+
+ if (count > 0)
+ {
+ while (count-- > 0)
+ {
+ if (frm.top().type == CT_SQUARE_OPEN)
+ {
+ if (frm.paren_count == 0)
+ {
+ fprintf(stderr, "%s(%d): frm.paren_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ frm.paren_count--;
+ }
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (next)
+ {
+ // End any assign operations with a semicolon on the same level
+ if (is_end_of_assignment(next, frm))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ // Indent the brace to match outer most brace/square
+ indent_column_set(frm.top().indent_tmp);
+ continue;
+ }
+ }
+
+ // a case is ended with another case or a close brace
+ if ( (frm.top().type == CT_CASE)
+ && ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_CASE)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (frm.top().pop_pc != nullptr)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pop_pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, frm.top().pop_pc->orig_line, frm.top().pop_pc->orig_col,
+ frm.top().pop_pc->Text(), get_token_name(frm.top().pop_pc->type));
+ }
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+
+ if ( (frm.top().type == CT_MEMBER)
+ && frm.top().pop_pc == pc)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if ( (frm.top().type == CT_LAMBDA)
+ && ( chunk_is_token(pc, CT_SEMICOLON)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_BRACE_OPEN)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ // a class scope is ended with another class scope or a close brace
+ log_rule_B("indent_access_spec_body");
+
+ if ( options::indent_access_spec_body()
+ && (frm.top().type == CT_ACCESS)
+ && ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_ACCESS)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // return & throw are ended with a semicolon
+ if ( chunk_is_semicolon(pc)
+ && ( (frm.top().type == CT_RETURN)
+ || (frm.top().type == CT_THROW)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // an OC SCOPE ('-' or '+') ends with a semicolon or brace open
+ if ( (frm.top().type == CT_OC_SCOPE)
+ && ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_BRACE_OPEN)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ /*
+ * a typedef and an OC SCOPE ('-' or '+') ends with a semicolon or
+ * brace open
+ */
+ if ( (frm.top().type == CT_TYPEDEF)
+ && ( chunk_is_semicolon(pc)
+ || chunk_is_paren_open(pc)
+ || chunk_is_token(pc, CT_BRACE_OPEN)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // an SQL EXEC is ended with a semicolon
+ if ( (frm.top().type == CT_SQL_EXEC)
+ && chunk_is_semicolon(pc))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // an CLASS is ended with a semicolon or brace open
+ if ( (frm.top().type == CT_CLASS)
+ && ( chunk_is_token(pc, CT_CLASS_COLON)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_semicolon(pc)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ log_rule_B("indent_oc_inside_msg_sel");
+
+ // Pop OC msg selector stack
+ if ( options::indent_oc_inside_msg_sel()
+ && (frm.top().type != CT_SQUARE_OPEN)
+ && frm.top().level >= pc->level
+ && ( chunk_is_token(pc, CT_OC_MSG_FUNC)
+ || chunk_is_token(pc, CT_OC_MSG_NAME))) // Issue #2658
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // Close out parenthesis and squares
+ if ( (frm.top().type == (pc->type - 1))
+ && ( chunk_is_token(pc, CT_PAREN_CLOSE)
+ || chunk_is_token(pc, CT_LPAREN_CLOSE) // Issue #3054
+ || chunk_is_token(pc, CT_SPAREN_CLOSE)
+ || chunk_is_token(pc, CT_FPAREN_CLOSE)
+ || chunk_is_token(pc, CT_SQUARE_CLOSE)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE)))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+
+ if (frm.paren_count == 0)
+ {
+ fprintf(stderr, "%s(%d): frm.paren_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ frm.paren_count--;
+ }
+ }
+ } while (old_frm_size > frm.size());
+
+ // Grab a copy of the current indent
+ indent_column_set(frm.top().indent_tmp); // Issue #3294
+ log_indent_tmp();
+
+ log_rule_B("indent_single_newlines");
+
+ if ( chunk_is_token(pc, CT_NEWLINE)
+ && options::indent_single_newlines())
+ {
+ pc->nl_column = indent_column;
+ }
+
+ if ( !chunk_is_newline(pc)
+ && !pc->IsComment()
+ && log_sev_on(LINDPC))
+ {
+ LOG_FMT(LINDPC, "%s(%d):\n", __func__, __LINE__);
+ LOG_FMT(LINDPC, " -=[ pc->orig_line is %zu, orig_col is %zu, Text() is '%s' ]=-, frm.size() is %zu\n",
+ pc->orig_line, pc->orig_col, pc->Text(), frm.size());
+
+ for (size_t ttidx = frm.size() - 1; ttidx > 0; ttidx--)
+ {
+ LOG_FMT(LINDPC, " [%zu %zu:%zu '%s' %s/%s tmp=%zu indent=%zu brace_indent=%zu indent_tab=%zu indent_cont=%d level=%zu pc->brace_level=%zu]\n",
+ ttidx,
+ frm.at(ttidx).pc->orig_line,
+ frm.at(ttidx).pc->orig_col,
+ frm.at(ttidx).pc->Text(),
+ get_token_name(frm.at(ttidx).type),
+ get_token_name(frm.at(ttidx).pc->parent_type),
+ frm.at(ttidx).indent_tmp,
+ frm.at(ttidx).indent,
+ frm.at(ttidx).brace_indent,
+ frm.at(ttidx).indent_tab,
+ frm.at(ttidx).indent_cont,
+ frm.at(ttidx).level,
+ frm.at(ttidx).pc->brace_level);
+ }
+ }
+ char copy[1000];
+ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, orig_col is %zu, column is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->column, pc->ElidedText(copy));
+
+ // Issue #672
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && classFound)
+ {
+ LOG_FMT(LINDENT, "%s(%d): CT_BRACE_OPEN found, CLOSE IT\n",
+ __func__, __LINE__);
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ classFound = false;
+ }
+ /*
+ * Handle stuff that can affect the current indent:
+ * - brace close
+ * - vbrace open
+ * - brace open
+ * - case (immediate)
+ * - labels (immediate)
+ * - class colons (immediate)
+ *
+ * And some stuff that can't
+ * - open paren
+ * - open square
+ * - assignment
+ * - return
+ */
+ log_rule_B("indent_braces");
+ log_rule_B("indent_braces_no_func");
+ log_rule_B("indent_braces_no_class");
+ log_rule_B("indent_braces_no_struct");
+ const bool brace_indent = ( ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_BRACE_OPEN))
+ && options::indent_braces()
+ && ( !options::indent_braces_no_func()
+ || get_chunk_parent_type(pc) != CT_FUNC_DEF)
+ && ( !options::indent_braces_no_func()
+ || get_chunk_parent_type(pc) != CT_FUNC_CLASS_DEF)
+ && ( !options::indent_braces_no_class()
+ || get_chunk_parent_type(pc) != CT_CLASS)
+ && ( !options::indent_braces_no_struct()
+ || get_chunk_parent_type(pc) != CT_STRUCT));
+ LOG_FMT(LINDENT, "%s(%d): brace_indent is %s\n",
+ __func__, __LINE__, brace_indent ? "TRue" : "FAlse");
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ if (language_is_set(LANG_OC))
+ {
+ if ( frm.top().type == CT_BRACE_OPEN
+ && frm.top().level >= pc->level)
+ {
+ size_t count = 1;
+ Chunk *next = pc->GetNextNc();
+
+ while ( next->IsNotNullChunk()
+ && ( ( chunk_is_token(next, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(next) == CT_OC_AT)
+ || ( chunk_is_token(next, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(next) == CT_OC_AT)
+ || ( chunk_is_token(next, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(next) == CT_OC_MSG)))
+ {
+ count++;
+ next = next->GetNextNc();
+ }
+ count = std::min(count, frm.size());
+
+ // End Objc nested boxed dictionary
+ // TODO: ideally formatting would know which opens occurred on a line and group closes in the same manor
+ if ( count > 0
+ && chunk_is_token(pc, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_OC_AT)
+ {
+ if (frm.top().ip.ref)
+ {
+ pc->indent.ref = frm.top().ip.ref;
+ pc->indent.delta = 0;
+ }
+
+ while (count-- > 0)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (next)
+ {
+ // End any assign operations with a semicolon on the same level
+ if (is_end_of_assignment(next, frm))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+
+ // Indent the brace to match outer most brace/square
+ if (frm.top().indent_cont)
+ {
+ indent_column_set(frm.top().indent_tmp - indent_size);
+ }
+ else
+ {
+ indent_column_set(frm.top().indent_tmp);
+ }
+ }
+ else
+ {
+ // Indent the brace to match the open brace
+ indent_column_set(frm.top().brace_indent);
+
+ if (frm.top().ip.ref)
+ {
+ pc->indent.ref = frm.top().ip.ref;
+ pc->indent.delta = 0;
+ }
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ }
+ else if (frm.top().brace_indent) // Issue #3421
+ {
+ // Indent the brace to match the open brace
+ indent_column_set(frm.top().brace_indent);
+
+ if (frm.top().ip.ref)
+ {
+ pc->indent.ref = frm.top().ip.ref;
+ pc->indent.delta = 0;
+ }
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ frm.push(pc, __func__, __LINE__);
+
+ log_rule_B("indent_min_vbrace_open");
+ size_t iMinIndent = options::indent_min_vbrace_open();
+
+ if (indent_size > iMinIndent)
+ {
+ iMinIndent = indent_size;
+ }
+ size_t iNewIndent = frm.prev().indent + iMinIndent;
+
+ log_rule_B("indent_vbrace_open_on_tabstop");
+
+ if (options::indent_vbrace_open_on_tabstop())
+ {
+ iNewIndent = next_tab_column(iNewIndent);
+ }
+ frm.top().indent = iNewIndent;
+ log_indent();
+ frm.top().indent_tmp = frm.top().indent;
+ frm.top().indent_tab = frm.top().indent;
+ log_indent_tmp();
+
+ // Always indent on virtual braces
+ indent_column_set(frm.top().indent_tmp);
+ }
+ else if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && ( pc->next != nullptr
+ && pc->next->type != CT_NAMESPACE))
+ {
+ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ frm.push(pc, __func__, __LINE__);
+
+ log_rule_B("indent_macro_brace");
+
+ if ( !options::indent_macro_brace()
+ && frm.prev().type == CT_PP_DEFINE
+ && frm.prev().open_line == frm.top().open_line)
+ {
+ LOG_FMT(LINDENT2, "%s(%d): indent_macro_brace\n", __func__, __LINE__);
+ }
+ else if ( options::indent_cpp_lambda_body()
+ && get_chunk_parent_type(pc) == CT_CPP_LAMBDA)
+ {
+ log_rule_B("indent_cpp_lambda_body");
+ frm.top().brace_indent = frm.prev().indent;
+
+ Chunk *head = frm.top().pc->GetPrevNcNnlNpp();
+ Chunk *tail = nullptr;
+ Chunk *frm_prev = frm.prev().pc;
+ bool enclosure = ( frm_prev->parent_type != CT_FUNC_DEF // Issue #3407
+ && frm_prev != chunk_skip_to_match(frm_prev));
+ bool linematch = true;
+
+ for (auto it = frm.rbegin(); it != frm.rend() && tail == nullptr; ++it)
+ {
+ if (it->pc && it->pc != frm.top().pc)
+ {
+ linematch &= are_chunks_in_same_line(it->pc, head);
+ }
+ Chunk *match = chunk_skip_to_match(it->pc);
+
+ if (match == nullptr)
+ {
+ continue;
+ }
+ Chunk *target = match->GetNextNcNnlNpp();
+
+ while ( tail == nullptr
+ && target->IsNotNullChunk())
+ {
+ if ( chunk_is_semicolon(target)
+ && target->level == match->level)
+ {
+ tail = target;
+ }
+ else if (target->level < match->level)
+ {
+ break;
+ }
+ else
+ {
+ target = target->GetNextNcNnlNpp();
+ }
+ }
+ }
+
+ bool toplevel = true;
+
+ for (auto it = frm.rbegin(); it != frm.rend() && tail != nullptr; ++it)
+ {
+ if (!chunk_is_token(it->pc, CT_FPAREN_OPEN))
+ {
+ continue;
+ }
+
+ if (it->pc->level < tail->level)
+ {
+ toplevel = false;
+ break;
+ }
+ }
+
+ // Issues: #1813, #3409, #3428
+ // if enclosure is set, the namespace is already accounted for
+ // so don't apply the correction twice.
+ // And for some reason, it's also accounted for when
+ // indent_namespace_single_indent is set
+ if (!enclosure && !options::indent_namespace_single_indent())
+ {
+ size_t namespace_indent_to_ignore = 0;
+ log_rule_B("indent_namespace");
+
+ for (auto i = frm.rbegin(); i != frm.rend(); ++i)
+ {
+ if (i->ns_cnt)
+ {
+ const auto foo = i->ns_cnt;
+ namespace_indent_to_ignore = indent_size * foo;
+ break;
+ }
+ }
+
+ if (namespace_indent_to_ignore && options::indent_namespace())
+ {
+ // I honestly don't know what's going on, so this is an
+ // emperical fix. For some reason lambda's don't have
+ // their indent calculated properly when indent_namespace
+ // is true. But only if they are not in enclosures.
+ namespace_indent_to_ignore = indent_size;
+ }
+
+ if (namespace_indent_to_ignore <= frm.top().brace_indent)
+ {
+ frm.top().brace_indent -= namespace_indent_to_ignore;
+ }
+ else
+ {
+ frm.top().brace_indent = 1;
+ }
+ }
+
+ // A few things to check:
+ // 1. The matching brace is on the same line as the ending semicolon
+ // 2a. If it's an assignment, check that both sides of the assignment operator are on the same line
+ // 2b. If it's inside some closure, check that all the frames are on the same line, and it is in the top level closure
+ if ( options::indent_continue() > 0
+ && are_chunks_in_same_line(chunk_skip_to_match(frm.top().pc), tail)
+ && ( ( !enclosure
+ && options::align_assign_span() == 0
+ && !options::indent_align_assign()
+ && are_chunks_in_same_line(frm.prev().pc->GetPrevNcNnlNpp(), frm.prev().pc)
+ && are_chunks_in_same_line(frm.prev().pc, frm.prev().pc->GetNextNcNnlNpp()))
+ || ( enclosure
+ && linematch
+ && toplevel)))
+ {
+ if (indent_size > frm.top().brace_indent) // if options::indent_indent_columns() is too big
+ {
+ frm.top().brace_indent = 1;
+ }
+ else
+ {
+ frm.top().brace_indent -= indent_size;
+ }
+ }
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = indent_column + indent_size;
+ log_indent();
+
+ frm.top().indent_tab = frm.top().indent;
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+
+ frm.prev().indent_tmp = frm.top().indent_tmp;
+ log_indent_tmp();
+ }
+ else if ( language_is_set(LANG_CPP)
+ && options::indent_cpp_lambda_only_once()
+ && (get_chunk_parent_type(pc) == CT_CPP_LAMBDA))
+ {
+ // test example cpp:30756
+ log_rule_B("indent_cpp_lambda_only_once");
+
+ size_t namespace_indent_to_ignore = 0; // Issue #1813
+ log_rule_B("indent_namespace");
+
+ if (!options::indent_namespace())
+ {
+ for (auto i = frm.rbegin(); i != frm.rend(); ++i)
+ {
+ if (i->ns_cnt)
+ {
+ namespace_indent_to_ignore = i->ns_cnt;
+ break;
+ }
+ }
+ }
+ // Issue # 1296
+ frm.top().brace_indent = 1 + ((pc->brace_level - namespace_indent_to_ignore) * indent_size);
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = indent_column + indent_size;
+ log_indent();
+ frm.top().indent_tab = frm.top().indent;
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+
+ frm.prev().indent_tmp = frm.top().indent_tmp;
+ log_indent_tmp();
+ }
+ else if ( language_is_set(LANG_CS | LANG_JAVA)
+ && options::indent_cs_delegate_brace()
+ && ( get_chunk_parent_type(pc) == CT_LAMBDA
+ || get_chunk_parent_type(pc) == CT_DELEGATE))
+ {
+ log_rule_B("indent_cs_delegate_brace");
+ frm.top().brace_indent = 1 + ((pc->brace_level + 1) * indent_size);
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = indent_column + indent_size;
+ log_indent();
+ frm.top().indent_tab = frm.top().indent;
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+
+ frm.prev().indent_tmp = frm.top().indent_tmp;
+ log_indent_tmp();
+ }
+ else if ( language_is_set(LANG_CS | LANG_JAVA)
+ && !options::indent_cs_delegate_brace()
+ && !options::indent_align_paren()
+ && ( get_chunk_parent_type(pc) == CT_LAMBDA
+ || get_chunk_parent_type(pc) == CT_DELEGATE))
+ {
+ log_rule_B("indent_cs_delegate_brace");
+ log_rule_B("indent_align_paren");
+ frm.top().brace_indent = frm.prev().indent;
+
+ // Issue # 1620, UNI-24090.cs
+ if (are_chunks_in_same_line(frm.prev().pc, frm.top().pc->GetPrevNcNnlNpp()))
+ {
+ frm.top().brace_indent -= indent_size;
+ }
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = indent_column + indent_size;
+ log_indent();
+ frm.top().indent_tab = frm.top().indent;
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ frm.prev().indent_tmp = frm.top().indent_tmp;
+ log_indent_tmp();
+ }
+ else if ( !options::indent_paren_open_brace()
+ && !language_is_set(LANG_CS)
+ && get_chunk_parent_type(pc) == CT_CPP_LAMBDA
+ && ( pc->flags.test(PCF_IN_FCN_DEF)
+ || pc->flags.test(PCF_IN_FCN_CTOR)) // Issue #2152
+ && chunk_is_newline(pc->GetNextNc()))
+ {
+ log_rule_B("indent_paren_open_brace");
+ // Issue #1165
+ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, pc->brace_level is %zu, for '%s', pc->level is %zu, pc(-1)->level is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->brace_level, pc->Text(), pc->level, frm.prev().pc->level);
+ frm.top().brace_indent = 1 + ((pc->brace_level + 1) * indent_size);
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = frm.prev().indent_tmp;
+ log_indent();
+
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ // any '{' that is inside of a '(' overrides the '(' indent
+ // only to help the vim command }
+ else if ( !options::indent_paren_open_brace()
+ && chunk_is_paren_open(frm.prev().pc)
+ && chunk_is_newline(pc->GetNextNc()))
+ {
+ log_rule_B("indent_paren_open_brace");
+ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, pc->brace_level is %zu, for '%s', pc->level is %zu, pc(-1)->level is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->brace_level, pc->Text(), pc->level, frm.prev().pc->level);
+ // FIXME: I don't know how much of this is necessary, but it seems to work
+ frm.top().brace_indent = 1 + (pc->brace_level * indent_size);
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = indent_column + indent_size;
+ log_indent();
+
+ if ( (get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR)
+ && pc->flags.test(PCF_IN_OC_MSG))
+ {
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ log_indent();
+ frm.top().brace_indent = frm.prev().indent_tmp;
+ indent_column_set(frm.top().brace_indent);
+ }
+ frm.top().indent_tab = frm.top().indent;
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+
+ frm.prev().indent_tmp = frm.top().indent_tmp;
+ }
+ else if (frm.paren_count != 0)
+ {
+ if (frm.top().pc->parent_type == CT_OC_BLOCK_EXPR)
+ {
+ log_rule_B("indent_oc_block_msg");
+
+ if ( pc->flags.test(PCF_IN_OC_MSG)
+ && options::indent_oc_block_msg())
+ {
+ frm.top().ip.ref = oc_msg_block_indent(pc, false, false, false, true);
+ log_rule_B("indent_oc_block_msg");
+ frm.top().ip.delta = options::indent_oc_block_msg();
+ }
+ log_rule_B("indent_oc_block");
+ log_rule_B("indent_oc_block_msg_xcode_style");
+
+ if ( options::indent_oc_block()
+ || options::indent_oc_block_msg_xcode_style())
+ {
+ bool in_oc_msg = pc->flags.test(PCF_IN_OC_MSG);
+ log_rule_B("indent_oc_block_msg_from_keyword");
+ bool indent_from_keyword = options::indent_oc_block_msg_from_keyword()
+ && in_oc_msg;
+ log_rule_B("indent_oc_block_msg_from_colon");
+ bool indent_from_colon = options::indent_oc_block_msg_from_colon()
+ && in_oc_msg;
+ log_rule_B("indent_oc_block_msg_from_caret");
+ bool indent_from_caret = options::indent_oc_block_msg_from_caret()
+ && in_oc_msg;
+ log_rule_B("indent_oc_block_msg_from_brace");
+ bool indent_from_brace = options::indent_oc_block_msg_from_brace()
+ && in_oc_msg;
+
+ /*
+ * In "Xcode indent mode", we want to indent:
+ * - if the colon is aligned (namely, if a newline has been
+ * added before it), indent_from_brace
+ * - otherwise, indent from previous block (the "else" statement here)
+ */
+ log_rule_B("indent_oc_block_msg_xcode_style");
+
+ if (options::indent_oc_block_msg_xcode_style())
+ {
+ Chunk *bbc = chunk_skip_to_match(pc); // block brace close '}'
+ Chunk *bbc_next_ncnl = bbc->GetNextNcNnl();
+
+ if ( bbc_next_ncnl->type == CT_OC_MSG_NAME
+ || bbc_next_ncnl->type == CT_OC_MSG_FUNC)
+ {
+ indent_from_brace = false;
+ indent_from_colon = false;
+ indent_from_caret = false;
+ indent_from_keyword = true;
+ }
+ else
+ {
+ indent_from_brace = false;
+ indent_from_colon = false;
+ indent_from_caret = false;
+ indent_from_keyword = false;
+ }
+ }
+ Chunk *ref = oc_msg_block_indent(pc, indent_from_brace,
+ indent_from_caret,
+ indent_from_colon,
+ indent_from_keyword);
+
+ if (ref)
+ {
+ frm.top().indent = indent_size + ref->column;
+ }
+ else
+ {
+ frm.top().indent = 1 + ((pc->brace_level + 1) * indent_size);
+ }
+ log_indent();
+ indent_column_set(frm.top().indent - indent_size);
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ log_indent();
+ }
+ }
+ else if ( frm.top().pc->type == CT_BRACE_OPEN
+ && frm.top().pc->parent_type == CT_OC_AT)
+ {
+ // We are inside @{ ... } -- indent one tab from the paren
+ if (frm.prev().indent_cont)
+ {
+ frm.top().indent = frm.prev().indent_tmp;
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ }
+ log_indent();
+ }
+ // Issue # 1620, UNI-24090.cs
+ else if ( are_chunks_in_same_line(frm.prev().pc, frm.top().pc)
+ && !options::indent_align_paren()
+ && chunk_is_paren_open(frm.prev().pc)
+ && !pc->flags.test(PCF_ONE_LINER))
+ {
+ log_rule_B("indent_align_paren");
+ // We are inside ({ ... }) -- where { and ( are on the same line, avoiding double indentations.
+ // only to help the vim command }
+ frm.top().brace_indent = frm.prev().indent - indent_size;
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = frm.prev().indent_tmp;
+ log_indent();
+ }
+ else if ( are_chunks_in_same_line(frm.prev().pc, frm.top().pc->GetPrevNcNnlNpp())
+ && !options::indent_align_paren()
+ && chunk_is_paren_open(frm.prev().pc)
+ && !pc->flags.test(PCF_ONE_LINER))
+ {
+ log_rule_B("indent_align_paren");
+ // We are inside ({ ... }) -- where { and ( are on adjacent lines, avoiding indentation of brace.
+ // only to help the vim command }
+ frm.top().brace_indent = frm.prev().indent - indent_size;
+ indent_column_set(frm.top().brace_indent);
+ frm.top().indent = frm.prev().indent_tmp;
+ log_indent();
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && ( frm.prev().type == CT_OC_MSG_FUNC
+ || frm.prev().type == CT_OC_MSG_NAME)) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ // [Class Message:{<here>
+ frm.top().indent = frm.prev().pc->column + indent_size;
+ log_indent();
+ indent_column_set(frm.prev().pc->column);
+ }
+ else
+ {
+ // We are inside ({ ... }) -- indent one tab from the paren
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+
+ if (!chunk_is_paren_open(frm.prev().pc))
+ {
+ frm.top().indent_tab = frm.top().indent;
+ }
+ log_indent();
+ }
+ }
+ else if ( frm.top().pc->type == CT_BRACE_OPEN
+ && frm.top().pc->parent_type == CT_OC_AT)
+ {
+ // We are inside @{ ... } -- indent one tab from the paren
+ if (frm.prev().indent_cont)
+ {
+ frm.top().indent = frm.prev().indent_tmp;
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ frm.top().indent_tab = frm.top().indent;
+ }
+ log_indent();
+ }
+ else if ( ( get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST
+ || ( !options::indent_compound_literal_return()
+ && get_chunk_parent_type(pc) == CT_C_CAST))
+ && frm.prev().type == CT_RETURN)
+ {
+ log_rule_B("indent_compound_literal_return");
+
+ // we're returning either a c compound literal (CT_C_CAST) or a
+ // C++11 initialization list (CT_BRACED_INIT_LIST), use indent from the return.
+ if (frm.prev().indent_cont)
+ {
+ frm.top().indent = frm.prev().indent_tmp;
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ }
+ log_indent();
+ }
+ else
+ {
+ // Use the prev indent level + indent_size.
+ if (get_chunk_parent_type(pc) == CT_SWITCH)
+ {
+ frm.top().indent = frm.prev().indent + options::indent_switch_body();
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent + indent_size;
+ }
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ... indent is %zu\n",
+ __func__, __LINE__, frm.size() - 1, frm.top().indent);
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ get_token_name(get_chunk_parent_type(pc)));
+
+ // If this brace is part of a statement, bump it out by indent_brace
+ if ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSE
+ || get_chunk_parent_type(pc) == CT_ELSEIF
+ || get_chunk_parent_type(pc) == CT_TRY
+ || get_chunk_parent_type(pc) == CT_CATCH
+ || get_chunk_parent_type(pc) == CT_DO
+ || get_chunk_parent_type(pc) == CT_WHILE
+ || get_chunk_parent_type(pc) == CT_USING_STMT
+ || get_chunk_parent_type(pc) == CT_SWITCH
+ || get_chunk_parent_type(pc) == CT_SYNCHRONIZED
+ || get_chunk_parent_type(pc) == CT_FOR)
+ {
+ if (parent_token_indent != 0)
+ {
+ frm.top().indent += parent_token_indent - indent_size;
+ log_indent();
+ }
+ else
+ {
+ log_rule_B("indent_brace");
+ frm.top().indent += options::indent_brace();
+ log_indent();
+ indent_column_set(indent_column + options::indent_brace());
+ }
+ }
+ else if (get_chunk_parent_type(pc) == CT_CASE)
+ {
+ if (options::indent_ignore_case_brace())
+ {
+ log_rule_B("indent_ignore_case_brace");
+ indent_column_set(pc->orig_col);
+ }
+ else
+ {
+ log_rule_B("indent_case_brace");
+ const auto tmp_indent = static_cast<int>(frm.prev().indent)
+ - static_cast<int>(indent_size)
+ + options::indent_case_brace();
+ /*
+ * An open brace with the parent of case does not indent by default
+ * UO_indent_case_brace can be used to indent the brace.
+ * So we need to take the CASE indent, subtract off the
+ * indent_size that was added above and then add indent_case_brace.
+ * may take negative value
+ */
+ indent_column_set(max(tmp_indent, 0));
+ }
+ // Stuff inside the brace still needs to be indented
+ frm.top().indent = indent_column + indent_size;
+ log_indent();
+
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if ( get_chunk_parent_type(pc) == CT_CLASS
+ && !options::indent_class())
+ {
+ log_rule_B("indent_class");
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, orig_col is %zu, text is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ frm.top().indent -= indent_size;
+ log_indent();
+ }
+ else if (get_chunk_parent_type(pc) == CT_NAMESPACE)
+ {
+ frm.top().ns_cnt = frm.prev().ns_cnt + 1;
+
+ log_rule_B("indent_namespace");
+ log_rule_B("indent_namespace_single_indent");
+
+ if ( options::indent_namespace()
+ && options::indent_namespace_single_indent())
+ {
+ if (frm.top().ns_cnt >= 2)
+ {
+ // undo indent on all except the first namespace
+ frm.top().indent -= indent_size;
+ log_indent();
+ }
+ indent_column_set(frm.prev(frm.top().ns_cnt).indent);
+ }
+ else if ( options::indent_namespace()
+ && options::indent_namespace_inner_only())
+ {
+ if (frm.top().ns_cnt == 1)
+ {
+ // undo indent on first namespace only
+ frm.top().indent -= indent_size;
+ log_indent();
+ }
+ }
+ else if ( pc->flags.test(PCF_LONG_BLOCK)
+ || !options::indent_namespace())
+ {
+ log_rule_B("indent_namespace");
+ // don't indent long blocks
+ frm.top().indent -= indent_size;
+ log_indent();
+ }
+ else // indenting 'short' namespace
+ {
+ log_rule_B("indent_namespace_level");
+
+ if (options::indent_namespace_level() > 0)
+ {
+ frm.top().indent -= indent_size;
+ log_indent();
+
+ frm.top().indent +=
+ options::indent_namespace_level();
+ log_indent();
+ }
+ }
+ }
+ else if ( get_chunk_parent_type(pc) == CT_EXTERN
+ && !options::indent_extern())
+ {
+ log_rule_B("indent_extern");
+ frm.top().indent -= indent_size;
+ log_indent();
+ }
+ frm.top().indent_tab = frm.top().indent;
+ }
+
+ if (pc->flags.test(PCF_DONT_INDENT))
+ {
+ frm.top().indent = pc->column;
+ log_indent();
+
+ indent_column_set(pc->column);
+ }
+ else
+ {
+ /*
+ * If there isn't a newline between the open brace and the next
+ * item, just indent to wherever the next token is.
+ * This covers this sort of stuff:
+ * { a++;
+ * b--; };
+ */
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ Chunk *prev = pc->GetPrev();
+
+ if ( get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST
+ && chunk_is_token(prev, CT_BRACE_OPEN)
+ && get_chunk_parent_type(prev) == CT_BRACED_INIT_LIST)
+ {
+ indent_column = frm.prev().brace_indent;
+ frm.top().indent = frm.prev().indent;
+ log_indent();
+ }
+ else if ( !chunk_is_newline_between(pc, next)
+ && get_chunk_parent_type(next) != CT_BRACED_INIT_LIST
+ && options::indent_token_after_brace()
+ && !pc->flags.test(PCF_ONE_LINER)) // Issue #1108
+ {
+ log_rule_B("indent_token_after_brace");
+ frm.top().indent = next->column;
+ log_indent();
+ }
+ frm.top().indent_tmp = frm.top().indent;
+ frm.top().open_line = pc->orig_line;
+ log_indent_tmp();
+
+ log_rule_B("Update the indent_column");
+
+ // Update the indent_column if needed
+ if ( brace_indent
+ || parent_token_indent != 0)
+ {
+ indent_column_set(frm.top().indent_tmp);
+ log_indent_tmp();
+ }
+ }
+ // Save the brace indent
+ frm.top().brace_indent = indent_column;
+ }
+ else if (chunk_is_token(pc, CT_SQL_END))
+ {
+ if (frm.top().type == CT_SQL_BEGIN)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ indent_column_set(frm.top().indent_tmp);
+ log_indent_tmp();
+ }
+ }
+ else if ( chunk_is_token(pc, CT_SQL_BEGIN)
+ || chunk_is_token(pc, CT_MACRO_OPEN)
+ || ( chunk_is_token(pc, CT_CLASS)
+ && language_is_set(LANG_CS))) // Issue #3536
+ {
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().indent = frm.prev().indent + indent_size;
+ log_indent();
+
+ frm.top().indent_tmp = frm.top().indent;
+ frm.top().indent_tab = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if (chunk_is_token(pc, CT_SQL_EXEC))
+ {
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().indent = frm.prev().indent + indent_size;
+ log_indent();
+
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if (chunk_is_token(pc, CT_MACRO_ELSE))
+ {
+ if (frm.top().type == CT_MACRO_OPEN)
+ {
+ indent_column_set(frm.prev().indent);
+ }
+ }
+ else if (chunk_is_token(pc, CT_CASE))
+ {
+ // Start a case - indent UO_indent_switch_case from the switch level
+ log_rule_B("indent_switch_case");
+ const size_t tmp = frm.top().indent + indent_size
+ - options::indent_switch_body()
+ + options::indent_switch_case();
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().indent = tmp;
+ log_indent();
+
+ log_rule_B("indent_case_shift");
+ frm.top().indent_tmp = tmp - indent_size + options::indent_case_shift();
+ frm.top().indent_tab = tmp;
+ log_indent_tmp();
+
+ // Always set on case statements
+ indent_column_set(frm.top().indent_tmp);
+
+ if (options::indent_case_comment())
+ {
+ // comments before 'case' need to be aligned with the 'case'
+ Chunk *pct = pc;
+
+ while ( ((pct = pct->GetPrevNnl())->IsNotNullChunk())
+ && pct->IsComment())
+ {
+ Chunk *t2 = pct->GetPrev();
+
+ if (chunk_is_newline(t2))
+ {
+ pct->column = frm.top().indent_tmp;
+ pct->column_indent = pct->column;
+ }
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_BREAK))
+ {
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_CASE)
+ {
+ // issue #663 + issue #1366
+ Chunk *prev_prev_newline = pc->GetPrevNl()->GetPrevNl();
+
+ if (prev_prev_newline->IsNotNullChunk())
+ {
+ // This only affects the 'break', so no need for a stack entry
+ indent_column_set(prev_prev_newline->GetNext()->column);
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_LABEL))
+ {
+ if (options::indent_ignore_label())
+ {
+ log_rule_B("indent_ignore_label");
+ indent_column_set(pc->orig_col);
+ }
+ else
+ {
+ log_rule_B("indent_label");
+ const auto val = options::indent_label();
+ const auto pse_indent = frm.top().indent;
+
+ // Labels get sent to the left or backed up
+ if (val > 0)
+ {
+ indent_column_set(val);
+
+ Chunk *next = pc->GetNext()->GetNext(); // colon + possible statement
+
+ if ( next->IsNotNullChunk()
+ && !chunk_is_newline(next)
+ // label (+ 2, because there is colon and space after it) must fit into indent
+ && (val + static_cast<int>(pc->Len()) + 2 <= static_cast<int>(pse_indent)))
+ {
+ reindent_line(next, pse_indent);
+ }
+ }
+ else
+ {
+ const auto no_underflow = cast_abs(pse_indent, val) < pse_indent;
+ indent_column_set(((no_underflow) ? (pse_indent + val) : 0));
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_ACCESS))
+ {
+ log_rule_B("indent_access_spec_body");
+
+ if (options::indent_access_spec_body())
+ {
+ const size_t tmp = frm.top().indent + indent_size;
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().indent = tmp;
+ log_indent();
+
+ frm.top().indent_tmp = tmp - indent_size;
+ frm.top().indent_tab = tmp;
+ log_indent_tmp();
+
+ /*
+ * If we are indenting the body, then we must leave the access spec
+ * indented at brace level
+ */
+ indent_column_set(frm.top().indent_tmp);
+ // Issues 1161 + 2704
+ // comments before 'access specifier' need to be aligned with the 'access specifier'
+ // unless it is a Doxygen comment
+ Chunk *pct = pc;
+
+ while ( ((pct = pct->GetPrevNnl())->IsNotNullChunk())
+ && pct->IsComment()
+ && !chunk_is_Doxygen_comment(pct))
+ {
+ Chunk *t2 = pct->GetPrev();
+
+ if (chunk_is_newline(t2))
+ {
+ pct->column = frm.top().indent_tmp;
+ pct->column_indent = pct->column;
+ }
+ }
+ }
+ else
+ {
+ // Access spec labels get sent to the left or backed up
+ log_rule_B("indent_access_spec");
+ const auto val = options::indent_access_spec();
+
+ if (val > 0)
+ {
+ indent_column_set(val);
+ }
+ else
+ {
+ const auto pse_indent = frm.top().indent;
+ const auto no_underflow = cast_abs(pse_indent, val) < pse_indent;
+
+ indent_column_set(no_underflow ? (pse_indent + val) : 0);
+ }
+ }
+ }
+ else if ( chunk_is_token(pc, CT_CLASS_COLON)
+ || chunk_is_token(pc, CT_CONSTR_COLON))
+ {
+ // just indent one level
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ log_indent();
+
+ frm.top().indent_tmp = frm.top().indent;
+ frm.top().indent_tab = frm.top().indent;
+ log_indent_tmp();
+
+ if (chunk_is_token(pc, CT_CLASS_COLON))
+ {
+ if (options::indent_ignore_before_class_colon())
+ {
+ log_rule_B("indent_ignore_before_class_colon");
+ frm.top().indent_tmp = pc->orig_col;
+ log_indent_tmp();
+ }
+ else if (options::indent_before_class_colon() != 0)
+ {
+ log_rule_B("indent_before_class_colon");
+ frm.top().indent_tmp = std::max<ptrdiff_t>(frm.top().indent_tmp + options::indent_before_class_colon(), 0);
+ log_indent_tmp();
+ }
+ }
+ indent_column_set(frm.top().indent_tmp);
+
+ log_rule_B("indent_class_colon");
+
+ if ( options::indent_class_colon()
+ && chunk_is_token(pc, CT_CLASS_COLON))
+ {
+ log_rule_B("indent_class_on_colon");
+
+ if (options::indent_class_on_colon())
+ {
+ frm.top().indent = pc->column;
+ log_indent();
+ }
+ else
+ {
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && !chunk_is_newline(next))
+ {
+ frm.top().indent = next->column;
+ log_indent();
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_CONSTR_COLON))
+ {
+ if (options::indent_ignore_before_constr_colon())
+ {
+ log_rule_B("indent_ignore_before_constr_colon");
+ frm.top().indent_tmp = pc->orig_col;
+ indent_column_set(frm.top().indent_tmp);
+ }
+
+ if (options::indent_constr_colon())
+ {
+ log_rule_B("indent_constr_colon");
+ Chunk *prev = pc->GetPrev();
+
+ if (chunk_is_newline(prev))
+ {
+ log_rule_B("indent_ctor_init_following");
+ frm.top().indent += options::indent_ctor_init_following();
+ log_indent();
+ }
+ // TODO: Create a dedicated indent_constr_on_colon?
+ log_rule_B("indent_class_on_colon");
+
+ if (options::indent_ctor_init() != 0)
+ {
+ log_rule_B("indent_ctor_init");
+ /*
+ * If the std::max() calls were specialized with size_t (the type of the underlying variable),
+ * they would never actually do their job, because size_t is unsigned and therefore even
+ * a "negative" result would be always greater than zero.
+ * Using ptrdiff_t (a standard signed type of the same size as size_t) in order to avoid that.
+ */
+ frm.top().indent = std::max<ptrdiff_t>(frm.top().indent + options::indent_ctor_init(), 0);
+ log_indent();
+ frm.top().indent_tmp = std::max<ptrdiff_t>(frm.top().indent_tmp + options::indent_ctor_init(), 0);
+ frm.top().indent_tab = std::max<ptrdiff_t>(frm.top().indent_tab + options::indent_ctor_init(), 0);
+ log_indent_tmp();
+ indent_column_set(frm.top().indent_tmp);
+ }
+ else if (options::indent_class_on_colon())
+ {
+ frm.top().indent = pc->column;
+ log_indent();
+ }
+ else
+ {
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && !chunk_is_newline(next))
+ {
+ frm.top().indent = next->column;
+ log_indent();
+ }
+ }
+ }
+ }
+ }
+ else if ( chunk_is_token(pc, CT_PAREN_OPEN)
+ && ( get_chunk_parent_type(pc) == CT_ASM
+ || ( pc->GetPrevNcNnl()->IsNotNullChunk()
+ && pc->GetPrevNcNnl()->type == CT_ASM))
+ && options::indent_ignore_asm_block())
+ {
+ log_rule_B("indent_ignore_asm_block");
+ Chunk *tmp = chunk_skip_to_match(pc);
+
+ int move = 0;
+
+ if ( chunk_is_newline(pc->GetPrev())
+ && pc->column != indent_column)
+ {
+ move = indent_column - pc->column;
+ }
+ else
+ {
+ move = pc->column - pc->orig_col;
+ }
+
+ do
+ {
+ pc->column = pc->orig_col + move;
+ pc = pc->GetNext();
+ } while (pc != tmp);
+
+ reindent_line(pc, indent_column);
+ }
+ else if ( chunk_is_token(pc, CT_PAREN_OPEN)
+ || chunk_is_token(pc, CT_LPAREN_OPEN) // Issue #3054
+ || chunk_is_token(pc, CT_SPAREN_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_SQUARE_OPEN)
+ || chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ /*
+ * Open parenthesis and squares - never update indent_column,
+ * unless right after a newline.
+ */
+ frm.push(pc, __func__, __LINE__);
+
+ if ( chunk_is_newline(pc->GetPrev())
+ && pc->column != indent_column
+ && !pc->flags.test(PCF_DONT_INDENT))
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent => %zu, text is '%s'\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ frm.top().indent = pc->column + pc->Len();
+ log_indent();
+
+ if ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ && language_is_set(LANG_D))
+ {
+ frm.top().indent_tab = frm.top().indent;
+ }
+ bool skipped = false;
+ log_rule_B("indent_inside_ternary_operator");
+ log_rule_B("indent_align_paren");
+
+ if ( options::indent_inside_ternary_operator()
+ && ( chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_PAREN_OPEN))
+ && frm.size() > 2
+ && ( frm.prev().type == CT_QUESTION
+ || frm.prev().type == CT_COND_COLON)
+ && !options::indent_align_paren())
+ {
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ log_indent();
+ frm.top().indent_tab = frm.top().indent;
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if ( ( chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_ANGLE_OPEN))
+ && ( ( options::indent_func_call_param()
+ && ( get_chunk_parent_type(pc) == CT_FUNC_CALL
+ || get_chunk_parent_type(pc) == CT_FUNC_CALL_USER))
+ || ( options::indent_func_proto_param()
+ && get_chunk_parent_type(pc) == CT_FUNC_PROTO)
+ || ( options::indent_func_class_param()
+ && ( get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_CLASS_PROTO))
+ || ( options::indent_template_param()
+ && get_chunk_parent_type(pc) == CT_TEMPLATE)
+ || ( options::indent_func_ctor_var_param()
+ && get_chunk_parent_type(pc) == CT_FUNC_CTOR_VAR)
+ || ( options::indent_func_def_param()
+ && get_chunk_parent_type(pc) == CT_FUNC_DEF)
+ || ( !options::indent_func_def_param() // Issue #931
+ && get_chunk_parent_type(pc) == CT_FUNC_DEF
+ && options::indent_func_def_param_paren_pos_threshold() > 0
+ && pc->orig_col > options::indent_func_def_param_paren_pos_threshold())))
+ {
+ log_rule_B("indent_func_call_param");
+ log_rule_B("indent_func_proto_param");
+ log_rule_B("indent_func_class_param");
+ log_rule_B("indent_template_param");
+ log_rule_B("indent_func_ctor_var_param");
+ log_rule_B("indent_func_def_param");
+ log_rule_B("indent_func_def_param_paren_pos_threshold");
+ // Skip any continuation indents
+ size_t idx = (!frm.empty()) ? frm.size() - 2 : 0;
+
+ while ( ( ( idx > 0
+ && frm.at(idx).type != CT_BRACE_OPEN
+ && frm.at(idx).type != CT_VBRACE_OPEN
+ && frm.at(idx).type != CT_PAREN_OPEN
+ && frm.at(idx).type != CT_FPAREN_OPEN
+ && frm.at(idx).type != CT_SPAREN_OPEN
+ && frm.at(idx).type != CT_SQUARE_OPEN
+ && frm.at(idx).type != CT_ANGLE_OPEN
+ && frm.at(idx).type != CT_CASE
+ && frm.at(idx).type != CT_MEMBER
+ && frm.at(idx).type != CT_QUESTION
+ && frm.at(idx).type != CT_COND_COLON
+ && frm.at(idx).type != CT_LAMBDA
+ && frm.at(idx).type != CT_ASSIGN_NL)
+ || are_chunks_in_same_line(frm.at(idx).pc, frm.top().pc))
+ && ( frm.at(idx).type != CT_CLASS_COLON
+ && frm.at(idx).type != CT_CONSTR_COLON
+ && !( frm.at(idx).type == CT_LAMBDA
+ && frm.at(idx).pc->GetPrevNc()->type == CT_NEWLINE)))
+ {
+ if (idx == 0)
+ {
+ fprintf(stderr, "%s(%d): idx is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ idx--;
+ skipped = true;
+ }
+ // PR#381
+ log_rule_B("indent_param");
+
+ if (options::indent_param() != 0)
+ {
+ frm.top().indent = frm.at(idx).indent + options::indent_param();
+ log_indent();
+ }
+ else
+ {
+ frm.top().indent = frm.at(idx).indent + indent_size;
+ log_indent();
+ }
+ log_rule_B("indent_func_param_double");
+
+ if (options::indent_func_param_double())
+ {
+ // double is: Use both values of the options indent_columns and indent_param
+ frm.top().indent += indent_size;
+ log_indent();
+ }
+ frm.top().indent_tab = frm.top().indent;
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && chunk_is_token(pc, CT_PAREN_OPEN)
+ && frm.size() > 2
+ && ( frm.prev().type == CT_OC_MSG_FUNC
+ || frm.prev().type == CT_OC_MSG_NAME)
+ && !options::indent_align_paren()) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ log_rule_B("indent_align_paren");
+ // When parens are inside OC messages, push on the parse frame stack
+ // [Class Message:(<here>
+ frm.top().indent = frm.prev().pc->column + indent_size;
+ log_indent();
+ frm.top().indent_tab = frm.top().indent;
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if ( chunk_is_token(pc, CT_PAREN_OPEN)
+ && !chunk_is_newline(pc->GetNext())
+ && !options::indent_align_paren()
+ && !pc->flags.test(PCF_IN_SPAREN))
+ {
+ log_rule_B("indent_align_paren");
+ int idx = static_cast<int>(frm.size()) - 2;
+
+ while ( idx > 0
+ && are_chunks_in_same_line(frm.at(idx).pc, frm.top().pc))
+ {
+ idx--;
+ skipped = true;
+ }
+ frm.top().indent = frm.at(idx).indent + indent_size;
+ log_indent();
+
+ frm.top().indent_tab = frm.top().indent;
+ skipped = true;
+ }
+ else if ( ( chunk_is_str(pc, "(")
+ && !options::indent_paren_nl())
+ || ( chunk_is_str(pc, "<")
+ && !options::indent_paren_nl()) // TODO: add indent_angle_nl?
+ || ( chunk_is_str(pc, "[")
+ && !options::indent_square_nl()))
+ {
+ log_rule_B("indent_paren_nl");
+ log_rule_B("indent_square_nl");
+ Chunk *next = pc->GetNextNc();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ log_rule_B("indent_paren_after_func_def");
+ log_rule_B("indent_paren_after_func_decl");
+ log_rule_B("indent_paren_after_func_call");
+
+ if ( chunk_is_newline(next)
+ && !options::indent_paren_after_func_def()
+ && !options::indent_paren_after_func_decl()
+ && !options::indent_paren_after_func_call())
+ {
+ size_t sub = 2;
+
+ if ( (frm.prev().type == CT_ASSIGN)
+ || (frm.prev().type == CT_RETURN))
+ {
+ sub = 3;
+ }
+ sub = static_cast<int>(frm.size()) - sub;
+
+ log_rule_B("indent_align_paren");
+
+ if (!options::indent_align_paren())
+ {
+ sub = static_cast<int>(frm.size()) - 2;
+
+ while ( sub > 0
+ && are_chunks_in_same_line(frm.at(sub).pc, frm.top().pc))
+ {
+ sub--;
+ skipped = true;
+ }
+
+ if ( ( frm.at(sub + 1).type == CT_CLASS_COLON
+ || frm.at(sub + 1).type == CT_CONSTR_COLON)
+ && (chunk_is_token(frm.at(sub + 1).pc->prev, CT_NEWLINE)))
+ {
+ sub = sub + 1;
+ }
+ }
+ frm.top().indent = frm.at(sub).indent + indent_size;
+ log_indent();
+
+ frm.top().indent_tab = frm.top().indent;
+ skipped = true;
+ }
+ else
+ {
+ if ( next->IsNotNullChunk()
+ && !next->IsComment())
+ {
+ if (chunk_is_token(next, CT_SPACE))
+ {
+ next = next->GetNextNc();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ }
+
+ if (next->prev->IsComment())
+ {
+ // Issue #2099
+ frm.top().indent = next->prev->column;
+ }
+ else
+ {
+ frm.top().indent = next->column;
+ }
+ log_indent();
+ }
+ }
+ }
+ log_rule_B("use_indent_continue_only_once");
+ log_rule_B("indent_paren_after_func_decl");
+ log_rule_B("indent_paren_after_func_def");
+ log_rule_B("indent_paren_after_func_call");
+
+ if ( ( ( !frm.top().indent_cont // Issue #3567
+ && vardefcol == 0)
+ || ( !options::use_indent_continue_only_once() // Issue #1160
+ && !options::indent_ignore_first_continue())) // Issue #3561
+ && ( chunk_is_token(pc, CT_FPAREN_OPEN)
+ && chunk_is_newline(pc->GetPrev()))
+ && ( ( ( get_chunk_parent_type(pc) == CT_FUNC_PROTO
+ || get_chunk_parent_type(pc) == CT_FUNC_CLASS_PROTO)
+ && options::indent_paren_after_func_decl())
+ || ( ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF)
+ && options::indent_paren_after_func_def())
+ || ( ( get_chunk_parent_type(pc) == CT_FUNC_CALL
+ || get_chunk_parent_type(pc) == CT_FUNC_CALL_USER)
+ && options::indent_paren_after_func_call())
+ || !chunk_is_newline(pc->GetNext())))
+ {
+ frm.top().indent = frm.prev().indent + indent_size;
+ log_indent();
+
+ indent_column_set(frm.top().indent);
+ }
+ log_rule_B("indent_continue");
+
+ if ( get_chunk_parent_type(pc) != CT_OC_AT
+ && ( options::indent_ignore_first_continue()
+ || options::indent_continue() != 0)
+ && !skipped)
+ {
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().indent = get_indent_first_continue(pc->GetNext());
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent;
+ }
+ log_indent();
+
+ if ( pc->level == pc->brace_level
+ && !options::indent_ignore_first_continue()
+ && ( chunk_is_token(pc, CT_FPAREN_OPEN)
+ || chunk_is_token(pc, CT_SPAREN_OPEN)
+ || ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(pc) != CT_OC_MSG)
+ || chunk_is_token(pc, CT_ANGLE_OPEN))) // Issue #1170
+ {
+ //log_rule_B("indent_continue");
+ //frm.top().indent += abs(options::indent_continue());
+ // frm.top().indent = calc_indent_continue(frm);
+ // frm.top().indent_cont = true;
+ log_rule_B("use_indent_continue_only_once");
+
+ if ( (options::use_indent_continue_only_once())
+ && (frm.top().indent_cont)
+ && vardefcol != 0)
+ {
+ /*
+ * The value of the indentation for a continuation line is calculate
+ * differently if the line is:
+ * a declaration :your case with QString fileName ...
+ * an assignment :your case with pSettings = new QSettings( ...
+ * At the second case the option value might be used twice:
+ * at the assignment
+ * at the function call (if present)
+ * If you want to prevent the double use of the option value
+ * you may use the new option :
+ * use_indent_continue_only_once
+ * with the value "true".
+ * use/don't use indent_continue once Guy 2016-05-16
+ */
+
+ // if vardefcol isn't zero, use it
+ frm.top().indent = vardefcol;
+ log_indent();
+ }
+ else
+ {
+ frm.top().indent = calc_indent_continue(frm);
+ log_indent();
+ frm.top().indent_cont = true;
+
+ log_rule_B("indent_sparen_extra");
+
+ if ( chunk_is_token(pc, CT_SPAREN_OPEN)
+ && options::indent_sparen_extra() != 0)
+ {
+ frm.top().indent += options::indent_sparen_extra();
+ log_indent();
+ }
+ }
+ }
+ }
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+
+ frm.paren_count++;
+ }
+ else if ( options::indent_member_single()
+ && chunk_is_token(pc, CT_MEMBER)
+ && (strcmp(pc->Text(), ".") == 0)
+ && language_is_set(LANG_CS | LANG_CPP))
+ {
+ log_rule_B("indent_member_single");
+
+ if (frm.top().type != CT_MEMBER)
+ {
+ frm.push(pc, __func__, __LINE__);
+ Chunk *tmp = frm.top().pc->GetPrevNcNnlNpp();
+
+ if (are_chunks_in_same_line(frm.prev().pc, tmp))
+ {
+ frm.top().indent = frm.prev().indent;
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent + indent_size;
+ }
+ log_indent();
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+
+ if (chunk_is_newline(pc->GetPrev()))
+ {
+ if ( chunk_is_token(pc, CT_MEMBER) // Issue #2890
+ && language_is_set(LANG_CPP))
+ {
+ // will be done at another place
+ // look at the comment: XXXXXXXXXXXXXXXXXXXXXXXXXX
+ }
+ else
+ {
+ indent_column_set(frm.top().indent);
+ reindent_line(pc, indent_column);
+ did_newline = false;
+ }
+ }
+ //check for the series of CT_member chunks else pop it.
+ Chunk *tmp = pc->GetNextNcNnlNpp();
+
+ if (tmp->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_FUNC_CALL))
+ {
+ tmp = tmp->GetNextType(CT_FPAREN_CLOSE, tmp->level);
+ tmp = tmp->GetNextNcNnlNpp();
+ }
+ else if ( chunk_is_token(tmp, CT_WORD)
+ || chunk_is_token(tmp, CT_TYPE))
+ {
+ tmp = tmp->GetNextNcNnlNpp();
+ }
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && ( (strcmp(tmp->Text(), ".") != 0)
+ || tmp->type != CT_MEMBER))
+ {
+ if (chunk_is_paren_close(tmp))
+ {
+ tmp = tmp->GetPrevNcNnlNpp();
+ }
+ Chunk *local_prev = tmp->GetPrev(); // Issue #3294
+
+ if (local_prev->IsComment())
+ {
+ tmp = tmp->GetPrev(); // Issue #3294
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && chunk_is_newline(tmp->GetPrev()))
+ {
+ tmp = tmp->GetPrevNcNnlNpp()->GetNextNl();
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ frm.top().pop_pc = tmp;
+ }
+ }
+ }
+ else if ( chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_IMPORT)
+ || ( chunk_is_token(pc, CT_USING)
+ && language_is_set(LANG_CS)))
+ {
+ /*
+ * if there is a newline after the '=' or the line starts with a '=',
+ * just indent one level,
+ * otherwise align on the '='.
+ */
+ if ( chunk_is_token(pc, CT_ASSIGN)
+ && chunk_is_newline(pc->GetPrev()))
+ {
+ if (frm.top().type == CT_ASSIGN_NL)
+ {
+ frm.top().indent_tmp = frm.top().indent;
+ }
+ else
+ {
+ frm.top().indent_tmp = frm.top().indent + indent_size;
+ }
+ log_indent_tmp();
+
+ indent_column_set(frm.top().indent_tmp);
+ LOG_FMT(LINDENT, "%s(%d): %zu] assign => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, frm.top().indent_tmp);
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNotNullChunk())
+ {
+ /*
+ * fixes 1260 , 1268 , 1277 (Extra indentation after line with multiple assignments)
+ * For multiple consecutive assignments in single line , the indent of all these
+ * assignments should be same and one more than this line's indent.
+ * so poping the previous assign and pushing the new one
+ */
+ if ( frm.top().type == CT_ASSIGN
+ && chunk_is_token(pc, CT_ASSIGN))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ frm.push(pc, __func__, __LINE__);
+
+ if ( chunk_is_token(pc, CT_ASSIGN)
+ && chunk_is_newline(pc->GetPrev()))
+ {
+ frm.top().type = CT_ASSIGN_NL;
+ }
+ log_rule_B("indent_continue");
+
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().indent = get_indent_first_continue(pc);
+ log_indent();
+ frm.top().indent_cont = true; // Issue #3567
+ }
+ else if (options::indent_continue() != 0)
+ {
+ frm.top().indent = frm.prev().indent;
+ log_indent();
+
+ if ( pc->level == pc->brace_level
+ && ( pc->type != CT_ASSIGN
+ || ( get_chunk_parent_type(pc) != CT_FUNC_PROTO
+ && get_chunk_parent_type(pc) != CT_FUNC_DEF)))
+ {
+ log_rule_B("use_indent_continue_only_once");
+
+ if ( (options::use_indent_continue_only_once())
+ && (frm.top().indent_cont)
+ && vardefcol != 0)
+ {
+ // if vardefcol isn't zero, use it
+ frm.top().indent = vardefcol;
+ log_indent();
+ }
+ else
+ {
+ frm.top().indent = calc_indent_continue(frm);
+ log_indent();
+
+ vardefcol = frm.top().indent; // use the same variable for the next line
+ frm.top().indent_cont = true;
+ }
+ }
+ }
+ else if ( chunk_is_newline(next)
+ || !options::indent_align_assign())
+ {
+ log_rule_B("indent_align_assign");
+ log_rule_B("indent_off_after_assign");
+
+ if (options::indent_off_after_assign()) // Issue #2591
+ {
+ frm.top().indent = frm.prev().indent_tmp;
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent_tmp + indent_size;
+ }
+ log_indent();
+
+ if ( chunk_is_token(pc, CT_ASSIGN)
+ && chunk_is_newline(next))
+ {
+ frm.top().type = CT_ASSIGN_NL;
+ frm.top().indent_tab = frm.top().indent;
+ }
+ }
+ else
+ {
+ frm.top().indent = pc->column + pc->Len() + 1;
+ log_indent();
+ }
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ }
+ else if ( chunk_is_token(pc, CT_RETURN)
+ || ( chunk_is_token(pc, CT_THROW)
+ && get_chunk_parent_type(pc) == CT_NONE))
+ {
+ // don't count returns inside a () or []
+ if ( pc->level == pc->brace_level
+ || pc->flags.test(PCF_IN_LAMBDA))
+ {
+ Chunk *next = pc->GetNext();
+
+ // Avoid indentation on return token set by the option.
+ log_rule_B("indent_off_after_return");
+
+ // Avoid indentation on return token if the next token is a new token
+ // to properly indent object initializers returned by functions.
+ log_rule_B("indent_off_after_return_new");
+ bool indent_after_return = ( next->IsNotNullChunk()
+ && next->type == CT_NEW)
+ ? !options::indent_off_after_return_new()
+ : !options::indent_off_after_return();
+
+ if ( indent_after_return
+ || next->IsNullChunk())
+ {
+ frm.push(pc, __func__, __LINE__);
+
+ log_rule_B("indent_single_after_return");
+
+ if ( chunk_is_newline(next)
+ || ( chunk_is_token(pc, CT_RETURN)
+ && options::indent_single_after_return()))
+ {
+ // apply normal single indentation
+ frm.top().indent = frm.prev().indent + indent_size;
+ }
+ else
+ {
+ // indent after the return token
+ frm.top().indent = frm.prev().indent + pc->Len() + 1;
+ }
+ log_indent();
+ frm.top().indent_tmp = frm.prev().indent;
+ log_indent_tmp();
+ }
+ log_indent();
+ }
+ }
+ else if ( chunk_is_token(pc, CT_OC_SCOPE)
+ || chunk_is_token(pc, CT_TYPEDEF))
+ {
+ frm.push(pc, __func__, __LINE__);
+ // Issue #405
+ frm.top().indent = frm.prev().indent;
+ log_indent();
+
+ frm.top().indent_tmp = frm.top().indent;
+ LOG_FMT(LINDLINE, "%s(%d): .indent is %zu, .indent_tmp is %zu\n",
+ __func__, __LINE__, frm.top().indent, frm.top().indent_tmp);
+
+ log_rule_B("indent_continue");
+
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().indent = get_indent_first_continue(pc);
+ log_indent();
+ }
+ else if (options::indent_continue() != 0)
+ {
+ frm.top().indent = calc_indent_continue(frm, frm.size() - 2);
+ log_indent();
+
+ frm.top().indent_cont = true;
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent + indent_size;
+ log_indent();
+ }
+ }
+ else if (chunk_is_token(pc, CT_C99_MEMBER))
+ {
+ // nothing to do
+ }
+ else if (chunk_is_token(pc, CT_WHERE_SPEC))
+ {
+ /* class indentation is ok already, just need to adjust func */
+ /* TODO: make this configurable, obviously.. */
+ if ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_PROTO
+ || ( get_chunk_parent_type(pc) == CT_STRUCT
+ && frm.top().type != CT_CLASS_COLON))
+ {
+ indent_column_set(frm.top().indent + 4);
+ }
+ }
+ else if ( options::indent_inside_ternary_operator()
+ && ( chunk_is_token(pc, CT_QUESTION)
+ || chunk_is_token(pc, CT_COND_COLON))) // Issue #1130, #1715
+ {
+ log_rule_B("indent_inside_ternary_operator");
+
+ // Pop any colons before because they should already be processed
+ while ( chunk_is_token(pc, CT_COND_COLON)
+ && frm.top().type == CT_COND_COLON)
+ {
+ frm.pop(__func__, __LINE__, pc);
+ }
+ log_rule_B("indent_inside_ternary_operator");
+
+ // Pop Question from stack in ternary operator
+ if ( options::indent_inside_ternary_operator()
+ && chunk_is_token(pc, CT_COND_COLON)
+ && frm.top().type == CT_QUESTION)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ indent_column_set(frm.top().indent_tmp);
+ }
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().indent = frm.prev().indent + indent_size;
+ frm.top().indent_tab = frm.top().indent;
+ log_indent();
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if ( chunk_is_token(pc, CT_LAMBDA)
+ && (language_is_set(LANG_CS | LANG_JAVA))
+ && pc->GetNextNcNnlNpp()->type != CT_BRACE_OPEN
+ && options::indent_cs_delegate_body())
+ {
+ log_rule_B("indent_cs_delegate_body");
+ frm.push(pc, __func__, __LINE__);
+ frm.top().indent = frm.prev().indent;
+ log_indent();
+
+ if ( chunk_is_newline(pc->GetPrevNc())
+ && !are_chunks_in_same_line(frm.prev().pc, pc->GetPrevNcNnl()))
+ {
+ frm.top().indent = frm.prev().indent + indent_size;
+ log_indent();
+ reindent_line(pc, (frm.prev().indent + indent_size));
+ did_newline = false;
+ }
+ else if ( chunk_is_newline(pc->GetNextNc())
+ && !are_chunks_in_same_line(frm.prev().pc, frm.top().pc))
+ {
+ frm.top().indent = frm.prev().indent + indent_size;
+ }
+ log_indent();
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && ( chunk_is_token(pc, CT_OC_MSG_FUNC)
+ || chunk_is_token(pc, CT_OC_MSG_NAME))
+ && chunk_is_token(pc->GetNextNcNnl(), CT_OC_COLON)) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ // Pop the OC msg name that is on the top of the stack
+ // [Class Message:<here>
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().indent = frm.prev().indent;
+ frm.top().indent_tab = frm.prev().indent_tab;
+ log_indent();
+ frm.top().indent_tmp = frm.prev().indent_tmp;
+ log_indent_tmp();
+ }
+ else if (pc->IsComment())
+ {
+ // Issue #3294
+ Chunk *next = pc->GetNext();
+
+ if (chunk_is_token(next, CT_COND_COLON))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): Comment and COND_COLON: pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ frm.pop(__func__, __LINE__, pc);
+ }
+// uncomment the line below to get debug info
+// #define ANYTHING_ELSE
+#ifdef ANYTHING_ELSE
+ else
+ {
+ // anything else?
+ // Issue #3294
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ LOG_FMT(LSPACE, "\n\n%s(%d): WARNING: unrecognize indent_text:\n",
+ __func__, __LINE__);
+ }
+#endif /* ANYTHING_ELSE */
+ }
+ else
+ {
+ // anything else?
+#ifdef ANYTHING_ELSE
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ LOG_FMT(LSPACE, "\n\n%s(%d): WARNING: unrecognize indent_text:\n",
+ __func__, __LINE__);
+#endif /* ANYTHING_ELSE */
+ }
+ // Handle shift expression continuation indenting
+ size_t shiftcontcol = 0;
+
+ log_rule_B("indent_shift");
+
+ if ( options::indent_shift() == 1
+ && !pc->flags.test(PCF_IN_ENUM)
+ && get_chunk_parent_type(pc) != CT_OPERATOR
+ && pc->type != CT_COMMENT
+ && pc->type != CT_COMMENT_CPP
+ && pc->type != CT_COMMENT_MULTI
+ && pc->type != CT_BRACE_OPEN
+ && pc->level > 0
+ && !pc->IsEmptyText())
+ {
+ bool in_shift = false;
+ bool is_operator = false;
+
+ // Are we in such an expression? Go both forwards and backwards.
+ Chunk *tmp = pc;
+
+ do
+ {
+ if (chunk_is_token(tmp, CT_SHIFT))
+ {
+ in_shift = true;
+ LOG_FMT(LINDENT2, "%s(%d): in_shift set to TRUE\n",
+ __func__, __LINE__);
+
+ tmp = tmp->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp, CT_OPERATOR))
+ {
+ is_operator = true;
+ }
+ break;
+ }
+ tmp = tmp->GetPrevNcNnl();
+ } while ( !in_shift
+ && tmp->IsNotNullChunk()
+ && tmp->type != CT_SEMICOLON
+ && tmp->type != CT_BRACE_OPEN
+ && tmp->type != CT_BRACE_CLOSE
+ && tmp->type != CT_COMMA
+ && tmp->type != CT_SPAREN_OPEN
+ && tmp->type != CT_SPAREN_CLOSE);
+
+ tmp = pc;
+
+ do
+ {
+ tmp = tmp->GetNextNcNnl();
+
+ if ( tmp->IsNotNullChunk()
+ && chunk_is_token(tmp, CT_SHIFT))
+ {
+ in_shift = true;
+ LOG_FMT(LINDENT2, "%s(%d): in_shift set to TRUE\n",
+ __func__, __LINE__);
+
+ tmp = tmp->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp, CT_OPERATOR))
+ {
+ is_operator = true;
+ }
+ break;
+ }
+ } while ( !in_shift
+ && tmp->IsNotNullChunk()
+ && tmp->type != CT_SEMICOLON
+ && tmp->type != CT_BRACE_OPEN
+ && tmp->type != CT_BRACE_CLOSE
+ && tmp->type != CT_COMMA
+ && tmp->type != CT_SPAREN_OPEN
+ && tmp->type != CT_SPAREN_CLOSE);
+
+ LOG_FMT(LINDENT2, "%s(%d): in_shift is %s\n",
+ __func__, __LINE__, in_shift ? "TRUE" : "FALSE");
+ Chunk *prev_nonl = pc->GetPrevNcNnl();
+ Chunk *prev2 = pc->GetPrevNc();
+
+ if (( chunk_is_semicolon(prev_nonl)
+ || chunk_is_token(prev_nonl, CT_BRACE_OPEN)
+ || chunk_is_token(prev_nonl, CT_BRACE_CLOSE)
+ || chunk_is_token(prev_nonl, CT_VBRACE_CLOSE)
+ || chunk_is_token(prev_nonl, CT_VBRACE_OPEN)
+ || chunk_is_token(prev_nonl, CT_CASE_COLON)
+ || ( prev_nonl->IsNotNullChunk()
+ && prev_nonl->flags.test(PCF_IN_PREPROC)) != pc->flags.test(PCF_IN_PREPROC)
+ || chunk_is_token(prev_nonl, CT_COMMA)
+ || is_operator))
+ {
+ in_shift = false;
+ }
+ LOG_FMT(LINDENT2, "%s(%d): in_shift is %s\n",
+ __func__, __LINE__, in_shift ? "TRUE" : "FALSE");
+
+ if ( chunk_is_token(prev2, CT_NEWLINE)
+ && in_shift)
+ {
+ shiftcontcol = calc_indent_continue(frm);
+ // Setting frm.top().indent_cont = true in the top context when the indent is not also set
+ // just leads to compications when succeeding statements try to indent based on being
+ // embedded in a continuation. In other words setting frm.top().indent_cont = true
+ // should only be set if frm.top().indent is also set.
+
+ // Work around the doubly increased indent in RETURNs and assignments
+ bool need_workaround = false;
+ size_t sub = 0;
+
+ for (int i = frm.size() - 1; i >= 0; i--)
+ {
+ if ( frm.at(i).type == CT_RETURN
+ || frm.at(i).type == CT_ASSIGN)
+ {
+ need_workaround = true;
+ sub = frm.size() - i;
+ break;
+ }
+ }
+
+ if (need_workaround)
+ {
+ shiftcontcol = calc_indent_continue(frm, frm.size() - 1 - sub);
+ }
+ }
+ }
+
+ // Handle variable definition continuation indenting
+ if ( vardefcol == 0
+ && ( chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_FUNC_CTOR_VAR))
+ && !pc->flags.test(PCF_IN_FCN_DEF)
+ && pc->flags.test(PCF_VAR_1ST_DEF))
+ {
+ log_rule_B("indent_continue");
+
+ if (options::indent_ignore_first_continue())
+ {
+ vardefcol = get_indent_first_continue(pc);
+ }
+ else if (options::indent_continue() != 0)
+ {
+ vardefcol = calc_indent_continue(frm);
+ // Setting frm.top().indent_cont = true in the top context when the indent is not also set
+ // just leads to compications when succeeding statements try to indent based on being
+ // embedded in a continuation. In other words setting frm.top().indent_cont = true
+ // should only be set if frm.top().indent is also set.
+ }
+ else if ( options::indent_var_def_cont()
+ || chunk_is_newline(pc->GetPrev()))
+ {
+ log_rule_B("indent_var_def_cont");
+ vardefcol = frm.top().indent + indent_size;
+ }
+ else
+ {
+ // Issue #3010
+ vardefcol = pc->column;
+ // BUT, we need to skip backward over any '*'
+ Chunk *tmp = pc->GetPrevNc();
+
+ while (chunk_is_token(tmp, CT_PTR_TYPE))
+ {
+ vardefcol = tmp->column;
+ tmp = tmp->GetPrevNc();
+ }
+ // BUT, we need to skip backward over any '::' or TYPE
+ //tmp = pc->GetPrevNc();
+
+ //if (chunk_is_token(tmp, CT_DC_MEMBER))
+ //{
+ // // look for a type
+ // Chunk *tmp2 = tmp->GetPrevNc();
+ // if (chunk_is_token(tmp2, CT_TYPE))
+ // {
+ // // we have something like "SomeLongNamespaceName::Foo()"
+ // vardefcol = tmp2->column;
+ // LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, vardefcol is %zu\n",
+ // __func__, __LINE__, pc->orig_line, vardefcol);
+ // }
+ //}
+ }
+ }
+
+ if ( chunk_is_semicolon(pc)
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && ( get_chunk_parent_type(pc) == CT_FUNCTION
+ || get_chunk_parent_type(pc) == CT_CLASS))) //Issue #3576
+ {
+ vardefcol = 0;
+ }
+
+ // Indent the line if needed
+ if ( did_newline
+ && !chunk_is_newline(pc)
+ && (pc->Len() != 0))
+ {
+ pc->column_indent = frm.top().indent_tab;
+
+ if (frm.top().ip.ref)
+ {
+ pc->indent.ref = frm.top().ip.ref;
+ pc->indent.delta = frm.top().ip.delta;
+ }
+ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, pc->column_indent is %zu, indent_column is %zu, for '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->column_indent, indent_column, pc->ElidedText(copy));
+
+ /*
+ * Check for special continuations.
+ * Note that some of these could be done as a stack item like
+ * everything else
+ */
+
+ auto prev = pc->GetPrevNcNnl();
+ auto prevv = prev->GetPrevNcNnl();
+ auto next = pc->GetNextNcNnl();
+
+ bool do_vardefcol = false;
+
+ if ( vardefcol > 0
+ && pc->level == pc->brace_level
+ && ( chunk_is_token(prev, CT_COMMA)
+ || chunk_is_token(prev, CT_TYPE)
+ || chunk_is_token(prev, CT_PTR_TYPE)
+ || chunk_is_token(prev, CT_WORD)))
+ {
+ Chunk *tmp = pc;
+
+ while (chunk_is_token(tmp, CT_PTR_TYPE))
+ {
+ tmp = tmp->GetNextNcNnl();
+ }
+ LOG_FMT(LINDENT2, "%s(%d): orig_line is %zu, for '%s'",
+ __func__, __LINE__, tmp->orig_line, tmp->Text());
+ LOG_FMT(LINDENT2, " tmp->flags: ");
+ log_pcf_flags(LINDENT2, tmp->flags); // Issue #2332
+
+ if ( tmp->flags.test(PCF_VAR_DEF)
+ && ( chunk_is_token(tmp, CT_WORD)
+ || chunk_is_token(tmp, CT_FUNC_CTOR_VAR)))
+ {
+ do_vardefcol = true;
+ }
+ }
+ //LOG_FMT(LINDENT2, "%s(%d): GUY 2:\n", __func__, __LINE__);
+
+ if (pc->flags.test(PCF_DONT_INDENT))
+ {
+ // no change
+ }
+ else if ( get_chunk_parent_type(pc) == CT_SQL_EXEC
+ && options::indent_preserve_sql())
+ {
+ log_rule_B("indent_preserve_sql");
+ reindent_line(pc, sql_col + (pc->orig_col - sql_orig_col));
+ LOG_FMT(LINDENT, "Indent SQL: [%s] to %zu (%zu/%zu)\n",
+ pc->Text(), pc->column, sql_col, sql_orig_col);
+ }
+ else if ( !options::indent_member_single()
+ && !pc->flags.test(PCF_STMT_START)
+ && ( chunk_is_token(pc, CT_MEMBER)
+ || ( chunk_is_token(pc, CT_DC_MEMBER)
+ && chunk_is_token(prev, CT_TYPE))
+ || ( chunk_is_token(prev, CT_MEMBER)
+ || ( chunk_is_token(prev, CT_DC_MEMBER)
+ && chunk_is_token(prevv, CT_TYPE)))))
+ {
+ log_rule_B("indent_member_single");
+ log_rule_B("indent_member");
+ size_t tmp = options::indent_member() + indent_column;
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, member => %zu\n",
+ __func__, __LINE__, pc->orig_line, tmp);
+ reindent_line(pc, tmp);
+ }
+ else if (do_vardefcol)
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, vardefcol is %zu\n",
+ __func__, __LINE__, pc->orig_line, vardefcol);
+ reindent_line(pc, vardefcol);
+ }
+ else if (shiftcontcol > 0)
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, shiftcontcol is %zu\n",
+ __func__, __LINE__, pc->orig_line, shiftcontcol);
+ reindent_line(pc, shiftcontcol);
+ }
+ else if ( chunk_is_token(pc, CT_NAMESPACE)
+ && options::indent_namespace()
+ && options::indent_namespace_single_indent()
+ && frm.top().ns_cnt)
+ {
+ log_rule_B("indent_namespace");
+ log_rule_B("indent_namespace_single_indent");
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, Namespace => %zu\n",
+ __func__, __LINE__, pc->orig_line, frm.top().brace_indent);
+ reindent_line(pc, frm.top().brace_indent);
+ }
+ else if ( chunk_is_token(pc, CT_STRING)
+ && chunk_is_token(prev, CT_STRING)
+ && options::indent_align_string())
+ {
+ log_rule_B("indent_align_string");
+ const int tmp = (xml_indent != 0) ? xml_indent : prev->column;
+
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, String => %d\n",
+ __func__, __LINE__, pc->orig_line, tmp);
+ reindent_line(pc, tmp);
+ }
+ else if (pc->IsComment())
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, comment => %zu\n",
+ __func__, __LINE__, pc->orig_line, frm.top().indent_tmp);
+ indent_comment(pc, frm.top().indent_tmp);
+ }
+ else if (chunk_is_token(pc, CT_PREPROC))
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, pp-indent => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( chunk_is_paren_close(pc)
+ || chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ /*
+ * This is a big hack. We assume that since we hit a paren close,
+ * that we just removed a paren open
+ */
+ LOG_FMT(LINDLINE, "%s(%d): indent_column is %zu\n",
+ __func__, __LINE__, indent_column);
+
+ if (frm.poped().type == E_Token(pc->type - 1))
+ {
+ // Issue # 405
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ Chunk *ck1 = frm.poped().pc;
+ LOG_FMT(LINDLINE, "%s(%d): ck1->orig_line is %zu, ck1->orig_col is %zu, ck1->Text() is '%s', ck1->type is %s\n",
+ __func__, __LINE__, ck1->orig_line, ck1->orig_col, ck1->Text(), get_token_name(ck1->type));
+ Chunk *ck2 = ck1->GetPrev();
+ LOG_FMT(LINDLINE, "%s(%d): ck2->orig_line is %zu, ck2->orig_col is %zu, ck2->Text() is '%s', ck2->type is %s\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col, ck2->Text(), get_token_name(ck2->type));
+
+ log_rule_B("indent_paren_close");
+
+ if (options::indent_paren_close() == -1)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is -1\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col);
+ indent_column_set(pc->orig_col);
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column);
+ }
+ else if ( chunk_is_newline(ck2)
+ || (options::indent_paren_close() == 1))
+ {
+ /*
+ * If the open parenthesis was the first thing on the line or we
+ * are doing mode 1, then put the close parenthesis in the same
+ * column
+ */
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is 1\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col);
+ indent_column_set(ck1->column);
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column);
+ }
+ else
+ {
+ if (options::indent_paren_close() != 2)
+ {
+ // indent_paren_close is 0 or 1
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is 0 or 1\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col);
+ indent_column_set(frm.poped().indent_tmp);
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column);
+ pc->column_indent = frm.poped().indent_tab;
+ log_rule_B("indent_paren_close");
+
+ if (options::indent_paren_close() == 1)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_paren_close is 1\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col);
+
+ if (indent_column == 0)
+ {
+ fprintf(stderr, "%s(%d): indent_column is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ indent_column--;
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col, indent_column);
+ }
+ }
+ else
+ {
+ // indent_paren_close is 2: Indent to the brace level
+ LOG_FMT(LINDLINE, "%s(%d): indent_paren_close is 2\n",
+ __func__, __LINE__);
+ LOG_FMT(LINDLINE, "%s(%d): ck2->orig_line is %zu, ck2->orig_col is %zu, ck2->Text() is '%s'\n",
+ __func__, __LINE__, ck2->orig_line, ck2->orig_col, ck2->Text());
+
+ if (pc->GetPrev()->type == CT_NEWLINE)
+ {
+ LOG_FMT(LINDLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ LOG_FMT(LINDLINE, "%s(%d): prev is <newline>\n",
+ __func__, __LINE__);
+ Chunk *search = pc;
+
+ while (chunk_is_paren_close(search->GetNext()))
+ {
+ search = search->GetNext();
+ }
+ Chunk *searchNext = search->GetNext();
+
+ // Issue #3407 - Skip over a possible 'noexcept' keyword before going forward.
+ if (searchNext->type == CT_NOEXCEPT)
+ {
+ searchNext = searchNext->GetNext();
+ }
+
+ if ( searchNext->type == CT_SEMICOLON
+ || searchNext->type == CT_MEMBER // Issue #2582
+ || searchNext->type == CT_NEWLINE)
+ {
+ LOG_FMT(LINDLINE, "%s(%d):\n", __func__, __LINE__);
+ search = chunk_skip_to_match_rev(search);
+
+ if ( options::indent_oc_inside_msg_sel()
+ && chunk_is_token(search->GetPrevNcNnl(), CT_OC_COLON)
+ && ( frm.top().type == CT_OC_MSG_FUNC
+ || frm.top().type == CT_OC_MSG_NAME)) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ // [Class Message:(...)<here>
+ indent_column_set(frm.top().pc->column);
+ }
+ else if ( options::indent_inside_ternary_operator()
+ && ( frm.top().type == CT_QUESTION
+ || frm.top().type == CT_COND_COLON)) // Issue #1130, #1715
+ {
+ log_rule_B("indent_inside_ternary_operator");
+ indent_column_set(frm.top().indent);
+ }
+ else
+ {
+ search = search->GetPrevNl()->GetNext();
+
+ if (search->IsNullChunk())
+ {
+ search = Chunk::GetHead();
+ }
+ indent_column_set(search->column);
+ }
+ }
+ }
+ }
+ }
+ }
+ size_t indent_value = 0;
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, closing parenthesis => %zu, text is '%s'\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ LOG_FMT(LINDENT, "%s(%d): [%s/%s]\n",
+ __func__, __LINE__,
+ get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)));
+ Chunk *prev2 = pc->GetPrev(); // Issue #2930
+ LOG_FMT(LINDENT, "%s(%d): prev2 is orig_line is %zu, text is '%s'\n",
+ __func__, __LINE__, prev2->orig_line, prev2->Text());
+ Chunk *next2 = pc->GetNext();
+ LOG_FMT(LINDENT, "%s(%d): next2 is orig_line is %zu, text is '%s'\n",
+ __func__, __LINE__, next2->orig_line, next2->Text());
+
+ if ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ && chunk_is_newline(prev2)
+ && chunk_is_newline(next2))
+ {
+ if (options::donot_indent_func_def_close_paren())
+ {
+ indent_value = 1;
+ }
+ else
+ {
+ reindent_line(pc, indent_column);
+ indent_value = indent_column;
+ }
+ }
+ else
+ {
+ indent_value = indent_column;
+ }
+ reindent_line(pc, indent_value);
+ }
+ else if (chunk_is_token(pc, CT_COMMA))
+ {
+ bool align = false;
+ bool ignore = false;
+
+ if (chunk_is_paren_open(frm.top().pc))
+ {
+ log_rule_B("indent_comma_paren");
+ align = options::indent_comma_paren() == (int)indent_mode_e::ALIGN;
+ ignore = options::indent_comma_paren() == (int)indent_mode_e::IGNORE;
+ }
+ else if (chunk_is_opening_brace(frm.top().pc))
+ {
+ log_rule_B("indent_comma_brace");
+ align = options::indent_comma_brace() == (int)indent_mode_e::ALIGN;
+ ignore = options::indent_comma_brace() == (int)indent_mode_e::IGNORE;
+ }
+
+ if (ignore)
+ {
+ indent_column_set(pc->orig_col);
+ }
+ else if (align)
+ {
+ indent_column_set(frm.top().pc->column);
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] comma => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( options::indent_func_const()
+ && chunk_is_token(pc, CT_QUALIFIER)
+ && strncasecmp(pc->Text(), "const", pc->Len()) == 0
+ && ( next == nullptr
+ || chunk_is_token(next, CT_BRACED)
+ || chunk_is_token(next, CT_BRACE_OPEN)
+ || chunk_is_token(next, CT_NEWLINE)
+ || chunk_is_token(next, CT_SEMICOLON)
+ || chunk_is_token(next, CT_THROW)
+ || chunk_is_token(next, CT_VBRACE_OPEN)))
+ {
+ // indent const - void GetFoo(void)\n const\n { return (m_Foo); }
+ log_rule_B("indent_func_const");
+ indent_column_set(frm.top().indent + options::indent_func_const());
+ LOG_FMT(LINDENT, "%s(%d): %zu] const => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( options::indent_func_throw()
+ && chunk_is_token(pc, CT_THROW)
+ && get_chunk_parent_type(pc) != CT_NONE)
+ {
+ // indent throw - void GetFoo(void)\n throw()\n { return (m_Foo); }
+ log_rule_B("indent_func_throw");
+ indent_column_set(options::indent_func_throw());
+ LOG_FMT(LINDENT, "%s(%d): %zu] throw => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ if ( pc->flags.test(PCF_IN_FOR)
+ && options::indent_semicolon_for_paren())
+ {
+ log_rule_B("indent_semicolon_for_paren");
+ indent_column_set(frm.top().pc->column);
+
+ log_rule_B("indent_first_for_expr");
+
+ if (options::indent_first_for_expr())
+ {
+ reindent_line(frm.top().pc->GetNext(),
+ indent_column + pc->Len() + 1);
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] SEMICOLON => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else
+ {
+ log_rule_B("indent_ignore_semicolon");
+
+ if (options::indent_ignore_semicolon())
+ {
+ indent_column_set(pc->orig_col);
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] semicolon => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ }
+ else if (chunk_is_token(pc, CT_BOOL))
+ {
+ if (chunk_is_paren_open(frm.top().pc))
+ {
+ log_rule_B("indent_bool_paren");
+
+ if (options::indent_bool_paren() == (int)indent_mode_e::IGNORE)
+ {
+ indent_column_set(pc->orig_col);
+ }
+ else if (options::indent_bool_paren() == (int)indent_mode_e::ALIGN)
+ {
+ indent_column_set(frm.top().pc->column);
+
+ log_rule_B("indent_first_bool_expr");
+
+ if (options::indent_first_bool_expr())
+ {
+ reindent_line(frm.top().pc->GetNext(),
+ indent_column + pc->Len() + 1);
+ }
+ }
+ }
+ else
+ {
+ log_rule_B("indent_ignore_bool");
+
+ if (options::indent_ignore_bool())
+ {
+ indent_column_set(pc->orig_col);
+ }
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] bool => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( chunk_is_token(pc, CT_ARITH)
+ || chunk_is_token(pc, CT_CARET))
+ {
+ log_rule_B("indent_ignore_arith");
+
+ if (options::indent_ignore_arith())
+ {
+ indent_column_set(pc->orig_col);
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] arith => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if (chunk_is_token(pc, CT_SHIFT))
+ {
+ log_rule_B("indent_shift");
+
+ if (options::indent_shift() == -1)
+ {
+ indent_column_set(pc->orig_col);
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] shift => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ log_rule_B("indent_ignore_assign");
+
+ if (options::indent_ignore_assign())
+ {
+ indent_column_set(pc->orig_col);
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] assign => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( options::indent_ternary_operator() == 1
+ && chunk_is_token(prev, CT_COND_COLON)
+ && ( chunk_is_token(pc, CT_ADDR)
+ || chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_DEREF)
+ || chunk_is_token(pc, CT_NUMBER)
+ || chunk_is_token(pc, CT_STRING)
+ || chunk_is_token(pc, CT_PAREN_OPEN)))
+ {
+ log_rule_B("indent_ternary_operator");
+ Chunk *tmp = prev->GetPrevType(CT_QUESTION, -1);
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = tmp->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ LOG_FMT(LINDENT, "%s: %zu] ternarydefcol => %zu [%s]\n",
+ __func__, pc->orig_line, tmp->column, pc->Text());
+ reindent_line(pc, tmp->column);
+ }
+ }
+ }
+ else if ( options::indent_ternary_operator() == 2
+ && chunk_is_token(pc, CT_COND_COLON))
+ {
+ log_rule_B("indent_ternary_operator");
+ Chunk *tmp = pc->GetPrevType(CT_QUESTION, -1);
+
+ if (tmp->IsNotNullChunk())
+ {
+ LOG_FMT(LINDENT, "%s: %zu] ternarydefcol => %zu [%s]\n",
+ __func__, pc->orig_line, tmp->column, pc->Text());
+ reindent_line(pc, tmp->column);
+ }
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && ( chunk_is_token(pc, CT_OC_MSG_FUNC)
+ || chunk_is_token(pc, CT_OC_MSG_NAME))) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ reindent_line(pc, frm.top().indent);
+ }
+ else
+ {
+ bool use_indent = true;
+ const size_t ttidx = frm.size() - 1;
+
+ if (ttidx > 0)
+ {
+ LOG_FMT(LINDPC, "%s(%d): (frm.at(ttidx).pc)->parent_type is %s\n",
+ __func__, __LINE__, get_token_name((frm.at(ttidx).pc)->parent_type));
+
+ if ((frm.at(ttidx).pc)->parent_type == CT_FUNC_CALL)
+ {
+ LOG_FMT(LINDPC, "FUNC_CALL OK [%d]\n", __LINE__);
+
+ log_rule_B("use_indent_func_call_param");
+
+ if (options::use_indent_func_call_param())
+ {
+ LOG_FMT(LINDPC, "use is true [%d]\n", __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LINDPC, "use is false [%d]\n", __LINE__);
+ use_indent = false;
+ }
+ }
+ }
+ LOG_FMT(LINDENT, "%s(%d): pc->line is %zu, pc->column is %zu, pc->Text() is '%s, indent_column is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->column, pc->Text(), indent_column);
+
+ if ( use_indent
+ && pc->type != CT_PP_IGNORE) // Leave indentation alone for PP_IGNORE tokens
+ {
+ log_rule_B("pos_conditional");
+
+ if ( ( chunk_is_token(pc, CT_QUESTION) // Issue #2101
+ || chunk_is_token(pc, CT_COND_COLON)) // Issue #2101
+ && options::pos_conditional() == TP_IGNORE)
+ {
+ // do not indent this line
+ LOG_FMT(LINDENT, "%s(%d): %zu] don't indent this line\n",
+ __func__, __LINE__, pc->orig_line);
+ }
+ else if (chunk_is_token(pc, CT_BREAK))
+ {
+ // Issue #1692
+ log_rule_B("indent_switch_break_with_case");
+
+ // Issue #2281
+ if ( options::indent_switch_break_with_case()
+ && get_type_of_the_parent(pc) == CT_SWITCH)
+ {
+ // look for a case before Issue #2735
+ Chunk *whereIsCase = pc->GetPrevType(CT_CASE, pc->level);
+
+ if (whereIsCase->IsNotNullChunk())
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, whereIsCase->orig_line, whereIsCase->orig_col, whereIsCase->Text());
+ LOG_FMT(LINDENT, "%s(%d): column is %zu\n",
+ __func__, __LINE__, whereIsCase->column);
+ reindent_line(pc, whereIsCase->column);
+ }
+ }
+ else
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent_column set to %zu, for '%s'\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ }
+ else if ( chunk_is_token(pc, CT_MEMBER) // Issue #2890
+ && language_is_set(LANG_CPP))
+ {
+ // comment name: XXXXXXXXXXXXXXXXXXXXXXXXXX
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent_column set to %zu, for '%s'\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ const size_t frm_size = frm.size();
+ LOG_FMT(LINDPC, "%s(%d): frm_size is %zu\n",
+ __func__, __LINE__, frm_size);
+ // get pc
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', (frm.at(frm_size - 1).pc)->type is %s\n",
+ __func__, __LINE__, (frm.at(frm_size - 1).pc)->Text(), get_token_name((frm.at(frm_size - 1).pc)->type));
+ // get the token before
+ const size_t temp_ttidx = frm_size - 2;
+
+ if (temp_ttidx == 0)
+ {
+ indent_column = 1 + indent_size;
+ reindent_line(pc, indent_column);
+ }
+ else
+ {
+ Chunk *token_before = frm.at(temp_ttidx).pc;
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', token_before->type is %s\n",
+ __func__, __LINE__, token_before->Text(), get_token_name(token_before->type));
+
+ size_t vor_col = 0;
+
+ if (chunk_is_token(token_before, CT_ASSIGN))
+ {
+ Chunk *before_Assign = frm.at(temp_ttidx - 1).pc;
+
+ if (before_Assign == nullptr)
+ {
+ indent_column = 1 + indent_size;
+ }
+ else
+ {
+ vor_col = before_Assign->column;
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', before_Assign->type is %s, column is %zu\n",
+ __func__, __LINE__, before_Assign->Text(), get_token_name(before_Assign->type), vor_col);
+ indent_column = vor_col + 2 * indent_size;
+ }
+ }
+ else if (chunk_is_token(token_before, CT_BRACE_OPEN))
+ {
+ vor_col = token_before->column;
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', token_before->type is %s, column is %zu\n",
+ __func__, __LINE__, token_before->Text(), get_token_name(token_before->type), vor_col);
+ indent_column = vor_col + 2 * indent_size;
+ }
+ else if (chunk_is_token(token_before, CT_RETURN))
+ {
+ Chunk *before_Return = frm.at(temp_ttidx - 1).pc;
+ vor_col = before_Return->column;
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', before_Return->type is %s, column is %zu\n",
+ __func__, __LINE__, before_Return->Text(), get_token_name(before_Return->type), vor_col);
+ indent_column = vor_col + 2 * indent_size;
+ }
+ else
+ {
+ // TO DO
+ }
+ reindent_line(pc, indent_column);
+ }
+ reindent_line(pc, indent_column);
+ }
+ else
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, indent_column set to %zu, for '%s'\n",
+ __func__, __LINE__, pc->orig_line, indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ }
+ else
+ {
+ // do not indent this line
+ LOG_FMT(LINDENT, "%s(%d): %zu] don't indent this line\n",
+ __func__, __LINE__, pc->orig_line);
+ }
+ }
+ did_newline = false;
+
+ if ( chunk_is_token(pc, CT_SQL_EXEC)
+ || chunk_is_token(pc, CT_SQL_BEGIN)
+ || chunk_is_token(pc, CT_SQL_END))
+ {
+ sql_col = pc->column;
+ sql_orig_col = pc->orig_col;
+ }
+
+ // Handle indent for variable defs at the top of a block of code
+ if (pc->flags.test(PCF_VAR_TYPE))
+ {
+ if ( !frm.top().non_vardef
+ && (frm.top().type == CT_BRACE_OPEN))
+ {
+ log_rule_B("indent_var_def_blk");
+ const auto val = options::indent_var_def_blk();
+
+ if (val != 0)
+ {
+ auto indent = indent_column;
+ indent = (val > 0) ? val // reassign if positive val,
+ : (cast_abs(indent, val) < indent) // else if no underflow
+ ? (indent + val) : 0; // reduce, else 0
+
+ LOG_FMT(LINDENT, "%s(%d): %zu] var_type indent => %zu [%s]\n",
+ __func__, __LINE__, pc->orig_line, indent, pc->Text());
+ reindent_line(pc, indent);
+ }
+ }
+ }
+ else if (pc != frm.top().pc)
+ {
+ frm.top().non_vardef = true;
+ }
+ }
+
+ // if we hit a newline, reset indent_tmp
+ if ( chunk_is_newline(pc)
+ || chunk_is_token(pc, CT_COMMENT_MULTI)
+ || chunk_is_token(pc, CT_COMMENT_CPP))
+ {
+ log_indent();
+ frm.top().indent_tmp = frm.top().indent;
+ log_indent_tmp();
+
+ /*
+ * Handle the case of a multi-line #define w/o anything on the
+ * first line (indent_tmp will be 1 or 0)
+ */
+ if ( chunk_is_token(pc, CT_NL_CONT)
+ && (frm.top().indent_tmp <= indent_size))
+ {
+ frm.top().indent_tmp = indent_size + 1;
+ log_indent_tmp();
+ }
+ // Get ready to indent the next item
+ did_newline = true;
+ }
+ // Check for open XML tags "</..."
+ log_rule_B("indent_xml_string");
+
+ if ( options::indent_xml_string() > 0
+ && chunk_is_token(pc, CT_STRING)
+ && pc->Len() > 4
+ && pc->str[1] == '<'
+ && pc->str[2] != '/'
+ && pc->str[pc->Len() - 3] != '/')
+ {
+ if (xml_indent <= 0)
+ {
+ xml_indent = pc->column;
+ }
+ log_rule_B("indent_xml_string");
+ xml_indent += options::indent_xml_string();
+ }
+ // Issue #672
+ log_rule_B("indent_continue_class_head");
+
+ if ( chunk_is_token(pc, CT_CLASS)
+ && language_is_set(LANG_CPP | LANG_JAVA)
+ && ( options::indent_ignore_first_continue()
+ || options::indent_continue_class_head() != 0)
+ && !classFound)
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig_line is %zu, CT_CLASS found, OPEN IT\n",
+ __func__, __LINE__, pc->orig_line);
+ frm.push(pc, __func__, __LINE__);
+
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().indent = get_indent_first_continue(pc);
+ }
+ else
+ {
+ frm.top().indent = frm.prev().indent + options::indent_continue_class_head();
+ }
+ log_indent();
+
+ frm.top().indent_tmp = frm.top().indent;
+ frm.top().indent_tab = frm.top().indent;
+ log_indent_tmp();
+ classFound = true;
+ }
+ pc = pc->GetNext();
+ LOG_FMT(LINDLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ }
+null_pc:
+
+ // Throw out any stuff inside a preprocessor - no need to warn
+ while ( !frm.empty()
+ && frm.top().in_preproc)
+ {
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // Throw out any VBRACE_OPEN at the end - implied with the end of file
+ while ( !frm.empty()
+ && frm.top().type == CT_VBRACE_OPEN)
+ {
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ for (size_t idx_temp = 1; idx_temp < frm.size(); idx_temp++)
+ {
+ LOG_FMT(LWARN, "%s(%d): size is %zu\n",
+ __func__, __LINE__, frm.size());
+ LOG_FMT(LWARN, "%s(%d): File: %s, open_line is %zu, parent is %s: Unmatched %s\n",
+ __func__, __LINE__, cpd.filename.c_str(), frm.at(idx_temp).open_line,
+ get_token_name(frm.at(idx_temp).parent),
+ get_token_name(frm.at(idx_temp).type));
+ cpd.error_count++;
+ }
+
+ LOG_FMT(LINDLINE, "%s(%d): before quick_align_again\n", __func__, __LINE__);
+ quick_align_again();
+ quick_indent_again();
+ LOG_FMT(LINDLINE, "%s(%d): after quick_align_again\n", __func__, __LINE__);
+} // indent_text
+
+
+static bool single_line_comment_indent_rule_applies(Chunk *start, bool forward)
+{
+ LOG_FUNC_ENTRY();
+
+ if (!chunk_is_single_line_comment(start))
+ {
+ return(false);
+ }
+ Chunk *pc = start;
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ size_t nl_count = 0;
+
+ while ((pc = forward ? pc->GetNext() : pc->GetPrev())->IsNotNullChunk())
+ {
+ if (chunk_is_newline(pc))
+ {
+ if ( nl_count > 0
+ || pc->nl_count > 1)
+ {
+ return(false);
+ }
+ nl_count++;
+ }
+ else if (chunk_is_single_line_comment(pc))
+ {
+ nl_count = 0;
+ }
+ else if ( chunk_is_token(pc, CT_COMMENT_MULTI)
+ || (forward && chunk_is_closing_brace(pc))
+ || (!forward && chunk_is_opening_brace(pc)))
+ {
+ /*
+ * check for things we wouldn't want to indent the comment for
+ * example: non-single line comment, closing brace
+ */
+ return(false);
+ }
+ else
+ {
+ return(true);
+ }
+ }
+ return(false);
+} // single_line_comment_indent_rule_applies
+
+
+static bool is_end_of_assignment(Chunk *pc, const ParseFrame &frm)
+{
+ return( ( frm.top().type == CT_ASSIGN_NL
+ || frm.top().type == CT_MEMBER
+ || frm.top().type == CT_ASSIGN)
+ && ( chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_SPAREN_CLOSE)
+ || ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(pc) == CT_ASSIGN))
+ && get_chunk_parent_type(pc) != CT_CPP_LAMBDA);
+}
+
+
+static size_t calc_comment_next_col_diff(Chunk *pc)
+{
+ Chunk *next = pc; // assumes pc has a comment type
+
+ LOG_FMT(LCMTIND, "%s(%d): next->Text() is '%s'\n",
+ __func__, __LINE__, next->Text());
+
+ // Note: every comment is squashed into a single token
+ // (including newline chars for multiline comments) and is followed by
+ // a newline token (unless there are no more tokens left)
+ do
+ {
+ Chunk *newline_token = next->GetNext();
+ LOG_FMT(LCMTIND, "%s(%d): newline_token->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, newline_token->Text(), newline_token->orig_line, newline_token->orig_col);
+
+ if ( newline_token->IsNullChunk()
+ || newline_token->nl_count > 1)
+ {
+ return(5000); // FIXME: Max thresh magic number 5000
+ }
+ next = newline_token->GetNext();
+
+ if (next->IsNotNullChunk())
+ {
+ LOG_FMT(LCMTIND, "%s(%d): next->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, next->Text(), next->orig_line, next->orig_col);
+ }
+ } while (next->IsComment());
+
+ if (next->IsNullChunk())
+ {
+ return(5000); // FIXME: Max thresh magic number 5000
+ }
+ LOG_FMT(LCMTIND, "%s(%d): next->Text() is '%s'\n",
+ __func__, __LINE__, next->Text());
+ // here next is the first non comment, non newline token
+ return(next->orig_col > pc->orig_col
+ ? next->orig_col - pc->orig_col
+ : pc->orig_col - next->orig_col);
+}
+
+
+static void indent_comment(Chunk *pc, size_t col)
+{
+ LOG_FUNC_ENTRY();
+ char copy[1000];
+
+ LOG_FMT(LCMTIND, "%s(%d): pc->Text() is '%s', orig_line %zu, orig_col %zu, level %zu\n",
+ __func__, __LINE__, pc->ElidedText(copy), pc->orig_line, pc->orig_col, pc->level);
+
+ // force column 1 comment to column 1 if not changing them
+ log_rule_B("indent_col1_comment");
+
+ if ( pc->orig_col == 1
+ && !options::indent_col1_comment()
+ && !pc->flags.test(PCF_INSERTED))
+ {
+ LOG_FMT(LCMTIND, "%s(%d): rule 1 - keep in col 1\n", __func__, __LINE__);
+ reindent_line(pc, 1);
+ return;
+ }
+ Chunk *nl = pc->GetPrev();
+
+ if (nl->IsNotNullChunk())
+ {
+ LOG_FMT(LCMTIND, "%s(%d): nl->Text() is '%s', orig_line %zu, orig_col %zu, level %zu\n",
+ __func__, __LINE__, nl->Text(), nl->orig_line, nl->orig_col, nl->level);
+ }
+
+ if (pc->orig_col > 1)
+ {
+ Chunk *prev = nl->GetPrev();
+
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LCMTIND, "%s(%d): prev->Text() is '%s', orig_line %zu, orig_col %zu, level %zu\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col, prev->level);
+ log_pcf_flags(LCMTIND, prev->flags);
+ }
+
+ if ( prev->IsComment()
+ && nl->nl_count == 1)
+ {
+ const size_t prev_col_diff = (prev->orig_col > pc->orig_col)
+ ? prev->orig_col - pc->orig_col
+ : pc->orig_col - prev->orig_col;
+ LOG_FMT(LCMTIND, "%s(%d): prev_col_diff is %zu\n",
+ __func__, __LINE__, prev_col_diff);
+
+ /*
+ * Here we want to align comments that are relatively close one to
+ * another but not when the comment is a Doxygen comment (Issue #1134)
+ */
+ if (prev_col_diff <= options::indent_comment_align_thresh())
+ {
+ LOG_FMT(LCMTIND, "%s(%d): prev->Text() is '%s', Doxygen_comment(prev) is %s\n",
+ __func__, __LINE__, prev->Text(), chunk_is_Doxygen_comment(prev) ? "TRUE" : "FALSE");
+ LOG_FMT(LCMTIND, "%s(%d): pc->Text() is '%s', Doxygen_comment(pc) is %s\n",
+ __func__, __LINE__, pc->Text(), chunk_is_Doxygen_comment(pc) ? "TRUE" : "FALSE");
+
+ if (chunk_is_Doxygen_comment(prev) == chunk_is_Doxygen_comment(pc))
+ {
+ const size_t next_col_diff = calc_comment_next_col_diff(pc);
+ LOG_FMT(LCMTIND, "%s(%d): next_col_diff is %zu\n",
+ __func__, __LINE__, next_col_diff);
+
+ // Align to the previous comment or to the next token?
+ if ( prev_col_diff <= next_col_diff
+ || next_col_diff == 5000) // FIXME: Max thresh magic number 5000
+ {
+ LOG_FMT(LCMTIND, "%s(%d): rule 3 - prev comment, coldiff = %zu, now in %zu\n",
+ __func__, __LINE__, prev_col_diff, pc->column);
+ reindent_line(pc, prev->column);
+ return;
+ }
+ }
+ }
+ }
+ }
+ // check if special single-line-comment-before-code rule applies
+ log_rule_B("indent_single_line_comments_before");
+
+ if ( (options::indent_single_line_comments_before() > 0)
+ && single_line_comment_indent_rule_applies(pc, true))
+ {
+ LOG_FMT(LCMTIND, "%s(%d): rule 4 - indent single line comments before code, now in %zu\n",
+ __func__, __LINE__, pc->column);
+ reindent_line(pc, col + options::indent_single_line_comments_before());
+ return;
+ }
+ // check if special single-line-comment-after-code rule applies
+ log_rule_B("indent_single_line_comments_after");
+
+ if ( (options::indent_single_line_comments_after() > 0)
+ && single_line_comment_indent_rule_applies(pc, false))
+ {
+ LOG_FMT(LCMTIND, "%s(%d): rule 4 - indent single line comments after code, now in %zu\n",
+ __func__, __LINE__, pc->column);
+ reindent_line(pc, col + options::indent_single_line_comments_after());
+ return;
+ }
+ log_rule_B("indent_comment");
+
+ if ( pc->orig_col > 1
+ && !options::indent_comment())
+ {
+ LOG_FMT(LCMTIND, "%s(%d): rule 5 - keep in orig_col\n", __func__, __LINE__);
+ reindent_line(pc, pc->orig_col);
+ return;
+ }
+ LOG_FMT(LCMTIND, "%s(%d): rule 6 - fall-through, stay in %zu\n",
+ __func__, __LINE__, col);
+ reindent_line(pc, col);
+} // indent_comment
+
+
+bool ifdef_over_whole_file(void)
+{
+ LOG_FUNC_ENTRY();
+
+ // if requested, treat an #if that guards the entire file the same as any other #if
+ // if running as frag, assume #if is not a guard
+ if ( options::pp_indent_in_guard()
+ || cpd.frag)
+ {
+ return(false);
+ }
+
+ // the results for this file are cached
+ if (cpd.ifdef_over_whole_file)
+ {
+ return(cpd.ifdef_over_whole_file > 0);
+ }
+ Chunk *start_pp = Chunk::NullChunkPtr;
+ Chunk *end_pp = Chunk::NullChunkPtr;
+ size_t IFstage = 0;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ LOG_FMT(LNOTE, "%s(%d): pc->pp_level is %zu, pc->orig_line is %zu, pc->orig_col is %zu, pc->Text() is '%s'\n",
+ __func__, __LINE__, pc->pp_level, pc->orig_line, pc->orig_col, pc->Text());
+
+ if ( pc->IsComment()
+ || chunk_is_newline(pc))
+ {
+ continue;
+ }
+
+ if (IFstage == 0) // 0 is BEGIN
+ {
+ // Check the first preprocessor, make sure it is an #if type
+ if (pc->type != CT_PREPROC)
+ {
+ break;
+ }
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNullChunk()
+ || next->type != CT_PP_IF)
+ {
+ break;
+ }
+ IFstage = 1; // 1 is CT_PP_IF found
+ start_pp = pc;
+ }
+ else if (IFstage == 1) // 1 is CT_PP_IF found
+ {
+ // Scan until a preprocessor at level 0 is found - the close to the #if
+ if (chunk_is_token(pc, CT_PREPROC))
+ {
+ if (pc->pp_level == 0)
+ {
+ IFstage = 2;
+ end_pp = pc;
+ }
+ }
+ continue;
+ }
+ else if (IFstage == 2)
+ {
+ // We should only see the rest of the preprocessor
+ if ( chunk_is_token(pc, CT_PREPROC)
+ || !pc->flags.test(PCF_IN_PREPROC))
+ {
+ IFstage = 0;
+ break;
+ }
+ }
+ }
+
+ cpd.ifdef_over_whole_file = (IFstage == 2) ? 1 : -1;
+
+ if (cpd.ifdef_over_whole_file > 0)
+ {
+ chunk_flags_set(start_pp, PCF_WF_IF);
+ chunk_flags_set(end_pp, PCF_WF_ENDIF);
+ }
+ LOG_FMT(LNOTE, "The whole file is%s covered by a #IF\n",
+ (cpd.ifdef_over_whole_file > 0) ? "" : " NOT");
+ return(cpd.ifdef_over_whole_file > 0);
+} // ifdef_over_whole_file
+
+
+void indent_preproc(void)
+{
+ LOG_FUNC_ENTRY();
+
+ // Scan to see if the whole file is covered by one #ifdef
+ const size_t pp_level_sub = ifdef_over_whole_file() ? 1 : 0;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ LOG_FMT(LPPIS, "%s(%d): orig_line is %zu, orig_col is %zu, pc->Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ if (pc->type != CT_PREPROC)
+ {
+ continue;
+ }
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ const size_t pp_level = (pc->pp_level > pp_level_sub)
+ ? pc->pp_level - pp_level_sub : 0;
+
+ // Adjust the indent of the '#'
+ log_rule_B("pp_indent");
+
+ if (options::pp_indent() & IARF_ADD)
+ {
+ log_rule_B("pp_indent_count");
+ reindent_line(pc, 1 + pp_level * options::pp_indent_count());
+ }
+ else if (options::pp_indent() & IARF_REMOVE)
+ {
+ log_rule_B("pp_indent");
+ reindent_line(pc, 1);
+ }
+ // Add spacing by adjusting the length
+ log_rule_B("pp_space");
+
+ if ( (options::pp_space() != IARF_IGNORE)
+ && next != nullptr)
+ {
+ if (options::pp_space() & IARF_ADD)
+ {
+ log_rule_B("pp_space_count");
+ // Issue #3055
+ const size_t mult = max<size_t>(options::pp_space_count(), 1);
+ reindent_line(next, pc->column + pc->Len() + (pp_level * mult));
+ }
+ else if (options::pp_space() & IARF_REMOVE)
+ {
+ log_rule_B("pp_space");
+ reindent_line(next, pc->column + pc->Len());
+ }
+ }
+ // Mark as already handled if not region stuff or in column 1
+ log_rule_B("pp_indent_at_level");
+
+ bool at_file_level = pc->brace_level <= ((get_chunk_parent_type(pc) == CT_PP_DEFINE) ? 1 : 0);
+
+ if ( ( ( at_file_level
+ && !options::pp_indent_at_level0())
+ || ( !at_file_level
+ && !options::pp_indent_at_level()))
+ && get_chunk_parent_type(pc) != CT_PP_REGION
+ && get_chunk_parent_type(pc) != CT_PP_ENDREGION)
+ {
+ log_rule_B("pp_define_at_level");
+
+ if ( !options::pp_define_at_level()
+ || get_chunk_parent_type(pc) != CT_PP_DEFINE)
+ {
+ chunk_flags_set(pc, PCF_DONT_INDENT);
+ }
+ }
+ LOG_FMT(LPPIS, "%s(%d): orig_line %zu to %zu (len %zu, next->col %zu)\n",
+ __func__, __LINE__, pc->orig_line, 1 + pp_level, pc->Len(),
+ next ? next->column : -1);
+ }
+} // indent_preproc
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.h
new file mode 100644
index 00000000..9e91a94a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/indent.h
@@ -0,0 +1,59 @@
+/**
+ * @file indent.h
+ * prototypes for indent.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef INDENT_H_INCLUDED
+#define INDENT_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * Change the top-level indentation only by changing the column member in
+ * the chunk structures.
+ * The level indicator must already be set.
+ */
+void indent_text(void);
+
+
+/**
+ * Indent the preprocessor stuff from column 1.
+ * FIXME: This is broken if there is a comment or escaped newline
+ * between '#' and 'define'.
+ */
+void indent_preproc(void);
+
+/**
+ *
+ * @param pc chunk at the start of the line
+ * @param column desired column
+ */
+void indent_to_column(Chunk *pc, size_t column);
+
+
+/**
+ * Same as indent_to_column, except we can move both ways
+ *
+ * @param pc chunk at the start of the line
+ * @param column desired column
+ */
+void align_to_column(Chunk *pc, size_t column);
+
+
+//! Scan to see if the whole file is covered by one #ifdef
+bool ifdef_over_whole_file(void);
+
+
+/**
+ * Changes the initial indent for a line to the given column
+ *
+ * @param pc The chunk at the start of the line
+ * @param column The desired column
+ */
+void reindent_line(Chunk *pc, size_t column);
+
+
+#endif /* INDENT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.cpp
new file mode 100644
index 00000000..78fb2134
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.cpp
@@ -0,0 +1,670 @@
+/**
+ * @file keywords.cpp
+ * Manages the table of keywords.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * October 2015, 2016
+ * @license GPL v2+
+ */
+
+#include "keywords.h"
+
+#include "args.h"
+#include "prototypes.h"
+#include "uncrustify.h"
+#include "uncrustify_limits.h"
+
+#include <cerrno>
+#include <map>
+
+
+using namespace std;
+
+// Dynamic keyword map
+typedef map<string, E_Token> dkwmap;
+static dkwmap dkwm;
+
+
+/**
+ * Compares two chunk_tag_t entries using strcmp on the strings
+ *
+ * @param the 'left' entry
+ * @param the 'right' entry
+ *
+ * @return == 0 if both keywords are equal
+ * @return < 0 p1 is smaller than p2
+ * @return > 0 p2 is smaller than p1
+ */
+static int kw_compare(const void *p1, const void *p2);
+
+
+/**
+ * search in static keywords for first occurrence of a given tag
+ *
+ * @param tag/keyword to search for
+ */
+static const chunk_tag_t *kw_static_first(const chunk_tag_t *tag);
+
+
+static const chunk_tag_t *kw_static_match(bool orig_list, const chunk_tag_t *tag, int lang_flags);
+
+/**
+ * selected keywords for the choosed language.
+ */
+
+static chunk_tag_t keyword_for_lang[uncrustify::limits::MAX_KEYWORDS];
+static size_t language_count;
+
+/**
+ * interesting static keywords - keep sorted.
+ * Table includes the Name, Type, and Language flags.
+ */
+static chunk_tag_t keywords[] =
+{
+ // TODO: it might be useful if users could add their custom keywords to this list
+ { "@autoreleasepool", CT_AUTORELEASEPOOL, LANG_OC },
+ { "@available", CT_OC_AVAILABLE, LANG_OC },
+ { "@catch", CT_CATCH, LANG_OC },
+ { "@dynamic", CT_OC_DYNAMIC, LANG_OC },
+ { "@end", CT_OC_END, LANG_OC },
+ { "@finally", CT_FINALLY, LANG_OC },
+ { "@implementation", CT_OC_IMPL, LANG_OC },
+ { "@interface", CT_OC_INTF, LANG_OC },
+ { "@interface", CT_CLASS, LANG_JAVA },
+ { "@private", CT_ACCESS, LANG_OC },
+ { "@property", CT_OC_PROPERTY, LANG_OC },
+ { "@protected", CT_ACCESS, LANG_OC },
+ { "@protocol", CT_OC_PROTOCOL, LANG_OC },
+ { "@public", CT_ACCESS, LANG_OC },
+ { "@selector", CT_OC_SEL, LANG_OC },
+ { "@synchronized", CT_SYNCHRONIZED, LANG_OC },
+ { "@synthesize", CT_OC_DYNAMIC, LANG_OC },
+ { "@throw", CT_THROW, LANG_OC },
+ { "@try", CT_TRY, LANG_OC },
+ { "API_AVAILABLE", CT_ATTRIBUTE, LANG_OC },
+ { "API_DEPRECATED", CT_ATTRIBUTE, LANG_OC },
+ { "API_DEPRECATED_WITH_REPLACEMENT", CT_ATTRIBUTE, LANG_OC },
+ { "API_UNAVAILABLE", CT_ATTRIBUTE, LANG_OC },
+ { "BOOL", CT_TYPE, LANG_OC },
+ { "NS_ENUM", CT_ENUM, LANG_OC },
+ { "NS_OPTIONS", CT_ENUM, LANG_OC },
+ { "Q_EMIT", CT_Q_EMIT, LANG_CPP },
+ { "Q_FOREACH", CT_FOR, LANG_CPP },
+ { "Q_FOREVER", CT_Q_FOREVER, LANG_CPP },
+ { "Q_GADGET", CT_Q_GADGET, LANG_CPP },
+ { "Q_OBJECT", CT_COMMENT_EMBED, LANG_CPP },
+ { "Q_SIGNALS", CT_ACCESS, LANG_CPP },
+ { "_Bool", CT_TYPE, LANG_C | LANG_CPP },
+ { "_Complex", CT_TYPE, LANG_C | LANG_CPP },
+ { "_Imaginary", CT_TYPE, LANG_C | LANG_CPP },
+ { "_Nonnull", CT_QUALIFIER, LANG_OC },
+ { "_Null_unspecified", CT_QUALIFIER, LANG_OC },
+ { "_Nullable", CT_QUALIFIER, LANG_OC },
+ { "_Pragma", CT_PP_PRAGMA, LANG_ALL | FLAG_PP },
+ { "__DI__", CT_DI, LANG_C | LANG_CPP },
+ { "__HI__", CT_HI, LANG_C | LANG_CPP },
+ { "__QI__", CT_QI, LANG_C | LANG_CPP },
+ { "__SI__", CT_SI, LANG_C | LANG_CPP },
+ { "__asm__", CT_ASM, LANG_C | LANG_CPP },
+ { "__attribute__", CT_ATTRIBUTE, LANG_C | LANG_CPP | LANG_OC },
+ { "__autoreleasing", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__block", CT_QUALIFIER, LANG_C | LANG_CPP | LANG_OC },
+ { "__bridge", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__bridge_retained", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__bridge_transfer", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__const__", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__declspec", CT_DECLSPEC, LANG_C | LANG_CPP },
+ { "__except", CT_CATCH, LANG_C | LANG_CPP },
+ { "__finally", CT_FINALLY, LANG_C | LANG_CPP },
+ { "__has_include", CT_CNG_HASINC, LANG_C | LANG_CPP | FLAG_PP },
+ { "__has_include_next", CT_CNG_HASINCN, LANG_C | LANG_CPP | FLAG_PP },
+ { "__inline__", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__nonnull", CT_QUALIFIER, LANG_OC },
+ { "__nothrow__", CT_NOTHROW, LANG_C | LANG_CPP },
+ { "__null_unspecified", CT_QUALIFIER, LANG_OC },
+ { "__nullable", CT_QUALIFIER, LANG_OC },
+ { "__pragma", CT_PP_PRAGMA, LANG_ALL | FLAG_PP },
+ { "__restrict", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__signed__", CT_TYPE, LANG_C | LANG_CPP },
+ { "__strong", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__thread", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__traits", CT_QUALIFIER, LANG_D },
+ { "__try", CT_TRY, LANG_C | LANG_CPP },
+ { "__typeof", CT_DECLTYPE, LANG_C | LANG_CPP | LANG_OC },
+ { "__typeof__", CT_DECLTYPE, LANG_C | LANG_CPP },
+ { "__unsafe_unretained", CT_QUALIFIER, LANG_OC },
+ { "__unused", CT_ATTRIBUTE, LANG_C | LANG_CPP },
+ { "__volatile__", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__weak", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "__word__", CT_WORD_, LANG_C | LANG_CPP },
+ { "abstract", CT_QUALIFIER, LANG_CS | LANG_D | LANG_JAVA | LANG_VALA | LANG_ECMA },
+ { "add", CT_GETSET, LANG_CS },
+ { "alias", CT_USING, LANG_D },
+ { "align", CT_ALIGN, LANG_D },
+ { "alignof", CT_SIZEOF, LANG_CPP },
+ { "and", CT_SBOOL, LANG_CPP },
+ { "and_eq", CT_SASSIGN, LANG_CPP },
+ { "as", CT_AS, LANG_CS | LANG_VALA },
+ { "asm", CT_ASM, LANG_C | LANG_CPP | LANG_D },
+ { "asm", CT_PP_ASM, LANG_ALL | FLAG_PP },
+ { "assert", CT_ASSERT, LANG_JAVA },
+ { "assert", CT_FUNCTION, LANG_D | LANG_PAWN },
+ { "assert", CT_PP_ASSERT, LANG_PAWN | FLAG_PP },
+ { "auto", CT_TYPE, LANG_C | LANG_CPP | LANG_D },
+ { "base", CT_BASE, LANG_CS | LANG_VALA },
+ { "bit", CT_TYPE, LANG_D },
+ { "bitand", CT_ARITH, LANG_C | LANG_CPP },
+ { "bitor", CT_ARITH, LANG_C | LANG_CPP },
+ { "body", CT_BODY, LANG_D },
+ { "bool", CT_TYPE, LANG_C | LANG_CPP | LANG_CS | LANG_VALA },
+ { "boolean", CT_TYPE, LANG_JAVA | LANG_ECMA },
+ { "break", CT_BREAK, LANG_ALL },
+ { "byte", CT_TYPE, LANG_CS | LANG_D | LANG_JAVA | LANG_ECMA },
+ { "callback", CT_QUALIFIER, LANG_VALA },
+ { "case", CT_CASE, LANG_ALL },
+ { "cast", CT_D_CAST, LANG_D },
+ { "catch", CT_CATCH, LANG_CPP | LANG_CS | LANG_VALA | LANG_D | LANG_JAVA | LANG_ECMA },
+ { "cdouble", CT_TYPE, LANG_D },
+ { "cent", CT_TYPE, LANG_D },
+ { "cfloat", CT_TYPE, LANG_D },
+ { "char", CT_CHAR, LANG_PAWN },
+ { "char", CT_TYPE, LANG_ALLC },
+ { "checked", CT_QUALIFIER, LANG_CS },
+ { "class", CT_CLASS, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_VALA | LANG_ECMA },
+ { "compl", CT_ARITH, LANG_CPP },
+ { "const", CT_QUALIFIER, LANG_ALL },
+ { "const_cast", CT_TYPE_CAST, LANG_CPP },
+ { "constexpr", CT_QUALIFIER, LANG_CPP },
+ { "construct", CT_CONSTRUCT, LANG_VALA },
+ { "continue", CT_CONTINUE, LANG_ALL },
+ { "creal", CT_TYPE, LANG_D },
+ { "dchar", CT_TYPE, LANG_D },
+ { "debug", CT_DEBUG, LANG_D },
+ { "debugger", CT_DEBUGGER, LANG_ECMA },
+ { "decltype", CT_DECLTYPE, LANG_CPP },
+ { "default", CT_DEFAULT, LANG_ALL },
+ { "define", CT_PP_DEFINE, LANG_ALL | FLAG_PP },
+ { "defined", CT_DEFINED, LANG_PAWN },
+ { "defined", CT_PP_DEFINED, LANG_ALLC | FLAG_PP },
+ { "delegate", CT_DELEGATE, LANG_CS | LANG_VALA | LANG_D },
+ { "delete", CT_DELETE, LANG_CPP | LANG_D | LANG_ECMA | LANG_VALA },
+ { "deprecated", CT_QUALIFIER, LANG_D },
+ { "do", CT_DO, LANG_ALL },
+ { "double", CT_TYPE, LANG_ALLC },
+ { "dynamic_cast", CT_TYPE_CAST, LANG_CPP },
+ { "elif", CT_PP_ELSE, LANG_ALLC | FLAG_PP },
+ { "else", CT_ELSE, LANG_ALL },
+ { "else", CT_PP_ELSE, LANG_ALL | FLAG_PP },
+ { "elseif", CT_PP_ELSE, LANG_PAWN | FLAG_PP },
+ { "emit", CT_PP_EMIT, LANG_PAWN | FLAG_PP },
+ { "endif", CT_PP_ENDIF, LANG_ALL | FLAG_PP },
+ { "endinput", CT_PP_ENDINPUT, LANG_PAWN | FLAG_PP },
+ { "endregion", CT_PP_ENDREGION, LANG_ALL | FLAG_PP },
+ { "endscript", CT_PP_ENDINPUT, LANG_PAWN | FLAG_PP },
+ { "enum", CT_ENUM, LANG_ALL },
+ { "error", CT_PP_ERROR, LANG_PAWN | FLAG_PP },
+ { "event", CT_TYPE, LANG_CS },
+ { "exit", CT_FUNCTION, LANG_PAWN },
+ { "explicit", CT_QUALIFIER, LANG_CPP | LANG_CS },
+ { "export", CT_EXPORT, LANG_CPP | LANG_D | LANG_ECMA },
+ { "extends", CT_QUALIFIER, LANG_JAVA | LANG_ECMA },
+ { "extern", CT_EXTERN, LANG_C | LANG_CPP | LANG_OC | LANG_CS | LANG_D | LANG_VALA },
+ { "false", CT_WORD, LANG_ALL },
+ { "file", CT_PP_FILE, LANG_PAWN | FLAG_PP },
+ { "final", CT_QUALIFIER, LANG_CPP | LANG_D | LANG_ECMA },
+ { "finally", CT_FINALLY, LANG_D | LANG_CS | LANG_VALA | LANG_ECMA | LANG_JAVA },
+ { "fixed", CT_FIXED, LANG_CS },
+ { "flags", CT_TYPE, LANG_VALA },
+ { "float", CT_TYPE, LANG_ALLC },
+ { "for", CT_FOR, LANG_ALL },
+ { "foreach", CT_FOR, LANG_CS | LANG_D | LANG_VALA },
+ { "foreach_reverse", CT_FOR, LANG_D },
+ { "forward", CT_FORWARD, LANG_PAWN },
+ { "friend", CT_FRIEND, LANG_CPP },
+ { "function", CT_FUNCTION, LANG_D | LANG_ECMA },
+ { "get", CT_GETSET, LANG_CS | LANG_VALA },
+ { "goto", CT_GOTO, LANG_ALL },
+ { "idouble", CT_TYPE, LANG_D },
+ { "if", CT_IF, LANG_ALL },
+ { "if", CT_PP_IF, LANG_ALL | FLAG_PP },
+ { "ifdef", CT_PP_IF, LANG_ALLC | FLAG_PP },
+ { "ifloat", CT_TYPE, LANG_D },
+ { "ifndef", CT_PP_IF, LANG_ALLC | FLAG_PP },
+ { "implements", CT_QUALIFIER, LANG_JAVA | LANG_ECMA },
+ { "implicit", CT_QUALIFIER, LANG_CS },
+ { "import", CT_IMPORT, LANG_D | LANG_JAVA | LANG_ECMA },
+ { "import", CT_PP_INCLUDE, LANG_OC | FLAG_PP },
+ { "in", CT_IN, LANG_D | LANG_CS | LANG_VALA | LANG_ECMA | LANG_OC },
+ { "include", CT_PP_INCLUDE, LANG_C | LANG_CPP | LANG_OC | LANG_PAWN | FLAG_PP },
+ { "inline", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "inout", CT_QUALIFIER, LANG_D },
+ { "instanceof", CT_SIZEOF, LANG_JAVA | LANG_ECMA },
+ { "int", CT_TYPE, LANG_ALLC },
+ { "interface", CT_CLASS, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_VALA | LANG_ECMA },
+ { "internal", CT_QUALIFIER, LANG_CS },
+ { "invariant", CT_INVARIANT, LANG_D },
+ { "ireal", CT_TYPE, LANG_D },
+ { "is", CT_SCOMPARE, LANG_D | LANG_CS | LANG_VALA },
+ { "lazy", CT_LAZY, LANG_D },
+ { "line", CT_PP_LINE, LANG_PAWN | FLAG_PP },
+ { "lock", CT_LOCK, LANG_CS | LANG_VALA },
+ { "long", CT_TYPE, LANG_ALLC },
+ { "macro", CT_D_MACRO, LANG_D },
+ { "mixin", CT_CLASS, LANG_D }, // may need special handling
+ { "module", CT_D_MODULE, LANG_D },
+ { "mutable", CT_QUALIFIER, LANG_CPP },
+ { "namespace", CT_NAMESPACE, LANG_CPP | LANG_CS | LANG_VALA },
+ { "native", CT_NATIVE, LANG_PAWN },
+ { "native", CT_QUALIFIER, LANG_JAVA | LANG_ECMA },
+ { "new", CT_NEW, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_PAWN | LANG_VALA | LANG_ECMA },
+ { "noexcept", CT_NOEXCEPT, LANG_CPP },
+ { "nonnull", CT_TYPE, LANG_OC },
+ { "not", CT_SARITH, LANG_CPP },
+ { "not_eq", CT_SCOMPARE, LANG_CPP },
+// { "null", CT_TYPE, LANG_CS | LANG_D | LANG_JAVA | LANG_VALA },
+ { "null_resettable", CT_OC_PROPERTY_ATTR, LANG_OC },
+ { "null_unspecified", CT_TYPE, LANG_OC },
+ { "nullable", CT_TYPE, LANG_OC },
+ { "object", CT_TYPE, LANG_CS },
+ { "operator", CT_OPERATOR, LANG_CPP | LANG_CS | LANG_PAWN },
+ { "or", CT_SBOOL, LANG_CPP },
+ { "or_eq", CT_SASSIGN, LANG_CPP },
+ { "out", CT_QUALIFIER, LANG_CS | LANG_D | LANG_VALA },
+ { "override", CT_QUALIFIER, LANG_CPP | LANG_CS | LANG_D | LANG_VALA },
+ { "package", CT_ACCESS, LANG_D },
+ { "package", CT_PACKAGE, LANG_ECMA | LANG_JAVA },
+ { "params", CT_TYPE, LANG_CS | LANG_VALA },
+ { "pragma", CT_PP_PRAGMA, LANG_ALL | FLAG_PP },
+ { "private", CT_ACCESS, LANG_ALLC }, // not C
+ { "property", CT_PP_PROPERTY, LANG_CS | FLAG_PP },
+ { "protected", CT_ACCESS, LANG_ALLC }, // not C
+ { "public", CT_ACCESS, LANG_ALL }, // PAWN // not C
+ { "readonly", CT_QUALIFIER, LANG_CS },
+ { "real", CT_TYPE, LANG_D },
+ { "ref", CT_QUALIFIER, LANG_CS | LANG_VALA },
+ { "region", CT_PP_REGION, LANG_ALL | FLAG_PP },
+ { "register", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "reinterpret_cast", CT_TYPE_CAST, LANG_CPP },
+ { "remove", CT_GETSET, LANG_CS },
+ { "restrict", CT_QUALIFIER, LANG_C | LANG_CPP },
+ { "return", CT_RETURN, LANG_ALL },
+ { "sbyte", CT_TYPE, LANG_CS },
+ { "scope", CT_D_SCOPE, LANG_D },
+ { "sealed", CT_QUALIFIER, LANG_CS },
+ { "section", CT_PP_SECTION, LANG_PAWN | FLAG_PP },
+ { "self", CT_THIS, LANG_OC },
+ { "set", CT_GETSET, LANG_CS | LANG_VALA },
+ { "short", CT_TYPE, LANG_ALLC },
+ { "signal", CT_ACCESS, LANG_VALA },
+ { "signals", CT_ACCESS, LANG_CPP },
+ { "signed", CT_TYPE, LANG_C | LANG_CPP },
+ { "size_t", CT_TYPE, LANG_ALLC },
+ { "sizeof", CT_SIZEOF, LANG_C | LANG_CPP | LANG_CS | LANG_VALA | LANG_PAWN },
+ { "sleep", CT_SIZEOF, LANG_PAWN },
+ { "stackalloc", CT_NEW, LANG_CS },
+ { "state", CT_STATE, LANG_PAWN },
+ { "static", CT_QUALIFIER, LANG_ALL },
+ { "static_cast", CT_TYPE_CAST, LANG_CPP },
+ { "stock", CT_STOCK, LANG_PAWN },
+ { "strictfp", CT_QUALIFIER, LANG_JAVA },
+ { "string", CT_TYPE, LANG_CS | LANG_VALA },
+ { "struct", CT_STRUCT, LANG_C | LANG_CPP | LANG_OC | LANG_CS | LANG_D | LANG_VALA },
+ { "super", CT_SUPER, LANG_D | LANG_JAVA | LANG_ECMA },
+ { "switch", CT_SWITCH, LANG_ALL },
+ { "synchronized", CT_QUALIFIER, LANG_D | LANG_ECMA },
+ { "synchronized", CT_SYNCHRONIZED, LANG_JAVA },
+ { "tagof", CT_TAGOF, LANG_PAWN },
+ { "template", CT_TEMPLATE, LANG_CPP | LANG_D },
+ { "this", CT_THIS, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_VALA | LANG_ECMA },
+ { "throw", CT_THROW, LANG_CPP | LANG_CS | LANG_VALA | LANG_D | LANG_JAVA | LANG_ECMA },
+ { "throws", CT_QUALIFIER, LANG_JAVA | LANG_ECMA | LANG_VALA },
+ { "transient", CT_QUALIFIER, LANG_JAVA | LANG_ECMA },
+ { "true", CT_WORD, LANG_ALL },
+ { "try", CT_TRY, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_ECMA | LANG_VALA },
+ { "tryinclude", CT_PP_INCLUDE, LANG_PAWN | FLAG_PP },
+ { "typedef", CT_TYPEDEF, LANG_C | LANG_CPP | LANG_OC | LANG_D },
+ { "typeid", CT_SIZEOF, LANG_CPP | LANG_D },
+ { "typename", CT_TYPENAME, LANG_CPP },
+ { "typeof", CT_DECLTYPE, LANG_C | LANG_CPP },
+ { "typeof", CT_SIZEOF, LANG_CS | LANG_D | LANG_VALA | LANG_ECMA },
+ { "ubyte", CT_TYPE, LANG_D },
+ { "ucent", CT_TYPE, LANG_D },
+ { "uint", CT_TYPE, LANG_CS | LANG_VALA | LANG_D },
+ { "ulong", CT_TYPE, LANG_CS | LANG_VALA | LANG_D },
+ { "unchecked", CT_QUALIFIER, LANG_CS },
+ { "undef", CT_PP_UNDEF, LANG_ALL | FLAG_PP },
+ { "union", CT_UNION, LANG_C | LANG_CPP | LANG_D },
+ { "unittest", CT_UNITTEST, LANG_D },
+ { "unsafe", CT_UNSAFE, LANG_CS },
+ { "unsafe_unretained", CT_QUALIFIER, LANG_OC },
+ { "unsigned", CT_TYPE, LANG_C | LANG_CPP },
+ { "ushort", CT_TYPE, LANG_CS | LANG_VALA | LANG_D },
+ { "using", CT_USING, LANG_CPP | LANG_CS | LANG_VALA },
+ { "var", CT_TYPE, LANG_VALA | LANG_ECMA },
+ { "version", CT_D_VERSION, LANG_D },
+ { "virtual", CT_QUALIFIER, LANG_CPP | LANG_CS | LANG_VALA },
+ { "void", CT_TYPE, LANG_ALLC },
+ { "volatile", CT_QUALIFIER, LANG_C | LANG_CPP | LANG_CS | LANG_JAVA | LANG_ECMA },
+ { "volatile", CT_VOLATILE, LANG_D },
+ { "wchar", CT_TYPE, LANG_D },
+ { "wchar_t", CT_TYPE, LANG_C | LANG_CPP },
+ { "weak", CT_QUALIFIER, LANG_VALA },
+ { "when", CT_WHEN, LANG_CS },
+ { "where", CT_WHERE, LANG_CS },
+ { "while", CT_WHILE, LANG_ALL },
+ { "with", CT_D_WITH, LANG_D | LANG_ECMA },
+ { "xor", CT_SARITH, LANG_CPP },
+ { "xor_eq", CT_SASSIGN, LANG_CPP },
+};
+
+
+// Issue #3353
+void init_keywords_for_language()
+{
+ unsigned int local_flags = cpd.lang_flags;
+ size_t keywords_count = ARRAY_SIZE(keywords);
+
+ language_count = 0;
+
+ for (size_t idx = 0; idx < keywords_count; idx++)
+ {
+ chunk_tag_t *tag = &keywords[idx];
+
+ if ((tag->lang_flags & local_flags) != 0)
+ {
+ // for debugging only
+ // fprintf(stderr, "%s(%d): %zu Keyword: '%s', type is '%s'\n",
+ // __func__, __LINE__, idx, tag->tag, get_token_name(tag->type));
+ keyword_for_lang[language_count].tag = tag->tag;
+ keyword_for_lang[language_count].type = tag->type;
+ keyword_for_lang[language_count].lang_flags = tag->lang_flags;
+ language_count++;
+ }
+ }
+
+ LOG_FMT(LDYNKW, "%s(%d): Number of Keywords for language %d: '%zu'\n",
+ __func__, __LINE__, local_flags, language_count);
+} // init_keywords_for_language
+
+
+static int kw_compare(const void *p1, const void *p2)
+{
+ const chunk_tag_t *t1 = static_cast<const chunk_tag_t *>(p1);
+ const chunk_tag_t *t2 = static_cast<const chunk_tag_t *>(p2);
+
+ return(strcmp(t1->tag, t2->tag));
+} // kw_compare
+
+
+bool keywords_are_sorted(void)
+{
+ size_t keywords_count = ARRAY_SIZE(keywords);
+
+ for (size_t idx = 1; idx < keywords_count; idx++)
+ {
+ if (kw_compare(&keywords[idx - 1], &keywords[idx]) > 0)
+ {
+ fprintf(stderr, "%s: bad sort order at idx %d, words '%s' and '%s'\n",
+ __func__, (int)idx - 1, keywords[idx - 1].tag, keywords[idx].tag);
+ // coveralls will always complain.
+ // these lines are only needed for the developper.
+ log_flush(true);
+ cpd.error_count++;
+ return(false);
+ }
+ }
+
+ return(true);
+} // keywords_are_sorted
+
+
+void add_keyword(const std::string &tag, E_Token type)
+{
+ // See if the keyword has already been added
+ dkwmap::iterator it = dkwm.find(tag);
+
+ if (it != dkwm.end())
+ {
+ LOG_FMT(LDYNKW, "%s(%d): changed '%s' to '%s'\n",
+ __func__, __LINE__, tag.c_str(), get_token_name(type));
+ (*it).second = type;
+ return;
+ }
+ // Insert the keyword
+ dkwm.insert(dkwmap::value_type(tag, type));
+ LOG_FMT(LDYNKW, "%s(%d): added '%s' as '%s'\n",
+ __func__, __LINE__, tag.c_str(), get_token_name(type));
+} // add_keyword
+
+
+static const chunk_tag_t *kw_static_first(const chunk_tag_t *tag)
+{
+ const chunk_tag_t *prev = tag - 1;
+
+ // TODO: avoid pointer arithmetics
+ // loop over static keyword array
+ while ( prev >= &keyword_for_lang[0] // not at beginning of keyword array
+ && strcmp(prev->tag, tag->tag) == 0) // tags match
+ {
+ tag = prev;
+ prev--;
+ }
+ return(tag);
+} // kw_static_first
+
+
+static const chunk_tag_t *kw_static_match(bool orig_list, const chunk_tag_t *tag, int lang_flags)
+{
+ bool in_pp = ( cpd.in_preproc != CT_NONE
+ && cpd.in_preproc != CT_PP_DEFINE);
+
+ for (const chunk_tag_t *iter = kw_static_first(tag);
+ (orig_list) ? (iter < &keywords[ARRAY_SIZE(keywords)]) : (iter < &keyword_for_lang[language_count]);
+ iter++)
+ {
+ bool pp_iter = (iter->lang_flags & FLAG_PP) != 0; // forcing value to bool
+
+ if ( (strcmp(iter->tag, tag->tag) == 0)
+ && language_is_set(iter->lang_flags)
+ && (lang_flags & iter->lang_flags)
+ && in_pp == pp_iter)
+ {
+ return(iter);
+ }
+ }
+
+ return(nullptr);
+} // kw_static_match
+
+
+E_Token find_keyword_type(const char *word, size_t len)
+{
+ if (len <= 0)
+ {
+ return(CT_NONE);
+ }
+ // check the dynamic word list first
+ string ss(word, len);
+ dkwmap::iterator it = dkwm.find(ss);
+
+ if (it != dkwm.end())
+ {
+ return((*it).second);
+ }
+ chunk_tag_t key;
+
+ key.tag = ss.c_str();
+
+ // check the static word list
+ const chunk_tag_t *p_ret = static_cast<const chunk_tag_t *>(
+ bsearch(&key, keyword_for_lang, language_count, sizeof(keyword_for_lang[0]), kw_compare));
+
+ if (p_ret != nullptr)
+ {
+ if ( strcmp(p_ret->tag, "__pragma") == 0
+ || strcmp(p_ret->tag, "_Pragma") == 0)
+ {
+ cpd.in_preproc = CT_PREPROC;
+ }
+ p_ret = kw_static_match(false, p_ret, cpd.lang_flags);
+ }
+ return((p_ret != nullptr) ? p_ret->type : CT_WORD);
+} // find_keyword_type
+
+
+int load_keyword_file(const char *filename)
+{
+ FILE *pf = fopen(filename, "r");
+
+ if (pf == nullptr)
+ {
+ LOG_FMT(LERR, "%s: fopen(%s) failed: %s (%d)\n",
+ __func__, filename, strerror(errno), errno);
+ cpd.error_count++;
+ return(EX_IOERR);
+ }
+ const int max_line_length = 256;
+ const int max_arg_count = 2;
+
+ // maximal length of a line in the file
+ char buf[max_line_length];
+ char *args[max_arg_count];
+ size_t line_no = 0;
+
+ // read file line by line
+ while (fgets(buf, max_line_length, pf) != nullptr)
+ {
+ line_no++;
+
+ // remove comments after '#' sign
+ char *ptr;
+
+ if ((ptr = strchr(buf, '#')) != nullptr)
+ {
+ *ptr = 0; // set string end where comment begins
+ }
+ size_t argc = Args::SplitLine(buf, args, max_arg_count);
+
+ if (argc > 0)
+ {
+ if ( argc == 1
+ && CharTable::IsKw1(*args[0]))
+ {
+ add_keyword(args[0], CT_TYPE);
+ }
+ else
+ {
+ LOG_FMT(LWARN, "%s:%zu Invalid line (starts with '%s')\n",
+ filename, line_no, args[0]);
+ cpd.error_count++;
+ }
+ }
+ else
+ {
+ continue; // the line is empty
+ }
+ }
+ fclose(pf);
+ return(EX_OK);
+} // load_keyword_file
+
+
+void print_custom_keywords(FILE *pfile)
+{
+ for (const auto &keyword_pair : dkwm)
+ {
+ E_Token tt = keyword_pair.second;
+
+ if (tt == CT_TYPE)
+ {
+ fprintf(pfile, "custom type %*.s%s\n",
+ uncrustify::limits::MAX_OPTION_NAME_LEN - 10, " ",
+ keyword_pair.first.c_str());
+ }
+ else if (tt == CT_MACRO_OPEN)
+ {
+ fprintf(pfile, "macro-open %*.s%s\n",
+ uncrustify::limits::MAX_OPTION_NAME_LEN - 11, " ",
+ keyword_pair.first.c_str());
+ }
+ else if (tt == CT_MACRO_CLOSE)
+ {
+ fprintf(pfile, "macro-close %*.s%s\n",
+ uncrustify::limits::MAX_OPTION_NAME_LEN - 12, " ",
+ keyword_pair.first.c_str());
+ }
+ else if (tt == CT_MACRO_ELSE)
+ {
+ fprintf(pfile, "macro-else %*.s%s\n",
+ uncrustify::limits::MAX_OPTION_NAME_LEN - 11, " ",
+ keyword_pair.first.c_str());
+ }
+ else
+ {
+ const char *tn = get_token_name(tt);
+
+ fprintf(pfile, "set %s %*.s%s\n",
+ tn,
+ uncrustify::limits::MAX_OPTION_NAME_LEN - (4 + static_cast<int>(strlen(tn))),
+ " ", keyword_pair.first.c_str());
+ }
+ }
+} // print_custom_keywords
+
+
+void clear_keyword_file(void)
+{
+ dkwm.clear();
+} // clear_keyword_file
+
+
+pattern_class_e get_token_pattern_class(E_Token tok)
+{
+ // TODO: instead of this switch better assign the pattern class to each statement
+ switch (tok)
+ {
+ case CT_IF:
+ case CT_ELSEIF:
+ case CT_SWITCH:
+ case CT_FOR:
+ case CT_WHILE:
+ case CT_SYNCHRONIZED:
+ case CT_USING_STMT:
+ case CT_LOCK:
+ case CT_D_WITH:
+ case CT_D_VERSION_IF:
+ case CT_D_SCOPE_IF:
+ return(pattern_class_e::PBRACED);
+
+ case CT_ELSE:
+ return(pattern_class_e::ELSE);
+
+ case CT_DO:
+ case CT_TRY:
+ case CT_FINALLY:
+ case CT_BODY:
+ case CT_UNITTEST:
+ case CT_UNSAFE:
+ case CT_VOLATILE:
+ case CT_GETSET:
+ return(pattern_class_e::BRACED);
+
+ case CT_CATCH:
+ case CT_D_VERSION:
+ case CT_DEBUG:
+ return(pattern_class_e::OPBRACED);
+
+ case CT_NAMESPACE:
+ return(pattern_class_e::VBRACED);
+
+ case CT_WHILE_OF_DO:
+ return(pattern_class_e::PAREN);
+
+ case CT_INVARIANT:
+ return(pattern_class_e::OPPAREN);
+
+ default:
+ return(pattern_class_e::NONE);
+ } // switch
+} // get_token_pattern_class
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.h
new file mode 100644
index 00000000..95c41aad
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/keywords.h
@@ -0,0 +1,85 @@
+/**
+ * @file keywords.h
+ * prototypes for keywords.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef KEYWORDS_H_INCLUDED
+#define KEYWORDS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+/**
+ * Initializes keywords table for a given language.
+ *
+ * Let us have a look on the problem is caused by the tokens "in" and "out",
+ * used in the file "Issue_3353.h" under.
+ * The strings representing the tokens ("in" and "out"), are found in the
+ * original table: static chunk_tag_t keywords[] because they are used by
+ * other languages. They are tokenized as CT_IN and CT_OUT.
+ * The correct tokenization is CT_FUNC_VAR.
+ *
+ * It is necessary to create (at run time) a new table with all the keywords
+ * proper to the used language.
+ *
+ */
+
+/**
+ * The file
+ * "Issue_3353.h"
+ * struct A {
+ * void (*in)(
+ * void);
+ * void (*out)(
+ * void);
+ * };
+ */
+void init_keywords_for_language(void);
+
+/**
+ * Loads the dynamic keywords from a file
+ *
+ * @param filename The path to the file to load
+ *
+ * @retval EX_OK successfully read keywords from file
+ * @retval EX_IOERR reading keywords file failed
+ */
+int load_keyword_file(const char *filename);
+
+
+/**
+ * Search first the dynamic and then the static table for a matching keyword
+ *
+ * @param word Pointer to the text -- NOT zero terminated
+ * @param len The length of the text
+ *
+ * @return CT_WORD (no match) or the keyword token
+ */
+E_Token find_keyword_type(const char *word, size_t len);
+
+
+/**
+ * Adds a keyword to the list of dynamic keywords
+ *
+ * @param tag The tag (string) must be zero terminated
+ * @param type The type, usually CT_TYPE
+ */
+void add_keyword(const std::string &tag, E_Token type);
+
+
+void print_custom_keywords(FILE *pfile);
+
+
+void clear_keyword_file(void);
+
+
+//! Returns the pattern that the keyword needs based on the token
+pattern_class_e get_token_pattern_class(E_Token tok);
+
+
+bool keywords_are_sorted(void);
+
+
+#endif /* KEYWORDS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.cpp
new file mode 100644
index 00000000..77831f55
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.cpp
@@ -0,0 +1,540 @@
+/**
+ * @file lang_pawn.cpp
+ * Special functions for pawn stuff
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "lang_pawn.h"
+
+#include "prototypes.h"
+
+using namespace uncrustify;
+
+
+/**
+ * Checks to see if a token continues a statement to the next line.
+ * We need to check for 'open' braces/paren/etc because the level doesn't
+ * change until the token after the open.
+ */
+static bool pawn_continued(Chunk *pc, size_t br_level);
+
+
+/**
+ * Functions prototypes and definitions can only appear in level 0.
+ *
+ * Function prototypes start with "native", "forward", or are just a function
+ * with a trailing semicolon instead of a open brace (or something else)
+ *
+ * somefunc(params) <-- def
+ * stock somefunc(params) <-- def
+ * somefunc(params); <-- proto
+ * forward somefunc(params) <-- proto
+ * native somefunc[rect](params) <-- proto
+ *
+ * Functions start with 'stock', 'static', 'public', or '@' (on level 0)
+ *
+ * Variable definitions start with 'stock', 'static', 'new', or 'public'.
+ */
+static Chunk *pawn_process_line(Chunk *start);
+
+
+//! We are on a level 0 function proto of def
+static Chunk *pawn_mark_function0(Chunk *start, Chunk *fcn);
+
+
+/**
+ * follows a variable definition at level 0 until the end.
+ * Adds a semicolon at the end, if needed.
+ */
+static Chunk *pawn_process_variable(Chunk *start);
+
+
+static Chunk *pawn_process_func_def(Chunk *pc);
+
+
+Chunk *pawn_add_vsemi_after(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( chunk_is_token(pc, CT_VSEMICOLON)
+ || chunk_is_token(pc, CT_SEMICOLON))
+ {
+ return(pc);
+ }
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ Chunk *next = pc->GetNextNc();
+
+ if ( next->IsNotNullChunk()
+ && ( chunk_is_token(next, CT_VSEMICOLON)
+ || chunk_is_token(next, CT_SEMICOLON)))
+ {
+ return(pc);
+ }
+ Chunk chunk = *pc;
+
+ set_chunk_type(&chunk, CT_VSEMICOLON);
+ set_chunk_parent(&chunk, CT_NONE);
+ chunk.str = options::mod_pawn_semicolon() ? ";" : "";
+ chunk.column += pc->Len();
+
+ LOG_FMT(LPVSEMI, "%s: Added VSEMI on line %zu, prev='%s' [%s]\n",
+ __func__, pc->orig_line, pc->Text(),
+ get_token_name(pc->type));
+
+ return(chunk_add_after(&chunk, pc));
+}
+
+
+void pawn_scrub_vsemi(void)
+{
+ constexpr static auto LCURRENT = LPVSEMI;
+
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_pawn_semicolon");
+
+ if (!options::mod_pawn_semicolon())
+ {
+ return;
+ }
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->type != CT_VSEMICOLON)
+ {
+ continue;
+ }
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if (chunk_is_token(prev, CT_BRACE_CLOSE))
+ {
+ if ( get_chunk_parent_type(prev) == CT_IF
+ || get_chunk_parent_type(prev) == CT_ELSE
+ || get_chunk_parent_type(prev) == CT_SWITCH
+ || get_chunk_parent_type(prev) == CT_CASE
+ || get_chunk_parent_type(prev) == CT_WHILE_OF_DO)
+ {
+ pc->str.clear();
+ }
+ }
+ }
+}
+
+
+static bool pawn_continued(Chunk *pc, size_t br_level)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return(false);
+ }
+
+ if ( pc->level > br_level
+ || chunk_is_token(pc, CT_ARITH)
+ || chunk_is_token(pc, CT_SHIFT)
+ || chunk_is_token(pc, CT_CARET)
+ || chunk_is_token(pc, CT_QUESTION)
+ || chunk_is_token(pc, CT_BOOL)
+ || chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_COMPARE)
+ || chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSE)
+ || chunk_is_token(pc, CT_DO)
+ || chunk_is_token(pc, CT_SWITCH)
+ || chunk_is_token(pc, CT_WHILE)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSE
+ || get_chunk_parent_type(pc) == CT_ELSEIF
+ || get_chunk_parent_type(pc) == CT_DO
+ || get_chunk_parent_type(pc) == CT_FOR
+ || get_chunk_parent_type(pc) == CT_SWITCH
+ || get_chunk_parent_type(pc) == CT_WHILE
+ || get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || get_chunk_parent_type(pc) == CT_ENUM
+ || pc->flags.test_any(PCF_IN_ENUM | PCF_IN_STRUCT)
+ || chunk_is_str(pc, ":")
+ || chunk_is_str(pc, "+")
+ || chunk_is_str(pc, "-"))
+ {
+ return(true);
+ }
+ return(false);
+} // pawn_continued
+
+
+void pawn_prescan(void)
+{
+ LOG_FUNC_ENTRY();
+
+ /*
+ * Start at the beginning and step through the entire file, and clean up
+ * any questionable stuff
+ */
+ bool did_nl = true;
+ Chunk *pc = Chunk::GetHead();
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ if ( did_nl
+ && pc->type != CT_PREPROC
+ && !chunk_is_newline(pc)
+ && pc->level == 0)
+ {
+ // pc now points to the start of a line
+ pc = pawn_process_line(pc);
+ }
+
+ // note that continued lines are ignored
+ if ( pc != nullptr
+ && pc->IsNotNullChunk())
+ {
+ did_nl = (chunk_is_token(pc, CT_NEWLINE));
+ }
+ pc = pc->GetNextNc();
+ }
+}
+
+
+static Chunk *pawn_process_line(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ //LOG_FMT(LSYS, "%s: %d - %s\n", __func__,
+ // start->orig_line, start->Text());
+
+ if ( chunk_is_token(start, CT_NEW)
+ || chunk_is_str(start, "const"))
+ {
+ return(pawn_process_variable(start));
+ }
+ // if a open paren is found before an assign, then this is a function
+ Chunk *fcn = nullptr;
+
+ if (chunk_is_token(start, CT_WORD))
+ {
+ fcn = start;
+ }
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ if (start != nullptr)
+ {
+ pc = start;
+ }
+
+ while ( ((pc = pc->GetNextNc())->IsNotNullChunk())
+ && !chunk_is_str(pc, "(")
+ && pc->type != CT_ASSIGN
+ && pc->type != CT_NEWLINE)
+ {
+ if ( pc->level == 0
+ && ( chunk_is_token(pc, CT_FUNCTION)
+ || chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_OPERATOR_VAL)))
+ {
+ fcn = pc;
+ }
+ }
+
+ if (pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ return(pawn_process_variable(pc));
+ }
+ }
+
+ if (fcn != nullptr)
+ {
+ //LOG_FMT(LSYS, "FUNCTION: %s\n", fcn->Text());
+ return(pawn_mark_function0(start, fcn));
+ }
+
+ if (chunk_is_token(start, CT_ENUM))
+ {
+ pc = start->GetNextType(CT_BRACE_CLOSE, start->level);
+ return(pc);
+ }
+ //LOG_FMT(LSYS, "%s: Don't understand line %d, starting with '%s' [%s]\n",
+ // __func__, start->orig_line, start->Text(), get_token_name(start->type));
+ return(start);
+} // pawn_process_line
+
+
+static Chunk *pawn_process_variable(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ if (start != nullptr)
+ {
+ pc = start;
+ }
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ while ((pc = pc->GetNextNc())->IsNotNullChunk())
+ {
+ if ( chunk_is_token(pc, CT_NEWLINE)
+ && prev->IsNotNullChunk()
+ && !pawn_continued(prev, start->level))
+ {
+ if ( prev->type != CT_VSEMICOLON
+ && prev->type != CT_SEMICOLON)
+ {
+ pawn_add_vsemi_after(prev);
+ }
+ break;
+ }
+ prev = pc;
+ }
+ return(pc);
+}
+
+
+void pawn_add_virtual_semicolons(void)
+{
+ LOG_FUNC_ENTRY();
+
+ // Add Pawn virtual semicolons
+ if (language_is_set(LANG_PAWN))
+ {
+ Chunk *prev = Chunk::NullChunkPtr;
+ Chunk *pc = Chunk::GetHead();
+
+ while ((pc = pc->GetNext())->IsNotNullChunk())
+ {
+ if ( !pc->IsComment()
+ && !chunk_is_newline(pc)
+ && pc->type != CT_VBRACE_CLOSE
+ && pc->type != CT_VBRACE_OPEN)
+ {
+ prev = pc;
+ }
+
+ if ( prev->IsNullChunk()
+ || ( pc->type != CT_NEWLINE
+ && pc->type != CT_BRACE_CLOSE
+ && pc->type != CT_VBRACE_CLOSE))
+ {
+ continue;
+ }
+
+ // we just hit a newline and we have a previous token
+ if ( !prev->flags.test(PCF_IN_PREPROC)
+ && !prev->flags.test_any(PCF_IN_ENUM | PCF_IN_STRUCT)
+ && prev->type != CT_VSEMICOLON
+ && prev->type != CT_SEMICOLON
+ && !pawn_continued(prev, prev->brace_level))
+ {
+ pawn_add_vsemi_after(prev);
+ prev = Chunk::NullChunkPtr;
+ }
+ }
+ }
+} // pawn_add_virtual_semicolons
+
+
+static Chunk *pawn_mark_function0(Chunk *start, Chunk *fcn)
+{
+ LOG_FUNC_ENTRY();
+
+ // handle prototypes
+ if (start == fcn)
+ {
+ Chunk *last = fcn->GetNextType(CT_PAREN_CLOSE, fcn->level)->GetNext();
+
+ if (chunk_is_token(last, CT_SEMICOLON))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' proto due to semicolon\n",
+ __func__, fcn->orig_line, fcn->Text());
+ set_chunk_type(fcn, CT_FUNC_PROTO);
+ return(last);
+ }
+ }
+ else
+ {
+ if ( chunk_is_token(start, CT_FORWARD)
+ || chunk_is_token(start, CT_NATIVE))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' [%s] proto due to %s\n",
+ __func__, fcn->orig_line, fcn->Text(),
+ get_token_name(fcn->type),
+ get_token_name(start->type));
+ set_chunk_type(fcn, CT_FUNC_PROTO);
+ return(fcn->GetNextNc());
+ }
+ }
+ // Not a prototype, so it must be a function def
+ return(pawn_process_func_def(fcn));
+}
+
+
+static Chunk *pawn_process_func_def(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ // We are on a function definition
+ set_chunk_type(pc, CT_FUNC_DEF);
+
+ LOG_FMT(LPFUNC, "%s: %zu:%zu %s\n",
+ __func__, pc->orig_line, pc->orig_col, pc->Text());
+
+ /*
+ * If we don't have a brace open right after the close fparen, then
+ * we need to add virtual braces around the function body.
+ */
+ Chunk *clp = pc->GetNextString(")", 1, 0);
+ Chunk *last = clp->GetNextNcNnl();
+
+ if (last->IsNotNullChunk())
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] last is '%s' [%s]\n",
+ __func__, last->orig_line, last->Text(), get_token_name(last->type));
+ }
+
+ // See if there is a state clause after the function
+ if ( last->IsNotNullChunk()
+ && chunk_is_str(last, "<"))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' has state angle open %s\n",
+ __func__, pc->orig_line, pc->Text(), get_token_name(last->type));
+
+ set_chunk_type(last, CT_ANGLE_OPEN);
+ set_chunk_parent(last, CT_FUNC_DEF);
+
+ while ( ((last = last->GetNext())->IsNotNullChunk())
+ && !chunk_is_str(last, ">"))
+ {
+ // do nothing just search, TODO: use search_chunk
+ }
+
+ if (last->IsNotNullChunk())
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' has state angle close %s\n",
+ __func__, pc->orig_line, pc->Text(), get_token_name(last->type));
+ set_chunk_type(last, CT_ANGLE_CLOSE);
+ set_chunk_parent(last, CT_FUNC_DEF);
+ }
+ last = last->GetNextNcNnl();
+ }
+
+ if (last->IsNullChunk())
+ {
+ return(last);
+ }
+
+ if (chunk_is_token(last, CT_BRACE_OPEN))
+ {
+ set_chunk_parent(last, CT_FUNC_DEF);
+ last = last->GetNextType(CT_BRACE_CLOSE, last->level);
+
+ if (last->IsNotNullChunk())
+ {
+ set_chunk_parent(last, CT_FUNC_DEF);
+ }
+ }
+ else
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' fdef: expected brace open: %s\n",
+ __func__, pc->orig_line, pc->Text(), get_token_name(last->type));
+
+ // do not insert a vbrace before a preproc
+ if (last->flags.test(PCF_IN_PREPROC))
+ {
+ return(last);
+ }
+ Chunk chunk = *last;
+ chunk.str.clear();
+ set_chunk_type(&chunk, CT_VBRACE_OPEN);
+ set_chunk_parent(&chunk, CT_FUNC_DEF);
+
+ Chunk *prev = chunk_add_before(&chunk, last);
+ last = prev;
+
+ // find the next newline at level 0
+ prev = prev->GetNextNcNnl();
+
+ do
+ {
+ LOG_FMT(LPFUNC, "%s:%zu] check %s, level %zu\n",
+ __func__, prev->orig_line, get_token_name(prev->type), prev->level);
+
+ if ( chunk_is_token(prev, CT_NEWLINE)
+ && prev->level == 0)
+ {
+ Chunk *next = prev->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && next->type != CT_ELSE
+ && next->type != CT_WHILE_OF_DO)
+ {
+ break;
+ }
+ }
+ prev->level++;
+ prev->brace_level++;
+ last = prev;
+ } while ((prev = prev->GetNext())->IsNotNullChunk());
+
+ if ( last != nullptr
+ && last->IsNotNullChunk())
+ {
+ LOG_FMT(LPFUNC, "%s:%zu] ended on %s, level %zu\n",
+ __func__, last->orig_line, get_token_name(last->type), last->level);
+ }
+ chunk = *last;
+ chunk.str.clear();
+ set_chunk_type(&chunk, CT_VBRACE_CLOSE);
+ set_chunk_parent(&chunk, CT_FUNC_DEF);
+ chunk.column += last->Len();
+ chunk.level = 0;
+ chunk.brace_level = 0;
+ last = chunk_add_after(&chunk, last);
+ }
+ return(last);
+} // pawn_process_func_def
+
+
+Chunk *pawn_check_vsemicolon(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ // Grab the open VBrace
+ Chunk *vb_open = pc->GetPrevType(CT_VBRACE_OPEN, -1);
+
+ /*
+ * Grab the item before the newline
+ * Don't do anything if:
+ * - the only thing previous is the V-Brace open
+ * - in a preprocessor
+ * - level > (vb_open->level + 1) -- ie, in () or []
+ * - it is something that needs a continuation
+ * + arith, assign, bool, comma, compare
+ */
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if ( prev->IsNullChunk()
+ || prev == vb_open
+ || prev->flags.test(PCF_IN_PREPROC)
+ || pawn_continued(prev, vb_open->level + 1))
+ {
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LPVSEMI, "%s: no VSEMI on line %zu, prev='%s' [%s]\n",
+ __func__, prev->orig_line, prev->Text(), get_token_name(prev->type));
+ }
+ return(pc);
+ }
+ return(pawn_add_vsemi_after(prev));
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.h
new file mode 100644
index 00000000..9e2d7832
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/lang_pawn.h
@@ -0,0 +1,49 @@
+/**
+ * @file long_pawn.h
+ * prototypes for long_pawn.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef LONG_PAWN_H_INCLUDED
+#define LONG_PAWN_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * Does a scan of level 0 BEFORE stuff in combine.cpp is called.
+ * At this point, VSemis have been added only in VBraces.
+ * Otherwise, all level info is correct, except for unbraced functions.
+ *
+ * We are looking for unbraced functions.
+ */
+void pawn_prescan(void);
+
+
+void pawn_add_virtual_semicolons(void);
+
+
+/**
+ * We are in a virtual brace and hit a newline.
+ * If this should end the vbrace, then insert a VSEMICOLON and return that.
+ *
+ * @param pc The newline (CT_NEWLINE)
+ *
+ * @return Either the newline or the newly inserted virtual semicolon
+ */
+Chunk *pawn_check_vsemicolon(Chunk *pc);
+
+
+/**
+ * Turns certain virtual semicolons invisible.
+ * - after a close brace with a parent of switch, case, else, if
+ */
+void pawn_scrub_vsemi(void);
+
+
+//! add a semicolon after ...
+Chunk *pawn_add_vsemi_after(Chunk *pc);
+
+
+#endif /* LONG_PAWN_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.cpp
new file mode 100644
index 00000000..77e577f4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.cpp
@@ -0,0 +1,17 @@
+/**
+ * @file language_tools.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "language_tools.h"
+
+
+/**
+ * check if the language(s) is/are set
+ */
+bool language_is_set(size_t lang)
+{
+ return((cpd.lang_flags & lang) != 0);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.h
new file mode 100644
index 00000000..5f57c3f1
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/language_tools.h
@@ -0,0 +1,18 @@
+/**
+ * @file language_tools.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+#ifndef LANGUAGE_TOOLS_H_INCLUDED
+#define LANGUAGE_TOOLS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * check if the language(s) is/are set
+ */
+bool language_is_set(size_t lang);
+
+#endif /* LANGUAGE_TOOLS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_levels.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_levels.h
new file mode 100644
index 00000000..d809514a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_levels.h
@@ -0,0 +1,138 @@
+/**
+ * @file log_levels.h
+ *
+ * Enum for log levels.
+ * Use these for the log severities in LOG_FMT(), etc.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel October 2015- 2021
+ * @license GPL v2+
+ */
+
+#ifndef LOG_LEVELS_H_INCLUDED
+#define LOG_LEVELS_H_INCLUDED
+
+/**
+ * list of available log levels
+ *
+ * The user defines which log level is active using the
+ * -L or -log option.
+ * use -L A to set all the levels
+ * All messages which have a level that is active will be stored to the log
+ * file.
+ * All other log messages will be discarded.
+ * Different parts of the software use different log levels.
+ * This allows to log only operations of a specific operation.
+ * This eases debugging.
+ * To get all log messages use the option -La
+ * By default only system messages (level=LSYS) are logged.
+ */
+enum log_sev_t
+{
+ LSYS = 0, //! system messages
+ LERR = 1, //! error messages
+ LWARN = 2, //! warnings
+ LNOTE = 3, //! user notifications
+ LINFO = 4, //! user informations
+ LDATA = 5, //! data logging
+
+ LFILELIST = 8, //! Files in the file list file
+ LLINEENDS = 9, //! Show which line endings are used
+ LCASTS = 10, //! align casts
+ LALBR = 11, //! align braces
+ LALTD = 12, //! Align Typedef
+ LALPP = 13, //! align #define
+ LALPROTO = 14, //! align prototype
+ LALNLC = 15, //! align backslash-newline
+ LALTC = 16, //! align trailing comments
+ LALADD = 17, //! align add
+ LALASS = 18, //! align assign
+ LFVD = 19, //! fix_var_def
+ LFVD2 = 20, //! fix_var_def-2
+ LINDENT = 21, //! indent_text
+ LINDENT2 = 22, //! indent_text tab level
+ LINDPSE = 23, //! indent_text stack
+ LINDPC = 24, //! indent play-by-play
+ LNEWLINE = 25, //! newlines
+ LPF = 26, //! Parse Frame
+ LSTMT = 27, //! Marking statements/expressions
+ LTOK = 28, //! Tokenize
+ LALRC = 29, //! align right comment
+ LCMTIND = 30, //! Comment Indent
+ LINDLINE = 31, //! indent line
+ LSIB = 32, //! Scan IB
+ LRETURN = 33, //! add/remove parens for return
+ LBRDEL = 34, //! brace removal
+ LFCN = 35, //! function detection
+ LFCNP = 36, //! function parameters
+ LPCU = 37, //! parse cleanup
+ LDYNKW = 38, //! dynamic keywords
+ LOUTIND = 39, //! output indent
+ LBCSAFTER = 40, //! Brace cleanup stack - after each token
+ LBCSPOP = 41, //! Brace cleanup stack - log pops
+ LBCSPUSH = 42, //! Brace cleanup stack - log push
+ LBCSSWAP = 43, //! Brace cleanup stack - log swaps
+ LFTOR = 44, //! Class Ctor or Dtor
+ LAS = 45, //! align_stack
+ LPPIS = 46, //! Preprocessor Indent and Space
+ LTYPEDEF = 47, //! Typedef and function types
+ LVARDEF = 48, //! Variable def marking
+ LDEFVAL = 49, //! define values
+ LPVSEMI = 50, //! Pawn: virtual semicolons
+ LPFUNC = 51, //! Pawn: function recognition
+ LSPLIT = 52, //! Line splitting
+ LFTYPE = 53, //! Function type detection
+ LTEMPL = 54, //! Template detection
+ LPARADD = 55, //! adding parens in if/while
+ LPARADD2 = 56, //! adding parens in if/while - details
+ LBLANKD = 57, //! blank line details
+ LTEMPFUNC = 58, //! Template function detection
+ LSCANSEMI = 59, //! scan semicolon removal
+ LDELSEMI = 60, //! Removing semicolons
+ LFPARAM = 61, //! Testing for a full parameter
+ LNL1LINE = 62, //! NL check for 1 liners
+ LPFCHK = 63, //! Parse Frame check function call
+ LAVDB = 64, //! align var def braces
+ LSORT = 65, //! Sorting
+ LSPACE = 66, //! Space
+ LALIGN = 67, //! align
+ LALAGAIN = 68, //! align again
+ LOPERATOR = 69, //! operator
+ LASFCP = 70, //! Align Same Function Call Params
+ LINDLINED = 71, //! indent line details
+ LBCTRL = 72, //! beautifier control
+ LRMRETURN = 73, //! remove 'return;'
+ LPPIF = 74, //! #if/#else/#endif pair processing
+ LMCB = 75, //! mod_case_brace
+ LBRCH = 76, //! if brace chain
+ LFCNR = 77, //! function return type
+ LOCCLASS = 78, //! OC Class stuff
+ LOCMSG = 79, //! OC Message stuff
+ LBLANK = 80, //! Blank Lines
+ LOBJCWORD = 81, //! Convert keyword to CT_WORD in certain circumstances
+ LCHANGE = 82, //! something changed
+ LCONTTEXT = 83, //! comment cont_text set
+ LANNOT = 84, //! Java annotation
+ LOCBLK = 85, //! OC Block stuff
+ LFLPAREN = 86, //! Flag paren
+ LOCMSGD = 87, //! OC Message declaration
+ LINDENTAG = 88, //! indent again
+ LNFD = 89, //! newline-function-def
+ LJDBI = 90, //! Java Double Brace Init
+ LSETPAR = 91, //! set_chunk_parent()
+ LSETTYP = 92, //! set_chunk_type()
+ LSETFLG = 93, //! set_chunk_flags()
+ LNLFUNCT = 94, //! newlines before function
+ LCHUNK = 95, //! Add or delete chunk
+ LBC = 96, //! brace cleanup
+ LCOMBINE = 97, //! combine
+ LGUY98 = 98, //! for guy-test
+ LGUY = 99, //! for guy-test
+ LBR = 100, //! braces
+ LOUTPUT = 101, //! output
+ LUNC = 102, //! rules used in uncrustify.cpp
+ LQT = 103, //! load/save options for Qt
+ LOTHER = 255, //! stuff that doesn't neatly fit any other category
+};
+
+#endif /* LOG_LEVELS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.cpp
new file mode 100644
index 00000000..82ee8b8e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.cpp
@@ -0,0 +1,80 @@
+/**
+ * @file log_rules.cpp
+ * is an extract from space.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "log_rules.h"
+
+#include "unc_tools.h"
+
+
+void log_rule2(const char *func, size_t line, const char *rule, Chunk *first, Chunk *second)
+{
+ LOG_FUNC_ENTRY();
+
+ if (second->type != CT_NEWLINE)
+ {
+ LOG_FMT(LSPACE, "%s(%zu): first->orig_line is %zu, first->orig_col is %zu, first->Text() is '%s', [%s/%s] <===>\n",
+ func, line, first->orig_line, first->orig_col, first->Text(),
+ get_token_name(first->type), get_token_name(get_chunk_parent_type(first)));
+ LOG_FMT(LSPACE, " second->orig_line is %zu, second->orig_col is %zu, second->Text() is '%s', [%s/%s] :",
+ second->orig_line, second->orig_col, second->Text(),
+ get_token_name(second->type), get_token_name(get_chunk_parent_type(second)));
+ LOG_FMT(LSPACE, " rule %s[line %zu]\n",
+ rule, line);
+ }
+}
+
+
+#ifdef SUPER_LOG
+
+
+void log_rule3(log_sev_t sev, const char *func, size_t line, const char *rule)
+#else
+
+
+void log_rule3(log_sev_t sev, const char *func, const char *rule)
+#endif
+{
+ // some Windows platforms provide a qualified function name ("ABC::XYZ::function_Name")
+ // as __func__; call get_unqualified_func_name() to return an unqualified function name
+
+ func = get_unqualified_func_name(func);
+
+#ifdef SUPER_LOG
+ LOG_FMT(sev, "log_rule(%s:%zu): rule is '%s'\n", func, line, rule);
+#else
+ LOG_FMT(sev, "log_rule(%s): rule is '%s'\n", func, rule);
+#endif
+}
+
+
+void log_rule4(const char *rule, Chunk *first)
+{
+ if (cpd.html_file == nullptr)
+ {
+ return;
+ }
+
+ if (first->tracking == nullptr)
+ {
+ first->tracking = new track_list;
+ first->tracking->reserve(3);
+ }
+ // copy the rule
+ size_t length = strlen(rule) + 1;
+ char *r = (char *)malloc(length);
+
+ strcpy(r, rule);
+ size_t a_number = get_A_Number();
+ Track_nr A = make_pair(a_number, r);
+
+ first->tracking->push_back(A);
+ size_t sizeOfTrack = first->tracking->size();
+
+ LOG_FMT(LSPACE, "log_rule4(%d): rule is '%s', after '%s', at line %zu, tracking number is %zu, size is %zu\n",
+ __LINE__, rule, first->Text(), first->orig_line, a_number, sizeOfTrack);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.h
new file mode 100644
index 00000000..e7916702
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/log_rules.h
@@ -0,0 +1,49 @@
+/**
+ * @file log_rules.h
+ * prototypes for log_rules.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef LOG_RULES_H_INCLUDED
+#define LOG_RULES_H_INCLUDED
+
+#include "chunk.h"
+#include "uncrustify.h"
+
+using namespace uncrustify;
+
+#if defined DEBUG
+#define log_rule(rule) \
+ log_rule2(__func__, __LINE__, (rule), first, second); \
+ log_rule4((rule), first)
+#else
+#define log_rule(rule) \
+ log_rule2(__func__, __LINE__, (rule), first, second)
+#endif
+
+// if you need more debug informations, remove the comment at the next line
+#define SUPER_LOG 1
+#ifdef SUPER_LOG
+#define log_rule_B(rule) \
+ log_rule3(LCURRENT, __func__, __LINE__, (rule))
+#else
+#define log_rule_B(rule) \
+ log_rule3(LCURRENT, __func__, (rule))
+#endif
+
+void log_rule2(const char *func, size_t line, const char *rule, Chunk *first, Chunk *second);
+
+
+#ifdef SUPER_LOG
+void log_rule3(log_sev_t sev, const char *func, size_t line, const char *rule);
+
+#else
+void log_rule3(log_sev_t sev, const char *func, const char *rule);
+
+#endif
+
+void log_rule4(const char *rule, Chunk *first);
+
+#endif /* LOG_RULES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.cpp
new file mode 100644
index 00000000..969a4192
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.cpp
@@ -0,0 +1,336 @@
+/**
+ * @file logger.cpp
+ *
+ * Functions to do logging.
+ *
+ * If a log statement ends in a newline, the current log is ended.
+ * When the log severity changes, an implicit newline is inserted.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "logger.h"
+
+#include "compat.h"
+
+#include <cstdarg> // to get va_start, va_end
+
+
+struct log_fcn_info
+{
+ log_fcn_info(const char *name_, int line_)
+ : name(name_)
+ , line(line_)
+ {
+ }
+
+ const char *name;
+ int line;
+};
+static std::deque<log_fcn_info> g_fq;
+
+//! Private log structure
+struct log_buf
+{
+ log_buf()
+ : log_file(nullptr)
+ , sev(LSYS)
+ , in_log(0)
+ , buf_len(0)
+ , show_hdr(false)
+ {
+ bufX.clear();
+ bufX.resize(256);
+ }
+
+ FILE *log_file; //! file where the log messages are stored into
+ log_sev_t sev; //! log level determines which messages are logged
+ int in_log; //! flag indicates if a log operation is going on
+ size_t buf_len; //! number of characters currently stored in buffer
+ std::vector<char> bufX; //! buffer holds the log message
+ log_mask_t mask;
+ bool show_hdr; //! flag determine if a header gets added to log message
+};
+
+
+static struct log_buf g_log;
+
+
+/**
+ * Starts the log statement by flushing if needed and printing the header
+ *
+ * @param sev The log severity
+ *
+ * @return The number of bytes available
+ */
+static size_t log_start(log_sev_t sev);
+
+
+/**
+ * Cleans up after a log statement by detecting whether the log is done,
+ * (it ends in a newline) and possibly flushing the log.
+ */
+static void log_end(void);
+
+
+/**
+ * Initializes the log subsystem - call this first.
+ * This function sets the log stream and enables the top 3 sevs (0-2).
+ *
+ * @param log_file NULL for stderr or the FILE stream for logs.
+ */
+void log_init(FILE *log_file)
+{
+ // set the top 3 severities
+ logmask_set_all(g_log.mask, false);
+ log_set_sev(LSYS, true);
+ log_set_sev(LERR, true);
+ log_set_sev(LWARN, true);
+
+ g_log.log_file = (log_file != nullptr) ? log_file : stderr;
+}
+
+
+void log_show_sev(bool show)
+{
+ g_log.show_hdr = show;
+}
+
+
+bool log_sev_on(log_sev_t sev)
+{
+ return(logmask_test(g_log.mask, sev));
+}
+
+
+void log_set_sev(log_sev_t sev, bool value)
+{
+ logmask_set_sev(g_log.mask, sev, value);
+}
+
+
+void log_set_mask(const log_mask_t &mask)
+{
+ g_log.mask = mask;
+}
+
+
+void log_get_mask(log_mask_t &mask)
+{
+ mask = g_log.mask;
+}
+
+
+void log_flush(bool force_nl)
+{
+ if (g_log.buf_len > 0)
+ {
+ if ( force_nl
+ && g_log.bufX[g_log.buf_len - 1] != '\n')
+ {
+ g_log.bufX[g_log.buf_len++] = '\n';
+ g_log.bufX[g_log.buf_len] = 0;
+ }
+ size_t retlength = fwrite(&g_log.bufX[0], g_log.buf_len, 1, g_log.log_file);
+
+ if (retlength != 1)
+ {
+ // maybe we should log something to complain... =)
+ }
+ g_log.buf_len = 0;
+ }
+}
+
+
+static size_t log_start(log_sev_t sev)
+{
+ if (sev != g_log.sev)
+ {
+ if (g_log.buf_len > 0)
+ {
+ log_flush(true);
+ }
+ g_log.sev = sev;
+ g_log.in_log = false;
+ }
+
+ // If not in a log, the buffer is empty. Add the header, if enabled.
+ if ( !g_log.in_log
+ && g_log.show_hdr)
+ {
+ g_log.buf_len = static_cast<size_t>(snprintf(&g_log.bufX[0], g_log.bufX.size(), "<%d>", sev));
+ }
+ size_t cap = (g_log.bufX.size() - 2) - g_log.buf_len;
+
+ return((cap > 0) ? cap : 0);
+}
+
+
+static void log_end(void)
+{
+ g_log.in_log = (g_log.bufX[g_log.buf_len - 1] != '\n');
+
+ if ( !g_log.in_log
+ || (g_log.buf_len > (g_log.bufX.size() / 2)))
+ {
+ log_flush(false);
+ }
+}
+
+
+void log_fmt(log_sev_t sev, const char *fmt, ...)
+{
+ if ( fmt == nullptr
+ || !log_sev_on(sev))
+ {
+ return;
+ }
+ // Issue #1203
+ unsigned int length = strlen(fmt);
+
+ if (length == 0)
+ {
+ return;
+ }
+ // the value of buffer_length is experimental
+ const int buffer_length = 40000;
+ char buf[buffer_length];
+
+ // it MUST be a 'unsigned int' variable to be runable under windows
+
+ if (length >= buffer_length)
+ {
+ fprintf(stderr, "FATAL(1): The variable 'buf' is not big enought:\n");
+ fprintf(stderr, " it should be bigger as %u\n", length);
+ fprintf(stderr, "Please make a report.\n");
+ fprintf(stderr, "For the buffer: %s\n", fmt);
+ exit(EX_SOFTWARE);
+ }
+ memcpy(buf, fmt, length);
+ buf[length] = 0;
+ convert_log_zu2lu(buf);
+
+ while (true)
+ {
+ /* Some implementation of vsnprintf() return the number of characters
+ * that would have been stored if the buffer was large enough instead of
+ * the number of characters actually stored.
+ *
+ * this gets the number of characters that fit into the log buffer
+ */
+ size_t cap = log_start(sev);
+ // Add on the variable log parameters to the log string
+ va_list args; // determine list of arguments ...
+ va_start(args, fmt);
+ size_t which = g_log.buf_len;
+ char *where = &g_log.bufX[which];
+ size_t lenX = static_cast<size_t>(vsnprintf(where, cap, buf, args));
+ va_end(args);
+
+ if (lenX > 0)
+ {
+ // The functions snprintf() and vsnprintf() do not write more than size bytes
+ // (including the terminating null byte ('\0')). If the output was truncated due
+ // to this limit, then the return value is the number of characters (excluding the
+ // terminating null byte) which would have been written to the final string if
+ // enough space had been available. Thus, a return value of size or more means
+ // that the output was truncated.
+ if (lenX > cap)
+ {
+ size_t bufXLength = g_log.bufX.size();
+ size_t X = bufXLength * 2;
+
+ if (X >= buffer_length)
+ {
+ fprintf(stderr, "FATAL(2): The variable 'buf' is not big enought:\n");
+ fprintf(stderr, " it should be bigger as %zu\n", X);
+ fprintf(stderr, "Please make a report.\n");
+ fprintf(stderr, "For the buffer: %s\n", fmt);
+ exit(EX_SOFTWARE);
+ }
+ g_log.bufX.resize(X);
+ }
+ else
+ {
+ g_log.buf_len += lenX;
+ g_log.bufX[g_log.buf_len] = 0;
+ break;
+ }
+ }
+ }
+ log_end();
+} // log_fmt
+
+
+log_func::log_func(const char *name, int line)
+{
+ g_fq.push_back(log_fcn_info(name, line));
+}
+
+
+log_func::~log_func()
+{
+ g_fq.pop_back();
+}
+
+
+void log_func_stack(log_sev_t sev, const char *prefix, const char *suffix, size_t skip_cnt)
+{
+ UNUSED(skip_cnt);
+
+ if (prefix)
+ {
+ LOG_FMT(sev, "%s", prefix);
+ }
+#ifdef DEBUG
+ const char *sep = "";
+ size_t g_fq_size = g_fq.size();
+ size_t begin_with;
+
+ if (g_fq_size > (skip_cnt + 1))
+ {
+ begin_with = g_fq_size - (skip_cnt + 1);
+
+ for (size_t idx = begin_with; idx != 0; idx--)
+ {
+ LOG_FMT(sev, "%s %s:%d", sep, g_fq[idx].name, g_fq[idx].line);
+ sep = ",";
+ }
+
+ LOG_FMT(sev, "%s %s:%d", sep, g_fq[0].name, g_fq[0].line);
+ }
+#else
+ LOG_FMT(sev, "-DEBUG NOT SET-");
+#endif
+
+ if (suffix)
+ {
+ LOG_FMT(sev, "%s", suffix);
+ }
+}
+
+
+const char *get_unqualified_func_name(const char *func)
+{
+ /**
+ * we look for the last ':' character;
+ */
+ for (auto i = strlen(func); i > 0; --i)
+ {
+ if (func[i - 1] == ':')
+ {
+ /**
+ * function name is qualified, so return the
+ * unqualified portion
+ */
+ return(func + i);
+ }
+ }
+
+ /**
+ * input function name is unqualified
+ */
+
+ return(func);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.h
new file mode 100644
index 00000000..68501967
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logger.h
@@ -0,0 +1,166 @@
+/**
+ * @file logger.h
+ *
+ * Functions to do logging.
+ * The macros check whether the logsev is active before evaluating the
+ * parameters. Use them instead of the functions.
+ *
+ * If a log statement ends in a newline, the current log is ended.
+ * When the log severity changes, an implicit newline is inserted.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef LOGGER_H_INCLUDED
+#define LOGGER_H_INCLUDED
+
+#include "logmask.h"
+
+#include <cstdio> // FILE
+
+
+/**
+ * Initializes the log subsystem - call this first.
+ * This function sets the log stream and enables the top 3 sevs (0-2).
+ *
+ * @param log_file nullptr for stderr or the FILE stream for logs.
+ */
+void log_init(FILE *log_file);
+
+
+/**
+ * Show or hide the severity prefix "<1>"
+ *
+ * @param show true=show, false=hide
+ */
+void log_show_sev(bool show);
+
+
+/**
+ * Returns whether a log severity is active.
+ *
+ * @param sev severity log level
+ *
+ * @return true/false
+ */
+bool log_sev_on(log_sev_t sev);
+
+
+/**
+ * Sets a log sev on or off
+ *
+ * @param sev severity log level to modify
+ * @param val new value for severity log level
+ *
+ * @return true/false
+ */
+void log_set_sev(log_sev_t sev, bool value);
+
+
+/**
+ * Sets the log mask
+ *
+ * @param mask The mask to copy
+ */
+void log_set_mask(const log_mask_t &mask);
+
+
+/**
+ * Gets the log mask
+ *
+ * @param mask Where to copy the mask
+ */
+void log_get_mask(log_mask_t &mask);
+
+
+#ifdef __MINGW_PRINTF_FORMAT
+// On MinGW, the printf functions can be provided by a number of different
+// implementations, with different format string support. Annontate log_fmt
+// below with the same format attribute as the currently chosen default printf
+// function.
+#define PRINTF_FORMAT __MINGW_PRINTF_FORMAT
+#else
+#define PRINTF_FORMAT printf
+#endif
+
+/**
+ * Logs a formatted string -- similar to printf()
+ *
+ * @param sev The severity
+ * @param fmt The format string
+ * @param ... Additional arguments
+ */
+void log_fmt(log_sev_t sev, const char *fmt, ...) __attribute__((format(PRINTF_FORMAT, 2, 3)));
+
+
+/**
+ * Flushes the cached log text to the stream
+ *
+ * @param force_nl Append NL if not present
+ */
+void log_flush(bool force_nl);
+
+
+// it is necessary to make at least one time pro change a check of all the
+// uses of the MACRO LOG_FMT under Linux. This to detect all the used pointers,
+// which might be nullptr.
+// uncomment the define to do that.
+// #define NO_MACRO_VARARG
+
+#ifdef NO_MACRO_VARARG
+#define LOG_FMT log_fmt
+// TODO during debugging add source file and line number
+#else
+#define LOG_FMT(sev, ...) \
+ if (log_sev_on(sev)) { log_fmt(sev, __VA_ARGS__); }
+#endif
+
+
+#define __unqualified_func__ get_unqualified_func_name(__func__)
+
+
+#ifdef DEBUG
+/**
+ * This should be called as the first thing in a function.
+ * It uses the log_func class to add an entry to the function log stack.
+ * It is automatically removed when the function returns.
+ */
+#define LOG_FUNC_ENTRY() log_func log_fe = log_func(__unqualified_func__, __LINE__)
+
+
+#else
+#define LOG_FUNC_ENTRY()
+#endif
+
+
+/**
+ * This class just adds a entry to the top of the stack on construction and
+ * removes it on destruction.
+ * RAII for the win.
+ */
+class log_func
+{
+public:
+ log_func(const char *name, int line);
+
+
+ ~log_func();
+};
+
+
+void log_func_stack(log_sev_t sev, const char *prefix = 0, const char *suffix = "\n", size_t skip_cnt = 0);
+
+
+/**
+ * Return the unqualified function name from the input argument
+ * @param the qualified function name, usually provided by __func__ macro
+ * @return the corresponding unqualified name
+ */
+const char *get_unqualified_func_name(const char *func);
+
+
+#define log_func_stack_inline(_sev) log_func_stack((_sev), " [CallStack:", "]\n", 0)
+
+
+#endif /* LOGGER_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.cpp
new file mode 100644
index 00000000..ca94cd05
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.cpp
@@ -0,0 +1,142 @@
+/**
+ * @file logmask.cpp
+ *
+ * Functions to convert between a string and a severity mask.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "logmask.h"
+
+#include "unc_ctype.h"
+
+#include <cstdio> // snprintf()
+#include <cstdlib> // strtoul()
+
+#ifdef DEVELOP_ONLY
+
+
+/*
+ * the test suite Coveralls: https://coveralls.io
+ * will complains because these functions are only
+ * used at developement time.
+ * Don't worry about unsed lines for the functions:
+ * logmask_to_str
+ */
+char *logmask_to_str(const log_mask_t &mask, char *buf, int size)
+{
+ if ( buf == nullptr
+ || size <= 0)
+ {
+ return(buf);
+ }
+ int last_sev = -1;
+ bool is_range = false;
+ int len = 0;
+
+ for (int sev = 0; sev < 256; sev++)
+ {
+ if (logmask_test(mask, static_cast<log_sev_t>(sev)))
+ {
+ if (last_sev == -1)
+ {
+ len += snprintf(&buf[len], size - len, "%d,", sev);
+ }
+ else
+ {
+ is_range = true;
+ }
+ last_sev = sev;
+ }
+ else
+ {
+ if (is_range)
+ {
+ buf[len - 1] = '-'; // change last comma to a dash
+ len += snprintf(&buf[len], size - len, "%d,", last_sev);
+ is_range = false;
+ }
+ last_sev = -1;
+ }
+ }
+
+ // handle a range that ends on the last bit
+ if ( is_range
+ && last_sev != -1)
+ {
+ buf[len - 1] = '-'; // change last comma to a dash
+ len += snprintf(&buf[len], size - len, "%d", last_sev);
+ }
+ else
+ {
+ // Eat the last comma
+ if (len > 0)
+ {
+ len--;
+ }
+ }
+ buf[len] = 0;
+
+ return(buf);
+} // logmask_to_str
+#endif /* DEVELOP_ONLY */
+
+
+void logmask_from_string(const char *str, log_mask_t &mask)
+{
+ if (str == nullptr)
+ {
+ return;
+ }
+ logmask_set_all(mask, false); // Start with a clean mask
+
+ // If the first character is 'a' or 'A', set all severities
+ if (unc_toupper(*str) == 'A')
+ {
+ logmask_set_all(mask, true);
+ str++;
+ }
+ char *ptmp;
+ bool was_dash = false;
+ int last_level = -1;
+
+ while (*str != 0) // check string until termination character
+ {
+ if (unc_isspace(*str)) // ignore spaces and go on with next character
+ {
+ str++;
+ continue;
+ }
+
+ if (unc_isdigit(*str))
+ {
+ int level = strtoul(str, &ptmp, 10);
+ str = ptmp;
+
+ logmask_set_sev(mask, static_cast<log_sev_t>(level), true);
+
+ if (was_dash)
+ {
+ for (int idx = last_level + 1; idx < level; idx++)
+ {
+ logmask_set_sev(mask, static_cast<log_sev_t>(idx), true);
+ }
+
+ was_dash = false;
+ }
+ last_level = level;
+ }
+ else if (*str == '-') // a dash marks all bits until the next number
+ {
+ was_dash = true;
+ str++;
+ }
+ else // probably a comma
+ {
+ last_level = -1;
+ was_dash = false;
+ str++;
+ }
+ }
+} // logmask_from_string
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.h
new file mode 100644
index 00000000..7cc24ca4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/logmask.h
@@ -0,0 +1,103 @@
+/**
+ * @file logmask.h
+ *
+ * Functions to manipulate a log severity mask.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef LOGMASK_H_INCLUDED
+#define LOGMASK_H_INCLUDED
+
+#include "base_types.h"
+#include "log_levels.h"
+
+#include <bitset>
+#include <cstring> // memset()
+
+/*
+ * the test suite Coveralls: https://coveralls.io
+ * will complains because these functions are only
+ * used at developement time.
+ * Don't worry about unsed lines for the functions:
+ * logmask_test
+ * logmask_set_all
+ */
+
+//! A simple array of 256 bits
+typedef std::bitset<256> log_mask_t;
+
+
+/**
+ * Tests whether a sev bit is set in the mask
+ *
+ * @param mask log mask to evaluate
+ * @param sev severity bit to check
+ *
+ * @return true (is set) or false (not set)
+ */
+static inline bool logmask_test(const log_mask_t &mask, log_sev_t sev)
+{
+ return(mask.test(sev));
+}
+
+
+/**
+ * Sets a set bit in the mask
+ *
+ * @param mask log mask to modify
+ * @param sev The severity to check
+ * @param value true (set bit) or false (clear bit)
+ */
+static inline void logmask_set_sev(log_mask_t &mask, log_sev_t sev, bool value)
+{
+ mask.set(sev, value);
+}
+
+
+/**
+ * Sets all bits to the same value
+ *
+ * @param mast log mask to operate on
+ * @param value true (set bit) or false (clear bit)
+ */
+static inline void logmask_set_all(log_mask_t &mask, bool value)
+{
+ if (value)
+ {
+ mask.set();
+ }
+ else
+ {
+ mask.reset();
+ }
+}
+
+
+#ifdef DEVELOP_ONLY
+/**
+ * Convert a logmask into a string.
+ * The string is a comma-delimited list of severities.
+ * Example: 1,3,5-10
+ *
+ * @param mask the mask to convert
+ * @param buf the buffer to hold the string
+ * @param size the size of the buffer
+ *
+ * @return buf (pass through)
+ */
+char *logmask_to_str(const log_mask_t &mask, char *buf, int size);
+
+#endif /* DEVELOP_ONLY */
+
+
+/**
+ * Parses a string into a log severity
+ *
+ * @param str string to parse
+ * @param mask bit mask to populate with log levels
+ */
+void logmask_from_string(const char *str, log_mask_t &mask);
+
+
+#endif /* LOGMASK_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.cpp
new file mode 100644
index 00000000..af8874a4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.cpp
@@ -0,0 +1,308 @@
+/**
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legales
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * @license Public Domain / GPL v2+
+ */
+
+#include "md5.h"
+
+#include <string.h>
+
+
+void MD5::reverse_u32(UINT8 *buf, int n_u32)
+{
+ UINT8 tmp;
+
+ if (m_big_endian)
+ {
+ // change { 4, 3, 2, 1 } => { 1, 2, 3, 4 }
+ while (n_u32-- > 0)
+ {
+ tmp = buf[0];
+ buf[0] = buf[3];
+ buf[3] = tmp;
+
+ tmp = buf[1];
+ buf[1] = buf[2];
+ buf[2] = tmp;
+
+ buf += 4;
+ }
+ }
+ else
+ {
+ // change { 4, 3, 2, 1 } => { 3, 4, 1, 2 }
+ while (n_u32-- > 0)
+ {
+ tmp = buf[0];
+ buf[0] = buf[1];
+ buf[1] = tmp;
+
+ tmp = buf[2];
+ buf[2] = buf[3];
+ buf[3] = tmp;
+
+ buf += 4;
+ }
+ }
+}
+
+
+MD5::MD5()
+{
+ m_buf[0] = 0x01020304;
+
+ /*
+ * Little endian = { 4, 3, 2, 1 }
+ * Big endian = { 1, 2, 3, 4 }
+ * PDP endian = { 3, 4, 1, 2 }
+ *
+ * The MD5 stuff is written for little endian.
+ */
+
+ m_in8 = (UINT8 *)m_in32;
+ m_need_byteswap = *(UINT8 *)m_buf != 4;
+ m_big_endian = *(UINT8 *)m_buf == 1;
+}
+
+
+//! Start MD5 accumulation.
+void MD5::Init()
+{
+ m_buf[0] = 0x67452301;
+ m_buf[1] = 0xefcdab89;
+ m_buf[2] = 0x98badcfe;
+ m_buf[3] = 0x10325476;
+
+ m_bits[0] = 0;
+ m_bits[1] = 0;
+}
+
+
+//! Update context to reflect the concatenation of another buffer full of bytes.
+void MD5::Update(const void *data, UINT32 len)
+{
+ const UINT8 *buf = (const UINT8 *)data;
+
+ UINT32 t = m_bits[0]; // Update bitcount
+
+ if ((m_bits[0] = t + ((UINT32)len << 3)) < t)
+ {
+ m_bits[1]++; // Carry from low to high
+ }
+ m_bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data
+
+ // Handle any leading odd-sized chunks
+ if (t)
+ {
+ UINT8 *p = m_in8 + t;
+
+ t = 64 - t;
+
+ if (len < t)
+ {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+
+ if (m_need_byteswap)
+ {
+ reverse_u32(m_in8, 16);
+ }
+ Transform(m_buf, m_in32);
+ buf += t;
+ len -= t;
+ }
+
+ // Process data in 64-byte chunks
+ while (len >= 64)
+ {
+ memcpy(m_in32, buf, 64);
+
+ if (m_need_byteswap)
+ {
+ reverse_u32(m_in8, 16);
+ }
+ Transform(m_buf, m_in32);
+ buf += 64; // TODO: possible creation of out-of-bounds pointer 64 beyond end of data
+ len -= 64;
+ }
+ // Save off any remaining bytes of data
+ memcpy(m_in32, buf, len); // TODO: possible access beyond array
+} // MD5::Update
+
+
+void MD5::Final(UINT8 digest[16])
+{
+ // Compute number of bytes modulo 64
+ UINT32 count = (m_bits[0] >> 3) & 0x3F;
+
+ /*
+ * Set the first char of padding to 0x80. This is safe since there is always
+ * at least one byte free
+ */
+ UINT8 *p = m_in8 + count;
+
+ *p++ = 0x80;
+
+ // Bytes of padding needed to make 64 bytes
+ count = 64 - 1 - count;
+
+ // Pad out to 56 modulo 64
+ if (count < 8)
+ {
+ // Two lots of padding: Pad the first block to 64 bytes
+ memset(p, 0, count);
+
+ if (m_need_byteswap)
+ {
+ reverse_u32(m_in8, 16);
+ }
+ Transform(m_buf, m_in32);
+
+ // Now fill the next block with 56 bytes
+ memset(m_in32, 0, 56);
+ }
+ else
+ {
+ // Pad block to 56 bytes
+ memset(p, 0, count - 8);
+ }
+
+ if (m_need_byteswap)
+ {
+ reverse_u32(m_in8, 14);
+ }
+ // Append length in bits and transform
+ memcpy(m_in8 + 56, &m_bits[0], 4);
+ memcpy(m_in8 + 60, &m_bits[1], 4);
+
+ Transform(m_buf, m_in32);
+
+ if (m_need_byteswap)
+ {
+ reverse_u32((UINT8 *)m_buf, 4);
+ }
+ memcpy(digest, m_buf, 16);
+} // MD5::Final
+
+
+// The four core functions - F1 is optimized somewhat
+// #define F1(x, y, z) (x & y | ~x & z)
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+
+// This is the central step in the MD5 algorithm.
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ((w) += f((x), (y), (z)) + (data), (w) = (w) << (s) | (w) >> (32 - (s)), (w) += (x))
+
+
+void MD5::Transform(UINT32 buf[4], UINT32 in_data[16])
+{
+ UINT32 a = buf[0];
+ UINT32 b = buf[1];
+ UINT32 c = buf[2];
+ UINT32 d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in_data[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in_data[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in_data[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in_data[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in_data[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in_data[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in_data[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in_data[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in_data[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in_data[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in_data[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in_data[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in_data[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in_data[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in_data[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in_data[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in_data[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in_data[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in_data[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in_data[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in_data[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in_data[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in_data[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in_data[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in_data[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in_data[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in_data[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in_data[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in_data[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in_data[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in_data[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in_data[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in_data[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in_data[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in_data[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in_data[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in_data[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in_data[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in_data[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in_data[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in_data[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in_data[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in_data[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in_data[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in_data[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in_data[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in_data[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in_data[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in_data[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in_data[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in_data[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in_data[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in_data[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in_data[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in_data[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in_data[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in_data[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in_data[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in_data[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in_data[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in_data[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in_data[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in_data[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in_data[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+} // MD5::Transform
+
+
+void MD5::Calc(const void *data, UINT32 length, UINT8 digest[16])
+{
+ MD5 md5;
+
+ md5.Init();
+ md5.Update(data, length);
+ md5.Final(digest);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.h
new file mode 100644
index 00000000..d1148b5e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/md5.h
@@ -0,0 +1,85 @@
+/**
+ * @file md5.h
+ * A simple class for MD5 calculation
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef MD5_H_INCLUDED
+#define MD5_H_INCLUDED
+
+#include "base_types.h"
+
+class MD5
+{
+public:
+ MD5();
+
+
+ ~MD5()
+ {
+ }
+
+
+ /**
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+ void Init();
+
+
+ /**
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+ void Update(const void *data, UINT32 len);
+
+
+ /**
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ *
+ * @param[out] digest calculated MD5 checksum
+ */
+ void Final(UINT8 digest[16]);
+
+
+ /**
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5::Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+ static void Transform(UINT32 buf[4], UINT32 in_data[16]);
+
+
+ /**
+ * Calculates MD5 for a block of data
+ *
+ * @param data data to calculate MD5 for
+ * @param length number of bytes in data
+ * @param[out] digest calculated MD5 checksum
+ */
+ static void Calc(const void *data, UINT32 length, UINT8 digest[16]);
+
+
+private:
+ UINT32 m_buf[4];
+ UINT32 m_bits[2];
+ UINT32 m_in32[16];
+ // Alternate view of m_in32
+ UINT8 *m_in8;
+ bool m_need_byteswap;
+ bool m_big_endian;
+
+
+ /**
+ * Reverse the bytes in 32-bit chunks.
+ * 'buf' might not be word-aligned.
+ *
+ * @param buf The byte array to reverse
+ * @param n_u32 The number of UINT32's in the data
+ */
+ void reverse_u32(UINT8 *buf, int n_u32);
+};
+
+#endif /* MD5_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.cpp
new file mode 100644
index 00000000..1b4f09b5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.cpp
@@ -0,0 +1,6721 @@
+/**
+ * @file newlines.cpp
+ * Adds or removes newlines.
+ *
+ * Informations
+ * "Ignore" means do not change it.
+ * "Add" in the context of spaces means make sure there is at least 1.
+ * "Add" elsewhere means make sure one is present.
+ * "Remove" mean remove the space/brace/newline/etc.
+ * "Force" in the context of spaces means ensure that there is exactly 1.
+ * "Force" in other contexts means the same as "add".
+ *
+ * Rmk: spaces = space + nl
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "newlines.h"
+
+#include "align_stack.h"
+#include "combine_skip.h"
+#include "flag_parens.h"
+#include "indent.h"
+#include "keywords.h"
+#include "prototypes.h"
+#include "space.h"
+#include "unc_tools.h"
+
+#ifdef WIN32
+#include <algorithm> // to get max
+#endif // ifdef WIN32
+
+
+constexpr static auto LCURRENT = LNEWLINE;
+
+using namespace std;
+using namespace uncrustify;
+
+
+static void mark_change(const char *func, size_t line);
+
+
+/**
+ * Check to see if we are allowed to increase the newline count.
+ * We can't increase the newline count:
+ * - if nl_squeeze_ifdef and a preproc is after the newline.
+ * - if eat_blanks_before_close_brace and the next is '}'
+ * - unless function contains an empty body and
+ * nl_inside_empty_func is non-zero
+ * - if eat_blanks_after_open_brace and the prev is '{'
+ * - unless the brace belongs to a namespace
+ * and nl_inside_namespace is non-zero
+ */
+static bool can_increase_nl(Chunk *nl);
+
+
+/**
+ * Basic approach:
+ * 1. Find next open brace
+ * 2. Find next close brace
+ * 3. Determine why the braces are there
+ * a. struct/union/enum "enum [name] {"
+ * c. assignment "= {"
+ * b. if/while/switch/for/etc ") {"
+ * d. else "} else {"
+ */
+static void setup_newline_add(Chunk *prev, Chunk *nl, Chunk *next);
+
+
+//! Make sure there is a blank line after a commented group of values
+static void newlines_double_space_struct_enum_union(Chunk *open_brace);
+
+
+//! If requested, make sure each entry in an enum is on its own line
+static void newlines_enum_entries(Chunk *open_brace, iarf_e av);
+
+
+/**
+ * Checks to see if it is OK to add a newline around the chunk.
+ * Don't want to break one-liners...
+ * return value:
+ * true: a new line may be added
+ * false: a new line may NOT be added
+ */
+static bool one_liner_nl_ok(Chunk *pc);
+
+
+static void nl_create_one_liner(Chunk *vbrace_open);
+
+
+static void nl_create_list_liner(Chunk *brace_open);
+
+
+/**
+ * Test if a chunk belongs to a one-liner method definition inside a class body
+ */
+static bool is_class_one_liner(Chunk *pc);
+
+
+/**
+ * Test if a chunk may be combined with a function prototype group.
+ *
+ * If nl_class_leave_one_liner_groups is enabled, a chunk may be combined with
+ * a function prototype group if it is a one-liner inside a class body, and is
+ * a definition of the same sort as surrounding prototypes. This checks against
+ * either the function name, or the function closing brace.
+ */
+bool is_func_proto_group(Chunk *pc, E_Token one_liner_type);
+
+
+//! Find the next newline or nl_cont
+static void nl_handle_define(Chunk *pc);
+
+
+/**
+ * Does the Ignore, Add, Remove, or Force thing between two chunks
+ *
+ * @param before The first chunk
+ * @param after The second chunk
+ * @param av The IARF value
+ */
+static void newline_iarf_pair(Chunk *before, Chunk *after, iarf_e av, bool check_nl_assign_leave_one_liners = false);
+
+
+/**
+ * Adds newlines to multi-line function call/decl/def
+ * Start points to the open paren
+ */
+static void newline_func_multi_line(Chunk *start);
+
+
+static void newline_template(Chunk *start);
+
+
+/**
+ * Formats a function declaration
+ * Start points to the open paren
+ */
+static void newline_func_def_or_call(Chunk *start);
+
+
+/**
+ * Formats a message, adding newlines before the item before the colons.
+ *
+ * Start points to the open '[' in:
+ * [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg
+ * error:arg3];
+ */
+static void newline_oc_msg(Chunk *start);
+
+
+//! Ensure that the next non-comment token after close brace is a newline
+static void newline_end_newline(Chunk *br_close);
+
+
+/**
+ * Add or remove a newline between the closing paren and opening brace.
+ * Also uncuddles anything on the closing brace. (may get fixed later)
+ *
+ * "if (...) { \n" or "if (...) \n { \n"
+ *
+ * For virtual braces, we can only add a newline after the vbrace open.
+ * If we do so, also add a newline after the vbrace close.
+ */
+static bool newlines_if_for_while_switch(Chunk *start, iarf_e nl_opt);
+
+
+/**
+ * Add or remove extra newline before the chunk.
+ * Adds before comments
+ * Doesn't do anything if open brace before it
+ * "code\n\ncomment\nif (...)" or "code\ncomment\nif (...)"
+ */
+static void newlines_if_for_while_switch_pre_blank_lines(Chunk *start, iarf_e nl_opt);
+
+
+static void blank_line_set(Chunk *pc, Option<unsigned> &opt);
+
+
+/**
+ * Add one/two newline(s) before the chunk.
+ * Adds before comments
+ * Adds before destructor
+ * Doesn't do anything if open brace before it
+ * "code\n\ncomment\nif (...)" or "code\ncomment\nif (...)"
+ */
+static void newlines_func_pre_blank_lines(Chunk *start, E_Token start_type);
+
+
+static Chunk *get_closing_brace(Chunk *start);
+
+
+/**
+ * remove any consecutive newlines following this chunk
+ * skip vbraces
+ */
+static void remove_next_newlines(Chunk *start);
+
+
+/**
+ * Add or remove extra newline after end of the block started in chunk.
+ * Doesn't do anything if close brace after it
+ * Interesting issue is that at this point, nls can be before or after vbraces
+ * VBraces will stay VBraces, conversion to real ones should have already happened
+ * "if (...)\ncode\ncode" or "if (...)\ncode\n\ncode"
+ */
+static void newlines_if_for_while_switch_post_blank_lines(Chunk *start, iarf_e nl_opt);
+
+
+/**
+ * Adds or removes a newline between the keyword and the open brace.
+ * If there is something after the '{' on the same line, then
+ * the newline is removed unconditionally.
+ * If there is a '=' between the keyword and '{', do nothing.
+ *
+ * "struct [name] {" or "struct [name] \n {"
+ */
+static void newlines_struct_union(Chunk *start, iarf_e nl_opt, bool leave_trailing);
+static void newlines_enum(Chunk *start);
+static void newlines_namespace(Chunk *start); // Issue #2186
+
+
+/**
+ * Cuddles or un-cuddles a chunk with a previous close brace
+ *
+ * "} while" vs "} \n while"
+ * "} else" vs "} \n else"
+ *
+ * @param start The chunk - should be CT_ELSE or CT_WHILE_OF_DO
+ */
+static void newlines_cuddle_uncuddle(Chunk *start, iarf_e nl_opt);
+
+
+/**
+ * Adds/removes a newline between else and '{'.
+ * "else {" or "else \n {"
+ */
+static void newlines_do_else(Chunk *start, iarf_e nl_opt);
+
+
+//! Check if token starts a variable declaration
+static bool is_var_def(Chunk *pc, Chunk *next);
+
+
+//! Put newline(s) before and/or after a block of variable definitions
+static Chunk *newline_def_blk(Chunk *start, bool fn_top);
+
+
+/**
+ * Handles the brace_on_func_line setting and decides if the closing brace
+ * of a pair should be right after a newline.
+ * The only cases where the closing brace shouldn't be the first thing on a line
+ * is where the opening brace has junk after it AND where a one-liner in a
+ * class is supposed to be preserved.
+ *
+ * General rule for break before close brace:
+ * If the brace is part of a function (call or definition) OR if the only
+ * thing after the opening brace is comments, the there must be a newline
+ * before the close brace.
+ *
+ * Example of no newline before close
+ * struct mystring { int len;
+ * char str[]; };
+ * while (*(++ptr) != 0) { }
+ *
+ * Examples of newline before close
+ * void foo() {
+ * }
+ */
+static void newlines_brace_pair(Chunk *br_open);
+
+
+/**
+ * Put a empty line between the 'case' statement and the previous case colon
+ * or semicolon.
+ * Does not work with PAWN (?)
+ */
+static void newline_case(Chunk *start);
+
+
+static void newline_case_colon(Chunk *start);
+
+
+//! Put a blank line before a return statement, unless it is after an open brace
+static void newline_before_return(Chunk *start);
+
+
+/**
+ * Put a empty line after a return statement, unless it is followed by a
+ * close brace.
+ *
+ * May not work with PAWN
+ */
+static void newline_after_return(Chunk *start);
+
+
+static void blank_line_max(Chunk *pc, Option<unsigned> &opt);
+
+
+static iarf_e newline_template_option(Chunk *pc, iarf_e special, iarf_e base, iarf_e fallback);
+
+
+#define MARK_CHANGE() mark_change(__func__, __LINE__)
+
+
+static void mark_change(const char *func, size_t line)
+{
+ LOG_FUNC_ENTRY();
+
+ cpd.changes++;
+
+ if (cpd.pass_count == 0)
+ {
+ LOG_FMT(LCHANGE, "%s(%d): change %d on %s:%zu\n",
+ __func__, __LINE__, cpd.changes, func, line);
+ }
+} // mark_change
+
+
+static bool can_increase_nl(Chunk *nl)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = nl->GetPrevNc();
+
+ Chunk *pcmt = nl->GetPrev();
+ Chunk *next = nl->GetNext();
+
+ if (options::nl_squeeze_ifdef())
+ {
+ log_rule_B("nl_squeeze_ifdef");
+
+ Chunk *pp_start = chunk_get_pp_start(prev);
+
+ if ( pp_start != nullptr
+ && ( get_chunk_parent_type(pp_start) == CT_PP_IF
+ || get_chunk_parent_type(pp_start) == CT_PP_ELSE)
+ && ( pp_start->level > 0
+ || options::nl_squeeze_ifdef_top_level()))
+ {
+ log_rule_B("nl_squeeze_ifdef_top_level");
+ bool rv = ifdef_over_whole_file() && pp_start->flags.test(PCF_WF_IF);
+ LOG_FMT(LBLANKD, "%s(%d): nl_squeeze_ifdef %zu (prev) pp_lvl=%zu rv=%d\n",
+ __func__, __LINE__, nl->orig_line, nl->pp_level, rv);
+ return(rv);
+ }
+
+ if ( chunk_is_token(next, CT_PREPROC)
+ && ( get_chunk_parent_type(next) == CT_PP_ELSE
+ || get_chunk_parent_type(next) == CT_PP_ENDIF)
+ && ( next->level > 0
+ || options::nl_squeeze_ifdef_top_level()))
+ {
+ log_rule_B("nl_squeeze_ifdef_top_level");
+ bool rv = ifdef_over_whole_file() && next->flags.test(PCF_WF_ENDIF);
+ LOG_FMT(LBLANKD, "%s(%d): nl_squeeze_ifdef %zu (next) pp_lvl=%zu rv=%d\n",
+ __func__, __LINE__, nl->orig_line, nl->pp_level, rv);
+ return(rv);
+ }
+ }
+
+ if (chunk_is_token(next, CT_BRACE_CLOSE))
+ {
+ if ( options::nl_inside_namespace() > 0
+ && get_chunk_parent_type(next) == CT_NAMESPACE)
+ {
+ log_rule_B("nl_inside_namespace");
+ LOG_FMT(LBLANKD, "%s(%d): nl_inside_namespace %zu\n",
+ __func__, __LINE__, nl->orig_line);
+ return(true);
+ }
+
+ if ( options::nl_inside_empty_func() > 0
+ && chunk_is_token(prev, CT_BRACE_OPEN)
+ && ( get_chunk_parent_type(next) == CT_FUNC_DEF
+ || get_chunk_parent_type(next) == CT_FUNC_CLASS_DEF))
+ {
+ log_rule_B("nl_inside_empty_func");
+ LOG_FMT(LBLANKD, "%s(%d): nl_inside_empty_func %zu\n",
+ __func__, __LINE__, nl->orig_line);
+ return(true);
+ }
+
+ if (options::eat_blanks_before_close_brace())
+ {
+ log_rule_B("eat_blanks_before_close_brace");
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_before_close_brace %zu\n",
+ __func__, __LINE__, nl->orig_line);
+ return(false);
+ }
+ }
+
+ if (chunk_is_token(prev, CT_BRACE_CLOSE))
+ {
+ if ( options::nl_before_namespace()
+ && get_chunk_parent_type(prev) == CT_NAMESPACE)
+ {
+ log_rule_B("nl_before_namespace");
+ LOG_FMT(LBLANKD, "%s(%d): nl_before_namespace %zu\n",
+ __func__, __LINE__, nl->orig_line);
+ return(true);
+ }
+ }
+
+ if (chunk_is_token(prev, CT_BRACE_OPEN))
+ {
+ if ( options::nl_inside_namespace() > 0
+ && get_chunk_parent_type(prev) == CT_NAMESPACE)
+ {
+ log_rule_B("nl_inside_namespace");
+ LOG_FMT(LBLANKD, "%s(%d): nl_inside_namespace %zu\n",
+ __func__, __LINE__, nl->orig_line);
+ return(true);
+ }
+
+ if ( options::nl_inside_empty_func() > 0
+ && chunk_is_token(next, CT_BRACE_CLOSE)
+ && ( get_chunk_parent_type(prev) == CT_FUNC_DEF
+ || get_chunk_parent_type(prev) == CT_FUNC_CLASS_DEF))
+ {
+ log_rule_B("nl_inside_empty_func");
+ LOG_FMT(LBLANKD, "%s(%d): nl_inside_empty_func %zu\n",
+ __func__, __LINE__, nl->orig_line);
+ return(true);
+ }
+
+ if (options::eat_blanks_after_open_brace())
+ {
+ log_rule_B("eat_blanks_after_open_brace");
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_after_open_brace %zu\n",
+ __func__, __LINE__, nl->orig_line);
+ return(false);
+ }
+ }
+ log_rule_B("nl_start_of_file");
+
+ if ( !pcmt
+ && (options::nl_start_of_file() != IARF_IGNORE))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): SOF no prev %zu\n", __func__, __LINE__, nl->orig_line);
+ return(false);
+ }
+ log_rule_B("nl_end_of_file");
+
+ if ( next->IsNullChunk()
+ && (options::nl_end_of_file() != IARF_IGNORE))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): EOF no next %zu\n", __func__, __LINE__, nl->orig_line);
+ return(false);
+ }
+ return(true);
+} // can_increase_nl
+
+
+static void setup_newline_add(Chunk *prev, Chunk *nl, Chunk *next)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( prev == nullptr
+ || nl == nullptr
+ || next == nullptr)
+ {
+ return;
+ }
+ undo_one_liner(prev);
+
+ nl->orig_line = prev->orig_line;
+ nl->level = prev->level;
+ nl->pp_level = prev->pp_level;
+ nl->brace_level = prev->brace_level;
+ nl->pp_level = prev->pp_level;
+ nl->nl_count = 1;
+ nl->flags = (prev->flags & PCF_COPY_FLAGS) & ~PCF_IN_PREPROC;
+ nl->orig_col = prev->orig_col_end;
+ nl->column = prev->orig_col;
+
+ if ( prev->flags.test(PCF_IN_PREPROC)
+ && next->flags.test(PCF_IN_PREPROC))
+ {
+ chunk_flags_set(nl, PCF_IN_PREPROC);
+ }
+
+ if (nl->flags.test(PCF_IN_PREPROC))
+ {
+ set_chunk_type(nl, CT_NL_CONT);
+ nl->str = "\\\n";
+ }
+ else
+ {
+ set_chunk_type(nl, CT_NEWLINE);
+ nl->str = "\n";
+ }
+} // setup_newline_add
+
+
+void double_newline(Chunk *nl)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ if (nl != nullptr)
+ {
+ prev = nl->GetPrev();
+ }
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): add newline after ", __func__, __LINE__);
+
+ if (chunk_is_token(prev, CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LNEWLINE, "VBRACE_CLOSE ");
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "'%s' ", prev->Text());
+ }
+ LOG_FMT(LNEWLINE, "on line %zu", prev->orig_line);
+
+ if (!can_increase_nl(nl))
+ {
+ LOG_FMT(LNEWLINE, " - denied\n");
+ return;
+ }
+ LOG_FMT(LNEWLINE, " - done\n");
+
+ if (nl->nl_count != 2)
+ {
+ nl->nl_count = 2;
+ MARK_CHANGE();
+ }
+} // double_newline
+
+
+Chunk *newline_add_before(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk nl;
+ Chunk *prev = pc->GetPrevNvb();
+
+ if (chunk_is_newline(prev))
+ {
+ // Already has a newline before this chunk
+ return(prev);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): Text() '%s', on orig_line is %zu, orig_col is %zu, pc->column is %zu",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col, pc->column);
+ log_func_stack_inline(LNEWLINE);
+
+ setup_newline_add(prev, &nl, pc);
+ nl.orig_col = pc->orig_col;
+ nl.pp_level = pc->pp_level;
+ LOG_FMT(LNEWLINE, "%s(%d): nl.column is %zu\n",
+ __func__, __LINE__, nl.column);
+
+ MARK_CHANGE();
+ return(chunk_add_before(&nl, pc));
+} // newline_add_before
+
+
+Chunk *newline_force_before(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *nl = newline_add_before(pc);
+
+ if ( nl->IsNotNullChunk()
+ && nl->nl_count > 1)
+ {
+ nl->nl_count = 1;
+ MARK_CHANGE();
+ }
+ return(nl);
+} // newline_force_before
+
+
+Chunk *newline_add_after(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ Chunk *next = pc->GetNextNvb();
+
+ if (chunk_is_newline(next))
+ {
+ // Already has a newline after this chunk
+ return(next);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): '%s' on line %zu",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ log_func_stack_inline(LNEWLINE);
+
+ Chunk nl;
+
+ nl.orig_line = pc->orig_line;
+ nl.orig_col = pc->orig_col;
+ setup_newline_add(pc, &nl, next);
+
+ MARK_CHANGE();
+ // TO DO: check why the next statement is necessary
+ nl.orig_col = pc->orig_col;
+ nl.pp_level = pc->pp_level;
+ return(chunk_add_after(&nl, pc));
+} // newline_add_after
+
+
+Chunk *newline_force_after(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *nl = newline_add_after(pc); // add a newline
+
+ if ( nl->IsNotNullChunk()
+ && nl->nl_count > 1) // check if there are more than 1 newline
+ {
+ nl->nl_count = 1; // if so change the newline count back to 1
+ MARK_CHANGE();
+ }
+ return(nl);
+} // newline_force_after
+
+
+static void newline_end_newline(Chunk *br_close)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *next = br_close->GetNext();
+ Chunk nl;
+
+ if ( !chunk_is_newline(next)
+ && !next->IsComment())
+ {
+ nl.orig_line = br_close->orig_line;
+ nl.orig_col = br_close->orig_col;
+ nl.nl_count = 1;
+ nl.pp_level = 0;
+ nl.flags = (br_close->flags & PCF_COPY_FLAGS) & ~PCF_IN_PREPROC;
+
+ if ( br_close->flags.test(PCF_IN_PREPROC)
+ && next->IsNotNullChunk()
+ && next->flags.test(PCF_IN_PREPROC))
+ {
+ nl.flags |= PCF_IN_PREPROC;
+ }
+
+ if (nl.flags.test(PCF_IN_PREPROC))
+ {
+ set_chunk_type(&nl, CT_NL_CONT);
+ nl.str = "\\\n";
+ }
+ else
+ {
+ set_chunk_type(&nl, CT_NEWLINE);
+ nl.str = "\n";
+ }
+ MARK_CHANGE();
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline after '%s'\n",
+ __func__, __LINE__, br_close->orig_line, br_close->orig_col, br_close->Text());
+ chunk_add_after(&nl, br_close);
+ }
+} // newline_end_newline
+
+
+static void newline_min_after(Chunk *ref, size_t count, pcf_flag_e flag)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNEWLINE, "%s(%d): for '%s', at orig_line %zu, count is %zu,\n flag is %s:",
+ __func__, __LINE__, ref->Text(), ref->orig_line, count,
+ pcf_flags_str(flag).c_str());
+ log_func_stack_inline(LNEWLINE);
+
+ Chunk *pc = ref;
+
+ do
+ {
+ pc = pc->GetNext();
+ } while ( pc->IsNotNullChunk()
+ && !chunk_is_newline(pc));
+
+ if (pc->IsNotNullChunk()) // Coverity CID 76002
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): type is %s, orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), pc->orig_line, pc->orig_col);
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+
+ if ( next->IsComment()
+ && next->nl_count == 1
+ && pc->GetPrev()->IsComment())
+ {
+ newline_min_after(next, count, flag);
+ return;
+ }
+ chunk_flags_set(pc, flag);
+
+ if ( chunk_is_newline(pc)
+ && can_increase_nl(pc))
+ {
+ if (pc->nl_count < count)
+ {
+ pc->nl_count = count;
+ MARK_CHANGE();
+ }
+ }
+} // newline_min_after
+
+
+Chunk *newline_add_between(Chunk *start, Chunk *end)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( start == nullptr
+ || end == nullptr
+ || chunk_is_token(end, CT_IGNORED))
+ {
+ return(nullptr);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', type is %s, orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->type),
+ start->orig_line, start->orig_col);
+ LOG_FMT(LNEWLINE, "%s(%d): and end->Text() is '%s', orig_line is %zu, orig_col is %zu\n ",
+ __func__, __LINE__, end->Text(), end->orig_line, end->orig_col);
+ log_func_stack_inline(LNEWLINE);
+
+ // Back-up check for one-liners (should never be true!)
+ if (!one_liner_nl_ok(start))
+ {
+ return(nullptr);
+ }
+
+ /*
+ * Scan for a line break, if there is a line break between start and end
+ * we won't add another one
+ */
+ for (Chunk *pc = start; pc != end; pc = pc->GetNext())
+ {
+ if (chunk_is_newline(pc))
+ {
+ return(pc);
+ }
+ }
+
+ /*
+ * If the second one is a brace open, then check to see
+ * if a comment + newline follows
+ */
+ if (chunk_is_token(end, CT_BRACE_OPEN))
+ {
+ Chunk *pc = end->GetNext();
+
+ if (pc->IsComment())
+ {
+ pc = pc->GetNext();
+
+ if (chunk_is_newline(pc))
+ {
+ // are there some more (comment + newline)s ?
+ Chunk *pc1 = end->GetNextNcNnl();
+
+ if (!chunk_is_newline(pc1))
+ {
+ // yes, go back
+ Chunk *pc2 = pc1->GetPrev();
+ pc = pc2;
+ }
+ }
+
+ if (end == pc)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): pc1 and pc are identical\n",
+ __func__, __LINE__);
+ }
+ else
+ {
+ // Move the open brace to after the newline
+ chunk_move_after(end, pc);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__);
+ newline_add_after(end);
+ return(pc);
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__);
+ }
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__);
+ }
+ Chunk *tmp = newline_add_before(end);
+
+ return(tmp);
+} // newline_add_between
+
+
+void newline_del_between(Chunk *start, Chunk *end)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, start->Text(), start->orig_line, start->orig_col);
+ LOG_FMT(LNEWLINE, "%s(%d): and end->Text() is '%s', orig_line is %zu, orig_col is %zu: preproc=%c/%c\n",
+ __func__, __LINE__, end->Text(), end->orig_line, end->orig_col,
+ start->flags.test(PCF_IN_PREPROC) ? 'y' : 'n',
+ end->flags.test(PCF_IN_PREPROC) ? 'y' : 'n');
+ log_func_stack_inline(LNEWLINE);
+
+ // Can't remove anything if the preproc status differs
+ if (!chunk_same_preproc(start, end))
+ {
+ return;
+ }
+ Chunk *pc = start;
+ bool start_removed = false;
+
+ do
+ {
+ Chunk *next = pc->GetNext();
+
+ if (chunk_is_newline(pc))
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( ( !prev->IsComment()
+ && !next->IsComment())
+ || chunk_is_newline(prev)
+ || chunk_is_newline(next))
+ {
+ if (chunk_safe_to_del_nl(pc))
+ {
+ if (pc == start)
+ {
+ start_removed = true;
+ }
+ chunk_del(pc);
+ MARK_CHANGE();
+
+ if (prev != nullptr)
+ {
+ align_to_column(next, prev->column + space_col_align(prev, next));
+ }
+ }
+ }
+ else
+ {
+ if (pc->nl_count > 1)
+ {
+ pc->nl_count = 1;
+ MARK_CHANGE();
+ }
+ }
+ }
+ pc = next;
+ } while (pc != end);
+
+ if ( !start_removed
+ && chunk_is_str(end, "{")
+ && ( chunk_is_str(start, ")")
+ || chunk_is_token(start, CT_DO)
+ || chunk_is_token(start, CT_ELSE)))
+ {
+ chunk_move_after(end, start);
+ }
+} // newline_del_between
+
+
+void newlines_sparens()
+{
+ LOG_FUNC_ENTRY();
+
+ //Chunk *sparen_open;
+
+ for (Chunk *sparen_open = Chunk::GetHead()->GetNextType(CT_SPAREN_OPEN, ANY_LEVEL);
+ sparen_open->IsNotNullChunk();
+ sparen_open = sparen_open->GetNextType(CT_SPAREN_OPEN, ANY_LEVEL))
+ {
+ Chunk *sparen_close = sparen_open->GetNextType(CT_SPAREN_CLOSE, sparen_open->level);
+
+ if (sparen_close->IsNullChunk())
+ {
+ continue;
+ }
+ Chunk *sparen_content_start = sparen_open->GetNextNnl();
+ Chunk *sparen_content_end = sparen_close->GetPrevNnl();
+ bool is_multiline = (
+ sparen_content_start != sparen_content_end
+ && !are_chunks_in_same_line(sparen_content_start, sparen_content_end));
+
+ // Add a newline after '(' if an if/for/while/switch condition spans multiple lines,
+ // as e.g. required by the ROS 2 development style guidelines:
+ // https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#open-versus-cuddled-braces
+ if (is_multiline)
+ {
+ log_rule_B("nl_multi_line_sparen_open");
+ newline_iarf(sparen_open, options::nl_multi_line_sparen_open());
+ }
+
+ // Add a newline before ')' if an if/for/while/switch condition spans multiple lines. Overrides nl_before_if_closing_paren if both are specified.
+ if ( is_multiline
+ && options::nl_multi_line_sparen_close() != IARF_IGNORE)
+ {
+ log_rule_B("nl_multi_line_sparen_close");
+ newline_iarf(sparen_content_end, options::nl_multi_line_sparen_close());
+ }
+ else
+ {
+ // add/remove trailing newline in an if condition
+ Chunk *ctrl_structure = sparen_open->GetPrevNcNnl();
+
+ if ( chunk_is_token(ctrl_structure, CT_IF)
+ || chunk_is_token(ctrl_structure, CT_ELSEIF))
+ {
+ log_rule_B("nl_before_if_closing_paren");
+ newline_iarf_pair(sparen_content_end, sparen_close, options::nl_before_if_closing_paren());
+ }
+ }
+ }
+} // newlines_sparens
+
+
+static bool newlines_if_for_while_switch(Chunk *start, iarf_e nl_opt)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_define_macro");
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return(false);
+ }
+ bool retval = false;
+ Chunk *pc = start->GetNextNcNnl();
+
+ if (chunk_is_token(pc, CT_SPAREN_OPEN))
+ {
+ Chunk *close_paren = pc->GetNextType(CT_SPAREN_CLOSE, pc->level);
+ Chunk *brace_open = close_paren->GetNextNcNnl();
+
+ if ( ( chunk_is_token(brace_open, CT_BRACE_OPEN)
+ || chunk_is_token(brace_open, CT_VBRACE_OPEN))
+ && one_liner_nl_ok(brace_open))
+ {
+ log_rule_B("nl_multi_line_cond");
+
+ if (options::nl_multi_line_cond())
+ {
+ while ((pc = pc->GetNext()) != close_paren)
+ {
+ if (chunk_is_newline(pc))
+ {
+ nl_opt = IARF_ADD;
+ break;
+ }
+ }
+ }
+
+ if (chunk_is_token(brace_open, CT_VBRACE_OPEN))
+ {
+ // Can only add - we don't want to create a one-line here
+ if (nl_opt & IARF_ADD)
+ {
+ newline_iarf_pair(close_paren, brace_open->GetNextNcNnl(), nl_opt);
+ pc = brace_open->GetNextType(CT_VBRACE_CLOSE, brace_open->level);
+
+ if ( !chunk_is_newline(pc->GetPrevNc())
+ && !chunk_is_newline(pc->GetNextNc()))
+ {
+ newline_add_after(pc);
+ retval = true;
+ }
+ }
+ }
+ else
+ {
+ newline_iarf_pair(close_paren, brace_open, nl_opt);
+ Chunk *next = brace_open->GetNextNcNnl();
+
+ if (brace_open->type != next->type) // Issue #2836
+ {
+ newline_add_between(brace_open, brace_open->GetNextNcNnl());
+ }
+ // Make sure nothing is cuddled with the closing brace
+ pc = brace_open->GetNextType(CT_BRACE_CLOSE, brace_open->level);
+ newline_add_between(pc, pc->GetNextNcNnlNet());
+ retval = true;
+ }
+ }
+ }
+ return(retval);
+} // newlines_if_for_while_switch
+
+
+static void newlines_if_for_while_switch_pre_blank_lines(Chunk *start, iarf_e nl_opt)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', type is %s, orig_line is %zu, orig_column is %zu\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->type), start->orig_line, start->orig_col);
+
+ log_rule_B("nl_define_macro");
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+
+ /*
+ * look backwards until we find
+ * open brace (don't add or remove)
+ * 2 newlines in a row (don't add)
+ * something else (don't remove)
+ */
+ for (Chunk *pc = start->GetPrev(); pc != nullptr && pc->IsNotNullChunk(); pc = pc->GetPrev())
+ {
+ size_t level = start->level;
+ bool do_add = (nl_opt & IARF_ADD) != IARF_IGNORE; // forcing value to bool
+ Chunk *last_nl = nullptr;
+
+ if (chunk_is_newline(pc))
+ {
+ last_nl = pc;
+
+ // if we found 2 or more in a row
+ if ( pc->nl_count > 1
+ || chunk_is_newline(pc->GetPrevNvb()))
+ {
+ // need to remove
+ if ( (nl_opt & IARF_REMOVE)
+ && !pc->flags.test(PCF_VAR_DEF))
+ {
+ // if we're also adding, take care of that here
+ size_t nl_count = do_add ? 2 : 1;
+
+ if (nl_count != pc->nl_count)
+ {
+ pc->nl_count = nl_count;
+ MARK_CHANGE();
+ }
+ Chunk *prev;
+
+ // can keep using pc because anything other than newline stops loop, and we delete if newline
+ while (chunk_is_newline(prev = pc->GetPrevNvb()))
+ {
+ // Make sure we don't combine a preproc and non-preproc
+ if (!chunk_safe_to_del_nl(prev))
+ {
+ break;
+ }
+ chunk_del(prev);
+ MARK_CHANGE();
+ }
+ }
+ return;
+ }
+ }
+ else if ( chunk_is_opening_brace(pc)
+ || pc->level < level)
+ {
+ return;
+ }
+ else if (pc->IsComment())
+ {
+ // vbrace close is ok because it won't go into output, so we should skip it
+ last_nl = nullptr;
+ continue;
+ }
+ else
+ {
+ if ( chunk_is_token(pc, CT_CASE_COLON)
+ && options::nl_before_ignore_after_case())
+ {
+ return;
+ }
+
+ if (do_add) // we found something previously besides a comment or a new line
+ {
+ // if we have run across a newline
+ if (last_nl != nullptr)
+ {
+ if (last_nl->nl_count < 2)
+ {
+ double_newline(last_nl);
+ }
+ }
+ else
+ {
+ Chunk *next;
+
+ // we didn't run into a newline, so we need to add one
+ if ( ((next = pc->GetNext())->IsNotNullChunk())
+ && next->IsComment())
+ {
+ pc = next;
+ }
+
+ if ((last_nl = newline_add_after(pc))->IsNotNullChunk())
+ {
+ double_newline(last_nl);
+ }
+ }
+ }
+ return;
+ }
+ }
+} // newlines_if_for_while_switch_pre_blank_lines
+
+
+static void blank_line_set(Chunk *pc, Option<unsigned> &opt)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return;
+ }
+ const unsigned optval = opt();
+
+ if ( (optval > 0)
+ && (pc->nl_count != optval))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): do_blank_lines: %s set line %zu to %u\n",
+ __func__, __LINE__, opt.name(), pc->orig_line, optval);
+ pc->nl_count = optval;
+ MARK_CHANGE();
+ }
+} // blank_line_set
+
+
+bool do_it_newlines_func_pre_blank_lines(Chunk *last_nl, E_Token start_type)
+{
+ LOG_FUNC_ENTRY();
+
+ if (last_nl == nullptr)
+ {
+ return(false);
+ }
+ LOG_FMT(LNLFUNCT, "%s(%d): orig_line is %zu, orig_col is %zu, type is %s, Text() is '%s'\n",
+ __func__, __LINE__,
+ last_nl->orig_line, last_nl->orig_col, get_token_name(last_nl->type), last_nl->Text());
+
+ switch (start_type)
+ {
+ case CT_FUNC_CLASS_DEF:
+ {
+ log_rule_B("nl_before_func_class_def");
+ bool diff = options::nl_before_func_class_def() <= last_nl->nl_count;
+ LOG_FMT(LNLFUNCT, "%s(%d): is %s\n",
+ __func__, __LINE__, diff ? "TRUE" : "FALSE");
+
+ log_rule_B("nl_before_func_class_def");
+
+ if (options::nl_before_func_class_def() != last_nl->nl_count)
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n",
+ __func__, __LINE__, options::nl_before_func_class_def());
+ blank_line_set(last_nl, options::nl_before_func_class_def);
+ }
+ return(diff);
+ }
+
+ case CT_FUNC_CLASS_PROTO:
+ {
+ log_rule_B("nl_before_func_class_proto");
+ bool diff = options::nl_before_func_class_proto() <= last_nl->nl_count;
+ LOG_FMT(LNLFUNCT, "%s(%d): is %s\n",
+ __func__, __LINE__, diff ? "TRUE" : "FALSE");
+
+ log_rule_B("nl_before_func_class_proto");
+
+ if (options::nl_before_func_class_proto() != last_nl->nl_count)
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n",
+ __func__, __LINE__, options::nl_before_func_class_proto());
+ blank_line_set(last_nl, options::nl_before_func_class_proto);
+ }
+ return(diff);
+ }
+
+ case CT_FUNC_DEF:
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): nl_before_func_body_def() is %u, last_nl->nl_count is %zu\n",
+ __func__, __LINE__, options::nl_before_func_body_def(), last_nl->nl_count);
+ log_rule_B("nl_before_func_body_def");
+ bool diff = options::nl_before_func_body_def() <= last_nl->nl_count;
+ LOG_FMT(LNLFUNCT, "%s(%d): is %s\n",
+ __func__, __LINE__, diff ? "TRUE" : "FALSE");
+
+ log_rule_B("nl_before_func_body_def");
+
+ if (options::nl_before_func_body_def() != last_nl->nl_count)
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n",
+ __func__, __LINE__, options::nl_before_func_body_def());
+ log_rule_B("nl_before_func_body_def");
+ blank_line_set(last_nl, options::nl_before_func_body_def);
+ }
+ LOG_FMT(LNLFUNCT, "%s(%d): nl_before_func_body_def() is %u, last_nl->nl_count is %zu\n",
+ __func__, __LINE__, options::nl_before_func_body_def(), last_nl->nl_count);
+ return(diff);
+ }
+
+ case CT_FUNC_PROTO:
+ {
+ log_rule_B("nl_before_func_body_proto");
+ bool diff = options::nl_before_func_body_proto() <= last_nl->nl_count;
+ LOG_FMT(LNLFUNCT, "%s(%d): is %s\n",
+ __func__, __LINE__, diff ? "TRUE" : "FALSE");
+
+ log_rule_B("nl_before_func_body_proto");
+
+ if (options::nl_before_func_body_proto() != last_nl->nl_count)
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s) to %u\n",
+ __func__, __LINE__, options::nl_before_func_body_proto());
+ log_rule_B("nl_before_func_body_proto");
+ blank_line_set(last_nl, options::nl_before_func_body_proto);
+ }
+ return(diff);
+ }
+
+ default:
+ {
+ LOG_FMT(LERR, "%s(%d): setting to blank line(s) at line %zu not possible\n",
+ __func__, __LINE__, last_nl->orig_line);
+ return(false);
+ }
+ } // switch
+} // do_it_newlines_func_pre_blank_lines
+
+
+static void newlines_func_pre_blank_lines(Chunk *start, E_Token start_type)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_before_func_class_def");
+ log_rule_B("nl_before_func_class_proto");
+ log_rule_B("nl_before_func_body_def");
+ log_rule_B("nl_before_func_body_proto");
+
+ if ( start == nullptr
+ || ( ( start_type != CT_FUNC_CLASS_DEF
+ || options::nl_before_func_class_def() == 0)
+ && ( start_type != CT_FUNC_CLASS_PROTO
+ || options::nl_before_func_class_proto() == 0)
+ && ( start_type != CT_FUNC_DEF
+ || options::nl_before_func_body_def() == 0)
+ && ( start_type != CT_FUNC_PROTO
+ || options::nl_before_func_body_proto() == 0)))
+ {
+ return;
+ }
+ LOG_FMT(LNLFUNCT, "%s(%d): set blank line(s): for <NL> at line %zu, column %zu, start_type is %s\n",
+ __func__, __LINE__, start->orig_line, start->orig_col, get_token_name(start_type));
+ LOG_FMT(LNLFUNCT, "%s(%d): BEGIN set blank line(s) for '%s' at line %zu\n",
+ __func__, __LINE__, start->Text(), start->orig_line);
+ /*
+ * look backwards until we find:
+ * - open brace (don't add or remove)
+ * - two newlines in a row (don't add)
+ * - a destructor
+ * - something else (don't remove)
+ */
+ Chunk *pc = nullptr;
+ Chunk *last_nl = nullptr;
+ Chunk *last_comment = nullptr;
+ size_t first_line = start->orig_line;
+
+ for (pc = start->GetPrev(); pc != nullptr && pc->IsNotNullChunk(); pc = pc->GetPrev())
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): orig_line is %zu, orig_col is %zu, type is %s, Text() is '%s', nl_count is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, get_token_name(pc->type), pc->Text(), pc->nl_count);
+
+ if (chunk_is_newline(pc))
+ {
+ last_nl = pc;
+ LOG_FMT(LNLFUNCT, "%s(%d): <chunk_is_newline> found at line %zu, column %zu, nl_count is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->nl_count);
+ LOG_FMT(LNLFUNCT, "%s(%d): last_nl set to %zu\n",
+ __func__, __LINE__, last_nl->orig_line);
+ bool break_now = false;
+
+ if (pc->nl_count > 1)
+ {
+ break_now = do_it_newlines_func_pre_blank_lines(last_nl, start_type);
+ LOG_FMT(LNLFUNCT, "%s(%d): break_now is %s\n",
+ __func__, __LINE__, break_now ? "TRUE" : "FALSE");
+ }
+
+ if (break_now)
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else if (pc->IsComment())
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): <chunk_is_comment> found at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+
+ if ( ( pc->orig_line < first_line
+ && ((first_line - pc->orig_line
+ - (chunk_is_token(pc, CT_COMMENT_MULTI) ? pc->nl_count : 0))) < 2)
+ || ( last_comment != nullptr
+ && chunk_is_token(pc, CT_COMMENT_CPP) // combine only cpp comments
+ && chunk_is_token(last_comment, pc->type) // don't mix comment types
+ && last_comment->orig_line > pc->orig_line
+ && (last_comment->orig_line - pc->orig_line) < 2))
+ {
+ last_comment = pc;
+ continue;
+ }
+ bool break_now = do_it_newlines_func_pre_blank_lines(last_nl, start_type);
+ LOG_FMT(LNLFUNCT, "%s(%d): break_now is %s\n",
+ __func__, __LINE__, break_now ? "TRUE" : "FALSE");
+ continue;
+ }
+ else if ( chunk_is_token(pc, CT_DESTRUCTOR)
+ || chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_TEMPLATE)
+ || chunk_is_token(pc, CT_QUALIFIER)
+ || chunk_is_token(pc, CT_PTR_TYPE)
+ || chunk_is_token(pc, CT_BYREF) // Issue #2163
+ || chunk_is_token(pc, CT_DC_MEMBER)
+ || chunk_is_token(pc, CT_EXTERN)
+ || ( chunk_is_token(pc, CT_STRING)
+ && get_chunk_parent_type(pc) == CT_EXTERN))
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): first_line set to %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ first_line = pc->orig_line;
+ continue;
+ }
+ else if ( chunk_is_token(pc, CT_ANGLE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_TEMPLATE)
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d):\n", __func__, __LINE__);
+ // skip template stuff to add newlines before it
+ pc = chunk_skip_to_match_rev(pc);
+
+ if (pc != nullptr)
+ {
+ first_line = pc->orig_line;
+ }
+ continue;
+ }
+ else
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): else ==================================\n",
+ __func__, __LINE__);
+ bool break_now = do_it_newlines_func_pre_blank_lines(last_nl, start_type);
+ LOG_FMT(LNLFUNCT, "%s(%d): break_now is %s\n",
+ __func__, __LINE__, break_now ? "TRUE" : "FALSE");
+ break;
+ }
+ }
+} // newlines_func_pre_blank_lines
+
+
+static Chunk *get_closing_brace(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc;
+ size_t level = start->level;
+
+ for (pc = start; (pc = pc->GetNext())->IsNotNullChunk();)
+ {
+ if ( ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE))
+ && pc->level == level)
+ {
+ return(pc);
+ }
+
+ // for some reason, we can have newlines between if and opening brace that are lower level than either
+ if ( !chunk_is_newline(pc)
+ && pc->level < level)
+ {
+ return(nullptr);
+ }
+ }
+
+ return(nullptr);
+} // get_closing_brace
+
+
+static void remove_next_newlines(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *next;
+
+ while ((next = start->GetNext())->IsNotNullChunk())
+ {
+ if ( chunk_is_newline(next)
+ && chunk_safe_to_del_nl(next))
+ {
+ chunk_del(next);
+ MARK_CHANGE();
+ }
+ else if (next->IsVBrace())
+ {
+ start = next;
+ }
+ else
+ {
+ break;
+ }
+ }
+} // remove_next_newlines
+
+
+static void newlines_if_for_while_switch_post_blank_lines(Chunk *start, iarf_e nl_opt)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev;
+
+ LOG_FMT(LNEWLINE, "%s(%d): start->Text() is '%s', type is %s, orig_line is %zu, orig_column is %zu\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->type), start->orig_line, start->orig_col);
+
+ log_rule_B("nl_define_macro");
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+ Chunk *pc = get_closing_brace(start);
+
+ // first find ending brace
+ if (pc == nullptr)
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type is %s, orig_line is %zu, orig_column is %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type), pc->orig_line, pc->orig_col);
+
+ /*
+ * if we're dealing with an if, we actually want to add or remove
+ * blank lines after any else
+ */
+ if (chunk_is_token(start, CT_IF))
+ {
+ Chunk *next;
+
+ while (true)
+ {
+ next = pc->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && ( chunk_is_token(next, CT_ELSE)
+ || chunk_is_token(next, CT_ELSEIF)))
+ {
+ // point to the closing brace of the else
+ if ((pc = get_closing_brace(next)) == nullptr)
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type), pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ /*
+ * if we're dealing with a do/while, we actually want to add or
+ * remove blank lines after while and its condition
+ */
+ if (chunk_is_token(start, CT_DO))
+ {
+ // point to the next semicolon
+ if ((pc = pc->GetNextType(CT_SEMICOLON, start->level))->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type), pc->orig_line, pc->orig_col);
+ }
+ bool isVBrace = (chunk_is_token(pc, CT_VBRACE_CLOSE));
+
+ if (isVBrace)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): isVBrace is TRUE\n", __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): isVBrace is FALSE\n", __func__, __LINE__);
+ }
+
+ if ((prev = pc->GetPrevNvb())->IsNullChunk())
+ {
+ return;
+ }
+ bool have_pre_vbrace_nl = isVBrace && chunk_is_newline(prev);
+
+ if (have_pre_vbrace_nl)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is TRUE\n", __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is FALSE\n", __func__, __LINE__);
+ }
+
+ if (nl_opt & IARF_REMOVE)
+ {
+ Chunk *next;
+
+ // if chunk before is a vbrace, remove any newlines after it
+ if (have_pre_vbrace_nl)
+ {
+ if (prev->nl_count != 1)
+ {
+ prev->nl_count = 1;
+ MARK_CHANGE();
+ }
+ remove_next_newlines(pc);
+ }
+ else if ( (chunk_is_newline(next = pc->GetNextNvb()))
+ && !next->flags.test(PCF_VAR_DEF))
+ {
+ // otherwise just deal with newlines after brace
+ if (next->nl_count != 1)
+ {
+ next->nl_count = 1;
+ MARK_CHANGE();
+ }
+ remove_next_newlines(next);
+ }
+ }
+
+ // may have a newline before and after vbrace
+ // don't do anything with it if the next non newline chunk is a closing brace
+ if (nl_opt & IARF_ADD)
+ {
+ Chunk *next = pc->GetNextNnl();
+
+ do
+ {
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+
+ if (chunk_is_not_token(next, CT_VBRACE_CLOSE))
+ {
+ break;
+ }
+ next = next->GetNextNnl();
+ } while (true);
+
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->type), next->orig_line, next->orig_col);
+
+ if (chunk_is_not_token(next, CT_BRACE_CLOSE))
+ {
+ // if vbrace, have to check before and after
+ // if chunk before vbrace, check its count
+ size_t nl_count = have_pre_vbrace_nl ? prev->nl_count : 0;
+ LOG_FMT(LNEWLINE, "%s(%d): nl_count %zu\n", __func__, __LINE__, nl_count);
+
+ if (chunk_is_newline(next = pc->GetNextNvb()))
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->type), next->orig_line, next->orig_col);
+ nl_count += next->nl_count;
+ LOG_FMT(LNEWLINE, "%s(%d): nl_count is %zu\n", __func__, __LINE__, nl_count);
+ }
+
+ // if we have no newlines, add one and make it double
+ if (nl_count == 0)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): nl_count is 0\n", __func__, __LINE__);
+
+ if ( ((next = pc->GetNext())->IsNotNullChunk())
+ && next->IsComment())
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->type), next->orig_line, next->orig_col);
+ pc = next;
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type), pc->orig_line, pc->orig_col);
+ }
+
+ if ((next = newline_add_after(pc))->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->type), next->orig_line, next->orig_col);
+ double_newline(next);
+ }
+ else if (nl_count == 1) // if we don't have enough newlines
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): nl_count is 1\n", __func__, __LINE__);
+
+ // if we have a preceeding vbrace, add one after it
+ if (have_pre_vbrace_nl)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is TRUE\n", __func__, __LINE__);
+ next = newline_add_after(pc);
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->type), next->orig_line, next->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): have_pre_vbrace_nl is FALSE\n", __func__, __LINE__);
+ prev = next->GetPrevNnl();
+ LOG_FMT(LNEWLINE, "%s(%d): prev->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, prev->Text(), get_token_name(prev->type), prev->orig_line, prev->orig_col);
+ pc = next->GetNextNl();
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type), pc->orig_line, pc->orig_col);
+ Chunk *pc2 = pc->GetNext();
+
+ if (pc2->IsNotNullChunk())
+ {
+ pc = pc2;
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig_line %zu, orig_column %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type), pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): no next found: <EOF>\n", __func__, __LINE__);
+ }
+ log_rule_B("nl_squeeze_ifdef");
+
+ if ( chunk_is_token(pc, CT_PREPROC)
+ && get_chunk_parent_type(pc) == CT_PP_ENDIF
+ && options::nl_squeeze_ifdef())
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): cannot add newline after orig_line %zu due to nl_squeeze_ifdef\n",
+ __func__, __LINE__, prev->orig_line);
+ }
+ else
+ {
+ // make newline after double
+ LOG_FMT(LNEWLINE, "%s(%d): call double_newline\n", __func__, __LINE__);
+ double_newline(next);
+ }
+ }
+ }
+ }
+ }
+} // newlines_if_for_while_switch_post_blank_lines
+
+
+static void newlines_struct_union(Chunk *start, iarf_e nl_opt, bool leave_trailing)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_define_macro");
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+ /*
+ * step past any junk between the keyword and the open brace
+ * Quit if we hit a semicolon or '=', which are not expected.
+ */
+ size_t level = start->level;
+ Chunk *pc = start->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= level)
+ {
+ if ( pc->level == level
+ && ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_ASSIGN)))
+ {
+ break;
+ }
+ start = pc;
+ pc = pc->GetNextNcNnl();
+ }
+
+ // If we hit a brace open, then we need to toy with the newlines
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ // Skip over embedded C comments
+ Chunk *next = pc->GetNext();
+
+ while (chunk_is_token(next, CT_COMMENT))
+ {
+ next = next->GetNext();
+ }
+
+ if ( leave_trailing
+ && !next->IsComment()
+ && !chunk_is_newline(next))
+ {
+ nl_opt = IARF_IGNORE;
+ }
+ newline_iarf_pair(start, pc, nl_opt);
+ }
+} // newlines_struct_union
+
+
+// enum {
+// enum class angle_state_e : unsigned int {
+// enum-key attr(optional) identifier(optional) enum-base(optional) { enumerator-list(optional) }
+// enum-key attr(optional) nested-name-specifier(optional) identifier enum-base(optional) ; TODO
+// enum-key - one of enum, enum class or enum struct TODO
+// identifier - the name of the enumeration that's being declared
+// enum-base(C++11) - colon (:), followed by a type-specifier-seq
+// enumerator-list - comma-separated list of enumerator definitions
+static void newlines_enum(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_define_macro");
+
+ if ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro())
+ {
+ return;
+ }
+ // look for 'enum class'
+ Chunk *pcClass = start->GetNextNcNnl();
+
+ if (chunk_is_token(pcClass, CT_ENUM_CLASS))
+ {
+ log_rule_B("nl_enum_class");
+ newline_iarf_pair(start, pcClass, options::nl_enum_class());
+ // look for 'identifier'/ 'type'
+ Chunk *pcType = pcClass->GetNextNcNnl();
+
+ if (chunk_is_token(pcType, CT_TYPE))
+ {
+ log_rule_B("nl_enum_class_identifier");
+ newline_iarf_pair(pcClass, pcType, options::nl_enum_class_identifier());
+ // look for ':'
+ Chunk *pcColon = pcType->GetNextNcNnl();
+
+ if (chunk_is_token(pcColon, CT_BIT_COLON))
+ {
+ log_rule_B("nl_enum_identifier_colon");
+ newline_iarf_pair(pcType, pcColon, options::nl_enum_identifier_colon());
+ // look for 'type' i.e. unsigned
+ Chunk *pcType1 = pcColon->GetNextNcNnl();
+
+ if (chunk_is_token(pcType1, CT_TYPE))
+ {
+ log_rule_B("nl_enum_colon_type");
+ newline_iarf_pair(pcColon, pcType1, options::nl_enum_colon_type());
+ // look for 'type' i.e. int
+ Chunk *pcType2 = pcType1->GetNextNcNnl();
+
+ if (chunk_is_token(pcType2, CT_TYPE))
+ {
+ log_rule_B("nl_enum_colon_type");
+ newline_iarf_pair(pcType1, pcType2, options::nl_enum_colon_type());
+ }
+ }
+ }
+ }
+ }
+ /*
+ * step past any junk between the keyword and the open brace
+ * Quit if we hit a semicolon or '=', which are not expected.
+ */
+ size_t level = start->level;
+ Chunk *pc = start->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->level >= level)
+ {
+ if ( pc->level == level
+ && ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_semicolon(pc)
+ || chunk_is_token(pc, CT_ASSIGN)))
+ {
+ break;
+ }
+ start = pc;
+ pc = pc->GetNextNcNnl();
+ }
+
+ // If we hit a brace open, then we need to toy with the newlines
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ // Skip over embedded C comments
+ Chunk *next = pc->GetNext();
+
+ while (chunk_is_token(next, CT_COMMENT))
+ {
+ next = next->GetNext();
+ }
+ iarf_e nl_opt;
+
+ if ( !next->IsComment()
+ && !chunk_is_newline(next))
+ {
+ nl_opt = IARF_IGNORE;
+ }
+ else
+ {
+ log_rule_B("nl_enum_brace");
+ nl_opt = options::nl_enum_brace();
+ }
+ newline_iarf_pair(start, pc, nl_opt);
+ }
+} // newlines_enum
+
+
+// namespace {
+// namespace word {
+// namespace type::word {
+static void newlines_namespace(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_namespace_brace");
+
+ // Add or remove newline between 'namespace' and 'BRACE_OPEN'
+ log_rule_B("nl_define_macro");
+ iarf_e nl_opt = options::nl_namespace_brace();
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+ Chunk *braceOpen = start->GetNextType(CT_BRACE_OPEN, start->level);
+
+ LOG_FMT(LNEWLINE, "%s(%d): braceOpen->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, braceOpen->orig_line, braceOpen->orig_col, braceOpen->Text());
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, braceOpen->flags);
+
+ if (braceOpen->flags.test(PCF_ONE_LINER))
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): is one_liner\n",
+ __func__, __LINE__);
+ return;
+ }
+ Chunk *beforeBrace = braceOpen->GetPrev();
+
+ LOG_FMT(LNEWLINE, "%s(%d): beforeBrace->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, beforeBrace->orig_line, beforeBrace->orig_col, beforeBrace->Text());
+ // 'namespace' 'BRACE_OPEN'
+ newline_iarf_pair(beforeBrace, braceOpen, nl_opt);
+} // newlines_namespace
+
+
+static void newlines_cuddle_uncuddle(Chunk *start, iarf_e nl_opt)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_define_macro");
+
+ if ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro())
+ {
+ return;
+ }
+ Chunk *br_close = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (chunk_is_token(br_close, CT_BRACE_CLOSE))
+ {
+ newline_iarf_pair(br_close, start, nl_opt);
+ }
+} // newlines_cuddle_uncuddle
+
+
+static void newlines_do_else(Chunk *start, iarf_e nl_opt)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_define_macro");
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+ Chunk *next = start->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && ( chunk_is_token(next, CT_BRACE_OPEN)
+ || chunk_is_token(next, CT_VBRACE_OPEN)))
+ {
+ if (!one_liner_nl_ok(next))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): a new line may NOT be added\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): a new line may be added\n", __func__, __LINE__);
+
+ if (chunk_is_token(next, CT_VBRACE_OPEN))
+ {
+ // Can only add - we don't want to create a one-line here
+ if (nl_opt & IARF_ADD)
+ {
+ newline_iarf_pair(start, next->GetNextNcNnl(), nl_opt);
+ Chunk *tmp = next->GetNextType(CT_VBRACE_CLOSE, next->level);
+
+ if ( !chunk_is_newline(tmp->GetNextNc())
+ && !chunk_is_newline(tmp->GetPrevNc()))
+ {
+ newline_add_after(tmp);
+ }
+ }
+ }
+ else
+ {
+ newline_iarf_pair(start, next, nl_opt);
+ newline_add_between(next, next->GetNextNcNnl());
+ }
+ }
+} // newlines_do_else
+
+
+static bool is_var_def(Chunk *pc, Chunk *next)
+{
+ if ( chunk_is_token(pc, CT_DECLTYPE)
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ // If current token starts a decltype expression, skip it
+ next = chunk_skip_to_match(next);
+ next = next->GetNextNcNnl();
+ }
+ else if (!chunk_is_type(pc))
+ {
+ // Otherwise, if the current token is not a type --> not a declaration
+ return(false);
+ }
+ else if (chunk_is_token(next, CT_DC_MEMBER))
+ {
+ // If next token is CT_DC_MEMBER, skip it
+ next = chunk_skip_dc_member(next);
+ }
+ else if (chunk_is_token(next, CT_ANGLE_OPEN))
+ {
+ // If we have a template type, skip it
+ next = chunk_skip_to_match(next);
+ next = next->GetNextNcNnl();
+ }
+ bool is = ( ( chunk_is_type(next)
+ && get_chunk_parent_type(next) != CT_FUNC_DEF) // Issue #2639
+ || chunk_is_token(next, CT_WORD)
+ || chunk_is_token(next, CT_FUNC_CTOR_VAR));
+
+ return(is);
+} // is_var_def
+
+
+// Put newline(s) before and/or after a block of variable definitions
+static Chunk *newline_def_blk(Chunk *start, bool fn_top)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279
+
+ // can't be any variable definitions in a "= {" block
+ if (chunk_is_token(prev, CT_ASSIGN))
+ {
+ Chunk *tmp = start->GetNextType(CT_BRACE_CLOSE, start->level);
+ return(tmp->GetNextNcNnl());
+ }
+ Chunk *pc = start->GetNext();
+
+ bool did_this_line = false;
+ bool first_var_blk = true;
+ bool var_blk = false;
+
+ while ( pc->IsNotNullChunk()
+ && ( pc->level >= start->level
+ || pc->level == 0))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ Chunk *next_pc = pc->GetNext();
+
+ if (chunk_is_token(next_pc, CT_DC_MEMBER))
+ {
+ // If next_pc token is CT_DC_MEMBER, skip it
+ pc = chunk_skip_dc_member(pc);
+ }
+
+ if (pc->IsComment())
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+
+ // process nested braces
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ pc = newline_def_blk(pc, false);
+ continue;
+ }
+
+ // Done with this brace set?
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ pc = pc->GetNext();
+ break;
+ }
+
+ if (pc->IsPreproc())
+ {
+ if (!var_blk)
+ {
+ pc = pc->GetNext();
+ break;
+ }
+ }
+
+ // skip vbraces
+ if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ pc = pc->GetNextType(CT_VBRACE_CLOSE, pc->level);
+ pc = pc->GetNext();
+ continue;
+ }
+
+ // Ignore stuff inside parenthesis/squares/angles
+ if (pc->level > pc->brace_level)
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+
+ if (chunk_is_newline(pc))
+ {
+ did_this_line = false;
+ pc = pc->GetNext();
+ continue;
+ }
+
+ // Determine if this is a variable definition or code
+ if ( !did_this_line
+ && chunk_is_not_token(pc, CT_FUNC_CLASS_DEF)
+ && chunk_is_not_token(pc, CT_FUNC_CLASS_PROTO)
+ && ( (pc->level == (start->level + 1))
+ || pc->level == 0))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( chunk_is_token(next, CT_PTR_TYPE) // Issue #2692
+ || chunk_is_token(next, CT_BYREF)) // Issue #3018
+ {
+ next = next->GetNextNcNnl();
+ }
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): next->orig_line is %zu, next->orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, next->Text());
+
+ prev = pc->GetPrevNcNnl();
+
+ while ( chunk_is_token(prev, CT_DC_MEMBER)
+ || chunk_is_token(prev, CT_TYPE))
+ {
+ prev = prev->GetPrevNcNnl();
+ }
+
+ if (!(chunk_is_opening_brace(prev) || chunk_is_closing_brace(prev)))
+ {
+ prev = pc->GetPrevType(CT_SEMICOLON, pc->level);
+ }
+
+ if (prev->IsNullChunk())
+ {
+ prev = pc->GetPrevType(CT_BRACE_OPEN, pc->level - 1); // Issue #2692
+ }
+
+ if ( chunk_is_token(prev, CT_STRING)
+ && get_chunk_parent_type(prev) == CT_EXTERN
+ && chunk_is_token(prev->prev, CT_EXTERN))
+ {
+ prev = prev->GetPrev()->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ if (is_var_def(pc, next))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): 'typ==var' found: '%s %s' at line %zu\n",
+ __func__, __LINE__, pc->Text(), next->Text(), pc->orig_line);
+ // Put newline(s) before a block of variable definitions
+ log_rule_B("nl_var_def_blk_start");
+
+ if ( !var_blk
+ && first_var_blk
+ && options::nl_var_def_blk_start() > 0)
+ {
+ LOG_FMT(LBLANKD, "%s(%d): pc is '%s', orig_line is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+
+ if (prev == nullptr)
+ {
+ LOG_FMT(LBLANKD, "%s(%d): prev is nullptr\n", __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LBLANKD, "%s(%d): prev is '%s', orig_line is %zu\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line);
+
+ if (!chunk_is_opening_brace(prev))
+ {
+ newline_min_after(prev, options::nl_var_def_blk_start() + 1, PCF_VAR_DEF);
+ }
+ }
+ }
+
+ // set newlines within var def block
+ if ( var_blk
+ && (options::nl_var_def_blk_in() > 0))
+ {
+ log_rule_B("nl_var_def_blk_in");
+ prev = pc->GetPrev();
+ LOG_FMT(LNL1LINE, "%s(%d): prev->orig_line is %zu, prev->orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text());
+
+ if (chunk_is_newline(prev))
+ {
+ log_rule_B("nl_var_def_blk_in");
+
+ if (prev->nl_count > options::nl_var_def_blk_in())
+ {
+ prev->nl_count = options::nl_var_def_blk_in();
+ MARK_CHANGE();
+ }
+ }
+ }
+ pc = pc->GetNextType(CT_SEMICOLON, pc->level);
+ var_blk = true;
+ }
+ else if (var_blk)
+ {
+ log_rule_B("nl_var_def_blk_end");
+
+ if (options::nl_var_def_blk_end() > 0)
+ {
+ // Issue #3516
+ newline_min_after(prev, options::nl_var_def_blk_end() + 1, PCF_VAR_DEF);
+ }
+ // set blank lines after first var def block
+ log_rule_B("nl_func_var_def_blk");
+ LOG_FMT(LBLANKD, "%s(%d): first_var_blk %s\n",
+ __func__, __LINE__, first_var_blk ? "TRUE" : "FALSE");
+ LOG_FMT(LBLANKD, "%s(%d): fn_top %s\n",
+ __func__, __LINE__, fn_top ? "TRUE" : "FALSE");
+
+ if ( first_var_blk
+ && fn_top
+ && (options::nl_func_var_def_blk() > 0))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): nl_func_var_def_blk at line %zu\n",
+ __func__, __LINE__, prev->orig_line);
+ log_rule_B("nl_func_var_def_blk");
+ newline_min_after(prev, options::nl_func_var_def_blk() + 1, PCF_VAR_DEF);
+ }
+ // reset the variables for the next block
+ first_var_blk = true;
+ var_blk = false;
+ }
+ }
+ else
+ {
+ if (chunk_is_token(pc, CT_FUNC_CLASS_DEF))
+ {
+ log_rule_B("nl_var_def_blk_end");
+
+ if ( var_blk
+ && options::nl_var_def_blk_end() > 0)
+ {
+ prev = pc->GetPrev();
+ prev = prev->GetPrev();
+ newline_min_after(prev, options::nl_var_def_blk_end() + 1, PCF_VAR_DEF);
+ pc = pc->GetNext();
+ first_var_blk = false;
+ var_blk = false;
+ }
+ }
+ }
+ did_this_line = true;
+
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ pc = pc->GetNext();
+ }
+ return(pc);
+} // newline_def_blk
+
+
+static bool collapse_empty_body(Chunk *br_open)
+{
+ log_rule_B("nl_collapse_empty_body");
+
+ if ( !options::nl_collapse_empty_body()
+ || !chunk_is_token(br_open->GetNextNnl(), CT_BRACE_CLOSE))
+ {
+ return(false);
+ }
+
+ for (Chunk *pc = br_open->GetNext()
+ ; chunk_is_not_token(pc, CT_BRACE_CLOSE)
+ ; pc = pc->GetNext())
+ {
+ if ( chunk_is_token(pc, CT_NEWLINE)
+ && chunk_safe_to_del_nl(pc))
+ {
+ pc = pc->prev;
+ Chunk *next = pc->next;
+ chunk_del(next);
+ MARK_CHANGE();
+ }
+ }
+
+ return(true);
+} // collapse_empty_body
+
+
+static void newlines_brace_pair(Chunk *br_open)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_define_macro");
+
+ if ( br_open->flags.test(PCF_IN_PREPROC)
+ && !options::nl_define_macro())
+ {
+ return;
+ }
+
+ //fixes 1235 Add single line namespace support
+ if ( chunk_is_token(br_open, CT_BRACE_OPEN)
+ && (get_chunk_parent_type(br_open) == CT_NAMESPACE)
+ && chunk_is_newline(br_open->GetPrev()))
+ {
+ Chunk *chunk_brace_close = chunk_skip_to_match(br_open, E_Scope::ALL);
+
+ if (chunk_brace_close != nullptr)
+ {
+ if (are_chunks_in_same_line(br_open, chunk_brace_close))
+ {
+ log_rule_B("nl_namespace_two_to_one_liner - 1");
+
+ if (options::nl_namespace_two_to_one_liner())
+ {
+ Chunk *prev = br_open->GetPrevNnl();
+ newline_del_between(prev, br_open);
+ }
+ /* Below code is to support conversion of 2 liner to 4 liners
+ * else
+ * {
+ * Chunk *nxt = br_open->GetNext();
+ * newline_add_between(br_open, nxt);
+ * }*/
+ }
+ }
+ }
+ // fix 1247 oneliner function support - converts 4,3,2 liners to oneliner
+ log_rule_B("nl_create_func_def_one_liner");
+
+ if ( get_chunk_parent_type(br_open) == CT_FUNC_DEF
+ && options::nl_create_func_def_one_liner()
+ && !br_open->flags.test(PCF_NOT_POSSIBLE)) // Issue #2795
+ {
+ Chunk *br_close = chunk_skip_to_match(br_open, E_Scope::ALL);
+ Chunk *tmp = br_open->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( br_close != nullptr // Issue #2594
+ && ((br_close->orig_line - br_open->orig_line) <= 2)
+ && chunk_is_paren_close(tmp)) // need to check the conditions.
+ {
+ // Issue #1825
+ bool is_it_possible = true;
+
+ while ( tmp->IsNotNullChunk()
+ && (tmp = tmp->GetNext())->IsNotNullChunk()
+ && !chunk_is_closing_brace(tmp)
+ && (tmp->GetNext()->IsNotNullChunk()))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): tmp->orig_line is %zu, tmp->orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+
+ if (tmp->IsComment())
+ {
+ is_it_possible = false;
+ break;
+ }
+ }
+
+ if (is_it_possible)
+ {
+ // Issue 2795
+ // we have to check if it could be too long for code_width
+ // make a vector to save the chunk
+ vector<Chunk> saved_chunk;
+ log_rule_B("code_width");
+
+ if (options::code_width() > 0)
+ {
+ saved_chunk.reserve(16);
+ Chunk *current = br_open->GetPrevNcNnlNi();
+ Chunk *next_br_close = br_close->GetNext();
+ current = current->GetNext();
+
+ while (current->IsNotNullChunk())
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): zu kopieren: current->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, current->orig_line, current->orig_col, current->Text());
+ saved_chunk.push_back(*current);
+ Chunk *the_next = current->GetNext();
+
+ if ( the_next->IsNullChunk()
+ || the_next == next_br_close)
+ {
+ break;
+ }
+ current = the_next;
+ }
+ }
+ Chunk *tmp_1 = br_open->GetPrevNcNnlNi();
+
+ while ( tmp_1->IsNotNullChunk()
+ && (tmp_1 = tmp_1->GetNext())->IsNotNullChunk()
+ && !chunk_is_closing_brace(tmp_1)
+ && (tmp_1->GetNext()->IsNotNullChunk()))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): tmp_1->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, tmp_1->orig_line, tmp_1->orig_col, tmp_1->Text());
+
+ if (chunk_is_newline(tmp_1))
+ {
+ tmp_1 = tmp_1->GetPrev(); // Issue #1825
+ newline_iarf_pair(tmp_1, tmp_1->GetNextNcNnl(), IARF_REMOVE);
+ }
+ }
+ chunk_flags_set(br_open, PCF_ONE_LINER); // set the one liner flag if needed
+ chunk_flags_set(br_close, PCF_ONE_LINER);
+ log_rule_B("code_width");
+
+ if ( options::code_width() > 0
+ && br_close->column > options::code_width())
+ {
+ // the created line is too long
+ // it is not possible to make an one_liner
+ // because the line would be too long
+ chunk_flags_set(br_open, PCF_NOT_POSSIBLE);
+ // restore the code
+ size_t count;
+ Chunk tmp_2;
+ Chunk *current = br_open;
+
+ for (count = 0; count < saved_chunk.size(); count++)
+ {
+ tmp_2 = saved_chunk.at(count);
+
+ if (tmp_2.orig_line != current->orig_line)
+ {
+ // restore the newline
+ Chunk chunk;
+ set_chunk_type(&chunk, CT_NEWLINE);
+ chunk.orig_line = current->orig_line;
+ chunk.orig_col = current->orig_col;
+ chunk.pp_level = current->pp_level;
+ chunk.nl_count = 1;
+ chunk_add_before(&chunk, current);
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline before '%s'\n",
+ __func__, __LINE__, current->orig_line, current->orig_col, current->Text());
+ }
+ else
+ {
+ current = current->GetNext();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Make sure we don't break a one-liner
+ if (!one_liner_nl_ok(br_open))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): br_open->orig_line is %zu, br_open->orig_col is %zu, a new line may NOT be added\n",
+ __func__, __LINE__, br_open->orig_line, br_open->orig_col);
+ return;
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): a new line may be added\n", __func__, __LINE__);
+
+ Chunk *next = br_open->GetNextNc();
+
+ // Insert a newline between the '=' and open brace, if needed
+ LOG_FMT(LNL1LINE, "%s(%d): br_open->Text() '%s', br_open->type [%s], br_open->parent_type [%s]\n",
+ __func__, __LINE__, br_open->Text(), get_token_name(br_open->type),
+ get_token_name(get_chunk_parent_type(br_open)));
+
+ if (get_chunk_parent_type(br_open) == CT_ASSIGN)
+ {
+ // Only mess with it if the open brace is followed by a newline
+ if (chunk_is_newline(next))
+ {
+ Chunk *prev = br_open->GetPrevNcNnlNi(); // Issue #2279
+ log_rule_B("nl_assign_brace");
+ newline_iarf_pair(prev, br_open, options::nl_assign_brace());
+ }
+ }
+
+ if ( get_chunk_parent_type(br_open) == CT_OC_MSG_DECL
+ || get_chunk_parent_type(br_open) == CT_FUNC_DEF
+ || get_chunk_parent_type(br_open) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(br_open) == CT_OC_CLASS
+ || get_chunk_parent_type(br_open) == CT_CS_PROPERTY
+ || get_chunk_parent_type(br_open) == CT_CPP_LAMBDA
+ || get_chunk_parent_type(br_open) == CT_FUNC_CALL
+ || get_chunk_parent_type(br_open) == CT_FUNC_CALL_USER)
+ {
+ Chunk *prev = Chunk::NullChunkPtr;
+ iarf_e val;
+
+ if (get_chunk_parent_type(br_open) == CT_OC_MSG_DECL)
+ {
+ log_rule_B("nl_oc_mdef_brace");
+ val = options::nl_oc_mdef_brace();
+ }
+ else
+ {
+ if ( get_chunk_parent_type(br_open) == CT_FUNC_DEF
+ || get_chunk_parent_type(br_open) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(br_open) == CT_OC_CLASS)
+ {
+ val = IARF_NOT_DEFINED;
+ log_rule_B("nl_fdef_brace_cond");
+ const iarf_e nl_fdef_brace_cond_v = options::nl_fdef_brace_cond();
+
+ if (nl_fdef_brace_cond_v != IARF_IGNORE)
+ {
+ prev = br_open->GetPrevNcNnlNi(); // Issue #2279
+
+ if (chunk_is_token(prev, CT_FPAREN_CLOSE))
+ {
+ val = nl_fdef_brace_cond_v;
+ }
+ }
+
+ if (val == IARF_NOT_DEFINED)
+ {
+ log_rule_B("nl_fdef_brace");
+ val = options::nl_fdef_brace();
+ }
+ }
+ else
+ {
+ log_rule_B("nl_property_brace");
+ log_rule_B("nl_cpp_ldef_brace");
+ log_rule_B("nl_fcall_brace");
+ val = ((get_chunk_parent_type(br_open) == CT_CS_PROPERTY) ?
+ options::nl_property_brace() :
+ ((get_chunk_parent_type(br_open) == CT_CPP_LAMBDA) ?
+ options::nl_cpp_ldef_brace() :
+ options::nl_fcall_brace()));
+ }
+ }
+
+ if (val != IARF_IGNORE)
+ {
+ if (prev->IsNullChunk())
+ {
+ // Grab the chunk before the open brace
+ prev = br_open->GetPrevNcNnlNi(); // Issue #2279
+ }
+ newline_iarf_pair(prev, br_open, val);
+ }
+ }
+
+ if (collapse_empty_body(br_open))
+ {
+ return;
+ }
+ //fixes #1245 will add new line between tsquare and brace open based on nl_tsquare_brace
+
+ if (chunk_is_token(br_open, CT_BRACE_OPEN))
+ {
+ Chunk *chunk_closeing_brace = chunk_skip_to_match(br_open, E_Scope::ALL);
+
+ if (chunk_closeing_brace != nullptr)
+ {
+ if (chunk_closeing_brace->orig_line > br_open->orig_line)
+ {
+ Chunk *prev = br_open->GetPrevNc();
+
+ if ( chunk_is_token(prev, CT_TSQUARE)
+ && chunk_is_newline(next))
+ {
+ log_rule_B("nl_tsquare_brace");
+ newline_iarf_pair(prev, br_open, options::nl_tsquare_brace());
+ }
+ }
+ }
+ }
+ // Eat any extra newlines after the brace open
+ log_rule_B("eat_blanks_after_open_brace");
+
+ if (options::eat_blanks_after_open_brace())
+ {
+ if (chunk_is_newline(next))
+ {
+ log_rule_B("nl_inside_empty_func");
+ log_rule_B("nl_inside_namespace");
+
+ if ( options::nl_inside_empty_func() > 0
+ && chunk_is_token(br_open->GetNextNnl(), CT_BRACE_CLOSE)
+ && ( get_chunk_parent_type(br_open) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(br_open) == CT_FUNC_DEF))
+ {
+ blank_line_set(next, options::nl_inside_empty_func);
+ }
+ else if ( options::nl_inside_namespace() > 0
+ && get_chunk_parent_type(br_open) == CT_NAMESPACE)
+ {
+ blank_line_set(next, options::nl_inside_namespace);
+ }
+ else if (next->nl_count > 1)
+ {
+ next->nl_count = 1;
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_after_open_brace %zu\n",
+ __func__, __LINE__, next->orig_line);
+ MARK_CHANGE();
+ }
+ }
+ }
+ bool nl_close_brace = false;
+
+ // Handle the cases where the brace is part of a function call or definition
+ if ( get_chunk_parent_type(br_open) == CT_FUNC_DEF
+ || get_chunk_parent_type(br_open) == CT_FUNC_CALL
+ || get_chunk_parent_type(br_open) == CT_FUNC_CALL_USER
+ || get_chunk_parent_type(br_open) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(br_open) == CT_OC_CLASS
+ || get_chunk_parent_type(br_open) == CT_OC_MSG_DECL
+ || get_chunk_parent_type(br_open) == CT_CS_PROPERTY
+ || get_chunk_parent_type(br_open) == CT_CPP_LAMBDA)
+ {
+ // Need to force a newline before the close brace, if not in a class body
+ if (!br_open->flags.test(PCF_IN_CLASS))
+ {
+ nl_close_brace = true;
+ }
+ // handle newlines after the open brace
+ Chunk *pc = br_open->GetNextNcNnl();
+ newline_add_between(br_open, pc);
+
+ Chunk *ne = pc->GetNextNcNnl();
+ bool this_is_var_def = is_var_def(pc, ne); // Issue #3518
+ newline_def_blk(br_open, this_is_var_def);
+ }
+
+ // Handle the cases where the brace is part of a class or struct
+ if ( get_chunk_parent_type(br_open) == CT_CLASS
+ || get_chunk_parent_type(br_open) == CT_STRUCT)
+ {
+ newline_def_blk(br_open, false);
+ }
+ // Grab the matching brace close
+ Chunk *br_close = br_open->GetNextType(CT_BRACE_CLOSE, br_open->level);
+
+ if (br_close->IsNullChunk())
+ {
+ return;
+ }
+
+ if (!nl_close_brace)
+ {
+ /*
+ * If the open brace hits a CT_NEWLINE, CT_NL_CONT, CT_COMMENT_MULTI, or
+ * CT_COMMENT_CPP without hitting anything other than CT_COMMENT, then
+ * there should be a newline before the close brace.
+ */
+ Chunk *pc = br_open->GetNext();
+
+ while (chunk_is_token(pc, CT_COMMENT))
+ {
+ pc = pc->GetNext();
+ }
+
+ if ( chunk_is_newline(pc)
+ || pc->IsComment())
+ {
+ nl_close_brace = true;
+ }
+ }
+ Chunk *prev = br_close->GetPrevNcNnlNet();
+
+ if (nl_close_brace)
+ {
+ newline_add_between(prev, br_close);
+ }
+ else
+ {
+ newline_del_between(prev, br_close);
+ }
+} // newlines_brace_pair
+
+
+static void newline_case(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ // printf("%s case (%s) on line %d col %d\n",
+ // __func__, c_chunk_names[start->type],
+ // start->orig_line, start->orig_col);
+
+ // Scan backwards until a '{' or ';' or ':'. Abort if a multi-newline is found
+ Chunk *prev = start;
+
+ do
+ {
+ prev = prev->GetPrevNc();
+
+ if ( prev->IsNotNullChunk()
+ && chunk_is_newline(prev)
+ && prev->nl_count > 1)
+ {
+ return;
+ }
+ } while ( chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && chunk_is_not_token(prev, CT_BRACE_CLOSE)
+ && chunk_is_not_token(prev, CT_SEMICOLON)
+ && chunk_is_not_token(prev, CT_CASE_COLON));
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *pc = newline_add_between(prev, start);
+
+ if (pc == nullptr)
+ {
+ return;
+ }
+
+ // Only add an extra line after a semicolon or brace close
+ if ( chunk_is_token(prev, CT_SEMICOLON)
+ || chunk_is_token(prev, CT_BRACE_CLOSE))
+ {
+ if ( chunk_is_newline(pc)
+ && pc->nl_count < 2)
+ {
+ double_newline(pc);
+ }
+ }
+} // newline_case
+
+
+static void newline_case_colon(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ // Scan forwards until a non-comment is found
+ Chunk *pc = start;
+
+ do
+ {
+ pc = pc->GetNext();
+ } while (pc->IsComment());
+
+ if ( pc->IsNotNullChunk()
+ && !chunk_is_newline(pc))
+ {
+ newline_add_before(pc);
+ }
+} // newline_case_colon
+
+
+static void newline_before_return(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ if (start != nullptr)
+ {
+ pc = start->GetPrev();
+ }
+ Chunk *nl = pc;
+
+ // Skip over single preceding newline
+ if (chunk_is_newline(pc))
+ {
+ // Do we already have a blank line?
+ if (nl->nl_count > 1)
+ {
+ return;
+ }
+ pc = nl->GetPrev();
+ }
+
+ // Skip over preceding comments that are not a trailing comment, taking
+ // into account that comment blocks may span multiple lines.
+ // Trailing comments are considered part of the previous token, not the
+ // return statement. They are handled below.
+ while ( pc->IsComment()
+ && get_chunk_parent_type(pc) != CT_COMMENT_END)
+ {
+ pc = pc->GetPrev();
+
+ if (!chunk_is_newline(pc))
+ {
+ return;
+ }
+ nl = pc;
+ pc = pc->GetPrev();
+ }
+ pc = nl->GetPrev();
+
+ // Peek over trailing comment of previous token
+ if ( pc->IsComment()
+ && get_chunk_parent_type(pc) == CT_COMMENT_END)
+ {
+ pc = pc->GetPrev();
+ }
+
+ // Don't add extra blanks after an opening brace or a case statement
+ if ( pc == nullptr
+ || ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_OPEN)
+ || chunk_is_token(pc, CT_CASE_COLON)))
+ {
+ return;
+ }
+
+ if ( chunk_is_newline(nl)
+ && nl->nl_count < 2)
+ {
+ nl->nl_count++;
+ MARK_CHANGE();
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, text is '%s', ++ nl_count is now %zu\n",
+ __func__, __LINE__, nl->orig_line, nl->orig_col, nl->Text(), nl->nl_count);
+ }
+} // newline_before_return
+
+
+static void newline_after_return(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *semi = start->GetNextType(CT_SEMICOLON, start->level);
+ Chunk *after = semi->GetNextNcNnlNet();
+
+ // If we hit a brace or an 'else', then a newline isn't needed
+ if ( after->IsNullChunk()
+ || chunk_is_token(after, CT_BRACE_CLOSE)
+ || chunk_is_token(after, CT_VBRACE_CLOSE)
+ || chunk_is_token(after, CT_ELSE))
+ {
+ return;
+ }
+ Chunk *pc;
+
+ for (pc = semi->GetNext(); pc != after; pc = pc->GetNext())
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ if (pc->nl_count < 2)
+ {
+ double_newline(pc);
+ }
+ return;
+ }
+ }
+} // newline_after_return
+
+
+static void newline_iarf_pair(Chunk *before, Chunk *after, iarf_e av, bool check_nl_assign_leave_one_liners)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNEWLINE, "%s(%d): ", __func__, __LINE__);
+ log_func_stack(LNEWLINE, "CallStack:");
+
+ if ( before == nullptr
+ || before == Chunk::NullChunkPtr
+ || after == nullptr
+ || after == Chunk::NullChunkPtr
+ || chunk_is_token(after, CT_IGNORED))
+ {
+ return;
+ }
+
+ if (av & IARF_ADD)
+ {
+ if ( check_nl_assign_leave_one_liners
+ && options::nl_assign_leave_one_liners()
+ && after->flags.test(PCF_ONE_LINER))
+ {
+ log_rule_B("nl_assign_leave_one_liners");
+ return;
+ }
+ Chunk *nl = newline_add_between(before, after);
+ LOG_FMT(LNEWLINE, "%s(%d): newline_add_between '%s' and '%s'\n",
+ __func__, __LINE__, before->Text(), after->Text());
+
+ if ( nl != nullptr
+ && av == IARF_FORCE
+ && nl->nl_count > 1)
+ {
+ nl->nl_count = 1;
+ }
+ }
+ else if (av & IARF_REMOVE)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): newline_remove_between '%s' and '%s'\n",
+ __func__, __LINE__, before->Text(), after->Text());
+ newline_del_between(before, after);
+ }
+} // newline_iarf_pair
+
+
+void newline_iarf(Chunk *pc, iarf_e av)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNFD, "%s(%d): ", __func__, __LINE__);
+ log_func_stack(LNFD, "CallStack:");
+ Chunk *after = Chunk::NullChunkPtr;
+
+ if (pc != nullptr)
+ {
+ after = pc->GetNextNnl();
+ }
+
+ if ( chunk_is_token(pc, CT_FPAREN_OPEN) // Issue #2914
+ && get_chunk_parent_type(pc) == CT_FUNC_CALL
+ && chunk_is_token(after, CT_COMMENT_CPP)
+ && options::donot_add_nl_before_cpp_comment())
+ {
+ return;
+ }
+ newline_iarf_pair(pc, after, av);
+} // newline_iarf
+
+
+static void newline_func_multi_line(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNFD, "%s(%d): called on %zu:%zu '%s' [%s/%s]\n",
+ __func__, __LINE__, start->orig_line, start->orig_col,
+ start->Text(), get_token_name(start->type), get_token_name(get_chunk_parent_type(start)));
+
+ bool add_start;
+ bool add_args;
+ bool add_end;
+
+ if ( get_chunk_parent_type(start) == CT_FUNC_DEF
+ || get_chunk_parent_type(start) == CT_FUNC_CLASS_DEF)
+ {
+ log_rule_B("nl_func_def_start_multi_line");
+ add_start = options::nl_func_def_start_multi_line();
+ log_rule_B("nl_func_def_args_multi_line");
+ add_args = options::nl_func_def_args_multi_line();
+ log_rule_B("nl_func_def_end_multi_line");
+ add_end = options::nl_func_def_end_multi_line();
+ }
+ else if ( get_chunk_parent_type(start) == CT_FUNC_CALL
+ || get_chunk_parent_type(start) == CT_FUNC_CALL_USER)
+ {
+ log_rule_B("nl_func_call_start_multi_line");
+ add_start = options::nl_func_call_start_multi_line();
+ log_rule_B("nl_func_call_args_multi_line");
+ add_args = options::nl_func_call_args_multi_line();
+ log_rule_B("nl_func_call_end_multi_line");
+ add_end = options::nl_func_call_end_multi_line();
+ }
+ else
+ {
+ log_rule_B("nl_func_decl_start_multi_line");
+ add_start = options::nl_func_decl_start_multi_line();
+ log_rule_B("nl_func_decl_args_multi_line");
+ add_args = options::nl_func_decl_args_multi_line();
+ log_rule_B("nl_func_decl_end_multi_line");
+ add_end = options::nl_func_decl_end_multi_line();
+ }
+
+ if ( !add_start
+ && !add_args
+ && !add_end)
+ {
+ return;
+ }
+ Chunk *pc = start->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->level > start->level)
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ if ( chunk_is_token(pc, CT_FPAREN_CLOSE)
+ && chunk_is_newline_between(start, pc))
+ {
+ Chunk *start_next = start->GetNextNcNnl();
+ bool has_leading_closure = ( start_next->parent_type == CT_OC_BLOCK_EXPR
+ || start_next->parent_type == CT_CPP_LAMBDA
+ || chunk_is_token(start_next, CT_BRACE_OPEN));
+
+ Chunk *prev_end = pc->GetPrevNcNnl();
+ bool has_trailing_closure = ( prev_end->parent_type == CT_OC_BLOCK_EXPR
+ || prev_end->parent_type == CT_CPP_LAMBDA
+ || chunk_is_token(prev_end, CT_BRACE_OPEN));
+
+ if ( add_start
+ && !chunk_is_newline(start->GetNext()))
+ {
+ log_rule_B("nl_func_call_args_multi_line_ignore_closures");
+
+ if (options::nl_func_call_args_multi_line_ignore_closures())
+ {
+ if ( !has_leading_closure
+ && !has_trailing_closure)
+ {
+ newline_iarf(start, IARF_ADD);
+ }
+ }
+ else
+ {
+ newline_iarf(start, IARF_ADD);
+ }
+ }
+
+ if ( add_end
+ && !chunk_is_newline(pc->GetPrev()))
+ {
+ log_rule_B("nl_func_call_args_multi_line_ignore_closures");
+
+ if (options::nl_func_call_args_multi_line_ignore_closures())
+ {
+ if ( !has_leading_closure
+ && !has_trailing_closure)
+ {
+ newline_iarf(pc->GetPrev(), IARF_ADD);
+ }
+ }
+ else
+ {
+ newline_iarf(pc->GetPrev(), IARF_ADD);
+ }
+ }
+
+ if (add_args)
+ {
+ // process the function in reverse and leave the first comma if the option to leave trailing closure
+ // is on. nl_func_call_args_multi_line_ignore_trailing_closure
+ for (pc = start->GetNextNcNnl();
+ pc->IsNotNullChunk() && pc->level > start->level;
+ pc = pc->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc, CT_COMMA)
+ && (pc->level == (start->level + 1)))
+ {
+ Chunk *tmp = pc->GetNext();
+
+ if (tmp->IsComment())
+ {
+ pc = tmp;
+ }
+
+ if (!chunk_is_newline(pc->GetNext()))
+ {
+ log_rule_B("nl_func_call_args_multi_line_ignore_closures");
+
+ if (options::nl_func_call_args_multi_line_ignore_closures())
+ {
+ Chunk *prev_comma = pc->GetPrevNcNnl();
+ Chunk *after_comma = pc->GetNextNcNnl();
+
+ if (!( ( prev_comma->parent_type == CT_OC_BLOCK_EXPR
+ || prev_comma->parent_type == CT_CPP_LAMBDA
+ || chunk_is_token(prev_comma, CT_BRACE_OPEN))
+ || ( after_comma->parent_type == CT_OC_BLOCK_EXPR
+ || after_comma->parent_type == CT_CPP_LAMBDA
+ || chunk_is_token(after_comma, CT_BRACE_OPEN))))
+ {
+ newline_iarf(pc, IARF_ADD);
+ }
+ }
+ else
+ {
+ newline_iarf(pc, IARF_ADD);
+ }
+ }
+ }
+ }
+ }
+ }
+} // newline_func_multi_line
+
+
+static void newline_template(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNFD, "%s(%d): called on %zu:%zu '%s' [%s/%s]\n",
+ __func__, __LINE__, start->orig_line, start->orig_col,
+ start->Text(), get_token_name(start->type), get_token_name(get_chunk_parent_type(start)));
+
+ log_rule_B("nl_template_start");
+ bool add_start = options::nl_template_start();
+
+ log_rule_B("nl_template_args");
+ bool add_args = options::nl_template_args();
+
+ log_rule_B("nl_template_end");
+ bool add_end = options::nl_template_end();
+
+ if ( !add_start
+ && !add_args
+ && !add_end)
+ {
+ return;
+ }
+ Chunk *pc = start->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->level > start->level)
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ if (chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ if (add_start)
+ {
+ newline_iarf(start, IARF_ADD);
+ }
+
+ if (add_end)
+ {
+ newline_iarf(pc->GetPrev(), IARF_ADD);
+ }
+
+ if (add_args)
+ {
+ Chunk *pc_1;
+
+ for (pc_1 = start->GetNextNcNnl();
+ pc_1->IsNotNullChunk() && pc_1->level > start->level;
+ pc_1 = pc_1->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc_1, CT_COMMA)
+ && (pc_1->level == (start->level + 1)))
+ {
+ Chunk *tmp = pc_1->GetNext();
+
+ if (tmp->IsComment())
+ {
+ pc_1 = tmp;
+ }
+
+ if (!chunk_is_newline(pc_1->GetNext()))
+ {
+ newline_iarf(pc_1, IARF_ADD);
+ }
+ }
+ }
+ }
+ }
+} // newline_template
+
+
+static void newline_func_def_or_call(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNFD, "%s(%d): called on start->Text() is '%s', orig_line is %zu, orig_col is %zu, [%s/%s]\n",
+ __func__, __LINE__, start->Text(), start->orig_line, start->orig_col,
+ get_token_name(start->type), get_token_name(get_chunk_parent_type(start)));
+
+ bool is_def = (get_chunk_parent_type(start) == CT_FUNC_DEF)
+ || get_chunk_parent_type(start) == CT_FUNC_CLASS_DEF;
+ bool is_call = (get_chunk_parent_type(start) == CT_FUNC_CALL)
+ || get_chunk_parent_type(start) == CT_FUNC_CALL_USER;
+
+ LOG_FMT(LNFD, "%s(%d): is_def is %s, is_call is %s\n",
+ __func__, __LINE__, is_def ? "TRUE" : "FALSE", is_call ? "TRUE" : "FALSE");
+
+ if (is_call)
+ {
+ log_rule_B("nl_func_call_paren");
+ iarf_e atmp = options::nl_func_call_paren();
+
+ if (atmp != IARF_IGNORE)
+ {
+ Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (prev->IsNotNullChunk())
+ {
+ newline_iarf(prev, atmp);
+ }
+ }
+ Chunk *pc = start->GetNextNcNnl();
+
+ if (chunk_is_str(pc, ")"))
+ {
+ log_rule_B("nl_func_call_paren_empty");
+ atmp = options::nl_func_call_paren_empty();
+
+ if (atmp != IARF_IGNORE)
+ {
+ Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (prev->IsNotNullChunk())
+ {
+ newline_iarf(prev, atmp);
+ }
+ }
+ log_rule_B("nl_func_call_empty");
+ atmp = options::nl_func_call_empty();
+
+ if (atmp != IARF_IGNORE)
+ {
+ newline_iarf(start, atmp);
+ }
+ return;
+ }
+ }
+ else
+ {
+ log_rule_B("nl_func_def_paren");
+ log_rule_B("nl_func_paren");
+ iarf_e atmp = is_def ? options::nl_func_def_paren()
+ : options::nl_func_paren();
+ LOG_FMT(LSPACE, "%s(%d): atmp is %s\n",
+ __func__, __LINE__,
+ (atmp == IARF_IGNORE) ? "IGNORE" :
+ (atmp == IARF_ADD) ? "ADD" :
+ (atmp == IARF_REMOVE) ? "REMOVE" : "FORCE");
+
+ if (atmp != IARF_IGNORE)
+ {
+ Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (prev->IsNotNullChunk())
+ {
+ newline_iarf(prev, atmp);
+ }
+ }
+ // Handle break newlines type and function
+ Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279
+ prev = skip_template_prev(prev);
+ // Don't split up a function variable
+ prev = chunk_is_paren_close(prev) ? nullptr : prev->GetPrevNcNnlNi(); // Issue #2279
+
+ log_rule_B("nl_func_class_scope");
+
+ if ( chunk_is_token(prev, CT_DC_MEMBER)
+ && (options::nl_func_class_scope() != IARF_IGNORE))
+ {
+ newline_iarf(prev->GetPrevNcNnlNi(), options::nl_func_class_scope()); // Issue #2279
+ }
+
+ if (chunk_is_not_token(prev, CT_ACCESS_COLON))
+ {
+ Chunk *tmp;
+
+ if (chunk_is_token(prev, CT_OPERATOR))
+ {
+ tmp = prev;
+ prev = prev->GetPrevNcNnlNi(); // Issue #2279
+ }
+ else
+ {
+ tmp = start;
+ }
+
+ if (chunk_is_token(prev, CT_DC_MEMBER))
+ {
+ log_rule_B("nl_func_scope_name");
+
+ if ( options::nl_func_scope_name() != IARF_IGNORE
+ && !start->flags.test(PCF_IN_DECLTYPE))
+ {
+ newline_iarf(prev, options::nl_func_scope_name());
+ }
+ }
+ const Chunk *tmp_next = prev->GetNextNcNnl();
+
+ if (chunk_is_not_token(tmp_next, CT_FUNC_CLASS_DEF))
+ {
+ Chunk *closing = chunk_skip_to_match(tmp);
+ Chunk *brace = closing->GetNextNcNnl();
+ iarf_e a; // Issue #2561
+
+ if ( get_chunk_parent_type(tmp) == CT_FUNC_PROTO
+ || get_chunk_parent_type(tmp) == CT_FUNC_CLASS_PROTO)
+ {
+ // proto
+ log_rule_B("nl_func_proto_type_name");
+ a = options::nl_func_proto_type_name();
+ }
+ else
+ {
+ // def
+
+ log_rule_B("nl_func_leave_one_liners");
+
+ if ( options::nl_func_leave_one_liners()
+ && ( brace == nullptr
+ || brace->flags.test(PCF_ONE_LINER))) // Issue #1511 and #3274
+ {
+ a = IARF_IGNORE;
+ }
+ else
+ {
+ log_rule_B("nl_func_type_name");
+ a = options::nl_func_type_name();
+ }
+ }
+ log_rule_B("nl_func_type_name_class");
+
+ if ( tmp->flags.test(PCF_IN_CLASS)
+ && (options::nl_func_type_name_class() != IARF_IGNORE))
+ {
+ a = options::nl_func_type_name_class();
+ }
+
+ if ( a != IARF_IGNORE
+ && prev != nullptr)
+ {
+ LOG_FMT(LNFD, "%s(%d): prev->Text() '%s', orig_line is %zu, orig_col is %zu, [%s/%s]\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col,
+ get_token_name(prev->type),
+ get_token_name(get_chunk_parent_type(prev)));
+
+ if (chunk_is_token(prev, CT_DESTRUCTOR))
+ {
+ prev = prev->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ /*
+ * If we are on a '::', step back two tokens
+ * TODO: do we also need to check for '.' ?
+ */
+ while (chunk_is_token(prev, CT_DC_MEMBER))
+ {
+ prev = prev->GetPrevNcNnlNi(); // Issue #2279
+ prev = skip_template_prev(prev);
+ prev = prev->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ if ( chunk_is_not_token(prev, CT_BRACE_CLOSE)
+ && chunk_is_not_token(prev, CT_VBRACE_CLOSE)
+ && chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && chunk_is_not_token(prev, CT_SEMICOLON)
+ && chunk_is_not_token(prev, CT_ACCESS_COLON)
+ // #1008: if we landed on an operator check that it is having
+ // a type before it, in order to not apply nl_func_type_name
+ // on conversion operators as they don't have a normal
+ // return type syntax
+ && (chunk_is_not_token(tmp_next, CT_OPERATOR) ? true : chunk_is_type(prev)))
+ {
+ newline_iarf(prev, a);
+ }
+ }
+ }
+ }
+ Chunk *pc = start->GetNextNcNnl();
+
+ if (chunk_is_str(pc, ")"))
+ {
+ log_rule_B("nl_func_def_empty");
+ log_rule_B("nl_func_decl_empty");
+ atmp = is_def ? options::nl_func_def_empty()
+ : options::nl_func_decl_empty();
+
+ if (atmp != IARF_IGNORE)
+ {
+ newline_iarf(start, atmp);
+ }
+ log_rule_B("nl_func_def_paren_empty");
+ log_rule_B("nl_func_paren_empty");
+ atmp = is_def ? options::nl_func_def_paren_empty()
+ : options::nl_func_paren_empty();
+
+ if (atmp != IARF_IGNORE)
+ {
+ prev = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (prev->IsNotNullChunk())
+ {
+ newline_iarf(prev, atmp);
+ }
+ }
+ return;
+ }
+ }
+ // Now scan for commas
+ size_t comma_count = 0;
+ Chunk *tmp;
+ Chunk *pc;
+
+ for (pc = start->GetNextNcNnl();
+ pc->IsNotNullChunk() && pc->level > start->level;
+ pc = pc->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc, CT_COMMA)
+ && (pc->level == (start->level + 1)))
+ {
+ comma_count++;
+ tmp = pc->GetNext();
+
+ if (tmp->IsComment())
+ {
+ pc = tmp;
+ }
+
+ if (is_def)
+ {
+ log_rule_B("nl_func_def_args");
+ newline_iarf(pc, options::nl_func_def_args());
+ }
+ else if (is_call)
+ {
+ // Issue #2604
+ log_rule_B("nl_func_call_args");
+ newline_iarf(pc, options::nl_func_call_args());
+ }
+ else // get_chunk_parent_type(start) == CT_FUNC_DECL
+ {
+ log_rule_B("nl_func_decl_args");
+ newline_iarf(pc, options::nl_func_decl_args());
+ }
+ }
+ }
+
+ log_rule_B("nl_func_def_start");
+ log_rule_B("nl_func_decl_start");
+ iarf_e as = is_def ? options::nl_func_def_start() : options::nl_func_decl_start();
+
+ log_rule_B("nl_func_def_end");
+ log_rule_B("nl_func_decl_end");
+ iarf_e ae = is_def ? options::nl_func_def_end() : options::nl_func_decl_end();
+
+ if (comma_count == 0)
+ {
+ iarf_e atmp;
+ log_rule_B("nl_func_def_start_single");
+ log_rule_B("nl_func_decl_start_single");
+ atmp = is_def ? options::nl_func_def_start_single() :
+ options::nl_func_decl_start_single();
+
+ if (atmp != IARF_IGNORE)
+ {
+ as = atmp;
+ }
+ log_rule_B("nl_func_def_end_single");
+ log_rule_B("nl_func_decl_end_single");
+ atmp = is_def ? options::nl_func_def_end_single() :
+ options::nl_func_decl_end_single();
+
+ if (atmp != IARF_IGNORE)
+ {
+ ae = atmp;
+ }
+ }
+
+ if (!is_call)
+ {
+ newline_iarf(start, as);
+ }
+
+ // and fix up the close parenthesis
+ if (chunk_is_token(pc, CT_FPAREN_CLOSE))
+ {
+ Chunk *prev = pc->GetPrevNnl();
+
+ if ( chunk_is_not_token(prev, CT_FPAREN_OPEN)
+ && !is_call)
+ {
+ newline_iarf(prev, ae);
+ }
+ newline_func_multi_line(start);
+ }
+} // newline_func_def_or_call
+
+
+static void newline_oc_msg(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *sq_c = chunk_skip_to_match(start);
+
+ if (sq_c == nullptr)
+ {
+ return;
+ }
+ log_rule_B("nl_oc_msg_leave_one_liner");
+
+ if (options::nl_oc_msg_leave_one_liner())
+ {
+ return;
+ }
+
+ for (Chunk *pc = start->GetNextNcNnl(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (pc->level <= start->level)
+ {
+ break;
+ }
+
+ if (chunk_is_token(pc, CT_OC_MSG_NAME))
+ {
+ newline_add_before(pc);
+ }
+ }
+} // newline_oc_msg
+
+
+static bool one_liner_nl_ok(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNL1LINE, "%s(%d): check type is %s, parent is %s, flag is %s, orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)),
+ pcf_flags_str(pc->flags).c_str(), pc->orig_line, pc->orig_col);
+
+ if (!pc->flags.test(PCF_ONE_LINER))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): true (not 1-liner), a new line may be added\n", __func__, __LINE__);
+ return(true);
+ }
+ // Step back to find the opening brace
+ Chunk *br_open = pc;
+
+ if (chunk_is_closing_brace(br_open))
+ {
+ br_open = br_open->GetPrevType(chunk_is_token(br_open, CT_BRACE_CLOSE) ? CT_BRACE_OPEN : CT_VBRACE_OPEN,
+ br_open->level, E_Scope::ALL);
+ }
+ else
+ {
+ while ( br_open->IsNotNullChunk()
+ && br_open->flags.test(PCF_ONE_LINER)
+ && !chunk_is_opening_brace(br_open)
+ && !chunk_is_closing_brace(br_open))
+ {
+ br_open = br_open->GetPrev();
+ }
+ }
+ pc = br_open;
+
+ if ( pc->IsNotNullChunk()
+ && pc->flags.test(PCF_ONE_LINER)
+ && ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_VBRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_CLOSE)))
+ {
+ log_rule_B("nl_class_leave_one_liners");
+
+ if ( options::nl_class_leave_one_liners()
+ && pc->flags.test(PCF_IN_CLASS))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (class)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_assign_leave_one_liners");
+
+ if ( options::nl_assign_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_ASSIGN)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (assign)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_enum_leave_one_liners");
+
+ if ( options::nl_enum_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_ENUM)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (enum)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_getset_leave_one_liners");
+
+ if ( options::nl_getset_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_GETSET)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (get/set), a new line may NOT be added\n", __func__, __LINE__);
+ return(false);
+ }
+ // Issue #UT-98
+ log_rule_B("nl_cs_property_leave_one_liners");
+
+ if ( options::nl_cs_property_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_CS_PROPERTY)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (c# property), a new line may NOT be added\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_func_leave_one_liners");
+
+ if ( options::nl_func_leave_one_liners()
+ && ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (func def)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_func_leave_one_liners");
+
+ if ( options::nl_func_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_OC_MSG_DECL)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (method def)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_cpp_lambda_leave_one_liners");
+
+ if ( options::nl_cpp_lambda_leave_one_liners()
+ && ((get_chunk_parent_type(pc) == CT_CPP_LAMBDA)))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (lambda)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_oc_msg_leave_one_liner");
+
+ if ( options::nl_oc_msg_leave_one_liner()
+ && pc->flags.test(PCF_IN_OC_MSG))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (message)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_if_leave_one_liners");
+
+ if ( options::nl_if_leave_one_liners()
+ && ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSEIF
+ || get_chunk_parent_type(pc) == CT_ELSE))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (if/else)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_while_leave_one_liners");
+
+ if ( options::nl_while_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_WHILE)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (while)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_do_leave_one_liners");
+
+ if ( options::nl_do_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_DO)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (do)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_for_leave_one_liners");
+
+ if ( options::nl_for_leave_one_liners()
+ && get_chunk_parent_type(pc) == CT_FOR)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (for)\n", __func__, __LINE__);
+ return(false);
+ }
+ log_rule_B("nl_namespace_two_to_one_liner - 2");
+
+ if ( options::nl_namespace_two_to_one_liner()
+ && get_chunk_parent_type(pc) == CT_NAMESPACE)
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): false (namespace)\n", __func__, __LINE__);
+ return(false);
+ }
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): true, a new line may be added\n", __func__, __LINE__);
+ return(true);
+} // one_liner_nl_ok
+
+
+void undo_one_liner(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc != nullptr
+ && pc->flags.test(PCF_ONE_LINER))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): pc->Text() '%s', orig_line is %zu, orig_col is %zu",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ chunk_flags_clr(pc, PCF_ONE_LINER);
+
+ // scan backward
+ LOG_FMT(LNL1LINE, "%s(%d): scan backward\n", __func__, __LINE__);
+ Chunk *tmp = pc;
+
+ while ((tmp = tmp->GetPrev())->IsNotNullChunk())
+ {
+ if (!tmp->flags.test(PCF_ONE_LINER))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): tmp->Text() '%s', orig_line is %zu, orig_col is %zu, --> break\n",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line, tmp->orig_col);
+ break;
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): clear for tmp->Text() '%s', orig_line is %zu, orig_col is %zu",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line, tmp->orig_col);
+ chunk_flags_clr(tmp, PCF_ONE_LINER);
+ }
+ // scan forward
+ LOG_FMT(LNL1LINE, "%s(%d): scan forward\n", __func__, __LINE__);
+ tmp = pc;
+ LOG_FMT(LNL1LINE, "%s(%d): - \n", __func__, __LINE__);
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if (!tmp->flags.test(PCF_ONE_LINER))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): tmp->Text() '%s', orig_line is %zu, orig_col is %zu, --> break\n",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line, tmp->orig_col);
+ break;
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): clear for tmp->Text() '%s', orig_line is %zu, orig_col is %zu",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line, tmp->orig_col);
+ chunk_flags_clr(tmp, PCF_ONE_LINER);
+ }
+ LOG_FMT(LNL1LINE, "\n");
+ }
+} // undo_one_liner
+
+
+static void nl_create_one_liner(Chunk *vbrace_open)
+{
+ LOG_FUNC_ENTRY();
+
+ // See if we get a newline between the next text and the vbrace_close
+ Chunk *tmp = vbrace_open->GetNextNcNnl();
+ Chunk *first = tmp;
+
+ if ( first->IsNullChunk()
+ || get_token_pattern_class(first->type) != pattern_class_e::NONE)
+ {
+ return;
+ }
+ size_t nl_total = 0;
+
+ while (chunk_is_not_token(tmp, CT_VBRACE_CLOSE))
+ {
+ if (chunk_is_newline(tmp))
+ {
+ nl_total += tmp->nl_count;
+
+ if (nl_total > 1)
+ {
+ return;
+ }
+ }
+ tmp = tmp->GetNext();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && first != nullptr)
+ {
+ newline_del_between(vbrace_open, first);
+ }
+} // nl_create_one_liner
+
+
+static void nl_create_list_liner(Chunk *brace_open)
+{
+ LOG_FUNC_ENTRY();
+
+ // See if we get a newline between the next text and the vbrace_close
+ if (brace_open == nullptr)
+ {
+ return;
+ }
+ Chunk *closing = brace_open->GetNextType(CT_BRACE_CLOSE, brace_open->level);
+ Chunk *tmp = brace_open;
+
+ do
+ {
+ if (chunk_is_token(tmp, CT_COMMA))
+ {
+ return;
+ }
+ tmp = tmp->GetNext();
+ } while (tmp != closing);
+
+ newline_del_between(brace_open, closing);
+} // nl_create_list_liner
+
+
+void newlines_remove_newlines(void)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LBLANK, "%s(%d):\n", __func__, __LINE__);
+ Chunk *pc = Chunk::GetHead();
+
+ if (!chunk_is_newline(pc))
+ {
+ pc = pc->GetNextNl();
+ }
+ Chunk *next;
+ Chunk *prev;
+
+ while (pc->IsNotNullChunk())
+ {
+ // Remove all newlines not in preproc
+ if (!pc->flags.test(PCF_IN_PREPROC))
+ {
+ next = pc->GetNext();
+ prev = pc->GetPrev();
+ newline_iarf(pc, IARF_REMOVE);
+
+ if (next == Chunk::GetHead())
+ {
+ pc = next;
+ continue;
+ }
+ else if ( prev->IsNotNullChunk()
+ && !chunk_is_newline(prev->GetNext()))
+ {
+ pc = prev;
+ }
+ }
+ pc = pc->GetNextNl();
+ }
+} // newlines_remove_newlines
+
+
+void newlines_remove_disallowed()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+ Chunk *next;
+
+ while ((pc = pc->GetNextNl())->IsNotNullChunk())
+ {
+ LOG_FMT(LBLANKD, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->nl_count);
+
+ next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && !chunk_is_token(next, CT_NEWLINE)
+ && !can_increase_nl(pc))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): force to 1 orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+
+ if (pc->nl_count != 1)
+ {
+ pc->nl_count = 1;
+ MARK_CHANGE();
+ }
+ }
+ }
+} // newlines_remove_disallowed
+
+
+void newlines_cleanup_angles()
+{
+ // Issue #1167
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ char copy[1000];
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy));
+
+ if (chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ newline_template(pc);
+ }
+ }
+} // newlines_cleanup_angles
+
+
+void newlines_cleanup_braces(bool first)
+{
+ LOG_FUNC_ENTRY();
+
+ // Get the first token that's not an empty line:
+ Chunk *pc = Chunk::GetHead();
+
+ if (chunk_is_newline(pc))
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ for ( ; pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ char copy[1000];
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy));
+
+ if ( chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_CONSTEXPR))
+ {
+ log_rule_B("nl_if_brace");
+ newlines_if_for_while_switch(pc, options::nl_if_brace());
+ }
+ else if (chunk_is_token(pc, CT_ELSEIF))
+ {
+ log_rule_B("nl_elseif_brace");
+ iarf_e arg = options::nl_elseif_brace();
+ log_rule_B("nl_if_brace");
+ newlines_if_for_while_switch(
+ pc, (arg != IARF_IGNORE) ? arg : options::nl_if_brace());
+ }
+ else if (chunk_is_token(pc, CT_FOR))
+ {
+ log_rule_B("nl_for_brace");
+ newlines_if_for_while_switch(pc, options::nl_for_brace());
+ }
+ else if (chunk_is_token(pc, CT_CATCH))
+ {
+ log_rule_B("nl_oc_brace_catch");
+
+ if ( language_is_set(LANG_OC)
+ && (pc->str[0] == '@')
+ && (options::nl_oc_brace_catch() != IARF_IGNORE))
+ {
+ newlines_cuddle_uncuddle(pc, options::nl_oc_brace_catch());
+ }
+ else
+ {
+ log_rule_B("nl_brace_catch");
+ newlines_cuddle_uncuddle(pc, options::nl_brace_catch());
+ }
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ log_rule_B("nl_oc_catch_brace");
+
+ if ( language_is_set(LANG_OC)
+ && (options::nl_oc_catch_brace() != IARF_IGNORE))
+ {
+ log_rule_B("nl_oc_catch_brace");
+ newlines_do_else(pc, options::nl_oc_catch_brace());
+ }
+ else
+ {
+ log_rule_B("nl_catch_brace");
+ newlines_do_else(pc, options::nl_catch_brace());
+ }
+ }
+ else
+ {
+ log_rule_B("nl_oc_catch_brace");
+
+ if ( language_is_set(LANG_OC)
+ && (options::nl_oc_catch_brace() != IARF_IGNORE))
+ {
+ newlines_if_for_while_switch(pc, options::nl_oc_catch_brace());
+ }
+ else
+ {
+ log_rule_B("nl_catch_brace");
+ newlines_if_for_while_switch(pc, options::nl_catch_brace());
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_WHILE))
+ {
+ log_rule_B("nl_while_brace");
+ newlines_if_for_while_switch(pc, options::nl_while_brace());
+ }
+ else if (chunk_is_token(pc, CT_USING_STMT))
+ {
+ log_rule_B("nl_using_brace");
+ newlines_if_for_while_switch(pc, options::nl_using_brace());
+ }
+ else if (chunk_is_token(pc, CT_D_SCOPE_IF))
+ {
+ log_rule_B("nl_scope_brace");
+ newlines_if_for_while_switch(pc, options::nl_scope_brace());
+ }
+ else if (chunk_is_token(pc, CT_UNITTEST))
+ {
+ log_rule_B("nl_unittest_brace");
+ newlines_do_else(pc, options::nl_unittest_brace());
+ }
+ else if (chunk_is_token(pc, CT_D_VERSION_IF))
+ {
+ log_rule_B("nl_version_brace");
+ newlines_if_for_while_switch(pc, options::nl_version_brace());
+ }
+ else if (chunk_is_token(pc, CT_SWITCH))
+ {
+ log_rule_B("nl_switch_brace");
+ newlines_if_for_while_switch(pc, options::nl_switch_brace());
+ }
+ else if (chunk_is_token(pc, CT_SYNCHRONIZED))
+ {
+ log_rule_B("nl_synchronized_brace");
+ newlines_if_for_while_switch(pc, options::nl_synchronized_brace());
+ }
+ else if (chunk_is_token(pc, CT_DO))
+ {
+ log_rule_B("nl_do_brace");
+ newlines_do_else(pc, options::nl_do_brace());
+ }
+ else if (chunk_is_token(pc, CT_ELSE))
+ {
+ log_rule_B("nl_brace_else");
+ newlines_cuddle_uncuddle(pc, options::nl_brace_else());
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_ELSEIF))
+ {
+ log_rule_B("nl_else_if");
+ newline_iarf_pair(pc, next, options::nl_else_if());
+ }
+ log_rule_B("nl_else_brace");
+ newlines_do_else(pc, options::nl_else_brace());
+ }
+ else if (chunk_is_token(pc, CT_TRY))
+ {
+ log_rule_B("nl_try_brace");
+ newlines_do_else(pc, options::nl_try_brace());
+ // Issue #1734
+ Chunk *po = pc->GetNextNcNnl();
+ flag_parens(po, PCF_IN_TRY_BLOCK, po->type, CT_NONE, false);
+ }
+ else if (chunk_is_token(pc, CT_GETSET))
+ {
+ log_rule_B("nl_getset_brace");
+ newlines_do_else(pc, options::nl_getset_brace());
+ }
+ else if (chunk_is_token(pc, CT_FINALLY))
+ {
+ log_rule_B("nl_brace_finally");
+ newlines_cuddle_uncuddle(pc, options::nl_brace_finally());
+ log_rule_B("nl_finally_brace");
+ newlines_do_else(pc, options::nl_finally_brace());
+ }
+ else if (chunk_is_token(pc, CT_WHILE_OF_DO))
+ {
+ log_rule_B("nl_brace_while");
+ newlines_cuddle_uncuddle(pc, options::nl_brace_while());
+ }
+ else if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ switch (get_chunk_parent_type(pc))
+ {
+ case CT_DOUBLE_BRACE:
+ {
+ log_rule_B("nl_paren_dbrace_open");
+
+ if (options::nl_paren_dbrace_open() != IARF_IGNORE)
+ {
+ Chunk *prev = pc->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #2279
+
+ if (chunk_is_paren_close(prev))
+ {
+ log_rule_B("nl_paren_dbrace_open");
+ newline_iarf_pair(prev, pc, options::nl_paren_dbrace_open());
+ }
+ }
+ break;
+ }
+
+ case CT_ENUM:
+ {
+ log_rule_B("nl_enum_own_lines");
+
+ if (options::nl_enum_own_lines() != IARF_IGNORE)
+ {
+ newlines_enum_entries(pc, options::nl_enum_own_lines());
+ }
+ log_rule_B("nl_ds_struct_enum_cmt");
+
+ if (options::nl_ds_struct_enum_cmt())
+ {
+ newlines_double_space_struct_enum_union(pc);
+ }
+ break;
+ }
+
+ case CT_STRUCT:
+ case CT_UNION:
+ {
+ log_rule_B("nl_ds_struct_enum_cmt");
+
+ if (options::nl_ds_struct_enum_cmt())
+ {
+ newlines_double_space_struct_enum_union(pc);
+ }
+ break;
+ }
+
+ case CT_CLASS:
+ {
+ if (pc->level == pc->brace_level)
+ {
+ log_rule_B("nl_class_brace");
+ newlines_do_else(pc->GetPrevNnl(), options::nl_class_brace());
+ }
+ break;
+ }
+
+ case CT_OC_CLASS:
+ {
+ if (pc->level == pc->brace_level)
+ {
+ // Request #126
+ // introduce two new options
+ // look back if we have a @interface or a @implementation
+ for (Chunk *tmp = pc->GetPrev(); tmp->IsNotNullChunk(); tmp = tmp->GetPrev())
+ {
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+
+ if ( chunk_is_token(tmp, CT_OC_INTF)
+ || chunk_is_token(tmp, CT_OC_IMPL))
+ {
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, may be remove/force newline before {\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+
+ if (chunk_is_token(tmp, CT_OC_INTF))
+ {
+ log_rule_B("nl_oc_interface_brace");
+ newlines_do_else(pc->GetPrevNnl(), options::nl_oc_interface_brace());
+ }
+ else
+ {
+ log_rule_B("nl_oc_implementation_brace");
+ newlines_do_else(pc->GetPrevNnl(), options::nl_oc_implementation_brace());
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case CT_BRACED_INIT_LIST:
+ {
+ // Issue #1052
+ log_rule_B("nl_create_list_one_liner");
+
+ if (options::nl_create_list_one_liner())
+ {
+ nl_create_list_liner(pc);
+ break;
+ }
+ Chunk *prev = pc->GetPrevNnl();
+
+ if ( prev->IsNotNullChunk()
+ && ( prev->type == CT_TYPE
+ || prev->type == CT_WORD
+ || prev->type == CT_ASSIGN // Issue #2957
+ || prev->parent_type == CT_TEMPLATE
+ || prev->parent_type == CT_DECLTYPE))
+ {
+ log_rule_B("nl_type_brace_init_lst");
+ newline_iarf_pair(prev, pc, options::nl_type_brace_init_lst(), true);
+ }
+ break;
+ }
+
+ case CT_OC_BLOCK_EXPR:
+ {
+ // issue # 477
+ log_rule_B("nl_oc_block_brace");
+ newline_iarf_pair(pc->GetPrev(), pc, options::nl_oc_block_brace());
+ break;
+ }
+
+ case CT_FUNC_CLASS_DEF: // Issue #2343
+ {
+ if (!one_liner_nl_ok(pc))
+ {
+ LOG_FMT(LNL1LINE, "a new line may NOT be added\n");
+ // no change - preserve one liner body
+ }
+ else
+ {
+ log_rule_B("nl_before_opening_brace_func_class_def");
+
+ if (options::nl_before_opening_brace_func_class_def() != IARF_IGNORE)
+ {
+ newline_iarf_pair(pc->GetPrev(), pc, options::nl_before_opening_brace_func_class_def());
+ }
+ }
+ }
+
+ default:
+ {
+ break;
+ }
+ } // switch
+
+ log_rule_B("nl_brace_brace");
+
+ if (options::nl_brace_brace() != IARF_IGNORE)
+ {
+ Chunk *next = pc->GetNextNc(E_Scope::PREPROC);
+
+ if (chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ newline_iarf_pair(pc, next, options::nl_brace_brace());
+ }
+ }
+ Chunk *next = pc->GetNextNnl();
+
+ if (next->IsNullChunk())
+ {
+ // do nothing
+ }
+ else if (chunk_is_token(next, CT_BRACE_CLOSE))
+ {
+ // TODO: add an option to split open empty statements? { };
+ }
+ else if (chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ // already handled
+ }
+ else
+ {
+ next = pc->GetNextNcNnl();
+
+ // Handle unnamed temporary direct-list-initialization
+ if (get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST)
+ {
+ log_rule_B("nl_type_brace_init_lst_open");
+ newline_iarf_pair(pc, pc->GetNextNnl(),
+ options::nl_type_brace_init_lst_open(), true);
+ }
+ // Handle nl_after_brace_open
+ else if ( ( get_chunk_parent_type(pc) == CT_CPP_LAMBDA
+ || pc->level == pc->brace_level)
+ && options::nl_after_brace_open())
+ {
+ log_rule_B("nl_after_brace_open");
+
+ if (!one_liner_nl_ok(pc))
+ {
+ LOG_FMT(LNL1LINE, "a new line may NOT be added (nl_after_brace_open)\n");
+ // no change - preserve one liner body
+ }
+ else if ( pc->flags.test(PCF_IN_ARRAY_ASSIGN)
+ || pc->flags.test(PCF_IN_PREPROC))
+ {
+ // no change - don't break up array assignments or preprocessors
+ }
+ else
+ {
+ // Step back from next to the first non-newline item
+ Chunk *tmp = next->GetPrev();
+
+ while (tmp != pc)
+ {
+ if (tmp->IsComment())
+ {
+ log_rule_B("nl_after_brace_open_cmt");
+
+ if ( !options::nl_after_brace_open_cmt()
+ && chunk_is_not_token(tmp, CT_COMMENT_MULTI))
+ {
+ break;
+ }
+ }
+ tmp = tmp->GetPrev();
+ }
+ // Add the newline
+ newline_iarf(tmp, IARF_ADD);
+ }
+ }
+ }
+ // braced-init-list is more like a function call with arguments,
+ // than curly braces that determine a structure of a source code,
+ // so, don't add a newline before a closing brace. Issue #1405.
+ log_rule_B("nl_type_brace_init_lst_open");
+ log_rule_B("nl_type_brace_init_lst_close");
+
+ if (!( get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST
+ && options::nl_type_brace_init_lst_open() == IARF_IGNORE
+ && options::nl_type_brace_init_lst_close() == IARF_IGNORE))
+ {
+ newlines_brace_pair(pc);
+ }
+
+ // Handle nl_before_brace_open
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ && pc->level == pc->brace_level
+ && options::nl_before_brace_open())
+ {
+ log_rule_B("nl_before_brace_open");
+
+ if (!one_liner_nl_ok(pc))
+ {
+ LOG_FMT(LNL1LINE, "a new line may NOT be added (nl_before_brace_open)\n");
+ // no change - preserve one liner body
+ }
+ else if ( pc->flags.test(PCF_IN_PREPROC)
+ || pc->flags.test(PCF_IN_ARRAY_ASSIGN))
+ {
+ // no change - don't break up array assignments or preprocessors
+ }
+ else
+ {
+ // Step back to previous non-newline item
+ Chunk *tmp = pc->GetPrev();
+
+ if (!chunk_is_token(tmp, CT_NEWLINE))
+ {
+ newline_iarf(tmp, IARF_ADD);
+ }
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ // newline between a close brace and x
+ log_rule_B("nl_brace_brace");
+
+ if (options::nl_brace_brace() != IARF_IGNORE)
+ {
+ Chunk *next = pc->GetNextNc(E_Scope::PREPROC);
+
+ if (chunk_is_token(next, CT_BRACE_CLOSE))
+ {
+ log_rule_B("nl_brace_brace");
+ newline_iarf_pair(pc, next, options::nl_brace_brace());
+ }
+ }
+ log_rule_B("nl_brace_square");
+
+ if (options::nl_brace_square() != IARF_IGNORE)
+ {
+ Chunk *next = pc->GetNextNc(E_Scope::PREPROC);
+
+ if (chunk_is_token(next, CT_SQUARE_CLOSE))
+ {
+ log_rule_B("nl_brace_square");
+ newline_iarf_pair(pc, next, options::nl_brace_square());
+ }
+ }
+ log_rule_B("nl_brace_fparen");
+
+ if (options::nl_brace_fparen() != IARF_IGNORE)
+ {
+ Chunk *next = pc->GetNextNc(E_Scope::PREPROC);
+
+ log_rule_B("nl_brace_fparen");
+
+ if ( chunk_is_token(next, CT_NEWLINE)
+ && (options::nl_brace_fparen() == IARF_REMOVE))
+ {
+ next = next->GetNextNc(E_Scope::PREPROC); // Issue #1000
+ }
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ log_rule_B("nl_brace_fparen");
+ newline_iarf_pair(pc, next, options::nl_brace_fparen());
+ }
+ }
+ // newline before a close brace
+ log_rule_B("nl_type_brace_init_lst_close");
+
+ if ( get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST
+ && options::nl_type_brace_init_lst_close() != IARF_IGNORE)
+ {
+ // Handle unnamed temporary direct-list-initialization
+ newline_iarf_pair(pc->GetPrevNnl(), pc,
+ options::nl_type_brace_init_lst_close(), true);
+ }
+ // blanks before a close brace
+ log_rule_B("eat_blanks_before_close_brace");
+
+ if (options::eat_blanks_before_close_brace())
+ {
+ // Limit the newlines before the close brace to 1
+ Chunk *prev = pc->GetPrev();
+
+ if (chunk_is_newline(prev))
+ {
+ log_rule_B("nl_inside_namespace");
+ log_rule_B("nl_inside_empty_func");
+
+ if ( options::nl_inside_empty_func() > 0
+ && chunk_is_token(pc->GetPrevNnl(), CT_BRACE_OPEN)
+ && ( get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_DEF))
+ {
+ blank_line_set(prev, options::nl_inside_empty_func);
+ }
+ else if ( options::nl_inside_namespace() > 0
+ && get_chunk_parent_type(pc) == CT_NAMESPACE)
+ {
+ blank_line_set(prev, options::nl_inside_namespace);
+ }
+ else if (prev->nl_count != 1)
+ {
+ prev->nl_count = 1;
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_before_close_brace %zu\n",
+ __func__, __LINE__, prev->orig_line);
+ MARK_CHANGE();
+ }
+ }
+ }
+ else if ( options::nl_ds_struct_enum_close_brace()
+ && ( get_chunk_parent_type(pc) == CT_ENUM
+ || get_chunk_parent_type(pc) == CT_STRUCT
+ || get_chunk_parent_type(pc) == CT_UNION))
+ {
+ log_rule_B("nl_ds_struct_enum_close_brace");
+
+ if (!pc->flags.test(PCF_ONE_LINER))
+ {
+ // Make sure the brace is preceded by two newlines
+ Chunk *prev = pc->GetPrev();
+
+ if (!chunk_is_newline(prev))
+ {
+ prev = newline_add_before(pc);
+ }
+
+ if (prev->nl_count < 2)
+ {
+ double_newline(prev);
+ }
+ }
+ }
+ // Force a newline after a close brace
+ log_rule_B("nl_brace_struct_var");
+
+ if ( (options::nl_brace_struct_var() != IARF_IGNORE)
+ && ( get_chunk_parent_type(pc) == CT_STRUCT
+ || get_chunk_parent_type(pc) == CT_ENUM
+ || get_chunk_parent_type(pc) == CT_UNION))
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( chunk_is_not_token(next, CT_SEMICOLON)
+ && chunk_is_not_token(next, CT_COMMA))
+ {
+ log_rule_B("nl_brace_struct_var");
+ newline_iarf(pc, options::nl_brace_struct_var());
+ }
+ }
+ else if ( get_chunk_parent_type(pc) != CT_OC_AT
+ && get_chunk_parent_type(pc) != CT_BRACED_INIT_LIST
+ && ( options::nl_after_brace_close()
+ || get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || get_chunk_parent_type(pc) == CT_OC_MSG_DECL))
+ {
+ log_rule_B("nl_after_brace_close");
+ Chunk *next = pc->GetNext();
+
+ if ( chunk_is_not_token(next, CT_SEMICOLON)
+ && chunk_is_not_token(next, CT_COMMA)
+ && chunk_is_not_token(next, CT_SPAREN_CLOSE) // Issue #664
+ && chunk_is_not_token(next, CT_SQUARE_CLOSE)
+ && chunk_is_not_token(next, CT_FPAREN_CLOSE)
+ && chunk_is_not_token(next, CT_PAREN_CLOSE)
+ && chunk_is_not_token(next, CT_WHILE_OF_DO)
+ && chunk_is_not_token(next, CT_VBRACE_CLOSE) // Issue #666
+ && ( chunk_is_not_token(next, CT_BRACE_CLOSE)
+ || !next->flags.test(PCF_ONE_LINER)) // #1258
+ && !pc->flags.test(PCF_IN_ARRAY_ASSIGN)
+ && !pc->flags.test(PCF_IN_TYPEDEF)
+ && !chunk_is_newline(next)
+ && !next->IsComment())
+ {
+ // #1258
+ // dont add newline between two consecutive braces closes, if the second is a part of one liner.
+ newline_end_newline(pc);
+ }
+ }
+ else if (get_chunk_parent_type(pc) == CT_NAMESPACE)
+ {
+ log_rule_B("nl_after_namespace");
+
+ if (options::nl_after_namespace() > 0)
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->IsNotNullChunk())
+ {
+ newline_add_before(next);
+ // newline_iarf(next, IARF_ADD);
+ }
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ log_rule_B("nl_after_vbrace_open");
+ log_rule_B("nl_after_vbrace_open_empty");
+
+ if ( options::nl_after_vbrace_open()
+ || options::nl_after_vbrace_open_empty())
+ {
+ Chunk *next = pc->GetNext(E_Scope::PREPROC);
+ bool add_it;
+
+ if (chunk_is_semicolon(next))
+ {
+ log_rule_B("nl_after_vbrace_open_empty");
+ add_it = options::nl_after_vbrace_open_empty();
+ }
+ else
+ {
+ log_rule_B("nl_after_vbrace_open");
+ add_it = ( options::nl_after_vbrace_open()
+ && chunk_is_not_token(next, CT_VBRACE_CLOSE)
+ && !next->IsComment()
+ && !chunk_is_newline(next));
+ }
+
+ if (add_it)
+ {
+ newline_iarf(pc, IARF_ADD);
+ }
+ }
+ log_rule_B("nl_create_if_one_liner");
+ log_rule_B("nl_create_for_one_liner");
+ log_rule_B("nl_create_while_one_liner");
+
+ if ( ( ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSEIF
+ || get_chunk_parent_type(pc) == CT_ELSE)
+ && options::nl_create_if_one_liner())
+ || ( get_chunk_parent_type(pc) == CT_FOR
+ && options::nl_create_for_one_liner())
+ || ( get_chunk_parent_type(pc) == CT_WHILE
+ && options::nl_create_while_one_liner()))
+ {
+ nl_create_one_liner(pc);
+ }
+ log_rule_B("nl_split_if_one_liner");
+ log_rule_B("nl_split_for_one_liner");
+ log_rule_B("nl_split_while_one_liner");
+
+ if ( ( ( get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSEIF
+ || get_chunk_parent_type(pc) == CT_ELSE)
+ && options::nl_split_if_one_liner())
+ || ( get_chunk_parent_type(pc) == CT_FOR
+ && options::nl_split_for_one_liner())
+ || ( get_chunk_parent_type(pc) == CT_WHILE
+ && options::nl_split_while_one_liner()))
+ {
+ if (pc->flags.test(PCF_ONE_LINER))
+ {
+ // split one-liner
+ Chunk *end = pc->GetNext()->GetNextType(CT_SEMICOLON, -1)->GetNext();
+ // Scan for clear flag
+ LOG_FMT(LNEWLINE, "(%d) ", __LINE__);
+ LOG_FMT(LNEWLINE, "\n");
+
+ for (Chunk *temp = pc; temp != end; temp = temp->GetNext())
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): Text() is '%s', type is %s, level is %zu\n",
+ __func__, __LINE__, temp->Text(), get_token_name(temp->type), temp->level);
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, temp->flags);
+ chunk_flags_clr(temp, PCF_ONE_LINER);
+ }
+
+ // split
+ newline_add_between(pc, pc->next);
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_CLOSE))
+ {
+ log_rule_B("nl_after_vbrace_close");
+
+ if (options::nl_after_vbrace_close())
+ {
+ if (!chunk_is_newline(pc->GetNextNc()))
+ {
+ newline_iarf(pc, IARF_ADD);
+ }
+ }
+ }
+ else if ( chunk_is_token(pc, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(pc) == CT_OC_MSG)
+ {
+ log_rule_B("nl_oc_msg_args");
+
+ if (options::nl_oc_msg_args())
+ {
+ newline_oc_msg(pc);
+ }
+ }
+ else if (chunk_is_token(pc, CT_STRUCT))
+ {
+ log_rule_B("nl_struct_brace");
+ newlines_struct_union(pc, options::nl_struct_brace(), true);
+ }
+ else if (chunk_is_token(pc, CT_UNION))
+ {
+ log_rule_B("nl_union_brace");
+ newlines_struct_union(pc, options::nl_union_brace(), true);
+ }
+ else if (chunk_is_token(pc, CT_ENUM))
+ {
+ newlines_enum(pc);
+ }
+ else if (chunk_is_token(pc, CT_CASE))
+ {
+ // Note: 'default' also maps to CT_CASE
+ log_rule_B("nl_before_case");
+
+ if (options::nl_before_case())
+ {
+ newline_case(pc);
+ }
+ }
+ else if (chunk_is_token(pc, CT_THROW))
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( chunk_is_token(prev, CT_PAREN_CLOSE)
+ || chunk_is_token(prev, CT_FPAREN_CLOSE)) // Issue #1122
+ {
+ log_rule_B("nl_before_throw");
+ newline_iarf(pc->GetPrevNcNnlNi(), options::nl_before_throw()); // Issue #2279
+ }
+ }
+ else if ( chunk_is_token(pc, CT_QUALIFIER)
+ && !strcmp(pc->Text(), "throws"))
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( chunk_is_token(prev, CT_PAREN_CLOSE)
+ || chunk_is_token(prev, CT_FPAREN_CLOSE)) // Issue #1122
+ {
+ log_rule_B("nl_before_throw");
+ newline_iarf(pc->GetPrevNcNnlNi(), options::nl_before_throw()); // Issue #2279
+ }
+ }
+ else if (chunk_is_token(pc, CT_CASE_COLON))
+ {
+ Chunk *next = pc->GetNextNnl();
+
+ log_rule_B("nl_case_colon_brace");
+
+ if ( chunk_is_token(next, CT_BRACE_OPEN)
+ && options::nl_case_colon_brace() != IARF_IGNORE)
+ {
+ newline_iarf(pc, options::nl_case_colon_brace());
+ }
+ else if (options::nl_after_case())
+ {
+ log_rule_B("nl_after_case");
+ newline_case_colon(pc);
+ }
+ }
+ else if (chunk_is_token(pc, CT_SPAREN_CLOSE))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_BRACE_OPEN))
+ {
+ /*
+ * TODO: this could be used to control newlines between the
+ * the if/while/for/switch close parenthesis and the open brace, but
+ * that is currently handled elsewhere.
+ */
+ }
+ }
+ else if (chunk_is_token(pc, CT_RETURN))
+ {
+ log_rule_B("nl_before_return");
+
+ if (options::nl_before_return())
+ {
+ newline_before_return(pc);
+ }
+ log_rule_B("nl_after_return");
+
+ if (options::nl_after_return())
+ {
+ newline_after_return(pc);
+ }
+ }
+ else if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ log_rule_B("nl_after_semicolon");
+
+ if ( !pc->flags.test(PCF_IN_SPAREN)
+ && !pc->flags.test(PCF_IN_PREPROC)
+ && options::nl_after_semicolon())
+ {
+ Chunk *next = pc->GetNext();
+
+ while (chunk_is_token(next, CT_VBRACE_CLOSE))
+ {
+ next = next->GetNext();
+ }
+
+ if ( next->IsNotNullChunk()
+ && !next->IsComment()
+ && !chunk_is_newline(next))
+ {
+ if (one_liner_nl_ok(next))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): a new line may be added\n", __func__, __LINE__);
+ newline_iarf(pc, IARF_ADD);
+ }
+ else
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): a new line may NOT be added\n", __func__, __LINE__);
+ }
+ }
+ }
+ else if (get_chunk_parent_type(pc) == CT_CLASS)
+ {
+ log_rule_B("nl_after_class");
+
+ if (options::nl_after_class() > 0)
+ {
+ newline_iarf(pc, IARF_ADD);
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_FPAREN_OPEN))
+ {
+ log_rule_B("nl_func_decl_start");
+ log_rule_B("nl_func_def_start");
+ log_rule_B("nl_func_decl_start_single");
+ log_rule_B("nl_func_def_start_single");
+ log_rule_B("nl_func_decl_start_multi_line");
+ log_rule_B("nl_func_def_start_multi_line");
+ log_rule_B("nl_func_decl_args");
+ log_rule_B("nl_func_def_args");
+ log_rule_B("nl_func_decl_args_multi_line");
+ log_rule_B("nl_func_def_args_multi_line");
+ log_rule_B("nl_func_decl_end");
+ log_rule_B("nl_func_def_end");
+ log_rule_B("nl_func_decl_end_single");
+ log_rule_B("nl_func_def_end_single");
+ log_rule_B("nl_func_decl_end_multi_line");
+ log_rule_B("nl_func_def_end_multi_line");
+ log_rule_B("nl_func_decl_empty");
+ log_rule_B("nl_func_def_empty");
+ log_rule_B("nl_func_type_name");
+ log_rule_B("nl_func_type_name_class");
+ log_rule_B("nl_func_class_scope");
+ log_rule_B("nl_func_scope_name");
+ log_rule_B("nl_func_proto_type_name");
+ log_rule_B("nl_func_paren");
+ log_rule_B("nl_func_def_paren");
+ log_rule_B("nl_func_def_paren_empty");
+ log_rule_B("nl_func_paren_empty");
+ log_rule_B("nl_func_call_args");
+
+ if ( ( ( get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_PROTO
+ || get_chunk_parent_type(pc) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(pc) == CT_FUNC_CLASS_PROTO
+ || get_chunk_parent_type(pc) == CT_OPERATOR)
+ && ( options::nl_func_decl_start() != IARF_IGNORE
+ || options::nl_func_def_start() != IARF_IGNORE
+ || options::nl_func_decl_start_single() != IARF_IGNORE
+ || options::nl_func_def_start_single() != IARF_IGNORE
+ || options::nl_func_decl_start_multi_line()
+ || options::nl_func_def_start_multi_line()
+ || options::nl_func_decl_args() != IARF_IGNORE
+ || options::nl_func_def_args() != IARF_IGNORE
+ || options::nl_func_decl_args_multi_line()
+ || options::nl_func_def_args_multi_line()
+ || options::nl_func_decl_end() != IARF_IGNORE
+ || options::nl_func_def_end() != IARF_IGNORE
+ || options::nl_func_decl_end_single() != IARF_IGNORE
+ || options::nl_func_def_end_single() != IARF_IGNORE
+ || options::nl_func_decl_end_multi_line()
+ || options::nl_func_def_end_multi_line()
+ || options::nl_func_decl_empty() != IARF_IGNORE
+ || options::nl_func_def_empty() != IARF_IGNORE
+ || options::nl_func_type_name() != IARF_IGNORE
+ || options::nl_func_type_name_class() != IARF_IGNORE
+ || options::nl_func_class_scope() != IARF_IGNORE
+ || options::nl_func_scope_name() != IARF_IGNORE
+ || options::nl_func_proto_type_name() != IARF_IGNORE
+ || options::nl_func_paren() != IARF_IGNORE
+ || options::nl_func_def_paren() != IARF_IGNORE
+ || options::nl_func_def_paren_empty() != IARF_IGNORE
+ || options::nl_func_paren_empty() != IARF_IGNORE))
+
+ || ( get_chunk_parent_type(pc) == CT_FUNC_CALL // Issue #2604
+ && options::nl_func_call_args() != IARF_IGNORE))
+ {
+ newline_func_def_or_call(pc);
+ }
+ else if ( ( get_chunk_parent_type(pc) == CT_FUNC_CALL // Issue #2020
+ || get_chunk_parent_type(pc) == CT_FUNC_CALL_USER)
+ && options::nl_func_call_start() != IARF_IGNORE)
+ {
+ log_rule_B("nl_func_call_start");
+ newline_iarf(pc, options::nl_func_call_start());
+ }
+ else if ( ( get_chunk_parent_type(pc) == CT_FUNC_CALL
+ || get_chunk_parent_type(pc) == CT_FUNC_CALL_USER)
+ && ( (options::nl_func_call_start_multi_line())
+ || (options::nl_func_call_args_multi_line())
+ || (options::nl_func_call_end_multi_line())
+ || (options::nl_func_call_paren() != IARF_IGNORE)
+ || (options::nl_func_call_paren_empty() != IARF_IGNORE)
+ || (options::nl_func_call_empty() != IARF_IGNORE)))
+ {
+ log_rule_B("nl_func_call_start_multi_line");
+ log_rule_B("nl_func_call_args_multi_line");
+ log_rule_B("nl_func_call_end_multi_line");
+ log_rule_B("nl_func_call_paren");
+ log_rule_B("nl_func_call_paren_empty");
+ log_rule_B("nl_func_call_empty");
+
+ if ( options::nl_func_call_paren() != IARF_IGNORE
+ || options::nl_func_call_paren_empty() != IARF_IGNORE
+ || options::nl_func_call_empty() != IARF_IGNORE)
+ {
+ newline_func_def_or_call(pc);
+ }
+ newline_func_multi_line(pc);
+ }
+ else if ( first
+ && (options::nl_remove_extra_newlines() == 1))
+ {
+ log_rule_B("nl_remove_extra_newlines");
+ newline_iarf(pc, IARF_REMOVE);
+ }
+ }
+ else if (chunk_is_token(pc, CT_FPAREN_CLOSE)) // Issue #2758
+ {
+ if ( ( get_chunk_parent_type(pc) == CT_FUNC_CALL
+ || get_chunk_parent_type(pc) == CT_FUNC_CALL_USER)
+ && options::nl_func_call_end() != IARF_IGNORE)
+ {
+ log_rule_B("nl_func_call_end");
+ newline_iarf(pc->prev, options::nl_func_call_end());
+ }
+ }
+ else if (chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ if (get_chunk_parent_type(pc) == CT_TEMPLATE)
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && next->level == next->brace_level)
+ {
+ Chunk *tmp = pc->GetPrevType(CT_ANGLE_OPEN, pc->level)->GetPrevNcNnlNi(); // Issue #2279
+
+ if (chunk_is_token(tmp, CT_TEMPLATE))
+ {
+ if (chunk_is_token(next, CT_USING))
+ {
+ newline_iarf(pc, options::nl_template_using());
+ log_rule_B("nl_template_using");
+ }
+ else if (get_chunk_parent_type(next) == CT_FUNC_DEF) // function definition
+ {
+ iarf_e const action =
+ newline_template_option(
+ pc,
+ options::nl_template_func_def_special(),
+ options::nl_template_func_def(),
+ options::nl_template_func());
+ log_rule_B("nl_template_func_def_special");
+ log_rule_B("nl_template_func_def");
+ log_rule_B("nl_template_func");
+ newline_iarf(pc, action);
+ }
+ else if (get_chunk_parent_type(next) == CT_FUNC_PROTO) // function declaration
+ {
+ iarf_e const action =
+ newline_template_option(
+ pc,
+ options::nl_template_func_decl_special(),
+ options::nl_template_func_decl(),
+ options::nl_template_func());
+ log_rule_B("nl_template_func_decl_special");
+ log_rule_B("nl_template_func_decl");
+ log_rule_B("nl_template_func");
+ newline_iarf(pc, action);
+ }
+ else if ( chunk_is_token(next, CT_TYPE)
+ || chunk_is_token(next, CT_QUALIFIER)) // variable
+ {
+ newline_iarf(pc, options::nl_template_var());
+ log_rule_B("nl_template_var");
+ }
+ else if (next->flags.test(PCF_INCOMPLETE)) // class declaration
+ {
+ iarf_e const action =
+ newline_template_option(
+ pc,
+ options::nl_template_class_decl_special(),
+ options::nl_template_class_decl(),
+ options::nl_template_class());
+ log_rule_B("nl_template_class_decl_special");
+ log_rule_B("nl_template_class_decl");
+ log_rule_B("nl_template_class");
+ newline_iarf(pc, action);
+ }
+ else // class definition
+ {
+ iarf_e const action =
+ newline_template_option(
+ pc,
+ options::nl_template_class_def_special(),
+ options::nl_template_class_def(),
+ options::nl_template_class());
+ log_rule_B("nl_template_class_def_special");
+ log_rule_B("nl_template_class_def");
+ log_rule_B("nl_template_class");
+ newline_iarf(pc, action);
+ }
+ }
+ }
+ }
+ }
+ else if ( chunk_is_token(pc, CT_NAMESPACE)
+ && get_chunk_parent_type(pc) != CT_USING)
+ {
+ // Issue #2387
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNotNullChunk())
+ {
+ next = next->GetNextNcNnl();
+
+ if (!chunk_is_token(next, CT_ASSIGN))
+ {
+ // Issue #1235
+ // Issue #2186
+ Chunk *braceOpen = pc->GetNextType(CT_BRACE_OPEN, pc->level);
+
+ if (braceOpen->IsNullChunk())
+ {
+ // fatal error
+ LOG_FMT(LERR, "%s(%d): Missing BRACE_OPEN after namespace\n orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ exit(EXIT_FAILURE);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): braceOpen->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, braceOpen->orig_line, braceOpen->orig_col, braceOpen->Text());
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, braceOpen->flags);
+ newlines_namespace(pc);
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ if ( get_chunk_parent_type(pc) == CT_ASSIGN
+ && !pc->flags.test(PCF_ONE_LINER))
+ {
+ Chunk *tmp = pc->GetPrevNcNnlNi(); // Issue #2279
+ newline_iarf(tmp, options::nl_assign_square());
+ log_rule_B("nl_assign_square");
+
+ iarf_e arg = options::nl_after_square_assign();
+ log_rule_B("nl_after_square_assign");
+
+ if (options::nl_assign_square() & IARF_ADD)
+ {
+ log_rule_B("nl_assign_square");
+ arg = IARF_ADD;
+ }
+ newline_iarf(pc, arg);
+
+ /*
+ * if there is a newline after the open, then force a newline
+ * before the close
+ */
+ tmp = pc->GetNextNc();
+
+ if (chunk_is_newline(tmp))
+ {
+ tmp = pc->GetNextType(CT_SQUARE_CLOSE, pc->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ newline_add_before(tmp);
+ }
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_ACCESS))
+ {
+ // Make sure there is a newline before an access spec
+ if (options::nl_before_access_spec() > 0)
+ {
+ log_rule_B("nl_before_access_spec");
+ Chunk *prev = pc->GetPrev();
+
+ if (!chunk_is_newline(prev))
+ {
+ newline_add_before(pc);
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_ACCESS_COLON))
+ {
+ // Make sure there is a newline after an access spec
+ if (options::nl_after_access_spec() > 0)
+ {
+ log_rule_B("nl_after_access_spec");
+ Chunk *next = pc->GetNext();
+
+ if (!chunk_is_newline(next))
+ {
+ newline_add_before(next);
+ }
+ }
+ }
+ else if (chunk_is_token(pc, CT_PP_DEFINE))
+ {
+ if (options::nl_multi_line_define())
+ {
+ log_rule_B("nl_multi_line_define");
+ nl_handle_define(pc);
+ }
+ }
+ else if ( first
+ && (options::nl_remove_extra_newlines() == 1)
+ && !pc->flags.test(PCF_IN_PREPROC))
+ {
+ log_rule_B("nl_remove_extra_newlines");
+ newline_iarf(pc, IARF_REMOVE);
+ }
+ else if ( chunk_is_token(pc, CT_MEMBER)
+ && ( language_is_set(LANG_JAVA)
+ || language_is_set(LANG_CPP))) // Issue #2574
+ {
+ // Issue #1124
+ if (pc->parent_type != CT_FUNC_DEF)
+ {
+ newline_iarf(pc->GetPrevNnl(), options::nl_before_member());
+ log_rule_B("nl_before_member");
+ newline_iarf(pc, options::nl_after_member());
+ log_rule_B("nl_after_member");
+ }
+ }
+ else
+ {
+ // ignore it
+ }
+ }
+
+ newline_def_blk(Chunk::GetHead(), false);
+} // newlines_cleanup_braces
+
+
+static void nl_handle_define(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *nl = pc;
+ Chunk *ref = Chunk::NullChunkPtr;
+
+ while ((nl = nl->GetNext())->IsNotNullChunk())
+ {
+ if (chunk_is_token(nl, CT_NEWLINE))
+ {
+ return;
+ }
+
+ if ( chunk_is_token(nl, CT_MACRO)
+ || ( chunk_is_token(nl, CT_FPAREN_CLOSE)
+ && get_chunk_parent_type(nl) == CT_MACRO_FUNC))
+ {
+ ref = nl;
+ }
+
+ if (chunk_is_token(nl, CT_NL_CONT))
+ {
+ if (ref->IsNotNullChunk())
+ {
+ newline_add_after(ref);
+ }
+ return;
+ }
+ }
+} // nl_handle_define
+
+
+void newline_after_multiline_comment(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (chunk_is_not_token(pc, CT_COMMENT_MULTI))
+ {
+ continue;
+ }
+ Chunk *tmp = pc;
+
+ while ( ((tmp = tmp->GetNext())->IsNotNullChunk())
+ && !chunk_is_newline(tmp))
+ {
+ if (!tmp->IsComment())
+ {
+ newline_add_before(tmp);
+ break;
+ }
+ }
+ }
+} // newline_after_multiline_comment
+
+
+void newline_after_label_colon(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (chunk_is_not_token(pc, CT_LABEL_COLON))
+ {
+ continue;
+ }
+ newline_add_after(pc);
+ }
+} // newline_after_label_colon
+
+
+static bool is_class_one_liner(Chunk *pc)
+{
+ if ( ( chunk_is_token(pc, CT_FUNC_CLASS_DEF)
+ || chunk_is_token(pc, CT_FUNC_DEF))
+ && pc->flags.test(PCF_IN_CLASS))
+ {
+ // Find opening brace
+ pc = pc->GetNextType(CT_BRACE_OPEN, pc->level);
+ return( pc->IsNotNullChunk()
+ && pc->flags.test(PCF_ONE_LINER));
+ }
+ return(false);
+} // is_class_one_liner
+
+
+void newlines_insert_blank_lines(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ //LOG_FMT(LNEWLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ // __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ if (chunk_is_token(pc, CT_IF))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_if());
+ log_rule_B("nl_before_if");
+ newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_if());
+ log_rule_B("nl_after_if");
+ }
+ else if (chunk_is_token(pc, CT_FOR))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_for());
+ log_rule_B("nl_before_for");
+ newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_for());
+ log_rule_B("nl_after_for");
+ }
+ else if (chunk_is_token(pc, CT_WHILE))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_while());
+ log_rule_B("nl_before_while");
+ newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_while());
+ log_rule_B("nl_after_while");
+ }
+ else if (chunk_is_token(pc, CT_SWITCH))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_switch());
+ log_rule_B("nl_before_switch");
+ newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_switch());
+ log_rule_B("nl_after_switch");
+ }
+ else if (chunk_is_token(pc, CT_SYNCHRONIZED))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_synchronized());
+ log_rule_B("nl_before_synchronized");
+ newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_synchronized());
+ log_rule_B("nl_after_synchronized");
+ }
+ else if (chunk_is_token(pc, CT_DO))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_before_do());
+ log_rule_B("nl_before_do");
+ newlines_if_for_while_switch_post_blank_lines(pc, options::nl_after_do());
+ log_rule_B("nl_after_do");
+ }
+ else if (chunk_is_token(pc, CT_OC_INTF))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_oc_before_interface());
+ log_rule_B("nl_oc_before_interface");
+ }
+ else if (chunk_is_token(pc, CT_OC_END))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_oc_before_end());
+ log_rule_B("nl_oc_before_end");
+ }
+ else if (chunk_is_token(pc, CT_OC_IMPL))
+ {
+ newlines_if_for_while_switch_pre_blank_lines(pc, options::nl_oc_before_implementation());
+ log_rule_B("nl_oc_before_implementation");
+ }
+ else if ( chunk_is_token(pc, CT_FUNC_CLASS_DEF)
+ || chunk_is_token(pc, CT_FUNC_DEF)
+ || chunk_is_token(pc, CT_FUNC_CLASS_PROTO)
+ || chunk_is_token(pc, CT_FUNC_PROTO))
+ {
+ if ( options::nl_class_leave_one_liner_groups()
+ && is_class_one_liner(pc))
+ {
+ log_rule_B("nl_class_leave_one_liner_groups");
+ newlines_func_pre_blank_lines(pc, CT_FUNC_PROTO);
+ }
+ else
+ {
+ newlines_func_pre_blank_lines(pc, pc->type);
+ }
+ }
+ else
+ {
+ // ignore it
+ //LOG_FMT(LNEWLINE, "%s(%d): ignore it\n", __func__, __LINE__);
+ }
+ }
+} // newlines_insert_blank_lines
+
+
+void newlines_functions_remove_extra_blank_lines(void)
+{
+ LOG_FUNC_ENTRY();
+
+ const size_t nl_max_blank_in_func = options::nl_max_blank_in_func();
+
+ log_rule_B("nl_max_blank_in_func");
+
+ if (nl_max_blank_in_func == 0)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): nl_max_blank_in_func is zero\n", __func__, __LINE__);
+ return;
+ }
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+
+ if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
+ || ( get_chunk_parent_type(pc) != CT_FUNC_DEF
+ && get_chunk_parent_type(pc) != CT_CPP_LAMBDA))
+ {
+ continue;
+ }
+ const size_t startMoveLevel = pc->level;
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && pc->level == startMoveLevel)
+ {
+ break;
+ }
+
+ // delete newlines
+ if ( !chunk_is_token(pc, CT_COMMENT_MULTI) // Issue #2195
+ && pc->nl_count > nl_max_blank_in_func)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ pc->nl_count = nl_max_blank_in_func;
+ MARK_CHANGE();
+ remove_next_newlines(pc);
+ }
+ else
+ {
+ pc = pc->GetNext();
+ }
+ }
+ }
+} // newlines_functions_remove_extra_blank_lines
+
+
+void newlines_squeeze_ifdef(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc;
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( chunk_is_token(pc, CT_PREPROC)
+ && ( pc->level > 0
+ || options::nl_squeeze_ifdef_top_level()))
+ {
+ log_rule_B("nl_squeeze_ifdef_top_level");
+ Chunk *ppr = pc->GetNext();
+
+ if ( chunk_is_token(ppr, CT_PP_IF)
+ || chunk_is_token(ppr, CT_PP_ELSE)
+ || chunk_is_token(ppr, CT_PP_ENDIF))
+ {
+ Chunk *pnl = Chunk::NullChunkPtr;
+ Chunk *nnl = ppr->GetNextNl();
+
+ if ( chunk_is_token(ppr, CT_PP_ELSE)
+ || chunk_is_token(ppr, CT_PP_ENDIF))
+ {
+ pnl = pc->GetPrevNl();
+ }
+ Chunk *tmp1;
+ Chunk *tmp2;
+
+ if (nnl->IsNotNullChunk())
+ {
+ if (pnl->IsNotNullChunk())
+ {
+ if (pnl->nl_count > 1)
+ {
+ pnl->nl_count = 1;
+ MARK_CHANGE();
+
+ tmp1 = pnl->GetPrevNnl();
+ tmp2 = nnl->GetPrevNnl();
+
+ LOG_FMT(LNEWLINE, "%s(%d): moved from after line %zu to after %zu\n",
+ __func__, __LINE__, tmp1->orig_line, tmp2->orig_line);
+ }
+ }
+
+ if ( chunk_is_token(ppr, CT_PP_IF)
+ || chunk_is_token(ppr, CT_PP_ELSE))
+ {
+ if (nnl->nl_count > 1)
+ {
+ tmp1 = nnl->GetPrevNnl();
+ LOG_FMT(LNEWLINE, "%s(%d): trimmed newlines after line %zu from %zu\n",
+ __func__, __LINE__, tmp1->orig_line, nnl->nl_count);
+ nnl->nl_count = 1;
+ MARK_CHANGE();
+ }
+ }
+ }
+ }
+ }
+ }
+} // newlines_squeeze_ifdef
+
+
+void newlines_squeeze_paren_close(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc;
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ Chunk *next;
+ Chunk *prev;
+
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ prev = pc->GetPrev();
+ }
+ else
+ {
+ prev = pc;
+ }
+ next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && prev->IsNotNullChunk()
+ && chunk_is_paren_close(next)
+ && chunk_is_paren_close(prev))
+ {
+ Chunk *prev_op = chunk_skip_to_match_rev(prev);
+ Chunk *next_op = chunk_skip_to_match_rev(next);
+ bool flag = true;
+
+ if (true)
+ {
+ Chunk *tmp = prev;
+
+ while (chunk_is_paren_close(tmp))
+ {
+ tmp = tmp->GetPrev();
+ }
+
+ if (chunk_is_not_token(tmp, CT_NEWLINE))
+ {
+ flag = false;
+ }
+ }
+
+ if (flag)
+ {
+ if (are_chunks_in_same_line(next_op, prev_op))
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ pc = next;
+ }
+ newline_del_between(prev, next);
+ }
+ else
+ {
+ newline_add_between(prev, next);
+ }
+ }
+ }
+ }
+} // newlines_squeeze_paren_close
+
+
+void newlines_eat_start_end(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc;
+
+ // Process newlines at the start of the file
+ if ( cpd.frag_cols == 0
+ && ( (options::nl_start_of_file() & IARF_REMOVE)
+ || ( (options::nl_start_of_file() & IARF_ADD)
+ && (options::nl_start_of_file_min() > 0))))
+ {
+ log_rule_B("nl_start_of_file");
+ log_rule_B("nl_start_of_file_min");
+ pc = Chunk::GetHead();
+
+ if (pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ if (options::nl_start_of_file() == IARF_REMOVE)
+ {
+ log_rule_B("nl_start_of_file");
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_start_of_file %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ chunk_del(pc);
+ MARK_CHANGE();
+ }
+ else if ( options::nl_start_of_file() == IARF_FORCE
+ || (pc->nl_count < options::nl_start_of_file_min()))
+ {
+ log_rule_B("nl_start_of_file");
+ LOG_FMT(LBLANKD, "%s(%d): set_blanks_start_of_file %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ pc->nl_count = options::nl_start_of_file_min();
+ log_rule_B("nl_start_of_file_min");
+ MARK_CHANGE();
+ }
+ }
+ else if ( (options::nl_start_of_file() & IARF_ADD)
+ && (options::nl_start_of_file_min() > 0))
+ {
+ log_rule_B("nl_start_of_file");
+ log_rule_B("nl_start_of_file_min");
+ Chunk chunk;
+ set_chunk_type(&chunk, CT_NEWLINE);
+ chunk.orig_line = pc->orig_line;
+ chunk.orig_col = pc->orig_col;
+ chunk.pp_level = pc->pp_level;
+ chunk.nl_count = options::nl_start_of_file_min();
+ log_rule_B("nl_start_of_file_min");
+ chunk_add_before(&chunk, pc);
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline before '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ MARK_CHANGE();
+ }
+ }
+ }
+
+ // Process newlines at the end of the file
+ if ( cpd.frag_cols == 0
+ && ( (options::nl_end_of_file() & IARF_REMOVE)
+ || ( (options::nl_end_of_file() & IARF_ADD)
+ && (options::nl_end_of_file_min() > 0))))
+ {
+ log_rule_B("nl_end_of_file");
+ log_rule_B("nl_end_of_file_min");
+ pc = Chunk::GetTail();
+
+ if (pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ if (options::nl_end_of_file() == IARF_REMOVE)
+ {
+ log_rule_B("nl_end_of_file");
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_end_of_file %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ chunk_del(pc);
+ MARK_CHANGE();
+ }
+ else if ( options::nl_end_of_file() == IARF_FORCE
+ || (pc->nl_count < options::nl_end_of_file_min()))
+ {
+ log_rule_B("nl_end_of_file");
+ log_rule_B("nl_end_of_file_min");
+
+ if (pc->nl_count != options::nl_end_of_file_min())
+ {
+ log_rule_B("nl_end_of_file_min");
+ LOG_FMT(LBLANKD, "%s(%d): set_blanks_end_of_file %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ pc->nl_count = options::nl_end_of_file_min();
+ log_rule_B("nl_end_of_file_min");
+ MARK_CHANGE();
+ }
+ }
+ }
+ else if ( (options::nl_end_of_file() & IARF_ADD)
+ && (options::nl_end_of_file_min() > 0))
+ {
+ log_rule_B("nl_end_of_file");
+ log_rule_B("nl_end_of_file_min");
+ Chunk chunk;
+ set_chunk_type(&chunk, CT_NEWLINE);
+ chunk.orig_line = pc->orig_line;
+ chunk.orig_col = pc->orig_col;
+ chunk.pp_level = pc->pp_level;
+ chunk.nl_count = options::nl_end_of_file_min();
+ log_rule_B("nl_end_of_file_min");
+ chunk_add_before(&chunk, nullptr);
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline after '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ MARK_CHANGE();
+ }
+ }
+ }
+} // newlines_eat_start_end
+
+
+void newlines_chunk_pos(E_Token chunk_type, token_pos_e mode)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LNEWLINE, "%s(%d): mode is %s\n",
+ __func__, __LINE__, to_string(mode));
+
+ if ( !(mode & (TP_JOIN | TP_LEAD | TP_TRAIL))
+ && chunk_type != CT_COMMA)
+ {
+ return;
+ }
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ char copy[1000];
+ LOG_FMT(LNEWLINE, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy));
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, pc->flags);
+
+ if (chunk_is_token(pc, chunk_type))
+ {
+ token_pos_e mode_local;
+
+ if (chunk_type == CT_COMMA)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, pc->flags);
+
+ if (pc->flags.test(PCF_IN_CONST_ARGS)) // Issue #2250
+ {
+ continue;
+ }
+
+ /*
+ * for chunk_type == CT_COMMA
+ * we get 'mode' from options::pos_comma()
+ * BUT we must take care of options::pos_class_comma()
+ * TODO and options::pos_constr_comma()
+ */
+ if (pc->flags.test(PCF_IN_CLASS_BASE))
+ {
+ // change mode
+ log_rule_B("pos_class_comma");
+ mode_local = options::pos_class_comma();
+ }
+ else if (pc->flags.test(PCF_IN_ENUM))
+ {
+ log_rule_B("pos_enum_comma");
+ mode_local = options::pos_enum_comma();
+ }
+ else
+ {
+ mode_local = mode;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): mode_local is %s\n",
+ __func__, __LINE__, to_string(mode_local));
+ }
+ else
+ {
+ mode_local = mode;
+ }
+ Chunk *prev = pc->GetPrevNc();
+ Chunk *next = pc->GetNextNc();
+
+ LOG_FMT(LNEWLINE, "%s(%d): mode_local is %s\n",
+ __func__, __LINE__, to_string(mode_local));
+
+ LOG_FMT(LNEWLINE, "%s(%d): prev->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text());
+ LOG_FMT(LNEWLINE, "%s(%d): next->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, next->Text());
+ size_t nl_flag = ((chunk_is_newline(prev) ? 1 : 0) |
+ (chunk_is_newline(next) ? 2 : 0));
+ LOG_FMT(LNEWLINE, "%s(%d): nl_flag is %zu\n",
+ __func__, __LINE__, nl_flag);
+
+ if (mode_local & TP_JOIN)
+ {
+ if (nl_flag & 1)
+ {
+ // remove newline if not preceded by a comment
+ Chunk *prev2 = prev->GetPrev();
+
+ if ( prev2->IsNotNullChunk()
+ && !(prev2->IsComment()))
+ {
+ remove_next_newlines(prev2);
+ }
+ }
+
+ if (nl_flag & 2)
+ {
+ // remove newline if not followed by a comment or by '{'
+ Chunk *next2 = next->GetNext();
+
+ if ( next2->IsNotNullChunk()
+ && !next2->IsComment()
+ && !(chunk_is_token(next2, CT_BRACE_OPEN)))
+ {
+ remove_next_newlines(pc);
+ }
+ }
+ continue;
+ }
+
+ if ( ( nl_flag == 0
+ && !(mode_local & (TP_FORCE | TP_BREAK)))
+ || ( nl_flag == 3
+ && !(mode_local & TP_FORCE)))
+ {
+ // No newlines and not adding any or both and not forcing
+ continue;
+ }
+
+ if ( ( (mode_local & TP_LEAD)
+ && nl_flag == 1)
+ || ( (mode_local & TP_TRAIL)
+ && nl_flag == 2))
+ {
+ // Already a newline before (lead) or after (trail)
+ continue;
+ }
+
+ // If there were no newlines, we need to add one
+ if (nl_flag == 0)
+ {
+ if (mode_local & TP_LEAD)
+ {
+ newline_add_before(pc);
+ }
+ else
+ {
+ newline_add_after(pc);
+ }
+ continue;
+ }
+
+ // If there were both newlines, we need to remove one
+ if (nl_flag == 3)
+ {
+ if (mode_local & TP_LEAD)
+ {
+ remove_next_newlines(pc);
+ }
+ else
+ {
+ remove_next_newlines(pc->GetPrevNcNnlNi()); // Issue #2279
+ }
+ continue;
+ }
+
+ // we need to move the newline
+ if (mode_local & TP_LEAD)
+ {
+ Chunk *next2 = next->GetNext();
+
+ if ( chunk_is_token(next2, CT_PREPROC)
+ || ( chunk_type == CT_ASSIGN
+ && chunk_is_token(next2, CT_BRACE_OPEN)))
+ {
+ continue;
+ }
+
+ if (next->nl_count == 1)
+ {
+ if ( prev != nullptr
+ && !prev->flags.test(PCF_IN_PREPROC))
+ {
+ // move the CT_BOOL to after the newline
+ chunk_move_after(pc, next);
+ }
+ }
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): prev->orig_line is %zu, orig_col is %zu, Text() is '%s', nl_count is %zu\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text(), prev->nl_count);
+
+ if (prev->nl_count == 1)
+ {
+ // Back up to the next non-comment item
+ prev = prev->GetPrevNc();
+ LOG_FMT(LNEWLINE, "%s(%d): prev->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text());
+
+ if ( prev->IsNotNullChunk()
+ && !chunk_is_newline(prev)
+ && !prev->flags.test(PCF_IN_PREPROC)
+ && !prev->flags.test(PCF_IN_OC_MSG))
+ {
+ chunk_move_after(pc, prev);
+ }
+ }
+ }
+ }
+ }
+} // newlines_chunk_pos
+
+
+void newlines_class_colon_pos(E_Token tok)
+{
+ LOG_FUNC_ENTRY();
+
+ token_pos_e tpc;
+ token_pos_e pcc;
+ iarf_e anc;
+ iarf_e ncia;
+
+ if (tok == CT_CLASS_COLON)
+ {
+ tpc = options::pos_class_colon();
+ log_rule_B("pos_class_colon");
+ anc = options::nl_class_colon();
+ log_rule_B("nl_class_colon");
+ ncia = options::nl_class_init_args();
+ log_rule_B("nl_class_init_args");
+ pcc = options::pos_class_comma();
+ log_rule_B("pos_class_comma");
+ }
+ else // tok == CT_CONSTR_COLON
+ {
+ tpc = options::pos_constr_colon();
+ log_rule_B("pos_constr_colon");
+ anc = options::nl_constr_colon();
+ log_rule_B("nl_constr_colon");
+ ncia = options::nl_constr_init_args();
+ log_rule_B("nl_constr_init_args");
+ pcc = options::pos_constr_comma();
+ log_rule_B("pos_constr_comma");
+ }
+ Chunk *ccolon = nullptr;
+ size_t acv_span = options::align_constr_value_span();
+
+ log_rule_B("align_constr_value_span");
+ bool with_acv = (acv_span > 0) && language_is_set(LANG_CPP);
+ AlignStack constructorValue; // ABC_Member(abc_value)
+
+ if (with_acv)
+ {
+ int acv_thresh = options::align_constr_value_thresh();
+ log_rule_B("align_constr_value_thresh");
+ size_t acv_gap = options::align_constr_value_gap();
+ log_rule_B("align_constr_value_gap");
+ constructorValue.Start(acv_span, acv_thresh);
+ constructorValue.m_gap = acv_gap;
+ constructorValue.m_right_align = !options::align_on_tabstop();
+ log_rule_B("align_on_tabstop");
+ }
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( ccolon == nullptr
+ && chunk_is_not_token(pc, tok))
+ {
+ continue;
+ }
+ Chunk *prev;
+ Chunk *next;
+
+ if (chunk_is_token(pc, tok))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ ccolon = pc;
+ prev = pc->GetPrevNc();
+ next = pc->GetNextNc();
+
+ if (chunk_is_token(pc, CT_CONSTR_COLON))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): pc->orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ Chunk *paren_vor_value = pc->GetNextType(CT_FPAREN_OPEN, pc->level);
+
+ if ( with_acv
+ && paren_vor_value->IsNotNullChunk())
+ {
+ LOG_FMT(LBLANKD, "%s(%d): paren_vor_value->orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, paren_vor_value->orig_line, paren_vor_value->orig_col,
+ paren_vor_value->Text(), get_token_name(paren_vor_value->type));
+ constructorValue.NewLines(paren_vor_value->nl_count);
+ constructorValue.Add(paren_vor_value);
+ }
+ }
+
+ if ( !chunk_is_newline(prev)
+ && !chunk_is_newline(next)
+ && (anc & IARF_ADD)) // nl_class_colon, nl_constr_colon: 1
+
+ {
+ newline_add_after(pc);
+ prev = pc->GetPrevNc();
+ next = pc->GetNextNc();
+ }
+
+ if (anc == IARF_REMOVE) // nl_class_colon, nl_constr_colon: 2
+ {
+ if ( chunk_is_newline(prev)
+ && chunk_safe_to_del_nl(prev))
+ {
+ chunk_del(prev);
+ MARK_CHANGE();
+ prev = pc->GetPrevNc();
+ }
+
+ if ( chunk_is_newline(next)
+ && chunk_safe_to_del_nl(next))
+ {
+ chunk_del(next);
+ MARK_CHANGE();
+ next = pc->GetNextNc();
+ }
+ }
+
+ if (tpc & TP_TRAIL) // pos_class_colon, pos_constr_colon: 4
+ {
+ if ( chunk_is_newline(prev)
+ && prev->nl_count == 1
+ && chunk_safe_to_del_nl(prev))
+ {
+ chunk_swap(pc, prev);
+ }
+ }
+ else if (tpc & TP_LEAD) // pos_class_colon, pos_constr_colon: 3
+ {
+ if ( chunk_is_newline(next)
+ && next->nl_count == 1
+ && chunk_safe_to_del_nl(next))
+ {
+ chunk_swap(pc, next);
+ }
+ }
+ }
+ else
+ {
+ // (pc->type != tok)
+ if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_SEMICOLON))
+ {
+ ccolon = nullptr;
+
+ if (with_acv)
+ {
+ constructorValue.End();
+ }
+ continue;
+ }
+
+ if ( chunk_is_token(pc, CT_COMMA)
+ && pc->level == ccolon->level)
+ {
+ LOG_FMT(LBLANKD, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ Chunk *paren_vor_value = pc->GetNextType(CT_FPAREN_OPEN, pc->level);
+
+ if ( with_acv
+ && paren_vor_value->IsNotNullChunk())
+ {
+ LOG_FMT(LBLANKD, "%s(%d): paren_vor_value->orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, paren_vor_value->orig_line, paren_vor_value->orig_col,
+ paren_vor_value->Text(), get_token_name(paren_vor_value->type));
+ constructorValue.NewLines(paren_vor_value->nl_count);
+ constructorValue.Add(paren_vor_value);
+ }
+
+ if (ncia & IARF_ADD) // nl_class_init_args, nl_constr_init_args:
+ {
+ if (pcc & TP_TRAIL) // pos_class_comma, pos_constr_comma
+ {
+ if (ncia == IARF_FORCE) // nl_class_init_args, nl_constr_init_args: 5
+ {
+ Chunk *after = pc->GetNext(); // Issue #2759
+
+ if (chunk_is_not_token(after, CT_COMMENT_CPP))
+ {
+ newline_force_after(pc);
+ }
+ }
+ else
+ {
+ // (ncia == IARF_ADD) // nl_class_init_args, nl_constr_init_args: 8
+ newline_add_after(pc);
+ }
+ prev = pc->GetPrevNc();
+
+ if ( chunk_is_newline(prev)
+ && chunk_safe_to_del_nl(prev))
+ {
+ chunk_del(prev);
+ MARK_CHANGE();
+ }
+ }
+ else if (pcc & TP_LEAD) // pos_class_comma, pos_constr_comma
+ {
+ if (ncia == IARF_FORCE) // nl_class_init_args, nl_constr_init_args: 7
+ {
+ newline_force_before(pc);
+ }
+ else
+ {
+ // (ncia == IARF_ADD) // nl_class_init_args, nl_constr_init_args: 9
+ newline_add_before(pc);
+ }
+ next = pc->GetNextNc();
+
+ if ( chunk_is_newline(next)
+ && chunk_safe_to_del_nl(next))
+ {
+ chunk_del(next);
+ MARK_CHANGE();
+ }
+ }
+ }
+ else if (ncia == IARF_REMOVE) // nl_class_init_args, nl_constr_init_args: 6
+ {
+ next = pc->GetNext();
+
+ if ( chunk_is_newline(next)
+ && chunk_safe_to_del_nl(next))
+ {
+ // comma is after
+ chunk_del(next);
+ MARK_CHANGE();
+ }
+ else
+ {
+ prev = pc->GetPrev();
+
+ if ( chunk_is_newline(prev)
+ && chunk_safe_to_del_nl(prev))
+ {
+ // comma is before
+ chunk_del(prev);
+ MARK_CHANGE();
+ }
+ }
+ }
+ }
+ }
+ }
+} // newlines_class_colon_pos
+
+
+static void blank_line_max(Chunk *pc, Option<unsigned> &opt)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return;
+ }
+ const auto optval = opt();
+
+ if ( (optval > 0)
+ && (pc->nl_count > optval))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): do_blank_lines: %s max line %zu\n",
+ __func__, __LINE__, opt.name(), pc->orig_line);
+ pc->nl_count = optval;
+ MARK_CHANGE();
+ }
+} // blank_line_max
+
+
+iarf_e newline_template_option(Chunk *pc, iarf_e special, iarf_e base, iarf_e fallback)
+{
+ Chunk *const prev = pc->GetPrevNcNnl();
+
+ if ( chunk_is_token(prev, CT_ANGLE_OPEN)
+ && special != IARF_IGNORE)
+ {
+ return(special);
+ }
+ else if (base != IARF_IGNORE)
+ {
+ return(base);
+ }
+ else
+ {
+ return(fallback);
+ }
+} // newline_template_option
+
+
+bool is_func_proto_group(Chunk *pc, E_Token one_liner_type)
+{
+ if ( pc != nullptr
+ && options::nl_class_leave_one_liner_groups()
+ && ( chunk_is_token(pc, one_liner_type)
+ || get_chunk_parent_type(pc) == one_liner_type)
+ && pc->flags.test(PCF_IN_CLASS))
+ {
+ log_rule_B("nl_class_leave_one_liner_groups");
+
+ if (chunk_is_token(pc, CT_BRACE_CLOSE))
+ {
+ return(pc->flags.test(PCF_ONE_LINER));
+ }
+ else
+ {
+ // Find opening brace
+ pc = pc->GetNextType(CT_BRACE_OPEN, pc->level);
+ return( pc->IsNotNullChunk()
+ && pc->flags.test(PCF_ONE_LINER));
+ }
+ }
+ return(false);
+} // is_func_proto_group
+
+
+void do_blank_lines(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc != nullptr && pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->nl_count);
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LBLANKD, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy), get_token_name(pc->type));
+ }
+ LOG_FMT(LBLANK, "%s(%d): nl_count is %zu\n",
+ __func__, __LINE__, pc->nl_count);
+
+ //if (pc->type != CT_NEWLINE)
+ if (chunk_is_not_token(pc, CT_NEWLINE))
+ {
+ continue;
+ }
+ Chunk *prev = pc->GetPrevNc();
+
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LBLANK, "%s(%d): prev->orig_line is %zu, prev->Text() '%s', prev->type is %s\n",
+ __func__, __LINE__, pc->orig_line,
+ prev->Text(), get_token_name(prev->type));
+
+ if (chunk_is_token(prev, CT_IGNORED))
+ {
+ continue;
+ }
+ }
+ Chunk *next = pc->GetNext();
+ Chunk *pcmt = pc->GetPrev();
+
+ bool line_added = false;
+
+ /*
+ * If this is the first or the last token, pretend that there is an extra
+ * line. It will be removed at the end.
+ */
+ if ( pc == Chunk::GetHead()
+ || next->IsNullChunk())
+ {
+ line_added = true;
+ ++pc->nl_count;
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, text is '%s', ++ nl_count is now %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), pc->nl_count);
+ }
+
+ // Limit consecutive newlines
+ if ( (options::nl_max() > 0)
+ && (pc->nl_count > options::nl_max()))
+ {
+ log_rule_B("nl_max");
+ blank_line_max(pc, options::nl_max);
+ }
+
+ if (!can_increase_nl(pc))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): force to 1 orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+
+ if (pc->nl_count != 1)
+ {
+ pc->nl_count = 1;
+ MARK_CHANGE();
+ }
+ continue;
+ }
+
+ // Control blanks before multi-line comments
+ if ( (options::nl_before_block_comment() > pc->nl_count)
+ && chunk_is_token(next, CT_COMMENT_MULTI))
+ {
+ log_rule_B("nl_before_block_comment");
+
+ // Don't add blanks after an open brace or a case statement
+ if ( ( prev == nullptr
+ || ( chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && chunk_is_not_token(prev, CT_VBRACE_OPEN)
+ && chunk_is_not_token(prev, CT_CASE_COLON)))
+ && chunk_is_not_token(pcmt, CT_COMMENT_MULTI)) // Issue #2383
+ {
+ blank_line_set(pc, options::nl_before_block_comment);
+ log_rule_B("nl_before_block_comment");
+ }
+ }
+
+ // Control blanks before single line C comments
+ if ( (options::nl_before_c_comment() > pc->nl_count)
+ && chunk_is_token(next, CT_COMMENT))
+ {
+ log_rule_B("nl_before_c_comment");
+
+ // Don't add blanks after an open brace, a case stamement, or a comment
+ if ( ( prev == nullptr
+ || ( chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && chunk_is_not_token(prev, CT_VBRACE_OPEN)
+ && chunk_is_not_token(prev, CT_CASE_COLON)))
+ && chunk_is_not_token(pcmt, CT_COMMENT)) // Issue #2383
+ {
+ blank_line_set(pc, options::nl_before_c_comment);
+ log_rule_B("nl_before_c_comment");
+ }
+ }
+
+ // Control blanks before CPP comments
+ if ( (options::nl_before_cpp_comment() > pc->nl_count)
+ && chunk_is_token(next, CT_COMMENT_CPP))
+ {
+ log_rule_B("nl_before_cpp_comment");
+
+ // Don't add blanks after an open brace or a case statement
+ if ( ( prev == nullptr
+ || ( chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && chunk_is_not_token(prev, CT_VBRACE_OPEN)
+ && chunk_is_not_token(prev, CT_CASE_COLON)))
+ && chunk_is_not_token(pcmt, CT_COMMENT_CPP)) // Issue #2383
+ {
+ blank_line_set(pc, options::nl_before_cpp_comment);
+ log_rule_B("nl_before_cpp_comment");
+ }
+ }
+
+ // Control blanks before a class/struct
+ if ( ( chunk_is_token(prev, CT_SEMICOLON)
+ || chunk_is_token(prev, CT_BRACE_CLOSE))
+ && ( get_chunk_parent_type(prev) == CT_CLASS
+ || get_chunk_parent_type(prev) == CT_STRUCT))
+ {
+ E_Token parent_type = get_chunk_parent_type(prev);
+ Chunk *start = prev->GetPrevType(parent_type, prev->level);
+ Chunk *tmp = start;
+
+ // Is this a class/struct template?
+ if (get_chunk_parent_type(tmp) == CT_TEMPLATE)
+ {
+ tmp = tmp->GetPrevType(CT_TEMPLATE, prev->level);
+ tmp = tmp->GetPrevNc();
+ }
+ else
+ {
+ tmp = tmp->GetPrevNc();
+
+ while ( chunk_is_token(tmp, CT_NEWLINE)
+ && tmp->GetPrev()->IsComment())
+ {
+ tmp = tmp->GetPrev()->GetPrevNc();
+ }
+
+ if (chunk_is_token(tmp, CT_FRIEND))
+ {
+ // Account for a friend declaration
+ tmp = tmp->GetPrevNc();
+ }
+ }
+
+ while ( chunk_is_token(tmp, CT_NEWLINE)
+ && tmp->GetPrev()->IsComment())
+ {
+ tmp = tmp->GetPrev()->GetPrevNc();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && !start->flags.test(PCF_INCOMPLETE))
+ {
+ if (parent_type == CT_CLASS && options::nl_before_class() > tmp->nl_count)
+ {
+ log_rule_B("nl_before_class");
+ blank_line_set(tmp, options::nl_before_class);
+ }
+ else if (parent_type == CT_STRUCT && options::nl_before_struct() > tmp->nl_count)
+ {
+ log_rule_B("nl_before_struct");
+ blank_line_set(tmp, options::nl_before_struct);
+ }
+ }
+ }
+
+ if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_NAMESPACE)
+ {
+ // Control blanks before a namespace
+ Chunk *tmp = prev->GetPrevType(CT_NAMESPACE, prev->level);
+ tmp = tmp->GetPrevNc();
+
+ while ( chunk_is_token(tmp, CT_NEWLINE)
+ && tmp->GetPrev()->IsComment())
+ {
+ tmp = tmp->GetPrev()->GetPrevNc();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && options::nl_before_namespace() > tmp->nl_count)
+ {
+ log_rule_B("nl_before_namespace");
+ blank_line_set(tmp, options::nl_before_namespace);
+ }
+
+ // Add blanks after namespace
+ if (options::nl_after_namespace() > pc->nl_count)
+ {
+ log_rule_B("nl_after_namespace");
+ blank_line_set(pc, options::nl_after_namespace);
+ }
+ }
+
+ // Control blanks inside empty function body
+ if ( chunk_is_token(prev, CT_BRACE_OPEN)
+ && chunk_is_token(next, CT_BRACE_CLOSE)
+ && ( get_chunk_parent_type(prev) == CT_FUNC_DEF
+ || get_chunk_parent_type(prev) == CT_FUNC_CLASS_DEF)
+ && options::nl_inside_empty_func() > pc->nl_count
+ && prev->flags.test(PCF_EMPTY_BODY))
+ {
+ blank_line_set(pc, options::nl_inside_empty_func);
+ log_rule_B("nl_inside_empty_func");
+ }
+
+ // Control blanks after an access spec
+ if ( (options::nl_after_access_spec() > 0)
+ && (options::nl_after_access_spec() != pc->nl_count)
+ && chunk_is_token(prev, CT_ACCESS_COLON))
+ {
+ log_rule_B("nl_after_access_spec");
+
+ // Don't add blanks before a closing brace
+ if ( next->IsNullChunk()
+ || ( chunk_is_not_token(next, CT_BRACE_CLOSE)
+ && chunk_is_not_token(next, CT_VBRACE_CLOSE)))
+ {
+ log_rule_B("nl_after_access_spec");
+ blank_line_set(pc, options::nl_after_access_spec);
+ }
+ }
+
+ // Add blanks after function bodies
+ if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && ( get_chunk_parent_type(prev) == CT_FUNC_DEF
+ || get_chunk_parent_type(prev) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(prev) == CT_OC_MSG_DECL
+ || get_chunk_parent_type(prev) == CT_ASSIGN))
+ {
+ if (prev->flags.test(PCF_ONE_LINER))
+ {
+ if (options::nl_after_func_body_one_liner() > pc->nl_count)
+ {
+ log_rule_B("nl_after_func_body_one_liner");
+ blank_line_set(pc, options::nl_after_func_body_one_liner);
+ }
+ }
+ else
+ {
+ if ( prev->flags.test(PCF_IN_CLASS)
+ && (options::nl_after_func_body_class() > 0))
+ {
+ log_rule_B("nl_after_func_body_class");
+
+ if (options::nl_after_func_body_class() != pc->nl_count)
+ {
+ log_rule_B("nl_after_func_body_class");
+ blank_line_set(pc, options::nl_after_func_body_class);
+ }
+ }
+ else if (options::nl_after_func_body() > 0)
+ {
+ log_rule_B("nl_after_func_body");
+
+ // Issue #1734
+ if (!(pc->prev->flags.test(PCF_IN_TRY_BLOCK)))
+ {
+ if (options::nl_after_func_body() != pc->nl_count)
+ {
+ log_rule_B("nl_after_func_body");
+ blank_line_set(pc, options::nl_after_func_body);
+ }
+ }
+ }
+ }
+ }
+
+ // Add blanks after function prototypes
+ if ( ( chunk_is_token(prev, CT_SEMICOLON)
+ && get_chunk_parent_type(prev) == CT_FUNC_PROTO)
+ || is_func_proto_group(prev, CT_FUNC_DEF))
+ {
+ if (options::nl_after_func_proto() > pc->nl_count)
+ {
+ log_rule_B("nl_after_func_proto");
+ pc->nl_count = options::nl_after_func_proto();
+ MARK_CHANGE();
+ }
+
+ if ( (options::nl_after_func_proto_group() > pc->nl_count)
+ && next->IsNotNullChunk()
+ && get_chunk_parent_type(next) != CT_FUNC_PROTO
+ && !is_func_proto_group(next, CT_FUNC_DEF))
+ {
+ log_rule_B("nl_after_func_proto_group");
+ blank_line_set(pc, options::nl_after_func_proto_group);
+ }
+ }
+
+ // Issue #411: Add blanks after function class prototypes
+ if ( ( chunk_is_token(prev, CT_SEMICOLON)
+ && get_chunk_parent_type(prev) == CT_FUNC_CLASS_PROTO)
+ || is_func_proto_group(prev, CT_FUNC_CLASS_DEF))
+ {
+ if (options::nl_after_func_class_proto() > pc->nl_count)
+ {
+ log_rule_B("nl_after_func_class_proto");
+ pc->nl_count = options::nl_after_func_class_proto();
+ MARK_CHANGE();
+ }
+
+ if ( (options::nl_after_func_class_proto_group() > pc->nl_count)
+ && chunk_is_not_token(next, CT_FUNC_CLASS_PROTO)
+ && get_chunk_parent_type(next) != CT_FUNC_CLASS_PROTO
+ && !is_func_proto_group(next, CT_FUNC_CLASS_DEF))
+ {
+ log_rule_B("nl_after_func_class_proto_group");
+ blank_line_set(pc, options::nl_after_func_class_proto_group);
+ }
+ }
+
+ // Add blanks after struct/enum/union/class
+ if ( ( chunk_is_token(prev, CT_SEMICOLON)
+ || chunk_is_token(prev, CT_BRACE_CLOSE))
+ && ( get_chunk_parent_type(prev) == CT_STRUCT
+ || get_chunk_parent_type(prev) == CT_ENUM
+ || get_chunk_parent_type(prev) == CT_UNION
+ || get_chunk_parent_type(prev) == CT_CLASS))
+ {
+ auto &opt = (get_chunk_parent_type(prev) == CT_CLASS
+ ? options::nl_after_class
+ : options::nl_after_struct);
+ log_rule_B("nl_after_class");
+ log_rule_B("nl_after_struct");
+
+ if (opt() > pc->nl_count)
+ {
+ // Issue #1702
+ // look back if we have a variable
+ Chunk *tmp = pc;
+ bool is_var_def = false;
+ bool is_fwd_decl = false;
+
+ while ((tmp = tmp->GetPrev())->IsNotNullChunk())
+ {
+ if (tmp->level > pc->level)
+ {
+ continue;
+ }
+ LOG_FMT(LBLANK, "%s(%d): %zu:%zu token is '%s'\n",
+ __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->Text());
+
+ if (tmp->flags.test(PCF_VAR_DEF))
+ {
+ is_var_def = true;
+ break;
+ }
+
+ if (chunk_is_token(tmp, get_chunk_parent_type(prev)))
+ {
+ is_fwd_decl = tmp->flags.test(PCF_INCOMPLETE);
+ break;
+ }
+ }
+ LOG_FMT(LBLANK, "%s(%d): var_def = %s, fwd_decl = %s\n",
+ __func__, __LINE__,
+ is_var_def ? "yes" : "no",
+ is_fwd_decl ? "yes" : "no");
+
+ if ( !is_var_def
+ && !is_fwd_decl)
+ {
+ blank_line_set(pc, opt);
+ }
+ }
+ }
+
+ // Change blanks between a function comment and body
+ if ( (options::nl_comment_func_def() != 0)
+ && chunk_is_token(pcmt, CT_COMMENT_MULTI)
+ && get_chunk_parent_type(pcmt) == CT_COMMENT_WHOLE
+ && next->IsNotNullChunk()
+ && ( get_chunk_parent_type(next) == CT_FUNC_DEF
+ || get_chunk_parent_type(next) == CT_FUNC_CLASS_DEF))
+ {
+ log_rule_B("nl_comment_func_def");
+
+ if (options::nl_comment_func_def() != pc->nl_count)
+ {
+ log_rule_B("nl_comment_func_def");
+ blank_line_set(pc, options::nl_comment_func_def);
+ }
+ }
+
+ // Change blanks after a try-catch-finally block
+ if ( (options::nl_after_try_catch_finally() != 0)
+ && (options::nl_after_try_catch_finally() != pc->nl_count)
+ && prev != nullptr
+ && next->IsNotNullChunk())
+ {
+ log_rule_B("nl_after_try_catch_finally");
+
+ if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && ( get_chunk_parent_type(prev) == CT_CATCH
+ || get_chunk_parent_type(prev) == CT_FINALLY))
+ {
+ if ( chunk_is_not_token(next, CT_BRACE_CLOSE)
+ && chunk_is_not_token(next, CT_CATCH)
+ && chunk_is_not_token(next, CT_FINALLY))
+ {
+ blank_line_set(pc, options::nl_after_try_catch_finally);
+ log_rule_B("nl_after_try_catch_finally");
+ }
+ }
+ }
+
+ // Change blanks after a try-catch-finally block
+ if ( (options::nl_between_get_set() != 0)
+ && (options::nl_between_get_set() != pc->nl_count)
+ && prev != nullptr
+ && next->IsNotNullChunk())
+ {
+ log_rule_B("nl_between_get_set");
+
+ if ( get_chunk_parent_type(prev) == CT_GETSET
+ && chunk_is_not_token(next, CT_BRACE_CLOSE)
+ && ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ || chunk_is_token(prev, CT_SEMICOLON)))
+ {
+ blank_line_set(pc, options::nl_between_get_set);
+ log_rule_B("nl_between_get_set");
+ }
+ }
+
+ // Change blanks after a try-catch-finally block
+ if ( (options::nl_around_cs_property() != 0)
+ && (options::nl_around_cs_property() != pc->nl_count)
+ && prev != nullptr
+ && next->IsNotNullChunk())
+ {
+ log_rule_B("nl_around_cs_property");
+
+ if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_CS_PROPERTY
+ && chunk_is_not_token(next, CT_BRACE_CLOSE))
+ {
+ blank_line_set(pc, options::nl_around_cs_property);
+ log_rule_B("nl_around_cs_property");
+ }
+ else if ( get_chunk_parent_type(next) == CT_CS_PROPERTY
+ && next->flags.test(PCF_STMT_START))
+ {
+ blank_line_set(pc, options::nl_around_cs_property);
+ log_rule_B("nl_around_cs_property");
+ }
+ }
+
+ // Control blanks before an access spec
+ if ( (options::nl_before_access_spec() > 0)
+ && (options::nl_before_access_spec() != pc->nl_count)
+ && chunk_is_token(next, CT_ACCESS))
+ {
+ log_rule_B("nl_before_access_spec");
+
+ // Don't add blanks after an open brace
+ if ( prev == nullptr
+ || ( chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && chunk_is_not_token(prev, CT_VBRACE_OPEN)))
+ {
+ log_rule_B("nl_before_access_spec");
+ blank_line_set(pc, options::nl_before_access_spec);
+ }
+ }
+
+ // Change blanks inside namespace braces
+ if ( (options::nl_inside_namespace() != 0)
+ && (options::nl_inside_namespace() != pc->nl_count)
+ && ( ( chunk_is_token(prev, CT_BRACE_OPEN)
+ && get_chunk_parent_type(prev) == CT_NAMESPACE)
+ || ( chunk_is_token(next, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(next) == CT_NAMESPACE)))
+ {
+ log_rule_B("nl_inside_namespace");
+ blank_line_set(pc, options::nl_inside_namespace);
+ }
+
+ // Control blanks before a whole-file #ifdef
+ if ( options::nl_before_whole_file_ifdef() != 0
+ && options::nl_before_whole_file_ifdef() != pc->nl_count
+ && chunk_is_token(next, CT_PREPROC)
+ && get_chunk_parent_type(next) == CT_PP_IF
+ && ifdef_over_whole_file()
+ && next->flags.test(PCF_WF_IF))
+ {
+ log_rule_B("nl_before_whole_file_ifdef");
+ blank_line_set(pc, options::nl_before_whole_file_ifdef);
+ }
+
+ // Control blanks after a whole-file #ifdef
+ if ( options::nl_after_whole_file_ifdef() != 0
+ && options::nl_after_whole_file_ifdef() != pc->nl_count)
+ {
+ Chunk *pp_start = chunk_get_pp_start(prev);
+
+ if ( pp_start != nullptr
+ && get_chunk_parent_type(pp_start) == CT_PP_IF
+ && ifdef_over_whole_file()
+ && pp_start->flags.test(PCF_WF_IF))
+ {
+ log_rule_B("nl_after_whole_file_ifdef");
+ blank_line_set(pc, options::nl_after_whole_file_ifdef);
+ }
+ }
+
+ // Control blanks before a whole-file #endif
+ if ( options::nl_before_whole_file_endif() != 0
+ && options::nl_before_whole_file_endif() != pc->nl_count
+ && chunk_is_token(next, CT_PREPROC)
+ && get_chunk_parent_type(next) == CT_PP_ENDIF
+ && ifdef_over_whole_file()
+ && next->flags.test(PCF_WF_ENDIF))
+ {
+ log_rule_B("nl_before_whole_file_endif");
+ blank_line_set(pc, options::nl_before_whole_file_endif);
+ }
+
+ // Control blanks after a whole-file #endif
+ if ( options::nl_after_whole_file_endif() != 0
+ && options::nl_after_whole_file_endif() != pc->nl_count)
+ {
+ Chunk *pp_start = chunk_get_pp_start(prev);
+
+ if ( pp_start != nullptr
+ && get_chunk_parent_type(pp_start) == CT_PP_ENDIF
+ && ifdef_over_whole_file()
+ && pp_start->flags.test(PCF_WF_ENDIF))
+ {
+ log_rule_B("nl_after_whole_file_endif");
+ blank_line_set(pc, options::nl_after_whole_file_endif);
+ }
+ }
+
+ if ( line_added
+ && pc->nl_count > 1)
+ {
+ --pc->nl_count;
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, text is '%s', -- nl_count is now %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), pc->nl_count);
+ }
+ LOG_FMT(LBLANK, "%s(%d): orig_line is %zu, orig_col is %zu, text is '%s', end nl_count is now %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), pc->nl_count);
+ }
+} // do_blank_lines
+
+
+void newlines_cleanup_dup(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+ Chunk *next = pc;
+
+ while (pc->IsNotNullChunk())
+ {
+ next = next->GetNext();
+
+ if ( chunk_is_token(pc, CT_NEWLINE)
+ && chunk_is_token(next, CT_NEWLINE))
+ {
+ next->nl_count = max(pc->nl_count, next->nl_count);
+ chunk_del(pc);
+ MARK_CHANGE();
+ }
+ pc = next;
+ }
+} // newlines_cleanup_dup
+
+
+static void newlines_enum_entries(Chunk *open_brace, iarf_e av)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ if (open_brace != nullptr)
+ {
+ pc = open_brace;
+ }
+
+ while ( (pc = pc->GetNextNc())->IsNotNullChunk()
+ && pc->level > open_brace->level)
+ {
+ if ( (pc->level != (open_brace->level + 1))
+ || chunk_is_not_token(pc, CT_COMMA)
+ || ( chunk_is_token(pc, CT_COMMA)
+ && pc->GetNext()->IsNotNullChunk()
+ && ( pc->GetNext()->type == CT_COMMENT_CPP
+ || pc->GetNext()->type == CT_COMMENT)))
+ {
+ continue;
+ }
+ newline_iarf(pc, av);
+ }
+ newline_iarf(open_brace, av);
+} // newlines_enum_entries
+
+
+static void newlines_double_space_struct_enum_union(Chunk *open_brace)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ if (open_brace != nullptr)
+ {
+ pc = open_brace;
+ }
+
+ while ( (pc = pc->GetNextNc())->IsNotNullChunk()
+ && pc->level > open_brace->level)
+ {
+ if ( pc->level != (open_brace->level + 1)
+ || chunk_is_not_token(pc, CT_NEWLINE))
+ {
+ continue;
+ }
+ /*
+ * If the newline is NOT after a comment or a brace open and
+ * it is before a comment, then make sure that the newline is
+ * at least doubled
+ */
+ Chunk *prev = pc->GetPrev();
+
+ if ( !prev->IsComment()
+ && chunk_is_not_token(prev, CT_BRACE_OPEN)
+ && pc->GetNext()->IsComment())
+ {
+ if (pc->nl_count < 2)
+ {
+ double_newline(pc);
+ }
+ }
+ }
+} // newlines_double_space_struct_enum_union
+
+
+void annotations_newlines(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *next;
+ Chunk *prev;
+ Chunk *ae; // last token of the annotation
+ Chunk *pc = Chunk::GetHead();
+
+ while ( (pc = pc->GetNextType(CT_ANNOTATION, -1))->IsNotNullChunk()
+ && (next = pc->GetNextNnl())->IsNotNullChunk())
+ {
+ // find the end of this annotation
+ if (chunk_is_paren_open(next))
+ {
+ // TODO: control newline between annotation and '(' ?
+ ae = chunk_skip_to_match(next);
+ }
+ else
+ {
+ ae = pc;
+ }
+
+ if (ae->IsNullChunk())
+ {
+ break;
+ }
+ LOG_FMT(LANNOT, "%s(%d): orig_line is %zu, orig_col is %zu, annotation is '%s', end @ orig_line %zu, orig_col %zu, is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ ae->orig_line, ae->orig_col, ae->Text());
+
+ prev = ae->GetPrev(); // Issue #1845
+ LOG_FMT(LANNOT, "%s(%d): prev->orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, prev->orig_line, prev->orig_col, prev->Text());
+ next = ae->GetNextNnl();
+
+ if (chunk_is_token(next, CT_ANNOTATION))
+ {
+ LOG_FMT(LANNOT, "%s(%d): -- nl_between_annotation\n",
+ __func__, __LINE__);
+ newline_iarf(ae, options::nl_between_annotation());
+ log_rule_B("nl_between_annotation");
+ }
+
+ if (chunk_is_token(next, CT_NEWLINE))
+ {
+ if (chunk_is_token(next, CT_ANNOTATION))
+ {
+ LOG_FMT(LANNOT, "%s(%d): -- nl_after_annotation\n",
+ __func__, __LINE__);
+ newline_iarf(ae, options::nl_after_annotation());
+ log_rule_B("nl_after_annotation");
+ }
+ }
+ }
+} // annotations_newlines
+
+
+bool newlines_between(Chunk *pc_start, Chunk *pc_end, size_t &newlines, E_Scope scope)
+{
+ if ( pc_start == nullptr
+ || pc_end == nullptr)
+ {
+ return(false);
+ }
+ newlines = 0;
+
+ Chunk *it = pc_start;
+
+ for ( ; it->IsNotNullChunk() && it != pc_end; it = it->GetNext(scope))
+ {
+ newlines += it->nl_count;
+ }
+
+ // newline count is valid if search stopped on expected chunk
+ return(it == pc_end);
+} // newlines_between
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.h
new file mode 100644
index 00000000..b5c7db03
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/newlines.h
@@ -0,0 +1,206 @@
+/**
+ * @file newlines.h
+ * prototypes for newlines.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef NEWLINES_H_INCLUDED
+#define NEWLINES_H_INCLUDED
+
+#include "chunk.h"
+
+/**
+ * Double the newline, if allowed.
+ */
+void double_newline(Chunk *nl);
+
+/**
+ * Remove all extra newlines.
+ * Modify line breaks as needed.
+ */
+void newlines_remove_newlines(void);
+
+
+/**
+ * Remove all newlines that fail the checks performed by the can_increase_nl() function
+ */
+void newlines_remove_disallowed();
+
+
+/** Step through all chunks, altering newlines inside parens of if/for/while/do as needed.
+ * Handles the style options: nl_multi_line_sparen_open, nl_multi_line_sparen_close, nl_before_if_closing_paren
+ */
+void newlines_sparens();
+
+//! Step through all chunks.
+void newlines_cleanup_braces(bool first);
+
+
+void newlines_cleanup_angles();
+
+
+//! Handle insertion/removal of blank lines before if/for/while/do and functions
+void newlines_insert_blank_lines(void);
+
+
+/**
+ * Handle removal of extra blank lines in functions
+ * x <= 0: do nothing, x > 0: allow max x-1 blank lines
+ */
+void newlines_functions_remove_extra_blank_lines(void);
+
+
+void newlines_squeeze_ifdef(void);
+
+/**
+ * In case of consecutive closing parens, which follow a newline,
+ * the closing paren are altered to different lines, as per the respective opening parens.
+ * In the given example, first 2 opening paren are in same line, hence the respective closing paren are put in the same line.
+ * input:
+ * func1(func2(
+ * func3(
+ * func4(
+ * )
+ * )
+ * )
+ * );
+ * output:
+ * func1(func2(
+ * func3(
+ * func4(
+ * )
+ * )
+ * ));
+ */
+void newlines_squeeze_paren_close(void);
+
+
+//! removes unnecessary newlines at start and end of a file
+void newlines_eat_start_end(void);
+
+
+/**
+ * Searches for a chunk of type chunk_type and moves them, if needed.
+ * Will not move tokens that are on their own line or have other than
+ * exactly 1 newline before (UO_pos_comma == TRAIL) or after (UO_pos_comma == LEAD).
+ * We can't remove a newline if it is right before a preprocessor.
+ */
+void newlines_chunk_pos(E_Token chunk_type, uncrustify::token_pos_e mode);
+
+
+/**
+ * Searches for CT_CLASS_COLON and moves them, if needed.
+ * Also breaks up the args
+ */
+void newlines_class_colon_pos(E_Token tok);
+
+
+void newlines_cleanup_dup(void);
+
+
+void annotations_newlines(void);
+
+
+void newline_after_multiline_comment(void);
+
+
+//! Handle insertion of blank lines after label colons
+void newline_after_label_colon(void);
+
+
+/**
+ * Scans for newline tokens and changes the nl_count.
+ * A newline token has a minimum nl_count of 1.
+ * Note that a blank line is actually 2 newlines, unless the newline is the
+ * first chunk.
+ * So, most comparisons have +1 below.
+ */
+void do_blank_lines(void);
+
+
+/**
+ * Clears the PCF_ONE_LINER flag on the current line.
+ * Done right before inserting a newline.
+ */
+void undo_one_liner(Chunk *pc);
+
+
+/**
+ * Does a simple Ignore, Add, Remove, or Force after the given chunk
+ *
+ * @param pc The chunk
+ * @param av The IARF value
+ */
+void newline_iarf(Chunk *pc, uncrustify::iarf_e av);
+
+
+/**
+ * Add a newline before the chunk if there isn't already a newline present.
+ * Virtual braces are skipped, as they do not contribute to the output.
+ */
+Chunk *newline_add_before(Chunk *pc);
+
+
+/**
+ * Add a newline after the chunk if there isn't already a newline present.
+ * Virtual braces are skipped, as they do not contribute to the output.
+ */
+Chunk *newline_force_before(Chunk *pc);
+
+
+Chunk *newline_add_after(Chunk *pc);
+
+
+Chunk *newline_force_after(Chunk *pc);
+
+
+/**
+ * Removes any CT_NEWLINE or CT_NL_CONT between start and end.
+ * Start must be before end on the chunk list.
+ * If the 'PCF_IN_PREPROC' status differs between two tags, we can't remove
+ * the newline.
+ *
+ * @param start The starting chunk (if it is a newline, it will be removed!)
+ * @param end The ending chunk (will not be removed, even if it is a newline)
+ *
+ * @return true/false - removed something
+ */
+void newline_del_between(Chunk *start, Chunk *end);
+
+
+/**
+ * Add a newline between two tokens.
+ * If there is already a newline between then, nothing is done.
+ * Otherwise a newline is inserted.
+ *
+ * If end is CT_BRACE_OPEN and a comment and newline follow, then
+ * the brace open is moved instead of inserting a newline.
+ *
+ * In this situation:
+ * if (...) { //comment
+ *
+ * you get:
+ * if (...) //comment
+ * {
+ */
+Chunk *newline_add_between(Chunk *start, Chunk *end);
+
+
+/**
+ * Counts newlines between two chunk elements
+ *
+ * @param pc_start chunk from which the counting of newlines will start
+ * @param pc_end chunk at which the counting of newlines will end
+ * @param newlines reference in which the amount of newlines will be written to
+ * (will be initialized with 0)
+ * @param scope specifies region chunks should/should not be considered.
+ *
+ * @return false if pc_start or pc_end are nullptr or if pc_end is not reached
+ * @return true if above cases are not met
+ */
+bool newlines_between(Chunk *pc_start, Chunk *pc_end, size_t &newlines, E_Scope scope = E_Scope::ALL);
+
+
+#endif /* NEWLINES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.cpp
new file mode 100644
index 00000000..8160c22b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.cpp
@@ -0,0 +1,1275 @@
+/**
+ * @file option.cpp
+ * Parses the options from the config file.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel October 2015, 2021
+ * @author Matthew Woehlke since version 0.67
+ * @license GPL v2+
+ */
+
+#include "option.h"
+
+#include "keywords.h"
+#include "uncrustify.h"
+#include "uncrustify_version.h"
+
+#include <fstream>
+#include <unordered_map>
+
+#include <cctype> // to get std::tolower
+#include <cstdarg> // to get va_start, va_end
+
+
+namespace uncrustify
+{
+
+namespace
+{
+
+static const char *DOC_TEXT_END = u8R"___(
+# Meaning of the settings:
+# Ignore - do not do any changes
+# Add - makes sure there is 1 or more space/brace/newline/etc
+# Force - makes sure there is exactly 1 space/brace/newline/etc,
+# behaves like Add in some contexts
+# Remove - removes space/brace/newline/etc
+#
+#
+# - Token(s) can be treated as specific type(s) with the 'set' option:
+# `set tokenType tokenString [tokenString...]`
+#
+# Example:
+# `set BOOL __AND__ __OR__`
+#
+# tokenTypes are defined in src/token_enum.h, use them without the
+# 'CT_' prefix: 'CT_BOOL' => 'BOOL'
+#
+#
+# - Token(s) can be treated as type(s) with the 'type' option.
+# `type tokenString [tokenString...]`
+#
+# Example:
+# `type int c_uint_8 Rectangle`
+#
+# This can also be achieved with `set TYPE int c_uint_8 Rectangle`
+#
+#
+# To embed whitespace in tokenStrings use the '\' escape character, or quote
+# the tokenStrings. These quotes are supported: "'`
+#
+#
+# - Support for the auto detection of languages through the file ending can be
+# added using the 'file_ext' command.
+# `file_ext langType langString [langString..]`
+#
+# Example:
+# `file_ext CPP .ch .cxx .cpp.in`
+#
+# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use
+# them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP'
+#
+#
+# - Custom macro-based indentation can be set up using 'macro-open',
+# 'macro-else' and 'macro-close'.
+# `(macro-open | macro-else | macro-close) tokenString`
+#
+# Example:
+# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP`
+# `macro-open BEGIN_MESSAGE_MAP`
+# `macro-close END_MESSAGE_MAP`
+#
+#
+)___";
+
+
+std::vector<OptionGroup> option_groups;
+std::unordered_map<std::string, GenericOption *> option_map;
+
+#define LOG_CONFIG(...) \
+ log_config(); LOG_FMT(LNOTE, __VA_ARGS__);
+
+
+//-----------------------------------------------------------------------------
+constexpr int option_level(int major, int minor, int patch = 0)
+{
+ return((major << 20) | (minor << 10) | (patch << 0));
+}
+
+
+//-----------------------------------------------------------------------------
+void log_config()
+{
+ // Print the name of the configuration file only once
+ static bool config_name_logged = false;
+
+ if (!config_name_logged)
+ {
+ LOG_FMT(LNOTE, "log_config: the configuration file is: %s\n",
+ cpd.filename.c_str());
+ config_name_logged = true;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// This identity function exists so that all Option<T>::str can simply call
+// to_string(m_val); this function will be used by Option<string>
+std::string to_string(const std::string &in)
+{
+ return(in);
+}
+
+using std::to_string;
+
+
+//-----------------------------------------------------------------------------
+std::string to_lower(const char *in, std::string::size_type size = 0)
+{
+ std::string out;
+
+ if (size > 0)
+ {
+ out.reserve(size);
+ }
+
+ while (*in)
+ {
+ out += static_cast<char>(std::tolower(*in));
+ ++in;
+ }
+ return(out);
+}
+
+
+//-----------------------------------------------------------------------------
+std::string to_lower(const std::string &in)
+{
+ return(to_lower(in.data(), in.size()));
+}
+
+
+//-----------------------------------------------------------------------------
+bool is_arg_sep(int ch)
+{
+ return( isspace(ch)
+ || ch == ','
+ || ch == '=');
+}
+
+
+//-----------------------------------------------------------------------------
+bool is_varg_sep(int ch)
+{
+ return(ch == '.');
+}
+
+
+//-----------------------------------------------------------------------------
+std::vector<std::string> split_args(std::string in, const char *filename,
+ bool (*is_sep)(int))
+{
+ std::vector<std::string> out;
+ std::string::size_type n = 0;
+ std::string::size_type k = in.size();
+
+ // Parse input string
+ while (n < k)
+ {
+ // Skip leading space
+ while ( n < k
+ && is_sep(in[n]))
+ {
+ ++n;
+ }
+
+ // Detect comments or trailing space
+ if ( n >= k
+ || in[n] == '#')
+ {
+ break;
+ }
+
+ // Detect and extract quoted string
+ if (const auto *quote = strchr("\'\"`", in[n]))
+ {
+ const auto start = ++n;
+
+ for ((void)n; in[n] != *quote; ++n)
+ {
+ if ( n < k
+ && in[n] == '\\')
+ {
+ in.erase(n, 1);
+ --k;
+ }
+
+ if (n >= k)
+ {
+ OptionWarning w{ filename };
+ w("found unterminated quoted-string");
+ return{};
+ }
+ }
+
+ out.push_back(in.substr(start, n - start));
+
+ if ( ++n < k
+ && !is_sep(in[n]))
+ {
+ OptionWarning w{ filename };
+ w("unexpected text following quoted-string");
+ return{};
+ }
+ continue;
+ }
+ // Extract anything else
+ const auto start = n;
+
+ for ((void)n;
+ ( n < k
+ && !is_sep(in[n]));
+ ++n)
+ {
+ if (in[n] == '\\')
+ {
+ in.erase(n, 1);
+ --k;
+ }
+
+ if (n >= k)
+ {
+ OptionWarning w{ filename };
+ w("found unterminated quoted-string");
+ return{};
+ }
+ }
+
+ out.push_back(in.substr(start, n - start));
+ }
+ return(out);
+} // split_args
+
+
+//-----------------------------------------------------------------------------
+bool is_path_relative(const std::string &path)
+{
+ assert(!path.empty());
+
+#ifdef WIN32
+ // Check for partition labels as indication for an absolute path
+ // 'X:\path\to\file' style absolute disk path
+ if ( path.size() > 1
+ && isalpha(path[0])
+ && path[1] == ':')
+ {
+ return(false);
+ }
+
+ // Check for double backslashs as indication for a network path
+ // '\\server\path\to\file style' absolute UNC path
+ if ( path.size() > 1
+ && path[0] == '\\'
+ && path[1] == '\\')
+ {
+ return(false);
+ }
+#endif
+
+ // Check for a slash as indication for a filename with leading path
+ // '/path/to/file' style absolute path
+ return(path[0] != '/');
+}
+
+
+//-----------------------------------------------------------------------------
+void print_description(FILE *pfile, std::string description,
+ const char *eol_marker)
+{
+ // Descriptions always start with a '\n', so skip the first character
+ for (std::string::size_type start = 1, length = description.length();
+ ( start != std::string::npos
+ && start < length);
+ ++start)
+ {
+ // Check for empty line so we can squelch trailing whitespace
+ if (description[start] == '\n')
+ {
+ fprintf(pfile, "#%s", eol_marker);
+ }
+ else
+ {
+ const auto end = description.find('\n', start);
+ fprintf(pfile, "# %s%s",
+ description.substr(start, end - start).c_str(), eol_marker);
+ start = end;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+bool process_option_line_compat_0_68(const std::string &cmd,
+ const std::vector<std::string> &args,
+ const char *filename)
+{
+ if (cmd == "sp_cpp_lambda_paren")
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; use '%s' instead",
+ cmd.c_str(), options::sp_cpp_lambda_square_paren.name());
+
+ UNUSED(options::sp_cpp_lambda_square_paren.read(args[1].c_str()));
+ return(true);
+ }
+ return(false);
+} // process_option_line_compat_0_68
+
+
+bool process_option_line_compat_0_70(const std::string &cmd,
+ const char *filename)
+{
+ if (cmd == "sp_word_brace") // Issue #2428
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; did you want to use '%s' instead?",
+ cmd.c_str(), options::sp_type_brace_init_lst.name());
+
+ //UNUSED(options::sp_type_brace_init_lst.read(args[1].c_str()));
+ return(true);
+ }
+ return(false);
+} // process_option_line_compat_0_70
+
+
+bool process_option_line_compat_0_73(const std::string &cmd,
+ const char *filename)
+{
+ if (cmd == "indent_sing_line_comments") // Issue #3249
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; did you want to use '%s' instead?",
+ cmd.c_str(), options::indent_single_line_comments_before.name());
+
+ //UNUSED(options::indent_single_line_comments_before.read(args[1].c_str()));
+ return(true);
+ }
+
+ if (cmd == "sp_before_tr_emb_cmt") // Issue #3339
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; did you want to use '%s' instead?",
+ cmd.c_str(), options::sp_before_tr_cmt.name());
+
+ //UNUSED(options::sp_before_tr_cmt.read(args[1].c_str()));
+ return(true);
+ }
+
+ if (cmd == "sp_num_before_tr_emb_cmt") // Issue #3339
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; did you want to use '%s' instead?",
+ cmd.c_str(), options::sp_num_before_tr_cmt.name());
+
+ //UNUSED(options::sp_num_before_tr_cmt.read(args[1].c_str()));
+ return(true);
+ }
+ return(false);
+} // process_option_line_compat_0_73
+
+
+bool process_option_line_compat_0_74(const std::string &cmd,
+ const char *filename)
+{
+ if (cmd == "sp_type_question") // PR #3638
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; did you want to use '%s' instead?",
+ cmd.c_str(), options::sp_before_ptr_star.name());
+
+ return(true);
+ }
+ return(false);
+} // process_option_line_compat_0_74
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<T> and helpers
+
+
+//-----------------------------------------------------------------------------
+OptionWarning::OptionWarning(const char *filename, Severity severity)
+{
+ if (severity != MINOR)
+ {
+ ++cpd.error_count;
+ }
+
+ if (cpd.line_number != 0)
+ {
+ fprintf(stderr, "%s:%u: ", filename, cpd.line_number);
+ }
+ else
+ {
+ fprintf(stderr, "%s: ", filename);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+OptionWarning::OptionWarning(const GenericOption *opt, Severity severity)
+{
+ if (severity != MINOR)
+ {
+ ++cpd.error_count;
+ }
+ fprintf(stderr, "Option<%s>: at %s:%d: ", to_string(opt->type()),
+ cpd.filename.c_str(), cpd.line_number);
+}
+
+
+//-----------------------------------------------------------------------------
+OptionWarning::~OptionWarning()
+{
+ fprintf(stderr, "\n");
+ log_flush(true);
+}
+
+
+//-----------------------------------------------------------------------------
+void OptionWarning::operator()(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+
+
+//-----------------------------------------------------------------------------
+void GenericOption::warnUnexpectedValue(const char *actual) const
+{
+ OptionWarning w{ this };
+
+ auto values = possibleValues();
+
+ if (values[1] == nullptr)
+ {
+ w("Expected %s ", *values);
+ }
+ else
+ {
+ w("Expected one of ");
+
+ while (*values)
+ {
+ w("'%s'", *values);
+
+ if (*(++values))
+ {
+ w(", ");
+ }
+ }
+ }
+ w(", for '%s'; got '%s'", name(), actual);
+}
+
+
+//-----------------------------------------------------------------------------
+void GenericOption::warnIncompatibleReference(const GenericOption *ref) const
+{
+ OptionWarning w{ this };
+
+ w("%s references option %s with incompatible type %s",
+ name(), ref->name(), to_string(ref->type()));
+}
+
+
+//-----------------------------------------------------------------------------
+template<typename T>
+bool read_enum(const char *in, Option<T> &out)
+{
+ assert(in);
+
+ if (convert_string(in, out.m_val))
+ {
+ return(true);
+ }
+
+ if (const auto *const opt = find_option(in))
+ {
+ if (opt->type() != out.type())
+ {
+ out.warnIncompatibleReference(opt);
+ return(false);
+ }
+ auto &topt = *static_cast<const Option<T> *>(opt);
+ out.m_val = topt();
+ return(true);
+ }
+ out.warnUnexpectedValue(in);
+ return(false);
+}
+
+
+//-----------------------------------------------------------------------------
+template<typename T>
+bool read_number(const char *in, Option<T> &out)
+{
+ assert(in);
+
+ char *c;
+ const auto val = std::strtol(in, &c, 10);
+
+ if ( *c == 0
+ && out.validate(val))
+ {
+ out.m_val = static_cast<T>(val);
+ return(true);
+ }
+ bool invert = false;
+
+ if (strchr("-", in[0]))
+ {
+ invert = true;
+ ++in;
+ }
+
+ if (const auto *const opt = find_option(in))
+ {
+ LOG_CONFIG("%s(%d): line_number is %d, option(%s) %s, ref(%s) %s\n",
+ __func__, __LINE__, cpd.line_number,
+ to_string(out.type()), out.name(),
+ to_string(opt->type()), opt->name());
+
+ long tval;
+
+ if (opt->type() == OT_NUM)
+ {
+ auto &sopt = *static_cast<const Option<signed> *>(opt);
+ tval = static_cast<long>(sopt());
+ }
+ else if (opt->type() == OT_UNUM)
+ {
+ auto &uopt = *static_cast<const Option<unsigned> *>(opt);
+ tval = static_cast<long>(uopt());
+ }
+ else
+ {
+ out.warnIncompatibleReference(opt);
+ return(false);
+ }
+ const auto rval = (invert ? -tval : tval);
+
+ if (out.validate(rval))
+ {
+ out.m_val = static_cast<T>(rval);
+ return(true);
+ }
+ return(false);
+ }
+ out.warnUnexpectedValue(in);
+ return(false);
+} // read_number
+
+
+//-----------------------------------------------------------------------------
+template<typename T>
+void Option<T>::reset()
+{
+ m_val = m_default;
+}
+
+
+//-----------------------------------------------------------------------------
+template<typename T>
+std::string Option<T>::str() const
+{
+ return(to_string(m_val));
+}
+
+
+//-----------------------------------------------------------------------------
+template<typename T>
+std::string Option<T>::defaultStr() const
+{
+ return(m_default != T{} ? to_string(m_default) : std::string{});
+}
+
+// Explicit instantiations
+template class Option<bool>;
+template class Option<iarf_e>;
+template class Option<line_end_e>;
+template class Option<token_pos_e>;
+template class Option<signed>;
+template class Option<unsigned>;
+template class Option<std::string>;
+
+//END Option<T> and helpers
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<bool>
+
+
+//-----------------------------------------------------------------------------
+template<>
+option_type_e Option<bool>::type() const
+{
+ return(OT_BOOL);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+const char *const *Option<bool>::possibleValues() const
+{
+ static char const *values[] = { "true", "false", nullptr };
+
+ return(values);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+bool Option<bool>::read(const char *in)
+{
+ assert(in);
+
+ if (convert_string(in, m_val))
+ {
+ return(true);
+ }
+ bool invert = false;
+
+ if (strchr("~!-", in[0]))
+ {
+ invert = true;
+ ++in;
+ }
+
+ if (const auto *const opt = find_option(in))
+ {
+ if (opt->type() != OT_BOOL)
+ {
+ warnIncompatibleReference(opt);
+ return(false);
+ }
+ auto &bopt = *static_cast<const Option<bool> *>(opt);
+ m_val = (invert ? !bopt() : bopt());
+ return(true);
+ }
+ warnUnexpectedValue(in);
+ return(false);
+}
+
+//END Option<bool>
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<iarf_e>
+
+
+//-----------------------------------------------------------------------------
+template<>
+option_type_e Option<iarf_e>::type() const
+{
+ return(OT_IARF);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+const char *const *Option<iarf_e>::possibleValues() const
+{
+ return(iarf_values);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+bool Option<iarf_e>::read(const char *in)
+{
+ return(read_enum(in, *this));
+}
+
+//END Option<iarf_e>
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<line_end_e>
+
+
+//-----------------------------------------------------------------------------
+template<>
+option_type_e Option<line_end_e>::type() const
+{
+ return(OT_LINEEND);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+const char *const *Option<line_end_e>::possibleValues() const
+{
+ return(line_end_values);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+bool Option<line_end_e>::read(const char *in)
+{
+ return(read_enum(in, *this));
+}
+
+//END Option<line_end_e>
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<token_pos_e>
+
+
+//-----------------------------------------------------------------------------
+template<>
+option_type_e Option<token_pos_e>::type() const
+{
+ return(OT_TOKENPOS);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+const char *const *Option<token_pos_e>::possibleValues() const
+{
+ return(token_pos_values);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+bool Option<token_pos_e>::read(const char *in)
+{
+ return(read_enum(in, *this));
+}
+
+//END Option<token_pos_e>
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<signed>
+
+
+//-----------------------------------------------------------------------------
+template<>
+option_type_e Option<signed>::type() const
+{
+ return(OT_NUM);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+const char *const *Option<signed>::possibleValues() const
+{
+ static char const *values[] = { "number", nullptr };
+
+ return(values);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+bool Option<signed>::read(const char *in)
+{
+ return(read_number(in, *this));
+}
+
+//END Option<signed>
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<unsigned>
+
+
+//-----------------------------------------------------------------------------
+template<>
+option_type_e Option<unsigned>::type() const
+{
+ return(OT_UNUM);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+const char *const *Option<unsigned>::possibleValues() const
+{
+ static char const *values[] = { "unsigned number", nullptr };
+
+ return(values);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+bool Option<unsigned>::read(const char *in)
+{
+ return(read_number(in, *this));
+}
+
+//END Option<unsigned>
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<string>
+
+
+//-----------------------------------------------------------------------------
+template<>
+option_type_e Option<std::string>::type() const
+{
+ return(OT_STRING);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+const char *const *Option<std::string>::possibleValues() const
+{
+ static char const *values[] = { "string", nullptr };
+
+ return(values);
+}
+
+
+//-----------------------------------------------------------------------------
+template<>
+bool Option<std::string>::read(const char *in)
+{
+ m_val = in;
+ return(true);
+}
+
+//END Option<string>
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN global functions for options
+
+
+//-----------------------------------------------------------------------------
+void begin_option_group(const char *description)
+{
+ auto g = OptionGroup{ description, {} };
+
+ option_groups.push_back(g);
+}
+
+
+//-----------------------------------------------------------------------------
+void register_option(GenericOption *option)
+{
+ assert(!option_groups.empty());
+
+ option_groups.back().options.push_back(option);
+ option_map.emplace(option->name(), option);
+}
+
+
+//-----------------------------------------------------------------------------
+uncrustify::GenericOption *find_option(const char *name)
+{
+ const auto iter = option_map.find(to_lower(name));
+
+ if (iter != option_map.end())
+ {
+ return(iter->second);
+ }
+ return(nullptr);
+}
+
+
+//-----------------------------------------------------------------------------
+OptionGroup *get_option_group(size_t i)
+{
+ if (i >= option_groups.size())
+ {
+ return(nullptr);
+ }
+ return(&option_groups[i]);
+}
+
+
+//-----------------------------------------------------------------------------
+size_t get_option_count()
+{
+ return(option_map.size());
+}
+
+
+//-----------------------------------------------------------------------------
+void process_option_line(const std::string &config_line, const char *filename,
+ int &compat_level)
+{
+ // Split line into arguments, and punt if no arguments are present
+ auto args = split_args(config_line, filename, is_arg_sep);
+
+ if (args.empty())
+ {
+ return;
+ }
+ // Check for necessary arguments
+ const auto &cmd = to_lower(args.front());
+
+ if ( cmd == "set"
+ || cmd == "file_ext")
+ {
+ if (args.size() < 3)
+ {
+ OptionWarning w{ filename };
+ w("%s requires at least three arguments", cmd.c_str());
+ return;
+ }
+ }
+ else
+ {
+ if (args.size() < 2)
+ {
+ OptionWarning w{ filename };
+ w("%s requires at least two arguments", cmd.c_str());
+ return;
+ }
+ }
+
+ if (cmd == "type")
+ {
+ for (size_t i = 1; i < args.size(); ++i)
+ {
+ add_keyword(args[i], CT_TYPE);
+ }
+ }
+ else if (cmd == "macro-open")
+ {
+ add_keyword(args[1], CT_MACRO_OPEN);
+ }
+ else if (cmd == "macro-close")
+ {
+ add_keyword(args[1], CT_MACRO_CLOSE);
+ }
+ else if (cmd == "macro-else")
+ {
+ add_keyword(args[1], CT_MACRO_ELSE);
+ }
+ else if (cmd == "set")
+ {
+ const auto token = find_token_name(args[1].c_str());
+
+ if (token != CT_NONE)
+ {
+ LOG_FMT(LNOTE, "%s:%d set '%s':",
+ filename, cpd.line_number, args[1].c_str());
+
+ for (size_t i = 2; i < args.size(); ++i)
+ {
+ LOG_FMT(LNOTE, " '%s'", args[i].c_str());
+ add_keyword(args[i], token);
+ }
+
+ LOG_FMT(LNOTE, "\n");
+ }
+ else
+ {
+ OptionWarning w{ filename };
+ w("%s: unknown type '%s'", cmd.c_str(), args[1].c_str());
+ }
+ }
+#ifndef EMSCRIPTEN
+ else if (cmd == "include")
+ {
+ auto this_line_number = cpd.line_number;
+ const auto &include_path = args[1];
+
+ if (include_path.empty())
+ {
+ OptionWarning w{ filename };
+ w("include: path cannot be empty");
+ }
+ else if (is_path_relative(include_path))
+ {
+ // include is a relative path to the current config file
+ unc_text ut = std::string{ filename };
+ ut.resize(static_cast<unsigned>(path_dirname_len(filename)));
+ ut.append(include_path);
+ UNUSED(load_option_file(ut.c_str(), compat_level));
+ }
+ else
+ {
+ // include is an absolute path
+ UNUSED(load_option_file(include_path.c_str(), compat_level));
+ }
+ cpd.line_number = this_line_number;
+ }
+#endif
+ else if (cmd == "file_ext")
+ {
+ auto *const lang_arg = args[1].c_str();
+
+ for (size_t i = 2; i < args.size(); ++i)
+ {
+ auto *const lang_name = extension_add(args[i].c_str(), lang_arg);
+
+ if (lang_name)
+ {
+ LOG_FMT(LNOTE, "%s:%d file_ext '%s' => '%s'\n",
+ filename, cpd.line_number, args[i].c_str(), lang_name);
+ }
+ else
+ {
+ OptionWarning w{ filename };
+ w("file_ext: unknown language '%s'", lang_arg);
+ break;
+ }
+ }
+ }
+ else if (cmd == "using")
+ {
+ auto vargs = split_args(args[1], filename, is_varg_sep);
+
+ if (vargs.size() == 2)
+ {
+ compat_level = option_level(std::stoi(vargs[0]), std::stoi(vargs[1]));
+ }
+ else if (vargs.size() == 3)
+ {
+ compat_level = option_level(std::stoi(vargs[0]),
+ std::stoi(vargs[1]),
+ std::stoi(vargs[2]));
+ }
+ else
+ {
+ OptionWarning w{ filename };
+ w("%s requires a version number in the form MAJOR.MINOR[.PATCH]",
+ cmd.c_str());
+ }
+ }
+ else
+ {
+ // Must be a regular option = value
+ if (compat_level < option_level(0, 69))
+ {
+ if (process_option_line_compat_0_68(cmd, args, filename))
+ {
+ return;
+ }
+ }
+
+ if (compat_level < option_level(0, 71))
+ {
+ if (process_option_line_compat_0_70(cmd, filename))
+ {
+ return;
+ }
+ }
+
+ if (compat_level < option_level(0, 74))
+ {
+ if (process_option_line_compat_0_73(cmd, filename))
+ {
+ return;
+ }
+ }
+
+ if (compat_level < option_level(0, 75))
+ {
+ if (process_option_line_compat_0_74(cmd, filename))
+ {
+ return;
+ }
+ }
+ const auto oi = option_map.find(cmd);
+
+ if (oi == option_map.end())
+ {
+ OptionWarning w{ filename };
+ w("unknown option '%s'", args[0].c_str());
+ }
+ else
+ {
+ UNUSED(oi->second->read(args[1].c_str()));
+ }
+ }
+} // process_option_line
+
+
+//-----------------------------------------------------------------------------
+bool load_option_file(const char *filename, int compat_level)
+{
+ cpd.line_number = 0;
+
+#ifdef WIN32
+ // "/dev/null" not understood by "fopen" in Windows
+ if (strcasecmp(filename, "/dev/null") == 0)
+ {
+ return(true);
+ }
+#endif
+
+ std::ifstream in;
+ in.open(filename, std::ifstream::in);
+
+ if (!in.good())
+ {
+ OptionWarning w{ filename };
+ w("file could not be opened: %s (%d)\n",
+ strerror(errno), errno);
+ return(false);
+ }
+ // Read in the file line by line
+ std::string line;
+
+ while (std::getline(in, line))
+ {
+ // check all characters of the line
+ size_t howmany = line.length();
+ int ch;
+
+ for (size_t n = 0; n < howmany; n++)
+ {
+ ch = line[n];
+
+ // do not check characters in comment part of line
+ if ('#' == ch)
+ {
+ break;
+ }
+
+ // ch >= 0 && ch <= 255
+ if ( ch < 0
+ || ch > 255)
+ {
+ // error
+ // related to PR #3298
+ fprintf(stderr, "%s: line %u: Character at position %zu, is not printable.\n", filename, cpd.line_number + 1, n + 1);
+ return(false);
+ }
+ }
+
+ ++cpd.line_number;
+ process_option_line(line, filename, compat_level);
+ }
+ return(true);
+} // load_option_file
+
+
+//-----------------------------------------------------------------------------
+const char *get_eol_marker()
+{
+ static char eol[3] = { 0x0A, 0x00, 0x00 };
+
+ const auto &lines = cpd.newline.get();
+
+ for (size_t i = 0; i < lines.size(); ++i)
+ {
+ eol[i] = static_cast<char>(lines[i]);
+ }
+
+ return(eol);
+}
+
+
+//-----------------------------------------------------------------------------
+void save_option_file(FILE *pfile, bool with_doc, bool minimal)
+{
+ int non_default_values = 0;
+ const char *eol_marker = get_eol_marker();
+
+ fprintf(pfile, "# %s%s", UNCRUSTIFY_VERSION, eol_marker);
+
+ // Print the options by group
+ for (auto &og : option_groups)
+ {
+ bool first = true;
+
+ for (auto *option : og.options)
+ {
+ const auto val = option->str();
+
+ if (!option->isDefault())
+ {
+ ++non_default_values;
+ }
+ else if (minimal)
+ {
+ continue;
+ }
+ //....................................................................
+
+ if (with_doc)
+ {
+ assert(option->description() != nullptr);
+ assert(*option->description() != 0);
+
+ if (first)
+ {
+ fprintf(pfile, "%s#%s", eol_marker, eol_marker);
+ print_description(pfile, og.description, eol_marker);
+ fprintf(pfile, "#%s", eol_marker);
+ }
+ fprintf(pfile, "%s", eol_marker);
+ print_description(pfile, option->description(), eol_marker);
+
+ const auto ds = option->defaultStr();
+
+ if (!ds.empty())
+ {
+ fprintf(pfile, "#%s# Default: %s%s",
+ eol_marker, ds.c_str(), eol_marker);
+ }
+ }
+ first = false;
+
+ const int name_len = static_cast<int>(strlen(option->name()));
+ const int pad = name_len < uncrustify::limits::MAX_OPTION_NAME_LEN
+ ? (uncrustify::limits::MAX_OPTION_NAME_LEN - name_len)
+ : 1;
+
+ fprintf(pfile, "%s%*.s= ", option->name(), pad, " ");
+
+ if (option->type() == OT_STRING)
+ {
+ fprintf(pfile, "\"%s\"", val.c_str());
+ }
+ else
+ {
+ fprintf(pfile, "%s", val.c_str());
+ }
+
+ if (with_doc)
+ {
+ const int val_len = static_cast<int>(val.length());
+ fprintf(pfile, "%*.s # ", 8 - val_len, " ");
+
+ for (auto pv = option->possibleValues(); *pv; ++pv)
+ {
+ fprintf(pfile, "%s%s", *pv, pv[1] ? "/" : "");
+ }
+ }
+ fputs(eol_marker, pfile);
+ }
+ }
+
+ if (with_doc)
+ {
+ fprintf(pfile, "%s", DOC_TEXT_END);
+ }
+ print_custom_keywords(pfile); // Print custom keywords
+ print_extensions(pfile); // Print custom file extensions
+
+ fprintf(pfile, "# option(s) with 'not default' value: %d%s#%s",
+ non_default_values, eol_marker, eol_marker);
+} // save_option_file
+
+} // namespace uncrustify
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.h
new file mode 100644
index 00000000..4ab356b5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option.h
@@ -0,0 +1,365 @@
+/**
+ * @file option.h
+ * Enumerations and data types for options.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * October 2015, 2016
+ * @author Matthew Woehlke since version 0.67
+ * @license GPL v2+
+ */
+#ifndef OPTION_H_INCLUDED
+#define OPTION_H_INCLUDED
+
+/* NOTE:
+ * This file is processed by make_option_enum.py, which parses any 'enum class'
+ * it finds, as well as the special macros UNC_OPTVAL_ALIAS and UNC_OPTVALS.
+ *
+ * The '// <PREFIX>' comment after an 'enum class' tells the script to generate
+ * aliases for the enum values using the prefix that is given in the '<>'s.
+ * Don't remove or alter these.
+ */
+
+#include "enum_flags.h"
+
+#include <string>
+#include <vector>
+
+#include <cassert>
+
+#ifdef IGNORE // WinBase.h
+#undef IGNORE
+#endif
+
+namespace uncrustify
+{
+
+template<typename T> class Option;
+
+//-----------------------------------------------------------------------------
+// Option types
+enum class option_type_e // <OT>
+{
+ // UNC_CONVERT_INTERNAL
+ BOOL,
+ IARF,
+ LINEEND,
+ TOKENPOS,
+ NUM,
+ UNUM,
+ STRING,
+};
+
+#if 0 // Fake enumeration for make_option_enum.py
+enum class bool
+{
+ true,
+ false,
+};
+#endif
+
+//-----------------------------------------------------------------------------
+/// I/A/R/F values - these are bit fields
+enum class iarf_e // <IARF>
+{
+ IGNORE = 0, //! option ignores a given feature
+ ADD = (1u << 0), //! option adds a given feature
+ REMOVE = (1u << 1), //! option removes a given feature
+ FORCE = (ADD | REMOVE), //! option forces the usage of a given feature
+ NOT_DEFINED = (1u << 2) //! for debugging
+};
+
+UNC_DECLARE_FLAGS(iarf_flags_t, iarf_e);
+UNC_DECLARE_OPERATORS_FOR_FLAGS(iarf_flags_t);
+
+//-----------------------------------------------------------------------------
+/// Line endings
+enum class line_end_e // <LE>
+{
+ LF, //! "\n" typically used on Unix/Linux system
+ CRLF, //! "\r\n" typically used on Windows systems
+ CR, //! "\r" carriage return without newline
+ AUTO, //! keep last
+};
+constexpr auto line_end_styles = static_cast<size_t>(line_end_e::AUTO);
+
+//-----------------------------------------------------------------------------
+/// Token position - these are bit fields
+enum class token_pos_e // <TP>
+{
+ IGNORE = 0, //! don't change it
+ BREAK = 1, //! add a newline before or after the if not present
+ FORCE = 2, //! force a newline on one side and not the other
+ LEAD = 4, //! at the start of a line or leading if wrapped line
+ TRAIL = 8, //! at the end of a line or trailing if wrapped line
+ JOIN = 16, //! remove newlines on both sides
+ LEAD_BREAK = (LEAD | BREAK), // 5
+ LEAD_FORCE = (LEAD | FORCE), // 6
+ TRAIL_BREAK = (TRAIL | BREAK), // 9
+ TRAIL_FORCE = (TRAIL | FORCE), // 10
+};
+
+UNC_DECLARE_FLAGS(token_pos_flags_t, token_pos_e);
+UNC_DECLARE_OPERATORS_FOR_FLAGS(token_pos_flags_t);
+
+//-----------------------------------------------------------------------------
+/// Abstract (untyped) interface for options
+class GenericOption
+{
+public:
+ GenericOption(const char *opt_name, const char *opt_desc)
+ : m_name{opt_name}
+ , m_desc{opt_desc}
+ {}
+
+ virtual ~GenericOption() = default;
+
+ virtual option_type_e type() const = 0;
+ const char *name() const { return(m_name); }
+ const char *description() const { return(m_desc); }
+ virtual const char *const *possibleValues() const = 0;
+
+ virtual std::string defaultStr() const = 0;
+ virtual std::string minStr() const { return(std::string{}); }
+ virtual std::string maxStr() const { return(std::string{}); }
+
+ virtual bool isDefault() const = 0;
+
+ virtual void reset() = 0;
+ virtual bool read(const char *s) = 0;
+ virtual std::string str() const = 0;
+
+protected:
+ template<typename V> friend bool read_enum(const char *s, Option<V> &o);
+ template<typename V> friend bool read_number(const char *s, Option<V> &o);
+
+ void warnUnexpectedValue(const char *actual) const;
+ void warnIncompatibleReference(const GenericOption *ref) const;
+
+ const char *const m_name;
+ const char *const m_desc;
+};
+
+//-----------------------------------------------------------------------------
+// Helper class for reporting problems with options
+class OptionWarning
+{
+public:
+ enum class /* UNC_NO_META */ Severity
+ {
+ OS_CRITICAL,
+ OS_MINOR,
+ };
+
+ constexpr static auto CRITICAL = Severity::OS_CRITICAL;
+ constexpr static auto MINOR = Severity::OS_MINOR;
+
+ OptionWarning(const char *filename, Severity = CRITICAL);
+ OptionWarning(const GenericOption *, Severity = CRITICAL);
+ OptionWarning(const OptionWarning &) = delete;
+ ~OptionWarning();
+
+#ifdef __GNUC__
+ [[gnu::format(printf, 2, 3)]]
+#endif
+ void operator()(const char *fmt, ...);
+};
+
+//-----------------------------------------------------------------------------
+// Concrete (strongly typed) interface for options
+template<typename T>
+class Option : public GenericOption
+{
+public:
+ Option(const char *opt_name, const char *opt_desc, T opt_val = T{})
+ : GenericOption{opt_name, opt_desc}
+ , m_val{opt_val}
+ , m_default{opt_val}
+ {}
+
+ option_type_e type() const override;
+ const char *const *possibleValues() const override;
+
+ std::string defaultStr() const override;
+
+ bool isDefault() const override { return(m_val == m_default); }
+
+ //! resets option to its default value
+ //- currently only used by the emscripten interface
+ virtual void reset() override;
+
+ bool read(const char *s) override;
+ std::string str() const override;
+
+ T operator()() const { return(m_val); }
+ Option &operator=(T val) { m_val = val; return(*this); }
+
+protected:
+ template<typename V> friend bool read_enum(const char *s, Option<V> &o);
+ template<typename V> friend bool read_number(const char *s, Option<V> &o);
+
+ virtual bool validate(long) { return(true); }
+
+ T m_val = T{};
+ T m_default = T{};
+};
+
+//-----------------------------------------------------------------------------
+// Concrete (strongly typed) interface for bounded numeric options
+template<typename T, T min, T max>
+class BoundedOption : public Option<T>
+{
+public:
+ BoundedOption(const char *opt_name, const char *opt_desc, T opt_val = T{})
+ : Option<T>{opt_name, opt_desc, opt_val}
+ {
+ assert( opt_val >= min
+ && opt_val <= max);
+ }
+
+ std::string minStr() const override { return(std::to_string(min)); }
+ std::string maxStr() const override { return(std::to_string(max)); }
+
+protected:
+ bool validate(long val) override
+ {
+ if (val < static_cast<long>(min))
+ {
+ OptionWarning w{ this };
+ w("requested value %ld for option '%s' "
+ "is less than the minimum value %ld",
+ val, this->name(), static_cast<long>(min));
+ return(false);
+ }
+
+ if (val > static_cast<long>(max))
+ {
+ OptionWarning w{ this };
+ w("requested value %ld for option '%s' "
+ "is greater than the maximum value %ld",
+ val, this->name(), static_cast<long>(max));
+ return(false);
+ }
+ return(true);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Declaration of option types; implementations are in option.cpp
+#define UNC_IMPLEMENT_OPTION(T) \
+ template<> option_type_e Option<T>::type() const; \
+ template<> const char *const *Option<T>::possibleValues() const; \
+ template<> bool Option<T>::read(const char *s); \
+ extern template class Option<T>
+
+UNC_IMPLEMENT_OPTION(bool);
+UNC_IMPLEMENT_OPTION(iarf_e);
+UNC_IMPLEMENT_OPTION(line_end_e);
+UNC_IMPLEMENT_OPTION(token_pos_e);
+UNC_IMPLEMENT_OPTION(signed);
+UNC_IMPLEMENT_OPTION(unsigned);
+UNC_IMPLEMENT_OPTION(std::string);
+
+// Additional mappings for option values
+#define UNC_OPTVAL_ALIAS(...) \
+ static_assert(true, "This is just a tag for make_option_enum.py")
+
+UNC_OPTVAL_ALIAS(bool, false, "0", "f", "n", "no");
+UNC_OPTVAL_ALIAS(bool, true, "1", "t", "y", "yes");
+UNC_OPTVAL_ALIAS(iarf_e, IGNORE, "i");
+UNC_OPTVAL_ALIAS(iarf_e, ADD, "a", "2", "t", "true", "y", "yes");
+UNC_OPTVAL_ALIAS(iarf_e, REMOVE, "r", "0", "f", "false", "n", "no");
+UNC_OPTVAL_ALIAS(iarf_e, FORCE, "f", "1");
+
+// Possible values for options, by type
+#define UNC_OPTVALS(e) extern const char *const e ## _values[]
+UNC_OPTVALS(iarf);
+UNC_OPTVALS(line_end);
+UNC_OPTVALS(token_pos);
+
+extern bool convert_string(const char *, bool &);
+extern bool convert_string(const char *, iarf_e &);
+extern bool convert_string(const char *, line_end_e &);
+extern bool convert_string(const char *, token_pos_e &);
+
+extern const char *to_string(bool);
+extern const char *to_string(iarf_e);
+extern const char *to_string(line_end_e);
+extern const char *to_string(token_pos_e);
+extern const char *to_string(option_type_e);
+
+struct OptionGroup
+{
+ const char *description;
+ std::vector<GenericOption *> options;
+};
+
+
+/**
+ * @brief Defines a new group of uncrustify options.
+ *
+ * New options are always added to the most recently defined group.
+ */
+void begin_option_group(const char *description);
+
+
+/**
+ * @brief Adds an uncrustify option to the global option registry.
+ *
+ * The option is added to the most recently defined option group.
+ */
+void register_option(GenericOption *);
+
+
+GenericOption *find_option(const char *name);
+
+
+//! Add all uncrustify options to the global option registry
+void register_options(void);
+
+
+OptionGroup *get_option_group(size_t);
+
+
+size_t get_option_count();
+
+
+/**
+ * processes a single line string to extract configuration settings
+ * increments cpd.line_number and cpd.error_count
+ *
+ * @param config_line single line string that will be processed
+ * @param filename for log messages, file from which the \p config_line
+ * param was extracted
+ * @param compat_level version of Uncrustify with which to be compatible
+ */
+void process_option_line(const std::string &config_line, const char *filename, int &compat_level);
+
+
+bool load_option_file(const char *filename, int compat_level = 0);
+
+
+/**
+ * save the used options into a text file
+ *
+ * @param pfile file to print into
+ * @param with_doc also print description
+ * @param minimal print only options with non default value
+ */
+void save_option_file(FILE *pfile, bool with_doc = false, bool minimal = false);
+
+
+/**
+ * get the marker that was selected for the end of line via the config file
+ *
+ * @return "\n" if newlines was set to LE_LF in the config file
+ * @return "\r\n" if newlines was set to LE_CRLF in the config file
+ * @return "\r" if newlines was set to LE_CR in the config file
+ * @return "\n" if newlines was set to LE_AUTO in the config file
+ */
+const char *get_eol_marker();
+
+} // namespace uncrustify
+
+#endif /* OPTION_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.cpp.in b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.cpp.in
new file mode 100644
index 00000000..aeb976b2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.cpp.in
@@ -0,0 +1,24 @@
+##BANNER##
+#include "options.h"
+
+#include "base_types.h"
+#include "logger.h"
+
+#include <cstdlib>
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h> // strcasecmp()
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4809)
+#elif __GNUC__ > 4 || __clang_major__ > 3 || __clang_minor__ > 4
+#pragma GCC diagnostic ignored "-Wswitch-bool"
+#endif
+
+namespace uncrustify
+{
+
+##VALUE_STRINGS##
+##CONVERSIONS##
+} // namespace uncrustify
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.h.in b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.h.in
new file mode 100644
index 00000000..e50a9281
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/option_enum.h.in
@@ -0,0 +1,17 @@
+##BANNER##
+#ifndef OPTION_ENUM_H_INCLUDED
+#define OPTION_ENUM_H_INCLUDED
+
+#include "option.h"
+
+#ifdef IGNORE // WinBase.h
+#undef IGNORE
+#endif
+
+namespace uncrustify
+{
+
+##ALIASES##
+} // namespace uncrustify
+
+#endif /* OPTION_ENUM_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.cpp.in b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.cpp.in
new file mode 100644
index 00000000..2ee14c8b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.cpp.in
@@ -0,0 +1,26 @@
+##BANNER##
+
+#include "uncrustify_types.h"
+
+namespace uncrustify
+{
+
+//BEGIN declarations of option object instances
+
+namespace options
+{
+
+##DECLARATIONS##
+} // namespace options
+
+//END declarations of option object instances
+
+///////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+void register_options(void)
+{
+##REGISTRATIONS##
+}
+
+} // namespace uncrustify
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.h
new file mode 100644
index 00000000..d3e5386d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options.h
@@ -0,0 +1,4189 @@
+/**
+ * @file options.h
+ * Declarations of all the options.
+ *
+ * September 2020
+ * @author Ben Gardner
+ * @author Guy Maurel
+ * @author Matthew Woehlke
+ * @license GPL v2+
+ */
+
+#ifndef OPTIONS_H_INCLUDED
+#define OPTIONS_H_INCLUDED
+
+/* NOTE:
+ * This file is processed by make_options.py, and must conform to a particular
+ * format. Option groups are marked by '//begin ' (in upper case; this example
+ * is lower case to prevent being considered a region marker for code folding)
+ * followed by the group description. Options consist of two lines of
+ * declaration preceded by one or more lines of C++ comments. The comments form
+ * the option description and are taken verbatim, aside from stripping the
+ * leading '// '. Only comments immediately preceding an option declaration,
+ * with no blank lines, are taken as part of the description, so a blank line
+ * may be used to separate notations from a description.
+ *
+ * An option declaration is 'extern TYPE\nNAME;', optionally followed by
+ * ' // = VALUE' if the option has a default value that is different from the
+ * default-constructed value type of the option. The 'VALUE' must be valid C++
+ * code, and is taken verbatim as an argument when creating the option's
+ * instantiation. Note also that the line break, as shown, is required.
+ */
+
+#include "option_enum.h"
+
+namespace uncrustify
+{
+
+namespace options
+{
+
+using std::string;
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN General options
+
+// The type of line endings.
+extern Option<line_end_e>
+newlines; // = LE_AUTO
+
+// The original size of tabs in the input.
+extern BoundedOption<unsigned, 1, 32>
+input_tab_size; // = 8
+
+// The size of tabs in the output (only used if align_with_tabs=true).
+extern BoundedOption<unsigned, 1, 32>
+output_tab_size; // = 8
+
+// The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^).
+extern BoundedOption<unsigned, 0, 255>
+string_escape_char; // = '\\'
+
+// Alternate string escape char (usually only used for Pawn).
+// Only works right before the quote char.
+extern BoundedOption<unsigned, 0, 255>
+string_escape_char2;
+
+// Replace tab characters found in string literals with the escape sequence \t
+// instead.
+extern Option<bool>
+string_replace_tab_chars;
+
+// Allow interpreting '>=' and '>>=' as part of a template in code like
+// 'void f(list<list<B>>=val);'. If true, 'assert(x<0 && y>=3)' will be broken.
+// Improvements to template detection may make this option obsolete.
+extern Option<bool>
+tok_split_gte;
+
+// Disable formatting of NL_CONT ('\\n') ended lines (e.g. multi-line macros).
+extern Option<bool>
+disable_processing_nl_cont;
+
+// Specify the marker used in comments to disable processing of part of the
+// file.
+extern Option<string>
+disable_processing_cmt; // = UNCRUSTIFY_OFF_TEXT
+
+// Specify the marker used in comments to (re)enable processing in a file.
+extern Option<string>
+enable_processing_cmt; // = UNCRUSTIFY_ON_TEXT
+
+// Enable parsing of digraphs.
+extern Option<bool>
+enable_digraphs;
+
+// Option to allow both disable_processing_cmt and enable_processing_cmt
+// strings, if specified, to be interpreted as ECMAScript regular expressions.
+// If true, a regex search will be performed within comments according to the
+// specified patterns in order to disable/enable processing.
+extern Option<bool>
+processing_cmt_as_regex;
+
+// Add or remove the UTF-8 BOM (recommend 'remove').
+extern Option<iarf_e>
+utf8_bom;
+
+// If the file contains bytes with values between 128 and 255, but is not
+// UTF-8, then output as UTF-8.
+extern Option<bool>
+utf8_byte;
+
+// Force the output encoding to UTF-8.
+extern Option<bool>
+utf8_force;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Spacing options
+
+// Add or remove space around non-assignment symbolic operators ('+', '/', '%',
+// '<<', and so forth).
+extern Option<iarf_e>
+sp_arith;
+
+// Add or remove space around arithmetic operators '+' and '-'.
+//
+// Overrides sp_arith.
+extern Option<iarf_e>
+sp_arith_additive;
+
+// Add or remove space around assignment operator '=', '+=', etc.
+extern Option<iarf_e>
+sp_assign;
+
+// Add or remove space around '=' in C++11 lambda capture specifications.
+//
+// Overrides sp_assign.
+extern Option<iarf_e>
+sp_cpp_lambda_assign;
+
+// Add or remove space after the capture specification of a C++11 lambda when
+// an argument list is present, as in '[] <here> (int x){ ... }'.
+extern Option<iarf_e>
+sp_cpp_lambda_square_paren;
+
+// Add or remove space after the capture specification of a C++11 lambda with
+// no argument list is present, as in '[] <here> { ... }'.
+extern Option<iarf_e>
+sp_cpp_lambda_square_brace;
+
+// Add or remove space after the opening parenthesis and before the closing
+// parenthesis of a argument list of a C++11 lambda, as in
+// '[]( <here> int x <here> ){ ... }'.
+extern Option<iarf_e>
+sp_cpp_lambda_argument_list;
+
+// Add or remove space after the argument list of a C++11 lambda, as in
+// '[](int x) <here> { ... }'.
+extern Option<iarf_e>
+sp_cpp_lambda_paren_brace;
+
+// Add or remove space between a lambda body and its call operator of an
+// immediately invoked lambda, as in '[]( ... ){ ... } <here> ( ... )'.
+extern Option<iarf_e>
+sp_cpp_lambda_fparen;
+
+// Add or remove space around assignment operator '=' in a prototype.
+//
+// If set to ignore, use sp_assign.
+extern Option<iarf_e>
+sp_assign_default;
+
+// Add or remove space before assignment operator '=', '+=', etc.
+//
+// Overrides sp_assign.
+extern Option<iarf_e>
+sp_before_assign;
+
+// Add or remove space after assignment operator '=', '+=', etc.
+//
+// Overrides sp_assign.
+extern Option<iarf_e>
+sp_after_assign;
+
+// Add or remove space in 'enum {'.
+extern Option<iarf_e>
+sp_enum_brace; // = IARF_ADD
+
+// Add or remove space in 'NS_ENUM ('.
+extern Option<iarf_e>
+sp_enum_paren;
+
+// Add or remove space around assignment '=' in enum.
+extern Option<iarf_e>
+sp_enum_assign;
+
+// Add or remove space before assignment '=' in enum.
+//
+// Overrides sp_enum_assign.
+extern Option<iarf_e>
+sp_enum_before_assign;
+
+// Add or remove space after assignment '=' in enum.
+//
+// Overrides sp_enum_assign.
+extern Option<iarf_e>
+sp_enum_after_assign;
+
+// Add or remove space around assignment ':' in enum.
+extern Option<iarf_e>
+sp_enum_colon;
+
+// Add or remove space around preprocessor '##' concatenation operator.
+extern Option<iarf_e>
+sp_pp_concat; // = IARF_ADD
+
+// Add or remove space after preprocessor '#' stringify operator.
+// Also affects the '#@' charizing operator.
+extern Option<iarf_e>
+sp_pp_stringify;
+
+// Add or remove space before preprocessor '#' stringify operator
+// as in '#define x(y) L#y'.
+extern Option<iarf_e>
+sp_before_pp_stringify;
+
+// Add or remove space around boolean operators '&&' and '||'.
+extern Option<iarf_e>
+sp_bool;
+
+// Add or remove space around compare operator '<', '>', '==', etc.
+extern Option<iarf_e>
+sp_compare;
+
+// Add or remove space inside '(' and ')'.
+extern Option<iarf_e>
+sp_inside_paren;
+
+// Add or remove space between nested parentheses, i.e. '((' vs. ') )'.
+extern Option<iarf_e>
+sp_paren_paren;
+
+// Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('.
+extern Option<iarf_e>
+sp_cparen_oparen;
+
+// Whether to balance spaces inside nested parentheses.
+extern Option<bool>
+sp_balance_nested_parens;
+
+// Add or remove space between ')' and '{'.
+extern Option<iarf_e>
+sp_paren_brace;
+
+// Add or remove space between nested braces, i.e. '{{' vs. '{ {'.
+extern Option<iarf_e>
+sp_brace_brace;
+
+// Add or remove space before pointer star '*'.
+extern Option<iarf_e>
+sp_before_ptr_star;
+
+// Add or remove space before pointer star '*' that isn't followed by a
+// variable name. If set to ignore, sp_before_ptr_star is used instead.
+extern Option<iarf_e>
+sp_before_unnamed_ptr_star;
+
+// Add or remove space between pointer stars '*', as in 'int ***a;'.
+extern Option<iarf_e>
+sp_between_ptr_star;
+
+// Add or remove space after pointer star '*', if followed by a word.
+//
+// Overrides sp_type_func.
+extern Option<iarf_e>
+sp_after_ptr_star;
+
+// Add or remove space after pointer caret '^', if followed by a word.
+extern Option<iarf_e>
+sp_after_ptr_block_caret;
+
+// Add or remove space after pointer star '*', if followed by a qualifier.
+extern Option<iarf_e>
+sp_after_ptr_star_qualifier;
+
+// Add or remove space after a pointer star '*', if followed by a function
+// prototype or function definition.
+//
+// Overrides sp_after_ptr_star and sp_type_func.
+extern Option<iarf_e>
+sp_after_ptr_star_func;
+
+// Add or remove space after a pointer star '*' in the trailing return of a
+// function prototype or function definition.
+extern Option<iarf_e>
+sp_after_ptr_star_trailing;
+
+// Add or remove space between the pointer star '*' and the name of the variable
+// in a function pointer definition.
+extern Option<iarf_e>
+sp_ptr_star_func_var;
+
+// Add or remove space between the pointer star '*' and the name of the type
+// in a function pointer type definition.
+extern Option<iarf_e>
+sp_ptr_star_func_type;
+
+// Add or remove space after a pointer star '*', if followed by an open
+// parenthesis, as in 'void* (*)()'.
+extern Option<iarf_e>
+sp_ptr_star_paren;
+
+// Add or remove space before a pointer star '*', if followed by a function
+// prototype or function definition.
+extern Option<iarf_e>
+sp_before_ptr_star_func;
+
+// Add or remove space before a pointer star '*' in the trailing return of a
+// function prototype or function definition.
+extern Option<iarf_e>
+sp_before_ptr_star_trailing;
+
+// Add or remove space before a reference sign '&'.
+extern Option<iarf_e>
+sp_before_byref;
+
+// Add or remove space before a reference sign '&' that isn't followed by a
+// variable name. If set to ignore, sp_before_byref is used instead.
+extern Option<iarf_e>
+sp_before_unnamed_byref;
+
+// Add or remove space after reference sign '&', if followed by a word.
+//
+// Overrides sp_type_func.
+extern Option<iarf_e>
+sp_after_byref;
+
+// Add or remove space after a reference sign '&', if followed by a function
+// prototype or function definition.
+//
+// Overrides sp_after_byref and sp_type_func.
+extern Option<iarf_e>
+sp_after_byref_func;
+
+// Add or remove space before a reference sign '&', if followed by a function
+// prototype or function definition.
+extern Option<iarf_e>
+sp_before_byref_func;
+
+// Add or remove space after a reference sign '&', if followed by an open
+// parenthesis, as in 'char& (*)()'.
+extern Option<iarf_e>
+sp_byref_paren;
+
+// Add or remove space between type and word. In cases where total removal of
+// whitespace would be a syntax error, a value of 'remove' is treated the same
+// as 'force'.
+//
+// This also affects some other instances of space following a type that are
+// not covered by other options; for example, between the return type and
+// parenthesis of a function type template argument, between the type and
+// parenthesis of an array parameter, or between 'decltype(...)' and the
+// following word.
+extern Option<iarf_e>
+sp_after_type; // = IARF_FORCE
+
+// Add or remove space between 'decltype(...)' and word,
+// brace or function call.
+extern Option<iarf_e>
+sp_after_decltype;
+
+// (D) Add or remove space before the parenthesis in the D constructs
+// 'template Foo(' and 'class Foo('.
+extern Option<iarf_e>
+sp_before_template_paren;
+
+// Add or remove space between 'template' and '<'.
+// If set to ignore, sp_before_angle is used.
+extern Option<iarf_e>
+sp_template_angle;
+
+// Add or remove space before '<'.
+extern Option<iarf_e>
+sp_before_angle;
+
+// Add or remove space inside '<' and '>'.
+extern Option<iarf_e>
+sp_inside_angle;
+
+// Add or remove space inside '<>'.
+extern Option<iarf_e>
+sp_inside_angle_empty;
+
+// Add or remove space between '>' and ':'.
+extern Option<iarf_e>
+sp_angle_colon;
+
+// Add or remove space after '>'.
+extern Option<iarf_e>
+sp_after_angle;
+
+// Add or remove space between '>' and '(' as found in 'new List<byte>(foo);'.
+extern Option<iarf_e>
+sp_angle_paren;
+
+// Add or remove space between '>' and '()' as found in 'new List<byte>();'.
+extern Option<iarf_e>
+sp_angle_paren_empty;
+
+// Add or remove space between '>' and a word as in 'List<byte> m;' or
+// 'template <typename T> static ...'.
+extern Option<iarf_e>
+sp_angle_word;
+
+// Add or remove space between '>' and '>' in '>>' (template stuff).
+extern Option<iarf_e>
+sp_angle_shift; // = IARF_ADD
+
+// (C++11) Permit removal of the space between '>>' in 'foo<bar<int> >'. Note
+// that sp_angle_shift cannot remove the space without this option.
+extern Option<bool>
+sp_permit_cpp11_shift;
+
+// Add or remove space before '(' of control statements ('if', 'for', 'switch',
+// 'while', etc.).
+extern Option<iarf_e>
+sp_before_sparen;
+
+// Add or remove space inside '(' and ')' of control statements other than
+// 'for'.
+extern Option<iarf_e>
+sp_inside_sparen;
+
+// Add or remove space after '(' of control statements other than 'for'.
+//
+// Overrides sp_inside_sparen.
+extern Option<iarf_e>
+sp_inside_sparen_open;
+
+// Add or remove space before ')' of control statements other than 'for'.
+//
+// Overrides sp_inside_sparen.
+extern Option<iarf_e>
+sp_inside_sparen_close;
+
+// Add or remove space inside '(' and ')' of 'for' statements.
+extern Option<iarf_e>
+sp_inside_for;
+
+// Add or remove space after '(' of 'for' statements.
+//
+// Overrides sp_inside_for.
+extern Option<iarf_e>
+sp_inside_for_open;
+
+// Add or remove space before ')' of 'for' statements.
+//
+// Overrides sp_inside_for.
+extern Option<iarf_e>
+sp_inside_for_close;
+
+// Add or remove space between '((' or '))' of control statements.
+extern Option<iarf_e>
+sp_sparen_paren;
+
+// Add or remove space after ')' of control statements.
+extern Option<iarf_e>
+sp_after_sparen;
+
+// Add or remove space between ')' and '{' of control statements.
+extern Option<iarf_e>
+sp_sparen_brace;
+
+// Add or remove space between 'do' and '{'.
+extern Option<iarf_e>
+sp_do_brace_open;
+
+// Add or remove space between '}' and 'while'.
+extern Option<iarf_e>
+sp_brace_close_while;
+
+// Add or remove space between 'while' and '('. Overrides sp_before_sparen.
+extern Option<iarf_e>
+sp_while_paren_open;
+
+// (D) Add or remove space between 'invariant' and '('.
+extern Option<iarf_e>
+sp_invariant_paren;
+
+// (D) Add or remove space after the ')' in 'invariant (C) c'.
+extern Option<iarf_e>
+sp_after_invariant_paren;
+
+// Add or remove space before empty statement ';' on 'if', 'for' and 'while'.
+extern Option<iarf_e>
+sp_special_semi;
+
+// Add or remove space before ';'.
+extern Option<iarf_e>
+sp_before_semi; // = IARF_REMOVE
+
+// Add or remove space before ';' in non-empty 'for' statements.
+extern Option<iarf_e>
+sp_before_semi_for;
+
+// Add or remove space before a semicolon of an empty left part of a for
+// statement, as in 'for ( <here> ; ; )'.
+extern Option<iarf_e>
+sp_before_semi_for_empty;
+
+// Add or remove space between the semicolons of an empty middle part of a for
+// statement, as in 'for ( ; <here> ; )'.
+extern Option<iarf_e>
+sp_between_semi_for_empty;
+
+// Add or remove space after ';', except when followed by a comment.
+extern Option<iarf_e>
+sp_after_semi; // = IARF_ADD
+
+// Add or remove space after ';' in non-empty 'for' statements.
+extern Option<iarf_e>
+sp_after_semi_for; // = IARF_FORCE
+
+// Add or remove space after the final semicolon of an empty part of a for
+// statement, as in 'for ( ; ; <here> )'.
+extern Option<iarf_e>
+sp_after_semi_for_empty;
+
+// Add or remove space before '[' (except '[]').
+extern Option<iarf_e>
+sp_before_square;
+
+// Add or remove space before '[' for a variable definition.
+extern Option<iarf_e>
+sp_before_vardef_square; // = IARF_REMOVE
+
+// Add or remove space before '[' for asm block.
+extern Option<iarf_e>
+sp_before_square_asm_block;
+
+// Add or remove space before '[]'.
+extern Option<iarf_e>
+sp_before_squares;
+
+// Add or remove space before C++17 structured bindings.
+extern Option<iarf_e>
+sp_cpp_before_struct_binding;
+
+// Add or remove space inside a non-empty '[' and ']'.
+extern Option<iarf_e>
+sp_inside_square;
+
+// Add or remove space inside '[]'.
+extern Option<iarf_e>
+sp_inside_square_empty;
+
+// (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and
+// ']'. If set to ignore, sp_inside_square is used.
+extern Option<iarf_e>
+sp_inside_square_oc_array;
+
+// Add or remove space after ',', i.e. 'a,b' vs. 'a, b'.
+extern Option<iarf_e>
+sp_after_comma;
+
+// Add or remove space before ',', i.e. 'a,b' vs. 'a ,b'.
+extern Option<iarf_e>
+sp_before_comma; // = IARF_REMOVE
+
+// (C#) Add or remove space between ',' and ']' in multidimensional array type
+// like 'int[,,]'.
+extern Option<iarf_e>
+sp_after_mdatype_commas;
+
+// (C#) Add or remove space between '[' and ',' in multidimensional array type
+// like 'int[,,]'.
+extern Option<iarf_e>
+sp_before_mdatype_commas;
+
+// (C#) Add or remove space between ',' in multidimensional array type
+// like 'int[,,]'.
+extern Option<iarf_e>
+sp_between_mdatype_commas;
+
+// Add or remove space between an open parenthesis and comma,
+// i.e. '(,' vs. '( ,'.
+extern Option<iarf_e>
+sp_paren_comma; // = IARF_FORCE
+
+// Add or remove space between a type and ':'.
+extern Option<iarf_e>
+sp_type_colon;
+
+// Add or remove space after the variadic '...' when preceded by a
+// non-punctuator.
+// The value REMOVE will be overridden with FORCE
+extern Option<iarf_e>
+sp_after_ellipsis;
+
+// Add or remove space before the variadic '...' when preceded by a
+// non-punctuator.
+// The value REMOVE will be overridden with FORCE
+extern Option<iarf_e>
+sp_before_ellipsis;
+
+// Add or remove space between a type and '...'.
+extern Option<iarf_e>
+sp_type_ellipsis;
+
+// Add or remove space between a '*' and '...'.
+extern Option<iarf_e>
+sp_ptr_type_ellipsis;
+
+// Add or remove space between ')' and '...'.
+extern Option<iarf_e>
+sp_paren_ellipsis;
+
+// Add or remove space between '&&' and '...'.
+extern Option<iarf_e>
+sp_byref_ellipsis;
+
+// Add or remove space between ')' and a qualifier such as 'const'.
+extern Option<iarf_e>
+sp_paren_qualifier;
+
+// Add or remove space between ')' and 'noexcept'.
+extern Option<iarf_e>
+sp_paren_noexcept;
+
+// Add or remove space after class ':'.
+extern Option<iarf_e>
+sp_after_class_colon;
+
+// Add or remove space before class ':'.
+extern Option<iarf_e>
+sp_before_class_colon;
+
+// Add or remove space after class constructor ':'.
+extern Option<iarf_e>
+sp_after_constr_colon; // = IARF_ADD
+
+// Add or remove space before class constructor ':'.
+extern Option<iarf_e>
+sp_before_constr_colon; // = IARF_ADD
+
+// Add or remove space before case ':'.
+extern Option<iarf_e>
+sp_before_case_colon; // = IARF_REMOVE
+
+// Add or remove space between 'operator' and operator sign.
+extern Option<iarf_e>
+sp_after_operator;
+
+// Add or remove space between the operator symbol and the open parenthesis, as
+// in 'operator ++('.
+extern Option<iarf_e>
+sp_after_operator_sym;
+
+// Overrides sp_after_operator_sym when the operator has no arguments, as in
+// 'operator *()'.
+extern Option<iarf_e>
+sp_after_operator_sym_empty;
+
+// Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or
+// '(int)a' vs. '(int) a'.
+extern Option<iarf_e>
+sp_after_cast;
+
+// Add or remove spaces inside cast parentheses.
+extern Option<iarf_e>
+sp_inside_paren_cast;
+
+// Add or remove space between the type and open parenthesis in a C++ cast,
+// i.e. 'int(exp)' vs. 'int (exp)'.
+extern Option<iarf_e>
+sp_cpp_cast_paren;
+
+// Add or remove space between 'sizeof' and '('.
+extern Option<iarf_e>
+sp_sizeof_paren;
+
+// Add or remove space between 'sizeof' and '...'.
+extern Option<iarf_e>
+sp_sizeof_ellipsis;
+
+// Add or remove space between 'sizeof...' and '('.
+extern Option<iarf_e>
+sp_sizeof_ellipsis_paren;
+
+// Add or remove space between '...' and a parameter pack.
+extern Option<iarf_e>
+sp_ellipsis_parameter_pack;
+
+// Add or remove space between a parameter pack and '...'.
+extern Option<iarf_e>
+sp_parameter_pack_ellipsis;
+
+// Add or remove space between 'decltype' and '('.
+extern Option<iarf_e>
+sp_decltype_paren;
+
+// (Pawn) Add or remove space after the tag keyword.
+extern Option<iarf_e>
+sp_after_tag;
+
+// Add or remove space inside enum '{' and '}'.
+extern Option<iarf_e>
+sp_inside_braces_enum;
+
+// Add or remove space inside struct/union '{' and '}'.
+extern Option<iarf_e>
+sp_inside_braces_struct;
+
+// (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}'
+extern Option<iarf_e>
+sp_inside_braces_oc_dict;
+
+// Add or remove space after open brace in an unnamed temporary
+// direct-list-initialization
+// if statement is a brace_init_lst
+// works only if sp_brace_brace is set to ignore.
+extern Option<iarf_e>
+sp_after_type_brace_init_lst_open;
+
+// Add or remove space before close brace in an unnamed temporary
+// direct-list-initialization
+// if statement is a brace_init_lst
+// works only if sp_brace_brace is set to ignore.
+extern Option<iarf_e>
+sp_before_type_brace_init_lst_close;
+
+// Add or remove space inside an unnamed temporary direct-list-initialization
+// if statement is a brace_init_lst
+// works only if sp_brace_brace is set to ignore
+// works only if sp_before_type_brace_init_lst_close is set to ignore.
+extern Option<iarf_e>
+sp_inside_type_brace_init_lst;
+
+// Add or remove space inside '{' and '}'.
+extern Option<iarf_e>
+sp_inside_braces;
+
+// Add or remove space inside '{}'.
+extern Option<iarf_e>
+sp_inside_braces_empty;
+
+// Add or remove space around trailing return operator '->'.
+extern Option<iarf_e>
+sp_trailing_return;
+
+// Add or remove space between return type and function name. A minimum of 1
+// is forced except for pointer return types.
+extern Option<iarf_e>
+sp_type_func;
+
+// Add or remove space between type and open brace of an unnamed temporary
+// direct-list-initialization.
+extern Option<iarf_e>
+sp_type_brace_init_lst;
+
+// Add or remove space between function name and '(' on function declaration.
+extern Option<iarf_e>
+sp_func_proto_paren;
+
+// Add or remove space between function name and '()' on function declaration
+// without parameters.
+extern Option<iarf_e>
+sp_func_proto_paren_empty;
+
+// Add or remove space between function name and '(' with a typedef specifier.
+extern Option<iarf_e>
+sp_func_type_paren;
+
+// Add or remove space between alias name and '(' of a non-pointer function type typedef.
+extern Option<iarf_e>
+sp_func_def_paren;
+
+// Add or remove space between function name and '()' on function definition
+// without parameters.
+extern Option<iarf_e>
+sp_func_def_paren_empty;
+
+// Add or remove space inside empty function '()'.
+// Overrides sp_after_angle unless use_sp_after_angle_always is set to true.
+extern Option<iarf_e>
+sp_inside_fparens;
+
+// Add or remove space inside function '(' and ')'.
+extern Option<iarf_e>
+sp_inside_fparen;
+
+// Add or remove space inside the first parentheses in a function type, as in
+// 'void (*x)(...)'.
+extern Option<iarf_e>
+sp_inside_tparen;
+
+// Add or remove space between the ')' and '(' in a function type, as in
+// 'void (*x)(...)'.
+extern Option<iarf_e>
+sp_after_tparen_close;
+
+// Add or remove space between ']' and '(' when part of a function call.
+extern Option<iarf_e>
+sp_square_fparen;
+
+// Add or remove space between ')' and '{' of function.
+extern Option<iarf_e>
+sp_fparen_brace;
+
+// Add or remove space between ')' and '{' of a function call in object
+// initialization.
+//
+// Overrides sp_fparen_brace.
+extern Option<iarf_e>
+sp_fparen_brace_initializer;
+
+// (Java) Add or remove space between ')' and '{{' of double brace initializer.
+extern Option<iarf_e>
+sp_fparen_dbrace;
+
+// Add or remove space between function name and '(' on function calls.
+extern Option<iarf_e>
+sp_func_call_paren;
+
+// Add or remove space between function name and '()' on function calls without
+// parameters. If set to ignore (the default), sp_func_call_paren is used.
+extern Option<iarf_e>
+sp_func_call_paren_empty;
+
+// Add or remove space between the user function name and '(' on function
+// calls. You need to set a keyword to be a user function in the config file,
+// like:
+// set func_call_user tr _ i18n
+extern Option<iarf_e>
+sp_func_call_user_paren;
+
+// Add or remove space inside user function '(' and ')'.
+extern Option<iarf_e>
+sp_func_call_user_inside_fparen;
+
+// Add or remove space between nested parentheses with user functions,
+// i.e. '((' vs. '( ('.
+extern Option<iarf_e>
+sp_func_call_user_paren_paren;
+
+// Add or remove space between a constructor/destructor and the open
+// parenthesis.
+extern Option<iarf_e>
+sp_func_class_paren;
+
+// Add or remove space between a constructor without parameters or destructor
+// and '()'.
+extern Option<iarf_e>
+sp_func_class_paren_empty;
+
+// Add or remove space after 'return'.
+extern Option<iarf_e>
+sp_return; // = IARF_FORCE
+
+// Add or remove space between 'return' and '('.
+extern Option<iarf_e>
+sp_return_paren;
+
+// Add or remove space between 'return' and '{'.
+extern Option<iarf_e>
+sp_return_brace;
+
+// Add or remove space between '__attribute__' and '('.
+extern Option<iarf_e>
+sp_attribute_paren;
+
+// Add or remove space between 'defined' and '(' in '#if defined (FOO)'.
+extern Option<iarf_e>
+sp_defined_paren;
+
+// Add or remove space between 'throw' and '(' in 'throw (something)'.
+extern Option<iarf_e>
+sp_throw_paren;
+
+// Add or remove space between 'throw' and anything other than '(' as in
+// '@throw [...];'.
+extern Option<iarf_e>
+sp_after_throw;
+
+// Add or remove space between 'catch' and '(' in 'catch (something) { }'.
+// If set to ignore, sp_before_sparen is used.
+extern Option<iarf_e>
+sp_catch_paren;
+
+// (OC) Add or remove space between '@catch' and '('
+// in '@catch (something) { }'. If set to ignore, sp_catch_paren is used.
+extern Option<iarf_e>
+sp_oc_catch_paren;
+
+// (OC) Add or remove space before Objective-C protocol list
+// as in '@protocol Protocol<here><Protocol_A>' or '@interface MyClass : NSObject<here><MyProtocol>'.
+extern Option<iarf_e>
+sp_before_oc_proto_list;
+
+// (OC) Add or remove space between class name and '('
+// in '@interface className(categoryName)<ProtocolName>:BaseClass'
+extern Option<iarf_e>
+sp_oc_classname_paren;
+
+// (D) Add or remove space between 'version' and '('
+// in 'version (something) { }'. If set to ignore, sp_before_sparen is used.
+extern Option<iarf_e>
+sp_version_paren;
+
+// (D) Add or remove space between 'scope' and '('
+// in 'scope (something) { }'. If set to ignore, sp_before_sparen is used.
+extern Option<iarf_e>
+sp_scope_paren;
+
+// Add or remove space between 'super' and '(' in 'super (something)'.
+extern Option<iarf_e>
+sp_super_paren; // = IARF_REMOVE
+
+// Add or remove space between 'this' and '(' in 'this (something)'.
+extern Option<iarf_e>
+sp_this_paren; // = IARF_REMOVE
+
+// Add or remove space between a macro name and its definition.
+extern Option<iarf_e>
+sp_macro;
+
+// Add or remove space between a macro function ')' and its definition.
+extern Option<iarf_e>
+sp_macro_func;
+
+// Add or remove space between 'else' and '{' if on the same line.
+extern Option<iarf_e>
+sp_else_brace;
+
+// Add or remove space between '}' and 'else' if on the same line.
+extern Option<iarf_e>
+sp_brace_else;
+
+// Add or remove space between '}' and the name of a typedef on the same line.
+extern Option<iarf_e>
+sp_brace_typedef;
+
+// Add or remove space before the '{' of a 'catch' statement, if the '{' and
+// 'catch' are on the same line, as in 'catch (decl) <here> {'.
+extern Option<iarf_e>
+sp_catch_brace;
+
+// (OC) Add or remove space before the '{' of a '@catch' statement, if the '{'
+// and '@catch' are on the same line, as in '@catch (decl) <here> {'.
+// If set to ignore, sp_catch_brace is used.
+extern Option<iarf_e>
+sp_oc_catch_brace;
+
+// Add or remove space between '}' and 'catch' if on the same line.
+extern Option<iarf_e>
+sp_brace_catch;
+
+// (OC) Add or remove space between '}' and '@catch' if on the same line.
+// If set to ignore, sp_brace_catch is used.
+extern Option<iarf_e>
+sp_oc_brace_catch;
+
+// Add or remove space between 'finally' and '{' if on the same line.
+extern Option<iarf_e>
+sp_finally_brace;
+
+// Add or remove space between '}' and 'finally' if on the same line.
+extern Option<iarf_e>
+sp_brace_finally;
+
+// Add or remove space between 'try' and '{' if on the same line.
+extern Option<iarf_e>
+sp_try_brace;
+
+// Add or remove space between get/set and '{' if on the same line.
+extern Option<iarf_e>
+sp_getset_brace;
+
+// Add or remove space between a variable and '{' for C++ uniform
+// initialization.
+extern Option<iarf_e>
+sp_word_brace_init_lst;
+
+// Add or remove space between a variable and '{' for a namespace.
+extern Option<iarf_e>
+sp_word_brace_ns; // = IARF_ADD
+
+// Add or remove space before the '::' operator.
+extern Option<iarf_e>
+sp_before_dc;
+
+// Add or remove space after the '::' operator.
+extern Option<iarf_e>
+sp_after_dc;
+
+// (D) Add or remove around the D named array initializer ':' operator.
+extern Option<iarf_e>
+sp_d_array_colon;
+
+// Add or remove space after the '!' (not) unary operator.
+extern Option<iarf_e>
+sp_not; // = IARF_REMOVE
+
+// Add or remove space between two '!' (not) unary operators.
+// If set to ignore, sp_not will be used.
+extern Option<iarf_e>
+sp_not_not; // = IARF_IGNORE
+
+// Add or remove space after the '~' (invert) unary operator.
+extern Option<iarf_e>
+sp_inv; // = IARF_REMOVE
+
+// Add or remove space after the '&' (address-of) unary operator. This does not
+// affect the spacing after a '&' that is part of a type.
+extern Option<iarf_e>
+sp_addr; // = IARF_REMOVE
+
+// Add or remove space around the '.' or '->' operators.
+extern Option<iarf_e>
+sp_member; // = IARF_REMOVE
+
+// Add or remove space after the '*' (dereference) unary operator. This does
+// not affect the spacing after a '*' that is part of a type.
+extern Option<iarf_e>
+sp_deref; // = IARF_REMOVE
+
+// Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'.
+extern Option<iarf_e>
+sp_sign; // = IARF_REMOVE
+
+// Add or remove space between '++' and '--' the word to which it is being
+// applied, as in '(--x)' or 'y++;'.
+extern Option<iarf_e>
+sp_incdec; // = IARF_REMOVE
+
+// Add or remove space before a backslash-newline at the end of a line.
+extern Option<iarf_e>
+sp_before_nl_cont; // = IARF_ADD
+
+// (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;'
+// or '+(int) bar;'.
+extern Option<iarf_e>
+sp_after_oc_scope;
+
+// (OC) Add or remove space after the colon in message specs,
+// i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'.
+extern Option<iarf_e>
+sp_after_oc_colon;
+
+// (OC) Add or remove space before the colon in message specs,
+// i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'.
+extern Option<iarf_e>
+sp_before_oc_colon;
+
+// (OC) Add or remove space after the colon in immutable dictionary expression
+// 'NSDictionary *test = @{@"foo" :@"bar"};'.
+extern Option<iarf_e>
+sp_after_oc_dict_colon;
+
+// (OC) Add or remove space before the colon in immutable dictionary expression
+// 'NSDictionary *test = @{@"foo" :@"bar"};'.
+extern Option<iarf_e>
+sp_before_oc_dict_colon;
+
+// (OC) Add or remove space after the colon in message specs,
+// i.e. '[object setValue:1];' vs. '[object setValue: 1];'.
+extern Option<iarf_e>
+sp_after_send_oc_colon;
+
+// (OC) Add or remove space before the colon in message specs,
+// i.e. '[object setValue:1];' vs. '[object setValue :1];'.
+extern Option<iarf_e>
+sp_before_send_oc_colon;
+
+// (OC) Add or remove space after the (type) in message specs,
+// i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'.
+extern Option<iarf_e>
+sp_after_oc_type;
+
+// (OC) Add or remove space after the first (type) in message specs,
+// i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'.
+extern Option<iarf_e>
+sp_after_oc_return_type;
+
+// (OC) Add or remove space between '@selector' and '(',
+// i.e. '@selector(msgName)' vs. '@selector (msgName)'.
+// Also applies to '@protocol()' constructs.
+extern Option<iarf_e>
+sp_after_oc_at_sel;
+
+// (OC) Add or remove space between '@selector(x)' and the following word,
+// i.e. '@selector(foo) a:' vs. '@selector(foo)a:'.
+extern Option<iarf_e>
+sp_after_oc_at_sel_parens;
+
+// (OC) Add or remove space inside '@selector' parentheses,
+// i.e. '@selector(foo)' vs. '@selector( foo )'.
+// Also applies to '@protocol()' constructs.
+extern Option<iarf_e>
+sp_inside_oc_at_sel_parens;
+
+// (OC) Add or remove space before a block pointer caret,
+// i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'.
+extern Option<iarf_e>
+sp_before_oc_block_caret;
+
+// (OC) Add or remove space after a block pointer caret,
+// i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'.
+extern Option<iarf_e>
+sp_after_oc_block_caret;
+
+// (OC) Add or remove space between the receiver and selector in a message,
+// as in '[receiver selector ...]'.
+extern Option<iarf_e>
+sp_after_oc_msg_receiver;
+
+// (OC) Add or remove space after '@property'.
+extern Option<iarf_e>
+sp_after_oc_property;
+
+// (OC) Add or remove space between '@synchronized' and the open parenthesis,
+// i.e. '@synchronized(foo)' vs. '@synchronized (foo)'.
+extern Option<iarf_e>
+sp_after_oc_synchronized;
+
+// Add or remove space around the ':' in 'b ? t : f'.
+extern Option<iarf_e>
+sp_cond_colon;
+
+// Add or remove space before the ':' in 'b ? t : f'.
+//
+// Overrides sp_cond_colon.
+extern Option<iarf_e>
+sp_cond_colon_before;
+
+// Add or remove space after the ':' in 'b ? t : f'.
+//
+// Overrides sp_cond_colon.
+extern Option<iarf_e>
+sp_cond_colon_after;
+
+// Add or remove space around the '?' in 'b ? t : f'.
+extern Option<iarf_e>
+sp_cond_question;
+
+// Add or remove space before the '?' in 'b ? t : f'.
+//
+// Overrides sp_cond_question.
+extern Option<iarf_e>
+sp_cond_question_before;
+
+// Add or remove space after the '?' in 'b ? t : f'.
+//
+// Overrides sp_cond_question.
+extern Option<iarf_e>
+sp_cond_question_after;
+
+// In the abbreviated ternary form '(a ?: b)', add or remove space between '?'
+// and ':'.
+//
+// Overrides all other sp_cond_* options.
+extern Option<iarf_e>
+sp_cond_ternary_short;
+
+// Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make
+// sense here.
+extern Option<iarf_e>
+sp_case_label;
+
+// (D) Add or remove space around the D '..' operator.
+extern Option<iarf_e>
+sp_range;
+
+// Add or remove space after ':' in a Java/C++11 range-based 'for',
+// as in 'for (Type var : <here> expr)'.
+extern Option<iarf_e>
+sp_after_for_colon;
+
+// Add or remove space before ':' in a Java/C++11 range-based 'for',
+// as in 'for (Type var <here> : expr)'.
+extern Option<iarf_e>
+sp_before_for_colon;
+
+// (D) Add or remove space between 'extern' and '(' as in 'extern <here> (C)'.
+extern Option<iarf_e>
+sp_extern_paren;
+
+// Add or remove space after the opening of a C++ comment, as in '// <here> A'.
+extern Option<iarf_e>
+sp_cmt_cpp_start;
+
+// Add or remove space in a C++ region marker comment, as in '// <here> BEGIN'.
+// A region marker is defined as a comment which is not preceded by other text
+// (i.e. the comment is the first non-whitespace on the line), and which starts
+// with either 'BEGIN' or 'END'.
+//
+// Overrides sp_cmt_cpp_start.
+extern Option<iarf_e>
+sp_cmt_cpp_region;
+
+// If true, space added with sp_cmt_cpp_start will be added after Doxygen
+// sequences like '///', '///<', '//!' and '//!<'.
+extern Option<bool>
+sp_cmt_cpp_doxygen;
+
+// If true, space added with sp_cmt_cpp_start will be added after Qt translator
+// or meta-data comments like '//:', '//=', and '//~'.
+extern Option<bool>
+sp_cmt_cpp_qttr;
+
+// Add or remove space between #else or #endif and a trailing comment.
+extern Option<iarf_e>
+sp_endif_cmt;
+
+// Add or remove space after 'new', 'delete' and 'delete[]'.
+extern Option<iarf_e>
+sp_after_new;
+
+// Add or remove space between 'new' and '(' in 'new()'.
+extern Option<iarf_e>
+sp_between_new_paren;
+
+// Add or remove space between ')' and type in 'new(foo) BAR'.
+extern Option<iarf_e>
+sp_after_newop_paren;
+
+// Add or remove space inside parenthesis of the new operator
+// as in 'new(foo) BAR'.
+extern Option<iarf_e>
+sp_inside_newop_paren;
+
+// Add or remove space after the open parenthesis of the new operator,
+// as in 'new(foo) BAR'.
+//
+// Overrides sp_inside_newop_paren.
+extern Option<iarf_e>
+sp_inside_newop_paren_open;
+
+// Add or remove space before the close parenthesis of the new operator,
+// as in 'new(foo) BAR'.
+//
+// Overrides sp_inside_newop_paren.
+extern Option<iarf_e>
+sp_inside_newop_paren_close;
+
+// Add or remove space before a trailing comment.
+extern Option<iarf_e>
+sp_before_tr_cmt;
+
+// Number of spaces before a trailing comment.
+extern BoundedOption<unsigned, 0, 16>
+sp_num_before_tr_cmt;
+
+// Add or remove space before an embedded comment.
+extern Option<iarf_e>
+sp_before_emb_cmt; // = IARF_FORCE
+
+// Number of spaces before an embedded comment.
+extern BoundedOption<unsigned, 0, 16>
+sp_num_before_emb_cmt; // = 1
+
+// Add or remove space after an embedded comment.
+extern Option<iarf_e>
+sp_after_emb_cmt; // = IARF_FORCE
+
+// Number of spaces after an embedded comment.
+extern BoundedOption<unsigned, 0, 16>
+sp_num_after_emb_cmt; // = 1
+
+// (Java) Add or remove space between an annotation and the open parenthesis.
+extern Option<iarf_e>
+sp_annotation_paren;
+
+// If true, vbrace tokens are dropped to the previous token and skipped.
+extern Option<bool>
+sp_skip_vbrace_tokens;
+
+// Add or remove space after 'noexcept'.
+extern Option<iarf_e>
+sp_after_noexcept;
+
+// Add or remove space after '_'.
+extern Option<iarf_e>
+sp_vala_after_translation;
+
+// If true, a <TAB> is inserted after #define.
+extern Option<bool>
+force_tab_after_define;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Indenting options
+
+// The number of columns to indent per level. Usually 2, 3, 4, or 8.
+extern BoundedOption<unsigned, 0, 16>
+indent_columns; // = 8
+
+// Whether to ignore indent for the first continuation line. Subsequent
+// continuation lines will still be indented to match the first.
+extern Option<bool>
+indent_ignore_first_continue;
+
+// The continuation indent. If non-zero, this overrides the indent of '(', '['
+// and '=' continuation indents. Negative values are OK; negative value is
+// absolute and not increased for each '(' or '[' level.
+//
+// For FreeBSD, this is set to 4.
+// Requires indent_ignore_first_continue=false.
+extern BoundedOption<signed, -16, 16>
+indent_continue;
+
+// The continuation indent, only for class header line(s). If non-zero, this
+// overrides the indent of 'class' continuation indents.
+// Requires indent_ignore_first_continue=false.
+extern BoundedOption<unsigned, 0, 16>
+indent_continue_class_head;
+
+// Whether to indent empty lines (i.e. lines which contain only spaces before
+// the newline character).
+extern Option<bool>
+indent_single_newlines;
+
+// The continuation indent for func_*_param if they are true. If non-zero, this
+// overrides the indent.
+extern BoundedOption<unsigned, 0, 16>
+indent_param;
+
+// How to use tabs when indenting code.
+//
+// 0: Spaces only
+// 1: Indent with tabs to brace level, align with spaces (default)
+// 2: Indent and align with tabs, using spaces when not on a tabstop
+extern BoundedOption<unsigned, 0, 2>
+indent_with_tabs; // = 1
+
+// Whether to indent comments that are not at a brace level with tabs on a
+// tabstop. Requires indent_with_tabs=2. If false, will use spaces.
+extern Option<bool>
+indent_cmt_with_tabs;
+
+// Whether to indent strings broken by '\' so that they line up.
+extern Option<bool>
+indent_align_string;
+
+// The number of spaces to indent multi-line XML strings.
+// Requires indent_align_string=true.
+extern BoundedOption<unsigned, 0, 16>
+indent_xml_string;
+
+// Spaces to indent '{' from level.
+extern BoundedOption<unsigned, 0, 16>
+indent_brace;
+
+// Whether braces are indented to the body level.
+extern Option<bool>
+indent_braces;
+
+// Whether to disable indenting function braces if indent_braces=true.
+extern Option<bool>
+indent_braces_no_func;
+
+// Whether to disable indenting class braces if indent_braces=true.
+extern Option<bool>
+indent_braces_no_class;
+
+// Whether to disable indenting struct braces if indent_braces=true.
+extern Option<bool>
+indent_braces_no_struct;
+
+// Whether to indent based on the size of the brace parent,
+// i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc.
+extern Option<bool>
+indent_brace_parent;
+
+// Whether to indent based on the open parenthesis instead of the open brace
+// in '({\n'.
+extern Option<bool>
+indent_paren_open_brace;
+
+// (C#) Whether to indent the brace of a C# delegate by another level.
+extern Option<bool>
+indent_cs_delegate_brace;
+
+// (C#) Whether to indent a C# delegate (to handle delegates with no brace) by
+// another level.
+extern Option<bool>
+indent_cs_delegate_body;
+
+// Whether to indent the body of a 'namespace'.
+extern Option<bool>
+indent_namespace;
+
+// Whether to indent only the first namespace, and not any nested namespaces.
+// Requires indent_namespace=true.
+extern Option<bool>
+indent_namespace_single_indent;
+
+// The number of spaces to indent a namespace block.
+// If set to zero, use the value indent_columns
+extern BoundedOption<unsigned, 0, 16>
+indent_namespace_level;
+
+// If the body of the namespace is longer than this number, it won't be
+// indented. Requires indent_namespace=true. 0 means no limit.
+extern BoundedOption<unsigned, 0, 255>
+indent_namespace_limit;
+
+// Whether to indent only in inner namespaces (nested in other namespaces).
+// Requires indent_namespace=true.
+extern Option<bool>
+indent_namespace_inner_only;
+
+// Whether the 'extern "C"' body is indented.
+extern Option<bool>
+indent_extern;
+
+// Whether the 'class' body is indented.
+extern Option<bool>
+indent_class;
+
+// Whether to ignore indent for the leading base class colon.
+extern Option<bool>
+indent_ignore_before_class_colon;
+
+// Additional indent before the leading base class colon.
+// Negative values decrease indent down to the first column.
+// Requires indent_ignore_before_class_colon=false and a newline break before
+// the colon (see pos_class_colon and nl_class_colon)
+extern BoundedOption<signed, -16, 16>
+indent_before_class_colon;
+
+// Whether to indent the stuff after a leading base class colon.
+extern Option<bool>
+indent_class_colon;
+
+// Whether to indent based on a class colon instead of the stuff after the
+// colon. Requires indent_class_colon=true.
+extern Option<bool>
+indent_class_on_colon;
+
+// Whether to ignore indent for a leading class initializer colon.
+extern Option<bool>
+indent_ignore_before_constr_colon;
+
+// Whether to indent the stuff after a leading class initializer colon.
+extern Option<bool>
+indent_constr_colon;
+
+// Virtual indent from the ':' for leading member initializers.
+extern BoundedOption<unsigned, 0, 16>
+indent_ctor_init_leading; // = 2
+
+// Virtual indent from the ':' for following member initializers.
+extern BoundedOption<unsigned, 0, 16>
+indent_ctor_init_following; // = 2
+
+// Additional indent for constructor initializer list.
+// Negative values decrease indent down to the first column.
+extern BoundedOption<signed, -16, 16>
+indent_ctor_init;
+
+// Whether to indent 'if' following 'else' as a new block under the 'else'.
+// If false, 'else\nif' is treated as 'else if' for indenting purposes.
+extern Option<bool>
+indent_else_if;
+
+// Amount to indent variable declarations after a open brace.
+//
+// <0: Relative
+// >=0: Absolute
+extern BoundedOption<signed, -16, 16>
+indent_var_def_blk;
+
+// Whether to indent continued variable declarations instead of aligning.
+extern Option<bool>
+indent_var_def_cont;
+
+// How to indent continued shift expressions ('<<' and '>>').
+// Set align_left_shift=false when using this.
+// 0: Align shift operators instead of indenting them (default)
+// 1: Indent by one level
+// -1: Preserve original indentation
+extern BoundedOption<signed, -1, 1>
+indent_shift;
+
+// Whether to force indentation of function definitions to start in column 1.
+extern Option<bool>
+indent_func_def_force_col1;
+
+// Whether to indent continued function call parameters one indent level,
+// rather than aligning parameters under the open parenthesis.
+extern Option<bool>
+indent_func_call_param;
+
+// Whether to indent continued function definition parameters one indent level,
+// rather than aligning parameters under the open parenthesis.
+extern Option<bool>
+indent_func_def_param;
+
+// for function definitions, only if indent_func_def_param is false
+// Allows to align params when appropriate and indent them when not
+// behave as if it was true if paren position is more than this value
+// if paren position is more than the option value
+extern BoundedOption<unsigned, 0, 160>
+indent_func_def_param_paren_pos_threshold;
+
+// Whether to indent continued function call prototype one indent level,
+// rather than aligning parameters under the open parenthesis.
+extern Option<bool>
+indent_func_proto_param;
+
+// Whether to indent continued function call declaration one indent level,
+// rather than aligning parameters under the open parenthesis.
+extern Option<bool>
+indent_func_class_param;
+
+// Whether to indent continued class variable constructors one indent level,
+// rather than aligning parameters under the open parenthesis.
+extern Option<bool>
+indent_func_ctor_var_param;
+
+// Whether to indent continued template parameter list one indent level,
+// rather than aligning parameters under the open parenthesis.
+extern Option<bool>
+indent_template_param;
+
+// Double the indent for indent_func_xxx_param options.
+// Use both values of the options indent_columns and indent_param.
+extern Option<bool>
+indent_func_param_double;
+
+// Indentation column for standalone 'const' qualifier on a function
+// prototype.
+extern BoundedOption<unsigned, 0, 69>
+indent_func_const;
+
+// Indentation column for standalone 'throw' qualifier on a function
+// prototype.
+extern BoundedOption<unsigned, 0, 41>
+indent_func_throw;
+
+// How to indent within a macro followed by a brace on the same line
+// This allows reducing the indent in macros that have (for example)
+// `do { ... } while (0)` blocks bracketing them.
+//
+// true: add an indent for the brace on the same line as the macro
+// false: do not add an indent for the brace on the same line as the macro
+extern Option<bool>
+indent_macro_brace; // = true
+
+// The number of spaces to indent a continued '->' or '.'.
+// Usually set to 0, 1, or indent_columns.
+extern BoundedOption<unsigned, 0, 16>
+indent_member;
+
+// Whether lines broken at '.' or '->' should be indented by a single indent.
+// The indent_member option will not be effective if this is set to true.
+extern Option<bool>
+indent_member_single;
+
+// Spaces to indent single line ('//') comments on lines before code.
+extern BoundedOption<unsigned, 0, 16>
+indent_single_line_comments_before;
+
+// Spaces to indent single line ('//') comments on lines after code.
+extern BoundedOption<unsigned, 0, 16>
+indent_single_line_comments_after;
+
+// When opening a paren for a control statement (if, for, while, etc), increase
+// the indent level by this value. Negative values decrease the indent level.
+extern BoundedOption<signed, -16, 16>
+indent_sparen_extra;
+
+// Whether to indent trailing single line ('//') comments relative to the code
+// instead of trying to keep the same absolute column.
+extern Option<bool>
+indent_relative_single_line_comments;
+
+// Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns.
+// It might be wise to choose the same value for the option indent_case_brace.
+extern BoundedOption<unsigned, 0, 16>
+indent_switch_case;
+
+// Spaces to indent the body of a 'switch' before any 'case'.
+// Usually the same as indent_columns or indent_switch_case.
+extern BoundedOption<unsigned, 0, 16>
+indent_switch_body;
+
+// Whether to ignore indent for '{' following 'case'.
+extern Option<bool>
+indent_ignore_case_brace;
+
+// Spaces to indent '{' from 'case'. By default, the brace will appear under
+// the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK.
+// It might be wise to choose the same value for the option indent_switch_case.
+extern BoundedOption<signed, -16, 16>
+indent_case_brace;
+
+// indent 'break' with 'case' from 'switch'.
+extern Option<bool>
+indent_switch_break_with_case;
+
+// Whether to indent preprocessor statements inside of switch statements.
+extern Option<bool>
+indent_switch_pp; // = true
+
+// Spaces to shift the 'case' line, without affecting any other lines.
+// Usually 0.
+extern BoundedOption<unsigned, 0, 16>
+indent_case_shift;
+
+// Whether to align comments before 'case' with the 'case'.
+extern Option<bool>
+indent_case_comment; // = true
+
+// Whether to indent comments not found in first column.
+extern Option<bool>
+indent_comment; // = true
+
+// Whether to indent comments found in first column.
+extern Option<bool>
+indent_col1_comment;
+
+// Whether to indent multi string literal in first column.
+extern Option<bool>
+indent_col1_multi_string_literal;
+
+// Align comments on adjacent lines that are this many columns apart or less.
+extern BoundedOption<unsigned, 0, 16>
+indent_comment_align_thresh; // = 3
+
+// Whether to ignore indent for goto labels.
+extern Option<bool>
+indent_ignore_label;
+
+// How to indent goto labels. Requires indent_ignore_label=false.
+//
+// >0: Absolute column where 1 is the leftmost column
+// <=0: Subtract from brace indent
+extern BoundedOption<signed, -16, 16>
+indent_label; // = 1
+
+// How to indent access specifiers that are followed by a
+// colon.
+//
+// >0: Absolute column where 1 is the leftmost column
+// <=0: Subtract from brace indent
+extern BoundedOption<signed, -16, 16>
+indent_access_spec; // = 1
+
+// Whether to indent the code after an access specifier by one level.
+// If true, this option forces 'indent_access_spec=0'.
+extern Option<bool>
+indent_access_spec_body;
+
+// If an open parenthesis is followed by a newline, whether to indent the next
+// line so that it lines up after the open parenthesis (not recommended).
+extern Option<bool>
+indent_paren_nl;
+
+// How to indent a close parenthesis after a newline.
+//
+// 0: Indent to body level (default)
+// 1: Align under the open parenthesis
+// 2: Indent to the brace level
+// -1: Preserve original indentation
+extern BoundedOption<signed, -1, 2>
+indent_paren_close;
+
+// Whether to indent the open parenthesis of a function definition,
+// if the parenthesis is on its own line.
+extern Option<bool>
+indent_paren_after_func_def;
+
+// Whether to indent the open parenthesis of a function declaration,
+// if the parenthesis is on its own line.
+extern Option<bool>
+indent_paren_after_func_decl;
+
+// Whether to indent the open parenthesis of a function call,
+// if the parenthesis is on its own line.
+extern Option<bool>
+indent_paren_after_func_call;
+
+// How to indent a comma when inside braces.
+// 0: Indent by one level (default)
+// 1: Align under the open brace
+// -1: Preserve original indentation
+extern BoundedOption<signed, -1, 1>
+indent_comma_brace;
+
+// How to indent a comma when inside parentheses.
+// 0: Indent by one level (default)
+// 1: Align under the open parenthesis
+// -1: Preserve original indentation
+extern BoundedOption<signed, -1, 1>
+indent_comma_paren;
+
+// How to indent a Boolean operator when inside parentheses.
+// 0: Indent by one level (default)
+// 1: Align under the open parenthesis
+// -1: Preserve original indentation
+extern BoundedOption<signed, -1, 1>
+indent_bool_paren;
+
+// Whether to ignore the indentation of a Boolean operator when outside
+// parentheses.
+extern Option<bool>
+indent_ignore_bool;
+
+// Whether to ignore the indentation of an arithmetic operator.
+extern Option<bool>
+indent_ignore_arith;
+
+// Whether to indent a semicolon when inside a for parenthesis.
+// If true, aligns under the open for parenthesis.
+extern Option<bool>
+indent_semicolon_for_paren;
+
+// Whether to ignore the indentation of a semicolon outside of a 'for'
+// statement.
+extern Option<bool>
+indent_ignore_semicolon;
+
+// Whether to align the first expression to following ones
+// if indent_bool_paren=1.
+extern Option<bool>
+indent_first_bool_expr;
+
+// Whether to align the first expression to following ones
+// if indent_semicolon_for_paren=true.
+extern Option<bool>
+indent_first_for_expr;
+
+// If an open square is followed by a newline, whether to indent the next line
+// so that it lines up after the open square (not recommended).
+extern Option<bool>
+indent_square_nl;
+
+// (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies.
+extern Option<bool>
+indent_preserve_sql;
+
+// Whether to ignore the indentation of an assignment operator.
+extern Option<bool>
+indent_ignore_assign;
+
+// Whether to align continued statements at the '='. If false or if the '=' is
+// followed by a newline, the next line is indent one tab.
+extern Option<bool>
+indent_align_assign; // = true
+
+// If true, the indentation of the chunks after a '=' sequence will be set at
+// LHS token indentation column before '='.
+extern Option<bool>
+indent_off_after_assign;
+
+// Whether to align continued statements at the '('. If false or the '(' is
+// followed by a newline, the next line indent is one tab.
+extern Option<bool>
+indent_align_paren; // = true
+
+// (OC) Whether to indent Objective-C code inside message selectors.
+extern Option<bool>
+indent_oc_inside_msg_sel;
+
+// (OC) Whether to indent Objective-C blocks at brace level instead of usual
+// rules.
+extern Option<bool>
+indent_oc_block;
+
+// (OC) Indent for Objective-C blocks in a message relative to the parameter
+// name.
+//
+// =0: Use indent_oc_block rules
+// >0: Use specified number of spaces to indent
+extern BoundedOption<unsigned, 0, 16>
+indent_oc_block_msg;
+
+// (OC) Minimum indent for subsequent parameters
+extern BoundedOption<unsigned, 0, 5000>
+indent_oc_msg_colon;
+
+// (OC) Whether to prioritize aligning with initial colon (and stripping spaces
+// from lines, if necessary).
+extern Option<bool>
+indent_oc_msg_prioritize_first_colon; // = true
+
+// (OC) Whether to indent blocks the way that Xcode does by default
+// (from the keyword if the parameter is on its own line; otherwise, from the
+// previous indentation level). Requires indent_oc_block_msg=true.
+extern Option<bool>
+indent_oc_block_msg_xcode_style;
+
+// (OC) Whether to indent blocks from where the brace is, relative to a
+// message keyword. Requires indent_oc_block_msg=true.
+extern Option<bool>
+indent_oc_block_msg_from_keyword;
+
+// (OC) Whether to indent blocks from where the brace is, relative to a message
+// colon. Requires indent_oc_block_msg=true.
+extern Option<bool>
+indent_oc_block_msg_from_colon;
+
+// (OC) Whether to indent blocks from where the block caret is.
+// Requires indent_oc_block_msg=true.
+extern Option<bool>
+indent_oc_block_msg_from_caret;
+
+// (OC) Whether to indent blocks from where the brace caret is.
+// Requires indent_oc_block_msg=true.
+extern Option<bool>
+indent_oc_block_msg_from_brace;
+
+// When indenting after virtual brace open and newline add further spaces to
+// reach this minimum indent.
+extern BoundedOption<unsigned, 0, 16>
+indent_min_vbrace_open;
+
+// Whether to add further spaces after regular indent to reach next tabstop
+// when indenting after virtual brace open and newline.
+extern Option<bool>
+indent_vbrace_open_on_tabstop;
+
+// How to indent after a brace followed by another token (not a newline).
+// true: indent all contained lines to match the token
+// false: indent all contained lines to match the brace
+extern Option<bool>
+indent_token_after_brace; // = true
+
+// Whether to indent the body of a C++11 lambda.
+extern Option<bool>
+indent_cpp_lambda_body;
+
+// How to indent compound literals that are being returned.
+// true: add both the indent from return & the compound literal open brace
+// (i.e. 2 indent levels)
+// false: only indent 1 level, don't add the indent for the open brace, only
+// add the indent for the return.
+extern Option<bool>
+indent_compound_literal_return; // = true
+
+// (C#) Whether to indent a 'using' block if no braces are used.
+extern Option<bool>
+indent_using_block; // = true
+
+// How to indent the continuation of ternary operator.
+//
+// 0: Off (default)
+// 1: When the `if_false` is a continuation, indent it under `if_false`
+// 2: When the `:` is a continuation, indent it under `?`
+extern BoundedOption<unsigned, 0, 2>
+indent_ternary_operator;
+
+// Whether to indent the statements inside ternary operator.
+extern Option<bool>
+indent_inside_ternary_operator;
+
+// If true, the indentation of the chunks after a `return` sequence will be set at return indentation column.
+extern Option<bool>
+indent_off_after_return;
+
+// If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column.
+extern Option<bool>
+indent_off_after_return_new;
+
+// If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token.
+extern Option<bool>
+indent_single_after_return;
+
+// Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they
+// have their own indentation).
+extern Option<bool>
+indent_ignore_asm_block;
+
+// Don't indent the close parenthesis of a function definition,
+// if the parenthesis is on its own line.
+extern Option<bool>
+donot_indent_func_def_close_paren;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Newline adding and removing options
+
+// Whether to collapse empty blocks between '{' and '}'.
+// If true, overrides nl_inside_empty_func
+extern Option<bool>
+nl_collapse_empty_body;
+
+// Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'.
+extern Option<bool>
+nl_assign_leave_one_liners;
+
+// Don't split one-line braced statements inside a 'class xx { }' body.
+extern Option<bool>
+nl_class_leave_one_liners;
+
+// Don't split one-line enums, as in 'enum foo { BAR = 15 };'
+extern Option<bool>
+nl_enum_leave_one_liners;
+
+// Don't split one-line get or set functions.
+extern Option<bool>
+nl_getset_leave_one_liners;
+
+// (C#) Don't split one-line property get or set functions.
+extern Option<bool>
+nl_cs_property_leave_one_liners;
+
+// Don't split one-line function definitions, as in 'int foo() { return 0; }'.
+// might modify nl_func_type_name
+extern Option<bool>
+nl_func_leave_one_liners;
+
+// Don't split one-line C++11 lambdas, as in '[]() { return 0; }'.
+extern Option<bool>
+nl_cpp_lambda_leave_one_liners;
+
+// Don't split one-line if/else statements, as in 'if(...) b++;'.
+extern Option<bool>
+nl_if_leave_one_liners;
+
+// Don't split one-line while statements, as in 'while(...) b++;'.
+extern Option<bool>
+nl_while_leave_one_liners;
+
+// Don't split one-line do statements, as in 'do { b++; } while(...);'.
+extern Option<bool>
+nl_do_leave_one_liners;
+
+// Don't split one-line for statements, as in 'for(...) b++;'.
+extern Option<bool>
+nl_for_leave_one_liners;
+
+// (OC) Don't split one-line Objective-C messages.
+extern Option<bool>
+nl_oc_msg_leave_one_liner;
+
+// (OC) Add or remove newline between method declaration and '{'.
+extern Option<iarf_e>
+nl_oc_mdef_brace;
+
+// (OC) Add or remove newline between Objective-C block signature and '{'.
+extern Option<iarf_e>
+nl_oc_block_brace;
+
+// (OC) Add or remove blank line before '@interface' statement.
+extern Option<iarf_e>
+nl_oc_before_interface;
+
+// (OC) Add or remove blank line before '@implementation' statement.
+extern Option<iarf_e>
+nl_oc_before_implementation;
+
+// (OC) Add or remove blank line before '@end' statement.
+extern Option<iarf_e>
+nl_oc_before_end;
+
+// (OC) Add or remove newline between '@interface' and '{'.
+extern Option<iarf_e>
+nl_oc_interface_brace;
+
+// (OC) Add or remove newline between '@implementation' and '{'.
+extern Option<iarf_e>
+nl_oc_implementation_brace;
+
+// Add or remove newlines at the start of the file.
+extern Option<iarf_e>
+nl_start_of_file;
+
+// The minimum number of newlines at the start of the file (only used if
+// nl_start_of_file is 'add' or 'force').
+extern BoundedOption<unsigned, 0, 16>
+nl_start_of_file_min;
+
+// Add or remove newline at the end of the file.
+extern Option<iarf_e>
+nl_end_of_file;
+
+// The minimum number of newlines at the end of the file (only used if
+// nl_end_of_file is 'add' or 'force').
+extern BoundedOption<unsigned, 0, 16>
+nl_end_of_file_min;
+
+// Add or remove newline between '=' and '{'.
+extern Option<iarf_e>
+nl_assign_brace;
+
+// (D) Add or remove newline between '=' and '['.
+extern Option<iarf_e>
+nl_assign_square;
+
+// Add or remove newline between '[]' and '{'.
+extern Option<iarf_e>
+nl_tsquare_brace;
+
+// (D) Add or remove newline after '= ['. Will also affect the newline before
+// the ']'.
+extern Option<iarf_e>
+nl_after_square_assign;
+
+// Add or remove newline between a function call's ')' and '{', as in
+// 'list_for_each(item, &list) { }'.
+extern Option<iarf_e>
+nl_fcall_brace;
+
+// Add or remove newline between 'enum' and '{'.
+extern Option<iarf_e>
+nl_enum_brace;
+
+// Add or remove newline between 'enum' and 'class'.
+extern Option<iarf_e>
+nl_enum_class;
+
+// Add or remove newline between 'enum class' and the identifier.
+extern Option<iarf_e>
+nl_enum_class_identifier;
+
+// Add or remove newline between 'enum class' type and ':'.
+extern Option<iarf_e>
+nl_enum_identifier_colon;
+
+// Add or remove newline between 'enum class identifier :' and type.
+extern Option<iarf_e>
+nl_enum_colon_type;
+
+// Add or remove newline between 'struct and '{'.
+extern Option<iarf_e>
+nl_struct_brace;
+
+// Add or remove newline between 'union' and '{'.
+extern Option<iarf_e>
+nl_union_brace;
+
+// Add or remove newline between 'if' and '{'.
+extern Option<iarf_e>
+nl_if_brace;
+
+// Add or remove newline between '}' and 'else'.
+extern Option<iarf_e>
+nl_brace_else;
+
+// Add or remove newline between 'else if' and '{'. If set to ignore,
+// nl_if_brace is used instead.
+extern Option<iarf_e>
+nl_elseif_brace;
+
+// Add or remove newline between 'else' and '{'.
+extern Option<iarf_e>
+nl_else_brace;
+
+// Add or remove newline between 'else' and 'if'.
+extern Option<iarf_e>
+nl_else_if;
+
+// Add or remove newline before '{' opening brace
+extern Option<iarf_e>
+nl_before_opening_brace_func_class_def;
+
+// Add or remove newline before 'if'/'else if' closing parenthesis.
+extern Option<iarf_e>
+nl_before_if_closing_paren;
+
+// Add or remove newline between '}' and 'finally'.
+extern Option<iarf_e>
+nl_brace_finally;
+
+// Add or remove newline between 'finally' and '{'.
+extern Option<iarf_e>
+nl_finally_brace;
+
+// Add or remove newline between 'try' and '{'.
+extern Option<iarf_e>
+nl_try_brace;
+
+// Add or remove newline between get/set and '{'.
+extern Option<iarf_e>
+nl_getset_brace;
+
+// Add or remove newline between 'for' and '{'.
+extern Option<iarf_e>
+nl_for_brace;
+
+// Add or remove newline before the '{' of a 'catch' statement, as in
+// 'catch (decl) <here> {'.
+extern Option<iarf_e>
+nl_catch_brace;
+
+// (OC) Add or remove newline before the '{' of a '@catch' statement, as in
+// '@catch (decl) <here> {'. If set to ignore, nl_catch_brace is used.
+extern Option<iarf_e>
+nl_oc_catch_brace;
+
+// Add or remove newline between '}' and 'catch'.
+extern Option<iarf_e>
+nl_brace_catch;
+
+// (OC) Add or remove newline between '}' and '@catch'. If set to ignore,
+// nl_brace_catch is used.
+extern Option<iarf_e>
+nl_oc_brace_catch;
+
+// Add or remove newline between '}' and ']'.
+extern Option<iarf_e>
+nl_brace_square;
+
+// Add or remove newline between '}' and ')' in a function invocation.
+extern Option<iarf_e>
+nl_brace_fparen;
+
+// Add or remove newline between 'while' and '{'.
+extern Option<iarf_e>
+nl_while_brace;
+
+// (D) Add or remove newline between 'scope (x)' and '{'.
+extern Option<iarf_e>
+nl_scope_brace;
+
+// (D) Add or remove newline between 'unittest' and '{'.
+extern Option<iarf_e>
+nl_unittest_brace;
+
+// (D) Add or remove newline between 'version (x)' and '{'.
+extern Option<iarf_e>
+nl_version_brace;
+
+// (C#) Add or remove newline between 'using' and '{'.
+extern Option<iarf_e>
+nl_using_brace;
+
+// Add or remove newline between two open or close braces. Due to general
+// newline/brace handling, REMOVE may not work.
+extern Option<iarf_e>
+nl_brace_brace;
+
+// Add or remove newline between 'do' and '{'.
+extern Option<iarf_e>
+nl_do_brace;
+
+// Add or remove newline between '}' and 'while' of 'do' statement.
+extern Option<iarf_e>
+nl_brace_while;
+
+// Add or remove newline between 'switch' and '{'.
+extern Option<iarf_e>
+nl_switch_brace;
+
+// Add or remove newline between 'synchronized' and '{'.
+extern Option<iarf_e>
+nl_synchronized_brace;
+
+// Add a newline between ')' and '{' if the ')' is on a different line than the
+// if/for/etc.
+//
+// Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and
+// nl_catch_brace.
+extern Option<bool>
+nl_multi_line_cond;
+
+// Add a newline after '(' if an if/for/while/switch condition spans multiple
+// lines
+extern Option<iarf_e>
+nl_multi_line_sparen_open;
+
+// Add a newline before ')' if an if/for/while/switch condition spans multiple
+// lines. Overrides nl_before_if_closing_paren if both are specified.
+extern Option<iarf_e>
+nl_multi_line_sparen_close;
+
+// Force a newline in a define after the macro name for multi-line defines.
+extern Option<bool>
+nl_multi_line_define;
+
+// Whether to add a newline before 'case', and a blank line before a 'case'
+// statement that follows a ';' or '}'.
+extern Option<bool>
+nl_before_case;
+
+// Whether to add a newline after a 'case' statement.
+extern Option<bool>
+nl_after_case;
+
+// Add or remove newline between a case ':' and '{'.
+//
+// Overrides nl_after_case.
+extern Option<iarf_e>
+nl_case_colon_brace;
+
+// Add or remove newline between ')' and 'throw'.
+extern Option<iarf_e>
+nl_before_throw;
+
+// Add or remove newline between 'namespace' and '{'.
+extern Option<iarf_e>
+nl_namespace_brace;
+
+// Add or remove newline after 'template<...>' of a template class.
+extern Option<iarf_e>
+nl_template_class;
+
+// Add or remove newline after 'template<...>' of a template class declaration.
+//
+// Overrides nl_template_class.
+extern Option<iarf_e>
+nl_template_class_decl;
+
+// Add or remove newline after 'template<>' of a specialized class declaration.
+//
+// Overrides nl_template_class_decl.
+extern Option<iarf_e>
+nl_template_class_decl_special;
+
+// Add or remove newline after 'template<...>' of a template class definition.
+//
+// Overrides nl_template_class.
+extern Option<iarf_e>
+nl_template_class_def;
+
+// Add or remove newline after 'template<>' of a specialized class definition.
+//
+// Overrides nl_template_class_def.
+extern Option<iarf_e>
+nl_template_class_def_special;
+
+// Add or remove newline after 'template<...>' of a template function.
+extern Option<iarf_e>
+nl_template_func;
+
+// Add or remove newline after 'template<...>' of a template function
+// declaration.
+//
+// Overrides nl_template_func.
+extern Option<iarf_e>
+nl_template_func_decl;
+
+// Add or remove newline after 'template<>' of a specialized function
+// declaration.
+//
+// Overrides nl_template_func_decl.
+extern Option<iarf_e>
+nl_template_func_decl_special;
+
+// Add or remove newline after 'template<...>' of a template function
+// definition.
+//
+// Overrides nl_template_func.
+extern Option<iarf_e>
+nl_template_func_def;
+
+// Add or remove newline after 'template<>' of a specialized function
+// definition.
+//
+// Overrides nl_template_func_def.
+extern Option<iarf_e>
+nl_template_func_def_special;
+
+// Add or remove newline after 'template<...>' of a template variable.
+extern Option<iarf_e>
+nl_template_var;
+
+// Add or remove newline between 'template<...>' and 'using' of a templated
+// type alias.
+extern Option<iarf_e>
+nl_template_using;
+
+// Add or remove newline between 'class' and '{'.
+extern Option<iarf_e>
+nl_class_brace;
+
+// Add or remove newline before or after (depending on pos_class_comma,
+// may not be IGNORE) each',' in the base class list.
+extern Option<iarf_e>
+nl_class_init_args;
+
+// Add or remove newline after each ',' in the constructor member
+// initialization. Related to nl_constr_colon, pos_constr_colon and
+// pos_constr_comma.
+extern Option<iarf_e>
+nl_constr_init_args;
+
+// Add or remove newline before first element, after comma, and after last
+// element, in 'enum'.
+extern Option<iarf_e>
+nl_enum_own_lines;
+
+// Add or remove newline between return type and function name in a function
+// definition.
+// might be modified by nl_func_leave_one_liners
+extern Option<iarf_e>
+nl_func_type_name;
+
+// Add or remove newline between return type and function name inside a class
+// definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name
+// is used instead.
+extern Option<iarf_e>
+nl_func_type_name_class;
+
+// Add or remove newline between class specification and '::'
+// in 'void A::f() { }'. Only appears in separate member implementation (does
+// not appear with in-line implementation).
+extern Option<iarf_e>
+nl_func_class_scope;
+
+// Add or remove newline between function scope and name, as in
+// 'void A :: <here> f() { }'.
+extern Option<iarf_e>
+nl_func_scope_name;
+
+// Add or remove newline between return type and function name in a prototype.
+extern Option<iarf_e>
+nl_func_proto_type_name;
+
+// Add or remove newline between a function name and the opening '(' in the
+// declaration.
+extern Option<iarf_e>
+nl_func_paren;
+
+// Overrides nl_func_paren for functions with no parameters.
+extern Option<iarf_e>
+nl_func_paren_empty;
+
+// Add or remove newline between a function name and the opening '(' in the
+// definition.
+extern Option<iarf_e>
+nl_func_def_paren;
+
+// Overrides nl_func_def_paren for functions with no parameters.
+extern Option<iarf_e>
+nl_func_def_paren_empty;
+
+// Add or remove newline between a function name and the opening '(' in the
+// call.
+extern Option<iarf_e>
+nl_func_call_paren;
+
+// Overrides nl_func_call_paren for functions with no parameters.
+extern Option<iarf_e>
+nl_func_call_paren_empty;
+
+// Add or remove newline after '(' in a function declaration.
+extern Option<iarf_e>
+nl_func_decl_start;
+
+// Add or remove newline after '(' in a function definition.
+extern Option<iarf_e>
+nl_func_def_start;
+
+// Overrides nl_func_decl_start when there is only one parameter.
+extern Option<iarf_e>
+nl_func_decl_start_single;
+
+// Overrides nl_func_def_start when there is only one parameter.
+extern Option<iarf_e>
+nl_func_def_start_single;
+
+// Whether to add a newline after '(' in a function declaration if '(' and ')'
+// are in different lines. If false, nl_func_decl_start is used instead.
+extern Option<bool>
+nl_func_decl_start_multi_line;
+
+// Whether to add a newline after '(' in a function definition if '(' and ')'
+// are in different lines. If false, nl_func_def_start is used instead.
+extern Option<bool>
+nl_func_def_start_multi_line;
+
+// Add or remove newline after each ',' in a function declaration.
+extern Option<iarf_e>
+nl_func_decl_args;
+
+// Add or remove newline after each ',' in a function definition.
+extern Option<iarf_e>
+nl_func_def_args;
+
+// Add or remove newline after each ',' in a function call.
+extern Option<iarf_e>
+nl_func_call_args;
+
+// Whether to add a newline after each ',' in a function declaration if '('
+// and ')' are in different lines. If false, nl_func_decl_args is used instead.
+extern Option<bool>
+nl_func_decl_args_multi_line;
+
+// Whether to add a newline after each ',' in a function definition if '('
+// and ')' are in different lines. If false, nl_func_def_args is used instead.
+extern Option<bool>
+nl_func_def_args_multi_line;
+
+// Add or remove newline before the ')' in a function declaration.
+extern Option<iarf_e>
+nl_func_decl_end;
+
+// Add or remove newline before the ')' in a function definition.
+extern Option<iarf_e>
+nl_func_def_end;
+
+// Overrides nl_func_decl_end when there is only one parameter.
+extern Option<iarf_e>
+nl_func_decl_end_single;
+
+// Overrides nl_func_def_end when there is only one parameter.
+extern Option<iarf_e>
+nl_func_def_end_single;
+
+// Whether to add a newline before ')' in a function declaration if '(' and ')'
+// are in different lines. If false, nl_func_decl_end is used instead.
+extern Option<bool>
+nl_func_decl_end_multi_line;
+
+// Whether to add a newline before ')' in a function definition if '(' and ')'
+// are in different lines. If false, nl_func_def_end is used instead.
+extern Option<bool>
+nl_func_def_end_multi_line;
+
+// Add or remove newline between '()' in a function declaration.
+extern Option<iarf_e>
+nl_func_decl_empty;
+
+// Add or remove newline between '()' in a function definition.
+extern Option<iarf_e>
+nl_func_def_empty;
+
+// Add or remove newline between '()' in a function call.
+extern Option<iarf_e>
+nl_func_call_empty;
+
+// Whether to add a newline after '(' in a function call,
+// has preference over nl_func_call_start_multi_line.
+extern Option<iarf_e>
+nl_func_call_start;
+
+// Whether to add a newline before ')' in a function call.
+extern Option<iarf_e>
+nl_func_call_end;
+
+// Whether to add a newline after '(' in a function call if '(' and ')' are in
+// different lines.
+extern Option<bool>
+nl_func_call_start_multi_line;
+
+// Whether to add a newline after each ',' in a function call if '(' and ')'
+// are in different lines.
+extern Option<bool>
+nl_func_call_args_multi_line;
+
+// Whether to add a newline before ')' in a function call if '(' and ')' are in
+// different lines.
+extern Option<bool>
+nl_func_call_end_multi_line;
+
+// Whether to respect nl_func_call_XXX option in case of closure args.
+extern Option<bool>
+nl_func_call_args_multi_line_ignore_closures; // false
+
+// Whether to add a newline after '<' of a template parameter list.
+extern Option<bool>
+nl_template_start;
+
+// Whether to add a newline after each ',' in a template parameter list.
+extern Option<bool>
+nl_template_args;
+
+// Whether to add a newline before '>' of a template parameter list.
+extern Option<bool>
+nl_template_end;
+
+// (OC) Whether to put each Objective-C message parameter on a separate line.
+// See nl_oc_msg_leave_one_liner.
+extern Option<bool>
+nl_oc_msg_args;
+
+// Add or remove newline between function signature and '{'.
+extern Option<iarf_e>
+nl_fdef_brace;
+
+// Add or remove newline between function signature and '{',
+// if signature ends with ')'. Overrides nl_fdef_brace.
+extern Option<iarf_e>
+nl_fdef_brace_cond;
+
+// Add or remove newline between C++11 lambda signature and '{'.
+extern Option<iarf_e>
+nl_cpp_ldef_brace;
+
+// Add or remove newline between 'return' and the return expression.
+extern Option<iarf_e>
+nl_return_expr;
+
+// Whether to add a newline after semicolons, except in 'for' statements.
+extern Option<bool>
+nl_after_semicolon;
+
+// (Java) Add or remove newline between the ')' and '{{' of the double brace
+// initializer.
+extern Option<iarf_e>
+nl_paren_dbrace_open;
+
+// Whether to add a newline after the type in an unnamed temporary
+// direct-list-initialization, better:
+// before a direct-list-initialization.
+extern Option<iarf_e>
+nl_type_brace_init_lst;
+
+// Whether to add a newline after the open brace in an unnamed temporary
+// direct-list-initialization.
+extern Option<iarf_e>
+nl_type_brace_init_lst_open;
+
+// Whether to add a newline before the close brace in an unnamed temporary
+// direct-list-initialization.
+extern Option<iarf_e>
+nl_type_brace_init_lst_close;
+
+// Whether to add a newline before '{'.
+extern Option<bool>
+nl_before_brace_open;
+
+// Whether to add a newline after '{'.
+extern Option<bool>
+nl_after_brace_open;
+
+// Whether to add a newline between the open brace and a trailing single-line
+// comment. Requires nl_after_brace_open=true.
+extern Option<bool>
+nl_after_brace_open_cmt;
+
+// Whether to add a newline after a virtual brace open with a non-empty body.
+// These occur in un-braced if/while/do/for statement bodies.
+extern Option<bool>
+nl_after_vbrace_open;
+
+// Whether to add a newline after a virtual brace open with an empty body.
+// These occur in un-braced if/while/do/for statement bodies.
+extern Option<bool>
+nl_after_vbrace_open_empty;
+
+// Whether to add a newline after '}'. Does not apply if followed by a
+// necessary ';'.
+extern Option<bool>
+nl_after_brace_close;
+
+// Whether to add a newline after a virtual brace close,
+// as in 'if (foo) a++; <here> return;'.
+extern Option<bool>
+nl_after_vbrace_close;
+
+// Add or remove newline between the close brace and identifier,
+// as in 'struct { int a; } <here> b;'. Affects enumerations, unions and
+// structures. If set to ignore, uses nl_after_brace_close.
+extern Option<iarf_e>
+nl_brace_struct_var;
+
+// Whether to alter newlines in '#define' macros.
+extern Option<bool>
+nl_define_macro;
+
+// Whether to alter newlines between consecutive parenthesis closes. The number
+// of closing parentheses in a line will depend on respective open parenthesis
+// lines.
+extern Option<bool>
+nl_squeeze_paren_close;
+
+// Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and
+// '#endif'. Does not affect top-level #ifdefs.
+extern Option<bool>
+nl_squeeze_ifdef;
+
+// Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well.
+extern Option<bool>
+nl_squeeze_ifdef_top_level;
+
+// Add or remove blank line before 'if'.
+extern Option<iarf_e>
+nl_before_if;
+
+// Add or remove blank line after 'if' statement. Add/Force work only if the
+// next token is not a closing brace.
+extern Option<iarf_e>
+nl_after_if;
+
+// Add or remove blank line before 'for'.
+extern Option<iarf_e>
+nl_before_for;
+
+// Add or remove blank line after 'for' statement.
+extern Option<iarf_e>
+nl_after_for;
+
+// Add or remove blank line before 'while'.
+extern Option<iarf_e>
+nl_before_while;
+
+// Add or remove blank line after 'while' statement.
+extern Option<iarf_e>
+nl_after_while;
+
+// Add or remove blank line before 'switch'.
+extern Option<iarf_e>
+nl_before_switch;
+
+// Add or remove blank line after 'switch' statement.
+extern Option<iarf_e>
+nl_after_switch;
+
+// Add or remove blank line before 'synchronized'.
+extern Option<iarf_e>
+nl_before_synchronized;
+
+// Add or remove blank line after 'synchronized' statement.
+extern Option<iarf_e>
+nl_after_synchronized;
+
+// Add or remove blank line before 'do'.
+extern Option<iarf_e>
+nl_before_do;
+
+// Add or remove blank line after 'do/while' statement.
+extern Option<iarf_e>
+nl_after_do;
+
+// Ignore nl_before_{if,for,switch,do,synchronized} if the control
+// statement is immediately after a case statement.
+// if nl_before_{if,for,switch,do} is set to remove, this option
+// does nothing.
+extern Option<bool>
+nl_before_ignore_after_case;
+
+// Whether to put a blank line before 'return' statements, unless after an open
+// brace.
+extern Option<bool>
+nl_before_return;
+
+// Whether to put a blank line after 'return' statements, unless followed by a
+// close brace.
+extern Option<bool>
+nl_after_return;
+
+// Whether to put a blank line before a member '.' or '->' operators.
+extern Option<iarf_e>
+nl_before_member;
+
+// (Java) Whether to put a blank line after a member '.' or '->' operators.
+extern Option<iarf_e>
+nl_after_member;
+
+// Whether to double-space commented-entries in 'struct'/'union'/'enum'.
+extern Option<bool>
+nl_ds_struct_enum_cmt;
+
+// Whether to force a newline before '}' of a 'struct'/'union'/'enum'.
+// (Lower priority than eat_blanks_before_close_brace.)
+extern Option<bool>
+nl_ds_struct_enum_close_brace;
+
+// Add or remove newline before or after (depending on pos_class_colon) a class
+// colon, as in 'class Foo <here> : <or here> public Bar'.
+extern Option<iarf_e>
+nl_class_colon;
+
+// Add or remove newline around a class constructor colon. The exact position
+// depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma.
+extern Option<iarf_e>
+nl_constr_colon;
+
+// Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }'
+// into a single line. If true, prevents other brace newline rules from turning
+// such code into four lines. If true, it also preserves one-liner namespaces.
+extern Option<bool>
+nl_namespace_two_to_one_liner;
+
+// Whether to remove a newline in simple unbraced if statements, turning them
+// into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'.
+extern Option<bool>
+nl_create_if_one_liner;
+
+// Whether to remove a newline in simple unbraced for statements, turning them
+// into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'.
+extern Option<bool>
+nl_create_for_one_liner;
+
+// Whether to remove a newline in simple unbraced while statements, turning
+// them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'.
+extern Option<bool>
+nl_create_while_one_liner;
+
+// Whether to collapse a function definition whose body (not counting braces)
+// is only one line so that the entire definition (prototype, braces, body) is
+// a single line.
+extern Option<bool>
+nl_create_func_def_one_liner;
+
+// Whether to split one-line simple list definitions into three lines by
+// adding newlines, as in 'int a[12] = { <here> 0 <here> };'.
+extern Option<bool>
+nl_create_list_one_liner;
+
+// Whether to split one-line simple unbraced if statements into two lines by
+// adding a newline, as in 'if(b) <here> i++;'.
+extern Option<bool>
+nl_split_if_one_liner;
+
+// Whether to split one-line simple unbraced for statements into two lines by
+// adding a newline, as in 'for (...) <here> stmt;'.
+extern Option<bool>
+nl_split_for_one_liner;
+
+// Whether to split one-line simple unbraced while statements into two lines by
+// adding a newline, as in 'while (expr) <here> stmt;'.
+extern Option<bool>
+nl_split_while_one_liner;
+
+// Don't add a newline before a cpp-comment in a parameter list of a function
+// call.
+extern Option<bool>
+donot_add_nl_before_cpp_comment;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Blank line options
+
+// The maximum number of consecutive newlines (3 = 2 blank lines).
+extern BoundedOption<unsigned, 0, 16>
+nl_max;
+
+// The maximum number of consecutive newlines in a function.
+extern BoundedOption<unsigned, 0, 16>
+nl_max_blank_in_func;
+
+// The number of newlines inside an empty function body.
+// This option overrides eat_blanks_after_open_brace and
+// eat_blanks_before_close_brace, but is ignored when
+// nl_collapse_empty_body=true
+extern BoundedOption<unsigned, 0, 16>
+nl_inside_empty_func;
+
+// The number of newlines before a function prototype.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_func_body_proto;
+
+// The number of newlines before a multi-line function definition. Where
+// applicable, this option is overridden with eat_blanks_after_open_brace=true
+extern BoundedOption<unsigned, 0, 16>
+nl_before_func_body_def;
+
+// The number of newlines before a class constructor/destructor prototype.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_func_class_proto;
+
+// The number of newlines before a class constructor/destructor definition.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_func_class_def;
+
+// The number of newlines after a function prototype.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_proto;
+
+// The number of newlines after a function prototype, if not followed by
+// another function prototype.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_proto_group;
+
+// The number of newlines after a class constructor/destructor prototype.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_class_proto;
+
+// The number of newlines after a class constructor/destructor prototype,
+// if not followed by another constructor/destructor prototype.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_class_proto_group;
+
+// Whether one-line method definitions inside a class body should be treated
+// as if they were prototypes for the purposes of adding newlines.
+//
+// Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def
+// and nl_before_func_class_def for one-liners.
+extern Option<bool>
+nl_class_leave_one_liner_groups;
+
+// The number of newlines after '}' of a multi-line function body.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_body;
+
+// The number of newlines after '}' of a multi-line function body in a class
+// declaration. Also affects class constructors/destructors.
+//
+// Overrides nl_after_func_body.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_body_class;
+
+// The number of newlines after '}' of a single line function body. Also
+// affects class constructors/destructors.
+//
+// Overrides nl_after_func_body and nl_after_func_body_class.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_body_one_liner;
+
+// The number of blank lines after a block of variable definitions at the top
+// of a function body.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_func_var_def_blk;
+
+// The number of newlines before a block of typedefs. If nl_after_access_spec
+// is non-zero, that option takes precedence.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_typedef_blk_start;
+
+// The number of newlines after a block of typedefs.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_typedef_blk_end;
+
+// The maximum number of consecutive newlines within a block of typedefs.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_typedef_blk_in;
+
+// The number of empty newlines before a block of variable definitions
+// not at the top of a function body. If nl_after_access_spec is non-zero,
+// that option takes precedence.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_var_def_blk_start;
+
+// The number of empty newlines after a block of variable definitions
+// not at the top of a function body.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_var_def_blk_end;
+
+// The maximum number of consecutive newlines within a block of variable
+// definitions.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_var_def_blk_in;
+
+// The minimum number of newlines before a multi-line comment.
+// Doesn't apply if after a brace open or another multi-line comment.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_block_comment;
+
+// The minimum number of newlines before a single-line C comment.
+// Doesn't apply if after a brace open or other single-line C comments.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_c_comment;
+
+// The minimum number of newlines before a CPP comment.
+// Doesn't apply if after a brace open or other CPP comments.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_cpp_comment;
+
+// Whether to force a newline after a multi-line comment.
+extern Option<bool>
+nl_after_multiline_comment;
+
+// Whether to force a newline after a label's colon.
+extern Option<bool>
+nl_after_label_colon;
+
+// The number of newlines before a struct definition.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_struct;
+
+// The number of newlines after '}' or ';' of a struct/enum/union definition.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_struct;
+
+// The number of newlines before a class definition.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_class;
+
+// The number of newlines after '}' or ';' of a class definition.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_class;
+
+// The number of newlines before a namespace.
+extern BoundedOption<unsigned, 0, 16>
+nl_before_namespace;
+
+// The number of newlines after '{' of a namespace. This also adds newlines
+// before the matching '}'.
+//
+// 0: Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if
+// applicable, otherwise no change.
+//
+// Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace.
+extern BoundedOption<unsigned, 0, 16>
+nl_inside_namespace;
+
+// The number of newlines after '}' of a namespace.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_namespace;
+
+// The number of newlines before an access specifier label. This also includes
+// the Qt-specific 'signals:' and 'slots:'. Will not change the newline count
+// if after a brace open.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_before_access_spec;
+
+// The number of newlines after an access specifier label. This also includes
+// the Qt-specific 'signals:' and 'slots:'. Will not change the newline count
+// if after a brace open.
+//
+// 0: No change (default).
+//
+// Overrides nl_typedef_blk_start and nl_var_def_blk_start.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_access_spec;
+
+// The number of newlines between a function definition and the function
+// comment, as in '// comment\n <here> void foo() {...}'.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_comment_func_def;
+
+// The number of newlines after a try-catch-finally block that isn't followed
+// by a brace close.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_after_try_catch_finally;
+
+// (C#) The number of newlines before and after a property, indexer or event
+// declaration.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_around_cs_property;
+
+// (C#) The number of newlines between the get/set/add/remove handlers.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_between_get_set;
+
+// (C#) Add or remove newline between property and the '{'.
+extern Option<iarf_e>
+nl_property_brace;
+
+// Whether to remove blank lines after '{'.
+extern Option<bool>
+eat_blanks_after_open_brace;
+
+// Whether to remove blank lines before '}'.
+extern Option<bool>
+eat_blanks_before_close_brace;
+
+// How aggressively to remove extra newlines not in preprocessor.
+//
+// 0: No change (default)
+// 1: Remove most newlines not handled by other config
+// 2: Remove all newlines and reformat completely by config
+extern BoundedOption<unsigned, 0, 2>
+nl_remove_extra_newlines;
+
+// (Java) Add or remove newline after an annotation statement. Only affects
+// annotations that are after a newline.
+extern Option<iarf_e>
+nl_after_annotation;
+
+// (Java) Add or remove newline between two annotations.
+extern Option<iarf_e>
+nl_between_annotation;
+
+// The number of newlines before a whole-file #ifdef.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_before_whole_file_ifdef;
+
+// The number of newlines after a whole-file #ifdef.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_after_whole_file_ifdef;
+
+// The number of newlines before a whole-file #endif.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_before_whole_file_endif;
+
+// The number of newlines after a whole-file #endif.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_after_whole_file_endif;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Positioning options
+
+// The position of arithmetic operators in wrapped expressions.
+extern Option<token_pos_e>
+pos_arith;
+
+// The position of assignment in wrapped expressions. Do not affect '='
+// followed by '{'.
+extern Option<token_pos_e>
+pos_assign;
+
+// The position of Boolean operators in wrapped expressions.
+extern Option<token_pos_e>
+pos_bool;
+
+// The position of comparison operators in wrapped expressions.
+extern Option<token_pos_e>
+pos_compare;
+
+// The position of conditional operators, as in the '?' and ':' of
+// 'expr ? stmt : stmt', in wrapped expressions.
+extern Option<token_pos_e>
+pos_conditional;
+
+// The position of the comma in wrapped expressions.
+extern Option<token_pos_e>
+pos_comma;
+
+// The position of the comma in enum entries.
+extern Option<token_pos_e>
+pos_enum_comma;
+
+// The position of the comma in the base class list if there is more than one
+// line. Affects nl_class_init_args.
+extern Option<token_pos_e>
+pos_class_comma;
+
+// The position of the comma in the constructor initialization list.
+// Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon.
+extern Option<token_pos_e>
+pos_constr_comma;
+
+// The position of trailing/leading class colon, between class and base class
+// list. Affects nl_class_colon.
+extern Option<token_pos_e>
+pos_class_colon;
+
+// The position of colons between constructor and member initialization.
+// Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma.
+extern Option<token_pos_e>
+pos_constr_colon;
+
+// The position of shift operators in wrapped expressions.
+extern Option<token_pos_e>
+pos_shift;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Line splitting options
+
+// Try to limit code width to N columns.
+extern BoundedOption<unsigned, 0, 10000>
+code_width;
+
+// Whether to fully split long 'for' statements at semi-colons.
+extern Option<bool>
+ls_for_split_full;
+
+// Whether to fully split long function prototypes/calls at commas.
+// The option ls_code_width has priority over the option ls_func_split_full.
+extern Option<bool>
+ls_func_split_full;
+
+// Whether to split lines as close to code_width as possible and ignore some
+// groupings.
+// The option ls_code_width has priority over the option ls_func_split_full.
+extern Option<bool>
+ls_code_width;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Code alignment options (not left column spaces/tabs)
+
+// Whether to keep non-indenting tabs.
+extern Option<bool>
+align_keep_tabs;
+
+// Whether to use tabs for aligning.
+extern Option<bool>
+align_with_tabs;
+
+// Whether to bump out to the next tab when aligning.
+extern Option<bool>
+align_on_tabstop;
+
+// Whether to right-align numbers.
+extern Option<bool>
+align_number_right;
+
+// Whether to keep whitespace not required for alignment.
+extern Option<bool>
+align_keep_extra_space;
+
+// Whether to align variable definitions in prototypes and functions.
+extern Option<bool>
+align_func_params;
+
+// The span for aligning parameter definitions in function on parameter name.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 16>
+align_func_params_span;
+
+// The threshold for aligning function parameter definitions.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_func_params_thresh;
+
+// The gap for aligning function parameter definitions.
+extern BoundedOption<unsigned, 0, 16>
+align_func_params_gap;
+
+// The span for aligning constructor value.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 16>
+align_constr_value_span;
+
+// The threshold for aligning constructor value.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_constr_value_thresh;
+
+// The gap for aligning constructor value.
+extern BoundedOption<unsigned, 0, 16>
+align_constr_value_gap;
+
+// Whether to align parameters in single-line functions that have the same
+// name. The function names must already be aligned with each other.
+extern Option<bool>
+align_same_func_call_params;
+
+// The span for aligning function-call parameters for single line functions.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_same_func_call_params_span;
+
+// The threshold for aligning function-call parameters for single line
+// functions.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_same_func_call_params_thresh;
+
+// The span for aligning variable definitions.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_var_def_span;
+
+// How to consider (or treat) the '*' in the alignment of variable definitions.
+//
+// 0: Part of the type 'void * foo;' (default)
+// 1: Part of the variable 'void *foo;'
+// 2: Dangling 'void *foo;'
+// Dangling: the '*' will not be taken into account when aligning.
+extern BoundedOption<unsigned, 0, 2>
+align_var_def_star_style;
+
+// How to consider (or treat) the '&' in the alignment of variable definitions.
+//
+// 0: Part of the type 'long & foo;' (default)
+// 1: Part of the variable 'long &foo;'
+// 2: Dangling 'long &foo;'
+// Dangling: the '&' will not be taken into account when aligning.
+extern BoundedOption<unsigned, 0, 2>
+align_var_def_amp_style;
+
+// The threshold for aligning variable definitions.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_var_def_thresh;
+
+// The gap for aligning variable definitions.
+extern BoundedOption<unsigned, 0, 16>
+align_var_def_gap;
+
+// Whether to align the colon in struct bit fields.
+extern Option<bool>
+align_var_def_colon;
+
+// The gap for aligning the colon in struct bit fields.
+extern BoundedOption<unsigned, 0, 16>
+align_var_def_colon_gap;
+
+// Whether to align any attribute after the variable name.
+extern Option<bool>
+align_var_def_attribute;
+
+// Whether to align inline struct/enum/union variable definitions.
+extern Option<bool>
+align_var_def_inline;
+
+// The span for aligning on '=' in assignments.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_assign_span;
+
+// The span for aligning on '{' in braced init list.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_braced_init_list_span;
+
+// The span for aligning on '=' in function prototype modifier.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_assign_func_proto_span;
+
+// The threshold for aligning on '=' in assignments.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_assign_thresh;
+
+// Whether to align on the left most assignment when multiple
+// definitions are found on the same line.
+// Depends on 'align_assign_span' and 'align_assign_thresh' settings.
+extern Option<bool>
+align_assign_on_multi_var_defs;
+
+// The threshold for aligning on '{' in braced init list.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_braced_init_list_thresh;
+
+// How to apply align_assign_span to function declaration "assignments", i.e.
+// 'virtual void foo() = 0' or '~foo() = {default|delete}'.
+//
+// 0: Align with other assignments (default)
+// 1: Align with each other, ignoring regular assignments
+// 2: Don't align
+extern BoundedOption<unsigned, 0, 2>
+align_assign_decl_func;
+
+// The span for aligning on '=' in enums.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_enum_equ_span;
+
+// The threshold for aligning on '=' in enums.
+// Use a negative number for absolute thresholds.
+//
+// 0: no limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_enum_equ_thresh;
+
+// The span for aligning class member definitions.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_var_class_span;
+
+// The threshold for aligning class member definitions.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_var_class_thresh;
+
+// The gap for aligning class member definitions.
+extern BoundedOption<unsigned, 0, 16>
+align_var_class_gap;
+
+// The span for aligning struct/union member definitions.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_var_struct_span;
+
+// The threshold for aligning struct/union member definitions.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_var_struct_thresh;
+
+// The gap for aligning struct/union member definitions.
+extern BoundedOption<unsigned, 0, 16>
+align_var_struct_gap;
+
+// The span for aligning struct initializer values.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_struct_init_span;
+
+// The span for aligning single-line typedefs.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 16>
+align_typedef_span;
+
+// The minimum space between the type and the synonym of a typedef.
+extern BoundedOption<unsigned, 0, 16>
+align_typedef_gap;
+
+// How to align typedef'd functions with other typedefs.
+//
+// 0: Don't mix them at all (default)
+// 1: Align the open parenthesis with the types
+// 2: Align the function type name with the other type names
+extern BoundedOption<unsigned, 0, 2>
+align_typedef_func;
+
+// How to consider (or treat) the '*' in the alignment of typedefs.
+//
+// 0: Part of the typedef type, 'typedef int * pint;' (default)
+// 1: Part of type name: 'typedef int *pint;'
+// 2: Dangling: 'typedef int *pint;'
+// Dangling: the '*' will not be taken into account when aligning.
+extern BoundedOption<unsigned, 0, 2>
+align_typedef_star_style;
+
+// How to consider (or treat) the '&' in the alignment of typedefs.
+//
+// 0: Part of the typedef type, 'typedef int & intref;' (default)
+// 1: Part of type name: 'typedef int &intref;'
+// 2: Dangling: 'typedef int &intref;'
+// Dangling: the '&' will not be taken into account when aligning.
+extern BoundedOption<unsigned, 0, 2>
+align_typedef_amp_style;
+
+// The span for aligning comments that end lines.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_right_cmt_span;
+
+// Minimum number of columns between preceding text and a trailing comment in
+// order for the comment to qualify for being aligned. Must be non-zero to have
+// an effect.
+extern BoundedOption<unsigned, 0, 16>
+align_right_cmt_gap;
+
+// If aligning comments, whether to mix with comments after '}' and #endif with
+// less than three spaces before the comment.
+extern Option<bool>
+align_right_cmt_mix;
+
+// Whether to only align trailing comments that are at the same brace level.
+extern Option<bool>
+align_right_cmt_same_level;
+
+// Minimum column at which to align trailing comments. Comments which are
+// aligned beyond this column, but which can be aligned in a lesser column,
+// may be "pulled in".
+//
+// 0: Ignore (default).
+extern BoundedOption<unsigned, 0, 200>
+align_right_cmt_at_col;
+
+// The span for aligning function prototypes.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_func_proto_span;
+
+// How to consider (or treat) the '*' in the alignment of function prototypes.
+//
+// 0: Part of the type 'void * foo();' (default)
+// 1: Part of the function 'void *foo();'
+// 2: Dangling 'void *foo();'
+// Dangling: the '*' will not be taken into account when aligning.
+extern BoundedOption<unsigned, 0, 2>
+align_func_proto_star_style;
+
+// How to consider (or treat) the '&' in the alignment of function prototypes.
+//
+// 0: Part of the type 'long & foo();' (default)
+// 1: Part of the function 'long &foo();'
+// 2: Dangling 'long &foo();'
+// Dangling: the '&' will not be taken into account when aligning.
+extern BoundedOption<unsigned, 0, 2>
+align_func_proto_amp_style;
+
+// The threshold for aligning function prototypes.
+// Use a negative number for absolute thresholds.
+//
+// 0: No limit (default).
+extern BoundedOption<signed, -1000, 5000>
+align_func_proto_thresh;
+
+// Minimum gap between the return type and the function name.
+extern BoundedOption<unsigned, 0, 16>
+align_func_proto_gap;
+
+// Whether to align function prototypes on the 'operator' keyword instead of
+// what follows.
+extern Option<bool>
+align_on_operator;
+
+// Whether to mix aligning prototype and variable declarations. If true,
+// align_var_def_XXX options are used instead of align_func_proto_XXX options.
+extern Option<bool>
+align_mix_var_proto;
+
+// Whether to align single-line functions with function prototypes.
+// Uses align_func_proto_span.
+extern Option<bool>
+align_single_line_func;
+
+// Whether to align the open brace of single-line functions.
+// Requires align_single_line_func=true. Uses align_func_proto_span.
+extern Option<bool>
+align_single_line_brace;
+
+// Gap for align_single_line_brace.
+extern BoundedOption<unsigned, 0, 16>
+align_single_line_brace_gap;
+
+// (OC) The span for aligning Objective-C message specifications.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_oc_msg_spec_span;
+
+// Whether to align macros wrapped with a backslash and a newline. This will
+// not work right if the macro contains a multi-line comment.
+extern Option<bool>
+align_nl_cont;
+
+// Whether to align macro functions and variables together.
+extern Option<bool>
+align_pp_define_together;
+
+// The span for aligning on '#define' bodies.
+//
+// =0: Don't align (default)
+// >0: Number of lines (including comments) between blocks
+extern BoundedOption<unsigned, 0, 5000>
+align_pp_define_span;
+
+// The minimum space between label and value of a preprocessor define.
+extern BoundedOption<unsigned, 0, 16>
+align_pp_define_gap;
+
+// Whether to align lines that start with '<<' with previous '<<'.
+extern Option<bool>
+align_left_shift; // = true
+
+// Whether to align comma-separated statements following '<<' (as used to
+// initialize Eigen matrices).
+extern Option<bool>
+align_eigen_comma_init;
+
+// Whether to align text after 'asm volatile ()' colons.
+extern Option<bool>
+align_asm_colon;
+
+// (OC) Span for aligning parameters in an Objective-C message call
+// on the ':'.
+//
+// 0: Don't align.
+extern BoundedOption<unsigned, 0, 5000>
+align_oc_msg_colon_span;
+
+// (OC) Whether to always align with the first parameter, even if it is too
+// short.
+extern Option<bool>
+align_oc_msg_colon_first;
+
+// (OC) Whether to align parameters in an Objective-C '+' or '-' declaration
+// on the ':'.
+extern Option<bool>
+align_oc_decl_colon;
+
+// (OC) Whether to not align parameters in an Objectve-C message call if first
+// colon is not on next line of the message call (the same way Xcode does
+// alignment)
+extern Option<bool>
+align_oc_msg_colon_xcode_like;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Comment modification options
+
+// Try to wrap comments at N columns.
+extern BoundedOption<unsigned, 0, 256>
+cmt_width;
+
+// How to reflow comments.
+//
+// 0: No reflowing (apart from the line wrapping due to cmt_width) (default)
+// 1: No touching at all
+// 2: Full reflow (enable cmt_indent_multi for indent with line wrapping due to cmt_width)
+extern BoundedOption<unsigned, 0, 2>
+cmt_reflow_mode;
+
+// Path to a file that contains regular expressions describing patterns for
+// which the end of one line and the beginning of the next will be folded into
+// the same sentence or paragraph during full comment reflow. The regular
+// expressions are described using ECMAScript syntax. The syntax for this
+// specification is as follows, where "..." indicates the custom regular
+// expression and "n" indicates the nth end_of_prev_line_regex and
+// beg_of_next_line_regex regular expression pair:
+//
+// end_of_prev_line_regex[1] = "...$"
+// beg_of_next_line_regex[1] = "^..."
+// end_of_prev_line_regex[2] = "...$"
+// beg_of_next_line_regex[2] = "^..."
+// .
+// .
+// .
+// end_of_prev_line_regex[n] = "...$"
+// beg_of_next_line_regex[n] = "^..."
+//
+// Note that use of this option overrides the default reflow fold regular
+// expressions, which are internally defined as follows:
+//
+// end_of_prev_line_regex[1] = "[\w,\]\)]$"
+// beg_of_next_line_regex[1] = "^[\w,\[\(]"
+// end_of_prev_line_regex[2] = "\.$"
+// beg_of_next_line_regex[2] = "^[A-Z]"
+extern Option<string>
+cmt_reflow_fold_regex_file;
+
+// Whether to indent wrapped lines to the start of the encompassing paragraph
+// during full comment reflow (cmt_reflow_mode = 2). Overrides the value
+// specified by cmt_sp_after_star_cont.
+//
+// Note that cmt_align_doxygen_javadoc_tags overrides this option for
+// paragraphs associated with javadoc tags
+extern Option<bool>
+cmt_reflow_indent_to_paragraph_start;
+
+// Whether to convert all tabs to spaces in comments. If false, tabs in
+// comments are left alone, unless used for indenting.
+extern Option<bool>
+cmt_convert_tab_to_spaces;
+
+// TODO This description is confusing and should be revised.
+
+// Whether to apply changes to multi-line comments, including cmt_width,
+// keyword substitution and leading chars.
+extern Option<bool>
+cmt_indent_multi; // = true
+
+// Whether to align doxygen javadoc-style tags ('@param', '@return', etc.)
+// and corresponding fields such that groups of consecutive block tags,
+// parameter names, and descriptions align with one another. Overrides that
+// which is specified by the cmt_sp_after_star_cont. If cmt_width > 0, it may
+// be necessary to enable cmt_indent_multi and set cmt_reflow_mode = 2
+// in order to achieve the desired alignment for line-wrapping.
+extern Option<bool>
+cmt_align_doxygen_javadoc_tags;
+
+// The number of spaces to insert after the star and before doxygen
+// javadoc-style tags (@param, @return, etc). Requires enabling
+// cmt_align_doxygen_javadoc_tags. Overrides that which is specified by the
+// cmt_sp_after_star_cont.
+extern BoundedOption<unsigned, 0, 16>
+cmt_sp_before_doxygen_javadoc_tags; // = 1
+
+// Whether to change trailing, single-line c-comments into cpp-comments.
+extern Option<bool>
+cmt_trailing_single_line_c_to_cpp;
+
+// Whether to group c-comments that look like they are in a block.
+extern Option<bool>
+cmt_c_group;
+
+// Whether to put an empty '/*' on the first line of the combined c-comment.
+extern Option<bool>
+cmt_c_nl_start;
+
+// Whether to add a newline before the closing '*/' of the combined c-comment.
+extern Option<bool>
+cmt_c_nl_end;
+
+// Whether to change cpp-comments into c-comments.
+extern Option<bool>
+cmt_cpp_to_c;
+
+// Whether to group cpp-comments that look like they are in a block. Only
+// meaningful if cmt_cpp_to_c=true.
+extern Option<bool>
+cmt_cpp_group;
+
+// Whether to put an empty '/*' on the first line of the combined cpp-comment
+// when converting to a c-comment.
+//
+// Requires cmt_cpp_to_c=true and cmt_cpp_group=true.
+extern Option<bool>
+cmt_cpp_nl_start;
+
+// Whether to add a newline before the closing '*/' of the combined cpp-comment
+// when converting to a c-comment.
+//
+// Requires cmt_cpp_to_c=true and cmt_cpp_group=true.
+extern Option<bool>
+cmt_cpp_nl_end;
+
+// Whether to put a star on subsequent comment lines.
+extern Option<bool>
+cmt_star_cont;
+
+// The number of spaces to insert at the start of subsequent comment lines.
+extern BoundedOption<unsigned, 0, 16>
+cmt_sp_before_star_cont;
+
+// The number of spaces to insert after the star on subsequent comment lines.
+extern BoundedOption<unsigned, 0, 16>
+cmt_sp_after_star_cont;
+
+// TODO This description is confusing and should be revised.
+
+// For multi-line comments with a '*' lead, remove leading spaces if the first
+// and last lines of the comment are the same length.
+extern Option<bool>
+cmt_multi_check_last; // = true
+
+// TODO This description is confusing and should be revised.
+
+// For multi-line comments with a '*' lead, remove leading spaces if the first
+// and last lines of the comment are the same length AND if the length is
+// bigger as the first_len minimum.
+extern BoundedOption<unsigned, 1, 20>
+cmt_multi_first_len_minimum; // = 4
+
+// Path to a file that contains text to insert at the beginning of a file if
+// the file doesn't start with a C/C++ comment. If the inserted text contains
+// '$(filename)', that will be replaced with the current file's name.
+extern Option<string>
+cmt_insert_file_header;
+
+// Path to a file that contains text to insert at the end of a file if the
+// file doesn't end with a C/C++ comment. If the inserted text contains
+// '$(filename)', that will be replaced with the current file's name.
+extern Option<string>
+cmt_insert_file_footer;
+
+// Path to a file that contains text to insert before a function definition if
+// the function isn't preceded by a C/C++ comment. If the inserted text
+// contains '$(function)', '$(javaparam)' or '$(fclass)', these will be
+// replaced with, respectively, the name of the function, the javadoc '@param'
+// and '@return' stuff, or the name of the class to which the member function
+// belongs.
+extern Option<string>
+cmt_insert_func_header;
+
+// Path to a file that contains text to insert before a class if the class
+// isn't preceded by a C/C++ comment. If the inserted text contains '$(class)',
+// that will be replaced with the class name.
+extern Option<string>
+cmt_insert_class_header;
+
+// Path to a file that contains text to insert before an Objective-C message
+// specification, if the method isn't preceded by a C/C++ comment. If the
+// inserted text contains '$(message)' or '$(javaparam)', these will be
+// replaced with, respectively, the name of the function, or the javadoc
+// '@param' and '@return' stuff.
+extern Option<string>
+cmt_insert_oc_msg_header;
+
+// TODO This description may be confusing; consider revising.
+
+// Whether a comment should be inserted if a preprocessor is encountered when
+// stepping backwards from a function name.
+//
+// Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and
+// cmt_insert_class_header.
+extern Option<bool>
+cmt_insert_before_preproc;
+
+// Whether a comment should be inserted if a function is declared inline to a
+// class definition.
+//
+// Applies to cmt_insert_func_header.
+extern Option<bool>
+cmt_insert_before_inlines; // = true
+
+// Whether a comment should be inserted if the function is a class constructor
+// or destructor.
+//
+// Applies to cmt_insert_func_header.
+extern Option<bool>
+cmt_insert_before_ctor_dtor;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Code modifying options (non-whitespace)
+
+// Add or remove braces on a single-line 'do' statement.
+extern Option<iarf_e>
+mod_full_brace_do;
+
+// Add or remove braces on a single-line 'for' statement.
+extern Option<iarf_e>
+mod_full_brace_for;
+
+// (Pawn) Add or remove braces on a single-line function definition.
+extern Option<iarf_e>
+mod_full_brace_function;
+
+// Add or remove braces on a single-line 'if' statement. Braces will not be
+// removed if the braced statement contains an 'else'.
+extern Option<iarf_e>
+mod_full_brace_if;
+
+// Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either
+// have, or do not have, braces. Overrides mod_full_brace_if.
+//
+// 0: Don't override mod_full_brace_if
+// 1: Add braces to all blocks if any block needs braces and remove braces if
+// they can be removed from all blocks
+// 2: Add braces to all blocks if any block already has braces, regardless of
+// whether it needs them
+// 3: Add braces to all blocks if any block needs braces and remove braces if
+// they can be removed from all blocks, except if all blocks have braces
+// despite none needing them
+extern BoundedOption<unsigned, 0, 3>
+mod_full_brace_if_chain;
+
+// Whether to add braces to all blocks of an 'if'/'else if'/'else' chain.
+// If true, mod_full_brace_if_chain will only remove braces from an 'if' that
+// does not have an 'else if' or 'else'.
+extern Option<bool>
+mod_full_brace_if_chain_only;
+
+// Add or remove braces on single-line 'while' statement.
+extern Option<iarf_e>
+mod_full_brace_while;
+
+// Add or remove braces on single-line 'using ()' statement.
+extern Option<iarf_e>
+mod_full_brace_using;
+
+// Don't remove braces around statements that span N newlines
+extern BoundedOption<unsigned, 0, 5000>
+mod_full_brace_nl;
+
+// Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks
+// which span multiple lines.
+//
+// Affects:
+// mod_full_brace_for
+// mod_full_brace_if
+// mod_full_brace_if_chain
+// mod_full_brace_if_chain_only
+// mod_full_brace_while
+// mod_full_brace_using
+//
+// Does not affect:
+// mod_full_brace_do
+// mod_full_brace_function
+extern Option<bool>
+mod_full_brace_nl_block_rem_mlcond;
+
+// Add or remove unnecessary parenthesis on 'return' statement.
+extern Option<iarf_e>
+mod_paren_on_return;
+
+// (Pawn) Whether to change optional semicolons to real semicolons.
+extern Option<bool>
+mod_pawn_semicolon;
+
+// Whether to fully parenthesize Boolean expressions in 'while' and 'if'
+// statement, as in 'if (a && b > c)' => 'if (a && (b > c))'.
+extern Option<bool>
+mod_full_paren_if_bool;
+
+// Whether to fully parenthesize Boolean expressions after '='
+// statement, as in 'x = a && b > c;' => 'x = (a && (b > c));'.
+extern Option<bool>
+mod_full_paren_assign_bool;
+
+// Whether to fully parenthesize Boolean expressions after '='
+// statement, as in 'return a && b > c;' => 'return (a && (b > c));'.
+extern Option<bool>
+mod_full_paren_return_bool;
+
+// Whether to remove superfluous semicolons.
+extern Option<bool>
+mod_remove_extra_semicolon;
+
+// Whether to remove duplicate include.
+extern Option<bool>
+mod_remove_duplicate_include;
+
+// If a function body exceeds the specified number of newlines and doesn't have
+// a comment after the close brace, a comment will be added.
+extern BoundedOption<unsigned, 0, 255>
+mod_add_long_function_closebrace_comment;
+
+// If a namespace body exceeds the specified number of newlines and doesn't
+// have a comment after the close brace, a comment will be added.
+extern BoundedOption<unsigned, 0, 255>
+mod_add_long_namespace_closebrace_comment;
+
+// If a class body exceeds the specified number of newlines and doesn't have a
+// comment after the close brace, a comment will be added.
+extern BoundedOption<unsigned, 0, 255>
+mod_add_long_class_closebrace_comment;
+
+// If a switch body exceeds the specified number of newlines and doesn't have a
+// comment after the close brace, a comment will be added.
+extern BoundedOption<unsigned, 0, 255>
+mod_add_long_switch_closebrace_comment;
+
+// If an #ifdef body exceeds the specified number of newlines and doesn't have
+// a comment after the #endif, a comment will be added.
+extern BoundedOption<unsigned, 0, 255>
+mod_add_long_ifdef_endif_comment;
+
+// If an #ifdef or #else body exceeds the specified number of newlines and
+// doesn't have a comment after the #else, a comment will be added.
+extern BoundedOption<unsigned, 0, 255>
+mod_add_long_ifdef_else_comment;
+
+// Whether to take care of the case by the mod_sort_xx options.
+extern Option<bool>
+mod_sort_case_sensitive;
+
+// Whether to sort consecutive single-line 'import' statements.
+extern Option<bool>
+mod_sort_import;
+
+// (C#) Whether to sort consecutive single-line 'using' statements.
+extern Option<bool>
+mod_sort_using;
+
+// Whether to sort consecutive single-line '#include' statements (C/C++) and
+// '#import' statements (Objective-C). Be aware that this has the potential to
+// break your code if your includes/imports have ordering dependencies.
+extern Option<bool>
+mod_sort_include;
+
+// Whether to prioritize '#include' and '#import' statements that contain
+// filename without extension when sorting is enabled.
+extern Option<bool>
+mod_sort_incl_import_prioritize_filename;
+
+// Whether to prioritize '#include' and '#import' statements that does not
+// contain extensions when sorting is enabled.
+extern Option<bool>
+mod_sort_incl_import_prioritize_extensionless;
+
+// Whether to prioritize '#include' and '#import' statements that contain
+// angle over quotes when sorting is enabled.
+extern Option<bool>
+mod_sort_incl_import_prioritize_angle_over_quotes;
+
+// Whether to ignore file extension in '#include' and '#import' statements
+// for sorting comparison.
+extern Option<bool>
+mod_sort_incl_import_ignore_extension;
+
+// Whether to group '#include' and '#import' statements when sorting is enabled.
+extern Option<bool>
+mod_sort_incl_import_grouping_enabled;
+
+// Whether to move a 'break' that appears after a fully braced 'case' before
+// the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'.
+extern Option<bool>
+mod_move_case_break;
+
+// Whether to move a 'return' that appears after a fully braced 'case' before
+// the close brace, as in 'case X: { ... } return;' => 'case X: { ... return; }'.
+extern Option<bool>
+mod_move_case_return;
+
+// Add or remove braces around a fully braced case statement. Will only remove
+// braces if there are no variable declarations in the block.
+extern Option<iarf_e>
+mod_case_brace;
+
+// Whether to remove a void 'return;' that appears as the last statement in a
+// function.
+extern Option<bool>
+mod_remove_empty_return;
+
+// Add or remove the comma after the last value of an enumeration.
+extern Option<iarf_e>
+mod_enum_last_comma;
+
+// (OC) Whether to organize the properties. If true, properties will be
+// rearranged according to the mod_sort_oc_property_*_weight factors.
+extern Option<bool>
+mod_sort_oc_properties;
+
+// (OC) Weight of a class property modifier.
+extern Option<signed>
+mod_sort_oc_property_class_weight;
+
+// (OC) Weight of 'atomic' and 'nonatomic'.
+extern Option<signed>
+mod_sort_oc_property_thread_safe_weight;
+
+// (OC) Weight of 'readwrite' when organizing properties.
+extern Option<signed>
+mod_sort_oc_property_readwrite_weight;
+
+// (OC) Weight of a reference type specifier ('retain', 'copy', 'assign',
+// 'weak', 'strong') when organizing properties.
+extern Option<signed>
+mod_sort_oc_property_reference_weight;
+
+// (OC) Weight of getter type ('getter=') when organizing properties.
+extern Option<signed>
+mod_sort_oc_property_getter_weight;
+
+// (OC) Weight of setter type ('setter=') when organizing properties.
+extern Option<signed>
+mod_sort_oc_property_setter_weight;
+
+// (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified',
+// 'null_resettable') when organizing properties.
+extern Option<signed>
+mod_sort_oc_property_nullability_weight;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Preprocessor options
+
+// Add or remove indentation of preprocessor directives inside #if blocks
+// at brace level 0 (file-level).
+extern Option<iarf_e>
+pp_indent;
+
+// Whether to indent #if/#else/#endif at the brace level. If false, these are
+// indented from column 1.
+extern Option<bool>
+pp_indent_at_level;
+
+// Whether to indent #if/#else/#endif at the parenthesis level if the brace
+// level is 0. If false, these are indented from column 1.
+extern Option<bool>
+pp_indent_at_level0;
+
+// Specifies the number of columns to indent preprocessors per level
+// at brace level 0 (file-level). If pp_indent_at_level=false, also specifies
+// the number of columns to indent preprocessors per level
+// at brace level > 0 (function-level).
+extern BoundedOption<unsigned, 0, 16>
+pp_indent_count; // = 1
+
+// Add or remove space after # based on pp_level of #if blocks.
+extern Option<iarf_e>
+pp_space;
+
+// Sets the number of spaces per level added with pp_space.
+extern BoundedOption<unsigned, 0, 16>
+pp_space_count;
+
+// The indent for '#region' and '#endregion' in C# and '#pragma region' in
+// C/C++. Negative values decrease indent down to the first column.
+extern BoundedOption<signed, -16, 16>
+pp_indent_region;
+
+// Whether to indent the code between #region and #endregion.
+extern Option<bool>
+pp_region_indent_code;
+
+// If pp_indent_at_level=true, sets the indent for #if, #else and #endif when
+// not at file-level. Negative values decrease indent down to the first column.
+//
+// =0: Indent preprocessors using output_tab_size
+// >0: Column at which all preprocessors will be indented
+extern BoundedOption<signed, -16, 16>
+pp_indent_if;
+
+// Whether to indent the code between #if, #else and #endif.
+extern Option<bool>
+pp_if_indent_code;
+
+// Whether to indent the body of an #if that encompasses all the code in the file.
+extern Option<bool>
+pp_indent_in_guard;
+
+// Whether to indent '#define' at the brace level. If false, these are
+// indented from column 1.
+extern Option<bool>
+pp_define_at_level;
+
+// Whether to indent '#include' at the brace level.
+extern Option<bool>
+pp_include_at_level;
+
+// Whether to ignore the '#define' body while formatting.
+extern Option<bool>
+pp_ignore_define_body;
+
+// TODO The following descriptions are confusing and suffer from sub-optimal
+// grammar, and should be revised; from here...
+
+// Whether to indent case statements between #if, #else, and #endif.
+// Only applies to the indent of the preprocesser that the case statements
+// directly inside of.
+extern Option<bool>
+pp_indent_case; // = true
+
+// Whether to indent whole function definitions between #if, #else, and #endif.
+// Only applies to the indent of the preprocesser that the function definition
+// is directly inside of.
+extern Option<bool>
+pp_indent_func_def; // = true
+
+// Whether to indent extern C blocks between #if, #else, and #endif.
+// Only applies to the indent of the preprocesser that the extern block is
+// directly inside of.
+extern Option<bool>
+pp_indent_extern; // = true
+
+// How to indent braces directly inside #if, #else, and #endif.
+// Requires pp_if_indent_code=true and only applies to the indent of the
+// preprocesser that the braces are directly inside of.
+// 0: No extra indent
+// 1: Indent by one level
+// -1: Preserve original indentation
+extern BoundedOption<signed, -1, 1>
+pp_indent_brace; // = 1
+
+// Whether to print warning messages for unbalanced #if and #else blocks.
+// This will print a message in the following cases:
+// - if an #ifdef block ends on a different indent level than
+// where it started from. Example:
+//
+// #ifdef TEST
+// int i;
+// {
+// int j;
+// #endif
+//
+// - an #elif/#else block ends on a different indent level than
+// the corresponding #ifdef block. Example:
+//
+// #ifdef TEST
+// int i;
+// #else
+// }
+// int j;
+// #endif
+extern Option<bool>
+pp_warn_unbalanced_if; // = false
+
+// TODO ...until here.
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Sort includes options
+
+// The regex for include category with priority 0.
+extern Option<string>
+include_category_0;
+
+// The regex for include category with priority 1.
+extern Option<string>
+include_category_1;
+
+// The regex for include category with priority 2.
+extern Option<string>
+include_category_2;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Use or Do not Use options
+
+// true: indent_func_call_param will be used (default)
+// false: indent_func_call_param will NOT be used
+extern Option<bool>
+use_indent_func_call_param; // = true
+
+// The value of the indentation for a continuation line is calculated
+// differently if the statement is:
+// - a declaration: your case with QString fileName ...
+// - an assignment: your case with pSettings = new QSettings( ...
+//
+// At the second case the indentation value might be used twice:
+// - at the assignment
+// - at the function call (if present)
+//
+// To prevent the double use of the indentation value, use this option with the
+// value 'true'.
+//
+// true: indent_continue will be used only once
+// false: indent_continue will be used every time (default)
+//
+// Requires indent_ignore_first_continue=false.
+extern Option<bool>
+use_indent_continue_only_once;
+
+// The indentation can be:
+// - after the assignment, at the '[' character
+// - at the begin of the lambda body
+//
+// true: indentation will be after the assignment
+// false: indentation will be at the begin of the lambda body (default)
+extern Option<bool>
+indent_cpp_lambda_only_once;
+
+// Whether sp_after_angle takes precedence over sp_inside_fparen. This was the
+// historic behavior, but is probably not the desired behavior, so this is off
+// by default.
+extern Option<bool>
+use_sp_after_angle_always;
+
+// Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially,
+// this tries to format these so that they match Qt's normalized form (i.e. the
+// result of QMetaObject::normalizedSignature), which can slightly improve the
+// performance of the QObject::connect call, rather than how they would
+// otherwise be formatted.
+//
+// See options_for_QT.cpp for details.
+extern Option<bool>
+use_options_overriding_for_qt_macros; // = true
+
+// If true: the form feed character is removed from the list of whitespace
+// characters. See https://en.cppreference.com/w/cpp/string/byte/isspace.
+extern Option<bool>
+use_form_feed_no_more_as_whitespace_character;
+
+//END
+
+///////////////////////////////////////////////////////////////////////////////
+//BEGIN Warn levels - 1: error, 2: warning (default), 3: note
+
+// (C#) Warning is given if doing tab-to-\t replacement and we have found one
+// in a C# verbatim string literal.
+extern BoundedOption<unsigned, 1, 3>
+warn_level_tabs_found_in_verbatim_string_literals; // = LWARN
+
+// For debugging purpose only.
+
+// Limit the number of loops.
+// Used by uncrustify.cpp to exit from infinite loop.
+// 0: no limit.
+extern Option<signed>
+debug_max_number_of_loops;
+
+// Set the number of the line to protocol;
+// Used in the function prot_the_line if the 2. parameter is zero.
+// 0: nothing protocol.
+extern Option<signed>
+debug_line_number_to_protocol;
+
+// Set the number of second(s) before terminating formatting the current file,
+// 0: no timeout.
+// only for linux
+extern Option<signed>
+debug_timeout;
+
+// Set the number of characters to be printed if the text is too long,
+// 0: do not truncate.
+extern BoundedOption<unsigned, 0, 960>
+debug_truncate;
+
+//END
+
+} // namespace options
+
+} // namespace uncrustify
+
+#endif /* OPTIONS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.cpp
new file mode 100644
index 00000000..f4a1d040
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.cpp
@@ -0,0 +1,126 @@
+/**
+ * @file options_for_QT.cpp
+ * Save the options which are needed to be changed to
+ * process the SIGNAL and SLOT QT macros.
+ * http://doc.qt.io/qt-4.8/qtglobal.html
+ *
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * October 2015, 2016
+ * @license GPL v2+
+ */
+
+#include "options_for_QT.h"
+
+#include "log_rules.h"
+
+constexpr static auto LCURRENT = LQT;
+
+using namespace uncrustify;
+
+// for the modification of options within the SIGNAL/SLOT call.
+bool QT_SIGNAL_SLOT_found = false;
+size_t QT_SIGNAL_SLOT_level = 0;
+bool restoreValues = false;
+
+namespace
+{
+
+//-----------------------------------------------------------------------------
+class temporary_iarf_option
+{
+public:
+ temporary_iarf_option(Option<iarf_e> *option,
+ iarf_e override_value = IARF_REMOVE)
+ : m_option{option}
+ , m_override_value{override_value}
+ {}
+
+ void save_and_override();
+ void restore();
+
+private:
+ Option<iarf_e> *m_option;
+ const iarf_e m_override_value;
+
+ iarf_e m_saved_value = IARF_NOT_DEFINED;
+};
+
+
+//-----------------------------------------------------------------------------
+void temporary_iarf_option::save_and_override()
+{
+ m_saved_value = (*m_option)();
+ (*m_option) = m_override_value;
+}
+
+
+//-----------------------------------------------------------------------------
+void temporary_iarf_option::restore()
+{
+ (*m_option) = m_saved_value;
+ m_saved_value = IARF_NOT_DEFINED;
+}
+
+//-----------------------------------------------------------------------------
+temporary_iarf_option for_qt_options[] =
+{
+ { &options::sp_inside_fparen },
+// Issue #481
+// connect( timer,SIGNAL( timeout() ),this,SLOT( timeoutImage() ) );
+ { &options::sp_inside_fparens },
+ { &options::sp_paren_paren },
+ { &options::sp_before_comma },
+ { &options::sp_after_comma },
+// Bug #654
+// connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &)));
+ { &options::sp_before_byref },
+ { &options::sp_before_unnamed_byref },
+ { &options::sp_after_type },
+// Issue #1969
+// connect( a, SIGNAL(b(c *)), this, SLOT(d(e *)) );
+ { &options::sp_before_ptr_star },
+ { &options::sp_before_unnamed_ptr_star },
+// connect( a, SIGNAL(b(c< d >)), this, SLOT(e(f< g >)) );
+ { &options::sp_inside_angle },
+};
+
+} // anonymous namespace
+
+
+//-----------------------------------------------------------------------------
+void save_set_options_for_QT(size_t level)
+{
+ log_rule_B("use_options_overriding_for_qt_macros");
+ assert(options::use_options_overriding_for_qt_macros());
+
+ LOG_FMT(LGUY, "save values, level=%zu\n", level);
+ // save the values
+ QT_SIGNAL_SLOT_level = level;
+
+ for (auto &opt : for_qt_options)
+ {
+ opt.save_and_override();
+ }
+
+ QT_SIGNAL_SLOT_found = true;
+}
+
+
+//-----------------------------------------------------------------------------
+void restore_options_for_QT(void)
+{
+ log_rule_B("use_options_overriding_for_qt_macros");
+ assert(options::use_options_overriding_for_qt_macros());
+
+ LOG_FMT(LGUY, "restore values\n");
+ // restore the values we had before SIGNAL/SLOT
+ QT_SIGNAL_SLOT_level = 0;
+
+ for (auto &opt : for_qt_options)
+ {
+ opt.restore();
+ }
+
+ QT_SIGNAL_SLOT_found = false;
+ restoreValues = false;
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.h
new file mode 100644
index 00000000..c114eb75
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/options_for_QT.h
@@ -0,0 +1,29 @@
+/**
+ * @file options_for_QT.h
+ * Save the options which are needed to be changed to
+ * process the SIGNAL and SLOT QT macros.
+ * http://doc.qt.io/qt-4.8/qtglobal.html
+ *
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * January 2016
+ * @license GPL v2+
+ */
+
+#ifndef OPTIONS_FOR_QT_H_INCLUDED
+#define OPTIONS_FOR_QT_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+// TODO can we avoid those extern variables?
+extern bool QT_SIGNAL_SLOT_found;
+extern size_t QT_SIGNAL_SLOT_level;
+extern bool restoreValues;
+
+
+void save_set_options_for_QT(size_t level);
+
+
+void restore_options_for_QT(void);
+
+
+#endif /* OPTIONS_FOR_QT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.cpp
new file mode 100644
index 00000000..57d4f0bd
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.cpp
@@ -0,0 +1,3422 @@
+/**
+ * @file output.cpp
+ * Does all the output & comment formatting.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel October 2015, 2021
+ * @license GPL v2+
+ */
+
+#include "output.h"
+
+#include "align_tab_column.h"
+#include "braces.h"
+#include "indent.h"
+#include "prototypes.h"
+#include "tokenize.h"
+#include "unc_ctype.h"
+#include "unicode.h"
+
+#include <ctime>
+#include <map>
+#include <regex>
+#include <set>
+
+
+constexpr static auto LCURRENT = LOUTPUT;
+
+using namespace uncrustify;
+
+
+struct cmt_reflow
+{
+ Chunk *pc = nullptr;
+ size_t column = 0; //! Column of the comment start
+ size_t brace_col = 0; //! Brace column (for indenting with tabs)
+ size_t base_col = 0; //! Base column (for indenting with tabs)
+ size_t word_count = 0; //! number of words on this line
+ size_t xtra_indent = 0; //! extra indent of non-first lines (0 or 1)
+ unc_text cont_text; //! fixed text to output at the start of a line (0 to 3 chars)
+ bool reflow = false; //! reflow the current line
+};
+
+
+/**
+ * A multiline comment
+ * The only trick here is that we have to trim out whitespace characters
+ * to get the comment to line up.
+ */
+static void output_comment_multi(Chunk *pc);
+
+
+static bool kw_fcn_filename(Chunk *cmt, unc_text &out_txt);
+
+
+static bool kw_fcn_class(Chunk *cmt, unc_text &out_txt);
+
+
+static bool kw_fcn_message(Chunk *cmt, unc_text &out_txt);
+
+
+static bool kw_fcn_category(Chunk *cmt, unc_text &out_txt);
+
+
+static bool kw_fcn_scope(Chunk *cmt, unc_text &out_txt);
+
+
+static bool kw_fcn_function(Chunk *cmt, unc_text &out_txt);
+
+
+/**
+ * Adds the javadoc-style @param and @return stuff, based on the params and
+ * return value for pc.
+ * If the arg list is '()' or '(void)', then no @params are added.
+ * Likewise, if the return value is 'void', then no @return is added.
+ */
+static bool kw_fcn_javaparam(Chunk *cmt, unc_text &out_txt);
+
+
+static bool kw_fcn_fclass(Chunk *cmt, unc_text &out_txt);
+
+
+static bool kw_fcn_year(Chunk *cmt, unc_text &out_txt);
+
+
+/**
+ * Output a multiline comment without any reformatting other than shifting
+ * it left or right to get the column right.
+ *
+ * Trims trailing whitespaces.
+ */
+static void output_comment_multi_simple(Chunk *pc);
+
+
+/**
+ * This renders the #if condition to a string buffer.
+ *
+ * @param[out] dst unc_text buffer to be filled
+ * @param[in] ifdef if conditional as chunk list
+ */
+static void generate_if_conditional_as_text(unc_text &dst, Chunk *ifdef);
+
+
+/**
+ * Do keyword substitution on a comment.
+ * NOTE: it is assumed that a comment will contain at most one of each type
+ * of keyword.
+ */
+static void do_kw_subst(Chunk *pc);
+
+
+//! All output text is sent here, one char at a time.
+static void add_char(UINT32 ch, bool is_literal = false);
+
+
+static void add_text(const char *ascii_text);
+
+
+static void add_text(const unc_text &text, bool is_ignored, bool is_literal);
+
+
+/**
+ * Count the number of characters to the end of the next chunk of text.
+ * If it exceeds the limit, return true.
+ */
+static bool next_word_exceeds_limit(const unc_text &text, size_t idx);
+
+
+/**
+ * Output a comment to the column using indent_with_tabs and
+ * indent_cmt_with_tabs as the rules.
+ * base_col is the indent of the first line of the comment.
+ * On the first line, column == base_col.
+ * On subsequent lines, column >= base_col.
+ *
+ * @param brace_col the brace-level indent of the comment
+ * @param base_col the indent of the start of the comment (multiline)
+ * @param column the column that we should end up in
+ */
+static void cmt_output_indent(size_t brace_col, size_t base_col, size_t column);
+
+
+/**
+ * Checks for and updates the lead chars.
+ *
+ * @param line the comment line
+ *
+ * @return 0: not present, >0: number of chars that are part of the lead
+ */
+static size_t cmt_parse_lead(const unc_text &line, bool is_last);
+
+
+/**
+ * Scans a multiline comment to determine the following:
+ * - the extra indent of the non-first line (0 or 1)
+ * - the continuation text ('' or '* ')
+ *
+ * The decision is based on:
+ * - cmt_indent_multi
+ * - cmt_star_cont
+ * - cmt_multi_first_len_minimum
+ * - the first line length
+ * - the second line leader length
+ * - the last line length (without leading space/tab)
+ *
+ * If the first and last line are the same length and don't contain any alnum
+ * chars and (the first line len > 2 or the second leader is the same as the
+ * first line length), then the indent is 0.
+ *
+ * If the leader on the second line is 1 wide or missing, then the indent is 1.
+ *
+ * Otherwise, the indent is 0.
+ *
+ * @param str The comment string
+ * @param len Length of the comment
+ * @param start_col Starting column
+ *
+ * @return cmt.xtra_indent is set to 0 or 1
+ */
+static void calculate_comment_body_indent(cmt_reflow &cmt, const unc_text &str);
+
+
+static int next_up(const unc_text &text, size_t idx, const unc_text &tag);
+
+
+/**
+ * Outputs the C comment at pc.
+ * C comment combining is done here
+ *
+ * @return the last chunk output'd
+ */
+static Chunk *output_comment_c(Chunk *pc);
+
+
+/**
+ * Outputs the CPP comment at pc.
+ * CPP comment combining is done here
+ *
+ * @return the last chunk output'd
+ */
+static Chunk *output_comment_cpp(Chunk *pc);
+
+
+static void cmt_trim_whitespace(unc_text &line, bool in_preproc);
+
+
+/**
+ * Outputs a comment. The initial opening '//' may be included in the text.
+ * Subsequent openings (if combining comments), should not be included.
+ * The closing (for C/D comments) should not be included.
+ *
+ * TODO:
+ * If reflowing text, the comment should be added one word (or line) at a time.
+ * A newline should only be sent if a blank line is encountered or if the next
+ * line is indented beyond the current line (optional?).
+ * If the last char on a line is a ':' or '.', then the next line won't be
+ * combined.
+ */
+static void add_comment_text(const unc_text &text, cmt_reflow &cmt, bool esc_close, size_t continuation_indent = 0);
+
+
+static void output_cmt_start(cmt_reflow &cmt, Chunk *pc);
+
+
+/**
+ * Checks to see if the current comment can be combined with the next comment.
+ * The two can be combined if:
+ * 1. They are the same type
+ * 2. There is exactly one newline between then
+ * 3. They are indented to the same level
+ */
+static bool can_combine_comment(Chunk *pc, cmt_reflow &cmt);
+
+
+#define LOG_CONTTEXT() \
+ LOG_FMT(LCONTTEXT, "%s(%d): set cont_text to '%s'\n", __func__, __LINE__, cmt.cont_text.c_str())
+
+
+static void add_spaces()
+{
+ while (cpd.spaces > 0)
+ {
+ write_char(' ');
+ cpd.spaces--;
+ }
+}
+
+
+static void add_char(UINT32 ch, bool is_literal)
+{
+ // If we did a '\r' and it isn't followed by a '\n', then output a newline
+ if ( (cpd.last_char == '\r')
+ && (ch != '\n'))
+ {
+ write_string(cpd.newline);
+ cpd.column = 1;
+ cpd.did_newline = 1;
+ cpd.spaces = 0;
+ }
+
+ // convert a newline into the LF/CRLF/CR sequence
+ if (ch == '\n')
+ {
+ add_spaces();
+ write_string(cpd.newline);
+ cpd.column = 1;
+ cpd.did_newline = 1;
+ cpd.spaces = 0;
+ }
+ else if (ch == '\r') // do not output the CARRIAGERETURN
+ {
+ // do not output '\r'
+ cpd.column = 1;
+ cpd.did_newline = 1;
+ cpd.spaces = 0;
+ }
+ else if ( (ch == '\t')
+ && cpd.output_tab_as_space)
+ {
+ size_t endcol = next_tab_column(cpd.column);
+
+ while (cpd.column < endcol)
+ {
+ add_char(' ');
+ }
+ return;
+ }
+ else
+ {
+ // explicitly disallow a tab after a space
+ if ( !is_literal
+ && ch == '\t'
+ && cpd.last_char == ' ')
+ {
+ log_rule_B("indent_with_tabs");
+
+ if (options::indent_with_tabs() == 0)
+ {
+ size_t endcol = next_tab_column(cpd.column);
+
+ while (cpd.column < endcol)
+ {
+ add_char(' ');
+ }
+ return;
+ }
+ }
+
+ if ( (ch == ' ')
+ && !cpd.output_trailspace)
+ {
+ cpd.spaces++;
+ cpd.column++;
+ }
+ else
+ {
+ add_spaces();
+ write_char(ch);
+
+ if (ch == '\t')
+ {
+ cpd.column = next_tab_column(cpd.column);
+ }
+ else
+ {
+ cpd.column++;
+ }
+ }
+ }
+ cpd.last_char = ch;
+} // add_char
+
+
+static void add_text(const char *ascii_text)
+{
+ char ch;
+
+ while ((ch = *ascii_text) != 0)
+ {
+ ascii_text++;
+ add_char(ch);
+ }
+}
+
+
+static void add_text(const unc_text &text, bool is_ignored = false, bool is_literal = false)
+{
+ for (size_t idx = 0; idx < text.size(); idx++)
+ {
+ int ch = text[idx];
+
+ if (is_ignored)
+ {
+ write_char(ch);
+ }
+ else
+ {
+ add_char(ch, is_literal);
+ }
+ }
+}
+
+
+static bool next_word_exceeds_limit(const unc_text &text, size_t idx)
+{
+ LOG_FMT(LCONTTEXT, "%s(%d): idx is %zu\n",
+ __func__, __LINE__, idx);
+ size_t length = 0;
+
+ // Count any whitespace
+ while ( (idx < text.size())
+ && unc_isspace(text[idx]))
+ {
+ idx++;
+ length++;
+ }
+
+ // Count non-whitespace
+ while ( (idx < text.size())
+ && !unc_isspace(text[idx]))
+ {
+ idx++;
+ length++;
+ }
+ return((cpd.column + length - 1) > options::cmt_width());
+}
+
+
+/**
+ * Advance to a specific column
+ * cpd.column is the current column
+ *
+ * @param column The column to advance to
+ */
+static void output_to_column(size_t column, bool allow_tabs)
+{
+ cpd.did_newline = 0;
+
+ if (allow_tabs)
+ {
+ // tab out as far as possible and then use spaces
+ size_t next_column = next_tab_column(cpd.column);
+
+ while (next_column <= column)
+ {
+ add_text("\t");
+ next_column = next_tab_column(cpd.column);
+ }
+ }
+
+ // space out the final bit
+ while (cpd.column < column)
+ {
+ add_text(" ");
+ }
+}
+
+
+static void cmt_output_indent(size_t brace_col, size_t base_col, size_t column)
+{
+ log_rule_B("indent_cmt_with_tabs");
+ log_rule_B("indent_with_tabs");
+ size_t iwt = options::indent_cmt_with_tabs() ? 2 :
+ (options::indent_with_tabs() ? 1 : 0);
+
+ size_t tab_col = (iwt == 0) ? 0 : ((iwt == 1) ? brace_col : base_col);
+
+ // LOG_FMT(LSYS, "%s(brace=%zd base=%zd col=%zd iwt=%zd) tab=%zd cur=%zd\n",
+ // __func__, brace_col, base_col, column, iwt, tab_col, cpd.column);
+
+ cpd.did_newline = 0;
+
+ if ( iwt == 2
+ || ( cpd.column == 1
+ && iwt == 1))
+ {
+ // tab out as far as possible and then use spaces
+ while (next_tab_column(cpd.column) <= tab_col)
+ {
+ add_text("\t");
+ }
+ }
+
+ // space out the rest
+ while (cpd.column < column)
+ {
+ add_text(" ");
+ }
+} // cmt_output_indent
+
+
+void output_parsed(FILE *pfile, bool withOptions)
+{
+ const char *eol_marker = get_eol_marker();
+
+ if (withOptions)
+ {
+ save_option_file(pfile, false, true);
+ }
+ fprintf(pfile, "# -=====-%s", eol_marker);
+ fprintf(pfile, "# number of loops = %d\n", cpd.changes);
+ fprintf(pfile, "# -=====-%s", eol_marker);
+ fprintf(pfile, "# language = %s\n", language_name_from_flags(cpd.lang_flags));
+ fprintf(pfile, "# -=====-%s", eol_marker);
+ // MAXLENGTHOFTHENAME must be consider at the format line at the file
+ // output.cpp, line 427: fprintf(pfile, "# Line Tag Parent...
+ // and 430: ... fprintf(pfile, "%s# %3zu>%19.19s[%19.19s] ...
+ // here xx xx xx xx
+#ifdef WIN32
+ fprintf(pfile, "# Line Tag Parent_type Type of the parent Columns Br/Lvl/pp Nl Text");
+#else // not WIN32
+ fprintf(pfile, "# Line Tag Parent_type Type of the parent Columns Br/Lvl/pp Flag Nl Text");
+#endif // ifdef WIN32
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+#ifdef WIN32
+ fprintf(pfile, "%s# %3d>%19.19s|%19.19s|%19.19s[%3d/%3d/%3d/%3d][%d/%d/%d][%d-%d]",
+ eol_marker, (int)pc->orig_line, get_token_name(pc->type),
+ get_token_name(get_chunk_parent_type(pc)), get_token_name(get_type_of_the_parent(pc)),
+ (int)pc->column, (int)pc->orig_col, (int)pc->orig_col_end, (int)pc->orig_prev_sp,
+ (int)pc->brace_level, (int)pc->level, (int)pc->pp_level, (int)pc->nl_count, pc->after_tab);
+#else // not WIN32
+ fprintf(pfile, "%s# %3zu>%19.19s|%19.19s|%19.19s[%3zu/%3zu/%3zu/%3d][%zu/%zu/%zu]",
+ eol_marker, pc->orig_line, get_token_name(pc->type),
+ get_token_name(get_chunk_parent_type(pc)), get_token_name(get_type_of_the_parent(pc)),
+ pc->column, pc->orig_col, pc->orig_col_end, pc->orig_prev_sp,
+ pc->brace_level, pc->level, pc->pp_level);
+ // Print pc flags in groups of 4 hex characters
+ char flag_string[20];
+ sprintf(flag_string, "%12llx", static_cast<pcf_flags_t::int_t>(pc->flags));
+ fprintf(pfile, "[%.4s %.4s %.4s]", flag_string, flag_string + 4, flag_string + 8);
+ fprintf(pfile, "[%zu-%d]",
+ pc->nl_count, pc->after_tab);
+#endif // ifdef WIN32
+
+ if ( pc->type != CT_NEWLINE
+ && (pc->Len() != 0))
+ {
+ for (size_t cnt = 0; cnt < pc->column; cnt++)
+ {
+ fprintf(pfile, " ");
+ }
+
+ if (pc->type != CT_NL_CONT)
+ {
+ fprintf(pfile, "%s", pc->Text());
+ }
+ else
+ {
+ fprintf(pfile, "\\");
+ }
+ }
+ }
+
+ fprintf(pfile, "%s# -=====-%s", eol_marker, eol_marker);
+ fflush(pfile);
+} // output_parsed
+
+
+void output_parsed_csv(FILE *pfile)
+{
+ const char *eol_marker = get_eol_marker();
+
+ fprintf(pfile, "number of loops,%d,\n", cpd.changes);
+ fprintf(pfile, "language,%s,\n", language_name_from_flags(cpd.lang_flags));
+ fprintf(pfile, "Line,Tag,Parent_type,Type of the parent,Column,Orig Col Strt,"
+ "Orig Col End,Orig Sp Before,Br,Lvl,pp,Flags,Nl Before,Nl After,Text,");
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ fprintf(pfile, "%s%zu,%s,%s,%s,%zu,%zu,%zu,%d,%zu,%zu,%zu,",
+ eol_marker, pc->orig_line, get_token_name(pc->type),
+ get_token_name(get_chunk_parent_type(pc)), get_token_name(get_type_of_the_parent(pc)),
+ pc->column, pc->orig_col, pc->orig_col_end, pc->orig_prev_sp,
+ pc->brace_level, pc->level, pc->pp_level);
+
+ auto pcf_flag_str = pcf_flags_str(pcf_flag_e(pc->flags));
+#ifdef WIN32
+ auto pcf_flag_str_start = pcf_flag_str.find("[") + 1;
+#else // not WIN32
+ auto pcf_flag_str_start = pcf_flag_str.find(":") + 1;
+#endif // ifdef WIN32
+ auto pcf_flag_str_end = pcf_flag_str.find("]");
+ auto pcf_names = pcf_flag_str.substr(pcf_flag_str_start,
+ pcf_flag_str_end - pcf_flag_str_start);
+ fprintf(pfile, "\"%s\",", pcf_names.c_str());
+ fprintf(pfile, "%zu,%d,",
+ pc->nl_count, pc->after_tab);
+
+ if ( pc->type != CT_NEWLINE
+ && (pc->Len() != 0))
+ {
+ fprintf(pfile, "\"");
+
+ for (size_t cnt = 0; cnt < pc->column; cnt++)
+ {
+ fprintf(pfile, " ");
+ }
+
+ if (pc->type != CT_NL_CONT)
+ {
+ for (auto *ch = pc->Text(); *ch != '\0'; ++ch)
+ {
+ fprintf(pfile, "%c", *ch);
+
+ if (*ch == '"')
+ {
+ // need to escape the double-quote for csv-format
+ fprintf(pfile, "\"");
+ }
+ }
+ }
+ else
+ {
+ fprintf(pfile, "\\");
+ }
+ fprintf(pfile, "\"");
+ }
+ }
+
+ fflush(pfile);
+} // output_parsed_csv
+
+
+void output_text(FILE *pfile)
+{
+ bool tracking = cpd.html_file != nullptr; // special for debugging
+
+ cpd.fout = pfile;
+ cpd.did_newline = 1;
+ cpd.column = 1;
+
+ if (cpd.bom)
+ {
+ write_bom();
+ }
+ Chunk *pc;
+
+ if (cpd.frag_cols > 0)
+ {
+ size_t indent = cpd.frag_cols - 1;
+
+ // loop over the whole chunk list
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ pc->column += indent;
+ pc->column_indent += indent;
+ }
+
+ cpd.frag_cols = 0;
+ }
+
+ if (tracking)
+ {
+ add_text("<html>\n");
+ add_text("<head>\n");
+ add_text(" <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/>\n");
+ add_text(" <title>Uncrustify: where do the Spaces options work</title>\n");
+ add_text("</head>\n");
+ add_text("<body lang=\"en-US\">\n");
+ add_text("<p>\n");
+ add_text("</p>\n");
+ add_text("<pre>\n");
+ }
+ bool write_in_tracking = false;
+
+ // loop over the whole chunk list
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ char copy[1000];
+ LOG_FMT(LCONTTEXT, "%s(%d): Text() is '%s', type is %s, orig_line is %zu, column is %zu, nl is %zu\n",
+ __func__, __LINE__, pc->ElidedText(copy), get_token_name(pc->type), pc->orig_line, pc->column, pc->nl_count);
+ log_rule_B("cmt_convert_tab_to_spaces");
+ cpd.output_tab_as_space = ( options::cmt_convert_tab_to_spaces()
+ && pc->IsComment());
+
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ for (size_t cnt = 0; cnt < pc->nl_count; cnt++)
+ {
+ if ( cnt > 0
+ && pc->nl_column > 1)
+ {
+ log_rule_B("indent_with_tabs");
+ output_to_column(pc->nl_column, (options::indent_with_tabs() == 2));
+ }
+ add_char('\n');
+ }
+
+ cpd.did_newline = 1;
+ cpd.column = 1;
+ LOG_FMT(LOUTIND, " xx\n");
+ }
+ else if (chunk_is_token(pc, CT_NL_CONT))
+ {
+ // FIXME: this really shouldn't be done here!
+ if (!pc->flags.test(PCF_WAS_ALIGNED))
+ {
+ // Add or remove space before a backslash-newline at the end of a line.
+ log_rule_B("sp_before_nl_cont");
+
+ if (options::sp_before_nl_cont() & IARF_REMOVE)
+ {
+ log_rule_B("sp_before_nl_cont");
+ pc->column = cpd.column + (options::sp_before_nl_cont() == IARF_FORCE);
+ }
+ else
+ {
+ // Try to keep the same relative spacing
+ Chunk *prev = pc->GetPrev();
+
+ if (chunk_is_token(prev, CT_PP_IGNORE))
+ {
+ /*
+ * Want to completely leave alone PP_IGNORE'd blocks because
+ * they likely have special column aligned newline
+ * continuations (common in multiline macros)
+ */
+ pc->column = pc->orig_col;
+ }
+ else
+ {
+ // Try to keep the same relative spacing
+ while ( prev != nullptr
+ && prev->IsNotNullChunk()
+ && prev->orig_col == 0
+ && prev->nl_count == 0)
+ {
+ prev = prev->GetPrev();
+ }
+
+ if ( prev != nullptr
+ && prev->IsNotNullChunk()
+ && prev->nl_count == 0)
+ {
+ int orig_sp = (pc->orig_col - prev->orig_col_end);
+
+ if ((int)(cpd.column + orig_sp) < 0)
+ {
+#ifdef WIN32
+ fprintf(stderr, "FATAL: negative value.\n pc->orig_col is %d, prev->orig_col_end is %d\n",
+ (int)pc->orig_col, (int)prev->orig_col_end);
+#else // not WIN32
+ fprintf(stderr, "FATAL: negative value.\n pc->orig_col is %zu, prev->orig_col_end is %zu\n",
+ pc->orig_col, prev->orig_col_end);
+#endif // ifdef WIN32
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ pc->column = cpd.column + orig_sp;
+
+ // Add or remove space before a backslash-newline at the end of a line.
+ log_rule_B("sp_before_nl_cont");
+
+ if ( (options::sp_before_nl_cont() != IARF_IGNORE)
+ && (pc->column < (cpd.column + 1)))
+ {
+ pc->column = cpd.column + 1;
+ }
+ }
+ }
+ }
+ output_to_column(pc->column, false);
+ }
+ else
+ {
+ log_rule_B("indent_with_tabs");
+ output_to_column(pc->column, (options::indent_with_tabs() == 2));
+ }
+ add_char('\\');
+ add_char('\n');
+ cpd.did_newline = 1;
+ cpd.column = 1;
+ LOG_FMT(LOUTIND, " \\xx\n");
+ }
+ else if (chunk_is_token(pc, CT_COMMENT_MULTI))
+ {
+ log_rule_B("cmt_indent_multi");
+
+ if (options::cmt_indent_multi())
+ {
+ output_comment_multi(pc);
+ }
+ else
+ {
+ output_comment_multi_simple(pc);
+ }
+ }
+ else if (chunk_is_token(pc, CT_COMMENT_CPP))
+ {
+ bool tmp = cpd.output_trailspace;
+ /*
+ * keep trailing spaces if they are still present in a chunk;
+ * note that tokenize() already strips spaces in comments,
+ * so if they made it up to here, they are to stay
+ */
+ cpd.output_trailspace = true;
+ pc = output_comment_cpp(pc);
+ cpd.output_trailspace = tmp;
+ }
+ else if (chunk_is_token(pc, CT_COMMENT))
+ {
+ pc = output_comment_c(pc);
+ }
+ else if ( chunk_is_token(pc, CT_JUNK)
+ || chunk_is_token(pc, CT_IGNORED))
+ {
+ LOG_FMT(LOUTIND, "%s(%d): orig_line is %zu, orig_col is %zu,\npc->Text() >%s<, pc->str.size() is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), pc->str.size());
+ // do not adjust the column for junk
+ add_text(pc->str, true);
+ }
+ else if (pc->Len() == 0)
+ {
+ // don't do anything for non-visible stuff
+ LOG_FMT(LOUTIND, "%s(%d): orig_line is %zu, column is %zu, non-visible stuff: type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->column, get_token_name(pc->type));
+ }
+ else
+ {
+ bool allow_tabs;
+ cpd.output_trailspace = (chunk_is_token(pc, CT_STRING_MULTI));
+
+ // indent to the 'level' first
+ if (cpd.did_newline)
+ {
+ log_rule_B("indent_with_tabs");
+
+ if (options::indent_with_tabs() == 1)
+ {
+ size_t lvlcol;
+
+ /*
+ * FIXME: it would be better to properly set column_indent in
+ * indent_text(), but this hack for '}' and '#' seems to work.
+ */
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ || chunk_is_token(pc, CT_CASE_COLON)
+ || chunk_is_token(pc, CT_PREPROC))
+ {
+ lvlcol = pc->column;
+ }
+ else
+ {
+ lvlcol = pc->column_indent;
+
+ if (lvlcol > pc->column)
+ {
+ lvlcol = pc->column;
+ }
+ }
+
+ if (lvlcol > 1)
+ {
+ output_to_column(lvlcol, true);
+ }
+ }
+ log_rule_B("indent_with_tabs");
+ allow_tabs = (options::indent_with_tabs() == 2)
+ || ( pc->IsComment()
+ && options::indent_with_tabs() != 0);
+
+ LOG_FMT(LOUTIND, "%s(%d): orig_line is %zu, column is %zu, column_indent is %zu, cpd.column is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->column, pc->column_indent, cpd.column);
+ }
+ else
+ {
+ /*
+ * Reformatting multi-line comments can screw up the column.
+ * Make sure we don't mess up the spacing on this line.
+ * This has to be done here because comments are not formatted
+ * until the output phase.
+ */
+ if (pc->column < cpd.column)
+ {
+ reindent_line(pc, cpd.column);
+ }
+ // not the first item on a line
+ Chunk *prev = pc->GetPrev();
+ log_rule_B("align_with_tabs");
+ allow_tabs = ( options::align_with_tabs()
+ && pc->flags.test(PCF_WAS_ALIGNED)
+ && ((prev->column + prev->Len() + 1) != pc->column));
+
+ log_rule_B("align_keep_tabs");
+
+ if (options::align_keep_tabs())
+ {
+ allow_tabs |= pc->after_tab;
+ }
+ LOG_FMT(LOUTIND, "%s(%d): at column %zu(%s)\n",
+ __func__, __LINE__, pc->column, (allow_tabs ? "true" : "FALSE"));
+ }
+ output_to_column(pc->column, allow_tabs);
+
+ if (write_in_tracking)
+ {
+ if (chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ add_text("&lt;", false, false);
+ }
+ else if (chunk_is_token(pc, CT_ANGLE_CLOSE))
+ {
+ add_text("&gt;", false, false);
+ }
+ else
+ {
+ add_text(pc->str, false, chunk_is_token(pc, CT_STRING));
+ }
+ write_in_tracking = false;
+ }
+ else
+ {
+ add_text(pc->str, false, chunk_is_token(pc, CT_STRING));
+ }
+
+ if (chunk_is_token(pc, CT_PP_DEFINE)) // Issue #876
+ {
+ // If true, a <TAB> is inserted after #define.
+ log_rule_B("force_tab_after_define");
+
+ if (options::force_tab_after_define())
+ {
+ add_char('\t');
+ }
+ }
+ cpd.did_newline = chunk_is_newline(pc);
+ cpd.output_trailspace = false;
+ }
+
+ if (pc->tracking != nullptr)
+ {
+ LOG_FMT(LGUY, " Tracking info are: \n");
+ LOG_FMT(LGUY, " number of track(s) %zu\n", pc->tracking->size());
+ add_text("<a title=\"");
+ char tempText[80];
+
+ for (size_t track = 0; track < pc->tracking->size(); track++)
+ {
+ track_list *A = pc->tracking;
+ Track_nr B = A->at(track);
+ size_t Bfirst = B.first;
+ char *Bsecond = B.second;
+
+ sprintf(tempText, "%zu", Bfirst);
+ add_text(tempText);
+ add_text(",");
+
+ if (track == pc->tracking->size() - 1)
+ {
+ sprintf(tempText, "%s", Bsecond);
+ add_text(tempText);
+ }
+ LOG_FMT(LGUY, " %zu, tracking number is %zu\n", track, Bfirst);
+ LOG_FMT(LGUY, " %zu, rule is %s\n", track, Bsecond);
+ }
+
+ add_text("\"><font color=\"red\">M</font></a>");
+ write_in_tracking = true;
+ }
+ }
+
+ if (tracking)
+ {
+ add_text("</pre>\n");
+ add_text("</body>\n");
+ add_text("</html>\n");
+ }
+} // output_text
+
+
+void dump_step(const char *filename, const char *step_description)
+{
+ static int file_num = 0;
+ char buffer[256];
+ FILE *dump_file;
+
+ if ( filename == nullptr
+ || strlen(filename) == 0)
+ {
+ return;
+ }
+
+ // On the first call, also save the options in use
+ if (file_num == 0)
+ {
+ snprintf(buffer, 256, "New dump file: %s_%03d.log - Options in use", filename, file_num);
+ log_rule_B(buffer);
+
+ snprintf(buffer, 256, "%s_%03d.log", filename, file_num);
+ ++file_num;
+
+ dump_file = fopen(buffer, "wb");
+
+ if (dump_file != nullptr)
+ {
+ save_option_file(dump_file, false, true);
+ fclose(dump_file);
+ }
+ }
+ snprintf(buffer, 256, "New dump file: %s_%03d.log - %s", filename, file_num, step_description);
+ log_rule_B(buffer);
+
+ snprintf(buffer, 256, "%s_%03d.log", filename, file_num);
+ ++file_num;
+
+ dump_file = fopen(buffer, "wb");
+
+ if (dump_file != nullptr)
+ {
+ fprintf(dump_file, "STEP: %s\n--------------\n", step_description);
+ output_parsed(dump_file, false);
+ fclose(dump_file);
+ }
+} // dump_step
+
+
+static size_t cmt_parse_lead(const unc_text &line, bool is_last)
+{
+ size_t len = 0;
+
+ while ( len < 32
+ && len < line.size()) // TODO what is the meaning of 32?
+ {
+ if ( len > 0
+ && line[len] == '/')
+ {
+ // ignore combined comments
+ size_t tmp = len + 1;
+
+ while ( tmp < line.size()
+ && unc_isspace(line[tmp]))
+ {
+ tmp++;
+ }
+
+ if ( tmp < line.size()
+ && line[tmp] == '/')
+ {
+ return(1);
+ }
+ break;
+ }
+ else if (strchr("*|\\#+", line[len]) == nullptr)
+ {
+ break; // none of the characters '*|\#+' found in line
+ }
+ len++;
+ }
+
+ if (len > 30) // TODO: what is the meaning of 30?
+ {
+ return(1);
+ }
+
+ if ( len > 0
+ && ( len >= line.size()
+ || unc_isspace(line[len])))
+ {
+ return(len);
+ }
+
+ if ( len == 1
+ && line[0] == '*')
+ {
+ return(len);
+ }
+
+ if ( is_last
+ && len > 0)
+ {
+ return(len);
+ }
+ return(0);
+} // cmt_parse_lead
+
+
+/**
+ * Eat whitespace characters starting at the specified index in the forward or reverse direction
+ * within a single line
+ * @param str the input string containing the comment text
+ * @param idx the starting index
+ * @param forward if true, searches in the forward direction;
+ * if false, searches in the reverse direction
+ * @return the first index at which a non-whitespace character is encountered, including
+ * a newline character
+ */
+template<typename String>
+static int eat_line_whitespace(const String &str,
+ int idx, bool
+ forward = true)
+{
+ auto advance_index = [&](int i)
+ {
+ return(forward ? i + 1 : i - 1);
+ };
+
+ auto index_in_range = [&](int i)
+ {
+ // TODO: the following BREAKS with source code formatting; uncrustify seems to
+ // think that the following is a template. This will NEED to be fixed!!!
+ // For now, reformulate the statement
+ //return(forward ? i<int(str.size()) : i> = 0);
+ return(forward ? (i < int(str.size())) : (i >= 0));
+ };
+
+ while ( index_in_range(idx)
+ && str[idx] != '\n'
+ && str[idx] != '\r'
+ && unc_isspace(str[idx]))
+ {
+ idx = advance_index(idx);
+ }
+ return(idx);
+} // eat_line_whitespace
+
+
+/**
+ * Returns whether or not a javaparam tag is the leading
+ * text in a comment line, with only a sequence of whitespace
+ * and/or '*' characters preceding it
+ * @param str the input string containing the comment text
+ * @param idx the starting index
+ * @return true/false
+ */
+template<typename String>
+static bool javaparam_tag_is_start_of_line(const String &str, int idx)
+{
+ idx = eat_line_whitespace(str,
+ str[idx] == '@' ? idx - 1 : idx,
+ false);
+
+ while (true)
+ {
+ if ( idx < 0
+ || str[idx] == '\n'
+ || str[idx] == '\r')
+ {
+ return(true);
+ }
+
+ if (str[idx] == '*')
+ {
+ idx = eat_line_whitespace(str,
+ idx - 1,
+ false);
+ }
+ else
+ {
+ return(false);
+ }
+ }
+} // javaparam_tag_is_start_of_line
+
+
+/**
+ * Attempts to match a doxygen/javadoc-style comment tag
+ * @param str the input string containing the comment text
+ * @param idx the starting index
+ * @return the index of the character immediately following the matched tag,
+ * or -1 if no match is found
+ */
+static int match_doxygen_javadoc_tag(const std::wstring &str, size_t idx)
+{
+ std::wsmatch match;
+
+ if (str[idx] == L'@')
+ {
+ // Issue #3357
+ std::wregex criteria(L"(@(?:author|"
+ L"deprecated|"
+ L"exception|"
+ L"param(?:\\s*?\\[\\s*(?:in\\s*,\\s*out|in|out)\\s*?\\])?|"
+ L"return|"
+ L"see|"
+ L"since|"
+ L"throws|"
+ L"version)(?=\\s))");
+
+ if ( std::regex_search(str.cbegin() + idx, str.cend(), match, criteria)
+ && match[1].matched
+ && match.position(1) == std::wsmatch::difference_type(0))
+ {
+ std::set<std::wstring> block_tags =
+ {
+ L"@author",
+ L"@deprecated",
+ L"@exception",
+ L"@param",
+ L"@param[in]",
+ L"@param[in,out]",
+ L"@param[out]",
+ L"@return",
+ L"@see",
+ L"@since",
+ L"@throws",
+ L"@version"
+ };
+ std::wstring result(match[1]);
+ result.erase(std::remove_if(result.begin(), result.end(), ::isspace), result.end());
+ auto &&it_block_tag = block_tags.find(result);
+
+ if ( it_block_tag != block_tags.end()
+ && javaparam_tag_is_start_of_line(str, idx))
+ {
+ return(int(idx + match[1].length()));
+ }
+ }
+ }
+ return(-1);
+} // match_javadoc_block_tag
+
+
+static void calculate_doxygen_javadoc_indent_alignment(const std::wstring &str,
+ size_t &doxygen_javadoc_param_name_indent,
+ size_t &doxygen_javadoc_continuation_indent)
+{
+ log_rule_B("cmt_align_doxygen_javadoc_tags");
+
+ doxygen_javadoc_continuation_indent = 0;
+ doxygen_javadoc_param_name_indent = 0;
+
+ if (!options::cmt_align_doxygen_javadoc_tags())
+ {
+ return;
+ }
+
+ for (size_t idx = 0; idx < str.size(); ++idx)
+ {
+ int start_idx = idx;
+ int end_idx = match_doxygen_javadoc_tag(str, start_idx);
+
+ if (end_idx > start_idx)
+ {
+ size_t block_tag_width = 1 + std::count_if(str.begin() + start_idx,
+ str.begin() + end_idx,
+ [](wchar_t ch) {
+ return(!unc_isspace(ch));
+ });
+
+ if (block_tag_width > doxygen_javadoc_param_name_indent)
+ {
+ doxygen_javadoc_param_name_indent = block_tag_width;
+ }
+ idx = eat_line_whitespace(str, end_idx);
+
+ size_t param_name_width = 0;
+
+ if (str.find(L"@param", start_idx) == size_t(start_idx))
+ {
+ param_name_width = 1;
+
+ while (true)
+ {
+ while ( !unc_isspace(str[idx])
+ && str[idx] != ',')
+ {
+ ++param_name_width;
+ ++idx;
+ }
+ idx = eat_line_whitespace(str, idx);
+
+ if (str[idx] != ',')
+ {
+ break;
+ }
+ param_name_width += 2;
+ idx = eat_line_whitespace(str, idx + 1);
+ }
+ }
+
+ if (param_name_width > doxygen_javadoc_continuation_indent)
+ {
+ doxygen_javadoc_continuation_indent = param_name_width;
+ }
+ }
+ }
+
+ if (doxygen_javadoc_param_name_indent > 0)
+ {
+ log_rule_B("cmt_sp_before_doxygen_javadoc_tags");
+
+ doxygen_javadoc_param_name_indent += options::cmt_sp_before_doxygen_javadoc_tags();
+ doxygen_javadoc_continuation_indent += doxygen_javadoc_param_name_indent;
+ }
+} // calculate_doxygen_javadoc_indent_alignment
+
+
+static void calculate_comment_body_indent(cmt_reflow &cmt, const unc_text &str)
+{
+ cmt.xtra_indent = 0;
+
+ log_rule_B("cmt_indent_multi");
+
+ if (!options::cmt_indent_multi())
+ {
+ return;
+ }
+ size_t idx = 0;
+ size_t len = str.size();
+ size_t last_len = 0;
+
+ log_rule_B("cmt_multi_check_last");
+
+ if (options::cmt_multi_check_last())
+ {
+ // find the last line length
+ for (idx = len - 1; idx > 0; idx--)
+ {
+ if ( str[idx] == '\n'
+ || str[idx] == '\r')
+ {
+ idx++;
+
+ while ( idx < len
+ && ( str[idx] == ' '
+ || str[idx] == '\t'))
+ {
+ idx++;
+ }
+ last_len = len - idx;
+ break;
+ }
+ }
+ }
+ // find the first line length
+ size_t first_len = 0;
+
+ for (idx = 0; idx < len; idx++)
+ {
+ if ( str[idx] == '\n'
+ || str[idx] == '\r')
+ {
+ first_len = idx;
+
+ while ( str[first_len - 1] == ' '
+ || str[first_len - 1] == '\t')
+ {
+ if (first_len == 0)
+ {
+ fprintf(stderr, "%s(%d): first_len is ZERO, cannot be decremented.\n",
+ __func__, __LINE__);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ first_len--;
+ }
+
+ // handle DOS endings
+ if ( str[idx] == '\r'
+ && str[idx + 1] == '\n')
+ {
+ idx++;
+ }
+ idx++;
+ break;
+ }
+ }
+
+ // Scan the second line
+ size_t width = 0;
+
+ for ( ; idx < len - 1; idx++)
+ {
+ if ( str[idx] == ' '
+ || str[idx] == '\t')
+ {
+ if (width > 0)
+ {
+ break;
+ }
+ continue;
+ }
+
+ if ( str[idx] == '\n'
+ || str[idx] == '\r')
+ {
+ break; // Done with second line
+ }
+
+ // Count the leading chars
+ if ( str[idx] == '*'
+ || str[idx] == '|'
+ || str[idx] == '\\'
+ || str[idx] == '#'
+ || str[idx] == '+')
+ {
+ width++;
+ }
+ else
+ {
+ if ( width != 1
+ || str[idx - 1] != '*')
+ {
+ width = 0;
+ }
+ break;
+ }
+ }
+
+ // LOG_FMT(LSYS, "%s: first=%d last=%d width=%d\n", __func__, first_len, last_len, width);
+
+ /*
+ * If the first and last line are the same length and don't contain any
+ * alphanumeric chars and (the first line len > cmt_multi_first_len_minimum
+ * or the second leader is the same as the first line length), then the
+ * indent is 0.
+ */
+ log_rule_B("cmt_multi_first_len_minimum");
+
+ if ( first_len == last_len
+ && ( first_len > options::cmt_multi_first_len_minimum()
+ || first_len == width))
+ {
+ return;
+ }
+ cmt.xtra_indent = (width == 2) ? 0 : 1;
+} // calculate_comment_body_indent
+
+
+// TODO: can we use search_next_chunk here?
+static Chunk *get_next_function(Chunk *pc)
+{
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ while ((pc = pc->GetNext())->IsNotNullChunk())
+ {
+ if ( chunk_is_token(pc, CT_FUNC_DEF)
+ || chunk_is_token(pc, CT_FUNC_PROTO)
+ || chunk_is_token(pc, CT_FUNC_CLASS_DEF)
+ || chunk_is_token(pc, CT_FUNC_CLASS_PROTO)
+ || chunk_is_token(pc, CT_OC_MSG_DECL))
+ {
+ return(pc);
+ }
+ }
+ return(nullptr);
+}
+
+
+static Chunk *get_next_class(Chunk *pc)
+{
+ return(chunk_search_next_cat(pc, CT_CLASS)->GetNext());
+}
+
+
+static Chunk *get_prev_category(Chunk *pc)
+{
+ return(chunk_search_prev_cat(pc, CT_OC_CATEGORY));
+}
+
+
+static Chunk *get_next_scope(Chunk *pc)
+{
+ return(chunk_search_next_cat(pc, CT_OC_SCOPE));
+}
+
+
+static Chunk *get_prev_oc_class(Chunk *pc)
+{
+ return(chunk_search_prev_cat(pc, CT_OC_CLASS));
+}
+
+
+static int next_up(const unc_text &text, size_t idx, const unc_text &tag)
+{
+ size_t offs = 0;
+
+ while ( idx < text.size()
+ && unc_isspace(text[idx]))
+ {
+ idx++;
+ offs++;
+ }
+
+ if (text.startswith(tag, idx))
+ {
+ return(offs);
+ }
+ return(-1);
+}
+
+
+static void add_comment_text(const unc_text &text,
+ cmt_reflow &cmt,
+ bool esc_close,
+ size_t continuation_indent)
+{
+ bool was_star = false;
+ bool was_slash = false;
+ bool in_word = false;
+ size_t len = text.size();
+ size_t ch_cnt = 0; // chars since newline
+
+ // If the '//' is included write it first else we may wrap an empty line
+ size_t idx = 0;
+
+ if (text.startswith("//"))
+ {
+ add_text("//");
+ idx += 2;
+
+ while (unc_isspace(text[idx]))
+ {
+ add_char(text[idx++]);
+ }
+ }
+
+ for ( ; idx < len; idx++) // TODO: avoid modifying idx in loop
+ {
+ // Split the comment
+ if (text[idx] == '\n')
+ {
+ in_word = false;
+ add_char('\n');
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+
+ if (cmt.xtra_indent > 0)
+ {
+ add_char(' ');
+ }
+ // hack to get escaped newlines to align and not duplicate the leading '//'
+ int tmp = next_up(text, idx + 1, "//");
+
+ if (tmp < 0)
+ {
+ add_text(cmt.cont_text);
+ }
+ else
+ {
+ idx += tmp;
+ }
+ ch_cnt = 0;
+ }
+ else if ( cmt.reflow
+ && text[idx] == ' '
+ && options::cmt_width() > 0
+ && ( cpd.column > options::cmt_width()
+ || ( ch_cnt > 1
+ && next_word_exceeds_limit(text, idx))))
+ {
+ log_rule_B("cmt_width");
+ in_word = false;
+ add_char('\n');
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+
+ if (cmt.xtra_indent > 0)
+ {
+ add_char(' ');
+ }
+ // The number of spaces to insert after the star on subsequent comment lines.
+ log_rule_B("cmt_sp_after_star_cont");
+
+ /**
+ * calculate the output column
+ */
+ size_t column = options::cmt_sp_after_star_cont();
+
+ if ( text[idx + 1] == 42 // this is star *
+ && text[idx + 2] == 47) // this is /
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d): we have a comment end\n",
+ __func__, __LINE__);
+
+ column += cmt.column;
+ }
+ else
+ {
+ add_text(cmt.cont_text);
+
+ if (continuation_indent > 0)
+ {
+ if (options::cmt_align_doxygen_javadoc_tags())
+ {
+ log_rule_B("cmt_align_doxygen_javadoc_tags");
+ }
+ else if (options::cmt_reflow_indent_to_paragraph_start())
+ {
+ log_rule_B("cmt_reflow_indent_to_paragraph_start");
+ }
+ column += continuation_indent;
+
+ log_rule_B("cmt_sp_after_star_cont");
+
+ if (column >= options::cmt_sp_after_star_cont())
+ {
+ column -= options::cmt_sp_after_star_cont();
+ }
+ }
+ /**
+ * count the number trailing spaces in the comment continuation text
+ */
+ size_t num_trailing_sp = 0;
+
+ while ( num_trailing_sp < cmt.cont_text.size()
+ && unc_isspace(cmt.cont_text[cmt.cont_text.size() - 1 - num_trailing_sp]))
+ {
+ ++num_trailing_sp;
+ }
+ column += cpd.column;
+
+ if (column >= num_trailing_sp)
+ {
+ column -= num_trailing_sp;
+ }
+ }
+ output_to_column(column,
+ false);
+ ch_cnt = 0;
+ }
+ else
+ {
+ // Escape a C closure in a CPP comment
+ if ( esc_close
+ && ( ( was_star
+ && text[idx] == '/')
+ || ( was_slash
+ && text[idx] == '*')))
+ {
+ add_char(' ');
+ }
+
+ if ( !in_word
+ && !unc_isspace(text[idx]))
+ {
+ cmt.word_count++;
+ }
+ in_word = !unc_isspace(text[idx]);
+
+ add_char(text[idx]);
+ was_star = (text[idx] == '*');
+ was_slash = (text[idx] == '/');
+ ch_cnt++;
+ }
+ }
+} // add_comment_text
+
+
+static void output_cmt_start(cmt_reflow &cmt, Chunk *pc)
+{
+ cmt.pc = pc;
+ cmt.column = pc->column;
+ cmt.brace_col = pc->column_indent;
+ cmt.base_col = pc->column_indent;
+ cmt.word_count = 0;
+ cmt.xtra_indent = 0;
+ cmt.cont_text.clear();
+ cmt.reflow = false;
+
+ // Issue #2752
+ log_rule_B("cmt_insert_file_header");
+ log_rule_B("cmt_insert_file_footer");
+ log_rule_B("cmt_insert_func_header)");
+ log_rule_B("cmt_insert_class_header");
+ log_rule_B("cmt_insert_oc_msg_header");
+
+ if ( options::cmt_insert_file_header().size() > 0
+ || options::cmt_insert_file_footer().size() > 0
+ || options::cmt_insert_func_header().size() > 0
+ || options::cmt_insert_class_header().size() > 0
+ || options::cmt_insert_oc_msg_header().size() > 0)
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d): cmt_insert_file\n", __func__, __LINE__);
+ do_kw_subst(pc);
+ }
+ else
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d): no cmt_insert_file\n", __func__, __LINE__);
+ }
+
+ if (cmt.brace_col == 0)
+ {
+ log_rule_B("output_tab_size");
+ cmt.brace_col = 1 + (pc->brace_level * options::output_tab_size());
+ }
+ // LOG_FMT(LSYS, "%s: line %zd, brace=%zd base=%zd col=%zd orig=%zd aligned=%x\n",
+ // __func__, pc->orig_line, cmt.brace_col, cmt.base_col, cmt.column, pc->orig_col,
+ // pc->flags & (PCF_WAS_ALIGNED | PCF_RIGHT_COMMENT));
+
+ if ( get_chunk_parent_type(pc) == CT_COMMENT_START
+ || get_chunk_parent_type(pc) == CT_COMMENT_WHOLE)
+ {
+ log_rule_B("indent_col1_comment");
+
+ if ( !options::indent_col1_comment()
+ && pc->orig_col == 1
+ && !pc->flags.test(PCF_INSERTED))
+ {
+ cmt.column = 1;
+ cmt.base_col = 1;
+ cmt.brace_col = 1;
+ }
+ }
+ // tab aligning code
+ log_rule_B("indent_cmt_with_tabs");
+
+ if ( options::indent_cmt_with_tabs()
+ && ( get_chunk_parent_type(pc) == CT_COMMENT_END
+ || get_chunk_parent_type(pc) == CT_COMMENT_WHOLE))
+ {
+ cmt.column = align_tab_column(cmt.column - 1);
+ // LOG_FMT(LSYS, "%s: line %d, orig:%d new:%d\n",
+ // __func__, pc->orig_line, pc->column, cmt.column);
+ pc->column = cmt.column;
+ }
+ cmt.base_col = cmt.column;
+
+ // LOG_FMT(LSYS, "%s: -- brace=%d base=%d col=%d\n",
+ // __func__, cmt.brace_col, cmt.base_col, cmt.column);
+
+ // Bump out to the column
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+} // output_cmt_start
+
+
+static bool can_combine_comment(Chunk *pc, cmt_reflow &cmt)
+{
+ // We can't combine if there is something other than a newline next
+ if (get_chunk_parent_type(pc) == CT_COMMENT_START)
+ {
+ return(false);
+ }
+
+ // next is a newline for sure, make sure it is a single newline
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && next->nl_count == 1)
+ {
+ // Make sure the comment is the same type at the same column
+ next = next->GetNext();
+
+ if ( chunk_is_token(next, pc->type)
+ && ( ( next->column == 1
+ && pc->column == 1)
+ || ( next->column == cmt.base_col
+ && pc->column == cmt.base_col)
+ || ( next->column > cmt.base_col
+ && get_chunk_parent_type(pc) == CT_COMMENT_END)))
+ {
+ return(true);
+ }
+ }
+ return(false);
+} // can_combine_comment
+
+
+static Chunk *output_comment_c(Chunk *first)
+{
+ cmt_reflow cmt;
+
+ output_cmt_start(cmt, first);
+ log_rule_B("cmt_reflow_mode");
+ cmt.reflow = (options::cmt_reflow_mode() != 1);
+
+ // See if we can combine this comment with the next comment
+ log_rule_B("cmt_c_group");
+
+ if ( !options::cmt_c_group()
+ || !can_combine_comment(first, cmt))
+ {
+ // Just add the single comment
+ log_rule_B("cmt_star_cont");
+ cmt.cont_text = options::cmt_star_cont() ? " * " : " ";
+ LOG_CONTTEXT();
+
+ log_rule_B("cmt_trailing_single_line_c_to_cpp");
+
+ if (options::cmt_trailing_single_line_c_to_cpp() && chunk_is_last_on_line(first))
+ {
+ add_text("//");
+
+ unc_text tmp;
+ tmp.set(first->str, 2, first->Len() - 4);
+ cmt_trim_whitespace(tmp, false);
+ add_comment_text(tmp, cmt, false);
+ }
+ else
+ {
+ add_comment_text(first->str, cmt, false);
+ }
+ return(first);
+ }
+ log_rule_B("cmt_star_cont");
+ cmt.cont_text = options::cmt_star_cont() ? " *" : " ";
+ LOG_CONTTEXT();
+
+ add_text("/*");
+
+ log_rule_B("cmt_c_nl_start");
+
+ if (options::cmt_c_nl_start())
+ {
+ add_comment_text("\n", cmt, false);
+ }
+ Chunk *pc = first;
+ unc_text tmp;
+
+ while (can_combine_comment(pc, cmt))
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d): Text() is '%s'\n",
+ __func__, __LINE__, pc->Text());
+ tmp.set(pc->str, 2, pc->Len() - 4);
+
+ if ( cpd.last_char == '*'
+ && ( tmp[0] == '/'
+ || tmp[0] != ' ')) // Issue #1908
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d): add_text a " "\n", __func__, __LINE__);
+ add_text(" ");
+ }
+ // In case of reflow, original comment could contain trailing spaces before closing the comment, we don't need them after reflow
+ LOG_FMT(LCONTTEXT, "%s(%d): trim\n", __func__, __LINE__);
+ cmt_trim_whitespace(tmp, false);
+ LOG_FMT(LCONTTEXT, "%s(%d): add_comment_text(tmp is '%s')\n",
+ __func__, __LINE__, tmp.c_str());
+ add_comment_text(tmp, cmt, false);
+ LOG_FMT(LCONTTEXT, "%s(%d): add_comment_text(newline)\n",
+ __func__, __LINE__);
+ add_comment_text("\n", cmt, false);
+ pc = pc->GetNext();
+ pc = pc->GetNext();
+ }
+ tmp.set(pc->str, 2, pc->Len() - 4);
+
+ if ( cpd.last_char == '*'
+ && tmp[0] == '/')
+ {
+ add_text(" ");
+ }
+ // In case of reflow, original comment could contain trailing spaces before closing the comment, we don't need them after reflow
+ cmt_trim_whitespace(tmp, false);
+ add_comment_text(tmp, cmt, false);
+
+ log_rule_B("cmt_c_nl_end");
+
+ if (options::cmt_c_nl_end())
+ {
+ cmt.cont_text = " ";
+ LOG_CONTTEXT();
+ add_comment_text("\n", cmt, false);
+ }
+ add_comment_text("*/", cmt, false);
+ return(pc);
+} // output_comment_c
+
+
+static Chunk *output_comment_cpp(Chunk *first)
+{
+ cmt_reflow cmt;
+
+ output_cmt_start(cmt, first);
+ log_rule_B("cmt_reflow_mode");
+ cmt.reflow = (options::cmt_reflow_mode() != 1);
+
+ unc_text leadin = "//"; // default setting to keep previous behaviour
+
+ // If true, space is added with sp_cmt_cpp_start will be added after doxygen
+ // sequences like '///', '///<', '//!' and '//!<'.
+ log_rule_B("sp_cmt_cpp_doxygen");
+
+ if (options::sp_cmt_cpp_doxygen()) // special treatment for doxygen style comments (treat as unity)
+ {
+ const char *sComment = first->Text();
+ bool grouping = (sComment[2] == '@');
+ size_t brace = 3;
+
+ if ( sComment[2] == '/'
+ || sComment[2] == '!') // doxygen style found!
+ {
+ leadin += sComment[2]; // at least one additional char (either "///" or "//!")
+
+ if (sComment[3] == '<') // and a further one (either "///<" or "//!<")
+ {
+ leadin += '<';
+ }
+ else
+ {
+ grouping = (sComment[3] == '@'); // or a further one (grouping)
+ brace = 4;
+ }
+ }
+
+ if ( grouping
+ && ( sComment[brace] == '{'
+ || sComment[brace] == '}'))
+ {
+ leadin += '@';
+ leadin += sComment[brace];
+ }
+ }
+ // Special treatment for Qt translator or meta-data comments (treat as unity)
+ // If true, space is added with sp_cmt_cpp_start will be added after Qt
+ // translator or meta-data comments like '//:', '//=', and '//~'.
+ log_rule_B("sp_cmt_cpp_qttr");
+
+ if (options::sp_cmt_cpp_qttr())
+ {
+ const int c = first->str[2];
+
+ if ( c == ':'
+ || c == '='
+ || c == '~')
+ {
+ leadin += c;
+ }
+ }
+ // CPP comments can't be grouped unless they are converted to C comments
+ log_rule_B("cmt_cpp_to_c");
+
+ if (!options::cmt_cpp_to_c())
+ {
+ auto const *cmt_text = first->str.c_str() + 2;
+ // Add or remove space after the opening of a C++ comment,
+ // i.e. '// A' vs. '//A'.
+ auto *sp_cmt = &options::sp_cmt_cpp_start;
+
+ cmt.cont_text = leadin;
+
+ // Get start of comment text
+ while ( *cmt_text != '\0'
+ && unc_isspace(*cmt_text))
+ {
+ ++cmt_text;
+ }
+
+ // Determine if we are dealing with a region marker
+ if ( ( !first->prev
+ || first->prev->orig_line != first->orig_line)
+ && ( strncmp(cmt_text, "BEGIN", 5) == 0
+ || strncmp(cmt_text, "END", 3) == 0))
+ {
+ // If sp_cmt_cpp_region is not ignore, use that instead of
+ // sp_cmt_cpp_start
+ if (options::sp_cmt_cpp_region() != IARF_IGNORE)
+ {
+ sp_cmt = &options::sp_cmt_cpp_region;
+ }
+ }
+ // Add or remove space after the opening of a C++ comment,
+ // i.e. '// A' vs. '//A'.
+ log_rule_B(sp_cmt->name());
+
+ if ((*sp_cmt)() != IARF_REMOVE)
+ {
+ cmt.cont_text += ' ';
+ }
+ LOG_CONTTEXT();
+
+ // Add or remove space after the opening of a C++ comment,
+ // i.e. '// A' vs. '//A'.
+ log_rule_B(sp_cmt->name());
+
+ if ((*sp_cmt)() == IARF_IGNORE)
+ {
+ add_comment_text(first->str, cmt, false);
+ }
+ else
+ {
+ size_t iLISz = leadin.size();
+ unc_text tmp(first->str, 0, iLISz);
+ add_comment_text(tmp, cmt, false);
+
+ tmp.set(first->str, iLISz, first->Len() - iLISz);
+
+ // Add or remove space after the opening of a C++ comment,
+ // i.e. '// A' vs. '//A'.
+ log_rule_B("sp_cmt_cpp_start");
+
+ if ((*sp_cmt)() & IARF_REMOVE)
+ {
+ while ( (tmp.size() > 0)
+ && unc_isspace(tmp[0]))
+ {
+ tmp.pop_front();
+ }
+ }
+
+ if (tmp.size() > 0)
+ {
+ // Add or remove space after the opening of a C++ comment,
+ // i.e. '// A' vs. '//A'.
+ log_rule_B("sp_cmt_cpp_start");
+
+ if ((*sp_cmt)() & IARF_ADD)
+ {
+ if ( !unc_isspace(tmp[0])
+ && (tmp[0] != '/'))
+ {
+ add_comment_text(" ", cmt, false);
+ }
+ }
+ add_comment_text(tmp, cmt, false);
+ }
+ }
+ return(first);
+ }
+ // We are going to convert the CPP comments to C comments
+ log_rule_B("cmt_star_cont");
+ cmt.cont_text = options::cmt_star_cont() ? " * " : " ";
+ LOG_CONTTEXT();
+
+ unc_text tmp;
+
+ // See if we can combine this comment with the next comment
+ log_rule_B("cmt_cpp_group");
+
+ if ( !options::cmt_cpp_group()
+ || !can_combine_comment(first, cmt))
+ {
+ // nothing to group: just output a single line
+ add_text("/*");
+
+ // patch # 32, 2012-03-23
+ // Add or remove space after the opening of a C++ comment,
+ // i.e. '// A' vs. '//A'.
+ log_rule_B("sp_cmt_cpp_start");
+
+ if ( !unc_isspace(first->str[2])
+ && (options::sp_cmt_cpp_start() & IARF_ADD))
+ {
+ add_char(' ');
+ }
+ tmp.set(first->str, 2, first->Len() - 2);
+ add_comment_text(tmp, cmt, true);
+ add_text(" */");
+ return(first);
+ }
+ add_text("/*");
+
+ log_rule_B("cmt_cpp_nl_start");
+
+ if (options::cmt_cpp_nl_start())
+ {
+ add_comment_text("\n", cmt, false);
+ }
+ else
+ {
+ add_text(" ");
+ }
+ Chunk *pc = first;
+ int offs;
+
+ while (can_combine_comment(pc, cmt))
+ {
+ offs = unc_isspace(pc->str[2]) ? 1 : 0;
+ tmp.set(pc->str, 2 + offs, pc->Len() - (2 + offs));
+
+ if ( cpd.last_char == '*'
+ && tmp[0] == '/')
+ {
+ add_text(" ");
+ }
+ add_comment_text(tmp, cmt, true);
+ add_comment_text("\n", cmt, false);
+ pc = pc->GetNext()->GetNext();
+ }
+ offs = unc_isspace(pc->str[2]) ? 1 : 0;
+ tmp.set(pc->str, 2 + offs, pc->Len() - (2 + offs));
+ add_comment_text(tmp, cmt, true);
+
+ log_rule_B("cmt_cpp_nl_end");
+
+ if (options::cmt_cpp_nl_end())
+ {
+ cmt.cont_text = "";
+ LOG_CONTTEXT();
+ add_comment_text("\n", cmt, false);
+ }
+ add_comment_text(" */", cmt, false);
+ return(pc);
+} // output_comment_cpp
+
+
+static void cmt_trim_whitespace(unc_text &line, bool in_preproc)
+{
+ // Remove trailing whitespace on the line
+ while ( line.size() > 0
+ && ( line.back() == ' '
+ || line.back() == '\t'))
+ {
+ line.pop_back();
+ }
+
+ // Shift back to the comment text, ...
+ if ( in_preproc // if in a preproc ...
+ && line.size() > 1 // with a line that holds ...
+ && line.back() == '\\') // a backslash-newline ...
+ {
+ bool do_space = false;
+
+ // If there was any space before the backslash, change it to 1 space
+ line.pop_back();
+
+ while ( line.size() > 0
+ && ( line.back() == ' '
+ || line.back() == '\t'))
+ {
+ do_space = true;
+ line.pop_back();
+ }
+
+ if (do_space)
+ {
+ line.append(' ');
+ }
+ line.append('\\');
+ }
+} // cmt_trim_whitespace
+
+
+/**
+ * Return an indexed-map of reflow fold end of line/beginning of line regex pairs read
+ * from file
+ */
+static std::map<std::size_t, std::pair<std::wregex, std::wregex> > get_reflow_fold_regex_map()
+{
+ /**
+ * TODO: should the following be static to prevent initializing it multiple times?
+ */
+ static std::map<std::size_t, std::pair<std::wregex, std::wregex> > regex_map;
+
+ if (regex_map.empty())
+ {
+ if (!options::cmt_reflow_fold_regex_file().empty())
+ {
+ std::wstring raw_wstring(cpd.reflow_fold_regex.raw.begin(),
+ cpd.reflow_fold_regex.raw.end());
+
+ std::wregex criteria(L"\\s*(?:(?:(beg_of_next)|(end_of_prev))_line_regex)"
+ "\\s*\\[\\s*([0-9]+)\\s*\\]\\s*=\\s*\"(.*)\"\\s*"
+ "(?=\\r\\n|\\r|\\n|$)");
+ std::wsregex_iterator it_regex(raw_wstring.cbegin(), raw_wstring.cend(), criteria);
+ std::wsregex_iterator it_regex_end = std::wsregex_iterator();
+
+ while (it_regex != it_regex_end)
+ {
+ std::wsmatch match = *it_regex;
+
+ if ( (( match[1].matched
+ || match[2].matched))
+ && match[3].matched
+ && match[4].matched)
+ {
+ auto &&index = std::stoi(match[3].str());
+ std::wregex *p_wregex = match[1].matched ? &regex_map[index].second
+ : &regex_map[index].first;
+ *p_wregex = match[4].str();
+ }
+ ++it_regex;
+ }
+ }
+ else
+ {
+ regex_map.emplace(0L, std::make_pair(L"[\\w,\\]\\)]$", L"^[\\w,\\[\\(]"));
+ regex_map.emplace(1L, std::make_pair(L"\\.$", L"^[A-Z]"));
+ }
+ }
+ return(regex_map);
+} // get_reflow_fold_regex_map
+
+
+static void output_comment_multi(Chunk *pc)
+{
+ if (pc == nullptr)
+ {
+ return;
+ }
+ cmt_reflow cmt;
+
+ char copy[1000];
+
+ LOG_FMT(LCONTTEXT, "%s(%d): Text() is '%s', type is %s, orig_col is %zu, column is %zu\n",
+ __func__, __LINE__, pc->ElidedText(copy), get_token_name(pc->type), pc->orig_col, pc->column);
+
+ output_cmt_start(cmt, pc);
+ log_rule_B("cmt_reflow_mode");
+ cmt.reflow = (options::cmt_reflow_mode() != 1);
+
+ size_t cmt_col = cmt.base_col;
+ int col_diff = pc->orig_col - cmt.base_col;
+
+ calculate_comment_body_indent(cmt, pc->str);
+
+ log_rule_B("cmt_indent_multi");
+ log_rule_B("cmt_star_cont");
+ cmt.cont_text = !options::cmt_indent_multi() ? "" :
+ (options::cmt_star_cont() ? "* " : " ");
+ LOG_CONTTEXT();
+
+ std::wstring pc_wstring(pc->str.get().cbegin(),
+ pc->str.get().cend());
+
+ size_t doxygen_javadoc_param_name_indent = 0;
+ size_t doxygen_javadoc_continuation_indent = 0;
+ size_t reflow_paragraph_continuation_indent = 0;
+
+ calculate_doxygen_javadoc_indent_alignment(pc_wstring,
+ doxygen_javadoc_param_name_indent,
+ doxygen_javadoc_continuation_indent);
+
+ size_t line_count = 0;
+ size_t ccol = pc->column; // the col of subsequent comment lines
+ size_t cmt_idx = 0;
+ bool nl_end = false;
+ bool doxygen_javadoc_indent_align = false;
+ unc_text line;
+
+ /*
+ * Get a map of regex pairs that define expressions to match at both the end
+ * of the previous line and the beginning of the next line
+ */
+ auto &&cmt_reflow_regex_map = get_reflow_fold_regex_map();
+
+ line.clear();
+ LOG_FMT(LCONTTEXT, "%s(%d): pc->Len() is %zu\n",
+ __func__, __LINE__, pc->Len());
+ //LOG_FMT(LCONTTEXT, "%s(%d): pc->str is %s\n",
+ // __func__, __LINE__, pc->str.c_str());
+
+ /**
+ * check for enable/disable processing comment strings that may
+ * both be embedded within the same multi-line comment
+ */
+ auto disable_processing_cmt_idx = find_disable_processing_comment_marker(pc->str);
+ auto enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->str);
+
+ while (cmt_idx < pc->Len())
+ {
+ int ch = pc->str[cmt_idx];
+ cmt_idx++;
+
+ if ( cmt_idx > std::size_t(disable_processing_cmt_idx)
+ && enable_processing_cmt_idx > disable_processing_cmt_idx)
+ {
+ auto length = enable_processing_cmt_idx - disable_processing_cmt_idx;
+ unc_text verbatim_text(pc->str,
+ disable_processing_cmt_idx,
+ length);
+
+ add_text(verbatim_text);
+
+ cmt_idx = enable_processing_cmt_idx;
+
+ /**
+ * check for additional enable/disable processing comment strings that may
+ * both be embedded within the same multi-line comment
+ */
+ disable_processing_cmt_idx = find_disable_processing_comment_marker(pc->str,
+ enable_processing_cmt_idx);
+ enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->str,
+ enable_processing_cmt_idx);
+
+ /**
+ * it's probably necessary to reset the line count to prevent line
+ * continuation characters from being added to the end of the current line
+ */
+ line_count = 0;
+ }
+
+ // handle the CRLF and CR endings. convert both to LF
+ if (ch == '\r')
+ {
+ ch = '\n';
+
+ if ( cmt_idx < pc->Len()
+ && pc->str[cmt_idx] == '\n')
+ {
+ cmt_idx++;
+ }
+ }
+
+ // Find the start column
+ if (line.size() == 0)
+ {
+ nl_end = false;
+
+ if (ch == ' ')
+ {
+ ccol++;
+ continue;
+ }
+ else if (ch == '\t')
+ {
+ log_rule_B("input_tab_size");
+ ccol = calc_next_tab_column(ccol, options::input_tab_size());
+ continue;
+ }
+ else
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d):ch is %d, %c\n", __func__, __LINE__, ch, char(ch));
+ }
+ }
+
+ if ( ch == '@'
+ && options::cmt_align_doxygen_javadoc_tags())
+ {
+ int start_idx = cmt_idx - 1;
+ int end_idx = match_doxygen_javadoc_tag(pc_wstring, start_idx);
+
+ if (end_idx > start_idx)
+ {
+ doxygen_javadoc_indent_align = true;
+
+ std::string match(pc->str.get().cbegin() + start_idx,
+ pc->str.get().cbegin() + end_idx);
+
+ match.erase(std::remove_if(match.begin(),
+ match.end(),
+ ::isspace),
+ match.end());
+
+ /**
+ * remove whitespace before the '@'
+ */
+ int line_size_before_indent = line.size();
+
+ while ( line_size_before_indent > 0
+ && unc_isspace(line.back()))
+ {
+ line.pop_back();
+ --line_size_before_indent;
+ }
+ log_rule_B("cmt_sp_before_doxygen_javadoc_tags");
+
+ int indent = options::cmt_sp_before_doxygen_javadoc_tags();
+
+ while (indent-- > 0)
+ {
+ line.append(' ');
+ }
+ cmt_idx += (end_idx - start_idx);
+ line.append(match.c_str());
+
+ bool is_exception_tag = match.find("@exception") != std::string::npos;
+ bool is_param_tag = match.find("@param") != std::string::npos;
+ bool is_throws_tag = match.find("@throws") != std::string::npos;
+
+ if ( is_exception_tag
+ || is_param_tag
+ || is_throws_tag)
+ {
+ indent = int(doxygen_javadoc_param_name_indent) - int(line.size());
+
+ while (indent-- > -line_size_before_indent)
+ {
+ line.append(' ');
+ }
+
+ while (true)
+ {
+ cmt_idx = eat_line_whitespace(pc->str,
+ cmt_idx);
+
+ while ( cmt_idx < pc->Len()
+ && !unc_isspace(pc->str[cmt_idx])
+ && pc->str[cmt_idx] != ',')
+ {
+ line.append(pc->str[cmt_idx++]);
+ }
+
+ if (!is_param_tag)
+ {
+ break;
+ }
+ /**
+ * check for the possibility that comma-separated parameter names are present
+ */
+ cmt_idx = eat_line_whitespace(pc->str,
+ cmt_idx);
+
+ if (pc->str[cmt_idx] != ',')
+ {
+ break;
+ }
+ ++cmt_idx;
+ line.append(", ");
+ }
+ }
+ cmt_idx = eat_line_whitespace(pc->str,
+ cmt_idx);
+ indent = int(doxygen_javadoc_continuation_indent) - int(line.size());
+
+ while (indent-- > -line_size_before_indent)
+ {
+ line.append(' ');
+ }
+
+ while ( cmt_idx < pc->Len()
+ && !unc_isspace(pc->str[cmt_idx]))
+ {
+ line.append(pc->str[cmt_idx++]);
+ }
+ continue;
+ }
+ }
+ /*
+ * Now see if we need/must fold the next line with the current to enable
+ * full reflow
+ */
+ log_rule_B("cmt_reflow_mode");
+
+ if ( options::cmt_reflow_mode() == 2
+ && ch == '\n'
+ && cmt_idx < pc->Len())
+ {
+ int next_nonempty_line = -1;
+ int prev_nonempty_line = -1;
+ size_t nwidx = line.size();
+
+ // strip trailing whitespace from the line collected so far
+ while (nwidx > 0)
+ {
+ nwidx--;
+
+ if ( prev_nonempty_line < 0
+ && !unc_isspace(line[nwidx])
+ && line[nwidx] != '*' // block comment: skip '*' at end of line
+ && (pc->flags.test(PCF_IN_PREPROC)
+ ? ( line[nwidx] != '\\'
+ || ( line[nwidx + 1] != '\r'
+ && line[nwidx + 1] != '\n'))
+ : true))
+ {
+ prev_nonempty_line = nwidx; // last non-whitespace char in the previous line
+ }
+ }
+
+ for (size_t nxt_idx = cmt_idx;
+ ( nxt_idx < pc->Len()
+ && pc->str[nxt_idx] != '\r'
+ && pc->str[nxt_idx] != '\n');
+ nxt_idx++)
+ {
+ if ( next_nonempty_line < 0
+ && !unc_isspace(pc->str[nxt_idx])
+ && pc->str[nxt_idx] != '*'
+ && (pc->flags.test(PCF_IN_PREPROC)
+ ? ( pc->str[nxt_idx] != '\\'
+ || ( pc->str[nxt_idx + 1] != '\r'
+ && pc->str[nxt_idx + 1] != '\n'))
+ : true))
+ {
+ next_nonempty_line = nxt_idx; // first non-whitespace char in the next line
+ }
+ }
+
+ if ( options::cmt_reflow_indent_to_paragraph_start()
+ && next_nonempty_line >= 0
+ && ( prev_nonempty_line <= 0
+ || doxygen_javadoc_indent_align))
+ {
+ log_rule_B("cmt_reflow_indent_to_paragraph_start");
+
+ int cmt_star_indent = 0;
+
+ while ( next_nonempty_line > cmt_star_indent
+ && pc->str[next_nonempty_line - cmt_star_indent - 1] != '*')
+ {
+ ++cmt_star_indent;
+ }
+ reflow_paragraph_continuation_indent = size_t(cmt_star_indent);
+ }
+
+ /*
+ * see if we should fold up; usually that'd be a YES, but there are a few
+ * situations where folding/reflowing by merging lines is frowned upon:
+ *
+ * - ASCII art in the comments (most often, these are drawings done in +-\/|.,*)
+ *
+ * - Doxygen/JavaDoc/etc. parameters: these often start with \ or @, at least
+ * something clearly non-alphanumeric (you see where we're going with this?)
+ *
+ * - bullet lists that are closely spaced: bullets are always non-alphanumeric
+ * characters, such as '-' or '+' (or, oh horror, '*' - that's bloody ambiguous
+ * to parse :-( ... with or without '*' comment start prefix, that's the
+ * question, then.)
+ *
+ * - semi-HTML formatted code, e.g. <pre>...</pre> comment sections (NDoc, etc.)
+ *
+ * - New lines which form a new paragraph without there having been added an
+ * extra empty line between the last sentence and the new one.
+ * A bit like this, really; so it is opportune to check if the last line ended
+ * in a terminal (that would be the set '.:;!?') and the new line starts with
+ * a capital.
+ * Though new lines starting with comment delimiters, such as '(', should be
+ * pulled up.
+ *
+ * So it bores down to this: the only folding (& reflowing) that's going to happen
+ * is when the next line starts with an alphanumeric character AND the last
+ * line didn't end with an non-alphanumeric character, except: ',' AND the next
+ * line didn't start with a '*' all of a sudden while the previous one didn't
+ * (the ambiguous '*'-for-bullet case!)
+ */
+ if ( prev_nonempty_line >= 0
+ && next_nonempty_line >= int(cmt_idx))
+ {
+ std::wstring prev_line(line.get().cbegin(),
+ line.get().cend());
+ std::wstring next_line(pc->str.get().cbegin() + next_nonempty_line,
+ pc->str.get().cend());
+
+ for (auto &&cmt_reflow_regex_map_entry : cmt_reflow_regex_map)
+ {
+ auto &&cmt_reflow_regex_pair = cmt_reflow_regex_map_entry.second;
+ auto &&end_of_prev_line_regex = cmt_reflow_regex_pair.first;
+ auto &&beg_of_next_line_regex = cmt_reflow_regex_pair.second;
+ std::wsmatch match[2];
+
+ if ( std::regex_search(prev_line, match[0], end_of_prev_line_regex)
+ && match[0].position(0) + match[0].length(0) == std::wsmatch::difference_type(line.size())
+ && std::regex_search(next_line, match[1], beg_of_next_line_regex)
+ && match[1].position(0) == 0)
+ {
+ // rewind the line to the last non-alpha:
+ line.resize(prev_nonempty_line + 1);
+
+ // roll the current line forward to the first non-alpha:
+ cmt_idx = next_nonempty_line;
+ // override the NL and make it a single whitespace:
+ ch = ' ';
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (ch == '\n')
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d):ch is newline\n", __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d):ch is %d, %c\n", __func__, __LINE__, ch, char(ch));
+ }
+ line.append(ch);
+
+ // If we just hit an end of line OR we just hit end-of-comment...
+ if ( ch == '\n'
+ || cmt_idx == pc->Len())
+ {
+ if (ch == '\n')
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d):ch is newline\n", __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d):ch is %d, %c\n", __func__, __LINE__, ch, char(ch));
+ }
+ line_count++;
+ LOG_FMT(LCONTTEXT, "%s(%d):line_count is %zu\n", __func__, __LINE__, line_count);
+
+ // strip trailing tabs and spaces before the newline
+ if (ch == '\n')
+ {
+ nl_end = true;
+ line.pop_back();
+ cmt_trim_whitespace(line, pc->flags.test(PCF_IN_PREPROC));
+ }
+
+ if (line_count == 1)
+ {
+ // this is the first line - add unchanged
+ add_comment_text(line, cmt, false);
+
+ if (nl_end)
+ {
+ add_char('\n');
+ }
+ }
+ else
+ {
+ /*
+ * This is not the first line, so we need to indent to the
+ * correct column. Each line is indented 0 or more spaces.
+ */
+ // Ensure ccol is not negative
+ if (static_cast<int>(ccol) >= col_diff)
+ {
+ ccol -= col_diff;
+ }
+
+ if (ccol < (cmt_col + 3))
+ {
+ ccol = cmt_col + 3;
+ }
+
+ if (line.size() == 0)
+ {
+ // Empty line - just a '\n'
+ log_rule_B("cmt_star_cont");
+
+ if (options::cmt_star_cont())
+ {
+ // The number of spaces to insert at the start of subsequent comment lines.
+ log_rule_B("cmt_sp_before_star_cont");
+ cmt.column = cmt_col + options::cmt_sp_before_star_cont();
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+
+ if (cmt.xtra_indent > 0)
+ {
+ add_char(' ');
+ }
+ // multiline comments can have empty lines with some spaces in them for alignment
+ // while adding * symbol and aligning them we don't want to keep these trailing spaces
+ unc_text tmp = unc_text(cmt.cont_text);
+ cmt_trim_whitespace(tmp, false);
+ add_text(tmp);
+ }
+ add_char('\n');
+ }
+ else
+ {
+ /*
+ * If this doesn't start with a '*' or '|'.
+ * '\name' is a common parameter documentation thing.
+ */
+ log_rule_B("cmt_indent_multi");
+
+ if ( options::cmt_indent_multi()
+ && line[0] != '*'
+ && line[0] != '|'
+ && line[0] != '#'
+ && ( line[0] != '\\'
+ || unc_isalpha(line[1]))
+ && line[0] != '+')
+ {
+ // The number of spaces to insert at the start of subsequent comment lines.
+ log_rule_B("cmt_sp_before_star_cont");
+ size_t start_col = cmt_col + options::cmt_sp_before_star_cont();
+
+ log_rule_B("cmt_star_cont");
+
+ if (options::cmt_star_cont())
+ {
+ cmt.column = start_col;
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+
+ if (cmt.xtra_indent > 0)
+ {
+ add_char(' ');
+ }
+ add_text(cmt.cont_text);
+ // The number of spaces to insert after the star on subsequent comment lines.
+ log_rule_B("cmt_sp_after_star_cont");
+ output_to_column(ccol + options::cmt_sp_after_star_cont(), false);
+ }
+ else
+ {
+ cmt.column = ccol;
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+ }
+ }
+ else
+ {
+ // The number of spaces to insert at the start of subsequent comment lines.
+ log_rule_B("cmt_sp_before_star_cont");
+ cmt.column = cmt_col + options::cmt_sp_before_star_cont();
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+
+ if (cmt.xtra_indent > 0)
+ {
+ add_char(' ');
+ }
+ size_t idx;
+
+ // Checks for and updates the lead chars.
+ // @return 0=not present, >0=number of chars that are part of the lead
+ idx = cmt_parse_lead(line, (cmt_idx == pc->Len()));
+
+ if (idx > 0)
+ {
+ // >0=number of chars that are part of the lead
+ cmt.cont_text.set(line, 0, idx);
+ LOG_CONTTEXT();
+
+ if ( (line.size() >= 2)
+ && (line[0] == '*')
+ && unc_isalnum(line[1]))
+ {
+ line.insert(1, ' ');
+ }
+ }
+ else
+ {
+ // bug #653
+ if (language_is_set(LANG_D))
+ {
+ // 0=no lead char present
+ add_text(cmt.cont_text);
+ }
+ }
+ }
+ size_t continuation_indent = 0;
+
+ if (doxygen_javadoc_indent_align)
+ {
+ continuation_indent = doxygen_javadoc_continuation_indent;
+ }
+ else if (reflow_paragraph_continuation_indent > 0)
+ {
+ continuation_indent = reflow_paragraph_continuation_indent;
+ }
+ add_comment_text(line,
+ cmt,
+ false,
+ continuation_indent);
+
+ if (nl_end)
+ {
+ add_text("\n");
+ }
+ }
+ }
+ line.clear();
+ doxygen_javadoc_indent_align = false;
+ ccol = 1;
+ }
+ }
+} // output_comment_multi
+
+
+static bool kw_fcn_filename(Chunk *cmt, unc_text &out_txt)
+{
+ UNUSED(cmt);
+ out_txt.append(path_basename(cpd.filename.c_str()));
+ return(true);
+}
+
+
+static bool kw_fcn_class(Chunk *cmt, unc_text &out_txt)
+{
+ Chunk *tmp = nullptr;
+
+ if (language_is_set(LANG_CPP | LANG_OC))
+ {
+ Chunk *fcn = get_next_function(cmt);
+
+ if (chunk_is_token(fcn, CT_OC_MSG_DECL))
+ {
+ tmp = get_prev_oc_class(cmt);
+ }
+ else
+ {
+ tmp = get_next_class(cmt);
+ }
+ }
+ else if (language_is_set(LANG_OC))
+ {
+ tmp = get_prev_oc_class(cmt);
+ }
+
+ if (tmp == nullptr)
+ {
+ tmp = get_next_class(cmt);
+ }
+
+ if (tmp != nullptr)
+ {
+ out_txt.append(tmp->str);
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if (tmp->type != CT_DC_MEMBER)
+ {
+ break;
+ }
+ tmp = tmp->GetNext();
+
+ if (tmp->IsNotNullChunk())
+ {
+ out_txt.append("::");
+ out_txt.append(tmp->str);
+ }
+ }
+ return(true);
+ }
+ return(false);
+} // kw_fcn_class
+
+
+static bool kw_fcn_message(Chunk *cmt, unc_text &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (fcn == nullptr)
+ {
+ return(false);
+ }
+ out_txt.append(fcn->str);
+
+ Chunk *tmp = fcn->GetNextNcNnl();
+ Chunk *word = Chunk::NullChunkPtr;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_BRACE_OPEN)
+ || chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if (chunk_is_token(tmp, CT_OC_COLON))
+ {
+ if (word->IsNotNullChunk())
+ {
+ out_txt.append(word->str);
+ word = Chunk::NullChunkPtr;
+ }
+ out_txt.append(":");
+ }
+
+ if (chunk_is_token(tmp, CT_WORD))
+ {
+ word = tmp;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ return(true);
+} // kw_fcn_message
+
+
+static bool kw_fcn_category(Chunk *cmt, unc_text &out_txt)
+{
+ Chunk *category = get_prev_category(cmt);
+
+ if (category)
+ {
+ out_txt.append('(');
+ out_txt.append(category->str);
+ out_txt.append(')');
+ }
+ return(true);
+} // kw_fcn_category
+
+
+static bool kw_fcn_scope(Chunk *cmt, unc_text &out_txt)
+{
+ Chunk *scope = get_next_scope(cmt);
+
+ if (scope)
+ {
+ out_txt.append(scope->str);
+ return(true);
+ }
+ return(false);
+} // kw_fcn_scope
+
+
+static bool kw_fcn_function(Chunk *cmt, unc_text &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (fcn)
+ {
+ if (get_chunk_parent_type(fcn) == CT_OPERATOR)
+ {
+ out_txt.append("operator ");
+ }
+
+ if ( fcn->prev != nullptr
+ && fcn->prev->type == CT_DESTRUCTOR)
+ {
+ out_txt.append('~');
+ }
+ out_txt.append(fcn->str);
+ return(true);
+ }
+ return(false);
+}
+
+
+static bool kw_fcn_javaparam(Chunk *cmt, unc_text &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (fcn == nullptr)
+ {
+ return(false);
+ }
+ Chunk *fpo;
+ Chunk *fpc;
+ bool has_param = true;
+ bool need_nl = false;
+
+ if (chunk_is_token(fcn, CT_OC_MSG_DECL))
+ {
+ Chunk *tmp = fcn->GetNextNcNnl();
+ has_param = false;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_BRACE_OPEN)
+ || chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if (has_param)
+ {
+ if (need_nl)
+ {
+ out_txt.append("\n");
+ }
+ need_nl = true;
+ out_txt.append("@param");
+ out_txt.append(" ");
+ out_txt.append(tmp->str);
+ out_txt.append(" TODO");
+ }
+ has_param = false;
+
+ if (chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ has_param = true;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ fpo = fpc = Chunk::NullChunkPtr;
+ }
+ else
+ {
+ fpo = fcn->GetNextType(CT_FPAREN_OPEN, fcn->level);
+
+ if (fpo->IsNullChunk())
+ {
+ return(true);
+ }
+ fpc = fpo->GetNextType(CT_FPAREN_CLOSE, fcn->level);
+
+ if (fpc->IsNullChunk())
+ {
+ return(true);
+ }
+ }
+ Chunk *tmp;
+
+ // Check for 'foo()' and 'foo(void)'
+ if (fpo->IsNotNullChunk())
+ {
+ if (fpo->GetNextNcNnl() == fpc)
+ {
+ has_param = false;
+ }
+ else
+ {
+ tmp = fpo->GetNextNcNnl();
+
+ if ( (tmp == fpc->GetPrevNcNnl())
+ && chunk_is_str(tmp, "void"))
+ {
+ has_param = false;
+ }
+ }
+ }
+
+ if (has_param)
+ {
+ Chunk *prev = Chunk::NullChunkPtr;
+ tmp = fpo;
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if ( chunk_is_token(tmp, CT_COMMA)
+ || tmp == fpc)
+ {
+ if (need_nl)
+ {
+ out_txt.append("\n");
+ }
+ need_nl = true;
+ out_txt.append("@param");
+
+ if (prev->IsNotNullChunk())
+ {
+ out_txt.append(" ");
+ out_txt.append(prev->str);
+ out_txt.append(" TODO");
+ }
+ prev = Chunk::NullChunkPtr;
+
+ if (tmp == fpc)
+ {
+ break;
+ }
+ }
+
+ if (chunk_is_token(tmp, CT_WORD))
+ {
+ prev = tmp;
+ }
+ }
+ }
+ // Do the return stuff
+ tmp = fcn->GetPrevNcNnl();
+
+ // For Objective-C we need to go to the previous chunk
+ if ( tmp->IsNotNullChunk()
+ && get_chunk_parent_type(tmp) == CT_OC_MSG_DECL
+ && chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && !chunk_is_str(tmp, "void"))
+ {
+ if (need_nl)
+ {
+ out_txt.append("\n");
+ }
+ out_txt.append("@return TODO");
+ }
+ return(true);
+} // kw_fcn_javaparam
+
+
+static bool kw_fcn_fclass(Chunk *cmt, unc_text &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (!fcn)
+ {
+ return(false);
+ }
+
+ if (fcn->flags.test(PCF_IN_CLASS))
+ {
+ // if inside a class, we need to find to the class name
+ Chunk *tmp = fcn->GetPrevType(CT_BRACE_OPEN, fcn->level - 1);
+ tmp = tmp->GetPrevType(CT_CLASS, tmp->level);
+
+ if (tmp->IsNullChunk())
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+ else
+ {
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ while ( tmp->IsNotNullChunk()
+ && chunk_is_token(tmp->GetNextNcNnl(), CT_DC_MEMBER))
+ {
+ tmp = tmp->GetNextNcNnl();
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ out_txt.append(tmp->str);
+ return(true);
+ }
+ }
+ else
+ {
+ // if outside a class, we expect "CLASS::METHOD(...)"
+ Chunk *tmp = fcn->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp, CT_OPERATOR))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && ( chunk_is_token(tmp, CT_DC_MEMBER)
+ || chunk_is_token(tmp, CT_MEMBER)))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ out_txt.append(tmp->str);
+ return(true);
+ }
+ }
+ return(false);
+} // kw_fcn_fclass
+
+
+static bool kw_fcn_year(Chunk *cmt, unc_text &out_txt)
+{
+ UNUSED(cmt);
+ time_t now = time(nullptr);
+
+ out_txt.append(std::to_string(1900 + localtime(&now)->tm_year));
+ return(true);
+}
+
+
+struct kw_subst_t
+{
+ const char *tag;
+ bool (*func)(Chunk *cmt, unc_text &out_txt);
+};
+
+
+static const kw_subst_t kw_subst_table[] =
+{
+ { "$(filename)", kw_fcn_filename },
+ { "$(class)", kw_fcn_class },
+ { "$(message)", kw_fcn_message },
+ { "$(category)", kw_fcn_category },
+ { "$(scope)", kw_fcn_scope },
+ { "$(function)", kw_fcn_function },
+ { "$(javaparam)", kw_fcn_javaparam },
+ { "$(fclass)", kw_fcn_fclass },
+ { "$(year)", kw_fcn_year },
+};
+
+
+static void do_kw_subst(Chunk *pc)
+{
+ for (const auto &kw : kw_subst_table)
+ {
+ int idx = pc->str.find(kw.tag);
+
+ if (idx < 0)
+ {
+ continue;
+ }
+ unc_text tmp_txt;
+ tmp_txt.clear();
+
+ if (kw.func(pc, tmp_txt))
+ {
+ // if the replacement contains '\n' we need to fix the lead
+ if (tmp_txt.find("\n") >= 0)
+ {
+ size_t nl_idx = pc->str.rfind("\n", idx);
+
+ if (nl_idx > 0)
+ {
+ // idx and nl_idx are both positive
+ unc_text nl_txt;
+ nl_txt.append("\n");
+ nl_idx++;
+
+ while ( (nl_idx < static_cast<size_t>(idx))
+ && !unc_isalnum(pc->str[nl_idx]))
+ {
+ nl_txt.append(pc->str[nl_idx++]);
+ }
+ tmp_txt.replace("\n", nl_txt);
+ }
+ }
+ pc->str.replace(kw.tag, tmp_txt);
+ }
+ }
+} // do_kw_subst
+
+
+static void output_comment_multi_simple(Chunk *pc)
+{
+ if ( pc == nullptr
+ && pc->IsNotNullChunk())
+ {
+ return;
+ }
+ cmt_reflow cmt;
+
+ LOG_FMT(LCONTTEXT, "%s(%d): Text() is '%s', type is %s, orig_col is %zu, column is %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type), pc->orig_col, pc->column);
+
+ output_cmt_start(cmt, pc);
+
+ // The multiline comment is saved inside one chunk. If the comment is
+ // shifted all lines of the comment need to be shifted by the same amount.
+ // Save the difference of initial and current position to apply it on every
+ // line_column
+ const int col_diff = [pc]()
+ {
+ int diff = 0;
+
+ if (chunk_is_newline(pc->GetPrev()))
+ {
+ // The comment should be indented correctly
+ diff = pc->column - pc->orig_col;
+ }
+ return(diff);
+ }();
+
+ /**
+ * check for enable/disable processing comment strings that may
+ * both be embedded within the same multi-line comment
+ */
+ auto disable_processing_cmt_idx = find_disable_processing_comment_marker(pc->str);
+ auto enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->str);
+
+ unc_text line;
+ size_t line_count = 0;
+ size_t line_column = pc->column;
+ size_t cmt_idx = 0;
+
+ while (cmt_idx < pc->Len())
+ {
+ int ch = pc->str[cmt_idx];
+ cmt_idx++;
+
+ if ( cmt_idx > std::size_t(disable_processing_cmt_idx)
+ && enable_processing_cmt_idx > disable_processing_cmt_idx)
+ {
+ auto length = enable_processing_cmt_idx - disable_processing_cmt_idx;
+ unc_text verbatim_text(pc->str,
+ disable_processing_cmt_idx,
+ length);
+
+ add_text(verbatim_text);
+
+ cmt_idx = enable_processing_cmt_idx;
+
+ /**
+ * check for additional enable/disable processing comment strings that may
+ * both be embedded within the same multi-line comment
+ */
+ disable_processing_cmt_idx = find_disable_processing_comment_marker(pc->str,
+ enable_processing_cmt_idx);
+ enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->str,
+ enable_processing_cmt_idx);
+
+ line.clear();
+
+ continue;
+ }
+ // 1: step through leading tabs and spaces to find the start column
+ log_rule_B("cmt_convert_tab_to_spaces");
+
+ if ( line.size() == 0
+ && ( line_column < cmt.base_col
+ || options::cmt_convert_tab_to_spaces()))
+ {
+ if (ch == ' ')
+ {
+ line_column++;
+ continue;
+ }
+ else if (ch == '\t')
+ {
+ log_rule_B("input_tab_size");
+ line_column = calc_next_tab_column(line_column, options::input_tab_size());
+ continue;
+ }
+ else
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d):ch is %d, %c\n", __func__, __LINE__, ch, char(ch));
+ }
+ }
+
+ // 2: add chars to line, handle the CRLF and CR endings (convert both to LF)
+ if (ch == '\r')
+ {
+ ch = '\n';
+
+ if ( (cmt_idx < pc->Len())
+ && (pc->str[cmt_idx] == '\n'))
+ {
+ cmt_idx++;
+ }
+ }
+ LOG_FMT(LCONTTEXT, "%s(%d):Line is %s\n", __func__, __LINE__, line.c_str());
+ line.append(ch);
+ LOG_FMT(LCONTTEXT, "%s(%d):Line is %s\n", __func__, __LINE__, line.c_str());
+
+ // If we just hit an end of line OR we just hit end-of-comment...
+ if ( ch == '\n'
+ || cmt_idx == pc->Len())
+ {
+ line_count++;
+ LOG_FMT(LCONTTEXT, "%s(%d):line_count is %zu\n", __func__, __LINE__, line_count);
+
+ // strip trailing tabs and spaces before the newline
+ if (ch == '\n')
+ {
+ line.pop_back();
+
+ // Say we aren't in a preproc to prevent changing any bs-nl
+ cmt_trim_whitespace(line, false);
+
+ line.append('\n');
+ }
+
+ if (line.size() > 0)
+ {
+ // unless line contains only a single newline char, indent if the
+ // line consists of either:
+ if ( line.size() > 1 // more than a single newline char or
+ || ch != '\n') // (end-of-comment) a single non newline char
+ {
+ if (line_count > 1)
+ {
+ // apply comment column shift without underflowing
+ line_column = ( col_diff < 0
+ && (cast_abs(line_column, col_diff) > line_column))
+ ? 0 : line_column + col_diff;
+ }
+ cmt.column = line_column;
+ cmt_output_indent(cmt.brace_col, cmt.base_col, cmt.column);
+ }
+ add_text(line);
+
+ line.clear();
+ }
+ line_column = 1;
+ }
+ }
+} // output_comment_multi_simple
+
+
+static void generate_if_conditional_as_text(unc_text &dst, Chunk *ifdef)
+{
+ int column = -1;
+
+ dst.clear();
+
+ for (Chunk *pc = ifdef; pc != nullptr && pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (column == -1)
+ {
+ column = pc->column;
+ }
+
+ if ( chunk_is_token(pc, CT_NEWLINE)
+ || chunk_is_token(pc, CT_COMMENT_MULTI)
+ || chunk_is_token(pc, CT_COMMENT_CPP))
+ {
+ break;
+ }
+ else if (chunk_is_token(pc, CT_NL_CONT))
+ {
+ dst += ' ';
+ column = -1;
+ }
+ else if ( chunk_is_token(pc, CT_COMMENT)
+ || chunk_is_token(pc, CT_COMMENT_EMBED))
+ {
+ }
+ else // if (chunk_is_token(pc, CT_JUNK)) || else
+ {
+ for (int spacing = pc->column - column; spacing > 0; spacing--)
+ {
+ dst += ' ';
+ column++;
+ }
+
+ dst.append(pc->str);
+ column += pc->Len();
+ }
+ }
+} // generate_if_conditional_as_text
+
+
+void add_long_preprocessor_conditional_block_comment(void)
+{
+ Chunk *pp_start = nullptr;
+ Chunk *pp_end = nullptr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ // just track the preproc level:
+ if (chunk_is_token(pc, CT_PREPROC))
+ {
+ pp_end = pp_start = pc;
+ }
+
+ if ( pc->type != CT_PP_IF
+ || !pp_start)
+ {
+ continue;
+ }
+#if 0
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ continue;
+ }
+#endif
+
+ Chunk *br_close;
+ Chunk *br_open = pc;
+ size_t nl_count = 0;
+
+ Chunk *tmp = pc;
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ // just track the preproc level:
+ if (chunk_is_token(tmp, CT_PREPROC))
+ {
+ pp_end = tmp;
+ }
+
+ if (chunk_is_newline(tmp))
+ {
+ nl_count += tmp->nl_count;
+ }
+ else if ( pp_end->pp_level == pp_start->pp_level
+ && ( chunk_is_token(tmp, CT_PP_ENDIF)
+ || ((chunk_is_token(br_open, CT_PP_IF)) ? (chunk_is_token(tmp, CT_PP_ELSE)) : 0)))
+ {
+ br_close = tmp;
+
+ LOG_FMT(LPPIF, "found #if / %s section on lines %zu and %zu, nl_count=%zu\n",
+ (chunk_is_token(tmp, CT_PP_ENDIF) ? "#endif" : "#else"),
+ br_open->orig_line, br_close->orig_line, nl_count);
+
+ // Found the matching #else or #endif - make sure a newline is next
+ tmp = tmp->GetNext();
+
+ LOG_FMT(LPPIF, "next item type %d (is %s)\n",
+ (tmp ? tmp->type : -1), (tmp ? chunk_is_newline(tmp) ? "newline"
+ : tmp->IsComment() ? "comment" : "other" : "---"));
+
+ if ( tmp->IsNullChunk()
+ || chunk_is_token(tmp, CT_NEWLINE)) // chunk_is_newline(tmp))
+ {
+ size_t nl_min;
+
+ if (chunk_is_token(br_close, CT_PP_ENDIF))
+ {
+ log_rule_B("mod_add_long_ifdef_endif_comment");
+ nl_min = options::mod_add_long_ifdef_endif_comment();
+ }
+ else
+ {
+ log_rule_B("mod_add_long_ifdef_else_comment");
+ nl_min = options::mod_add_long_ifdef_else_comment();
+ }
+ const char *txt = !tmp ? "EOF" : ((chunk_is_token(tmp, CT_PP_ENDIF)) ? "#endif" : "#else");
+ LOG_FMT(LPPIF, "#if / %s section candidate for augmenting when over NL threshold %zu != 0 (nl_count=%zu)\n",
+ txt, nl_min, nl_count);
+
+ if ( nl_min > 0
+ && nl_count > nl_min) // nl_count is 1 too large at all times as #if line was counted too
+ {
+ // determine the added comment style
+ E_Token style = (language_is_set(LANG_CPP)) ?
+ CT_COMMENT_CPP : CT_COMMENT;
+
+ unc_text str;
+ generate_if_conditional_as_text(str, br_open);
+
+ LOG_FMT(LPPIF, "#if / %s section over threshold %zu (nl_count=%zu) --> insert comment after the %s: %s\n",
+ txt, nl_min, nl_count, txt, str.c_str());
+
+ // Add a comment after the close brace
+ insert_comment_after(br_close, style, str);
+ }
+ }
+
+ // checks both the #else and #endif for a given level, only then look further in the main loop
+ if (chunk_is_token(br_close, CT_PP_ENDIF))
+ {
+ break;
+ }
+ }
+ }
+ }
+} // add_long_preprocessor_conditional_block_comment
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.h
new file mode 100644
index 00000000..b3e685d9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/output.h
@@ -0,0 +1,50 @@
+/**
+ * @file output.h
+ * prototypes for output.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef OUTPUT_H_INCLUDED
+#define OUTPUT_H_INCLUDED
+
+#include "unc_text.h"
+
+#include <stdio.h>
+
+
+//! This renders the chunk list to a file.
+void output_parsed(FILE *pfile, bool withOptions = true);
+
+
+//! This renders the chunk list to a file formatted as csv.
+void output_parsed_csv(FILE *pfile);
+
+
+//! This renders the chunk list to a file.
+void output_text(FILE *pfile);
+
+
+//! This save the next formatting step to a file
+void dump_step(const char *filename, const char *description);
+
+
+/**
+ * See also it's preprocessor counterpart
+ * add_long_closebrace_comment
+ * in braces.cpp
+ *
+ * Note: since this concerns itself with the preprocessor -- which is line-oriented --
+ * it turns out that just looking at pc->pp_level is NOT the right thing to do.
+ * See a --parsed dump if you don't believe this: an '#endif' will be one level
+ * UP from the corresponding #ifdef when you look at the tokens 'ifdef' versus 'endif',
+ * but it's a whole another story when you look at their CT_PREPROC ('#') tokens!
+ *
+ * Hence we need to track and seek matching CT_PREPROC pp_levels here, which complicates
+ * things a little bit, but not much.
+ */
+void add_long_preprocessor_conditional_block_comment(void);
+
+
+#endif /* OUTPUT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.cpp
new file mode 100644
index 00000000..7b81175a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.cpp
@@ -0,0 +1,67 @@
+/**
+ * @file parameter_pack_cleanup.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "parameter_pack_cleanup.h"
+
+#include "chunk.h"
+
+
+void parameter_pack_cleanup(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ // look for template
+ if (chunk_is_token(pc, CT_TEMPLATE)) // Issue #3309
+ {
+ Chunk *template_end = pc->GetNextType(CT_SEMICOLON, pc->level);
+
+ // look for a parameter pack
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ if (chunk_is_token(pc, CT_PARAMETER_PACK))
+ {
+ Chunk *parameter_pack = pc;
+
+ // look for a token with the same text
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LTOK, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+
+ if (pc == template_end)
+ {
+ break;
+ }
+
+ if (strcmp(pc->Text(), parameter_pack->Text()) == 0)
+ {
+ set_chunk_type(pc, CT_PARAMETER_PACK);
+ }
+ pc = pc->GetNext();
+ }
+ }
+ pc = pc->GetNext();
+
+ if (pc == template_end)
+ {
+ break;
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+} // parameter_pack_cleanup
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.h
new file mode 100644
index 00000000..97ff6b17
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parameter_pack_cleanup.h
@@ -0,0 +1,15 @@
+/**
+ * @file parameter_pack_cleanup.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef PARAMETER_PACK_CLEANUP_H_INCLUDED
+#define PARAMETER_PACK_CLEANUP_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+void parameter_pack_cleanup(void);
+
+#endif /* PARAMETER_PACK_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.cpp
new file mode 100644
index 00000000..64f65f50
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.cpp
@@ -0,0 +1,349 @@
+/**
+ * @file parens.cpp
+ * Adds or removes parens.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "parens.h"
+
+#include "log_rules.h"
+
+using namespace uncrustify;
+
+
+//! Add an open parenthesis after first and add a close parenthesis before the last
+static void add_parens_between(Chunk *first, Chunk *last);
+
+
+/**
+ * Scans between two parens and adds additional parens if needed.
+ * This function is recursive. If it hits another open paren, it'll call itself
+ * with the new bounds.
+ *
+ * Adds optional parens in an IF or SWITCH conditional statement.
+ *
+ * This basically just checks for a CT_COMPARE that isn't surrounded by parens.
+ * The edges for the compare are the open, close and any CT_BOOL tokens.
+ *
+ * This only handles VERY simple patterns:
+ * (!a && b) => (!a && b) -- no change
+ * (a && b == 1) => (a && (b == 1))
+ * (a == 1 || b > 2) => ((a == 1) || (b > 2))
+ *
+ * FIXME: we really should bail if we transition between a preprocessor and
+ * a non-preprocessor
+ */
+static void check_bool_parens(Chunk *popen, Chunk *pclose, int nest);
+
+
+void do_parens(void)
+{
+ constexpr static auto LCURRENT = LPARADD;
+
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_full_paren_if_bool");
+
+ if (options::mod_full_paren_if_bool())
+ {
+ Chunk *pc = Chunk::GetHead();
+
+ while ( (pc = pc->GetNextNcNnl()) != nullptr
+ && pc->IsNotNullChunk())
+ {
+ if ( pc->type != CT_SPAREN_OPEN
+ || ( get_chunk_parent_type(pc) != CT_IF
+ && get_chunk_parent_type(pc) != CT_ELSEIF
+ && get_chunk_parent_type(pc) != CT_SWITCH))
+ {
+ continue;
+ }
+ // Grab the close sparen
+ Chunk *pclose = pc->GetNextType(CT_SPAREN_CLOSE, pc->level, E_Scope::PREPROC);
+
+ if (pclose->IsNotNullChunk())
+ {
+ check_bool_parens(pc, pclose, 0);
+ pc = pclose;
+ }
+ }
+ }
+} // do_parens
+
+
+void do_parens_assign(void) // Issue #3316
+{
+ constexpr static auto LCURRENT = LPARADD;
+
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_full_paren_assign_bool");
+
+ if (options::mod_full_paren_assign_bool())
+ {
+ Chunk *pc = Chunk::GetHead();
+
+ while ( (pc = pc->GetNextNcNnl()) != nullptr
+ && pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ LOG_FMT(LPARADD, "%s(%d): orig_line is %zu, text is '%s', level is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->Text(), pc->level);
+ // look before for a open sparen
+ size_t check_level = pc->level;
+ Chunk *p = pc->GetPrevNc(E_Scope::PREPROC);
+
+ while (p->IsNotNullChunk())
+ {
+ LOG_FMT(LPARADD, "%s(%d): orig_line is %zu, text is '%s', level is %zu, type is %s\n",
+ __func__, __LINE__, p->orig_line, p->Text(), p->level, get_token_name(p->type));
+
+ //log_pcf_flags(LPARADD, p->flags);
+ if (p->flags.test(PCF_STMT_START))
+ {
+ break;
+ }
+
+ if (chunk_is_token(p, CT_PAREN_OPEN))
+ {
+ check_level--;
+ }
+
+ if (chunk_is_token(p, CT_SPAREN_OPEN))
+ {
+ break;
+ }
+ p = p->GetPrevNc(E_Scope::PREPROC);
+
+ if (p->level < check_level - 1)
+ {
+ break;
+ }
+ }
+ LOG_FMT(LPARADD, "%s(%d): orig_line is %zu, text is '%s', level is %zu, type is %s\n",
+ __func__, __LINE__, p->orig_line, p->Text(), p->level, get_token_name(p->type));
+
+ if (get_chunk_parent_type(p) == CT_WHILE)
+ {
+ continue;
+ }
+ // Grab the semicolon
+ Chunk *semicolon = pc->GetNextType(CT_SEMICOLON, pc->level, E_Scope::PREPROC);
+
+ if (semicolon->IsNotNullChunk())
+ {
+ check_bool_parens(pc, semicolon, 0);
+ pc = semicolon;
+ }
+ }
+ }
+ }
+} // do_parens_assign
+
+
+void do_parens_return(void) // Issue #3316
+{
+ constexpr static auto LCURRENT = LPARADD;
+
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_full_paren_return_bool");
+
+ if (options::mod_full_paren_return_bool())
+ {
+ Chunk *pc = Chunk::GetHead();
+
+ while ( (pc = pc->GetNextNcNnl()) != nullptr
+ && pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_RETURN))
+ {
+ LOG_FMT(LPARADD, "%s(%d): orig_line is %zu, text is '%s', level is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->Text(), pc->level);
+ // look before for a open sparen
+ size_t check_level = pc->level;
+ Chunk *p = pc->GetPrevNc(E_Scope::PREPROC);
+
+ while (p->IsNotNullChunk())
+ {
+ LOG_FMT(LPARADD, "%s(%d): orig_line is %zu, text is '%s', level is %zu, type is %s\n",
+ __func__, __LINE__, p->orig_line, p->Text(), p->level, get_token_name(p->type));
+
+ //log_pcf_flags(LPARADD, p->flags);
+ if (p->flags.test(PCF_STMT_START))
+ {
+ break;
+ }
+
+ if (chunk_is_token(p, CT_PAREN_OPEN))
+ {
+ check_level--;
+ }
+
+ if (chunk_is_token(p, CT_SPAREN_OPEN))
+ {
+ break;
+ }
+ p = p->GetPrevNc(E_Scope::PREPROC);
+
+ if (p->level < check_level - 1)
+ {
+ break;
+ }
+ }
+ LOG_FMT(LPARADD, "%s(%d): orig_line is %zu, text is '%s', level is %zu, type is %s\n",
+ __func__, __LINE__, p->orig_line, p->Text(), p->level, get_token_name(p->type));
+
+ if (get_chunk_parent_type(p) == CT_WHILE)
+ {
+ continue;
+ }
+ // Grab the semicolon
+ Chunk *semicolon = pc->GetNextType(CT_SEMICOLON, pc->level, E_Scope::PREPROC);
+
+ if (semicolon->IsNotNullChunk())
+ {
+ check_bool_parens(pc, semicolon, 0);
+ pc = semicolon;
+ }
+ }
+ }
+ }
+} // do_parens_return
+
+
+static void add_parens_between(Chunk *first, Chunk *last)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LPARADD, "%s(%d): line %zu, between '%s' [lvl is %zu] and '%s' [lvl is %zu]\n",
+ __func__, __LINE__, first->orig_line,
+ first->Text(), first->level,
+ last->Text(), last->level);
+
+ // Don't do anything if we have a bad sequence, ie "&& )"
+ Chunk *first_n = first->GetNextNcNnl();
+
+ if (first_n == last)
+ {
+ return;
+ }
+ Chunk pc;
+
+ set_chunk_type(&pc, CT_PAREN_OPEN);
+ pc.orig_line = first_n->orig_line;
+ pc.orig_col = first_n->orig_col;
+ pc.str = "(";
+ pc.flags = first_n->flags & PCF_COPY_FLAGS;
+ pc.level = first_n->level;
+ pc.pp_level = first_n->pp_level;
+ pc.brace_level = first_n->brace_level;
+
+ chunk_add_before(&pc, first_n);
+
+ Chunk *last_p = last->GetPrevNcNnl(E_Scope::PREPROC);
+
+ set_chunk_type(&pc, CT_PAREN_CLOSE);
+ pc.orig_line = last_p->orig_line;
+ pc.orig_col = last_p->orig_col;
+ pc.str = ")";
+ pc.flags = last_p->flags & PCF_COPY_FLAGS;
+ pc.level = last_p->level;
+ pc.pp_level = last_p->pp_level;
+ pc.brace_level = last_p->brace_level;
+
+ chunk_add_after(&pc, last_p);
+
+ for (Chunk *tmp = first_n;
+ tmp != last_p;
+ tmp = tmp->GetNextNcNnl())
+ {
+ tmp->level++;
+ }
+
+ last_p->level++;
+} // add_parens_between
+
+
+static void check_bool_parens(Chunk *popen, Chunk *pclose, int nest)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *ref = popen;
+ bool hit_compare = false;
+
+ LOG_FMT(LPARADD, "%s(%d): nest is %d, popen on line %zu, orig_col is %zu, pclose on line %zu, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, nest,
+ popen->orig_line, popen->orig_col,
+ pclose->orig_line, pclose->orig_col,
+ popen->level);
+
+ Chunk *pc = popen;
+
+ while ( (pc = pc->GetNextNcNnl()) != nullptr
+ && pc->IsNotNullChunk()
+ && pc != pclose)
+ {
+ if (pc->flags.test(PCF_IN_PREPROC))
+ {
+ LOG_FMT(LPARADD2, " -- bail on PP %s [%s] at line %zu col %zu, level %zu\n",
+ get_token_name(pc->type),
+ pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+ return;
+ }
+
+ if ( chunk_is_token(pc, CT_BOOL)
+ || chunk_is_token(pc, CT_QUESTION)
+ || chunk_is_token(pc, CT_COND_COLON)
+ || chunk_is_token(pc, CT_COMMA))
+ {
+ LOG_FMT(LPARADD2, " -- %s [%s] at line %zu col %zu, level %zu\n",
+ get_token_name(pc->type),
+ pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+
+ if (hit_compare)
+ {
+ hit_compare = false;
+
+ if (!language_is_set(LANG_CS))
+ {
+ add_parens_between(ref, pc);
+ }
+ }
+ ref = pc;
+ }
+ else if (chunk_is_token(pc, CT_COMPARE))
+ {
+ LOG_FMT(LPARADD2, " -- compare '%s' at line %zu, orig_col is %zu, level is %zu\n",
+ pc->Text(), pc->orig_line, pc->orig_col, pc->level);
+ hit_compare = true;
+ }
+ else if (chunk_is_paren_open(pc))
+ {
+ Chunk *next = chunk_skip_to_match(pc);
+
+ if (next != nullptr)
+ {
+ check_bool_parens(pc, next, nest + 1);
+ pc = next;
+ }
+ }
+ else if ( chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_SQUARE_OPEN)
+ || chunk_is_token(pc, CT_ANGLE_OPEN))
+ {
+ // Skip [], {}, and <>
+ pc = chunk_skip_to_match(pc);
+ }
+ }
+
+ if ( hit_compare
+ && ref != popen
+ && !language_is_set(LANG_CS))
+ {
+ add_parens_between(ref, pclose);
+ }
+} // check_bool_parens
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.h
new file mode 100644
index 00000000..0c961529
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parens.h
@@ -0,0 +1,24 @@
+/**
+ * @file parens.h
+ * prototypes for parens.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef PARENS_H_INCLUDED
+#define PARENS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+//! add parenthesis
+void do_parens(void);
+
+
+void do_parens_assign(void);
+
+
+void do_parens_return(void);
+
+
+#endif /* PARENS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.cpp
new file mode 100644
index 00000000..3ed93ef2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.cpp
@@ -0,0 +1,54 @@
+/**
+ * @file parent_for_pp.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "parent_for_pp.h"
+
+#include "chunk.h"
+
+
+void do_parent_for_pp(void)
+{
+ LOG_FUNC_ENTRY();
+
+ vector<Chunk *> viz;
+
+ Chunk *pc = Chunk::GetHead()->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ // CT_PP_IF, // #if, #ifdef, or #ifndef
+ // CT_PP_ELSE, // #else or #elif
+ // CT_PP_ENDIF, // #endif
+ if (chunk_is_token(pc, CT_PP_IF))
+ {
+ LOG_FMT(LMCB, "%s(%d): IF: orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_pcf_flags(LMCB, pc->flags);
+ viz.push_back(pc);
+ }
+ else if (chunk_is_token(pc, CT_PP_ELSE))
+ {
+ LOG_FMT(LMCB, "%s(%d): ELSE: orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_pcf_flags(LMCB, pc->flags);
+ size_t level = pc->pp_level;
+ Chunk *a = viz.at(level - 1);
+ chunk_set_parent(pc, a);
+ }
+ else if (chunk_is_token(pc, CT_PP_ENDIF))
+ {
+ LOG_FMT(LMCB, "%s(%d): ENDIF: orig_line %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_pcf_flags(LMCB, pc->flags);
+ size_t level = pc->pp_level;
+ Chunk *a = viz.at(level);
+ chunk_set_parent(pc, a);
+ viz.pop_back();
+ }
+ pc = pc->GetNextNcNnl();
+ }
+} // do_parent_for_pp
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.h
new file mode 100644
index 00000000..cb069680
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/parent_for_pp.h
@@ -0,0 +1,17 @@
+/**
+ * @file parent_for_pp.h
+ * prototype for parent_for_pp.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef PARENT_FOR_PP_H_INCLUDED
+#define PARENT_FOR_PP_H_INCLUDED
+
+
+// mark the parent
+void do_parent_for_pp(void);
+
+
+#endif /* PARENT_FOR_PP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.cpp
new file mode 100644
index 00000000..0a22bf72
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.cpp
@@ -0,0 +1,105 @@
+/**
+ * @file pcf_flags.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "pcf_flags.h"
+
+static const char *pcf_names[] =
+{
+ "IN_PREPROC", // 0
+ "IN_STRUCT", // 1
+ "IN_ENUM", // 2
+ "IN_FCN_DEF", // 3
+ "IN_FCN_CALL", // 4
+ "IN_SPAREN", // 5
+ "IN_TEMPLATE", // 6
+ "IN_TYPEDEF", // 7
+ "IN_CONST_ARGS", // 8
+ "IN_ARRAY_ASSIGN", // 9
+ "IN_CLASS", // 10
+ "IN_CLASS_BASE", // 11
+ "IN_NAMESPACE", // 12
+ "IN_FOR", // 13
+ "IN_OC_MSG", // 14
+ "IN_WHERE_SPEC", // 15
+ "IN_DECLTYPE", // 16
+ "FORCE_SPACE", // 17
+ "STMT_START", // 18
+ "EXPR_START", // 19
+ "DONT_INDENT", // 20
+ "ALIGN_START", // 21
+ "WAS_ALIGNED", // 22
+ "VAR_TYPE", // 23
+ "VAR_DEF", // 24
+ "VAR_1ST", // 25
+ "VAR_INLINE", // 26
+ "RIGHT_COMMENT", // 27
+ "OLD_FCN_PARAMS", // 28
+ "LVALUE", // 29
+ "ONE_LINER", // 30
+ "EMPTY_BODY", // 31
+ "ANCHOR", // 32
+ "PUNCTUATOR", // 33
+ "INSERTED", // 34
+ "LONG_BLOCK", // 35
+ "OC_BOXED", // 36
+ "KEEP_BRACE", // 37
+ "OC_RTYPE", // 38
+ "OC_ATYPE", // 39
+ "WF_ENDIF", // 40
+ "IN_QT_MACRO", // 41
+ "IN_FCN_CTOR", // 42 Issue #2152
+ "IN_TRY_BLOCK", // 43 Issue #1734
+ "INCOMPLETE", // 44
+ "IN_LAMBDA", // 45
+ "WF_IF", // 46
+};
+
+
+std::string pcf_flags_str(pcf_flags_t flags)
+{
+ char buffer[64];
+
+ // Generate hex representation first
+#ifdef WIN32
+ snprintf(buffer, 63, "[");
+#else // not WIN32
+ snprintf(buffer, 63, "[0x%llx:", (long long unsigned int)(flags));
+#endif // ifdef WIN32
+
+ // Add human-readable names
+ auto out = std::string{ buffer };
+ auto first = true;
+
+ for (size_t i = 0; i < ARRAY_SIZE(pcf_names); ++i)
+ {
+ if (flags & static_cast<pcf_flag_e>(pcf_bit(i)))
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ out += ',';
+ }
+ out += pcf_names[i];
+ }
+ }
+
+ out += ']';
+ return(out);
+}
+
+
+void log_pcf_flags(log_sev_t sev, pcf_flags_t flags)
+{
+ if (!log_sev_on(sev))
+ {
+ return;
+ }
+ log_fmt(sev, "%s\n", pcf_flags_str(flags).c_str());
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.h
new file mode 100644
index 00000000..f0c7bbd5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/pcf_flags.h
@@ -0,0 +1,96 @@
+/**
+ * @file pcf_flags.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef PCF_FLAGS_STR_INCLUDED
+#define PCF_FLAGS_STR_INCLUDED
+
+#include "enum_flags.h"
+#include "logger.h"
+
+// and the ever-so-important array size macro
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+using namespace std;
+
+
+constexpr auto pcf_bit(size_t b) -> decltype(0ULL)
+{
+ return(1ULL << b);
+}
+
+enum pcf_flag_e : decltype ( 0ULL )
+{
+// Copy flags are in the lower 17 bits
+ PCF_NONE = 0ULL,
+ PCF_COPY_FLAGS = 0x0001ffffULL,
+ PCF_IN_PREPROC = pcf_bit(0), //! in a preprocessor
+ PCF_IN_STRUCT = pcf_bit(1), //! in a struct
+ PCF_IN_ENUM = pcf_bit(2), //! in enum
+ PCF_IN_FCN_DEF = pcf_bit(3), //! inside function def parens
+ PCF_IN_FCN_CALL = pcf_bit(4), //! inside function call parens
+ PCF_IN_SPAREN = pcf_bit(5), //! inside for/if/while/switch parens
+ PCF_IN_TEMPLATE = pcf_bit(6),
+ PCF_IN_TYPEDEF = pcf_bit(7),
+ PCF_IN_CONST_ARGS = pcf_bit(8),
+ PCF_IN_ARRAY_ASSIGN = pcf_bit(9),
+ PCF_IN_CLASS = pcf_bit(10),
+ PCF_IN_CLASS_BASE = pcf_bit(11),
+ PCF_IN_NAMESPACE = pcf_bit(12),
+ PCF_IN_FOR = pcf_bit(13),
+ PCF_IN_OC_MSG = pcf_bit(14),
+ PCF_IN_WHERE_SPEC = pcf_bit(15), /* inside C# 'where' constraint clause on class or function def */
+ PCF_IN_DECLTYPE = pcf_bit(16),
+
+// Non-Copy flags are in the upper 47 bits
+ PCF_FORCE_SPACE = pcf_bit(17), //! must have a space after this token
+ PCF_STMT_START = pcf_bit(18), //! marks the start of a statement
+ PCF_EXPR_START = pcf_bit(19),
+ PCF_DONT_INDENT = pcf_bit(20), //! already aligned!
+ PCF_ALIGN_START = pcf_bit(21),
+ PCF_WAS_ALIGNED = pcf_bit(22),
+ PCF_VAR_TYPE = pcf_bit(23), //! part of a variable def type
+ PCF_VAR_DEF = pcf_bit(24), //! variable name in a variable def
+ PCF_VAR_1ST = pcf_bit(25), //! 1st variable def in a statement
+ PCF_VAR_1ST_DEF = (PCF_VAR_DEF | PCF_VAR_1ST),
+ PCF_VAR_INLINE = pcf_bit(26), //! type was an inline struct/enum/union
+ PCF_RIGHT_COMMENT = pcf_bit(27),
+ PCF_OLD_FCN_PARAMS = pcf_bit(28),
+ PCF_LVALUE = pcf_bit(29), //! left of assignment
+ PCF_ONE_LINER = pcf_bit(30),
+ PCF_ONE_CLASS = (PCF_ONE_LINER | PCF_IN_CLASS),
+ PCF_EMPTY_BODY = pcf_bit(31),
+ PCF_ANCHOR = pcf_bit(32), //! aligning anchor
+ PCF_PUNCTUATOR = pcf_bit(33),
+ PCF_INSERTED = pcf_bit(34), //! chunk was inserted from another file
+ PCF_LONG_BLOCK = pcf_bit(35), //! the block is 'long' by some measure
+ PCF_OC_BOXED = pcf_bit(36), //! inside OC boxed expression
+ PCF_KEEP_BRACE = pcf_bit(37), //! do not remove brace
+ PCF_OC_RTYPE = pcf_bit(38), //! inside OC return type
+ PCF_OC_ATYPE = pcf_bit(39), //! inside OC arg type
+ PCF_WF_ENDIF = pcf_bit(40), //! #endif for whole file ifdef
+ PCF_IN_QT_MACRO = pcf_bit(41), //! in a QT-macro, i.e. SIGNAL, SLOT
+ PCF_IN_FCN_CTOR = pcf_bit(42), //! inside function constructor
+ PCF_IN_TRY_BLOCK = pcf_bit(43), //! inside Function-try-block
+ PCF_INCOMPLETE = pcf_bit(44), //! class/struct forward declaration
+ PCF_IN_LAMBDA = pcf_bit(45), //! inside a lambda expression
+ PCF_WF_IF = pcf_bit(46), //! #if for a whole file ifdef
+ PCF_NOT_POSSIBLE = pcf_bit(47), //! it is not possible to make an one_liner
+ //! because the line would be too long
+};
+
+UNC_DECLARE_FLAGS(pcf_flags_t, pcf_flag_e);
+UNC_DECLARE_OPERATORS_FOR_FLAGS(pcf_flags_t);
+
+std::string pcf_flags_str(pcf_flags_t flags);
+
+
+void log_pcf_flags(log_sev_t sev, pcf_flags_t flags);
+
+
+#endif /* PCF_FLAGS_STR_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/prototypes.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/prototypes.h
new file mode 100644
index 00000000..55fe35b6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/prototypes.h
@@ -0,0 +1,64 @@
+/**
+ * @file prototypes.h
+ * Big jumble of prototypes used in Uncrustify.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef C_PARSE_PROTOTYPES_H_INCLUDED
+#define C_PARSE_PROTOTYPES_H_INCLUDED
+
+#include "chunk.h"
+#include "log_rules.h"
+#include "uncrustify_types.h"
+
+#include <deque>
+#include <string>
+
+
+/**
+ * Advances to the next tab stop.
+ * Column 1 is the left-most column.
+ *
+ * @param col The current column
+ * @param tabsize The tabsize
+ * @return the next tabstop column
+ */
+static inline size_t calc_next_tab_column(size_t col, size_t tabsize)
+{
+ if (col == 0)
+ {
+ col = 1;
+ }
+
+ if (cpd.frag_cols > 0)
+ {
+ col += cpd.frag_cols - 1;
+ }
+ col = 1 + ((((col - 1) / tabsize) + 1) * tabsize);
+
+ if (cpd.frag_cols > 0)
+ {
+ col -= cpd.frag_cols - 1;
+ }
+ return(col);
+}
+
+
+/**
+ * Advances to the next tab stop for output.
+ *
+ * @param col The current column
+ * @return the next tabstop column
+ */
+static inline size_t next_tab_column(size_t col)
+{
+ constexpr static auto LCURRENT = LINDENT;
+
+ log_rule_B("output_tab_size");
+ return(calc_next_tab_column(col, uncrustify::options::output_tab_size()));
+}
+
+
+#endif /* C_PARSE_PROTOTYPES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.cpp
new file mode 100644
index 00000000..6c9c41f4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.cpp
@@ -0,0 +1,85 @@
+/**
+ * @file punctuators.cpp
+ * Manages the table of punctuators.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "punctuators.h"
+
+//#include "log_rules.h"
+#include "prototypes.h"
+
+#include <algorithm>
+
+constexpr static auto LCURRENT = LOTHER;
+
+using namespace std;
+using namespace uncrustify;
+
+
+/**
+ *
+ * The file "punctuator_table.h" was generated by punc.py from this file.
+ * If you change one of the below symbol tables, re-run punc.py.
+ * $ python scripts/punc.py > src/punctuator_table.h
+ * now automatically with CMakeLists.txt
+ *
+ * NOTE: the tables below do not need to be sorted.
+ */
+
+#include "symbols_table.h"
+// must be positioned here, after all symbolsX[], because punc_table uses them
+#include "punctuator_table.h"
+
+
+const chunk_tag_t *find_punctuator(const char *str, int lang_flags)
+{
+ if ( str == nullptr
+ || str[0] == '\0')
+ {
+ return(nullptr);
+ }
+ const auto binary_find = [](const lookup_entry_t *first, const lookup_entry_t *last, const char &value)
+ {
+ const auto tmp = std::lower_bound(first, last, value,
+ lookup_entry_t::comperator());
+
+ return((value == tmp->ch) ? tmp : nullptr);
+ };
+
+ const chunk_tag_t *match = nullptr;
+ const auto *parent = punc_table; //!< graph in table form, initially point at first entry
+ auto ch_idx = int{};
+
+ while ( ch_idx < 6
+ && str[ch_idx] != '\0') //!< symbols6: max punc len = 6
+ {
+ // search for next parent node in all current child nodes
+ parent = binary_find(parent, next(parent, parent->left_in_group), str[ch_idx]);
+
+ if (parent == nullptr)
+ {
+ break; // no nodes found with the searched char
+ }
+ log_rule_B("enable_digraphs");
+
+ if ( parent->tag != nullptr
+ && (parent->tag->lang_flags & lang_flags) != 0 // punctuator lang and processing lang match
+ && ( (parent->tag->lang_flags & FLAG_DIG) == 0 // punctuator is not a di/tri-graph
+ || options::enable_digraphs())) // or di/tri-graph processing is enabled
+ {
+ match = parent->tag;
+ }
+
+ if (parent->next_idx == 0)
+ {
+ break; // no child nodes, leaf reached
+ }
+ parent = &punc_table[parent->next_idx]; // point at the first child node
+ ch_idx++;
+ continue;
+ }
+ return(match);
+} // find_punctuator
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.h
new file mode 100644
index 00000000..ed4c3fa5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/punctuators.h
@@ -0,0 +1,52 @@
+/**
+ * @file punctuators.h
+ */
+
+#ifndef PUNCTUATORS_H_INCLUDED
+#define PUNCTUATORS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+struct lookup_entry_t
+{
+ char ch;
+ char left_in_group;
+ UINT16 next_idx;
+ const chunk_tag_t *tag;
+
+ struct comperator
+ {
+ static char get_char(const lookup_entry_t &v)
+ {
+ return(v.ch);
+ }
+
+
+ static char get_char(char t)
+ {
+ return(t);
+ }
+
+ template<typename T1, typename T2>
+ bool operator()(T1 const &t1, T2 const &t2)
+ {
+ return(get_char(t1) < get_char(t2));
+ }
+ };
+};
+
+
+/**
+ * Checks if the first max. 6 chars of a given string match a punctuator
+ *
+ * @param str string that will be checked, can be shorter than 6 chars
+ * @param lang_flags specifies from which language punctuators will be considered
+ *
+ * @retval chunk tag of the found punctuator
+ * @retval nullptr if nothing found
+ */
+const chunk_tag_t *find_punctuator(const char *str, int lang_flags);
+
+
+#endif /* PUNCTUATORS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.cpp
new file mode 100644
index 00000000..45dd3943
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.cpp
@@ -0,0 +1,53 @@
+/**
+ * @file quick_align_again.cpp
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "quick_align_again.h"
+
+#include "align_stack.h"
+#include "chunk.h"
+
+
+void quick_align_again(void)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ char copy[1000];
+ LOG_FMT(LALAGAIN, "%s(%d): orig_line is %zu, orig_col is %zu, column is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->column, pc->ElidedText(copy));
+
+ if ( pc->align.next != nullptr
+ && pc->flags.test(PCF_ALIGN_START))
+ {
+ AlignStack as;
+ as.Start(100, 0);
+ as.m_right_align = pc->align.right_align;
+ as.m_star_style = static_cast<AlignStack::StarStyle>(pc->align.star_style);
+ as.m_amp_style = static_cast<AlignStack::StarStyle>(pc->align.amp_style);
+ as.m_gap = pc->align.gap;
+
+ LOG_FMT(LALAGAIN, "%s(%d): pc->Text() is '%s', orig_line is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+ as.Add(pc->align.start);
+ chunk_flags_set(pc, PCF_WAS_ALIGNED);
+
+ for (Chunk *tmp = pc->align.next; tmp != nullptr; tmp = tmp->align.next)
+ {
+ chunk_flags_set(tmp, PCF_WAS_ALIGNED);
+ as.Add(tmp->align.start);
+ LOG_FMT(LALAGAIN, "%s(%d): => tmp->Text() is '%s', orig_line is %zu\n",
+ __func__, __LINE__, tmp->Text(), tmp->orig_line);
+ }
+
+ LOG_FMT(LALAGAIN, "\n");
+ as.End();
+ }
+ }
+} // quick_align_again
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.h
new file mode 100644
index 00000000..b31a450a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/quick_align_again.h
@@ -0,0 +1,17 @@
+/**
+ * @file quick_align_again.h
+ *
+ * @author Guy Maurel
+ * split from align.cpp
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef QUICK_ALIGN_AGAIN_H_INCLUDED
+#define QUICK_ALIGN_AGAIN_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+void quick_align_again(void);
+
+#endif /* QUICK_ALIGN_AGAIN_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.cpp
new file mode 100644
index 00000000..90cf0abb
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.cpp
@@ -0,0 +1,94 @@
+/**
+ * @file remove_duplicate_include.cpp
+ *
+ * @author Guy Maurel
+ * October 2015, 2016
+ * @license GPL v2+
+ */
+
+#include "remove_duplicate_include.h"
+
+#include "chunk.h"
+#include "uncrustify.h"
+
+using std::vector;
+
+
+void remove_duplicate_include(void)
+{
+ LOG_FUNC_ENTRY();
+
+ vector<Chunk *> includes;
+
+ Chunk *preproc = Chunk::NullChunkPtr;
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ //LOG_FMT(LRMRETURN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s, parent_type is %s\n",
+ // __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ // get_token_name(pc->type), get_token_name(pc->parent_type));
+
+ if (chunk_is_token(pc, CT_PREPROC))
+ {
+ preproc = pc;
+ }
+ else if (chunk_is_token(pc, CT_PP_INCLUDE))
+ {
+ Chunk *next = pc->GetNext();
+
+ //LOG_FMT(LRMRETURN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s, parent_type is %s\n",
+ // __func__, __LINE__, next->orig_line, next->orig_col, next->Text(),
+ // get_token_name(next->type), get_token_name(next->parent_type));
+ if (includes.empty())
+ {
+ includes.push_back(next);
+ // goto next newline
+ pc = next->GetNextNl();
+ }
+ else
+ {
+ //LOG_FMT(LRMRETURN, "%s(%d): size is %zu\n",
+ // __func__, __LINE__, includes.size());
+ // look for duplicate
+ auto ite = includes.end();
+
+ for (auto itc = includes.begin(); itc != ite; ++itc)
+ {
+ Chunk *current = *itc;
+
+ //LOG_FMT(LRMRETURN, "%s(%d): next->Text() is '%s'\n",
+ // __func__, __LINE__, next->Text());
+ //LOG_FMT(LRMRETURN, "%s(%d): current->Text() is '%s'\n",
+ // __func__, __LINE__, current->Text());
+ if (std::strcmp(next->Text(), current->Text()) == 0)
+ {
+ // erase the statement
+ Chunk *temp = pc;
+ Chunk *comment = next->GetNext();
+ Chunk *eol = next->GetNextNl();
+ pc = preproc->GetPrev();
+ chunk_del(preproc);
+ chunk_del(temp);
+ chunk_del(next);
+
+ if (comment != eol)
+ {
+ chunk_del(comment);
+ }
+ chunk_del(eol);
+ break;
+ }
+ else
+ {
+ // goto next newline
+ pc = next->GetNextNl();
+ // and still look for duplicate
+ }
+ } // for (auto itc = includes.begin();
+ } // if (includes.empty())
+ } // else if (chunk_is_token(pc, CT_PP_INCLUDE))
+ // get the next token
+ pc = pc->GetNext();
+ }
+} // remove_duplicate_include
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.h
new file mode 100644
index 00000000..a7ade094
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_duplicate_include.h
@@ -0,0 +1,20 @@
+/**
+ * @file remove_duplicate_include.h
+ * prototypes for remove_duplicate_include.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef REMOVE_DUPLICATE_INCLUDE_H_INCLUDED
+#define REMOVE_DUPLICATE_INCLUDE_H_INCLUDED
+
+#include "chunk.h"
+
+/**
+ * @brief Remove duplicate include
+ */
+void remove_duplicate_include(void);
+
+
+#endif /* REMOVE_DUPLICATE_INCLUDE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.cpp
new file mode 100644
index 00000000..6fe4d6f0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.cpp
@@ -0,0 +1,84 @@
+/**
+ * @file remove_extra_returns.cpp
+ *
+ * @author Guy Maurel
+ * October 2015, 2016
+ * @license GPL v2+
+ * extract from combine.cpp
+ */
+
+#include "remove_extra_returns.h"
+
+#include "chunk.h"
+#include "uncrustify.h"
+
+
+void remove_extra_returns(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LRMRETURN, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s', type is %s, parent_type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(),
+ get_token_name(pc->type), get_token_name(pc->parent_type));
+
+ if ( chunk_is_token(pc, CT_RETURN)
+ && !pc->flags.test(PCF_IN_PREPROC))
+ {
+ // we might be in a class, check it Issue #2705
+ // look for a closing brace
+ bool remove_it = false;
+ Chunk *closing_brace = pc->GetNextType(CT_BRACE_CLOSE, 1);
+ LOG_FMT(LRMRETURN, "%s(%d): on orig_line %zu, level is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->level);
+
+ if (closing_brace->IsNotNullChunk())
+ {
+ if (get_chunk_parent_type(closing_brace) == CT_FUNC_CLASS_DEF)
+ {
+ // we have a class. Do nothing
+ }
+ else if ( get_chunk_parent_type(closing_brace) == CT_FUNC_DEF
+ && pc->level < 2)
+ {
+ remove_it = true;
+ }
+ }
+ else
+ {
+ // it is not a class
+ // look for a closing brace
+ closing_brace = pc->GetNextType(CT_BRACE_CLOSE, 0);
+ LOG_FMT(LRMRETURN, "%s(%d): on orig_line %zu, level is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->level);
+
+ if (closing_brace->IsNotNullChunk())
+ {
+ if (get_chunk_parent_type(closing_brace) == CT_FUNC_DEF)
+ {
+ remove_it = true;
+ }
+ }
+ }
+
+ if (remove_it)
+ {
+ Chunk *semicolon = pc->GetNextNcNnl();
+
+ if ( semicolon->IsNotNullChunk()
+ && chunk_is_token(semicolon, CT_SEMICOLON))
+ {
+ LOG_FMT(LRMRETURN, "%s(%d): Removed 'return;' on orig_line %zu\n",
+ __func__, __LINE__, pc->orig_line);
+ chunk_del(pc);
+ chunk_del(semicolon);
+ pc = closing_brace;
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+} // remove_extra_returns
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.h
new file mode 100644
index 00000000..df0974c9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/remove_extra_returns.h
@@ -0,0 +1,21 @@
+/**
+ * @file remove_extra_returns.h
+ * prototypes for remove_extra_returns.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ * extract from combine.h
+ */
+
+#ifndef REMOVE_EXTRA_RETURNS_H_INCLUDED
+#define REMOVE_EXTRA_RETURNS_H_INCLUDED
+
+
+/**
+ * @brief Remove unnecessary returns
+ * that is remove 'return;' that appears as the last statement in a function
+ */
+void remove_extra_returns(void);
+
+
+#endif /* REMOVE_EXTRA_RETURNS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.cpp
new file mode 100644
index 00000000..6f78099c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.cpp
@@ -0,0 +1,125 @@
+/**
+ * @file semicolons.cpp
+ * Removes extra semicolons
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "semicolons.h"
+
+#include "prototypes.h"
+
+
+static void remove_semicolon(Chunk *pc);
+
+
+/**
+ * We are on a semicolon that is after an unidentified brace close.
+ * Check for what is before the brace open.
+ * Do not remove if it is a square close, word, type, or paren close.
+ */
+static void check_unknown_brace_close(Chunk *semi, Chunk *brace_close);
+
+
+static void remove_semicolon(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LDELSEMI, "%s(%d): Removed semicolon: orig_line is %zu, orig_col is %zu",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_func_stack_inline(LDELSEMI);
+ // TODO: do we want to shift stuff back a column?
+ chunk_del(pc);
+}
+
+
+void remove_extra_semicolons(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ Chunk *next = pc->GetNextNcNnl();
+ Chunk *prev;
+
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ && !pc->flags.test(PCF_IN_PREPROC)
+ && (prev = pc->GetPrevNcNnl())->IsNotNullChunk())
+ {
+ LOG_FMT(LSCANSEMI, "%s(%d): Semi orig_line is %zu, orig_col is %zu, parent is %s, prev = '%s' [%s/%s]\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, get_token_name(get_chunk_parent_type(pc)),
+ prev->Text(),
+ get_token_name(prev->type), get_token_name(get_chunk_parent_type(prev)));
+
+ if (get_chunk_parent_type(pc) == CT_TYPEDEF)
+ {
+ // keep it
+ }
+ else if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && ( get_chunk_parent_type(prev) == CT_IF
+ || get_chunk_parent_type(prev) == CT_ELSEIF
+ || get_chunk_parent_type(prev) == CT_ELSE
+ || get_chunk_parent_type(prev) == CT_SWITCH
+ || get_chunk_parent_type(prev) == CT_WHILE
+ || get_chunk_parent_type(prev) == CT_USING_STMT
+ || get_chunk_parent_type(prev) == CT_FOR
+ || get_chunk_parent_type(prev) == CT_FUNC_DEF
+ || get_chunk_parent_type(prev) == CT_OC_MSG_DECL
+ || get_chunk_parent_type(prev) == CT_FUNC_CLASS_DEF
+ || get_chunk_parent_type(prev) == CT_NAMESPACE))
+ {
+ remove_semicolon(pc);
+ }
+ else if ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(prev) == CT_NONE)
+ {
+ check_unknown_brace_close(pc, prev);
+ }
+ else if ( chunk_is_token(prev, CT_SEMICOLON)
+ && get_chunk_parent_type(prev) != CT_FOR)
+ {
+ remove_semicolon(pc);
+ }
+ else if ( language_is_set(LANG_D)
+ && ( get_chunk_parent_type(prev) == CT_ENUM
+ || get_chunk_parent_type(prev) == CT_UNION
+ || get_chunk_parent_type(prev) == CT_STRUCT))
+ {
+ remove_semicolon(pc);
+ }
+ else if ( language_is_set(LANG_JAVA)
+ && get_chunk_parent_type(prev) == CT_SYNCHRONIZED)
+ {
+ remove_semicolon(pc);
+ }
+ else if (chunk_is_token(prev, CT_BRACE_OPEN))
+ {
+ remove_semicolon(pc);
+ }
+ }
+ pc = next;
+ }
+} // remove_extra_semicolons
+
+
+static void check_unknown_brace_close(Chunk *semi, Chunk *brace_close)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = brace_close->GetPrevType(CT_BRACE_OPEN, brace_close->level);
+
+ pc = pc->GetPrevNcNnl();
+
+ if ( pc->IsNotNullChunk()
+ && pc->type != CT_RETURN
+ && pc->type != CT_WORD
+ && pc->type != CT_TYPE
+ && pc->type != CT_SQUARE_CLOSE
+ && pc->type != CT_ANGLE_CLOSE
+ && pc->type != CT_TSQUARE
+ && !chunk_is_paren_close(pc))
+ {
+ remove_semicolon(semi);
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.h
new file mode 100644
index 00000000..c0542a76
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/semicolons.h
@@ -0,0 +1,26 @@
+/**
+ * @file semicolons.h
+ * prototypes for semicolons.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef SEMICOLONS_H_INCLUDED
+#define SEMICOLONS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * Removes superfluous semicolons:
+ * - after brace close whose parent is IF, ELSE, SWITCH, WHILE, FOR, NAMESPACE
+ * - after another semicolon where parent is not FOR
+ * - (D) after brace close whose parent is ENUM/STRUCT/UNION
+ * - (Java) after brace close whose parent is SYNCHRONIZED
+ * - after an open brace
+ * - when not in a #DEFINE
+ */
+void remove_extra_semicolons(void);
+
+
+#endif /* SEMICOLONS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.cpp
new file mode 100644
index 00000000..888569f2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.cpp
@@ -0,0 +1,700 @@
+/**
+ * @file sorting.cpp
+ * Sorts chunks and imports
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "sorting.h"
+
+#include "newlines.h"
+#include "prototypes.h"
+
+#include <regex>
+
+constexpr static auto LCURRENT = LSORT;
+
+using namespace uncrustify;
+
+Option<std::string> *include_category_options[] =
+{
+ &options::include_category_0,
+ &options::include_category_1,
+ &options::include_category_2,
+};
+constexpr static int kIncludeCategoriesCount = 3;
+
+
+struct include_category
+{
+ include_category(const std::string &pattern)
+ : regex(pattern)
+ {
+ }
+ std::regex regex;
+};
+
+
+include_category *include_categories[kIncludeCategoriesCount];
+
+
+/**
+ * Compare two series of chunks, starting with the given ones.
+ * @param pc1 first instance to compare
+ * @param pc2 second instance to compare
+ * @param tcare take care of case (lower case/ upper case) Issue #2091
+ *
+ * @retval == 0 both text elements are equal
+ * @retval > 0
+ * @retval < 0
+ */
+static int compare_chunks(Chunk *pc1, Chunk *pc2, bool tcare = false);
+
+
+/**
+ * Sorting should be pretty rare and should usually only include a few chunks.
+ * We need to minimize the number of swaps, as those are expensive.
+ * So, we do a min sort.
+ */
+static void do_the_sort(Chunk **chunks, size_t num_chunks);
+
+
+#define MARK_CHANGE() mark_change(__func__, __LINE__)
+
+
+static void mark_change(const char *func, size_t line)
+{
+ LOG_FUNC_ENTRY();
+ cpd.changes++;
+
+ if (cpd.pass_count == 0)
+ {
+ LOG_FMT(LCHANGE, "%s(%d): change %d on %s:%zu\n",
+ __func__, __LINE__, cpd.changes, func, line);
+ }
+}
+
+
+static void prepare_categories()
+{
+ for (int i = 0; i < kIncludeCategoriesCount; ++i)
+ {
+ const auto &cat_pattern = (*include_category_options[i])();
+
+ if (!cat_pattern.empty())
+ {
+ include_categories[i] = new include_category(cat_pattern);
+ }
+ else
+ {
+ include_categories[i] = nullptr;
+ }
+ }
+}
+
+
+static void cleanup_categories()
+{
+ for (auto &include_category : include_categories)
+ {
+ if (include_category == nullptr)
+ {
+ continue;
+ }
+ delete include_category;
+ include_category = NULL;
+ }
+}
+
+
+static int get_chunk_priority(Chunk *pc)
+{
+ for (int i = 0; i < kIncludeCategoriesCount; i++)
+ {
+ if (include_categories[i] != nullptr)
+ {
+ if (std::regex_match(pc->Text(), include_categories[i]->regex))
+ {
+ return(i);
+ }
+ }
+ }
+
+ return(kIncludeCategoriesCount);
+}
+
+
+/**
+ * Returns true if the text contains filename without extension.
+ */
+static bool text_contains_filename_without_ext(const char *text)
+{
+ std::string filepath = cpd.filename;
+ size_t slash_idx = filepath.find_last_of("/\\");
+ std::string filename_without_ext = filepath;
+
+ if ( slash_idx != std::string::npos
+ && slash_idx < (filepath.size() - 1))
+ {
+ std::string filename = filepath.substr(slash_idx + 1);
+ size_t dot_idx = filename.find_last_of('.');
+ filename_without_ext = filename.substr(0, dot_idx);
+ }
+ const std::regex special_chars = std::regex(R"([-[\]{}()*+?.,\^$|#\s])");
+ const std::string sanitized_filename = std::regex_replace(filename_without_ext, special_chars, R"(\$&)");
+ const std::regex filename_pattern = std::regex("\\S?" + sanitized_filename + "\\b.*");
+
+ return(std::regex_match(text, filename_pattern));
+}
+
+
+/**
+ * Get chunk text without the extension.
+ */
+static unc_text get_text_without_ext(const unc_text &chunk_text)
+{
+ unc_text result = chunk_text;
+ int idx = result.rfind(".", result.size() - 1);
+
+ if (idx == -1)
+ {
+ return(result);
+ }
+ result.erase(idx, result.size() - idx);
+ return(result);
+}
+
+
+/**
+ * Returns true if unc_text has "." which implies extension.
+ */
+static bool has_dot(const unc_text &chunk_text)
+{
+ int idx = chunk_text.rfind(".", chunk_text.size() - 1);
+
+ return(idx != -1);
+}
+
+
+/**
+ * Returns chunk string required for sorting.
+ */
+static unc_text chunk_sort_str(Chunk *pc)
+{
+ if (get_chunk_parent_type(pc) == CT_PP_INCLUDE)
+ {
+ return(unc_text{ pc->str, 0, pc->Len() - 1 });
+ }
+ return(pc->str);
+}
+
+
+//! Compare two chunks
+static int compare_chunks(Chunk *pc1, Chunk *pc2, bool tcare)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSORT, "%s(%d): @begin pc1->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc1->Len(), pc1->orig_line, pc1->orig_col);
+ LOG_FMT(LSORT, "%s(%d): @begin pc2->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc2->Len(), pc2->orig_line, pc2->orig_col);
+
+ if (pc1 == pc2) // same chunk is always identical thus return 0 differences
+ {
+ return(0);
+ }
+
+ while ( pc1->IsNotNullChunk()
+ && pc2->IsNotNullChunk())
+ {
+ auto const &s1_ext = chunk_sort_str(pc1);
+ auto const &s2_ext = chunk_sort_str(pc2);
+
+ log_rule_B("mod_sort_incl_import_ignore_extension");
+ auto const &s1 = (options::mod_sort_incl_import_ignore_extension()) ? get_text_without_ext(s1_ext) : s1_ext;
+ auto const &s2 = (options::mod_sort_incl_import_ignore_extension()) ? get_text_without_ext(s2_ext) : s2_ext;
+ log_rule_B("mod_sort_incl_import_prioritize_filename");
+
+ if (options::mod_sort_incl_import_prioritize_filename())
+ {
+ bool s1_contains_filename = text_contains_filename_without_ext(s1.c_str());
+ bool s2_contains_filename = text_contains_filename_without_ext(s2.c_str());
+
+ if ( s1_contains_filename
+ && !s2_contains_filename)
+ {
+ return(-1);
+ }
+ else if ( !s1_contains_filename
+ && s2_contains_filename)
+ {
+ return(1);
+ }
+ }
+
+ if (options::mod_sort_incl_import_prioritize_extensionless())
+ {
+ log_rule_B("mod_sort_incl_import_prioritize_extensionless");
+ const bool s1_has_dot = has_dot(s1_ext);
+ const bool s2_has_dot = has_dot(s2_ext);
+
+ if ( s1_has_dot
+ && !s2_has_dot)
+ {
+ return(1);
+ }
+ else if ( !s1_has_dot
+ && s2_has_dot)
+ {
+ return(-1);
+ }
+ }
+
+ if (options::mod_sort_incl_import_prioritize_angle_over_quotes())
+ {
+ log_rule_B("mod_sort_incl_import_prioritize_angle_over_quotes");
+
+ if ( s1.startswith("<")
+ && s2.startswith("\""))
+ {
+ return(-1);
+ }
+ else if ( s1.startswith("\"")
+ && s2.startswith("<"))
+ {
+ return(1);
+ }
+ }
+ int ppc1 = get_chunk_priority(pc1);
+ int ppc2 = get_chunk_priority(pc2);
+
+ if (ppc1 != ppc2)
+ {
+ return(ppc1 - ppc2);
+ }
+ LOG_FMT(LSORT, "%s(%d): text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc1->Text(), pc1->Len(), pc1->orig_line, pc1->orig_col);
+ LOG_FMT(LSORT, "%s(%d): text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc2->Text(), pc2->Len(), pc2->orig_line, pc2->orig_col);
+
+ int ret_val = unc_text::compare(s1, s2, std::min(s1.size(), s2.size()), tcare);
+ LOG_FMT(LSORT, "%s(%d): ret_val is %d\n",
+ __func__, __LINE__, ret_val);
+
+ if (ret_val != 0)
+ {
+ return(ret_val);
+ }
+
+ if (pc1->Len() != pc2->Len())
+ {
+ return(pc1->Len() - pc2->Len());
+ }
+ // Same word, same length. Step to the next chunk.
+ pc1 = pc1->GetNext();
+ LOG_FMT(LSORT, "%s(%d): text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc1->Text(), pc1->Len(), pc1->orig_line, pc1->orig_col);
+
+ if (chunk_is_token(pc1, CT_MEMBER))
+ {
+ pc1 = pc1->GetNext();
+ LOG_FMT(LSORT, "%s(%d): text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc1->Text(), pc1->Len(), pc1->orig_line, pc1->orig_col);
+ }
+ pc2 = pc2->GetNext();
+ LOG_FMT(LSORT, "%s(%d): text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc2->Text(), pc2->Len(), pc2->orig_line, pc2->orig_col);
+
+ if (chunk_is_token(pc2, CT_MEMBER))
+ {
+ pc2 = pc2->GetNext();
+ LOG_FMT(LSORT, "%s(%d): text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc2->Text(), pc2->Len(), pc2->orig_line, pc2->orig_col);
+ }
+ LOG_FMT(LSORT, "%s(%d): >>>text is %s, pc1->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc1->Text(), pc1->Len(), pc1->orig_line, pc1->orig_col);
+ LOG_FMT(LSORT, "%s(%d): >>>text is %s, pc2->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc2->Text(), pc2->Len(), pc2->orig_line, pc2->orig_col);
+
+ // If we hit a newline or nullptr, we are done
+ if ( pc1->IsNullChunk()
+ || chunk_is_newline(pc1)
+ || pc2->IsNullChunk()
+ || chunk_is_newline(pc2))
+ {
+ break;
+ }
+ }
+
+ if ( pc1->IsNullChunk()
+ || !chunk_is_newline(pc2))
+ {
+ return(-1);
+ }
+
+ if (!chunk_is_newline(pc1))
+ {
+ return(1);
+ }
+ return(0);
+} // compare_chunks
+
+
+/**
+ * Sorting should be pretty rare and should usually only include a few chunks.
+ * We need to minimize the number of swaps, as those are expensive.
+ * So, we do a min sort.
+ */
+static void do_the_sort(Chunk **chunks, size_t num_chunks)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LSORT, "%s(%d): %zu chunks:",
+ __func__, __LINE__, num_chunks);
+
+ for (size_t idx = 0; idx < num_chunks; idx++)
+ {
+ LOG_FMT(LSORT, " [%s]", chunks[idx]->Text());
+ }
+
+ LOG_FMT(LSORT, "\n");
+
+ size_t start_idx;
+
+ log_rule_B("mod_sort_case_sensitive");
+ bool take_care = options::mod_sort_case_sensitive(); // Issue #2091
+
+ for (start_idx = 0; start_idx < (num_chunks - 1); start_idx++)
+ {
+ // Find the index of the minimum value
+ size_t min_idx = start_idx;
+
+ for (size_t idx = start_idx + 1; idx < num_chunks; idx++)
+ {
+ if (compare_chunks(chunks[idx], chunks[min_idx], take_care) < 0) // Issue #2091
+ {
+ min_idx = idx;
+ }
+ }
+
+ // Swap the lines if the minimum isn't the first entry
+ if (min_idx != start_idx)
+ {
+ chunk_swap_lines(chunks[start_idx], chunks[min_idx]);
+ log_rule_B("mod_sort_incl_import_grouping_enabled");
+
+ if (options::mod_sort_incl_import_grouping_enabled())
+ {
+ Chunk *pc = chunks[min_idx];
+ chunks[min_idx] = chunks[start_idx];
+ chunks[start_idx] = pc;
+ }
+ else
+ {
+ // Don't need to swap, since we only want the side-effects
+ chunks[min_idx] = chunks[start_idx];
+ }
+ }
+ }
+} // do_the_sort
+
+
+/**
+ * Remove blank lines between chunks.
+ */
+static void remove_blank_lines_between_imports(Chunk **chunks, size_t num_chunks)
+{
+ LOG_FUNC_ENTRY();
+
+ if (num_chunks < 2)
+ {
+ return;
+ }
+
+ for (size_t idx = 0; idx < (num_chunks - 1); idx++)
+ {
+ Chunk *chunk1 = chunks[idx]->GetNextNl();
+ chunk1->nl_count = 1;
+ MARK_CHANGE();
+ }
+}
+
+
+/**
+ * Delete chunks on line having chunk.
+ */
+static void delete_chunks_on_line_having_chunk(Chunk *chunk)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = chunk_first_on_line(chunk);
+
+ while ( pc != nullptr
+ && pc->IsNotNullChunk()
+ && !pc->IsComment())
+ {
+ Chunk *next_pc = pc->GetNext();
+ LOG_FMT(LCHUNK, "%s(%d): Removed '%s' on orig_line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line);
+
+ if (chunk_is_newline(pc))
+ {
+ chunk_del(pc);
+ break;
+ }
+ else
+ {
+ chunk_del(pc);
+ }
+ pc = next_pc;
+ }
+}
+
+
+/**
+ * Dedupe import/include directives.
+ */
+static void dedupe_imports(Chunk **chunks, size_t num_chunks)
+{
+ LOG_FUNC_ENTRY();
+ log_rule_B("mod_sort_case_sensitive");
+
+ for (size_t idx = 1; idx < num_chunks; idx++)
+ {
+ auto const &s1 = chunk_sort_str(chunks[idx - 1]);
+ auto const &s2 = chunk_sort_str(chunks[idx]);
+
+ if (s1.size() != s2.size())
+ {
+ continue;
+ }
+ int ret_val = unc_text::compare(s1, s2, std::min(s1.size(), s2.size()), options::mod_sort_case_sensitive());
+
+ if (ret_val == 0)
+ {
+ delete_chunks_on_line_having_chunk(chunks[idx - 1]);
+ }
+ }
+}
+
+
+/**
+ * Add blank line before the chunk.
+ */
+static void blankline_add_before(Chunk *pc)
+{
+ Chunk *newline = newline_add_before(chunk_first_on_line(pc));
+
+ if (newline->nl_count < 2)
+ {
+ double_newline(newline);
+ }
+}
+
+
+/**
+ * Group imports.
+ */
+static void group_imports_by_adding_newlines(Chunk **chunks, size_t num_chunks)
+{
+ LOG_FUNC_ENTRY();
+
+ // Group imports based on first character, typically quote or angle.
+ int c_idx = -1;
+ int c_idx_last = -1;
+
+ for (size_t idx = 0; idx < num_chunks; idx++)
+ {
+ if (chunks[idx]->str.size() > 0)
+ {
+ c_idx = chunks[idx]->str.at(0);
+ }
+ else
+ {
+ c_idx = -1;
+ }
+
+ if ( c_idx_last != c_idx
+ && idx > 0)
+ {
+ blankline_add_before(chunks[idx]);
+ }
+ c_idx_last = c_idx;
+ }
+
+ // Group imports based on having extension.
+ bool chunk_has_dot = false;
+ bool chunk_last_has_dot = false;
+
+ for (size_t idx = 0; idx < num_chunks; idx++)
+ {
+ chunk_has_dot = has_dot(chunks[idx]->str);
+
+ if ( chunk_last_has_dot != chunk_has_dot
+ && idx > 0)
+ {
+ blankline_add_before(chunks[idx]);
+ }
+ chunk_last_has_dot = chunk_has_dot;
+ }
+
+ // Group imports based on priority defined by config.
+ int chunk_pri = -1;
+ int chunk_pri_last = -1;
+
+ for (size_t idx = 0; idx < num_chunks; idx++)
+ {
+ chunk_pri = get_chunk_priority(chunks[idx]);
+
+ if ( chunk_pri_last != chunk_pri
+ && idx > 0)
+ {
+ blankline_add_before(chunks[idx]);
+ }
+ chunk_pri_last = chunk_pri;
+ }
+
+ // Group imports that contain filename pattern.
+ bool chunk_has_filename = false;
+ bool last_chunk_has_filename = false;
+
+ for (size_t idx = 0; idx < num_chunks; idx++)
+ {
+ auto const &chunk_text = chunk_sort_str(chunks[idx]);
+ chunk_has_filename = text_contains_filename_without_ext(chunk_text.c_str());
+
+ if ( !chunk_has_filename
+ && last_chunk_has_filename)
+ {
+ blankline_add_before(chunks[idx]);
+ }
+ last_chunk_has_filename = chunk_has_filename;
+ }
+} // group_imports_by_adding_newlines
+
+
+void sort_imports(void)
+{
+ LOG_FUNC_ENTRY();
+ const int max_number_to_sort = 1024;
+ const int max_lines_to_check_for_sort_after_include = 128;
+ const int max_gap_threshold_between_include_to_sort = 32;
+
+ Chunk *chunks[max_number_to_sort];
+ size_t num_chunks = 0;
+ Chunk *p_last = nullptr;
+ Chunk *p_imp = nullptr;
+ Chunk *p_imp_last = nullptr;
+
+ prepare_categories();
+
+ Chunk *pc = Chunk::GetHead();
+
+ log_rule_B("mod_sort_incl_import_grouping_enabled");
+
+ while (pc->IsNotNullChunk())
+ {
+ // Simple optimization to limit the sorting. Any MAX_LINES_TO_CHECK_AFTER_INCLUDE lines after last
+ // import is seen are ignore from sorting.
+ if ( options::mod_sort_incl_import_grouping_enabled()
+ && p_imp_last != nullptr
+ && (pc->orig_line - p_imp_last->orig_line) > max_lines_to_check_for_sort_after_include)
+ {
+ break;
+ }
+ Chunk *next = pc->GetNext();
+
+ if (chunk_is_newline(pc))
+ {
+ bool did_import = false;
+
+ if ( p_imp != nullptr
+ && p_imp->IsNotNullChunk()
+ && p_last != nullptr
+ && ( chunk_is_token(p_last, CT_SEMICOLON)
+ || p_imp->flags.test(PCF_IN_PREPROC)))
+ {
+ if (num_chunks < max_number_to_sort)
+ {
+ LOG_FMT(LSORT, "%s(%d): p_imp is %s\n",
+ __func__, __LINE__, p_imp->Text());
+ chunks[num_chunks++] = p_imp;
+ }
+ else
+ {
+ fprintf(stderr, "Number of 'import' to be sorted is too big for the current value %d.\n", max_number_to_sort);
+ fprintf(stderr, "Please make a report.\n");
+ log_flush(true);
+ cpd.error_count++;
+ exit(2);
+ }
+ did_import = true;
+ }
+ log_rule_B("mod_sort_incl_import_grouping_enabled");
+
+ if ( !did_import
+ || ( !options::mod_sort_incl_import_grouping_enabled()
+ && pc->nl_count > 1)
+ || ( options::mod_sort_incl_import_grouping_enabled()
+ && p_imp_last != nullptr
+ && (pc->orig_line - p_imp_last->orig_line) > max_gap_threshold_between_include_to_sort)
+ || next->IsNullChunk())
+ {
+ if (num_chunks > 1)
+ {
+ log_rule_B("mod_sort_incl_import_grouping_enabled");
+
+ if (options::mod_sort_incl_import_grouping_enabled())
+ {
+ remove_blank_lines_between_imports(chunks, num_chunks);
+ do_the_sort(chunks, num_chunks);
+ group_imports_by_adding_newlines(chunks, num_chunks);
+ dedupe_imports(chunks, num_chunks);
+ }
+ else
+ {
+ do_the_sort(chunks, num_chunks);
+ }
+ }
+ num_chunks = 0;
+ }
+ p_imp_last = p_imp;
+ p_imp = nullptr;
+ p_last = nullptr;
+ }
+ else if (chunk_is_token(pc, CT_IMPORT))
+ {
+ log_rule_B("mod_sort_import");
+
+ if (options::mod_sort_import())
+ {
+ p_imp = pc->GetNext();
+ }
+ }
+ else if (chunk_is_token(pc, CT_USING))
+ {
+ log_rule_B("mod_sort_using");
+
+ if (options::mod_sort_using())
+ {
+ p_imp = pc->GetNext();
+ }
+ }
+ else if (chunk_is_token(pc, CT_PP_INCLUDE))
+ {
+ log_rule_B("mod_sort_include");
+
+ if (options::mod_sort_include())
+ {
+ p_imp = pc->GetNext();
+ p_last = pc;
+ }
+ }
+ else if (!pc->IsComment())
+ {
+ p_last = pc;
+ }
+ pc = next;
+ }
+ cleanup_categories();
+} // sort_imports
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.h
new file mode 100644
index 00000000..5d767824
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/sorting.h
@@ -0,0 +1,24 @@
+/**
+ * @file sorting.h
+ * prototypes for sorting.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef SORTING_H_INCLUDED
+#define SORTING_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+/**
+ * alphabetically sort the #include or #import
+ * statements of a file
+ *
+ * @todo better use a chunk pointer parameter
+ * instead of a global variable
+ */
+void sort_imports(void);
+
+
+#endif /* SORTING_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.cpp
new file mode 100644
index 00000000..e907d1ef
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.cpp
@@ -0,0 +1,3841 @@
+/**
+ * @file space.cpp
+ * Adds or removes inter-chunk spaces.
+ *
+ * Informations
+ * "Ignore" means do not change it.
+ * "Add" in the context of spaces means make sure there is at least 1.
+ * "Add" elsewhere means make sure one is present.
+ * "Remove" mean remove the space/brace/newline/etc.
+ * "Force" in the context of spaces means ensure that there is exactly 1.
+ * "Force" in other contexts means the same as "add".
+ *
+ * Rmk: spaces = space + nl
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel, 2015-2021
+ * @license GPL v2+
+ */
+
+#include "space.h"
+
+#include "log_rules.h"
+#include "options_for_QT.h"
+#include "punctuators.h"
+
+#ifdef WIN32
+#include <algorithm> // to get max
+#endif // ifdef WIN32
+
+using namespace std;
+using namespace uncrustify;
+
+
+/**
+ * Decides how to change inter-chunk spacing.
+ * Note that the order of the if statements is VERY important.
+ *
+ * @param first The first chunk
+ * @param second The second chunk
+ *
+ * @return IARF_IGNORE, IARF_ADD, IARF_REMOVE or IARF_FORCE
+ */
+static iarf_e do_space(Chunk *first, Chunk *second, int &min_sp);
+
+/**
+ * Ensure to force the space between the \a first and the \a second chunks
+ * if the PCF_FORCE_SPACE flag is set in the \a first.
+ *
+ * @param first The first chunk
+ * @param second The second chunk
+ * @param av Av from the do_space()
+ *
+ * @return IARF_IGNORE, IARF_ADD, IARF_REMOVE or IARF_FORCE
+ */
+static iarf_e ensure_force_space(Chunk *first, Chunk *second, iarf_e av);
+
+//! type that stores two chunks between those no space shall occur
+struct no_space_table_t
+{
+ E_Token first; //! first chunk
+ E_Token second; //! second chunk
+};
+
+
+/**
+ * this table lists out all combos where a space MUST be present
+ * CT_UNKNOWN is a wildcard.
+ *
+ * TODO: some of these are no longer needed.
+ */
+const no_space_table_t add_space_table[] =
+{
+#include "add_space_table.h"
+};
+
+
+/**
+ * this table lists out all combos where a space should NOT be present
+ * CT_UNKNOWN is a wildcard.
+ *
+ * TODO: some of these are no longer needed.
+ */
+const no_space_table_t no_space_table[] =
+{
+ { CT_OC_AT, CT_UNKNOWN },
+ { CT_INCDEC_BEFORE, CT_WORD },
+ { CT_UNKNOWN, CT_INCDEC_AFTER },
+ { CT_UNKNOWN, CT_LABEL_COLON },
+ { CT_UNKNOWN, CT_ACCESS_COLON },
+ { CT_UNKNOWN, CT_SEMICOLON },
+ { CT_UNKNOWN, CT_D_TEMPLATE },
+ { CT_D_TEMPLATE, CT_UNKNOWN },
+ { CT_MACRO_FUNC, CT_FPAREN_OPEN },
+ { CT_PAREN_OPEN, CT_UNKNOWN },
+ { CT_UNKNOWN, CT_PAREN_CLOSE },
+ { CT_FPAREN_OPEN, CT_UNKNOWN },
+ { CT_UNKNOWN, CT_SPAREN_CLOSE },
+ { CT_SPAREN_OPEN, CT_UNKNOWN },
+ { CT_UNKNOWN, CT_FPAREN_CLOSE },
+ { CT_UNKNOWN, CT_COMMA },
+ { CT_POS, CT_UNKNOWN },
+ { CT_STAR, CT_UNKNOWN },
+ { CT_VBRACE_CLOSE, CT_UNKNOWN },
+ { CT_VBRACE_OPEN, CT_UNKNOWN },
+ { CT_UNKNOWN, CT_VBRACE_CLOSE },
+ { CT_UNKNOWN, CT_VBRACE_OPEN },
+ { CT_PREPROC, CT_UNKNOWN },
+ { CT_PREPROC_INDENT, CT_UNKNOWN },
+ { CT_NEG, CT_UNKNOWN },
+ { CT_UNKNOWN, CT_SQUARE_OPEN },
+ { CT_UNKNOWN, CT_SQUARE_CLOSE },
+ { CT_SQUARE_OPEN, CT_UNKNOWN },
+ { CT_PAREN_CLOSE, CT_WORD },
+ { CT_PAREN_CLOSE, CT_FUNC_DEF },
+ { CT_PAREN_CLOSE, CT_FUNC_CALL },
+ { CT_PAREN_CLOSE, CT_ADDR },
+ { CT_PAREN_CLOSE, CT_FPAREN_OPEN },
+ { CT_OC_SEL_NAME, CT_OC_SEL_NAME },
+ { CT_TYPENAME, CT_TYPE },
+};
+
+
+bool token_is_within_trailing_return(Chunk *pc)
+{
+ // look back for '->' type is TRAILING_RET
+ // until CT_FPAREN_CLOSE
+ // or CT_FPAREN_OPEN is found
+ Chunk *prev = pc;
+
+ if (prev == nullptr)
+ {
+ prev = Chunk::NullChunkPtr;
+ }
+
+ while (prev->IsNotNullChunk())
+ {
+ if (chunk_is_token(prev, CT_TRAILING_RET))
+ {
+ return(true);
+ }
+ else if ( chunk_is_token(prev, CT_FPAREN_CLOSE)
+ || chunk_is_token(prev, CT_FPAREN_OPEN))
+ {
+ return(false);
+ }
+ else
+ {
+ prev = prev->GetPrev();
+ }
+ }
+ return(false);
+} // token_is_within_trailing_return
+
+
+/*
+ * this function is called for every chunk in the input file.
+ * Thus it is important to keep this function efficient
+ */
+static iarf_e do_space(Chunk *first, Chunk *second, int &min_sp)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LSPACE, "%s(%d): orig_line is %zu, orig_col is %zu, first->Text() '%s', type is %s\n",
+ __func__, __LINE__, first->orig_line, first->orig_col, first->Text(), get_token_name(first->type));
+
+ min_sp = 1;
+
+ if ( chunk_is_token(first, CT_IGNORED)
+ || chunk_is_token(second, CT_IGNORED))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( chunk_is_token(first, CT_PP_IGNORE)
+ && chunk_is_token(second, CT_PP_IGNORE))
+ {
+ // Leave spacing alone between PP_IGNORE tokens as we don't want the default behavior (which is ADD).
+ log_rule("PP_IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ if ( chunk_is_token(first, CT_PP)
+ || chunk_is_token(second, CT_PP))
+ {
+ // Add or remove space around preprocessor '##' concatenation operator.
+ log_rule("sp_pp_concat");
+ return(options::sp_pp_concat());
+ }
+
+ if (chunk_is_token(first, CT_POUND))
+ {
+ // Add or remove space after preprocessor '#' stringify operator.
+ // Also affects the '#@' charizing operator.
+ log_rule("sp_pp_stringify");
+ return(options::sp_pp_stringify());
+ }
+
+ if ( chunk_is_token(second, CT_POUND)
+ && second->flags.test(PCF_IN_PREPROC)
+ && get_chunk_parent_type(first) != CT_MACRO_FUNC)
+ {
+ // Add or remove space before preprocessor '#' stringify operator
+ // as in '#define x(y) L#y'.
+ log_rule("sp_before_pp_stringify");
+ return(options::sp_before_pp_stringify());
+ }
+
+ if ( chunk_is_token(first, CT_SPACE)
+ || chunk_is_token(second, CT_SPACE))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(first, CT_DECLSPEC)) // Issue 1289
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( chunk_is_token(second, CT_NEWLINE)
+ || chunk_is_token(second, CT_VBRACE_OPEN))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( chunk_is_token(first, CT_VBRACE_OPEN)
+ && second->type != CT_NL_CONT
+ && second->type != CT_SEMICOLON) // # Issue 1158
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( chunk_is_token(first, CT_VBRACE_CLOSE)
+ && second->type != CT_NL_CONT)
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(second, CT_VSEMICOLON))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(first, CT_MACRO_FUNC))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(second, CT_NL_CONT))
+ {
+ // Add or remove space before a backslash-newline at the end of a line.
+ log_rule("sp_before_nl_cont");
+ return(options::sp_before_nl_cont());
+ }
+
+ if ( language_is_set(LANG_D)
+ && ( chunk_is_token(first, CT_D_ARRAY_COLON)
+ || chunk_is_token(second, CT_D_ARRAY_COLON)))
+ {
+ // (D) Add or remove around the D named array initializer ':' operator.
+ log_rule("sp_d_array_colon");
+ return(options::sp_d_array_colon());
+ }
+
+ if ( chunk_is_token(first, CT_CASE)
+ && (( CharTable::IsKw1(second->str[0])
+ || chunk_is_token(second, CT_NUMBER))))
+ {
+ // Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make
+ // sense here.
+ log_rule("sp_case_label");
+ return(options::sp_case_label() | IARF_ADD);
+ }
+
+ if (chunk_is_token(first, CT_FOR_COLON))
+ {
+ // java
+ // Add or remove space after ':' in a Java/C++11 range-based 'for',
+ // as in 'for (Type var : expr)'.
+ log_rule("sp_after_for_colon");
+ return(options::sp_after_for_colon());
+ }
+
+ if (chunk_is_token(second, CT_FOR_COLON))
+ {
+ // java
+ // Add or remove space before ':' in a Java/C++11 range-based 'for',
+ // as in 'for (Type var : expr)'.
+ log_rule("sp_before_for_colon");
+ return(options::sp_before_for_colon());
+ }
+
+ if ( chunk_is_token(first, CT_QUESTION)
+ && chunk_is_token(second, CT_COND_COLON))
+ {
+ // In the abbreviated ternary form '(a ?: b)', add or remove space between '?'
+ // and ':'.
+ // Overrides all other sp_cond_* options.
+ log_rule("sp_cond_ternary_short");
+ return(options::sp_cond_ternary_short());
+ }
+
+ if ( chunk_is_token(first, CT_QUESTION) // see the tests cpp:34513-34516
+ || chunk_is_token(second, CT_QUESTION))
+ {
+ if ( chunk_is_token(second, CT_QUESTION)
+ && (options::sp_cond_question_before() != IARF_IGNORE))
+ {
+ // Add or remove space before the '?' in 'b ? t : f'.
+ // Overrides sp_cond_question.
+ log_rule("sp_cond_question_before");
+ return(options::sp_cond_question_before());
+ }
+
+ if ( chunk_is_token(first, CT_QUESTION)
+ && (options::sp_cond_question_after() != IARF_IGNORE))
+ {
+ // Add or remove space after the '?' in 'b ? t : f'.
+ // Overrides sp_cond_question.
+ log_rule("sp_cond_question_after");
+ return(options::sp_cond_question_after());
+ }
+ log_rule("sp_cond_question");
+ return(options::sp_cond_question());
+ }
+
+ if ( chunk_is_token(first, CT_COND_COLON)
+ || chunk_is_token(second, CT_COND_COLON))
+ {
+ if ( chunk_is_token(second, CT_COND_COLON)
+ && (options::sp_cond_colon_before() != IARF_IGNORE))
+ {
+ // Add or remove space before the ':' in 'b ? t : f'.
+ // Overrides sp_cond_colon.
+ log_rule("sp_cond_colon_before");
+ return(options::sp_cond_colon_before());
+ }
+
+ if ( chunk_is_token(first, CT_COND_COLON)
+ && (options::sp_cond_colon_after() != IARF_IGNORE))
+ {
+ // Add or remove space after the ':' in 'b ? t : f'.
+ // Overrides sp_cond_colon.
+ log_rule("sp_cond_colon_after");
+ return(options::sp_cond_colon_after());
+ }
+ // Issue #2596
+ // replace "if (chunk_is_token(first, CT_WORD) && chunk_is_token(second, CT_COND_COLON))"
+ // Add or remove space around the ':' in 'b ? t : f'.
+ log_rule("sp_cond_colon");
+ return(options::sp_cond_colon());
+ }
+
+ if ( language_is_set(LANG_D)
+ && ( chunk_is_token(first, CT_RANGE)
+ || chunk_is_token(second, CT_RANGE)))
+ {
+ // (D) Add or remove space around the D '..' operator.
+ log_rule("sp_range");
+ return(options::sp_range());
+ }
+
+ if ( chunk_is_token(first, CT_COLON)
+ && get_chunk_parent_type(first) == CT_SQL_EXEC)
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ // Macro stuff can only return IGNORE, ADD, or FORCE
+ if (chunk_is_token(first, CT_MACRO))
+ {
+ // Add or remove space between a macro name and its definition.
+ log_rule("sp_macro");
+ iarf_e arg = options::sp_macro();
+ return(arg | ((arg != IARF_IGNORE) ? IARF_ADD : IARF_IGNORE));
+ }
+
+ if ( chunk_is_token(first, CT_FPAREN_CLOSE)
+ && get_chunk_parent_type(first) == CT_MACRO_FUNC)
+ {
+ // Add or remove space between a macro function ')' and its definition.
+ log_rule("sp_macro_func");
+ iarf_e arg = options::sp_macro_func();
+ return(arg | ((arg != IARF_IGNORE) ? IARF_ADD : IARF_IGNORE));
+ }
+
+ if (chunk_is_token(first, CT_PREPROC))
+ {
+ // Remove spaces, unless we are ignoring. See indent_preproc()
+ if (options::pp_space() == IARF_IGNORE)
+ {
+ log_rule("pp_space");
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(second, CT_SEMICOLON)) // see the tests cpp:34517-34519
+ {
+ if (chunk_is_token(first, CT_VBRACE_OPEN))
+ {
+ // Add or remove space before ';'.
+ log_rule("sp_before_semi");
+ return(options::sp_before_semi());
+ }
+
+ if (get_chunk_parent_type(second) == CT_FOR)
+ {
+ if (chunk_is_token(first, CT_SPAREN_OPEN))
+ {
+ // empty, e.g. for (;;)
+ // ^ is first
+ // ^ is second
+ // Add or remove space before a semicolon of an empty left part of a for statement.
+ log_rule("sp_before_semi_for_empty");
+ return(options::sp_before_semi_for_empty());
+ }
+
+ if (chunk_is_token(first, CT_SEMICOLON))
+ {
+ // empty, e.g. for (;;)
+ // ^ is first
+ // ^ is second
+ // Add or remove space between semicolons of an empty middle part of a for statement.
+ log_rule("sp_between_semi_for_empty");
+ return(options::sp_between_semi_for_empty());
+ }
+ // Add or remove space before ';' in non-empty 'for' statements.
+ log_rule("sp_before_semi_for");
+ return(options::sp_before_semi_for());
+ }
+ iarf_e arg = options::sp_before_semi(); // see the tests cpp:34517-34519
+
+ if ( chunk_is_token(first, CT_VBRACE_OPEN) // Issue #2942
+ && chunk_is_token(first->prev, CT_SPAREN_CLOSE)
+ && get_chunk_parent_type(first) != CT_WHILE_OF_DO)
+ {
+ // Add or remove space before empty statement ';' on 'if', 'for' and 'while'.
+ log_rule("sp_special_semi");
+ arg = arg | options::sp_special_semi();
+ }
+ else
+ {
+ // Add or remove space before ';'.
+ log_rule("sp_before_semi");
+ }
+ return(arg);
+ }
+
+ if ( ( chunk_is_token(second, CT_COMMENT)
+ || chunk_is_token(second, CT_COMMENT_CPP))
+ && ( chunk_is_token(first, CT_PP_ELSE)
+ || chunk_is_token(first, CT_PP_ENDIF)))
+ {
+ set_chunk_type(second, CT_COMMENT_ENDIF);
+ // Add or remove space between #else or #endif and a trailing comment.
+ log_rule("sp_endif_cmt");
+ return(options::sp_endif_cmt());
+ }
+
+ if ( options::sp_before_tr_cmt() != IARF_IGNORE
+ && get_chunk_parent_type(second) == CT_COMMENT_END)
+ {
+ // Add or remove space before a trailing comment.
+ // Number of spaces before a trailing comment.
+ log_rule("sp_num_before_tr_cmt");
+ min_sp = options::sp_num_before_tr_cmt();
+ return(options::sp_before_tr_cmt());
+ }
+
+ if (get_chunk_parent_type(second) == CT_COMMENT_END)
+ {
+ switch (second->orig_prev_sp)
+ {
+ case 0:
+ log_rule("orig_prev_sp-REMOVE");
+ return(IARF_REMOVE);
+
+ case 1:
+ log_rule("orig_prev_sp-FORCE");
+ return(IARF_FORCE);
+
+ default:
+ log_rule("orig_prev_sp-ADD");
+ return(IARF_ADD);
+ }
+ }
+
+ // "for (;;)" vs. "for (;; )" and "for (a;b;c)" vs. "for (a; b; c)"
+ if (chunk_is_token(first, CT_SEMICOLON)) // see the tests cpp:34517-34519
+ {
+ if (get_chunk_parent_type(first) == CT_FOR)
+ {
+ if (chunk_is_token(second, CT_SPAREN_CLOSE))
+ {
+ // Add or remove space after the final semicolon of an empty part of a for
+ // statement, as in 'for ( ; ; <here> )'.
+ log_rule("sp_after_semi_for_empty");
+ return(options::sp_after_semi_for_empty());
+ }
+
+ if (second->type != CT_SPAREN_CLOSE) // Issue 1324
+ {
+ // Add or remove space after ';' in non-empty 'for' statements.
+ log_rule("sp_after_semi_for");
+ return(options::sp_after_semi_for());
+ }
+ }
+ else if ( !second->IsComment()
+ && second->type != CT_BRACE_CLOSE) // issue #197
+ {
+ // Add or remove space after ';', except when followed by a comment.
+ // see the tests cpp:34517-34519
+ log_rule("sp_after_semi");
+ return(options::sp_after_semi());
+ }
+ // Let the comment spacing rules handle this
+ }
+
+ // puts a space in the rare '+-' or '-+'
+ if ( ( chunk_is_token(first, CT_NEG)
+ || chunk_is_token(first, CT_POS)
+ || chunk_is_token(first, CT_ARITH)
+ || chunk_is_token(first, CT_SHIFT))
+ && ( chunk_is_token(second, CT_NEG)
+ || chunk_is_token(second, CT_POS)
+ || chunk_is_token(second, CT_ARITH)
+ || chunk_is_token(second, CT_SHIFT)))
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ // "return(a);" vs. "return (foo_t)a + 3;" vs. "return a;" vs. "return;"
+ if (chunk_is_token(first, CT_RETURN))
+ {
+ if ( chunk_is_token(second, CT_PAREN_OPEN)
+ && get_chunk_parent_type(second) == CT_RETURN)
+ {
+ // Add or remove space between 'return' and '('.
+ log_rule("sp_return_paren");
+ return(options::sp_return_paren());
+ }
+ else if ( chunk_is_token(second, CT_BRACE_OPEN)
+ && get_chunk_parent_type(second) == CT_BRACED_INIT_LIST)
+ {
+ // Add or remove space between 'return' and '{'.
+ log_rule("sp_return_brace");
+ return(options::sp_return_brace());
+ }
+ // Everything else requires a space
+ // The value REMOVE will be overridden with FORCE
+ log_rule("sp_return");
+
+ if (options::sp_return() == IARF_REMOVE)
+ {
+ return(IARF_FORCE);
+ }
+ return(options::sp_return());
+ }
+
+ // "sizeof(foo_t)" vs. "sizeof (foo_t)"
+ if (chunk_is_token(first, CT_SIZEOF))
+ {
+ if (chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'sizeof' and '('.
+ log_rule("sp_sizeof_paren");
+ return(options::sp_sizeof_paren());
+ }
+
+ if (chunk_is_token(second, CT_ELLIPSIS))
+ {
+ // Add or remove space between 'sizeof' and '...'.
+ log_rule("sp_sizeof_ellipsis");
+ return(options::sp_sizeof_ellipsis());
+ }
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ // "decltype(foo_t)" vs. "decltype (foo_t)"
+ if (chunk_is_token(first, CT_DECLTYPE))
+ {
+ if (chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'decltype' and '('.
+ log_rule("sp_decltype_paren");
+ return(options::sp_decltype_paren());
+ }
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ // handle '::'
+ if (chunk_is_token(first, CT_DC_MEMBER))
+ {
+ // Add or remove space after the '::' operator.
+ log_rule("sp_after_dc");
+ return(options::sp_after_dc());
+ }
+
+ // Issue #889
+ // mapped_file_source abc((int) ::CW2A(sTemp));
+ if ( chunk_is_token(first, CT_PAREN_CLOSE)
+ && chunk_is_token(second, CT_DC_MEMBER)
+ && second->next != nullptr
+ && second->next->type == CT_FUNC_CALL)
+ {
+ log_rule("sp_after_cast");
+ return(options::sp_after_cast());
+ }
+
+ if (chunk_is_token(second, CT_DC_MEMBER))
+ {
+ /* '::' at the start of an identifier is not member access, but global scope operator.
+ * Detect if previous chunk is keyword
+ */
+ switch (first->type)
+ {
+ case CT_SBOOL:
+ case CT_SASSIGN:
+ case CT_ARITH:
+ case CT_SHIFT:
+ case CT_CASE:
+ case CT_CLASS:
+ case CT_DELETE:
+ case CT_FRIEND:
+ case CT_NAMESPACE:
+ case CT_NEW:
+ case CT_SARITH:
+ case CT_SCOMPARE:
+ case CT_OPERATOR:
+ case CT_ACCESS:
+ case CT_QUALIFIER:
+ case CT_RETURN:
+ case CT_SIZEOF:
+ case CT_DECLTYPE:
+ case CT_STRUCT:
+ case CT_THROW:
+ case CT_TYPEDEF:
+ case CT_TYPENAME:
+ case CT_UNION:
+ case CT_USING:
+ log_rule("FORCE");
+ return(IARF_FORCE);
+
+ default:
+ break;
+ }
+
+ if ( ( chunk_is_token(first, CT_WORD)
+ || chunk_is_token(first, CT_TYPE)
+ || chunk_is_token(first, CT_PAREN_CLOSE)
+ || CharTable::IsKw1(first->str[0]))
+ && (strcmp(first->Text(), "void") != 0)) // Issue 1249
+ {
+ // Add or remove space before the '::' operator.
+ log_rule("sp_before_dc");
+ return(options::sp_before_dc());
+ }
+ }
+
+ // "a,b" vs. "a, b"
+ if (chunk_is_token(first, CT_COMMA)) // see the tests cpp:34520-34524
+ // see the tests c-sharp:12200-12202
+ {
+ if ( language_is_set(LANG_CS)
+ && get_chunk_parent_type(first) == CT_TYPE)
+ {
+ // C# multidimensional array type: ',,' vs. ', ,' or ',]' vs. ', ]'
+ if (chunk_is_token(second, CT_COMMA))
+ {
+ // (C#) Add or remove space between ',' in multidimensional array type
+ // like 'int[,,]'.
+ log_rule("sp_between_mdatype_commas");
+ return(options::sp_between_mdatype_commas());
+ }
+ // (C#) Add or remove space between ',' and ']' in multidimensional array type
+ // like 'int[,,]'.
+ log_rule("sp_after_mdatype_commas");
+ return(options::sp_after_mdatype_commas());
+ }
+
+ // Fix for issue #1243
+ // Don't add extra space after comma immediately followed by Angle close
+ if (chunk_is_token(second, CT_ANGLE_CLOSE))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+ // Add or remove space after ',', i.e. 'a,b' vs. 'a, b'.
+ log_rule("sp_after_comma");
+ return(options::sp_after_comma());
+ }
+
+ // test if we are within a SIGNAL/SLOT call
+ if (QT_SIGNAL_SLOT_found)
+ {
+ if ( chunk_is_token(first, CT_FPAREN_CLOSE)
+ && ( chunk_is_token(second, CT_FPAREN_CLOSE)
+ || chunk_is_token(second, CT_COMMA)))
+ {
+ if (second->level == QT_SIGNAL_SLOT_level)
+ {
+ restoreValues = true;
+ }
+ }
+ }
+
+ if (chunk_is_token(second, CT_COMMA))
+ {
+ if ( language_is_set(LANG_CS)
+ && chunk_is_token(first, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(first) == CT_TYPE)
+ {
+ // Only for C#.
+ // (C#) Add or remove space between '[' and ',' in multidimensional array type
+ // like 'int[,,]'.
+ log_rule("sp_before_mdatype_commas");
+ return(options::sp_before_mdatype_commas());
+ }
+
+ if ( chunk_is_token(first, CT_PAREN_OPEN)
+ || chunk_is_token(first, CT_FPAREN_OPEN))
+ {
+ // Add or remove space between an open parenthesis and comma,
+ // i.e. '(,' vs. '( ,'.
+ log_rule("sp_paren_comma");
+ return(options::sp_paren_comma());
+ }
+ // Add or remove space before ',', i.e. 'a,b' vs. 'a ,b'.
+ log_rule("sp_before_comma");
+ return(options::sp_before_comma());
+ }
+
+ if (chunk_is_token(second, CT_ELLIPSIS))
+ {
+ // type followed by a ellipsis
+ Chunk *tmp = first;
+
+ if ( chunk_is_token(tmp, CT_PTR_TYPE)
+ || chunk_is_token(tmp, CT_BYREF))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ }
+
+ if ( chunk_is_token(tmp, CT_TYPE)
+ || chunk_is_token(tmp, CT_QUALIFIER))
+ {
+ // Add or remove space between a type and '...'.
+ log_rule("sp_type_ellipsis");
+ return(options::sp_type_ellipsis());
+ }
+
+ // non-punc followed by a ellipsis
+ if ( !first->flags.test(PCF_PUNCTUATOR)
+ && (options::sp_before_ellipsis() != IARF_IGNORE))
+ {
+ // Add or remove space before the variadic '...' when preceded by a
+ // non-punctuator.
+ log_rule("sp_before_ellipsis");
+ return(options::sp_before_ellipsis());
+ }
+
+ if ( chunk_is_token(first, CT_FPAREN_CLOSE)
+ || chunk_is_token(first, CT_PAREN_CLOSE))
+ {
+ // Add or remove space between ')' and '...'.
+ log_rule("sp_paren_ellipsis");
+ return(options::sp_paren_ellipsis());
+ }
+
+ if (chunk_is_token(first, CT_TAG_COLON))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if (chunk_is_token(first, CT_BYREF)) // Issue #3309
+ {
+ log_rule("sp_byref_ellipsis");
+ return(options::sp_byref_ellipsis());
+ }
+
+ if (chunk_is_token(first, CT_PARAMETER_PACK)) // Issue #3309
+ {
+ log_rule("sp_parameter_pack_ellipsis");
+ return(options::sp_parameter_pack_ellipsis());
+ }
+ }
+
+ if (chunk_is_token(first, CT_ELLIPSIS))
+ {
+ if (chunk_is_token(second, CT_PARAMETER_PACK)) // Issue #3309
+ {
+ log_rule("sp_ellipsis_parameter_pack");
+ return(options::sp_ellipsis_parameter_pack());
+ }
+
+ if (CharTable::IsKw1(second->str[0]))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( chunk_is_token(second, CT_PAREN_OPEN)
+ && first->prev != nullptr
+ && chunk_is_token(first->prev, CT_SIZEOF))
+ {
+ // Add or remove space between 'sizeof...' and '('.
+ log_rule("sp_sizeof_ellipsis_paren");
+ return(options::sp_sizeof_ellipsis_paren());
+ }
+ }
+
+ if ( language_is_set(LANG_PAWN)
+ && chunk_is_token(first, CT_TAG_COLON))
+ {
+ // (Pawn) Add or remove space after the tag keyword.
+ log_rule("sp_after_tag");
+ return(options::sp_after_tag());
+ }
+
+ if (chunk_is_token(second, CT_TAG_COLON))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ // handle '~'
+ if (chunk_is_token(first, CT_DESTRUCTOR))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_CATCH)
+ && chunk_is_token(second, CT_SPAREN_OPEN)
+ && (options::sp_oc_catch_paren() != IARF_IGNORE))
+ {
+ // (OC) Add or remove space between '@catch' and '('
+ // in '@catch (something) { }'. If set to ignore, sp_catch_paren is used.
+ log_rule("sp_oc_catch_paren");
+ return(options::sp_oc_catch_paren());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && ( chunk_is_token(first, CT_PAREN_CLOSE)
+ || chunk_is_token(first, CT_OC_CLASS)
+ || chunk_is_token(first, CT_WORD))
+ && chunk_is_token(second, CT_ANGLE_OPEN)
+ && ( get_chunk_parent_type(second) == CT_OC_PROTO_LIST
+ || get_chunk_parent_type(second) == CT_OC_GENERIC_SPEC)
+ && (options::sp_before_oc_proto_list() != IARF_IGNORE))
+ {
+ // (OC) Add or remove space before Objective-C protocol list
+ // as in '@protocol Protocol<here><Protocol_A>' or '@interface MyClass : NSObject<here><MyProtocol>'.
+ log_rule("sp_before_oc_proto_list");
+ return(options::sp_before_oc_proto_list());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_OC_CLASS)
+ && chunk_is_token(second, CT_PAREN_OPEN)
+ && (options::sp_oc_classname_paren() != IARF_IGNORE))
+ {
+ // (OC) Add or remove space between class name and '('
+ // in '@interface className(categoryName)<ProtocolName>:BaseClass'
+ log_rule("sp_oc_classname_paren");
+ return(options::sp_oc_classname_paren());
+ }
+
+ if ( chunk_is_token(first, CT_CATCH)
+ && chunk_is_token(second, CT_SPAREN_OPEN)
+ && (options::sp_catch_paren() != IARF_IGNORE))
+ {
+ // Add or remove space between 'catch' and '(' in 'catch (something) { }'.
+ // If set to ignore, sp_before_sparen is used.
+ log_rule("sp_catch_paren");
+ return(options::sp_catch_paren());
+ }
+
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(first, CT_D_VERSION_IF)
+ && chunk_is_token(second, CT_SPAREN_OPEN)
+ && (options::sp_version_paren() != IARF_IGNORE))
+ {
+ // (D) Add or remove space between 'version' and '('
+ // in 'version (something) { }'. If set to ignore, sp_before_sparen is used.
+ log_rule("sp_version_paren");
+ return(options::sp_version_paren());
+ }
+
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(first, CT_D_SCOPE_IF)
+ && chunk_is_token(second, CT_SPAREN_OPEN)
+ && (options::sp_scope_paren() != IARF_IGNORE))
+ {
+ // (D) Add or remove space between 'scope' and '('
+ // in 'scope (something) { }'. If set to ignore, sp_before_sparen is used.
+ log_rule("sp_scope_paren");
+ return(options::sp_scope_paren());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_SYNCHRONIZED)
+ && chunk_is_token(second, CT_SPAREN_OPEN))
+ {
+ // (OC) Add or remove space between '@synchronized' and the open parenthesis,
+ // i.e. '@synchronized(foo)' vs. '@synchronized (foo)'.
+ log_rule("sp_after_oc_synchronized");
+ return(options::sp_after_oc_synchronized());
+ }
+
+ // "if (" vs. "if("
+ if (chunk_is_token(second, CT_SPAREN_OPEN))
+ {
+ // Add or remove space after 'do' between 'while' and '('. Issue #995
+ if ( chunk_is_token(first, CT_WHILE_OF_DO)
+ && options::sp_while_paren_open() != IARF_IGNORE)
+ {
+ log_rule("sp_while_paren_open");
+ return(options::sp_while_paren_open());
+ }
+ // Add or remove space before '(' of other control statements ('if', 'for',
+ // 'switch', 'while', etc.).
+ log_rule("sp_before_sparen");
+ return(options::sp_before_sparen());
+ }
+
+ if ( chunk_is_token(first, CT_LAMBDA)
+ || chunk_is_token(second, CT_LAMBDA))
+ {
+ // Add or remove space around assignment operator '=', '+=', etc.
+ log_rule("sp_assign (lambda)");
+ return(options::sp_assign());
+ }
+
+ // Handle the special lambda case for C++11:
+ // [=](Something arg){.....}
+ // Add or remove space around '=' in C++11 lambda capture specifications.
+ // Overrides sp_assign.
+ if ( (options::sp_cpp_lambda_assign() != IARF_IGNORE)
+ && ( ( chunk_is_token(first, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(first) == CT_CPP_LAMBDA
+ && chunk_is_token(second, CT_ASSIGN))
+ || ( chunk_is_token(first, CT_ASSIGN)
+ && chunk_is_token(second, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(second) == CT_CPP_LAMBDA)))
+ {
+ log_rule("sp_cpp_lambda_assign");
+ return(options::sp_cpp_lambda_assign());
+ }
+
+ if ( chunk_is_token(first, CT_SQUARE_CLOSE)
+ && get_chunk_parent_type(first) == CT_CPP_LAMBDA)
+ {
+ // Handle the special lambda case for C++11:
+ // [](Something arg){.....}
+ // Add or remove space after the capture specification of a C++11 lambda when
+ // an argument list is present, as in '[] <here> (int x){ ... }'.
+ if (chunk_is_token(second, CT_LPAREN_OPEN))
+ {
+ log_rule("sp_cpp_lambda_square_paren");
+ return(options::sp_cpp_lambda_square_paren());
+ }
+ else if (chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space after the capture specification of a C++11 lambda with
+ // no argument list is present, as in '[] <here> { ... }'.
+ log_rule("sp_cpp_lambda_square_brace");
+ return(options::sp_cpp_lambda_square_brace());
+ }
+ }
+
+ if (chunk_is_token(first, CT_LPAREN_OPEN))
+ {
+ // Add or remove space after the opening parenthesis of a argument list
+ // of a C++11 lambda, as in '[]( <here> int x ){ ... }'.
+ log_rule("sp_cpp_lambda_argument_list");
+ return(options::sp_cpp_lambda_argument_list());
+ }
+
+ if (chunk_is_token(first, CT_LPAREN_CLOSE))
+ {
+ if (chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space after the argument list of a C++11 lambda, as in
+ // '[](int x) <here> { ... }'.
+ log_rule("sp_cpp_lambda_paren_brace");
+ return(options::sp_cpp_lambda_paren_brace());
+ }
+ }
+
+ if (chunk_is_token(second, CT_LPAREN_CLOSE))
+ {
+ // Add or remove space before the closing parenthesis of a argument list
+ // of a C++11 lambda, as in '[]( int x <here> ){ ... }'.
+ log_rule("sp_cpp_lambda_argument_list");
+ return(options::sp_cpp_lambda_argument_list());
+ }
+
+ if ( chunk_is_token(first, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(first) == CT_CPP_LAMBDA
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ // Add or remove space between a lambda body and its call operator of an
+ // immediately invoked lambda, as in '[]( ... ){ ... } <here> ( ... )'.
+ log_rule("sp_cpp_lambda_fparen");
+ return(options::sp_cpp_lambda_fparen());
+ }
+
+ if (chunk_is_token(first, CT_ENUM))
+ {
+ if (chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space in 'enum {'.
+ log_rule("sp_enum_brace");
+ return(options::sp_enum_brace());
+ }
+ else if (chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ // Add or remove space in 'NS_ENUM ('.
+ log_rule("sp_enum_paren");
+ return(options::sp_enum_paren());
+ }
+ }
+
+ if (chunk_is_token(second, CT_ASSIGN))
+ {
+ if (second->flags.test(PCF_IN_ENUM))
+ {
+ // Add or remove space before assignment '=' in enum.
+ // Overrides sp_enum_assign.
+ if (options::sp_enum_before_assign() != IARF_IGNORE)
+ {
+ log_rule("sp_enum_before_assign");
+ return(options::sp_enum_before_assign());
+ }
+ // Add or remove space around assignment '=' in enum.
+ log_rule("sp_enum_assign");
+ return(options::sp_enum_assign());
+ }
+
+ // Add or remove space around assignment operator '=' in a prototype.
+ // If set to ignore, use sp_assign.
+ if ( (options::sp_assign_default() != IARF_IGNORE)
+ && get_chunk_parent_type(second) == CT_FUNC_PROTO)
+ {
+ log_rule("sp_assign_default");
+ return(options::sp_assign_default());
+ }
+
+ // Add or remove space before assignment operator '=', '+=', etc.
+ // Overrides sp_assign.
+ if (options::sp_before_assign() != IARF_IGNORE)
+ {
+ log_rule("sp_before_assign");
+ return(options::sp_before_assign());
+ }
+ // Add or remove space around assignment operator '=', '+=', etc.
+ log_rule("sp_assign");
+ return(options::sp_assign());
+ }
+
+ if (chunk_is_token(second, CT_ASSIGN_DEFAULT_ARG))
+ {
+ // Add or remove space around assignment operator '=' in a prototype.
+ // If set to ignore, use sp_assign.
+ if ( (options::sp_assign_default() != IARF_IGNORE)
+ && get_chunk_parent_type(second) == CT_FUNC_PROTO)
+ {
+ log_rule("sp_assign_default");
+ return(options::sp_assign_default());
+ }
+
+ // Add or remove space before assignment operator '=', '+=', etc.
+ // Overrides sp_assign.
+ if (options::sp_before_assign() != IARF_IGNORE)
+ {
+ log_rule("sp_before_assign");
+ return(options::sp_before_assign());
+ }
+ // Add or remove space around assignment operator '=', '+=', etc.
+ log_rule("sp_assign");
+ return(options::sp_assign());
+ }
+
+ if (chunk_is_token(first, CT_ASSIGN))
+ {
+ if (first->flags.test(PCF_IN_ENUM))
+ {
+ // Add or remove space after assignment '=' in enum.
+ // Overrides sp_enum_assign.
+ if (options::sp_enum_after_assign() != IARF_IGNORE)
+ {
+ log_rule("sp_enum_after_assign");
+ return(options::sp_enum_after_assign());
+ }
+ // Add or remove space around assignment '=' in enum.
+ log_rule("sp_enum_assign");
+ return(options::sp_enum_assign());
+ }
+
+ // Add or remove space around assignment operator '=' in a prototype.
+ // If set to ignore, use sp_assign.
+ if ( (options::sp_assign_default() != IARF_IGNORE)
+ && get_chunk_parent_type(first) == CT_FUNC_PROTO)
+ {
+ log_rule("sp_assign_default");
+ return(options::sp_assign_default());
+ }
+
+ // Add or remove space after assignment operator '=', '+=', etc.
+ // Overrides sp_assign.
+ if (options::sp_after_assign() != IARF_IGNORE)
+ {
+ log_rule("sp_after_assign");
+ return(options::sp_after_assign());
+ }
+ // Add or remove space around assignment operator '=', '+=', etc.
+ log_rule("sp_assign");
+ return(options::sp_assign());
+ }
+
+ if ( chunk_is_token(first, CT_TRAILING_RET)
+ || chunk_is_token(first, CT_CPP_LAMBDA_RET)
+ || chunk_is_token(second, CT_TRAILING_RET)
+ || chunk_is_token(second, CT_CPP_LAMBDA_RET))
+ {
+ // Add or remove space around trailing return operator '->'.
+ log_rule("sp_trailing_return");
+ return(options::sp_trailing_return());
+ }
+
+ if (chunk_is_token(first, CT_ASSIGN_DEFAULT_ARG))
+ {
+ // Add or remove space around assignment operator '=' in a prototype.
+ // If set to ignore, use sp_assign.
+ if ( (options::sp_assign_default() != IARF_IGNORE)
+ && get_chunk_parent_type(first) == CT_FUNC_PROTO)
+ {
+ log_rule("sp_assign_default");
+ return(options::sp_assign_default());
+ }
+
+ // Add or remove space after assignment operator '=', '+=', etc.
+ // Overrides sp_assign.
+ if (options::sp_after_assign() != IARF_IGNORE)
+ {
+ log_rule("sp_after_assign");
+ return(options::sp_after_assign());
+ }
+ // Add or remove space around assignment operator '=', '+=', etc.
+ log_rule("sp_assign");
+ return(options::sp_assign());
+ }
+
+ if (chunk_is_token(first, CT_BIT_COLON))
+ {
+ if ( first->flags.test(PCF_IN_ENUM)
+ || first->parent_type == CT_ENUM)
+ {
+ // Add or remove space around assignment ':' in enum.
+ log_rule("sp_enum_colon");
+ return(options::sp_enum_colon());
+ }
+ }
+
+ if (chunk_is_token(second, CT_BIT_COLON))
+ {
+ if ( second->flags.test(PCF_IN_ENUM)
+ || second->parent_type == CT_ENUM)
+ {
+ // Add or remove space around assignment ':' in enum.
+ log_rule("sp_enum_colon");
+ return(options::sp_enum_colon());
+ }
+ }
+
+ if ( chunk_is_token(first, CT_OC_AVAILABLE_VALUE)
+ || chunk_is_token(second, CT_OC_AVAILABLE_VALUE))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ if (language_is_set(LANG_OC))
+ {
+ if (chunk_is_token(second, CT_OC_BLOCK_CARET))
+ {
+ // (OC) Add or remove space before a block pointer caret,
+ // i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'.
+ log_rule("sp_before_oc_block_caret");
+ return(options::sp_before_oc_block_caret());
+ }
+
+ if (chunk_is_token(first, CT_OC_BLOCK_CARET))
+ {
+ // (OC) Add or remove space after a block pointer caret,
+ // i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'.
+ log_rule("sp_after_oc_block_caret");
+ return(options::sp_after_oc_block_caret());
+ }
+
+ if (chunk_is_token(second, CT_OC_MSG_FUNC))
+ {
+ if ( (options::sp_after_oc_msg_receiver() == IARF_REMOVE)
+ && ( (first->type != CT_SQUARE_CLOSE)
+ && (first->type != CT_FPAREN_CLOSE)
+ && (first->type != CT_PAREN_CLOSE)))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+ // (OC) Add or remove space between the receiver and selector in a message,
+ // as in '[receiver selector ...]'.
+ log_rule("sp_after_oc_msg_receiver");
+ return(options::sp_after_oc_msg_receiver());
+ }
+ }
+
+ // c++17 structured bindings e.g., "auto [x, y, z]" vs. a[x, y, z]" or "auto const [x, y, z]" vs. "auto const[x, y, z]"
+ if ( language_is_set(LANG_CPP)
+ && ( chunk_is_token(first, CT_BYREF)
+ || chunk_is_token(first, CT_QUALIFIER)
+ || chunk_is_token(first, CT_TYPE))
+ && chunk_is_token(second, CT_SQUARE_OPEN)
+ && get_chunk_parent_type(second) != CT_OC_MSG
+ && get_chunk_parent_type(second) != CT_CS_SQ_STMT)
+ {
+ // Add or remove space before C++17 structured bindings.
+ log_rule("sp_cpp_before_struct_binding");
+ return(options::sp_cpp_before_struct_binding());
+ }
+
+ // "a [x]" vs. "a[x]"
+ if ( chunk_is_token(second, CT_SQUARE_OPEN)
+ && ( get_chunk_parent_type(second) != CT_OC_MSG
+ && get_chunk_parent_type(second) != CT_CS_SQ_STMT
+ && get_chunk_parent_type(second) != CT_CPP_LAMBDA))
+ {
+ if ( second->flags.test(PCF_IN_SPAREN)
+ && (chunk_is_token(first, CT_IN)))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if (chunk_is_token(first, CT_ASM_COLON))
+ {
+ // Add or remove space before '[' for asm block.
+ log_rule("sp_before_square_asm_block");
+ return(options::sp_before_square_asm_block());
+ }
+
+ if (first->flags.test(PCF_VAR_DEF))
+ {
+ // Add or remove space before '[' for a variable definition.
+ log_rule("sp_before_vardef_square");
+ return(options::sp_before_vardef_square());
+ }
+ // Add or remove space before '[' (except '[]').
+ log_rule("sp_before_square");
+ return(options::sp_before_square());
+ }
+
+ // "byte[]" vs. "byte []"
+ if (chunk_is_token(second, CT_TSQUARE))
+ {
+ // Add or remove space before '[]'.
+ log_rule("sp_before_squares");
+ return(options::sp_before_squares());
+ }
+
+ if ( (options::sp_angle_shift() != IARF_IGNORE)
+ && chunk_is_token(first, CT_ANGLE_CLOSE)
+ && chunk_is_token(second, CT_ANGLE_CLOSE))
+ {
+ // Add or remove space between '>' and '>' in '>>' (template stuff).
+ log_rule("sp_angle_shift");
+ return(options::sp_angle_shift());
+ }
+
+ // spacing around template < > stuff
+ if ( chunk_is_token(first, CT_ANGLE_OPEN)
+ || chunk_is_token(second, CT_ANGLE_CLOSE))
+ {
+ if ( chunk_is_token(first, CT_ANGLE_OPEN)
+ && chunk_is_token(second, CT_ANGLE_CLOSE))
+ {
+ // Add or remove space inside '<>'.
+ log_rule("sp_inside_angle_empty");
+ return(options::sp_inside_angle_empty());
+ }
+ // Add or remove space inside '<' and '>'.
+ log_rule("sp_inside_angle");
+ iarf_e op = options::sp_inside_angle();
+
+ // special: if we're not supporting digraphs, then we shouldn't create them!
+ if ( (op == IARF_REMOVE)
+ && !options::enable_digraphs()
+ && chunk_is_token(first, CT_ANGLE_OPEN)
+ && chunk_is_token(second, CT_DC_MEMBER))
+ {
+ op = IARF_IGNORE;
+ }
+ return(op);
+ }
+
+ if (chunk_is_token(second, CT_ANGLE_OPEN))
+ {
+ if ( chunk_is_token(first, CT_TEMPLATE)
+ && (options::sp_template_angle() != IARF_IGNORE))
+ {
+ // Add or remove space between 'template' and '<'.
+ // If set to ignore, sp_before_angle is used.
+ log_rule("sp_template_angle");
+ return(options::sp_template_angle());
+ }
+
+ if (first->type != CT_QUALIFIER)
+ {
+ // Add or remove space before '<'.
+ log_rule("sp_before_angle");
+ return(options::sp_before_angle());
+ }
+ }
+
+ if (chunk_is_token(first, CT_ANGLE_CLOSE))
+ {
+ if ( chunk_is_token(second, CT_WORD)
+ || CharTable::IsKw1(second->str[0]))
+ {
+ // Add or remove space between '>' and a word as in 'List<byte> m;' or
+ // 'template <typename T> static ...'.
+ log_rule("sp_angle_word");
+ return(options::sp_angle_word());
+ }
+
+ if ( chunk_is_token(second, CT_FPAREN_OPEN)
+ || chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ // Add or remove space between '>' and '()' as found in 'new List<byte>();'.
+ log_rule("sp_angle_paren_empty");
+ return(options::sp_angle_paren_empty());
+ }
+ // Add or remove space between '>' and '(' as found in 'new List<byte>(foo);'.
+ log_rule("sp_angle_paren");
+ return(options::sp_angle_paren());
+ }
+
+ if (chunk_is_token(second, CT_DC_MEMBER))
+ {
+ // Add or remove space before the '::' operator.
+ log_rule("sp_before_dc");
+ return(options::sp_before_dc());
+ }
+
+ if ( second->type != CT_BYREF
+ && second->type != CT_PTR_TYPE
+ && second->type != CT_BRACE_OPEN
+ && second->type != CT_PAREN_CLOSE)
+ {
+ if ( chunk_is_token(second, CT_CLASS_COLON)
+ && options::sp_angle_colon() != IARF_IGNORE)
+ {
+ // Add or remove space between '>' and ':'.
+ log_rule("sp_angle_colon");
+ return(options::sp_angle_colon());
+ }
+
+ // Whether sp_after_angle takes precedence over sp_inside_fparen. This was the
+ // historic behavior, but is probably not the desired behavior, so this is off
+ // by default.
+ if ( chunk_is_token(second, CT_FPAREN_CLOSE)
+ && options::sp_inside_fparen() != IARF_IGNORE
+ && !options::use_sp_after_angle_always())
+ {
+ // Add or remove space between '>' and ')'.
+ log_rule("sp_inside_fparen");
+ return(options::sp_inside_fparen());
+ }
+ // Add or remove space after '>'.
+ log_rule("sp_after_angle");
+ return(options::sp_after_angle());
+ }
+ }
+
+ if (chunk_is_token(first, CT_BYREF)) // see the tests cpp:34509-34512
+ {
+ if (chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space after a reference sign '&', if followed by an open
+ // parenthesis, as in 'char& (*)()'.
+ log_rule("sp_byref_paren");
+ return(options::sp_byref_paren());
+ }
+ else if ( get_chunk_parent_type(first) == CT_FUNC_DEF // Issue #3197, #3210
+ || get_chunk_parent_type(first) == CT_FUNC_PROTO)
+ {
+ // Add or remove space after a reference sign '&', if followed by a function
+ // prototype or function definition.
+ log_rule("sp_after_byref_func"); // byref 2
+ return(options::sp_after_byref_func());
+ }
+ else if ( CharTable::IsKw1(second->str[0])
+ && ( options::sp_after_byref() != IARF_IGNORE
+ || ( !chunk_is_token(second, CT_FUNC_PROTO)
+ && !chunk_is_token(second, CT_FUNC_DEF))))
+ {
+ // Add or remove space after reference sign '&', if followed by a word.
+ log_rule("sp_after_byref"); // byref 1
+ return(options::sp_after_byref());
+ }
+ }
+
+ if ( chunk_is_token(second, CT_BYREF)
+ && !chunk_is_token(first, CT_PAREN_OPEN)) // Issue #1804
+ {
+ if ( get_chunk_parent_type(second) == CT_FUNC_DEF // Issue #3197, #3210
+ || get_chunk_parent_type(second) == CT_FUNC_PROTO)
+ {
+ // Add or remove space before a reference sign '&', if followed by a function
+ // prototype or function definition.
+ log_rule("sp_before_byref_func"); // byref 4
+ return(options::sp_before_byref_func());
+ }
+ Chunk *next = second->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && ( chunk_is_token(next, CT_COMMA)
+ || chunk_is_token(next, CT_FPAREN_CLOSE)
+ || chunk_is_token(next, CT_SEMICOLON)))
+ {
+ if (options::sp_before_unnamed_byref() != IARF_IGNORE)
+ {
+ // Add or remove space before a reference sign '&' that isn't followed by a
+ // variable name. If set to 'ignore', sp_before_byref is used instead.
+ log_rule("sp_before_unnamed_byref"); // byref 5
+ return(options::sp_before_unnamed_byref());
+ }
+ else
+ {
+ // Add or remove space before a reference sign '&'.
+ log_rule("sp_before_byref"); // byref 3
+ return(options::sp_before_byref());
+ }
+ }
+ // Add or remove space before a reference sign '&'.
+ log_rule("sp_before_byref"); // byref 3
+ return(options::sp_before_byref());
+ }
+
+ if (chunk_is_token(first, CT_SPAREN_CLOSE))
+ {
+ if (chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ if (get_chunk_parent_type(second) == CT_CATCH)
+ {
+ if ( language_is_set(LANG_OC)
+ && (options::sp_oc_catch_brace() != IARF_IGNORE))
+ {
+ // (OC) Add or remove space before the '{' of a '@catch' statement, if the '{'
+ // and '@catch' are on the same line, as in '@catch (decl) <here> {'.
+ // If set to ignore, sp_catch_brace is used.
+ // only to help the vim command }}
+ log_rule("sp_oc_catch_brace");
+ return(options::sp_oc_catch_brace());
+ }
+
+ if (options::sp_catch_brace() != IARF_IGNORE)
+ {
+ // Add or remove space before the '{' of a 'catch' statement, if the '{' and
+ // 'catch' are on the same line, as in 'catch (decl) <here> {'.
+ log_rule("sp_catch_brace");
+ return(options::sp_catch_brace());
+ }
+ }
+
+ if (options::sp_sparen_brace() != IARF_IGNORE)
+ {
+ // Add or remove space between ')' and '{' of control statements.
+ log_rule("sp_sparen_brace");
+ return(options::sp_sparen_brace());
+ }
+ }
+
+ if ( !second->IsComment()
+ && (options::sp_after_sparen() != IARF_IGNORE))
+ {
+ // Add or remove space after ')' of control statements.
+ log_rule("sp_after_sparen");
+ return(options::sp_after_sparen());
+ }
+ }
+
+ if ( chunk_is_token(second, CT_FPAREN_OPEN)
+ && get_chunk_parent_type(first) == CT_OPERATOR
+ && (options::sp_after_operator_sym() != IARF_IGNORE))
+ {
+ if ( (options::sp_after_operator_sym_empty() != IARF_IGNORE)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ // Overrides sp_after_operator_sym when the operator has no arguments, as in
+ // 'operator *()'.
+ log_rule("sp_after_operator_sym_empty");
+ return(options::sp_after_operator_sym_empty());
+ }
+ }
+ // Add or remove space between the operator symbol and the open parenthesis, as
+ // in 'operator ++('.
+ log_rule("sp_after_operator_sym");
+ return(options::sp_after_operator_sym());
+ }
+
+ // Issue #2270
+ // Translations under vala
+ if ( language_is_set(LANG_VALA)
+ && chunk_is_token(first, CT_FUNC_CALL))
+ {
+ if ( chunk_is_str(first, "_")
+ && chunk_is_token(second, CT_FPAREN_OPEN)
+ && (options::sp_vala_after_translation() != IARF_IGNORE))
+ {
+ // Add or remove space after '_'.
+ log_rule("sp_vala_after_translation");
+ return(options::sp_vala_after_translation());
+ }
+ }
+
+ if ( chunk_is_token(first, CT_MACRO_OPEN)
+ || chunk_is_token(first, CT_MACRO_CLOSE)
+ || chunk_is_token(first, CT_MACRO_ELSE))
+ {
+ if (chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ // TODO: provide some test data to check this block
+ // Add or remove space between function name and '(' on function calls.
+ log_rule("sp_func_call_paren");
+ return(options::sp_func_call_paren());
+ }
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ // spaces between function and open paren
+ if ( chunk_is_token(first, CT_FUNC_CALL)
+ || chunk_is_token(first, CT_FUNCTION) // Issue #2665
+ || chunk_is_token(first, CT_FUNC_CTOR_VAR)
+ || chunk_is_token(first, CT_CNG_HASINC)
+ || chunk_is_token(first, CT_CNG_HASINCN)
+ || ( chunk_is_token(first, CT_BRACE_CLOSE)
+ && first->parent_type == CT_BRACED_INIT_LIST
+ && chunk_is_token(second, CT_FPAREN_OPEN)))
+ {
+ if ( (options::sp_func_call_paren_empty() != IARF_IGNORE)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ // Add or remove space between function name and '()' on function calls without
+ // parameters. If set to 'ignore' (the default), sp_func_call_paren is used.
+ log_rule("sp_func_call_paren_empty");
+ return(options::sp_func_call_paren_empty());
+ }
+ }
+ // Add or remove space between function name and '(' on function calls.
+ log_rule("sp_func_call_paren");
+ return(options::sp_func_call_paren());
+ }
+
+ if (chunk_is_token(first, CT_FUNC_CALL_USER))
+ {
+ // Add or remove space between the user function name and '(' on function
+ // calls. You need to set a keyword to be a user function in the config file,
+ // like:
+ // set func_call_user tr _ i18n
+ log_rule("sp_func_call_user_paren");
+ return(options::sp_func_call_user_paren());
+ }
+
+ if ( chunk_is_token(first, CT_ATTRIBUTE)
+ && chunk_is_paren_open(second))
+ {
+ // Add or remove space between '__attribute__' and '('.
+ log_rule("sp_attribute_paren");
+ return(options::sp_attribute_paren());
+ }
+
+ if (chunk_is_token(first, CT_FUNC_DEF))
+ {
+ if ( (options::sp_func_def_paren_empty() != IARF_IGNORE)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ // Add or remove space between function name and '()' on function definition
+ // without parameters.
+ log_rule("sp_func_def_paren_empty");
+ return(options::sp_func_def_paren_empty());
+ }
+ }
+ // Add or remove space between function name and '(' on function definition.
+ log_rule("sp_func_def_paren");
+ return(options::sp_func_def_paren());
+ }
+
+ if ( chunk_is_token(first, CT_CPP_CAST)
+ || chunk_is_token(first, CT_TYPE_WRAP))
+ {
+ // Add or remove space between the type and open parenthesis in a C++ cast,
+ // i.e. 'int(exp)' vs. 'int (exp)'.
+ log_rule("sp_cpp_cast_paren");
+ return(options::sp_cpp_cast_paren());
+ }
+
+ if ( chunk_is_token(first, CT_SPAREN_CLOSE)
+ && chunk_is_token(second, CT_WHEN))
+ {
+ // TODO: provide some test data to check this block
+ log_rule("FORCE");
+ return(IARF_FORCE); // TODO: make this configurable?
+ }
+
+ if ( chunk_is_token(first, CT_PAREN_CLOSE)
+ && ( chunk_is_token(second, CT_PAREN_OPEN)
+ || chunk_is_token(second, CT_FPAREN_OPEN)))
+ {
+ // "(int)a" vs. "(int) a" or "cast(int)a" vs. "cast(int) a"
+ if ( get_chunk_parent_type(first) == CT_C_CAST
+ || get_chunk_parent_type(first) == CT_D_CAST)
+ {
+ // Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or
+ // '(int)a' vs. '(int) a'.
+ log_rule("sp_after_cast");
+ return(options::sp_after_cast());
+ }
+ // Probably a parenthesized indirect function call or similar (issue #3260)
+ log_rule("sp_cparen_oparen");
+ return(options::sp_cparen_oparen());
+ }
+
+ // handle the space between parens in fcn type 'void (*f)(void)'
+ if (chunk_is_token(first, CT_TPAREN_CLOSE))
+ {
+ // Add or remove space between the ')' and '(' in a function type, as in
+ // 'void (*x)(...)'.
+ log_rule("sp_after_tparen_close");
+ return(options::sp_after_tparen_close());
+ }
+
+ // ")(" vs. ") ("
+ if ( ( chunk_is_str(first, ")")
+ && chunk_is_str(second, "("))
+ || ( chunk_is_paren_close(first)
+ && chunk_is_paren_open(second)))
+ {
+ // Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('.
+ log_rule("sp_cparen_oparen");
+ return(options::sp_cparen_oparen());
+ }
+
+ if ( chunk_is_token(first, CT_FUNC_PROTO)
+ || ( chunk_is_token(second, CT_FPAREN_OPEN)
+ && get_chunk_parent_type(second) == CT_FUNC_PROTO))
+ {
+ if ( (options::sp_func_proto_paren_empty() != IARF_IGNORE)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ // Add or remove space between function name and '()' on function declaration
+ // without parameters.
+ log_rule("sp_func_proto_paren_empty");
+ return(options::sp_func_proto_paren_empty());
+ }
+ }
+ // Add or remove space between function name and '(' on function declaration.
+ log_rule("sp_func_proto_paren");
+ return(options::sp_func_proto_paren());
+ }
+
+ // Issue #2437
+ if ( chunk_is_token(first, CT_FUNC_TYPE)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ // Add or remove space between function name and '(' with a typedef specifier.
+ log_rule("sp_func_type_paren");
+ return(options::sp_func_type_paren());
+ }
+
+ if ( chunk_is_token(first, CT_FUNC_CLASS_DEF)
+ || chunk_is_token(first, CT_FUNC_CLASS_PROTO))
+ {
+ if ( (options::sp_func_class_paren_empty() != IARF_IGNORE)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ // Add or remove space between a constructor without parameters or destructor
+ // and '()'.
+ log_rule("sp_func_class_paren_empty");
+ return(options::sp_func_class_paren_empty());
+ }
+ }
+ // Add or remove space between a constructor/destructor and the open
+ // parenthesis.
+ log_rule("sp_func_class_paren");
+ return(options::sp_func_class_paren());
+ }
+
+ if ( chunk_is_token(first, CT_CLASS)
+ && !first->flags.test(PCF_IN_OC_MSG))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( chunk_is_token(first, CT_BRACE_OPEN)
+ && chunk_is_token(second, CT_BRACE_CLOSE))
+ {
+ // Add or remove space inside '{}'.
+ log_rule("sp_inside_braces_empty");
+ return(options::sp_inside_braces_empty());
+ }
+
+ if ( ( chunk_is_token(first, CT_TYPE) // Issue #2428
+ || chunk_is_token(first, CT_ANGLE_CLOSE))
+ && chunk_is_token(second, CT_BRACE_OPEN)
+ && get_chunk_parent_type(second) == CT_BRACED_INIT_LIST)
+ {
+ iarf_flags_t arg = iarf_flags_t{ options::sp_type_brace_init_lst() };
+
+ if ( arg != IARF_IGNORE
+ || get_chunk_parent_type(first) != CT_DECLTYPE)
+ {
+ // 'int{9}' vs. 'int {9}'
+ // Add or remove space between type and open brace of an unnamed temporary
+ // direct-list-initialization.
+ log_rule("sp_type_brace_init_lst");
+ return(arg);
+ }
+ }
+
+ if ( ( chunk_is_token(first, CT_WORD) // Issue #2428
+ || chunk_is_token(first, CT_SQUARE_CLOSE)
+ || chunk_is_token(first, CT_TSQUARE))
+ && chunk_is_token(second, CT_BRACE_OPEN)
+ && get_chunk_parent_type(second) == CT_BRACED_INIT_LIST)
+ {
+ // Add or remove space between a variable and '{' for C++ uniform
+ // initialization.
+ auto arg = iarf_flags_t{ options::sp_word_brace_init_lst() };
+
+ if ( arg != IARF_IGNORE
+ || get_chunk_parent_type(first) != CT_DECLTYPE)
+ {
+ // 'a{9}' vs. 'a {9}'
+ // Add or remove space between variable/word and open brace of an unnamed
+ // temporary direct-list-initialization.
+ log_rule("sp_word_brace_init_lst");
+ return(arg);
+ }
+ }
+
+ if (chunk_is_token(second, CT_BRACE_CLOSE))
+ {
+ if (get_chunk_parent_type(second) == CT_ENUM)
+ {
+ // Add or remove space inside enum '{' and '}'.
+ log_rule("sp_inside_braces_enum");
+ return(options::sp_inside_braces_enum());
+ }
+
+ if ( get_chunk_parent_type(second) == CT_STRUCT
+ || get_chunk_parent_type(second) == CT_UNION)
+ {
+ // Fix for issue #1240 adding space in struct initializers
+ Chunk *tmp = chunk_skip_to_match_rev(second)->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp, CT_ASSIGN))
+ {
+ // TODO: provide some test data to check this block
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+ // Add or remove space inside struct/union '{' and '}'.
+ log_rule("sp_inside_braces_struct");
+ return(options::sp_inside_braces_struct());
+ }
+ else if ( language_is_set(LANG_OC)
+ && get_chunk_parent_type(second) == CT_OC_AT
+ && options::sp_inside_braces_oc_dict() != IARF_IGNORE)
+ {
+ // (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}'
+ log_rule("sp_inside_braces_oc_dict");
+ return(options::sp_inside_braces_oc_dict());
+ }
+
+ if (get_chunk_parent_type(second) == CT_BRACED_INIT_LIST)
+ {
+ // Add or remove space between nested braces, i.e. '{{' vs. '{ {'.
+ // only to help the vim command }}}}
+ if ( options::sp_brace_brace() != IARF_IGNORE
+ && chunk_is_token(first, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(first) == CT_BRACED_INIT_LIST)
+ {
+ log_rule("sp_brace_brace");
+ return(options::sp_brace_brace());
+ }
+
+ if (options::sp_before_type_brace_init_lst_close() != IARF_IGNORE)
+ {
+ // Add or remove space before close brace in an unnamed temporary
+ // direct-list-initialization
+ // if statement is a brace_init_lst
+ // works only if sp_brace_brace is set to ignore.
+ log_rule("sp_before_type_brace_init_lst_close");
+ return(options::sp_before_type_brace_init_lst_close());
+ }
+
+ if (options::sp_inside_type_brace_init_lst() != IARF_IGNORE)
+ {
+ // Add or remove space inside an unnamed temporary direct-list-initialization.
+ // if statement is a brace_init_lst
+ // works only if sp_brace_brace is set to ignore
+ // works only if sp_before_type_brace_init_lst_close is set to ignore.
+ log_rule("sp_inside_type_brace_init_lst");
+ return(options::sp_inside_type_brace_init_lst());
+ }
+ }
+ // Add or remove space inside '{' and '}'.
+ log_rule("sp_inside_braces");
+ return(options::sp_inside_braces());
+ }
+
+ if (chunk_is_token(first, CT_D_CAST))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( chunk_is_token(first, CT_PP_DEFINED)
+ && chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'defined' and '(' in '#if defined (FOO)'.
+ log_rule("sp_defined_paren");
+ return(options::sp_defined_paren());
+ }
+
+ if (chunk_is_token(first, CT_THROW))
+ {
+ if (chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'throw' and '(' in 'throw (something)'.
+ log_rule("sp_throw_paren");
+ return(options::sp_throw_paren());
+ }
+ // Add or remove space between 'throw' and anything other than '(' as in
+ // '@throw [...];'.
+ log_rule("sp_after_throw");
+ return(options::sp_after_throw());
+ }
+
+ if ( chunk_is_token(first, CT_THIS)
+ && chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'this' and '(' in 'this (something)'.
+ log_rule("sp_this_paren");
+ return(options::sp_this_paren());
+ }
+
+ if ( chunk_is_token(first, CT_STATE)
+ && chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ if ( chunk_is_token(first, CT_DELEGATE)
+ && chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( chunk_is_token(first, CT_MEMBER)
+ || chunk_is_token(second, CT_MEMBER))
+ {
+ // Add or remove space around the '.' or '->' operators.
+ log_rule("sp_member");
+ return(options::sp_member());
+ }
+
+ if (chunk_is_token(first, CT_C99_MEMBER))
+ {
+ // always remove space(s) after then '.' of a C99-member
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( chunk_is_token(first, CT_SUPER)
+ && chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'super' and '(' in 'super (something)'.
+ log_rule("sp_super_paren");
+ return(options::sp_super_paren());
+ }
+
+ if ( chunk_is_token(first, CT_FPAREN_CLOSE)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ if ( language_is_set(LANG_JAVA)
+ && get_chunk_parent_type(second) == CT_DOUBLE_BRACE)
+ {
+ // (Java) Add or remove space between ')' and '{{' of double brace initializer.
+ // only to help the vim command }}
+ log_rule("sp_fparen_dbrace");
+ return(options::sp_fparen_dbrace());
+ }
+
+ // To fix issue #1234
+ // check for initializers and add space or ignore based on the option.
+ if (get_chunk_parent_type(first) == CT_FUNC_CALL)
+ {
+ Chunk *tmp = first->GetPrevType(get_chunk_parent_type(first), first->level);
+ tmp = tmp->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp, CT_NEW))
+ {
+ // Add or remove space between ')' and '{' of s function call in object
+ // initialization.
+ // Overrides sp_fparen_brace.
+ log_rule("sp_fparen_brace_initializer");
+ return(options::sp_fparen_brace_initializer());
+ }
+ }
+ // Add or remove space between ')' and '{' of function.
+ log_rule("sp_fparen_brace");
+ return(options::sp_fparen_brace());
+ }
+
+ if ( chunk_is_token(first, CT_D_TEMPLATE)
+ || chunk_is_token(second, CT_D_TEMPLATE))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( chunk_is_token(first, CT_ELSE)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space between 'else' and '{' if on the same line.
+ log_rule("sp_else_brace");
+ return(options::sp_else_brace());
+ }
+
+ if ( chunk_is_token(first, CT_ELSE)
+ && chunk_is_token(second, CT_ELSEIF))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( chunk_is_token(first, CT_FINALLY)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space between 'finally' and '{' if on the same line.
+ log_rule("sp_finally_brace");
+ return(options::sp_finally_brace());
+ }
+
+ if ( chunk_is_token(first, CT_TRY)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space between 'try' and '{' if on the same line.
+ log_rule("sp_try_brace");
+ return(options::sp_try_brace());
+ }
+
+ if ( chunk_is_token(first, CT_GETSET)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space between get/set and '{' if on the same line.
+ log_rule("sp_getset_brace");
+ return(options::sp_getset_brace());
+ }
+
+ if ( chunk_is_token(first, CT_WORD)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ if (get_chunk_parent_type(first) == CT_NAMESPACE)
+ {
+ // Add or remove space between a variable and '{' for a namespace.
+ log_rule("sp_word_brace_ns");
+ return(options::sp_word_brace_ns());
+ }
+ }
+
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(second, CT_PAREN_OPEN)
+ && get_chunk_parent_type(second) == CT_INVARIANT)
+ {
+ // (D) Add or remove space between 'invariant' and '('.
+ log_rule("sp_invariant_paren");
+ return(options::sp_invariant_paren());
+ }
+
+ if ( chunk_is_token(first, CT_PAREN_CLOSE)
+ && get_chunk_parent_type(first) != CT_DECLTYPE)
+ {
+ if ( language_is_set(LANG_D)
+ && get_chunk_parent_type(first) == CT_INVARIANT)
+ {
+ // (D) Add or remove space after the ')' in 'invariant (C) c'.
+ log_rule("sp_after_invariant_paren");
+ return(options::sp_after_invariant_paren());
+ }
+
+ // "(struct foo) {...}" vs. "(struct foo){...}"
+ if (chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space between ')' and '{'.
+ log_rule("sp_paren_brace");
+ return(options::sp_paren_brace());
+ }
+
+ // D-specific: "delegate(some thing) dg
+ if (get_chunk_parent_type(first) == CT_DELEGATE)
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ // PAWN-specific: "state (condition) next"
+ if (get_chunk_parent_type(first) == CT_STATE)
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ /* C++ new operator: new(bar) Foo */
+ if (get_chunk_parent_type(first) == CT_NEW)
+ {
+ // Add or remove space between ')' and type in 'new(foo) BAR'.
+ log_rule("sp_after_newop_paren");
+ return(options::sp_after_newop_paren());
+ }
+ }
+
+ /* "((" vs. "( (" or "))" vs. ") )" */
+ // Issue #1342
+ if ( ( chunk_is_str(first, "(")
+ && chunk_is_str(second, "("))
+ || ( chunk_is_str(first, ")")
+ && chunk_is_str(second, ")")))
+ {
+ if (get_chunk_parent_type(second) == CT_FUNC_CALL_USER)
+ {
+ // Add or remove space between nested parentheses with user functions,
+ // i.e. '((' vs. '( ('.
+ log_rule("sp_func_call_user_paren_paren");
+ return(options::sp_func_call_user_paren_paren());
+ }
+
+ if ( options::sp_sparen_paren() != IARF_IGNORE
+ && ( chunk_is_token(first, CT_SPAREN_OPEN)
+ || chunk_is_token(second, CT_SPAREN_CLOSE)))
+ {
+ // Add or remove space between nested parentheses with control
+ // statements, i.e. 'if ((' vs. 'if ( ('. Issue #3209
+ log_rule("sp_sparen_paren");
+ return(options::sp_sparen_paren());
+ }
+ // Add or remove space between nested parentheses, i.e. '((' vs. ') )'.
+ log_rule("sp_paren_paren");
+ return(options::sp_paren_paren());
+ }
+
+ // "foo(...)" vs. "foo( ... )"
+ if ( chunk_is_token(first, CT_FPAREN_OPEN)
+ || chunk_is_token(second, CT_FPAREN_CLOSE))
+ {
+ if ( (get_chunk_parent_type(first) == CT_FUNC_CALL_USER)
+ || ( (get_chunk_parent_type(second) == CT_FUNC_CALL_USER)
+ && ( (chunk_is_token(first, CT_WORD))
+ || (chunk_is_token(first, CT_SQUARE_CLOSE)))))
+ {
+ // Add or remove space inside user function '(' and ')'.
+ log_rule("sp_func_call_user_inside_fparen");
+ return(options::sp_func_call_user_inside_fparen());
+ }
+
+ if ( chunk_is_token(first, CT_FPAREN_OPEN)
+ && chunk_is_token(second, CT_FPAREN_CLOSE))
+ {
+ // Add or remove space inside empty function '()'.
+ log_rule("sp_inside_fparens");
+ return(options::sp_inside_fparens());
+ }
+ // Add or remove space inside function '(' and ')'.
+ log_rule("sp_inside_fparen");
+ return(options::sp_inside_fparen());
+ }
+
+ // "foo(...)" vs. "foo( ... )"
+ if ( chunk_is_token(first, CT_TPAREN_OPEN)
+ || chunk_is_token(second, CT_TPAREN_CLOSE))
+ {
+ // Add or remove space inside the first parentheses in a function type, as in
+ // 'void (*x)(...)'.
+ log_rule("sp_inside_tparen");
+ return(options::sp_inside_tparen());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_PAREN_CLOSE))
+ {
+ if ( first->flags.test(PCF_OC_RTYPE) // == CT_OC_RTYPE)
+ && ( get_chunk_parent_type(first) == CT_OC_MSG_DECL
+ || get_chunk_parent_type(first) == CT_OC_MSG_SPEC))
+ {
+ // (OC) Add or remove space after the first (type) in message specs,
+ // i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'.
+ log_rule("sp_after_oc_return_type");
+ return(options::sp_after_oc_return_type());
+ }
+
+ if ( get_chunk_parent_type(first) == CT_OC_MSG_SPEC
+ || get_chunk_parent_type(first) == CT_OC_MSG_DECL)
+ {
+ // (OC) Add or remove space after the (type) in message specs,
+ // i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'.
+ log_rule("sp_after_oc_type");
+ return(options::sp_after_oc_type());
+ }
+
+ if ( get_chunk_parent_type(first) == CT_OC_SEL
+ && second->type != CT_SQUARE_CLOSE)
+ {
+ // (OC) Add or remove space between '@selector(x)' and the following word,
+ // i.e. '@selector(foo) a:' vs. '@selector(foo)a:'.
+ log_rule("sp_after_oc_at_sel_parens");
+ return(options::sp_after_oc_at_sel_parens());
+ }
+ }
+
+ if ( language_is_set(LANG_OC)
+ && options::sp_inside_oc_at_sel_parens() != IARF_IGNORE)
+ {
+ if ( ( chunk_is_token(first, CT_PAREN_OPEN)
+ && ( get_chunk_parent_type(first) == CT_OC_SEL
+ || get_chunk_parent_type(first) == CT_OC_PROTOCOL))
+ || ( chunk_is_token(second, CT_PAREN_CLOSE)
+ && ( get_chunk_parent_type(second) == CT_OC_SEL
+ || get_chunk_parent_type(second) == CT_OC_PROTOCOL)))
+ {
+ // (OC) Add or remove space inside '@selector' parentheses,
+ // i.e. '@selector(foo)' vs. '@selector( foo )'.
+ // Also applies to '@protocol()' constructs.
+ log_rule("sp_inside_oc_at_sel_parens");
+ return(options::sp_inside_oc_at_sel_parens());
+ }
+ }
+
+ if ( chunk_is_token(second, CT_PAREN_OPEN)
+ && ( chunk_is_token(first, CT_OC_SEL)
+ || chunk_is_token(first, CT_OC_PROTOCOL)))
+ {
+ // (OC) Add or remove space between '@selector' and '(',
+ // i.e. '@selector(msgName)' vs. '@selector (msgName)'.
+ // Also applies to '@protocol()' constructs.
+ log_rule("sp_after_oc_at_sel");
+ return(options::sp_after_oc_at_sel());
+ }
+
+ /*
+ * C cast: "(int)" vs. "( int )"
+ * D cast: "cast(int)" vs. "cast( int )"
+ * CPP cast: "int(a + 3)" vs. "int( a + 3 )"
+ */
+ if (chunk_is_token(first, CT_PAREN_OPEN))
+ {
+ if ( get_chunk_parent_type(first) == CT_C_CAST
+ || get_chunk_parent_type(first) == CT_CPP_CAST
+ || get_chunk_parent_type(first) == CT_D_CAST)
+ {
+ // Add or remove spaces inside cast parentheses.
+ log_rule("sp_inside_paren_cast");
+ return(options::sp_inside_paren_cast());
+ }
+
+ if (get_chunk_parent_type(first) == CT_NEW)
+ {
+ if (options::sp_inside_newop_paren_open() != IARF_IGNORE)
+ {
+ // Add or remove space after the open parenthesis of the new operator,
+ // as in 'new(foo) BAR'.
+ // Overrides sp_inside_newop_paren.
+ log_rule("sp_inside_newop_paren_open");
+ return(options::sp_inside_newop_paren_open());
+ }
+
+ if (options::sp_inside_newop_paren() != IARF_IGNORE)
+ {
+ // Add or remove space inside parenthesis of the new operator
+ // as in 'new(foo) BAR'.
+ log_rule("sp_inside_newop_paren");
+ return(options::sp_inside_newop_paren());
+ }
+ }
+ log_rule("sp_inside_paren");
+ return(options::sp_inside_paren());
+ }
+
+ if (chunk_is_token(second, CT_PAREN_CLOSE))
+ {
+ if ( get_chunk_parent_type(second) == CT_C_CAST
+ || get_chunk_parent_type(second) == CT_CPP_CAST
+ || get_chunk_parent_type(second) == CT_D_CAST)
+ {
+ // Add or remove spaces inside cast parentheses.
+ log_rule("sp_inside_paren_cast");
+ return(options::sp_inside_paren_cast());
+ }
+
+ if (get_chunk_parent_type(second) == CT_NEW)
+ {
+ if (options::sp_inside_newop_paren_close() != IARF_IGNORE)
+ {
+ // Add or remove space before the close parenthesis of the new operator,
+ // as in 'new(foo) BAR'.
+ // Overrides sp_inside_newop_paren.
+ log_rule("sp_inside_newop_paren_close");
+ return(options::sp_inside_newop_paren_close());
+ }
+
+ if (options::sp_inside_newop_paren() != IARF_IGNORE)
+ {
+ // Add or remove space inside parenthesis of the new operator
+ // as in 'new(foo) BAR'.
+ log_rule("sp_inside_newop_paren");
+ return(options::sp_inside_newop_paren());
+ }
+ }
+ // Add or remove space inside '(' and ')'.
+ log_rule("sp_inside_paren");
+ return(options::sp_inside_paren());
+ }
+
+ if ( chunk_is_token(first, CT_SQUARE_OPEN)
+ && chunk_is_token(second, CT_SQUARE_CLOSE))
+ {
+ // Add or remove space inside '[]'.
+ log_rule("sp_inside_square_empty");
+ return(options::sp_inside_square_empty());
+ }
+
+ // "[3]" vs. "[ 3 ]" or for objective-c "@[@3]" vs. "@[ @3 ]"
+ if ( chunk_is_token(first, CT_SQUARE_OPEN)
+ || chunk_is_token(second, CT_SQUARE_CLOSE))
+ {
+ if ( language_is_set(LANG_OC)
+ && ( ( get_chunk_parent_type(first) == CT_OC_AT
+ && chunk_is_token(first, CT_SQUARE_OPEN))
+ || ( get_chunk_parent_type(second) == CT_OC_AT
+ && chunk_is_token(second, CT_SQUARE_CLOSE)))
+ && (options::sp_inside_square_oc_array() != IARF_IGNORE))
+ {
+ // (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and
+ // ']'. If set to ignore, sp_inside_square is used.
+ log_rule("sp_inside_square_oc_array");
+ return(options::sp_inside_square_oc_array());
+ }
+ // Add or remove space inside a non-empty '[' and ']'.
+ log_rule("sp_inside_square");
+ return(options::sp_inside_square());
+ }
+
+ if ( chunk_is_token(first, CT_SQUARE_CLOSE)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ // Add or remove space between ']' and '(' when part of a function call.
+ log_rule("sp_square_fparen");
+ return(options::sp_square_fparen());
+ }
+
+ // "if(...)" vs. "if( ... )" etc.
+ if (chunk_is_token(second, CT_SPAREN_CLOSE))
+ {
+ if ( get_chunk_parent_type(second) == CT_FOR
+ && options::sp_inside_for_open() != IARF_IGNORE)
+ {
+ // Add or remove space before ')' of 'for' statements.
+ // Overrides sp_inside_for.
+ log_rule("sp_inside_for_close");
+ return(options::sp_inside_for_close());
+ }
+ else if (options::sp_inside_sparen_open() != IARF_IGNORE)
+ {
+ // Add or remove space before ')' of other control statements.
+ // Overrides sp_inside_sparen.
+ log_rule("sp_inside_sparen_close");
+ return(options::sp_inside_sparen_close());
+ }
+ }
+
+ if (chunk_is_token(first, CT_SPAREN_OPEN))
+ {
+ if ( get_chunk_parent_type(first) == CT_FOR
+ && options::sp_inside_for_open() != IARF_IGNORE)
+ {
+ // Add or remove space before ')' of 'for' statements.
+ // Overrides sp_inside_for.
+ log_rule("sp_inside_for_close");
+ return(options::sp_inside_for_close());
+ }
+ else if (options::sp_inside_sparen_open() != IARF_IGNORE)
+ {
+ // Add or remove space after '(' of other control statements.
+ // Overrides sp_inside_sparen.
+ log_rule("sp_inside_sparen_open");
+ return(options::sp_inside_sparen_open());
+ }
+ }
+
+ if (chunk_is_token(first, CT_SPAREN_OPEN))
+ {
+ if (get_chunk_parent_type(first) == CT_FOR)
+ {
+ // Add or remove space inside '(' and ')' of 'for' statements.
+ log_rule("sp_inside_for");
+ return(options::sp_inside_for());
+ }
+ else
+ {
+ // Add or remove space inside '(' and ')' of other control statements.
+ log_rule("sp_inside_sparen");
+ return(options::sp_inside_sparen());
+ }
+ }
+
+ if (chunk_is_token(second, CT_SPAREN_CLOSE))
+ {
+ if (get_chunk_parent_type(second) == CT_FOR)
+ {
+ // Add or remove space inside '(' and ')' of 'for' statements.
+ log_rule("sp_inside_for");
+ return(options::sp_inside_for());
+ }
+ else
+ {
+ // Add or remove space inside '(' and ')' of other control statements.
+ log_rule("sp_inside_sparen");
+ return(options::sp_inside_sparen());
+ }
+ }
+
+ if (chunk_is_token(first, CT_CLASS_COLON))
+ {
+ if ( get_chunk_parent_type(first) == CT_OC_CLASS
+ && ( first->GetPrevType(CT_OC_INTF, first->level, E_Scope::ALL)->IsNullChunk()
+ && first->GetPrevType(CT_OC_IMPL, first->level, E_Scope::ALL)->IsNullChunk()))
+ {
+ if (options::sp_after_oc_colon() != IARF_IGNORE)
+ {
+ // TODO: provide some test data to check this block
+ // (OC) Add or remove space after the colon in message specs,
+ // i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'.
+ log_rule("sp_after_oc_colon");
+ return(options::sp_after_oc_colon());
+ }
+ }
+
+ if (options::sp_after_class_colon() != IARF_IGNORE)
+ {
+ // Add or remove space after class ':'.
+ log_rule("sp_after_class_colon");
+ return(options::sp_after_class_colon());
+ }
+ }
+
+ if (chunk_is_token(second, CT_CLASS_COLON))
+ {
+ if ( language_is_set(LANG_OC)
+ && get_chunk_parent_type(second) == CT_OC_CLASS
+ && ( second->GetPrevType(CT_OC_INTF, second->level, E_Scope::ALL)->IsNullChunk()
+ && second->GetPrevType(CT_OC_IMPL, second->level, E_Scope::ALL)->IsNullChunk()))
+ {
+ if ( get_chunk_parent_type(second) == CT_OC_CLASS
+ && second->GetPrevType(CT_OC_INTF, second->level, E_Scope::ALL)->IsNullChunk())
+ {
+ if (options::sp_before_oc_colon() != IARF_IGNORE)
+ {
+ // TODO: provide some test data to check this block
+ // (OC) Add or remove space before the colon in message specs,
+ // i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'.
+ log_rule("sp_before_oc_colon");
+ return(options::sp_before_oc_colon());
+ }
+ }
+ }
+
+ if (options::sp_before_class_colon() != IARF_IGNORE)
+ {
+ // Add or remove space before class ':'.
+ log_rule("sp_before_class_colon");
+ return(options::sp_before_class_colon());
+ }
+ }
+
+ if (chunk_is_token(first, CT_CONSTR_COLON))
+ {
+ min_sp = options::indent_ctor_init_leading() - 1; // default indent is 1 space
+ // Add or remove space after class constructor ':'.
+ log_rule("sp_after_constr_colon");
+ return(options::sp_after_constr_colon());
+ }
+
+ if (chunk_is_token(second, CT_CONSTR_COLON))
+ {
+ // Add or remove space before class constructor ':'.
+ log_rule("sp_before_constr_colon");
+ return(options::sp_before_constr_colon());
+ }
+
+ if (chunk_is_token(second, CT_CASE_COLON))
+ {
+ // Add or remove space before case ':'.
+ log_rule("sp_before_case_colon");
+ return(options::sp_before_case_colon());
+ }
+
+ if (chunk_is_token(first, CT_DOT))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(second, CT_DOT))
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ if ( chunk_is_token(first, CT_NULLCOND)
+ || chunk_is_token(second, CT_NULLCOND))
+ {
+ // TODO: provide some test data to check this block
+ // LANG_CS null conditional operator
+ // Add or remove space around the '.' or '->' operators.
+ log_rule("sp_member");
+ return(options::sp_member());
+ }
+
+ if ( chunk_is_token(first, CT_ARITH)
+ || chunk_is_token(first, CT_SHIFT)
+ || chunk_is_token(first, CT_CARET)
+ || chunk_is_token(second, CT_ARITH)
+ || chunk_is_token(second, CT_SHIFT)
+ || chunk_is_token(second, CT_CARET))
+ {
+ // Add or remove space around arithmetic operators '+' and '-'.
+ // Overrides sp_arith.
+ if (options::sp_arith_additive() != IARF_IGNORE)
+ {
+ auto arith_char = ( chunk_is_token(first, CT_ARITH)
+ || chunk_is_token(first, CT_SHIFT)
+ || chunk_is_token(first, CT_CARET))
+ ? first->str[0] : second->str[0];
+
+ if ( arith_char == '+'
+ || arith_char == '-')
+ {
+ log_rule("sp_arith_additive");
+ return(options::sp_arith_additive());
+ }
+ }
+ // Add or remove space around non-assignment symbolic operators ('+', '/', '%',
+ // '<<', and so forth).
+ log_rule("sp_arith");
+ return(options::sp_arith());
+ }
+
+ if ( chunk_is_token(first, CT_BOOL)
+ || chunk_is_token(second, CT_BOOL))
+ {
+ // Add or remove space around boolean operators '&&' and '||'.
+ iarf_e arg = options::sp_bool();
+
+ if ( (options::pos_bool() != TP_IGNORE)
+ && first->orig_line != second->orig_line)
+ {
+ arg = arg | IARF_ADD;
+ }
+ log_rule("sp_bool");
+ return(arg);
+ }
+
+ if ( chunk_is_token(first, CT_COMPARE)
+ || chunk_is_token(second, CT_COMPARE))
+ {
+ // Add or remove space around compare operator '<', '>', '==', etc.
+ log_rule("sp_compare");
+ return(options::sp_compare());
+ }
+
+ if ( chunk_is_token(first, CT_PAREN_OPEN)
+ && chunk_is_token(second, CT_PTR_TYPE))
+ {
+ // TODO: provide some test data to check this block
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(first, CT_PTR_TYPE)) // see the tests cpp:34505-34508
+ {
+ if ( chunk_is_token(second, CT_FPAREN_OPEN)
+ || chunk_is_token(second, CT_TPAREN_OPEN))
+ {
+ // Add or remove space after a pointer star '*', if followed by an open
+ // parenthesis, as in 'void* (*)()'.
+ log_rule("sp_ptr_star_paren"); // ptr_star 10
+ return(options::sp_ptr_star_paren());
+ }
+ else if (chunk_is_token(second, CT_PTR_TYPE))
+ {
+ // Add or remove space between pointer stars '*'.
+ // as in 'int ***a;'.
+ log_rule("sp_between_ptr_star"); // ptr_star 9
+ return(options::sp_between_ptr_star());
+ }
+ else if (chunk_is_token(second, CT_FUNC_VAR))
+ {
+ // Add or remove space between the pointer star '*' and the name of the
+ // variable in a function pointer definition.
+ log_rule("sp_ptr_star_func_var");
+ return(options::sp_ptr_star_func_var());
+ }
+ else if (chunk_is_token(second, CT_FUNC_TYPE))
+ {
+ // Add or remove space between the pointer star '*' and the name of the
+ // type in a function pointer type definition.
+ log_rule("sp_ptr_star_func_type");
+ return(options::sp_ptr_star_func_type());
+ }
+ else if ( get_chunk_parent_type(first) == CT_FUNC_DEF
+ || get_chunk_parent_type(first) == CT_FUNC_PROTO
+ || get_chunk_parent_type(first) == CT_FUNC_VAR)
+ {
+ if (token_is_within_trailing_return(first))
+ {
+ // Add or remove space after a pointer star '*', in the trailing return
+ // a function prototype or function definition.
+ log_rule("sp_after_ptr_star_trailing"); // ptr_star 3
+ return(options::sp_after_ptr_star_trailing());
+ }
+ else
+ {
+ // Add or remove space after a pointer star '*', if followed by a function
+ // prototype or function definition.
+ log_rule("sp_after_ptr_star_func"); // ptr_star 2
+ return(options::sp_after_ptr_star_func());
+ }
+ }
+ else if (CharTable::IsKw1(second->str[0]))
+ {
+ Chunk *prev = first->GetPrev();
+
+ if (chunk_is_token(prev, CT_IN))
+ {
+ // Add or remove space after the '*' (dereference) unary operator. This does
+ // not affect the spacing after a '*' that is part of a type.
+ log_rule("sp_deref");
+ return(options::sp_deref());
+ }
+ else if ( get_chunk_parent_type(first) == CT_FUNC_VAR
+ || get_chunk_parent_type(first) == CT_FUNC_TYPE)
+ {
+ // Add or remove space after pointer caret '^', if followed by a word.
+ log_rule("sp_after_ptr_block_caret");
+ return(options::sp_after_ptr_block_caret());
+ }
+ else if (chunk_is_token(second, CT_QUALIFIER))
+ {
+ // Add or remove space after pointer star '*', if followed by a qualifier.
+ log_rule("sp_after_ptr_star_qualifier"); // ptr_star 4
+ return(options::sp_after_ptr_star_qualifier());
+ }
+ // Add or remove space after pointer star '*', if followed by a word.
+ log_rule("sp_after_ptr_star"); // ptr_star 1
+ return(options::sp_after_ptr_star());
+ }
+ else if (chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // Add or remove space after pointer star '*', if followed by a word.
+ log_rule("sp_after_ptr_star"); // ptr_star 1
+ return(options::sp_after_ptr_star());
+ }
+
+ // must be placed at the end of the block
+ // look back for '->' type is TRAILING_RET
+ if (token_is_within_trailing_return(first))
+ {
+ log_rule("sp_after_ptr_star_trailing"); // ptr_star 3
+ return(options::sp_after_ptr_star_trailing());
+ }
+ }
+
+ if ( chunk_is_token(second, CT_PTR_TYPE)
+ && first->type != CT_IN)
+ {
+ // look back for '->' type is TRAILING_RET
+ if (token_is_within_trailing_return(second))
+ {
+ log_rule("sp_before_ptr_star_trailing"); // ptr_star 7
+ return(options::sp_before_ptr_star_trailing());
+ }
+
+ // Add or remove space before a pointer star '*', if followed by a function
+ // prototype or function definition.
+ if (options::sp_before_ptr_star_func() != IARF_IGNORE)
+ {
+ // Find the next non-'*' chunk
+ Chunk *next = second;
+
+ do
+ {
+ next = next->GetNext();
+ } while (chunk_is_token(next, CT_PTR_TYPE));
+
+ if ( chunk_is_token(next, CT_FUNC_DEF)
+ || chunk_is_token(next, CT_FUNC_PROTO))
+ {
+ log_rule("sp_before_ptr_star_func"); // ptr_star 6
+ return(options::sp_before_ptr_star_func());
+ }
+ }
+
+ // Add or remove space before pointer star '*' that isn't followed by a
+ // variable name. If set to 'ignore', sp_before_ptr_star is used instead.
+ if (options::sp_before_unnamed_ptr_star() != IARF_IGNORE)
+ {
+ Chunk *next = second->GetNextNc();
+
+ while (chunk_is_token(next, CT_PTR_TYPE))
+ {
+ next = next->GetNextNc();
+ }
+
+ if ( next->IsNotNullChunk()
+ && next->type != CT_WORD)
+ {
+ log_rule("sp_before_unnamed_ptr_star"); // ptr_star 8
+ return(options::sp_before_unnamed_ptr_star());
+ }
+ }
+
+ // Add or remove space before pointer star '*'.
+ if (options::sp_before_ptr_star() != IARF_IGNORE)
+ {
+ log_rule("sp_before_ptr_star"); // ptr_star 5
+ return(options::sp_before_ptr_star());
+ }
+ }
+
+ if (chunk_is_token(first, CT_OPERATOR))
+ {
+ // Add or remove space between 'operator' and operator sign.
+ log_rule("sp_after_operator");
+ return(options::sp_after_operator());
+ }
+
+ if ( chunk_is_token(second, CT_FUNC_PROTO)
+ || chunk_is_token(second, CT_FUNC_DEF))
+ {
+ if ( first->type != CT_PTR_TYPE
+ && first->type != CT_BYREF)
+ {
+ // Add or remove space between return type and function name. A
+ // minimum of 1 is forced except for pointer/reference return types.
+ log_rule("sp_type_func | ADD");
+ return(options::sp_type_func() | IARF_ADD);
+ }
+ // Add or remove space between return type and function name. A
+ // minimum of 1 is forced except for pointer/reference return types.
+ log_rule("sp_type_func");
+ return(options::sp_type_func());
+ }
+
+ // "(int)a" vs. "(int) a" or "cast(int)a" vs. "cast(int) a"
+ if ( ( get_chunk_parent_type(first) == CT_C_CAST
+ || get_chunk_parent_type(first) == CT_D_CAST)
+ && chunk_is_token(first, CT_PAREN_CLOSE))
+ {
+ log_rule("sp_after_cast");
+ return(options::sp_after_cast());
+ }
+
+ if (chunk_is_token(first, CT_BRACE_CLOSE))
+ {
+ if (chunk_is_token(second, CT_ELSE))
+ {
+ // Add or remove space between '}' and 'else' if on the same line.
+ log_rule("sp_brace_else");
+ return(options::sp_brace_else());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(second, CT_CATCH)
+ && (options::sp_oc_brace_catch() != IARF_IGNORE))
+ {
+ // TODO: provide some test data to check this block
+ // (OC) Add or remove space between '}' and '@catch' if on the same line.
+ // If set to ignore, sp_brace_catch is used.
+ log_rule("sp_oc_brace_catch");
+ return(options::sp_oc_brace_catch());
+ }
+
+ if (chunk_is_token(second, CT_CATCH))
+ {
+ // TODO: provide some test data to check this block
+ // Add or remove space between '}' and 'catch' if on the same line.
+ log_rule("sp_brace_catch");
+ return(options::sp_brace_catch());
+ }
+
+ if (chunk_is_token(second, CT_FINALLY))
+ {
+ // Add or remove space between '}' and 'finally' if on the same line.
+ log_rule("sp_brace_finally");
+ return(options::sp_brace_finally());
+ }
+ }
+
+ if (chunk_is_token(first, CT_BRACE_OPEN))
+ {
+ if (get_chunk_parent_type(first) == CT_ENUM)
+ {
+ // Add or remove space inside enum '{' and '}'.
+ log_rule("sp_inside_braces_enum");
+ return(options::sp_inside_braces_enum());
+ }
+
+ if ( get_chunk_parent_type(first) == CT_STRUCT
+ || get_chunk_parent_type(first) == CT_UNION)
+ {
+ // Fix for issue #1240 adding space in struct initializers
+ Chunk *tmp = first->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp, CT_ASSIGN))
+ {
+ // TODO: provide some test data to check this block
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+ // Add or remove space inside struct/union '{' and '}'.
+ log_rule("sp_inside_braces_struct");
+ return(options::sp_inside_braces_struct());
+ }
+ else if ( get_chunk_parent_type(first) == CT_OC_AT
+ && options::sp_inside_braces_oc_dict() != IARF_IGNORE)
+ {
+ // (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}'
+ log_rule("sp_inside_braces_oc_dict");
+ return(options::sp_inside_braces_oc_dict());
+ }
+
+ if (get_chunk_parent_type(first) == CT_BRACED_INIT_LIST)
+ {
+ // Add or remove space between nested braces, i.e. '{{' vs. '{ {'.
+ // only to help the vim command }}}}
+ if ( options::sp_brace_brace() != IARF_IGNORE
+ && chunk_is_token(second, CT_BRACE_OPEN)
+ && get_chunk_parent_type(second) == CT_BRACED_INIT_LIST)
+ {
+ log_rule("sp_brace_brace");
+ return(options::sp_brace_brace());
+ }
+
+ if (options::sp_after_type_brace_init_lst_open() != IARF_IGNORE)
+ {
+ // Add or remove space after open brace in an unnamed temporary
+ // direct-list-initialization
+ // if statement is a brace_init_lst
+ // works only if sp_brace_brace is set to ignore.
+ log_rule("sp_after_type_brace_init_lst_open");
+ return(options::sp_after_type_brace_init_lst_open());
+ }
+
+ if (options::sp_inside_type_brace_init_lst() != IARF_IGNORE)
+ {
+ // Add or remove space inside an unnamed temporary direct-list-initialization
+ // if statement is a brace_init_lst
+ // works only if sp_brace_brace is set to ignore
+ // works only if sp_after_type_brace_init_lst_close is set to ignore.
+ log_rule("sp_inside_type_brace_init_lst");
+ return(options::sp_inside_type_brace_init_lst());
+ }
+ }
+
+ if (!second->IsComment())
+ {
+ // Add or remove space inside '{' and '}'.
+ log_rule("sp_inside_braces");
+ return(options::sp_inside_braces());
+ }
+ }
+
+ if ( chunk_is_token(first, CT_BRACE_CLOSE)
+ && first->flags.test(PCF_IN_TYPEDEF)
+ && ( get_chunk_parent_type(first) == CT_ENUM
+ || get_chunk_parent_type(first) == CT_STRUCT
+ || get_chunk_parent_type(first) == CT_UNION))
+ {
+ // Add or remove space between '}' and the name of a typedef on the same line.
+ log_rule("sp_brace_typedef");
+ return(options::sp_brace_typedef());
+ }
+
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(second, CT_PAREN_OPEN)
+ && get_chunk_parent_type(second) == CT_TEMPLATE)
+ {
+ // (D) Add or remove space before the parenthesis in the D constructs
+ // 'template Foo(' and 'class Foo('.
+ log_rule("sp_before_template_paren");
+ return(options::sp_before_template_paren());
+ }
+
+ // Issue #3080
+ if ( chunk_is_token(first, CT_PAREN_CLOSE)
+ && get_chunk_parent_type(first) == CT_DECLTYPE
+ && ( chunk_is_token(second, CT_WORD)
+ || chunk_is_token(second, CT_BRACE_OPEN)
+ || chunk_is_token(second, CT_FUNC_CALL)))
+ {
+ iarf_e arg = options::sp_after_decltype();
+ // Add or remove space between 'decltype(...)' and word, brace or function call.
+ log_rule("sp_after_decltype");
+ return(arg);
+ }
+
+ // Issue #3080
+ if ( !language_is_set(LANG_D)
+ && chunk_is_token(first, CT_PAREN_CLOSE)
+ && chunk_is_token(second, CT_WORD))
+ {
+ // Add or remove space between type and word.
+ log_rule("sp_after_type");
+ return(options::sp_after_type());
+ }
+
+ // see if the D template expression is used as a type
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(first, CT_PAREN_CLOSE)
+ && get_chunk_parent_type(first) == CT_D_TEMPLATE)
+ {
+ if (get_chunk_parent_type(second) == CT_USING_ALIAS)
+ {
+ log_rule("sp_after_type | ADD");
+ return(options::sp_after_type() | IARF_ADD);
+ }
+
+ if (chunk_is_token(second, CT_WORD))
+ {
+ Chunk *open_paren = chunk_skip_to_match_rev(first);
+
+ if (open_paren == nullptr)
+ {
+ open_paren = Chunk::NullChunkPtr;
+ }
+ Chunk *type = open_paren->GetPrev()->GetPrev();
+
+ if (chunk_is_token(type, CT_TYPE))
+ {
+ log_rule("sp_after_type");
+ return(options::sp_after_type());
+ }
+ }
+ }
+
+ if ( chunk_is_token(first, CT_TYPE) // Issue #3457
+ && chunk_is_token(second, CT_COLON))
+ {
+ log_rule("sp_type_colon");
+ return(options::sp_type_colon());
+ }
+
+ if ( !chunk_is_token(second, CT_PTR_TYPE)
+ && ( chunk_is_token(first, CT_QUALIFIER)
+ || chunk_is_token(first, CT_TYPE)))
+ {
+ // Add or remove space between type and word. In cases where total removal of
+ // whitespace would be a syntax error, a value of 'remove' is treated the same
+ // as 'force'.
+ //
+ // This also affects some other instances of space following a type that are
+ // not covered by other options; for example, between the return type and
+ // parenthesis of a function type template argument, between the type and
+ // parenthesis of an array parameter, or between 'decltype(...)' and the
+ // following word.
+ iarf_e arg = options::sp_after_type();
+ log_rule("sp_after_type");
+ return(arg);
+ }
+
+ if ( chunk_is_token(first, CT_PTR_TYPE)
+ && chunk_is_token(second, CT_ELLIPSIS))
+ {
+ log_rule("sp_ptr_type_ellipsis");
+ return(options::sp_ptr_type_ellipsis());
+ }
+
+ // If nothing claimed the PTR_TYPE, then return ignore
+ if ( chunk_is_token(first, CT_PTR_TYPE)
+ || chunk_is_token(second, CT_PTR_TYPE))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ if (chunk_is_token(first, CT_NOT))
+ {
+ if ( chunk_is_token(second, CT_NOT)
+ && (options::sp_not_not() != IARF_IGNORE))
+ {
+ log_rule("sp_not_not");
+ return(options::sp_not_not());
+ }
+ // Add or remove space after the '!' (not) unary operator.
+ log_rule("sp_not");
+ return(options::sp_not());
+ }
+
+ if (chunk_is_token(first, CT_INV))
+ {
+ // Add or remove space after the '~' (invert) unary operator.
+ log_rule("sp_inv");
+ return(options::sp_inv());
+ }
+
+ if (chunk_is_token(first, CT_ADDR))
+ {
+ // Add or remove space after the '&' (address-of) unary operator. This does not
+ // affect the spacing after a '&' that is part of a type.
+ log_rule("sp_addr");
+ return(options::sp_addr());
+ }
+
+ if (chunk_is_token(first, CT_DEREF))
+ {
+ // Add or remove space after the '*' (dereference) unary operator. This does
+ // not affect the spacing after a '*' that is part of a type.
+ log_rule("sp_deref");
+ return(options::sp_deref());
+ }
+
+ if ( chunk_is_token(first, CT_POS)
+ || chunk_is_token(first, CT_NEG))
+ {
+ // Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'.
+ log_rule("sp_sign");
+ return(options::sp_sign());
+ }
+
+ if ( chunk_is_token(first, CT_INCDEC_BEFORE)
+ || chunk_is_token(second, CT_INCDEC_AFTER))
+ {
+ // Add or remove space between '++' and '--' the word to which it is being
+ // applied, as in '(--x)' or 'y++;'.
+ log_rule("sp_incdec");
+ return(options::sp_incdec());
+ }
+
+ if (chunk_is_token(second, CT_CS_SQ_COLON))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (chunk_is_token(first, CT_CS_SQ_COLON))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_OC_SCOPE))
+ {
+ // (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;'
+ // or '+(int) bar;'.
+ log_rule("sp_after_oc_scope");
+ return(options::sp_after_oc_scope());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_OC_DICT_COLON))
+ {
+ // (OC) Add or remove space after the colon in immutable dictionary expression
+ // 'NSDictionary *test = @{@"foo" :@"bar"};'.
+ log_rule("sp_after_oc_dict_colon");
+ return(options::sp_after_oc_dict_colon());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(second, CT_OC_DICT_COLON))
+ {
+ // (OC) Add or remove space before the colon in immutable dictionary expression
+ // 'NSDictionary *test = @{@"foo" :@"bar"};'.
+ log_rule("sp_before_oc_dict_colon");
+ return(options::sp_before_oc_dict_colon());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_OC_COLON))
+ {
+ if (first->flags.test(PCF_IN_OC_MSG))
+ {
+ // (OC) Add or remove space after the colon in message specs,
+ // i.e. '[object setValue:1];' vs. '[object setValue: 1];'.
+ log_rule("sp_after_send_oc_colon");
+ return(options::sp_after_send_oc_colon());
+ }
+ // (OC) Add or remove space after the colon in message specs,
+ // i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'.
+ log_rule("sp_after_oc_colon");
+ return(options::sp_after_oc_colon());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(second, CT_OC_COLON))
+ {
+ if ( first->flags.test(PCF_IN_OC_MSG)
+ && ( chunk_is_token(first, CT_OC_MSG_FUNC)
+ || chunk_is_token(first, CT_OC_MSG_NAME)))
+ {
+ // (OC) Add or remove space before the colon in message specs,
+ // i.e. '[object setValue:1];' vs. '[object setValue :1];'.
+ log_rule("sp_before_send_oc_colon");
+ return(options::sp_before_send_oc_colon());
+ }
+ // (OC) Add or remove space before the colon in message specs,
+ // i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'.
+ log_rule("sp_before_oc_colon");
+ return(options::sp_before_oc_colon());
+ }
+
+ if ( chunk_is_token(second, CT_COMMENT)
+ && get_chunk_parent_type(second) == CT_COMMENT_EMBED)
+ {
+ // Add or remove space before an embedded comment.
+ // Number of spaces before an embedded comment.
+ log_rule("sp_before_emb_cmt");
+ min_sp = options::sp_num_before_emb_cmt();
+ return(options::sp_before_emb_cmt());
+ }
+
+ if (chunk_is_token(first, CT_COMMENT))
+ {
+ // Add or remove space after an embedded comment.
+ // Number of spaces after an embedded comment.
+ log_rule("sp_after_emb_cmt");
+ min_sp = options::sp_num_after_emb_cmt();
+ return(options::sp_after_emb_cmt());
+ }
+
+ if ( chunk_is_token(first, CT_NEW)
+ && chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // c# new Constraint, c++ new operator
+ // Add or remove space between 'new' and '(' in 'new()'.
+ log_rule("sp_between_new_paren");
+ return(options::sp_between_new_paren());
+ }
+
+ if ( chunk_is_token(first, CT_NEW)
+ || chunk_is_token(first, CT_DELETE)
+ || ( chunk_is_token(first, CT_TSQUARE)
+ && get_chunk_parent_type(first) == CT_DELETE))
+ {
+ // Add or remove space after 'new', 'delete' and 'delete[]'.
+ log_rule("sp_after_new");
+ return(options::sp_after_new());
+ }
+
+ if ( language_is_set(LANG_JAVA)
+ && chunk_is_token(first, CT_ANNOTATION)
+ && chunk_is_paren_open(second))
+ {
+ // (Java) Add or remove space between an annotation and the open parenthesis.
+ log_rule("sp_annotation_paren");
+ return(options::sp_annotation_paren());
+ }
+
+ if ( language_is_set(LANG_OC)
+ && chunk_is_token(first, CT_OC_PROPERTY))
+ {
+ // (OC) Add or remove space after '@property'.
+ log_rule("sp_after_oc_property");
+ return(options::sp_after_oc_property());
+ }
+
+ if ( language_is_set(LANG_D)
+ && chunk_is_token(first, CT_EXTERN)
+ && chunk_is_token(second, CT_PAREN_OPEN))
+ {
+ // (D) Add or remove space between 'extern' and '(' as in 'extern (C)'.
+ log_rule("sp_extern_paren");
+ return(options::sp_extern_paren());
+ }
+
+ if ( chunk_is_token(second, CT_TYPE)
+ && ( ( chunk_is_token(first, CT_STRING)
+ && get_chunk_parent_type(first) == CT_EXTERN)
+ || ( chunk_is_token(first, CT_FPAREN_CLOSE)
+ && get_chunk_parent_type(first) == CT_ATTRIBUTE)))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE); /* TODO: make this configurable? */
+ }
+
+ if (chunk_is_token(first, CT_NOEXCEPT))
+ {
+ // Add or remove space after 'noexcept'.
+ log_rule("sp_after_noexcept");
+ return(options::sp_after_noexcept());
+ }
+
+ // Issue #2138
+ if (chunk_is_token(first, CT_FPAREN_CLOSE))
+ {
+ if (chunk_is_token(second, CT_QUALIFIER))
+ {
+ // Add or remove space between ')' and a qualifier such as 'const'.
+ log_rule("sp_paren_qualifier");
+ return(options::sp_paren_qualifier());
+ }
+ else if (chunk_is_token(second, CT_NOEXCEPT))
+ {
+ // Add or remove space between ')' and 'noexcept'.
+ log_rule("sp_paren_noexcept");
+ return(options::sp_paren_noexcept());
+ }
+ }
+
+ // Issue #2098
+ if ( chunk_is_token(first, CT_PP_PRAGMA)
+ && chunk_is_token(second, CT_PREPROC_BODY))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ // Issue #1733
+ if ( chunk_is_token(first, CT_OPERATOR_VAL)
+ && chunk_is_token(second, CT_TYPE))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ // Issue #995
+ if ( chunk_is_token(first, CT_DO)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ // Add or remove space between 'do' and '{'.
+ log_rule("sp_do_brace_open");
+ return(options::sp_do_brace_open());
+ }
+
+ // Issue #995
+ if ( chunk_is_token(first, CT_BRACE_CLOSE)
+ && chunk_is_token(second, CT_WHILE_OF_DO))
+ {
+ // Add or remove space between '}' and 'while.
+ log_rule("sp_brace_close_while");
+ return(options::sp_brace_close_while());
+ }
+
+ // TODO: have a look to Issue #2186, why NEWLINE?
+ // Issue #2524
+ if ( chunk_is_token(first, CT_NEWLINE)
+ && chunk_is_token(second, CT_BRACE_OPEN))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ // =============================================================
+ // categorie 1
+ // this table lists out all combos where a space should NOT be present
+ // CT_UNKNOWN is a wildcard.
+ for (auto it : no_space_table)
+ {
+ if ( ( it.first == CT_UNKNOWN
+ || it.first == first->type)
+ && ( it.second == CT_UNKNOWN
+ || it.second == second->type))
+ {
+ log_rule("REMOVE from no_space_table");
+ return(IARF_REMOVE);
+ }
+ }
+
+ // =============================================================
+ // categorie 2
+ // this table lists out all combos where a space MUST be present
+ for (auto it : add_space_table)
+ {
+ if ( it.first == first->type
+ && it.second == second->type)
+ {
+ // TODO: if necessary create a new option
+ log_rule("ADD from add_space_table");
+ return(IARF_ADD);
+ }
+ }
+
+ // Issue #2386
+ if ( chunk_is_token(first, CT_FORM_FEED)
+ || chunk_is_token(second, CT_FORM_FEED))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ // TODO: if necessary create a new option
+ if ( chunk_is_token(first, CT_MACRO_FUNC_CALL)
+ && chunk_is_token(second, CT_FPAREN_OPEN))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ if ( chunk_is_token(first, CT_CASE_ELLIPSIS)
+ && chunk_is_token(second, CT_NUMBER))
+ {
+ // Add or remove space after the variadic '...' when preceded by a
+ // non-punctuator.
+ // The value REMOVE will be overridden with FORCE
+ if (options::sp_after_ellipsis() == IARF_REMOVE)
+ {
+ log_rule("sp_after_ellipsis/FORCE");
+ return(IARF_FORCE);
+ }
+ else
+ {
+ log_rule("sp_after_ellipsis");
+ return(options::sp_after_ellipsis());
+ }
+ }
+
+ if ( chunk_is_token(first, CT_NUMBER)
+ && chunk_is_token(second, CT_CASE_ELLIPSIS))
+ {
+ // Add or remove space before the variadic '...' when preceded by a
+ // non-punctuator.
+ // The value REMOVE will be overridden with FORCE
+ if (options::sp_before_ellipsis() == IARF_REMOVE)
+ {
+ log_rule("sp_before_ellipsis/FORCE");
+ return(IARF_FORCE);
+ }
+ else
+ {
+ log_rule("sp_before_ellipsis");
+ return(options::sp_before_ellipsis());
+ }
+ }
+ // =============================================================
+ // categorie 3
+ // these lines are only useful for debugging uncrustify itself
+ LOG_FMT(LSPACE, "\n\n%s(%d): WARNING: unrecognize do_space:\n",
+ __func__, __LINE__);
+ LOG_FMT(LSPACE, " first->orig_line is %zu, first->orig_col is %zu, first->Text() '%s', first->type is %s\n",
+ first->orig_line, first->orig_col, first->Text(), get_token_name(first->type));
+ LOG_FMT(LSPACE, " second->orig_line is %zu, second->orig_col is %zu, second->Text() '%s', second->type is %s\n",
+ second->orig_line, second->orig_col, second->Text(), get_token_name(second->type));
+ LOG_FMT(LSPACE, " Please make a call at https://github.com/uncrustify/uncrustify/issues/new\n");
+ LOG_FMT(LSPACE, " or merge the line:\n");
+ LOG_FMT(LSPACE, " {%s, %s},\n",
+ get_token_name(first->type), get_token_name(second->type));
+ LOG_FMT(LSPACE, " in the file <Path_to_uncrustify>/src/add_space_table.h\n");
+
+ log_rule("ADD as default value");
+ return(IARF_ADD);
+} // do_space
+
+
+static iarf_e ensure_force_space(Chunk *first, Chunk *second, iarf_e av)
+{
+ if (first->flags.test(PCF_FORCE_SPACE))
+ {
+ LOG_FMT(LSPACE, "%s(%d): <force between '%s' and '%s'>",
+ __func__, __LINE__, first->Text(), second->Text());
+ return(av | IARF_ADD);
+ }
+ return(av);
+}
+
+
+static iarf_e do_space_ensured(Chunk *first, Chunk *second, int &min_sp)
+{
+ iarf_e aa = ensure_force_space(first, second, do_space(first, second, min_sp));
+
+ return(aa);
+}
+
+
+void space_text(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+ Chunk *next;
+ size_t prev_column;
+ size_t column = pc->column;
+
+ while (pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LSPACE, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->nl_count);
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LSPACE, "%s(%d): orig_line is %zu, orig_col is %zu, '%s' type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy), get_token_name(pc->type));
+ }
+
+ if ( (options::use_options_overriding_for_qt_macros())
+ && ( (strcmp(pc->Text(), "SIGNAL") == 0)
+ || (strcmp(pc->Text(), "SLOT") == 0)))
+ {
+ LOG_FMT(LSPACE, "%s(%d): orig_col is %zu, type is %s SIGNAL/SLOT found\n",
+ __func__, __LINE__, pc->orig_line, get_token_name(pc->type));
+ chunk_flags_set(pc, PCF_IN_QT_MACRO); // flag the chunk for a second processing
+
+ // save the values
+ save_set_options_for_QT(pc->level);
+ }
+
+ // Bug # 637
+ // If true, vbrace tokens are dropped to the previous token and skipped.
+ if (options::sp_skip_vbrace_tokens())
+ {
+ next = pc->GetNext();
+
+ while ( next->IsEmptyText()
+ && !chunk_is_newline(next)
+ && ( chunk_is_token(next, CT_VBRACE_OPEN)
+ || chunk_is_token(next, CT_VBRACE_CLOSE)))
+ {
+ LOG_FMT(LSPACE, "%s(%d): orig_line is %zu, orig_col is %zu, Skip %s (%zu+%zu)\n",
+ __func__, __LINE__, next->orig_line, next->orig_col, get_token_name(next->type),
+ pc->column, pc->str.size());
+ next->column = pc->column + pc->str.size();
+ next = next->GetNext();
+ }
+ }
+ else
+ {
+ next = pc->GetNext();
+ }
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+
+ // Issue # 481
+ // Whether to balance spaces inside nested parentheses.
+ if ( QT_SIGNAL_SLOT_found
+ && options::sp_balance_nested_parens())
+ {
+ Chunk *nn = next->GetNext(); // Issue #2734
+
+ if ( nn->IsNotNullChunk()
+ && chunk_is_token(nn, CT_SPACE))
+ {
+ chunk_del(nn); // remove the space
+ }
+ }
+
+ /*
+ * If the current chunk contains a newline, do not change the column
+ * of the next item
+ */
+ if ( chunk_is_token(pc, CT_NEWLINE)
+ || chunk_is_token(pc, CT_NL_CONT)
+ || chunk_is_token(pc, CT_COMMENT_MULTI))
+ {
+ column = next->column;
+ }
+ else
+ {
+ // Set to the minimum allowed column
+ if (pc->nl_count == 0)
+ {
+ column += pc->Len();
+ }
+ else
+ {
+ column = pc->orig_col_end;
+ }
+ prev_column = column;
+
+ /*
+ * Apply a general safety check
+ * If the two chunks combined will tokenize differently, then we
+ * must force a space.
+ * Two chunks -- "()" and "[]" will always tokenize differently.
+ * They are always safe to not have a space after them.
+ */
+ chunk_flags_clr(pc, PCF_FORCE_SPACE);
+
+ if ( (pc->Len() > 0)
+ && !chunk_is_str(pc, "[]")
+ && !chunk_is_str(pc, "{{")
+ && !chunk_is_str(pc, "}}")
+ && !chunk_is_str(pc, "()")
+ && !pc->str.startswith("@\""))
+ {
+ // Find the next non-empty chunk on this line
+ Chunk *tmp = next;
+
+ while ( tmp->IsNotNullChunk()
+ && (tmp->Len() == 0)
+ && !chunk_is_newline(tmp))
+ {
+ tmp = tmp->GetNext();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->Len() > 0)
+ {
+ bool kw1 = CharTable::IsKw2(pc->str[pc->Len() - 1]);
+ bool kw2 = CharTable::IsKw1(next->str[0]);
+
+ if ( kw1
+ && kw2)
+ {
+ // back-to-back words need a space
+ LOG_FMT(LSPACE, "%s(%d): back-to-back words need a space: pc->Text() '%s', next->Text() '%s'\n",
+ __func__, __LINE__, pc->Text(), next->Text());
+ chunk_flags_set(pc, PCF_FORCE_SPACE);
+ }
+ // TODO: what is the meaning of 4
+ else if ( !kw1
+ && !kw2
+ && (pc->Len() < 4)
+ && (next->Len() < 4))
+ {
+ // We aren't dealing with keywords. concat and try punctuators
+ char buf[9];
+ memcpy(buf, pc->Text(), pc->Len());
+ memcpy(buf + pc->Len(), next->Text(), next->Len());
+ buf[pc->Len() + next->Len()] = 0;
+
+ const chunk_tag_t *ct;
+ ct = find_punctuator(buf, cpd.lang_flags);
+
+ if ( ct != nullptr
+ && (strlen(ct->tag) != pc->Len()))
+ {
+ // punctuator parsed to a different size..
+
+ /*
+ * C++11 allows '>>' to mean '> >' in templates:
+ * some_func<vector<string>>();
+ */
+ // (C++11) Permit removal of the space between '>>' in 'foo<bar<int> >'. Note
+ // that sp_angle_shift cannot remove the space without this option.
+ if ( ( ( language_is_set(LANG_CPP)
+ && options::sp_permit_cpp11_shift())
+ || (language_is_set(LANG_JAVA | LANG_CS | LANG_VALA | LANG_OC)))
+ && chunk_is_token(pc, CT_ANGLE_CLOSE)
+ && chunk_is_token(next, CT_ANGLE_CLOSE))
+ {
+ // allow '>' and '>' to become '>>'
+ }
+ else if (strcmp(ct->tag, "[]") == 0)
+ {
+ // this is OK
+ }
+ else
+ {
+ LOG_FMT(LSPACE, "%s(%d): : pc->Text() is %s, next->Text() is %s\n",
+ __func__, __LINE__, pc->Text(), next->Text());
+ chunk_flags_set(pc, PCF_FORCE_SPACE);
+ }
+ }
+ }
+ }
+ }
+ int min_sp;
+ LOG_FMT(LSPACE, "%s(%d): orig_line is %zu, orig_col is %zu, pc-Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text(), get_token_name(pc->type));
+ iarf_e av = do_space_ensured(pc, next, min_sp);
+ min_sp = max(1, min_sp);
+
+ switch (av)
+ {
+ case IARF_FORCE:
+ column += min_sp; // add exactly the specified number of spaces
+ break;
+
+ case IARF_ADD:
+ {
+ int delta = min_sp;
+
+ if ( next->orig_col >= pc->orig_col_end
+ && pc->orig_col_end != 0)
+ {
+ // Keep the same relative spacing, minimum 1
+ delta = next->orig_col - pc->orig_col_end;
+
+ if (delta < min_sp)
+ {
+ delta = min_sp;
+ }
+ }
+ column += delta;
+ break;
+ }
+
+ case IARF_REMOVE:
+ // the symbols will be back-to-back "a+3"
+ break;
+
+ case IARF_IGNORE:
+
+ // Keep the same relative spacing, if possible
+ if ( next->orig_col >= pc->orig_col_end
+ && pc->orig_col_end != 0)
+ {
+ column += next->orig_col - pc->orig_col_end;
+ }
+ else
+ {
+ // preserve the position if virtual brace
+ // Issue #1854
+ if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ column = next->orig_col;
+ }
+ }
+ break;
+
+ default:
+ // If we got here, something is wrong...
+ break;
+ } // switch
+
+ if ( next->IsComment()
+ && chunk_is_newline(next->GetNext())
+ && column < next->orig_col)
+ {
+ /*
+ * do some comment adjustments if sp_before_tr_cmt and sp_endif_cmt
+ * did not apply.
+ */
+ // Add or remove space between #else or #endif and a trailing comment.
+ if ( ( options::sp_before_tr_cmt() == IARF_IGNORE
+ || get_chunk_parent_type(next) != CT_COMMENT_END)
+ && ( options::sp_endif_cmt() == IARF_IGNORE
+ || ( pc->type != CT_PP_ELSE
+ && pc->type != CT_PP_ENDIF)))
+ {
+ if (options::indent_relative_single_line_comments())
+ {
+ // Try to keep relative spacing between tokens
+ LOG_FMT(LSPACE, "%s(%d): <relative adj>", __func__, __LINE__);
+ LOG_FMT(LSPACE, "%s(%d): pc is '%s', pc->orig_col is %zu, next->orig_col is %zu, pc->orig_col_end is %zu\n",
+ __func__, __LINE__, pc->Text(),
+ pc->orig_col, next->orig_col, pc->orig_col_end);
+ column = pc->column + (next->orig_col - pc->orig_col_end);
+ }
+ else
+ {
+ /*
+ * If there was a space, we need to force one, otherwise
+ * try to keep the comment in the same column.
+ */
+ size_t col_min = pc->column + pc->Len() + ((next->orig_prev_sp > 0) ? 1 : 0);
+ column = next->orig_col;
+
+ if (column < col_min)
+ {
+ column = col_min;
+ }
+ LOG_FMT(LSPACE, "%s(%d): <relative set>", __func__, __LINE__);
+ }
+ }
+ }
+ next->column = column;
+
+ LOG_FMT(LSPACE, " rule = %s @ %zu => %zu\n",
+ (av == IARF_IGNORE) ? "IGNORE" :
+ (av == IARF_ADD) ? "ADD" :
+ (av == IARF_REMOVE) ? "REMOVE" : "FORCE",
+ column - prev_column, next->column);
+
+ if (restoreValues) // guy 2015-09-22
+ {
+ restore_options_for_QT();
+ }
+ }
+ pc = next;
+
+ if (QT_SIGNAL_SLOT_found)
+ {
+ // flag the chunk for a second processing
+ chunk_flags_set(pc, PCF_IN_QT_MACRO);
+ }
+ }
+} // space_text
+
+
+void space_text_balance_nested_parens(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *first = Chunk::GetHead();
+
+ while (first->IsNotNullChunk())
+ {
+ Chunk *next = first->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+
+ // if there are two successive opening parenthesis
+ if ( chunk_is_str(first, "(")
+ && chunk_is_str(next, "("))
+ {
+ // insert a space between them
+ space_add_after(first, 1);
+
+ // test after the closing parens Issue #1703
+ Chunk *closing = first->GetNextType((E_Token)(first->type + 1), first->level);
+
+ if (closing->orig_col == closing->prev->orig_col_end)
+ {
+ space_add_after(closing->prev, 1);
+ }
+ }
+ else if ( chunk_is_str(first, ")")
+ && chunk_is_str(next, ")"))
+ {
+ // insert a space between the two closing parens
+ space_add_after(first, 1);
+
+ // test after the opening parens Issue #1703
+ Chunk *opening = next->GetPrevType((E_Token)(next->type - 1), next->level);
+
+ if (opening->orig_col_end == opening->GetNext()->orig_col)
+ {
+ space_add_after(opening, 1);
+ }
+ }
+ first = next;
+ }
+} // space_text_balance_nested_parens
+
+
+size_t space_needed(Chunk *first, Chunk *second)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPACE, "%s(%d)\n", __func__, __LINE__);
+
+ int min_sp;
+
+ switch (do_space_ensured(first, second, min_sp))
+ {
+ case IARF_ADD:
+ case IARF_FORCE:
+ return(max(1, min_sp));
+
+ case IARF_REMOVE:
+ return(0);
+
+ case IARF_IGNORE:
+ default:
+ return(second->orig_col > (first->orig_col + first->Len()));
+ }
+}
+
+
+size_t space_col_align(Chunk *first, Chunk *second)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LSPACE, "%s(%d): first->orig_line is %zu, orig_col is %zu, [%s/%s], Text() '%s' <==>\n",
+ __func__, __LINE__, first->orig_line, first->orig_col,
+ get_token_name(first->type), get_token_name(get_chunk_parent_type(first)),
+ first->Text());
+ LOG_FMT(LSPACE, "%s(%d): second->orig_line is %zu, orig_col is %zu [%s/%s], Text() '%s',",
+ __func__, __LINE__, second->orig_line, second->orig_col,
+ get_token_name(second->type), get_token_name(get_chunk_parent_type(second)),
+ second->Text());
+ log_func_stack_inline(LSPACE);
+
+ int min_sp;
+ iarf_e av = do_space_ensured(first, second, min_sp);
+
+ LOG_FMT(LSPACE, "%s(%d): av is %s\n", __func__, __LINE__, to_string(av));
+ size_t coldiff;
+
+ if (first->nl_count)
+ {
+ LOG_FMT(LSPACE, "%s(%d): nl_count is %zu, orig_col_end is %zu\n", __func__, __LINE__, first->nl_count, first->orig_col_end);
+ coldiff = first->orig_col_end - 1;
+ }
+ else
+ {
+ LOG_FMT(LSPACE, "%s(%d): Len is %zu\n", __func__, __LINE__, first->Len());
+ coldiff = first->Len();
+ }
+ LOG_FMT(LSPACE, "%s(%d): => coldiff is %zu\n", __func__, __LINE__, coldiff);
+
+ LOG_FMT(LSPACE, "%s(%d): => av is %s\n", __func__, __LINE__,
+ (av == IARF_IGNORE) ? "IGNORE" :
+ (av == IARF_ADD) ? "ADD" :
+ (av == IARF_REMOVE) ? "REMOVE" : "FORCE");
+
+ switch (av)
+ {
+ case IARF_ADD:
+ case IARF_FORCE:
+ coldiff++;
+ break;
+
+ case IARF_REMOVE:
+ break;
+
+ case IARF_IGNORE: // Issue #2064
+ LOG_FMT(LSPACE, "%s(%d): => first->orig_line is %zu\n", __func__, __LINE__, first->orig_line);
+ LOG_FMT(LSPACE, "%s(%d): => second->orig_line is %zu\n", __func__, __LINE__, second->orig_line);
+ LOG_FMT(LSPACE, "%s(%d): => first->Text() is '%s'\n", __func__, __LINE__, first->Text());
+ LOG_FMT(LSPACE, "%s(%d): => second->Text() is '%s'\n", __func__, __LINE__, second->Text());
+ LOG_FMT(LSPACE, "%s(%d): => first->orig_col is %zu\n", __func__, __LINE__, first->orig_col);
+ LOG_FMT(LSPACE, "%s(%d): => second->orig_col is %zu\n", __func__, __LINE__, second->orig_col);
+ LOG_FMT(LSPACE, "%s(%d): => first->Len() is %zu\n", __func__, __LINE__, first->Len());
+
+ if ( first->orig_line == second->orig_line
+ && second->orig_col > (first->orig_col + first->Len()))
+ {
+ coldiff++;
+ }
+ break;
+
+ default:
+ // If we got here, something is wrong...
+ break;
+ }
+ LOG_FMT(LSPACE, "%s(%d): => coldiff is %zu\n", __func__, __LINE__, coldiff);
+ return(coldiff);
+} // space_col_align
+
+
+void space_add_after(Chunk *pc, size_t count)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *next = pc->GetNext();
+
+ // don't add at the end of the file or before a newline
+ if ( next->IsNullChunk()
+ || chunk_is_newline(next))
+ {
+ return;
+ }
+
+ // Limit to 16 spaces
+ if (count > 16)
+ {
+ count = 16;
+ }
+
+ // Two CT_SPACE in a row -- use the max of the two
+ if (chunk_is_token(next, CT_SPACE))
+ {
+ if (next->Len() < count)
+ {
+ while (next->Len() < count)
+ {
+ next->str.append(' ');
+ }
+ }
+ return;
+ }
+ Chunk sp;
+
+ set_chunk_type(&sp, CT_SPACE);
+ sp.flags = pc->flags & PCF_COPY_FLAGS;
+ sp.str = " "; // 16 spaces
+ sp.str.resize(count);
+ sp.level = pc->level;
+ sp.brace_level = pc->brace_level;
+ sp.pp_level = pc->pp_level;
+ sp.column = pc->column + pc->Len();
+ sp.orig_line = pc->orig_line;
+ sp.orig_col = pc->orig_col;
+
+ chunk_add_after(&sp, pc);
+} // space_add_after
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.h
new file mode 100644
index 00000000..3989e126
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/space.h
@@ -0,0 +1,45 @@
+/**
+ * @file space.h
+ * prototypes for space.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef SPACE_H_INCLUDED
+#define SPACE_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * Marches through the whole file and checks to see how many spaces should be
+ * between two chunks
+ */
+void space_text(void);
+
+
+//! Marches through the whole file and adds spaces around nested parenthesis
+void space_text_balance_nested_parens(void);
+
+
+//! Determines if a space is required between two chunks
+size_t space_needed(Chunk *first, Chunk *second);
+
+
+/**
+ * Calculates the column difference between two chunks.
+ * The rules are bent a bit here, as IARF_IGNORE and IARF_ADD become IARF_FORCE.
+ * So the column difference is either first->len or first->len + 1.
+ *
+ * @param first The first chunk
+ * @param second The second chunk
+ *
+ * @return the column difference between the two chunks
+ */
+size_t space_col_align(Chunk *first, Chunk *second);
+
+
+void space_add_after(Chunk *pc, size_t count);
+
+
+#endif /* SPACE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/symbols_table.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/symbols_table.h
new file mode 100644
index 00000000..1a864478
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/symbols_table.h
@@ -0,0 +1,146 @@
+/**
+ * @file symbols
+ * Manages the table of punctuators.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+/**
+ *
+ * Contet of the generated "punctuator_table.h" file is based off this.
+ *
+ * NOTE: the tables below do not need to be sorted.
+ */
+
+// 6-char symbols
+static const chunk_tag_t symbols6[] =
+{
+ { R"_(??(??))_", CT_TSQUARE, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph []
+ { R"_(??!??!)_", CT_BOOL, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph ||
+ { R"_(??=??=)_", CT_PP, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph ##
+};
+
+/* 5-char symbols */
+static const chunk_tag_t symbols5[] =
+{
+ { R"_(??!=)_", CT_ASSIGN, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph |=
+ { R"_(??'=)_", CT_ASSIGN, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph ^=
+ { R"_(??=@)_", CT_POUND, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph #@ MS extension
+};
+
+/* 4-char symbols */
+static const chunk_tag_t symbols4[] =
+{
+ { "!<>=", CT_COMPARE, LANG_D },
+ { ">>>=", CT_ASSIGN, LANG_D | LANG_JAVA | LANG_PAWN },
+ { R"_(<::>)_", CT_TSQUARE, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // digraph []
+ { R"_(%:%:)_", CT_PP, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // digraph ##
+};
+
+// 3-char symbols
+static const chunk_tag_t symbols3[] =
+{
+ { "!<=", CT_COMPARE, LANG_D },
+ { "!<>", CT_COMPARE, LANG_D },
+ { "!==", CT_COMPARE, LANG_D | LANG_ECMA },
+ { "!>=", CT_COMPARE, LANG_D },
+ { "<=>", CT_COMPARE, LANG_CPP },
+ { "->*", CT_MEMBER, LANG_C | LANG_CPP | LANG_OC | LANG_D },
+ { "...", CT_ELLIPSIS, LANG_C | LANG_CPP | LANG_OC | LANG_D | LANG_PAWN | LANG_JAVA },
+ { "<<=", CT_ASSIGN, LANG_ALL },
+ { "<>=", CT_COMPARE, LANG_D },
+ { "===", CT_COMPARE, LANG_D | LANG_ECMA },
+ { ">>=", CT_ASSIGN, LANG_ALL },
+ { ">>>", CT_ARITH, LANG_D | LANG_JAVA | LANG_PAWN | LANG_ECMA },
+ { "%:@", CT_POUND, LANG_C | LANG_CPP | LANG_OC }, // digraph #@ MS extension
+ { R"_(??=)_", CT_POUND, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph #
+ { R"_(??=)_", CT_COMPARE, LANG_CS }, // cs: Null-Coalescing Assignment Operator
+ { R"_(??()_", CT_SQUARE_OPEN, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph [
+ { R"_(??))_", CT_SQUARE_CLOSE, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph ]
+ { R"_(??')_", CT_CARET, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph ^
+ { R"_(??<)_", CT_BRACE_OPEN, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph {
+ { R"_(??>)_", CT_BRACE_CLOSE, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph }
+ { R"_(??-)_", CT_INV, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph ~
+ { R"_(??!)_", CT_ARITH, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph |
+};
+// { R"_(??/)_", CT_UNKNOWN, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // trigraph '\'
+
+// 2-char symbols
+static const chunk_tag_t symbols2[] =
+{
+ { "!<", CT_COMPARE, LANG_D }, // 0
+ { "!=", CT_COMPARE, LANG_ALL }, // 1
+ { "!>", CT_COMPARE, LANG_D }, // 2
+ { "!~", CT_COMPARE, LANG_D }, // 3
+ { "##", CT_PP, LANG_C | LANG_CPP | LANG_OC }, // 4
+ { "#@", CT_POUND, LANG_C | LANG_CPP | LANG_OC }, // MS extension
+ { "%=", CT_ASSIGN, LANG_ALL }, // 6
+ { "&&", CT_BOOL, LANG_ALL }, // 7
+ { "&=", CT_ASSIGN, LANG_ALL }, // 8
+ { "*=", CT_ASSIGN, LANG_ALL }, // 9
+ { "++", CT_INCDEC_AFTER, LANG_ALL }, // 10
+ { "+=", CT_ASSIGN, LANG_ALL }, // 11
+ { "--", CT_INCDEC_AFTER, LANG_ALL }, // 12
+ { "-=", CT_ASSIGN, LANG_ALL }, // 13
+ { "->", CT_MEMBER, LANG_ALLC }, // 14
+ { ".*", CT_MEMBER, LANG_C | LANG_CPP | LANG_OC | LANG_D }, // 15
+ { "..", CT_RANGE, LANG_D }, // 16
+ { "?.", CT_NULLCOND, LANG_CS }, // null conditional operator
+ { "/=", CT_ASSIGN, LANG_ALL }, // 18
+ { "::", CT_DC_MEMBER, LANG_ALLC }, // 19
+ { "<<", CT_SHIFT, LANG_ALL }, // 20
+ { "<=", CT_COMPARE, LANG_ALL }, // 21
+ { "<>", CT_COMPARE, LANG_D }, // 22
+ { "==", CT_COMPARE, LANG_ALL }, // 23
+ { ">=", CT_COMPARE, LANG_ALL }, // 24
+ { ">>", CT_SHIFT, LANG_ALL }, // 25
+ { "[]", CT_TSQUARE, LANG_ALL }, // 26
+ { "^=", CT_ASSIGN, LANG_ALL }, // 27
+ { "|=", CT_ASSIGN, LANG_ALL }, // 28
+ { "||", CT_BOOL, LANG_ALL }, // 29
+ { "~=", CT_COMPARE, LANG_D }, // 30
+ { "~~", CT_COMPARE, LANG_D }, // 31
+ { "=>", CT_LAMBDA, LANG_VALA | LANG_CS | LANG_D }, // 32
+ { "??", CT_COMPARE, LANG_CS | LANG_VALA }, // 33
+ { R"_(<%)_", CT_BRACE_OPEN, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // digraph {
+ { R"_(%>)_", CT_BRACE_CLOSE, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // digraph }
+ { R"_(<:)_", CT_SQUARE_OPEN, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // digraph [
+ { R"_(:>)_", CT_SQUARE_CLOSE, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // digraph ]
+ { R"_(%:)_", CT_POUND, LANG_C | LANG_CPP | LANG_OC | FLAG_DIG }, // digraph #
+};
+
+// *INDENT-OFF*
+// 1-char symbols
+static const chunk_tag_t symbols1[] =
+{
+ { R"_( )_", CT_FORM_FEED, LANG_ALL },
+ { "!", CT_NOT, LANG_ALL },
+ { "#", CT_POUND, LANG_ALL & ~(LANG_JAVA | LANG_ECMA) },
+ { "$", CT_COMPARE, LANG_D },
+ { "%", CT_ARITH, LANG_ALL },
+ { "&", CT_AMP, LANG_ALL },
+ { "(", CT_PAREN_OPEN, LANG_ALL },
+ { ")", CT_PAREN_CLOSE, LANG_ALL },
+ { "*", CT_STAR, LANG_ALL },
+ { "+", CT_PLUS, LANG_ALL },
+ { ",", CT_COMMA, LANG_ALL },
+ { "-", CT_MINUS, LANG_ALL },
+ { ".", CT_DOT, LANG_ALL },
+ { "/", CT_ARITH, LANG_ALL },
+ { ":", CT_COLON, LANG_ALL },
+ { ";", CT_SEMICOLON, LANG_ALL },
+ { "<", CT_ANGLE_OPEN, LANG_ALL },
+ { "=", CT_ASSIGN, LANG_ALL },
+ { ">", CT_ANGLE_CLOSE, LANG_ALL },
+ { "@", CT_OC_AT, LANG_OC },
+ { "?", CT_QUESTION, LANG_ALL },
+ { "[", CT_SQUARE_OPEN, LANG_ALL },
+ { "]", CT_SQUARE_CLOSE, LANG_ALL },
+ { "^", CT_CARET, LANG_ALL },
+ { "{", CT_BRACE_OPEN, LANG_ALL },
+ { "|", CT_ARITH, LANG_ALL },
+ { "}", CT_BRACE_CLOSE, LANG_ALL },
+ { "~", CT_INV, LANG_ALL },
+};
+// *INDENT-ON*
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/token_enum.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/token_enum.h
new file mode 100644
index 00000000..7a138d41
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/token_enum.h
@@ -0,0 +1,399 @@
+/**
+ * @file token_enum.h
+ * List of the different tokens used in the program.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * October 2015
+ * @license GPL v2+
+ */
+
+#ifndef TOKEN_ENUM_H_INCLUDED
+#define TOKEN_ENUM_H_INCLUDED
+
+/**
+ * abbreviations used:
+ * CT = chunk type
+ */
+
+
+/**
+ * This is an enum of all the different chunks/tokens/elements that the
+ * program can work with. The parser and scanner assigns one of these to
+ * each chunk/token.
+ */
+enum E_Token
+{
+ CT_NONE,
+ CT_PARENT_NOT_SET,
+ CT_EOF,
+ CT_UNKNOWN,
+
+ CT_JUNK, // junk collected when parsing is disabled
+
+ CT_WHITESPACE, // whitespace without any newlines
+ CT_SPACE, // a fixed number of spaces to support weird spacing rules
+ CT_NEWLINE, // CRA, one or more newlines
+ CT_NL_CONT, // CRA, backslash-newline
+ CT_FORM_FEED, // character 12
+ CT_COMMENT_CPP, // C++ comment (always followed by CT_NEWLINE)
+ CT_COMMENT, // C-comment, single line
+ CT_COMMENT_MULTI, // Multi-lined comment
+ CT_COMMENT_EMBED, // comment parent_type: non-newline before and after
+ CT_COMMENT_START, // comment parent_type: newline before
+ CT_COMMENT_END, // comment parent_type: newline after
+ CT_COMMENT_WHOLE, // comment parent_type: newline before and after
+ CT_COMMENT_ENDIF, // C-comment, single line, after ENDIF
+
+ CT_IGNORED, // a chunk of ignored text
+
+ CT_WORD, // variable, type, function name, etc
+ CT_NUMBER,
+ CT_NUMBER_FP,
+ CT_STRING, // quoted string "hi" or 'a' or <in> for include
+ CT_STRING_MULTI, // quoted string with embedded newline
+ CT_IF, // built-in keywords
+ CT_ELSE,
+ CT_ELSEIF,
+ CT_CONSTEXPR, // only when preceded by 'if' (otherwise CT_QUALIFIER)
+ CT_FOR,
+ CT_WHILE,
+ CT_WHILE_OF_DO,
+ CT_SWITCH,
+ CT_CASE,
+ CT_DO,
+ CT_SYNCHRONIZED,
+ CT_VOLATILE,
+ CT_TYPEDEF,
+ CT_STRUCT,
+ CT_ENUM,
+ CT_ENUM_CLASS,
+ CT_SIZEOF,
+ CT_DECLTYPE,
+ CT_RETURN,
+ CT_BREAK,
+ CT_UNION,
+ CT_GOTO,
+ CT_CONTINUE,
+ CT_C_CAST, // C-style cast: "(int)5.6"
+ CT_CPP_CAST, // C++-style cast: "int(5.6)"
+ CT_D_CAST, // D-style cast: "cast(type)" and "const(type)"
+ CT_TYPE_CAST, // static_cast<type>(exp)
+ CT_TYPENAME, // typename type
+ CT_TEMPLATE, // template<...>
+ CT_PARAMETER_PACK, // template<typename ... ARGS>
+ CT_WHERE_SPEC, // 'where' : used in C# generic constraint
+
+ CT_ASSIGN, // =, +=, /=, etc
+ CT_ASSIGN_NL, // Assign followed by a newline - fake item for indenting
+ CT_SASSIGN, // 'and_eq'
+
+ CT_ASSIGN_DEFAULT_ARG, // Default argument such as
+ // Foo( int Foo = 5 );
+ CT_ASSIGN_FUNC_PROTO, // function prototype modifier such as
+ // void* operator new(std::size_t) = delete;
+ // Foo( const Foo & ) = default;
+ // Foo( const Foo & ) = 0;
+
+ CT_COMPARE, // ==, !=, <=, >=
+ CT_SCOMPARE, // compare op that is a string 'is', 'neq'
+ CT_BOOL, // || or &&
+ CT_SBOOL, // or, and
+ CT_ARITH, // +, -, /, etc
+ CT_SARITH, // 'not', 'xor'
+ CT_SHIFT, // <<, >>
+ CT_CARET, // ^
+ CT_DEREF, // * dereference
+ CT_INCDEC_BEFORE, // ++a or --a
+ CT_INCDEC_AFTER, // a++ or a--
+ CT_MEMBER, // . or ->
+ CT_DC_MEMBER, // ::
+ CT_C99_MEMBER, // . in structure stuff
+ CT_INV, // ~
+ CT_DESTRUCTOR, // ~
+ CT_NOT, // !
+ CT_D_TEMPLATE, // ! as in Foo!(A)
+ CT_ADDR, // &
+ CT_NEG, // - as in -1
+ CT_POS, // + as in +1
+ CT_STAR, // * : raw char to be changed
+ CT_PLUS, // + : raw char to be changed
+ CT_MINUS, // - : raw char to be changed
+ CT_AMP, // & : raw char to be changed
+ CT_BYREF, // & in function def/proto params
+
+ // CT_BITWISE_AND, // & // is a CT_ARITH
+ // CT_BITWISE_OR, // | // is a CT_ARITH
+ // CT_BITWISE_EXCLUSIVE_OR,// ^ // is a CT_ARITH
+ // CT_BITWISE_NOT, // ~ // is a CT_ARITH
+
+ CT_POUND, // #
+ CT_PREPROC, // # at the start of a line
+ CT_PREPROC_INDENT, // # at the start of a line that gets indented: #region
+ CT_PREPROC_BODY, // body of every preproc EXCEPT #define
+ CT_PP, // ##
+ CT_ELLIPSIS, // ...
+ CT_RANGE, // ..
+ CT_NULLCOND, // ?.
+
+ CT_SEMICOLON,
+ CT_VSEMICOLON, // virtual semicolon for PAWN
+ CT_COLON,
+ CT_ASM_COLON,
+ CT_CASE_COLON,
+ CT_CASE_ELLIPSIS, // '...' in `case 1 ... 5`:
+ CT_CLASS_COLON, // colon after a class def
+ CT_CONSTR_COLON, // colon after a constructor
+ CT_D_ARRAY_COLON, // D named array initializer colon
+ CT_COND_COLON, // conditional colon in 'b ? t : f'
+ CT_WHERE_COLON, // C# where-constraint colon (after the type)
+ CT_QUESTION,
+ CT_COMMA,
+
+ CT_ASM,
+ CT_ATTRIBUTE,
+ CT_AUTORELEASEPOOL, // OC: Autorelease Pool Blocks, used by iOS
+ CT_OC_AVAILABLE,
+ CT_OC_AVAILABLE_VALUE,
+ CT_CATCH,
+ CT_WHEN,
+ CT_WHERE, // C# where clause
+ CT_CLASS,
+ CT_DELETE,
+ CT_EXPORT,
+ CT_FRIEND,
+ CT_NAMESPACE,
+ CT_PACKAGE,
+ CT_NEW, // may turn into CT_PBRACED if followed by a '('
+ CT_OPERATOR,
+ CT_OPERATOR_VAL,
+ CT_ASSIGN_OPERATOR, // the value after 'operator' such as:
+ // Foo &operator= ( const Foo & );
+ CT_ACCESS,
+ CT_ACCESS_COLON,
+ CT_THROW,
+ CT_NOEXCEPT,
+ CT_TRY,
+ CT_BRACED_INIT_LIST,
+ CT_USING,
+ CT_USING_STMT, // using (xxx) ...
+ CT_USING_ALIAS, // using identifier attr(optional) = type-id
+ CT_D_WITH, // D: parenthetis+braced
+ CT_D_MODULE,
+ CT_SUPER,
+ CT_DELEGATE,
+ CT_BODY,
+ CT_DEBUG,
+ CT_DEBUGGER,
+ CT_INVARIANT,
+ CT_UNITTEST,
+ CT_UNSAFE,
+ CT_FINALLY,
+ CT_FIXED, // C# fixed
+ CT_IMPORT,
+ CT_D_SCOPE,
+ CT_D_SCOPE_IF,
+ CT_LAZY,
+ CT_D_MACRO,
+ CT_D_VERSION, // turns into CT_D_VERSION_IF if not followed by '='
+ CT_D_VERSION_IF, // version(x) { }
+
+ // note for parenthetis/brace/square pairs: close MUST be open + 1
+ CT_PAREN_OPEN,
+ CT_PAREN_CLOSE,
+
+ CT_ANGLE_OPEN, // template<T*>
+ CT_ANGLE_CLOSE,
+
+ CT_SPAREN_OPEN, // 'special' parenthetis after if/for/switch/while/synchronized/catch
+ CT_SPAREN_CLOSE,
+
+ CT_PPAREN_OPEN, // 'protect' parenthetis to protect a type such as (*int)
+ CT_PPAREN_CLOSE, // used at align_func_param
+
+ CT_FPAREN_OPEN, // 'function' parenthetis after fcn/macro fcn
+ CT_FPAREN_CLOSE,
+
+ CT_LPAREN_OPEN, // lambda-declarator parenthetis
+ CT_LPAREN_CLOSE,
+
+ CT_TPAREN_OPEN, // 'type' parenthetis used in function types
+ CT_TPAREN_CLOSE,
+
+ CT_BRACE_OPEN, // {...}
+ CT_BRACE_CLOSE,
+
+ CT_VBRACE_OPEN, // virtual brace, i.e. brace inserted by uncrustify
+ CT_VBRACE_CLOSE,
+
+ CT_SQUARE_OPEN, // [...]
+ CT_SQUARE_CLOSE,
+
+ CT_TSQUARE, // special case of []
+
+ CT_MACRO_OPEN, // stuff specified via custom-pair
+ CT_MACRO_CLOSE,
+ CT_MACRO_ELSE,
+
+ // aggregate types
+ CT_LABEL, // a non-case label
+ CT_LABEL_COLON, // the colon for a label
+ CT_FUNCTION, // function - unspecified, call mark_function()
+ CT_FUNC_CALL, // function call
+ CT_FUNC_CALL_USER, // function call (special user)
+ CT_FUNC_DEF, // function definition/implementation
+ CT_FUNC_TYPE, // function type - foo in "typedef void (*foo)(void)"
+ CT_FUNC_VAR, // foo and parent type of first parens in "void (*foo)(void)"
+ CT_FUNC_PROTO, // function prototype
+ CT_FUNC_START, // global DC member for functions(void ::func())
+ CT_FUNC_CLASS_DEF, // ctor or dtor for a class
+ CT_FUNC_CLASS_PROTO, // ctor or dtor for a class
+ CT_FUNC_CTOR_VAR, // variable or class initialization
+ CT_FUNC_WRAP, // macro that wraps the function name
+ CT_PROTO_WRAP, // macro: "RETVAL PROTO_WRAP( fcn_name, (PARAMS))". Parens for PARAMS are optional.
+ CT_MACRO_FUNC, // function-like macro
+ CT_MACRO_FUNC_CALL, // function-like macro call
+ CT_MACRO, // a macro def
+ CT_QUALIFIER, // static, const, etc
+ CT_EXTERN, // extern
+ CT_DECLSPEC, // __declspec
+ CT_ALIGN, // paren'd qualifier: align(4) struct a { }
+ CT_TYPE,
+ CT_PTR_TYPE, // a '*' as part of a type
+ CT_TYPE_WRAP, // macro that wraps a type name
+ CT_CPP_LAMBDA, // parent for '[=](...){...}'
+ CT_CPP_LAMBDA_RET, // '->' in '[=](...) -> type {...}'
+ CT_EXECUTION_CONTEXT, // Keyword for use in lambda statement: [] CT_EXECUTION_CONTEXT ()->{}
+ CT_TRAILING_RET, // '->' in 'auto fname(...) -> type;'
+ // '->' in 'auto fname(...) const -> type;'
+ CT_BIT_COLON, // a ':' in a variable declaration
+
+ CT_OC_DYNAMIC,
+ CT_OC_END, // ObjC: @end
+ CT_OC_IMPL, // ObjC: @implementation
+ CT_OC_INTF, // ObjC: @interface
+ CT_OC_PROTOCOL, // ObjC: @protocol or @protocol()
+ CT_OC_PROTO_LIST, // ObjC: protocol list < > (parent token only)
+ CT_OC_GENERIC_SPEC, // ObjC: specification of generic < >
+ CT_OC_PROPERTY, // ObjC: @property
+ CT_OC_CLASS, // ObjC: the name after @interface or @implementation
+ CT_OC_CLASS_EXT, // ObjC: a pair of empty parens after the class name in a @interface or @implementation
+ CT_OC_CATEGORY, // ObjC: the category name in parens after the class name in a @interface or @implementation
+ CT_OC_SCOPE, // ObjC: the '-' or '+' in '-(void) func: (int) i;'
+ CT_OC_MSG, // ObjC: parent type to '[', ']' and ';' in '[class func : param name: param];'
+ CT_OC_MSG_CLASS, // ObjC: 'class' in '[class func : param name: param];' (see also PCF_IN_OC_MSG)
+ CT_OC_MSG_FUNC, // ObjC: 'func' in '[class func : param name: param];' (see also PCF_IN_OC_MSG)
+ CT_OC_MSG_NAME, // ObjC: 'name' in '[class func : param name: param];' (see also PCF_IN_OC_MSG)
+ CT_OC_MSG_SPEC, // ObjC: msg spec '-(void) func: (int) i;'
+ CT_OC_MSG_DECL, // ObjC: msg decl '-(void) func: (int) i { }'
+ CT_OC_RTYPE, // ObjC: marks parens of the return type after scope
+ CT_OC_ATYPE, // ObjC: marks parens of the arg type after scope
+ CT_OC_COLON, // ObjC: the colon in a msg spec
+ CT_OC_DICT_COLON, // ObjC: colon in dictionary constant: "KEY: VALUE"
+ CT_OC_SEL, // ObjC: @selector
+ CT_OC_SEL_NAME, // ObjC: selector name
+ CT_OC_BLOCK, // ObjC: block parent type.
+ CT_OC_BLOCK_ARG, // ObjC: block arguments parent type.
+ CT_OC_BLOCK_TYPE, // ObjC: block declaration parent type, e.g. mainly the '(^block_t)' in 'void (^block_t)(int arg);'
+ CT_OC_BLOCK_EXPR, // ObjC: block expression with arg: '^(int arg) { arg++; };' and without (called a block literal): '^{ ... };'
+ CT_OC_BLOCK_CARET, // ObjC: block pointer caret: '^'
+ CT_OC_AT, // ObjC: boxed constants using '@'
+ CT_OC_PROPERTY_ATTR, // ObjC: property attribute (strong, weak, readonly, etc...)
+
+ // start PP types
+ CT_PP_DEFINE, // #define
+ CT_PP_DEFINED, // #if defined
+ CT_PP_INCLUDE, // #include
+ CT_PP_IF, // #if, #ifdef, or #ifndef
+ CT_PP_ELSE, // #else or #elif
+ CT_PP_ENDIF, // #endif
+ CT_PP_ASSERT,
+ CT_PP_EMIT,
+ CT_PP_ENDINPUT,
+ CT_PP_ERROR,
+ CT_PP_FILE,
+ CT_PP_LINE,
+ CT_PP_SECTION,
+ CT_PP_ASM, // start of assembly code section
+ CT_PP_UNDEF,
+ CT_PP_PROPERTY,
+
+ CT_PP_BODYCHUNK, // everything after this gets put in CT_PREPROC_BODY
+
+ CT_PP_PRAGMA, // pragma's should not be altered
+ CT_PP_REGION, // C# #region
+ CT_PP_ENDREGION, // C# #endregion
+ CT_PP_REGION_INDENT, // Dummy token for indenting a C# #region
+ CT_PP_IF_INDENT, // Dummy token for indenting a #if stuff
+ CT_PP_IGNORE, // Dummy token for ignoring a certain preprocessor directive (do not do any processing)
+ CT_PP_OTHER, // #line, #error, #pragma, etc
+ // end PP types
+
+ // PAWN stuff
+ CT_CHAR,
+ CT_DEFINED,
+ CT_FORWARD,
+ CT_NATIVE,
+ CT_STATE,
+ CT_STOCK,
+ CT_TAGOF,
+ CT_DOT,
+ CT_TAG,
+ CT_TAG_COLON,
+
+ // C-sharp
+ CT_LOCK, // lock/unlock
+ CT_AS,
+ CT_IN, // "foreach (T c in x)" or "foo(in char c)" or "in { ..."
+ CT_BRACED, // simple braced items: try {}
+ CT_THIS, // may turn into CT_PBRACED if followed by a '('
+ CT_BASE, // C# thingy
+ CT_DEFAULT, // may be changed into CT_CASE
+ CT_GETSET, // must be followed by CT_BRACE_OPEN or reverts to CT_WORD
+ CT_GETSET_EMPTY, // get/set/add/remove followed by a semicolon
+ CT_CONCAT, // The '~' between strings
+ CT_CS_SQ_STMT, // '[assembly: xxx]' or '[Attribute()]' or '[Help()]', etc
+ CT_CS_SQ_COLON, // the colon in one of those [] thingys
+ CT_CS_PROPERTY, // word or ']' followed by '{'
+
+ // Embedded SQL - always terminated with a semicolon
+ CT_SQL_EXEC, // the 'EXEC' in 'EXEC SQL ...'
+ CT_SQL_BEGIN, // the 'BEGINN' in 'EXEC SQL BEGIN ...'
+ CT_SQL_END, // the 'END' in 'EXEC SQL END ...'
+ CT_SQL_WORD, // CT_WORDs in the 'EXEC SQL' statement
+ CT_SQL_ASSIGN, // :=
+
+ // Vala stuff
+ CT_CONSTRUCT, // braced "construct { }" or qualifier "(construct int x)"
+ CT_LAMBDA,
+
+ // Java
+ CT_ASSERT, // assert EXP1 [ : EXP2 ] ;
+ CT_ANNOTATION, // @interface or @something(...)
+ CT_FOR_COLON, // colon in "for ( TYPE var: EXPR ) { ... }"
+ CT_DOUBLE_BRACE, // parent for double brace
+
+ /* Clang */
+ CT_CNG_HASINC, // Clang: __has_include()
+ CT_CNG_HASINCN, // Clang: __has_include_next()
+
+ // extensions for Qt macros
+ CT_Q_EMIT, // guy 2015-10-16
+ CT_Q_FOREACH, // guy 2015-09-23
+ CT_Q_FOREVER, // guy 2015-10-18
+ CT_Q_GADGET, // guy 2016-05-04
+ CT_Q_OBJECT, // guy 2015-10-16
+
+ // Machine Modes
+ CT_MODE, // guy 2016-03-11
+ CT_DI, // guy 2016-03-11
+ CT_HI, // guy 2016-03-11
+ CT_QI, // guy 2016-03-11
+ CT_SI, // guy 2016-03-11
+ CT_NOTHROW, // guy 2016-03-11
+ CT_WORD_, // guy 2016-03-11
+
+ CT_TOKEN_COUNT_ // NOTE: Keep this the last entry because it's used as a counter.
+};
+
+#endif /* TOKEN_ENUM_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.cpp
new file mode 100644
index 00000000..4d446f6c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.cpp
@@ -0,0 +1,2855 @@
+/**
+ * @file tokenize.cpp
+ * This file breaks up the text stream into tokens or chunks.
+ *
+ * Each routine needs to set pc.len and pc.type.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "tokenize.h"
+
+#include "keywords.h"
+#include "prototypes.h"
+#include "punctuators.h"
+#include "unc_ctype.h"
+
+#include <regex>
+#include <stack>
+
+
+#define LE_COUNT(x) cpd.le_counts[static_cast<size_t>(LE_ ## x)]
+
+constexpr static auto LCURRENT = LTOK;
+
+using namespace std;
+using namespace uncrustify;
+
+
+struct tok_info
+{
+ tok_info()
+ : last_ch(0)
+ , idx(0)
+ , row(1)
+ , col(1)
+ {
+ }
+
+ size_t last_ch;
+ size_t idx;
+ size_t row;
+ size_t col;
+};
+
+
+struct tok_ctx
+{
+ tok_ctx(const deque<int> &d)
+ : data(d)
+ {
+ }
+
+
+ //! save before trying to parse something that may fail
+ void save()
+ {
+ save(s);
+ }
+
+
+ void save(tok_info &info)
+ {
+ info = c;
+ }
+
+
+ //! restore previous saved state
+ void restore()
+ {
+ restore(s);
+ }
+
+
+ void restore(const tok_info &info)
+ {
+ c = info;
+ }
+
+
+ bool more()
+ {
+ return(c.idx < data.size());
+ }
+
+
+ size_t peek()
+ {
+ return(more() ? data[c.idx] : 0);
+ }
+
+
+ size_t peek(size_t idx)
+ {
+ idx += c.idx;
+ return((idx < data.size()) ? data[idx] : 0);
+ }
+
+
+ size_t get()
+ {
+ if (more())
+ {
+ size_t ch = data[c.idx++];
+
+ switch (ch)
+ {
+ case '\t':
+ log_rule_B("input_tab_size");
+ c.col = calc_next_tab_column(c.col, options::input_tab_size());
+ break;
+
+ case '\n':
+
+ if (c.last_ch != '\r')
+ {
+ c.row++;
+ c.col = 1;
+ }
+ break;
+
+ case '\r':
+ c.row++;
+ c.col = 1;
+ break;
+
+ default:
+ c.col++;
+ break;
+ }
+ c.last_ch = ch;
+ return(ch);
+ }
+ return(0);
+ }
+
+
+ bool expect(size_t ch)
+ {
+ if (peek() == ch)
+ {
+ get();
+ return(true);
+ }
+ return(false);
+ }
+
+
+ const deque<int> &data;
+ tok_info c; //! current
+ tok_info s; //! saved
+};
+
+
+/**
+ * Count the number of characters in a quoted string.
+ * The next bit of text starts with a quote char " or ' or <.
+ * Count the number of characters until the matching character.
+ *
+ * @param pc The structure to update, str is an input.
+ *
+ * @return Whether a string was parsed
+ */
+static bool parse_string(tok_ctx &ctx, Chunk &pc, size_t quote_idx, bool allow_escape);
+
+
+/**
+ * Literal string, ends with single "
+ * Two "" don't end the string.
+ *
+ * @param pc The structure to update, str is an input.
+ *
+ * @return Whether a string was parsed
+ */
+static bool parse_cs_string(tok_ctx &ctx, Chunk &pc);
+
+
+/**
+ * VALA verbatim string, ends with three quotes (""")
+ *
+ * @param pc The structure to update, str is an input.
+ */
+static void parse_verbatim_string(tok_ctx &ctx, Chunk &pc);
+
+
+static bool tag_compare(const deque<int> &d, size_t a_idx, size_t b_idx, size_t len);
+
+
+/**
+ * Parses a C++0x 'R' string. R"( xxx )" R"tag( )tag" u8R"(x)" uR"(x)"
+ * Newlines may be in the string.
+ *
+ * @param pc structure to update, str is an input.
+ */
+static bool parse_cr_string(tok_ctx &ctx, Chunk &pc, size_t q_idx);
+
+
+/**
+ * Count the number of whitespace characters.
+ *
+ * @param pc The structure to update, str is an input.
+ *
+ * @return Whether whitespace was parsed
+ */
+static bool parse_whitespace(tok_ctx &ctx, Chunk &pc);
+
+
+/**
+ * Called when we hit a backslash.
+ * If there is nothing but whitespace until the newline, then this is a
+ * backslash newline
+ *
+ * @param pc structure to update, str is an input
+ */
+static bool parse_bs_newline(tok_ctx &ctx, Chunk &pc);
+
+
+/**
+ * Parses any number of tab or space chars followed by a newline.
+ * Does not change pc.len if a newline isn't found.
+ * This is not the same as parse_whitespace() because it only consumes until
+ * a single newline is encountered.
+ */
+static bool parse_newline(tok_ctx &ctx);
+
+
+/**
+ * PAWN #define is different than C/C++.
+ * #define PATTERN REPLACEMENT_TEXT
+ * The PATTERN may not contain a space or '[' or ']'.
+ * A generic whitespace check should be good enough.
+ * Do not change the pattern.
+ *
+ * @param pc structure to update, str is an input
+ */
+static void parse_pawn_pattern(tok_ctx &ctx, Chunk &pc, E_Token tt);
+
+
+static bool parse_ignored(tok_ctx &ctx, Chunk &pc);
+
+
+/**
+ * Skips the next bit of whatever and returns the type of block.
+ *
+ * pc.str is the input text.
+ * pc.len in the output length.
+ * pc.type is the output type
+ * pc.column is output column
+ *
+ * @param pc The structure to update, str is an input.
+ * @param prev_pc The previous structure
+ *
+ * @return true/false - whether anything was parsed
+ */
+static bool parse_next(tok_ctx &ctx, Chunk &pc, const Chunk *prev_pc);
+
+
+/**
+ * Parses all legal D string constants.
+ *
+ * Quoted strings:
+ * r"Wysiwyg" # WYSIWYG string
+ * x"hexstring" # Hexadecimal array
+ * `Wysiwyg` # WYSIWYG string
+ * 'char' # single character
+ * "reg_string" # regular string
+ *
+ * Non-quoted strings:
+ * \x12 # 1-byte hex constant
+ * \u1234 # 2-byte hex constant
+ * \U12345678 # 4-byte hex constant
+ * \123 # octal constant
+ * \&amp; # named entity
+ * \n # single character
+ *
+ * @param pc The structure to update, str is an input.
+ *
+ * @return Whether a string was parsed
+ */
+static bool d_parse_string(tok_ctx &ctx, Chunk &pc);
+
+
+/**
+ * Figure of the length of the comment at text.
+ * The next bit of text starts with a '/', so it might be a comment.
+ * There are three types of comments:
+ * - C comments that start with '/ *' and end with '* /'
+ * - C++ comments that start with //
+ * - D nestable comments '/+' '+/'
+ *
+ * @param pc The structure to update, str is an input.
+ *
+ * @return Whether a comment was parsed
+ */
+static bool parse_comment(tok_ctx &ctx, Chunk &pc);
+
+
+/**
+ * Figure of the length of the code placeholder at text, if present.
+ * This is only for Xcode which sometimes inserts temporary code placeholder chunks, which in plaintext <#look like this#>.
+ *
+ * @param pc The structure to update, str is an input.
+ *
+ * @return Whether a placeholder was parsed.
+ */
+static bool parse_code_placeholder(tok_ctx &ctx, Chunk &pc);
+
+
+/**
+ * Parse any attached suffix, which may be a user-defined literal suffix.
+ * If for a string, explicitly exclude common format and scan specifiers, ie,
+ * PRIx32 and SCNx64.
+ */
+static void parse_suffix(tok_ctx &ctx, Chunk &pc, bool forstring);
+
+
+//! check if a symbol holds a boolean value
+static bool is_bin(int ch);
+static bool is_bin_(int ch);
+
+
+//! check if a symbol holds a octal value
+static bool is_oct(int ch);
+static bool is_oct_(int ch);
+
+
+//! check if a symbol holds a decimal value;
+static bool is_dec(int ch);
+static bool is_dec_(int ch);
+
+
+//! check if a symbol holds a hexadecimal value
+static bool is_hex(int ch);
+static bool is_hex_(int ch);
+
+
+/**
+ * Count the number of characters in the number.
+ * The next bit of text starts with a number (0-9 or '.'), so it is a number.
+ * Count the number of characters in the number.
+ *
+ * This should cover all number formats for all languages.
+ * Note that this is not a strict parser. It will happily parse numbers in
+ * an invalid format.
+ *
+ * For example, only D allows underscores in the numbers, but they are
+ * allowed in all formats.
+ *
+ * @param[in,out] pc The structure to update, str is an input.
+ *
+ * @return Whether a number was parsed
+ */
+static bool parse_number(tok_ctx &ctx, Chunk &pc);
+
+
+static bool d_parse_string(tok_ctx &ctx, Chunk &pc)
+{
+ size_t ch = ctx.peek();
+
+ if ( ch == '"'
+ || ch == '\'')
+ {
+ return(parse_string(ctx, pc, 0, true));
+ }
+
+ if (ch == '`')
+ {
+ return(parse_string(ctx, pc, 0, false));
+ }
+
+ if ( ( ch == 'r'
+ || ch == 'x')
+ && ctx.peek(1) == '"')
+ {
+ return(parse_string(ctx, pc, 1, false));
+ }
+
+ if (ch != '\\')
+ {
+ return(false);
+ }
+ ctx.save();
+ int cnt;
+
+ pc.str.clear();
+
+ while (ctx.peek() == '\\')
+ {
+ pc.str.append(ctx.get());
+
+ // Check for end of file
+ switch (ctx.peek())
+ {
+ case 'x': // \x HexDigit HexDigit
+ cnt = 3;
+
+ while (cnt--)
+ {
+ pc.str.append(ctx.get());
+ }
+ break;
+
+ case 'u': // \u HexDigit (x4)
+ cnt = 5;
+
+ while (cnt--)
+ {
+ pc.str.append(ctx.get());
+ }
+ break;
+
+ case 'U': // \U HexDigit (x8)
+ cnt = 9;
+
+ while (cnt--)
+ {
+ pc.str.append(ctx.get());
+ }
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ // handle up to 3 octal digits
+ pc.str.append(ctx.get());
+ ch = ctx.peek();
+
+ if ( (ch >= '0')
+ && (ch <= '7'))
+ {
+ pc.str.append(ctx.get());
+ ch = ctx.peek();
+
+ if ( (ch >= '0')
+ && (ch <= '7'))
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+ break;
+
+ case '&':
+ // \& NamedCharacterEntity ;
+ pc.str.append(ctx.get());
+
+ while (unc_isalpha(ctx.peek()))
+ {
+ pc.str.append(ctx.get());
+ }
+
+ if (ctx.peek() == ';')
+ {
+ pc.str.append(ctx.get());
+ }
+ break;
+
+ default:
+ // Everything else is a single character
+ pc.str.append(ctx.get());
+ break;
+ } // switch
+ }
+
+ if (pc.str.size() < 1)
+ {
+ ctx.restore();
+ return(false);
+ }
+ set_chunk_type(&pc, CT_STRING);
+ return(true);
+} // d_parse_string
+
+
+#if 0
+
+
+//! A string-in-string search. Like strstr() with a haystack length.
+static const char *str_search(const char *needle, const char *haystack, int haystack_len)
+{
+ int needle_len = strlen(needle);
+
+ while (haystack_len-- >= needle_len)
+ {
+ if (memcmp(needle, haystack, needle_len) == 0)
+ {
+ return(haystack);
+ }
+ haystack++;
+ }
+ return(NULL);
+}
+#endif
+
+
+static bool parse_comment(tok_ctx &ctx, Chunk &pc)
+{
+ bool is_d = language_is_set(LANG_D);
+ bool is_cs = language_is_set(LANG_CS);
+ size_t d_level = 0;
+
+ // does this start with '/ /' or '/ *' or '/ +' (d)
+ if ( (ctx.peek() != '/')
+ || ( (ctx.peek(1) != '*')
+ && (ctx.peek(1) != '/')
+ && ( (ctx.peek(1) != '+')
+ || !is_d)))
+ {
+ return(false);
+ }
+ ctx.save();
+
+ // account for opening two chars
+ pc.str = ctx.get(); // opening '/'
+ size_t ch = ctx.get();
+
+ pc.str.append(ch); // second char
+
+ if (ch == '/')
+ {
+ set_chunk_type(&pc, CT_COMMENT_CPP);
+
+ while (true)
+ {
+ int bs_cnt = 0;
+
+ while (ctx.more())
+ {
+ ch = ctx.peek();
+
+ if ( (ch == '\r')
+ || (ch == '\n'))
+ {
+ break;
+ }
+
+ if ( (ch == '\\')
+ && !is_cs) // backslashes aren't special in comments in C#
+ {
+ bs_cnt++;
+ }
+ else
+ {
+ bs_cnt = 0;
+ }
+ pc.str.append(ctx.get());
+ }
+
+ /*
+ * If we hit an odd number of backslashes right before the newline,
+ * then we keep going.
+ */
+ if ( ((bs_cnt & 1) == 0)
+ || !ctx.more())
+ {
+ break;
+ }
+
+ if (ctx.peek() == '\r')
+ {
+ pc.str.append(ctx.get());
+ }
+
+ if (ctx.peek() == '\n')
+ {
+ pc.str.append(ctx.get());
+ }
+ pc.nl_count++;
+ cpd.did_newline = true;
+ }
+ }
+ else if (!ctx.more())
+ {
+ // unexpected end of file
+ ctx.restore();
+ return(false);
+ }
+ else if (ch == '+')
+ {
+ set_chunk_type(&pc, CT_COMMENT);
+ d_level++;
+
+ while ( d_level > 0
+ && ctx.more())
+ {
+ if ( (ctx.peek() == '+')
+ && (ctx.peek(1) == '/'))
+ {
+ pc.str.append(ctx.get()); // store the '+'
+ pc.str.append(ctx.get()); // store the '/'
+ d_level--;
+ continue;
+ }
+
+ if ( (ctx.peek() == '/')
+ && (ctx.peek(1) == '+'))
+ {
+ pc.str.append(ctx.get()); // store the '/'
+ pc.str.append(ctx.get()); // store the '+'
+ d_level++;
+ continue;
+ }
+ ch = ctx.get();
+ pc.str.append(ch);
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ set_chunk_type(&pc, CT_COMMENT_MULTI);
+ pc.nl_count++;
+
+ if (ch == '\r')
+ {
+ if (ctx.peek() == '\n')
+ {
+ ++LE_COUNT(CRLF);
+ pc.str.append(ctx.get()); // store the '\n'
+ }
+ else
+ {
+ ++LE_COUNT(CR);
+ }
+ }
+ else
+ {
+ ++LE_COUNT(LF);
+ }
+ }
+ }
+ }
+ else // must be '/ *'
+ {
+ set_chunk_type(&pc, CT_COMMENT);
+
+ while (ctx.more())
+ {
+ if ( (ctx.peek() == '*')
+ && (ctx.peek(1) == '/'))
+ {
+ pc.str.append(ctx.get()); // store the '*'
+ pc.str.append(ctx.get()); // store the '/'
+
+ tok_info ss;
+ ctx.save(ss);
+ size_t oldsize = pc.str.size();
+
+ // If there is another C comment right after this one, combine them
+ while ( (ctx.peek() == ' ')
+ || (ctx.peek() == '\t'))
+ {
+ pc.str.append(ctx.get());
+ }
+
+ if ( (ctx.peek() != '/')
+ || (ctx.peek(1) != '*'))
+ {
+ // undo the attempt to join
+ ctx.restore(ss);
+ pc.str.resize(oldsize);
+ break;
+ }
+ }
+ ch = ctx.get();
+ pc.str.append(ch);
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ set_chunk_type(&pc, CT_COMMENT_MULTI);
+ pc.nl_count++;
+
+ if (ch == '\r')
+ {
+ if (ctx.peek() == '\n')
+ {
+ ++LE_COUNT(CRLF);
+ pc.str.append(ctx.get()); // store the '\n'
+ }
+ else
+ {
+ ++LE_COUNT(CR);
+ }
+ }
+ else
+ {
+ ++LE_COUNT(LF);
+ }
+ }
+ }
+ }
+
+ if (cpd.unc_off)
+ {
+ bool found_enable_marker = (find_enable_processing_comment_marker(pc.str) >= 0);
+
+ if (found_enable_marker)
+ {
+ const auto &ontext = options::enable_processing_cmt();
+
+ LOG_FMT(LBCTRL, "%s(%d): Found '%s' on line %zu\n",
+ __func__, __LINE__, ontext.c_str(), pc.orig_line);
+ cpd.unc_off = false;
+ }
+ }
+ else
+ {
+ auto position_disable_processing_cmt = find_disable_processing_comment_marker(pc.str);
+ bool found_disable_marker = (position_disable_processing_cmt >= 0);
+
+ if (found_disable_marker)
+ {
+ /**
+ * the user may wish to disable processing part of a multiline comment,
+ * in which case we'll handle at a late time. Check to see if processing
+ * is re-enabled elsewhere in this comment
+ */
+ auto position_enable_processing_cmt = find_enable_processing_comment_marker(pc.str);
+
+ if (position_enable_processing_cmt < position_disable_processing_cmt)
+ {
+ const auto &offtext = options::disable_processing_cmt();
+
+ LOG_FMT(LBCTRL, "%s(%d): Found '%s' on line %zu\n",
+ __func__, __LINE__, offtext.c_str(), pc.orig_line);
+ cpd.unc_off = true;
+ // Issue #842
+ cpd.unc_off_used = true;
+ }
+ }
+ }
+ return(true);
+} // parse_comment
+
+
+static bool parse_code_placeholder(tok_ctx &ctx, Chunk &pc)
+{
+ if ( (ctx.peek() != '<')
+ || (ctx.peek(1) != '#'))
+ {
+ return(false);
+ }
+ ctx.save();
+
+ // account for opening two chars '<#'
+ pc.str = ctx.get();
+ pc.str.append(ctx.get());
+
+ // grab everything until '#>', fail if not found.
+ size_t last1 = 0;
+
+ while (ctx.more())
+ {
+ size_t last2 = last1;
+ last1 = ctx.get();
+ pc.str.append(last1);
+
+ if ( (last2 == '#')
+ && (last1 == '>'))
+ {
+ set_chunk_type(&pc, CT_WORD);
+ return(true);
+ }
+ }
+ ctx.restore();
+ return(false);
+}
+
+
+static void parse_suffix(tok_ctx &ctx, Chunk &pc, bool forstring = false)
+{
+ if (CharTable::IsKw1(ctx.peek()))
+ {
+ size_t slen = 0;
+ size_t oldsize = pc.str.size();
+
+ // don't add the suffix if we see L" or L' or S"
+ size_t p1 = ctx.peek();
+ size_t p2 = ctx.peek(1);
+
+ if ( forstring
+ && ( ( (p1 == 'L')
+ && ( (p2 == '"')
+ || (p2 == '\'')))
+ || ( (p1 == 'S')
+ && (p2 == '"'))))
+ {
+ return;
+ }
+ tok_info ss;
+ ctx.save(ss);
+
+ while ( ctx.more()
+ && CharTable::IsKw2(ctx.peek()))
+ {
+ slen++;
+ pc.str.append(ctx.get());
+ }
+
+ if ( forstring
+ && slen >= 4
+ && ( pc.str.startswith("PRI", oldsize)
+ || pc.str.startswith("SCN", oldsize)))
+ {
+ ctx.restore(ss);
+ pc.str.resize(oldsize);
+ }
+ }
+}
+
+
+static bool is_bin(int ch)
+{
+ return( (ch == '0')
+ || (ch == '1'));
+}
+
+
+static bool is_bin_(int ch)
+{
+ return( is_bin(ch)
+ || ch == '_'
+ || ch == '\'');
+}
+
+
+static bool is_oct(int ch)
+{
+ return( (ch >= '0')
+ && (ch <= '7'));
+}
+
+
+static bool is_oct_(int ch)
+{
+ return( is_oct(ch)
+ || ch == '_'
+ || ch == '\'');
+}
+
+
+static bool is_dec(int ch)
+{
+ return( (ch >= '0')
+ && (ch <= '9'));
+}
+
+
+static bool is_dec_(int ch)
+{
+ // number separators: JAVA: "_", C++14: "'"
+ return( is_dec(ch)
+ || (ch == '_')
+ || (ch == '\''));
+}
+
+
+static bool is_hex(int ch)
+{
+ return( ( (ch >= '0')
+ && (ch <= '9'))
+ || ( (ch >= 'a')
+ && (ch <= 'f'))
+ || ( (ch >= 'A')
+ && (ch <= 'F')));
+}
+
+
+static bool is_hex_(int ch)
+{
+ return( is_hex(ch)
+ || ch == '_'
+ || ch == '\'');
+}
+
+
+static bool parse_number(tok_ctx &ctx, Chunk &pc)
+{
+ /*
+ * A number must start with a digit or a dot, followed by a digit
+ * (signs handled elsewhere)
+ */
+ if ( !is_dec(ctx.peek())
+ && ( (ctx.peek() != '.')
+ || !is_dec(ctx.peek(1))))
+ {
+ return(false);
+ }
+ bool is_float = (ctx.peek() == '.');
+
+ if ( is_float
+ && (ctx.peek(1) == '.')) // make sure it isn't '..'
+ {
+ return(false);
+ }
+ /*
+ * Check for Hex, Octal, or Binary
+ * Note that only D, C++14 and Pawn support binary
+ * Fixes the issue # 1591
+ * In c# the numbers starting with 0 are not treated as octal numbers.
+ */
+ bool did_hex = false;
+
+ if ( ctx.peek() == '0'
+ && !language_is_set(LANG_CS))
+ {
+ size_t ch;
+ Chunk pc_temp;
+
+ pc.str.append(ctx.get()); // store the '0'
+ pc_temp.str.append('0');
+
+ // MS constant might have an "h" at the end. Look for it
+ ctx.save();
+
+ while ( ctx.more()
+ && CharTable::IsKw2(ctx.peek()))
+ {
+ ch = ctx.get();
+ pc_temp.str.append(ch);
+ }
+ ch = pc_temp.str[pc_temp.Len() - 1];
+ ctx.restore();
+ LOG_FMT(LGUY, "%s(%d): pc_temp:%s\n", __func__, __LINE__, pc_temp.Text());
+
+ if (ch == 'h') // TODO can we combine this in analyze_character
+ {
+ // we have an MS hexadecimal number with "h" at the end
+ LOG_FMT(LGUY, "%s(%d): MS hexadecimal number\n", __func__, __LINE__);
+ did_hex = true;
+
+ do
+ {
+ pc.str.append(ctx.get()); // store the rest
+ } while (is_hex_(ctx.peek()));
+
+ pc.str.append(ctx.get()); // store the h
+ LOG_FMT(LGUY, "%s(%d): pc:%s\n", __func__, __LINE__, pc.Text());
+ }
+ else
+ {
+ switch (unc_toupper(ctx.peek()))
+ {
+ case 'X': // hex
+ did_hex = true;
+
+ do
+ {
+ pc.str.append(ctx.get()); // store the 'x' and then the rest
+ } while (is_hex_(ctx.peek()));
+
+ break;
+
+ case 'B': // binary
+
+ do
+ {
+ pc.str.append(ctx.get()); // store the 'b' and then the rest
+ } while (is_bin_(ctx.peek()));
+
+ break;
+
+ case '0': // octal or decimal
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+
+ do
+ {
+ pc.str.append(ctx.get());
+ } while (is_oct_(ctx.peek()));
+
+ break;
+
+ default:
+ // either just 0 or 0.1 or 0UL, etc
+ break;
+ } // switch
+ }
+ }
+ else
+ {
+ // Regular int or float
+ while (is_dec_(ctx.peek()))
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+
+ // Check if we stopped on a decimal point & make sure it isn't '..'
+ if ( (ctx.peek() == '.')
+ && (ctx.peek(1) != '.'))
+ {
+ // Issue #1265, 5.clamp()
+ tok_info ss;
+ ctx.save(ss);
+
+ while ( ctx.more()
+ && CharTable::IsKw2(ctx.peek(1)))
+ {
+ // skip characters to check for paren open
+ ctx.get();
+ }
+
+ if (ctx.peek(1) == '(')
+ {
+ ctx.restore(ss);
+ set_chunk_type(&pc, CT_NUMBER);
+ return(true);
+ }
+ else
+ {
+ ctx.restore(ss);
+ }
+ pc.str.append(ctx.get());
+ is_float = true;
+
+ if (did_hex)
+ {
+ while (is_hex_(ctx.peek()))
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+ else
+ {
+ while (is_dec_(ctx.peek()))
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+ }
+ /*
+ * Check exponent
+ * Valid exponents per language (not that it matters):
+ * C/C++/D/Java: eEpP
+ * C#/Pawn: eE
+ */
+ size_t tmp = unc_toupper(ctx.peek());
+
+ if ( (tmp == 'E')
+ || (tmp == 'P'))
+ {
+ is_float = true;
+ pc.str.append(ctx.get());
+
+ if ( (ctx.peek() == '+')
+ || (ctx.peek() == '-'))
+ {
+ pc.str.append(ctx.get());
+ }
+
+ while (is_dec_(ctx.peek()))
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+
+ /*
+ * Check the suffixes
+ * Valid suffixes per language (not that it matters):
+ * Integer Float
+ * C/C++: uUlL64 lLfF
+ * C#: uUlL fFdDMm
+ * D: uUL ifFL
+ * Java: lL fFdD
+ * Pawn: (none) (none)
+ *
+ * Note that i, f, d, and m only appear in floats.
+ */
+ while (1)
+ {
+ size_t tmp2 = unc_toupper(ctx.peek());
+
+ if ( (tmp2 == 'I')
+ || (tmp2 == 'F')
+ || (tmp2 == 'D')
+ || (tmp2 == 'M'))
+ {
+ is_float = true;
+ }
+ else if ( (tmp2 != 'L')
+ && (tmp2 != 'U'))
+ {
+ break;
+ }
+ pc.str.append(ctx.get());
+ }
+
+ // skip the Microsoft-specific '32' and '64' suffix
+ if ( ( (ctx.peek() == '3')
+ && (ctx.peek(1) == '2'))
+ || ( (ctx.peek() == '6')
+ && (ctx.peek(1) == '4')))
+ {
+ pc.str.append(ctx.get());
+ pc.str.append(ctx.get());
+ }
+ set_chunk_type(&pc, is_float ? CT_NUMBER_FP : CT_NUMBER);
+
+ /*
+ * If there is anything left, then we are probably dealing with garbage or
+ * some sick macro junk. Eat it.
+ */
+ parse_suffix(ctx, pc);
+
+ return(true);
+} // parse_number
+
+
+static bool parse_string(tok_ctx &ctx, Chunk &pc, size_t quote_idx, bool allow_escape)
+{
+ log_rule_B("string_escape_char");
+ const size_t escape_char = options::string_escape_char();
+
+ log_rule_B("string_escape_char2");
+ const size_t escape_char2 = options::string_escape_char2();
+
+ log_rule_B("string_replace_tab_chars");
+ const bool should_escape_tabs = ( allow_escape
+ && options::string_replace_tab_chars()
+ && language_is_set(LANG_ALLC));
+
+ pc.str.clear();
+
+ while (quote_idx-- > 0)
+ {
+ pc.str.append(ctx.get());
+ }
+ set_chunk_type(&pc, CT_STRING);
+ const size_t termination_character = CharTable::Get(ctx.peek()) & 0xff;
+
+ pc.str.append(ctx.get()); // store the "
+
+ bool escaped = false;
+
+ while (ctx.more())
+ {
+ const size_t ch = ctx.get();
+
+ // convert char 9 (\t) to chars \t
+ if ( (ch == '\t')
+ && should_escape_tabs)
+ {
+ const size_t lastcol = ctx.c.col - 1;
+ ctx.c.col = lastcol + 2;
+ pc.str.append(escape_char);
+ pc.str.append('t');
+ continue;
+ }
+ pc.str.append(ch);
+
+ if (ch == '\n')
+ {
+ pc.nl_count++;
+ set_chunk_type(&pc, CT_STRING_MULTI);
+ }
+ else if ( ch == '\r'
+ && ctx.peek() != '\n')
+ {
+ pc.str.append(ctx.get());
+ pc.nl_count++;
+ set_chunk_type(&pc, CT_STRING_MULTI);
+ }
+
+ // if last char in prev loop was escaped the one in the current loop isn't
+ if (escaped)
+ {
+ escaped = false;
+ continue;
+ }
+
+ // see if the current char is a escape char
+ if (allow_escape)
+ {
+ if (ch == escape_char)
+ {
+ escaped = (escape_char != 0);
+ continue;
+ }
+
+ if ( ch == escape_char2
+ && (ctx.peek() == termination_character))
+ {
+ escaped = allow_escape;
+ continue;
+ }
+ }
+
+ if (ch == termination_character)
+ {
+ break;
+ }
+ }
+ parse_suffix(ctx, pc, true);
+ return(true);
+} // parse_string
+
+enum cs_string_t
+{
+ CS_STRING_NONE = 0,
+ CS_STRING_STRING = 1 << 0, // is any kind of string
+ CS_STRING_VERBATIM = 1 << 1, // @"" style string
+ CS_STRING_INTERPOLATED = 1 << 2, // $"" or $@"" style string
+};
+
+static cs_string_t operator|=(cs_string_t &value, cs_string_t other)
+{
+ return(value = static_cast<cs_string_t>(value | other));
+}
+
+
+static cs_string_t parse_cs_string_start(tok_ctx &ctx, Chunk &pc)
+{
+ cs_string_t stringType = CS_STRING_NONE;
+ int offset = 0;
+
+ if (ctx.peek(offset) == '$')
+ {
+ stringType |= CS_STRING_INTERPOLATED;
+ ++offset;
+ }
+
+ if (ctx.peek(offset) == '@')
+ {
+ stringType |= CS_STRING_VERBATIM;
+ ++offset;
+ }
+
+ if (ctx.peek(offset) == '"')
+ {
+ stringType |= CS_STRING_STRING;
+
+ set_chunk_type(&pc, CT_STRING);
+
+ for (int i = 0; i <= offset; ++i)
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+ else
+ {
+ stringType = CS_STRING_NONE;
+ }
+ return(stringType);
+} // parse_cs_string_start
+
+
+struct CsStringParseState
+{
+ cs_string_t type;
+ int braceDepth;
+
+
+ CsStringParseState(cs_string_t stringType)
+ {
+ type = stringType;
+ braceDepth = 0;
+ }
+};
+
+
+/**
+ * C# strings are complex enough (mostly due to interpolation and nesting) that they need a custom parser.
+ */
+static bool parse_cs_string(tok_ctx &ctx, Chunk &pc)
+{
+ cs_string_t stringType = parse_cs_string_start(ctx, pc);
+
+ if (stringType == 0)
+ {
+ return(false);
+ }
+ // an interpolated string can contain {expressions}, which can contain $"strings", which in turn
+ // can contain {expressions}, so we must track both as they are interleaved, in order to properly
+ // parse the outermost string.
+
+ std::stack<CsStringParseState> parseState; // each entry is a nested string
+
+ parseState.push(CsStringParseState(stringType));
+
+ log_rule_B("string_replace_tab_chars");
+ bool should_escape_tabs = options::string_replace_tab_chars();
+
+ while (ctx.more())
+ {
+ if (parseState.top().braceDepth > 0)
+ {
+ // all we can do when in an expr is look for expr close with }, or a new string opening. must do this first
+ // so we can peek and potentially consume chars for new string openings, before the ch=get() happens later,
+ // which is needed for newline processing.
+
+ if (ctx.peek() == '}')
+ {
+ pc.str.append(ctx.get());
+
+ if (ctx.peek() == '}')
+ {
+ pc.str.append(ctx.get()); // in interpolated string, `}}` is escape'd `}`
+ }
+ else
+ {
+ --parseState.top().braceDepth;
+ }
+ continue;
+ }
+ stringType = parse_cs_string_start(ctx, pc);
+
+ if (stringType)
+ {
+ parseState.push(CsStringParseState(stringType));
+ continue;
+ }
+ }
+ int lastcol = ctx.c.col;
+ int ch = ctx.get();
+
+ pc.str.append(ch);
+
+ if (ch == '\n')
+ {
+ set_chunk_type(&pc, CT_STRING_MULTI);
+ pc.nl_count++;
+ }
+ else if (ch == '\r')
+ {
+ set_chunk_type(&pc, CT_STRING_MULTI);
+ }
+ else if (parseState.top().braceDepth > 0)
+ {
+ // do nothing. if we're in a brace, we only want the newline handling, and skip the rest.
+ }
+ else if ( (ch == '\t')
+ && should_escape_tabs)
+ {
+ if (parseState.top().type & CS_STRING_VERBATIM)
+ {
+ if (!cpd.warned_unable_string_replace_tab_chars)
+ {
+ cpd.warned_unable_string_replace_tab_chars = true;
+
+ log_rule_B("warn_level_tabs_found_in_verbatim_string_literals");
+ log_sev_t warnlevel = (log_sev_t)options::warn_level_tabs_found_in_verbatim_string_literals();
+
+ /*
+ * a tab char can't be replaced with \\t because escapes don't
+ * work in here-strings. best we can do is warn.
+ */
+ LOG_FMT(warnlevel, "%s(%d): %s: orig_line is %zu, orig_col is %zu, Detected non-replaceable tab char in literal string\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc.orig_line, pc.orig_col);
+ LOG_FMT(warnlevel, "%s(%d): Warning is given if doing tab-to-\\t replacement and we have found one in a C# verbatim string literal.\n",
+ __func__, __LINE__);
+
+ if (warnlevel < LWARN)
+ {
+ cpd.error_count++;
+ }
+ }
+ }
+ else
+ {
+ ctx.c.col = lastcol + 2;
+ pc.str.pop_back(); // remove \t
+ pc.str.append("\\t");
+
+ continue;
+ }
+ }
+ else if ( ch == '\\'
+ && !(parseState.top().type & CS_STRING_VERBATIM))
+ {
+ // catch escaped quote in order to avoid ending string (but also must handle \\ to avoid accidental 'escape' seq of `\\"`)
+ if ( ctx.peek() == '"'
+ || ctx.peek() == '\\')
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+ else if (ch == '"')
+ {
+ if ( (parseState.top().type & CS_STRING_VERBATIM)
+ && (ctx.peek() == '"'))
+ {
+ // in verbatim string, `""` is escape'd `"`
+ pc.str.append(ctx.get());
+ }
+ else
+ {
+ // end of string
+ parseState.pop();
+
+ if (parseState.empty())
+ {
+ break;
+ }
+ }
+ }
+ else if (parseState.top().type & CS_STRING_INTERPOLATED)
+ {
+ if (ch == '{')
+ {
+ if (ctx.peek() == '{')
+ {
+ pc.str.append(ctx.get()); // in interpolated string, `{{` is escape'd `{`
+ }
+ else
+ {
+ ++parseState.top().braceDepth;
+ }
+ }
+ }
+ }
+ return(true);
+} // parse_cs_string
+
+
+static void parse_verbatim_string(tok_ctx &ctx, Chunk &pc)
+{
+ set_chunk_type(&pc, CT_STRING);
+
+ // consume the initial """
+ pc.str = ctx.get();
+ pc.str.append(ctx.get());
+ pc.str.append(ctx.get());
+
+ // go until we hit a zero (end of file) or a """
+ while (ctx.more())
+ {
+ size_t ch = ctx.get();
+ pc.str.append(ch);
+
+ if ( (ch == '"')
+ && (ctx.peek() == '"')
+ && (ctx.peek(1) == '"'))
+ {
+ pc.str.append(ctx.get());
+ pc.str.append(ctx.get());
+ break;
+ }
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ set_chunk_type(&pc, CT_STRING_MULTI);
+ pc.nl_count++;
+ }
+ }
+}
+
+
+static bool tag_compare(const deque<int> &d, size_t a_idx, size_t b_idx, size_t len)
+{
+ if (a_idx != b_idx)
+ {
+ while (len-- > 0)
+ {
+ if (d[a_idx] != d[b_idx])
+ {
+ return(false);
+ }
+ }
+ }
+ return(true);
+}
+
+
+static bool parse_cr_string(tok_ctx &ctx, Chunk &pc, size_t q_idx)
+{
+ size_t tag_idx = ctx.c.idx + q_idx + 1;
+ size_t tag_len = 0;
+
+ ctx.save();
+
+ // Copy the prefix + " to the string
+ pc.str.clear();
+ int cnt = q_idx + 1;
+
+ while (cnt--)
+ {
+ pc.str.append(ctx.get());
+ }
+
+ // Add the tag and get the length of the tag
+ while ( ctx.more()
+ && (ctx.peek() != '('))
+ {
+ tag_len++;
+ pc.str.append(ctx.get());
+ }
+
+ if (ctx.peek() != '(')
+ {
+ ctx.restore();
+ return(false);
+ }
+ set_chunk_type(&pc, CT_STRING);
+
+ while (ctx.more())
+ {
+ if ( (ctx.peek() == ')')
+ && (ctx.peek(tag_len + 1) == '"')
+ && tag_compare(ctx.data, tag_idx, ctx.c.idx + 1, tag_len))
+ {
+ cnt = tag_len + 2; // for the )"
+
+ while (cnt--)
+ {
+ pc.str.append(ctx.get());
+ }
+ parse_suffix(ctx, pc);
+ return(true);
+ }
+
+ if (ctx.peek() == '\n')
+ {
+ pc.str.append(ctx.get());
+ pc.nl_count++;
+ set_chunk_type(&pc, CT_STRING_MULTI);
+ }
+ else
+ {
+ pc.str.append(ctx.get());
+ }
+ }
+ ctx.restore();
+ return(false);
+} // parse_cr_string
+
+
+/**
+ * Count the number of characters in a word.
+ * The first character is already valid for a keyword
+ *
+ * @param pc The structure to update, str is an input.
+ * @return Whether a word was parsed (always true)
+ */
+static bool parse_word(tok_ctx &ctx, Chunk &pc, bool skipcheck)
+{
+ static unc_text intr_txt("@interface");
+
+ // The first character is already valid
+ pc.str.clear();
+ pc.str.append(ctx.get());
+
+ while (ctx.more())
+ {
+ size_t ch = ctx.peek();
+
+ if (CharTable::IsKw2(ch))
+ {
+ pc.str.append(ctx.get());
+ }
+ else if ( (ch == '\\')
+ && (unc_tolower(ctx.peek(1)) == 'u'))
+ {
+ pc.str.append(ctx.get());
+ pc.str.append(ctx.get());
+ skipcheck = true;
+ }
+ else
+ {
+ break;
+ }
+
+ // HACK: Non-ASCII character are only allowed in identifiers
+ if (ch > 0x7f)
+ {
+ skipcheck = true;
+ }
+ }
+ set_chunk_type(&pc, CT_WORD);
+
+ if (skipcheck)
+ {
+ return(true);
+ }
+
+ // Detect pre-processor functions now
+ if ( cpd.in_preproc == CT_PP_DEFINE
+ && cpd.preproc_ncnl_count == 1)
+ {
+ if (ctx.peek() == '(')
+ {
+ set_chunk_type(&pc, CT_MACRO_FUNC);
+ }
+ else
+ {
+ set_chunk_type(&pc, CT_MACRO);
+
+ log_rule_B("pp_ignore_define_body");
+
+ if (options::pp_ignore_define_body())
+ {
+ /*
+ * We are setting the PP_IGNORE preproc state because the following
+ * chunks are part of the macro body and will have to be ignored.
+ */
+ cpd.in_preproc = CT_PP_IGNORE;
+ }
+ }
+ }
+ else
+ {
+ // '@interface' is reserved, not an interface itself
+ if ( language_is_set(LANG_JAVA)
+ && pc.str.startswith("@")
+ && !pc.str.equals(intr_txt))
+ {
+ set_chunk_type(&pc, CT_ANNOTATION);
+ }
+ else
+ {
+ // Turn it into a keyword now
+ // Issue #1460 will return "COMMENT_CPP"
+ set_chunk_type(&pc, find_keyword_type(pc.Text(), pc.str.size()));
+
+ /* Special pattern: if we're trying to redirect a preprocessor directive to PP_IGNORE,
+ * then ensure we're actually part of a preprocessor before doing the swap, or we'll
+ * end up with a function named 'define' as PP_IGNORE. This is necessary because with
+ * the config 'set' feature, there's no way to do a pair of tokens as a word
+ * substitution. */
+ if ( pc.type == CT_PP_IGNORE
+ && !cpd.in_preproc)
+ {
+ set_chunk_type(&pc, find_keyword_type(pc.Text(), pc.str.size()));
+ }
+ else if (pc.type == CT_COMMENT_CPP) // Issue #1460
+ {
+ size_t ch;
+ bool is_cs = language_is_set(LANG_CS);
+
+ // read until EOL
+ while (true)
+ {
+ int bs_cnt = 0;
+
+ while (ctx.more())
+ {
+ ch = ctx.peek();
+
+ if ( (ch == '\r')
+ || (ch == '\n'))
+ {
+ break;
+ }
+
+ if ( (ch == '\\')
+ && !is_cs) // backslashes aren't special in comments in C#
+ {
+ bs_cnt++;
+ }
+ else
+ {
+ bs_cnt = 0;
+ }
+ pc.str.append(ctx.get());
+ }
+
+ /*
+ * If we hit an odd number of backslashes right before the newline,
+ * then we keep going.
+ */
+ if ( ((bs_cnt & 1) == 0)
+ || !ctx.more())
+ {
+ break;
+ }
+
+ if (ctx.peek() == '\r')
+ {
+ pc.str.append(ctx.get());
+ }
+
+ if (ctx.peek() == '\n')
+ {
+ pc.str.append(ctx.get());
+ }
+ pc.nl_count++;
+ cpd.did_newline = true;
+ }
+ // Store off the end column
+ pc.orig_col_end = ctx.c.col;
+ }
+ }
+ }
+ return(true);
+} // parse_word
+
+
+static size_t parse_attribute_specifier_sequence(tok_ctx &ctx)
+{
+ size_t nested = 0;
+ size_t offset = 0;
+ size_t parens = 0;
+ auto ch1 = ctx.peek(offset++);
+
+ while (ch1)
+ {
+ auto ch2 = ctx.peek(offset++);
+
+ while ( ch2 == ' '
+ || ch2 == '\n'
+ || ch2 == '\r'
+ || ch2 == '\t')
+ {
+ ch2 = ctx.peek(offset++);
+ }
+
+ if ( nested == 0
+ && ch2 != '[')
+ {
+ break;
+ }
+
+ if (ch1 == '(')
+ {
+ ++parens;
+ ch1 = ch2;
+ continue;
+ }
+
+ if (ch1 == ')')
+ {
+ if (parens == 0)
+ {
+ break;
+ }
+ --parens;
+ ch1 = ch2;
+ continue;
+ }
+
+ if ( ch1 != '['
+ && ch1 != ']')
+ {
+ ch1 = ch2;
+ continue;
+ }
+
+ if (ch2 != ch1)
+ {
+ if (parens == 0)
+ {
+ break;
+ }
+ ch1 = ch2;
+ continue;
+ }
+
+ if (ch1 == '[')
+ {
+ if ( nested != 0
+ && parens == 0)
+ {
+ break;
+ }
+ ++nested;
+ }
+ else if (--nested == 0)
+ {
+ return(offset);
+ }
+ ch1 = ctx.peek(offset++);
+ }
+ return(0);
+} // parse_attribute_specifier_sequence
+
+
+static bool extract_attribute_specifier_sequence(tok_ctx &ctx, Chunk &pc, size_t length)
+{
+ pc.str.clear();
+
+ while (length--)
+ {
+ pc.str.append(ctx.get());
+ }
+ set_chunk_type(&pc, CT_ATTRIBUTE);
+ return(true);
+} // extract_attribute_specifier_sequence
+
+
+static bool parse_whitespace(tok_ctx &ctx, Chunk &pc)
+{
+ size_t nl_count = 0;
+ size_t ch = 0;
+
+ // REVISIT: use a better whitespace detector?
+ while ( ctx.more()
+ && unc_isspace(ctx.peek()))
+ {
+ ch = ctx.get(); // throw away the whitespace char
+
+ switch (ch)
+ {
+ case '\r':
+
+ if (ctx.expect('\n'))
+ {
+ // CRLF ending
+ ++LE_COUNT(CRLF);
+ }
+ else
+ {
+ // CR ending
+ ++LE_COUNT(CR);
+ }
+ nl_count++;
+ pc.orig_prev_sp = 0;
+ break;
+
+ case '\n':
+ // LF ending
+ ++LE_COUNT(LF);
+ nl_count++;
+ pc.orig_prev_sp = 0;
+ break;
+
+ case '\t':
+ log_rule_B("input_tab_size");
+ pc.orig_prev_sp += calc_next_tab_column(cpd.column, options::input_tab_size()) - cpd.column;
+ break;
+
+ case ' ':
+ pc.orig_prev_sp++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (ch != 0)
+ {
+ pc.str.clear();
+ set_chunk_type(&pc, nl_count ? CT_NEWLINE : CT_WHITESPACE);
+ pc.nl_count = nl_count;
+ pc.after_tab = (ctx.c.last_ch == '\t');
+ return(true);
+ }
+ return(false);
+} // parse_whitespace
+
+
+static bool parse_bs_newline(tok_ctx &ctx, Chunk &pc)
+{
+ ctx.save();
+ ctx.get(); // skip the '\'
+
+ size_t ch;
+
+ while ( ctx.more()
+ && unc_isspace(ch = ctx.peek()))
+ {
+ ctx.get();
+
+ if ( (ch == '\r')
+ || (ch == '\n'))
+ {
+ if (ch == '\r')
+ {
+ ctx.expect('\n');
+ }
+ set_chunk_type(&pc, CT_NL_CONT);
+ pc.str = "\\";
+ pc.nl_count = 1;
+ return(true);
+ }
+ }
+ ctx.restore();
+ return(false);
+}
+
+
+static bool parse_newline(tok_ctx &ctx)
+{
+ ctx.save();
+
+ // Eat whitespace
+ while ( (ctx.peek() == ' ')
+ || (ctx.peek() == '\t'))
+ {
+ ctx.get();
+ }
+
+ if ( (ctx.peek() == '\r')
+ || (ctx.peek() == '\n'))
+ {
+ if (!ctx.expect('\n'))
+ {
+ ctx.get();
+ ctx.expect('\n');
+ }
+ return(true);
+ }
+ ctx.restore();
+ return(false);
+}
+
+
+static void parse_pawn_pattern(tok_ctx &ctx, Chunk &pc, E_Token tt)
+{
+ pc.str.clear();
+ set_chunk_type(&pc, tt);
+
+ while (!unc_isspace(ctx.peek()))
+ {
+ // end the pattern on an escaped newline
+ if (ctx.peek() == '\\')
+ {
+ size_t ch = ctx.peek(1);
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ break;
+ }
+ }
+ pc.str.append(ctx.get());
+ }
+}
+
+
+static bool parse_off_newlines(tok_ctx &ctx, Chunk &pc)
+{
+ size_t nl_count = 0;
+
+ // Parse off newlines/blank lines
+ while (parse_newline(ctx))
+ {
+ nl_count++;
+ }
+
+ if (nl_count > 0)
+ {
+ pc.nl_count = nl_count;
+ set_chunk_type(&pc, CT_NEWLINE);
+ return(true);
+ }
+ return(false);
+}
+
+
+static bool parse_macro(tok_ctx &ctx, Chunk &pc, const Chunk *prev_pc)
+{
+ if (parse_off_newlines(ctx, pc))
+ {
+ return(true);
+ }
+
+ if (parse_comment(ctx, pc)) // allow CT_COMMENT_MULTI within macros
+ {
+ return(true);
+ }
+ ctx.save();
+ pc.str.clear();
+
+ bool continued = ( chunk_is_token(prev_pc, CT_NL_CONT)
+ || chunk_is_token(prev_pc, CT_COMMENT_MULTI));
+
+ while (ctx.more())
+ {
+ size_t pk = ctx.peek(), pk1 = ctx.peek(1);
+ bool nl = ( pk == '\n'
+ || pk == '\r');
+ bool nl_cont = ( pk == '\\'
+ && ( pk1 == '\n'
+ || pk1 == '\r'));
+
+ if ( ( nl_cont
+ || ( continued
+ && nl))
+ && pc.str.size() > 0)
+ {
+ set_chunk_type(&pc, CT_IGNORED);
+ return(true);
+ }
+ else if (nl)
+ {
+ break;
+ }
+ pc.str.append(ctx.get());
+ }
+ pc.str.clear();
+ ctx.restore();
+ return(false);
+} // parse_macro
+
+
+static bool parse_ignored(tok_ctx &ctx, Chunk &pc)
+{
+ if (parse_off_newlines(ctx, pc))
+ {
+ return(true);
+ }
+ // See if the UO_enable_processing_cmt or #pragma endasm / #endasm text is on this line
+ ctx.save();
+ pc.str.clear();
+
+ while ( ctx.more()
+ && (ctx.peek() != '\r')
+ && (ctx.peek() != '\n'))
+ {
+ pc.str.append(ctx.get());
+ }
+
+ if (pc.str.size() == 0)
+ {
+ // end of file?
+ return(false);
+ }
+
+ // HACK: turn on if we find '#endasm' or '#pragma' and 'endasm' separated by blanks
+ if ( ( ( (pc.str.find("#pragma ") >= 0)
+ || (pc.str.find("#pragma ") >= 0))
+ && ( (pc.str.find(" endasm") >= 0)
+ || (pc.str.find(" endasm") >= 0)))
+ || (pc.str.find("#endasm") >= 0))
+ {
+ cpd.unc_off = false;
+ ctx.restore();
+ pc.str.clear();
+ return(false);
+ }
+ // Note that we aren't actually making sure this is in a comment, yet
+ log_rule_B("enable_processing_cmt");
+ const auto &ontext = options::enable_processing_cmt();
+
+ if (!ontext.empty())
+ {
+ bool found_enable_pattern = false;
+
+ if ( ontext != UNCRUSTIFY_ON_TEXT
+ && options::processing_cmt_as_regex())
+ {
+ std::wstring pc_wstring(pc.str.get().cbegin(),
+ pc.str.get().cend());
+ std::wregex criteria(std::wstring(ontext.cbegin(),
+ ontext.cend()));
+
+ found_enable_pattern = std::regex_search(pc_wstring.cbegin(),
+ pc_wstring.cend(),
+ criteria);
+ }
+ else
+ {
+ found_enable_pattern = (pc.str.find(ontext.c_str()) >= 0);
+ }
+
+ if (!found_enable_pattern)
+ {
+ set_chunk_type(&pc, CT_IGNORED);
+ return(true);
+ }
+ }
+ ctx.restore();
+
+ // parse off whitespace leading to the comment
+ if (parse_whitespace(ctx, pc))
+ {
+ set_chunk_type(&pc, CT_IGNORED);
+ return(true);
+ }
+
+ // Look for the ending comment and let it pass
+ if ( parse_comment(ctx, pc)
+ && !cpd.unc_off)
+ {
+ return(true);
+ }
+ // Reset the chunk & scan to until a newline
+ pc.str.clear();
+
+ while ( ctx.more()
+ && (ctx.peek() != '\r')
+ && (ctx.peek() != '\n'))
+ {
+ pc.str.append(ctx.get());
+ }
+
+ if (pc.str.size() > 0)
+ {
+ set_chunk_type(&pc, CT_IGNORED);
+ return(true);
+ }
+ return(false);
+} // parse_ignored
+
+
+static bool parse_next(tok_ctx &ctx, Chunk &pc, const Chunk *prev_pc)
+{
+ if (!ctx.more())
+ {
+ return(false);
+ }
+ // Save off the current column
+ set_chunk_type(&pc, CT_NONE);
+ pc.orig_line = ctx.c.row;
+ pc.column = ctx.c.col;
+ pc.orig_col = ctx.c.col;
+ pc.nl_count = 0;
+ pc.flags = PCF_NONE;
+
+ // If it is turned off, we put everything except newlines into CT_UNKNOWN
+ if (cpd.unc_off)
+ {
+ if (parse_ignored(ctx, pc))
+ {
+ return(true);
+ }
+ }
+ log_rule_B("disable_processing_nl_cont");
+
+ // Parse macro blocks
+ if (options::disable_processing_nl_cont())
+ {
+ if (parse_macro(ctx, pc, prev_pc))
+ {
+ return(true);
+ }
+ }
+
+ // Parse whitespace
+ if (parse_whitespace(ctx, pc))
+ {
+ return(true);
+ }
+
+ // Handle unknown/unhandled preprocessors
+ if ( cpd.in_preproc > CT_PP_BODYCHUNK
+ && cpd.in_preproc <= CT_PP_OTHER)
+ {
+ pc.str.clear();
+ tok_info ss;
+ ctx.save(ss);
+ // Chunk to a newline or comment
+ set_chunk_type(&pc, CT_PREPROC_BODY);
+ size_t last = 0;
+
+ while (ctx.more())
+ {
+ size_t ch = ctx.peek();
+
+ // Fix for issue #1752
+ // Ignoring extra spaces after ' \ ' for preproc body continuations
+ if ( last == '\\'
+ && ch == ' ')
+ {
+ ctx.get();
+ continue;
+ }
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ // Back off if this is an escaped newline
+ if (last == '\\')
+ {
+ ctx.restore(ss);
+ pc.str.pop_back();
+ }
+ break;
+ }
+
+ // Quit on a C or C++ comment start Issue #1966
+ if ( (ch == '/')
+ && ( (ctx.peek(1) == '/')
+ || (ctx.peek(1) == '*')))
+ {
+ break;
+ }
+ last = ch;
+ ctx.save(ss);
+
+ pc.str.append(ctx.get());
+ }
+
+ if (pc.str.size() > 0)
+ {
+ return(true);
+ }
+ }
+
+ // Detect backslash-newline
+ if ( (ctx.peek() == '\\')
+ && parse_bs_newline(ctx, pc))
+ {
+ return(true);
+ }
+
+ // Parse comments
+ if (parse_comment(ctx, pc))
+ {
+ return(true);
+ }
+
+ // Parse code placeholders
+ if (parse_code_placeholder(ctx, pc))
+ {
+ return(true);
+ }
+
+ if (language_is_set(LANG_CS))
+ {
+ if (parse_cs_string(ctx, pc))
+ {
+ return(true);
+ }
+
+ // check for non-keyword identifiers such as @if @switch, etc
+ if ( (ctx.peek() == '@')
+ && CharTable::IsKw1(ctx.peek(1)))
+ {
+ parse_word(ctx, pc, true);
+ return(true);
+ }
+ }
+
+ // handle VALA """ strings """
+ if ( language_is_set(LANG_VALA)
+ && (ctx.peek() == '"')
+ && (ctx.peek(1) == '"')
+ && (ctx.peek(2) == '"'))
+ {
+ parse_verbatim_string(ctx, pc);
+ return(true);
+ }
+ /*
+ * handle C++(11) string/char literal prefixes u8|u|U|L|R including all
+ * possible combinations and optional R delimiters: R"delim(x)delim"
+ */
+ auto ch = ctx.peek();
+
+ if ( language_is_set(LANG_C | LANG_CPP)
+ && ( ch == 'u'
+ || ch == 'U'
+ || ch == 'R'
+ || ch == 'L'))
+ {
+ auto idx = size_t{};
+ auto is_real = false;
+
+ if ( ch == 'u'
+ && ctx.peek(1) == '8')
+ {
+ idx = 2;
+ }
+ else if ( unc_tolower(ch) == 'u'
+ || ch == 'L')
+ {
+ idx++;
+ }
+
+ if ( language_is_set(LANG_C | LANG_CPP)
+ && ctx.peek(idx) == 'R')
+ {
+ idx++;
+ is_real = true;
+ }
+ const auto quote = ctx.peek(idx);
+
+ if (is_real)
+ {
+ if ( quote == '"'
+ && parse_cr_string(ctx, pc, idx))
+ {
+ return(true);
+ }
+ }
+ else if ( ( quote == '"'
+ || quote == '\'')
+ && parse_string(ctx, pc, idx, true))
+ {
+ return(true);
+ }
+ }
+
+ // PAWN specific stuff
+ if (language_is_set(LANG_PAWN))
+ {
+ if ( cpd.preproc_ncnl_count == 1
+ && ( cpd.in_preproc == CT_PP_DEFINE
+ || cpd.in_preproc == CT_PP_EMIT))
+ {
+ parse_pawn_pattern(ctx, pc, CT_MACRO);
+ return(true);
+ }
+
+ // Check for PAWN strings: \"hi" or !"hi" or !\"hi" or \!"hi"
+ if ( (ctx.peek() == '\\')
+ || (ctx.peek() == '!'))
+ {
+ if (ctx.peek(1) == '"')
+ {
+ parse_string(ctx, pc, 1, (ctx.peek() == '!'));
+ return(true);
+ }
+
+ if ( ( (ctx.peek(1) == '\\')
+ || (ctx.peek(1) == '!'))
+ && (ctx.peek(2) == '"'))
+ {
+ parse_string(ctx, pc, 2, false);
+ return(true);
+ }
+ }
+
+ // handle PAWN preprocessor args %0 .. %9
+ if ( cpd.in_preproc == CT_PP_DEFINE
+ && (ctx.peek() == '%')
+ && unc_isdigit(ctx.peek(1)))
+ {
+ pc.str.clear();
+ pc.str.append(ctx.get());
+ pc.str.append(ctx.get());
+ set_chunk_type(&pc, CT_WORD);
+ return(true);
+ }
+ }
+ // Parse strings and character constants
+
+//parse_word(ctx, pc_temp, true);
+//ctx.restore(ctx.c);
+ if (parse_number(ctx, pc))
+ {
+ return(true);
+ }
+
+ if (language_is_set(LANG_D))
+ {
+ // D specific stuff
+ if (d_parse_string(ctx, pc))
+ {
+ return(true);
+ }
+ }
+ else
+ {
+ // Not D stuff
+
+ // Check for L'a', L"abc", 'a', "abc", <abc> strings
+ ch = ctx.peek();
+ size_t ch1 = ctx.peek(1);
+
+ if ( ( ( (ch == 'L')
+ || (ch == 'S'))
+ && ( (ch1 == '"')
+ || (ch1 == '\'')))
+ || (ch == '"')
+ || (ch == '\'')
+ || ( (ch == '<')
+ && cpd.in_preproc == CT_PP_INCLUDE))
+ {
+ parse_string(ctx, pc, unc_isalpha(ch) ? 1 : 0, true);
+ set_chunk_parent(&pc, CT_PP_INCLUDE);
+ return(true);
+ }
+
+ if ( (ch == '<')
+ && cpd.in_preproc == CT_PP_DEFINE)
+ {
+ if (chunk_is_token(Chunk::GetTail(), CT_MACRO))
+ {
+ // We have "#define XXX <", assume '<' starts an include string
+ parse_string(ctx, pc, 0, false);
+ return(true);
+ }
+ }
+ /* Inside clang's __has_include() could be "path/to/file.h" or system-style <path/to/file.h> */
+ Chunk *tail = Chunk::GetTail();
+
+ if ( (ch == '(')
+ && (tail->IsNotNullChunk())
+ && ( chunk_is_token(tail, CT_CNG_HASINC)
+ || chunk_is_token(tail, CT_CNG_HASINCN)))
+ {
+ parse_string(ctx, pc, 0, false);
+ return(true);
+ }
+ }
+
+ // Check for Objective C literals and VALA identifiers ('@1', '@if')
+ if ( language_is_set(LANG_OC | LANG_VALA)
+ && (ctx.peek() == '@'))
+ {
+ size_t nc = ctx.peek(1);
+
+ if (nc == 'R') // Issue #2720
+ {
+ if (ctx.peek(2) == '"')
+ {
+ if (parse_cr_string(ctx, pc, 2)) // Issue #3027
+ {
+ return(true);
+ }
+ // parse string without escaping
+ parse_string(ctx, pc, 2, false);
+ return(true);
+ }
+ }
+
+ if ( (nc == '"')
+ || (nc == '\''))
+ {
+ // literal string
+ parse_string(ctx, pc, 1, true);
+ return(true);
+ }
+
+ if ( (nc >= '0')
+ && (nc <= '9'))
+ {
+ // literal number
+ pc.str.append(ctx.get()); // store the '@'
+ parse_number(ctx, pc);
+ return(true);
+ }
+ }
+
+ // Check for pawn/ObjectiveC/Java and normal identifiers
+ if ( CharTable::IsKw1(ctx.peek())
+ || ( (ctx.peek() == '\\')
+ && (unc_tolower(ctx.peek(1)) == 'u'))
+ || ( (ctx.peek() == '@')
+ && CharTable::IsKw1(ctx.peek(1))))
+ {
+ parse_word(ctx, pc, false);
+ return(true);
+ }
+
+ // Check for C++11/14/17/20 attribute specifier sequences
+ if ( language_is_set(LANG_CPP)
+ && ctx.peek() == '[')
+ {
+ if ( !language_is_set(LANG_OC)
+ || !chunk_is_token(prev_pc, CT_OC_AT))
+ {
+ if (auto length = parse_attribute_specifier_sequence(ctx))
+ {
+ extract_attribute_specifier_sequence(ctx, pc, length);
+ return(true);
+ }
+ }
+ }
+ // see if we have a punctuator
+ char punc_txt[7];
+
+ punc_txt[0] = ctx.peek();
+ punc_txt[1] = ctx.peek(1);
+ punc_txt[2] = ctx.peek(2);
+ punc_txt[3] = ctx.peek(3);
+ punc_txt[4] = ctx.peek(4);
+ punc_txt[5] = ctx.peek(5);
+ punc_txt[6] = '\0';
+ const chunk_tag_t *punc;
+
+ if ((punc = find_punctuator(punc_txt, cpd.lang_flags)) != nullptr)
+ {
+ int cnt = strlen(punc->tag);
+
+ while (cnt--)
+ {
+ pc.str.append(ctx.get());
+ }
+ set_chunk_type(&pc, punc->type);
+ pc.flags |= PCF_PUNCTUATOR;
+ return(true);
+ }
+ /* When parsing C/C++ files and running into some unknown token,
+ * check if matches Objective-C as a last resort, before
+ * considering it as garbage.
+ */
+ int probe_lang_flags = 0;
+
+ if (language_is_set(LANG_C | LANG_CPP))
+ {
+ probe_lang_flags = cpd.lang_flags | LANG_OC;
+ }
+
+ if (probe_lang_flags != 0)
+ {
+ if ((punc = find_punctuator(punc_txt, probe_lang_flags)) != NULL)
+ {
+ cpd.lang_flags = probe_lang_flags;
+ int cnt = strlen(punc->tag);
+
+ while (cnt--)
+ {
+ pc.str.append(ctx.get());
+ }
+ set_chunk_type(&pc, punc->type);
+ pc.flags |= PCF_PUNCTUATOR;
+ return(true);
+ }
+ }
+ // throw away this character
+ set_chunk_type(&pc, CT_UNKNOWN);
+ pc.str.append(ctx.get());
+
+ LOG_FMT(LWARN, "%s:%zu Garbage in col %zu: %x\n",
+ cpd.filename.c_str(), pc.orig_line, ctx.c.col, pc.str[0]);
+ cpd.error_count++;
+ return(true);
+} // parse_next
+
+
+int find_disable_processing_comment_marker(const unc_text &text,
+ std::size_t start_idx)
+{
+ log_rule_B("disable_processing_cmt");
+ const auto &offtext = options::disable_processing_cmt();
+ int idx = -1;
+
+ if ( !offtext.empty()
+ && start_idx < text.size())
+ {
+ if ( offtext != UNCRUSTIFY_OFF_TEXT
+ && options::processing_cmt_as_regex())
+ {
+ std::wsmatch match;
+ std::wstring pc_wstring(text.get().cbegin() + start_idx,
+ text.get().cend());
+ std::wregex criteria(std::wstring(offtext.cbegin(),
+ offtext.cend()));
+
+ std::regex_search(pc_wstring.cbegin(),
+ pc_wstring.cend(),
+ match,
+ criteria);
+
+ if (!match.empty())
+ {
+ idx = int(match.position() + start_idx);
+ }
+ }
+ else
+ {
+ idx = text.find(offtext.c_str(),
+ start_idx);
+
+ if (idx >= 0)
+ {
+ idx += int(offtext.size());
+ }
+ }
+
+ /**
+ * update the position to the start of the current line
+ */
+ while ( idx > 0
+ && text[idx - 1] != '\n')
+ {
+ --idx;
+ }
+ }
+ return(idx);
+} // find_disable_processing_comment_marker
+
+
+int find_enable_processing_comment_marker(const unc_text &text,
+ std::size_t start_idx)
+{
+ log_rule_B("enable_processing_cmt");
+ const auto &ontext = options::enable_processing_cmt();
+ int idx = -1;
+
+ if ( !ontext.empty()
+ && start_idx < text.size())
+ {
+ if ( ontext != UNCRUSTIFY_ON_TEXT
+ && options::processing_cmt_as_regex())
+ {
+ std::wsmatch match;
+ std::wstring pc_wstring(text.get().cbegin() + start_idx,
+ text.get().cend());
+ std::wregex criteria(std::wstring(ontext.cbegin(),
+ ontext.cend()));
+
+ std::regex_search(pc_wstring.cbegin(),
+ pc_wstring.cend(),
+ match,
+ criteria);
+
+ if (!match.empty())
+ {
+ idx = int(start_idx + match.position() + match.size());
+ }
+ }
+ else
+ {
+ idx = text.find(ontext.c_str(),
+ start_idx);
+
+ if (idx >= 0)
+ {
+ idx += int(ontext.size());
+ }
+ }
+
+ /**
+ * update the position to the end of the current line
+ */
+ if (idx >= 0)
+ {
+ while ( idx < int(text.size())
+ && text[idx] != '\n')
+ {
+ ++idx;
+ }
+ }
+ }
+ return(idx);
+} // find_enable_processing_comment_marker
+
+
+void tokenize(const deque<int> &data, Chunk *ref)
+{
+ tok_ctx ctx(data);
+ Chunk chunk;
+ Chunk *pc = nullptr;
+ Chunk *rprev = nullptr;
+ bool last_was_tab = false;
+ size_t prev_sp = 0;
+ int num_stripped = 0; // Issue #1966
+
+ cpd.unc_stage = unc_stage_e::TOKENIZE;
+
+ while (ctx.more())
+ {
+ chunk.Reset();
+ chunk.pp_level = 0;
+
+ if (!parse_next(ctx, chunk, pc))
+ {
+ LOG_FMT(LERR, "%s:%zu Bailed before the end?\n",
+ cpd.filename.c_str(), ctx.c.row);
+ cpd.error_count++;
+ break;
+ }
+
+ if ( language_is_set(LANG_JAVA)
+ && chunk.type == CT_MEMBER
+ && !memcmp(chunk.Text(), "->", 2))
+ {
+ chunk.type = CT_LAMBDA;
+ }
+
+ // Don't create an entry for whitespace
+ if (chunk.type == CT_WHITESPACE)
+ {
+ last_was_tab = chunk.after_tab;
+ prev_sp = chunk.orig_prev_sp;
+ continue;
+ }
+ chunk.orig_prev_sp = prev_sp;
+ prev_sp = 0;
+
+ if (chunk.type == CT_NEWLINE)
+ {
+ last_was_tab = chunk.after_tab;
+ chunk.after_tab = false;
+ chunk.str.clear();
+ }
+ else if (chunk.type == CT_NL_CONT)
+ {
+ last_was_tab = chunk.after_tab;
+ chunk.after_tab = false;
+ chunk.str = "\\\n";
+ }
+ else
+ {
+ chunk.after_tab = last_was_tab;
+ last_was_tab = false;
+ }
+ num_stripped = 0; // Issue #1966 and #3565
+
+ if (chunk.type != CT_IGNORED)
+ {
+ // Issue #1338
+ // Strip trailing whitespace (for CPP comments and PP blocks)
+ while ( (chunk.str.size() > 0)
+ && ( (chunk.str[chunk.str.size() - 1] == ' ')
+ || (chunk.str[chunk.str.size() - 1] == '\t')))
+ {
+ // If comment contains backslash '\' followed by whitespace chars, keep last one;
+ // this will prevent it from turning '\' into line continuation.
+ if ( (chunk.str.size() > 1)
+ && (chunk.str[chunk.str.size() - 2] == '\\'))
+ {
+ break;
+ }
+ chunk.str.pop_back();
+ num_stripped++; // Issue #1966
+ }
+ }
+ // Store off the end column
+ chunk.orig_col_end = ctx.c.col - num_stripped; // Issue #1966 and #3565
+
+ // Add the chunk to the list
+ rprev = pc;
+
+ if (rprev != nullptr)
+ {
+ chunk_flags_set(pc, rprev->flags & PCF_COPY_FLAGS);
+
+ // a newline can't be in a preprocessor
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ chunk_flags_clr(pc, PCF_IN_PREPROC);
+ }
+ }
+
+ if (ref != nullptr)
+ {
+ chunk.flags |= PCF_INSERTED;
+ }
+ else
+ {
+ chunk.flags &= ~PCF_INSERTED;
+ }
+ pc = chunk_add_before(&chunk, ref);
+
+ // A newline marks the end of a preprocessor
+ if (chunk_is_token(pc, CT_NEWLINE)) // || chunk_is_token(pc, CT_COMMENT_MULTI))
+ {
+ cpd.in_preproc = CT_NONE;
+ cpd.preproc_ncnl_count = 0;
+ }
+
+ // Disable indentation when #asm directive found
+ if (chunk_is_token(pc, CT_PP_ASM))
+ {
+ LOG_FMT(LBCTRL, "Found a directive %s on line %zu\n", "#asm", pc->orig_line);
+ cpd.unc_off = true;
+ }
+
+ // Special handling for preprocessor stuff
+ if (cpd.in_preproc != CT_NONE)
+ {
+ chunk_flags_set(pc, PCF_IN_PREPROC);
+
+ // Count words after the preprocessor
+ if ( !pc->IsComment()
+ && !chunk_is_newline(pc))
+ {
+ cpd.preproc_ncnl_count++;
+ }
+
+ // Disable indentation if a #pragma asm directive is found
+ if (cpd.in_preproc == CT_PP_PRAGMA)
+ {
+ if (memcmp(pc->Text(), "asm", 3) == 0)
+ {
+ LOG_FMT(LBCTRL, "Found a pragma %s on line %zu\n", "asm", pc->orig_line);
+ cpd.unc_off = true;
+ }
+ }
+
+ // Figure out the type of preprocessor for #include parsing
+ if (cpd.in_preproc == CT_PREPROC)
+ {
+ if ( pc->type < CT_PP_DEFINE
+ || pc->type > CT_PP_OTHER)
+ {
+ set_chunk_type(pc, CT_PP_OTHER);
+ }
+ cpd.in_preproc = pc->type;
+ }
+ else if (cpd.in_preproc == CT_PP_IGNORE)
+ {
+ // ASSERT(options::pp_ignore_define_body());
+ if ( !chunk_is_token(pc, CT_NL_CONT)
+ && !chunk_is_token(pc, CT_COMMENT_CPP)
+ && !chunk_is_token(pc, CT_COMMENT)
+ && !chunk_is_token(pc, CT_COMMENT_MULTI)) // Issue #1966
+ {
+ set_chunk_type(pc, CT_PP_IGNORE);
+ }
+ }
+ else if ( cpd.in_preproc == CT_PP_DEFINE
+ && chunk_is_token(pc, CT_PAREN_CLOSE)
+ && options::pp_ignore_define_body())
+ {
+ log_rule_B("pp_ignore_define_body");
+ // When we have a PAREN_CLOSE in a PP_DEFINE we should be terminating a MACRO_FUNC
+ // arguments list. Therefore we can enter the PP_IGNORE state and ignore next chunks.
+ cpd.in_preproc = CT_PP_IGNORE;
+ }
+ }
+ else
+ {
+ // Check for a preprocessor start
+ if ( chunk_is_token(pc, CT_POUND)
+ && ( rprev == nullptr
+ || chunk_is_token(rprev, CT_NEWLINE)))
+ {
+ set_chunk_type(pc, CT_PREPROC);
+ chunk_flags_set(pc, PCF_IN_PREPROC);
+ cpd.in_preproc = CT_PREPROC;
+ }
+ }
+
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->nl_count);
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "%s(%d): orig_line is %zu, orig_col is %zu, type is %s, orig_col_end is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, get_token_name(pc->type), pc->orig_col_end);
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LGUY, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s', type is %s, orig_col_end is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy), get_token_name(pc->type), pc->orig_col_end);
+ }
+ }
+ // Set the cpd.newline string for this file
+ log_rule_B("newlines");
+
+ if ( options::newlines() == LE_LF
+ || ( options::newlines() == LE_AUTO
+ && (LE_COUNT(LF) >= LE_COUNT(CRLF))
+ && (LE_COUNT(LF) >= LE_COUNT(CR))))
+ {
+ // LF line ends
+ cpd.newline = "\n";
+ LOG_FMT(LLINEENDS, "Using LF line endings\n");
+ }
+ else if ( options::newlines() == LE_CRLF
+ || ( options::newlines() == LE_AUTO
+ && (LE_COUNT(CRLF) >= LE_COUNT(LF))
+ && (LE_COUNT(CRLF) >= LE_COUNT(CR))))
+ {
+ // CRLF line ends
+ cpd.newline = "\r\n";
+ LOG_FMT(LLINEENDS, "Using CRLF line endings\r\n");
+ }
+ else
+ {
+ // CR line ends
+ cpd.newline = "\r";
+ LOG_FMT(LLINEENDS, "Using CR line endings\n");
+ }
+} // tokenize
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.h
new file mode 100644
index 00000000..a111143b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize.h
@@ -0,0 +1,55 @@
+/**
+ * @file tokenize.h
+ * prototypes for tokenize.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef TOKENIZE_H_INCLUDED
+#define TOKENIZE_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * Test the input string to see if it satisfies the criteria
+ * specified by the disable_processing_cmt option
+ * @param text the string to which a match will be attempted
+ * @param start_idx the starting index within the string from which the
+ * search will be performed
+ * @return returns a non-negative position index that points to the beginning
+ * of the line containing the marker, if found
+ */
+int find_disable_processing_comment_marker(const unc_text &text, std::size_t start_idx = 0);
+
+
+/**
+ * Test the input string to see if it satisfies the criteria
+ * specified by the enable_processing_cmt option
+ * @param text the string to which a match will be attempted
+ * @param start_idx the starting index within the string from which the
+ * search will be performed
+ * @return returns a non-negative position index that points to the end
+ * of the line containing the marker, if found
+ */
+int find_enable_processing_comment_marker(const unc_text &text, std::size_t start_idx = 0);
+
+
+/**
+ * @brief Parse the text into chunks
+ *
+ * This function parses or tokenizes the whole buffer into a list.
+ * It has to do some tricks to parse preprocessors.
+ *
+ * If output_text() were called immediately after, two things would happen:
+ * - trailing whitespace are removed.
+ * - leading space & tabs are converted to the appropriate format.
+ *
+ * All the tokens are inserted before ref. If ref is NULL, they are inserted
+ * at the end of the list. Line numbers are relative to the start of the data.
+ */
+void tokenize(const std::deque<int> &data, Chunk *ref);
+
+
+#endif /* TOKENIZE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.cpp
new file mode 100644
index 00000000..108a8db8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.cpp
@@ -0,0 +1,1766 @@
+/**
+ * @file tokenize_cleanup.cpp
+ * Looks at simple sequences to refine the chunk types.
+ * Examples:
+ * - change '[' + ']' into '[]'/
+ * - detect "version = 10;" vs "version (xxx) {"
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel 2015, 2021
+ * @license GPL v2+
+ */
+
+#include "tokenize_cleanup.h"
+
+#include "combine.h"
+#include "combine_skip.h"
+#include "flag_braced_init_list.h"
+#include "flag_decltype.h"
+#include "keywords.h"
+#include "prototypes.h"
+#include "punctuators.h"
+#include "space.h"
+#include "unc_ctype.h"
+
+
+using namespace uncrustify;
+
+
+/**
+ * Mark types in a single template argument.
+ *
+ * @param start chunk to start check at
+ * @param end chunk to end check at
+ */
+static void check_template_arg(Chunk *start, Chunk *end);
+
+
+/**
+ * Mark types in template argument(s).
+ *
+ * @param start chunk to start check at
+ * @param end chunk to end check at
+ */
+static void check_template_args(Chunk *start, Chunk *end);
+
+
+/**
+ * If there is nothing but CT_WORD and CT_MEMBER, then it's probably a
+ * template thingy. Otherwise, it's likely a comparison.
+ *
+ * @param start chunk to start check at
+ */
+static void check_template(Chunk *start, bool in_type_cast);
+
+
+/**
+ * Convert '>' + '>' into '>>'
+ * If we only have a single '>', then change it to CT_COMPARE.
+ *
+ * @param pc chunk to start at
+ */
+static Chunk *handle_double_angle_close(Chunk *pc);
+
+
+/**
+ * Marks ObjC specific chunks in propery declaration, by setting
+ * parent types and chunk types.
+ */
+static void cleanup_objc_property(Chunk *start);
+
+
+/**
+ * Marks ObjC specific chunks in propery declaration (getter/setter attribute)
+ * Will mark 'test4Setter'and ':' in '@property (setter=test4Setter:, strong) int test4;' as CT_OC_SEL_NAME
+ */
+static void mark_selectors_in_property_with_open_paren(Chunk *open_paren);
+
+
+/**
+ * Marks ObjC specific chunks in propery declaration ( attributes)
+ * Changes all the CT_WORD and CT_TYPE to CT_OC_PROPERTY_ATTR
+ */
+static void mark_attributes_in_property_with_open_paren(Chunk *open_paren);
+
+
+static Chunk *handle_double_angle_close(Chunk *pc)
+{
+ if (pc == nullptr)
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNotNullChunk())
+ {
+ if ( chunk_is_token(pc, CT_ANGLE_CLOSE)
+ && chunk_is_token(next, CT_ANGLE_CLOSE)
+ && get_chunk_parent_type(pc) == CT_NONE
+ && (pc->orig_col_end + 1) == next->orig_col
+ && get_chunk_parent_type(next) == CT_NONE)
+ {
+ pc->str.append('>');
+ set_chunk_type(pc, CT_SHIFT);
+ pc->orig_col_end = next->orig_col_end;
+
+ Chunk *tmp = next->GetNextNcNnl();
+ chunk_del(next);
+ next = tmp;
+ }
+ else
+ {
+ // bug #663
+ set_chunk_type(pc, CT_COMPARE);
+ }
+ }
+ return(next);
+}
+
+
+void split_off_angle_close(Chunk *pc)
+{
+ const chunk_tag_t *ct = find_punctuator(pc->Text() + 1, cpd.lang_flags);
+
+ if (ct == nullptr)
+ {
+ return;
+ }
+ Chunk nc = *pc;
+
+ pc->str.resize(1);
+ pc->orig_col_end = pc->orig_col + 1;
+ set_chunk_type(pc, CT_ANGLE_CLOSE);
+
+ set_chunk_type(&nc, ct->type);
+ nc.str.pop_front();
+ nc.orig_col++;
+ nc.column++;
+ chunk_add_after(&nc, pc);
+}
+
+
+void tokenize_trailing_return_types(void)
+{
+ // Issue #2330
+ // auto max(int a, int b) -> int;
+ // Issue #2460
+ // auto f01() -> bool;
+ // auto f02() noexcept -> bool;
+ // auto f03() noexcept(true) -> bool;
+ // auto f04() noexcept(false) -> bool;
+ // auto f05() noexcept -> bool = delete;
+ // auto f06() noexcept(true) -> bool = delete;
+ // auto f07() noexcept(false) -> bool = delete;
+ // auto f11() const -> bool;
+ // auto f12() const noexcept -> bool;
+ // auto f13() const noexcept(true) -> bool;
+ // auto f14() const noexcept(false) -> bool;
+ // auto f15() const noexcept -> bool = delete;
+ // auto f16() const noexcept(true) -> bool = delete;
+ // auto f17() const noexcept(false) -> bool = delete;
+ // auto f21() throw() -> bool;
+ // auto f22() throw() -> bool = delete;
+ // auto f23() const throw() -> bool;
+ // auto f24() const throw() -> bool = delete;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ char copy[1000];
+ LOG_FMT(LNOTE, "%s(%d): orig_line is %zu, orig_col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->ElidedText(copy));
+
+ if ( chunk_is_token(pc, CT_MEMBER)
+ && (strcmp(pc->Text(), "->") == 0))
+ {
+ Chunk *tmp = pc->GetPrevNcNnl();
+ Chunk *tmp_2;
+ Chunk *open_paren;
+
+ if (chunk_is_token(tmp, CT_QUALIFIER))
+ {
+ // auto max(int a, int b) const -> int;
+ // auto f11() const -> bool;
+ tmp = tmp->GetPrevNcNnl();
+ }
+ else if (chunk_is_token(tmp, CT_NOEXCEPT))
+ {
+ // noexcept is present
+ tmp_2 = tmp->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp_2, CT_QUALIFIER))
+ {
+ // auto f12() const noexcept -> bool;
+ // auto f15() const noexcept -> bool = delete;
+ tmp = tmp_2->GetPrevNcNnl();
+ }
+ else
+ {
+ // auto f02() noexcept -> bool;
+ // auto f05() noexcept -> bool = delete;
+ tmp = tmp_2;
+ }
+ }
+ else if (chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ open_paren = tmp->GetPrevType(CT_PAREN_OPEN, tmp->level);
+ tmp = open_paren->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp, CT_NOEXCEPT))
+ {
+ // noexcept is present
+ tmp_2 = tmp->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp_2, CT_QUALIFIER))
+ {
+ // auto f13() const noexcept(true) -> bool;
+ // auto f14() const noexcept(false) -> bool;
+ // auto f16() const noexcept(true) -> bool = delete;
+ // auto f17() const noexcept(false) -> bool = delete;
+ tmp = tmp_2->GetPrevNcNnl();
+ }
+ else
+ {
+ // auto f03() noexcept(true) -> bool;
+ // auto f04() noexcept(false) -> bool;
+ // auto f06() noexcept(true) -> bool = delete;
+ // auto f07() noexcept(false) -> bool = delete;
+ tmp = tmp_2;
+ }
+ }
+ else if (chunk_is_token(tmp, CT_THROW))
+ {
+ // throw is present
+ tmp_2 = tmp->GetPrevNcNnl();
+
+ if (chunk_is_token(tmp_2, CT_QUALIFIER))
+ {
+ // auto f23() const throw() -> bool;
+ // auto f24() const throw() -> bool = delete;
+ tmp = tmp_2->GetPrevNcNnl();
+ }
+ else
+ {
+ // auto f21() throw() -> bool;
+ // auto f22() throw() -> bool = delete;
+ tmp = tmp_2;
+ }
+ }
+ else
+ {
+ LOG_FMT(LNOTE, "%s(%d): NOT COVERED\n", __func__, __LINE__);
+ }
+ }
+ else
+ {
+ LOG_FMT(LNOTE, "%s(%d): NOT COVERED\n", __func__, __LINE__);
+ }
+
+ if ( chunk_is_token(tmp, CT_FPAREN_CLOSE)
+ && ( get_chunk_parent_type(tmp) == CT_FUNC_PROTO
+ || get_chunk_parent_type(tmp) == CT_FUNC_DEF))
+ {
+ set_chunk_type(pc, CT_TRAILING_RET);
+ LOG_FMT(LNOTE, "%s(%d): set trailing return type for Text() is '%s'\n",
+ __func__, __LINE__, pc->Text()); // Issue #3222
+ // TODO
+ // https://en.cppreference.com/w/cpp/language/function
+ // noptr-declarator ( parameter-list ) cv(optional) ref(optional) except(optional) attr(optional) -> trailing
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_DECLTYPE))
+ {
+ // TODO
+ }
+ else if (chunk_is_token(next, CT_WORD))
+ {
+ set_chunk_type(next, CT_TYPE); // Issue #3222
+ next = next->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_ARITH))
+ {
+ if (next->str[0] == '*')
+ {
+ set_chunk_type(next, CT_PTR_TYPE);
+ }
+ else if (next->str[0] == '&') // Issue #3407
+ {
+ set_chunk_type(next, CT_BYREF);
+ }
+ }
+ }
+ else
+ {
+ // TODO
+ }
+ }
+ }
+ }
+} // tokenize_trailing_return_types
+
+
+void tokenize_cleanup(void)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = nullptr;
+ Chunk *next;
+ bool in_type_cast = false;
+
+ cpd.unc_stage = unc_stage_e::TOKENIZE_CLEANUP;
+
+ /*
+ * Since [] is expected to be TSQUARE for the 'operator', we need to make
+ * this change in the first pass.
+ */
+ Chunk *pc;
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (chunk_is_token(pc, CT_SQUARE_OPEN))
+ {
+ next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_SQUARE_CLOSE))
+ {
+ // Change '[' + ']' into '[]'
+ set_chunk_type(pc, CT_TSQUARE);
+ pc->str = "[]";
+ /*
+ * bug #664: The original orig_col_end of CT_SQUARE_CLOSE is
+ * stored at orig_col_end of CT_TSQUARE.
+ * pc->orig_col_end += 1;
+ */
+ pc->orig_col_end = next->orig_col_end;
+ chunk_del(next);
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ && pc->flags.test(PCF_IN_PREPROC)
+ && !pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ LOG_FMT(LNOTE, "%s(%d): %s:%zu Detected a macro that ends with a semicolon. Possible failures if used.\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc->orig_line);
+ }
+ }
+
+ // change := to CT_SQL_ASSIGN Issue #527
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (chunk_is_token(pc, CT_COLON))
+ {
+ next = pc->GetNextNcNnl();
+
+ if (chunk_is_token(next, CT_ASSIGN))
+ {
+ // Change ':' + '=' into ':='
+ set_chunk_type(pc, CT_SQL_ASSIGN);
+ pc->str = ":=";
+ pc->orig_col_end = next->orig_col_end;
+ chunk_del(next);
+ }
+ }
+ }
+
+ // We can handle everything else in the second pass
+ pc = Chunk::GetHead();
+ next = pc->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ if ( chunk_is_token(pc, CT_DOT)
+ && language_is_set(LANG_ALLC))
+ {
+ set_chunk_type(pc, CT_MEMBER);
+ }
+
+ if ( chunk_is_token(pc, CT_NULLCOND)
+ && language_is_set(LANG_CS))
+ {
+ set_chunk_type(pc, CT_MEMBER);
+ }
+
+ // Determine the version stuff (D only)
+ if (chunk_is_token(pc, CT_D_VERSION))
+ {
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_D_VERSION_IF);
+ }
+ else
+ {
+ if (next->type != CT_ASSIGN)
+ {
+ LOG_FMT(LERR, "%s(%d): %s:%zu: version: Unexpected token %s\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, get_token_name(next->type));
+ cpd.error_count++;
+ }
+ set_chunk_type(pc, CT_WORD);
+ }
+ }
+
+ // Determine the scope stuff (D only)
+ if (chunk_is_token(pc, CT_D_SCOPE))
+ {
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_D_SCOPE_IF);
+ }
+ else
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ }
+
+ /*
+ * Change CT_BASE before CT_PAREN_OPEN to CT_WORD.
+ * public myclass() : base() {}
+ * -or-
+ * var x = (T)base.y;
+ */
+ if ( chunk_is_token(pc, CT_BASE)
+ && ( chunk_is_token(next, CT_PAREN_OPEN)
+ || chunk_is_token(next, CT_DOT)))
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+
+ if ( chunk_is_token(pc, CT_ENUM)
+ && ( chunk_is_token(next, CT_STRUCT)
+ || chunk_is_token(next, CT_CLASS)))
+ {
+ set_chunk_type(next, CT_ENUM_CLASS);
+ }
+ Chunk *next_non_attr = language_is_set(LANG_CPP) ? skip_attribute_next(next) : next;
+
+ /*
+ * Change CT_WORD after CT_ENUM, CT_UNION, CT_STRUCT, or CT_CLASS to CT_TYPE
+ * Change CT_WORD before CT_WORD to CT_TYPE
+ */
+ if (chunk_is_token(next_non_attr, CT_WORD))
+ {
+ if ( chunk_is_token(pc, CT_ENUM)
+ || chunk_is_token(pc, CT_ENUM_CLASS)
+ || chunk_is_token(pc, CT_UNION)
+ || chunk_is_token(pc, CT_STRUCT)
+ || chunk_is_token(pc, CT_CLASS))
+ {
+ set_chunk_type(next_non_attr, CT_TYPE);
+ }
+
+ if (chunk_is_token(pc, CT_WORD))
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ }
+
+ /*
+ * change extern to qualifier if extern isn't followed by a string or
+ * an open parenthesis
+ */
+ if (chunk_is_token(pc, CT_EXTERN))
+ {
+ if (chunk_is_token(next, CT_STRING))
+ {
+ // Probably 'extern "C"'
+ }
+ else if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ // Probably 'extern (C)'
+ }
+ else
+ {
+ // Something else followed by a open brace
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if ( tmp->IsNullChunk()
+ || tmp->type != CT_BRACE_OPEN)
+ {
+ set_chunk_type(pc, CT_QUALIFIER);
+ }
+ }
+ }
+
+ /*
+ * Change CT_STAR to CT_PTR_TYPE if preceded by
+ * CT_TYPE, CT_QUALIFIER, or CT_PTR_TYPE
+ * or by a
+ * CT_WORD which is preceded by CT_DC_MEMBER: '::aaa *b'
+ */
+ if ( (chunk_is_token(next, CT_STAR))
+ || ( language_is_set(LANG_CPP)
+ && (chunk_is_token(next, CT_CARET)))
+ || ( language_is_set(LANG_CS | LANG_VALA)
+ && (chunk_is_token(next, CT_QUESTION))
+ && (strcmp(pc->Text(), "null") != 0)))
+ {
+ if ( chunk_is_token(pc, CT_TYPE)
+ || chunk_is_token(pc, CT_QUALIFIER)
+ || chunk_is_token(pc, CT_PTR_TYPE))
+ {
+ set_chunk_type(next, CT_PTR_TYPE);
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_TYPE_CAST)
+ && chunk_is_token(next, CT_ANGLE_OPEN))
+ {
+ set_chunk_parent(next, CT_TYPE_CAST);
+ in_type_cast = true;
+ }
+
+ if (chunk_is_token(pc, CT_DECLTYPE))
+ {
+ flag_cpp_decltype(pc);
+ }
+
+ // Change angle open/close to CT_COMPARE, if not a template thingy
+ if ( chunk_is_token(pc, CT_ANGLE_OPEN)
+ && pc->parent_type != CT_TYPE_CAST)
+ {
+ /*
+ * pretty much all languages except C use <> for something other than
+ * comparisons. "#include<xxx>" is handled elsewhere.
+ */
+ if (language_is_set(LANG_OC | LANG_CPP | LANG_CS | LANG_JAVA | LANG_VALA))
+ {
+ // bug #663
+ check_template(pc, in_type_cast);
+ }
+ else
+ {
+ // convert CT_ANGLE_OPEN to CT_COMPARE
+ set_chunk_type(pc, CT_COMPARE);
+ }
+ }
+
+ if ( chunk_is_token(pc, CT_ANGLE_CLOSE)
+ && pc->parent_type != CT_TEMPLATE)
+ {
+ if (in_type_cast)
+ {
+ in_type_cast = false;
+ set_chunk_parent(pc, CT_TYPE_CAST);
+ }
+ else
+ {
+ next = handle_double_angle_close(pc);
+ }
+ }
+
+ if (language_is_set(LANG_D))
+ {
+ // Check for the D string concat symbol '~'
+ if ( chunk_is_token(pc, CT_INV)
+ && ( chunk_is_token(prev, CT_STRING)
+ || chunk_is_token(prev, CT_WORD)
+ || chunk_is_token(next, CT_STRING)))
+ {
+ set_chunk_type(pc, CT_CONCAT);
+ }
+
+ // Check for the D template symbol '!' (word + '!' + word or '(')
+ if ( chunk_is_token(pc, CT_NOT)
+ && chunk_is_token(prev, CT_WORD)
+ && ( chunk_is_token(next, CT_PAREN_OPEN)
+ || chunk_is_token(next, CT_WORD)
+ || chunk_is_token(next, CT_TYPE)
+ || chunk_is_token(next, CT_NUMBER)
+ || chunk_is_token(next, CT_NUMBER_FP)
+ || chunk_is_token(next, CT_STRING)
+ || chunk_is_token(next, CT_STRING_MULTI)))
+ {
+ set_chunk_type(pc, CT_D_TEMPLATE);
+ }
+
+ // handle "version(unittest) { }" vs "unittest { }"
+ if ( chunk_is_token(pc, CT_UNITTEST)
+ && chunk_is_token(prev, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+
+ // handle 'static if' and merge the tokens
+ if ( chunk_is_token(pc, CT_IF)
+ && chunk_is_str(prev, "static"))
+ {
+ // delete PREV and merge with IF
+ pc->str.insert(0, ' ');
+ pc->str.insert(0, prev->str);
+ pc->orig_col = prev->orig_col;
+ pc->orig_line = prev->orig_line;
+ Chunk *to_be_deleted = prev;
+ prev = prev->GetPrevNcNnl();
+
+ if (prev->IsNotNullChunk())
+ {
+ chunk_del(to_be_deleted);
+ }
+ }
+ }
+
+ if (language_is_set(LANG_CPP))
+ {
+ // Change Word before '::' into a type
+ if ( chunk_is_token(pc, CT_WORD)
+ && chunk_is_token(next, CT_DC_MEMBER))
+ {
+ prev = pc->GetPrev();
+
+ if (prev->IsNullChunk()) // Issue #3010
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ else
+ {
+ if (chunk_is_token(prev, CT_COLON))
+ {
+ // nothing to do
+ }
+ else
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ }
+ }
+
+ // Set parent type for 'if constexpr'
+ if ( chunk_is_token(prev, CT_IF)
+ && chunk_is_token(pc, CT_QUALIFIER)
+ && chunk_is_str(pc, "constexpr"))
+ {
+ set_chunk_type(pc, CT_CONSTEXPR);
+ }
+ }
+
+ // Change get/set to CT_WORD if not followed by a brace open
+ if ( chunk_is_token(pc, CT_GETSET)
+ && next->type != CT_BRACE_OPEN)
+ {
+ if ( chunk_is_token(next, CT_SEMICOLON)
+ && ( chunk_is_token(prev, CT_BRACE_CLOSE)
+ || chunk_is_token(prev, CT_BRACE_OPEN)
+ || chunk_is_token(prev, CT_SEMICOLON)))
+ {
+ set_chunk_type(pc, CT_GETSET_EMPTY);
+ set_chunk_parent(next, CT_GETSET);
+ }
+ else
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+ }
+
+ /*
+ * Interface is only a keyword in MS land if followed by 'class' or 'struct'
+ * likewise, 'class' may be a member name in Java.
+ */
+ if ( chunk_is_token(pc, CT_CLASS)
+ && !CharTable::IsKw1(next->str[0]))
+ {
+ if ( chunk_is_not_token(next, CT_DC_MEMBER)
+ && chunk_is_not_token(next, CT_ATTRIBUTE)) // Issue #2570
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+ else if ( chunk_is_token(prev, CT_DC_MEMBER)
+ || chunk_is_token(prev, CT_TYPE))
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ else if (chunk_is_token(next, CT_DC_MEMBER))
+ {
+ Chunk *next2 = next->GetNextNcNnlNet();
+
+ if ( chunk_is_token(next2, CT_INV) // CT_INV hasn't turned into CT_DESTRUCTOR just yet
+ || ( chunk_is_token(next2, CT_CLASS) // constructor isn't turned into CT_FUNC* just yet
+ && !strcmp(pc->Text(), next2->Text())))
+ {
+ set_chunk_type(pc, CT_TYPE);
+ }
+ }
+ }
+
+ /*
+ * Change item after operator (>=, ==, etc) to a CT_OPERATOR_VAL
+ * Usually the next item is part of the operator.
+ * In a few cases the next few tokens are part of it:
+ * operator + - common case
+ * operator >> - need to combine '>' and '>'
+ * operator ()
+ * operator [] - already converted to TSQUARE
+ * operator new []
+ * operator delete []
+ * operator const char *
+ * operator const B&
+ * operator std::allocator<U>
+ *
+ * In all cases except the last, this will put the entire operator value
+ * in one chunk.
+ */
+ if (chunk_is_token(pc, CT_OPERATOR))
+ {
+ Chunk *tmp2 = next->GetNext();
+
+ // Handle special case of () operator -- [] already handled
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ Chunk *tmp = next->GetNext();
+
+ if (chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ next->str = "()";
+ set_chunk_type(next, CT_OPERATOR_VAL);
+ chunk_del(tmp);
+ next->orig_col_end += 1;
+ }
+ }
+ else if ( chunk_is_token(next, CT_ANGLE_CLOSE)
+ && chunk_is_token(tmp2, CT_ANGLE_CLOSE)
+ && tmp2->orig_col == next->orig_col_end)
+ {
+ next->str.append('>');
+ next->orig_col_end++;
+ set_chunk_type(next, CT_OPERATOR_VAL);
+ chunk_del(tmp2);
+ }
+ else if (next->flags.test(PCF_PUNCTUATOR))
+ {
+ set_chunk_type(next, CT_OPERATOR_VAL);
+ }
+ else
+ {
+ set_chunk_type(next, CT_TYPE);
+
+ /*
+ * Replace next with a collection of all tokens that are part of
+ * the type.
+ */
+ tmp2 = next;
+ Chunk *tmp;
+
+ while ((tmp = tmp2->GetNext())->IsNotNullChunk())
+ {
+ if ( tmp->type != CT_WORD
+ && tmp->type != CT_TYPE
+ && tmp->type != CT_QUALIFIER
+ && tmp->type != CT_STAR
+ && tmp->type != CT_CARET
+ && tmp->type != CT_AMP
+ && tmp->type != CT_TSQUARE)
+ {
+ break;
+ }
+ // Change tmp into a type so that space_needed() works right
+ make_type(tmp);
+ size_t num_sp = space_needed(tmp2, tmp);
+
+ while (num_sp-- > 0)
+ {
+ next->str.append(" ");
+ }
+ next->str.append(tmp->str);
+ tmp2 = tmp;
+ }
+
+ while ((tmp2 = next->GetNext()) != tmp)
+ {
+ chunk_del(tmp2);
+ }
+ set_chunk_type(next, CT_OPERATOR_VAL);
+
+ next->orig_col_end = next->orig_col + next->Len();
+ }
+ set_chunk_parent(next, CT_OPERATOR);
+
+ LOG_FMT(LOPERATOR, "%s(%d): %zu:%zu operator '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, next->Text());
+ }
+
+ // Change private, public, protected into either a qualifier or label
+ if (chunk_is_token(pc, CT_ACCESS))
+ {
+ // Handle Qt slots - maybe should just check for a CT_WORD?
+ if ( chunk_is_str(next, "slots")
+ || chunk_is_str(next, "Q_SLOTS"))
+ {
+ Chunk *tmp = next->GetNext();
+
+ if (chunk_is_token(tmp, CT_COLON))
+ {
+ next = tmp;
+ }
+ }
+
+ if (chunk_is_token(next, CT_COLON))
+ {
+ set_chunk_type(next, CT_ACCESS_COLON);
+ Chunk *tmp;
+
+ if ((tmp = next->GetNextNcNnl())->IsNotNullChunk())
+ {
+ chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);
+ }
+ }
+ else
+ {
+ set_chunk_type(pc, ( chunk_is_str(pc, "signals")
+ || chunk_is_str(pc, "Q_SIGNALS"))
+ ? CT_WORD : CT_QUALIFIER);
+ }
+ }
+
+ // Look for <newline> 'EXEC' 'SQL'
+ if ( ( chunk_is_str_case(pc, "EXEC", 4)
+ && chunk_is_str_case(next, "SQL", 3))
+ || ( (*pc->str.c_str() == '$')
+ && pc->type != CT_SQL_WORD
+ /* but avoid breaking tokenization for C# 6 interpolated strings. */
+ && ( !language_is_set(LANG_CS)
+ || ( chunk_is_token(pc, CT_STRING)
+ && (!pc->str.startswith("$\""))
+ && (!pc->str.startswith("$@\""))))))
+ {
+ Chunk *tmp = pc->GetPrev();
+
+ if (chunk_is_newline(tmp))
+ {
+ if (*pc->str.c_str() == '$')
+ {
+ set_chunk_type(pc, CT_SQL_EXEC);
+
+ if (pc->Len() > 1)
+ {
+ // SPLIT OFF '$'
+ Chunk nc;
+
+ nc = *pc;
+ pc->str.resize(1);
+ pc->orig_col_end = pc->orig_col + 1;
+
+ set_chunk_type(&nc, CT_SQL_WORD);
+ nc.str.pop_front();
+ nc.orig_col++;
+ nc.column++;
+ chunk_add_after(&nc, pc);
+
+ next = pc->GetNext();
+ }
+ }
+ tmp = next->GetNext();
+
+ if (chunk_is_str_case(tmp, "BEGIN", 5))
+ {
+ set_chunk_type(pc, CT_SQL_BEGIN);
+ }
+ else if (chunk_is_str_case(tmp, "END", 3))
+ {
+ set_chunk_type(pc, CT_SQL_END);
+ }
+ else
+ {
+ set_chunk_type(pc, CT_SQL_EXEC);
+ }
+
+ // Change words into CT_SQL_WORD until CT_SEMICOLON
+ while (tmp->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if ( (tmp->Len() > 0)
+ && ( unc_isalpha(*tmp->str.c_str())
+ || (*tmp->str.c_str() == '$')))
+ {
+ set_chunk_type(tmp, CT_SQL_WORD);
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+ }
+
+ // handle MS abomination 'for each'
+ if ( chunk_is_token(pc, CT_FOR)
+ && chunk_is_str(next, "each")
+ && (next == pc->GetNext()))
+ {
+ // merge the two with a space between
+ pc->str.append(' ');
+ pc->str += next->str;
+ pc->orig_col_end = next->orig_col_end;
+ chunk_del(next);
+ next = pc->GetNextNcNnl();
+
+ // label the 'in'
+ if (chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ Chunk *tmp = next->GetNextNcNnl();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->type != CT_PAREN_CLOSE)
+ {
+ if (chunk_is_str(tmp, "in"))
+ {
+ set_chunk_type(tmp, CT_IN);
+ break;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+ }
+
+ /*
+ * ObjectiveC allows keywords to be used as identifiers in some situations
+ * This is a dirty hack to allow some of the more common situations.
+ */
+ if (language_is_set(LANG_OC))
+ {
+ if ( ( chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_FOR)
+ || chunk_is_token(pc, CT_WHILE))
+ && !chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+
+ if ( chunk_is_token(pc, CT_DO)
+ && ( chunk_is_token(prev, CT_MINUS)
+ || chunk_is_token(next, CT_SQUARE_CLOSE)))
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+
+ // Fix self keyword back to word when mixing c++/objective-c
+ if ( chunk_is_token(pc, CT_THIS)
+ && !strcmp(pc->Text(), "self")
+ && ( chunk_is_token(next, CT_COMMA)
+ || chunk_is_token(next, CT_PAREN_CLOSE)))
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+
+ // Fix self keyword back to word when mixing c++/objective-c
+ if ( chunk_is_token(pc, CT_THIS)
+ && !strcmp(pc->Text(), "self")
+ && ( chunk_is_token(next, CT_COMMA)
+ || chunk_is_token(next, CT_PAREN_CLOSE)))
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+ }
+
+ // Another hack to clean up more keyword abuse
+ if ( chunk_is_token(pc, CT_CLASS)
+ && ( chunk_is_token(prev, CT_DOT)
+ || chunk_is_token(next, CT_DOT)
+ || chunk_is_token(prev, CT_MEMBER) // Issue #3031
+ || chunk_is_token(next, CT_MEMBER)))
+ {
+ set_chunk_type(pc, CT_WORD);
+ }
+
+ // Detect Objective C class name
+ if ( chunk_is_token(pc, CT_OC_IMPL)
+ || chunk_is_token(pc, CT_OC_INTF)
+ || chunk_is_token(pc, CT_OC_PROTOCOL))
+ {
+ if (next->type != CT_PAREN_OPEN)
+ {
+ set_chunk_type(next, CT_OC_CLASS);
+ }
+ set_chunk_parent(next, pc->type);
+
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);
+ }
+ tmp = pc->GetNextType(CT_OC_END, pc->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_parent(tmp, pc->type);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_OC_INTF))
+ {
+ Chunk *tmp = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->type != CT_OC_END)
+ {
+ if (get_token_pattern_class(tmp->type) != pattern_class_e::NONE)
+ {
+ LOG_FMT(LOBJCWORD, "%s(%d): @interface %zu:%zu change '%s' (%s) to CT_WORD\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, tmp->Text(),
+ get_token_name(tmp->type));
+ set_chunk_type(tmp, CT_WORD);
+ }
+ tmp = tmp->GetNextNcNnl(E_Scope::PREPROC);
+ }
+ }
+
+ /*
+ * Detect Objective-C categories and class extensions:
+ * @interface ClassName (CategoryName)
+ * @implementation ClassName (CategoryName)
+ * @interface ClassName ()
+ * @implementation ClassName ()
+ */
+ if ( ( get_chunk_parent_type(pc) == CT_OC_IMPL
+ || get_chunk_parent_type(pc) == CT_OC_INTF
+ || chunk_is_token(pc, CT_OC_CLASS))
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_parent(next, get_chunk_parent_type(pc));
+
+ Chunk *tmp = next->GetNext();
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetNext()->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ //set_chunk_type(tmp, CT_OC_CLASS_EXT);
+ set_chunk_parent(tmp, get_chunk_parent_type(pc));
+ }
+ else
+ {
+ set_chunk_type(tmp, CT_OC_CATEGORY);
+ set_chunk_parent(tmp, get_chunk_parent_type(pc));
+ }
+ }
+ tmp = pc->GetNextType(CT_PAREN_CLOSE, pc->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_parent(tmp, get_chunk_parent_type(pc));
+ }
+ }
+
+ /*
+ * Detect Objective C @property:
+ * @property NSString *stringProperty;
+ * @property(nonatomic, retain) NSMutableDictionary *shareWith;
+ */
+ if (chunk_is_token(pc, CT_OC_PROPERTY))
+ {
+ if (next->type != CT_PAREN_OPEN)
+ {
+ chunk_flags_set(next, PCF_STMT_START | PCF_EXPR_START);
+ }
+ else
+ {
+ cleanup_objc_property(pc);
+ }
+ }
+
+ /*
+ * Detect Objective C @selector:
+ * @selector(msgNameWithNoArg)
+ * @selector(msgNameWith1Arg:)
+ * @selector(msgNameWith2Args:arg2Name:)
+ */
+ if ( chunk_is_token(pc, CT_OC_SEL)
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_parent(next, pc->type);
+
+ Chunk *tmp = next->GetNext();
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_type(tmp, CT_OC_SEL_NAME);
+ set_chunk_parent(tmp, pc->type);
+
+ while ((tmp = tmp->GetNextNcNnl())->IsNotNullChunk())
+ {
+ if (chunk_is_token(tmp, CT_PAREN_CLOSE))
+ {
+ set_chunk_parent(tmp, CT_OC_SEL);
+ break;
+ }
+ set_chunk_type(tmp, CT_OC_SEL_NAME);
+ set_chunk_parent(tmp, pc->type);
+ }
+ }
+ }
+
+ // Handle special preprocessor junk
+ if (chunk_is_token(pc, CT_PREPROC))
+ {
+ set_chunk_parent(pc, next->type);
+ }
+
+ // Detect "pragma region" and "pragma endregion"
+ if ( chunk_is_token(pc, CT_PP_PRAGMA)
+ && chunk_is_token(next, CT_PREPROC_BODY))
+ {
+ if ( (strncmp(next->str.c_str(), "region", 6) == 0)
+ || (strncmp(next->str.c_str(), "endregion", 9) == 0))
+ // TODO: probably better use strncmp
+ {
+ set_chunk_type(pc, (*next->str.c_str() == 'r') ? CT_PP_REGION : CT_PP_ENDREGION);
+
+ set_chunk_parent(prev, pc->type);
+ }
+ }
+
+ // Change 'default(' into a sizeof-like statement
+ if ( language_is_set(LANG_CS)
+ && chunk_is_token(pc, CT_DEFAULT)
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_SIZEOF);
+ }
+
+ if ( chunk_is_token(pc, CT_UNSAFE)
+ && next->type != CT_BRACE_OPEN)
+ {
+ set_chunk_type(pc, CT_QUALIFIER);
+ }
+
+ if ( ( chunk_is_token(pc, CT_USING)
+ || ( chunk_is_token(pc, CT_TRY)
+ && language_is_set(LANG_JAVA)))
+ && chunk_is_token(next, CT_PAREN_OPEN))
+ {
+ set_chunk_type(pc, CT_USING_STMT);
+ }
+
+ // Add minimal support for C++0x rvalue references
+ if ( chunk_is_token(pc, CT_BOOL)
+ && language_is_set(LANG_CPP)
+ && chunk_is_str(pc, "&&"))
+ {
+ if (chunk_is_token(prev, CT_TYPE))
+ {
+ // Issue # 1002
+ if (!pc->flags.test(PCF_IN_TEMPLATE))
+ {
+ set_chunk_type(pc, CT_BYREF);
+ }
+ }
+ }
+
+ /*
+ * HACK: treat try followed by a colon as a qualifier to handle this:
+ * A::A(int) try : B() { } catch (...) { }
+ */
+ if ( chunk_is_token(pc, CT_TRY)
+ && chunk_is_str(pc, "try")
+ && chunk_is_token(next, CT_COLON))
+ {
+ set_chunk_type(pc, CT_QUALIFIER);
+ }
+
+ /*
+ * If Java's 'synchronized' is in a method declaration, it should be
+ * a qualifier.
+ */
+ if ( language_is_set(LANG_JAVA)
+ && chunk_is_token(pc, CT_SYNCHRONIZED)
+ && next->type != CT_PAREN_OPEN)
+ {
+ set_chunk_type(pc, CT_QUALIFIER);
+ }
+
+ // change CT_DC_MEMBER + CT_FOR into CT_DC_MEMBER + CT_FUNC_CALL
+ if ( chunk_is_token(pc, CT_FOR)
+ && chunk_is_token(pc->prev, CT_DC_MEMBER))
+ {
+ set_chunk_type(pc, CT_FUNC_CALL);
+ }
+ // TODO: determine other stuff here
+
+ prev = pc;
+ pc = next;
+ next = pc->GetNextNcNnl();
+ }
+} // tokenize_cleanup
+
+
+bool invalid_open_angle_template(Chunk *prev)
+{
+ if (prev == nullptr)
+ {
+ return(false);
+ }
+ // A template requires a word/type right before the open angle
+ return( prev->type != CT_WORD
+ && prev->type != CT_TYPE
+ && prev->type != CT_COMMA
+ && prev->type != CT_QUALIFIER
+ && prev->type != CT_OPERATOR_VAL
+ && get_chunk_parent_type(prev) != CT_OPERATOR);
+}
+
+
+static void check_template(Chunk *start, bool in_type_cast)
+{
+ LOG_FMT(LTEMPL, "%s(%d): orig_line %zu, orig_col %zu:\n",
+ __func__, __LINE__, start->orig_line, start->orig_col);
+
+ Chunk *prev = start->GetPrevNcNnl(E_Scope::PREPROC);
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *end;
+ Chunk *pc;
+
+ if (chunk_is_token(prev, CT_TEMPLATE))
+ {
+ LOG_FMT(LTEMPL, "%s(%d): CT_TEMPLATE:\n", __func__, __LINE__);
+
+ // We have: "template< ... >", which is a template declaration
+ size_t level = 1;
+ size_t parens = 0;
+
+ for (pc = start->GetNextNcNnl(E_Scope::PREPROC);
+ pc->IsNotNullChunk();
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ LOG_FMT(LTEMPL, "%s(%d): type is %s, level is %zu\n",
+ __func__, __LINE__, get_token_name(pc->type), level);
+
+ if ( (pc->str[0] == '>')
+ && (pc->Len() > 1))
+ {
+ if (pc->str[1] == '=') // Issue #1462 and #2565
+ {
+ LOG_FMT(LTEMPL, "%s(%d): do not split '%s' at orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LTEMPL, "%s(%d): {split '%s' at orig_line %zu, orig_col %zu}\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+ split_off_angle_close(pc);
+ }
+ }
+
+ if (chunk_is_token(pc, CT_DECLTYPE))
+ {
+ flag_cpp_decltype(pc);
+ }
+ else if (chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ ++parens;
+ }
+ else if (chunk_is_token(pc, CT_PAREN_CLOSE))
+ {
+ --parens;
+ }
+
+ if (parens == 0)
+ {
+ if (chunk_is_str(pc, "<"))
+ {
+ level++;
+ }
+ else if (chunk_is_str(pc, ">"))
+ {
+ if (level == 0)
+ {
+ fprintf(stderr, "%s(%d): level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ level--;
+
+ if (level == 0)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ end = pc;
+ }
+ else
+ {
+ /*
+ * We may have something like "a< ... >", which is a template where
+ * '...' may consist of anything except a semicolon, unbalanced
+ * parens, or braces (with one exception being braced initializers
+ * embedded within decltypes).
+ *
+ * For example, braces may be encountered as such in the following
+ * snippet of valid C++ code:
+ *
+ * template<typename T,
+ * typename = enable_if_t<is_same<typename decay<T>::type,
+ * decltype (make_index_sequence<5> { })>::value>>
+ * void foo(T &&arg)
+ * {
+ *
+ * }
+ *
+ * Finally, if we are inside an 'if' statement and hit a CT_BOOL,
+ * then it isn't a template.
+ */
+
+ if (invalid_open_angle_template(prev))
+ {
+ LOG_FMT(LTEMPL, "%s(%d): - after type %s + ( - Not a template\n",
+ __func__, __LINE__, get_token_name(prev->type));
+ set_chunk_type(start, CT_COMPARE);
+ return;
+ }
+ LOG_FMT(LTEMPL, "%s(%d): - prev->type is %s -\n",
+ __func__, __LINE__, get_token_name(prev->type));
+
+ // Scan back and make sure we aren't inside square parenthesis
+ bool in_if = false;
+ bool hit_semicolon = false;
+ pc = start->GetPrevNcNnl(E_Scope::PREPROC);
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( ( chunk_is_token(pc, CT_SEMICOLON)
+ && hit_semicolon)
+ || chunk_is_token(pc, CT_SQUARE_CLOSE))
+ {
+ break;
+ }
+
+ if (chunk_is_token(pc, CT_DECLTYPE))
+ {
+ flag_cpp_decltype(pc);
+ }
+
+ if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ if ( !pc->flags.test(PCF_IN_DECLTYPE)
+ || !detect_cpp_braced_init_list(pc->prev, pc))
+ {
+ break;
+ }
+ flag_cpp_braced_init_list(pc->prev, pc);
+ }
+
+ if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(pc) != CT_BRACED_INIT_LIST
+ && !pc->flags.test(PCF_IN_DECLTYPE))
+ {
+ break;
+ }
+
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ && !hit_semicolon)
+ {
+ hit_semicolon = true;
+ }
+
+ if ( ( ( chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_RETURN)
+ || chunk_is_token(pc, CT_WHILE)
+ || chunk_is_token(pc, CT_WHILE_OF_DO))
+ && !hit_semicolon)
+ || ( chunk_is_token(pc, CT_FOR)
+ && hit_semicolon))
+ {
+ in_if = true;
+ break;
+ }
+ pc = pc->GetPrevNcNnl(E_Scope::PREPROC);
+ }
+ /*
+ * Scan forward to the angle close
+ * If we have a comparison in there, then it can't be a template.
+ */
+ const int max_token_count = 1024;
+ E_Token tokens[max_token_count];
+ size_t num_tokens = 1;
+
+ tokens[0] = CT_ANGLE_OPEN;
+
+ for (pc = start->GetNextNcNnl(E_Scope::PREPROC);
+ pc->IsNotNullChunk();
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ constexpr static auto LCURRENT = LTEMPL;
+
+ LOG_FMT(LTEMPL, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu, type is %s, num_tokens is %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, get_token_name(pc->type), num_tokens);
+
+ log_rule_B("tok_split_gte");
+
+ if (chunk_is_token(pc, CT_BRACE_OPEN)) // Issue #2886
+ {
+ // look for the closing brace
+ Chunk *A = chunk_skip_to_match(pc);
+ LOG_FMT(LTEMPL, "%s(%d): A->orig_line is %zu, A->orig_col is %zu, type is %s\n",
+ __func__, __LINE__, A->orig_line, A->orig_col, get_token_name(A->type));
+ pc = A->GetNext();
+ }
+
+ if ( (tokens[num_tokens - 1] == CT_ANGLE_OPEN)
+ && (pc->str[0] == '>')
+ && (pc->Len() > 1)
+ && ( options::tok_split_gte()
+ || ( ( chunk_is_str(pc, ">>")
+ || chunk_is_str(pc, ">>>"))
+ && ( num_tokens >= 2
+ || ( num_tokens >= 1
+ && in_type_cast)))))
+ {
+ LOG_FMT(LTEMPL, "%s(%d): {split '%s' at orig_line %zu, orig_col %zu}\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+
+ split_off_angle_close(pc);
+ }
+
+ if (chunk_is_str(pc, "<"))
+ {
+ if ( num_tokens > 0 && (tokens[num_tokens - 1] == CT_PAREN_OPEN)
+ && invalid_open_angle_template(pc->prev))
+ {
+ set_chunk_type(pc, CT_COMPARE); // Issue #3127
+ }
+ else
+ {
+ tokens[num_tokens] = CT_ANGLE_OPEN;
+ num_tokens++;
+ }
+ }
+ else if (chunk_is_str(pc, ">"))
+ {
+ if (num_tokens > 0 && (tokens[num_tokens - 1] == CT_PAREN_OPEN))
+ {
+ handle_double_angle_close(pc);
+ }
+ else if (--num_tokens <= 0)
+ {
+ break;
+ }
+ else if (tokens[num_tokens] != CT_ANGLE_OPEN)
+ {
+ break; // unbalanced parentheses
+ }
+ }
+ else if ( in_if
+ && ( chunk_is_token(pc, CT_BOOL)
+ || chunk_is_token(pc, CT_COMPARE)))
+ {
+ break;
+ }
+ else if (chunk_is_token(pc, CT_BRACE_OPEN))
+ {
+ if ( !pc->flags.test(PCF_IN_DECLTYPE)
+ || !detect_cpp_braced_init_list(pc->prev, pc))
+ {
+ break;
+ }
+ auto brace_open = pc->GetNextNcNnl();
+ auto brace_close = chunk_skip_to_match(brace_open);
+
+ set_chunk_parent(brace_open, CT_BRACED_INIT_LIST);
+ set_chunk_parent(brace_close, CT_BRACED_INIT_LIST);
+ }
+ else if ( chunk_is_token(pc, CT_BRACE_CLOSE)
+ && get_chunk_parent_type(pc) != CT_BRACED_INIT_LIST
+ && !pc->flags.test(PCF_IN_DECLTYPE))
+ {
+ break;
+ }
+ else if (chunk_is_token(pc, CT_SEMICOLON))
+ {
+ break;
+ }
+ else if (chunk_is_token(pc, CT_PAREN_OPEN))
+ {
+ if (num_tokens >= max_token_count - 1)
+ {
+ break;
+ }
+ tokens[num_tokens] = CT_PAREN_OPEN;
+ num_tokens++;
+ }
+ else if ( chunk_is_token(pc, CT_QUESTION) // Issue #2949
+ && language_is_set(LANG_CPP))
+ {
+ break;
+ }
+ else if (chunk_is_token(pc, CT_PAREN_CLOSE))
+ {
+ if (num_tokens == 0)
+ {
+ fprintf(stderr, "%s(%d): num_tokens is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ num_tokens--;
+
+ if (tokens[num_tokens] != CT_PAREN_OPEN)
+ {
+ break; // unbalanced parentheses
+ }
+ }
+ }
+
+ end = pc;
+ }
+
+ if (chunk_is_token(end, CT_ANGLE_CLOSE))
+ {
+ pc = end->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( pc->IsNullChunk()
+ || pc->type != CT_NUMBER)
+ {
+ LOG_FMT(LTEMPL, "%s(%d): Template detected\n", __func__, __LINE__);
+ LOG_FMT(LTEMPL, "%s(%d): from orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, start->orig_line, start->orig_col);
+ LOG_FMT(LTEMPL, "%s(%d): to orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, end->orig_line, end->orig_col);
+ set_chunk_parent(start, CT_TEMPLATE);
+
+ check_template_args(start, end);
+
+ set_chunk_parent(end, CT_TEMPLATE);
+ chunk_flags_set(end, PCF_IN_TEMPLATE);
+ return;
+ }
+ }
+ LOG_FMT(LTEMPL, "%s(%d): - Not a template: end = %s\n",
+ __func__, __LINE__, (end != nullptr) ? get_token_name(end->type) : "<null>");
+ set_chunk_type(start, CT_COMPARE);
+} // check_template
+
+
+static void check_template_arg(Chunk *start, Chunk *end)
+{
+ LOG_FMT(LTEMPL, "%s(%d): Template argument detected\n", __func__, __LINE__);
+ LOG_FMT(LTEMPL, "%s(%d): from orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, start->orig_line, start->orig_col);
+ LOG_FMT(LTEMPL, "%s(%d): to orig_line %zu, orig_col %zu\n",
+ __func__, __LINE__, end->orig_line, end->orig_col);
+
+ // Issue #1127
+ // MyFoo<mySize * 2> foo1;
+ // MyFoo<2*mySize * 2> foo1;
+ // Issue #1346
+ // use it as ONE line:
+ // typename std::enable_if<!std::is_void<T>::value,
+ // QVector<T> >::type dummy(const std::function<T*(const S&)>&
+ // pFunc, const QVector<S>& pItems)
+ // we need two runs
+ // 1. run to test if expression is numeric
+ bool expressionIsNumeric = false;
+ Chunk *pc = start;
+
+ while (pc != end)
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+ // a test "if (next == nullptr)" is not necessary
+ chunk_flags_set(pc, PCF_IN_TEMPLATE);
+
+ if ( chunk_is_token(pc, CT_DECLTYPE)
+ || chunk_is_token(pc, CT_SIZEOF))
+ {
+ expressionIsNumeric = true;
+ break;
+ }
+
+ if (next->type != CT_PAREN_OPEN)
+ {
+ if ( chunk_is_token(pc, CT_NUMBER)
+ || chunk_is_token(pc, CT_ARITH)
+ || chunk_is_token(pc, CT_SHIFT))
+ {
+ expressionIsNumeric = true;
+ break;
+ }
+ }
+ pc = next;
+ }
+ LOG_FMT(LTEMPL, "%s(%d): expressionIsNumeric is %s\n",
+ __func__, __LINE__, expressionIsNumeric ? "TRUE" : "FALSE");
+
+ // 2. run to do the work
+ if (!expressionIsNumeric)
+ {
+ pc = start;
+
+ while (pc != end)
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+ // a test "if (next == nullptr)" is not necessary
+ chunk_flags_set(pc, PCF_IN_TEMPLATE);
+
+ Chunk *prev = pc->GetPrevNcNnl(E_Scope::PREPROC);
+ Chunk *prev2 = prev->GetPrevNcNnl(E_Scope::PREPROC);
+
+ if ( chunk_is_token(prev, CT_ELLIPSIS) // Issue #3309
+ && chunk_is_token(prev2, CT_TYPENAME))
+ {
+ set_chunk_type(pc, CT_PARAMETER_PACK);
+ }
+ else
+ {
+ make_type(pc);
+ }
+ pc = next;
+ }
+ }
+} // check_template_arg
+
+
+static void check_template_args(Chunk *start, Chunk *end)
+{
+ std::vector<E_Token> tokens;
+
+ // Scan for commas
+ Chunk *pc;
+
+ for (pc = start->GetNextNcNnl(E_Scope::PREPROC);
+ pc->IsNotNullChunk() && pc != end;
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ switch (pc->type)
+ {
+ case CT_COMMA:
+
+ if (tokens.empty())
+ {
+ // Check current argument
+ check_template_args(start, pc);
+ start = pc;
+ }
+ break;
+
+ case CT_ANGLE_OPEN:
+ case CT_PAREN_OPEN:
+ tokens.push_back(pc->type);
+ break;
+
+ case CT_ANGLE_CLOSE:
+
+ if ( !tokens.empty()
+ && tokens.back() == CT_ANGLE_OPEN)
+ {
+ tokens.pop_back();
+ }
+ break;
+
+ case CT_PAREN_CLOSE:
+
+ if ( !tokens.empty()
+ && tokens.back() == CT_PAREN_OPEN)
+ {
+ tokens.pop_back();
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Check whatever is left
+ check_template_arg(start, end);
+} // check_template_args
+
+
+static void cleanup_objc_property(Chunk *start)
+{
+ assert(chunk_is_token(start, CT_OC_PROPERTY));
+
+ Chunk *open_paren = start->GetNextType(CT_PAREN_OPEN, start->level);
+
+ if (open_paren->IsNullChunk())
+ {
+ LOG_FMT(LTEMPL, "%s(%d): Property is not followed by openning paren\n", __func__, __LINE__);
+ return;
+ }
+ set_chunk_parent(open_paren, start->type);
+
+ Chunk *tmp = start->GetNextType(CT_PAREN_CLOSE, start->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_parent(tmp, start->type);
+ tmp = tmp->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);
+
+ tmp = tmp->GetNextType(CT_SEMICOLON, start->level);
+
+ if (tmp->IsNotNullChunk())
+ {
+ set_chunk_parent(tmp, start->type);
+ }
+ }
+ }
+ mark_selectors_in_property_with_open_paren(open_paren);
+ mark_attributes_in_property_with_open_paren(open_paren);
+}
+
+
+static void mark_selectors_in_property_with_open_paren(Chunk *open_paren)
+{
+ assert(chunk_is_token(open_paren, CT_PAREN_OPEN));
+
+ Chunk *tmp = open_paren;
+
+ while ( tmp != nullptr
+ && tmp->type != CT_PAREN_CLOSE)
+ {
+ if ( chunk_is_token(tmp, CT_WORD)
+ && ( chunk_is_str(tmp, "setter")
+ || chunk_is_str(tmp, "getter")))
+ {
+ tmp = tmp->next;
+
+ while ( tmp != nullptr
+ && tmp->type != CT_COMMA
+ && tmp->type != CT_PAREN_CLOSE)
+ {
+ if ( chunk_is_token(tmp, CT_WORD)
+ || chunk_is_str(tmp, ":"))
+ {
+ set_chunk_type(tmp, CT_OC_SEL_NAME);
+ }
+ tmp = tmp->next;
+ }
+ }
+ else
+ {
+ tmp = tmp->next;
+ }
+ }
+}
+
+
+static void mark_attributes_in_property_with_open_paren(Chunk *open_paren)
+{
+ assert(chunk_is_token(open_paren, CT_PAREN_OPEN));
+
+ Chunk *tmp = open_paren;
+
+ while ( tmp != nullptr
+ && tmp->type != CT_PAREN_CLOSE)
+ {
+ if ( ( chunk_is_token(tmp, CT_COMMA)
+ || chunk_is_token(tmp, CT_PAREN_OPEN))
+ && ( chunk_is_token(tmp->next, CT_WORD)
+ || chunk_is_token(tmp->next, CT_TYPE)))
+ {
+ set_chunk_type(tmp->next, CT_OC_PROPERTY_ATTR);
+ }
+ tmp = tmp->next;
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.h
new file mode 100644
index 00000000..1a75cde9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/tokenize_cleanup.h
@@ -0,0 +1,31 @@
+/**
+ * @file tokenize_cleanup.h
+ * prototypes for tokenize_cleanup.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef TOKENIZ_CLEANUP_H_INCLUDED
+#define TOKENIZ_CLEANUP_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * @brief clean up tokens
+ *
+ * Change certain token types based on simple sequence.
+ * Example: change '[' + ']' to '[]'
+ * Note that level info is not yet available, so it is OK to do all
+ * processing that doesn't need to know level info. (that's very little!)
+ */
+void tokenize_cleanup(void);
+
+
+void tokenize_trailing_return_types(void);
+
+
+void split_off_angle_close(Chunk *pc);
+
+
+#endif /* TOKENIZ_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_ctype.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_ctype.h
new file mode 100644
index 00000000..50b7a6f3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_ctype.h
@@ -0,0 +1,106 @@
+/**
+ * @file unc_ctype.h
+ * The ctype function are only required to handle values 0-255 and EOF.
+ * A char is sign-extended when cast to an int.
+ * With some C libraries, these values cause a crash.
+ * These wrappers will properly handle all char values.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef UNC_CTYPE_H_INCLUDED
+#define UNC_CTYPE_H_INCLUDED
+
+#include "options.h"
+
+#include <cctype> // to get std::tolower
+
+// TODO: better avoid inline and move implementation to cpp file
+
+
+//! Test anything EOF (-1) to 0-255
+static inline int unc_fix_ctype(int ch)
+{
+ if ( ch >= -1
+ && ch <= 255)
+ {
+ return(ch);
+ }
+ return(0); // Issue #3025
+}
+
+
+//! check if a character is a space
+static inline int unc_isspace(int ch)
+{
+ if ( (ch == 12) // Issue #2386
+ && uncrustify::options::use_form_feed_no_more_as_whitespace_character())
+ {
+ return(0);
+ }
+ else
+ {
+ return(isspace(unc_fix_ctype(ch)));
+ }
+}
+
+
+//! check if a character is a printing character
+static inline int unc_isprint(int ch)
+{
+ return(isprint(unc_fix_ctype(ch)));
+}
+
+
+//! check if a character is an alphabetic character (a letter).
+static inline int unc_isalpha(int ch)
+{
+ return(isalpha(unc_fix_ctype(ch)));
+}
+
+
+//! check if a character is an alphanumeric character.
+static inline int unc_isalnum(int ch)
+{
+ return(isalnum(unc_fix_ctype(ch)));
+}
+
+
+//! convert a character to upper case
+static inline int unc_toupper(int ch)
+{
+ return(toupper(unc_fix_ctype(ch)));
+}
+
+
+//! convert a character to lower case
+static inline int unc_tolower(int ch)
+{
+ return(tolower(unc_fix_ctype(ch)));
+}
+
+
+//! check if a character is a hexadecimal digit
+static inline int unc_isxdigit(int ch)
+{
+ return(isxdigit(unc_fix_ctype(ch)));
+}
+
+
+//! check if a character is a decimal digit
+static inline int unc_isdigit(int ch)
+{
+ return(isdigit(unc_fix_ctype(ch)));
+}
+
+
+//! check if a character is upper case
+static inline int unc_isupper(int ch)
+{
+ return( isalpha(unc_fix_ctype(ch))
+ && (unc_toupper(unc_fix_ctype(ch)) == ch));
+}
+
+
+#endif /* UNC_CTYPE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.cpp
new file mode 100644
index 00000000..1f96a67c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.cpp
@@ -0,0 +1,759 @@
+/**
+ * @file unc_text.cpp
+ * A simple class that handles the chunk text.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "unc_text.h"
+
+#include "unc_ctype.h"
+#include "unicode.h" // encode_utf8()
+
+#include <algorithm>
+#include <stdexcept>
+
+
+using namespace std;
+
+
+static constexpr const int_fast8_t UTF8_BLOCKS = 6; // 6 -> max utf8 blocks per char
+
+
+static size_t fix_len_idx(size_t size, size_t idx, size_t len);
+
+//! converts \n and \r chars are into NL and CR UTF8 symbols before encode_utf8 is called
+static void toLogTextUtf8(int c, unc_text::log_type &container);
+
+/**
+ * calculates the size a 'log_type' container needs to have in order to take
+ * in values of a 'unc_text::value_type' up to idx
+ * (without \0, with symbols for the converted \n and \r chars)
+ *
+ * throws if char is greater than 0x7fffffff
+ */
+static int getLogTextUtf8Len(unc_text::value_type &c0, size_t end);
+
+static int getLogTextUtf8Len(unc_text::value_type &c0, size_t start, size_t end);
+
+
+static int getLogTextUtf8Len(unc_text::value_type &c0, size_t start, size_t end)
+{
+ size_t c1_idx = 0;
+
+ for (size_t i = start; i < end; ++i)
+ {
+ auto ch = c0[i];
+
+ if (ch == '\n')
+ {
+ ch = 0x2424; // NL symbol
+ }
+ else if (ch == '\r')
+ {
+ ch = 0x240d; // CR symbol
+ }
+
+ if (ch < 0x80) // 1-byte sequence
+ {
+ c1_idx += 1;
+ }
+ else if (ch < 0x0800) // 2-byte sequence
+ {
+ c1_idx += 2;
+ }
+ else if (ch < 0x10000) // 3-byte sequence
+ {
+ c1_idx += 3;
+ }
+ else if (ch < 0x200000) // 4-byte sequence
+ {
+ c1_idx += 4;
+ }
+ else if (ch < 0x4000000) // 5-byte sequence
+ {
+ c1_idx += 5;
+ }
+ else if (ch <= 0x7fffffff) // 6-byte sequence
+ {
+ c1_idx += 6;
+ }
+ else
+ {
+ throw out_of_range(string(__func__) + ":" + to_string(__LINE__)
+ + " - ch value too big, can't convert to utf8");
+ }
+ }
+
+ return(c1_idx);
+} // getLogTextUTF8Len
+
+
+static int getLogTextUtf8Len(unc_text::value_type &c0, size_t end)
+{
+ return(getLogTextUtf8Len(c0, 0, end));
+}
+
+
+static void toLogTextUtf8(int c, unc_text::log_type &container)
+{
+ if (c == '\n')
+ {
+ c = 0x2424; // NL symbol
+ }
+ else if (c == '\r')
+ {
+ c = 0x240d; // CR symbol
+ }
+ encode_utf8(c, container);
+}
+
+
+static size_t fix_len_idx(size_t size, size_t idx, size_t len)
+{
+ if (idx >= size)
+ {
+ return(0);
+ }
+ const size_t left = size - idx;
+
+ return((len > left) ? left : len);
+}
+
+
+unc_text::unc_text()
+{
+ m_logtext = log_type{ '\0' };
+}
+
+
+unc_text::unc_text(const unc_text &ref)
+{
+ set(ref);
+}
+
+
+unc_text::unc_text(const unc_text &ref, size_t idx, size_t len)
+{
+ set(ref, idx, len);
+}
+
+
+unc_text::unc_text(const char *ascii_text)
+{
+ set(ascii_text);
+}
+
+
+unc_text::unc_text(const std::string &ascii_text)
+{
+ set(ascii_text);
+}
+
+
+unc_text::unc_text(const value_type &data, size_t idx, size_t len)
+{
+ set(data, idx, len);
+}
+
+
+size_t unc_text::size() const
+{
+ return(m_chars.size());
+}
+
+
+unc_text &unc_text::operator=(int ch)
+{
+ set(ch);
+ return(*this);
+}
+
+
+unc_text &unc_text::operator=(const unc_text &ref)
+{
+ set(ref);
+ return(*this);
+}
+
+
+unc_text &unc_text::operator=(const std::string &ascii_text)
+{
+ set(ascii_text);
+ return(*this);
+}
+
+
+unc_text &unc_text::operator=(const char *ascii_text)
+{
+ set(ascii_text);
+ return(*this);
+}
+
+
+unc_text &unc_text::operator+=(int ch)
+{
+ append(ch);
+ return(*this);
+}
+
+
+unc_text &unc_text::operator+=(const unc_text &ref)
+{
+ append(ref);
+ return(*this);
+}
+
+
+unc_text &unc_text::operator+=(const std::string &ascii_text)
+{
+ append(ascii_text);
+ return(*this);
+}
+
+
+unc_text &unc_text::operator+=(const char *ascii_text)
+{
+ append(ascii_text);
+ return(*this);
+}
+
+
+const unc_text::value_type &unc_text::get() const
+{
+ return(m_chars);
+}
+
+
+int unc_text::operator[](size_t idx) const
+{
+ return((idx < m_chars.size()) ? m_chars[idx] : 0);
+}
+
+
+const int &unc_text::at(size_t idx) const
+{
+ return(m_chars.at(idx));
+}
+
+
+const int &unc_text::back() const
+{
+ return(m_chars.back());
+}
+
+
+void unc_text::push_back(int ch)
+{
+ append(ch);
+}
+
+
+void unc_text::pop_back()
+{
+ if (size() == 0)
+ {
+ return;
+ }
+ m_chars.pop_back();
+ update_logtext();
+}
+
+
+void unc_text::pop_front()
+{
+ if (size() == 0)
+ {
+ return;
+ }
+ m_chars.pop_front();
+ update_logtext();
+}
+
+
+void unc_text::update_logtext()
+{
+ // make a pessimistic guess at the size
+ m_logtext.clear();
+ m_logtext.reserve(m_chars.size() * 3);
+
+ for (int m_char : m_chars)
+ {
+ toLogTextUtf8(m_char, m_logtext);
+ }
+
+ m_logtext.push_back(0);
+}
+
+
+int unc_text::compare(const unc_text &ref1, const unc_text &ref2, size_t len, bool tcare)
+{
+ const size_t len1 = ref1.size();
+ const size_t len2 = ref2.size();
+ const auto max_idx = std::min({ len, len1, len2 });
+ size_t idx = 0;
+
+ for ( ; idx < max_idx; idx++)
+ {
+ // exactly the same character ?
+ if (ref1.m_chars[idx] == ref2.m_chars[idx])
+ {
+ continue;
+ }
+ int diff; // Issue #2091
+
+ if (tcare)
+ {
+ diff = ref1.m_chars[idx] - ref2.m_chars[idx];
+ }
+ else
+ {
+ diff = unc_tolower(ref1.m_chars[idx]) - unc_tolower(ref2.m_chars[idx]);
+ }
+
+ if (diff == 0)
+ {
+ /*
+ * if we're comparing the same character but in different case
+ * we want to favor lower case before upper case (e.g. a before A)
+ * so the order is the reverse of ASCII order (we negate).
+ */
+ return(-(ref1.m_chars[idx] - ref2.m_chars[idx]));
+ }
+ // return the case-insensitive diff to sort alphabetically
+ return(diff);
+ }
+
+ if (idx == len)
+ {
+ return(0);
+ }
+ // underflow save: return(len1 - len2);
+ return((len1 > len2) ? (len1 - len2) : -static_cast<int>(len2 - len1));
+} // unc_text::compare
+
+
+bool unc_text::equals(const unc_text &ref) const
+{
+ const size_t len = size();
+
+ if (ref.size() != len)
+ {
+ return(false);
+ }
+
+ for (size_t idx = 0; idx < len; idx++)
+ {
+ if (m_chars[idx] != ref.m_chars[idx])
+ {
+ return(false);
+ }
+ }
+
+ return(true);
+}
+
+
+const char *unc_text::c_str() const
+{
+ return(reinterpret_cast<const char *>(&m_logtext[0]));
+}
+
+
+void unc_text::set(int ch)
+{
+ m_logtext.clear();
+ toLogTextUtf8(ch, m_logtext);
+ m_logtext.push_back('\0');
+
+
+ m_chars.clear();
+ m_chars.push_back(ch);
+}
+
+
+void unc_text::set(const unc_text &ref)
+{
+ m_chars = ref.m_chars;
+ m_logtext = ref.m_logtext;
+}
+
+
+void unc_text::set(const unc_text &ref, size_t idx, size_t len)
+{
+ const auto ref_size = ref.size();
+
+ if (len == ref_size)
+ {
+ m_chars = ref.m_chars;
+ update_logtext();
+ return;
+ }
+ m_chars.resize(len);
+
+ len = fix_len_idx(ref_size, idx, len);
+
+ for (size_t di = 0;
+ len > 0;
+ di++, idx++, len--)
+ {
+ m_chars[di] = ref.m_chars[idx];
+ }
+
+ update_logtext();
+}
+
+
+void unc_text::set(const string &ascii_text)
+{
+ const size_t len = ascii_text.size();
+
+ m_chars.resize(len);
+
+ for (size_t idx = 0; idx < len; idx++)
+ {
+ m_chars[idx] = ascii_text[idx];
+ }
+
+ update_logtext();
+}
+
+
+void unc_text::set(const char *ascii_text)
+{
+ const size_t len = strlen(ascii_text);
+
+ m_chars.resize(len);
+
+ for (size_t idx = 0; idx < len; idx++)
+ {
+ m_chars[idx] = *ascii_text++;
+ }
+
+ update_logtext();
+}
+
+
+void unc_text::set(const value_type &data, size_t idx, size_t len)
+{
+ m_chars.resize(len);
+
+ len = fix_len_idx(data.size(), idx, len);
+
+ for (size_t di = 0;
+ len > 0;
+ di++, idx++, len--)
+ {
+ m_chars[di] = data[idx];
+ }
+
+ update_logtext();
+}
+
+
+void unc_text::resize(size_t new_size)
+{
+ if (size() == new_size)
+ {
+ return;
+ }
+ const auto log_new_size = getLogTextUtf8Len(m_chars, new_size);
+
+ m_logtext.resize(log_new_size + 1); // one extra for \0
+ m_logtext[log_new_size] = '\0';
+
+
+ m_chars.resize(new_size);
+}
+
+
+void unc_text::clear()
+{
+ m_logtext.clear();
+ m_logtext.push_back('\0');
+
+
+ m_chars.clear();
+}
+
+
+void unc_text::insert(size_t idx, int ch)
+{
+ if (idx >= m_chars.size())
+ {
+ throw out_of_range(string(__func__) + ":" + to_string(__LINE__)
+ + " - idx >= m_chars.size()");
+ }
+ log_type utf8converted;
+
+ utf8converted.reserve(UTF8_BLOCKS);
+ toLogTextUtf8(ch, utf8converted);
+
+ const auto utf8_idx = getLogTextUtf8Len(m_chars, idx);
+
+ m_logtext.pop_back(); // remove '\0'
+ m_logtext.insert(std::next(std::begin(m_logtext), utf8_idx),
+ std::begin(utf8converted), std::end(utf8converted));
+ m_logtext.push_back('\0');
+
+
+ m_chars.insert(std::next(std::begin(m_chars), idx), ch);
+}
+
+
+void unc_text::insert(size_t idx, const unc_text &ref)
+{
+ if (ref.size() == 0)
+ {
+ return;
+ }
+
+ if (idx >= m_chars.size())
+ {
+ throw out_of_range(string(__func__) + ":" + to_string(__LINE__)
+ + " - idx >= m_chars.size()");
+ }
+ const auto utf8_idx = getLogTextUtf8Len(m_chars, idx);
+
+ // (A+B) remove \0 from both containers, add back a single at the end
+ m_logtext.pop_back(); // A
+ m_logtext.insert(std::next(std::begin(m_logtext), utf8_idx),
+ std::begin(ref.m_logtext),
+ std::prev(std::end(ref.m_logtext))); // B
+ m_logtext.push_back('\0');
+
+
+ m_chars.insert(std::next(std::begin(m_chars), idx),
+ std::begin(ref.m_chars), std::end(ref.m_chars));
+}
+
+
+void unc_text::append(int ch)
+{
+ m_logtext.pop_back();
+
+ if ( ch < 0x80
+ && ch != '\n'
+ && ch != '\r')
+ {
+ m_logtext.push_back(ch);
+ }
+ else
+ {
+ log_type utf8converted;
+ utf8converted.reserve(UTF8_BLOCKS);
+ toLogTextUtf8(ch, utf8converted);
+
+ m_logtext.insert(std::end(m_logtext),
+ std::begin(utf8converted), std::end(utf8converted));
+ }
+ m_logtext.push_back('\0');
+
+
+ m_chars.push_back(ch);
+}
+
+
+void unc_text::append(const unc_text &ref)
+{
+ if (ref.size() == 0)
+ {
+ return;
+ }
+ m_logtext.pop_back();
+ m_logtext.insert(std::end(m_logtext),
+ std::begin(ref.m_logtext), std::end(ref.m_logtext));
+
+ m_chars.insert(m_chars.end(), ref.m_chars.begin(), ref.m_chars.end());
+}
+
+
+void unc_text::append(const string &ascii_text)
+{
+ unc_text tmp(ascii_text);
+
+ append(tmp);
+}
+
+
+void unc_text::append(const char *ascii_text)
+{
+ unc_text tmp(ascii_text);
+
+ append(tmp);
+}
+
+
+void unc_text::append(const value_type &data, size_t idx, size_t len)
+{
+ unc_text tmp(data, idx, len);
+
+ append(tmp);
+}
+
+
+bool unc_text::startswith(const char *text, size_t idx) const
+{
+ const auto orig_idx = idx;
+
+ for ( ;
+ ( idx < size()
+ && *text);
+ idx++, text++)
+ {
+ if (*text != m_chars[idx])
+ {
+ return(false);
+ }
+ }
+
+ return( idx != orig_idx
+ && (*text == 0));
+}
+
+
+bool unc_text::startswith(const unc_text &text, size_t idx) const
+{
+ size_t si = 0;
+ const auto orig_idx = idx;
+
+ for ( ;
+ ( idx < size()
+ && si < text.size());
+ idx++, si++)
+ {
+ if (text.m_chars[si] != m_chars[idx])
+ {
+ return(false);
+ }
+ }
+
+ return( idx != orig_idx
+ && (si == text.size()));
+}
+
+
+int unc_text::find(const char *search_txt, size_t start_idx) const
+{
+ const size_t t_len = strlen(search_txt); // the length of 'text' we are looking for
+ const size_t s_len = size(); // the length of the string we are looking in
+
+ if ( s_len < t_len // search_txt longer than the string we are looking in
+ || start_idx + t_len - 1 >= s_len) // starting position to high to find search_txt
+ {
+ return(-1);
+ }
+ const size_t end_idx = s_len - t_len;
+
+ for (size_t idx = start_idx; idx <= end_idx; idx++)
+ {
+ bool match = true;
+
+ for (size_t ii = 0; ii < t_len; ii++)
+ {
+ if (m_chars[idx + ii] != search_txt[ii])
+ {
+ match = false;
+ break;
+ }
+ }
+
+ if (match) // 'text' found at position 'idx'
+ {
+ return(idx);
+ }
+ }
+
+ return(-1); // 'text' not found
+}
+
+
+int unc_text::rfind(const char *search_txt, size_t start_idx) const
+{
+ const size_t t_len = strlen(search_txt); // the length of 'text' we are looking for
+ const size_t s_len = size(); // the length of the string we are looking in
+
+ if ( s_len < t_len // search_txt longer than the string we are looking in
+ || start_idx < t_len - 1) // starting position to low to find search_txt
+ {
+ return(-1);
+ }
+ const size_t end_idx = s_len - t_len;
+
+ if (start_idx > end_idx)
+ {
+ start_idx = end_idx;
+ }
+
+ for (auto idx = static_cast<int>(start_idx); idx >= 0; idx--)
+ {
+ bool match = true;
+
+ for (size_t ii = 0; ii < t_len; ii++)
+ {
+ if (m_chars[idx + ii] != search_txt[ii])
+ {
+ match = false;
+ break;
+ }
+ }
+
+ if (match)
+ {
+ return(idx);
+ }
+ }
+
+ return(-1);
+}
+
+
+void unc_text::erase(size_t start_idx, size_t len)
+{
+ if (len == 0)
+ {
+ return;
+ }
+ const size_t end_idx = start_idx + len - 1;
+
+ if (end_idx >= m_chars.size())
+ {
+ throw out_of_range(string(__func__) + ":" + to_string(__LINE__)
+ + " - idx + len >= m_chars.size()");
+ }
+ const auto pos_s = getLogTextUtf8Len(m_chars, start_idx);
+ const auto pos_e = pos_s + getLogTextUtf8Len(m_chars, start_idx, end_idx);
+
+ m_logtext.pop_back();
+ m_logtext.erase(std::next(std::begin(m_logtext), pos_s),
+ std::next(std::begin(m_logtext), pos_e + 1));
+ m_logtext.push_back('\0');
+
+
+ m_chars.erase(std::next(std::begin(m_chars), start_idx),
+ std::next(std::begin(m_chars), end_idx + 1));
+}
+
+
+int unc_text::replace(const char *search_text, const unc_text &replace_text)
+{
+ const size_t s_len = strlen(search_text);
+ const size_t r_len = replace_text.size();
+
+ int rcnt = 0;
+ int fidx = find(search_text);
+
+ while (fidx >= 0)
+ {
+ rcnt++;
+ erase(static_cast<size_t>(fidx), s_len);
+
+ (static_cast<size_t>(fidx) >= m_chars.size())
+ ? append(replace_text)
+ : insert(static_cast<size_t>(fidx), replace_text);
+
+ fidx = find(search_text, static_cast<size_t>(fidx) + r_len);
+ }
+ return(rcnt);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.h
new file mode 100644
index 00000000..dd678f16
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_text.h
@@ -0,0 +1,196 @@
+/**
+ * @file unc_text.h
+ * A simple class that handles the chunk text.
+ * At the start of processing, the entire file is decoded into a std::vector of ints.
+ * This class is intended to hold sections of that large std::vector.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef UNC_TEXT_H_INCLUDED
+#define UNC_TEXT_H_INCLUDED
+
+#include "base_types.h"
+
+#include <deque>
+#include <string>
+#include <vector>
+
+
+/**
+ * abbreviations used:
+ * - unc_text - uncrustify text
+ */
+
+class unc_text
+{
+public:
+ typedef std::deque<int> value_type; // double encoded list of int values
+ typedef std::vector<UINT8> log_type;
+
+
+ unc_text();
+
+ unc_text(const unc_text &ref);
+
+ unc_text(const unc_text &ref, size_t idx, size_t len = 0);
+
+ unc_text(const char *ascii_text);
+
+ unc_text(const std::string &ascii_text);
+
+ unc_text(const value_type &data, size_t idx = 0, size_t len = 0);
+
+
+ ~unc_text() = default;
+
+
+ void resize(size_t new_size);
+
+
+ void clear();
+
+
+ //! grab the number of characters
+ size_t size() const;
+
+
+ void set(int ch);
+
+ void set(const unc_text &ref);
+
+ void set(const unc_text &ref, size_t idx, size_t len = 0);
+
+ void set(const std::string &ascii_text);
+
+ void set(const char *ascii_text);
+
+ void set(const value_type &data, size_t idx = 0, size_t len = 0);
+
+
+ unc_text &operator=(int ch);
+
+ unc_text &operator=(const unc_text &ref);
+
+ unc_text &operator=(const std::string &ascii_text);
+
+ unc_text &operator=(const char *ascii_text);
+
+
+ void insert(size_t idx, int ch);
+
+ void insert(size_t idx, const unc_text &ref);
+
+
+ void erase(size_t idx, size_t len = 1);
+
+
+ //! Add a unc_text character to an unc_text
+ void append(int ch);
+
+ void append(const unc_text &ref);
+
+ //! Add a string to an unc_text
+ void append(const std::string &ascii_text);
+
+ /**
+ * Add a variable length string to an unc_text.
+ * The variable length string format is similar as for printf
+ *
+ * @note the overall length of the string must not exceed 256 characters
+ *
+ * @param ascii_text a variable length string
+ */
+ void append(const char *ascii_text);
+
+ void append(const value_type &data, size_t idx = 0, size_t len = 0);
+
+
+ unc_text &operator+=(int ch);
+
+ unc_text &operator+=(const unc_text &ref);
+
+ unc_text &operator+=(const std::string &ascii_text);
+
+ unc_text &operator+=(const char *ascii_text);
+
+
+ //! Returns the UTF-8 string for logging
+ const char *c_str() const;
+
+
+ /**
+ * compares the content of two unc_text instances
+ *
+ * @param ref1 first instance to compare
+ * @param ref2 second instance to compare
+ * @param len number of character to compare
+ * @param tcare take care of case (lower case/ upper case) Issue #2091
+ *
+ * @retval == 0 both text elements are equal
+ * @retval > 0
+ * @retval < 0
+ */
+ static int compare(const unc_text &ref1, const unc_text &ref2, size_t len = 0, bool tcare = false);
+
+
+ bool equals(const unc_text &ref) const;
+
+
+ //! grab the data as a series of ints for outputting to a file
+ const value_type &get() const;
+
+
+ int operator[](size_t idx) const;
+
+
+ // throws an exception if out of bounds
+ const int &at(size_t idx) const;
+
+
+ //! returns the last element of the character list
+ const int &back() const;
+
+
+ void push_back(int ch);
+
+
+ void pop_back();
+
+
+ void pop_front();
+
+
+ bool startswith(const unc_text &text, size_t idx = 0) const;
+
+ bool startswith(const char *text, size_t idx = 0) const;
+
+
+ /**
+ * look for 'text', beginning with position 'sidx'
+ *
+ * @param text text to search for
+ * @param idx position to start search
+ *
+ * @return == -1 if not found
+ * @return >= 0 the position
+ */
+ int find(const char *text, size_t idx = 0) const;
+
+
+ int rfind(const char *text, size_t idx = 0) const;
+
+
+ int replace(const char *oldtext, const unc_text &newtext);
+
+
+protected:
+ void update_logtext();
+
+ value_type m_chars; //! this contains the non-encoded 31-bit chars
+ log_type m_logtext; //! logging text, utf8 encoded - updated in c_str()
+};
+
+
+#endif /* UNC_TEXT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.cpp
new file mode 100644
index 00000000..20aa4b99
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.cpp
@@ -0,0 +1,496 @@
+/**
+ * @file unc_tools.cpp
+ * This file contains lot of tools for debugging
+ *
+ * @author Guy Maurel
+ * October 2015- 2021
+ * @license GPL v2+
+ */
+
+#include "unc_tools.h"
+
+#include "args.h"
+#include "output.h"
+
+
+/*
+ * the test suite Coveralls: https://coveralls.io
+ * will complains because these functions are only
+ * used at developement time.
+ * Don't worry about unsed lines for the functions:
+ * prot_the_line
+ * prot_the_source
+ * examine_Data
+ * dump_out
+ * dump_in
+ */
+
+static size_t counter = 0;
+static size_t tokenCounter;
+
+
+/* protocol of the line
+ * examples:
+ * prot_the_line(__func__, __LINE__, pc->orig_line, 0);
+ * prot_the_line(__func__, __LINE__, 0, 0);
+ * prot_the_line(__func__, __LINE__, 6, 5);
+ * prot_the_source(__LINE__);
+ * log_pcf_flags(LSYS, pc->flags);
+ *
+ * if actual_line is zero, use the option debug_line_number_to_protocol.
+ * if the value is zero, don't make any protocol and return.
+ *
+ * if partNumber is zero, all the tokens of the line are shown,
+ * if partNumber is NOT zero, only the token with this partNumber is shown.
+ *
+ * prot_the_line_pc(pc_sub, __func__, __LINE__, 6, 5);
+ * to get a protocol of a sub branch, which begins with pc_sub
+ */
+void prot_the_line(const char *func_name, int theLine, unsigned int actual_line, size_t partNumber)
+{
+ prot_the_line_pc(Chunk::GetHead(), func_name, theLine, actual_line, partNumber);
+}
+
+
+void prot_the_line_pc(Chunk *pc_sub, const char *func_name, int theLine, unsigned int actual_line, size_t partNumber)
+{
+ if (actual_line == 0)
+ {
+ // use the option debug_line_number_to_protocol.
+ actual_line = options::debug_line_number_to_protocol();
+
+ if (actual_line == 0)
+ {
+ // don't make any protocol.
+ return;
+ }
+ }
+ counter++;
+ tokenCounter = 0;
+ LOG_FMT(LGUY, "Prot_the_line:(%s:%d)(%zu)\n", func_name, theLine, counter);
+
+ for (Chunk *pc = pc_sub; pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->orig_line == actual_line)
+ {
+ tokenCounter++;
+
+ if ( partNumber == 0
+ || partNumber == tokenCounter)
+ {
+ LOG_FMT(LGUY, " orig_line is %d, (%zu) ", actual_line, tokenCounter);
+
+ if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<VBRACE_OPEN>, ");
+ }
+ else if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "<NL>(nl_count is %zu), ", pc->nl_count);
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_CLOSE>, ");
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_OPEN>, ");
+ }
+ else if (chunk_is_token(pc, CT_SPACE))
+ {
+ LOG_FMT(LGUY, "<CT_SPACE>, ");
+ }
+ else if (chunk_is_token(pc, CT_IGNORED))
+ {
+ LOG_FMT(LGUY, "<IGNORED> ");
+ }
+ else
+ {
+ LOG_FMT(LGUY, "Text() '%s', ", pc->Text());
+ }
+ LOG_FMT(LGUY, " column is %zu, pp_level is %zu, type is %s, parent_type is %s, orig_col is %zu,",
+ pc->column, pc->pp_level, get_token_name(pc->type),
+ get_token_name(get_chunk_parent_type(pc)), pc->orig_col);
+
+ if (chunk_is_token(pc, CT_IGNORED))
+ {
+ LOG_FMT(LGUY, "\n");
+ }
+ else
+ {
+ LOG_FMT(LGUY, " pc->flags: ");
+ log_pcf_flags(LGUY, pc->flags);
+ }
+
+ if (pc->tracking != nullptr)
+ {
+ LOG_FMT(LGUY, " Tracking info are: \n");
+ LOG_FMT(LGUY, " number of track(s) %zu\n", pc->tracking->size());
+
+ for (size_t track = 0; track < pc->tracking->size(); track++)
+ {
+ track_list *A = pc->tracking;
+ Track_nr B = A->at(track);
+ size_t Bfirst = B.first;
+ char *Bsecond = B.second;
+
+ LOG_FMT(LGUY, " %zu, tracking number is %zu\n", track, Bfirst);
+ LOG_FMT(LGUY, " %zu, rule is %s\n", track, Bsecond);
+ }
+ }
+ }
+ }
+ }
+
+ LOG_FMT(LGUY, "\n");
+} // prot_the_line_pc
+
+
+void prot_all_lines(const char *func_name, int theLine)
+{
+ counter++;
+ tokenCounter = 0;
+ size_t lineNumber = 1;
+
+ LOG_FMT(LGUY, "Prot_all_lines:(%s:%d)(%zu)\n", func_name, theLine, counter);
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ tokenCounter++;
+
+ LOG_FMT(LGUY, " orig_line is %zu,%zu, pp_level is %zu, ", lineNumber, tokenCounter, pc->pp_level);
+
+ if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<VBRACE_OPEN>, ");
+ }
+ else if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "<NL>(nl_count is %zu), ", pc->nl_count);
+ tokenCounter = 0;
+ lineNumber = lineNumber + pc->nl_count;
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_CLOSE>, ");
+ }
+ else if (chunk_is_token(pc, CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_OPEN>, ");
+ }
+ else if (chunk_is_token(pc, CT_SPACE))
+ {
+ LOG_FMT(LGUY, "<CT_SPACE>, ");
+ }
+ else if (chunk_is_token(pc, CT_IGNORED))
+ {
+ LOG_FMT(LGUY, "<IGNORED> ");
+ }
+ else
+ {
+ LOG_FMT(LGUY, "Text() '%s', ", pc->Text());
+ }
+ LOG_FMT(LGUY, " column is %zu, type is %s\n",
+ pc->column, get_token_name(pc->type));
+ }
+} // prot_all_lines
+
+
+void prot_the_source(int theLine)
+{
+ counter++;
+ LOG_FMT(LGUY, "Prot_the_source:(%d)(%zu)\n", theLine, counter);
+ output_text(stderr);
+}
+
+
+// examples:
+// examine_Data(__func__, __LINE__, n);
+void examine_Data(const char *func_name, int theLine, int what)
+{
+ LOG_FMT(LGUY, "\n%s:", func_name);
+
+ Chunk *pc;
+
+ switch (what)
+ {
+ case 1:
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( chunk_is_token(pc, CT_SQUARE_CLOSE)
+ || chunk_is_token(pc, CT_TSQUARE))
+ {
+ LOG_FMT(LGUY, "\n");
+ LOG_FMT(LGUY, "1:(%d),", theLine);
+ LOG_FMT(LGUY, "%s, orig_col=%zu, orig_col_end=%zu\n", pc->Text(), pc->orig_col, pc->orig_col_end);
+ }
+ }
+
+ break;
+
+ case 2:
+ LOG_FMT(LGUY, "2:(%d)\n", theLine);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->orig_line == 7)
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "(%zu)<NL> col=%zu\n\n", pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LGUY, "(%zu)%s %s, col=%zu, column=%zu\n", pc->orig_line, pc->Text(), get_token_name(pc->type), pc->orig_col, pc->column);
+ }
+ }
+ }
+
+ break;
+
+ case 3:
+ LOG_FMT(LGUY, "3:(%d)\n", theLine);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "(%zu)<NL> col=%zu\n\n", pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LGUY, "(%zu)%s %s, col=%zu, column=%zu\n", pc->orig_line, pc->Text(), get_token_name(pc->type), pc->orig_col, pc->column);
+ }
+ }
+
+ break;
+
+ case 4:
+ LOG_FMT(LGUY, "4:(%d)\n", theLine);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->orig_line == 6)
+ {
+ if (chunk_is_token(pc, CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "(%zu)<NL> col=%zu\n\n", pc->orig_line, pc->orig_col);
+ }
+ else
+ {
+ LOG_FMT(LGUY, "(%zu)%s %s, col=%zu, column=%zu\n", pc->orig_line, pc->Text(), get_token_name(pc->type), pc->orig_col, pc->column);
+ }
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ } // switch
+} // examine_Data
+
+
+void dump_out(unsigned int type)
+{
+ char dumpFileName[300];
+
+ if (cpd.dumped_file == nullptr)
+ {
+ sprintf(dumpFileName, "%s.%u", cpd.filename.c_str(), type);
+ }
+ else
+ {
+ sprintf(dumpFileName, "%s.%u", cpd.dumped_file, type);
+ }
+ FILE *D_file = fopen(dumpFileName, "w");
+
+ if (D_file != nullptr)
+ {
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ fprintf(D_file, "[%p]\n", pc);
+ fprintf(D_file, " type %s\n", get_token_name(pc->type));
+ fprintf(D_file, " orig_line %zu\n", pc->orig_line);
+ fprintf(D_file, " orig_col %zu\n", pc->orig_col);
+ fprintf(D_file, " orig_col_end %zu\n", pc->orig_col_end);
+
+ if (pc->orig_prev_sp != 0)
+ {
+ fprintf(D_file, " orig_prev_sp %u\n", pc->orig_prev_sp);
+ }
+
+ if (pc->column != 0)
+ {
+ fprintf(D_file, " column %zu\n", pc->column);
+ }
+
+ if (pc->column_indent != 0)
+ {
+ fprintf(D_file, " column_indent %zu\n", pc->column_indent);
+ }
+
+ if (pc->nl_count != 0)
+ {
+ fprintf(D_file, " nl_count %zu\n", pc->nl_count);
+ }
+
+ if (pc->level != 0)
+ {
+ fprintf(D_file, " level %zu\n", pc->level);
+ }
+
+ if (pc->brace_level != 0)
+ {
+ fprintf(D_file, " brace_level %zu\n", pc->brace_level);
+ }
+
+ if (pc->pp_level != 0)
+ {
+ fprintf(D_file, " pp_level %zu\n", pc->pp_level);
+ }
+
+ if (pc->after_tab != 0)
+ {
+ fprintf(D_file, " after_tab %d\n", pc->after_tab);
+ }
+
+ if (pc->type != CT_NEWLINE)
+ {
+ fprintf(D_file, " Text %s\n", pc->Text());
+ }
+ }
+
+ fclose(D_file);
+ }
+} // dump_out
+
+
+void dump_in(unsigned int type)
+{
+ char buffer[256];
+ bool aNewChunkIsFound = false;
+ Chunk chunk;
+ char dumpFileName[300];
+
+ if (cpd.dumped_file == nullptr)
+ {
+ sprintf(dumpFileName, "%s.%u", cpd.filename.c_str(), type);
+ }
+ else
+ {
+ sprintf(dumpFileName, "%s.%u", cpd.dumped_file, type);
+ }
+ FILE *D_file = fopen(dumpFileName, "r");
+
+ if (D_file != nullptr)
+ {
+ unsigned int lineNumber = 0;
+
+ while (fgets(buffer, sizeof(buffer), D_file) != nullptr)
+ {
+ ++lineNumber;
+
+ if (aNewChunkIsFound)
+ {
+ // look for the next chunk
+ char first = buffer[0];
+
+ if (first == '[')
+ {
+ aNewChunkIsFound = false;
+ // add the chunk in the list
+ chunk_add_before(&chunk, nullptr);
+ chunk.Reset();
+ aNewChunkIsFound = true;
+ continue;
+ }
+ // the line as the form
+ // part value
+ // Split the line
+ const int max_parts_count = 3;
+ char *parts[max_parts_count];
+ int parts_count = Args::SplitLine(buffer, parts, max_parts_count - 1);
+
+ if (parts_count != 2)
+ {
+ exit(EX_SOFTWARE);
+ }
+
+ if (strcasecmp(parts[0], "type") == 0)
+ {
+ E_Token tokenName = find_token_name(parts[1]);
+ set_chunk_type(&chunk, tokenName);
+ }
+ else if (strcasecmp(parts[0], "orig_line") == 0)
+ {
+ chunk.orig_line = strtol(parts[1], nullptr, 0);
+ }
+ else if (strcasecmp(parts[0], "orig_col") == 0)
+ {
+ chunk.orig_col = strtol(parts[1], nullptr, 0);
+ }
+ else if (strcasecmp(parts[0], "orig_col_end") == 0)
+ {
+ chunk.orig_col_end = strtol(parts[1], nullptr, 0);
+ }
+ else if (strcasecmp(parts[0], "orig_prev_sp") == 0)
+ {
+ chunk.orig_prev_sp = strtol(parts[1], nullptr, 0);
+ }
+ else if (strcasecmp(parts[0], "column") == 0)
+ {
+ chunk.column = strtol(parts[1], nullptr, 0);
+ }
+ else if (strcasecmp(parts[0], "nl_count") == 0)
+ {
+ chunk.nl_count = strtol(parts[1], nullptr, 0);
+ }
+ else if (strcasecmp(parts[0], "text") == 0)
+ {
+ if (chunk.type != CT_NEWLINE)
+ {
+ chunk.str = parts[1];
+ }
+ }
+ else
+ {
+ fprintf(stderr, "on line=%d, for '%s'\n", lineNumber, parts[0]);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ }
+ else
+ {
+ // look for a new chunk
+ char first = buffer[0];
+
+ if (first == '[')
+ {
+ aNewChunkIsFound = true;
+ chunk.Reset();
+ }
+ }
+ }
+ // add the last chunk in the list
+ chunk_add_before(&chunk, nullptr);
+ fclose(D_file);
+ }
+ else
+ {
+ fprintf(stderr, "FATAL: file not found '%s'\n", dumpFileName);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+} // dump_in
+
+
+size_t number = 0;
+
+
+size_t get_A_Number()
+{
+ number = number + 1;
+ return(number);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.h
new file mode 100644
index 00000000..acd199b9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unc_tools.h
@@ -0,0 +1,46 @@
+/**
+ * @file unc_tools.h
+ *
+ * @author Guy Maurel
+ * October 2015, 2016, 2017, 2018, 2019, 2020, 2021
+ * @license GPL v2+
+ */
+
+#ifndef UNC_TOOLS_H_INCLUDED
+#define UNC_TOOLS_H_INCLUDED
+
+#include "prototypes.h"
+
+#if defined DEBUG
+#define PROT_THE_LINE prot_the_line(__func__, __LINE__, 0, 0);
+#else
+#define PROT_THE_LINE /* do nothing */;
+#endif
+
+
+void prot_the_line(const char *func_name, int theLine, unsigned int actual_line, size_t partNumber);
+
+
+void prot_the_line_pc(Chunk *pc_sub, const char *func_name, int theLine, unsigned int actual_line, size_t partNumber);
+
+
+void prot_all_lines(const char *func_name, int theLine);
+
+
+void prot_the_source(int theLine);
+
+
+void examine_Data(const char *func_name, int theLine, int what);
+
+
+//! dump the chunk list to a file
+void dump_out(unsigned int type);
+
+
+//! create chunk list from a file
+void dump_in(unsigned int type);
+
+
+size_t get_A_Number();
+
+#endif /* UNC_TOOLS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.cpp
new file mode 100644
index 00000000..ee5dac2b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.cpp
@@ -0,0 +1,2708 @@
+/**
+ * @file uncrustify.cpp
+ * This file takes an input C/C++/D/Java file and reformats it.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#define DEFINE_CHAR_TABLE
+
+#include "uncrustify.h"
+
+#include "align.h"
+#include "align_nl_cont.h"
+#include "align_preprocessor.h"
+#include "align_trailing_comments.h"
+#include "args.h"
+#include "backup.h"
+#include "brace_cleanup.h"
+#include "braces.h"
+#include "combine.h"
+#include "compat.h"
+#include "detect.h"
+#include "enum_cleanup.h"
+#include "indent.h"
+#include "keywords.h"
+#include "lang_pawn.h"
+#include "newlines.h"
+#include "output.h"
+#include "parameter_pack_cleanup.h"
+#include "parens.h"
+#include "parent_for_pp.h"
+#include "remove_duplicate_include.h"
+#include "remove_extra_returns.h"
+#include "semicolons.h"
+#include "sorting.h"
+#include "space.h"
+#include "token_names.h"
+#include "tokenize.h"
+#include "tokenize_cleanup.h"
+#include "unc_ctype.h"
+#include "unc_tools.h"
+#include "uncrustify_version.h"
+#include "unicode.h"
+#include "universalindentgui.h"
+#include "width.h"
+
+#include <cerrno>
+#include <fcntl.h>
+#include <map>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h> // provides strcasecmp()
+#endif
+#ifdef HAVE_UTIME_H
+#include <time.h>
+#endif
+
+
+// VS throws an error if an attribute newer than the requested standard level
+// is used; everyone else just ignores it (or warns) like they are supposed to
+
+#if __cplusplus >= 201703L
+#define NODISCARD [[nodiscard]]
+#elif defined (__has_cpp_attribute)
+#if __has_cpp_attribute(nodiscard)
+#define NODISCARD [[nodiscard]]
+#else
+#define NODISCARD
+#endif
+#else
+#define NODISCARD
+#endif
+
+constexpr static auto LCURRENT = LUNC;
+
+using namespace std;
+using namespace uncrustify;
+
+
+// Global data
+cp_data_t cpd;
+
+
+static size_t language_flags_from_name(const char *tag);
+
+
+/**
+ * Find the language for the file extension
+ * Defaults to C
+ *
+ * @param filename The name of the file
+ * @return LANG_xxx
+ */
+static size_t language_flags_from_filename(const char *filename);
+
+
+static bool read_stdin(file_mem &fm);
+
+
+static void uncrustify_start(const deque<int> &data);
+
+
+static bool ends_with(const char *filename, const char *tag, bool case_sensitive);
+
+
+/**
+ * Does a source file.
+ *
+ * @param filename_in the file to read
+ * @param filename_out nullptr (stdout) or the file to write
+ * @param parsed_file nullptr or the filename for the parsed debug info
+ * @param dump_file nullptr or the filename prefix for dumping formatting steps debug info
+ * @param no_backup don't create a backup, if filename_out == filename_in
+ * @param keep_mtime don't change the mtime (dangerous)
+ */
+static void do_source_file(const char *filename_in, const char *filename_out, const char *parsed_file, const char *dump_file, bool no_backup, bool keep_mtime);
+
+
+static void add_file_header();
+
+
+static void add_file_footer();
+
+
+static void add_func_header(E_Token type, file_mem &fm);
+
+
+static void add_msg_header(E_Token type, file_mem &fm);
+
+
+static void process_source_list(const char *source_list, const char *prefix, const char *suffix, bool no_backup, bool keep_mtime);
+
+
+static const char *make_output_filename(char *buf, size_t buf_size, const char *filename, const char *prefix, const char *suffix);
+
+
+//! compare the content of two files
+static bool file_content_matches(const string &filename1, const string &filename2);
+
+
+static string fix_filename(const char *filename);
+
+
+static bool bout_content_matches(const file_mem &fm, bool report_status);
+
+
+/**
+ * Loads a file into memory
+ *
+ * @param filename name of file to load
+ *
+ * @retval true file was loaded successfully
+ * @retval false file could not be loaded
+ */
+static int load_mem_file(const char *filename, file_mem &fm);
+
+
+/**
+ * Try to load the file from the config folder first and then by name
+ *
+ * @param filename name of file to load
+ *
+ * @retval true file was loaded successfully
+ * @retval false file could not be loaded
+ */
+static int load_mem_file_config(const std::string &filename, file_mem &fm);
+
+
+//! print uncrustify version number and terminate
+static void version_exit(void);
+
+
+const char *path_basename(const char *path)
+{
+ if (path == nullptr)
+ {
+ return("");
+ }
+ const char *last_path = path;
+ char ch;
+
+ while ((ch = *path) != 0) // check for end of string
+ {
+ path++;
+
+ // Check both slash types to support Linux and Windows
+ if ( (ch == '/')
+ || (ch == '\\'))
+ {
+ last_path = path;
+ }
+ }
+ return(last_path);
+}
+
+
+int path_dirname_len(const char *filename)
+{
+ if (filename == nullptr)
+ {
+ return(0);
+ }
+ // subtracting addresses like this works only on big endian systems
+ return(static_cast<int>(path_basename(filename) - filename));
+}
+
+
+void usage_error(const char *msg)
+{
+ if (msg != nullptr)
+ {
+ fprintf(stderr, "%s\n", msg);
+ log_flush(true);
+ }
+ fprintf(stderr, "Try running with -h for usage information\n");
+ log_flush(true);
+}
+
+
+static void tease()
+{
+ fprintf(stdout,
+ "There are currently %zu options and minimal documentation.\n"
+ "Try UniversalIndentGUI and good luck.\n", get_option_count());
+}
+
+
+void usage(const char *argv0)
+{
+ fprintf(stdout,
+ "Usage:\n"
+ "%s [options] [files ...]\n"
+ "\n"
+ "If no input files are specified, the input is read from stdin\n"
+ "If reading from stdin, you should specify the language using -l\n"
+ "or specify a filename using --assume for automatic language detection.\n"
+ "\n"
+ "If -F is used or files are specified on the command line,\n"
+ "the output filename is 'prefix/filename' + suffix\n"
+ "\n"
+ "When reading from stdin or doing a single file via the '-f' option,\n"
+ "the output is dumped to stdout, unless redirected with -o FILE.\n"
+ "\n"
+ "Errors are always dumped to stderr\n"
+ "\n"
+ "The '-f' and '-o' options may not be used with '-F' or '--replace'.\n"
+ "The '--prefix' and '--suffix' options may not be used with '--replace'.\n"
+ "\n"
+ "Basic Options:\n"
+ " -c CFG : Use the config file CFG, or defaults if CFG is set to '-'.\n"
+ " -f FILE : Process the single file FILE (output to stdout, use with -o).\n"
+ " -o FILE : Redirect stdout to FILE.\n"
+ " -F FILE : Read files to process from FILE, one filename per line (- is stdin).\n"
+ " --check : Do not output the new text, instead verify that nothing changes when\n"
+ " the file(s) are processed.\n"
+ " The status of every file is printed to stderr.\n"
+ " The exit code is EXIT_SUCCESS if there were no changes, EXIT_FAILURE otherwise.\n"
+ " files : Files to process (can be combined with -F).\n"
+ " --suffix SFX : Append SFX to the output filename. The default is '.uncrustify'\n"
+ " --prefix PFX : Prepend PFX to the output filename path.\n"
+ " --replace : Replace source files (creates a backup).\n"
+ " --no-backup : Do not create backup and md5 files. Useful if files are under source control.\n"
+ " --if-changed : Write to stdout (or create output FILE) only if a change was detected.\n"
+#ifdef HAVE_UTIME_H
+ " --mtime : Preserve mtime on replaced files.\n"
+#endif
+ " -l : Language override: C, CPP, D, CS, JAVA, PAWN, OC, OC+, VALA.\n"
+ " -t : Load a file with types (usually not needed).\n"
+ " -q : Quiet mode - no output on stderr (-L will override).\n"
+ " --frag : Code fragment, assume the first line is indented correctly.\n"
+ " --assume FN : Uses the filename FN for automatic language detection if reading\n"
+ " from stdin unless -l is specified.\n"
+ "\n"
+ "Config/Help Options:\n"
+ " -h -? --help --usage : Print this message and exit.\n"
+ " --version : Print the version and exit.\n"
+ " --count-options : Print the number of available options and exit.\n"
+ " --show-config : Print out option documentation and exit.\n"
+ " --update-config : Output a new config file. Use with -o FILE.\n"
+ " --update-config-with-doc : Output a new config file. Use with -o FILE.\n"
+ " --universalindent : Output a config file for Universal Indent GUI.\n"
+ " --detect : Detects the config from a source file. Use with '-f FILE'.\n"
+ " Detection is fairly limited.\n"
+ " --set <option>=<value> : Sets a new value to a config option.\n"
+ "\n"
+ "Debug Options:\n"
+ " -p FILE : Dump debug info into FILE, or to stdout if FILE is set to '-'.\n"
+ " Must be used in combination with '-f FILE'\n"
+ " -ds FILE : Dump parsing info at various moments of the formatting process.\n"
+ " --dump-steps FILE This creates a series of files named 'FILE_nnn.log', each\n"
+ " corresponding to a formatting step in uncrustify.\n"
+ " The file 'FILE_000.log' lists the formatting options in use.\n"
+ " Must be used in combination with '-f FILE'\n"
+ " -L SEV : Set the log severity (see log_levels.h; note 'A' = 'all')\n"
+ " -s : Show the log severity in the logs.\n"
+ " --decode : Decode remaining args (chunk flags) and exit.\n"
+ " --tracking_space FILE : Prepare tracking informations for debugging.\n"
+ " Cannot be used with the -o option'\n"
+ "\n"
+ "Usage Examples\n"
+ "cat foo.d | uncrustify -q -c my.cfg -l d\n"
+ "uncrustify -c my.cfg -f foo.d\n"
+ "uncrustify -c my.cfg -f foo.d -L0-2,20-23,51\n"
+ "uncrustify -c my.cfg -f foo.d -o foo.d\n"
+ "uncrustify -c my.cfg -f foo.d -o foo.d -ds dump\n"
+ "uncrustify -c my.cfg foo.d\n"
+ "uncrustify -c my.cfg --replace foo.d\n"
+ "uncrustify -c my.cfg --no-backup foo.d\n"
+ "uncrustify -c my.cfg --prefix=out -F files.txt\n"
+ "\n"
+ "Note: Use comments containing ' *INDENT-OFF*' and ' *INDENT-ON*' to disable\n"
+ " processing of parts of the source file (these can be overridden with\n"
+ " enable_processing_cmt and disable_processing_cmt).\n"
+ "\n"
+ ,
+ path_basename(argv0));
+ tease();
+} // usage
+
+
+static void version_exit(void)
+{
+ printf("%s\n", UNCRUSTIFY_VERSION);
+ exit(EX_OK);
+}
+
+
+NODISCARD static int redir_stdout(const char *output_file)
+{
+ FILE *my_stdout = stdout; // Reopen stdout
+
+ if (output_file != nullptr)
+ {
+ my_stdout = freopen(output_file, "wb", stdout);
+
+ if (my_stdout == nullptr)
+ {
+ LOG_FMT(LERR, "Unable to open %s for write: %s (%d)\n",
+ output_file, strerror(errno), errno);
+ cpd.error_count++;
+ usage_error();
+ return(EX_IOERR);
+ }
+ LOG_FMT(LNOTE, "Redirecting output to %s\n", output_file);
+ }
+ return(EXIT_SUCCESS);
+}
+
+// Currently, the crash handler is only supported while building under MSVC
+#if defined (WIN32) && defined (_MSC_VER)
+
+
+void setup_crash_handling()
+{
+ // prevent crash popup. uncrustify is a batch processing tool and a popup is unacceptable.
+ ::SetErrorMode(::GetErrorMode() | SEM_NOGPFAULTERRORBOX);
+
+ struct local
+ {
+ static LONG WINAPI crash_filter(_In_ struct _EXCEPTION_POINTERS *exceptionInfo)
+ {
+ __try
+ {
+ LOG_FMT(LERR, "crash_filter: exception 0x%08X at [%d:%d] (ip=%p)",
+ exceptionInfo->ExceptionRecord->ExceptionCode,
+ cpd.line_number, cpd.column,
+ exceptionInfo->ExceptionRecord->ExceptionAddress);
+ log_func_stack(LERR, " [CallStack:", "]\n", 0);
+
+ // treat an exception the same as a parse failure. exceptions can result from parse failures where we
+ // do not have specific handling (null-checks for particular parse paths etc.) and callers generally
+ // won't care about the difference. they just want to know it failed.
+ exit(EXIT_FAILURE);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ // have to be careful of crashes in crash handling code
+ }
+
+ // safety - note that this will not flush like we need, but at least will get the right return code
+ ::ExitProcess(EXIT_FAILURE);
+ }
+ };
+
+ // route all crashes through our own handler
+ ::SetUnhandledExceptionFilter(local::crash_filter);
+}
+
+#else
+
+
+void setup_crash_handling()
+{
+ // TODO: unixes
+}
+
+#endif
+
+
+int main(int argc, char *argv[])
+{
+ // initialize the global data
+ cpd.unc_off_used = false;
+
+ setup_crash_handling();
+
+ // Build options map
+ register_options();
+
+ // If ran without options show the usage info and exit */
+ if (argc == 1)
+ {
+ usage(argv[0]);
+ return(EXIT_SUCCESS);
+ }
+#ifdef DEBUG
+ // make sure we have 'name' not too big
+ const int max_name_length = 19;
+
+ // maxLengthOfTheName must be consider at the format line at the file
+ // output.cpp, line 427: fprintf(pfile, "# Line Tag Parent...
+ // and 430: ... fprintf(pfile, "%s# %3zu>%19.19s[%19.19s] ...
+ // here xx xx xx xx
+ for (size_t token = 0; token < ARRAY_SIZE(token_names); token++)
+ {
+ const size_t name_length = strlen(token_names[token]);
+
+ if (name_length > max_name_length)
+ {
+ fprintf(stderr, "%s(%d): The token name '%s' is too long (%d)\n",
+ __func__, __LINE__, token_names[token], static_cast<int>(name_length));
+ fprintf(stderr, "%s(%d): the max token name length is %d\n",
+ __func__, __LINE__, max_name_length);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ }
+
+ // make sure we have token_names.h in sync with token_enum.h
+ assert(ARRAY_SIZE(token_names) == CT_TOKEN_COUNT_);
+#endif // DEBUG
+
+ Args arg(argc, argv);
+
+ if ( arg.Present("--version")
+ || arg.Present("-v"))
+ {
+ version_exit();
+ }
+
+ if ( arg.Present("--help")
+ || arg.Present("-h")
+ || arg.Present("--usage")
+ || arg.Present("-?"))
+ {
+ usage(argv[0]);
+ return(EXIT_SUCCESS);
+ }
+
+ if (arg.Present("--count-options"))
+ {
+ tease();
+ return(EXIT_SUCCESS);
+ }
+
+ if (arg.Present("--show-config"))
+ {
+ save_option_file(stdout, true);
+ return(EXIT_SUCCESS);
+ }
+ cpd.do_check = arg.Present("--check");
+ cpd.if_changed = arg.Present("--if-changed");
+
+#ifdef WIN32
+ // tell Windows not to change what I write to stdout
+ UNUSED(_setmode(_fileno(stdout), _O_BINARY));
+#endif
+
+ // Init logging
+ log_init(cpd.do_check ? stdout : stderr);
+ log_mask_t mask;
+
+ if (arg.Present("-q"))
+ {
+ logmask_from_string("", mask);
+ log_set_mask(mask);
+ }
+ const char *p_arg;
+
+ if ( ((p_arg = arg.Param("-L")) != nullptr)
+ || ((p_arg = arg.Param("--log")) != nullptr))
+ {
+ logmask_from_string(p_arg, mask);
+ log_set_mask(mask);
+ }
+ cpd.frag = arg.Present("--frag");
+
+ if (arg.Present("--decode"))
+ {
+ size_t idx = 1;
+
+ while ((p_arg = arg.Unused(idx)) != nullptr)
+ {
+ log_pcf_flags(LSYS, static_cast<pcf_flag_e>(strtoul(p_arg, nullptr, 16)));
+ }
+ return(EXIT_SUCCESS);
+ }
+ // Get the config file name
+ string cfg_file;
+
+ if ( ((p_arg = arg.Param("--config")) != nullptr)
+ || ((p_arg = arg.Param("-c")) != nullptr))
+ {
+ cfg_file = p_arg;
+ }
+ else if (!unc_getenv("UNCRUSTIFY_CONFIG", cfg_file))
+ {
+ // Try to find a config file at an alternate location
+ string home;
+
+ if (unc_homedir(home))
+ {
+ struct stat tmp_stat = {};
+
+ const auto path0 = home + "/.uncrustify.cfg";
+ const auto path1 = home + "/uncrustify.cfg";
+
+ if (stat(path0.c_str(), &tmp_stat) == 0)
+ {
+ cfg_file = path0;
+ }
+ else if (stat(path1.c_str(), &tmp_stat) == 0)
+ {
+ cfg_file = path1;
+ }
+ }
+ }
+ // Get the parsed file name
+ const char *parsed_file;
+
+ if ( ((parsed_file = arg.Param("--parsed")) != nullptr)
+ || ((parsed_file = arg.Param("-p")) != nullptr))
+ {
+ if ( parsed_file[0] == '-'
+ && !parsed_file[1])
+ {
+ LOG_FMT(LNOTE, "Will print parsed data to stdout\n");
+ }
+ else
+ {
+ LOG_FMT(LNOTE, "Will export parsed data to: %s\n", parsed_file);
+ }
+ }
+ // Get the dump file name prefix
+ const char *dump_file;
+
+ if ( ((dump_file = arg.Param("--dump-steps")) != nullptr)
+ || ((dump_file = arg.Param("-ds")) != nullptr))
+ {
+ LOG_FMT(LNOTE, "Will export formatting steps data to '%s_nnn.log' files\n", dump_file);
+ }
+
+ // Enable log severities
+ if ( arg.Present("-s")
+ || arg.Present("--show"))
+ {
+ log_show_sev(true);
+ }
+ // Load type files
+ size_t idx = 0;
+
+ while ((p_arg = arg.Params("-t", idx)) != nullptr)
+ {
+ load_keyword_file(p_arg);
+ }
+ // add types
+ idx = 0;
+
+ while ((p_arg = arg.Params("--type", idx)) != nullptr)
+ {
+ add_keyword(p_arg, CT_TYPE);
+ }
+ bool arg_l_is_set = false;
+
+ // Check for a language override
+ if ((p_arg = arg.Param("-l")) != nullptr)
+ {
+ arg_l_is_set = true;
+ cpd.lang_flags = language_flags_from_name(p_arg);
+
+ if (cpd.lang_flags == 0)
+ {
+ LOG_FMT(LWARN, "Ignoring unknown language: %s\n", p_arg);
+ }
+ else
+ {
+ cpd.lang_forced = true;
+ }
+ }
+ // Get the source file name
+ const char *source_file;
+
+ if ( ((source_file = arg.Param("--file")) == nullptr)
+ && ((source_file = arg.Param("-f")) == nullptr))
+ {
+ // not using a single file, source_file is nullptr
+ }
+ // Get a source file list
+ const char *source_list;
+
+ if ( ((source_list = arg.Param("--files")) == nullptr)
+ && ((source_list = arg.Param("-F")) == nullptr))
+ {
+ // not using a file list, source_list is nullptr
+ }
+ const char *prefix = arg.Param("--prefix");
+ const char *suffix = arg.Param("--suffix");
+ const char *assume = arg.Param("--assume");
+
+ bool no_backup = arg.Present("--no-backup");
+ bool replace = arg.Present("--replace");
+ bool keep_mtime = arg.Present("--mtime");
+ bool update_config = arg.Present("--update-config");
+ bool update_config_wd = arg.Present("--update-config-with-doc");
+ bool detect = arg.Present("--detect");
+ bool pfile_csv = arg.Present("--debug-csv-format");
+
+ std::string parsed_file_csv;
+
+ if (pfile_csv)
+ {
+ if ( parsed_file == nullptr
+ || ( parsed_file[0] == '-'
+ && !parsed_file[1]))
+ {
+ fprintf(stderr,
+ "FAIL: --debug-csv-format option must be used in combination with '-p FILE', where FILE\n"
+ " is not set to '-'\n");
+ log_flush(true);
+ exit(EX_CONFIG);
+ }
+ else if (!ends_with(parsed_file, ".csv", false))
+ {
+ parsed_file_csv = parsed_file;
+
+ // user-specified parsed filename does not end in a ".csv" extension, so add it
+ parsed_file_csv += ".csv";
+ parsed_file = parsed_file_csv.c_str();
+ }
+ }
+ // Grab the output override
+ const char *output_file = arg.Param("-o");
+
+ // for debugging tracking
+ cpd.html_file = arg.Param("--tracking_space");
+
+ LOG_FMT(LDATA, "%s\n", UNCRUSTIFY_VERSION);
+ LOG_FMT(LDATA, "config_file = %s\n", cfg_file.c_str());
+ LOG_FMT(LDATA, "output_file = %s\n", (output_file != NULL) ? output_file : "null");
+ LOG_FMT(LDATA, "source_file = %s\n", (source_file != NULL) ? source_file : "null");
+ LOG_FMT(LDATA, "source_list = %s\n", (source_list != NULL) ? source_list : "null");
+ LOG_FMT(LDATA, "tracking = %s\n", (cpd.html_file != NULL) ? cpd.html_file : "null");
+ LOG_FMT(LDATA, "prefix = %s\n", (prefix != NULL) ? prefix : "null");
+ LOG_FMT(LDATA, "suffix = %s\n", (suffix != NULL) ? suffix : "null");
+ LOG_FMT(LDATA, "assume = %s\n", (assume != NULL) ? assume : "null");
+ LOG_FMT(LDATA, "replace = %s\n", replace ? "true" : "false");
+ LOG_FMT(LDATA, "no_backup = %s\n", no_backup ? "true" : "false");
+ LOG_FMT(LDATA, "detect = %s\n", detect ? "true" : "false");
+ LOG_FMT(LDATA, "check = %s\n", cpd.do_check ? "true" : "false");
+ LOG_FMT(LDATA, "if_changed = %s\n", cpd.if_changed ? "true" : "false");
+
+ if ( cpd.do_check
+ && ( output_file
+ || replace
+ || no_backup
+ || keep_mtime
+ || update_config
+ || update_config_wd
+ || detect
+ || prefix
+ || suffix
+ || cpd.if_changed))
+ {
+ usage_error("Cannot use --check with output options.");
+ return(EX_NOUSER);
+ }
+
+ if (!cpd.do_check)
+ {
+ if (replace)
+ {
+ if ( prefix != nullptr
+ || suffix != nullptr)
+ {
+ usage_error("Cannot use --replace with --prefix or --suffix");
+ return(EX_NOINPUT);
+ }
+
+ if ( source_file != nullptr
+ || output_file != nullptr)
+ {
+ usage_error("Cannot use --replace with -f or -o");
+ return(EX_NOINPUT);
+ }
+ }
+ else if (!no_backup)
+ {
+ if ( prefix == nullptr
+ && suffix == nullptr)
+ {
+ suffix = ".uncrustify";
+ }
+ }
+ }
+
+ /*
+ * Try to load the config file, if available.
+ * It is optional for "--universalindent", "--parsed" and "--detect", but
+ * required for everything else.
+ */
+ if ( !cfg_file.empty()
+ && cfg_file[0] != '-')
+ {
+ cpd.filename = cfg_file;
+
+ if (!load_option_file(cpd.filename.c_str()))
+ {
+ usage_error("Unable to load the config file");
+ return(EX_IOERR);
+ }
+ // test if all options are compatible to each other
+ log_rule_B("nl_max");
+
+ if (options::nl_max() > 0)
+ {
+ // test if one/some option(s) is/are not too big for that
+ log_rule_B("nl_func_var_def_blk");
+
+ if (options::nl_func_var_def_blk() >= options::nl_max())
+ {
+ fprintf(stderr, "The option 'nl_func_var_def_blk' is too big against the option 'nl_max'\n");
+ log_flush(true);
+ exit(EX_CONFIG);
+ }
+ }
+ }
+ // Set config options using command line arguments.
+ idx = 0;
+
+ const size_t max_args_length = 256;
+
+ while ((p_arg = arg.Params("--set", idx)) != nullptr)
+ {
+ size_t argLength = strlen(p_arg);
+
+ if (argLength > max_args_length)
+ {
+ fprintf(stderr, "The buffer is to short for the set argument '%s'\n", p_arg);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ char buffer[max_args_length];
+ strcpy(buffer, p_arg);
+
+ // Tokenize and extract key and value
+ const char *token = strtok(buffer, "=");
+ const char *option = token;
+
+ token = strtok(nullptr, "=");
+ const char *value = token;
+
+ if ( option != nullptr
+ && value != nullptr
+ && strtok(nullptr, "=") == nullptr) // end of argument reached
+ {
+ if (auto *opt = uncrustify::find_option(option))
+ {
+ if (!opt->read(value))
+ {
+ return(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Unknown option '%s' to override.\n", buffer);
+ log_flush(true);
+ return(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ // TODO: consider using defines like EX_USAGE from sysexits.h
+ usage_error("Error while parsing --set");
+ return(EX_USAGE);
+ }
+ }
+
+ if (arg.Present("--universalindent"))
+ {
+ FILE *pfile = stdout;
+
+ if (output_file != nullptr)
+ {
+ pfile = fopen(output_file, "w");
+
+ if (pfile == nullptr)
+ {
+ fprintf(stderr, "Unable to open %s for write: %s (%d)\n",
+ output_file, strerror(errno), errno);
+ log_flush(true);
+ return(EXIT_FAILURE);
+ }
+ }
+ print_universal_indent_cfg(pfile);
+ fclose(pfile);
+
+ return(EXIT_SUCCESS);
+ }
+ // Set the number of second(s) before terminating formatting the current file.
+#ifdef WIN32
+ if (options::debug_timeout() > 0)
+ {
+ fprintf(stderr, "The option 'debug_timeout' is not available under Windows.\n");
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+#else
+ if (options::debug_timeout() > 0)
+ {
+ alarm(options::debug_timeout());
+ }
+#endif // ifdef WIN32
+
+ if (detect)
+ {
+ file_mem fm;
+
+ if ( source_file == nullptr
+ || source_list != nullptr)
+ {
+ fprintf(stderr, "The --detect option requires a single input file\n");
+ log_flush(true);
+ return(EXIT_FAILURE);
+ }
+
+ // Do some simple language detection based on the filename extension
+ if ( !cpd.lang_forced
+ || cpd.lang_flags == 0)
+ {
+ cpd.lang_flags = language_flags_from_filename(source_file);
+ }
+
+ // Try to read in the source file
+ if (load_mem_file(source_file, fm) < 0)
+ {
+ LOG_FMT(LERR, "Failed to load (%s)\n", source_file);
+ cpd.error_count++;
+ return(EXIT_FAILURE);
+ }
+ uncrustify_start(fm.data);
+ detect_options();
+ uncrustify_end();
+
+ if (auto error = redir_stdout(output_file))
+ {
+ return(error);
+ }
+ save_option_file(stdout, update_config_wd);
+ return(EXIT_SUCCESS);
+ }
+
+ if ( update_config
+ || update_config_wd)
+ {
+ // TODO: complain if file-processing related options are present
+ if (auto error = redir_stdout(output_file))
+ {
+ return(error);
+ }
+ save_option_file(stdout, update_config_wd);
+ return(EXIT_SUCCESS);
+ }
+
+ /*
+ * Everything beyond this point aside from dumping the parse tree is silly
+ * without a config file, so complain and bail if we don't have one.
+ */
+ if ( cfg_file.empty()
+ && !parsed_file)
+ {
+ usage_error("Specify the config file with '-c file' or set UNCRUSTIFY_CONFIG");
+ return(EX_IOERR);
+ }
+ // Done parsing args
+
+ // Check for unused args (ignore them)
+ idx = 1;
+ p_arg = arg.Unused(idx);
+
+ // Check args - for multifile options
+ if ( source_list != nullptr
+ || p_arg != nullptr)
+ {
+ if (source_file != nullptr)
+ {
+ usage_error("Cannot specify both the single file option and a multi-file option.");
+ return(EX_NOUSER);
+ }
+
+ if (output_file != nullptr)
+ {
+ usage_error("Cannot specify -o with a multi-file option.");
+ return(EX_NOHOST);
+ }
+ }
+ // This relies on cpd.filename being the config file name
+ load_header_files();
+
+ if ( cpd.do_check
+ || cpd.if_changed)
+ {
+ cpd.bout = new deque<UINT8>();
+ }
+ idx = 1;
+
+ if ( source_file == nullptr
+ && source_list == nullptr
+ && arg.Unused(idx) == nullptr)
+ {
+ if (!arg_l_is_set) // Issue #3064
+ {
+ if (assume == nullptr)
+ {
+ LOG_FMT(LERR, "If reading from stdin, you should specify the language using -l\n");
+ LOG_FMT(LERR, "or specify a filename using --assume for automatic language detection.\n");
+ return(EXIT_FAILURE);
+ }
+ }
+
+ if (cpd.lang_flags == 0)
+ {
+ if (assume != nullptr)
+ {
+ cpd.lang_flags = language_flags_from_filename(assume);
+ }
+ else
+ {
+ cpd.lang_flags = LANG_C;
+ }
+ }
+
+ if (!cpd.do_check)
+ {
+ if (auto error = redir_stdout(output_file))
+ {
+ return(error);
+ }
+ }
+ file_mem fm;
+
+ if (!read_stdin(fm))
+ {
+ LOG_FMT(LERR, "Failed to read stdin\n");
+ cpd.error_count++;
+ return(100);
+ }
+ cpd.filename = "stdin";
+
+ // Done reading from stdin
+ LOG_FMT(LSYS, "%s(%d): Parsing: %zu bytes (%zu chars) from stdin as language %s\n",
+ __func__, __LINE__, fm.raw.size(), fm.data.size(),
+ language_name_from_flags(cpd.lang_flags));
+
+ // Issue #3427
+ init_keywords_for_language();
+ uncrustify_file(fm, stdout, parsed_file, dump_file);
+ }
+ else if (source_file != nullptr)
+ {
+ // Doing a single file
+ do_source_file(source_file, output_file, parsed_file, dump_file, no_backup, keep_mtime);
+ }
+ else
+ {
+ if (parsed_file != nullptr) // Issue #930
+ {
+ fprintf(stderr, "FAIL: -p option must be used with the -f option\n");
+ log_flush(true);
+ exit(EX_CONFIG);
+ }
+
+ if (dump_file != nullptr)
+ {
+ fprintf(stderr, "FAIL: -ds/--dump-steps option must be used with the -f option\n");
+ log_flush(true);
+ exit(EX_CONFIG);
+ }
+
+ // Doing multiple files, TODO: multiple threads for parallel processing
+ if (prefix != nullptr)
+ {
+ LOG_FMT(LSYS, "Output prefix: %s/\n", prefix);
+ }
+
+ if (suffix != nullptr)
+ {
+ LOG_FMT(LSYS, "Output suffix: %s\n", suffix);
+ }
+ // Do the files on the command line first
+ idx = 1;
+
+ while ((p_arg = arg.Unused(idx)) != nullptr)
+ {
+ char outbuf[1024];
+ do_source_file(p_arg,
+ make_output_filename(outbuf, sizeof(outbuf), p_arg, prefix, suffix),
+ nullptr, nullptr, no_backup, keep_mtime);
+ }
+
+ if (source_list != nullptr)
+ {
+ process_source_list(source_list, prefix, suffix, no_backup, keep_mtime);
+ }
+ }
+ clear_keyword_file();
+
+ if (cpd.error_count != 0)
+ {
+ return(EXIT_FAILURE);
+ }
+
+ if ( cpd.do_check
+ && cpd.check_fail_cnt != 0)
+ {
+ return(EXIT_FAILURE);
+ }
+ return(EXIT_SUCCESS);
+} // main
+
+
+static void process_source_list(const char *source_list,
+ const char *prefix, const char *suffix,
+ bool no_backup, bool keep_mtime)
+{
+ bool from_stdin = strcmp(source_list, "-") == 0;
+ FILE *p_file = from_stdin ? stdin : fopen(source_list, "r");
+
+ if (p_file == nullptr)
+ {
+ LOG_FMT(LERR, "%s: fopen(%s) failed: %s (%d)\n",
+ __func__, source_list, strerror(errno), errno);
+ cpd.error_count++;
+ return;
+ }
+ char linebuf[256];
+ int line = 0;
+
+ while (fgets(linebuf, sizeof(linebuf), p_file) != nullptr)
+ {
+ line++;
+ char *fname = linebuf;
+ int len = strlen(fname);
+
+ while ( len > 0
+ && unc_isspace(*fname))
+ {
+ fname++;
+ len--;
+ }
+
+ while ( len > 0
+ && unc_isspace(fname[len - 1]))
+ {
+ len--;
+ }
+ fname[len] = 0;
+
+ while (len-- > 0)
+ {
+ if (fname[len] == '\\')
+ {
+ fname[len] = '/';
+ }
+ }
+ LOG_FMT(LFILELIST, "%3d file to uncrustify: %s\n", line, fname);
+
+ if (fname[0] != '#')
+ {
+ char outbuf[1024];
+ do_source_file(fname,
+ make_output_filename(outbuf, sizeof(outbuf), fname, prefix, suffix),
+ nullptr, nullptr, no_backup, keep_mtime);
+ }
+ }
+
+ if (!from_stdin)
+ {
+ fclose(p_file);
+ }
+} // process_source_list
+
+
+static bool read_stdin(file_mem &fm)
+{
+ deque<UINT8> dq;
+ char buf[4096];
+
+ fm.raw.clear();
+ fm.data.clear();
+ fm.enc = char_encoding_e::e_ASCII;
+
+ // Re-open stdin in binary mode to preserve newline characters
+#ifdef WIN32
+ _setmode(_fileno(stdin), _O_BINARY);
+#endif
+
+ while (!feof(stdin))
+ {
+ int len = fread(buf, 1, sizeof(buf), stdin);
+
+ for (int idx = 0; idx < len; idx++)
+ {
+ dq.push_back(buf[idx]);
+ }
+ }
+ // Copy the raw data from the deque to the vector
+ fm.raw.insert(fm.raw.end(), dq.begin(), dq.end());
+ return(decode_unicode(fm.raw, fm.data, fm.enc, fm.bom));
+}
+
+
+static void make_folders(const string &filename)
+{
+ int last_idx = 0;
+ char outname[4096];
+
+ snprintf(outname, sizeof(outname), "%s", filename.c_str());
+
+ for (int idx = 0; outname[idx] != 0; idx++)
+ {
+ if ( (outname[idx] == '/')
+ || (outname[idx] == '\\'))
+ {
+ outname[idx] = PATH_SEP;
+ }
+
+ // search until end of subpath is found
+ if ( idx > last_idx
+ && (outname[idx] == PATH_SEP))
+ {
+ outname[idx] = 0; // mark the end of the subpath
+
+ // create subfolder if it is not the start symbol of a path
+ // and not a Windows drive letter
+ if ( (strcmp(&outname[last_idx], ".") != 0)
+ && (strcmp(&outname[last_idx], "..") != 0)
+ && (!( last_idx == 0
+ && idx == 2
+ && outname[1] == ':')))
+ {
+ int status; // Coverity CID 75999
+ status = mkdir(outname, 0750);
+
+ if ( status != 0
+ && errno != EEXIST)
+ {
+ LOG_FMT(LERR, "%s: Unable to create %s: %s (%d)\n",
+ __func__, outname, strerror(errno), errno);
+ cpd.error_count++;
+ return;
+ }
+ }
+ outname[idx] = PATH_SEP; // reconstruct full path to search for next subpath
+ }
+
+ if (outname[idx] == PATH_SEP)
+ {
+ last_idx = idx + 1;
+ }
+ }
+} // make_folders
+
+
+static int load_mem_file(const char *filename, file_mem &fm)
+{
+ int retval = -1;
+ struct stat my_stat;
+ FILE *p_file;
+
+ fm.raw.clear();
+ fm.data.clear();
+ fm.enc = char_encoding_e::e_ASCII;
+
+ // Grab the stat info for the file, return if it cannot be read
+ if (stat(filename, &my_stat) < 0)
+ {
+ return(-1);
+ }
+#ifdef HAVE_UTIME_H
+ // Save off modification time (mtime)
+ fm.utb.modtime = my_stat.st_mtime;
+#endif
+
+ // Try to read in the file
+ p_file = fopen(filename, "rb");
+
+ if (p_file == nullptr)
+ {
+ return(-1);
+ }
+ fm.raw.resize(my_stat.st_size);
+
+ if (my_stat.st_size == 0) // check if file is empty
+ {
+ retval = 0;
+ fm.bom = false;
+ fm.enc = char_encoding_e::e_ASCII;
+ fm.data.clear();
+ }
+ else
+ {
+ // read the raw data
+ if (fread(&fm.raw[0], fm.raw.size(), 1, p_file) != 1)
+ {
+ LOG_FMT(LERR, "%s: fread(%s) failed: %s (%d)\n",
+ __func__, filename, strerror(errno), errno);
+ cpd.error_count++;
+ }
+ else if (!decode_unicode(fm.raw, fm.data, fm.enc, fm.bom))
+ {
+ LOG_FMT(LERR, "%s: failed to decode the file '%s'\n", __func__, filename);
+ cpd.error_count++;
+ }
+ else
+ {
+ LOG_FMT(LNOTE, "%s: '%s' encoding looks like %s (%d)\n", __func__, filename,
+ fm.enc == char_encoding_e::e_ASCII ? "ASCII" :
+ fm.enc == char_encoding_e::e_BYTE ? "BYTES" :
+ fm.enc == char_encoding_e::e_UTF8 ? "UTF-8" :
+ fm.enc == char_encoding_e::e_UTF16_LE ? "UTF-16-LE" :
+ fm.enc == char_encoding_e::e_UTF16_BE ? "UTF-16-BE" : "Error",
+ (int)fm.enc);
+ retval = 0;
+ }
+ }
+ fclose(p_file);
+ return(retval);
+} // load_mem_file
+
+
+static int load_mem_file_config(const std::string &filename, file_mem &fm)
+{
+ int retval;
+ char buf[1024];
+
+ snprintf(buf, sizeof(buf), "%.*s%s",
+ path_dirname_len(cpd.filename.c_str()), cpd.filename.c_str(), filename.c_str());
+
+ retval = load_mem_file(buf, fm);
+
+ if (retval < 0)
+ {
+ retval = load_mem_file(filename.c_str(), fm);
+
+ if (retval < 0)
+ {
+ LOG_FMT(LERR, "Failed to load (%s) or (%s)\n", buf, filename.c_str());
+ cpd.error_count++;
+ }
+ }
+ return(retval);
+}
+
+
+int load_header_files()
+{
+ int retval = 0;
+
+ log_rule_B("cmt_insert_file_header");
+
+ if (!options::cmt_insert_file_header().empty())
+ {
+ // try to load the file referred to by the options string
+ retval |= load_mem_file_config(options::cmt_insert_file_header(),
+ cpd.file_hdr);
+ }
+ log_rule_B("cmt_insert_file_footer");
+
+ if (!options::cmt_insert_file_footer().empty())
+ {
+ retval |= load_mem_file_config(options::cmt_insert_file_footer(),
+ cpd.file_ftr);
+ }
+ log_rule_B("cmt_insert_func_header");
+
+ if (!options::cmt_insert_func_header().empty())
+ {
+ retval |= load_mem_file_config(options::cmt_insert_func_header(),
+ cpd.func_hdr);
+ }
+ log_rule_B("cmt_insert_class_header");
+
+ if (!options::cmt_insert_class_header().empty())
+ {
+ retval |= load_mem_file_config(options::cmt_insert_class_header(),
+ cpd.class_hdr);
+ }
+ log_rule_B("cmt_insert_oc_msg_header");
+
+ if (!options::cmt_insert_oc_msg_header().empty())
+ {
+ retval |= load_mem_file_config(options::cmt_insert_oc_msg_header(),
+ cpd.oc_msg_hdr);
+ }
+ log_rule_B("cmt_reflow_fold_regex_file");
+
+ if (!options::cmt_reflow_fold_regex_file().empty())
+ {
+ retval |= load_mem_file_config(options::cmt_reflow_fold_regex_file(),
+ cpd.reflow_fold_regex);
+ }
+ return(retval);
+} // load_header_files
+
+
+static const char *make_output_filename(char *buf, size_t buf_size,
+ const char *filename,
+ const char *prefix,
+ const char *suffix)
+{
+ int len = 0;
+
+ if (prefix != nullptr)
+ {
+ len = snprintf(buf, buf_size, "%s/", prefix);
+ }
+ snprintf(&buf[len], buf_size - len, "%s%s", filename,
+ (suffix != nullptr) ? suffix : "");
+
+ return(buf);
+}
+
+
+static bool file_content_matches(const string &filename1, const string &filename2)
+{
+ struct stat st1, st2;
+ int fd1, fd2;
+
+ // Check the file sizes first
+ if ( (stat(filename1.c_str(), &st1) != 0)
+ || (stat(filename2.c_str(), &st2) != 0)
+ || st1.st_size != st2.st_size)
+ {
+ return(false);
+ }
+
+ if ((fd1 = open(filename1.c_str(), O_RDONLY)) < 0)
+ {
+ return(false);
+ }
+
+ if ((fd2 = open(filename2.c_str(), O_RDONLY)) < 0)
+ {
+ close(fd1);
+ return(false);
+ }
+ int len1 = 0;
+ int len2 = 0;
+ UINT8 buf1[1024];
+ UINT8 buf2[1024];
+
+ memset(buf1, 0, sizeof(buf1));
+ memset(buf2, 0, sizeof(buf2));
+
+ while ( len1 >= 0
+ && len2 >= 0)
+ {
+ if (len1 == 0)
+ {
+ len1 = read(fd1, buf1, sizeof(buf1));
+ }
+
+ if (len2 == 0)
+ {
+ len2 = read(fd2, buf2, sizeof(buf2));
+ }
+
+ if ( len1 <= 0
+ || len2 <= 0)
+ {
+ break; // reached end of either files
+ // TODO: what is if one file is longer than the other, do we miss that ?
+ }
+ int minlen = (len1 < len2) ? len1 : len2;
+
+ if (memcmp(buf1, buf2, minlen) != 0)
+ {
+ break; // found a difference
+ }
+ len1 -= minlen;
+ len2 -= minlen;
+ }
+ close(fd1);
+ close(fd2);
+
+ return( len1 == 0
+ && len2 == 0);
+} // file_content_matches
+
+
+static string fix_filename(const char *filename)
+{
+ char *tmp_file;
+ string rv;
+
+ // Create 'outfile.uncrustify'
+ tmp_file = new char[strlen(filename) + 16 + 1]; // + 1 for '// + 1 for '/* + 1 for '\0' */' '
+
+ if (tmp_file != nullptr)
+ {
+ sprintf(tmp_file, "%s.uncrustify", filename);
+ }
+ rv = tmp_file;
+ delete[] tmp_file;
+ return(rv);
+}
+
+
+static bool bout_content_matches(const file_mem &fm, bool report_status)
+{
+ bool is_same = true;
+
+ // compare the old data vs the new data
+ if (cpd.bout->size() != fm.raw.size())
+ {
+ if (report_status)
+ {
+ fprintf(stderr, "FAIL: %s (File size changed from %u to %u)\n",
+ cpd.filename.c_str(), static_cast<int>(fm.raw.size()),
+ static_cast<int>(cpd.bout->size()));
+ log_flush(true);
+ }
+ is_same = false;
+ }
+ else
+ {
+ for (int idx = 0; idx < static_cast<int>(fm.raw.size()); idx++)
+ {
+ if (fm.raw[idx] != (*cpd.bout)[idx])
+ {
+ if (report_status)
+ {
+ fprintf(stderr, "FAIL: %s (Difference at byte %u)\n",
+ cpd.filename.c_str(), idx);
+ log_flush(true);
+ }
+ is_same = false;
+ break;
+ }
+ }
+ }
+
+ if ( is_same
+ && report_status)
+ {
+ fprintf(stdout, "PASS: %s (%u bytes)\n",
+ cpd.filename.c_str(), static_cast<int>(fm.raw.size()));
+ }
+ return(is_same);
+} // bout_content_matches
+
+
+static void do_source_file(const char *filename_in,
+ const char *filename_out,
+ const char *parsed_file,
+ const char *dump_file,
+ bool no_backup,
+ bool keep_mtime)
+{
+ FILE *pfout = nullptr;
+ bool did_open = false;
+ bool need_backup = false;
+ file_mem fm;
+ string filename_tmp;
+
+ // Do some simple language detection based on the filename extension
+ if ( !cpd.lang_forced
+ || cpd.lang_flags == 0)
+ {
+ cpd.lang_flags = language_flags_from_filename(filename_in);
+ }
+
+ // Try to read in the source file
+ if (load_mem_file(filename_in, fm) < 0)
+ {
+ LOG_FMT(LERR, "Failed to load (%s)\n", filename_in);
+ cpd.error_count++;
+ return;
+ }
+ LOG_FMT(LSYS, "%s(%d): Parsing: %s as language %s\n",
+ __func__, __LINE__, filename_in, language_name_from_flags(cpd.lang_flags));
+
+ // check keyword sort
+ assert(keywords_are_sorted());
+
+ // Issue #3353
+ init_keywords_for_language();
+
+ cpd.filename = filename_in;
+
+ /*
+ * If we're only going to write on an actual change, then build the output
+ * buffer now and if there were changes, run it through the normal file
+ * write path.
+ *
+ * Future: many code paths could be simplified if 'bout' were always used and not
+ * optionally selected in just for do_check and if_changed.
+ */
+ if (cpd.if_changed)
+ {
+ /*
+ * Cleanup is deferred because we need 'bout' preserved long enough
+ * to write it to a file (if it changed).
+ */
+ uncrustify_file(fm, nullptr, parsed_file, dump_file, true);
+
+ if (bout_content_matches(fm, false))
+ {
+ uncrustify_end();
+ return;
+ }
+ }
+
+ if (!cpd.do_check)
+ {
+ if (filename_out == nullptr)
+ {
+ pfout = stdout;
+ }
+ else
+ {
+ // If the out file is the same as the in file, then use a temp file
+ filename_tmp = filename_out;
+
+ if (strcmp(filename_in, filename_out) == 0)
+ {
+ // Create 'outfile.uncrustify'
+ filename_tmp = fix_filename(filename_out);
+
+ if (!no_backup)
+ {
+ if (backup_copy_file(filename_in, fm.raw) != EX_OK)
+ {
+ LOG_FMT(LERR, "%s: Failed to create backup file for %s\n",
+ __func__, filename_in);
+ cpd.error_count++;
+ return;
+ }
+ need_backup = true;
+ }
+ }
+ make_folders(filename_tmp);
+
+ pfout = fopen(filename_tmp.c_str(), "wb");
+
+ if (pfout == nullptr)
+ {
+ LOG_FMT(LERR, "%s: Unable to create %s: %s (%d)\n",
+ __func__, filename_tmp.c_str(), strerror(errno), errno);
+ cpd.error_count++;
+ return;
+ }
+ did_open = true;
+ //LOG_FMT(LSYS, "Output file %s\n", filename_out);
+ }
+ }
+
+ if (cpd.if_changed)
+ {
+ for (deque<UINT8>::const_iterator i = cpd.bout->begin(), end = cpd.bout->end(); i != end; ++i)
+ {
+ fputc(*i, pfout);
+ }
+
+ uncrustify_end();
+ }
+ else
+ {
+ uncrustify_file(fm, pfout, parsed_file, dump_file);
+ }
+
+ if (did_open)
+ {
+ fclose(pfout);
+
+ if (need_backup)
+ {
+ backup_create_md5_file(filename_in);
+ }
+
+ if (filename_tmp != filename_out)
+ {
+ // We need to compare and then do a rename (but avoid redundant test when if_changed set)
+ if ( !cpd.if_changed
+ && file_content_matches(filename_tmp, filename_out))
+ {
+ // No change - remove tmp file
+ UNUSED(unlink(filename_tmp.c_str()));
+ }
+ else
+ {
+ // Change - rename filename_tmp to filename_out
+
+#ifdef WIN32
+ /*
+ * Atomic rename in windows can't go through stdio rename() func because underneath
+ * it calls MoveFileExW without MOVEFILE_REPLACE_EXISTING.
+ */
+ if (!MoveFileEx(filename_tmp.c_str(), filename_out, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
+#else
+ if (rename(filename_tmp.c_str(), filename_out) != 0)
+#endif
+ {
+ LOG_FMT(LERR, "%s: Unable to rename '%s' to '%s'\n",
+ __func__, filename_tmp.c_str(), filename_out);
+ cpd.error_count++;
+ }
+ }
+ }
+
+ if (keep_mtime)
+ {
+#ifdef HAVE_UTIME_H
+ // update mtime -- don't care if it fails
+ fm.utb.actime = time(nullptr);
+ UNUSED(utime(filename_in, &fm.utb));
+#endif
+ }
+ }
+} // do_source_file
+
+
+static void add_file_header()
+{
+ // don't add the file header if running as frag
+ if ( !Chunk::GetHead()->IsComment()
+ && !cpd.frag)
+ {
+ // TODO: detect the typical #ifndef FOO / #define FOO sequence
+ tokenize(cpd.file_hdr.data, Chunk::GetHead());
+ }
+}
+
+
+static void add_file_footer()
+{
+ Chunk *pc = Chunk::GetTail();
+
+ // Back up if the file ends with a newline
+ if ( pc->IsNotNullChunk()
+ && chunk_is_newline(pc))
+ {
+ pc = pc->GetPrev();
+ }
+
+ if ( pc->IsNotNullChunk()
+ && ( !pc->IsComment()
+ || !chunk_is_newline(pc->GetPrev())))
+ {
+ pc = Chunk::GetTail();
+
+ if (!chunk_is_newline(pc))
+ {
+ LOG_FMT(LSYS, "Adding a newline at the end of the file\n");
+ newline_add_after(pc);
+ }
+ tokenize(cpd.file_ftr.data, nullptr);
+ }
+}
+
+
+static void add_func_header(E_Token type, file_mem &fm)
+{
+ Chunk *pc;
+ Chunk *ref;
+ Chunk *tmp;
+ bool do_insert;
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnlNpp())
+ {
+ if (pc->type != type)
+ {
+ continue;
+ }
+ log_rule_B("cmt_insert_before_inlines");
+
+ if ( pc->flags.test(PCF_IN_CLASS)
+ && !options::cmt_insert_before_inlines())
+ {
+ continue;
+ }
+ // Check for one liners for classes. Declarations only. Walk down the chunks.
+ ref = pc;
+
+ if ( chunk_is_token(ref, CT_CLASS)
+ && get_chunk_parent_type(ref) == CT_NONE
+ && ref->GetNext())
+ {
+ ref = ref->GetNext();
+
+ if ( chunk_is_token(ref, CT_TYPE)
+ && get_chunk_parent_type(ref) == type
+ && ref->GetNext())
+ {
+ ref = ref->GetNext();
+
+ if ( chunk_is_token(ref, CT_SEMICOLON)
+ && ref->level == pc->level)
+ {
+ continue;
+ }
+ }
+ }
+ // Check for one liners for functions. There'll be a closing brace w/o any newlines. Walk down the chunks.
+ ref = pc;
+
+ if ( chunk_is_token(ref, CT_FUNC_DEF)
+ && get_chunk_parent_type(ref) == CT_NONE
+ && ref->GetNext())
+ {
+ int found_brace = 0; // Set if a close brace is found before a newline
+
+ while ( ref->type != CT_NEWLINE
+ && (ref = ref->GetNext())) // TODO: is the assignment of ref wanted here?, better move it to the loop
+ {
+ if (chunk_is_token(ref, CT_BRACE_CLOSE))
+ {
+ found_brace = 1;
+ break;
+ }
+ }
+
+ if (found_brace)
+ {
+ continue;
+ }
+ }
+ do_insert = false;
+
+ /*
+ * On a function proto or def. Back up to a close brace or semicolon on
+ * the same level
+ */
+ ref = pc;
+
+ while ( (ref = ref->GetPrev())
+ && ref->IsNotNullChunk())
+ {
+ // Bail if we change level or find an access specifier colon
+ if ( ref->level != pc->level
+ || chunk_is_token(ref, CT_ACCESS_COLON))
+ {
+ do_insert = true;
+ break;
+ }
+
+ // If we hit an angle close, back up to the angle open
+ if (chunk_is_token(ref, CT_ANGLE_CLOSE))
+ {
+ ref = ref->GetPrevType(CT_ANGLE_OPEN, ref->level, E_Scope::PREPROC);
+ continue;
+ }
+
+ // Bail if we hit a preprocessor and cmt_insert_before_preproc is false
+ if (ref->flags.test(PCF_IN_PREPROC))
+ {
+ tmp = ref->GetPrevType(CT_PREPROC, ref->level);
+
+ if ( tmp->IsNotNullChunk()
+ && get_chunk_parent_type(tmp) == CT_PP_IF)
+ {
+ tmp = tmp->GetPrevNnl();
+
+ log_rule_B("cmt_insert_before_preproc");
+
+ if ( tmp->IsComment()
+ && !options::cmt_insert_before_preproc())
+ {
+ break;
+ }
+ }
+ }
+
+ // Ignore 'right' comments
+ if ( ref->IsComment()
+ && chunk_is_newline(ref->GetPrev()))
+ {
+ break;
+ }
+
+ if ( ref->level == pc->level
+ && ( ref->flags.test(PCF_IN_PREPROC)
+ || chunk_is_token(ref, CT_SEMICOLON)
+ || chunk_is_token(ref, CT_BRACE_CLOSE)))
+ {
+ do_insert = true;
+ break;
+ }
+ }
+
+ if ( ref->IsNullChunk()
+ && !Chunk::GetHead()->IsComment()
+ && get_chunk_parent_type(Chunk::GetHead()) == type)
+ {
+ /**
+ * In addition to testing for preceding semicolons, closing braces, etc.,
+ * we need to also account for the possibility that the function declaration
+ * or definition occurs at the very beginning of the file
+ */
+ tokenize(fm.data, Chunk::GetHead());
+ }
+ else if (do_insert)
+ {
+ // Insert between after and ref
+ Chunk *after = ref->GetNextNcNnl();
+ tokenize(fm.data, after);
+
+ for (tmp = ref->GetNext(); tmp != after; tmp = tmp->GetNext())
+ {
+ tmp->level = after->level;
+ }
+ }
+ }
+} // add_func_header
+
+
+static void add_msg_header(E_Token type, file_mem &fm)
+{
+ Chunk *pc;
+ Chunk *ref;
+ Chunk *tmp;
+ bool do_insert;
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnlNpp())
+ {
+ if (pc->type != type)
+ {
+ continue;
+ }
+ do_insert = false;
+
+ /*
+ * On a message declaration back up to a Objective-C scope
+ * the same level
+ */
+ ref = pc;
+
+ while ( (ref = ref->GetPrev()) != nullptr
+ && ref->IsNotNullChunk())
+ {
+ // ignore the CT_TYPE token that is the result type
+ if ( ref->level != pc->level
+ && ( chunk_is_token(ref, CT_TYPE)
+ || chunk_is_token(ref, CT_PTR_TYPE)))
+ {
+ continue;
+ }
+
+ // If we hit a parentheses around return type, back up to the open parentheses
+ if (chunk_is_token(ref, CT_PAREN_CLOSE))
+ {
+ ref = ref->GetPrevType(CT_PAREN_OPEN, ref->level, E_Scope::PREPROC);
+ continue;
+ }
+
+ // Bail if we hit a preprocessor and cmt_insert_before_preproc is false
+ if (ref->flags.test(PCF_IN_PREPROC))
+ {
+ tmp = ref->GetPrevType(CT_PREPROC, ref->level);
+
+ if ( tmp->IsNotNullChunk()
+ && get_chunk_parent_type(tmp) == CT_PP_IF)
+ {
+ tmp = tmp->GetPrevNnl();
+
+ log_rule_B("cmt_insert_before_preproc");
+
+ if ( tmp->IsComment()
+ && !options::cmt_insert_before_preproc())
+ {
+ break;
+ }
+ }
+ }
+
+ if ( ref->level == pc->level
+ && ( ref->flags.test(PCF_IN_PREPROC)
+ || chunk_is_token(ref, CT_OC_SCOPE)))
+ {
+ ref = ref->GetPrev();
+
+ if (ref->IsNotNullChunk())
+ {
+ // Ignore 'right' comments
+ if ( chunk_is_newline(ref)
+ && ref->GetPrev()->IsComment())
+ {
+ break;
+ }
+ do_insert = true;
+ }
+ break;
+ }
+ }
+
+ if (do_insert)
+ {
+ // Insert between after and ref
+ Chunk *after = ref->GetNextNcNnl();
+ tokenize(fm.data, after);
+
+ for (tmp = ref->GetNext(); tmp != after; tmp = tmp->GetNext())
+ {
+ tmp->level = after->level;
+ }
+ }
+ }
+} // add_msg_header
+
+
+static void uncrustify_start(const deque<int> &data)
+{
+ // Parse the text into chunks
+ tokenize(data, nullptr);
+ PROT_THE_LINE
+
+ cpd.unc_stage = unc_stage_e::HEADER;
+
+ // Get the column for the fragment indent
+ if (cpd.frag)
+ {
+ Chunk *pc = Chunk::GetHead();
+
+ cpd.frag_cols = pc->orig_col;
+ }
+
+ // Add the file header
+ if (!cpd.file_hdr.data.empty())
+ {
+ add_file_header();
+ }
+
+ // Add the file footer
+ if (!cpd.file_ftr.data.empty())
+ {
+ add_file_footer();
+ }
+ /*
+ * Change certain token types based on simple sequence.
+ * Example: change '[' + ']' to '[]'
+ * Note that level info is not yet available, so it is OK to do all
+ * processing that doesn't need to know level info. (that's very little!)
+ */
+ tokenize_cleanup();
+
+ /*
+ * Detect the brace and paren levels and insert virtual braces.
+ * This handles all that nasty preprocessor stuff
+ */
+ brace_cleanup();
+
+ parameter_pack_cleanup();
+
+ // At this point, the level information is available and accurate.
+
+ if (language_is_set(LANG_PAWN))
+ {
+ pawn_prescan();
+ }
+ // Re-type chunks, combine chunks
+ fix_symbols();
+ tokenize_trailing_return_types();
+
+ mark_comments();
+
+ // Look at all colons ':' and mark labels, :? sequences, etc.
+ combine_labels();
+
+ enum_cleanup();
+} // uncrustify_start
+
+
+void uncrustify_file(const file_mem &fm, FILE *pfout, const char *parsed_file,
+ const char *dump_file, bool defer_uncrustify_end)
+{
+ const deque<int> &data = fm.data;
+
+ // Save off the encoding and whether a BOM is required
+ cpd.bom = fm.bom;
+ cpd.enc = fm.enc;
+
+ log_rule_B("utf8_force");
+ log_rule_B("utf8_byte");
+
+ if ( options::utf8_force()
+ || ( (cpd.enc == char_encoding_e::e_BYTE)
+ && options::utf8_byte()))
+ {
+ cpd.enc = char_encoding_e::e_UTF8;
+ }
+ iarf_e av;
+
+ switch (cpd.enc)
+ {
+ case char_encoding_e::e_UTF8:
+ log_rule_B("utf8_bom");
+ av = options::utf8_bom();
+ break;
+
+ case char_encoding_e::e_UTF16_LE:
+ case char_encoding_e::e_UTF16_BE:
+ av = IARF_FORCE;
+ break;
+
+ default:
+ av = IARF_IGNORE;
+ break;
+ }
+
+ if (av == IARF_REMOVE)
+ {
+ cpd.bom = false;
+ }
+ else if (av != IARF_IGNORE)
+ {
+ cpd.bom = true;
+ }
+ // Check for embedded 0's (represents a decoding failure or corrupt file)
+ size_t count_line = 1;
+ size_t count_column = 1;
+
+ for (int idx = 0; idx < static_cast<int>(data.size()) - 1; idx++)
+ {
+ if (data[idx] == 0)
+ {
+ LOG_FMT(LERR, "An embedded 0 was found in '%s' %zu:%zu.\n",
+ cpd.filename.c_str(), count_line, count_column);
+ LOG_FMT(LERR, "The file may be encoded in an unsupported Unicode format.\n");
+ LOG_FMT(LERR, "Aborting.\n");
+ cpd.error_count++;
+ return;
+ }
+ count_column++;
+
+ if (data[idx] == '\n')
+ {
+ count_line++;
+ count_column = 1;
+ }
+ }
+
+ uncrustify_start(data);
+ dump_step(dump_file, "After uncrustify_start()");
+
+ cpd.unc_stage = unc_stage_e::OTHER;
+
+ /*
+ * Done with detection. Do the rest only if the file will go somewhere.
+ * The detection code needs as few changes as possible.
+ */
+ {
+ // Add comments before function defs and classes
+ if (!cpd.func_hdr.data.empty())
+ {
+ add_func_header(CT_FUNC_DEF, cpd.func_hdr);
+
+ log_rule_B("cmt_insert_before_ctor_dtor");
+
+ if (options::cmt_insert_before_ctor_dtor())
+ {
+ add_func_header(CT_FUNC_CLASS_DEF, cpd.func_hdr);
+ }
+ }
+
+ if (!cpd.class_hdr.data.empty())
+ {
+ add_func_header(CT_CLASS, cpd.class_hdr);
+ }
+
+ if (!cpd.oc_msg_hdr.data.empty())
+ {
+ add_msg_header(CT_OC_MSG_DECL, cpd.oc_msg_hdr);
+ }
+ do_parent_for_pp();
+ do_braces(); // Change virtual braces into real braces...
+
+ // Scrub extra semicolons
+ log_rule_B("mod_remove_extra_semicolon");
+
+ if (options::mod_remove_extra_semicolon())
+ {
+ remove_extra_semicolons();
+ }
+ // Remove unnecessary returns
+ log_rule_B("mod_remove_empty_return");
+
+ if (options::mod_remove_empty_return())
+ {
+ remove_extra_returns();
+ }
+ // Remove duplicate include
+ log_rule_B("mod_duplicate_include");
+
+ if (options::mod_remove_duplicate_include())
+ {
+ remove_duplicate_include();
+ }
+ // Add parens
+ do_parens();
+ do_parens_assign();
+ do_parens_return();
+
+ // Modify line breaks as needed
+ bool first = true;
+ int old_changes;
+
+ log_rule_B("nl_remove_extra_newlines");
+
+ if (options::nl_remove_extra_newlines() == 2)
+ {
+ newlines_remove_newlines();
+ }
+ cpd.pass_count = 3;
+
+ dump_step(dump_file, "Before first while loop");
+
+ do
+ {
+ old_changes = cpd.changes;
+
+ LOG_FMT(LNEWLINE, "Newline loop start: %d\n", cpd.changes);
+
+ annotations_newlines();
+ newlines_cleanup_dup();
+ newlines_sparens();
+ newlines_cleanup_braces(first);
+ newlines_cleanup_angles(); // Issue #1167
+
+ log_rule_B("nl_after_multiline_comment");
+
+ if (options::nl_after_multiline_comment())
+ {
+ newline_after_multiline_comment();
+ }
+ log_rule_B("nl_after_label_colon");
+
+ if (options::nl_after_label_colon())
+ {
+ newline_after_label_colon();
+ }
+ newlines_insert_blank_lines();
+
+ log_rule_B("pos_bool");
+
+ if (options::pos_bool() != TP_IGNORE)
+ {
+ newlines_chunk_pos(CT_BOOL, options::pos_bool());
+ }
+ log_rule_B("pos_compare");
+
+ if (options::pos_compare() != TP_IGNORE)
+ {
+ newlines_chunk_pos(CT_COMPARE, options::pos_compare());
+ }
+ log_rule_B("pos_conditional");
+
+ if (options::pos_conditional() != TP_IGNORE)
+ {
+ newlines_chunk_pos(CT_COND_COLON, options::pos_conditional());
+ newlines_chunk_pos(CT_QUESTION, options::pos_conditional());
+ }
+ log_rule_B("pos_comma");
+ log_rule_B("pos_enum_comma");
+
+ if ( options::pos_comma() != TP_IGNORE
+ || options::pos_enum_comma() != TP_IGNORE)
+ {
+ newlines_chunk_pos(CT_COMMA, options::pos_comma());
+ }
+ log_rule_B("pos_assign");
+
+ if (options::pos_assign() != TP_IGNORE)
+ {
+ newlines_chunk_pos(CT_ASSIGN, options::pos_assign());
+ }
+ log_rule_B("pos_arith");
+
+ if (options::pos_arith() != TP_IGNORE)
+ {
+ newlines_chunk_pos(CT_ARITH, options::pos_arith());
+ newlines_chunk_pos(CT_CARET, options::pos_arith());
+ }
+ log_rule_B("pos_shift");
+
+ if (options::pos_shift() != TP_IGNORE)
+ {
+ newlines_chunk_pos(CT_SHIFT, options::pos_shift());
+ }
+ newlines_class_colon_pos(CT_CLASS_COLON);
+ newlines_class_colon_pos(CT_CONSTR_COLON);
+
+ log_rule_B("nl_squeeze_ifdef");
+
+ if (options::nl_squeeze_ifdef())
+ {
+ newlines_squeeze_ifdef();
+ }
+ log_rule_B("nl_squeeze_paren_close");
+
+ if (options::nl_squeeze_paren_close())
+ {
+ newlines_squeeze_paren_close();
+ }
+ do_blank_lines();
+ newlines_eat_start_end();
+ newlines_functions_remove_extra_blank_lines();
+ newlines_cleanup_dup();
+ first = false;
+ dump_step(dump_file, "Inside first while loop");
+ } while ( old_changes != cpd.changes
+ && cpd.pass_count-- > 0);
+
+ mark_comments();
+
+ // Add balanced spaces around nested params
+ log_rule_B("sp_balance_nested_parens");
+
+ if (options::sp_balance_nested_parens())
+ {
+ space_text_balance_nested_parens();
+ }
+ // Scrub certain added semicolons
+ log_rule_B("mod_pawn_semicolon");
+
+ if ( language_is_set(LANG_PAWN)
+ && options::mod_pawn_semicolon())
+ {
+ pawn_scrub_vsemi();
+ }
+ // Sort imports/using/include
+ log_rule_B("mod_sort_import");
+ log_rule_B("mod_sort_include");
+ log_rule_B("mod_sort_using");
+
+ if ( options::mod_sort_import()
+ || options::mod_sort_include()
+ || options::mod_sort_using())
+ {
+ sort_imports();
+ }
+ // Fix same-line inter-chunk spacing
+ space_text();
+
+ // Do any aligning of preprocessors
+ log_rule_B("align_pp_define_span");
+
+ if (options::align_pp_define_span() > 0)
+ {
+ align_preprocessor();
+ }
+ // Indent the text
+ indent_preproc();
+ indent_text();
+
+ // Insert trailing comments after certain close braces
+ log_rule_B("mod_add_long_switch_closebrace_comment");
+ log_rule_B("mod_add_long_function_closebrace_comment");
+ log_rule_B("mod_add_long_class_closebrace_comment");
+ log_rule_B("mod_add_long_namespace_closebrace_comment");
+
+ if ( (options::mod_add_long_switch_closebrace_comment() > 0)
+ || (options::mod_add_long_function_closebrace_comment() > 0)
+ || (options::mod_add_long_class_closebrace_comment() > 0)
+ || (options::mod_add_long_namespace_closebrace_comment() > 0))
+ {
+ add_long_closebrace_comment();
+ }
+ // Insert trailing comments after certain preprocessor conditional blocks
+ log_rule_B("mod_add_long_ifdef_else_comment");
+ log_rule_B("mod_add_long_ifdef_endif_comment");
+
+ if ( (options::mod_add_long_ifdef_else_comment() > 0)
+ || (options::mod_add_long_ifdef_endif_comment() > 0))
+ {
+ add_long_preprocessor_conditional_block_comment();
+ }
+ // Align everything else, reindent and break at code_width
+ first = true;
+
+ dump_step(dump_file, "Before second while loop");
+
+ do
+ {
+ align_all();
+ indent_text();
+ old_changes = cpd.changes;
+
+ log_rule_B("code_width");
+
+ if (options::code_width() > 0)
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): Code_width loop start: %d\n",
+ __func__, __LINE__, cpd.changes);
+ log_rule_B("debug_max_number_of_loops");
+
+ if (options::debug_max_number_of_loops() > 0)
+ {
+ if (cpd.changes > options::debug_max_number_of_loops()) // Issue #2432
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): too many loops. Make a report, please.\n",
+ __func__, __LINE__);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ }
+ do_code_width();
+
+ if ( old_changes != cpd.changes
+ && first)
+ {
+ // retry line breaks caused by splitting 1-liners
+ newlines_cleanup_braces(false);
+ newlines_insert_blank_lines();
+ newlines_functions_remove_extra_blank_lines();
+ newlines_remove_disallowed();
+ first = false;
+ }
+ }
+ dump_step(dump_file, "Inside second while loop");
+ } while (old_changes != cpd.changes);
+
+ // And finally, align the backslash newline stuff
+ align_right_comments();
+
+ log_rule_B("align_nl_cont");
+
+ if (options::align_nl_cont())
+ {
+ align_backslash_newline();
+ }
+ dump_step(dump_file, "Final version");
+
+ // which output is to be done?
+ if (cpd.html_file == nullptr)
+ {
+ // Now render it all to the output file
+ output_text(pfout);
+ }
+ else
+ {
+ // create the tracking file
+ FILE *t_file;
+ t_file = fopen(cpd.html_file, "wb");
+
+ if (t_file)
+ {
+ output_text(t_file);
+ fclose(t_file);
+ exit(EX_OK);
+ }
+ exit(EX_USAGE);
+ }
+ }
+
+ // Special hook for dumping parsed data for debugging
+ if (parsed_file != nullptr)
+ {
+ FILE *p_file;
+
+ if ( parsed_file[0] == '-'
+ && !parsed_file[1])
+ {
+ p_file = stdout;
+ }
+ else
+ {
+ p_file = fopen(parsed_file, "wb");
+ }
+
+ if (p_file != nullptr)
+ {
+ if (ends_with(parsed_file, ".csv", false))
+ {
+ output_parsed_csv(p_file);
+ }
+ else
+ {
+ output_parsed(p_file);
+ }
+
+ if (p_file != stdout)
+ {
+ fclose(p_file);
+ }
+ }
+ else
+ {
+ LOG_FMT(LERR, "%s: Failed to open '%s' for write: %s (%d)\n",
+ __func__, parsed_file, strerror(errno), errno);
+ cpd.error_count++;
+ }
+ }
+
+ if ( cpd.do_check
+ && !bout_content_matches(fm, true))
+ {
+ cpd.check_fail_cnt++;
+ }
+
+ if (!defer_uncrustify_end)
+ {
+ uncrustify_end();
+ }
+} // uncrustify_file
+
+
+void uncrustify_end()
+{
+ // Free all the memory
+ Chunk *pc;
+
+ cpd.unc_stage = unc_stage_e::CLEANUP;
+
+ while ((pc = Chunk::GetHead())->IsNotNullChunk())
+ {
+ chunk_del(pc);
+ }
+
+ if (cpd.bout)
+ {
+ cpd.bout->clear();
+ }
+ // Clean up some state variables
+ cpd.unc_off = false;
+ cpd.al_cnt = 0;
+ cpd.did_newline = true;
+ cpd.pp_level = 0;
+ cpd.changes = 0;
+ cpd.in_preproc = CT_NONE;
+ memset(cpd.le_counts, 0, sizeof(cpd.le_counts));
+ cpd.preproc_ncnl_count = 0;
+ cpd.ifdef_over_whole_file = 0;
+ cpd.warned_unable_string_replace_tab_chars = false;
+}
+
+
+const char *get_token_name(E_Token token)
+{
+ if ( token >= 0
+ && (token < static_cast<int> ARRAY_SIZE(token_names))
+ && (token_names[token] != nullptr))
+ {
+ return(token_names[token]);
+ }
+ return("???");
+}
+
+
+E_Token find_token_name(const char *text)
+{
+ if ( text != nullptr
+ && (*text != 0))
+ {
+ for (int idx = 1; idx < static_cast<int> ARRAY_SIZE(token_names); idx++)
+ {
+ if (strcasecmp(text, token_names[idx]) == 0)
+ {
+ return(static_cast<E_Token>(idx));
+ }
+ }
+ }
+ return(CT_NONE);
+}
+
+
+static bool ends_with(const char *filename, const char *tag, bool case_sensitive = true)
+{
+ int len1 = strlen(filename);
+ int len2 = strlen(tag);
+
+ return( len2 <= len1
+ && ( ( case_sensitive
+ && (strcmp(&filename[len1 - len2], tag) == 0))
+ || ( !case_sensitive
+ && (strcasecmp(&filename[len1 - len2], tag) == 0))));
+}
+
+
+struct lang_name_t
+{
+ const char *name;
+ size_t lang;
+};
+
+static lang_name_t language_names[] =
+{
+ { "C", LANG_C }, // 0x0001
+ { "CPP", LANG_CPP }, // 0x0002
+ { "D", LANG_D }, // 0x0004
+ { "CS", LANG_CS }, // 0x0008
+ { "JAVA", LANG_JAVA }, // 0x0010
+ { "OC", LANG_OC }, // 0x0020
+ { "VALA", LANG_VALA }, // 0x0040
+ { "PAWN", LANG_PAWN }, // 0x0080
+ { "ECMA", LANG_ECMA }, // 0x0100
+ { "OC+", LANG_OC | LANG_CPP }, // 0x0020 + 0x0002
+ { "CS+", LANG_CS | LANG_CPP }, // 0x0008 + 0x0002
+ { "C-Header", LANG_C | LANG_CPP | FLAG_HDR }, // 0x0001 + 0x0002 + 0x2000 = 0x2022
+};
+
+
+static size_t language_flags_from_name(const char *name)
+{
+ for (const auto &language : language_names)
+ {
+ if (strcasecmp(name, language.name) == 0)
+ {
+ return(language.lang);
+ }
+ }
+
+ return(0);
+}
+
+
+const char *language_name_from_flags(size_t lang)
+{
+ // Check for an exact match first
+ for (auto &language_name : language_names)
+ {
+ if (language_name.lang == lang)
+ {
+ return(language_name.name);
+ }
+ }
+
+ // Check for the first set language bit
+ for (auto &language_name : language_names)
+ {
+ if ((language_name.lang & lang) != 0)
+ {
+ return(language_name.name);
+ }
+ }
+
+ return("???");
+}
+
+
+//! type to map a programming language to a typically used filename extension
+struct lang_ext_t
+{
+ const char *ext; //! filename extension typically used for ...
+ const char *name; //! a programming language
+};
+
+//! known filename extensions linked to the corresponding programming language
+struct lang_ext_t language_exts[] =
+{
+ { ".c", "C" },
+ { ".c++", "CPP" },
+ { ".cc", "CPP" },
+ { ".cp", "CPP" },
+ { ".cpp", "CPP" },
+ { ".cs", "CS" },
+ { ".cxx", "CPP" },
+ { ".d", "D" },
+ { ".di", "D" },
+ { ".es", "ECMA" },
+ { ".h", "C-Header" },
+ { ".h++", "CPP" },
+ { ".hh", "CPP" },
+ { ".hp", "CPP" },
+ { ".hpp", "CPP" },
+ { ".hxx", "CPP" },
+ { ".inl", "PAWN" },
+ { ".java", "JAVA" },
+ { ".js", "ECMA" },
+ { ".m", "OC" },
+ { ".mm", "OC+" },
+ { ".p", "PAWN" },
+ { ".pawn", "PAWN" },
+ { ".sma", "PAWN" },
+ { ".sqc", "C" }, // embedded SQL
+ { ".sql", "SQL" },
+ { ".vala", "VALA" },
+};
+
+
+const char *get_file_extension(int &idx)
+{
+ const char *val = nullptr;
+
+ if (idx < static_cast<int> ARRAY_SIZE(language_exts))
+ {
+ val = language_exts[idx].ext;
+ }
+ idx++;
+ return(val);
+}
+
+
+typedef std::map<string, string> extension_map_t;
+/**
+ * maps a file extension to a language flag.
+ *
+ * @note The "." need to be included, as in ".c". The file extensions
+ * ARE case sensitive.
+ */
+static extension_map_t g_ext_map;
+
+
+const char *extension_add(const char *ext_text, const char *lang_text)
+{
+ size_t lang_flags = language_flags_from_name(lang_text);
+
+ if (lang_flags)
+ {
+ const char *lang_name = language_name_from_flags(lang_flags);
+ g_ext_map[string(ext_text)] = lang_name;
+ return(lang_name);
+ }
+ return(nullptr);
+}
+
+
+void print_extensions(FILE *pfile)
+{
+ for (auto &language : language_names)
+ {
+ bool did_one = false;
+
+ for (auto &extension_val : g_ext_map)
+ {
+ if (strcmp(extension_val.second.c_str(), language.name) == 0)
+ {
+ if (!did_one)
+ {
+ fprintf(pfile, "file_ext %s", extension_val.second.c_str());
+ did_one = true;
+ }
+ fprintf(pfile, " %s", extension_val.first.c_str());
+ }
+ }
+
+ if (did_one)
+ {
+ fprintf(pfile, "\n");
+ }
+ }
+}
+
+
+// TODO: better use enum lang_t for source file language
+static size_t language_flags_from_filename(const char *filename)
+{
+ // check custom extensions first
+ for (const auto &extension_val : g_ext_map)
+ {
+ if (ends_with(filename, extension_val.first.c_str()))
+ {
+ return(language_flags_from_name(extension_val.second.c_str()));
+ }
+ }
+
+ for (auto &language : language_exts)
+ {
+ if (ends_with(filename, language.ext))
+ {
+ return(language_flags_from_name(language.name));
+ }
+ }
+
+ // check again without case sensitivity
+ for (auto &extension_val : g_ext_map)
+ {
+ if (ends_with(filename, extension_val.first.c_str(), false))
+ {
+ return(language_flags_from_name(extension_val.second.c_str()));
+ }
+ }
+
+ for (auto &language : language_exts)
+ {
+ if (ends_with(filename, language.ext, false))
+ {
+ return(language_flags_from_name(language.name));
+ }
+ }
+
+ return(LANG_C);
+} // language_flags_from_filename
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.h
new file mode 100644
index 00000000..1f85b993
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify.h
@@ -0,0 +1,99 @@
+/**
+ * @file uncrustify.h
+ * prototypes for uncrustify.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef UNCRUSTIFY_H_INCLUDED
+#define UNCRUSTIFY_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+#include <stdio.h>
+
+int load_header_files(void);
+
+
+void uncrustify_file(const file_mem &fm, FILE *pfout, const char *parsed_file, const char *dump_filename, bool defer_uncrustify_end = false);
+
+
+void uncrustify_end();
+
+
+const char *get_token_name(E_Token token);
+
+
+/**
+ * Gets the tag text for a language
+ *
+ * @param lang The LANG_xxx enum
+ *
+ * @return A string
+ */
+const char *language_name_from_flags(size_t lang);
+
+
+/**
+ * Grab the token id for the text.
+ *
+ * @return token, will be CT_NONE on failure to match
+ */
+E_Token find_token_name(const char *text);
+
+std::string pcf_flags_str(pcf_flags_t flags);
+
+
+void log_pcf_flags(log_sev_t sev, pcf_flags_t flags);
+
+
+/**
+ * Replace the brain-dead and non-portable basename().
+ * Returns a pointer to the character after the last '/'.
+ * The returned value always points into path, unless path is nullptr.
+ *
+ * Input Returns
+ * nullptr => ""
+ * "/some/path/" => ""
+ * "/some/path" => "path"
+ * "afile" => "afile"
+ *
+ * @param path The path to look at
+ *
+ * @return Pointer to the character after the last path separator
+ */
+const char *path_basename(const char *path);
+
+
+/**
+ * Returns the length of the directory part of the filename.
+ *
+ * @param filename filename including full path
+ *
+ * @return character size of path
+ */
+int path_dirname_len(const char *filename);
+
+
+void usage(const char *argv0);
+
+
+void usage_error(const char *msg = nullptr);
+
+
+/**
+ * Set idx = 0 before the first call.
+ * Done when returns nullptr
+ */
+const char *get_file_extension(int &idx);
+
+
+//! Prints custom file extensions to the file
+void print_extensions(FILE *pfile);
+
+
+const char *extension_add(const char *ext_text, const char *lang_text);
+
+
+#endif /* UNCRUSTIFY_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_emscripten.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_emscripten.cpp
new file mode 100644
index 00000000..a336fea4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_emscripten.cpp
@@ -0,0 +1,1218 @@
+/*
+ * uncrustify_emscripten.cpp - JavaScript Emscripten binding interface
+ *
+ * Created on: May 8, 2016
+ * Author: Daniel Chumak
+ *
+ * INTERFACE:
+ * ============================================================================
+ * unsure about these:
+ * --check TODO ???
+ * --decode TODO ???
+ * --detect TODO needs uncrustify start and end which both are static
+ *
+ *
+ * will not be included:
+ * ----------------------------------------------------------------------------
+ * -t ( define via multiple --type )
+ * -d ( define via multiple --define )
+ * --assume ( no files available to guess the lang. based on the filename ending )
+ * --files ( no batch processing will be available )
+ * --prefix
+ * --suffix
+ * --assume
+ * --no-backup
+ * --replace
+ * --mtime
+ * --universalindent
+ * --ds/--dump-steps
+ * -help, -h, --usage, -?
+ *
+ *
+ * done:
+ * ----------------------------------------------------------------------------
+ * --update-config ( use show_config() )
+ * --update-config-with-doc ( show_config( bool withDoc = true ) )
+ * --version, -v ( use get_version() )
+ * --log, -L ( use log_type_enable( log_sev_t sev, bool value ) )
+ * -q ( use quiet() )
+ * --config, -c ( use loadConfig( string _cfg ) )
+ * --file, -f ( use uncrustify( string _file ) )
+ * --show ( use log_type_show_name( bool ) )
+ * --frag ( use uncrustify( string _file, bool frag = true ) )
+ * --type ( use add_keyword( string _type, E_Token type ) )
+ * -l ( use uncrustify() )
+ * --parsed, -p ( use debug() )
+ */
+
+
+#if defined (__linux__)
+
+
+#include "keywords.h"
+#include "log_levels.h"
+#include "logger.h"
+#include "option.h"
+#include "options.h"
+#include "output.h"
+#include "prototypes.h"
+#include "uncrustify.h"
+#include "uncrustify_version.h"
+#include "unicode.h"
+
+#include <iostream>
+#include <map>
+#include <memory>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unordered_map>
+#include <vector>
+
+
+#ifdef EMSCRIPTEN
+#include <emscripten/bind.h>
+#include <emscripten/val.h>
+using namespace emscripten;
+#else
+#define EMSCRIPTEN_BINDINGS(module) void dummyFcn()
+template<class T>
+struct base {};
+struct emscripten
+{
+ template<class... Args>
+ emscripten value(Args...) { return{}; }
+
+ template<class... Args>
+ static emscripten function(Args...) { return{}; }
+
+ template<class... Args>
+ emscripten property(Args...) { return{}; }
+};
+using Dummy = emscripten;
+
+
+template<class T>
+Dummy enum_(char const *const)
+{
+ return(Dummy{});
+}
+
+
+template<class T>
+Dummy register_vector(char const *const)
+{
+ return(Dummy{});
+}
+
+
+template<class... Args>
+Dummy class_(char const *const)
+{
+ return(Dummy{});
+}
+
+
+template<class T>
+Dummy select_overload(T)
+{
+ return(Dummy{});
+}
+#endif
+
+using namespace std;
+using namespace uncrustify;
+
+namespace
+{
+
+/**
+ * Loads options from a file represented as a single char array.
+ * Modifies: input char array, cpd.line_number
+ * Expects: \0 terminated char array
+ *
+ * @param configString char array that holds the whole config
+ * @return EXIT_SUCCESS on success
+ */
+int load_option_fileChar(char *configString)
+{
+ char *delimPos = &configString[0];
+ char *subStringStart = &configString[0];
+
+ cpd.line_number = 0;
+
+ // TODO: handle compat_level
+ int compat_level = 0;
+
+ while (true)
+ {
+ delimPos = strchr(delimPos, '\n');
+
+ if (delimPos == nullptr)
+ {
+ break;
+ }
+ // replaces \n with \0 -> string including multiple terminated substrings
+ *delimPos = '\0';
+
+
+ process_option_line(subStringStart, "", compat_level);
+
+ delimPos++;
+ subStringStart = delimPos;
+ }
+ //get last line, expectation: ends with \0
+ process_option_line(subStringStart, "", compat_level);
+
+ return(EXIT_SUCCESS);
+}
+
+
+/**
+ * adds a new keyword to Uncrustify's dynamic keyword map (dkwm, keywords.cpp)
+ *
+ * @param tag: keyword that is going to be added
+ * @param type: type of the keyword
+ */
+void _add_keyword(string tag, E_Token type)
+{
+ if (tag.empty())
+ {
+ LOG_FMT(LERR, "%s: input string is empty\n", __func__);
+ return;
+ }
+ add_keyword(tag, type);
+}
+
+
+//! clears Uncrustify's dynamic keyword map (dkwm, keywords.cpp)
+void clear_keywords()
+{
+ clear_keyword_file();
+}
+
+
+/**
+ * Show or hide the severity prefix "<1>"
+ *
+ * @param b: true=show, false=hide
+ */
+void show_log_type(bool b)
+{
+ log_show_sev(b);
+}
+
+
+//! returns the UNCRUSTIFY_VERSION string
+string get_version()
+{
+ return(UNCRUSTIFY_VERSION);
+}
+
+
+//! disables all logging messages
+void set_quiet()
+{
+ // set empty mask
+ log_set_mask({});
+}
+
+
+/**
+ * resets value of an option to its default
+ *
+ * @param name: name of the option
+ * @return options enum value of the found option or -1 if option was not found
+ */
+int reset_option(string name)
+{
+ if (name.empty())
+ {
+ LOG_FMT(LERR, "%s: name string is empty\n", __func__);
+ return(-1);
+ }
+ const auto option = find_option(name.c_str());
+
+ if (option == nullptr)
+ {
+ LOG_FMT(LERR, "Option %s not found\n", name.c_str());
+ return(-1);
+ }
+ option->reset();
+ return(0);
+}
+
+
+/**
+ * sets value of an option
+ *
+ * @param name: name of the option
+ * @param value: value that is going to be set
+ * @return options enum value of the found option or -1 if option was not found
+ */
+int set_option(string name, string value)
+{
+ if (name.empty())
+ {
+ LOG_FMT(LERR, "%s: name string is empty\n", __func__);
+ return(-1);
+ }
+
+ if (value.empty())
+ {
+ LOG_FMT(LERR, "%s: value string is empty\n", __func__);
+ return(-1);
+ }
+ const auto option = find_option(name.c_str());
+
+ if (option == nullptr)
+ {
+ LOG_FMT(LERR, "Option %s not found\n", name.c_str());
+ return(-1);
+ }
+
+ if (!option->read(value.c_str()))
+ {
+ LOG_FMT(
+ LERR,
+ "Failed to set value %s for option: %s of type: %s\n",
+ name.c_str(),
+ value.c_str(),
+ to_string(option->type())
+ );
+ return(-1);
+ }
+ return(0);
+}
+
+
+/**
+ * returns value of an option
+ *
+ * @param name: name of the option
+ * @return currently set value of the option
+ */
+string get_option(string name)
+{
+ if (name.empty())
+ {
+ LOG_FMT(LERR, "%s: input string is empty\n", __func__);
+ return("");
+ }
+ const auto option = find_option(name.c_str());
+
+ if (option == nullptr)
+ {
+ LOG_FMT(LWARN, "Option %s not found\n", name.c_str());
+ return("");
+ }
+ return(option->str());
+}
+
+
+/**
+ * returns the config file string based on the current configuration
+ *
+ * @param withDoc: false=without documentation,
+ * true=with documentation text lines
+ * @param only_not_default: false=containing all options,
+ * true=containing only options with non default values
+ * @return returns the config file string based on the current configuration
+ */
+string show_config(bool withDoc, bool only_not_default)
+{
+ char *buf;
+ size_t len;
+
+ FILE *stream = open_memstream(&buf, &len);
+
+ if (stream == nullptr)
+ {
+ LOG_FMT(LERR, "Failed to open_memstream\n");
+ fflush(stream);
+ fclose(stream);
+ free(buf);
+ return("");
+ }
+ save_option_file(stream, withDoc, only_not_default);
+
+ fflush(stream);
+ fclose(stream);
+
+ string out(buf);
+
+ free(buf);
+
+ return(out);
+}
+
+
+/**
+ * returns the config file string with all options based on the current configuration
+ *
+ * @param withDoc: false= without documentation, true=with documentation text lines
+ * @return returns the config file string with all options based on the current configuration
+ */
+string show_config(bool withDoc)
+{
+ return(show_config(withDoc, false));
+}
+
+
+//!returns the config file string with all options and without documentation based on the current configuration
+string show_config()
+{
+ return(show_config(false, false));
+}
+
+
+std::vector<OptionGroup *> get_groups()
+{
+ std::vector<OptionGroup *> groups;
+
+ groups.reserve(5);
+
+ for (size_t i = 0; true; ++i)
+ {
+ OptionGroup *group = get_option_group(i);
+
+ if (!group)
+ {
+ break;
+ }
+ groups.push_back(group);
+ }
+
+ return(groups);
+}
+
+
+std::vector<GenericOption *> get_options()
+{
+ std::vector<GenericOption *> options;
+
+ options.reserve(get_option_count());
+
+ for (size_t i = 0; true; ++i)
+ {
+ OptionGroup *group = get_option_group(i);
+
+ if (!group)
+ {
+ break;
+ }
+ options.insert(
+ end(options),
+ begin(group->options),
+ end(group->options)
+ );
+ }
+
+ return(options);
+}
+
+
+//! resets all options to their default values
+void reset_options()
+{
+ auto options = get_options();
+
+ for (auto *option : options)
+ {
+ option->reset();
+ }
+}
+
+
+/**
+ * initializes the current libUncrustify instance,
+ * used only for emscripten binding here and will be automatically called while
+ * module initialization
+ */
+void _initialize()
+{
+ register_options();
+ log_init(stdout);
+
+ LOG_FMT(LSYS, "Initialized libUncrustify - " UNCRUSTIFY_VERSION "\n");
+}
+
+
+//! destroys the current libUncrustify instance
+void destruct()
+{
+ clear_keyword_file();
+}
+
+
+/**
+ * reads option file string, sets the defined options
+ *
+ * @return returns EXIT_SUCCESS on success
+ */
+int _loadConfig(intptr_t _cfg)
+{
+ // reset everything in case a config was loaded previously
+ clear_keyword_file();
+ reset_options();
+
+ // embind complains about char* so we use an int to get the pointer and cast
+ // it, memory management is done in /emscripten/postfix_module.js
+ char *cfg = reinterpret_cast<char *>(_cfg);
+
+ if (load_option_fileChar(cfg) != EXIT_SUCCESS)
+ {
+ LOG_FMT(LERR, "unable to load the config\n");
+ return(EXIT_FAILURE);
+ }
+ // This relies on cpd.filename being the config file name
+ load_header_files();
+
+ LOG_FMT(LSYS, "finished loading config\n");
+ return(EXIT_SUCCESS);
+}
+
+
+/**
+ * format string
+ *
+ * @param file: pointer to the file char* string that is going to be formatted
+ * @param langIDX: specifies in which language the input file is written
+ * @param frag: true=fragmented code input, false=unfragmented code input
+ * @param defer: true=do not perform cleanup of Uncrustify structures
+ *
+ * @return pointer to the formatted file char* string
+ */
+intptr_t _uncrustify(intptr_t _file, lang_flag_e langIDX, bool frag, bool defer)
+{
+ // Problem: uncrustify originally is not a lib and uses global vars such as
+ // cpd.error_count for the whole program execution
+ // to know if errors occurred during the formating step we reset this var here
+ cpd.error_count = 0;
+ cpd.filename = "stdin";
+ cpd.frag = frag;
+
+ if (langIDX == 0) // 0 == undefined
+ {
+ LOG_FMT(LWARN, "language of input file not defined, C++ will be assumed\n");
+ cpd.lang_flags = LANG_CPP;
+ }
+ else
+ {
+ cpd.lang_flags = langIDX;
+ }
+ // embind complains about char* so we use an intptr_t to get the pointer and
+ // cast it, memory management is done in /emscripten/postfix_module.js
+ char *file = reinterpret_cast<char *>(_file);
+
+ file_mem fm;
+
+ fm.raw.clear();
+ fm.data.clear();
+ fm.enc = char_encoding_e::e_ASCII;
+ fm.raw = vector<UINT8>();
+
+ char c;
+
+ for (auto idx = 0; (c = file[idx]) != 0; ++idx)
+ {
+ fm.raw.push_back(c);
+ }
+
+ if (!decode_unicode(fm.raw, fm.data, fm.enc, fm.bom))
+ {
+ LOG_FMT(LERR, "Failed to read code\n");
+ return(0);
+ }
+ // Done reading from stdin
+ LOG_FMT(LSYS, "Parsing: %zu bytes (%zu chars) from stdin as language %s\n",
+ fm.raw.size(), fm.data.size(),
+ language_name_from_flags(cpd.lang_flags));
+
+
+ char *buf = nullptr;
+ size_t len = 0;
+
+ // uncrustify uses FILE instead of streams for its outputs
+ // to redirect FILE writes into a char* open_memstream is used
+ // windows lacks open_memstream, only UNIX/BSD is supported
+ // apparently emscripten has its own implementation, if that is not working
+ // see: stackoverflow.com/questions/10305095#answer-10341073
+ FILE *stream = open_memstream(&buf, &len);
+
+ if (stream == nullptr)
+ {
+ LOG_FMT(LERR, "Failed to open_memstream\n");
+ return(0);
+ }
+ // TODO One way to implement the --parsed, -p functionality would
+ // be to let the uncrustify_file function run, throw away the formated
+ // output and return the debug as a string. For this uncrustify_file would
+ // need to accept a stream, FILE or a char array pointer in which the output
+ // will be stored.
+ // Another option would be to check, inside the uncrustify_file function,
+ // if the current filename string matches stdout or stderr and use those as
+ // output locations. This is the easier fix but the debug info in the
+ // browsers console is littered with other unneeded text.
+ // Finally, the ugliest solution, would be also possible to re-route
+ // either stdout or stderr inside the Module var of emscripten to a js
+ // function which passes the debug output into a dedicated output js target.
+ // This therefore would introduce the dependency on the user to always have
+ // the output js target available.
+ uncrustify_file(fm, stream, nullptr, nullptr, defer);
+
+ fflush(stream);
+ fclose(stream);
+
+ if (cpd.error_count != 0)
+ {
+ LOG_FMT(LWARN, "%d errors occurred during formating\n", cpd.error_count);
+ }
+
+ if (len == 0)
+ {
+ return(0);
+ }
+ // buf is deleted inside js code
+ return(reinterpret_cast<intptr_t>(buf));
+} // uncrustify
+
+
+/**
+ * format string
+ *
+ * @param file: pointer to the file char* string that is going to be formatted
+ * @param langIDX: specifies in which language the input file is written
+ * @param frag: true=fragmented code input, false=unfragmented code input
+ *
+ * @return pointer to the formatted file char* string
+ */
+intptr_t _uncrustify(intptr_t file, lang_flag_e langIDX, bool frag)
+{
+ return(_uncrustify(file, langIDX, frag, false));
+}
+
+
+/**
+ * format string, assume unfragmented code input
+ *
+ * @param file: pointer to the file char* string that is going to be formatted
+ * @param langIDX: specifies in which language the input file is written
+ *
+ * @return pointer to the formatted file char* string
+ */
+intptr_t _uncrustify(intptr_t file, lang_flag_e langIDX)
+{
+ return(_uncrustify(file, langIDX, false, false));
+}
+
+
+/**
+ * generate debug output
+ *
+ * @param file: pointer to the file char* string that is going to be formatted
+ * @param langIDX: specifies in which language the input file is written
+ * @param frag: true=fragmented code input, false=unfragmented code input
+ *
+ * @return pointer to the debug file char* string
+ */
+intptr_t _debug(intptr_t _file, lang_flag_e langIDX, bool frag)
+{
+ auto formatted_str_ptr = _uncrustify(_file, langIDX, frag, true);
+ char *formatted_str = reinterpret_cast<char *>(formatted_str_ptr);
+
+ // Lazy solution: Throw away the formated file output.
+ // Maybe later add option to return both formatted file string and debug
+ // file string together ... somehow.
+ free(formatted_str);
+
+ char *buf = nullptr;
+ size_t len = 0;
+ FILE *stream = open_memstream(&buf, &len);
+
+ if (stream == nullptr)
+ {
+ LOG_FMT(LERR, "Failed to open_memstream\n");
+ return(0);
+ }
+ output_parsed(stream);
+ fflush(stream);
+ fclose(stream);
+
+ // start deferred _uncrustify cleanup
+ uncrustify_end();
+
+ if (len == 0)
+ {
+ return(0);
+ }
+ // buf is deleted inside js code
+ return(reinterpret_cast<intptr_t>(buf));
+} // uncrustify
+
+
+/**
+ * generate debug output, assume unfragmented code input
+ *
+ * @param file: pointer to the file char* string that is going to be formatted
+ * @param langIDX: specifies in which language the input file is written
+ *
+ * @return pointer to the debug file char* string
+ */
+intptr_t _debug(intptr_t _file, lang_flag_e langIDX)
+{
+ return(_debug(_file, langIDX, false));
+}
+
+} // namespace
+
+EMSCRIPTEN_BINDINGS(MainModule)
+{
+ // region enum bindings
+ enum_<option_type_e>("OptionType")
+ .value("BOOL", option_type_e::BOOL)
+ .value("IARF", option_type_e::IARF)
+ .value("LINEEND", option_type_e::LINEEND)
+ .value("TOKENPOS", option_type_e::TOKENPOS)
+ .value("NUM", option_type_e::NUM)
+ .value("UNUM", option_type_e::UNUM)
+ .value("STRING", option_type_e::STRING);
+
+ enum_<iarf_e>("IARF")
+ .value("IGNORE", IARF_IGNORE)
+ .value("ADD", IARF_ADD)
+ .value("REMOVE", IARF_REMOVE)
+ .value("FORCE", IARF_FORCE);
+
+ enum_<line_end_e>("LineEnd")
+ .value("LF", line_end_e::LF)
+ .value("CRLF", line_end_e::CRLF)
+ .value("CR", line_end_e::CR)
+ .value("AUTO", line_end_e::AUTO);
+
+ enum_<token_pos_e>("TokenPos")
+ .value("IGNORE", token_pos_e::IGNORE)
+ .value("BREAK", token_pos_e::BREAK)
+ .value("FORCE", token_pos_e::FORCE)
+ .value("LEAD", token_pos_e::LEAD)
+ .value("TRAIL", token_pos_e::TRAIL)
+ .value("JOIN", token_pos_e::JOIN)
+ .value("LEAD_BREAK", token_pos_e::LEAD_BREAK)
+ .value("LEAD_FORCE", token_pos_e::LEAD_FORCE)
+ .value("TRAIL_BREAK", token_pos_e::TRAIL_BREAK)
+ .value("TRAIL_FORCE", token_pos_e::TRAIL_FORCE);
+
+ enum_<log_sev_t>("LogType")
+ .value("SYS", log_sev_t::LSYS)
+ .value("ERR", log_sev_t::LERR)
+ .value("WARN", log_sev_t::LWARN)
+ .value("NOTE", log_sev_t::LNOTE)
+ .value("INFO", log_sev_t::LINFO)
+ .value("DATA", log_sev_t::LDATA)
+ .value("FILELIST", log_sev_t::LFILELIST)
+ .value("LINEENDS", log_sev_t::LLINEENDS)
+ .value("CASTS", log_sev_t::LCASTS)
+ .value("ALBR", log_sev_t::LALBR)
+ .value("ALTD", log_sev_t::LALTD)
+ .value("ALPP", log_sev_t::LALPP)
+ .value("ALPROTO", log_sev_t::LALPROTO)
+ .value("ALNLC", log_sev_t::LALNLC)
+ .value("ALTC", log_sev_t::LALTC)
+ .value("ALADD", log_sev_t::LALADD)
+ .value("ALASS", log_sev_t::LALASS)
+ .value("FVD", log_sev_t::LFVD)
+ .value("FVD2", log_sev_t::LFVD2)
+ .value("INDENT", log_sev_t::LINDENT)
+ .value("INDENT2", log_sev_t::LINDENT2)
+ .value("INDPSE", log_sev_t::LINDPSE)
+ .value("INDPC", log_sev_t::LINDPC)
+ .value("NEWLINE", log_sev_t::LNEWLINE)
+ .value("PF", log_sev_t::LPF)
+ .value("STMT", log_sev_t::LSTMT)
+ .value("TOK", log_sev_t::LTOK)
+ .value("ALRC", log_sev_t::LALRC)
+ .value("CMTIND", log_sev_t::LCMTIND)
+ .value("INDLINE", log_sev_t::LINDLINE)
+ .value("SIB", log_sev_t::LSIB)
+ .value("RETURN", log_sev_t::LRETURN)
+ .value("BRDEL", log_sev_t::LBRDEL)
+ .value("FCN", log_sev_t::LFCN)
+ .value("FCNP", log_sev_t::LFCNP)
+ .value("PCU", log_sev_t::LPCU)
+ .value("DYNKW", log_sev_t::LDYNKW)
+ .value("OUTIND", log_sev_t::LOUTIND)
+ .value("BCSAFTER", log_sev_t::LBCSAFTER)
+ .value("BCSPOP", log_sev_t::LBCSPOP)
+ .value("BCSPUSH", log_sev_t::LBCSPUSH)
+ .value("BCSSWAP", log_sev_t::LBCSSWAP)
+ .value("FTOR", log_sev_t::LFTOR)
+ .value("AS", log_sev_t::LAS)
+ .value("PPIS", log_sev_t::LPPIS)
+ .value("TYPEDEF", log_sev_t::LTYPEDEF)
+ .value("VARDEF", log_sev_t::LVARDEF)
+ .value("DEFVAL", log_sev_t::LDEFVAL)
+ .value("PVSEMI", log_sev_t::LPVSEMI)
+ .value("PFUNC", log_sev_t::LPFUNC)
+ .value("SPLIT", log_sev_t::LSPLIT)
+ .value("FTYPE", log_sev_t::LFTYPE)
+ .value("TEMPL", log_sev_t::LTEMPL)
+ .value("PARADD", log_sev_t::LPARADD)
+ .value("PARADD2", log_sev_t::LPARADD2)
+ .value("BLANKD", log_sev_t::LBLANKD)
+ .value("TEMPFUNC", log_sev_t::LTEMPFUNC)
+ .value("SCANSEMI", log_sev_t::LSCANSEMI)
+ .value("DELSEMI", log_sev_t::LDELSEMI)
+ .value("FPARAM", log_sev_t::LFPARAM)
+ .value("NL1LINE", log_sev_t::LNL1LINE)
+ .value("PFCHK", log_sev_t::LPFCHK)
+ .value("AVDB", log_sev_t::LAVDB)
+ .value("SORT", log_sev_t::LSORT)
+ .value("SPACE", log_sev_t::LSPACE)
+ .value("ALIGN", log_sev_t::LALIGN)
+ .value("ALAGAIN", log_sev_t::LALAGAIN)
+ .value("OPERATOR", log_sev_t::LOPERATOR)
+ .value("ASFCP", log_sev_t::LASFCP)
+ .value("INDLINED", log_sev_t::LINDLINED)
+ .value("BCTRL", log_sev_t::LBCTRL)
+ .value("RMRETURN", log_sev_t::LRMRETURN)
+ .value("PPIF", log_sev_t::LPPIF)
+ .value("MCB", log_sev_t::LMCB)
+ .value("BRCH", log_sev_t::LBRCH)
+ .value("FCNR", log_sev_t::LFCNR)
+ .value("OCCLASS", log_sev_t::LOCCLASS)
+ .value("OCMSG", log_sev_t::LOCMSG)
+ .value("BLANK", log_sev_t::LBLANK)
+ .value("OBJCWORD", log_sev_t::LOBJCWORD)
+ .value("CHANGE", log_sev_t::LCHANGE)
+ .value("CONTTEXT", log_sev_t::LCONTTEXT)
+ .value("ANNOT", log_sev_t::LANNOT)
+ .value("OCBLK", log_sev_t::LOCBLK)
+ .value("FLPAREN", log_sev_t::LFLPAREN)
+ .value("OCMSGD", log_sev_t::LOCMSGD)
+ .value("INDENTAG", log_sev_t::LINDENTAG)
+ .value("NFD", log_sev_t::LNFD)
+ .value("JDBI", log_sev_t::LJDBI)
+ .value("SETPAR", log_sev_t::LSETPAR)
+ .value("SETTYP", log_sev_t::LSETTYP)
+ .value("SETFLG", log_sev_t::LSETFLG)
+ .value("NLFUNCT", log_sev_t::LNLFUNCT)
+ .value("CHUNK", log_sev_t::LCHUNK)
+ .value("GUY98", log_sev_t::LGUY98)
+ .value("GUY", log_sev_t::LGUY);
+
+ enum_<E_Token>("TokenType")
+ .value("NONE", E_Token::CT_NONE)
+ .value("EOF", E_Token::CT_EOF)
+ .value("UNKNOWN", E_Token::CT_UNKNOWN)
+ .value("JUNK", E_Token::CT_JUNK)
+ .value("WHITESPACE", E_Token::CT_WHITESPACE)
+ .value("SPACE", E_Token::CT_SPACE)
+ .value("NEWLINE", E_Token::CT_NEWLINE)
+ .value("NL_CONT", E_Token::CT_NL_CONT)
+ .value("COMMENT_CPP", E_Token::CT_COMMENT_CPP)
+ .value("COMMENT", E_Token::CT_COMMENT)
+ .value("COMMENT_MULTI", E_Token::CT_COMMENT_MULTI)
+ .value("COMMENT_EMBED", E_Token::CT_COMMENT_EMBED)
+ .value("COMMENT_START", E_Token::CT_COMMENT_START)
+ .value("COMMENT_END", E_Token::CT_COMMENT_END)
+ .value("COMMENT_WHOLE", E_Token::CT_COMMENT_WHOLE)
+ .value("COMMENT_ENDIF", E_Token::CT_COMMENT_ENDIF)
+ .value("IGNORED", E_Token::CT_IGNORED)
+ .value("WORD", E_Token::CT_WORD)
+ .value("NUMBER", E_Token::CT_NUMBER)
+ .value("NUMBER_FP", E_Token::CT_NUMBER_FP)
+ .value("STRING", E_Token::CT_STRING)
+ .value("STRING_MULTI", E_Token::CT_STRING_MULTI)
+ .value("IF", E_Token::CT_IF)
+ .value("ELSE", E_Token::CT_ELSE)
+ .value("ELSEIF", E_Token::CT_ELSEIF)
+ .value("FOR", E_Token::CT_FOR)
+ .value("WHILE", E_Token::CT_WHILE)
+ .value("WHILE_OF_DO", E_Token::CT_WHILE_OF_DO)
+ .value("SWITCH", E_Token::CT_SWITCH)
+ .value("CASE", E_Token::CT_CASE)
+ .value("DO", E_Token::CT_DO)
+ .value("SYNCHRONIZED", E_Token::CT_SYNCHRONIZED)
+ .value("VOLATILE", E_Token::CT_VOLATILE)
+ .value("TYPEDEF", E_Token::CT_TYPEDEF)
+ .value("STRUCT", E_Token::CT_STRUCT)
+ .value("ENUM", E_Token::CT_ENUM)
+ .value("ENUM_CLASS", E_Token::CT_ENUM_CLASS)
+ .value("SIZEOF", E_Token::CT_SIZEOF)
+ .value("DECLTYPE", E_Token::CT_DECLTYPE)
+ .value("RETURN", E_Token::CT_RETURN)
+ .value("BREAK", E_Token::CT_BREAK)
+ .value("UNION", E_Token::CT_UNION)
+ .value("GOTO", E_Token::CT_GOTO)
+ .value("CONTINUE", E_Token::CT_CONTINUE)
+ .value("C_CAST", E_Token::CT_C_CAST)
+ .value("CPP_CAST", E_Token::CT_CPP_CAST)
+ .value("D_CAST", E_Token::CT_D_CAST)
+ .value("TYPE_CAST", E_Token::CT_TYPE_CAST)
+ .value("TYPENAME", E_Token::CT_TYPENAME)
+ .value("TEMPLATE", E_Token::CT_TEMPLATE)
+ .value("WHERE_SPEC", E_Token::CT_WHERE_SPEC)
+ .value("ASSIGN", E_Token::CT_ASSIGN)
+ .value("ASSIGN_NL", E_Token::CT_ASSIGN_NL)
+ .value("SASSIGN", E_Token::CT_SASSIGN)
+ .value("ASSIGN_DEFAULT_ARG", E_Token::CT_ASSIGN_DEFAULT_ARG)
+ .value("ASSIGN_FUNC_PROTO", E_Token::CT_ASSIGN_FUNC_PROTO)
+ .value("COMPARE", E_Token::CT_COMPARE)
+ .value("SCOMPARE", E_Token::CT_SCOMPARE)
+ .value("BOOL", E_Token::CT_BOOL)
+ .value("SBOOL", E_Token::CT_SBOOL)
+ .value("ARITH", E_Token::CT_ARITH)
+ .value("SARITH", E_Token::CT_SARITH)
+ .value("CARET", E_Token::CT_CARET)
+ .value("DEREF", E_Token::CT_DEREF)
+ .value("INCDEC_BEFORE", E_Token::CT_INCDEC_BEFORE)
+ .value("INCDEC_AFTER", E_Token::CT_INCDEC_AFTER)
+ .value("MEMBER", E_Token::CT_MEMBER)
+ .value("DC_MEMBER", E_Token::CT_DC_MEMBER)
+ .value("C99_MEMBER", E_Token::CT_C99_MEMBER)
+ .value("INV", E_Token::CT_INV)
+ .value("DESTRUCTOR", E_Token::CT_DESTRUCTOR)
+ .value("NOT", E_Token::CT_NOT)
+ .value("D_TEMPLATE", E_Token::CT_D_TEMPLATE)
+ .value("ADDR", E_Token::CT_ADDR)
+ .value("NEG", E_Token::CT_NEG)
+ .value("POS", E_Token::CT_POS)
+ .value("STAR", E_Token::CT_STAR)
+ .value("PLUS", E_Token::CT_PLUS)
+ .value("MINUS", E_Token::CT_MINUS)
+ .value("AMP", E_Token::CT_AMP)
+ .value("BYREF", E_Token::CT_BYREF)
+ .value("POUND", E_Token::CT_POUND)
+ .value("PREPROC", E_Token::CT_PREPROC)
+ .value("PREPROC_INDENT", E_Token::CT_PREPROC_INDENT)
+ .value("PREPROC_BODY", E_Token::CT_PREPROC_BODY)
+ .value("PP", E_Token::CT_PP)
+ .value("ELLIPSIS", E_Token::CT_ELLIPSIS)
+ .value("RANGE", E_Token::CT_RANGE)
+ .value("NULLCOND", E_Token::CT_NULLCOND)
+ .value("SEMICOLON", E_Token::CT_SEMICOLON)
+ .value("VSEMICOLON", E_Token::CT_VSEMICOLON)
+ .value("COLON", E_Token::CT_COLON)
+ .value("ASM_COLON", E_Token::CT_ASM_COLON)
+ .value("CASE_COLON", E_Token::CT_CASE_COLON)
+ .value("CLASS_COLON", E_Token::CT_CLASS_COLON)
+ .value("CONSTR_COLON", E_Token::CT_CONSTR_COLON)
+ .value("D_ARRAY_COLON", E_Token::CT_D_ARRAY_COLON)
+ .value("COND_COLON", E_Token::CT_COND_COLON)
+ .value("WHERE_COLON", E_Token::CT_WHERE_COLON)
+ .value("QUESTION", E_Token::CT_QUESTION)
+ .value("COMMA", E_Token::CT_COMMA)
+ .value("ASM", E_Token::CT_ASM)
+ .value("ATTRIBUTE", E_Token::CT_ATTRIBUTE)
+ .value("AUTORELEASEPOOL", E_Token::CT_AUTORELEASEPOOL)
+ .value("OC_AVAILABLE", E_Token::CT_OC_AVAILABLE)
+ .value("OC_AVAILABLE_VALUE", E_Token::CT_OC_AVAILABLE_VALUE)
+ .value("CATCH", E_Token::CT_CATCH)
+ .value("WHEN", E_Token::CT_WHEN)
+ .value("WHERE", E_Token::CT_WHERE)
+ .value("CLASS", E_Token::CT_CLASS)
+ .value("DELETE", E_Token::CT_DELETE)
+ .value("EXPORT", E_Token::CT_EXPORT)
+ .value("FRIEND", E_Token::CT_FRIEND)
+ .value("NAMESPACE", E_Token::CT_NAMESPACE)
+ .value("PACKAGE", E_Token::CT_PACKAGE)
+ .value("NEW", E_Token::CT_NEW)
+ .value("OPERATOR", E_Token::CT_OPERATOR)
+ .value("OPERATOR_VAL", E_Token::CT_OPERATOR_VAL)
+ .value("ASSIGN_OPERATOR", E_Token::CT_ASSIGN_OPERATOR)
+ .value("ACCESS", E_Token::CT_ACCESS)
+ .value("ACCESS_COLON", E_Token::CT_ACCESS_COLON)
+ .value("THROW", E_Token::CT_THROW)
+ .value("NOEXCEPT", E_Token::CT_NOEXCEPT)
+ .value("TRY", E_Token::CT_TRY)
+ .value("BRACED_INIT_LIST", E_Token::CT_BRACED_INIT_LIST)
+ .value("USING", E_Token::CT_USING)
+ .value("USING_STMT", E_Token::CT_USING_STMT)
+ .value("USING_ALIAS", E_Token::CT_USING_ALIAS)
+ .value("D_WITH", E_Token::CT_D_WITH)
+ .value("D_MODULE", E_Token::CT_D_MODULE)
+ .value("SUPER", E_Token::CT_SUPER)
+ .value("DELEGATE", E_Token::CT_DELEGATE)
+ .value("BODY", E_Token::CT_BODY)
+ .value("DEBUG", E_Token::CT_DEBUG)
+ .value("DEBUGGER", E_Token::CT_DEBUGGER)
+ .value("INVARIANT", E_Token::CT_INVARIANT)
+ .value("UNITTEST", E_Token::CT_UNITTEST)
+ .value("UNSAFE", E_Token::CT_UNSAFE)
+ .value("FINALLY", E_Token::CT_FINALLY)
+ .value("FIXED", E_Token::CT_FIXED)
+ .value("IMPORT", E_Token::CT_IMPORT)
+ .value("D_SCOPE", E_Token::CT_D_SCOPE)
+ .value("D_SCOPE_IF", E_Token::CT_D_SCOPE_IF)
+ .value("LAZY", E_Token::CT_LAZY)
+ .value("D_MACRO", E_Token::CT_D_MACRO)
+ .value("D_VERSION", E_Token::CT_D_VERSION)
+ .value("D_VERSION_IF", E_Token::CT_D_VERSION_IF)
+ .value("PAREN_OPEN", E_Token::CT_PAREN_OPEN)
+ .value("PAREN_CLOSE", E_Token::CT_PAREN_CLOSE)
+ .value("ANGLE_OPEN", E_Token::CT_ANGLE_OPEN)
+ .value("ANGLE_CLOSE", E_Token::CT_ANGLE_CLOSE)
+ .value("SPAREN_OPEN", E_Token::CT_SPAREN_OPEN)
+ .value("SPAREN_CLOSE", E_Token::CT_SPAREN_CLOSE)
+ .value("FPAREN_OPEN", E_Token::CT_FPAREN_OPEN)
+ .value("FPAREN_CLOSE", E_Token::CT_FPAREN_CLOSE)
+ .value("TPAREN_OPEN", E_Token::CT_TPAREN_OPEN)
+ .value("TPAREN_CLOSE", E_Token::CT_TPAREN_CLOSE)
+ .value("BRACE_OPEN", E_Token::CT_BRACE_OPEN)
+ .value("BRACE_CLOSE", E_Token::CT_BRACE_CLOSE)
+ .value("VBRACE_OPEN", E_Token::CT_VBRACE_OPEN)
+ .value("VBRACE_CLOSE", E_Token::CT_VBRACE_CLOSE)
+ .value("SQUARE_OPEN", E_Token::CT_SQUARE_OPEN)
+ .value("SQUARE_CLOSE", E_Token::CT_SQUARE_CLOSE)
+ .value("TSQUARE", E_Token::CT_TSQUARE)
+ .value("MACRO_OPEN", E_Token::CT_MACRO_OPEN)
+ .value("MACRO_CLOSE", E_Token::CT_MACRO_CLOSE)
+ .value("MACRO_ELSE", E_Token::CT_MACRO_ELSE)
+ .value("LABEL", E_Token::CT_LABEL)
+ .value("LABEL_COLON", E_Token::CT_LABEL_COLON)
+ .value("FUNCTION", E_Token::CT_FUNCTION)
+ .value("FUNC_CALL", E_Token::CT_FUNC_CALL)
+ .value("FUNC_CALL_USER", E_Token::CT_FUNC_CALL_USER)
+ .value("FUNC_DEF", E_Token::CT_FUNC_DEF)
+ .value("FUNC_TYPE", E_Token::CT_FUNC_TYPE)
+ .value("FUNC_VAR", E_Token::CT_FUNC_VAR)
+ .value("FUNC_PROTO", E_Token::CT_FUNC_PROTO)
+ .value("FUNC_START", E_Token::CT_FUNC_START)
+ .value("FUNC_CLASS_DEF", E_Token::CT_FUNC_CLASS_DEF)
+ .value("FUNC_CLASS_PROTO", E_Token::CT_FUNC_CLASS_PROTO)
+ .value("FUNC_CTOR_VAR", E_Token::CT_FUNC_CTOR_VAR)
+ .value("FUNC_WRAP", E_Token::CT_FUNC_WRAP)
+ .value("PROTO_WRAP", E_Token::CT_PROTO_WRAP)
+ .value("MACRO_FUNC", E_Token::CT_MACRO_FUNC)
+ .value("MACRO", E_Token::CT_MACRO)
+ .value("QUALIFIER", E_Token::CT_QUALIFIER)
+ .value("EXTERN", E_Token::CT_EXTERN)
+ .value("DECLSPEC", E_Token::CT_DECLSPEC)
+ .value("ALIGN", E_Token::CT_ALIGN)
+ .value("TYPE", E_Token::CT_TYPE)
+ .value("PTR_TYPE", E_Token::CT_PTR_TYPE)
+ .value("TYPE_WRAP", E_Token::CT_TYPE_WRAP)
+ .value("CPP_LAMBDA", E_Token::CT_CPP_LAMBDA)
+ .value("CPP_LAMBDA_RET", E_Token::CT_CPP_LAMBDA_RET)
+ .value("TRAILING_RET", E_Token::CT_TRAILING_RET)
+ .value("BIT_COLON", E_Token::CT_BIT_COLON)
+ .value("OC_DYNAMIC", E_Token::CT_OC_DYNAMIC)
+ .value("OC_END", E_Token::CT_OC_END)
+ .value("OC_IMPL", E_Token::CT_OC_IMPL)
+ .value("OC_INTF", E_Token::CT_OC_INTF)
+ .value("OC_PROTOCOL", E_Token::CT_OC_PROTOCOL)
+ .value("OC_PROTO_LIST", E_Token::CT_OC_PROTO_LIST)
+ .value("OC_GENERIC_SPEC", E_Token::CT_OC_GENERIC_SPEC)
+ .value("OC_PROPERTY", E_Token::CT_OC_PROPERTY)
+ .value("OC_CLASS", E_Token::CT_OC_CLASS)
+ .value("OC_CLASS_EXT", E_Token::CT_OC_CLASS_EXT)
+ .value("OC_CATEGORY", E_Token::CT_OC_CATEGORY)
+ .value("OC_SCOPE", E_Token::CT_OC_SCOPE)
+ .value("OC_MSG", E_Token::CT_OC_MSG)
+ .value("OC_MSG_CLASS", E_Token::CT_OC_MSG_CLASS)
+ .value("OC_MSG_FUNC", E_Token::CT_OC_MSG_FUNC)
+ .value("OC_MSG_NAME", E_Token::CT_OC_MSG_NAME)
+ .value("OC_MSG_SPEC", E_Token::CT_OC_MSG_SPEC)
+ .value("OC_MSG_DECL", E_Token::CT_OC_MSG_DECL)
+ .value("OC_RTYPE", E_Token::CT_OC_RTYPE)
+ .value("OC_ATYPE", E_Token::CT_OC_ATYPE)
+ .value("OC_COLON", E_Token::CT_OC_COLON)
+ .value("OC_DICT_COLON", E_Token::CT_OC_DICT_COLON)
+ .value("OC_SEL", E_Token::CT_OC_SEL)
+ .value("OC_SEL_NAME", E_Token::CT_OC_SEL_NAME)
+ .value("OC_BLOCK", E_Token::CT_OC_BLOCK)
+ .value("OC_BLOCK_ARG", E_Token::CT_OC_BLOCK_ARG)
+ .value("OC_BLOCK_TYPE", E_Token::CT_OC_BLOCK_TYPE)
+ .value("OC_BLOCK_EXPR", E_Token::CT_OC_BLOCK_EXPR)
+ .value("OC_BLOCK_CARET", E_Token::CT_OC_BLOCK_CARET)
+ .value("OC_AT", E_Token::CT_OC_AT)
+ .value("OC_PROPERTY_ATTR", E_Token::CT_OC_PROPERTY_ATTR)
+ .value("PP_DEFINE", E_Token::CT_PP_DEFINE)
+ .value("PP_DEFINED", E_Token::CT_PP_DEFINED)
+ .value("PP_INCLUDE", E_Token::CT_PP_INCLUDE)
+ .value("PP_IF", E_Token::CT_PP_IF)
+ .value("PP_ELSE", E_Token::CT_PP_ELSE)
+ .value("PP_ENDIF", E_Token::CT_PP_ENDIF)
+ .value("PP_ASSERT", E_Token::CT_PP_ASSERT)
+ .value("PP_EMIT", E_Token::CT_PP_EMIT)
+ .value("PP_ENDINPUT", E_Token::CT_PP_ENDINPUT)
+ .value("PP_ERROR", E_Token::CT_PP_ERROR)
+ .value("PP_FILE", E_Token::CT_PP_FILE)
+ .value("PP_LINE", E_Token::CT_PP_LINE)
+ .value("PP_SECTION", E_Token::CT_PP_SECTION)
+ .value("PP_ASM", E_Token::CT_PP_ASM)
+ .value("PP_UNDEF", E_Token::CT_PP_UNDEF)
+ .value("PP_PROPERTY", E_Token::CT_PP_PROPERTY)
+ .value("PP_BODYCHUNK", E_Token::CT_PP_BODYCHUNK)
+ .value("PP_PRAGMA", E_Token::CT_PP_PRAGMA)
+ .value("PP_REGION", E_Token::CT_PP_REGION)
+ .value("PP_ENDREGION", E_Token::CT_PP_ENDREGION)
+ .value("PP_REGION_INDENT", E_Token::CT_PP_REGION_INDENT)
+ .value("PP_IF_INDENT", E_Token::CT_PP_IF_INDENT)
+ .value("PP_IGNORE", E_Token::CT_PP_IGNORE)
+ .value("PP_OTHER", E_Token::CT_PP_OTHER)
+ .value("CHAR", E_Token::CT_CHAR)
+ .value("DEFINED", E_Token::CT_DEFINED)
+ .value("FORWARD", E_Token::CT_FORWARD)
+ .value("NATIVE", E_Token::CT_NATIVE)
+ .value("STATE", E_Token::CT_STATE)
+ .value("STOCK", E_Token::CT_STOCK)
+ .value("TAGOF", E_Token::CT_TAGOF)
+ .value("DOT", E_Token::CT_DOT)
+ .value("TAG", E_Token::CT_TAG)
+ .value("TAG_COLON", E_Token::CT_TAG_COLON)
+ .value("LOCK", E_Token::CT_LOCK)
+ .value("AS", E_Token::CT_AS)
+ .value("IN", E_Token::CT_IN)
+ .value("BRACED", E_Token::CT_BRACED)
+ .value("THIS", E_Token::CT_THIS)
+ .value("BASE", E_Token::CT_BASE)
+ .value("DEFAULT", E_Token::CT_DEFAULT)
+ .value("GETSET", E_Token::CT_GETSET)
+ .value("GETSET_EMPTY", E_Token::CT_GETSET_EMPTY)
+ .value("CONCAT", E_Token::CT_CONCAT)
+ .value("CS_SQ_STMT", E_Token::CT_CS_SQ_STMT)
+ .value("CS_SQ_COLON", E_Token::CT_CS_SQ_COLON)
+ .value("CS_PROPERTY", E_Token::CT_CS_PROPERTY)
+ .value("SQL_EXEC", E_Token::CT_SQL_EXEC)
+ .value("SQL_BEGIN", E_Token::CT_SQL_BEGIN)
+ .value("SQL_END", E_Token::CT_SQL_END)
+ .value("SQL_WORD", E_Token::CT_SQL_WORD)
+ .value("SQL_ASSIGN", E_Token::CT_SQL_ASSIGN)
+ .value("CONSTRUCT", E_Token::CT_CONSTRUCT)
+ .value("LAMBDA", E_Token::CT_LAMBDA)
+ .value("ASSERT", E_Token::CT_ASSERT)
+ .value("ANNOTATION", E_Token::CT_ANNOTATION)
+ .value("FOR_COLON", E_Token::CT_FOR_COLON)
+ .value("DOUBLE_BRACE", E_Token::CT_DOUBLE_BRACE)
+ .value("CNG_HASINC", E_Token::CT_CNG_HASINC)
+ .value("CNG_HASINCN", E_Token::CT_CNG_HASINCN)
+ .value("Q_EMIT", E_Token::CT_Q_EMIT)
+ .value("Q_FOREACH", E_Token::CT_Q_FOREACH)
+ .value("Q_FOREVER", E_Token::CT_Q_FOREVER)
+ .value("Q_GADGET", E_Token::CT_Q_GADGET)
+ .value("Q_OBJECT", E_Token::CT_Q_OBJECT)
+ .value("MODE", E_Token::CT_MODE)
+ .value("DI", E_Token::CT_DI)
+ .value("HI", E_Token::CT_HI)
+ .value("QI", E_Token::CT_QI)
+ .value("SI", E_Token::CT_SI)
+ .value("NOTHROW", E_Token::CT_NOTHROW)
+ .value("WORD_", E_Token::CT_WORD_);
+
+ enum_<lang_flag_e>("Language")
+ .value("C", lang_flag_e::LANG_C)
+ .value("CPP", lang_flag_e::LANG_CPP)
+ .value("D", lang_flag_e::LANG_D)
+ .value("CS", lang_flag_e::LANG_CS)
+ .value("JAVA", lang_flag_e::LANG_JAVA)
+ .value("OC", lang_flag_e::LANG_OC)
+ .value("VALA", lang_flag_e::LANG_VALA)
+ .value("PAWN", lang_flag_e::LANG_PAWN)
+ .value("ECMA", lang_flag_e::LANG_ECMA);
+
+ // endregion enum bindings
+
+ register_vector<std::string>("strings");
+
+ class_<GenericOption>("GenericOption")
+ .function("type", &GenericOption::type)
+ .function("description", select_overload<std::string(const GenericOption &)>(
+ [](const GenericOption &o)
+ {
+ return((o.description() != nullptr) ? string(o.description()) : "");
+ }))
+ .function("name", select_overload<std::string(const GenericOption &)>(
+ [](const GenericOption &o)
+ {
+ return((o.name() != nullptr) ? string(o.name()) : "");
+ }))
+ .function("possible_values", select_overload<std::vector<std::string>(const GenericOption &)>(
+ [](const GenericOption &o)
+ {
+ std::vector<std::string> strings;
+
+ auto ptr = o.possibleValues();
+
+ for (auto c = *ptr; c; c = *++ptr)
+ {
+ strings.push_back(std::string{ c });
+ }
+
+ return(strings);
+ }))
+ .function("default", &GenericOption::defaultStr)
+ .function("min", &GenericOption::minStr)
+ .function("max", &GenericOption::maxStr)
+ .function("is_default", &GenericOption::isDefault)
+ .function("reset", &GenericOption::reset)
+ .function("set", select_overload<bool(GenericOption &o, const std::string &s)>(
+ [](GenericOption &o, const std::string &s)
+ {
+ return(o.read(s.c_str()));
+ }))
+ .function("value", &GenericOption::str);
+
+ register_vector<GenericOption *>("options");
+
+ class_<Option<iarf_e>, base<GenericOption> >("OptionIARF")
+ .function("value", &Option<iarf_e>::operator());
+
+ class_<Option<line_end_e>, base<GenericOption> >("OptionLineEnd")
+ .function("value", &Option<line_end_e>::operator());
+
+ class_<Option<token_pos_e>, base<GenericOption> >("OptionTokenPos")
+ .function("value", &Option<token_pos_e>::operator());
+
+ class_<Option<unsigned>, base<GenericOption> >("OptionUnsigned")
+ .function("value", &Option<unsigned>::operator());
+
+ class_<Option<signed>, base<GenericOption> >("OptionSigned")
+ .function("value", &Option<signed>::operator());
+
+ class_<Option<std::string>, base<GenericOption> >("OptionString")
+ .function("value", &Option<std::string>::operator());
+
+ class_<OptionGroup>("OptionGroup")
+ .property("description", select_overload<std::string(const OptionGroup &)>(
+ [](const OptionGroup &g)
+ {
+ return(std::string(g.description));
+ }))
+ .property("options", &OptionGroup::options);
+
+ register_vector<OptionGroup *>("groups");
+
+ emscripten::function("get_options", &get_options);
+ emscripten::function("get_groups", &get_groups);
+
+ emscripten::function("_initialize", &_initialize);
+ emscripten::function("destruct", &destruct);
+
+ emscripten::function("get_version", &get_version);
+
+ emscripten::function("add_keyword", &_add_keyword);
+ emscripten::function("clear_keywords", &clear_keywords);
+
+ emscripten::function("reset_options", &reset_options);
+ emscripten::function("option_reset_value", &reset_option);
+ emscripten::function("option_set_value", &set_option);
+ emscripten::function("option_get_value", &get_option);
+
+ emscripten::function("_load_config", &_loadConfig);
+ emscripten::function("show_config", select_overload<string(bool, bool)>(&show_config));
+ emscripten::function("show_config", select_overload<string(bool)>(&show_config));
+ emscripten::function("show_config", select_overload<string()>(&show_config));
+
+ emscripten::function("log_type_enable", &log_set_sev);
+ emscripten::function("log_type_show_name", &show_log_type);
+ emscripten::function("quiet", &set_quiet);
+
+ emscripten::function("_uncrustify", select_overload<intptr_t(intptr_t, lang_flag_e, bool, bool)>(&_uncrustify));
+ emscripten::function("_uncrustify", select_overload<intptr_t(intptr_t, lang_flag_e, bool)>(&_uncrustify));
+ emscripten::function("_uncrustify", select_overload<intptr_t(intptr_t, lang_flag_e)>(&_uncrustify));
+
+ emscripten::function("_debug", select_overload<intptr_t(intptr_t, lang_flag_e, bool)>(&_debug));
+ emscripten::function("_debug", select_overload<intptr_t(intptr_t, lang_flag_e)>(&_debug));
+};
+
+#endif
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_limits.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_limits.h
new file mode 100644
index 00000000..9f226870
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_limits.h
@@ -0,0 +1,19 @@
+#pragma once
+
+namespace uncrustify
+{
+
+namespace limits
+{
+
+static constexpr int MAX_OPTION_NAME_LEN = 32;
+static constexpr int AL_SIZE = 8000;
+static constexpr int MAX_KEYWORDS = 300;
+
+// uncrustify doesn't support more than one variable definition per line/ type,
+// the maximum level of pointer indirection is 3 (i.e., ***p).
+// TODO add some more limitations
+
+} // namespace limits
+
+} // namespace uncrustify
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.cpp
new file mode 100644
index 00000000..bd57f2d5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.cpp
@@ -0,0 +1,88 @@
+/**
+ * @file uncrustify_types.cpp
+ * Defines some types for the uncrustify program
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "uncrustify_types.h"
+
+
+const char *get_brace_stage_name(brace_stage_e brace_stage)
+{
+ switch (brace_stage)
+ {
+ case brace_stage_e::NONE:
+ return("NONE");
+
+ case brace_stage_e::PAREN1:
+ return("PAREN1");
+
+ case brace_stage_e::OP_PAREN1:
+ return("OP_PAREN1");
+
+ case brace_stage_e::WOD_PAREN:
+ return("WOD_PAREN");
+
+ case brace_stage_e::WOD_SEMI:
+ return("WOD_SEMI");
+
+ case brace_stage_e::BRACE_DO:
+ return("BRACE_DO");
+
+ case brace_stage_e::BRACE2:
+ return("BRACE2");
+
+ case brace_stage_e::ELSE:
+ return("ELSE");
+
+ case brace_stage_e::ELSEIF:
+ return("ELSEIF");
+
+ case brace_stage_e::WHILE:
+ return("WHILE");
+
+ case brace_stage_e::CATCH:
+ return("CATCH");
+
+ case brace_stage_e::CATCH_WHEN:
+ return("CATCH_WHEN");
+ }
+ return("?????");
+} // get_brace_stage_name
+
+
+const char *get_unc_stage_name(unc_stage_e unc_stage)
+{
+ switch (unc_stage)
+ {
+ case unc_stage_e::TOKENIZE:
+ return("TOKENIZE");
+
+ case unc_stage_e::HEADER:
+ return("HEADER");
+
+ case unc_stage_e::TOKENIZE_CLEANUP:
+ return("TOKENIZE_CLEANUP");
+
+ case unc_stage_e::BRACE_CLEANUP:
+ return("BRACE_CLEANUP");
+
+ case unc_stage_e::FIX_SYMBOLS:
+ return("FIX_SYMBOLS");
+
+ case unc_stage_e::MARK_COMMENTS:
+ return("MARK_COMMENTS");
+
+ case unc_stage_e::COMBINE_LABELS:
+ return("COMBINE_LABELS");
+
+ case unc_stage_e::OTHER:
+ return("OTHER");
+
+ case unc_stage_e::CLEANUP:
+ return("CLEANUP");
+ }
+ return("?????");
+} // get_unc_stage_name
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.h
new file mode 100644
index 00000000..b0bdae8d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_types.h
@@ -0,0 +1,284 @@
+/**
+ * @file uncrustify_types.h
+ *
+ * Defines some types for the uncrustify program
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef UNCRUSTIFY_TYPES_H_INCLUDED
+#define UNCRUSTIFY_TYPES_H_INCLUDED
+
+#include "options.h"
+#include "pcf_flags.h"
+#include "token_enum.h" // E_Token
+#include "unc_text.h"
+#include "uncrustify_limits.h"
+
+#include <assert.h>
+#include <cstddef> // do get the definition of size_t
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+
+class ParseFrame;
+
+
+/**
+ * abbreviations used:
+ * SS = star style
+ */
+
+/**
+ * special strings to mark a part of the input file where
+ * uncrustify shall not change anything
+ */
+#define UNCRUSTIFY_OFF_TEXT " *INDENT-OFF*"
+#define UNCRUSTIFY_ON_TEXT " *INDENT-ON*"
+
+//! returns type (with removed reference) of a variable
+#define noref_decl_t(X) std::remove_reference<decltype((X))>::type
+
+//! returns type (with removed const and reference) of a variable
+#define nocref_decl_t(X) std::remove_const<noref_decl_t((X))>::type
+
+//! static casts Y to the type (with removed reference) of X
+#define s_cast_noref_decl_t(X, Y) static_cast<nocref_decl_t(X)>(Y)
+
+//! performs abs on Y after static casting it to the type (with removed reference) of X
+#define cast_abs(X, Y) s_cast_noref_decl_t(X, abs(Y))
+
+/**
+ * @brief Macro to inform the compiler that a variable is intentionally
+ * not in use.
+ *
+ * @param [in] variableName: The unused variable.
+ */
+#define UNUSED(variableName) ((void)variableName)
+
+
+//! Brace stage enum used in brace_cleanup
+enum class brace_stage_e : unsigned int
+{
+ NONE,
+ PAREN1, //! expected paren after if/catch (C++)/for/switch/synchronized/while
+ OP_PAREN1, //! optional paren after catch (C#)
+ WOD_PAREN, //! while of do parens
+ WOD_SEMI, //! semicolon after while of do
+ BRACE_DO, //! do
+ BRACE2, //! if/catch/else/finally/for/switch/synchronized/while
+ ELSE, //! expecting 'else' after 'if'
+ ELSEIF, //! expecting 'if' after 'else'
+ WHILE, //! expecting 'while' after 'do'
+ CATCH, //! expecting 'catch' or 'finally' after 'try'
+ CATCH_WHEN, //! optional 'when' after 'catch'
+};
+
+
+enum class char_encoding_e : unsigned int
+{
+ e_ASCII, //! 0-127
+ e_BYTE, //! 0-255, not UTF-8
+ e_UTF8, //! utf 8 bit wide
+ e_UTF16_LE, //! utf 16 bit wide, little endian
+ e_UTF16_BE //! utf 16 bit wide, big endian
+};
+
+
+class Chunk; //forward declaration
+
+
+/**
+ * Sort of like the aligning stuff, but the token indent is relative to the
+ * indent of another chunk. This is needed, as that chunk may be aligned and
+ * so the indent cannot be determined in the indent code.
+ */
+struct indent_ptr_t
+{
+ Chunk *ref;
+ int delta;
+};
+
+
+struct align_ptr_t
+{
+ Chunk *next; //! nullptr or the chunk that should be under this one
+ bool right_align; //! AlignStack.m_right_align
+ size_t star_style; //! AlignStack.m_star_style
+ size_t amp_style; //! AlignStack.m_amp_style
+ int gap; //! AlignStack.m_gap
+
+ /*
+ * col_adj is the amount to alter the column for the token.
+ * For example, a dangling '*' would be set to -1.
+ * A right-aligned word would be a positive value.
+ */
+ int col_adj;
+ Chunk *ref;
+ Chunk *start;
+};
+
+
+// for debugging purpose only
+typedef std::pair<size_t, char *> Track_nr; // track for "trackNumber" and "rule"
+typedef std::vector<Track_nr> track_list; // liste for many tracks
+
+//! list of all programming languages Uncrustify supports
+enum lang_flag_e
+{
+ LANG_C = 0x0001,
+ LANG_CPP = 0x0002,
+ LANG_D = 0x0004,
+ LANG_CS = 0x0008, //! C# (C-Sharp)
+ LANG_JAVA = 0x0010,
+ LANG_OC = 0x0020, //! Objective-C
+ LANG_VALA = 0x0040,
+ LANG_PAWN = 0x0080,
+ LANG_ECMA = 0x0100, //! ECMA Script (JavaScript)
+
+ LANG_ALLC = 0x017f, /** LANG_C | LANG_CPP | LANG_D | LANG_CS |
+ * LANG_JAVA | LANG_OC | LANG_VALA | LANG_ECMA */
+ LANG_ALL = 0x0fff, //! applies to all languages
+
+ FLAG_HDR = 0x2000, /*<< Header file for C family languages */
+ FLAG_DIG = 0x4000, //! digraph/trigraph
+ FLAG_PP = 0x8000, //! only appears in a preprocessor
+};
+
+//! Pattern classes for special keywords
+enum class pattern_class_e : unsigned int
+{
+ NONE,
+ BRACED, /** keyword + braced statement:
+ * do, try, finally, body, unittest, unsafe, volatile
+ * add, get, remove, set */
+ PBRACED, /** keyword + parens + braced statement:
+ * if, elseif, switch, for, while, synchronized,
+ * using, lock, with, version, CT_D_SCOPE_IF */
+ OPBRACED, /** keyword + optional parens + braced statement:
+ * catch, version, debug */
+ VBRACED, /** keyword + value + braced statement:
+ * namespace */
+ PAREN, /** keyword + parens:
+ * while-of-do */
+ OPPAREN, /** keyword + optional parens:
+ * invariant (D lang) */
+ ELSE, /** Special case of pattern_class_e::BRACED for handling CT_IF
+ * else */
+};
+
+//! used to link language keywords with some addition information
+struct chunk_tag_t
+{
+ const char *tag; //! name of the keyword e.g. "bool"
+ E_Token type; //! uncrustify type assigned to that keyword
+ size_t lang_flags; //! programming language that uses this keyword
+};
+
+
+struct align_t
+{
+ size_t col;
+ E_Token type;
+ size_t len; //! length of the token + space
+};
+
+//! holds information and data of a file
+struct file_mem
+{
+ std::vector<UINT8> raw; //! raw content of file
+ std::deque<int> data; //! processed content of file
+ bool bom;
+ char_encoding_e enc; //! character encoding of file ASCII, utf, etc.
+#ifdef HAVE_UTIME_H
+ struct utimbuf utb;
+#endif
+};
+
+enum class unc_stage_e : unsigned int
+{
+ TOKENIZE,
+ HEADER,
+ TOKENIZE_CLEANUP,
+ BRACE_CLEANUP,
+ FIX_SYMBOLS,
+ MARK_COMMENTS,
+ COMBINE_LABELS,
+ OTHER,
+ CLEANUP
+};
+
+struct cp_data_t
+{
+ std::deque<UINT8> *bout;
+ FILE *fout;
+ int last_char;
+ bool do_check;
+ unc_stage_e unc_stage;
+ int check_fail_cnt; //! total failure count
+ bool if_changed;
+
+ UINT32 error_count; //! counts how many errors occurred so far
+ std::string filename;
+
+ file_mem file_hdr; // for cmt_insert_file_header
+ file_mem file_ftr; // for cmt_insert_file_footer
+ file_mem func_hdr; // for cmt_insert_func_header
+ file_mem oc_msg_hdr; // for cmt_insert_oc_msg_header
+ file_mem class_hdr; // for cmt_insert_class_header
+ file_mem reflow_fold_regex; // for cmt_reflow_fold_regex_file
+
+ size_t lang_flags; //! defines the language of the source input
+ bool lang_forced; //! overwrites automatic language detection
+
+ bool unc_off;
+ bool unc_off_used; //! true if the `disable_processing_cmt` option was actively used in the processed file
+ UINT32 line_number;
+ size_t column; //! column for parsing
+ UINT16 spaces; //! space count on output
+
+ int ifdef_over_whole_file;
+
+ bool frag; //! activates code fragment option
+ UINT32 frag_cols;
+
+ // stuff to auto-detect line endings
+ UINT32 le_counts[uncrustify::line_end_styles];
+ unc_text newline;
+
+ int did_newline; //! flag indicates if a newline was added or converted
+ E_Token in_preproc;
+ int preproc_ncnl_count;
+ bool output_trailspace;
+ bool output_tab_as_space;
+
+ bool bom;
+ char_encoding_e enc;
+
+ // bumped up when a line is split or indented
+ int changes;
+ int pass_count; //! indicates how often the chunk list shall be processed
+
+ align_t al[uncrustify::limits::AL_SIZE];
+ size_t al_cnt;
+ bool al_c99_array;
+
+ bool warned_unable_string_replace_tab_chars;
+
+ int pp_level; // TODO: can this ever be -1?
+
+ const char *phase_name;
+ const char *dumped_file;
+ const char *html_file = nullptr; // for debugging purpose only
+};
+
+extern cp_data_t cpd; // TODO: can we avoid this external variable?
+
+const char *get_brace_stage_name(brace_stage_e brace_stage);
+
+const char *get_unc_stage_name(unc_stage_e unc_stage);
+
+#endif /* UNCRUSTIFY_TYPES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_version.h.in b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_version.h.in
new file mode 100644
index 00000000..079e0fa6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/uncrustify_version.h.in
@@ -0,0 +1,18 @@
+/**
+ * @file uncrustify_version.h
+ * Simply defines UNCRUSTIFY_VERSION.
+ * I don't particularly like how autoconf and friends handle the version...
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef UNCRUSTIFY_VERSION_H_INCLUDED
+#define UNCRUSTIFY_VERSION_H_INCLUDED
+
+#ifdef DEBUG
+#define UNCRUSTIFY_VERSION "Uncrustify_d-@UNCRUSTIFY_VERSION@"
+#else
+#define UNCRUSTIFY_VERSION "Uncrustify-@UNCRUSTIFY_VERSION@"
+#endif
+
+#endif /* UNCRUSTIFY_VERSION_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.cpp
new file mode 100644
index 00000000..172cda28
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.cpp
@@ -0,0 +1,580 @@
+/**
+ * @file unicode.cpp
+ * Detects, read and writes characters in the proper format.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "unicode.h"
+
+
+using namespace std;
+
+
+//! See if all characters are ASCII (0-127)
+static bool is_ascii(const vector<UINT8> &data, size_t &non_ascii_cnt, size_t &zero_cnt);
+
+
+//! Convert the array of bytes into an array of ints
+static bool decode_bytes(const vector<UINT8> &in_data, deque<int> &out_data);
+
+
+/**
+ * Decode UTF-8 sequences from in_data and put the chars in out_data.
+ * If there are any decoding errors, then return false.
+ */
+static bool decode_utf8(const vector<UINT8> &in_data, deque<int> &out_data);
+
+
+/**
+ * Extract 2 bytes from the stream and increment idx by 2
+ *
+ * @param in byte vector with input data
+ * @param idx index points to working position in vector
+ */
+static int get_word(const vector<UINT8> &in_data, size_t &idx, bool be);
+
+
+/**
+ * Decode a UTF-16 sequence.
+ * Sets enc based on the BOM.
+ * Must have the BOM as the first two bytes.
+ */
+static bool decode_utf16(const vector<UINT8> &in_data, deque<int> &out_data, char_encoding_e &enc);
+
+
+/**
+ * Looks for the BOM of UTF-16 BE/LE and UTF-8.
+ * If found, set enc and return true.
+ * Sets enc to char_encoding_e::e_ASCII and returns false if not found.
+ */
+static bool decode_bom(const vector<UINT8> &in_data, char_encoding_e &enc);
+
+
+//! Write for ASCII and BYTE encoding
+static void write_byte(int ch);
+
+
+//! Writes a single character to a file using UTF-8 encoding
+static void write_utf8(int ch);
+
+
+static void write_utf16(int ch, bool be);
+
+
+static bool is_ascii(const vector<UINT8> &data, size_t &non_ascii_cnt, size_t &zero_cnt)
+{
+ non_ascii_cnt = 0;
+ zero_cnt = 0;
+
+ for (unsigned char value : data)
+ {
+ if (value & 0x80)
+ {
+ non_ascii_cnt++;
+ }
+
+ if (!value)
+ {
+ zero_cnt++;
+ }
+ }
+
+ return((non_ascii_cnt + zero_cnt) == 0);
+}
+
+
+static bool decode_bytes(const vector<UINT8> &in_data, deque<int> &out_data)
+{
+ out_data.resize(in_data.size());
+
+ for (size_t idx = 0; idx < in_data.size(); idx++)
+ {
+ out_data[idx] = in_data[idx];
+ }
+
+ return(true);
+}
+
+
+void encode_utf8(int ch, vector<UINT8> &res)
+{
+ if (ch < 0)
+ {
+ // illegal code - do not store
+ }
+ else if (ch < 0x80)
+ {
+ // 0xxxxxxx
+ res.push_back(ch);
+ }
+ else if (ch < 0x0800)
+ {
+ // 110xxxxx 10xxxxxx
+ res.push_back(0xC0 | (ch >> 6));
+ res.push_back(0x80 | (ch & 0x3f));
+ }
+ else if (ch < 0x10000)
+ {
+ // 1110xxxx 10xxxxxx 10xxxxxx
+ res.push_back(0xE0 | (ch >> 12));
+ res.push_back(0x80 | ((ch >> 6) & 0x3f));
+ res.push_back(0x80 | (ch & 0x3f));
+ }
+ else if (ch < 0x200000)
+ {
+ // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ res.push_back(0xF0 | (ch >> 18));
+ res.push_back(0x80 | ((ch >> 12) & 0x3f));
+ res.push_back(0x80 | ((ch >> 6) & 0x3f));
+ res.push_back(0x80 | (ch & 0x3f));
+ }
+ else if (ch < 0x4000000)
+ {
+ // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ res.push_back(0xF8 | (ch >> 24));
+ res.push_back(0x80 | ((ch >> 18) & 0x3f));
+ res.push_back(0x80 | ((ch >> 12) & 0x3f));
+ res.push_back(0x80 | ((ch >> 6) & 0x3f));
+ res.push_back(0x80 | (ch & 0x3f));
+ }
+ else // (ch <= 0x7fffffff)
+ {
+ // 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ res.push_back(0xFC | (ch >> 30));
+ res.push_back(0x80 | ((ch >> 24) & 0x3f));
+ res.push_back(0x80 | ((ch >> 18) & 0x3f));
+ res.push_back(0x80 | ((ch >> 12) & 0x3f));
+ res.push_back(0x80 | ((ch >> 6) & 0x3f));
+ res.push_back(0x80 | (ch & 0x3f));
+ }
+} // encode_utf8
+
+
+static bool decode_utf8(const vector<UINT8> &in_data, deque<int> &out_data)
+{
+ size_t idx = 0;
+ int cnt;
+
+ out_data.clear();
+
+ // check for UTF-8 BOM silliness and skip
+ if (in_data.size() >= 3)
+ {
+ if ( (in_data[0] == 0xef)
+ && (in_data[1] == 0xbb)
+ && (in_data[2] == 0xbf))
+ {
+ idx = 3; // skip it
+ }
+ }
+
+ while (idx < in_data.size())
+ {
+ int ch = in_data[idx++];
+
+ if (ch < 0x80) // 1-byte sequence
+ {
+ out_data.push_back(ch);
+ continue;
+ }
+ else if ((ch & 0xE0) == 0xC0) // 2-byte sequence
+ {
+ ch &= 0x1F;
+ cnt = 1;
+ }
+ else if ((ch & 0xF0) == 0xE0) // 3-byte sequence
+ {
+ ch &= 0x0F;
+ cnt = 2;
+ }
+ else if ((ch & 0xF8) == 0xF0) // 4-byte sequence
+ {
+ ch &= 0x07;
+ cnt = 3;
+ }
+ else if ((ch & 0xFC) == 0xF8) // 5-byte sequence
+ {
+ ch &= 0x03;
+ cnt = 4;
+ }
+ else if ((ch & 0xFE) == 0xFC) // 6-byte sequence
+ {
+ ch &= 0x01;
+ cnt = 5;
+ }
+ else
+ {
+ // invalid UTF-8 sequence
+ return(false);
+ }
+
+ while ( cnt-- > 0
+ && idx < in_data.size())
+ {
+ int tmp = in_data[idx++];
+
+ if ((tmp & 0xC0) != 0x80)
+ {
+ // invalid UTF-8 sequence
+ return(false);
+ }
+ ch = (ch << 6) | (tmp & 0x3f);
+ }
+
+ if (cnt >= 0)
+ {
+ // short UTF-8 sequence
+ return(false);
+ }
+ out_data.push_back(ch);
+ }
+ return(true);
+} // decode_utf8
+
+
+static int get_word(const vector<UINT8> &in_data, size_t &idx, bool be)
+{
+ int ch;
+
+ if ((idx + 2) > in_data.size())
+ {
+ ch = -1;
+ }
+ else if (be)
+ {
+ ch = (in_data[idx] << 8) | in_data[idx + 1];
+ }
+ else
+ {
+ ch = in_data[idx] | (in_data[idx + 1] << 8);
+ }
+ idx += 2;
+ return(ch);
+}
+
+
+static bool decode_utf16(const vector<UINT8> &in_data, deque<int> &out_data, char_encoding_e &enc)
+{
+ out_data.clear();
+
+ if (in_data.size() & 1)
+ {
+ // can't have and odd length
+ return(false);
+ }
+
+ if (in_data.size() < 2)
+ {
+ // we require the BOM or at least 1 char
+ return(false);
+ }
+ size_t idx = 2;
+
+ if ( (in_data[0] == 0xfe)
+ && (in_data[1] == 0xff))
+ {
+ enc = char_encoding_e::e_UTF16_BE;
+ }
+ else if ( (in_data[0] == 0xff)
+ && (in_data[1] == 0xfe))
+ {
+ enc = char_encoding_e::e_UTF16_LE;
+ }
+ else
+ {
+ /*
+ * If we have a few words, we can take a guess, assuming the first few
+ * chars are ASCII
+ */
+ enc = char_encoding_e::e_ASCII;
+ idx = 0;
+
+ if (in_data.size() >= 6)
+ {
+ if ( (in_data[0] == 0)
+ && (in_data[2] == 0)
+ && (in_data[4] == 0))
+ {
+ enc = char_encoding_e::e_UTF16_BE;
+ }
+ else if ( (in_data[1] == 0)
+ && (in_data[3] == 0)
+ && (in_data[5] == 0))
+ {
+ enc = char_encoding_e::e_UTF16_LE;
+ }
+ }
+
+ if (enc == char_encoding_e::e_ASCII)
+ {
+ return(false);
+ }
+ }
+ bool be = (enc == char_encoding_e::e_UTF16_BE);
+
+ while (idx < in_data.size())
+ {
+ int ch = get_word(in_data, idx, be);
+
+ if ((ch & 0xfc00) == 0xd800)
+ {
+ ch &= 0x3ff;
+ ch <<= 10;
+ int tmp = get_word(in_data, idx, be);
+
+ if ((tmp & 0xfc00) != 0xdc00)
+ {
+ return(false);
+ }
+ ch |= (tmp & 0x3ff);
+ ch += 0x10000;
+ out_data.push_back(ch);
+ }
+ else if ( ( ch >= 0
+ && ch < 0xD800)
+ || ch >= 0xE000)
+ {
+ out_data.push_back(ch);
+ }
+ else
+ {
+ // invalid character
+ return(false);
+ }
+ }
+ return(true);
+} // decode_utf16
+
+
+static bool decode_bom(const vector<UINT8> &in_data, char_encoding_e &enc)
+{
+ enc = char_encoding_e::e_ASCII;
+
+ if (in_data.size() >= 2)
+ {
+ if ( (in_data[0] == 0xfe)
+ && (in_data[1] == 0xff))
+ {
+ enc = char_encoding_e::e_UTF16_BE;
+ return(true);
+ }
+
+ if ( (in_data[0] == 0xff)
+ && (in_data[1] == 0xfe))
+ {
+ enc = char_encoding_e::e_UTF16_LE;
+ return(true);
+ }
+
+ if ( (in_data.size() >= 3)
+ && (in_data[0] == 0xef)
+ && (in_data[1] == 0xbb)
+ && (in_data[2] == 0xbf))
+ {
+ enc = char_encoding_e::e_UTF8;
+ return(true);
+ }
+ }
+ return(false);
+}
+
+
+bool decode_unicode(const vector<UINT8> &in_data, deque<int> &out_data, char_encoding_e &enc, bool &has_bom)
+{
+ // check for a BOM
+ if (decode_bom(in_data, enc))
+ {
+ has_bom = true;
+
+ if (enc == char_encoding_e::e_UTF8)
+ {
+ return(decode_utf8(in_data, out_data));
+ }
+ return(decode_utf16(in_data, out_data, enc));
+ }
+ has_bom = false;
+
+ // Check for simple ASCII
+ size_t non_ascii_cnt;
+ size_t zero_cnt;
+
+ if (is_ascii(in_data, non_ascii_cnt, zero_cnt))
+ {
+ enc = char_encoding_e::e_ASCII;
+ return(decode_bytes(in_data, out_data));
+ }
+
+ // There are a lot of 0's in UTF-16 (~50%)
+ if ( (zero_cnt > (in_data.size() / 4))
+ && (zero_cnt <= (in_data.size() / 2)))
+ {
+ // likely is UTF-16
+ if (decode_utf16(in_data, out_data, enc))
+ {
+ return(true);
+ }
+ }
+
+ if (decode_utf8(in_data, out_data))
+ {
+ enc = char_encoding_e::e_UTF8;
+ return(true);
+ }
+ // it is an unrecognized byte sequence
+ enc = char_encoding_e::e_BYTE;
+ return(decode_bytes(in_data, out_data));
+} // decode_unicode
+
+
+static void write_byte(int ch)
+{
+ if ((ch & 0xff) == ch)
+ {
+ if (cpd.fout)
+ {
+ fputc(ch, cpd.fout);
+ }
+
+ if (cpd.bout)
+ {
+ cpd.bout->push_back(static_cast<UINT8>(ch));
+ }
+ }
+ else
+ {
+ // illegal code - do not store
+ }
+}
+
+
+static void write_utf8(int ch)
+{
+ vector<UINT8> vv;
+
+ vv.reserve(6);
+
+ encode_utf8(ch, vv);
+
+ for (unsigned char char_val : vv)
+ {
+ write_byte(char_val);
+ }
+}
+
+
+static void write_utf16(int ch, bool be)
+{
+ // U+0000 to U+D7FF and U+E000 to U+FFFF
+ if ( ( ch >= 0
+ && ch < 0xD800)
+ || ( ch >= 0xE000
+ && ch < 0x10000))
+ {
+ if (be)
+ {
+ write_byte(ch >> 8);
+ write_byte(ch & 0xff);
+ }
+ else
+ {
+ write_byte(ch & 0xff);
+ write_byte(ch >> 8);
+ }
+ }
+ else if ( ch >= 0x10000
+ && ch < 0x110000)
+ {
+ int v1 = ch - 0x10000;
+ int w1 = 0xD800 + (v1 >> 10);
+ int w2 = 0xDC00 + (v1 & 0x3ff);
+
+ if (be)
+ {
+ write_byte(w1 >> 8);
+ write_byte(w1 & 0xff);
+ write_byte(w2 >> 8);
+ write_byte(w2 & 0xff);
+ }
+ else
+ {
+ write_byte(w1 & 0xff);
+ write_byte(w1 >> 8);
+ write_byte(w2 & 0xff);
+ write_byte(w2 >> 8);
+ }
+ }
+ else
+ {
+ // illegal code - do not store
+ }
+} // write_utf16
+
+
+void write_bom(void)
+{
+ switch (cpd.enc)
+ {
+ case char_encoding_e::e_UTF8:
+ write_byte(0xef);
+ write_byte(0xbb);
+ write_byte(0xbf);
+ break;
+
+ case char_encoding_e::e_UTF16_LE:
+ write_utf16(0xfeff, false);
+ break;
+
+ case char_encoding_e::e_UTF16_BE:
+ write_utf16(0xfeff, true);
+ break;
+
+ default:
+ // char_encoding_e::e_ASCII
+ // char_encoding_e::e_BYTE
+ // do nothing
+ // Coveralls will complain
+ break;
+ }
+}
+
+
+void write_char(int ch)
+{
+ if (ch >= 0)
+ {
+ switch (cpd.enc)
+ {
+ case char_encoding_e::e_BYTE:
+ write_byte(ch & 0xff);
+ break;
+
+ case char_encoding_e::e_ASCII:
+ default:
+ write_byte(ch);
+ break;
+
+ case char_encoding_e::e_UTF8:
+ write_utf8(ch);
+ break;
+
+ case char_encoding_e::e_UTF16_LE:
+ write_utf16(ch, false);
+ break;
+
+ case char_encoding_e::e_UTF16_BE:
+ write_utf16(ch, true);
+ break;
+ }
+ }
+}
+
+
+void write_string(const unc_text &text)
+{
+ for (size_t idx = 0; idx < text.size(); idx++)
+ {
+ write_char(text[idx]);
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.h
new file mode 100644
index 00000000..e9cbd97c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/unicode.h
@@ -0,0 +1,34 @@
+/**
+ * @file unicode.h
+ * prototypes for unicode.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef UNICODE_H_INCLUDED
+#define UNICODE_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+void write_bom(void);
+
+
+/**
+ * @param ch the 31-bit char value
+ */
+void write_char(int ch);
+
+
+void write_string(const unc_text &text);
+
+
+//! Figure out the encoding and convert to an int sequence
+bool decode_unicode(const std::vector<UINT8> &in_data, std::deque<int> &out_data, char_encoding_e &enc, bool &has_bom);
+
+
+void encode_utf8(int ch, std::vector<UINT8> &res);
+
+
+#endif /* UNICODE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.cpp
new file mode 100644
index 00000000..eff612be
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.cpp
@@ -0,0 +1,372 @@
+/**
+ * @file universalindentgui.cpp
+ * Exports the config file for UniversalIndentGUI
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * October 2015, 2016
+ * @license GPL v2+
+ */
+#include "universalindentgui.h"
+
+#include "error_types.h"
+#include "log_rules.h"
+#include "prototypes.h"
+#include "unc_ctype.h"
+#include "uncrustify.h"
+#include "uncrustify_version.h"
+
+#include <cstdio>
+#include <vector>
+
+
+constexpr static auto LCURRENT = LOTHER;
+
+using namespace std;
+
+
+std::vector<uncrustify::OptionGroup *> get_option_groups()
+{
+ std::vector<uncrustify::OptionGroup *> groups;
+ size_t i = 0;
+
+ while (auto *const g = uncrustify::get_option_group(i))
+ {
+ groups.push_back(g);
+ ++i;
+ }
+ return(groups);
+}
+
+
+void print_option_choices(FILE *pfile, uncrustify::GenericOption *option,
+ char const *key = "Choices")
+{
+ fprintf(pfile, "%s=", key);
+
+ for (auto c = option->possibleValues(); *c; ++c)
+ {
+ fprintf(pfile, "%s=%s%c", option->name(), *c, c[1] ? '|' : '\n');
+ }
+}
+
+
+void print_universal_indent_cfg(FILE *pfile)
+{
+ const char *p_name;
+ char ch = '=';
+ const auto &groups = get_option_groups();
+ size_t idx;
+
+#if defined (DEBUG) && !defined (WIN32)
+ vector<size_t> allGroups;
+ allGroups.reserve(16);
+ // first run to get the first option number of each group/categorie
+ size_t optionNumber = 0;
+ bool firstOptionNumberSet = false;
+
+ for (idx = 0; idx < groups.size(); ++idx)
+ {
+ const auto *p_grp = groups[idx];
+
+ for (auto *const option : p_grp->options)
+ {
+ UNUSED(option);
+
+ if (!firstOptionNumberSet)
+ {
+ allGroups[idx] = optionNumber;
+ firstOptionNumberSet = true;
+ }
+ optionNumber++;
+ } // for (auto *const option : p_grp->options)
+
+ firstOptionNumberSet = false;
+ } // end of first run
+
+//#else
+// UNUSED(allGroups);
+#endif // DEBUG
+
+ // second run
+ // Dump the header and the categories
+ fprintf(pfile, "[header]\n");
+
+ // Add all the categories
+ //const auto &groups = get_option_groups();
+ ch = '=';
+
+ fprintf(pfile, "categories");
+ idx = 0;
+#if defined (DEBUG) && !defined (WIN32)
+ optionNumber = 0;
+#endif // DEBUG
+
+ for (auto *const g : groups)
+ {
+ fputc(ch, pfile);
+ ch = '|';
+
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "(%zu)", allGroups[idx]);
+#endif // DEBUG
+
+ // Write description, stripping leading and trailing newlines
+ for (auto dc = g->description + 1; *(dc + 1); ++dc)
+ {
+ fputc(*dc, pfile);
+ }
+
+ idx++;
+ }
+
+ fprintf(pfile, "\n");
+
+ fprintf(pfile,
+ "cfgFileParameterEnding=cr\n"
+ "configFilename=uncrustify.cfg\n");
+
+
+ // Add all the recognized file extensions
+ ch = '=';
+ int fileIdx = 0;
+ fprintf(pfile, "fileTypes");
+
+ while ((p_name = get_file_extension(fileIdx)) != nullptr)
+ {
+ fprintf(pfile, "%c*%s", ch, p_name);
+ ch = '|';
+ }
+ fprintf(pfile, "\n");
+
+ // Add the rest of the constant file header
+ fprintf(pfile,
+ "indenterFileName=uncrustify\n"
+ "indenterName=Uncrustify (C, C++, C#, ObjectiveC, D, Java, Pawn, VALA)\n"
+ "inputFileName=indentinput\n"
+ "inputFileParameter=\"-f \"\n"
+ "manual=http://uncrustify.sourceforge.net/config.txt\n"
+ "outputFileName=indentoutput\n"
+ "outputFileParameter=\"-o \"\n"
+ "stringparaminquotes=false\n"
+ "parameterOrder=ipo\n"
+ "showHelpParameter=-h\n"
+ "stringparaminquotes=false\n"
+ "useCfgFileParameter=\"-c \"\n");
+
+ fprintf(pfile, "version=%s\n", UNCRUSTIFY_VERSION);
+
+ ch = '=';
+
+ // Now add each option
+ for (idx = 0; idx < groups.size(); ++idx)
+ {
+ const auto *p_grp = groups[idx];
+
+ for (auto *const option : p_grp->options)
+ {
+ /*
+ * Create a better readable name from the options name
+ * by replacing '_' by a space and use some upper case characters.
+ */
+ char *optionNameReadable = new char[strlen(option->name()) + 1];
+ strcpy(optionNameReadable, option->name());
+
+ bool was_space = true;
+
+ for (char *character = optionNameReadable; *character != 0; character++)
+ {
+ if (*character == '_')
+ {
+ *character = ' ';
+ was_space = true;
+ }
+ else if (was_space)
+ {
+ *character = unc_toupper(*character);
+ was_space = false;
+ }
+ }
+
+ fprintf(pfile, "\n[%s]\n", optionNameReadable);
+ fprintf(pfile, "Category=%zu\n", idx);
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "Description=\"<html>(%zu)", optionNumber);
+#else // DEBUG
+ fprintf(pfile, "Description=\"<html>");
+#endif // DEBUG
+
+ // Skip first character, which is always a newline
+ const char *tmp = option->description() + 1;
+ ch = 0;
+
+ // Output the description which may contain forbidden chars, skipping
+ // the last character which is always an extra newline
+ while ( *tmp != 0
+ && *(tmp + 1) != 0)
+ {
+ switch (*tmp)
+ {
+ case '<':
+ fputs("&lt;", pfile);
+ break;
+
+ case '>':
+ fputs("&gt;", pfile);
+ break;
+
+ case '&':
+ fputs("&amp;", pfile);
+ break;
+
+ case '\n':
+ fputs("<br/>", pfile);
+ break;
+
+ default:
+ fputc(*tmp, pfile);
+ }
+ tmp++;
+ }
+ const auto ds = option->defaultStr();
+
+ if (!ds.empty())
+ {
+ fprintf(pfile, "<br/><br/>Default: %s", ds.c_str());
+ }
+ fprintf(pfile, "</html>\"\n");
+
+ // Handle some options independent of their type and most by their type.
+ log_rule_B("indent_with_tabs");
+
+ if (option == &uncrustify::options::indent_with_tabs)
+ {
+ // Indenting with tabs selector becomes a multiple selector and not
+ // only a number. Also it is by default enabled.
+ fprintf(pfile, "Enabled=true\n");
+ fprintf(pfile, "EditorType=multiple\n");
+ fprintf(pfile, "Choices=\"%s=0|%s=1|%s=2\"\n",
+ option->name(), option->name(), option->name());
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "ChoicesReadable=\"(%zu)Spaces only|(%zu)Indent with tabs, align with spaces|(%zu)Indent and align with tabs\"\n",
+ optionNumber, optionNumber, optionNumber);
+#else // DEBUG
+ fprintf(pfile, "ChoicesReadable=\"Spaces only|Indent with tabs, align with spaces|Indent and align with tabs\"\n");
+#endif // DEBUG
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ }
+ else
+ {
+ // All not specially handled options are created only dependent by
+ // their type.
+ fprintf(pfile, "Enabled=false\n");
+
+ switch (option->type())
+ {
+ case uncrustify::OT_BOOL:
+ fprintf(pfile, "EditorType=boolean\n");
+ print_option_choices(pfile, option, "TrueFalse");
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ break;
+
+ case uncrustify::OT_IARF:
+ fprintf(pfile, "EditorType=multiple\n");
+ print_option_choices(pfile, option);
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "ChoicesReadable=\"(%zu)Ignore %s|(%zu)Add %s|(%zu)Remove %s|(%zu)Force %s\"\n",
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable);
+#else // DEBUG
+ // 0 1 2 3
+ fprintf(pfile, "ChoicesReadable=\"Ignore %s|Add %s|Remove %s|Force %s\"\n",
+ optionNameReadable, optionNameReadable, optionNameReadable, optionNameReadable);
+#endif // DEBUG
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ break;
+
+ case uncrustify::OT_NUM:
+ fprintf(pfile, "EditorType=numeric\n");
+ fprintf(pfile, "CallName=\"%s=\"\n", option->name());
+ fprintf(pfile, "MinVal=%s\n", option->minStr().c_str());
+ fprintf(pfile, "MaxVal=%s\n", option->maxStr().c_str());
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ break;
+
+ case uncrustify::OT_UNUM:
+ fprintf(pfile, "EditorType=numeric\n");
+ fprintf(pfile, "CallName=\"%s=\"\n", option->name());
+ fprintf(pfile, "MinVal=%s\n", option->minStr().c_str());
+ fprintf(pfile, "MaxVal=%s\n", option->maxStr().c_str());
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ break;
+
+ case uncrustify::OT_LINEEND:
+ fprintf(pfile, "EditorType=multiple\n");
+ print_option_choices(pfile, option);
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "ChoicesReadable=\"(%zu)Newlines Unix|(%zu)Newlines Win|(%zu)Newlines Mac|(%zu)Newlines Auto\"\n",
+ optionNumber, optionNumber, optionNumber, optionNumber);
+#else // DEBUG
+ fprintf(pfile, "ChoicesReadable=\"Newlines Unix|Newlines Win|Newlines Mac|Newlines Auto\"\n");
+#endif // DEBUG
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ break;
+
+ case uncrustify::OT_TOKENPOS:
+ fprintf(pfile, "EditorType=multiple\n");
+ // Issue #2300-a
+ print_option_choices(pfile, option);
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "ChoicesReadable=\"(%zu)Ignore %s|(%zu)Break %s|(%zu)Force %s|(%zu)Lead %s|(%zu)Trail %s|",
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable);
+#else // DEBUG
+ // 0 1 2 4 8
+ fprintf(pfile, "ChoicesReadable=\"Ignore %s|Break %s|Force %s|Lead %s|Trail %s|",
+ optionNameReadable, optionNameReadable, optionNameReadable,
+ optionNameReadable, optionNameReadable);
+#endif // DEBUG
+ // 16 5 6 9 10
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "(%zu)Join %s|(%zu)Lead Break %s|(%zu)Lead Force %s|(%zu)Trail Break %s|(%zu)Trail Force %s\"\n",
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable,
+ optionNumber, optionNameReadable);
+#else // DEBUG
+ fprintf(pfile, "Join %s|Lead Break %s|Lead Force %s|Trail Break %s|Trail Force %s\"\n",
+ optionNameReadable, optionNameReadable, optionNameReadable,
+ optionNameReadable, optionNameReadable);
+#endif // DEBUG
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ break;
+
+ case uncrustify::OT_STRING:
+ {
+ fprintf(pfile, "CallName=%s=\n", option->name());
+ fprintf(pfile, "EditorType=string\n");
+ fprintf(pfile, "ValueDefault=%s\n", option->str().c_str());
+ break;
+ }
+
+ default:
+ fprintf(stderr, "FATAL: Illegal option type %d for '%s'\n",
+ static_cast<int>(option->type()), option->name());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ break;
+ } // switch
+ }
+#if defined (DEBUG) && !defined (WIN32)
+ optionNumber++;
+#endif // DEBUG
+ delete[] optionNameReadable;
+ } // for (auto *const option : p_grp->options)
+ }
+} // print_universal_indent_cfg
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.h
new file mode 100644
index 00000000..35a65167
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/universalindentgui.h
@@ -0,0 +1,17 @@
+/**
+ * @file universalindentgui.h
+ * prototypes for universalindentgui.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef UNIVERSALINDENTGUI_H_INCLUDED
+#define UNIVERSALINDENTGUI_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+void print_universal_indent_cfg(FILE *pfile);
+
+
+#endif /* UNIVERSALINDENTGUI_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.cpp
new file mode 100644
index 00000000..a3dbeab4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.cpp
@@ -0,0 +1,923 @@
+/**
+ * @file width.cpp
+ * Limits line width.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "width.h"
+
+#include "indent.h"
+#include "newlines.h"
+#include "prototypes.h"
+
+
+constexpr static auto LCURRENT = LSPLIT;
+
+using namespace uncrustify;
+
+
+/**
+ * abbreviations used:
+ * - fparen = function parenthesis
+ */
+
+struct cw_entry
+{
+ Chunk *pc;
+ size_t pri;
+};
+
+
+struct token_pri
+{
+ E_Token tok;
+ size_t pri;
+};
+
+
+static inline bool is_past_width(Chunk *pc);
+
+
+//! Split right after the chunk
+static void split_before_chunk(Chunk *pc);
+
+
+static size_t get_split_pri(E_Token tok);
+
+
+/**
+ * Checks to see if pc is a better spot to split.
+ * This should only be called going BACKWARDS (ie prev)
+ * A lower level wins
+ *
+ * Splitting Preference:
+ * - semicolon
+ * - comma
+ * - boolean op
+ * - comparison
+ * - arithmetic op
+ * - assignment
+ * - concatenated strings
+ * - ? :
+ * - function open paren not followed by close paren
+ */
+static void try_split_here(cw_entry &ent, Chunk *pc);
+
+
+/**
+ * Scan backwards to find the most appropriate spot to split the line
+ * and insert a newline.
+ *
+ * See if this needs special function handling.
+ * Scan backwards and find the best token for the split.
+ *
+ * @param start The first chunk that exceeded the limit
+ */
+static bool split_line(Chunk *pc);
+
+
+/**
+ * Figures out where to split a function def/proto/call
+ *
+ * For function prototypes and definition. Also function calls where
+ * level == brace_level:
+ * - find the open function parenthesis
+ * + if it doesn't have a newline right after it
+ * * see if all parameters will fit individually after the paren
+ * * if not, throw a newline after the open paren & return
+ * - scan backwards to the open fparen or comma
+ * + if there isn't a newline after that item, add one & return
+ * + otherwise, add a newline before the start token
+ *
+ * @param start the offending token
+ * @return the token that should have a newline
+ * inserted before it
+ */
+static void split_fcn_params(Chunk *start);
+
+
+/**
+ * Figures out where to split a template
+ *
+ *
+ * @param start the offending token
+ */
+static void split_template(Chunk *start);
+
+
+/**
+ * Splits the parameters at every comma that is at the fparen level.
+ *
+ * @param start the offending token
+ */
+static void split_fcn_params_full(Chunk *start);
+
+
+/**
+ * A for statement is too long.
+ * Step backwards and forwards to find the semicolons
+ * Try splitting at the semicolons first.
+ * If that doesn't work, then look for a comma at paren level.
+ * If that doesn't work, then look for an assignment at paren level.
+ * If that doesn't work, then give up.
+ */
+static void split_for_stmt(Chunk *start);
+
+
+static inline bool is_past_width(Chunk *pc)
+{
+ // allow char to sit at last column by subtracting 1
+ LOG_FMT(LSPLIT, "%s(%d): orig_line is %zu, orig_col is %zu, for %s\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ log_rule_B("code_width");
+ return((pc->column + pc->Len() - 1) > options::code_width());
+}
+
+
+static void split_before_chunk(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPLIT, "%s(%d): Text() '%s'\n", __func__, __LINE__, pc->Text());
+
+ if ( !chunk_is_newline(pc)
+ && !chunk_is_newline(pc->GetPrev()))
+ {
+ newline_add_before(pc);
+ // reindent needs to include the indent_continue value and was off by one
+ log_rule_B("indent_columns");
+ log_rule_B("indent_continue");
+ reindent_line(pc, pc->brace_level * options::indent_columns() +
+ abs(options::indent_continue()) + 1);
+ cpd.changes++;
+ }
+}
+
+
+void do_code_width(void)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPLIT, "%s(%d)\n", __func__, __LINE__);
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( !chunk_is_newline(pc)
+ && !pc->IsComment()
+ && chunk_is_not_token(pc, CT_SPACE)
+ && is_past_width(pc))
+ {
+ if ( chunk_is_token(pc, CT_VBRACE_CLOSE) // don't break if a vbrace close
+ && chunk_is_last_on_line(pc)) // is the last chunk on its line
+ {
+ continue;
+ }
+ bool split_OK = split_line(pc);
+
+ if (split_OK)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ }
+ else
+ {
+ LOG_FMT(LSPLIT, "%s(%d): Bailed! orig_line is %zu, orig_col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col, pc->Text());
+ break;
+ }
+ }
+ }
+}
+
+
+static const token_pri pri_table[] =
+{
+ { CT_SEMICOLON, 1 },
+ { CT_COMMA, 2 },
+ { CT_BOOL, 3 },
+ { CT_COMPARE, 4 },
+ { CT_SHIFT, 5 },
+ { CT_ARITH, 6 },
+ { CT_CARET, 7 },
+ { CT_ASSIGN, 8 },
+ { CT_STRING, 9 },
+ { CT_FOR_COLON, 10 },
+ //{ CT_DC_MEMBER, 11 },
+ //{ CT_MEMBER, 11 },
+ { CT_QUESTION, 20 }, // allow break in ? : for ls_code_width
+ { CT_COND_COLON, 20 },
+ { CT_FPAREN_OPEN, 21 }, // break after function open paren not followed by close paren
+ { CT_QUALIFIER, 25 },
+ { CT_CLASS, 25 },
+ { CT_STRUCT, 25 },
+ { CT_TYPE, 25 },
+ { CT_TYPENAME, 25 },
+ { CT_VOLATILE, 25 },
+};
+
+
+static size_t get_split_pri(E_Token tok)
+{
+ for (auto token : pri_table)
+ {
+ if (token.tok == tok)
+ {
+ return(token.pri);
+ }
+ }
+
+ return(0);
+}
+
+
+static void try_split_here(cw_entry &ent, Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LSPLIT, "%s(%d): at %s, orig_col=%zu\n", __func__, __LINE__, pc->Text(), pc->orig_col);
+ size_t pc_pri = get_split_pri(pc->type);
+
+ LOG_FMT(LSPLIT, "%s(%d): pc_pri is %zu\n", __func__, __LINE__, pc_pri);
+
+ if (pc_pri == 0)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): pc_pri is 0, return\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+ // Can't split after a newline
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev == nullptr
+ || ( chunk_is_newline(prev)
+ && chunk_is_not_token(pc, CT_STRING)))
+ {
+ if (prev != nullptr)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): Can't split after a newline, orig_line is %zu, return\n",
+ __func__, __LINE__, prev->orig_line);
+ }
+ return;
+ }
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+
+ // Can't split a function without arguments
+ if (chunk_is_token(pc, CT_FPAREN_OPEN))
+ {
+ Chunk *next = pc->GetNext();
+
+ if (chunk_is_token(next, CT_FPAREN_CLOSE))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): Can't split a function without arguments, return\n", __func__, __LINE__);
+ return;
+ }
+ }
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+
+ // Only split concatenated strings
+ if (chunk_is_token(pc, CT_STRING))
+ {
+ Chunk *next = pc->GetNext();
+
+ if (chunk_is_not_token(next, CT_STRING))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): Only split concatenated strings, return\n", __func__, __LINE__);
+ return;
+ }
+ }
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+
+ // keep common groupings unless ls_code_width
+ log_rule_B("ls_code_width");
+
+ if ( !options::ls_code_width()
+ && pc_pri >= 20)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): keep common groupings unless ls_code_width, return\n", __func__, __LINE__);
+ return;
+ }
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+
+ // don't break after last term of a qualified type
+ if (pc_pri == 25)
+ {
+ Chunk *next = pc->GetNext();
+
+ if ( chunk_is_not_token(next, CT_WORD)
+ && (get_split_pri(next->type) != 25))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): don't break after last term of a qualified type, return\n", __func__, __LINE__);
+ return;
+ }
+ }
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+ // Check levels first
+ bool change = false;
+
+ if ( ent.pc == nullptr
+ || pc->level < ent.pc->level)
+ {
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+ change = true;
+ }
+ else
+ {
+ if (pc_pri < ent.pri)
+ {
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+ change = true;
+ }
+ }
+ LOG_FMT(LSPLIT, "%s(%d): change is %s\n", __func__, __LINE__, change ? "TRUE" : "FALSE");
+
+ if (change)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): do the change\n", __func__, __LINE__);
+ ent.pc = pc;
+ ent.pri = pc_pri;
+ }
+} // try_split_here
+
+
+static bool split_line(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPLIT, "%s(%d): start->Text() '%s', orig_line is %zu, orig_col is %zu, type is %s\n",
+ __func__, __LINE__, start->Text(), start->orig_line, start->orig_col, get_token_name(start->type));
+ LOG_FMT(LSPLIT, " start->flags ");
+ log_pcf_flags(LSPLIT, start->flags);
+ LOG_FMT(LSPLIT, " start->parent_type %s, (PCF_IN_FCN_DEF is %s), (PCF_IN_FCN_CALL is %s)\n",
+ get_token_name(get_chunk_parent_type(start)),
+ start->flags.test((PCF_IN_FCN_DEF)) ? "TRUE" : "FALSE",
+ start->flags.test((PCF_IN_FCN_CALL)) ? "TRUE" : "FALSE");
+
+ // break at maximum line length if ls_code_width is true
+ // Issue #2432
+ if (start->flags.test(PCF_ONE_LINER))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): ** ONCE LINER SPLIT **\n", __func__, __LINE__);
+ undo_one_liner(start);
+ newlines_cleanup_braces(false);
+ // Issue #1352
+ cpd.changes++;
+ return(false);
+ }
+ LOG_FMT(LSPLIT, "%s(%d): before ls_code_width\n", __func__, __LINE__);
+
+ log_rule_B("ls_code_width");
+
+ if (options::ls_code_width())
+ {
+ }
+ // Check to see if we are in a for statement
+ else if (start->flags.test(PCF_IN_FOR))
+ {
+ LOG_FMT(LSPLIT, " ** FOR SPLIT **\n");
+ split_for_stmt(start);
+
+ if (!is_past_width(start))
+ {
+ return(true);
+ }
+ LOG_FMT(LSPLIT, "%s(%d): for split didn't work\n", __func__, __LINE__);
+ }
+
+ /*
+ * If this is in a function call or prototype, split on commas or right
+ * after the open parenthesis
+ */
+ else if ( start->flags.test(PCF_IN_FCN_DEF)
+ || get_chunk_parent_type(start) == CT_FUNC_PROTO // Issue #1169
+ || ( (start->level == (start->brace_level + 1))
+ && start->flags.test(PCF_IN_FCN_CALL)))
+ {
+ LOG_FMT(LSPLIT, " ** FUNC SPLIT **\n");
+
+ log_rule_B("ls_func_split_full");
+
+ if (options::ls_func_split_full())
+ {
+ split_fcn_params_full(start);
+
+ if (!is_past_width(start))
+ {
+ return(true);
+ }
+ }
+ split_fcn_params(start);
+ return(true);
+ }
+
+ /*
+ * If this is in a template, split on commas, Issue #1170
+ */
+ else if (start->flags.test(PCF_IN_TEMPLATE))
+ {
+ LOG_FMT(LSPLIT, " ** TEMPLATE SPLIT **\n");
+ split_template(start);
+ return(true);
+ }
+ LOG_FMT(LSPLIT, "%s(%d):\n", __func__, __LINE__);
+ // Try to find the best spot to split the line
+ cw_entry ent;
+
+ memset(&ent, 0, sizeof(ent));
+ Chunk *pc = start;
+ Chunk *prev;
+
+ while ( ((pc = pc->GetPrev()) != nullptr)
+ && pc->IsNotNullChunk()
+ && !chunk_is_newline(pc))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): at %s, orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_line, pc->orig_col);
+
+ if (chunk_is_not_token(pc, CT_SPACE))
+ {
+ try_split_here(ent, pc);
+
+ // break at maximum line length
+ log_rule_B("ls_code_width");
+
+ if ( ent.pc != nullptr
+ && (options::ls_code_width()))
+ {
+ break;
+ }
+ }
+ }
+
+ if (ent.pc == nullptr)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): TRY_SPLIT yielded NO SOLUTION for orig_line %zu at '%s' [%s]\n",
+ __func__, __LINE__, start->orig_line, start->Text(), get_token_name(start->type));
+ }
+ else
+ {
+ LOG_FMT(LSPLIT, "%s(%d): TRY_SPLIT yielded '%s' [%s] on orig_line %zu\n",
+ __func__, __LINE__, ent.pc->Text(), get_token_name(ent.pc->type), ent.pc->orig_line);
+ LOG_FMT(LSPLIT, "%s(%d): ent at '%s', orig_col is %zu\n",
+ __func__, __LINE__, ent.pc->Text(), ent.pc->orig_col);
+ }
+
+ // Break before the token instead of after it according to the pos_xxx rules
+ if (ent.pc == nullptr)
+ {
+ pc = nullptr;
+ }
+ else
+ {
+ log_rule_B("pos_arith");
+ log_rule_B("pos_assign");
+ log_rule_B("pos_compare");
+ log_rule_B("pos_conditional");
+ log_rule_B("pos_shift");
+ log_rule_B("pos_bool");
+
+ if ( ( chunk_is_token(ent.pc, CT_SHIFT)
+ && (options::pos_shift() & TP_LEAD))
+ || ( ( chunk_is_token(ent.pc, CT_ARITH)
+ || chunk_is_token(ent.pc, CT_CARET))
+ && (options::pos_arith() & TP_LEAD))
+ || ( chunk_is_token(ent.pc, CT_ASSIGN)
+ && (options::pos_assign() & TP_LEAD))
+ || ( chunk_is_token(ent.pc, CT_COMPARE)
+ && (options::pos_compare() & TP_LEAD))
+ || ( ( chunk_is_token(ent.pc, CT_COND_COLON)
+ || chunk_is_token(ent.pc, CT_QUESTION))
+ && (options::pos_conditional() & TP_LEAD))
+ || ( chunk_is_token(ent.pc, CT_BOOL)
+ && (options::pos_bool() & TP_LEAD)))
+ {
+ pc = ent.pc;
+ }
+ else
+ {
+ pc = ent.pc->GetNext();
+ }
+ LOG_FMT(LSPLIT, "%s(%d): at '%s', orig_col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->orig_col);
+ }
+
+ if ( pc == nullptr
+ || pc->IsNullChunk())
+ {
+ pc = start;
+
+ // Don't break before a close, comma, or colon
+ if ( chunk_is_token(start, CT_PAREN_CLOSE)
+ || chunk_is_token(start, CT_PAREN_OPEN)
+ || chunk_is_token(start, CT_FPAREN_CLOSE)
+ || chunk_is_token(start, CT_FPAREN_OPEN)
+ || chunk_is_token(start, CT_SPAREN_CLOSE)
+ || chunk_is_token(start, CT_SPAREN_OPEN)
+ || chunk_is_token(start, CT_ANGLE_CLOSE)
+ || chunk_is_token(start, CT_BRACE_CLOSE)
+ || chunk_is_token(start, CT_COMMA)
+ || chunk_is_token(start, CT_SEMICOLON)
+ || chunk_is_token(start, CT_VSEMICOLON)
+ || start->Len() == 0)
+ {
+ LOG_FMT(LSPLIT, " ** NO GO **\n");
+
+ // TODO: Add in logic to handle 'hard' limits by backing up a token
+ return(true);
+ }
+ }
+ // add a newline before pc
+ prev = pc->GetPrev();
+
+ if ( prev != nullptr
+ && prev->IsNotNullChunk()
+ && !chunk_is_newline(pc)
+ && !chunk_is_newline(prev))
+ {
+ //int plen = (pc->Len() < 5) ? pc->Len() : 5;
+ //int slen = (start->Len() < 5) ? start->Len() : 5;
+ //LOG_FMT(LSPLIT, " '%.*s' [%s], started on token '%.*s' [%s]\n",
+ // plen, pc->Text(), get_token_name(pc->type),
+ // slen, start->Text(), get_token_name(start->type));
+ LOG_FMT(LSPLIT, "%s(%d): Text() '%s', type %s, started on token '%s', type %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type),
+ start->Text(), get_token_name(start->type));
+
+ split_before_chunk(pc);
+ }
+ return(true);
+} // split_line
+
+
+/*
+ * The for statement split algorithm works as follows:
+ * 1. Step backwards and forwards to find the semicolons
+ * 2. Try splitting at the semicolons first.
+ * 3. If that doesn't work, then look for a comma at paren level.
+ * 4. If that doesn't work, then look for an assignment at paren level.
+ * 5. If that doesn't work, then give up.
+ */
+static void split_for_stmt(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ // how many semicolons (1 or 2) do we need to find
+ log_rule_B("ls_for_split_full");
+ size_t max_cnt = options::ls_for_split_full() ? 2 : 1;
+ Chunk *open_paren = nullptr;
+ size_t nl_cnt = 0;
+
+ LOG_FMT(LSPLIT, "%s: starting on %s, line %zu\n",
+ __func__, start->Text(), start->orig_line);
+
+ // Find the open paren so we know the level and count newlines
+ Chunk *pc = start;
+
+ while ( ((pc = pc->GetPrev()) != nullptr)
+ && pc->IsNotNullChunk())
+ {
+ if (chunk_is_token(pc, CT_SPAREN_OPEN))
+ {
+ open_paren = pc;
+ break;
+ }
+
+ if (pc->nl_count > 0)
+ {
+ nl_cnt += pc->nl_count;
+ }
+ }
+
+ if (open_paren == nullptr)
+ {
+ LOG_FMT(LSPLIT, "No open paren\n");
+ return;
+ }
+ // see if we started on the semicolon
+ int count = 0;
+ Chunk *st[2];
+
+ pc = start;
+
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ && get_chunk_parent_type(pc) == CT_FOR)
+ {
+ st[count++] = pc;
+ }
+
+ // first scan backwards for the semicolons
+ while ( (count < static_cast<int>(max_cnt))
+ && ((pc = pc->GetPrev()) != nullptr)
+ && pc->IsNotNullChunk()
+ && pc->flags.test(PCF_IN_SPAREN))
+ {
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ && get_chunk_parent_type(pc) == CT_FOR)
+ {
+ st[count++] = pc;
+ }
+ }
+ // And now scan forward
+ pc = start;
+
+ while ( (count < static_cast<int>(max_cnt))
+ && ((pc = pc->GetNext())->IsNotNullChunk())
+ && pc->flags.test(PCF_IN_SPAREN))
+ {
+ if ( chunk_is_token(pc, CT_SEMICOLON)
+ && get_chunk_parent_type(pc) == CT_FOR)
+ {
+ st[count++] = pc;
+ }
+ }
+
+ while (--count >= 0)
+ {
+ // TODO: st[0] may be uninitialized here
+ LOG_FMT(LSPLIT, "%s(%d): split before %s\n", __func__, __LINE__, st[count]->Text());
+ split_before_chunk(st[count]->GetNext());
+ }
+
+ if ( !is_past_width(start)
+ || nl_cnt > 0)
+ {
+ return;
+ }
+ // Still past width, check for commas at parenthese level
+ pc = open_paren;
+
+ while ((pc = pc->GetNext()) != start)
+ {
+ if ( chunk_is_token(pc, CT_COMMA)
+ && (pc->level == (open_paren->level + 1)))
+ {
+ split_before_chunk(pc->GetNext());
+
+ if (!is_past_width(pc))
+ {
+ return;
+ }
+ }
+ }
+ // Still past width, check for a assignments at parenthese level
+ pc = open_paren;
+
+ while ((pc = pc->GetNext()) != start)
+ {
+ if ( chunk_is_token(pc, CT_ASSIGN)
+ && (pc->level == (open_paren->level + 1)))
+ {
+ split_before_chunk(pc->GetNext());
+
+ if (!is_past_width(pc))
+ {
+ return;
+ }
+ }
+ }
+ // Oh, well. We tried.
+} // split_for_stmt
+
+
+static void split_fcn_params_full(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPLIT, "%s(%d): %s\n", __func__, __LINE__, start->Text());
+
+ // Find the opening function parenthesis
+ Chunk *fpo = start;
+
+ LOG_FMT(LSPLIT, " %s(%d): Find the opening function parenthesis\n", __func__, __LINE__);
+
+ while ( (fpo = fpo->GetPrev()) != nullptr
+ && fpo->IsNotNullChunk())
+ {
+ LOG_FMT(LSPLIT, "%s(%d): %s, orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, fpo->Text(), fpo->orig_col, fpo->level);
+
+ if ( chunk_is_token(fpo, CT_FPAREN_OPEN)
+ && (fpo->level == start->level - 1))
+ {
+ break; // opening parenthesis found. Issue #1020
+ }
+ }
+ // Now break after every comma
+ Chunk *pc = fpo->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->level <= fpo->level)
+ {
+ break;
+ }
+
+ if ( (pc->level == (fpo->level + 1))
+ && chunk_is_token(pc, CT_COMMA))
+ {
+ split_before_chunk(pc->GetNext());
+ }
+ pc = pc->GetNextNcNnl();
+ }
+}
+
+
+static void split_fcn_params(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPLIT, "%s(%d): start->Text() is '%s', orig_line is %zu, orig_col is %zu\n",
+ __func__, __LINE__, start->Text(), start->orig_line, start->orig_col);
+ Chunk *fpo = start;
+
+ if (!chunk_is_token(start, CT_FPAREN_OPEN))
+ {
+ // Find the opening function parenthesis
+ LOG_FMT(LSPLIT, "%s(%d): Find the opening function parenthesis\n", __func__, __LINE__);
+
+ while ( ((fpo = fpo->GetPrev()) != nullptr)
+ && fpo->IsNotNullChunk()
+ && chunk_is_not_token(fpo, CT_FPAREN_OPEN))
+ {
+ // do nothing
+ LOG_FMT(LSPLIT, "%s(%d): '%s', orig_col is %zu, level is %zu\n",
+ __func__, __LINE__, fpo->Text(), fpo->orig_col, fpo->level);
+ }
+ }
+ Chunk *pc = fpo->GetNextNcNnl();
+ size_t min_col = pc->column;
+
+ log_rule_B("code_width");
+ LOG_FMT(LSPLIT, " mincol is %zu, max_width is %zu\n",
+ min_col, options::code_width() - min_col);
+
+ int cur_width = 0;
+ int last_col = -1;
+
+ LOG_FMT(LSPLIT, "%s(%d):look forward until CT_COMMA or CT_FPAREN_CLOSE\n", __func__, __LINE__);
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LSPLIT, "%s(%d): pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->type));
+
+ if (chunk_is_newline(pc))
+ {
+ cur_width = 0;
+ last_col = -1;
+ }
+ else
+ {
+ if (last_col < 0)
+ {
+ last_col = pc->column;
+ LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n",
+ __func__, __LINE__, last_col);
+ }
+ cur_width += (pc->column - last_col) + pc->Len();
+ last_col = pc->column + pc->Len();
+
+ LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n",
+ __func__, __LINE__, last_col);
+
+ if ( chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_FPAREN_CLOSE))
+ {
+ if (cur_width == 0)
+ {
+ fprintf(stderr, "%s(%d): cur_width is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->orig_line, pc->orig_col);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ cur_width--;
+ LOG_FMT(LSPLIT, "%s(%d): cur_width is %d\n",
+ __func__, __LINE__, cur_width);
+
+ log_rule_B("code_width");
+
+ if ( ((last_col - 1) > static_cast<int>(options::code_width()))
+ || chunk_is_token(pc, CT_FPAREN_CLOSE))
+ {
+ break;
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+ // back up until the prev is a comma
+ Chunk *prev = pc;
+
+ LOG_FMT(LSPLIT, "%s(%d): back up until the prev is a comma, begin is '%s', level is %zu\n",
+ __func__, __LINE__, prev->Text(), prev->level);
+
+ while ((prev = prev->GetPrev())->IsNotNullChunk())
+ {
+ LOG_FMT(LSPLIT, "%s(%d): prev->Text() is '%s', prev->orig_line is %zu, prev->orig_col is %zu\n",
+ __func__, __LINE__, prev->Text(), prev->orig_line, prev->orig_col);
+ LOG_FMT(LSPLIT, "%s(%d): prev->level is %zu, prev '%s', prev->type is %s\n",
+ __func__, __LINE__, prev->level, prev->Text(), get_token_name(prev->type));
+
+ if ( chunk_is_newline(prev)
+ || chunk_is_token(prev, CT_COMMA))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): found at %zu\n",
+ __func__, __LINE__, prev->orig_col);
+ break;
+ }
+ LOG_FMT(LSPLIT, "%s(%d): last_col is %d, prev->Len() is %zu\n",
+ __func__, __LINE__, last_col, prev->Len());
+ last_col -= prev->Len();
+ LOG_FMT(LSPLIT, "%s(%d): last_col is %d\n",
+ __func__, __LINE__, last_col);
+
+ if (chunk_is_token(prev, CT_FPAREN_OPEN))
+ {
+ pc = prev->GetNext();
+
+ log_rule_B("indent_paren_nl");
+
+ if (!options::indent_paren_nl())
+ {
+ log_rule_B("indent_columns");
+ min_col = pc->brace_level * options::indent_columns() + 1;
+ LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n",
+ __func__, __LINE__, min_col);
+
+ log_rule_B("indent_continue");
+
+ if (options::indent_continue() == 0)
+ {
+ log_rule_B("indent_columns");
+ min_col += options::indent_columns();
+ }
+ else
+ {
+ min_col += abs(options::indent_continue());
+ }
+ LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n",
+ __func__, __LINE__, min_col);
+ }
+
+ // Don't split "()"
+ if (pc->type != E_Token(prev->type + 1))
+ {
+ break;
+ }
+ }
+ }
+
+ if ( prev->IsNotNullChunk()
+ && !chunk_is_newline(prev))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): -- ended on %s --\n",
+ __func__, __LINE__, get_token_name(prev->type));
+ LOG_FMT(LSPLIT, "%s(%d): min_col is %zu\n",
+ __func__, __LINE__, min_col);
+ pc = prev->GetNext();
+ newline_add_before(pc);
+ reindent_line(pc, min_col);
+ cpd.changes++;
+ }
+} // split_fcn_params
+
+
+static void split_template(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPLIT, " %s(%d): start %s\n", __func__, __LINE__, start->Text());
+ LOG_FMT(LSPLIT, " %s(%d): back up until the prev is a comma\n", __func__, __LINE__);
+
+ // back up until the prev is a comma
+ Chunk *prev = start;
+
+ while ((prev = prev->GetPrev())->IsNotNullChunk())
+ {
+ LOG_FMT(LSPLIT, " %s(%d): prev '%s'\n", __func__, __LINE__, prev->Text());
+
+ if ( chunk_is_newline(prev)
+ || chunk_is_token(prev, CT_COMMA))
+ {
+ break;
+ }
+ }
+
+ if ( prev != nullptr
+ && !chunk_is_newline(prev))
+ {
+ LOG_FMT(LSPLIT, " %s(%d):", __func__, __LINE__);
+ LOG_FMT(LSPLIT, " -- ended on %s --\n", get_token_name(prev->type));
+ Chunk *pc = prev->GetNext();
+ newline_add_before(pc);
+ size_t min_col = 1;
+
+ log_rule_B("indent_continue");
+
+ if (options::indent_continue() == 0)
+ {
+ log_rule_B("indent_columns");
+ min_col += options::indent_columns();
+ }
+ else
+ {
+ min_col += abs(options::indent_continue());
+ }
+ reindent_line(pc, min_col);
+ cpd.changes++;
+ }
+} // split_templatefcn_params
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.h
new file mode 100644
index 00000000..3c5ad0b0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/width.h
@@ -0,0 +1,21 @@
+/**
+ * @file width.h
+ * prototypes for width.c
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef WIDTH_H_INCLUDED
+#define WIDTH_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * Step forward until a token goes beyond the limit and then call split_line()
+ * to split the line at or before that point.
+ */
+void do_code_width(void);
+
+
+#endif /* WIDTH_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/windows_compat.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/windows_compat.h
new file mode 100644
index 00000000..8210adab
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/windows_compat.h
@@ -0,0 +1,97 @@
+/**
+ * @file windows_compat.h
+ * Hacks to work with different versions of windows.
+ * This is only included if WIN32 is set.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef WINDOWS_COMPAT_H_INCLUDED
+#define WINDOWS_COMPAT_H_INCLUDED
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include "windows.h"
+
+#define HAVE_SYS_STAT_H
+
+#define NO_MACRO_VARARG
+
+typedef char CHAR;
+
+typedef signed char INT8;
+typedef short INT16;
+typedef int INT32;
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+
+#ifndef PRIx64
+#define PRIx64 "llx"
+#endif
+
+#ifndef PRIu64
+#define PRIu64 "llu"
+#endif
+
+// Make sure to keep GNU style attributes if they are supported; other
+// included headers may have chosen to rely on them. This is essential
+// if building with libc++ headers, where attributes are relied upon
+// if they are supported (see _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION).
+#ifndef __GNUC__
+// eliminate GNU's attribute
+#define __attribute__(x)
+#endif
+
+/*
+ * MSVC compilers before VC7 don't have __func__ at all; later ones call it
+ * __FUNCTION__.
+ */
+#ifdef _MSC_VER
+#if _MSC_VER < 1300
+#define __func__ "???"
+#else
+#define __func__ __FUNCTION__
+#endif
+#else // _MSC_VER
+#ifndef __GNUC__
+#define __func__ "???"
+#endif // __GNUC__
+#endif // _MSC_VER
+
+#include "stdio.h"
+#include "string.h"
+
+#undef snprintf
+#define snprintf _snprintf
+
+#undef vsnprintf
+#define vsnprintf _vsnprintf
+
+#undef strcasecmp
+#define strcasecmp _strcmpi
+
+#undef strncasecmp
+#define strncasecmp _strnicmp
+
+#undef strdup
+#define strdup _strdup
+
+#undef fileno
+#define fileno _fileno
+
+// includes for _setmode()
+#include <direct.h>
+#include <fcntl.h>
+#include <io.h>
+
+// on windows the file permissions have no meaning thus neglect them
+#define mkdir(x, y) _mkdir(x)
+
+#define PATH_SEP '\\'
+
+#endif /* WINDOWS_COMPAT_H_INCLUDED */