⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.y

📁 linux 内核源代码
💻 Y
字号:
/* C global declaration parser for genksyms.   Copyright 1996, 1997 Linux International.   New implementation contributed by Richard Henderson <rth@tamu.edu>   Based on original work by Bjorn Ekwall <bj0rn@blox.se>   This file is part of the Linux modutils.   This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the   Free Software Foundation; either version 2 of the License, or (at your   option) any later version.   This program is distributed in the hope that it will be useful, but   WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software Foundation,   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */%{#include <assert.h>#include <malloc.h>#include "genksyms.h"static int is_typedef;static int is_extern;static char *current_name;static struct string_list *decl_spec;static void yyerror(const char *);static inline voidremove_node(struct string_list **p){  struct string_list *node = *p;  *p = node->next;  free_node(node);}static inline voidremove_list(struct string_list **pb, struct string_list **pe){  struct string_list *b = *pb, *e = *pe;  *pb = e;  free_list(b, e);}%}%token ASM_KEYW%token ATTRIBUTE_KEYW%token AUTO_KEYW%token BOOL_KEYW%token CHAR_KEYW%token CONST_KEYW%token DOUBLE_KEYW%token ENUM_KEYW%token EXTERN_KEYW%token EXTENSION_KEYW%token FLOAT_KEYW%token INLINE_KEYW%token INT_KEYW%token LONG_KEYW%token REGISTER_KEYW%token RESTRICT_KEYW%token SHORT_KEYW%token SIGNED_KEYW%token STATIC_KEYW%token STRUCT_KEYW%token TYPEDEF_KEYW%token UNION_KEYW%token UNSIGNED_KEYW%token VOID_KEYW%token VOLATILE_KEYW%token TYPEOF_KEYW%token EXPORT_SYMBOL_KEYW%token ASM_PHRASE%token ATTRIBUTE_PHRASE%token BRACE_PHRASE%token BRACKET_PHRASE%token EXPRESSION_PHRASE%token CHAR%token DOTS%token IDENT%token INT%token REAL%token STRING%token TYPE%token OTHER%token FILENAME%%declaration_seq:	declaration	| declaration_seq declaration	;declaration:	{ is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; }	declaration1	{ free_list(*$2, NULL); *$2 = NULL; }	;declaration1:	EXTENSION_KEYW TYPEDEF_KEYW { is_typedef = 1; } simple_declaration		{ $$ = $4; }	| TYPEDEF_KEYW { is_typedef = 1; } simple_declaration		{ $$ = $3; }	| simple_declaration	| function_definition	| asm_definition	| export_definition	| error ';'				{ $$ = $2; }	| error '}'				{ $$ = $2; }	;simple_declaration:	decl_specifier_seq_opt init_declarator_list_opt ';'		{ if (current_name) {		    struct string_list *decl = (*$3)->next;		    (*$3)->next = NULL;		    add_symbol(current_name,			       is_typedef ? SYM_TYPEDEF : SYM_NORMAL,			       decl, is_extern);		    current_name = NULL;		  }		  $$ = $3;		}	;init_declarator_list_opt:	/* empty */				{ $$ = NULL; }	| init_declarator_list	;init_declarator_list:	init_declarator		{ struct string_list *decl = *$1;		  *$1 = NULL;		  add_symbol(current_name,			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);		  current_name = NULL;		  $$ = $1;		}	| init_declarator_list ',' init_declarator		{ struct string_list *decl = *$3;		  *$3 = NULL;		  free_list(*$2, NULL);		  *$2 = decl_spec;		  add_symbol(current_name,			     is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);		  current_name = NULL;		  $$ = $3;		}	;init_declarator:	declarator asm_phrase_opt attribute_opt initializer_opt		{ $$ = $4 ? $4 : $3 ? $3 : $2 ? $2 : $1; }	;/* Hang on to the specifiers so that we can reuse them.  */decl_specifier_seq_opt:	/* empty */				{ decl_spec = NULL; }	| decl_specifier_seq	;decl_specifier_seq:	decl_specifier				{ decl_spec = *$1; }	| decl_specifier_seq decl_specifier	{ decl_spec = *$2; }	;decl_specifier:	storage_class_specifier		{ /* Version 2 checksumming ignores storage class, as that		     is really irrelevant to the linkage.  */		  remove_node($1);		  $$ = $1;		}	| type_specifier	;storage_class_specifier:	AUTO_KEYW	| REGISTER_KEYW	| STATIC_KEYW	| EXTERN_KEYW	{ is_extern = 1; $$ = $1; }	| INLINE_KEYW	{ is_extern = 0; $$ = $1; }	;type_specifier:	simple_type_specifier	| cvar_qualifier	| TYPEOF_KEYW '(' decl_specifier_seq '*' ')'	| TYPEOF_KEYW '(' decl_specifier_seq ')'	/* References to s/u/e's defined elsewhere.  Rearrange things	   so that it is easier to expand the definition fully later.  */	| STRUCT_KEYW IDENT		{ remove_node($1); (*$2)->tag = SYM_STRUCT; $$ = $2; }	| UNION_KEYW IDENT		{ remove_node($1); (*$2)->tag = SYM_UNION; $$ = $2; }	| ENUM_KEYW IDENT		{ remove_node($1); (*$2)->tag = SYM_ENUM; $$ = $2; }	/* Full definitions of an s/u/e.  Record it.  */	| STRUCT_KEYW IDENT class_body		{ struct string_list *s = *$3, *i = *$2, *r;		  r = copy_node(i); r->tag = SYM_STRUCT;		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL;		  add_symbol(i->string, SYM_STRUCT, s, is_extern);		  $$ = $3;		}	| UNION_KEYW IDENT class_body		{ struct string_list *s = *$3, *i = *$2, *r;		  r = copy_node(i); r->tag = SYM_UNION;		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL;		  add_symbol(i->string, SYM_UNION, s, is_extern);		  $$ = $3;		}	| ENUM_KEYW IDENT BRACE_PHRASE		{ struct string_list *s = *$3, *i = *$2, *r;		  r = copy_node(i); r->tag = SYM_ENUM;		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL;		  add_symbol(i->string, SYM_ENUM, s, is_extern);		  $$ = $3;		}	/* Anonymous s/u/e definitions.  Nothing needs doing.  */	| ENUM_KEYW BRACE_PHRASE			{ $$ = $2; }	| STRUCT_KEYW class_body			{ $$ = $2; }	| UNION_KEYW class_body				{ $$ = $2; }	;simple_type_specifier:	CHAR_KEYW	| SHORT_KEYW	| INT_KEYW	| LONG_KEYW	| SIGNED_KEYW	| UNSIGNED_KEYW	| FLOAT_KEYW	| DOUBLE_KEYW	| VOID_KEYW	| BOOL_KEYW	| TYPE			{ (*$1)->tag = SYM_TYPEDEF; $$ = $1; }	;ptr_operator:	'*' cvar_qualifier_seq_opt		{ $$ = $2 ? $2 : $1; }	;cvar_qualifier_seq_opt:	/* empty */					{ $$ = NULL; }	| cvar_qualifier_seq	;cvar_qualifier_seq:	cvar_qualifier	| cvar_qualifier_seq cvar_qualifier		{ $$ = $2; }	;cvar_qualifier:	CONST_KEYW | VOLATILE_KEYW | ATTRIBUTE_PHRASE	| RESTRICT_KEYW		{ /* restrict has no effect in prototypes so ignore it */		  remove_node($1);		  $$ = $1;		}	;declarator:	ptr_operator declarator			{ $$ = $2; }	| direct_declarator	;direct_declarator:	IDENT		{ if (current_name != NULL) {		    error_with_pos("unexpected second declaration name");		    YYERROR;		  } else {		    current_name = (*$1)->string;		    $$ = $1;		  }		}	| direct_declarator '(' parameter_declaration_clause ')'		{ $$ = $4; }	| direct_declarator '(' error ')'		{ $$ = $4; }	| direct_declarator BRACKET_PHRASE		{ $$ = $2; }	| '(' declarator ')'		{ $$ = $3; }	| '(' error ')'		{ $$ = $3; }	;/* Nested declarators differ from regular declarators in that they do   not record the symbols they find in the global symbol table.  */nested_declarator:	ptr_operator nested_declarator		{ $$ = $2; }	| direct_nested_declarator	;direct_nested_declarator:	IDENT	| TYPE	| direct_nested_declarator '(' parameter_declaration_clause ')'		{ $$ = $4; }	| direct_nested_declarator '(' error ')'		{ $$ = $4; }	| direct_nested_declarator BRACKET_PHRASE		{ $$ = $2; }	| '(' nested_declarator ')'		{ $$ = $3; }	| '(' error ')'		{ $$ = $3; }	;parameter_declaration_clause:	parameter_declaration_list_opt DOTS		{ $$ = $2; }	| parameter_declaration_list_opt	| parameter_declaration_list ',' DOTS		{ $$ = $3; }	;parameter_declaration_list_opt:	/* empty */					{ $$ = NULL; }	| parameter_declaration_list	;parameter_declaration_list:	parameter_declaration	| parameter_declaration_list ',' parameter_declaration		{ $$ = $3; }	;parameter_declaration:	decl_specifier_seq m_abstract_declarator		{ $$ = $2 ? $2 : $1; }	;m_abstract_declarator:	ptr_operator m_abstract_declarator		{ $$ = $2 ? $2 : $1; }	| direct_m_abstract_declarator	;direct_m_abstract_declarator:	/* empty */					{ $$ = NULL; }	| IDENT		{ /* For version 2 checksums, we don't want to remember		     private parameter names.  */		  remove_node($1);		  $$ = $1;		}	/* This wasn't really a typedef name but an identifier that	   shadows one.  */	| TYPE		{ remove_node($1);		  $$ = $1;		}	| direct_m_abstract_declarator '(' parameter_declaration_clause ')'		{ $$ = $4; }	| direct_m_abstract_declarator '(' error ')'		{ $$ = $4; }	| direct_m_abstract_declarator BRACKET_PHRASE		{ $$ = $2; }	| '(' m_abstract_declarator ')'		{ $$ = $3; }	| '(' error ')'		{ $$ = $3; }	;function_definition:	decl_specifier_seq_opt declarator BRACE_PHRASE		{ struct string_list *decl = *$2;		  *$2 = NULL;		  add_symbol(current_name, SYM_NORMAL, decl, is_extern);		  $$ = $3;		}	;initializer_opt:	/* empty */					{ $$ = NULL; }	| initializer	;/* We never care about the contents of an initializer.  */initializer:	'=' EXPRESSION_PHRASE		{ remove_list($2, &(*$1)->next); $$ = $2; }	;class_body:	'{' member_specification_opt '}'		{ $$ = $3; }	| '{' error '}'					{ $$ = $3; }	;member_specification_opt:	/* empty */					{ $$ = NULL; }	| member_specification	;member_specification:	member_declaration	| member_specification member_declaration	{ $$ = $2; }	;member_declaration:	decl_specifier_seq_opt member_declarator_list_opt ';'		{ $$ = $3; }	| error ';'		{ $$ = $2; }	;member_declarator_list_opt:	/* empty */					{ $$ = NULL; }	| member_declarator_list	;member_declarator_list:	member_declarator	| member_declarator_list ',' member_declarator	{ $$ = $3; }	;member_declarator:	nested_declarator attribute_opt			{ $$ = $2 ? $2 : $1; }	| IDENT member_bitfield_declarator		{ $$ = $2; }	| member_bitfield_declarator	;member_bitfield_declarator:	':' EXPRESSION_PHRASE				{ $$ = $2; }	;attribute_opt:	/* empty */					{ $$ = NULL; }	| ATTRIBUTE_PHRASE	;asm_definition:	ASM_PHRASE ';'					{ $$ = $2; }	;asm_phrase_opt:	/* empty */					{ $$ = NULL; }	| ASM_PHRASE	;export_definition:	EXPORT_SYMBOL_KEYW '(' IDENT ')' ';'		{ export_symbol((*$3)->string); $$ = $5; }	;%%static voidyyerror(const char *e){  error_with_pos("%s", e);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -