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);
|
char *str = strdup(param_start);
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
err(1, NULL);
|
err(1, NULL);
|
||||||
addkey(str, 4);
|
add_typename(str);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -342,6 +342,7 @@ add_typedefs_from_file(const char *str)
|
|||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
char line[BUFSIZ];
|
char line[BUFSIZ];
|
||||||
|
char *copy;
|
||||||
|
|
||||||
if ((file = fopen(str, "r")) == NULL) {
|
if ((file = fopen(str, "r")) == NULL) {
|
||||||
fprintf(stderr, "indent: cannot open file %s\n", str);
|
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) {
|
while ((fgets(line, BUFSIZ, file)) != NULL) {
|
||||||
/* Remove trailing whitespace */
|
/* Remove trailing whitespace */
|
||||||
*(line + strcspn(line, " \t\n\r")) = '\0';
|
line[strcspn(line, " \t\n\r")] = '\0';
|
||||||
addkey(strdup(line), 4);
|
if ((copy = strdup(line)) == NULL) {
|
||||||
|
err(1, NULL);
|
||||||
|
}
|
||||||
|
add_typename(copy);
|
||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,7 @@ main(int argc, char **argv)
|
|||||||
tokenbuf = (char *) malloc(bufsize);
|
tokenbuf = (char *) malloc(bufsize);
|
||||||
if (tokenbuf == NULL)
|
if (tokenbuf == NULL)
|
||||||
err(1, NULL);
|
err(1, NULL);
|
||||||
|
alloc_typenames();
|
||||||
l_com = combuf + bufsize - 5;
|
l_com = combuf + bufsize - 5;
|
||||||
l_lab = labbuf + bufsize - 5;
|
l_lab = labbuf + bufsize - 5;
|
||||||
l_code = codebuf + bufsize - 5;
|
l_code = codebuf + bufsize - 5;
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void addkey(char *, int);
|
void add_typename(const char *);
|
||||||
|
void alloc_typenames(void);
|
||||||
int compute_code_target(void);
|
int compute_code_target(void);
|
||||||
int compute_label_target(void);
|
int compute_label_target(void);
|
||||||
int count_spaces(int, char *);
|
int count_spaces(int, char *);
|
||||||
|
@ -64,42 +64,49 @@ struct templ {
|
|||||||
int rwcode;
|
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},
|
{"break", 9},
|
||||||
{"struct", 3},
|
{"case", 8},
|
||||||
{"union", 3},
|
|
||||||
{"enum", 3},
|
|
||||||
{"default", 8},
|
|
||||||
{"int", 4},
|
|
||||||
{"char", 4},
|
{"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},
|
{"const", 4},
|
||||||
{"volatile", 4},
|
{"default", 8},
|
||||||
{"goto", 9},
|
|
||||||
{"return", 9},
|
|
||||||
{"if", 5},
|
|
||||||
{"while", 5},
|
|
||||||
{"for", 5},
|
|
||||||
{"else", 6},
|
|
||||||
{"do", 6},
|
{"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},
|
{"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] =
|
char chartype[128] =
|
||||||
{ /* this is used to facilitate the decision of
|
{ /* this is used to facilitate the decision of
|
||||||
* what type (alphanumeric, operator) each
|
* what type (alphanumeric, operator) each
|
||||||
@ -122,6 +129,12 @@ char chartype[128] =
|
|||||||
1, 1, 1, 0, 3, 0, 3, 0
|
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
|
int
|
||||||
lexi(void)
|
lexi(void)
|
||||||
{
|
{
|
||||||
@ -150,9 +163,6 @@ lexi(void)
|
|||||||
/*
|
/*
|
||||||
* we have a character or number
|
* we have a character or number
|
||||||
*/
|
*/
|
||||||
const char *j; /* used for searching thru list of
|
|
||||||
*
|
|
||||||
* reserved words */
|
|
||||||
struct templ *p;
|
struct templ *p;
|
||||||
|
|
||||||
if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) {
|
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
|
last_code = ident; /* Remember that this is the code we will
|
||||||
* return */
|
* return */
|
||||||
|
|
||||||
if (auto_typedefs) {
|
p = bsearch(s_token,
|
||||||
const char *q = s_token;
|
specials,
|
||||||
size_t q_len = strlen(q);
|
sizeof(specials) / sizeof(specials[0]),
|
||||||
/* Check if we have an "_t" in the end */
|
sizeof(specials[0]),
|
||||||
if (q_len > 2 &&
|
strcmp_type);
|
||||||
(strcmp(q + q_len - 2, "_t") == 0)) {
|
if (p == NULL) { /* not a special keyword... */
|
||||||
ps.keyword = 4; /* a type name */
|
char *u;
|
||||||
ps.last_u_d = true;
|
|
||||||
goto found_auto_typedef;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/* ... so maybe a type_t or a typedef */
|
||||||
* This loop will check if the token is a keyword.
|
if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
|
||||||
*/
|
strcmp(u, "_t") == 0) || (typename_top >= 0 &&
|
||||||
for (p = specials; (j = p->rwd) != NULL; p++) {
|
bsearch(s_token, typenames, typename_top + 1,
|
||||||
const char *q = s_token; /* point at scanned token */
|
sizeof(typenames[0]), strcmp_type))) {
|
||||||
if (*j++ != *q++ || *j++ != *q++)
|
ps.keyword = 4; /* a type name */
|
||||||
continue; /* This test depends on the fact that
|
ps.last_u_d = true;
|
||||||
* identifiers are always at least 1 character
|
goto found_typename;
|
||||||
* long (ie. the first two bytes of the
|
}
|
||||||
* identifier are always meaningful) */
|
} else { /* we have a keyword */
|
||||||
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:
|
|
||||||
ps.keyword = p->rwcode;
|
ps.keyword = p->rwcode;
|
||||||
ps.last_u_d = true;
|
ps.last_u_d = true;
|
||||||
switch (p->rwcode) {
|
switch (p->rwcode) {
|
||||||
@ -295,7 +292,7 @@ lexi(void)
|
|||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
case 4: /* one of the declaration keywords */
|
case 4: /* one of the declaration keywords */
|
||||||
found_auto_typedef:
|
found_typename:
|
||||||
if (ps.p_l_follow) {
|
if (ps.p_l_follow) {
|
||||||
/* inside parens: cast, param list, offsetof or sizeof */
|
/* inside parens: cast, param list, offsetof or sizeof */
|
||||||
ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.not_cast_mask;
|
ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.not_cast_mask;
|
||||||
@ -583,24 +580,43 @@ stop_lit:
|
|||||||
return (code);
|
return (code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the given keyword to the keyword table, using val as the keyword type
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
addkey(char *key, int val)
|
alloc_typenames(void)
|
||||||
{
|
{
|
||||||
struct templ *p = specials;
|
|
||||||
while (p->rwd)
|
typenames = (const char **)malloc(sizeof(typenames[0]) *
|
||||||
if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
|
(typename_count = 16));
|
||||||
return;
|
if (typenames == NULL)
|
||||||
else
|
err(1, NULL);
|
||||||
p++;
|
}
|
||||||
if (p >= specials + sizeof(specials) / sizeof(specials[0])) {
|
|
||||||
fprintf(stderr, "indent: typedef table overflow\n");
|
void
|
||||||
exit(1);
|
add_typename(const char *key)
|
||||||
}
|
{
|
||||||
p->rwd = key;
|
int comparison;
|
||||||
p->rwcode = val;
|
|
||||||
p[1].rwd = NULL;
|
if (typename_top + 1 >= typename_count) {
|
||||||
p[1].rwcode = 0;
|
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