Blame parser.y

Packit Service 80a84b
/*
Packit Service 80a84b
	Copyright(C) 2016, Red Hat, Inc., Jerome Marchand
Packit Service 80a84b
Packit Service 80a84b
	This program is free software: you can redistribute it and/or modify
Packit Service 80a84b
	it under the terms of the GNU General Public License as published by
Packit Service 80a84b
	the Free Software Foundation, either version 3 of the License, or
Packit Service 80a84b
	(at your option) any later version.
Packit Service 80a84b
Packit Service 80a84b
	This program is distributed in the hope that it will be useful,
Packit Service 80a84b
	but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 80a84b
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 80a84b
	GNU General Public License for more details.
Packit Service 80a84b
Packit Service 80a84b
	You should have received a copy of the GNU General Public License
Packit Service 80a84b
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit Service 80a84b
*/
Packit Service 80a84b
Packit Service 80a84b
%{
Packit Service 80a84b
#include "parser.h"
Packit Service 80a84b
#include <limits.h>
Packit Service 80a84b
Packit Service 80a84b
#include "utils.h"
Packit Service 80a84b
Packit Service 80a84b
#define abort(...)				\
Packit Service 80a84b
{						\
Packit Service 80a84b
	fprintf(stderr, __VA_ARGS__);		\
Packit Service 80a84b
	YYABORT;				\
Packit Service 80a84b
}
Packit Service 80a84b
Packit Service 80a84b
#define check_and_free_keyword(identifier, expected)			\
Packit Service 80a84b
{									\
Packit Service 80a84b
	if (strcmp(identifier, expected))				\
Packit Service 80a84b
		abort("Wrong keyword: %s expected, %s received\n",	\
Packit Service 80a84b
		      expected, identifier);				\
Packit Service 80a84b
	free(identifier);						\
Packit Service 80a84b
}
Packit Service 80a84b
Packit Service 80a84b
Packit Service 80a84b
%}
Packit Service 80a84b
Packit Service 80a84b
%union {
Packit Service 80a84b
	int i;
Packit Service 80a84b
	unsigned int ui;
Packit Service 80a84b
	long l;
Packit Service 80a84b
	unsigned long ul;
Packit Service 80a84b
	void *ptr;
Packit Service 80a84b
	char *str;
Packit Service 80a84b
	obj_t *obj;
Packit Service 80a84b
	obj_list_head_t *list;
Packit Service 80a84b
}
Packit Service 80a84b
Packit Service 80a84b
%token <str> IDENTIFIER STRING SRCFILE
Packit Service 80a84b
%token 
    CONSTANT
Packit Service 80a84b
Packit Service 80a84b
%token NEWLINE
Packit Service 80a84b
%token TYPEDEF
Packit Service 80a84b
%token CONST VOLATILE
Packit Service 80a84b
%token STRUCT UNION ENUM ELLIPSIS
Packit Service 80a84b
%token VERSION_KW CU_KW FILE_KW STACK_KW SYMBOL_KW_NL
Packit Service 80a84b
%token ARROW UNKNOWN_FIELD
Packit Service 80a84b
Packit Service 80a84b
%type <str> type_qualifier
Packit Service 80a84b
%type <obj> typed_type base_type reference_file array_type
Packit Service 80a84b
%type <obj> type ptr_type variable_var_list func_type elt enum_elt enum_type
Packit Service 80a84b
%type <obj> union_type struct_type struct_elt
Packit Service 80a84b
%type <obj> declaration_var declaration_typedef declaration
Packit Service 80a84b
%type <obj> kabi_dw_file symbol
Packit Service 80a84b
%type <obj> asm_symbol weak_symbol
Packit Service 80a84b
%type <list> elt_list arg_list enum_list struct_list
Packit Service 80a84b
%type 
    alignment byte_size
Packit Service 80a84b
Packit Service 80a84b
%parse-param {obj_t **root}
Packit Service 80a84b
Packit Service 80a84b
%%
Packit Service 80a84b
Packit Service 80a84b
kabi_dw_file:
Packit Service 80a84b
	fmt_version header SYMBOL_KW_NL symbol
