Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parsers,lisp: speed up token lookup #3741

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 110 additions & 95 deletions parsers/lisp.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,106 +149,121 @@ static int lisp_hint2kind (const vString *const hint)
return k;
}

/* TODO: implement this in hashtable. */
/* Lookup code produced by gperf version 3.1
*
* For example, run
*
* echo -e "(defconst\n(defmacro\n(defgroup\n(defalias" | gperf
*
* This is not included in the build process because gperf might not be
* available on all systems.
*/
static unsigned int hash_hint (const char *str, size_t len)
{
static unsigned char asso_values[] =
{
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 8, 41, 30,
41, 41, 0, 20, 41, 5, 41, 41, 41, 5,
41, 41, 41, 41, 41, 0, 15, 15, 0, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
41, 41, 41, 41, 41, 41
};
return len + asso_values[(unsigned char)str[4]];
}

static int elisp_hint2kind (const vString *const hint)
{
int k = eK_UNKNOWN;
int n;

/* 4 means strlen("(def"). */
#define EQN(X) strncmp(vStringValue (hint) + 4, &X[3], n) == 0
switch (vStringLength (hint) - 4)
#define MIN_WORD_LENGTH 6
#define MAX_WORD_LENGTH 31
#define MAX_HASH_VALUE 40

static const struct {
const char *str;
int kind;
} tokens[] = {
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "(defvar", eK_VARIABLE, },
{ "(defface", eK_FACE, },
{ "(defsubst", eK_SUBST, },
{ "(defsubst*", eK_SUBST, },
{ "", eK_UNKNOWN, },
{ "(defvaralias", eK_VARALIAS, },
{ "(defvar-local", eK_VARIABLE, },
{ "(defmacro", eK_MACRO, },
{ "(defmacro*", eK_MACRO, },
{ "(define-key", KIND_GHOST_INDEX, },
{ "(defalias", eK_ALIAS, },
{ "(define-error", eK_ERROR, },
{ "(define-inline", eK_INLINE, },
{ "", eK_UNKNOWN, },
{ "(defun", eK_FUNCTION, },
{ "(defun*", eK_FUNCTION, },
{ "(define-minor-mode", eK_MINOR_MODE, },
{ "(deftheme", eK_THEME, },
{ "(define-derived-mode", eK_DERIVED_MODE, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "(defgroup", eK_GROUP, },
{ "(define-global-minor-mode", eK_MINOR_MODE, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "(define-globalized-minor-mode", eK_MINOR_MODE, },
{ "", eK_UNKNOWN, },
{ "(define-obsolete-function-alias", eK_ALIAS, },
{ "", eK_UNKNOWN, },
{ "", eK_UNKNOWN, },
{ "(defconst", eK_CONST, },
{ "(defcustom", eK_CUSTOM, },
};

const char *const str = vStringValue (hint);
const size_t len = vStringLength (hint);
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
case 2:
n = 2;
if (EQN("defun"))
k = eK_FUNCTION;
break;
case 3:
n = 3;
if (EQN("defvar"))
k = eK_VARIABLE;
else if (EQN("defun*"))
k = eK_FUNCTION;
break;
case 4:
n = 4;
if (EQN("defface"))
k = eK_FACE;
case 5:
n = 5;
if (EQN("defconst"))
k = eK_CONST;
else if (EQN("defmacro"))
k = eK_MACRO;
else if (EQN("defalias"))
k = eK_ALIAS;
else if (EQN("defsubst"))
k = eK_SUBST;
else if (EQN("defgroup"))
k = eK_GROUP;
else if (EQN("deftheme"))
k = eK_THEME;
break;
case 6:
n = 6;
if (EQN("defcustom"))
k = eK_CUSTOM;
else if (EQN("defsubst*"))
k = eK_SUBST;
else if (EQN("defmacro*"))
k = eK_MACRO;
break;
case 7:
n = 7;
if (EQN("define-key"))
k = KIND_GHOST_INDEX;
break;
case 9:
n = 9;
if (EQN("defvar-local"))
k = eK_VARIABLE;
else if (EQN("define-error"))
k = eK_ERROR;
break;
case 8:
n = 8;
if (EQN("defvaralias"))
k = eK_VARALIAS;
break;
case 10:
n = 10;
if (EQN("define-inline"))
k = eK_INLINE;
break;
case 14:
n = 14;
if (EQN("define-minor-mode"))
k = eK_MINOR_MODE;
break;
case 16:
n = 16;
if (EQN("define-derived-mode"))
k = eK_DERIVED_MODE;
break;
case 21:
n = 21;
if (EQN("define-global-minor-mode"))
k = eK_MINOR_MODE;
break;
case 25:
n = 25;
if (EQN("define-globalized-minor-mode"))
k = eK_MINOR_MODE;
break;
case 27:
n = 27;
if (EQN("define-obsolete-function-alias"))
k = eK_ALIAS;
break;
const unsigned int key = hash_hint (str, len);
if (key <= MAX_HASH_VALUE)
{
const char *const s = tokens[key].str;
if (*str == *s && 0 == strncmp (str + 1, s + 1, len - 1))
return tokens[key].kind;
}
}
#undef EQN
return k;
return eK_UNKNOWN;

#undef MIN_WORD_LENGTH
#undef MAX_WORD_LENGTH
#undef MAX_HASH_VALUE

}

static void L_getit (vString *const name, const unsigned char *dbp,
Expand Down