root/usr/src/tools/cscope-fast/lookup.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*      Copyright (c) 1988 AT&T */
/*        All Rights Reserved   */


/*
 * Copyright (c) 1999 by Sun Microsystems, Inc.
 * All rights reserved.
 */

/*
 *      cscope - interactive C symbol cross-reference
 *
 *      keyword look-up routine for the C symbol scanner
 */

#include "global.h"

/* keyword text for fast testing of keywords in the scanner */
char    externtext[] = "extern";
char    typedeftext[] = "typedef";

/*
 * This keyword table is also used for keyword text compression.  Keywords
 * with an index less than the numeric value of a space are replaced with the
 * control character corresponding to the index, so they cannot be moved
 * without changing the database file version and adding compatibility code
 * for old databases.
 */
struct  keystruct keyword[] = {
        { "#define",    ' ',    MISC,   NULL }, /* must be table entry 0 */
                                                /* for old databases */
        { "#include",   ' ',    MISC,   NULL }, /* must be table entry 1 */
        { "break",      '\0',   FLOW,   NULL }, /* rarely in cross-reference */
        { "case",       ' ',    FLOW,   NULL },
        { "char",       ' ',    DECL,   NULL },
        { "continue",   '\0',   FLOW,   NULL }, /* rarely in cross-reference */
        { "default",    '\0',   FLOW,   NULL }, /* rarely in cross-reference */
        { "#define",    ' ',    MISC,   NULL }, /* must be table entry 7 */
        { "double",     ' ',    DECL,   NULL },
        { "\t",         '\0',   MISC,   NULL }, /* must be table entry 9 */
        { "\n",         '\0',   MISC,   NULL }, /* must be table entry 10 */
        { "else",       ' ',    FLOW,   NULL },
        { "enum",       ' ',    DECL,   NULL },
        { externtext,   ' ',    DECL,   NULL },
        { "float",      ' ',    DECL,   NULL },
        { "for",        '(',    FLOW,   NULL },
        { "goto",       ' ',    FLOW,   NULL },
        { "if",         '(',    FLOW,   NULL },
        { "int",        ' ',    DECL,   NULL },
        { "long",       ' ',    DECL,   NULL },
        { "register",   ' ',    DECL,   NULL },
        { "return",     '\0',   FLOW,   NULL },
        { "short",      ' ',    DECL,   NULL },
        { "sizeof",     '\0',   MISC,   NULL },
        { "static",     ' ',    DECL,   NULL },
        { "struct",     ' ',    DECL,   NULL },
        { "switch",     '(',    FLOW,   NULL },
        { typedeftext,  ' ',    DECL,   NULL },
        { "union",      ' ',    DECL,   NULL },
        { "unsigned",   ' ',    DECL,   NULL },
        { "void",       ' ',    DECL,   NULL },
        { "while",      '(',    FLOW,   NULL },

        /* these keywords are not compressed */
        { "auto",       ' ',    DECL,   NULL },
        { "do",         ' ',    FLOW,   NULL },
        { "fortran",    ' ',    DECL,   NULL },
        { "const",      ' ',    DECL,   NULL },
        { "signed",     ' ',    DECL,   NULL },
        { "volatile",   ' ',    DECL,   NULL },
};

#define KEYWORDS        (sizeof (keyword) / sizeof (struct keystruct))

#define HASHMOD (KEYWORDS * 2 + 1)

static  struct  keystruct *hashtab[HASHMOD]; /* pointer table */

/* put the keywords into the symbol table */

void
initsymtab(void)
{
        int     i, j;
        struct  keystruct *p;

        for (i = 1; i < KEYWORDS; ++i) {
                p = &keyword[i];
                j = hash(p->text) % HASHMOD;
                p->next = hashtab[j];
                hashtab[j] = p;
        }
}

/* see if this identifier is a keyword */

struct keystruct *
lookup(char *ident)
{
        struct  keystruct *p;
        int     c;

        /* look up the identifier in the keyword table */
        for (p = hashtab[hash(ident) % HASHMOD]; p != NULL; p = p->next) {
                if (strequal(ident, p->text)) {
                        if (compress == YES && (c = p - keyword) < ' ') {
                                ident[0] = c;   /* compress the keyword */
                        }
                        return (p);
                }
        }
        /* this is an identifier */
        return (NULL);
}

/* form hash value for string */

int
hash(char *s)
{
        unsigned i;

        for (i = 0; *s != '\0'; )
                i += *s++;      /* += is faster than <<= for cscope */
        return (i);
}