Packit Service 80a84b
	{
Packit Service 80a84b
		$$ = *root = $symbol;
Packit Service 80a84b
		obj_fill_parent(*root);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
fmt_version:
Packit Service 80a84b
	VERSION_KW CONSTANT '.' CONSTANT NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
		if (($2 != FILEFMT_VERSION_MAJOR) |
Packit Service 80a84b
		    ($4 > FILEFMT_VERSION_MINOR))
Packit Service 80a84b
			abort("Unsupported file version: %lu.%lu\n", $2, $4);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
header:
Packit Service 80a84b
	/* empty */
Packit Service 80a84b
	| header header_field
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
header_field:
Packit Service 80a84b
	cu_field
Packit Service 80a84b
	| source_file_field
Packit Service 80a84b
	| stack_field
Packit Service 80a84b
	| UNKNOWN_FIELD
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
cu_field:
Packit Service 80a84b
	CU_KW STRING NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
	    free($STRING);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
source_file_field:
Packit Service 80a84b
	FILE_KW SRCFILE ':' CONSTANT NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
	    free($SRCFILE);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
stack_field:
Packit Service 80a84b
	STACK_KW NEWLINE stack_list
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
stack_list:
Packit Service 80a84b
	/* empty */
Packit Service 80a84b
	| stack_list stack_elt NEWLINE
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
stack_elt:
Packit Service 80a84b
	ARROW STRING
Packit Service 80a84b
	{
Packit Service 80a84b
		free($STRING);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
symbol:
Packit Service 80a84b
	declaration NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
		$$ = $declaration;
Packit Service 80a84b
	}
Packit Service 80a84b
	| alignment declaration NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
		$$ = $declaration;
Packit Service 80a84b
		$$->alignment = $alignment;
Packit Service 80a84b
	}
Packit Service 80a84b
	| byte_size declaration NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
		$$ = $declaration;
Packit Service 80a84b
		$$->byte_size = $byte_size;
Packit Service 80a84b
	}
Packit Service 80a84b
	| byte_size alignment declaration NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
		$$ = $declaration;
Packit Service 80a84b
		$$->byte_size = $byte_size;
Packit Service 80a84b
		$$->alignment = $alignment;
Packit Service 80a84b
	}
Packit Service 80a84b
Packit Service 80a84b
alignment:
Packit Service 80a84b
        IDENTIFIER CONSTANT NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
		check_and_free_keyword($IDENTIFIER, "Alignment");
Packit Service 80a84b
		$$ = $CONSTANT;
Packit Service 80a84b
	}
Packit Service 80a84b
Packit Service 80a84b
byte_size:
Packit Service 80a84b
        IDENTIFIER IDENTIFIER CONSTANT NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
		check_and_free_keyword($1, "Byte");
Packit Service 80a84b
		check_and_free_keyword($2, "size");
Packit Service 80a84b
		$$ = $CONSTANT;
Packit Service 80a84b
	}
Packit Service 80a84b
Packit Service 80a84b
/* Possible types are struct union enum func typedef and var */
Packit Service 80a84b
declaration:
Packit Service 80a84b
	struct_type
Packit Service 80a84b
	| union_type
Packit Service 80a84b
	| enum_type
Packit Service 80a84b
	| func_type
Packit Service 80a84b
	| declaration_typedef
Packit Service 80a84b
	| declaration_var
Packit Service 80a84b
	| weak_symbol
Packit Service 80a84b
	| asm_symbol
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
declaration_typedef:
Packit Service 80a84b
	TYPEDEF IDENTIFIER NEWLINE type
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_typedef_new_add($IDENTIFIER, $type);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
declaration_var:
Packit Service 80a84b
	IDENTIFIER IDENTIFIER type
Packit Service 80a84b
	{
Packit Service 80a84b
	    check_and_free_keyword($1, "var");
Packit Service 80a84b
	    $$ = obj_var_new_add($2, $type);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
type:
Packit Service 80a84b
	base_type
Packit Service 80a84b
	| reference_file
Packit Service 80a84b
	| struct_type
Packit Service 80a84b
	| union_type
Packit Service 80a84b
	| enum_type
Packit Service 80a84b
	| func_type
Packit Service 80a84b
	| ptr_type
Packit Service 80a84b
	| array_type
Packit Service 80a84b
	| typed_type
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
struct_type:
Packit Service 80a84b
	STRUCT IDENTIFIER '{' NEWLINE '}'
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_struct_new($IDENTIFIER);
Packit Service 80a84b
	}
Packit Service 80a84b
	| STRUCT IDENTIFIER '{' NEWLINE struct_list NEWLINE '}'
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_struct_new($IDENTIFIER);
Packit Service 80a84b
	    $$->member_list = $struct_list;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
struct_list:
Packit Service 80a84b
	struct_elt
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_list_head_new($struct_elt);
Packit Service 80a84b
	}
Packit Service 80a84b
	| struct_list NEWLINE struct_elt
