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

📄 ytab.c

📁 这是一个C程序分析工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* c:/mks\bin\yacc -d gram.y */#line 1 "gram.y"/*************************************************************   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 *);#define TK_IDENTIFIER	257#define TK_CONSTANT	258#define TK_STRING_LITERAL	259#define TK_SIZEOF	260#define TK_PTR_OP	261#define TK_INC_OP	262#define TK_DEC_OP	263#define TK_LEFT_OP	264#define TK_RIGHT_OP	265#define TK_LE_OP	266#define TK_GE_OP	267#define TK_EQ_OP	268#define TK_NE_OP	269#define TK_AND_OP	270#define TK_OR_OP	271#define TK_MUL_ASSIGN	272#define TK_DIV_ASSIGN	273#define TK_MOD_ASSIGN	274#define TK_ADD_ASSIGN	275#define TK_SUB_ASSIGN	276#define TK_LEFT_ASSIGN	277#define TK_RIGHT_ASSIGN	278#define TK_AND_ASSIGN	279#define TK_XOR_ASSIGN	280#define TK_OR_ASSIGN	281#define TK_TYPE_NAME	282#define TK_TYPEDEF	283#define TK_EXTERN	284#define TK_STATIC	285#define TK_AUTO	286#define TK_REGISTER	287#define TK_CHAR	288#define TK_SHORT	289#define TK_INT	290#define TK_LONG	291#define TK_SIGNED	292#define TK_UNSIGNED	293#define TK_FLOAT	294#define TK_DOUBLE	295#define TK_CONST	296#define TK_VOLATILE	297#define TK_VOID	298#define TK_STRUCT	299#define TK_UNION	300#define TK_ENUM	301#define TK_ELIPSIS	302#define TK_RANGE	303#define TK_CASE	304#define TK_DEFAULT	305#define TK_IF	306#define TK_ELSE	307#define TK_SWITCH	308#define TK_WHILE	309#define TK_DO	310#define TK_FOR	311#define TK_GOTO	312#define TK_CONTINUE	313#define TK_BREAK	314#define TK_RETURN	315#define THEN	316extern int yychar, yyerrflag;#ifndef YYSTYPE#define YYSTYPE int#endifextern YYSTYPE yyval;extern YYSTYPE yylval;#line 1472 "gram.y"/* Functions. */int main(int main_argc, char *main_argv[]){   ZERO(grm);   ZERO(int_grm);   /* Input not determined yet. */   yyin = NULL;   /* Use stdout until/if output is redirected with command-line option. */   out_fp = stdout;   /* Fire the need-command-name trigger. */   ZERO(int_prj);   int_prj.need_cmd_name = TRUE;   fire_prj();   int_prj.need_cmd_name = FALSE;   print_banner();   /* Save so that the argument list may be accessed globally. */   cmd_line_argv = main_argv;   cmd_line_argc = main_argc;   /* Get command-line options that affect Metre at the start. */   check_starting_options();   /* Initialize YACC and Lex. */   init_yacc();   init_lex();   if (option(HELP_OPT_CHAR))      print_help();   else   {      /*         Look for the first input file and first original name of that         input file.      */      next_cmd_line_file = 0;      next_cmd_line_file_orig_n = 0;      if ((input_file = get_next_input_file(&next_cmd_line_file)) != NULL)         if ((yyin = fopen(input_file, "r")) != NULL)            begin_project(input_file);         else            int_warn(W_CANNOT_OPEN_FILE, input_file);      else         /* Since no input file specified on command line, process stdin. */         begin_project("stdin");   }   return RETURN_FROM_MAIN_VALUE;}/* Begin the project by firing initial triggers and calling parser. */static void begin_project(char *input_file){   input_file_orig_name =         get_next_input_file_orig_name(&next_cmd_line_file_orig_n);   /* If no original name given, use the actual as the original, also. */   if (input_file_orig_name == NULL)      input_file_orig_name = input_file;   /* Fire the beginning-of-project trigger. */   ZERO(int_prj);   int_prj.begin = TRUE;   fire_prj();   int_prj.begin = FALSE;   /* Fire the beginning-of-module trigger. */   ZERO(int_mod);   int_mod.begin = TRUE;   fire_mod();   int_mod.begin = FALSE;   /*      Call the YACC-generated parser to wade through the input file(s).      When all done, close the last input file. yywrap() could have      opened any number of subsequent input files.   */   yyparse();   fclose(yyin);}/* Common exception-handling function. */static void print_exception(int n, char *severity_str, char *format, va_list ap){   fflush(out_fp);   /*      Display input line if supposed to, then display line with marker      character in it if appropriate.   */   if (mod_name() != NULL && strlen(mod_name()) > 0 &&         !int_mod.end && !int_fcn.end)   {      if (!display_input)         fputs(line(), out_fp);      if (!int_lin.end)         fputs(marker(), out_fp);   }   /*      Display module name and line number if a module name has been      established. If one hasn't, the error must not relate to a      location in the input file.   */   if (mod_name() != NULL && strlen(mod_name()) > 0)      fprintf(out_fp, "%s(%u): ", mod_name(), lineno());   fprintf(out_fp, "%s%04u: ", severity_str, n);   vfprintf(out_fp, format, ap);   fputc('\n', out_fp);}/* Print message for internal fatal error. */void int_fatal(int n, char *format, ...){   va_list ap;   va_start(ap, format);

⌨️ 快捷键说明

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