Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a88bab9a authored by Michal Marek's avatar Michal Marek
Browse files

Merge branch 'genksyms-enum' into kbuild/kbuild

parents 00759c0e 303fc01f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ $(obj)/keywords.c: $(obj)/keywords.gperf FORCE
# flex

quiet_cmd_lex.c = FLEX    $@
      cmd_lex.c = flex -o$@ -d $< $(obj)/parse.h
      cmd_lex.c = flex -o$@ -d $<

$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h $(obj)/keywords.c FORCE
$(obj)/lex.c: $(obj)/lex.l $(obj)/keywords.c FORCE
	$(call if_changed,lex.c)
	cp $@ $@_shipped

+136 −56
Original line number Diff line number Diff line
@@ -53,12 +53,22 @@ static int nsyms;
static struct symbol *expansion_trail;
static struct symbol *visited_symbols;

static const char *const symbol_type_name[] = {
	"normal", "typedef", "enum", "struct", "union"
static const struct {
	int n;
	const char *name;
} symbol_types[] = {
	[SYM_NORMAL]     = { 0, NULL},
	[SYM_TYPEDEF]    = {'t', "typedef"},
	[SYM_ENUM]       = {'e', "enum"},
	[SYM_STRUCT]     = {'s', "struct"},
	[SYM_UNION]      = {'u', "union"},
	[SYM_ENUM_CONST] = {'E', "enum constant"},
};

static int equal_list(struct string_list *a, struct string_list *b);
static void print_list(FILE * f, struct string_list *list);
static struct string_list *concat_list(struct string_list *start, ...);
static struct string_list *mk_node(const char *string);
static void print_location(void);
static void print_type_name(enum symbol_type type, const char *name);

@@ -140,14 +150,20 @@ static unsigned long crc32(const char *s)

static enum symbol_type map_to_ns(enum symbol_type t)
{
	if (t == SYM_TYPEDEF)
		t = SYM_NORMAL;
	else if (t == SYM_UNION)
		t = SYM_STRUCT;
	switch (t) {
	case SYM_ENUM_CONST:
	case SYM_NORMAL:
	case SYM_TYPEDEF:
		return SYM_NORMAL;
	case SYM_ENUM:
	case SYM_STRUCT:
	case SYM_UNION:
		return SYM_STRUCT;
	}
	return t;
}

struct symbol *find_symbol(const char *name, enum symbol_type ns)
struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
{
	unsigned long h = crc32(name) % HASH_BUCKETS;
	struct symbol *sym;
@@ -158,6 +174,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
		    sym->is_declared)
			break;

	if (exact && sym && sym->type != ns)
		return NULL;
	return sym;
}

@@ -180,10 +198,47 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
			    struct string_list *defn, int is_extern,
			    int is_reference)
{
	unsigned long h = crc32(name) % HASH_BUCKETS;
	unsigned long h;
	struct symbol *sym;
	enum symbol_status status = STATUS_UNCHANGED;
	/* The parser adds symbols in the order their declaration completes,
	 * so it is safe to store the value of the previous enum constant in
	 * a static variable.
	 */
	static int enum_counter;
	static struct string_list *last_enum_expr;

	if (type == SYM_ENUM_CONST) {
		if (defn) {
			free_list(last_enum_expr, NULL);
			last_enum_expr = copy_list_range(defn, NULL);
			enum_counter = 1;
		} else {
			struct string_list *expr;
			char buf[20];

			snprintf(buf, sizeof(buf), "%d", enum_counter++);
			if (last_enum_expr) {
				expr = copy_list_range(last_enum_expr, NULL);
				defn = concat_list(mk_node("("),
						   expr,
						   mk_node(")"),
						   mk_node("+"),
						   mk_node(buf), NULL);
			} else {
				defn = mk_node(buf);
			}
		}
	} else if (type == SYM_ENUM) {
		free_list(last_enum_expr, NULL);
		last_enum_expr = NULL;
		enum_counter = 0;
		if (!name)
			/* Anonymous enum definition, nothing more to do */
			return NULL;
	}

	h = crc32(name) % HASH_BUCKETS;
	for (sym = symtab[h]; sym; sym = sym->hash_next) {
		if (map_to_ns(sym->type) == map_to_ns(type) &&
		    strcmp(name, sym->name) == 0) {
@@ -247,8 +302,12 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
	sym->is_override = 0;

	if (flag_debug) {
		if (symbol_types[type].name)
			fprintf(debugfile, "Defn for %s %s == <",
			symbol_type_name[type], name);
				symbol_types[type].name, name);
		else
			fprintf(debugfile, "Defn for type%d %s == <",
				type, name);
		if (is_extern)
			fputs("extern ", debugfile);
		print_list(debugfile, defn);
@@ -288,6 +347,35 @@ void free_list(struct string_list *s, struct string_list *e)
	}
}

static struct string_list *mk_node(const char *string)
{
	struct string_list *newnode;

	newnode = xmalloc(sizeof(*newnode));
	newnode->string = xstrdup(string);
	newnode->tag = SYM_NORMAL;
	newnode->next = NULL;

	return newnode;
}

static struct string_list *concat_list(struct string_list *start, ...)
{
	va_list ap;
	struct string_list *n, *n2;

	if (!start)
		return NULL;
	for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
		for (n2 = n; n2->next; n2 = n2->next)
			;
		n2->next = start;
		start = n;
	}
	va_end(ap);
	return start;
}