Packit Service 80a84b
	{
Packit Service 80a84b
	    obj_list_add($1, $struct_elt);
Packit Service 80a84b
	    $$ = $1;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
struct_elt:
Packit Service 80a84b
	CONSTANT IDENTIFIER type
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_struct_member_new_add($IDENTIFIER, $type);
Packit Service 80a84b
	    $$->offset = $CONSTANT;
Packit Service 80a84b
	}
Packit Service 80a84b
	/* with alignment */
Packit Service 80a84b
	| CONSTANT CONSTANT IDENTIFIER type
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_struct_member_new_add($IDENTIFIER, $type);
Packit Service 80a84b
	    $$->offset = $1;
Packit Service 80a84b
            $$->alignment = $2;
Packit Service 80a84b
	}
Packit Service 80a84b
	| CONSTANT ':' CONSTANT '-' CONSTANT IDENTIFIER type
Packit Service 80a84b
	{
Packit Service 80a84b
	    if ($5 > UCHAR_MAX || $3 > $5)
Packit Service 80a84b
		abort("Invalid offset: %lx:%lu:%lu\n", $1, $3, $5);
Packit Service 80a84b
	    $$ = obj_struct_member_new_add($IDENTIFIER, $type);
Packit Service 80a84b
	    $$->offset = $1;
Packit Service 80a84b
	    $$->is_bitfield = 1;
Packit Service 80a84b
	    $$->first_bit = $3;
Packit Service 80a84b
	    $$->last_bit = $5;
Packit Service 80a84b
	}
Packit Service 80a84b
	/* with alignment */
Packit Service 80a84b
	| CONSTANT ':' CONSTANT '-' CONSTANT CONSTANT IDENTIFIER type
Packit Service 80a84b
	{
Packit Service 80a84b
	    if ($5 > UCHAR_MAX || $3 > $5)
Packit Service 80a84b
		abort("Invalid offset: %lx:%lu:%lu\n", $1, $3, $5);
Packit Service 80a84b
	    $$ = obj_struct_member_new_add($IDENTIFIER, $type);
Packit Service 80a84b
	    $$->offset = $1;
Packit Service 80a84b
	    $$->is_bitfield = 1;
Packit Service 80a84b
	    $$->first_bit = $3;
Packit Service 80a84b
	    $$->last_bit = $5;
Packit Service 80a84b
	    $$->alignment = $6;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
union_type:
Packit Service 80a84b
	UNION IDENTIFIER '{' NEWLINE '}'
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_union_new($IDENTIFIER);
Packit Service 80a84b
	}
Packit Service 80a84b
	| UNION IDENTIFIER '{' NEWLINE elt_list NEWLINE '}'
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_union_new($IDENTIFIER);
Packit Service 80a84b
	    $$->member_list = $elt_list;
Packit Service 80a84b
	    $elt_list->object = $$;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
enum_type:
Packit Service 80a84b
	ENUM IDENTIFIER '{' NEWLINE enum_list NEWLINE '}'
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_enum_new($IDENTIFIER);
Packit Service 80a84b
	    $$->member_list = $enum_list;
Packit Service 80a84b
	    $enum_list->object = $$;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
enum_list:
Packit Service 80a84b
	enum_elt
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_list_head_new($enum_elt);
Packit Service 80a84b
	}
Packit Service 80a84b
	| enum_list NEWLINE enum_elt
Packit Service 80a84b
	{
Packit Service 80a84b
	    obj_list_add($1, $enum_elt);
Packit Service 80a84b
	    $$ = $1;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
enum_elt:
Packit Service 80a84b
	IDENTIFIER '=' CONSTANT
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_constant_new($IDENTIFIER);
Packit Service 80a84b
	    $$->constant = $CONSTANT;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
func_type:
Packit Service 80a84b
	IDENTIFIER IDENTIFIER '(' NEWLINE arg_list ')' NEWLINE type
Packit Service 80a84b
	{
Packit Service 80a84b
	    check_and_free_keyword($1, "func");
Packit Service 80a84b
	    $$ = obj_func_new_add($2, $type);
Packit Service 80a84b
	    $$->member_list = $arg_list;
Packit Service 80a84b
	    if ($arg_list)
Packit Service 80a84b
		    $arg_list->object = $$;
Packit Service 80a84b
	}
Packit Service 80a84b
	| IDENTIFIER reference_file /* protype define as typedef */
Packit Service 80a84b
	{
Packit Service 80a84b
	    check_and_free_keyword($IDENTIFIER, "func");
Packit Service 80a84b
	    $$ = obj_func_new_add(NULL, $reference_file);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
arg_list:
Packit Service 80a84b
	/* empty */
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = NULL;
Packit Service 80a84b
	}
Packit Service 80a84b
	| elt_list NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = $elt_list;
Packit Service 80a84b
	}
