indent(1): Use bsearch() for looking up type keywords.
Reference:
f3b8e6e57f
Submitted by: Piotr Stefaniak
Differential Revision: https://reviews.freebsd.org/D6966
This commit is contained in:
parent
b0316526b0
commit
a6bcfda487
@ -298,7 +298,7 @@ found:
|
||||
char *str = strdup(param_start);
|
||||
if (str == NULL)
|
||||
err(1, NULL);
|
||||
addkey(str, 4);
|
||||
add_typename(str);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -342,6 +342,7 @@ add_typedefs_from_file(const char *str)
|
||||
{
|
||||
FILE *file;
|
||||
char line[BUFSIZ];
|
||||
char *copy;
|
||||
|
||||
if ((file = fopen(str, "r")) == NULL) {
|
||||
fprintf(stderr, "indent: cannot open file %s\n", str);
|
||||
@ -349,8 +350,11 @@ add_typedefs_from_file(const char *str)
|
||||
}
|
||||
while ((fgets(line, BUFSIZ, file)) != NULL) {
|
||||
/* Remove trailing whitespace */
|
||||
*(line + strcspn(line, " \t\n\r")) = '\0';
|
||||
addkey(strdup(line), 4);
|
||||
line[strcspn(line, " \t\n\r")] = '\0';
|
||||
if ((copy = strdup(line)) == NULL) {
|
||||
err(1, NULL);
|
||||
}
|
||||
add_typename(copy);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ main(int argc, char **argv)
|
||||
tokenbuf = (char *) malloc(bufsize);
|
||||
if (tokenbuf == NULL)
|
||||
err(1, NULL);
|
||||
alloc_typenames();
|
||||
l_com = combuf + bufsize - 5;
|
||||
l_lab = labbuf + bufsize - 5;
|
||||
l_code = codebuf + bufsize - 5;
|
||||
|
@ -28,7 +28,8 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
|
||||
void addkey(char *, int);
|
||||
void add_typename(const char *);
|
||||
void alloc_typenames(void);
|
||||
int compute_code_target(void);
|
||||
int compute_label_target(void);
|
||||
int count_spaces(int, char *);
|
||||
|
@ -64,42 +64,49 @@ struct templ {
|
||||
int rwcode;
|
||||
};
|
||||
|
||||
struct templ specials[16384] =
|
||||
/*
|
||||
* This table has to be sorted alphabetically, because it'll be used in binary
|
||||
* search. For the same reason, string must be the first thing in struct templ.
|
||||
*/
|
||||
struct templ specials[] =
|
||||
{
|
||||
{"switch", 7},
|
||||
{"case", 8},
|
||||
{"break", 9},
|
||||
{"struct", 3},
|
||||
{"union", 3},
|
||||
{"enum", 3},
|
||||
{"default", 8},
|
||||
{"int", 4},
|
||||
{"case", 8},
|
||||
{"char", 4},
|
||||
{"float", 4},
|
||||
{"double", 4},
|
||||
{"long", 4},
|
||||
{"short", 4},
|
||||
{"typedef", 4},
|
||||
{"unsigned", 4},
|
||||
{"register", 4},
|
||||
{"static", 4},
|
||||
{"global", 4},
|
||||
{"extern", 4},
|
||||
{"void", 4},
|
||||
{"const", 4},
|
||||
{"volatile", 4},
|
||||
{"goto", 9},
|
||||
{"return", 9},
|
||||
{"if", 5},
|
||||
{"while", 5},
|
||||
{"for", 5},
|
||||
{"else", 6},
|
||||
{"default", 8},
|
||||
{"do", 6},
|
||||
{"sizeof", 2},
|
||||
{"double", 4},
|
||||
{"else", 6},
|
||||
{"enum", 3},
|
||||
{"extern", 4},
|
||||
{"float", 4},
|
||||
{"for", 5},
|
||||
{"global", 4},
|
||||
{"goto", 9},
|
||||
{"if", 5},
|
||||
{"int", 4},
|
||||
{"long", 4},
|
||||
{"offsetof", 1},
|
||||
{0, 0}
|
||||
{"register", 4},
|
||||
{"return", 9},
|
||||
{"short", 4},
|
||||
{"sizeof", 2},
|
||||
{"static", 4},
|
||||
{"struct", 3},
|
||||
{"switch", 7},
|
||||
{"typedef", 4},
|
||||
{"union", 3},
|
||||
{"unsigned", 4},
|
||||
{"void", 4},
|
||||
{"volatile", 4},
|
||||
{"while", 5}
|
||||
};
|
||||
|
||||
const char **typenames;
|
||||
int typename_count;
|
||||
int typename_top = -1;
|
||||
|
||||
char chartype[128] =
|
||||
{ /* this is used to facilitate the decision of
|
||||
* what type (alphanumeric, operator) each
|
||||
@ -122,6 +129,12 @@ char chartype[128] =
|
||||
1, 1, 1, 0, 3, 0, 3, 0
|
||||
};
|
||||
|
||||
static int
|
||||
strcmp_type(const void *e1, const void *e2)
|
||||
{
|
||||
return (strcmp(e1, *(const char * const *)e2));
|
||||
}
|
||||
|
||||
int
|
||||
lexi(void)
|
||||
{
|
||||
@ -150,9 +163,6 @@ lexi(void)
|
||||
/*
|
||||
* we have a character or number
|
||||
*/
|
||||
const char *j; /* used for searching thru list of
|
||||
*
|
||||
* reserved words */
|
||||
struct templ *p;
|
||||
|
||||
if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) {
|
||||
@ -247,37 +257,24 @@ lexi(void)
|
||||
last_code = ident; /* Remember that this is the code we will
|
||||
* return */
|
||||
|
||||
if (auto_typedefs) {
|
||||
const char *q = s_token;
|
||||
size_t q_len = strlen(q);
|
||||
/* Check if we have an "_t" in the end */
|
||||
if (q_len > 2 &&
|
||||
(strcmp(q + q_len - 2, "_t") == 0)) {
|
||||
ps.keyword = 4; /* a type name */
|
||||
ps.last_u_d = true;
|
||||
goto found_auto_typedef;
|
||||
}
|
||||
}
|
||||
p = bsearch(s_token,
|
||||
specials,
|
||||
sizeof(specials) / sizeof(specials[0]),
|
||||
sizeof(specials[0]),
|
||||
strcmp_type);
|
||||
if (p == NULL) { /* not a special keyword... */
|
||||
char *u;
|
||||
|
||||
/*
|
||||
* This loop will check if the token is a keyword.
|
||||
*/
|
||||
for (p = specials; (j = p->rwd) != NULL; p++) {
|
||||
const char *q = s_token; /* point at scanned token */
|
||||
if (*j++ != *q++ || *j++ != *q++)
|
||||
continue; /* This test depends on the fact that
|
||||
* identifiers are always at least 1 character
|
||||
* long (ie. the first two bytes of the
|
||||
* identifier are always meaningful) */
|
||||
if (q[-1] == 0)
|
||||
break; /* If its a one-character identifier */
|
||||
while (*q++ == *j)
|
||||
if (*j++ == 0)
|
||||
goto found_keyword; /* I wish that C had a multi-level
|
||||
* break... */
|
||||
}
|
||||
if (p->rwd) { /* we have a keyword */
|
||||
found_keyword:
|
||||
/* ... so maybe a type_t or a typedef */
|
||||
if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
|
||||
strcmp(u, "_t") == 0) || (typename_top >= 0 &&
|
||||
bsearch(s_token, typenames, typename_top + 1,
|
||||
sizeof(typenames[0]), strcmp_type))) {
|
||||
ps.keyword = 4; /* a type name */
|
||||
ps.last_u_d = true;
|
||||
goto found_typename;
|
||||
}
|
||||
} else { /* we have a keyword */
|
||||
ps.keyword = p->rwcode;
|
||||
ps.last_u_d = true;
|
||||
switch (p->rwcode) {
|
||||
@ -295,7 +292,7 @@ lexi(void)
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 4: /* one of the declaration keywords */
|
||||
found_auto_typedef:
|
||||
found_typename:
|
||||
if (ps.p_l_follow) {
|
||||
/* inside parens: cast, param list, offsetof or sizeof */
|
||||
ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.not_cast_mask;
|
||||
@ -583,24 +580,43 @@ stop_lit:
|
||||
return (code);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the given keyword to the keyword table, using val as the keyword type
|
||||
*/
|
||||
void
|
||||
addkey(char *key, int val)
|
||||
alloc_typenames(void)
|
||||
{
|
||||
struct templ *p = specials;
|
||||
while (p->rwd)
|
||||
if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
|
||||
return;
|
||||
else
|
||||
p++;
|
||||
if (p >= specials + sizeof(specials) / sizeof(specials[0])) {
|
||||
fprintf(stderr, "indent: typedef table overflow\n");
|
||||
exit(1);
|
||||
}
|
||||
p->rwd = key;
|
||||
p->rwcode = val;
|
||||
p[1].rwd = NULL;
|
||||
p[1].rwcode = 0;
|
||||
|
||||
typenames = (const char **)malloc(sizeof(typenames[0]) *
|
||||
(typename_count = 16));
|
||||
if (typenames == NULL)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
add_typename(const char *key)
|
||||
{
|
||||
int comparison;
|
||||
|
||||
if (typename_top + 1 >= typename_count) {
|
||||
typenames = realloc((void *)typenames,
|
||||
sizeof(typenames[0]) * (typename_count *= 2));
|
||||
if (typenames == NULL)
|
||||
err(1, NULL);
|
||||
}
|
||||
if (typename_top == -1)
|
||||
typenames[++typename_top] = key;
|
||||
else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) {
|
||||
/* take advantage of sorted input */
|
||||
if (comparison != 0) /* remove duplicates */
|
||||
typenames[++typename_top] = key;
|
||||
}
|
||||
else {
|
||||
int p;
|
||||
|
||||
for (p = 0; (comparison = strcmp(key, typenames[p])) >= 0; p++)
|
||||
/* find place for the new key */;
|
||||
if (comparison == 0) /* remove duplicates */
|
||||
return;
|
||||
memmove(&typenames[p + 1], &typenames[p],
|
||||
sizeof(typenames[0]) * (++typename_top - p));
|
||||
typenames[p] = key;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user