Skip to content

Commit

Permalink
[optimization] Use bsearch() for looking up type keywords.
Browse files Browse the repository at this point in the history
  • Loading branch information
pstef committed Jul 31, 2016
1 parent 49c52cf commit f3b8e6e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 76 deletions.
10 changes: 7 additions & 3 deletions args.c
Expand Up @@ -300,7 +300,7 @@ set_option(char *arg)
char *str = strdup(param_start);
if (str == NULL)
err(1, NULL);
addkey(str, 4);
add_typename(str);
}
break;

Expand Down Expand Up @@ -345,15 +345,19 @@ 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);
exit(1);
}
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);
}
1 change: 1 addition & 0 deletions indent.c
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion indent.h
Expand Up @@ -28,7 +28,8 @@
__FBSDID("$FreeBSD: head/usr.bin/indent/indent.h 93440 2002-03-30 17:10:20Z dwmalone $");
#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 *);
Expand Down
159 changes: 87 additions & 72 deletions lexi.c
Expand Up @@ -66,42 +66,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},
{"const", 4},
{"default", 8},
{"do", 6},
{"double", 4},
{"else", 6},
{"enum", 3},
{"extern", 4},
{"float", 4},
{"for", 5},
{"global", 4},
{"goto", 9},
{"if", 5},
{"int", 4},
{"long", 4},
{"offsetof", 1},
{"register", 4},
{"return", 9},
{"short", 4},
{"sizeof", 2},
{"static", 4},
{"struct", 3},
{"switch", 7},
{"typedef", 4},
{"union", 3},
{"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},
{"do", 6},
{"sizeof", 2},
{"offsetof", 1},
{0, 0}
{"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
Expand All @@ -124,6 +131,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)
{
Expand Down Expand Up @@ -152,9 +165,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]))) {
Expand Down Expand Up @@ -249,37 +259,27 @@ 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 */
p = bsearch(s_token,
specials,
sizeof(specials) / sizeof(specials[0]),
sizeof(specials[0]),
strcmp_type);
if (!p) { /* not a special keyword... */

This comment has been minimized.

Copy link
@pstef

pstef Aug 3, 2016

Author Owner

p should be compared to NULL.

char *u;

/* ... so maybe a type_t or a typedef */
if ((auto_typedefs && (u = strrchr(s_token, '_')) && strcmp(u, "_t") == 0)

This comment has been minimized.

Copy link
@pstef

pstef Aug 3, 2016

Author Owner

Surplus parens. u should be compared to NULL.

|| (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_auto_typedef;
goto found_typename;
}
}

/*
* This loop will check if the token is a keyword.
*/
for (p = specials; (j = p->rwd) != 0; 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:
else { /* we have a keyword */
ps.keyword = p->rwcode;
ps.last_u_d = true;
switch (p->rwcode) {
Expand All @@ -297,7 +297,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;
Expand Down Expand Up @@ -585,24 +585,39 @@ lexi(void)
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)
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;
else
p++;
if (p >= specials + sizeof specials / sizeof specials[0]) {
fprintf(stderr, "indent: typedef table overflow\n");
exit(1);
memmove(&typenames[p + 1], &typenames[p], sizeof(typenames[0]) * (++typename_top - p));
typenames[p] = key;
}
p->rwd = key;
p->rwcode = val;
p[1].rwd = 0;
p[1].rwcode = 0;
}

0 comments on commit f3b8e6e

Please sign in to comment.