Packit Service 80a84b
	| elt_list NEWLINE variable_var_list NEWLINE
Packit Service 80a84b
	{
Packit Service 80a84b
	    obj_list_add($elt_list, $variable_var_list);
Packit Service 80a84b
	    $$ = $elt_list;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
variable_var_list:
Packit Service 80a84b
	IDENTIFIER ELLIPSIS
Packit Service 80a84b
	{
Packit Service 80a84b
	    /* TODO: there may be a better solution */
Packit Service 80a84b
	    $$ = obj_var_new_add(NULL, obj_basetype_new(strdup("...")));
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
elt_list:
Packit Service 80a84b
	elt
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_list_head_new($elt);
Packit Service 80a84b
	}
Packit Service 80a84b
	| elt_list NEWLINE elt
Packit Service 80a84b
	{
Packit Service 80a84b
	    obj_list_add($1, $elt);
Packit Service 80a84b
	    $$ = $1;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
elt:
Packit Service 80a84b
	IDENTIFIER type
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_var_new_add($IDENTIFIER, $type);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
ptr_type:
Packit Service 80a84b
	'*' type
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_ptr_new_add($type);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
array_type:
Packit Service 80a84b
        '['CONSTANT ']' type
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_array_new_add($type);
Packit Service 80a84b
	    $$->index = $CONSTANT;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
typed_type:
Packit Service 80a84b
	type_qualifier type
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_qualifier_new_add($type);
Packit Service 80a84b
	    $$->base_type = $type_qualifier;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
type_qualifier:
Packit Service 80a84b
	CONST
Packit Service 80a84b
	{
Packit Service 80a84b
	    debug("Qualifier: const\n");
Packit Service 80a84b
	    $$ = strdup("const");
Packit Service 80a84b
	}
Packit Service 80a84b
	| VOLATILE
Packit Service 80a84b
	{
Packit Service 80a84b
	    debug("Qualifier: volatile\n");
Packit Service 80a84b
	    $$ = strdup("volatile");
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
base_type:
Packit Service 80a84b
	STRING
Packit Service 80a84b
	{
Packit Service 80a84b
	    debug("Base type: %s\n", $STRING);
Packit Service 80a84b
	    $$ = obj_basetype_new($STRING);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
reference_file:
Packit Service 80a84b
	'@' STRING
Packit Service 80a84b
	{
Packit Service 80a84b
	    $$ = obj_reffile_new();
Packit Service 80a84b
	    $$->base_type = $STRING;
Packit Service 80a84b
	    }
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
asm_symbol:
Packit Service 80a84b
	IDENTIFIER IDENTIFIER
Packit Service 80a84b
	{
Packit Service 80a84b
		check_and_free_keyword($1, "assembly");
Packit Service 80a84b
		$$ = obj_assembly_new($2);
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
weak_symbol:
Packit Service 80a84b
        IDENTIFIER IDENTIFIER ARROW IDENTIFIER
Packit Service 80a84b
	{
Packit Service 80a84b
		check_and_free_keyword($1, "weak");
Packit Service 80a84b
		$$ = obj_weak_new($2);
Packit Service 80a84b
		$$->link = $4;
Packit Service 80a84b
	}
Packit Service 80a84b
	;
Packit Service 80a84b
Packit Service 80a84b
Packit Service 80a84b
%%
Packit Service 80a84b
Packit Service 80a84b
extern void usage(void);
Packit Service 80a84b
Packit Service 80a84b
obj_t *obj_parse(FILE *file, char *fn) {
Packit Service 80a84b
	obj_t *root = NULL;
Packit Service 80a84b
Packit Service 80a84b
#ifdef DEBUG
Packit Service 80a84b
	yydebug = 1;
Packit Service 80a84b
#else
Packit Service 80a84b
	yydebug = 0;
Packit Service 80a84b
#endif
Packit Service 80a84b
Packit Service 80a84b
	yyin = file;
Packit Service 80a84b
	yyparse(&root);
Packit Service 80a84b
	if (!root)
Packit Service 80a84b
		fail("No object build for file %s\n", fn);
Packit Service 80a84b
Packit Service 80a84b
	return root;
Packit Service 80a84b
}
Packit Service 80a84b
Packit Service 80a84b
int yyerror(obj_t **root, char *s)
Packit Service 80a84b
{
Packit Service 80a84b
	fprintf(stderr, "error: %s\n", s);
Packit Service 80a84b
	return 0;
Packit Service 80a84b
}