Search
lxdream.org :: lxdream :: r948:545c85cc56f1
lxdream 0.9.1
released Jun 29
Download Now
changeset948:545c85cc56f1 lxdream-mem
parent947:aa80962d6439
child949:d7833018931f
authornkeynes
dateWed Jan 07 04:39:04 2009 +0000 (11 years ago)
branchlxdream-mem
Introduce sh4_finalize_instruction to clean-up on instruction exits
Remove the sh4_flush_icache special cases, now works through the
general case.
src/sh4/mmu.c
src/sh4/sh4.c
src/sh4/sh4core.h
src/sh4/sh4core.in
src/test/testsh4x86.c
src/tools/actparse.c
src/tools/gendec.c
src/tools/gendec.h
1.1 --- a/src/sh4/mmu.c Tue Jan 06 02:03:36 2009 +0000
1.2 +++ b/src/sh4/mmu.c Wed Jan 07 04:39:04 2009 +0000
1.3 @@ -277,7 +277,8 @@
1.4 // current block
1.5 mmu_set_tlb_enabled( val & MMUCR_AT );
1.6 MMIO_WRITE( MMU, MMUCR, val );
1.7 - sh4_flush_icache();
1.8 + sh4_core_exit( CORE_EXIT_FLUSH_ICACHE );
1.9 + xlat_flush_cache(); // If we're not running, flush the cache anyway
1.10 }
1.11 break;
1.12 case CCR:
2.1 --- a/src/sh4/sh4.c Tue Jan 06 02:03:36 2009 +0000
2.2 +++ b/src/sh4/sh4.c Wed Jan 07 04:39:04 2009 +0000
2.3 @@ -209,24 +209,15 @@
2.4 }
2.5 }
2.6 #endif
2.7 + if( exit_code != CORE_EXIT_EXCEPTION ) {
2.8 + sh4_finalize_instruction();
2.9 + }
2.10 // longjmp back into sh4_run_slice
2.11 sh4_running = FALSE;
2.12 longjmp(sh4_exit_jmp_buf, exit_code);
2.13 }
2.14 }
2.15
2.16 -void sh4_flush_icache()
2.17 -{
2.18 -#ifdef SH4_TRANSLATOR
2.19 - // FIXME: Special case needs to be generalized
2.20 - if( sh4_use_translator ) {
2.21 - if( sh4_translate_flush_cache() ) {
2.22 - longjmp(sh4_exit_jmp_buf, CORE_EXIT_CONTINUE);
2.23 - }
2.24 - }
2.25 -#endif
2.26 -}
2.27 -
2.28 void sh4_save_state( FILE *f )
2.29 {
2.30 if( sh4_use_translator ) {
2.31 @@ -377,10 +368,7 @@
2.32 sh4r.pc = sh4r.vbr + v; \
2.33 sh4r.new_pc = sh4r.pc + 2; \
2.34 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
2.35 - if( sh4r.in_delay_slot ) { \
2.36 - sh4r.in_delay_slot = 0; \
2.37 - sh4r.spc -= 2; \
2.38 - } \
2.39 + sh4r.in_delay_slot = 0; \
2.40 } \
2.41 return TRUE; } while(0)
2.42
3.1 --- a/src/sh4/sh4core.h Tue Jan 06 02:03:36 2009 +0000
3.2 +++ b/src/sh4/sh4core.h Wed Jan 07 04:39:04 2009 +0000
3.3 @@ -72,7 +72,7 @@
3.4
3.5
3.6 /**
3.7 - * SH4 vm-exit flag - exit the current block but continue (eg exception handling)
3.8 + * SH4 vm-exit flag - exit the current block but continue normally
3.9 */
3.10 #define CORE_EXIT_CONTINUE 1
3.11
3.12 @@ -239,6 +239,13 @@
3.13 gboolean FASTCALL sh4_raise_tlb_exception( int );
3.14 void FASTCALL sh4_accept_interrupt( void );
3.15
3.16 +/**
3.17 + * Complete the current instruction as part of a core exit. Prevents the
3.18 + * system from being left in an inconsistent state when an exit is
3.19 + * triggered during a memory write.
3.20 + */
3.21 +void sh4_finalize_instruction( void );
3.22 +
3.23 /* Status Register (SR) bits */
3.24 #define SR_MD 0x40000000 /* Processor mode ( User=0, Privileged=1 ) */
3.25 #define SR_RB 0x20000000 /* Register bank (priviledged mode only) */
4.1 --- a/src/sh4/sh4core.in Tue Jan 06 02:03:36 2009 +0000
4.2 +++ b/src/sh4/sh4core.in Wed Jan 07 04:39:04 2009 +0000
4.3 @@ -102,9 +102,6 @@
4.4
4.5 /********************** SH4 emulation core ****************************/
4.6
4.7 -#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
4.8 -#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }while(0)
4.9 -
4.10 #if(SH4_CALLTRACE == 1)
4.11 #define MAX_CALLSTACK 32
4.12 static struct call_stack {
4.13 @@ -187,10 +184,6 @@
4.14 #define MEM_WRITE_LONG( addr, val ) ADDRSPACE[(addr)>>12]->write_long(addr, val)
4.15 #define MEM_PREFETCH( addr ) ADDRSPACE[(addr)>>12]->prefetch(addr)
4.16 #endif
4.17 -
4.18 -
4.19 -
4.20 -
4.21
4.22 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
4.23
4.24 @@ -223,6 +216,131 @@
4.25 MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
4.26 }
4.27
4.28 +#define UNDEF(ir)
4.29 +#define UNIMP(ir)
4.30 +
4.31 +/**
4.32 + * Perform instruction-completion following core exit of a partially completed
4.33 + * instruction. NOTE: This is only allowed on memory writes, operation is not
4.34 + * guaranteed in any other case.
4.35 + */
4.36 +void sh4_finalize_instruction( void )
4.37 +{
4.38 + unsigned short ir;
4.39 + uint32_t tmp;
4.40 +
4.41 + assert( IS_IN_ICACHE(sh4r.pc) );
4.42 + ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
4.43 +
4.44 + /**
4.45 + * Note - we can't take an exit on a control transfer instruction itself,
4.46 + * which means the exit must have happened in the delay slot. So for these
4.47 + * cases, finalize the delay slot instruction, and re-execute the control transfer.
4.48 + *
4.49 + * For delay slots which modify the argument used in the branch instruction,
4.50 + * we pretty much just assume that that can't have already happened in an exit case.
4.51 + */
4.52 +
4.53 +%%
4.54 +BRA disp {:
4.55 + sh4r.pc += 2;
4.56 + sh4_finalize_instruction();
4.57 + sh4r.pc += disp;
4.58 + sh4r.slice_cycle += sh4_cpu_period;
4.59 +:}
4.60 +BRAF Rn {:
4.61 + sh4r.pc += 2;
4.62 + tmp = sh4r.r[Rn];
4.63 + sh4_finalize_instruction();
4.64 + sh4r.pc += tmp;
4.65 + sh4r.slice_cycle += sh4_cpu_period;
4.66 +:}
4.67 +BSR disp {:
4.68 + /* Note: PR is already set */
4.69 + sh4r.pc += 2;
4.70 + sh4_finalize_instruction();
4.71 + sh4r.pc += disp;
4.72 + sh4r.slice_cycle += sh4_cpu_period;
4.73 +:}
4.74 +BSRF Rn {:
4.75 + /* Note: PR is already set */
4.76 + sh4r.pc += 2;
4.77 + tmp = sh4r.r[Rn];
4.78 + sh4_finalize_instruction();
4.79 + sh4r.pc += tmp;
4.80 + sh4r.slice_cycle += sh4_cpu_period;
4.81 +:}
4.82 +BF/S disp {:
4.83 + sh4r.pc += 2;
4.84 + sh4_finalize_instruction();
4.85 + if( !sh4r.t ) {
4.86 + sh4r.pc += disp;
4.87 + }
4.88 + sh4r.slice_cycle += sh4_cpu_period;
4.89 +:}
4.90 +BT/S disp {:
4.91 + sh4r.pc += 2;
4.92 + sh4_finalize_instruction();
4.93 + if( sh4r.t ) {
4.94 + sh4r.pc += disp;
4.95 + }
4.96 + sh4r.slice_cycle += sh4_cpu_period;
4.97 +:}
4.98 +JMP @Rn {:
4.99 + sh4r.pc += 2;
4.100 + tmp = sh4r.r[Rn];
4.101 + sh4_finalize_instruction();
4.102 + sh4r.pc = tmp;
4.103 + sh4r.new_pc = tmp + 2;
4.104 + sh4r.slice_cycle += 2*sh4_cpu_period;
4.105 + return;
4.106 +:}
4.107 +JSR @Rn {:
4.108 + /* Note: PR is already set */
4.109 + sh4r.pc += 2;
4.110 + tmp = sh4r.r[Rn];
4.111 + sh4_finalize_instruction();
4.112 + sh4r.pc = tmp;
4.113 + sh4r.new_pc = tmp + 2;
4.114 + sh4r.slice_cycle += 2*sh4_cpu_period;
4.115 + return;
4.116 +:}
4.117 +RTS {:
4.118 + sh4r.pc += 2;
4.119 + sh4_finalize_instruction();
4.120 + sh4r.pc = sh4r.pr;
4.121 + sh4r.new_pc = sh4r.pr + 2;
4.122 + sh4r.slice_cycle += 2*sh4_cpu_period;
4.123 + return;
4.124 +:}
4.125 +RTE {:
4.126 + /* SR is already set */
4.127 + sh4r.pc += 2;
4.128 + sh4_finalize_instruction();
4.129 + sh4r.pc = sh4r.spc;
4.130 + sh4r.new_pc = sh4r.pr + 2;
4.131 + sh4r.slice_cycle += 2*sh4_cpu_period;
4.132 + return;
4.133 +:}
4.134 +MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
4.135 +MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
4.136 +MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
4.137 +MOV.B @Rm+, Rn {: sh4r.r[Rm] ++; :}
4.138 +MOV.W @Rm+, Rn {: sh4r.r[Rm] += 2; :}
4.139 +MOV.L @Rm+, Rn {: sh4r.r[Rm] += 4; :}
4.140 +%%
4.141 + sh4r.pc += 2;
4.142 + sh4r.new_pc = sh4r.pc+2;
4.143 + sh4r.slice_cycle += sh4_cpu_period;
4.144 +}
4.145 +
4.146 +#undef UNDEF(ir)
4.147 +#undef UNIMP(ir)
4.148 +
4.149 +#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
4.150 +#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }while(0)
4.151 +
4.152 +
4.153 gboolean sh4_execute_instruction( void )
4.154 {
4.155 uint32_t pc;
4.156 @@ -265,6 +383,14 @@
4.157 }
4.158 assert( IS_IN_ICACHE(pc) );
4.159 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
4.160 +
4.161 + /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
4.162 + * be visible until after the instruction has executed (for exception
4.163 + * correctness)
4.164 + */
4.165 + if( sh4r.in_delay_slot ) {
4.166 + sh4r.pc -= 2;
4.167 + }
4.168 %%
4.169 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
4.170 AND #imm, R0 {: R0 &= imm; :}
5.1 --- a/src/test/testsh4x86.c Tue Jan 06 02:03:36 2009 +0000
5.2 +++ b/src/test/testsh4x86.c Wed Jan 07 04:39:04 2009 +0000
5.3 @@ -78,8 +78,8 @@
5.4 gboolean sh4_clear_breakpoint( uint32_t pc, breakpoint_type_t type ) { return TRUE; }
5.5 gboolean dreamcast_is_running() { return FALSE; }
5.6 int sh4_get_breakpoint( uint32_t pc ) { return 0; }
5.7 +void sh4_finalize_instruction() { }
5.8 void sh4_core_exit( int exit_code ){}
5.9 -void sh4_flush_icache(){}
5.10 void event_execute() {}
5.11 void TMU_run_slice( uint32_t nanos ) {}
5.12 void CCN_set_cache_control( uint32_t val ) { }
6.1 --- a/src/tools/actparse.c Tue Jan 06 02:03:36 2009 +0000
6.2 +++ b/src/tools/actparse.c Wed Jan 07 04:39:04 2009 +0000
6.3 @@ -32,7 +32,7 @@
6.4 return action;
6.5 }
6.6
6.7 -int add_action( struct actionset *actions, struct ruleset *rules, char *operation, char *action )
6.8 +int add_action( char **actions, struct ruleset *rules, char *operation, char *action )
6.9 {
6.10 char *act = g_strchomp(action);
6.11
6.12 @@ -65,11 +65,11 @@
6.13
6.14 for( i=0; i<rules->rule_count; i++ ) {
6.15 if( strcasecmp(rules->rules[i]->format, operation) == 0 ) {
6.16 - if( actions->actions[i] != NULL ) {
6.17 + if( actions[i] != NULL ) {
6.18 fprintf( stderr, "Duplicate actions for operation '%s'\n", operation );
6.19 return -1;
6.20 }
6.21 - actions->actions[i] = act;
6.22 + actions[i] = act;
6.23 return 0;
6.24 }
6.25 }
6.26 @@ -77,65 +77,105 @@
6.27 return -1;
6.28 }
6.29
6.30 +struct actionfile {
6.31 + FILE *f;
6.32 + char *text;
6.33 + int length;
6.34 + int yyposn;
6.35 + int yyline;
6.36 + struct ruleset *rules;
6.37 + struct actiontoken token;
6.38 +};
6.39
6.40 -struct actionset *parse_action_file( struct ruleset *rules, FILE *f )
6.41 +actionfile_t action_file_open( const char *filename, struct ruleset *rules )
6.42 {
6.43 - struct actionset *actions = malloc( sizeof(struct actionset ) );
6.44 struct stat st;
6.45 - char *text;
6.46 - int i, length;
6.47 + FILE *f = fopen( filename, "ro" );
6.48 + if( f == NULL )
6.49 + return NULL;
6.50 + fstat( fileno(f), &st );
6.51 +
6.52 + actionfile_t af = malloc( sizeof(struct actionfile) );
6.53 + af->f = f;
6.54 + af->length = st.st_size+1;
6.55 + af->text = malloc( st.st_size+1 );
6.56 + fread( af->text, st.st_size, 1, f );
6.57 + af->text[st.st_size] = '\0';
6.58 + af->yyline = 0;
6.59 + af->yyposn = 0;
6.60 + af->rules = rules;
6.61 + af->token.symbol = NONE;
6.62 +
6.63 + return af;
6.64 +}
6.65
6.66 - memset( actions, 0, sizeof( struct actionset ) );
6.67 - /* Read whole file in (for convenience) */
6.68 - fstat( fileno(f), &st );
6.69 - length = st.st_size;
6.70 - text = malloc( length+1 );
6.71 - fread( text, length, 1, f );
6.72 - text[length] = '\0';
6.73 - yyline = 0;
6.74 - actions->pretext = text;
6.75 - for( i=0; i<length; i++ ) {
6.76 - if( text[i] == '\n' ) {
6.77 - yyline++;
6.78 - if( i+3 < length && text[i+1] == '%' && text[i+2] == '%' ) {
6.79 - text[i+1] = '\0';
6.80 - i+=3;
6.81 - break;
6.82 +actiontoken_t action_file_next( actionfile_t af )
6.83 +{
6.84 + if( af->token.symbol == ACTIONS ) {
6.85 + /* Destroy previous actions */
6.86 + memset( af->token.actions, 0, sizeof(af->token.actions) );
6.87 + }
6.88 +
6.89 + if( af->yyposn == af->length ) {
6.90 + af->token.symbol = END;
6.91 + } else if( af->token.symbol == TEXT || /* ACTIONS must follow TEXT */
6.92 + (af->token.symbol == NONE && af->text[af->yyposn] == '\%' && af->text[af->yyposn+1] == '%') ) {
6.93 + /* Begin action block */
6.94 + af->token.symbol = ACTIONS;
6.95 +
6.96 + char *operation = &af->text[af->yyposn];
6.97 + while( af->yyposn < af->length ) {
6.98 + if( af->text[af->yyposn] == '\n' ) {
6.99 + yyline++;
6.100 + if( af->text[af->yyposn+1] == '%' && af->text[af->yyposn+2] == '%' ) {
6.101 + af->yyposn += 3;
6.102 + break;
6.103 + }
6.104 }
6.105 +
6.106 + if( af->text[af->yyposn] == '{' && af->text[af->yyposn+1] == ':' ) {
6.107 + af->text[af->yyposn] = '\0';
6.108 + af->yyposn+=2;
6.109 + char *action = &af->text[af->yyposn];
6.110 + while( af->yyposn < af->length ) {
6.111 + if( af->text[af->yyposn] == ':' && af->text[af->yyposn+1] == '}' ) {
6.112 + af->text[af->yyposn] = '\0';
6.113 + af->yyposn++;
6.114 + if( add_action( af->token.actions, af->rules, operation, action ) != 0 ) {
6.115 + af->token.symbol = ERROR;
6.116 + return &af->token;
6.117 + }
6.118 + operation = &af->text[af->yyposn+1];
6.119 + break;
6.120 + }
6.121 + af->yyposn++;
6.122 + }
6.123 + }
6.124 + af->yyposn++;
6.125 }
6.126 - }
6.127 -
6.128 - char *operation = &text[i];
6.129 - for( ; i<length; i++ ) {
6.130 - if( text[i] == '\n' ) {
6.131 - yyline++;
6.132 - if( i+3 < length && text[i+1] == '%' && text[i+2] == '%' ) {
6.133 - i+=3;
6.134 - break;
6.135 - }
6.136 - }
6.137 -
6.138 - if( text[i] == '{' && text[i+1] == ':' ) {
6.139 - text[i] = '\0';
6.140 - i+=2;
6.141 - char *action = &text[i];
6.142 - for( ;i<length; i++ ) {
6.143 - if( text[i] == ':' && text[i+1] == '}' ) {
6.144 - text[i] = '\0';
6.145 - i++;
6.146 - if( add_action( actions, rules, operation, action ) != 0 ) {
6.147 - free(actions);
6.148 - free(text);
6.149 - return NULL;
6.150 - }
6.151 - operation = &text[i+1];
6.152 + } else {
6.153 + /* Text block */
6.154 + af->token.symbol = TEXT;
6.155 + af->token.text = &af->text[af->yyposn];
6.156 + while( af->yyposn < af->length ) {
6.157 + af->yyposn++;
6.158 + if( af->text[af->yyposn-1] == '\n' ) {
6.159 + af->yyline++;
6.160 + if( af->text[af->yyposn] == '%' && af->text[af->yyposn+1] == '%' ) {
6.161 + af->text[af->yyposn] = '\0';
6.162 + af->yyposn += 2;
6.163 break;
6.164 }
6.165 }
6.166 }
6.167 }
6.168 + return &af->token;
6.169 +}
6.170
6.171 - actions->posttext = &text[i];
6.172 +void action_file_close( actionfile_t af )
6.173 +{
6.174 + free( af->text );
6.175 + fclose( af->f );
6.176 + free( af );
6.177 +}
6.178
6.179 - return actions;
6.180 -}
7.1 --- a/src/tools/gendec.c Tue Jan 06 02:03:36 2009 +0000
7.2 +++ b/src/tools/gendec.c Wed Jan 07 04:39:04 2009 +0000
7.3 @@ -161,7 +161,7 @@
7.4 }
7.5 }
7.6
7.7 -void split_and_generate( struct ruleset *rules, struct actionset *actions,
7.8 +void split_and_generate( struct ruleset *rules, char **actions,
7.9 int ruleidx[], int rule_count, int input_mask,
7.10 int depth, FILE *f ) {
7.11 uint32_t mask;
7.12 @@ -170,7 +170,7 @@
7.13 if( rule_count == 0 ) {
7.14 fprintf( f, "%*cUNDEF(ir);\n", depth*8, ' ' );
7.15 } else if( rule_count == 1 ) {
7.16 - fprint_action( rules->rules[ruleidx[0]], actions->actions[ruleidx[0]], depth, f );
7.17 + fprint_action( rules->rules[ruleidx[0]], actions[ruleidx[0]], depth, f );
7.18 } else {
7.19
7.20 mask = find_mask(rules, ruleidx, rule_count, input_mask);
7.21 @@ -223,7 +223,7 @@
7.22 }
7.23 }
7.24
7.25 -int generate_decoder( struct ruleset *rules, struct actionset *actions, FILE *f )
7.26 +int generate_decoder( struct ruleset *rules, actionfile_t af, FILE *out )
7.27 {
7.28 int ruleidx[rules->rule_count];
7.29 int i;
7.30 @@ -232,27 +232,42 @@
7.31 ruleidx[i] = i;
7.32 }
7.33
7.34 - fputs( actions->pretext, f );
7.35 -
7.36 - split_and_generate( rules, actions, ruleidx, rules->rule_count, 0, 1, f );
7.37 -
7.38 - fputs( actions->posttext, f );
7.39 -
7.40 + actiontoken_t token = action_file_next(af);
7.41 + while( token->symbol != END ) {
7.42 + if( token->symbol == TEXT ) {
7.43 + fputs( token->text, out );
7.44 + } else if( token->symbol == ERROR ) {
7.45 + fprintf( stderr, "Error parsing action file" );
7.46 + return -1;
7.47 + } else {
7.48 + split_and_generate( rules, token->actions, ruleidx, rules->rule_count, 0, 1, out );
7.49 + }
7.50 + token = action_file_next(af);
7.51 + }
7.52 return 0;
7.53 }
7.54
7.55 -int generate_template( struct ruleset *rules, struct actionset *actions, FILE *f )
7.56 +int generate_template( struct ruleset *rules, actionfile_t af, FILE *out )
7.57 {
7.58 int i;
7.59 - fputs( actions->pretext, f );
7.60 - fputs( "%%\n", f );
7.61 -
7.62 - for( i=0; i<rules->rule_count; i++ ) {
7.63 - fprintf( f, "%s {: %s :}\n", rules->rules[i]->format,
7.64 - actions->actions[i] == NULL ? "" : actions->actions[i] );
7.65 +
7.66 + actiontoken_t token = action_file_next(af);
7.67 + while( token->symbol != END ) {
7.68 + if( token->symbol == TEXT ) {
7.69 + fputs( token->text, out );
7.70 + } else if( token->symbol == ERROR ) {
7.71 + fprintf( stderr, "Error parsing action file" );
7.72 + return -1;
7.73 + } else {
7.74 + fputs( "%%\n", out );
7.75 + for( i=0; i<rules->rule_count; i++ ) {
7.76 + fprintf( out, "%s {: %s :}\n", rules->rules[i]->format,
7.77 + token->actions[i] == NULL ? "" : token->actions[i] );
7.78 + }
7.79 + fputs( "%%\n", out );
7.80 + }
7.81 + token = action_file_next(af);
7.82 }
7.83 - fputs( "%%\n", f );
7.84 - fputs( actions->posttext, f );
7.85
7.86 return 0;
7.87 }
7.88 @@ -309,26 +324,21 @@
7.89 exit(2);
7.90 }
7.91
7.92 - act_file = fopen( act_filename, "ro" );
7.93 - if( act_file == NULL ) {
7.94 - fprintf( stderr, "Unable to open '%s' for reading (%s)\n", act_filename, strerror(errno) );
7.95 - exit(3);
7.96 - }
7.97 -
7.98 /* Parse the input */
7.99 struct ruleset *rules = parse_ruleset_file( ins_file );
7.100 fclose( ins_file );
7.101 if( rules == NULL ) {
7.102 exit(5);
7.103 }
7.104 -
7.105 - struct actionset *actions = parse_action_file( rules, act_file );
7.106 - fclose( act_file );
7.107 - if( actions == NULL ) {
7.108 - exit(6);
7.109 +
7.110 + actionfile_t af = action_file_open( act_filename, rules );
7.111 + if( af == NULL ) {
7.112 + fprintf( stderr, "Unable to open '%s' for reading (%s)\n", act_filename, strerror(errno) );
7.113 + exit(3);
7.114 }
7.115
7.116 - /* Finally write out the results */
7.117 +
7.118 + /* Open the output file */
7.119 out_file = fopen( out_filename, "wo" );
7.120 if( out_file == NULL ) {
7.121 fprintf( stderr, "Unable to open '%s' for writing (%s)\n", out_filename, strerror(errno) );
7.122 @@ -337,16 +347,18 @@
7.123
7.124 switch( gen_mode ) {
7.125 case GEN_SOURCE:
7.126 - if( generate_decoder( rules, actions, out_file ) != 0 ) {
7.127 + if( generate_decoder( rules, af, out_file ) != 0 ) {
7.128 exit(7);
7.129 }
7.130 break;
7.131 case GEN_TEMPLATE:
7.132 - if( generate_template( rules, actions, out_file ) != 0 ) {
7.133 + if( generate_template( rules, af, out_file ) != 0 ) {
7.134 exit(7);
7.135 }
7.136 break;
7.137 }
7.138 +
7.139 + action_file_close(af);
7.140 fclose( out_file );
7.141 return 0;
7.142 }
8.1 --- a/src/tools/gendec.h Tue Jan 06 02:03:36 2009 +0000
8.2 +++ b/src/tools/gendec.h Wed Jan 07 04:39:04 2009 +0000
8.3 @@ -70,14 +70,24 @@
8.4 };
8.5
8.6 struct actionset {
8.7 - char *pretext;
8.8 - char *posttext;
8.9 char *actions[MAX_RULES];
8.10 };
8.11
8.12 -struct actionset *parse_action_file( struct ruleset *rules, FILE *f );
8.13 +typedef struct actionfile *actionfile_t;
8.14
8.15 -int generate_decoder( struct ruleset *rules, struct actionset *actions, FILE *f );
8.16 +typedef struct actiontoken {
8.17 + enum { NONE, TEXT, ACTIONS, END, ERROR } symbol;
8.18 + char *text;
8.19 + char *actions[MAX_RULES];
8.20 +} *actiontoken_t;
8.21 +
8.22 +actionfile_t action_file_open( const char *filename, struct ruleset *rules );
8.23 +
8.24 +actiontoken_t action_file_next( actionfile_t af );
8.25 +
8.26 +void action_file_close( actionfile_t af );
8.27 +
8.28 +int generate_decoder( struct ruleset *rules, actionfile_t af, FILE *f );
8.29
8.30 #ifdef __cplusplus
8.31 }
.