summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src
diff options
context:
space:
mode:
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src')
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/.kateconfig1
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ChunkStack.cpp120
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ChunkStack.h124
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/EnumStructUnionParser.cpp2948
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/EnumStructUnionParser.h497
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ListManager.h216
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/add_space_table.h375
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align.cpp232
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_add.cpp58
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_add.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_asm_colon.cpp62
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_asm_colon.h25
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_assign.cpp289
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_assign.h25
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_braced_init_list.cpp165
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_braced_init_list.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_eigen_comma_init.cpp113
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_eigen_comma_init.h14
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_params.cpp186
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_params.h19
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_proto.cpp230
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_proto.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_init_brace.cpp205
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_init_brace.h49
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_left_shift.cpp134
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_left_shift.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_log_al.cpp31
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_log_al.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_nl_cont.cpp85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_nl_cont.h33
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_decl_colon.cpp90
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_decl_colon.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_colons.cpp182
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_colons.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_spec.cpp37
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_spec.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_preprocessor.cpp109
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_preprocessor.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.cpp286
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.h23
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_stack.cpp659
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_stack.h154
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_struct_initializers.cpp34
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_struct_initializers.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tab_column.cpp39
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tab_column.h23
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tools.cpp192
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tools.h48
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_trailing_comments.cpp235
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_trailing_comments.h46
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_typedefs.cpp65
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_typedefs.h25
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_var_def_brace.cpp362
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_var_def_brace.h22
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/args.cpp228
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/args.h122
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/backup.cpp164
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/backup.h66
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/base_types.h53
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/brace_cleanup.cpp1440
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/brace_cleanup.h23
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/braces.cpp1696
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/braces.h33
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/calculate_closing_brace_position.cpp197
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/calculate_closing_brace_position.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/change_int_types.cpp186
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/change_int_types.h19
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/char_table.h84
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/check_template.cpp536
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/check_template.h55
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.cpp915
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.h1797
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.cpp4044
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.h75
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_fix_mark.cpp2651
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_fix_mark.h196
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_labels.cpp452
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_labels.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.cpp222
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.h137
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_tools.cpp569
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_tools.h85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/compat.h26
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/compat_posix.cpp39
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/compat_win32.cpp82
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/config.h.in97
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/cs_top_is_question.cpp20
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/cs_top_is_question.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/detect.cpp445
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/detect.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_cleanup.cpp95
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_cleanup.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_flags.h120
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/error_types.h53
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_braced_init_list.cpp112
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_braced_init_list.h27
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_decltype.cpp46
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_decltype.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_parens.cpp72
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_parens.h28
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.cpp4792
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.h59
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/keywords.cpp691
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/keywords.h85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.cpp520
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.h49
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_names.cpp227
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_names.h109
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_tools.cpp17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_tools.h18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_levels.h139
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_rules.cpp133
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_rules.h56
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logger.cpp336
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logger.h184
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logmask.cpp142
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logmask.h103
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_functor.cpp114
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_functor.h13
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.cpp192
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.h13
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/md5.cpp308
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/md5.h85
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/newlines.cpp6856
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/newlines.h206
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option.cpp1325
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option.h365
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option_enum.cpp.in24
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option_enum.h.in17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options.cpp.in26
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options.h4436
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options_for_QT.cpp126
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options_for_QT.h29
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.cpp3580
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.h46
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parameter_pack_cleanup.cpp65
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parameter_pack_cleanup.h15
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parens.cpp362
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parens.h24
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parent_for_pp.cpp54
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parent_for_pp.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.cpp256
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.h797
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.cpp353
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.h43
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pcf_flags.cpp105
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pcf_flags.h100
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.cpp98
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.h16
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/prototypes.h64
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/punctuators.cpp86
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/punctuators.h52
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/quick_align_again.cpp53
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/quick_align_again.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_duplicate_include.cpp94
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_duplicate_include.h20
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_extra_returns.cpp87
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_extra_returns.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.cpp345
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.h19
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.cpp151
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.h26
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/sorting.cpp709
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/sorting.h24
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/space.cpp4004
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/space.h45
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/symbols_table.h148
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/token_enum.h405
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize.cpp2946
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize.h55
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize_cleanup.cpp1223
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize_cleanup.h31
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.cpp75
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.h49
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_text.cpp766
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_text.h197
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_tools.cpp722
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_tools.h66
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.cpp2537
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.h69
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_emscripten.cpp1213
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_limits.h19
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_types.cpp108
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_types.h280
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_version.h.in18
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unicode.cpp580
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unicode.h34
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/universalindentgui.cpp377
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/universalindentgui.h17
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/width.cpp756
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/width.h21
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/windows_compat.h102
193 files changed, 72838 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/.kateconfig b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/.kateconfig
new file mode 100644
index 00000000..4d9024f0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/.kateconfig
@@ -0,0 +1 @@
+kate: indent-width 3;
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ChunkStack.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ChunkStack.cpp
new file mode 100644
index 00000000..fbf8a737
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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(Chunk::NullChunkPtr);
+}
+
+
+Chunk *ChunkStack::Pop_Front()
+{
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ if (!m_cse.empty())
+ {
+ pc = m_cse[0].m_pc;
+ m_cse.pop_front();
+ }
+ return(pc);
+}
+
+
+Chunk *ChunkStack::Pop_Back()
+{
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ 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 = Chunk::NullChunkPtr;
+ }
+}
+
+
+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->IsNotNullChunk())
+ {
+ 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.78.0/src/ChunkStack.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ChunkStack.h
new file mode 100644
index 00000000..6ab1c867
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ChunkStack.h
@@ -0,0 +1,124 @@
+/**
+ * @file ChunkStack.h
+ * Manages a simple stack of chunks
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef CHUNKSTACK_H_INCLUDED
+#define CHUNKSTACK_H_INCLUDED
+
+#include "chunk.h"
+#include "uncrustify_types.h"
+
+class ChunkStack
+{
+public:
+ struct Entry
+ {
+ Entry()
+ : m_seqnum(0)
+ , m_pc(Chunk::NullChunkPtr)
+ {
+ }
+
+
+ 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.78.0/src/EnumStructUnionParser.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/EnumStructUnionParser.cpp
new file mode 100644
index 00000000..93c76995
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/EnumStructUnionParser.cpp
@@ -0,0 +1,2948 @@
+/**
+ * @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);
+
+
+/**
+ * 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->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ auto prev_token_type = prev->GetType();
+ auto next_token_type = next->GetType();
+
+ 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(prev->GetClosingParen(E_Scope::PREPROC)->IsNotNullChunk());
+
+ 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->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ auto prev_token_type = prev->GetType();
+ auto next_token_type = next->GetType();
+
+ 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( next->IsPointerOrReference()
+ || 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(prev->GetClosingParen(E_Scope::PREPROC)->IsNotNullChunk());
+
+ 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( next->IsPointerOrReference()
+ || 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(prev->GetClosingParen(E_Scope::PREPROC)->IsNotNullChunk());
+
+ 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)
+ && ( next->IsPointerOrReference()
+ || 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( next->IsPointerOrReference()
+ || 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 = prev->GetClosingParen(E_Scope::PREPROC);
+
+ if (next->IsNotNullChunk())
+ {
+ next_token_type = next->GetType();
+ }
+ 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( next->IsPointerOrReference()
+ || 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( next->IsPointerOrReference()
+ || 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(prev->GetClosingParen(E_Scope::PREPROC)->IsNotNullChunk());
+
+ 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( next->IsPointerOrReference()
+ || 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( next->IsPointerOrReference()
+ || 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->IsNotNullChunk())
+ {
+ if ( test_equal
+ && pc == after)
+ {
+ return(true);
+ }
+ else if (after->IsNotNullChunk())
+ {
+ auto pc_column = pc->GetOrigCol();
+ auto pc_line = pc->GetOrigLine();
+ auto after_column = after->GetOrigCol();
+ auto after_line = after->GetOrigLine();
+
+ 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->IsNotNullChunk())
+ {
+ if ( test_equal
+ && pc == before)
+ {
+ return(true);
+ }
+ else if (before->IsNotNullChunk())
+ {
+ auto pc_column = pc->GetOrigCol();
+ auto pc_line = pc->GetOrigLine();
+ auto before_column = before->GetOrigCol();
+ auto before_line = before->GetOrigLine();
+
+ 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))
+ && pc->Is(CT_WORD)
+ && !pc->TestFlags(PCF_IN_PREPROC))
+ {
+ while (next->IsNotNullChunk())
+ {
+ if ( next->TestFlags(PCF_IN_PREPROC)
+ && std::strcmp(pc->GetStr().c_str(), next->GetStr().c_str()) == 0)
+ {
+ return(true);
+ }
+ next = next->GetNextType(CT_MACRO);
+ }
+ }
+ return(false);
+} // chunk_is_macro_reference
+
+
+bool Chunk::IsPointerReferenceOrQualifier() const
+{
+ LOG_FUNC_ENTRY();
+
+ return( IsPointerOrReference()
+ || ( Is(CT_QUALIFIER)
+ && !IsCppInheritanceAccessSpecifier()));
+}
+
+
+/**
+ * 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->IsNotNullChunk()
+ && start->IsNotNullChunk())
+ {
+ auto *double_colon = start->GetNextType(CT_DC_MEMBER);
+
+ if ( double_colon->IsNotNullChunk()
+ && chunk_is_between(double_colon, start, end))
+ {
+ return(std::make_pair(start, end));
+ }
+ }
+ return(std::make_pair(Chunk::NullChunkPtr, Chunk::NullChunkPtr));
+} // 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->IsNotNullChunk() ? 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->IsNotNullChunk()
+ || identifier->GetPrevNcNnlNi()->Is(CT_WORD)))
+ {
+ return(std::make_tuple(start, identifier, end));
+ }
+ return(std::make_tuple(Chunk::NullChunkPtr, Chunk::NullChunkPtr, Chunk::NullChunkPtr));
+} // 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 = Chunk::NullChunkPtr;
+
+ while (pc->IsNotNullChunk())
+ {
+ /**
+ * skip any right-hand side assignments
+ */
+ Chunk *rhs_exp_end = Chunk::NullChunkPtr;
+
+ if (pc->Is(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->IsNotNullChunk()
+ && pc->GetLevel() > level)
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ /**
+ * skip to any following match for angle brackets, braces, parens,
+ * or square brackets
+ */
+ if ( pc->Is(CT_ANGLE_OPEN)
+ || pc->Is(CT_BRACE_OPEN)
+ || pc->IsParenOpen()
+ || pc->Is(CT_SQUARE_OPEN))
+ {
+ pc = pc->GetClosingParen(E_Scope::PREPROC);
+ }
+ /**
+ * call a separate function to validate adjacent tokens as potentially
+ * matching a variable declaration/definition
+ */
+
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( next->IsNot(CT_COMMA)
+ && next->IsNot(CT_FPAREN_CLOSE)
+ && !next->IsSemicolon()
+ && !adj_tokens_match_var_def_pattern(pc, next))
+ {
+ /**
+ * error, pattern is not consistent with a variable declaration/definition
+ */
+ break;
+ }
+
+ if ( pc->Is(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 ( next->Is(CT_COMMA)
+ || next->Is(CT_FPAREN_CLOSE)
+ || next->IsSemicolon())
+ {
+ return(std::make_pair(identifier, pc));
+ }
+ pc = next;
+ }
+ return(std::make_pair(Chunk::NullChunkPtr, Chunk::NullChunkPtr));
+} // 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;
+
+ 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 (next->Is(CT_ASSIGN))
+ {
+ pc = prev;
+ }
+ }
+ /**
+ * skip current and preceding chunks if at a higher brace level
+ */
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() > level)
+ {
+ pc = pc->GetPrevNcNnlNi();
+ }
+
+ /**
+ * skip to any preceding match for angle brackets, braces, parens,
+ * or square brackets
+ */
+ if ( pc->Is(CT_ANGLE_CLOSE)
+ || pc->Is(CT_BRACE_CLOSE)
+ || pc->IsParenClose()
+ || pc->Is(CT_SQUARE_CLOSE))
+ {
+ pc = pc->GetOpeningParen(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 ( prev->IsNot(CT_WORD)
+ || ( !pc->IsPointerOrReference()
+ && pc->IsNot(CT_WORD)))
+ {
+ /**
+ * error, pattern is not consistent with a variable declaration/definition
+ */
+
+ break;
+ }
+ }
+
+ if ( identifier->IsNullChunk()
+ && pc->Is(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 ( prev->Is(CT_ANGLE_CLOSE)
+ || prev->Is(CT_BRACE_CLOSE)
+ || prev->Is(CT_COMMA)
+ || prev->Is(CT_TYPE)
+ || prev->Is(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->TestFlags(PCF_IN_TEMPLATE)
+ || pc->Is(CT_DC_MEMBER)
+ || pc->Is(CT_TYPE)
+ || pc->Is(CT_WORD))
+ {
+ while (pc->IsNotNullChunk())
+ {
+ /**
+ * skip to any following match for angle brackets
+ */
+ if (pc->Is(CT_ANGLE_OPEN))
+ {
+ pc = pc->GetClosingParen(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->TestFlags(PCF_IN_TEMPLATE)
+ || pc->Is(CT_DC_MEMBER)
+ || pc->Is(CT_TYPE)
+ || pc->Is(CT_WORD))
+ {
+ while (pc->IsNotNullChunk())
+ {
+ /**
+ * skip to any preceding match for angle brackets
+ */
+ if (pc->Is(CT_ANGLE_CLOSE))
+ {
+ pc = pc->GetOpeningParen(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(Chunk::NullChunkPtr)
+ , m_parse_error(false)
+ , m_start(Chunk::NullChunkPtr)
+ , m_type(Chunk::NullChunkPtr)
+{
+} // 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();
+ PcfFlags flags = PCF_VAR_1ST_DEF;
+ auto *inheritance_start = get_inheritance_start();
+ Chunk *pc = body_end->IsNotNullChunk() ? 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->IsNotNullChunk())
+ {
+ pc = body_end;
+ }
+ else if (template_end->IsNotNullChunk())
+ {
+ pc = template_end;
+ }
+ }
+
+ 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()
+ || pc->IsClassEnumStructOrUnion()
+ || 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->IsNotNullChunk())
+ {
+ /**
+ * 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->GetLevel());
+ auto *start = std::get<0>(match);
+ auto *identifier = std::get<1>(match);
+ auto *end = std::get<2>(match);
+
+ if ( start->IsNotNullChunk()
+ && identifier->IsNotNullChunk())
+ {
+ if (end->IsNotNullChunk())
+ {
+ mark_variable(identifier, flags);
+
+ if (flags & PCF_VAR_1ST)
+ {
+ flags &= ~PCF_VAR_1ST; // clear the first flag for the next items
+ }
+ }
+ }
+
+ if (end->IsNotNullChunk())
+ {
+ pc = end;
+ }
+ pc = pc->GetNextNcNnl();
+
+ /**
+ * skip any right-hand side assignments
+ */
+ if (pc->Is(CT_ASSIGN))
+ {
+ pc = skip_to_expression_end(pc);
+ }
+
+ /**
+ * if we're sitting at a comma or semicolon, skip it
+ */
+ if ( pc->IsSemicolon()
+ || ( pc->Is(CT_COMMA)
+ && !pc->GetFlags().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 ( m_start->IsClassOrStruct()
+ && ( m_start->IsNot(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
+ */
+ m_type->SetFlagBits(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->IsNotNullChunk()
+ && body_start->IsNotNullChunk());
+} // 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(Chunk::NullChunkPtr);
+} // 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(Chunk::NullChunkPtr);
+} // 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(Chunk::NullChunkPtr);
+} // 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(Chunk::NullChunkPtr);
+} // EnumStructUnionParser::get_first_top_level_comma
+
+
+Chunk *EnumStructUnionParser::get_inheritance_end() const
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *brace_open = Chunk::NullChunkPtr;
+ auto *inheritance_start = get_inheritance_start();
+
+ if (inheritance_start->IsNotNullChunk())
+ {
+ brace_open = get_body_start();
+
+ if (brace_open->IsNullChunk())
+ {
+ brace_open = inheritance_start->GetNextType(CT_BRACE_OPEN, m_start->GetLevel(), 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(Chunk::NullChunkPtr);
+} // 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(Chunk::NullChunkPtr);
+} // 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(Chunk::NullChunkPtr);
+} // 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 = Chunk::NullChunkPtr;
+ auto *where_start = get_where_start();
+
+ if (where_start->IsNotNullChunk())
+ {
+ brace_open = get_body_start();
+
+ if (brace_open->IsNullChunk())
+ {
+ brace_open = where_start->GetNextType(CT_BRACE_OPEN, m_start->GetLevel(), 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(Chunk::NullChunkPtr);
+} // 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 = Chunk::NullChunkPtr;
+ pc = try_find_end_chunk(pc);
+
+ if (parse_error_detected())
+ {
+ return;
+ }
+ m_end = refine_end_chunk(pc);
+} // EnumStructUnionParser::initialize
+
+
+bool EnumStructUnionParser::is_potential_end_chunk(Chunk *pc) const
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+
+ /**
+ * test for a semicolon or closing brace at the level of the starting chunk
+ */
+ if ( pc->IsNullChunk()
+ || parse_error_detected()
+ || ( ( pc->IsSemicolon()
+ || pc->Is(CT_BRACE_CLOSE))
+ && pc->GetLevel() == m_start->GetLevel()))
+ {
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ 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->GetFlags() & PCF_IN_FCN_DEF;
+ auto const pc_in_preproc = pc->GetFlags() & PCF_IN_PREPROC;
+ auto const start_in_funcdef = m_start->GetFlags() & PCF_IN_FCN_DEF;
+ auto const start_in_preproc = m_start->GetFlags() & PCF_IN_PREPROC;
+
+ /**
+ * the following may identify cases where we've reached the
+ * end of a cast terminated by a closing paren
+ */
+ if ( ( pc->IsParenClose() // Issue #3538
+ && pc->GetLevel() < m_start->GetLevel())
+ || (start_in_funcdef ^ pc_in_funcdef).test_any()
+ || (start_in_preproc ^ pc_in_preproc).test_any())
+ {
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ 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)
+ {
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ 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->GetFlags() & PCF_IN_FCN_CALL;
+ auto const start_in_funccall = m_start->GetFlags() & PCF_IN_FCN_CALL;
+
+ if ( ( pc_in_funccall.test_any()
+ && start_in_funccall.test_any()
+ && pc->Is(CT_COMMA)
+ && pc->GetLevel() == m_start->GetLevel())
+ || ( pc_in_funcdef.test_any()
+ && ( ( pc->Is(CT_FPAREN_CLOSE)
+ && pc->GetLevel() < m_start->GetLevel())
+ || ( ( pc->Is(CT_ASSIGN)
+ || pc->Is(CT_COMMA))
+ && pc->GetLevel() == m_start->GetLevel()))))
+ {
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ return(true);
+ }
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ 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->TestFlags(PCF_IN_CLASS_BASE))
+ {
+ return(true);
+ }
+ auto *inheritance_end = get_inheritance_end();
+ auto *inheritance_start = get_inheritance_start();
+
+ if ( inheritance_end->IsNotNullChunk()
+ && inheritance_start->IsNotNullChunk())
+ {
+ 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->TestFlags(PCF_IN_WHERE_SPEC))
+ {
+ return(true);
+ }
+ auto *where_end = get_where_end();
+ auto *where_start = get_where_start();
+
+ if ( where_end->IsNotNullChunk()
+ && where_start->IsNotNullChunk())
+ {
+ 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();
+
+ PcfFlags flags = PCF_VAR_1ST_DEF;
+
+ while (pc->IsNotNullChunk())
+ {
+ pc->SetFlagBits(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->ResetFlagBits(PCF_VAR_TYPE);
+
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->Is(CT_DC_MEMBER))
+ {
+ /**
+ * just in case it's a templated type
+ */
+ pc = skip_template_prev(pc);
+
+ if (pc->Is(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!
+ */
+ pc->SetType(CT_TYPE);
+ }
+ }
+ else if ( ( next->Is(CT_BRACE_OPEN)
+ || ( next->Is(CT_COMMA)
+ && !is_within_where_clause(next)))
+ && next->GetLevel() == m_start->GetLevel())
+ {
+ /**
+ * just in case it's a templated type
+ */
+ pc = skip_template_prev(pc);
+
+ if (pc->Is(CT_WORD))
+ {
+ pc->SetFlagBits(flags);
+
+ if (flags & PCF_VAR_1ST)
+ {
+ flags &= ~PCF_VAR_1ST; // clear the first flag for the next items
+ }
+ }
+
+ if (next->Is(CT_BRACE_OPEN))
+ {
+ break;
+ }
+ }
+ pc = next;
+ }
+ pc->SetFlagBits(PCF_IN_CLASS_BASE);
+} // EnumStructUnionParser::mark_base_classes
+
+
+void EnumStructUnionParser::mark_braces(Chunk *brace_open)
+{
+ LOG_FUNC_ENTRY();
+
+ PcfFlags flags = PCF_NONE;
+
+ if (m_start->Is(CT_CLASS))
+ {
+ flags = PCF_IN_CLASS;
+ }
+ else if (m_start->IsEnum())
+ {
+ flags = PCF_IN_ENUM;
+ }
+ else if (m_start->Is(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 (m_start->IsClassStructOrUnion())
+ {
+ mark_struct_union_body(brace_open);
+
+ auto *inheritance_start = get_inheritance_start();
+
+ if (inheritance_start->IsNotNullChunk())
+ {
+ /**
+ * 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);
+ }
+ }
+ brace_open->SetParentType(m_start->GetType());
+
+ auto *brace_close = brace_open->GetClosingParen(E_Scope::PREPROC);
+
+ if (brace_close->IsNotNullChunk())
+ {
+ brace_close->SetParentType(m_start->GetType());
+ }
+} // 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->GetOrigLine(),
+ colon->GetOrigCol());
+
+ colon->SetType(CT_CLASS_COLON);
+ colon->SetParentType(m_start->GetType());
+} // EnumStructUnionParser::mark_class_colon
+
+
+void EnumStructUnionParser::mark_conditional_colon(Chunk *colon)
+{
+ colon->SetType(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()
+ && m_start->IsClassOrStruct())
+ {
+ 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->GetOrigLine(),
+ m_start->GetOrigCol(),
+ m_start->Text(),
+ get_token_name(m_start->GetParentType()));
+
+ log_pcf_flags(LFTOR, m_start->GetFlags());
+
+ /**
+ * 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->GetFlags());
+
+ Chunk *next = Chunk::NullChunkPtr;
+ std::size_t level = m_type->GetBraceLevel() + 1;
+
+ for (auto *prev = body_start; next != body_end; prev = next)
+ {
+ prev->SetFlagBits(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->GetLevel() == level
+ && next->IsParenOpen())
+ {
+ prev->SetType(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->GetOrigLine(),
+ prev->GetOrigCol(),
+ get_token_name(prev->GetType()));
+
+ mark_cpp_constructor(prev);
+ }
+ }
+
+ next->SetFlagBits(PCF_IN_CLASS);
+ }
+} // EnumStructUnionParser::mark_constructor
+
+
+void EnumStructUnionParser::mark_enum_integral_type(Chunk *colon)
+{
+ LOG_FUNC_ENTRY();
+
+ // Issue #4040
+ LOG_FMT(LFTOR,
+ "%s(%d): orig line is %zu, orig col is %zu\n",
+ __unqualified_func__, __LINE__,
+ colon->GetOrigLine(), colon->GetOrigCol());
+ colon->SetType(CT_ENUM_COLON);
+ colon->SetParentType(m_start->GetType());
+
+ 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
+ && pc->IsNot(CT_BRACE_OPEN)
+ && !pc->IsSemicolon())
+ {
+ /**
+ * 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 (pc->IsNot(CT_DC_MEMBER)) // Issue #3198
+ {
+ pc->ResetFlagBits(PCF_VAR_TYPE);
+ pc->SetType(CT_TYPE);
+ pc->SetParentType(colon->GetType());
+ }
+ 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 (next->GetParentType() == CT_TEMPLATE)
+ {
+ while (true)
+ {
+ prev = next->GetPrevNcNnlNi();
+
+ if ( prev->IsNullChunk()
+ || ( !prev->TestFlags(PCF_IN_TEMPLATE)
+ && prev->IsNot(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->TestFlags(PCF_LVALUE))
+ {
+ next->ResetFlagBits(PCF_LVALUE);
+ }
+ else if ( ( next->Is(CT_ASSIGN)
+ || next->Is(CT_BRACE_OPEN))
+ && prev->Is(CT_WORD)
+ && prev->GetFlags().test_any(PCF_VAR_DEF | PCF_VAR_1ST | PCF_VAR_INLINE))
+ {
+ prev->SetFlagBits(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 (pc->Is(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 (next->Is(CT_ANGLE_OPEN))
+ {
+ /**
+ * the template may have already been previously marked elsewhere...
+ */
+ auto *angle_open = next;
+ auto *angle_close = angle_open->GetClosingParen(E_Scope::PREPROC);
+
+ if (angle_close->IsNullChunk())
+ {
+ // 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->GetOrigLine(),
+ angle_open->GetOrigCol());
+
+ break;
+ }
+ pc->SetType(CT_TYPE);
+ mark_template(next);
+ pc = angle_close;
+ }
+ else if ( is_within_inheritance_list(pc)
+ && ( next->Is(CT_COMMA)
+ || next->Is(CT_BRACE_OPEN)))
+ {
+ pc->SetType(CT_TYPE);
+ }
+ }
+ }
+} // EnumStructUnionParser::mark_nested_name_specifiers
+
+
+void EnumStructUnionParser::mark_pointer_types(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->Is(CT_WORD))
+ {
+ do
+ {
+ // TODO: should there be a CT_BYREF_TYPE?
+ pc = pc->GetPrevNcNnlNi();
+
+ if (pc->IsPointerOperator())
+ {
+ pc->SetParentType(m_start->GetType());
+ pc->SetType(CT_PTR_TYPE);
+ }
+ } while (pc->IsPointerReferenceOrQualifier());
+ }
+} // EnumStructUnionParser::mark_pointer_types
+
+
+void EnumStructUnionParser::mark_template(Chunk *start) const
+{
+ LOG_FUNC_ENTRY();
+
+ if (start->IsNotNullChunk())
+ {
+ LOG_FMT(LTEMPL,
+ "%s(%d): Template detected: '%s' at orig line %zu, orig col %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ start->Text(),
+ start->GetOrigLine(),
+ start->GetOrigCol());
+ }
+ start->SetParentType(CT_TEMPLATE);
+
+ auto *end = start->GetClosingParen(E_Scope::PREPROC);
+
+ if (end->IsNotNullChunk())
+ {
+ end->SetParentType(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->IsNotNullChunk()
+ && start->IsNotNullChunk())
+ {
+ LOG_FMT(LTEMPL,
+ "%s(%d): Start of template detected: '%s' at orig line %zu, orig col %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ start->Text(),
+ start->GetOrigLine(),
+ start->GetOrigCol());
+
+ PcfFlags 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;
+ }
+ next->SetFlagBits(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->GetOrigLine(),
+ end->GetOrigCol());
+ }
+} // EnumStructUnionParser::mark_template_args
+
+
+void EnumStructUnionParser::mark_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->IsNotNullChunk())
+ {
+ m_type = pc;
+
+ do
+ {
+ make_type(pc);
+ pc->SetParentType(m_start->GetType());
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ } while (pc->IsPointerOrReference());
+ }
+} // EnumStructUnionParser::mark_type
+
+
+void EnumStructUnionParser::mark_variable(Chunk *variable, PcfFlags flags)
+{
+ LOG_FUNC_ENTRY();
+
+ if (variable->IsNotNullChunk())
+ {
+ 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->GetOrigLine(),
+ variable->GetOrigCol(),
+ flags & PCF_VAR_1ST_DEF ? "PCF_VAR_1ST_DEF" : "PCF_VAR_1ST");
+
+ variable->SetFlagBits(flags);
+ variable->SetType(CT_WORD);
+ mark_pointer_types(variable);
+ }
+} // EnumStructUnionParser::mark_variable
+
+
+void EnumStructUnionParser::mark_where_clause(Chunk *where)
+{
+ LOG_FUNC_ENTRY();
+
+ if (where->IsNotNullChunk())
+ {
+ LOG_FMT(LFTOR,
+ "%s(%d): Where clause detected: orig line is %zu, orig col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ where->GetOrigLine(),
+ where->GetOrigCol());
+ }
+ set_where_start(where);
+
+ auto *where_end = get_where_end();
+ auto *where_start = get_where_start();
+
+ set_where_end(where_end);
+
+ PcfFlags flags;
+
+ for (auto *pc = where_start; pc != where_end; pc = pc->GetNextNcNnl())
+ {
+ flags = mark_where_chunk(pc, m_start->GetType(), flags);
+ }
+} // EnumStructUnionParser::mark_where_clause
+
+
+void EnumStructUnionParser::mark_where_colon(Chunk *colon)
+{
+ LOG_FUNC_ENTRY();
+
+ if (colon->IsNotNullChunk())
+ {
+ LOG_FMT(LFTOR,
+ "%s(%d): Where colon detected: orig line is %zu, orig col is %zu\n",
+ __unqualified_func__,
+ __LINE__,
+ colon->GetOrigLine(),
+ colon->GetOrigCol());
+ }
+ colon->SetType(CT_WHERE_COLON);
+ colon->SetParentType(m_start->GetType());
+} // EnumStructUnionParser::mark_where_colon
+
+
+void EnumStructUnionParser::parse(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ initialize(pc);
+
+ if (parse_error_detected())
+ {
+ return;
+ }
+
+ /**
+ * make sure this wasn't a cast, and also make sure we're
+ * actually dealing with a class/enum/struct/union type
+ */
+ if ( m_start->GetParentType() == CT_C_CAST
+ || !m_start->IsClassEnumStructOrUnion())
+ {
+ return;
+ }
+ Chunk *prev = m_start;
+ Chunk *next = prev->GetNextNcNnl();
+
+ /**
+ * the enum-key might be enum, enum class or enum struct
+ */
+ if (next->IsEnum())
+ {
+ prev = next;
+ next = prev->GetNextNcNnl();
+ }
+ else if (prev->IsEnum())
+ {
+ Chunk *prev_prev = prev->GetPrevNcNnlNi();
+
+ if ( prev_prev->IsEnum()
+ && prev->IsEnum())
+ {
+ 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 (next->Is(CT_ASSIGN))
+ {
+ next = skip_to_expression_end(next);
+ }
+
+ if ( next->Is(CT_ANGLE_OPEN)
+ && !template_detected())
+ {
+ next = parse_angles(next);
+ }
+ else if ( next->Is(CT_BRACE_OPEN)
+ && !body_detected())
+ {
+ next = parse_braces(next);
+ }
+ else if (next->IsColon())
+ {
+ parse_colon(next);
+ }
+ else if (next->Is(CT_COMMA))
+ {
+ record_top_level_comma(next);
+ }
+ else if (next->Is(CT_DC_MEMBER))
+ {
+ next = parse_double_colon(next);
+ }
+ else if ( next->IsParenOpen()
+ && ( language_is_set(LANG_D)
+ || ( language_is_set(LANG_PAWN)
+ && m_start->IsEnum())))
+ {
+ set_paren_parent(next, m_start->GetType());
+
+ if ( prev->Is(CT_WORD)
+ && language_is_set(LANG_D))
+ {
+ mark_template(next);
+ }
+ next = next->GetClosingParen(E_Scope::PREPROC);
+ }
+ else if ( next->Is(CT_QUALIFIER)
+ && language_is_set(LANG_JAVA)
+ && std::strncmp(next->GetStr().c_str(), "implements", 10) == 0)
+ {
+ mark_base_classes(next);
+ }
+ else if (next->Is(CT_QUESTION))
+ {
+ record_question_operator(next);
+ }
+ else if ( next->Is(CT_WHERE)
+ && !where_clause_detected())
+ {
+ mark_where_clause(next);
+ }
+ prev = next;
+
+ do
+ {
+ next = next->GetNextNcNnl();
+ } while ( next->IsNotNullChunk()
+ && next->GetLevel() > m_start->GetLevel());
+ }
+ /**
+ * identify the type and/or variable(s)
+ */
+ analyze_identifiers();
+
+ /**
+ * identify and mark lvalues occurring outside the body definition
+ */
+ mark_extracorporeal_lvalues();
+
+ if ( prev->IsNotNullChunk()
+ && prev->IsSemicolon()
+ && prev->GetLevel() == m_start->GetLevel()
+ && !prev->TestFlags(PCF_IN_FOR))
+ {
+ prev->SetParentType(m_start->GetType());
+ }
+} // 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 = angle_open->GetClosingParen(E_Scope::PREPROC);
+
+ if (angle_close->IsNullChunk())
+ {
+ // 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->GetOrigLine(),
+ angle_open->GetOrigCol());
+ }
+ 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 (next->IsNot(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 (prev->IsNot(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->GetOrigLine(),
+ angle_open->GetOrigCol());
+ }
+ 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 = pc->GetClosingParen(E_Scope::PREPROC);
+
+ if (brace_close->IsNotNullChunk())
+ {
+ /**
+ * 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))
+ && prev->IsParenClose())
+ {
+ /**
+ * 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 = paren_close->GetOpeningParen();
+
+ if (paren_open->IsNotNullChunk())
+ {
+ /**
+ * 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 = ( ( identifier->Is(CT_FUNCTION)
+ || identifier->Is(CT_FUNC_DEF)
+ || identifier->Is(CT_WORD))
+ && type != identifier);
+ }
+ }
+
+ if ( language_is_set(LANG_D)
+ || language_is_set(LANG_PAWN)
+ || !prev->IsParenClose()
+ || 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)
+ && m_start->IsEnum())
+ {
+ 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->GetOrigLine(),
+ brace_open->GetOrigCol());
+
+ // parse error
+ parse_error_detected(true);
+ }
+ }
+ return(pc);
+} // EnumStructUnionParser::parse_braces
+
+
+void EnumStructUnionParser::parse_colon(Chunk *colon)
+{
+ LOG_FUNC_ENTRY();
+
+ if (m_start->Is(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->GetOrigLine(),
+ colon->GetOrigCol());
+
+ // 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 (m_start->IsClassOrStruct())
+ {
+ /**
+ * the colon likely specifies an inheritance list for a struct
+ * or class type
+ */
+
+ set_inheritance_start(colon);
+ mark_class_colon(colon);
+ }
+ else if (m_start->IsEnum())
+ {
+ 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)
+ && pc->Is(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 (question->Is(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->IsNotNullChunk()
+ && comma->GetLevel() == m_start->GetLevel()
+ && !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))
+ && pc->Is(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 (next->IsSemicolon())
+ {
+ pc = next;
+
+ break;
+ }
+ else
+ {
+ /**
+ * if we're sitting at a comma, skip it
+ */
+ if (next->Is(CT_COMMA))
+ {
+ next = next->GetNextNcNnl();
+ }
+ auto match = match_variable(next, m_start->GetLevel());
+ auto *start = std::get<0>(match);
+ auto *identifier = std::get<1>(match);
+ auto *end = std::get<2>(match);
+
+ if ( end->IsNullChunk()
+ || identifier->IsNullChunk()
+ || start->IsNullChunk())
+ {
+ break;
+ }
+ else
+ {
+ pc = end->GetNextNcNnl();
+
+ /**
+ * skip any right-hand side assignments
+ */
+ if (pc->Is(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 (body_end->Is(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 (body_start->Is(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 (enum_base_start->IsColon())
+ {
+ 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 (inheritance_start->IsColon())
+ {
+ m_chunk_map[CT_COLON][0] = inheritance_start;
+ }
+} // EnumStructUnionParser::set_inheritance_start
+
+
+void EnumStructUnionParser::set_template_end(Chunk *template_end)
+{
+ LOG_FUNC_ENTRY();
+
+ if (template_end->Is(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 (template_start->Is(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 (where_end->Is(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 (where_start->Is(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->IsNotNullChunk()
+ && template_start->IsNotNullChunk());
+} // EnumStructUnionParser::template_detected
+
+
+Chunk *EnumStructUnionParser::try_find_end_chunk(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+
+ do
+ {
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+
+ /**
+ * 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 ( pc->Is(CT_TYPE)
+ || pc->Is(CT_WORD))
+ {
+ pc->SetType(CT_WORD);
+ pc->SetParentType(CT_NONE);
+ }
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+
+ do
+ {
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ } while ( pc->IsNotNullChunk()
+ && pc->GetLevel() > m_start->GetLevel());
+
+ if (pc->IsNullChunk())
+ {
+ LOG_FMT(LFTOR, "%s(%d): IsNullChunk\n",
+ __unqualified_func__, __LINE__);
+ // parse error
+ parse_error_detected(true);
+ return(Chunk::NullChunkPtr);
+ }
+ else
+ {
+ LOG_FMT(LFTOR, "%s(%d): orig line is %zu, orig col is %zu, type is %s\n",
+ __unqualified_func__, __LINE__,
+ pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ }
+ } 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 = Chunk::NullChunkPtr;
+
+ do
+ {
+ if ( !chunk_is_between(prev, inheritance_start, body_start)
+ && ( prev->Is(CT_WORD)
+ || prev->Is(CT_FUNCTION)
+ || prev->Is(CT_FUNC_DEF))
+ && !prev->GetFlags().test_any(PCF_VAR_DEF | PCF_VAR_1ST | PCF_VAR_INLINE)
+ && prev->GetLevel() == m_start->GetLevel())
+ {
+ if (pc->IsParenOpen())
+ {
+ auto *paren_open = pc;
+ auto *paren_close = paren_open->GetClosingParen(E_Scope::PREPROC);
+
+ if (paren_close->IsNotNullChunk())
+ {
+ paren_open->SetType(CT_FPAREN_OPEN);
+ paren_open->SetParentType(CT_MACRO_FUNC_CALL);
+ paren_close->SetType(CT_FPAREN_CLOSE);
+ paren_close->SetParentType(CT_MACRO_FUNC_CALL);
+ prev->SetType(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->IsNullChunk())
+ {
+ /**
+ * 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 = Chunk::NullChunkPtr;
+ 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->GetFlags().test_any(PCF_VAR_DEF | PCF_VAR_1ST | PCF_VAR_INLINE))
+ {
+ break;
+ }
+ else if ( pc->Is(CT_WORD)
+ || pc->Is(CT_ANGLE_CLOSE))
+ {
+ type = skip_template_prev(pc);
+ }
+ pc = pc->GetNextNcNnl();
+ } while (chunk_is_between(pc, m_start, m_end));
+
+ if (type->IsNotNullChunk())
+ {
+ 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)
+ && m_start->IsEnum())
+ {
+ set_paren_parent(pc, m_start->GetType());
+ }
+ 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 (m_start->Is(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->GetOrigLine(),
+ m_start->GetOrigCol());
+
+ parse_error_detected(true);
+
+ return(false);
+ }
+ }
+
+ if (pc->IsNullChunk())
+ {
+ 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()
+ && next->Is(CT_WORD)
+ && next_next->Is(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)
+ || m_start->GetParentType() == 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)
+ && ( ( next->IsNot(CT_ASSIGN)
+ && next->IsNot(CT_COMMA))
+ || next->GetLevel() != m_start->GetLevel())
+ && !next->IsSemicolon())
+ {
+ 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
+ || next->IsParenOpen())
+ {
+ prev = next->GetClosingParen(E_Scope::PREPROC);
+ next = prev->GetNextNcNnl(E_Scope::PREPROC);
+ }
+
+ if ( prev->Is(CT_WORD)
+ && next->IsPointerOrReference())
+ {
+ pc = next;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (pc->IsNotNullChunk())
+ {
+ /**
+ * the chunk preceding the previously selected chunk should indicate the type
+ */
+
+ pc = pc->GetPrevNcNnlNi(E_Scope::PREPROC);
+
+ if ( pc->Is(CT_QUALIFIER)
+ && std::strncmp(pc->GetStr().c_str(), "final", 5) == 0)
+ {
+ pc = pc->GetPrevNcNnlNi(E_Scope::PREPROC);
+ }
+
+ if ( language_is_set(LANG_D)
+ && pc->IsParenClose())
+ {
+ pc = pc->GetOpeningParen();
+ pc = pc->GetPrevNcNnlNi();
+ }
+
+ if (pc->Is(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->IsNotNullChunk());
+} // 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->IsNotNullChunk()
+ && where_start->IsNotNullChunk());
+} // EnumStructUnionParser::where_clause_detected
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/EnumStructUnionParser.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/EnumStructUnionParser.h
new file mode 100644
index 00000000..136a0eb7
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/EnumStructUnionParser.h
@@ -0,0 +1,497 @@
+/**
+ * @file combine_fix_mark_enum_struct_union.h
+ *
+ * @author Joshua Parker
+ * @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, PcfFlags 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.78.0/src/ListManager.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ListManager.h
new file mode 100644
index 00000000..64bc5fd8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/ListManager.h
@@ -0,0 +1,216 @@
+/**
+ * @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
+
+#include "chunk.h"
+
+/**
+ * A simple list manager for a double-linked list of Chunk items.
+ */
+class ChunkListManager
+{
+protected:
+ Chunk *m_head; // pointer to the head of list
+ Chunk *m_tail; // pointer to tail of list
+
+public:
+ ChunkListManager()
+ {
+ m_head = Chunk::NullChunkPtr;
+ m_tail = Chunk::NullChunkPtr;
+ }
+
+
+ /**
+ * @return pointer to first element of the linked list
+ */
+ Chunk *GetHead() const
+ {
+ return(m_head);
+ }
+
+
+ /**
+ * @return pointer to last element of the linked list
+ */
+ Chunk *GetTail() const
+ {
+ return(m_tail);
+ }
+
+
+ /**
+ * @brief remove an element from a linked list
+ * @param[in] obj chunk to remove from the list
+ */
+ void Remove(Chunk *obj)
+ {
+ if (obj != Chunk::NullChunkPtr)
+ {
+ if (m_head == obj)
+ {
+ m_head = obj->m_next;
+ }
+
+ if (m_tail == obj)
+ {
+ m_tail = obj->m_prev;
+ }
+
+ if (obj->m_next != Chunk::NullChunkPtr)
+ {
+ obj->m_next->m_prev = obj->m_prev;
+ }
+
+ if (obj->m_prev != Chunk::NullChunkPtr)
+ {
+ obj->m_prev->m_next = obj->m_next;
+ }
+ obj->m_next = Chunk::NullChunkPtr;
+ obj->m_prev = Chunk::NullChunkPtr;
+ }
+ }
+
+
+ //! swap two elements of a list
+ void Swap(Chunk *obj1, Chunk *obj2)
+ {
+ if ( obj1 != Chunk::NullChunkPtr
+ && obj2 != Chunk::NullChunkPtr)
+ {
+ if (obj1->m_prev == obj2)
+ {
+ Remove(obj1);
+ AddBefore(obj1, obj2);
+ }
+ else if (obj2->m_prev == obj1)
+ {
+ Remove(obj2);
+ AddBefore(obj2, obj1);
+ }
+ else
+ {
+ Chunk *m_prev1 = obj1->m_prev;
+ Remove(obj1);
+
+ Chunk *m_prev2 = obj2->m_prev;
+ Remove(obj2);
+
+ AddAfter(obj1, m_prev2);
+ AddAfter(obj2, m_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(Chunk *obj, Chunk *ref)
+ {
+ if ( obj != Chunk::NullChunkPtr
+ && ref != Chunk::NullChunkPtr)
+ {
+ obj->m_next = ref->m_next;
+ obj->m_prev = ref;
+
+ if (ref->m_next != Chunk::NullChunkPtr)
+ {
+ ref->m_next->m_prev = obj;
+ }
+ else
+ {
+ m_tail = obj;
+ }
+ ref->m_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(Chunk *obj, Chunk *ref)
+ {
+ if ( obj != Chunk::NullChunkPtr
+ && ref != Chunk::NullChunkPtr)
+ {
+ Remove(obj);
+ obj->m_next = ref;
+ obj->m_prev = ref->m_prev;
+
+ if (ref->m_prev != Chunk::NullChunkPtr)
+ {
+ ref->m_prev->m_next = obj;
+ }
+ else
+ {
+ m_head = obj;
+ }
+ ref->m_prev = obj;
+ }
+ }
+
+
+ /**
+ * @brief add a new element to the tail of a lis
+ *
+ * @param obj new element to add to the list
+ */
+ void AddTail(Chunk *obj)
+ {
+ obj->m_next = Chunk::NullChunkPtr;
+ obj->m_prev = m_tail;
+
+ if (m_tail == Chunk::NullChunkPtr)
+ {
+ m_tail = obj;
+ m_head = obj;
+ }
+ else
+ {
+ m_tail->m_next = obj;
+ }
+ m_tail = obj;
+ }
+
+
+ /**
+ * @brief add a new element to the head of a list
+ *
+ * @param obj new element to add to the list
+ */
+ void AddHead(Chunk *obj)
+ {
+ obj->m_next = m_head;
+ obj->m_prev = Chunk::NullChunkPtr;
+
+ if (m_head == Chunk::NullChunkPtr)
+ {
+ m_tail = obj;
+ m_head = obj;
+ }
+ else
+ {
+ m_head->m_prev = obj;
+ }
+ m_head = obj;
+ }
+};
+
+
+#endif /* LIST_MANAGER_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/add_space_table.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/add_space_table.h
new file mode 100644
index 00000000..47b54148
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/add_space_table.h
@@ -0,0 +1,375 @@
+// *INDENT-OFF*
+
+#include "token_enum.h"
+
+//! 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[] =
+{
+ { 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_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_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_IGNORED, CT_IGNORED },
+ { 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_PRAGMA, CT_PP_ENDASM },
+ { CT_PP_PRAGMA, CT_PP_ENDREGION },
+ { CT_PP_PRAGMA, CT_PP_REGION },
+ { CT_PP_PROPERTY, CT_WORD },
+ { CT_PP_REGION, CT_IGNORED },
+ { 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_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 },
+};
+
+/**
+ * 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 },
+};
+
+/**
+ * this table lists out all combos where nothing is to do
+ * CT_UNKNOWN is a wildcard.
+ *
+ * TODO: some of these are no longer needed.
+ */
+const no_space_table_t IGNORE_space_table[] =
+{
+ //{ CT_RPAREN_OPEN, CT_RPAREN_CLOSE},
+ //{ CT_RPAREN_OPEN, CT_UNKNOWN },
+ //{ CT_UNKNOWN, CT_RPAREN_CLOSE},
+ { CT_PAREN_CLOSE, CT_SIZEOF},
+};
+
+
+// *INDENT-ON*
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align.cpp
new file mode 100644
index 00000000..830c41b8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align.cpp
@@ -0,0 +1,232 @@
+/**
+ * @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 occurred.", "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()
+{
+ LOG_FUNC_ENTRY();
+
+ if (options::align_typedef_span() > 0)
+ {
+ log_rule_B("align_typedef_span");
+ align_typedefs(options::align_typedef_span());
+ }
+
+ if (options::align_left_shift())
+ {
+ log_rule_B("align_left_shift");
+ align_left_shift();
+ }
+
+ if (options::align_eigen_comma_init())
+ {
+ log_rule_B("align_eigen_comma_init");
+ align_eigen_comma_init();
+ }
+
+ if (options::align_oc_msg_colon_span() > 0)
+ {
+ log_rule_B("align_oc_msg_colon_span");
+ align_oc_msg_colons();
+ }
+
+ if ( (options::align_var_def_span() > 0)
+ || (options::align_var_struct_span() > 0)
+ || (options::align_var_class_span() > 0))
+ {
+ // Align variable definitions
+ log_rule_B("align_var_def_span");
+ log_rule_B("align_var_struct_span");
+ log_rule_B("align_var_class_span");
+ align_var_def_brace(Chunk::GetHead(), options::align_var_def_span(), nullptr);
+ }
+
+ if ( (options::align_enum_equ_span() > 0)
+ || (options::align_assign_span() > 0))
+ {
+ // Align assignments
+ log_rule_B("align_enum_equ_span");
+ log_rule_B("align_assign_span");
+ 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 initializers lists
+ align_braced_init_list(Chunk::GetHead(),
+ options::align_braced_init_list_span(),
+ options::align_braced_init_list_thresh(),
+ nullptr);
+ }
+
+ if (options::align_struct_init_span() > 0)
+ {
+ // Align structure initializers
+ log_rule_B("align_struct_init_span");
+ align_struct_initializers();
+ }
+
+ if ( (options::align_func_proto_span() > 0)
+ && !options::align_mix_var_proto())
+ {
+ // Align function prototypes
+ log_rule_B("align_func_proto_span");
+ log_rule_B("align_mix_var_proto");
+ align_func_proto(options::align_func_proto_span());
+ }
+
+ if (options::align_oc_msg_spec_span() > 0)
+ {
+ // Align OC message spec
+ log_rule_B("align_oc_msg_spec_span");
+ align_oc_msg_spec(options::align_oc_msg_spec_span());
+ }
+
+ if (options::align_oc_decl_colon())
+ {
+ // Align OC colons
+ log_rule_B("align_oc_decl_colon");
+ align_oc_decl_colon();
+ }
+
+ if (options::align_asm_colon())
+ {
+ // Align ASM colons
+ log_rule_B("align_asm_colon");
+ align_asm_colon();
+ }
+
+ if ( options::align_func_params()
+ || options::align_func_params_span() > 0)
+ {
+ // Align variable definitions in function prototypes
+ log_rule_B("align_func_params");
+ log_rule_B("align_func_params_span");
+ align_func_params();
+ }
+
+ if (options::align_same_func_call_params())
+ {
+ // Align parameters in function call
+ log_rule_B("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.78.0/src/align.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align.h
new file mode 100644
index 00000000..000fc935
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align.h
@@ -0,0 +1,16 @@
+/**
+ * @file align.h
+ * prototypes for align.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef ALIGN_H_INCLUDED
+#define ALIGN_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+void align_all();
+
+#endif /* ALIGN_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_add.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_add.cpp
new file mode 100644
index 00000000..ae8460d2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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->IsNotNullChunk())
+ {
+ prev = pc->GetPrev();
+ }
+
+ if ( prev->IsNullChunk()
+ || prev->IsNewline())
+ {
+ 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->GetOrigLine(), pc->GetColumn(), max_col, min_col);
+ }
+ else
+ {
+ if (prev->Is(CT_COMMENT_MULTI))
+ {
+ min_col = prev->GetOrigColEnd() + 1;
+ }
+ else
+ {
+ min_col = prev->GetColumn() + 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->GetOrigLine(), pc->GetColumn(), max_col, min_col, (prev->Is(CT_COMMENT_MULTI)) ? "Y" : "N",
+ (prev->Is(CT_COMMENT_MULTI)) ? prev->GetOrigColEnd() : (UINT32)prev->GetColumn(), prev->Len(), get_token_name(prev->GetType()));
+ }
+
+ 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.78.0/src/align_add.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_add.h
new file mode 100644
index 00000000..e178b5bd
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_asm_colon.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_asm_colon.cpp
new file mode 100644
index 00000000..4eaca4f3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ LOG_FUNC_ENTRY();
+
+ bool did_nl;
+ AlignStack cas; // for the colons
+
+ cas.Start(4);
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->IsNot(CT_ASM_COLON))
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+ cas.Reset();
+
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ size_t level = pc->IsNotNullChunk() ? pc->GetLevel() : 0;
+ did_nl = true;
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() >= level)
+ {
+ if (pc->IsNewline())
+ {
+ cas.NewLines(pc->GetNlCount());
+ did_nl = true;
+ }
+ else if (pc->Is(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.78.0/src/align_asm_colon.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_asm_colon.h
new file mode 100644
index 00000000..2b0d3738
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_ASM_COLON_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_assign.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_assign.cpp
new file mode 100644
index 00000000..b9012a2b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_assign.cpp
@@ -0,0 +1,289 @@
+/**
+ * @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->IsNullChunk())
+ {
+ // coveralls will complain here. There are no example for that.
+ // see https://en.wikipedia.org/wiki/Robustness_principle
+ return(Chunk::NullChunkPtr);
+ }
+ size_t my_level = first->GetLevel();
+
+ 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->GetOrigLine(), 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 nl_count = 0;
+ size_t fcn_idx = 0;
+ size_t tmp;
+ Chunk *pc = first;
+ Chunk *vdas_pc = Chunk::NullChunkPtr;
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): orig line is %zu, check pc->Text() is '%s', type is %s, m_parentType is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->ElidedText(copy), get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ if (nl_count != 0)
+ {
+ if (vdas_pc->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): vdas.Add on '%s' on orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, vdas_pc->Text(), vdas_pc->GetOrigLine(), vdas_pc->GetOrigCol());
+ vdas.Add(vdas_pc);
+ vdas_pc = Chunk::NullChunkPtr;
+ }
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += nl_count;
+ }
+ as.NewLines(nl_count);
+ vdas.NewLines(nl_count);
+ fcnProto.NewLines(nl_count);
+
+ for (auto &fcn : fcnDefault)
+ {
+ fcn.NewLines(nl_count);
+ }
+
+ fcn_idx = 0;
+ nl_count = 0;
+ var_def_cnt = 0;
+ equ_count = 0;
+ }
+
+ // Don't check inside SPAREN, PAREN or SQUARE groups
+ if ( pc->Is(CT_SPAREN_OPEN)
+ // || pc->Is(CT_FPAREN_OPEN) Issue #1340
+ || pc->Is(CT_SQUARE_OPEN)
+ || pc->Is(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->GetType()));
+ tmp = pc->GetOrigLine();
+ pc = pc->GetClosingParen();
+
+ if (pc->IsNotNullChunk())
+ {
+ nl_count = pc->GetOrigLine() - tmp;
+ }
+ continue;
+ }
+
+ // Recurse if a brace set is found
+ if ( ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_VBRACE_OPEN))
+ && !(pc->GetParentType() == CT_BRACED_INIT_LIST))
+ {
+ size_t myspan;
+ size_t mythresh;
+
+ if (pc->GetParentType() == 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->GetNext(), myspan, mythresh, &nl_count);
+ continue;
+ }
+
+ // Done with this brace set?
+ if ( ( pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_VBRACE_CLOSE))
+ && !(pc->GetParentType() == CT_BRACED_INIT_LIST))
+ {
+ pc = pc->GetNext();
+ break;
+ }
+
+ if (pc->IsNewline())
+ {
+ nl_count = pc->GetNlCount();
+ }
+ else if ( pc->TestFlags(PCF_VAR_DEF)
+ && !pc->TestFlags(PCF_IN_CONST_ARGS) // Issue #1717
+ && !pc->TestFlags(PCF_IN_FCN_DEF) // Issue #1717
+ && !pc->TestFlags(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->GetFlags():\n ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->GetFlags());
+ 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_pc = Chunk::NullChunkPtr;
+ }
+ else if ( equ_count == 0 // indent only if first '=' in line
+ && !pc->TestFlags(PCF_IN_TEMPLATE) // and it is not inside a template #999
+ && ( pc->Is(CT_ASSIGN)
+ || pc->Is(CT_ASSIGN_DEFAULT_ARG)
+ || pc->Is(CT_ASSIGN_FUNC_PROTO)))
+ {
+ if (pc->Is(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->GetFlags(): ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->GetFlags());
+
+ log_rule_B("align_assign_decl_func");
+
+ if ( options::align_assign_decl_func() == 0 // Align with other assignments (default)
+ && ( pc->Is(CT_ASSIGN_DEFAULT_ARG) // Foo( int bar = 777 );
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol());
+
+ 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 (pc->Is(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->GetOrigLine(), pc->GetOrigCol());
+
+ 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 (pc->Is(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->GetOrigLine(), pc->GetOrigCol());
+ fcnProto.Add(pc);
+ }
+ else if (pc->Is(CT_ASSIGN)) // Issue #2197
+ {
+ vdas_pc = pc;
+ }
+ }
+ else if ( options::align_assign_decl_func() == 2 // Don't align
+ && ( pc->Is(CT_ASSIGN_DEFAULT_ARG) // Foo( int bar = 777 );
+ || pc->Is(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)
+ {
+ vdas_pc = pc;
+ }
+ else
+ {
+ if (pc->Is(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->GetOrigLine(), pc->GetOrigCol());
+ as.Add(pc);
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+
+ if (vdas_pc->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): vdas.Add on '%s' on orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, vdas_pc->Text(), vdas_pc->GetOrigLine(), vdas_pc->GetOrigCol());
+ vdas.Add(vdas_pc);
+ vdas_pc = Chunk::NullChunkPtr;
+ }
+ as.End();
+ vdas.End();
+
+ for (auto &fcn : fcnDefault)
+ {
+ fcn.End();
+ }
+
+ fcnProto.End();
+
+ if (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): done on '%s' on orig line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ }
+ 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.78.0/src/align_assign.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_assign.h
new file mode 100644
index 00000000..8a23d0d5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_braced_init_list.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_braced_init_list.cpp
new file mode 100644
index 00000000..8071a3ce
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_braced_init_list.cpp
@@ -0,0 +1,165 @@
+/**
+ * @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->IsNullChunk())
+ {
+ // coveralls will complain here. There are no example for that.
+ // see https://en.wikipedia.org/wiki/Robustness_principle
+ return(Chunk::NullChunkPtr);
+ }
+ size_t my_level = first->GetLevel();
+
+ 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->GetOrigLine(), 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->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): orig line is %zu, check pc->Text() is '%s', type is %s, parent type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->ElidedText(copy), get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ // Don't check inside SPAREN, PAREN or SQUARE groups
+ if ( pc->Is(CT_SPAREN_OPEN)
+ || pc->Is(CT_SQUARE_OPEN)
+ || pc->Is(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->GetType()));
+ tmp = pc->GetOrigLine();
+ pc = pc->GetClosingParen();
+
+ if (pc->IsNotNullChunk())
+ {
+ vdas.NewLines(pc->GetOrigLine() - tmp);
+ }
+ continue;
+ }
+
+ // Recurse if a brace set is found
+ if ( pc->Is(CT_BRACE_OPEN)
+ && !(pc->GetParentType() == 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 ( ( pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_VBRACE_CLOSE))
+ && !(pc->GetParentType() == CT_BRACED_INIT_LIST))
+ {
+ pc = pc->GetNext();
+ break;
+ }
+
+ if (pc->IsNewline())
+ {
+ vdas.NewLines(pc->GetNlCount());
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += pc->GetNlCount();
+ }
+ var_def_cnt = 0;
+ equ_count = 0;
+ }
+ else if ( pc->TestFlags(PCF_VAR_DEF)
+ && !pc->TestFlags(PCF_IN_CONST_ARGS) // Issue #1717
+ && !pc->TestFlags(PCF_IN_FCN_DEF) // Issue #1717
+ && !pc->TestFlags(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->GetFlags():\n ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->GetFlags());
+ 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->TestFlags(PCF_IN_TEMPLATE)
+ && pc->Is(CT_BRACE_OPEN)
+ && (pc->GetParentType() == 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->GetFlags(): ", __func__, __LINE__);
+ //log_pcf_flags(LALASS, pc->GetFlags());
+
+ 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->GetOrigLine(), pc->GetOrigCol());
+ vdas.Add(pc);
+ }
+ }
+ pc = pc->GetNext();
+ }
+ vdas.End();
+
+ if (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LALASS, "%s(%d): done on '%s' on orig line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ }
+ 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.78.0/src/align_braced_init_list.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_braced_init_list.h
new file mode 100644
index 00000000..e29868e0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_eigen_comma_init.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_eigen_comma_init.cpp
new file mode 100644
index 00000000..d096a9a7
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_eigen_comma_init.cpp
@@ -0,0 +1,113 @@
+/**
+ * @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()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *start = Chunk::NullChunkPtr;
+ AlignStack as;
+
+ as.Start(255);
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ if ( start->IsNotNullChunk()
+ && ((pc->GetFlags() & PCF_IN_PREPROC) != (start->GetFlags() & PCF_IN_PREPROC)))
+ {
+ // a change in preproc status restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if (pc->IsNewline())
+ {
+ as.NewLines(pc->GetNlCount());
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->GetLevel() < start->GetLevel())
+ {
+ // A drop in level restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->GetLevel() > start->GetLevel())
+ {
+ // Ignore any deeper levels when aligning
+ }
+ else if (pc->Is(CT_SEMICOLON))
+ {
+ // A semicolon at the same level flushes
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( !pc->TestFlags(PCF_IN_ENUM)
+ && !pc->TestFlags(PCF_IN_TYPEDEF)
+ && pc->IsString("<<"))
+ {
+ if (pc->GetParentType() == 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()
+ && prev->IsNewline())
+ {
+ log_rule_B("indent_columns");
+ indent_to_column(pc, pc->GetColumnIndent() + options::indent_columns());
+ pc->SetColumnIndent(pc->GetColumn());
+ pc->SetFlagBits(PCF_DONT_INDENT);
+ }
+ // Restart alignment
+ as.Flush();
+ as.Add(pc->GetNext());
+ start = pc;
+ }
+ }
+ else if (!as.m_aligned.Empty())
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->IsNewline()
+ && pc->GetPrevNcNnl()->Is(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.78.0/src/align_eigen_comma_init.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_eigen_comma_init.h
new file mode 100644
index 00000000..6647f030
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_EIGEN_COMMA_INIT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_params.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_params.cpp
new file mode 100644
index 00000000..50e04d78
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_params.cpp
@@ -0,0 +1,186 @@
+/**
+ * @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->GetOrigLine(), start->GetColumn(),
+ get_token_name(start->GetType()), start->GetLevel());
+ // 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_CHUNK(LTOK, pc);
+
+ if (pc->Is(CT_FUNC_VAR)) // Issue #2278
+ {
+ // look after 'protect parenthesis'
+ Chunk *after = pc->GetNextNc();
+
+ if (after->Is(CT_PAREN_CLOSE))
+ {
+ Chunk *before = after->GetPrevType(CT_PAREN_OPEN, after->GetLevel());
+
+ if (before->IsNotNullChunk())
+ {
+ // these are 'protect parenthesis'
+ // change the types and the level
+ before->SetType(CT_PPAREN_OPEN);
+ after->SetType(CT_PPAREN_CLOSE);
+ pc->SetLevel(before->GetLevel());
+ Chunk *tmp = pc->GetPrevNc();
+
+ if (tmp->Is(CT_PTR_TYPE))
+ {
+ tmp->SetLevel(before->GetLevel());
+ }
+ }
+ }
+ }
+
+ if (pc->IsNewline())
+ {
+ comma_count = 0;
+ chunk_count = 0;
+ many_as[pc->GetLevel()].NewLines(pc->GetNlCount());
+ }
+ else if (pc->GetLevel() <= start->GetLevel())
+ {
+ break;
+ }
+ else if (pc->TestFlags(PCF_VAR_DEF))
+ {
+ if (chunk_count > 1)
+ {
+ if (pc->GetLevel() > HOW_MANY_AS)
+ {
+ fprintf(stderr, "%s(%d): Not enough 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->GetLevel());
+ many_as[pc->GetLevel()].Add(pc);
+ }
+ }
+ else if (comma_count > 0)
+ {
+ if (!pc->IsComment())
+ {
+ comma_count = 2;
+ break;
+ }
+ }
+ else if (pc->Is(CT_COMMA))
+ {
+ if (pc->TestFlags(PCF_IN_TEMPLATE)) // Issue #2757
+ {
+ LOG_FMT(LFLPAREN, "%s(%d): comma is in template\n",
+ __func__, __LINE__);
+ }
+ else
+ {
+ Chunk *tmp_prev = pc->GetPrevNc();
+
+ if (!tmp_prev->IsNewline()) // 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()
+{
+ 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', type is %s, parent type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(),
+ get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ if ( pc->IsNot(CT_FPAREN_OPEN)
+ || ( pc->GetParentType() != CT_FUNC_PROTO
+ && pc->GetParentType() != CT_FUNC_DEF
+ && pc->GetParentType() != CT_FUNC_CLASS_PROTO
+ && pc->GetParentType() != CT_FUNC_CLASS_DEF
+ && pc->GetParentType() != 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.78.0/src/align_func_params.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_params.h
new file mode 100644
index 00000000..4beb8cbf
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+Chunk *align_func_param(Chunk *start);
+
+#endif /* ALIGN_FUNC_PARAMS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_proto.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_proto.cpp
new file mode 100644
index 00000000..ede4c70d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_proto.cpp
@@ -0,0 +1,230 @@
+/**
+ * @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->GetLevel() == token-2->GetLevel()
+ // and
+ // token-1->GetBraceLevel() == token-2->GetBraceLevel()
+ // 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 %zu, orig col %zu, text '%s', type %s, level %zu, brace level %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy),
+ get_token_name(pc->GetType()), pc->GetLevel(), pc->GetBraceLevel());
+
+ // make the vector larger if necessary
+ if ( pc->GetLevel() >= num_of_column // Issue #2960
+ || pc->GetBraceLevel() >= num_of_row)
+ {
+ num_of_column = pc->GetLevel() + 1;
+ num_of_row = pc->GetBraceLevel() + 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 ( pc->IsNewline()
+ && ( !options::align_func_proto_span_ignore_cont_lines()
+ || !pc->GetNextNnl()->TestFlags(PCF_CONT_LINE)) // Issue #4131
+ && !pc->TestFlags(PCF_IN_FCN_CALL)) // Issue #2831
+ {
+ look_bro = false;
+ AlignStack *stack_at_l_bl = many_as.at(pc->GetLevel()).at(pc->GetBraceLevel());
+
+ 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->GetLevel()).at(pc->GetBraceLevel()) = 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->GetNlCount());
+ }
+ }
+ }
+
+ AlignStack *stack_at_l_bl_brace = many_as_brace.at(pc->GetLevel()).at(pc->GetBraceLevel());
+
+ 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->GetLevel()).at(pc->GetBraceLevel()) = stack_at_l_bl_brace;
+ }
+ stack_at_l_bl_brace->Debug();
+ stack_at_l_bl_brace->NewLines(pc->GetNlCount());
+ }
+ else if ( pc->Is(CT_FUNC_PROTO)
+ || ( pc->Is(CT_FUNC_DEF)
+ && options::align_single_line_func()))
+ {
+ log_rule_B("align_single_line_func");
+ log_rule_B("align_on_operator");
+
+ if ( pc->GetParentType() == 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->GetOrigLine(), tmp->GetOrigCol(),
+ tmp->GetLevel(), tmp->GetBraceLevel());
+ // test the Stack
+ AlignStack *stack_at_l_bl = many_as.at(pc->GetLevel()).at(pc->GetBraceLevel());
+
+ 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->GetLevel()).at(pc->GetBraceLevel()) = stack_at_l_bl;
+ }
+ stack_at_l_bl->Add(tmp);
+ stack_at_l_bl->Debug();
+ log_rule_B("align_single_line_brace");
+ look_bro = (pc->Is(CT_FUNC_DEF))
+ && options::align_single_line_brace();
+ }
+ else if ( look_bro
+ && pc->Is(CT_BRACE_OPEN)
+ && pc->TestFlags(PCF_ONE_LINER))
+ {
+ AlignStack *stack_at_l_bl_brace = many_as_brace.at(pc->GetLevel()).at(pc->GetBraceLevel());
+
+ 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->GetLevel()).at(pc->GetBraceLevel()) = stack_at_l_bl_brace;
+ }
+ stack_at_l_bl_brace->Add(pc);
+ stack_at_l_bl_brace->Debug();
+ 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.78.0/src/align_func_proto.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_func_proto.h
new file mode 100644
index 00000000..811020e0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_init_brace.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_init_brace.cpp
new file mode 100644
index 00000000..3d72af5f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_init_brace.cpp
@@ -0,0 +1,205 @@
+/**
+ * @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 = Chunk::NullChunkPtr;
+
+ 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->GetOrigLine(), start->GetOrigCol());
+
+ Chunk *pc = start->GetNextNcNnl();
+ Chunk *pcSingle = scan_ib_line(pc);
+
+ if ( pcSingle->IsNullChunk()
+ || ( pcSingle->Is(CT_BRACE_CLOSE)
+ && pcSingle->GetParentType() == 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);
+
+ // debug dump the current frame
+ LOG_FMT(LALBR, "%s(%d): debug dump after, orig line is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine());
+ align_log_al(LALBR, pc->GetOrigLine());
+
+ while (pc->IsNewline())
+ {
+ pc = pc->GetNext();
+ }
+ } while ( pc->IsNotNullChunk()
+ && pc->GetLevel() > start->GetLevel());
+
+ // debug dump the current frame
+ align_log_al(LALBR, start->GetOrigLine());
+
+ 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))->IsNotNullChunk()))
+ {
+ pc = tmp;
+
+ LOG_FMT(LALBR, " -%zu- skipped '[] =' to %s\n",
+ pc->GetOrigLine(), get_token_name(pc->GetType()));
+ continue;
+ }
+ Chunk *next = pc;
+
+ if (idx < cpd.al_cnt)
+ {
+ LOG_FMT(LALBR, "%s(%d): (%zu) check %s vs %s -- ??\n",
+ __func__, __LINE__, idx, get_token_name(pc->GetType()), get_token_name(cpd.al[idx].type));
+
+ if (pc->Is(cpd.al[idx].type))
+ {
+ if ( idx == 0
+ && cpd.al_c99_array)
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if (prev->IsNewline())
+ {
+ pc->SetFlagBits(PCF_DONT_INDENT);
+ }
+ }
+ LOG_FMT(LALBR, "%s(%d): cpd.al[%zu].col is %zu\n",
+ __func__, __LINE__, idx, cpd.al[idx].col);
+ LOG_FMT(LALBR, "%s(%d): (idx is %zu) check %s vs %s -- [%s] to col %zu\n",
+ __func__, __LINE__,
+ idx, get_token_name(pc->GetType()), get_token_name(cpd.al[idx].type), pc->Text(), cpd.al[idx].col);
+
+ if (num_token->IsNotNullChunk())
+ {
+ int col_diff = pc->GetColumn() - num_token->GetColumn();
+
+ reindent_line(num_token, cpd.al[idx].col - col_diff);
+ //LOG_FMT(LSYS, "-= %zu =- NUM indent [%s] col=%d diff=%d\n",
+ // num_token->GetOrigLine(),
+ // num_token->Text(), cpd.al[idx - 1].col, col_diff);
+
+ num_token->SetFlagBits(PCF_WAS_ALIGNED);
+ num_token = Chunk::NullChunkPtr;
+ }
+
+ // Comma's need to 'fall back' to the previous token
+ if (pc->Is(CT_COMMA))
+ {
+ next = pc->GetNext();
+
+ if (!next->IsNewline())
+ {
+ //LOG_FMT(LSYS, "-= %zu =- indent [%s] col=%d len=%d\n",
+ // next->GetOrigLine(),
+ // 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()
+ && ( next->Is(CT_NUMBER_FP)
+ || next->Is(CT_NUMBER)
+ || next->Is(CT_POS)
+ || next->Is(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);
+ next->SetFlagBits(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);
+ pc->SetFlagBits(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 ( !next->IsNewline()
+ && ( next->Is(CT_NUMBER_FP)
+ || next->Is(CT_NUMBER)
+ || next->Is(CT_POS)
+ || next->Is(CT_NEG)))
+ {
+ // Need to wait until the next match to indent numbers
+ num_token = next;
+ }
+ }
+ }
+ idx++;
+ }
+ else
+ {
+ LOG_FMT(LALBR, "%s(%d): (%zu) check %s vs %s -- no match\n",
+ __func__, __LINE__, idx, get_token_name(pc->GetType()), get_token_name(cpd.al[idx].type));
+ }
+ }
+
+ if ( pc->IsNewline()
+ || next->IsNewline())
+ {
+ idx = 0;
+ }
+ pc = pc->GetNext();
+ } while ( pc->IsNotNullChunk()
+ && pc->GetLevel() > start->GetLevel());
+} // align_init_brace
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_init_brace.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_init_brace.h
new file mode 100644
index 00000000..c749eb54
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_left_shift.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_left_shift.cpp
new file mode 100644
index 00000000..6ac2175c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *start = Chunk::NullChunkPtr;
+ AlignStack as;
+
+ as.Start(255);
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->IsNewline())
+ {
+ LOG_FMT(LALIGN, "%s(%d): orig line is %zu, <Newline>\n", __func__, __LINE__, pc->GetOrigLine());
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LALIGN, "%s(%d): orig line is %zu, orig col is %zu, pc->Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy));
+ }
+
+ if ( start->IsNotNullChunk()
+ && ((pc->GetFlags() & PCF_IN_PREPROC) != (start->GetFlags() & PCF_IN_PREPROC)))
+ {
+ // a change in preproc status restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if (pc->IsNewline())
+ {
+ as.NewLines(pc->GetNlCount());
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->GetLevel() < start->GetLevel())
+ {
+ // A drop in level restarts the aligning
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( start->IsNotNullChunk()
+ && pc->GetLevel() > start->GetLevel())
+ {
+ // Ignore any deeper levels when aligning
+ }
+ else if (pc->Is(CT_SEMICOLON))
+ {
+ // A semicolon at the same level flushes
+ as.Flush();
+ start = Chunk::NullChunkPtr;
+ }
+ else if ( !pc->TestFlags(PCF_IN_ENUM)
+ && !pc->TestFlags(PCF_IN_TYPEDEF)
+ && pc->IsString("<<"))
+ {
+ if (pc->GetParentType() == 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()
+ && prev->IsNewline())
+ {
+ log_rule_B("indent_columns");
+ indent_to_column(pc, pc->GetColumnIndent() + options::indent_columns());
+ pc->SetColumnIndent(pc->GetColumn());
+ pc->SetFlagBits(PCF_DONT_INDENT);
+ }
+ // first one can be anywhere
+ as.Add(pc);
+ start = pc;
+ }
+ else if (pc->GetPrev()->IsNewline())
+ {
+ // 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()
+ && prev->IsNewline())
+ {
+ log_rule_B("indent_columns");
+ indent_to_column(pc, pc->GetColumnIndent() + options::indent_columns());
+ pc->SetColumnIndent(pc->GetColumn());
+ pc->SetFlagBits(PCF_DONT_INDENT);
+ }
+ }
+ pc = pc->GetNext();
+ }
+ as.End();
+} // align_left_shift
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_left_shift.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_left_shift.h
new file mode 100644
index 00000000..d02155b0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_LEFT_SHIFT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_log_al.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_log_al.cpp
new file mode 100644
index 00000000..802b0280
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_log_al.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_log_al.h
new file mode 100644
index 00000000..8cb2ece8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_nl_cont.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_nl_cont.cpp
new file mode 100644
index 00000000..8019fddf
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_nl_cont.cpp
@@ -0,0 +1,85 @@
+/**
+ * @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"
+
+#include <algorithm> // to get max
+#include <limits>
+
+
+using namespace std;
+using namespace uncrustify;
+
+
+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->GetType()), start->GetOrigLine());
+
+ // Decide which column to align to
+ ChunkStack cs;
+ size_t align_col = 0;
+ size_t min_col = numeric_limits<size_t>::max();
+ size_t max_col = 0;
+ Chunk *pc = start;
+
+ while ( pc->IsNotNullChunk()
+ && pc->IsNot(CT_NEWLINE)
+ && pc->IsNot(CT_COMMENT_MULTI))
+ {
+ if (pc->Is(CT_NL_CONT))
+ {
+ align_add(cs, pc, align_col);
+ min_col = min(min_col, pc->GetColumn());
+ max_col = max(max_col, pc->GetColumn());
+ }
+ pc = pc->GetNext();
+ }
+ align_col = align_col - 1 + options::align_nl_cont_spaces();
+
+ if (options::align_nl_cont() == 2) // align with leftmost backslash
+ {
+ align_col = max(align_col, min_col);
+ }
+ else if (options::align_nl_cont() == 3) // align with rightmost backslash
+ {
+ align_col = max(align_col, max_col);
+ }
+ // NL_CONT is always the last thing on a line
+ Chunk *tmp;
+
+ while ((tmp = cs.Pop_Back())->IsNotNullChunk())
+ {
+ tmp->SetFlagBits(PCF_WAS_ALIGNED);
+ tmp->SetColumn(align_col);
+ }
+ return(pc);
+} // align_nl_cont
+
+
+void align_backslash_newline()
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->IsNot(CT_NL_CONT))
+ {
+ pc = pc->GetNextType(CT_NL_CONT);
+ continue;
+ }
+ pc = align_nl_cont(pc);
+ }
+} // align_backslash_newline
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_nl_cont.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_nl_cont.h
new file mode 100644
index 00000000..fb2db581
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 (null chunk/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();
+
+#endif /* ALIGN_NL_COUNT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_decl_colon.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_decl_colon.cpp
new file mode 100644
index 00000000..35b4b58e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ 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 (pc->IsNot(CT_OC_SCOPE))
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+ nas.Reset();
+ cas.Reset();
+
+ size_t level = pc->GetLevel();
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ did_line = false;
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() >= level)
+ {
+ // The declaration ends with an open brace or semicolon
+ if ( pc->Is(CT_BRACE_OPEN)
+ || pc->IsSemicolon())
+ {
+ break;
+ }
+
+ if (pc->IsNewline())
+ {
+ nas.NewLines(pc->GetNlCount());
+ cas.NewLines(pc->GetNlCount());
+ did_line = false;
+ }
+ else if ( !did_line
+ && pc->Is(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 ( ( tmp->Is(CT_WORD)
+ || tmp->Is(CT_TYPE)
+ || tmp->Is(CT_OC_MSG_DECL)
+ || tmp->Is(CT_OC_MSG_SPEC))
+ && ( tmp2->Is(CT_WORD)
+ || tmp2->Is(CT_TYPE)
+ || tmp2->Is(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.78.0/src/align_oc_decl_colon.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_decl_colon.h
new file mode 100644
index 00000000..b44b11ee
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_OC_DECL_COLON_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_colons.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_colons.cpp
new file mode 100644
index 00000000..85b509d5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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->GetLevel();
+ 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->GetLevel() > level)
+ {
+ if (pc->GetLevel() > (level + 1))
+ {
+ // do nothing
+ }
+ else if (pc->IsNewline())
+ {
+ 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)
+ && pc->Is(CT_OC_COLON))
+ {
+ has_colon = true;
+ cas.Add(pc);
+ Chunk *tmp = pc->GetPrev();
+
+ if ( tmp->IsNotNullChunk()
+ && ( tmp->Is(CT_OC_MSG_FUNC)
+ || tmp->Is(CT_OC_MSG_NAME)))
+ {
+ nas.Add(tmp);
+ tmp->SetFlagBits(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 = Chunk::NullChunkPtr;
+
+ size_t len = nas.m_aligned.Len();
+
+ for (size_t idx = 0; idx < len; idx++)
+ {
+ Chunk *tmp = nas.m_aligned.GetChunk(idx);
+
+ if (tmp->IsNotNullChunk())
+ {
+ size_t tlen = tmp->GetStr().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->IsNotNullChunk()
+ && options::indent_oc_msg_prioritize_first_colon()
+ && len_diff > 0
+ && ( (longest->GetColumn() >= len_diff)
+ && (longest->GetColumn() - len_diff) > (longest->GetBraceLevel() * indent_size)))
+ {
+ longest->SetColumn(longest->GetColumn() - len_diff);
+ }
+ else if ( longest->IsNotNullChunk()
+ && len > 0)
+ {
+ Chunk chunk;
+
+ chunk.SetType(CT_SPACE);
+ chunk.SetParentType(CT_NONE);
+ chunk.SetOrigLine(longest->GetOrigLine());
+ chunk.SetOrigCol(longest->GetOrigCol());
+ chunk.SetLevel(longest->GetLevel());
+ chunk.SetBraceLevel(longest->GetBraceLevel());
+ chunk.SetFlags(longest->GetFlags() & PCF_COPY_FLAGS);
+
+ // start at one since we already indent for the '['
+ for (size_t idx = 1; idx < len; idx++)
+ {
+ chunk.Str().append(' ');
+ }
+
+ chunk.CopyAndAddBefore(longest);
+ }
+ nas.End();
+ cas.End();
+} // align_oc_msg_colon
+
+
+void align_oc_msg_colons()
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( pc->Is(CT_SQUARE_OPEN)
+ && pc->GetParentType() == CT_OC_MSG)
+ {
+ align_oc_msg_colon(pc);
+ }
+ }
+} // align_oc_msg_colons
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_colons.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_colons.h
new file mode 100644
index 00000000..0bbb7b6b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_OC_MSG_COLONS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_spec.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_spec.cpp
new file mode 100644
index 00000000..88671254
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 (pc->IsNewline())
+ {
+ as.NewLines(pc->GetNlCount());
+ }
+ else if (pc->Is(CT_OC_MSG_SPEC))
+ {
+ as.Add(pc);
+ }
+ }
+
+ as.End();
+} // void align_oc_msg_spec
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_spec.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_oc_msg_spec.h
new file mode 100644
index 00000000..b6500a6e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_preprocessor.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_preprocessor.cpp
new file mode 100644
index 00000000..18a853ea
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_preprocessor.cpp
@@ -0,0 +1,109 @@
+/**
+ * @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()
+{
+ 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->IsNotNullChunk())
+ {
+ // Note: not counting back-slash newline combos
+ if (pc->Is(CT_NEWLINE)) // mind the gap: pc->IsNewline() is NOT the same!
+ {
+ as.NewLines(pc->GetNlCount());
+ asf.NewLines(pc->GetNlCount());
+ }
+
+ // If we aren't on a 'define', then skip to the next non-comment
+ if (pc->IsNot(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->GetOrigLine(), pc->GetOrigCol());
+
+ cur_as = &as;
+
+ if (pc->Is(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->GetLevel());
+
+ LOG_FMT(LALPP, "%s(%d): jumped to (%s) on line %zu col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ // 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 (!pc->IsNewline())
+ {
+ LOG_FMT(LALPP, "%s(%d): align on '%s', line %zu col %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+
+ cur_as->Add(pc);
+ }
+ }
+ as.End();
+ asf.End();
+} // align_preprocessor
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_preprocessor.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_preprocessor.h
new file mode 100644
index 00000000..1095c94e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_PREPROCESSOR_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.cpp
new file mode 100644
index 00000000..d0750ae4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.cpp
@@ -0,0 +1,286 @@
+/**
+ * @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()
+{
+ 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;
+ UncText align_fcn_name;
+ UncText 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 (pc->IsNewline()) // for debugging
+ {
+ LOG_FMT(LAS, "%s(%3d): orig line is %zu, <Newline>\n", __func__, __LINE__, pc->GetOrigLine());
+ }
+ else
+ {
+ LOG_FMT(LAS, "%s(%3d): orig line is %zu, orig col is %zu, pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ }
+
+ if (pc->IsNot(CT_FUNC_CALL))
+ {
+ if (pc->IsNewline())
+ {
+ for (auto &as_v : array_of_AlignStack)
+ {
+ as_v.NewLines(pc->GetNlCount());
+ }
+
+ fcn_as.NewLines(pc->GetNlCount());
+ }
+ else if (pc->Is(CT_FUNC_CTOR_VAR)) // Issue #3916
+ {
+ Chunk *open_paren = pc->GetNextType(CT_FPAREN_OPEN, pc->GetLevel());
+ Chunk *close_paren = open_paren->GetClosingParen();
+ LOG_FMT(LAS, "%s(%3d): orig line is %zu, orig col is %zu, pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, open_paren->GetOrigLine(), open_paren->GetOrigCol(), open_paren->Text(), get_token_name(open_paren->GetType()));
+ LOG_FMT(LAS, "%s(%3d): orig line is %zu, orig col is %zu, pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, close_paren->GetOrigLine(), close_paren->GetOrigCol(), close_paren->Text(), get_token_name(close_paren->GetType()));
+ pc = close_paren;
+ }
+ else
+ {
+ // if we drop below the brace level that started it, we are done
+ if ( align_root->IsNotNullChunk()
+ && align_root->GetBraceLevel() > pc->GetBraceLevel())
+ {
+ 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 if (pc->Is(CT_FUNC_CALL))
+ // Only align function calls that are right after a newline
+ Chunk *prev = pc->GetPrev();
+
+ while ( prev->Is(CT_MEMBER)
+ || prev->Is(CT_DC_MEMBER))
+ {
+ Chunk *tprev = prev->GetPrev();
+
+ if (tprev->IsNot(CT_TYPE))
+ {
+ prev = tprev;
+ break;
+ }
+ prev = tprev->GetPrev();
+ }
+
+ if (!prev->IsNewline())
+ {
+ 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->GetStr();
+ prev = prev->GetNext();
+ }
+ align_fcn_name += pc->GetStr();
+ LOG_FMT(LASFCP, "%s(%3d): Func Call found at orig line is %zu, orig col is %zu, c_str() '%s'\n",
+ __func__, __LINE__, align_fcn->GetOrigLine(),
+ align_fcn->GetOrigCol(),
+ 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 NullChunk\n", __func__, __LINE__);
+
+ if ( align_root->GetBraceLevel() == pc->GetBraceLevel()
+ && align_root->GetLevel() == pc->GetLevel()
+ && align_fcn_name.equals(align_root_name))
+ {
+ //WITH_STACKID_DEBUG;
+ fcn_as.Add(pc);
+ align_cur->AlignData().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";
+ }
+
+ if (add_str != nullptr)
+ {
+ LOG_FMT(LASFCP, "%s(%3d): %s with function '%s', on orig line %zu\n",
+ __func__, __LINE__, add_str, align_fcn_name.c_str(), pc->GetOrigLine());
+ align_params(pc, chunks);
+
+ 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 ( chunks[idx]->Is(CT_NUMBER_FP)
+ || chunks[idx]->Is(CT_NUMBER)
+ || chunks[idx]->Is(CT_POS)
+ || chunks[idx]->Is(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->GetLevel());
+
+ while ((pc = pc->GetNext())->IsNotNullChunk())
+ {
+ LOG_FMT(LAS, "%s(%3d): orig line is %zu, orig col is %zu, pc->Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+
+ if ( pc->IsNewline()
+ || pc->Is(CT_SEMICOLON)
+ || ( pc->Is(CT_FPAREN_CLOSE)
+ && pc->GetLevel() == start->GetLevel()))
+ {
+ break;
+ }
+
+ if (pc->GetLevel() == (start->GetLevel() + 1))
+ {
+ if (hit_comma)
+ {
+ LOG_FMT(LAS, "%s(%3d): hit_comma, orig line is %zu, orig col is %zu, pc->Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ chunks.push_back(pc);
+ hit_comma = false;
+ }
+ else if (pc->Is(CT_COMMA))
+ {
+ hit_comma = true;
+ }
+ }
+ }
+} // void align_params
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.h
new file mode 100644
index 00000000..d308b0b5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_same_func_call_params.h
@@ -0,0 +1,23 @@
+/**
+ * @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();
+
+#endif /* ALIGN_SAME_FUNC_CALL_PARAMS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_stack.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_stack.cpp
new file mode 100644
index 00000000..72cbc29d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_stack.cpp
@@ -0,0 +1,659 @@
+/**
+ * @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;
+} // AlignStack::Start
+
+
+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
+} // AlignStack::ReAddSkipped
+
+
+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 '%s': orig line %zu, column %zu, type %s, level %zu\n",
+ __func__, __LINE__, start->Text(), start->GetOrigLine(), start->GetColumn(), get_token_name(start->GetType()), start->GetLevel());
+ LOG_FMT(LAS, "AlignStack::%s(%d): seqnum %zu m_seqnum %zu\n", __func__, __LINE__, seqnum, m_seqnum);
+
+ // Assign a seqnum if needed
+ if (seqnum == 0)
+ {
+ seqnum = m_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.
+ */
+
+ 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 = start->GetPrev();
+
+ while ( prev->IsPointerOperator()
+ || prev->Is(CT_TPAREN_OPEN))
+ {
+ prev = prev->GetPrev();
+ }
+
+ if (prev->IsNullChunk())
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): 'ref' chunk not found. Do not add.\n",
+ __func__, __LINE__);
+ return;
+ }
+ Chunk *ref = prev;
+
+ if (ref->IsNewline())
+ {
+ ref = ref->GetNext();
+ }
+ // Find the item that we are going to align.
+ Chunk *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()
+ || tmp_prev->IsMsRef())
+ {
+ ali = tmp_prev;
+ tmp_prev = ali->GetPrev();
+ }
+
+ if (tmp_prev->Is(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 (tmp_prev->IsAddress())
+ {
+ ali = tmp_prev;
+ tmp_prev = ali->GetPrev();
+ }
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%3d): 'ref' orig line %zu, orig col %zu, text '%s', level %zu, type %s\n",
+ __func__, __LINE__, ref->GetOrigLine(), ref->GetOrigCol(), ref->Text(), ref->GetLevel(), get_token_name(ref->GetType()));
+ LOG_FMT(LAS, "AlignStack::%s(%3d): 'ali' orig line %zu, orig col %zu, text '%s', level %zu, type %s\n",
+ __func__, __LINE__, ali->GetOrigLine(), ali->GetOrigCol(), ali->Text(), ali->GetLevel(), get_token_name(ali->GetType()));
+ 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->GetColumn();
+ Chunk *tmp = ref;
+ LOG_FMT(LAS, "AlignStack::%s(%3d): 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(%3d): 'next' orig line %zu, orig col %zu, text '%s', level %zu, type %s\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text(), next->GetLevel(), get_token_name(next->GetType()));
+ tmp_col += space_col_align(tmp, next);
+ LOG_FMT(LAS, "AlignStack::%s(%3d): 'next' column %zu, level %zu, tmp_col %zu\n",
+ __func__, __LINE__, next->GetColumn(), next->GetLevel(), tmp_col);
+
+ if (next->GetColumn() != tmp_col)
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%3d): call align_to_column\n", __func__, __LINE__);
+ align_to_column(next, tmp_col);
+ }
+ }
+ tmp = next;
+ }
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%3d): m_min_col %zu, m_max_col %zu, start_col %zu, m_thresh %zu, m_gap %zu\n",
+ __func__, __LINE__, m_min_col, m_max_col, start->GetColumn(), m_thresh, m_gap);
+
+ // Check threshold limits
+ if ( m_max_col == 0
+ || m_thresh == 0
+ || ( ((start->GetColumn() + m_gap) <= (m_thresh + (m_absolute_thresh ? m_min_col : m_max_col))) // don't use subtraction here to prevent underflow
+ && ( (start->GetColumn() + m_gap + m_thresh) >= m_max_col // change the expression to mind negative expression
+ || start->GetColumn() >= 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->GetColumn() - (ref->GetColumn() + ref->Len());
+ }
+ Chunk *tmp = ali;
+
+ if (tmp->Is(CT_TPAREN_OPEN))
+ {
+ tmp = tmp->GetNext();
+ }
+
+ if ( ( tmp->IsStar()
+ && m_star_style == SS_DANGLE)
+ || ( tmp->IsAddress()
+ && m_amp_style == SS_DANGLE)
+ || ( tmp->IsNullable()
+ && (m_star_style == SS_DANGLE))
+ || ( tmp->IsMsRef()
+ && m_star_style == SS_DANGLE)) // TODO: add m_msref_style
+ {
+ col_adj = start->GetColumn() - ali->GetColumn();
+ gap = start->GetColumn() - (ref->GetColumn() + ref->Len());
+ }
+ // See if this pushes out the max_col
+ const size_t endcol = ali->GetColumn() + col_adj
+ + (gap < m_gap ? m_gap - gap : 0);
+
+ ali->AlignData().col_adj = col_adj;
+ ali->AlignData().ref = ref;
+ ali->AlignData().start = start;
+ m_aligned.Push_Back(ali, seqnum);
+ m_last_added = 1;
+
+ // Issue #2278
+ if (ali->Is(CT_PTR_TYPE))
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%d): add [%s][%s]: 'ali' orig line %zu, column %zu, type %s, level %zu\n",
+ __func__, __LINE__, ali->Text(), start->Text(), ali->GetOrigLine(), ali->GetColumn(), get_token_name(ali->GetType()), ali->GetLevel());
+ }
+ else
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%3d): add [%s]: 'ali' orig line %zu, column %zu, type %s, level %zu\n",
+ __func__, __LINE__, ali->Text(), ali->GetOrigLine(), ali->GetColumn(), get_token_name(ali->GetType()), ali->GetLevel());
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%3d): 'ali' alignment col_adj %d, ref '%s', endcol %zu\n",
+ __func__, __LINE__, ali->GetAlignData().col_adj, ref->Text(), endcol);
+
+ if (m_min_col > endcol)
+ {
+ m_min_col = endcol;
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%3d): add aligned: seqnum %zu, m_nl_seqnum %zu, m_seqnum %zu\n",
+ __func__, __LINE__, seqnum, m_nl_seqnum, m_seqnum);
+ LOG_FMT(LAS, "AlignStack::%s(%3d): 'ali' orig line %zu, column %zu, m_min_col %zu, max_col old/new %zu/%zu\n",
+ __func__, __LINE__, ali->GetOrigLine(), ali->GetColumn(), m_min_col, m_max_col, endcol);
+
+ if (endcol > m_max_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())
+ {
+ LOG_FMT(LAS, "AlignStack::%s(%3d): ReAddSkipped()\n", __func__, __LINE__);
+ ReAddSkipped();
+ }
+ }
+ }
+ else
+ {
+ // The threshold check failed, so add it to the skipped l
+ 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->GetOrigLine(), start->GetColumn(), m_max_col, m_thresh);
+ }
+ LOG_FMT(LAS, "AlignStack::%s(%3d): end of add\n", __func__, __LINE__);
+ // produces much more log output. Use it only debugging purpose
+} // 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, empty\n", __LINE__);
+ return;
+ }
+ LOG_FMT(LAS, "AlignStack::Newlines(%d): cnt %zu\n", __LINE__, cnt);
+ m_seqnum += cnt;
+ LOG_FMT(LAS, "AlignStack::Newlines(%d): m_seqnum %zu, m_nl_seqnum %zu, m_span %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 %zu\n", __LINE__, cnt);
+ Flush();
+ }
+} // AlignStack::NewLines
+
+
+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, "AlignStack::%s(%d): min is %zu, max is %zu\n",
+ __func__, __LINE__, m_min_col, m_max_col);
+ }
+ else
+ {
+ return;
+ }
+
+ 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->GetLevel());
+
+ if (temp->IsNotNullChunk())
+ {
+ if (pc->GetOrigLine() == temp->GetOrigLine())
+ {
+ // 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
+ 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', orig line is %zu, orig col is %zu, alignment col_adj is %d\n",
+ __func__, __LINE__, idx, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol(), pc->GetAlignData().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->GetAlignData().ref)
+ {
+ gap = pc->GetColumn() - (pc->GetAlignData().ref->GetColumn() + pc->GetAlignData().ref->Len());
+ }
+
+ if (m_star_style == SS_DANGLE)
+ {
+ Chunk *tmp = (pc->Is(CT_TPAREN_OPEN)) ? pc->GetNext() : pc;
+
+ if (tmp->IsPointerOperator())
+ {
+ col_adj = pc->GetAlignData().start->GetColumn() - pc->GetColumn();
+ gap = pc->GetAlignData().start->GetColumn() - (pc->GetAlignData().ref->GetColumn() + pc->GetAlignData().ref->Len());
+ }
+ }
+
+ if (m_right_align)
+ {
+ // Adjust the width for signed numbers
+ if (pc->GetAlignData().start->IsNotNullChunk())
+ {
+ size_t start_len = pc->GetAlignData().start->Len();
+
+ if (pc->GetAlignData().start->GetType() == CT_NEG)
+ {
+ Chunk *next = pc->GetAlignData().start->GetNext();
+
+ if (next->Is(CT_NUMBER))
+ {
+ start_len += next->Len();
+ }
+ }
+ col_adj += start_len;
+ }
+ }
+ pc->AlignData().col_adj = col_adj;
+
+ // See if this pushes out the max_col
+ const size_t endcol = pc->GetColumn() + 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): 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', orig line is %zu, orig col is %zu, alignment col_adj is %d\n",
+ __func__, __LINE__, idx, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol(), pc->GetAlignData().col_adj);
+ }
+
+ const ChunkStack::Entry *ce = nullptr;
+
+ 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->GetAlignData().col_adj;
+
+ if (idx == 0)
+ {
+ if ( m_skip_first
+ && pc->GetColumn() != 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->GetOrigLine(), pc->GetOrigCol());
+ m_skip_first = false;
+ m_aligned.Pop_Front();
+ Flush();
+ m_skip_first = true;
+ return;
+ }
+ pc->SetFlagBits(PCF_ALIGN_START);
+
+ pc->AlignData().right_align = m_right_align;
+ pc->AlignData().amp_style = m_amp_style;
+ pc->AlignData().star_style = m_star_style;
+ }
+ pc->AlignData().gap = m_gap;
+ pc->AlignData().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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), tmp_col, pc->GetAlignData().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();
+} // AlignStack::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();
+} // AlignStack::End
+
+
+size_t AlignStack::Len()
+{
+ // WITH_STACKID_DEBUG;
+ return(m_aligned.Len());
+} // AlignStack::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 (pc->Is(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->GetNext()->Text(), pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), pc->GetLevel(), pc->GetBraceLevel());
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), pc->GetLevel(), pc->GetBraceLevel());
+ }
+ }
+ }
+} // AlignStack::Debug
+
+
+const char *AlignStack::get_StarStyle_name(StarStyle star_style)
+{
+ // WITH_STACKID_DEBUG;
+ 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("?????");
+} // AlignStack::get_StarStyle_name
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_stack.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_stack.h
new file mode 100644
index 00000000..6d079fe5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 purposes 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 debugging 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.78.0/src/align_struct_initializers.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_struct_initializers.cpp
new file mode 100644
index 00000000..ca032bc3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if ( prev->Is(CT_ASSIGN)
+ && ( pc->Is(CT_BRACE_OPEN)
+ || ( language_is_set(LANG_D)
+ && pc->Is(CT_SQUARE_OPEN))))
+ {
+ align_init_brace(pc);
+ }
+ pc = pc->GetNextType(CT_BRACE_OPEN);
+ }
+} // align_struct_initializers
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_struct_initializers.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_struct_initializers.h
new file mode 100644
index 00000000..7310d072
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_STRUCT_INITIALIZERS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tab_column.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tab_column.cpp
new file mode 100644
index 00000000..8d91b0ff
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_tab_column.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tab_column.h
new file mode 100644
index 00000000..9e57baa0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tools.cpp
new file mode 100644
index 00000000..e90afd2f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tools.cpp
@@ -0,0 +1,192 @@
+/**
+ * @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 (sq_open->Is(CT_SQUARE_OPEN))
+ {
+ Chunk *tmp = sq_open->GetClosingParen()->GetNextNc();
+
+ if (tmp->Is(CT_ASSIGN))
+ {
+ return(tmp->GetNextNc());
+ }
+ }
+ return(Chunk::NullChunkPtr);
+} // skip_c99_array
+
+
+Chunk *scan_ib_line(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *prev_match = Chunk::NullChunkPtr;
+ size_t idx = 0;
+
+ // Skip past C99 "[xx] =" stuff
+ Chunk *tmp = skip_c99_array(start);
+
+ if (tmp->IsNotNullChunk())
+ {
+ start->SetParentType(CT_TSQUARE);
+ start = tmp;
+ cpd.al_c99_array = true;
+ }
+ Chunk *pc = start;
+
+ if (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LSIB, "%s(%d): start: orig line is %zu, orig col is %zu, column is %zu, type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetColumn(), get_token_name(pc->GetType()));
+ }
+ else
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+
+ while ( pc->IsNotNullChunk()
+ && !pc->IsNewline()
+ && pc->GetLevel() >= start->GetLevel())
+ {
+ //LOG_FMT(LSIB, "%s: '%s' col %d/%d line %zu\n", __func__,
+ // pc->Text(), pc->GetColumn(), pc->GetOrigCol(), pc->GetOrigLine());
+
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNullChunk()
+ || next->IsComment())
+ {
+ // do nothing
+ }
+ else if ( pc->Is(CT_ASSIGN)
+ || pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(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->GetColumn() is %2.1zu, Text() '%s', token_width is %zu, type is %s\n",
+ __func__, __LINE__, idx, pc->GetColumn(), pc->Text(), token_width, get_token_name(pc->GetType()));
+ cpd.al[cpd.al_cnt].type = pc->GetType();
+ cpd.al[cpd.al_cnt].col = pc->GetColumn();
+ cpd.al[cpd.al_cnt].len = token_width;
+ cpd.al[cpd.al_cnt].ref = pc; // Issue #3786
+ 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->GetOrigLine(), pc->GetOrigCol());
+ 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->GetType())
+ {
+ 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->GetOrigLine(), pc->GetColumn(), token_width, get_token_name(pc->GetType()));
+
+ // Shift out based on column
+ if (prev_match->IsNullChunk())
+ {
+ if (pc->GetColumn() > cpd.al[idx].col)
+ {
+ LOG_FMT(LSIB, "%s(%d): [ pc column (%zu) > cpd.al[%zu].col(%zu) ] \n",
+ __func__, __LINE__, pc->GetColumn(), idx, cpd.al[idx].col);
+
+ ib_shift_out(idx, pc->GetColumn() - cpd.al[idx].col);
+ cpd.al[idx].col = pc->GetColumn();
+ }
+ }
+ else if (idx > 0)
+ {
+ LOG_FMT(LSIB, "%s(%d): prev_match '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, prev_match->Text(), prev_match->GetOrigLine(), prev_match->GetOrigCol());
+ int min_col_diff = pc->GetColumn() - prev_match->GetColumn();
+ 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->GetOrigLine());
+ 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)
+ {
+ bool is_empty = false; // Issue #3786
+ Chunk *tmp = cpd.al[idx].ref;
+
+ if (tmp->Is(CT_BRACE_CLOSE))
+ {
+ Chunk *pre = tmp->GetPrev();
+
+ if (pre->Is(CT_COMMA))
+ {
+ is_empty = true;
+ }
+ }
+
+ if (!is_empty)
+ {
+ cpd.al[idx].col += num;
+ }
+ idx++;
+ }
+} // ib_shift_out
+
+
+Chunk *step_back_over_member(Chunk *pc)
+{
+ Chunk *tmp = pc->GetPrevNcNnl();
+
+ // Skip over any class stuff: bool CFoo::bar()
+ while (tmp->Is(CT_DC_MEMBER))
+ {
+ pc = tmp->GetPrevNcNnl();
+ tmp = pc->GetPrevNcNnl();
+ }
+ return(pc);
+} // step_back_over_member
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_tools.h
new file mode 100644
index 00000000..897e2da2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 Chunk::NullChunkPtr 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);
+
+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.78.0/src/align_trailing_comments.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_trailing_comments.cpp
new file mode 100644
index 00000000..86b875eb
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_trailing_comments.cpp
@@ -0,0 +1,235 @@
+/**
+ * @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())->IsNotNullChunk())
+ {
+ align_to_column(pc, col);
+ pc->SetFlagBits(PCF_WAS_ALIGNED);
+
+ LOG_FMT(sev, "%s(%d): indented [%s] on line %zu to %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetColumn());
+ }
+ }
+ 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->GetBraceLevel();
+ 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->GetOrigLine());
+
+ // Find the max column
+ log_rule_B("align_right_cmt_span");
+
+ while ( pc->IsNotNullChunk()
+ && (nl_count < options::align_right_cmt_span()))
+ {
+ if ( pc->TestFlags(PCF_RIGHT_COMMENT)
+ && pc->GetColumn() > 1)
+ {
+ if ( same_level
+ && pc->GetBraceLevel() != 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->GetOrigLine(), min_col, pc->GetColumn(), pc->Len(),
+ get_token_name(pc->GetType()));
+
+ if ( min_orig == 0
+ || min_orig > pc->GetColumn())
+ {
+ min_orig = pc->GetColumn();
+ }
+ align_add(cs, pc, min_col); // (intended_col < col));
+ nl_count = 0;
+ }
+ }
+
+ if (pc->IsNewline())
+ {
+ nl_count += pc->GetNlCount();
+ }
+ 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->IsNotNullChunk()
+ && ((prev = cmt->GetPrev())->IsNotNullChunk()))
+ {
+ if ( prev->Is(CT_PP_ENDIF)
+ || prev->Is(CT_PP_ELSE)
+ || prev->Is(CT_ELSE)
+ || prev->Is(CT_BRACE_CLOSE))
+ {
+ // TODO: make the magic 3 configurable
+ if ((cmt->GetColumn() - (prev->GetColumn() + prev->Len())) < 3)
+ {
+ cmt_type = (prev->Is(CT_PP_ENDIF)) ? comment_align_e::ENDIF : comment_align_e::BRACE;
+ }
+ }
+ }
+ return(cmt_type);
+} // get_comment_align_type
+
+
+void align_right_comments()
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( pc->Is(CT_COMMENT)
+ || pc->Is(CT_COMMENT_CPP)
+ || pc->Is(CT_COMMENT_MULTI))
+ {
+ if (pc->GetParentType() == CT_COMMENT_END)
+ {
+ log_rule_B("align_right_cmt_gap");
+
+ if (pc->GetOrigPrevSp() < options::align_right_cmt_gap())
+ {
+ LOG_FMT(LALTC, "NOT changing END comment on line %zu (%zu < %u)\n",
+ pc->GetOrigLine(), pc->GetOrigPrevSp(),
+ options::align_right_cmt_gap());
+ }
+ else
+ {
+ LOG_FMT(LALTC, "Changing END comment on line %zu into a RIGHT-comment\n",
+ pc->GetOrigLine());
+ pc->SetFlagBits(PCF_RIGHT_COMMENT);
+ }
+ }
+
+ // Change certain WHOLE comments into RIGHT-alignable comments
+ if (pc->GetParentType() == CT_COMMENT_WHOLE)
+ {
+ log_rule_B("input_tab_size");
+ size_t max_col = pc->GetColumnIndent() + options::input_tab_size();
+
+ // If the comment is further right than the brace level...
+ if (pc->GetColumn() >= 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->GetOrigLine(), pc->GetColumn(), pc->GetColumnIndent(), max_col);
+
+ pc->SetFlagBits(PCF_RIGHT_COMMENT);
+ }
+ }
+ }
+ }
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->TestFlags(PCF_RIGHT_COMMENT))
+ {
+ pc = align_trailing_comments(pc);
+ }
+ else
+ {
+ pc = pc->GetNext();
+ }
+ }
+} // align_right_comments
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_trailing_comments.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_trailing_comments.h
new file mode 100644
index 00000000..4fec7b8b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* ALIGN_TRAILING_COMMENTS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_typedefs.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_typedefs.cpp
new file mode 100644
index 00000000..b97d9ddf
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 (pc->IsNewline())
+ {
+ as.NewLines(pc->GetNlCount());
+ c_typedef = Chunk::NullChunkPtr;
+ }
+ else if (c_typedef->IsNotNullChunk())
+ {
+ if (pc->TestFlags(PCF_ANCHOR))
+ {
+ as.Add(pc);
+ LOG_FMT(LALTD, "%s(%d): typedef @ %zu:%zu, tag '%s' @ %zu:%zu\n",
+ __func__, __LINE__, c_typedef->GetOrigLine(), c_typedef->GetOrigCol(),
+ pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+ c_typedef = Chunk::NullChunkPtr;
+ }
+ }
+ else
+ {
+ if (pc->Is(CT_TYPEDEF))
+ {
+ c_typedef = pc;
+ }
+ }
+ pc = pc->GetNext();
+ }
+ as.End();
+} // align_typedefs
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_typedefs.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_typedefs.h
new file mode 100644
index 00000000..2902d0d2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/align_var_def_brace.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_var_def_brace.cpp
new file mode 100644
index 00000000..93eb34b2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_var_def_brace.cpp
@@ -0,0 +1,362 @@
+/**
+ * @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(Chunk::NullChunkPtr);
+ }
+ Chunk *next;
+ size_t myspan = span;
+ size_t mythresh = 0;
+ size_t mygap = 0;
+
+ // Override the span, if this is a struct/union
+ if ( start->GetParentType() == CT_STRUCT
+ || start->GetParentType() == 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 (start->GetParentType() == 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 (prev->Is(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->GetType()), start->GetOrigLine());
+
+ Chunk *pc = start->GetNextType(CT_BRACE_CLOSE, start->GetLevel());
+ 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->GetType()), start->GetOrigLine());
+
+ 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();
+ LOG_FMT(LAVDB, "%s(%d): start->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, start->IsNewline() ? "Newline" : start->Text(), start->GetLevel(), start->GetBraceLevel());
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LAVDB, pc);
+
+ if ( pc->GetLevel() < start->GetLevel()
+ && pc->GetLevel() != 0
+ && !pc->IsPreproc())
+ {
+ LOG_FMT(LAVDB, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s, PRE is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()), pc->IsPreproc() ? "true" : "false");
+ break;
+ }
+
+ if (pc->IsComment())
+ {
+ if (pc->GetNlCount() > 0)
+ {
+ as.NewLines(pc->GetNlCount());
+ as_bc.NewLines(pc->GetNlCount());
+ as_at.NewLines(pc->GetNlCount());
+ as_br.NewLines(pc->GetNlCount());
+ }
+ pc = pc->GetNext();
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, pc->IsNewline() ? "Newline" : pc->Text(), pc->GetLevel(), pc->GetBraceLevel());
+ continue;
+ }
+
+ if ( fp_active
+ && !pc->TestFlags(PCF_IN_CLASS_BASE))
+ {
+ // WARNING: Duplicate from the align_func_proto()
+ log_rule_B("align_single_line_func");
+
+ if ( pc->Is(CT_FUNC_PROTO)
+ || ( pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+
+ Chunk *toadd;
+
+ log_rule_B("align_on_operator");
+
+ if ( pc->GetParentType() == 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 = (pc->Is(CT_FUNC_DEF))
+ && options::align_single_line_brace();
+ }
+ else if ( fp_look_bro
+ && pc->Is(CT_BRACE_OPEN)
+ && pc->TestFlags(PCF_ONE_LINER))
+ {
+ as_br.Add(pc);
+ fp_look_bro = false;
+ }
+ }
+
+ // process nested braces
+ if (pc->Is(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 (pc->Is(CT_BRACE_CLOSE))
+ {
+ pc = pc->GetNext();
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, pc->IsNewline() ? "Newline" : pc->Text(), pc->GetLevel(), pc->GetBraceLevel());
+ break;
+ }
+
+ if (pc->IsNewline())
+ {
+ fp_look_bro = false;
+ did_this_line = false;
+ as.NewLines(pc->GetNlCount());
+ as_bc.NewLines(pc->GetNlCount());
+ as_at.NewLines(pc->GetNlCount());
+ as_br.NewLines(pc->GetNlCount());
+
+ if (p_nl_count != nullptr)
+ {
+ *p_nl_count += pc->GetNlCount();
+ }
+ }
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, pc->IsNewline() ? "Newline" : pc->Text(), pc->GetLevel(), pc->GetBraceLevel());
+
+ if (!pc->IsNewline())
+ {
+ LOG_FMT(LAVDB, "%s(%d): pc orig line is %zu, orig col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+
+ if (pc->IsNot(CT_IGNORED))
+ {
+ LOG_FMT(LAVDB, " ");
+ log_pcf_flags(LAVDB, pc->GetFlags());
+ }
+ }
+
+ // don't align stuff inside parenthesis/squares/angles
+ if (pc->GetLevel() > pc->GetBraceLevel())
+ {
+ pc = pc->GetNext();
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, pc->IsNewline() ? "Newline" : pc->Text(), pc->GetLevel(), pc->GetBraceLevel());
+ continue;
+ }
+
+ // If this is a variable def, update the max_col
+ if ( !pc->TestFlags(PCF_IN_CLASS_BASE)
+ && pc->IsNot(CT_FUNC_CLASS_DEF)
+ && pc->IsNot(CT_FUNC_CLASS_PROTO)
+ && ((pc->GetFlags() & align_mask) == PCF_VAR_1ST)
+ && pc->IsNot(CT_FUNC_DEF) // Issue 1452
+ && ( (pc->GetLevel() == (start->GetLevel() + 1))
+ || pc->GetLevel() == 0)
+ && pc->GetPrev()->IsNot(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->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+
+ if (!did_this_line)
+ {
+ if ( start->GetParentType() == CT_STRUCT
+ && (as.m_star_style == AlignStack::SS_INCLUDE))
+ {
+ // we must look after the previous token
+ Chunk *prev_local = pc->GetPrev();
+
+ while ( prev_local->Is(CT_PTR_TYPE)
+ || prev_local->Is(CT_ADDR))
+ {
+ LOG_FMT(LAVDB, "%s(%d): prev_local '%s', prev_local->GetType() %s\n",
+ __func__, __LINE__, prev_local->Text(), get_token_name(prev_local->GetType()));
+ prev_local = prev_local->GetPrev();
+ }
+ pc = prev_local->GetNext();
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, pc->IsNewline() ? "Newline" : pc->Text(), pc->GetLevel(), pc->GetBraceLevel());
+ }
+ // we must look after the previous token
+ Chunk *prev_local = pc->GetPrev();
+
+ if (prev_local->IsNot(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->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+
+ as.Add(step_back_over_member(pc));
+ }
+ log_rule_B("align_var_def_colon");
+
+ if (options::align_var_def_colon())
+ {
+ next = pc->GetNextNc();
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, pc->IsNewline() ? "Newline" : pc->Text(), pc->GetLevel(), pc->GetBraceLevel());
+
+ if (next->Is(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 (next->Is(CT_ATTRIBUTE))
+ {
+ as_at.Add(next);
+ break;
+ }
+
+ if ( next->Is(CT_SEMICOLON)
+ || next->IsNewline())
+ {
+ break;
+ }
+ }
+ }
+ }
+ did_this_line = true;
+ }
+ else if (pc->Is(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();
+ LOG_FMT(LAVDB, "%s(%d): pc->Text() is '%s', level is %zu, brace level is %zu\n",
+ __func__, __LINE__, pc->IsNewline() ? "Newline" : pc->Text(), pc->GetLevel(), pc->GetBraceLevel());
+ }
+ 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.78.0/src/align_var_def_brace.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/align_var_def_brace.h
new file mode 100644
index 00000000..6d06adf9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/args.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/args.cpp
new file mode 100644
index 00000000..a03bbe00
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/args.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/args.h
new file mode 100644
index 00000000..712fbd59
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/backup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/backup.cpp
new file mode 100644
index 00000000..93a19c6a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/backup.cpp
@@ -0,0 +1,164 @@
+/**
+ * @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);
+ exit(EX_SOFTWARE);
+ }
+ else
+ {
+ LOG_FMT(LERR, "fopen(%s) failed: %s (%d)\n",
+ newpath, strerror(errno), errno);
+ exit(EX_SOFTWARE);
+ }
+ 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);
+ exit(EX_SOFTWARE);
+ }
+
+ // 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.78.0/src/backup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/backup.h
new file mode 100644
index 00000000..0d385649
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/backup.h
@@ -0,0 +1,66 @@
+/**
+ * @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
+
+#include "base_types.h"
+#include <vector>
+
+#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.78.0/src/base_types.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/base_types.h
new file mode 100644
index 00000000..1e98b0ac
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/brace_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/brace_cleanup.cpp
new file mode 100644
index 00000000..565dae46
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/brace_cleanup.cpp
@@ -0,0 +1,1440 @@
+/**
+ * @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 "keywords.h"
+#include "lang_pawn.h"
+#include "parsing_frame_stack.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;
+
+
+struct BraceState
+{
+ ParsingFrameStack 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(ParsingFrame &frm, Chunk *pc, const BraceState &braceState);
+
+
+static size_t preproc_start(BraceState &braceState, ParsingFrame &frm, Chunk *pc);
+
+
+static void print_stack(log_sev_t logsev, const char *str, const ParsingFrame &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 ParsingFrame &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, ParsingFrame &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(ParsingFrame &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(ParsingFrame &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, ParsingFrame &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->GetType();
+
+ // If we are not in a define, check for #if, #else, #endif, etc
+ if (braceState.in_preproc != CT_PP_DEFINE)
+ {
+ int pp_indent = braceState.frames.check(frm, braceState.pp_level, pc);
+ return(pp_indent);
+ }
+ // else push the frame stack
+ braceState.frames.push(frm);
+
+ // a preproc body starts a new, blank frame
+ frm = ParsingFrame();
+ frm.SetParenLevel(1);
+ frm.SetBraceLevel(1);
+
+ // TODO: not sure about the next 3 lines
+ frm.push(Chunk::NullChunkPtr, __func__, __LINE__);
+ frm.top().SetOpenToken(CT_PP_DEFINE);
+
+ return(pp_level);
+}
+
+
+static void print_stack(log_sev_t logsev, const char *str,
+ const ParsingFrame &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).GetStage() != E_BraceStage::NONE)
+ {
+ LOG_FMT(logsev, " [%s - %u]", get_token_name(frm.at(idx).GetOpenToken()),
+ (unsigned int)frm.at(idx).GetStage());
+ }
+ else
+ {
+ LOG_FMT(logsev, " [%s]", get_token_name(frm.at(idx).GetOpenToken()));
+ }
+ }
+
+ log_fmt(logsev, "\n");
+}
+
+
+//TODO: This can be cleaned up and simplified - we can look both forward and backward!
+void brace_cleanup()
+{
+ LOG_FUNC_ENTRY();
+
+ BraceState braceState;
+ ParsingFrame frm;
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ // Check for leaving a #define body
+ if ( braceState.in_preproc != CT_NONE
+ && !pc->TestFlags(PCF_IN_PREPROC))
+ {
+ if (braceState.in_preproc == CT_PP_DEFINE)
+ {
+ // out of the #define body, restore the frame
+ size_t brace_level = frm.GetBraceLevel();
+
+ 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->GetOrigLine(), brace_level);
+ }
+ braceState.frames.pop(frm);
+ }
+ braceState.in_preproc = CT_NONE;
+ }
+ // Check for a preprocessor start
+ size_t pp_level;
+
+ if (pc->Is(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().GetOpenToken() == CT_VBRACE_OPEN
+ && pc->Is(CT_NEWLINE))
+ {
+ pc = pawn_check_vsemicolon(pc);
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+ }
+
+ // Issue #1813
+ if (pc->Is(CT_NAMESPACE))
+ {
+ mark_namespace(pc);
+ }
+ // Assume the level won't change
+ pc->SetLevel(frm.GetParenLevel());
+ pc->SetBraceLevel(frm.GetBraceLevel());
+ pc->SetPpLevel(pp_level);
+
+ /*
+ * #define bodies get the full formatting treatment
+ * Also need to pass in the initial '#' to close out any virtual braces.
+ */
+ if ( !pc->IsCommentOrNewline()
+ && !pc->Is(CT_ATTRIBUTE)
+ && !pc->Is(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, (pc->Is(CT_VBRACE_CLOSE)) ? "Virt-}\n" : pc->GetStr().c_str(), frm);
+ }
+ pc = pc->GetNext();
+ }
+} // brace_cleanup
+
+
+static bool maybe_while_of_do(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if ( prev->IsNullChunk()
+ || !prev->TestFlags(PCF_IN_PREPROC))
+ {
+ return(false);
+ }
+
+ // Find the chunk before the preprocessor
+ while ( prev->IsNullChunk()
+ && prev->TestFlags(PCF_IN_PREPROC))
+ {
+ prev = prev->GetPrevNcNnl();
+ }
+
+ if ( ( prev->Is(CT_VBRACE_CLOSE)
+ || prev->Is(CT_BRACE_CLOSE))
+ && prev->GetParentType() == 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 (m_parenStack 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 m_parenStack 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, ParsingFrame &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->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()),
+ frm.size() - 1, get_token_name(frm.top().GetOpenToken()),
+ get_brace_stage_name(frm.top().GetStage()));
+ log_pcf_flags(LTOK, pc->GetFlags());
+
+ // Mark statement starts
+ LOG_FMT(LTOK, "%s(%d): orig line is %zu, type is %s, Text() is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), get_token_name(pc->GetType()), pc->Text());
+ LOG_FMT(LTOK, "%s(%d): frame statement count is %zu, expression count is %zu\n",
+ __func__, __LINE__, frm.GetStmtCount(), frm.GetExprCount());
+
+ if ( ( frm.GetStmtCount() == 0
+ || frm.GetExprCount() == 0)
+ && !pc->IsSemicolon()
+ && pc->IsNot(CT_BRACE_CLOSE)
+ && pc->IsNot(CT_VBRACE_CLOSE)
+ && !pc->IsString(")")
+ && !pc->IsString("]"))
+ {
+ pc->SetFlagBits(PCF_EXPR_START | ((frm.GetStmtCount() == 0) ? PCF_STMT_START : PCF_NONE));
+ LOG_FMT(LSTMT, "%s(%d): orig line is %zu, 1.marked '%s' as %s, start statement count is %zu, expression count is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->Text(),
+ pc->TestFlags(PCF_STMT_START) ? "statement" : "expression", frm.GetStmtCount(),
+ frm.GetExprCount());
+ pc->TestFlags(PCF_STMT_START) ? log_ruleStart("start statement", pc) : log_ruleStart("start expression", pc);
+ }
+ frm.SetStmtCount(frm.GetStmtCount() + 1);
+ frm.SetExprCount(frm.GetExprCount() + 1);
+ LOG_FMT(LTOK, "%s(%d): frame statement count is %zu, expression count is %zu\n",
+ __func__, __LINE__, frm.GetStmtCount(), frm.GetExprCount());
+
+ if (frm.GetSParenCount() > 0)
+ {
+ pc->SetFlagBits(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).GetOpenToken() == CT_FOR)
+ {
+ pc->SetFlagBits(PCF_IN_FOR);
+ break;
+ }
+ }
+
+ // Mark the parent on semicolons in for() statements
+ if ( pc->Is(CT_SEMICOLON)
+ && frm.size() > 2
+ && frm.prev().GetOpenToken() == CT_FOR)
+ {
+ pc->SetParentType(CT_FOR);
+ }
+ }
+
+ // Check the progression of complex statements
+ if ( frm.top().GetStage() != E_BraceStage::NONE
+ && !pc->Is(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().GetOpenToken() == CT_VBRACE_OPEN)
+ {
+ if (pc->IsSemicolon())
+ {
+ braceState.consumed = true;
+ close_statement(frm, pc, braceState);
+ }
+ else if ( language_is_set(LANG_PAWN)
+ && pc->Is(CT_BRACE_CLOSE))
+ {
+ close_statement(frm, pc, braceState);
+ }
+ else if ( language_is_set(LANG_D)
+ && pc->Is(CT_BRACE_CLOSE))
+ {
+ close_statement(frm, pc, braceState);
+ }
+ }
+
+ // Handle close parenthesis, vbrace, brace, and square
+ if ( pc->Is(CT_PAREN_CLOSE)
+ || pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_VBRACE_CLOSE)
+ || pc->Is(CT_ANGLE_CLOSE)
+ || pc->Is(CT_MACRO_CLOSE)
+ || pc->Is(CT_SQUARE_CLOSE))
+ {
+ // Change CT_PAREN_CLOSE into CT_SPAREN_CLOSE or CT_FPAREN_CLOSE
+ if ( pc->Is(CT_PAREN_CLOSE)
+ && ( (frm.top().GetOpenToken() == CT_FPAREN_OPEN)
+ || (frm.top().GetOpenToken() == CT_SPAREN_OPEN)))
+ {
+ // TODO: fix enum hack
+ pc->SetType(static_cast<E_Token>(frm.top().GetOpenToken() + 1));
+
+ if (pc->Is(CT_SPAREN_CLOSE))
+ {
+ frm.SetSParenCount(frm.GetSParenCount() - 1);
+ pc->ResetFlagBits(PCF_IN_SPAREN);
+ }
+ }
+
+ // Make sure the open / close match
+ if (pc->IsNot((E_Token)(frm.top().GetOpenToken() + 1)))
+ {
+ if (pc->TestFlags(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ const ParenStackEntry &AA = frm.top(); // Issue #3055
+
+ if (AA.GetOpenToken() != CT_EOF)
+ {
+ LOG_FMT(LWARN, "%s(%d): (frm.top().type + 1) is %s\n",
+ __func__, __LINE__, get_token_name((E_Token)(frm.top().GetOpenToken() + 1)));
+ }
+
+ if ( frm.top().GetOpenToken() != CT_EOF
+ && frm.top().GetOpenToken() != 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->GetOrigLine(), pc->GetOrigCol(),
+ pc->Text(), get_token_name(frm.top().GetOpenChunk()->GetType()),
+ frm.top().GetOpenChunk()->GetOrigLine());
+ print_stack(LBCSPOP, "=Error ", frm);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ else
+ {
+ braceState.consumed = true;
+
+ // Copy the parent, update the parenthesis/brace levels
+ pc->SetParentType(frm.top().GetParent());
+ frm.SetParenLevel(frm.GetParenLevel() - 1);
+
+ if ( pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_VBRACE_CLOSE)
+ || pc->Is(CT_MACRO_CLOSE))
+ {
+ frm.SetBraceLevel(frm.GetBraceLevel() - 1);
+ LOG_FMT(LBCSPOP, "%s(%d): frame brace level decreased to %zu",
+ __func__, __LINE__, frm.GetBraceLevel());
+ log_pcf_flags(LBCSPOP, pc->GetFlags());
+ }
+ pc->SetLevel(frm.GetParenLevel());
+ pc->SetBraceLevel(frm.GetBraceLevel());
+
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-Close ", frm);
+
+ if ( frm.top().GetStage() == E_BraceStage::NONE
+ && ( pc->Is(CT_VBRACE_CLOSE)
+ || pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_SEMICOLON))
+ && frm.top().GetOpenChunk()->Is(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(Chunk::NullChunkPtr, __func__, __LINE__); // <- dummy frame for the function
+ frm.top().SetStage(E_BraceStage::BRACE2);
+ }
+
+ // See if we are in a complex statement
+ if (frm.top().GetStage() != E_BraceStage::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 already handled.
+ */
+ if (frm.top().GetStage() == E_BraceStage::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 (!tmp->IsSemicolon())
+ {
+ pawn_add_vsemi_after(pc);
+ }
+ }
+ }
+ else
+ {
+ // Complain if this ISN'T a semicolon, but close out WHILE_OF_DO anyway
+ if (pc->IsSemicolon())
+ {
+ braceState.consumed = true;
+ pc->SetParentType(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->GetOrigLine(),
+ get_token_name(pc->GetType()));
+ exit(EX_SOFTWARE);
+ }
+ handle_complex_close(frm, pc, braceState);
+ }
+ }
+ // Get the parent type for brace and parenthesis open
+ E_Token parentType = pc->GetParentType();
+
+ if ( pc->Is(CT_PAREN_OPEN)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_SPAREN_OPEN)
+ || pc->Is(CT_BRACE_OPEN))
+ {
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if (prev->IsNotNullChunk())
+ {
+ if ( pc->Is(CT_PAREN_OPEN)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_SPAREN_OPEN))
+ {
+ // Set the parent for parenthesis and change parenthesis type
+ if ( prev->Is(CT_IF)
+ || prev->Is(CT_CONSTEXPR)
+ || prev->Is(CT_ELSEIF)
+ || prev->Is(CT_WHILE)
+ || prev->Is(CT_WHILE_OF_DO)
+ || prev->Is(CT_DO)
+ || prev->Is(CT_FOR)
+ || prev->Is(CT_SWITCH)
+ || prev->Is(CT_CATCH)
+ || prev->Is(CT_SYNCHRONIZED)
+ || prev->Is(CT_D_VERSION)
+ || prev->Is(CT_D_VERSION_IF)
+ || prev->Is(CT_D_SCOPE)
+ || prev->Is(CT_D_SCOPE_IF))
+ {
+ pc->SetType(CT_SPAREN_OPEN);
+ parentType = frm.top().GetOpenToken();
+ frm.SetSParenCount(frm.GetSParenCount() + 1);
+ }
+ else if (prev->Is(CT_FUNCTION))
+ {
+ pc->SetType(CT_FPAREN_OPEN);
+ parentType = CT_FUNCTION;
+ }
+ // NS_ENUM and NS_OPTIONS are followed by a (type, name) pair
+ else if ( prev->Is(CT_ENUM)
+ && language_is_set(LANG_OC))
+ {
+ // Treat both as CT_ENUM since the syntax is identical
+ pc->SetType(CT_FPAREN_OPEN);
+ parentType = CT_ENUM;
+ }
+ else if (prev->Is(CT_DECLSPEC)) // Issue 1289
+ {
+ parentType = CT_DECLSPEC;
+ }
+ // else: no need to set parent
+ }
+ else // must be CT_BRACE_OPEN
+ {
+ // Set the parent for open braces
+ if (frm.top().GetStage() != E_BraceStage::NONE)
+ {
+ parentType = frm.top().GetOpenToken();
+ }
+ else if ( prev->Is(CT_ASSIGN)
+ && (prev->GetStr()[0] == '='))
+ {
+ parentType = CT_ASSIGN;
+ }
+ else if ( prev->Is(CT_RETURN)
+ && language_is_set(LANG_CPP))
+ {
+ parentType = CT_RETURN;
+ }
+ // Carry through CT_ENUM parent in NS_ENUM (type, name) {
+ // only to help the vim command }
+ else if ( prev->Is(CT_FPAREN_CLOSE)
+ && language_is_set(LANG_OC)
+ && prev->GetParentType() == CT_ENUM)
+ {
+ parentType = CT_ENUM;
+ }
+ else if (prev->Is(CT_FPAREN_CLOSE))
+ {
+ parentType = 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 ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_PAREN_OPEN)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_SPAREN_OPEN)
+ || pc->Is(CT_ANGLE_OPEN)
+ || pc->Is(CT_MACRO_OPEN)
+ || pc->Is(CT_SQUARE_OPEN))
+ {
+ frm.SetParenLevel(frm.GetParenLevel() + 1);
+
+ if ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_MACRO_OPEN))
+ {
+ // Issue #1813
+ bool single = false;
+
+ if (pc->GetParentType() == CT_NAMESPACE)
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): parent type is NAMESPACE\n",
+ __func__, __LINE__);
+ Chunk *tmp = frm.top().GetOpenChunk();
+
+ if (tmp->GetParentType() == CT_NAMESPACE)
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): tmp->GetParentType() 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ if (!single)
+ {
+ frm.SetBraceLevel(frm.GetBraceLevel() + 1);
+ LOG_FMT(LBCSPOP, "%s(%d): frame brace level increased to %zu\n",
+ __func__, __LINE__, frm.GetBraceLevel());
+ }
+ }
+ frm.push(pc, __func__, __LINE__);
+ frm.top().SetParent(parentType);
+ pc->SetParentType(parentType);
+ }
+ // Issue #2281
+
+ if ( pc->Is(CT_BRACE_OPEN)
+ && pc->GetParentType() == 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).GetOpenChunk();
+
+ if (saved->IsNotNullChunk())
+ {
+ // set parent member
+ pc->SetParent(saved);
+ }
+ }
+
+ if ( pc->Is(CT_CASE)
+ || pc->Is(CT_DEFAULT))
+ {
+ Chunk *prev = pc->GetPrevNcNnl(); // Issue #3176
+
+ if ( pc->Is(CT_CASE)
+ || ( pc->Is(CT_DEFAULT)
+ && prev->IsNot(CT_ASSIGN)))
+ {
+ // it is a CT_DEFAULT from a switch
+ LOG_FMT(LBCSPOP, "%s(%d): pc orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ pc->SetParentType(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).GetOpenChunk();
+
+ if (saved->IsNotNullChunk())
+ {
+ // set parent member
+ pc->SetParent(saved);
+ }
+ }
+ }
+
+ if (pc->Is(CT_BREAK))
+ {
+ LOG_FMT(LBCSPOP, "%s(%d): pc orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ size_t idx = frm.size();
+ LOG_FMT(LBCSPOP, "%s(%d): idx is %zu\n",
+ __func__, __LINE__, idx);
+ Chunk *saved = frm.at(idx - 2).GetOpenChunk();
+
+ if (saved->IsNotNullChunk())
+ {
+ // set parent member
+ pc->SetParent(saved);
+ }
+ }
+ const pattern_class_e patcls = get_token_pattern_class(pc->GetType());
+
+ /*
+ * 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__, (pc->Is(CT_DO) ? E_BraceStage::BRACE_DO
+ : E_BraceStage::BRACE2));
+ // "+ComplexBraced"
+ }
+ else if (patcls == pattern_class_e::PBRACED)
+ {
+ E_BraceStage bs = E_BraceStage::PAREN1;
+
+ if ( pc->Is(CT_WHILE)
+ && maybe_while_of_do(pc))
+ {
+ pc->SetType(CT_WHILE_OF_DO);
+ bs = E_BraceStage::WOD_PAREN;
+ }
+ frm.push(pc, __func__, __LINE__, bs);
+ // "+ComplexParenBraced"
+ }
+ else if (patcls == pattern_class_e::OPBRACED)
+ {
+ frm.push(pc, __func__, __LINE__, E_BraceStage::OP_PAREN1);
+ // "+ComplexOpParenBraced");
+ }
+ else if (patcls == pattern_class_e::ELSE)
+ {
+ frm.push(pc, __func__, __LINE__, E_BraceStage::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 ( pc->Is(CT_SQUARE_OPEN)
+ || ( pc->Is(CT_BRACE_OPEN)
+ && pc->GetParentType() != CT_ASSIGN)
+ || pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_VBRACE_CLOSE)
+ || ( pc->Is(CT_SPAREN_OPEN)
+ && pc->GetParentType() == CT_FOR)
+ || pc->Is(CT_COLON)
+ || pc->Is(CT_OC_END)
+ || ( pc->IsSemicolon()
+ && frm.top().GetOpenToken() != CT_PAREN_OPEN
+ && frm.top().GetOpenToken() != CT_FPAREN_OPEN
+ && frm.top().GetOpenToken() != CT_SPAREN_OPEN)
+ || pc->Is(CT_MACRO)) // Issue #2742
+ {
+ LOG_FMT(LSTMT, "%s(%d): orig line is %zu, reset1 stmt on '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->Text());
+ frm.SetStmtCount(0);
+ frm.SetExprCount(0);
+ LOG_FMT(LTOK, "%s(%d): frame statement count is %zu, expression count is %zu\n",
+ __func__, __LINE__, frm.GetStmtCount(), frm.GetExprCount());
+ }
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if ( pc->Is(CT_ARITH)
+ || pc->Is(CT_SHIFT)
+ || pc->Is(CT_ASSIGN)
+ || pc->Is(CT_CASE)
+ || pc->Is(CT_COMPARE)
+ || ( pc->Is(CT_STAR)
+ && tmp->IsNot(CT_STAR))
+ || pc->Is(CT_BOOL)
+ || pc->Is(CT_MINUS)
+ || pc->Is(CT_PLUS)
+ || pc->Is(CT_CARET)
+ || pc->Is(CT_ANGLE_OPEN)
+ || pc->Is(CT_ANGLE_CLOSE)
+ || pc->Is(CT_RETURN)
+ || pc->Is(CT_THROW)
+ || pc->Is(CT_GOTO)
+ || pc->Is(CT_CONTINUE)
+ || pc->Is(CT_PAREN_OPEN)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_SPAREN_OPEN)
+ || pc->Is(CT_BRACE_OPEN)
+ || pc->IsSemicolon()
+ || pc->Is(CT_COMMA)
+ || pc->Is(CT_NOT)
+ || pc->Is(CT_INV)
+ || pc->Is(CT_COLON)
+ || pc->Is(CT_QUESTION))
+ {
+ frm.SetExprCount(0);
+ LOG_FMT(LSTMT, "%s(%d): orig line is %zu, orig col is %zu, reset expr on '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ }
+} // parse_cleanup
+
+
+static bool check_complex_statements(ParsingFrame &frm, Chunk *pc, const BraceState &braceState)
+{
+ LOG_FUNC_ENTRY();
+
+ E_BraceStage atest = frm.top().GetStage();
+
+ 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().GetStage() == E_BraceStage::OP_PAREN1)
+ {
+ frm.top().SetStage(pc->IsNot(CT_PAREN_OPEN)
+ ? E_BraceStage::BRACE2
+ : E_BraceStage::PAREN1);
+ LOG_FMT(LBCSPOP, "%s(%d): frm.top().stage is now %s\n",
+ __func__, __LINE__, get_brace_stage_name(frm.top().GetStage()));
+ }
+
+ // Check for CT_ELSE after CT_IF
+ while (frm.top().GetStage() == E_BraceStage::ELSE)
+ {
+ if (pc->Is(CT_ELSE))
+ {
+ // Replace CT_IF with CT_ELSE on the stack & we are done
+ frm.top().SetOpenToken(CT_ELSE);
+ frm.top().SetStage(E_BraceStage::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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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().GetStage() == E_BraceStage::ELSEIF)
+ {
+ log_rule_B("indent_else_if");
+
+ if ( pc->Is(CT_IF)
+ && ( !options::indent_else_if()
+ || !pc->GetPrevNc()->IsNewline()))
+ {
+ // Replace CT_ELSE with CT_IF
+ pc->SetType(CT_ELSEIF);
+ frm.top().SetOpenToken(CT_ELSEIF);
+ frm.top().SetStage(E_BraceStage::PAREN1);
+ return(true);
+ }
+ // Jump to the 'expecting brace' stage
+ frm.top().SetStage(E_BraceStage::BRACE2);
+ }
+
+ // Check for CT_CATCH or CT_FINALLY after CT_TRY or CT_CATCH
+ while (frm.top().GetStage() == E_BraceStage::CATCH)
+ {
+ if ( pc->Is(CT_CATCH)
+ || pc->Is(CT_FINALLY))
+ {
+ // Replace CT_TRY with CT_CATCH or CT_FINALLY on the stack & we are done
+ frm.top().SetOpenToken(pc->GetType());
+
+ if (language_is_set(LANG_CS))
+ {
+ frm.top().SetStage((pc->Is(CT_CATCH)) ? E_BraceStage::CATCH_WHEN : E_BraceStage::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().SetStage((pc->Is(CT_CATCH)) ? E_BraceStage::PAREN1 : E_BraceStage::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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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().GetStage() == E_BraceStage::CATCH_WHEN)
+ {
+ if (pc->Is(CT_PAREN_OPEN)) // this is for the paren after "catch"
+ {
+ // Replace CT_PAREN_OPEN with CT_SPAREN_OPEN
+ pc->SetType(CT_SPAREN_OPEN);
+ frm.top().SetOpenToken(pc->GetType());
+ frm.top().SetStage(E_BraceStage::PAREN1);
+
+ return(false);
+ }
+
+ if (pc->Is(CT_WHEN))
+ {
+ frm.top().SetOpenToken(pc->GetType());
+ frm.top().SetStage(E_BraceStage::OP_PAREN1);
+
+ return(true);
+ }
+
+ if (pc->Is(CT_BRACE_OPEN))
+ {
+ frm.top().SetStage(E_BraceStage::BRACE2);
+
+ return(false);
+ }
+ }
+
+ // Check for CT_WHILE after the CT_DO
+ if (frm.top().GetStage() == E_BraceStage::WHILE)
+ {
+ if (pc->Is(CT_WHILE))
+ {
+ pc->SetType(CT_WHILE_OF_DO);
+ frm.top().SetOpenToken(CT_WHILE_OF_DO);
+ frm.top().SetStage(E_BraceStage::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->GetOrigLine(),
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-Error ", frm);
+ exit(EX_SOFTWARE);
+ }
+ // Insert a CT_VBRACE_OPEN, if needed
+ // but not in a preprocessor
+ atest = frm.top().GetStage();
+
+ if ( pc->IsNot(CT_BRACE_OPEN)
+ && !pc->TestFlags(PCF_IN_PREPROC)
+ && ( (frm.top().GetStage() == E_BraceStage::BRACE2)
+ || (frm.top().GetStage() == E_BraceStage::BRACE_DO)))
+ {
+ log_rule_B("indent_using_block");
+
+ if ( language_is_set(LANG_CS)
+ && pc->Is(CT_USING_STMT)
+ && (!options::indent_using_block()))
+ {
+ // don't indent the using block
+ }
+ else
+ {
+ const E_Token parentType = frm.top().GetOpenToken();
+
+ Chunk *vbrace = insert_vbrace_open_before(pc, frm);
+ vbrace->SetParentType(parentType);
+
+ frm.SetParenLevel(frm.GetParenLevel() + 1);
+ frm.SetBraceLevel(frm.GetBraceLevel() + 1);
+ LOG_FMT(LBCSPOP, "%s(%d): frame brace level increased to %zu\n",
+ __func__, __LINE__, frm.GetBraceLevel());
+ log_pcf_flags(LBCSPOP, pc->GetFlags());
+
+ frm.push(vbrace, __func__, __LINE__, E_BraceStage::NONE);
+ // "+VBrace");
+
+ frm.top().SetParent(parentType);
+
+ // update the level of pc
+ pc->SetLevel(frm.GetParenLevel());
+ pc->SetBraceLevel(frm.GetBraceLevel());
+
+ // Mark as a start of a statement
+ frm.SetStmtCount(0);
+ frm.SetExprCount(0);
+ LOG_FMT(LTOK, "%s(%d): frame statement count is %zu, expression count is %zu\n",
+ __func__, __LINE__, frm.GetStmtCount(), frm.GetExprCount());
+ pc->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ frm.SetStmtCount(1);
+ frm.SetExprCount(1);
+ LOG_FMT(LSTMT, "%s(%d): orig line is %zu, 2.marked '%s' as stmt start\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->Text());
+ }
+ }
+
+ // Check for "constexpr" after CT_IF or CT_ELSEIF
+ if ( frm.top().GetStage() == E_BraceStage::PAREN1
+ && ( frm.top().GetOpenToken() == CT_IF
+ || frm.top().GetOpenToken() == CT_ELSEIF)
+ && pc->Is(CT_CONSTEXPR))
+ {
+ return(false);
+ }
+
+ // Verify open parenthesis in complex statement
+ if ( pc->IsNot(CT_PAREN_OPEN)
+ && ( (frm.top().GetStage() == E_BraceStage::PAREN1)
+ || (frm.top().GetStage() == E_BraceStage::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->GetOrigLine(), pc->Text(),
+ get_token_name(frm.top().GetOpenToken()));
+
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-Error ", frm);
+ exit(EX_SOFTWARE);
+ }
+ return(false);
+} // check_complex_statements
+
+
+static bool handle_complex_close(ParsingFrame &frm, Chunk *pc, const BraceState &braceState)
+{
+ LOG_FUNC_ENTRY();
+
+ if (frm.top().GetStage() == E_BraceStage::PAREN1)
+ {
+ if (pc->GetNext()->GetType() == CT_WHEN)
+ {
+ frm.top().SetOpenToken(pc->GetType());
+ frm.top().SetStage(E_BraceStage::CATCH_WHEN);
+
+ return(true);
+ }
+ // PAREN1 always => BRACE2
+ frm.top().SetStage(E_BraceStage::BRACE2);
+ }
+ else if (frm.top().GetStage() == E_BraceStage::BRACE2)
+ {
+ // BRACE2: IF => ELSE, anything else => close
+ if ( (frm.top().GetOpenToken() == CT_IF)
+ || (frm.top().GetOpenToken() == CT_ELSEIF))
+ {
+ frm.top().SetStage(E_BraceStage::ELSE);
+
+ // If the next chunk isn't CT_ELSE, close the statement
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( next->IsNullChunk()
+ || next->IsNot(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-IF-HCS ", frm);
+
+ return(close_statement(frm, pc, braceState));
+ }
+ }
+ else if ( (frm.top().GetOpenToken() == CT_TRY)
+ || (frm.top().GetOpenToken() == CT_CATCH))
+ {
+ frm.top().SetStage(E_BraceStage::CATCH);
+
+ // If the next chunk isn't CT_CATCH or CT_FINALLY, close the statement
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( next->IsNot(CT_CATCH)
+ && next->IsNot(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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 E_BraceStage::BRACE2\n",
+ __func__, __LINE__, get_token_name(frm.top().GetOpenToken()));
+ LOG_FMT(LBCSPOP, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ print_stack(LBCSPOP, "-HCC B2 ", frm);
+
+ return(close_statement(frm, pc, braceState));
+ }
+ }
+ else if (frm.top().GetStage() == E_BraceStage::BRACE_DO)
+ {
+ frm.top().SetStage(E_BraceStage::WHILE);
+ }
+ else if (frm.top().GetStage() == E_BraceStage::WOD_PAREN)
+ {
+ LOG_FMT(LNOTE, "%s(%d): close_statement on %s E_BraceStage::WOD_PAREN\n",
+ __func__, __LINE__, get_token_name(frm.top().GetOpenToken()));
+ frm.top().SetStage(E_BraceStage::WOD_SEMI);
+ print_stack(LBCSPOP, "-HCC WoDP ", frm);
+ }
+ else if (frm.top().GetStage() == E_BraceStage::WOD_SEMI)
+ {
+ LOG_FMT(LNOTE, "%s(%d): close_statement on %s E_BraceStage::WOD_SEMI\n",
+ __func__, __LINE__, get_token_name(frm.top().GetOpenToken()));
+ LOG_FMT(LBCSPOP, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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->GetOrigLine(),
+ get_token_name(frm.top().GetOpenToken()),
+ (unsigned int)frm.top().GetStage());
+ exit(EX_SOFTWARE);
+ }
+ 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 (pc->Is(CT_USING))
+ {
+ is_using = true;
+ pns->SetParentType(CT_USING);
+ }
+ pc = pns->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ pc->SetParentType(CT_NAMESPACE);
+
+ if (pc->IsNot(CT_BRACE_OPEN))
+ {
+ if (pc->Is(CT_SEMICOLON))
+ {
+ if (is_using)
+ {
+ pc->SetParentType(CT_USING);
+ }
+ return;
+ }
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+ log_rule_B("indent_namespace_limit");
+
+ if ( (options::indent_namespace_limit() > 0)
+ && ((br_close = pc->GetClosingParen())->IsNotNullChunk()))
+ {
+ // br_close->GetOrigLine() is always >= pc->GetOrigLine();
+ size_t numberOfLines = br_close->GetOrigLine() - pc->GetOrigLine() - 1; // Issue #2345
+ LOG_FMT(LTOK, "%s(%d): br_close orig line is %zu, pc orig line is %zu\n",
+ __func__, __LINE__, br_close->GetOrigLine(), pc->GetOrigLine());
+ 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__);
+ pc->SetFlagBits(PCF_LONG_BLOCK);
+ br_close->SetFlagBits(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 ParsingFrame &frm)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk chunk;
+
+ chunk.SetParentType(frm.top().GetOpenToken());
+ chunk.SetOrigLine(pc->GetOrigLine());
+ chunk.SetLevel(frm.GetParenLevel());
+ chunk.SetPpLevel(frm.GetPpLevel());
+ chunk.SetBraceLevel(frm.GetBraceLevel());
+ chunk.SetFlags(pc->GetFlags() & PCF_COPY_FLAGS);
+ chunk.Str() = "";
+
+ if (after)
+ {
+ chunk.SetOrigCol(pc->GetOrigCol());
+ chunk.SetType(CT_VBRACE_CLOSE);
+ return(chunk.CopyAndAddAfter(pc));
+ }
+ Chunk *ref = pc->GetPrev();
+
+ if (ref->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+
+ if (!ref->TestFlags(PCF_IN_PREPROC))
+ {
+ chunk.ResetFlagBits(PCF_IN_PREPROC);
+ }
+ bool ref_is_comment = ref->IsComment(); // Issue #3351
+
+ while (ref->IsCommentOrNewline())
+ {
+ ref->SetLevel(ref->GetLevel() + 1);
+ ref->SetBraceLevel(ref->GetBraceLevel() + 1);
+ ref = ref->GetPrev();
+ }
+
+ if (ref->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+
+ // Don't back into a preprocessor
+ if ( !pc->TestFlags(PCF_IN_PREPROC)
+ && ref->TestFlags(PCF_IN_PREPROC))
+ {
+ if (ref->Is(CT_PREPROC_BODY))
+ {
+ while ( ref->IsNotNullChunk()
+ && ref->TestFlags(PCF_IN_PREPROC))
+ {
+ ref = ref->GetPrev();
+ }
+ }
+ else
+ {
+ ref = ref->GetNext();
+
+ if (ref->Is(CT_COMMENT)) // Issue #3034
+ {
+ ref = ref->GetNextNc();
+ }
+ }
+ }
+
+ if (ref_is_comment) // Issue #3351
+ {
+ ref = ref->GetNext();
+ }
+
+ if (ref->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ chunk.SetOrigLine(ref->GetOrigLine());
+ chunk.SetOrigCol(ref->GetOrigCol());
+ chunk.SetColumn(ref->GetColumn() + ref->Len() + 1);
+ chunk.SetPpLevel(ref->GetPpLevel()); // Issue #3055
+ chunk.SetType(CT_VBRACE_OPEN);
+
+ return(chunk.CopyAndAddAfter(ref));
+} // insert_vbrace
+
+
+bool close_statement(ParsingFrame &frm, Chunk *pc, const BraceState &braceState)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->IsNullChunk())
+ {
+ throw invalid_argument(string(__func__) + ":" + to_string(__LINE__)
+ + "args cannot be null chunk");
+ }
+ LOG_FMT(LTOK, "%s(%d): orig line is %zu, type is %s, '%s' type is %s, stage is %u\n",
+ __func__, __LINE__, pc->GetOrigLine(),
+ get_token_name(pc->GetType()), pc->Text(),
+ get_token_name(frm.top().GetOpenToken()),
+ (unsigned int)frm.top().GetStage());
+
+ if (braceState.consumed)
+ {
+ frm.SetStmtCount(0);
+ frm.SetExprCount(0);
+ LOG_FMT(LSTMT, "%s(%d): orig line is %zu> reset2 stmt on '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), 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().GetOpenToken() == 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.SetParenLevel(frm.GetParenLevel() - 1);
+ frm.SetBraceLevel(frm.GetBraceLevel() - 1);
+ vbc = insert_vbrace_close_after(vbc, frm);
+ vbc->SetParentType(frm.top().GetParent());
+
+ LOG_FMT(LBCSPOP, "%s(%d): frame brace level decreased to %zu\n",
+ __func__, __LINE__, frm.GetBraceLevel());
+ log_pcf_flags(LBCSPOP, pc->GetFlags());
+ LOG_FMT(LBCSPOP, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+
+ // Update the token level
+ pc->SetLevel(frm.GetParenLevel());
+ pc->SetBraceLevel(frm.GetBraceLevel());
+
+ 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().GetStage() != E_BraceStage::NONE)
+ {
+ if (handle_complex_close(frm, vbc, braceState))
+ {
+ return(true);
+ }
+ }
+ return(false);
+} // close_statement
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/brace_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/brace_cleanup.h
new file mode 100644
index 00000000..10bc482a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 "parsing_frame.h"
+
+/**
+ * Scans through the whole list and does stuff.
+ * It has to do some tricks to parse preprocessors.
+ */
+void brace_cleanup();
+
+
+#endif /* BRACE_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/braces.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/braces.cpp
new file mode 100644
index 00000000..c4b4b666
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/braces.cpp
@@ -0,0 +1,1696 @@
+/**
+ * @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();
+
+
+//! Go backwards to honor brace newline removal limits
+static void examine_braces();
+
+
+/**
+ * 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();
+
+
+static void move_case_return();
+
+
+static void mod_case_brace();
+
+
+static void mod_full_brace_if_chain();
+
+
+/**
+ * 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(UncText &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 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->IsNot(CT_BRACE_OPEN)
+ && brace->IsNot(CT_BRACE_CLOSE))
+ || ( brace->GetParentType() != CT_IF
+ && brace->GetParentType() != CT_ELSEIF
+ && brace->GetParentType() != CT_FOR
+ && brace->GetParentType() != CT_USING_STMT
+ && brace->GetParentType() != CT_WHILE
+ && brace->GetParentType() != CT_FUNC_CLASS_DEF
+ && brace->GetParentType() != 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->GetLevel(), E_Scope::ALL);
+ auto paren_open = paren_close->GetOpeningParen();
+
+ 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()
+{
+ LOG_FUNC_ENTRY();
+ // Mark one-liners
+ // Issue #2232 put this at the beginning
+ Chunk *pc = Chunk::GetHead()->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( pc->IsNot(CT_BRACE_OPEN)
+ && pc->IsNot(CT_VBRACE_OPEN))
+ {
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+ Chunk *br_open = pc;
+ const E_Token brc_type = E_Token(pc->GetType() + 1); // corresponds to closing type
+ // Detect empty bodies
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (tmp->Is(brc_type))
+ {
+ br_open->SetFlagBits(PCF_EMPTY_BODY);
+ tmp->SetFlagBits(PCF_EMPTY_BODY);
+ }
+ // Scan for the brace close or a newline
+ tmp = br_open->GetNextNc();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if (tmp->IsNewline())
+ {
+ break;
+ }
+
+ if ( tmp->Is(brc_type)
+ && br_open->GetLevel() == tmp->GetLevel())
+ {
+ 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()
+{
+ 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);
+
+ if ( pc->Is(CT_BRACE_OPEN)
+ && !pc->TestFlags(PCF_IN_PREPROC)
+ && ( ( ( pc->GetParentType() == CT_IF
+ || pc->GetParentType() == CT_ELSE
+ || pc->GetParentType() == CT_ELSEIF)
+ && options::mod_full_brace_if() == IARF_REMOVE)
+ || ( pc->GetParentType() == CT_DO
+ && options::mod_full_brace_do() == IARF_REMOVE)
+ || ( pc->GetParentType() == CT_FOR
+ && options::mod_full_brace_for() == IARF_REMOVE)
+ || ( pc->GetParentType() == CT_USING_STMT
+ && options::mod_full_brace_using() == IARF_REMOVE)
+ || ( pc->GetParentType() == 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->GetOrigLine());
+
+ size_t nl_count = 0;
+
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ for (pc = vbopen->GetNextNc(E_Scope::PREPROC);
+ (pc->IsNotNullChunk() && pc->GetLevel() > vbopen->GetLevel());
+ pc = pc->GetNextNc(E_Scope::PREPROC))
+ {
+ if (pc->IsNewline())
+ {
+ nl_count += pc->GetNlCount();
+ }
+ }
+
+ if ( pc->IsNotNullChunk()
+ && nl_count > nl_max
+ && vbopen->GetPpLevel() == pc->GetPpLevel())
+ {
+ 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->GetOrigLine());
+
+ // Cannot remove braces inside a preprocessor
+ if (bopen->TestFlags(PCF_IN_PREPROC))
+ {
+ return(false);
+ }
+ Chunk *pc = bopen->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (pc->Is(CT_BRACE_CLOSE))
+ {
+ // Can't remove empty statement
+ return(false);
+ }
+ const size_t level = bopen->GetLevel() + 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->GetOrigLine(), pc->GetOrigCol());
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() >= level)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): test token '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+
+ if (pc->TestFlags(PCF_IN_PREPROC))
+ {
+ // Cannot remove braces that contain a preprocessor
+ return(false);
+ }
+
+ if (pc->IsNewline())
+ {
+ nl_count += pc->GetNlCount();
+
+ 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 (pc->Is(CT_BRACE_OPEN))
+ {
+ br_count++;
+ }
+ else if (pc->Is(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->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ br_count--;
+
+ if (pc->GetLevel() == level)
+ {
+ // mean a statement in a braces { stmt; }
+ // as a statement with a semicolon { stmt; };
+ ++semi_count;
+ hit_semi = true;
+ }
+ }
+ else if ( ( pc->Is(CT_IF)
+ || pc->Is(CT_ELSEIF))
+ && br_count == 0)
+ {
+ if_count++;
+ }
+
+ if (pc->GetLevel() == 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->GetOrigLine(), semi_count);
+
+ if (pc->Is(CT_ELSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ return(false);
+ }
+
+ if ( pc->IsSemicolon()
+ || pc->Is(CT_IF)
+ || pc->Is(CT_ELSEIF)
+ || pc->Is(CT_FOR)
+ || pc->Is(CT_DO)
+ || pc->Is(CT_WHILE)
+ || pc->Is(CT_USING_STMT)
+ || ( pc->Is(CT_BRACE_OPEN)
+ && prev->Is(CT_FPAREN_CLOSE)))
+ {
+ hit_semi |= pc->IsSemicolon();
+
+ if (++semi_count > 1)
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on %zu because of '%s' on line %zu\n",
+ __func__, __LINE__, bopen->GetOrigLine(), pc->Text(), pc->GetOrigLine());
+ 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 ( pc->Is(CT_BRACE_CLOSE)
+ && pc->GetParentType() == CT_IF)
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+ Chunk *tmp_prev = pc->GetPrevNcNnl(E_Scope::PREPROC);
+
+ if ( next->Is(CT_ELSE)
+ && tmp_prev->IsBraceClose()
+ && tmp_prev->GetParentType() == 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->GetType()), get_token_name(pc->GetParentType()),
+ pc->GetOrigLine());
+ 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->GetType()), pc->GetOrigLine(), if_count, semi_count);
+
+ return( pc->Is(CT_BRACE_CLOSE)
+ && pc->GetPpLevel() == bopen->GetPpLevel());
+} // can_remove_braces
+
+
+static void examine_brace(Chunk *bopen)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LBRDEL, "%s(%d): start on orig line %zu, bopen->GetLevel() is %zu\n",
+ __func__, __LINE__, bopen->GetOrigLine(), bopen->GetLevel());
+
+ const size_t level = bopen->GetLevel() + 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->GetLevel() >= level)
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig line is %zu, orig col is %zu, <Newline>\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ else
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ }
+
+ if (pc->TestFlags(PCF_IN_PREPROC))
+ {
+ // Cannot remove braces that contain a preprocessor
+ LOG_FMT(LBRDEL, "%s(%d): PREPROC\n", __func__, __LINE__);
+ return;
+ }
+
+ if (pc->IsNewline())
+ {
+ nl_count += pc->GetNlCount();
+
+ 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->GetLevel() is %zu, bopen->GetLevel() is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetLevel(), bopen->GetLevel());
+
+ if ( pc->Is(CT_BRACE_OPEN)
+ && pc->GetLevel() == bopen->GetLevel())
+ {
+ br_count++;
+ LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->GetLevel() is %zu, bopen->GetLevel() is %zu\n",
+ __func__, __LINE__, br_count, pc->GetLevel(), bopen->GetLevel());
+ }
+ else if ( pc->Is(CT_BRACE_CLOSE)
+ && pc->GetLevel() == bopen->GetLevel())
+ {
+ if (br_count == 0)
+ {
+ fprintf(stderr, "%s(%d): br_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ br_count--;
+ LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->GetLevel() is %zu, bopen->GetLevel() is %zu\n",
+ __func__, __LINE__, br_count, pc->GetLevel(), bopen->GetLevel());
+
+ if (br_count == 0)
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( next->IsNullChunk()
+ || next->IsNot(CT_BRACE_CLOSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): junk after close brace\n", __func__, __LINE__);
+ return;
+ }
+ }
+ }
+ else if ( ( pc->Is(CT_IF)
+ || pc->Is(CT_ELSEIF))
+ && br_count == 0)
+ {
+ if_count++;
+ }
+ LOG_FMT(LBRDEL, "%s(%d): pc->GetLevel() is %zu, level is %zu\n",
+ __func__, __LINE__, pc->GetLevel(), level);
+
+ if (pc->GetLevel() == 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->GetOrigLine(), semi_count);
+
+ if (pc->Is(CT_ELSE))
+ {
+ LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ return;
+ }
+
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LBRDEL, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', prev->Text '%s', prev->GetType() %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), prev->Text(), get_token_name(prev->GetType()));
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ }
+ LOG_FMT(LBRDEL, "%s(%d): for pc->Text() '%s', pc->GetLevel() is %zu, bopen->GetLevel() is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetLevel(), bopen->GetLevel());
+
+ if ( pc->IsSemicolon()
+ || pc->Is(CT_IF)
+ || pc->Is(CT_ELSEIF)
+ || pc->Is(CT_FOR)
+ || pc->Is(CT_DO)
+ || pc->Is(CT_WHILE)
+ || pc->Is(CT_SWITCH)
+ || pc->Is(CT_USING_STMT)
+ || ( pc->Is(CT_BRACE_OPEN)
+ && pc->GetLevel() == bopen->GetLevel())) // 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->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+ hit_semi |= pc->IsSemicolon();
+ 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->GetOrigLine(), pc->Text(), pc->GetOrigLine());
+ return;
+ }
+ }
+ }
+ }
+ prev = pc;
+ pc = pc->GetNext(); // Issue #1907
+ }
+
+ if (pc->IsNullChunk())
+ {
+ LOG_FMT(LBRDEL, "%s(%d): pc is a null chunk\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->GetType()), pc->GetOrigLine(), if_count, semi_count);
+
+ if (pc->Is(CT_BRACE_CLOSE))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNotNullChunk())
+ {
+ while (next->Is(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->GetOrigLine(), next->GetOrigCol(), get_token_name(next->GetType()));
+ }
+
+ if ( if_count > 0
+ && ( next->Is(CT_ELSE)
+ || next->Is(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->GetParentType() is %s\n",
+ __func__, __LINE__, get_token_name(bopen->GetParentType()));
+
+ if (bopen->GetParentType() == CT_ELSE)
+ {
+ Chunk *tmp_next = bopen->GetNextNcNnl();
+
+ if (tmp_next->Is(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->GetOrigLine(), pc->GetOrigLine());
+
+ Chunk::Delete(bopen);
+ Chunk::Delete(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->GetOrigLine(), pc->GetOrigLine());
+ 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->TestFlags(PCF_KEEP_BRACE))
+ {
+ return;
+ }
+ Chunk *tmp;
+
+ if (br->Is(CT_BRACE_OPEN))
+ {
+ br->SetType(CT_VBRACE_OPEN);
+ br->Str().clear();
+ tmp = br->GetPrev();
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+ }
+ else if (br->Is(CT_BRACE_CLOSE))
+ {
+ br->SetType(CT_VBRACE_CLOSE);
+ br->Str().clear();
+ tmp = br->GetNext();
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ if (tmp->IsNewline())
+ {
+ if (tmp->GetNlCount() > 1)
+ {
+ if (!br->TestFlags(PCF_ONE_LINER)) // Issue #2232
+ {
+ tmp->SetNlCount(tmp->GetNlCount() - 1);
+ LOG_FMT(LBRDEL, "%s(%d): tmp new line count is %zu\n",
+ __func__, __LINE__, tmp->GetNlCount());
+ }
+ }
+ else
+ {
+ // Issue #2219
+ // look for opening brace
+ Chunk *brace = Chunk::NullChunkPtr;
+
+ if (br->Is(CT_VBRACE_OPEN))
+ {
+ brace = tmp;
+ }
+ else if (br->Is(CT_VBRACE_CLOSE))
+ {
+ brace = br->GetOpeningParen();
+
+ if (brace->IsNullChunk())
+ {
+ brace = br->GetPrevType(CT_BRACE_OPEN, br->GetLevel());
+ }
+ }
+
+ if ( br->Is(CT_VBRACE_OPEN)
+ || ( br->Is(CT_VBRACE_CLOSE)
+ && brace->GetOrigLine() < tmp->GetOrigLine()))
+ {
+ if (tmp->SafeToDeleteNl())
+ {
+ Chunk::Delete(tmp);
+ }
+ }
+ }
+ }
+} // convert_brace
+
+
+static void convert_vbrace(Chunk *vbr)
+{
+ LOG_FUNC_ENTRY();
+
+ if (vbr->Is(CT_VBRACE_OPEN))
+ {
+ vbr->SetType(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 (tmp->Is(CT_PREPROC))
+ {
+ tmp = vbr->GetNext(E_Scope::PREPROC);
+ vbr->MoveAfter(tmp);
+ newline_add_after(vbr);
+ }
+ }
+ else if (vbr->Is(CT_VBRACE_CLOSE))
+ {
+ vbr->SetType(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, unless we're keeping a one-liner.
+ */
+ Chunk *tmp = vbr->GetNext();
+
+ if ( tmp->IsComment()
+ && ( !vbr->TestFlags(PCF_ONE_LINER)
+ || !options::nl_if_leave_one_liners()))
+ {
+ tmp = tmp->GetNext();
+
+ if (tmp->IsNewline())
+ {
+ vbr->MoveAfter(tmp);
+ newline_add_after(vbr);
+ }
+ }
+ }
+} // convert_vbrace
+
+
+static void convert_vbrace_to_brace()
+{
+ 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->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (pc->IsNot(CT_VBRACE_OPEN))
+ {
+ continue;
+ }
+ auto const in_preproc = pc->TestFlags(PCF_IN_PREPROC);
+
+ if ( ( ( pc->GetParentType() == CT_IF
+ || pc->GetParentType() == CT_ELSE
+ || pc->GetParentType() == CT_ELSEIF)
+ && (options::mod_full_brace_if() & IARF_ADD)
+ && !options::mod_full_brace_if_chain())
+ || ( pc->GetParentType() == CT_FOR
+ && (options::mod_full_brace_for() & IARF_ADD))
+ || ( pc->GetParentType() == CT_DO
+ && (options::mod_full_brace_do() & IARF_ADD))
+ || ( pc->GetParentType() == CT_WHILE
+ && (options::mod_full_brace_while() & IARF_ADD))
+ || ( pc->GetParentType() == CT_USING_STMT
+ && (options::mod_full_brace_using() & IARF_ADD))
+ || ( pc->GetParentType() == 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->TestFlags(PCF_IN_PREPROC))
+ {
+ // Can't leave a preprocessor
+ break;
+ }
+
+ if ( pc->GetBraceLevel() == tmp->GetBraceLevel()
+ && tmp->Is(CT_VBRACE_CLOSE)
+ && pc->GetParentType() == tmp->GetParentType()
+ && ((tmp->GetFlags() & PCF_IN_PREPROC) == (pc->GetFlags() & 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 UncText &cmt_text)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk new_cmt = *ref;
+
+ new_cmt.SetFlags(ref->GetFlags() & PCF_COPY_FLAGS);
+ new_cmt.SetType(cmt_type);
+ new_cmt.Str().clear();
+
+ if (cmt_type == CT_COMMENT_CPP)
+ {
+ new_cmt.Str().append("// ");
+ new_cmt.Str().append(cmt_text);
+ }
+ else
+ {
+ if (ref->Is(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.SetColumn(ref->GetColumn() + ref->Len() + 1);
+ new_cmt.SetOrigCol(new_cmt.GetColumn());
+
+ return(new_cmt.CopyAndAddAfter(ref));
+}
+
+
+static void append_tag_name(UncText &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 ( tmp->IsNot(CT_DC_MEMBER)
+ && tmp->IsNot(CT_MEMBER))
+ {
+ break;
+ }
+ tmp = tmp->GetPrevNcNnl();
+ pc = tmp;
+
+ if (!tmp->IsWord())
+ {
+ break;
+ }
+ }
+ txt += pc->GetStr();
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+
+ pc = pc->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( pc->IsNot(CT_DC_MEMBER)
+ && pc->IsNot(CT_MEMBER))
+ {
+ break;
+ }
+ txt += pc->GetStr();
+ LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
+ __func__, __LINE__, txt.c_str());
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNotNullChunk())
+ {
+ txt += pc->GetStr();
+ 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()
+{
+ 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 ( pc->Is(CT_FUNC_DEF)
+ || pc->Is(CT_OC_MSG_DECL))
+ {
+ fcn_pc = pc;
+ }
+ else if (pc->Is(CT_SWITCH))
+ {
+ // pointless, since it always has the text "switch"
+ sw_pc = pc;
+ }
+ else if (pc->Is(CT_NAMESPACE))
+ {
+ ns_pc = pc;
+ }
+ else if (pc->Is(CT_CLASS))
+ {
+ cl_pc = pc;
+ }
+
+ if ( pc->IsNot(CT_BRACE_OPEN)
+ || pc->TestFlags(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 (tmp->IsNewline())
+ {
+ nl_count += tmp->GetNlCount();
+ continue;
+ }
+
+ // handle only matching closing braces, skip other chunks
+ if ( tmp->GetLevel() != br_open->GetLevel()
+ || tmp->IsNot(CT_BRACE_CLOSE))
+ {
+ continue;
+ }
+ Chunk *br_close = tmp;
+
+ tmp = tmp->GetNext();
+
+ // check for a possible end semicolon
+ if (tmp->Is(CT_SEMICOLON))
+ {
+ // set br_close to the semi token,
+ // as br_close is used to add the comment 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()
+ && !tmp->IsNewline())
+ {
+ break;
+ }
+ size_t nl_min = 0;
+ Chunk *tag_pc = Chunk::NullChunkPtr;
+ UncText xstr;
+
+ if ( br_open->GetParentType() == CT_FUNC_DEF
+ || br_open->GetParentType() == 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 ( br_open->GetParentType() == CT_SWITCH
+ && sw_pc->IsNotNullChunk())
+ {
+ 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->GetStr();
+ LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
+ __func__, __LINE__, xstr.c_str());
+ }
+ else if ( br_open->GetParentType() == CT_NAMESPACE
+ && ns_pc->IsNotNullChunk())
+ {
+ 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->GetStr(); // 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 (tmp_next->IsNot(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 ( br_open->GetParentType() == CT_CLASS
+ && cl_pc->IsNotNullChunk()
+ && ( !language_is_set(LANG_CPP) // proceed if not C++
+ || br_close->Is(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->GetStr();
+ 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())
+ {
+ E_Token style;
+
+ if (options::mod_add_force_c_closebrace_comment())
+ {
+ // force the C comment style
+ style = CT_COMMENT;
+ }
+ else
+ {
+ // use the comment style that fits to the selected language
+ 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()
+{
+ LOG_FUNC_ENTRY();
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( pc->Is(CT_BREAK)
+ && prev->Is(CT_BRACE_CLOSE)
+ && prev->GetParentType() == CT_CASE
+ && pc->GetPrev()->IsNewline()
+ && prev->GetPrev()->IsNewline())
+ {
+ prev->SwapLines(pc);
+ }
+ prev = pc;
+ }
+}
+
+
+static void move_case_return()
+{
+ LOG_FUNC_ENTRY();
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( pc->Is(CT_RETURN)
+ && prev->Is(CT_BRACE_CLOSE)
+ && prev->GetParentType() == CT_CASE
+ && pc->GetPrev()->IsNewline()
+ && prev->GetPrev()->IsNewline())
+ {
+ // Find the end of the return statement
+ while (pc->IsNot(CT_SEMICOLON))
+ {
+ if ( pc->Is(CT_CASE)
+ || pc->Is(CT_BRACE_CLOSE))
+ {
+ // This may indicate a semicolon was missing in the code to format.
+ // Avoid moving the return statement to prevent potential unwanted errors.
+ 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->GetOrigLine(), pc->GetOrigLine());
+ Chunk *curr = prev->GetNextNcNnl();
+
+ while (curr != pc)
+ {
+ prev->SwapLines(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->GetOrigLine());
+
+ // Find the matching brace close
+ Chunk *next = br_open->GetNextNcNnl(E_Scope::PREPROC);
+ Chunk *br_close = br_open->GetNextType(CT_BRACE_CLOSE, br_open->GetLevel(), 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()
+ || ( pc->IsNot(CT_BREAK)
+ && pc->IsNot(CT_RETURN)
+ && pc->IsNot(CT_CASE)
+ && pc->IsNot(CT_GOTO)
+ && pc->IsNot(CT_BRACE_CLOSE)))
+ {
+ LOG_FMT(LMCB, "%s(%d): - after '%s'\n",
+ __func__, __LINE__, (pc->IsNullChunk()) ? "null chuck" : get_token_name(pc->GetType()));
+ 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->GetLevel() == (br_open->GetLevel() + 1)
+ && tmp_pc->TestFlags(PCF_VAR_DEF))
+ {
+ LOG_FMT(LMCB, "%s(%d): - vardef on line %zu: '%s'\n",
+ __func__, __LINE__, tmp_pc->GetOrigLine(), pc->Text());
+ return(next);
+ }
+ }
+
+ LOG_FMT(LMCB, "%s(%d): - removing braces on lines %zu and %zu\n",
+ __func__, __LINE__, br_open->GetOrigLine(), br_close->GetOrigLine());
+
+ for (Chunk *tmp_pc = br_open;
+ tmp_pc != br_close;
+ tmp_pc = tmp_pc->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ if (tmp_pc->GetBraceLevel() == 0)
+ {
+ fprintf(stderr, "%s(%d): brace level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp_pc->GetOrigLine(), tmp_pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ tmp_pc->SetBraceLevel(tmp_pc->GetBraceLevel() - 1);
+
+ if (tmp_pc->GetLevel() == 0)
+ {
+ fprintf(stderr, "%s(%d): tmp_pc->GetLevel() is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, tmp_pc->GetOrigLine(), tmp_pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ tmp_pc->SetLevel(tmp_pc->GetLevel() - 1);
+ }
+
+ next = br_open->GetPrev(E_Scope::PREPROC);
+
+ Chunk::Delete(br_open);
+ Chunk::Delete(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->GetOrigLine(), cl_colon->GetOrigCol());
+
+ 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->GetLevel());
+ // look for the parent
+ Chunk *swit = cas_->GetParent();
+ // look for the opening brace of the switch
+ Chunk *open = swit->GetNextType(CT_BRACE_OPEN, swit->GetLevel());
+ // look for the closing brace of the switch
+ Chunk *clos = open->GetClosingParen();
+
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->GetPpLevel());
+
+ if (pc->GetLevel() == cl_colon->GetLevel())
+ {
+ if (pc->Is(CT_CASE))
+ {
+ LOG_FMT(LMCB, "%s(%d): Text() is '%s', orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+ last = calculate_closing_brace_position(cl_colon, pc);
+ break;
+ }
+ }
+ else if (pc->GetLevel() == cl_colon->GetLevel() - 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->GetOrigLine(), pc->GetOrigCol());
+ // 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->GetOrigLine(), last->GetOrigCol());
+ 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->GetOrigLine(), last->GetOrigCol());
+ LOG_FMT(LMCB, "%s(%d): adding braces after '%s' on line %zu\n",
+ __func__, __LINE__, cl_colon->Text(), cl_colon->GetOrigLine());
+
+ Chunk chunk;
+
+ chunk.SetType(CT_BRACE_OPEN);
+ chunk.SetParentType(CT_CASE);
+ chunk.SetOrigLine(cl_colon->GetOrigLine());
+ chunk.SetOrigCol(cl_colon->GetOrigCol());
+ chunk.SetLevel(cl_colon->GetLevel());
+ chunk.SetPpLevel(cl_colon->GetPpLevel());
+ chunk.SetBraceLevel(cl_colon->GetBraceLevel());
+ chunk.SetFlags(pc->GetFlags() & PCF_COPY_FLAGS);
+ chunk.Str() = "{";
+ Chunk *br_open = chunk.CopyAndAddAfter(cl_colon);
+
+ chunk.SetType(CT_BRACE_CLOSE);
+ chunk.SetOrigLine(last->GetOrigLine());
+ chunk.SetOrigCol(last->GetOrigCol());
+ chunk.Str() = "}";
+ Chunk *br_close = chunk.CopyAndAddAfter(last);
+
+ for (pc = br_open->GetNext(E_Scope::PREPROC);
+ pc != br_close;
+ pc = pc->GetNext(E_Scope::PREPROC))
+ {
+ pc->SetLevel(pc->GetLevel() + 1);
+ pc->SetBraceLevel(pc->GetBraceLevel() + 1);
+ }
+
+ return(br_open);
+} // mod_case_brace_add
+
+
+static void mod_case_brace()
+{
+ 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->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
+ && pc->Is(CT_BRACE_OPEN)
+ && pc->GetParentType() == CT_CASE)
+ {
+ log_rule_B("mod_case_brace - add");
+ pc = mod_case_brace_remove(pc);
+ }
+ else if ( (options::mod_case_brace() & IARF_ADD)
+ && pc->Is(CT_CASE_COLON)
+ && next->IsNot(CT_BRACE_OPEN)
+ && next->IsNot(CT_BRACE_CLOSE)
+ && next->IsNot(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->GetOrigLine(), br_start->GetOrigCol());
+
+ vector<Chunk *> braces;
+
+ braces.reserve(16);
+
+ bool must_have_braces = false;
+ bool has_unbraced_block = false;
+
+ Chunk *pc = br_start;
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ if (pc->Is(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->GetOrigLine(), tmp ? "" : "not",
+ get_token_name(pc->GetType()));
+
+ 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->GetOrigLine(), tmp ? "should add" : "ignore",
+ get_token_name(pc->GetType()));
+
+ 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 = pc->GetClosingParen(E_Scope::PREPROC);
+
+ if (br_close->IsNullChunk())
+ {
+ break;
+ }
+ braces.push_back(br_close);
+
+ pc = br_close->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( pc->IsNullChunk()
+ || pc->IsNot(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 (pc->Is(CT_ELSEIF))
+ {
+ while ( pc->IsNot(CT_VBRACE_OPEN)
+ && pc->IsNot(CT_BRACE_OPEN))
+ {
+ pc = pc->GetNextNcNnl(E_Scope::PREPROC);
+ }
+ }
+
+ if (pc->IsNullChunk())
+ {
+ break;
+ }
+
+ if ( pc->IsNot(CT_BRACE_OPEN)
+ && pc->IsNot(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;
+
+ brace->SetFlagBits(PCF_KEEP_BRACE);
+
+ if (brace->IsVBrace())
+ {
+ LOG_FMT(LBRCH, "%s(%d): %zu",
+ __func__, __LINE__, brace->GetOrigLine());
+ convert_vbrace(brace);
+ }
+ else
+ {
+ LOG_FMT(LBRCH, "%s(%d): {%zu}",
+ __func__, __LINE__, brace->GetOrigLine());
+ }
+ }
+
+ 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 ( ( brace->Is(CT_BRACE_OPEN)
+ || brace->Is(CT_BRACE_CLOSE))
+ && (brace->GetParentType() != CT_BRACED_INIT_LIST)
+ && (multiline_block ? !paren_multiline_before_brace(brace) : true))
+ {
+ LOG_FMT(LBRCH, "%s(%d): brace orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, brace->GetOrigLine(), brace->GetOrigCol());
+ convert_brace(brace);
+ }
+ else
+ {
+ LOG_FMT(LBRCH, "%s(%d): brace orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, brace->GetOrigLine(), brace->GetOrigCol());
+ }
+ }
+ }
+} // process_if_chain
+
+
+static void mod_full_brace_if_chain()
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( pc->IsBraceOpen()
+ && pc->GetParentType() == CT_IF)
+ {
+ process_if_chain(pc);
+ }
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/braces.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/braces.h
new file mode 100644
index 00000000..2536aabf
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+/**
+ * See the preprocessor counterpart:
+ * add_long_preprocessor_conditional_block_comment
+ * in output.cpp
+ */
+void add_long_closebrace_comment();
+
+
+/**
+ * Adds a comment after the ref chunk
+ * Returns the added chunk or Chunk::NullChunkPtr
+ */
+Chunk *insert_comment_after(Chunk *ref, E_Token cmt_type, const UncText &cmt_text);
+
+
+#endif /* BRACES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/calculate_closing_brace_position.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/calculate_closing_brace_position.cpp
new file mode 100644
index 00000000..eda1c8e2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/calculate_closing_brace_position.cpp
@@ -0,0 +1,197 @@
+/**
+ * @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->GetOrigLine(), cl_colon->GetOrigCol(), cl_colon->GetLevel());
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+ // 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 (pc->Is(CT_BRACE_CLOSE))
+ {
+ check_level = pc->GetLevel() + 1;
+ }
+ else
+ {
+ check_level = pc->GetLevel();
+ }
+ 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->GetLevel() == check_level)
+ {
+ if (back->IsBraceClose())
+ {
+ // 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->GetOrigLine(), is_brace_close->GetOrigCol(), is_brace_close->GetLevel());
+ erst_found = 3;
+ }
+
+ if (back->Is(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->GetOrigLine(), is_semicolon->GetOrigCol(), is_semicolon->GetLevel());
+ 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->GetOrigLine(), back->GetOrigCol(), back->GetLevel());
+ }
+ }
+ 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->GetOrigLine() == second->GetOrigLine())
+ {
+ last = is_comment;
+
+ if (cl_colon->GetOrigLine() == is_comment->GetOrigLine())
+ {
+ last = is_comment->GetNext();
+ }
+ }
+ else
+ {
+ last = pc->GetPrevNcNnl();
+ }
+ }
+ else
+ {
+ LOG_FMT(LMCB, "\n\n%s(%d): FATAL: second is null chunk\n", __func__, __LINE__);
+ fprintf(stderr, "FATAL: second is null chunk\n");
+ fprintf(stderr, "Please make a report.\n");
+ exit(EX_SOFTWARE);
+ }
+ }
+ else
+ {
+ last = pc->GetPrevNcNnl();
+ }
+ }
+ else
+ {
+ LOG_FMT(LMCB, "\n\n%s(%d): FATAL: erst_found is not 3 or 4\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 (last->Is(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->GetOrigLine(), last->GetOrigCol());
+
+ 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->GetOrigLine(), last->GetOrigCol());
+
+ if (last->Is(CT_PP_ENDIF))
+ {
+ // look for the parent and compare the positions
+ Chunk *parent_last = last->GetParent();
+ int comp = parent_last->ComparePosition(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 = last->GetPpStart();
+ 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->GetOrigLine(), last->GetOrigCol());
+ }
+ 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->GetOrigLine(), last->GetOrigCol());
+ }
+ 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->GetOrigLine(), last->GetOrigCol());
+
+ if (!last->IsPreproc())
+ {
+ break;
+ }
+ }
+ }
+ return(last);
+} // calculate_closing_brace_position
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/calculate_closing_brace_position.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/calculate_closing_brace_position.h
new file mode 100644
index 00000000..6d2b0f06
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/change_int_types.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/change_int_types.cpp
new file mode 100644
index 00000000..e87f598b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/change_int_types.cpp
@@ -0,0 +1,186 @@
+/**
+ * @file change_int_types.cpp
+ *
+ * @author Alex Henrie
+ * @license GPL v2+
+ */
+
+#include "change_int_types.h"
+
+#include "chunk.h"
+#include "uncrustify.h"
+
+
+using namespace uncrustify;
+
+
+static bool is_storage_keyword(const Chunk *pc)
+{
+ return( strcmp(pc->Text(), "auto") == 0
+ || strcmp(pc->Text(), "const") == 0
+ || strcmp(pc->Text(), "extern") == 0
+ || strcmp(pc->Text(), "mutable") == 0
+ || strcmp(pc->Text(), "register") == 0
+ || strcmp(pc->Text(), "static") == 0
+ || strcmp(pc->Text(), "thread_local") == 0
+ || strcmp(pc->Text(), "typedef") == 0
+ || strcmp(pc->Text(), "volatile") == 0
+ || strcmp(pc->Text(), "_Atomic") == 0
+ || strcmp(pc->Text(), "_Thread_local") == 0);
+}
+
+
+static bool is_non_integer(const Chunk *pc)
+{
+ return( strcmp(pc->Text(), "char") == 0
+ || strcmp(pc->Text(), "double") == 0);
+}
+
+
+static bool find_non_storage_siblings(const Chunk *pc, Chunk * &prev, Chunk * &next)
+{
+ prev = pc->GetPrevNcNnl();
+ next = pc->GetNextNcNnl();
+
+ // Find the last token that was not a storage keyword
+ while (is_storage_keyword(prev))
+ {
+ prev = prev->GetPrevNcNnl();
+ }
+
+ // Return false if the last token indicates that this is not an integer type
+ if (is_non_integer(prev))
+ {
+ return(false);
+ }
+
+ // Find the next token that is not a storage keyword
+ while (is_storage_keyword(next))
+ {
+ next = next->GetNextNcNnl();
+ }
+
+ // Return false if the next token indicates that this is not an integer type
+ if (is_non_integer(next))
+ {
+ return(false);
+ }
+ // Return true if this is indeed an integer type
+ return(true);
+}
+
+
+static void add_or_remove_int_keyword(Chunk *pc, Chunk *sibling, iarf_e action, E_Direction dir, Chunk * &int_keyword)
+{
+ if (strcmp(sibling->Text(), "int") == 0)
+ {
+ if (action == IARF_REMOVE)
+ {
+ if (sibling == int_keyword)
+ {
+ int_keyword = Chunk::NullChunkPtr;
+ }
+ Chunk::Delete(sibling);
+ }
+ else if ( int_keyword->IsNotNullChunk()
+ && int_keyword != sibling)
+ {
+ // We added an int keyword, but now we see that there already was one.
+ // Keep one or the other but not both.
+ if (options::mod_int_prefer_int_on_left())
+ {
+ Chunk::Delete(sibling);
+ }
+ else
+ {
+ Chunk::Delete(int_keyword);
+ int_keyword = sibling;
+ }
+ }
+ else
+ {
+ int_keyword = sibling;
+ }
+ }
+ else
+ {
+ if ( action == IARF_ADD
+ || action == IARF_FORCE)
+ {
+ if (int_keyword->IsNotNullChunk())
+ {
+ // There was already an int keyword. Either keep it and don't add a
+ // new one or delete it to make way for the new one.
+ if (options::mod_int_prefer_int_on_left())
+ {
+ return;
+ }
+ else
+ {
+ Chunk::Delete(int_keyword);
+ }
+ }
+
+ if (dir == E_Direction::BACKWARD)
+ {
+ int_keyword = pc->CopyAndAddBefore(pc);
+ }
+ else
+ {
+ int_keyword = pc->CopyAndAddAfter(pc);
+ }
+ int_keyword->Str() = "int";
+ }
+ }
+} // add_or_remove_int_keyword
+
+
+void change_int_types()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev;
+ Chunk *next;
+ Chunk *int_keyword = Chunk::NullChunkPtr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (strcmp(pc->Text(), "short") == 0)
+ {
+ if (find_non_storage_siblings(pc, prev, next))
+ {
+ add_or_remove_int_keyword(pc, prev, options::mod_int_short(), E_Direction::BACKWARD, int_keyword);
+ add_or_remove_int_keyword(pc, next, options::mod_short_int(), E_Direction::FORWARD, int_keyword);
+ }
+ }
+ else if (strcmp(pc->Text(), "long") == 0)
+ {
+ if (find_non_storage_siblings(pc, prev, next))
+ {
+ add_or_remove_int_keyword(pc, prev, options::mod_int_long(), E_Direction::BACKWARD, int_keyword);
+ add_or_remove_int_keyword(pc, next, options::mod_long_int(), E_Direction::FORWARD, int_keyword);
+ }
+ }
+ else if (strcmp(pc->Text(), "signed") == 0)
+ {
+ if (find_non_storage_siblings(pc, prev, next))
+ {
+ add_or_remove_int_keyword(pc, prev, options::mod_int_signed(), E_Direction::BACKWARD, int_keyword);
+ add_or_remove_int_keyword(pc, next, options::mod_signed_int(), E_Direction::FORWARD, int_keyword);
+ }
+ }
+ else if (strcmp(pc->Text(), "unsigned") == 0)
+ {
+ if (find_non_storage_siblings(pc, prev, next))
+ {
+ add_or_remove_int_keyword(pc, prev, options::mod_int_unsigned(), E_Direction::BACKWARD, int_keyword);
+ add_or_remove_int_keyword(pc, next, options::mod_unsigned_int(), E_Direction::FORWARD, int_keyword);
+ }
+ }
+ else if ( strcmp(pc->Text(), "int") != 0
+ && !is_storage_keyword(pc))
+ {
+ int_keyword = Chunk::NullChunkPtr; // We are no longer in a variable declaration
+ }
+ }
+} // change_int_types
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/change_int_types.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/change_int_types.h
new file mode 100644
index 00000000..b392a5d7
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/change_int_types.h
@@ -0,0 +1,19 @@
+/**
+ * @file change_int_types.h
+ * prototypes for change_int_types.cpp
+ *
+ * @author Alex Henrie
+ * @license GPL v2+
+ */
+
+#ifndef CHANGE_INT_TYPES_H_INCLUDED
+#define CHANGE_INT_TYPES_H_INCLUDED
+
+
+/**
+ * @brief Add or remove redundant 'int' keyword of integer types
+ */
+void change_int_types();
+
+
+#endif /* CHANGE_INT_TYPES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/char_table.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/char_table.h
new file mode 100644
index 00000000..bcc30404
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/char_table.h
@@ -0,0 +1,84 @@
+/**
+ * @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
+
+#include "base_types.h"
+#include <cstddef>
+
+/**
+ * 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.78.0/src/check_template.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/check_template.cpp
new file mode 100644
index 00000000..870b3316
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/check_template.cpp
@@ -0,0 +1,536 @@
+/**
+ * @file check_template.cpp
+ *
+ * splitted from tokenize_cleanup.cpp
+ *
+ * @author Guy Maurel 2022
+ * @license GPL v2+
+ */
+
+#include "tokenize_cleanup.h"
+
+#include "check_template.h"
+#include "chunk.h"
+#include "combine.h"
+#include "flag_braced_init_list.h"
+#include "flag_decltype.h"
+#include "prototypes.h"
+
+
+using namespace uncrustify;
+
+
+bool invalid_open_angle_template(Chunk *prev)
+{
+ if (prev->IsNullChunk())
+ {
+ return(false);
+ }
+ // A template requires a word/type right before the open angle
+ return( prev->IsNot(CT_WORD)
+ && prev->IsNot(CT_TYPE)
+ && prev->IsNot(CT_COMMA)
+ && prev->IsNot(CT_QUALIFIER)
+ && prev->IsNot(CT_OPERATOR_VAL)
+ && prev->GetParentType() != CT_OPERATOR);
+}
+
+
+Chunk *handle_double_angle_close(Chunk *pc)
+{
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNotNullChunk())
+ {
+ if ( pc->Is(CT_ANGLE_CLOSE)
+ && next->Is(CT_ANGLE_CLOSE)
+ && pc->GetParentType() == CT_NONE
+ && (pc->GetOrigColEnd() + 1) == next->GetOrigCol()
+ && next->GetParentType() == CT_NONE)
+ {
+ pc->Str().append('>');
+ pc->SetType(CT_SHIFT);
+ pc->SetOrigColEnd(next->GetOrigColEnd());
+
+ Chunk *tmp = next->GetNextNcNnl();
+ Chunk::Delete(next);
+ next = tmp;
+ }
+ else
+ {
+ // bug #663
+ pc->SetType(CT_COMPARE);
+ }
+ }
+ return(next);
+}
+
+
+void check_template(Chunk *start, bool in_type_cast)
+{
+ LOG_FMT(LTEMPL, "%s(%d): orig line %zu, orig col %zu:\n",
+ __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol());
+
+ Chunk *prev = start->GetPrevNcNnl(E_Scope::PREPROC);
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *end;
+ Chunk *pc;
+
+ if (prev->Is(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->GetType()), level);
+
+ if ( (pc->GetStr()[0] == '>')
+ && (pc->Len() > 1))
+ {
+ if (pc->GetStr()[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->GetOrigLine(), pc->GetOrigCol());
+ }
+ else
+ {
+ LOG_FMT(LTEMPL, "%s(%d): {split '%s' at orig line %zu, orig col %zu}\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+ split_off_angle_close(pc);
+ }
+ }
+
+ if (pc->Is(CT_DECLTYPE))
+ {
+ flag_cpp_decltype(pc);
+ }
+ else if (pc->Is(CT_PAREN_OPEN))
+ {
+ ++parens;
+ }
+ else if (pc->Is(CT_PAREN_CLOSE))
+ {
+ --parens;
+ }
+
+ if (parens == 0)
+ {
+ if (pc->IsString("<"))
+ {
+ level++;
+ }
+ else if (pc->IsString(">"))
+ {
+ if (level == 0)
+ {
+ fprintf(stderr, "%s(%d): level is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ 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->GetType()));
+ start->SetType(CT_COMPARE);
+ return;
+ }
+ LOG_FMT(LTEMPL, "%s(%d): - prev->GetType() is %s -\n",
+ __func__, __LINE__, get_token_name(prev->GetType()));
+
+ // 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 ( ( pc->Is(CT_SEMICOLON)
+ && hit_semicolon)
+ || pc->Is(CT_SQUARE_CLOSE))
+ {
+ break;
+ }
+
+ if (pc->Is(CT_DECLTYPE))
+ {
+ flag_cpp_decltype(pc);
+ }
+
+ if (pc->Is(CT_BRACE_OPEN))
+ {
+ if ( !pc->TestFlags(PCF_IN_DECLTYPE)
+ || !detect_cpp_braced_init_list(pc->GetPrev(), pc))
+ {
+ break;
+ }
+ flag_cpp_braced_init_list(pc->GetPrev(), pc);
+ }
+
+ if ( pc->Is(CT_BRACE_CLOSE)
+ && pc->GetParentType() != CT_BRACED_INIT_LIST
+ && !pc->TestFlags(PCF_IN_DECLTYPE))
+ {
+ break;
+ }
+
+ if ( pc->Is(CT_SEMICOLON)
+ && !hit_semicolon)
+ {
+ hit_semicolon = true;
+ }
+
+ if ( ( ( pc->Is(CT_IF)
+ || pc->Is(CT_RETURN)
+ || pc->Is(CT_WHILE)
+ || pc->Is(CT_WHILE_OF_DO))
+ && !hit_semicolon)
+ || ( pc->Is(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, orig col is %zu, type is %s, num_tokens is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), num_tokens);
+
+ log_rule_B("tok_split_gte");
+
+ if (pc->Is(CT_BRACE_OPEN)) // Issue #2886
+ {
+ // look for the closing brace
+ Chunk *A = pc->GetClosingParen();
+ LOG_FMT(LTEMPL, "%s(%d): A orig line is %zu, orig col is %zu, type is %s\n",
+ __func__, __LINE__, A->GetOrigLine(), A->GetOrigCol(), get_token_name(A->GetType()));
+ pc = A->GetNext();
+ }
+
+ if ( (tokens[num_tokens - 1] == CT_ANGLE_OPEN)
+ && (pc->GetStr()[0] == '>')
+ && (pc->Len() > 1)
+ && ( options::tok_split_gte()
+ || ( ( pc->IsString(">>")
+ || pc->IsString(">>>"))
+ && ( 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->GetOrigLine(), pc->GetOrigCol());
+
+ split_off_angle_close(pc);
+ }
+
+ if (pc->IsString("<"))
+ {
+ if ( num_tokens > 0 && (tokens[num_tokens - 1] == CT_PAREN_OPEN)
+ && invalid_open_angle_template(pc->GetPrev()))
+ {
+ pc->SetType(CT_COMPARE); // Issue #3127
+ }
+ else
+ {
+ tokens[num_tokens] = CT_ANGLE_OPEN;
+ num_tokens++;
+ }
+ }
+ else if (pc->IsString(">"))
+ {
+ 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
+ && ( pc->Is(CT_BOOL)
+ || pc->Is(CT_COMPARE)))
+ {
+ break;
+ }
+ else if (pc->Is(CT_BRACE_OPEN))
+ {
+ if ( !pc->TestFlags(PCF_IN_DECLTYPE)
+ || !detect_cpp_braced_init_list(pc->GetPrev(), pc))
+ {
+ break;
+ }
+ auto brace_open = pc->GetNextNcNnl();
+ auto brace_close = brace_open->GetClosingParen();
+
+ brace_open->SetParentType(CT_BRACED_INIT_LIST);
+ brace_close->SetParentType(CT_BRACED_INIT_LIST);
+ }
+ else if ( pc->Is(CT_BRACE_CLOSE)
+ && pc->GetParentType() != CT_BRACED_INIT_LIST
+ && !pc->TestFlags(PCF_IN_DECLTYPE))
+ {
+ break;
+ }
+ else if (pc->Is(CT_SEMICOLON))
+ {
+ break;
+ }
+ else if (pc->Is(CT_PAREN_OPEN))
+ {
+ if (num_tokens >= max_token_count - 1)
+ {
+ break;
+ }
+ tokens[num_tokens] = CT_PAREN_OPEN;
+ num_tokens++;
+ }
+ else if ( pc->Is(CT_QUESTION) // Issue #2949
+ && language_is_set(LANG_CPP))
+ {
+ break;
+ }
+ else if (pc->Is(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->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ num_tokens--;
+
+ if (tokens[num_tokens] != CT_PAREN_OPEN)
+ {
+ break; // unbalanced parentheses
+ }
+ }
+ }
+
+ end = pc;
+ }
+
+ if (end->Is(CT_ANGLE_CLOSE))
+ {
+ pc = end->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( pc->IsNullChunk()
+ || pc->IsNot(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->GetOrigLine(), start->GetOrigCol());
+ LOG_FMT(LTEMPL, "%s(%d): to orig line %zu, orig col %zu\n",
+ __func__, __LINE__, end->GetOrigLine(), end->GetOrigCol());
+ start->SetParentType(CT_TEMPLATE);
+
+ check_template_args(start, end);
+
+ end->SetParentType(CT_TEMPLATE);
+ end->SetFlagBits(PCF_IN_TEMPLATE);
+ return;
+ }
+ }
+ LOG_FMT(LTEMPL, "%s(%d): - Not a template: end = %s\n",
+ __func__, __LINE__, (end->IsNotNullChunk() ? get_token_name(end->GetType()) : "<null>"));
+ start->SetType(CT_COMPARE);
+} // check_template
+
+
+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->GetOrigLine(), start->GetOrigCol());
+ LOG_FMT(LTEMPL, "%s(%d): to orig line %zu, orig col %zu\n",
+ __func__, __LINE__, end->GetOrigLine(), end->GetOrigCol());
+
+ // 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);
+ pc->SetFlagBits(PCF_IN_TEMPLATE);
+
+ if ( pc->Is(CT_DECLTYPE)
+ || pc->Is(CT_SIZEOF))
+ {
+ expressionIsNumeric = true;
+ break;
+ }
+
+ if (next->IsNot(CT_PAREN_OPEN))
+ {
+ if ( pc->Is(CT_NUMBER)
+ || pc->Is(CT_ARITH)
+ || pc->Is(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);
+ pc->SetFlagBits(PCF_IN_TEMPLATE);
+
+ Chunk *prev = pc->GetPrevNcNnl(E_Scope::PREPROC);
+ Chunk *prev2 = prev->GetPrevNcNnl(E_Scope::PREPROC);
+
+ if ( prev->Is(CT_ELLIPSIS) // Issue #3309
+ && prev2->Is(CT_TYPENAME))
+ {
+ pc->SetType(CT_PARAMETER_PACK);
+ }
+ else
+ {
+ make_type(pc);
+ }
+ pc = next;
+ }
+ }
+} // check_template_arg
+
+
+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->GetType())
+ {
+ 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->GetType());
+ 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
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/check_template.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/check_template.h
new file mode 100644
index 00000000..d65f2504
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/check_template.h
@@ -0,0 +1,55 @@
+/**
+ * @file check_template.h
+ * prototypes for check_template.cpp
+ *
+ * splitted from tokenize_cleanup.cpp
+ *
+ * @author Guy Maurel 2022
+ * @license GPL v2+
+ */
+#ifndef CHECK_TEMPLATE_H_INCLUDED
+#define CHECK_TEMPLATE_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+/**
+ * Mark types in a single template argument.
+ *
+ * @param start chunk to start check at
+ * @param end chunk to end check at
+ */
+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
+ */
+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
+ */
+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
+ */
+Chunk *handle_double_angle_close(Chunk *pc);
+
+
+bool invalid_open_angle_template(Chunk *prev);
+
+
+#endif /* CHECK_TEMPLATE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.cpp
new file mode 100644
index 00000000..35d9281c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.cpp
@@ -0,0 +1,915 @@
+/**
+ * @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"
+
+static ChunkListManager gChunkList; // global chunk list
+
+
+/*
+ * Chunk class methods
+ */
+
+// Null Chunk
+Chunk Chunk::NullChunk(true);
+Chunk *const Chunk::NullChunkPtr(&Chunk::NullChunk);
+
+
+void Chunk::CopyFrom(const Chunk &o)
+{
+ m_type = o.m_type;
+ m_parentType = o.m_parentType;
+ m_origLine = o.m_origLine;
+ m_origCol = o.m_origCol;
+ m_origColEnd = o.m_origColEnd;
+ m_origPrevSp = o.m_origPrevSp;
+ m_column = o.m_column;
+ m_columnIndent = o.m_columnIndent;
+ m_nlCount = o.m_nlCount;
+ m_nlColumn = o.m_nlColumn;
+ m_level = o.m_level;
+ m_braceLevel = o.m_braceLevel;
+ m_ppLevel = o.m_ppLevel;
+ m_afterTab = o.m_afterTab;
+
+ m_flags = o.m_flags;
+ m_alignmentData = o.m_alignmentData;
+ m_indentationData = o.m_indentationData;
+
+ m_next = Chunk::NullChunkPtr;
+ m_prev = Chunk::NullChunkPtr;
+ m_parent = Chunk::NullChunkPtr;
+
+ m_str = o.m_str;
+ m_trackingList = o.m_trackingList;
+}
+
+
+void Chunk::Reset()
+{
+ m_type = CT_NONE;
+ m_parentType = CT_NONE;
+ m_origLine = 0;
+ m_origCol = 0;
+ m_origColEnd = 0;
+ m_origPrevSp = 0;
+ m_column = 0;
+ m_columnIndent = 0;
+ m_nlCount = 0;
+ m_nlColumn = 0;
+ m_level = 0;
+ m_braceLevel = 0;
+ m_ppLevel = 999; // use a big value to find some errors
+ m_afterTab = false;
+
+ m_flags = PCF_NONE;
+ memset(&m_alignmentData, 0, sizeof(m_alignmentData));
+ m_alignmentData.next = NullChunkPtr;
+ m_alignmentData.start = NullChunkPtr;
+ m_alignmentData.ref = NullChunkPtr;
+ memset(&m_indentationData, 0, sizeof(m_indentationData));
+
+ m_next = Chunk::NullChunkPtr;
+ m_prev = Chunk::NullChunkPtr;
+ m_parent = Chunk::NullChunkPtr;
+
+ // for debugging purpose only
+ m_str.clear();
+ m_trackingList = nullptr;
+}
+
+
+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 (scope == E_Scope::ALL)
+ {
+ return(m_next);
+ }
+ Chunk *pc = m_next;
+
+ if (TestFlags(PCF_IN_PREPROC))
+ {
+ // If in a preproc, return a null chunk if trying to leave
+ if (!pc->TestFlags(PCF_IN_PREPROC))
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+ }
+
+ // Not in a preproc, skip any preproc
+ while ( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_IN_PREPROC))
+ {
+ pc = pc->m_next;
+ }
+ return(pc);
+} // Chunk::GetNext
+
+
+Chunk *Chunk::GetPrev(const E_Scope scope) const
+{
+ if (scope == E_Scope::ALL)
+ {
+ return(m_prev);
+ }
+ Chunk *pc = m_prev;
+
+ if (TestFlags(PCF_IN_PREPROC))
+ {
+ // If in a preproc, return a null chunk if trying to leave
+ if (!pc->TestFlags(PCF_IN_PREPROC))
+ {
+ return(NullChunkPtr);
+ }
+ return(pc);
+ }
+
+ // Not in a preproc, skip any preproc
+ while ( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_IN_PREPROC))
+ {
+ pc = pc->m_prev;
+ }
+ return(pc);
+} // Chunk::GetPrev
+
+
+static void chunk_log(Chunk *pc, const char *text);
+
+
+Chunk *Chunk::GetHead()
+{
+ return(gChunkList.GetHead());
+}
+
+
+Chunk *Chunk::GetTail()
+{
+ return(gChunkList.GetTail());
+}
+
+
+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
+}
+
+
+bool Chunk::IsOnSameLine(const Chunk *end) const
+{
+ if (IsNullChunk())
+ {
+ return(false);
+ }
+ Chunk *tmp = GetNext();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp != end)
+ {
+ if (tmp->Is(CT_NEWLINE))
+ {
+ return(false);
+ }
+ tmp = tmp->GetNext();
+ }
+ return(true);
+}
+
+
+Chunk *Chunk::SearchTypeLevel(const E_Token type, const E_Scope scope,
+ const E_Direction dir, const int level) 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(type, level))); // and the chunk was not found either
+
+ return(pc); // the latest chunk is the searched one
+}
+
+
+Chunk *Chunk::SearchStringLevel(const char *str, const size_t len, int level,
+ 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(str, len, true, level)); // 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 (!TestFlags(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->TestFlags(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(pc->Is(CT_NEWLINE));
+ return(pc);
+ }
+
+ if (pc->Is(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->GetOrigLine(), chunk->GetOrigCol());
+
+ if (chunk->Is(CT_NEWLINE))
+ {
+ LOG_FMT(log, "<Newline>,\n");
+ }
+ else if (chunk->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(log, "<VBRACE_OPEN>,\n");
+ }
+ else if (chunk->Is(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->GetType()));
+ }
+}
+
+
+static void chunk_log(Chunk *pc, const char *text)
+{
+ if ( 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);
+ }
+}
+
+
+void Chunk::Delete(Chunk * &pc)
+{
+ gChunkList.Remove(pc);
+ delete pc;
+ pc = Chunk::NullChunkPtr;
+}
+
+
+void Chunk::MoveAfter(Chunk *ref)
+{
+ LOG_FUNC_ENTRY();
+
+ if (ref == this)
+ {
+ return;
+ }
+ gChunkList.Remove(this);
+ gChunkList.AddAfter(this, ref);
+
+ // Adjust the original column
+ m_column = ref->m_column + space_col_align(ref, this);
+ m_origCol = m_column;
+ m_origColEnd = m_origCol + Len();
+}
+
+
+void Chunk::Swap(Chunk *other)
+{
+ gChunkList.Swap(this, other);
+}
+
+
+bool Chunk::IsAddress() const
+{
+ if ( IsNotNullChunk()
+ && ( Is(CT_BYREF)
+ || ( Len() == 1
+ && m_str[0] == '&'
+ && IsNot(CT_OPERATOR_VAL))))
+ {
+ Chunk *prevc = GetPrev();
+
+ if ( TestFlags(PCF_IN_TEMPLATE)
+ && ( prevc->Is(CT_COMMA)
+ || prevc->Is(CT_ANGLE_OPEN)))
+ {
+ return(false);
+ }
+ return(true);
+ }
+ return(false);
+}
+
+
+Chunk *Chunk::GetFirstChunkOnLine() const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+ Chunk *first = pc;
+
+ pc = pc->GetPrev();
+
+ while ( pc->IsNotNullChunk()
+ && !pc->IsNewline())
+ {
+ first = pc;
+ pc = pc->GetPrev();
+ }
+ return(first);
+}
+
+
+bool Chunk::IsLastChunkOnLine() const
+{
+ if (this == Chunk::GetTail())
+ {
+ return(true);
+ }
+
+ // if the next chunk is a newline then pc is the last chunk on its line
+ if (GetNext()->Is(CT_NEWLINE))
+ {
+ return(true);
+ }
+ return(false);
+}
+
+
+void Chunk::SwapLines(Chunk *other)
+{
+ // to swap lines we need to find the first chunk of the lines
+ Chunk *pc1 = GetFirstChunkOnLine();
+ Chunk *pc2 = other->GetFirstChunkOnLine();
+
+ 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()
+ && !pc2->IsNewline())
+ {
+ Chunk *tmp = pc2->GetNext();
+ gChunkList.Remove(pc2);
+ gChunkList.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()
+ && !pc1->IsNewline())
+ {
+ Chunk *tmp = pc1->GetNext();
+ gChunkList.Remove(pc1);
+
+ if (ref2->IsNotNullChunk())
+ {
+ gChunkList.AddAfter(pc1, ref2);
+ }
+ else
+ {
+ gChunkList.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 new line count so that the spacing remains the same.
+ */
+ if ( pc1->IsNotNullChunk()
+ && pc2->IsNotNullChunk())
+ {
+ size_t nlCount = pc1->GetNlCount();
+
+ pc1->SetNlCount(pc2->GetNlCount());
+ pc2->SetNlCount(nlCount);
+
+ pc1->Swap(pc2);
+ }
+} // Chunk::SwapLines
+
+
+void Chunk::SetResetFlags(PcfFlags resetBits, PcfFlags setBits)
+{
+ if (IsNotNullChunk())
+ {
+ LOG_FUNC_ENTRY();
+ const PcfFlags newFlags = (m_flags & ~resetBits) | setBits;
+
+ if (m_flags != newFlags)
+ {
+ LOG_FMT(LSETFLG,
+ "%s(%d): %016llx^%016llx=%016llx\n"
+ "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s', type is %s,",
+ __func__, __LINE__,
+ static_cast<PcfFlags::int_t>(m_flags),
+ static_cast<PcfFlags::int_t>(m_flags ^ newFlags),
+ static_cast<PcfFlags::int_t>(newFlags),
+ __func__, __LINE__, m_origLine, m_origCol, Text(), get_token_name(m_type));
+ LOG_FMT(LSETFLG, " parent type is %s,\n",
+ get_token_name(m_parentType));
+ log_func_stack_inline(LSETFLG);
+
+ LOG_FMT(LSETFLG, " before: ");
+ log_pcf_flags(LSETFLG, m_flags);
+ LOG_FMT(LSETFLG, " after: ");
+ log_pcf_flags(LSETFLG, newFlags);
+ m_flags = newFlags;
+ }
+ }
+}
+
+
+void Chunk::SetType(const E_Token token)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( IsNullChunk()
+ || m_type == token)
+ {
+ return;
+ }
+ LOG_FMT(LSETTYP, "%s(%d): orig line is %zu, orig col is %zu, Text() is ",
+ __func__, __LINE__, m_origLine, m_origCol);
+
+ if (token == CT_NEWLINE)
+ {
+ LOG_FMT(LSETTYP, "<Newline>\n");
+ }
+ else
+ {
+ LOG_FMT(LSETTYP, "'%s'\n", Text());
+ }
+ LOG_FMT(LSETTYP, " type is %s, parent type is %s => new type is %s\n",
+ get_token_name(m_type), get_token_name(m_parentType), get_token_name(token));
+ m_type = token;
+}
+
+
+void Chunk::SetParentType(const E_Token token)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( IsNullChunk()
+ || m_parentType == token)
+ {
+ return;
+ }
+ LOG_FMT(LSETPAR, "%s(%d): orig line is %zu, orig col is %zu, Text() is ",
+ __func__, __LINE__, m_origLine, m_origCol);
+
+ if (token == CT_NEWLINE)
+ {
+ LOG_FMT(LSETPAR, "<Newline>\n");
+ }
+ else
+ {
+ LOG_FMT(LSETPAR, "'%s'\n", Text());
+ }
+ LOG_FMT(LSETPAR, " type is %s, parent type is %s => new parent type is %s\n",
+ get_token_name(m_type), get_token_name(m_parentType), get_token_name(token));
+ m_parentType = token;
+}
+
+
+Chunk *Chunk::CopyAndAdd(Chunk *pos, const E_Direction dir) const
+{
+#ifdef DEBUG
+ // test if this chunk is properly set
+ if (m_ppLevel == 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 (m_origLine == 0)
+ {
+ fprintf(stderr, "%s(%d): no line number\n", __func__, __LINE__);
+ log_func_stack_inline(LSETFLG);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+
+ if (m_origCol == 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(*this);
+
+ if (pos->IsNotNullChunk())
+ {
+ (dir == E_Direction::FORWARD) ? gChunkList.AddAfter(pc, pos) : gChunkList.AddBefore(pc, pos);
+ }
+ else
+ {
+ (dir == E_Direction::FORWARD) ? gChunkList.AddHead(pc) : gChunkList.AddTail(pc);
+ }
+ chunk_log(pc, "CopyAndAdd(A):");
+ return(pc);
+} // Chunk::CopyAndAdd
+
+
+Chunk *Chunk::GetNextNbsb() const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while ( pc->Is(CT_TSQUARE)
+ || pc->Is(CT_SQUARE_OPEN))
+ {
+ if (pc->Is(CT_SQUARE_OPEN))
+ {
+ pc = pc->GetClosingParen();
+ }
+ pc = pc->GetNextNcNnl();
+ }
+ return(pc);
+}
+
+
+Chunk *Chunk::GetPrevNbsb() const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while ( pc->Is(CT_TSQUARE)
+ || pc->Is(CT_SQUARE_CLOSE))
+ {
+ if (pc->Is(CT_SQUARE_CLOSE))
+ {
+ pc = pc->GetOpeningParen();
+ }
+ pc = pc->GetPrevNcNnl();
+ }
+ return(pc);
+}
+
+
+Chunk *Chunk::GetPpStart() const
+{
+ if (!IsPreproc())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while (pc->IsNot(CT_PREPROC))
+ {
+ pc = pc->GetPrev(E_Scope::PREPROC);
+ }
+ return(pc);
+}
+
+
+Chunk *Chunk::SkipDcMember() const
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = const_cast<Chunk *>(this);
+ Chunk *nxt = pc->Is(CT_DC_MEMBER) ? pc : pc->GetNextNcNnl(E_Scope::ALL);
+
+ while (nxt->Is(CT_DC_MEMBER))
+ {
+ pc = nxt->GetNextNcNnl(E_Scope::ALL);
+
+ if (pc->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ nxt = pc->GetNextNcNnl(E_Scope::ALL);
+ }
+ return(pc);
+}
+
+
+int Chunk::ComparePosition(const Chunk *other) const
+{
+ if (m_origLine < other->m_origLine)
+ {
+ return(-1);
+ }
+ else if (m_origLine == other->m_origLine)
+ {
+ if (m_origCol < other->m_origCol)
+ {
+ return(-1);
+ }
+ else if (m_origCol == other->m_origCol)
+ {
+ return(0);
+ }
+ }
+ return(1);
+}
+
+
+bool Chunk::IsOCForinOpenParen() const
+{
+ if ( language_is_set(LANG_OC)
+ && Is(CT_SPAREN_OPEN)
+ && GetPrevNcNnl()->Is(CT_FOR))
+ {
+ Chunk *nxt = const_cast<Chunk *>(this);
+
+ while ( nxt->IsNotNullChunk()
+ && nxt->IsNot(CT_SPAREN_CLOSE)
+ && nxt->IsNot(CT_IN))
+ {
+ nxt = nxt->GetNextNcNnl();
+ }
+
+ if (nxt->Is(CT_IN))
+ {
+ return(true);
+ }
+ }
+ return(false);
+}
+
+
+bool Chunk::IsStringAndLevel(const char *str, const size_t len,
+ bool caseSensitive, const int level) const
+{
+ return( ( level < 0
+ || m_level == static_cast<size_t>(level))
+ && Len() == len // the length is as expected
+ && ( ( caseSensitive
+ && memcmp(Text(), str, len) == 0)
+ || ( !caseSensitive
+ && strncasecmp(Text(), str, len) == 0))); // the strings are equal
+}
+
+
+Chunk *Chunk::GetClosingParen(E_Scope scope) const
+{
+ if ( Is(CT_PAREN_OPEN)
+ || Is(CT_SPAREN_OPEN)
+ || Is(CT_FPAREN_OPEN)
+ || Is(CT_TPAREN_OPEN)
+ || Is(CT_BRACE_OPEN)
+ || Is(CT_VBRACE_OPEN)
+ || Is(CT_ANGLE_OPEN)
+ || Is(CT_SQUARE_OPEN))
+ {
+ return(GetNextType((E_Token)(m_type + 1), m_level, scope));
+ }
+ return(const_cast<Chunk *>(this));
+}
+
+
+Chunk *Chunk::GetOpeningParen(E_Scope scope) const
+{
+ if ( Is(CT_PAREN_CLOSE)
+ || Is(CT_SPAREN_CLOSE)
+ || Is(CT_FPAREN_CLOSE)
+ || Is(CT_TPAREN_CLOSE)
+ || Is(CT_BRACE_CLOSE)
+ || Is(CT_VBRACE_CLOSE)
+ || Is(CT_ANGLE_CLOSE)
+ || Is(CT_SQUARE_CLOSE))
+ {
+ return(GetPrevType((E_Token)(m_type - 1), m_level, scope));
+ }
+ return(const_cast<Chunk *>(this));
+}
+
+
+bool Chunk::IsCppInheritanceAccessSpecifier() const
+{
+ return( language_is_set(LANG_CPP)
+ && ( Is(CT_ACCESS)
+ || Is(CT_QUALIFIER))
+ && ( IsString("private")
+ || IsString("protected")
+ || IsString("public")));
+}
+
+
+bool Chunk::IsColon() const
+{
+ return( Is(CT_ACCESS_COLON)
+ || Is(CT_ASM_COLON)
+ || Is(CT_BIT_COLON)
+ || Is(CT_CASE_COLON)
+ || Is(CT_CLASS_COLON)
+ || Is(CT_COLON)
+ || Is(CT_COND_COLON)
+ || Is(CT_CONSTR_COLON)
+ || Is(CT_CS_SQ_COLON)
+ || Is(CT_D_ARRAY_COLON)
+ || Is(CT_ENUM_COLON)
+ || Is(CT_FOR_COLON)
+ || Is(CT_LABEL_COLON)
+ || Is(CT_OC_COLON)
+ || Is(CT_OC_DICT_COLON)
+ || Is(CT_TAG_COLON)
+ || Is(CT_WHERE_COLON));
+}
+
+
+bool Chunk::IsDoxygenComment() const
+{
+ if (!IsComment())
+ {
+ return(false);
+ }
+
+ if (Len() < 3)
+ {
+ return(false);
+ }
+ // check the third character
+ const char *sComment = Text();
+ return( (sComment[2] == '/')
+ || (sComment[2] == '!')
+ || (sComment[2] == '@'));
+}
+
+
+bool Chunk::IsTypeDefinition() const
+{
+ return( Is(CT_TYPE)
+ || Is(CT_PTR_TYPE)
+ || Is(CT_BYREF)
+ || Is(CT_DC_MEMBER)
+ || Is(CT_QUALIFIER)
+ || Is(CT_STRUCT)
+ || Is(CT_ENUM)
+ || Is(CT_UNION));
+}
+
+
+bool Chunk::IsNewlineBetween(const Chunk *other) const
+{
+ Chunk *pc = const_cast<Chunk *>(this);
+
+ while (pc != other)
+ {
+ if (pc->IsNewline())
+ {
+ return(true);
+ }
+ pc = pc->GetNext();
+ }
+ return(false);
+}
+
+
+void shift_the_rest_of_the_line(Chunk *first)
+{
+ // shift all the tokens in this line to the right Issue #3236
+ for (Chunk *temp = first; ; temp = temp->GetNext())
+ {
+ temp->SetColumn(temp->GetColumn() + 1); // Issue #3236
+ temp->SetOrigCol(temp->GetOrigCol() + 1); // Issue #3236
+ temp->SetOrigColEnd(temp->GetOrigColEnd() + 1); // Issue #3236
+
+ if (temp->Is(CT_NEWLINE))
+ {
+ break;
+ }
+ }
+} //shift_the_rest_of_the_line
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.h
new file mode 100644
index 00000000..7d7e0167
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/chunk.h
@@ -0,0 +1,1797 @@
+/**
+ * @file chunk.h
+ * Manages and navigates the list of chunks.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel
+ * @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_names.h"
+#include "language_tools.h"
+
+
+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 Chunk::NullChunkPtr)
+ */
+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
+};
+
+
+class ChunkListManager;
+
+// This is the main type of this program
+class Chunk
+{
+ friend ChunkListManager;
+
+public:
+ //! 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(m_nullChunk); }
+ bool IsNotNullChunk() const { return(!m_nullChunk); }
+
+ //! sets all elements of the struct to their default value
+ void Reset();
+
+
+ // --------- Access methods
+
+ /**
+ * @brief returns the type of the chunk
+ */
+ E_Token GetType() const;
+
+ /**
+ * @brief Sets the chunk type
+ * @param token the type to set
+ */
+ void SetType(const E_Token token);
+
+ /**
+ * @brief Returns the parent type of the chunk
+ */
+ E_Token GetParentType() const;
+
+ /**
+ * @brief Sets the type of the parent chunk
+ * @param token the type to set
+ */
+ void SetParentType(const E_Token token);
+
+ /**
+ * @brief Returns the parent of the chunk
+ */
+ Chunk *GetParent() const;
+
+ /**
+ * @brief Sets the parent of the chunk
+ * @param parent the parent chunk to set
+ */
+ void SetParent(Chunk *parent);
+
+ /**
+ * @brief Returns the alignment data of the chunk as a const reference
+ */
+ const AlignmentData &GetAlignData() const;
+
+ /**
+ * @brief Returns the alignment data of the chunk as a modifiable reference
+ */
+ AlignmentData &AlignData();
+
+ /**
+ * @brief Returns the indentation data of the chunk as a const reference
+ */
+ const IndentationData &GetIndentData() const;
+
+ /**
+ * @brief Returns the indentation data of the chunk as a modifiable reference
+ */
+ IndentationData &IndentData();
+
+ /**
+ * @brief Returns the text data of the chunk as a const reference
+ */
+ const UncText &GetStr() const;
+
+ /**
+ * @brief Returns the text data of the chunk as a modifiable reference
+ */
+ UncText &Str();
+
+ /**
+ * @brief returns the number of characters in the chunk text string
+ */
+ size_t Len() const;
+
+ /**
+ * @brief returns the content of the chunk text as C string
+ */
+ const char *Text() const;
+
+ /**
+ * Returns a filled up (if necessary) copy of the first chars of the Text() string
+ */
+ const char *ElidedText(char *for_the_copy) const;
+
+ /**
+ * @brief Returns the tracking data of the chunk as a const reference
+ */
+ const TrackList *GetTrackingData() const;
+
+ /**
+ * @brief Returns the tracking data of the chunk as a modifiable reference
+ */
+ TrackList * &TrackingData();
+
+ /**
+ * @brief Returns the type of the parent chunk
+ */
+ E_Token GetTypeOfParent() const;
+
+ /**
+ * @brief Returns the chunk flags
+ */
+ PcfFlags GetFlags() const;
+
+ /**
+ * @brief Sets the chunk flags
+ * @param flags the new chunk flags
+ */
+ void SetFlags(PcfFlags flags);
+
+ /**
+ * @brief Tests if some chunk flags are set
+ * @param flags the flag bits to test
+ * @return true if the specified bits are set, false otherwise
+ */
+ bool TestFlags(PcfFlags flags) const;
+
+ /**
+ * @brief Resets some of the chunk flag bits
+ * @param resetBits the flag bits to reset
+ */
+ void ResetFlagBits(PcfFlags resetBits);
+
+ /**
+ * @brief Sets some of the chunk flag bits
+ * @param setBits the flag bits to set
+ */
+ void SetFlagBits(PcfFlags setBits);
+
+ /**
+ * @brief Sets and reset some of the chunk flag bits
+ * @param resetBits the flag bits to reset
+ * @param setBits the flag bits to set
+ */
+ void UpdateFlagBits(PcfFlags resetBits, PcfFlags setBits);
+
+ /**
+ * @brief Returns the line number of the chunk in the input file
+ */
+ size_t GetOrigLine() const;
+
+ /**
+ * @brief Sets the line number of the chunk in the input file
+ * @param line the line number of the chunk
+ */
+ void SetOrigLine(size_t line);
+
+ /**
+ * @brief Returns the column number of the chunk in the input file
+ */
+ size_t GetOrigCol() const;
+
+ /**
+ * @brief Sets the column number of the chunk in the input file
+ * @param col the column number of the chunk
+ */
+ void SetOrigCol(size_t col);
+
+ /**
+ * @brief Returns the end column number of the chunk in the input file
+ */
+ size_t GetOrigColEnd() const;
+
+ /**
+ * @brief Sets the end column number of the chunk in the input file
+ * @param col the end column number of the chunk
+ */
+ void SetOrigColEnd(size_t col);
+
+ /**
+ * @brief Returns the position of the whitespace before this chunk
+ */
+ size_t GetOrigPrevSp() const;
+
+ /**
+ * @brief Sets the position of the whitespace before this chunk
+ * @param col the end column number of the chunk in the input file
+ */
+ void SetOrigPrevSp(size_t col);
+
+ /**
+ * @brief Returns the column of the chunk
+ */
+ size_t GetColumn() const;
+
+ /**
+ * @brief Sets the column of the chunk
+ * @param col the column of the chunk
+ */
+ void SetColumn(size_t col);
+
+ /**
+ * @brief Returns the column indentation of the chunk
+ */
+ size_t GetColumnIndent() const;
+
+ /**
+ * @brief Sets the column indentation of the chunk
+ * @param col the column indentation of the chunk
+ */
+ void SetColumnIndent(size_t col);
+
+ /**
+ * @brief Returns the number of newlines in a CT_NEWLINE chunk
+ */
+ size_t GetNlCount() const;
+
+ /**
+ * @brief Sets the number of newlines in a CT_NEWLINE chunk
+ * @param cnt the number of newlines
+ */
+ void SetNlCount(size_t cnt);
+
+ /**
+ * @brief Returns the column of the newline entries
+ */
+ size_t GetNlColumn() const;
+
+ /**
+ * @brief Sets the column of the newline entries
+ * @param col the number of the column
+ */
+ void SetNlColumn(size_t col);
+
+ /**
+ * @brief Returns the level of the chunk
+ */
+ size_t GetLevel() const;
+
+ /**
+ * @brief Sets the level of the chunk
+ * @param col the level of the chunk
+ */
+ void SetLevel(size_t level);
+
+ /**
+ * @brief Returns the brace level of the chunk
+ */
+ size_t GetBraceLevel() const;
+
+ /**
+ * @brief Sets the brace level of the chunk
+ * @param level the brace level of the chunk
+ */
+ void SetBraceLevel(size_t lvl);
+
+ /**
+ * @brief Returns the preprocessor level of the chunk
+ */
+ size_t GetPpLevel() const;
+
+ /**
+ * @brief Sets the preprocessor level of the chunk
+ * @param level the preprocessor level of the chunk
+ */
+ void SetPpLevel(size_t lvl);
+
+ /**
+ * @brief Returns the after tab property of the chunk
+ */
+ bool GetAfterTab() const;
+
+ /**
+ * @brief Sets the after tab property of the chunk
+ * @param afterTab the after tab property of the chunk
+ */
+ void SetAfterTab(bool afterTab);
+
+
+ // --------- Get* chunk functions
+
+ /**
+ * @brief returns the head of the chunk list
+ * @return pointer to the first chunk
+ */
+ static Chunk *GetHead();
+
+ /**
+ * @brief returns the tail of the chunk list
+ * @return pointer to the last chunk
+ */
+ static Chunk *GetTail();
+
+ /**
+ * @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 Chunk::NullChunkPtr 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 type the type to look for
+ * @param level the level to match or 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 type, const int level = ANY_LEVEL, const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev chunk of the given type at the level.
+ * @param type the type to look for
+ * @param level the level to match or 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 = ANY_LEVEL, E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next chunk that holds a given string at a given level.
+ * @param str string to search for
+ * @param len length of string
+ * @param level the level to match or 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 *GetNextString(const char *str, const size_t len, const int level, const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the prev chunk that holds a given string at a given level.
+ * @param str string to search for
+ * @param len length of string
+ * @param level the level to match or 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 *GetPrevString(const char *str, const size_t len, const int level, const E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the next chunk that is not part of balanced square brackets.
+ * This handles stacked[] instances to accommodate multidimensional arrays.
+ * @return pointer to the next matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetNextNbsb() const;
+
+ /**
+ * @brief returns the prev chunk that is not part of balanced square brackets.
+ * This handles stacked[] instances to accommodate multidimensional arrays.
+ * @return pointer to the prev matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPrevNbsb() const;
+
+ /**
+ * @brief returns the corresponding start chunk if the given chunk is within a
+ * preprocessor directive, or Chunk::NullChunkPtr otherwise.
+ * @return start chunk of the preprocessor directive or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetPpStart() const;
+
+ /**
+ * @brief Finds the first chunk on the line the current chunk is on.
+ * This just backs up until a newline or null chuck is hit.
+ *
+ * given: [ a - b - c - n1 - d - e - n2 ]
+ * input: [ a | b | c | n1 ] => a
+ * input: [ d | e | n2 ] => d
+ *
+ * @return pointer to the first chunk on the line the current chunk is on.
+ */
+ Chunk *GetFirstChunkOnLine() 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 and level is found.
+ *
+ * This function is a specialization of Chunk::Search.
+ *
+ * @param type category to search for
+ * @param scope code parts to consider for search
+ * @param dir search direction
+ * @param level nesting level to match or ANY_LEVEL
+ * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *SearchTypeLevel(const E_Token type, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD, const int level = ANY_LEVEL) 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 str string that searched chunk needs to have
+ * @param len length of the string
+ * @param level 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 *str, const size_t len, const int level, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD) const;
+
+ /**
+ * @brief returns the closing match for the current paren/brace/square.
+ * @param scope chunk section to consider
+ * @return pointer to the next matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetClosingParen(E_Scope scope = E_Scope::ALL) const;
+
+ /**
+ * @brief returns the opening match for the current paren/brace/square.
+ * @param scope chunk section to consider
+ * @return pointer to the prev matching chunk or Chunk::NullChunkPtr if no chunk was found
+ */
+ Chunk *GetOpeningParen(E_Scope scope = E_Scope::ALL) 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 token name is a specific string
+ * @param str string to compare token name with
+ * @param caseSensitive whether to do a case sensitive or insensitive comparison
+ * @return true if the chunk token name matches the specified string, false otherwise
+ */
+ bool IsString(const char *str, bool caseSensitive = true) 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 other chunk has the same preproc flags
+ * @return true if the other chunk has the same preproc flags
+ */
+ bool IsSamePreproc(const Chunk *other) 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 single line comment
+ * @return true if the chunk is a single line comment
+ */
+ bool IsSingleLineComment() const;
+
+ /**
+ * @brief checks whether the chunk is a Doxygen comment
+ * @return true if the chunk is a Doxygen comment
+ */
+ bool IsDoxygenComment() 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 type, const int level) const;
+
+ /**
+ * @brief checks whether the chunk matches a given string and level
+ * @param str the expected string
+ * @param len length of the string
+ * @param caseSensitive whether to do a case sensitive or insensitive comparison
+ * @param level nesting level of the searched chunk, ignored when negative
+ * @return true if the chunk matches a given string and level
+ */
+ bool IsStringAndLevel(const char *str, const size_t len, bool caseSensitive, const int level) const;
+
+ /**
+ * @brief checks whether the chunk is a star/asterisk
+ * @return true if the chunk is a star/asterisk
+ */
+ bool IsStar() const;
+
+ /**
+ * @brief checks whether the chunk is a colon
+ * @return true if the chunk is a colon
+ */
+ bool IsColon() const;
+
+ /**
+ * @brief checks whether the chunk is a semicolon
+ * @return true if the chunk is a semicolon
+ */
+ bool IsSemicolon() const;
+
+ /**
+ * @brief checks whether the chunk is a pointer operator
+ * @return true if the chunk is a pointer operator
+ */
+ bool IsPointerOperator() const;
+
+ /**
+ * @brief checks whether the chunk is a pointer or a reference
+ * @return true if the chunk is a pointer or a reference
+ */
+ bool IsPointerOrReference() const;
+
+ /**
+ * @brief checks whether the chunk is an inheritance access specifier
+ * @return true if the chunk is an inheritance access specifier
+ */
+ bool IsCppInheritanceAccessSpecifier() const;
+
+ /**
+ * @brief checks whether the chunk is a pointer, reference or a qualifier
+ * @return true if the chunk is a pointer, reference or a qualifier
+ */
+ bool IsPointerReferenceOrQualifier() const;
+
+ /**
+ * @brief checks whether the chunk is an address
+ * @return true if the chunk is an address
+ */
+ bool IsAddress() const;
+
+ /**
+ * @brief checks whether the chunk is a MS reference
+ * @return true if the chunk is a MS reference
+ * NOTE: MS compilers for C++/CLI and WinRT use '^' instead of '*'
+ * for marking up reference types vs pointer types
+ */
+ bool IsMsRef() const;
+
+ /**
+ * @brief checks whether the chunk is nullable
+ * @return true if the chunk is nullable
+ */
+ bool IsNullable() const;
+
+ /**
+ * @brief Checks if a given chunk is the last on its line
+ * @return true or false depending on whether a given chunk is the last on its line
+ */
+ bool IsLastChunkOnLine() const;
+
+ /**
+ * @brief checks whether the current chunk is on same line of the given 'end' chunk.
+ * The current chunk must be before the 'end' chunk
+ * @param end the end chunk
+ * @return true if there is no newline between the current chunk and end chunk
+ */
+ bool IsOnSameLine(const Chunk *end) const;
+
+ /**
+ * @brief checks whether the chunk is an opening brace
+ * @return true if the chunk is an opening brace
+ */
+ bool IsBraceOpen() const;
+
+ /**
+ * @brief checks whether the chunk is a closing brace
+ * @return true if the chunk is a closing brace
+ */
+ bool IsBraceClose() const;
+
+ /**
+ * @brief checks whether the chunk is an opening parenthesis
+ * @return true if the chunk is an opening parenthesis
+ */
+ bool IsParenOpen() const;
+
+ /**
+ * @brief checks whether the chunk is a closing parenthesis
+ * @return true if the chunk is a closing parenthesis
+ */
+ bool IsParenClose() const;
+
+ /**
+ * @brief checks if a chunk points to the opening parentheses of a
+ * for (...in...) loop in Objective-C.
+ * @return true if the chunk is the opening parentheses of a for-in loop
+ */
+ bool IsOCForinOpenParen() const;
+
+ /**
+ * @brief checks whether the chunk is a type defining token
+ * @return true if the chunk is a type defining token
+ */
+ bool IsTypeDefinition() const;
+
+ /**
+ * @brief checks whether the chunk is a word
+ * @return true if the chunk is a word
+ */
+ bool IsWord() const;
+
+ /**
+ * @brief checks whether the chunk is an enum or an enum class
+ * @return true if the chunk is an enum or an enum class
+ */
+ bool IsEnum() const;
+
+ /**
+ * @brief checks whether the chunk is a class or a struct
+ * @return true if the chunk is a class or a struct
+ */
+ bool IsClassOrStruct() const;
+
+ /**
+ * @brief checks whether the chunk is a class, struct or union
+ * @return true if the chunk is a class, struct or union
+ */
+ bool IsClassStructOrUnion() const;
+
+ /**
+ * @brief checks whether the chunk is a class, enum, struct or union
+ * @return true if the chunk is a class, enum, struct or union
+ */
+ bool IsClassEnumStructOrUnion() const;
+
+ /**
+ * @brief checks whether there is a newline between this chunk and the other
+ * @return true if there is a newline between this chunk and the other
+ */
+ bool IsNewlineBetween(const Chunk *other) const;
+
+
+ // --------- Util functions
+
+ /**
+ * @brief delete the chunk from the chunk list
+ * @param pc the chunk to remove from the list
+ */
+ static void Delete(Chunk * &pc);
+
+ /**
+ * @brief add a copy of this chunk after the given position in a chunk list.
+ * @note If pos is NullChunk, add at the tail of the chunk list
+ * @param pos insert position in list
+ * @return pointer to the newly added chunk
+ */
+ Chunk *CopyAndAddAfter(Chunk *pos) const;
+
+ /**
+ * @brief add a copy of this chunk before the given position in a chunk list.
+ * @note If pos is NullChunk, add at the head of the chunk list
+ * @param pos insert position in list
+ * @return pointer to the newly added chunk
+ */
+ Chunk *CopyAndAddBefore(Chunk *pos) const;
+
+ /**
+ * @brief move the chunk after the reference position in the chunk list
+ * @param ref chunk after which to move the current chunk
+ */
+ void MoveAfter(Chunk *ref);
+
+ /**
+ * @brief swaps the place of this chunk with the given one
+ * @param other the other chunk
+ */
+ void Swap(Chunk *other);
+
+ /**
+ * @brief swaps the two lines that are started by the current chunk and the other chunk
+ * @param other the other chunk
+ */
+ void SwapLines(Chunk *other);
+
+ //!
+ /**
+ * @brief skips to the final word/type in a :: chain
+ * @return pointer to the chunk after the final word/type in a :: chain
+ */
+ Chunk *SkipDcMember() const;
+
+ /**
+ * @brief compare the positions of the chunk with another one
+ * @param other the other chunk
+ * @return returns -1 if this chunk comes first, +1 if it comes after, or 0.
+ */
+ int ComparePosition(const Chunk *other) const;
+
+ /**
+ * 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.
+ */
+ bool SafeToDeleteNl() const;
+
+
+protected:
+ // --------- Protected util functions
+
+ /**
+ * @brief copy the values from another chunk.
+ * @NOTE: this is a partial copy only: the chunk is not linked to others
+ * @param o the chunk to copy from
+ */
+ void CopyFrom(const Chunk &o);
+
+ /**
+ * @brief add a copy of this chunk before/after the given position in a chunk list.
+ * @note If pos is NullChunk, add the new chuck either at the head or tail of the
+ * list based on the specified direction.
+ * @param pos insert position in list
+ * @param dir insert before or after the given position chunk
+ * @return pointer to the newly added chunk
+ */
+ Chunk *CopyAndAdd(Chunk *pos, const E_Direction dir = E_Direction::FORWARD) const;
+
+ /**
+ * @brief set and/or clear the chunk flags
+ * @param setBits the flag bits to set
+ * @param resetBits the flag bits to reset
+ */
+ void SetResetFlags(PcfFlags resetBits, PcfFlags setBits);
+
+
+ // --------- Data members
+ E_Token m_type; //! type of the chunk itself
+ E_Token m_parentType; //! type of the parent chunk usually CT_NONE
+ size_t m_origLine; //! line number of chunk in input file
+ size_t m_origCol; //! column where chunk started in the input file, is always > 0
+ size_t m_origColEnd; //! column where chunk ended in the input file, is always > 1
+ size_t m_origPrevSp; //! whitespace before this token
+ size_t m_column; //! column of the chunk
+ size_t m_columnIndent; //! if 1st chunk on a line, set to the 'indent' column, which may
+ //! be less than the real column used to indent with tabs
+ size_t m_nlCount; //! number of newlines in CT_NEWLINE
+ size_t m_nlColumn; //! column of the subsequent newline entries(all of them should have the same column)
+ size_t m_level; //! nest level in {, (, or [. Only to help vim command }
+ size_t m_braceLevel; //! nest level in braces only
+ size_t m_ppLevel; //! nest level in preprocessor
+ bool m_afterTab; //! whether this token was after a tab
+
+ PcfFlags m_flags; //! see PCF_xxx
+ AlignmentData m_alignmentData; //! alignment data of the chunk
+ IndentationData m_indentationData; //! indentation data of the chunk
+
+ Chunk *m_next; //! pointer to next chunk in list
+ Chunk *m_prev; //! pointer to previous chunk in list
+ Chunk *m_parent; //! pointer to parent chunk (not always set)
+
+ UncText m_str; //! the token text
+ TrackList *m_trackingList; //! for debugging purpose only
+
+
+private:
+ const bool m_nullChunk; //! true for null chunks
+
+
+public:
+ static Chunk NullChunk; //! Null Chunk
+ static Chunk *const NullChunkPtr; //! Pointer to the Null Chunk
+};
+
+
+inline Chunk::Chunk(bool null_c)
+ : m_nullChunk(null_c)
+{
+ Reset();
+}
+
+
+inline Chunk::Chunk(const Chunk &o)
+ : m_nullChunk(o.m_nullChunk)
+{
+ CopyFrom(o);
+}
+
+
+inline Chunk &Chunk::operator=(const Chunk &o)
+{
+ if (this != &o)
+ {
+ CopyFrom(o);
+ }
+ return(*this);
+}
+
+
+inline size_t Chunk::Len() const
+{
+ return(m_str.size());
+}
+
+
+inline const char *Chunk::Text() const
+{
+ return(m_str.c_str());
+}
+
+
+inline Chunk *Chunk::GetParent() const
+{
+ return(m_parent);
+}
+
+
+inline void Chunk::SetParent(Chunk *parent)
+{
+ if (this != parent)
+ {
+ m_parent = parent;
+ }
+}
+
+
+inline const AlignmentData &Chunk::GetAlignData() const
+{
+ return(m_alignmentData);
+}
+
+
+inline AlignmentData &Chunk::AlignData()
+{
+ return(m_alignmentData);
+}
+
+
+inline const IndentationData &Chunk::GetIndentData() const
+{
+ return(m_indentationData);
+}
+
+
+inline IndentationData &Chunk::IndentData()
+{
+ return(m_indentationData);
+}
+
+
+inline const UncText &Chunk::GetStr() const
+{
+ return(m_str);
+}
+
+
+inline UncText &Chunk::Str()
+{
+ return(m_str);
+}
+
+
+inline const TrackList *Chunk::GetTrackingData() const
+{
+ return(m_trackingList);
+}
+
+
+inline TrackList * &Chunk::TrackingData()
+{
+ return(m_trackingList);
+}
+
+
+inline E_Token Chunk::GetType() const
+{
+ return(m_type);
+}
+
+
+inline E_Token Chunk::GetParentType() const
+{
+ return(m_parentType);
+}
+
+
+inline E_Token Chunk::GetTypeOfParent() const
+{
+ if (GetParent()->IsNullChunk())
+ {
+ return(CT_PARENT_NOT_SET);
+ }
+ return(GetParent()->GetType());
+}
+
+
+inline PcfFlags Chunk::GetFlags() const
+{
+ return(m_flags);
+}
+
+
+inline void Chunk::SetFlags(PcfFlags flags)
+{
+ m_flags = flags;
+}
+
+
+inline bool Chunk::TestFlags(PcfFlags flags) const
+{
+ return(m_flags.test(flags));
+}
+
+
+inline void Chunk::ResetFlagBits(PcfFlags resetBits)
+{
+ SetResetFlags(resetBits, PCF_NONE);
+}
+
+
+inline void Chunk::SetFlagBits(PcfFlags setBits)
+{
+ SetResetFlags(PCF_NONE, setBits);
+}
+
+
+inline void Chunk::UpdateFlagBits(PcfFlags resetBits, PcfFlags setBits)
+{
+ SetResetFlags(resetBits, setBits);
+}
+
+
+inline size_t Chunk::GetOrigLine() const
+{
+ return(m_origLine);
+}
+
+
+inline void Chunk::SetOrigLine(size_t line)
+{
+ m_origLine = line;
+}
+
+
+inline size_t Chunk::GetOrigCol() const
+{
+ return(m_origCol);
+}
+
+
+inline void Chunk::SetOrigCol(size_t col)
+{
+ m_origCol = col;
+}
+
+
+inline size_t Chunk::GetOrigColEnd() const
+{
+ return(m_origColEnd);
+}
+
+
+inline void Chunk::SetOrigColEnd(size_t col)
+{
+ m_origColEnd = col;
+}
+
+
+inline size_t Chunk::GetOrigPrevSp() const
+{
+ return(m_origPrevSp);
+}
+
+
+inline void Chunk::SetOrigPrevSp(size_t col)
+{
+ m_origPrevSp = col;
+}
+
+
+inline size_t Chunk::GetColumn() const
+{
+ return(m_column);
+}
+
+
+inline void Chunk::SetColumn(size_t col)
+{
+ m_column = col;
+}
+
+
+inline size_t Chunk::GetColumnIndent() const
+{
+ return(m_columnIndent);
+}
+
+
+inline void Chunk::SetColumnIndent(size_t col)
+{
+ m_columnIndent = col;
+}
+
+
+inline size_t Chunk::GetNlCount() const
+{
+ return(m_nlCount);
+}
+
+
+inline void Chunk::SetNlCount(size_t cnt)
+{
+ m_nlCount = cnt;
+}
+
+
+inline size_t Chunk::GetNlColumn() const
+{
+ return(m_nlColumn);
+}
+
+
+inline void Chunk::SetNlColumn(size_t col)
+{
+ m_nlColumn = col;
+}
+
+
+inline size_t Chunk::GetLevel() const
+{
+ return(m_level);
+}
+
+
+inline void Chunk::SetLevel(size_t level)
+{
+ m_level = level;
+}
+
+
+inline size_t Chunk::GetBraceLevel() const
+{
+ return(m_braceLevel);
+}
+
+
+inline void Chunk::SetBraceLevel(size_t lvl)
+{
+ m_braceLevel = lvl;
+}
+
+
+inline size_t Chunk::GetPpLevel() const
+{
+ return(m_ppLevel);
+}
+
+
+inline void Chunk::SetPpLevel(size_t lvl)
+{
+ m_ppLevel = lvl;
+}
+
+
+inline bool Chunk::GetAfterTab() const
+{
+ return(m_afterTab);
+}
+
+
+inline void Chunk::SetAfterTab(bool afterTab)
+{
+ m_afterTab = afterTab;
+}
+
+
+inline Chunk *Chunk::GetNextNl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::FORWARD, true));
+}
+
+
+inline Chunk *Chunk::GetPrevNl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::BACKWARD, true));
+}
+
+
+inline Chunk *Chunk::GetNextNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsNewline, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline Chunk *Chunk::GetNextNc(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsComment, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNc(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsComment, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline Chunk *Chunk::GetNextNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewline, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewline, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline Chunk *Chunk::GetNextNcNnlNpp(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrPreproc, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNcNnlNpp(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrPreproc, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline Chunk *Chunk::GetNextNppOrNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewlineInPreproc, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNppOrNcNnl(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentOrNewlineInPreproc, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline Chunk *Chunk::PpaGetNextNcNnl() const
+{
+ return(SearchPpa(&Chunk::IsCommentOrNewline, false));
+}
+
+
+inline Chunk *Chunk::GetNextNcNnlNet(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrEmptyText, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNcNnlNet(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrEmptyText, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNcNnlNi(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsCommentNewlineOrIgnored, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline Chunk *Chunk::GetNextNisq(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsSquareBracket, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetNextType(const E_Token type, const int level, const E_Scope scope) const
+{
+ return(SearchTypeLevel(type, scope, E_Direction::FORWARD, level));
+}
+
+
+inline Chunk *Chunk::GetPrevType(const E_Token type, const int level, const E_Scope scope) const
+{
+ return(SearchTypeLevel(type, scope, E_Direction::BACKWARD, level));
+}
+
+
+inline Chunk *Chunk::GetNextString(const char *str, const size_t len, const int level, const E_Scope scope) const
+{
+ return(SearchStringLevel(str, len, level, scope, E_Direction::FORWARD));
+}
+
+
+inline Chunk *Chunk::GetPrevString(const char *str, const size_t len, const int level, const E_Scope scope) const
+{
+ return(SearchStringLevel(str, len, level, scope, E_Direction::BACKWARD));
+}
+
+
+inline Chunk *Chunk::GetNextNvb(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsVBrace, scope, E_Direction::FORWARD, false));
+}
+
+
+inline Chunk *Chunk::GetPrevNvb(const E_Scope scope) const
+{
+ return(Search(&Chunk::IsVBrace, scope, E_Direction::BACKWARD, false));
+}
+
+
+inline bool Chunk::IsTypeAndLevel(const E_Token type, const int level) const
+{
+ return( ( level < 0
+ || m_level == static_cast<size_t>(level))
+ && m_type == type);
+}
+
+
+inline bool Chunk::Is(E_Token token) const
+{
+ return( IsNotNullChunk()
+ && m_type == token);
+}
+
+
+inline bool Chunk::IsString(const char *str, bool caseSensitive) const
+{
+ return(IsStringAndLevel(str, strlen(str), caseSensitive, ANY_LEVEL));
+}
+
+
+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()
+ && TestFlags(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::IsSingleLineComment() const
+{
+ return( Is(CT_COMMENT)
+ || Is(CT_COMMENT_CPP));
+}
+
+
+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
+ && m_str[0] == '*'
+ && IsNot(CT_OPERATOR_VAL));
+}
+
+
+inline bool Chunk::IsSemicolon() const
+{
+ return( Is(CT_SEMICOLON)
+ || Is(CT_VSEMICOLON));
+}
+
+
+inline bool Chunk::IsWord() const
+{
+ return( Len() >= 1
+ && CharTable::IsKw1(m_str[0]));
+}
+
+
+inline bool Chunk::IsNullable() const
+{
+ return( language_is_set(LANG_CS | LANG_VALA)
+ && Len() == 1
+ && m_str[0] == '?');
+}
+
+
+inline bool Chunk::IsMsRef() const
+{
+ return( language_is_set(LANG_CPP)
+ && Len() == 1
+ && m_str[0] == '^'
+ && IsNot(CT_OPERATOR_VAL));
+}
+
+
+inline bool Chunk::IsPointerOperator() const
+{
+ return( IsStar()
+ || IsAddress()
+ || IsMsRef()
+ || IsNullable());
+}
+
+
+inline bool Chunk::IsPointerOrReference() const
+{
+ return( IsPointerOperator()
+ || Is(CT_BYREF));
+}
+
+
+inline bool Chunk::IsBraceOpen() const
+{
+ return( Is(CT_BRACE_OPEN)
+ || Is(CT_VBRACE_OPEN));
+}
+
+
+inline bool Chunk::IsBraceClose() const
+{
+ return( Is(CT_BRACE_CLOSE)
+ || Is(CT_VBRACE_CLOSE));
+}
+
+
+inline bool Chunk::IsParenOpen() const
+{
+ return( Is(CT_PAREN_OPEN)
+ || Is(CT_SPAREN_OPEN)
+ || Is(CT_PPAREN_OPEN)
+ || Is(CT_TPAREN_OPEN)
+ || Is(CT_FPAREN_OPEN)
+ || Is(CT_LPAREN_OPEN));
+}
+
+
+inline bool Chunk::IsParenClose() const
+{
+ return( Is(CT_PAREN_CLOSE)
+ || Is(CT_SPAREN_CLOSE)
+ || Is(CT_PPAREN_CLOSE)
+ || Is(CT_TPAREN_CLOSE)
+ || Is(CT_FPAREN_CLOSE)
+ || Is(CT_LPAREN_CLOSE));
+}
+
+
+inline bool Chunk::IsSamePreproc(const Chunk *other) const
+{
+ return( IsNotNullChunk()
+ && other->IsNotNullChunk()
+ && (TestFlags(PCF_IN_PREPROC) == other->TestFlags(PCF_IN_PREPROC)));
+}
+
+
+inline bool Chunk::SafeToDeleteNl() const
+{
+ Chunk *tmp = GetPrev();
+
+ if (tmp->Is(CT_COMMENT_CPP))
+ {
+ return(false);
+ }
+ return(tmp->IsSamePreproc(GetNext()));
+}
+
+
+inline bool Chunk::IsEnum() const
+{
+ return( Is(CT_ENUM)
+ || Is(CT_ENUM_CLASS));
+}
+
+
+inline bool Chunk::IsClassOrStruct() const
+{
+ return( Is(CT_CLASS)
+ || Is(CT_STRUCT));
+}
+
+
+inline bool Chunk::IsClassStructOrUnion() const
+{
+ return( IsClassOrStruct()
+ || Is(CT_UNION));
+}
+
+
+inline bool Chunk::IsClassEnumStructOrUnion() const
+{
+ return( IsClassStructOrUnion()
+ || IsEnum());
+}
+
+
+inline Chunk *Chunk::CopyAndAddAfter(Chunk *ref) const
+{
+ return(CopyAndAdd(ref, E_Direction::FORWARD));
+}
+
+
+inline Chunk *Chunk::CopyAndAddBefore(Chunk *ref) const
+{
+ return(CopyAndAdd(ref, E_Direction::BACKWARD));
+}
+
+
+// shift all the tokens in this line to the right Issue #3236
+void shift_the_rest_of_the_line(Chunk *first);
+
+
+#endif /* CHUNK_LIST_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.cpp
new file mode 100644
index 00000000..a033be49
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.cpp
@@ -0,0 +1,4044 @@
+/**
+ * @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 "mark_question_colon.h"
+#include "newlines.h"
+#include "prototypes.h"
+#include "tokenize_cleanup.h"
+#include "unc_tools.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);
+
+
+/**
+ * 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_and_throws();
+
+
+/**
+ * Processes a 'return' or 'throw' statement, labeling the parens and marking
+ * the parent. May remove or add parens around the return/throw statement.
+ *
+ * @param pc Pointer to the return or throw chunk
+ */
+static Chunk *process_return_or_throw(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, PcfFlags 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 (tmp->IsNot(CT_QUALIFIER))
+ {
+ return;
+ }
+ Chunk *po = tmp->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (!po->IsParenOpen())
+ {
+ return;
+ }
+ Chunk *end = po->GetClosingParen(E_Scope::PREPROC);
+
+ if (end->IsNullChunk())
+ {
+ return;
+ }
+ po->SetParentType(CT_ASM);
+ end->SetParentType(CT_ASM);
+
+ for ( tmp = po->GetNextNcNnl(E_Scope::PREPROC);
+ tmp->IsNotNullChunk()
+ && tmp != end;
+ tmp = tmp->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ if (tmp->Is(CT_COLON))
+ {
+ tmp->SetType(CT_ASM_COLON);
+ }
+ else if (tmp->Is(CT_DC_MEMBER))
+ {
+ // if there is a string on both sides, then this is two ASM_COLONs
+ if ( tmp->GetNextNcNnl(E_Scope::PREPROC)->Is(CT_STRING)
+ && tmp->GetPrevNcNnlNi(E_Scope::PREPROC)->Is(CT_STRING)) // Issue #2279
+ {
+ Chunk nc;
+
+ nc = *tmp;
+
+ tmp->Str().resize(1);
+ tmp->SetOrigColEnd(tmp->GetOrigCol() + 1);
+ tmp->SetType(CT_ASM_COLON);
+
+ nc.SetType(tmp->GetType());
+ nc.Str().pop_front();
+ nc.SetOrigCol(nc.GetOrigCol() + 1);
+ nc.SetColumn(nc.GetColumn() + 1);
+ nc.CopyAndAddAfter(tmp);
+ }
+ }
+ }
+
+ tmp = end->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+
+ if (tmp->Is(CT_SEMICOLON))
+ {
+ tmp->SetParentType(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->GetType()));
+ log_pcf_flags(LFCNR, prev->GetFlags());
+ LOG_FMT(LFCNR, "%s(%d): pc is '%s' %s\n",
+ __func__, __LINE__,
+ pc->Text(), get_token_name(pc->GetType()));
+ log_pcf_flags(LFCNR, pc->GetFlags());
+ LOG_FMT(LFCNR, "%s(%d): next is '%s' %s\n",
+ __func__, __LINE__,
+ next->Text(), get_token_name(next->GetType()));
+ log_pcf_flags(LFCNR, next->GetFlags());
+
+ if ( pc->Is(CT_NOEXCEPT) // Issue #3284
+ && next->Is(CT_ASSIGN)) // skip over noexcept
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc = next;
+ next = pc->GetNext();
+ }
+
+ // separate the uses of CT_ASSIGN sign '='
+ // into CT_ASSIGN_DEFAULT_ARG, CT_ASSIGN_FUNC_PROTO
+ if ( pc->Is(CT_ASSIGN)
+ && pc->GetParentType() == CT_FUNC_PROTO
+ && ( pc->TestFlags(PCF_IN_FCN_DEF) // Issue #2236
+ || pc->TestFlags(PCF_IN_CONST_ARGS)))
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ log_pcf_flags(LFCNR, pc->GetFlags());
+ pc->SetType(CT_ASSIGN_DEFAULT_ARG);
+ return;
+ }
+
+ if ( ( prev->Is(CT_FPAREN_CLOSE)
+ || ( ( prev->IsString("const")
+ || prev->IsString("override"))
+ && prev->GetPrev()->Is(CT_FPAREN_CLOSE)))
+ && pc->Is(CT_ASSIGN)
+ && ( next->Is(CT_DEFAULT)
+ || next->Is(CT_DELETE)
+ || next->IsString("0")))
+ {
+ pc->SetType(CT_ASSIGN_FUNC_PROTO);
+ return; // cpp 30031
+ }
+
+ if (pc->Is(CT_OC_AT))
+ {
+ if ( next->Is(CT_PAREN_OPEN)
+ || next->Is(CT_BRACE_OPEN)
+ || next->Is(CT_SQUARE_OPEN))
+ {
+ flag_parens(next, PCF_OC_BOXED, next->GetType(), CT_OC_AT, false);
+ }
+ else
+ {
+ next->SetParentType(CT_OC_AT);
+ return; // objective-c_50095
+ }
+ }
+
+ // D stuff
+ if ( language_is_set(LANG_D)
+ && pc->Is(CT_QUALIFIER)
+ && pc->IsString("const")
+ && next->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_D_CAST);
+ set_paren_parent(next, pc->GetType());
+ return; // d_40061
+ }
+
+ if ( next->Is(CT_PAREN_OPEN)
+ && ( pc->Is(CT_D_CAST)
+ || pc->Is(CT_DELEGATE)
+ || pc->Is(CT_ALIGN)))
+ {
+ // mark the parenthesis parent
+ Chunk *tmp = set_paren_parent(next, pc->GetType());
+
+ // For a D cast - convert the next item
+ if ( pc->Is(CT_D_CAST)
+ && tmp->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_STAR))
+ {
+ tmp->SetType(CT_DEREF);
+ return; // d_40006
+ }
+ else if (tmp->Is(CT_AMP))
+ {
+ tmp->SetType(CT_ADDR);
+ return; // d_40060
+ }
+ else if (tmp->Is(CT_MINUS))
+ {
+ tmp->SetType(CT_NEG);
+ return; // d_40060
+ }
+ else if (tmp->Is(CT_PLUS))
+ {
+ tmp->SetType(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 (pc->Is(CT_DELEGATE))
+ {
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(CT_DELEGATE);
+
+ if (tmp->GetLevel() == tmp->GetBraceLevel())
+ {
+ tmp->SetFlagBits(PCF_VAR_1ST_DEF);
+ }
+ }
+
+ for (tmp = pc->GetPrevNcNnlNi(); tmp->IsNotNullChunk(); tmp = tmp->GetPrevNcNnlNi()) // Issue #2279
+ {
+ if ( tmp->IsSemicolon()
+ || tmp->Is(CT_BRACE_OPEN)
+ || tmp->Is(CT_VBRACE_OPEN))
+ {
+ break;
+ }
+ make_type(tmp);
+ }
+
+ return; // c-sharp_10160
+ }
+
+ if ( pc->Is(CT_ALIGN)
+ && tmp->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ set_paren_parent(tmp, pc->GetType());
+ return; // d_40024
+ }
+ else if (tmp->Is(CT_COLON))
+ {
+ tmp->SetParentType(pc->GetType());
+ return; // d_40024
+ }
+ }
+ } // paren open + cast/align/delegate
+
+ if (pc->Is(CT_INVARIANT))
+ {
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ next->SetParentType(pc->GetType());
+ Chunk *tmp = next->GetNext();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_PAREN_CLOSE))
+ {
+ tmp->SetParentType(pc->GetType());
+ break;
+ }
+ make_type(tmp);
+ tmp = tmp->GetNext();
+ }
+ return; // d_40100
+ }
+ else
+ {
+ pc->SetType(CT_QUALIFIER);
+ return;
+ }
+ }
+
+ if ( prev->Is(CT_BRACE_OPEN)
+ && prev->GetParentType() != CT_CS_PROPERTY
+ && ( pc->Is(CT_GETSET)
+ || pc->Is(CT_GETSET_EMPTY)))
+ {
+ flag_parens(prev, PCF_NONE, CT_NONE, CT_GETSET, false);
+ return;
+ }
+
+ if (pc->Is(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 (pc->Is(CT_CARET))
+ {
+ if ( pc->TestFlags(PCF_EXPR_START)
+ || pc->TestFlags(PCF_IN_PREPROC))
+ {
+ handle_oc_block_literal(pc);
+ return;
+ }
+ }
+ }
+
+ // Objective C stuff
+ if (language_is_set(LANG_OC))
+ {
+ // Check for message declarations
+ if (pc->TestFlags(PCF_STMT_START))
+ {
+ if ( ( pc->IsString("-")
+ || pc->IsString("+"))
+ && next->IsString("("))
+ {
+ handle_oc_message_decl(pc);
+ return;
+ }
+ }
+
+ if ( pc->TestFlags(PCF_EXPR_START)
+ || pc->TestFlags(PCF_IN_PREPROC))
+ {
+ if (pc->Is(CT_SQUARE_OPEN))
+ {
+ handle_oc_message_send(pc);
+
+ // Only return early if the '[' was determined to be an OC MSG
+ // Otherwise, it could have been a lambda capture list (ie '[&]')
+ if (pc->GetParentType() == CT_OC_MSG)
+ {
+ return; // objective-c_50003
+ }
+ }
+ }
+
+ if (pc->Is(CT_OC_PROPERTY))
+ {
+ handle_oc_property_decl(pc);
+ return;
+ }
+
+ if (pc->Is(CT_OC_AVAILABLE))
+ {
+ handle_oc_available(pc);
+ return;
+ }
+ }
+
+ // C# and Vala stuff
+ if (language_is_set(LANG_CS | LANG_VALA))
+ {
+ // '[assembly: xxx]' stuff
+ if ( language_is_set(LANG_CS)
+ && pc->TestFlags(PCF_EXPR_START)
+ && pc->Is(CT_SQUARE_OPEN))
+ {
+ handle_cs_square_stmt(pc);
+ return;
+ }
+
+ if ( language_is_set(LANG_CS)
+ && next->Is(CT_BRACE_OPEN)
+ && next->GetParentType() == CT_NONE
+ && ( pc->Is(CT_SQUARE_CLOSE)
+ || pc->Is(CT_ANGLE_CLOSE)
+ || pc->Is(CT_WORD)))
+ {
+ handle_cs_property(next);
+ return;
+ }
+
+ if ( pc->Is(CT_SQUARE_CLOSE)
+ && next->Is(CT_WORD))
+ {
+ handle_cs_array_type(pc);
+ return;
+ }
+
+ if ( ( pc->Is(CT_LAMBDA)
+ || pc->Is(CT_DELEGATE))
+ && next->Is(CT_BRACE_OPEN))
+ {
+ set_paren_parent(next, pc->GetType());
+ return;
+ }
+
+ if ( language_is_set(LANG_CS)
+ && pc->Is(CT_WHEN)
+ && pc->GetNext()->IsNotNullChunk()
+ && pc->GetNext()->IsNot(CT_SPAREN_OPEN))
+ {
+ pc->SetType(CT_WORD);
+ return;
+ }
+ }
+
+ if ( language_is_set(LANG_JAVA)
+ && pc->Is(CT_LAMBDA)
+ && next->Is(CT_BRACE_OPEN))
+ {
+ set_paren_parent(next, pc->GetType());
+ return;
+ }
+
+ if (pc->Is(CT_NEW))
+ {
+ Chunk *ts = Chunk::NullChunkPtr;
+ Chunk *tmp = next;
+
+ if (tmp->Is(CT_TSQUARE))
+ {
+ ts = tmp;
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if ( tmp->Is(CT_BRACE_OPEN)
+ || tmp->Is(CT_PAREN_OPEN))
+ {
+ set_paren_parent(tmp, pc->GetType());
+
+ if (ts->IsNotNullChunk())
+ {
+ ts->SetParentType(pc->GetType());
+ }
+ }
+ return;
+ }
+
+ // C++11 Lambda stuff
+ if ( language_is_set(LANG_CPP)
+ && ( pc->Is(CT_SQUARE_OPEN)
+ || pc->Is(CT_TSQUARE)))
+ {
+ handle_cpp_lambda(pc);
+ }
+
+ // FIXME: which language does this apply to?
+ // Issue #2432
+ if (!language_is_set(LANG_OC))
+ {
+ if ( pc->Is(CT_ASSIGN)
+ && next->Is(CT_SQUARE_OPEN))
+ {
+ set_paren_parent(next, CT_ASSIGN);
+
+ // Mark one-liner assignment
+ Chunk *tmp = next;
+
+ while ((tmp = tmp->GetNextNc())->IsNotNullChunk())
+ {
+ if (tmp->IsNewline())
+ {
+ break;
+ }
+
+ if ( tmp->Is(CT_SQUARE_CLOSE)
+ && next->GetLevel() == tmp->GetLevel())
+ {
+ tmp->SetFlagBits(PCF_ONE_LINER);
+ next->SetFlagBits(PCF_ONE_LINER);
+ break;
+ }
+ }
+ return;
+ }
+ }
+
+ if (pc->Is(CT_ASSERT))
+ {
+ handle_java_assert(pc);
+ return;
+ }
+
+ if (pc->Is(CT_ANNOTATION))
+ {
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (tmp->IsParenOpen())
+ {
+ set_paren_parent(tmp, CT_ANNOTATION);
+ }
+ return;
+ }
+
+ if ( pc->Is(CT_SIZEOF)
+ && language_is_set(LANG_ALLC))
+ {
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (tmp->Is(CT_ELLIPSIS))
+ {
+ tmp->SetParentType(CT_SIZEOF);
+ }
+ return;
+ }
+
+ if ( pc->Is(CT_DECLTYPE)
+ && pc->GetParentType() != CT_FUNC_DEF)
+ {
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (tmp->IsParenOpen())
+ {
+ // decltype may be followed by a braced-init-list
+ tmp = set_paren_parent(tmp, CT_DECLTYPE);
+
+ if (tmp->IsBraceOpen() && !pc->TestFlags(PCF_IN_LAMBDA))
+ {
+ tmp = set_paren_parent(tmp, CT_BRACED_INIT_LIST);
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->ResetFlagBits(PCF_EXPR_START | PCF_STMT_START);
+ }
+ }
+ else
+ {
+ if (tmp->Is(CT_WORD))
+ {
+ tmp->SetFlagBits(PCF_VAR_1ST_DEF);
+ }
+ }
+ }
+ return;
+ }
+
+ // A [] in C#, D and Vala only follows a type
+ if ( pc->Is(CT_TSQUARE)
+ && language_is_set(LANG_D | LANG_CS | LANG_VALA))
+ {
+ if (prev->Is(CT_WORD))
+ {
+ prev->SetType(CT_TYPE);
+ }
+
+ if (next->Is(CT_WORD))
+ {
+ next->SetFlagBits(PCF_VAR_1ST_DEF);
+ }
+ return;
+ }
+
+ if ( pc->Is(CT_SQL_EXEC)
+ || pc->Is(CT_SQL_BEGIN)
+ || pc->Is(CT_SQL_END))
+ {
+ mark_exec_sql(pc);
+ return;
+ }
+
+ if (pc->Is(CT_PROTO_WRAP))
+ {
+ handle_proto_wrap(pc);
+ return;
+ }
+
+ // Handle the typedef
+ if (pc->Is(CT_TYPEDEF))
+ {
+ fix_typedef(pc);
+ return;
+ }
+
+ if ( pc->IsClassEnumStructOrUnion()
+ && prev->IsNot(CT_TYPEDEF))
+ {
+ // Issue #3811
+ // Sometimes the enum chunk can exist in a parameter (ie. `void foo(enum EnumType param)`)
+ // In this case we don't need to run the parser since we are not declaring an enum.
+ if (pc->IsEnum())
+ {
+ const size_t level = pc->GetLevel();
+ Chunk *tmp = pc;
+
+ while (tmp->GetLevel() == level && tmp->IsNotNullChunk())
+ {
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if (tmp->GetLevel() < level)
+ {
+ return;
+ }
+ }
+ EnumStructUnionParser parser;
+ parser.parse(pc);
+ return;
+ }
+
+ if (pc->Is(CT_EXTERN))
+ {
+ if (next->IsParenOpen())
+ {
+ Chunk *tmp = flag_parens(next, PCF_NONE, CT_NONE, CT_EXTERN, true);
+
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ set_paren_parent(tmp, CT_EXTERN);
+ }
+ }
+ else
+ {
+ // next likely is a string (see tokenize_cleanup.cpp)
+ next->SetParentType(CT_EXTERN);
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ set_paren_parent(tmp, CT_EXTERN);
+ }
+ }
+ return;
+ }
+
+ if (pc->Is(CT_TEMPLATE))
+ {
+ if (language_is_set(LANG_D))
+ {
+ handle_d_template(pc);
+ }
+ else
+ {
+ handle_cpp_template(pc);
+ }
+ return;
+ }
+
+ if ( pc->Is(CT_WORD)
+ && next->Is(CT_ANGLE_OPEN)
+ && next->GetParentType() == CT_TEMPLATE)
+ {
+ mark_template_func(pc, next);
+ return;
+ }
+
+ if ( pc->Is(CT_SQUARE_CLOSE)
+ && next->Is(CT_PAREN_OPEN))
+ {
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_NONE, false);
+ return;
+ }
+
+ if (pc->Is(CT_TYPE_CAST))
+ {
+ fix_type_cast(pc);
+ return;
+ }
+
+ if ( pc->GetParentType() == CT_ASSIGN
+ && ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_SQUARE_OPEN)))
+ {
+ // Mark everything in here as in assign
+ flag_parens(pc, PCF_IN_ARRAY_ASSIGN, pc->GetType(), CT_NONE, false);
+ return;
+ }
+
+ if (pc->Is(CT_D_TEMPLATE))
+ {
+ set_paren_parent(next, pc->GetType());
+ return;
+ }
+
+ /*
+ * A word before an open paren is a function call or definition.
+ * CT_WORD => CT_FUNC_CALL or CT_FUNC_DEF
+ */
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if ( language_is_set(LANG_C | LANG_CPP | LANG_OC)
+ && tmp->Is(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 ( ( tmp->Is(CT_OC_BLOCK_CARET)
+ || tmp->Is(CT_CARET))
+ && pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_CALL);
+ }
+ }
+ else if ( pc->Is(CT_WORD)
+ || pc->Is(CT_OPERATOR_VAL))
+ {
+ pc->SetType(CT_FUNCTION);
+ }
+ else if (pc->Is(CT_FIXED))
+ {
+ pc->SetType(CT_FUNCTION);
+ pc->SetParentType(CT_FIXED);
+ }
+ else if (pc->Is(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->GetOrigLine(), pc->GetOrigCol(), 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 (tmp->Is(CT_AMP))
+ {
+ auto tmp2 = tmp->GetNextNcNnl();
+
+ if (tmp2->Is(CT_WORD))
+ {
+ tmp2 = tmp2->GetNextNcNnl();
+ }
+
+ if (tmp2->Is(CT_PAREN_CLOSE))
+ {
+ tmp2 = tmp2->GetNextNcNnl();
+
+ if (tmp2->Is(CT_SQUARE_OPEN))
+ {
+ is_byref_array = true;
+ tmp->SetType(CT_BYREF);
+ }
+ }
+ }
+ }
+
+ if (!is_byref_array)
+ {
+ tmp = next->GetNextType(CT_PAREN_CLOSE, next->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = tmp->GetNext();
+
+ if (tmp->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_FUNCTION);
+ }
+ else
+ {
+ if ( pc->GetParentType() == CT_NONE
+ && !pc->TestFlags(PCF_IN_TYPEDEF))
+ {
+ tmp = next->GetNextNcNnl();
+
+ if (tmp->Is(CT_PAREN_CLOSE))
+ {
+ // we have TYPE()
+ pc->SetType(CT_FUNCTION);
+ }
+ else
+ {
+ // we have TYPE(...)
+ pc->SetType(CT_CPP_CAST);
+ set_paren_parent(next, CT_CPP_CAST);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (language_is_set(LANG_PAWN))
+ {
+ if ( pc->Is(CT_FUNCTION)
+ && pc->GetBraceLevel() > 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_CALL);
+ }
+
+ if ( pc->Is(CT_STATE)
+ && next->Is(CT_PAREN_OPEN))
+ {
+ set_paren_parent(next, pc->GetType());
+ }
+ }
+ else
+ {
+ if ( ( pc->Is(CT_FUNCTION)
+ || pc->Is(CT_FUNC_DEF))
+ && ( (pc->GetParentType() == CT_OC_BLOCK_EXPR)
+ || !is_oc_block(pc)))
+ {
+ mark_function(pc);
+ }
+ }
+
+ // Detect C99 member stuff
+ if ( pc->Is(CT_MEMBER)
+ && ( prev->Is(CT_COMMA)
+ || prev->Is(CT_BRACE_OPEN)))
+ {
+ pc->SetType(CT_C99_MEMBER);
+ next->SetParentType(CT_C99_MEMBER);
+ return;
+ }
+
+ // Mark function parens and braces
+ if ( pc->Is(CT_FUNC_DEF)
+ || pc->Is(CT_FUNC_CALL)
+ || pc->Is(CT_FUNC_CALL_USER)
+ || pc->Is(CT_FUNC_PROTO))
+ {
+ Chunk *tmp = next;
+
+ if (tmp->Is(CT_SQUARE_OPEN))
+ {
+ tmp = set_paren_parent(tmp, pc->GetType());
+ }
+ else if ( tmp->Is(CT_TSQUARE)
+ || tmp->GetParentType() == CT_OPERATOR)
+ {
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ if (tmp->IsParenOpen())
+ {
+ tmp = flag_parens(tmp, PCF_NONE, CT_FPAREN_OPEN, pc->GetType(), false);
+
+ if (tmp->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ if ( tmp->GetParentType() != CT_DOUBLE_BRACE
+ && !pc->TestFlags(PCF_IN_CONST_ARGS))
+ {
+ set_paren_parent(tmp, pc->GetType());
+ }
+ }
+ else if ( tmp->IsSemicolon()
+ && pc->Is(CT_FUNC_PROTO))
+ {
+ tmp->SetParentType(pc->GetType());
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ // Mark the parameters in catch()
+ if ( pc->Is(CT_CATCH)
+ && next->Is(CT_SPAREN_OPEN))
+ {
+ fix_fcn_def_params(next);
+ return;
+ }
+
+ if ( pc->Is(CT_THROW)
+ && prev->Is(CT_FPAREN_CLOSE))
+ {
+ pc->SetParentType(prev->GetParentType());
+
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ set_paren_parent(next, CT_THROW);
+ }
+ return;
+ }
+
+ // Mark the braces in: "for_each_entry(xxx) { }"
+ if ( pc->Is(CT_BRACE_OPEN)
+ && pc->GetParentType() != CT_DOUBLE_BRACE
+ && prev->Is(CT_FPAREN_CLOSE)
+ && ( prev->GetParentType() == CT_FUNC_CALL
+ || prev->GetParentType() == CT_FUNC_CALL_USER)
+ && !pc->TestFlags(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->GetOrigLine(), pc->GetOrigCol(), 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->TestFlags(PCF_IN_TEMPLATE) // Issue #3252
+ && pc->GetParentType() != CT_CPP_CAST
+ && pc->GetParentType() != CT_C_CAST
+ && !pc->TestFlags(PCF_IN_PREPROC)
+ && !is_oc_block(pc)
+ && pc->GetParentType() != CT_OC_MSG_DECL
+ && pc->GetParentType() != CT_OC_MSG_SPEC
+ && ( pc->IsString(")")
+ || pc->Is(CT_FUNC_TYPE))
+ && next->IsString("("))
+ {
+ 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 (pc->Is(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 ( pc->Is(CT_PAREN_OPEN)
+ && ( pc->GetParentType() == CT_NONE
+ || pc->GetParentType() == CT_OC_MSG
+ || pc->GetParentType() == CT_OC_BLOCK_EXPR
+ || pc->GetParentType() == CT_CS_SQ_STMT) // Issue # 1256
+ && ( next->Is(CT_WORD)
+ || next->Is(CT_TYPE)
+ || next->Is(CT_STRUCT)
+ || next->Is(CT_QUALIFIER)
+ || next->Is(CT_MEMBER)
+ || next->Is(CT_DC_MEMBER)
+ || next->Is(CT_ENUM)
+ || next->Is(CT_UNION))
+ && prev->IsNot(CT_DECLTYPE)
+ && prev->IsNot(CT_SIZEOF)
+ && prev->GetParentType() != CT_SIZEOF
+ && prev->GetParentType() != CT_OPERATOR
+ && !pc->TestFlags(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->GetFlags().test_any(PCF_IN_STRUCT | PCF_IN_CLASS)
+ && pc->Is(CT_ASSIGN)
+ && nnext->Is(CT_SEMICOLON)
+ && ( next->Is(CT_DEFAULT)
+ || next->Is(CT_DELETE)
+ || ( next->Is(CT_NUMBER)
+ && next->IsString("0"))))
+ {
+ const size_t level = pc->GetLevel();
+ bool found_status = false;
+ Chunk *pprev = pc->GetPrev();
+
+ for ( ; ( pprev->IsNotNullChunk()
+ && pprev->GetLevel() >= level
+ && pprev->IsNot(CT_SEMICOLON)
+ && pprev->IsNot(CT_ACCESS_COLON))
+ ; pprev = pprev->GetPrev())
+ {
+ if (pprev->GetLevel() != level)
+ {
+ continue;
+ }
+
+ if (next->Is(CT_NUMBER))
+ {
+ if ( pprev->Is(CT_QUALIFIER)
+ && pprev->IsString("virtual"))
+ {
+ found_status = true;
+ break;
+ }
+ }
+ else
+ {
+ if ( pprev->Is(CT_FUNC_CLASS_PROTO) // ctor/dtor
+ || pprev->Is(CT_FUNC_PROTO)) // normal function
+ {
+ found_status = true;
+ break;
+ }
+ }
+ }
+
+ if (found_status)
+ {
+ pc->SetParentType(pprev->GetType());
+ }
+ }
+
+ 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->TestFlags(PCF_EXPR_START)
+ || ( prev->TestFlags(PCF_EXPR_START)
+ && pc->GetParentType() == CT_OC_AT))
+ {
+ // Change STAR, MINUS, and PLUS in the easy cases
+ if (pc->Is(CT_STAR))
+ {
+ // issue #596
+ // [0x100062020:IN_SPAREN,IN_FOR,STMT_START,EXPR_START,PUNCTUATOR]
+ // prev->GetType() is CT_COLON ==> CT_DEREF
+ if (prev->Is(CT_ANGLE_CLOSE))
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if (prev->Is(CT_COLON))
+ {
+ pc->SetType(CT_DEREF);
+ }
+ else
+ {
+ pc->SetType(CT_DEREF);
+ }
+ }
+
+ if ( language_is_set(LANG_CPP)
+ && pc->Is(CT_CARET)
+ && prev->Is(CT_ANGLE_CLOSE))
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+
+ if ( language_is_set(LANG_CS | LANG_VALA)
+ && pc->Is(CT_QUESTION)
+ && prev->Is(CT_ANGLE_CLOSE))
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+
+ else if (pc->Is(CT_MINUS))
+ {
+ pc->SetType(CT_NEG);
+ }
+
+ else if (pc->Is(CT_PLUS))
+ {
+ pc->SetType(CT_POS);
+ }
+
+ else if (pc->Is(CT_INCDEC_AFTER))
+ {
+ pc->SetType(CT_INCDEC_BEFORE);
+ }
+
+ else if (pc->Is(CT_AMP))
+ {
+ if (prev->Is(CT_ANGLE_CLOSE)) // Issue #2324
+ {
+ pc->SetType(CT_BYREF);
+ }
+ else
+ {
+ pc->SetType(CT_ADDR);
+ }
+ }
+
+ else if (pc->Is(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 (pc->Is(CT_MACRO_FUNC))
+ {
+ flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_MACRO_FUNC, false);
+ }
+
+ if ( pc->Is(CT_MACRO_OPEN)
+ || pc->Is(CT_MACRO_ELSE)
+ || pc->Is(CT_MACRO_CLOSE))
+ {
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, pc->GetType(), false);
+ }
+ }
+
+ if ( pc->Is(CT_DELETE)
+ && next->Is(CT_TSQUARE))
+ {
+ next->SetParentType(CT_DELETE);
+ }
+
+ // Change CT_STAR to CT_PTR_TYPE or CT_ARITH or CT_DEREF
+ if ( pc->Is(CT_STAR)
+ || ( language_is_set(LANG_CPP)
+ && pc->Is(CT_CARET)))
+ {
+ if ( next->IsParenClose()
+ || next->Is(CT_COMMA))
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if ( language_is_set(LANG_OC)
+ && next->Is(CT_STAR))
+ {
+ /*
+ * Change pointer-to-pointer types in OC_MSG_DECLs
+ * from ARITH <===> DEREF to PTR_TYPE <===> PTR_TYPE
+ */
+ pc->SetType(CT_PTR_TYPE);
+ pc->SetParentType(prev->GetParentType());
+
+ next->SetType(CT_PTR_TYPE);
+ next->SetParentType(pc->GetParentType());
+ }
+ else if ( pc->Is(CT_STAR)
+ && ( prev->Is(CT_DECLTYPE)
+ || prev->Is(CT_SIZEOF)
+ || prev->Is(CT_DELETE)
+ || pc->GetParentType() == CT_SIZEOF))
+ {
+ pc->SetType(CT_DEREF);
+ }
+ else if ( ( prev->Is(CT_WORD)
+ && chunk_ends_type(prev)
+ && !prev->TestFlags(PCF_IN_FCN_CTOR)
+ && !prev->TestFlags(PCF_IN_ARRAY_ASSIGN)) // Issue #3345
+ || prev->Is(CT_DC_MEMBER)
+ || prev->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ log_pcf_flags(LFCNR, pc->GetFlags());
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if ( next->Is(CT_SQUARE_OPEN)
+ && !language_is_set(LANG_OC)) // Issue #408
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if (pc->Is(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, function call, return to distinguish between
+ // double result = Constants::PI * factor;
+ // and
+ // ::some::name * foo;
+ if ( prev->Is(CT_WORD)
+ && prev->GetPrev()->Is(CT_DC_MEMBER)
+ && language_is_set(LANG_CPP))
+ {
+ // Issue 1402
+ bool is_multiplication = false;
+ Chunk *tmp = pc;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( tmp->Is(CT_SEMICOLON)
+ || tmp->GetParentType() == CT_CLASS)
+ {
+ break;
+ }
+ else if ( tmp->Is(CT_ASSIGN)
+ || tmp->Is(CT_FUNC_CALL)
+ || tmp->Is(CT_RETURN))
+ {
+ is_multiplication = true;
+ break;
+ }
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ if (is_multiplication)
+ {
+ // double result = Constants::PI * factor;
+ pc->SetType(CT_ARITH);
+ }
+ else
+ {
+ // ::some::name * foo;
+ prev->SetType(CT_TYPE);
+ pc->SetType(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 (prev->Is(CT_TYPE))
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if ( pc->GetNext()->Is(CT_SEMICOLON) // Issue #2319
+ || ( pc->GetNext()->Is(CT_STAR)
+ && pc->GetNext()->GetNext()->Is(CT_SEMICOLON)))
+ {
+ // example:
+ // using AbstractLinkPtr = AbstractLink*;
+ // using AbstractLinkPtrPtr = AbstractLink**;
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if ( ( pc->GetParentType() == CT_FUNC_DEF
+ && ( next->IsBraceOpen()
+ || pc->GetNext()->IsStar()))
+ || next->Is(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 }}
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if ( pc->GetNext()->Is(CT_SEMICOLON) // Issue #2319
+ || ( pc->GetNext()->Is(CT_STAR)
+ && pc->GetNext()->GetNext()->Is(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->GetOrigLine(), pc->GetOrigCol());
+ fprintf(stderr, "Please make a report.\n");
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ else if ( !prev->TestFlags(PCF_PUNCTUATOR)
+ || prev->Is(CT_INCDEC_AFTER)
+ || prev->Is(CT_SQUARE_CLOSE)
+ || prev->Is(CT_DC_MEMBER)) // Issue 1402
+ {
+ pc->SetType(CT_ARITH);
+ }
+ else if ( !prev->IsParenClose()
+ || prev->Is(CT_SPAREN_CLOSE)
+ || prev->GetParentType() == CT_MACRO_FUNC)
+ {
+ pc->SetType(CT_DEREF);
+ }
+ else
+ {
+ pc->SetType(CT_ARITH);
+ }
+
+ if (pc->TestFlags(PCF_IN_TYPEDEF)) // Issue #1255/#633
+ {
+ Chunk *tmp = pc;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( tmp->Is(CT_SEMICOLON)
+ || tmp->Is(CT_BRACE_OPEN)
+ || tmp->Is(CT_SQUARE_OPEN)) // Issue #3342
+ {
+ break;
+ }
+ else if (tmp->Is(CT_TYPEDEF))
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+ }
+ }
+ }
+ }
+
+ if (pc->Is(CT_AMP))
+ {
+ Chunk *prevNext = prev->GetNext();
+
+ if (prev->Is(CT_DELETE))
+ {
+ pc->SetType(CT_ADDR);
+ }
+ else if ( prev->Is(CT_TYPE)
+ || prev->Is(CT_QUALIFIER)
+ || prevNext->Is(CT_QUALIFIER))
+ {
+ pc->SetType(CT_BYREF);
+ }
+ else if ( prev->Is(CT_WORD) // Issue #3204
+ && next->Is(CT_OPERATOR))
+ {
+ pc->SetType(CT_BYREF);
+ }
+ else if ( next->Is(CT_FPAREN_CLOSE)
+ || next->Is(CT_COMMA))
+ {
+ // fix the bug #654
+ // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &)));
+ pc->SetType(CT_BYREF);
+ }
+ else if (pc->GetParentType() == CT_USING_ALIAS)
+ {
+ // fix the Issue # 1689
+ // using reference = value_type &;
+ pc->GetPrev()->SetType(CT_TYPE);
+ pc->SetType(CT_BYREF);
+ }
+ else
+ {
+ // Issue # 1398
+ if ( pc->TestFlags(PCF_IN_FCN_DEF)
+ && prev->Is(CT_WORD)
+ && pc->Is(CT_AMP)
+ && next->Is(CT_WORD))
+ {
+ /*
+ * Change CT_WORD before CT_AMP before CT_WORD to CT_TYPE
+ */
+ prev->SetType(CT_TYPE);
+ }
+ else if ( pc->TestFlags(PCF_IN_PREPROC) // Issue #3559
+ && prev->IsNot(CT_WORD) // Issue #2205
+ && pc->Is(CT_AMP)
+ && next->Is(CT_WORD)
+ && !pc->TestFlags(PCF_IN_SPAREN))
+ {
+ pc->SetType(CT_ADDR);
+ }
+ else
+ {
+ pc->SetType(CT_ARITH);
+
+ if ( prev->Is(CT_WORD)
+ && next->IsNot(CT_NUMBER)) // Issue #3407
+ {
+ Chunk *tmp = prev->GetPrevNcNnlNi(); // Issue #2279
+
+ if (tmp->IsNotNullChunk())
+ {
+ if ( tmp->IsSemicolon()
+ || tmp->Is(CT_BRACE_OPEN)
+ || tmp->Is(CT_QUALIFIER))
+ {
+ pc->SetType(CT_BYREF);
+ prev->SetType(CT_TYPE);
+
+ if (!( next->Is(CT_OPERATOR)
+ || next->Is(CT_TYPE)
+ || next->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ next->SetFlagBits(PCF_VAR_1ST);
+ }
+ }
+ else if (tmp->Is(CT_DC_MEMBER))
+ {
+ // see also Issue #3967
+ // Issue #2103 & Issue #3865: partial fix
+ // No easy way to tell between an enum and a type with
+ // a namespace qualifier. Compromise: if we're in a
+ // function def or call, assume it's a ref.
+ Chunk *nextNext = next->GetNext();
+
+ if ( nextNext->IsNot(CT_DC_MEMBER)
+ && ( pc->TestFlags(PCF_IN_FCN_CALL)
+ || pc->TestFlags(PCF_IN_FCN_CTOR)
+ || pc->TestFlags(PCF_IN_FCN_DEF)))
+ {
+ pc->SetType(CT_BYREF);
+ }
+ else
+ {
+ prev->SetType(CT_TYPE);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( pc->Is(CT_MINUS)
+ || pc->Is(CT_PLUS))
+ {
+ if ( prev->Is(CT_POS)
+ || prev->Is(CT_NEG)
+ || prev->Is(CT_ARITH)
+ || prev->Is(CT_SHIFT))
+ {
+ pc->SetType(pc->Is(CT_MINUS) ? CT_NEG : CT_POS);
+ }
+ else if (prev->Is(CT_OC_CLASS))
+ {
+ pc->SetType((pc->Is(CT_MINUS)) ? CT_NEG : CT_POS);
+ }
+ else
+ {
+ pc->SetType(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 (pc->Is(CT_WORD)) // here NSString
+ {
+ Chunk *pcNext = pc->GetNext();
+ Chunk *pcPrev = pc->GetPrev();
+
+ if (pcNext->Is(CT_STAR)) // here *
+ {
+ // compare text with "C" to find extern "C" instructions
+ if (pcPrev->Is(CT_STRING))
+ {
+ if (UncText::compare(pcPrev->Text(), "\"C\"") == 0)
+ {
+ if (pcPrev->GetPrev()->Is(CT_EXTERN))
+ {
+ pc->SetType(CT_TYPE); // change CT_WORD => CT_TYPE
+ pcNext->SetType(CT_PTR_TYPE); // change CT_STAR => CT_PTR_TYPE
+ }
+ }
+ }
+ // Issue #322 STDMETHOD(GetValues)(BSTR bsName, REFDATA** pData);
+ Chunk *nnext = pcNext->GetNext();
+
+ if ( nnext->Is(CT_STAR)
+ && pc->TestFlags(PCF_IN_CONST_ARGS))
+ {
+ // change CT_STAR => CT_PTR_TYPE
+ pcNext->SetType(CT_PTR_TYPE);
+ nnext->SetType(CT_PTR_TYPE);
+ }
+
+ // Issue #222 whatever3 *(func_ptr)( whatever4 *foo2, ...
+ if ( nnext->Is(CT_WORD)
+ && pc->TestFlags(PCF_IN_FCN_DEF))
+ {
+ // look for the opening parenthesis
+ // Issue 1403
+ Chunk *tmp = pc->GetPrevType(CT_FPAREN_OPEN, pc->GetLevel() - 1);
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetParentType() != CT_FUNC_CTOR_VAR)
+ {
+ pcNext->SetType(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 (pc->Is(CT_WORD)) // here NSString
+ {
+ Chunk *pcNext = pc->GetNext();
+
+ if (pcNext->Is(CT_STAR)) // here *
+ {
+ Chunk *tmp = pc;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_ATTRIBUTE))
+ {
+ LOG_FMT(LFCNR, "%s(%d): ATTRIBUTE found, type is %s, Text() '%s'\n",
+ __func__, __LINE__, get_token_name(tmp->GetType()), tmp->Text());
+ LOG_FMT(LFCNR, "for token, type is %s, Text() '%s'\n", get_token_name(pc->GetType()), pc->Text());
+ // change CT_WORD => CT_TYPE
+ pc->SetType(CT_TYPE);
+ // change CT_STAR => CT_PTR_TYPE
+ pcNext->SetType(CT_PTR_TYPE);
+ }
+
+ if (tmp->TestFlags(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 (pc->Is(CT_USING))
+ {
+ // look for CT_ASSIGN before CT_SEMICOLON at the end of the statement
+
+ bool is_preproc = pc->TestFlags(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->GetOrigLine(), temp->GetOrigCol(),
+ temp->Text(), get_token_name(temp->GetType()));
+
+ if (temp->Is(CT_ASSIGN))
+ {
+ return(true);
+ }
+
+ if ( temp->Is(CT_SEMICOLON)
+ || ( is_preproc
+ && ( !temp->TestFlags(PCF_IN_PREPROC)
+ || temp->Is(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 (temp->GetParentType() == CT_NONE)
+ {
+ temp->SetParentType(CT_USING_ALIAS);
+ }
+
+ if ( temp->Is(CT_SEMICOLON)
+ || ( is_preproc
+ && ( !temp->TestFlags(PCF_IN_PREPROC)
+ || temp->Is(CT_PREPROC))))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ // Issue #548: inline T && someFunc(foo * *p, bar && q) { }
+ if ( pc->Is(CT_BOOL)
+ && !pc->TestFlags(PCF_IN_PREPROC)
+ && pc->IsString("&&")
+ && chunk_ends_type(pc->GetPrev()))
+ {
+ 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->GetOrigLine(), tmp->GetOrigCol(),
+ tmp->Text(), get_token_name(tmp->GetType()));
+ log_pcf_flags(LFCNR, tmp->GetFlags());
+ // look for a type
+
+ if (tmp->Is(CT_TYPE))
+ {
+ LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(),
+ pc->Text(), get_token_name(pc->GetType()));
+ log_pcf_flags(LFCNR, pc->GetFlags());
+ pc->SetType(CT_BYREF);
+ }
+ // look next, is there a "assign" before the ";"
+ Chunk *semi = pc->GetNextType(CT_SEMICOLON, pc->GetLevel()); // 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->GetOrigLine(), semi->GetOrigCol(),
+ semi->Text(), get_token_name(semi->GetType()));
+
+ 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->GetOrigLine(), test_it->GetOrigCol(),
+ test_it->Text(), get_token_name(test_it->GetType()));
+
+ if (test_it->Is(CT_ASSIGN))
+ {
+ // the statement is an assignment
+ // && is before assign
+ pc->SetType(CT_BYREF);
+ break;
+ }
+ }
+ }
+ }
+
+ // Issue #1704
+ if ( pc->Is(CT_INCDEC_AFTER)
+ && pc->TestFlags(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->GetOrigLine(), pc->GetOrigCol(),
+ pc->Text(), get_token_name(pc->GetType()));
+ log_pcf_flags(LFTYPE, pc->GetFlags());
+
+ if (tmp_2->Is(CT_WORD))
+ {
+ pc->SetType(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->GetOrigLine(), bo1->GetOrigCol());
+ Chunk *pc = bo1->GetPrevNcNnlNi(); // Issue #2279
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+
+ if (pc->IsParenClose())
+ {
+ Chunk *bo2 = bo1->GetNext();
+
+ if (bo2->IsNullChunk())
+ {
+ return;
+ }
+
+ if (bo2->Is(CT_BRACE_OPEN))
+ {
+ // found a potential double brace
+ Chunk *bc2 = bo2->GetClosingParen();
+
+ if (bc2->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *bc1 = bc2->GetNext();
+
+ if (bc1->IsNullChunk())
+ {
+ return;
+ }
+
+ if (bc1->Is(CT_BRACE_CLOSE))
+ {
+ LOG_FMT(LJDBI, " - end, orig line is %zu, orig col is %zu\n", bc2->GetOrigLine(), bc2->GetOrigCol());
+ // delete bo2 and bc1
+ bo1->Str() += bo2->GetStr();
+ bo1->SetOrigColEnd(bo2->GetOrigColEnd());
+ Chunk::Delete(bo2);
+ bo1->SetParentType(CT_DOUBLE_BRACE);
+
+ bc2->Str() += bc1->GetStr();
+ bc2->SetOrigColEnd(bc1->GetOrigColEnd());
+ Chunk::Delete(bc1);
+ bc2->SetParentType(CT_DOUBLE_BRACE);
+ return;
+ }
+ }
+ }
+ LOG_FMT(LJDBI, " - no\n");
+} // check_double_brace_init
+
+
+void fix_symbols()
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc;
+
+ 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())
+ {
+ LOG_FMT(LFCNR, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+
+ if ( pc->Is(CT_FUNC_WRAP)
+ || pc->Is(CT_TYPE_WRAP))
+ {
+ handle_wrap(pc);
+ }
+
+ if (pc->Is(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
+ && pc->Is(CT_BRACE_OPEN)
+ && ( prev->Is(CT_WORD)
+ || prev->Is(CT_TYPE)))
+ {
+ mark_lvalue(pc);
+ }
+
+ if ( is_java
+ && pc->Is(CT_BRACE_OPEN))
+ {
+ check_double_brace_init(pc);
+ }
+
+ if (pc->Is(CT_ATTRIBUTE))
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( next->IsNotNullChunk()
+ && next->Is(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 (pc->Is(CT_IGNORED))
+ {
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+ LOG_FMT(LFCNR, "%s(%d): pc orig line %zu, orig col %zu, text '%s', type %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ Chunk *prev = pc->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #2279
+
+ if (prev->Is(CT_QUALIFIER))
+ {
+ prev = prev->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #3513
+ }
+
+ if (prev->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): prev is NOT defined\n", __func__, __LINE__);
+ }
+ else
+ {
+ // Issue #2279
+ LOG_FMT(LFCNR, "%s(%d): prev(ni) orig line %zu, orig col %zu, text '%s', type %s\n",
+ __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text(), get_token_name(prev->GetType()));
+ }
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): next is NOT defined\n", __func__, __LINE__);
+ }
+ else
+ {
+ // Issue #2279
+ LOG_FMT(LFCNR, "%s(%d): next orig line %zu, orig col %zu, text '%s', type %s\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text(), get_token_name(next->GetType()));
+ }
+ LOG_FMT(LFCNR, "%s(%d): do_symbol_check for '%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_and_throws();
+
+ /*
+ * 2nd pass - handle variable definitions
+ * REVISIT: We need function params marked to do this (?)
+ */
+ pc = Chunk::GetHead();
+ int square_level = -1;
+
+ while (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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ // Can't have a variable definition inside [ ]
+ if (square_level < 0)
+ {
+ if (pc->Is(CT_SQUARE_OPEN))
+ {
+ square_level = pc->GetLevel();
+ }
+ }
+ else
+ {
+ if (pc->GetLevel() <= static_cast<size_t>(square_level))
+ {
+ square_level = -1;
+ }
+ }
+
+ if ( pc->Is(CT_EXTERN)
+ && language_is_set(LANG_ALLC))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->Is(CT_STRING))
+ {
+ Chunk *tmp = next->GetNextNcNnl();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( tmp->Is(CT_TYPE)
+ || tmp->Is(CT_BRACE_OPEN)
+ || tmp->Is(CT_ATTRIBUTE))
+ {
+ break;
+ }
+
+ if (tmp->Is(CT_WORD))
+ {
+ tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ log_ruleStart("start statement/ expression", tmp);
+ break;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+ }
+
+ if ( pc->Is(CT_ATTRIBUTE)
+ && language_is_set(LANG_ALLC))
+ {
+ Chunk *tmp = skip_attribute_next(pc);
+
+ if (tmp->Is(CT_WORD))
+ {
+ tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ log_ruleStart("start statement/ expression", tmp);
+ }
+ }
+
+ if ( pc->Is(CT_BRACE_OPEN) // Issue #2332
+ && pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc = pc->GetNextType(CT_BRACE_CLOSE, pc->GetLevel());
+ }
+ /*
+ * 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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+ log_pcf_flags(LFCNR, pc->GetFlags());
+
+ if ( (square_level < 0)
+ && pc->TestFlags(PCF_STMT_START)
+ && ( pc->Is(CT_QUALIFIER)
+ || pc->Is(CT_TYPE)
+ || pc->Is(CT_TYPENAME)
+ || pc->Is(CT_DC_MEMBER) // Issue #2478
+ || ( pc->Is(CT_WORD)
+ && !pc->TestFlags(PCF_IN_CONDITIONAL) // Issue #3558
+// && language_is_set(LANG_CPP)
+ )
+ )
+ && pc->GetParentType() != CT_BIT_COLON
+ && pc->GetParentType() != CT_ENUM_COLON // Issue #4040
+ && pc->GetParentType() != CT_ENUM
+ && !pc->TestFlags(PCF_IN_CLASS_BASE)
+ && !pc->TestFlags(PCF_IN_ENUM))
+ {
+ pc = fix_variable_definition(pc);
+ }
+ else
+ {
+ pc = pc->GetNextNcNnl();
+ }
+ }
+} // fix_symbols
+
+
+static void process_returns_and_throws()
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc;
+
+ pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( pc->Is(CT_RETURN)
+ || pc->Is(CT_THROW))
+ {
+ pc = process_return_or_throw(pc);
+ }
+ else
+ {
+ pc = pc->GetNext();
+ }
+ }
+}
+
+
+static Chunk *process_return_or_throw(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ const char *nl_expr_name;
+ iarf_e nl_expr_value;
+ const char *mod_paren_name;
+ iarf_e mod_paren_value;
+
+ if (pc->Is(CT_RETURN))
+ {
+ nl_expr_name = "nl_return_expr";
+ nl_expr_value = options::nl_return_expr();
+ mod_paren_name = "mod_paren_on_return";
+ mod_paren_value = options::mod_paren_on_return();
+ }
+ else if (pc->Is(CT_THROW))
+ {
+ nl_expr_name = "nl_throw_expr";
+ nl_expr_value = options::nl_throw_expr();
+ mod_paren_name = "mod_paren_on_throw";
+ mod_paren_value = options::mod_paren_on_throw();
+ }
+ else // should never happen
+ {
+ return(pc->GetNext());
+ }
+ 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()
+ || next->IsSemicolon()
+ || next->Is(CT_NEWLINE))
+ {
+ return(next);
+ }
+ log_rule_B(nl_expr_name);
+
+ if ( nl_expr_value != IARF_IGNORE
+ && !pc->TestFlags(PCF_IN_PREPROC))
+ {
+ newline_iarf(pc, nl_expr_value);
+ }
+
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ // See if the return/throw is fully paren'd
+ cpar = next->GetNextType(CT_PAREN_CLOSE, next->GetLevel());
+
+ if (cpar->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ semi = cpar->PpaGetNextNcNnl();
+
+ if (semi->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+
+ if ( semi->Is(CT_NEWLINE)
+ || semi->IsSemicolon())
+ {
+ log_rule_B(mod_paren_name);
+
+ if (mod_paren_value == IARF_REMOVE)
+ {
+ LOG_FMT(LRETURN, "%s(%d): removing parens on orig line %zu\n",
+ __func__, __LINE__, pc->GetOrigLine());
+
+ // lower the level of everything
+ for (temp = next; temp != cpar; temp = temp->GetNext())
+ {
+ if (temp->GetLevel() == 0)
+ {
+ fprintf(stderr, "%s(%d): temp->GetLevel() is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, temp->GetOrigLine(), temp->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ temp->SetLevel(temp->GetLevel() - 1);
+ }
+
+ // delete the parenthesis
+ Chunk::Delete(next);
+ Chunk::Delete(cpar);
+
+ // back up following chunks
+ temp = semi;
+
+ while ( temp->IsNotNullChunk()
+ && temp->IsNot(CT_NEWLINE))
+ {
+ temp->SetColumn(temp->GetColumn() - 2);
+ temp->SetOrigCol(temp->GetOrigCol() - 2);
+ temp->SetOrigColEnd(temp->GetOrigColEnd() - 2);
+ temp = temp->GetNext();
+ }
+ }
+ else
+ {
+ LOG_FMT(LRETURN, "%s(%d): keeping parens on orig line %zu\n",
+ __func__, __LINE__, pc->GetOrigLine());
+
+ // mark & keep them
+ next->SetParentType(pc->GetType());
+ cpar->SetParentType(pc->GetType());
+ }
+ return(semi);
+ }
+ }
+ // We don't have a fully paren'd return/throw. Should we add some?
+ log_rule_B(mod_paren_name);
+
+ if (!(mod_paren_value & 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)
+ && next->Is(CT_BRACE_OPEN)
+ && next->GetParentType() == CT_BRACED_INIT_LIST)
+ {
+ LOG_FMT(LRETURN, "%s(%d): not adding parens around braced initializer"
+ " on orig line %zd\n",
+ __func__, __LINE__, pc->GetOrigLine());
+ return(next);
+ }
+ // find the next semicolon on the same level
+ semi = next;
+
+ if (pc->TestFlags(PCF_IN_PREPROC))
+ {
+ while ((semi = semi->GetNext())->IsNotNullChunk())
+ {
+ if (!semi->TestFlags(PCF_IN_PREPROC))
+ {
+ break;
+ }
+
+ if (semi->GetLevel() < pc->GetLevel())
+ {
+ return(semi);
+ }
+
+ if ( semi->IsSemicolon()
+ && pc->GetLevel() == semi->GetLevel())
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ while ((semi = semi->GetNext())->IsNotNullChunk())
+ {
+ if (semi->GetLevel() < pc->GetLevel())
+ {
+ return(semi);
+ }
+
+ if ( semi->IsSemicolon()
+ && pc->GetLevel() == semi->GetLevel())
+ {
+ break;
+ }
+ }
+ }
+
+ if (semi->IsNotNullChunk())
+ {
+ // add the parenthesis
+ chunk.SetType(CT_PAREN_OPEN);
+ chunk.SetParentType(pc->GetType());
+ chunk.Str() = "(";
+ chunk.SetLevel(pc->GetLevel());
+ chunk.SetPpLevel(pc->GetPpLevel());
+ chunk.SetBraceLevel(pc->GetBraceLevel());
+ chunk.SetOrigLine(pc->GetOrigLine());
+ chunk.SetOrigCol(next->GetOrigCol() - 1);
+ chunk.SetFlags(pc->GetFlags() & PCF_COPY_FLAGS);
+ chunk.CopyAndAddBefore(next);
+
+ chunk.SetType(CT_PAREN_CLOSE);
+ chunk.Str() = ")";
+ chunk.SetOrigLine(semi->GetOrigLine());
+ chunk.SetOrigCol(semi->GetOrigCol() - 1);
+ cpar = chunk.CopyAndAddBefore(semi);
+
+ LOG_FMT(LRETURN, "%s(%d): added parens on orig line %zu\n",
+ __func__, __LINE__, pc->GetOrigLine());
+
+ for (temp = next; temp != cpar; temp = temp->GetNext())
+ {
+ temp->SetLevel(temp->GetLevel() + 1);
+ }
+ }
+ return(semi);
+} // process_return_or_throw
+
+
+static bool is_oc_block(Chunk *pc)
+{
+ return( pc->GetParentType() == CT_OC_BLOCK_TYPE
+ || pc->GetParentType() == CT_OC_BLOCK_EXPR
+ || pc->GetParentType() == CT_OC_BLOCK_ARG
+ || pc->GetParentType() == CT_OC_BLOCK
+ || pc->Is(CT_OC_BLOCK_CARET)
+ || pc->GetNext()->Is(CT_OC_BLOCK_CARET)
+ || pc->GetPrev()->Is(CT_OC_BLOCK_CARET));
+}
+
+
+void mark_comments()
+{
+ 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() || next->IsNewline();
+
+ if (cur->IsComment())
+ {
+ if ( next_nl
+ && prev_nl)
+ {
+ cur->SetParentType(CT_COMMENT_WHOLE);
+ }
+ else if (next_nl)
+ {
+ cur->SetParentType(CT_COMMENT_END);
+ }
+ else if (prev_nl)
+ {
+ cur->SetParentType(CT_COMMENT_START);
+ }
+ else
+ {
+ cur->SetParentType(CT_COMMENT_EMBED);
+ }
+ }
+ prev_nl = cur->IsNewline();
+ cur = next;
+ }
+}
+
+
+static void handle_cpp_template(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *tmp = pc->GetNextNcNnl();
+
+ if (tmp->IsNot(CT_ANGLE_OPEN))
+ {
+ return;
+ }
+ tmp->SetParentType(CT_TEMPLATE);
+
+ size_t level = tmp->GetLevel();
+
+ tmp = tmp->GetNext();
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( tmp->Is(CT_CLASS)
+ || tmp->Is(CT_STRUCT))
+ {
+ tmp->SetType(CT_TYPE);
+ }
+ else if ( tmp->Is(CT_ANGLE_CLOSE)
+ && tmp->GetLevel() == level)
+ {
+ tmp->SetParentType(CT_TEMPLATE);
+ break;
+ }
+ tmp = tmp->GetNext();
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = tmp->GetNextNcNnl();
+
+ if (tmp->Is(CT_FRIEND))
+ {
+ // Account for a template friend declaration
+ tmp->SetParentType(CT_TEMPLATE);
+
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if (tmp->IsClassOrStruct())
+ {
+ tmp->SetParentType(CT_TEMPLATE);
+
+ // REVISIT: This may be a bit risky - might need to track the { };
+ tmp = tmp->GetNextType(CT_SEMICOLON, tmp->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(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 null chunk\n", __func__, __LINE__);
+ }
+
+ if ( prev->IsNullChunk()
+ || ( prev->IsNot(CT_ASSIGN)
+ && prev->IsNot(CT_COMMA)
+ && prev->IsNot(CT_PAREN_OPEN) // allow Js like self invoking lambda syntax: ([](){})();
+ && prev->IsNot(CT_FPAREN_OPEN)
+ && prev->IsNot(CT_SQUARE_OPEN)
+ && prev->IsNot(CT_BRACE_OPEN)
+ && prev->IsNot(CT_SEMICOLON)
+ && prev->IsNot(CT_RETURN)))
+ {
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+ Chunk *sq_c = sq_o; // assuming '[]'
+
+ if (sq_o->Is(CT_SQUARE_OPEN))
+ {
+ // make sure there is a ']'
+ sq_c = sq_o->GetClosingParen();
+
+ if (sq_c->IsNullChunk())
+ {
+ 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 (pa_o->Is(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 (pa_o->Is(CT_PAREN_OPEN))
+ {
+ // and now find the ')'
+ pa_c = pa_o->GetClosingParen();
+
+ 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 (br_o->IsString("mutable"))
+ {
+ br_o = br_o->GetNextNcNnl();
+ }
+ //TODO: also check for exception and attribute between [] ... {}
+
+ // skip possible arrow syntax: '-> ret'
+ if (br_o->IsString("->"))
+ {
+ ret = br_o;
+ // REVISIT: really should check the stuff we are skipping
+ br_o = br_o->GetNextType(CT_BRACE_OPEN, br_o->GetLevel());
+ }
+
+ // skip possible CT_NOEXCEPT
+ if (br_o->Is(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->GetLevel());
+ }
+
+ if (br_o->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): br_o is null. Return\n", __func__, __LINE__);
+ return;
+ }
+
+ if (br_o->IsNot(CT_BRACE_OPEN))
+ {
+ LOG_FMT(LFCNR, "%s(%d): br_o is '%s'/%s\n",
+ __func__, __LINE__,
+ br_o->Text(), get_token_name(br_o->GetType()));
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+ // and now find the '}'
+ Chunk *br_c = br_o->GetClosingParen();
+
+ if (br_c->IsNullChunk())
+ {
+ LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__);
+ return;
+ }
+
+ // This looks like a lambda expression
+ if (sq_o->Is(CT_TSQUARE))
+ {
+ // split into two chunks
+ Chunk nc;
+
+ nc = *sq_o;
+ sq_o->SetType(CT_SQUARE_OPEN);
+ sq_o->Str().resize(1);
+ /*
+ * bug # 664
+ *
+ * The original m_origCol of CT_SQUARE_CLOSE is stored at m_origColEnd
+ * of CT_TSQUARE. CT_SQUARE_CLOSE m_origCol and m_origColEnd values
+ * are calculate from m_origColEnd of CT_TSQUARE.
+ */
+ nc.SetOrigCol(sq_o->GetOrigColEnd() - 1);
+ nc.SetColumn(nc.GetOrigCol());
+ nc.SetOrigColEnd(sq_o->GetOrigColEnd());
+ sq_o->SetOrigColEnd(sq_o->GetOrigCol() + 1);
+
+ nc.SetType(CT_SQUARE_CLOSE);
+ nc.Str().pop_front();
+ sq_c = nc.CopyAndAddAfter(sq_o);
+ }
+ sq_o->SetParentType(CT_CPP_LAMBDA);
+ sq_c->SetParentType(CT_CPP_LAMBDA);
+
+ if (pa_c->IsNotNullChunk())
+ {
+ pa_o->SetType(CT_LPAREN_OPEN); // Issue #3054
+ pa_o->SetParentType(CT_CPP_LAMBDA);
+ pa_o->SetParent(sq_o);
+ br_o->SetParent(sq_o);
+ pa_c->SetType(CT_LPAREN_CLOSE);
+ pa_c->SetParentType(CT_CPP_LAMBDA);
+ pa_c->SetParent(sq_o);
+ br_c->SetParent(sq_o);
+ }
+ br_o->SetParentType(CT_CPP_LAMBDA);
+ br_c->SetParentType(CT_CPP_LAMBDA);
+
+ if (ret->IsNotNullChunk())
+ {
+ ret->SetType(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 (call_pa_o->Is(CT_PAREN_OPEN))
+ {
+ Chunk *call_pa_c = call_pa_o->GetClosingParen();
+
+ if (call_pa_c->IsNotNullChunk())
+ {
+ call_pa_o->SetType(CT_FPAREN_OPEN);
+ call_pa_o->SetParentType(CT_FUNC_CALL);
+ call_pa_c->SetType(CT_FPAREN_CLOSE);
+ call_pa_c->SetParentType(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->IsNullChunk()
+ || name->IsNot(CT_WORD))
+ {
+ // TODO: log an error, expected NAME
+ return;
+ }
+
+ if ( po->IsNullChunk()
+ || po->IsNot(CT_PAREN_OPEN))
+ {
+ // TODO: log an error, expected '('
+ return;
+ }
+ name->SetType(CT_TYPE);
+ name->SetParentType(CT_TEMPLATE);
+ po->SetParentType(CT_TEMPLATE);
+
+ ChunkStack cs;
+ Chunk *tmp = get_d_template_types(cs, po);
+
+ if ( tmp->IsNullChunk()
+ || tmp->IsNot(CT_PAREN_CLOSE))
+ {
+ // TODO: log an error, expected ')'
+ return;
+ }
+ tmp->SetParentType(CT_TEMPLATE);
+
+ tmp = tmp->GetNextNcNnl();
+
+ if (tmp->IsNot(CT_BRACE_OPEN))
+ {
+ // TODO: log an error, expected '{'
+ return;
+ }
+ tmp->SetParentType(CT_TEMPLATE);
+ po = tmp;
+ tmp = tmp->GetNextNcNnl();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->GetLevel() > po->GetLevel())
+ {
+ if ( tmp->Is(CT_WORD)
+ && chunkstack_match(cs, tmp))
+ {
+ tmp->SetType(CT_TYPE);
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+// if (!tmp->Is(CT_BRACE_CLOSE))
+// {
+// // TODO: log an error, expected '}'
+// }
+ tmp->SetParentType(CT_TEMPLATE);
+} // handle_d_template
+
+
+Chunk *skip_template_next(Chunk *ang_open)
+{
+ if (ang_open->Is(CT_ANGLE_OPEN))
+ {
+ Chunk *pc = ang_open->GetNextType(CT_ANGLE_CLOSE, ang_open->GetLevel());
+
+ 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(pc->GetParentType()), pc->GetOrigLine());
+
+ if (pc->GetParentType() == CT_OC_PROTOCOL)
+ {
+ tmp = pc->GetNextNcNnl();
+
+ if (tmp->IsSemicolon())
+ {
+ tmp->SetParentType(pc->GetParentType());
+ LOG_FMT(LOCCLASS, "%s(%d): bail on semicolon\n", __func__, __LINE__);
+ return;
+ }
+ }
+ tmp = pc;
+
+ while ((tmp = tmp->GetNextNnl())->IsNotNullChunk())
+ {
+ LOG_FMT(LOCCLASS, "%s(%d): orig line is %zu, [%s]\n",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->Text());
+
+ if (tmp->Is(CT_OC_END))
+ {
+ break;
+ }
+
+ if (tmp->Is(CT_PAREN_OPEN))
+ {
+ passed_name = true;
+ }
+
+ if (tmp->IsString("<"))
+ {
+ tmp->SetType(CT_ANGLE_OPEN);
+
+ if (passed_name)
+ {
+ tmp->SetParentType(CT_OC_PROTO_LIST);
+ }
+ else
+ {
+ tmp->SetParentType(CT_OC_GENERIC_SPEC);
+ generic_level++;
+ }
+ as = angle_state_e::OPEN;
+ }
+
+ if (tmp->IsString(">"))
+ {
+ tmp->SetType(CT_ANGLE_CLOSE);
+
+ if (passed_name)
+ {
+ tmp->SetParentType(CT_OC_PROTO_LIST);
+ as = angle_state_e::CLOSE;
+ }
+ else
+ {
+ tmp->SetParentType(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->GetOrigLine(), tmp->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ generic_level--;
+
+ if (generic_level == 0)
+ {
+ as = angle_state_e::CLOSE;
+ }
+ }
+ }
+
+ if (tmp->IsString(">>"))
+ {
+ tmp->SetType(CT_ANGLE_CLOSE);
+ tmp->SetParentType(CT_OC_GENERIC_SPEC);
+ split_off_angle_close(tmp);
+ generic_level -= 1;
+
+ if (generic_level == 0)
+ {
+ as = angle_state_e::CLOSE;
+ }
+ }
+
+ if ( tmp->Is(CT_BRACE_OPEN)
+ && tmp->GetParentType() != CT_ASSIGN)
+ {
+ as = angle_state_e::CLOSE;
+ tmp->SetParentType(CT_OC_CLASS);
+ tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->GetLevel());
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetParentType() != CT_ASSIGN)
+ {
+ tmp->SetParentType(CT_OC_CLASS);
+ }
+ }
+ else if (tmp->Is(CT_COLON))
+ {
+ if (as != angle_state_e::OPEN)
+ {
+ passed_name = true;
+ }
+ tmp->SetType(hit_scope ? CT_OC_COLON : CT_CLASS_COLON);
+
+ if (tmp->Is(CT_CLASS_COLON))
+ {
+ tmp->SetParentType(CT_OC_CLASS);
+ }
+ }
+ else if ( tmp->IsString("-")
+ || tmp->IsString("+"))
+ {
+ as = angle_state_e::CLOSE;
+
+ if (tmp->GetPrev()->IsNewline())
+ {
+ tmp->SetType(CT_OC_SCOPE);
+ tmp->SetFlagBits(PCF_STMT_START);
+ log_ruleStart("start statement", tmp);
+ hit_scope = true;
+ }
+ }
+
+ if (as == angle_state_e::OPEN)
+ {
+ if (passed_name)
+ {
+ tmp->SetParentType(CT_OC_PROTO_LIST);
+ }
+ else
+ {
+ tmp->SetParentType(CT_OC_GENERIC_SPEC);
+ }
+ }
+ }
+
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(CT_OC_CLASS);
+ }
+ }
+} // handle_oc_class
+
+
+static void handle_oc_block_literal(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ 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->GetOrigLine(), pc->GetOrigCol());
+
+ 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 (tmp->IsString("<"))
+ {
+ Chunk *ao = tmp;
+ Chunk *ac = ao->GetNextString(">", 1, ao->GetLevel());
+
+ if (ac->IsNotNullChunk())
+ {
+ ao->SetType(CT_ANGLE_OPEN);
+ ao->SetParentType(CT_OC_PROTO_LIST);
+ ac->SetType(CT_ANGLE_CLOSE);
+ ac->SetParentType(CT_OC_PROTO_LIST);
+
+ for (tmp = ao->GetNext(); tmp != ac; tmp = tmp->GetNext())
+ {
+ tmp->SetLevel(tmp->GetLevel() + 1);
+ tmp->SetParentType(CT_OC_PROTO_LIST);
+ }
+
+ tmp = ac->GetNextNcNnl();
+ }
+ else
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+ }
+ LOG_FMT(LOCBLK, " '%s'", tmp->Text());
+
+ if ( tmp->GetLevel() < pc->GetLevel()
+ || tmp->Is(CT_SEMICOLON))
+ {
+ LOG_FMT(LOCBLK, "[DONE]");
+ break;
+ }
+
+ if (tmp->GetLevel() == pc->GetLevel())
+ {
+ if (tmp->IsParenOpen())
+ {
+ apo = tmp;
+ LOG_FMT(LOCBLK, "[PAREN]");
+ }
+
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ LOG_FMT(LOCBLK, "[BRACE]");
+ bbo = tmp;
+ break;
+ }
+ }
+ }
+
+ // make sure we have braces
+ bbc = bbo->GetClosingParen();
+
+ if ( bbo->IsNullChunk()
+ || bbc->IsNullChunk())
+ {
+ LOG_FMT(LOCBLK, " -- no braces found\n");
+ return;
+ }
+ LOG_FMT(LOCBLK, "\n");
+
+ // we are on a block literal for sure
+ pc->SetType(CT_OC_BLOCK_CARET);
+ pc->SetParentType(CT_OC_BLOCK_EXPR);
+
+ // handle the optional args
+ Chunk *lbp; // last before paren - end of return type, if any
+
+ if (apo->IsNotNullChunk())
+ {
+ Chunk *apc = apo->GetClosingParen(); // arg parenthesis close
+
+ if (apc->IsParenClose())
+ {
+ LOG_FMT(LOCBLK, " -- marking parens @ apo orig line is %zu, orig col is %zu and apc orig line is %zu, orig col is %zu\n",
+ apo->GetOrigLine(), apo->GetOrigCol(), apc->GetOrigLine(), apc->GetOrigCol());
+ 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->GetType()));
+ make_type(lbp);
+ lbp->SetFlagBits(PCF_OC_RTYPE);
+ lbp->SetParentType(CT_OC_BLOCK_EXPR);
+ lbp = lbp->GetPrevNcNnlNi(); // Issue #2279
+ }
+ // mark the braces
+ bbo->SetParentType(CT_OC_BLOCK_EXPR);
+ bbc->SetParentType(CT_OC_BLOCK_EXPR);
+
+ // mark the OC_BLOCK
+ for (Chunk *tmp1 = bbo; tmp1 != bbc; tmp1 = tmp1->GetNextNcNnl())
+ {
+ tmp1->SetFlagBits(PCF_OC_IN_BLOCK);
+ }
+} // handle_oc_block_literal
+
+
+static void handle_oc_block_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+
+ if (pc->TestFlags(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->GetOrigLine(), pc->GetOrigCol());
+ return;
+ }
+ // make sure we have '( ^'
+ Chunk *tpo = pc->GetPrevNcNnlNi(); // type paren open Issue #2279
+
+ if (tpo->IsParenOpen())
+ {
+ /*
+ * block type: 'RTYPE (^LABEL)(ARGS)'
+ * LABEL is optional.
+ */
+ Chunk *tpc = tpo->GetClosingParen(); // type close paren (after '^')
+ Chunk *nam = tpc->GetPrevNcNnlNi(); // name (if any) or '^' Issue #2279
+ Chunk *apo = tpc->GetNextNcNnl(); // arg open paren
+ Chunk *apc = apo->GetClosingParen(); // 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 (nam->IsBraceClose())
+ {
+ return(handle_oc_block_literal(pc));
+ }
+
+ // Check apo is '(' or else this might be a block literal. Issue 2643.
+ if (!apo->IsParenOpen())
+ {
+ return(handle_oc_block_literal(pc));
+ }
+
+ if (apc->IsParenClose())
+ {
+ Chunk *aft = apc->GetNextNcNnl();
+ E_Token pt;
+
+ if (nam->IsString("^"))
+ {
+ nam->SetType(CT_PTR_TYPE);
+ pt = CT_FUNC_TYPE;
+ }
+ else if ( aft->Is(CT_ASSIGN)
+ || aft->Is(CT_SEMICOLON))
+ {
+ nam->SetType(CT_FUNC_VAR);
+ pt = CT_FUNC_VAR;
+ }
+ else
+ {
+ nam->SetType(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->GetOrigLine(), pc->GetOrigCol(), nam->Text(), get_token_name(nam->GetType()));
+ pc->SetType(CT_PTR_TYPE);
+ pc->SetParentType(pt); //CT_OC_BLOCK_TYPE;
+ tpo->SetType(CT_TPAREN_OPEN);
+ tpo->SetParentType(pt); //CT_OC_BLOCK_TYPE;
+ tpc->SetType(CT_TPAREN_CLOSE);
+ tpc->SetParentType(pt); //CT_OC_BLOCK_TYPE;
+ apo->SetType(CT_FPAREN_OPEN);
+ apo->SetParentType(CT_FUNC_PROTO);
+ apc->SetType(CT_FPAREN_CLOSE);
+ apc->SetParentType(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, PcfFlags flags, bool &did_it)
+{
+ Chunk *paren_close;
+
+ if ( !paren_open->IsParenOpen()
+ || ((paren_close = paren_open->GetClosingParen())->IsNullChunk()))
+ {
+ did_it = false;
+ return(paren_open);
+ }
+ did_it = true;
+
+ paren_open->SetParentType(ptype);
+ paren_open->SetFlagBits(flags);
+ paren_close->SetParentType(ptype);
+ paren_close->SetFlagBits(flags);
+
+ for (Chunk *cur = paren_open->GetNextNcNnl();
+ cur != paren_close;
+ cur = cur->GetNextNcNnl())
+ {
+ LOG_FMT(LOCMSGD, " <%s|%s>", cur->Text(), get_token_name(cur->GetType()));
+ cur->SetFlagBits(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;
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if (tmp->GetLevel() < pc->GetLevel())
+ {
+ // should not happen
+ return;
+ }
+
+ if ( tmp->Is(CT_SEMICOLON)
+ || tmp->Is(CT_BRACE_OPEN))
+ {
+ break;
+ }
+ }
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+ E_Token pt = tmp->Is(CT_SEMICOLON) ? CT_OC_MSG_SPEC : CT_OC_MSG_DECL;
+
+ pc->SetType(CT_OC_SCOPE);
+ pc->SetParentType(pt);
+
+ LOG_FMT(LOCMSGD, "%s(%d): %s @ orig line is %zu, orig col is %zu -",
+ __func__, __LINE__, get_token_name(pt), pc->GetOrigLine(), pc->GetOrigCol());
+
+ // 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 (tmp->IsNot(CT_WORD))
+ {
+ LOG_FMT(LOCMSGD, " -- missing method name\n");
+ return;
+ } // expect the method name/label
+
+ Chunk *label = tmp;
+
+ tmp->SetType(pt);
+ tmp->SetParentType(pt);
+ pc = tmp->GetNextNcNnl();
+
+ LOG_FMT(LOCMSGD, " [%s]%s", pc->Text(), get_token_name(pc->GetType()));
+
+ // if we have a colon next, we have args
+ if ( pc->Is(CT_COLON)
+ || pc->Is(CT_OC_COLON))
+ {
+ pc = label;
+
+ while (true)
+ {
+ // skip optional label
+ if ( pc->Is(CT_WORD)
+ || pc->Is(pt))
+ {
+ pc->SetParentType(pt);
+ pc = pc->GetNextNcNnl();
+ }
+
+ // a colon must be next
+ if (!pc->IsString(":"))
+ {
+ break;
+ }
+ pc->SetType(CT_OC_COLON);
+ pc->SetParentType(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->GetOrigLine(), pc->GetOrigCol());
+ 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
+ pc->SetFlagBits(PCF_VAR_DEF);
+ LOG_FMT(LOCMSGD, " arg[%s]", pc->Text());
+ pc = pc->GetNextNcNnl();
+ }
+ }
+ LOG_FMT(LOCMSGD, " end[%s]", pc->Text());
+
+ if (pc->Is(CT_BRACE_OPEN))
+ {
+ pc->SetParentType(pt);
+ pc = pc->GetClosingParen();
+
+ if (pc->IsNotNullChunk())
+ {
+ pc->SetParentType(pt);
+ }
+ }
+ else if (pc->Is(CT_SEMICOLON))
+ {
+ pc->SetParentType(pt);
+ }
+ LOG_FMT(LOCMSGD, "\n");
+} // handle_oc_message_decl
+
+
+static void handle_oc_message_send(Chunk *os)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *cs = os->GetNext();
+
+ while ( cs->IsNotNullChunk()
+ && cs->GetLevel() > os->GetLevel())
+ {
+ cs = cs->GetNext();
+ }
+
+ if ( cs->IsNullChunk()
+ || cs->IsNot(CT_SQUARE_CLOSE))
+ {
+ return;
+ }
+ LOG_FMT(LOCMSG, "%s(%d): orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, os->GetOrigLine(), os->GetOrigCol());
+
+ Chunk *tmp = cs->GetNextNcNnl();
+
+ if (tmp->IsSemicolon())
+ {
+ tmp->SetParentType(CT_OC_MSG);
+ }
+ // expect a word first thing or [...]
+ tmp = os->GetNextNcNnl();
+
+ if ( tmp->Is(CT_SQUARE_OPEN)
+ || tmp->Is(CT_PAREN_OPEN)
+ || tmp->Is(CT_OC_AT))
+ {
+ Chunk *tt = tmp->GetNextNcNnl();
+
+ if ( tmp->Is(CT_OC_AT)
+ && tt->IsNotNullChunk())
+ {
+ if ( tt->Is(CT_PAREN_OPEN)
+ || tt->Is(CT_BRACE_OPEN)
+ || tt->Is(CT_SQUARE_OPEN))
+ {
+ tmp = tt;
+ }
+ else
+ {
+ LOG_FMT(LOCMSG, "%s(%d): tmp orig line is %zu, orig col is %zu, expected identifier, not '%s' [%s]\n",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(),
+ tmp->Text(), get_token_name(tmp->GetType()));
+ return;
+ }
+ }
+ tmp = tmp->GetClosingParen();
+ }
+ else if ( tmp->IsNot(CT_WORD)
+ && tmp->IsNot(CT_TYPE)
+ && tmp->IsNot(CT_THIS)
+ && tmp->IsNot(CT_STAR)
+ && tmp->IsNot(CT_STRING))
+ {
+ LOG_FMT(LOCMSG, "%s(%d): orig line is %zu, orig col is %zu, expected identifier, not '%s' [%s]\n",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(),
+ tmp->Text(), get_token_name(tmp->GetType()));
+ return;
+ }
+ else
+ {
+ if (tmp->IsStar()) // Issue #2722
+ {
+ tmp->SetType(CT_PTR_TYPE);
+ tmp = tmp->GetNextNcNnl();
+ }
+ Chunk *tt = tmp->GetNextNcNnl();
+
+ if (tt->IsParenOpen())
+ {
+ 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->GetOrigLine(), tmp->GetOrigCol(), tmp->Text());
+ tmp->SetType(CT_FUNC_CALL);
+ tmp = set_paren_parent(tt, CT_FUNC_CALL)->GetPrevNcNnlNi(); // Issue #2279
+ }
+ else
+ {
+ tmp->SetType(CT_OC_MSG_CLASS);
+ }
+ }
+ os->SetParentType(CT_OC_MSG);
+ os->SetFlagBits(PCF_IN_OC_MSG);
+ cs->SetParentType(CT_OC_MSG);
+ cs->SetFlagBits(PCF_IN_OC_MSG);
+
+ // handle '< protocol >'
+ tmp = tmp->GetNextNcNnl();
+
+ if (tmp->IsString("<"))
+ {
+ Chunk *ao = tmp;
+ Chunk *ac = ao->GetNextString(">", 1, ao->GetLevel());
+
+ if (ac->IsNotNullChunk())
+ {
+ ao->SetType(CT_ANGLE_OPEN);
+ ao->SetParentType(CT_OC_PROTO_LIST);
+ ac->SetType(CT_ANGLE_CLOSE);
+ ac->SetParentType(CT_OC_PROTO_LIST);
+
+ for (tmp = ao->GetNext(); tmp != ac; tmp = tmp->GetNext())
+ {
+ tmp->SetLevel(tmp->GetLevel() + 1);
+ tmp->SetParentType(CT_OC_PROTO_LIST);
+ }
+
+ tmp = ac->GetNextNcNnl();
+ }
+ else
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+ }
+ // handle 'object.property' and 'collection[index]'
+ else
+ {
+ while (tmp->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_MEMBER)) // move past [object.prop1.prop2
+ {
+ Chunk *typ = tmp->GetNextNcNnl();
+
+ if ( typ->Is(CT_WORD)
+ || typ->Is(CT_TYPE))
+ {
+ tmp = typ->GetNextNcNnl();
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if (tmp->Is(CT_SQUARE_OPEN)) // move past [collection[index]
+ {
+ Chunk *tcs = tmp->GetNextNcNnl();
+
+ while ( tcs->IsNotNullChunk()
+ && tcs->GetLevel() > tmp->GetLevel())
+ {
+ tcs = tcs->GetNextNcNnl();
+ }
+
+ if (tcs->Is(CT_SQUARE_CLOSE))
+ {
+ tmp = tcs->GetNextNcNnl();
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ // [(self.foo.bar) method]
+ if (tmp->IsParenOpen())
+ {
+ tmp = tmp->GetClosingParen()->GetNextNcNnl();
+ }
+
+ if ( tmp->Is(CT_WORD)
+ || tmp->Is(CT_ACCESS)
+ || tmp->Is(CT_TYPE))
+ {
+ tmp->SetType(CT_OC_MSG_FUNC);
+ }
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ for (tmp = os->GetNext(); tmp != cs; tmp = tmp->GetNext())
+ {
+ tmp->SetFlagBits(PCF_IN_OC_MSG);
+
+ if (tmp->GetLevel() == cs->GetLevel() + 1)
+ {
+ if ( tmp->Is(CT_COLON)
+ || tmp->Is(CT_ACCESS_COLON))
+ {
+ tmp->SetType(CT_OC_COLON);
+
+ if ( prev->Is(CT_WORD)
+ || prev->Is(CT_ACCESS)
+ || prev->Is(CT_TYPE))
+ {
+ // Might be a named param, check previous block
+ Chunk *pp = prev->GetPrev();
+
+ if ( pp->IsNotNullChunk()
+ && pp->IsNot(CT_OC_COLON)
+ && pp->IsNot(CT_ARITH)
+ && pp->IsNot(CT_SHIFT)
+ && pp->IsNot(CT_CARET))
+ {
+ prev->SetType(CT_OC_MSG_NAME);
+ tmp->SetParentType(CT_OC_MSG_NAME);
+ }
+ }
+ }
+ }
+ prev = tmp;
+ }
+} // handle_oc_message_send
+
+
+static void handle_oc_available(Chunk *os)
+{
+ os = os->GetNext();
+
+ while (os->IsNotNullChunk())
+ {
+ E_Token origType = os->GetType();
+ os->SetType(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 = os->GetNext();
+ Chunk *open_paren = Chunk::NullChunkPtr;
+
+ 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 (next->Is(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()
+ && next->IsNot(CT_PAREN_CLOSE))
+ {
+ if (next->Is(CT_OC_PROPERTY_ATTR))
+ {
+ if ( next->IsString("atomic")
+ || next->IsString("nonatomic"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ thread_chunks.push_back(chunkGroup);
+ }
+ else if ( next->IsString("readonly")
+ || next->IsString("readwrite"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ readwrite_chunks.push_back(chunkGroup);
+ }
+ else if ( next->IsString("assign")
+ || next->IsString("retain")
+ || next->IsString("copy")
+ || next->IsString("strong")
+ || next->IsString("weak")
+ || next->IsString("unsafe_unretained"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ ref_chunks.push_back(chunkGroup);
+ }
+ else if (next->IsString("getter"))
+ {
+ ChunkGroup chunkGroup;
+
+ do
+ {
+ chunkGroup.push_back(next);
+ next = next->GetNext();
+ } while ( next->IsNotNullChunk()
+ && next->IsNot(CT_COMMA)
+ && next->IsNot(CT_PAREN_CLOSE));
+
+ next = next->GetPrev();
+
+ // coverity CID 160946
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ getter_chunks.push_back(chunkGroup);
+ }
+ else if (next->IsString("setter"))
+ {
+ ChunkGroup chunkGroup;
+
+ do
+ {
+ chunkGroup.push_back(next);
+ next = next->GetNext();
+ } while ( next->IsNotNullChunk()
+ && next->IsNot(CT_COMMA)
+ && next->IsNot(CT_PAREN_CLOSE));
+
+ if (next->IsNotNullChunk())
+ {
+ next = next->GetPrev();
+ }
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ setter_chunks.push_back(chunkGroup);
+ }
+ else if ( next->IsString("nullable")
+ || next->IsString("nonnull")
+ || next->IsString("null_resettable")
+ || next->IsString("null_unspecified"))
+ {
+ ChunkGroup chunkGroup;
+ chunkGroup.push_back(next);
+ nullability_chunks.push_back(chunkGroup);
+ }
+ else if (next->IsString("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 (next->IsWord())
+ {
+ if (next->IsString("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->SetOrigPrevSp(0);
+
+ if (chunk != curr_chunk)
+ {
+ chunk->MoveAfter(curr_chunk);
+ curr_chunk = chunk;
+ }
+ else
+ {
+ curr_chunk = curr_chunk->GetNext();
+ }
+ }
+
+ // add the parenthesis
+ Chunk endchunk;
+ endchunk.SetType(CT_COMMA);
+ endchunk.SetParentType(curr_chunk->GetParentType());
+ endchunk.Str() = ",";
+ endchunk.SetLevel(curr_chunk->GetLevel());
+ endchunk.SetPpLevel(curr_chunk->GetPpLevel());
+ endchunk.SetBraceLevel(curr_chunk->GetBraceLevel());
+ endchunk.SetOrigLine(curr_chunk->GetOrigLine());
+ endchunk.SetOrigCol(curr_chunk->GetOrigCol());
+ endchunk.SetColumn(curr_chunk->GetOrigColEnd() + 1);
+ endchunk.SetFlags(curr_chunk->GetFlags() & PCF_COPY_FLAGS);
+ endchunk.CopyAndAddAfter(curr_chunk);
+ curr_chunk = curr_chunk->GetNext();
+ }
+ }
+
+ // Remove the extra comma's that we did not move
+ while ( curr_chunk->IsNotNullChunk()
+ && curr_chunk->IsNot(CT_PAREN_CLOSE))
+ {
+ Chunk *rm_chunk = curr_chunk;
+ curr_chunk = curr_chunk->GetNext();
+ Chunk::Delete(rm_chunk);
+ }
+ }
+ }
+ Chunk *tmp = os->GetNextNcNnl();
+
+ if (tmp->IsParenOpen())
+ {
+ tmp = tmp->GetClosingParen()->GetNextNcNnl();
+ }
+ fix_variable_definition(tmp);
+} // handle_oc_property_decl
+
+
+static void handle_cs_square_stmt(Chunk *os)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *cs = os->GetNext();
+
+ while ( cs->IsNotNullChunk()
+ && cs->GetLevel() > os->GetLevel())
+ {
+ cs = cs->GetNext();
+ }
+
+ if ( cs->IsNullChunk()
+ || cs->IsNot(CT_SQUARE_CLOSE))
+ {
+ return;
+ }
+ os->SetParentType(CT_CS_SQ_STMT);
+ cs->SetParentType(CT_CS_SQ_STMT);
+
+ Chunk *tmp;
+
+ for (tmp = os->GetNext(); tmp != cs; tmp = tmp->GetNext())
+ {
+ tmp->SetParentType(CT_CS_SQ_STMT);
+
+ if (tmp->Is(CT_COLON))
+ {
+ tmp->SetType(CT_CS_SQ_COLON);
+ }
+ }
+
+ tmp = cs->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ log_ruleStart("start statement/ expression", tmp);
+ }
+} // 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->GetLevel() == bro->GetLevel())
+ {
+ //prevent scanning back past 'new' in expressions like new List<int> {1,2,3}
+ // Issue # 1620, UNI-24090.cs
+ if (pc->Is(CT_NEW))
+ {
+ break;
+ }
+
+ if ( !did_prop
+ && ( pc->Is(CT_WORD)
+ || pc->Is(CT_THIS)))
+ {
+ pc->SetType(CT_CS_PROPERTY);
+ did_prop = true;
+ }
+ else
+ {
+ pc->SetParentType(CT_CS_PROPERTY);
+ make_type(pc);
+ }
+
+ if (pc->TestFlags(PCF_STMT_START))
+ {
+ break;
+ }
+ }
+ }
+}
+
+
+static void handle_cs_array_type(Chunk *pc)
+{
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *prev = pc->GetPrev();
+
+ for ( ;
+ prev->Is(CT_COMMA);
+ prev = prev->GetPrev())
+ {
+ // empty
+ }
+
+ if (prev->Is(CT_SQUARE_OPEN))
+ {
+ while (pc != prev)
+ {
+ pc->SetParentType(CT_TYPE);
+ pc = pc->GetPrev();
+ }
+ prev->SetParentType(CT_TYPE);
+ }
+}
+
+
+static void handle_wrap(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *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 = pc->Is(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 = pc->Is(CT_FUNC_WRAP) ?
+ options::sp_inside_fparen() :
+ options::sp_inside_paren_cast();
+
+ if ( clp->Is(CT_PAREN_CLOSE)
+ && opp->Is(CT_PAREN_OPEN)
+ && ( name->Is(CT_WORD)
+ || name->Is(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->GetStr());
+ pc->Str().append(fsp);
+ pc->Str().append(")");
+
+ pc->SetType(pc->Is(CT_FUNC_WRAP) ? CT_FUNCTION : CT_TYPE);
+
+ pc->SetOrigColEnd(pc->GetOrigCol() + pc->Len());
+
+ Chunk::Delete(opp);
+ Chunk::Delete(name);
+ Chunk::Delete(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 = opp->GetClosingParen();
+ Chunk *cma = clp->GetNextNcNnl();
+
+ if ( opp->IsNullChunk()
+ || name->IsNullChunk()
+ || tmp->IsNullChunk()
+ || clp->IsNullChunk()
+ || cma->IsNullChunk()
+ || ( name->IsNot(CT_WORD)
+ && name->IsNot(CT_TYPE))
+ || opp->IsNot(CT_PAREN_OPEN))
+ {
+ return;
+ }
+
+ if (cma->Is(CT_SEMICOLON))
+ {
+ pc->SetType(CT_FUNC_PROTO);
+ }
+ else if (cma->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_DEF);
+ }
+ else
+ {
+ return;
+ }
+ opp->SetParentType(pc->GetType());
+ clp->SetParentType(pc->GetType());
+
+ tmp->SetParentType(CT_PROTO_WRAP);
+
+ if (tmp->Is(CT_PAREN_OPEN))
+ {
+ fix_fcn_def_params(tmp);
+ }
+ else
+ {
+ fix_fcn_def_params(opp);
+ name->SetType(CT_WORD);
+ }
+ tmp = tmp->GetClosingParen();
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(CT_PROTO_WRAP);
+ }
+ // Mark return type (TODO: move to own function)
+ tmp = pc;
+
+ while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ if ( !tmp->IsTypeDefinition()
+ && tmp->IsNot(CT_OPERATOR)
+ && tmp->IsNot(CT_WORD)
+ && tmp->IsNot(CT_ADDR))
+ {
+ break;
+ }
+ tmp->SetParentType(pc->GetType());
+ 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;
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if (tmp->GetLevel() == pc->GetLevel())
+ {
+ if ( !did_colon
+ && tmp->Is(CT_COLON))
+ {
+ did_colon = true;
+ tmp->SetParentType(pc->GetType());
+ }
+
+ if (tmp->Is(CT_SEMICOLON))
+ {
+ tmp->SetParentType(pc->GetType());
+ break;
+ }
+ }
+ }
+} // handle_java_assert
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.h
new file mode 100644
index 00000000..a121449b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine.h
@@ -0,0 +1,75 @@
+/**
+ * @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();
+
+
+/**
+ * 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();
+
+
+//! help function for mark_variable_definition...
+bool go_on(Chunk *pc, Chunk *start);
+
+
+//! Sets the parent for comments.
+void mark_comments();
+
+
+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.
+ */
+void do_symbol_check(Chunk *prev, Chunk *pc, Chunk *next);
+
+
+#endif /* COMBINE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_fix_mark.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_fix_mark.cpp
new file mode 100644
index 00000000..ff487e92
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_fix_mark.cpp
@@ -0,0 +1,2651 @@
+/**
+ * @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 = Chunk::NullChunkPtr;
+ 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->GetOrigLine(), start->GetOrigCol());
+
+ prev = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+
+ if (prev->Is(CT_PP_DEFINED))
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - after defined\n",
+ __func__, __LINE__);
+ return;
+ }
+
+ if (prev->Is(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()
+ && ( pc->IsTypeDefinition()
+ || pc->Is(CT_WORD)
+ || pc->Is(CT_QUALIFIER)
+ || pc->Is(CT_DC_MEMBER)
+ || pc->Is(CT_PP)
+ || pc->Is(CT_STAR)
+ || pc->Is(CT_QUESTION)
+ || pc->Is(CT_CARET)
+ || pc->Is(CT_TSQUARE)
+ || ( ( pc->Is(CT_ANGLE_OPEN)
+ || pc->Is(CT_ANGLE_CLOSE))
+ && language_is_set(LANG_OC | LANG_JAVA | LANG_CS | LANG_VALA | LANG_CPP))
+ || ( ( pc->Is(CT_QUESTION)
+ || pc->Is(CT_COMMA)
+ || pc->Is(CT_MEMBER))
+ && language_is_set(LANG_JAVA | LANG_CS | LANG_VALA))
+ || ( pc->Is(CT_COMMA)
+ && language_is_set(LANG_CPP))
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+
+ if ( pc->Is(CT_WORD)
+ || ( last->Is(CT_ANGLE_CLOSE)
+ && pc->Is(CT_DC_MEMBER)))
+ {
+ word_count++;
+ }
+ else if ( pc->Is(CT_DC_MEMBER)
+ || pc->Is(CT_MEMBER)
+ || pc->Is(CT_PP))
+ {
+ // might be negative, such as with:
+ // a = val + (CFoo::bar_t)7;
+ word_count--;
+ }
+ last = pc;
+ pc = pc->GetNextNcNnl();
+ count++;
+ }
+
+ if ( pc->IsNullChunk()
+ || pc->IsNot(CT_PAREN_CLOSE)
+ || prev->Is(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->GetType()));
+ 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 ( last->Is(CT_STAR)
+ || last->Is(CT_CARET)
+ || last->Is(CT_PTR_TYPE)
+ || last->Is(CT_TYPE)
+ || ( last->Is(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->GetStr()[last->Len() - 2] == '_')
+ && (last->GetStr()[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)
+ && last->IsString("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 (after->Is(CT_PAREN_OPEN));
+
+ if (after->IsNullChunk())
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - hit null chunk\n",
+ __func__, __LINE__);
+ return;
+ }
+ nope = false;
+
+ if (pc->IsPointerOperator())
+ {
+ // star (*) and address (&) are ambiguous
+ if ( after->Is(CT_NUMBER_FP)
+ || after->Is(CT_NUMBER)
+ || after->Is(CT_STRING)
+ || doubtful_cast)
+ {
+ nope = true;
+ }
+ }
+ else if (pc->Is(CT_MINUS))
+ {
+ // (UINT8)-1 or (foo)-1 or (FOO)-'a'
+ if ( after->Is(CT_STRING)
+ || doubtful_cast)
+ {
+ nope = true;
+ }
+ }
+ else if (pc->Is(CT_PLUS))
+ {
+ // (UINT8)+1 or (foo)+1
+ if ( ( after->IsNot(CT_NUMBER)
+ && after->IsNot(CT_NUMBER_FP))
+ || doubtful_cast)
+ {
+ nope = true;
+ }
+ }
+ else if ( pc->IsNot(CT_NUMBER_FP)
+ && pc->IsNot(CT_NUMBER)
+ && pc->IsNot(CT_WORD)
+ && pc->IsNot(CT_THIS)
+ && pc->IsNot(CT_TYPE)
+ && pc->IsNot(CT_PAREN_OPEN)
+ && pc->IsNot(CT_STRING)
+ && pc->IsNot(CT_DECLTYPE)
+ && pc->IsNot(CT_SIZEOF)
+ && pc->GetParentType() != CT_SIZEOF
+ && pc->IsNot(CT_FUNC_CALL)
+ && pc->IsNot(CT_FUNC_CALL_USER)
+ && pc->IsNot(CT_FUNCTION)
+ && pc->IsNot(CT_BRACE_OPEN)
+ && (!( pc->Is(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->GetType()));
+ 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->GetType()));
+ 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 ( pc->IsSemicolon()
+ || pc->Is(CT_COMMA)
+ || pc->Is(CT_BOOL) // Issue #2151
+ || pc->IsParenClose())
+ {
+ LOG_FMT(LCASTS, "%s(%d): -- not a cast - followed by type %s\n",
+ __func__, __LINE__, get_token_name(pc->GetType()));
+ return;
+ }
+ start->SetParentType(CT_C_CAST);
+ paren_close->SetParentType(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())
+ {
+ pc->SetParentType(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())
+ {
+ pc->SetFlagBits(PCF_EXPR_START);
+
+ if (pc->IsBraceOpen())
+ {
+ set_paren_parent(pc, start->GetParentType());
+ }
+ }
+} // fix_casts
+
+
+void fix_fcn_def_params(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start->IsNullChunk())
+ {
+ 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->GetType()), start->GetOrigLine(), start->GetLevel());
+
+ while ( start->IsNotNullChunk()
+ && !start->IsParenOpen())
+ {
+ start = start->GetNextNcNnl();
+ }
+
+ if (start->IsNullChunk()) // Coverity CID 76003, 1100782
+ {
+ return;
+ }
+ // ensure start chunk holds a single '(' character
+ assert( (start->Len() == 1)
+ && (start->GetStr()[0] == '('));
+
+ ChunkStack cs;
+ size_t level = start->GetLevel() + 1;
+ Chunk *pc = start->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( ( (start->Len() == 1)
+ && (start->GetStr()[0] == ')'))
+ || pc->GetLevel() < level)
+ {
+ LOG_FMT(LFCNP, "%s(%d): bailed on Text() '%s', on orig line %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ break;
+ }
+ LOG_FMT(LFCNP, "%s(%d): %s, Text() '%s' on orig line %zu, level %zu\n",
+ __func__, __LINE__, (pc->GetLevel() > level) ? "skipping" : "looking at",
+ pc->Text(), pc->GetOrigLine(), pc->GetLevel());
+
+ if (pc->GetLevel() > level)
+ {
+ pc = pc->GetNextNcNnl();
+ continue;
+ }
+
+ if ( pc->IsStar()
+ || pc->IsMsRef()
+ || pc->IsNullable())
+ {
+ pc->SetType(CT_PTR_TYPE);
+ cs.Push_Back(pc);
+ }
+ else if ( language_is_set(LANG_CPP) // Issue #3662
+ && ( pc->Is(CT_AMP)
+ || pc->IsString("&&")))
+ {
+ pc->SetType(CT_BYREF);
+ cs.Push_Back(pc);
+ }
+ else if (pc->Is(CT_TYPE_WRAP))
+ {
+ cs.Push_Back(pc);
+ }
+ else if ( pc->Is(CT_WORD)
+ || pc->Is(CT_TYPE))
+ {
+ cs.Push_Back(pc);
+ }
+ else if ( pc->Is(CT_COMMA)
+ || pc->Is(CT_ASSIGN))
+ {
+ mark_variable_stack(cs, LFCNP);
+
+ if (pc->Is(CT_ASSIGN))
+ {
+ // Mark assignment for default param spacing
+ pc->SetParentType(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->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *pc = start->GetNextNcNnl();
+
+ if ( pc->IsNullChunk()
+ || pc->IsNot(CT_ANGLE_OPEN))
+ {
+ return;
+ }
+ pc = pc->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() >= start->GetLevel())
+ {
+ if ( pc->GetLevel() == start->GetLevel()
+ && pc->Is(CT_ANGLE_CLOSE))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+
+ if (pc->IsString("("))
+ {
+ 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->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LTYPEDEF, "%s(%d): typedef @ orig line %zu, orig col %zu\n",
+ __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol());
+
+ 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->GetLevel() >= start->GetLevel()
+ ; next = next->GetNextNcNnl(E_Scope::PREPROC))
+ {
+ next->SetFlagBits(PCF_IN_TYPEDEF);
+
+ if (start->GetLevel() == next->GetLevel())
+ {
+ if (next->IsSemicolon())
+ {
+ next->SetParentType(CT_TYPEDEF);
+ break;
+ }
+
+ if (next->Is(CT_ATTRIBUTE))
+ {
+ break;
+ }
+
+ if ( language_is_set(LANG_D)
+ && next->Is(CT_ASSIGN))
+ {
+ next->SetParentType(CT_TYPEDEF);
+ break;
+ }
+ make_type(next);
+
+ if (next->Is(CT_TYPE))
+ {
+ the_type = next;
+ }
+ next->ResetFlagBits(PCF_VAR_1ST_DEF);
+
+ if (*next->GetStr().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)
+ && last_op->GetParentType() == 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 = Chunk::NullChunkPtr;
+
+ if (the_type->IsParenClose())
+ {
+ open_paren = the_type->GetOpeningParen();
+ 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);"
+ the_type->SetType(CT_FUNC_TYPE);
+ }
+ the_type->SetParentType(CT_TYPEDEF);
+
+ LOG_FMT(LTYPEDEF, "%s(%d): fcn typedef Text() '%s', on orig line %zu\n",
+ __func__, __LINE__, the_type->Text(), the_type->GetOrigLine());
+
+ // If we are aligning on the open parenthesis, grab that instead
+ log_rule_B("align_typedef_func");
+
+ if ( open_paren->IsNotNullChunk()
+ && 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->GetOrigLine(), the_type->GetOrigCol());
+ the_type->SetFlagBits(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 ( after->IsNot(CT_ENUM)
+ && after->IsNot(CT_STRUCT)
+ && after->IsNot(CT_UNION))
+ {
+ if (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->GetOrigLine());
+ the_type->SetFlagBits(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 (next->Is(CT_TYPE))
+ {
+ next = next->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ }
+
+ if (next->Is(CT_BRACE_OPEN))
+ {
+ // Skip to the closing brace
+ Chunk *br_c = next->GetNextType(CT_BRACE_CLOSE, next->GetLevel(), E_Scope::PREPROC);
+
+ if (br_c->IsNotNullChunk())
+ {
+ const E_Token tag = after->GetType();
+ next->SetParentType(tag);
+ br_c->SetParentType(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->IsNotNullChunk())
+ {
+ LOG_FMT(LTYPEDEF, "%s(%d): %s typedef Text() %s, on orig line %zu\n",
+ __func__, __LINE__, get_token_name(after->GetType()), the_type->Text(),
+ the_type->GetOrigLine());
+ the_type->SetFlagBits(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, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_pcf_flags(LFCNR, pc->GetFlags());
+
+ // Scan for words and types and stars oh my!
+ while ( pc->Is(CT_TYPE)
+ || pc->Is(CT_WORD)
+ || pc->Is(CT_QUALIFIER)
+ || pc->Is(CT_TYPENAME)
+ || pc->Is(CT_DC_MEMBER)
+ || pc->Is(CT_MEMBER)
+ || pc->Is(CT_PP) // Issue #3169
+ || pc->IsPointerOperator())
+ {
+ LOG_FMT(LFVD, "%s(%d): 1:pc->Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()));
+ 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->GetType()));
+
+ // 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->GetType()));
+
+ 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->GetType()));
+
+ 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->GetType()));
+ }
+ else
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ }
+ }
+ end = pc;
+
+ if (end->IsNullChunk())
+ {
+ LOG_FMT(LFVD, "%s(%d): end is null chunk\n", __func__, __LINE__);
+ return(Chunk::NullChunkPtr);
+ }
+ LOG_FMT(LFVD, "%s(%d): end->GetType() is %s\n", __func__, __LINE__, get_token_name(end->GetType()));
+
+ if (end->Is(CT_FUNC_CTOR_VAR)) // Issue #3010
+ {
+ return(end);
+ }
+
+ if ( cs.Len() == 1
+ && end->Is(CT_BRACE_OPEN)
+ && end->GetParentType() == CT_BRACED_INIT_LIST)
+ {
+ cs.Get(0)->m_pc->SetType(CT_TYPE);
+ }
+
+ // Function defs are handled elsewhere
+ if ( (cs.Len() <= 1)
+ || end->Is(CT_FUNC_DEF)
+ || end->Is(CT_FUNC_PROTO)
+ || end->Is(CT_FUNC_CLASS_DEF)
+ || end->Is(CT_FUNC_CLASS_PROTO)
+ || end->Is(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->GetType() == CT_MEMBER)
+ || (cs.Get(cs.Len() - 2)->m_pc->GetType() == CT_DC_MEMBER)))
+ {
+ idx = cs.Len() - 2;
+
+ while (idx > 0)
+ {
+ tmp_pc = cs.Get(idx)->m_pc;
+
+ if ( tmp_pc->IsNot(CT_DC_MEMBER)
+ && tmp_pc->IsNot(CT_MEMBER))
+ {
+ break;
+ }
+ idx--;
+ tmp_pc = cs.Get(idx)->m_pc;
+
+ if ( tmp_pc->IsNot(CT_WORD)
+ && tmp_pc->IsNot(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->GetOrigLine());
+
+ for (size_t idxForCs = 0; idxForCs < cs.Len() - 1; idxForCs++)
+ {
+ tmp_pc = cs.Get(idxForCs)->m_pc;
+ make_type(tmp_pc);
+ tmp_pc->SetFlagBits(PCF_VAR_TYPE);
+ LOG_FMT(LFVD2, " Text() is '%s', type is %s", tmp_pc->Text(), get_token_name(tmp_pc->GetType()));
+ }
+
+ 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, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ mark_variable_definition(cs.Get(cs.Len() - 1)->m_pc);
+
+ if (end->Is(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 ( tmp->Is(CT_INV)
+ || tmp->Is(CT_DESTRUCTOR))
+ {
+ tmp->SetType(CT_DESTRUCTOR);
+ pc->SetParentType(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->GetOrigLine(), pc->GetOrigCol(),
+ is_destr ? "DE" : "CON",
+ pc->Text(), get_token_name(pc->GetType()),
+ tmp->Text(), get_token_name(tmp->GetType()));
+
+ paren_open = skip_template_next(pc->GetNextNcNnl());
+
+ if (!paren_open->IsString("("))
+ {
+ LOG_FMT(LWARN, "%s:%zu Expected '(', got: [%s]\n",
+ cpd.filename.c_str(), paren_open->GetOrigLine(),
+ 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()
+ && ( tmp->IsNot(CT_BRACE_OPEN)
+ || tmp->GetLevel() != paren_open->GetLevel())
+ && !tmp->IsSemicolon())
+ {
+ LOG_FMT(LFTOR, "%s(%d): tmp is '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, tmp->Text(), tmp->GetOrigLine(), tmp->GetOrigCol());
+ tmp->SetFlagBits(PCF_IN_CONST_ARGS);
+ tmp = tmp->GetNextNcNnl();
+
+ if ( tmp->IsString(":")
+ && tmp->GetLevel() == paren_open->GetLevel())
+ {
+ tmp->SetType(CT_CONSTR_COLON);
+ hit_colon = true;
+ }
+
+ if ( hit_colon
+ && ( tmp->IsParenOpen()
+ || tmp->IsBraceOpen())
+ && tmp->GetLevel() == paren_open->GetLevel())
+ {
+ var = skip_template_prev(tmp->GetPrevNcNnlNi()); // Issue #2279
+
+ if ( var->Is(CT_TYPE)
+ || var->Is(CT_WORD))
+ {
+ var->SetType(CT_FUNC_CTOR_VAR);
+ flag_parens(tmp, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CTOR_VAR, false);
+ }
+ }
+ }
+
+ if (tmp->Is(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->GetOrigLine(), pc->GetOrigCol());
+ }
+ else
+ {
+ tmp->SetParentType(CT_FUNC_CLASS_PROTO);
+ pc->SetType(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->GetOrigLine(), pc->GetOrigCol());
+ }
+ tmp = pc->GetPrevNcNnlNi(); // Issue #2907
+
+ if (tmp->Is(CT_DESTRUCTOR))
+ {
+ tmp->SetParentType(pc->GetType());
+ tmp = tmp->GetPrevNcNnlNi();
+ }
+
+ while (tmp->Is(CT_QUALIFIER))
+ {
+ tmp->SetParentType(pc->GetType());
+ tmp = tmp->GetPrevNcNnlNi();
+ }
+} // mark_cpp_constructor
+
+
+void mark_cpp_lambda(Chunk *square_open)
+{
+ if ( square_open->Is(CT_SQUARE_OPEN)
+ && square_open->GetParentType() == CT_CPP_LAMBDA)
+ {
+ auto *brace_close = square_open->GetNextType(CT_BRACE_CLOSE, square_open->GetLevel());
+
+ if (brace_close->GetParentType() == CT_CPP_LAMBDA)
+ {
+ for (auto *pc = square_open; pc != brace_close; pc = pc->GetNextNcNnl())
+ {
+ pc->SetFlagBits(PCF_IN_LAMBDA);
+ }
+ }
+ }
+} // mark_cpp_lambda
+
+
+void mark_define_expressions()
+{
+ LOG_FUNC_ENTRY();
+
+ bool in_define = false;
+ bool first = true;
+ Chunk *pc = Chunk::GetHead();
+ Chunk *prev = pc;
+
+ while (pc->IsNotNullChunk())
+ {
+ if (!in_define)
+ {
+ if ( pc->Is(CT_PP_DEFINE)
+ || pc->Is(CT_PP_IF)
+ || pc->Is(CT_PP_ELSE))
+ {
+ in_define = true;
+ first = true;
+ }
+ }
+ else
+ {
+ if ( !pc->TestFlags(PCF_IN_PREPROC)
+ || pc->Is(CT_PREPROC))
+ {
+ in_define = false;
+ }
+ else
+ {
+ if ( pc->IsNot(CT_MACRO)
+ && ( first
+ || prev->Is(CT_PAREN_OPEN)
+ || prev->Is(CT_ARITH)
+ || prev->Is(CT_SHIFT)
+ || prev->Is(CT_CARET)
+ || prev->Is(CT_ASSIGN)
+ || prev->Is(CT_COMPARE)
+ || prev->Is(CT_RETURN)
+ || prev->Is(CT_GOTO)
+ || prev->Is(CT_CONTINUE)
+ || prev->Is(CT_FPAREN_OPEN)
+ || prev->Is(CT_SPAREN_OPEN)
+ || prev->Is(CT_BRACE_OPEN)
+ || prev->IsSemicolon()
+ || prev->Is(CT_COMMA)
+ || prev->Is(CT_COLON)
+ || prev->Is(CT_QUESTION)))
+ {
+ pc->SetFlagBits(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->IsNotNullChunk(); tmp = tmp->GetNext())
+ {
+ tmp->SetParentType(pc->GetType());
+
+ if (tmp->Is(CT_WORD))
+ {
+ tmp->SetType(CT_SQL_WORD);
+ }
+
+ if (tmp->Is(CT_SEMICOLON))
+ {
+ break;
+ }
+ }
+
+ if ( pc->IsNot(CT_SQL_BEGIN)
+ || tmp->IsNullChunk()
+ || tmp->IsNot(CT_SEMICOLON))
+ {
+ return;
+ }
+
+ for (tmp = tmp->GetNext();
+ tmp->IsNotNullChunk() && tmp->IsNot(CT_SQL_END);
+ tmp = tmp->GetNext())
+ {
+ tmp->SetLevel(tmp->GetLevel() + 1);
+ }
+} // mark_exec_sql
+
+
+void mark_function_return_type(Chunk *fname, Chunk *start, E_Token parent_type)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = start;
+
+ if (pc->IsNotNullChunk())
+ {
+ // 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->GetOrigLine(), fname->GetOrigCol());
+
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ log_pcf_flags(LFCNR, pc->GetFlags());
+
+ if (pc->Is(CT_ANGLE_CLOSE))
+ {
+ pc = skip_template_prev(pc);
+
+ if ( pc->IsNullChunk()
+ || pc->Is(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 ( ( !pc->IsTypeDefinition()
+ && pc->IsNot(CT_OPERATOR)
+ && pc->IsNot(CT_WORD)
+ && pc->IsNot(CT_ADDR))
+ || pc->TestFlags(PCF_IN_PREPROC))
+ {
+ break;
+ }
+
+ if (!pc->IsPointerOperator())
+ {
+ 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 ( pc->Is(CT_PAREN_CLOSE)
+ && !pc->TestFlags(PCF_IN_PREPROC))
+ {
+ first = pc->GetOpeningParen();
+ is_return_tuple = true;
+ }
+ pc = first;
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ if (parent_type != CT_NONE)
+ {
+ pc->SetParentType(parent_type);
+ }
+ Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( !is_return_tuple
+ || pc->IsNot(CT_WORD)
+ || ( prev->IsNullChunk()
+ && prev->IsNot(CT_TYPE)))
+ {
+ make_type(pc);
+ }
+
+ if (pc == start)
+ {
+ break;
+ }
+ pc = pc->GetNextNcNnl();
+
+ //template angles should keep parent type CT_TEMPLATE
+ if (pc->Is(CT_ANGLE_OPEN))
+ {
+ pc = pc->GetNextType(CT_ANGLE_CLOSE, pc->GetLevel());
+
+ 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->TestFlags(PCF_IN_CLASS))
+ {
+ pc = first->GetPrevNcNnlNi(); // Issue #2279
+
+ if (pc->Is(CT_FRIEND))
+ {
+ LOG_FMT(LFCNR, "%s(%d): marking friend\n", __func__, __LINE__);
+ pc->SetParentType(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 (pc->Is(CT_ANGLE_CLOSE))
+ {
+ pc = skip_template_prev(pc);
+
+ if (pc->Is(CT_TEMPLATE))
+ {
+ LOG_FMT(LFCNR, "%s(%d): marking friend template\n",
+ __func__, __LINE__);
+ pc->SetParentType(parent_type);
+ }
+ }
+ }
+ }
+ }
+} // mark_function_return_type
+
+
+void mark_function(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LFCN, "%s(%d): orig line is %zu, orig col is %zu, text '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279
+ Chunk *next = pc->GetNextNppOrNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ Chunk *tmp;
+ Chunk *semi = Chunk::NullChunkPtr;
+ Chunk *paren_open;
+ Chunk *paren_close;
+
+ // Find out what is before the operator
+ if (pc->GetParentType() == CT_OPERATOR)
+ {
+ LOG_FMT(LFCN, "%s(%d): orig line %zu, orig col %zu, text '%s",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ log_pcf_flags(LFCN, pc->GetFlags());
+ Chunk *pc_op = pc->GetPrevType(CT_OPERATOR, pc->GetLevel());
+
+ if ( pc_op->IsNotNullChunk()
+ && pc_op->TestFlags(PCF_EXPR_START))
+ {
+ LOG_FMT(LFCN, "%s(%d): (4) SET TO CT_FUNC_CALL: orig line %zu, orig col %zu, text '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_CALL);
+ }
+
+ if (language_is_set(LANG_CPP))
+ {
+ tmp = pc;
+
+ while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ if ( tmp->Is(CT_BRACE_CLOSE)
+ || tmp->Is(CT_BRACE_OPEN) // Issue 575
+ || tmp->Is(CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if ( tmp->IsParenOpen()
+ && !pc->TestFlags(PCF_IN_PREPROC)) // Issue #2703
+ {
+ LOG_FMT(LFCN, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s'\n",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_CALL);
+ break;
+ }
+
+ if (tmp->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_CALL);
+ break;
+ }
+
+ if (tmp->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_DEF);
+ break;
+ }
+
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ if (tmp->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_CALL);
+ }
+
+ if ( tmp->GetParentType() == CT_CLASS
+ || tmp->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_DEF);
+ }
+ break;
+ }
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && pc->IsNot(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 ( next->IsPointerOperator()
+ || next->IsNewline())
+ {
+ next = next->GetNextNppOrNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ }
+ LOG_FMT(LFCN, "%s(%d): orig line %zu, orig col %zu, text '%s', type %s, parent type %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(),
+ get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+ LOG_FMT(LFCN, " level %zu, brace level %zu, next->text '%s', next->type %s, next->level is %zu\n",
+ pc->GetLevel(), pc->GetBraceLevel(),
+ next->Text(), get_token_name(next->GetType()), next->GetLevel());
+
+ if (pc->TestFlags(PCF_IN_CONST_ARGS))
+ {
+ pc->SetType(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->GetOrigLine(), pc->GetOrigCol());
+ next = skip_template_next(next);
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, pc->GetType(), true);
+ return;
+ }
+ // Skip over any template and attribute madness
+ next = skip_template_next(next);
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ next = skip_attribute_next(next);
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+ // Find the open and close parenthesis
+ paren_open = pc->GetNextString("(", 1, pc->GetLevel());
+ paren_close = paren_open->GetNextString(")", 1, pc->GetLevel());
+
+ 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->GetOrigLine(), pc->GetOrigCol());
+ return;
+ }
+ /*
+ * This part detects either chained function calls or a function ptr definition.
+ * MYTYPE (*func)(void);
+ * MYTYPE (*func(param))(void);
+ * MYTYPE (*func(param_call1)(param_call2))(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 or by a sequence of one or more expressions each within brackets.
+ *
+ * Otherwise, it must be chained function calls.
+ */
+ tmp = paren_close->GetNextNcNnl();
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->IsString("("))
+ {
+ 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 ( !tmp1->IsWord()
+ || tmp2->IsNot(CT_DC_MEMBER))
+ {
+ break;
+ }
+ tmp1 = tmp2->GetNextNcNnl();
+ }
+ tmp2 = tmp1->GetNextNcNnl();
+
+ if (tmp2->IsString(")"))
+ {
+ tmp3 = tmp2;
+ tmp2 = Chunk::NullChunkPtr;
+ }
+ else
+ {
+ tmp3 = tmp2->GetNextNcNnl();
+ }
+ tmp3 = tmp3->GetNextNbsb();
+
+ // Issue #3852
+ while (tmp3->IsString("("))
+ {
+ tmp3 = tmp3->GetClosingParen();
+ tmp3 = tmp3->GetNextNcNnl();
+ }
+
+ if ( tmp3->IsString(")")
+ && ( tmp1->IsStar()
+ || tmp1->IsMsRef()
+ || ( language_is_set(LANG_OC)
+ && tmp1->Is(CT_CARET)))
+ && ( tmp2->IsNullChunk()
+ || tmp2->Is(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->GetOrigLine(), pc->GetOrigCol(), tmp2->Text(), pc->Text());
+ tmp2->SetType(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->GetOrigLine(), paren_open->GetOrigCol());
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+
+ if (tmp2->IsNotNullChunk())
+ {
+ tmp2->SetType(CT_FUNC_TYPE);
+ }
+ flag_parens(paren_open, PCF_NONE, CT_PAREN_OPEN, CT_FUNC_TYPE, false);
+ }
+ pc->SetType(CT_TYPE);
+ tmp1->SetType(CT_PTR_TYPE);
+ pc->ResetFlagBits(PCF_VAR_1ST_DEF);
+
+ if (tmp2->IsNotNullChunk())
+ {
+ tmp2->SetFlagBits(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->GetOrigLine(), pc->GetOrigCol());
+ }
+
+ // Assume it is a function call if not already labeled
+ if (pc->Is(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->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ // look for an assignment. Issue #575
+ Chunk *temp = pc->GetNextType(CT_ASSIGN, pc->GetLevel());
+
+ if (temp->IsNotNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): assignment found, orig line is %zu, orig col is %zu, Text() '%s'\n",
+ __func__, __LINE__, temp->GetOrigLine(), temp->GetOrigCol(), 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(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__, (pc->GetParentType() == CT_OPERATOR) ? "CT_FUNC_DEF" : "CT_FUNC_CALL",
+ pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType((pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+
+ 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->GetOrigLine(), prev->GetOrigCol(), get_token_name(prev->GetType()));
+ }
+
+ // Check for C++ function def
+ if ( pc->Is(CT_FUNC_CLASS_DEF)
+ || ( prev->IsNotNullChunk()
+ && ( prev->Is(CT_INV)
+ || prev->Is(CT_DC_MEMBER))))
+ {
+ Chunk *destr = Chunk::NullChunkPtr;
+
+ if (prev->Is(CT_INV))
+ {
+ // TODO: do we care that this is the destructor?
+ prev->SetType(CT_DESTRUCTOR);
+ pc->SetType(CT_FUNC_CLASS_DEF);
+
+ pc->SetParentType(CT_DESTRUCTOR);
+
+ destr = prev;
+ // Point to the item previous to the class name
+ prev = prev->GetPrevNcNnlNpp();
+ }
+
+ if (prev->Is(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->GetOrigLine(), prev->GetOrigCol(),
+ get_token_name(prev->GetType()));
+ 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->GetOrigLine(), prev->GetOrigCol(),
+ get_token_name(prev->GetType()));
+ 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->GetOrigLine(), prev->GetOrigCol(),
+ get_token_name(prev->GetType()));
+ }
+
+ if ( prev->Is(CT_WORD)
+ || prev->Is(CT_TYPE))
+ {
+ if (pc->GetStr().equals(prev->GetStr()))
+ {
+ 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->GetOrigLine(), pc->GetOrigCol(),
+ get_token_name(prev->GetType()));
+ pc->SetType(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->GetOrigLine(), prev->GetOrigCol(),
+ (destr->IsNotNullChunk()) ? "DE" : "CON",
+ prev->Text(), get_token_name(prev->GetType()));
+
+ 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 ( pc->Is(CT_FUNC_CALL)
+ && ( pc->GetLevel() == pc->GetBraceLevel()
+ || pc->GetLevel() == 1)
+ && !pc->TestFlags(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->GetOrigLine(), pc->GetOrigCol(),
+ get_token_name(pc->GetType()));
+
+ 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->GetType() is %s\n",
+ __func__, __LINE__, prev->Text(), get_token_name(prev->GetType()));
+ }
+ // 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->GetOrigLine(), prev->GetOrigCol(), prev->Text());
+
+ if (pc->GetParentType() == CT_FIXED)
+ {
+ isa_def = true;
+ }
+
+ if (prev->TestFlags(PCF_IN_PREPROC))
+ {
+ prev = prev->GetPrevNcNnlNpp();
+ continue;
+ }
+
+ // Some code slips an attribute between the type and function
+ if ( prev->Is(CT_FPAREN_CLOSE)
+ && prev->GetParentType() == CT_ATTRIBUTE)
+ {
+ prev = skip_attribute_prev(prev);
+ continue;
+ }
+
+ // skip const(TYPE)
+ if ( prev->Is(CT_PAREN_CLOSE)
+ && prev->GetParentType() == CT_D_CAST)
+ {
+ LOG_FMT(LFCN, "%s(%d): --> For sure a prototype or definition\n",
+ __func__, __LINE__);
+ isa_def = true;
+ break;
+ }
+
+ if (prev->GetParentType() == CT_DECLSPEC) // Issue 1289
+ {
+ prev = prev->GetOpeningParen();
+
+ if (prev->IsNotNullChunk())
+ {
+ prev = prev->GetPrev();
+ }
+
+ if (prev->Is(CT_DECLSPEC))
+ {
+ if (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
+ && prev->Is(CT_MEMBER))
+ {
+ isa_def = false;
+ }
+
+ // get first chunk before: A::B::pc | this.B.pc | this->B->pc
+ if ( prev->Is(CT_DC_MEMBER)
+ || prev->Is(CT_MEMBER))
+ {
+ while ( prev->Is(CT_DC_MEMBER)
+ || prev->Is(CT_MEMBER))
+ {
+ prev = prev->GetPrevNcNnlNpp();
+
+ if ( prev->IsNullChunk()
+ || ( prev->IsNot(CT_WORD)
+ && prev->IsNot(CT_TYPE)
+ && prev->IsNot(CT_THIS)))
+ {
+ LOG_FMT(LFCN, "%s(%d): --? skipped MEMBER and landed on %s\n",
+ __func__, __LINE__, (prev->IsNullChunk()) ? "<null chunk>" : get_token_name(prev->GetType()));
+ 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->GetOrigLine(), prev->GetOrigCol(), prev->Text());
+ }
+ }
+
+ if (prev->IsNullChunk())
+ {
+ break;
+ }
+ }
+
+ // If we are on a TYPE or WORD, then this could be a proto or def
+ if ( prev->Is(CT_TYPE)
+ || prev->Is(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 (!prev_prev->Is(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->GetOrigLine(), prev->GetOrigCol(),
+ get_token_name(prev->GetType()), get_token_name(prev->GetParentType()));
+ log_pcf_flags(LFCN, pc->GetFlags());
+ isa_def = true;
+ }
+ }
+
+ if (prev->IsPointerOperator())
+ {
+ hit_star = true;
+ }
+
+ if ( prev->IsNot(CT_OPERATOR)
+ && prev->IsNot(CT_TSQUARE)
+ && prev->IsNot(CT_ANGLE_CLOSE)
+ && prev->IsNot(CT_QUALIFIER)
+ && prev->IsNot(CT_TYPE)
+ && prev->IsNot(CT_WORD)
+ && !prev->IsPointerOperator())
+ {
+ 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->GetOrigLine(), prev->GetOrigCol(), get_token_name(prev->GetType()));
+
+ // certain tokens are unlikely to precede a prototype or definition
+ if ( prev->Is(CT_ARITH)
+ || prev->Is(CT_SHIFT)
+ || prev->Is(CT_ASSIGN)
+ || prev->Is(CT_COMMA)
+ || ( prev->Is(CT_STRING)
+ && prev->GetParentType() != CT_EXTERN) // fixes issue 1259
+ || prev->Is(CT_STRING_MULTI)
+ || prev->Is(CT_NUMBER)
+ || prev->Is(CT_NUMBER_FP)
+ || prev->Is(CT_FPAREN_OPEN)) // issue #1464
+ {
+ isa_def = false;
+ }
+ break;
+ }
+
+ // Skip over template and attribute stuff
+ if (prev->Is(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->GetType()));
+
+ // Fixes issue #1634
+ if (prev->IsParenClose())
+ {
+ Chunk *preproc = prev->GetNextNcNnl();
+
+ if (preproc->Is(CT_PREPROC))
+ {
+ size_t pp_level = preproc->GetPpLevel();
+
+ if (preproc->GetNextNcNnl()->Is(CT_PP_ELSE))
+ {
+ do
+ {
+ preproc = preproc->GetPrevNcNnlNi(); // Issue #2279
+
+ if (preproc->Is(CT_PP_IF))
+ {
+ preproc = preproc->GetPrevNcNnlNi(); // Issue #2279
+
+ if (preproc->GetPpLevel() == pp_level)
+ {
+ prev = preproc->GetPrevNcNnlNpp();
+ break;
+ }
+ }
+ } while (preproc->IsNotNullChunk());
+ }
+ }
+ }
+
+ if ( isa_def
+ && prev->IsNotNullChunk()
+ && ( ( prev->IsParenClose()
+ && prev->GetParentType() != CT_D_CAST
+ && prev->GetParentType() != CT_MACRO_OPEN // Issue #2726
+ && prev->GetParentType() != CT_MACRO_CLOSE)
+ || prev->Is(CT_ASSIGN)
+ || prev->Is(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->GetType()));
+ isa_def = false;
+ }
+
+ // Fixes issue #1266, identification of a tuple return type in CS.
+ if ( !isa_def
+ && prev->Is(CT_PAREN_CLOSE)
+ && prev->GetNextNcNnl() == pc)
+ {
+ tmp = prev->GetOpeningParen();
+
+ while ( tmp->IsNotNullChunk() // Issue #2315
+ && tmp != prev)
+ {
+ if ( tmp->Is(CT_COMMA)
+ && tmp->GetLevel() == prev->GetLevel() + 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->GetType()));
+ 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->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_DEF);
+
+ if (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->GetType()));
+ make_type(tmp);
+ }
+ }
+ }
+
+ if (pc->IsNot(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->GetType()),
+ pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+
+ tmp = flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->Is(CT_BRACE_OPEN)
+ && tmp->GetParentType() != CT_DOUBLE_BRACE)
+ {
+ set_paren_parent(tmp, pc->GetType());
+ }
+ 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->GetLevel() < pc->GetLevel())
+ {
+ // No semicolon - guess that it is a prototype
+ pc->ResetFlagBits(PCF_VAR_1ST_DEF);
+ pc->SetType(CT_FUNC_PROTO);
+ break;
+ }
+ else if (tmp->GetLevel() == pc->GetLevel())
+ {
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ // its a function def for sure
+ break;
+ }
+ else if (tmp->IsSemicolon())
+ {
+ // Set the parent for the semicolon for later
+ semi = tmp;
+ pc->ResetFlagBits(PCF_VAR_1ST_DEF);
+ pc->SetType(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->GetOrigLine(), pc->GetOrigCol());
+ break;
+ }
+ else if (pc->Is(CT_COMMA))
+ {
+ pc->SetType(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->GetOrigLine(), pc->GetOrigCol());
+ 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)
+ && pc->Is(CT_FUNC_PROTO)
+ && pc->GetParentType() != 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->GetType()),
+ get_token_name(paren_close->GetType()));
+
+ /*
+ * 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->TestFlags(PCF_STMT_START))
+ {
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+ }
+ const bool is_extern = ( tmp->IsNotNullChunk()
+ && tmp->GetStr().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 ( tmp->Is(CT_COMMA)
+ && (tmp->GetLevel() == (paren_open->GetLevel() + 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)
+ {
+ pc->SetType(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->GetOrigLine(), pc->GetOrigCol());
+ }
+ else if (pc->GetBraceLevel() > 0)
+ {
+ Chunk *br_open = pc->GetPrevType(CT_BRACE_OPEN, pc->GetBraceLevel() - 1);
+
+ if ( br_open->IsNotNullChunk()
+ && br_open->GetParentType() != CT_EXTERN
+ && br_open->GetParentType() != CT_NAMESPACE)
+ {
+ // Do a check to see if the level is right
+ prev = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( !prev->IsString("*")
+ && !prev->IsString("&"))
+ {
+ Chunk *p_op = pc->GetPrevType(CT_BRACE_OPEN, pc->GetBraceLevel() - 1);
+
+ if ( p_op->IsNotNullChunk()
+ && p_op->GetParentType() != CT_CLASS
+ && p_op->GetParentType() != CT_STRUCT
+ && p_op->GetParentType() != CT_NAMESPACE)
+ {
+ pc->SetType(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->GetOrigLine(), pc->GetOrigCol());
+ }
+ }
+ }
+ }
+ }
+
+ if (semi->IsNotNullChunk())
+ {
+ semi->SetParentType(pc->GetType());
+ }
+
+ // Issue # 1403, 2152
+ if (paren_open->GetPrev()->Is(CT_FUNC_CTOR_VAR))
+ {
+ flag_parens(paren_open, PCF_IN_FCN_CTOR, CT_FPAREN_OPEN, pc->GetType(), false);
+ }
+ else
+ {
+ // see also Issue #2103
+ Chunk *funtionName = paren_open->GetPrevNcNnl(); // Issue #3967
+ Chunk *a = funtionName->GetPrevNcNnl();
+
+ while (a->IsNotNullChunk())
+ {
+ LOG_FMT(LFCN, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s', type is %s, parent type is %s\n",
+ __func__, __LINE__, a->GetOrigLine(), a->GetOrigCol(), a->Text(),
+ get_token_name(a->GetType()), get_token_name(a->GetParentType()));
+ log_pcf_flags(LFCN, a->GetFlags());
+
+ if ( a->Is(CT_ARITH)
+ && (strcmp(a->Text(), "&") == 0))
+ {
+ a->SetType(CT_BYREF);
+ }
+
+ if (a->GetParentType() == CT_NONE)
+ {
+ a->SetParentType(CT_FUNC_DEF);
+ }
+ // if token has PCF_STMT_START set, exit the loop
+ PcfFlags f = a->GetFlags();
+ PcfFlags u = f & PCF_STMT_START;
+ bool b = u != E_PcfFlag::PCF_NONE;
+
+ if (b)
+ {
+ break;
+ }
+ a = a->GetPrevNcNnl();
+ }
+ flag_parens(paren_open, PCF_IN_FCN_DEF, CT_FPAREN_OPEN, pc->GetType(), false);
+ }
+
+ if (pc->Is(CT_FUNC_CTOR_VAR))
+ {
+ pc->SetFlagBits(PCF_VAR_1ST_DEF);
+ return;
+ }
+
+ if (next->Is(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->GetType()); // Issue #2279
+
+ /* mark C# where chunk */
+ if ( language_is_set(LANG_CS)
+ && ( (pc->Is(CT_FUNC_DEF))
+ || (pc->Is(CT_FUNC_PROTO))))
+ {
+ tmp = paren_close->GetNextNcNnl();
+ PcfFlags in_where_spec_flags = PCF_NONE;
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->IsNot(CT_BRACE_OPEN)
+ && tmp->IsNot(CT_SEMICOLON))
+ {
+ mark_where_chunk(tmp, pc->GetType(), tmp->GetFlags() | in_where_spec_flags);
+ in_where_spec_flags = tmp->GetFlags() & PCF_IN_WHERE_SPEC;
+
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+
+ // Find the brace pair and set the parent
+ if (pc->Is(CT_FUNC_DEF))
+ {
+ tmp = paren_close->GetNextNcNnl();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->IsNot(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->GetOrigLine(), tmp->GetOrigCol(), tmp->Text());
+ tmp->SetParentType(CT_FUNC_DEF);
+
+ if (!tmp->IsSemicolon())
+ {
+ tmp->SetFlagBits(PCF_OLD_FCN_PARAMS);
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if (tmp->Is(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->GetOrigLine(), tmp->GetOrigCol(), tmp->Text());
+ tmp->SetParentType(CT_FUNC_DEF);
+ tmp = tmp->GetClosingParen();
+
+ if (tmp->IsNotNullChunk())
+ {
+ 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->GetOrigLine(), tmp->GetOrigCol(), tmp->Text());
+ tmp->SetParentType(CT_FUNC_DEF);
+ }
+ }
+ }
+} // mark_function
+
+
+bool mark_function_type(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LFTYPE, "%s(%d): type %s, text '%s' @ orig line %zu, orig col %zu\n",
+ __func__, __LINE__, get_token_name(pc->GetType()), pc->Text(),
+ pc->GetOrigLine(), pc->GetOrigCol());
+
+ size_t star_count = 0;
+ size_t word_count = 0;
+ Chunk *ptrcnk = Chunk::NullChunkPtr;
+ 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 = varcnk->GetPrevNbsb();
+
+ if ( varcnk->IsNotNullChunk()
+ && !varcnk->IsWord())
+ {
+ if ( language_is_set(LANG_OC)
+ && varcnk->IsString("^")
+ && varcnk->GetPrevNcNnlNi()->IsParenOpen()) // Issue #2279
+ {
+ // anonymous ObjC block type -- RTYPE (^)(ARGS)
+ anon = true;
+ }
+ else
+ {
+ LOG_FMT(LFTYPE, "%s(%d): not a word: text '%s', type %s, @ orig line %zu:, orig col %zu\n",
+ __func__, __LINE__, varcnk->Text(), get_token_name(varcnk->GetType()),
+ varcnk->GetOrigLine(), varcnk->GetOrigCol());
+ goto nogo_exit;
+ }
+ }
+ apo = pc->GetNextNcNnl();
+
+ if (apo->IsNullChunk())
+ {
+ return(false);
+ }
+ apc = apo->GetClosingParen();
+
+ if ( apc->IsNotNullChunk()
+ && ( !apo->IsParenOpen()
+ || ((apc = apo->GetClosingParen())->IsNullChunk())))
+ {
+ LOG_FMT(LFTYPE, "%s(%d): not followed by parens\n", __func__, __LINE__);
+ goto nogo_exit;
+ }
+ aft = apc->GetNextNcNnl();
+
+ if (aft->Is(CT_BRACE_OPEN))
+ {
+ pt = CT_FUNC_DEF;
+ }
+ else if ( aft->Is(CT_SEMICOLON)
+ || aft->Is(CT_ASSIGN))
+ {
+ pt = CT_FUNC_PROTO;
+ }
+ else
+ {
+ LOG_FMT(LFTYPE, "%s(%d): not followed by '{' or ';'\n", __func__, __LINE__);
+ goto nogo_exit;
+ }
+ ptp = pc->TestFlags(PCF_IN_TYPEDEF) ? CT_FUNC_TYPE : CT_FUNC_VAR;
+
+ tmp = pc;
+
+ while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279
+ {
+ tmp = tmp->GetPrevNbsb();
+ LOG_FMT(LFTYPE, " -- type is %s, %s on orig line %zu, orig col is %zu",
+ get_token_name(tmp->GetType()), tmp->Text(),
+ tmp->GetOrigLine(), tmp->GetOrigCol());
+
+ if (tmp->IsSemicolon())
+ {
+ // Stop if we found previous statement. Make 'tmp' null to make sure
+ // chunk_ends_type() does not start from the previous statement
+ LOG_FMT(LFTYPE, " -- found semicolon (break)\n");
+ tmp = Chunk::NullChunkPtr;
+ break;
+ }
+ else if ( tmp->IsStar()
+ || tmp->Is(CT_PTR_TYPE)
+ || tmp->Is(CT_CARET))
+ {
+ star_count++;
+ ptrcnk = tmp;
+ LOG_FMT(LFTYPE, " -- PTR_TYPE\n");
+ }
+ else if ( tmp->IsWord()
+ || tmp->Is(CT_WORD)
+ || tmp->Is(CT_TYPE))
+ {
+ word_count++;
+ LOG_FMT(LFTYPE, " -- TYPE(%s)\n", tmp->Text());
+ }
+ else if (tmp->Is(CT_DC_MEMBER))
+ {
+ word_count = 0;
+ LOG_FMT(LFTYPE, " -- :: reset word_count\n");
+ }
+ else if (tmp->IsString("("))
+ {
+ 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->GetType()), tmp->Text(),
+ tmp->GetOrigLine(), tmp->GetOrigCol());
+ goto nogo_exit;
+ }
+ }
+
+ // Fixes #issue 1577
+ // Allow word count 2 in case 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->IsNotNullChunk())
+ {
+ ptrcnk->SetType(CT_PTR_TYPE);
+ }
+
+ if (!anon)
+ {
+ if (pc->TestFlags(PCF_IN_TYPEDEF))
+ {
+ varcnk->SetType(CT_FUNC_TYPE); // Issue #3402
+ }
+ else
+ {
+ varcnk->SetType(CT_FUNC_VAR);
+ varcnk->SetFlagBits(PCF_VAR_1ST_DEF);
+ }
+ }
+ pc->SetType(CT_TPAREN_CLOSE);
+ pc->SetParentType(ptp);
+
+ apo->SetType(CT_FPAREN_OPEN);
+ apo->SetParentType(pt);
+ apc->SetType(CT_FPAREN_CLOSE);
+ apc->SetParentType(pt);
+ fix_fcn_def_params(apo);
+ flag_parens(apo, PCF_IN_FCN_DEF, CT_NONE, pt, false);
+
+ if (aft->IsSemicolon())
+ {
+ aft->SetParentType(aft->TestFlags(PCF_IN_TYPEDEF) ? CT_TYPEDEF : CT_FUNC_VAR);
+ }
+ else if (aft->Is(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->GetType()), tmp->Text(),
+ tmp->GetOrigLine(), tmp->GetOrigCol());
+
+ if (*tmp->GetStr().c_str() == '(')
+ {
+ if (!pc->TestFlags(PCF_IN_TYPEDEF))
+ {
+ tmp->SetFlagBits(PCF_VAR_1ST_DEF);
+ }
+ tmp->SetType(CT_TPAREN_OPEN);
+ tmp->SetParentType(ptp);
+
+ tmp = tmp->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( tmp->Is(CT_FUNCTION)
+ || tmp->Is(CT_FUNC_CALL)
+ || tmp->Is(CT_FUNC_CALL_USER)
+ || tmp->Is(CT_FUNC_DEF)
+ || tmp->Is(CT_FUNC_PROTO))
+ {
+ tmp->SetType(CT_TYPE);
+ tmp->ResetFlagBits(PCF_VAR_1ST_DEF);
+ }
+ mark_function_return_type(varcnk, tmp, ptp);
+ break;
+ }
+ }
+ return(true);
+
+nogo_exit:
+ tmp = pc->GetNextNcNnl();
+
+ if (tmp->IsParenOpen())
+ {
+ LOG_FMT(LFTYPE, "%s(%d): setting FUNC_CALL on orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol());
+ flag_parens(tmp, PCF_IN_FCN_DEF, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
+ }
+ return(false);
+} // mark_function_type
+
+
+void mark_lvalue(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->TestFlags(PCF_IN_PREPROC))
+ {
+ return;
+ }
+
+ for (Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279
+ prev->IsNotNullChunk();
+ prev = prev->GetPrevNcNnlNi()) // Issue #2279
+ {
+ if ( prev->GetLevel() < pc->GetLevel()
+ || prev->Is(CT_ACCESS_COLON)
+ || prev->Is(CT_ASSIGN)
+ || prev->Is(CT_BOOL)
+ || prev->Is(CT_COMMA)
+ || prev->IsCppInheritanceAccessSpecifier()
+ || prev->IsSemicolon()
+ || prev->IsString("(")
+ || prev->IsString("{")
+ || prev->IsString("[")
+ || prev->TestFlags(PCF_IN_PREPROC)
+ || prev->GetParentType() == CT_NAMESPACE
+ || prev->GetParentType() == CT_TEMPLATE)
+ {
+ break;
+ }
+ prev->SetFlagBits(PCF_LVALUE);
+
+ if ( prev->GetLevel() == pc->GetLevel()
+ && prev->IsString("&"))
+ {
+ make_type(prev);
+ }
+ }
+} // mark_lvalue
+
+
+void mark_struct_union_body(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = start;
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() >= start->GetLevel()
+ && !( pc->GetLevel() == start->GetLevel()
+ && pc->Is(CT_BRACE_CLOSE)))
+ {
+ if ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_SEMICOLON))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (pc->IsNullChunk())
+ {
+ break;
+ }
+ }
+
+ if (pc->Is(CT_ALIGN))
+ {
+ pc = skip_align(pc); // "align(x)" or "align(x):"
+
+ if (pc->IsNullChunk())
+ {
+ break;
+ }
+ }
+ else if (pc->Is(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->GetLevel());
+ Chunk *after = angle_close->GetNextNcNnl();
+
+ if (after->IsNotNullChunk())
+ {
+ if (after->IsString("("))
+ {
+ if (angle_close->TestFlags(PCF_IN_FCN_CALL))
+ {
+ LOG_FMT(LTEMPFUNC, "%s(%d): marking '%s' in line %zu as a FUNC_CALL\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(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->GetOrigLine());
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ pc->SetType(CT_FUNC_CALL);
+ mark_function(pc);
+ }
+ }
+ else if (after->Is(CT_WORD))
+ {
+ // its a type!
+ pc->SetType(CT_TYPE);
+ pc->SetFlagBits(PCF_VAR_TYPE);
+ after->SetFlagBits(PCF_VAR_DEF);
+ }
+ }
+} // mark_template_func
+
+
+Chunk *mark_variable_definition(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ if (start->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ Chunk *pc = start;
+ PcfFlags 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(),
+ get_token_name(pc->GetType()));
+
+ // Issue #596
+ bool bit_field_colon_is_present = false;
+
+ while (go_on(pc, start))
+ {
+ if ( pc->Is(CT_WORD)
+ || pc->Is(CT_FUNC_CTOR_VAR))
+ {
+ auto const orig_flags = pc->GetFlags();
+
+ if (!pc->TestFlags(PCF_IN_ENUM))
+ {
+ pc->SetFlagBits(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->GetOrigLine(), pc->GetOrigCol(), 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->GetOrigLine(), pc->Text(),
+ get_token_name(pc->GetType()), pc->GetOrigCol(),
+ pcf_flags_str(orig_flags).c_str(),
+ pcf_flags_str(pc->GetFlags()).c_str());
+ }
+ else if ( !bit_field_colon_is_present // Issue #2689
+ && ( pc->IsStar()
+ || pc->IsMsRef()))
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if (pc->IsAddress())
+ {
+ pc->SetType(CT_BYREF);
+ }
+ else if ( pc->Is(CT_SQUARE_OPEN)
+ || pc->Is(CT_ASSIGN))
+ {
+ pc = skip_expression(pc);
+ continue;
+ }
+ else if (pc->Is(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->IsNotNullChunk()
+ && var_name->GetPrev()->IsNotNullChunk()
+ && var_name->GetPrev()->GetType() == CT_DC_MEMBER)
+ {
+ cs.Push_Back(var_name);
+ }
+
+ if (var_name->IsNotNullChunk())
+ {
+ LOG_FMT(LFCNP, "%s(%d): parameter on orig line %zu, orig col %zu:\n",
+ __func__, __LINE__, var_name->GetOrigLine(), var_name->GetOrigCol());
+
+ size_t word_cnt = 0;
+ Chunk *word_type;
+
+ while ((word_type = cs.Pop_Back())->IsNotNullChunk())
+ {
+ if ( word_type->Is(CT_WORD)
+ || word_type->Is(CT_TYPE))
+ {
+ LOG_FMT(LFCNP, "%s(%d): parameter on orig line %zu, orig col %zu: <%s> as TYPE\n",
+ __func__, __LINE__, var_name->GetOrigLine(), var_name->GetOrigCol(), word_type->Text());
+ word_type->SetType(CT_TYPE);
+ word_type->SetFlagBits(PCF_VAR_TYPE);
+ }
+ word_cnt++;
+ }
+
+ if (var_name->Is(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->GetOrigLine(), var_name->GetOrigCol(), var_name->Text());
+ var_name->SetFlagBits(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->GetOrigLine(), var_name->GetOrigCol(), var_name->Text());
+ var_name->SetType(CT_TYPE);
+ var_name->SetFlagBits(PCF_VAR_TYPE);
+ }
+ }
+ }
+} // mark_variable_stack
+
+
+PcfFlags mark_where_chunk(Chunk *pc, E_Token parent_type, PcfFlags 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 (pc->Is(CT_WHERE))
+ {
+ pc->SetType(CT_WHERE_SPEC);
+ pc->SetParentType(parent_type);
+ flags |= PCF_IN_WHERE_SPEC;
+ LOG_FMT(LFTOR, "%s: where-spec on line %zu\n",
+ __func__, pc->GetOrigLine());
+ }
+ else if (flags.test(PCF_IN_WHERE_SPEC))
+ {
+ if (pc->IsString(":"))
+ {
+ pc->SetType(CT_WHERE_COLON);
+ LOG_FMT(LFTOR, "%s: where-spec colon on line %zu\n",
+ __func__, pc->GetOrigLine());
+ }
+ else if (pc->IsClassOrStruct())
+ {
+ /* class/struct inside of a where-clause confuses parser for indentation; set it as a word so it looks like the rest */
+ pc->SetType(CT_WORD);
+ }
+ }
+
+ if (flags.test(PCF_IN_WHERE_SPEC))
+ {
+ pc->SetFlagBits(PCF_IN_WHERE_SPEC);
+ }
+ return(flags);
+} // mark_where_chunk
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_fix_mark.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_fix_mark.h
new file mode 100644
index 00000000..f61aa7fb
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+/**
+ * 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
+ *
+ */
+PcfFlags mark_where_chunk(Chunk *pc, E_Token parent_type, PcfFlags flags);
+
+
+#endif /* COMBINE_FIX_MARK_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_labels.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_labels.cpp
new file mode 100644
index 00000000..3a26839b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_labels.cpp
@@ -0,0 +1,452 @@
+/**
+ * @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 "unc_tools.h"
+#include "uncrustify.h"
+
+
+Chunk *chunk_get_next_local(Chunk *pc, E_Scope scope = E_Scope::ALL)
+{
+ Chunk *tmp = pc;
+
+ do
+ {
+ tmp = tmp->GetNext(scope);
+ } while ( tmp->IsNotNullChunk()
+ && ( tmp->IsComment()
+ || tmp->Is(CT_NOEXCEPT)));
+
+ return(tmp);
+}
+
+
+Chunk *chunk_get_prev_local(Chunk *pc, E_Scope scope = E_Scope::ALL)
+{
+ Chunk *tmp = pc;
+
+ do
+ {
+ tmp = tmp->GetPrev(scope);
+ } while ( tmp->IsNotNullChunk()
+ && ( tmp->IsCommentOrNewline()
+ || tmp->Is(CT_NOEXCEPT)));
+
+ return(tmp);
+}
+
+
+void combine_labels()
+{
+ 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->IsNotNullChunk())
+ {
+ if (next->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LFCN, "%s(%d): next orig line is %zu, orig col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->GetNlCount());
+ }
+ else if (next->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LFCN, "%s(%d): next orig line is %zu, orig col is %zu, VBRACE_OPEN\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol());
+ }
+ else if (next->Is(CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LFCN, "%s(%d): next orig line is %zu, orig col is %zu, VBRACE_CLOSE\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol());
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): next orig line is %zu, orig col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text(), get_token_name(next->GetType()));
+ }
+ E_Token pt = next->GetParentType(); // Issue #4042
+
+ if ( pt == CT_UNION
+ && next->Is(CT_BRACE_OPEN))
+ {
+ Chunk *close_brace = next->GetClosingParen();
+ next = close_brace->GetNextNc();
+ continue;
+ }
+
+ if ( !next->TestFlags(PCF_IN_OC_MSG) // filter OC case of [self class] msg send
+ && ( next->Is(CT_CLASS)
+ || next->Is(CT_OC_CLASS)
+ || next->Is(CT_TEMPLATE)))
+ {
+ hit_class = true;
+ }
+
+ if ( next->IsSemicolon()
+ || next->Is(CT_BRACE_OPEN))
+ {
+ hit_class = false;
+ }
+
+ if ( prev->Is(CT_SQUARE_OPEN)
+ && prev->GetParentType() == CT_OC_MSG)
+ {
+ cs.Push_Back(prev);
+ }
+ else if ( next->Is(CT_SQUARE_CLOSE)
+ && next->GetParentType() == CT_OC_MSG)
+ {
+ // pop until we hit '['
+ while (!cs.Empty())
+ {
+ Chunk *t2 = cs.Top()->m_pc;
+ cs.Pop_Back();
+
+ if (t2->Is(CT_SQUARE_OPEN))
+ {
+ break;
+ }
+ }
+ }
+
+ if ( next->Is(CT_QUESTION)
+ && !next->TestFlags(PCF_IN_TEMPLATE))
+ {
+ cs.Push_Back(next);
+ }
+ else if (next->Is(CT_CASE))
+ {
+ if (cur->Is(CT_GOTO))
+ {
+ // handle "goto case x;"
+ next->SetType(CT_QUALIFIER);
+ }
+ else
+ {
+ hit_case = true;
+ }
+ }
+ else if ( next->Is(CT_COLON)
+ || ( next->Is(CT_OC_COLON)
+ && cs_top_is_question(cs, next->GetLevel())))
+ {
+ if (cur->Is(CT_DEFAULT))
+ {
+ cur->SetType(CT_CASE);
+ hit_case = true;
+ }
+
+ if ( cs_top_is_question(cs, next->GetLevel())
+ && !cur->Is(CT_OC_MSG_NAME)
+ && next->TestFlags(PCF_IN_CONDITIONAL)) // Issue #3558
+ {
+ //log_pcf_flags(LFCN, next->GetFlags());
+ next->SetType(CT_COND_COLON);
+ cs.Pop_Back();
+ }
+ else if (hit_case)
+ {
+ hit_case = false;
+ next->SetType(CT_CASE_COLON);
+ Chunk *tmp = next->GetNextNcNnlNpp(); // Issue #2150
+
+ if (tmp->Is(CT_BRACE_OPEN))
+ {
+ tmp->SetParentType(CT_CASE);
+ tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(CT_CASE);
+ }
+ }
+
+ if ( cur->Is(CT_NUMBER)
+ && prev->Is(CT_ELLIPSIS))
+ {
+ Chunk *pre_elipsis = prev->GetPrevNcNnlNpp();
+
+ if (pre_elipsis->Is(CT_NUMBER))
+ {
+ prev->SetType(CT_CASE_ELLIPSIS);
+ }
+ }
+ }
+ else if (cur->TestFlags(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->GetOrigLine(), prev->GetOrigCol());
+ LOG_FMT(LFCN, "%s(%d): cur->Text() is '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, cur->Text(), cur->GetOrigLine(), cur->GetOrigCol());
+ LOG_FMT(LFCN, "%s(%d): next->Text() is '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, next->Text(), next->GetOrigLine(), next->GetOrigCol());
+ Chunk *nextprev = chunk_get_prev_local(next); // Issue #2279
+
+ if (nextprev->IsNullChunk())
+ {
+ return;
+ }
+
+ if (language_is_set(LANG_PAWN))
+ {
+ if ( cur->Is(CT_WORD)
+ || cur->Is(CT_BRACE_CLOSE))
+ {
+ E_Token new_type = CT_TAG;
+
+ Chunk *tmp = next->GetNextNc();
+
+ if (tmp->IsNullChunk())
+ {
+ return;
+ }
+
+ if ( prev->IsNewline()
+ && tmp->IsNewline())
+ {
+ new_type = CT_LABEL;
+ next->SetType(CT_LABEL_COLON);
+ }
+ else
+ {
+ next->SetType(CT_TAG_COLON);
+ }
+
+ if (cur->Is(CT_WORD))
+ {
+ cur->SetType(new_type);
+ }
+ }
+ }
+ else if (next->TestFlags(PCF_IN_ARRAY_ASSIGN))
+ {
+ next->SetType(CT_D_ARRAY_COLON);
+ }
+ else if (next->TestFlags(PCF_IN_FOR))
+ {
+ next->SetType(CT_FOR_COLON);
+ }
+ else if (next->TestFlags(PCF_OC_BOXED))
+ {
+ next->SetType(CT_OC_DICT_COLON);
+ }
+ else if (cur->Is(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->GetOrigLine(), tmp->GetOrigCol(),
+ (tmp->Is(CT_NEWLINE)) ? "<Newline>" : tmp->Text());
+ log_pcf_flags(LFCN, tmp->GetFlags());
+
+ if (next->TestFlags(PCF_IN_FCN_CALL))
+ {
+ // Must be a macro thingy, assume some sort of label
+ next->SetType(CT_LABEL_COLON);
+ }
+ else if ( tmp->IsNullChunk()
+ || ( tmp->IsNot(CT_NUMBER)
+ && tmp->IsNot(CT_DECLTYPE)
+ && tmp->IsNot(CT_SIZEOF)
+ && tmp->GetParentType() != CT_SIZEOF
+ && !tmp->GetFlags().test_any(PCF_IN_STRUCT | PCF_IN_CLASS))
+ || tmp->Is(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 (labelPrev->Is(CT_NEWLINE))
+ {
+ labelPrev = prev->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ if ( labelPrev->IsNotNullChunk()
+ && labelPrev->IsNot(CT_FPAREN_CLOSE))
+ {
+ cur->SetType(CT_LABEL);
+ next->SetType(CT_LABEL_COLON);
+ }
+ }
+ else
+ {
+ cur->SetType(CT_LABEL);
+ next->SetType(CT_LABEL_COLON);
+ }
+ }
+ else if (next->GetFlags().test_any(PCF_IN_STRUCT | PCF_IN_CLASS | PCF_IN_TYPEDEF))
+ {
+ next->SetType(CT_BIT_COLON);
+
+ Chunk *nnext = next->GetNext();
+
+ if (nnext->IsNullChunk())
+ {
+ return;
+ }
+
+ while ((nnext = nnext->GetNext())->IsNotNullChunk())
+ {
+ if (nnext->Is(CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if (nnext->Is(CT_COLON))
+ {
+ nnext->SetType(CT_BIT_COLON);
+ }
+ }
+ }
+ }
+ else if (nextprev->Is(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->GetOrigLine(), nextprev->GetOrigCol(),
+ get_token_name(nextprev->GetType()));
+ 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->GetOrigLine(), next->GetOrigCol(),
+ get_token_name(next->GetType()));
+
+ // Issue #2172
+ if (next->GetParentType() == CT_FUNC_DEF)
+ {
+ LOG_FMT(LFCN, "%s(%d): it's a construct colon\n", __func__, __LINE__);
+ // it's a construct colon
+ next->SetType(CT_CONSTR_COLON);
+ }
+ else
+ {
+ LOG_FMT(LFCN, "%s(%d): it's a class colon\n", __func__, __LINE__);
+ // it's a class colon
+ next->SetType(CT_CLASS_COLON);
+ }
+ }
+ else if (next->GetLevel() > next->GetBraceLevel())
+ {
+ // ignore it, as it is inside a paren
+ }
+ else if ( cur->Is(CT_TYPE)
+ || cur->Is(CT_ENUM) // Issue #2584
+ || nextprev->Is(CT_TYPE)
+ || nextprev->Is(CT_ENUM)) // Issue #2584
+ {
+ next->SetType(CT_BIT_COLON);
+ }
+ else if ( cur->Is(CT_ENUM)
+ || cur->Is(CT_ACCESS)
+ || cur->Is(CT_QUALIFIER)
+ || cur->GetParentType() == CT_ALIGN)
+ {
+ // ignore it - bit field, align or public/private, etc
+ }
+ else if ( cur->Is(CT_ANGLE_CLOSE)
+ || hit_class)
+ {
+ // ignore it - template thingy
+ }
+ else if (cur->GetParentType() == CT_SQL_EXEC)
+ {
+ // ignore it - SQL variable name
+ }
+ else if (next->GetParentType() == CT_ASSERT)
+ {
+ // ignore it - Java assert thing
+ }
+ else if (next->GetParentType() == 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->GetOrigLine(), tmp->GetOrigCol(),
+ get_token_name(tmp->GetType()));
+
+ if ( tmp->Is(CT_BASE)
+ || tmp->Is(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->GetOrigLine(), next->GetOrigCol(),
+ get_token_name(next->GetParentType()),
+ get_token_name(cur->GetParentType()),
+ next->GetLevel(), next->GetBraceLevel());
+
+ if (language_is_set(LANG_OC))
+ {
+ // TO DO: what is to do? any expert?
+ }
+ else
+ {
+ exit(EX_SOFTWARE);
+ }
+ }
+ }
+ }
+ }
+ }
+ prev = cur;
+ cur = next;
+ next = chunk_get_next_local(next);
+ }
+} // combine_labels
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_labels.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_labels.h
new file mode 100644
index 00000000..5d5954b2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+#endif /* COMBINE_LABELS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.cpp
new file mode 100644
index 00000000..3360547c
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.cpp
@@ -0,0 +1,222 @@
+/**
+ * @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 (pc->Is(CT_ALIGN))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (pc->Is(CT_PAREN_OPEN))
+ {
+ pc = pc->GetNextType(CT_PAREN_CLOSE, pc->GetLevel());
+
+ if (pc->IsNotNullChunk())
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ if (pc->Is(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->IsNotNullChunk())
+ {
+ std::size_t level = prev->GetLevel();
+ Chunk *next = prev;
+ std::size_t template_nest = get_cpp_template_angle_nest_level(prev);
+
+ while ( next->IsNotNullChunk()
+ && next->GetLevel() >= level)
+ {
+ /**
+ * if we encounter a comma or semicolon at the level of the starting chunk,
+ * return the current chunk
+ */
+ if ( next->GetLevel() == level
+ && ( next->Is(CT_COMMA)
+ || next->IsSemicolon()))
+ {
+ 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)
+{
+ while ( pc->IsNotNullChunk()
+ && !pc->IsSemicolon()
+ && pc->IsNot(CT_BRACE_OPEN)
+ && pc->IsNot(CT_BRACE_CLOSE))
+ {
+ pc = pc->GetNextNcNnl();
+ }
+ return(pc);
+}
+
+
+Chunk *skip_template_prev(Chunk *ang_close)
+{
+ if (ang_close->Is(CT_ANGLE_CLOSE))
+ {
+ Chunk *pc = ang_close->GetPrevType(CT_ANGLE_OPEN, ang_close->GetLevel());
+ return(pc->GetPrevNcNnlNi()); // Issue #2279
+ }
+ return(ang_close);
+}
+
+
+Chunk *skip_tsquare_next(Chunk *ary_def)
+{
+ if ( ary_def->Is(CT_SQUARE_OPEN)
+ || ary_def->Is(CT_TSQUARE))
+ {
+ return(ary_def->GetNextNisq());
+ }
+ return(ary_def);
+}
+
+
+Chunk *skip_attribute(Chunk *attr)
+{
+ Chunk *pc = attr;
+
+ while (pc->Is(CT_ATTRIBUTE))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (pc->Is(CT_FPAREN_OPEN))
+ {
+ pc = pc->GetNextType(CT_FPAREN_CLOSE, pc->GetLevel());
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_attribute_next(Chunk *attr)
+{
+ Chunk *next = skip_attribute(attr);
+
+ if ( next != attr
+ && next->Is(CT_FPAREN_CLOSE))
+ {
+ attr = next->GetNextNcNnl();
+ }
+ return(attr);
+}
+
+
+Chunk *skip_attribute_prev(Chunk *fp_close)
+{
+ Chunk *pc = fp_close;
+
+ while (true)
+ {
+ if ( pc->Is(CT_FPAREN_CLOSE)
+ && pc->GetParentType() == CT_ATTRIBUTE)
+ {
+ pc = pc->GetPrevType(CT_ATTRIBUTE, pc->GetLevel());
+ }
+ else if (pc->IsNot(CT_ATTRIBUTE))
+ {
+ break;
+ }
+ pc = pc->GetPrevNcNnlNi(); // Issue #2279
+
+ if (pc->IsNullChunk()) // Issue #3356
+ {
+ break;
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_declspec(Chunk *pc)
+{
+ if (pc->Is(CT_DECLSPEC))
+ {
+ pc = pc->GetNextNcNnl();
+
+ if (pc->Is(CT_PAREN_OPEN))
+ {
+ pc = pc->GetClosingParen();
+ }
+ }
+ return(pc);
+}
+
+
+Chunk *skip_declspec_next(Chunk *pc)
+{
+ Chunk *next = skip_declspec(pc);
+
+ if ( next != pc
+ && next->Is(CT_PAREN_CLOSE))
+ {
+ pc = next->GetNextNcNnl();
+ }
+ return(pc);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.h
new file mode 100644
index 00000000..8bd9134e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_skip.h
@@ -0,0 +1,137 @@
+/**
+ * @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 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);
+
+
+#endif /* COMBINE_SKIP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_tools.cpp
new file mode 100644
index 00000000..53818133
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_tools.cpp
@@ -0,0 +1,569 @@
+/**
+ * @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->GetType()));
+ LOG_FMT(LFPARAM, "%s(%d): end->Text() is '%s', type is %s\n",
+ __func__, __LINE__, end->Text(), get_token_name(end->GetType()));
+
+ int word_count = 0;
+ int type_count = 0;
+ Chunk *pc = Chunk::NullChunkPtr;
+ Chunk *first_word = Chunk::NullChunkPtr;
+ bool first_word_set = false;
+
+ for (pc = start;
+ 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->GetType()));
+
+ if ( pc->Is(CT_QUALIFIER)
+ || pc->Is(CT_STRUCT)
+ || pc->Is(CT_ENUM)
+ || pc->Is(CT_UNION)
+ || pc->Is(CT_TYPENAME))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== %s! (yes)\n",
+ __func__, __LINE__, get_token_name(pc->GetType()));
+ return(true);
+ }
+
+ if ( pc->Is(CT_WORD)
+ || pc->Is(CT_TYPE))
+ {
+ ++word_count;
+
+ if (!first_word_set)
+ {
+ first_word = pc;
+ first_word_set = true;
+ }
+
+ if (pc->Is(CT_TYPE))
+ {
+ ++type_count;
+ }
+ }
+ else if ( pc->Is(CT_MEMBER)
+ || pc->Is(CT_DC_MEMBER))
+ {
+ if (word_count > 0)
+ {
+ --word_count;
+ }
+ }
+ else if ( pc != start
+ && pc->IsPointerOperator())
+ {
+ // chunk is OK
+ }
+ else if (pc->Is(CT_ASSIGN))
+ {
+ // chunk is OK (default values)
+ break;
+ }
+ else if (pc->Is(CT_ANGLE_OPEN))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== template\n",
+ __func__, __LINE__);
+
+ return(true);
+ }
+ else if (pc->Is(CT_ELLIPSIS))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== ellipsis\n",
+ __func__, __LINE__);
+
+ return(true);
+ }
+ else if ( word_count == 0
+ && pc->Is(CT_PAREN_OPEN))
+ {
+ // Check for old-school func proto param '(type)'
+ Chunk *tmp1 = pc->GetClosingParen(E_Scope::PREPROC);
+
+ if (tmp1->IsNullChunk())
+ {
+ return(false);
+ }
+ Chunk *tmp2 = tmp1->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp2->IsNullChunk())
+ {
+ return(false);
+ }
+
+ if ( tmp2->Is(CT_COMMA)
+ || tmp2->IsParenClose())
+ {
+ 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->GetType()));
+ } 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->GetType()));
+ return(false);
+ }
+ }
+ else if ( ( word_count == 1
+ || (word_count == type_count))
+ && pc->Is(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->Is(CT_QUALIFIER))
+ {
+ // tmp2 is the "nullable" qualifier in this case:
+ // void (^nullable name)(params)
+ // skip the qualifier
+ tmp2 = tmp2->GetNextNcNnl(E_Scope::PREPROC);
+ }
+
+ if (tmp2->IsNullChunk())
+ {
+ return(false);
+ }
+ Chunk *tmp3 = (tmp2->IsString(")")) ? tmp2 : tmp2->GetNextNcNnl(E_Scope::PREPROC);
+
+ if (tmp3->IsNullChunk())
+ {
+ return(false);
+ }
+
+ if ( !tmp3->IsString(")")
+ || !( tmp1->IsString("*")
+ || tmp1->IsString("^")) // Issue #2656
+ || !( tmp2->GetType() == CT_WORD
+ || tmp2->IsString(")")))
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== '%s' not fcn type!\n",
+ __func__, __LINE__, get_token_name(pc->GetType()));
+ 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 (tmp1->IsString("("))
+ {
+ tmp3 = tmp1->GetClosingParen(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->GetType()));
+
+ // reset some vars to allow [] after parens
+ word_count = 1;
+ type_count = 1;
+ }
+ else if (pc->Is(CT_TSQUARE))
+ {
+ // ignore it
+ }
+ else if ( word_count == 1
+ && pc->Is(CT_SQUARE_OPEN))
+ {
+ // skip over any array stuff
+ pc = pc->GetClosingParen(E_Scope::PREPROC);
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()));
+ }
+ else if ( word_count == 2
+ && pc->Is(CT_SQUARE_OPEN))
+ {
+ // Bug #671: is it such as: bool foo[FOO_MAX]
+ pc = pc->GetClosingParen(E_Scope::PREPROC);
+ LOG_FMT(LFPARAM, "%s(%d): pc->Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()));
+ }
+ else if ( word_count == 1
+ && language_is_set(LANG_CPP)
+ && pc->IsString("&&"))
+ {
+ // 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->GetType()), 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->GetType()));
+ }
+
+ 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->GetType()));
+
+ if (last->IsPointerOperator())
+ {
+ LOG_FMT(LFPARAM, "%s(%d): <== type is %s, sure!\n",
+ __func__, __LINE__, get_token_name(last->GetType()));
+ return(true);
+ }
+
+ if ( word_count < 2
+ && type_count < 1
+ && start->GetBraceLevel() > 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->GetBraceLevel() - 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(brace->GetParentType()), brace->GetOrigLine(), brace->GetOrigCol());
+ }
+
+ if ( brace->IsNotNullChunk()
+ && ( brace->GetParentType() == CT_CLASS
+ || brace->GetParentType() == 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->IsNullChunk() ? "null chunk" : get_token_name(pc->GetType())));
+ 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->IsNotNullChunk())
+ {
+ 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->IsNullChunk() ? "null chunk" : get_token_name(pc->GetType())));
+
+ 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();
+
+ if (start->TestFlags(PCF_IN_FCN_CTOR))
+ {
+ return(false);
+ }
+ Chunk *pc = start;
+ bool ret = false;
+ size_t cnt = 0;
+ bool last_expr = false;
+ bool last_lval = 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->GetType()), pc->Text(),
+ pc->GetOrigLine(), pc->GetOrigCol());
+ log_pcf_flags(LFTYPE, pc->GetFlags());
+
+ if ( pc->Is(CT_WORD)
+ || pc->Is(CT_TYPE)
+ || pc->Is(CT_PTR_TYPE)
+ || pc->Is(CT_STAR)
+ || pc->Is(CT_STRUCT)
+ || pc->Is(CT_DC_MEMBER)
+ || pc->Is(CT_PP)
+ || pc->Is(CT_QUALIFIER)
+ || ( language_is_set(LANG_CPP | LANG_OC) // Issue #2727
+ && pc->GetParentType() == CT_TEMPLATE
+ && ( pc->Is(CT_ANGLE_OPEN)
+ || pc->Is(CT_ANGLE_CLOSE)))
+ || ( language_is_set(LANG_CS | LANG_VALA)
+ && (pc->Is(CT_MEMBER))))
+ {
+ cnt++;
+ last_expr = pc->TestFlags(PCF_EXPR_START)
+ && !pc->TestFlags(PCF_IN_FCN_CALL);
+ last_lval = pc->TestFlags(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 ( ( pc->IsSemicolon()
+ && !pc->TestFlags(PCF_IN_FOR))
+ || pc->Is(CT_TYPEDEF)
+ || pc->Is(CT_BRACE_OPEN)
+ || pc->IsBraceClose()
+ || pc->Is(CT_FPAREN_CLOSE)
+ || pc->IsOCForinOpenParen()
+ || pc->Is(CT_MACRO)
+ || pc->Is(CT_PP_IF)
+ || pc->Is(CT_PP_ELSE)
+ || pc->Is(CT_PP_ENDIF)
+ || pc->GetParentType() == CT_PP_INCLUDE // Issue #3233
+ || ( ( pc->Is(CT_COMMA)
+ && !pc->TestFlags(PCF_IN_FCN_CALL)
+ && get_cpp_template_angle_nest_level(start) ==
+ get_cpp_template_angle_nest_level(pc))
+ && last_expr)
+ || ( pc->Is(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->GetStr().equals(tmp->GetStr()))
+ {
+ return(true);
+ }
+ }
+
+ return(false);
+} // chunkstack_match
+
+
+void flag_series(Chunk *start, Chunk *end, PcfFlags set_flags, PcfFlags clr_flags, E_Scope nav)
+{
+ LOG_FUNC_ENTRY();
+
+ while ( start->IsNotNullChunk()
+ && start != end)
+ {
+ start->UpdateFlagBits(clr_flags, set_flags);
+ log_pcf_flags(LFTYPE, start->GetFlags());
+
+ start = start->GetNext(nav);
+
+ if (start->IsNullChunk())
+ {
+ return;
+ }
+ }
+
+ if (end->IsNotNullChunk())
+ {
+ end->UpdateFlagBits(clr_flags, set_flags);
+ log_pcf_flags(LFTYPE, end->GetFlags());
+ }
+} // flag_series
+
+
+size_t get_cpp_template_angle_nest_level(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+ int nestLevel = 0;
+
+ while ( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_IN_TEMPLATE))
+ {
+ if ( pc->Is(CT_ANGLE_CLOSE)
+ && pc->GetParentType() == CT_TEMPLATE)
+ {
+ --nestLevel;
+ }
+ else if ( pc->Is(CT_ANGLE_OPEN)
+ && pc->GetParentType() == 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->GetLevel() > open_paren->GetLevel())
+ {
+ if ( tmp->Is(CT_TYPE)
+ || tmp->Is(CT_WORD))
+ {
+ if (maybe_type)
+ {
+ make_type(tmp);
+ cs.Push_Back(tmp);
+ }
+ maybe_type = false;
+ }
+ else if (tmp->Is(CT_COMMA))
+ {
+ maybe_type = true;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ return(tmp);
+} // get_d_template_types
+
+
+bool go_on(Chunk *pc, Chunk *start)
+{
+ if ( pc->IsNullChunk()
+ || pc->GetLevel() != start->GetLevel())
+ {
+ return(false);
+ }
+
+ if (pc->TestFlags(PCF_IN_FOR))
+ {
+ return( (!pc->IsSemicolon())
+ && (!(pc->Is(CT_COLON))));
+ }
+ return(!pc->IsSemicolon());
+} // 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->IsNotNullChunk())
+ {
+ if (pc->Is(CT_WORD))
+ {
+ pc->SetType(CT_TYPE);
+ }
+ else if ( ( pc->IsStar()
+ || pc->IsMsRef()
+ || pc->IsNullable())
+ && pc->GetPrev()->IsTypeDefinition()) // Issue # 2640
+ {
+ pc->SetType(CT_PTR_TYPE);
+ }
+ else if ( pc->IsAddress()
+ && pc->GetPrev()->IsNot(CT_SQUARE_OPEN)) // Issue # 2166
+ {
+ pc->SetType(CT_BYREF);
+ }
+ }
+} // make_type
+
+
+Chunk *set_paren_parent(Chunk *start, E_Token parent_type)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *end;
+
+ end = start->GetClosingParen(E_Scope::PREPROC);
+
+ if (end->IsNotNullChunk())
+ {
+ LOG_FMT(LFLPAREN, "%s(%d): %zu:%zu '%s' and %zu:%zu '%s' type is %s, parent type is %s",
+ __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), start->Text(),
+ end->GetOrigLine(), end->GetOrigCol(), end->Text(),
+ get_token_name(start->GetType()), get_token_name(parent_type));
+ log_func_stack_inline(LFLPAREN);
+ start->SetParentType(parent_type);
+ end->SetParentType(parent_type);
+ LOG_FMT(LFLPAREN, "%s(%d):\n", __func__, __LINE__);
+ return(end->GetNextNcNnl(E_Scope::PREPROC));
+ }
+ LOG_FMT(LFLPAREN, "%s(%d):\n", __func__, __LINE__);
+ return(Chunk::NullChunkPtr);
+} // set_paren_parent
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/combine_tools.h
new file mode 100644
index 00000000..a2575bfc
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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, PcfFlags set_flags, PcfFlags 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.78.0/src/compat.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/compat.h
new file mode 100644
index 00000000..66d60a06
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/compat.h
@@ -0,0 +1,26 @@
+/**
+ * @file compat.h
+ * prototypes for compat_xxx.cpp
+ *
+ * @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.78.0/src/compat_posix.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/compat_posix.cpp
new file mode 100644
index 00000000..c77c7a89
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/compat_win32.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/compat_win32.cpp
new file mode 100644
index 00000000..ff79199d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 != nullptr)
+ {
+ 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.78.0/src/config.h.in b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/config.h.in
new file mode 100644
index 00000000..420de635
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 substitute if compiler doesn't 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.78.0/src/cs_top_is_question.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/cs_top_is_question.cpp
new file mode 100644
index 00000000..b9b5b958
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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() ? Chunk::NullChunkPtr : cs.Top()->m_pc;
+
+ return( pc->Is(CT_QUESTION)
+ && pc->GetLevel() == level);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/cs_top_is_question.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/cs_top_is_question.h
new file mode 100644
index 00000000..de6ace3e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/detect.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/detect.cpp
new file mode 100644
index 00000000..2f0be40a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/detect.cpp
@@ -0,0 +1,445 @@
+/**
+ * @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();
+
+
+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->IsNullChunk()
+ || first->IsNewline()
+ || second->IsNullChunk()
+ || second->IsNewline())
+ {
+ return;
+ }
+ int col_dif = second->GetColumn() - (first->GetColumn() + 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 "options::xxx()"
+#define SP_VOTE_VAR(x) sp_votes vote_ ## x(options::x)
+
+
+static void detect_space_options()
+{
+ 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_between_ptr_ref);
+ 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 ( pc->Is(CT_ARITH)
+ || pc->Is(CT_SHIFT))
+ {
+ vote_sp_arith.vote(pc, next);
+ vote_sp_arith.vote(prev, pc);
+ }
+
+ if (pc->Is(CT_ASSIGN))
+ {
+ if (!pc->TestFlags(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 (pc->Is(CT_SQUARE_OPEN))
+ {
+ vote_sp_before_square.vote(prev, pc);
+ vote_sp_inside_square.vote(pc, next);
+ }
+
+ if (pc->Is(CT_SQUARE_CLOSE))
+ {
+ vote_sp_inside_square.vote(prev, pc);
+ }
+
+ if (pc->Is(CT_TSQUARE))
+ {
+ vote_sp_before_squares.vote(prev, pc);
+ }
+
+ if (pc->Is(CT_BOOL))
+ {
+ vote_sp_bool.vote(prev, pc);
+ vote_sp_bool.vote(pc, next);
+ }
+
+ if (pc->Is(CT_COMPARE))
+ {
+ vote_sp_compare.vote(prev, pc);
+ vote_sp_compare.vote(pc, next);
+ }
+
+ if (pc->Is(CT_PAREN_CLOSE))
+ {
+ vote_sp_inside_paren.vote(prev, pc);
+ }
+
+ if (pc->Is(CT_PAREN_OPEN))
+ {
+ vote_sp_inside_paren.vote(pc, next);
+ }
+
+ if ( ( pc->IsParenOpen()
+ && next->IsParenOpen())
+ || ( pc->IsParenClose()
+ && next->IsParenClose()))
+ {
+ vote_sp_paren_paren.vote(pc, next);
+ }
+
+ if ( pc->IsParenClose()
+ && next->Is(CT_BRACE_OPEN))
+ {
+ vote_sp_paren_brace.vote(pc, next);
+ }
+
+ if (pc->Is(CT_PTR_TYPE))
+ {
+ if (prev->Is(CT_PTR_TYPE))
+ {
+ vote_sp_between_ptr_star.vote(prev, pc);
+ }
+ else if (next->IsNot(CT_WORD))
+ {
+ vote_sp_before_unnamed_ptr_star.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_before_ptr_star.vote(prev, pc);
+ }
+
+ if (CharTable::IsKw1(next->GetStr()[0]))
+ {
+ vote_sp_after_ptr_star.vote(pc, next);
+ }
+ }
+
+ if (pc->Is(CT_BYREF))
+ {
+ if (next->IsNot(CT_WORD))
+ {
+ vote_sp_before_unnamed_byref.vote(prev, pc);
+ }
+
+ if (prev->Is(CT_PTR_TYPE))
+ {
+ vote_sp_between_ptr_ref.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_before_byref.vote(prev, pc);
+ }
+ vote_sp_after_byref.vote(pc, next);
+ }
+
+ if ( pc->IsNot(CT_PTR_TYPE)
+ && ( prev->Is(CT_QUALIFIER)
+ || prev->Is(CT_TYPE)))
+ {
+ vote_sp_after_type.vote(prev, pc);
+ }
+
+ if (pc->Is(CT_ANGLE_OPEN))
+ {
+ vote_sp_inside_angle.vote(pc, next);
+
+ if (prev->Is(CT_TEMPLATE))
+ {
+ vote_sp_template_angle.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_before_angle.vote(prev, pc);
+ }
+ }
+
+ if (pc->Is(CT_ANGLE_CLOSE))
+ {
+ vote_sp_inside_angle.vote(prev, pc);
+
+ if (next->IsParenOpen())
+ {
+ vote_sp_angle_paren.vote(prev, pc);
+ }
+ else if ( next->Is(CT_WORD)
+ || CharTable::IsKw1(next->GetStr()[0]))
+ {
+ vote_sp_angle_word.vote(prev, pc);
+ }
+ else
+ {
+ vote_sp_after_angle.vote(pc, next);
+ }
+ }
+
+ if (pc->Is(CT_SPAREN_OPEN))
+ {
+ vote_sp_before_sparen.vote(prev, pc);
+ vote_sp_inside_sparen.vote(pc, next);
+ }
+
+ if (pc->Is(CT_SPAREN_CLOSE))
+ {
+ vote_sp_inside_sparen.vote(prev, pc);
+
+ if (next->Is(CT_BRACE_OPEN))
+ {
+ vote_sp_sparen_brace.vote(pc, next);
+ }
+ else
+ {
+ vote_sp_after_sparen.vote(pc, next);
+ }
+ }
+
+ if (pc->Is(CT_SEMICOLON))
+ {
+ if (pc->GetParentType() == CT_FOR)
+ {
+ if (prev->Is(CT_SPAREN_OPEN))
+ {
+ // empty, ie for (;;)
+ // ^ is prev
+ // ^ is pc
+ vote_sp_before_semi_for_empty.vote(prev, pc);
+ }
+ else if (next->Is(CT_SPAREN_CLOSE))
+ {
+ // empty, ie for (;;)
+ // ^ is pc
+ // ^ is next
+ vote_sp_after_semi_for_empty.vote(pc, next);
+ }
+ else if (prev->IsNot(CT_SEMICOLON))
+ {
+ // empty, ie for (; i < 8;)
+ // ^ is pc
+ // or
+ // ^ is prev
+ vote_sp_before_semi_for.vote(prev, pc);
+ }
+ }
+ else if (prev->Is(CT_VBRACE_OPEN))
+ {
+ vote_sp_special_semi.vote(prev->GetPrev(), pc);
+ }
+ else
+ {
+ vote_sp_before_semi.vote(prev, pc);
+ }
+ }
+
+ if (pc->Is(CT_COMMA))
+ {
+ vote_sp_before_comma.vote(prev, pc);
+ vote_sp_after_comma.vote(pc, next);
+ }
+
+ if (pc->Is(CT_CLASS_COLON))
+ {
+ vote_sp_before_class_colon.vote(prev, pc);
+ vote_sp_after_class_colon.vote(pc, next);
+ }
+
+ if (pc->Is(CT_BRACE_OPEN))
+ {
+ if (prev->Is(CT_ELSE))
+ {
+ vote_sp_else_brace.vote(prev, pc);
+ }
+ else if (prev->Is(CT_CATCH))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+ else if (prev->Is(CT_FINALLY))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+ else if (prev->Is(CT_TRY))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+ else if (prev->Is(CT_GETSET))
+ {
+ vote_sp_catch_brace.vote(prev, pc);
+ }
+
+ if (next->Is(CT_BRACE_CLOSE))
+ {
+ vote_sp_inside_braces_empty.vote(pc, next);
+ }
+ else
+ {
+ vote_sp_inside_braces.vote(pc, next);
+ }
+ }
+
+ if (pc->Is(CT_BRACE_CLOSE))
+ {
+ vote_sp_inside_braces.vote(prev, pc);
+
+ if (next->Is(CT_ELSE))
+ {
+ vote_sp_brace_else.vote(pc, next);
+ }
+ else if (next->Is(CT_CATCH))
+ {
+ vote_sp_brace_catch.vote(pc, next);
+ }
+ else if (next->Is(CT_FINALLY))
+ {
+ vote_sp_brace_finally.vote(pc, next);
+ }
+ }
+ prev = pc;
+ pc = next;
+ }
+} // detect_space_options
+
+
+void detect_options()
+{
+ detect_space_options();
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/detect.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/detect.h
new file mode 100644
index 00000000..203aad16
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/detect.h
@@ -0,0 +1,16 @@
+/**
+ * @file detect.h
+ * prototypes for detect.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef DETECT_H_INCLUDED
+#define DETECT_H_INCLUDED
+
+
+//! Call all the detect_xxxx() functions
+void detect_options();
+
+
+#endif /* DETECT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_cleanup.cpp
new file mode 100644
index 00000000..f89f61c4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_cleanup.cpp
@@ -0,0 +1,95 @@
+/**
+ * @file enum_cleanup.cpp
+ * works on the last comma within 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()
+{
+ 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 ( pc->GetParentType() == CT_ENUM
+ && pc->Is(CT_BRACE_CLOSE))
+ {
+ LOG_FMT(LTOK, "%s(%d): orig line is %zu, type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), get_token_name(pc->GetType()));
+ Chunk *prev = pc->GetPrevNcNnl(); // Issue #3604
+
+ if (prev->IsNotNullChunk())
+ {
+ if (prev->Is(CT_COMMA))
+ {
+ log_rule_B("mod_enum_last_comma");
+
+ if (options::mod_enum_last_comma() == IARF_REMOVE)
+ {
+ Chunk::Delete(prev);
+ }
+ }
+ else
+ {
+ if (prev->Is(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;
+ comma.SetType(CT_COMMA);
+ comma.SetOrigLine(prev->GetOrigLine());
+ comma.SetOrigCol(prev->GetOrigCol() + 1);
+ comma.SetNlCount(0);
+ comma.SetPpLevel(0);
+ comma.SetFlags(PCF_NONE);
+ comma.Str() = ",";
+
+ if (prev->Is(CT_PP_ENDIF)) // Issue #3604
+ {
+ prev = prev->GetPrevNcNnlNpp();
+ }
+
+ if (prev->Is(CT_COMMA)) // Issue #3604
+ {
+ // nothing to do
+ }
+ else
+ {
+ comma.CopyAndAddAfter(prev);
+ }
+ pc = pc->GetNext();
+ }
+ }
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+} // enum_cleanup
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_cleanup.h
new file mode 100644
index 00000000..f9c46dc2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 within enum
+ */
+void enum_cleanup();
+
+#endif /* ENUM_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_flags.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/enum_flags.h
new file mode 100644
index 00000000..4f4e33c5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/error_types.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/error_types.h
new file mode 100644
index 00000000..4b162768
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/flag_braced_init_list.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_braced_init_list.cpp
new file mode 100644
index 00000000..66c128fa
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_braced_init_list.cpp
@@ -0,0 +1,112 @@
+/**
+ * @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 (pc->Is(CT_COLON))
+ {
+ // check if we have a case before
+ Chunk *switch_before = pc->GetPrevType(CT_CASE, pc->GetLevel());
+
+ 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->GetOrigLine(), switch_before->GetOrigCol(),
+ switch_before->Text(), get_token_name(switch_before->GetType()));
+ we_have_a_case_before = true;
+ }
+ }
+
+ // Detect a braced-init-list
+ if ( pc->Is(CT_WORD)
+ || pc->Is(CT_TYPE)
+ || pc->Is(CT_ASSIGN)
+ || pc->Is(CT_RETURN)
+ || pc->Is(CT_COMMA)
+ || pc->Is(CT_ANGLE_CLOSE)
+ || pc->Is(CT_SQUARE_CLOSE)
+ || pc->Is(CT_TSQUARE)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_QUESTION)
+ || ( pc->Is(CT_COLON)
+ && !we_have_a_case_before)
+ || ( pc->Is(CT_BRACE_OPEN)
+ && ( pc->GetParentType() == CT_NONE
+ || pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ log_pcf_flags(LFCNR, pc->GetFlags());
+ auto brace_open = pc->GetNextNcNnl();
+
+ if ( brace_open->Is(CT_BRACE_OPEN)
+ && ( brace_open->GetParentType() == CT_NONE
+ || brace_open->GetParentType() == CT_ASSIGN
+ || brace_open->GetParentType() == CT_RETURN
+ || brace_open->GetParentType() == CT_BRACED_INIT_LIST))
+ {
+ log_pcf_flags(LFCNR, brace_open->GetFlags());
+ auto brace_close = next->GetClosingParen();
+
+ if (brace_close->Is(CT_BRACE_CLOSE))
+ {
+ return(true);
+ }
+ }
+ }
+ return(false);
+} // detect_cpp_braced_init_list
+
+
+void flag_cpp_braced_init_list(Chunk *pc, Chunk *next)
+{
+ Chunk *brace_open = pc->GetNextNcNnl();
+ Chunk *brace_close = next->GetClosingParen();
+
+ brace_open->SetParentType(CT_BRACED_INIT_LIST);
+ brace_close->SetParentType(CT_BRACED_INIT_LIST);
+
+ Chunk *tmp = brace_close->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->ResetFlagBits(PCF_EXPR_START | PCF_STMT_START);
+
+ // Flag call operator
+ if (tmp->Is(CT_PAREN_OPEN))
+ {
+ Chunk *c = tmp->GetClosingParen();
+
+ if (c->IsNotNullChunk())
+ {
+ tmp->SetType(CT_FPAREN_OPEN);
+ tmp->SetParentType(CT_FUNC_CALL);
+ c->SetType(CT_FPAREN_CLOSE);
+ c->SetParentType(CT_FUNC_CALL);
+ }
+ }
+ }
+ // TODO: Change pc->GetType() CT_WORD -> CT_TYPE
+ // for the case CT_ASSIGN (and others).
+
+ // TODO: Move this block to the fix_fcn_call_args function.
+ if ( pc->Is(CT_WORD)
+ && pc->TestFlags(PCF_IN_FCN_CALL))
+ {
+ pc->SetType(CT_TYPE);
+ }
+} // flag_cpp_braced_init_list
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_braced_init_list.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_braced_init_list.h
new file mode 100644
index 00000000..75d19a79
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_braced_init_list.h
@@ -0,0 +1,27 @@
+/**
+ * @file flag_braced_init_list.h
+ *
+ * @license GPL v2+
+ */
+
+#ifndef FLAG_BRACED_INIT_LIST_INCLUDED
+#define FLAG_BRACED_INIT_LIST_INCLUDED
+
+#include "chunk.h"
+
+
+/**
+ * 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.78.0/src/flag_decltype.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_decltype.cpp
new file mode 100644
index 00000000..6950bc10
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 (pc->Is(CT_DECLTYPE))
+ {
+ auto paren_open = pc->GetNextNcNnl();
+
+ if (paren_open->Is(CT_PAREN_OPEN))
+ {
+ // We would like to simply call Chunk::SkipToMatch(), 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.
+ paren_open->SetFlagBits(PCF_IN_DECLTYPE);
+ pc = paren_open->GetNextNcNnl();
+
+ for (int level = 1; pc->IsNotNullChunk() && level > 0; pc = pc->GetNextNcNnl())
+ {
+ level += pc->Is(CT_PAREN_OPEN);
+ level -= pc->Is(CT_PAREN_CLOSE);
+ pc->SetFlagBits(PCF_IN_DECLTYPE);
+ }
+
+ return(pc->IsNotNullChunk());
+ }
+ }
+ return(false);
+} // mark_cpp_decltype
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_decltype.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_decltype.h
new file mode 100644
index 00000000..293fcd02
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_decltype.h
@@ -0,0 +1,21 @@
+/**
+ * @file flag_decltype.h
+ *
+ * @license GPL v2+
+ */
+
+#ifndef FLAG_DECLTYPE_INCLUDED
+#define FLAG_DECLTYPE_INCLUDED
+
+#include "chunk.h"
+
+/**
+ * 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.78.0/src/flag_parens.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_parens.cpp
new file mode 100644
index 00000000..44de133b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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, PcfFlags flags, E_Token opentype, E_Token parent_type, bool parent_all)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *paren_close;
+
+ paren_close = po->GetClosingParen(E_Scope::PREPROC);
+
+ if (paren_close->IsNullChunk())
+ {
+ LOG_FMT(LERR, "%s(%d): no match for '%s' at [%zu:%zu]",
+ __func__, __LINE__, po->Text(), po->GetOrigLine(), po->GetOrigCol());
+ log_func_stack_inline(LERR);
+ exit(EX_SOFTWARE);
+ }
+ LOG_FMT(LFLPAREN, "%s(%d): between po is '%s', orig line is %zu, orig col is %zu, and\n",
+ __func__, __LINE__, po->Text(), po->GetOrigLine(), po->GetOrigCol());
+ 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->GetOrigLine(), paren_close->GetOrigCol(),
+ get_token_name(opentype), get_token_name(parent_type));
+ 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
+ && parent_type != CT_NONE))
+ {
+ Chunk *pc;
+
+ //for (pc = po;
+ for (pc = po->GetNext(E_Scope::PREPROC);
+ pc->IsNotNullChunk() && pc != after_paren_close;
+ pc = pc->GetNext(E_Scope::PREPROC))
+ {
+ pc->SetFlagBits(flags);
+
+ if (parent_all)
+ {
+ pc->SetParentType(parent_type);
+ }
+ }
+ }
+
+ if (opentype != CT_NONE)
+ {
+ po->SetType(opentype);
+ paren_close->SetType((E_Token)(opentype + 1));
+ }
+
+ if (parent_type != CT_NONE)
+ {
+ po->SetParentType(parent_type);
+ paren_close->SetParentType(parent_type);
+ }
+ }
+ return(paren_close->GetNextNcNnl(E_Scope::PREPROC));
+} // flag_parens
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_parens.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/flag_parens.h
new file mode 100644
index 00000000..b789a810
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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, PcfFlags flags, E_Token opentype, E_Token parenttype, bool parent_all);
+
+
+#endif /* FLAG_PARENS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.cpp
new file mode 100644
index 00000000..364a899e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.cpp
@@ -0,0 +1,4792 @@
+/**
+ * @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 "options.h"
+#include "options_for_QT.h"
+#include "parsing_frame_stack.h"
+#include "prototypes.h"
+#include "quick_align_again.h"
+#include "space.h"
+#include <cstdint>
+
+#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_function_name(
+ * param1, param2);
+ * a_really_long_function_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 ParsingFrame &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 ParsingFrame &frm);
+
+
+void indent_to_column(Chunk *pc, size_t column)
+{
+ LOG_FUNC_ENTRY();
+
+ if (column < pc->GetColumn())
+ {
+ column = pc->GetColumn();
+ }
+ 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->IsNullChunk()
+ || column == pc->GetColumn())
+ {
+ 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->GetOrigLine(), pc->GetColumn(), pc->Text(),
+ get_token_name(pc->GetType()), column);
+
+ const int col_delta = column - pc->GetColumn();
+ size_t min_col = column;
+
+ pc->SetColumn(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()
+ && pc->GetParentType() != CT_COMMENT_EMBED)
+ {
+ log_rule_B("indent_relative_single_line_comments");
+ almod = ( pc->IsSingleLineComment()
+ && 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->SetColumn(max(pc->GetOrigCol(), min_col));
+ }
+ else if (almod == align_mode_e::KEEP_REL)
+ {
+ // Keep same relative column
+ size_t orig_delta = pc->GetOrigPrevSp() + prev->Len();
+ orig_delta = max<size_t>(orig_delta, min_delta); // keeps orig_delta positive
+
+ pc->SetColumn(prev->GetColumn() + orig_delta);
+ }
+ else // SHIFT
+ {
+ // Shift by the same amount, keep above negative values
+ pc->SetColumn(( col_delta >= 0
+ || (size_t)(abs(col_delta)) < pc->GetColumn())
+ ? pc->GetColumn() + col_delta : 0);
+ pc->SetColumn(max(pc->GetColumn(), 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->GetType()), pc->GetOrigLine(), pc->GetColumn(), pc->GetOrigCol());
+ } while ( pc->IsNotNullChunk()
+ && pc->GetNlCount() == 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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy),
+ get_token_name(pc->GetType()), get_token_name(pc->GetParentType()),
+ column);
+ log_func_stack_inline(LINDLINE);
+
+ if (column == pc->GetColumn())
+ {
+ return;
+ }
+ int col_delta = column - pc->GetColumn();
+ size_t min_col = column;
+
+ pc->SetColumn(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->TestFlags(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->TestFlags(PCF_IN_QT_MACRO))
+ {
+ LOG_FMT(LINDLINE, "FLAGS is set: PCF_IN_QT_MACRO\n");
+ save_set_options_for_QT(pc->GetLevel());
+ }
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+
+ if (pc->GetNlCount())
+ {
+ 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
+ && pc->IsSingleLineComment()
+ && options::indent_relative_single_line_comments());
+
+ if ( is_comment
+ && pc->GetParentType() != CT_COMMENT_EMBED
+ && !keep)
+ {
+ pc->SetColumn(max(pc->GetOrigCol(), min_col));
+ LOG_FMT(LINDLINE, "%s(%d): set comment on line %zu to col %zu (orig %zu)\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetColumn(), pc->GetOrigCol());
+ }
+ else
+ {
+ pc->SetColumn(max(pc->GetColumn() + col_delta, min_col));
+
+ LOG_FMT(LINDLINED, "%s(%d): set column of ", __func__, __LINE__);
+
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LINDLINED, "<Newline>");
+ }
+ else
+ {
+ LOG_FMT(LINDLINED, "'%s'", pc->Text());
+ }
+ LOG_FMT(LINDLINED, " to %zu (orig %zu/%zu)\n", pc->GetColumn(), pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ } while ( pc->IsNotNullChunk()
+ && pc->GetNlCount() == 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->GetOrigLine(), 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->GetLevel());
+
+ if (continuation->IsNotNullChunk())
+ {
+ continuation = continuation->GetNext();
+
+ if (continuation->IsNotNullChunk())
+ {
+ return(continuation->GetOrigCol());
+ }
+ }
+ return(0);
+}
+
+
+static size_t calc_indent_continue(const ParsingFrame &frm, size_t pse_tos)
+{
+ log_rule_B("indent_continue");
+ const int ic = options::indent_continue();
+
+ if ( ic < 0
+ && frm.at(pse_tos).GetIndentContinue())
+ {
+ return(frm.at(pse_tos).GetIndent());
+ }
+ return(frm.at(pse_tos).GetIndent() + abs(ic));
+}
+
+
+static size_t calc_indent_continue(const ParsingFrame &frm)
+{
+ return(calc_indent_continue(frm, frm.size() - 1));
+}
+
+
+static Chunk *candidate_chunk_first_on_line(Chunk *pc)
+{
+ Chunk *first = pc->GetFirstChunkOnLine();
+
+ log_rule_B("indent_inside_ternary_operator");
+
+ if ( options::indent_inside_ternary_operator()
+ && ( first->Is(CT_QUESTION)
+ || first->Is(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 = pc->GetPrevNc();
+
+ if (from_brace)
+ {
+ return(pc);
+ }
+
+ // Skip to open paren in ':^TYPE *(ARGS) {'
+ if (tmp->IsParenClose())
+ {
+ tmp = tmp->GetOpeningParen()->GetPrevNc();
+ }
+
+ // // Check for star in ':^TYPE *(ARGS) {'. Issue 2477
+ if (tmp->Is(CT_PTR_TYPE))
+ {
+ tmp = tmp->GetPrevNc();
+ }
+
+ // Check for type in ':^TYPE *(ARGS) {'. Issue 2482
+ if (tmp->Is(CT_TYPE))
+ {
+ tmp = tmp->GetPrevNc();
+ }
+ // Check for caret in ':^TYPE *(ARGS) {'
+ // Store the caret position
+ Chunk *caret_tmp = Chunk::NullChunkPtr;
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetType() == CT_OC_BLOCK_CARET)
+ {
+ caret_tmp = tmp;
+ }
+ else
+ {
+ caret_tmp = tmp->GetPrevType(CT_OC_BLOCK_CARET);
+ tmp = caret_tmp;
+ }
+
+ // If we still cannot find caret then return first chunk on the line
+ if ( tmp->IsNullChunk()
+ || tmp->IsNot(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->IsNot(CT_OC_COLON))
+ {
+ return(candidate_chunk_first_on_line(pc));
+ }
+ else
+ {
+ return(tmp);
+ }
+ }
+ tmp = tmp->GetPrevNc();
+
+ if (from_keyword)
+ {
+ if ( tmp->IsNullChunk()
+ || ( tmp->IsNot(CT_OC_MSG_NAME)
+ && tmp->IsNot(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 ParsingFrame &frm)
+{
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ...indent is %zu\n",
+ func, line, frm.size() - 1, frm.top().GetIndent());
+}
+
+
+#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 ParsingFrame &frm)
+{
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, prev....indent is %zu\n",
+ func, line, frm.size() - 1, frm.prev().GetIndent());
+}
+
+
+#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 ParsingFrame &frm)
+{
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ...indent_tmp is %zu\n",
+ func, line, frm.size() - 1, frm.top().GetIndentTmp());
+}
+
+
+static void quick_indent_again()
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->GetIndentData().ref == nullptr)
+ {
+ continue;
+ }
+ Chunk *tmp = pc->GetPrev();
+
+ if (!tmp->IsNewline())
+ {
+ continue;
+ }
+ const size_t col = pc->GetIndentData().ref->GetColumn() + pc->GetIndentData().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->GetOrigLine(), pc->Text(), col,
+ pc->GetIndentData().ref->Text(), pc->GetIndentData().ref->GetOrigLine(),
+ pc->GetIndentData().ref->GetColumn());
+ }
+}
+
+
+void indent_text()
+{
+ 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;
+
+
+ ParsingFrameStack frames;
+ ParsingFrame frm;
+
+
+ Chunk *pc = Chunk::GetHead();
+ bool classFound = false; // Issue #672
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LINDLINE, pc);
+
+ // Mark continuation lines if absolute indentation is requested
+ if ( options::indent_continue() < 0
+ && ( pc->Is(CT_PAREN_OPEN)
+ || pc->Is(CT_LPAREN_OPEN)
+ || pc->Is(CT_SPAREN_OPEN)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_RPAREN_OPEN)
+ || pc->Is(CT_SQUARE_OPEN)
+ || pc->Is(CT_ANGLE_OPEN)))
+ {
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNewline())
+ {
+ while (next->IsNewline())
+ {
+ next = next->GetNext();
+ }
+
+ if ( next->IsNotNullChunk()
+ && !next->IsPreproc())
+ {
+ // Mark chunk as continuation line, so indentation can be
+ // correctly set over multiple passes
+ next->SetFlagBits(PCF_CONT_LINE);
+
+ // Mark open and close parens as continuation line chunks.
+ // This will prevent an additional level and frame to be
+ // added to the current frame stack (issue 3105).
+ LOG_FMT(LSPLIT, "%s(%d): set PCF_LINE_CONT for pc text '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+
+ pc->SetFlagBits(PCF_CONT_LINE);
+ Chunk *closing_paren = pc->GetClosingParen();
+
+ if (closing_paren->IsNotNullChunk())
+ {
+ closing_paren->SetFlagBits(PCF_CONT_LINE);
+ }
+ }
+ }
+ }
+ // forces string literal to column-1 [Fix for 1246]
+ log_rule_B("indent_col1_multi_string_literal");
+
+ if ( (pc->GetType() == 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()->GetType() == CT_NEWLINE))
+ {
+ indent_column_set(1);
+ reindent_line(pc, indent_column);
+ pc = pc->GetNext();
+ did_newline = false;
+ }
+ }
+
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): orig line is %zu, <Newline>\n",
+ __func__, __LINE__, pc->GetOrigLine());
+ }
+ else if (pc->Is(CT_NL_CONT))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): orig line is %zu, CT_NL_CONT\n",
+ __func__, __LINE__, pc->GetOrigLine());
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->GetColumn(), pc->ElidedText(copy));
+ log_pcf_flags(LINDLINE, pc->GetFlags());
+ }
+ 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->GetOrigLine(), get_token_name(pc->GetType()));
+ }
+ // Handle preprocessor transitions
+ log_rule_B("indent_brace_parent");
+ const size_t parent_token_indent = (options::indent_brace_parent())
+ ? token_indent(pc->GetParentType()) : 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 ( pc->GetParentType() == CT_FUNC_DEF
+ || ( pc->Is(CT_COMMENT)
+ && next->IsNotNullChunk()
+ && next->GetParentType() == CT_FUNC_DEF))
+ {
+ in_func_def = true;
+ frm.push(pc, __func__, __LINE__);
+ frm.top().SetIndentTmp(1);
+ frm.top().SetIndent(1);
+ frm.top().SetIndentTab(1);
+ }
+ }
+ else
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->Is(CT_BRACE_CLOSE)
+ && prev->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ }
+ // Clean up after a #define, etc
+ const bool in_preproc = pc->TestFlags(PCF_IN_PREPROC);
+
+ if (!in_preproc)
+ {
+ while ( !frm.empty()
+ && frm.top().GetInPreproc())
+ {
+ const E_Token type = frm.top().GetOpenToken();
+ LOG_FMT(LINDLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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().GetOpenToken() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ }
+ else if (pc->Is(CT_PREPROC)) // #
+ {
+ // Close out PP_IF_INDENT before playing with the parse frames
+ if ( frm.top().GetOpenToken() == CT_PP_IF_INDENT
+ && ( pc->GetParentType() == CT_PP_ENDIF
+ || pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ ParsingFrame frmbkup = frm;
+ frames.check(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()
+ && pc->GetParentType() == CT_PP_REGION)
+ {
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ // Hack to get the logs to look right
+ next->SetType(CT_PP_REGION_INDENT);
+ frm.push(next, __func__, __LINE__);
+ next->SetType(CT_PP_REGION);
+
+ // Indent one level
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTab(frm.prev().GetIndentTab() + indent_size);
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ frm.top().SetInPreproc(false);
+ log_indent_tmp();
+ }
+ // If option set, remove indent inside switch statement
+ log_rule_B("indent_switch_pp");
+
+ if ( frm.top().GetOpenToken() == 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().GetIndent(), indent_size);
+
+ if (frm.top().GetIndent() >= indent_size)
+ {
+ frm.prev().SetIndent(frm.top().GetIndent() - 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()
+ && ( pc->GetParentType() == CT_PP_IF
+ || pc->GetParentType() == 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->IsNot(CT_NEWLINE))
+ {
+ if ( (preproc_next->Is(CT_BRACE_OPEN))
+ || (preproc_next->Is(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 ( ( preproc_next->Is(CT_FUNC_DEF)
+ && !options::pp_indent_func_def())
+ || ( preproc_next->Is(CT_CASE)
+ && !options::pp_indent_case())
+ || ( preproc_next->Is(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->GetType();
+ next->SetType(CT_PP_IF_INDENT);
+ frm.push(next, __func__, __LINE__);
+ next->SetType(memtype);
+
+ if (should_ignore_preproc)
+ {
+ // Preserve original indentation
+ frm.top().SetIndent(pc->GetNextNl()->GetNext()->GetOrigCol());
+ log_indent();
+ }
+ else
+ {
+ // Indent one level except if the #if is a #include guard
+ size_t extra = ( pc->GetPpLevel() == 0
+ && ifdef_over_whole_file())
+ ? 0 : indent_size;
+
+ frm.top().SetIndent(frm.prev().GetIndent() + extra);
+ log_indent();
+
+ frm.top().SetIndentTab(frm.prev().GetIndentTab() + extra);
+ }
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ frm.top().SetInPreproc(false);
+ log_indent_tmp();
+ }
+ }
+ log_rule_B("indent_member_single");
+
+ if (options::indent_member_single())
+ {
+ if (pc->GetParentType() == CT_PP_IF)
+ {
+ // do nothing
+ }
+ else if (pc->GetParentType() == CT_PP_ELSE)
+ {
+ if ( frm.top().GetOpenToken() == CT_MEMBER
+ && frm.top().GetPopChunk()->IsNotNullChunk()
+ && frm.top().GetOpenChunk() != frmbkup.top().GetOpenChunk())
+ {
+ Chunk *tmp = pc->GetNextNcNnlNpp();
+
+ if (tmp->IsNotNullChunk())
+ {
+ if ( tmp->Is(CT_WORD)
+ || tmp->Is(CT_TYPE))
+ {
+ tmp = pc->GetNextNcNnlNpp();
+ }
+ else if ( tmp->Is(CT_FUNC_CALL)
+ || tmp->Is(CT_FPAREN_OPEN))
+ {
+ tmp = tmp->GetNextType(CT_FPAREN_CLOSE, tmp->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = pc->GetNextNcNnlNpp();
+ }
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ frm.top().SetPopChunk(tmp);
+ }
+ }
+ }
+ }
+ else if (pc->GetParentType() == CT_PP_ENDIF)
+ {
+ if ( frmbkup.top().GetOpenToken() == CT_MEMBER
+ && frm.top().GetOpenToken() == CT_MEMBER)
+ {
+ frm.top().SetPopChunk(frmbkup.top().GetPopChunk());
+ }
+ }
+ }
+ // 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 ( pc->GetParentType() == CT_PP_DEFINE
+ || pc->GetParentType() == CT_PP_UNDEF)
+ {
+ log_rule_B("pp_define_at_level");
+ frm.top().SetIndentTmp(options::pp_define_at_level()
+ ? frm.prev().GetIndentTmp() : 1);
+
+ log_rule_B("pp_multiline_define_body_indent");
+
+ if (options::pp_multiline_define_body_indent() < 0)
+ {
+ frm.top().SetIndent(-options::pp_multiline_define_body_indent());
+ }
+ else
+ {
+ frm.top().SetIndent(pc->GetColumn() + options::pp_multiline_define_body_indent());
+ }
+ log_indent();
+
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if ( ( pc->GetParentType() == CT_PP_PRAGMA
+ || pc->GetParentType() == CT_PP_OTHER)
+ && options::pp_define_at_level())
+ {
+ log_rule_B("pp_define_at_level");
+ frm.top().SetIndentTmp(frm.prev().GetIndentTmp());
+ frm.top().SetIndent(frm.top().GetIndentTmp() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if ( pc->GetParentType() == CT_PP_INCLUDE
+ && options::pp_include_at_level())
+ {
+ log_rule_B("pp_include_at_level");
+ frm.top().SetIndentTmp(frm.prev().GetIndentTmp());
+ frm.top().SetIndent(frm.top().GetIndentTmp() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else
+ {
+ if ( (frm.prev().GetOpenToken() == CT_PP_REGION_INDENT)
+ || ( (frm.prev().GetOpenToken() == CT_PP_IF_INDENT)
+ && (frm.top().GetOpenToken() != CT_PP_ENDIF)))
+ {
+ frm.top().SetIndent(frm.prev(2).GetIndent());
+ log_indent();
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndent());
+ log_indent();
+ }
+ log_indent();
+
+
+ int val = 0;
+
+ if ( pc->GetParentType() == CT_PP_REGION
+ || pc->GetParentType() == CT_PP_ENDREGION)
+ {
+ log_rule_B("pp_indent_region");
+ val = options::pp_indent_region();
+ log_indent();
+ }
+ else if ( pc->GetParentType() == CT_PP_IF
+ || pc->GetParentType() == CT_PP_ELSE
+ || pc->GetParentType() == CT_PP_ENDIF)
+ {
+ log_rule_B("pp_indent_if");
+ val = options::pp_indent_if();
+ log_indent();
+ }
+
+ if (val != 0)
+ {
+ size_t indent = frm.top().GetIndent();
+ indent = (val > 0) ? val // reassign if positive val,
+ : ((size_t)(abs(val)) < indent) // else if no underflow
+ ? (indent + val) : 0; // reduce, else 0
+ frm.top().SetIndent(indent);
+ }
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ }
+ // Check for close XML tags "</..."
+ log_rule_B("indent_xml_string");
+
+ if (options::indent_xml_string() > 0)
+ {
+ if (pc->Is(CT_STRING))
+ {
+ if ( pc->Len() > 4
+ && xml_indent > 0
+ && pc->GetStr()[1] == '<'
+ && pc->GetStr()[2] == '/')
+ {
+ log_rule_B("indent_xml_string");
+ xml_indent -= options::indent_xml_string();
+ }
+ }
+ else if (!pc->IsCommentOrNewline())
+ {
+ 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 ( !pc->IsCommentOrNewline()
+ && frm.top().GetOpenLevel() > pc->GetLevel())
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (frm.top().GetOpenLevel() >= pc->GetLevel())
+ {
+ // process virtual braces closes (no text output)
+ if ( pc->Is(CT_VBRACE_CLOSE)
+ && frm.top().GetOpenToken() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+
+ if (pc->IsNullChunk())
+ {
+ // need to break out of both the do and while loops
+ goto null_pc;
+ }
+ }
+
+ if ( pc->Is(CT_BRACE_CLOSE)
+ && pc->GetParentType() == CT_ENUM)
+ {
+ Chunk *prev_ncnl = pc->GetPrevNcNnl();
+ LOG_FMT(LINDLINE, "%s(%d): prev_ncnl is '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, prev_ncnl->Text(), prev_ncnl->GetOrigLine(), prev_ncnl->GetOrigCol());
+
+ if (prev_ncnl->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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().GetOpenToken() == CT_COND_COLON)
+ && ( pc->IsSemicolon()
+ || pc->Is(CT_COMMA)
+ || pc->Is(CT_OC_MSG_NAME)
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End any assign operations with a semicolon on the same level
+ if ( pc->IsSemicolon()
+ && ( (frm.top().GetOpenToken() == CT_IMPORT)
+ || (frm.top().GetOpenToken() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End any custom macro-based open/closes
+ if ( !token_used
+ && (frm.top().GetOpenToken() == CT_MACRO_OPEN)
+ && pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End any CPP/ObjC class colon stuff
+ if ( ( (frm.top().GetOpenToken() == CT_CLASS_COLON)
+ || (frm.top().GetOpenToken() == CT_CONSTR_COLON))
+ && ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_OC_END)
+ || pc->Is(CT_OC_SCOPE)
+ || pc->Is(CT_OC_PROPERTY)
+ || pc->Is(CT_TYPEDEF) // Issue #2675
+ || pc->Is(CT_MACRO_OPEN)
+ || pc->Is(CT_MACRO_CLOSE)
+ || ( language_is_set(LANG_OC)
+ && pc->IsComment()
+ && pc->GetParentType() == CT_COMMENT_WHOLE) // Issue #2675
+ || pc->IsSemicolon()))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // End ObjC class colon stuff inside of generic definition (like Test<T1: id<T3>>)
+ if ( (frm.top().GetOpenToken() == CT_CLASS_COLON)
+ && pc->Is(CT_ANGLE_CLOSE)
+ && pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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)
+ && pc->Is(CT_SQUARE_CLOSE)
+ && pc->GetParentType() == CT_OC_AT
+ && frm.top().GetOpenLevel() >= pc->GetLevel())
+ {
+ size_t count = 1;
+ Chunk *next = pc->GetNextNc();
+
+ while ( next->IsNotNullChunk()
+ && ( ( next->Is(CT_BRACE_CLOSE)
+ && next->GetParentType() == CT_OC_AT)
+ || ( next->Is(CT_SQUARE_CLOSE)
+ && next->GetParentType() == CT_OC_AT)
+ || ( next->Is(CT_SQUARE_CLOSE)
+ && next->GetParentType() == CT_OC_MSG)))
+ {
+ count++;
+ next = next->GetNextNc();
+ }
+ count = std::min(count, frm.size());
+
+ if (count > 0)
+ {
+ while (count-- > 0)
+ {
+ if (frm.top().GetOpenToken() == CT_SQUARE_OPEN)
+ {
+ if (frm.GetParenCount() == 0)
+ {
+ fprintf(stderr, "%s(%d): frame parenthesis count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ frm.SetParenCount(frm.GetParenCount() - 1);
+ }
+ LOG_FMT(LINDLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (next->IsNotNullChunk())
+ {
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ // Indent the brace to match outer most brace/square
+ indent_column_set(frm.top().GetIndentTmp());
+ continue;
+ }
+ }
+
+ // a case is ended with another case or a close brace
+ if ( (frm.top().GetOpenToken() == CT_CASE)
+ && ( pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (frm.top().GetPopChunk()->IsNotNullChunk())
+ {
+ 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().GetPopChunk()->GetOrigLine(), frm.top().GetPopChunk()->GetOrigCol(),
+ frm.top().GetPopChunk()->Text(), get_token_name(frm.top().GetPopChunk()->GetType()));
+ }
+ LOG_FMT(LINDLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+
+ if ( (frm.top().GetOpenToken() == CT_MEMBER)
+ && frm.top().GetPopChunk() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if ( (frm.top().GetOpenToken() == CT_LAMBDA)
+ && ( pc->Is(CT_SEMICOLON)
+ || pc->Is(CT_COMMA)
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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().GetOpenToken() == CT_ACCESS)
+ && ( pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // return & throw are ended with a semicolon
+ if ( pc->IsSemicolon()
+ && ( (frm.top().GetOpenToken() == CT_RETURN)
+ || (frm.top().GetOpenToken() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // an OC SCOPE ('-' or '+') ends with a semicolon or brace open
+ if ( (frm.top().GetOpenToken() == CT_OC_SCOPE)
+ && ( pc->IsSemicolon()
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ /*
+ * a typedef and an OC SCOPE ('-' or '+') ends with a semicolon or
+ * brace open
+ */
+ if ( (frm.top().GetOpenToken() == CT_TYPEDEF)
+ && ( pc->IsSemicolon()
+ || pc->IsParenOpen()
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // an SQL EXEC is ended with a semicolon
+ if ( (frm.top().GetOpenToken() == CT_SQL_EXEC)
+ && pc->IsSemicolon())
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // an CLASS is ended with a semicolon or brace open
+ if ( (frm.top().GetOpenToken() == CT_CLASS)
+ && ( pc->Is(CT_CLASS_COLON)
+ || pc->Is(CT_BRACE_OPEN)
+ || pc->IsSemicolon()))
+ {
+ LOG_FMT(LINDLINE, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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().GetOpenToken() != CT_SQUARE_OPEN)
+ && frm.top().GetOpenLevel() >= pc->GetLevel()
+ && ( pc->Is(CT_OC_MSG_FUNC)
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // Close out parenthesis and squares
+ if ( (frm.top().GetOpenToken() == (pc->GetType() - 1))
+ && ( pc->Is(CT_PAREN_CLOSE)
+ || pc->Is(CT_LPAREN_CLOSE) // Issue #3054
+ || pc->Is(CT_SPAREN_CLOSE)
+ || pc->Is(CT_FPAREN_CLOSE)
+ || pc->Is(CT_RPAREN_CLOSE) // Issue #3914
+ || pc->Is(CT_SQUARE_CLOSE)
+ || pc->Is(CT_ANGLE_CLOSE))
+ && ( !pc->TestFlags(PCF_CONT_LINE)
+ || options::indent_continue() >= 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+
+ if (frm.GetParenCount() == 0)
+ {
+ fprintf(stderr, "%s(%d): frame parenthesis count is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ frm.SetParenCount(frm.GetParenCount() - 1);
+ }
+ }
+ } while (old_frm_size > frm.size());
+
+ // Grab a copy of the current indent
+ indent_column_set(frm.top().GetIndentTmp()); // Issue #3294
+ log_indent_tmp();
+
+ log_rule_B("indent_single_newlines");
+
+ if ( pc->Is(CT_NEWLINE)
+ && options::indent_single_newlines())
+ {
+ pc->SetNlColumn(indent_column);
+ }
+
+ if ( !pc->IsCommentOrNewline()
+ && 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->GetOrigLine(), pc->GetOrigCol(), 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 continue=%d level=%zu pc brace level=%zu]\n",
+ ttidx,
+ frm.at(ttidx).GetOpenChunk()->GetOrigLine(),
+ frm.at(ttidx).GetOpenChunk()->GetOrigCol(),
+ frm.at(ttidx).GetOpenChunk()->Text(),
+ get_token_name(frm.at(ttidx).GetOpenToken()),
+ get_token_name(frm.at(ttidx).GetOpenChunk()->GetParentType()),
+ frm.at(ttidx).GetIndentTmp(),
+ frm.at(ttidx).GetIndent(),
+ frm.at(ttidx).GetBraceIndent(),
+ frm.at(ttidx).GetIndentTab(),
+ frm.at(ttidx).GetIndentContinue(),
+ frm.at(ttidx).GetOpenLevel(),
+ frm.at(ttidx).GetOpenChunk()->GetBraceLevel());
+ }
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->GetColumn(), pc->ElidedText(copy));
+
+ // Issue #672
+ if ( pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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 = ( ( pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_BRACE_OPEN))
+ && options::indent_braces()
+ && ( !options::indent_braces_no_func()
+ || pc->GetParentType() != CT_FUNC_DEF)
+ && ( !options::indent_braces_no_func()
+ || pc->GetParentType() != CT_FUNC_CLASS_DEF)
+ && ( !options::indent_braces_no_class()
+ || pc->GetParentType() != CT_CLASS)
+ && ( !options::indent_braces_no_struct()
+ || pc->GetParentType() != CT_STRUCT));
+ LOG_FMT(LINDENT, "%s(%d): brace_indent is %s\n",
+ __func__, __LINE__, brace_indent ? "true" : "false");
+
+ if (pc->Is(CT_BRACE_CLOSE))
+ {
+ if (language_is_set(LANG_OC))
+ {
+ if ( frm.top().GetOpenToken() == CT_BRACE_OPEN
+ && frm.top().GetOpenLevel() >= pc->GetLevel())
+ {
+ size_t count = 1;
+ Chunk *next = pc->GetNextNc();
+
+ while ( next->IsNotNullChunk()
+ && ( ( next->Is(CT_BRACE_CLOSE)
+ && next->GetParentType() == CT_OC_AT)
+ || ( next->Is(CT_SQUARE_CLOSE)
+ && next->GetParentType() == CT_OC_AT)))
+ {
+ 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
+ && pc->Is(CT_BRACE_CLOSE)
+ && pc->GetParentType() == CT_OC_AT)
+ {
+ if (frm.top().GetIndentData().ref)
+ {
+ pc->IndentData().ref = frm.top().GetIndentData().ref;
+ pc->IndentData().delta = 0;
+ }
+
+ while (count-- > 0)
+ {
+ LOG_CHUNK(LINDLINE, pc);
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ if (next->IsNotNullChunk())
+ {
+ // End any assign operations with a semicolon on the same level
+ if (is_end_of_assignment(next, frm))
+ {
+ LOG_CHUNK(LINDLINE, pc);
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+
+ // Indent the brace to match outer most brace/square
+ if (frm.top().GetIndentContinue())
+ {
+ indent_column_set(frm.top().GetIndentTmp() - indent_size);
+ }
+ else
+ {
+ indent_column_set(frm.top().GetIndentTmp());
+ }
+ }
+ else
+ {
+ // Indent the brace to match the open brace
+ indent_column_set(frm.top().GetBraceIndent());
+
+ if (frm.top().GetIndentData().ref)
+ {
+ pc->IndentData().ref = frm.top().GetIndentData().ref;
+ pc->IndentData().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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ }
+ else if (frm.top().GetBraceIndent()) // Issue #3421
+ {
+ // Indent the brace to match the open brace
+ indent_column_set(frm.top().GetBraceIndent());
+
+ if (frm.top().GetIndentData().ref)
+ {
+ pc->IndentData().ref = frm.top().GetIndentData().ref;
+ pc->IndentData().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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ }
+ else if (pc->Is(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().GetIndent() + iMinIndent;
+
+ log_rule_B("indent_vbrace_open_on_tabstop");
+
+ if (options::indent_vbrace_open_on_tabstop())
+ {
+ iNewIndent = next_tab_column(iNewIndent);
+ }
+ frm.top().SetIndent(iNewIndent);
+ log_indent();
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent_tmp();
+
+ // Always indent on virtual braces
+ indent_column_set(frm.top().GetIndentTmp());
+ }
+ else if ( pc->Is(CT_BRACE_OPEN)
+ && pc->GetNext()->IsNot(CT_NAMESPACE))
+ {
+ LOG_FMT(LINDENT2, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ frm.push(pc, __func__, __LINE__);
+
+ log_rule_B("indent_macro_brace");
+
+ if ( !options::indent_macro_brace()
+ && frm.prev().GetOpenToken() == CT_PP_DEFINE
+ && frm.prev().GetOpenLine() == frm.top().GetOpenLine())
+ {
+ LOG_FMT(LINDENT2, "%s(%d): indent_macro_brace\n", __func__, __LINE__);
+ }
+ else if ( options::indent_cpp_lambda_body()
+ && pc->GetParentType() == CT_CPP_LAMBDA)
+ {
+ log_rule_B("indent_cpp_lambda_body");
+ frm.top().SetBraceIndent(frm.prev().GetIndent());
+
+ Chunk *head = frm.top().GetOpenChunk()->GetPrevNcNnlNpp();
+ Chunk *tail = Chunk::NullChunkPtr;
+ Chunk *frm_prev = frm.prev().GetOpenChunk();
+ bool enclosure = ( frm_prev->GetParentType() != CT_FUNC_DEF // Issue #3407
+ && frm_prev != frm_prev->GetClosingParen());
+ bool linematch = true;
+
+ for (auto it = frm.rbegin(); it != frm.rend() && tail->IsNullChunk(); ++it)
+ {
+ if (it->GetOpenChunk() != frm.top().GetOpenChunk())
+ {
+ linematch &= it->GetOpenChunk()->IsOnSameLine(head);
+ }
+ Chunk *match = it->GetOpenChunk()->GetClosingParen();
+
+ if (match->IsNullChunk())
+ {
+ continue;
+ }
+ Chunk *target = match->GetNextNcNnlNpp();
+
+ while ( tail->IsNullChunk()
+ && target->IsNotNullChunk())
+ {
+ if ( target->IsSemicolon()
+ && target->GetLevel() == match->GetLevel())
+ {
+ tail = target;
+ }
+ else if (target->GetLevel() < match->GetLevel())
+ {
+ break;
+ }
+ else
+ {
+ target = target->GetNextNcNnlNpp();
+ }
+ }
+ }
+
+ bool toplevel = true;
+
+ for (auto it = frm.rbegin(); it != frm.rend() && tail->IsNotNullChunk(); ++it)
+ {
+ if (!it->GetOpenChunk()->Is(CT_FPAREN_OPEN))
+ {
+ continue;
+ }
+
+ if (it->GetOpenChunk()->GetLevel() < tail->GetLevel())
+ {
+ toplevel = false;
+ break;
+ }
+ }
+
+ // 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, and indent_continue is non-zero
+ bool sameLine = frm.top().GetOpenChunk()->GetClosingParen()->IsOnSameLine(tail);
+
+ bool isAssignSameLine =
+ !enclosure
+ && options::align_assign_span() == 0
+ && !options::indent_align_assign()
+ && frm.prev().GetOpenChunk()->GetPrevNcNnlNpp()->IsOnSameLine(frm.prev().GetOpenChunk())
+ && frm.prev().GetOpenChunk()->IsOnSameLine(frm.prev().GetOpenChunk()->GetNextNcNnlNpp());
+
+ bool closureSameLineTopLevel =
+ (options::indent_continue() > 0)
+ && enclosure
+ && linematch
+ && toplevel
+ && frm.top().GetOpenChunk()->GetClosingParen()->IsOnSameLine(frm.top().GetOpenChunk());
+
+ if ( sameLine
+ && ( (isAssignSameLine)
+ || (closureSameLineTopLevel)))
+ {
+ if (indent_size > frm.top().GetBraceIndent()) // if options::indent_indent_columns() is too big
+ {
+ frm.top().SetBraceIndent(1);
+ }
+ else
+ {
+ frm.top().SetBraceIndent(frm.top().GetBraceIndent() - indent_size);
+ }
+ }
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(indent_column + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+
+ frm.prev().SetIndentTmp(frm.top().GetIndentTmp());
+ log_indent_tmp();
+ }
+ else if ( language_is_set(LANG_CPP)
+ && options::indent_cpp_lambda_only_once()
+ && (pc->GetParentType() == 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->GetNsCount())
+ {
+ namespace_indent_to_ignore = i->GetNsCount();
+ break;
+ }
+ }
+ }
+ // Issue # 1296
+ frm.top().SetBraceIndent(1 + (pc->GetBraceLevel() - namespace_indent_to_ignore) * indent_size);
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(indent_column + indent_size);
+ log_indent();
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+
+ frm.prev().SetIndentTmp(frm.top().GetIndentTmp());
+ log_indent_tmp();
+ }
+ else if ( language_is_set(LANG_CS | LANG_JAVA)
+ && options::indent_cs_delegate_brace()
+ && ( pc->GetParentType() == CT_LAMBDA
+ || pc->GetParentType() == CT_DELEGATE))
+ {
+ log_rule_B("indent_cs_delegate_brace");
+ frm.top().SetBraceIndent(1 + (pc->GetBraceLevel() + 1) * indent_size);
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(indent_column + indent_size);
+ log_indent();
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+
+ frm.prev().SetIndentTmp(frm.top().GetIndentTmp());
+ log_indent_tmp();
+ }
+ else if ( language_is_set(LANG_CS | LANG_JAVA)
+ && !options::indent_cs_delegate_brace()
+ && !options::indent_align_paren()
+ && ( pc->GetParentType() == CT_LAMBDA
+ || pc->GetParentType() == CT_DELEGATE))
+ {
+ log_rule_B("indent_cs_delegate_brace");
+ log_rule_B("indent_align_paren");
+ frm.top().SetBraceIndent(frm.prev().GetIndent());
+
+ // Issue # 1620, UNI-24090.cs
+ if (frm.prev().GetOpenChunk()->IsOnSameLine(frm.top().GetOpenChunk()->GetPrevNcNnlNpp()))
+ {
+ frm.top().SetBraceIndent(frm.top().GetBraceIndent() - indent_size);
+ }
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(indent_column + indent_size);
+ log_indent();
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ frm.prev().SetIndentTmp(frm.top().GetIndentTmp());
+ log_indent_tmp();
+ }
+ else if ( !options::indent_paren_open_brace()
+ && !language_is_set(LANG_CS)
+ && pc->GetParentType() == CT_CPP_LAMBDA
+ && ( pc->TestFlags(PCF_IN_FCN_DEF)
+ || pc->TestFlags(PCF_IN_FCN_CTOR)) // Issue #2152
+ && pc->GetNextNc()->IsNewline())
+ {
+ log_rule_B("indent_paren_open_brace");
+ // Issue #1165
+ LOG_FMT(LINDENT2, "%s(%d): orig line is %zu, brace level is %zu, for '%s', pc->GetLevel() is %zu, pc(-1)->GetLevel() is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetBraceLevel(), pc->Text(), pc->GetLevel(), frm.prev().GetOpenChunk()->GetLevel());
+ frm.top().SetBraceIndent(1 + (pc->GetBraceLevel() + 1) * indent_size);
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(frm.prev().GetIndentTmp());
+ log_indent();
+
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ 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()
+ && frm.prev().GetOpenChunk()->IsParenOpen()
+ && pc->GetNextNc()->IsNewline())
+ {
+ log_rule_B("indent_paren_open_brace");
+ LOG_FMT(LINDENT2, "%s(%d): orig line is %zu, brace level is %zu, for '%s', pc->GetLevel() is %zu, pc(-1)->GetLevel() is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetBraceLevel(), pc->Text(), pc->GetLevel(), frm.prev().GetOpenChunk()->GetLevel());
+ // FIXME: I don't know how much of this is necessary, but it seems to work
+ frm.top().SetBraceIndent(1 + pc->GetBraceLevel() * indent_size);
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(indent_column + indent_size);
+ log_indent();
+
+ if ( (pc->GetParentType() == CT_OC_BLOCK_EXPR)
+ && pc->TestFlags(PCF_IN_OC_MSG))
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ log_indent();
+ frm.top().SetBraceIndent(frm.prev().GetIndentTmp());
+ indent_column_set(frm.top().GetBraceIndent());
+ }
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+
+ frm.prev().SetIndentTmp(frm.top().GetIndentTmp());
+ }
+ else if ( frm.GetParenCount() != 0
+ && !pc->TestFlags(PCF_IN_LAMBDA)) // Issue #3761
+ {
+ if (frm.top().GetOpenChunk()->GetParentType() == CT_OC_BLOCK_EXPR)
+ {
+ log_rule_B("indent_oc_block_msg");
+
+ if ( pc->TestFlags(PCF_IN_OC_MSG)
+ && options::indent_oc_block_msg())
+ {
+ frm.top().IndentData().ref = oc_msg_block_indent(pc, false, false, false, true);
+ log_rule_B("indent_oc_block_msg");
+ frm.top().IndentData().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->TestFlags(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 = pc->GetClosingParen(); // block brace close '}'
+ Chunk *bbc_next_ncnl = bbc->GetNextNcNnl();
+
+ if ( bbc_next_ncnl->GetType() == CT_OC_MSG_NAME
+ || bbc_next_ncnl->GetType() == 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->IsNotNullChunk())
+ {
+ frm.top().SetIndent(indent_size + ref->GetColumn());
+ }
+ else
+ {
+ frm.top().SetIndent(1 + ((pc->GetBraceLevel() + 1) * indent_size));
+ }
+ log_indent();
+ indent_column_set(frm.top().GetIndent() - indent_size);
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ log_indent();
+ }
+ }
+ else if ( frm.top().GetOpenChunk()->GetType() == CT_BRACE_OPEN
+ && frm.top().GetOpenChunk()->GetParentType() == CT_OC_AT)
+ {
+ // We are inside @{ ... } -- indent one tab from the paren
+ if (frm.prev().GetIndentContinue())
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp());
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ }
+ log_indent();
+ }
+ // Issue # 1620, UNI-24090.cs
+ else if ( frm.prev().GetOpenChunk()->IsOnSameLine(frm.top().GetOpenChunk())
+ && !options::indent_align_paren()
+ && frm.prev().GetOpenChunk()->IsParenOpen()
+ && !pc->TestFlags(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().SetBraceIndent(frm.prev().GetIndent() - indent_size);
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(frm.prev().GetIndentTmp());
+ log_indent();
+ }
+ else if ( frm.prev().GetOpenChunk()->IsOnSameLine(frm.top().GetOpenChunk()->GetPrevNcNnlNpp())
+ && !options::indent_align_paren()
+ && frm.prev().GetOpenChunk()->IsParenOpen()
+ && !pc->TestFlags(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().SetBraceIndent(frm.prev().GetIndent() - indent_size);
+ indent_column_set(frm.top().GetBraceIndent());
+ frm.top().SetIndent(frm.prev().GetIndentTmp());
+ log_indent();
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && ( frm.prev().GetOpenToken() == CT_OC_MSG_FUNC
+ || frm.prev().GetOpenToken() == CT_OC_MSG_NAME)) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ // [Class Message:{<here>
+ frm.top().SetIndent(frm.prev().GetOpenChunk()->GetColumn() + indent_size);
+ log_indent();
+ indent_column_set(frm.prev().GetOpenChunk()->GetColumn());
+ }
+ // Issue #3813
+ else if (pc->TestFlags(PCF_OC_IN_BLOCK) && pc->GetParentType() == CT_SWITCH)
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp());
+ }
+ else
+ {
+ // We are inside ({ ... }) -- indent one tab from the paren
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+
+ if (!frm.prev().GetOpenChunk()->IsParenOpen())
+ {
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ }
+ log_indent();
+ }
+ }
+ else if ( frm.top().GetOpenChunk()->GetType() == CT_BRACE_OPEN
+ && frm.top().GetOpenChunk()->GetParentType() == CT_OC_AT)
+ {
+ // We are inside @{ ... } -- indent one tab from the paren
+ if (frm.prev().GetIndentContinue())
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp());
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ }
+ log_indent();
+ }
+ else if ( ( pc->GetParentType() == CT_BRACED_INIT_LIST
+ || ( !options::indent_compound_literal_return()
+ && pc->GetParentType() == CT_C_CAST))
+ && frm.prev().GetOpenToken() == 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().GetIndentContinue())
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp());
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ }
+ log_indent();
+ }
+ else
+ {
+ // Use the prev indent level + indent_size.
+ if (pc->GetParentType() == CT_SWITCH)
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + options::indent_switch_body());
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ }
+ LOG_FMT(LINDLINE, "%s(%d): frm.pse_tos is %zu, ... indent is %zu\n",
+ __func__, __LINE__, frm.size() - 1, frm.top().GetIndent());
+ LOG_FMT(LINDLINE, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s', parent type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(),
+ get_token_name(pc->GetParentType()));
+
+ // If this brace is part of a statement, bump it out by indent_brace
+ if ( pc->GetParentType() == CT_IF
+ || pc->GetParentType() == CT_ELSE
+ || pc->GetParentType() == CT_ELSEIF
+ || pc->GetParentType() == CT_TRY
+ || pc->GetParentType() == CT_CATCH
+ || pc->GetParentType() == CT_DO
+ || pc->GetParentType() == CT_WHILE
+ || pc->GetParentType() == CT_USING_STMT
+ || pc->GetParentType() == CT_SWITCH
+ || pc->GetParentType() == CT_SYNCHRONIZED
+ || pc->GetParentType() == CT_FOR)
+ {
+ if (parent_token_indent != 0)
+ {
+ frm.top().SetIndent(frm.top().GetIndent() + parent_token_indent - indent_size);
+ log_indent();
+ }
+ else
+ {
+ log_rule_B("indent_brace");
+ frm.top().SetIndent(frm.top().GetIndent() + options::indent_brace());
+ log_indent();
+ indent_column_set(indent_column + options::indent_brace());
+ }
+ }
+ else if (pc->GetParentType() == CT_CASE)
+ {
+ if (options::indent_ignore_case_brace())
+ {
+ log_rule_B("indent_ignore_case_brace");
+ indent_column_set(pc->GetOrigCol());
+ }
+ else
+ {
+ log_rule_B("indent_case_brace");
+ const auto tmp_indent = static_cast<int>(frm.prev().GetIndent())
+ - static_cast<int>(indent_size)
+ + options::indent_case_brace();
+ /*
+ * An open brace with the parent of case does not indent by default
+ * options::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().SetIndent(indent_column + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if ( pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ frm.top().SetIndent(frm.top().GetIndent() - indent_size);
+ log_indent();
+ }
+ else if (pc->GetParentType() == CT_NAMESPACE)
+ {
+ frm.top().SetNsCount(frm.prev().GetNsCount() + 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().GetNsCount() >= 2)
+ {
+ // undo indent on all except the first namespace
+ frm.top().SetIndent(frm.top().GetIndent() - indent_size);
+ log_indent();
+ }
+ indent_column_set(frm.prev(frm.top().GetNsCount()).GetIndent());
+ }
+ else if ( options::indent_namespace()
+ && options::indent_namespace_inner_only())
+ {
+ if (frm.top().GetNsCount() == 1)
+ {
+ // undo indent on first namespace only
+ frm.top().SetIndent(frm.top().GetIndent() - indent_size);
+ log_indent();
+ }
+ }
+ else if ( pc->TestFlags(PCF_LONG_BLOCK)
+ || !options::indent_namespace())
+ {
+ log_rule_B("indent_namespace");
+ // don't indent long blocks
+ frm.top().SetIndent(frm.top().GetIndent() - indent_size);
+ log_indent();
+ }
+ else // indenting 'short' namespace
+ {
+ log_rule_B("indent_namespace_level");
+
+ if (options::indent_namespace_level() > 0)
+ {
+ frm.top().SetIndent(frm.top().GetIndent() - indent_size);
+ log_indent();
+ frm.top().SetIndent(frm.top().GetIndent() + options::indent_namespace_level());
+ log_indent();
+ }
+ }
+ }
+ else if ( pc->GetParentType() == CT_EXTERN
+ && !options::indent_extern())
+ {
+ log_rule_B("indent_extern");
+ frm.top().SetIndent(frm.top().GetIndent() - indent_size);
+ log_indent();
+ }
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ }
+
+ if (pc->TestFlags(PCF_DONT_INDENT))
+ {
+ frm.top().SetIndent(pc->GetColumn());
+ log_indent();
+
+ indent_column_set(pc->GetColumn());
+ }
+ 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 ( pc->GetParentType() == CT_BRACED_INIT_LIST
+ && prev->Is(CT_BRACE_OPEN)
+ && prev->GetParentType() == CT_BRACED_INIT_LIST)
+ {
+ indent_column = frm.prev().GetBraceIndent();
+ frm.top().SetIndent(frm.prev().GetIndent());
+ log_indent();
+ }
+ else if ( !pc->IsNewlineBetween(next)
+ && next->GetParentType() != CT_BRACED_INIT_LIST
+ && options::indent_token_after_brace()
+ && !pc->TestFlags(PCF_ONE_LINER)) // Issue #1108
+ {
+ log_rule_B("indent_token_after_brace");
+ frm.top().SetIndent(next->GetColumn());
+ log_indent();
+ }
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ frm.top().SetOpenLine(pc->GetOrigLine());
+ 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().GetIndentTmp());
+ log_indent_tmp();
+ }
+ }
+ // Save the brace indent
+ frm.top().SetBraceIndent(indent_column);
+ }
+ else if (pc->Is(CT_SQL_END))
+ {
+ if (frm.top().GetOpenToken() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ indent_column_set(frm.top().GetIndentTmp());
+ log_indent_tmp();
+ }
+ }
+ else if ( pc->Is(CT_SQL_BEGIN)
+ || pc->Is(CT_MACRO_OPEN)
+ || ( pc->Is(CT_CLASS)
+ && language_is_set(LANG_CS))) // Issue #3536
+ {
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if (pc->Is(CT_SQL_EXEC))
+ {
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if (pc->Is(CT_MACRO_ELSE))
+ {
+ if (frm.top().GetOpenToken() == CT_MACRO_OPEN)
+ {
+ indent_column_set(frm.prev().GetIndent());
+ }
+ }
+ else if (pc->Is(CT_CASE))
+ {
+ // Start a case - indent options::indent_switch_case() from the switch level
+ log_rule_B("indent_switch_case");
+ const size_t tmp = frm.top().GetIndent() + indent_size
+ - options::indent_switch_body()
+ + options::indent_switch_case();
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().SetIndent(tmp);
+ log_indent();
+
+ log_rule_B("indent_case_shift");
+ frm.top().SetIndentTmp(tmp - indent_size + options::indent_case_shift());
+ frm.top().SetIndentTab(tmp);
+ log_indent_tmp();
+
+ // Always set on case statements
+ indent_column_set(frm.top().GetIndentTmp());
+
+ 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 (t2->IsNewline())
+ {
+ pct->SetColumn(frm.top().GetIndentTmp());
+ pct->SetColumnIndent(pct->GetColumn());
+ }
+ }
+ }
+ }
+ else if (pc->Is(CT_BREAK))
+ {
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if ( prev->Is(CT_BRACE_CLOSE)
+ && prev->GetParentType() == 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()->GetColumn());
+ }
+ }
+ }
+ else if (pc->Is(CT_LABEL))
+ {
+ if (options::indent_ignore_label())
+ {
+ log_rule_B("indent_ignore_label");
+ indent_column_set(pc->GetOrigCol());
+ }
+ else
+ {
+ log_rule_B("indent_label");
+ const int val = options::indent_label();
+ size_t pse_indent = frm.top().GetIndent();
+
+ // 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()
+ && !next->IsNewline()
+ // label (+ 2, because there is colon and space after it) must fit into indent
+ && (val + pc->Len() + 2 <= pse_indent))
+ {
+ reindent_line(next, pse_indent);
+ }
+ }
+ else
+ {
+ bool no_underflow = (size_t)(abs(val)) < pse_indent;
+ indent_column_set((no_underflow ? (pse_indent + val) : 0));
+ }
+ }
+ }
+ else if (pc->Is(CT_ACCESS))
+ {
+ log_rule_B("indent_access_spec_body");
+
+ if (options::indent_access_spec_body())
+ {
+ const size_t tmp = frm.top().GetIndent() + indent_size;
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().SetIndent(tmp);
+ log_indent();
+
+ frm.top().SetIndentTmp(tmp - indent_size);
+ frm.top().SetIndentTab(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().GetIndentTmp());
+ // 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()
+ && !pct->IsDoxygenComment())
+ {
+ Chunk *t2 = pct->GetPrev();
+
+ if (t2->IsNewline())
+ {
+ pct->SetColumn(frm.top().GetIndentTmp());
+ pct->SetColumnIndent(pct->GetColumn());
+ }
+ }
+ }
+ else
+ {
+ // Access spec labels get sent to the left or backed up
+ log_rule_B("indent_access_spec");
+ int val = options::indent_access_spec();
+
+ if (val > 0)
+ {
+ indent_column_set(val);
+ }
+ else
+ {
+ size_t pse_indent = frm.top().GetIndent();
+ bool no_underflow = (size_t)(abs(val)) < pse_indent;
+
+ indent_column_set(no_underflow ? (pse_indent + val) : 0);
+ }
+ }
+ }
+ else if ( pc->Is(CT_CLASS_COLON)
+ || pc->Is(CT_CONSTR_COLON))
+ {
+ // just indent one level
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent_tmp();
+
+ if (pc->Is(CT_CLASS_COLON))
+ {
+ if (options::indent_ignore_before_class_colon())
+ {
+ log_rule_B("indent_ignore_before_class_colon");
+ frm.top().SetIndentTmp(pc->GetOrigCol());
+ log_indent_tmp();
+ }
+ else if (options::indent_before_class_colon() != 0)
+ {
+ log_rule_B("indent_before_class_colon");
+ frm.top().SetIndentTmp(std::max<ptrdiff_t>(frm.top().GetIndentTmp() + options::indent_before_class_colon(), 0));
+ log_indent_tmp();
+ }
+ }
+ indent_column_set(frm.top().GetIndentTmp());
+
+ log_rule_B("indent_class_colon");
+
+ if ( options::indent_class_colon()
+ && pc->Is(CT_CLASS_COLON))
+ {
+ log_rule_B("indent_class_on_colon");
+
+ if (options::indent_class_on_colon())
+ {
+ frm.top().SetIndent(pc->GetColumn());
+ log_indent();
+ }
+ else
+ {
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && !next->IsNewline())
+ {
+ frm.top().SetIndent(next->GetColumn());
+ log_indent();
+ }
+ }
+ }
+ else if (pc->Is(CT_CONSTR_COLON))
+ {
+ if (options::indent_ignore_before_constr_colon())
+ {
+ log_rule_B("indent_ignore_before_constr_colon");
+ frm.top().SetIndentTmp(pc->GetOrigCol());
+ indent_column_set(frm.top().GetIndentTmp());
+ }
+
+ if (options::indent_constr_colon())
+ {
+ log_rule_B("indent_constr_colon");
+ Chunk *prev = pc->GetPrev();
+
+ if (prev->IsNewline())
+ {
+ log_rule_B("indent_ctor_init_following");
+ frm.top().SetIndent(frm.top().GetIndent() + 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().SetIndent(std::max<ptrdiff_t>(frm.top().GetIndent() + options::indent_ctor_init(), 0));
+ log_indent();
+ frm.top().SetIndentTmp(std::max<ptrdiff_t>(frm.top().GetIndentTmp() + options::indent_ctor_init(), 0));
+ frm.top().SetIndentTab(std::max<ptrdiff_t>(frm.top().GetIndentTab() + options::indent_ctor_init(), 0));
+ log_indent_tmp();
+ indent_column_set(frm.top().GetIndentTmp());
+ }
+ else if (options::indent_class_on_colon())
+ {
+ frm.top().SetIndent(pc->GetColumn());
+ log_indent();
+ }
+ else
+ {
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && !next->IsNewline())
+ {
+ frm.top().SetIndent(next->GetColumn());
+ log_indent();
+ }
+ }
+ }
+ }
+ }
+ else if ( pc->Is(CT_PAREN_OPEN)
+ && ( pc->GetParentType() == CT_ASM
+ || ( pc->GetPrevNcNnl()->IsNotNullChunk()
+ && pc->GetPrevNcNnl()->GetType() == CT_ASM))
+ && options::indent_ignore_asm_block())
+ {
+ log_rule_B("indent_ignore_asm_block");
+ Chunk *tmp = pc->GetClosingParen();
+
+ int move = 0;
+
+ if ( pc->GetPrev()->IsNewline()
+ && pc->GetColumn() != indent_column)
+ {
+ move = indent_column - pc->GetColumn();
+ }
+ else
+ {
+ move = pc->GetColumn() - pc->GetOrigCol();
+ }
+
+ do
+ {
+ if (!pc->TestFlags(PCF_IN_PREPROC))
+ {
+ pc->SetColumn(pc->GetOrigCol() + move);
+ }
+ pc = pc->GetNext();
+ } while (pc != tmp);
+
+ reindent_line(pc, indent_column);
+ }
+ else if ( ( pc->Is(CT_PAREN_OPEN)
+ || pc->Is(CT_LPAREN_OPEN) // Issue #3054
+ || pc->Is(CT_SPAREN_OPEN)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_RPAREN_OPEN) // Issue #3914
+ || pc->Is(CT_SQUARE_OPEN)
+ || pc->Is(CT_ANGLE_OPEN))
+ && ( !pc->TestFlags(PCF_CONT_LINE)
+ || options::indent_continue() >= 0))
+ {
+ /*
+ * Open parenthesis and squares - never update indent_column,
+ * unless right after a newline.
+ */
+ frm.push(pc, __func__, __LINE__);
+
+ if ( pc->GetPrev()->IsNewline()
+ && pc->GetColumn() != indent_column
+ && !pc->TestFlags(PCF_DONT_INDENT))
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig line is %zu, indent => %zu, text is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ frm.top().SetIndent(pc->GetColumn() + pc->Len());
+ log_indent();
+
+ if ( pc->Is(CT_SQUARE_OPEN)
+ && language_is_set(LANG_D))
+ {
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ }
+ bool skipped = false;
+ log_rule_B("indent_inside_ternary_operator");
+ log_rule_B("indent_align_paren");
+
+ if ( options::indent_inside_ternary_operator()
+ && ( pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_PAREN_OPEN))
+ && frm.size() > 2
+ && ( frm.prev().GetOpenToken() == CT_QUESTION
+ || frm.prev().GetOpenToken() == CT_COND_COLON)
+ && !options::indent_align_paren())
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ log_indent();
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if ( ( pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_ANGLE_OPEN))
+ && ( ( options::indent_func_call_param()
+ && ( pc->GetParentType() == CT_FUNC_CALL
+ || pc->GetParentType() == CT_FUNC_CALL_USER))
+ || ( options::indent_func_proto_param()
+ && pc->GetParentType() == CT_FUNC_PROTO)
+ || ( options::indent_func_class_param()
+ && ( pc->GetParentType() == CT_FUNC_CLASS_DEF
+ || pc->GetParentType() == CT_FUNC_CLASS_PROTO))
+ || ( options::indent_template_param()
+ && pc->GetParentType() == CT_TEMPLATE)
+ || ( options::indent_func_ctor_var_param()
+ && pc->GetParentType() == CT_FUNC_CTOR_VAR)
+ || ( options::indent_func_def_param()
+ && pc->GetParentType() == CT_FUNC_DEF)
+ || ( !options::indent_func_def_param() // Issue #931
+ && pc->GetParentType() == CT_FUNC_DEF
+ && options::indent_func_def_param_paren_pos_threshold() > 0
+ && pc->GetOrigCol() > 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).GetOpenToken() != CT_BRACE_OPEN
+ && frm.at(idx).GetOpenToken() != CT_VBRACE_OPEN
+ && frm.at(idx).GetOpenToken() != CT_PAREN_OPEN
+ && frm.at(idx).GetOpenToken() != CT_FPAREN_OPEN
+ && frm.at(idx).GetOpenToken() != CT_RPAREN_OPEN // Issue #3914
+ && frm.at(idx).GetOpenToken() != CT_SPAREN_OPEN
+ && frm.at(idx).GetOpenToken() != CT_SQUARE_OPEN
+ && frm.at(idx).GetOpenToken() != CT_ANGLE_OPEN
+ && frm.at(idx).GetOpenToken() != CT_CASE
+ && frm.at(idx).GetOpenToken() != CT_MEMBER
+ && frm.at(idx).GetOpenToken() != CT_QUESTION
+ && frm.at(idx).GetOpenToken() != CT_COND_COLON
+ && frm.at(idx).GetOpenToken() != CT_LAMBDA
+ && frm.at(idx).GetOpenToken() != CT_ASSIGN_NL)
+ || frm.at(idx).GetOpenChunk()->IsOnSameLine(frm.top().GetOpenChunk()))
+ && ( frm.at(idx).GetOpenToken() != CT_CLASS_COLON
+ && frm.at(idx).GetOpenToken() != CT_CONSTR_COLON
+ && !( frm.at(idx).GetOpenToken() == CT_LAMBDA
+ && frm.at(idx).GetOpenChunk()->GetPrevNc()->GetType() == CT_NEWLINE)))
+ {
+ if (idx == 0)
+ {
+ fprintf(stderr, "%s(%d): idx is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ idx--;
+ skipped = true;
+ }
+ // PR#381
+ log_rule_B("indent_param");
+
+ if (options::indent_param() != 0)
+ {
+ frm.top().SetIndent(frm.at(idx).GetIndent() + options::indent_param());
+ log_indent();
+ }
+ else
+ {
+ frm.top().SetIndent(frm.at(idx).GetIndent() + 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().SetIndent(frm.top().GetIndent() + indent_size);
+ log_indent();
+ }
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && pc->Is(CT_PAREN_OPEN)
+ && frm.size() > 2
+ && ( frm.prev().GetOpenToken() == CT_OC_MSG_FUNC
+ || frm.prev().GetOpenToken() == 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().SetIndent(frm.prev().GetOpenChunk()->GetColumn() + indent_size);
+ log_indent();
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if ( pc->Is(CT_PAREN_OPEN)
+ && !pc->GetNext()->IsNewline()
+ && !options::indent_align_paren()
+ && !pc->TestFlags(PCF_IN_SPAREN))
+ {
+ log_rule_B("indent_align_paren");
+ size_t idx = frm.size() - 2;
+
+ while ( idx > 0
+ && frm.at(idx).GetOpenChunk()->IsOnSameLine(frm.top().GetOpenChunk()))
+ {
+ idx--;
+ skipped = true;
+ }
+ frm.top().SetIndent(frm.at(idx).GetIndent() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ skipped = true;
+ }
+ else if ( ( pc->IsString("(")
+ && !options::indent_paren_nl())
+ || ( pc->IsString("<")
+ && !options::indent_paren_nl()) // TODO: add indent_angle_nl?
+ || ( pc->IsString("[")
+ && !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 ( next->IsNewline()
+ && !options::indent_paren_after_func_def()
+ && !options::indent_paren_after_func_decl()
+ && !options::indent_paren_after_func_call()
+ && ( !pc->TestFlags(PCF_CONT_LINE)
+ || options::indent_continue() >= 0))
+ {
+ size_t sub = 2;
+
+ if ( (frm.prev().GetOpenToken() == CT_ASSIGN)
+ || (frm.prev().GetOpenToken() == CT_RETURN))
+ {
+ sub = 3;
+ }
+ sub = frm.size() - sub;
+
+ log_rule_B("indent_align_paren");
+
+ if (!options::indent_align_paren())
+ {
+ sub = frm.size() - 2;
+
+ while ( sub > 0
+ && frm.at(sub).GetOpenChunk()->IsOnSameLine(frm.top().GetOpenChunk()))
+ {
+ sub--;
+ skipped = true;
+ }
+
+ if ( ( frm.at(sub + 1).GetOpenToken() == CT_CLASS_COLON
+ || frm.at(sub + 1).GetOpenToken() == CT_CONSTR_COLON)
+ && (frm.at(sub + 1).GetOpenChunk()->GetPrev()->Is(CT_NEWLINE)))
+ {
+ sub = sub + 1;
+ }
+ }
+ frm.top().SetIndent(frm.at(sub).GetIndent() + indent_size);
+ log_indent();
+
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ skipped = true;
+ }
+ else
+ {
+ if ( next->IsNotNullChunk()
+ && !next->IsComment())
+ {
+ if (next->Is(CT_SPACE))
+ {
+ next = next->GetNextNc();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ }
+
+ if (next->GetPrev()->IsComment())
+ {
+ // Issue #2099
+ frm.top().SetIndent(next->GetPrev()->GetColumn());
+ }
+ else
+ {
+ frm.top().SetIndent(next->GetColumn());
+ }
+ 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().GetIndentContinue() // Issue #3567
+ && vardefcol == 0)
+ || ( !options::use_indent_continue_only_once() // Issue #1160
+ && !options::indent_ignore_first_continue())) // Issue #3561
+ && ( pc->Is(CT_FPAREN_OPEN)
+ && pc->GetPrev()->IsNewline())
+ && ( ( ( pc->GetParentType() == CT_FUNC_PROTO
+ || pc->GetParentType() == CT_FUNC_CLASS_PROTO)
+ && options::indent_paren_after_func_decl())
+ || ( ( pc->GetParentType() == CT_FUNC_DEF
+ || pc->GetParentType() == CT_FUNC_CLASS_DEF)
+ && options::indent_paren_after_func_def())
+ || ( ( pc->GetParentType() == CT_FUNC_CALL
+ || pc->GetParentType() == CT_FUNC_CALL_USER)
+ && options::indent_paren_after_func_call())
+ || !pc->GetNext()->IsNewline()))
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ log_indent();
+
+ indent_column_set(frm.top().GetIndent());
+ }
+ log_rule_B("indent_continue");
+
+ if ( pc->GetParentType() != CT_OC_AT
+ && ( options::indent_ignore_first_continue()
+ || options::indent_continue() != 0)
+ && !skipped)
+ {
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().SetIndent(get_indent_first_continue(pc->GetNext()));
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndent());
+ }
+ log_indent();
+
+ if ( pc->GetLevel() == pc->GetBraceLevel()
+ && !options::indent_ignore_first_continue()
+ && ( pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_RPAREN_OPEN) // Issue #1170
+ || pc->Is(CT_SPAREN_OPEN)
+ || ( pc->Is(CT_SQUARE_OPEN)
+ && pc->GetParentType() != CT_OC_MSG)
+ || pc->Is(CT_ANGLE_OPEN))) // Issue #1170
+ {
+ log_rule_B("use_indent_continue_only_once");
+
+ if ( (options::use_indent_continue_only_once())
+ && (frm.top().GetIndentContinue())
+ && 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().SetIndent(vardefcol);
+ log_indent();
+ }
+ else
+ {
+ frm.top().SetIndent(calc_indent_continue(frm));
+ log_indent();
+ frm.top().SetIndentContinue(true);
+
+ log_rule_B("indent_sparen_extra");
+
+ if ( pc->Is(CT_SPAREN_OPEN)
+ && options::indent_sparen_extra() != 0)
+ {
+ frm.top().SetIndent(frm.top().GetIndent() + options::indent_sparen_extra());
+ log_indent();
+ }
+ }
+ }
+ }
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+
+ frm.SetParenCount(frm.GetParenCount() + 1);
+ }
+ else if ( options::indent_member_single()
+ && pc->Is(CT_MEMBER)
+ && (strcmp(pc->Text(), ".") == 0)
+ && language_is_set(LANG_CS | LANG_CPP))
+ {
+ log_rule_B("indent_member_single");
+
+ if (frm.top().GetOpenToken() != CT_MEMBER)
+ {
+ frm.push(pc, __func__, __LINE__);
+ Chunk *tmp = frm.top().GetOpenChunk()->GetPrevNcNnlNpp();
+
+ if (frm.prev().GetOpenChunk()->IsOnSameLine(tmp))
+ {
+ frm.top().SetIndent(frm.prev().GetIndent());
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ }
+ log_indent();
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+
+ if (pc->GetPrev()->IsNewline())
+ {
+ if ( pc->Is(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().GetIndent());
+ 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 (tmp->Is(CT_FUNC_CALL))
+ {
+ tmp = tmp->GetNextType(CT_FPAREN_CLOSE, tmp->GetLevel());
+ tmp = tmp->GetNextNcNnlNpp();
+ }
+ else if ( tmp->Is(CT_WORD)
+ || tmp->Is(CT_TYPE))
+ {
+ tmp = tmp->GetNextNcNnlNpp();
+ }
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && ( (strcmp(tmp->Text(), ".") != 0)
+ || tmp->IsNot(CT_MEMBER)))
+ {
+ if (tmp->IsParenClose())
+ {
+ tmp = tmp->GetPrevNcNnlNpp();
+ }
+ Chunk *local_prev = tmp->GetPrev(); // Issue #3294
+
+ if (local_prev->IsComment())
+ {
+ tmp = tmp->GetPrev(); // Issue #3294
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetPrev()->IsNewline())
+ {
+ tmp = tmp->GetPrevNcNnlNpp()->GetNextNl();
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ frm.top().SetPopChunk(tmp);
+ }
+ }
+ }
+ else if ( pc->Is(CT_ASSIGN)
+ || pc->Is(CT_IMPORT)
+ || ( pc->Is(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 ( pc->Is(CT_ASSIGN)
+ && pc->GetPrev()->IsNewline())
+ {
+ if (frm.top().GetOpenToken() == CT_ASSIGN_NL)
+ {
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ }
+ else
+ {
+ frm.top().SetIndentTmp(frm.top().GetIndent() + indent_size);
+ }
+ log_indent_tmp();
+
+ indent_column_set(frm.top().GetIndentTmp());
+ LOG_FMT(LINDENT, "%s(%d): %zu] assign => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, frm.top().GetIndentTmp());
+ }
+ 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 popping the previous assign and pushing the new one
+ */
+ if ( frm.top().GetOpenToken() == CT_ASSIGN
+ && pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ }
+ frm.push(pc, __func__, __LINE__);
+
+ if ( pc->Is(CT_ASSIGN)
+ && pc->GetPrev()->IsNewline())
+ {
+ frm.top().SetOpenToken(CT_ASSIGN_NL);
+ }
+ log_rule_B("indent_continue");
+
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().SetIndent(get_indent_first_continue(pc));
+ log_indent();
+ frm.top().SetIndentContinue(true); // Issue #3567
+ }
+ else if (options::indent_continue() != 0)
+ {
+ frm.top().SetIndent(frm.prev().GetIndent());
+ log_indent();
+
+ if ( pc->GetLevel() == pc->GetBraceLevel()
+ && ( pc->IsNot(CT_ASSIGN)
+ || ( pc->GetParentType() != CT_FUNC_PROTO
+ && pc->GetParentType() != CT_FUNC_DEF)))
+ {
+ log_rule_B("use_indent_continue_only_once");
+
+ if ( (options::use_indent_continue_only_once())
+ && (frm.top().GetIndentContinue())
+ && vardefcol != 0)
+ {
+ // if vardefcol isn't zero, use it
+ frm.top().SetIndent(vardefcol);
+ log_indent();
+ }
+ else
+ {
+ frm.top().SetIndent(calc_indent_continue(frm));
+ log_indent();
+
+ vardefcol = frm.top().GetIndent(); // use the same variable for the next line
+ frm.top().SetIndentContinue(true);
+ }
+ }
+ }
+ else if ( next->IsNewline()
+ || !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().SetIndent(frm.prev().GetIndentTmp());
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndentTmp() + indent_size);
+ }
+ log_indent();
+
+ if ( pc->Is(CT_ASSIGN)
+ && next->IsNewline())
+ {
+ frm.top().SetOpenToken(CT_ASSIGN_NL);
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ }
+ }
+ else
+ {
+ frm.top().SetIndent(pc->GetColumn() + pc->Len() + 1);
+ log_indent();
+ }
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ }
+ else if ( pc->Is(CT_RETURN)
+ || ( pc->Is(CT_THROW)
+ && pc->GetParentType() == CT_NONE))
+ {
+ // don't count returns inside a () or []
+ if ( pc->GetLevel() == pc->GetBraceLevel()
+ || pc->TestFlags(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->GetType() == 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 ( next->IsNewline()
+ || ( pc->Is(CT_RETURN)
+ && options::indent_single_after_return()))
+ {
+ // apply normal single indentation
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ }
+ else
+ {
+ // indent after the return token
+ frm.top().SetIndent(frm.prev().GetIndent() + pc->Len() + 1);
+ }
+ log_indent();
+ frm.top().SetIndentTmp(frm.prev().GetIndent());
+ log_indent_tmp();
+ }
+ log_indent();
+ }
+ }
+ else if ( pc->Is(CT_OC_SCOPE)
+ || pc->Is(CT_TYPEDEF))
+ {
+ frm.push(pc, __func__, __LINE__);
+ // Issue #405
+ frm.top().SetIndent(frm.prev().GetIndent());
+ log_indent();
+
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ LOG_FMT(LINDLINE, "%s(%d): .indent is %zu, .indent_tmp is %zu\n",
+ __func__, __LINE__, frm.top().GetIndent(), frm.top().GetIndentTmp());
+
+ log_rule_B("indent_continue");
+
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().SetIndent(get_indent_first_continue(pc));
+ log_indent();
+ }
+ else if (options::indent_continue() != 0)
+ {
+ frm.top().SetIndent(calc_indent_continue(frm, frm.size() - 2));
+ log_indent();
+
+ frm.top().SetIndentContinue(true);
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ log_indent();
+ }
+ }
+ else if (pc->Is(CT_C99_MEMBER))
+ {
+ // nothing to do
+ }
+ else if (pc->Is(CT_WHERE_SPEC))
+ {
+ /* class indentation is ok already, just need to adjust func */
+ /* TODO: make this configurable, obviously.. */
+ if ( pc->GetParentType() == CT_FUNC_DEF
+ || pc->GetParentType() == CT_FUNC_PROTO
+ || ( pc->GetParentType() == CT_STRUCT
+ && frm.top().GetOpenToken() != CT_CLASS_COLON))
+ {
+ indent_column_set(frm.top().GetIndent() + 4);
+ }
+ }
+ else if ( options::indent_inside_ternary_operator()
+ && ( pc->Is(CT_QUESTION)
+ || pc->Is(CT_COND_COLON))) // Issue #1130, #1715
+ {
+ log_rule_B("indent_inside_ternary_operator");
+
+ // Pop any colons before because they should already be processed
+ while ( pc->Is(CT_COND_COLON)
+ && frm.top().GetOpenToken() == 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()
+ && pc->Is(CT_COND_COLON)
+ && frm.top().GetOpenToken() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ frm.pop(__func__, __LINE__, pc);
+ indent_column_set(frm.top().GetIndentTmp());
+ }
+ frm.push(pc, __func__, __LINE__);
+
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent();
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if ( pc->Is(CT_LAMBDA)
+ && (language_is_set(LANG_CS | LANG_JAVA))
+ && pc->GetNextNcNnlNpp()->IsNot(CT_BRACE_OPEN)
+ && options::indent_cs_delegate_body())
+ {
+ log_rule_B("indent_cs_delegate_body");
+ frm.push(pc, __func__, __LINE__);
+ frm.top().SetIndent(frm.prev().GetIndent());
+ log_indent();
+
+ if ( pc->GetPrevNc()->IsNewline()
+ && !frm.prev().GetOpenChunk()->IsOnSameLine(pc->GetPrevNcNnl()))
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ log_indent();
+ reindent_line(pc, (frm.prev().GetIndent() + indent_size));
+ did_newline = false;
+ }
+ else if ( pc->GetNextNc()->IsNewline()
+ && !frm.prev().GetOpenChunk()->IsOnSameLine(frm.top().GetOpenChunk()))
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + indent_size);
+ }
+ log_indent();
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ log_indent_tmp();
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && ( pc->Is(CT_OC_MSG_FUNC)
+ || pc->Is(CT_OC_MSG_NAME))
+ && pc->GetNextNcNnl()->Is(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().SetIndent(frm.prev().GetIndent());
+ frm.top().SetIndentTab(frm.prev().GetIndentTab());
+ log_indent();
+ frm.top().SetIndentTmp(frm.prev().GetIndentTmp());
+ log_indent_tmp();
+ }
+ else if (pc->IsComment())
+ {
+ // Issue #3294
+ Chunk *next = pc->GetNext();
+
+ if (next->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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->TestFlags(PCF_IN_ENUM)
+ && pc->GetParentType() != CT_OPERATOR
+ && !pc->IsComment()
+ && pc->IsNot(CT_BRACE_OPEN)
+ && pc->GetLevel() > 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 (tmp->Is(CT_SHIFT))
+ {
+ in_shift = true;
+ LOG_FMT(LINDENT2, "%s(%d): in_shift set to TRUE\n",
+ __func__, __LINE__);
+
+ tmp = tmp->GetPrevNcNnl();
+
+ if (tmp->Is(CT_OPERATOR))
+ {
+ is_operator = true;
+ }
+ break;
+ }
+ tmp = tmp->GetPrevNcNnl();
+ } while ( !in_shift
+ && tmp->IsNotNullChunk()
+ && tmp->IsNot(CT_SEMICOLON)
+ && tmp->IsNot(CT_BRACE_OPEN)
+ && tmp->IsNot(CT_BRACE_CLOSE)
+ && tmp->IsNot(CT_COMMA)
+ && tmp->IsNot(CT_SPAREN_OPEN)
+ && tmp->IsNot(CT_SPAREN_CLOSE));
+
+ tmp = pc;
+
+ do
+ {
+ tmp = tmp->GetNextNcNnl();
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->Is(CT_SHIFT))
+ {
+ in_shift = true;
+ LOG_FMT(LINDENT2, "%s(%d): in_shift set to TRUE\n",
+ __func__, __LINE__);
+
+ tmp = tmp->GetPrevNcNnl();
+
+ if (tmp->Is(CT_OPERATOR))
+ {
+ is_operator = true;
+ }
+ break;
+ }
+ } while ( !in_shift
+ && tmp->IsNotNullChunk()
+ && tmp->IsNot(CT_SEMICOLON)
+ && tmp->IsNot(CT_BRACE_OPEN)
+ && tmp->IsNot(CT_BRACE_CLOSE)
+ && tmp->IsNot(CT_COMMA)
+ && tmp->IsNot(CT_SPAREN_OPEN)
+ && tmp->IsNot(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 (( prev_nonl->IsSemicolon()
+ || prev_nonl->IsBraceOpen()
+ || prev_nonl->IsBraceClose()
+ || prev_nonl->Is(CT_CASE_COLON)
+ || ( prev_nonl->IsNotNullChunk()
+ && prev_nonl->TestFlags(PCF_IN_PREPROC)) != pc->TestFlags(PCF_IN_PREPROC)
+ || prev_nonl->Is(CT_COMMA)
+ || is_operator))
+ {
+ in_shift = false;
+ }
+ LOG_FMT(LINDENT2, "%s(%d): in_shift is %s\n",
+ __func__, __LINE__, in_shift ? "TRUE" : "FALSE");
+
+ if ( prev2->Is(CT_NEWLINE)
+ && in_shift)
+ {
+ shiftcontcol = calc_indent_continue(frm);
+ // Calling frm.top().SetIndentContinue(true) in the top context when the indent is not also set
+ // just leads to complications when succeeding statements try to indent based on being
+ // embedded in a continuation. In other words setting frm.top().SetIndentContinue(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).GetOpenToken() == CT_RETURN
+ || frm.at(i).GetOpenToken() == 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
+ && ( pc->Is(CT_WORD)
+ || pc->Is(CT_FUNC_CTOR_VAR))
+ && !pc->TestFlags(PCF_IN_FCN_DEF)
+ && pc->TestFlags(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);
+ // Calling frm.top().SetIndentContinue(true) in the top context when the indent is not also set
+ // just leads to complications when succeeding statements try to indent based on being
+ // embedded in a continuation. In other words setting frm.top().SetIndentContinue(true)
+ // should only be set if frm.top().indent is also set.
+ }
+ else if ( options::indent_var_def_cont()
+ || pc->GetPrev()->IsNewline())
+ {
+ log_rule_B("indent_var_def_cont");
+ vardefcol = frm.top().GetIndent() + indent_size;
+ }
+ else
+ {
+ // Issue #3010
+ vardefcol = pc->GetColumn();
+ // BUT, we need to skip backward over any '*'
+ Chunk *tmp = pc->GetPrevNc();
+
+ while (tmp->Is(CT_PTR_TYPE))
+ {
+ vardefcol = tmp->GetColumn();
+ tmp = tmp->GetPrevNc();
+ }
+ // BUT, we need to skip backward over any '::' or TYPE
+ //tmp = pc->GetPrevNc();
+
+ //if (tmp->Is(CT_DC_MEMBER))
+ //{
+ // // look for a type
+ // Chunk *tmp2 = tmp->GetPrevNc();
+ // if (tmp2->Is(CT_TYPE))
+ // {
+ // // we have something like "SomeLongNamespaceName::Foo()"
+ // vardefcol = tmp2->GetColumn();
+ // LOG_FMT(LINDENT, "%s(%d): orig line is %zu, vardefcol is %zu\n",
+ // __func__, __LINE__, pc->GetOrigLine(), vardefcol);
+ // }
+ //}
+ }
+ }
+
+ if ( pc->IsSemicolon()
+ || ( pc->Is(CT_BRACE_OPEN)
+ && ( pc->GetParentType() == CT_FUNCTION
+ || pc->GetParentType() == CT_CLASS))) //Issue #3576
+ {
+ vardefcol = 0;
+ }
+
+ // Indent the line if needed
+ if ( did_newline
+ && !pc->IsNewline()
+ && (pc->Len() != 0))
+ {
+ if ( pc->TestFlags(PCF_CONT_LINE)
+ && options::indent_continue() < 0)
+ {
+ log_rule_B("indent_continue");
+ indent_column = calc_indent_continue(frm);
+ log_indent();
+ }
+ pc->SetColumnIndent(frm.top().GetIndentTab());
+
+ if (frm.top().GetIndentData().ref)
+ {
+ pc->IndentData().ref = frm.top().GetIndentData().ref;
+ pc->IndentData().delta = frm.top().GetIndentData().delta;
+ }
+ LOG_FMT(LINDENT2, "%s(%d): orig line is %zu, pc->GetColumn() indent is %zu, indent_column is %zu, for '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetColumnIndent(), indent_column, pc->ElidedText(copy));
+
+ /*
+ * Check for special continuations.
+ * Note that some of these could be done as a stack item like
+ * everything else
+ */
+
+ Chunk *prev = pc->GetPrevNcNnl();
+ Chunk *prevv = prev->GetPrevNcNnl();
+ Chunk *next = pc->GetNextNcNnl();
+
+ bool do_vardefcol = false;
+
+ if ( vardefcol > 0
+ && pc->GetLevel() == pc->GetBraceLevel()
+ && ( prev->Is(CT_COMMA)
+ || prev->Is(CT_TYPE)
+ || prev->Is(CT_PTR_TYPE)
+ || prev->Is(CT_WORD)))
+ {
+ Chunk *tmp = pc;
+
+ while (tmp->Is(CT_PTR_TYPE))
+ {
+ tmp = tmp->GetNextNcNnl();
+ }
+ LOG_FMT(LINDENT2, "%s(%d): orig line is %zu, for '%s'",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->Text());
+ LOG_FMT(LINDENT2, " tmp->GetFlags(): ");
+ log_pcf_flags(LINDENT2, tmp->GetFlags()); // Issue #2332
+
+ if ( tmp->TestFlags(PCF_VAR_DEF)
+ && ( tmp->Is(CT_WORD)
+ || tmp->Is(CT_FUNC_CTOR_VAR)))
+ {
+ do_vardefcol = true;
+ }
+ }
+ //LOG_FMT(LINDENT2, "%s(%d): GUY 2:\n", __func__, __LINE__);
+
+ if (pc->TestFlags(PCF_DONT_INDENT))
+ {
+ // no change
+ }
+ else if ( pc->GetParentType() == CT_SQL_EXEC
+ && options::indent_preserve_sql())
+ {
+ log_rule_B("indent_preserve_sql");
+ reindent_line(pc, sql_col + (pc->GetOrigCol() - sql_orig_col));
+ LOG_FMT(LINDENT, "Indent SQL: [%s] to %zu (%zu/%zu)\n",
+ pc->Text(), pc->GetColumn(), sql_col, sql_orig_col);
+ }
+ else if ( !options::indent_member_single()
+ && !pc->TestFlags(PCF_STMT_START)
+ && ( pc->Is(CT_MEMBER)
+ || ( pc->Is(CT_DC_MEMBER)
+ && prev->Is(CT_TYPE))
+ || ( prev->Is(CT_MEMBER)
+ || ( prev->Is(CT_DC_MEMBER)
+ && prevv->Is(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->GetOrigLine(), 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->GetOrigLine(), 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->GetOrigLine(), shiftcontcol);
+ reindent_line(pc, shiftcontcol);
+ }
+ else if ( pc->Is(CT_NAMESPACE)
+ && options::indent_namespace()
+ && options::indent_namespace_single_indent()
+ && frm.top().GetNsCount())
+ {
+ 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->GetOrigLine(), frm.top().GetBraceIndent());
+ reindent_line(pc, frm.top().GetBraceIndent());
+ }
+ else if ( pc->Is(CT_STRING)
+ && prev->Is(CT_STRING)
+ && options::indent_align_string())
+ {
+ log_rule_B("indent_align_string");
+ const int tmp = (xml_indent != 0) ? xml_indent : prev->GetColumn();
+
+ LOG_FMT(LINDENT, "%s(%d): orig line is %zu, String => %d\n",
+ __func__, __LINE__, pc->GetOrigLine(), tmp);
+ reindent_line(pc, tmp);
+ }
+ else if (pc->IsComment())
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig line is %zu, comment => %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), frm.top().GetIndentTmp());
+ indent_comment(pc, frm.top().GetIndentTmp());
+ }
+ else if (pc->Is(CT_PREPROC))
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig line is %zu, pp-indent => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( pc->IsParenClose()
+ || pc->Is(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.lastPopped().GetOpenToken() == E_Token(pc->GetType() - 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ Chunk *ck1 = frm.lastPopped().GetOpenChunk();
+ LOG_FMT(LINDLINE, "%s(%d): ck1 orig line is %zu, orig col is %zu, Text() is '%s', GetType() is %s\n",
+ __func__, __LINE__, ck1->GetOrigLine(), ck1->GetOrigCol(), ck1->Text(), get_token_name(ck1->GetType()));
+ Chunk *ck2 = ck1->GetPrev();
+ LOG_FMT(LINDLINE, "%s(%d): ck2 orig line is %zu, orig col is %zu, Text() is '%s', GetType() is %s\n",
+ __func__, __LINE__, ck2->GetOrigLine(), ck2->GetOrigCol(), ck2->Text(), get_token_name(ck2->GetType()));
+
+ 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->GetOrigLine(), ck2->GetOrigCol());
+ indent_column_set(pc->GetOrigCol());
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->GetOrigLine(), ck2->GetOrigCol(), indent_column);
+ }
+ else if ( ck2->IsNewline()
+ || (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->GetOrigLine(), ck2->GetOrigCol());
+ indent_column_set(ck1->GetColumn());
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->GetOrigLine(), ck2->GetOrigCol(), 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->GetOrigLine(), ck2->GetOrigCol());
+ indent_column_set(frm.lastPopped().GetIndentTmp());
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->GetOrigLine(), ck2->GetOrigCol(), indent_column);
+ pc->SetColumnIndent(frm.lastPopped().GetIndentTab());
+ 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->GetOrigLine(), ck2->GetOrigCol());
+
+ if (indent_column == 0)
+ {
+ fprintf(stderr, "%s(%d): indent_column is ZERO, cannot be decremented, at line %zu, column %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ indent_column--;
+ LOG_FMT(LINDLINE, "%s(%d): [%zu:%zu] indent_column set to %zu\n",
+ __func__, __LINE__, ck2->GetOrigLine(), ck2->GetOrigCol(), 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, orig col is %zu, ck2->Text() is '%s'\n",
+ __func__, __LINE__, ck2->GetOrigLine(), ck2->GetOrigCol(), ck2->Text());
+
+ if (pc->GetPrev()->GetType() == 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ LOG_FMT(LINDLINE, "%s(%d): prev is <newline>\n",
+ __func__, __LINE__);
+ Chunk *search = pc;
+
+ while (search->GetNext()->IsParenClose())
+ {
+ search = search->GetNext();
+ }
+ Chunk *searchNext = search->GetNext();
+
+ // Issue #3407 - Skip over a possible 'noexcept' keyword before going forward.
+ if (searchNext->GetType() == CT_NOEXCEPT)
+ {
+ searchNext = searchNext->GetNext();
+ }
+
+ if ( searchNext->GetType() == CT_SEMICOLON
+ || searchNext->GetType() == CT_MEMBER // Issue #2582
+ || searchNext->GetType() == CT_NEWLINE)
+ {
+ LOG_FMT(LINDLINE, "%s(%d):\n", __func__, __LINE__);
+ search = search->GetOpeningParen();
+
+ if ( options::indent_oc_inside_msg_sel()
+ && search->GetPrevNcNnl()->Is(CT_OC_COLON)
+ && ( frm.top().GetOpenToken() == CT_OC_MSG_FUNC
+ || frm.top().GetOpenToken() == CT_OC_MSG_NAME)) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ // [Class Message:(...)<here>
+ indent_column_set(frm.top().GetOpenChunk()->GetColumn());
+ }
+ else if ( options::indent_inside_ternary_operator()
+ && ( frm.top().GetOpenToken() == CT_QUESTION
+ || frm.top().GetOpenToken() == CT_COND_COLON)) // Issue #1130, #1715
+ {
+ log_rule_B("indent_inside_ternary_operator");
+ indent_column_set(frm.top().GetIndent());
+ }
+ else
+ {
+ search = search->GetPrevNl()->GetNext();
+
+ if (search->IsNullChunk())
+ {
+ search = Chunk::GetHead();
+ }
+ indent_column_set(search->GetColumn());
+ }
+ }
+ }
+ }
+ }
+ }
+ size_t indent_value = 0;
+ LOG_FMT(LINDENT, "%s(%d): orig line is %zu, closing parenthesis => %zu, text is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ LOG_FMT(LINDENT, "%s(%d): [%s/%s]\n",
+ __func__, __LINE__,
+ get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+ Chunk *prev2 = pc->GetPrev(); // Issue #2930
+ LOG_FMT(LINDENT, "%s(%d): prev2 is orig line is %zu, text is '%s'\n",
+ __func__, __LINE__, prev2->GetOrigLine(), prev2->Text());
+ Chunk *next2 = pc->GetNext();
+ LOG_FMT(LINDENT, "%s(%d): next2 is orig line is %zu, text is '%s'\n",
+ __func__, __LINE__, next2->GetOrigLine(), next2->Text());
+
+ if ( pc->GetParentType() == CT_FUNC_DEF
+ && prev2->IsNewline()
+ && next2->IsNewline())
+ {
+ 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 (pc->Is(CT_COMMA))
+ {
+ bool indent_align = false;
+ bool indent_ignore = false;
+
+ if (frm.top().GetOpenChunk()->IsParenOpen())
+ {
+ log_rule_B("indent_comma_paren");
+ indent_align = options::indent_comma_paren() == (int)indent_mode_e::ALIGN;
+ indent_ignore = options::indent_comma_paren() == (int)indent_mode_e::IGNORE;
+ }
+ else if (frm.top().GetOpenChunk()->IsBraceOpen())
+ {
+ log_rule_B("indent_comma_brace");
+ indent_align = options::indent_comma_brace() == (int)indent_mode_e::ALIGN;
+ indent_ignore = options::indent_comma_brace() == (int)indent_mode_e::IGNORE;
+ }
+
+ if (indent_ignore)
+ {
+ indent_column_set(pc->GetOrigCol());
+ }
+ else if (indent_align)
+ {
+ indent_column_set(frm.top().GetOpenChunk()->GetColumn());
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] comma => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( options::indent_func_const()
+ && pc->Is(CT_QUALIFIER)
+ && strncasecmp(pc->Text(), "const", pc->Len()) == 0
+ && ( next->Is(CT_BRACED)
+ || next->IsBraceOpen()
+ || next->Is(CT_NEWLINE)
+ || next->Is(CT_SEMICOLON)
+ || next->Is(CT_THROW)))
+ {
+ // indent const - void GetFoo(void)\n const\n { return (m_Foo); }
+ log_rule_B("indent_func_const");
+ indent_column_set(frm.top().GetIndent() + options::indent_func_const());
+ LOG_FMT(LINDENT, "%s(%d): %zu] const => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( options::indent_func_throw()
+ && pc->Is(CT_THROW)
+ && pc->GetParentType() != 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->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if (pc->Is(CT_SEMICOLON))
+ {
+ if ( pc->TestFlags(PCF_IN_FOR)
+ && options::indent_semicolon_for_paren())
+ {
+ log_rule_B("indent_semicolon_for_paren");
+ indent_column_set(frm.top().GetOpenChunk()->GetColumn());
+
+ log_rule_B("indent_first_for_expr");
+
+ if (options::indent_first_for_expr())
+ {
+ reindent_line(frm.top().GetOpenChunk()->GetNext(),
+ indent_column + pc->Len() + 1);
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] SEMICOLON => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), 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->GetOrigCol());
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] semicolon => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ }
+ else if (pc->Is(CT_BOOL))
+ {
+ if (frm.top().GetOpenChunk()->IsParenOpen())
+ {
+ log_rule_B("indent_bool_paren");
+
+ if (options::indent_bool_paren() == (int)indent_mode_e::IGNORE)
+ {
+ indent_column_set(pc->GetOrigCol());
+ }
+ else if (options::indent_bool_paren() == (int)indent_mode_e::ALIGN)
+ {
+ indent_column_set(frm.top().GetOpenChunk()->GetColumn());
+
+ log_rule_B("indent_first_bool_expr");
+
+ if (options::indent_first_bool_expr())
+ {
+ reindent_line(frm.top().GetOpenChunk()->GetNext(),
+ indent_column + pc->Len() + 1);
+ }
+ }
+ }
+ else
+ {
+ log_rule_B("indent_ignore_bool");
+
+ if (options::indent_ignore_bool())
+ {
+ indent_column_set(pc->GetOrigCol());
+ }
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] bool => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( pc->Is(CT_ARITH)
+ || pc->Is(CT_CARET))
+ {
+ log_rule_B("indent_ignore_arith");
+
+ if (options::indent_ignore_arith())
+ {
+ indent_column_set(pc->GetOrigCol());
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] arith => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if (pc->Is(CT_SHIFT))
+ {
+ log_rule_B("indent_shift");
+
+ if (options::indent_shift() == -1)
+ {
+ indent_column_set(pc->GetOrigCol());
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] shift => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if (pc->Is(CT_ASSIGN))
+ {
+ log_rule_B("indent_ignore_assign");
+
+ if (options::indent_ignore_assign())
+ {
+ indent_column_set(pc->GetOrigCol());
+ }
+ LOG_FMT(LINDENT, "%s(%d): %zu] assign => %zu [%s]\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ else if ( options::indent_ternary_operator() == 1
+ && prev->Is(CT_COND_COLON))
+ {
+ log_rule_B("indent_ternary_operator");
+ Chunk *tmp = prev->GetPrevType(CT_QUESTION);
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp = tmp->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ LOG_FMT(LINDENT, "%s: %zu] ternarydefcol => %zu [%s]\n",
+ __func__, pc->GetOrigLine(), tmp->GetColumn(), pc->Text());
+ reindent_line(pc, tmp->GetColumn());
+ }
+ }
+ }
+ else if ( options::indent_ternary_operator() == 2
+ && pc->Is(CT_COND_COLON))
+ {
+ log_rule_B("indent_ternary_operator");
+ // get the parent, the QUESTION
+ Chunk *question = pc->GetParent();
+
+ if (question->IsNotNullChunk())
+ {
+ LOG_FMT(LINDENT, "%s: %zu] ternarydefcol => %zu [%s]\n",
+ __func__, pc->GetOrigLine(), question->GetColumn(), pc->Text());
+ reindent_line(pc, question->GetColumn());
+ }
+ }
+ else if ( options::indent_oc_inside_msg_sel()
+ && ( pc->Is(CT_OC_MSG_FUNC)
+ || pc->Is(CT_OC_MSG_NAME))) // Issue #2658
+ {
+ log_rule_B("indent_oc_inside_msg_sel");
+ reindent_line(pc, frm.top().GetIndent());
+ }
+ else
+ {
+ bool use_indent = true;
+ const size_t ttidx = frm.size() - 1;
+
+ if (ttidx > 0)
+ {
+ LOG_FMT(LINDPC, "%s(%d): (frm.at(ttidx).pc)->GetParentType() is %s\n",
+ __func__, __LINE__, get_token_name((frm.at(ttidx).GetOpenChunk())->GetParentType()));
+
+ if ((frm.at(ttidx).GetOpenChunk())->GetParentType() == 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->GetColumn() is %zu, pc->Text() is '%s, indent_column is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetColumn(), pc->Text(), indent_column);
+
+ if ( use_indent
+ && pc->IsNot(CT_PP_IGNORE)) // Leave indentation alone for PP_IGNORE tokens
+ {
+ log_rule_B("pos_conditional");
+
+ if ( ( pc->Is(CT_QUESTION) // Issue #2101
+ || pc->Is(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->GetOrigLine());
+ }
+ else if (pc->Is(CT_BREAK))
+ {
+ // Issue #1692
+ log_rule_B("indent_switch_break_with_case");
+
+ // Issue #2281
+ if ( options::indent_switch_break_with_case()
+ && pc->GetTypeOfParent() == CT_SWITCH)
+ {
+ // look for a case before Issue #2735
+ Chunk *whereIsCase = pc->GetPrevType(CT_CASE, pc->GetLevel());
+
+ if (whereIsCase->IsNotNullChunk())
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, whereIsCase->GetOrigLine(), whereIsCase->GetOrigCol(), whereIsCase->Text());
+ LOG_FMT(LINDENT, "%s(%d): column is %zu\n",
+ __func__, __LINE__, whereIsCase->GetColumn());
+ reindent_line(pc, whereIsCase->GetColumn());
+ }
+ }
+ else
+ {
+ LOG_FMT(LINDENT, "%s(%d): orig line is %zu, indent_column set to %zu, for '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), indent_column, pc->Text());
+ reindent_line(pc, indent_column);
+ }
+ }
+ else if ( pc->Is(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->GetOrigLine(), 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)->GetType() is %s\n",
+ __func__, __LINE__, (frm.at(frm_size - 1).GetOpenChunk())->Text(), get_token_name((frm.at(frm_size - 1).GetOpenChunk())->GetType()));
+ // 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).GetOpenChunk();
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', token_before->GetType() is %s\n",
+ __func__, __LINE__, token_before->Text(), get_token_name(token_before->GetType()));
+
+ size_t vor_col = 0;
+
+ if (token_before->Is(CT_ASSIGN))
+ {
+ Chunk *before_Assign = frm.at(temp_ttidx - 1).GetOpenChunk();
+
+ if (before_Assign->IsNullChunk())
+ {
+ indent_column = 1 + indent_size;
+ }
+ else
+ {
+ vor_col = before_Assign->GetColumn();
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', before_Assign->GetType() is %s, column is %zu\n",
+ __func__, __LINE__, before_Assign->Text(), get_token_name(before_Assign->GetType()), vor_col);
+ indent_column = vor_col + 2 * indent_size;
+ }
+ }
+ else if (token_before->Is(CT_BRACE_OPEN))
+ {
+ vor_col = token_before->GetColumn();
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', token_before->GetType() is %s, column is %zu\n",
+ __func__, __LINE__, token_before->Text(), get_token_name(token_before->GetType()), vor_col);
+ indent_column = vor_col + 2 * indent_size;
+ }
+ else if (token_before->Is(CT_RETURN))
+ {
+ Chunk *before_Return = frm.at(temp_ttidx - 1).GetOpenChunk();
+ vor_col = before_Return->GetColumn();
+ LOG_FMT(LINDPC, "%s(%d): Text() is '%s', before_Return->GetType() is %s, column is %zu\n",
+ __func__, __LINE__, before_Return->Text(), get_token_name(before_Return->GetType()), 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->GetOrigLine(), 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->GetOrigLine());
+ }
+ }
+ did_newline = false;
+
+ if ( pc->Is(CT_SQL_EXEC)
+ || pc->Is(CT_SQL_BEGIN)
+ || pc->Is(CT_SQL_END))
+ {
+ sql_col = pc->GetColumn();
+ sql_orig_col = pc->GetOrigCol();
+ }
+
+ // Handle indent for variable defs at the top of a block of code
+ if (pc->TestFlags(PCF_VAR_TYPE))
+ {
+ if ( !frm.top().GetNonVardef()
+ && (frm.top().GetOpenToken() == CT_BRACE_OPEN))
+ {
+ log_rule_B("indent_var_def_blk");
+ int val = options::indent_var_def_blk();
+
+ if (val != 0)
+ {
+ size_t indent = indent_column;
+ indent = (val > 0) ? val // reassign if positive val,
+ : ((size_t)(abs(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->GetOrigLine(), indent, pc->Text());
+ reindent_line(pc, indent);
+ }
+ }
+ }
+ else if (pc != frm.top().GetOpenChunk())
+ {
+ frm.top().SetNonVardef(true);
+ }
+ }
+
+ // if we hit a newline, reset indent_tmp
+ if ( pc->IsNewline()
+ || pc->Is(CT_COMMENT_MULTI)
+ || pc->Is(CT_COMMENT_CPP))
+ {
+ log_indent();
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ 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 ( pc->Is(CT_NL_CONT)
+ && frm.top().GetIndentTmp() <= indent_size
+ && frm.top().GetOpenToken() != CT_PP_DEFINE)
+ {
+ frm.top().SetIndentTmp(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
+ && pc->Is(CT_STRING)
+ && pc->Len() > 4
+ && pc->GetStr()[1] == '<'
+ && pc->GetStr()[2] != '/'
+ && pc->GetStr()[pc->Len() - 3] != '/')
+ {
+ if (xml_indent <= 0)
+ {
+ xml_indent = pc->GetColumn();
+ }
+ log_rule_B("indent_xml_string");
+ xml_indent += options::indent_xml_string();
+ }
+ // Issue #672
+ log_rule_B("indent_continue_class_head");
+
+ if ( pc->Is(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->GetOrigLine());
+ frm.push(pc, __func__, __LINE__);
+
+ if (options::indent_ignore_first_continue())
+ {
+ frm.top().SetIndent(get_indent_first_continue(pc));
+ }
+ else
+ {
+ frm.top().SetIndent(frm.prev().GetIndent() + options::indent_continue_class_head());
+ }
+ log_indent();
+
+ frm.top().SetIndentTmp(frm.top().GetIndent());
+ frm.top().SetIndentTab(frm.top().GetIndent());
+ log_indent_tmp();
+ classFound = true;
+ }
+ pc = pc->GetNext();
+
+ if (pc->Is(CT_SPACE)) // Issue #3710
+ {
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ }
+null_pc:
+
+ // Throw out any stuff inside a preprocessor - no need to warn
+ while ( !frm.empty()
+ && frm.top().GetInPreproc())
+ {
+ frm.pop(__func__, __LINE__, pc);
+ }
+
+ // Throw out any VBRACE_OPEN at the end - implied with the end of file
+ while ( !frm.empty()
+ && frm.top().GetOpenToken() == 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).GetOpenLine(),
+ get_token_name(frm.at(idx_temp).GetParent()),
+ get_token_name(frm.at(idx_temp).GetOpenToken()));
+ exit(EX_IOERR);
+ }
+
+ 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 (!start->IsSingleLineComment())
+ {
+ return(false);
+ }
+ Chunk *pc = start;
+ size_t nl_count = 0;
+
+ while ((pc = forward ? pc->GetNext() : pc->GetPrev())->IsNotNullChunk())
+ {
+ if (pc->IsNewline())
+ {
+ if ( nl_count > 0
+ || pc->GetNlCount() > 1)
+ {
+ return(false);
+ }
+ nl_count++;
+ }
+ else if (pc->IsSingleLineComment())
+ {
+ nl_count = 0;
+ }
+ else if ( pc->Is(CT_COMMENT_MULTI)
+ || (forward && pc->IsBraceClose())
+ || (!forward && pc->IsBraceOpen()))
+ {
+ /*
+ * 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 ParsingFrame &frm)
+{
+ return( ( frm.top().GetOpenToken() == CT_ASSIGN_NL
+ || frm.top().GetOpenToken() == CT_MEMBER
+ || frm.top().GetOpenToken() == CT_ASSIGN)
+ && ( pc->IsSemicolon()
+ || pc->Is(CT_COMMA)
+ || pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_SPAREN_CLOSE)
+ || ( pc->Is(CT_SQUARE_OPEN)
+ && pc->GetParentType() == CT_ASSIGN))
+ && pc->GetParentType() != 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->GetOrigLine(), newline_token->GetOrigCol());
+
+ if ( newline_token->IsNullChunk()
+ || newline_token->GetNlCount() > 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->GetOrigLine(), next->GetOrigCol());
+ }
+ } 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->GetOrigCol() > pc->GetOrigCol()
+ ? next->GetOrigCol() - pc->GetOrigCol()
+ : pc->GetOrigCol() - next->GetOrigCol());
+}
+
+
+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->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+
+ // force column 1 comment to column 1 if not changing them
+ log_rule_B("indent_col1_comment");
+
+ if ( pc->GetOrigCol() == 1
+ && !options::indent_col1_comment()
+ && !pc->TestFlags(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->GetOrigLine(), nl->GetOrigCol(), nl->GetLevel());
+ }
+
+ if (pc->GetOrigCol() > 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->GetOrigLine(), prev->GetOrigCol(), prev->GetLevel());
+ log_pcf_flags(LCMTIND, prev->GetFlags());
+ }
+
+ if ( prev->IsComment()
+ && nl->GetNlCount() == 1)
+ {
+ const size_t prev_col_diff = (prev->GetOrigCol() > pc->GetOrigCol())
+ ? prev->GetOrigCol() - pc->GetOrigCol()
+ : pc->GetOrigCol() - prev->GetOrigCol();
+ 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(), prev->IsDoxygenComment() ? "TRUE" : "FALSE");
+ LOG_FMT(LCMTIND, "%s(%d): pc->Text() is '%s', Doxygen_comment(pc) is %s\n",
+ __func__, __LINE__, pc->Text(), pc->IsDoxygenComment() ? "TRUE" : "FALSE");
+
+ if (prev->IsDoxygenComment() == pc->IsDoxygenComment())
+ {
+ 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->GetColumn());
+ reindent_line(pc, prev->GetColumn());
+ 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->GetColumn());
+ 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->GetColumn());
+ reindent_line(pc, col + options::indent_single_line_comments_after());
+ return;
+ }
+ log_rule_B("indent_comment");
+
+ if ( pc->GetOrigCol() > 1
+ && !options::indent_comment())
+ {
+ LOG_FMT(LCMTIND, "%s(%d): rule 5 - keep in orig col\n", __func__, __LINE__);
+ reindent_line(pc, pc->GetOrigCol());
+ 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()
+{
+ 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, orig col is %zu, pc->Text() is '%s'\n",
+ __func__, __LINE__, pc->GetPpLevel(), pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+
+ if (pc->IsCommentOrNewline())
+ {
+ continue;
+ }
+
+ if (IFstage == 0) // 0 is BEGIN
+ {
+ // Check the first preprocessor, make sure it is an #if type
+ if (pc->IsNot(CT_PREPROC))
+ {
+ break;
+ }
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNullChunk()
+ || next->IsNot(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 (pc->Is(CT_PREPROC))
+ {
+ if (pc->GetPpLevel() == 0)
+ {
+ IFstage = 2;
+ end_pp = pc;
+ }
+ }
+ continue;
+ }
+ else if (IFstage == 2)
+ {
+ // We should only see the rest of the preprocessor
+ if ( pc->Is(CT_PREPROC)
+ || !pc->TestFlags(PCF_IN_PREPROC))
+ {
+ IFstage = 0;
+ break;
+ }
+ }
+ }
+
+ cpd.ifdef_over_whole_file = (IFstage == 2) ? 1 : -1;
+
+ if (cpd.ifdef_over_whole_file > 0)
+ {
+ start_pp->SetFlagBits(PCF_WF_IF);
+ end_pp->SetFlagBits(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()
+{
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+
+ if (pc->IsNot(CT_PREPROC))
+ {
+ continue;
+ }
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ const size_t pp_level = (pc->GetPpLevel() > pp_level_sub)
+ ? pc->GetPpLevel() - pp_level_sub : 0;
+
+ // Adjust the indent of the '#'
+ if (options::pp_indent() & IARF_ADD)
+ {
+ log_rule_B("pp_indent ADD");
+ reindent_line(pc, 1 + pp_level * options::pp_indent_count());
+ }
+ else if (options::pp_indent() & IARF_REMOVE)
+ {
+ log_rule_B("pp_indent REMOVE");
+ reindent_line(pc, 1);
+ }
+ // Add spacing by adjusting the length
+ log_rule_B("pp_space_after");
+
+ if ( (options::pp_space_after() != IARF_IGNORE)
+ && next->IsNotNullChunk())
+ {
+ if (options::pp_space_after() & IARF_ADD)
+ {
+ log_rule_B("pp_space_after ADD");
+ const size_t mult = options::pp_space_count();
+ reindent_line(next, pc->GetColumn() + pc->Len() + (pp_level * mult));
+ }
+ else if (options::pp_space_after() & IARF_REMOVE)
+ {
+ log_rule_B("pp_space_after REMOVE");
+ reindent_line(next, pc->GetColumn() + 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->GetBraceLevel() <= ((pc->GetParentType() == CT_PP_DEFINE) ? 1 : 0);
+
+ if ( ( ( at_file_level
+ && !options::pp_indent_at_level0())
+ || ( !at_file_level
+ && !options::pp_indent_at_level()))
+ && pc->GetParentType() != CT_PP_REGION
+ && pc->GetParentType() != CT_PP_ENDREGION)
+ {
+ log_rule_B("pp_define_at_level");
+
+ if ( !options::pp_define_at_level()
+ || pc->GetParentType() != CT_PP_DEFINE)
+ {
+ pc->SetFlagBits(PCF_DONT_INDENT);
+ }
+ }
+ LOG_FMT(LPPIS, "%s(%d): orig line %zu to %zu (len %zu, next->col %zu)\n",
+ __func__, __LINE__, pc->GetOrigLine(), 1 + pp_level, pc->Len(),
+ next ? next->GetColumn() : -1);
+ }
+} // indent_preproc
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.h
new file mode 100644
index 00000000..ee927638
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/indent.h
@@ -0,0 +1,59 @@
+/**
+ * @file indent.h
+ * prototypes for indent.cpp
+ *
+ * @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();
+
+
+/**
+ * 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();
+
+/**
+ *
+ * @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();
+
+
+/**
+ * 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.78.0/src/keywords.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/keywords.cpp
new file mode 100644
index 00000000..98ff84a3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/keywords.cpp
@@ -0,0 +1,691 @@
+/**
+ * @file keywords.cpp
+ * Manages the table of keywords.
+ *
+ * @author Ben Gardner
+ * @author Guy Maurel since version 0.62 for uncrustify4Qt
+ * October 2015, 2023
+ * @license GPL v2+
+ */
+
+#include "keywords.h"
+
+#include "args.h"
+#include "prototypes.h"
+#include "uncrustify.h"
+#include "uncrustify_limits.h"
+//# define DEBUG_LANGUAGE
+// see also the call to dump_keyword_for_lang
+#ifdef DEBUG_LANGUAGE
+#include "unc_tools.h"
+#endif
+
+#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 chosen 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 },
+ { "INT16_C", CT_TYPE, LANG_CPP },
+ { "INT32_C", CT_TYPE, LANG_CPP },
+ { "INT64_C", CT_TYPE, LANG_CPP },
+ { "INT8_C", CT_TYPE, LANG_CPP },
+ { "INTMAX_C", CT_TYPE, LANG_CPP },
+ { "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 },
+ { "UINT16_C", CT_TYPE, LANG_CPP },
+ { "UINT32_C", CT_TYPE, LANG_CPP },
+ { "UINT64_C", CT_TYPE, LANG_CPP },
+ { "UINT8_C", CT_TYPE, LANG_CPP },
+ { "UINTMAX_C", CT_TYPE, 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 | LANG_OC | 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 },
+ { "async", CT_QUALIFIER, LANG_VALA },
+ { "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 },
+ { "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", CT_QUALIFIER, LANG_VALA },
+ { "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 },
+ { "errordomain", CT_ENUM, LANG_VALA },
+ { "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 | LANG_VALA },
+ { "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 },
+ { "owned", CT_QUALIFIER, 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 }, // Issue # 4044
+ { "property", CT_PP_PROPERTY, LANG_CS | FLAG_PP },
+ { "protected", CT_ACCESS, LANG_ALLC_NOT_C }, // Issue # 4044
+ { "public", CT_ACCESS, LANG_ALLC_NOT_C }, // Issue # 4044
+ { "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 },
+ { "unowned", CT_QUALIFIER, LANG_VALA },
+ { "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_CS | 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++;
+ }
+ }
+
+#ifdef DEBUG_LANGUAGE
+ dump_keyword_for_lang(language_count, keyword_for_lang);
+#endif
+
+ LOG_FMT(LDYNKW, "%s(%d): Number of Keywords for language %s: '%zu'\n",
+ __func__, __LINE__, language_name_from_flags(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()
+{
+ 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 developer.
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ }
+
+ 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 arithmetic
+ // 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);
+ exit(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]);
+ exit(EX_SOFTWARE);
+ }
+ }
+ 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()
+{
+ 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.78.0/src/keywords.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/keywords.h
new file mode 100644
index 00000000..25a4a536
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/keywords.h
@@ -0,0 +1,85 @@
+/**
+ * @file keywords.h
+ * prototypes for keywords.cpp
+ *
+ * @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();
+
+/**
+ * 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();
+
+
+//! 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();
+
+
+#endif /* KEYWORDS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.cpp
new file mode 100644
index 00000000..fe999a2a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.cpp
@@ -0,0 +1,520 @@
+/**
+ * @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 (pc->IsSemicolon())
+ {
+ return(pc);
+ }
+ Chunk *next = pc->GetNextNc();
+
+ if ( next->IsNotNullChunk()
+ && next->IsSemicolon())
+ {
+ return(pc);
+ }
+ Chunk chunk = *pc;
+
+ chunk.SetType(CT_VSEMICOLON);
+ chunk.SetParentType(CT_NONE);
+ chunk.Str() = options::mod_pawn_semicolon() ? ";" : "";
+ chunk.SetColumn(pc->GetColumn() + pc->Len());
+
+ LOG_FMT(LPVSEMI, "%s: Added VSEMI on line %zu, prev='%s' [%s]\n",
+ __func__, pc->GetOrigLine(), pc->Text(),
+ get_token_name(pc->GetType()));
+
+ return(chunk.CopyAndAddAfter(pc));
+}
+
+
+void pawn_scrub_vsemi()
+{
+ 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->IsNot(CT_VSEMICOLON))
+ {
+ continue;
+ }
+ Chunk *prev = pc->GetPrevNcNnl();
+
+ if (prev->Is(CT_BRACE_CLOSE))
+ {
+ if ( prev->GetParentType() == CT_IF
+ || prev->GetParentType() == CT_ELSE
+ || prev->GetParentType() == CT_SWITCH
+ || prev->GetParentType() == CT_CASE
+ || prev->GetParentType() == CT_WHILE_OF_DO)
+ {
+ pc->Str().clear();
+ }
+ }
+ }
+}
+
+
+static bool pawn_continued(Chunk *pc, size_t br_level)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->IsNullChunk())
+ {
+ return(false);
+ }
+
+ if ( pc->GetLevel() > br_level
+ || pc->Is(CT_ARITH)
+ || pc->Is(CT_SHIFT)
+ || pc->Is(CT_CARET)
+ || pc->Is(CT_QUESTION)
+ || pc->Is(CT_BOOL)
+ || pc->Is(CT_ASSIGN)
+ || pc->Is(CT_COMMA)
+ || pc->Is(CT_COMPARE)
+ || pc->Is(CT_IF)
+ || pc->Is(CT_ELSE)
+ || pc->Is(CT_DO)
+ || pc->Is(CT_SWITCH)
+ || pc->Is(CT_WHILE)
+ || pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_VBRACE_OPEN)
+ || pc->Is(CT_FPAREN_OPEN)
+ || pc->GetParentType() == CT_IF
+ || pc->GetParentType() == CT_ELSE
+ || pc->GetParentType() == CT_ELSEIF
+ || pc->GetParentType() == CT_DO
+ || pc->GetParentType() == CT_FOR
+ || pc->GetParentType() == CT_SWITCH
+ || pc->GetParentType() == CT_WHILE
+ || pc->GetParentType() == CT_FUNC_DEF
+ || pc->GetParentType() == CT_ENUM
+ || pc->GetFlags().test_any(PCF_IN_ENUM | PCF_IN_STRUCT)
+ || pc->IsString(":")
+ || pc->IsString("+")
+ || pc->IsString("-"))
+ {
+ return(true);
+ }
+ return(false);
+} // pawn_continued
+
+
+void pawn_prescan()
+{
+ 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->IsNotNullChunk())
+ {
+ if ( did_nl
+ && pc->IsNot(CT_PREPROC)
+ && !pc->IsNewline()
+ && pc->GetLevel() == 0)
+ {
+ // pc now points to the start of a line
+ pc = pawn_process_line(pc);
+ }
+
+ // note that continued lines are ignored
+ if (pc->IsNotNullChunk())
+ {
+ did_nl = (pc->Is(CT_NEWLINE));
+ }
+ pc = pc->GetNextNc();
+ }
+}
+
+
+static Chunk *pawn_process_line(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ //LOG_FMT(LSYS, "%s: %d - %s\n", __func__,
+ // start->GetOrigLine(), start->Text());
+
+ if ( start->Is(CT_NEW)
+ || start->IsString("const"))
+ {
+ return(pawn_process_variable(start));
+ }
+ // if a open paren is found before an assign, then this is a function
+ Chunk *fcn = Chunk::NullChunkPtr;
+
+ if (start->Is(CT_WORD))
+ {
+ fcn = start;
+ }
+ Chunk *pc = start;
+
+ while ( ((pc = pc->GetNextNc())->IsNotNullChunk())
+ && !pc->IsString("(")
+ && pc->IsNot(CT_ASSIGN)
+ && pc->IsNot(CT_NEWLINE))
+ {
+ if ( pc->GetLevel() == 0
+ && ( pc->Is(CT_FUNCTION)
+ || pc->Is(CT_WORD)
+ || pc->Is(CT_OPERATOR_VAL)))
+ {
+ fcn = pc;
+ }
+ }
+
+ if (pc->IsNotNullChunk())
+ {
+ if (pc->Is(CT_ASSIGN))
+ {
+ return(pawn_process_variable(pc));
+ }
+ }
+
+ if (fcn->IsNotNullChunk())
+ {
+ //LOG_FMT(LSYS, "FUNCTION: %s\n", fcn->Text());
+ return(pawn_mark_function0(start, fcn));
+ }
+
+ if (start->Is(CT_ENUM))
+ {
+ pc = start->GetNextType(CT_BRACE_CLOSE, start->GetLevel());
+ return(pc);
+ }
+ //LOG_FMT(LSYS, "%s: Don't understand line %d, starting with '%s' [%s]\n",
+ // __func__, start->GetOrigLine(), start->Text(), get_token_name(start->GetType()));
+ return(start);
+} // pawn_process_line
+
+
+static Chunk *pawn_process_variable(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::NullChunkPtr;
+
+ if (start->IsNotNullChunk())
+ {
+ pc = start;
+ }
+ Chunk *prev = Chunk::NullChunkPtr;
+
+ while ((pc = pc->GetNextNc())->IsNotNullChunk())
+ {
+ if ( pc->Is(CT_NEWLINE)
+ && prev->IsNotNullChunk()
+ && !pawn_continued(prev, start->GetLevel()))
+ {
+ if (!prev->IsSemicolon())
+ {
+ pawn_add_vsemi_after(prev);
+ }
+ break;
+ }
+ prev = pc;
+ }
+ return(pc);
+}
+
+
+void pawn_add_virtual_semicolons()
+{
+ 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->IsCommentOrNewline()
+ && !pc->IsVBrace())
+ {
+ prev = pc;
+ }
+
+ if ( prev->IsNullChunk()
+ || ( pc->IsNot(CT_NEWLINE)
+ && !pc->IsBraceClose()))
+ {
+ continue;
+ }
+
+ // we just hit a newline and we have a previous token
+ if ( !prev->TestFlags(PCF_IN_PREPROC)
+ && !prev->GetFlags().test_any(PCF_IN_ENUM | PCF_IN_STRUCT)
+ && !prev->IsSemicolon()
+ && !pawn_continued(prev, prev->GetBraceLevel()))
+ {
+ 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->GetLevel())->GetNext();
+
+ if (last->Is(CT_SEMICOLON))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' proto due to semicolon\n",
+ __func__, fcn->GetOrigLine(), fcn->Text());
+ fcn->SetType(CT_FUNC_PROTO);
+ return(last);
+ }
+ }
+ else
+ {
+ if ( start->Is(CT_FORWARD)
+ || start->Is(CT_NATIVE))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' [%s] proto due to %s\n",
+ __func__, fcn->GetOrigLine(), fcn->Text(),
+ get_token_name(fcn->GetType()),
+ get_token_name(start->GetType()));
+ fcn->SetType(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
+ pc->SetType(CT_FUNC_DEF);
+
+ LOG_FMT(LPFUNC, "%s: %zu:%zu %s\n",
+ __func__, pc->GetOrigLine(), pc->GetOrigCol(), 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->GetOrigLine(), last->Text(), get_token_name(last->GetType()));
+ }
+
+ // See if there is a state clause after the function
+ if ( last->IsNotNullChunk()
+ && last->IsString("<"))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' has state angle open %s\n",
+ __func__, pc->GetOrigLine(), pc->Text(), get_token_name(last->GetType()));
+
+ last->SetType(CT_ANGLE_OPEN);
+ last->SetParentType(CT_FUNC_DEF);
+
+ while ( ((last = last->GetNext())->IsNotNullChunk())
+ && !last->IsString(">"))
+ {
+ // 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->GetOrigLine(), pc->Text(), get_token_name(last->GetType()));
+ last->SetType(CT_ANGLE_CLOSE);
+ last->SetParentType(CT_FUNC_DEF);
+ }
+ last = last->GetNextNcNnl();
+ }
+
+ if (last->IsNullChunk())
+ {
+ return(last);
+ }
+
+ if (last->Is(CT_BRACE_OPEN))
+ {
+ last->SetParentType(CT_FUNC_DEF);
+ last = last->GetNextType(CT_BRACE_CLOSE, last->GetLevel());
+
+ if (last->IsNotNullChunk())
+ {
+ last->SetParentType(CT_FUNC_DEF);
+ }
+ }
+ else
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' fdef: expected brace open: %s\n",
+ __func__, pc->GetOrigLine(), pc->Text(), get_token_name(last->GetType()));
+
+ // do not insert a vbrace before a preproc
+ if (last->TestFlags(PCF_IN_PREPROC))
+ {
+ return(last);
+ }
+ Chunk chunk = *last;
+ chunk.Str().clear();
+ chunk.SetType(CT_VBRACE_OPEN);
+ chunk.SetParentType(CT_FUNC_DEF);
+
+ Chunk *prev = chunk.CopyAndAddBefore(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->GetOrigLine(), get_token_name(prev->GetType()), prev->GetLevel());
+
+ if ( prev->Is(CT_NEWLINE)
+ && prev->GetLevel() == 0)
+ {
+ Chunk *next = prev->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && next->IsNot(CT_ELSE)
+ && next->IsNot(CT_WHILE_OF_DO))
+ {
+ break;
+ }
+ }
+ prev->SetLevel(prev->GetLevel() + 1);
+ prev->SetBraceLevel(prev->GetBraceLevel() + 1);
+ last = prev;
+ } while ((prev = prev->GetNext())->IsNotNullChunk());
+
+ if (last->IsNotNullChunk())
+ {
+ LOG_FMT(LPFUNC, "%s:%zu] ended on %s, level %zu\n",
+ __func__, last->GetOrigLine(), get_token_name(last->GetType()), last->GetLevel());
+ }
+ chunk = *last;
+ chunk.Str().clear();
+ chunk.SetType(CT_VBRACE_CLOSE);
+ chunk.SetParentType(CT_FUNC_DEF);
+ chunk.SetColumn(chunk.GetColumn() + last->Len());
+ chunk.SetLevel(0);
+ chunk.SetBraceLevel(0);
+ last = chunk.CopyAndAddAfter(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);
+
+ /*
+ * 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->GetLevel() + 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->TestFlags(PCF_IN_PREPROC)
+ || pawn_continued(prev, vb_open->GetLevel() + 1))
+ {
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LPVSEMI, "%s: no VSEMI on line %zu, prev='%s' [%s]\n",
+ __func__, prev->GetOrigLine(), prev->Text(), get_token_name(prev->GetType()));
+ }
+ return(pc);
+ }
+ return(pawn_add_vsemi_after(prev));
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.h
new file mode 100644
index 00000000..7f4c503d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/lang_pawn.h
@@ -0,0 +1,49 @@
+/**
+ * @file long_pawn.h
+ * prototypes for long_pawn.cpp
+ *
+ * @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 pawn_add_virtual_semicolons();
+
+
+/**
+ * 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();
+
+
+//! 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.78.0/src/language_names.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_names.cpp
new file mode 100644
index 00000000..546b240e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_names.cpp
@@ -0,0 +1,227 @@
+/**
+ * @file language_names.cpp
+ *
+ * @author Guy Maurel
+ * extract from uncrustify.cpp
+ * @license GPL v2+
+ */
+
+#include "language_names.h"
+
+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
+};
+
+
+//! 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" },
+ { ".inc", "PAWN" },
+ { ".inl", "CPP" },
+ { ".java", "JAVA" },
+ { ".js", "ECMA" },
+ { ".m", "OC" },
+ { ".mm", "OC+" },
+ { ".p", "PAWN" },
+ { ".pawn", "PAWN" },
+ { ".sma", "PAWN" },
+ { ".sqc", "C" }, // embedded SQL
+ { ".sql", "SQL" },
+ { ".vala", "VALA" },
+ { ".vapi", "VALA" },
+};
+
+
+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);
+ }
+ }
+
+ static char lang_liste[120];
+ lang_liste[0] = '\0';
+
+ // Check for the next set language bit
+ for (auto &language_name : language_names)
+ {
+ if (strcmp(language_name.name, "OC+") == 0)
+ {
+ break;
+ }
+
+ if ((language_name.lang & lang) != 0)
+ {
+ if (lang_liste[0] == '\0')
+ {
+ strcpy(lang_liste, language_name.name);
+ }
+ else
+ {
+ int ll = strlen(lang_liste);
+ strcpy(&lang_liste[ll], ", ");
+ strcpy(&lang_liste[ll + 2], language_name.name);
+ }
+ }
+ }
+
+ return(lang_liste);
+} // language_name_from_flags
+
+
+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))));
+} // ends_with
+
+
+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);
+} // get_file_extension
+
+
+////typedef std::map<std::string, std::string> extension_map_t;
+//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[std::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
+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.78.0/src/language_names.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_names.h
new file mode 100644
index 00000000..df63d894
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_names.h
@@ -0,0 +1,109 @@
+/**
+ * @file language_names.h
+ *
+ * @author Guy Maurel
+ * extract from uncrustify.cpp
+ * @license GPL v2+
+ */
+
+#ifndef LANGUAGE_NAMES_H_INCLUDED
+#define LANGUAGE_NAMES_H_INCLUDED
+
+#include "base_types.h"
+
+#include <cstddef> // to get size_t
+#include <cstdio>
+#include <map>
+#include <string>
+#include <string.h>
+//#include <strings.h>
+
+struct lang_name_t
+{
+ const char *name;
+ size_t lang;
+};
+
+//! 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_NOT_C = 0x017e, /** LANG_CPP | LANG_D | LANG_CS | Issue # 4044
+ * LANG_JAVA | LANG_OC | LANG_VALA | LANG_ECMA */
+ 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
+};
+
+
+size_t language_flags_from_name(const char *name);
+
+
+/**
+ * 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);
+
+bool ends_with(const char *filename, const char *tag, bool case_sensitive);
+
+
+//! 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
+};
+
+
+/**
+ * Set idx = 0 before the first call.
+ * Done when returns nullptr
+ */
+const char *get_file_extension(int &idx);
+
+
+typedef std::map<std::string, std::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);
+
+
+//! Prints custom file extensions to the file
+void print_extensions(FILE *pfile);
+
+
+// TODO: better use enum lang_t for source file language
+/**
+ * Find the language for the file extension
+ * Defaults to C
+ *
+ * @param filename The name of the file
+ * @return LANG_xxx
+ */
+size_t language_flags_from_filename(const char *filename);
+
+#endif /* LANGUAGE_NAMES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_tools.cpp
new file mode 100644
index 00000000..77e577f4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/language_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/language_tools.h
new file mode 100644
index 00000000..5f57c3f1
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/log_levels.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_levels.h
new file mode 100644
index 00000000..db2acf71
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_levels.h
@@ -0,0 +1,139 @@
+/**
+ * @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 information
+ 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 or throw
+ 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, //! Chunk::SetParentType()
+ LSETTYP = 92, //! Chunk::SetType()
+ 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
+ LVARDFBLK = 104, //! newlines for variable definition blocks
+ 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.78.0/src/log_rules.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_rules.cpp
new file mode 100644
index 00000000..01e6b7fe
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_rules.cpp
@@ -0,0 +1,133 @@
+/**
+ * @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->IsNot(CT_NEWLINE))
+ {
+ LOG_FMT(LSPACE, "%s(%zu): first orig line is %zu, orig col is %zu, Text() is '%s', [%s/%s] <===>\n",
+ func, line, first->GetOrigLine(), first->GetOrigCol(), first->Text(),
+ get_token_name(first->GetType()), get_token_name(first->GetParentType()));
+ LOG_FMT(LSPACE, " second orig line is %zu, orig col is %zu, Text() is '%s', [%s/%s] :",
+ second->GetOrigLine(), second->GetOrigCol(), second->Text(),
+ get_token_name(second->GetType()), get_token_name(second->GetParentType()));
+ 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_type == tracking_type_e::TT_SPACE))
+ {
+ return;
+ }
+
+ if (first->GetTrackingData() == nullptr)
+ {
+ first->TrackingData() = new TrackList;
+ }
+ // copy the rule
+ size_t length = strlen(rule) + 1;
+ char *r = (char *)malloc(length);
+
+ strcpy(r, rule);
+ size_t a_number = get_A_Number();
+ TrackNumber A = make_pair(a_number, r);
+
+ first->TrackingData()->push_back(A);
+ size_t sizeOfTrack = first->GetTrackingData()->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->GetOrigLine(), a_number, sizeOfTrack);
+}
+
+
+void log_ruleStart(const char *rule, Chunk *first)
+{
+ if (!(cpd.html_type == tracking_type_e::TT_START))
+ {
+ return;
+ }
+
+ if (first->GetTrackingData() == nullptr)
+ {
+ first->TrackingData() = new TrackList;
+ }
+ // copy the rule
+ size_t length = strlen(rule) + 1;
+ char *r = (char *)malloc(length);
+
+ strcpy(r, rule);
+ size_t a_number = get_A_Number();
+ TrackNumber A = make_pair(a_number, r);
+
+ first->TrackingData()->push_back(A);
+ size_t sizeOfTrack = first->GetTrackingData()->size();
+
+ LOG_FMT(LSPACE, "log_ruleStart(%d): rule is '%s', '%s', at line %zu, tracking number is %zu, size is %zu\n",
+ __LINE__, rule, first->Text(), first->GetOrigLine(), a_number, sizeOfTrack);
+} // log_ruleStart
+
+
+void log_ruleNL(const char *rule, Chunk *pc)
+{
+ if (!(cpd.html_type == tracking_type_e::TT_NEWLINE))
+ {
+ return;
+ }
+
+ if (pc->GetTrackingData() == nullptr)
+ {
+ pc->TrackingData() = new TrackList;
+ }
+ // copy the rule
+ size_t length = strlen(rule) + 1;
+ char *r = (char *)malloc(length);
+
+ strcpy(r, rule);
+ size_t a_number = get_A_Number();
+ TrackNumber A = make_pair(a_number, r);
+
+ pc->TrackingData()->push_back(A);
+ size_t sizeOfTrack = pc->GetTrackingData()->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, pc->Text(), pc->GetOrigLine(), a_number, sizeOfTrack);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_rules.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_rules.h
new file mode 100644
index 00000000..1c1583e6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/log_rules.h
@@ -0,0 +1,56 @@
+/**
+ * @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;
+
+#define log_rule(rule) \
+ log_rule2(__func__, __LINE__, (rule), first, second); \
+ log_rule4((rule), first)
+
+// if you need more debug information, 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
+
+#ifdef SUPER_LOG
+#define log_rule_NL(rule) \
+ log_ruleNL((rule), pc)
+#else
+#define log_rule_NL(rule) \
+ log_ruleNL(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);
+
+void log_ruleStart(const char *rule, Chunk *first);
+
+void log_ruleNL(const char *rule, Chunk *pc);
+
+#endif /* LOG_RULES_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logger.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logger.cpp
new file mode 100644
index 00000000..f2f6e626
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+/**
+ * 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()
+{
+ 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 enough:\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 enough:\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 != nullptr)
+ {
+ 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 != nullptr)
+ {
+ 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.78.0/src/logger.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logger.h
new file mode 100644
index 00000000..9b27fbab
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logger.h
@@ -0,0 +1,184 @@
+/**
+ * @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__)
+
+
+#define LOG_CHUNK(sev, pc_current) \
+ if (pc_current->Is(CT_NEWLINE)) \
+ { \
+ LOG_FMT(sev, "%s(%d): orig line is %zu, orig col is %zu, <Newline>, PRE is %s\n", \
+ __func__, __LINE__, pc_current->GetOrigLine(), pc_current->GetOrigCol(), pc_current->IsPreproc() ? "true" : "false"); \
+ } \
+ else if (pc_current->Is(CT_NL_CONT)) \
+ { \
+ LOG_FMT(sev, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s, PRE is %s\n", \
+ __func__, __LINE__, pc_current->GetOrigLine(), pc_current->GetOrigCol(), pc_current->Text(), get_token_name(pc_current->GetType()), pc_current->IsPreproc() ? "true" : "false"); \
+ } \
+ else \
+ { \
+ LOG_FMT(sev, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s, PRE is %s\n", \
+ __func__, __LINE__, pc_current->GetOrigLine(), pc_current->GetOrigCol(), pc_current->Text(), get_token_name(pc_current->GetType()), pc_current->IsPreproc() ? "true" : "false"); \
+ }
+
+
+#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.78.0/src/logmask.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logmask.cpp
new file mode 100644
index 00000000..148ce193
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 development time.
+ * Don't worry about unused 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.78.0/src/logmask.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/logmask.h
new file mode 100644
index 00000000..ef00e1d0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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 development time.
+ * Don't worry about unused 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.78.0/src/mark_functor.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_functor.cpp
new file mode 100644
index 00000000..40bec01e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_functor.cpp
@@ -0,0 +1,114 @@
+/**
+ * @file mark_functor.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "mark_functor.h"
+
+#include "chunk.h"
+
+
+/*
+ * tokenize the functor such as:
+ * desc->add_options() ( a ) (b)(c);
+ */
+void mark_functor()
+{
+ LOG_FUNC_ENTRY();
+ bool found_functor = false;
+ Chunk *is_it_closing = Chunk::NullChunkPtr;
+
+ // Issue #3914
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+
+ if (pc->Is(CT_SEMICOLON))
+ {
+ found_functor = false;
+ continue;
+ }
+
+ if (found_functor)
+ {
+ if ( pc->Is(CT_FPAREN_CLOSE)
+ || pc->Is(CT_RPAREN_CLOSE))
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): FOUND a Closing: orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+ // desc->add_options() ( a ) (
+ // ^
+ pc->SetType(CT_RPAREN_CLOSE);
+ }
+ else if ( pc->Is(CT_FPAREN_OPEN)
+ || pc->Is(CT_RPAREN_OPEN))
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): FOUND a Opening: orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+ // desc->add_options() ( a ) (
+ // ^
+ pc->SetType(CT_RPAREN_OPEN);
+ }
+ else // pc->Is(CT_FPAREN_CLOSE) || pc->Is(CT_RPAREN_CLOSE))
+ {
+ continue;
+ }
+ }
+ else // (found_functor)
+ {
+ if (pc->Is(CT_FPAREN_OPEN))
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): FOUND 1 Opening: orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+ is_it_closing = pc->GetPrevNcNnl();
+ LOG_FMT(LCOMBINE, "%s(%d): FOUND 2 Closing: orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, is_it_closing->GetOrigLine(), is_it_closing->GetOrigCol(), is_it_closing->GetLevel(), is_it_closing->Text());
+
+ if (is_it_closing->Is(CT_FPAREN_CLOSE))
+ {
+ Chunk *opening = is_it_closing->GetOpeningParen();
+ LOG_FMT(LCOMBINE, "%s(%d): FOUND 3 Opening: orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, opening->GetOrigLine(), opening->GetOrigCol(), opening->GetLevel(), opening->Text());
+ // look for member function
+ Chunk *is_it_func = opening->GetPrevNcNnl();
+ LOG_FMT(LCOMBINE, "%s(%d): FOUND 4 func: orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, is_it_func->GetOrigLine(), is_it_func->GetOrigCol(), is_it_func->GetLevel(), is_it_func->Text());
+ Chunk *is_it_member = is_it_func->GetPrevNcNnl(); // CT_MEMBER
+ LOG_FMT(LCOMBINE, "%s(%d): FOUND 5 func: orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, is_it_member->GetOrigLine(), is_it_member->GetOrigCol(), is_it_member->GetLevel(), is_it_member->Text());
+
+ if (is_it_member->Is(CT_MEMBER))
+ {
+ // set parenthesis at the function
+ // desc->add_options() ( a ) (
+ // ^
+ is_it_closing->SetType(CT_RPAREN_CLOSE);
+ // desc->add_options() ( a ) (
+ // ^
+ opening->SetType(CT_RPAREN_OPEN);
+ // desc->add_options() ( a ) (
+ // ^
+ pc->SetType(CT_RPAREN_OPEN);
+ found_functor = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): NOT useable\n", __func__, __LINE__);
+ continue;
+ }
+ }
+ else // (pc->Is(CT_FPAREN_OPEN))
+ {
+ continue;
+ } // (pc->Is(CT_FPAREN_OPEN))
+ } // (found_functor)
+ }
+} // mark_functor
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_functor.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_functor.h
new file mode 100644
index 00000000..f9449ea9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_functor.h
@@ -0,0 +1,13 @@
+/**
+ * @file mark_functor.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef MARK_FUNCTOR_H_INCLUDED
+#define MARK_FUNCTOR_H_INCLUDED
+
+void mark_functor();
+
+#endif /* MARK_FUNCTOR_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.cpp
new file mode 100644
index 00000000..84131bc7
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.cpp
@@ -0,0 +1,192 @@
+/**
+ * @file mark_question_colon.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "mark_question_colon.h"
+
+#include "chunk.h"
+#include "combine_tools.h"
+#include "log_levels.h"
+
+
+/*
+ * Issue #3558
+ * will be called if a ? (CT_QUESTION) chunk is encountered
+ * return the chunk colon if found or Chunk::NullChunkPtr
+ * if a ; (CT_SEMI_COLON) chunk is found
+ */
+Chunk *search_for_colon(Chunk *pc_question)
+{
+ Chunk *pc2 = pc_question->GetNextNcNnl();
+ bool colon_found = false;
+
+ LOG_FMT(LCOMBINE, "%s(%d): pc_question.orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc_question->GetOrigLine(), pc_question->GetOrigCol(), pc_question->GetLevel(),
+ pc_question->Text());
+
+ // examine the next tokens, look for E2, E3, COLON, might be for a next CT_QUESTION
+ while (pc2->IsNotNullChunk())
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+
+ if ( pc2->Is(CT_SEMICOLON)
+ || ( pc2->Is(CT_PAREN_CLOSE)
+ && (pc_question->GetLevel() == pc2->GetLevel() + 1))
+ || pc2->Is(CT_COMMA))
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+ pc2->SetFlagBits(PCF_IN_CONDITIONAL);
+ log_pcf_flags(LCOMBINE, pc2->GetFlags());
+
+ if (colon_found)
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+ pc_question->SetParent(pc2); // back again
+
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+ return(pc2);
+ }
+ else
+ {
+ pc2->SetParent(pc_question); // save the question token
+ pc_question->SetParent(pc2); // back again
+ }
+ }
+ else if (pc2->Is(CT_COMMA))
+ {
+ // TODO: is it necessary?
+ }
+ else if (pc2->Is(CT_QUESTION))
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+ pc2 = search_for_colon(pc2);
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+ continue;
+ }
+ else if (pc2->Is(CT_COND_COLON))
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+
+ if (colon_found)
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+ Chunk *pr = pc2->GetPrevNcNnl();
+ return(pr);
+ }
+ else
+ {
+ pc2->SetParent(pc_question); // save the question token
+ pc_question->SetParent(pc2); // back again
+ colon_found = true;
+ }
+
+ if (pc2->Is(CT_COLON))
+ {
+ if (colon_found)
+ {
+ return(pc2);
+ }
+ else
+ {
+ }
+ }
+ }
+ else if (pc2->Is(CT_COLON))
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+
+ if (colon_found)
+ {
+ pc2->SetType(CT_COND_COLON);
+ return(pc2);
+ }
+ else
+ {
+ // E2 found orig line is 23, orig col is 3
+ pc2->SetType(CT_COND_COLON);
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
+ pc2->SetParent(pc_question); // save the question token
+ pc_question->SetParent(pc2); // back again
+
+ // look for E3
+ colon_found = true;
+ }
+ }
+ pc2 = pc2->GetNextNcNnl();
+ }
+
+ if (pc2->IsNotNullChunk())
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '?'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel());
+ }
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '?'\n",
+ __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel());
+ return(pc2);
+} // search_for_colon
+
+
+void mark_question_colon()
+{
+ LOG_FUNC_ENTRY();
+ Chunk *pc = Chunk::GetHead();
+ Chunk *pc_question;
+
+ // Issue #3558
+ while (pc->IsNotNullChunk())
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+ log_pcf_flags(LCOMBINE, pc->GetFlags());
+
+ if ( pc->Is(CT_QUESTION)
+ && !language_is_set(LANG_JAVA))
+ {
+ pc_question = pc;
+ // look for E2, COLON, E3...
+ pc = search_for_colon(pc);
+
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+
+ if ( pc->Is(CT_SEMICOLON)
+ || ( pc->Is(CT_PAREN_CLOSE)
+ && (pc_question->GetLevel() == pc->GetLevel() + 1))
+ || pc->Is(CT_COMMA))
+ {
+ // set at the end of the question statement ...
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+ // ... and go on
+ }
+ }
+ pc = pc->GetNextNcNnl();
+ }
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
+
+ if (pc->Is(CT_QUESTION))
+ {
+ Chunk *from = pc;
+ Chunk *to = pc->GetParent();
+ flag_series(from, to, PCF_IN_CONDITIONAL);
+ pc = to;
+ }
+ }
+} // mark_question_colon
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.h
new file mode 100644
index 00000000..20fca294
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/mark_question_colon.h
@@ -0,0 +1,13 @@
+/**
+ * @file mark_question_colon.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef MARK_QUESTION_COLON_H_INCLUDED
+#define MARK_QUESTION_COLON_H_INCLUDED
+
+void mark_question_colon();
+
+#endif /* MARK_QUESTION_COLON_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/md5.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/md5.cpp
new file mode 100644
index 00000000..af8874a4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/md5.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/md5.h
new file mode 100644
index 00000000..d1148b5e
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/newlines.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/newlines.cpp
new file mode 100644
index 00000000..360e568a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/newlines.cpp
@@ -0,0 +1,6856 @@
+/**
+ * @file newlines.cpp
+ * Adds or removes newlines.
+ *
+ * Information
+ * "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);
+
+/**
+ * Test if an opening brace is part of a function call or definition.
+ */
+static bool is_func_call_or_def(Chunk *pc);
+
+
+//! 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_var_def_blk(Chunk *start);
+
+
+/**
+ * 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 = prev->GetPpStart();
+
+ if ( pp_start->IsNotNullChunk()
+ && ( pp_start->GetParentType() == CT_PP_IF
+ || pp_start->GetParentType() == CT_PP_ELSE)
+ && ( pp_start->GetLevel() > 0
+ || options::nl_squeeze_ifdef_top_level()))
+ {
+ log_rule_B("nl_squeeze_ifdef_top_level");
+ bool rv = ifdef_over_whole_file() && pp_start->TestFlags(PCF_WF_IF);
+ LOG_FMT(LBLANKD, "%s(%d): nl_squeeze_ifdef %zu (prev) pp_lvl=%zu rv=%d\n",
+ __func__, __LINE__, nl->GetOrigLine(), nl->GetPpLevel(), rv);
+ return(rv);
+ }
+
+ if ( next->Is(CT_PREPROC)
+ && ( next->GetParentType() == CT_PP_ELSE
+ || next->GetParentType() == CT_PP_ENDIF)
+ && ( next->GetLevel() > 0
+ || options::nl_squeeze_ifdef_top_level()))
+ {
+ log_rule_B("nl_squeeze_ifdef_top_level");
+ bool rv = ifdef_over_whole_file() && next->TestFlags(PCF_WF_ENDIF);
+ LOG_FMT(LBLANKD, "%s(%d): nl_squeeze_ifdef %zu (next) pp_lvl=%zu rv=%d\n",
+ __func__, __LINE__, nl->GetOrigLine(), nl->GetPpLevel(), rv);
+ return(rv);
+ }
+ }
+
+ if (next->Is(CT_BRACE_CLOSE))
+ {
+ if ( options::nl_inside_namespace() > 0
+ && next->GetParentType() == CT_NAMESPACE)
+ {
+ log_rule_B("nl_inside_namespace");
+ LOG_FMT(LBLANKD, "%s(%d): nl_inside_namespace %zu\n",
+ __func__, __LINE__, nl->GetOrigLine());
+ return(true);
+ }
+
+ if ( options::nl_inside_empty_func() > 0
+ && prev->Is(CT_BRACE_OPEN)
+ && ( next->GetParentType() == CT_FUNC_DEF
+ || next->GetParentType() == 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->GetOrigLine());
+ 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->GetOrigLine());
+ return(false);
+ }
+ }
+
+ if (prev->Is(CT_BRACE_CLOSE))
+ {
+ if ( options::nl_before_namespace()
+ && prev->GetParentType() == CT_NAMESPACE)
+ {
+ log_rule_B("nl_before_namespace");
+ LOG_FMT(LBLANKD, "%s(%d): nl_before_namespace %zu\n",
+ __func__, __LINE__, nl->GetOrigLine());
+ return(true);
+ }
+ }
+
+ if (prev->Is(CT_BRACE_OPEN))
+ {
+ if ( options::nl_inside_namespace() > 0
+ && prev->GetParentType() == CT_NAMESPACE)
+ {
+ log_rule_B("nl_inside_namespace");
+ LOG_FMT(LBLANKD, "%s(%d): nl_inside_namespace %zu\n",
+ __func__, __LINE__, nl->GetOrigLine());
+ return(true);
+ }
+
+ if ( options::nl_inside_empty_func() > 0
+ && next->Is(CT_BRACE_CLOSE)
+ && ( prev->GetParentType() == CT_FUNC_DEF
+ || prev->GetParentType() == 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->GetOrigLine());
+ 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->GetOrigLine());
+ 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->GetOrigLine());
+ 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->GetOrigLine());
+ return(false);
+ }
+ return(true);
+} // can_increase_nl
+
+
+static void setup_newline_add(Chunk *prev, Chunk *nl, Chunk *next)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( prev->IsNullChunk()
+ || nl->IsNullChunk()
+ || next->IsNullChunk())
+ {
+ return;
+ }
+ undo_one_liner(prev);
+
+ nl->SetOrigLine(prev->GetOrigLine());
+ nl->SetLevel(prev->GetLevel());
+ nl->SetPpLevel(prev->GetPpLevel());
+ nl->SetBraceLevel(prev->GetBraceLevel());
+ nl->SetPpLevel(prev->GetPpLevel());
+ nl->SetNlCount(1);
+ nl->SetFlags((prev->GetFlags() & PCF_COPY_FLAGS) & ~PCF_IN_PREPROC);
+ nl->SetOrigCol(prev->GetOrigColEnd());
+ nl->SetColumn(prev->GetOrigCol());
+
+ if ( prev->TestFlags(PCF_IN_PREPROC)
+ && next->TestFlags(PCF_IN_PREPROC))
+ {
+ nl->SetFlagBits(PCF_IN_PREPROC);
+ }
+
+ if (nl->TestFlags(PCF_IN_PREPROC))
+ {
+ nl->SetType(CT_NL_CONT);
+ nl->Str() = "\\\n";
+ }
+ else
+ {
+ nl->SetType(CT_NEWLINE);
+ nl->Str() = "\n";
+ }
+} // setup_newline_add
+
+
+void double_newline(Chunk *nl)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = nl->GetPrev();
+
+ if (prev->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): add newline after ", __func__, __LINE__);
+
+ if (prev->Is(CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LNEWLINE, "VBRACE_CLOSE ");
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "'%s' ", prev->Text());
+ }
+ LOG_FMT(LNEWLINE, "on line %zu", prev->GetOrigLine());
+
+ if (!can_increase_nl(nl))
+ {
+ LOG_FMT(LNEWLINE, " - denied\n");
+ return;
+ }
+ LOG_FMT(LNEWLINE, " - done\n");
+
+ if (nl->GetNlCount() != 2)
+ {
+ nl->SetNlCount(2);
+ MARK_CHANGE();
+ }
+} // double_newline
+
+
+Chunk *newline_add_before(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk nl;
+ Chunk *prev = pc->GetPrevNvb();
+
+ if (prev->IsNewline())
+ {
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->GetColumn());
+ log_func_stack_inline(LNEWLINE);
+
+ setup_newline_add(prev, &nl, pc);
+ nl.SetOrigCol(pc->GetOrigCol());
+ nl.SetPpLevel(pc->GetPpLevel());
+ LOG_FMT(LNEWLINE, "%s(%d): nl column is %zu\n",
+ __func__, __LINE__, nl.GetColumn());
+
+ MARK_CHANGE();
+ return(nl.CopyAndAddBefore(pc));
+} // newline_add_before
+
+
+Chunk *newline_force_before(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *nl = newline_add_before(pc);
+
+ if ( nl->IsNotNullChunk()
+ && nl->GetNlCount() > 1)
+ {
+ nl->SetNlCount(1);
+ MARK_CHANGE();
+ }
+ return(nl);
+} // newline_force_before
+
+
+Chunk *newline_add_after(Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc->IsNullChunk())
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ Chunk *next = pc->GetNextNvb();
+
+ if (next->IsNewline())
+ {
+ // Already has a newline after this chunk
+ return(next);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): '%s' on line %zu",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ log_func_stack_inline(LNEWLINE);
+
+ Chunk nl;
+
+ nl.SetOrigLine(pc->GetOrigLine());
+ nl.SetOrigCol(pc->GetOrigCol());
+ setup_newline_add(pc, &nl, next);
+
+ MARK_CHANGE();
+ // TO DO: check why the next statement is necessary
+ nl.SetOrigCol(pc->GetOrigCol());
+ nl.SetPpLevel(pc->GetPpLevel());
+ return(nl.CopyAndAddAfter(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->GetNlCount() > 1) // check if there are more than 1 newline
+ {
+ nl->SetNlCount(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 (!next->IsCommentOrNewline())
+ {
+ nl.SetOrigLine(br_close->GetOrigLine());
+ nl.SetOrigCol(br_close->GetOrigCol());
+ nl.SetNlCount(1);
+ nl.SetPpLevel(0);
+ nl.SetFlags((br_close->GetFlags() & PCF_COPY_FLAGS) & ~PCF_IN_PREPROC);
+
+ if ( br_close->TestFlags(PCF_IN_PREPROC)
+ && next->IsNotNullChunk()
+ && next->TestFlags(PCF_IN_PREPROC))
+ {
+ nl.SetFlagBits(PCF_IN_PREPROC);
+ }
+
+ if (nl.TestFlags(PCF_IN_PREPROC))
+ {
+ nl.SetType(CT_NL_CONT);
+ nl.Str() = "\\\n";
+ }
+ else
+ {
+ nl.SetType(CT_NEWLINE);
+ nl.Str() = "\n";
+ }
+ MARK_CHANGE();
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline after '%s'\n",
+ __func__, __LINE__, br_close->GetOrigLine(), br_close->GetOrigCol(), br_close->Text());
+ nl.CopyAndAddAfter(br_close);
+ }
+} // newline_end_newline
+
+
+static void newline_min_after(Chunk *ref, size_t count, E_PcfFlag 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->GetOrigLine(), count,
+ pcf_flags_str(flag).c_str());
+ log_func_stack_inline(LNEWLINE);
+
+ Chunk *pc = ref;
+
+ do
+ {
+ pc = pc->GetNext();
+ } while ( pc->IsNotNullChunk()
+ && !pc->IsNewline());
+
+ 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->GetType()), pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ return;
+ }
+
+ if ( next->IsComment()
+ && next->GetNlCount() == 1
+ && pc->GetPrev()->IsComment())
+ {
+ newline_min_after(next, count, flag);
+ return;
+ }
+ pc->SetFlagBits(flag);
+
+ if ( pc->IsNewline()
+ && can_increase_nl(pc))
+ {
+ if (pc->GetNlCount() < count)
+ {
+ pc->SetNlCount(count);
+ MARK_CHANGE();
+ }
+ }
+} // newline_min_after
+
+
+Chunk *newline_add_between(Chunk *start, Chunk *end)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( start->IsNullChunk()
+ || end->IsNullChunk()
+ || end->Is(CT_IGNORED))
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ 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->GetType()),
+ start->GetOrigLine(), start->GetOrigCol());
+ LOG_FMT(LNEWLINE, "%s(%d): and end->Text() is '%s', orig line is %zu, orig col is %zu\n ",
+ __func__, __LINE__, end->Text(), end->GetOrigLine(), end->GetOrigCol());
+ log_func_stack_inline(LNEWLINE);
+
+ // Back-up check for one-liners (should never be true!)
+ if (!one_liner_nl_ok(start))
+ {
+ return(Chunk::NullChunkPtr);
+ }
+
+ /*
+ * 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 (pc->IsNewline())
+ {
+ return(pc);
+ }
+ }
+
+ /*
+ * If the second one is a brace open, then check to see
+ * if a comment + newline follows
+ */
+ if (end->Is(CT_BRACE_OPEN))
+ {
+ Chunk *pc = end->GetNext();
+
+ if (pc->IsComment())
+ {
+ pc = pc->GetNext();
+
+ if (pc->IsNewline())
+ {
+ // are there some more (comment + newline)s ?
+ Chunk *pc1 = end->GetNextNcNnl();
+
+ if (!pc1->IsNewline())
+ {
+ // 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
+ end->MoveAfter(pc);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__);
+ newline_add_after(end);
+ return(pc);
+ }
+ else // Issue #3873
+ {
+ LOG_FMT(LNEWLINE, "%s(%d):\n", __func__, __LINE__);
+ }
+ }
+ 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->GetOrigLine(), start->GetOrigCol());
+ 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->GetOrigLine(), end->GetOrigCol(),
+ start->TestFlags(PCF_IN_PREPROC) ? 'y' : 'n',
+ end->TestFlags(PCF_IN_PREPROC) ? 'y' : 'n');
+ log_func_stack_inline(LNEWLINE);
+
+ // Can't remove anything if the preproc status differs
+ if (!start->IsSamePreproc(end))
+ {
+ return;
+ }
+ Chunk *pc = start;
+ bool start_removed = false;
+
+ do
+ {
+ Chunk *next = pc->GetNext();
+
+ if (pc->IsNewline())
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( ( !prev->IsComment()
+ && !next->IsComment())
+ || prev->IsNewline()
+ || next->IsNewline())
+ {
+ if (pc->SafeToDeleteNl())
+ {
+ if (pc == start)
+ {
+ start_removed = true;
+ }
+ Chunk::Delete(pc);
+ MARK_CHANGE();
+
+ if (prev->IsNotNullChunk())
+ {
+ size_t temp = space_col_align(prev, next);
+ align_to_column(next, prev->GetColumn() + temp);
+ dump_step(dump_file_name, "del 1");
+ }
+ }
+ }
+ else
+ {
+ if (pc->GetNlCount() > 1)
+ {
+ pc->SetNlCount(1);
+ MARK_CHANGE();
+ }
+ }
+ }
+ pc = next;
+ } while (pc != end);
+
+ if ( !start_removed
+ && end->IsString("{")
+ && ( start->IsString(")")
+ || start->Is(CT_DO)
+ || start->Is(CT_ELSE)))
+ {
+ end->MoveAfter(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->GetLevel());
+
+ 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
+ && !sparen_content_start->IsOnSameLine(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 ( ctrl_structure->Is(CT_IF)
+ || ctrl_structure->Is(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->TestFlags(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return(false);
+ }
+ bool retval = false;
+ Chunk *pc = start->GetNextNcNnl();
+
+ if (pc->Is(CT_SPAREN_OPEN))
+ {
+ Chunk *close_paren = pc->GetNextType(CT_SPAREN_CLOSE, pc->GetLevel());
+ Chunk *brace_open = close_paren->GetNextNcNnl();
+
+ if ( ( brace_open->Is(CT_BRACE_OPEN)
+ || brace_open->Is(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 (pc->IsNewline())
+ {
+ nl_opt = IARF_ADD;
+ break;
+ }
+ }
+ }
+
+ if (brace_open->Is(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->GetLevel());
+
+ if ( !pc->GetPrevNc()->IsNewline()
+ && !pc->GetNextNc()->IsNewline())
+ {
+ newline_add_after(pc);
+ retval = true;
+ }
+ }
+ }
+ else
+ {
+ newline_iarf_pair(close_paren, brace_open, nl_opt);
+ Chunk *next = brace_open->GetNextNcNnl();
+
+ if (brace_open->GetType() != next->GetType()) // 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->GetLevel());
+ 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 col is %zu\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->GetType()), start->GetOrigLine(), start->GetOrigCol());
+
+ log_rule_B("nl_define_macro");
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->TestFlags(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->IsNotNullChunk(); pc = pc->GetPrev())
+ {
+ size_t level = start->GetLevel();
+ bool do_add = (nl_opt & IARF_ADD) != IARF_IGNORE; // forcing value to bool
+ Chunk *last_nl = Chunk::NullChunkPtr;
+
+ if (pc->IsNewline())
+ {
+ last_nl = pc;
+
+ // if we found 2 or more in a row
+ if ( pc->GetNlCount() > 1
+ || pc->GetPrevNvb()->IsNewline())
+ {
+ // need to remove
+ if ( (nl_opt & IARF_REMOVE)
+ && !pc->TestFlags(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->GetNlCount())
+ {
+ pc->SetNlCount(nl_count);
+ MARK_CHANGE();
+ }
+ Chunk *prev;
+
+ // can keep using pc because anything other than newline stops loop, and we delete if newline
+ while ((prev = pc->GetPrevNvb())->IsNewline())
+ {
+ // Make sure we don't combine a preproc and non-preproc
+ if (!prev->SafeToDeleteNl())
+ {
+ break;
+ }
+ Chunk::Delete(prev);
+ MARK_CHANGE();
+ }
+ }
+ return;
+ }
+ }
+ else if ( pc->IsBraceOpen()
+ || pc->GetLevel() < level)
+ {
+ return;
+ }
+ else if (pc->IsComment())
+ {
+ // vbrace close is ok because it won't go into output, so we should skip it
+ last_nl = Chunk::NullChunkPtr;
+ continue;
+ }
+ else
+ {
+ if ( pc->Is(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->IsNotNullChunk())
+ {
+ if (last_nl->GetNlCount() < 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->IsNullChunk())
+ {
+ return;
+ }
+ const unsigned optval = opt();
+
+ if ( (optval > 0)
+ && (pc->GetNlCount() != optval))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): do_blank_lines: %s set line %zu to %u\n",
+ __func__, __LINE__, opt.name(), pc->GetOrigLine(), optval);
+ pc->SetNlCount(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->IsNullChunk())
+ {
+ 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->GetOrigLine(), last_nl->GetOrigCol(), get_token_name(last_nl->GetType()), 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->GetNlCount();
+ 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->GetNlCount())
+ {
+ 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->GetNlCount();
+ 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->GetNlCount())
+ {
+ 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 new line count is %zu\n",
+ __func__, __LINE__, options::nl_before_func_body_def(), last_nl->GetNlCount());
+ log_rule_B("nl_before_func_body_def");
+ bool diff = options::nl_before_func_body_def() <= last_nl->GetNlCount();
+ 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->GetNlCount())
+ {
+ 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 new line count is %zu\n",
+ __func__, __LINE__, options::nl_before_func_body_def(), last_nl->GetNlCount());
+ return(diff);
+ }
+
+ case CT_FUNC_PROTO:
+ {
+ log_rule_B("nl_before_func_body_proto");
+ bool diff = options::nl_before_func_body_proto() <= last_nl->GetNlCount();
+ 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->GetNlCount())
+ {
+ 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->GetOrigLine());
+ 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->IsNullChunk()
+ || ( ( 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->GetOrigLine(), start->GetOrigCol(), 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->GetOrigLine());
+ /*
+ * 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 = Chunk::NullChunkPtr;
+ Chunk *last_nl = Chunk::NullChunkPtr;
+ Chunk *last_comment = Chunk::NullChunkPtr;
+ size_t first_line = start->GetOrigLine();
+
+ for (pc = start->GetPrev(); pc->IsNotNullChunk(); pc = pc->GetPrev())
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): orig line is %zu, orig col is %zu, type is %s, Text() is '%s', new line count is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), pc->Text(), pc->GetNlCount());
+
+ if (pc->IsNewline())
+ {
+ last_nl = pc;
+ LOG_FMT(LNLFUNCT, "%s(%d): <Chunk::IsNewline> found at line %zu, column %zu, new line count is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount());
+ LOG_FMT(LNLFUNCT, "%s(%d): last_nl set to %zu\n",
+ __func__, __LINE__, last_nl->GetOrigLine());
+ bool break_now = false;
+
+ if (pc->GetNlCount() > 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::IsComment> found at line %zu, column %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+
+ if ( ( pc->GetOrigLine() < first_line
+ && ((first_line - pc->GetOrigLine()
+ - (pc->Is(CT_COMMENT_MULTI) ? pc->GetNlCount() : 0))) < 2)
+ || ( last_comment->IsNotNullChunk()
+ && pc->Is(CT_COMMENT_CPP) // combine only cpp comments
+ && last_comment->Is(pc->GetType()) // don't mix comment types
+ && last_comment->GetOrigLine() > pc->GetOrigLine()
+ && (last_comment->GetOrigLine() - pc->GetOrigLine()) < 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 ( pc->Is(CT_DESTRUCTOR)
+ || pc->Is(CT_TYPE)
+ || pc->Is(CT_TEMPLATE)
+ || pc->Is(CT_QUALIFIER)
+ || pc->Is(CT_PTR_TYPE)
+ || pc->Is(CT_BYREF) // Issue #2163
+ || pc->Is(CT_DC_MEMBER)
+ || pc->Is(CT_EXTERN)
+ || ( pc->Is(CT_STRING)
+ && pc->GetParentType() == CT_EXTERN))
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d): first_line set to %zu\n",
+ __func__, __LINE__, pc->GetOrigLine());
+ first_line = pc->GetOrigLine();
+ continue;
+ }
+ else if ( pc->Is(CT_ANGLE_CLOSE)
+ && pc->GetParentType() == CT_TEMPLATE)
+ {
+ LOG_FMT(LNLFUNCT, "%s(%d):\n", __func__, __LINE__);
+ // skip template stuff to add newlines before it
+ pc = pc->GetOpeningParen();
+
+ if (pc->IsNotNullChunk())
+ {
+ first_line = pc->GetOrigLine();
+ }
+ 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->GetLevel();
+
+ for (pc = start; (pc = pc->GetNext())->IsNotNullChunk();)
+ {
+ if ( (pc->IsBraceClose())
+ && pc->GetLevel() == level)
+ {
+ return(pc);
+ }
+
+ // for some reason, we can have newlines between if and opening brace that are lower level than either
+ if ( !pc->IsNewline()
+ && pc->GetLevel() < level)
+ {
+ return(Chunk::NullChunkPtr);
+ }
+ }
+
+ return(Chunk::NullChunkPtr);
+} // get_closing_brace
+
+
+static void remove_next_newlines(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *next;
+
+ while ((next = start->GetNext())->IsNotNullChunk())
+ {
+ if ( next->IsNewline()
+ && next->SafeToDeleteNl())
+ {
+ Chunk::Delete(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 col is %zu\n",
+ __func__, __LINE__, start->Text(), get_token_name(start->GetType()), start->GetOrigLine(), start->GetOrigCol());
+
+ log_rule_B("nl_define_macro");
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->TestFlags(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+ Chunk *pc = get_closing_brace(start);
+
+ // first find ending brace
+ if (pc->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type is %s, orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol());
+
+ /*
+ * if we're dealing with an if, we actually want to add or remove
+ * blank lines after any else
+ */
+ if (start->Is(CT_IF))
+ {
+ Chunk *next;
+
+ while (true)
+ {
+ next = pc->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && ( next->Is(CT_ELSE)
+ || next->Is(CT_ELSEIF)))
+ {
+ // point to the closing brace of the else
+ if ((pc = get_closing_brace(next))->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ 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 (start->Is(CT_DO))
+ {
+ // point to the next semicolon
+ if ((pc = pc->GetNextType(CT_SEMICOLON, start->GetLevel()))->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ bool isVBrace = (pc->Is(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 && prev->IsNewline();
+
+ 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->GetNlCount() != 1)
+ {
+ prev->SetNlCount(1);
+ MARK_CHANGE();
+ }
+ remove_next_newlines(pc);
+ }
+ else if ( ((next = pc->GetNextNvb())->IsNewline())
+ && !next->TestFlags(PCF_VAR_DEF))
+ {
+ // otherwise just deal with newlines after brace
+ if (next->GetNlCount() != 1)
+ {
+ next->SetNlCount(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 (next->IsNot(CT_VBRACE_CLOSE))
+ {
+ break;
+ }
+ next = next->GetNextNnl();
+ } while (true);
+
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol());
+
+ if (next->IsNot(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->GetNlCount() : 0;
+ LOG_FMT(LNEWLINE, "%s(%d): new line count %zu\n", __func__, __LINE__, nl_count);
+
+ if ((next = pc->GetNextNvb())->IsNewline())
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol());
+ nl_count += next->GetNlCount();
+ LOG_FMT(LNEWLINE, "%s(%d): new line 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): new line 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 col %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol());
+ pc = next;
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol());
+ }
+
+ if ((next = newline_add_after(pc))->IsNullChunk())
+ {
+ return;
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): next->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol());
+ double_newline(next);
+ }
+ else if (nl_count == 1) // if we don't have enough newlines
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): new line count is 1\n", __func__, __LINE__);
+
+ // if we have a preceding 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 col %zu\n",
+ __func__, __LINE__, next->Text(), get_token_name(next->GetType()), next->GetOrigLine(), next->GetOrigCol());
+ }
+ 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 col %zu\n",
+ __func__, __LINE__, prev->Text(), get_token_name(prev->GetType()), prev->GetOrigLine(), prev->GetOrigCol());
+ pc = next->GetNextNl();
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol());
+ Chunk *pc2 = pc->GetNext();
+
+ if (pc2->IsNotNullChunk())
+ {
+ pc = pc2;
+ LOG_FMT(LNEWLINE, "%s(%d): pc->Text() is '%s', type %s, orig line %zu, orig col %zu\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()), pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): no next found: <EOF>\n", __func__, __LINE__);
+ }
+ log_rule_B("nl_squeeze_ifdef");
+
+ if ( pc->Is(CT_PREPROC)
+ && pc->GetParentType() == 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->GetOrigLine());
+ }
+ 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->TestFlags(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->GetLevel();
+ Chunk *pc = start->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() >= level)
+ {
+ if ( pc->GetLevel() == level
+ && ( pc->Is(CT_BRACE_OPEN)
+ || pc->IsSemicolon()
+ || pc->Is(CT_ASSIGN)))
+ {
+ break;
+ }
+ start = pc;
+ pc = pc->GetNextNcNnl();
+ }
+
+ // If we hit a brace open, then we need to toy with the newlines
+ if (pc->Is(CT_BRACE_OPEN))
+ {
+ // Skip over embedded C comments
+ Chunk *next = pc->GetNext();
+
+ while (next->Is(CT_COMMENT))
+ {
+ next = next->GetNext();
+ }
+
+ if ( leave_trailing
+ && !next->IsCommentOrNewline())
+ {
+ 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->TestFlags(PCF_IN_PREPROC)
+ && !options::nl_define_macro())
+ {
+ return;
+ }
+ // look for 'enum class'
+ Chunk *pcClass = start->GetNextNcNnl();
+
+ if (pcClass->Is(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 (pcType->Is(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 (pcColon->Is(CT_ENUM_COLON)) // Issue #4040
+ {
+ 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 (pcType1->Is(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 (pcType2->Is(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->GetLevel();
+ Chunk *pc = start->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && pc->GetLevel() >= level)
+ {
+ if ( pc->GetLevel() == level
+ && ( pc->Is(CT_BRACE_OPEN)
+ || pc->IsSemicolon()
+ || pc->Is(CT_ASSIGN)))
+ {
+ break;
+ }
+ start = pc;
+ pc = pc->GetNextNcNnl();
+ }
+
+ // If we hit a brace open, then we need to toy with the newlines
+ if (pc->Is(CT_BRACE_OPEN))
+ {
+ // Skip over embedded C comments
+ Chunk *next = pc->GetNext();
+
+ while (next->Is(CT_COMMENT))
+ {
+ next = next->GetNext();
+ }
+ iarf_e nl_opt;
+
+ if (!next->IsCommentOrNewline())
+ {
+ 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->TestFlags(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+ Chunk *braceOpen = start->GetNextType(CT_BRACE_OPEN, start->GetLevel());
+
+ LOG_FMT(LNEWLINE, "%s(%d): braceOpen orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, braceOpen->GetOrigLine(), braceOpen->GetOrigCol(), braceOpen->Text());
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, braceOpen->GetFlags());
+
+ if (braceOpen->TestFlags(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->GetOrigLine(), beforeBrace->GetOrigCol(), 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->TestFlags(PCF_IN_PREPROC)
+ && !options::nl_define_macro())
+ {
+ return;
+ }
+ Chunk *br_close = start->GetPrevNcNnlNi(); // Issue #2279
+
+ if (br_close->Is(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");
+ log_ruleNL("nl_define_macro", start);
+
+ if ( nl_opt == IARF_IGNORE
+ || ( start->TestFlags(PCF_IN_PREPROC)
+ && !options::nl_define_macro()))
+ {
+ return;
+ }
+ Chunk *next = start->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && ( next->Is(CT_BRACE_OPEN)
+ || next->Is(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 (next->Is(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->GetLevel());
+
+ if ( !tmp->GetNextNc()->IsNewline()
+ && !tmp->GetPrevNc()->IsNewline())
+ {
+ 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 ( pc->Is(CT_DECLTYPE)
+ && next->Is(CT_PAREN_OPEN))
+ {
+ // If current token starts a decltype expression, skip it
+ next = next->GetClosingParen();
+ next = next->GetNextNcNnl();
+ }
+ else if (!pc->IsTypeDefinition())
+ {
+ // Otherwise, if the current token is not a type --> not a declaration
+ return(false);
+ }
+ else if (next->Is(CT_DC_MEMBER))
+ {
+ // If next token is CT_DC_MEMBER, skip it
+ next = next->SkipDcMember();
+ }
+ else if (next->Is(CT_ANGLE_OPEN))
+ {
+ // If we have a template type, skip it
+ next = next->GetClosingParen();
+ next = next->GetNextNcNnl();
+ }
+ bool is = ( ( next->IsTypeDefinition()
+ && next->GetParentType() != CT_FUNC_DEF) // Issue #2639
+ || next->Is(CT_WORD)
+ || next->Is(CT_FUNC_CTOR_VAR));
+
+ return(is);
+} // is_var_def
+
+
+static bool is_func_call_or_def(Chunk *pc)
+{
+ if ( pc->GetParentType() == CT_FUNC_DEF
+ || pc->GetParentType() == CT_FUNC_CALL
+ || pc->GetParentType() == CT_FUNC_CALL_USER
+ || pc->GetParentType() == CT_FUNC_CLASS_DEF
+ || pc->GetParentType() == CT_OC_CLASS
+ || pc->GetParentType() == CT_OC_MSG_DECL
+ || pc->GetParentType() == CT_CS_PROPERTY
+ || pc->GetParentType() == CT_CPP_LAMBDA)
+ {
+ return(true);
+ }
+ return(false);
+} // is_func_call_or_def
+
+
+// Put newline(s) before and/or after a block of variable definitions
+static Chunk *newline_var_def_blk(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = start;
+ Chunk *prev = start->GetPrevNcNnlNi(); // Issue #2279
+ bool did_this_line = false;
+ bool fn_top = false;
+ bool var_blk = false;
+ bool first_var_blk = true;
+
+ LOG_FMT(LVARDFBLK, "%s(%d): start orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), start->Text());
+
+ if (start->Is(CT_BRACE_OPEN))
+ {
+ // can't be any variable definitions in a "= {" block
+ if ( prev->IsNotNullChunk()
+ && prev->Is(CT_ASSIGN))
+ {
+ Chunk *tmp = start->GetClosingParen();
+ return(tmp->GetNextNcNnl());
+ }
+ // check if we're at the top of a function definition, or function call with a
+ // possible variable block
+ fn_top = is_func_call_or_def(start);
+ // opening brace is processed, start with next chunk
+ pc = pc->GetNext();
+ }
+
+ while ( pc->IsNotNullChunk()
+ && ( pc->GetLevel() >= start->GetLevel()
+ || pc->GetLevel() == 0))
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ Chunk *next_pc = pc->GetNext();
+ LOG_FMT(LVARDFBLK, "%s(%d): next_pc orig line is %zu, orig col is %zu, type is %s, Text() is '%s'\n",
+ __func__, __LINE__, next_pc->GetOrigLine(), next_pc->GetOrigCol(), get_token_name(next_pc->GetType()), next_pc->Text());
+
+ // If next_pc token is CT_DC_MEMBER, skip it
+ if (next_pc->Is(CT_DC_MEMBER))
+ {
+ pc = pc->SkipDcMember();
+ }
+
+ // skip qualifiers
+ if (pc->Is(CT_QUALIFIER))
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+
+ if (pc->IsComment())
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+
+ // process nested braces
+ if (pc->Is(CT_BRACE_OPEN))
+ {
+ pc = newline_var_def_blk(pc);
+ continue;
+ }
+
+ // Done with this brace set?
+ if (pc->Is(CT_BRACE_CLOSE))
+ {
+ pc = pc->GetNext();
+ break;
+ }
+
+ // skip vbraces
+ if (pc->Is(CT_VBRACE_OPEN))
+ {
+ pc = pc->GetNextType(CT_VBRACE_CLOSE, pc->GetLevel());
+ pc = pc->GetNext();
+ continue;
+ }
+
+ // Ignore stuff inside parenthesis/squares/angles
+ if (pc->GetLevel() > pc->GetBraceLevel())
+ {
+ pc = pc->GetNext();
+ continue;
+ }
+
+ if (pc->IsNewline())
+ {
+ did_this_line = false;
+ pc = pc->GetNext();
+ continue;
+ }
+
+ // Determine if this is a variable definition or code
+ if ( !did_this_line
+ && pc->IsNot(CT_FUNC_CLASS_DEF)
+ && pc->IsNot(CT_FUNC_CLASS_PROTO)
+ && ( (pc->GetLevel() == (start->GetLevel() + 1))
+ || pc->GetLevel() == 0))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+ LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text());
+
+ // skip over all other type-like things
+ while ( next->Is(CT_PTR_TYPE) // Issue #2692
+ || next->Is(CT_BYREF) // Issue #3018
+ || next->Is(CT_QUALIFIER)
+ || next->Is(CT_TSQUARE))
+ {
+ next = next->GetNextNcNnl();
+ LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text());
+ }
+
+ if (next->IsNullChunk())
+ {
+ break;
+ }
+ LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text());
+
+ prev = pc->GetPrevNcNnl();
+
+ while ( prev->Is(CT_DC_MEMBER)
+ || prev->Is(CT_QUALIFIER)
+ || prev->Is(CT_TYPE))
+ {
+ prev = prev->GetPrevNcNnl();
+ }
+
+ if (!( prev->IsBraceOpen()
+ || prev->IsBraceClose()))
+ {
+ prev = pc->GetPrevType(CT_SEMICOLON, pc->GetLevel());
+ }
+
+ if (prev->IsNullChunk())
+ {
+ prev = pc->GetPrevType(CT_BRACE_OPEN, pc->GetLevel() - 1); // Issue #2692
+ }
+
+ if ( prev->Is(CT_STRING)
+ && prev->GetParentType() == CT_EXTERN
+ && prev->GetPrev()->Is(CT_EXTERN))
+ {
+ prev = prev->GetPrev()->GetPrevNcNnlNi(); // Issue #2279
+ }
+ LOG_FMT(LVARDFBLK, "%s(%d): pc orig line is %zu, orig col is %zu, type is %s, Text() is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), pc->Text());
+ LOG_FMT(LVARDFBLK, "%s(%d): next orig line is %zu, orig col is %zu, type is %s, Text() is '%s'\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), get_token_name(next->GetType()), next->Text());
+
+ if (is_var_def(pc, next))
+ {
+ LOG_FMT(LVARDFBLK, "%s(%d): 'typ==var' found: '%s %s' at line %zu\n",
+ __func__, __LINE__, pc->Text(), next->Text(), pc->GetOrigLine());
+ LOG_FMT(LBLANKD, "%s(%d): var_blk %s, first_var_blk %s, fn_top %s\n",
+ __func__, __LINE__, var_blk ? "TRUE" : "FALSE",
+ first_var_blk ? "TRUE" : "FALSE", fn_top ? "TRUE" : "FALSE");
+ // 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(LVARDFBLK, "%s(%d): pc is '%s', orig line is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+
+ if (prev->IsNullChunk())
+ {
+ LOG_FMT(LVARDFBLK, "%s(%d): prev is a null chunk\n", __func__, __LINE__);
+ }
+ else
+ {
+ LOG_FMT(LVARDFBLK, "%s(%d): prev is '%s', orig line is %zu\n",
+ __func__, __LINE__, prev->Text(), prev->GetOrigLine());
+
+ if (!prev->IsBraceOpen())
+ {
+ newline_min_after(prev, options::nl_var_def_blk_start() + 1, PCF_VAR_DEF);
+ }
+ }
+ }
+ // set newlines within var def block
+ log_rule_B("nl_var_def_blk_in");
+
+ if ( var_blk
+ && (options::nl_var_def_blk_in() > 0))
+ {
+ prev = pc->GetPrev();
+ LOG_FMT(LVARDFBLK, "%s(%d): prev orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text());
+
+ if (prev->IsNewline())
+ {
+ if (prev->GetNlCount() > options::nl_var_def_blk_in())
+ {
+ prev->SetNlCount(options::nl_var_def_blk_in());
+ MARK_CHANGE();
+ }
+ }
+ }
+ pc = pc->GetNextType(CT_SEMICOLON, pc->GetLevel());
+ var_blk = true;
+ }
+ else if (var_blk)
+ {
+ LOG_FMT(LVARDFBLK, "%s(%d): var_blk %s, first_var_blk %s, fn_top %s\n",
+ __func__, __LINE__, var_blk ? "TRUE" : "FALSE",
+ first_var_blk ? "TRUE" : "FALSE", fn_top ? "TRUE" : "FALSE");
+ log_rule_B("nl_var_def_blk_end_func_top");
+ log_rule_B("nl_var_def_blk_end");
+
+ if ( first_var_blk
+ && fn_top)
+ {
+ // set blank lines after first var def block at the top of a function
+ if (options::nl_var_def_blk_end_func_top() > 0)
+ {
+ LOG_FMT(LVARDFBLK, "%s(%d): nl_var_def_blk_end_func_top at line %zu\n",
+ __func__, __LINE__, prev->GetOrigLine());
+ newline_min_after(prev, options::nl_var_def_blk_end_func_top() + 1, PCF_VAR_DEF);
+ }
+ }
+ else if ( !pc->IsPreproc()
+ && options::nl_var_def_blk_end() > 0)
+ {
+ // set blank lines after other var def blocks
+ LOG_FMT(LVARDFBLK, "%s(%d): nl_var_def_blk_end at line %zu\n",
+ __func__, __LINE__, prev->GetOrigLine());
+ // Issue #3516
+ newline_min_after(prev, options::nl_var_def_blk_end() + 1, PCF_VAR_DEF);
+ }
+ // reset the variables for the next block
+ first_var_blk = false;
+ var_blk = false;
+ }
+ else
+ {
+ first_var_blk = false;
+ var_blk = false;
+ }
+ }
+ else
+ {
+ if (pc->Is(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();
+ }
+ LOG_FMT(LVARDFBLK, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', level is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetLevel());
+ LOG_FMT(LVARDFBLK, "%s(%d): start orig line is %zu, orig col is %zu, Text() is '%s', level is %zu\n",
+ __func__, __LINE__, start->GetOrigLine(), start->GetOrigCol(), start->Text(), start->GetLevel());
+ return(pc);
+} // newline_var_def_blk
+
+
+static void collapse_empty_body(Chunk *br_open)
+{
+ for (Chunk *pc = br_open->GetNext(); pc->IsNot(CT_BRACE_CLOSE); pc = pc->GetNext())
+ {
+ if ( pc->Is(CT_NEWLINE)
+ && pc->SafeToDeleteNl())
+ {
+ pc = pc->GetPrev();
+ Chunk *next = pc->GetNext();
+ Chunk::Delete(next);
+ MARK_CHANGE();
+ }
+ }
+} // collapse_empty_body
+
+
+static void newlines_brace_pair(Chunk *br_open)
+{
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("nl_define_macro");
+
+ if ( br_open->TestFlags(PCF_IN_PREPROC)
+ && !options::nl_define_macro())
+ {
+ return;
+ }
+
+ //fixes 1235 Add single line namespace support
+ if ( br_open->Is(CT_BRACE_OPEN)
+ && (br_open->GetParentType() == CT_NAMESPACE)
+ && br_open->GetPrev()->IsNewline())
+ {
+ Chunk *chunk_brace_close = br_open->GetClosingParen();
+
+ if (chunk_brace_close->IsNotNullChunk())
+ {
+ if (br_open->IsOnSameLine(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 ( br_open->GetParentType() == CT_FUNC_DEF
+ && options::nl_create_func_def_one_liner()
+ && !br_open->TestFlags(PCF_NOT_POSSIBLE)) // Issue #2795
+ {
+ Chunk *br_close = br_open->GetClosingParen();
+ Chunk *tmp = br_open->GetPrevNcNnlNi(); // Issue #2279
+
+ if ( br_close->IsNotNullChunk() // Issue #2594
+ && ((br_close->GetOrigLine() - br_open->GetOrigLine()) <= 2)
+ && tmp->IsParenClose()) // need to check the conditions.
+ {
+ // Issue #1825
+ bool is_it_possible = true;
+
+ while ( tmp->IsNotNullChunk()
+ && (tmp = tmp->GetNext())->IsNotNullChunk()
+ && !tmp->IsBraceClose()
+ && (tmp->GetNext()->IsNotNullChunk()))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): tmp orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), 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->GetOrigLine(), current->GetOrigCol(), 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()
+ && !tmp_1->IsBraceClose()
+ && (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->GetOrigLine(), tmp_1->GetOrigCol(), tmp_1->Text());
+
+ if (tmp_1->IsNewline())
+ {
+ tmp_1 = tmp_1->GetPrev(); // Issue #1825
+ newline_iarf_pair(tmp_1, tmp_1->GetNextNcNnl(), IARF_REMOVE);
+ }
+ }
+ br_open->SetFlagBits(PCF_ONE_LINER); // set the one liner flag if needed
+ br_close->SetFlagBits(PCF_ONE_LINER);
+ log_rule_B("code_width");
+
+ if ( options::code_width() > 0
+ && br_close->GetColumn() > 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
+ br_open->SetFlagBits(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.GetOrigLine() != current->GetOrigLine())
+ {
+ // restore the newline
+ Chunk chunk;
+ chunk.SetType(CT_NEWLINE);
+ chunk.SetOrigLine(current->GetOrigLine());
+ chunk.SetOrigCol(current->GetOrigCol());
+ chunk.SetPpLevel(current->GetPpLevel());
+ chunk.SetNlCount(1);
+ chunk.CopyAndAddBefore(current);
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline before '%s'\n",
+ __func__, __LINE__, current->GetOrigLine(), current->GetOrigCol(), 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, orig col is %zu, a new line may NOT be added\n",
+ __func__, __LINE__, br_open->GetOrigLine(), br_open->GetOrigCol());
+ 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->GetType() [%s], br_open->GetParentType() [%s]\n",
+ __func__, __LINE__, br_open->Text(), get_token_name(br_open->GetType()),
+ get_token_name(br_open->GetParentType()));
+
+ if (br_open->GetParentType() == CT_ASSIGN)
+ {
+ // Only mess with it if the open brace is followed by a newline
+ if (next->IsNewline())
+ {
+ Chunk *prev = br_open->GetPrevNcNnlNi(); // Issue #2279
+ log_rule_B("nl_assign_brace");
+ newline_iarf_pair(prev, br_open, options::nl_assign_brace());
+ }
+ }
+
+ if ( br_open->GetParentType() == CT_OC_MSG_DECL
+ || br_open->GetParentType() == CT_FUNC_DEF
+ || br_open->GetParentType() == CT_FUNC_CLASS_DEF
+ || br_open->GetParentType() == CT_OC_CLASS
+ || br_open->GetParentType() == CT_CS_PROPERTY
+ || br_open->GetParentType() == CT_CPP_LAMBDA
+ || br_open->GetParentType() == CT_FUNC_CALL
+ || br_open->GetParentType() == CT_FUNC_CALL_USER)
+ {
+ Chunk *prev = Chunk::NullChunkPtr;
+ iarf_e val;
+
+ if (br_open->GetParentType() == CT_OC_MSG_DECL)
+ {
+ log_rule_B("nl_oc_mdef_brace");
+ val = options::nl_oc_mdef_brace();
+ }
+ else
+ {
+ if ( br_open->GetParentType() == CT_FUNC_DEF
+ || br_open->GetParentType() == CT_FUNC_CLASS_DEF
+ || br_open->GetParentType() == 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 (prev->Is(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 = ((br_open->GetParentType() == CT_CS_PROPERTY) ?
+ options::nl_property_brace() :
+ ((br_open->GetParentType() == 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 (br_open->GetNextNnl()->Is(CT_BRACE_CLOSE))
+ {
+ // Chunk is "{" and "}" with only whitespace/newlines in between
+
+ if (br_open->GetParentType() == CT_FUNC_DEF)
+ {
+ // Braces belong to a function definition
+ log_rule_B("nl_collapse_empty_body_functions");
+
+ if (options::nl_collapse_empty_body_functions())
+ {
+ collapse_empty_body(br_open);
+ return;
+ }
+ }
+ else
+ {
+ log_rule_B("nl_collapse_empty_body");
+
+ if (options::nl_collapse_empty_body())
+ {
+ collapse_empty_body(br_open);
+ return;
+ }
+ }
+ }
+ //fixes #1245 will add new line between tsquare and brace open based on nl_tsquare_brace
+
+ if (br_open->Is(CT_BRACE_OPEN))
+ {
+ Chunk *chunk_closing_brace = br_open->GetClosingParen();
+
+ if (chunk_closing_brace->IsNotNullChunk())
+ {
+ if (chunk_closing_brace->GetOrigLine() > br_open->GetOrigLine())
+ {
+ Chunk *prev = br_open->GetPrevNc();
+
+ if ( prev->Is(CT_TSQUARE)
+ && next->IsNewline())
+ {
+ 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 (next->IsNewline())
+ {
+ log_rule_B("nl_inside_empty_func");
+ log_rule_B("nl_inside_namespace");
+
+ if ( options::nl_inside_empty_func() > 0
+ && br_open->GetNextNnl()->Is(CT_BRACE_CLOSE)
+ && ( br_open->GetParentType() == CT_FUNC_CLASS_DEF
+ || br_open->GetParentType() == CT_FUNC_DEF))
+ {
+ blank_line_set(next, options::nl_inside_empty_func);
+ }
+ else if ( options::nl_inside_namespace() > 0
+ && br_open->GetParentType() == CT_NAMESPACE)
+ {
+ blank_line_set(next, options::nl_inside_namespace);
+ }
+ else if (next->GetNlCount() > 1)
+ {
+ next->SetNlCount(1);
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_after_open_brace %zu\n",
+ __func__, __LINE__, next->GetOrigLine());
+ MARK_CHANGE();
+ }
+ }
+ }
+ bool nl_close_brace = false;
+
+ // Handle the cases where the brace is part of a function call or definition
+ if (is_func_call_or_def(br_open))
+ {
+ // Need to force a newline before the close brace, if not in a class body
+ if (!br_open->TestFlags(PCF_IN_CLASS))
+ {
+ nl_close_brace = true;
+ }
+ // handle newlines after the open brace
+ Chunk *pc = br_open->GetNextNcNnl();
+ newline_add_between(br_open, pc);
+ }
+ // Grab the matching brace close
+ Chunk *br_close = br_open->GetNextType(CT_BRACE_CLOSE, br_open->GetLevel());
+
+ 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 (pc->Is(CT_COMMENT))
+ {
+ pc = pc->GetNext();
+ }
+
+ if (pc->IsCommentOrNewline())
+ {
+ 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->GetType()],
+ // start->GetOrigLine(), start->GetOrigCol());
+
+ // Scan backwards until a '{' or ';' or ':'. Abort if a multi-newline is found
+ Chunk *prev = start;
+
+ do
+ {
+ prev = prev->GetPrevNc();
+
+ if ( prev->IsNotNullChunk()
+ && prev->IsNewline()
+ && prev->GetNlCount() > 1)
+ {
+ return;
+ }
+ } while ( prev->IsNot(CT_BRACE_OPEN)
+ && prev->IsNot(CT_BRACE_CLOSE)
+ && prev->IsNot(CT_SEMICOLON)
+ && prev->IsNot(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 ( prev->Is(CT_SEMICOLON)
+ || prev->Is(CT_BRACE_CLOSE))
+ {
+ if ( pc->IsNewline()
+ && pc->GetNlCount() < 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()
+ && !pc->IsNewline())
+ {
+ 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 (pc->IsNewline())
+ {
+ // Do we already have a blank line?
+ if (nl->GetNlCount() > 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()
+ && pc->GetParentType() != CT_COMMENT_END)
+ {
+ pc = pc->GetPrev();
+
+ if (!pc->IsNewline())
+ {
+ return;
+ }
+ nl = pc;
+ pc = pc->GetPrev();
+ }
+ pc = nl->GetPrev();
+
+ // Peek over trailing comment of previous token
+ if ( pc->IsComment()
+ && pc->GetParentType() == CT_COMMENT_END)
+ {
+ pc = pc->GetPrev();
+ }
+
+ // Don't add extra blanks after an opening brace or a case statement
+ if ( pc->IsNullChunk()
+ || ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_VBRACE_OPEN)
+ || pc->Is(CT_CASE_COLON)))
+ {
+ return;
+ }
+
+ if ( nl->IsNewline()
+ && nl->GetNlCount() < 2)
+ {
+ nl->SetNlCount(nl->GetNlCount() + 1);
+ MARK_CHANGE();
+ LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', new line count is now %zu\n",
+ __func__, __LINE__, nl->GetOrigLine(), nl->GetOrigCol(), nl->Text(), nl->GetNlCount());
+ }
+} // newline_before_return
+
+
+static void newline_after_return(Chunk *start)
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *semi = start->GetNextType(CT_SEMICOLON, start->GetLevel());
+ Chunk *after = semi->GetNextNcNnlNet();
+
+ // If we hit a brace or an 'else', then a newline isn't needed
+ if ( after->IsNullChunk()
+ || after->IsBraceClose()
+ || after->Is(CT_ELSE))
+ {
+ return;
+ }
+ Chunk *pc;
+
+ for (pc = semi->GetNext(); pc != after; pc = pc->GetNext())
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ if (pc->GetNlCount() < 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
+ || after->Is(CT_IGNORED))
+ {
+ return;
+ }
+
+ if (av & IARF_ADD)
+ {
+ if ( check_nl_assign_leave_one_liners
+ && options::nl_assign_leave_one_liners()
+ && after->TestFlags(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->GetNlCount() > 1)
+ {
+ nl->SetNlCount(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 ( (pc != nullptr && pc->Is(CT_FPAREN_OPEN)) // Issue #2914
+ && pc->GetParentType() == CT_FUNC_CALL
+ && after->Is(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->GetOrigLine(), start->GetOrigCol(),
+ start->Text(), get_token_name(start->GetType()), get_token_name(start->GetParentType()));
+
+ bool add_start;
+ bool add_args;
+ bool add_end;
+
+ if ( start->GetParentType() == CT_FUNC_DEF
+ || start->GetParentType() == 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 ( start->GetParentType() == CT_FUNC_CALL
+ || start->GetParentType() == 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->GetLevel() > start->GetLevel())
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ if ( pc->Is(CT_FPAREN_CLOSE)
+ && start->IsNewlineBetween(pc))
+ {
+ Chunk *start_next = start->GetNextNcNnl();
+ bool has_leading_closure = ( start_next->GetParentType() == CT_OC_BLOCK_EXPR
+ || start_next->GetParentType() == CT_CPP_LAMBDA
+ || start_next->Is(CT_BRACE_OPEN));
+
+ Chunk *prev_end = pc->GetPrevNcNnl();
+ bool has_trailing_closure = ( prev_end->GetParentType() == CT_OC_BLOCK_EXPR
+ || prev_end->GetParentType() == CT_CPP_LAMBDA
+ || prev_end->Is(CT_BRACE_OPEN));
+
+ if ( add_start
+ && !start->GetNext()->IsNewline())
+ {
+ 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
+ && !pc->GetPrev()->IsNewline())
+ {
+ 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->GetLevel() > start->GetLevel();
+ pc = pc->GetNextNcNnl())
+ {
+ if ( pc->Is(CT_COMMA)
+ && (pc->GetLevel() == (start->GetLevel() + 1)))
+ {
+ Chunk *tmp = pc->GetNext();
+
+ if (tmp->IsComment())
+ {
+ pc = tmp;
+ }
+
+ if (!pc->GetNext()->IsNewline())
+ {
+ 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->GetParentType() == CT_OC_BLOCK_EXPR
+ || prev_comma->GetParentType() == CT_CPP_LAMBDA
+ || prev_comma->Is(CT_BRACE_OPEN))
+ || ( after_comma->GetParentType() == CT_OC_BLOCK_EXPR
+ || after_comma->GetParentType() == CT_CPP_LAMBDA
+ || after_comma->Is(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->GetOrigLine(), start->GetOrigCol(),
+ start->Text(), get_token_name(start->GetType()), get_token_name(start->GetParentType()));
+
+ 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->GetLevel() > start->GetLevel())
+ {
+ pc = pc->GetNextNcNnl();
+ }
+
+ if (pc->Is(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->GetLevel() > start->GetLevel();
+ pc_1 = pc_1->GetNextNcNnl())
+ {
+ if ( pc_1->Is(CT_COMMA)
+ && (pc_1->GetLevel() == (start->GetLevel() + 1)))
+ {
+ Chunk *tmp = pc_1->GetNext();
+
+ if (tmp->IsComment())
+ {
+ pc_1 = tmp;
+ }
+
+ if (!pc_1->GetNext()->IsNewline())
+ {
+ 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->GetOrigLine(), start->GetOrigCol(),
+ get_token_name(start->GetType()), get_token_name(start->GetParentType()));
+
+ bool is_def = (start->GetParentType() == CT_FUNC_DEF)
+ || start->GetParentType() == CT_FUNC_CLASS_DEF;
+ bool is_call = (start->GetParentType() == CT_FUNC_CALL)
+ || start->GetParentType() == 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 (pc->IsString(")"))
+ {
+ 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 = prev->IsParenClose() ? Chunk::NullChunkPtr : prev->GetPrevNcNnlNi(); // Issue #2279
+
+ log_rule_B("nl_func_class_scope");
+
+ if ( prev->Is(CT_DC_MEMBER)
+ && (options::nl_func_class_scope() != IARF_IGNORE))
+ {
+ newline_iarf(prev->GetPrevNcNnlNi(), options::nl_func_class_scope()); // Issue #2279
+ }
+
+ if (prev->IsNot(CT_ACCESS_COLON))
+ {
+ Chunk *tmp;
+
+ if (prev->Is(CT_OPERATOR))
+ {
+ tmp = prev;
+ prev = prev->GetPrevNcNnlNi(); // Issue #2279
+ }
+ else
+ {
+ tmp = start;
+ }
+
+ if (prev->Is(CT_DC_MEMBER))
+ {
+ log_rule_B("nl_func_scope_name");
+
+ if ( options::nl_func_scope_name() != IARF_IGNORE
+ && !start->TestFlags(PCF_IN_DECLTYPE))
+ {
+ newline_iarf(prev, options::nl_func_scope_name());
+ }
+ }
+ const Chunk *tmp_next = prev->GetNextNcNnl();
+
+ if (tmp_next->IsNot(CT_FUNC_CLASS_DEF))
+ {
+ Chunk *closing = tmp->GetClosingParen();
+ Chunk *brace = closing->GetNextNcNnl();
+ iarf_e a; // Issue #2561
+
+ if ( tmp->GetParentType() == CT_FUNC_PROTO
+ || tmp->GetParentType() == 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->TestFlags(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->TestFlags(PCF_IN_CLASS)
+ && (options::nl_func_type_name_class() != IARF_IGNORE))
+ {
+ a = options::nl_func_type_name_class();
+ }
+
+ if ( (a != IARF_IGNORE)
+ && prev->IsNotNullChunk())
+ {
+ LOG_FMT(LNFD, "%s(%d): prev->Text() '%s', orig line is %zu, orig col is %zu, [%s/%s]\n",
+ __func__, __LINE__, prev->Text(), prev->GetOrigLine(), prev->GetOrigCol(),
+ get_token_name(prev->GetType()),
+ get_token_name(prev->GetParentType()));
+
+ if (prev->Is(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 (prev->Is(CT_DC_MEMBER))
+ {
+ prev = prev->GetPrevNcNnlNi(); // Issue #2279
+ prev = skip_template_prev(prev);
+ prev = prev->GetPrevNcNnlNi(); // Issue #2279
+ }
+
+ if ( !prev->IsBraceClose()
+ && prev->IsNot(CT_BRACE_OPEN)
+ && prev->IsNot(CT_SEMICOLON)
+ && prev->IsNot(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
+ && (tmp_next->IsNot(CT_OPERATOR) ? true : prev->IsTypeDefinition()))
+ {
+ newline_iarf(prev, a);
+ }
+ }
+ }
+ }
+ Chunk *pc = start->GetNextNcNnl();
+
+ if (pc->IsString(")"))
+ {
+ 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->GetLevel() > start->GetLevel();
+ pc = pc->GetNextNcNnl())
+ {
+ if ( pc->Is(CT_COMMA)
+ && (pc->GetLevel() == (start->GetLevel() + 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 // start->GetParentType() == 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 (pc->Is(CT_FPAREN_CLOSE))
+ {
+ Chunk *prev = pc->GetPrevNnl();
+
+ if ( prev->IsNot(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 = start->GetClosingParen();
+
+ if (sq_c->IsNullChunk())
+ {
+ return;
+ }
+ log_rule_B("nl_oc_msg_leave_one_liner");
+
+ if (options::nl_oc_msg_leave_one_liner())
+ {
+ return;
+ }
+ bool should_nl_msg = false;
+
+ // Get count of parameters
+ size_t parameter_count = 0;
+
+ for (Chunk *pc = start->GetNextNcNnl(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (pc->GetLevel() <= start->GetLevel())
+ {
+ break;
+ }
+
+ if (pc->Is(CT_OC_COLON) && pc->GetLevel() - 1 == start->GetLevel())
+ {
+ parameter_count++;
+ }
+ }
+
+ size_t min_params = options::nl_oc_msg_args_min_params();
+
+ if ( parameter_count >= min_params
+ && min_params != 0)
+ {
+ should_nl_msg = true;
+ }
+ // Get length of longest line
+ size_t longest_line = 0;
+
+ for (Chunk *pc = start->GetNextNcNnl(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (pc->GetLevel() <= start->GetLevel())
+ {
+ break;
+ }
+
+ if (pc->GetOrigColEnd() > longest_line)
+ {
+ longest_line = pc->GetOrigColEnd();
+ }
+ }
+
+ size_t max_code_width = options::nl_oc_msg_args_max_code_width();
+
+ if ( longest_line > max_code_width
+ && max_code_width != 0)
+ {
+ should_nl_msg = true;
+ }
+
+ // If both nl_oc_msg_args_min_params and nl_oc_msg_args_max_code_width are disabled
+ // we should newline all messages.
+ if ( max_code_width == 0
+ && min_params == 0)
+ {
+ should_nl_msg = true;
+ }
+
+ if (!should_nl_msg)
+ {
+ return;
+ }
+
+ for (Chunk *pc = start->GetNextNcNnl(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (pc->GetLevel() <= start->GetLevel())
+ {
+ break;
+ }
+
+ if (pc->Is(CT_OC_MSG_NAME) && pc->GetLevel() - 1 == start->GetLevel())
+ {
+ 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->GetType()), get_token_name(pc->GetParentType()),
+ pcf_flags_str(pc->GetFlags()).c_str(), pc->GetOrigLine(), pc->GetOrigCol());
+
+ if (!pc->TestFlags(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 (br_open->IsBraceClose())
+ {
+ br_open = br_open->GetPrevType(br_open->Is(CT_BRACE_CLOSE) ? CT_BRACE_OPEN : CT_VBRACE_OPEN,
+ br_open->GetLevel(), E_Scope::ALL);
+ }
+ else
+ {
+ while ( br_open->IsNotNullChunk()
+ && br_open->TestFlags(PCF_ONE_LINER)
+ && !br_open->IsBraceOpen()
+ && !br_open->IsBraceClose())
+ {
+ br_open = br_open->GetPrev();
+ }
+ }
+ pc = br_open;
+
+ if ( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_ONE_LINER)
+ && ( pc->IsBraceOpen()
+ || pc->IsBraceClose()))
+ {
+ log_rule_B("nl_class_leave_one_liners");
+
+ if ( options::nl_class_leave_one_liners()
+ && pc->TestFlags(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()
+ && pc->GetParentType() == 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()
+ && pc->GetParentType() == 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()
+ && pc->GetParentType() == 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()
+ && pc->GetParentType() == 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()
+ && ( pc->GetParentType() == CT_FUNC_DEF
+ || pc->GetParentType() == 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()
+ && pc->GetParentType() == 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()
+ && ((pc->GetParentType() == 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->TestFlags(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()
+ && ( pc->GetParentType() == CT_IF
+ || pc->GetParentType() == CT_ELSEIF
+ || pc->GetParentType() == 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()
+ && pc->GetParentType() == 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()
+ && pc->GetParentType() == 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()
+ && pc->GetParentType() == 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()
+ && pc->GetParentType() == 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->TestFlags(PCF_ONE_LINER))
+ {
+ LOG_FMT(LNL1LINE, "%s(%d): pc->Text() '%s', orig line is %zu, orig col is %zu",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+ pc->ResetFlagBits(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->TestFlags(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->GetOrigLine(), tmp->GetOrigCol());
+ break;
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): clear for tmp->Text() '%s', orig line is %zu, orig col is %zu",
+ __func__, __LINE__, tmp->Text(), tmp->GetOrigLine(), tmp->GetOrigCol());
+ tmp->ResetFlagBits(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->TestFlags(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->GetOrigLine(), tmp->GetOrigCol());
+ break;
+ }
+ LOG_FMT(LNL1LINE, "%s(%d): clear for tmp->Text() '%s', orig line is %zu, orig col is %zu",
+ __func__, __LINE__, tmp->Text(), tmp->GetOrigLine(), tmp->GetOrigCol());
+ tmp->ResetFlagBits(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->GetType()) != pattern_class_e::NONE)
+ {
+ return;
+ }
+ size_t nl_total = 0;
+
+ while (tmp->IsNot(CT_VBRACE_CLOSE))
+ {
+ if (tmp->IsNewline())
+ {
+ nl_total += tmp->GetNlCount();
+
+ if (nl_total > 1)
+ {
+ return;
+ }
+ }
+ tmp = tmp->GetNext();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && first->IsNotNullChunk())
+ {
+ 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->GetLevel());
+ Chunk *tmp = brace_open;
+
+ do
+ {
+ if (tmp->Is(CT_COMMA))
+ {
+ return;
+ }
+ tmp = tmp->GetNext();
+ } while (tmp != closing);
+
+ newline_del_between(brace_open, closing);
+} // nl_create_list_liner
+
+
+void newlines_remove_newlines()
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LBLANK, "%s(%d):\n", __func__, __LINE__);
+ Chunk *pc = Chunk::GetHead();
+
+ if (!pc->IsNewline())
+ {
+ pc = pc->GetNextNl();
+ }
+ Chunk *next;
+ Chunk *prev;
+
+ while (pc->IsNotNullChunk())
+ {
+ // Remove all newlines not in preproc
+ if (!pc->TestFlags(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()
+ && !prev->GetNext()->IsNewline())
+ {
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount());
+
+ next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && !next->Is(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->GetOrigLine(), pc->GetOrigCol());
+
+ if (pc->GetNlCount() != 1)
+ {
+ pc->SetNlCount(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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy));
+
+ if (pc->Is(CT_ANGLE_OPEN))
+ {
+ newline_template(pc);
+ }
+ }
+} // newlines_cleanup_angles
+
+
+void newlines_cleanup_braces(bool first)
+{
+ LOG_FUNC_ENTRY();
+ dump_step(dump_file_name, "new 2");
+
+ // Get the first token that's not an empty line:
+ Chunk *pc = Chunk::GetHead();
+
+ if (pc->IsNewline())
+ {
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy));
+
+ if ( pc->Is(CT_IF)
+ || pc->Is(CT_CONSTEXPR))
+ {
+ log_rule_B("nl_if_brace");
+ newlines_if_for_while_switch(pc, options::nl_if_brace());
+ }
+ else if (pc->Is(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 (pc->Is(CT_FOR))
+ {
+ log_rule_B("nl_for_brace");
+ newlines_if_for_while_switch(pc, options::nl_for_brace());
+ }
+ else if (pc->Is(CT_CATCH))
+ {
+ log_rule_B("nl_oc_brace_catch");
+
+ if ( language_is_set(LANG_OC)
+ && (pc->GetStr()[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 (next->Is(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 (pc->Is(CT_WHILE))
+ {
+ log_rule_B("nl_while_brace");
+ newlines_if_for_while_switch(pc, options::nl_while_brace());
+ }
+ else if (pc->Is(CT_USING_STMT))
+ {
+ log_rule_B("nl_using_brace");
+ newlines_if_for_while_switch(pc, options::nl_using_brace());
+ }
+ else if (pc->Is(CT_D_SCOPE_IF))
+ {
+ log_rule_B("nl_scope_brace");
+ newlines_if_for_while_switch(pc, options::nl_scope_brace());
+ }
+ else if (pc->Is(CT_UNITTEST))
+ {
+ log_rule_B("nl_unittest_brace");
+ newlines_do_else(pc, options::nl_unittest_brace());
+ }
+ else if (pc->Is(CT_D_VERSION_IF))
+ {
+ log_rule_B("nl_version_brace");
+ newlines_if_for_while_switch(pc, options::nl_version_brace());
+ }
+ else if (pc->Is(CT_SWITCH))
+ {
+ log_rule_B("nl_switch_brace");
+ newlines_if_for_while_switch(pc, options::nl_switch_brace());
+ }
+ else if (pc->Is(CT_SYNCHRONIZED))
+ {
+ log_rule_B("nl_synchronized_brace");
+ newlines_if_for_while_switch(pc, options::nl_synchronized_brace());
+ }
+ else if (pc->Is(CT_DO))
+ {
+ log_rule_B("nl_do_brace");
+ newlines_do_else(pc, options::nl_do_brace());
+ }
+ else if (pc->Is(CT_ELSE))
+ {
+ log_rule_B("nl_brace_else");
+ newlines_cuddle_uncuddle(pc, options::nl_brace_else());
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->Is(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 (pc->Is(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->GetType(), CT_NONE, false);
+ }
+ else if (pc->Is(CT_GETSET))
+ {
+ log_rule_B("nl_getset_brace");
+ newlines_do_else(pc, options::nl_getset_brace());
+ }
+ else if (pc->Is(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 (pc->Is(CT_WHILE_OF_DO))
+ {
+ log_rule_B("nl_brace_while");
+ newlines_cuddle_uncuddle(pc, options::nl_brace_while());
+ }
+ else if (pc->Is(CT_BRACE_OPEN))
+ {
+ switch (pc->GetParentType())
+ {
+ 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 (prev->IsParenClose())
+ {
+ 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->GetLevel() == pc->GetBraceLevel())
+ {
+ log_rule_B("nl_class_brace");
+ log_ruleNL("nl_class_brace", pc->GetPrevNnl());
+ newlines_do_else(pc->GetPrevNnl(), options::nl_class_brace());
+ }
+ break;
+ }
+
+ case CT_OC_CLASS:
+ {
+ if (pc->GetLevel() == pc->GetBraceLevel())
+ {
+ // 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->GetOrigLine(), tmp->GetOrigCol(), tmp->Text());
+
+ if ( tmp->Is(CT_OC_INTF)
+ || tmp->Is(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->GetOrigLine(), pc->GetOrigCol());
+
+ if (tmp->Is(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->GetType() == CT_TYPE
+ || prev->GetType() == CT_WORD
+ || prev->GetType() == CT_ASSIGN // Issue #2957
+ || prev->GetParentType() == CT_TEMPLATE
+ || prev->GetParentType() == 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 (next->Is(CT_BRACE_OPEN))
+ {
+ newline_iarf_pair(pc, next, options::nl_brace_brace());
+ }
+ }
+ Chunk *next = pc->GetNextNnl();
+
+ if (next->IsNullChunk())
+ {
+ // do nothing
+ }
+ else if (next->Is(CT_BRACE_CLOSE))
+ {
+ // TODO: add an option to split open empty statements? { };
+ }
+ else if (next->Is(CT_BRACE_OPEN))
+ {
+ // already handled
+ }
+ else
+ {
+ next = pc->GetNextNcNnl();
+
+ // Handle unnamed temporary direct-list-initialization
+ if (pc->GetParentType() == 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 ( ( pc->GetParentType() == CT_CPP_LAMBDA
+ || pc->GetLevel() == pc->GetBraceLevel())
+ && 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->TestFlags(PCF_IN_PREPROC)
+ || ( pc->TestFlags(PCF_ONE_LINER)
+ && pc->TestFlags(PCF_IN_ARRAY_ASSIGN)
+ && options::nl_assign_leave_one_liners()))
+ {
+ // no change - don't break up 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()
+ && tmp->IsNot(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 (!( pc->GetParentType() == 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 ( pc->Is(CT_BRACE_OPEN)
+ && pc->GetLevel() == pc->GetBraceLevel()
+ && 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->TestFlags(PCF_IN_PREPROC)
+ || pc->TestFlags(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 (!tmp->Is(CT_NEWLINE))
+ {
+ newline_iarf(tmp, IARF_ADD);
+ }
+ }
+ }
+ }
+ else if (pc->Is(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 (next->Is(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 (next->Is(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 ( next->Is(CT_NEWLINE)
+ && (options::nl_brace_fparen() == IARF_REMOVE))
+ {
+ next = next->GetNextNc(E_Scope::PREPROC); // Issue #1000
+ }
+
+ if (next->Is(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 ( pc->GetParentType() == 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 (prev->IsNewline())
+ {
+ log_rule_B("nl_inside_namespace");
+ log_rule_B("nl_inside_empty_func");
+
+ if ( options::nl_inside_empty_func() > 0
+ && pc->GetPrevNnl()->Is(CT_BRACE_OPEN)
+ && ( pc->GetParentType() == CT_FUNC_CLASS_DEF
+ || pc->GetParentType() == CT_FUNC_DEF))
+ {
+ blank_line_set(prev, options::nl_inside_empty_func);
+ }
+ else if ( options::nl_inside_namespace() > 0
+ && pc->GetParentType() == CT_NAMESPACE)
+ {
+ blank_line_set(prev, options::nl_inside_namespace);
+ }
+ else if (prev->GetNlCount() != 1)
+ {
+ prev->SetNlCount(1);
+ LOG_FMT(LBLANKD, "%s(%d): eat_blanks_before_close_brace %zu\n",
+ __func__, __LINE__, prev->GetOrigLine());
+ MARK_CHANGE();
+ }
+ }
+ }
+ else if ( options::nl_ds_struct_enum_close_brace()
+ && ( pc->GetParentType() == CT_ENUM
+ || pc->GetParentType() == CT_STRUCT
+ || pc->GetParentType() == CT_UNION))
+ {
+ log_rule_B("nl_ds_struct_enum_close_brace");
+
+ if (!pc->TestFlags(PCF_ONE_LINER))
+ {
+ // Make sure the brace is preceded by two newlines
+ Chunk *prev = pc->GetPrev();
+
+ if (!prev->IsNewline())
+ {
+ prev = newline_add_before(pc);
+ }
+
+ if (prev->GetNlCount() < 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)
+ && ( pc->GetParentType() == CT_STRUCT
+ || pc->GetParentType() == CT_ENUM
+ || pc->GetParentType() == CT_UNION))
+ {
+ Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ if ( next->IsNot(CT_SEMICOLON)
+ && next->IsNot(CT_COMMA))
+ {
+ log_rule_B("nl_brace_struct_var");
+ newline_iarf(pc, options::nl_brace_struct_var());
+ }
+ }
+ else if ( pc->GetParentType() != CT_OC_AT
+ && pc->GetParentType() != CT_BRACED_INIT_LIST
+ && ( options::nl_after_brace_close()
+ || pc->GetParentType() == CT_FUNC_CLASS_DEF
+ || pc->GetParentType() == CT_FUNC_DEF
+ || pc->GetParentType() == CT_OC_MSG_DECL))
+ {
+ log_rule_B("nl_after_brace_close");
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNot(CT_SEMICOLON)
+ && next->IsNot(CT_COMMA)
+ && next->IsNot(CT_SPAREN_CLOSE) // Issue #664
+ && next->IsNot(CT_SQUARE_CLOSE)
+ && next->IsNot(CT_FPAREN_CLOSE)
+ && next->IsNot(CT_PAREN_CLOSE)
+ && next->IsNot(CT_WHILE_OF_DO)
+ && next->IsNot(CT_VBRACE_CLOSE) // Issue #666
+ && ( next->IsNot(CT_BRACE_CLOSE)
+ || !next->TestFlags(PCF_ONE_LINER)) // #1258
+ && !pc->TestFlags(PCF_IN_ARRAY_ASSIGN)
+ && !pc->TestFlags(PCF_IN_TYPEDEF)
+ && !next->IsCommentOrNewline()
+ && next->IsNotNullChunk())
+ {
+ // #1258
+ // dont add newline between two consecutive braces closes, if the second is a part of one liner.
+ newline_end_newline(pc);
+ }
+ }
+ else if (pc->GetParentType() == 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 (pc->Is(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 (next->IsSemicolon())
+ {
+ 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()
+ && next->IsNot(CT_VBRACE_CLOSE)
+ && !next->IsCommentOrNewline());
+ }
+
+ 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 ( ( ( pc->GetParentType() == CT_IF
+ || pc->GetParentType() == CT_ELSEIF
+ || pc->GetParentType() == CT_ELSE)
+ && options::nl_create_if_one_liner())
+ || ( pc->GetParentType() == CT_FOR
+ && options::nl_create_for_one_liner())
+ || ( pc->GetParentType() == 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 ( ( ( pc->GetParentType() == CT_IF
+ || pc->GetParentType() == CT_ELSEIF
+ || pc->GetParentType() == CT_ELSE)
+ && options::nl_split_if_one_liner())
+ || ( pc->GetParentType() == CT_FOR
+ && options::nl_split_for_one_liner())
+ || ( pc->GetParentType() == CT_WHILE
+ && options::nl_split_while_one_liner()))
+ {
+ if (pc->TestFlags(PCF_ONE_LINER))
+ {
+ // split one-liner
+ Chunk *end = pc->GetNext()->GetNextType(CT_SEMICOLON)->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->GetType()), temp->GetLevel());
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, temp->GetFlags());
+ temp->ResetFlagBits(PCF_ONE_LINER);
+ }
+
+ // split
+ newline_add_between(pc, pc->GetNext());
+ }
+ }
+ }
+ else if (pc->Is(CT_VBRACE_CLOSE))
+ {
+ log_rule_B("nl_after_vbrace_close");
+
+ if (options::nl_after_vbrace_close())
+ {
+ if (!pc->GetNextNc()->IsNewline())
+ {
+ newline_iarf(pc, IARF_ADD);
+ }
+ }
+ }
+ else if ( pc->Is(CT_SQUARE_OPEN)
+ && pc->GetParentType() == CT_OC_MSG)
+ {
+ log_rule_B("nl_oc_msg_args");
+
+ if (options::nl_oc_msg_args())
+ {
+ newline_oc_msg(pc);
+ }
+ }
+ else if (pc->Is(CT_STRUCT))
+ {
+ log_rule_B("nl_struct_brace");
+ newlines_struct_union(pc, options::nl_struct_brace(), true);
+ }
+ else if (pc->Is(CT_UNION))
+ {
+ log_rule_B("nl_union_brace");
+ newlines_struct_union(pc, options::nl_union_brace(), true);
+ }
+ else if (pc->Is(CT_ENUM))
+ {
+ newlines_enum(pc);
+ }
+ else if (pc->Is(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 (pc->Is(CT_THROW))
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->Is(CT_PAREN_CLOSE)
+ || prev->Is(CT_FPAREN_CLOSE)) // Issue #1122
+ {
+ log_rule_B("nl_before_throw");
+ newline_iarf(pc->GetPrevNcNnlNi(), options::nl_before_throw()); // Issue #2279
+ }
+ }
+ else if ( pc->Is(CT_QUALIFIER)
+ && !strcmp(pc->Text(), "throws"))
+ {
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->Is(CT_PAREN_CLOSE)
+ || prev->Is(CT_FPAREN_CLOSE)) // Issue #1122
+ {
+ log_rule_B("nl_before_throw");
+ newline_iarf(pc->GetPrevNcNnlNi(), options::nl_before_throw()); // Issue #2279
+ }
+ }
+ else if (pc->Is(CT_CASE_COLON))
+ {
+ Chunk *next = pc->GetNextNnl();
+
+ log_rule_B("nl_case_colon_brace");
+
+ if ( next->Is(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 (pc->Is(CT_SPAREN_CLOSE))
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->Is(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 (pc->Is(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 (pc->Is(CT_SEMICOLON))
+ {
+ log_rule_B("nl_after_semicolon");
+ log_rule_NL("nl_after_semicolon");
+
+ if ( !pc->TestFlags(PCF_IN_SPAREN)
+ && !pc->TestFlags(PCF_IN_PREPROC)
+ && options::nl_after_semicolon())
+ {
+ Chunk *next = pc->GetNext();
+
+ while (next->Is(CT_VBRACE_CLOSE))
+ {
+ next = next->GetNext();
+ }
+
+ if ( next->IsNotNullChunk()
+ && !next->IsCommentOrNewline())
+ {
+ 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 (pc->GetParentType() == CT_CLASS)
+ {
+ log_rule_B("nl_after_class");
+
+ if (options::nl_after_class() > 0)
+ {
+ /*
+ * If there is already a "class" comment, then don't add a newline if
+ * one exists after the comment. or else this will interfere with the
+ * mod_add_long_class_closebrace_comment option.
+ */
+ iarf_e mode = IARF_ADD;
+ Chunk *next = pc->GetNext();
+
+ if (next->IsComment())
+ {
+ pc = next;
+ next = pc->GetNext();
+
+ if (next->IsNewline())
+ {
+ mode = IARF_IGNORE;
+ }
+ }
+ newline_iarf(pc, mode);
+ }
+ }
+ }
+ else if (pc->Is(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");
+
+ if ( ( pc->GetParentType() == CT_FUNC_DEF
+ || pc->GetParentType() == CT_FUNC_PROTO
+ || pc->GetParentType() == CT_FUNC_CLASS_DEF
+ || pc->GetParentType() == CT_FUNC_CLASS_PROTO
+ || pc->GetParentType() == 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))
+ {
+ newline_func_def_or_call(pc);
+ }
+ else if ( ( pc->GetParentType() == CT_FUNC_CALL
+ || pc->GetParentType() == 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_start() != IARF_IGNORE) // Issue #2020
+ || (options::nl_func_call_args() != IARF_IGNORE) // Issue #2604
+ || (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_start");
+ log_rule_B("nl_func_call_args");
+ 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_start() != IARF_IGNORE)
+ {
+ newline_iarf(pc, options::nl_func_call_start());
+ }
+ // note that newline_func_def_or_call() calls newline_func_multi_line()
+ newline_func_def_or_call(pc);
+ }
+ else if ( first
+ && (options::nl_remove_extra_newlines() == 1))
+ {
+ log_rule_B("nl_remove_extra_newlines");
+ newline_iarf(pc, IARF_REMOVE);
+ }
+ }
+ else if (pc->Is(CT_FPAREN_CLOSE)) // Issue #2758
+ {
+ if ( ( pc->GetParentType() == CT_FUNC_CALL
+ || pc->GetParentType() == CT_FUNC_CALL_USER)
+ && options::nl_func_call_end() != IARF_IGNORE)
+ {
+ log_rule_B("nl_func_call_end");
+ newline_iarf(pc->GetPrev(), options::nl_func_call_end());
+ }
+ }
+ else if (pc->Is(CT_ANGLE_CLOSE))
+ {
+ if (pc->GetParentType() == CT_TEMPLATE)
+ {
+ Chunk *next = pc->GetNextNcNnl();
+
+ if ( next->IsNotNullChunk()
+ && next->GetLevel() == next->GetBraceLevel())
+ {
+ Chunk *tmp = pc->GetPrevType(CT_ANGLE_OPEN, pc->GetLevel())->GetPrevNcNnlNi(); // Issue #2279
+
+ if (tmp->Is(CT_TEMPLATE))
+ {
+ if (next->Is(CT_USING))
+ {
+ newline_iarf(pc, options::nl_template_using());
+ log_rule_B("nl_template_using");
+ }
+ else if (next->GetParentType() == 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 (next->GetParentType() == 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 ( next->Is(CT_TYPE)
+ || next->Is(CT_QUALIFIER)) // variable
+ {
+ newline_iarf(pc, options::nl_template_var());
+ log_rule_B("nl_template_var");
+ }
+ else if (next->TestFlags(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 ( pc->Is(CT_NAMESPACE)
+ && pc->GetParentType() != CT_USING)
+ {
+ // Issue #2387
+ Chunk *next = pc->GetNextNcNnl();
+
+ if (next->IsNotNullChunk())
+ {
+ next = next->GetNextNcNnl();
+
+ if (!next->Is(CT_ASSIGN))
+ {
+ // Issue #1235
+ // Issue #2186
+ Chunk *braceOpen = pc->GetNextType(CT_BRACE_OPEN, pc->GetLevel());
+
+ 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->GetOrigLine(), pc->GetOrigCol());
+ exit(EXIT_FAILURE);
+ }
+ LOG_FMT(LNEWLINE, "%s(%d): braceOpen orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, braceOpen->GetOrigLine(), braceOpen->GetOrigCol(), braceOpen->Text());
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, braceOpen->GetFlags());
+ newlines_namespace(pc);
+ }
+ }
+ }
+ else if (pc->Is(CT_SQUARE_OPEN))
+ {
+ if ( pc->GetParentType() == CT_ASSIGN
+ && !pc->TestFlags(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 (tmp->IsNewline())
+ {
+ tmp = pc->GetNextType(CT_SQUARE_CLOSE, pc->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ newline_add_before(tmp);
+ }
+ }
+ }
+ }
+ else if (pc->Is(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 (!prev->IsNewline())
+ {
+ newline_add_before(pc);
+ }
+ }
+ }
+ else if (pc->Is(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 (!next->IsNewline())
+ {
+ newline_add_before(next);
+ }
+ }
+ }
+ else if (pc->Is(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->TestFlags(PCF_IN_PREPROC))
+ {
+ log_rule_B("nl_remove_extra_newlines");
+ log_rule_NL("nl_remove_extra_newlines");
+ newline_iarf(pc, IARF_REMOVE);
+ }
+ else if ( pc->Is(CT_MEMBER)
+ && ( language_is_set(LANG_JAVA)
+ || language_is_set(LANG_CPP))) // Issue #2574
+ {
+ // Issue #1124
+ if (pc->GetParentType() != 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_var_def_blk(Chunk::GetHead());
+} // 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 (nl->Is(CT_NEWLINE))
+ {
+ return;
+ }
+
+ if ( nl->Is(CT_MACRO)
+ || ( nl->Is(CT_FPAREN_CLOSE)
+ && nl->GetParentType() == CT_MACRO_FUNC))
+ {
+ ref = nl;
+ }
+
+ if (nl->Is(CT_NL_CONT))
+ {
+ if (ref->IsNotNullChunk())
+ {
+ newline_add_after(ref);
+ }
+ return;
+ }
+ }
+} // nl_handle_define
+
+
+void newline_after_multiline_comment()
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->IsNot(CT_COMMENT_MULTI))
+ {
+ continue;
+ }
+ Chunk *tmp = pc;
+
+ while ( ((tmp = tmp->GetNext())->IsNotNullChunk())
+ && !tmp->IsNewline())
+ {
+ if (!tmp->IsComment())
+ {
+ newline_add_before(tmp);
+ break;
+ }
+ }
+ }
+} // newline_after_multiline_comment
+
+
+void newline_after_label_colon()
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->IsNot(CT_LABEL_COLON))
+ {
+ continue;
+ }
+ newline_add_after(pc);
+ }
+} // newline_after_label_colon
+
+
+static bool is_class_one_liner(Chunk *pc)
+{
+ if ( ( pc->Is(CT_FUNC_CLASS_DEF)
+ || pc->Is(CT_FUNC_DEF))
+ && pc->TestFlags(PCF_IN_CLASS))
+ {
+ // Find opening brace
+ pc = pc->GetNextType(CT_BRACE_OPEN, pc->GetLevel());
+ return( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_ONE_LINER));
+ }
+ return(false);
+} // is_class_one_liner
+
+
+void newlines_insert_blank_lines()
+{
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ if (pc->Is(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 (pc->Is(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 (pc->Is(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 (pc->Is(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 (pc->Is(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 (pc->Is(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 (pc->Is(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 (pc->Is(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 (pc->Is(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 ( pc->Is(CT_FUNC_CLASS_DEF)
+ || pc->Is(CT_FUNC_DEF)
+ || pc->Is(CT_FUNC_CLASS_PROTO)
+ || pc->Is(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->GetType());
+ }
+ }
+ else
+ {
+ // ignore it
+ //LOG_FMT(LNEWLINE, "%s(%d): ignore it\n", __func__, __LINE__);
+ }
+ }
+} // newlines_insert_blank_lines
+
+
+void newlines_functions_remove_extra_blank_lines()
+{
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+
+ if ( pc->IsNot(CT_BRACE_OPEN)
+ || ( pc->GetParentType() != CT_FUNC_DEF
+ && pc->GetParentType() != CT_CPP_LAMBDA))
+ {
+ continue;
+ }
+ const size_t startMoveLevel = pc->GetLevel();
+
+ while (pc->IsNotNullChunk())
+ {
+ if ( pc->Is(CT_BRACE_CLOSE)
+ && pc->GetLevel() == startMoveLevel)
+ {
+ break;
+ }
+
+ // delete newlines
+ if ( !pc->Is(CT_COMMENT_MULTI) // Issue #2195
+ && pc->GetNlCount() > 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ pc->SetNlCount(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()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc;
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if ( pc->Is(CT_PREPROC)
+ && ( pc->GetLevel() > 0
+ || options::nl_squeeze_ifdef_top_level()))
+ {
+ log_rule_B("nl_squeeze_ifdef_top_level");
+ Chunk *ppr = pc->GetNext();
+
+ if ( ppr->Is(CT_PP_IF)
+ || ppr->Is(CT_PP_ELSE)
+ || ppr->Is(CT_PP_ENDIF))
+ {
+ Chunk *pnl = Chunk::NullChunkPtr;
+ Chunk *nnl = ppr->GetNextNl();
+
+ if ( ppr->Is(CT_PP_ELSE)
+ || ppr->Is(CT_PP_ENDIF))
+ {
+ pnl = pc->GetPrevNl();
+ }
+ Chunk *tmp1;
+ Chunk *tmp2;
+
+ if (nnl->IsNotNullChunk())
+ {
+ if (pnl->IsNotNullChunk())
+ {
+ if (pnl->GetNlCount() > 1)
+ {
+ pnl->SetNlCount(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->GetOrigLine(), tmp2->GetOrigLine());
+ }
+ }
+
+ if ( ppr->Is(CT_PP_IF)
+ || ppr->Is(CT_PP_ELSE))
+ {
+ if (nnl->GetNlCount() > 1)
+ {
+ tmp1 = nnl->GetPrevNnl();
+ LOG_FMT(LNEWLINE, "%s(%d): trimmed newlines after line %zu from %zu\n",
+ __func__, __LINE__, tmp1->GetOrigLine(), nnl->GetNlCount());
+ nnl->SetNlCount(1);
+ MARK_CHANGE();
+ }
+ }
+ }
+ }
+ }
+ }
+} // newlines_squeeze_ifdef
+
+
+void newlines_squeeze_paren_close()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc;
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ Chunk *next;
+ Chunk *prev;
+
+ if (pc->Is(CT_NEWLINE))
+ {
+ prev = pc->GetPrev();
+ }
+ else
+ {
+ prev = pc;
+ }
+ next = pc->GetNext();
+
+ if ( next->IsNotNullChunk()
+ && prev->IsNotNullChunk()
+ && next->IsParenClose()
+ && prev->IsParenClose())
+ {
+ Chunk *prev_op = prev->GetOpeningParen();
+ Chunk *next_op = next->GetOpeningParen();
+ bool flag = true;
+
+ Chunk *tmp = prev;
+
+ while (tmp->IsParenClose())
+ {
+ tmp = tmp->GetPrev();
+ }
+
+ if (tmp->IsNot(CT_NEWLINE))
+ {
+ flag = false;
+ }
+
+ if (flag)
+ {
+ if (next_op->IsOnSameLine(prev_op))
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ pc = next;
+ }
+ newline_del_between(prev, next);
+ }
+ else
+ {
+ newline_add_between(prev, next);
+ }
+ }
+ }
+ }
+} // newlines_squeeze_paren_close
+
+
+void newlines_eat_start_end()
+{
+ 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 (pc->Is(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->GetOrigLine());
+ Chunk::Delete(pc);
+ MARK_CHANGE();
+ }
+ else if ( options::nl_start_of_file() == IARF_FORCE
+ || (pc->GetNlCount() < 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->GetOrigLine());
+ pc->SetNlCount(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;
+ chunk.SetType(CT_NEWLINE);
+ chunk.SetOrigLine(pc->GetOrigLine());
+ chunk.SetOrigCol(pc->GetOrigCol());
+ chunk.SetPpLevel(pc->GetPpLevel());
+ chunk.SetNlCount(options::nl_start_of_file_min());
+ log_rule_B("nl_start_of_file_min");
+ chunk.CopyAndAddBefore(pc);
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline before '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), 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 (pc->Is(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->GetOrigLine());
+ Chunk::Delete(pc);
+ MARK_CHANGE();
+ }
+ else if ( options::nl_end_of_file() == IARF_FORCE
+ || (pc->GetNlCount() < options::nl_end_of_file_min()))
+ {
+ log_rule_B("nl_end_of_file");
+ log_rule_B("nl_end_of_file_min");
+
+ if (pc->GetNlCount() != 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->GetOrigLine());
+ pc->SetNlCount(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;
+ chunk.SetType(CT_NEWLINE);
+ chunk.SetOrigLine(pc->GetOrigLine());
+ chunk.SetOrigCol(pc->GetOrigCol());
+ chunk.SetPpLevel(pc->GetPpLevel());
+ chunk.SetNlCount(options::nl_end_of_file_min());
+ log_rule_B("nl_end_of_file_min");
+ chunk.CopyAndAddBefore(Chunk::NullChunkPtr);
+ LOG_FMT(LNEWLINE, "%s(%d): %zu:%zu add newline after '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), 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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy));
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, pc->GetFlags());
+
+ if (pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ // produces much more log output. Use it only debugging purpose
+ //log_pcf_flags(LNEWLINE, pc->GetFlags());
+
+ if (pc->TestFlags(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->TestFlags(PCF_IN_CLASS_BASE))
+ {
+ // change mode
+ log_rule_B("pos_class_comma");
+ mode_local = options::pos_class_comma();
+ }
+ else if (pc->TestFlags(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->GetOrigLine(), prev->GetOrigCol(), prev->Text());
+ LOG_FMT(LNEWLINE, "%s(%d): next orig line is %zu, orig col is %zu, Text() is '%s'\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text());
+ size_t nl_flag = ((prev->IsNewline() ? 1 : 0) |
+ (next->IsNewline() ? 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()
+ && !next2->Is(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 ( next2->Is(CT_PREPROC)
+ || ( chunk_type == CT_ASSIGN
+ && next2->Is(CT_BRACE_OPEN)))
+ {
+ continue;
+ }
+
+ if (next->GetNlCount() == 1)
+ {
+ if ( prev != nullptr
+ && !prev->TestFlags(PCF_IN_PREPROC))
+ {
+ // move the CT_BOOL to after the newline
+ pc->MoveAfter(next);
+ }
+ }
+ }
+ else
+ {
+ LOG_FMT(LNEWLINE, "%s(%d): prev orig line is %zu, orig col is %zu, Text() is '%s', new line count is %zu\n",
+ __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text(), prev->GetNlCount());
+
+ if (prev->GetNlCount() == 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->GetOrigLine(), prev->GetOrigCol(), prev->Text());
+
+ if ( prev->IsNotNullChunk()
+ && !prev->IsNewline()
+ && !prev->TestFlags(PCF_IN_PREPROC)
+ && !prev->TestFlags(PCF_IN_OC_MSG))
+ {
+ pc->MoveAfter(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
+ && pc->IsNot(tok))
+ {
+ continue;
+ }
+ Chunk *prev;
+ Chunk *next;
+
+ if (pc->Is(tok))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ ccolon = pc;
+ prev = pc->GetPrevNc();
+ next = pc->GetNextNc();
+
+ if (pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ Chunk *paren_vor_value = pc->GetNextType(CT_FPAREN_OPEN, pc->GetLevel());
+
+ 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->GetOrigLine(), paren_vor_value->GetOrigCol(),
+ paren_vor_value->Text(), get_token_name(paren_vor_value->GetType()));
+ constructorValue.NewLines(paren_vor_value->GetNlCount());
+ constructorValue.Add(paren_vor_value);
+ }
+ }
+
+ if ( !prev->IsNewline()
+ && !next->IsNewline()
+ && (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 ( prev->IsNewline()
+ && prev->SafeToDeleteNl())
+ {
+ Chunk::Delete(prev);
+ MARK_CHANGE();
+ prev = pc->GetPrevNc();
+ }
+
+ if ( next->IsNewline()
+ && next->SafeToDeleteNl())
+ {
+ Chunk::Delete(next);
+ MARK_CHANGE();
+ next = pc->GetNextNc();
+ }
+ }
+
+ if (tpc & TP_TRAIL) // pos_class_colon, pos_constr_colon: 4
+ {
+ if ( prev->IsNewline()
+ && prev->GetNlCount() == 1
+ && prev->SafeToDeleteNl())
+ {
+ pc->Swap(prev);
+ }
+ }
+ else if (tpc & TP_LEAD) // pos_class_colon, pos_constr_colon: 3
+ {
+ if ( next->IsNewline()
+ && next->GetNlCount() == 1
+ && next->SafeToDeleteNl())
+ {
+ pc->Swap(next);
+ }
+ }
+ }
+ else
+ {
+ // (pc->GetType() != tok)
+ if ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_SEMICOLON))
+ {
+ ccolon = nullptr;
+
+ if (with_acv)
+ {
+ constructorValue.End();
+ }
+ continue;
+ }
+
+ if ( pc->Is(CT_COMMA)
+ && pc->GetLevel() == ccolon->GetLevel())
+ {
+ LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ Chunk *paren_vor_value = pc->GetNextType(CT_FPAREN_OPEN, pc->GetLevel());
+
+ 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->GetOrigLine(), paren_vor_value->GetOrigCol(),
+ paren_vor_value->Text(), get_token_name(paren_vor_value->GetType()));
+ constructorValue.NewLines(paren_vor_value->GetNlCount());
+ 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 (after->IsNot(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 ( prev->IsNewline()
+ && prev->SafeToDeleteNl())
+ {
+ Chunk::Delete(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 ( next->IsNewline()
+ && next->SafeToDeleteNl())
+ {
+ Chunk::Delete(next);
+ MARK_CHANGE();
+ }
+ }
+ }
+ else if (ncia == IARF_REMOVE) // nl_class_init_args, nl_constr_init_args: 6
+ {
+ next = pc->GetNext();
+
+ if ( next->IsNewline()
+ && next->SafeToDeleteNl())
+ {
+ // comma is after
+ Chunk::Delete(next);
+ MARK_CHANGE();
+ }
+ else
+ {
+ prev = pc->GetPrev();
+
+ if ( prev->IsNewline()
+ && prev->SafeToDeleteNl())
+ {
+ // comma is before
+ Chunk::Delete(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->GetNlCount() > optval))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): do_blank_lines: %s max line %zu\n",
+ __func__, __LINE__, opt.name(), pc->GetOrigLine());
+ pc->SetNlCount(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 ( prev->Is(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()
+ && ( pc->Is(one_liner_type)
+ || pc->GetParentType() == one_liner_type)
+ && pc->TestFlags(PCF_IN_CLASS))
+ {
+ log_rule_B("nl_class_leave_one_liner_groups");
+
+ if (pc->Is(CT_BRACE_CLOSE))
+ {
+ return(pc->TestFlags(PCF_ONE_LINER));
+ }
+ else
+ {
+ // Find opening brace
+ pc = pc->GetNextType(CT_BRACE_OPEN, pc->GetLevel());
+ return( pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_ONE_LINER));
+ }
+ }
+ return(false);
+} // is_func_proto_group
+
+
+void do_blank_lines()
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LBLANKD, "%s(%d): orig line is %zu, orig col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount());
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()));
+ }
+ LOG_FMT(LBLANK, "%s(%d): new line count is %zu\n",
+ __func__, __LINE__, pc->GetNlCount());
+
+ if (pc->IsNot(CT_NEWLINE))
+ {
+ continue;
+ }
+ Chunk *prev = pc->GetPrevNc();
+
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LBLANK, "%s(%d): prev orig line is %zu, prev->Text() '%s', prev->GetType() is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(),
+ prev->Text(), get_token_name(prev->GetType()));
+
+ if (prev->Is(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->SetNlCount(pc->GetNlCount() + 1);
+ LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', new line count is now %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetNlCount());
+ }
+
+ // Limit consecutive newlines
+ if ( (options::nl_max() > 0)
+ && (pc->GetNlCount() > 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->GetOrigLine(), pc->GetOrigCol());
+
+ if (pc->GetNlCount() != 1)
+ {
+ pc->SetNlCount(1);
+ MARK_CHANGE();
+ }
+ continue;
+ }
+
+ // Control blanks before multi-line comments
+ if ( (options::nl_before_block_comment() > pc->GetNlCount())
+ && next->Is(CT_COMMENT_MULTI))
+ {
+ log_rule_B("nl_before_block_comment");
+
+ // Don't add blanks after an open brace or a case statement
+ if ( ( prev->IsNullChunk()
+ || ( prev->IsNot(CT_BRACE_OPEN)
+ && prev->IsNot(CT_VBRACE_OPEN)
+ && prev->IsNot(CT_CASE_COLON)))
+ && pcmt->IsNot(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->GetNlCount())
+ && next->Is(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->IsNullChunk()
+ || ( prev->IsNot(CT_BRACE_OPEN)
+ && prev->IsNot(CT_VBRACE_OPEN)
+ && prev->IsNot(CT_CASE_COLON)))
+ && pcmt->IsNot(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->GetNlCount())
+ && next->Is(CT_COMMENT_CPP))
+ {
+ log_rule_B("nl_before_cpp_comment");
+
+ // Don't add blanks after an open brace or a case statement
+ if ( ( prev->IsNullChunk()
+ || ( prev->IsNot(CT_BRACE_OPEN)
+ && prev->IsNot(CT_VBRACE_OPEN)
+ && prev->IsNot(CT_CASE_COLON)))
+ && pcmt->IsNot(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 ( ( prev->Is(CT_SEMICOLON)
+ || prev->Is(CT_BRACE_CLOSE))
+ && ( prev->GetParentType() == CT_CLASS
+ || prev->GetParentType() == CT_STRUCT))
+ {
+ E_Token parent_type = prev->GetParentType();
+ Chunk *start = prev->GetPrevType(parent_type, prev->GetLevel());
+ Chunk *tmp = start;
+
+ // Is this a class/struct template?
+ if (tmp->GetParentType() == CT_TEMPLATE)
+ {
+ tmp = tmp->GetPrevType(CT_TEMPLATE, prev->GetLevel());
+ tmp = tmp->GetPrevNc();
+ }
+ else
+ {
+ tmp = tmp->GetPrevNc();
+
+ while ( tmp->Is(CT_NEWLINE)
+ && tmp->GetPrev()->IsComment())
+ {
+ tmp = tmp->GetPrev()->GetPrevNc();
+ }
+
+ if (tmp->Is(CT_FRIEND))
+ {
+ // Account for a friend declaration
+ tmp = tmp->GetPrevNc();
+ }
+ }
+
+ while ( tmp->Is(CT_NEWLINE)
+ && tmp->GetPrev()->IsComment())
+ {
+ tmp = tmp->GetPrev()->GetPrevNc();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && !start->TestFlags(PCF_INCOMPLETE))
+ {
+ if (parent_type == CT_CLASS && options::nl_before_class() > tmp->GetNlCount())
+ {
+ 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->GetNlCount())
+ {
+ log_rule_B("nl_before_struct");
+ blank_line_set(tmp, options::nl_before_struct);
+ }
+ }
+ }
+
+ if ( prev->Is(CT_BRACE_CLOSE)
+ && prev->GetParentType() == CT_NAMESPACE)
+ {
+ // Control blanks before a namespace
+ Chunk *tmp = prev->GetPrevType(CT_NAMESPACE, prev->GetLevel());
+ tmp = tmp->GetPrevNc();
+
+ while ( tmp->Is(CT_NEWLINE)
+ && tmp->GetPrev()->IsComment())
+ {
+ tmp = tmp->GetPrev()->GetPrevNc();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && options::nl_before_namespace() > tmp->GetNlCount())
+ {
+ log_rule_B("nl_before_namespace");
+ blank_line_set(tmp, options::nl_before_namespace);
+ }
+
+ // Add blanks after namespace
+ if (options::nl_after_namespace() > pc->GetNlCount())
+ {
+ log_rule_B("nl_after_namespace");
+ blank_line_set(pc, options::nl_after_namespace);
+ }
+ }
+
+ // Control blanks inside empty function body
+ if ( prev->Is(CT_BRACE_OPEN)
+ && next->Is(CT_BRACE_CLOSE)
+ && ( prev->GetParentType() == CT_FUNC_DEF
+ || prev->GetParentType() == CT_FUNC_CLASS_DEF)
+ && options::nl_inside_empty_func() > pc->GetNlCount()
+ && prev->TestFlags(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->GetNlCount())
+ && prev->Is(CT_ACCESS_COLON))
+ {
+ log_rule_B("nl_after_access_spec");
+
+ // Don't add blanks before a closing brace
+ if ( next->IsNullChunk()
+ || !next->IsBraceClose())
+ {
+ log_rule_B("nl_after_access_spec");
+ blank_line_set(pc, options::nl_after_access_spec);
+ }
+ }
+
+ // Add blanks after function bodies
+ if ( prev->Is(CT_BRACE_CLOSE)
+ && ( prev->GetParentType() == CT_FUNC_DEF
+ || prev->GetParentType() == CT_FUNC_CLASS_DEF
+ || prev->GetParentType() == CT_OC_MSG_DECL
+ || prev->GetParentType() == CT_ASSIGN))
+ {
+ if (prev->TestFlags(PCF_ONE_LINER))
+ {
+ if (options::nl_after_func_body_one_liner() > pc->GetNlCount())
+ {
+ log_rule_B("nl_after_func_body_one_liner");
+ blank_line_set(pc, options::nl_after_func_body_one_liner);
+ }
+ }
+ else
+ {
+ if ( prev->TestFlags(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->GetNlCount())
+ {
+ log_rule_B("nl_after_func_body_class");
+ blank_line_set(pc, options::nl_after_func_body_class);
+ }
+ }
+ else
+ {
+ if (!(pc->GetPrev()->TestFlags(PCF_IN_TRY_BLOCK))) // Issue #1734
+ {
+ if (options::nl_after_func_body() > 0)
+ {
+ log_rule_B("nl_after_func_body");
+
+ if (options::nl_after_func_body() != pc->GetNlCount())
+ {
+ log_rule_B("nl_after_func_body");
+ blank_line_set(pc, options::nl_after_func_body);
+ }
+ }
+ else
+ {
+ if (options::nl_min_after_func_body() > 0) // Issue #2787
+ {
+ log_rule_B("nl_min_after_func_body");
+
+ if (options::nl_min_after_func_body() > pc->GetNlCount())
+ {
+ log_rule_B("nl_min_after_func_body");
+ blank_line_set(pc, options::nl_min_after_func_body);
+ }
+ }
+
+ if (options::nl_max_after_func_body() > 0)
+ {
+ log_rule_B("nl_max_after_func_body");
+
+ if (options::nl_max_after_func_body() < pc->GetNlCount())
+ {
+ log_rule_B("nl_max_after_func_body");
+ blank_line_set(pc, options::nl_max_after_func_body);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Add blanks after function prototypes
+ if ( ( prev->Is(CT_SEMICOLON)
+ && prev->GetParentType() == CT_FUNC_PROTO)
+ || is_func_proto_group(prev, CT_FUNC_DEF))
+ {
+ if (options::nl_after_func_proto() > pc->GetNlCount())
+ {
+ log_rule_B("nl_after_func_proto");
+ pc->SetNlCount(options::nl_after_func_proto());
+ MARK_CHANGE();
+ }
+
+ if ( (options::nl_after_func_proto_group() > pc->GetNlCount())
+ && next->IsNotNullChunk()
+ && next->GetParentType() != 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 ( ( prev->Is(CT_SEMICOLON)
+ && prev->GetParentType() == CT_FUNC_CLASS_PROTO)
+ || is_func_proto_group(prev, CT_FUNC_CLASS_DEF))
+ {
+ if (options::nl_after_func_class_proto() > pc->GetNlCount())
+ {
+ log_rule_B("nl_after_func_class_proto");
+ pc->SetNlCount(options::nl_after_func_class_proto());
+ MARK_CHANGE();
+ }
+
+ if ( (options::nl_after_func_class_proto_group() > pc->GetNlCount())
+ && next->IsNot(CT_FUNC_CLASS_PROTO)
+ && next->GetParentType() != 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 ( ( prev->Is(CT_SEMICOLON)
+ || prev->Is(CT_BRACE_CLOSE))
+ && ( prev->GetParentType() == CT_STRUCT
+ || prev->GetParentType() == CT_ENUM
+ || prev->GetParentType() == CT_UNION
+ || prev->GetParentType() == CT_CLASS))
+ {
+ auto &opt = (prev->GetParentType() == 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->GetNlCount())
+ {
+ // 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->GetLevel() > pc->GetLevel())
+ {
+ continue;
+ }
+ LOG_FMT(LBLANK, "%s(%d): %zu:%zu token is '%s'\n",
+ __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), tmp->Text());
+
+ if (tmp->TestFlags(PCF_VAR_DEF))
+ {
+ is_var_def = true;
+ break;
+ }
+
+ if (tmp->Is(prev->GetParentType()))
+ {
+ is_fwd_decl = tmp->TestFlags(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)
+ && pcmt->Is(CT_COMMENT_MULTI)
+ && pcmt->GetParentType() == CT_COMMENT_WHOLE
+ && next->IsNotNullChunk()
+ && ( next->GetParentType() == CT_FUNC_DEF
+ || next->GetParentType() == CT_FUNC_CLASS_DEF))
+ {
+ log_rule_B("nl_comment_func_def");
+
+ if (options::nl_comment_func_def() != pc->GetNlCount())
+ {
+ 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->GetNlCount())
+ && prev->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ log_rule_B("nl_after_try_catch_finally");
+
+ if ( prev->Is(CT_BRACE_CLOSE)
+ && ( prev->GetParentType() == CT_CATCH
+ || prev->GetParentType() == CT_FINALLY))
+ {
+ if ( next->IsNot(CT_BRACE_CLOSE)
+ && next->IsNot(CT_CATCH)
+ && next->IsNot(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->GetNlCount())
+ && prev->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ log_rule_B("nl_between_get_set");
+
+ if ( prev->GetParentType() == CT_GETSET
+ && next->IsNot(CT_BRACE_CLOSE)
+ && ( prev->Is(CT_BRACE_CLOSE)
+ || prev->Is(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->GetNlCount())
+ && prev->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ log_rule_B("nl_around_cs_property");
+
+ if ( prev->Is(CT_BRACE_CLOSE)
+ && prev->GetParentType() == CT_CS_PROPERTY
+ && next->IsNot(CT_BRACE_CLOSE))
+ {
+ blank_line_set(pc, options::nl_around_cs_property);
+ log_rule_B("nl_around_cs_property");
+ }
+ else if ( next->GetParentType() == CT_CS_PROPERTY
+ && next->TestFlags(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->GetNlCount())
+ && next->Is(CT_ACCESS))
+ {
+ log_rule_B("nl_before_access_spec");
+
+ // Don't add blanks after an open brace
+ if ( prev->IsNullChunk()
+ || ( prev->IsNot(CT_BRACE_OPEN)
+ && prev->IsNot(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->GetNlCount())
+ && ( ( prev->Is(CT_BRACE_OPEN)
+ && prev->GetParentType() == CT_NAMESPACE)
+ || ( next->Is(CT_BRACE_CLOSE)
+ && next->GetParentType() == 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->GetNlCount()
+ && next->Is(CT_PREPROC)
+ && next->GetParentType() == CT_PP_IF
+ && ifdef_over_whole_file()
+ && next->TestFlags(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->GetNlCount())
+ {
+ Chunk *pp_start = prev->GetPpStart();
+
+ if ( pp_start->IsNotNullChunk()
+ && pp_start->GetParentType() == CT_PP_IF
+ && ifdef_over_whole_file()
+ && pp_start->TestFlags(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->GetNlCount()
+ && next->Is(CT_PREPROC)
+ && next->GetParentType() == CT_PP_ENDIF
+ && ifdef_over_whole_file()
+ && next->TestFlags(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->GetNlCount())
+ {
+ Chunk *pp_start = prev->GetPpStart();
+
+ if ( pp_start->IsNotNullChunk()
+ && pp_start->GetParentType() == CT_PP_ENDIF
+ && ifdef_over_whole_file()
+ && pp_start->TestFlags(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->GetNlCount() > 1)
+ {
+ pc->SetNlCount(pc->GetNlCount() - 1);
+ LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', new line count is now %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetNlCount());
+ }
+ LOG_FMT(LBLANK, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', end new line count is now %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetNlCount());
+ }
+} // do_blank_lines
+
+
+void newlines_cleanup_dup()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+ Chunk *next = pc;
+
+ while (pc->IsNotNullChunk())
+ {
+ next = next->GetNext();
+
+ if ( pc->Is(CT_NEWLINE)
+ && next->Is(CT_NEWLINE))
+ {
+ next->SetNlCount(max(pc->GetNlCount(), next->GetNlCount()));
+ Chunk::Delete(pc);
+ MARK_CHANGE();
+ }
+ pc = next;
+ }
+} // newlines_cleanup_dup
+
+
+static void newlines_enum_entries(Chunk *open_brace, iarf_e av)
+{
+ LOG_FUNC_ENTRY();
+
+ for (Chunk *pc = open_brace->GetNextNc();
+ pc->IsNotNullChunk() && pc->GetLevel() > open_brace->GetLevel();
+ pc = pc->GetNextNc())
+ {
+ if ( (pc->GetLevel() != (open_brace->GetLevel() + 1))
+ || pc->IsNot(CT_COMMA)
+ || ( pc->Is(CT_COMMA)
+ && ( pc->GetNext()->GetType() == CT_COMMENT_CPP
+ || pc->GetNext()->GetType() == CT_COMMENT
+ || pc->GetNext()->GetType() == CT_COMMENT_MULTI)))
+ {
+ 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->GetLevel() > open_brace->GetLevel())
+ {
+ if ( pc->GetLevel() != (open_brace->GetLevel() + 1)
+ || pc->IsNot(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()
+ && prev->IsNot(CT_BRACE_OPEN)
+ && pc->GetNext()->IsComment())
+ {
+ if (pc->GetNlCount() < 2)
+ {
+ double_newline(pc);
+ }
+ }
+ }
+} // newlines_double_space_struct_enum_union
+
+
+void annotations_newlines()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *next;
+ Chunk *prev;
+ Chunk *ae; // last token of the annotation
+ Chunk *pc = Chunk::GetHead();
+
+ while ( (pc = pc->GetNextType(CT_ANNOTATION))->IsNotNullChunk()
+ && (next = pc->GetNextNnl())->IsNotNullChunk())
+ {
+ // find the end of this annotation
+ if (next->IsParenOpen())
+ {
+ // TODO: control newline between annotation and '(' ?
+ ae = next->GetClosingParen();
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(),
+ ae->GetOrigLine(), ae->GetOrigCol(), 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->GetOrigLine(), prev->GetOrigCol(), prev->Text());
+ next = ae->GetNextNnl();
+
+ if (next->Is(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 (next->Is(CT_NEWLINE))
+ {
+ if (next->Is(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->IsNullChunk()
+ || pc_end->IsNullChunk())
+ {
+ return(false);
+ }
+ newlines = 0;
+
+ Chunk *it = pc_start;
+
+ for ( ; it->IsNotNullChunk() && it != pc_end; it = it->GetNext(scope))
+ {
+ newlines += it->GetNlCount();
+ }
+
+ // 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.78.0/src/newlines.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/newlines.h
new file mode 100644
index 00000000..c9e15511
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/newlines.h
@@ -0,0 +1,206 @@
+/**
+ * @file newlines.h
+ * prototypes for newlines.cpp
+ *
+ * @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();
+
+
+/**
+ * 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();
+
+
+/**
+ * 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 newlines_squeeze_ifdef();
+
+/**
+ * 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();
+
+
+//! removes unnecessary newlines at start and end of a file
+void newlines_eat_start_end();
+
+
+/**
+ * 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 (options::pos_comma() == TRAIL) or after (options::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 annotations_newlines();
+
+
+void newline_after_multiline_comment();
+
+
+//! Handle insertion of blank lines after label colons
+void newline_after_label_colon();
+
+
+/**
+ * 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();
+
+
+/**
+ * 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 null chunks 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.78.0/src/option.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option.cpp
new file mode 100644
index 00000000..be09ac2f
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option.cpp
@@ -0,0 +1,1325 @@
+/**
+ * @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 "language_names.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 backslashes 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
+
+
+bool process_option_line_compat_0_75(const std::string &cmd, const char *filename)
+{
+ if (cmd == "pp_space")
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; it has been replaced by '%s'.",
+ cmd.c_str(), options::pp_space_after.name());
+
+ return(true);
+ }
+
+ if (cmd == "pp_space_before")
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; it was a temporary option used\n"
+ "during the development of version 0.76. Use '%s' and '%s' instead.",
+ cmd.c_str(), options::pp_indent.name(), options::pp_indent_count.name());
+
+ return(true);
+ }
+ return(false);
+} // process_option_line_compat_0_75
+
+
+bool process_option_line_compat_0_76(const std::string &cmd, const std::vector<std::string> &args, const char *filename)
+{
+ if (cmd == "nl_func_var_def_blk")
+ {
+ OptionWarning w{ filename, OptionWarning::MINOR };
+ w("option '%s' is deprecated; it has been replaced by '%s'.\n"
+ "You can also use '%s' for additional functionality",
+ cmd.c_str(), options::nl_var_def_blk_end_func_top.name(),
+ options::nl_var_def_blk_end.name());
+
+ UNUSED(options::nl_var_def_blk_end_func_top.read(args[1].c_str()));
+ return(true);
+ }
+ return(false);
+} // process_option_line_compat_0_76
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+//BEGIN Option<T> and helpers
+
+
+//-----------------------------------------------------------------------------
+OptionWarning::OptionWarning(const char *filename, Severity severity)
+{
+ UNUSED(severity);
+
+ 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)
+{
+ UNUSED(severity);
+
+ 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
+ UncText 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;
+ }
+ }
+
+ if (compat_level < option_level(0, 76))
+ {
+ if (process_option_line_compat_0_75(cmd, filename))
+ {
+ return;
+ }
+ }
+
+ if (compat_level < option_level(0, 77))
+ {
+ if (process_option_line_compat_0_76(cmd, args, 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);
+ exit(EX_SOFTWARE);
+ }
+ // 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);
+ exit(EX_SOFTWARE);
+ }
+ }
+
+ ++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.78.0/src/option.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option.h
new file mode 100644
index 00000000..7b961940
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+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.78.0/src/option_enum.cpp.in b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option_enum.cpp.in
new file mode 100644
index 00000000..aeb976b2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/option_enum.h.in b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/option_enum.h.in
new file mode 100644
index 00000000..e50a9281
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/options.cpp.in b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options.cpp.in
new file mode 100644
index 00000000..2ee14c8b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/options.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options.h
new file mode 100644
index 00000000..52dbebed
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options.h
@@ -0,0 +1,4436 @@
+/**
+ * @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> ){ ... }'
+// with an empty list.
+extern Option<iarf_e>
+sp_cpp_lambda_argument_list_empty;
+
+// 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 before pointer star '*' that is followed by a qualifier.
+// If set to ignore, sp_before_unnamed_ptr_star is used instead.
+extern Option<iarf_e>
+sp_before_qualifier_ptr_star;
+
+// Add or remove space before pointer star '*' that is followed by 'operator' keyword.
+// If set to ignore, sp_before_unnamed_ptr_star is used instead.
+extern Option<iarf_e>
+sp_before_operator_ptr_star;
+
+// Add or remove space before pointer star '*' that is followed by
+// a class scope (as in 'int *MyClass::method()') or namespace scope
+// (as in 'int *my_ns::func()').
+// If set to ignore, sp_before_unnamed_ptr_star is used instead.
+extern Option<iarf_e>
+sp_before_scope_ptr_star;
+
+// Add or remove space before pointer star '*' that is followed by '::',
+// as in 'int *::func()'.
+// If set to ignore, sp_before_unnamed_ptr_star is used instead.
+extern Option<iarf_e>
+sp_before_global_scope_ptr_star;
+
+// Add or remove space between a qualifier and a pointer star '*' that isn't
+// followed by a variable name, as in '(char const *)'. If set to ignore,
+// sp_before_ptr_star is used instead.
+extern Option<iarf_e>
+sp_qualifier_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 between pointer star '*' and reference '&', as in 'int *& a;'.
+extern Option<iarf_e>
+sp_between_ptr_ref;
+
+// 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. If set to ignore, sp_before_ptr_star is
+// used instead.
+extern Option<iarf_e>
+sp_before_ptr_star_func;
+
+// Add or remove space between a qualifier and a pointer star '*' followed by
+// the name of the function in a function prototype or definition, as in
+// 'char const *foo()`. If set to ignore, sp_before_ptr_star is used instead.
+extern Option<iarf_e>
+sp_qualifier_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 between a qualifier and a pointer star '*' in the
+// trailing return of a function prototype or function definition, as in
+// 'auto foo() -> char const *'.
+extern Option<iarf_e>
+sp_qualifier_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 '<>'.
+// if empty.
+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 '[]'.
+// if empty.
+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#, Vala) Add or remove space between ',' and ']' in multidimensional array type
+// like 'int[,,]'.
+extern Option<iarf_e>
+sp_after_mdatype_commas;
+
+// (C#, Vala) Add or remove space between '[' and ',' in multidimensional array type
+// like 'int[,,]'.
+extern Option<iarf_e>
+sp_before_mdatype_commas;
+
+// (C#, Vala) 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 '{}'.
+// if empty.
+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
+// if empty.
+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
+// if empty.
+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 user functor '(' and ')'.
+extern Option<iarf_e>
+sp_func_call_user_inside_rparen;
+
+// Add or remove space inside empty functor '()'.
+// Overrides sp_after_angle unless use_sp_after_angle_always is set to true.
+extern Option<iarf_e>
+sp_inside_rparens;
+
+// Add or remove space inside functor '(' and ')'.
+extern Option<iarf_e>
+sp_inside_rparen;
+
+// 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;
+
+// remove space after the '//' and the pvs command '-V1234',
+// only works with sp_cmt_cpp_start set to add or force.
+extern Option<bool>
+sp_cmt_cpp_pvs;
+
+// remove space after the '//' and the command 'lint',
+// only works with sp_cmt_cpp_start set to add or force.
+extern Option<bool>
+sp_cmt_cpp_lint;
+
+// 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 parentheses 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;
+
+// Add or remove space before a bit colon ':'.
+extern Option<iarf_e>
+sp_before_bit_colon;
+
+// Add or remove space after a bit colon ':'.
+extern Option<iarf_e>
+sp_after_bit_colon;
+
+// 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 the `if_true` branch
+// 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 '}' except for functions.
+// Use nl_collapse_empty_body_functions to specify how empty function braces
+// should be formatted.
+extern Option<bool>
+nl_collapse_empty_body;
+
+// Whether to collapse empty blocks between '{' and '}' for functions only.
+// If true, overrides nl_inside_empty_func.
+extern Option<bool>
+nl_collapse_empty_body_functions;
+
+// 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;
+
+// (OC) Minimum number of Objective-C message parameters before applying nl_oc_msg_args.
+extern BoundedOption<unsigned, 0, 16>
+nl_oc_msg_args_min_params;
+
+// (OC) Max code width of Objective-C message before applying nl_oc_msg_args.
+extern BoundedOption<unsigned, 0, 10000>
+nl_oc_msg_args_max_code_width;
+
+// 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;
+
+// Add or remove newline between 'throw' and the throw expression.
+extern Option<iarf_e>
+nl_throw_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_functions=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.
+//
+// Overrides nl_min_after_func_body and nl_max_after_func_body.
+extern BoundedOption<unsigned, 0, 16>
+nl_after_func_body;
+
+// The minimum number of newlines after '}' of a multi-line function body.
+//
+// Only works when nl_after_func_body is 0.
+extern BoundedOption<unsigned, 0, 16>
+nl_min_after_func_body;
+
+// The maximum number of newlines after '}' of a multi-line function body.
+//
+// Only works when nl_after_func_body is 0.
+// Takes precedence over nl_min_after_func_body.
+extern BoundedOption<unsigned, 0, 16>
+nl_max_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 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 minimum number of blank lines after a block of variable definitions
+// at the top of a function body. If any preprocessor directives appear
+// between the opening brace of the function and the variable block, then
+// it is considered as not at the top of the function.Newlines are added
+// before trailing preprocessor directives, if any exist.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_var_def_blk_end_func_top;
+
+// The minimum 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. Newlines are not added at the top of the
+// file or just after an opening brace. Newlines are added above any
+// preprocessor directives before the block.
+//
+// 0: No change (default).
+extern BoundedOption<unsigned, 0, 16>
+nl_var_def_blk_start;
+
+// The minimum number of empty newlines after a block of variable definitions
+// not at the top of a function body. Newlines are not added if the block
+// is at the bottom of the file or just before a preprocessor directive.
+//
+// 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 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 span for aligning on '{' in braced init list.
+//
+// 0: Don't align (default).
+extern BoundedOption<unsigned, 0, 5000>
+align_braced_init_list_span;
+
+// 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;
+
+// Whether to ignore continuation lines when evaluating the number of
+// new lines for the function prototype alignment's span.
+//
+// false: continuation lines are part of the newlines count
+// true: continuation lines are not counted
+extern Option<bool>
+align_func_proto_span_ignore_cont_lines; // = false
+
+// 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 and how to align backslashes that split a macro onto multiple lines.
+// This will not work right if the macro contains a multi-line comment.
+//
+// 0: Do nothing (default)
+// 1: Align the backslashes in the column at the end of the longest line
+// 2: Align with the backslash that is farthest to the left, or, if that
+// backslash is farther left than the end of the longest line, at the end of
+// the longest line
+// 3: Align with the backslash that is farthest to the right
+extern BoundedOption<unsigned, 0, 3>
+align_nl_cont;
+
+// The minimum number of spaces between the end of a line and its continuation
+// backslash. Requires align_nl_cont.
+extern BoundedOption<unsigned, 0, 16>
+align_nl_cont_spaces; // = 1
+
+// 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 parentheses on 'return' statement.
+extern Option<iarf_e>
+mod_paren_on_return;
+
+// Add or remove unnecessary parentheses on 'throw' statement.
+extern Option<iarf_e>
+mod_paren_on_throw;
+
+// (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;
+
+// the following options (mod_XX_closebrace_comment) use different comment,
+// depending of the setting of the next option.
+// false: Use the c comment (default)
+// true : Use the cpp comment
+extern Option<bool>
+mod_add_force_c_closebrace_comment;
+
+// 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;
+
+// Syntax to use for infinite loops.
+//
+// 0: Leave syntax alone (default)
+// 1: Rewrite as `for(;;)`
+// 2: Rewrite as `while(true)`
+// 3: Rewrite as `do`...`while(true);`
+// 4: Rewrite as `while(1)`
+// 5: Rewrite as `do`...`while(1);`
+//
+// Infinite loops that do not already match one of these syntaxes are ignored.
+// Other options that affect loop formatting will be applied after transforming
+// the syntax.
+extern BoundedOption<unsigned, 0, 5>
+mod_infinite_loop;
+
+// Add or remove the 'int' keyword in 'int short'.
+extern Option<iarf_e>
+mod_int_short;
+
+// Add or remove the 'int' keyword in 'short int'.
+extern Option<iarf_e>
+mod_short_int;
+
+// Add or remove the 'int' keyword in 'int long'.
+extern Option<iarf_e>
+mod_int_long;
+
+// Add or remove the 'int' keyword in 'long int'.
+extern Option<iarf_e>
+mod_long_int;
+
+// Add or remove the 'int' keyword in 'int signed'.
+extern Option<iarf_e>
+mod_int_signed;
+
+// Add or remove the 'int' keyword in 'signed int'.
+extern Option<iarf_e>
+mod_signed_int;
+
+// Add or remove the 'int' keyword in 'int unsigned'.
+extern Option<iarf_e>
+mod_int_unsigned;
+
+// Add or remove the 'int' keyword in 'unsigned int'.
+extern Option<iarf_e>
+mod_unsigned_int;
+
+// If there is a situation where mod_int_* and mod_*_int would result in
+// multiple int keywords, whether to keep the rightmost int (the default) or the
+// leftmost int.
+extern Option<bool>
+mod_int_prefer_int_on_left;
+
+// (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
+
+// How to use tabs when indenting preprocessor code.
+//
+// -1: Use 'indent_with_tabs' setting (default)
+// 0: Spaces only
+// 1: Indent with tabs to brace level, align with spaces
+// 2: Indent and align with tabs, using spaces when not on a tabstop
+extern BoundedOption<signed, -1, 2>
+pp_indent_with_tabs; // = -1
+
+// 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_after;
+
+// Sets the number of spaces per level added with pp_space_after.
+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;
+
+// An offset value that controls the indentation of the body of a multiline #define.
+// 'body' refers to all the lines of a multiline #define except the first line.
+// Requires 'pp_ignore_define_body = false'.
+//
+// <0: Absolute column: the body indentation starts off at the specified column
+// (ex. -3 ==> the body is indented starting from column 3)
+// >=0: Relative to the column of the '#' of '#define'
+// (ex. 3 ==> the body is indented starting 3 columns at the right of '#')
+extern BoundedOption<signed, -32, 32>
+pp_multiline_define_body_indent; // = 8
+
+// 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 preprocessor 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 preprocessor 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 preprocessor 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
+// preprocessor 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 beginning of the lambda body
+//
+// true: indentation will be at the beginning of the lambda body
+// false: indentation will be after the assignment (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;
+
+// sort (or not) the tracking info.
+extern Option<bool>
+debug_sort_the_tracks; // = true
+
+// decode (or not) the flags as a new line.
+// only if the -p option is set.
+extern Option<bool>
+debug_decode_the_flags;
+
+// use (or not) the exit(EX_SOFTWARE) function.
+extern Option<bool>
+debug_use_the_exit_function_pop; // = true
+
+// insert the number of the line at the beginning of each line
+extern Option<bool>
+set_numbering_for_html_output;
+
+//END
+
+} // namespace options
+
+} // namespace uncrustify
+
+#endif /* OPTIONS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options_for_QT.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options_for_QT.cpp
new file mode 100644
index 00000000..c0a178f0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ 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.78.0/src/options_for_QT.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/options_for_QT.h
new file mode 100644
index 00000000..1b8bfccf
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+#endif /* OPTIONS_FOR_QT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.cpp
new file mode 100644
index 00000000..6de21597
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.cpp
@@ -0,0 +1,3580 @@
+/**
+ * @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>
+
+// if you need more logs, commented out the next define line
+#define EXTRA_LOG
+
+constexpr static auto LCURRENT = LOUTPUT;
+
+using namespace uncrustify;
+
+
+struct cmt_reflow
+{
+ Chunk *pc = Chunk::NullChunkPtr;
+ 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)
+ UncText cont_text; //! fixed text to output at the start of a line (0 to 3 chars)
+ bool reflow = false; //! reflow the current line
+};
+
+
+// for tracking line numbering
+bool numbering_status = false;
+int line_number;
+char char_number[16] = { 0 };
+
+
+void set_numbering(bool status)
+{
+ if (options::set_numbering_for_html_output())
+ {
+ numbering_status = status;
+ }
+}
+
+
+bool get_numbering()
+{
+ return(numbering_status);
+}
+
+
+void set_line_number()
+{
+ line_number = 0;
+}
+
+
+void print_numbering()
+{
+ if (get_numbering())
+ {
+ line_number++;
+ sprintf(char_number, "%d ", line_number);
+ write_string(char_number);
+ }
+}
+
+
+/**
+ * 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, UncText &out_txt);
+
+
+static bool kw_fcn_class(Chunk *cmt, UncText &out_txt);
+
+
+static bool kw_fcn_message(Chunk *cmt, UncText &out_txt);
+
+
+static bool kw_fcn_category(Chunk *cmt, UncText &out_txt);
+
+
+static bool kw_fcn_scope(Chunk *cmt, UncText &out_txt);
+
+
+static bool kw_fcn_function(Chunk *cmt, UncText &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, UncText &out_txt);
+
+
+static bool kw_fcn_fclass(Chunk *cmt, UncText &out_txt);
+
+
+static bool kw_fcn_year(Chunk *cmt, UncText &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 UncText buffer to be filled
+ * @param[in] ifdef if conditional as chunk list
+ */
+static void generate_if_conditional_as_text(UncText &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 UncText &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 UncText &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 UncText &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 UncText &str);
+
+
+static int next_up(const UncText &text, size_t idx, const UncText &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(UncText &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 UncText &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 = true;
+ 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 = true;
+ cpd.spaces = 0;
+ print_numbering();
+ }
+ else if (ch == '\r') // do not output the CARRIAGERETURN
+ {
+ // do not output '\r'
+ cpd.column = 1;
+ cpd.did_newline = true;
+ 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");
+
+ int indent_with_tabs = options::pp_indent_with_tabs();
+
+ if ( cpd.in_preproc != CT_PREPROC
+ || indent_with_tabs == -1)
+ {
+ indent_with_tabs = options::indent_with_tabs();
+ }
+
+ if (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 UncText &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 UncText &text, size_t 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++;
+ }
+ bool exceed_limit = (cpd.column + length - 1) > options::cmt_width();
+ LOG_FMT(LCONTTEXT, "%s(%d): idx is %zu%s\n",
+ __func__, __LINE__, idx, (exceed_limit ? " exceeds limit" : ""));
+ return(exceed_limit);
+}
+
+
+/**
+ * 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 = false;
+
+ 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");
+ 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 = false;
+
+ 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 Flags 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->GetOrigLine(), get_token_name(pc->GetType()),
+ get_token_name(pc->GetParentType()), get_token_name(pc->GetTypeOfParent()),
+ (int)pc->GetColumn(), (int)pc->GetOrigCol(), (int)pc->GetOrigColEnd(), (int)pc->GetOrigPrevSp(),
+ (int)pc->GetBraceLevel(), (int)pc->GetLevel(), (int)pc->GetPpLevel(), (int)pc->GetNlCount(), pc->GetAfterTab());
+#else // not WIN32
+ fprintf(pfile, "%s# %3zu>%19.19s|%19.19s|%19.19s[%3zu/%3zu/%3zu/%3zu][%zu/%zu/%zu]",
+ eol_marker, pc->GetOrigLine(), get_token_name(pc->GetType()),
+ get_token_name(pc->GetParentType()), get_token_name(pc->GetTypeOfParent()),
+ pc->GetColumn(), pc->GetOrigCol(), pc->GetOrigColEnd(), pc->GetOrigPrevSp(),
+ pc->GetBraceLevel(), pc->GetLevel(), pc->GetPpLevel());
+ // Print pc flags in groups of 4 hex characters
+ char flag_string[24];
+ sprintf(flag_string, "%16llx", static_cast<PcfFlags::int_t>(pc->GetFlags()));
+ fprintf(pfile, "[%.4s %.4s %.4s %.4s]", flag_string, flag_string + 4, flag_string + 8, flag_string + 12);
+ fprintf(pfile, "[%zu-%d]",
+ pc->GetNlCount(), pc->GetAfterTab());
+#endif // ifdef WIN32
+
+ if ( pc->IsNot(CT_NEWLINE)
+ && (pc->Len() != 0))
+ {
+ for (size_t cnt = 0; cnt < pc->GetColumn(); cnt++)
+ {
+ fprintf(pfile, " ");
+ }
+
+ if (pc->IsNot(CT_NL_CONT))
+ {
+ fprintf(pfile, "%s", pc->Text());
+ }
+ else
+ {
+ fprintf(pfile, "\\");
+ }
+ }
+
+ if (options::debug_decode_the_flags())
+ {
+ // such as:
+ // The flags are: [0xc0400:IN_CLASS,STMT_START,EXPR_START]
+ fprintf(pfile, "%s The flags are: ", eol_marker);
+ fprintf(pfile, "%s", pcf_flags_str(pc->GetFlags()).c_str());
+ }
+ }
+
+ 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,%zu,%zu,%zu,%zu,",
+ eol_marker, pc->GetOrigLine(), get_token_name(pc->GetType()),
+ get_token_name(pc->GetParentType()), get_token_name(pc->GetTypeOfParent()),
+ pc->GetColumn(), pc->GetOrigCol(), pc->GetOrigColEnd(), pc->GetOrigPrevSp(),
+ pc->GetBraceLevel(), pc->GetLevel(), pc->GetPpLevel());
+
+ auto pcf_flag_str = pcf_flags_str(E_PcfFlag(pc->GetFlags()));
+#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->GetNlCount(), pc->GetAfterTab());
+
+ if ( pc->IsNot(CT_NEWLINE)
+ && (pc->Len() != 0))
+ {
+ fprintf(pfile, "\"");
+
+ for (size_t cnt = 0; cnt < pc->GetColumn(); cnt++)
+ {
+ fprintf(pfile, " ");
+ }
+
+ if (pc->IsNot(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
+
+
+// Compares two tracks according to second in descending order.
+bool compareTrack(TrackNumber t1, TrackNumber t2)
+{
+ char *t1s = t1.second;
+ char *t2s = t2.second;
+ int vergleich = strcmp(t2s, t1s);
+ bool int_vergleich = vergleich > 0;
+
+ return(int_vergleich);
+}
+
+
+void output_text(FILE *pfile)
+{
+ bool tracking = cpd.html_type != tracking_type_e::TT_NONE; // special for debugging
+
+ cpd.fout = pfile;
+ cpd.did_newline = true;
+ 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->SetColumn(pc->GetColumn() + indent);
+ pc->SetColumnIndent(pc->GetColumnIndent() + indent);
+ }
+
+ cpd.frag_cols = 0;
+ }
+
+ if (tracking)
+ {
+ set_numbering(false);
+ 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");
+ set_numbering(true);
+ set_line_number();
+ print_numbering();
+ }
+ bool write_in_tracking = false;
+ int pp_indent_with_tabs = options::pp_indent_with_tabs();
+
+ if (pp_indent_with_tabs == -1)
+ {
+ pp_indent_with_tabs = options::indent_with_tabs();
+ }
+
+ // 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->GetType()), pc->GetOrigLine(), pc->GetColumn(), pc->GetNlCount());
+ cpd.output_tab_as_space = false;
+
+ if (pc->Is(CT_NEWLINE))
+ {
+ for (size_t cnt = 0; cnt < pc->GetNlCount(); cnt++)
+ {
+ if ( cnt > 0
+ && pc->GetNlColumn() > 1)
+ {
+ log_rule_B("indent_with_tabs - newline");
+
+ if (pc->IsPreproc())
+ {
+ output_to_column(pc->GetNlColumn(), (pp_indent_with_tabs == 2));
+ }
+ else
+ {
+ output_to_column(pc->GetNlColumn(), (options::indent_with_tabs() == 2));
+ }
+ }
+ add_char('\n');
+ }
+
+ cpd.did_newline = true;
+ cpd.column = 1;
+ }
+ else if (pc->Is(CT_NL_CONT))
+ {
+ // FIXME: this really shouldn't be done here!
+ if (!pc->TestFlags(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->SetColumn(cpd.column + (options::sp_before_nl_cont() == IARF_FORCE));
+ }
+ else
+ {
+ // Try to keep the same relative spacing
+ Chunk *prev = pc->GetPrev();
+
+ if (prev->Is(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->SetColumn(pc->GetOrigCol());
+ }
+ else
+ {
+ // Try to keep the same relative spacing
+ while ( prev->IsNotNullChunk()
+ && prev->GetOrigCol() == 0
+ && prev->GetNlCount() == 0)
+ {
+ prev = prev->GetPrev();
+ }
+
+ if ( prev->IsNotNullChunk()
+ && prev->GetNlCount() == 0)
+ {
+ int orig_sp = pc->GetOrigPrevSp();
+
+ if ((int)(cpd.column + orig_sp) < 0)
+ {
+#ifdef WIN32
+ fprintf(stderr, "FATAL: negative value.\n pc->GetOrigCol() is %d, prev->GetOrigColEnd() is %d\n",
+ (int)pc->GetOrigCol(), (int)prev->GetOrigColEnd());
+#else // not WIN32
+ fprintf(stderr, "FATAL: negative value.\n pc->GetOrigCol() is %zu, prev->GetOrigColEnd() is %zu\n",
+ pc->GetOrigCol(), prev->GetOrigColEnd());
+#endif // ifdef WIN32
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ pc->SetColumn(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->GetColumn() < (cpd.column + 1)))
+ {
+ pc->SetColumn(cpd.column + 1);
+ }
+ }
+ }
+ }
+ output_to_column(pc->GetColumn(), false);
+ }
+ else
+ {
+ log_rule_B("indent_with_tabs - newline cont");
+
+ if (pc->IsPreproc())
+ {
+ output_to_column(pc->GetColumn(), (pp_indent_with_tabs == 2));
+ }
+ else
+ {
+ output_to_column(pc->GetColumn(), (options::indent_with_tabs() == 2));
+ }
+ }
+ add_char('\\');
+ add_char('\n');
+ cpd.did_newline = true;
+ cpd.column = 1;
+ }
+ else if (pc->Is(CT_COMMENT_MULTI))
+ {
+ log_rule_B("cmt_indent_multi");
+ log_rule_B("cmt_convert_tab_to_spaces - multi");
+ cpd.output_tab_as_space = options::cmt_convert_tab_to_spaces();
+
+ if (options::cmt_indent_multi())
+ {
+ output_comment_multi(pc);
+ }
+ else
+ {
+ output_comment_multi_simple(pc);
+ }
+ }
+ else if ( pc->Is(CT_COMMENT_CPP)
+ || pc->Is(CT_COMMENT_CPP_ENDIF))
+ {
+ log_rule_B("cmt_comment_cpp");
+ log_rule_B("cmt_convert_tab_to_spaces - comment_cpp");
+ cpd.output_tab_as_space = options::cmt_convert_tab_to_spaces();
+
+ 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 ( pc->Is(CT_COMMENT)
+ || pc->Is(CT_COMMENT_ENDIF))
+ {
+ log_rule_B("cmt_comment");
+ log_rule_B("cmt_convert_tab_to_spaces - comment");
+ cpd.output_tab_as_space = options::cmt_convert_tab_to_spaces();
+
+ pc = output_comment_c(pc);
+ }
+ else if ( pc->Is(CT_JUNK)
+ || pc->Is(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetStr().size());
+ // do not adjust the column for junk
+ add_text(pc->GetStr(), 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->GetOrigLine(), pc->GetColumn(), get_token_name(pc->GetType()));
+ }
+ else
+ {
+ bool allow_tabs;
+ cpd.output_trailspace = (pc->Is(CT_STRING_MULTI));
+
+ // indent to the 'level' first
+ if (cpd.did_newline)
+ {
+ if ( ( pc->IsPreproc()
+ && pp_indent_with_tabs == 1)
+ || ( !pc->IsPreproc()
+ && options::indent_with_tabs() == 1))
+ {
+ size_t lvlcol;
+
+ /*
+ * FIXME: it would be better to properly set m_columnIndent in
+ * indent_text(), but this hack for '}' and '#' seems to work.
+ */
+ if ( pc->Is(CT_BRACE_CLOSE)
+ || pc->Is(CT_CASE_COLON)
+ || pc->IsPreproc())
+ {
+ lvlcol = pc->GetColumn();
+ }
+ else
+ {
+ lvlcol = pc->GetColumnIndent();
+
+ if (lvlcol > pc->GetColumn())
+ {
+ lvlcol = pc->GetColumn();
+ }
+ }
+
+ if (lvlcol > 1)
+ {
+ log_rule_B("indent_with_tabs - hack");
+ output_to_column(lvlcol, true);
+ }
+ }
+ log_rule_B("indent_with_tabs");
+ allow_tabs = ( pc->IsPreproc()
+ && pp_indent_with_tabs == 2)
+ || ( !pc->IsPreproc()
+ && 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->GetOrigLine(), pc->GetColumn(), pc->GetColumnIndent(), 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->GetColumn() < 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->TestFlags(PCF_WAS_ALIGNED)
+ && ((prev->GetColumn() + prev->Len() + 1) != pc->GetColumn()));
+
+ log_rule_B("align_keep_tabs");
+
+ if (options::align_keep_tabs())
+ {
+ allow_tabs |= pc->GetAfterTab();
+ }
+ LOG_FMT(LOUTIND, "%s(%d): at column %zu(%s)\n",
+ __func__, __LINE__, pc->GetColumn(), (allow_tabs ? "true" : "FALSE"));
+ }
+ output_to_column(pc->GetColumn(), allow_tabs);
+
+ if (write_in_tracking)
+ {
+ if (pc->Is(CT_ANGLE_OPEN))
+ {
+ add_text("&lt;", false, false);
+ }
+ else if (pc->Is(CT_ANGLE_CLOSE))
+ {
+ add_text("&gt;", false, false);
+ }
+ else
+ {
+ if (tracking)
+ {
+ if (pc->GetStr()[0] == '<')
+ {
+ add_text("&lt;", false, false);
+ size_t lang = pc->GetStr().size();
+
+ for (size_t idx = 1; idx < lang - 1; idx++)
+ {
+ int ch = pc->GetStr()[idx];
+ add_char(ch);
+ }
+
+ add_text("&gt;", false, false);
+ }
+ }
+ add_text(pc->GetStr(), false, pc->Is(CT_STRING));
+ }
+ write_in_tracking = false;
+ }
+ else
+ {
+ add_text(pc->GetStr(), false, pc->Is(CT_STRING));
+ }
+
+ if (pc->Is(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 = pc->IsNewline();
+ cpd.output_trailspace = false;
+ }
+
+ if (pc->GetTrackingData() != nullptr)
+ {
+ LOG_FMT(LGUY, " Tracking info are: \n");
+ LOG_FMT(LGUY, " number of track(s) %zu\n", pc->GetTrackingData()->size());
+ add_text("<a title=\"");
+ char tempText[80];
+
+ // is sorting necessary?
+ size_t many = pc->GetTrackingData()->size();
+
+ if (many > 1)
+ {
+#ifdef EXTRA_LOG
+ // protocol before sort
+ for (size_t track = 0; track < pc->GetTrackingData()->size(); track++)
+ {
+ const TrackList *A = pc->GetTrackingData();
+ const TrackNumber 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);
+ }
+#endif
+
+ if (options::debug_sort_the_tracks())
+ {
+ TrackList *A1 = pc->TrackingData();
+ sort(A1->begin(), A1->end(), compareTrack);
+ }
+#ifdef EXTRA_LOG
+ // protocol after sort
+ for (size_t track = 0; track < pc->GetTrackingData()->size(); track++)
+ {
+ const TrackList *A = pc->GetTrackingData();
+ const TrackNumber 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);
+ }
+#endif
+ }
+ char *old_one = nullptr;
+
+ for (size_t track = 0; track < pc->GetTrackingData()->size(); track++)
+ {
+ const TrackList *A = pc->GetTrackingData();
+ const TrackNumber B = A->at(track);
+ size_t Bfirst = B.first;
+ char *Bsecond = B.second;
+ bool first_text = true;
+
+ if ( old_one == nullptr
+ || strcmp(old_one, Bsecond) != 0)
+ {
+ // first time this option
+ if (old_one != nullptr)
+ {
+ add_text("&#010;");
+ }
+ old_one = Bsecond;
+
+ if (first_text)
+ {
+ sprintf(tempText, "%s", Bsecond);
+ add_text(tempText);
+ add_text(": ");
+ first_text = false;
+ }
+ }
+ else
+ {
+ add_text(", ");
+ }
+ sprintf(tempText, "%zu", Bfirst);
+ add_text(tempText);
+ } // for (size_t track = 0; track < pc->GetTrackingData()->size(); track++)
+
+ add_text("\"><font color=\"red\">M</font></a>");
+ write_in_tracking = true;
+ }
+ } // loop over the whole chunk list
+
+ if (tracking)
+ {
+ set_numbering(false);
+ add_text("</pre>\n");
+ add_text("</body>\n");
+ add_text("</html>\n");
+ }
+} // output_text
+
+
+static size_t cmt_parse_lead(const UncText &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 UncText &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)
+{
+ while ((pc = pc->GetNext())->IsNotNullChunk())
+ {
+ if ( pc->Is(CT_FUNC_DEF)
+ || pc->Is(CT_FUNC_PROTO)
+ || pc->Is(CT_FUNC_CLASS_DEF)
+ || pc->Is(CT_FUNC_CLASS_PROTO)
+ || pc->Is(CT_OC_MSG_DECL))
+ {
+ return(pc);
+ }
+ }
+ return(Chunk::NullChunkPtr);
+}
+
+
+static Chunk *get_next_class(Chunk *pc)
+{
+ return(pc->GetNextType(CT_CLASS)->GetNext());
+}
+
+
+static Chunk *get_prev_category(Chunk *pc)
+{
+ return(pc->GetPrevType(CT_OC_CATEGORY));
+}
+
+
+static Chunk *get_next_scope(Chunk *pc)
+{
+ return(pc->GetNextType(CT_OC_SCOPE));
+}
+
+
+static Chunk *get_prev_oc_class(Chunk *pc)
+{
+ return(pc->GetPrevType(CT_OC_CLASS));
+}
+
+
+static int next_up(const UncText &text, size_t idx, const UncText &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 UncText &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->GetColumn();
+ cmt.brace_col = pc->GetColumnIndent();
+ cmt.base_col = pc->GetColumnIndent();
+ 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->GetBraceLevel() * options::output_tab_size());
+ }
+ // LOG_FMT(LSYS, "%s: line %zd, brace=%zd base=%zd col=%zd orig=%zd aligned=%x\n",
+ // __func__, pc->GetOrigLine(), cmt.brace_col, cmt.base_col, cmt.column, pc->GetOrigCol(),
+ // pc->GetFlags() & (PCF_WAS_ALIGNED | PCF_RIGHT_COMMENT));
+
+ if ( pc->GetParentType() == CT_COMMENT_START
+ || pc->GetParentType() == CT_COMMENT_WHOLE)
+ {
+ log_rule_B("indent_col1_comment");
+
+ if ( !options::indent_col1_comment()
+ && pc->GetOrigCol() == 1
+ && !pc->TestFlags(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()
+ && ( pc->GetParentType() == CT_COMMENT_END
+ || pc->GetParentType() == CT_COMMENT_WHOLE))
+ {
+ cmt.column = align_tab_column(cmt.column - 1);
+ // LOG_FMT(LSYS, "%s: line %d, orig:%d new:%d\n",
+ // __func__, pc->GetOrigLine(), pc->GetColumn(), cmt.column);
+ pc->SetColumn(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 (pc->GetParentType() == 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->GetNlCount() == 1)
+ {
+ // Make sure the comment is the same type at the same column
+ next = next->GetNext();
+
+ if ( next->Is(pc->GetType())
+ && ( ( next->GetColumn() == 1
+ && pc->GetColumn() == 1)
+ || ( next->GetColumn() == cmt.base_col
+ && pc->GetColumn() == cmt.base_col)
+ || ( next->GetColumn() > cmt.base_col
+ && pc->GetParentType() == 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();
+
+ bool replace_comment = ( options::cmt_trailing_single_line_c_to_cpp()
+ && first->IsLastChunkOnLine()
+ && first->Str().at(2) != '*');
+
+ if ( replace_comment
+ && first->TestFlags(PCF_IN_PREPROC))
+ {
+ // Do not replace a single line comment if we are inside a #define line
+ if (first->GetPpStart()->GetParentType() == CT_PP_DEFINE)
+ {
+ replace_comment = false;
+ }
+ }
+
+ if (replace_comment)
+ {
+ // Transform the comment to CPP and reuse the same logic (issue #4121)
+ log_rule_B("cmt_trailing_single_line_c_to_cpp");
+
+ UncText tmp(first->GetStr(), 0, first->Len() - 2);
+ tmp.at(1) = '/'; // Change '/*' to '//'
+ cmt_trim_whitespace(tmp, false);
+ first->Str() = tmp;
+
+ output_comment_cpp(first);
+ }
+ else
+ {
+ add_comment_text(first->GetStr(), 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;
+ UncText tmp;
+
+ while (can_combine_comment(pc, cmt))
+ {
+ LOG_FMT(LCONTTEXT, "%s(%d): Text() is '%s'\n",
+ __func__, __LINE__, pc->Text());
+ tmp.set(pc->GetStr(), 2, pc->Len() - 4);
+
+ if ( cpd.last_char == '*'
+ && 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->GetStr(), 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);
+
+ UncText 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->GetStr()[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->GetStr().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->GetPrev()->IsNullChunk()
+ || first->GetPrev()->GetOrigLine() != first->GetOrigLine())
+ && ( 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->GetStr(), cmt, false);
+ }
+ else
+ {
+ size_t iLISz = leadin.size();
+ UncText tmp(first->GetStr(), 0, iLISz);
+ add_comment_text(tmp, cmt, false);
+
+ tmp.set(first->GetStr(), 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] != '/'))
+ {
+ // only with sp_cmt_cpp_start set to 'add' or 'force'
+ bool sp_cmt_pvs = options::sp_cmt_cpp_pvs(); // Issue #3919
+ bool sp_cmt_lint = options::sp_cmt_cpp_lint(); // Issue #3614
+ UncText temp = first->GetStr();
+ int PVS = temp.find("//-V");
+ int LINT = temp.find("//lint");
+
+ // @return == -1 if not found
+ // @return >= 0 the position
+ if ( ( PVS == 0
+ && sp_cmt_pvs)
+ || ( LINT == 0
+ && sp_cmt_lint))
+ {
+ // do not include a space
+ }
+ else
+ {
+ 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();
+
+ UncText 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->GetStr()[2])
+ && (options::sp_cmt_cpp_start() & IARF_ADD))
+ {
+ add_char(' ');
+ }
+ tmp.set(first->GetStr(), 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->GetStr()[2]) ? 1 : 0;
+ tmp.set(pc->GetStr(), 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->GetStr()[2]) ? 1 : 0;
+ tmp.set(pc->GetStr(), 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(UncText &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((std::wregex)L"[\\w,\\]\\)]$", (std::wregex)L"^[\\w,\\[\\(]"));
+ regex_map.emplace(1L, std::make_pair((std::wregex)L"\\.$", (std::wregex)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->GetType()), pc->GetOrigCol(), pc->GetColumn());
+
+ 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->GetOrigCol() - cmt.base_col;
+
+ calculate_comment_body_indent(cmt, pc->GetStr());
+
+ 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->GetStr().get().cbegin(),
+ pc->GetStr().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->GetColumn(); // the col of subsequent comment lines
+ size_t cmt_idx = 0;
+ bool nl_end = false;
+ bool doxygen_javadoc_indent_align = false;
+ UncText 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->GetStr());
+ auto enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->GetStr());
+
+ while (cmt_idx < pc->Len())
+ {
+ int ch = pc->GetStr()[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;
+ UncText verbatim_text(pc->GetStr(),
+ 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->GetStr(),
+ enable_processing_cmt_idx);
+ enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->GetStr(),
+ 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->GetStr()[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->GetStr().get().cbegin() + start_idx,
+ pc->GetStr().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->GetStr(),
+ cmt_idx);
+
+ while ( cmt_idx < pc->Len()
+ && !unc_isspace(pc->GetStr()[cmt_idx])
+ && pc->GetStr()[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->GetStr(),
+ cmt_idx);
+
+ if (pc->GetStr()[cmt_idx] != ',')
+ {
+ break;
+ }
+ ++cmt_idx;
+ line.append(", ");
+ }
+ }
+ cmt_idx = eat_line_whitespace(pc->GetStr(),
+ 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->GetStr()[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->TestFlags(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->GetStr()[nxt_idx] != '\r'
+ && pc->GetStr()[nxt_idx] != '\n');
+ nxt_idx++)
+ {
+ if ( next_nonempty_line < 0
+ && !unc_isspace(pc->GetStr()[nxt_idx])
+ && pc->GetStr()[nxt_idx] != '*'
+ && (pc->TestFlags(PCF_IN_PREPROC)
+ ? ( pc->GetStr()[nxt_idx] != '\\'
+ || ( pc->GetStr()[nxt_idx + 1] != '\r'
+ && pc->GetStr()[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->GetStr()[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->GetStr().get().cbegin() + next_nonempty_line,
+ pc->GetStr().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->TestFlags(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
+ UncText tmp = UncText(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, UncText &out_txt)
+{
+ UNUSED(cmt);
+ out_txt.append(path_basename(cpd.filename.c_str()));
+ return(true);
+}
+
+
+static bool kw_fcn_class(Chunk *cmt, UncText &out_txt)
+{
+ Chunk *tmp = Chunk::NullChunkPtr;
+
+ if (language_is_set(LANG_CPP | LANG_OC))
+ {
+ Chunk *fcn = get_next_function(cmt);
+
+ if (fcn->Is(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->IsNullChunk())
+ {
+ tmp = get_next_class(cmt);
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ out_txt.append(tmp->GetStr());
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if (tmp->IsNot(CT_DC_MEMBER))
+ {
+ break;
+ }
+ tmp = tmp->GetNext();
+
+ if (tmp->IsNotNullChunk())
+ {
+ out_txt.append("::");
+ out_txt.append(tmp->GetStr());
+ }
+ }
+ return(true);
+ }
+ return(false);
+} // kw_fcn_class
+
+
+static bool kw_fcn_message(Chunk *cmt, UncText &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (fcn->IsNullChunk())
+ {
+ return(false);
+ }
+ out_txt.append(fcn->GetStr());
+
+ Chunk *tmp = fcn->GetNextNcNnl();
+ Chunk *word = Chunk::NullChunkPtr;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( tmp->Is(CT_BRACE_OPEN)
+ || tmp->Is(CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if (tmp->Is(CT_OC_COLON))
+ {
+ if (word->IsNotNullChunk())
+ {
+ out_txt.append(word->GetStr());
+ word = Chunk::NullChunkPtr;
+ }
+ out_txt.append(":");
+ }
+
+ if (tmp->Is(CT_WORD))
+ {
+ word = tmp;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ return(true);
+} // kw_fcn_message
+
+
+static bool kw_fcn_category(Chunk *cmt, UncText &out_txt)
+{
+ Chunk *category = get_prev_category(cmt);
+
+ if (category->IsNotNullChunk())
+ {
+ out_txt.append('(');
+ out_txt.append(category->GetStr());
+ out_txt.append(')');
+ }
+ return(true);
+} // kw_fcn_category
+
+
+static bool kw_fcn_scope(Chunk *cmt, UncText &out_txt)
+{
+ Chunk *scope = get_next_scope(cmt);
+
+ if (scope->IsNotNullChunk())
+ {
+ out_txt.append(scope->GetStr());
+ return(true);
+ }
+ return(false);
+} // kw_fcn_scope
+
+
+static bool kw_fcn_function(Chunk *cmt, UncText &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (fcn->IsNotNullChunk())
+ {
+ if (fcn->GetParentType() == CT_OPERATOR)
+ {
+ out_txt.append("operator ");
+ }
+
+ if (fcn->GetPrev()->GetType() == CT_DESTRUCTOR)
+ {
+ out_txt.append('~');
+ }
+ out_txt.append(fcn->GetStr());
+ return(true);
+ }
+ return(false);
+}
+
+
+static bool kw_fcn_javaparam(Chunk *cmt, UncText &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (fcn->IsNullChunk())
+ {
+ return(false);
+ }
+ Chunk *fpo;
+ Chunk *fpc;
+ bool has_param = true;
+ bool need_nl = false;
+
+ if (fcn->Is(CT_OC_MSG_DECL))
+ {
+ Chunk *tmp = fcn->GetNextNcNnl();
+ has_param = false;
+
+ while (tmp->IsNotNullChunk())
+ {
+ if ( tmp->Is(CT_BRACE_OPEN)
+ || tmp->Is(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->GetStr());
+ out_txt.append(" TODO");
+ }
+ has_param = false;
+
+ if (tmp->Is(CT_PAREN_CLOSE))
+ {
+ has_param = true;
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ fpo = fpc = Chunk::NullChunkPtr;
+ }
+ else
+ {
+ fpo = fcn->GetNextType(CT_FPAREN_OPEN, fcn->GetLevel());
+
+ if (fpo->IsNullChunk())
+ {
+ return(true);
+ }
+ fpc = fpo->GetNextType(CT_FPAREN_CLOSE, fcn->GetLevel());
+
+ 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())
+ && tmp->IsString("void"))
+ {
+ has_param = false;
+ }
+ }
+ }
+
+ if (has_param)
+ {
+ Chunk *prev = Chunk::NullChunkPtr;
+ tmp = fpo;
+
+ while ((tmp = tmp->GetNext())->IsNotNullChunk())
+ {
+ if ( tmp->Is(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->GetStr());
+ out_txt.append(" TODO");
+ }
+ prev = Chunk::NullChunkPtr;
+
+ if (tmp == fpc)
+ {
+ break;
+ }
+ }
+
+ if (tmp->Is(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()
+ && tmp->GetParentType() == CT_OC_MSG_DECL
+ && tmp->Is(CT_PAREN_CLOSE))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && !tmp->IsString("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, UncText &out_txt)
+{
+ Chunk *fcn = get_next_function(cmt);
+
+ if (!fcn)
+ {
+ return(false);
+ }
+
+ if (fcn->TestFlags(PCF_IN_CLASS))
+ {
+ // if inside a class, we need to find to the class name
+ Chunk *tmp = fcn->GetPrevType(CT_BRACE_OPEN, fcn->GetLevel() - 1);
+ tmp = tmp->GetPrevType(CT_CLASS, tmp->GetLevel());
+
+ if (tmp->IsNullChunk())
+ {
+ tmp = Chunk::NullChunkPtr;
+ }
+ else
+ {
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->GetNextNcNnl()->Is(CT_DC_MEMBER))
+ {
+ tmp = tmp->GetNextNcNnl();
+ tmp = tmp->GetNextNcNnl();
+ }
+
+ if (tmp->IsNotNullChunk())
+ {
+ out_txt.append(tmp->GetStr());
+ return(true);
+ }
+ }
+ else
+ {
+ // if outside a class, we expect "CLASS::METHOD(...)"
+ Chunk *tmp = fcn->GetPrevNcNnl();
+
+ if (tmp->Is(CT_OPERATOR))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && ( tmp->Is(CT_DC_MEMBER)
+ || tmp->Is(CT_MEMBER)))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ out_txt.append(tmp->GetStr());
+ return(true);
+ }
+ }
+ return(false);
+} // kw_fcn_fclass
+
+
+static bool kw_fcn_year(Chunk *cmt, UncText &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, UncText &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->GetStr().find(kw.tag);
+
+ if (idx < 0)
+ {
+ continue;
+ }
+ UncText 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->GetStr().rfind("\n", idx);
+
+ if (nl_idx > 0)
+ {
+ // idx and nl_idx are both positive
+ UncText nl_txt;
+ nl_txt.append("\n");
+ nl_idx++;
+
+ while ( (nl_idx < static_cast<size_t>(idx))
+ && !unc_isalnum(pc->GetStr()[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->GetType()), pc->GetOrigCol(), pc->GetColumn());
+
+ 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 (pc->GetPrev()->IsNewline())
+ {
+ // The comment should be indented correctly
+ diff = pc->GetColumn() - pc->GetOrigCol();
+ }
+ 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->GetStr());
+ auto enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->GetStr());
+
+ UncText line;
+ size_t line_count = 0;
+ size_t line_column = pc->GetColumn();
+ size_t cmt_idx = 0;
+
+ while (cmt_idx < pc->Len())
+ {
+ int ch = pc->GetStr()[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;
+ UncText verbatim_text(pc->GetStr(),
+ 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->GetStr(),
+ enable_processing_cmt_idx);
+ enable_processing_cmt_idx = find_enable_processing_comment_marker(pc->GetStr(),
+ 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->GetStr()[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
+ && (size_t)(abs(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(UncText &dst, Chunk *ifdef)
+{
+ int column = -1;
+
+ dst.clear();
+
+ for (Chunk *pc = ifdef; pc != nullptr && pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (column == -1)
+ {
+ column = pc->GetColumn();
+ }
+
+ if ( pc->Is(CT_NEWLINE)
+ || pc->Is(CT_COMMENT_MULTI)
+ || pc->Is(CT_COMMENT_CPP))
+ {
+ break;
+ }
+ else if (pc->Is(CT_NL_CONT))
+ {
+ dst += ' ';
+ column = -1;
+ }
+ else if ( pc->Is(CT_COMMENT)
+ || pc->Is(CT_COMMENT_EMBED))
+ {
+ }
+ else // if (pc->Is(CT_JUNK)) || else
+ {
+ for (int spacing = pc->GetColumn() - column; spacing > 0; spacing--)
+ {
+ dst += ' ';
+ column++;
+ }
+
+ dst.append(pc->GetStr());
+ column += pc->Len();
+ }
+ }
+} // generate_if_conditional_as_text
+
+
+void add_long_preprocessor_conditional_block_comment()
+{
+ Chunk *pp_start = nullptr;
+ Chunk *pp_end = nullptr;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ // just track the preproc level:
+ if (pc->Is(CT_PREPROC))
+ {
+ pp_end = pp_start = pc;
+ }
+
+ if ( pc->IsNot(CT_PP_IF)
+ || !pp_start)
+ {
+ continue;
+ }
+#if 0
+ if (pc->TestFlags(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 (tmp->Is(CT_PREPROC))
+ {
+ pp_end = tmp;
+ }
+
+ if (tmp->IsNewline())
+ {
+ nl_count += tmp->GetNlCount();
+ }
+ else if ( pp_end->GetPpLevel() == pp_start->GetPpLevel()
+ && ( tmp->Is(CT_PP_ENDIF)
+ || ((br_open->Is(CT_PP_IF)) ? (tmp->Is(CT_PP_ELSE)) : 0)))
+ {
+ br_close = tmp;
+
+ LOG_FMT(LPPIF, "found #if / %s section on lines %zu and %zu, new line count=%zu\n",
+ (tmp->Is(CT_PP_ENDIF) ? "#endif" : "#else"),
+ br_open->GetOrigLine(), br_close->GetOrigLine(), 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->GetType() : -1), (tmp ? tmp->IsNewline() ? "newline"
+ : tmp->IsComment() ? "comment" : "other" : "---"));
+
+ if ( tmp->IsNullChunk()
+ || tmp->Is(CT_NEWLINE)) // tmp->IsNewline())
+ {
+ size_t nl_min;
+
+ if (br_close->Is(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" : ((tmp->Is(CT_PP_ENDIF)) ? "#endif" : "#else");
+ LOG_FMT(LPPIF, "#if / %s section candidate for augmenting when over NL threshold %zu != 0 (new line 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;
+
+ UncText str;
+ generate_if_conditional_as_text(str, br_open);
+
+ LOG_FMT(LPPIF, "#if / %s section over threshold %zu (new line 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 (br_close->Is(CT_PP_ENDIF))
+ {
+ break;
+ }
+ }
+ }
+ }
+} // add_long_preprocessor_conditional_block_comment
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.h
new file mode 100644
index 00000000..1d55c8c8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/output.h
@@ -0,0 +1,46 @@
+/**
+ * @file output.h
+ * prototypes for output.cpp
+ *
+ * @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);
+
+
+/**
+ * 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->GetPpLevel() 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();
+
+
+#endif /* OUTPUT_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parameter_pack_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parameter_pack_cleanup.cpp
new file mode 100644
index 00000000..12992ff3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parameter_pack_cleanup.cpp
@@ -0,0 +1,65 @@
+/**
+ * @file parameter_pack_cleanup.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "parameter_pack_cleanup.h"
+
+#include "chunk.h"
+#include "uncrustify.h"
+
+
+void parameter_pack_cleanup()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ // look for template
+ if (pc->Is(CT_TEMPLATE)) // Issue #3309
+ {
+ Chunk *template_end = pc->GetNextType(CT_SEMICOLON, pc->GetLevel());
+
+ // look for a parameter pack
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ if (pc->Is(CT_PARAMETER_PACK))
+ {
+ Chunk *parameter_pack = pc;
+
+ // look for a token with the same text
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ if (pc == template_end)
+ {
+ break;
+ }
+
+ if (strcmp(pc->Text(), parameter_pack->Text()) == 0)
+ {
+ pc->SetType(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.78.0/src/parameter_pack_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parameter_pack_cleanup.h
new file mode 100644
index 00000000..e3aa31ac
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* PARAMETER_PACK_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parens.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parens.cpp
new file mode 100644
index 00000000..18b69210
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parens.cpp
@@ -0,0 +1,362 @@
+/**
+ * @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()
+{
+ 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())->IsNotNullChunk())
+ {
+ if ( pc->IsNot(CT_SPAREN_OPEN)
+ || ( pc->GetParentType() != CT_IF
+ && pc->GetParentType() != CT_ELSEIF
+ && pc->GetParentType() != CT_SWITCH))
+ {
+ continue;
+ }
+ // Grab the close sparen
+ Chunk *pclose = pc->GetNextType(CT_SPAREN_CLOSE, pc->GetLevel(), E_Scope::PREPROC);
+
+ if (pclose->IsNotNullChunk())
+ {
+ check_bool_parens(pc, pclose, 0);
+ pc = pclose;
+ }
+ }
+ }
+} // do_parens
+
+
+void do_parens_assign() // 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())->IsNotNullChunk())
+ {
+ if (pc->Is(CT_ASSIGN))
+ {
+ if (pc->TestFlags(PCF_IN_SPAREN)) // Issue #4239
+ {
+ continue;
+ }
+ LOG_FMT(LPARADD, "%s(%d): orig line is %zu, orig col is %zu, text is '%s', level is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), pc->GetLevel());
+ // look before for a open sparen
+ size_t check_level = pc->GetLevel();
+ 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->GetOrigLine(), p->Text(), p->GetLevel(), get_token_name(p->GetType()));
+
+ //log_pcf_flags(LPARADD, p->GetFlags());
+ if (p->TestFlags(PCF_STMT_START))
+ {
+ break;
+ }
+
+ if (p->Is(CT_PAREN_OPEN))
+ {
+ check_level--;
+ }
+
+ if (p->Is(CT_SPAREN_OPEN))
+ {
+ break;
+ }
+ p = p->GetPrevNc(E_Scope::PREPROC);
+
+ if (p->GetLevel() < 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->GetOrigLine(), p->Text(), p->GetLevel(), get_token_name(p->GetType()));
+
+ if (p->GetParentType() == CT_WHILE)
+ {
+ continue;
+ }
+ // Grab the semicolon
+ Chunk *semicolon = pc->GetNextType(CT_SEMICOLON, pc->GetLevel(), E_Scope::PREPROC);
+
+ if (semicolon->IsNotNullChunk())
+ {
+ check_bool_parens(pc, semicolon, 0);
+ pc = semicolon;
+ }
+ }
+ }
+ }
+} // do_parens_assign
+
+
+void do_parens_return() // 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())->IsNotNullChunk())
+ {
+ if (pc->Is(CT_RETURN))
+ {
+ LOG_FMT(LPARADD, "%s(%d): orig line is %zu, text is '%s', level is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->Text(), pc->GetLevel());
+ // look before for a open sparen
+ size_t check_level = pc->GetLevel();
+ 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->GetOrigLine(), p->Text(), p->GetLevel(), get_token_name(p->GetType()));
+
+ //log_pcf_flags(LPARADD, p->GetFlags());
+ if (p->TestFlags(PCF_STMT_START))
+ {
+ break;
+ }
+
+ if (p->Is(CT_PAREN_OPEN))
+ {
+ check_level--;
+ }
+
+ if (p->Is(CT_SPAREN_OPEN))
+ {
+ break;
+ }
+ p = p->GetPrevNc(E_Scope::PREPROC);
+
+ if (p->GetLevel() < 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->GetOrigLine(), p->Text(), p->GetLevel(), get_token_name(p->GetType()));
+
+ if (p->GetParentType() == CT_WHILE)
+ {
+ continue;
+ }
+ // Grab the semicolon
+ Chunk *semicolon = pc->GetNextType(CT_SEMICOLON, pc->GetLevel(), 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): first: line %zu, col %zu, between '%s' [lvl is %zu] and\n",
+ __func__, __LINE__, first->GetOrigLine(), first->GetOrigCol(),
+ first->Text(), first->GetLevel());
+ LOG_FMT(LPARADD, "%s(%d): last: line %zu, col %zu, '%s' [lvl is %zu]\n",
+ __func__, __LINE__, last->GetOrigLine(), last->GetOrigCol(),
+ last->Text(), last->GetLevel());
+
+ // Don't do anything if we have a bad sequence, ie "&& )"
+ Chunk *first_n = first->GetNextNcNnl();
+
+ if (first_n == last)
+ {
+ return;
+ }
+ Chunk pc;
+
+ pc.SetType(CT_PAREN_OPEN);
+ pc.SetOrigLine(first_n->GetOrigLine());
+ pc.SetColumn(first_n->GetColumn()); // Issue #3236
+ pc.SetOrigCol(first_n->GetOrigCol()); // Issue #3236
+ pc.SetOrigColEnd(first_n->GetOrigColEnd()); // Issue #3236
+ pc.Str() = "(";
+ pc.SetFlags(first_n->GetFlags() & PCF_COPY_FLAGS);
+ pc.SetLevel(first_n->GetLevel());
+ pc.SetPpLevel(first_n->GetPpLevel());
+ pc.SetBraceLevel(first_n->GetBraceLevel());
+ pc.CopyAndAddBefore(first_n);
+
+ shift_the_rest_of_the_line(first_n); // Issue #3236
+
+ Chunk *last_prev = last->GetPrevNcNnl(E_Scope::PREPROC);
+
+ pc.SetType(CT_PAREN_CLOSE);
+ pc.SetOrigLine(last_prev->GetOrigLine());
+ pc.SetOrigCol(last_prev->GetOrigCol());
+ pc.SetColumn(last_prev->GetColumn() + 1); // Issue #3236
+ pc.SetOrigCol(last_prev->GetOrigCol() + 1); // Issue #3236
+ pc.SetOrigColEnd(last_prev->GetOrigColEnd() + 1); // Issue #3236
+ pc.Str() = ")";
+ pc.SetFlags(last_prev->GetFlags() & PCF_COPY_FLAGS);
+ pc.SetLevel(last_prev->GetLevel());
+ pc.SetPpLevel(last_prev->GetPpLevel());
+ pc.SetBraceLevel(last_prev->GetBraceLevel());
+ pc.CopyAndAddAfter(last_prev);
+
+ shift_the_rest_of_the_line(last); // Issue #3236
+
+ for (Chunk *tmp = first_n;
+ tmp != last_prev;
+ tmp = tmp->GetNextNcNnl())
+ {
+ tmp->SetLevel(tmp->GetLevel() + 1);
+ }
+
+ last_prev->SetLevel(last_prev->GetLevel() + 1);
+} // 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->GetOrigLine(), popen->GetOrigCol(),
+ pclose->GetOrigLine(), pclose->GetOrigCol(),
+ popen->GetLevel());
+
+ Chunk *pc = popen;
+
+ while ( (pc = pc->GetNextNcNnl())->IsNotNullChunk()
+ && pc != pclose)
+ {
+ if (pc->TestFlags(PCF_IN_PREPROC))
+ {
+ LOG_FMT(LPARADD2, " -- bail on PP %s [%s] at line %zu col %zu, level %zu\n",
+ get_token_name(pc->GetType()),
+ pc->Text(), pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+ return;
+ }
+
+ if ( pc->Is(CT_BOOL)
+ || pc->Is(CT_QUESTION)
+ || pc->Is(CT_COND_COLON)
+ || pc->Is(CT_COMMA))
+ {
+ LOG_FMT(LPARADD2, " -- %s [%s] at line %zu col %zu, level %zu\n",
+ get_token_name(pc->GetType()),
+ pc->Text(), pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+
+ if (hit_compare)
+ {
+ hit_compare = false;
+
+ if (!language_is_set(LANG_CS))
+ {
+ add_parens_between(ref, pc);
+ }
+ }
+ ref = pc;
+ }
+ else if (pc->Is(CT_COMPARE))
+ {
+ LOG_FMT(LPARADD2, " -- compare '%s' at line %zu, orig col is %zu, level is %zu\n",
+ pc->Text(), pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel());
+ hit_compare = true;
+ }
+ else if (pc->IsParenOpen())
+ {
+ Chunk *next = pc->GetClosingParen();
+
+ if (next->IsNotNullChunk())
+ {
+ check_bool_parens(pc, next, nest + 1);
+ pc = next;
+ }
+ }
+ else if (pc->Is(CT_SEMICOLON)) // Issue #3236
+ {
+ ref = pc;
+ }
+ else if ( pc->Is(CT_BRACE_OPEN)
+ || pc->Is(CT_SQUARE_OPEN)
+ || pc->Is(CT_ANGLE_OPEN))
+ {
+ // Skip [], {}, and <>
+ pc = pc->GetClosingParen();
+ }
+ }
+
+ 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.78.0/src/parens.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parens.h
new file mode 100644
index 00000000..f3c6fe87
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parens.h
@@ -0,0 +1,24 @@
+/**
+ * @file parens.h
+ * prototypes for parens.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+#ifndef PARENS_H_INCLUDED
+#define PARENS_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+//! add parenthesis
+void do_parens();
+
+
+void do_parens_assign();
+
+
+void do_parens_return();
+
+
+#endif /* PARENS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parent_for_pp.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parent_for_pp.cpp
new file mode 100644
index 00000000..f731b9f7
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ 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 (pc->Is(CT_PP_IF))
+ {
+ LOG_FMT(LMCB, "%s(%d): IF: orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_pcf_flags(LMCB, pc->GetFlags());
+ viz.push_back(pc);
+ }
+ else if (pc->Is(CT_PP_ELSE))
+ {
+ LOG_FMT(LMCB, "%s(%d): ELSE: orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_pcf_flags(LMCB, pc->GetFlags());
+ size_t level = pc->GetPpLevel();
+ Chunk *a = viz.at(level - 1);
+ pc->SetParent(a);
+ }
+ else if (pc->Is(CT_PP_ENDIF))
+ {
+ LOG_FMT(LMCB, "%s(%d): ENDIF: orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_pcf_flags(LMCB, pc->GetFlags());
+ size_t level = pc->GetPpLevel();
+ Chunk *a = viz.at(level);
+ pc->SetParent(a);
+ viz.pop_back();
+ }
+ pc = pc->GetNextNcNnl();
+ }
+} // do_parent_for_pp
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parent_for_pp.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parent_for_pp.h
new file mode 100644
index 00000000..7e77700a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+#endif /* PARENT_FOR_PP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.cpp
new file mode 100644
index 00000000..f91ecbf4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.cpp
@@ -0,0 +1,256 @@
+/**
+ * @file parsing_frame.cpp
+ *
+ * Holds data needed for indenting and brace parsing
+ *
+ * @author Daniel Chumak
+ * @license GPL v2+
+ */
+
+#include "parsing_frame.h"
+
+#include "chunk.h"
+#include "options.h"
+#include "uncrustify.h"
+
+#include <stdexcept> // to get std::logic_error
+
+
+using std::string;
+using std::to_string;
+using std::invalid_argument;
+
+
+ParenStackEntry::ParenStackEntry()
+{
+ m_openToken = CT_EOF;
+ m_openChunk = Chunk::NullChunkPtr;
+ m_openLevel = 0;
+ m_openLine = 0;
+ m_openCol = 0;
+ m_braceIndent = 0;
+ m_indent = 1;
+ m_indentTmp = 1;
+ m_indentTab = 1;
+ m_nsCount = 0;
+ m_indentContinue = false;
+ m_inPreproc = false;
+ m_nonVardef = false;
+ m_parent = CT_NONE;
+ m_stage = E_BraceStage::NONE;
+ m_indentationData = { Chunk::NullChunkPtr, 0 };
+ m_popChunk = Chunk::NullChunkPtr;
+}
+
+
+ParsingFrame::ParsingFrame()
+{
+ //! amount of elements for which memory is going to be pre-initialized
+ static constexpr int CONTAINER_INIT_SIZE = 16;
+
+ m_parenStack = std::vector<ParenStackEntry>();
+ m_parenStack.reserve(CONTAINER_INIT_SIZE);
+ m_parenStack.push_back(ParenStackEntry());
+
+ m_lastPopped = ParenStackEntry();
+ m_refNumber = 0;
+ m_parenLevel = 0;
+ m_braceLevel = 0;
+ m_ppLevel = 0;
+ m_sParenCount = 0;
+ m_parenCount = 0;
+ m_ifdefType = E_Token::CT_NONE;
+ m_stmtCount = 0;
+ m_exprCount = 0;
+}
+
+
+ParenStackEntry &ParsingFrame::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 >= m_parenStack.size())
+ {
+ LOG_FMT(LINDPSE, "%s(%d): idx is %zu, size is %zu\n",
+ __func__, __LINE__, idx, m_parenStack.size());
+ throw invalid_argument(string(__FILE__) + ":" + to_string(__LINE__)
+ + " idx can't be >= size()");
+ }
+ return(*std::prev(std::end(m_parenStack), idx + 1));
+}
+
+
+const ParenStackEntry &ParsingFrame::prev(size_t idx) const
+{
+ LOG_FUNC_ENTRY();
+ // Reuse the code from non-const method
+ return((const_cast<ParsingFrame *>(this))->prev(idx));
+}
+
+
+ParenStackEntry &ParsingFrame::top()
+{
+ // always at least one (dummy) element inside m_parenStack guaranteed
+ return(*std::prev(std::end(m_parenStack)));
+}
+
+
+const ParenStackEntry &ParsingFrame::top() const
+{
+ // always at least one (dummy) element inside m_parenStack guaranteed
+ return(*std::prev(std::end(m_parenStack)));
+}
+
+
+void ParsingFrame::push(Chunk *pc, const char *func, int line, E_BraceStage stage)
+{
+ LOG_FUNC_ENTRY();
+
+ ParenStackEntry new_entry;
+
+ if (pc->IsNotNullChunk())
+ {
+ new_entry.SetOpenToken(pc->GetType());
+ new_entry.SetOpenLevel(pc->GetLevel());
+ new_entry.SetOpenLine(pc->GetOrigLine());
+ new_entry.SetOpenCol(pc->GetOrigCol());
+ new_entry.SetOpenChunk(pc);
+
+ new_entry.SetIndentTab(top().GetIndentTab());
+ new_entry.SetIndentContinue(top().GetIndentContinue());
+ new_entry.SetStage(stage);
+
+ new_entry.SetInPreproc(pc->TestFlags(PCF_IN_PREPROC));
+ new_entry.SetNonVardef(false);
+ new_entry.IndentData() = top().GetIndentData();
+ new_entry.SetPopChunk(Chunk::NullChunkPtr);
+ }
+ m_parenStack.push_back(new_entry);
+
+// uncomment the line below to get the address of the m_parenStack
+// #define DEBUG_PUSH_POP
+#ifdef DEBUG_PUSH_POP
+ LOG_FMT(LINDPSE, "ParsingFrame::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->GetOrigLine(), pc->GetOrigCol(),
+ get_token_name(pc->GetType()), pc->GetBraceLevel(), pc->GetLevel(),
+ (m_parenStack.size() - 2), (m_parenStack.size() - 1));
+#else /* DEBUG_PUSH_POP */
+ LOG_FMT(LINDPSE, "ParsingFrame::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->GetOrigLine(), pc->GetOrigCol(),
+ get_token_name(pc->GetType()), pc->GetBraceLevel(), pc->GetLevel(),
+ (m_parenStack.size() - 2), (m_parenStack.size() - 1));
+#endif /* DEBUG_PUSH_POP */
+}
+
+
+void ParsingFrame::pop(const char *func, int line, Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( pc->GetType() == CT_ACCESS
+ || pc->GetType() == CT_ANGLE_CLOSE
+ || pc->GetType() == CT_ANGLE_OPEN
+ || pc->GetType() == CT_ARITH // Issue #3965
+ || pc->GetType() == CT_ASSIGN
+ || pc->GetType() == CT_ASSIGN_FUNC_PROTO // Issue #4026
+ || pc->GetType() == CT_BRACE_CLOSE
+ || pc->GetType() == CT_BRACE_OPEN
+ || pc->GetType() == CT_BOOL
+ || pc->GetType() == CT_CASE
+ || pc->GetType() == CT_CLASS_COLON
+ || pc->GetType() == CT_COMMA
+ || pc->GetType() == CT_COMMENT
+ || pc->GetType() == CT_COMMENT_CPP
+ || pc->GetType() == CT_COMMENT_MULTI
+ || pc->GetType() == CT_COMPARE // Issue #3915
+ || pc->GetType() == CT_COND_COLON
+ || pc->GetType() == CT_DC_MEMBER // Issue #4026
+ || pc->GetType() == CT_FPAREN_CLOSE
+ || pc->GetType() == CT_FPAREN_OPEN
+ || pc->GetType() == CT_FUNC_CTOR_VAR // Issue #4026
+ || pc->GetType() == CT_INCDEC_AFTER // Issue #4026
+ || pc->GetType() == CT_LPAREN_CLOSE
+ || pc->GetType() == CT_LPAREN_OPEN
+ || pc->GetType() == CT_MACRO_CLOSE
+ || pc->GetType() == CT_MACRO_FUNC_CALL // Issue #4026
+ || pc->GetType() == CT_MACRO_OPEN
+ || pc->GetType() == CT_MEMBER // Issue #3996
+ || pc->GetType() == CT_NEWLINE
+ || pc->GetType() == CT_NONE
+ || pc->GetType() == CT_OC_END
+ || pc->GetType() == CT_OC_MSG_NAME
+ || pc->GetType() == CT_OC_PROPERTY
+ || pc->GetType() == CT_OC_SCOPE
+ || pc->GetType() == CT_OPERATOR // Issue #4026
+ || pc->GetType() == CT_PARAMETER_PACK // Issue #4075
+ || pc->GetType() == CT_PAREN_CLOSE
+ || pc->GetType() == CT_PAREN_OPEN
+ || pc->GetType() == CT_PREPROC
+ || pc->GetType() == CT_QUESTION // Issue #4023
+ || pc->GetType() == CT_RPAREN_CLOSE // Issue #3914
+ || pc->GetType() == CT_RPAREN_OPEN
+ || pc->GetType() == CT_SBOOL // Issue #3965
+ || pc->GetType() == CT_SEMICOLON
+ || pc->GetType() == CT_SHIFT // Issue #3983
+ || pc->GetType() == CT_SPAREN_CLOSE
+ || pc->GetType() == CT_SPAREN_OPEN
+ || pc->GetType() == CT_SQL_END
+ || pc->GetType() == CT_SQUARE_CLOSE
+ || pc->GetType() == CT_SQUARE_OPEN
+ || pc->GetType() == CT_TPAREN_CLOSE
+ || pc->GetType() == CT_TPAREN_OPEN
+ || pc->GetType() == CT_TYPEDEF
+ || pc->GetType() == CT_VBRACE_CLOSE
+ || pc->GetType() == CT_VBRACE_OPEN
+ || pc->GetType() == CT_VSEMICOLON
+ || pc->GetType() == CT_WORD)
+ {
+ LOG_FMT(LINDPSE, "ParsingFrame::pop (%s:%d): orig line is %4zu, orig col is %4zu, type is %12s\n",
+ func, line, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ }
+ else
+ {
+ fprintf(stderr, "ParsingFrame::pop (%s:%d): orig line is %4zu, orig col is %4zu, type is %12s,\n",
+ func, line, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()));
+ fprintf(stderr, "ParsingFrame::pop (%s:%d): the type is %s, is not coded. Please make a call.\n",
+ func, line, get_token_name(pc->GetType()));
+ log_flush(true);
+
+ if (uncrustify::options::debug_use_the_exit_function_pop()) // Issue #4075
+ {
+ exit(EX_SOFTWARE);
+ }
+ }
+#ifdef DEBUG_PUSH_POP
+ LOG_FMT(LINDPSE, "ParsingFrame::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, m_parenStack.back().open_line, m_parenStack.back().open_colu,
+ get_token_name(m_parenStack.back().type), cpd.pp_level, m_parenStack.back().level,
+ (m_parenStack.size() - 1), (m_parenStack.size() - 2));
+#else /* DEBUG_PUSH_POP */
+ LOG_FMT(LINDPSE, "ParsingFrame::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, m_parenStack.back().GetOpenLine(), m_parenStack.back().GetOpenCol(),
+ get_token_name(m_parenStack.back().GetOpenToken()), cpd.pp_level, m_parenStack.back().GetOpenLevel(),
+ (m_parenStack.size() - 1), (m_parenStack.size() - 2));
+#endif /* DEBUG_PUSH_POP */
+
+ m_lastPopped = *std::prev(std::end(m_parenStack));
+
+ if (m_parenStack.size() == 1)
+ {
+ *std::begin(m_parenStack) = ParenStackEntry();
+ }
+ else
+ {
+ m_parenStack.pop_back();
+ }
+} // ParsingFrame::pop
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.h
new file mode 100644
index 00000000..1431b43d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame.h
@@ -0,0 +1,797 @@
+/**
+ * @file parsing_frame.h
+ *
+ * Holds data needed for indenting and brace parsing
+ *
+ * @author Daniel Chumak
+ * @license GPL v2+
+ */
+
+#ifndef PARSING_FRAME_H_INCLUDED
+#define PARSING_FRAME_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+#include <vector>
+
+
+//! Class describing a parenthesis stack entry and its information
+class ParenStackEntry
+{
+public:
+ ParenStackEntry();
+
+ // --------- Access methods
+
+ /**
+ * @brief returns the token that opened the entry
+ */
+ E_Token GetOpenToken() const;
+
+ /**
+ * @brief Sets the token that opened the entry
+ * @param token the token to set
+ */
+ void SetOpenToken(const E_Token token);
+
+ /**
+ * @brief returns the chunk that opened the entry
+ */
+ Chunk *GetOpenChunk() const;
+
+ /**
+ * @brief Sets the chunk that opened the entry
+ * @param chunk the chunk to set
+ */
+ void SetOpenChunk(Chunk *chunk);
+
+ /**
+ * @brief returns the level that opened the entry
+ */
+ size_t GetOpenLevel() const;
+
+ /**
+ * @brief Sets the level that opened the entry
+ * @param level the level to set
+ */
+ void SetOpenLevel(size_t level);
+
+ /**
+ * @brief returns the line that opened the entry
+ */
+ size_t GetOpenLine() const;
+
+ /**
+ * @brief Sets the line that opened the entry
+ * @param line the line to set
+ */
+ void SetOpenLine(size_t line);
+
+ /**
+ * @brief returns the column that opened the entry
+ */
+ size_t GetOpenCol() const;
+
+ /**
+ * @brief Sets the column that opened the entry
+ * @param column the column to set
+ */
+ void SetOpenCol(size_t column);
+
+ /**
+ * @brief returns the indent for braces
+ */
+ size_t GetBraceIndent() const;
+
+ /**
+ * @brief Sets the indent for braces
+ * @param indent the indent for braces
+ */
+ void SetBraceIndent(size_t indent);
+
+ /**
+ * @brief returns the indent level
+ */
+ size_t GetIndent() const;
+
+ /**
+ * @brief Sets the indent level
+ * @param level the indent level
+ */
+ void SetIndent(size_t level);
+
+ /**
+ * @brief returns the temporary indent level
+ */
+ size_t GetIndentTmp() const;
+
+ /**
+ * @brief Sets the temporary indent level
+ * @param level the temporary indent level
+ */
+ void SetIndentTmp(size_t level);
+
+ /**
+ * @brief returns the tab indent level
+ */
+ size_t GetIndentTab() const;
+
+ /**
+ * @brief Sets the tab indent level
+ * @param level the tab indent level
+ */
+ void SetIndentTab(size_t level);
+
+ /**
+ * @brief returns the consecutive namespace levels
+ */
+ size_t GetNsCount() const;
+
+ /**
+ * @brief Sets the consecutive namespace levels
+ * @param count the consecutive namespace levels
+ */
+ void SetNsCount(size_t count);
+
+ /**
+ * @brief returns whether indent_continue was applied
+ */
+ bool GetIndentContinue() const;
+
+ /**
+ * @brief Sets whether indent_continue was applied
+ * @param cont new value
+ */
+ void SetIndentContinue(bool cont);
+
+ /**
+ * @brief returns whether this was created in a preprocessor
+ */
+ bool GetInPreproc() const;
+
+ /**
+ * @brief Sets whether this was created in a preprocessor
+ * @param preproc new value
+ */
+ void SetInPreproc(bool preproc);
+
+ /**
+ * @brief returns whether a non-vardef line was hit
+ */
+ bool GetNonVardef() const;
+
+ /**
+ * @brief Sets whether a non-vardef line was hit
+ * @param vardef new value
+ */
+ void SetNonVardef(bool vardef);
+
+ /**
+ * @brief returns the parent token (if, for, function, etc)
+ */
+ E_Token GetParent() const;
+
+ /**
+ * @brief Sets the parent token (if, for, function, etc)
+ * @param parent the token to set
+ */
+ void SetParent(const E_Token parent);
+
+ /**
+ * @brief returns the stage used to check progression of complex statements
+ */
+ E_BraceStage GetStage() const;
+
+ /**
+ * @brief Sets the stage used to check progression of complex statements
+ * @param stage the new value
+ */
+ void SetStage(const E_BraceStage stage);
+
+ /**
+ * @brief Returns the associated indentation data as a const reference
+ */
+ const IndentationData &GetIndentData() const;
+
+ /**
+ * @brief Returns the associated indentation data as a modifiable reference
+ */
+ IndentationData &IndentData();
+
+ /**
+ * @brief returns the pop chunk
+ */
+ Chunk *GetPopChunk() const;
+
+ /**
+ * @brief Sets the pop chunk
+ * @param chunk the new chunk
+ */
+ void SetPopChunk(Chunk *chunk);
+
+
+protected:
+ E_Token m_openToken; // the type that opened the entry
+ Chunk *m_openChunk; // chunk that opened the level
+ size_t m_openLevel; // level of opening type
+ size_t m_openLine; // line that open symbol is on, only for logging purposes
+ size_t m_openCol; // column that open symbol is on, only for logging purposes
+ size_t m_braceIndent; // indent for braces - may not relate to indent
+ size_t m_indent; // indent level (depends on use)
+ size_t m_indentTmp; // temporary indent level (depends on use)
+ size_t m_indentTab; // the 'tab' indent (always <= real column)
+ size_t m_nsCount; // Number of consecutive namespace levels
+ bool m_indentContinue; // indent_continue was applied
+ bool m_inPreproc; // whether this was created in a preprocessor
+ bool m_nonVardef; // Hit a non-vardef line
+ E_Token m_parent; // if, for, function, etc
+ E_BraceStage m_stage; // used to check progression of complex statements.
+ IndentationData m_indentationData; // Indentation data
+ Chunk *m_popChunk; // Pop chunk
+};
+
+
+//! Class describing a parsing frame and its information
+class ParsingFrame
+{
+public:
+ ParsingFrame();
+ virtual ~ParsingFrame() = default;
+
+ /**
+ * @brief Returns whether the frame paren stack is empty or not
+ */
+ bool empty() const;
+
+ /**
+ * @brief Returns the size of the frame paren stack
+ */
+ size_t size() const;
+
+ /**
+ * @brief Returns the last popped entry from the frame paren stack
+ */
+ const ParenStackEntry &lastPopped() const;
+
+ /**
+ * @brief Returns the frame reference number
+ */
+ size_t GetRefNumber() const;
+
+ /**
+ * @brief Set the frame reference number
+ * @param the new reference number
+ */
+ void SetRefNumber(const size_t refNo);
+
+ /**
+ * @brief Returns the frame parenthesis level
+ */
+ size_t GetParenLevel() const;
+
+ /**
+ * @brief Set the frame parenthesis level
+ * @param the new parenthesis level
+ */
+ void SetParenLevel(const size_t parenLevel);
+
+ /**
+ * @brief Returns the frame brace level
+ */
+ size_t GetBraceLevel() const;
+
+ /**
+ * @brief Set the frame brace level
+ * @param the new brace level
+ */
+ void SetBraceLevel(const size_t braceLevel);
+
+ /**
+ * @brief Returns the frame preprocessor level
+ */
+ size_t GetPpLevel() const;
+
+ /**
+ * @brief Set the frame preprocessor level
+ * @param the new preprocessor level
+ */
+ void SetPpLevel(const size_t ppLevel);
+
+ /**
+ * @brief Returns the count of special parenthesis
+ */
+ size_t GetSParenCount() const;
+
+ /**
+ * @brief Set the count of special parenthesis
+ * @param the new special parenthesis count value
+ */
+ void SetSParenCount(const size_t sParenCount);
+
+ /**
+ * @brief Returns the count of parenthesis
+ */
+ size_t GetParenCount() const;
+
+ /**
+ * @brief Set the count of parenthesis
+ * @param the new parenthesis count value
+ */
+ void SetParenCount(const size_t parenCount);
+
+ /**
+ * @brief Returns the count of statements
+ */
+ size_t GetStmtCount() const;
+
+ /**
+ * @brief Set the count of statements
+ * @param the new statement count value
+ */
+ void SetStmtCount(const size_t stmtCount);
+
+ /**
+ * @brief Returns the count of statements
+ */
+ size_t GetExprCount() const;
+
+ /**
+ * @brief Set the count of statements
+ * @param the new statement count value
+ */
+ void SetExprCount(const size_t exprCount);
+
+ /**
+ * @brief Returns the ifdef type
+ */
+ E_Token GetIfdefType() const;
+
+ /**
+ * @brief Set the ifdef type
+ * @param the new type
+ */
+ void SetIfdefType(const E_Token inIfdef);
+
+ ParenStackEntry &at(size_t idx);
+ const ParenStackEntry &at(size_t idx) const;
+
+ ParenStackEntry &prev(size_t idx = 1);
+ const ParenStackEntry &prev(size_t idx = 1) const;
+
+ ParenStackEntry &top();
+ const ParenStackEntry &top() const;
+
+ void push(Chunk *pc, const char *func, int line, E_BraceStage stage = E_BraceStage::NONE);
+ void pop(const char *func, int line, Chunk *pc);
+
+ using iterator = std::vector<ParenStackEntry>::iterator;
+ iterator begin();
+ iterator end();
+
+ using const_iterator = std::vector<ParenStackEntry>::const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ using reverse_iterator = std::vector<ParenStackEntry>::reverse_iterator;
+ reverse_iterator rbegin();
+ reverse_iterator rend();
+
+ using const_reverse_iterator = std::vector<ParenStackEntry>::const_reverse_iterator;
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+
+
+protected:
+ // Members
+ std::vector<ParenStackEntry> m_parenStack; //! The parenthesis stack
+ ParenStackEntry m_lastPopped; //! last popped frame or nullptr
+
+ size_t m_refNumber; //! frame reference number
+ size_t m_parenLevel; //! level of parens/square/angle/brace
+ size_t m_braceLevel; //! level of brace/vbrace
+ size_t m_ppLevel; //! level of preproc #if stuff
+ size_t m_sParenCount; //! count of special parenthesis
+ size_t m_parenCount; //! count of parenthesis
+ size_t m_stmtCount; //! count of statements
+ size_t m_exprCount; //! count of expressions
+ E_Token m_ifdefType; //! the ifdef type
+};
+
+
+// ------------------------------
+// ParenStackEntry inline methods
+// ------------------------------
+inline E_Token ParenStackEntry::GetOpenToken() const
+{
+ return(m_openToken);
+}
+
+
+inline void ParenStackEntry::SetOpenToken(const E_Token token)
+{
+ m_openToken = token;
+}
+
+
+inline Chunk *ParenStackEntry::GetOpenChunk() const
+{
+ return(m_openChunk);
+}
+
+
+inline void ParenStackEntry::SetOpenChunk(Chunk *chunk)
+{
+ m_openChunk = chunk;
+}
+
+
+inline size_t ParenStackEntry::GetOpenLevel() const
+{
+ return(m_openLevel);
+}
+
+
+inline void ParenStackEntry::SetOpenLevel(size_t level)
+{
+ m_openLevel = level;
+}
+
+
+inline size_t ParenStackEntry::GetOpenLine() const
+{
+ return(m_openLine);
+}
+
+
+inline void ParenStackEntry::SetOpenLine(size_t line)
+{
+ m_openLine = line;
+}
+
+
+inline size_t ParenStackEntry::GetOpenCol() const
+{
+ return(m_openCol);
+}
+
+
+inline void ParenStackEntry::SetOpenCol(size_t column)
+{
+ m_openCol = column;
+}
+
+
+inline size_t ParenStackEntry::GetBraceIndent() const
+{
+ return(m_braceIndent);
+}
+
+
+inline void ParenStackEntry::SetBraceIndent(size_t indent)
+{
+ m_braceIndent = indent;
+}
+
+
+inline size_t ParenStackEntry::GetIndent() const
+{
+ return(m_indent);
+}
+
+
+inline void ParenStackEntry::SetIndent(size_t level)
+{
+ m_indent = level;
+}
+
+
+inline size_t ParenStackEntry::GetIndentTmp() const
+{
+ return(m_indentTmp);
+}
+
+
+inline void ParenStackEntry::SetIndentTmp(size_t level)
+{
+ m_indentTmp = level;
+}
+
+
+inline size_t ParenStackEntry::GetIndentTab() const
+{
+ return(m_indentTab);
+}
+
+
+inline void ParenStackEntry::SetIndentTab(size_t level)
+{
+ m_indentTab = level;
+}
+
+
+inline size_t ParenStackEntry::GetNsCount() const
+{
+ return(m_nsCount);
+}
+
+
+inline void ParenStackEntry::SetNsCount(size_t count)
+{
+ m_nsCount = count;
+}
+
+
+inline bool ParenStackEntry::GetIndentContinue() const
+{
+ return(m_indentContinue);
+}
+
+
+inline void ParenStackEntry::SetIndentContinue(bool cont)
+{
+ m_indentContinue = cont;
+}
+
+
+inline bool ParenStackEntry::GetInPreproc() const
+{
+ return(m_inPreproc);
+}
+
+
+inline void ParenStackEntry::SetInPreproc(bool preproc)
+{
+ m_inPreproc = preproc;
+}
+
+
+inline bool ParenStackEntry::GetNonVardef() const
+{
+ return(m_nonVardef);
+}
+
+
+inline void ParenStackEntry::SetNonVardef(bool vardef)
+{
+ m_nonVardef = vardef;
+}
+
+
+inline E_Token ParenStackEntry::GetParent() const
+{
+ return(m_parent);
+}
+
+
+inline void ParenStackEntry::SetParent(const E_Token parent)
+{
+ m_parent = parent;
+}
+
+
+inline E_BraceStage ParenStackEntry::GetStage() const
+{
+ return(m_stage);
+}
+
+
+inline void ParenStackEntry::SetStage(const E_BraceStage stage)
+{
+ m_stage = stage;
+}
+
+
+inline const IndentationData &ParenStackEntry::GetIndentData() const
+{
+ return(m_indentationData);
+}
+
+
+inline IndentationData &ParenStackEntry::IndentData()
+{
+ return(m_indentationData);
+}
+
+
+inline Chunk *ParenStackEntry::GetPopChunk() const
+{
+ return(m_popChunk);
+}
+
+
+inline void ParenStackEntry::SetPopChunk(Chunk *chunk)
+{
+ m_popChunk = chunk;
+}
+
+
+// ------------------------------
+// ParsingFrame inline methods
+// ------------------------------
+inline bool ParsingFrame::empty() const
+{
+ return(m_parenStack.empty());
+}
+
+
+inline size_t ParsingFrame::size() const
+{
+ return(m_parenStack.size());
+}
+
+
+inline const ParenStackEntry &ParsingFrame::lastPopped() const
+{
+ return(m_lastPopped);
+}
+
+
+inline size_t ParsingFrame::GetRefNumber() const
+{
+ return(m_refNumber);
+}
+
+
+inline void ParsingFrame::SetRefNumber(const size_t refNo)
+{
+ m_refNumber = refNo;
+}
+
+
+inline size_t ParsingFrame::GetParenLevel() const
+{
+ return(m_parenLevel);
+}
+
+
+inline void ParsingFrame::SetParenLevel(const size_t parenLevel)
+{
+ m_parenLevel = parenLevel;
+}
+
+
+inline size_t ParsingFrame::GetBraceLevel() const
+{
+ return(m_braceLevel);
+}
+
+
+inline void ParsingFrame::SetBraceLevel(const size_t braceLevel)
+{
+ m_braceLevel = braceLevel;
+}
+
+
+inline size_t ParsingFrame::GetPpLevel() const
+{
+ return(m_ppLevel);
+}
+
+
+inline void ParsingFrame::SetPpLevel(const size_t ppLevel)
+{
+ m_ppLevel = ppLevel;
+}
+
+
+inline size_t ParsingFrame::GetSParenCount() const
+{
+ return(m_sParenCount);
+}
+
+
+inline void ParsingFrame::SetSParenCount(const size_t sParenCount)
+{
+ m_sParenCount = sParenCount;
+}
+
+
+inline size_t ParsingFrame::GetParenCount() const
+{
+ return(m_parenCount);
+}
+
+
+inline void ParsingFrame::SetParenCount(const size_t parenCount)
+{
+ m_parenCount = parenCount;
+}
+
+
+inline size_t ParsingFrame::GetStmtCount() const
+{
+ return(m_stmtCount);
+}
+
+
+inline void ParsingFrame::SetStmtCount(const size_t stmtCount)
+{
+ m_stmtCount = stmtCount;
+}
+
+
+inline size_t ParsingFrame::GetExprCount() const
+{
+ return(m_exprCount);
+}
+
+
+inline void ParsingFrame::SetExprCount(const size_t exprCount)
+{
+ m_exprCount = exprCount;
+}
+
+
+inline E_Token ParsingFrame::GetIfdefType() const
+{
+ return(m_ifdefType);
+}
+
+
+inline void ParsingFrame::SetIfdefType(const E_Token inIfdef)
+{
+ m_ifdefType = inIfdef;
+}
+
+
+inline ParenStackEntry &ParsingFrame::at(size_t idx)
+{
+ return(m_parenStack.at(idx));
+}
+
+
+inline const ParenStackEntry &ParsingFrame::at(size_t idx) const
+{
+ return(m_parenStack.at(idx));
+}
+
+
+inline ParsingFrame::iterator ParsingFrame::begin()
+{
+ return(std::begin(m_parenStack));
+}
+
+
+inline ParsingFrame::const_iterator ParsingFrame::begin() const
+{
+ return(std::begin(m_parenStack));
+}
+
+
+inline ParsingFrame::reverse_iterator ParsingFrame::rbegin()
+{
+ return(m_parenStack.rbegin());
+}
+
+
+inline ParsingFrame::const_reverse_iterator ParsingFrame::rbegin() const
+{
+ return(m_parenStack.rbegin());
+}
+
+
+inline ParsingFrame::iterator ParsingFrame::end()
+{
+ return(std::end(m_parenStack));
+}
+
+
+inline ParsingFrame::const_iterator ParsingFrame::end() const
+{
+ return(std::end(m_parenStack));
+}
+
+
+inline ParsingFrame::reverse_iterator ParsingFrame::rend()
+{
+ return(m_parenStack.rend());
+}
+
+
+inline ParsingFrame::const_reverse_iterator ParsingFrame::rend() const
+{
+ return(m_parenStack.rend());
+}
+
+
+#endif /* PARSING_FRAME_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.cpp
new file mode 100644
index 00000000..7a370b16
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.cpp
@@ -0,0 +1,353 @@
+/**
+ * @file parsing_frame_stack.cpp
+ * mainly used to handle preprocessor stuff
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "parsing_frame_stack.h"
+
+#include "prototypes.h"
+
+
+namespace
+{
+
+typedef std::vector<ParsingFrame> ParsingFrameOrigStack;
+
+void fl_log_frms(log_sev_t logsev, const char *txt, const ParsingFrame &frm, const ParsingFrameOrigStack &frames);
+
+
+//! Logs the entire parse frame stack
+void fl_log_all(log_sev_t logsev, const ParsingFrameOrigStack &frames);
+
+
+/**
+ * Copy the top element of the frame list into the ParsingFrame.
+ *
+ * If the frame list is empty nothing happens.
+ *
+ * This is called on #else and #elif.
+ */
+void fl_copy_tos(ParsingFrame &pf, const ParsingFrameOrigStack &frames);
+
+
+/**
+ * Copy the 2nd top element off the list into the ParsingFrame.
+ * 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(ParsingFrame &pf, const ParsingFrameOrigStack &frames);
+
+
+//! Deletes the top element from the list.
+void fl_trash_tos(ParsingFrameOrigStack &frames);
+
+
+//! Logs one parse frame
+void fl_log(log_sev_t logsev, const ParsingFrame &frm)
+{
+ LOG_FMT(logsev, "[%s] Brace level=%zu Paren level=%zu PseTos=%zu\n",
+ get_token_name(frm.GetIfdefType()), frm.GetBraceLevel(), frm.GetParenLevel(), 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).GetOpenToken()),
+ get_brace_stage_name(frm.at(idx).GetStage()));
+ }
+
+ LOG_FMT(logsev, "\n");
+}
+
+
+void fl_log_frms(log_sev_t logsev,
+ const char *txt,
+ const ParsingFrame &frm,
+ const ParsingFrameOrigStack &frames)
+{
+ LOG_FMT(logsev, "%s Parse Frames(%zu):", txt, frames.size());
+
+ for (const auto &frame : frames)
+ {
+ LOG_FMT(logsev, " [%s-%zu]", get_token_name(frame.GetIfdefType()),
+ frame.GetRefNumber());
+ }
+
+ LOG_FMT(logsev, "-[%s-%zu]\n", get_token_name(frm.GetIfdefType()), frm.GetRefNumber());
+}
+
+
+void fl_log_all(log_sev_t logsev, const ParsingFrameOrigStack &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(ParsingFrame &pf, const ParsingFrameOrigStack &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(ParsingFrame &pf, const ParsingFrameOrigStack &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(ParsingFrameOrigStack &frames)
+{
+ if (!frames.empty())
+ {
+ frames.pop_back();
+ }
+ LOG_FMT(LPF, "%s(%d): frame_count is %zu\n", __func__, __LINE__, frames.size());
+}
+
+} // namespace
+
+
+ParsingFrameStack::ParsingFrameStack()
+ : m_frames()
+{
+}
+
+
+void ParsingFrameStack::push(ParsingFrame &frm)
+{
+ static int seq_ref_no = 1;
+
+ m_frames.push_back(frm);
+ frm.SetRefNumber(seq_ref_no++);
+
+ LOG_FMT(LPF, "%s(%d): frame_count is %zu\n", __func__, __LINE__, m_frames.size());
+}
+
+
+void ParsingFrameStack::pop(ParsingFrame &pf)
+{
+ if (m_frames.empty())
+ {
+ return;
+ }
+ fl_copy_tos(pf, m_frames);
+ fl_trash_tos(m_frames);
+}
+
+
+int ParsingFrameStack::check(ParsingFrame &frm, int &pp_level, Chunk *pc)
+{
+ if (pc->IsNot(CT_PREPROC))
+ {
+ return(pp_level);
+ }
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNullChunk())
+ {
+ return(pp_level);
+ }
+
+ if (pc->GetParentType() != next->GetType())
+ {
+ LOG_FMT(LNOTE, "%s(%d): Preproc parent not set correctly on orig line %zu: got %s expected %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), get_token_name(pc->GetParentType()),
+ get_token_name(next->GetType()));
+ pc->SetParentType(next->GetType());
+ }
+ LOG_FMT(LPFCHK, "%s(%d): orig line is %zu, %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), get_token_name(pc->GetParentType()));
+ fl_log_frms(LPFCHK, "TOP", frm, m_frames);
+
+
+ int out_pp_level = pp_level;
+ const E_Token in_ifdef = frm.GetIfdefType();
+ const size_t b4_cnt = m_frames.size();
+
+ const char *txt = nullptr;
+
+ if (pc->TestFlags(PCF_IN_PREPROC))
+ {
+ LOG_FMT(LPF, " <In> ");
+ fl_log(LPF, frm);
+
+ if (pc->GetParentType() == CT_PP_IF)
+ {
+ // An #if pushes a copy of the current frame on the stack
+ pp_level++;
+ push(frm);
+ frm.SetIfdefType(CT_PP_IF);
+ txt = "if-push";
+ }
+ else if (pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol());
+ 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.GetIfdefType() == CT_PP_IF)
+ {
+ // we have [...] [base]-[if], so push an [else]
+ push(frm);
+ frm.SetIfdefType(CT_PP_ELSE);
+ if_block = true;
+ }
+ size_t brace_level = frm.GetBraceLevel();
+ // we have [...] [base] [if]-[else], copy [base] over [else]
+ fl_copy_2nd_tos(frm, m_frames);
+ frm.SetIfdefType(CT_PP_ELSE);
+
+ if (if_block)
+ {
+ // check if #if block was unbalanced
+ size_t base_brace_level = m_frames[m_frames.size() - 2].GetBraceLevel();
+
+ 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->GetOrigLine(), 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 = m_frames[m_frames.size() - 1].GetBraceLevel();
+
+ 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->GetOrigLine(), brace_level, if_brace_level);
+ }
+ }
+ txt = "else-push";
+ }
+ else if (pc->GetParentType() == 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->GetOrigLine(), pc->GetOrigCol());
+ 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->GetOrigLine(), pc->GetOrigCol());
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ out_pp_level--;
+
+ if (frm.GetIfdefType() == CT_PP_ELSE)
+ {
+ size_t brace_level = frm.GetBraceLevel(); // brace level or current #else block
+ /*
+ * We have: [...] [base] [if]-[else]
+ * We want: [...]-[if]
+ */
+ fl_copy_tos(frm, m_frames); // [...] [base] [if]-[if]
+
+ if ( options::pp_warn_unbalanced_if()
+ && brace_level != frm.GetBraceLevel())
+ {
+ 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->GetOrigLine(), brace_level, frm.GetBraceLevel());
+ }
+
+ if (m_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.SetIfdefType(m_frames[m_frames.size() - 2].GetIfdefType());
+ fl_trash_tos(m_frames); // [...] [base]-[if]
+ fl_trash_tos(m_frames); // [...]-[if]
+
+ txt = "endif-trash/pop";
+ }
+ else if (frm.GetIfdefType() == CT_PP_IF)
+ {
+ /*
+ * We have: [...] [base] [if]
+ * We want: [...] [base]
+ */
+ // check if #if block was unbalanced
+ size_t brace_level = frm.GetBraceLevel();
+ pop(frm);
+
+ if ( options::pp_warn_unbalanced_if()
+ && brace_level != frm.GetBraceLevel())
+ {
+ 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->GetOrigLine(), frm.GetBraceLevel(), brace_level);
+ }
+ txt = "endif-pop";
+ }
+ else
+ {
+ txt = "???";
+ }
+ }
+ }
+
+ if (txt != nullptr)
+ {
+ LOG_FMT(LPF, "%s(%d): orig line is %zu, type is %s: %s ifdef token is %s/%s, counts is %zu, frame_count is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(),
+ get_token_name(pc->GetParentType()), txt, get_token_name(in_ifdef),
+ get_token_name(frm.GetIfdefType()), b4_cnt, m_frames.size());
+ fl_log_all(LPF, m_frames);
+ LOG_FMT(LPF, " <Out>");
+ fl_log(LPF, frm);
+ }
+ fl_log_frms(LPFCHK, "END", frm, m_frames);
+
+ return(out_pp_level);
+} // check
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.h
new file mode 100644
index 00000000..0cc908dc
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/parsing_frame_stack.h
@@ -0,0 +1,43 @@
+/**
+ * @file parsing_frame_stack.h
+ * mainly used to handle preprocessor stuff
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef PARSING_FRAME_STACK_H_INCLUDED
+#define PARSING_FRAME_STACK_H_INCLUDED
+
+#include "parsing_frame.h"
+
+//! Class describing a parsing frame stack
+class ParsingFrameStack
+{
+public:
+ ParsingFrameStack();
+
+ /**
+ * Push a copy of a ParsingFrame onto the frame stack.
+ */
+ void push(ParsingFrame &frm);
+
+
+ /**
+ * Pop and return the top element of the frame stack.
+ * TODO: return the frame rather than passing it as argument
+ */
+ void pop(ParsingFrame &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 check(ParsingFrame &frm, int &pp_level, Chunk *pc);
+
+private:
+ std::vector<ParsingFrame> m_frames;
+};
+
+#endif /* PARSING_FRAME_STACK_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pcf_flags.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pcf_flags.cpp
new file mode 100644
index 00000000..1b8722e4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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
+ "NOT_POSSIBLE", // 47
+ "IN_CONDITIONAL", // 48 Issue #3558
+ "OC_IN_BLOCK", // 49
+ "CONT_LINE", // 50
+};
+
+
+std::string pcf_flags_str(PcfFlags flags)
+{
+ char buffer[64];
+
+ // Generate hex representation first
+ snprintf(buffer, 63, "[0x%llx:", (long long unsigned int)(flags));
+
+ // 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<E_PcfFlag>(pcf_bit(i)))
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ out += ',';
+ }
+ out += pcf_names[i];
+ }
+ }
+
+ out += ']';
+ return(out);
+}
+
+
+void log_pcf_flags(log_sev_t sev, PcfFlags flags)
+{
+ if (!log_sev_on(sev))
+ {
+ return;
+ }
+ log_fmt(sev, " chunk flags: %s\n", pcf_flags_str(flags).c_str());
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pcf_flags.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pcf_flags.h
new file mode 100644
index 00000000..7f09edb1
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pcf_flags.h
@@ -0,0 +1,100 @@
+/**
+ * @file pcf_flags.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef PCF_FLAGS_STR_INCLUDED
+#define PCF_FLAGS_STR_INCLUDED
+
+#include "base_types.h"
+#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 E_PcfFlag : 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
+ PCF_IN_CONDITIONAL = pcf_bit(48), //! inside a conditional ternary expression
+ PCF_OC_IN_BLOCK = pcf_bit(49), //! inside OC block function
+ PCF_CONT_LINE = pcf_bit(50), //! continuation line split
+};
+
+UNC_DECLARE_FLAGS(PcfFlags, E_PcfFlag);
+UNC_DECLARE_OPERATORS_FOR_FLAGS(PcfFlags);
+
+std::string pcf_flags_str(PcfFlags flags);
+
+
+void log_pcf_flags(log_sev_t sev, PcfFlags flags);
+
+
+#endif /* PCF_FLAGS_STR_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.cpp
new file mode 100644
index 00000000..336a1272
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.cpp
@@ -0,0 +1,98 @@
+/**
+ * @file pragma_cleanup.cpp
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#include "pragma_cleanup.h"
+
+#include "chunk.h"
+#include "unc_tools.h"
+
+
+void pragma_cleanup()
+{
+ LOG_FUNC_ENTRY();
+
+ bool preproc_found = false;
+ bool pragma_found = false;
+ bool parameter_found = false;
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ LOG_CHUNK(LTOK, pc);
+
+ if (!preproc_found)
+ {
+ if (pc->Is(CT_PREPROC))
+ {
+ LOG_FMT(LMCB, "%s(%d): PREPROC found: orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_pcf_flags(LMCB, pc->GetFlags());
+ preproc_found = true;
+ }
+ }
+ else
+ {
+ if (!pragma_found)
+ {
+ if (pc->Is(CT_PP_PRAGMA))
+ {
+ LOG_FMT(LMCB, "%s(%d): PP_PRAGMA found: orig line %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol());
+ log_pcf_flags(LMCB, pc->GetFlags());
+ pragma_found = true;
+ }
+ }
+ else
+ {
+ if (!parameter_found)
+ {
+ LOG_FMT(LMCB, "%s(%d): PARAMETER found: orig line %zu, orig col is %zu, Text is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ log_pcf_flags(LMCB, pc->GetFlags());
+
+ if (strcmp(pc->Text(), "endasm") == 0)
+ {
+ pc->SetType(CT_PP_ENDASM);
+ }
+ else if (strcmp(pc->Text(), "region") == 0)
+ {
+ pc->SetType(CT_PP_REGION);
+ }
+ //else if (strcmp(pc->Text(), "comment") == 0)
+ //{
+ // pc->SetType(CT_PP_COMMENT);
+ //}
+ else
+ {
+ pc->SetType(CT_PP_PRAGMA);
+ }
+ parameter_found = true;
+ }
+ else
+ {
+ LOG_FMT(LMCB, "%s(%d): orig line is %zu, orig col is %zu, Text is '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+
+ if (pc->IsNewline())
+ {
+ // reset
+ preproc_found = false;
+ pragma_found = false;
+ parameter_found = false;
+ }
+ else
+ {
+ pc->SetType(CT_PP_IGNORE);
+ }
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+ //prot_the_line(__func__, __LINE__, 3, 0);
+} // pragma_cleanup
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.h
new file mode 100644
index 00000000..47a3a03d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/pragma_cleanup.h
@@ -0,0 +1,16 @@
+/**
+ * @file pragma_cleanup.h
+ *
+ * @author Guy Maurel
+ * @license GPL v2+
+ */
+
+#ifndef PRAGMA_CLEANUP_H_INCLUDED
+#define PRAGMA_CLEANUP_H_INCLUDED
+
+
+// cleanup the pagma line(s)
+void pragma_cleanup();
+
+
+#endif /* PRAGMA_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/prototypes.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/prototypes.h
new file mode 100644
index 00000000..55fe35b6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/punctuators.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/punctuators.cpp
new file mode 100644
index 00000000..1d1aab3d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/punctuators.cpp
@@ -0,0 +1,86 @@
+/**
+ * @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
+ * Automatically generated by <code>scripts/make_punctuator_table.py</code>
+ *
+ * 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.78.0/src/punctuators.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/punctuators.h
new file mode 100644
index 00000000..ed4c3fa5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/quick_align_again.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/quick_align_again.cpp
new file mode 100644
index 00000000..640abba9
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->GetColumn(), pc->ElidedText(copy));
+
+ if ( pc->GetAlignData().next->IsNotNullChunk()
+ && pc->TestFlags(PCF_ALIGN_START))
+ {
+ AlignStack as;
+ as.Start(100, 0);
+ as.m_right_align = pc->GetAlignData().right_align;
+ as.m_star_style = static_cast<AlignStack::StarStyle>(pc->GetAlignData().star_style);
+ as.m_amp_style = static_cast<AlignStack::StarStyle>(pc->GetAlignData().amp_style);
+ as.m_gap = pc->GetAlignData().gap;
+
+ LOG_FMT(LALAGAIN, "%s(%d): pc->Text() is '%s', orig line is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine());
+ as.Add(pc->GetAlignData().start);
+ pc->SetFlagBits(PCF_WAS_ALIGNED);
+
+ for (Chunk *tmp = pc->GetAlignData().next; tmp->IsNotNullChunk(); tmp = tmp->GetAlignData().next)
+ {
+ tmp->SetFlagBits(PCF_WAS_ALIGNED);
+ as.Add(tmp->GetAlignData().start);
+ LOG_FMT(LALAGAIN, "%s(%d): => tmp->Text() is '%s', orig line is %zu\n",
+ __func__, __LINE__, tmp->Text(), tmp->GetOrigLine());
+ }
+
+ LOG_FMT(LALAGAIN, "\n");
+ as.End();
+ }
+ }
+} // quick_align_again
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/quick_align_again.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/quick_align_again.h
new file mode 100644
index 00000000..c370c612
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+#endif /* QUICK_ALIGN_AGAIN_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_duplicate_include.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_duplicate_include.cpp
new file mode 100644
index 00000000..e06029f1
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(),
+ // get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ if (pc->Is(CT_PREPROC))
+ {
+ preproc = pc;
+ }
+ else if (pc->Is(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->GetOrigLine(), next->GetOrigCol(), next->Text(),
+ // get_token_name(next->GetType()), get_token_name(next->GetParentType()));
+ 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::Delete(preproc);
+ Chunk::Delete(temp);
+ Chunk::Delete(next);
+
+ if (comment != eol)
+ {
+ Chunk::Delete(comment);
+ }
+ Chunk::Delete(eol);
+ break;
+ }
+ else
+ {
+ // goto next newline
+ pc = next->GetNextNl();
+ // and still look for duplicate
+ }
+ } // for (auto itc = includes.begin();
+ } // if (includes.empty())
+ } // else if (pc->Is(CT_PP_INCLUDE))
+ // get the next token
+ pc = pc->GetNext();
+ }
+} // remove_duplicate_include
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_duplicate_include.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_duplicate_include.h
new file mode 100644
index 00000000..c58416c2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+#endif /* REMOVE_DUPLICATE_INCLUDE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_extra_returns.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_extra_returns.cpp
new file mode 100644
index 00000000..221e97b4
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_extra_returns.cpp
@@ -0,0 +1,87 @@
+/**
+ * @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()
+{
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->Text(),
+ get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ if ( pc->Is(CT_RETURN)
+ && !pc->TestFlags(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->GetOrigLine(), pc->GetLevel());
+
+ if (closing_brace->IsNotNullChunk())
+ {
+ if (closing_brace->GetParentType() == CT_FUNC_CLASS_DEF)
+ {
+ // we have a class. Do nothing
+ }
+ else if ( closing_brace->GetParentType() == CT_FUNC_DEF
+ && pc->GetLevel() < 2)
+ {
+ remove_it = true;
+ }
+ }
+ else
+ {
+ // it is not a class
+ // look for a closing brace
+ // make sure we are at level 1 because 'return' could
+ // be part of nested 'if' blocks
+ closing_brace = pc->GetNextType(CT_BRACE_CLOSE, 0);
+ LOG_FMT(LRMRETURN, "%s(%d): on orig line %zu, level is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetLevel());
+
+ if (closing_brace->IsNotNullChunk())
+ {
+ if ( closing_brace->GetParentType() == CT_FUNC_DEF
+ && pc->GetLevel() < 2)
+ {
+ remove_it = true;
+ }
+ }
+ }
+
+ if (remove_it)
+ {
+ Chunk *semicolon = pc->GetNextNcNnl();
+
+ if ( semicolon->IsNotNullChunk()
+ && semicolon->Is(CT_SEMICOLON))
+ {
+ LOG_FMT(LRMRETURN, "%s(%d): Removed 'return;' on orig line %zu\n",
+ __func__, __LINE__, pc->GetOrigLine());
+ Chunk::Delete(pc);
+ Chunk::Delete(semicolon);
+ pc = closing_brace;
+ }
+ }
+ }
+ pc = pc->GetNext();
+ }
+} // remove_extra_returns
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_extra_returns.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/remove_extra_returns.h
new file mode 100644
index 00000000..85fc6429
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+#endif /* REMOVE_EXTRA_RETURNS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.cpp
new file mode 100644
index 00000000..6b97ea7d
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.cpp
@@ -0,0 +1,345 @@
+/**
+ * @file rewrite_infinite_loops.cpp
+ *
+ * @author Alex Henrie
+ * @license GPL v2+
+ */
+
+#include "rewrite_infinite_loops.h"
+
+#include "chunk.h"
+#include "newlines.h"
+#include "uncrustify.h"
+
+
+using namespace uncrustify;
+
+
+static bool for_needs_rewrite(Chunk *pc, E_Token desired_type)
+{
+ // The 'for' statement needs to be rewritten if `for(;;)` is not the
+ // preferred syntax for infinite loops and this 'for' is an infinite loop
+ // with no extra tokens (such as inline comments).
+
+ if (desired_type == CT_FOR)
+ {
+ return(false);
+ }
+ pc = pc->GetNext();
+
+ if (!pc->Is(CT_SPAREN_OPEN))
+ {
+ return(false);
+ }
+ pc = pc->GetNext();
+
+ if (!pc->Is(CT_SEMICOLON))
+ {
+ return(false);
+ }
+ pc = pc->GetNext();
+
+ if (!pc->Is(CT_SEMICOLON))
+ {
+ return(false);
+ }
+ pc = pc->GetNext();
+
+ if (!pc->Is(CT_SPAREN_CLOSE))
+ {
+ return(false);
+ }
+ return(true);
+}
+
+
+static bool while_needs_rewrite(Chunk *keyword, E_Token desired_type, const char *desired_condition)
+{
+ // The 'while' statement needs to be rewritten if it has only the tokens that
+ // are strictly necessary (keyword, condition, two parentheses, and semicolon
+ // if do-while) and either the keyword or the condition needs to be changed.
+
+ Chunk *oparen = keyword->GetNext();
+ Chunk *condition = oparen->GetNext();
+ Chunk *cparen = condition->GetNext();
+
+ if (!oparen->Is(CT_SPAREN_OPEN))
+ {
+ return(false);
+ }
+
+ if ( strcmp(condition->Text(), "true") != 0
+ && strcmp(condition->Text(), "1") != 0)
+ {
+ return(false);
+ }
+
+ if (!cparen->Is(CT_SPAREN_CLOSE))
+ {
+ return(false);
+ }
+
+ if (keyword->Is(CT_WHILE_OF_DO))
+ {
+ Chunk *semicolon = cparen->GetNext();
+
+ if (!semicolon->Is(CT_SEMICOLON))
+ {
+ return(false);
+ }
+ }
+
+ if (!keyword->Is(desired_type))
+ {
+ return(true);
+ }
+
+ if ( strcmp(condition->Text(), "true") == 0
+ && strcmp(desired_condition, "true") != 0)
+ {
+ return(true);
+ }
+
+ if ( strcmp(condition->Text(), "1") == 0
+ && strcmp(desired_condition, "1") != 0)
+ {
+ return(true);
+ }
+ return(false);
+} // while_needs_rewrite
+
+
+void rewrite_loop_keyword(Chunk *keyword, E_Token new_type)
+{
+ keyword->SetType(new_type);
+
+ switch (new_type)
+ {
+ case CT_DO:
+ keyword->SetOrigColEnd(keyword->GetOrigColEnd() + strlen("do") - keyword->Len());
+ keyword->Str() = "do";
+ break;
+
+ case CT_WHILE:
+ case CT_WHILE_OF_DO:
+ keyword->SetOrigColEnd(keyword->GetOrigColEnd() + strlen("while") - keyword->Len());
+ keyword->Str() = "while";
+ break;
+
+ case CT_FOR:
+ keyword->SetOrigColEnd(keyword->GetOrigColEnd() + strlen("for") - keyword->Len());
+ keyword->Str() = "for";
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+static void move_one_token(Chunk * &source, Chunk * &destination, E_Token parent_type)
+{
+ Chunk *next_source = source->GetNext();
+
+ // Place the source token immediately after the destination token, without
+ // any whitespace.
+
+ source->MoveAfter(destination);
+ source->SetColumn(destination->GetColumn() + destination->Len());
+ source->SetOrigCol(destination->GetOrigCol() + destination->Len());
+ source->SetOrigColEnd(source->GetOrigColEnd() + source->Len());
+ source->SetOrigPrevSp(0);
+ source->SetParentType(parent_type);
+
+ destination = source;
+ source = next_source;
+}
+
+
+static void rewrite_loop_condition(Chunk * &source, Chunk * &destination,
+ E_Token desired_type, const char *desired_condition)
+{
+ // Move the opening parenthesis
+ move_one_token(source, destination, desired_type);
+
+ // Move the condition
+ if (desired_type == CT_FOR)
+ {
+ source->SetType(CT_SEMICOLON);
+ source->SetParentType(CT_FOR);
+ source->Str() = ";";
+ move_one_token(source, destination, desired_type);
+ destination = (destination)->CopyAndAddAfter(destination);
+ }
+ else
+ {
+ source->SetType(CT_WORD);
+ source->Str() = desired_condition;
+ move_one_token(source, destination, desired_type);
+ }
+
+ // If converting a 'for' to a 'while', delete the second semicolon
+ if (source->Is(CT_SEMICOLON))
+ {
+ Chunk *next_source = source->GetNext();
+ Chunk::Delete(source);
+ source = next_source;
+ }
+ // Move the closing parenthesis
+ move_one_token(source, destination, desired_type);
+}
+
+
+void rewrite_loop_in_place(Chunk *keyword, E_Token desired_type, const char *desired_condition)
+{
+ Chunk *top = keyword->GetNext();
+ Chunk *bottom = keyword;
+
+ rewrite_loop_keyword(keyword, desired_type);
+ rewrite_loop_condition(top, bottom, desired_type, desired_condition);
+}
+
+
+static Chunk *find_start_brace(Chunk *pc)
+{
+ while (!pc->IsBraceOpen())
+ {
+ pc = pc->GetNextNcNnl();
+ }
+ return(pc);
+}
+
+
+void rewrite_infinite_loops()
+{
+ LOG_FUNC_ENTRY();
+
+ E_Token desired_type;
+ const char *desired_condition;
+
+ switch (options::mod_infinite_loop())
+ {
+ case 1: // for(;;)
+ desired_type = CT_FOR;
+ desired_condition = nullptr;
+ break;
+
+ case 2: // while(true)
+ desired_type = CT_WHILE;
+ desired_condition = "true";
+ break;
+
+ case 3: // do...while(true)
+ desired_type = CT_WHILE_OF_DO;
+ desired_condition = "true";
+ break;
+
+ case 4: // while(1)
+ desired_type = CT_WHILE;
+ desired_condition = "1";
+ break;
+
+ case 5: // do...while(1)
+ desired_type = CT_WHILE_OF_DO;
+ desired_condition = "1";
+ break;
+
+ default:
+ return;
+ }
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (pc->Is(CT_DO))
+ {
+ Chunk *start_brace = find_start_brace(pc);
+ Chunk *end_brace = start_brace->GetClosingParen();
+ Chunk *while_keyword = end_brace->GetNextNcNnl();
+
+ if ( !while_keyword->Is(CT_WHILE_OF_DO)
+ || !while_needs_rewrite(while_keyword, desired_type, desired_condition))
+ {
+ continue;
+ }
+
+ if (desired_type == CT_WHILE_OF_DO)
+ {
+ // Change the loop condition
+ rewrite_loop_in_place(while_keyword, desired_type, desired_condition);
+
+ // Update the braces' parent types
+ start_brace->SetParentType(CT_DO);
+ end_brace->SetParentType(CT_DO);
+ }
+ else
+ {
+ Chunk *top = pc;
+ Chunk *bottom = while_keyword->GetNext();
+
+ // Change the 'do' at the top of the loop to a 'for' or a 'while'
+ rewrite_loop_keyword(top, desired_type);
+
+ // Delete the 'while' at the bottom of the loop
+ Chunk::Delete(while_keyword);
+
+ // Move the rest of the tokens from the bottom to the top
+ rewrite_loop_condition(bottom, top, desired_type, desired_condition);
+
+ // Delete the final semicolon
+ Chunk::Delete(bottom);
+
+ // Update the braces' parent types
+ start_brace->SetParentType(desired_type);
+ end_brace->SetParentType(desired_type);
+ }
+ }
+ else if ( ( pc->Is(CT_WHILE)
+ && while_needs_rewrite(pc, desired_type, desired_condition))
+ || ( pc->Is(CT_FOR)
+ && for_needs_rewrite(pc, desired_type)))
+ {
+ Chunk *start_brace = find_start_brace(pc);
+ Chunk *end_brace = start_brace->GetClosingParen();
+
+ if (desired_type == CT_WHILE_OF_DO)
+ {
+ Chunk *top = pc;
+ Chunk *bottom = end_brace;
+
+ if (bottom->Is(CT_VBRACE_CLOSE))
+ {
+ // Insert a new line before the new 'while' keyword
+ newline_add_before(bottom);
+ }
+ // Add a 'while' at the bottom of the loop
+ bottom = top->CopyAndAddAfter(bottom);
+ rewrite_loop_keyword(bottom, CT_WHILE_OF_DO);
+
+ // Change the 'while' at the top of the loop to a 'do'
+ rewrite_loop_keyword(top, CT_DO);
+ top = top->GetNext();
+
+ // Move the tokens from the top to the bottom
+ rewrite_loop_condition(top, bottom, desired_type, desired_condition);
+
+ // Add the final semicolon
+ bottom = bottom->CopyAndAddAfter(bottom);
+ bottom->SetType(CT_SEMICOLON);
+ bottom->Str() = ";";
+
+ // Update the braces' parent types
+ start_brace->SetParentType(CT_DO);
+ end_brace->SetParentType(CT_DO);
+ }
+ else
+ {
+ // Change 'for' to 'while' or vice-versa
+ rewrite_loop_in_place(pc, desired_type, desired_condition);
+
+ // Update the braces' parent types
+ start_brace->SetParentType(desired_type);
+ end_brace->SetParentType(desired_type);
+ }
+ }
+ }
+} // rewrite_infinite_loops
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.h
new file mode 100644
index 00000000..5b8f3fee
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/rewrite_infinite_loops.h
@@ -0,0 +1,19 @@
+/**
+ * @file rewrite_infinite_loops.h
+ * prototypes for rewrite_infinite_loops.cpp
+ *
+ * @author Alex Henrie
+ * @license GPL v2+
+ */
+
+#ifndef REWRITE_INFINITE_LOOPS_H_INCLUDED
+#define REWRITE_INFINITE_LOOPS_H_INCLUDED
+
+
+/**
+ * @brief Rewrite infinite loops in a consistent syntax
+ */
+void rewrite_infinite_loops();
+
+
+#endif /* REWRITE_INFINITE_LOOPS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.cpp
new file mode 100644
index 00000000..569f5271
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.cpp
@@ -0,0 +1,151 @@
+/**
+ * @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->GetOrigLine(), pc->GetOrigCol());
+ log_func_stack_inline(LDELSEMI);
+ // TODO: do we want to shift stuff back a column?
+ Chunk::Delete(pc);
+}
+
+
+void remove_extra_semicolons()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+
+ while (pc->IsNotNullChunk())
+ {
+ Chunk *next = pc->GetNextNcNnl();
+ Chunk *prev;
+
+ if ( pc->Is(CT_SEMICOLON)
+ && !pc->TestFlags(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->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetParentType()),
+ prev->Text(),
+ get_token_name(prev->GetType()), get_token_name(prev->GetParentType()));
+
+ if (pc->GetParentType() == CT_TYPEDEF)
+ {
+ // keep it
+ }
+ else if ( prev->Is(CT_BRACE_CLOSE)
+ && ( prev->GetParentType() == CT_ELSE
+ || prev->GetParentType() == CT_ELSEIF
+ || prev->GetParentType() == CT_FOR
+ || prev->GetParentType() == CT_FUNC_CLASS_DEF
+ || prev->GetParentType() == CT_FUNC_DEF
+ || prev->GetParentType() == CT_IF
+ || prev->GetParentType() == CT_NAMESPACE
+ || prev->GetParentType() == CT_OC_MSG_DECL
+ || prev->GetParentType() == CT_SWITCH
+ || prev->GetParentType() == CT_USING_STMT
+ || prev->GetParentType() == CT_WHILE))
+ {
+ // looking for code block vs. initialisation
+ bool code_block_found = true;
+ Chunk *closing_brace = pc->GetPrevNcNnl(); // Issue #3506
+
+ if (closing_brace->IsNotNullChunk())
+ {
+ Chunk *opening_brace = closing_brace->GetOpeningParen();
+
+ if (opening_brace->IsNotNullChunk())
+ {
+ Chunk *equal_sign = opening_brace->GetPrevNcNnl();
+
+ if ( equal_sign->IsNotNullChunk()
+ && equal_sign->Is(CT_ASSIGN))
+ {
+ // initialisation found
+ code_block_found = false;
+ }
+ }
+ }
+
+ if (code_block_found)
+ {
+ // code block found
+ remove_semicolon(pc);
+ }
+ }
+ else if ( prev->Is(CT_BRACE_CLOSE)
+ && prev->GetParentType() == CT_NONE)
+ {
+ check_unknown_brace_close(pc, prev);
+ }
+ else if ( prev->Is(CT_SEMICOLON)
+ && prev->GetParentType() != CT_FOR)
+ {
+ remove_semicolon(pc);
+ }
+ else if ( language_is_set(LANG_D)
+ && ( prev->GetParentType() == CT_ENUM
+ || prev->GetParentType() == CT_STRUCT
+ || prev->GetParentType() == CT_UNION))
+ {
+ remove_semicolon(pc);
+ }
+ else if ( language_is_set(LANG_JAVA)
+ && prev->GetParentType() == CT_SYNCHRONIZED)
+ {
+ remove_semicolon(pc);
+ }
+ else if (prev->Is(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->GetLevel());
+
+ pc = pc->GetPrevNcNnl();
+
+ if ( pc->IsNotNullChunk()
+ && pc->IsNot(CT_ANGLE_CLOSE)
+ && pc->IsNot(CT_COND_COLON) // Issue #3920
+ && pc->IsNot(CT_RETURN)
+ && pc->IsNot(CT_SQUARE_CLOSE)
+ && pc->IsNot(CT_TSQUARE)
+ && pc->IsNot(CT_TYPE)
+ && pc->IsNot(CT_WORD)
+ && !pc->IsParenClose())
+ {
+ remove_semicolon(semi);
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.h
new file mode 100644
index 00000000..60839e67
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/semicolons.h
@@ -0,0 +1,26 @@
+/**
+ * @file semicolons.h
+ * prototypes for semicolons.cpp
+ *
+ * @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();
+
+
+#endif /* SEMICOLONS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/sorting.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/sorting.cpp
new file mode 100644
index 00000000..807e0739
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/sorting.cpp
@@ -0,0 +1,709 @@
+/**
+ * @file sorting.cpp
+ * Sorts chunks and imports
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#include "sorting.h"
+
+#include "newlines.h"
+#include "prototypes.h"
+
+#include <regex>
+#include <unordered_map>
+
+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];
+unordered_map<Chunk *, int> chunk_priority_cache;
+unordered_map<std::string, bool> filename_without_ext_cache;
+
+
+/**
+ * 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);
+
+
+/**
+ * Sort all of the chunks in O(n log n) time with a maximum of O(n) swaps
+ */
+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()
+{
+ chunk_priority_cache.clear();
+ filename_without_ext_cache.clear();
+
+ for (auto &include_category : include_categories)
+ {
+ if (include_category == nullptr)
+ {
+ continue;
+ }
+ delete include_category;
+ include_category = NULL;
+ }
+}
+
+
+static int get_chunk_priority(Chunk *pc)
+{
+ if (chunk_priority_cache.count(pc) > 0)
+ {
+ return(chunk_priority_cache[pc]);
+ }
+ int category = kIncludeCategoriesCount;
+
+ for (int i = 0; i < kIncludeCategoriesCount; i++)
+ {
+ if (include_categories[i] != nullptr)
+ {
+ if (std::regex_match(pc->Text(), include_categories[i]->regex))
+ {
+ category = i;
+ break;
+ }
+ }
+ }
+
+ chunk_priority_cache[pc] = category;
+ return(category);
+}
+
+
+/**
+ * Returns true if the text contains filename without extension.
+ */
+static bool text_contains_filename_without_ext(const char *text)
+{
+ if (filename_without_ext_cache.count(text) > 0)
+ {
+ return(filename_without_ext_cache[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.*");
+
+ filename_without_ext_cache[text] = std::regex_match(text, filename_pattern);
+ return(filename_without_ext_cache[text]);
+}
+
+
+/**
+ * Get chunk text without the extension.
+ */
+static UncText get_text_without_ext(const UncText &chunk_text)
+{
+ UncText 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 UncText has "." which implies extension.
+ */
+static bool has_dot(const UncText &chunk_text)
+{
+ int idx = chunk_text.rfind(".", chunk_text.size() - 1);
+
+ return(idx != -1);
+}
+
+
+/**
+ * Returns chunk string required for sorting.
+ */
+static UncText chunk_sort_str(Chunk *pc)
+{
+ if (pc->GetParentType() == CT_PP_INCLUDE)
+ {
+ return(UncText{ pc->GetStr(), 0, pc->Len() - 1 });
+ }
+ return(pc->GetStr());
+}
+
+
+//! 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->GetOrigLine(), pc1->GetOrigCol());
+ LOG_FMT(LSORT, "%s(%d): @begin pc2->len is %zu, line is %zu, column is %zu\n",
+ __func__, __LINE__, pc2->Len(), pc2->GetOrigLine(), pc2->GetOrigCol());
+
+ 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->GetOrigLine(), pc1->GetOrigCol());
+ 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->GetOrigLine(), pc2->GetOrigCol());
+
+ int ret_val = UncText::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->GetOrigLine(), pc1->GetOrigCol());
+
+ if (pc1->Is(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->GetOrigLine(), pc1->GetOrigCol());
+ }
+ 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->GetOrigLine(), pc2->GetOrigCol());
+
+ if (pc2->Is(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->GetOrigLine(), pc2->GetOrigCol());
+ }
+ 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->GetOrigLine(), pc1->GetOrigCol());
+ 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->GetOrigLine(), pc2->GetOrigCol());
+
+ // If we hit a newline or null chuck, we are done
+ if ( pc1->IsNullChunk()
+ || pc1->IsNewline()
+ || pc2->IsNullChunk()
+ || pc2->IsNewline())
+ {
+ break;
+ }
+ }
+
+ if ( pc1->IsNullChunk()
+ || !pc2->IsNewline())
+ {
+ return(-1);
+ }
+
+ if (!pc1->IsNewline())
+ {
+ return(1);
+ }
+ return(0);
+} // compare_chunks
+
+
+/**
+ * Sort all of the chunks in O(n log n) time with a maximum of O(n) swaps
+ */
+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");
+
+ log_rule_B("mod_sort_case_sensitive");
+ bool take_care = options::mod_sort_case_sensitive(); // Issue #2091
+
+ // Sort an array of the chunk positions in order to minimize the number of swaps
+ std::vector<size_t> chunk_positions(num_chunks);
+
+ for (size_t idx = 0; idx < num_chunks; idx++)
+ {
+ chunk_positions[idx] = idx;
+ }
+
+ sort(chunk_positions.begin(), chunk_positions.end(), [chunks, take_care](const size_t &l, const size_t &r) {
+ return(compare_chunks(chunks[l], chunks[r], take_care) < 0);
+ });
+
+ // Swap the chunk positions
+ for (size_t idx = 0; idx < num_chunks; idx++)
+ {
+ if (chunk_positions[idx] != idx)
+ {
+ log_rule_B("mod_sort_incl_import_grouping_enabled");
+
+ const size_t from = chunk_positions[idx];
+ const size_t to = chunk_positions[from];
+ chunks[from]->SwapLines(chunks[to]);
+
+ Chunk *pc = chunks[from];
+ chunks[from] = chunks[to];
+ chunks[to] = pc;
+
+ chunk_positions[from] = from;
+ chunk_positions[idx] = to;
+ 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->SetNlCount(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->GetFirstChunkOnLine();
+
+ while ( 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->GetOrigLine());
+
+ if (pc->IsNewline())
+ {
+ Chunk::Delete(pc);
+ break;
+ }
+ else
+ {
+ Chunk::Delete(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 = UncText::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(pc->GetFirstChunkOnLine());
+
+ if (newline->GetNlCount() < 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]->GetStr().size() > 0)
+ {
+ c_idx = chunks[idx]->GetStr().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]->GetStr());
+
+ 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()
+{
+ 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 = Chunk::NullChunkPtr;
+ Chunk *p_imp = Chunk::NullChunkPtr;
+ Chunk *p_imp_last = Chunk::NullChunkPtr;
+
+ 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->IsNotNullChunk()
+ && (pc->GetOrigLine() - p_imp_last->GetOrigLine()) > max_lines_to_check_for_sort_after_include)
+ {
+ break;
+ }
+ Chunk *next = pc->GetNext();
+
+ if (pc->IsNewline())
+ {
+ bool did_import = false;
+
+ if ( p_imp->IsNotNullChunk()
+ && ( p_last->Is(CT_SEMICOLON)
+ || p_imp->TestFlags(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);
+ exit(EX_SOFTWARE);
+ }
+ did_import = true;
+ }
+ log_rule_B("mod_sort_incl_import_grouping_enabled");
+
+ if ( !did_import
+ || ( !options::mod_sort_incl_import_grouping_enabled()
+ && pc->GetNlCount() > 1)
+ || ( options::mod_sort_incl_import_grouping_enabled()
+ && p_imp_last->IsNotNullChunk()
+ && (pc->GetOrigLine() - p_imp_last->GetOrigLine()) > 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 = Chunk::NullChunkPtr;
+ p_last = Chunk::NullChunkPtr;
+ }
+ else if (pc->Is(CT_IMPORT))
+ {
+ log_rule_B("mod_sort_import");
+
+ if (options::mod_sort_import())
+ {
+ p_imp = pc->GetNext();
+ }
+ }
+ else if (pc->Is(CT_USING))
+ {
+ log_rule_B("mod_sort_using");
+
+ if (options::mod_sort_using())
+ {
+ p_imp = pc->GetNext();
+ }
+ }
+ else if (pc->Is(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.78.0/src/sorting.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/sorting.h
new file mode 100644
index 00000000..8d518df8
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+#endif /* SORTING_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/space.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/space.cpp
new file mode 100644
index 00000000..ed85a4d3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/space.cpp
@@ -0,0 +1,4004 @@
+/**
+ * @file space.cpp
+ * Adds or removes inter-chunk spaces.
+ *
+ * Information
+ * "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-2023
+ * @license GPL v2+
+ */
+
+#include "space.h"
+
+#include "add_space_table.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;
+
+
+/**
+ * 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);
+
+
+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;
+
+ while (prev->IsNotNullChunk())
+ {
+ if (prev->Is(CT_TRAILING_RET))
+ {
+ return(true);
+ }
+ else if ( prev->Is(CT_FPAREN_CLOSE)
+ || prev->Is(CT_FPAREN_OPEN)
+ || prev->Is(CT_SEMICOLON)) // Issue #4080
+ {
+ return(false);
+ }
+ else
+ {
+ prev = prev->GetPrev();
+ }
+ }
+ return(false);
+} // token_is_within_trailing_return
+
+
+/**
+ * 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
+ *
+ * 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 %zu, orig col %zu, first text '%s', type %s\n",
+ __func__, __LINE__, first->GetOrigLine(), first->GetOrigCol(), first->Text(), get_token_name(first->GetType()));
+
+ min_sp = 1;
+
+ if ( first->Is(CT_VBRACE_OPEN)
+ && first->GetPrev()->Is(CT_SPAREN_CLOSE)
+ && second->IsNot(CT_SEMICOLON))
+ {
+ // Add or remove space after ')' of control statements.
+ log_rule("sp_after_sparen");
+ return(options::sp_after_sparen());
+ }
+
+ if (first->Is(CT_SPAREN_CLOSE))
+ {
+ if (second->Is(CT_VBRACE_OPEN))
+ {
+ // Fix spacing between SPAREN_CLOSE and VBRACE_OPEN tokens as we don't want the default behavior (which is ADD).
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( options::sp_sparen_brace() == IARF_IGNORE
+ && second->Is(CT_BRACE_OPEN))
+ {
+ // Do sp_after_sparen if sp_sparen_brace is ignored. No need for VBRACE_OPEN spacing.
+ log_rule("sp_after_sparen");
+ return(options::sp_after_sparen());
+ }
+ }
+
+ if ( first->Is(CT_PP_IGNORE)
+ && second->Is(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 ( first->Is(CT_PP)
+ || second->Is(CT_PP))
+ {
+ // Add or remove space around preprocessor '##' concatenation operator.
+ log_rule("sp_pp_concat");
+ return(options::sp_pp_concat());
+ }
+
+ if (first->Is(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 ( second->Is(CT_POUND)
+ && second->TestFlags(PCF_IN_PREPROC)
+ && first->GetParentType() != 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 ( first->Is(CT_SPACE)
+ || second->Is(CT_SPACE))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (first->Is(CT_DECLSPEC)) // Issue 1289
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( second->Is(CT_NEWLINE)
+ || second->Is(CT_VBRACE_OPEN))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( first->Is(CT_VBRACE_OPEN)
+ && second->IsNot(CT_NL_CONT)
+ && second->IsNot(CT_SEMICOLON)) // # Issue 1158
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( first->Is(CT_VBRACE_CLOSE)
+ && second->IsNot(CT_NL_CONT))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (second->Is(CT_VSEMICOLON))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (first->Is(CT_MACRO_FUNC))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (second->Is(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)
+ && ( first->Is(CT_D_ARRAY_COLON)
+ || second->Is(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 ( first->Is(CT_CASE)
+ && (( CharTable::IsKw1(second->GetStr()[0])
+ || second->Is(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 (first->Is(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 (second->Is(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 ( first->Is(CT_QUESTION)
+ && second->Is(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 ( first->Is(CT_QUESTION) // see the tests cpp:34513-34516
+ || second->Is(CT_QUESTION))
+ {
+ if ( second->Is(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 ( first->Is(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 ( first->Is(CT_COND_COLON)
+ || second->Is(CT_COND_COLON))
+ {
+ if ( second->Is(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 ( first->Is(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 (first->Is(CT_WORD) && second->Is(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)
+ && ( first->Is(CT_RANGE)
+ || second->Is(CT_RANGE)))
+ {
+ // (D) Add or remove space around the D '..' operator.
+ log_rule("sp_range");
+ return(options::sp_range());
+ }
+
+ if ( first->Is(CT_COLON)
+ && first->GetParentType() == CT_SQL_EXEC)
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ // Macro stuff can only return IGNORE, ADD, or FORCE
+ if (first->Is(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 ( first->Is(CT_FPAREN_CLOSE)
+ && first->GetParentType() == 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 (first->Is(CT_PREPROC))
+ {
+ // Remove spaces, unless we are ignoring. See indent_preproc()
+ log_rule("pp_space_after");
+
+ if (options::pp_space_after() == IARF_IGNORE)
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (second->Is(CT_PREPROC))
+ {
+ // Remove spaces, unless we are ignoring. See indent_preproc()
+ log_rule("pp_indent");
+
+ if (options::pp_indent() == IARF_IGNORE)
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (second->Is(CT_SEMICOLON)) // see the tests cpp:34517-34519
+ {
+ if (first->Is(CT_VBRACE_OPEN))
+ {
+ // Add or remove space before ';'.
+ log_rule("sp_before_semi");
+ return(options::sp_before_semi());
+ }
+
+ // Issue #4094-03
+ if (second->GetParentType() == CT_FOR)
+ {
+ if (first->Is(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 (first->Is(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 ( first->Is(CT_VBRACE_OPEN) // Issue #2942
+ && first->GetPrev()->Is(CT_SPAREN_CLOSE)
+ && first->GetParentType() != 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 ( ( second->Is(CT_COMMENT)
+ || second->Is(CT_COMMENT_CPP))
+ && ( first->Is(CT_PP_ELSE)
+ || first->Is(CT_PP_ENDIF)))
+ {
+ if (second->Is(CT_COMMENT_CPP))
+ {
+ second->SetType(CT_COMMENT_CPP_ENDIF);
+ }
+ else
+ {
+ second->SetType(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
+ && second->GetParentType() == 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 (second->GetParentType() == CT_COMMENT_END)
+ {
+ switch (second->GetOrigPrevSp())
+ {
+ 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);
+ }
+ }
+
+ // Issue #4094-05
+ // "for (;;)" vs. "for (;; )" and "for (a;b;c)" vs. "for (a; b; c)"
+ if (first->Is(CT_SEMICOLON)) // see the tests cpp:34517-34519
+ {
+ if (first->GetParentType() == CT_FOR)
+ {
+ if (second->Is(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->IsNot(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->IsNot(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 ( ( first->Is(CT_NEG)
+ || first->Is(CT_POS)
+ || first->Is(CT_ARITH)
+ || first->Is(CT_SHIFT))
+ && ( second->Is(CT_NEG)
+ || second->Is(CT_POS)
+ || second->Is(CT_ARITH)
+ || second->Is(CT_SHIFT)))
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ // "return(a);" vs. "return (foo_t)a + 3;" vs. "return a;" vs. "return;"
+ if (first->Is(CT_RETURN))
+ {
+ if ( second->Is(CT_PAREN_OPEN)
+ && second->GetParentType() == CT_RETURN)
+ {
+ // Add or remove space between 'return' and '('.
+ log_rule("sp_return_paren");
+ return(options::sp_return_paren());
+ }
+ else if ( second->Is(CT_BRACE_OPEN)
+ && second->GetParentType() == 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 (first->Is(CT_SIZEOF))
+ {
+ if (second->Is(CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'sizeof' and '('.
+ log_rule("sp_sizeof_paren");
+ return(options::sp_sizeof_paren());
+ }
+
+ if (second->Is(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 (first->Is(CT_DECLTYPE))
+ {
+ if (second->Is(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 (first->Is(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 ( first->Is(CT_PAREN_CLOSE)
+ && second->Is(CT_DC_MEMBER)
+ && second->GetNext()->GetType() == CT_FUNC_CALL)
+ {
+ log_rule("sp_after_cast");
+ return(options::sp_after_cast());
+ }
+
+ if (second->Is(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->GetType())
+ {
+ 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 ( ( first->Is(CT_WORD)
+ || first->Is(CT_TYPE)
+ || first->Is(CT_PAREN_CLOSE)
+ || CharTable::IsKw1(first->GetStr()[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 (first->Is(CT_COMMA)) // see the tests cpp:34520-34524
+ // see the tests c-sharp:12200-12202
+ {
+ if ( language_is_set(LANG_CS | LANG_VALA)
+ && first->GetParentType() == CT_TYPE)
+ {
+ // (C#, Vala) multidimensional array type: ',,' vs. ', ,' or ',]' vs. ', ]'
+ if (second->Is(CT_COMMA))
+ {
+ // (C#, Vala) Add or remove space between ',' in multidimensional array type
+ // like 'int[,,]'.
+ log_rule("sp_between_mdatype_commas");
+ return(options::sp_between_mdatype_commas());
+ }
+ // (C#, Vala) 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 (second->Is(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 ( first->Is(CT_FPAREN_CLOSE)
+ && ( second->Is(CT_FPAREN_CLOSE)
+ || second->Is(CT_COMMA)))
+ {
+ if (second->GetLevel() == QT_SIGNAL_SLOT_level)
+ {
+ restoreValues = true;
+ }
+ }
+ }
+
+ if (second->Is(CT_COMMA))
+ {
+ if ( language_is_set(LANG_CS | LANG_VALA)
+ && first->Is(CT_SQUARE_OPEN)
+ && first->GetParentType() == CT_TYPE)
+ {
+ // (C#, Vala) 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 ( first->Is(CT_PAREN_OPEN)
+ || first->Is(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 (second->Is(CT_ELLIPSIS))
+ {
+ // type followed by a ellipsis
+ Chunk *tmp = first;
+
+ if ( tmp->Is(CT_PTR_TYPE)
+ || tmp->Is(CT_BYREF))
+ {
+ tmp = tmp->GetPrevNcNnl();
+ }
+
+ if ( tmp->Is(CT_TYPE)
+ || tmp->Is(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->TestFlags(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 ( first->Is(CT_FPAREN_CLOSE)
+ || first->Is(CT_PAREN_CLOSE))
+ {
+ // Add or remove space between ')' and '...'.
+ log_rule("sp_paren_ellipsis");
+ return(options::sp_paren_ellipsis());
+ }
+
+ if (first->Is(CT_TAG_COLON))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if (first->Is(CT_BYREF)) // Issue #3309
+ {
+ log_rule("sp_byref_ellipsis");
+ return(options::sp_byref_ellipsis());
+ }
+
+ if (first->Is(CT_PARAMETER_PACK)) // Issue #3309
+ {
+ log_rule("sp_parameter_pack_ellipsis");
+ return(options::sp_parameter_pack_ellipsis());
+ }
+ }
+
+ if (first->Is(CT_ELLIPSIS))
+ {
+ if (second->Is(CT_PARAMETER_PACK)) // Issue #3309
+ {
+ log_rule("sp_ellipsis_parameter_pack");
+ return(options::sp_ellipsis_parameter_pack());
+ }
+
+ if (CharTable::IsKw1(second->GetStr()[0]))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( second->Is(CT_PAREN_OPEN)
+ && first->GetPrev()->Is(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)
+ && first->Is(CT_TAG_COLON))
+ {
+ // (Pawn) Add or remove space after the tag keyword.
+ log_rule("sp_after_tag");
+ return(options::sp_after_tag());
+ }
+
+ if (second->Is(CT_TAG_COLON))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ // handle '~'
+ if (first->Is(CT_DESTRUCTOR))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( language_is_set(LANG_OC)
+ && first->Is(CT_CATCH)
+ && second->Is(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)
+ && ( first->Is(CT_PAREN_CLOSE)
+ || first->Is(CT_OC_CLASS)
+ || first->Is(CT_WORD))
+ && second->Is(CT_ANGLE_OPEN)
+ && ( second->GetParentType() == CT_OC_PROTO_LIST
+ || second->GetParentType() == 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)
+ && first->Is(CT_OC_CLASS)
+ && second->Is(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 ( first->Is(CT_CATCH)
+ && second->Is(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)
+ && first->Is(CT_D_VERSION_IF)
+ && second->Is(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)
+ && first->Is(CT_D_SCOPE_IF)
+ && second->Is(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)
+ && first->Is(CT_SYNCHRONIZED)
+ && second->Is(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 (second->Is(CT_SPAREN_OPEN))
+ {
+ // Add or remove space after 'do' between 'while' and '('. Issue #995
+ if ( first->Is(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 ( first->Is(CT_LAMBDA)
+ || second->Is(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)
+ && ( ( first->Is(CT_SQUARE_OPEN)
+ && first->GetParentType() == CT_CPP_LAMBDA
+ && second->Is(CT_ASSIGN))
+ || ( first->Is(CT_ASSIGN)
+ && second->Is(CT_SQUARE_CLOSE)
+ && second->GetParentType() == CT_CPP_LAMBDA)))
+ {
+ log_rule("sp_cpp_lambda_assign");
+ return(options::sp_cpp_lambda_assign());
+ }
+
+ if ( first->Is(CT_SQUARE_CLOSE)
+ && first->GetParentType() == 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 (second->Is(CT_LPAREN_OPEN))
+ {
+ log_rule("sp_cpp_lambda_square_paren");
+ return(options::sp_cpp_lambda_square_paren());
+ }
+ else if (second->Is(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 (first->Is(CT_LPAREN_OPEN))
+ {
+ if (second->Is(CT_LPAREN_CLOSE))
+ {
+ // 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> ){ ... }'
+ // with an empty list.
+ log_rule("sp_cpp_lambda_argument_list_empty");
+ return(options::sp_cpp_lambda_argument_list_empty());
+ }
+ // 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 (first->Is(CT_LPAREN_CLOSE))
+ {
+ if (second->Is(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 (second->Is(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 ( first->Is(CT_BRACE_CLOSE)
+ && first->GetParentType() == CT_CPP_LAMBDA
+ && second->Is(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 (first->Is(CT_ENUM))
+ {
+ if (second->Is(CT_BRACE_OPEN))
+ {
+ // Add or remove space in 'enum {'.
+ log_rule("sp_enum_brace");
+ return(options::sp_enum_brace());
+ }
+ else if (second->Is(CT_FPAREN_OPEN))
+ {
+ // Add or remove space in 'NS_ENUM ('.
+ log_rule("sp_enum_paren");
+ return(options::sp_enum_paren());
+ }
+ }
+
+ if (second->Is(CT_ASSIGN))
+ {
+ if (second->TestFlags(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)
+ && second->GetParentType() == 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 (second->Is(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)
+ && second->GetParentType() == 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 (first->Is(CT_ASSIGN))
+ {
+ if (first->TestFlags(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)
+ && first->GetParentType() == 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 ( first->Is(CT_TRAILING_RET)
+ || first->Is(CT_CPP_LAMBDA_RET)
+ || second->Is(CT_TRAILING_RET)
+ || second->Is(CT_CPP_LAMBDA_RET))
+ {
+ // Add or remove space around trailing return operator '->'.
+ log_rule("sp_trailing_return");
+ return(options::sp_trailing_return());
+ }
+
+ if (first->Is(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)
+ && first->GetParentType() == 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 (first->Is(CT_ENUM_COLON)) // Issue #4040
+ {
+ // Add or remove space around assignment ':' in enum.
+ log_rule("sp_enum_colon");
+ return(options::sp_enum_colon());
+ }
+
+ if (second->Is(CT_ENUM_COLON)) // Issue #4040
+ {
+ // Add or remove space around assignment ':' in enum.
+ log_rule("sp_enum_colon");
+ return(options::sp_enum_colon());
+ }
+
+ if (first->Is(CT_BIT_COLON)) // Issue #4040
+ {
+ // Add or remove space after a bit colon ':'.
+ log_rule("sp_after_bit_colon");
+ return(options::sp_after_bit_colon());
+ }
+
+ if (second->Is(CT_BIT_COLON)) // Issue #4040
+ {
+ // Add or remove space before a bit colon ':'.
+ log_rule("sp_before_bit_colon");
+ return(options::sp_before_bit_colon());
+ }
+
+ if ( first->Is(CT_OC_AVAILABLE_VALUE)
+ || second->Is(CT_OC_AVAILABLE_VALUE))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ if (language_is_set(LANG_OC))
+ {
+ if (second->Is(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 (first->Is(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 (second->Is(CT_OC_MSG_FUNC))
+ {
+ if ( (options::sp_after_oc_msg_receiver() == IARF_REMOVE)
+ && ( first->IsNot(CT_SQUARE_CLOSE)
+ && first->IsNot(CT_FPAREN_CLOSE)
+ && first->IsNot(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)
+ && ( first->Is(CT_BYREF)
+ || first->Is(CT_QUALIFIER)
+ || first->Is(CT_TYPE))
+ && second->Is(CT_SQUARE_OPEN)
+ && second->GetParentType() != CT_OC_MSG
+ && second->GetParentType() != 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 ( second->Is(CT_SQUARE_OPEN)
+ && ( second->GetParentType() != CT_OC_MSG
+ && second->GetParentType() != CT_CS_SQ_STMT
+ && second->GetParentType() != CT_CPP_LAMBDA))
+ {
+ if ( second->TestFlags(PCF_IN_SPAREN)
+ && (first->Is(CT_IN)))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if (first->Is(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->TestFlags(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 (second->Is(CT_TSQUARE))
+ {
+ // Add or remove space before '[]'.
+ log_rule("sp_before_squares");
+ return(options::sp_before_squares());
+ }
+
+ if ( (options::sp_angle_shift() != IARF_IGNORE)
+ && first->Is(CT_ANGLE_CLOSE)
+ && second->Is(CT_ANGLE_CLOSE))
+ {
+ // Add or remove space between '>' and '>' in '>>' (template stuff).
+ log_rule("sp_angle_shift");
+ return(options::sp_angle_shift());
+ }
+
+ // Issue #4094-01
+ // spacing around template < > stuff
+ if ( first->Is(CT_ANGLE_OPEN)
+ || second->Is(CT_ANGLE_CLOSE))
+ {
+ if ( first->Is(CT_ANGLE_OPEN)
+ && second->Is(CT_ANGLE_CLOSE))
+ {
+ // Add or remove space inside '<>'.
+ // if empty.
+ 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()
+ && first->Is(CT_ANGLE_OPEN)
+ && second->Is(CT_DC_MEMBER))
+ {
+ op = IARF_IGNORE;
+ }
+ return(op);
+ }
+
+ if (second->Is(CT_ANGLE_OPEN))
+ {
+ if ( first->Is(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->IsNot(CT_QUALIFIER))
+ {
+ // Add or remove space before '<'.
+ log_rule("sp_before_angle");
+ return(options::sp_before_angle());
+ }
+ }
+
+ if (first->Is(CT_ANGLE_CLOSE))
+ {
+ if ( second->Is(CT_WORD)
+ || CharTable::IsKw1(second->GetStr()[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());
+ }
+
+ // Issue #4094-02
+ if ( second->Is(CT_FPAREN_OPEN)
+ || second->Is(CT_PAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (next->Is(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 (second->Is(CT_DC_MEMBER))
+ {
+ // Add or remove space before the '::' operator.
+ log_rule("sp_before_dc");
+ return(options::sp_before_dc());
+ }
+
+ if ( second->IsNot(CT_BYREF)
+ && second->IsNot(CT_PTR_TYPE)
+ && second->IsNot(CT_BRACE_OPEN)
+ && second->IsNot(CT_PAREN_CLOSE))
+ {
+ if ( second->Is(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 ( second->Is(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 (first->Is(CT_BYREF)) // see the tests cpp:34509-34512
+ {
+ if (second->Is(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 ( first->GetParentType() == CT_FUNC_DEF // Issue #3197, #3210
+ || first->GetParentType() == 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->GetStr()[0])
+ && ( options::sp_after_byref() != IARF_IGNORE
+ || ( !second->Is(CT_FUNC_PROTO)
+ && !second->Is(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 ( second->Is(CT_BYREF)
+ && !first->Is(CT_PAREN_OPEN)) // Issue #1804
+ {
+ if ( second->GetParentType() == CT_FUNC_DEF // Issue #3197, #3210
+ || second->GetParentType() == 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()
+ && ( next->Is(CT_COMMA)
+ || next->Is(CT_PAREN_CLOSE) // Issue #3691
+ || next->Is(CT_FPAREN_CLOSE)
+ || next->Is(CT_SEMICOLON)))
+ {
+ if (options::sp_before_unnamed_byref() != IARF_IGNORE) // Issue #3691
+ {
+ // 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());
+ }
+ }
+
+ if (first->Is(CT_PTR_TYPE))
+ {
+ // Add or remove space between pointer and Ref.
+ // as in 'int *& a'.
+ log_rule("sp_between_ptr_ref"); // ptr_ref 1
+ return(options::sp_between_ptr_ref());
+ }
+ // Add or remove space before a reference sign '&'.
+ log_rule("sp_before_byref"); // byref 3
+ return(options::sp_before_byref());
+ }
+
+ if (first->Is(CT_SPAREN_CLOSE))
+ {
+ if (second->Is(CT_BRACE_OPEN))
+ {
+ if (second->GetParentType() == 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());
+ }
+ }
+ }
+
+ // Issue #4094-07
+ if ( second->Is(CT_FPAREN_OPEN)
+ && first->GetParentType() == CT_OPERATOR
+ && (options::sp_after_operator_sym() != IARF_IGNORE))
+ {
+ if ( (options::sp_after_operator_sym_empty() != IARF_IGNORE)
+ && second->Is(CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (next->Is(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)
+ && first->Is(CT_FUNC_CALL))
+ {
+ if ( first->IsString("_")
+ && second->Is(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 ( first->Is(CT_MACRO_OPEN)
+ || first->Is(CT_MACRO_CLOSE)
+ || first->Is(CT_MACRO_ELSE))
+ {
+ if (second->Is(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);
+ }
+
+ // Issue #4094-11
+ // spaces between function and open paren
+ if ( first->Is(CT_FUNC_CALL)
+ || first->Is(CT_FUNCTION) // Issue #2665
+ || first->Is(CT_FUNC_CTOR_VAR)
+ || first->Is(CT_CNG_HASINC)
+ || first->Is(CT_CNG_HASINCN)
+ || ( first->Is(CT_BRACE_CLOSE)
+ && first->GetParentType() == CT_BRACED_INIT_LIST
+ && second->Is(CT_FPAREN_OPEN))
+ || ( first->Is(CT_FUNC_VAR) // Issue #3852
+ && second->Is(CT_PAREN_OPEN)))
+ {
+ if ( (options::sp_func_call_paren_empty() != IARF_IGNORE)
+ && second->Is(CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (next->Is(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 (first->Is(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 ( first->Is(CT_ATTRIBUTE)
+ && second->IsParenOpen())
+ {
+ // Add or remove space between '__attribute__' and '('.
+ log_rule("sp_attribute_paren");
+ return(options::sp_attribute_paren());
+ }
+
+ // Issue #4094-10
+ if (first->Is(CT_FUNC_DEF))
+ {
+ if ( (options::sp_func_def_paren_empty() != IARF_IGNORE)
+ && second->Is(CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (next->Is(CT_FPAREN_CLOSE))
+ {
+ // Add or remove space between function name and '()' on function definition
+ // if empty.
+ 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 ( first->Is(CT_CPP_CAST)
+ || first->Is(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 ( first->Is(CT_SPAREN_CLOSE)
+ && second->Is(CT_WHEN))
+ {
+ // TODO: provide some test data to check this block
+ log_rule("FORCE");
+ return(IARF_FORCE); // TODO: make this configurable?
+ }
+
+ if ( first->Is(CT_PAREN_CLOSE)
+ && ( second->Is(CT_PAREN_OPEN)
+ || second->Is(CT_FPAREN_OPEN)))
+ {
+ // "(int)a" vs. "(int) a" or "cast(int)a" vs. "cast(int) a"
+ if ( first->GetParentType() == CT_C_CAST
+ || first->GetParentType() == 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 (first->Is(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 ( ( first->IsString(")")
+ && second->IsString("("))
+ || ( first->IsParenClose()
+ && second->IsParenOpen()))
+ {
+ // Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('.
+ log_rule("sp_cparen_oparen");
+ return(options::sp_cparen_oparen());
+ }
+
+ // Issue #4094-09
+ if ( first->Is(CT_FUNC_PROTO)
+ || ( second->Is(CT_FPAREN_OPEN)
+ && second->GetParentType() == CT_FUNC_PROTO))
+ {
+ if ( (options::sp_func_proto_paren_empty() != IARF_IGNORE)
+ && second->Is(CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (next->Is(CT_FPAREN_CLOSE))
+ {
+ // Add or remove space between function name and '()' on function declaration
+ // if empty.
+ 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 ( first->Is(CT_FUNC_TYPE)
+ && second->Is(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());
+ }
+
+ // Issue #4094-12
+ if ( first->Is(CT_FUNC_CLASS_DEF)
+ || first->Is(CT_FUNC_CLASS_PROTO))
+ {
+ if ( (options::sp_func_class_paren_empty() != IARF_IGNORE)
+ && second->Is(CT_FPAREN_OPEN))
+ {
+ Chunk *next = second->GetNextNcNnl();
+
+ if (next->Is(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 ( first->Is(CT_CLASS)
+ && !first->TestFlags(PCF_IN_OC_MSG))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ // Issue #4094-08
+ if ( first->Is(CT_BRACE_OPEN)
+ && second->Is(CT_BRACE_CLOSE))
+ {
+ // Add or remove space inside '{}'.
+ // if empty.
+ log_rule("sp_inside_braces_empty");
+ return(options::sp_inside_braces_empty());
+ }
+
+ if ( ( first->Is(CT_TYPE) // Issue #2428
+ || first->Is(CT_ANGLE_CLOSE))
+ && second->Is(CT_BRACE_OPEN)
+ && second->GetParentType() == CT_BRACED_INIT_LIST)
+ {
+ iarf_flags_t arg = iarf_flags_t{ options::sp_type_brace_init_lst() };
+
+ if ( arg != IARF_IGNORE
+ || first->GetParentType() != 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 ( ( first->Is(CT_WORD) // Issue #2428
+ || first->Is(CT_SQUARE_CLOSE)
+ || first->Is(CT_TSQUARE))
+ && second->Is(CT_BRACE_OPEN)
+ && second->GetParentType() == 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
+ || first->GetParentType() != 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 (second->Is(CT_BRACE_CLOSE))
+ {
+ if (second->GetParentType() == CT_ENUM)
+ {
+ // Add or remove space inside enum '{' and '}'.
+ log_rule("sp_inside_braces_enum");
+ return(options::sp_inside_braces_enum());
+ }
+
+ if ( second->GetParentType() == CT_STRUCT
+ || second->GetParentType() == CT_UNION)
+ {
+ // Fix for issue #1240 adding space in struct initializers
+ Chunk *tmp = second->GetOpeningParen()->GetPrevNcNnl();
+
+ if (tmp->Is(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)
+ && second->GetParentType() == 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 (second->GetParentType() == 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
+ && first->Is(CT_BRACE_CLOSE)
+ && first->GetParentType() == 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 (first->Is(CT_D_CAST))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( first->Is(CT_PP_DEFINED)
+ && second->Is(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 (first->Is(CT_THROW))
+ {
+ if (second->Is(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 ( first->Is(CT_THIS)
+ && second->Is(CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'this' and '(' in 'this (something)'.
+ log_rule("sp_this_paren");
+ return(options::sp_this_paren());
+ }
+
+ if ( first->Is(CT_STATE)
+ && second->Is(CT_PAREN_OPEN))
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ if ( first->Is(CT_DELEGATE)
+ && second->Is(CT_PAREN_OPEN))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( first->Is(CT_MEMBER)
+ || second->Is(CT_MEMBER))
+ {
+ // Add or remove space around the '.' or '->' operators.
+ log_rule("sp_member");
+ return(options::sp_member());
+ }
+
+ if (first->Is(CT_C99_MEMBER))
+ {
+ // always remove space(s) after then '.' of a C99-member
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( first->Is(CT_SUPER)
+ && second->Is(CT_PAREN_OPEN))
+ {
+ // Add or remove space between 'super' and '(' in 'super (something)'.
+ log_rule("sp_super_paren");
+ return(options::sp_super_paren());
+ }
+
+ if ( first->Is(CT_FPAREN_CLOSE)
+ && second->Is(CT_BRACE_OPEN))
+ {
+ if ( language_is_set(LANG_JAVA)
+ && second->GetParentType() == 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 (first->GetParentType() == CT_FUNC_CALL)
+ {
+ Chunk *tmp = first->GetPrevType(first->GetParentType(), first->GetLevel());
+ tmp = tmp->GetPrevNcNnl();
+
+ if (tmp->Is(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 ( first->Is(CT_D_TEMPLATE)
+ || second->Is(CT_D_TEMPLATE))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if ( first->Is(CT_ELSE)
+ && second->Is(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 ( first->Is(CT_ELSE)
+ && second->Is(CT_ELSEIF))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( first->Is(CT_FINALLY)
+ && second->Is(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 ( first->Is(CT_TRY)
+ && second->Is(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 ( first->Is(CT_GETSET)
+ && second->Is(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 ( first->Is(CT_WORD)
+ && second->Is(CT_BRACE_OPEN))
+ {
+ if (first->GetParentType() == 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)
+ && second->Is(CT_PAREN_OPEN)
+ && second->GetParentType() == CT_INVARIANT)
+ {
+ // (D) Add or remove space between 'invariant' and '('.
+ log_rule("sp_invariant_paren");
+ return(options::sp_invariant_paren());
+ }
+
+ if ( first->Is(CT_PAREN_CLOSE)
+ && first->GetParentType() != CT_DECLTYPE)
+ {
+ if ( language_is_set(LANG_D)
+ && first->GetParentType() == 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 (second->Is(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 (first->GetParentType() == CT_DELEGATE)
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ // PAWN-specific: "state (condition) next"
+ if (first->GetParentType() == CT_STATE)
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ /* C++ new operator: new(bar) Foo */
+ if (first->GetParentType() == 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 ( ( first->IsString("(")
+ && second->IsString("("))
+ || ( first->IsString(")")
+ && second->IsString(")")))
+ {
+ if (second->GetParentType() == 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
+ && ( first->Is(CT_SPAREN_OPEN)
+ || second->Is(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 ( first->Is(CT_FPAREN_OPEN)
+ || second->Is(CT_FPAREN_CLOSE))
+ {
+ if ( (first->GetParentType() == CT_FUNC_CALL_USER)
+ || ( (second->GetParentType() == CT_FUNC_CALL_USER)
+ && ( (first->Is(CT_WORD))
+ || (first->Is(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 ( first->Is(CT_FPAREN_OPEN)
+ && second->Is(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());
+ }
+
+ // functor "foo(...)" vs. "foo( ... )"
+ if ( first->Is(CT_RPAREN_OPEN)
+ || second->Is(CT_RPAREN_CLOSE)) // Issue #3914
+ {
+ if ( (first->GetParentType() == CT_FUNC_CALL_USER)
+ || ( (second->GetParentType() == CT_FUNC_CALL_USER)
+ && ( (first->Is(CT_WORD))
+ || (first->Is(CT_SQUARE_CLOSE)))))
+ {
+ // Add or remove space inside user function '(' and ')'.
+ log_rule("sp_func_call_user_inside_rparen");
+ return(options::sp_func_call_user_inside_rparen());
+ }
+
+ if ( first->Is(CT_RPAREN_OPEN)
+ && second->Is(CT_RPAREN_CLOSE)) // Issue #3914
+ {
+ // Add or remove space inside empty function '()'.
+ log_rule("sp_inside_rparens");
+ return(options::sp_inside_rparens());
+ }
+ // Add or remove space inside function '(' and ')'.
+ log_rule("sp_inside_rparen");
+ return(options::sp_inside_rparen());
+ }
+
+ // "foo(...)" vs. "foo( ... )"
+ if ( first->Is(CT_TPAREN_OPEN)
+ || second->Is(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)
+ && first->Is(CT_PAREN_CLOSE))
+ {
+ if ( first->TestFlags(PCF_OC_RTYPE) // == CT_OC_RTYPE)
+ && ( first->GetParentType() == CT_OC_MSG_DECL
+ || first->GetParentType() == 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 ( first->GetParentType() == CT_OC_MSG_SPEC
+ || first->GetParentType() == 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 ( first->GetParentType() == CT_OC_SEL
+ && second->IsNot(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 ( ( first->Is(CT_PAREN_OPEN)
+ && ( first->GetParentType() == CT_OC_SEL
+ || first->GetParentType() == CT_OC_PROTOCOL))
+ || ( second->Is(CT_PAREN_CLOSE)
+ && ( second->GetParentType() == CT_OC_SEL
+ || second->GetParentType() == 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 ( second->Is(CT_PAREN_OPEN)
+ && ( first->Is(CT_OC_SEL)
+ || first->Is(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 (first->Is(CT_PAREN_OPEN))
+ {
+ if ( first->GetParentType() == CT_C_CAST
+ || first->GetParentType() == CT_CPP_CAST
+ || first->GetParentType() == CT_D_CAST)
+ {
+ // Add or remove spaces inside cast parentheses.
+ log_rule("sp_inside_paren_cast");
+ return(options::sp_inside_paren_cast());
+ }
+
+ if (first->GetParentType() == 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 parentheses 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 (second->Is(CT_PAREN_CLOSE))
+ {
+ if ( second->GetParentType() == CT_C_CAST
+ || second->GetParentType() == CT_CPP_CAST
+ || second->GetParentType() == CT_D_CAST)
+ {
+ // Add or remove spaces inside cast parentheses.
+ log_rule("sp_inside_paren_cast");
+ return(options::sp_inside_paren_cast());
+ }
+
+ if (second->GetParentType() == 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 parentheses 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());
+ }
+
+ // Issue #4094-06
+ if ( first->Is(CT_SQUARE_OPEN)
+ && second->Is(CT_SQUARE_CLOSE))
+ {
+ // Add or remove space inside '[]'.
+ // if empty.
+ log_rule("sp_inside_square_empty");
+ return(options::sp_inside_square_empty());
+ }
+
+ // "[3]" vs. "[ 3 ]" or for objective-c "@[@3]" vs. "@[ @3 ]"
+ if ( first->Is(CT_SQUARE_OPEN)
+ || second->Is(CT_SQUARE_CLOSE))
+ {
+ if ( language_is_set(LANG_OC)
+ && ( ( first->GetParentType() == CT_OC_AT
+ && first->Is(CT_SQUARE_OPEN))
+ || ( second->GetParentType() == CT_OC_AT
+ && second->Is(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 ( first->Is(CT_SQUARE_CLOSE)
+ && second->Is(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 (second->Is(CT_SPAREN_CLOSE))
+ {
+ if ( second->GetParentType() == 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 (first->Is(CT_SPAREN_OPEN))
+ {
+ if ( first->GetParentType() == 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 (first->Is(CT_SPAREN_OPEN))
+ {
+ if (first->GetParentType() == 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 (second->Is(CT_SPAREN_CLOSE))
+ {
+ if (second->GetParentType() == 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 (first->Is(CT_CLASS_COLON))
+ {
+ if ( first->GetParentType() == CT_OC_CLASS
+ && ( first->GetPrevType(CT_OC_INTF, first->GetLevel(), E_Scope::ALL)->IsNullChunk()
+ && first->GetPrevType(CT_OC_IMPL, first->GetLevel(), 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 (second->Is(CT_CLASS_COLON))
+ {
+ if ( language_is_set(LANG_OC)
+ && second->GetParentType() == CT_OC_CLASS
+ && ( second->GetPrevType(CT_OC_INTF, second->GetLevel(), E_Scope::ALL)->IsNullChunk()
+ && second->GetPrevType(CT_OC_IMPL, second->GetLevel(), E_Scope::ALL)->IsNullChunk()))
+ {
+ if ( second->GetParentType() == CT_OC_CLASS
+ && second->GetPrevType(CT_OC_INTF, second->GetLevel(), 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 (first->Is(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 (second->Is(CT_CONSTR_COLON))
+ {
+ // Add or remove space before class constructor ':'.
+ log_rule("sp_before_constr_colon");
+ return(options::sp_before_constr_colon());
+ }
+
+ if (second->Is(CT_CASE_COLON))
+ {
+ // Add or remove space before case ':'.
+ log_rule("sp_before_case_colon");
+ return(options::sp_before_case_colon());
+ }
+
+ if (first->Is(CT_DOT))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (second->Is(CT_DOT))
+ {
+ log_rule("ADD");
+ return(IARF_ADD);
+ }
+
+ if ( first->Is(CT_NULLCOND)
+ || second->Is(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 ( first->Is(CT_ARITH)
+ || first->Is(CT_SHIFT)
+ || first->Is(CT_CARET)
+ || second->Is(CT_ARITH)
+ || second->Is(CT_SHIFT)
+ || second->Is(CT_CARET))
+ {
+ // Add or remove space around arithmetic operators '+' and '-'.
+ // Overrides sp_arith.
+ if (options::sp_arith_additive() != IARF_IGNORE)
+ {
+ auto arith_char = ( first->Is(CT_ARITH)
+ || first->Is(CT_SHIFT)
+ || first->Is(CT_CARET))
+ ? first->GetStr()[0] : second->GetStr()[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 ( first->Is(CT_BOOL)
+ || second->Is(CT_BOOL))
+ {
+ // Add or remove space around boolean operators '&&' and '||'.
+ iarf_e arg = options::sp_bool();
+
+ if ( (options::pos_bool() != TP_IGNORE)
+ && first->GetOrigLine() != second->GetOrigLine())
+ {
+ arg = arg | IARF_ADD;
+ }
+ log_rule("sp_bool");
+ return(arg);
+ }
+
+ if ( first->Is(CT_COMPARE)
+ || second->Is(CT_COMPARE))
+ {
+ // Add or remove space around compare operator '<', '>', '==', etc.
+ log_rule("sp_compare");
+ return(options::sp_compare());
+ }
+
+ if ( first->Is(CT_PAREN_OPEN)
+ && second->Is(CT_PTR_TYPE))
+ {
+ // TODO: provide some test data to check this block
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (first->Is(CT_PTR_TYPE)) // see the tests cpp:34505-34508
+ {
+ if ( second->Is(CT_FPAREN_OPEN)
+ || second->Is(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 (second->Is(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 (second->Is(CT_BYREF))
+ {
+ // Add or remove space between pointer and Ref.
+ // as in 'int *& a'.
+ log_rule("sp_between_ptr_ref"); // ptr_ref 1
+ return(options::sp_between_ptr_ref());
+ }
+ else if (second->Is(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 (second->Is(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 ( first->GetParentType() == CT_FUNC_DEF
+ || first->GetParentType() == CT_FUNC_PROTO
+ || first->GetParentType() == 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->GetStr()[0]))
+ {
+ Chunk *prev = first->GetPrev();
+
+ if (prev->Is(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 ( first->GetParentType() == CT_FUNC_VAR
+ || first->GetParentType() == 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 (second->Is(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 (second->Is(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 ( second->Is(CT_PTR_TYPE)
+ && first->IsNot(CT_IN))
+ {
+ // look back for '->' type is TRAILING_RET
+ if (token_is_within_trailing_return(second))
+ {
+ if (first->Is(CT_QUALIFIER))
+ {
+ log_rule("sp_qualifier_ptr_star_trailing");
+ return(options::sp_qualifier_ptr_star_trailing());
+ }
+ else
+ {
+ log_rule("sp_before_ptr_star_trailing"); // ptr_star 7
+ return(options::sp_before_ptr_star_trailing());
+ }
+ }
+ // Find the next non-'*' chunk
+ Chunk *next = second;
+
+ do
+ {
+ next = next->GetNext();
+ } while (next->Is(CT_PTR_TYPE));
+
+ if ( next->Is(CT_FUNC_DEF)
+ || next->Is(CT_FUNC_PROTO))
+ {
+ // Add or remove space before a pointer star '*', if followed by a function
+ // prototype or function definition. If set to ignore, sp_before_ptr_star is
+ // used instead.
+
+ if (first->Is(CT_QUALIFIER))
+ {
+ if (options::sp_qualifier_ptr_star_func() != IARF_IGNORE)
+ {
+ log_rule("sp_qualifier_ptr_star_func");
+ return(options::sp_qualifier_ptr_star_func());
+ }
+ }
+ else
+ {
+ if (options::sp_before_ptr_star_func() != IARF_IGNORE)
+ {
+ log_rule("sp_before_ptr_star_func"); // ptr_star 6
+ return(options::sp_before_ptr_star_func());
+ }
+ }
+ }
+ else
+ {
+ // 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.
+
+ next = second->GetNextNc();
+
+ while (next->Is(CT_PTR_TYPE))
+ {
+ next = next->GetNextNc();
+ }
+
+ if ( next->IsNotNullChunk()
+ && next->IsNot(CT_WORD))
+ {
+ if (first->Is(CT_QUALIFIER))
+ {
+ if (options::sp_qualifier_unnamed_ptr_star() != IARF_IGNORE)
+ {
+ log_rule("sp_qualifier_unnamed_ptr_star");
+ return(options::sp_qualifier_unnamed_ptr_star());
+ }
+ }
+ else
+ {
+ if (next->Is(CT_QUALIFIER))
+ {
+ if (options::sp_before_qualifier_ptr_star() != IARF_IGNORE)
+ {
+ log_rule("sp_before_qualifier_ptr_star"); // ptr_star 11
+ return(options::sp_before_qualifier_ptr_star());
+ }
+ }
+ else if (next->Is(CT_OPERATOR))
+ {
+ if (options::sp_before_operator_ptr_star() != IARF_IGNORE)
+ {
+ log_rule("sp_before_operator_ptr_star"); // ptr_star 14
+ return(options::sp_before_operator_ptr_star());
+ }
+ }
+ else if (next->Is(CT_DC_MEMBER))
+ {
+ if (options::sp_before_global_scope_ptr_star() != IARF_IGNORE)
+ {
+ log_rule("sp_before_global_scope_ptr_star"); // ptr_star 13
+ return(options::sp_before_global_scope_ptr_star());
+ }
+ }
+ else
+ {
+ Chunk *next_next = next->GetNextNc();
+
+ if (next_next->IsNotNullChunk() && next_next->Is(CT_DC_MEMBER))
+ {
+ if (options::sp_before_scope_ptr_star() != IARF_IGNORE)
+ {
+ log_rule("sp_before_scope_ptr_star"); // ptr_star 12
+ return(options::sp_before_scope_ptr_star());
+ }
+ }
+ }
+
+ if (options::sp_before_unnamed_ptr_star() != IARF_IGNORE)
+ {
+ 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 (first->Is(CT_OPERATOR))
+ {
+ // Add or remove space between 'operator' and operator sign.
+ log_rule("sp_after_operator");
+ return(options::sp_after_operator());
+ }
+
+ if ( second->Is(CT_FUNC_PROTO)
+ || second->Is(CT_FUNC_DEF))
+ {
+ if ( first->IsNot(CT_PTR_TYPE)
+ && first->IsNot(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 ( ( first->GetParentType() == CT_C_CAST
+ || first->GetParentType() == CT_D_CAST)
+ && first->Is(CT_PAREN_CLOSE))
+ {
+ log_rule("sp_after_cast");
+ return(options::sp_after_cast());
+ }
+
+ if (first->Is(CT_BRACE_CLOSE))
+ {
+ if (second->Is(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)
+ && second->Is(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 (second->Is(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 (second->Is(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 (first->Is(CT_BRACE_OPEN))
+ {
+ if (first->GetParentType() == CT_ENUM)
+ {
+ // Add or remove space inside enum '{' and '}'.
+ log_rule("sp_inside_braces_enum");
+ return(options::sp_inside_braces_enum());
+ }
+
+ if ( first->GetParentType() == CT_STRUCT
+ || first->GetParentType() == CT_UNION)
+ {
+ // Fix for issue #1240 adding space in struct initializers
+ Chunk *tmp = first->GetPrevNcNnl();
+
+ if (tmp->Is(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 ( first->GetParentType() == 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 (first->GetParentType() == 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
+ && second->Is(CT_BRACE_OPEN)
+ && second->GetParentType() == 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 ( first->Is(CT_BRACE_CLOSE)
+ && first->TestFlags(PCF_IN_TYPEDEF)
+ && ( first->GetParentType() == CT_ENUM
+ || first->GetParentType() == CT_STRUCT
+ || first->GetParentType() == 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)
+ && second->Is(CT_PAREN_OPEN)
+ && second->GetParentType() == 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 ( first->Is(CT_PAREN_CLOSE)
+ && first->GetParentType() == CT_DECLTYPE
+ && ( second->Is(CT_WORD)
+ || second->Is(CT_BRACE_OPEN)
+ || second->Is(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)
+ && first->Is(CT_PAREN_CLOSE)
+ && second->Is(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)
+ && first->Is(CT_PAREN_CLOSE)
+ && first->GetParentType() == CT_D_TEMPLATE)
+ {
+ if (second->GetParentType() == CT_USING_ALIAS)
+ {
+ log_rule("sp_after_type | ADD");
+ return(options::sp_after_type() | IARF_ADD);
+ }
+
+ if (second->Is(CT_WORD))
+ {
+ Chunk *open_paren = first->GetOpeningParen();
+ Chunk *type = open_paren->GetPrev()->GetPrev();
+
+ if (type->Is(CT_TYPE))
+ {
+ log_rule("sp_after_type");
+ return(options::sp_after_type());
+ }
+ }
+ }
+
+ if ( first->Is(CT_TYPE) // Issue #3457
+ && second->Is(CT_COLON))
+ {
+ log_rule("sp_type_colon");
+ return(options::sp_type_colon());
+ }
+
+ if ( !second->Is(CT_PTR_TYPE)
+ && ( first->Is(CT_QUALIFIER)
+ || first->Is(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 ( first->Is(CT_PTR_TYPE)
+ && second->Is(CT_ELLIPSIS))
+ {
+ log_rule("sp_ptr_type_ellipsis");
+ return(options::sp_ptr_type_ellipsis());
+ }
+
+ // If nothing claimed the PTR_TYPE, then return ignore
+ if ( first->Is(CT_PTR_TYPE)
+ || second->Is(CT_PTR_TYPE))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ if (first->Is(CT_NOT))
+ {
+ if ( second->Is(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 (first->Is(CT_INV))
+ {
+ // Add or remove space after the '~' (invert) unary operator.
+ log_rule("sp_inv");
+ return(options::sp_inv());
+ }
+
+ if (first->Is(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 (first->Is(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 ( first->Is(CT_POS)
+ || first->Is(CT_NEG))
+ {
+ // Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'.
+ log_rule("sp_sign");
+ return(options::sp_sign());
+ }
+
+ if ( first->Is(CT_INCDEC_BEFORE)
+ || second->Is(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 (second->Is(CT_CS_SQ_COLON))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ if (first->Is(CT_CS_SQ_COLON))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE);
+ }
+
+ if ( language_is_set(LANG_OC)
+ && first->Is(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)
+ && first->Is(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)
+ && second->Is(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)
+ && first->Is(CT_OC_COLON))
+ {
+ if (first->TestFlags(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)
+ && second->Is(CT_OC_COLON))
+ {
+ if ( first->TestFlags(PCF_IN_OC_MSG)
+ && ( first->Is(CT_OC_MSG_FUNC)
+ || first->Is(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 ( second->Is(CT_COMMENT)
+ && second->GetParentType() == 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 (first->Is(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 ( first->Is(CT_NEW)
+ && second->Is(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 ( first->Is(CT_NEW)
+ || first->Is(CT_DELETE)
+ || ( first->Is(CT_TSQUARE)
+ && first->GetParentType() == 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)
+ && first->Is(CT_ANNOTATION)
+ && second->IsParenOpen())
+ {
+ // (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)
+ && first->Is(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)
+ && first->Is(CT_EXTERN)
+ && second->Is(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 ( second->Is(CT_TYPE)
+ && ( ( first->Is(CT_STRING)
+ && first->GetParentType() == CT_EXTERN)
+ || ( first->Is(CT_FPAREN_CLOSE)
+ && first->GetParentType() == CT_ATTRIBUTE)))
+ {
+ log_rule("FORCE");
+ return(IARF_FORCE); /* TODO: make this configurable? */
+ }
+
+ if (first->Is(CT_NOEXCEPT))
+ {
+ // Add or remove space after 'noexcept'.
+ log_rule("sp_after_noexcept");
+ return(options::sp_after_noexcept());
+ }
+
+ // Issue #2138
+ if (first->Is(CT_FPAREN_CLOSE))
+ {
+ if (second->Is(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 (second->Is(CT_NOEXCEPT))
+ {
+ // Add or remove space between ')' and 'noexcept'.
+ log_rule("sp_paren_noexcept");
+ return(options::sp_paren_noexcept());
+ }
+ }
+
+ // Issue #2098
+ if ( first->Is(CT_PP_PRAGMA)
+ && second->Is(CT_PREPROC_BODY))
+ {
+ log_rule("REMOVE");
+ return(IARF_REMOVE);
+ }
+
+ // Issue #1733
+ if ( first->Is(CT_OPERATOR_VAL)
+ && second->Is(CT_TYPE))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ // Issue #995
+ if ( first->Is(CT_DO)
+ && second->Is(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 ( first->Is(CT_BRACE_CLOSE)
+ && second->Is(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 ( first->Is(CT_NEWLINE)
+ && second->Is(CT_BRACE_OPEN))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ // =============================================================
+ // category 0
+ // this table lists out all combos where nothing is to do
+ // CT_UNKNOWN is a wildcard.
+ for (auto it : IGNORE_space_table)
+ {
+ if ( ( it.first == CT_UNKNOWN
+ || it.first == first->GetType())
+ && ( it.second == CT_UNKNOWN
+ || it.second == second->GetType()))
+ {
+ log_rule("IGNORE from IGNORE_space_table");
+ return(IARF_IGNORE);
+ }
+ }
+
+ // =============================================================
+ // category 1
+ // this table lists out all combos where a space should NOT be present
+ // CT_UNKNOWN is a wildcard.
+ size_t number = 0;
+
+ for (auto it : no_space_table)
+ {
+ if ( ( it.first == CT_UNKNOWN
+ || it.first == first->GetType())
+ && ( it.second == CT_UNKNOWN
+ || it.second == second->GetType()))
+ {
+ char text[80];
+ sprintf(text, "REMOVE from no_space_table @ %zu.", number);
+ log_rule(text);
+ return(IARF_REMOVE);
+ }
+ number++;
+ }
+
+ // =============================================================
+ // category 2
+ // this table lists out all combos where a space MUST be present
+ number = 0;
+
+ for (auto it : add_space_table)
+ {
+ if ( it.first == first->GetType()
+ && it.second == second->GetType())
+ {
+ char text[80];
+ sprintf(text, "ADD from add_space_table @ %zu.", number);
+ log_rule(text);
+ return(IARF_ADD);
+ }
+ number++;
+ }
+
+ // Issue #2386
+ if ( first->Is(CT_FORM_FEED)
+ || second->Is(CT_FORM_FEED))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+
+ // TODO: if necessary create a new option
+ if ( first->Is(CT_MACRO_FUNC_CALL)
+ && second->Is(CT_FPAREN_OPEN))
+ {
+ log_rule("IGNORE");
+ return(IARF_IGNORE);
+ }
+ //// TODO: if necessary create a new option
+ //if ( first->Is(CT_RPAREN_OPEN)
+ // && second->Is(CT_RPAREN_CLOSE))
+ //{
+ // log_rule("IGNORE");
+ // return(IARF_IGNORE);
+ //}
+
+ //// TODO: if necessary create a new option
+ //if ( first->Is(CT_RPAREN_OPEN)
+ // && second->Is(CT_UNKNOWN))
+ //{
+ // log_rule("IGNORE");
+ // return(IARF_IGNORE);
+ //}
+
+ //// TODO: if necessary create a new option
+ //if ( first->Is(CT_UNKNOWN)
+ // && second->Is(CT_RPAREN_CLOSE))
+ //{
+ // log_rule("IGNORE");
+ // return(IARF_IGNORE);
+ //}
+
+ if ( first->Is(CT_CASE_ELLIPSIS)
+ && second->Is(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 ( first->Is(CT_NUMBER)
+ && second->Is(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());
+ }
+ }
+ // =============================================================
+ // category 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, orig col is %zu, Text() '%s', GetType() is %s\n",
+ first->GetOrigLine(), first->GetOrigCol(), first->Text(), get_token_name(first->GetType()));
+ LOG_FMT(LSPACE, " second orig line is %zu, orig col is %zu, Text() '%s', GetType() is %s\n",
+ second->GetOrigLine(), second->GetOrigCol(), second->Text(), get_token_name(second->GetType()));
+ 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, " { CT_%s, CT_%s},\n",
+ get_token_name(first->GetType()), get_token_name(second->GetType()));
+ 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->TestFlags(PCF_FORCE_SPACE))
+ {
+ LOG_FMT(LSPACE, "%s(%d): force between '%s' and '%s'\n",
+ __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)
+{
+ return(ensure_force_space(first, second, do_space(first, second, min_sp)));
+}
+
+
+void space_text()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *pc = Chunk::GetHead();
+ Chunk *next;
+ size_t prev_column;
+ size_t column = pc->GetColumn();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount());
+ }
+ 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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()));
+ }
+
+ 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->GetOrigLine(), get_token_name(pc->GetType()));
+ pc->SetFlagBits(PCF_IN_QT_MACRO); // flag the chunk for a second processing
+
+ // save the values
+ save_set_options_for_QT(pc->GetLevel());
+ }
+
+ // 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()
+ && !next->IsNewline()
+ && next->IsVBrace())
+ {
+ LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, Skip %s (%zu+%zu)\n",
+ __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), get_token_name(next->GetType()),
+ pc->GetColumn(), pc->GetStr().size());
+ next->SetColumn(pc->GetColumn() + pc->GetStr().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()
+ && nn->Is(CT_SPACE))
+ {
+ Chunk::Delete(nn); // remove the space
+ }
+ }
+
+ /*
+ * If the current chunk contains a newline, do not change the column
+ * of the next item
+ */
+ if ( pc->IsNewline()
+ || pc->Is(CT_COMMENT_MULTI))
+ {
+ column = next->GetColumn();
+ }
+ else
+ {
+ // Set to the minimum allowed column
+ if (pc->GetNlCount() == 0)
+ {
+ column += pc->Len();
+ }
+ else
+ {
+ column = pc->GetOrigColEnd();
+ }
+ 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.
+ */
+ pc->ResetFlagBits(PCF_FORCE_SPACE);
+
+ if ( (pc->Len() > 0)
+ && !pc->IsString("[]")
+ && !pc->IsString("{{")
+ && !pc->IsString("}}")
+ && !pc->IsString("()")
+ && !pc->GetStr().startswith("@\""))
+ {
+ // Find the next non-empty chunk on this line
+ Chunk *tmp = next;
+
+ while ( tmp->IsNotNullChunk()
+ && (tmp->Len() == 0)
+ && !tmp->IsNewline())
+ {
+ tmp = tmp->GetNext();
+ }
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->Len() > 0)
+ {
+ bool kw1 = CharTable::IsKw2(pc->GetStr()[pc->Len() - 1]);
+ bool kw2 = CharTable::IsKw1(next->GetStr()[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());
+ pc->SetFlagBits(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)))
+ && pc->Is(CT_ANGLE_CLOSE)
+ && next->Is(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());
+ pc->SetFlagBits(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->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ 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;
+
+ // Handle the condition of a CT_VBRACE_OPEN with more complicated spacing mechanics.
+ if ( pc->Is(CT_VBRACE_OPEN)
+ && next->GetOrigCol() >= pc->GetPrev()->GetOrigCol())
+ {
+ delta = next->GetOrigCol() - pc->GetPrev()->GetOrigCol();
+
+ if ((delta - 1) < min_sp)
+ {
+ column += min_sp;
+ break;
+ }
+ column += (delta - 1);
+ break;
+ }
+
+ if ( next->GetOrigCol() >= pc->GetOrigColEnd()
+ && pc->GetOrigColEnd() != 0)
+ {
+ // Keep the same relative spacing, minimum 1
+ delta = next->GetOrigCol() - pc->GetOrigColEnd();
+
+ 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->GetOrigCol() >= pc->GetOrigColEnd()
+ && pc->GetOrigColEnd() != 0)
+ {
+ column += next->GetOrigCol() - pc->GetOrigColEnd();
+ }
+ else
+ {
+ // preserve the position if virtual brace
+ // Issue #1854
+ if (pc->Is(CT_VBRACE_OPEN))
+ {
+ column = next->GetOrigCol();
+ }
+ }
+ break;
+
+ default:
+ // If we got here, something is wrong...
+ break;
+ } // switch
+
+ if ( next->IsComment()
+ && next->GetNext()->IsNewline()
+ && column < next->GetOrigCol())
+ {
+ /*
+ * 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
+ || next->GetParentType() != CT_COMMENT_END)
+ && ( options::sp_endif_cmt() == IARF_IGNORE
+ || ( pc->IsNot(CT_PP_ELSE)
+ && pc->IsNot(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', orig col is %zu, next orig col is %zu, pc orig col end is %zu\n",
+ __func__, __LINE__, pc->Text(),
+ pc->GetOrigCol(), next->GetOrigCol(), pc->GetOrigColEnd());
+ column = pc->GetColumn() + (next->GetOrigCol() - pc->GetOrigColEnd());
+ }
+ 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->GetColumn() + pc->Len() + ((next->GetOrigPrevSp() > 0) ? 1 : 0);
+ column = next->GetOrigCol();
+
+ if (column < col_min)
+ {
+ column = col_min;
+ }
+ LOG_FMT(LSPACE, "%s(%d): <relative set>", __func__, __LINE__);
+ }
+ }
+ }
+ next->SetColumn(column);
+ LOG_FMT(LSPACE, "%s(%d): orig line is %zu, orig col is %zu, pc-Text() '%s', type is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType()));
+ LOG_FMT(LSPACE, "%s(%d): ",
+ __func__, __LINE__);
+ 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->GetColumn());
+
+ if (restoreValues) // guy 2015-09-22
+ {
+ restore_options_for_QT();
+ }
+ }
+ pc = next;
+
+ if (QT_SIGNAL_SLOT_found)
+ {
+ // flag the chunk for a second processing
+ pc->SetFlagBits(PCF_IN_QT_MACRO);
+ }
+ }
+} // space_text
+
+
+void space_text_balance_nested_parens()
+{
+ 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 ( first->IsString("(")
+ && next->IsString("("))
+ {
+ // insert a space between them
+ space_add_after(first, 1);
+
+ // test after the closing parens Issue #1703
+ Chunk *closing = first->GetNextType((E_Token)(first->GetType() + 1), first->GetLevel());
+
+ if (closing->GetOrigCol() == closing->GetPrev()->GetOrigColEnd())
+ {
+ space_add_after(closing->GetPrev(), 1);
+ }
+ }
+ else if ( first->IsString(")")
+ && next->IsString(")"))
+ {
+ // 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->GetType() - 1), next->GetLevel());
+
+ if (opening->GetOrigColEnd() == opening->GetNext()->GetOrigCol())
+ {
+ 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->GetOrigCol() > (first->GetOrigCol() + first->Len()));
+ }
+}
+
+
+size_t space_col_align(Chunk *first, Chunk *second)
+{
+ LOG_FUNC_ENTRY();
+
+ LOG_FMT(LSPACE, "%s(%d): 1st orig line %zu, orig col %zu, [%s/%s], text '%s' <==>\n",
+ __func__, __LINE__, first->GetOrigLine(), first->GetOrigCol(),
+ get_token_name(first->GetType()), get_token_name(first->GetParentType()),
+ first->Text());
+ LOG_FMT(LSPACE, "%s(%d): 2nd orig line %zu, orig col %zu, [%s/%s], text '%s'\n",
+ __func__, __LINE__, second->GetOrigLine(), second->GetOrigCol(),
+ get_token_name(second->GetType()), get_token_name(second->GetParentType()),
+ 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->GetNlCount() > 0)
+ {
+ LOG_FMT(LSPACE, "%s(%d): new line count %zu, orig col end %zu\n",
+ __func__, __LINE__, first->GetNlCount(), first->GetOrigColEnd());
+ coldiff = first->GetOrigColEnd() - 1;
+ }
+ else
+ {
+ LOG_FMT(LSPACE, "%s(%d): '1st' 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->GetOrigLine());
+ LOG_FMT(LSPACE, "%s(%d): => second orig line is %zu\n", __func__, __LINE__, second->GetOrigLine());
+ 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->GetOrigCol());
+ LOG_FMT(LSPACE, "%s(%d): => second orig col is %zu\n", __func__, __LINE__, second->GetOrigCol());
+ LOG_FMT(LSPACE, "%s(%d): => first len is %zu\n", __func__, __LINE__, first->Len());
+
+ if ( first->GetOrigLine() == second->GetOrigLine()
+ && second->GetOrigCol() > (first->GetOrigCol() + 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()
+ || next->IsNewline())
+ {
+ return;
+ }
+
+ // Limit to 16 spaces
+ if (count > 16)
+ {
+ count = 16;
+ }
+
+ // Two CT_SPACE in a row -- use the max of the two
+ if (next->Is(CT_SPACE))
+ {
+ if (next->Len() < count)
+ {
+ while (next->Len() < count)
+ {
+ next->Str().append(' ');
+ }
+ }
+ return;
+ }
+ Chunk sp;
+
+ sp.SetType(CT_SPACE);
+ sp.SetFlags(pc->GetFlags() & PCF_COPY_FLAGS);
+ sp.Str() = " "; // 16 spaces
+ sp.Str().resize(count);
+ sp.SetLevel(pc->GetLevel());
+ sp.SetBraceLevel(pc->GetBraceLevel());
+ sp.SetPpLevel(pc->GetPpLevel());
+ sp.SetColumn(pc->GetColumn() + pc->Len());
+ sp.SetOrigLine(pc->GetOrigLine());
+ sp.SetOrigCol(pc->GetOrigCol());
+
+ sp.CopyAndAddAfter(pc);
+} // space_add_after
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/space.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/space.h
new file mode 100644
index 00000000..275772f2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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();
+
+
+//! Marches through the whole file and adds spaces around nested parenthesis
+void space_text_balance_nested_parens();
+
+
+//! 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.78.0/src/symbols_table.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/symbols_table.h
new file mode 100644
index 00000000..bcf7c8b2
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/symbols_table.h
@@ -0,0 +1,148 @@
+/**
+ * @file symbols
+ * Manages the table of punctuators.
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+/**
+ *
+ * Content of the generated "punctuator_table.h" file is based off this.
+ *
+ * NOTE: the tables below do not need to be sorted.
+ */
+
+#include "uncrustify_types.h"
+
+// 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.78.0/src/token_enum.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/token_enum.h
new file mode 100644
index 00000000..6c912e07
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/token_enum.h
@@ -0,0 +1,405 @@
+/**
+ * @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_CPP_ENDIF, // C++ comment, single line, after #endif or #else
+ CT_COMMENT_ENDIF, // C-comment, single line, after #endif or #else
+
+ 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, // conditional question in 'b ? t : f'
+ 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_RPAREN_OPEN, // functor Issue #3914
+ CT_RPAREN_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_ENUM_COLON, // a ':' in a enum definition
+
+ 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_ENDASM, // end of assembly code section
+ 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.78.0/src/tokenize.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize.cpp
new file mode 100644
index 00000000..846755fe
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize.cpp
@@ -0,0 +1,2946 @@
+/**
+ * @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 TokenInfo
+{
+ TokenInfo()
+ : last_ch(0)
+ , idx(0)
+ , row(1)
+ , col(1)
+ {
+ }
+
+ size_t last_ch;
+ size_t idx;
+ size_t row;
+ size_t col;
+};
+
+
+struct TokenContext
+{
+ TokenContext(const deque<int> &d)
+ : data(d)
+ {
+ }
+
+
+ //! save before trying to parse something that may fail
+ void save()
+ {
+ save(s);
+ }
+
+
+ void save(TokenInfo &info)
+ {
+ info = c;
+ }
+
+
+ //! restore previous saved state
+ void restore()
+ {
+ restore(s);
+ }
+
+
+ void restore(const TokenInfo &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;
+ TokenInfo c; //! current
+ TokenInfo 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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &ctx, Chunk &pc, E_Token tt);
+
+
+static bool parse_ignored(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &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(TokenContext &ctx, Chunk &pc);
+
+
+static bool d_parse_string(TokenContext &ctx, Chunk &pc)
+{
+ size_t ch = ctx.peek();
+
+ if ( ch == '"' // 34
+ || ch == '\'') // 39
+ {
+ return(parse_string(ctx, pc, 0, true));
+ }
+
+ if (ch == '`') // 96
+ {
+ return(parse_string(ctx, pc, 0, false));
+ }
+
+ if ( ( ch == 'r' // 114
+ || ch == 'x') // 120
+ && ctx.peek(1) == '"') // 34
+ {
+ return(parse_string(ctx, pc, 1, false));
+ }
+
+ if (ch != '\\')
+ {
+ return(false);
+ }
+ ctx.save();
+ int cnt;
+
+ pc.Str().clear();
+
+ while (ctx.peek() == '\\') // 92
+ {
+ 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() == ';') // 59
+ {
+ pc.Str().append(ctx.get());
+ }
+ break;
+
+ default:
+ // Everything else is a single character
+ pc.Str().append(ctx.get());
+ break;
+ } // switch
+ }
+
+ if (pc.GetStr().size() < 1)
+ {
+ ctx.restore();
+ return(false);
+ }
+ pc.SetType(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(TokenContext &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 == '/') // 47
+ {
+ pc.SetType(CT_COMMENT_CPP);
+
+ while (true)
+ {
+ int bs_cnt = 0;
+
+ while (ctx.more())
+ {
+ ch = ctx.peek();
+
+ if ( (ch == '\r')
+ || (ch == '\n'))
+ {
+ break;
+ }
+
+ if ( (ch == '\\') // 92
+ && !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.SetNlCount(pc.GetNlCount() + 1);
+ cpd.did_newline = true;
+ }
+ }
+ else if (!ctx.more())
+ {
+ // unexpected end of file
+ ctx.restore();
+ return(false);
+ }
+ else if (ch == '+') // 43
+ {
+ pc.SetType(CT_COMMENT);
+ d_level++;
+
+ while ( d_level > 0
+ && ctx.more())
+ {
+ if ( (ctx.peek() == '+') // 43
+ && (ctx.peek(1) == '/')) // 47
+ {
+ pc.Str().append(ctx.get()); // store the '+'
+ pc.Str().append(ctx.get()); // store the '/'
+ d_level--;
+ continue;
+ }
+
+ if ( (ctx.peek() == '/') // 47
+ && (ctx.peek(1) == '+')) // 43
+ {
+ 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'))
+ {
+ pc.SetType(CT_COMMENT_MULTI);
+ pc.SetNlCount(pc.GetNlCount() + 1);
+
+ 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 '/ *'
+ {
+ pc.SetType(CT_COMMENT);
+
+ while (ctx.more())
+ {
+ if ( (ctx.peek() == '*') // 43
+ && (ctx.peek(1) == '/')) // 47
+ {
+ pc.Str().append(ctx.get()); // store the '*'
+ pc.Str().append(ctx.get()); // store the '/'
+
+ TokenInfo ss;
+ ctx.save(ss);
+ size_t oldsize = pc.GetStr().size();
+
+ // If there is another C comment right after this one, combine them
+ while ( (ctx.peek() == ' ') // 32
+ || (ctx.peek() == '\t')) // tab
+ {
+ 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'))
+ {
+ pc.SetType(CT_COMMENT_MULTI);
+ pc.SetNlCount(pc.GetNlCount() + 1);
+
+ 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.GetStr()) >= 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.GetOrigLine());
+ cpd.unc_off = false;
+ }
+ }
+ else
+ {
+ auto position_disable_processing_cmt = find_disable_processing_comment_marker(pc.GetStr());
+ 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.GetStr());
+
+ 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.GetOrigLine());
+ cpd.unc_off = true;
+ // Issue #842
+ cpd.unc_off_used = true;
+ }
+ }
+ }
+ return(true);
+} // parse_comment
+
+
+static bool parse_code_placeholder(TokenContext &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 == '#') // 35
+ && (last1 == '>')) // 62
+ {
+ pc.SetType(CT_WORD);
+ return(true);
+ }
+ }
+ ctx.restore();
+ return(false);
+}
+
+
+static void parse_suffix(TokenContext &ctx, Chunk &pc, bool forstring = false)
+{
+ if (CharTable::IsKw1(ctx.peek()))
+ {
+ size_t slen = 0;
+ size_t oldsize = pc.GetStr().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') // 76
+ && ( (p2 == '"') // 34
+ || (p2 == '\''))) // 39
+ || ( (p1 == 'S') // 83
+ && (p2 == '"')))) // 34
+ {
+ return;
+ }
+ TokenInfo ss;
+ ctx.save(ss);
+
+ while ( ctx.more()
+ && CharTable::IsKw2(ctx.peek()))
+ {
+ slen++;
+ pc.Str().append(ctx.get());
+ }
+
+ if ( forstring
+ && slen >= 4
+ && ( pc.GetStr().startswith("PRI", oldsize)
+ || pc.GetStr().startswith("SCN", oldsize)))
+ {
+ ctx.restore(ss);
+ pc.Str().resize(oldsize);
+ }
+ }
+} // parse_suffix
+
+
+static bool is_bin(int ch)
+{
+ return( (ch == '0') // 48
+ || (ch == '1')); // 49
+}
+
+
+static bool is_bin_(int ch)
+{
+ return( is_bin(ch)
+ || ch == '_' // 95
+ || ch == '\''); // 39
+}
+
+
+static bool is_oct(int ch)
+{
+ return( (ch >= '0') // 48
+ && (ch <= '7')); // 55
+}
+
+
+static bool is_oct_(int ch)
+{
+ return( is_oct(ch)
+ || ch == '_' // 95
+ || ch == '\''); // 39
+}
+
+
+static bool is_dec(int ch)
+{
+ return( (ch >= '0') // 48
+ && (ch <= '9')); // 57
+}
+
+
+static bool is_dec_(int ch)
+{
+ // number separators: JAVA: "_", C++14: "'"
+ return( is_dec(ch)
+ || (ch == '_') // 95
+ || (ch == '\'')); // 39
+}
+
+
+static bool is_hex(int ch)
+{
+ return( ( (ch >= '0') // 48
+ && (ch <= '9')) // 57
+ || ( (ch >= 'a') // 97
+ && (ch <= 'f')) // 102
+ || ( (ch >= 'A') // 65
+ && (ch <= 'F'))); // 70
+}
+
+
+static bool is_hex_(int ch)
+{
+ return( is_hex(ch)
+ || ch == '_' // 95
+ || ch == '\''); // 39
+}
+
+
+static bool parse_number(TokenContext &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() != '.') // 46
+ || !is_dec(ctx.peek(1))))
+ {
+ return(false);
+ }
+ bool is_float = (ctx.peek() == '.'); // 46
+
+ if ( is_float
+ && (ctx.peek(1) == '.')) // make sure it isn't '..' 46
+ {
+ 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' // 48
+ && !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.GetStr()[pc_temp.Len() - 1];
+ ctx.restore();
+ LOG_FMT(LBCTRL, "%s(%d): pc_temp:%s\n", __func__, __LINE__, pc_temp.Text());
+
+ if (ch == 'h') // TODO can we combine this in analyze_character 104
+ {
+ // we have an MS hexadecimal number with "h" at the end
+ LOG_FMT(LBCTRL, "%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(LBCTRL, "%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() == '.') // 46
+ && (ctx.peek(1) != '.')) // 46
+ {
+ // Issue #1265, 5.clamp()
+ TokenInfo 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) == '(') // 40
+ {
+ ctx.restore(ss);
+ pc.SetType(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') // 69
+ || (tmp == 'P')) // 80
+ {
+ is_float = true;
+ pc.Str().append(ctx.get());
+
+ if ( (ctx.peek() == '+') // 43
+ || (ctx.peek() == '-')) // 45
+ {
+ 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());
+
+ // https://en.cppreference.com/w/cpp/language/floating_literal
+ if ( (tmp2 == 'I') // 73
+ || (tmp2 == 'F') // 70
+ || (tmp2 == 'D') // 68
+ || (tmp2 == 'M')) // 77
+ {
+ // is a decimal point found? Issue #4027
+ const char *test_it = pc.Text();
+ size_t test_long = strlen(test_it);
+ bool point_found = false;
+
+ for (size_t ind = 0; ind < test_long; ind++)
+ {
+ if (test_it[ind] == '.')
+ {
+ point_found = true;
+ break;
+ }
+ }
+
+ if (point_found)
+ {
+ is_float = true;
+ }
+ else
+ {
+ // append the char(s) until is not IsKw2
+ while (ctx.more())
+ {
+ size_t ch = ctx.peek();
+
+ if (CharTable::IsKw2(ch))
+ {
+ pc.Str().append(ctx.get());
+ }
+ else
+ {
+ break;
+ }
+ }
+ pc.SetType(CT_WORD);
+ return(true);
+ }
+ }
+ else if ( (tmp2 != 'L') // 76
+ && (tmp2 != 'U')) // 85
+ {
+ break;
+ }
+ pc.Str().append(ctx.get());
+ }
+
+ // skip the Microsoft-specific '8' suffix
+ if ((ctx.peek() == '8')) // 56
+ {
+ pc.Str().append(ctx.get());
+ }
+
+ // skip the Microsoft-specific '16', '32' and '64' suffix
+ if ( ( (ctx.peek() == '1') // 49
+ && (ctx.peek(1) == '6')) // 54
+ || ( (ctx.peek() == '3') // 51
+ && (ctx.peek(1) == '2')) // 50
+ || ( (ctx.peek() == '6') // 54
+ && (ctx.peek(1) == '4'))) // 52
+ {
+ pc.Str().append(ctx.get());
+ pc.Str().append(ctx.get());
+ }
+
+ // skip the Microsoft-specific '128' suffix
+ if (( (ctx.peek() == '1') // 49
+ && (ctx.peek(1) == '2') // 50
+ && (ctx.peek(2) == '8'))) // 56
+ {
+ pc.Str().append(ctx.get());
+ pc.Str().append(ctx.get());
+ pc.Str().append(ctx.get());
+ }
+ pc.SetType(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(TokenContext &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());
+ }
+ pc.SetType(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.SetNlCount(pc.GetNlCount() + 1);
+ pc.SetType(CT_STRING_MULTI);
+ }
+ else if ( ch == '\r'
+ && ctx.peek() != '\n')
+ {
+ pc.Str().append(ctx.get());
+ pc.SetNlCount(pc.GetNlCount() + 1);
+ pc.SetType(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(TokenContext &ctx, Chunk &pc)
+{
+ cs_string_t stringType = CS_STRING_NONE;
+ int offset = 0;
+
+ if (ctx.peek(offset) == '$') // 36
+ {
+ stringType |= CS_STRING_INTERPOLATED;
+ ++offset;
+ }
+
+ if (ctx.peek(offset) == '@') // 64
+ {
+ stringType |= CS_STRING_VERBATIM;
+ ++offset;
+ }
+
+ if (ctx.peek(offset) == '"') // 34
+ {
+ stringType |= CS_STRING_STRING;
+
+ pc.SetType(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(TokenContext &ctx, Chunk &pc)
+{
+ cs_string_t stringType = parse_cs_string_start(ctx, pc);
+
+ if (stringType == CS_STRING_NONE)
+ {
+ 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() == '}') // 125
+ {
+ pc.Str().append(ctx.get());
+
+ if (ctx.peek() == '}') // 125
+ {
+ 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 != CS_STRING_NONE)
+ {
+ parseState.push(CsStringParseState(stringType));
+ continue;
+ }
+ }
+ int lastcol = ctx.c.col;
+ int ch = ctx.get();
+
+ pc.Str().append(ch);
+
+ if (ch == '\n')
+ {
+ pc.SetType(CT_STRING_MULTI);
+ pc.SetNlCount(pc.GetNlCount() + 1);
+ }
+ else if (ch == '\r')
+ {
+ pc.SetType(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.GetOrigLine(), pc.GetOrigCol());
+ 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)
+ {
+ // TODO: replace the code ?? 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() == '"' // 34
+ || ctx.peek() == '\\') // 92
+ {
+ pc.Str().append(ctx.get());
+ }
+ }
+ else if (ch == '"') // 34
+ {
+ if ( (parseState.top().type & CS_STRING_VERBATIM)
+ && (ctx.peek() == '"')) // 34
+ {
+ // 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 == '{') // 123
+ {
+ if (ctx.peek() == '{') // 123
+ {
+ 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(TokenContext &ctx, Chunk &pc)
+{
+ pc.SetType(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 == '"') // 34
+ && (ctx.peek() == '"') // 34
+ && (ctx.peek(1) == '"')) // 34
+ {
+ pc.Str().append(ctx.get());
+ pc.Str().append(ctx.get());
+ break;
+ }
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ pc.SetType(CT_STRING_MULTI);
+ pc.SetNlCount(pc.GetNlCount() + 1);
+ }
+ }
+}
+
+
+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(TokenContext &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);
+ }
+ pc.SetType(CT_STRING);
+
+ while (ctx.more())
+ {
+ if ( (ctx.peek() == ')') // 41
+ && (ctx.peek(tag_len + 1) == '"') // 34
+ && 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.SetNlCount(pc.GetNlCount() + 1);
+ pc.SetType(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(TokenContext &ctx, Chunk &pc, bool skipcheck)
+{
+ static UncText 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 == '\\') // 92
+ && (unc_tolower(ctx.peek(1)) == 'u')) // 117
+ {
+ 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;
+ }
+ }
+ pc.SetType(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() == '(') // 40
+ {
+ pc.SetType(CT_MACRO_FUNC);
+ }
+ else
+ {
+ pc.SetType(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.GetStr().startswith("@")
+ && !pc.GetStr().equals(intr_txt))
+ {
+ pc.SetType(CT_ANNOTATION);
+ }
+ else
+ {
+ // Turn it into a keyword now
+ // Issue #1460 will return "COMMENT_CPP"
+ pc.SetType(find_keyword_type(pc.Text(), pc.GetStr().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.GetType() == CT_PP_IGNORE
+ && !cpd.in_preproc)
+ {
+ pc.SetType(find_keyword_type(pc.Text(), pc.GetStr().size()));
+ }
+ else if (pc.GetType() == 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 == '\\') // 92
+ && !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.SetNlCount(pc.GetNlCount() + 1);
+ cpd.did_newline = true;
+ }
+ // Store off the end column
+ pc.SetOrigColEnd(ctx.c.col);
+ }
+ }
+ }
+ return(true);
+} // parse_word
+
+
+static size_t parse_attribute_specifier_sequence(TokenContext &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 == ' ' // 32
+ || ch2 == '\n'
+ || ch2 == '\r'
+ || ch2 == '\t')
+ {
+ ch2 = ctx.peek(offset++);
+ }
+
+ if ( nested == 0
+ && ch2 != '[') // 91
+ {
+ break;
+ }
+
+ if (ch1 == '(') // 40
+ {
+ ++parens;
+ ch1 = ch2;
+ continue;
+ }
+
+ if (ch1 == ')') // 41
+ {
+ 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 == '[') // 91
+ {
+ 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(TokenContext &ctx, Chunk &pc, size_t length)
+{
+ pc.Str().clear();
+
+ while (length--)
+ {
+ pc.Str().append(ctx.get());
+ }
+ pc.SetType(CT_ATTRIBUTE);
+ return(true);
+} // extract_attribute_specifier_sequence
+
+
+static bool parse_whitespace(TokenContext &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()))
+ {
+ int lastcol = ctx.c.col;
+ 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.SetOrigPrevSp(0);
+ break;
+
+ case '\n':
+ // LF ending
+ ++LE_COUNT(LF);
+ nl_count++;
+ pc.SetOrigPrevSp(0);
+ break;
+
+ case '\t':
+ pc.SetOrigPrevSp(pc.GetOrigPrevSp() + ctx.c.col - lastcol);
+ break;
+
+ case ' ':
+ pc.SetOrigPrevSp(pc.GetOrigPrevSp() + 1);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (ch != 0)
+ {
+ pc.Str().clear();
+ pc.SetType(nl_count ? CT_NEWLINE : CT_WHITESPACE);
+ pc.SetNlCount(nl_count);
+ pc.SetAfterTab((ctx.c.last_ch == '\t'));
+ return(true);
+ }
+ return(false);
+} // parse_whitespace
+
+
+static bool parse_bs_newline(TokenContext &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');
+ }
+ pc.SetType(CT_NL_CONT);
+ pc.Str() = "\\";
+ pc.SetNlCount(1);
+ return(true);
+ }
+ }
+ ctx.restore();
+ return(false);
+}
+
+
+static bool parse_newline(TokenContext &ctx)
+{
+ ctx.save();
+
+ // Eat whitespace
+ while ( (ctx.peek() == ' ') // 32
+ || (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(TokenContext &ctx, Chunk &pc, E_Token tt)
+{
+ pc.Str().clear();
+ pc.SetType(tt);
+
+ while (!unc_isspace(ctx.peek()))
+ {
+ // end the pattern on an escaped newline
+ if (ctx.peek() == '\\') // 92
+ {
+ size_t ch = ctx.peek(1);
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ break;
+ }
+ }
+ pc.Str().append(ctx.get());
+ }
+}
+
+
+static bool parse_off_newlines(TokenContext &ctx, Chunk &pc)
+{
+ size_t nl_count = 0;
+
+ // Parse off newlines/blank lines
+ while (parse_newline(ctx))
+ {
+ nl_count++;
+ }
+
+ if (nl_count > 0)
+ {
+ pc.SetNlCount(nl_count);
+ pc.SetType(CT_NEWLINE);
+ return(true);
+ }
+ return(false);
+}
+
+
+static bool parse_macro(TokenContext &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();
+
+ if (prev_pc->IsNullChunk())
+ {
+ return(false);
+ }
+ bool continued = ( prev_pc->Is(CT_NL_CONT)
+ || prev_pc->Is(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 == '\\' // 92
+ && ( pk1 == '\n'
+ || pk1 == '\r'));
+
+ if ( ( nl_cont
+ || ( continued
+ && nl))
+ && pc.GetStr().size() > 0)
+ {
+ pc.SetType(CT_PP_IGNORE);
+ return(true);
+ }
+ else if (nl)
+ {
+ break;
+ }
+ pc.Str().append(ctx.get());
+ }
+ pc.Str().clear();
+ ctx.restore();
+ return(false);
+} // parse_macro
+
+
+static bool parse_ignored(TokenContext &ctx, Chunk &pc)
+{
+ if (parse_off_newlines(ctx, pc))
+ {
+ return(true);
+ }
+ // See if the options::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.GetStr().size() == 0)
+ {
+ // end of file?
+ return(false);
+ }
+
+ // HACK: turn on if we find '#endasm' or '#pragma' and 'endasm' separated by blanks
+ if ( ( ( (pc.GetStr().find("#pragma ") >= 0)
+ || (pc.GetStr().find("#pragma ") >= 0))
+ && ( (pc.GetStr().find(" endasm") >= 0)
+ || (pc.GetStr().find(" endasm") >= 0)))
+ || (pc.GetStr().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.GetStr().get().cbegin(),
+ pc.GetStr().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.GetStr().find(ontext.c_str()) >= 0);
+ }
+
+ if (!found_enable_pattern)
+ {
+ pc.SetType(CT_IGNORED);
+ return(true);
+ }
+ }
+ ctx.restore();
+
+ // parse off whitespace leading to the comment
+ if (parse_whitespace(ctx, pc))
+ {
+ pc.SetType(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.GetStr().size() > 0)
+ {
+ pc.SetType(CT_IGNORED);
+ return(true);
+ }
+ return(false);
+} // parse_ignored
+
+
+static bool parse_next(TokenContext &ctx, Chunk &pc, const Chunk *prev_pc)
+{
+ if (!ctx.more())
+ {
+ return(false);
+ }
+ // Save off the current column
+ pc.SetType(CT_NONE);
+ pc.SetOrigLine(ctx.c.row);
+ pc.SetColumn(ctx.c.col);
+ pc.SetOrigCol(ctx.c.col);
+ pc.SetNlCount(0);
+ pc.SetFlags(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();
+ TokenInfo ss;
+ ctx.save(ss);
+ // Chunk to a newline or comment
+ pc.SetType(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 == '\\' // 92
+ && ch == ' ') // 32
+ {
+ ctx.get();
+ continue;
+ }
+
+ if ( (ch == '\n')
+ || (ch == '\r'))
+ {
+ // Back off if this is an escaped newline
+ if (last == '\\') // 92
+ {
+ ctx.restore(ss);
+ pc.Str().pop_back();
+ }
+ break;
+ }
+
+ // Quit on a C or C++ comment start Issue #1966
+ if ( (ch == '/') // 47
+ && ( (ctx.peek(1) == '/') // 47
+ || (ctx.peek(1) == '*'))) // 42
+ {
+ break;
+ }
+ last = ch;
+ ctx.save(ss);
+
+ pc.Str().append(ctx.get());
+ }
+
+ if (pc.GetStr().size() > 0)
+ {
+ return(true);
+ }
+ }
+
+ // Detect backslash-newline
+ if ( (ctx.peek() == '\\') // 92
+ && 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);
+ }
+ }
+
+ if (language_is_set(LANG_CS | LANG_VALA))
+ {
+ // check for non-keyword identifiers such as @if @switch, etc
+ // Vala also allows numeric identifiers if prefixed with '@'
+ if ( ctx.peek() == '@' // 64
+ && ( CharTable::IsKw1(ctx.peek(1))
+ || ( language_is_set(LANG_VALA)
+ && CharTable::IsKw2(ctx.peek(1)))))
+ {
+ parse_word(ctx, pc, true);
+ return(true);
+ }
+ }
+
+ // handle VALA """ strings """
+ if ( language_is_set(LANG_VALA)
+ && (ctx.peek() == '"') // 34
+ && (ctx.peek(1) == '"') // 34
+ && (ctx.peek(2) == '"')) // 34
+ {
+ 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' // 117
+ || ch == 'U' // 85
+ || ch == 'R' // 82
+ || ch == 'L')) // 76
+ {
+ auto idx = size_t{};
+ auto is_real = false;
+
+ if ( ch == 'u' // 117
+ && ctx.peek(1) == '8') // 56
+ {
+ idx = 2;
+ }
+ else if ( unc_tolower(ch) == 'u' // 117
+ || ch == 'L') // 76
+ {
+ idx++;
+ }
+
+ if ( language_is_set(LANG_C | LANG_CPP)
+ && ctx.peek(idx) == 'R') // 82
+ {
+ idx++;
+ is_real = true;
+ }
+ const auto quote = ctx.peek(idx);
+
+ if (is_real)
+ {
+ if ( quote == '"' // 34
+ && parse_cr_string(ctx, pc, idx))
+ {
+ return(true);
+ }
+ }
+ else if ( ( quote == '"' // 34
+ || quote == '\'') // 39
+ && 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() == '\\') // 92
+ || (ctx.peek() == '!')) // 33
+ {
+ if (ctx.peek(1) == '"') // 32
+ {
+ parse_string(ctx, pc, 1, (ctx.peek() == '!')); // 33
+ return(true);
+ }
+
+ if ( ( (ctx.peek(1) == '\\') // 92
+ || (ctx.peek(1) == '!')) // 33
+ && (ctx.peek(2) == '"')) // 32
+ {
+ parse_string(ctx, pc, 2, false);
+ return(true);
+ }
+ }
+
+ // handle PAWN preprocessor args %0 .. %9
+ if ( cpd.in_preproc == CT_PP_DEFINE
+ && (ctx.peek() == '%') // 37
+ && unc_isdigit(ctx.peek(1)))
+ {
+ pc.Str().clear();
+ pc.Str().append(ctx.get());
+ pc.Str().append(ctx.get());
+ pc.SetType(CT_WORD);
+ return(true);
+ }
+ }
+ // Parse strings and character constants
+
+ 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') // 76
+ || (ch == 'S')) // 83
+ && ( (ch1 == '"') // 34
+ || (ch1 == '\''))) // 39
+ || (ch == '"') // 34
+ || (ch == '\'') // 39
+ || ( (ch == '<') // 60
+ && cpd.in_preproc == CT_PP_INCLUDE))
+ {
+ parse_string(ctx, pc, unc_isalpha(ch) ? 1 : 0, true);
+
+ if (cpd.in_preproc == CT_PP_INCLUDE)
+ {
+ pc.SetParentType(CT_PP_INCLUDE);
+ }
+ return(true);
+ }
+
+ if ( (ch == '<') // 60
+ && cpd.in_preproc == CT_PP_DEFINE)
+ {
+ if (Chunk::GetTail()->Is(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 == '(') // 40
+ && (tail->IsNotNullChunk())
+ && ( tail->Is(CT_CNG_HASINC)
+ || tail->Is(CT_CNG_HASINCN)))
+ {
+ parse_string(ctx, pc, 0, false);
+ return(true);
+ }
+ }
+
+ // Check for Vala string templates
+ if ( language_is_set(LANG_VALA)
+ && (ctx.peek() == '@')) // 64
+ {
+ size_t nc = ctx.peek(1);
+
+ if (nc == '"') // 34
+ {
+ // literal string
+ parse_string(ctx, pc, 1, true);
+ return(true);
+ }
+ }
+
+ // Check for Objective C literals
+ if ( language_is_set(LANG_OC)
+ && (ctx.peek() == '@')) // 64
+ {
+ size_t nc = ctx.peek(1);
+
+ if (nc == 'R') // Issue #2720 82
+ {
+ if (ctx.peek(2) == '"') // 34
+ {
+ 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 == '"') // 34
+ || (nc == '\'')) // 39
+ {
+ // 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() == '\\') // 92
+ && (unc_tolower(ctx.peek(1)) == 'u')) // 117
+ || ( (ctx.peek() == '@') // 64
+ && 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() == '[') // 91
+ {
+ if ( !language_is_set(LANG_OC)
+ || ( prev_pc->IsNotNullChunk()
+ && !prev_pc->Is(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());
+ }
+ pc.SetType(punc->type);
+ pc.SetFlagBits(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)) != nullptr)
+ {
+ cpd.lang_flags = probe_lang_flags;
+ int cnt = strlen(punc->tag);
+
+ while (cnt--)
+ {
+ pc.Str().append(ctx.get());
+ }
+ pc.SetType(punc->type);
+ pc.SetFlagBits(PCF_PUNCTUATOR);
+ return(true);
+ }
+ }
+ // throw away this character
+ pc.SetType(CT_UNKNOWN);
+ pc.Str().append(ctx.get());
+
+ LOG_FMT(LWARN, "%s:%zu Garbage in col %zu: %x\n",
+ cpd.filename.c_str(), pc.GetOrigLine(), ctx.c.col, pc.GetStr()[0]);
+ exit(EX_SOFTWARE);
+} // parse_next
+
+
+int find_disable_processing_comment_marker(const UncText &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 UncText &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)
+{
+ TokenContext ctx(data);
+ Chunk chunk;
+ Chunk *pc = Chunk::NullChunkPtr;
+ Chunk *rprev = Chunk::NullChunkPtr;
+ 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.SetPpLevel(0);
+
+ if (!parse_next(ctx, chunk, pc))
+ {
+ LOG_FMT(LERR, "%s:%zu Bailed before the end?\n",
+ cpd.filename.c_str(), ctx.c.row);
+ exit(EX_SOFTWARE);
+ }
+
+ if ( language_is_set(LANG_JAVA)
+ && chunk.GetType() == CT_MEMBER
+ && !memcmp(chunk.Text(), "->", 2))
+ {
+ chunk.SetType(CT_LAMBDA);
+ }
+
+ // Don't create an entry for whitespace
+ if (chunk.GetType() == CT_WHITESPACE)
+ {
+ last_was_tab = chunk.GetAfterTab();
+ prev_sp = chunk.GetOrigPrevSp();
+ continue;
+ }
+ chunk.SetOrigPrevSp(prev_sp);
+ prev_sp = 0;
+
+ if (chunk.GetType() == CT_NEWLINE)
+ {
+ last_was_tab = chunk.GetAfterTab();
+ chunk.SetAfterTab(false);
+ chunk.Str().clear();
+ }
+ else if (chunk.GetType() == CT_NL_CONT)
+ {
+ last_was_tab = chunk.GetAfterTab();
+ chunk.SetAfterTab(false);
+ chunk.Str() = "\\\n";
+ }
+ else
+ {
+ chunk.SetAfterTab(last_was_tab);
+ last_was_tab = false;
+ }
+ num_stripped = 0; // Issue #1966 and #3565
+
+ if (chunk.GetType() != CT_IGNORED)
+ {
+ // Issue #1338
+ // Strip trailing whitespace (for CPP comments and PP blocks)
+ while ( (chunk.GetStr().size() > 0)
+ && ( (chunk.GetStr()[chunk.GetStr().size() - 1] == ' ') // 32
+ || (chunk.GetStr()[chunk.GetStr().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.GetStr().size() > 1)
+ && (chunk.GetStr()[chunk.GetStr().size() - 2] == '\\'))
+ {
+ break;
+ }
+ chunk.Str().pop_back();
+ num_stripped++; // Issue #1966
+ }
+ }
+ // Store off the end column
+ chunk.SetOrigColEnd(ctx.c.col - num_stripped); // Issue #1966 and #3565
+
+ // Make the whitespace we disposed of be attributed to the next chunk
+ prev_sp = num_stripped;
+
+ // Add the chunk to the list
+ rprev = pc;
+
+ if (rprev->IsNotNullChunk())
+ {
+ pc->SetFlagBits(rprev->GetFlags() & PCF_COPY_FLAGS);
+
+ // a newline can't be in a preprocessor
+ if (pc->Is(CT_NEWLINE))
+ {
+ pc->ResetFlagBits(PCF_IN_PREPROC);
+ }
+ }
+
+ if (ref->IsNotNullChunk())
+ {
+ chunk.SetFlagBits(PCF_INSERTED);
+ }
+ else
+ {
+ chunk.ResetFlagBits(PCF_INSERTED);
+ }
+ pc = chunk.CopyAndAddBefore(ref);
+
+ // A newline marks the end of a preprocessor
+ if (pc->Is(CT_NEWLINE)) // || pc->Is(CT_COMMENT_MULTI))
+ {
+ cpd.in_preproc = CT_NONE;
+ cpd.preproc_ncnl_count = 0;
+ }
+
+ // Disable indentation when #asm directive found
+ if (pc->Is(CT_PP_ASM))
+ {
+ LOG_FMT(LBCTRL, "Found a directive %s on line %zu\n", "#asm", pc->GetOrigLine());
+ cpd.unc_off = true;
+ }
+
+ // Special handling for preprocessor stuff
+ if (cpd.in_preproc != CT_NONE)
+ {
+ pc->SetFlagBits(PCF_IN_PREPROC);
+ // Issue #2225
+ LOG_FMT(LBCTRL, "%s(%d): orig line is %zu, orig col is %zu, type is %s, parentType is %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(),
+ get_token_name(pc->GetType()), get_token_name(pc->GetParentType()));
+
+ if ( pc->Is(CT_STRING_MULTI)
+ && pc->GetParentType() == CT_PP_INCLUDE)
+ {
+ LOG_FMT(LWARN, "%s:%zu: File name is not possible %s\n",
+ cpd.filename.c_str(), pc->GetOrigLine(), pc->Text());
+ exit(EX_SOFTWARE);
+ }
+
+ // Count words after the preprocessor
+ if (!pc->IsCommentOrNewline())
+ {
+ 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->GetOrigLine());
+ cpd.unc_off = true;
+ }
+ }
+
+ // Figure out the type of preprocessor for #include parsing
+ if (cpd.in_preproc == CT_PREPROC)
+ {
+ if ( pc->GetType() < CT_PP_DEFINE
+ || pc->GetType() > CT_PP_OTHER)
+ {
+ pc->SetType(CT_PP_OTHER);
+ }
+ cpd.in_preproc = pc->GetType();
+ }
+ else if (cpd.in_preproc == CT_PP_IGNORE)
+ {
+ if ( !pc->Is(CT_NL_CONT)
+ && !pc->IsComment()) // Issue #1966
+ {
+ pc->SetType(CT_PP_IGNORE);
+ }
+ }
+ else if ( cpd.in_preproc == CT_PP_DEFINE
+ && pc->Is(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 ( pc->Is(CT_POUND)
+ && ( rprev->IsNullChunk()
+ || rprev->Is(CT_NEWLINE)))
+ {
+ pc->SetType(CT_PREPROC);
+ pc->SetFlagBits(PCF_IN_PREPROC);
+ cpd.in_preproc = CT_PREPROC;
+ }
+ }
+
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LBCTRL, "%s(%d): orig line is %zu, orig col is %zu, <Newline>, nl is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetNlCount());
+ }
+ else if (pc->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LBCTRL, "%s(%d): orig line is %zu, orig col is %zu, type is %s, orig col end is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), get_token_name(pc->GetType()), pc->GetOrigColEnd());
+ }
+ else
+ {
+ char copy[1000];
+ LOG_FMT(LBCTRL, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s, orig col end is %zu\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()), pc->GetOrigColEnd());
+ }
+ }
+ // 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.78.0/src/tokenize.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize.h
new file mode 100644
index 00000000..6f1df591
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize.h
@@ -0,0 +1,55 @@
+/**
+ * @file tokenize.h
+ * prototypes for tokenize.cpp
+ *
+ * @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 UncText &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 UncText &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.78.0/src/tokenize_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize_cleanup.cpp
new file mode 100644
index 00000000..831e1aae
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize_cleanup.cpp
@@ -0,0 +1,1223 @@
+/**
+ * @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, 2022
+ * @license GPL v2+
+ */
+
+#include "tokenize_cleanup.h"
+
+#include "check_template.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;
+
+
+/**
+ * Marks ObjC specific chunks in property declaration, by setting
+ * parent types and chunk types.
+ */
+static void cleanup_objc_property(Chunk *start);
+
+
+/**
+ * Marks ObjC specific chunks in property 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 property 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);
+
+
+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->SetOrigColEnd(pc->GetOrigCol() + 1);
+ pc->SetType(CT_ANGLE_CLOSE);
+
+ nc.SetType(ct->type);
+ nc.Str().pop_front();
+ nc.SetOrigCol(nc.GetOrigCol() + 1);
+ nc.SetColumn(nc.GetColumn() + 1);
+ nc.CopyAndAddAfter(pc);
+}
+
+
+void tokenize_trailing_return_types()
+{
+ // 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->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy));
+
+ if ( pc->Is(CT_MEMBER)
+ && (strcmp(pc->Text(), "->") == 0))
+ {
+ Chunk *tmp = pc->GetPrevNcNnl();
+ Chunk *tmp_2;
+ Chunk *open_paren;
+
+ if (tmp->Is(CT_QUALIFIER))
+ {
+ // auto max(int a, int b) const -> int;
+ // auto f11() const -> bool;
+ tmp = tmp->GetPrevNcNnl();
+ }
+ else if (tmp->Is(CT_NOEXCEPT))
+ {
+ // noexcept is present
+ tmp_2 = tmp->GetPrevNcNnl();
+
+ if (tmp_2->Is(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 (tmp->Is(CT_PAREN_CLOSE))
+ {
+ open_paren = tmp->GetPrevType(CT_PAREN_OPEN, tmp->GetLevel());
+ tmp = open_paren->GetPrevNcNnl();
+
+ if (tmp->Is(CT_NOEXCEPT))
+ {
+ // noexcept is present
+ tmp_2 = tmp->GetPrevNcNnl();
+
+ if (tmp_2->Is(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 (tmp->Is(CT_THROW))
+ {
+ // throw is present
+ tmp_2 = tmp->GetPrevNcNnl();
+
+ if (tmp_2->Is(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 ( tmp->Is(CT_FPAREN_CLOSE)
+ && ( tmp->GetParentType() == CT_FUNC_PROTO
+ || tmp->GetParentType() == CT_FUNC_DEF))
+ {
+ pc->SetType(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 (next->Is(CT_DECLTYPE))
+ {
+ // TODO
+ }
+ else if (next->Is(CT_WORD))
+ {
+ next->SetType(CT_TYPE); // Issue #3222
+ next = next->GetNextNcNnl();
+
+ if (next->Is(CT_ARITH))
+ {
+ if (next->GetStr()[0] == '*')
+ {
+ next->SetType(CT_PTR_TYPE);
+ }
+ else if (next->GetStr()[0] == '&') // Issue #3407
+ {
+ next->SetType(CT_BYREF);
+ }
+ }
+ }
+ else
+ {
+ // TODO
+ }
+ }
+ }
+ }
+} // tokenize_trailing_return_types
+
+
+void tokenize_cleanup()
+{
+ LOG_FUNC_ENTRY();
+
+ Chunk *prev = Chunk::NullChunkPtr;
+ 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 (pc->Is(CT_SQUARE_OPEN))
+ {
+ next = pc->GetNextNcNnl();
+
+ if (next->Is(CT_SQUARE_CLOSE))
+ {
+ // Change '[' + ']' into '[]'
+ pc->SetType(CT_TSQUARE);
+ pc->Str() = "[]";
+ /*
+ * bug #664: The original m_origColEnd of CT_SQUARE_CLOSE is
+ * stored at m_origColEnd of CT_TSQUARE.
+ * pc->SetOrigColEnd(pc->GetOrigColEnd() + 1);
+ */
+ pc->SetOrigColEnd(next->GetOrigColEnd());
+ Chunk::Delete(next);
+ }
+ }
+
+ if ( pc->Is(CT_SEMICOLON)
+ && pc->TestFlags(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->GetOrigLine());
+ }
+ }
+
+ // change := to CT_SQL_ASSIGN Issue #527
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
+ {
+ if (pc->Is(CT_COLON))
+ {
+ next = pc->GetNextNcNnl();
+
+ if (next->Is(CT_ASSIGN))
+ {
+ // Change ':' + '=' into ':='
+ pc->SetType(CT_SQL_ASSIGN);
+ pc->Str() = ":=";
+ pc->SetOrigColEnd(next->GetOrigColEnd());
+ Chunk::Delete(next);
+ }
+ }
+ }
+
+ // We can handle everything else in the second pass
+ pc = Chunk::GetHead();
+ next = pc->GetNextNcNnl();
+
+ while ( pc->IsNotNullChunk()
+ && next->IsNotNullChunk())
+ {
+ if ( pc->Is(CT_DOT)
+ && language_is_set(LANG_ALLC))
+ {
+ pc->SetType(CT_MEMBER);
+ }
+
+ if ( pc->Is(CT_NULLCOND)
+ && language_is_set(LANG_CS))
+ {
+ pc->SetType(CT_MEMBER);
+ }
+
+ // Determine the version stuff (D only)
+ if (pc->Is(CT_D_VERSION))
+ {
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_D_VERSION_IF);
+ }
+ else
+ {
+ if (next->IsNot(CT_ASSIGN))
+ {
+ LOG_FMT(LERR, "%s(%d): %s:%zu: version: Unexpected token %s\n",
+ __func__, __LINE__, cpd.filename.c_str(), pc->GetOrigLine(), get_token_name(next->GetType()));
+ exit(EX_SOFTWARE);
+ }
+ pc->SetType(CT_WORD);
+ }
+ }
+
+ // Determine the scope stuff (D only)
+ if (pc->Is(CT_D_SCOPE))
+ {
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_D_SCOPE_IF);
+ }
+ else
+ {
+ pc->SetType(CT_TYPE);
+ }
+ }
+
+ /*
+ * Change CT_BASE before CT_PAREN_OPEN to CT_WORD.
+ * public myclass() : base() {}
+ * -or-
+ * var x = (T)base.y;
+ */
+ if ( pc->Is(CT_BASE)
+ && ( next->Is(CT_PAREN_OPEN)
+ || next->Is(CT_DOT)))
+ {
+ pc->SetType(CT_WORD);
+ }
+
+ if ( pc->Is(CT_ENUM)
+ && ( next->Is(CT_STRUCT)
+ || next->Is(CT_CLASS)))
+ {
+ next->SetType(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 (next_non_attr->Is(CT_WORD))
+ {
+ if (pc->IsClassEnumStructOrUnion())
+ {
+ next_non_attr->SetType(CT_TYPE);
+ }
+
+ if (pc->Is(CT_WORD))
+ {
+ pc->SetType(CT_TYPE);
+ }
+ }
+
+ /*
+ * change extern to qualifier if extern isn't followed by a string or
+ * an open parenthesis
+ */
+ if (pc->Is(CT_EXTERN))
+ {
+ if (next->Is(CT_STRING))
+ {
+ // Probably 'extern "C"'
+ }
+ else if (next->Is(CT_PAREN_OPEN))
+ {
+ // Probably 'extern (C)'
+ }
+ else
+ {
+ // Something else followed by a open brace
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if ( tmp->IsNullChunk()
+ || tmp->IsNot(CT_BRACE_OPEN))
+ {
+ pc->SetType(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 ( (next->Is(CT_STAR))
+ || ( language_is_set(LANG_CPP)
+ && (next->Is(CT_CARET)))
+ || ( language_is_set(LANG_CS | LANG_VALA)
+ && (next->Is(CT_QUESTION))
+ && (strcmp(pc->Text(), "null") != 0)))
+ {
+ if ( pc->Is(CT_TYPE)
+ || pc->Is(CT_QUALIFIER)
+ || pc->Is(CT_PTR_TYPE))
+ {
+ next->SetType(CT_PTR_TYPE);
+ }
+ }
+
+ if ( pc->Is(CT_TYPE_CAST)
+ && next->Is(CT_ANGLE_OPEN))
+ {
+ next->SetParentType(CT_TYPE_CAST);
+ in_type_cast = true;
+ }
+
+ if (pc->Is(CT_DECLTYPE))
+ {
+ flag_cpp_decltype(pc);
+ }
+
+ // Change angle open/close to CT_COMPARE, if not a template thingy
+ if ( pc->Is(CT_ANGLE_OPEN)
+ && pc->GetParentType() != 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
+ pc->SetType(CT_COMPARE);
+ }
+ }
+
+ if ( pc->Is(CT_ANGLE_CLOSE)
+ && pc->GetParentType() != CT_TEMPLATE)
+ {
+ if (in_type_cast)
+ {
+ in_type_cast = false;
+ pc->SetParentType(CT_TYPE_CAST);
+ }
+ else
+ {
+ next = handle_double_angle_close(pc);
+ }
+ }
+
+ if (language_is_set(LANG_D))
+ {
+ // Check for the D string concat symbol '~'
+ if ( pc->Is(CT_INV)
+ && ( prev->Is(CT_STRING)
+ || prev->Is(CT_WORD)
+ || next->Is(CT_STRING)))
+ {
+ pc->SetType(CT_CONCAT);
+ }
+
+ // Check for the D template symbol '!' (word + '!' + word or '(')
+ if ( pc->Is(CT_NOT)
+ && prev->Is(CT_WORD)
+ && ( next->Is(CT_PAREN_OPEN)
+ || next->Is(CT_WORD)
+ || next->Is(CT_TYPE)
+ || next->Is(CT_NUMBER)
+ || next->Is(CT_NUMBER_FP)
+ || next->Is(CT_STRING)
+ || next->Is(CT_STRING_MULTI)))
+ {
+ pc->SetType(CT_D_TEMPLATE);
+ }
+
+ // handle "version(unittest) { }" vs "unittest { }"
+ if ( pc->Is(CT_UNITTEST)
+ && prev->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_WORD);
+ }
+
+ // handle 'static if' and merge the tokens
+ if ( pc->Is(CT_IF)
+ && prev->IsString("static"))
+ {
+ // delete PREV and merge with IF
+ pc->Str().insert(0, ' ');
+ pc->Str().insert(0, prev->GetStr());
+ pc->SetOrigCol(prev->GetOrigCol());
+ pc->SetOrigLine(prev->GetOrigLine());
+ Chunk *to_be_deleted = prev;
+ prev = prev->GetPrevNcNnl();
+
+ if (prev->IsNotNullChunk())
+ {
+ Chunk::Delete(to_be_deleted);
+ }
+ }
+ }
+
+ if (language_is_set(LANG_CPP))
+ {
+ // Change Word before '::' into a type
+ if ( pc->Is(CT_WORD)
+ && next->Is(CT_DC_MEMBER))
+ {
+ prev = pc->GetPrev();
+
+ if (prev->IsNullChunk()) // Issue #3010
+ {
+ pc->SetType(CT_TYPE);
+ }
+ else
+ {
+ if (prev->Is(CT_COLON))
+ {
+ // nothing to do
+ }
+ else
+ {
+ pc->SetType(CT_TYPE);
+ }
+ }
+ }
+
+ // Set parent type for 'if constexpr'
+ if ( prev->Is(CT_IF)
+ && pc->Is(CT_QUALIFIER)
+ && pc->IsString("constexpr"))
+ {
+ pc->SetType(CT_CONSTEXPR);
+ }
+ }
+
+ // Change get/set to CT_WORD if not followed by a brace open
+ if ( pc->Is(CT_GETSET)
+ && next->IsNot(CT_BRACE_OPEN))
+ {
+ if ( next->Is(CT_SEMICOLON)
+ && ( prev->Is(CT_BRACE_CLOSE)
+ || prev->Is(CT_BRACE_OPEN)
+ || prev->Is(CT_SEMICOLON)))
+ {
+ pc->SetType(CT_GETSET_EMPTY);
+ next->SetParentType(CT_GETSET);
+ }
+ else
+ {
+ pc->SetType(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 ( pc->Is(CT_CLASS)
+ && !CharTable::IsKw1(next->GetStr()[0]))
+ {
+ if ( next->IsNot(CT_DC_MEMBER)
+ && next->IsNot(CT_ATTRIBUTE)) // Issue #2570
+ {
+ pc->SetType(CT_WORD);
+ }
+ else if ( prev->Is(CT_DC_MEMBER)
+ || prev->Is(CT_TYPE))
+ {
+ pc->SetType(CT_TYPE);
+ }
+ else if (next->Is(CT_DC_MEMBER))
+ {
+ Chunk *next2 = next->GetNextNcNnlNet();
+
+ if ( next2->Is(CT_INV) // CT_INV hasn't turned into CT_DESTRUCTOR just yet
+ || ( next2->Is(CT_CLASS) // constructor isn't turned into CT_FUNC* just yet
+ && !strcmp(pc->Text(), next2->Text())))
+ {
+ pc->SetType(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 (pc->Is(CT_OPERATOR))
+ {
+ Chunk *tmp2 = next->GetNext();
+
+ // Handle special case of () operator -- [] already handled
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ Chunk *tmp = next->GetNext();
+
+ if (tmp->Is(CT_PAREN_CLOSE))
+ {
+ next->Str() = "()";
+ next->SetType(CT_OPERATOR_VAL);
+ Chunk::Delete(tmp);
+ next->SetOrigColEnd(next->GetOrigColEnd() + 1);
+ }
+ }
+ else if ( next->Is(CT_ANGLE_CLOSE)
+ && tmp2->Is(CT_ANGLE_CLOSE)
+ && tmp2->GetOrigCol() == next->GetOrigColEnd())
+ {
+ next->Str().append('>');
+ next->SetOrigColEnd(next->GetOrigColEnd() + 1);
+ next->SetType(CT_OPERATOR_VAL);
+ Chunk::Delete(tmp2);
+ }
+ else if (next->TestFlags(PCF_PUNCTUATOR))
+ {
+ next->SetType(CT_OPERATOR_VAL);
+ }
+ else
+ {
+ next->SetType(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->IsNot(CT_WORD)
+ && tmp->IsNot(CT_TYPE)
+ && tmp->IsNot(CT_QUALIFIER)
+ && tmp->IsNot(CT_STAR)
+ && tmp->IsNot(CT_CARET)
+ && tmp->IsNot(CT_AMP)
+ && tmp->IsNot(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->GetStr());
+ tmp2 = tmp;
+ }
+
+ while ((tmp2 = next->GetNext()) != tmp)
+ {
+ Chunk::Delete(tmp2);
+ }
+ next->SetType(CT_OPERATOR_VAL);
+
+ next->SetOrigColEnd(next->GetOrigCol() + next->Len());
+ }
+ next->SetParentType(CT_OPERATOR);
+
+ LOG_FMT(LOPERATOR, "%s(%d): %zu:%zu operator '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), next->Text());
+ }
+
+ // Change private, public, protected into either a qualifier or label
+ if (pc->Is(CT_ACCESS))
+ {
+ // Handle Qt slots - maybe should just check for a CT_WORD?
+ if ( next->IsString("slots")
+ || next->IsString("Q_SLOTS"))
+ {
+ Chunk *tmp = next->GetNext();
+
+ if (tmp->Is(CT_COLON))
+ {
+ next = tmp;
+ }
+ }
+
+ if (next->Is(CT_COLON))
+ {
+ next->SetType(CT_ACCESS_COLON);
+ Chunk *tmp;
+
+ if ((tmp = next->GetNextNcNnl())->IsNotNullChunk())
+ {
+ tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ log_ruleStart("start statementi/ expression", tmp);
+ }
+ }
+ else
+ {
+ pc->SetType(( pc->IsString("signals")
+ || pc->IsString("Q_SIGNALS"))
+ ? CT_WORD : CT_QUALIFIER);
+ }
+ }
+
+ // Look for <newline> 'EXEC' 'SQL'
+ if ( ( pc->IsString("EXEC", false)
+ && next->IsString("SQL", false))
+ || ( (*pc->GetStr().c_str() == '$')
+ && pc->IsNot(CT_SQL_WORD)
+ /* but avoid breaking tokenization for C# 6 interpolated strings. */
+ && ( !language_is_set(LANG_CS)
+ || ( pc->Is(CT_STRING)
+ && (!pc->GetStr().startswith("$\""))
+ && (!pc->GetStr().startswith("$@\""))))))
+ {
+ Chunk *tmp = pc->GetPrev();
+
+ if (tmp->IsNewline())
+ {
+ if (*pc->GetStr().c_str() == '$')
+ {
+ pc->SetType(CT_SQL_EXEC);
+
+ if (pc->Len() > 1)
+ {
+ // SPLIT OFF '$'
+ Chunk nc;
+
+ nc = *pc;
+ pc->Str().resize(1);
+ pc->SetOrigColEnd(pc->GetOrigCol() + 1);
+
+ nc.SetType(CT_SQL_WORD);
+ nc.Str().pop_front();
+ nc.SetOrigCol(nc.GetOrigCol() + 1);
+ nc.SetColumn(nc.GetColumn() + 1);
+ nc.CopyAndAddAfter(pc);
+
+ next = pc->GetNext();
+ }
+ }
+ tmp = next->GetNext();
+
+ if (tmp->IsString("BEGIN", false))
+ {
+ pc->SetType(CT_SQL_BEGIN);
+ }
+ else if (tmp->IsString("END", false))
+ {
+ pc->SetType(CT_SQL_END);
+ }
+ else
+ {
+ pc->SetType(CT_SQL_EXEC);
+ }
+
+ // Change words into CT_SQL_WORD until CT_SEMICOLON
+ while (tmp->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_SEMICOLON))
+ {
+ break;
+ }
+
+ if ( (tmp->Len() > 0)
+ && ( unc_isalpha(*tmp->GetStr().c_str())
+ || (*tmp->GetStr().c_str() == '$')))
+ {
+ tmp->SetType(CT_SQL_WORD);
+ }
+ tmp = tmp->GetNextNcNnl();
+ }
+ }
+ }
+
+ // handle MS abomination 'for each'
+ if ( pc->Is(CT_FOR)
+ && next->IsString("each")
+ && (next == pc->GetNext()))
+ {
+ // merge the two with a space between
+ pc->Str().append(' ');
+ pc->Str() += next->GetStr();
+ pc->SetOrigColEnd(next->GetOrigColEnd());
+ Chunk::Delete(next);
+ next = pc->GetNextNcNnl();
+
+ // label the 'in'
+ if (next->Is(CT_PAREN_OPEN))
+ {
+ Chunk *tmp = next->GetNextNcNnl();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->IsNot(CT_PAREN_CLOSE))
+ {
+ if (tmp->IsString("in"))
+ {
+ tmp->SetType(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 ( ( pc->Is(CT_IF)
+ || pc->Is(CT_FOR)
+ || pc->Is(CT_WHILE))
+ && !next->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_WORD);
+ }
+
+ if ( pc->Is(CT_DO)
+ && ( prev->Is(CT_MINUS)
+ || next->Is(CT_SQUARE_CLOSE)))
+ {
+ pc->SetType(CT_WORD);
+ }
+
+ // Fix self keyword back to word when mixing c++/objective-c
+ if ( pc->Is(CT_THIS)
+ && !strcmp(pc->Text(), "self")
+ && ( next->Is(CT_COMMA)
+ || next->Is(CT_PAREN_CLOSE)))
+ {
+ pc->SetType(CT_WORD);
+ }
+
+ // Fix self keyword back to word when mixing c++/objective-c
+ if ( pc->Is(CT_THIS)
+ && !strcmp(pc->Text(), "self")
+ && ( next->Is(CT_COMMA)
+ || next->Is(CT_PAREN_CLOSE)))
+ {
+ pc->SetType(CT_WORD);
+ }
+ }
+
+ // Vala allows keywords to be used as identifiers
+ if (language_is_set(LANG_VALA))
+ {
+ if ( find_keyword_type(pc->Text(), pc->Len()) != CT_WORD
+ && ( prev->Is(CT_DOT)
+ || next->Is(CT_DOT)
+ || prev->Is(CT_MEMBER)
+ || next->Is(CT_MEMBER)
+ || prev->Is(CT_TYPE)))
+ {
+ pc->SetType(CT_WORD);
+ }
+ }
+
+ // Another hack to clean up more keyword abuse
+ if ( pc->Is(CT_CLASS)
+ && ( prev->Is(CT_DOT)
+ || next->Is(CT_DOT)
+ || prev->Is(CT_MEMBER) // Issue #3031
+ || next->Is(CT_MEMBER)))
+ {
+ pc->SetType(CT_WORD);
+ }
+
+ // Detect Objective C class name
+ if ( pc->Is(CT_OC_IMPL)
+ || pc->Is(CT_OC_INTF)
+ || pc->Is(CT_OC_PROTOCOL))
+ {
+ if (next->IsNot(CT_PAREN_OPEN))
+ {
+ next->SetType(CT_OC_CLASS);
+ }
+ next->SetParentType(pc->GetType());
+
+ Chunk *tmp = next->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ log_ruleStart("start statementi/ expression", tmp);
+ }
+ tmp = pc->GetNextType(CT_OC_END, pc->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(pc->GetType());
+ }
+ }
+
+ if (pc->Is(CT_OC_INTF))
+ {
+ Chunk *tmp = pc->GetNextNcNnl(E_Scope::PREPROC);
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->IsNot(CT_OC_END))
+ {
+ if (get_token_pattern_class(tmp->GetType()) != pattern_class_e::NONE)
+ {
+ LOG_FMT(LOBJCWORD, "%s(%d): @interface %zu:%zu change '%s' (%s) to CT_WORD\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), tmp->Text(),
+ get_token_name(tmp->GetType()));
+ tmp->SetType(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 ( ( pc->GetParentType() == CT_OC_IMPL
+ || pc->GetParentType() == CT_OC_INTF
+ || pc->Is(CT_OC_CLASS))
+ && next->Is(CT_PAREN_OPEN))
+ {
+ next->SetParentType(pc->GetParentType());
+
+ Chunk *tmp = next->GetNext();
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetNext()->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_PAREN_CLOSE))
+ {
+ //tmp->SetType(CT_OC_CLASS_EXT);
+ tmp->SetParentType(pc->GetParentType());
+ }
+ else
+ {
+ tmp->SetType(CT_OC_CATEGORY);
+ tmp->SetParentType(pc->GetParentType());
+ }
+ }
+ tmp = pc->GetNextType(CT_PAREN_CLOSE, pc->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(pc->GetParentType());
+ }
+ }
+
+ /*
+ * Detect Objective C @property:
+ * @property NSString *stringProperty;
+ * @property(nonatomic, retain) NSMutableDictionary *shareWith;
+ */
+ if (pc->Is(CT_OC_PROPERTY))
+ {
+ if (next->IsNot(CT_PAREN_OPEN))
+ {
+ next->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ log_ruleStart("start statement/ expression", next);
+ }
+ else
+ {
+ cleanup_objc_property(pc);
+ }
+ }
+
+ /*
+ * Detect Objective C @selector:
+ * @selector(msgNameWithNoArg)
+ * @selector(msgNameWith1Arg:)
+ * @selector(msgNameWith2Args:arg2Name:)
+ */
+ if ( pc->Is(CT_OC_SEL)
+ && next->Is(CT_PAREN_OPEN))
+ {
+ next->SetParentType(pc->GetType());
+
+ Chunk *tmp = next->GetNext();
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetType(CT_OC_SEL_NAME);
+ tmp->SetParentType(pc->GetType());
+
+ while ((tmp = tmp->GetNextNcNnl())->IsNotNullChunk())
+ {
+ if (tmp->Is(CT_PAREN_CLOSE))
+ {
+ tmp->SetParentType(CT_OC_SEL);
+ break;
+ }
+ tmp->SetType(CT_OC_SEL_NAME);
+ tmp->SetParentType(pc->GetType());
+ }
+ }
+ }
+
+ // Handle special preprocessor junk
+ if (pc->Is(CT_PREPROC))
+ {
+ pc->SetParentType(next->GetType());
+ }
+
+ // Detect "pragma region" and "pragma endregion"
+ if ( pc->Is(CT_PP_PRAGMA)
+ && next->Is(CT_PREPROC_BODY))
+ {
+ if ( (strncmp(next->GetStr().c_str(), "region", 6) == 0)
+ || (strncmp(next->GetStr().c_str(), "endregion", 9) == 0))
+ // TODO: probably better use strncmp
+ {
+ pc->SetType((*next->GetStr().c_str() == 'r') ? CT_PP_REGION : CT_PP_ENDREGION);
+
+ prev->SetParentType(pc->GetType());
+ }
+ }
+
+ // Change 'default(' into a sizeof-like statement
+ if ( language_is_set(LANG_CS)
+ && pc->Is(CT_DEFAULT)
+ && next->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_SIZEOF);
+ }
+
+ if ( pc->Is(CT_UNSAFE)
+ && next->IsNot(CT_BRACE_OPEN))
+ {
+ pc->SetType(CT_QUALIFIER);
+ }
+
+ if ( ( pc->Is(CT_USING)
+ || ( pc->Is(CT_TRY)
+ && language_is_set(LANG_JAVA)))
+ && next->Is(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_USING_STMT);
+ }
+
+ // Add minimal support for C++0x rvalue references
+ if ( pc->Is(CT_BOOL)
+ && language_is_set(LANG_CPP)
+ && pc->IsString("&&"))
+ {
+ if (prev->Is(CT_TYPE))
+ {
+ // Issue # 1002
+ if (!pc->TestFlags(PCF_IN_TEMPLATE))
+ {
+ pc->SetType(CT_BYREF);
+ }
+ }
+ }
+
+ /*
+ * HACK: treat try followed by a colon as a qualifier to handle this:
+ * A::A(int) try : B() { } catch (...) { }
+ */
+ if ( pc->Is(CT_TRY)
+ && pc->IsString("try")
+ && next->Is(CT_COLON))
+ {
+ pc->SetType(CT_QUALIFIER);
+ }
+
+ /*
+ * If Java's 'synchronized' is in a method declaration, it should be
+ * a qualifier.
+ */
+ if ( language_is_set(LANG_JAVA)
+ && pc->Is(CT_SYNCHRONIZED)
+ && next->IsNot(CT_PAREN_OPEN))
+ {
+ pc->SetType(CT_QUALIFIER);
+ }
+
+ // change CT_DC_MEMBER + CT_FOR into CT_DC_MEMBER + CT_FUNC_CALL
+ if ( pc->Is(CT_FOR)
+ && pc->GetPrev()->Is(CT_DC_MEMBER))
+ {
+ pc->SetType(CT_FUNC_CALL);
+ }
+ // TODO: determine other stuff here
+
+ prev = pc;
+ pc = next;
+ next = pc->GetNextNcNnl();
+ }
+} // tokenize_cleanup
+
+
+static void cleanup_objc_property(Chunk *start)
+{
+ assert(start->Is(CT_OC_PROPERTY));
+
+ Chunk *open_paren = start->GetNextType(CT_PAREN_OPEN, start->GetLevel());
+
+ if (open_paren->IsNullChunk())
+ {
+ LOG_FMT(LTEMPL, "%s(%d): Property is not followed by opening paren\n", __func__, __LINE__);
+ return;
+ }
+ open_paren->SetParentType(start->GetType());
+
+ Chunk *tmp = start->GetNextType(CT_PAREN_CLOSE, start->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(start->GetType());
+ tmp = tmp->GetNextNcNnl();
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START);
+ log_ruleStart("start statement/ expression", tmp);
+
+ tmp = tmp->GetNextType(CT_SEMICOLON, start->GetLevel());
+
+ if (tmp->IsNotNullChunk())
+ {
+ tmp->SetParentType(start->GetType());
+ }
+ }
+ }
+ 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(open_paren->Is(CT_PAREN_OPEN));
+
+ Chunk *tmp = open_paren;
+
+ while (tmp->IsNot(CT_PAREN_CLOSE))
+ {
+ if ( tmp->Is(CT_WORD)
+ && ( tmp->IsString("setter")
+ || tmp->IsString("getter")))
+ {
+ tmp = tmp->GetNext();
+
+ while ( tmp->IsNotNullChunk()
+ && tmp->IsNot(CT_COMMA)
+ && tmp->IsNot(CT_PAREN_CLOSE))
+ {
+ if ( tmp->Is(CT_WORD)
+ || tmp->IsString(":"))
+ {
+ tmp->SetType(CT_OC_SEL_NAME);
+ }
+ tmp = tmp->GetNext();
+ }
+ }
+ else
+ {
+ tmp = tmp->GetNext();
+ }
+ }
+}
+
+
+static void mark_attributes_in_property_with_open_paren(Chunk *open_paren)
+{
+ assert(open_paren->Is(CT_PAREN_OPEN));
+
+ Chunk *tmp = open_paren;
+
+ while (tmp->IsNot(CT_PAREN_CLOSE))
+ {
+ Chunk *next = tmp->GetNext();
+
+ if ( ( tmp->Is(CT_COMMA)
+ || tmp->Is(CT_PAREN_OPEN))
+ && ( next->Is(CT_WORD)
+ || next->Is(CT_TYPE)))
+ {
+ next->SetType(CT_OC_PROPERTY_ATTR);
+ }
+ tmp = next;
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize_cleanup.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize_cleanup.h
new file mode 100644
index 00000000..b6dde163
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/tokenize_cleanup.h
@@ -0,0 +1,31 @@
+/**
+ * @file tokenize_cleanup.h
+ * prototypes for tokenize_cleanup.cpp
+ *
+ * @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 tokenize_trailing_return_types();
+
+
+void split_off_angle_close(Chunk *pc);
+
+
+#endif /* TOKENIZ_CLEANUP_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.cpp
new file mode 100644
index 00000000..352b4efb
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.cpp
@@ -0,0 +1,75 @@
+#include "options.h"
+
+
+int unc_fix_ctype(int ch)
+{
+ if ( ch >= -1
+ && ch <= 255)
+ {
+ return(ch);
+ }
+ return(0); // Issue #3025
+}
+
+
+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)));
+ }
+}
+
+
+int unc_isprint(int ch)
+{
+ return(isprint(unc_fix_ctype(ch)));
+}
+
+
+int unc_isalpha(int ch)
+{
+ return(isalpha(unc_fix_ctype(ch)));
+}
+
+
+int unc_isalnum(int ch)
+{
+ return(isalnum(unc_fix_ctype(ch)));
+}
+
+
+int unc_toupper(int ch)
+{
+ return(toupper(unc_fix_ctype(ch)));
+}
+
+
+int unc_tolower(int ch)
+{
+ return(tolower(unc_fix_ctype(ch)));
+}
+
+
+int unc_isxdigit(int ch)
+{
+ return(isxdigit(unc_fix_ctype(ch)));
+}
+
+
+int unc_isdigit(int ch)
+{
+ return(isdigit(unc_fix_ctype(ch)));
+}
+
+
+int unc_isupper(int ch)
+{
+ return( isalpha(unc_fix_ctype(ch))
+ && (unc_toupper(unc_fix_ctype(ch)) == ch));
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.h
new file mode 100644
index 00000000..8cfcbf3b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_ctype.h
@@ -0,0 +1,49 @@
+/**
+ * @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
+
+//! Test anything EOF (-1) to 0-255
+int unc_fix_ctype(int ch);
+
+//! check if a character is a space
+int unc_isspace(int ch);
+
+//! check if a character is a printing character
+int unc_isprint(int ch);
+
+//! check if a character is an alphabetic character (a letter).
+int unc_isalpha(int ch);
+
+//! check if a character is an alphanumeric character.
+int unc_isalnum(int ch);
+
+//! convert a character to upper case
+int unc_toupper(int ch);
+
+//! convert a character to lower case
+int unc_tolower(int ch);
+
+//! check if a character is a hexadecimal digit
+int unc_isxdigit(int ch);
+
+//! check if a character is a decimal digit
+int unc_isdigit(int ch);
+
+//! check if a character is upper case
+int unc_isupper(int ch);
+
+#endif /* UNC_CTYPE_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_text.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_text.cpp
new file mode 100644
index 00000000..6b4eb7fa
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_text.cpp
@@ -0,0 +1,766 @@
+/**
+ * @file UncText.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 <cstdint>
+#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, UncText::log_type &container);
+
+/**
+ * calculates the size a 'log_type' container needs to have in order to take
+ * in values of a 'UncText::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(UncText::value_type &c0, size_t end);
+
+static int getLogTextUtf8Len(UncText::value_type &c0, size_t start, size_t end);
+
+
+static int getLogTextUtf8Len(UncText::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(UncText::value_type &c0, size_t end)
+{
+ return(getLogTextUtf8Len(c0, 0, end));
+}
+
+
+static void toLogTextUtf8(int c, UncText::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);
+}
+
+
+UncText::UncText()
+{
+ m_logtext = log_type{ '\0' };
+}
+
+
+UncText::UncText(const UncText &ref)
+{
+ set(ref);
+}
+
+
+UncText::UncText(const UncText &ref, size_t idx, size_t len)
+{
+ set(ref, idx, len);
+}
+
+
+UncText::UncText(const char *ascii_text)
+{
+ set(ascii_text);
+}
+
+
+UncText::UncText(const std::string &ascii_text)
+{
+ set(ascii_text);
+}
+
+
+UncText::UncText(const value_type &data, size_t idx, size_t len)
+{
+ set(data, idx, len);
+}
+
+
+size_t UncText::size() const
+{
+ return(m_chars.size());
+}
+
+
+UncText &UncText::operator=(int ch)
+{
+ set(ch);
+ return(*this);
+}
+
+
+UncText &UncText::operator=(const UncText &ref)
+{
+ set(ref);
+ return(*this);
+}
+
+
+UncText &UncText::operator=(const std::string &ascii_text)
+{
+ set(ascii_text);
+ return(*this);
+}
+
+
+UncText &UncText::operator=(const char *ascii_text)
+{
+ set(ascii_text);
+ return(*this);
+}
+
+
+UncText &UncText::operator+=(int ch)
+{
+ append(ch);
+ return(*this);
+}
+
+
+UncText &UncText::operator+=(const UncText &ref)
+{
+ append(ref);
+ return(*this);
+}
+
+
+UncText &UncText::operator+=(const std::string &ascii_text)
+{
+ append(ascii_text);
+ return(*this);
+}
+
+
+UncText &UncText::operator+=(const char *ascii_text)
+{
+ append(ascii_text);
+ return(*this);
+}
+
+
+const UncText::value_type &UncText::get() const
+{
+ return(m_chars);
+}
+
+
+int UncText::operator[](size_t idx) const
+{
+ return((idx < m_chars.size()) ? m_chars[idx] : 0);
+}
+
+
+const int &UncText::at(size_t idx) const
+{
+ return(m_chars.at(idx));
+}
+
+
+int &UncText::at(size_t idx)
+{
+ return(m_chars.at(idx));
+}
+
+
+const int &UncText::back() const
+{
+ return(m_chars.back());
+}
+
+
+void UncText::push_back(int ch)
+{
+ append(ch);
+}
+
+
+void UncText::pop_back()
+{
+ if (size() == 0)
+ {
+ return;
+ }
+ m_chars.pop_back();
+ update_logtext();
+}
+
+
+void UncText::pop_front()
+{
+ if (size() == 0)
+ {
+ return;
+ }
+ m_chars.pop_front();
+ update_logtext();
+}
+
+
+void UncText::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 UncText::compare(const UncText &ref1, const UncText &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));
+} // UncText::compare
+
+
+bool UncText::equals(const UncText &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 *UncText::c_str() const
+{
+ return(reinterpret_cast<const char *>(&m_logtext[0]));
+}
+
+
+void UncText::set(int ch)
+{
+ m_logtext.clear();
+ toLogTextUtf8(ch, m_logtext);
+ m_logtext.push_back('\0');
+
+
+ m_chars.clear();
+ m_chars.push_back(ch);
+}
+
+
+void UncText::set(const UncText &ref)
+{
+ m_chars = ref.m_chars;
+ m_logtext = ref.m_logtext;
+}
+
+
+void UncText::set(const UncText &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 UncText::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 UncText::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 UncText::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 UncText::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 UncText::clear()
+{
+ m_logtext.clear();
+ m_logtext.push_back('\0');
+
+
+ m_chars.clear();
+}
+
+
+void UncText::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 UncText::insert(size_t idx, const UncText &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 UncText::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 UncText::append(const UncText &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 UncText::append(const string &ascii_text)
+{
+ UncText tmp(ascii_text);
+
+ append(tmp);
+}
+
+
+void UncText::append(const char *ascii_text)
+{
+ UncText tmp(ascii_text);
+
+ append(tmp);
+}
+
+
+void UncText::append(const value_type &data, size_t idx, size_t len)
+{
+ UncText tmp(data, idx, len);
+
+ append(tmp);
+}
+
+
+bool UncText::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 UncText::startswith(const UncText &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 UncText::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 UncText::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 UncText::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 UncText::replace(const char *search_text, const UncText &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.78.0/src/unc_text.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_text.h
new file mode 100644
index 00000000..22217f3b
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_text.h
@@ -0,0 +1,197 @@
+/**
+ * @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 UncText
+{
+public:
+ typedef std::deque<int> value_type; // double encoded list of int values
+ typedef std::vector<UINT8> log_type;
+
+
+ UncText();
+
+ UncText(const UncText &ref);
+
+ UncText(const UncText &ref, size_t idx, size_t len = 0);
+
+ UncText(const char *ascii_text);
+
+ UncText(const std::string &ascii_text);
+
+ UncText(const value_type &data, size_t idx = 0, size_t len = 0);
+
+
+ ~UncText() = 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 UncText &ref);
+
+ void set(const UncText &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);
+
+
+ UncText &operator=(int ch);
+
+ UncText &operator=(const UncText &ref);
+
+ UncText &operator=(const std::string &ascii_text);
+
+ UncText &operator=(const char *ascii_text);
+
+
+ void insert(size_t idx, int ch);
+
+ void insert(size_t idx, const UncText &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 UncText &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);
+
+
+ UncText &operator+=(int ch);
+
+ UncText &operator+=(const UncText &ref);
+
+ UncText &operator+=(const std::string &ascii_text);
+
+ UncText &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 UncText &ref1, const UncText &ref2, size_t len = 0, bool tcare = false);
+
+
+ bool equals(const UncText &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;
+ int &at(size_t idx);
+
+
+ //! 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 UncText &text, size_t idx = 0) const;
+
+ bool startswith(const char *text, size_t idx = 0) const;
+
+
+ /**
+ * look for 'text', beginning with position 'idx'
+ *
+ * @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 UncText &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.78.0/src/unc_tools.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_tools.cpp
new file mode 100644
index 00000000..0da2bdd3
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_tools.cpp
@@ -0,0 +1,722 @@
+/**
+ * @file unc_tools.cpp
+ * This file contains lot of tools for debugging
+ *
+ * @author Guy Maurel
+ * October 2015- 2023
+ * @license GPL v2+
+ */
+
+#include "unc_tools.h"
+
+#include "args.h"
+#include "output.h"
+
+constexpr static auto LCURRENT = LGUY;
+
+/*
+ * the test suite Coveralls: https://coveralls.io
+ * will complains because these functions are only
+ * used at development time.
+ * Don't worry about unused 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->GetOrigLine(), 0);
+ * prot_the_line(__func__, __LINE__, 0, 0);
+ * prot_the_line(__func__, __LINE__, 6, 5);
+ * prot_the_source(__LINE__);
+ * log_pcf_flags(LSYS, pc->GetFlags());
+ *
+ * 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->GetOrigLine() == actual_line)
+ {
+ tokenCounter++;
+
+ if ( partNumber == 0
+ || partNumber == tokenCounter)
+ {
+ LOG_FMT(LGUY, " orig line is %d, (%zu) ", actual_line, tokenCounter);
+
+ if (pc->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<VBRACE_OPEN>, ");
+ }
+ else if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "<NL>(new line count is %zu), ", pc->GetNlCount());
+ }
+ else if (pc->Is(CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_CLOSE>, ");
+ }
+ else if (pc->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_OPEN>, ");
+ }
+ else if (pc->Is(CT_SPACE))
+ {
+ LOG_FMT(LGUY, "<CT_SPACE>, ");
+ }
+ else if (pc->Is(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->GetColumn(), pc->GetPpLevel(), get_token_name(pc->GetType()),
+ get_token_name(pc->GetParentType()), pc->GetOrigCol());
+
+ if (pc->Is(CT_IGNORED))
+ {
+ LOG_FMT(LGUY, "\n");
+ }
+ else
+ {
+ LOG_FMT(LGUY, " pc->GetFlags(): ");
+ log_pcf_flags(LGUY, pc->GetFlags());
+ }
+
+ if (pc->Is(CT_COND_COLON))
+ {
+ Chunk *pa = pc->GetParent();
+ LOG_FMT(LGUY, "<> pa-type is %s, orig_line is %zu\n", get_token_name(pa->GetType()), pa->GetOrigLine());
+ }
+
+ if (pc->GetTrackingData() != nullptr)
+ {
+ LOG_FMT(LGUY, " Tracking info are: \n");
+ LOG_FMT(LGUY, " number of track(s) %zu\n", pc->GetTrackingData()->size());
+
+ for (size_t track = 0; track < pc->GetTrackingData()->size(); track++)
+ {
+ const TrackList *A = pc->GetTrackingData();
+ const TrackNumber 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_the_columns(int theLine, unsigned int actual_line)
+{
+ 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++;
+ LOG_FMT(LGUY, "%4d:", theLine);
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->GetOrigLine() == actual_line)
+ {
+ LOG_FMT(LGUY, "%4zu,",
+ pc->GetColumn());
+ }
+ }
+
+ LOG_FMT(LGUY, " (%2zu)\n", counter);
+} // prot_the_columns
+
+
+void prot_the_OrigCols(int theLine, unsigned int actual_line)
+{
+ 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++;
+ LOG_FMT(LGUY, "%4d:", theLine);
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->GetOrigLine() == actual_line)
+ {
+ LOG_FMT(LGUY, "%4zu,",
+ pc->GetOrigCol());
+ }
+ }
+
+ LOG_FMT(LGUY, " (%2zu)\n", counter);
+} // prot_the_OrigCols
+
+
+void rebuild_the_line(int theLine, unsigned int actual_line, bool increment)
+{
+#define MANY 1000
+
+ 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;
+ }
+ }
+ char rebuildLine[MANY];
+ char virtualLine[MANY];
+
+ // fill the array
+ for (size_t where = 0; where < MANY; where++)
+ {
+ rebuildLine[where] = ' ';
+ virtualLine[where] = '_';
+ }
+
+ rebuildLine[MANY - 1] = '\0';
+ virtualLine[MANY - 1] = '\0';
+ LOG_FMT(LGUY, "%4d:", theLine);
+
+ size_t len0 = 0;
+ bool has_a_virtual_brace;
+ has_a_virtual_brace = false;
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->GetOrigLine() == actual_line)
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ size_t col = pc->GetColumn();
+ size_t len1 = pc->Len();
+ len0 = col + len1 - 1;
+ rebuildLine[len0] = '\0';
+ virtualLine[len0] = '\0';
+ break;
+ }
+ else if ( pc->Is(CT_VBRACE_OPEN)
+ || pc->Is(CT_VBRACE_CLOSE))
+ {
+ has_a_virtual_brace = true;
+ size_t col = pc->GetOrigCol();
+ virtualLine[col - 1] = 'V';
+ }
+ else
+ {
+ size_t col = pc->GetColumn();
+ size_t len1 = pc->Len();
+ const char *A = pc->Text();
+
+ for (size_t x = 0; x < len1; x++)
+ {
+ char B = A[x];
+
+ if (col + x >= MANY)
+ {
+ LOG_FMT(LGUY, " ***** MANY is too little for this line %d\n", theLine);
+ exit(EX_SOFTWARE);
+ }
+ rebuildLine[col + x - 1] = B;
+ }
+ }
+ }
+ }
+
+ if (increment)
+ {
+ counter++;
+ }
+ LOG_FMT(LGUY, "%s , counter is %zu\n", rebuildLine, counter);
+
+ if (has_a_virtual_brace)
+ {
+ LOG_FMT(LGUY, "VIRT:%s\n", virtualLine);
+ }
+} // rebuild_the_line
+
+
+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->GetPpLevel());
+
+ if (pc->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<VBRACE_OPEN>, ");
+ }
+ else if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "<NL>(new line count is %zu), ", pc->GetNlCount());
+ tokenCounter = 0;
+ lineNumber = lineNumber + pc->GetNlCount();
+ }
+ else if (pc->Is(CT_VBRACE_CLOSE))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_CLOSE>, ");
+ }
+ else if (pc->Is(CT_VBRACE_OPEN))
+ {
+ LOG_FMT(LGUY, "<CT_VBRACE_OPEN>, ");
+ }
+ else if (pc->Is(CT_SPACE))
+ {
+ LOG_FMT(LGUY, "<CT_SPACE>, ");
+ }
+ else if (pc->Is(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->GetColumn(), get_token_name(pc->GetType()));
+ }
+} // 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 ( pc->Is(CT_SQUARE_CLOSE)
+ || pc->Is(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->GetOrigCol(), pc->GetOrigColEnd());
+ }
+ }
+
+ break;
+
+ case 2:
+ LOG_FMT(LGUY, "2:(%d)\n", theLine);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->GetOrigLine() == 7)
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "(%zu)<NL> col=%zu\n\n", pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ else
+ {
+ LOG_FMT(LGUY, "(%zu)%s %s, col=%zu, column=%zu\n", pc->GetOrigLine(), pc->Text(), get_token_name(pc->GetType()), pc->GetOrigCol(), pc->GetColumn());
+ }
+ }
+ }
+
+ break;
+
+ case 3:
+ LOG_FMT(LGUY, "3:(%d)\n", theLine);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "(%zu)<NL> col=%zu\n\n", pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ else
+ {
+ LOG_FMT(LGUY, "(%zu)%s %s, col=%zu, column=%zu\n", pc->GetOrigLine(), pc->Text(), get_token_name(pc->GetType()), pc->GetOrigCol(), pc->GetColumn());
+ }
+ }
+
+ break;
+
+ case 4:
+ LOG_FMT(LGUY, "4:(%d)\n", theLine);
+
+ for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if (pc->GetOrigLine() == 6)
+ {
+ if (pc->Is(CT_NEWLINE))
+ {
+ LOG_FMT(LGUY, "(%zu)<NL> col=%zu\n\n", pc->GetOrigLine(), pc->GetOrigCol());
+ }
+ else
+ {
+ LOG_FMT(LGUY, "(%zu)%s %s, col=%zu, column=%zu\n", pc->GetOrigLine(), pc->Text(), get_token_name(pc->GetType()), pc->GetOrigCol(), pc->GetColumn());
+ }
+ }
+ }
+
+ 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->GetType()));
+ fprintf(D_file, " orig line %zu\n", pc->GetOrigLine());
+ fprintf(D_file, " orig col %zu\n", pc->GetOrigCol());
+ fprintf(D_file, " orig col end %zu\n", pc->GetOrigColEnd());
+
+ if (pc->GetOrigPrevSp() != 0)
+ {
+ fprintf(D_file, " orig prev sp %zu\n", pc->GetOrigPrevSp());
+ }
+
+ if (pc->GetColumn() != 0)
+ {
+ fprintf(D_file, " column %zu\n", pc->GetColumn());
+ }
+
+ if (pc->GetColumnIndent() != 0)
+ {
+ fprintf(D_file, " column indent %zu\n", pc->GetColumnIndent());
+ }
+
+ if (pc->GetNlCount() != 0)
+ {
+ fprintf(D_file, " nl_count %zu\n", pc->GetNlCount());
+ }
+
+ if (pc->GetLevel() != 0)
+ {
+ fprintf(D_file, " level %zu\n", pc->GetLevel());
+ }
+
+ if (pc->GetBraceLevel() != 0)
+ {
+ fprintf(D_file, " brace level %zu\n", pc->GetBraceLevel());
+ }
+
+ if (pc->GetPpLevel() != 0)
+ {
+ fprintf(D_file, " pp level %zu\n", pc->GetPpLevel());
+ }
+
+ if (pc->GetAfterTab() != 0)
+ {
+ fprintf(D_file, " after tab %d\n", pc->GetAfterTab());
+ }
+
+ if (pc->IsNot(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.CopyAndAddBefore(Chunk::NullChunkPtr);
+ 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]);
+ chunk.SetType(tokenName);
+ }
+ else if (strcasecmp(parts[0], "orig line") == 0)
+ {
+ chunk.SetOrigLine(strtol(parts[1], nullptr, 0));
+ }
+ else if (strcasecmp(parts[0], "orig col") == 0)
+ {
+ chunk.SetOrigCol(strtol(parts[1], nullptr, 0));
+ }
+ else if (strcasecmp(parts[0], "orig col end") == 0)
+ {
+ chunk.SetOrigColEnd(strtol(parts[1], nullptr, 0));
+ }
+ else if (strcasecmp(parts[0], "orig prev sp") == 0)
+ {
+ chunk.SetOrigPrevSp(strtol(parts[1], nullptr, 0));
+ }
+ else if (strcasecmp(parts[0], "column") == 0)
+ {
+ chunk.SetColumn(strtol(parts[1], nullptr, 0));
+ }
+ else if (strcasecmp(parts[0], "nl_count") == 0)
+ {
+ chunk.SetNlCount(strtol(parts[1], nullptr, 0));
+ }
+ else if (strcasecmp(parts[0], "text") == 0)
+ {
+ if (chunk.GetType() != 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.CopyAndAddBefore(Chunk::NullChunkPtr);
+ 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);
+}
+
+
+void dump_keyword_for_lang(size_t language_count, chunk_tag_t *keyword_for_lang)
+{
+ LOG_FMT(LDYNKW, "%s: tag type flags\n", __func__);
+
+ for (size_t ii = 0; ii < language_count; ii++)
+ {
+ std::bitset<16> bit_a;
+ bit_a = keyword_for_lang[ii].lang_flags;
+ std::string g_a;
+ g_a = bit_a.to_string();
+ LOG_FMT(LDYNKW, "%s: %3zu: %18s, %14s, %12ld, %16s, %s\n",
+ __func__, ii,
+ keyword_for_lang[ii].tag, get_token_name(keyword_for_lang[ii].type),
+ (long)keyword_for_lang[ii].lang_flags,
+ g_a.data(),
+ language_name_from_flags(keyword_for_lang[ii].lang_flags));
+ }
+}
+
+
+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
+
+char dump_file_name[80];
+
+
+void set_dump_file_name(const char *name)
+{
+ sprintf(dump_file_name, "%s", name);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_tools.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_tools.h
new file mode 100644
index 00000000..6cae2ff6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unc_tools.h
@@ -0,0 +1,66 @@
+/**
+ * @file unc_tools.h
+ *
+ * @author Guy Maurel
+ * October 2015, 2023
+ * @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
+
+extern char dump_file_name[80];
+
+void set_dump_file_name(const char *name);
+
+
+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 prot_the_columns(int theLine, unsigned int actual_line);
+
+
+void prot_the_OrigCols(int theLine, unsigned int actual_line);
+
+
+void rebuild_the_line(int theLine, unsigned int actual_line, bool increment = true);
+
+
+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();
+
+
+void dump_keyword_for_lang(size_t language_count, chunk_tag_t *keyword_for_lang);
+
+//! This save the next formatting step to a file
+void dump_step(const char *filename, const char *description);
+
+
+#endif /* UNC_TOOLS_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.cpp
new file mode 100644
index 00000000..0a7bda62
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.cpp
@@ -0,0 +1,2537 @@
+/**
+ * @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 "change_int_types.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 "language_names.h"
+#include "mark_functor.h"
+#include "mark_question_colon.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 "rewrite_infinite_loops.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;
+
+
+/**
+ * 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);
+
+
+/**
+ * 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)
+ * @param is_quiet whether output should be quiet
+ */
+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, bool is_quiet);
+
+
+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, bool is_quiet);
+
+
+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 bool bout_content_matches(const file_mem &fm, bool report_status, bool is_quiet);
+
+
+/**
+ * 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();
+
+
+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 space tracking information for debugging.\n"
+ " --tracking nl:FILE : Prepare newline tracking information for debugging.\n"
+ " --tracking start:FILE : Prepare start of statement tracking information 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()
+{
+ 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);
+ usage_error();
+ exit(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 (const auto &token_name : token_names)
+ {
+ const size_t name_length = strlen(token_name);
+
+ if (name_length > max_name_length)
+ {
+ fprintf(stderr, "%s(%d): The token name '%s' is too long (%d)\n",
+ __func__, __LINE__, token_name, 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
+ static_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<E_PcfFlag>(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_T;
+
+ if ( ((dump_file_T = arg.Param("--dump-steps")) != nullptr)
+ || ((dump_file_T = arg.Param("-ds")) != nullptr))
+ {
+ // and save it
+ // Issue #3976
+ set_dump_file_name(dump_file_T);
+ LOG_FMT(LNOTE, "Will export formatting steps data to '%s_nnn.log' files\n", dump_file_name);
+ }
+
+ // 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");
+ bool is_quiet = arg.Present("-q");
+
+ 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
+ const char *html_arg = nullptr;
+ html_arg = arg.Param("--tracking");
+
+ if (html_arg != nullptr)
+ {
+ const size_t max_args_length = 256;
+ size_t argLength = strlen(html_arg);
+
+ if (argLength > max_args_length)
+ {
+ fprintf(stderr, "The buffer is to short for the tracking argument '%s'\n", html_arg);
+ log_flush(true);
+ exit(EX_SOFTWARE);
+ }
+ char buffer[max_args_length];
+ strcpy(buffer, html_arg);
+
+ // Tokenize and extract key and value
+ const char *tracking_art = strtok(buffer, ":");
+ const char *html_file = strtok(nullptr, ":");
+
+ if (html_file != nullptr)
+ {
+ if (strcmp(tracking_art, "space") == 0)
+ {
+ cpd.html_type = tracking_type_e::TT_SPACE;
+ }
+ else if (strcmp(tracking_art, "nl") == 0)
+ {
+ cpd.html_type = tracking_type_e::TT_NEWLINE;
+ }
+ else if (strcmp(tracking_art, "start") == 0)
+ {
+ cpd.html_type = tracking_type_e::TT_START;
+ }
+ else
+ {
+ fprintf(stderr, "tracking_art '%s' not implemented\n",
+ tracking_art);
+ log_flush(true);
+ return(EXIT_FAILURE);
+ }
+ cpd.html_file = html_file;
+ }
+ }
+ 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 != nullptr) ? output_file : "null");
+ LOG_FMT(LDATA, "source_file = %s\n", (source_file != nullptr) ? source_file : "null");
+ LOG_FMT(LDATA, "source_list = %s\n", (source_list != nullptr) ? source_list : "null");
+ LOG_FMT(LDATA, "tracking_art = %s\n", get_tracking_type_e_name(cpd.html_type));
+ LOG_FMT(LDATA, "tracking = %s\n", (cpd.html_file != nullptr) ? cpd.html_file : "null");
+ LOG_FMT(LDATA, "prefix = %s\n", (prefix != nullptr) ? prefix : "null");
+ LOG_FMT(LDATA, "suffix = %s\n", (suffix != nullptr) ? suffix : "null");
+ LOG_FMT(LDATA, "assume = %s\n", (assume != nullptr) ? 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_var_def_blk_end_func_top");
+
+ if (options::nl_var_def_blk_end_func_top() >= options::nl_max())
+ {
+ fprintf(stderr, "The option 'nl_var_def_blk_end_func_top' is too big against the option 'nl_max'\n");
+ log_flush(true);
+ exit(EX_CONFIG);
+ }
+ }
+ }
+ // Set config options using command line arguments.
+ idx = 0;
+
+ while ((p_arg = arg.Params("--set", idx)) != nullptr)
+ {
+ size_t argLength = strlen(p_arg);
+ const size_t max_args_length = 256;
+
+ 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((unsigned int)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);
+ exit(EX_IOERR);
+ }
+ 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
+ && cpd.html_type == tracking_type_e::TT_NONE)) // Issue #4066
+ {
+ 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");
+ exit(EX_IOERR);
+ }
+ 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_name, is_quiet);
+ }
+ else if (source_file != nullptr)
+ {
+ // Doing a single file
+ do_source_file(source_file, output_file, parsed_file, dump_file_name, no_backup, keep_mtime, is_quiet);
+ }
+ 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_name[0] != char(0)) // Issue #3976
+ {
+ 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, is_quiet);
+ }
+
+ if (source_list != nullptr)
+ {
+ process_source_list(source_list, prefix, suffix, no_backup, keep_mtime, is_quiet);
+ }
+ }
+ clear_keyword_file();
+
+ 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 is_quiet)
+{
+ 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);
+ exit(EX_IOERR);
+ }
+ 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, is_quiet);
+ }
+ }
+
+ 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);
+ exit(EX_IOERR);
+ }
+ }
+ 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);
+ exit(EX_IOERR);
+ }
+ 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);
+ exit(EX_IOERR);
+ }
+ 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());
+ exit(EX_IOERR);
+ }
+ }
+ 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 bool bout_content_matches(const file_mem &fm, bool report_status, bool is_quiet)
+{
+ 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)
+ {
+ if (!is_quiet)
+ {
+ 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,
+ bool is_quiet)
+{
+ 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);
+ exit(EX_IOERR);
+ }
+ LOG_FMT(LSYS, "%s: Parsing: %s as language %s\n",
+ __func__, 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, is_quiet, true);
+
+ if (bout_content_matches(fm, false, is_quiet))
+ {
+ 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 += ".uncrustify";
+
+ 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);
+ exit(EX_IOERR);
+ }
+ 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);
+ exit(EX_IOERR);
+ }
+ did_open = true;
+ //LOG_FMT(LSYS, "Output file %s\n", filename_out);
+ }
+ }
+
+ if (cpd.if_changed)
+ {
+ for (UINT8 i : *cpd.bout)
+ {
+ fputc(i, pfout);
+ }
+
+ uncrustify_end();
+ }
+ else
+ {
+ uncrustify_file(fm, pfout, parsed_file, dump_file, is_quiet);
+ }
+
+ 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);
+ exit(EX_IOERR);
+ }
+ }
+ }
+
+ 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()
+ && pc->IsNewline())
+ {
+ pc = pc->GetPrev();
+ }
+
+ if ( pc->IsNotNullChunk()
+ && ( !pc->IsComment()
+ || !pc->GetPrev()->IsNewline()))
+ {
+ pc = Chunk::GetTail();
+
+ if (!pc->IsNewline())
+ {
+ LOG_FMT(LSYS, "Adding a newline at the end of the file\n");
+ newline_add_after(pc);
+ }
+ tokenize(cpd.file_ftr.data, Chunk::NullChunkPtr);
+ }
+}
+
+
+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->GetType() != type)
+ {
+ continue;
+ }
+ log_rule_B("cmt_insert_before_inlines");
+
+ if ( pc->TestFlags(PCF_IN_CLASS)
+ && !options::cmt_insert_before_inlines())
+ {
+ continue;
+ }
+ // Check for one liners for classes. Declarations only. Walk down the chunks.
+ ref = pc;
+
+ if ( ref->Is(CT_CLASS)
+ && ref->GetParentType() == CT_NONE
+ && ref->GetNext())
+ {
+ ref = ref->GetNext();
+
+ if ( ref->Is(CT_TYPE)
+ && ref->GetParentType() == type
+ && ref->GetNext())
+ {
+ ref = ref->GetNext();
+
+ if ( ref->Is(CT_SEMICOLON)
+ && ref->GetLevel() == pc->GetLevel())
+ {
+ continue;
+ }
+ }
+ }
+ // Check for one liners for functions. There'll be a closing brace w/o any newlines. Walk down the chunks.
+ ref = pc;
+
+ if ( ref->Is(CT_FUNC_DEF)
+ && ref->GetParentType() == CT_NONE
+ && ref->GetNext())
+ {
+ int found_brace = 0; // Set if a close brace is found before a newline
+
+ while ( ref->IsNot(CT_NEWLINE)
+ && (ref = ref->GetNext())) // TODO: is the assignment of ref wanted here?, better move it to the loop
+ {
+ if (ref->Is(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->GetLevel() != pc->GetLevel()
+ || ref->Is(CT_ACCESS_COLON))
+ {
+ do_insert = true;
+ break;
+ }
+
+ // If we hit an angle close, back up to the angle open
+ if (ref->Is(CT_ANGLE_CLOSE))
+ {
+ ref = ref->GetPrevType(CT_ANGLE_OPEN, ref->GetLevel(), E_Scope::PREPROC);
+ continue;
+ }
+
+ // Bail if we hit a preprocessor and cmt_insert_before_preproc is false
+ if (ref->TestFlags(PCF_IN_PREPROC))
+ {
+ tmp = ref->GetPrevType(CT_PREPROC, ref->GetLevel());
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetParentType() == 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()
+ && ref->GetPrev()->IsNewline())
+ {
+ break;
+ }
+
+ if ( ref->GetLevel() == pc->GetLevel()
+ && ( ref->TestFlags(PCF_IN_PREPROC)
+ || ref->Is(CT_SEMICOLON)
+ || ref->Is(CT_BRACE_CLOSE)))
+ {
+ do_insert = true;
+ break;
+ }
+ }
+
+ if ( ref->IsNullChunk()
+ && !Chunk::GetHead()->IsComment()
+ && Chunk::GetHead()->GetParentType() == 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->SetLevel(after->GetLevel());
+ }
+ }
+ }
+} // 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->GetType() != 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())->IsNotNullChunk())
+ {
+ // ignore the CT_TYPE token that is the result type
+ if ( ref->GetLevel() != pc->GetLevel()
+ && ( ref->Is(CT_TYPE)
+ || ref->Is(CT_PTR_TYPE)))
+ {
+ continue;
+ }
+
+ // If we hit a parentheses around return type, back up to the open parentheses
+ if (ref->Is(CT_PAREN_CLOSE))
+ {
+ ref = ref->GetPrevType(CT_PAREN_OPEN, ref->GetLevel(), E_Scope::PREPROC);
+ continue;
+ }
+
+ // Bail if we hit a preprocessor and cmt_insert_before_preproc is false
+ if (ref->TestFlags(PCF_IN_PREPROC))
+ {
+ tmp = ref->GetPrevType(CT_PREPROC, ref->GetLevel());
+
+ if ( tmp->IsNotNullChunk()
+ && tmp->GetParentType() == CT_PP_IF)
+ {
+ tmp = tmp->GetPrevNnl();
+
+ log_rule_B("cmt_insert_before_preproc");
+
+ if ( tmp->IsComment()
+ && !options::cmt_insert_before_preproc())
+ {
+ break;
+ }
+ }
+ }
+
+ if ( ref->GetLevel() == pc->GetLevel()
+ && ( ref->TestFlags(PCF_IN_PREPROC)
+ || ref->Is(CT_OC_SCOPE)))
+ {
+ ref = ref->GetPrev();
+
+ if (ref->IsNotNullChunk())
+ {
+ // Ignore 'right' comments
+ if ( ref->IsNewline()
+ && 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->SetLevel(after->GetLevel());
+ }
+ }
+ }
+} // add_msg_header
+
+
+static void uncrustify_start(const deque<int> &data)
+{
+ // Parse the text into chunks
+ tokenize(data, Chunk::NullChunkPtr);
+ 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->GetOrigCol();
+ }
+
+ // 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();
+ }
+ mark_question_colon();
+
+ // 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();
+
+ mark_functor();
+} // uncrustify_start
+
+
+void uncrustify_file(const file_mem &fm, FILE *pfout, const char *parsed_file,
+ const char *dump_file, bool is_quiet, 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;
+
+ if ( options::utf8_force()
+ || ( (cpd.enc == char_encoding_e::e_BYTE)
+ && options::utf8_byte()))
+ {
+ log_rule_B("utf8_force");
+ log_rule_B("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");
+ exit(EX_IOERR);
+ }
+ 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())
+ {
+ log_rule_B("cmt_insert_function_header");
+
+ add_func_header(CT_FUNC_DEF, cpd.func_hdr);
+
+ if (options::cmt_insert_before_ctor_dtor())
+ {
+ add_func_header(CT_FUNC_CLASS_DEF, cpd.func_hdr);
+ }
+ }
+
+ if (!cpd.class_hdr.data.empty())
+ {
+ log_rule_B("cmt_insert_class_header");
+ add_func_header(CT_CLASS, cpd.class_hdr);
+ }
+
+ if (!cpd.oc_msg_hdr.data.empty())
+ {
+ log_rule_B("cmt_insert_oc_message_header");
+ add_msg_header(CT_OC_MSG_DECL, cpd.oc_msg_hdr);
+ }
+ do_parent_for_pp();
+
+ // Rewrite infinite loops
+ if (options::mod_infinite_loop())
+ {
+ log_rule_B("mod_infinite_loop");
+ rewrite_infinite_loops();
+ }
+ // Change virtual braces into real braces
+ do_braces();
+
+ // Scrub extra semicolons
+ if (options::mod_remove_extra_semicolon())
+ {
+ log_rule_B("mod_remove_extra_semicolon");
+ remove_extra_semicolons();
+ }
+
+ // Remove unnecessary returns
+ if (options::mod_remove_empty_return())
+ {
+ log_rule_B("mod_remove_empty_return");
+ remove_extra_returns();
+ }
+
+ // Add or remove redundant 'int' keyword of integer types
+ if ( ( language_is_set(LANG_C)
+ || language_is_set(LANG_CPP))
+ && ( options::mod_int_short() != IARF_IGNORE
+ || options::mod_short_int() != IARF_IGNORE
+ || options::mod_int_long() != IARF_IGNORE
+ || options::mod_long_int() != IARF_IGNORE
+ || options::mod_int_signed() != IARF_IGNORE
+ || options::mod_signed_int() != IARF_IGNORE
+ || options::mod_int_unsigned() != IARF_IGNORE
+ || options::mod_unsigned_int() != IARF_IGNORE))
+ {
+ log_rule_B("mod_int_short");
+ log_rule_B("mod_short_int");
+ log_rule_B("mod_int_long");
+ log_rule_B("mod_long_int");
+ log_rule_B("mod_int_signed");
+ log_rule_B("mod_signed_int");
+ log_rule_B("mod_int_unsigned");
+ log_rule_B("mod_unsigned_int");
+ change_int_types();
+ }
+
+ // Remove duplicate include
+ if (options::mod_remove_duplicate_include())
+ {
+ log_rule_B("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;
+
+ if (options::nl_remove_extra_newlines() == 2)
+ {
+ log_rule_B("nl_remove_extra_newlines");
+ 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
+
+ if (options::nl_after_multiline_comment())
+ {
+ log_rule_B("nl_after_multiline_comment");
+ newline_after_multiline_comment();
+ }
+
+ if (options::nl_after_label_colon())
+ {
+ log_rule_B("nl_after_label_colon");
+ newline_after_label_colon();
+ }
+ newlines_insert_blank_lines();
+
+ if (options::pos_bool() != TP_IGNORE)
+ {
+ log_rule_B("pos_bool");
+ newlines_chunk_pos(CT_BOOL, options::pos_bool());
+ }
+
+ if (options::pos_compare() != TP_IGNORE)
+ {
+ log_rule_B("pos_compare");
+ newlines_chunk_pos(CT_COMPARE, options::pos_compare());
+ }
+
+ if (options::pos_conditional() != TP_IGNORE)
+ {
+ log_rule_B("pos_conditional");
+ newlines_chunk_pos(CT_COND_COLON, options::pos_conditional());
+ newlines_chunk_pos(CT_QUESTION, options::pos_conditional());
+ }
+
+ if ( options::pos_comma() != TP_IGNORE
+ || options::pos_enum_comma() != TP_IGNORE)
+ {
+ log_rule_B("pos_comma");
+ log_rule_B("pos_enum_comma");
+ newlines_chunk_pos(CT_COMMA, options::pos_comma());
+ }
+
+ if (options::pos_assign() != TP_IGNORE)
+ {
+ log_rule_B("pos_assign");
+ newlines_chunk_pos(CT_ASSIGN, options::pos_assign());
+ }
+
+ if (options::pos_arith() != TP_IGNORE)
+ {
+ log_rule_B("pos_arith");
+ newlines_chunk_pos(CT_ARITH, options::pos_arith());
+ newlines_chunk_pos(CT_CARET, options::pos_arith());
+ }
+
+ if (options::pos_shift() != TP_IGNORE)
+ {
+ log_rule_B("pos_shift");
+ newlines_chunk_pos(CT_SHIFT, options::pos_shift());
+ }
+ newlines_class_colon_pos(CT_CLASS_COLON);
+ newlines_class_colon_pos(CT_CONSTR_COLON);
+
+ if (options::nl_squeeze_ifdef())
+ {
+ log_rule_B("nl_squeeze_ifdef");
+ newlines_squeeze_ifdef();
+ }
+
+ if (options::nl_squeeze_paren_close())
+ {
+ log_rule_B("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
+ if (options::sp_balance_nested_parens())
+ {
+ log_rule_B("sp_balance_nested_parens");
+ space_text_balance_nested_parens();
+ }
+
+ // Scrub certain added semicolons
+ if ( language_is_set(LANG_PAWN)
+ && options::mod_pawn_semicolon())
+ {
+ log_rule_B("mod_pawn_semicolon");
+ pawn_scrub_vsemi();
+ }
+
+ // Sort imports/using/include
+ if ( options::mod_sort_import()
+ || options::mod_sort_include()
+ || options::mod_sort_using())
+ {
+ log_rule_B("mod_sort_import");
+ log_rule_B("mod_sort_include");
+ log_rule_B("mod_sort_using");
+ sort_imports();
+ }
+ // Fix same-line inter-chunk spacing
+ space_text();
+
+ if (options::align_pp_define_span() > 0)
+ {
+ // Do any aligning of preprocessors
+ log_rule_B("align_pp_define_span");
+ align_preprocessor();
+ }
+ // Indent the text
+ indent_preproc();
+ indent_text();
+
+ // Insert trailing comments after certain close braces
+ 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))
+ {
+ 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");
+ add_long_closebrace_comment();
+ }
+
+ // Insert trailing comments after certain preprocessor conditional blocks
+ if ( (options::mod_add_long_ifdef_else_comment() > 0)
+ || (options::mod_add_long_ifdef_endif_comment() > 0))
+ {
+ log_rule_B("mod_add_long_ifdef_else_comment");
+ log_rule_B("mod_add_long_ifdef_endif_comment");
+ 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;
+
+ if (options::code_width() > 0)
+ {
+ log_rule_B("code_width");
+ LOG_FMT(LNEWLINE, "%s(%d): Code_width loop start: %d\n",
+ __func__, __LINE__, cpd.changes);
+
+ if (options::debug_max_number_of_loops() > 0)
+ {
+ log_rule_B("debug_max_number_of_loops");
+
+ 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();
+
+ if (options::align_nl_cont())
+ {
+ log_rule_B("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
+ {
+ make_folders(cpd.html_file); // Issue #4066
+ // create the tracking file
+ FILE *t_file;
+ t_file = fopen(cpd.html_file, "wb");
+
+ if (t_file == nullptr)
+ {
+ LOG_FMT(LERR, "%s: Unable to create %s: %s (%d)\n",
+ __func__, cpd.html_file, strerror(errno), errno);
+ exit(EX_IOERR);
+ }
+ output_text(t_file);
+ fclose(t_file);
+ exit(EX_OK);
+ }
+
+ // 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);
+ exit(EX_IOERR);
+ }
+ }
+
+ if ( cpd.do_check
+ && !bout_content_matches(fm, true, is_quiet))
+ {
+ 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::Delete(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);
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.h
new file mode 100644
index 00000000..3b839060
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify.h
@@ -0,0 +1,69 @@
+/**
+ * @file uncrustify.h
+ * prototypes for uncrustify.cpp
+ *
+ * @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 uncrustify_file(const file_mem &fm, FILE *pfout, const char *parsed_file, const char *dump_filename, bool is_quiet, bool defer_uncrustify_end = false);
+
+
+void uncrustify_end();
+
+
+const char *get_token_name(E_Token token);
+
+
+/**
+ * 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);
+
+
+/**
+ * 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);
+
+#endif /* UNCRUSTIFY_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_emscripten.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_emscripten.cpp
new file mode 100644
index 00000000..790e7ece
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_emscripten.cpp
@@ -0,0 +1,1213 @@
+/*
+ * 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 formatting step we reset this var here
+ 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 formatted
+ // 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 (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 formatted 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_CPP_ENDIF", E_Token::CT_COMMENT_CPP_ENDIF)
+ .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.78.0/src/uncrustify_limits.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_limits.h
new file mode 100644
index 00000000..9f226870
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/uncrustify_types.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_types.cpp
new file mode 100644
index 00000000..4dc959c7
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_types.cpp
@@ -0,0 +1,108 @@
+/**
+ * @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(E_BraceStage brace_stage)
+{
+ switch (brace_stage)
+ {
+ case E_BraceStage::NONE:
+ return("NONE");
+
+ case E_BraceStage::PAREN1:
+ return("PAREN1");
+
+ case E_BraceStage::OP_PAREN1:
+ return("OP_PAREN1");
+
+ case E_BraceStage::WOD_PAREN:
+ return("WOD_PAREN");
+
+ case E_BraceStage::WOD_SEMI:
+ return("WOD_SEMI");
+
+ case E_BraceStage::BRACE_DO:
+ return("BRACE_DO");
+
+ case E_BraceStage::BRACE2:
+ return("BRACE2");
+
+ case E_BraceStage::ELSE:
+ return("ELSE");
+
+ case E_BraceStage::ELSEIF:
+ return("ELSEIF");
+
+ case E_BraceStage::WHILE:
+ return("WHILE");
+
+ case E_BraceStage::CATCH:
+ return("CATCH");
+
+ case E_BraceStage::CATCH_WHEN:
+ return("CATCH_WHEN");
+ }
+ return("?????");
+} // get_brace_stage_name
+
+
+const char *get_tracking_type_e_name(tracking_type_e type)
+{
+ switch (type)
+ {
+ case tracking_type_e::TT_NONE:
+ return("NONE");
+
+ case tracking_type_e::TT_SPACE:
+ return("space");
+
+ case tracking_type_e::TT_NEWLINE:
+ return("newline");
+
+ case tracking_type_e::TT_START:
+ return("start");
+ }
+ return("?????");
+} // get_tracking_type_e_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.78.0/src/uncrustify_types.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_types.h
new file mode 100644
index 00000000..0e2a0786
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_types.h
@@ -0,0 +1,280 @@
+/**
+ * @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> // to get size_t
+
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+
+
+/**
+ * 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*"
+
+/**
+ * @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 E_BraceStage : 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
+};
+
+enum class tracking_type_e : unsigned int
+{
+ TT_NONE,
+ TT_SPACE,
+ TT_NEWLINE,
+ TT_START
+};
+
+const char *get_tracking_type_e_name(tracking_type_e type);
+
+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 IndentationData
+{
+ Chunk *ref;
+ int delta;
+};
+
+
+struct AlignmentData
+{
+ Chunk *next; //! Chunk::NullChunkPtr 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 *> TrackNumber; // track for "trackNumber" and "rule"
+typedef std::vector<TrackNumber> TrackList; // list of 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
+ Chunk *ref; // Issue #3786
+};
+
+//! 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;
+
+ 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];
+ UncText newline;
+
+ bool 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;
+ // for debugging purpose only
+ tracking_type_e html_type = tracking_type_e::TT_NONE;
+ const char *html_file = nullptr;
+};
+
+extern cp_data_t cpd; // TODO: can we avoid this external variable?
+
+const char *get_brace_stage_name(E_BraceStage 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.78.0/src/uncrustify_version.h.in b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/uncrustify_version.h.in
new file mode 100644
index 00000000..079e0fa6
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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.78.0/src/unicode.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unicode.cpp
new file mode 100644
index 00000000..684f5b0a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.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()
+{
+ 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 UncText &text)
+{
+ for (size_t idx = 0; idx < text.size(); idx++)
+ {
+ write_char(text[idx]);
+ }
+}
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unicode.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unicode.h
new file mode 100644
index 00000000..28318f91
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/unicode.h
@@ -0,0 +1,34 @@
+/**
+ * @file unicode.h
+ * prototypes for unicode.cpp
+ *
+ * @author Ben Gardner
+ * @license GPL v2+
+ */
+
+#ifndef UNICODE_H_INCLUDED
+#define UNICODE_H_INCLUDED
+
+#include "uncrustify_types.h"
+
+
+void write_bom();
+
+
+/**
+ * @param ch the 31-bit char value
+ */
+void write_char(int ch);
+
+
+void write_string(const UncText &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.78.0/src/universalindentgui.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/universalindentgui.cpp
new file mode 100644
index 00000000..23b2912a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/universalindentgui.cpp
@@ -0,0 +1,377 @@
+/**
+ * @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*=\\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/category
+ 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"
+ "useRegex=true\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;
+ }
+ }
+
+#if defined (DEBUG) && !defined (WIN32)
+ fprintf(pfile, "\n[(%zu)%s]\n", optionNumber, optionNameReadable);
+#else // DEBUG
+ fprintf(pfile, "\n[%s]\n", optionNameReadable);
+#endif // DEBUG
+ 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\\s*=\\s*0|%s\\s*=\\s*1|%s\\s*=\\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\\s*=\\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\\s*=\\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\\s*=\\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.78.0/src/universalindentgui.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/universalindentgui.h
new file mode 100644
index 00000000..79a41bf5
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/universalindentgui.h
@@ -0,0 +1,17 @@
+/**
+ * @file universalindentgui.h
+ * prototypes for universalindentgui.cpp
+ *
+ * @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.78.0/src/width.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/width.cpp
new file mode 100644
index 00000000..4dcc0249
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/width.cpp
@@ -0,0 +1,756 @@
+/**
+ * @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 SplitEntry
+{
+ Chunk *pc;
+ size_t pri;
+
+ SplitEntry()
+ : pc(Chunk::NullChunkPtr)
+ , pri(0) {}
+};
+
+
+struct TokenPriority
+{
+ 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(SplitEntry &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 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
+ size_t currCol = pc->GetColumn() + pc->Len() - 1;
+
+ LOG_FMT(LSPLIT, "%s(%d): orig line %zu, orig col %zu, curr col %zu, text %s\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), currCol, pc->Text());
+ return(currCol > 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());
+
+ Chunk *prev = pc->GetPrev();
+
+ if ( !pc->IsNewline()
+ && !prev->IsNewline())
+ {
+ newline_add_before(pc);
+ // Mark chunk as continuation line, so indentation can be
+ // correctly set over multiple passes
+ pc->SetFlagBits(PCF_CONT_LINE);
+
+ // Mark open and close parens as continuation line chunks.
+ // This will prevent an additional level and frame to be
+ // added to the current frame stack (issue 3105).
+ if ( prev->Is(CT_PAREN_OPEN)
+ || prev->Is(CT_LPAREN_OPEN)
+ || prev->Is(CT_SPAREN_OPEN)
+ || prev->Is(CT_FPAREN_OPEN)
+ || prev->Is(CT_SQUARE_OPEN)
+ || prev->Is(CT_ANGLE_OPEN))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): set PCF_LINE_CONT for prev text '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, prev->Text(), prev->GetOrigLine(), prev->GetOrigCol());
+
+ prev->SetFlagBits(PCF_CONT_LINE);
+ Chunk *closing_paren = prev->GetClosingParen();
+
+ if (closing_paren->IsNotNullChunk())
+ {
+ closing_paren->SetFlagBits(PCF_CONT_LINE);
+ }
+ }
+ // 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->GetBraceLevel() * options::indent_columns() +
+ abs(options::indent_continue()) + 1);
+ cpd.changes++;
+ }
+} // split_before_chunk
+
+
+static TokenPriority 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, 9 },
+ { CT_STRING, 10 },
+ { CT_FOR_COLON, 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 },
+};
+
+
+void do_code_width()
+{
+ LOG_FUNC_ENTRY();
+ LOG_FMT(LSPLIT, "%s(%d)\n", __func__, __LINE__);
+
+ // If indent_continue is negative, we want to look for long lines splits,
+ // so raise CT_FPAREN_OPEN priority to get better results.
+ if (options::indent_continue() < 0)
+ {
+ for (TokenPriority &token : pri_table)
+ {
+ if (token.tok == CT_FPAREN_OPEN)
+ {
+ token.pri = 8; // Before assignment priority
+ break;
+ }
+ }
+ }
+
+ for (Chunk *pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNext())
+ {
+ if ( !pc->IsCommentOrNewline()
+ && pc->IsNot(CT_SPACE)
+ && is_past_width(pc))
+ {
+ if ( pc->Is(CT_VBRACE_CLOSE) // don't break if a vbrace close
+ && pc->IsLastChunkOnLine()) // 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->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ }
+ else
+ {
+ LOG_FMT(LSPLIT, "%s(%d): Bailed! orig line is %zu, orig col is %zu, Text() '%s'\n",
+ __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text());
+ break;
+ }
+ }
+ }
+} // do_code_width
+
+
+static size_t get_split_pri(E_Token tok)
+{
+ for (TokenPriority token : pri_table)
+ {
+ if (token.tok == tok)
+ {
+ return(token.pri);
+ }
+ }
+
+ return(100); // Bigger than any valid priority
+}
+
+
+static void try_split_here(SplitEntry &ent, Chunk *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ size_t pc_pri = get_split_pri(pc->GetType());
+ LOG_FMT(LSPLIT, "%s(%d): text '%s', orig col %zu pc_pri %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigCol(), pc_pri);
+
+ if (pc_pri == 0)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): pc_pri is 0, return\n", __func__, __LINE__);
+ return;
+ }
+ // Can't split after a newline
+ Chunk *prev = pc->GetPrev();
+
+ if ( prev->IsNullChunk()
+ || ( prev->IsNewline()
+ && pc->IsNot(CT_STRING)))
+ {
+ if (prev->IsNotNullChunk())
+ {
+ LOG_FMT(LSPLIT, "%s(%d): can't split after a newline, orig line is %zu, return\n",
+ __func__, __LINE__, prev->GetOrigLine());
+ }
+ return;
+ }
+
+ // Can't split a function without arguments
+ if (pc->Is(CT_FPAREN_OPEN))
+ {
+ Chunk *next = pc->GetNext();
+
+ if (next->Is(CT_FPAREN_CLOSE))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): can't split a function without arguments, return\n", __func__, __LINE__);
+ return;
+ }
+ }
+
+ // Only split concatenated strings
+ if (pc->Is(CT_STRING))
+ {
+ Chunk *next = pc->GetNext();
+
+ if (next->IsNot(CT_STRING))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): only split concatenated strings, return\n", __func__, __LINE__);
+ return;
+ }
+ }
+
+ // keep common groupings unless ls_code_width
+ if ( !options::ls_code_width()
+ && pc_pri >= 22)
+ {
+ LOG_FMT(LSPLIT, "%s(%d): keep common groupings unless ls_code_width, return\n", __func__, __LINE__);
+ return;
+ }
+
+ // don't break after last term of a qualified type
+ if (pc_pri == 25)
+ {
+ Chunk *next = pc->GetNext();
+
+ if ( next->IsNot(CT_WORD)
+ && (get_split_pri(next->GetType()) != 25))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): don't break after last term of a qualified type, return\n", __func__, __LINE__);
+ return;
+ }
+ }
+
+ if ( ent.pc->IsNullChunk()
+ || pc_pri < ent.pri
+ || ( pc_pri == ent.pri
+ && pc->IsNot(CT_FPAREN_OPEN)
+ && pc->GetLevel() < ent.pc->GetLevel()))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): found possible split\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 %zu, orig col %zu, type %s\n",
+ __func__, __LINE__, start->Text(), start->GetOrigLine(), start->GetOrigCol(), get_token_name(start->GetType()));
+ LOG_FMT(LSPLIT, " start->GetFlags() ");
+ log_pcf_flags(LSPLIT, start->GetFlags());
+ LOG_FMT(LSPLIT, " start->GetParentType() %s, (PCF_IN_FCN_DEF %s), (PCF_IN_FCN_CALL %s)\n",
+ get_token_name(start->GetParentType()),
+ start->TestFlags((PCF_IN_FCN_DEF)) ? "TRUE" : "FALSE",
+ start->TestFlags((PCF_IN_FCN_CALL)) ? "TRUE" : "FALSE");
+
+ // break at maximum line length if ls_code_width is true
+ // Issue #2432
+ if (start->TestFlags(PCF_ONE_LINER))
+ {
+ LOG_FMT(LSPLIT, "%s(%d): ** ONE 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__);
+
+ if (options::ls_code_width())
+ {
+ log_rule_B("ls_code_width");
+ }
+ // Check to see if we are in a for statement
+ else if (start->TestFlags(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->TestFlags(PCF_IN_FCN_DEF)
+ || start->TestFlags(PCF_IN_FCN_CALL)
+ || start->GetParentType() == CT_FUNC_PROTO) // Issue #1169
+ {
+ LOG_FMT(LSPLIT, " ** FUNC SPLIT **\n");
+
+ if (options::ls_func_split_full())
+ {
+ log_rule_B("ls_func_split_full");
+
+ split_fcn_params_full(start);
+
+ if (!is_past_width(start))
+ {
+ return(true);
+ }
+ }
+ }
+
+ /*
+ * If this is in a template, split on commas, Issue #1170
+ */
+ else if (start->TestFlags(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
+ SplitEntry ent;
+ ent.pc = Chunk::NullChunkPtr;
+ ent.pri = CT_UNKNOWN;
+
+ Chunk *pc = start->GetPrev();
+ Chunk *prev;
+
+ while ( pc->IsNotNullChunk()
+ && !pc->IsNewline())
+ {
+ LOG_FMT(LSPLIT, "%s(%d): text '%s', orig line is %zu, orig col is %zu\n",
+ __func__, __LINE__, pc->Text(), pc->GetOrigLine(), pc->GetOrigCol());
+
+ if (pc->IsNot(CT_SPACE))
+ {
+ try_split_here(ent, pc);
+
+ // break at maximum line length
+ if ( ent.pc->IsNotNullChunk()
+ && options::ls_code_width())
+ {
+ log_rule_B("ls_code_width");
+ LOG_FMT(LSPLIT, "%s(%d): found split\n", __func__, __LINE__);
+ break;
+ }
+ }
+ pc = pc->GetPrev();
+ }
+
+ if (ent.pc->IsNullChunk())
+ {
+ LOG_FMT(LSPLIT, "%s(%d): TRY_SPLIT yielded NO SOLUTION for orig line %zu at '%s' [%s]\n",
+ __func__, __LINE__, start->GetOrigLine(), start->Text(), get_token_name(start->GetType()));
+ }
+ 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->GetType()), ent.pc->GetOrigLine());
+ LOG_FMT(LSPLIT, "%s(%d): ent at '%s', orig col is %zu\n",
+ __func__, __LINE__, ent.pc->Text(), ent.pc->GetOrigCol());
+ }
+
+ // Break before the token instead of after it according to the pos_xxx rules
+ if (ent.pc->IsNullChunk())
+ {
+ pc = Chunk::NullChunkPtr;
+ }
+ 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 ( ( ent.pc->Is(CT_SHIFT)
+ && (options::pos_shift() & TP_LEAD))
+ || ( ( ent.pc->Is(CT_ARITH)
+ || ent.pc->Is(CT_CARET))
+ && (options::pos_arith() & TP_LEAD))
+ || ( ent.pc->Is(CT_ASSIGN)
+ && (options::pos_assign() & TP_LEAD))
+ || ( ent.pc->Is(CT_COMPARE)
+ && (options::pos_compare() & TP_LEAD))
+ || ( ( ent.pc->Is(CT_COND_COLON)
+ || ent.pc->Is(CT_QUESTION))
+ && (options::pos_conditional() & TP_LEAD))
+ || ( ent.pc->Is(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->GetOrigCol());
+ }
+
+ if (pc->IsNullChunk())
+ {
+ pc = start;
+
+ // Don't break before a close, comma, or colon
+ if ( start->Is(CT_PAREN_CLOSE)
+ || start->Is(CT_PAREN_OPEN)
+ || start->Is(CT_FPAREN_CLOSE)
+ || start->Is(CT_FPAREN_OPEN)
+ || start->Is(CT_SPAREN_CLOSE)
+ || start->Is(CT_SPAREN_OPEN)
+ || start->Is(CT_ANGLE_CLOSE)
+ || start->Is(CT_BRACE_CLOSE)
+ || start->Is(CT_COMMA)
+ || start->IsSemicolon()
+ || 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->IsNotNullChunk()
+ && !pc->IsNewline()
+ && !prev->IsNewline())
+ {
+ //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->GetType()),
+ // slen, start->Text(), get_token_name(start->GetType()));
+ LOG_FMT(LSPLIT, "%s(%d): Text() '%s', type %s, started on token '%s', type %s\n",
+ __func__, __LINE__, pc->Text(), get_token_name(pc->GetType()),
+ start->Text(), get_token_name(start->GetType()));
+
+ 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 = Chunk::NullChunkPtr;
+ size_t nl_cnt = 0;
+
+ LOG_FMT(LSPLIT, "%s: starting on %s, line %zu\n",
+ __func__, start->Text(), start->GetOrigLine());
+
+ // Find the open paren so we know the level and count newlines
+ Chunk *pc = start;
+
+ while ((pc = pc->GetPrev())->IsNotNullChunk())
+ {
+ if (pc->Is(CT_SPAREN_OPEN))
+ {
+ open_paren = pc;
+ break;
+ }
+
+ if (pc->GetNlCount() > 0)
+ {
+ nl_cnt += pc->GetNlCount();
+ }
+ }
+
+ if (open_paren->IsNullChunk())
+ {
+ LOG_FMT(LSPLIT, "No open paren\n");
+ return;
+ }
+ // see if we started on the semicolon
+ int count = 0;
+ Chunk *st[2];
+
+ pc = start;
+
+ if ( pc->Is(CT_SEMICOLON)
+ && pc->GetParentType() == CT_FOR)
+ {
+ st[count++] = pc;
+ }
+
+ // first scan backwards for the semicolons
+ while ( (count < static_cast<int>(max_cnt))
+ && ((pc = pc->GetPrev())->IsNotNullChunk())
+ && pc->IsNotNullChunk()
+ && pc->TestFlags(PCF_IN_SPAREN))
+ {
+ if ( pc->Is(CT_SEMICOLON)
+ && pc->GetParentType() == CT_FOR)
+ {
+ st[count++] = pc;
+ }
+ }
+ // And now scan forward
+ pc = start;
+
+ while ( (count < static_cast<int>(max_cnt))
+ && ((pc = pc->GetNext())->IsNotNullChunk())
+ && pc->TestFlags(PCF_IN_SPAREN))
+ {
+ if ( pc->Is(CT_SEMICOLON)
+ && pc->GetParentType() == 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 parentheses level
+ pc = open_paren;
+
+ while ((pc = pc->GetNext()) != start)
+ {
+ if ( pc->Is(CT_COMMA)
+ && (pc->GetLevel() == (open_paren->GetLevel() + 1)))
+ {
+ split_before_chunk(pc->GetNext());
+
+ if (!is_past_width(pc))
+ {
+ return;
+ }
+ }
+ }
+ // Still past width, check for a assignments at parentheses level
+ pc = open_paren;
+
+ while ((pc = pc->GetNext()) != start)
+ {
+ if ( pc->Is(CT_ASSIGN)
+ && (pc->GetLevel() == (open_paren->GetLevel() + 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): start at '%s'\n", __func__, __LINE__, start->Text());
+
+ // Find the opening function parenthesis
+ Chunk *fpo = start;
+
+ LOG_FMT(LSPLIT, " %s(%d): search for opening function parenthesis\n", __func__, __LINE__);
+
+ while ((fpo = fpo->GetPrev())->IsNotNullChunk())
+ {
+ LOG_FMT(LSPLIT, " %s(%d): %s, orig col is %zu, level is %zu\n",
+ __func__, __LINE__, fpo->Text(), fpo->GetOrigCol(), fpo->GetLevel());
+
+ if ( fpo->Is(CT_FPAREN_OPEN)
+ && (fpo->GetLevel() == start->GetLevel() - 1))
+ {
+ LOG_FMT(LSPLIT, " %s(%d): found open paren\n", __func__, __LINE__);
+ break; // opening parenthesis found. Issue #1020
+ }
+ }
+ // Now break after every comma
+ Chunk *pc = fpo->GetNextNcNnl();
+
+ while (pc->IsNotNullChunk())
+ {
+ if (pc->GetLevel() <= fpo->GetLevel())
+ {
+ break;
+ }
+
+ if ( (pc->GetLevel() == (fpo->GetLevel() + 1))
+ && pc->Is(CT_COMMA))
+ {
+ split_before_chunk(pc->GetNext());
+ }
+ pc = pc->GetNextNcNnl();
+ }
+}
+
+
+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 ( prev->IsNewline()
+ || prev->Is(CT_COMMA))
+ {
+ break;
+ }
+ }
+
+ if ( prev->IsNotNullChunk()
+ && !prev->IsNewline())
+ {
+ LOG_FMT(LSPLIT, " %s(%d):", __func__, __LINE__);
+ LOG_FMT(LSPLIT, " -- ended on %s --\n", get_token_name(prev->GetType()));
+ 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.78.0/src/width.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/width.h
new file mode 100644
index 00000000..f418fb23
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/width.h
@@ -0,0 +1,21 @@
+/**
+ * @file width.h
+ * prototypes for width.cpp
+ *
+ * @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();
+
+
+#endif /* WIDTH_H_INCLUDED */
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/windows_compat.h b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/windows_compat.h
new file mode 100644
index 00000000..619581b0
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.0/src/windows_compat.h
@@ -0,0 +1,102 @@
+/**
+ * @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
+
+#ifdef WIN32
+#include "windows.h"
+#endif
+
+#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()
+#ifdef WIN32
+#include <direct.h>
+#include <io.h>
+#endif
+#include <fcntl.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 */