summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/lang_pawn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/lang_pawn.cpp')
-rw-r--r--debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/lang_pawn.cpp520
1 files changed, 520 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/lang_pawn.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/lang_pawn.cpp
new file mode 100644
index 00000000..fe999a2a
--- /dev/null
+++ b/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/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));
+}