/* Copyright (C) 1995 Bjoern Beutel. */ /* Description. =============================================================*/ /* Program to dump a compiled Malaga rule file with intermediate code. */ /* Includes. ================================================================*/ #include #include #include #include #include #include #include #include "basic.h" #include "pools.h" #include "values.h" #include "symbols.h" #include "files.h" #include "rule_type.h" #include "rules.h" #include "patterns.h" #include "hangul.h" /* Functions. ===============================================================*/ static void print_instruction( int_t pos, rule_sys_t *rule_sys ) /* Print the instruction at POS in RULE_SYS. */ { int_t opcode, info; string_t string; opcode = OPCODE( rule_sys->instrs[ pos ] ); info = INSTR_INFO( rule_sys->instrs[ pos ] ); switch (opcode) { case INS_SYSTEM_ERROR: switch (info) { case ASSERTION_ERROR: string = "assertion_error"; break; case NO_RETURN_ERROR: string = "no_return_error"; break; } printf( "error %s", string ); break; case INS_ERROR: printf( "error" ); break; case INS_TERMINATE: printf( "terminate" ); break; case INS_NOP: printf( "nop" ); break; case INS_TERMINATE_IF_NULL: printf( "terminate_if_null" ); break; case INS_ADD_END_STATE: printf( "add_end_state" ); break; case INS_ADD_STATE: string = rule_set_readable( rule_sys, info ); printf( "add_state %s", string ); free_mem( &string ); break; case INS_ADD_ALLO: printf( "add_allo" ); break; case INS_ACCEPT: printf( "accept" ); break; case INS_PUSH_NULL: printf( "push_null %d", info ); break; case INS_PUSH_VAR: printf( "push_var %d", info ); break; case INS_PUSH_CONST: string = value_to_readable( rule_sys->values + info, TRUE, 30 ); printf( "push_const %s", string ); free_mem( &string ); break; case INS_PUSH_SYMBOL: printf( "push_symbol %s", get_symbol_name( info ) ); break; case INS_PUSH_PATTERN_VAR: printf( "push_pattern_var %d", info ); break; case INS_POP: printf( "pop %d", info ); break; case INS_POP_TO: printf( "pop_to %d", info ); break; case INS_BUILD_LIST: printf( "build_list %d", info ); break; case INS_DECOMPOSE_LIST: printf( "decompose_list %d", info ); break; case INS_BUILD_RECORD: printf( "build_record %d", info ); break; case INS_BUILD_PATH: printf( "build_path %d", info ); break; case INS_DOT_OPERATION: printf( "dot_operation" ); break; case INS_PLUS_OPERATION: printf( "plus_operation" ); break; case INS_MINUS_OPERATION: printf( "minus_operation" ); break; case INS_ASTERISK_OPERATION: printf( "asterisk_operation" ); break; case INS_SLASH_OPERATION: printf( "slash_operation" ); break; case INS_UNARY_MINUS_OP: printf( "unary_minus_op" ); break; case INS_GET_ATTRIBUTE: printf( "get_attribute %s", get_symbol_name( info ) ); break; case INS_REMOVE_ATTRIBUTE: printf( "remove_attribute %s", get_symbol_name( info ) ); break; case INS_STD_FUNCTION: switch (info) { case FUNC_TO_ATOMS: string = "to_atoms"; break; case FUNC_IS_CAPITAL: string = "is_capital"; break; case FUNC_GET_LENGTH: string = "get_length"; break; case FUNC_TO_MULTI: string = "to_multi"; break; case FUNC_TO_SET: string = "to_set"; break; case FUNC_GET_SWITCH: string = "get_switch"; break; case FUNC_GET_VALUE_STRING: string = "get_value_string"; break; case FUNC_GET_VALUE_TYPE: string = "get_value_type"; break; case FUNC_TRANSMIT: string = "transmit"; break; case FUNC_FLOOR: string = "floor"; break; case FUNC_SUBSTRING: string = "substring"; break; default: complain( "Internal error." ); } printf( "std_function %s", string ); break; case INS_MATCH: string = new_string_readable( rule_sys->strings + info, NULL ); printf( "match %s", string ); free_mem( &string ); break; case INS_SET_VAR: printf( "set_var %d", info ); break; case INS_PLUS_VAR: printf( "plus_var %d", info ); break; case INS_MINUS_VAR: printf( "minus_var %d", info ); break; case INS_ASTERISK_VAR: printf( "asterisk_var %d", info ); break; case INS_SLASH_VAR: printf( "slash_var %d", info ); break; case INS_SET_VAR_PATH: printf( "set_var_path %d", info ); break; case INS_PLUS_VAR_PATH: printf( "plus_var_path %d", info ); break; case INS_MINUS_VAR_PATH: printf( "minus_var_path %d", info ); break; case INS_ASTERISK_VAR_PATH: printf( "asterisk_var_path %d", info ); break; case INS_SLASH_VAR_PATH: printf( "slash_var_path %d", info ); break; case INS_GET_1ST_ELEMENT: printf( "get_1st_element" ); break; case INS_ITERATE: printf( "iterate %d", info ); break; case INS_JUMP: printf( "jump %d", info ); break; case INS_JUMP_IF_EQUAL: printf( "jump_if_equal %d", info ); break; case INS_JUMP_IF_NOT_EQUAL: printf( "jump_if_not_equal %d", info ); break; case INS_JUMP_IF_CONGR: printf( "jump_if_congr %d", info ); break; case INS_JUMP_IF_NOT_CONGR: printf( "jump_if_not_congr %d", info ); break; case INS_JUMP_IF_IN: printf( "jump_if_in %d", info ); break; case INS_JUMP_IF_NOT_IN: printf( "jump_if_not_in %d", info ); break; case INS_JUMP_IF_LESS: printf( "jump_if_less %d", info ); break; case INS_JUMP_IF_NOT_LESS: printf( "jump_if_not_less %d", info ); break; case INS_JUMP_IF_GREATER: printf( "jump_if_greater %d", info ); break; case INS_JUMP_IF_NOT_GREATER: printf( "jump_if_not_greater %d", info ); break; case INS_JUMP_IF_NULL: printf( "jump_if_null %d", info ); break; case INS_JUMP_IF_NOT_NULL: printf( "jump_if_not_null %d", info ); break; case INS_JUMP_IF_YES: printf( "jump_if_yes %d", info ); break; case INS_JUMP_IF_NO: printf( "jump_if_no %d", info ); break; case INS_JUMP_NOW: printf( "jump_now %d", info ); break; case INS_JUMP_LATER: printf( "jump_later %d", info ); break; case INS_JUMP_SUBRULE: printf( "jump_subrule %s", rule_sys->strings + rule_sys->rules[ info ].name ); break; case INS_RETURN: printf( "return %d", info ); break; default: printf( "ILLEGAL INSTRUCTION %d", opcode ); break; } } /*---------------------------------------------------------------------------*/ static void print_rules( string_t source_name, rule_sys_t *rule_sys ) /* Print all rules of SOURCE_NAME. */ { string_t next_source_name; int_t instr, next_instr; int_t source_line, next_source_line; FILE *stream; int_t c; if (source_name != NULL) stream = open_stream( source_name, "r" ); else stream = NULL; source_line = 1; next_instr = next_source_line = 0; for (instr = 0; instr < rule_sys->instr_count; instr++) { if (stream != NULL) { if (instr >= next_instr) /* NEXT_INSTR has a new source location. */ { for (next_instr = instr; next_instr < rule_sys->instr_count; next_instr++) { source_of_instr( rule_sys, next_instr, &next_source_line, &next_source_name, NULL ); if (next_source_name != NULL && strcmp( name_in_path( next_source_name ), name_in_path( source_name ) ) == 0 && next_source_line > source_line) { break; } } } while (source_line < next_source_line) { c = getc( stream ); if (c == EOF) break; if (c == '\n') source_line++; putchar( c ); } } printf( "|%6d: ", instr ); print_instruction( instr, rule_sys ); printf( "\n" ); } if (stream != NULL) { /* Print remainder of source file. */ while ((c = getc( stream )) != EOF) putchar( c ); close_stream( &stream, source_name ); } } /* Top level functions. =====================================================*/ int main( int argc, char *argv[] ) /* The main function of "maldump". */ { rule_sys_t *rule_sys; string_t rule_file, symbol_file, source_file; int_t i; init_basic( "maldump" ); /* Parse arguments. */ if (argc == 2) { if (strcmp_no_case( argv[1], "--version" ) == 0 || strcmp_no_case( argv[1], "-version" ) == 0 || strcmp_no_case( argv[1], "-v" ) == 0) { program_message(); exit(0); } else if (strcmp_no_case( argv[1], "--help" ) == 0 || strcmp_no_case( argv[1], "-help" ) == 0 || strcmp_no_case( argv[1], "-h" ) == 0) { printf( "Dump a compiled rule file of a Malaga grammar.\n\n" "Usage:\n" "maldump SYM_FILE RULE_FILE " "-- Disassemble RULE_FILE on stdout.\n" "maldump -v[ersion] " "-- Print version information.\n" "maldump -h[elp] " "-- Print this help.\n\n" "SYM_FILE may end on \".sym\" or \".esym\".\n" "RULE_FILE may end on \".all\", \"mor\" or \"syn\".\n" "Option \"-s[ource] SOURCE_FILE\" gives " "a source file for RULE_FILE.\n" ); exit(0); } } rule_file = symbol_file = source_file = NULL; for (i = 1; i < argc; i++) { if (has_extension( argv[i], "all" ) || has_extension( argv[i], "mor" ) || has_extension( argv[i], "syn" )) { set_binary_file_name( &rule_file, argv[i] ); } else if (has_extension( argv[i], "sym" ) || has_extension( argv[i], "esym" )) { set_binary_file_name( &symbol_file, argv[i] ); } else if (strcmp_no_case( argv[i], "-source" ) == 0 || strcmp_no_case( argv[i], "-s" ) == 0) { if (argv[ ++i ] == NULL) complain( "Missing file name after \"-source\"." ); set_file_name( &source_file, argv[i] ); } else complain( "Illegal argument \"%s\".", argv[i] ); } if (rule_file == NULL) complain( "Missing rule file name." ); if (symbol_file == NULL) complain( "Missing symbol file name." ); init_values(); init_symbols( symbol_file ); rule_sys = read_rule_sys( rule_file ); init_hangul(); print_rules( source_file, rule_sys ); terminate_hangul(); free_rule_sys( &rule_sys ); terminate_symbols(); free_mem( &symbol_file ); free_mem( &rule_file ); free_mem( &source_file ); terminate_values(); terminate_patterns(); terminate_basic(); return 0; } /* End of file. =============================================================*/