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 Original line Diff line number Diff line
@@ -28,9 +28,9 @@ $(obj)/keywords.c: $(obj)/keywords.gperf FORCE
# flex
# flex


quiet_cmd_lex.c = 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)
	$(call if_changed,lex.c)
	cp $@ $@_shipped
	cp $@ $@_shipped


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


static const char *const symbol_type_name[] = {
static const struct {
	"normal", "typedef", "enum", "struct", "union"
	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 int equal_list(struct string_list *a, struct string_list *b);
static void print_list(FILE * f, struct string_list *list);
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_location(void);
static void print_type_name(enum symbol_type type, const char *name);
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)
static enum symbol_type map_to_ns(enum symbol_type t)
{
{
	if (t == SYM_TYPEDEF)
	switch (t) {
		t = SYM_NORMAL;
	case SYM_ENUM_CONST:
	else if (t == SYM_UNION)
	case SYM_NORMAL:
		t = SYM_STRUCT;
	case SYM_TYPEDEF:
		return SYM_NORMAL;
	case SYM_ENUM:
	case SYM_STRUCT:
	case SYM_UNION:
		return SYM_STRUCT;
	}
	return t;
	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;
	unsigned long h = crc32(name) % HASH_BUCKETS;
	struct symbol *sym;
	struct symbol *sym;
@@ -158,6 +174,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
		    sym->is_declared)
		    sym->is_declared)
			break;
			break;


	if (exact && sym && sym->type != ns)
		return NULL;
	return sym;
	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,
			    struct string_list *defn, int is_extern,
			    int is_reference)
			    int is_reference)
{
{
	unsigned long h = crc32(name) % HASH_BUCKETS;
	unsigned long h;
	struct symbol *sym;
	struct symbol *sym;
	enum symbol_status status = STATUS_UNCHANGED;
	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) {
	for (sym = symtab[h]; sym; sym = sym->hash_next) {
		if (map_to_ns(sym->type) == map_to_ns(type) &&
		if (map_to_ns(sym->type) == map_to_ns(type) &&
		    strcmp(name, sym->name) == 0) {
		    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;
	sym->is_override = 0;


	if (flag_debug) {
	if (flag_debug) {
		if (symbol_types[type].name)
			fprintf(debugfile, "Defn for %s %s == <",
			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)
		if (is_extern)
			fputs("extern ", debugfile);
			fputs("extern ", debugfile);
		print_list(debugfile, defn);
		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 *copy_node(struct string_list *node)
{
{
	struct string_list *newnode;
	struct string_list *newnode;
@@ -299,6 +387,22 @@ struct string_list *copy_node(struct string_list *node)
	return newnode;
	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)
static int equal_list(struct string_list *a, struct string_list *b)
{
{
	while (a && b) {
	while (a && b) {
@@ -346,8 +450,8 @@ static struct string_list *read_node(FILE *f)
	if (node.string[1] == '#') {
	if (node.string[1] == '#') {
		int n;
		int n;


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


static void print_node(FILE * f, struct string_list *list)
static void print_node(FILE * f, struct string_list *list)
{
{
	if (list->tag != SYM_NORMAL) {
	if (symbol_types[list->tag].n) {
		putc(symbol_type_name[list->tag][0], f);
		putc(symbol_types[list->tag].n, f);
		putc('#', f);
		putc('#', f);
	}
	}
	fputs(list->string, 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);
			crc = partial_crc32_one(' ', crc);
			break;
			break;


		case SYM_ENUM_CONST:
		case SYM_TYPEDEF:
		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. */
			/* FIXME: Bad reference files can segfault here. */
			if (subsym->expansion_trail) {
			if (subsym->expansion_trail) {
				if (flag_dump_defs)
				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_STRUCT:
		case SYM_UNION:
		case SYM_UNION:
		case SYM_ENUM:
		case SYM_ENUM:
			subsym = find_symbol(cur->string, cur->tag);
			subsym = find_symbol(cur->string, cur->tag, 0);
			if (!subsym) {
			if (!subsym) {
				struct string_list *n, *t = NULL;
				struct string_list *n;


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

				n = concat_list(mk_node
				n = xmalloc(sizeof(*n));
						(symbol_types[cur->tag].name),
				n->string = xstrdup(symbol_type_name[cur->tag]);
						mk_node(cur->string),
				n->tag = SYM_NORMAL;
						mk_node("{"),
				n->next = t;
						mk_node("UNKNOWN"),
				t = n;
						mk_node("}"), NULL);

				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;

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


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


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


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


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


enum symbol_type {
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 {
enum symbol_status {
@@ -58,7 +59,7 @@ typedef struct string_list **yystype;
extern int cur_line;
extern int cur_line;
extern char *cur_filename;
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 symbol *add_symbol(const char *name, enum symbol_type type,
			  struct string_list *defn, int is_extern);
			  struct string_list *defn, int is_extern);
void export_symbol(const char *);
void export_symbol(const char *);
@@ -66,6 +67,8 @@ void export_symbol(const char *);
void free_node(struct string_list *list);
void free_node(struct string_list *list);
void free_list(struct string_list *s, struct string_list *e);
void free_list(struct string_list *s, struct string_list *e);
struct string_list *copy_node(struct string_list *);
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 yylex(void);
int yyparse(void);
int yyparse(void);
+150 −277

File changed.

Preview size limit exceeded, changes collapsed.

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


MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
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.  */
/* We don't do multiple input files.  */
%option noyywrap
%option noyywrap


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


"..."					return DOTS;
"..."					return DOTS;


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


/* Macros to append to our phrase collection list.  */
/* 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 {						   \
#define _APP(T,L)	do {						   \
			  cur_node = next_node;				   \
			  cur_node = next_node;				   \
			  next_node = xmalloc(sizeof(*next_node));	   \
			  next_node = xmalloc(sizeof(*next_node));	   \
			  next_node->next = cur_node;			   \
			  next_node->next = cur_node;			   \
			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
			  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)
			} while (0)


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


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


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


@@ -198,8 +204,7 @@ repeat:
	      }
	      }
	    if (!suppress_type_lookup)
	    if (!suppress_type_lookup)
	      {
	      {
		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
		if (find_symbol(yytext, SYM_TYPEDEF, 1))
		if (sym && sym->type == SYM_TYPEDEF)
		  token = TYPE;
		  token = TYPE;
	      }
	      }
	  }
	  }
@@ -318,7 +323,20 @@ repeat:
	  ++count;
	  ++count;
	  APP;
	  APP;
	  goto repeat;
	  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;
	  --count;
	  APP;
	  APP;
	  goto repeat;
	  goto repeat;
Loading