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

📄 gram.y

📁 这是一个C程序分析工具
💻 Y
📖 第 1 页 / 共 4 页
字号:
%{/*************************************************************   Copyright (c) 1993-1995 by Paul Long  All rights reserved.**************************************************************//*************************************************************   gram.y - This source file contains the YACC grammar and            actions for Metre's Standard C parser. It also            contains main(), error-handling functions,            trigger-firing functions, functions that            maintain the typedef symbol table, functions            that administer the execution of Metre,            functions that can be called from the rules()            function, and a replacement for YACC's            yyerror(). As you can see, most of the grammar            rules have no actions. This is because the            grammar is largely used to just skip over the            parts of C that Metre doesn't care about.**************************************************************/#include <stdio.h>#include <limits.h>#include <stdarg.h>#include <stdlib.h>#include "metreint.h"/*   NOTE: Someone said that that the default stack size for MKS yacc and   AT&T (SCO) yacc of 150 was not sufficient for the code he was running   through Metre, so he redefined the stack size to 1000. If you   encounter the same situation, use one of the following directives to   increase the stack size for the the version of yacc that you're   using.*/#if 0#define YYSSIZE      1000  /* MKS yacc stack size */#define YYMAXDEPTH   1000  /* AT&T yacc stack size */#endif/* String containing all of the white-space characters. */#define WHITE_SPACE_CHARS  " \t\r\n\v\f"/* VMS has different ideas about what constitutes a successful return value. */#ifdef VAX#define RETURN_FROM_MAIN_VALUE 1#else#define RETURN_FROM_MAIN_VALUE 0#endif/* External-function prototypes. *//* Defines behavior for this Metre tool. */extern void rules(void);/* YACC-generated parser function. */extern yyparse();/* lex-generated scanner function. */extern yylex();/* Error function that yacc-generated parser calls. */extern void yyerror(char *);/* External variables. *//*   Metre maintains statistics in the int_* structures, e.g., int_prj.   The structures with the unadorned names, e.g., prj, are used to   communicate with the rules. They are zero-filled except when a   trigger is being fired. At that time, the contents of the   corresponding int_* structure is copied to it, the rules() function   is called, and then the structure is zero-filed again.*/PRJ prj, int_prj;    /* Project. */MOD mod, int_mod;    /* Module. */FCN fcn;             /* Function. */static FCN int_fcn;STM stm;             /* Statement. */static STM int_stm;LIN lin, int_lin;    /* Line. */GRM grm, int_grm;    /* Grammatical. */LEX lex, int_lex;    /* Lexical. *//*   Which command-line argument (argv) at which to start looking for the   next file name to process and original file name, respectively.*/unsigned next_cmd_line_file;unsigned next_cmd_line_file_orig_n;/* Number of decision points, conditions, and functions in module (file). */unsigned mod_decisions;unsigned mod_conditions;unsigned mod_functions;/*   Indicates whether we are looking for a tag. Parser writes it, lexer   reads it. Since tags are in a separate name space from other   identifiers, this helps the lexer determine whether a lexeme is an   identifier or a type name.*/BOOLEAN looking_for_tag;/*   Indicates whether we are within a function definition. Used to   determine whether to use the last identifier as the function name.*/BOOLEAN is_within_function;/*   Name of current input file and name of original file, if specified on   command line with the substitute-file-name option. If substitute not   provided, input_file_orig_name points to the same name as input_file.*/char *input_file;char *input_file_orig_name;/* Where all output is written. */FILE *out_fp;static char *command_name = DEFAULT_COMMAND_NAME;/* Global versions of main's argc and argv. */int cmd_line_argc;char **cmd_line_argv;/*   Block within which typedef type names are held in the typedef   symbol-table.*/typedef struct typedef_sym_blk {   struct typedef_sym_blk *next;          /* Next block. */   unsigned total;                        /* Total in this block. */   char *id[TYPEDEF_SYMBOLS_PER_BLOCK]; /* Array of pointers to type names. */} TYPEDEF_SYM_BLK;/*   Head of the typedef symbol-table. NOTE: This is the only symbol table   in Metre, and it is used just to hold typedef type names, not all   symbols.*/TYPEDEF_SYM_BLK *typedef_sym_tbl_head = NULL;/* Command-line argument. Used to hold arguments taken from script file. */typedef struct arg {   struct arg *next;   char *string;} ARG;/* Static variables. *//* Control depth--current number of nested control structures. */static unsigned depth;/* Used to determine how many statements are on a line. */static unsigned previous_statements_line_number;/* Number of decision points and conditions in function. */static unsigned fcn_decisions;static unsigned fcn_conditions;/*   Metre maintains the number of statements appearing on a line. The   is_if and is_else BOOLEANs are used principally to relax the criteria   for what constitutes a statement. For example, "else if," is not   considered two statements because this is a common idiom.*/static BOOLEAN is_else, is_if;/*   is_typedef indicates whether we are parsing a typedef. Since typedefs   cannot be nested, it's okay that this is just a BOOLEAN. This is used   to find the type name of a typedef so that it can be added to the   typedef symbol table. If the type name is subsequently encountered by   the lexer, the lexer returns a token for a type name rather than for   an identifier. This is the ugly part of C that cannot practically be   expressed by a YACC grammar specification.*/static BOOLEAN is_typedef;/*   nested_decl_specs is used to distinguish the name of the thing being   declared, such as the type name in a typedef, from other identifiers   in the declaration.*/static unsigned nested_decl_specs;/*   Whether the last statement was a case label. Used to consider   adjacent case labels as one decision point. The transition from   is_case_label==TRUE to is_case_label==FALSE is a decision point,   instead of each case label being a decision point. Adjacent case   labels are considered one decision point because this is analogous to   an if statement with or logical operators, ||. For example,      switch (expr) {      case 5:      case 10:         a;      }   is, in this regard, analogous to      if (expr == 5 || expr == 10)         a;   I did not want to bias the metric against the switch statement.*/static BOOLEAN is_case_label;static IDENTIFIER function_name;static IDENTIFIER last_ident;static IDENTIFIER last_decl;/*   Pointer to current operator, keyword, or identifier as passed to   rules if such a token is encountered.*/static char *current_operator;static char *current_keyword;static char *current_identifier;static char *current_type_name;/* Static function declarations. */static void begin_project(char *);static void fire_fcn(void);static void fire_stm(void);static void print_exception(int, char *, char *, va_list);static void typedef_symbol_table_add(char *);static void case_label(void);static void not_case_label(void);static void check_starting_options(void);static void print_banner(void);static void print_help(void);static void stat_func_begin(void);static void stat_func_end(void);static void check_multiple_statements(void);static void int_warn(int, char *, ...);static void fire_operator(void);static void fire_keyword(void);static void fire_identifier(void);static void fire_declarator(void);static void fire_type_name(void);static void found_constant(void);static void found_string(void);static void found_expression_statement(BOOLEAN);static void function_call(void);static void after_compound_declarations(void);static void before_compound_declarations(void);static void after_initializer(void);static void before_initializer(void);static void get_options_from_file(char *);static void build_new_argv(ARG *);%}%token TK_IDENTIFIER TK_CONSTANT TK_STRING_LITERAL TK_SIZEOF%token TK_PTR_OP TK_INC_OP TK_DEC_OP TK_LEFT_OP TK_RIGHT_OP%token TK_LE_OP TK_GE_OP TK_EQ_OP TK_NE_OP%token TK_AND_OP TK_OR_OP TK_MUL_ASSIGN TK_DIV_ASSIGN TK_MOD_ASSIGN%token TK_ADD_ASSIGN TK_SUB_ASSIGN TK_LEFT_ASSIGN TK_RIGHT_ASSIGN TK_AND_ASSIGN%token TK_XOR_ASSIGN TK_OR_ASSIGN TK_TYPE_NAME%token TK_TYPEDEF TK_EXTERN TK_STATIC TK_AUTO TK_REGISTER%token TK_CHAR TK_SHORT TK_INT TK_LONG TK_SIGNED TK_UNSIGNED%token TK_FLOAT TK_DOUBLE TK_CONST TK_VOLATILE TK_VOID%token TK_STRUCT TK_UNION TK_ENUM TK_ELIPSIS TK_RANGE%token TK_CASE TK_DEFAULT TK_IF TK_ELSE TK_SWITCH TK_WHILE TK_DO TK_FOR%token TK_GOTO TK_CONTINUE TK_BREAK TK_RETURN%start translation_unit/* Used to disambiguate if from if/else. */%nonassoc THEN%nonassoc TK_ELSE%%tk_lparen   : '('      { fire_operator(); }   ;tk_rparen   : ')'      { fire_operator(); }   ;tk_lsquare_brace   : '['      { fire_operator(); }   ;tk_rsquare_brace   : ']'      { fire_operator(); }   ;tk_dot   : '.'      { fire_operator(); }   ;tk_ptr_to   : TK_PTR_OP      { fire_operator(); }   ;tk_inc   : TK_INC_OP      { fire_operator(); }   ;tk_dec   : TK_DEC_OP      { fire_operator(); }   ;tk_comma   : ','      { fire_operator(); }   ;tk_sizeof   : TK_SIZEOF      { fire_keyword(); }   ;tk_ampersand   : '&'      { fire_operator(); }   ;tk_asterisk   : '*'      { fire_operator(); }   ;tk_plus   : '+'      { fire_operator(); }   ;tk_minus   : '-'      { fire_operator(); }   ;tk_tilde   : '~'      { fire_operator(); }   ;tk_exclamation   : '!'      { fire_operator(); }   ;tk_slash   : '/'      { fire_operator(); }   ;tk_percent   : '%'      { fire_operator(); }   ;tk_left   : TK_LEFT_OP      { fire_operator(); }   ;tk_right   : TK_RIGHT_OP      { fire_operator(); }   ;tk_lt   : '<'      { fire_operator(); }   ;tk_gt   : '>'      { fire_operator(); }   ;tk_le   : TK_LE_OP      { fire_operator(); }   ;tk_ge   : TK_GE_OP      { fire_operator(); }   ;tk_eq   : TK_EQ_OP      { fire_operator(); }   ;tk_ne   : TK_NE_OP      { fire_operator(); }   ;tk_circumflex   : '^'      { fire_operator(); }   ;tk_bar   : '|'      { fire_operator(); }   ;tk_land   : TK_AND_OP      { fire_operator(); }   ;tk_lor   : TK_OR_OP      { fire_operator(); }   ;tk_question   : '?'      { fire_operator(); }   ;tk_colon   : ':'      { fire_operator(); }   ;tk_assign   : '='      { fire_operator(); }   ;tk_mul_assign   : TK_MUL_ASSIGN      { fire_operator(); }   ;tk_div_assign   : TK_DIV_ASSIGN      { fire_operator(); }   ;tk_mod_assign   : TK_MOD_ASSIGN      { fire_operator(); }   ;tk_add_assign   : TK_ADD_ASSIGN      { fire_operator(); }   ;tk_sub_assign   : TK_SUB_ASSIGN      { fire_operator(); }   ;tk_left_assign   : TK_LEFT_ASSIGN      { fire_operator(); }   ;tk_right_assign   : TK_RIGHT_ASSIGN      { fire_operator(); }   ;tk_and_assign   : TK_AND_ASSIGN      { fire_operator(); }   ;tk_xor_assign   : TK_XOR_ASSIGN      { fire_operator(); }   ;tk_or_assign   : TK_OR_ASSIGN      { fire_operator(); }   ;tk_semicolon   : ';'      { fire_operator(); }   ;tk_typedef   : TK_TYPEDEF      { fire_keyword(); }   ;tk_extern   : TK_EXTERN      { fire_keyword(); }   ;tk_static   : TK_STATIC      { fire_keyword(); }   ;tk_auto   : TK_AUTO      { fire_keyword(); }   ;tk_register   : TK_REGISTER      { fire_keyword(); }   ;tk_char   : TK_CHAR      { fire_keyword(); }   ;tk_short   : TK_SHORT      { fire_keyword(); }   ;tk_int   : TK_INT      { fire_keyword(); }   ;tk_long   : TK_LONG      { fire_keyword(); }   ;tk_signed   : TK_SIGNED      { fire_keyword(); }   ;tk_unsigned   : TK_UNSIGNED      { fire_keyword(); }   ;tk_float   : TK_FLOAT      { fire_keyword(); }   ;tk_double   : TK_DOUBLE      { fire_keyword(); }   ;tk_const   : TK_CONST      { fire_keyword(); }   ;tk_volatile   : TK_VOLATILE      { fire_keyword(); }   ;tk_void   : TK_VOID      { fire_keyword(); }   ;tk_struct   : TK_STRUCT      { fire_keyword(); }   ;tk_union   : TK_UNION      { fire_keyword(); }   ;tk_enum   : TK_ENUM      { fire_keyword(); }   ;tk_type_name   : TK_TYPE_NAME      { fire_type_name(); }   ;tk_lcurly_brace   : '{'      { fire_operator(); }

⌨️ 快捷键说明

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