📄 ytab.c
字号:
print_exception(n, "Fatal Error ME", format, ap); exit(1);}/* Print message for fatal error that occured in the rules() function. */void fatal(int n, char *format, ...){ va_list ap; va_start(ap, format); print_exception(n, "Fatal Error E", format, ap); exit(1);}/* Print message for internal warning. */static void int_warn(int n, char *format, ...){ va_list ap; if (!option(NO_WARNINGS_OPT_CHAR)) { va_start(ap, format); print_exception(n, "Warning MW", format, ap); }}/* Print message for warning that occured in the rules() function. */void warn(int n, char *format, ...){ va_list ap; if (!option(NO_WARNINGS_OPT_CHAR)) { va_start(ap, format); print_exception(n, "Warning W", format, ap); }}/* Function called by YACC when it detects an error. */void yyerror(char *s){#ifdef DEBUG_TYPEDEF /* Used for debugging typedef processing. */ typedef_symbol_table_dump();#endif int_fatal(0, "%s", s);}/* Add type name to the typedef symbol table. */static void typedef_symbol_table_add(char *p_symbol){ TYPEDEF_SYM_BLK *block; /* Allocate room for string and its '\0' terminator. */ char *str_buf = (char *)malloc(strlen(p_symbol) + 1); if (str_buf == NULL) int_fatal(E_NO_HEAP); /* Make copy of argument. */ strcpy(str_buf, p_symbol); /* Is symbol table empty? */ if (typedef_sym_tbl_head == NULL) { /* Allocate first block and make the head of the table list. */ typedef_sym_tbl_head = block = (TYPEDEF_SYM_BLK *)malloc(sizeof *block); if (block == NULL) int_fatal(E_NO_HEAP); block->total = 0; block->next = NULL; } else { TYPEDEF_SYM_BLK *prev_block; /* Find first block in symbol-table list that isn't full. */ for (prev_block = NULL, block = typedef_sym_tbl_head; block != NULL && block->total == DIM_OF(block->id); prev_block = block, block = block->next) ; /* If all blocks are full, allocate a new one and append to list. */ if (block == NULL) { block = (TYPEDEF_SYM_BLK *)malloc(sizeof *block); if (block == NULL) int_fatal(E_NO_HEAP); block->total = 0; block->next = NULL; if (prev_block == NULL) typedef_sym_tbl_head = block; else prev_block->next = block; } } /* Save pointer to the new type name in first empty slot of this block. */ block->id[block->total++] = str_buf;}/* Return TRUE if symbol exists in the typedef symbol table. */BOOLEAN typedef_symbol_table_find(char *p_symbol){ TYPEDEF_SYM_BLK *block; BOOLEAN found = FALSE; /* Loop for each block of symbols. */ for (block = typedef_sym_tbl_head; block != NULL; block = block->next) { unsigned i; /* Loop for each symbol in this block. */ for (i = 0; i < block->total; ++i) if (strcmp(block->id[i], p_symbol) == 0) found = TRUE; } return found;}/* Remove all symbols (and symbol blocks) from the symbol table--make the table empty.*/void typedef_symbol_table_flush(void){ TYPEDEF_SYM_BLK *block; /* Loop for each block of symbols. */ for (block = typedef_sym_tbl_head; block != NULL; ) { unsigned i; TYPEDEF_SYM_BLK *temp_block; /* Loop for each symbol in this block. */ for (i = 0; i < block->total; ++i) free(block->id[i]); /* Free symbol. */ temp_block = block->next; free(block); /* Free block now that it's empty. */ block = temp_block; } typedef_sym_tbl_head = NULL;}#ifdef DEBUG_TYPEDEF/* Display the contents of the typedef symbol table. Used for debugging typedef processing.*/void typedef_symbol_table_dump(void){ TYPEDEF_SYM_BLK *block; fputs("typedef symbol table dump:\n", out_fp); /* Loop for each block of symbols. */ for (block = typedef_sym_tbl_head; block != NULL; block = block->next) { unsigned i; /* Loop for each symbol in this block. */ for (i = 0; i < block->total; ++i) fprintf(out_fp, "%s\n", block->id[i]); }}#endif/* Record that the last statement was a case label. */static void case_label(void){ is_case_label = TRUE;}/* Record that the last statement was not a case label. If the previous statement was a case label, increment the decision-point counter--this ends a run of adjacent case labels which count as one decision point.*/static void not_case_label(void){ if (is_case_label) { is_case_label = FALSE; ++fcn_decisions; /* This is a decision point. */ }}/* Initialize parser. */void init_yacc(void){ /* Make the typedef symbol table empty. */ typedef_symbol_table_flush(); /* See the definition of each of these variables, above, for more information. */ is_typedef = FALSE; nested_decl_specs = 0; is_case_label = FALSE; function_name[0] = '\0'; last_ident[0] = '\0'; last_decl[0] = '\0'; mod_decisions = 0; mod_conditions = 0; mod_functions = 0; is_else = is_if = FALSE; looking_for_tag = FALSE; is_within_function = FALSE; current_operator = ""; current_keyword = ""; current_identifier = ""; current_type_name = "";}/* Returns 1 if the indicated option character was specified on the command line. E.g., for -S, it would return 1 for option('S'). If option character is immediately followed by a decimal integer, this function will instead return the value of that number, e.g. for -S3, it would return 3. NOTE: 0 would be ambiguous, e.g., -S0, because 0 would also be returned if -S were not specified.*/int option(int opt_char){ char *opt_str = str_option(opt_char); return opt_str == NULL ? 0 : strlen(opt_str) == 0 ? 1 : atoi(opt_str);}/* Returns pointer to the part of an option following the option character. E.g., for -Xabc=def, it would point to the "abc=def" part.*/char *str_option(int opt_char){ unsigned i; /* (Skip the command itself, argv[0].) */ for (i = 1; i < cmd_line_argc; ++i) if (strchr(OPT_INTRO_CHARS, cmd_line_argv[i][0]) != NULL) if (cmd_line_argv[i][OPTION_START] == opt_char) break; return i < cmd_line_argc ? &cmd_line_argv[i][OPTION_STRING_START] : NULL;}/* Return pointer to the name of the next input file in the argv array starting with the argument that p_i points to. An input file name is distinguished from the command-line options by not starting with one of characters in the OPT_INTRO_CHARS string. NOTE: argument 0 is the name of the command, not the first argument, per se.*/char *get_next_input_file(unsigned *p_i){ for (++*p_i; *p_i < cmd_line_argc && strchr(OPT_INTRO_CHARS, cmd_line_argv[*p_i][0]) != NULL; ++*p_i) ; return *p_i < cmd_line_argc ? cmd_line_argv[*p_i] : NULL;}/* Return pointer to the original name of the next input file in the argv array starting with the argument that p_i points to. An original name is specified as a command-line option. That is how an original name is distinguished from the name of an actual input file NOTE: argument 0 is the name of the command, not the first argument, per se.*/char *get_next_input_file_orig_name(unsigned *p_i){ for (++*p_i; *p_i < cmd_line_argc; ++*p_i) if (strchr(OPT_INTRO_CHARS, cmd_line_argv[*p_i][0]) != NULL && cmd_line_argv[*p_i][OPTION_START] == SUBST_FILE_OPT_CHAR) break; return *p_i < cmd_line_argc ? &cmd_line_argv[*p_i][OPTION_STRING_START] : NULL;}/* Returns pointer to current module (file) name. */char *mod_name(void){ return input_file_orig_name;}/* Process the command-line options that affect the start of Metre. */static void check_starting_options(void){ static char *output_file_name; char *script_file_name; /* Get options from file rather than command line? */ script_file_name = str_option(SCRIPT_FILE_OPT_CHAR); if (script_file_name != NULL) get_options_from_file(script_file_name); /* Interleave the input with the output? */ display_input = option(COPY_INPUT_OPT_CHAR); /* Name of listing file to contain output. This for those OS's that don't support command-line redirection, e.g., VMS. */ output_file_name = str_option(LISTING_OPT_CHAR); if (output_file_name != NULL && strlen(output_file_name) > 0) { out_fp = fopen(output_file_name, "w"); if (out_fp == NULL) { out_fp = stdout; /* Restore to previous, good output file. */ int_fatal(E_CANT_OPEN_LISTING_FILE); /* Die. */ } }}/* Build a "fake" argument list and count, copy command name (argv[0]) to it, then append the options that are in the file to it. (Sneaky, aren't I?) (Perhaps the arguments from the file should be appended to whatever is on the command line. Maybe next time.)*/static void get_options_from_file(char *file){ FILE *cmd_fp; /* If other options on command line, generate warning but continue. Note: 2 = the command itself + the file option. */ if (cmd_line_argc > 2) int_warn(W_OPTIONS_IGNORED); /* Attempt to open the specified script file. */ if (strlen(file) == 0 || (cmd_fp = fopen(file, "r")) == NULL) int_fatal(E_CANT_OPEN_COMMAND_FILE); else { ARG *args = NULL, *args_tail = NULL; char buf[BUFSIZ]; /* Initialize argc to 1 for the command name which is carried over from the orginal argv. */ cmd_line_argc = 1; /* Loop for each line of input. */ while (fgets(buf, sizeof buf, cmd_fp) != NULL) { char *start; /* Buffer address 1st time through loop, then NULL. */ char *token; /* Pointer to token in buffer. */ /* Loop for each token in this line of input. */ for (start = buf; (token = strtok(start, WHITE_SPACE_CHARS)) != NULL; start = NULL) { ARG *arg; /* Allocate buffers for this argument and its string (including its '\0' terminator). */ if ((arg = (ARG *)malloc(sizeof *arg)) == NULL) int_fatal(E_NO_HEAP); if ((arg->string = (char *)malloc(strlen(token) + 1)) == NULL) int_fatal(E_NO_HEAP); /* Copy argument into string buffer. */ strcpy(arg->string, token); /* Attach this argument to end of argument linked list. */ if (args_tail == NULL) args = arg; else args_tail->next = arg; args_tail = arg; arg->next = NULL; ++cmd_line_argc; } } /* Allocate buffer for argv array then move arguments from linked list. */ build_new_argv(args); }}/* Build a new list of "command-line arguments" pointed to by cmd_line_argv. */static void build_new_argv(ARG *args){ unsigned i; char *argv_cmd_name; /* Save pointer to command name from original argv. */ argv_cmd_name = cmd_line_argv[0]; /* Allocate buffer to hold array of pointers to arguments. */ cmd_line_argv = (char **)malloc(cmd_line_argc * sizeof *cmd_line_argv); if (cmd_line_argv == NULL) int_fatal(E_NO_HEAP); /* Restore pointer to command name. */ cmd_line_argv[0] = argv_cmd_name; /* Fill in new argv from linked list of arguments, freeing list entries but not the strings from the list. (Skip the place for the "command" argument.) */ for (i = 1; i < cmd_line_argc; ++i) { ARG *arg; cmd_line_argv[i] = args->string; arg = args->next; free(args); args = arg; }}/* Print name, version, and copyright notice. */static void print_banner(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -