1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /* Copyright (c) 1988 AT&T */
23 /* All Rights Reserved */
24
25
26 /*
27 * Copyright (c) 1999 by Sun Microsystems, Inc.
28 * All rights reserved.
29 */
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
32
33 /*
34 * cscope - interactive C symbol cross-reference
35 *
36 * keyword look-up routine for the C symbol scanner
37 */
38
39 #include "global.h"
40
41 /* keyword text for fast testing of keywords in the scanner */
42 char externtext[] = "extern";
43 char typedeftext[] = "typedef";
44
45 /*
46 * This keyword table is also used for keyword text compression. Keywords
47 * with an index less than the numeric value of a space are replaced with the
48 * control character corresponding to the index, so they cannot be moved
49 * without changing the database file version and adding compatibility code
50 * for old databases.
51 */
52 struct keystruct keyword[] = {
53 { "#define", ' ', MISC, NULL }, /* must be table entry 0 */
54 /* for old databases */
55 { "#include", ' ', MISC, NULL }, /* must be table entry 1 */
56 { "break", '\0', FLOW, NULL }, /* rarely in cross-reference */
57 { "case", ' ', FLOW, NULL },
58 { "char", ' ', DECL, NULL },
59 { "continue", '\0', FLOW, NULL }, /* rarely in cross-reference */
60 { "default", '\0', FLOW, NULL }, /* rarely in cross-reference */
61 { "#define", ' ', MISC, NULL }, /* must be table entry 7 */
62 { "double", ' ', DECL, NULL },
63 { "\t", '\0', MISC, NULL }, /* must be table entry 9 */
64 { "\n", '\0', MISC, NULL }, /* must be table entry 10 */
65 { "else", ' ', FLOW, NULL },
66 { "enum", ' ', DECL, NULL },
67 { externtext, ' ', DECL, NULL },
68 { "float", ' ', DECL, NULL },
69 { "for", '(', FLOW, NULL },
70 { "goto", ' ', FLOW, NULL },
71 { "if", '(', FLOW, NULL },
72 { "int", ' ', DECL, NULL },
73 { "long", ' ', DECL, NULL },
74 { "register", ' ', DECL, NULL },
75 { "return", '\0', FLOW, NULL },
76 { "short", ' ', DECL, NULL },
77 { "sizeof", '\0', MISC, NULL },
78 { "static", ' ', DECL, NULL },
79 { "struct", ' ', DECL, NULL },
80 { "switch", '(', FLOW, NULL },
81 { typedeftext, ' ', DECL, NULL },
82 { "union", ' ', DECL, NULL },
83 { "unsigned", ' ', DECL, NULL },
84 { "void", ' ', DECL, NULL },
85 { "while", '(', FLOW, NULL },
86
87 /* these keywords are not compressed */
88 { "auto", ' ', DECL, NULL },
89 { "do", ' ', FLOW, NULL },
90 { "fortran", ' ', DECL, NULL },
91 { "const", ' ', DECL, NULL },
92 { "signed", ' ', DECL, NULL },
93 { "volatile", ' ', DECL, NULL },
94 };
95
96 #define KEYWORDS (sizeof (keyword) / sizeof (struct keystruct))
97
98 #define HASHMOD (KEYWORDS * 2 + 1)
99
100 static struct keystruct *hashtab[HASHMOD]; /* pointer table */
101
102 /* put the keywords into the symbol table */
103
104 void
initsymtab(void)105 initsymtab(void)
106 {
107 int i, j;
108 struct keystruct *p;
109
110 for (i = 1; i < KEYWORDS; ++i) {
111 p = &keyword[i];
112 j = hash(p->text) % HASHMOD;
113 p->next = hashtab[j];
114 hashtab[j] = p;
115 }
116 }
117
118 /* see if this identifier is a keyword */
119
120 struct keystruct *
lookup(char * ident)121 lookup(char *ident)
122 {
123 struct keystruct *p;
124 int c;
125
126 /* look up the identifier in the keyword table */
127 for (p = hashtab[hash(ident) % HASHMOD]; p != NULL; p = p->next) {
128 if (strequal(ident, p->text)) {
129 if (compress == YES && (c = p - keyword) < ' ') {
130 ident[0] = c; /* compress the keyword */
131 }
132 return (p);
133 }
134 }
135 /* this is an identifier */
136 return (NULL);
137 }
138
139 /* form hash value for string */
140
141 int
hash(char * s)142 hash(char *s)
143 {
144 unsigned i;
145
146 for (i = 0; *s != '\0'; )
147 i += *s++; /* += is faster than <<= for cscope */
148 return (i);
149 }
150