blob: f4c6f03c1c9b443d3b078a6f36fc3c41d676a09b [file] [log] [blame]
/**
* @file keywords.cpp
* Manages the table of keywords.
*
* @author Ben Gardner
* @license GPL v2+
*/
#include "uncrustify_types.h"
#include "prototypes.h"
#include "char_table.h"
#include "args.h"
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include <map>
#include "unc_ctype.h"
using namespace std;
/* Dynamic keyword map */
typedef map<string, c_token_t> dkwmap;
static dkwmap dkwm;
/**
* interesting static keywords - keep sorted.
* Table should include the Name, Type, and Language flags.
*/
static const chunk_tag_t keywords[] =
{
{ "@catch", CT_CATCH, LANG_OC | LANG_CPP | LANG_C },
{ "@dynamic", CT_OC_DYNAMIC, LANG_OC | LANG_CPP | LANG_C },
{ "@end", CT_OC_END, LANG_OC | LANG_CPP | LANG_C },
{ "@finally", CT_FINALLY, LANG_OC | LANG_CPP | LANG_C },
{ "@implementation", CT_OC_IMPL, LANG_OC | LANG_CPP | LANG_C },
{ "@interface", CT_OC_INTF, LANG_OC | LANG_CPP | LANG_C },
{ "@interface", CT_CLASS, LANG_JAVA },
{ "@private", CT_PRIVATE, LANG_OC | LANG_CPP | LANG_C },
{ "@property", CT_OC_PROPERTY, LANG_OC | LANG_CPP | LANG_C },
{ "@protocol", CT_OC_PROTOCOL, LANG_OC | LANG_CPP | LANG_C },
{ "@selector", CT_OC_SEL, LANG_OC | LANG_CPP | LANG_C },
{ "@synthesize", CT_OC_DYNAMIC, LANG_OC | LANG_CPP | LANG_C },
{ "@throw", CT_THROW, LANG_OC },
{ "@try", CT_TRY, LANG_OC | LANG_CPP | LANG_C },
{ "NS_ENUM", CT_ENUM, LANG_OC },
{ "NS_OPTIONS", CT_ENUM, LANG_OC },
{ "_Bool", CT_TYPE, LANG_CPP },
{ "_Complex", CT_TYPE, LANG_CPP },
{ "_Imaginary", CT_TYPE, LANG_CPP },
{ "__attribute__", CT_ATTRIBUTE, LANG_C | LANG_CPP },
{ "__block", CT_QUALIFIER, LANG_OC },
{ "__const__", CT_QUALIFIER, LANG_C | LANG_CPP },
{ "__except", CT_CATCH, LANG_C | LANG_CPP },
{ "__finally", CT_FINALLY, LANG_C | LANG_CPP },
{ "__inline__", CT_QUALIFIER, LANG_C | LANG_CPP },
{ "__restrict", CT_QUALIFIER, LANG_C | LANG_CPP },
{ "__signed__", CT_TYPE, 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_SIZEOF, LANG_C | LANG_CPP },
{ "__volatile__", CT_QUALIFIER, LANG_C | LANG_CPP },
{ "abstract", CT_QUALIFIER, LANG_CS | LANG_D | LANG_JAVA | LANG_VALA | LANG_ECMA },
{ "add", CT_GETSET, LANG_CS },
{ "alias", CT_QUALIFIER, LANG_D },
{ "align", CT_ALIGN, LANG_D },
{ "alignof", CT_SIZEOF, LANG_C | LANG_CPP },
{ "and", CT_SBOOL, LANG_C | LANG_CPP | FLAG_PP },
{ "and_eq", CT_SASSIGN, LANG_C | LANG_CPP },
{ "as", CT_AS, LANG_CS },
{ "asm", CT_ASM, LANG_C | LANG_CPP | LANG_D },
{ "assert", CT_ASSERT, LANG_JAVA },
{ "assert", CT_FUNCTION, LANG_D | LANG_PAWN }, // PAWN
{ "assert", CT_PP_ASSERT, LANG_PAWN | FLAG_PP }, // PAWN
{ "auto", CT_QUALIFIER, 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_CPP | LANG_CS | LANG_VALA },
{ "boolean", CT_TYPE, LANG_JAVA | LANG_ECMA },
{ "break", CT_BREAK, LANG_ALL }, // PAWN
{ "byte", CT_TYPE, LANG_CS | LANG_D | LANG_JAVA | LANG_ECMA },
{ "callback", CT_QUALIFIER, LANG_VALA },
{ "case", CT_CASE, LANG_ALL }, // PAWN
{ "cast", CT_D_CAST, LANG_D },
{ "catch", CT_CATCH, LANG_CPP | LANG_CS | 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 }, // 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_C | LANG_CPP },
{ "const", CT_QUALIFIER, LANG_ALL }, // PAWN
{ "const_cast", CT_TYPE_CAST, LANG_CPP },
{ "constexpr", CT_QUALIFIER, LANG_CPP },
{ "construct", CT_CONSTRUCT, LANG_VALA },
{ "continue", CT_CONTINUE, LANG_ALL }, // PAWN
{ "creal", CT_TYPE, LANG_D },
{ "dchar", CT_TYPE, LANG_D },
{ "debug", CT_DEBUG, LANG_D },
{ "debugger", CT_DEBUGGER, LANG_ECMA },
{ "decltype", CT_SIZEOF, LANG_CPP },
{ "default", CT_DEFAULT, LANG_ALL }, // PAWN
{ "define", CT_PP_DEFINE, LANG_ALL | FLAG_PP }, // PAWN
{ "defined", CT_DEFINED, LANG_PAWN }, // PAWN
{ "defined", CT_PP_DEFINED, LANG_ALLC | FLAG_PP },
{ "delegate", CT_DELEGATE, LANG_CS | LANG_D },
{ "delete", CT_DELETE, LANG_CPP | LANG_D | LANG_ECMA },
{ "deprecated", CT_QUALIFIER, LANG_D },
{ "do", CT_DO, LANG_ALL }, // PAWN
{ "double", CT_TYPE, LANG_ALLC },
{ "dynamic_cast", CT_TYPE_CAST, LANG_CPP },
{ "elif", CT_PP_ELSE, LANG_ALLC | FLAG_PP },
{ "else", CT_ELSE, LANG_ALL }, // PAWN
{ "else", CT_PP_ELSE, LANG_ALL | FLAG_PP }, // PAWN
{ "elseif", CT_PP_ELSE, LANG_PAWN | FLAG_PP }, // PAWN
{ "emit", CT_PP_EMIT, LANG_PAWN | FLAG_PP }, // PAWN
{ "endif", CT_PP_ENDIF, LANG_ALL | FLAG_PP }, // PAWN
{ "endinput", CT_PP_ENDINPUT, LANG_PAWN | FLAG_PP }, // PAWN
{ "endregion", CT_PP_ENDREGION, LANG_ALL | FLAG_PP },
{ "endscript", CT_PP_ENDINPUT, LANG_PAWN | FLAG_PP }, // PAWN
{ "enum", CT_ENUM, LANG_ALL }, // PAWN
{ "error", CT_PP_ERROR, LANG_PAWN | FLAG_PP }, // PAWN
{ "event", CT_TYPE, LANG_CS },
{ "exit", CT_FUNCTION, LANG_PAWN }, // PAWN
{ "explicit", CT_TYPE, LANG_C | LANG_CPP | LANG_CS },
{ "export", CT_EXPORT, LANG_C | LANG_CPP | LANG_D | LANG_ECMA },
{ "extends", CT_QUALIFIER, LANG_JAVA | LANG_ECMA },
{ "extern", CT_EXTERN, LANG_C | LANG_CPP | LANG_CS | LANG_D | LANG_VALA },
{ "false", CT_WORD, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_VALA },
{ "file", CT_PP_FILE, LANG_PAWN | FLAG_PP }, // PAWN
{ "final", CT_QUALIFIER, LANG_CPP | LANG_D | LANG_ECMA },
{ "finally", CT_FINALLY, LANG_D | LANG_CS | LANG_ECMA | LANG_JAVA },
{ "flags", CT_TYPE, LANG_VALA },
{ "float", CT_TYPE, LANG_ALLC },
{ "for", CT_FOR, LANG_ALL }, // PAWN
{ "foreach", CT_FOR, LANG_CS | LANG_D | LANG_VALA },
{ "foreach_reverse", CT_FOR, LANG_D },
{ "forward", CT_FORWARD, LANG_PAWN }, // 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 }, // PAWN
{ "idouble", CT_TYPE, LANG_D },
{ "if", CT_IF, LANG_ALL }, // PAWN
{ "if", CT_PP_IF, LANG_ALL | FLAG_PP }, // PAWN
{ "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 }, // fudged to get indenting
{ "import", CT_PP_INCLUDE, LANG_OC | FLAG_PP }, // ObjectiveC version of include
{ "in", CT_IN, LANG_D | LANG_CS | LANG_VALA | LANG_ECMA | LANG_OC },
{ "include", CT_PP_INCLUDE, LANG_C | LANG_CPP | LANG_PAWN | FLAG_PP }, // PAWN
{ "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_C | LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_VALA | LANG_ECMA },
{ "internal", CT_QUALIFIER, LANG_CS },
{ "invariant", CT_INVARIANT, LANG_D },
{ "ireal", CT_TYPE, LANG_D },
{ "is", CT_SCOMPARE, LANG_D | LANG_CS | LANG_VALA },
{ "lazy", CT_LAZY, LANG_D },
{ "line", CT_PP_LINE, LANG_PAWN | FLAG_PP }, // PAWN
{ "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_C | LANG_CPP },
{ "namespace", CT_NAMESPACE, LANG_CPP | LANG_CS | LANG_VALA },
{ "native", CT_NATIVE, LANG_PAWN }, // 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 }, // PAWN
{ "not", CT_SARITH, LANG_C | LANG_CPP },
{ "not_eq", CT_SCOMPARE, LANG_C | LANG_CPP },
{ "null", CT_TYPE, LANG_CS | LANG_D | LANG_JAVA | LANG_VALA },
{ "object", CT_TYPE, LANG_CS },
{ "operator", CT_OPERATOR, LANG_CPP | LANG_CS | LANG_PAWN }, // PAWN
{ "or", CT_SBOOL, LANG_C | LANG_CPP | FLAG_PP },
{ "or_eq", CT_SASSIGN, LANG_C | LANG_CPP },
{ "out", CT_QUALIFIER, LANG_CS | LANG_D | LANG_VALA },
{ "override", CT_QUALIFIER, LANG_CS | LANG_D | LANG_VALA },
{ "package", CT_PRIVATE, LANG_D },
{ "package", CT_PACKAGE, LANG_ECMA | LANG_JAVA },
{ "params", CT_TYPE, LANG_CS },
{ "pragma", CT_PP_PRAGMA, LANG_ALL | FLAG_PP }, // PAWN
{ "private", CT_PRIVATE, LANG_ALLC }, // not C
{ "property", CT_PP_PROPERTY, LANG_CS | FLAG_PP },
{ "protected", CT_PRIVATE, LANG_ALLC }, // not C
{ "public", CT_PRIVATE, LANG_ALL }, // PAWN // not C
{ "readonly", CT_QUALIFIER, LANG_CS },
{ "real", CT_TYPE, LANG_D },
{ "ref", CT_QUALIFIER, LANG_CS | LANG_VALA },
{ "region", CT_PP_REGION, LANG_ALL | FLAG_PP },
{ "register", CT_QUALIFIER, LANG_C | LANG_CPP },
{ "reinterpret_cast", CT_TYPE_CAST, LANG_C | LANG_CPP },
{ "remove", CT_GETSET, LANG_CS },
{ "restrict", CT_QUALIFIER, LANG_C | LANG_CPP },
{ "return", CT_RETURN, LANG_ALL }, // PAWN
{ "sbyte", CT_TYPE, LANG_CS },
{ "scope", CT_D_SCOPE, LANG_D },
{ "sealed", CT_QUALIFIER, LANG_CS },
{ "section", CT_PP_SECTION, LANG_PAWN | FLAG_PP }, // PAWN
{ "set", CT_GETSET, LANG_CS | LANG_VALA },
{ "short", CT_TYPE, LANG_ALLC },
{ "signal", CT_PRIVATE, LANG_VALA },
{ "signals", CT_PRIVATE, LANG_CPP },
{ "signed", CT_TYPE, LANG_C | LANG_CPP },
{ "sizeof", CT_SIZEOF, LANG_C | LANG_CPP | LANG_CS | LANG_PAWN }, // PAWN
{ "sleep", CT_SIZEOF, LANG_PAWN }, // PAWN
{ "stackalloc", CT_NEW, LANG_CS },
{ "state", CT_STATE, LANG_PAWN }, // PAWN
{ "static", CT_QUALIFIER, LANG_ALL }, // PAWN
{ "static_cast", CT_TYPE_CAST, LANG_CPP },
{ "stock", CT_STOCK, LANG_PAWN }, // PAWN
{ "strictfp", CT_QUALIFIER, LANG_JAVA },
{ "string", CT_TYPE, LANG_CS },
{ "struct", CT_STRUCT, LANG_C | LANG_CPP | LANG_CS | LANG_D | LANG_VALA },
{ "super", CT_SUPER, LANG_D | LANG_JAVA | LANG_ECMA },
{ "switch", CT_SWITCH, LANG_ALL }, // PAWN
{ "synchronized", CT_QUALIFIER, LANG_D | LANG_JAVA | LANG_ECMA },
{ "tagof", CT_TAGOF, LANG_PAWN }, // 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_D | LANG_JAVA | LANG_ECMA },
{ "throws", CT_QUALIFIER, LANG_JAVA | LANG_ECMA },
{ "transient", CT_QUALIFIER, LANG_JAVA | LANG_ECMA },
{ "true", CT_WORD, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_VALA },
{ "try", CT_TRY, LANG_CPP | LANG_CS | LANG_D | LANG_JAVA | LANG_ECMA },
{ "tryinclude", CT_PP_INCLUDE, LANG_PAWN | FLAG_PP }, // PAWN
{ "typedef", CT_TYPEDEF, LANG_C | LANG_CPP | LANG_D | LANG_OC },
{ "typeid", CT_SIZEOF, LANG_C | LANG_CPP | LANG_D },
{ "typename", CT_TYPENAME, LANG_CPP },
{ "typeof", CT_SIZEOF, LANG_C | LANG_CPP | LANG_CS | LANG_D | LANG_VALA | LANG_ECMA },
{ "ubyte", CT_TYPE, LANG_D },
{ "ucent", CT_TYPE, LANG_D },
{ "uint", CT_TYPE, LANG_CS | LANG_D },
{ "ulong", CT_TYPE, LANG_CS | LANG_D },
{ "unchecked", CT_QUALIFIER, LANG_CS },
{ "undef", CT_PP_UNDEF, LANG_ALL | FLAG_PP }, // PAWN
{ "union", CT_UNION, LANG_C | LANG_CPP | LANG_D },
{ "unittest", CT_UNITTEST, LANG_D },
{ "unsafe", CT_UNSAFE, LANG_CS },
{ "unsigned", CT_TYPE, LANG_C | LANG_CPP },
{ "ushort", CT_TYPE, LANG_CS | LANG_D },
{ "using", CT_USING, LANG_CPP | LANG_CS | LANG_VALA },
{ "var", CT_TYPE, LANG_VALA | LANG_ECMA },
{ "version", CT_D_VERSION, LANG_D },
{ "virtual", CT_QUALIFIER, LANG_CPP | LANG_CS | LANG_VALA },
{ "void", CT_TYPE, LANG_ALLC },
{ "volatile", CT_QUALIFIER, LANG_C | LANG_CPP | LANG_CS | LANG_JAVA | LANG_ECMA },
{ "volatile", CT_VOLATILE, LANG_D },
{ "wchar", CT_TYPE, LANG_D },
{ "wchar_t", CT_TYPE, LANG_C | LANG_CPP },
{ "weak", CT_QUALIFIER, LANG_VALA },
{ "while", CT_WHILE, LANG_ALL }, // PAWN
{ "with", CT_D_WITH, LANG_D | LANG_ECMA },
{ "xor", CT_SARITH, LANG_C | LANG_CPP },
{ "xor_eq", CT_SASSIGN, LANG_C | LANG_CPP },
};
void init_keywords()
{
}
/**
* Compares two chunk_tag_t entries using strcmp on the strings
*
* @param p1 The 'left' entry
* @param p2 The 'right' entry
*/
static int kw_compare(const void *p1, const void *p2)
{
const chunk_tag_t *t1 = (const chunk_tag_t *)p1;
const chunk_tag_t *t2 = (const chunk_tag_t *)p2;
return(strcmp(t1->tag, t2->tag));
}
bool keywords_are_sorted(void)
{
int idx;
bool retval = true;
for (idx = 1; idx < (int)ARRAY_SIZE(keywords); idx++)
{
if (kw_compare(&keywords[idx - 1], &keywords[idx]) > 0)
{
LOG_FMT(LERR, "%s: bad sort order at idx %d, words '%s' and '%s'\n",
__func__, idx - 1, keywords[idx - 1].tag, keywords[idx].tag);
retval = false;
}
}
return(retval);
}
/**
* 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 char *tag, c_token_t type)
{
string ss = tag;
/* See if the keyword has already been added */
dkwmap::iterator it = dkwm.find(ss);
if (it != dkwm.end())
{
LOG_FMT(LDYNKW, "%s: changed '%s' to %d\n", __func__, tag, type);
(*it).second = type;
return;
}
/* Insert the keyword */
dkwm.insert(dkwmap::value_type(ss, type));
LOG_FMT(LDYNKW, "%s: added '%s' as %d\n", __func__, tag, type);
}
/**
* Backs up to the first string match in keywords.
*/
static const chunk_tag_t *kw_static_first(const chunk_tag_t *tag)
{
const chunk_tag_t *prev = tag - 1;
while ((prev >= &keywords[0]) && (strcmp(prev->tag, tag->tag) == 0))
{
tag = prev;
prev--;
}
//fprintf(stderr, "first:%s -", tag->tag);
return(tag);
}
static const chunk_tag_t *kw_static_match(const chunk_tag_t *tag)
{
bool in_pp = ((cpd.in_preproc != CT_NONE) && (cpd.in_preproc != CT_PP_DEFINE));
bool pp_iter;
const chunk_tag_t *iter;
for (iter = kw_static_first(tag);
iter < &keywords[ARRAY_SIZE(keywords)];
iter++)
{
//fprintf(stderr, " check:%s", iter->tag);
pp_iter = (iter->lang_flags & FLAG_PP) != 0;
if ((strcmp(iter->tag, tag->tag) == 0) &&
((cpd.lang_flags & iter->lang_flags) != 0) &&
(in_pp == pp_iter))
{
//fprintf(stderr, " match:%s", iter->tag);
return(iter);
}
}
return(NULL);
}
/**
* 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
*/
c_token_t find_keyword_type(const char *word, int len)
{
string ss(word, len);
chunk_tag_t key;
const chunk_tag_t *p_ret;
if (len <= 0)
{
return(CT_NONE);
}
/* check the dynamic word list first */
dkwmap::iterator it = dkwm.find(ss);
if (it != dkwm.end())
{
return((*it).second);
}
key.tag = ss.c_str();
/* check the static word list */
p_ret = (const chunk_tag_t *)bsearch(&key, keywords, ARRAY_SIZE(keywords),
sizeof(keywords[0]), kw_compare);
if (p_ret != NULL)
{
p_ret = kw_static_match(p_ret);
}
return((p_ret != NULL) ? p_ret->type : CT_WORD);
}
/**
* Loads the dynamic keywords from a file
*
* @param filename The path to the file to load
* @return SUCCESS or FAILURE
*/
int load_keyword_file(const char *filename)
{
FILE *pf;
char buf[256];
char *ptr;
char *args[3];
int argc;
int line_no = 0;
pf = fopen(filename, "r");
if (pf == NULL)
{
LOG_FMT(LERR, "%s: fopen(%s) failed: %s (%d)\n",
__func__, filename, strerror(errno), errno);
cpd.error_count++;
return(FAILURE);
}
while (fgets(buf, sizeof(buf), pf) != NULL)
{
line_no++;
/* remove comments */
if ((ptr = strchr(buf, '#')) != NULL)
{
*ptr = 0;
}
argc = Args::SplitLine(buf, args, ARRAY_SIZE(args) - 1);
args[argc] = 0;
if (argc > 0)
{
if ((argc == 1) && CharTable::IsKw1(*args[0]))
{
add_keyword(args[0], CT_TYPE);
}
else
{
LOG_FMT(LWARN, "%s:%d Invalid line (starts with '%s')\n",
filename, line_no, args[0]);
cpd.error_count++;
}
}
}
fclose(pf);
return(SUCCESS);
}
void print_keywords(FILE *pfile)
{
for (dkwmap::iterator it = dkwm.begin(); it != dkwm.end(); ++it)
{
c_token_t tt = (*it).second;
if (tt == CT_TYPE)
{
fprintf(pfile, "type %*.s%s\n",
cpd.max_option_name_len - 4, " ", (*it).first.c_str());
}
else if (tt == CT_MACRO_OPEN)
{
fprintf(pfile, "macro-open %*.s%s\n",
cpd.max_option_name_len - 11, " ", (*it).first.c_str());
}
else if (tt == CT_MACRO_CLOSE)
{
fprintf(pfile, "macro-close %*.s%s\n",
cpd.max_option_name_len - 12, " ", (*it).first.c_str());
}
else if (tt == CT_MACRO_ELSE)
{
fprintf(pfile, "macro-else %*.s%s\n",
cpd.max_option_name_len - 11, " ", (*it).first.c_str());
}
else
{
const char *tn = get_token_name(tt);
fprintf(pfile, "set %s %*.s%s\n", tn,
int(cpd.max_option_name_len - (4 + strlen(tn))), " ", (*it).first.c_str());
}
}
}
void clear_keyword_file(void)
{
dkwm.clear();
}
/**
* Returns the pattern that the keyword needs based on the token
*/
pattern_class get_token_pattern_class(c_token_t tok)
{
switch (tok)
{
case CT_IF:
case CT_ELSEIF:
case CT_SWITCH:
case CT_FOR:
case CT_WHILE:
case CT_USING_STMT:
case CT_LOCK:
case CT_D_WITH:
case CT_D_VERSION_IF:
case CT_D_SCOPE_IF:
return(PATCLS_PBRACED);
case CT_ELSE:
return(PATCLS_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(PATCLS_BRACED);
case CT_CATCH:
case CT_D_VERSION:
case CT_DEBUG:
return(PATCLS_OPBRACED);
case CT_NAMESPACE:
return(PATCLS_VBRACED);
case CT_WHILE_OF_DO:
return(PATCLS_PAREN);
case CT_INVARIANT:
return(PATCLS_OPPAREN);
default:
return(PATCLS_NONE);
}
}