summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/lang_pawn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/lang_pawn.cpp')
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/lang_pawn.cpp523
1 files changed, 523 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/lang_pawn.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/lang_pawn.cpp
new file mode 100644
index 00000000..a3b3ed65
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/lang_pawn.cpp
@@ -0,0 +1,523 @@
+/**
+ * @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_t *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_t *pawn_process_line(chunk_t *start);
+
+
+//! We are on a level 0 function proto of def
+static chunk_t *pawn_mark_function0(chunk_t *start, chunk_t *fcn);
+
+
+/**
+ * follows a variable definition at level 0 until the end.
+ * Adds a semicolon at the end, if needed.
+ */
+static chunk_t *pawn_process_variable(chunk_t *start);
+
+
+static chunk_t *pawn_process_func_def(chunk_t *pc);
+
+
+chunk_t *pawn_add_vsemi_after(chunk_t *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ if ( chunk_is_token(pc, CT_VSEMICOLON)
+ || chunk_is_token(pc, CT_SEMICOLON))
+ {
+ return(pc);
+ }
+ chunk_t *next = chunk_get_next_nc(pc);
+
+ if ( next != nullptr
+ && ( chunk_is_token(next, CT_VSEMICOLON)
+ || chunk_is_token(next, CT_SEMICOLON)))
+ {
+ return(pc);
+ }
+ chunk_t chunk = *pc;
+
+ set_chunk_type(&chunk, CT_VSEMICOLON);
+ set_chunk_parent(&chunk, CT_NONE);
+ chunk.str = options::mod_pawn_semicolon() ? ";" : "";
+ chunk.column += pc->len();
+
+ LOG_FMT(LPVSEMI, "%s: Added VSEMI on line %zu, prev='%s' [%s]\n",
+ __func__, pc->orig_line, pc->text(),
+ get_token_name(pc->type));
+
+ return(chunk_add_after(&chunk, pc));
+}
+
+
+void pawn_scrub_vsemi(void)
+{
+ constexpr static auto LCURRENT = LPVSEMI;
+
+ LOG_FUNC_ENTRY();
+
+ log_rule_B("mod_pawn_semicolon");
+
+ if (!options::mod_pawn_semicolon())
+ {
+ return;
+ }
+
+ for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next(pc))
+ {
+ if (pc->type != CT_VSEMICOLON)
+ {
+ continue;
+ }
+ chunk_t *prev = chunk_get_prev_ncnnl(pc);
+
+ if (chunk_is_token(prev, CT_BRACE_CLOSE))
+ {
+ if ( get_chunk_parent_type(prev) == CT_IF
+ || get_chunk_parent_type(prev) == CT_ELSE
+ || get_chunk_parent_type(prev) == CT_SWITCH
+ || get_chunk_parent_type(prev) == CT_CASE
+ || get_chunk_parent_type(prev) == CT_WHILE_OF_DO)
+ {
+ pc->str.clear();
+ }
+ }
+ }
+}
+
+
+static bool pawn_continued(chunk_t *pc, size_t br_level)
+{
+ LOG_FUNC_ENTRY();
+
+ if (pc == nullptr)
+ {
+ return(false);
+ }
+
+ if ( pc->level > br_level
+ || chunk_is_token(pc, CT_ARITH)
+ || chunk_is_token(pc, CT_SHIFT)
+ || chunk_is_token(pc, CT_CARET)
+ || chunk_is_token(pc, CT_QUESTION)
+ || chunk_is_token(pc, CT_BOOL)
+ || chunk_is_token(pc, CT_ASSIGN)
+ || chunk_is_token(pc, CT_COMMA)
+ || chunk_is_token(pc, CT_COMPARE)
+ || chunk_is_token(pc, CT_IF)
+ || chunk_is_token(pc, CT_ELSE)
+ || chunk_is_token(pc, CT_DO)
+ || chunk_is_token(pc, CT_SWITCH)
+ || chunk_is_token(pc, CT_WHILE)
+ || chunk_is_token(pc, CT_BRACE_OPEN)
+ || chunk_is_token(pc, CT_VBRACE_OPEN)
+ || chunk_is_token(pc, CT_FPAREN_OPEN)
+ || get_chunk_parent_type(pc) == CT_IF
+ || get_chunk_parent_type(pc) == CT_ELSE
+ || get_chunk_parent_type(pc) == CT_ELSEIF
+ || get_chunk_parent_type(pc) == CT_DO
+ || get_chunk_parent_type(pc) == CT_FOR
+ || get_chunk_parent_type(pc) == CT_SWITCH
+ || get_chunk_parent_type(pc) == CT_WHILE
+ || get_chunk_parent_type(pc) == CT_FUNC_DEF
+ || get_chunk_parent_type(pc) == CT_ENUM
+ || pc->flags.test_any(PCF_IN_ENUM | PCF_IN_STRUCT)
+ || chunk_is_str(pc, ":", 1)
+ || chunk_is_str(pc, "+", 1)
+ || chunk_is_str(pc, "-", 1))
+ {
+ return(true);
+ }
+ return(false);
+} // pawn_continued
+
+
+void pawn_prescan(void)
+{
+ LOG_FUNC_ENTRY();
+
+ /*
+ * Start at the beginning and step through the entire file, and clean up
+ * any questionable stuff
+ */
+ bool did_nl = true;
+ chunk_t *pc = chunk_get_head();
+
+ while (pc != nullptr)
+ {
+ if ( did_nl
+ && pc->type != CT_PREPROC
+ && !chunk_is_newline(pc)
+ && pc->level == 0)
+ {
+ // pc now points to the start of a line
+ pc = pawn_process_line(pc);
+ }
+
+ // note that continued lines are ignored
+ if (pc != nullptr)
+ {
+ did_nl = (chunk_is_token(pc, CT_NEWLINE));
+ }
+ pc = chunk_get_next_nc(pc);
+ }
+}
+
+
+static chunk_t *pawn_process_line(chunk_t *start)
+{
+ LOG_FUNC_ENTRY();
+
+ //LOG_FMT(LSYS, "%s: %d - %s\n", __func__,
+ // start->orig_line, start->text());
+
+ if ( chunk_is_token(start, CT_NEW)
+ || chunk_is_str(start, "const", 5))
+ {
+ return(pawn_process_variable(start));
+ }
+ // if a open paren is found before an assign, then this is a function
+ chunk_t *fcn = nullptr;
+
+ if (chunk_is_token(start, CT_WORD))
+ {
+ fcn = start;
+ }
+ chunk_t *pc = start;
+
+ while ( ((pc = chunk_get_next_nc(pc)) != nullptr)
+ && !chunk_is_str(pc, "(", 1)
+ && pc->type != CT_ASSIGN
+ && pc->type != CT_NEWLINE)
+ {
+ if ( pc->level == 0
+ && ( chunk_is_token(pc, CT_FUNCTION)
+ || chunk_is_token(pc, CT_WORD)
+ || chunk_is_token(pc, CT_OPERATOR_VAL)))
+ {
+ fcn = pc;
+ }
+ }
+
+ if (pc != nullptr)
+ {
+ if (chunk_is_token(pc, CT_ASSIGN))
+ {
+ return(pawn_process_variable(pc));
+ }
+ }
+
+ if (fcn != nullptr)
+ {
+ //LOG_FMT(LSYS, "FUNCTION: %s\n", fcn->text());
+ return(pawn_mark_function0(start, fcn));
+ }
+
+ if (chunk_is_token(start, CT_ENUM))
+ {
+ pc = chunk_get_next_type(start, CT_BRACE_CLOSE, start->level);
+ return(pc);
+ }
+ //LOG_FMT(LSYS, "%s: Don't understand line %d, starting with '%s' [%s]\n",
+ // __func__, start->orig_line, start->text(), get_token_name(start->type));
+ return(start);
+} // pawn_process_line
+
+
+static chunk_t *pawn_process_variable(chunk_t *start)
+{
+ LOG_FUNC_ENTRY();
+ chunk_t *prev = nullptr;
+ chunk_t *pc = start;
+
+ while ((pc = chunk_get_next_nc(pc)) != nullptr)
+ {
+ if ( chunk_is_token(pc, CT_NEWLINE)
+ && prev != nullptr // Issue 2586
+ && !pawn_continued(prev, start->level))
+ {
+ if ( prev->type != CT_VSEMICOLON
+ && prev->type != CT_SEMICOLON)
+ {
+ pawn_add_vsemi_after(prev);
+ }
+ break;
+ }
+ prev = pc;
+ }
+ return(pc);
+}
+
+
+void pawn_add_virtual_semicolons(void)
+{
+ LOG_FUNC_ENTRY();
+
+ // Add Pawn virtual semicolons
+ if (language_is_set(LANG_PAWN))
+ {
+ chunk_t *prev = nullptr;
+ chunk_t *pc = chunk_get_head();
+
+ while ((pc = chunk_get_next(pc)) != nullptr)
+ {
+ if ( !chunk_is_comment(pc)
+ && !chunk_is_newline(pc)
+ && pc->type != CT_VBRACE_CLOSE
+ && pc->type != CT_VBRACE_OPEN)
+ {
+ prev = pc;
+ }
+
+ if ( prev == nullptr
+ || ( pc->type != CT_NEWLINE
+ && pc->type != CT_BRACE_CLOSE
+ && pc->type != CT_VBRACE_CLOSE))
+ {
+ continue;
+ }
+
+ // we just hit a newline and we have a previous token
+ if ( !prev->flags.test(PCF_IN_PREPROC)
+ && !prev->flags.test_any(PCF_IN_ENUM | PCF_IN_STRUCT)
+ && prev->type != CT_VSEMICOLON
+ && prev->type != CT_SEMICOLON
+ && !pawn_continued(prev, prev->brace_level))
+ {
+ pawn_add_vsemi_after(prev);
+ prev = nullptr;
+ }
+ }
+ }
+}
+
+
+static chunk_t *pawn_mark_function0(chunk_t *start, chunk_t *fcn)
+{
+ LOG_FUNC_ENTRY();
+
+ // handle prototypes
+ if (start == fcn)
+ {
+ chunk_t *last = chunk_get_next_type(fcn, CT_PAREN_CLOSE, fcn->level);
+ last = chunk_get_next(last);
+
+ if (chunk_is_token(last, CT_SEMICOLON))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' proto due to semicolon\n",
+ __func__, fcn->orig_line, fcn->text());
+ set_chunk_type(fcn, CT_FUNC_PROTO);
+ return(last);
+ }
+ }
+ else
+ {
+ if ( chunk_is_token(start, CT_FORWARD)
+ || chunk_is_token(start, CT_NATIVE))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' [%s] proto due to %s\n",
+ __func__, fcn->orig_line, fcn->text(),
+ get_token_name(fcn->type),
+ get_token_name(start->type));
+ set_chunk_type(fcn, CT_FUNC_PROTO);
+ return(chunk_get_next_nc(fcn));
+ }
+ }
+ // Not a prototype, so it must be a function def
+ return(pawn_process_func_def(fcn));
+}
+
+
+static chunk_t *pawn_process_func_def(chunk_t *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ // We are on a function definition
+ set_chunk_type(pc, CT_FUNC_DEF);
+
+ LOG_FMT(LPFUNC, "%s: %zu:%zu %s\n",
+ __func__, pc->orig_line, pc->orig_col, pc->text());
+
+ /*
+ * If we don't have a brace open right after the close fparen, then
+ * we need to add virtual braces around the function body.
+ */
+ chunk_t *clp = chunk_get_next_str(pc, ")", 1, 0);
+ chunk_t *last = chunk_get_next_ncnnl(clp);
+
+ if (last != nullptr)
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] last is '%s' [%s]\n",
+ __func__, last->orig_line, last->text(), get_token_name(last->type));
+ }
+
+ // See if there is a state clause after the function
+ if ( last != nullptr
+ && chunk_is_str(last, "<", 1))
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' has state angle open %s\n",
+ __func__, pc->orig_line, pc->text(), get_token_name(last->type));
+
+ set_chunk_type(last, CT_ANGLE_OPEN);
+ set_chunk_parent(last, CT_FUNC_DEF);
+
+ while ( ((last = chunk_get_next(last)) != nullptr)
+ && !chunk_is_str(last, ">", 1))
+ {
+ // do nothing just search, TODO: use search_chunk
+ }
+
+ if (last != nullptr)
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' has state angle close %s\n",
+ __func__, pc->orig_line, pc->text(), get_token_name(last->type));
+ set_chunk_type(last, CT_ANGLE_CLOSE);
+ set_chunk_parent(last, CT_FUNC_DEF);
+ }
+ last = chunk_get_next_ncnnl(last);
+ }
+
+ if (last == nullptr)
+ {
+ return(last);
+ }
+
+ if (chunk_is_token(last, CT_BRACE_OPEN))
+ {
+ set_chunk_parent(last, CT_FUNC_DEF);
+ last = chunk_get_next_type(last, CT_BRACE_CLOSE, last->level);
+
+ if (last != nullptr)
+ {
+ set_chunk_parent(last, CT_FUNC_DEF);
+ }
+ }
+ else
+ {
+ LOG_FMT(LPFUNC, "%s: %zu] '%s' fdef: expected brace open: %s\n",
+ __func__, pc->orig_line, pc->text(), get_token_name(last->type));
+
+ // do not insert a vbrace before a preproc
+ if (last->flags.test(PCF_IN_PREPROC))
+ {
+ return(last);
+ }
+ chunk_t chunk = *last;
+ chunk.str.clear();
+ set_chunk_type(&chunk, CT_VBRACE_OPEN);
+ set_chunk_parent(&chunk, CT_FUNC_DEF);
+
+ chunk_t *prev = chunk_add_before(&chunk, last);
+ last = prev;
+
+ // find the next newline at level 0
+ prev = chunk_get_next_ncnnl(prev);
+
+ do
+ {
+ LOG_FMT(LPFUNC, "%s:%zu] check %s, level %zu\n",
+ __func__, prev->orig_line, get_token_name(prev->type), prev->level);
+
+ if ( chunk_is_token(prev, CT_NEWLINE)
+ && prev->level == 0)
+ {
+ chunk_t *next = chunk_get_next_ncnnl(prev);
+
+ if ( next != nullptr
+ && next->type != CT_ELSE
+ && next->type != CT_WHILE_OF_DO)
+ {
+ break;
+ }
+ }
+ prev->level++;
+ prev->brace_level++;
+ last = prev;
+ } while ((prev = chunk_get_next(prev)) != nullptr);
+
+ if (last != nullptr)
+ {
+ LOG_FMT(LPFUNC, "%s:%zu] ended on %s, level %zu\n",
+ __func__, last->orig_line, get_token_name(last->type), last->level);
+ }
+ chunk = *last;
+ chunk.str.clear();
+ set_chunk_type(&chunk, CT_VBRACE_CLOSE);
+ set_chunk_parent(&chunk, CT_FUNC_DEF);
+ chunk.column += last->len();
+ chunk.level = 0;
+ chunk.brace_level = 0;
+ last = chunk_add_after(&chunk, last);
+ }
+ return(last);
+} // pawn_process_func_def
+
+
+chunk_t *pawn_check_vsemicolon(chunk_t *pc)
+{
+ LOG_FUNC_ENTRY();
+
+ // Grab the open VBrace
+ chunk_t *vb_open = chunk_get_prev_type(pc, CT_VBRACE_OPEN, -1);
+
+ /*
+ * Grab the item before the newline
+ * Don't do anything if:
+ * - the only thing previous is the V-Brace open
+ * - in a preprocessor
+ * - level > (vb_open->level + 1) -- ie, in () or []
+ * - it is something that needs a continuation
+ * + arith, assign, bool, comma, compare
+ */
+ chunk_t *prev = chunk_get_prev_ncnnl(pc);
+
+ if ( prev == nullptr
+ || prev == vb_open
+ || prev->flags.test(PCF_IN_PREPROC)
+ || pawn_continued(prev, vb_open->level + 1))
+ {
+ if (prev != nullptr)
+ {
+ LOG_FMT(LPVSEMI, "%s: no VSEMI on line %zu, prev='%s' [%s]\n",
+ __func__, prev->orig_line, prev->text(), get_token_name(prev->type));
+ }
+ return(pc);
+ }
+ return(pawn_add_vsemi_after(prev));
+}