struct string_list *copy_node(struct string_list *node)
{
	struct string_list *newnode;
@@ -299,6 +387,22 @@ struct string_list *copy_node(struct string_list *node)
	return newnode;
}

struct string_list *copy_list_range(struct string_list *start,
				    struct string_list *end)
{
	struct string_list *res, *n;

	if (start == end)
		return NULL;
	n = res = copy_node(start);
	for (start = start->next; start != end; start = start->next) {
		n->next = copy_node(start);
		n = n->next;
	}
	n->next = NULL;
	return res;
}

static int equal_list(struct string_list *a, struct string_list *b)
{
	while (a && b) {
@@ -346,8 +450,8 @@ static struct string_list *read_node(FILE *f)
	if (node.string[1] == '#') {
		int n;

		for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) {
			if (node.string[0] == symbol_type_name[n][0]) {
		for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
			if (node.string[0] == symbol_types[n].n) {
				node.tag = n;
				node.string += 2;
				return copy_node(&node);
@@ -397,8 +501,8 @@ static void read_reference(FILE *f)

static void print_node(FILE * f, struct string_list *list)
{
	if (list->tag != SYM_NORMAL) {
		putc(symbol_type_name[list->tag][0], f);
	if (symbol_types[list->tag].n) {
		putc(symbol_types[list->tag].n, f);
		putc('#', f);
	}
	fputs(list->string, f);
@@ -468,8 +572,9 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
			crc = partial_crc32_one(' ', crc);
			break;

		case SYM_ENUM_CONST:
		case SYM_TYPEDEF:
			subsym = find_symbol(cur->string, cur->tag);
			subsym = find_symbol(cur->string, cur->tag, 0);
			/* FIXME: Bad reference files can segfault here. */
			if (subsym->expansion_trail) {
				if (flag_dump_defs)
@@ -486,55 +591,30 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
		case SYM_STRUCT:
		case SYM_UNION:
		case SYM_ENUM:
			subsym = find_symbol(cur->string, cur->tag);
			subsym = find_symbol(cur->string, cur->tag, 0);
			if (!subsym) {
				struct string_list *n, *t = NULL;
				struct string_list *n;

				error_with_pos("expand undefined %s %s",
					       symbol_type_name[cur->tag],
					       symbol_types[cur->tag].name,
					       cur->string);

				n = xmalloc(sizeof(*n));
				n->string = xstrdup(symbol_type_name[cur->tag]);
				n->tag = SYM_NORMAL;
				n->next = t;
				t = n;

				n = xmalloc(sizeof(*n));
				n->string = xstrdup(cur->string);
				n->tag = SYM_NORMAL;
				n->next = t;
				t = n;

				n = xmalloc(sizeof(*n));
				n->string = xstrdup("{");
				n->tag = SYM_NORMAL;
				n->next = t;
				t = n;

				n = xmalloc(sizeof(*n));
				n->string = xstrdup("UNKNOWN");
				n->tag = SYM_NORMAL;
				n->next = t;
				t = n;

				n = xmalloc(sizeof(*n));
				n->string = xstrdup("}");
				n->tag = SYM_NORMAL;
				n->next = t;
				t = n;

				n = concat_list(mk_node
						(symbol_types[cur->tag].name),
						mk_node(cur->string),
						mk_node("{"),
						mk_node("UNKNOWN"),
						mk_node("}"), NULL);
				subsym =
				    add_symbol(cur->string, cur->tag, n, 0);
			}
			if (subsym->expansion_trail) {
				if (flag_dump_defs) {
					fprintf(debugfile, "%s %s ",
						symbol_type_name[cur->tag],
						symbol_types[cur->tag].name,
						cur->string);
				}

				crc = partial_crc32(symbol_type_name[cur->tag],
				crc = partial_crc32(symbol_types[cur->tag].name,
						    crc);
				crc = partial_crc32_one(' ', crc);
				crc = partial_crc32(cur->string, crc);
@@ -565,7 +645,7 @@ void export_symbol(const char *name)
{
	struct symbol *sym;

	sym = find_symbol(name, SYM_NORMAL);
	sym = find_symbol(name, SYM_NORMAL, 0);
	if (!sym)
		error_with_pos("export undefined symbol %s", name);
	else {
@@ -624,8 +704,8 @@ static void print_location(void)

static void print_type_name(enum symbol_type type, const char *name)
{
	if (type != SYM_NORMAL)
		fprintf(stderr, "%s %s", symbol_type_name[type], name);
	if (symbol_types[type].name)
		fprintf(stderr, "%s %s", symbol_types[type].name, name);
	else
		fprintf(stderr, "%s", name);
}
@@ -771,8 +851,8 @@ int main(int argc, char **argv)

			if (sym->is_override)
				fputs("override ", dumpfile);
			if (sym->type != SYM_NORMAL) {
				putc(symbol_type_name[sym->type][0], dumpfile);
			if (symbol_types[sym->type].n) {
				putc(symbol_types[sym->type].n, dumpfile);
				putc('#', dumpfile);
			}
			fputs(sym->name, dumpfile);
+5 −2
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@
#include <stdio.h>

enum symbol_type {
	SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION
	SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION,
	SYM_ENUM_CONST
};

enum symbol_status {
@@ -58,7 +59,7 @@ typedef struct string_list **yystype;
extern int cur_line;
extern char *cur_filename;

struct symbol *find_symbol(const char *name, enum symbol_type ns);
struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact);
struct symbol *add_symbol(const char *name, enum symbol_type type,
			  struct string_list *defn, int is_extern);
void export_symbol(const char *);
@@ -66,6 +67,8 @@ void export_symbol(const char *);
void free_node(struct string_list *list);
void free_list(struct string_list *s, struct string_list *e);
struct string_list *copy_node(struct string_list *);
struct string_list *copy_list_range(struct string_list *start,
				    struct string_list *end);

int yylex(void);
int yyparse(void);
+150 −277

File changed.

Preview size limit exceeded, changes collapsed.

+31 −13
Original line number Diff line number Diff line
@@ -55,10 +55,6 @@ CHAR L?\'([^\\\']*\\.)*[^\\\']*\'

MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)

/* Version 2 checksumming does proper tokenization; version 1 wasn't
   quite so pedantic.  */
%s V2_TOKENS

/* We don't do multiple input files.  */
%option noyywrap

@@ -84,9 +80,9 @@ MC_TOKEN ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
    recognized as tokens.  We don't actually use them since we don't
    parse expressions, but we do want whitespace to be arranged
    around them properly.  */
<V2_TOKENS>{MC_TOKEN}			return OTHER;
<V2_TOKENS>{INT}			return INT;
<V2_TOKENS>{REAL}			return REAL;
{MC_TOKEN}				return OTHER;
{INT}					return INT;
{REAL}					return REAL;

"..."					return DOTS;

@@ -103,12 +99,23 @@ MC_TOKEN ([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)

/* Macros to append to our phrase collection list.  */

/*
 * We mark any token, that that equals to a known enumerator, as
 * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
 * the only problem is struct and union members:
 *    enum e { a, b }; struct s { int a, b; }
 * but in this case, the only effect will be, that the ABI checksums become
 * more volatile, which is acceptable. Also, such collisions are quite rare,
 * so far it was only observed in include/linux/telephony.h.
 */
#define _APP(T,L)	do {						   \
			  cur_node = next_node;				   \
			  next_node = xmalloc(sizeof(*next_node));	   \
			  next_node->next = cur_node;			   \
			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
			  cur_node->tag = SYM_NORMAL;			   \
			  cur_node->tag =				   \
			    find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
			    SYM_ENUM_CONST : SYM_NORMAL ;		   \
			} while (0)

#define APP		_APP(yytext, yyleng)
@@ -134,7 +141,6 @@ yylex(void)

  if (lexstate == ST_NOTSTARTED)
    {
      BEGIN(V2_TOKENS);
      next_node = xmalloc(sizeof(*next_node));
      next_node->next = NULL;
      lexstate = ST_NORMAL;
@@ -187,8 +193,8 @@ repeat:

		  case STRUCT_KEYW:
		  case UNION_KEYW:
		    dont_want_brace_phrase = 3;
		  case ENUM_KEYW:
		    dont_want_brace_phrase = 3;
		    suppress_type_lookup = 2;
		    goto fini;

@@ -198,8 +204,7 @@ repeat:
	      }
	    if (!suppress_type_lookup)
	      {
		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
		if (sym && sym->type == SYM_TYPEDEF)
		if (find_symbol(yytext, SYM_TYPEDEF, 1))
		  token = TYPE;
	      }
	  }
@@ -318,7 +323,20 @@ repeat:
	  ++count;
	  APP;
	  goto repeat;
	case ')': case ']': case '}':
	case '}':
	  /* is this the last line of an enum declaration? */
	  if (count == 0)
	    {
	      /* Put back the token we just read so's we can find it again
		 after registering the expression.  */
	      unput(token);

	      lexstate = ST_NORMAL;
	      token = EXPRESSION_PHRASE;
	      break;
	    }
	  /* FALLTHRU */
	case ')': case ']':
	  --count;
	  APP;
	  goto repeat;
Loading