copy .clang-format from x48ng and format all the code

This commit is contained in:
Gwenhael Le Moine 2024-03-26 13:36:50 +01:00
parent 18be3f70ba
commit d085a1537e
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
56 changed files with 10264 additions and 11720 deletions

59
.clang-format Normal file
View file

@ -0,0 +1,59 @@
---
Language: Cpp
ColumnLimit: 140
IndentWidth: 4
PPIndentWidth: 2
UseTab: Never
AlignArrayOfStructures: Left
IndentCaseBlocks: true
IndentCaseLabels: true
IndentGotoLabels: false
IndentPPDirectives: AfterHash
IndentWrappedFunctionNames: true
InsertBraces: false
InsertNewlineAtEOF: true
MaxEmptyLinesToKeep: 1
PointerAlignment: Left
ReferenceAlignment: Left
QualifierAlignment: Left
SortIncludes: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesInAngles: true
SpacesInCStyleCastParentheses: true
SpacesInContainerLiterals: true
SpacesInParentheses: true
SpacesInSquareBrackets: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
...

View file

@ -87,7 +87,7 @@ clean-all: mrproper
# Formatting # Formatting
pretty-code: pretty-code:
clang-format -i src/*.c src/*.h clang-format -i src/*.c src/*.h src/libChf/*.c src/libChf/*.h
# Dependencies # Dependencies
get-roms: get-roms:

View file

@ -74,27 +74,25 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Data type definitions - require config.h Data type definitions - require config.h
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
struct Args struct Args {
{ int reset; /* 2.1: Force emulator reset */
int reset; /* 2.1: Force emulator reset */ int monitor; /* 2.1: Call monitor() on startup */
int monitor; /* 2.1: Call monitor() on startup */ int batchXfer; /* 3.15: Non-interactive file transfers */
int batchXfer; /* 3.15: Non-interactive file transfers */ char* mod_file_name;
char *mod_file_name; char* cpu_file_name;
char *cpu_file_name; char* hdw_file_name;
char *hdw_file_name; char* rom_file_name;
char *rom_file_name; char* ram_file_name;
char *ram_file_name; char* port_1_file_name;
char *port_1_file_name; char* port_2_file_name;
char *port_2_file_name; char* hw; /* 2.1: Hardware configuration (unused) */
char *hw; /* 2.1: Hardware configuration (unused) */
}; };
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Global variables Global variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
extern struct Args args; extern struct Args args;

View file

@ -121,14 +121,12 @@
.- */ .- */
/* CHF_EXTENDED_INFO: /* CHF_EXTENDED_INFO:
Define this symbol if extended information is desired during condition Define this symbol if extended information is desired during condition
handling; this is usually useful only for debugging purposes. handling; this is usually useful only for debugging purposes.
*/ */
/* #define CHF_EXTENDED_INFO */ /* #define CHF_EXTENDED_INFO */
/* DEBUG: /* DEBUG:
Define this symbol to include the debugging code for all source modules Define this symbol to include the debugging code for all source modules
in the executable image. in the executable image.
@ -139,7 +137,6 @@
*/ */
/* #define DEBUG */ /* #define DEBUG */
/* DEBUG_LEVEL: /* DEBUG_LEVEL:
When this symbol is defined and the debugging code has been included When this symbol is defined and the debugging code has been included
in the executable image (DEBUG symbol set), the initial debug level in the executable image (DEBUG symbol set), the initial debug level
@ -149,8 +146,7 @@
DEBUG_C_<> defined in debug.h; each of them corresponds to a class DEBUG_C_<> defined in debug.h; each of them corresponds to a class
of debugging conditions that can be individually enabled or disabled. of debugging conditions that can be individually enabled or disabled.
*/ */
#define DEBUG_LEVEL DEBUG_C_REVISION #define DEBUG_LEVEL DEBUG_C_REVISION
/* CPU_SPIN_SHUTDN /* CPU_SPIN_SHUTDN
If this symbol is defined, the cpu module implements the SHUTDN If this symbol is defined, the cpu module implements the SHUTDN
@ -176,7 +172,6 @@
*/ */
/* #define CPU_SPIN_SHUTDN */ /* #define CPU_SPIN_SHUTDN */
/* 2.1: FORCE_NONMODAL /* 2.1: FORCE_NONMODAL
If this symbol is defined, nonmodal navigation is forced in the If this symbol is defined, nonmodal navigation is forced in the
OSF/Motif GUI, by setting navigationType to XmNONE and traversalOn OSF/Motif GUI, by setting navigationType to XmNONE and traversalOn
@ -184,15 +179,13 @@
*/ */
/* #define FORCE_NONMODAL */ /* #define FORCE_NONMODAL */
/* 2.4: N_PORT_2_BANK /* 2.4: N_PORT_2_BANK
This symbol is used to dimension the HP48GX Port_2: it denotes the This symbol is used to dimension the HP48GX Port_2: it denotes the
number of 128 Kbyte banks the port must have and must be a power of 2 number of 128 Kbyte banks the port must have and must be a power of 2
between 1 and 32, inclusive. When undefined, Port_2 is not emulated at all. between 1 and 32, inclusive. When undefined, Port_2 is not emulated at all.
The default value is 8, that is, Port_2 is emulated and its size is 1Mbyte. The default value is 8, that is, Port_2 is emulated and its size is 1Mbyte.
*/ */
#define N_PORT_2_BANK 8 #define N_PORT_2_BANK 8
/* 2.5: SERIAL_FORCE_OPENPTY, SERIAL_FORCE_STREAMSPTY /* 2.5: SERIAL_FORCE_OPENPTY, SERIAL_FORCE_STREAMSPTY
Optionally define exactly one of these symbols to force the use of a Optionally define exactly one of these symbols to force the use of a
@ -203,7 +196,6 @@
/* #define SERIAL_FORCE_OPENPTY */ /* #define SERIAL_FORCE_OPENPTY */
/* #define SERIAL_FORCE_STREAMSPTY */ /* #define SERIAL_FORCE_STREAMSPTY */
/* 3.2: HP49_SUPPORT /* 3.2: HP49_SUPPORT
Define this symbol to enable HP49-specific support code in the Define this symbol to enable HP49-specific support code in the
emulator; it does not harm if this symbol is defined when emulating emulator; it does not harm if this symbol is defined when emulating
@ -211,7 +203,6 @@
*/ */
#define HP49_SUPPORT #define HP49_SUPPORT
/* 3.13: REAL_CPU_SPEED /* 3.13: REAL_CPU_SPEED
Define this symbol (recommended) to force the emulated CPU to run Define this symbol (recommended) to force the emulated CPU to run
no faster than a software-controlled limit; by default, the limit no faster than a software-controlled limit; by default, the limit
@ -219,7 +210,6 @@
*/ */
#define REAL_CPU_SPEED #define REAL_CPU_SPEED
/* 3.14: CPU_SLOW_IN /* 3.14: CPU_SLOW_IN
Define this symbol (recommended) to slow down the A=IN and C=IN Define this symbol (recommended) to slow down the A=IN and C=IN
instructions depending on the current emulated CPU speed. instructions depending on the current emulated CPU speed.
@ -227,8 +217,7 @@
The value of the macro determines the gain of the relation between The value of the macro determines the gain of the relation between
CPU speed and slow down ratio. CPU speed and slow down ratio.
*/ */
#define CPU_SLOW_IN 16 #define CPU_SLOW_IN 16
/* 4.1.1.1: LCD_MAG /* 4.1.1.1: LCD_MAG
This symbol represents the magnification ratio of the emulated LCD pixels This symbol represents the magnification ratio of the emulated LCD pixels
@ -236,32 +225,29 @@
default. Currently, the value cannot be set at runtime for performance default. Currently, the value cannot be set at runtime for performance
reasons. reasons.
*/ */
#define LCD_MAG 2 #define LCD_MAG 2
/* 4.1.1.1: When defined, this symbol represents the threshold of the long /* 4.1.1.1: When defined, this symbol represents the threshold of the long
key pression. When the mouse button is kept pressed on a calculator's key key pression. When the mouse button is kept pressed on a calculator's key
for more than LONG_PRESS_THR milliseconds, the key stays pressed after for more than LONG_PRESS_THR milliseconds, the key stays pressed after
release. release.
*/ */
#define LONG_PRESS_THR 1000 #define LONG_PRESS_THR 1000
/* Chf Module Identifiers: /* Chf Module Identifiers:
Each main module of the emulator has its own Chf Module Identifier; the Each main module of the emulator has its own Chf Module Identifier; the
values defined here must match those actually used in the message catalogs. values defined here must match those actually used in the message catalogs.
*/ */
#define MAIN_CHF_MODULE_ID 10 #define MAIN_CHF_MODULE_ID 10
#define CPU_CHF_MODULE_ID 11 #define CPU_CHF_MODULE_ID 11
#define MOD_CHF_MODULE_ID 12 #define MOD_CHF_MODULE_ID 12
#define DISK_IO_CHF_MODULE_ID 13 #define DISK_IO_CHF_MODULE_ID 13
#define X11_CHF_MODULE_ID 14 #define X11_CHF_MODULE_ID 14
#define SERIAL_CHF_MODULE_ID 15 /* 2.5 */ #define SERIAL_CHF_MODULE_ID 15 /* 2.5 */
#define FLASH_CHF_MODULE_ID 16 /* 3.3 */ #define FLASH_CHF_MODULE_ID 16 /* 3.3 */
#define UTIL_CHF_MODULE_ID 17 /* 3.6 */ #define UTIL_CHF_MODULE_ID 17 /* 3.6 */
#define X_FUNC_CHF_MODULE_ID 18 /* 3.13 */ #define X_FUNC_CHF_MODULE_ID 18 /* 3.13 */
#define DEBUG_CHF_MODULE_ID 30 #define DEBUG_CHF_MODULE_ID 30
/* 3.16: Include automatic exceptions to user configuration */ /* 3.16: Include automatic exceptions to user configuration */
#include "config_x.h" #include "config_x.h"

View file

@ -58,8 +58,7 @@
.- */ .- */
/* REAL_CPU_SPEED is not supported on ultrix, because there is no usleep() */ /* REAL_CPU_SPEED is not supported on ultrix, because there is no usleep() */
#ifdef ultrix #ifdef ultrix
#undef REAL_CPU_SPEED # undef REAL_CPU_SPEED
#endif #endif

3903
src/cpu.c

File diff suppressed because it is too large Load diff

333
src/cpu.h
View file

@ -67,8 +67,8 @@
requests and emulator's extended functions: requests and emulator's extended functions:
- Added new fields: - Added new fields:
struct CpuStatus.halt (number of pending halt requests) struct CpuStatus.halt (number of pending halt requests)
struct CpuStatus.inner_loop_max (upper limit of inner_loop) struct CpuStatus.inner_loop_max (upper limit of inner_loop)
- New condition codes: CPU_I_HALT, CPU_I_RUN, CPU_E_NO_HALT - New condition codes: CPU_I_HALT, CPU_I_RUN, CPU_E_NO_HALT
- New prototypes: CpuHaltRequest(), CpuRunRequest(), CpuHaltAllowed() - New prototypes: CpuHaltRequest(), CpuRunRequest(), CpuHaltAllowed()
@ -105,9 +105,8 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macro/Data type definitions - require machdep.h Macro/Data type definitions - require machdep.h
N_SCRATCH_REGISTER_ALL, used during scratch register space allocation N_SCRATCH_REGISTER_ALL, used during scratch register space allocation
is larger than necessary to avoid additional checks on the validity of is larger than necessary to avoid additional checks on the validity of
@ -115,238 +114,224 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* General */ /* General */
#define NIBBLE_PER_REGISTER 16 #define NIBBLE_PER_REGISTER 16
#define N_WORKING_REGISTER 4 #define N_WORKING_REGISTER 4
#define N_SCRATCH_REGISTER 5 #define N_SCRATCH_REGISTER 5
#define N_SCRATCH_REGISTER_ALL 8 #define N_SCRATCH_REGISTER_ALL 8
#define N_DATA_POINTER_REGISTER 2 #define N_DATA_POINTER_REGISTER 2
#define RETURN_STACK_SIZE 8 #define RETURN_STACK_SIZE 8
#define NIBBLE_VALUES 16 #define NIBBLE_VALUES 16
#define INT_HANDLER_PC ((Address)0x0000F) #define INT_HANDLER_PC ( ( Address )0x0000F )
#define DISASSEMBLE_OB_SIZE 128 #define DISASSEMBLE_OB_SIZE 128
#define DUMP_CPU_STATUS_OB_SIZE 512 #define DUMP_CPU_STATUS_OB_SIZE 512
#define CPU_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
#define CPU_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
/* Instruction opcode access macros: /* Instruction opcode access macros:
GetFS(f) returns the short field-selector value from the GetFS(f) returns the short field-selector value from the
given nibble (bits 2..0) given nibble (bits 2..0)
GetImmFS(f) returns the immediate-field-selector flag from the GetImmFS(f) returns the immediate-field-selector flag from the
given nibble (bit 3) given nibble (bit 3)
=0: regular field selector =0: regular field selector
!=0: immediate field selector !=0: immediate field selector
GetOC_1(o) returns the short operation code from the given GetOC_1(o) returns the short operation code from the given
nibble (bits 3..2 >>2) nibble (bits 3..2 >>2)
GetOC_2(f, o) returns the long operation code from the given GetOC_2(f, o) returns the long operation code from the given
nibbles (f bit 3, o bits 3..2) nibbles (f bit 3, o bits 3..2)
GetOC_3b(o) returns the long operation code from the given GetOC_3b(o) returns the long operation code from the given
nibble (bits 2..0) nibble (bits 2..0)
GetRP(o) returns the register-pair identifier from the given GetRP(o) returns the register-pair identifier from the given
nibble (bits 1..0) nibble (bits 1..0)
GetRn(r) returns the R register index from the given nibble GetRn(r) returns the R register index from the given nibble
(bits 2..0) (bits 2..0)
GetAC(r) returns the A/C register flag from the given nibble GetAC(r) returns the A/C register flag from the given nibble
(bit 3) (bit 3)
=0: register A =0: register A
!=0: register C !=0: register C
GetAS(r) returns the add/subtract flag from the given nibble GetAS(r) returns the add/subtract flag from the given nibble
(bit 3) (bit 3)
=0: add =0: add
!=0: subtract !=0: subtract
*/ */
#define GetFS(f) ((f) & 0x7) #define GetFS( f ) ( ( f ) & 0x7 )
#define GetImmFS(o) ((o) & 0x8) #define GetImmFS( o ) ( ( o ) & 0x8 )
#define GetOC_1(o) (((o) & 0xC)>>2) #define GetOC_1( o ) ( ( ( o ) & 0xC ) >> 2 )
#define GetOC_2(f, o) ((((f) & 0x8)>>1) | (((o) & 0xC)>>2)) #define GetOC_2( f, o ) ( ( ( ( f ) & 0x8 ) >> 1 ) | ( ( ( o ) & 0xC ) >> 2 ) )
#define GetOC_3b(o) ((o) & 0x7) #define GetOC_3b( o ) ( ( o ) & 0x7 )
#define GetRP(o) ((o) & 0x3) #define GetRP( o ) ( ( o ) & 0x3 )
#define GetRn(r) ((r) & 0x7) #define GetRn( r ) ( ( r ) & 0x7 )
#define GetAC(r) ((r) & 0x8) #define GetAC( r ) ( ( r ) & 0x8 )
#define GetAS(r) ((r) & 0x8) #define GetAS( r ) ( ( r ) & 0x8 )
/* Field selector codes */ /* Field selector codes */
#define FS_P 0 #define FS_P 0
#define FS_WP 1 #define FS_WP 1
#define FS_XS 2 #define FS_XS 2
#define FS_X 3 #define FS_X 3
#define FS_S 4 #define FS_S 4
#define FS_M 5 #define FS_M 5
#define FS_B 6 #define FS_B 6
#define FS_W 7 #define FS_W 7
#define FS_A 15 #define FS_A 15
#define N_FS 16 /* Total # of FS codes */ #define N_FS 16 /* Total # of FS codes */
/* Register pair codes */ /* Register pair codes */
#define RP_AB 0 #define RP_AB 0
#define RP_BC 1 #define RP_BC 1
#define RP_CA 2 #define RP_CA 2
#define RP_DC 3 #define RP_DC 3
#define N_RP 4 /* Total # of RP codes */ #define N_RP 4 /* Total # of RP codes */
/* Masks */ /* Masks */
#define NIBBLE_MASK ((Nibble)0xF) #define NIBBLE_MASK ( ( Nibble )0xF )
#define ADDRESS_MASK ((Address)0xFFFFF) #define ADDRESS_MASK ( ( Address )0xFFFFF )
#define CLRST_MASK ((ProgramStatusRegister)0xF000) #define CLRST_MASK ( ( ProgramStatusRegister )0xF000 )
#define D_S_MASK ((Address)0xF0000) #define D_S_MASK ( ( Address )0xF0000 )
#define RETURN_SP_MASK 0x7 #define RETURN_SP_MASK 0x7
typedef int1 Bit;
typedef int1 Bit; typedef int4 Nibble;
typedef int4 Nibble; typedef int20 Address;
typedef int20 Address; typedef int12 OutputRegister;
typedef int12 OutputRegister; typedef int16 InputRegister;
typedef int16 InputRegister; typedef int16 ProgramStatusRegister;
typedef int16 ProgramStatusRegister; typedef Nibble DataRegister[ NIBBLE_PER_REGISTER ];
typedef Nibble DataRegister[NIBBLE_PER_REGISTER];
/* The XAddress data type holds extended addresses used to access Port 2 */ /* The XAddress data type holds extended addresses used to access Port 2 */
typedef int32 XAddress; typedef int32 XAddress;
enum IntRequest enum IntRequest { INT_REQUEST_NONE, INT_REQUEST_IRQ, INT_REQUEST_NMI };
{
INT_REQUEST_NONE,
INT_REQUEST_IRQ,
INT_REQUEST_NMI
};
struct CpuStatus struct CpuStatus {
{ DataRegister work[ N_WORKING_REGISTER ];
DataRegister work[N_WORKING_REGISTER]; #define A work[ 0 ]
#define A work[0] #define B work[ 1 ]
#define B work[1] #define C work[ 2 ]
#define C work[2] #define D work[ 3 ]
#define D work[3]
DataRegister R[N_SCRATCH_REGISTER_ALL]; DataRegister R[ N_SCRATCH_REGISTER_ALL ];
#define R0 R[0] #define R0 R[ 0 ]
#define R1 R[1] #define R1 R[ 1 ]
#define R2 R[2] #define R2 R[ 2 ]
#define R3 R[3] #define R3 R[ 3 ]
#define R4 R[4] #define R4 R[ 4 ]
Address DAT[N_DATA_POINTER_REGISTER]; Address DAT[ N_DATA_POINTER_REGISTER ];
#define D0 DAT[0] #define D0 DAT[ 0 ]
#define D1 DAT[1] #define D1 DAT[ 1 ]
Nibble P; Nibble P;
Address PC; Address PC;
InputRegister IN; InputRegister IN;
OutputRegister OUT; OutputRegister OUT;
ProgramStatusRegister ST; ProgramStatusRegister ST;
Nibble HST; Nibble HST;
#define HST_MP_MASK 0x08 #define HST_MP_MASK 0x08
#define HST_SR_MASK 0x04 #define HST_SR_MASK 0x04
#define HST_SB_MASK 0x02 #define HST_SB_MASK 0x02
#define HST_XM_MASK 0x01 #define HST_XM_MASK 0x01
Address return_stack[RETURN_STACK_SIZE]; Address return_stack[ RETURN_STACK_SIZE ];
int return_sp; int return_sp;
int fs_idx_lo[N_FS]; int fs_idx_lo[ N_FS ];
int fs_idx_hi[N_FS]; int fs_idx_hi[ N_FS ];
int hexmode; /* DEC/HEX mode, 1=HEX */ int hexmode; /* DEC/HEX mode, 1=HEX */
int carry; /* Carry bit 1=set */ int carry; /* Carry bit 1=set */
int shutdn; /* SHUTDN flag, 1=executed */ int shutdn; /* SHUTDN flag, 1=executed */
int halt; /* 3.13: # of pending Halt */ int halt; /* 3.13: # of pending Halt */
int int_enable; /* Int. enable, 1=enabled */ int int_enable; /* Int. enable, 1=enabled */
int int_service; /* Int. service, 1=service */ int int_service; /* Int. service, 1=service */
enum IntRequest int_pending; /* Pending interrupt request */ enum IntRequest int_pending; /* Pending interrupt request */
/* 3.13: inner_loop_max gives the upper limit of the CPU speed if the /* 3.13: inner_loop_max gives the upper limit of the CPU speed if the
compile-time option REAL_CPU_SPEED is defined. When the CPU is reset compile-time option REAL_CPU_SPEED is defined. When the CPU is reset
it has the default value INNER_LOOP_MAX, that should be close to the it has the default value INNER_LOOP_MAX, that should be close to the
real cpu speed (~4MHz). real cpu speed (~4MHz).
*/ */
int inner_loop; /* Inner loop multiplier */ int inner_loop; /* Inner loop multiplier */
int inner_loop_max; /* Max value of inner_loop */ int inner_loop_max; /* Max value of inner_loop */
#define INNER_LOOP_MAX 26 #define INNER_LOOP_MAX 26
#define INNER_LOOP_MED 13 #define INNER_LOOP_MED 13
#define INNER_LOOP_MIN 2 #define INNER_LOOP_MIN 2
#ifdef CPU_SPIN_LOOP #ifdef CPU_SPIN_LOOP
int reset_req; /* Reset req. after shutdn */ int reset_req; /* Reset req. after shutdn */
#endif #endif
}; };
enum ExitOption /* 2.1: EmulatorExit() option */ enum ExitOption /* 2.1: EmulatorExit() option */
{ {
IMMEDIATE_EXIT, IMMEDIATE_EXIT,
SAVE_AND_EXIT SAVE_AND_EXIT
}; };
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Global variables Global variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
extern struct CpuStatus cpu_status; extern struct CpuStatus cpu_status;
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define CPU_I_CALLED 101 /* Function %s called */ #define CPU_I_CALLED 101 /* Function %s called */
#define CPU_I_EXECUTING 102 /* Executing @PC %X */ #define CPU_I_EXECUTING 102 /* Executing @PC %X */
#define CPU_I_SHUTDN 103 /* Shutdown */ #define CPU_I_SHUTDN 103 /* Shutdown */
#define CPU_I_WAKE 104 /* Wake */ #define CPU_I_WAKE 104 /* Wake */
#define CPU_I_INT 105 /* %s request accepted */ #define CPU_I_INT 105 /* %s request accepted */
#define CPU_I_INT_PENDING 106 /* %s request pending */ #define CPU_I_INT_PENDING 106 /* %s request pending */
#define CPU_I_RTI_LOOP 107 /* RTI loop to service %s */ #define CPU_I_RTI_LOOP 107 /* RTI loop to service %s */
#define CPU_I_RTI_END 108 /* RTI returning */ #define CPU_I_RTI_END 108 /* RTI returning */
#define CPU_I_INTON 109 /* INTON servicing %s */ #define CPU_I_INTON 109 /* INTON servicing %s */
#define CPU_I_REVISION 110 /* CPU emulation revision: %s */ #define CPU_I_REVISION 110 /* CPU emulation revision: %s */
#define CPU_I_TIMER1_EX 111 /* Timer 1 expired; ctrl=%x */ #define CPU_I_TIMER1_EX 111 /* Timer 1 expired; ctrl=%x */
#define CPU_I_TIMER2_EX 112 /* Timer 1 expired; ctrl=%x */ #define CPU_I_TIMER2_EX 112 /* Timer 1 expired; ctrl=%x */
#define CPU_I_EMULATOR_INT 113 /* Emulator interrupt req. detected */ #define CPU_I_EMULATOR_INT 113 /* Emulator interrupt req. detected */
#define CPU_I_TIMER_ST 114 /* 3.1: Timer %s st: ctrl %x, val %x */ #define CPU_I_TIMER_ST 114 /* 3.1: Timer %s st: ctrl %x, val %x */
#define CPU_I_TIMER_EXP 115 /* 3.1: Timer %s expiration %d ms */ #define CPU_I_TIMER_EXP 115 /* 3.1: Timer %s expiration %d ms */
#define CPU_I_IDLE_X_LOOP 116 /* 3.1: Start idle loop, t/out %d ms */ #define CPU_I_IDLE_X_LOOP 116 /* 3.1: Start idle loop, t/out %d ms */
#define CPU_I_ELAPSED 117 /* 3.1: Spent %d us in idle loop */ #define CPU_I_ELAPSED 117 /* 3.1: Spent %d us in idle loop */
#define CPU_I_HALT 118 /* 3.13: CPU halted */ #define CPU_I_HALT 118 /* 3.13: CPU halted */
#define CPU_I_RUN 119 /* 3.13: CPU running */ #define CPU_I_RUN 119 /* 3.13: CPU running */
#define CPU_W_RESETTING 201 /* Resetting CPU */ #define CPU_W_RESETTING 201 /* Resetting CPU */
#define CPU_W_BAD_MONITOR_CMD 202 /* Bad monitor command: %s */ #define CPU_W_BAD_MONITOR_CMD 202 /* Bad monitor command: %s */
#define CPU_E_BAD_OPCODE 301 /* Bad opc. pc=%x, value=%x */ #define CPU_E_BAD_OPCODE 301 /* Bad opc. pc=%x, value=%x */
#define CPU_E_SAVE 302 /* Can't save CPU status */ #define CPU_E_SAVE 302 /* Can't save CPU status */
#define CPU_E_NO_HALT 303 /* 3.13: Halt/Run not allowed */ #define CPU_E_NO_HALT 303 /* 3.13: Halt/Run not allowed */
#define CPU_F_INTERR 401 /* Internal error %s */ #define CPU_F_INTERR 401 /* Internal error %s */
#define CPU_F_BAD_SHUTDN 402 /* Unexpected CPU shutdown */ #define CPU_F_BAD_SHUTDN 402 /* Unexpected CPU shutdown */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
void CpuInit(void); void CpuInit( void );
void CpuReset(void); void CpuReset( void );
void CpuSave(void); void CpuSave( void );
void OneStep(void); void OneStep( void );
void CpuIntRequest(enum IntRequest ireq); void CpuIntRequest( enum IntRequest ireq );
void CpuWake(void); void CpuWake( void );
void Emulator(void); void Emulator( void );
void EmulatorIntRequest(void); void EmulatorIntRequest( void );
void EmulatorInit(void); /* 2.1 */ void EmulatorInit( void ); /* 2.1 */
void EmulatorExit(enum ExitOption opt); /* 2.1 */ void EmulatorExit( enum ExitOption opt ); /* 2.1 */
int CpuHaltRequest(void); /* 3.13 */ int CpuHaltRequest( void ); /* 3.13 */
int CpuRunRequest(void); /* 3.13 */ int CpuRunRequest( void ); /* 3.13 */
int CpuHaltAllowed(void); /* 3.13 */ int CpuHaltAllowed( void ); /* 3.13 */
Address Disassemble(Address pc, char ob[DISASSEMBLE_OB_SIZE]); Address Disassemble( Address pc, char ob[ DISASSEMBLE_OB_SIZE ] );
void DumpCpuStatus(char ob[DUMP_CPU_STATUS_OB_SIZE]); void DumpCpuStatus( char ob[ DUMP_CPU_STATUS_OB_SIZE ] );

View file

@ -73,25 +73,23 @@ static char rcs_id[] = "$Id: debug.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include "cpu.h" #include "cpu.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID DEBUG_CHF_MODULE_ID #define CHF_MODULE_ID DEBUG_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Static/Global variables Static/Global variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#ifdef DEBUG #ifdef DEBUG
#ifdef DEBUG_LEVEL # ifdef DEBUG_LEVEL
int debug_level = DEBUG_LEVEL; int debug_level = DEBUG_LEVEL;
#else # else
int debug_level = 0; int debug_level = 0;
# endif
#endif #endif
#endif
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -105,23 +103,23 @@ int debug_level = 0;
it signals a condition and does nothing more. it signals a condition and does nothing more.
.call : .call :
SetDebugLevel(new_level) SetDebugLevel(new_level)
.input : .input :
int new_level, new value of the debug_level flag int new_level, new value of the debug_level flag
.output : .output :
void void
.status_codes : .status_codes :
DEBUG_W_NOT_SUPPORTED DEBUG_W_NOT_SUPPORTED
.notes : .notes :
1.1, 28-Jan-1998, creation 1.1, 28-Jan-1998, creation
.- */ .- */
void SetDebugLevel(int new_level) void SetDebugLevel( int new_level )
{ {
#ifdef DEBUG #ifdef DEBUG
debug_level = new_level; debug_level = new_level;
#else #else
ChfCondition DEBUG_W_NOT_SUPPORTED, CHF_WARNING ChfEnd; ChfCondition DEBUG_W_NOT_SUPPORTED, CHF_WARNING ChfEnd;
ChfSignal(); ChfSignal();
#endif #endif
} }

View file

@ -44,10 +44,10 @@
.description : .description :
This header defines the following macros: This header defines the following macros:
- debug0(debug_class, condition_code) - debug0(debug_class, condition_code)
- debug1(debug_class, condition_code, arg_1) - debug1(debug_class, condition_code, arg_1)
- debug2(debug_class, condition_code, arg_1, arg_2) - debug2(debug_class, condition_code, arg_1, arg_2)
- debug3(debug_class, condition_code, arg_1, arg_2, arg_3) - debug3(debug_class, condition_code, arg_1, arg_2, arg_3)
used throughout the source code for debugging purposes. used throughout the source code for debugging purposes.
@ -101,73 +101,62 @@
#ifdef DEBUG #ifdef DEBUG
#define debug_preamble(debug_class, condition_code) \ # define debug_preamble( debug_class, condition_code ) \
{ \ { \
extern int debug_level; \ extern int debug_level; \
if(debug_level & (debug_class)) \ if ( debug_level & ( debug_class ) ) { \
{ \ ChfCondition( condition_code ), CHF_INFO
ChfCondition (condition_code), CHF_INFO
#define debug_postamble \ # define debug_postamble \
ChfEnd; \ ChfEnd; \
ChfSignal(); \ ChfSignal(); \
} \ } \
} }
#define debug0(debug_class, condition_code) \ # define debug0( debug_class, condition_code ) debug_preamble( debug_class, condition_code ) debug_postamble
debug_preamble(debug_class, condition_code) \
debug_postamble
#define debug1(debug_class, condition_code, arg_1) \ # define debug1( debug_class, condition_code, arg_1 ) debug_preamble( debug_class, condition_code ), arg_1 debug_postamble
debug_preamble(debug_class, condition_code), arg_1 \
debug_postamble
#define debug2(debug_class, condition_code, arg_1, arg_2) \ # define debug2( debug_class, condition_code, arg_1, arg_2 ) debug_preamble( debug_class, condition_code ), arg_1, arg_2 debug_postamble
debug_preamble(debug_class, condition_code), arg_1, arg_2 \
debug_postamble
#define debug3(debug_class, condition_code, arg_1, arg_2, arg_3) \ # define debug3( debug_class, condition_code, arg_1, arg_2, arg_3 ) \
debug_preamble(debug_class, condition_code), arg_1, arg_2, arg_3 \ debug_preamble( debug_class, condition_code ), arg_1, arg_2, arg_3 debug_postamble
debug_postamble
#else #else
#define debug0(debug_class, condition_code) # define debug0( debug_class, condition_code )
#define debug1(debug_class, condition_code, arg_1) # define debug1( debug_class, condition_code, arg_1 )
#define debug2(debug_class, condition_code, arg_1, arg_2) # define debug2( debug_class, condition_code, arg_1, arg_2 )
#define debug3(debug_class, condition_code, arg_1, arg_2, arg_3) # define debug3( debug_class, condition_code, arg_1, arg_2, arg_3 )
#endif #endif
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Debug classes Debug classes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define DEBUG_C_TRACE 0x8000 /* Function Call trace */ #define DEBUG_C_TRACE 0x8000 /* Function Call trace */
#define DEBUG_C_MODULES 0x4000 /* Modules configuration */ #define DEBUG_C_MODULES 0x4000 /* Modules configuration */
#define DEBUG_C_DISPLAY 0x2000 /* Display activity */ #define DEBUG_C_DISPLAY 0x2000 /* Display activity */
#define DEBUG_C_INT 0x1000 /* Interrupt activity */ #define DEBUG_C_INT 0x1000 /* Interrupt activity */
#define DEBUG_C_TIMERS 0x0800 /* Timers activity */ #define DEBUG_C_TIMERS 0x0800 /* Timers activity */
#define DEBUG_C_SERIAL 0x0400 /* 2.5: Serial port activity */ #define DEBUG_C_SERIAL 0x0400 /* 2.5: Serial port activity */
#define DEBUG_C_MOD_CACHE 0x0200 /* 2.7: Module cache */ #define DEBUG_C_MOD_CACHE 0x0200 /* 2.7: Module cache */
#define DEBUG_C_IMPLEMENTATION 0x0100 /* Feature implementation */ #define DEBUG_C_IMPLEMENTATION 0x0100 /* Feature implementation */
#define DEBUG_C_FLASH 0x0080 /* 3.3: Flash ROM */ #define DEBUG_C_FLASH 0x0080 /* 3.3: Flash ROM */
#define DEBUG_C_X_FUNC 0x0040 /* 3.13: Extended functions */ #define DEBUG_C_X_FUNC 0x0040 /* 3.13: Extended functions */
#define DEBUG_C_REVISION 0x0010 /* Revision information */ #define DEBUG_C_REVISION 0x0010 /* Revision information */
#define DEBUG_C_X11 0x0001 /* X11 Interface */ #define DEBUG_C_X11 0x0001 /* X11 Interface */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define DEBUG_W_NOT_SUPPORTED 201 /* Debug not supported */ #define DEBUG_W_NOT_SUPPORTED 201 /* Debug not supported */
#define DEBUG_W_BAD_CMD 202 /* Invalid command */ #define DEBUG_W_BAD_CMD 202 /* Invalid command */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
void SetDebugLevel(int new_level); void SetDebugLevel( int new_level );

2271
src/dis.c

File diff suppressed because it is too large Load diff

View file

@ -76,10 +76,9 @@ static char rcs_id[] = "$Id: disk_io.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $"
#include "disk_io.h" #include "disk_io.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID #define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/* .+ /* .+
.title : ReadNibblesFromFile .title : ReadNibblesFromFile
@ -91,60 +90,55 @@ static char rcs_id[] = "$Id: disk_io.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $"
caller a status code. caller a status code.
.call : .call :
st = ReadNibbledFromFile(name, size, dest); st = ReadNibbledFromFile(name, size, dest);
.input : .input :
const char *name, file name const char *name, file name
int size, size of the file (nibbles, NOT bytes) int size, size of the file (nibbles, NOT bytes)
.output : .output :
Nibble *dest, pointer to the destination memory area Nibble *dest, pointer to the destination memory area
int st, status code int st, status code
.status_codes : .status_codes :
DISK_IO_I_CALLED (signalled) DISK_IO_I_CALLED (signalled)
DISK_IO_E_OPEN DISK_IO_E_OPEN
DISK_IO_E_GETC DISK_IO_E_GETC
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
.- */ .- */
int ReadNibblesFromFile(const char *name, int size, Nibble *dest) int ReadNibblesFromFile( const char* name, int size, Nibble* dest )
{ {
FILE *f; FILE* f;
int i; int i;
int by; int by;
int st = DISK_IO_S_OK; int st = DISK_IO_S_OK;
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadNibblesFromFile"); debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadNibblesFromFile" );
if((f = fopen(name, "rb")) == (FILE *)NULL) if ( ( f = fopen( name, "rb" ) ) == ( FILE* )NULL ) {
{
ChfErrnoCondition;
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
}
else
{
for(i=0; i<size;)
{
by = getc(f);
if(by == -1)
{
ChfErrnoCondition; ChfErrnoCondition;
ChfCondition st=DISK_IO_E_GETC, CHF_ERROR, name ChfEnd; ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
break;
}
dest[i++] = (Nibble)(by & 0x0F);
dest[i++] = (Nibble)((by & 0xF0) >> 4);
} }
(void)fclose(f); else {
} for ( i = 0; i < size; ) {
by = getc( f );
return st; if ( by == -1 ) {
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
break;
}
dest[ i++ ] = ( Nibble )( by & 0x0F );
dest[ i++ ] = ( Nibble )( ( by & 0xF0 ) >> 4 );
}
( void )fclose( f );
}
return st;
} }
/* .+ /* .+
.title : WriteNibblesToFile .title : WriteNibblesToFile
@ -155,63 +149,57 @@ int ReadNibblesFromFile(const char *name, int size, Nibble *dest)
It returns to the caller a status code It returns to the caller a status code
.call : .call :
st = WriteNibblesToFile(src, size, name); st = WriteNibblesToFile(src, size, name);
.input : .input :
const Nibble *src, pointer to data to be written const Nibble *src, pointer to data to be written
int size, # of nibble to write int size, # of nibble to write
const char *name, file name const char *name, file name
.output : .output :
int st, status code int st, status code
.status_codes : .status_codes :
DISK_IO_I_CALLED (signalled) DISK_IO_I_CALLED (signalled)
DISK_IO_E_OPEN DISK_IO_E_OPEN
DISK_IO_E_PUTC DISK_IO_E_PUTC
DISK_IO_E_CLOSE DISK_IO_E_CLOSE
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
.- */ .- */
int WriteNibblesToFile(const Nibble *src, int size, const char *name) int WriteNibblesToFile( const Nibble* src, int size, const char* name )
{ {
FILE *f; FILE* f;
int i; int i;
int by; int by;
int st = DISK_IO_S_OK; int st = DISK_IO_S_OK;
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteNibblesToFile"); debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteNibblesToFile" );
if((f = fopen(name, "wb")) == (FILE *)NULL) if ( ( f = fopen( name, "wb" ) ) == ( FILE* )NULL ) {
{
ChfErrnoCondition;
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
}
else
{
for(i=0; i<size;)
{
by = (int)src[i++];
by |= (int)src[i++] << 4;
if(putc(by, f) == EOF)
{
ChfErrnoCondition; ChfErrnoCondition;
ChfCondition st=DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd; ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
break;
}
} }
if(fclose(f) == EOF) else {
{ for ( i = 0; i < size; ) {
ChfErrnoCondition; by = ( int )src[ i++ ];
ChfCondition st=DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd; by |= ( int )src[ i++ ] << 4;
}
}
return st; if ( putc( by, f ) == EOF ) {
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
break;
}
}
if ( fclose( f ) == EOF ) {
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
}
}
return st;
} }
/* .+ /* .+
.title : ReadStructFromFile .title : ReadStructFromFile
@ -222,48 +210,44 @@ int WriteNibblesToFile(const Nibble *src, int size, const char *name)
from the disk file 'name' and returns a status code to the caller. from the disk file 'name' and returns a status code to the caller.
.call : .call :
st = ReadStructFromFile(name, s_size, s); st = ReadStructFromFile(name, s_size, s);
.input : .input :
const char *name, file name const char *name, file name
size_t s_size, structure size size_t s_size, structure size
.output : .output :
void *s, pointer to the structure void *s, pointer to the structure
.status_codes : .status_codes :
DISK_IO_I_CALLED (signalled) DISK_IO_I_CALLED (signalled)
DISK_IO_E_OPEN DISK_IO_E_OPEN
DISK_IO_E_READ DISK_IO_E_READ
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
.- */ .- */
int ReadStructFromFile(const char *name, size_t s_size, void *s) int ReadStructFromFile( const char* name, size_t s_size, void* s )
{ {
FILE *f; FILE* f;
int st = DISK_IO_S_OK; int st = DISK_IO_S_OK;
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadStructFromFile"); debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadStructFromFile" );
if((f = fopen(name, "rb")) == (FILE *)NULL) if ( ( f = fopen( name, "rb" ) ) == ( FILE* )NULL ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
}
else
{
if(fread(s, s_size, (size_t)1, f) != 1)
{
ChfErrnoCondition;
ChfCondition st=DISK_IO_E_READ, CHF_ERROR, name ChfEnd;
} }
(void)fclose(f); else {
} if ( fread( s, s_size, ( size_t )1, f ) != 1 ) {
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_READ, CHF_ERROR, name ChfEnd;
}
return st; ( void )fclose( f );
}
return st;
} }
/* .+ /* .+
.title : WriteStructToFile .title : WriteStructToFile
@ -274,49 +258,45 @@ int ReadStructFromFile(const char *name, size_t s_size, void *s)
'name' and returns to the caller a status code. 'name' and returns to the caller a status code.
.call : .call :
st =WriteStructToFile(s, s_size, name); st =WriteStructToFile(s, s_size, name);
.input : .input :
const void *s, pointer to the structure to be written const void *s, pointer to the structure to be written
size_t s_size, structure size size_t s_size, structure size
const char *name, output file name const char *name, output file name
.output : .output :
int st, status code int st, status code
.status_codes : .status_codes :
DISK_IO_I_CALLED (signalled) DISK_IO_I_CALLED (signalled)
DISK_IO_E_OPEN DISK_IO_E_OPEN
DISK_IO_E_WRITE DISK_IO_E_WRITE
DISK_IO_E_CLOSE DISK_IO_E_CLOSE
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
.- */ .- */
int WriteStructToFile(const void *s, size_t s_size, const char *name) int WriteStructToFile( const void* s, size_t s_size, const char* name )
{ {
FILE *f; FILE* f;
int st = DISK_IO_S_OK; int st = DISK_IO_S_OK;
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteStructToFile"); debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteStructToFile" );
if((f = fopen(name, "wb")) == (FILE *)NULL) if ( ( f = fopen( name, "wb" ) ) == ( FILE* )NULL ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
}
else
{
if(fwrite(s, s_size, (size_t)1, f) != 1)
{
ChfErrnoCondition;
ChfCondition st=DISK_IO_E_WRITE, CHF_ERROR, name ChfEnd;
} }
if(fclose(f) == EOF) else {
{ if ( fwrite( s, s_size, ( size_t )1, f ) != 1 ) {
ChfErrnoCondition; ChfErrnoCondition;
ChfCondition st=DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd; ChfCondition st = DISK_IO_E_WRITE, CHF_ERROR, name ChfEnd;
} }
}
return st; if ( fclose( f ) == EOF ) {
ChfErrnoCondition;
ChfCondition st = DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
}
}
return st;
} }

View file

@ -68,33 +68,29 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define DISK_IO_S_OK 0 /* Function completed succesfully */ #define DISK_IO_S_OK 0 /* Function completed succesfully */
#define DISK_IO_I_CALLED 101 /* Function %s called */ #define DISK_IO_I_CALLED 101 /* Function %s called */
#define DISK_IO_E_OPEN 401 /* Open file %s failed */ #define DISK_IO_E_OPEN 401 /* Open file %s failed */
#define DISK_IO_E_GETC 402 /* getc() from file %s failed */ #define DISK_IO_E_GETC 402 /* getc() from file %s failed */
#define DISK_IO_E_PUTC 403 /* putc() to file %s failed */ #define DISK_IO_E_PUTC 403 /* putc() to file %s failed */
#define DISK_IO_E_READ 404 /* fread() from file %s failed */ #define DISK_IO_E_READ 404 /* fread() from file %s failed */
#define DISK_IO_E_WRITE 405 /* fwrite() to file %s failed */ #define DISK_IO_E_WRITE 405 /* fwrite() to file %s failed */
#define DISK_IO_E_CLOSE 406 /* Close file %s failed */ #define DISK_IO_E_CLOSE 406 /* Close file %s failed */
#define DISK_IO_E_BAD_HDR 407 /* File %s has a bad header */ #define DISK_IO_E_BAD_HDR 407 /* File %s has a bad header */
#define DISK_IO_E_SIZE 408 /* File %s too large */ #define DISK_IO_E_SIZE 408 /* File %s too large */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
int ReadNibblesFromFile(const char *name, int size, Nibble *dest); int ReadNibblesFromFile( const char* name, int size, Nibble* dest );
int WriteNibblesToFile(const Nibble *src, int size, const char *name); int WriteNibblesToFile( const Nibble* src, int size, const char* name );
int ReadStructFromFile(const char *name, size_t s_size, void *s); int ReadStructFromFile( const char* name, size_t s_size, void* s );
int WriteStructToFile(const void *s, size_t s_size, const char *name); int WriteStructToFile( const void* s, size_t s_size, const char* name );
int ReadObjectFromFile( int ReadObjectFromFile( const char* name, const char* hdr, Address start, Address end );
const char *name, const char *hdr, Address start, Address end); int WriteObjectToFile( Address start, Address end, const char* hdr, const char* name );
int WriteObjectToFile(
Address start, Address end, const char *hdr, const char *name);

View file

@ -75,10 +75,9 @@ static char rcs_id[] = "$Id: disk_io_obj.c,v 4.1 2000/12/11 09:54:19 cibrario Re
#include "disk_io.h" #include "disk_io.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID #define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/* .+ /* .+
.title : ReadObjectFromFile .title : ReadObjectFromFile
@ -104,111 +103,100 @@ static char rcs_id[] = "$Id: disk_io_obj.c,v 4.1 2000/12/11 09:54:19 cibrario Re
This function returns to the caller a status code. This function returns to the caller a status code.
.call : .call :
st = ReadObjectFromFile(name, hdr, start, end); st = ReadObjectFromFile(name, hdr, start, end);
.input : .input :
const char *name, input file name const char *name, input file name
const char *hdr, file header const char *hdr, file header
Address start, start address (inclusive) Address start, start address (inclusive)
Address end, end address (exclusive) Address end, end address (exclusive)
.output : .output :
int st, status code int st, status code
.status_codes : .status_codes :
DISK_IO_I_CALLED (signalled) DISK_IO_I_CALLED (signalled)
DISK_IO_E_OPEN DISK_IO_E_OPEN
DISK_IO_E_GETC DISK_IO_E_GETC
DISK_IO_E_BAD_HDR DISK_IO_E_BAD_HDR
DISK_IO_E_SIZE DISK_IO_E_SIZE
.notes : .notes :
3.14, 10-Nov-2000, creation 3.14, 10-Nov-2000, creation
.- */ .- */
int ReadObjectFromFile( int ReadObjectFromFile( const char* name, const char* hdr, Address start, Address end )
const char *name, const char *hdr, Address start, Address end)
{ {
size_t hdr_len = strlen(hdr); size_t hdr_len = strlen( hdr );
FILE *f; FILE* f;
int i; int i;
int by; int by;
Address cur; Address cur;
#define N_SAVE_AREA 10 #define N_SAVE_AREA 10
Nibble save_area[N_SAVE_AREA]; Nibble save_area[ N_SAVE_AREA ];
int st = DISK_IO_S_OK; int st = DISK_IO_S_OK;
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadObjectFromFile"); debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadObjectFromFile" );
/* Save first nibbles of target space into save_area */ /* Save first nibbles of target space into save_area */
for(cur=start, i=0; cur < end && i<N_SAVE_AREA; cur++, i++) for ( cur = start, i = 0; cur < end && i < N_SAVE_AREA; cur++, i++ )
save_area[i] = ReadNibble(cur); save_area[ i ] = ReadNibble( cur );
if((f = fopen(name, "rb")) == (FILE *)NULL) if ( ( f = fopen( name, "rb" ) ) == ( FILE* )NULL ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} }
else else {
{ /* Check and skip header */
/* Check and skip header */ for ( i = 0; i < hdr_len; i++ ) {
for(i=0; i<hdr_len; i++) by = getc( f );
{
by = getc(f);
if(by == EOF) if ( by == EOF ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_GETC, CHF_ERROR, name ChfEnd; break;
break; }
}
else if(hdr[i] != '?' && by != hdr[i]) else if ( hdr[ i ] != '?' && by != hdr[ i ] ) {
{ ChfCondition st = DISK_IO_E_BAD_HDR, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_BAD_HDR, CHF_ERROR, name ChfEnd; break;
break; }
} }
}
if(st == DISK_IO_S_OK) if ( st == DISK_IO_S_OK ) {
{ cur = start;
cur = start;
/* Header check/skip OK; transfer */ /* Header check/skip OK; transfer */
while((by = getc(f)) != EOF) while ( ( by = getc( f ) ) != EOF ) {
{ /* Next byte available in by; check available space */
/* Next byte available in by; check available space */ if ( cur >= end - 1 ) {
if(cur >= end-1) ChfCondition st = DISK_IO_E_SIZE, CHF_ERROR, name ChfEnd;
{ break;
ChfCondition st=DISK_IO_E_SIZE, CHF_ERROR, name ChfEnd; }
break;
}
/* Store it */ /* Store it */
WriteNibble(cur++, (Nibble)(by & 0x0F)); WriteNibble( cur++, ( Nibble )( by & 0x0F ) );
WriteNibble(cur++, (Nibble)((by & 0xF0) >> 4)); WriteNibble( cur++, ( Nibble )( ( by & 0xF0 ) >> 4 ) );
} }
/* Check why getc() failed */ /* Check why getc() failed */
if(ferror(f) && !feof(f)) if ( ferror( f ) && !feof( f ) ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_GETC, CHF_ERROR, name ChfEnd; }
}
/* Recover from save_area if transfer failed */ /* Recover from save_area if transfer failed */
if(st) if ( st )
for(cur=start, i=0; cur < end && i<N_SAVE_AREA; cur++, i++) for ( cur = start, i = 0; cur < end && i < N_SAVE_AREA; cur++, i++ )
WriteNibble(cur, save_area[i]); WriteNibble( cur, save_area[ i ] );
} }
(void)fclose(f); ( void )fclose( f );
} }
return st; return st;
} }
/* .+ /* .+
.title : WriteObjectToFile .title : WriteObjectToFile
@ -225,92 +213,81 @@ int ReadObjectFromFile(
This function returns to the caller a status code. This function returns to the caller a status code.
.call : .call :
st = WriteObjectToFile(start, end, hdr, name); st = WriteObjectToFile(start, end, hdr, name);
.input : .input :
Address start, start address (inclusive) Address start, start address (inclusive)
Address end, end address (exclusive) Address end, end address (exclusive)
const char *hdr, file header const char *hdr, file header
const char *name, output file name const char *name, output file name
.output : .output :
int st, status code int st, status code
.status_codes : .status_codes :
DISK_IO_I_CALLED (signalled) DISK_IO_I_CALLED (signalled)
DISK_IO_E_OPEN DISK_IO_E_OPEN
DISK_IO_E_PUTC DISK_IO_E_PUTC
DISK_IO_E_CLOSE DISK_IO_E_CLOSE
.notes : .notes :
3.14, 10-Nov-2000, creation 3.14, 10-Nov-2000, creation
.- */ .- */
int WriteObjectToFile( int WriteObjectToFile( Address start, Address end, const char* hdr, const char* name )
Address start, Address end, const char *hdr, const char *name)
{ {
size_t hdr_len = strlen(hdr); size_t hdr_len = strlen( hdr );
FILE *f; FILE* f;
int i; int i;
int by; int by;
Address cur; Address cur;
int st = DISK_IO_S_OK; int st = DISK_IO_S_OK;
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteObjectFromFile"); debug1( DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteObjectFromFile" );
if((f = fopen(name, "wb")) == (FILE *)NULL) if ( ( f = fopen( name, "wb" ) ) == ( FILE* )NULL ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
} }
else else {
{ /* Write header; replace wildcard character '?' with 'S' */
/* Write header; replace wildcard character '?' with 'S' */ for ( i = 0; i < hdr_len; i++ ) {
for(i=0; i<hdr_len; i++) if ( putc( hdr[ i ] == '?' ? 'S' : hdr[ i ], f ) == EOF ) {
{ ChfErrnoCondition;
if(putc(hdr[i] == '?' ? 'S' : hdr[i], f) == EOF) ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
{ break;
ChfErrnoCondition; }
ChfCondition st=DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd; }
break;
}
}
if(st == DISK_IO_S_OK) if ( st == DISK_IO_S_OK ) {
{ cur = start;
cur = start;
while(cur < end-1) while ( cur < end - 1 ) {
{ /* Make a byte with two nibbles */
/* Make a byte with two nibbles */ by = ( int )ReadNibble( cur++ );
by = (int)ReadNibble(cur++); by |= ( int )ReadNibble( cur++ ) << 4;
by |= (int)ReadNibble(cur++) << 4;
if(putc(by, f) == EOF) if ( putc( by, f ) == EOF ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd; break;
break; }
} }
}
/* Write the last odd nibble, if necessary */ /* Write the last odd nibble, if necessary */
if(st == DISK_IO_S_OK && cur == end-1) if ( st == DISK_IO_S_OK && cur == end - 1 ) {
{ by = ( int )ReadNibble( cur++ );
by = (int)ReadNibble(cur++);
if(putc(by, f) == EOF) if ( putc( by, f ) == EOF ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd; }
} }
} }
}
/* Close the output file anyway */ /* Close the output file anyway */
if(fclose(f) == EOF) if ( fclose( f ) == EOF ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition st = DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
ChfCondition st=DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd; }
}
} }
return st; return st;

View file

@ -52,10 +52,10 @@
x48 source code by Eddie C. Dost (ecd@dressler.de) x48 source code by Eddie C. Dost (ecd@dressler.de)
NOTE: In the current (r1.1) implementation, the control fields NOTE: In the current (r1.1) implementation, the control fields
mod_status.hdw.lcd_offset and mod_status.hdw.lcd_contrast are mod_status.hdw.lcd_offset and mod_status.hdw.lcd_contrast are
not supported. Therefore, the emulation accuracy is sometimes not supported. Therefore, the emulation accuracy is sometimes
poor; for example, the Equation Writer does not work well with poor; for example, the Equation Writer does not work well with
large equations. large equations.
.include : config.h, machdep.h, cpu.h, modules.h, display.h .include : config.h, machdep.h, cpu.h, modules.h, display.h
@ -97,7 +97,7 @@ static char rcs_id[] = "$Id: display.c,v 4.1.1.1 2002/11/11 16:12:46 cibrario Ex
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <setjmp.h> #include <setjmp.h>
#include <string.h> /* 3.1: memset() */ #include <string.h> /* 3.1: memset() */
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -109,157 +109,121 @@ static char rcs_id[] = "$Id: display.c,v 4.1.1.1 2002/11/11 16:12:46 cibrario Ex
#include "x11.h" #include "x11.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID X11_CHF_MODULE_ID #define CHF_MODULE_ID X11_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
#ifndef LCD_MAG #ifndef LCD_MAG
# define LCD_MAG 2 /* 4.1.1.1: Compat. default */ # define LCD_MAG 2 /* 4.1.1.1: Compat. default */
#endif #endif
#define NIBBLES_PER_ROW 34 /* 136 pixel total */ #define NIBBLES_PER_ROW 34 /* 136 pixel total */
#define MAX_ROWS 64 /* 64 rows total */ #define MAX_ROWS 64 /* 64 rows total */
#define N_ANN 6 /* # of annunciators */ #define N_ANN 6 /* # of annunciators */
#define LCD_X_ORIGIN 1+4*(LCD_MAG-1) /* x origin */ #define LCD_X_ORIGIN 1 + 4 * ( LCD_MAG - 1 ) /* x origin */
#if LCD_MAG==1 #if LCD_MAG == 1
# define LCD_Y_ORIGIN 14 /* y origin */ # define LCD_Y_ORIGIN 14 /* y origin */
#else #else
# define LCD_Y_ORIGIN 20 /* y origin */ # define LCD_Y_ORIGIN 20 /* y origin */
#endif #endif
/* 3.8: Origin and size of clip rectangle */ /* 3.8: Origin and size of clip rectangle */
#define LCD_CLIP_X_ORIGIN LCD_X_ORIGIN #define LCD_CLIP_X_ORIGIN LCD_X_ORIGIN
#define LCD_CLIP_Y_ORIGIN 0 /* Don't clip annunciators */ #define LCD_CLIP_Y_ORIGIN 0 /* Don't clip annunciators */
#define LCD_CLIP_WIDTH 131*LCD_MAG #define LCD_CLIP_WIDTH 131 * LCD_MAG
#define LCD_CLIP_HEIGHT LCD_Y_ORIGIN+64*LCD_MAG #define LCD_CLIP_HEIGHT LCD_Y_ORIGIN + 64 * LCD_MAG
#define MASK_ANN_LEFT 0x81 /* Annunciator's bit masks */
#define MASK_ANN_RIGHT 0x82
#define MASK_ANN_ALPHA 0x84
#define MASK_ANN_BATTERY 0x88
#define MASK_ANN_BUSY 0x90
#define MASK_ANN_IO 0xA0
#define MASK_ANN_LEFT 0x81 /* Annunciator's bit masks */
#define MASK_ANN_RIGHT 0x82
#define MASK_ANN_ALPHA 0x84
#define MASK_ANN_BATTERY 0x88
#define MASK_ANN_BUSY 0x90
#define MASK_ANN_IO 0xA0
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Static/Global variables Static/Global variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
static /*const*/ char nibble_bitmap_data[NIBBLE_VALUES][LCD_MAG] = static /*const*/ char nibble_bitmap_data[ NIBBLE_VALUES ][ LCD_MAG ] = {
{ #if LCD_MAG == 1
#if LCD_MAG==1 { 0x00 }, /* ---- */
{ 0x00 }, /* ---- */ { 0x01 }, /* *--- */
{ 0x01 }, /* *--- */ { 0x02 }, /* -*-- */
{ 0x02 }, /* -*-- */ { 0x03 }, /* **-- */
{ 0x03 }, /* **-- */ { 0x04 }, /* --*- */
{ 0x04 }, /* --*- */ { 0x05 }, /* *-*- */
{ 0x05 }, /* *-*- */ { 0x06 }, /* -**- */
{ 0x06 }, /* -**- */ { 0x07 }, /* ***- */
{ 0x07 }, /* ***- */ { 0x08 }, /* ---* */
{ 0x08 }, /* ---* */ { 0x09 }, /* *--* */
{ 0x09 }, /* *--* */ { 0x0a }, /* -*-* */
{ 0x0a }, /* -*-* */ { 0x0b }, /* **-* */
{ 0x0b }, /* **-* */ { 0x0c }, /* --** */
{ 0x0c }, /* --** */ { 0x0d }, /* *-** */
{ 0x0d }, /* *-** */ { 0x0e }, /* -*** */
{ 0x0e }, /* -*** */ { 0x0f } /* **** */
{ 0x0f } /* **** */ #elif LCD_MAG == 2
#elif LCD_MAG==2 { 0x00, 0x00 }, /* ---- */
{ 0x00, 0x00 }, /* ---- */ { 0x03, 0x03 }, /* *--- */
{ 0x03, 0x03 }, /* *--- */ { 0x0c, 0x0c }, /* -*-- */
{ 0x0c, 0x0c }, /* -*-- */ { 0x0f, 0x0f }, /* **-- */
{ 0x0f, 0x0f }, /* **-- */ { 0x30, 0x30 }, /* --*- */
{ 0x30, 0x30 }, /* --*- */ { 0x33, 0x33 }, /* *-*- */
{ 0x33, 0x33 }, /* *-*- */ { 0x3c, 0x3c }, /* -**- */
{ 0x3c, 0x3c }, /* -**- */ { 0x3f, 0x3f }, /* ***- */
{ 0x3f, 0x3f }, /* ***- */ { 0xc0, 0xc0 }, /* ---* */
{ 0xc0, 0xc0 }, /* ---* */ { 0xc3, 0xc3 }, /* *--* */
{ 0xc3, 0xc3 }, /* *--* */ { 0xcc, 0xcc }, /* -*-* */
{ 0xcc, 0xcc }, /* -*-* */ { 0xcf, 0xcf }, /* **-* */
{ 0xcf, 0xcf }, /* **-* */ { 0xf0, 0xf0 }, /* --** */
{ 0xf0, 0xf0 }, /* --** */ { 0xf3, 0xf3 }, /* *-** */
{ 0xf3, 0xf3 }, /* *-** */ { 0xfc, 0xfc }, /* -*** */
{ 0xfc, 0xfc }, /* -*** */ { 0xff, 0xff } /* **** */
{ 0xff, 0xff } /* **** */
#else #else
# error "Bad LCD_MAG; supported values are 1 and 2" # error "Bad LCD_MAG; supported values are 1 and 2"
#endif #endif
}; };
static /*const*/ struct static /*const*/ struct {
{ int mask; /* Bit mask */
int mask; /* Bit mask */ int x, y; /* Position */
int x, y; /* Position */ int w, h; /* Width, Height */
int w, h; /* Width, Height */ char bitmap_data[ 24 ]; /* Bitmap data */
char bitmap_data[24]; /* Bitmap data */
} }
#define ANN_X(i) (8*LCD_MAG+(22*LCD_MAG+1)*i) #define ANN_X( i ) ( 8 * LCD_MAG + ( 22 * LCD_MAG + 1 ) * i )
#define ANN_Y(i) (1+3*(LCD_MAG-1)) #define ANN_Y( i ) ( 1 + 3 * ( LCD_MAG - 1 ) )
ann_data[N_ANN] =
{
{ MASK_ANN_LEFT,
ANN_X(0), ANN_Y(0),
15, 12,
{ 0xfe, 0x3f, 0xff, 0x7f, 0x9f, 0x7f, 0xcf, 0x7f, 0xe7, 0x7f, 0x03, 0x78,
0x03, 0x70, 0xe7, 0x73, 0xcf, 0x73, 0x9f, 0x73, 0xff, 0x73, 0xfe, 0x33
}
},
{ MASK_ANN_RIGHT,
ANN_X(1), ANN_Y(1),
15, 12,
{ 0xfe, 0x3f, 0xff, 0x7f, 0xff, 0x7c, 0xff, 0x79, 0xff, 0x73, 0x0f, 0x60,
0x07, 0x60, 0xe7, 0x73, 0xe7, 0x79, 0xe7, 0x7c, 0xe7, 0x7f, 0xe6, 0x3f
}
},
{ MASK_ANN_ALPHA,
ANN_X(2), ANN_Y(2),
15, 12,
{ 0xe0, 0x03, 0x18, 0x44, 0x0c, 0x4c, 0x06, 0x2c, 0x07, 0x2c, 0x07, 0x1c,
0x07, 0x0c, 0x07, 0x0c, 0x07, 0x0e, 0x0e, 0x4d, 0xf8, 0x38, 0x00, 0x00
}
},
{ MASK_ANN_BATTERY,
ANN_X(3), ANN_Y(3),
15, 12,
{ 0x04, 0x10, 0x02, 0x20, 0x12, 0x24, 0x09, 0x48, 0xc9, 0x49, 0xc9, 0x49,
0xc9, 0x49, 0x09, 0x48, 0x12, 0x24, 0x02, 0x20, 0x04, 0x10, 0x00, 0x00
}
},
{ MASK_ANN_BUSY,
ANN_X(4), ANN_Y(4),
15, 12,
{ 0xfc, 0x1f, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01,
0x40, 0x01, 0x20, 0x02, 0x10, 0x04, 0xc8, 0x09, 0xe8, 0x0b, 0xfc, 0x1f
}
},
{ MASK_ANN_IO,
ANN_X(5), ANN_Y(5),
15, 12,
{ 0x0c, 0x00, 0x1e, 0x00, 0x33, 0x0c, 0x61, 0x18, 0xcc, 0x30, 0xfe, 0x7f,
0xfe, 0x7f, 0xcc, 0x30, 0x61, 0x18, 0x33, 0x0c, 0x1e, 0x00, 0x0c, 0x00
}
}
ann_data[ N_ANN ] = {
{MASK_ANN_LEFT, ANN_X( 0 ), ANN_Y( 0 ), 15, 12, { 0xfe, 0x3f, 0xff, 0x7f, 0x9f, 0x7f, 0xcf, 0x7f, 0xe7, 0x7f, 0x03, 0x78,
0x03, 0x70, 0xe7, 0x73, 0xcf, 0x73, 0x9f, 0x73, 0xff, 0x73, 0xfe, 0x33 } },
{MASK_ANN_RIGHT, ANN_X( 1 ), ANN_Y( 1 ), 15, 12, { 0xfe, 0x3f, 0xff, 0x7f, 0xff, 0x7c, 0xff, 0x79, 0xff, 0x73, 0x0f, 0x60,
0x07, 0x60, 0xe7, 0x73, 0xe7, 0x79, 0xe7, 0x7c, 0xe7, 0x7f, 0xe6, 0x3f } },
{MASK_ANN_ALPHA, ANN_X( 2 ), ANN_Y( 2 ), 15, 12, { 0xe0, 0x03, 0x18, 0x44, 0x0c, 0x4c, 0x06, 0x2c, 0x07, 0x2c, 0x07, 0x1c,
0x07, 0x0c, 0x07, 0x0c, 0x07, 0x0e, 0x0e, 0x4d, 0xf8, 0x38, 0x00, 0x00 } },
{MASK_ANN_BATTERY, ANN_X( 3 ), ANN_Y( 3 ), 15, 12, { 0x04, 0x10, 0x02, 0x20, 0x12, 0x24, 0x09, 0x48, 0xc9, 0x49, 0xc9, 0x49,
0xc9, 0x49, 0x09, 0x48, 0x12, 0x24, 0x02, 0x20, 0x04, 0x10, 0x00, 0x00 }},
{MASK_ANN_BUSY, ANN_X( 4 ), ANN_Y( 4 ), 15, 12, { 0xfc, 0x1f, 0x08, 0x08, 0x08, 0x08, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01,
0x40, 0x01, 0x20, 0x02, 0x10, 0x04, 0xc8, 0x09, 0xe8, 0x0b, 0xfc, 0x1f } },
{MASK_ANN_IO, ANN_X( 5 ), ANN_Y( 5 ), 15, 12, { 0x0c, 0x00, 0x1e, 0x00, 0x33, 0x0c, 0x61, 0x18, 0xcc, 0x30, 0xfe, 0x7f,
0xfe, 0x7f, 0xcc, 0x30, 0x61, 0x18, 0x33, 0x0c, 0x1e, 0x00, 0x0c, 0x00 } }
}; };
static Nibble lcd_buffer[MAX_ROWS][NIBBLES_PER_ROW]; static Nibble lcd_buffer[ MAX_ROWS ][ NIBBLES_PER_ROW ];
static int ann_buffer; static int ann_buffer;
static int clean; static int clean;
static Display *display; static Display* display;
static Window window; static Window window;
static GC gc; static GC gc;
static unsigned long fg_pixel, bg_pixel; static unsigned long fg_pixel, bg_pixel;
static unsigned int depth; static unsigned int depth;
static Pixmap nibble_pixmap[NIBBLE_VALUES]; static Pixmap nibble_pixmap[ NIBBLE_VALUES ];
static Pixmap ann_pixmap[N_ANN]; static Pixmap ann_pixmap[ N_ANN ];
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private functions Private functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -272,56 +236,43 @@ static Pixmap ann_pixmap[N_ANN];
stores them into the appropriate global variables. stores them into the appropriate global variables.
.call : .call :
InitPixmaps(); InitPixmaps();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
X11_I_CALLED X11_I_CALLED
X11_F_X_ERROR X11_F_X_ERROR
.notes : .notes :
1.1, 29-Jan-1998, creation 1.1, 29-Jan-1998, creation
.- */ .- */
static void InitPixmaps(void) static void InitPixmaps( void )
{ {
int i; int i;
debug1(DEBUG_C_TRACE, X11_I_CALLED, "InitPixmaps"); debug1( DEBUG_C_TRACE, X11_I_CALLED, "InitPixmaps" );
/* Initialize nibble_pixmap */ /* Initialize nibble_pixmap */
for(i=0; i<NIBBLE_VALUES; i++) for ( i = 0; i < NIBBLE_VALUES; i++ ) {
{ if ( ( nibble_pixmap[ i ] = XCreatePixmapFromBitmapData( display, window, nibble_bitmap_data[ i ], 4 * LCD_MAG, LCD_MAG, fg_pixel,
if((nibble_pixmap[i] = bg_pixel, depth ) ) == None ) {
XCreatePixmapFromBitmapData( ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
display, window, nibble_bitmap_data[i], 4*LCD_MAG, LCD_MAG, ChfSignal();
fg_pixel, bg_pixel, depth }
)) ==
None)
{
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
ChfSignal();
} }
}
/* Initialize ann_pixmap */ /* Initialize ann_pixmap */
for (i=0; i<N_ANN; i++) for ( i = 0; i < N_ANN; i++ ) {
{ if ( ( ann_pixmap[ i ] = XCreatePixmapFromBitmapData( display, window, ann_data[ i ].bitmap_data, ann_data[ i ].w, ann_data[ i ].h,
if((ann_pixmap[i] = fg_pixel, bg_pixel, depth ) ) == None ) {
XCreatePixmapFromBitmapData(display, window, ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
ann_data[i].bitmap_data, ann_data[i].w, ann_data[i].h, ChfSignal();
fg_pixel, bg_pixel, depth }
)) ==
None)
{
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
ChfSignal();
} }
}
} }
/* .+ /* .+
.title : ClearLcd .title : ClearLcd
@ -331,32 +282,31 @@ static void InitPixmaps(void)
This function clears the Lcd screen This function clears the Lcd screen
.call : .call :
ClearLcd(); ClearLcd();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
X11_I_CALLED X11_I_CALLED
.notes : .notes :
1.1, 29-Jan-1998, creation 1.1, 29-Jan-1998, creation
.- */ .- */
static void ClearLcd(void) static void ClearLcd( void )
{ {
debug1(DEBUG_C_TRACE, X11_I_CALLED, "ClearLcd"); debug1( DEBUG_C_TRACE, X11_I_CALLED, "ClearLcd" );
/* Clear Lcd display */ /* Clear Lcd display */
(void)memset((void *)lcd_buffer, 0, sizeof(lcd_buffer)); ( void )memset( ( void* )lcd_buffer, 0, sizeof( lcd_buffer ) );
ann_buffer = 0; ann_buffer = 0;
XClearWindow(display, window); XClearWindow( display, window );
XFlush(display); XFlush( display );
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public funcitons Public funcitons
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -369,86 +319,79 @@ static void ClearLcd(void)
The LCD screen is initially cleared. The LCD screen is initially cleared.
.call : .call :
InitLcd(lcd_display, lcd_window, lcd_fg_pixel, lcd_bg_pixel); InitLcd(lcd_display, lcd_window, lcd_fg_pixel, lcd_bg_pixel);
.input : .input :
Display *lcd_display, X display Display *lcd_display, X display
Window lcd_window, X window to be used for display Window lcd_window, X window to be used for display
unsigned long lcd_fg_pixel, foreground color to be used unsigned long lcd_fg_pixel, foreground color to be used
unsigned long lcd_bg_pixel, background color to be used unsigned long lcd_bg_pixel, background color to be used
.output : .output :
void void
.status_codes : .status_codes :
X11_I_CALLED X11_I_CALLED
X11_F_X_ERROR X11_F_X_ERROR
.notes : .notes :
1.1, 29-Jan-1998, creation 1.1, 29-Jan-1998, creation
3.8, 23-Oct-2000, bug fix: 3.8, 23-Oct-2000, bug fix:
- added clip rectangle to GC, to avoid drawing non-existent pixels. - added clip rectangle to GC, to avoid drawing non-existent pixels.
.- */ .- */
void InitLcd(Display *lcd_display, Window lcd_window, void InitLcd( Display* lcd_display, Window lcd_window, unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel )
unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel)
{ {
XWindowAttributes xwa; XWindowAttributes xwa;
XGCValues gc_values; XGCValues gc_values;
debug1(DEBUG_C_TRACE, X11_I_CALLED, "InitLcdWindow"); debug1( DEBUG_C_TRACE, X11_I_CALLED, "InitLcdWindow" );
display = lcd_display; display = lcd_display;
window = lcd_window; window = lcd_window;
fg_pixel = lcd_fg_pixel; fg_pixel = lcd_fg_pixel;
bg_pixel = lcd_bg_pixel; bg_pixel = lcd_bg_pixel;
/* Get window attributes and initialize window depth */ /* Get window attributes and initialize window depth */
if(XGetWindowAttributes(display, window, &xwa) == 0) if ( XGetWindowAttributes( display, window, &xwa ) == 0 ) {
{ ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd; ChfSignal();
ChfSignal(); }
}
depth = xwa.depth; depth = xwa.depth;
/* Create GC */ /* Create GC */
gc_values.function = GXcopy; gc_values.function = GXcopy;
gc_values.plane_mask = AllPlanes; gc_values.plane_mask = AllPlanes;
gc_values.subwindow_mode = IncludeInferiors; gc_values.subwindow_mode = IncludeInferiors;
gc_values.foreground = lcd_fg_pixel; gc_values.foreground = lcd_fg_pixel;
gc_values.background = lcd_bg_pixel; gc_values.background = lcd_bg_pixel;
gc_values.graphics_exposures = False; gc_values.graphics_exposures = False;
gc = XCreateGC(display, window, gc = XCreateGC( display, window, GCFunction | GCPlaneMask | GCForeground | GCBackground | GCSubwindowMode | GCGraphicsExposures,
GCFunction|GCPlaneMask|GCForeground|GCBackground|GCSubwindowMode| &gc_values );
GCGraphicsExposures,
&gc_values);
{ {
/* 3.8: This clip rectangle prevents XCopyArea() (in DrawLcd()) from /* 3.8: This clip rectangle prevents XCopyArea() (in DrawLcd()) from
drawing non-visible pixels drawing non-visible pixels
*/ */
XRectangle rect[1]; XRectangle rect[ 1 ];
rect[0].x = LCD_CLIP_X_ORIGIN; /* This is the clip rectangle */ rect[ 0 ].x = LCD_CLIP_X_ORIGIN; /* This is the clip rectangle */
rect[0].y = LCD_CLIP_Y_ORIGIN; rect[ 0 ].y = LCD_CLIP_Y_ORIGIN;
rect[0].width = LCD_CLIP_WIDTH; rect[ 0 ].width = LCD_CLIP_WIDTH;
rect[0].height = LCD_CLIP_HEIGHT; rect[ 0 ].height = LCD_CLIP_HEIGHT;
XSetClipRectangles( XSetClipRectangles( display, gc, 0, 0, /* Alsolute clip X,Y origin */
display, gc, rect, 1, YXBanded );
0, 0, /* Alsolute clip X,Y origin */ }
rect, 1, YXBanded);
}
/* Initialize Pixmaps */ /* Initialize Pixmaps */
InitPixmaps(); InitPixmaps();
/* Clear screen and initialize the static memory areas */ /* Clear screen and initialize the static memory areas */
ClearLcd(); ClearLcd();
/* Set the 'display is clean' flag */ /* Set the 'display is clean' flag */
clean = 1; clean = 1;
} }
/* .+ /* .+
.title : DrawLcd .title : DrawLcd
@ -459,146 +402,113 @@ void InitLcd(Display *lcd_display, Window lcd_window,
the mod_status.hdw structure. the mod_status.hdw structure.
.call : .call :
DrawLcd(); DrawLcd();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
X11_I_CALLED X11_I_CALLED
X11_I_LCD_PAR X11_I_LCD_PAR
.notes : .notes :
1.1, 29-Jan-1998, creation 1.1, 29-Jan-1998, creation
.- */ .- */
void DrawLcd(void) void DrawLcd( void )
{ {
Address addr = mod_status.hdw.lcd_base_addr; Address addr = mod_status.hdw.lcd_base_addr;
int y, x; int y, x;
Nibble v; Nibble v;
debug1(DEBUG_C_TRACE, X11_I_CALLED, "DrawLcd"); debug1( DEBUG_C_TRACE, X11_I_CALLED, "DrawLcd" );
/* If the debug class DEBUG_C_DISPLAY is enabled, print the display /* If the debug class DEBUG_C_DISPLAY is enabled, print the display
parameters parameters
*/ */
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_base_addr", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_base_addr", ( int )mod_status.hdw.lcd_base_addr );
(int)mod_status.hdw.lcd_base_addr);
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_on", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_on", ( int )mod_status.hdw.lcd_on );
(int)mod_status.hdw.lcd_on);
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_contrast", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_contrast", ( int )mod_status.hdw.lcd_contrast );
(int)mod_status.hdw.lcd_contrast);
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_vlc", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_vlc", ( int )mod_status.hdw.lcd_vlc );
(int)mod_status.hdw.lcd_vlc);
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_offset", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_offset", ( int )mod_status.hdw.lcd_offset );
(int)mod_status.hdw.lcd_offset);
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_line_offset", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_line_offset", ( int )mod_status.hdw.lcd_line_offset );
(int)mod_status.hdw.lcd_line_offset);
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_menu_addr", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_menu_addr", ( int )mod_status.hdw.lcd_menu_addr );
(int)mod_status.hdw.lcd_menu_addr);
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_ann", debug2( DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_ann", ( int )mod_status.hdw.lcd_ann );
(int)mod_status.hdw.lcd_ann);
/* Check if display is on */ /* Check if display is on */
if(!mod_status.hdw.lcd_on) if ( !mod_status.hdw.lcd_on ) {
{ /* Display is off; clear lcd if necessary */
/* Display is off; clear lcd if necessary */ if ( !clean ) {
if(!clean) /* Set the 'display is clean' flag and clear the screen */
{ clean = 1;
/* Set the 'display is clean' flag and clear the screen */ ClearLcd();
clean = 1; }
ClearLcd(); return;
}
return;
}
/* The display is on and will be no longer clean */
clean = 0;
/* Scan active display rows */
for(y=0; y<=mod_status.hdw.lcd_vlc; y++)
{
/* Scan columns */
for(x=0; x<NIBBLES_PER_ROW; x++)
{
v = FetchNibble(addr++);
if( v != lcd_buffer[y][x] )
{
lcd_buffer[y][x] = v;
XCopyArea(display, nibble_pixmap[(int)v], window, gc,
0, 0, /* src_x, src_y */
4*LCD_MAG, LCD_MAG, /* width, height */
x*4*LCD_MAG + LCD_X_ORIGIN,
y*LCD_MAG + LCD_Y_ORIGIN
);
}
} }
addr += mod_status.hdw.lcd_line_offset; /* The display is on and will be no longer clean */
} clean = 0;
/* Scan menu display rows */ /* Scan active display rows */
addr = mod_status.hdw.lcd_menu_addr; for ( y = 0; y <= mod_status.hdw.lcd_vlc; y++ ) {
for(; y<MAX_ROWS; y++) /* Scan columns */
{ for ( x = 0; x < NIBBLES_PER_ROW; x++ ) {
/* Scan columns */ v = FetchNibble( addr++ );
for(x=0; x<NIBBLES_PER_ROW; x++) if ( v != lcd_buffer[ y ][ x ] ) {
{ lcd_buffer[ y ][ x ] = v;
v = FetchNibble(addr++);
if( v != lcd_buffer[y][x] ) XCopyArea( display, nibble_pixmap[ ( int )v ], window, gc, 0, 0, /* src_x, src_y */
{ 4 * LCD_MAG, LCD_MAG, /* width, height */
lcd_buffer[y][x] = v; x * 4 * LCD_MAG + LCD_X_ORIGIN, y * LCD_MAG + LCD_Y_ORIGIN );
XCopyArea(display, nibble_pixmap[(int)v], window, gc, }
0, 0, /* src_x, src_y */ }
4*LCD_MAG, LCD_MAG, /* width, height */
x*4*LCD_MAG + LCD_X_ORIGIN, addr += mod_status.hdw.lcd_line_offset;
y*LCD_MAG + LCD_Y_ORIGIN
);
}
} }
}
/* Scan annunciators */ /* Scan menu display rows */
if(mod_status.hdw.lcd_ann != ann_buffer) addr = mod_status.hdw.lcd_menu_addr;
{ for ( ; y < MAX_ROWS; y++ ) {
ann_buffer = mod_status.hdw.lcd_ann; /* Scan columns */
for ( x = 0; x < NIBBLES_PER_ROW; x++ ) {
for(y=0; y<N_ANN; y++) v = FetchNibble( addr++ );
{ if ( v != lcd_buffer[ y ][ x ] ) {
if((ann_buffer & ann_data[y].mask) == ann_data[y].mask) lcd_buffer[ y ][ x ] = v;
{ XCopyArea( display, nibble_pixmap[ ( int )v ], window, gc, 0, 0, /* src_x, src_y */
XCopyArea(display, ann_pixmap[y], window, gc, 4 * LCD_MAG, LCD_MAG, /* width, height */
0, 0, /* src_x, src_y */ x * 4 * LCD_MAG + LCD_X_ORIGIN, y * LCD_MAG + LCD_Y_ORIGIN );
ann_data[y].w, ann_data[y].h, /* width, height */ }
ann_data[y].x, }
ann_data[y].y
);
}
else
{
XClearArea(display, window,
ann_data[y].x, ann_data[y].y,
ann_data[y].w, ann_data[y].h,
False /* No exposures */
);
}
} }
}
/* Flush display */ /* Scan annunciators */
XFlush(display); if ( mod_status.hdw.lcd_ann != ann_buffer ) {
ann_buffer = mod_status.hdw.lcd_ann;
for ( y = 0; y < N_ANN; y++ ) {
if ( ( ann_buffer & ann_data[ y ].mask ) == ann_data[ y ].mask ) {
XCopyArea( display, ann_pixmap[ y ], window, gc, 0, 0, /* src_x, src_y */
ann_data[ y ].w, ann_data[ y ].h, /* width, height */
ann_data[ y ].x, ann_data[ y ].y );
}
else {
XClearArea( display, window, ann_data[ y ].x, ann_data[ y ].y, ann_data[ y ].w, ann_data[ y ].h, False /* No exposures */
);
}
}
}
/* Flush display */
XFlush( display );
} }
/* .+ /* .+
.title : RefreshLcd .title : RefreshLcd
@ -608,21 +518,21 @@ void DrawLcd(void)
This function refreshes the Lcd screen after a X Window Expose event. This function refreshes the Lcd screen after a X Window Expose event.
.call : .call :
RefreshLcd(); RefreshLcd();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
X11_I_CALLED X11_I_CALLED
.notes : .notes :
1.1, 17-Feb-1998, creation 1.1, 17-Feb-1998, creation
.- */ .- */
void RefreshLcd(void) void RefreshLcd( void )
{ {
debug1(DEBUG_C_TRACE, X11_I_CALLED, "RefreshLcd"); debug1( DEBUG_C_TRACE, X11_I_CALLED, "RefreshLcd" );
ClearLcd(); ClearLcd();
DrawLcd(); DrawLcd();
} }

View file

@ -66,28 +66,23 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Data type definitions - require config.h, machdep.h, cpu.h Data type definitions - require config.h, machdep.h, cpu.h
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macros Macros
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Global variables Global variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
void InitLcd(Display *lcd_display, Window lcd_window, void InitLcd( Display* lcd_display, Window lcd_window, unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel );
unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel);
void DrawLcd(void); void DrawLcd( void );
void RefreshLcd(void); void RefreshLcd( void );

View file

@ -130,17 +130,16 @@ static char rcs_id[] = "$Id: emulator.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
#include "args.h" #include "args.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID CPU_CHF_MODULE_ID #define CHF_MODULE_ID CPU_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private macros / variables / functions Private macros / variables / functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define T1_MULTIPLIER (8192/16) /* T2/T1 increment ratio */ #define T1_MULTIPLIER ( 8192 / 16 ) /* T2/T1 increment ratio */
#define T1_INTERVAL 62500 /* us per T1 increment */ #define T1_INTERVAL 62500 /* us per T1 increment */
#define T2_INTERVAL 122 /* us per T2 increment */ #define T2_INTERVAL 122 /* us per T2 increment */
/* 3.1: MAX_IDLE_X_LOOP_TIMEOUT must be low enough to prevent overflow /* 3.1: MAX_IDLE_X_LOOP_TIMEOUT must be low enough to prevent overflow
of an int when computing the difference in microseconds between two of an int when computing the difference in microseconds between two
@ -155,383 +154,353 @@ static char rcs_id[] = "$Id: emulator.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
module will support asynchronous selection on pty fd and will module will support asynchronous selection on pty fd and will
be able to interact with the GUI's select mechanism. be able to interact with the GUI's select mechanism.
*/ */
#define T1_MS_MULTIPLIER 63 /* 3.1: Milliseconds per T1 tick (~) */ #define T1_MS_MULTIPLIER 63 /* 3.1: Milliseconds per T1 tick (~) */
#define T2_MS_DIVISOR 8 /* 3.1: T2 ticks per millisecond (~) */ #define T2_MS_DIVISOR 8 /* 3.1: T2 ticks per millisecond (~) */
#define MAX_IDLE_X_LOOP_TIMEOUT 1000 /* 3.1: Max timeout for IdleXLoop() */ #define MAX_IDLE_X_LOOP_TIMEOUT 1000 /* 3.1: Max timeout for IdleXLoop() */
#define T1_OVF_MASK NIBBLE_MASK /* 3.1: Timer overflow masks */ #define T1_OVF_MASK NIBBLE_MASK /* 3.1: Timer overflow masks */
#define T2_OVF_MASK 0xFFFFFFFF #define T2_OVF_MASK 0xFFFFFFFF
#define LCD_T1_MASK 0x3 /* LCD refresh timing mask */ #define LCD_T1_MASK 0x3 /* LCD refresh timing mask */
#define INT_T1_MASK 0xF /* Int. req. timing mask */ #define INT_T1_MASK 0xF /* Int. req. timing mask */
static int emulator_int_req = 0; /* Interrupt request flag */ static int emulator_int_req = 0; /* Interrupt request flag */
/* This function contains the main emulator loop; under normal conditions, /* This function contains the main emulator loop; under normal conditions,
it never returns to the caller. The only way to exit this function is it never returns to the caller. The only way to exit this function is
to signal a Chf condition that triggers an unwind operation. to signal a Chf condition that triggers an unwind operation.
*/ */
static void EmulatorLoop(void) static void EmulatorLoop( void )
{ {
struct timeval old_t, cur_t; struct timeval old_t, cur_t;
int ela; int ela;
int inner_loop = cpu_status.inner_loop; int inner_loop = cpu_status.inner_loop;
int t1_count = 0; int t1_count = 0;
int i, j; int i, j;
debug1(DEBUG_C_TRACE, CPU_I_CALLED, "EmulatorLoop"); debug1( DEBUG_C_TRACE, CPU_I_CALLED, "EmulatorLoop" );
/* Ignore past interrupt requests */ /* Ignore past interrupt requests */
emulator_int_req = 0; emulator_int_req = 0;
/* Get current time of day */ /* Get current time of day */
gettimeofday(&old_t, NULL); gettimeofday( &old_t, NULL );
while(1) while ( 1 ) {
{ /* T1 loop */
/* T1 loop */ for ( j = 0; j < T1_MULTIPLIER; j++ ) {
for(j=0; j<T1_MULTIPLIER; j++) /* Inner loop */
{ for ( i = 0; i < inner_loop; i++ )
/* Inner loop */ OneStep();
for(i=0; i<inner_loop; i++) OneStep();
/* T2 update */ /* T2 update */
if(mod_status.hdw.t2_ctrl & T2_CTRL_TRUN) if ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) {
{ if ( --mod_status.hdw.t2_val == 0xFFFFFFFF ) {
if(--mod_status.hdw.t2_val == 0xFFFFFFFF) debug1( DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl );
{
debug1(DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl);
mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ; mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ;
if(mod_status.hdw.t2_ctrl & T2_CTRL_WAKE) if ( mod_status.hdw.t2_ctrl & T2_CTRL_WAKE )
CpuWake(); CpuWake();
if(mod_status.hdw.t2_ctrl & T2_CTRL_INT) if ( mod_status.hdw.t2_ctrl & T2_CTRL_INT )
CpuIntRequest(INT_REQUEST_IRQ); CpuIntRequest( INT_REQUEST_IRQ );
} }
} }
} }
/* T1 update */ /* T1 update */
mod_status.hdw.t1_val = (mod_status.hdw.t1_val - 1) & NIBBLE_MASK; mod_status.hdw.t1_val = ( mod_status.hdw.t1_val - 1 ) & NIBBLE_MASK;
if(mod_status.hdw.t1_val == 0xF) if ( mod_status.hdw.t1_val == 0xF ) {
{ debug1( DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl );
debug1(DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl);
mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ; mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ;
if(mod_status.hdw.t1_ctrl & T1_CTRL_WAKE) if ( mod_status.hdw.t1_ctrl & T1_CTRL_WAKE )
CpuWake(); CpuWake();
if(mod_status.hdw.t1_ctrl & T1_CTRL_INT) if ( mod_status.hdw.t1_ctrl & T1_CTRL_INT )
CpuIntRequest(INT_REQUEST_IRQ); CpuIntRequest( INT_REQUEST_IRQ );
} }
/* LCD update */ /* LCD update */
if((t1_count++ & LCD_T1_MASK) == 0) DrawLcd(); if ( ( t1_count++ & LCD_T1_MASK ) == 0 )
DrawLcd();
/* Emulator Interrupt Request */ /* Emulator Interrupt Request */
if((t1_count & INT_T1_MASK) == 0 && emulator_int_req) if ( ( t1_count & INT_T1_MASK ) == 0 && emulator_int_req ) {
{ ChfCondition CPU_I_EMULATOR_INT, CHF_INFO ChfEnd;
ChfCondition CPU_I_EMULATOR_INT, CHF_INFO ChfEnd; ChfSignal();
ChfSignal(); }
}
/* X Events handling */ /* X Events handling */
HandleXEvents(); HandleXEvents();
/* Handle serial port */ /* Handle serial port */
HandleSerial(); HandleSerial();
/* Adjust inner_loop limit */ /* Adjust inner_loop limit */
gettimeofday(&cur_t, NULL); gettimeofday( &cur_t, NULL );
ela = (cur_t.tv_sec - old_t.tv_sec) * 1000000 + ela = ( cur_t.tv_sec - old_t.tv_sec ) * 1000000 + ( cur_t.tv_usec - old_t.tv_usec );
(cur_t.tv_usec - old_t.tv_usec);
inner_loop = inner_loop * T1_INTERVAL / ela; inner_loop = inner_loop * T1_INTERVAL / ela;
if(inner_loop < INNER_LOOP_MIN) inner_loop = INNER_LOOP_MIN; if ( inner_loop < INNER_LOOP_MIN )
inner_loop = INNER_LOOP_MIN;
#ifdef REAL_CPU_SPEED #ifdef REAL_CPU_SPEED
/* 3.13: Force an upper limit to the CPU speed if the compile-time option /* 3.13: Force an upper limit to the CPU speed if the compile-time option
REAL_CPU_SPEED is defined: inner_loop is limited to REAL_CPU_SPEED is defined: inner_loop is limited to
cpu_status.inner_loop_max cpu_status.inner_loop_max
and the excess time, if any, is spent sleeping; usleep() is and the excess time, if any, is spent sleeping; usleep() is
BSD 4.3-specific, but most recent systems should offer it anyway, BSD 4.3-specific, but most recent systems should offer it anyway,
well, I hope. well, I hope.
The special value cpu_status.inner_loop_max==0 gives maximum speed. The special value cpu_status.inner_loop_max==0 gives maximum speed.
*/ */
if(cpu_status.inner_loop_max != 0 if ( cpu_status.inner_loop_max != 0 && inner_loop >= cpu_status.inner_loop_max ) {
&& inner_loop >= cpu_status.inner_loop_max) inner_loop = cpu_status.inner_loop_max;
{ if ( T1_INTERVAL > ela )
inner_loop = cpu_status.inner_loop_max; usleep( T1_INTERVAL - ela );
if(T1_INTERVAL > ela) usleep(T1_INTERVAL - ela); }
}
#endif #endif
cpu_status.inner_loop = inner_loop; cpu_status.inner_loop = inner_loop;
old_t = cur_t; old_t = cur_t;
} }
} }
/* Condition handler for the EmulatorLoop */ /* Condition handler for the EmulatorLoop */
static ChfAction EmulatorLoopHandler( static ChfAction EmulatorLoopHandler( const ChfDescriptor* d, const ChfState s, ChfPointer ctx )
const ChfDescriptor *d,
const ChfState s,
ChfPointer ctx
)
{ {
ChfAction act; ChfAction act;
/* Check Chf state */ /* Check Chf state */
switch(s) switch ( s ) {
{ /* 2.1: Chf release 2 fixed the spelling of 'SIGNALING' */
/* 2.1: Chf release 2 fixed the spelling of 'SIGNALING' */ case CHF_SIGNALING:
case CHF_SIGNALING: /* ChfSignal() in progress */
/* ChfSignal() in progress */ if ( ChfGetModuleId( d ) == CPU_CHF_MODULE_ID ) {
if(ChfGetModuleId(d) == CPU_CHF_MODULE_ID) /* Condition from CPU modules; check Condition Code */
{ switch ( ChfGetConditionCode( d ) ) {
/* Condition from CPU modules; check Condition Code */
switch(ChfGetConditionCode(d))
{
#ifdef CPU_SPIN_SHUTDN #ifdef CPU_SPIN_SHUTDN
case CPU_I_SHUTDN: case CPU_I_SHUTDN:
/* CPU shutdown signalled with CPU_SPIN_SHUTDN defined; /* CPU shutdown signalled with CPU_SPIN_SHUTDN defined;
Fatal error. Fatal error.
*/ */
ChfCondition CPU_F_BAD_SHUTDN, CHF_FATAL ChfEnd; ChfCondition CPU_F_BAD_SHUTDN, CHF_FATAL ChfEnd;
ChfSignal(); ChfSignal();
act = CHF_RESIGNAL; act = CHF_RESIGNAL;
break; break;
#else #else
case CPU_I_SHUTDN: case CPU_I_SHUTDN:
{ {
/* 3.1: CPU_SPIN_SHUTDN is not defined, and the cpu emulator /* 3.1: CPU_SPIN_SHUTDN is not defined, and the cpu emulator
has just executed a shutdown instruction. has just executed a shutdown instruction.
Let's do something a little tricky here: Let's do something a little tricky here:
1- redraw the LCD 1- redraw the LCD
2- handle serial port activities 2- handle serial port activities
3- determine which timer will expire first, and 3- determine which timer will expire first, and
compute an approximate value of the maximum duration compute an approximate value of the maximum duration
of the shutdown --> ms of the shutdown --> ms
4- handle serial port activities 4- handle serial port activities
5- enter the inner idle loop; it breaks when either an 5- enter the inner idle loop; it breaks when either an
X Event occurred (possibly clearing the shutdown) or X Event occurred (possibly clearing the shutdown) or
the shutdown timeout elapses the shutdown timeout elapses
6- determine the actual time we spend in the idle loop 6- determine the actual time we spend in the idle loop
(X timeouts are not accurate enough for this purpose) (X timeouts are not accurate enough for this purpose)
7- update T1 and T2, check their state and wake/interrupt 7- update T1 and T2, check their state and wake/interrupt
the CPU if necessary the CPU if necessary
Activities 3-7 above are enclosed in an outer loop because we Activities 3-7 above are enclosed in an outer loop because we
cannot be absolutely sure of the actual time spent cannot be absolutely sure of the actual time spent
in the idle loop; moreover, not all X Events actually in the idle loop; moreover, not all X Events actually
spool up the CPU. The outer loop breaks when the CPU is spool up the CPU. The outer loop breaks when the CPU is
actually brought out of shutdown. actually brought out of shutdown.
frac_t1 and frac_t2 contain the number of microseconds frac_t1 and frac_t2 contain the number of microseconds
not accounted for in the last T1/T2 update, respectively; not accounted for in the last T1/T2 update, respectively;
they help minimize the cumulative timing error induced they help minimize the cumulative timing error induced
by executing the outer idle loop more than once. by executing the outer idle loop more than once.
*/ */
struct timeval start_idle, end_idle; struct timeval start_idle, end_idle;
int frac_t1=0, frac_t2=0; int frac_t1 = 0, frac_t2 = 0;
gettimeofday(&start_idle, NULL); gettimeofday( &start_idle, NULL );
/* Redraw the LCD immediately before entering idle loop; /* Redraw the LCD immediately before entering idle loop;
this ensures that the latest LCD updated actually this ensures that the latest LCD updated actually
get to the screen. get to the screen.
*/ */
DrawLcd(); DrawLcd();
/* Handle serial port activity before entering the outer idle /* Handle serial port activity before entering the outer idle
loop, because this could possibly bring the cpu out of loop, because this could possibly bring the cpu out of
shutdown right now. shutdown right now.
*/ */
HandleSerial(); HandleSerial();
/* XXX /* XXX
If either timer has a pending service request, If either timer has a pending service request,
process it immediately. It is not clear why it was process it immediately. It is not clear why it was
not processed *before* shutdown, though. not processed *before* shutdown, though.
*/ */
if(mod_status.hdw.t1_ctrl & T1_CTRL_SREQ) if ( mod_status.hdw.t1_ctrl & T1_CTRL_SREQ ) {
{ if ( mod_status.hdw.t1_ctrl & T1_CTRL_WAKE )
if(mod_status.hdw.t1_ctrl & T1_CTRL_WAKE) CpuWake();
CpuWake();
if(mod_status.hdw.t1_ctrl & T1_CTRL_INT) if ( mod_status.hdw.t1_ctrl & T1_CTRL_INT )
CpuIntRequest(INT_REQUEST_IRQ); CpuIntRequest( INT_REQUEST_IRQ );
} }
if(mod_status.hdw.t2_ctrl & T2_CTRL_SREQ) if ( mod_status.hdw.t2_ctrl & T2_CTRL_SREQ ) {
{ if ( mod_status.hdw.t2_ctrl & T2_CTRL_WAKE )
if(mod_status.hdw.t2_ctrl & T2_CTRL_WAKE) CpuWake();
CpuWake();
if(mod_status.hdw.t2_ctrl & T2_CTRL_INT) if ( mod_status.hdw.t2_ctrl & T2_CTRL_INT )
CpuIntRequest(INT_REQUEST_IRQ); CpuIntRequest( INT_REQUEST_IRQ );
} }
while(cpu_status.shutdn) while ( cpu_status.shutdn ) {
{ unsigned long ms = MAX_IDLE_X_LOOP_TIMEOUT;
unsigned long ms = MAX_IDLE_X_LOOP_TIMEOUT; unsigned long mst;
unsigned long mst; int ela;
int ela; int ela_ticks;
int ela_ticks;
debug3(DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (during SHUTDN)", debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (during SHUTDN)", mod_status.hdw.t1_ctrl,
mod_status.hdw.t1_ctrl, mod_status.hdw.t1_val); mod_status.hdw.t1_val );
debug3(DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (during SHUTDN)", debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (during SHUTDN)", mod_status.hdw.t2_ctrl,
mod_status.hdw.t2_ctrl, mod_status.hdw.t2_val); mod_status.hdw.t2_val );
/* Determine which timer will expire first */ /* Determine which timer will expire first */
if(mod_status.hdw.t1_ctrl & (T1_CTRL_INT|T1_CTRL_WAKE)) if ( mod_status.hdw.t1_ctrl & ( T1_CTRL_INT | T1_CTRL_WAKE ) ) {
{ /* T1 will do something on expiration */
/* T1 will do something on expiration */ mst = ( ( unsigned long )mod_status.hdw.t1_val + 1 ) * T1_MS_MULTIPLIER;
mst = ((unsigned long)mod_status.hdw.t1_val + 1)
* T1_MS_MULTIPLIER;
debug2(DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T1", mst); debug2( DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T1", mst );
if(mst < ms) ms = mst; if ( mst < ms )
} ms = mst;
}
if((mod_status.hdw.t2_ctrl & T2_CTRL_TRUN) if ( ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) &&
&& (mod_status.hdw.t2_ctrl & (T2_CTRL_INT|T2_CTRL_WAKE))) ( mod_status.hdw.t2_ctrl & ( T2_CTRL_INT | T2_CTRL_WAKE ) ) ) {
{ /* T2 is running and will do something on expiration */
/* T2 is running and will do something on expiration */ mst = ( ( unsigned long )mod_status.hdw.t2_val + 1 ) / T2_MS_DIVISOR;
mst = ((unsigned long)mod_status.hdw.t2_val + 1)
/ T2_MS_DIVISOR;
debug2(DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T2", mst); debug2( DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T2", mst );
if(mst < ms) ms = mst; if ( mst < ms )
} ms = mst;
}
/* Handle serial port activities at each iteration of /* Handle serial port activities at each iteration of
the outer idle loop; this ensures that the serial the outer idle loop; this ensures that the serial
port emulation will not starve. port emulation will not starve.
*/ */
HandleSerial(); HandleSerial();
/* Enter idle loop, possibly with timeout; /* Enter idle loop, possibly with timeout;
The loop breaks when: The loop breaks when:
- any X Event occurs (possibly clearing the shutdown) - any X Event occurs (possibly clearing the shutdown)
- the given timeout expires - the given timeout expires
*/ */
debug1(DEBUG_C_TIMERS, CPU_I_IDLE_X_LOOP, ms); debug1( DEBUG_C_TIMERS, CPU_I_IDLE_X_LOOP, ms );
IdleXLoop(ms); IdleXLoop( ms );
/* End of idle loop; compute actual elapsed time */ /* End of idle loop; compute actual elapsed time */
gettimeofday(&end_idle, NULL); gettimeofday( &end_idle, NULL );
ela = (end_idle.tv_sec - start_idle.tv_sec) * 1000000 + ela = ( end_idle.tv_sec - start_idle.tv_sec ) * 1000000 + ( end_idle.tv_usec - start_idle.tv_usec );
(end_idle.tv_usec - start_idle.tv_usec);
/* Update start_idle here to contain lag */ /* Update start_idle here to contain lag */
start_idle = end_idle; start_idle = end_idle;
debug1(DEBUG_C_TIMERS, CPU_I_ELAPSED, ela); debug1( DEBUG_C_TIMERS, CPU_I_ELAPSED, ela );
/* Update timers and act accordingly */ /* Update timers and act accordingly */
ela_ticks = ((ela+frac_t1) + T1_INTERVAL/2) / T1_INTERVAL; ela_ticks = ( ( ela + frac_t1 ) + T1_INTERVAL / 2 ) / T1_INTERVAL;
frac_t1 = (ela+frac_t1) - ela_ticks * T1_INTERVAL; frac_t1 = ( ela + frac_t1 ) - ela_ticks * T1_INTERVAL;
if(ela_ticks > mod_status.hdw.t1_val) if ( ela_ticks > mod_status.hdw.t1_val ) {
{ debug1( DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl );
debug1(DEBUG_C_TIMERS, CPU_I_TIMER1_EX,
mod_status.hdw.t1_ctrl);
mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ; mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ;
if(mod_status.hdw.t1_ctrl & T1_CTRL_WAKE) if ( mod_status.hdw.t1_ctrl & T1_CTRL_WAKE )
CpuWake(); CpuWake();
if(mod_status.hdw.t1_ctrl & T1_CTRL_INT) if ( mod_status.hdw.t1_ctrl & T1_CTRL_INT )
CpuIntRequest(INT_REQUEST_IRQ); CpuIntRequest( INT_REQUEST_IRQ );
} }
mod_status.hdw.t1_val = mod_status.hdw.t1_val = ( mod_status.hdw.t1_val - ela_ticks ) & T1_OVF_MASK;
(mod_status.hdw.t1_val - ela_ticks) & T1_OVF_MASK;
if(mod_status.hdw.t2_ctrl & T2_CTRL_TRUN) if ( mod_status.hdw.t2_ctrl & T2_CTRL_TRUN ) {
{ ela_ticks = ( ( ela + frac_t2 ) + T2_INTERVAL / 2 ) / T2_INTERVAL;
ela_ticks = ((ela+frac_t2) + T2_INTERVAL/2) / T2_INTERVAL; frac_t2 = ( ela + frac_t2 ) - ela_ticks * T2_INTERVAL;
frac_t2 = (ela+frac_t2) - ela_ticks * T2_INTERVAL;
if(ela_ticks > mod_status.hdw.t2_val) if ( ela_ticks > mod_status.hdw.t2_val ) {
{ debug1( DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl );
debug1(DEBUG_C_TIMERS, CPU_I_TIMER2_EX,
mod_status.hdw.t2_ctrl);
mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ; mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ;
if(mod_status.hdw.t2_ctrl & T2_CTRL_WAKE) if ( mod_status.hdw.t2_ctrl & T2_CTRL_WAKE )
CpuWake(); CpuWake();
if(mod_status.hdw.t2_ctrl & T2_CTRL_INT) if ( mod_status.hdw.t2_ctrl & T2_CTRL_INT )
CpuIntRequest(INT_REQUEST_IRQ); CpuIntRequest( INT_REQUEST_IRQ );
} }
mod_status.hdw.t2_val = mod_status.hdw.t2_val = ( mod_status.hdw.t2_val - ela_ticks ) & T2_OVF_MASK;
(mod_status.hdw.t2_val - ela_ticks) & T2_OVF_MASK; }
} }
}
debug3(DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (after SHUTDN)", debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (after SHUTDN)", mod_status.hdw.t1_ctrl, mod_status.hdw.t1_val );
mod_status.hdw.t1_ctrl, mod_status.hdw.t1_val); debug3( DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (after SHUTDN)", mod_status.hdw.t2_ctrl, mod_status.hdw.t2_val );
debug3(DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (after SHUTDN)",
mod_status.hdw.t2_ctrl, mod_status.hdw.t2_val);
act = CHF_CONTINUE; act = CHF_CONTINUE;
} }
break; break;
#endif #endif
case CPU_I_EMULATOR_INT: case CPU_I_EMULATOR_INT:
/* Emulator interrupt; unwind */ /* Emulator interrupt; unwind */
act = CHF_UNWIND; act = CHF_UNWIND;
break; break;
default: default:
/* Condition Code not handled; resignal */ /* Condition Code not handled; resignal */
act = CHF_RESIGNAL; act = CHF_RESIGNAL;
} }
} }
else else
/* Condition from other modules; resignal */ /* Condition from other modules; resignal */
act = CHF_RESIGNAL; act = CHF_RESIGNAL;
break; break;
default: default:
/* Other states; resignal the condition */ /* Other states; resignal the condition */
act = CHF_RESIGNAL; act = CHF_RESIGNAL;
break; break;
} }
return act; return act;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
.title : Emulator .title : Emulator
@ -547,43 +516,40 @@ static ChfAction EmulatorLoopHandler(
a Chf Condition that triggers an unwind operation. a Chf Condition that triggers an unwind operation.
.call : .call :
Emulator(); Emulator();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
CPU_I_CALLED CPU_I_CALLED
CPU_I_TIMER1_EX CPU_I_TIMER1_EX
CPU_I_TIMER2_EX CPU_I_TIMER2_EX
Other conditions signalled by lower level modules Other conditions signalled by lower level modules
.notes : .notes :
1.1, 17-Feb-1998, creation 1.1, 17-Feb-1998, creation
.- */ .- */
void Emulator(void) void Emulator( void )
{ {
jmp_buf unwind_context; jmp_buf unwind_context;
debug1(DEBUG_C_TRACE, CPU_I_CALLED, "Emulator"); debug1( DEBUG_C_TRACE, CPU_I_CALLED, "Emulator" );
/* Setup unwind_context */ /* Setup unwind_context */
if(setjmp(unwind_context) == 0) if ( setjmp( unwind_context ) == 0 ) {
{ /* Push condition handler, with NULL context */
/* Push condition handler, with NULL context */ ChfPushHandler( EmulatorLoopHandler, &unwind_context, ( ChfPointer )NULL );
ChfPushHandler(EmulatorLoopHandler, &unwind_context, (ChfPointer)NULL);
/* Activate emulator loop */ /* Activate emulator loop */
EmulatorLoop(); EmulatorLoop();
} }
else else {
{ /* Unwinding after an emulator interrupt */
/* Unwinding after an emulator interrupt */ }
}
} }
/* .+ /* .+
.title : EmulatorIntRequest .title : EmulatorIntRequest
@ -595,22 +561,18 @@ void Emulator(void)
return to the caller. return to the caller.
.call : .call :
EmulatorIntRequest(); EmulatorIntRequest();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
* *
.notes : .notes :
1.1, 18-Feb-1998, creation 1.1, 18-Feb-1998, creation
.- */ .- */
void EmulatorIntRequest(void) void EmulatorIntRequest( void ) { emulator_int_req = 1; }
{
emulator_int_req = 1;
}
/* .+ /* .+
@ -623,14 +585,14 @@ void EmulatorIntRequest(void)
subsystems, too. subsystems, too.
.call : .call :
EmulatorInit(); EmulatorInit();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
* Status codes signaled by CpuInit() and CpuReset() * Status codes signaled by CpuInit() and CpuReset()
* Status codes signaled by ModInit() and ModReset() * Status codes signaled by ModInit() and ModReset()
.notes : .notes :
2.1, 8-Sep-2000, creation 2.1, 8-Sep-2000, creation
2.4, 12-Sep-2000, update 2.4, 12-Sep-2000, update
@ -642,24 +604,22 @@ void EmulatorIntRequest(void)
args.hw option. args.hw option.
.- */ .- */
void EmulatorInit(void) void EmulatorInit( void )
{ {
/* Select a module description table */ /* Select a module description table */
ModSelectDescription(args.hw); ModSelectDescription( args.hw );
/* Initialize cpu and modules subsystems */ /* Initialize cpu and modules subsystems */
CpuInit(); CpuInit();
ModInit(); ModInit();
/* Reset if appropriate */ /* Reset if appropriate */
if(args.reset) if ( args.reset ) {
{ CpuReset();
CpuReset(); ModReset();
ModReset();
} }
} }
/* .+ /* .+
.title : EmulatorExit .title : EmulatorExit
@ -672,30 +632,29 @@ void EmulatorInit(void)
returns to the caller unless an unrecoverable error occurs. returns to the caller unless an unrecoverable error occurs.
.call : .call :
EmulatorExit(opt); EmulatorExit(opt);
.input : .input :
enum ExitOption opt, emulator exit option enum ExitOption opt, emulator exit option
.output : .output :
void void
.status_codes : .status_codes :
* Status codes signaled by CpuSave() and ModSave() * Status codes signaled by CpuSave() and ModSave()
.notes : .notes :
2.1, 8-Sep-2000, creation 2.1, 8-Sep-2000, creation
.- */ .- */
void EmulatorExit(enum ExitOption opt) void EmulatorExit( enum ExitOption opt )
{ {
switch(opt) switch ( opt ) {
{
case SAVE_AND_EXIT: case SAVE_AND_EXIT:
/* Save state of cpu and modules subsystems */ /* Save state of cpu and modules subsystems */
ModSave(); ModSave();
CpuSave(); CpuSave();
break; break;
default: default:
/* Default behavior; do nothing */ /* Default behavior; do nothing */
break; break;
} }
} }

View file

@ -87,326 +87,273 @@ static char rcs_id[] = "$Id: flash49.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $"
#include "args.h" #include "args.h"
#define CHF_MODULE_ID FLASH_CHF_MODULE_ID #define CHF_MODULE_ID FLASH_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private Macro/Data type definitions Private Macro/Data type definitions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define BLOCK_SIZE 0x10000 #define BLOCK_SIZE 0x10000
#define BLOCK_BASE_MASK 0xFFFF #define BLOCK_BASE_MASK 0xFFFF
#define ByteAddress(address) ((address) >> 1)
#define NibbleAddress(address) ((address) << 1)
#define BlockBase(address) ((address) & ~BLOCK_BASE_MASK)
#define IsOdd(address) ((address) & 0x1)
#define LowNibble(d) ((Nibble)((d) & NIBBLE_MASK))
#define HighNibble(d) ((Nibble)(((d) >> 4) & NIBBLE_MASK))
#define ShiftHigh(d) ((d) << 4)
#define ByteAddress( address ) ( ( address ) >> 1 )
#define NibbleAddress( address ) ( ( address ) << 1 )
#define BlockBase( address ) ( ( address ) & ~BLOCK_BASE_MASK )
#define IsOdd( address ) ( ( address ) & 0x1 )
#define LowNibble( d ) ( ( Nibble )( ( d ) & NIBBLE_MASK ) )
#define HighNibble( d ) ( ( Nibble )( ( ( d ) >> 4 ) & NIBBLE_MASK ) )
#define ShiftHigh( d ) ( ( d ) << 4 )
/* Flash cycle types */ /* Flash cycle types */
enum FlashCycle enum FlashCycle {
{
FLASH_CYCLE_READ = 0, FLASH_CYCLE_READ = 0,
FLASH_CYCLE_WRITE, FLASH_CYCLE_WRITE,
FLASH_CYCLE_N /* Total # of cycle types */ FLASH_CYCLE_N /* Total # of cycle types */
}; };
/* State transition function */ /* State transition function */
typedef int (*FlashF) typedef int ( *FlashF )( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data );
(enum FlashState *state, enum FlashCycle cycle,
XAddress address, int data);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private state variables Private state variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* External storage */ /* External storage */
extern struct ModStatus_49 *mod_status_49; extern struct ModStatus_49* mod_status_49;
static int r_buffer; /* Nibble buffer during read */ static int r_buffer; /* Nibble buffer during read */
static int w_buffer; /* Nibble buffer during write */ static int w_buffer; /* Nibble buffer during write */
static enum FlashState fsm_state; /* FSM state */ static enum FlashState fsm_state; /* FSM state */
/* Write buffer */ /* Write buffer */
#define WB_COUNT_MASK 0x1F #define WB_COUNT_MASK 0x1F
#define WB_SIZE 0x20 #define WB_SIZE 0x20
static int wb_count; /* Counter for Write to Buffer */ static int wb_count; /* Counter for Write to Buffer */
static int wb_cdown; /* Count down */ static int wb_cdown; /* Count down */
static XAddress wb_start; /* Start address for Write to Buffer */ static XAddress wb_start; /* Start address for Write to Buffer */
static int wb[WB_SIZE]; /* Write buffer */ static int wb[ WB_SIZE ]; /* Write buffer */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
State transition private functions State transition private functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* This function is called by default for unhandled state transitions */ /* This function is called by default for unhandled state transitions */
static int BadCommand(enum FlashState *state, enum FlashCycle cycle, static int BadCommand( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
/* Unknown command: signal and reset state to FLASH_ST_READ_ARRAY */ /* Unknown command: signal and reset state to FLASH_ST_READ_ARRAY */
ChfCondition FLASH_W_BAD_CMD, CHF_WARNING, ChfCondition FLASH_W_BAD_CMD, CHF_WARNING, *state, cycle, address, data ChfEnd;
*state, cycle, address, data
ChfEnd;
ChfSignal(); ChfSignal();
*state = FLASH_ST_READ_ARRAY; *state = FLASH_ST_READ_ARRAY;
return 0; /* Dummy result */ return 0; /* Dummy result */
} }
/* This function is called to read the Flash Rom array */ /* This function is called to read the Flash Rom array */
static int ReadArray(enum FlashState *state, enum FlashCycle cycle, static int ReadArray( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
/* Read a byte from the array; no state transitions */ /* Read a byte from the array; no state transitions */
return return mod_status_49->flash[ NibbleAddress( address ) ] | ShiftHigh( mod_status_49->flash[ NibbleAddress( address ) + 1 ] );
mod_status_49->flash[NibbleAddress(address)]
| ShiftHigh(mod_status_49->flash[NibbleAddress(address)+1]);
} }
/* This function is called to parse the first byte of any command */ /* This function is called to parse the first byte of any command */
static int ParseCommand(enum FlashState *state, enum FlashCycle cycle, static int ParseCommand( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
switch(data) switch ( data ) {
{ case FLASH_CMD_READ_ARRAY:
case FLASH_CMD_READ_ARRAY: /* Transition to FLASH_ST_READ_ARRAY state */
/* Transition to FLASH_ST_READ_ARRAY state */ debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Array" );
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Array"); *state = FLASH_ST_READ_ARRAY;
*state = FLASH_ST_READ_ARRAY; break;
break;
case FLASH_CMD_CLR_SR: case FLASH_CMD_CLR_SR:
/* Clear status register; section 4.5 on Data Sheet. /* Clear status register; section 4.5 on Data Sheet.
The current implementation does nothing, because The current implementation does nothing, because
the value of the status register is fixed. No state transitions. the value of the status register is fixed. No state transitions.
*/ */
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Clear Status"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Clear Status" );
break; break;
case FLASH_CMD_WRITE_BUFFER: case FLASH_CMD_WRITE_BUFFER:
/* Write to Buffer; section 4.8 on Data Sheet. /* Write to Buffer; section 4.8 on Data Sheet.
Transition to FLASH_ST_READ_XSR state. Transition to FLASH_ST_READ_XSR state.
*/ */
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (start)"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (start)" );
*state = FLASH_ST_READ_XSR; *state = FLASH_ST_READ_XSR;
break; break;
case FLASH_CMD_READ_SR: case FLASH_CMD_READ_SR:
/* Read Status; section 4.4 on Data Sheet. /* Read Status; section 4.4 on Data Sheet.
Transition to FLASH_ST_READ_SR state. Transition to FLASH_ST_READ_SR state.
*/ */
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Status"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Status" );
*state = FLASH_ST_READ_SR; *state = FLASH_ST_READ_SR;
break; break;
case FLASH_CMD_BL_ERASE: case FLASH_CMD_BL_ERASE:
/* Block Erase; section 4.6 on Data Sheet. /* Block Erase; section 4.6 on Data Sheet.
Transition to FLASH_ST_BL_ERASE state. Transition to FLASH_ST_BL_ERASE state.
Consistency of block addresses is not checked. Consistency of block addresses is not checked.
*/ */
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Erase Block (start)"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Erase Block (start)" );
*state = FLASH_ST_BL_ERASE; *state = FLASH_ST_BL_ERASE;
break; break;
default: default:
/* Unknown command; signal, ignore, keep current state. */ /* Unknown command; signal, ignore, keep current state. */
ChfCondition FLASH_W_BAD_CMD, CHF_WARNING, ChfCondition FLASH_W_BAD_CMD, CHF_WARNING, *state, cycle, address, data ChfEnd;
*state, cycle, address, data ChfSignal();
ChfEnd; break;
ChfSignal();
break;
} }
return 0; /* No result; this is a write cycle */ return 0; /* No result; this is a write cycle */
} }
/* This function returns to the caller the value of XSR */ /* This function returns to the caller the value of XSR */
static int ReadXSR(enum FlashState *state, enum FlashCycle cycle, static int ReadXSR( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
/* Return XSR status; a buffer is always available in the current /* Return XSR status; a buffer is always available in the current
emulation scheme. Keep current state. emulation scheme. Keep current state.
*/ */
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read XSR"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read XSR" );
return FLASH_XSR_WBS; return FLASH_XSR_WBS;
} }
/* This function returns to the caller the value of SR */ /* This function returns to the caller the value of SR */
static int ReadSR(enum FlashState *state, enum FlashCycle cycle, static int ReadSR( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
/* Return SR status; the WSM executes in zero time in the current /* Return SR status; the WSM executes in zero time in the current
emulation scheme. Keep current state. emulation scheme. Keep current state.
*/ */
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read SR"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read SR" );
return FLASH_SR_WSMS; return FLASH_SR_WSMS;
} }
/* This function is called to store the WRITE_BUFFER byte count; /* This function is called to store the WRITE_BUFFER byte count;
both wb_count and wb_cdown are set; StoreData() decrements the both wb_count and wb_cdown are set; StoreData() decrements the
latter, WriteConfirm() uses the former to determine how many bytes latter, WriteConfirm() uses the former to determine how many bytes
must write to the Flash array. must write to the Flash array.
*/ */
static int StoreCount(enum FlashState *state, enum FlashCycle cycle, static int StoreCount( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
/* Store WRITE_BUFFER count; next state is FLASH_ST_WRITE_DATA */ /* Store WRITE_BUFFER count; next state is FLASH_ST_WRITE_DATA */
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (count)"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (count)" );
wb_count = wb_cdown = data & WB_COUNT_MASK; wb_count = wb_cdown = data & WB_COUNT_MASK;
*state = FLASH_ST_WRITE_DATA_1; *state = FLASH_ST_WRITE_DATA_1;
return 0; /* No result; this is a write cycle */ return 0; /* No result; this is a write cycle */
} }
/* This function is called to store a byte into the write buffer. /* This function is called to store a byte into the write buffer.
The first write cycle also sets the buffer's base address (wb_start). The first write cycle also sets the buffer's base address (wb_start).
The function transitions to state FLASH_ST_WRITE_CONFIRM when all The function transitions to state FLASH_ST_WRITE_CONFIRM when all
bytes have been stored. bytes have been stored.
*/ */
static int StoreData(enum FlashState *state, enum FlashCycle cycle, static int StoreData( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
int index; int index;
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (data)"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (data)" );
/* Store WRITE_BUFFER data; the first write also stores the /* Store WRITE_BUFFER data; the first write also stores the
buffer starting address. buffer starting address.
*/ */
switch(*state) switch ( *state ) {
{
case FLASH_ST_WRITE_DATA_1: case FLASH_ST_WRITE_DATA_1:
wb_start = address; wb_start = address;
wb[0] = data; wb[ 0 ] = data;
*state = FLASH_ST_WRITE_DATA_N; *state = FLASH_ST_WRITE_DATA_N;
break; break;
case FLASH_ST_WRITE_DATA_N: case FLASH_ST_WRITE_DATA_N:
index = address - wb_start; index = address - wb_start;
if(index < 0 || index >= WB_SIZE) if ( index < 0 || index >= WB_SIZE ) {
{ ChfCondition FLASH_W_BAD_ADDRESS, CHF_WARNING, *state, cycle, address, data ChfEnd;
ChfCondition FLASH_W_BAD_ADDRESS, CHF_WARNING, ChfSignal();
*state, cycle, address, data } else
ChfEnd; wb[ index ] = data;
ChfSignal(); break;
}
else
wb[index] = data;
break;
default: default:
*state = FLASH_ST_READ_ARRAY; *state = FLASH_ST_READ_ARRAY;
break; break;
} }
if(--wb_cdown < 0) if ( --wb_cdown < 0 )
*state = FLASH_ST_WRITE_CONFIRM; *state = FLASH_ST_WRITE_CONFIRM;
return 0; /* No result; this is a write cycle */ return 0; /* No result; this is a write cycle */
} }
/* This function expects a Write to Buffer confirmation command /* This function expects a Write to Buffer confirmation command
(FLASH_CMD_WRITE_BUFFER_2); if it is received, the write buffer (FLASH_CMD_WRITE_BUFFER_2); if it is received, the write buffer
is copied into the Flash Rom array, otherwise the write cycle is is copied into the Flash Rom array, otherwise the write cycle is
aborted. In both cases, the new state is FLASH_ST_READ_ARRAY. aborted. In both cases, the new state is FLASH_ST_READ_ARRAY.
*/ */
static int WriteConfirm(enum FlashState *state, enum FlashCycle cycle, static int WriteConfirm( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (end)"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (end)" );
/* Expect Write to Buffer confirmation code */ /* Expect Write to Buffer confirmation code */
if(data == FLASH_CMD_WRITE_BUFFER_2) if ( data == FLASH_CMD_WRITE_BUFFER_2 ) {
{ int i;
int i;
/* Confirmation OK; write. /* Confirmation OK; write.
Remember that wb_count is the byte count MINUS 1. Remember that wb_count is the byte count MINUS 1.
*/ */
for(i=0; i<=wb_count; i++) for ( i = 0; i <= wb_count; i++ ) {
{ mod_status_49->flash[ NibbleAddress( wb_start + i ) ] = LowNibble( wb[ i ] );
mod_status_49->flash[NibbleAddress(wb_start+i)] mod_status_49->flash[ NibbleAddress( wb_start + i ) + 1 ] = HighNibble( wb[ i ] );
= LowNibble(wb[i]); }
mod_status_49->flash[NibbleAddress(wb_start+i)+1]
= HighNibble(wb[i]);
}
} }
*state = FLASH_ST_READ_ARRAY; *state = FLASH_ST_READ_ARRAY;
return 0; /* No result */ return 0; /* No result */
} }
/* If the FLASH_CMD_BL_ERASE_2 command is received, this function erases /* If the FLASH_CMD_BL_ERASE_2 command is received, this function erases
the block pointed by the current address; otherwise the block erase the block pointed by the current address; otherwise the block erase
operation is aborted. operation is aborted.
In both cases, the new state is FLASH_ST_READ_SR. In both cases, the new state is FLASH_ST_READ_SR.
*/ */
static int BlockErase(enum FlashState *state, enum FlashCycle cycle, static int BlockErase( enum FlashState* state, enum FlashCycle cycle, XAddress address, int data )
XAddress address, int data)
{ {
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Block Erase (end)"); debug1( DEBUG_C_FLASH, FLASH_I_FSM_OP, "Block Erase (end)" );
/* Expect Write to Buffer confirmation code */ /* Expect Write to Buffer confirmation code */
if(data == FLASH_CMD_BL_ERASE_2) if ( data == FLASH_CMD_BL_ERASE_2 ) {
{ XAddress block_base = BlockBase( address );
XAddress block_base = BlockBase(address); int i;
int i;
/* Confirmation OK; erase */ /* Confirmation OK; erase */
for(i=0; i<BLOCK_SIZE; i++) for ( i = 0; i < BLOCK_SIZE; i++ ) {
{ mod_status_49->flash[ NibbleAddress( block_base + i ) ] = ( Nibble )0xF;
mod_status_49->flash[ mod_status_49->flash[ NibbleAddress( block_base + i ) + 1 ] = ( Nibble )0xF;
NibbleAddress(block_base+i)] = (Nibble)0xF; }
mod_status_49->flash[
NibbleAddress(block_base+i)+1] = (Nibble)0xF;
}
} }
*state = FLASH_ST_READ_SR; *state = FLASH_ST_READ_SR;
return 0; /* No result */ return 0; /* No result */
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
FSM state diagram; two-dimensional array of FlashF; each function FSM state diagram; two-dimensional array of FlashF; each function
is invoked when the FSM is in a given state (first index), and is invoked when the FSM is in a given state (first index), and
a particular cycle (second index) is requested. a particular cycle (second index) is requested.
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
static FlashF F[FLASH_ST_N][FLASH_CYCLE_N] = static FlashF F[ FLASH_ST_N ][ FLASH_CYCLE_N ] = {
{ {ReadArray, ParseCommand}, /* FLASH_ST_READ_ARRAY */
{ ReadArray, ParseCommand }, /* FLASH_ST_READ_ARRAY */ {ReadSR, ParseCommand}, /* FLASH_ST_READ_SR */
{ ReadSR, ParseCommand }, /* FLASH_ST_READ_SR */ {ReadXSR, StoreCount }, /* FLASH_ST_READ_XSR */
{ ReadXSR, StoreCount }, /* FLASH_ST_READ_XSR */ {BadCommand, StoreData }, /* FLASH_ST_WRITE_DATA_1 */
{ BadCommand, StoreData }, /* FLASH_ST_WRITE_DATA_1 */ {BadCommand, StoreData }, /* FLASH_ST_WRITE_DATA_N */
{ BadCommand, StoreData }, /* FLASH_ST_WRITE_DATA_N */ {BadCommand, WriteConfirm}, /* FLASH_ST_WRITE_CONFIRM */
{ BadCommand, WriteConfirm }, /* FLASH_ST_WRITE_CONFIRM */ {BadCommand, BlockErase } /* FLASH_ST_BL_ERASE */
{ BadCommand, BlockErase } /* FLASH_ST_BL_ERASE */
}; };
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Other private functions Other private functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
@ -415,25 +362,23 @@ static FlashF F[FLASH_ST_N][FLASH_CYCLE_N] =
with 'address' and 'data' as arguments. Returns the with 'address' and 'data' as arguments. Returns the
result of the FSM, if any. result of the FSM, if any.
*/ */
static int FSM(enum FlashCycle cycle, XAddress address, int data) static int FSM( enum FlashCycle cycle, XAddress address, int data )
{ {
int result; int result;
debug2(DEBUG_C_FLASH, FLASH_I_FSM, fsm_state, cycle); debug2( DEBUG_C_FLASH, FLASH_I_FSM, fsm_state, cycle );
debug2(DEBUG_C_FLASH, FLASH_I_FSM_AD, address, data); debug2( DEBUG_C_FLASH, FLASH_I_FSM_AD, address, data );
result = F[fsm_state][cycle](&fsm_state, cycle, address, data); result = F[ fsm_state ][ cycle ]( &fsm_state, cycle, address, data );
debug2(DEBUG_C_FLASH, FLASH_I_FSM_RESULT, fsm_state, result); debug2( DEBUG_C_FLASH, FLASH_I_FSM_RESULT, fsm_state, result );
return result; return result;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
.title : FlashRead49 .title : FlashRead49
@ -447,41 +392,38 @@ static int FSM(enum FlashCycle cycle, XAddress address, int data)
addresses. addresses.
.call : .call :
n = FlashRead49(address); n = FlashRead49(address);
.input : .input :
XAddress address XAddress address
.output : .output :
Nibble n Nibble n
.status_codes : .status_codes :
FLASH_I_READ FLASH_I_READ
FLASH_I_FSM_OP FLASH_I_FSM_OP
FLASH_W_BAD_CMD FLASH_W_BAD_CMD
.notes : .notes :
3.3, 25-Sep-2000, creation 3.3, 25-Sep-2000, creation
.- */ .- */
Nibble FlashRead49(XAddress address) Nibble FlashRead49( XAddress address )
{ {
Nibble result; Nibble result;
if(IsOdd(address)) if ( IsOdd( address ) )
/* Odd address, return buffered data from previous read */ /* Odd address, return buffered data from previous read */
result = HighNibble(r_buffer); result = HighNibble( r_buffer );
else else {
{ /* Even address, invoke FSM */
/* Even address, invoke FSM */ r_buffer = FSM( FLASH_CYCLE_READ, ByteAddress( address ), 0 );
r_buffer = FSM(FLASH_CYCLE_READ, ByteAddress(address), 0); result = LowNibble( r_buffer );
result = LowNibble(r_buffer);
} }
debug2( DEBUG_C_TRACE | DEBUG_C_FLASH, FLASH_I_READ, address, result );
debug2(DEBUG_C_TRACE|DEBUG_C_FLASH, FLASH_I_READ, address, result);
return result; return result;
} }
/* .+ /* .+
.title : FlashWrite49 .title : FlashWrite49
@ -494,32 +436,30 @@ Nibble FlashRead49(XAddress address)
addresses. addresses.
.call : .call :
FlashWrite49(address, datum); FlashWrite49(address, datum);
.input : .input :
XAddress address XAddress address
Nibble datum Nibble datum
.output : .output :
void void
.status_codes : .status_codes :
FLASH_I_WRITE FLASH_I_WRITE
FLASH_I_FSM_OP FLASH_I_FSM_OP
FLASH_W_BAD_CMD FLASH_W_BAD_CMD
FLASH_W_BAD_ADDRESS FLASH_W_BAD_ADDRESS
.notes : .notes :
3.3, 25-Sep-2000, creation 3.3, 25-Sep-2000, creation
.- */ .- */
void FlashWrite49(XAddress address, Nibble datum) void FlashWrite49( XAddress address, Nibble datum )
{ {
debug2(DEBUG_C_TRACE|DEBUG_C_FLASH, FLASH_I_WRITE, address, datum); debug2( DEBUG_C_TRACE | DEBUG_C_FLASH, FLASH_I_WRITE, address, datum );
if(IsOdd(address)) if ( IsOdd( address ) )
/* Odd address, invoke FSM; ignore result */ /* Odd address, invoke FSM; ignore result */
FSM(FLASH_CYCLE_WRITE, ByteAddress(address), FSM( FLASH_CYCLE_WRITE, ByteAddress( address ), w_buffer | ShiftHigh( datum ) );
w_buffer|ShiftHigh(datum));
else else
/* Even address, buffer datum */ /* Even address, buffer datum */
w_buffer = datum; w_buffer = datum;
} }

View file

@ -31,7 +31,6 @@
/* +-+ */ /* +-+ */
/* .+ /* .+
.identifier : $Id: flash49.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $ .identifier : $Id: flash49.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
@ -72,13 +71,11 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macro/Data type definitions Macro/Data type definitions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define FLASH49_RCS_INFO "$Revision: 4.1 $ $State: Rel $" #define FLASH49_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
/* Command Set Definitions, Table 3 on Data Sheet. /* Command Set Definitions, Table 3 on Data Sheet.
Both BCS and SCS commands are listed here; commands marked with Both BCS and SCS commands are listed here; commands marked with
@ -86,79 +83,73 @@
The last fixed byte of multibyte commands has a '_2' suffix. The last fixed byte of multibyte commands has a '_2' suffix.
*/ */
#define FLASH_CMD_READ_ARRAY 0xFF /* BCS */ #define FLASH_CMD_READ_ARRAY 0xFF /* BCS */
#define FLASH_CMD_READ_ID 0x90 /* BCS (*) */ #define FLASH_CMD_READ_ID 0x90 /* BCS (*) */
#define FLASH_CMD_READ_QUERY 0x98 /* SCS (*) */ #define FLASH_CMD_READ_QUERY 0x98 /* SCS (*) */
#define FLASH_CMD_READ_SR 0x70 /* BCS */ #define FLASH_CMD_READ_SR 0x70 /* BCS */
#define FLASH_CMD_CLR_SR 0x50 /* BCS */ #define FLASH_CMD_CLR_SR 0x50 /* BCS */
#define FLASH_CMD_WRITE_BUFFER 0xE8 /* SCS */ #define FLASH_CMD_WRITE_BUFFER 0xE8 /* SCS */
# define FLASH_CMD_WRITE_BUFFER_2 0xD0 #define FLASH_CMD_WRITE_BUFFER_2 0xD0
#define FLASH_CMD_BW_PGM 0x40 /* BCS (*) */ #define FLASH_CMD_BW_PGM 0x40 /* BCS (*) */
#define FLASH_CMD_BW_PGM_ALT 0x10 /* BCS, alternate (*) */ #define FLASH_CMD_BW_PGM_ALT 0x10 /* BCS, alternate (*) */
#define FLASH_CMD_BL_ERASE 0x20 /* BCS */ #define FLASH_CMD_BL_ERASE 0x20 /* BCS */
# define FLASH_CMD_BL_ERASE_2 0xD0 #define FLASH_CMD_BL_ERASE_2 0xD0
#define FLASH_CMD_SUSPEND 0xB0 /* BCS (*) */ #define FLASH_CMD_SUSPEND 0xB0 /* BCS (*) */
#define FLASH_CMD_RESUME 0xD0 /* BCS (*) */ #define FLASH_CMD_RESUME 0xD0 /* BCS (*) */
#define FLASH_CMD_STS_CONFIG 0xB8 /* SCS (*) */ #define FLASH_CMD_STS_CONFIG 0xB8 /* SCS (*) */
#define FLASH_CMD_BL_LB 0x60 /* SCS (*) */ #define FLASH_CMD_BL_LB 0x60 /* SCS (*) */
# define FLASH_CMD_BL_LB_SET 0x01 #define FLASH_CMD_BL_LB_SET 0x01
# define FLASH_CMD_BL_LB_CLR 0xD0 #define FLASH_CMD_BL_LB_CLR 0xD0
#define FLASH_CMD_CHIP_ERASE 0x30 /* SCS (*) */ #define FLASH_CMD_CHIP_ERASE 0x30 /* SCS (*) */
# define FLASH_CMD_CHIP_ERASE_2 0xD0 #define FLASH_CMD_CHIP_ERASE_2 0xD0
/* Status Register bit masks, Table 15 on Data Sheet /* Status Register bit masks, Table 15 on Data Sheet
*/ */
#define FLASH_SR_WSMS 0x80 /* WSM state, 0=busy, 1=ready */ #define FLASH_SR_WSMS 0x80 /* WSM state, 0=busy, 1=ready */
#define FLASH_SR_ESS 0x40 /* Erase suspend, 1=suspended */ #define FLASH_SR_ESS 0x40 /* Erase suspend, 1=suspended */
#define FLASH_SR_ECLBS 0x20 /* 1=Error during erasure */ #define FLASH_SR_ECLBS 0x20 /* 1=Error during erasure */
#define FLASH_SR_BWSLBS 0x10 /* 1=Error during program */ #define FLASH_SR_BWSLBS 0x10 /* 1=Error during program */
#define FLASH_SR_VPPS 0x08 /* 1=Vpp error */ #define FLASH_SR_VPPS 0x08 /* 1=Vpp error */
#define FLASH_SR_BWSS 0x04 /* Program suspend, 1=suspended */ #define FLASH_SR_BWSS 0x04 /* Program suspend, 1=suspended */
#define FLASH_SR_DPS 0x02 /* 1=Lock encountered */ #define FLASH_SR_DPS 0x02 /* 1=Lock encountered */
/* Extended Status Register bit masks, Table 16 on Data Sheet /* Extended Status Register bit masks, Table 16 on Data Sheet
*/ */
#define FLASH_XSR_WBS 0x80 /* Write buffer status 1=available */ #define FLASH_XSR_WBS 0x80 /* Write buffer status 1=available */
/* State of the Flash FSM, derived from command descriptions on /* State of the Flash FSM, derived from command descriptions on
pages 16...28 and from flowcharts on Figure 6...12 of Data Sheet pages 16...28 and from flowcharts on Figure 6...12 of Data Sheet
*/ */
enum FlashState enum FlashState {
{ FLASH_ST_READ_ARRAY = 0, /* Read Array after CMD_READ_ARRAY */
FLASH_ST_READ_ARRAY = 0, /* Read Array after CMD_READ_ARRAY */ FLASH_ST_READ_SR, /* Read Status Reg. after CMD_READ_SR */
FLASH_ST_READ_SR, /* Read Status Reg. after CMD_READ_SR */ FLASH_ST_READ_XSR, /* Read XSR after CMD_WRITE_BUFFER */
FLASH_ST_READ_XSR, /* Read XSR after CMD_WRITE_BUFFER */ FLASH_ST_WRITE_DATA_1, /* Write data after ST_WRITE_COUNT */
FLASH_ST_WRITE_DATA_1, /* Write data after ST_WRITE_COUNT */ FLASH_ST_WRITE_DATA_N, /* Write data after first write */
FLASH_ST_WRITE_DATA_N, /* Write data after first write */ FLASH_ST_WRITE_CONFIRM, /* Write confirmation after (ST_WRITE_DATA)* */
FLASH_ST_WRITE_CONFIRM, /* Write confirmation after (ST_WRITE_DATA)* */ FLASH_ST_BL_ERASE, /* Block erase started */
FLASH_ST_BL_ERASE, /* Block erase started */ FLASH_ST_N /* Total # of FSM states */
FLASH_ST_N /* Total # of FSM states */
}; };
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define FLASH_I_READ 101 /* Read from address %x: %d */ #define FLASH_I_READ 101 /* Read from address %x: %d */
#define FLASH_I_WRITE 102 /* Write address %x, datum %x */ #define FLASH_I_WRITE 102 /* Write address %x, datum %x */
#define FLASH_I_FSM 103 /* FSM from state %d, cycle %d */ #define FLASH_I_FSM 103 /* FSM from state %d, cycle %d */
#define FLASH_I_FSM_AD 104 /* FSM address %x, data %x */ #define FLASH_I_FSM_AD 104 /* FSM address %x, data %x */
#define FLASH_I_FSM_RESULT 105 /* FSM next state %d, result %x */ #define FLASH_I_FSM_RESULT 105 /* FSM next state %d, result %x */
#define FLASH_I_FSM_OP 106 /* FSM operation %s */ #define FLASH_I_FSM_OP 106 /* FSM operation %s */
#define FLASH_W_BAD_CMD 201 /* Bad cmd st%d, cycle%d, a%x, d%d */ #define FLASH_W_BAD_CMD 201 /* Bad cmd st%d, cycle%d, a%x, d%d */
#define FLASH_W_BAD_ADDRESS 202 /* Bad addr st%d, cycle%d, a%x, d%d */ #define FLASH_W_BAD_ADDRESS 202 /* Bad addr st%d, cycle%d, a%x, d%d */
#define FLASH_E_xxx 301 #define FLASH_E_xxx 301
#define FLASH_F_xxx 401 #define FLASH_F_xxx 401
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Read/Write operations, nibble-by-nibble */ /* Read/Write operations, nibble-by-nibble */
Nibble FlashRead49(XAddress address); Nibble FlashRead49( XAddress address );
void FlashWrite49(XAddress address, Nibble datum); void FlashWrite49( XAddress address, Nibble datum );

604
src/hdw.c
View file

@ -106,7 +106,7 @@ static char rcs_id[] = "$Id: hdw.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <setjmp.h> #include <setjmp.h>
#include <string.h> /* 3.1: memset() */ #include <string.h> /* 3.1: memset() */
#include <errno.h> #include <errno.h>
#include "config.h" #include "config.h"
@ -114,22 +114,18 @@ static char rcs_id[] = "$Id: hdw.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include "cpu.h" #include "cpu.h"
#include "modules.h" #include "modules.h"
#include "disk_io.h" #include "disk_io.h"
#include "serial.h" /* 2.5: Serial port emulation module */ #include "serial.h" /* 2.5: Serial port emulation module */
#include "x_func.h" /* 3.13: Extended emulator functions */ #include "x_func.h" /* 3.13: Extended emulator functions */
#include "debug.h" #include "debug.h"
#include "args.h" #include "args.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID #define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
static const int addr_mask[] = { 0x0000F, 0x000F0, 0x00F00, 0x0F000, 0xF0000 }; static const int addr_mask[] = { 0x0000F, 0x000F0, 0x00F00, 0x0F000, 0xF0000 };
static const int32 int32_mask[] = static const int32 int32_mask[] = { 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F000, 0x000F0000, 0x00F00000, 0x0F000000, 0xF0000000 };
{ 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F000,
0x000F0000, 0x00F00000, 0x0F000000, 0xF0000000 };
/* .+ /* .+
@ -141,35 +137,32 @@ static const int32 int32_mask[] =
peripheral devices associated to it from disk. peripheral devices associated to it from disk.
.call : .call :
HdwInit(); HdwInit();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_W_HDW_INIT MOD_W_HDW_INIT
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, bug fix: 2.4, 11-Sep-2000, bug fix:
memset() invocation was improper, and could lead to memory corruption memset() invocation was improper, and could lead to memory corruption
.- */ .- */
void HdwInit(void) void HdwInit( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwInit"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwInit" );
if(ReadStructFromFile(args.hdw_file_name, sizeof(mod_status.hdw), if ( ReadStructFromFile( args.hdw_file_name, sizeof( mod_status.hdw ), &mod_status.hdw ) ) {
&mod_status.hdw)) ChfCondition MOD_W_HDW_INIT, CHF_WARNING ChfEnd;
{ ChfSignal();
ChfCondition MOD_W_HDW_INIT, CHF_WARNING ChfEnd;
ChfSignal();
(void)memset(&mod_status.hdw, 0, sizeof(mod_status.hdw)); ( void )memset( &mod_status.hdw, 0, sizeof( mod_status.hdw ) );
} }
} }
/* .+ /* .+
.title : HdwSave .title : HdwSave
@ -180,31 +173,28 @@ void HdwInit(void)
to the Hdw module to disk. to the Hdw module to disk.
.call : .call :
HdwSave(); HdwSave();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_HDW_SAVE MOD_E_HDW_SAVE
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
.- */ .- */
void HdwSave(void) void HdwSave( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwSave"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwSave" );
if(WriteStructToFile(&mod_status.hdw, sizeof(mod_status.hdw), if ( WriteStructToFile( &mod_status.hdw, sizeof( mod_status.hdw ), args.hdw_file_name ) ) {
args.hdw_file_name)) ChfCondition MOD_E_HDW_SAVE, CHF_ERROR ChfEnd;
{ ChfSignal();
ChfCondition MOD_E_HDW_SAVE, CHF_ERROR ChfEnd; }
ChfSignal();
}
} }
/* .+ /* .+
.title : HdwRead .title : HdwRead
@ -214,14 +204,14 @@ void HdwSave(void)
This function reads a nibble from the Hdw module. This function reads a nibble from the Hdw module.
.call : .call :
d = HdwRead(rel_address); d = HdwRead(rel_address);
.input : .input :
Address rel_address, relative address Address rel_address, relative address
.output : .output :
Nibble d, data Nibble d, data
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_W_HDW_READ MOD_W_HDW_READ
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, update 2.4, 11-Sep-2000, update
@ -232,130 +222,127 @@ void HdwSave(void)
- added support for serial port emulation - added support for serial port emulation
.- */ .- */
Nibble HdwRead(Address rel_address) Nibble HdwRead( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwRead"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwRead" );
/* In the following switch, each case corresponds to one hdw register. /* In the following switch, each case corresponds to one hdw register.
If the register must be read from the shadow space mod_status.hdw.hdw[], If the register must be read from the shadow space mod_status.hdw.hdw[],
simply put a break in the case, otherwise code any special action for simply put a break in the case, otherwise code any special action for
the register and end the case with a return. the register and end the case with a return.
*/
switch(rel_address)
{
case 0x00: /* LCD driver registers */
case 0x01:
case 0x02:
case 0x03:
case 0x0B:
case 0x0C:
case 0x25:
case 0x26:
case 0x27:
case 0x28:
case 0x29:
break;
case 0x04: /* CRC register */
case 0x05:
case 0x06:
case 0x07:
return (Nibble)((mod_status.hdw.crc >> ((rel_address-0x04)*4)) & 0x0F);
case 0x08: /* Power status */
/* No power status related interrupt have occoured */
return (Nibble)0;
case 0x09: /* Power control */
break;
case 0x0D: /* Serial port baud-rate register */
break;
case 0x10: /* Serial port interrupt and I/O control register */
return Serial_IOC_Read();
case 0x11: /* Serial port receiver control/status register */
return Serial_RCS_Read();
case 0x12: /* Serial port transmitter control/status register */
return Serial_TCS_Read();
/* Serial port receiver buffer register; the actual read takes place
when the LS nibble is read; serial_rbr buffers the MS nibble.
*/ */
case 0x14: switch ( rel_address ) {
return (mod_status.hdw.serial_rbr = Serial_RBR_Read()) & 0x0F; case 0x00: /* LCD driver registers */
case 0x01:
case 0x02:
case 0x03:
case 0x0B:
case 0x0C:
case 0x25:
case 0x26:
case 0x27:
case 0x28:
case 0x29:
break;
case 0x15: case 0x04: /* CRC register */
return (mod_status.hdw.serial_rbr >> 4) & 0x0F; case 0x05:
case 0x06:
case 0x07:
return ( Nibble )( ( mod_status.hdw.crc >> ( ( rel_address - 0x04 ) * 4 ) ) & 0x0F );
case 0x0E: /* Card interface */ case 0x08: /* Power status */
break; /* No power status related interrupt have occoured */
return ( Nibble )0;
case 0x0F: /* Card interface */ case 0x09: /* Power control */
/* 2.4: Return current card status */ break;
return mod_status.hdw.card_status;
case 0x18: /* Service request */ case 0x0D: /* Serial port baud-rate register */
case 0x19: break;
break;
case 0x1A: /* IR registers */ case 0x10: /* Serial port interrupt and I/O control register */
case 0x1C: return Serial_IOC_Read();
case 0x1D:
break;
case 0x1B: /* Base nibble offset */ case 0x11: /* Serial port receiver control/status register */
break; return Serial_RCS_Read();
case 0x1E: /* Scratch pad */ case 0x12: /* Serial port transmitter control/status register */
break; return Serial_TCS_Read();
case 0x1F: /* Base Nibble */ /* Serial port receiver buffer register; the actual read takes place
break; when the LS nibble is read; serial_rbr buffers the MS nibble.
*/
case 0x14:
return ( mod_status.hdw.serial_rbr = Serial_RBR_Read() ) & 0x0F;
case 0x2E: /* Timer 1 Control */ case 0x15:
return mod_status.hdw.t1_ctrl; return ( mod_status.hdw.serial_rbr >> 4 ) & 0x0F;
case 0x2F: /* Timer 2 Control */ case 0x0E: /* Card interface */
return mod_status.hdw.t2_ctrl; break;
case 0x0F: /* Card interface */
/* 2.4: Return current card status */
return mod_status.hdw.card_status;
case 0x18: /* Service request */
case 0x19:
break;
case 0x1A: /* IR registers */
case 0x1C:
case 0x1D:
break;
case 0x1B: /* Base nibble offset */
break;
case 0x1E: /* Scratch pad */
break;
case 0x1F: /* Base Nibble */
break;
case 0x2E: /* Timer 1 Control */
return mod_status.hdw.t1_ctrl;
case 0x2F: /* Timer 2 Control */
return mod_status.hdw.t2_ctrl;
#ifdef HP49_SUPPORT #ifdef HP49_SUPPORT
/* 3.2: The HP49 firmware (1.19-4) reads a nibble from 0x30 */ /* 3.2: The HP49 firmware (1.19-4) reads a nibble from 0x30 */
case 0x30: case 0x30:
case 0x31: case 0x31:
case 0x32: case 0x32:
case 0x33: case 0x33:
case 0x34: case 0x34:
return (Nibble)0x0; return ( Nibble )0x0;
#endif #endif
case 0x37: /* Timer 1 value */ case 0x37: /* Timer 1 value */
return mod_status.hdw.t1_val; return mod_status.hdw.t1_val;
case 0x38: /* Timer 2 value */ case 0x38: /* Timer 2 value */
case 0x39: case 0x39:
case 0x3A: case 0x3A:
case 0x3B: case 0x3B:
case 0x3C: case 0x3C:
case 0x3D: case 0x3D:
case 0x3E: case 0x3E:
case 0x3F: case 0x3F:
return return ( Nibble )( ( mod_status.hdw.t2_val >> ( ( rel_address - 0x38 ) * 4 ) ) & 0x0F );
(Nibble)((mod_status.hdw.t2_val >> ((rel_address-0x38)*4)) & 0x0F);
default: default:
ChfCondition MOD_W_HDW_READ, CHF_WARNING, rel_address ChfEnd; ChfCondition MOD_W_HDW_READ, CHF_WARNING, rel_address ChfEnd;
ChfSignal(); ChfSignal();
return (Nibble)0xF; return ( Nibble )0xF;
} }
/* Read from hdw register array */ /* Read from hdw register array */
return mod_status.hdw.hdw[rel_address]; return mod_status.hdw.hdw[ rel_address ];
} }
/* .+ /* .+
.title : HdwWrite .title : HdwWrite
@ -365,201 +352,198 @@ Nibble HdwRead(Address rel_address)
This function writes a nibble to the Hdw module. This function writes a nibble to the Hdw module.
.call : .call :
HdwWrite(rel_address, data); HdwWrite(rel_address, data);
.input : .input :
Address rel_address, relative address Address rel_address, relative address
Nibble data, data to be written Nibble data, data to be written
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_W_HDW_WRITE MOD_W_HDW_WRITE
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.5, 14-Sep-2000, update 2.5, 14-Sep-2000, update
- added support for serial port emulation - added support for serial port emulation
.- */ .- */
void HdwWrite(Address rel_address, Nibble data) void HdwWrite( Address rel_address, Nibble data )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwWrite"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "HdwWrite" );
/* This switch has a case for each 'known' hdw register. The code inside the /* This switch has a case for each 'known' hdw register. The code inside the
case performs the actions specific for that register; the code following case performs the actions specific for that register; the code following
the switch, instead, simply takes care to shadow the hdw register into the switch, instead, simply takes care to shadow the hdw register into
the mod_status.hdw.hdw[] array the mod_status.hdw.hdw[] array
*/
switch(rel_address)
{
case 0x00: /* LCD horizontal offset, LCD enable flag */
mod_status.hdw.lcd_offset = (int)data & 0x07;
mod_status.hdw.lcd_on = ((data & 0x08) != 0);
break;
case 0x01: /* LCD contrast, LS nibble */
mod_status.hdw.lcd_contrast &= 0x10;
mod_status.hdw.lcd_contrast |= (int)data;
break;
case 0x02: /* LCD contrast, MS bit */
mod_status.hdw.lcd_contrast &= 0x0F;
mod_status.hdw.lcd_contrast |= (((int)data & 0x01) << 4);
break;
case 0x03: /* LCD test control */
break;
case 0x04: /* CRC register */
case 0x05:
case 0x06:
case 0x07:
mod_status.hdw.crc &= ~addr_mask[rel_address-0x04];
mod_status.hdw.crc |= ((int)data << ((rel_address-0x04)*4));
break;
case 0x08: /* Power status and power control */
case 0x09:
break;
case 0x0B: /* LCD annunciator control (low nibble) */
mod_status.hdw.lcd_ann &= 0xF0;
mod_status.hdw.lcd_ann |= (int)data;
break;
case 0x0C: /* LCD annunciator control (high nibble) */
mod_status.hdw.lcd_ann &= 0x0F;
mod_status.hdw.lcd_ann |= ((int)data << 4);
break;
case 0x0D: /* Serial port baud rate */
break;
case 0x0E: /* Card interface */
case 0x0F:
break;
case 0x10: /* Serial port interrupt and I/O control/status */
Serial_IOC_Write(data);
break;
case 0x11: /* Serial port receiver control/status register */
Serial_RCS_Write(data);
break;
case 0x12: /* Serial port transmitter control/status register */
Serial_TCS_Write(data);
break;
case 0x13: /* Clear serial port receive error */
Serial_CRER_Write(data);
break;
/* 3.13: A write operation into the receiver buffer register
triggers an extended emulator function.
*/ */
case 0x14: switch ( rel_address ) {
ExtendedFunction(data); case 0x00: /* LCD horizontal offset, LCD enable flag */
break; mod_status.hdw.lcd_offset = ( int )data & 0x07;
mod_status.hdw.lcd_on = ( ( data & 0x08 ) != 0 );
break;
/* Serial port transmitter buffer; the actual write takes place case 0x01: /* LCD contrast, LS nibble */
when the MS nibble is written; serial_tbr buffers the LS nibble. mod_status.hdw.lcd_contrast &= 0x10;
*/ mod_status.hdw.lcd_contrast |= ( int )data;
case 0x16: break;
mod_status.hdw.serial_tbr =
(mod_status.hdw.serial_tbr & 0xF0) | (int8)data;
break;
case 0x17: case 0x02: /* LCD contrast, MS bit */
mod_status.hdw.serial_tbr = mod_status.hdw.lcd_contrast &= 0x0F;
(mod_status.hdw.serial_tbr & 0x0F) | ((int8)data << 4); mod_status.hdw.lcd_contrast |= ( ( ( int )data & 0x01 ) << 4 );
Serial_TBR_Write(mod_status.hdw.serial_tbr); break;
break;
case 0x18: /* Service request */ case 0x03: /* LCD test control */
case 0x19: break;
break;
case 0x1A: /* IR Control Register */ case 0x04: /* CRC register */
break; case 0x05:
case 0x06:
case 0x07:
mod_status.hdw.crc &= ~addr_mask[ rel_address - 0x04 ];
mod_status.hdw.crc |= ( ( int )data << ( ( rel_address - 0x04 ) * 4 ) );
break;
case 0x1B: /* Base nibble offset */ case 0x08: /* Power status and power control */
break; case 0x09:
break;
case 0x1C: /* IR Status Register */ case 0x0B: /* LCD annunciator control (low nibble) */
break; mod_status.hdw.lcd_ann &= 0xF0;
mod_status.hdw.lcd_ann |= ( int )data;
break;
case 0x1D: /* IR Led Buffer */ case 0x0C: /* LCD annunciator control (high nibble) */
break; mod_status.hdw.lcd_ann &= 0x0F;
mod_status.hdw.lcd_ann |= ( ( int )data << 4 );
break;
case 0x1E: /* Scratch Pad */ case 0x0D: /* Serial port baud rate */
break; break;
case 0x1F: /* Base Nibble */ case 0x0E: /* Card interface */
break; case 0x0F:
break;
case 0x20: /* LCD base address register (write only) */ case 0x10: /* Serial port interrupt and I/O control/status */
case 0x21: Serial_IOC_Write( data );
case 0x22: break;
case 0x23:
case 0x24:
mod_status.hdw.lcd_base_addr &= ~addr_mask[rel_address-0x20];
mod_status.hdw.lcd_base_addr |= ((int)data << ((rel_address-0x20)*4));
break;
case 0x25: /* LCD line offset register */ case 0x11: /* Serial port receiver control/status register */
case 0x26: Serial_RCS_Write( data );
case 0x27: break;
mod_status.hdw.lcd_line_offset &= ~addr_mask[rel_address-0x25];
mod_status.hdw.lcd_line_offset |= ((int)data << ((rel_address-0x25)*4));
break;
case 0x28: /* LCD vertical line count (low nibble) */ case 0x12: /* Serial port transmitter control/status register */
mod_status.hdw.lcd_vlc &= 0x30; Serial_TCS_Write( data );
mod_status.hdw.lcd_vlc |= (int)data; break;
break;
case 0x29: /* LCD vertical line count (higher 2 bits), others (TBD) */ case 0x13: /* Clear serial port receive error */
mod_status.hdw.lcd_vlc &= 0x0F; Serial_CRER_Write( data );
mod_status.hdw.lcd_vlc |= (((int)data & 0x03) << 4); break;
case 0x2E: /* Timer 1 Control */ /* 3.13: A write operation into the receiver buffer register
mod_status.hdw.t1_ctrl = data; triggers an extended emulator function.
break; */
case 0x14:
ExtendedFunction( data );
break;
case 0x2F: /* Timer 2 Control */ /* Serial port transmitter buffer; the actual write takes place
mod_status.hdw.t2_ctrl = data; when the MS nibble is written; serial_tbr buffers the LS nibble.
break; */
case 0x16:
mod_status.hdw.serial_tbr = ( mod_status.hdw.serial_tbr & 0xF0 ) | ( int8 )data;
break;
case 0x30: /* LCD menu address register (write only) */ case 0x17:
case 0x31: mod_status.hdw.serial_tbr = ( mod_status.hdw.serial_tbr & 0x0F ) | ( ( int8 )data << 4 );
case 0x32: Serial_TBR_Write( mod_status.hdw.serial_tbr );
case 0x33: break;
case 0x34:
mod_status.hdw.lcd_menu_addr &= ~addr_mask[rel_address-0x30];
mod_status.hdw.lcd_menu_addr |= ((int)data << ((rel_address-0x30)*4));
break;
case 0x37: /* Timer 1 value */ case 0x18: /* Service request */
mod_status.hdw.t1_val = data; case 0x19:
break; break;
case 0x38: /* Timer 2 value */ case 0x1A: /* IR Control Register */
case 0x39: break;
case 0x3A:
case 0x3B:
case 0x3C:
case 0x3D:
case 0x3E:
case 0x3F:
mod_status.hdw.t2_val &= ~int32_mask[rel_address-0x38];
mod_status.hdw.t2_val |= ((int32)data << ((rel_address-0x38)*4));
break;
default: case 0x1B: /* Base nibble offset */
ChfCondition MOD_W_HDW_WRITE, CHF_WARNING, rel_address, (int)data ChfEnd; break;
ChfSignal();
}
/* Save copy into hdw register array */ case 0x1C: /* IR Status Register */
mod_status.hdw.hdw[rel_address] = data; break;
case 0x1D: /* IR Led Buffer */
break;
case 0x1E: /* Scratch Pad */
break;
case 0x1F: /* Base Nibble */
break;
case 0x20: /* LCD base address register (write only) */
case 0x21:
case 0x22:
case 0x23:
case 0x24:
mod_status.hdw.lcd_base_addr &= ~addr_mask[ rel_address - 0x20 ];
mod_status.hdw.lcd_base_addr |= ( ( int )data << ( ( rel_address - 0x20 ) * 4 ) );
break;
case 0x25: /* LCD line offset register */
case 0x26:
case 0x27:
mod_status.hdw.lcd_line_offset &= ~addr_mask[ rel_address - 0x25 ];
mod_status.hdw.lcd_line_offset |= ( ( int )data << ( ( rel_address - 0x25 ) * 4 ) );
break;
case 0x28: /* LCD vertical line count (low nibble) */
mod_status.hdw.lcd_vlc &= 0x30;
mod_status.hdw.lcd_vlc |= ( int )data;
break;
case 0x29: /* LCD vertical line count (higher 2 bits), others (TBD) */
mod_status.hdw.lcd_vlc &= 0x0F;
mod_status.hdw.lcd_vlc |= ( ( ( int )data & 0x03 ) << 4 );
case 0x2E: /* Timer 1 Control */
mod_status.hdw.t1_ctrl = data;
break;
case 0x2F: /* Timer 2 Control */
mod_status.hdw.t2_ctrl = data;
break;
case 0x30: /* LCD menu address register (write only) */
case 0x31:
case 0x32:
case 0x33:
case 0x34:
mod_status.hdw.lcd_menu_addr &= ~addr_mask[ rel_address - 0x30 ];
mod_status.hdw.lcd_menu_addr |= ( ( int )data << ( ( rel_address - 0x30 ) * 4 ) );
break;
case 0x37: /* Timer 1 value */
mod_status.hdw.t1_val = data;
break;
case 0x38: /* Timer 2 value */
case 0x39:
case 0x3A:
case 0x3B:
case 0x3C:
case 0x3D:
case 0x3E:
case 0x3F:
mod_status.hdw.t2_val &= ~int32_mask[ rel_address - 0x38 ];
mod_status.hdw.t2_val |= ( ( int32 )data << ( ( rel_address - 0x38 ) * 4 ) );
break;
default:
ChfCondition MOD_W_HDW_WRITE, CHF_WARNING, rel_address, ( int )data ChfEnd;
ChfSignal();
}
/* Save copy into hdw register array */
mod_status.hdw.hdw[ rel_address ] = data;
} }

View file

@ -87,194 +87,257 @@ static char rcs_id[] = "$Id: hw_config.c,v 4.1 2000/12/11 09:54:19 cibrario Rel
#include "modules.h" #include "modules.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID #define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Module description tables Module description tables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
extern void RomInit(void); extern void RomInit( void );
extern void HdwInit(void); extern void HdwInit( void );
extern void RamInit(void); extern void RamInit( void );
extern void Ce1Init(void); extern void Ce1Init( void );
extern void Ce2Init(void); extern void Ce2Init( void );
extern void NCe3Init(void); extern void NCe3Init( void );
extern void RomSave(void); extern void RomSave( void );
extern void HdwSave(void); extern void HdwSave( void );
extern void RamSave(void); extern void RamSave( void );
extern void Ce1Save(void); extern void Ce1Save( void );
extern void Ce2Save(void); extern void Ce2Save( void );
extern void NCe3Save(void); extern void NCe3Save( void );
extern Nibble RomRead(Address); extern Nibble RomRead( Address );
extern Nibble HdwRead(Address); extern Nibble HdwRead( Address );
extern Nibble RamRead(Address); extern Nibble RamRead( Address );
extern Nibble Ce1Read(Address); extern Nibble Ce1Read( Address );
extern Nibble Ce2Read(Address); extern Nibble Ce2Read( Address );
extern Nibble NCe3Read(Address); extern Nibble NCe3Read( Address );
extern void RomWrite(Address, Nibble); extern void RomWrite( Address, Nibble );
extern void HdwWrite(Address, Nibble); extern void HdwWrite( Address, Nibble );
extern void RamWrite(Address, Nibble); extern void RamWrite( Address, Nibble );
extern void Ce1Write(Address, Nibble); extern void Ce1Write( Address, Nibble );
extern void Ce2Write(Address, Nibble); extern void Ce2Write( Address, Nibble );
extern void NCe3Write(Address, Nibble); extern void NCe3Write( Address, Nibble );
extern void RomInit49(void); extern void RomInit49( void );
extern void HdwInit49(void); extern void HdwInit49( void );
extern void RamInit49(void); extern void RamInit49( void );
extern void Ce1Init49(void); extern void Ce1Init49( void );
extern void Ce2Init49(void); extern void Ce2Init49( void );
extern void NCe3Init49(void); extern void NCe3Init49( void );
extern void RomSave49(void); extern void RomSave49( void );
extern void HdwSave49(void); extern void HdwSave49( void );
extern void RamSave49(void); extern void RamSave49( void );
extern void Ce1Save49(void); extern void Ce1Save49( void );
extern void Ce2Save49(void); extern void Ce2Save49( void );
extern void NCe3Save49(void); extern void NCe3Save49( void );
extern Nibble RomRead49(Address); extern Nibble RomRead49( Address );
extern Nibble HdwRead49(Address); extern Nibble HdwRead49( Address );
extern Nibble RamRead49(Address); extern Nibble RamRead49( Address );
extern Nibble Ce1Read49(Address); extern Nibble Ce1Read49( Address );
extern Nibble Ce2Read49(Address); extern Nibble Ce2Read49( Address );
extern Nibble NCe3Read49(Address); extern Nibble NCe3Read49( Address );
extern void RomWrite49(Address, Nibble); extern void RomWrite49( Address, Nibble );
extern void HdwWrite49(Address, Nibble); extern void HdwWrite49( Address, Nibble );
extern void RamWrite49(Address, Nibble); extern void RamWrite49( Address, Nibble );
extern void Ce1Write49(Address, Nibble); extern void Ce1Write49( Address, Nibble );
extern void Ce2Write49(Address, Nibble); extern void Ce2Write49( Address, Nibble );
extern void NCe3Write49(Address, Nibble); extern void NCe3Write49( Address, Nibble );
static const struct static const struct {
{ const char* hw;
const char *hw;
ModDescription description; ModDescription description;
} }
table[] = table[] =
{
/*---------------------------------------------------------------------------
HP48
---------------------------------------------------------------------------*/
{ {
"hp48",
{ /*---------------------------------------------------------------------------
/* name, id, access_prio, HP48
init, save, ---------------------------------------------------------------------------*/
read, write,
r_config, r_abs_base_addr, r_size,
map_flags
*/
{ "ROM (ROM)", 0x00, 0, {"hp48",
RomInit, RomSave,
RomRead, RomWrite,
MOD_CONFIGURED, 0x00000, 0xFFFFF,
},
{ "Hardware Regs. (HDW)", 0x19, 5, { /* name, id, access_prio,
HdwInit, HdwSave, init, save,
HdwRead, HdwWrite, read, write,
MOD_SIZE_CONFIGURED, 0x00000, 0x00040, r_config, r_abs_base_addr, r_size,
}, map_flags
*/
{ "Internal RAM (RAM)", 0x03, 4, {
RamInit, RamSave, "ROM (ROM)",
RamRead, RamWrite, 0x00,
MOD_UNCONFIGURED, 0, 0, 0,
}, RomInit,
RomSave,
RomRead,
RomWrite,
MOD_CONFIGURED,
0x00000,
0xFFFFF,
},
{ "Bank Select (CE1)", 0x05, 2, {
Ce1Init, Ce1Save, "Hardware Regs. (HDW)",
Ce1Read, Ce1Write, 0x19,
MOD_UNCONFIGURED, 0, 0, 5,
}, HdwInit,
HdwSave,
HdwRead,
HdwWrite,
MOD_SIZE_CONFIGURED,
0x00000,
0x00040,
},
{ "Port 1 Control (CE2)", 0x07, 3, {
Ce2Init, Ce2Save, "Internal RAM (RAM)",
Ce2Read, Ce2Write, 0x03,
MOD_UNCONFIGURED, 0, 0, 4,
}, RamInit,
RamSave,
RamRead,
RamWrite,
MOD_UNCONFIGURED,
0,
0,
},
{ "Port 2 Control (NCE3)", 0x01, 1, {
NCe3Init, NCe3Save, "Bank Select (CE1)",
NCe3Read, NCe3Write, 0x05,
MOD_UNCONFIGURED, 0, 0, 2,
} Ce1Init,
}}, Ce1Save,
Ce1Read,
Ce1Write,
MOD_UNCONFIGURED,
0,
0,
},
/*--------------------------------------------------------------------------- {
HP49 "Port 1 Control (CE2)",
---------------------------------------------------------------------------*/ 0x07,
3,
Ce2Init,
Ce2Save,
Ce2Read,
Ce2Write,
MOD_UNCONFIGURED,
0,
0,
},
{ {
"hp49", "Port 2 Control (NCE3)",
0x01,
1,
NCe3Init,
NCe3Save,
NCe3Read,
NCe3Write,
MOD_UNCONFIGURED,
0,
0,
} } },
{ /*---------------------------------------------------------------------------
/* name, id, access_prio, HP49
init, save, ---------------------------------------------------------------------------*/
read, write,
r_config, r_abs_base_addr, r_size,
map_flags
*/
{ "ROM (ROM)", 0x00, 0, {"hp49",
RomInit49, RomSave49,
RomRead49, RomWrite49,
MOD_CONFIGURED, 0x00000, 0xFFFFF,
},
{ "Hardware Regs. (HDW)", 0x19, 5, { /* name, id, access_prio,
HdwInit, HdwSave, init, save,
HdwRead, HdwWrite, read, write,
MOD_SIZE_CONFIGURED, 0x00000, 0x00040, r_config, r_abs_base_addr, r_size,
}, map_flags
*/
{ "IRAM (RAM)", 0x03, 4, {
RamInit49, RamSave49, "ROM (ROM)",
RamRead49, RamWrite49, 0x00,
MOD_UNCONFIGURED, 0, 0, 0,
}, RomInit49,
RomSave49,
RomRead49,
RomWrite49,
MOD_CONFIGURED,
0x00000,
0xFFFFF,
},
{ "Bank Select (CE1)", 0x05, 2, {
Ce1Init49, Ce1Save49, "Hardware Regs. (HDW)",
Ce1Read49, Ce1Write49, 0x19,
MOD_UNCONFIGURED, 0, 0, 5,
}, HdwInit,
HdwSave,
HdwRead,
HdwWrite,
MOD_SIZE_CONFIGURED,
0x00000,
0x00040,
},
{ "ERAM Bank 0 (CE2)", 0x07, 3, {
Ce2Init49, Ce2Save49, "IRAM (RAM)",
Ce2Read49, Ce2Write49, 0x03,
MOD_UNCONFIGURED, 0, 0, 4,
}, RamInit49,
RamSave49,
RamRead49,
RamWrite49,
MOD_UNCONFIGURED,
0,
0,
},
{ "ERAM Bank 1 (NCE3)", 0x01, 1, {
NCe3Init49, NCe3Save49, "Bank Select (CE1)",
NCe3Read49, NCe3Write49, 0x05,
MOD_UNCONFIGURED, 0, 0, 2,
MOD_MAP_FLAGS_ABS Ce1Init49,
} Ce1Save49,
}} Ce1Read49,
Ce1Write49,
MOD_UNCONFIGURED,
0,
0,
},
{
"ERAM Bank 0 (CE2)",
0x07,
3,
Ce2Init49,
Ce2Save49,
Ce2Read49,
Ce2Write49,
MOD_UNCONFIGURED,
0,
0,
},
{ "ERAM Bank 1 (NCE3)", 0x01, 1, NCe3Init49, NCe3Save49, NCe3Read49, NCe3Write49, MOD_UNCONFIGURED, 0, 0,
MOD_MAP_FLAGS_ABS } }}
}; };
#define N_DESCRIPTIONS (sizeof(table)/sizeof(table[0])) #define N_DESCRIPTIONS ( sizeof( table ) / sizeof( table[ 0 ] ) )
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
.title : ModSelectDescription .title : ModSelectDescription
@ -286,32 +349,32 @@ table[] =
string passed as argument. string passed as argument.
.call : .call :
ModSelectDescription(hw) ModSelectDescription(hw)
.input : .input :
const char *hw, hardware configuration string const char *hw, hardware configuration string
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_NO_MATCH MOD_E_NO_MATCH
.notes : .notes :
1.1, 28-Jan-1998, creation 1.1, 28-Jan-1998, creation
.- */ .- */
void ModSelectDescription(const char *hw) void ModSelectDescription( const char* hw )
{ {
int i; int i;
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "ModSelectDescription"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "ModSelectDescription" );
for(i=0; i<N_DESCRIPTIONS && strcmp(hw, table[i].hw); i++); for ( i = 0; i < N_DESCRIPTIONS && strcmp( hw, table[ i ].hw ); i++ )
;
if(i==N_DESCRIPTIONS) if ( i == N_DESCRIPTIONS ) {
{ ChfCondition MOD_E_NO_MATCH, CHF_ERROR, hw ChfEnd;
ChfCondition MOD_E_NO_MATCH, CHF_ERROR, hw ChfEnd; ChfSignal();
ChfSignal();
} }
else else
ModRegisterDescription(table[i].description); ModRegisterDescription( table[ i ].description );
} }

View file

@ -51,7 +51,7 @@
x48 source code by Eddie C. Dost (ecd@dressler.de) x48 source code by Eddie C. Dost (ecd@dressler.de)
NOTE: In the current (r1.1) implementation, NOTE: In the current (r1.1) implementation,
the emulation accuracy could be poor. the emulation accuracy could be poor.
.include : config.h, machdep.h, cpu.h, modules.h, keyb.h .include : config.h, machdep.h, cpu.h, modules.h, keyb.h
@ -97,18 +97,17 @@ static char rcs_id[] = "$Id: keyb.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include "keyb.h" #include "keyb.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID #define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
#define OUT_BITS 12 #define OUT_BITS 12
/* cur_in: /* cur_in:
This array contains the current value the CPU IN register will assume This array contains the current value the CPU IN register will assume
for each bit set in the OUT register. for each bit set in the OUT register.
*/ */
static InputRegister cur_in[OUT_BITS]; static InputRegister cur_in[ OUT_BITS ];
/* .+ /* .+
@ -121,29 +120,27 @@ static InputRegister cur_in[OUT_BITS];
interrupt request if any key is pressed. interrupt request if any key is pressed.
NOTE: This function currently (r1.1) always posts an IRQ request; perhaps, NOTE: This function currently (r1.1) always posts an IRQ request; perhaps,
if the ON key is down, a NMI request should be posted instead. if the ON key is down, a NMI request should be posted instead.
.call : .call :
KeybRSI(); KeybRSI();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
* *
.notes : .notes :
1.1, 17-Feb-1998, creation 1.1, 17-Feb-1998, creation
.- */ .- */
void KeybRSI(void) void KeybRSI( void )
{ {
/* Post an IRQ if the IN register is not zero */ /* Post an IRQ if the IN register is not zero */
CpuIntRequest(KeybIN((OutputRegister)0x1FF) != (InputRegister)0 ? CpuIntRequest( KeybIN( ( OutputRegister )0x1FF ) != ( InputRegister )0 ? INT_REQUEST_IRQ : INT_REQUEST_NONE );
INT_REQUEST_IRQ : INT_REQUEST_NONE);
} }
/* .+ /* .+
.title : KeybIn .title : KeybIn
@ -155,36 +152,35 @@ void KeybRSI(void)
value of the IN register for the given value of the OUT reguster. value of the IN register for the given value of the OUT reguster.
.call : .call :
in = KeybIN(out); in = KeybIN(out);
.input : .input :
OutputRegister out, current value of the OUT register OutputRegister out, current value of the OUT register
.output : .output :
InputRegister in, computed value of the IN register InputRegister in, computed value of the IN register
.status_codes : .status_codes :
* *
.notes : .notes :
1.1, 17-Feb-1998, creation 1.1, 17-Feb-1998, creation
.- */ .- */
InputRegister KeybIN(OutputRegister out) InputRegister KeybIN( OutputRegister out )
{ {
/* Compute the current value of the IN register */ /* Compute the current value of the IN register */
InputRegister in = (InputRegister)0; InputRegister in = ( InputRegister )0;
int bit; int bit;
/* For each bit set in the 'out' register, OR the corresponding IN register /* For each bit set in the 'out' register, OR the corresponding IN register
value into 'in' value into 'in'
*/ */
for(bit=0; bit<OUT_BITS; bit++) for ( bit = 0; bit < OUT_BITS; bit++ ) {
{ if ( out & 0x01 )
if(out & 0x01) in |= cur_in[bit]; in |= cur_in[ bit ];
out >>= 1; out >>= 1;
} }
return in; return in;
} }
/* .+ /* .+
.title : KeybPress .title : KeybPress
@ -196,63 +192,57 @@ InputRegister KeybIN(OutputRegister out)
necessary, posts an interrupt request to the CPU. necessary, posts an interrupt request to the CPU.
.call : .call :
KeybPress(key); KeybPress(key);
.input : .input :
const char *key, identifies the key that has been pressed. const char *key, identifies the key that has been pressed.
.output : .output :
void void
.status_codes : .status_codes :
MOD_W_BAD_KEY MOD_W_BAD_KEY
MOD_W_BAD_OUT_BIT MOD_W_BAD_OUT_BIT
.notes : .notes :
1.1, 17-Feb-1998, creation 1.1, 17-Feb-1998, creation
2.1, 6-Sep-2000, 2.1, 6-Sep-2000,
deeply revised to accomodate the new GUI deeply revised to accomodate the new GUI
.- */ .- */
void KeybPress(const char *key) void KeybPress( const char* key )
{ {
if(strcmp(key, "*") == 0) if ( strcmp( key, "*" ) == 0 ) {
{ /* This is the ON key */
/* This is the ON key */ int i;
int i;
/* Set all 0x8000 lines */ /* Set all 0x8000 lines */
for(i=0; i<OUT_BITS; i++) cur_in[i] |= 0x8000; for ( i = 0; i < OUT_BITS; i++ )
cur_in[ i ] |= 0x8000;
/* Post an interrupt request to the CPU */ /* Post an interrupt request to the CPU */
CpuIntRequest(INT_REQUEST_NMI); CpuIntRequest( INT_REQUEST_NMI );
} }
else else {
{ int in_val, out_bit;
int in_val, out_bit;
if(sscanf(key, "%x/%x", &out_bit, &in_val) != 2) if ( sscanf( key, "%x/%x", &out_bit, &in_val ) != 2 ) {
{ ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd; ChfSignal();
ChfSignal(); }
}
else if(out_bit < 0 || out_bit >= OUT_BITS) else if ( out_bit < 0 || out_bit >= OUT_BITS ) {
{ ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd;
ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd; ChfSignal();
ChfSignal(); }
}
else else {
{ /* Update the cur_in array */
/* Update the cur_in array */ cur_in[ out_bit ] |= in_val;
cur_in[out_bit] |= in_val;
/* Post an interrupt request to the CPU */ /* Post an interrupt request to the CPU */
CpuIntRequest(INT_REQUEST_NMI); CpuIntRequest( INT_REQUEST_NMI );
}
}
} }
} }
/* .+ /* .+
.title : KeybRelease .title : KeybRelease
@ -263,56 +253,51 @@ void KeybPress(const char *key)
released. It updates the internal keyboard status information. released. It updates the internal keyboard status information.
.call : .call :
KeybRelease(key); KeybRelease(key);
.input : .input :
const char *key, identifies the key that has been released. const char *key, identifies the key that has been released.
.output : .output :
void void
.status_codes : .status_codes :
MOD_W_BAD_KEY MOD_W_BAD_KEY
MOD_W_BAD_OUT_BIT MOD_W_BAD_OUT_BIT
.notes : .notes :
1.1, 17-Feb-1998, creation 1.1, 17-Feb-1998, creation
2.1, 6-Sep-2000, 2.1, 6-Sep-2000,
deeply revised to accomodate the new GUI deeply revised to accomodate the new GUI
.- */ .- */
void KeybRelease(const char *key) void KeybRelease( const char* key )
{ {
if(strcmp(key, "*") == 0) if ( strcmp( key, "*" ) == 0 ) {
{ /* This is the ON key */
/* This is the ON key */ int i;
int i;
/* Reset all 0x8000 lines */ /* Reset all 0x8000 lines */
for(i=0; i<OUT_BITS; i++) cur_in[i] &= 0x7FFF; for ( i = 0; i < OUT_BITS; i++ )
cur_in[ i ] &= 0x7FFF;
} }
else else {
{ int in_val, out_bit;
int in_val, out_bit;
if(sscanf(key, "%x/%x", &out_bit, &in_val) != 2) if ( sscanf( key, "%x/%x", &out_bit, &in_val ) != 2 ) {
{ ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd; ChfSignal();
ChfSignal(); }
}
else if(out_bit < 0 || out_bit >= OUT_BITS) else if ( out_bit < 0 || out_bit >= OUT_BITS ) {
{ ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd;
ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd; ChfSignal();
ChfSignal(); }
}
else else {
{ /* Update the cur_in array */
/* Update the cur_in array */ cur_in[ out_bit ] &= ~in_val;
cur_in[out_bit] &= ~in_val; }
}
} }
} }
/* .+ /* .+
.title : KeybReset .title : KeybReset
@ -322,20 +307,21 @@ void KeybRelease(const char *key)
This function resets the emulated keyboard; all keys are released. This function resets the emulated keyboard; all keys are released.
.call : .call :
KeybReset(); KeybReset();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
.notes : .notes :
3.13, 7-Nov-2000, creation 3.13, 7-Nov-2000, creation
.- */ .- */
void KeybReset(void) void KeybReset( void )
{ {
int i; int i;
/* Reset all 0x8000 lines */ /* Reset all 0x8000 lines */
for(i=0; i<OUT_BITS; i++) cur_in[i] = 0; for ( i = 0; i < OUT_BITS; i++ )
cur_in[ i ] = 0;
} }

View file

@ -76,13 +76,12 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
void KeybRSI(void); void KeybRSI( void );
InputRegister KeybIN(OutputRegister out); InputRegister KeybIN( OutputRegister out );
void KeybPress(const char *key); void KeybPress( const char* key );
void KeybRelease(const char *key); void KeybRelease( const char* key );
void KeybReset(void); void KeybReset( void );

View file

@ -51,321 +51,263 @@
.- */ .- */
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Win32 & UNICODE support Win32 & UNICODE support
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifdef _WIN32 #ifdef _WIN32
#define ChfChar TCHAR # define ChfChar TCHAR
#define ChfText(x) _T(x) # define ChfText( x ) _T( x )
#define ChfSigjmp_buf jmp_buf # define ChfSigjmp_buf jmp_buf
#define ChfSigsetjmp(x,y) setjmp(x) # define ChfSigsetjmp( x, y ) setjmp( x )
#define ChfSiglongjmp(x,y) longjmp(x,y) # define ChfSiglongjmp( x, y ) longjmp( x, y )
#else #else
#define ChfChar char # define ChfChar char
#define ChfText(x) x # define ChfText( x ) x
#define ChfSigjmp_buf sigjmp_buf # define ChfSigjmp_buf sigjmp_buf
#define ChfSigsetjmp(x,y) sigsetjmp(x,y) # define ChfSigsetjmp( x, y ) sigsetjmp( x, y )
#define ChfSiglongjmp(x,y) siglongjmp(x,y) # define ChfSiglongjmp( x, y ) siglongjmp( x, y )
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
CHF implementation limits and other symbolic constants CHF implementation limits and other symbolic constants
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#define CHF_MAX_MESSAGE_LENGTH 256 #define CHF_MAX_MESSAGE_LENGTH 256
#define CHF_UNKNOWN_LINE_NUMBER (-1) #define CHF_UNKNOWN_LINE_NUMBER ( -1 )
#define CHF_UNKNOWN_FILE_NAME (ChfChar *)NULL #define CHF_UNKNOWN_FILE_NAME ( ChfChar* )NULL
#define CHF_NULL_DESCRIPTOR (ChfDescriptor *)NULL #define CHF_NULL_DESCRIPTOR ( ChfDescriptor* )NULL
#define CHF_NULL_CONTEXT (void *)NULL #define CHF_NULL_CONTEXT ( void* )NULL
#define CHF_NULL_POINTER (ChfPointer *)NULL #define CHF_NULL_POINTER ( ChfPointer* )NULL
#define CHF_NULL_HANDLER (ChfHandler)NULL #define CHF_NULL_HANDLER ( ChfHandler ) NULL
#define CHF_LIBRARY_ID ChfText("$Id: Chf.h,v 2.2 2001/01/25 11:56:44 cibrario Exp $") #define CHF_LIBRARY_ID ChfText( "$Id: Chf.h,v 2.2 2001/01/25 11:56:44 cibrario Exp $" )
#define CHF_MAJOR_RELEASE_NUMBER 2 #define CHF_MAJOR_RELEASE_NUMBER 2
#define CHF_MINOR_RELEASE_NUMBER 2 #define CHF_MINOR_RELEASE_NUMBER 2
#define CHF_MODULE_NAMES_SET 1
#define CHF_SET 2
#define CHF_ERRNO_SET 3
#define CHF_MODULE_NAMES_SET 1
#define CHF_SET 2
#define CHF_ERRNO_SET 3
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Condition codes Condition codes
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#define CHF_S_OK 0 #define CHF_S_OK 0
#define CHF_F_COND_STACK_FULL 1 /* Condition stack is full */ #define CHF_F_COND_STACK_FULL 1 /* Condition stack is full */
#define CHF_F_HDLR_STACK_FULL 2 /* Handler stack is full */ #define CHF_F_HDLR_STACK_FULL 2 /* Handler stack is full */
#define CHF_F_HDLR_STACK_EMPTY 3 /* Handler stack is empty */ #define CHF_F_HDLR_STACK_EMPTY 3 /* Handler stack is empty */
#define CHF_F_BAD_STATE 4 /* Bad CHF state for req. operation */ #define CHF_F_BAD_STATE 4 /* Bad CHF state for req. operation */
#define CHF_F_INVALID_ACTION 5 /* Invalid action from handler: %d */ #define CHF_F_INVALID_ACTION 5 /* Invalid action from handler: %d */
#define CHF_F_MALLOC 6 /* Dynamic memory allocation failed */ #define CHF_F_MALLOC 6 /* Dynamic memory allocation failed */
#define CHF_F_NOT_AVAILABLE 7 /* Function not available */ #define CHF_F_NOT_AVAILABLE 7 /* Function not available */
#define CHF_F_SETLOCALE 10 /* setlocale() failed */ #define CHF_F_SETLOCALE 10 /* setlocale() failed */
#define CHF_F_CATOPEN 11 /* catopen() failed */ #define CHF_F_CATOPEN 11 /* catopen() failed */
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Type definitions Type definitions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
typedef enum /* Condition severity codes */ typedef enum /* Condition severity codes */
{ { CHF_SUCCESS,
CHF_SUCCESS,
CHF_INFO, CHF_INFO,
CHF_WARNING, CHF_WARNING,
CHF_ERROR, CHF_ERROR,
CHF_FATAL CHF_FATAL } ChfSeverity;
}
ChfSeverity;
typedef enum /* Condition handler action codes */ typedef enum /* Condition handler action codes */
{ { CHF_CONTINUE, /* Continue application */
CHF_CONTINUE, /* Continue application */ CHF_RESIGNAL, /* Resignal to next handler */
CHF_RESIGNAL, /* Resignal to next handler */ CHF_UNWIND, /* Stack unwind */
CHF_UNWIND, /* Stack unwind */ CHF_UNWIND_KEEP /* Unwind, keep last cond. group */
CHF_UNWIND_KEEP /* Unwind, keep last cond. group */ } ChfAction;
}
ChfAction;
typedef int /* CHF options */ typedef int /* CHF options */
ChfOptions; ChfOptions;
#define CHF_DEFAULT 0x0000 /* default flags */ #define CHF_DEFAULT 0x0000 /* default flags */
#define CHF_ABORT 0x0001 /* use abort() instead of exit() */ #define CHF_ABORT 0x0001 /* use abort() instead of exit() */
typedef enum /* Current CHF state */ typedef enum /* Current CHF state */
{ { CHF_UNKNOWN,
CHF_UNKNOWN,
CHF_IDLE, CHF_IDLE,
CHF_SIGNALING, CHF_SIGNALING,
CHF_UNWINDING, CHF_UNWINDING,
CHF_SIGNAL_UNWINDING CHF_SIGNAL_UNWINDING } ChfState;
}
ChfState;
typedef struct ChfDescriptor_S /* Condition descriptor */ typedef struct ChfDescriptor_S /* Condition descriptor */
{ {
int module_id; /* Module identifier */ int module_id; /* Module identifier */
int condition_code; /* Condition code */ int condition_code; /* Condition code */
ChfSeverity severity; /* Severity */ ChfSeverity severity; /* Severity */
int line_number; /* Line # or CHF_UNK_LINE_NUMBER */ int line_number; /* Line # or CHF_UNK_LINE_NUMBER */
const ChfChar *file_name; /* File name or CHF_UNK_FILE_NAME */ const ChfChar* file_name; /* File name or CHF_UNK_FILE_NAME */
ChfChar message[CHF_MAX_MESSAGE_LENGTH]; /* Partial message */ ChfChar message[ CHF_MAX_MESSAGE_LENGTH ]; /* Partial message */
struct ChfDescriptor_S *next; /* Link to next descriptor */ struct ChfDescriptor_S* next; /* Link to next descriptor */
} } ChfDescriptor;
ChfDescriptor;
typedef struct ChfTable_S /* Standalone message table */ typedef struct ChfTable_S /* Standalone message table */
{ {
int module; /* Module identifier */ int module; /* Module identifier */
int code; /* Condition code */ int code; /* Condition code */
ChfChar *msg_template; /* Message template */ ChfChar* msg_template; /* Message template */
} } ChfTable;
ChfTable;
typedef /* Generic pointer */ typedef /* Generic pointer */
void *ChfPointer; void* ChfPointer;
typedef /* Condition handler */ typedef /* Condition handler */
ChfAction (*ChfHandler)( ChfAction ( *ChfHandler )( const ChfDescriptor*, const ChfState, ChfPointer );
const ChfDescriptor *,
const ChfState,
ChfPointer
);
typedef /* Message retrieval 'get_message' function */ typedef /* Message retrieval 'get_message' function */
const ChfChar * (*ChfMrsGet)( const ChfChar* ( *ChfMrsGet )( void*, const int, const int, const ChfChar* default_message );
void *,
const int,
const int,
const ChfChar *default_message
);
typedef /* Message retrieval 'exit' function */
void (*ChfMrsExit)(
void *
);
typedef /* Message retrieval 'exit' function */
void ( *ChfMrsExit )( void* );
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Condition generation macros Condition generation macros
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#if defined(CHF_EXTENDED_INFO) #if defined( CHF_EXTENDED_INFO )
#define ChfCondition \ # define ChfCondition \
ChfGenerate( \ ChfGenerate( \
CHF_MODULE_ID, \ CHF_MODULE_ID, \
ChfText(__FILE__), __LINE__, ChfText(__FILE__), __LINE__,
#ifdef _WIN32 # ifdef _WIN32
#define ChfErrnoCondition # define ChfErrnoCondition
#else # else
#define ChfErrnoCondition \ # define ChfErrnoCondition ChfGenerate( CHF_ERRNO_SET, ChfText( __FILE__ ), __LINE__, errno, CHF_ERROR )
ChfGenerate( \ # endif
CHF_ERRNO_SET, \
ChfText(__FILE__), __LINE__, \
errno, \
CHF_ERROR \
)
#endif
#else #else
#define ChfCondition \ # define ChfCondition \
ChfGenerate( \ ChfGenerate( \
CHF_MODULE_ID, \ CHF_MODULE_ID, \
CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER, CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER,
#ifdef _WIN32 # ifdef _WIN32
#define ChfErrnoCondition # define ChfErrnoCondition
#else # else
#define ChfErrnoCondition \ # define ChfErrnoCondition ChfGenerate( CHF_ERRNO_SET, CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER, errno, CHF_ERROR )
ChfGenerate( \ # endif
CHF_ERRNO_SET, \
CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER, \
errno, \
CHF_ERROR \
)
#endif
#endif #endif
#define ChfEnd \ #define ChfEnd \
) )
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Structured condition handling Structured condition handling
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#define ChfTry \ #define ChfTry \
{\ { \
ChfSigjmp_buf _chf_sigjmp_buf;\ ChfSigjmp_buf _chf_sigjmp_buf; \
if(ChfSigsetjmp(_chf_sigjmp_buf, 1) == 0)\ if ( ChfSigsetjmp( _chf_sigjmp_buf, 1 ) == 0 ) { \
{\ ChfPushHandler( CHF_NULL_HANDLER, _chf_sigjmp_buf, CHF_NULL_POINTER );
ChfPushHandler(CHF_NULL_HANDLER, _chf_sigjmp_buf, CHF_NULL_POINTER);
#define ChfCatch \ #define ChfCatch \
ChfPopHandler();\ ChfPopHandler(); \
}\ } \
else\ else \
{ {
#define ChfEndTry \ #define ChfEndTry \
ChfDiscard();\ ChfDiscard(); \
}\ } \
} }
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Other macros Other macros
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#define ChfGetNextDescriptor(d) (d)->next #define ChfGetNextDescriptor( d ) ( d )->next
#define ChfGetModuleId(d) (d)->module_id #define ChfGetModuleId( d ) ( d )->module_id
#define ChfGetConditionCode(d) (d)->condition_code #define ChfGetConditionCode( d ) ( d )->condition_code
#define ChfGetSeverity(d) (d)->severity #define ChfGetSeverity( d ) ( d )->severity
#define ChfGetLineNumber(d) (d)->line_number #define ChfGetLineNumber( d ) ( d )->line_number
#define ChfGetFileName(d) (d)->file_name #define ChfGetFileName( d ) ( d )->file_name
#define ChfGetPartialMessage(d) (d)->message #define ChfGetPartialMessage( d ) ( d )->message
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Function prototypes Function prototypes
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
int ChfInit( /* Generic initialization */ int ChfInit( /* Generic initialization */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
void *mrs_data, /* Message retrieval private data */ void* mrs_data, /* Message retrieval private data */
ChfMrsGet mrs_get, /* 'GetMessage' function */ ChfMrsGet mrs_get, /* 'GetMessage' function */
ChfMrsExit mrs_exit, /* 'Exit' function */ ChfMrsExit mrs_exit, /* 'Exit' function */
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
); );
int ChfMsgcatInit( /* Initialization with msgcat subsystem */ int ChfMsgcatInit( /* Initialization with msgcat subsystem */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
const ChfChar *msgcat_name, /* Name of the message catalog */ const ChfChar* msgcat_name, /* Name of the message catalog */
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
); );
int ChfStaticInit( /* Initialization with static message tables */ int ChfStaticInit( /* Initialization with static message tables */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
const ChfTable *table, /* Static message table */ const ChfTable* table, /* Static message table */
const size_t table_size, /* Size of the message table */ const size_t table_size, /* Size of the message table */
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
); );
int ChfWin32Init( /* Initialization within _WIN32 */ int ChfWin32Init( /* Initialization within _WIN32 */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
#ifndef _WIN32 #ifndef _WIN32
void *instance, /* Fake arguments */ void* instance, /* Fake arguments */
#else #else
HINSTANCE instance, /* App. instance handle */ HINSTANCE instance, /* App. instance handle */
#endif #endif
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
); );
void ChfExit( /* Exit */ void ChfExit( /* Exit */
void void );
void ChfAbort( /* Abort application */
const int abort_code );
void ChfPushHandler( /* Push a new handler into the stack */
ChfHandler new_handler, /* Handler to be added */
void* unwind_context, /* Unwind context */
ChfPointer handler_context /* Private handler context */
); );
void ChfAbort( /* Abort application */ void ChfPopHandler( /* Pop a handler */
const int abort_code void );
);
void ChfPushHandler( /* Push a new handler into the stack */ ChfChar* ChfBuildMessage( /* Build a condition message */
ChfHandler new_handler, /* Handler to be added */ const ChfDescriptor* descriptor );
void *unwind_context, /* Unwind context */
ChfPointer handler_context /* Private handler context */
);
void ChfPopHandler( /* Pop a handler */ void ChfSignal( /* Signal the current conditions */
void void );
);
ChfChar *ChfBuildMessage( /* Build a condition message */ void ChfDiscard( /* Discard the current conditions */
const ChfDescriptor *descriptor void );
);
void ChfSignal( /* Signal the current conditions */ void ChfGenerate( /* Generate a condition into the stack */
void const int module_id, const ChfChar* file_name, const int line_number, const int condition_code,
); const ChfSeverity severity, ... );
void ChfDiscard( /* Discard the current conditions */ const ChfChar* ChfGetMessage( /* Retrieve a condition message */
void const int module_id, const int condition_code, const ChfChar* default_message );
);
void ChfGenerate( /* Generate a condition into the stack */ const ChfDescriptor* ChfGetTopCondition( /* Retrieve top condition */
const int module_id, void );
const ChfChar *file_name,
const int line_number,
const int condition_code,
const ChfSeverity severity,
...
);
const ChfChar *ChfGetMessage( /* Retrieve a condition message */
const int module_id,
const int condition_code,
const ChfChar *default_message
);
const ChfDescriptor *ChfGetTopCondition( /* Retrieve top condition */
void
);

View file

@ -37,119 +37,110 @@
.- */ .- */
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Macros Macros
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#define CHF_MODULE_ID CHF_SET #define CHF_MODULE_ID CHF_SET
#define CHF_TMP_MESSAGE_LENGTH (2*CHF_MAX_MESSAGE_LENGTH) #define CHF_TMP_MESSAGE_LENGTH ( 2 * CHF_MAX_MESSAGE_LENGTH )
#define CHF_DEF_MESSAGE_LENGTH 40 #define CHF_DEF_MESSAGE_LENGTH 40
#define CHF_DEF_PARTIAL_MSG_FMT ChfText("Code <%d>d") #define CHF_DEF_PARTIAL_MSG_FMT ChfText( "Code <%d>d" )
#define CHF_DEF_MID_MSG_FMT ChfText("Mid <%d>d") #define CHF_DEF_MID_MSG_FMT ChfText( "Mid <%d>d" )
#define CHF_EXTENDED_INFO_FMT ChfText("(%s,%d)") #define CHF_EXTENDED_INFO_FMT ChfText( "(%s,%d)" )
#define CHF_SEVERITY_NAMES \ #define CHF_SEVERITY_NAMES \
{ ChfText("S"), ChfText("I"), ChfText("W"), ChfText("E"), ChfText("F") } { \
#define CHF_UNKNOWN_SEVERITY ChfText("?") ChfText( "S" ), ChfText( "I" ), ChfText( "W" ), ChfText( "E" ), ChfText( "F" ) \
#define CHF_MESSAGE_SEPARATOR ChfText("-") }
#define CHF_MESSAGE_TERMINATOR ChfText("\n") #define CHF_UNKNOWN_SEVERITY ChfText( "?" )
#define CHF_ABORT_HEADER ChfText("ChfAbort-F-") #define CHF_MESSAGE_SEPARATOR ChfText( "-" )
#define CHF_ABORT_BAD_CODE_FMT ChfText("Bad abort code <%d>d\n") #define CHF_MESSAGE_TERMINATOR ChfText( "\n" )
#define CHF_ABORT_GOOD_CODE_FMT ChfText("%s\n") #define CHF_ABORT_HEADER ChfText( "ChfAbort-F-" )
#define CHF_ABORT_BAD_CODE_FMT ChfText( "Bad abort code <%d>d\n" )
#define CHF_ABORT_GOOD_CODE_FMT ChfText( "%s\n" )
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Abort codes used with ChfAbort() Abort codes used with ChfAbort()
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#define CHF_ABORT_SILENT 0 #define CHF_ABORT_SILENT 0
#define CHF_ABORT_INIT 1 #define CHF_ABORT_INIT 1
#define CHF_ABORT_MSG_OVF 2 #define CHF_ABORT_MSG_OVF 2
#define CHF_ABORT_INVALID_ACTION 3 #define CHF_ABORT_INVALID_ACTION 3
#define CHF_ABORT_DUP_INIT 4 #define CHF_ABORT_DUP_INIT 4
#define CHF_ABORT_ALREADY_UNWINDING 5 #define CHF_ABORT_ALREADY_UNWINDING 5
#define CHF_ABORT_IMPROPERLY_HANDLED 6 #define CHF_ABORT_IMPROPERLY_HANDLED 6
#define CHF_ABORT_FATAL_UNWINDING 7 #define CHF_ABORT_FATAL_UNWINDING 7
#define CHF_ABORT_COND_STACK_OVF 8 #define CHF_ABORT_COND_STACK_OVF 8
#define CHF_ABORT_GET_CONTEXT 9 #define CHF_ABORT_GET_CONTEXT 9
#define CHF_ABORT_PTHREAD 10 #define CHF_ABORT_PTHREAD 10
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Type definitions Type definitions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
typedef struct ChfHandlerDescriptor_S typedef struct ChfHandlerDescriptor_S {
{ ChfHandler handler;
ChfHandler handler; void* unwind_context;
void *unwind_context; ChfPointer handler_context;
ChfPointer handler_context; } ChfHandlerDescriptor;
}
ChfHandlerDescriptor;
typedef struct ChfContext_S /* CHF Context */ typedef struct ChfContext_S /* CHF Context */
{ {
ChfState state; /* Current CHF state */ ChfState state; /* Current CHF state */
const ChfChar *app_name; /* Application's name */ const ChfChar* app_name; /* Application's name */
ChfOptions options; /* Options */ ChfOptions options; /* Options */
void *mrs_data; /* Message retrieval private data */ void* mrs_data; /* Message retrieval private data */
ChfMrsGet mrs_get; /* 'GetMessage' function */ ChfMrsGet mrs_get; /* 'GetMessage' function */
ChfMrsExit mrs_exit; /* 'Exit' function */ ChfMrsExit mrs_exit; /* 'Exit' function */
int condition_stack_size; /* Size of the condition stack */ int condition_stack_size; /* Size of the condition stack */
int handler_stack_size; /* Size of the handler stack */ int handler_stack_size; /* Size of the handler stack */
int exit_code; /* Abnormal exit code */ int exit_code; /* Abnormal exit code */
ChfDescriptor *condition_stack; /* Condition stack */ ChfDescriptor* condition_stack; /* Condition stack */
ChfDescriptor *condition_base; /* Current condition stack base */ ChfDescriptor* condition_base; /* Current condition stack base */
ChfDescriptor *condition_sp; /* Current condition stack pointer */ ChfDescriptor* condition_sp; /* Current condition stack pointer */
ChfHandlerDescriptor *handler_stack; /* Handler stack */ ChfHandlerDescriptor* handler_stack; /* Handler stack */
ChfHandlerDescriptor *handler_sp; /* Current handler stack pointer */ ChfHandlerDescriptor* handler_sp; /* Current handler stack pointer */
ChfChar *message_buffer; /* Message buffer */ ChfChar* message_buffer; /* Message buffer */
} } ChfContext;
ChfContext;
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Multithreading support Multithreading support
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifdef _REENTRANT #ifdef _REENTRANT
#define chf_context (*_ChfGetContext()) # define chf_context ( *_ChfGetContext() )
#else #else
#define chf_context _chf_context # define chf_context _chf_context
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Global variables Global variables
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
extern ChfContext _chf_context; /* CHF Context */ extern ChfContext _chf_context; /* CHF Context */
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Private function prototypes Private function prototypes
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifdef _REENTRANT #ifdef _REENTRANT
ChfContext *_ChfGetContext(void); ChfContext* _ChfGetContext( void );
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Private redirection of stdlib functions needed by Win32 Private redirection of stdlib functions needed by Win32
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifdef _WIN32 #ifdef _WIN32
#define ChfStrlen _tcslen # define ChfStrlen _tcslen
#define ChfStrcpy _tcscpy # define ChfStrcpy _tcscpy
#define ChfStrcat _tcscat # define ChfStrcat _tcscat
#define ChfStrncpy _tcsncpy # define ChfStrncpy _tcsncpy
#define ChfSprintf _stprintf # define ChfSprintf _stprintf
#define ChfVsprintf _vstprintf # define ChfVsprintf _vstprintf
#else #else
#define ChfStrlen strlen # define ChfStrlen strlen
#define ChfStrcpy strcpy # define ChfStrcpy strcpy
#define ChfStrcat strcat # define ChfStrcat strcat
#define ChfStrncpy strncpy # define ChfStrncpy strncpy
#define ChfSprintf sprintf # define ChfSprintf sprintf
#define ChfVsprintf vsprintf # define ChfVsprintf vsprintf
#endif #endif

View file

@ -37,43 +37,38 @@ static char rcs_id[] = "$Id: chf_abrt.c,v 2.2 2001/01/25 12:08:24 cibrario Exp $
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
/* Abort codes message table; the relative position of the messages must /* Abort codes message table; the relative position of the messages must
match the numeric codes CHF_ABORT_xxxx defined in ChfPriv.h match the numeric codes CHF_ABORT_xxxx defined in ChfPriv.h
*/ */
static const ChfChar *message_table[] = static const ChfChar* message_table[] = { ( const ChfChar* )NULL,
{ ChfText( "Not initialized" ),
(const ChfChar *)NULL, ChfText( "Temporary message buffer overflow" ),
ChfText("Not initialized"), ChfText( "Invalid action from last chance handler" ),
ChfText("Temporary message buffer overflow"), ChfText( "Already initialized" ),
ChfText("Invalid action from last chance handler"), ChfText( "Unwind request while unwinding" ),
ChfText("Already initialized"), ChfText( "Improperly handled condition" ),
ChfText("Unwind request while unwinding"), ChfText( "Fatal condition while unwinding" ),
ChfText("Improperly handled condition"), ChfText( "Condition stack overflow" ),
ChfText("Fatal condition while unwinding"), ChfText( "Can't prime a new Chf context" ),
ChfText("Condition stack overflow"), ChfText( "Pthread interaction failed" ) };
ChfText("Can't prime a new Chf context"),
ChfText("Pthread interaction failed")
};
#define MESSAGE_TABLE_SIZE (sizeof(message_table)/sizeof(const ChfChar *))
#define MESSAGE_TABLE_SIZE ( sizeof( message_table ) / sizeof( const ChfChar* ) )
/* .+ /* .+
@ -96,7 +91,7 @@ static const ChfChar *message_table[] =
application when a CHF_FATAL condition occours. application when a CHF_FATAL condition occours.
NOTE: This function must be called only when either a serious internal CHF NOTE: This function must be called only when either a serious internal CHF
failure occurs or it's necessary to abort the application. failure occurs or it's necessary to abort the application.
WIN32: WIN32:
@ -107,13 +102,13 @@ static const ChfChar *message_table[] =
- abort() is not supported and has been replaced by exit(EXIT_FAILURE) - abort() is not supported and has been replaced by exit(EXIT_FAILURE)
.call : .call :
ChfAbort(abort_code); ChfAbort(abort_code);
.input : .input :
const int abort_code, abort_code const int abort_code, abort_code
.output : .output :
void void
.status_codes : .status_codes :
none none
.notes : .notes :
1.1, 13-May-1996, creation 1.1, 13-May-1996, creation
2.1, 19-May-2000, update: 2.1, 19-May-2000, update:
@ -122,78 +117,66 @@ static const ChfChar *message_table[] =
- added Win32 support - added Win32 support
.- */ .- */
void ChfAbort( /* Abort application */ void ChfAbort( /* Abort application */
const int abort_code const int abort_code )
)
{ {
#ifdef _WIN32 #ifdef _WIN32
if(abort_code != CHF_ABORT_SILENT) if ( abort_code != CHF_ABORT_SILENT ) {
{ TCHAR abort_msg[ CHF_MAX_MESSAGE_LENGTH ];
TCHAR abort_msg[CHF_MAX_MESSAGE_LENGTH]; HWND active_window;
HWND active_window;
/* stderr not available; /* stderr not available;
put complaint in a message box and display it put complaint in a message box and display it
*/
if ( abort_code < 0 || abort_code >= MESSAGE_TABLE_SIZE )
_stprintf( abort_msg, CHF_ABORT_BAD_CODE_FMT, abort_code );
else
_stprintf( abort_msg, CHF_ABORT_GOOD_CODE_FMT, message_table[ abort_code ] );
/* Return value of MessageBox() ignored, because there is only
one available choice (abort) here. Avoid using a NULL handle.
*/
if ( chf_context.state != CHF_UNKNOWN && ( active_window = GetActiveWindow() ) != ( HWND )NULL )
( void )MessageBox( active_window, abort_msg, chf_context.app_name, MB_OK | MB_ICONERROR | MB_APPLMODAL | MB_SETFOREGROUND );
}
/* Immediately exit the application with exit code EXIT_FAILURE
if CHF_ABORT option is set or if something is wrong with Chf state.
*/ */
if(abort_code < 0 || abort_code >= MESSAGE_TABLE_SIZE) if ( chf_context.state == CHF_UNKNOWN || chf_context.options & CHF_ABORT )
_stprintf(abort_msg, exit( EXIT_FAILURE );
CHF_ABORT_BAD_CODE_FMT, abort_code);
else else
_stprintf(abort_msg,
CHF_ABORT_GOOD_CODE_FMT, message_table[abort_code]);
/* Return value of MessageBox() ignored, because there is only
one available choice (abort) here. Avoid using a NULL handle.
*/
if(chf_context.state != CHF_UNKNOWN
&& (active_window = GetActiveWindow()) != (HWND)NULL)
(void)
MessageBox(active_window,
abort_msg,
chf_context.app_name,
MB_OK
|MB_ICONERROR
|MB_APPLMODAL|MB_SETFOREGROUND);
}
/* Immediately exit the application with exit code EXIT_FAILURE
if CHF_ABORT option is set or if something is wrong with Chf state.
*/
if(chf_context.state == CHF_UNKNOWN || chf_context.options & CHF_ABORT)
exit(EXIT_FAILURE);
else
/* Else, exit the application anyway, but with the exit code /* Else, exit the application anyway, but with the exit code
registered by the application. Don't use PostQuitMessage(), registered by the application. Don't use PostQuitMessage(),
because the contract is that ChfAbort() never returns to the caller. because the contract is that ChfAbort() never returns to the caller.
*/ */
#ifndef _REENTRANT # ifndef _REENTRANT
exit(chf_context.exit_code); exit( chf_context.exit_code );
#else # else
#error "_REENTRANT not supported yet" # error "_REENTRANT not supported yet"
#endif # endif
#else #else
if(abort_code != CHF_ABORT_SILENT) if ( abort_code != CHF_ABORT_SILENT ) {
{ fputs( CHF_ABORT_HEADER, stderr );
fputs(CHF_ABORT_HEADER, stderr);
if(abort_code < 0 || abort_code >= MESSAGE_TABLE_SIZE) if ( abort_code < 0 || abort_code >= MESSAGE_TABLE_SIZE )
fprintf(stderr, CHF_ABORT_BAD_CODE_FMT, abort_code); fprintf( stderr, CHF_ABORT_BAD_CODE_FMT, abort_code );
else
fprintf( stderr, CHF_ABORT_GOOD_CODE_FMT, message_table[ abort_code ] );
}
if ( chf_context.state == CHF_UNKNOWN || chf_context.options & CHF_ABORT )
abort();
else else
fprintf(stderr, CHF_ABORT_GOOD_CODE_FMT, message_table[abort_code]); # ifndef _REENTRANT
} exit( chf_context.exit_code );
# else
if(chf_context.state == CHF_UNKNOWN || chf_context.options & CHF_ABORT) pthread_exit( ( void* )( chf_context.exit_code ) );
abort(); # endif
else
#ifndef _REENTRANT
exit(chf_context.exit_code);
#else
pthread_exit((void *)(chf_context.exit_code));
#endif
#endif #endif
} }

View file

@ -31,21 +31,20 @@ static char rcs_id[] = "$Id: chf_gen.c,v 2.2 2001/01/25 12:10:22 cibrario Exp $"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* .+ /* .+
.title : ChfGenerate .title : ChfGenerate
@ -63,117 +62,104 @@ static char rcs_id[] = "$Id: chf_gen.c,v 2.2 2001/01/25 12:10:22 cibrario Exp $"
condition stack. condition stack.
NOTE: This function calls the CHF function 'ChfAbort()' to NOTE: This function calls the CHF function 'ChfAbort()' to
abort the application if either: abort the application if either:
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT) - CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
- there is an overflow in the internal buffer used during the - there is an overflow in the internal buffer used during the
generation of the partial message associated with the condition generation of the partial message associated with the condition
(abort code CHF_ABORT_MSG_OVF) (abort code CHF_ABORT_MSG_OVF)
- there was an attempt to generate a condition while the CHF condition - there was an attempt to generate a condition while the CHF condition
CHF_F_COND_STACK_FULL (condition stack full) was being signalled CHF_F_COND_STACK_FULL (condition stack full) was being signalled
(abort code CHF_ABORT_COND_STACK_OVF) (abort code CHF_ABORT_COND_STACK_OVF)
.call : .call :
ChfGenerate(module_id, file_name, line_number, ChfGenerate(module_id, file_name, line_number,
condition_code, severity, ...); condition_code, severity, ...);
.input : .input :
const int module_id, module identifier const int module_id, module identifier
const char *file_name, file name const char *file_name, file name
const int line_number, line number const int line_number, line number
const int condition_code, condition code const int condition_code, condition code
const ChfSeverity severity, severity const ChfSeverity severity, severity
..., additional arguments ..., additional arguments
.output : .output :
void void
.status_codes : .status_codes :
(*) CHF_F_COND_STACK_FULL, the condition stack is full (*) CHF_F_COND_STACK_FULL, the condition stack is full
.notes : .notes :
1.1, 3-May-1996, creation 1.1, 3-May-1996, creation
.- */ .- */
void ChfGenerate( /* Generate a condition into the stack */ void ChfGenerate( /* Generate a condition into the stack */
const int module_id, const int module_id, const ChfChar* file_name, const int line_number, const int condition_code,
const ChfChar *file_name, const ChfSeverity severity, ... )
const int line_number,
const int condition_code,
const ChfSeverity severity,
...
)
{ {
ChfDescriptor *new_descriptor; ChfDescriptor* new_descriptor;
va_list aux_arg; va_list aux_arg;
/* Check that CHF has been correctly initialized */ /* Check that CHF has been correctly initialized */
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
/* Prepare the additional arguments list */ /* Prepare the additional arguments list */
va_start(aux_arg, severity); va_start( aux_arg, severity );
if((new_descriptor = chf_context.condition_sp) - if ( ( new_descriptor = chf_context.condition_sp ) - chf_context.condition_stack >= chf_context.condition_stack_size ) {
chf_context.condition_stack >= chf_context.condition_stack_size) /* The condition stack is full;
{ generate the CHF_F_COND_STACK_FULL condition and signal it immediately,
/* The condition stack is full; using the last available slot of the stack, if it's still empty,
generate the CHF_F_COND_STACK_FULL condition and signal it immediately, otherwise abort the application.
using the last available slot of the stack, if it's still empty, */
otherwise abort the application. if ( new_descriptor - chf_context.condition_stack == chf_context.condition_stack_size ) {
*/ new_descriptor->module_id = CHF_MODULE_ID;
if(new_descriptor - chf_context.condition_stack == new_descriptor->condition_code = CHF_F_COND_STACK_FULL;
chf_context.condition_stack_size) new_descriptor->severity = CHF_FATAL;
{ new_descriptor->line_number = CHF_UNKNOWN_LINE_NUMBER;
new_descriptor->module_id = CHF_MODULE_ID; new_descriptor->file_name = CHF_UNKNOWN_FILE_NAME;
new_descriptor->condition_code = CHF_F_COND_STACK_FULL;
new_descriptor->severity = CHF_FATAL;
new_descriptor->line_number = CHF_UNKNOWN_LINE_NUMBER;
new_descriptor->file_name = CHF_UNKNOWN_FILE_NAME;
ChfStrncpy(new_descriptor->message, ChfStrncpy( new_descriptor->message,
ChfGetMessage(CHF_MODULE_ID, CHF_F_COND_STACK_FULL, ChfGetMessage( CHF_MODULE_ID, CHF_F_COND_STACK_FULL, ChfText( "Condition stack is full" ) ),
ChfText("Condition stack is full")), CHF_MAX_MESSAGE_LENGTH-1); CHF_MAX_MESSAGE_LENGTH - 1 );
new_descriptor->message[CHF_MAX_MESSAGE_LENGTH-1] = '\0'; new_descriptor->message[ CHF_MAX_MESSAGE_LENGTH - 1 ] = '\0';
new_descriptor->next = CHF_NULL_DESCRIPTOR; new_descriptor->next = CHF_NULL_DESCRIPTOR;
chf_context.condition_sp++; chf_context.condition_sp++;
ChfSignal(); ChfSignal();
}
else
ChfAbort( CHF_ABORT_COND_STACK_OVF );
} }
else else {
ChfAbort(CHF_ABORT_COND_STACK_OVF); ChfChar def_message[ CHF_DEF_MESSAGE_LENGTH ];
} ChfChar tmp_message[ CHF_TMP_MESSAGE_LENGTH ];
else new_descriptor->module_id = module_id;
{ new_descriptor->condition_code = condition_code;
ChfChar def_message[CHF_DEF_MESSAGE_LENGTH]; new_descriptor->severity = severity;
ChfChar tmp_message[CHF_TMP_MESSAGE_LENGTH]; new_descriptor->line_number = line_number;
new_descriptor->file_name = file_name;
new_descriptor->module_id = module_id; /* Generate the default message */
new_descriptor->condition_code = condition_code; ChfSprintf( def_message, CHF_DEF_PARTIAL_MSG_FMT, condition_code );
new_descriptor->severity = severity;
new_descriptor->line_number = line_number;
new_descriptor->file_name = file_name;
/* Generate the default message */ /* Generate the partial message associated with the condition using a
ChfSprintf(def_message, CHF_DEF_PARTIAL_MSG_FMT, condition_code); temporary area
*/
if ( ChfVsprintf( tmp_message, ChfGetMessage( module_id, condition_code, def_message ), aux_arg ) >= CHF_TMP_MESSAGE_LENGTH )
ChfAbort( CHF_ABORT_MSG_OVF );
/* Generate the partial message associated with the condition using a /* Copy the message into the condition descriptor */
temporary area ChfStrncpy( new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH - 1 );
*/ new_descriptor->message[ CHF_MAX_MESSAGE_LENGTH - 1 ] = '\0';
if(
ChfVsprintf(tmp_message,
ChfGetMessage(module_id, condition_code, def_message), aux_arg) >=
CHF_TMP_MESSAGE_LENGTH)
ChfAbort(CHF_ABORT_MSG_OVF);
/* Copy the message into the condition descriptor */ /* Link the new descriptor with the current descriptor list, if it
ChfStrncpy(new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH-1); isn't the first descriptor of the list
new_descriptor->message[CHF_MAX_MESSAGE_LENGTH-1] = '\0'; */
new_descriptor->next = ( new_descriptor == chf_context.condition_base ) ? CHF_NULL_DESCRIPTOR : new_descriptor - 1;
/* Link the new descriptor with the current descriptor list, if it chf_context.condition_sp++;
isn't the first descriptor of the list }
*/
new_descriptor->next = (new_descriptor == chf_context.condition_base)
? CHF_NULL_DESCRIPTOR : new_descriptor - 1;
chf_context.condition_sp++;
}
} }

View file

@ -44,19 +44,18 @@ static char rcs_id[] = "$Id: chf_hdlr.c,v 2.2 2001/01/25 12:12:46 cibrario Exp $
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* .+ /* .+
.title : StructuredHelper .title : StructuredHelper
@ -68,42 +67,36 @@ static char rcs_id[] = "$Id: chf_hdlr.c,v 2.2 2001/01/25 12:12:46 cibrario Exp $
ChfPushHandler() when its 'new_handler' argument is CHF_NULL_HANDLER, ChfPushHandler() when its 'new_handler' argument is CHF_NULL_HANDLER,
and performs the following functions: and performs the following functions:
- if called during an ordinary signalling operation with a - if called during an ordinary signalling operation with a
CHF_FATAL condition, it requests the action CHF_UNWIND_KEEP CHF_FATAL condition, it requests the action CHF_UNWIND_KEEP
- if called when Chf is in any other state, or with a - if called when Chf is in any other state, or with a
severity less than CHF_FATAL, it requests the action CHF_RESIGNAL severity less than CHF_FATAL, it requests the action CHF_RESIGNAL
The structured condition handling helper currently makes no use of The structured condition handling helper currently makes no use of
handler_context. handler_context.
.call : .call :
action = StructuredHelper(desc, state, context); action = StructuredHelper(desc, state, context);
.input : .input :
const ChfDescriptor *desc, condition descriptor const ChfDescriptor *desc, condition descriptor
const ChfState state, current CHF state const ChfState state, current CHF state
.output : .output :
ChfAction action, action requested by the handler ChfAction action, action requested by the handler
.status_codes : .status_codes :
none none
.notes : .notes :
2.1, 19-May-2000, creation 2.1, 19-May-2000, creation
.- */ .- */
static ChfAction StructuredHelper( static ChfAction StructuredHelper( const ChfDescriptor* desc, const ChfState state, ChfPointer handler_context )
const ChfDescriptor *desc,
const ChfState state,
ChfPointer handler_context
)
{ {
ChfAction action; ChfAction action;
const ChfDescriptor *d; const ChfDescriptor* d;
return((state == CHF_SIGNALING && ChfGetSeverity(desc) == CHF_FATAL) return ( ( state == CHF_SIGNALING && ChfGetSeverity( desc ) == CHF_FATAL ) ? CHF_UNWIND_KEEP : CHF_RESIGNAL );
? CHF_UNWIND_KEEP : CHF_RESIGNAL);
} }
/* .+ /* .+
.title : ChfPushHandler .title : ChfPushHandler
@ -139,19 +132,19 @@ static ChfAction StructuredHelper(
conditions are CHF_FATAL. conditions are CHF_FATAL.
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
the CHF subsystem has not been initialized. the CHF subsystem has not been initialized.
.call : .call :
ChfPushHandler(new_handler, unwind_context); ChfPushHandler(new_handler, unwind_context);
.input : .input :
ChfHandler new_handler, new condition handler ChfHandler new_handler, new condition handler
void *unwind_context, handler unwind context pointer void *unwind_context, handler unwind context pointer
ChfPointer handler_context, private handler context pointer ChfPointer handler_context, private handler context pointer
.output : .output :
void void
.status_codes : .status_codes :
(*) CHF_F_BAD_STATE, bad CHF state for requested operation (*) CHF_F_BAD_STATE, bad CHF state for requested operation
(*) CHF_F_HDLR_STACK_FULL, the handler stack is full (*) CHF_F_HDLR_STACK_FULL, the handler stack is full
.notes : .notes :
1.1, 13-May-1996, creation 1.1, 13-May-1996, creation
1.6, 15-Jan-1997, update: 1.6, 15-Jan-1997, update:
@ -162,44 +155,34 @@ static ChfAction StructuredHelper(
- added StructuredHelper handling - added StructuredHelper handling
.- */ .- */
void ChfPushHandler( /* Push a new handler into the stack */ void ChfPushHandler( /* Push a new handler into the stack */
ChfHandler new_handler, ChfHandler new_handler, void* unwind_context, ChfPointer handler_context )
void *unwind_context,
ChfPointer handler_context
)
{ {
/* Make sure that CHF has been correctly initialized and is idle */ /* Make sure that CHF has been correctly initialized and is idle */
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if(chf_context.state != CHF_IDLE) if ( chf_context.state != CHF_IDLE ) {
{ ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
ChfCondition CHF_F_BAD_STATE, CHF_FATAL
ChfEnd;
ChfSignal(); ChfSignal();
} }
/* Check if the handler stack is full */ /* Check if the handler stack is full */
else if(chf_context.handler_sp - chf_context.handler_stack >= else if ( chf_context.handler_sp - chf_context.handler_stack >= chf_context.handler_stack_size ) {
chf_context.handler_stack_size) ChfCondition CHF_F_HDLR_STACK_FULL, CHF_FATAL ChfEnd;
{
ChfCondition CHF_F_HDLR_STACK_FULL, CHF_FATAL
ChfEnd;
ChfSignal(); ChfSignal();
} }
else else {
{ chf_context.handler_sp->unwind_context = unwind_context;
chf_context.handler_sp->unwind_context = unwind_context; chf_context.handler_sp->handler_context = handler_context;
chf_context.handler_sp->handler_context = handler_context; chf_context.handler_sp->handler = ( ( new_handler == CHF_NULL_HANDLER ) ? StructuredHelper : new_handler );
chf_context.handler_sp->handler = chf_context.handler_sp++;
((new_handler == CHF_NULL_HANDLER) ? StructuredHelper : new_handler); }
chf_context.handler_sp++;
}
} }
/* .+ /* .+
.title : ChfPopHandler .title : ChfPopHandler
@ -215,17 +198,17 @@ void ChfPushHandler( /* Push a new handler into the stack */
conditions are CHF_FATAL. conditions are CHF_FATAL.
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
the CHF subsystem has not been initialized. the CHF subsystem has not been initialized.
.call : .call :
ChfPopHandler(); ChfPopHandler();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
CHF_F_BAD_STATE, bad CHF state for requested operation CHF_F_BAD_STATE, bad CHF state for requested operation
CHF_F_HDLR_STACK_FULL, the handler stack is full CHF_F_HDLR_STACK_FULL, the handler stack is full
.notes : .notes :
1.1, 13-May-1996, creation 1.1, 13-May-1996, creation
1.6, 15-Jan-1997, update: 1.6, 15-Jan-1997, update:
@ -234,31 +217,27 @@ void ChfPushHandler( /* Push a new handler into the stack */
- improved documentation - improved documentation
.- */ .- */
void ChfPopHandler( /* Pop a handler */ void ChfPopHandler( /* Pop a handler */
void void )
)
{ {
/* Make sure that CHF has been correctly initialized and is idle */ /* Make sure that CHF has been correctly initialized and is idle */
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if(chf_context.state != CHF_IDLE) if ( chf_context.state != CHF_IDLE ) {
{ ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
ChfCondition CHF_F_BAD_STATE, CHF_FATAL
ChfEnd;
ChfSignal(); ChfSignal();
} }
/* Check if the handler stack is empty */ /* Check if the handler stack is empty */
else if(chf_context.handler_sp == chf_context.handler_stack) else if ( chf_context.handler_sp == chf_context.handler_stack ) {
{ ChfCondition CHF_F_HDLR_STACK_EMPTY, CHF_FATAL ChfEnd;
ChfCondition CHF_F_HDLR_STACK_EMPTY, CHF_FATAL
ChfEnd;
ChfSignal(); ChfSignal();
} }
/* Discard the topmost condition handler */ /* Discard the topmost condition handler */
else else
--chf_context.handler_sp; --chf_context.handler_sp;
} }

View file

@ -54,20 +54,19 @@ static char rcs_id[] = "$Id: chf_init.c,v 2.2 2001/01/25 14:05:23 cibrario Exp $
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Global and static variables Global and static variables
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -82,14 +81,13 @@ ChfContext _chf_context;
/* Message separator and severity names for ChfBuildMessage() */ /* Message separator and severity names for ChfBuildMessage() */
static const ChfChar separator[] = CHF_MESSAGE_SEPARATOR; static const ChfChar separator[] = CHF_MESSAGE_SEPARATOR;
static const ChfChar *severity_name[] = CHF_SEVERITY_NAMES; static const ChfChar* severity_name[] = CHF_SEVERITY_NAMES;
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Multithreading support Multithreading support
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
/* Mutex to access chf_context during initialization and exit; /* Mutex to access chf_context during initialization and exit;
mutex to puts condition messages on stderr (DefaultHandler) mutex to puts condition messages on stderr (DefaultHandler)
@ -103,21 +101,19 @@ static pthread_key_t data_key;
/* This function is called to destroy a Chf context when the owning /* This function is called to destroy a Chf context when the owning
thread terminated. thread terminated.
*/ */
static void DestroyContext(void *context) static void DestroyContext( void* context )
{ {
free(((ChfContext *)context)->message_buffer); free( ( ( ChfContext* )context )->message_buffer );
free(((ChfContext *)context)->handler_stack); free( ( ( ChfContext* )context )->handler_stack );
free(((ChfContext *)context)->condition_stack); free( ( ( ChfContext* )context )->condition_stack );
free(context); free( context );
} }
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Private functions Private functions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
/* .+ /* .+
.title : DefaultHandler .title : DefaultHandler
@ -128,21 +124,21 @@ static void DestroyContext(void *context)
pushed into the condition handler stack by ChfInit() and performs the pushed into the condition handler stack by ChfInit() and performs the
following functions: following functions:
- if called during an unwind, it returns immediately to the caller, - if called during an unwind, it returns immediately to the caller,
requesting the action CHF_RESIGNAL, else requesting the action CHF_RESIGNAL, else
- if the severity of the condition being signalled is greater than - if the severity of the condition being signalled is greater than
CHF_SUCCESS, it prints the messages associated with the entire CHF_SUCCESS, it prints the messages associated with the entire
condition group on stderr using the standard function condition group on stderr using the standard function
ChfBuildMessage() to build the messages. ChfBuildMessage() to build the messages.
- if the severity of the condition being signalled is less than - if the severity of the condition being signalled is less than
CHF_FATAL, it returns to the caller requesting the action CHF_FATAL, it returns to the caller requesting the action
CHF_CONTINUE, else CHF_CONTINUE, else
- if the CHF_FATAL condition was NOT signalled during an unwind - if the CHF_FATAL condition was NOT signalled during an unwind
operation, it returns to the caller requesting the action operation, it returns to the caller requesting the action
CHF_UNWIND, otherwise it requests the action CHF_RESIGNAL. CHF_UNWIND, otherwise it requests the action CHF_RESIGNAL.
WIN32: WIN32:
@ -151,14 +147,14 @@ static void DestroyContext(void *context)
anything anything
.call : .call :
action = DefaultHandler(desc, state, context); action = DefaultHandler(desc, state, context);
.input : .input :
const ChfDescriptor *desc, condition descriptor const ChfDescriptor *desc, condition descriptor
const ChfState state, current CHF state const ChfState state, current CHF state
.output : .output :
ChfAction action, action requested by the handler ChfAction action, action requested by the handler
.status_codes : .status_codes :
none none
.notes : .notes :
1.1, 16-May-1996, creation 1.1, 16-May-1996, creation
1.6, 15-Jan-1997, update: 1.6, 15-Jan-1997, update:
@ -170,69 +166,62 @@ static void DestroyContext(void *context)
- added Win32 support - added Win32 support
.- */ .- */
static ChfAction DefaultHandler( static ChfAction DefaultHandler( const ChfDescriptor* desc, const ChfState state, ChfPointer handler_context )
const ChfDescriptor *desc,
const ChfState state,
ChfPointer handler_context
)
{ {
ChfAction action; ChfAction action;
const ChfDescriptor *d; const ChfDescriptor* d;
if(state == CHF_UNWINDING) if ( state == CHF_UNWINDING )
/* If CHF is unwinding, do nothing */ /* If CHF is unwinding, do nothing */
action = CHF_RESIGNAL; action = CHF_RESIGNAL;
else else {
{ /* Print the condition messages, if necessary. The sequence of fputs()
/* Print the condition messages, if necessary. The sequence of fputs() is done atomically if multithreading support is enabled.
is done atomically if multithreading support is enabled. In Win32, the default handler does not print anything.
In Win32, the default handler does not print anything. */
*/ if ( ChfGetSeverity( desc ) > CHF_SUCCESS ) {
if(ChfGetSeverity(desc) > CHF_SUCCESS)
{
#ifdef _REENTRANT #ifdef _REENTRANT
if(pthread_mutex_lock(&fputs_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_lock( &fputs_mutex ) )
ChfAbort( CHF_ABORT_PTHREAD );
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
for(d = desc; d != CHF_NULL_DESCRIPTOR; d = ChfGetNextDescriptor(d)) for ( d = desc; d != CHF_NULL_DESCRIPTOR; d = ChfGetNextDescriptor( d ) )
fputs(ChfBuildMessage(d), stderr); fputs( ChfBuildMessage( d ), stderr );
#endif #endif
#ifdef _REENTRANT #ifdef _REENTRANT
if(pthread_mutex_unlock(&fputs_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_unlock( &fputs_mutex ) )
ChfAbort( CHF_ABORT_PTHREAD );
#endif #endif
}
/* Determine the handler action */
switch ( ChfGetSeverity( desc ) ) {
case CHF_SUCCESS:
case CHF_INFO:
case CHF_WARNING:
case CHF_ERROR:
{
/* Continue execution if the severity is less than CHF_FATAL */
action = CHF_CONTINUE;
break;
}
default:
{
/* The severity of the condition is CHF_FATAL; appempt to unwind if
the fatal condition wasn't signalled during another unwind.
*/
action = ( ( state == CHF_SIGNAL_UNWINDING ) ? CHF_RESIGNAL : CHF_UNWIND );
break;
}
}
} }
/* Determine the handler action */ /* Return the action code to the Chf handler dispatcher */
switch(ChfGetSeverity(desc)) return action;
{
case CHF_SUCCESS:
case CHF_INFO:
case CHF_WARNING:
case CHF_ERROR:
{
/* Continue execution if the severity is less than CHF_FATAL */
action = CHF_CONTINUE;
break;
}
default:
{
/* The severity of the condition is CHF_FATAL; appempt to unwind if
the fatal condition wasn't signalled during another unwind.
*/
action = ((state == CHF_SIGNAL_UNWINDING) ? CHF_RESIGNAL: CHF_UNWIND);
break;
}
}
}
/* Return the action code to the Chf handler dispatcher */
return action;
} }
/* .+ /* .+
.title : scopy .title : scopy
@ -244,45 +233,38 @@ static ChfAction DefaultHandler(
The function returns a pointer to the NUL-terminator just written. The function returns a pointer to the NUL-terminator just written.
.call : .call :
np = scopy(p, q, p_end); np = scopy(p, q, p_end);
.input : .input :
char *p, starting position for the write char *p, starting position for the write
const char *q, pointer to the string to be copied const char *q, pointer to the string to be copied
char *p_end, pointer to the end of the output area char *p_end, pointer to the end of the output area
.output : .output :
char *np, pointer to the NUL-terminator just written char *np, pointer to the NUL-terminator just written
.status_codes : .status_codes :
none none
.notes : .notes :
1.1, 16-May-1996, creation 1.1, 16-May-1996, creation
.- */ .- */
static ChfChar *scopy( static ChfChar* scopy( ChfChar* p, const ChfChar* q, ChfChar* p_end )
ChfChar *p,
const ChfChar *q,
ChfChar *p_end
)
{ {
size_t q_len = ChfStrlen(q); size_t q_len = ChfStrlen( q );
size_t p_avail = p_end - p; size_t p_avail = p_end - p;
if(q_len < p_avail) if ( q_len < p_avail ) {
{ ChfStrcpy( p, q );
ChfStrcpy(p, q); p += q_len;
p += q_len; }
}
else if(p_avail > 1) else if ( p_avail > 1 ) {
{ ChfStrncpy( p, q, p_avail - 2 );
ChfStrncpy(p, q, p_avail-2); p[ p_avail - 1 ] = '\0';
p[p_avail-1] = '\0'; p = p_end;
p = p_end; }
}
return p; return p;
} }
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Public functions Public functions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -300,10 +282,10 @@ static ChfChar *scopy(
necessary, to retrieve the requested message. necessary, to retrieve the requested message.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
if CHF hasn't been correctly initialized. if CHF hasn't been correctly initialized.
NOTE: The returned pointer points to per-thread static storage, which will be NOTE: The returned pointer points to per-thread static storage, which will be
overwritten by subsequent calls to this function. overwritten by subsequent calls to this function.
WIN32: WIN32:
@ -311,46 +293,42 @@ static ChfChar *scopy(
codes in CHF_ERRNO_SET is not performed codes in CHF_ERRNO_SET is not performed
.call : .call :
message = ChfGetMessage(module_id, condition_code, message = ChfGetMessage(module_id, condition_code,
default_message); default_message);
.input : .input :
const int module_id, module identifier const int module_id, module identifier
const int condition_code, condition code const int condition_code, condition code
const char *default_message, default message const char *default_message, default message
.output : .output :
const char *message, pointer to the retrieved message const char *message, pointer to the retrieved message
.status_codes : .status_codes :
none none
.notes : .notes :
1.1, 17-May-1996, creation 1.1, 17-May-1996, creation
2.2, 22-Jan-2001, update: 2.2, 22-Jan-2001, update:
- added Win32 support - added Win32 support
.- */ .- */
const ChfChar *ChfGetMessage( /* Retrieve a condition message */ const ChfChar* ChfGetMessage( /* Retrieve a condition message */
const int module_id, const int module_id, const int condition_code, const ChfChar* default_message )
const int condition_code,
const ChfChar *default_message
)
{ {
const ChfChar *message; const ChfChar* message;
/* Check that CHF has been correctly initialized */ /* Check that CHF has been correctly initialized */
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if((message = chf_context.mrs_get(chf_context.mrs_data, if ( ( message = chf_context.mrs_get( chf_context.mrs_data, module_id, condition_code, default_message ) ) == default_message &&
module_id, condition_code, default_message)) == default_message && module_id == CHF_ERRNO_SET )
module_id == CHF_ERRNO_SET) #ifdef _WIN32
# ifdef _WIN32 message = default_message;
message = default_message; #else
# else message = strerror( condition_code );
message = strerror(condition_code); #endif
# endif
return(message); return ( message );
} }
/* .+ /* .+
.title : ChfBuildMessage .title : ChfBuildMessage
@ -361,10 +339,10 @@ const ChfChar *ChfGetMessage( /* Retrieve a condition message */
descriptor and returns a pointer to a string containing it. descriptor and returns a pointer to a string containing it.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
if CHF hasn't been correctly initialized. if CHF hasn't been correctly initialized.
NOTE: The returned pointer points to per-thread static storage, which will be NOTE: The returned pointer points to per-thread static storage, which will be
overwritten by subsequent calls to this function. overwritten by subsequent calls to this function.
WIN32: WIN32:
@ -372,87 +350,81 @@ const ChfChar *ChfGetMessage( /* Retrieve a condition message */
included in the message included in the message
.call : .call :
msg = ChfBuildMessage(descriptor); msg = ChfBuildMessage(descriptor);
.input : .input :
const ChfDescriptor *descriptor, condition descriptor const ChfDescriptor *descriptor, condition descriptor
.output : .output :
char *msg, pointer to the message associated with 'descriptor' char *msg, pointer to the message associated with 'descriptor'
.status_codes : .status_codes :
none none
.notes : .notes :
1.1, 16-May-1996, creation 1.1, 16-May-1996, creation
2.2, 22-Jan-2001, update: 2.2, 22-Jan-2001, update:
- added Win32 support - added Win32 support
.- */ .- */
ChfChar *ChfBuildMessage( /* Build a condition message */ ChfChar* ChfBuildMessage( /* Build a condition message */
const ChfDescriptor *descriptor const ChfDescriptor* descriptor )
)
{ {
ChfChar *tmp_p; ChfChar* tmp_p;
ChfChar *tmp_end; ChfChar* tmp_end;
ChfChar def_message[CHF_DEF_MESSAGE_LENGTH]; ChfChar def_message[ CHF_DEF_MESSAGE_LENGTH ];
ChfSeverity severity; ChfSeverity severity;
/* Check that CHF has been correctly initialized */ /* Check that CHF has been correctly initialized */
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
/* Set appropriate pointers to the start/end of the message buffer */ /* Set appropriate pointers to the start/end of the message buffer */
tmp_p = chf_context.message_buffer; tmp_p = chf_context.message_buffer;
tmp_end = tmp_p + CHF_MAX_MESSAGE_LENGTH; tmp_end = tmp_p + CHF_MAX_MESSAGE_LENGTH;
#ifndef _WIN32 #ifndef _WIN32
/* The message starts with "<app_name>: " if the condition is the first of /* The message starts with "<app_name>: " if the condition is the first of
its condition group, with "\t" if not. its condition group, with "\t" if not.
*/ */
if(descriptor == chf_context.condition_sp-1) if ( descriptor == chf_context.condition_sp - 1 ) {
{ tmp_p = scopy( tmp_p, chf_context.app_name, tmp_end );
tmp_p = scopy(tmp_p, chf_context.app_name, tmp_end); tmp_p = scopy( tmp_p, separator, tmp_end );
tmp_p = scopy(tmp_p, separator, tmp_end); }
}
else else
tmp_p = scopy(tmp_p, ChfText("\t"), tmp_end); tmp_p = scopy( tmp_p, ChfText( "\t" ), tmp_end );
#endif #endif
/* The message continues with the module name */ /* The message continues with the module name */
ChfSprintf(def_message, CHF_DEF_MID_MSG_FMT, ChfGetModuleId(descriptor)); ChfSprintf( def_message, CHF_DEF_MID_MSG_FMT, ChfGetModuleId( descriptor ) );
tmp_p = scopy(tmp_p, tmp_p = scopy( tmp_p, ChfGetMessage( CHF_MODULE_NAMES_SET, ChfGetModuleId( descriptor ), def_message ), tmp_end );
ChfGetMessage(CHF_MODULE_NAMES_SET, ChfGetModuleId(descriptor),
def_message), tmp_end);
/* Add also the extended information, if any */ /* Add also the extended information, if any */
if(ChfGetLineNumber(descriptor) != CHF_UNKNOWN_LINE_NUMBER) if ( ChfGetLineNumber( descriptor ) != CHF_UNKNOWN_LINE_NUMBER ) {
{ tmp_p = scopy( tmp_p, ChfText( " " ), tmp_end );
tmp_p = scopy(tmp_p, ChfText(" "), tmp_end);
ChfSprintf(def_message, CHF_EXTENDED_INFO_FMT, ChfSprintf( def_message, CHF_EXTENDED_INFO_FMT, ChfGetFileName( descriptor ), ChfGetLineNumber( descriptor ) );
ChfGetFileName(descriptor), ChfGetLineNumber(descriptor));
tmp_p = scopy(tmp_p, def_message, tmp_end); tmp_p = scopy( tmp_p, def_message, tmp_end );
} }
tmp_p = scopy(tmp_p, separator, tmp_end); tmp_p = scopy( tmp_p, separator, tmp_end );
#ifndef _WIN32 #ifndef _WIN32
/* Add the severity code of the message */ /* Add the severity code of the message */
tmp_p = scopy(tmp_p, tmp_p = scopy( tmp_p,
((severity = ChfGetSeverity(descriptor)) < CHF_SUCCESS || ( ( severity = ChfGetSeverity( descriptor ) ) < CHF_SUCCESS || severity > CHF_FATAL ) ? CHF_UNKNOWN_SEVERITY
severity > CHF_FATAL) ? CHF_UNKNOWN_SEVERITY : severity_name[severity], : severity_name[ severity ],
tmp_end); tmp_end );
tmp_p = scopy(tmp_p, separator, tmp_end); tmp_p = scopy( tmp_p, separator, tmp_end );
#endif #endif
/* The message ends with the partial message from the descriptor */ /* The message ends with the partial message from the descriptor */
tmp_p = scopy(tmp_p, ChfGetPartialMessage(descriptor), tmp_end); tmp_p = scopy( tmp_p, ChfGetPartialMessage( descriptor ), tmp_end );
(void)scopy(tmp_p, CHF_MESSAGE_TERMINATOR, tmp_end); ( void )scopy( tmp_p, CHF_MESSAGE_TERMINATOR, tmp_end );
return chf_context.message_buffer; return chf_context.message_buffer;
} }
/* .+ /* .+
.title : ChfInit .title : ChfInit
@ -467,29 +439,29 @@ ChfChar *ChfBuildMessage( /* Build a condition message */
function. function.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
if CHF has already been initialized before. if CHF has already been initialized before.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_PTHREAD NOTE: This function will call ChfAbort() with abort code CHF_ABORT_PTHREAD
if a pthread operation fails. if a pthread operation fails.
.call : .call :
cc = ChfInit(app_name, options, cc = ChfInit(app_name, options,
mrs_data, mrs_get, mrs_exit, mrs_data, mrs_get, mrs_exit,
condition_stack_size, handler_stack_size, condition_stack_size, handler_stack_size,
exit_code); exit_code);
.input : .input :
const char *app_name, Application's name const char *app_name, Application's name
const ChfOptions options, Options const ChfOptions options, Options
void *mrs_data, Message retrieval private data void *mrs_data, Message retrieval private data
ChfMrsGet mrs_get, 'GetMessage' function ChfMrsGet mrs_get, 'GetMessage' function
ChfMrsExit mrs_exit, 'Exit' function ChfMrsExit mrs_exit, 'Exit' function
const int condition_stack_size, Size of the condition stack const int condition_stack_size, Size of the condition stack
const int handler_stack_size, Size of the handler stack const int handler_stack_size, Size of the handler stack
const int exit_code, Abnormal exit code const int exit_code, Abnormal exit code
.output : .output :
int cc, condition code int cc, condition code
.status_codes : .status_codes :
CHF_F_MALLOC, FATAL, dynamic memory allocation failed CHF_F_MALLOC, FATAL, dynamic memory allocation failed
.notes : .notes :
1.1, 13-May-1996, creation 1.1, 13-May-1996, creation
1.6, 15-Jan-1997, update: 1.6, 15-Jan-1997, update:
@ -500,104 +472,98 @@ ChfChar *ChfBuildMessage( /* Build a condition message */
- added Win32 support; a malloc() call was not portable. - added Win32 support; a malloc() call was not portable.
.- */ .- */
int ChfInit( /* Generic initialization */ int ChfInit( /* Generic initialization */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
void *mrs_data, /* Message retrieval private data */ void* mrs_data, /* Message retrieval private data */
ChfMrsGet mrs_get, /* 'GetMessage' function */ ChfMrsGet mrs_get, /* 'GetMessage' function */
ChfMrsExit mrs_exit, /* 'Exit' function */ ChfMrsExit mrs_exit, /* 'Exit' function */
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
) )
{ {
int cc; int cc;
/* Check that CHF has not been initialized yet */ /* Check that CHF has not been initialized yet */
#ifndef _REENTRANT #ifndef _REENTRANT
if(_chf_context.state != CHF_UNKNOWN) ChfAbort(CHF_ABORT_DUP_INIT); if ( _chf_context.state != CHF_UNKNOWN )
ChfAbort( CHF_ABORT_DUP_INIT );
#else #else
/* Reentrant check; lock context_mutex first */ /* Reentrant check; lock context_mutex first */
if(pthread_mutex_lock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_lock( &context_mutex ) )
if(_chf_context.state != CHF_UNKNOWN) ChfAbort( CHF_ABORT_PTHREAD );
{ if ( _chf_context.state != CHF_UNKNOWN ) {
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_unlock( &context_mutex ) )
ChfAbort(CHF_ABORT_DUP_INIT); ChfAbort( CHF_ABORT_PTHREAD );
} ChfAbort( CHF_ABORT_DUP_INIT );
}
#endif #endif
#ifndef _REENTRANT #ifndef _REENTRANT
if((_chf_context.condition_stack = if ( ( _chf_context.condition_stack = ( ChfDescriptor* )malloc( ( size_t )( condition_stack_size + 1 ) * sizeof( ChfDescriptor ) ) ) ==
(ChfDescriptor *) CHF_NULL_DESCRIPTOR )
malloc((size_t)(condition_stack_size+1)*sizeof(ChfDescriptor))) == cc = CHF_F_MALLOC;
CHF_NULL_DESCRIPTOR)
cc = CHF_F_MALLOC;
else if((_chf_context.handler_stack = else if ( ( _chf_context.handler_stack = ( ChfHandlerDescriptor* )malloc(
(ChfHandlerDescriptor *) ( size_t )handler_stack_size * sizeof( ChfHandlerDescriptor ) ) ) == ( ChfHandlerDescriptor* )NULL ) {
malloc((size_t)handler_stack_size*sizeof(ChfHandlerDescriptor))) == free( _chf_context.condition_stack );
(ChfHandlerDescriptor *)NULL) cc = CHF_F_MALLOC;
{ }
free(_chf_context.condition_stack);
cc = CHF_F_MALLOC;
}
else if((_chf_context.message_buffer = else if ( ( _chf_context.message_buffer = ( ChfChar* )malloc( ( size_t )( CHF_MAX_MESSAGE_LENGTH ) * sizeof( ChfChar ) ) ) ==
(ChfChar *)malloc( ( ChfChar* )NULL ) {
(size_t)(CHF_MAX_MESSAGE_LENGTH) * sizeof(ChfChar))) == (ChfChar *)NULL) free( _chf_context.condition_stack );
{ free( _chf_context.handler_stack );
free(_chf_context.condition_stack); cc = CHF_F_MALLOC;
free(_chf_context.handler_stack); }
cc = CHF_F_MALLOC;
}
else else
#else #else
/* Reentrant init: condition_stack, handler_stack, message_buffer /* Reentrant init: condition_stack, handler_stack, message_buffer
are not needed in the master Chf context. are not needed in the master Chf context.
Init the Chf data key instead. Init the Chf data key instead.
*/
_chf_context.condition_stack = CHF_NULL_DESCRIPTOR;
_chf_context.handler_stack = (ChfHandlerDescriptor *)NULL;
_chf_context.message_buffer = (char *)NULL;
if(pthread_key_create(&data_key, DestroyContext))
ChfAbort(CHF_ABORT_PTHREAD);
#endif
{
/* Initialize the CHF context */
_chf_context.app_name = app_name;
_chf_context.options = options;
_chf_context.mrs_data = mrs_data;
_chf_context.mrs_get = mrs_get;
_chf_context.mrs_exit = mrs_exit;
_chf_context.condition_stack_size = condition_stack_size;
_chf_context.handler_stack_size = handler_stack_size;
_chf_context.exit_code = exit_code;
_chf_context.condition_base = _chf_context.condition_sp =
_chf_context.condition_stack;
_chf_context.handler_sp = _chf_context.handler_stack;
_chf_context.state = CHF_IDLE;
#ifndef _REENTRANT
/* Push the default handler; in the reentrant case, this will be
done once per thread, when the thread-specific context is primed.
*/ */
ChfPushHandler(DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER); _chf_context.condition_stack = CHF_NULL_DESCRIPTOR;
_chf_context.handler_stack = ( ChfHandlerDescriptor* )NULL;
_chf_context.message_buffer = ( char* )NULL;
if ( pthread_key_create( &data_key, DestroyContext ) )
ChfAbort( CHF_ABORT_PTHREAD );
#endif #endif
cc = CHF_S_OK; {
} /* Initialize the CHF context */
_chf_context.app_name = app_name;
_chf_context.options = options;
_chf_context.mrs_data = mrs_data;
_chf_context.mrs_get = mrs_get;
_chf_context.mrs_exit = mrs_exit;
_chf_context.condition_stack_size = condition_stack_size;
_chf_context.handler_stack_size = handler_stack_size;
_chf_context.exit_code = exit_code;
_chf_context.condition_base = _chf_context.condition_sp = _chf_context.condition_stack;
_chf_context.handler_sp = _chf_context.handler_stack;
_chf_context.state = CHF_IDLE;
#ifndef _REENTRANT
/* Push the default handler; in the reentrant case, this will be
done once per thread, when the thread-specific context is primed.
*/
ChfPushHandler( DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER );
#endif
cc = CHF_S_OK;
}
#ifdef _REENTRANT #ifdef _REENTRANT
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_unlock( &context_mutex ) )
ChfAbort( CHF_ABORT_PTHREAD );
#endif #endif
return cc; return cc;
} }
/* .+ /* .+
.title : ChfExit .title : ChfExit
@ -610,82 +576,82 @@ int ChfInit( /* Generic initialization */
the application using ChfAbort() with abort code CHF_ABORT_INIT. the application using ChfAbort() with abort code CHF_ABORT_INIT.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
if CHF hasn't been initialized. if CHF hasn't been initialized.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_PTHREAD NOTE: This function will call ChfAbort() with abort code CHF_ABORT_PTHREAD
if a pthread operation fails. if a pthread operation fails.
.call : .call :
ChfExit(); ChfExit();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
none none
.notes : .notes :
1.1, 24-May-1996, creation 1.1, 24-May-1996, creation
2.1, 19-May-2000, update: 2.1, 19-May-2000, update:
- added multithreading support - added multithreading support
.- */ .- */
void ChfExit( void ChfExit( void )
void
)
{ {
/* Check that CHF has been correctly initialized */ /* Check that CHF has been correctly initialized */
#ifndef _REENTRANT #ifndef _REENTRANT
if(_chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( _chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
#else #else
/* Reentrant check; lock context_mutex first */ /* Reentrant check; lock context_mutex first */
if(pthread_mutex_lock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_lock( &context_mutex ) )
if(_chf_context.state == CHF_UNKNOWN) ChfAbort( CHF_ABORT_PTHREAD );
{ if ( _chf_context.state == CHF_UNKNOWN ) {
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_unlock( &context_mutex ) )
ChfAbort(CHF_ABORT_INIT); ChfAbort( CHF_ABORT_PTHREAD );
} ChfAbort( CHF_ABORT_INIT );
}
#endif #endif
/* Destroy the context associated with this thread now; this is necessary /* Destroy the context associated with this thread now; this is necessary
to ensure that the context is actually destroyed when a single-threaded to ensure that the context is actually destroyed when a single-threaded
application links with the multithreaded version of Chf: in this case, application links with the multithreaded version of Chf: in this case,
pthread_exit() is called *after* ChfExit(), the Chf data key no longer pthread_exit() is called *after* ChfExit(), the Chf data key no longer
exists when pthread_exit() is called and the destructor registered exists when pthread_exit() is called and the destructor registered
with pthread_key_create() does not take place. with pthread_key_create() does not take place.
The data pointer associated with the Chf data key is set to NULL to The data pointer associated with the Chf data key is set to NULL to
avoid any subsequent reactivation of the destructor. avoid any subsequent reactivation of the destructor.
*/ */
#ifdef _REENTRANT #ifdef _REENTRANT
DestroyContext(&chf_context); DestroyContext( &chf_context );
if(pthread_setspecific(data_key, (void *)NULL)) if ( pthread_setspecific( data_key, ( void* )NULL ) ) {
{ ( void )pthread_mutex_unlock( &context_mutex );
(void)pthread_mutex_unlock(&context_mutex); ChfAbort( CHF_ABORT_PTHREAD );
ChfAbort(CHF_ABORT_PTHREAD); }
}
#endif #endif
/* Shut down the message retrieval subsystem first */ /* Shut down the message retrieval subsystem first */
_chf_context.mrs_exit(_chf_context.mrs_data); _chf_context.mrs_exit( _chf_context.mrs_data );
#ifndef _REENTRANT #ifndef _REENTRANT
/* Free the dynamic memory previously allocated */ /* Free the dynamic memory previously allocated */
free(_chf_context.message_buffer); free( _chf_context.message_buffer );
free(_chf_context.handler_stack); free( _chf_context.handler_stack );
free(_chf_context.condition_stack); free( _chf_context.condition_stack );
#else #else
/* Destroy the Chf data key */ /* Destroy the Chf data key */
if(pthread_key_delete(data_key)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_key_delete( data_key ) )
ChfAbort( CHF_ABORT_PTHREAD );
#endif #endif
/* Reset CHF state to prevent subsequent calls to ChfExit() itself */ /* Reset CHF state to prevent subsequent calls to ChfExit() itself */
_chf_context.state = CHF_UNKNOWN; _chf_context.state = CHF_UNKNOWN;
#ifdef _REENTRANT #ifdef _REENTRANT
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD); if ( pthread_mutex_unlock( &context_mutex ) )
ChfAbort( CHF_ABORT_PTHREAD );
#endif #endif
} }
/* .+ /* .+
.title : _ChfGetContext .title : _ChfGetContext
@ -701,80 +667,66 @@ void ChfExit(
successful call to ChfInit(). successful call to ChfInit().
.call : .call :
context = _ChfGetContext(void); context = _ChfGetContext(void);
.input : .input :
.output : .output :
ChfContext *context, per-thread Chf context ChfContext *context, per-thread Chf context
.status_codes : .status_codes :
none none
.notes : .notes :
2.1, 19-May-2000, creation 2.1, 19-May-2000, creation
.- */ .- */
ChfContext *_ChfGetContext( ChfContext* _ChfGetContext( void )
void
)
{ {
ChfContext *context; ChfContext* context;
#ifndef _REENTRANT #ifndef _REENTRANT
/* This function is doomed to fail if _REENTRANT is not defined */ /* This function is doomed to fail if _REENTRANT is not defined */
ChfAbort(CHF_ABORT_GET_CONTEXT); ChfAbort( CHF_ABORT_GET_CONTEXT );
return((ChfContext *)NULL); return ( ( ChfContext* )NULL );
#else #else
/* Get the thread-specific context pointer associated with the /* Get the thread-specific context pointer associated with the
CHF data key */ CHF data key */
if((context = (ChfContext *)pthread_getspecific(data_key)) if ( ( context = ( ChfContext* )pthread_getspecific( data_key ) ) == ( ChfContext* )NULL ) {
== (ChfContext *)NULL) /* No context pointer; prime a new one, cloning the master context */
{ if ( ( context = ( ChfContext* )malloc( sizeof( ChfContext ) ) ) == ( ChfContext* )NULL )
/* No context pointer; prime a new one, cloning the master context */ ChfAbort( CHF_ABORT_GET_CONTEXT );
if((context = (ChfContext *)malloc(sizeof(ChfContext)))
== (ChfContext *)NULL)
ChfAbort(CHF_ABORT_GET_CONTEXT);
memcpy(context, &_chf_context, sizeof(ChfContext)); memcpy( context, &_chf_context, sizeof( ChfContext ) );
/* Allocate per-thread stacks and message buffer */ /* Allocate per-thread stacks and message buffer */
if((context->condition_stack = if ( ( context->condition_stack = ( ChfDescriptor* )malloc( ( size_t )( context->condition_stack_size + 1 ) *
(ChfDescriptor *) sizeof( ChfDescriptor ) ) ) == CHF_NULL_DESCRIPTOR )
malloc((size_t)(context->condition_stack_size+1) ChfAbort( CHF_ABORT_GET_CONTEXT );
*sizeof(ChfDescriptor))) == CHF_NULL_DESCRIPTOR)
ChfAbort(CHF_ABORT_GET_CONTEXT);
if((context->handler_stack = if ( ( context->handler_stack = ( ChfHandlerDescriptor* )malloc(
(ChfHandlerDescriptor *) ( size_t )( context->handler_stack_size ) * sizeof( ChfHandlerDescriptor ) ) ) == ( ChfHandlerDescriptor* )NULL ) {
malloc((size_t)(context->handler_stack_size) free( context->condition_stack );
*sizeof(ChfHandlerDescriptor))) == (ChfHandlerDescriptor *)NULL) ChfAbort( CHF_ABORT_GET_CONTEXT );
{ }
free(context->condition_stack);
ChfAbort(CHF_ABORT_GET_CONTEXT); if ( ( context->message_buffer = ( char* )malloc( ( size_t )( CHF_MAX_MESSAGE_LENGTH ) ) ) == ( char* )NULL ) {
free( context->condition_stack );
free( context->handler_stack );
ChfAbort( CHF_ABORT_GET_CONTEXT );
}
/* Initialize stack pointers */
context->condition_base = context->condition_sp = context->condition_stack;
context->handler_sp = context->handler_stack;
/* Set the thread-specific context pointer; this must be done
before invoking any other function using the context,
including ChfPushHandler() below.
*/
if ( pthread_setspecific( data_key, context ) )
ChfAbort( CHF_ABORT_GET_CONTEXT );
/* Push the default handler */
ChfPushHandler( DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER );
} }
if((context->message_buffer = return context;
(char *)
malloc((size_t)(CHF_MAX_MESSAGE_LENGTH))) == (char *)NULL)
{
free(context->condition_stack);
free(context->handler_stack);
ChfAbort(CHF_ABORT_GET_CONTEXT);
}
/* Initialize stack pointers */
context->condition_base = context->condition_sp =
context->condition_stack;
context->handler_sp = context->handler_stack;
/* Set the thread-specific context pointer; this must be done
before invoking any other function using the context,
including ChfPushHandler() below.
*/
if(pthread_setspecific(data_key, context))
ChfAbort(CHF_ABORT_GET_CONTEXT);
/* Push the default handler */
ChfPushHandler(DefaultHandler, CHF_NULL_CONTEXT, CHF_NULL_POINTER);
}
return context;
#endif #endif
} }

View file

@ -35,24 +35,23 @@ static char rcs_id[] = "$Id: chf_msgc.c,v 2.2 2001/01/25 14:06:47 cibrario Exp $
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#ifndef _WIN32 #ifndef _WIN32
#include <locale.h> # include <locale.h>
#include <nl_types.h> # include <nl_types.h>
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Global and static variables Global and static variables
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -62,41 +61,28 @@ static char rcs_id[] = "$Id: chf_msgc.c,v 2.2 2001/01/25 14:06:47 cibrario Exp $
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifndef _WIN32 #ifndef _WIN32
typedef struct typedef struct {
{ nl_catd catalog; /* Message catalog descriptor */
nl_catd catalog; /* Message catalog descriptor */ } ChfMsgcatContext;
}
ChfMsgcatContext;
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Private functions Private functions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifndef _WIN32 #ifndef _WIN32
static const char *GetMessage( static const char* GetMessage( void* private_context, const int module_id, const int condition_code, const char* default_message )
void *private_context,
const int module_id,
const int condition_code,
const char *default_message
)
{ {
return(catgets(((ChfMsgcatContext *)private_context)->catalog, module_id, return ( catgets( ( ( ChfMsgcatContext* )private_context )->catalog, module_id, condition_code, default_message ) );
condition_code, default_message));
} }
static void ExitMessage( static void ExitMessage( void* private_context )
void *private_context
)
{ {
(void)catclose(((ChfMsgcatContext *)private_context)->catalog); ( void )catclose( ( ( ChfMsgcatContext* )private_context )->catalog );
free(private_context); free( private_context );
} }
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Public functions Public functions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -115,7 +101,7 @@ static void ExitMessage(
other CHF initialization routines before using any other CHF function. other CHF initialization routines before using any other CHF function.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
if CHF has already been initialized before. if CHF has already been initialized before.
WIN32: WIN32:
@ -123,79 +109,72 @@ static void ExitMessage(
always returns CHF_F_NOT_AVAILABLE always returns CHF_F_NOT_AVAILABLE
.call : .call :
cc = ChfMsgcatInit(app_name, options, cc = ChfMsgcatInit(app_name, options,
msgcat_name, msgcat_name,
condition_stack_size, handler_stack_size, condition_stack_size, handler_stack_size,
exit_code); exit_code);
.input : .input :
const char *app_name, Application's name const char *app_name, Application's name
const ChfOptions options, Options const ChfOptions options, Options
const char *msgcat_name, Name of the message catalog const char *msgcat_name, Name of the message catalog
const int condition_stack_size, Size of the condition stack const int condition_stack_size, Size of the condition stack
const int handler_stack_size, Size of the handler stack const int handler_stack_size, Size of the handler stack
const int exit_code, Abnormal exit code const int exit_code, Abnormal exit code
.output : .output :
int cc, condition code int cc, condition code
.status_codes : .status_codes :
CHF_F_SETLOCALE, setlocale() failed CHF_F_SETLOCALE, setlocale() failed
CHF_F_CATOPEN, catopen() failed CHF_F_CATOPEN, catopen() failed
CHF_F_MALLOC, FATAL, memory allocation failed CHF_F_MALLOC, FATAL, memory allocation failed
CHF_F_NOT_AVAILABLE, FATAL, function not available CHF_F_NOT_AVAILABLE, FATAL, function not available
.notes : .notes :
1.1, 17-May-1996, creation 1.1, 17-May-1996, creation
2.2, 22-Jan-2001, update: 2.2, 22-Jan-2001, update:
- added Win32 support - added Win32 support
.- */ .- */
int ChfMsgcatInit( /* Initialization with msgcat subsystem */ int ChfMsgcatInit( /* Initialization with msgcat subsystem */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
const ChfChar *msgcat_name, /* Name of the message catalog */ const ChfChar* msgcat_name, /* Name of the message catalog */
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
) )
{ {
#ifdef _WIN32 #ifdef _WIN32
/* This function always fails in _WIN32, because message catalogs /* This function always fails in _WIN32, because message catalogs
are not supported. are not supported.
*/ */
return CHF_F_NOT_AVAILABLE; return CHF_F_NOT_AVAILABLE;
#else #else
ChfMsgcatContext *private_context; ChfMsgcatContext* private_context;
int cc; int cc;
if((private_context = if ( ( private_context = ( ChfMsgcatContext* )malloc( sizeof( ChfMsgcatContext ) ) ) == ( ChfMsgcatContext* )NULL )
(ChfMsgcatContext *)malloc(sizeof(ChfMsgcatContext))) == cc = CHF_F_MALLOC;
(ChfMsgcatContext *)NULL)
cc = CHF_F_MALLOC;
else if(setlocale(LC_ALL, "") == (char *)NULL) else if ( setlocale( LC_ALL, "" ) == ( char* )NULL ) {
{ free( private_context );
free(private_context); cc = CHF_F_SETLOCALE;
cc = CHF_F_SETLOCALE; }
}
else if((private_context->catalog = catopen(msgcat_name, 0)) == else if ( ( private_context->catalog = catopen( msgcat_name, 0 ) ) == ( nl_catd )( -1 ) ) {
(nl_catd)(-1)) free( private_context );
{ cc = CHF_F_CATOPEN;
free(private_context); }
cc = CHF_F_CATOPEN;
}
else if((cc = ChfInit(app_name, options, (void *)private_context, else if ( ( cc = ChfInit( app_name, options, ( void* )private_context, GetMessage, ExitMessage, condition_stack_size,
GetMessage, ExitMessage, condition_stack_size, handler_stack_size, handler_stack_size, exit_code ) ) != CHF_S_OK ) {
exit_code)) != CHF_S_OK) ( void )catclose( private_context->catalog );
{ free( private_context );
(void)catclose(private_context->catalog); }
free(private_context);
}
else else
cc = CHF_S_OK; cc = CHF_S_OK;
return cc; return cc;
#endif #endif
} }

View file

@ -44,19 +44,18 @@ static char rcs_id[] = "$Id: chf_sig.c,v 2.2 2001/01/25 14:07:42 cibrario Exp $"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* .+ /* .+
.title : ChfSignal .title : ChfSignal
@ -68,26 +67,26 @@ static char rcs_id[] = "$Id: chf_sig.c,v 2.2 2001/01/25 14:07:42 cibrario Exp $"
handlers. handlers.
NOTE: This function uses the CHF function 'ChfAbort()' to NOTE: This function uses the CHF function 'ChfAbort()' to
abort the application if either abort the application if either
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT) - CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
- the last handler on the handler stack has returned an invalid action - the last handler on the handler stack has returned an invalid action
code (abort code CHF_ABORT_INVALID_ACTION) code (abort code CHF_ABORT_INVALID_ACTION)
- one of the handlers has requested the CHF_UNWIND action while - one of the handlers has requested the CHF_UNWIND action while
CHF was already unwinding (abort code CHF_ABORT_ALREADY_UNWINDING) CHF was already unwinding (abort code CHF_ABORT_ALREADY_UNWINDING)
- a CHF_FATAL condition was signalled while CHF was unwinding - a CHF_FATAL condition was signalled while CHF was unwinding
(abort code CHF_ABORT_FATAL_UNWINDING) (abort code CHF_ABORT_FATAL_UNWINDING)
- all the handlers refused to handle a condition (abort code - all the handlers refused to handle a condition (abort code
CHF_ABORT_IMPROPERLY_HANDLED) CHF_ABORT_IMPROPERLY_HANDLED)
.call : .call :
ChfSignal(); ChfSignal();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
(*) CHF_F_COND_STACK_FULL, the condition stack is full (*) CHF_F_COND_STACK_FULL, the condition stack is full
(*) CHF_F_INVALID_ACTION, invalid handler action (%d) (*) CHF_F_INVALID_ACTION, invalid handler action (%d)
.notes : .notes :
1.1, 10-May-1996, creation 1.1, 10-May-1996, creation
1.6, 15-Jan-1997, update & bug fix: 1.6, 15-Jan-1997, update & bug fix:
@ -99,269 +98,246 @@ static char rcs_id[] = "$Id: chf_sig.c,v 2.2 2001/01/25 14:07:42 cibrario Exp $"
- added support for structured condition handling - added support for structured condition handling
.- */ .- */
void ChfSignal( void ChfSignal( void )
void
)
{ {
ChfState saved_state; ChfState saved_state;
ChfDescriptor *saved_condition_base; ChfDescriptor* saved_condition_base;
ChfDescriptor *current_condition; ChfDescriptor* current_condition;
ChfHandlerDescriptor *saved_handler_sp; ChfHandlerDescriptor* saved_handler_sp;
ChfHandlerDescriptor *handler_up; ChfHandlerDescriptor* handler_up;
ChfHandlerDescriptor *unwind_handler; ChfHandlerDescriptor* unwind_handler;
ChfAction handler_result; ChfAction handler_result;
/* Check that CHF has been correctly initialized and save the current CHF /* Check that CHF has been correctly initialized and save the current CHF
state. If CHF was CHF_IDLE change state to CHF_SIGNALING, else if CHF was state. If CHF was CHF_IDLE change state to CHF_SIGNALING, else if CHF was
CHF_UNWINDING change to CHF_SIGNAL_UNWINDING, otherwise remain in the CHF_UNWINDING change to CHF_SIGNAL_UNWINDING, otherwise remain in the
previous state (that must be CHF_SIGNALING) previous state (that must be CHF_SIGNALING)
*/
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
saved_state = chf_context.state;
if(chf_context.state == CHF_IDLE)
chf_context.state = CHF_SIGNALING;
else if(chf_context.state == CHF_UNWINDING)
chf_context.state = CHF_SIGNAL_UNWINDING;
if(chf_context.condition_sp > chf_context.condition_base)
{
/* Save the base of the current condition group and then update it in
order to allow further generation of conditions inside the condition
handlers that will be called soon.
*/ */
current_condition = chf_context.condition_sp-1; if ( chf_context.state == CHF_UNKNOWN )
saved_condition_base = chf_context.condition_base; ChfAbort( CHF_ABORT_INIT );
chf_context.condition_base = chf_context.condition_sp; saved_state = chf_context.state;
/* Save the current condition handler pointer */ if ( chf_context.state == CHF_IDLE )
saved_handler_sp = chf_context.handler_sp; chf_context.state = CHF_SIGNALING;
else if ( chf_context.state == CHF_UNWINDING )
chf_context.state = CHF_SIGNAL_UNWINDING;
/* Call the condition handlers; the loop will exit either: if ( chf_context.condition_sp > chf_context.condition_base ) {
- when the handler stack is empty, or /* Save the base of the current condition group and then update it in
- when the current handler returns either CHF_CONTINUE or CHF_UNWIND order to allow further generation of conditions inside the condition
*/ handlers that will be called soon.
handler_result = CHF_RESIGNAL; */
while(handler_result == CHF_RESIGNAL && current_condition = chf_context.condition_sp - 1;
chf_context.handler_sp > chf_context.handler_stack) saved_condition_base = chf_context.condition_base;
{ chf_context.condition_base = chf_context.condition_sp;
chf_context.handler_sp--;
/* The current condition handler, described by chf_context.handler_sp, /* Save the current condition handler pointer */
can recursively invoke ChfGenerate() and ChfSignal(). saved_handler_sp = chf_context.handler_sp;
ChfGenerate() will store the new condition group starting from /* Call the condition handlers; the loop will exit either:
chf_context.condition_sp, that points to the first free slot - when the handler stack is empty, or
of the condition stack. During the first generation, since - when the current handler returns either CHF_CONTINUE or CHF_UNWIND
chf_context.condition_sp == chf_context.condition_base, the */
link pointer of the condition will be NULL and, therefore, handler_result = CHF_RESIGNAL;
the condition will be the first of a new condition group. while ( handler_result == CHF_RESIGNAL && chf_context.handler_sp > chf_context.handler_stack ) {
chf_context.handler_sp--;
ChfSignal() will signal the condition group described by the /* The current condition handler, described by chf_context.handler_sp,
stack block from chf_context.condition_base to
chf_context.condition_sp-1, if it contains at least one condition;
it will call the handlers starting from chf_context.handler_sp-1,
that describes the handler immediately preceding the current handler.
*/
handler_result = chf_context.handler_sp->handler(
current_condition, chf_context.state,
chf_context.handler_sp->handler_context);
/* When the CHF state is CHF_SIGNALING, any condition group generated
but not yet signalled when the current handler exits must be merged
with the condition group currently being signalled, in order to allow
the condition handlers to add their own conditions to the condition
group. If the severity of the previous condition group was CHF_FATAL,
the severity of the new group is forced to CHF_FATAL, too.
When the CHF state is CHF_UNWINDING, the condition group for
which the UNWIND has been requested is 'frozen', no further
modifications are allowed on it, and the condition group is simply
discarded.
*/
if(chf_context.condition_sp > chf_context.condition_base)
{
if(chf_context.state == CHF_SIGNALING)
{
/* Force the new severity to CHF_FATAL if necessary */
if(ChfGetSeverity(current_condition) == CHF_FATAL)
ChfGetSeverity(chf_context.condition_sp-1) = CHF_FATAL;
/* Link together the condition groups */
chf_context.condition_base->next = current_condition;
current_condition = chf_context.condition_sp-1;
chf_context.condition_base = chf_context.condition_sp;
}
else
chf_context.condition_sp = chf_context.condition_base;
}
/* The action CHF_CONTINUE is not allowed if the current condition
severity is CHF_FATAL; it's automatically changed to CHF_RESIGNAL
*/
if(handler_result == CHF_CONTINUE &&
ChfGetSeverity(current_condition) == CHF_FATAL)
handler_result = CHF_RESIGNAL;
}
/* Perform the action requested by the last condition handler invoked */
switch(handler_result)
{
case CHF_CONTINUE:
{
/* Restore the handler stack pointer; the next ChfSignal() invoked
from our same nesting level will invoke our same handler chain
again.
*/
chf_context.handler_sp = saved_handler_sp;
/* Discard the current condition group */
chf_context.condition_base = chf_context.condition_sp =
saved_condition_base;
/* Restore che saved CHF state */
chf_context.state = saved_state;
/* Continue from the instruction following the ChfSignal() */
break;
}
case CHF_UNWIND:
case CHF_UNWIND_KEEP:
{
/* Unwind the execution stack. Check that another unwind isn't
already in progress
*/
if(chf_context.state == CHF_UNWINDING)
ChfAbort(CHF_ABORT_ALREADY_UNWINDING);
else
{
/* Change CHF state */
chf_context.state = CHF_UNWINDING;
/* chf_context.handler_sp points to the condition handler that
has requested the unwind; call all the handlers again, starting
from saved_handler_sp (top of the handler stack) up to and
including chf_context.handler_sp.
*/
handler_up = saved_handler_sp;
while(handler_up > chf_context.handler_sp)
{
ChfAction unw_handler_result;
handler_up--;
/* The current condition handler, described by handler_up
can recursively invoke ChfGenerate() and ChfSignal(). can recursively invoke ChfGenerate() and ChfSignal().
ChfGenerate() will store the new condition group starting from ChfGenerate() will store the new condition group starting from
chf_context.condition_sp, that points to the first free slot chf_context.condition_sp, that points to the first free slot
of the condition stack. During the first generation, since of the condition stack. During the first generation, since
chf_context.condition_sp == chf_context.condition_base, the chf_context.condition_sp == chf_context.condition_base, the
link pointer of the condition will be NULL and, therefore, link pointer of the condition will be NULL and, therefore,
the condition will be the first of a new condition group. the condition will be the first of a new condition group.
ChfSignal() will generate the condition group described by the ChfSignal() will signal the condition group described by the
stack block from chf_context.condition_base to stack block from chf_context.condition_base to
chf_context.condition_sp-1, if it contains at least one chf_context.condition_sp-1, if it contains at least one condition;
condition; it will call the handlers starting from it will call the handlers starting from chf_context.handler_sp-1,
chf_context.handler_sp-1, that describes the handler that describes the handler immediately preceding the current handler.
immediately preceding the handler that has requested the unwind.
Further unwind requests are not allowed, and will trigger
the condition CHF_F_UNWINDING
*/ */
unw_handler_result = handler_up->handler( handler_result =
current_condition, chf_context.state, chf_context.handler_sp->handler( current_condition, chf_context.state, chf_context.handler_sp->handler_context );
handler_up->handler_context);
/* When the CHF state is CHF_UNWINDING, any condition group /* When the CHF state is CHF_SIGNALING, any condition group generated
generated but not yet signalled when the current handler but not yet signalled when the current handler exits must be merged
returns must be discarded with the condition group currently being signalled, in order to allow
*/ the condition handlers to add their own conditions to the condition
chf_context.condition_sp = chf_context.condition_base; group. If the severity of the previous condition group was CHF_FATAL,
} the severity of the new group is forced to CHF_FATAL, too.
/* Restore the handler stack pointer, discarding the unwinded When the CHF state is CHF_UNWINDING, the condition group for
condition handlers. chf_context.handler_sp points to the which the UNWIND has been requested is 'frozen', no further
handler that requested the unwind; that handler has been modifications are allowed on it, and the condition group is simply
unwinded and its location is now the first free slot in the discarded.
condition handler stack. */
*/ if ( chf_context.condition_sp > chf_context.condition_base ) {
unwind_handler = chf_context.handler_sp; if ( chf_context.state == CHF_SIGNALING ) {
/* Force the new severity to CHF_FATAL if necessary */
if ( ChfGetSeverity( current_condition ) == CHF_FATAL )
ChfGetSeverity( chf_context.condition_sp - 1 ) = CHF_FATAL;
if(handler_result == CHF_UNWIND) /* Link together the condition groups */
{ chf_context.condition_base->next = current_condition;
/* Normal unwind: current_condition = chf_context.condition_sp - 1;
restore the condition stack pointers, discarding all condition chf_context.condition_base = chf_context.condition_sp;
groups. }
*/
chf_context.condition_base = chf_context.condition_sp =
chf_context.condition_stack;
}
else
{
/* Special unwind for structured condition handling:
restore the condition_base pointer only, to keep the
topmost condition group on the condition stack. This way,
the condition group remains accessible after the unwind.
*/
chf_context.condition_base = saved_condition_base;
}
/* Change the CHF state to CHF_IDLE, and execute longjmp(). else
If the handler hasn't a valid unwind_context associated with it, chf_context.condition_sp = chf_context.condition_base;
simply abort the application. }
*/
chf_context.state = CHF_IDLE;
if(unwind_handler->unwind_context == CHF_NULL_CONTEXT) /* The action CHF_CONTINUE is not allowed if the current condition
ChfAbort(CHF_ABORT_SILENT); severity is CHF_FATAL; it's automatically changed to CHF_RESIGNAL
else */
ChfSiglongjmp(unwind_handler->unwind_context, 1); if ( handler_result == CHF_CONTINUE && ChfGetSeverity( current_condition ) == CHF_FATAL )
} handler_result = CHF_RESIGNAL;
}
break; /* Perform the action requested by the last condition handler invoked */
} switch ( handler_result ) {
case CHF_CONTINUE:
{
/* Restore the handler stack pointer; the next ChfSignal() invoked
from our same nesting level will invoke our same handler chain
again.
*/
chf_context.handler_sp = saved_handler_sp;
case CHF_RESIGNAL: /* Discard the current condition group */
{ chf_context.condition_base = chf_context.condition_sp = saved_condition_base;
ChfAbort(
(chf_context.state == CHF_SIGNALING) ?
CHF_ABORT_IMPROPERLY_HANDLED : CHF_ABORT_FATAL_UNWINDING);
break; /* Restore che saved CHF state */
} chf_context.state = saved_state;
default: /* Continue from the instruction following the ChfSignal() */
{ break;
/* Invalid handler action detected; generate and immediately signal a }
condition if the broken handler isn't the last handler on the stack,
otherwise call ChfAbort()
*/
if(chf_context.handler_sp > chf_context.handler_stack)
{
ChfCondition CHF_F_INVALID_ACTION, CHF_FATAL, handler_result
ChfEnd;
ChfSignal(); case CHF_UNWIND:
} case CHF_UNWIND_KEEP:
{
/* Unwind the execution stack. Check that another unwind isn't
already in progress
*/
if ( chf_context.state == CHF_UNWINDING )
ChfAbort( CHF_ABORT_ALREADY_UNWINDING );
else else {
ChfAbort(CHF_ABORT_INVALID_ACTION); /* Change CHF state */
chf_context.state = CHF_UNWINDING;
break; /* chf_context.handler_sp points to the condition handler that
} has requested the unwind; call all the handlers again, starting
from saved_handler_sp (top of the handler stack) up to and
including chf_context.handler_sp.
*/
handler_up = saved_handler_sp;
while ( handler_up > chf_context.handler_sp ) {
ChfAction unw_handler_result;
handler_up--;
/* The current condition handler, described by handler_up
can recursively invoke ChfGenerate() and ChfSignal().
ChfGenerate() will store the new condition group starting from
chf_context.condition_sp, that points to the first free slot
of the condition stack. During the first generation, since
chf_context.condition_sp == chf_context.condition_base, the
link pointer of the condition will be NULL and, therefore,
the condition will be the first of a new condition group.
ChfSignal() will generate the condition group described by the
stack block from chf_context.condition_base to
chf_context.condition_sp-1, if it contains at least one
condition; it will call the handlers starting from
chf_context.handler_sp-1, that describes the handler
immediately preceding the handler that has requested the unwind.
Further unwind requests are not allowed, and will trigger
the condition CHF_F_UNWINDING
*/
unw_handler_result = handler_up->handler( current_condition, chf_context.state, handler_up->handler_context );
/* When the CHF state is CHF_UNWINDING, any condition group
generated but not yet signalled when the current handler
returns must be discarded
*/
chf_context.condition_sp = chf_context.condition_base;
}
/* Restore the handler stack pointer, discarding the unwinded
condition handlers. chf_context.handler_sp points to the
handler that requested the unwind; that handler has been
unwinded and its location is now the first free slot in the
condition handler stack.
*/
unwind_handler = chf_context.handler_sp;
if ( handler_result == CHF_UNWIND ) {
/* Normal unwind:
restore the condition stack pointers, discarding all condition
groups.
*/
chf_context.condition_base = chf_context.condition_sp = chf_context.condition_stack;
} else {
/* Special unwind for structured condition handling:
restore the condition_base pointer only, to keep the
topmost condition group on the condition stack. This way,
the condition group remains accessible after the unwind.
*/
chf_context.condition_base = saved_condition_base;
}
/* Change the CHF state to CHF_IDLE, and execute longjmp().
If the handler hasn't a valid unwind_context associated with it,
simply abort the application.
*/
chf_context.state = CHF_IDLE;
if ( unwind_handler->unwind_context == CHF_NULL_CONTEXT )
ChfAbort( CHF_ABORT_SILENT );
else
ChfSiglongjmp( unwind_handler->unwind_context, 1 );
}
break;
}
case CHF_RESIGNAL:
{
ChfAbort( ( chf_context.state == CHF_SIGNALING ) ? CHF_ABORT_IMPROPERLY_HANDLED : CHF_ABORT_FATAL_UNWINDING );
break;
}
default:
{
/* Invalid handler action detected; generate and immediately signal a
condition if the broken handler isn't the last handler on the stack,
otherwise call ChfAbort()
*/
if ( chf_context.handler_sp > chf_context.handler_stack ) {
ChfCondition CHF_F_INVALID_ACTION, CHF_FATAL, handler_result ChfEnd;
ChfSignal();
}
else
ChfAbort( CHF_ABORT_INVALID_ACTION );
break;
}
}
} }
}
/* Restore the old CHF state */ /* Restore the old CHF state */
chf_context.state = saved_state; chf_context.state = saved_state;
} }
/* .+ /* .+
.title : ChfDiscard .title : ChfDiscard
@ -373,30 +349,30 @@ void ChfSignal(
the condition stack is empty. the condition stack is empty.
NOTE: This function uses the CHF function 'ChfAbort()' to NOTE: This function uses the CHF function 'ChfAbort()' to
abort the application if either abort the application if either
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT) - CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
.call : .call :
ChfDiscard(); ChfDiscard();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
none none
.notes : .notes :
1.1, 17-May-1996, creation 1.1, 17-May-1996, creation
.- */ .- */
void ChfDiscard( /* Discard the current conditions */ void ChfDiscard( /* Discard the current conditions */
void void )
)
{ {
/* Check that CHF has been correctly initialized */ /* Check that CHF has been correctly initialized */
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
/* Reset the current condition stack pointer to the current condition /* Reset the current condition stack pointer to the current condition
stack base pointer stack base pointer
*/ */
chf_context.condition_sp = chf_context.condition_base; chf_context.condition_sp = chf_context.condition_base;
} }

View file

@ -31,20 +31,19 @@ static char rcs_id[] = "$Id: chf_st.c,v 2.2 2001/01/25 14:08:45 cibrario Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Global and static variables Global and static variables
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -53,13 +52,10 @@ static char rcs_id[] = "$Id: chf_st.c,v 2.2 2001/01/25 14:08:45 cibrario Exp $";
Private type definitions Private type definitions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
typedef struct typedef struct {
{ const ChfTable* table;
const ChfTable *table; size_t size;
size_t size; } ChfStaticContext;
}
ChfStaticContext;
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Private functions Private functions
@ -69,88 +65,67 @@ typedef struct
/* Win32 does not have bsearch(); /* Win32 does not have bsearch();
provide a simple one from glibc here. provide a simple one from glibc here.
*/ */
static void *bsearch( static void* bsearch( const void* key, const void* base, size_t nmemb, size_t size, int ( *compar )( const void*, const void* ) )
const void *key,
const void *base,
size_t nmemb,
size_t size,
int (*compar)(const void *, const void *)
)
{ {
size_t l, u, idx; size_t l, u, idx;
const void *p; const void* p;
int comparison; int comparison;
l = 0; l = 0;
u = nmemb; u = nmemb;
while (l < u) while ( l < u ) {
{ idx = ( l + u ) / 2;
idx = (l + u) / 2; p = ( void* )( ( ( const char* )base ) + ( idx * size ) );
p = (void *) (((const char *) base) + (idx * size)); comparison = ( *compar )( key, p );
comparison = (*compar) (key, p); if ( comparison < 0 )
if (comparison < 0) u = idx;
u = idx; else if ( comparison > 0 )
else if (comparison > 0) l = idx + 1;
l = idx + 1; else
else return ( void* )p;
return (void *) p;
} }
return NULL; return NULL;
} }
#endif #endif
#define GT 1 #define GT 1
#define LT -1 #define LT -1
#define EQ 0 #define EQ 0
static int Search( static int Search( const void* l, const void* r )
const void *l,
const void *r
)
{ {
if(((ChfTable *)l)->module > ((ChfTable *)r)->module) if ( ( ( ChfTable* )l )->module > ( ( ChfTable* )r )->module )
return(GT); return ( GT );
else if(((ChfTable *)l)->module < ((ChfTable *)r)->module) else if ( ( ( ChfTable* )l )->module < ( ( ChfTable* )r )->module )
return(LT); return ( LT );
else if(((ChfTable *)l)->code > ((ChfTable *)r)->code) else if ( ( ( ChfTable* )l )->code > ( ( ChfTable* )r )->code )
return(GT); return ( GT );
else if(((ChfTable *)l)->code < ((ChfTable *)r)->code) else if ( ( ( ChfTable* )l )->code < ( ( ChfTable* )r )->code )
return(LT); return ( LT );
return(EQ); return ( EQ );
} }
static const ChfChar *StGetMessage( static const ChfChar* StGetMessage( void* private_context, const int module_id, const int condition_code, const ChfChar* default_message )
void *private_context,
const int module_id,
const int condition_code,
const ChfChar *default_message
)
{ {
ChfTable key; ChfTable key;
ChfTable *res; ChfTable* res;
key.module = module_id; key.module = module_id;
key.code = condition_code; key.code = condition_code;
if((res = bsearch(&key, ((ChfStaticContext *)private_context)->table, if ( ( res = bsearch( &key, ( ( ChfStaticContext* )private_context )->table, ( ( ChfStaticContext* )private_context )->size,
((ChfStaticContext *)private_context)->size, sizeof(ChfTable), Search)) == sizeof( ChfTable ), Search ) ) == ( void* )NULL )
(void *)NULL) return ( default_message );
return(default_message);
return(((ChfTable *)res)->msg_template); return ( ( ( ChfTable* )res )->msg_template );
}
static void ExitMessage(
void *private_context
)
{
} }
static void ExitMessage( void* private_context ) {}
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Public functions Public functions
@ -170,58 +145,54 @@ static void ExitMessage(
other CHF initialization routines before using any other CHF function. other CHF initialization routines before using any other CHF function.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
if CHF has already been initialized before. if CHF has already been initialized before.
.call : .call :
cc = ChfStaticInit(app_name, options, cc = ChfStaticInit(app_name, options,
table, table_size, table, table_size,
condition_stack_size, handler_stack_size, condition_stack_size, handler_stack_size,
exit_code); exit_code);
.input : .input :
const char *app_name, Application's name const char *app_name, Application's name
const ChfOptions options, Options const ChfOptions options, Options
const ChfTable *table, pointer to the static message table const ChfTable *table, pointer to the static message table
const size_t table_size, size of the table (# of entries) const size_t table_size, size of the table (# of entries)
const int condition_stack_size, Size of the condition stack const int condition_stack_size, Size of the condition stack
const int handler_stack_size, Size of the handler stack const int handler_stack_size, Size of the handler stack
const int exit_code, Abnormal exit code const int exit_code, Abnormal exit code
.output : .output :
int cc, condition code int cc, condition code
.status_codes : .status_codes :
CHF_F_MALLOC, FATAL, memory allocation failed CHF_F_MALLOC, FATAL, memory allocation failed
.notes : .notes :
1.1, 27-May-1996, creation 1.1, 27-May-1996, creation
.- */ .- */
int ChfStaticInit( /* Initialization with static message tables */ int ChfStaticInit( /* Initialization with static message tables */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
const ChfTable *table, /* Static message table */ const ChfTable* table, /* Static message table */
const size_t table_size, /* Size of the message table */ const size_t table_size, /* Size of the message table */
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
) )
{ {
ChfStaticContext *private_context; ChfStaticContext* private_context;
int cc; int cc;
if((private_context = if ( ( private_context = ( ChfStaticContext* )malloc( sizeof( ChfStaticContext ) ) ) == ( ChfStaticContext* )NULL )
(ChfStaticContext *)malloc(sizeof(ChfStaticContext))) == cc = CHF_F_MALLOC;
(ChfStaticContext *)NULL)
cc = CHF_F_MALLOC;
else if((cc = ChfInit(app_name, options, (void *)private_context, else if ( ( cc = ChfInit( app_name, options, ( void* )private_context, StGetMessage, ExitMessage, condition_stack_size,
StGetMessage, ExitMessage, condition_stack_size, handler_stack_size, handler_stack_size, exit_code ) ) != CHF_S_OK )
exit_code)) != CHF_S_OK) free( private_context );
free(private_context);
else else {
{ private_context->table = table;
private_context->table = table; private_context->size = table_size;
private_context->size = table_size; cc = CHF_S_OK;
cc = CHF_S_OK; }
}
return cc; return cc;
} }

View file

@ -35,20 +35,19 @@ static char rcs_id[] = "$Id: chf_top.c,v 2.2 2001/01/25 14:09:21 cibrario Exp $"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Public functions Public functions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -65,26 +64,26 @@ static char rcs_id[] = "$Id: chf_top.c,v 2.2 2001/01/25 14:09:21 cibrario Exp $"
NOTE: During condition signalling, CHF creates a new, empty, condition group NOTE: During condition signalling, CHF creates a new, empty, condition group
immediately before starting the invocation sequence of the condition immediately before starting the invocation sequence of the condition
handlers, as described in the documentation. Therefore handlers, as described in the documentation. Therefore
ChfGetTopCondition(), if called from a condition handler, will return ChfGetTopCondition(), if called from a condition handler, will return
a pointer to the top condition generated during the handling ONLY, and a pointer to the top condition generated during the handling ONLY, and
NOT to the top condition of the condition group being signalled. The NOT to the top condition of the condition group being signalled. The
latter pointer is directly available, as an argument, to the condition latter pointer is directly available, as an argument, to the condition
handlers. handlers.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
if CHF hasn't been correctly initialized. if CHF hasn't been correctly initialized.
NOTE: The returned pointer is no longer valid when any other CHF function NOTE: The returned pointer is no longer valid when any other CHF function
is called after ChfGetTopCondition(). is called after ChfGetTopCondition().
.call : .call :
d = ChfGetTopCondition(); d = ChfGetTopCondition();
.input : .input :
void void
.output : .output :
const ChfDescriptor *d, condition descriptor const ChfDescriptor *d, condition descriptor
.status_codes : .status_codes :
.notes : .notes :
@ -93,23 +92,22 @@ static char rcs_id[] = "$Id: chf_top.c,v 2.2 2001/01/25 14:09:21 cibrario Exp $"
- condition stack referenced incorrectly - condition stack referenced incorrectly
.- */ .- */
const ChfDescriptor *ChfGetTopCondition( /* Retrieve top condition */ const ChfDescriptor* ChfGetTopCondition( /* Retrieve top condition */
void void )
)
{ {
ChfDescriptor *d; ChfDescriptor* d;
/* Check that CHF has been correctly initialized */ /* Check that CHF has been correctly initialized */
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT); if ( chf_context.state == CHF_UNKNOWN )
ChfAbort( CHF_ABORT_INIT );
if((d = chf_context.condition_sp) == chf_context.condition_base) if ( ( d = chf_context.condition_sp ) == chf_context.condition_base ) {
{ ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd; ChfSignal();
ChfSignal(); }
}
/* The top element of the condition group is the element immediately /* The top element of the condition group is the element immediately
below the stack pointer. below the stack pointer.
*/ */
return d-1; return d - 1;
} }

View file

@ -28,20 +28,19 @@ static char rcs_id[] = "$Id: chf_win32.c,v 2.2 2001/01/25 14:11:58 cibrario Exp
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <errno.h> # include <errno.h>
#endif #endif
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> # include <windows.h>
#include <tchar.h> # include <tchar.h>
#endif #endif
#include "Chf.h" #include "Chf.h"
#include "ChfPriv.h" #include "ChfPriv.h"
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Global and static variables Global and static variables
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -51,46 +50,30 @@ static char rcs_id[] = "$Id: chf_win32.c,v 2.2 2001/01/25 14:11:58 cibrario Exp
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifdef _WIN32 #ifdef _WIN32
typedef struct typedef struct {
{ HINSTANCE instance; /* App. instance handle */
HINSTANCE instance; /* App. instance handle */ ChfChar buffer[ CHF_MAX_MESSAGE_LENGTH ]; /* Temporary buffer */
ChfChar buffer[CHF_MAX_MESSAGE_LENGTH]; /* Temporary buffer */ } ChfWin32Context;
}
ChfWin32Context;
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Private functions Private functions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
#ifdef _WIN32 #ifdef _WIN32
static const ChfChar *Win32GetMessage( static const ChfChar* Win32GetMessage( void* private_context, const int module_id, const int condition_code,
void *private_context, const ChfChar* default_message )
const int module_id,
const int condition_code,
const ChfChar *default_message
)
{ {
if(!LoadString( if ( !LoadString( ( ( ChfWin32Context* )private_context )->instance, module_id * 1000 + condition_code,
((ChfWin32Context *)private_context)->instance, ( ( ChfWin32Context* )private_context )->buffer, CHF_MAX_MESSAGE_LENGTH - 1 ) )
module_id*1000 + condition_code, return default_message;
((ChfWin32Context *)private_context)->buffer,
CHF_MAX_MESSAGE_LENGTH-1))
return default_message;
return ((ChfWin32Context *)private_context)->buffer; return ( ( ChfWin32Context* )private_context )->buffer;
} }
static void ExitMessage( static void ExitMessage( void* private_context ) { free( private_context ); }
void *private_context
)
{
free(private_context);
}
#endif #endif
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
Public functions Public functions
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -109,7 +92,7 @@ static void ExitMessage(
other CHF initialization routines before using any other CHF function. other CHF initialization routines before using any other CHF function.
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
if CHF has already been initialized before. if CHF has already been initialized before.
WIN32: WIN32:
@ -124,68 +107,63 @@ static void ExitMessage(
0 <= module_id <= 64 0 <= module_id <= 64
.call : .call :
cc = ChfWin32Init(app_name, options, cc = ChfWin32Init(app_name, options,
msgcat_name, msgcat_name,
condition_stack_size, handler_stack_size, condition_stack_size, handler_stack_size,
exit_code); exit_code);
.input : .input :
const ChfChar *app_name, Application's name const ChfChar *app_name, Application's name
const ChfOptions options, Options const ChfOptions options, Options
HINSTANCE instance, App. instance handle HINSTANCE instance, App. instance handle
const int condition_stack_size, Size of the condition stack const int condition_stack_size, Size of the condition stack
const int handler_stack_size, Size of the handler stack const int handler_stack_size, Size of the handler stack
const int exit_code, Abnormal exit code const int exit_code, Abnormal exit code
.output : .output :
int cc, condition code int cc, condition code
.status_codes : .status_codes :
CHF_F_MALLOC, FATAL, memory allocation failed CHF_F_MALLOC, FATAL, memory allocation failed
CHF_F_NOT_AVAILABLE, FATAL, function not available CHF_F_NOT_AVAILABLE, FATAL, function not available
.notes : .notes :
2.2, 19-Jan-2001, creation 2.2, 19-Jan-2001, creation
.- */ .- */
int ChfWin32Init( /* Initialization within _WIN32 */ int ChfWin32Init( /* Initialization within _WIN32 */
const ChfChar *app_name, /* Application's name */ const ChfChar* app_name, /* Application's name */
const ChfOptions options, /* Options */ const ChfOptions options, /* Options */
#ifndef _WIN32 #ifndef _WIN32
void *instance, /* Fake arguments */ void* instance, /* Fake arguments */
#else #else
HINSTANCE instance, /* App. instance handle */ HINSTANCE instance, /* App. instance handle */
#endif #endif
const int condition_stack_size, /* Size of the condition stack */ const int condition_stack_size, /* Size of the condition stack */
const int handler_stack_size, /* Size of the handler stack */ const int handler_stack_size, /* Size of the handler stack */
const int exit_code /* Abnormal exit code */ const int exit_code /* Abnormal exit code */
) )
{ {
#ifndef _WIN32 #ifndef _WIN32
/* This function is available only in Win32 */ /* This function is available only in Win32 */
return CHF_F_NOT_AVAILABLE; return CHF_F_NOT_AVAILABLE;
#else #else
ChfWin32Context *private_context; ChfWin32Context* private_context;
int cc; int cc;
if((private_context = if ( ( private_context = ( ChfWin32Context* )malloc( sizeof( ChfWin32Context ) ) ) == ( ChfWin32Context* )NULL )
(ChfWin32Context *)malloc(sizeof(ChfWin32Context))) == cc = CHF_F_MALLOC;
(ChfWin32Context *)NULL)
cc = CHF_F_MALLOC;
else if((cc = ChfInit(app_name, options, (void *)private_context, else if ( ( cc = ChfInit( app_name, options, ( void* )private_context, Win32GetMessage, ExitMessage, condition_stack_size,
Win32GetMessage, ExitMessage, condition_stack_size, handler_stack_size, handler_stack_size, exit_code ) ) != CHF_S_OK ) {
exit_code)) != CHF_S_OK) free( private_context );
{ }
free(private_context);
}
else else {
{ /* Save Win32 specific context items into private Chf context */
/* Save Win32 specific context items into private Chf context */ private_context->instance = instance;
private_context->instance = instance;
cc = CHF_S_OK; cc = CHF_S_OK;
} }
return cc; return cc;
#endif #endif
} }

12
src/libChf/resource.h Executable file → Normal file
View file

@ -6,10 +6,10 @@
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS # ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101 # define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001 # define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000 # define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101 # define _APS_NEXT_SYMED_VALUE 101
#endif # endif
#endif #endif

View file

@ -11,64 +11,55 @@
#include <setjmp.h> #include <setjmp.h>
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
#define CHF_MODULE_ID 255 #define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO #define CHF_EXTENDED_INFO
#include "Chf.h" #include "Chf.h"
int main( int argc, char* argv[] )
int main(int argc, char *argv[])
{ {
int st; int st;
const char *msg; const char* msg;
const ChfDescriptor *d, *e; const ChfDescriptor *d, *e;
puts("test01"); puts( "test01" );
system("gencat test01.cat test01.msf"); system( "gencat test01.cat test01.msf" );
system("gencat test01.cat chf.msf"); system( "gencat test01.cat chf.msf" );
/* Initialization */ /* Initialization */
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1)) if ( st = ChfMsgcatInit( argv[ 0 ], CHF_DEFAULT, "./test01.cat", 50, 10, 1 ) )
exit(st); exit( st );
/* ChfGetMessage: /* ChfGetMessage:
message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not
*/ */
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1"); msg = ChfGetMessage( CHF_MODULE_ID, 1, "Default_1" );
if(strcmp(msg, "Set_255,Message_1")) exit(EXIT_FAILURE); if ( strcmp( msg, "Set_255,Message_1" ) )
msg = ChfGetMessage(CHF_MODULE_ID, 2, "Default_2"); exit( EXIT_FAILURE );
if(strcmp(msg, "Default_2")) exit(EXIT_FAILURE); msg = ChfGetMessage( CHF_MODULE_ID, 2, "Default_2" );
if ( strcmp( msg, "Default_2" ) )
exit( EXIT_FAILURE );
/* Generate a condition and check descriptor; this is line 46 */ /* Generate a condition and check descriptor; this is line 46 */
ChfCondition 3, CHF_WARNING, 456 ChfEnd; ChfCondition 3, CHF_WARNING, 456 ChfEnd;
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( d = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
d->module_id != CHF_MODULE_ID if ( d->module_id != CHF_MODULE_ID || d->condition_code != 3 || d->severity != CHF_WARNING || d->line_number != 46 ||
|| d->condition_code != 3 strcmp( d->file_name, "test01.c" ) || strcmp( d->message, "Set_255,Arg_456,Message_3" ) || d->next != NULL )
|| d->severity != CHF_WARNING exit( EXIT_FAILURE );
|| d->line_number != 46
|| strcmp(d->file_name, "test01.c")
|| strcmp(d->message, "Set_255,Arg_456,Message_3")
|| d->next != NULL
) exit(EXIT_FAILURE);
/* Generate another condition and check; this is line 60 */ /* Generate another condition and check; this is line 60 */
ChfCondition 4, CHF_INFO, "arg" ChfEnd; ChfCondition 4, CHF_INFO, "arg" ChfEnd;
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( e = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
e->module_id != CHF_MODULE_ID if ( e->module_id != CHF_MODULE_ID || e->condition_code != 4 || e->severity != CHF_INFO || e->line_number != 60 ||
|| e->condition_code != 4 strcmp( e->file_name, "test01.c" ) || strcmp( e->message, "Set_255,Arg_arg,Message_4" ) || e->next != d )
|| e->severity != CHF_INFO exit( EXIT_FAILURE );
|| e->line_number != 60
|| strcmp(e->file_name, "test01.c")
|| strcmp(e->message, "Set_255,Arg_arg,Message_4")
|| e->next != d
) exit(EXIT_FAILURE);
/* Discard the previous condition group and create a new one */ /* Discard the previous condition group and create a new one */
ChfDiscard(); ChfDiscard();
@ -76,18 +67,13 @@ int main(int argc, char *argv[])
/* This is line 77 */ /* This is line 77 */
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd; ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( d = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
d->module_id != CHF_MODULE_ID if ( d->module_id != CHF_MODULE_ID || d->condition_code != 5 || d->severity != CHF_ERROR || d->line_number != 77 ||
|| d->condition_code != 5 strcmp( d->file_name, "test01.c" ) || strcmp( d->message, "Set_255,Arg_456-789,Message_5" ) || d->next != NULL )
|| d->severity != CHF_ERROR exit( EXIT_FAILURE );
|| d->line_number != 77
|| strcmp(d->file_name, "test01.c")
|| strcmp(d->message, "Set_255,Arg_456-789,Message_5")
|| d->next != NULL
) exit(EXIT_FAILURE);
/* Exit Chf */ /* Exit Chf */
ChfExit(); ChfExit();
exit(EXIT_SUCCESS); exit( EXIT_SUCCESS );
} }

View file

@ -11,54 +11,45 @@
#include <setjmp.h> #include <setjmp.h>
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
#define CHF_MODULE_ID 255 #define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO #define CHF_EXTENDED_INFO
#include "Chf.h" #include "Chf.h"
void* task( void* arg )
void *task(void *arg)
{ {
const char *msg; const char* msg;
const ChfDescriptor *d, *e; const ChfDescriptor *d, *e;
printf("\tThread %d\n", (int)arg); printf( "\tThread %d\n", ( int )arg );
/* message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not */ /* message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not */
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1"); msg = ChfGetMessage( CHF_MODULE_ID, 1, "Default_1" );
if(strcmp(msg, "Set_255,Message_1")) exit(EXIT_FAILURE); if ( strcmp( msg, "Set_255,Message_1" ) )
msg = ChfGetMessage(CHF_MODULE_ID, 2, "Default_2"); exit( EXIT_FAILURE );
if(strcmp(msg, "Default_2")) exit(EXIT_FAILURE); msg = ChfGetMessage( CHF_MODULE_ID, 2, "Default_2" );
if ( strcmp( msg, "Default_2" ) )
exit( EXIT_FAILURE );
/* Generate a condition and check descriptor; this is line 36 */ /* Generate a condition and check descriptor; this is line 36 */
ChfCondition 3, CHF_WARNING, 456 ChfEnd; ChfCondition 3, CHF_WARNING, 456 ChfEnd;
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( d = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
d->module_id != CHF_MODULE_ID if ( d->module_id != CHF_MODULE_ID || d->condition_code != 3 || d->severity != CHF_WARNING || d->line_number != 36 ||
|| d->condition_code != 3 strcmp( d->file_name, "test02.c" ) || strcmp( d->message, "Set_255,Arg_456,Message_3" ) || d->next != NULL )
|| d->severity != CHF_WARNING exit( EXIT_FAILURE );
|| d->line_number != 36
|| strcmp(d->file_name, "test02.c")
|| strcmp(d->message, "Set_255,Arg_456,Message_3")
|| d->next != NULL
) exit(EXIT_FAILURE);
/* Generate another condition and check; this is line 50 */ /* Generate another condition and check; this is line 50 */
ChfCondition 4, CHF_INFO, "arg" ChfEnd; ChfCondition 4, CHF_INFO, "arg" ChfEnd;
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( e = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
e->module_id != CHF_MODULE_ID if ( e->module_id != CHF_MODULE_ID || e->condition_code != 4 || e->severity != CHF_INFO || e->line_number != 50 ||
|| e->condition_code != 4 strcmp( e->file_name, "test02.c" ) || strcmp( e->message, "Set_255,Arg_arg,Message_4" ) || e->next != d )
|| e->severity != CHF_INFO exit( EXIT_FAILURE );
|| e->line_number != 50
|| strcmp(e->file_name, "test02.c")
|| strcmp(e->message, "Set_255,Arg_arg,Message_4")
|| e->next != d
) exit(EXIT_FAILURE);
/* Discard the previous condition group and create a new one */ /* Discard the previous condition group and create a new one */
ChfDiscard(); ChfDiscard();
@ -66,56 +57,49 @@ void *task(void *arg)
/* This is line 67 */ /* This is line 67 */
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd; ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( d = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
d->module_id != CHF_MODULE_ID if ( d->module_id != CHF_MODULE_ID || d->condition_code != 5 || d->severity != CHF_ERROR || d->line_number != 67 ||
|| d->condition_code != 5 strcmp( d->file_name, "test02.c" ) || strcmp( d->message, "Set_255,Arg_456-789,Message_5" ) || d->next != NULL )
|| d->severity != CHF_ERROR exit( EXIT_FAILURE );
|| d->line_number != 67
|| strcmp(d->file_name, "test02.c")
|| strcmp(d->message, "Set_255,Arg_456-789,Message_5")
|| d->next != NULL
) exit(EXIT_FAILURE);
return (void *)0; return ( void* )0;
} }
#define N_THREADS 50 #define N_THREADS 50
int main(int argc, char *argv[]) int main( int argc, char* argv[] )
{ {
int st; int st;
int i; int i;
void *ret; void* ret;
#ifdef _REENTRANT #ifdef _REENTRANT
pthread_t t[N_THREADS]; pthread_t t[ N_THREADS ];
#endif #endif
puts("test02"); puts( "test02" );
#ifdef _REENTRANT #ifdef _REENTRANT
/* Initialization */ /* Initialization */
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1)) if ( st = ChfMsgcatInit( argv[ 0 ], CHF_DEFAULT, "./test01.cat", 50, 10, 1 ) )
exit(st); exit( st );
/* Create */ /* Create */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(st = pthread_create(&(t[i]), NULL, task, (void *)i)) if ( st = pthread_create( &( t[ i ] ), NULL, task, ( void* )i ) ) {
{ printf( "pthread_create: error %d", st );
printf("pthread_create: error %d", st); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
/* Join */ /* Join */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(st = pthread_join(t[i], &ret)) if ( st = pthread_join( t[ i ], &ret ) ) {
{ printf( "pthread_join: error %d", st );
printf("pthread_join: error %d", st); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
/* Exit Chf */ /* Exit Chf */
ChfExit(); ChfExit();
#endif #endif
exit(EXIT_SUCCESS); exit( EXIT_SUCCESS );
} }

View file

@ -14,77 +14,74 @@
#include <setjmp.h> #include <setjmp.h>
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
#define CHF_MODULE_ID 255 #define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO #define CHF_EXTENDED_INFO
#include "Chf.h" #include "Chf.h"
void* task( void* arg )
void *task(void *arg)
{ {
const char *msg; const char* msg;
const ChfDescriptor *d, *e; const ChfDescriptor *d, *e;
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
printf("\tThread %d\n", (int)arg); printf( "\tThread %d\n", ( int )arg );
/* Generate a condition group and signal it */ /* Generate a condition group and signal it */
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
ChfCondition 7, CHF_INFO, (int)arg ChfEnd; ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
ChfSignal(); ChfSignal();
return (void *)0; return ( void* )0;
} }
#define N_THREADS 50 #define N_THREADS 50
int main(int argc, char *argv[]) int main( int argc, char* argv[] )
{ {
int st; int st;
int i; int i;
void *ret; void* ret;
#ifdef _REENTRANT #ifdef _REENTRANT
pthread_t t[N_THREADS]; pthread_t t[ N_THREADS ];
#endif #endif
puts("test03"); puts( "test03" );
/* Initialization */ /* Initialization */
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1)) if ( st = ChfMsgcatInit( argv[ 0 ], CHF_DEFAULT, "./test01.cat", 50, 10, 1 ) )
exit(st); exit( st );
#ifdef _REENTRANT #ifdef _REENTRANT
/* Create */ /* Create */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(pthread_create(&(t[i]), NULL, task, (void *)i)) if ( pthread_create( &( t[ i ] ), NULL, task, ( void* )i ) ) {
{ perror( "pthread_create" );
perror("pthread_create"); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
/* Join */ /* Join */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(pthread_join(t[i], &ret)) if ( pthread_join( t[ i ], &ret ) ) {
{ perror( "pthread_join" );
perror("pthread_join"); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
#else #else
task((void *)0); task( ( void* )0 );
#endif #endif
/* Exit Chf */ /* Exit Chf */
ChfExit(); ChfExit();
exit(EXIT_SUCCESS); exit( EXIT_SUCCESS );
} }

View file

@ -14,193 +14,161 @@
#include <setjmp.h> #include <setjmp.h>
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
#define CHF_MODULE_ID 255 #define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO #define CHF_EXTENDED_INFO
#include "Chf.h" #include "Chf.h"
struct tdata_s struct tdata_s {
{
const ChfDescriptor *d, *e; const ChfDescriptor *d, *e;
int phase; int phase;
}; };
ChfAction h1( ChfAction h1( const ChfDescriptor* c, const ChfState s, ChfPointer p )
const ChfDescriptor *c,
const ChfState s,
ChfPointer p
)
{ {
struct tdata_s *tdata_p = (struct tdata_s *)p; struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action; ChfAction action;
if(c != tdata_p->e || if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d ) {
ChfGetNextDescriptor(c) != tdata_p->d) ChfCondition 10, CHF_FATAL ChfEnd;
{ action = CHF_RESIGNAL;
ChfCondition 10, CHF_FATAL ChfEnd;
action = CHF_RESIGNAL;
} }
else else
action = CHF_CONTINUE; action = CHF_CONTINUE;
return action; return action;
} }
ChfAction h2( ChfAction h2( const ChfDescriptor* c, const ChfState s, ChfPointer p )
const ChfDescriptor *c,
const ChfState s,
ChfPointer p
)
{ {
struct tdata_s *tdata_p = (struct tdata_s *)p; struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action; ChfAction action;
switch(s) switch ( s ) {
{ case CHF_SIGNALING:
case CHF_SIGNALING: {
{ if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d || ( tdata_p->phase != 2 && tdata_p->phase != 4 ) ) {
if(c != tdata_p->e ChfCondition 10, CHF_FATAL ChfEnd;
|| ChfGetNextDescriptor(c) != tdata_p->d action = CHF_RESIGNAL;
|| (tdata_p->phase != 2 && tdata_p->phase != 4)) }
{
ChfCondition 10, CHF_FATAL ChfEnd;
action = CHF_RESIGNAL;
}
else else {
{ action = ( ChfGetConditionCode( c ) != 8 ? CHF_CONTINUE : CHF_UNWIND );
action = (ChfGetConditionCode(c) != 8 ? CHF_CONTINUE : CHF_UNWIND); }
} break;
break; }
} case CHF_UNWINDING:
case CHF_UNWINDING: {
{ if ( tdata_p->phase != 4 )
if(tdata_p->phase != 4) exit(EXIT_FAILURE); exit( EXIT_FAILURE );
tdata_p->phase = 5; tdata_p->phase = 5;
action = CHF_CONTINUE; action = CHF_CONTINUE;
break; break;
} }
default: default:
{ {
exit(EXIT_FAILURE); exit( EXIT_FAILURE );
} }
} }
return action; return action;
} }
ChfAction h3( ChfAction h3( const ChfDescriptor* c, const ChfState s, ChfPointer p )
const ChfDescriptor *c,
const ChfState s,
ChfPointer p
)
{ {
struct tdata_s *tdata_p = (struct tdata_s *)p; struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action; ChfAction action;
/* This handler must be invoked only during the first signal */ /* This handler must be invoked only during the first signal */
if(tdata_p->phase != 3) exit(EXIT_FAILURE); if ( tdata_p->phase != 3 )
exit( EXIT_FAILURE );
switch(s) switch ( s ) {
{ case CHF_SIGNALING:
case CHF_SIGNALING: {
{ if ( ChfGetConditionCode( c ) != 9 || ChfGetNextDescriptor( c ) != NULL ) {
if(ChfGetConditionCode(c) != 9 || exit( EXIT_FAILURE );
ChfGetNextDescriptor(c) != NULL) }
{
exit(EXIT_FAILURE);
}
else else {
{ tdata_p->phase = 4;
tdata_p->phase = 4; action = CHF_CONTINUE;
action = CHF_CONTINUE; }
} break;
break; }
} default:
default: {
{ exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
} }
return action; return action;
} }
ChfAction h4( ChfAction h4( const ChfDescriptor* c, const ChfState s, ChfPointer p )
const ChfDescriptor *c,
const ChfState s,
ChfPointer p
)
{ {
struct tdata_s *tdata_p = (struct tdata_s *)p; struct tdata_s* tdata_p = ( struct tdata_s* )p;
ChfAction action; ChfAction action;
/* This handler must be invoked only during the first signal */ /* This handler must be invoked only during the first signal */
if(tdata_p->phase != 2) exit(EXIT_FAILURE); if ( tdata_p->phase != 2 )
exit( EXIT_FAILURE );
switch(s) switch ( s ) {
{ case CHF_SIGNALING:
case CHF_SIGNALING: {
{ if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d ) {
if(c != tdata_p->e ChfCondition 10, CHF_FATAL ChfEnd;
|| ChfGetNextDescriptor(c) != tdata_p->d) action = CHF_RESIGNAL;
{ }
ChfCondition 10, CHF_FATAL ChfEnd;
action = CHF_RESIGNAL;
}
else else {
{ /* This generates a new group and signals it */
/* This generates a new group and signals it */ tdata_p->phase = 3;
tdata_p->phase = 3; ChfCondition 9, CHF_INFO ChfEnd;
ChfCondition 9, CHF_INFO ChfEnd; ChfSignal();
ChfSignal();
if(tdata_p->phase != 4) exit(EXIT_FAILURE); if ( tdata_p->phase != 4 )
tdata_p->phase = 5; exit( EXIT_FAILURE );
tdata_p->phase = 5;
if(c != tdata_p->e if ( c != tdata_p->e || ChfGetNextDescriptor( c ) != tdata_p->d ) {
|| ChfGetNextDescriptor(c) != tdata_p->d) ChfCondition 10, CHF_FATAL ChfEnd;
{ action = CHF_RESIGNAL;
ChfCondition 10, CHF_FATAL ChfEnd; } else
action = CHF_RESIGNAL; action = CHF_CONTINUE;
} }
else break;
action = CHF_CONTINUE; }
} default:
break; {
} exit( EXIT_FAILURE );
default: }
{
exit(EXIT_FAILURE);
}
} }
return action; return action;
} }
void *task(void *arg) void* task( void* arg )
{ {
volatile struct tdata_s tdata; volatile struct tdata_s tdata;
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
printf("\tThread %d\n", (int)arg); printf( "\tThread %d\n", ( int )arg );
/* Push the handler */ /* Push the handler */
ChfPushHandler(h1, NULL, (ChfPointer)(&tdata)); ChfPushHandler( h1, NULL, ( ChfPointer )( &tdata ) );
/* Generate a condition group and signal it */ /* Generate a condition group and signal it */
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition(); tdata.d = ChfGetTopCondition();
ChfCondition 7, CHF_INFO, (int)arg ChfEnd; ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition(); tdata.e = ChfGetTopCondition();
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
ChfSignal(); ChfSignal();
/* Pop the handler */ /* Pop the handler */
@ -210,122 +178,117 @@ void *task(void *arg)
and signal it; this checks that the handler has actually been and signal it; this checks that the handler has actually been
removed. removed.
*/ */
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = NULL; tdata.d = NULL;
ChfCondition 7, CHF_INFO, (int)arg ChfEnd; ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = NULL; tdata.e = NULL;
ChfSignal(); ChfSignal();
/* Conditional unwind test */ /* Conditional unwind test */
{ {
sigjmp_buf jb; sigjmp_buf jb;
tdata.phase = 0; tdata.phase = 0;
if(setjmp(jb) == 0) if ( setjmp( jb ) == 0 ) {
{ ChfPushHandler( h2, jb, ( ChfPointer )( &tdata ) );
ChfPushHandler(h2, jb, (ChfPointer)(&tdata));
/* Generate a condition group and signal it */ /* Generate a condition group and signal it */
tdata.phase = 1; tdata.phase = 1;
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition(); tdata.d = ChfGetTopCondition();
ChfCondition 7, CHF_INFO, (int)arg ChfEnd; ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition(); tdata.e = ChfGetTopCondition();
/* This does not trigger an unwind */ /* This does not trigger an unwind */
tdata.phase = 2; tdata.phase = 2;
ChfSignal(); ChfSignal();
tdata.phase = 3; tdata.phase = 3;
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition(); tdata.d = ChfGetTopCondition();
ChfCondition 8, CHF_INFO, (int)arg ChfEnd; ChfCondition 8, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition(); tdata.e = ChfGetTopCondition();
/* This MUST trigger an unwind */ /* This MUST trigger an unwind */
tdata.phase = 4; tdata.phase = 4;
ChfSignal(); ChfSignal();
exit(EXIT_FAILURE); exit( EXIT_FAILURE );
} } else {
else /* Unwind */
{ if ( tdata.phase != 5 )
/* Unwind */ exit( EXIT_FAILURE );
if(tdata.phase != 5)
exit(EXIT_FAILURE);
ChfPopHandler(); ChfPopHandler();
} }
} }
/* Condition generation and signal while a signal is in progress; /* Condition generation and signal while a signal is in progress;
this requires two handlers. this requires two handlers.
*/ */
{ {
tdata.phase = 0; tdata.phase = 0;
ChfPushHandler(h3, NULL, (ChfPointer)&tdata); ChfPushHandler( h3, NULL, ( ChfPointer )&tdata );
ChfPushHandler(h4, NULL, (ChfPointer)&tdata); ChfPushHandler( h4, NULL, ( ChfPointer )&tdata );
tdata.phase = 1; tdata.phase = 1;
ChfCondition 6, CHF_INFO, (int)arg ChfEnd; ChfCondition 6, CHF_INFO, ( int )arg ChfEnd;
tdata.d = ChfGetTopCondition(); tdata.d = ChfGetTopCondition();
ChfCondition 7, CHF_INFO, (int)arg ChfEnd; ChfCondition 7, CHF_INFO, ( int )arg ChfEnd;
tdata.e = ChfGetTopCondition(); tdata.e = ChfGetTopCondition();
tdata.phase = 2; tdata.phase = 2;
ChfSignal(); ChfSignal();
if(tdata.phase != 5) if ( tdata.phase != 5 )
exit(EXIT_FAILURE); exit( EXIT_FAILURE );
ChfPopHandler(); ChfPopHandler();
ChfPopHandler(); ChfPopHandler();
} }
return (void *)0; return ( void* )0;
} }
#define N_THREADS 50 #define N_THREADS 50
int main(int argc, char *argv[]) int main( int argc, char* argv[] )
{ {
int st; int st;
int i; int i;
void *ret; void* ret;
#ifdef _REENTRANT #ifdef _REENTRANT
pthread_t t[N_THREADS]; pthread_t t[ N_THREADS ];
#endif #endif
puts("test04"); puts( "test04" );
/* Initialization */ /* Initialization */
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1)) if ( st = ChfMsgcatInit( argv[ 0 ], CHF_DEFAULT, "./test01.cat", 50, 10, 1 ) )
exit(st); exit( st );
#ifdef _REENTRANT #ifdef _REENTRANT
/* Create */ /* Create */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(pthread_create(&(t[i]), NULL, task, (void *)i)) if ( pthread_create( &( t[ i ] ), NULL, task, ( void* )i ) ) {
{ perror( "pthread_create" );
perror("pthread_create"); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
/* Join */ /* Join */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(pthread_join(t[i], &ret)) if ( pthread_join( t[ i ], &ret ) ) {
{ perror( "pthread_join" );
perror("pthread_join"); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
#else #else
task((void *)0); task( ( void* )0 );
#endif #endif
/* Exit Chf */ /* Exit Chf */
ChfExit(); ChfExit();
exit(EXIT_SUCCESS); exit( EXIT_SUCCESS );
} }

View file

@ -14,63 +14,45 @@
#include <setjmp.h> #include <setjmp.h>
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
#define CHF_MODULE_ID 255 #define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO #define CHF_EXTENDED_INFO
#include "Chf.h" #include "Chf.h"
#define H_STACK_SIZE 10 #define H_STACK_SIZE 10
#define C_STACK_SIZE 30 #define C_STACK_SIZE 30
/* Dummy handler; pushed only to verify that the handler stack overflow /* Dummy handler; pushed only to verify that the handler stack overflow
checks are correct. checks are correct.
*/ */
ChfAction h1( ChfAction h1( const ChfDescriptor* c, const ChfState s, ChfPointer p ) { return CHF_RESIGNAL; }
const ChfDescriptor *c,
const ChfState s,
ChfPointer p
)
{
return CHF_RESIGNAL;
}
/* Overflow check handler; it unwinds if the CHF_F_HDLR_STACK_FULL /* Overflow check handler; it unwinds if the CHF_F_HDLR_STACK_FULL
condition is signalled exactly after H_STACK_SIZE-2 invocations condition is signalled exactly after H_STACK_SIZE-2 invocations
of ChfPushHandler(), it resignals a modified condition if the of ChfPushHandler(), it resignals a modified condition if the
condition is signalled too early condition is signalled too early
*/ */
ChfAction h2( ChfAction h2( const ChfDescriptor* c, const ChfState s, ChfPointer p )
const ChfDescriptor *c,
const ChfState s,
ChfPointer p
)
{ {
int push_count = *((int *)p); int push_count = *( ( int* )p );
ChfAction action; ChfAction action;
if(s == CHF_SIGNALING) if ( s == CHF_SIGNALING ) {
{ if ( ChfGetModuleId( c ) == CHF_SET && ChfGetConditionCode( c ) == CHF_F_HDLR_STACK_FULL ) {
if(ChfGetModuleId(c) == CHF_SET /* Handler stack is full; check correctness of the descriptor */
&& ChfGetConditionCode(c) == CHF_F_HDLR_STACK_FULL) if ( push_count == H_STACK_SIZE - 2 && ChfGetNextDescriptor( c ) == NULL && ChfGetSeverity( c ) == CHF_FATAL )
{ action = CHF_UNWIND;
/* Handler stack is full; check correctness of the descriptor */ else {
if(push_count == H_STACK_SIZE-2 ChfCondition 11, CHF_FATAL, push_count, H_STACK_SIZE - 2 ChfEnd;
&& ChfGetNextDescriptor(c) == NULL action = CHF_RESIGNAL;
&& ChfGetSeverity(c) == CHF_FATAL) }
action = CHF_UNWIND; }
else
{
ChfCondition 11, CHF_FATAL, push_count, H_STACK_SIZE-2
ChfEnd;
action = CHF_RESIGNAL;
}
}
} }
else else
action = CHF_RESIGNAL; action = CHF_RESIGNAL;
return action; return action;
} }
@ -80,68 +62,55 @@ ChfAction h2(
of ChfCondition, it resignals a modified condition if the of ChfCondition, it resignals a modified condition if the
condition is signalled too early condition is signalled too early
*/ */
ChfAction h3( ChfAction h3( const ChfDescriptor* c, const ChfState s, ChfPointer p )
const ChfDescriptor *c,
const ChfState s,
ChfPointer p
)
{ {
int push_count = *((int *)p); int push_count = *( ( int* )p );
ChfAction action; ChfAction action;
if(s == CHF_SIGNALING) if ( s == CHF_SIGNALING ) {
{ if ( ChfGetModuleId( c ) == CHF_SET && ChfGetConditionCode( c ) == CHF_F_COND_STACK_FULL ) {
if(ChfGetModuleId(c) == CHF_SET /* Handler stack is full; check correctness of the descriptor */
&& ChfGetConditionCode(c) == CHF_F_COND_STACK_FULL) if ( push_count == C_STACK_SIZE && ChfGetNextDescriptor( c ) == NULL && ChfGetSeverity( c ) == CHF_FATAL )
{ action = CHF_UNWIND;
/* Handler stack is full; check correctness of the descriptor */ else {
if(push_count == C_STACK_SIZE ChfCondition 12, CHF_FATAL, push_count, C_STACK_SIZE ChfEnd;
&& ChfGetNextDescriptor(c) == NULL action = CHF_RESIGNAL;
&& ChfGetSeverity(c) == CHF_FATAL) }
action = CHF_UNWIND; }
else
{
ChfCondition 12, CHF_FATAL, push_count, C_STACK_SIZE
ChfEnd;
action = CHF_RESIGNAL;
}
}
} }
else else
action = CHF_RESIGNAL; action = CHF_RESIGNAL;
return action; return action;
} }
void* task( void* arg )
void *task(void *arg)
{ {
int push_count = 0; int push_count = 0;
sigjmp_buf jb; sigjmp_buf jb;
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
printf("\tThread %d\n", (int)arg); printf( "\tThread %d\n", ( int )arg );
/* Check handler stack overflow checks */ /* Check handler stack overflow checks */
if(sigsetjmp(jb, 1) == 0) if ( sigsetjmp( jb, 1 ) == 0 ) {
{ int i;
int i;
/* Push the handler */ /* Push the handler */
ChfPushHandler(h2, jb, (ChfPointer)(&push_count)); ChfPushHandler( h2, jb, ( ChfPointer )( &push_count ) );
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
/* Push dummy handlers until an error should occur */ /* Push dummy handlers until an error should occur */
for(; push_count<H_STACK_SIZE-1; push_count++) for ( ; push_count < H_STACK_SIZE - 1; push_count++ )
ChfPushHandler(h1, NULL, NULL); ChfPushHandler( h1, NULL, NULL );
/* No error? Bad! */ /* No error? Bad! */
return (void *)EXIT_FAILURE; return ( void* )EXIT_FAILURE;
} }
/* Flow control returns here if 'handler stack full' was signalled /* Flow control returns here if 'handler stack full' was signalled
@ -149,22 +118,21 @@ void *task(void *arg)
Check condition stack overflow checks Check condition stack overflow checks
*/ */
push_count = 0; push_count = 0;
if(sigsetjmp(jb, 1) == 0) if ( sigsetjmp( jb, 1 ) == 0 ) {
{ int i;
int i;
/* Push the handler */ /* Push the handler */
ChfPushHandler(h3, jb, (ChfPointer)(&push_count)); ChfPushHandler( h3, jb, ( ChfPointer )( &push_count ) );
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
/* Push dummy conditions until an error should occur */ /* Push dummy conditions until an error should occur */
for(; push_count<=C_STACK_SIZE; push_count++) for ( ; push_count <= C_STACK_SIZE; push_count++ )
ChfCondition 1, CHF_INFO ChfEnd; ChfCondition 1, CHF_INFO ChfEnd;
/* No error? Bad! */ /* No error? Bad! */
return (void *)EXIT_FAILURE; return ( void* )EXIT_FAILURE;
} }
/* Flow control returns here if 'condition stack full' was signalled /* Flow control returns here if 'condition stack full' was signalled
@ -173,75 +141,67 @@ void *task(void *arg)
conditions were left out in the previous check. conditions were left out in the previous check.
*/ */
push_count = 0; push_count = 0;
if(sigsetjmp(jb, 1) == 0) if ( sigsetjmp( jb, 1 ) == 0 ) {
{ int i;
int i;
/* Push the handler */ /* Push the handler */
ChfPushHandler(h3, jb, (ChfPointer)(&push_count)); ChfPushHandler( h3, jb, ( ChfPointer )( &push_count ) );
/* The sleep() is here to increase contention between threads */ /* The sleep() is here to increase contention between threads */
sleep(1); sleep( 1 );
/* Push dummy conditions until an error should occur */ /* Push dummy conditions until an error should occur */
for(; push_count<=C_STACK_SIZE; push_count++) for ( ; push_count <= C_STACK_SIZE; push_count++ )
ChfCondition 1, CHF_INFO ChfEnd; ChfCondition 1, CHF_INFO ChfEnd;
/* No error? Bad! */ /* No error? Bad! */
return (void *)EXIT_FAILURE; return ( void* )EXIT_FAILURE;
} }
return (void *)EXIT_SUCCESS; return ( void* )EXIT_SUCCESS;
} }
#define N_THREADS 50
#define N_THREADS 50 int main( int argc, char* argv[] )
int main(int argc, char *argv[])
{ {
int st; int st;
int i; int i;
void *ret; void* ret;
#ifdef _REENTRANT #ifdef _REENTRANT
pthread_t t[N_THREADS]; pthread_t t[ N_THREADS ];
#endif #endif
puts("test05"); puts( "test05" );
/* Initialization */ /* Initialization */
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", if ( st = ChfMsgcatInit( argv[ 0 ], CHF_DEFAULT, "./test01.cat", C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE ) )
C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE)) exit( st );
exit(st);
#ifdef _REENTRANT #ifdef _REENTRANT
/* Create */ /* Create */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(pthread_create(&(t[i]), NULL, task, (void *)i)) if ( pthread_create( &( t[ i ] ), NULL, task, ( void* )i ) ) {
{ perror( "pthread_create" );
perror("pthread_create"); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
/* Join */ /* Join */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ ) {
{ if ( pthread_join( t[ i ], &ret ) ) {
if(pthread_join(t[i], &ret)) perror( "pthread_join" );
{ exit( EXIT_FAILURE );
perror("pthread_join"); } else if ( ( int )ret != EXIT_SUCCESS )
exit(EXIT_FAILURE); exit( ( int )ret );
}
else if((int)ret != EXIT_SUCCESS)
exit((int)ret);
} }
st = EXIT_SUCCESS; st = EXIT_SUCCESS;
#else #else
st = (int)task((void *)0); st = ( int )task( ( void* )0 );
#endif #endif
/* Exit Chf */ /* Exit Chf */
ChfExit(); ChfExit();
exit(st); exit( st );
} }

View file

@ -14,125 +14,109 @@
#include <setjmp.h> #include <setjmp.h>
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
#define CHF_MODULE_ID 255 #define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO #define CHF_EXTENDED_INFO
#include "Chf.h" #include "Chf.h"
#define H_STACK_SIZE 10 #define H_STACK_SIZE 10
#define C_STACK_SIZE 30 #define C_STACK_SIZE 30
void* task( void* arg )
void *task(void *arg)
{ {
volatile int phase = 0; volatile int phase = 0;
ChfTry ChfTry
{ {
phase = 1; phase = 1;
ChfCondition 20, CHF_SUCCESS ChfEnd; ChfCondition 20, CHF_SUCCESS ChfEnd;
ChfSignal(); ChfSignal();
phase = 2; phase = 2;
ChfCondition 20, CHF_INFO ChfEnd; ChfCondition 20, CHF_INFO ChfEnd;
ChfSignal(); ChfSignal();
phase = 3; phase = 3;
ChfCondition 20, CHF_WARNING ChfEnd; ChfCondition 20, CHF_WARNING ChfEnd;
ChfSignal(); ChfSignal();
phase = 4; phase = 4;
ChfCondition 20, CHF_ERROR ChfEnd; ChfCondition 20, CHF_ERROR ChfEnd;
ChfSignal(); ChfSignal();
phase = 5; phase = 5;
ChfCondition 20, CHF_FATAL ChfEnd; ChfCondition 20, CHF_FATAL ChfEnd;
ChfSignal(); ChfSignal();
/* Should not be reached */ /* Should not be reached */
return (void *)EXIT_FAILURE; return ( void* )EXIT_FAILURE;
} }
ChfCatch ChfCatch
{ {
/* Catched an exception; check descriptor */ /* Catched an exception; check descriptor */
const ChfDescriptor *d = ChfGetTopCondition(); const ChfDescriptor* d = ChfGetTopCondition();
if(d == NULL if ( d == NULL || ChfGetNextDescriptor( d ) != NULL || ChfGetModuleId( d ) != CHF_MODULE_ID || ChfGetConditionCode( d ) != 20 )
|| ChfGetNextDescriptor(d) != NULL return ( void* )EXIT_FAILURE;
|| ChfGetModuleId(d) != CHF_MODULE_ID }
|| ChfGetConditionCode(d) != 20)
return (void *)EXIT_FAILURE;
}
ChfEndTry; ChfEndTry;
/* Check that the condition stack actually is empty after catch */ /* Check that the condition stack actually is empty after catch */
ChfTry ChfTry { const volatile ChfDescriptor* e = ChfGetTopCondition(); }
{
volatile const ChfDescriptor *e = ChfGetTopCondition();
}
ChfCatch ChfCatch
{ {
const ChfDescriptor *d = ChfGetTopCondition(); const ChfDescriptor* d = ChfGetTopCondition();
if(d == NULL if ( d == NULL || ChfGetNextDescriptor( d ) != NULL || ChfGetModuleId( d ) != CHF_SET ||
|| ChfGetNextDescriptor(d) != NULL ChfGetConditionCode( d ) != CHF_F_BAD_STATE )
|| ChfGetModuleId(d) != CHF_SET return ( void* )EXIT_FAILURE;
|| ChfGetConditionCode(d) != CHF_F_BAD_STATE) }
return (void *)EXIT_FAILURE;
}
ChfEndTry; ChfEndTry;
return (void *)EXIT_SUCCESS; return ( void* )EXIT_SUCCESS;
} }
#define N_THREADS 50
#define N_THREADS 50 int main( int argc, char* argv[] )
int main(int argc, char *argv[])
{ {
int st; int st;
int i; int i;
void *ret; void* ret;
#ifdef _REENTRANT #ifdef _REENTRANT
pthread_t t[N_THREADS]; pthread_t t[ N_THREADS ];
#endif #endif
puts("test06"); puts( "test06" );
/* Initialization */ /* Initialization */
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", if ( st = ChfMsgcatInit( argv[ 0 ], CHF_DEFAULT, "./test01.cat", C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE ) )
C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE)) exit( st );
exit(st);
#ifdef _REENTRANT #ifdef _REENTRANT
/* Create */ /* Create */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ )
if(pthread_create(&(t[i]), NULL, task, (void *)i)) if ( pthread_create( &( t[ i ] ), NULL, task, ( void* )i ) ) {
{ perror( "pthread_create" );
perror("pthread_create"); exit( EXIT_FAILURE );
exit(EXIT_FAILURE); }
}
/* Join */ /* Join */
for(i=0; i<N_THREADS; i++) for ( i = 0; i < N_THREADS; i++ ) {
{ if ( pthread_join( t[ i ], &ret ) ) {
if(pthread_join(t[i], &ret)) perror( "pthread_join" );
{ exit( EXIT_FAILURE );
perror("pthread_join"); } else if ( ( int )ret != EXIT_SUCCESS )
exit(EXIT_FAILURE); exit( ( int )ret );
}
else if((int)ret != EXIT_SUCCESS)
exit((int)ret);
} }
st = EXIT_SUCCESS; st = EXIT_SUCCESS;
#else #else
st = (int)task((void *)0); st = ( int )task( ( void* )0 );
#endif #endif
/* Exit Chf */ /* Exit Chf */
ChfExit(); ChfExit();
exit(st); exit( st );
} }

View file

@ -11,64 +11,55 @@
#include <setjmp.h> #include <setjmp.h>
#ifdef _REENTRANT #ifdef _REENTRANT
#include <pthread.h> # include <pthread.h>
#endif #endif
#define CHF_MODULE_ID 255 #define CHF_MODULE_ID 255
#define CHF_EXTENDED_INFO #define CHF_EXTENDED_INFO
#include "Chf.h" #include "Chf.h"
extern ChfTable message_table[]; extern ChfTable message_table[];
extern size_t message_table_size; extern size_t message_table_size;
int main(int argc, char *argv[]) int main( int argc, char* argv[] )
{ {
int st; int st;
const char *msg; const char* msg;
const ChfDescriptor *d, *e; const ChfDescriptor *d, *e;
puts("test07"); puts( "test07" );
/* Initialization */ /* Initialization */
if(st = ChfStaticInit(argv[0], CHF_DEFAULT, if ( st = ChfStaticInit( argv[ 0 ], CHF_DEFAULT, message_table, message_table_size, 50, 10, 1 ) )
message_table, message_table_size, 50, 10, 1)) exit( st );
exit(st);
/* ChfGetMessage: /* ChfGetMessage:
message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not
*/ */
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1"); msg = ChfGetMessage( CHF_MODULE_ID, 1, "Default_1" );
if(strcmp(msg, "Set_255,Message_1")) exit(EXIT_FAILURE); if ( strcmp( msg, "Set_255,Message_1" ) )
msg = ChfGetMessage(CHF_MODULE_ID, 2, "Default_2"); exit( EXIT_FAILURE );
if(strcmp(msg, "Default_2")) exit(EXIT_FAILURE); msg = ChfGetMessage( CHF_MODULE_ID, 2, "Default_2" );
if ( strcmp( msg, "Default_2" ) )
exit( EXIT_FAILURE );
/* Generate a condition and check descriptor; this is line 46 */ /* Generate a condition and check descriptor; this is line 46 */
ChfCondition 3, CHF_WARNING, 456 ChfEnd; ChfCondition 3, CHF_WARNING, 456 ChfEnd;
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( d = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
d->module_id != CHF_MODULE_ID if ( d->module_id != CHF_MODULE_ID || d->condition_code != 3 || d->severity != CHF_WARNING || d->line_number != 46 ||
|| d->condition_code != 3 strcmp( d->file_name, "test07.c" ) || strcmp( d->message, "Set_255,Arg_456,Message_3" ) || d->next != NULL )
|| d->severity != CHF_WARNING exit( EXIT_FAILURE );
|| d->line_number != 46
|| strcmp(d->file_name, "test07.c")
|| strcmp(d->message, "Set_255,Arg_456,Message_3")
|| d->next != NULL
) exit(EXIT_FAILURE);
/* Generate another condition and check; this is line 60 */ /* Generate another condition and check; this is line 60 */
ChfCondition 4, CHF_INFO, "arg" ChfEnd; ChfCondition 4, CHF_INFO, "arg" ChfEnd;
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( e = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
e->module_id != CHF_MODULE_ID if ( e->module_id != CHF_MODULE_ID || e->condition_code != 4 || e->severity != CHF_INFO || e->line_number != 60 ||
|| e->condition_code != 4 strcmp( e->file_name, "test07.c" ) || strcmp( e->message, "Set_255,Arg_arg,Message_4" ) || e->next != d )
|| e->severity != CHF_INFO exit( EXIT_FAILURE );
|| e->line_number != 60
|| strcmp(e->file_name, "test07.c")
|| strcmp(e->message, "Set_255,Arg_arg,Message_4")
|| e->next != d
) exit(EXIT_FAILURE);
/* Discard the previous condition group and create a new one */ /* Discard the previous condition group and create a new one */
ChfDiscard(); ChfDiscard();
@ -76,28 +67,22 @@ int main(int argc, char *argv[])
/* This is line 77 */ /* This is line 77 */
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd; ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE); if ( ( d = ChfGetTopCondition() ) == NULL )
if( exit( EXIT_FAILURE );
d->module_id != CHF_MODULE_ID if ( d->module_id != CHF_MODULE_ID || d->condition_code != 5 || d->severity != CHF_ERROR || d->line_number != 77 ||
|| d->condition_code != 5 strcmp( d->file_name, "test07.c" ) || strcmp( d->message, "Set_255,Arg_456-789,Message_5" ) || d->next != NULL )
|| d->severity != CHF_ERROR exit( EXIT_FAILURE );
|| d->line_number != 77
|| strcmp(d->file_name, "test07.c")
|| strcmp(d->message, "Set_255,Arg_456-789,Message_5")
|| d->next != NULL
) exit(EXIT_FAILURE);
/* Exit Chf */ /* Exit Chf */
ChfExit(); ChfExit();
exit(EXIT_SUCCESS); exit( EXIT_SUCCESS );
} }
ChfTable message_table[] = ChfTable message_table[] = {
{ {CHF_MODULE_ID, 1, "Set_255,Message_1" },
{ CHF_MODULE_ID, 1, "Set_255,Message_1" }, {CHF_MODULE_ID, 3, "Set_255,Arg_%d,Message_3" },
{ CHF_MODULE_ID, 3, "Set_255,Arg_%d,Message_3" }, {CHF_MODULE_ID, 4, "Set_255,Arg_%s,Message_4" },
{ CHF_MODULE_ID, 4, "Set_255,Arg_%s,Message_4" }, {CHF_MODULE_ID, 5, "Set_255,Arg_%d-%d,Message_5"}
{ CHF_MODULE_ID, 5, "Set_255,Arg_%d-%d,Message_5" }
}; };
size_t message_table_size = sizeof(message_table)/sizeof(message_table[0]); size_t message_table_size = sizeof( message_table ) / sizeof( message_table[ 0 ] );

View file

@ -60,16 +60,15 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Data type definitions Data type definitions
All Data types must be SIGNED All Data types must be SIGNED
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
typedef char int1; typedef char int1;
typedef char int4; typedef char int4;
typedef char int8; typedef char int8;
typedef int int12; typedef int int12;
typedef int int16; typedef int int16;
typedef int int20; typedef int int20;
typedef int int32; typedef int int32;

View file

@ -103,8 +103,8 @@ static char rcs_id[] = "$Id: saturn.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <setjmp.h> #include <setjmp.h>
#include <string.h> /* 3.1: strcpy(), strcat() */ #include <string.h> /* 3.1: strcpy(), strcat() */
#include <unistd.h> /* isatty() */ #include <unistd.h> /* isatty() */
#include "config.h" #include "config.h"
#include "machdep.h" #include "machdep.h"
@ -114,24 +114,22 @@ static char rcs_id[] = "$Id: saturn.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include "args.h" #include "args.h"
#include "debug.h" #include "debug.h"
/* Chf condition codes (main program only) */ /* Chf condition codes (main program only) */
#define CHF_MODULE_ID MAIN_CHF_MODULE_ID #define CHF_MODULE_ID MAIN_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
#define MAIN_M_COPYRIGHT 501 #define MAIN_M_COPYRIGHT 501
#define MAIN_M_LICENSE 502 #define MAIN_M_LICENSE 502
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf parameters - Do not change. Chf parameters - Do not change.
The ABNORMAL_EXIT_CODE is taken from stdlib.h (EXIT_FAILURE) The ABNORMAL_EXIT_CODE is taken from stdlib.h (EXIT_FAILURE)
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define CONDITION_STACK_SIZE 16 #define CONDITION_STACK_SIZE 16
#define HANDLER_STACK_SIZE 8 #define HANDLER_STACK_SIZE 8
#define ABNORMAL_EXIT_CODE EXIT_FAILURE #define ABNORMAL_EXIT_CODE EXIT_FAILURE
/* Conditional prefix and mandatory suffix to make a message catalog /* Conditional prefix and mandatory suffix to make a message catalog
name from argv[0] name from argv[0]
@ -139,31 +137,27 @@ static char rcs_id[] = "$Id: saturn.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
static const char cat_prefix[] = "./"; static const char cat_prefix[] = "./";
static const char cat_suffix[] = ".cat"; static const char cat_suffix[] = ".cat";
#define CAT_PREFIX_LEN (sizeof(cat_prefix)+1) #define CAT_PREFIX_LEN ( sizeof( cat_prefix ) + 1 )
#define CAT_SUFFIX_LEN (sizeof(cat_suffix)+1) #define CAT_SUFFIX_LEN ( sizeof( cat_suffix ) + 1 )
static void adjust_setlocale( void )
static void adjust_setlocale(void)
{ {
fprintf(stderr, fprintf( stderr, "saturn-W-locale probably bad; reverting to C locale\n" );
"saturn-W-locale probably bad; reverting to C locale\n");
putenv("LC_ALL=C"); putenv( "LC_ALL=C" );
putenv("LC_COLLATE=C"); putenv( "LC_COLLATE=C" );
putenv("LC_CTYPE=C"); putenv( "LC_CTYPE=C" );
putenv("LC_MESSAGES=C"); putenv( "LC_MESSAGES=C" );
putenv("LC_MONETARY=C"); putenv( "LC_MONETARY=C" );
putenv("LC_NUMERIC=C"); putenv( "LC_NUMERIC=C" );
putenv("LC_TIME=C"); putenv( "LC_TIME=C" );
putenv("LANG=C"); putenv( "LANG=C" );
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
.title : main .title : main
@ -182,98 +176,89 @@ static void adjust_setlocale(void)
- made Chf initialization more robust with respect to bad locales - made Chf initialization more robust with respect to bad locales
.- */ .- */
int main(int argc, char *argv[]) int main( int argc, char* argv[] )
{ {
char *cat_name; char* cat_name;
int st; int st;
int retry = 0; int retry = 0;
if((cat_name = malloc(strlen(argv[0])+CAT_PREFIX_LEN+CAT_SUFFIX_LEN+1)) if ( ( cat_name = malloc( strlen( argv[ 0 ] ) + CAT_PREFIX_LEN + CAT_SUFFIX_LEN + 1 ) ) == NULL ) {
== NULL) fprintf( stderr, "saturn-E-cat_name initialization failed\n" );
{ exit( ABNORMAL_EXIT_CODE );
fprintf(stderr, "saturn-E-cat_name initialization failed\n");
exit(ABNORMAL_EXIT_CODE);
} }
/* Generate catalog name, without optional prefix */ /* Generate catalog name, without optional prefix */
strcpy(cat_name, argv[0]); strcpy( cat_name, argv[ 0 ] );
strcat(cat_name, cat_suffix); strcat( cat_name, cat_suffix );
/* 3.15: Retry the initialization steps below two times; before trying /* 3.15: Retry the initialization steps below two times; before trying
the second time, adjust the setlocale() environment variables the second time, adjust the setlocale() environment variables
with adjust_setlocale() with adjust_setlocale()
*/ */
while(retry < 2) while ( retry < 2 ) {
{ /* Chf initialization with msgcat subsystem; notice that on
/* Chf initialization with msgcat subsystem; notice that on some systems (e.g. Digital UNIX) catopen() can succeed even
some systems (e.g. Digital UNIX) catopen() can succeed even if it was not able to open the right message catalog;
if it was not able to open the right message catalog; better try it now.
better try it now. */
*/ if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
if((st = ChfMsgcatInit( CHF_DEFAULT, /* Options */
argv[0], /* Application's name */ cat_name, /* Name of the message catalog */
CHF_DEFAULT, /* Options */ CONDITION_STACK_SIZE, /* Size of the condition stack */
cat_name, /* Name of the message catalog */ HANDLER_STACK_SIZE, /* Size of the handler stack */
CONDITION_STACK_SIZE, /* Size of the condition stack */ ABNORMAL_EXIT_CODE /* Abnormal exit code */
HANDLER_STACK_SIZE, /* Size of the handler stack */ ) ) != CHF_S_OK ||
ABNORMAL_EXIT_CODE /* Abnormal exit code */ ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL ) == NULL )
)) != CHF_S_OK fprintf( stderr, "saturn-E-Primary Chf initialization failed (%d)\n", st );
||
ChfGetMessage(CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL) == NULL)
fprintf(stderr,
"saturn-E-Primary Chf initialization failed (%d)\n", st);
else else
break; break;
/* Bring down Chf before initializing it again */ /* Bring down Chf before initializing it again */
if(st == CHF_S_OK) ChfExit(); if ( st == CHF_S_OK )
ChfExit();
/* Try alternate message catalog name (with prefix) */ /* Try alternate message catalog name (with prefix) */
strcpy(cat_name, cat_prefix); strcpy( cat_name, cat_prefix );
strcat(cat_name, argv[0]); strcat( cat_name, argv[ 0 ] );
strcat(cat_name, cat_suffix); strcat( cat_name, cat_suffix );
if((st = ChfMsgcatInit( if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
argv[0], /* Application's name */ CHF_DEFAULT, /* Options */
CHF_DEFAULT, /* Options */ cat_name, /* Name of the message catalog */
cat_name, /* Name of the message catalog */ CONDITION_STACK_SIZE, /* Size of the condition stack */
CONDITION_STACK_SIZE, /* Size of the condition stack */ HANDLER_STACK_SIZE, /* Size of the handler stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */ ABNORMAL_EXIT_CODE /* Abnormal exit code */
ABNORMAL_EXIT_CODE /* Abnormal exit code */ ) ) != CHF_S_OK ||
)) != CHF_S_OK ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL ) == NULL )
|| fprintf( stderr, "saturn-E-Alternate Chf initialization failed (%d)\n", st );
ChfGetMessage(CHF_MODULE_ID, MAIN_M_COPYRIGHT, NULL) == NULL)
fprintf(stderr,
"saturn-E-Alternate Chf initialization failed (%d)\n",
st);
else else
break; break;
/* Bring down Chf before initializing it again */ /* Bring down Chf before initializing it again */
if(st == CHF_S_OK) ChfExit(); if ( st == CHF_S_OK )
ChfExit();
/* Attempt to adjust setlocale() environment variables */ /* Attempt to adjust setlocale() environment variables */
if(retry++ == 0) adjust_setlocale(); if ( retry++ == 0 )
adjust_setlocale();
} }
if(retry == 2) if ( retry == 2 ) {
{ fprintf( stderr, "saturn-F-Application aborted\n" );
fprintf(stderr, "saturn-F-Application aborted\n"); exit( ABNORMAL_EXIT_CODE );
exit(ABNORMAL_EXIT_CODE);
} }
/* cat_name no longer needed */ /* cat_name no longer needed */
free(cat_name); free( cat_name );
/* 3.9: Print out MAIN_M_COPYRIGHT and MAIN_M_LICENSE on stdout now */ /* 3.9: Print out MAIN_M_COPYRIGHT and MAIN_M_LICENSE on stdout now */
fprintf(stdout, ChfGetMessage(CHF_MODULE_ID, MAIN_M_COPYRIGHT, ""), fprintf( stdout, ChfGetMessage( CHF_MODULE_ID, MAIN_M_COPYRIGHT, "" ), "$Revision: 4.1 $" );
"$Revision: 4.1 $"); fprintf( stdout, ChfGetMessage( CHF_MODULE_ID, MAIN_M_LICENSE, "" ) );
fprintf(stdout, ChfGetMessage(CHF_MODULE_ID, MAIN_M_LICENSE, ""));
/* Initialize GUI and associated lcd display emulation module */ /* Initialize GUI and associated lcd display emulation module */
InitializeGui(argc, argv); InitializeGui( argc, argv );
/* Initialize serial port emulation. /* Initialize serial port emulation.
This function returns the name of the slave side of the pty; This function returns the name of the slave side of the pty;
@ -281,30 +266,28 @@ int main(int argc, char *argv[])
a condition containing the same information and displays the pty name a condition containing the same information and displays the pty name
on the main emulator's window. on the main emulator's window.
*/ */
(void)SerialInit(); ( void )SerialInit();
/* Initialize emulator proper */ /* Initialize emulator proper */
EmulatorInit(); EmulatorInit();
/* 3.15: Repeat copyright message on GUI if stdout is not a tty */ /* 3.15: Repeat copyright message on GUI if stdout is not a tty */
if(! isatty(fileno(stdout))) if ( !isatty( fileno( stdout ) ) ) {
{ ChfCondition MAIN_M_LICENSE, CHF_INFO ChfEnd;
ChfCondition MAIN_M_LICENSE, CHF_INFO ChfEnd; ChfCondition MAIN_M_COPYRIGHT, CHF_INFO, "$Revision: 4.1 $" ChfEnd;
ChfCondition MAIN_M_COPYRIGHT, CHF_INFO, "$Revision: 4.1 $" ChfEnd;
ChfSignal(); ChfSignal();
} }
if(args.monitor) if ( args.monitor ) {
{ /* Invoke Monitor */
/* Invoke Monitor */ void Monitor( void );
void Monitor(void); Monitor();
Monitor();
} }
else else
/* Call Emulator directly */ /* Call Emulator directly */
Emulator(); Emulator();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

File diff suppressed because it is too large Load diff

View file

@ -117,145 +117,135 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Data type definitions - require config.h, machdep.h, cpu.h Data type definitions - require config.h, machdep.h, cpu.h
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define N_MOD 6 #define N_MOD 6
#define N_PAGE_TABLE_ENTRIES 16384 #define N_PAGE_TABLE_ENTRIES 16384
#define N_ROM_SIZE 512*1024*2 #define N_ROM_SIZE 512 * 1024 * 2
#define N_RAM_SIZE 128*1024*2 #define N_RAM_SIZE 128 * 1024 * 2
#define N_FLASH_SIZE_49 2048*1024*2 /* 3.2 */ #define N_FLASH_SIZE_49 2048 * 1024 * 2 /* 3.2 */
#define N_RAM_SIZE_49 512*1024*2 /* 3.2 */ #define N_RAM_SIZE_49 512 * 1024 * 2 /* 3.2 */
/* 2.4: Port_1 (CE2) size */ /* 2.4: Port_1 (CE2) size */
#define N_PORT_1_SIZE 128*1024*2 #define N_PORT_1_SIZE 128 * 1024 * 2
/* 2.4: Port_2 (NCE3) size */ /* 2.4: Port_2 (NCE3) size */
#define N_PORT_2_SIZE N_PORT_2_BANK*128*1024*2 #define N_PORT_2_SIZE N_PORT_2_BANK * 128 * 1024 * 2
#define N_HDW_SIZE 256 #define N_HDW_SIZE 256
#define MOD_MAP_CHECK_OB_SIZE 128 #define MOD_MAP_CHECK_OB_SIZE 128
#define MOD_MAP_TABLE_OB_SIZE 512 #define MOD_MAP_TABLE_OB_SIZE 512
/* 2.7: Number of entries in module config cache */ /* 2.7: Number of entries in module config cache */
#define N_MOD_CACHE_ENTRIES 8 #define N_MOD_CACHE_ENTRIES 8
#define MOD_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
#define MOD_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macros Macros
ModAddress returns the base address of a page, given its number (Address) ModAddress returns the base address of a page, given its number (Address)
ModOffset returns the page offset of an address (int) ModOffset returns the page offset of an address (int)
ModPage returns the page number of an address (Address) ModPage returns the page number of an address (Address)
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define ModAddress(page) ((Address)(page) << 6) #define ModAddress( page ) ( ( Address )( page ) << 6 )
#define ModPage(address) ((int)(((address) & 0xFFFC0) >> 6)) #define ModPage( address ) ( ( int )( ( ( address ) & 0xFFFC0 ) >> 6 ) )
#define ModOffset(address) ((address) & 0x0003F) #define ModOffset( address ) ( ( address ) & 0x0003F )
/* /*
ModDescription ModDescription
This const array contains an entry for each peripheral module connected This const array contains an entry for each peripheral module connected
to the peripheral bus of the Saturn CPU; the entry describes the to the peripheral bus of the Saturn CPU; the entry describes the
characteristics of the module. characteristics of the module.
name: the mnemonic name of the module; the Saturn CPU doesn't name: the mnemonic name of the module; the Saturn CPU doesn't
actually use this information, but it's still useful during actually use this information, but it's still useful during
debugging. debugging.
id: the ID of the module, returned by the C=ID instruction id: the ID of the module, returned by the C=ID instruction
when the module is unconfigured. when the module is unconfigured.
access_prio: the access priority of the module, when the address spaces of access_prio: the access priority of the module, when the address spaces of
more than one module overlap. Higher values correspond to more than one module overlap. Higher values correspond to
higher priorities. higher priorities.
The configuration priority of the module, when there is more The configuration priority of the module, when there is more
than one unconfigured module on the peripheral bus, is than one unconfigured module on the peripheral bus, is
determined implicitly by the order in which the module determined implicitly by the order in which the module
descriptions into the array. The modules that come first descriptions into the array. The modules that come first
in the array are configured first. in the array are configured first.
init: this function is called, without arguments, during VM startup init: this function is called, without arguments, during VM startup
to initialize the device. For example, the initialization to initialize the device. For example, the initialization
function for the ROM module will read the ROM image from function for the ROM module will read the ROM image from
disk and store them into the module status structure. disk and store them into the module status structure.
read: this function reads a nibble from the module. It receives the read: this function reads a nibble from the module. It receives the
relative address of the nibble to be read. The read function relative address of the nibble to be read. The read function
can return an interrupt request for the CPU. can return an interrupt request for the CPU.
write: this function writes a nibble to the module. It receives the write: this function writes a nibble to the module. It receives the
relative address and the value of the nibble to be written. relative address and the value of the nibble to be written.
The write function can return an interrupt request for the CPU. The write function can return an interrupt request for the CPU.
r_config: this flag contains the configuration status of the module after r_config: this flag contains the configuration status of the module after
a bus reset. If the after-reset configuration status is a bus reset. If the after-reset configuration status is
MOD_CONFIGURED, the module can never be unconfigured. MOD_CONFIGURED, the module can never be unconfigured.
r_abs_base_addr: absolute base address of the module after a bus reset. r_abs_base_addr: absolute base address of the module after a bus reset.
It should be set only if the module is at least partially It should be set only if the module is at least partially
configured automatically after a bus reset. configured automatically after a bus reset.
r_size: size of the address window of the module after a bus reset. r_size: size of the address window of the module after a bus reset.
It should be set only if the module is at least partially It should be set only if the module is at least partially
configured automatically after a bus reset. configured automatically after a bus reset.
map_flags: special map flags: map_flags: special map flags:
MOD_MAP_FLAGS_ABS pass absolute addresses to module MOD_MAP_FLAGS_ABS pass absolute addresses to module
read/write functions read/write functions
Notice that the current implementation requires that the index of Notice that the current implementation requires that the index of
the HDW registers in the mod_description table must be fixed the HDW registers in the mod_description table must be fixed
and equal to MOD_HDW_INDEX... this is unfortunate. and equal to MOD_HDW_INDEX... this is unfortunate.
*/ */
typedef void (*ModInitFunction)(void); typedef void ( *ModInitFunction )( void );
typedef void (*ModSaveFunction)(void); typedef void ( *ModSaveFunction )( void );
typedef Nibble (*ModReadFunction)(Address rel_addr); typedef Nibble ( *ModReadFunction )( Address rel_addr );
typedef void (*ModWriteFunction)(Address rel_addr, Nibble data); typedef void ( *ModWriteFunction )( Address rel_addr, Nibble data );
enum ModConfig enum ModConfig { MOD_UNCONFIGURED, MOD_SIZE_CONFIGURED, MOD_CONFIGURED };
{
MOD_UNCONFIGURED, struct ModDescriptionEntry {
MOD_SIZE_CONFIGURED, char* name;
MOD_CONFIGURED Address id;
int access_prio;
#define MOD_MIN_ACCESS_PRIO ( -1 )
ModInitFunction init;
ModSaveFunction save;
ModReadFunction read;
ModWriteFunction write;
enum ModConfig r_config;
Address r_abs_base_addr;
Address r_size;
int map_flags; /* 3.3 */
#define MOD_MAP_FLAGS_ABS 0x1 /* Abs addresses to r/w */
}; };
struct ModDescriptionEntry #define MOD_HDW_INDEX 1
{ typedef const struct ModDescriptionEntry ModDescription[ N_MOD ];
char *name;
Address id;
int access_prio;
#define MOD_MIN_ACCESS_PRIO (-1)
ModInitFunction init;
ModSaveFunction save;
ModReadFunction read;
ModWriteFunction write;
enum ModConfig r_config;
Address r_abs_base_addr;
Address r_size;
int map_flags; /* 3.3 */
#define MOD_MAP_FLAGS_ABS 0x1 /* Abs addresses to r/w */
};
#define MOD_HDW_INDEX 1
typedef const struct ModDescriptionEntry ModDescription[N_MOD];
/* /*
ModMapInfo ModMapInfo
This array contains an entry for each peripheral module connected This array contains an entry for each peripheral module connected
to the peripheral bus of the Saturn CPU; the entry describes the to the peripheral bus of the Saturn CPU; the entry describes the
@ -264,41 +254,39 @@ typedef const struct ModDescriptionEntry ModDescription[N_MOD];
config: contains the current configuration status of the module. config: contains the current configuration status of the module.
abs_base_addr: contains the current absolute base address of the module. abs_base_addr: contains the current absolute base address of the module.
It's valid only if the module is currently configured. It's valid only if the module is currently configured.
size: contains the current size of the address window of the module. size: contains the current size of the address window of the module.
It's valid only if the module is currently configured. It's valid only if the module is currently configured.
*/ */
struct ModMapInfoEntry struct ModMapInfoEntry {
{ enum ModConfig config;
enum ModConfig config; Address abs_base_addr;
Address abs_base_addr; Address size;
Address size;
}; };
typedef struct ModMapInfoEntry ModMapInfo[N_MOD]; typedef struct ModMapInfoEntry ModMapInfo[ N_MOD ];
/* /*
ModPageTable ModPageTable
This array contains an entry (of type ModPageTableEntry) for each 'page' This array contains an entry (of type ModPageTableEntry) for each 'page'
(of size #40 nibbles) of the Saturn CPU physical address space. For (of size #40 nibbles) of the Saturn CPU physical address space. For
each page, the following information is stored: each page, the following information is stored:
index: the index of the module that responds to the address range of index: the index of the module that responds to the address range of
the page in the ModDescription table.The special value the page in the ModDescription table.The special value
MOD_NO_MOD_INDEX indicates that no module responds to the MOD_NO_MOD_INDEX indicates that no module responds to the
address range. address range.
rel_base_addr: the relative base address of the page in the address rel_base_addr: the relative base address of the page in the address
space of the module that responds to the address range of space of the module that responds to the address range of
the page, if any. the page, if any.
read, write: the read/write functions of the module that responds to the read, write: the read/write functions of the module that responds to the
address range of the page, if any. address range of the page, if any.
Relative address calculation for module access Relative address calculation for module access
The Saturn Physical Address (SPA) is divided into two portions: The Saturn Physical Address (SPA) is divided into two portions:
@ -315,18 +303,16 @@ typedef struct ModMapInfoEntry ModMapInfo[N_MOD];
is called. is called.
*/ */
struct ModPageTableEntry struct ModPageTableEntry {
{ int index;
int index; #define MOD_NO_MOD_INDEX ( -1 )
#define MOD_NO_MOD_INDEX (-1)
Address rel_base_addr; Address rel_base_addr;
ModReadFunction read; ModReadFunction read;
ModWriteFunction write; ModWriteFunction write;
}; };
typedef struct ModPageTableEntry ModPageTable[N_PAGE_TABLE_ENTRIES]; typedef struct ModPageTableEntry ModPageTable[ N_PAGE_TABLE_ENTRIES ];
/* struct ModCache (2.7) /* struct ModCache (2.7)
@ -359,58 +345,53 @@ typedef struct ModPageTableEntry ModPageTable[N_PAGE_TABLE_ENTRIES];
The .link field links all cached struct ModMap together. The .link field links all cached struct ModMap together.
*/ */
struct ModCacheTableEntry struct ModCacheTableEntry {
{
Address tag; Address tag;
struct ModMap *map_ptr; struct ModMap* map_ptr;
}; };
struct ModCache struct ModCache {
{ struct ModCacheTableEntry config[ N_MOD_CACHE_ENTRIES ];
struct ModCacheTableEntry config[N_MOD_CACHE_ENTRIES];
int victim; int victim;
struct ModMap *(unconfig[N_MOD]); struct ModMap*( unconfig[ N_MOD ] );
int config_point; int config_point;
int ref_count; int ref_count;
struct ModMap *link; struct ModMap* link;
}; };
/* /*
struct ModMap struct ModMap
This structure contains all the mapping information about the peripheral This structure contains all the mapping information about the peripheral
modules of the Saturn CPU. Its components are: modules of the Saturn CPU. Its components are:
map_info: this array describes the dynamic mapping information of map_info: this array describes the dynamic mapping information of
each module connected to the Saturn peripheral bus. each module connected to the Saturn peripheral bus.
page_table: this array describes the current layout of the address space page_table: this array describes the current layout of the address space
of the Saturn CPU. of the Saturn CPU.
cache (2.7): this structure holds caching information used to speed up cache (2.7): this structure holds caching information used to speed up
module config/unconfig instructions module config/unconfig instructions
*/ */
struct ModMap struct ModMap {
{ ModMapInfo map_info;
ModMapInfo map_info; ModPageTable page_table;
ModPageTable page_table; struct ModCache cache;
struct ModCache cache;
}; };
/* /*
struct ModStatus struct ModStatus
This structure contains the actual status of all peripheral modules of the This structure contains the actual status of all peripheral modules of the
Saturn CPU. The status of all modules is centralized to allow any device Saturn CPU. The status of all modules is centralized to allow any device
to easily access the status of other devices. to easily access the status of other devices.
struct ModHdw struct ModHdw
This substructure contains the status of all peripheral devices controlled This substructure contains the status of all peripheral devices controlled
by the hdw module. by the hdw module.
@ -429,188 +410,177 @@ struct ModMap
configuration-specific ROM/RAM emulation module. configuration-specific ROM/RAM emulation module.
*/ */
struct ModHdw48Accel struct ModHdw48Accel {
{ XAddress bs_address; /* Bank Switcher ext. address */
XAddress bs_address; /* Bank Switcher ext. address */
}; };
struct ModHdw49Accel struct ModHdw49Accel {
{ XAddress view[ 2 ]; /* Base of Flash views */
XAddress view[2]; /* Base of Flash views */
}; };
struct ModHdw struct ModHdw {
{ Nibble hdw[ N_HDW_SIZE ]; /* HDW registers */
Nibble hdw[N_HDW_SIZE]; /* HDW registers */
/* LCD driver */ /* LCD driver */
Address lcd_base_addr; /* LCD driver base address */ Address lcd_base_addr; /* LCD driver base address */
int lcd_on; /* LCD driver enable flag */ int lcd_on; /* LCD driver enable flag */
int lcd_contrast; /* LCD contrast value */ int lcd_contrast; /* LCD contrast value */
int lcd_vlc; /* LCD vertical line count */ int lcd_vlc; /* LCD vertical line count */
int lcd_offset; /* LCD horizontal offset */ int lcd_offset; /* LCD horizontal offset */
int lcd_line_offset; /* LCD line offset */ int lcd_line_offset; /* LCD line offset */
Address lcd_menu_addr; /* LCD menu base address */ Address lcd_menu_addr; /* LCD menu base address */
int lcd_ann; /* LCD annunciators status */ int lcd_ann; /* LCD annunciators status */
/* Timers */ /* Timers */
Nibble t1_ctrl; /* Timer 1 control */ Nibble t1_ctrl; /* Timer 1 control */
#define T1_CTRL_EXTRA 0x01 #define T1_CTRL_EXTRA 0x01
#define T1_CTRL_INT 0x02 #define T1_CTRL_INT 0x02
#define T1_CTRL_WAKE 0x04 #define T1_CTRL_WAKE 0x04
#define T1_CTRL_SREQ 0x08 #define T1_CTRL_SREQ 0x08
Nibble t2_ctrl; /* Timer 2 control */ Nibble t2_ctrl; /* Timer 2 control */
#define T2_CTRL_TRUN 0x01 #define T2_CTRL_TRUN 0x01
#define T2_CTRL_INT 0x02 #define T2_CTRL_INT 0x02
#define T2_CTRL_WAKE 0x04 #define T2_CTRL_WAKE 0x04
#define T2_CTRL_SREQ 0x08 #define T2_CTRL_SREQ 0x08
Nibble t1_val; /* Timer 1 value */ Nibble t1_val; /* Timer 1 value */
int32 t2_val; /* Timer 2 value */ int32 t2_val; /* Timer 2 value */
/* 2.4: New member required to support Port emulation */ /* 2.4: New member required to support Port emulation */
Nibble card_status; /* Card status (hdw register 0x0F) */ Nibble card_status; /* Card status (hdw register 0x0F) */
#define NCE3_CARD_PRESENT 0x01 #define NCE3_CARD_PRESENT 0x01
#define CE2_CARD_PRESENT 0x02 #define CE2_CARD_PRESENT 0x02
#define NCE3_CARD_WE 0x04 #define NCE3_CARD_WE 0x04
#define CE2_CARD_WE 0x08 #define CE2_CARD_WE 0x08
/* 2.4: Hw configuration-specific members used as accelerators; /* 2.4: Hw configuration-specific members used as accelerators;
accel_valid is non-zero if the accelerators are valid accel_valid is non-zero if the accelerators are valid
*/ */
int accel_valid; int accel_valid;
union union {
{ struct ModHdw48Accel a48;
struct ModHdw48Accel a48; struct ModHdw49Accel a49;
struct ModHdw49Accel a49; } accel;
} accel;
/* 2.5: Serial port buffer registers */ /* 2.5: Serial port buffer registers */
int8 serial_rbr; int8 serial_rbr;
int8 serial_tbr; int8 serial_tbr;
/* Misc */ /* Misc */
int16 crc; /* CRC */ int16 crc; /* CRC */
}; };
struct ModStatus struct ModStatus {
{ struct ModHdw hdw; /* HDW status */
struct ModHdw hdw; /* HDW status */
}; };
struct ModStatus_48 struct ModStatus_48 {
{ Nibble rom[ N_ROM_SIZE ]; /* Internal ROM */
Nibble rom[N_ROM_SIZE]; /* Internal ROM */ Nibble ram[ N_RAM_SIZE ]; /* Internal RAM */
Nibble ram[N_RAM_SIZE]; /* Internal RAM */ Nibble port_1[ N_PORT_1_SIZE ]; /* 2.4: Port_1 (CE2) storage */
Nibble port_1[N_PORT_1_SIZE]; /* 2.4: Port_1 (CE2) storage */
/* 2.4: Port_2 (NCE3) storage; only needed if N_PORT_2_BANK is defined */ /* 2.4: Port_2 (NCE3) storage; only needed if N_PORT_2_BANK is defined */
#ifdef N_PORT_2_BANK #ifdef N_PORT_2_BANK
Nibble port_2[N_PORT_2_SIZE]; Nibble port_2[ N_PORT_2_SIZE ];
#endif #endif
}; };
struct ModStatus_49 struct ModStatus_49 {
{ Nibble flash[ N_FLASH_SIZE_49 ]; /* Internal Flash ROM */
Nibble flash[N_FLASH_SIZE_49]; /* Internal Flash ROM */ Nibble ram[ N_RAM_SIZE_49 ]; /* Internal RAM */
Nibble ram[N_RAM_SIZE_49]; /* Internal RAM */ Nibble *ce2, *nce3; /* ERAM bases */
Nibble *ce2, *nce3; /* ERAM bases */
}; };
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Global variables Global variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
extern struct ModStatus mod_status; extern struct ModStatus mod_status;
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define MOD_I_CALLED 101 /* Function %s called */ #define MOD_I_CALLED 101 /* Function %s called */
#define MOD_I_INITIALIZING 102 /* Initializing module %s */ #define MOD_I_INITIALIZING 102 /* Initializing module %s */
#define MOD_I_RESETTING 103 /* Resetting module %s */ #define MOD_I_RESETTING 103 /* Resetting module %s */
#define MOD_I_GET_ID 106 /* ModGetID returning %x */ #define MOD_I_GET_ID 106 /* ModGetID returning %x */
#define MOD_I_CONFIG 107 /* ModConfig %s %x %x completed */ #define MOD_I_CONFIG 107 /* ModConfig %s %x %x completed */
#define MOD_I_UNCONFIG 108 /* ModUnconfig %s %x %x completed */ #define MOD_I_UNCONFIG 108 /* ModUnconfig %s %x %x completed */
#define MOD_I_SAVING 109 /* Saving status of module %s */ #define MOD_I_SAVING 109 /* Saving status of module %s */
#define MOD_I_NOT_IMPLEMENTED 110 /* Function %s not implemented */ #define MOD_I_NOT_IMPLEMENTED 110 /* Function %s not implemented */
#define MOD_I_REVISION 111 /* Modules revision: %s */ #define MOD_I_REVISION 111 /* Modules revision: %s */
#define MOD_I_BS_ADDRESS 112 /* 2.4: Bank Switcher address: %x */ #define MOD_I_BS_ADDRESS 112 /* 2.4: Bank Switcher address: %x */
#define MOD_I_PORT_1_WP 113 /* 2.4: Port 1 is write protected */ #define MOD_I_PORT_1_WP 113 /* 2.4: Port 1 is write protected */
#define MOD_I_PORT_2_WP 114 /* 2.4: Port 2 is write protected */ #define MOD_I_PORT_2_WP 114 /* 2.4: Port 2 is write protected */
#define MOD_I_PERF_CTR 115 /* 2.7: Value of PerfCtr %s is %d */ #define MOD_I_PERF_CTR 115 /* 2.7: Value of PerfCtr %s is %d */
#define MOD_I_CACHED_UNCONFIG 116 /* 2.7: Cached ModUnconfig completed */ #define MOD_I_CACHED_UNCONFIG 116 /* 2.7: Cached ModUnconfig completed */
#define MOD_I_CACHED_CONFIG 117 /* 2.7: Cached ModConfig %x comp. */ #define MOD_I_CACHED_CONFIG 117 /* 2.7: Cached ModConfig %x comp. */
#define MOD_I_UNCONFIG_L_HIT 118 /* 2.7: Late unconfig hit */ #define MOD_I_UNCONFIG_L_HIT 118 /* 2.7: Late unconfig hit */
#define MOD_I_UNCONFIG_L_MISS 119 /* 2.7: Late unconfig miss */ #define MOD_I_UNCONFIG_L_MISS 119 /* 2.7: Late unconfig miss */
#define MOD_W_BAD_CONFIG 202 /* Bad ModConfig %x ignored */ #define MOD_W_BAD_CONFIG 202 /* Bad ModConfig %x ignored */
#define MOD_W_BAD_UNCONFIG 203 /* Bad ModUnconfig %x ignored */ #define MOD_W_BAD_UNCONFIG 203 /* Bad ModUnconfig %x ignored */
#define MOD_W_HDW_WRITE 204 /* Bad HdwWrite %x, %x */ #define MOD_W_HDW_WRITE 204 /* Bad HdwWrite %x, %x */
#define MOD_W_HDW_READ 205 /* Bad HdwRead %x */ #define MOD_W_HDW_READ 205 /* Bad HdwRead %x */
#define MOD_W_RESETTING_ALL 206 /* Resetting all modules */ #define MOD_W_RESETTING_ALL 206 /* Resetting all modules */
#define MOD_W_RAM_INIT 207 /* Can't initialize internal RAM */ #define MOD_W_RAM_INIT 207 /* Can't initialize internal RAM */
#define MOD_W_HDW_INIT 208 /* Can't initialize HDW */ #define MOD_W_HDW_INIT 208 /* Can't initialize HDW */
#define MOD_W_BAD_KEY 209 /* 2.1: Bad key %s ignored */ #define MOD_W_BAD_KEY 209 /* 2.1: Bad key %s ignored */
#define MOD_W_BAD_OUT_BIT 210 /* 2.1: Bad out_bit %x ignored */ #define MOD_W_BAD_OUT_BIT 210 /* 2.1: Bad out_bit %x ignored */
#define MOD_W_PORT_1_INIT 211 /* 2.4: Can't initialize Port 1 */ #define MOD_W_PORT_1_INIT 211 /* 2.4: Can't initialize Port 1 */
#define MOD_W_PORT_2_INIT 212 /* 2.4: Can't initialize Port 2 */ #define MOD_W_PORT_2_INIT 212 /* 2.4: Can't initialize Port 2 */
#define MOD_W_NO_VICTIM 213 /* 2.7: No cache victim; flush/retry */ #define MOD_W_NO_VICTIM 213 /* 2.7: No cache victim; flush/retry */
#define MOD_E_BAD_READ 301 /* Read unmapped addr %x */ #define MOD_E_BAD_READ 301 /* Read unmapped addr %x */
#define MOD_E_BAD_WRITE 302 /* Write unmapped addr %x datum %x */ #define MOD_E_BAD_WRITE 302 /* Write unmapped addr %x datum %x */
#define MOD_E_ROM_WRITE 303 /* Write into ROM addr %x datum %x */ #define MOD_E_ROM_WRITE 303 /* Write into ROM addr %x datum %x */
#define MOD_E_RAM_SAVE 304 /* Can't save internal RAM status */ #define MOD_E_RAM_SAVE 304 /* Can't save internal RAM status */
#define MOD_E_HDW_SAVE 305 /* Can't save HDW status */ #define MOD_E_HDW_SAVE 305 /* Can't save HDW status */
#define MOD_E_PORT_1_SAVE 306 /* 2.4: Can't save Port 1 status */ #define MOD_E_PORT_1_SAVE 306 /* 2.4: Can't save Port 1 status */
#define MOD_E_CE1_WRITE 307 /* 2.4: Ce1Write addr %x datum %x */ #define MOD_E_CE1_WRITE 307 /* 2.4: Ce1Write addr %x datum %x */
#define MOD_E_PORT_2_SAVE 308 /* 2.4: Can't save Port 2 status */ #define MOD_E_PORT_2_SAVE 308 /* 2.4: Can't save Port 2 status */
#define MOD_E_NCE3_READ 309 /* 2.4: Read from NCE3 addr %x */ #define MOD_E_NCE3_READ 309 /* 2.4: Read from NCE3 addr %x */
#define MOD_E_NCE3_WRITE 310 /* 2.4: Wr. to NCE3 addr %x datum %x */ #define MOD_E_NCE3_WRITE 310 /* 2.4: Wr. to NCE3 addr %x datum %x */
#define MOD_E_NO_MATCH 311 /* 3.2: Hw desription %s not found */ #define MOD_E_NO_MATCH 311 /* 3.2: Hw desription %s not found */
#define MOD_E_ROM_SAVE 312 /* 3.3: Can't save Flash ROM */ #define MOD_E_ROM_SAVE 312 /* 3.3: Can't save Flash ROM */
#define MOD_F_MAP_SAVE 401 /* Can't save mod_map information */ #define MOD_F_MAP_SAVE 401 /* Can't save mod_map information */
#define MOD_F_ROM_INIT 402 /* Can't initialize internal ROM */ #define MOD_F_ROM_INIT 402 /* Can't initialize internal ROM */
#define MOD_F_MAP_ALLOC 403 /* Dynamic map allocation failed */ #define MOD_F_MAP_ALLOC 403 /* Dynamic map allocation failed */
#define MOD_F_BAD_ALLOC_C 404 /* 2.7: Bad alloc_c %d aft FlushCache*/ #define MOD_F_BAD_ALLOC_C 404 /* 2.7: Bad alloc_c %d aft FlushCache*/
#define MOD_F_CHAIN_CORRUPTED 405 /* 2.7: ModMap chain corrupted */ #define MOD_F_CHAIN_CORRUPTED 405 /* 2.7: ModMap chain corrupted */
#define MOD_F_NO_VICTIM 406 /* 2.7: No cache victim after flush */ #define MOD_F_NO_VICTIM 406 /* 2.7: No cache victim after flush */
#define MOD_F_MOD_STATUS_ALLOC 407 /* 3.2: ModStatus_xx alloc failed %d */ #define MOD_F_MOD_STATUS_ALLOC 407 /* 3.2: ModStatus_xx alloc failed %d */
#define MOD_F_NO_DESCRIPTION 408 /* 3.2: No module description */ #define MOD_F_NO_DESCRIPTION 408 /* 3.2: No module description */
#define MOD_M_NOT_MAPPED 501 /* Address %x not mapped */ #define MOD_M_NOT_MAPPED 501 /* Address %x not mapped */
#define MOD_M_MAPPED 502 /* Address %x mapped to %s:%x */ #define MOD_M_MAPPED 502 /* Address %x mapped to %s:%x */
#define MOD_M_MAP_TABLE_TITLE 503 /* */ #define MOD_M_MAP_TABLE_TITLE 503 /* */
#define MOD_M_MAP_TABLE_ROW 504 /* %s %x %x %s */ #define MOD_M_MAP_TABLE_ROW 504 /* %s %x %x %s */
#define MOD_M_MAP_CONFIGURED 505 /* Configured */ #define MOD_M_MAP_CONFIGURED 505 /* Configured */
#define MOD_M_MAP_SZ_CONFIGURED 506 /* Size configured */ #define MOD_M_MAP_SZ_CONFIGURED 506 /* Size configured */
#define MOD_M_MAP_UNCONFIGURED 507 /* Unconfigured */ #define MOD_M_MAP_UNCONFIGURED 507 /* Unconfigured */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Initialization */ /* Initialization */
void ModSelectDescription(const char *hw); void ModSelectDescription( const char* hw );
void ModRegisterDescription(ModDescription p); void ModRegisterDescription( ModDescription p );
void ModInit(void); void ModInit( void );
void ModSave(void); void ModSave( void );
void ModReset(void); void ModReset( void );
/* Configuration */ /* Configuration */
Address ModGetID(void); Address ModGetID( void );
void ModConfig(Address config_info); void ModConfig( Address config_info );
void ModUnconfig(Address unconfig_info); void ModUnconfig( Address unconfig_info );
/* Read/Write */ /* Read/Write */
Nibble FetchNibble(Address addr); Nibble FetchNibble( Address addr );
Nibble ReadNibble(Address addr); Nibble ReadNibble( Address addr );
void WriteNibble(Address addr, Nibble datum); void WriteNibble( Address addr, Nibble datum );
/* Monitor */ /* Monitor */
void ModMapCheck(Address addr, char ob[MOD_MAP_CHECK_OB_SIZE]); void ModMapCheck( Address addr, char ob[ MOD_MAP_CHECK_OB_SIZE ] );
void ModMapTable(char ob[MOD_MAP_TABLE_OB_SIZE]); void ModMapTable( char ob[ MOD_MAP_TABLE_OB_SIZE ] );

View file

@ -85,232 +85,229 @@ static char rcs_id[] = "$Id: monitor.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $"
#include "args.h" #include "args.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID CPU_CHF_MODULE_ID #define CHF_MODULE_ID CPU_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macro & Data type definitions Macro & Data type definitions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define LINE_BUFFER_SIZE 512 #define LINE_BUFFER_SIZE 512
#define TOK_DELIMITERS " \t\n" #define TOK_DELIMITERS " \t\n"
#define ADDRESS_FMT "%x" #define ADDRESS_FMT "%x"
#define COUNT_FMT "%d" #define COUNT_FMT "%d"
#define PROMPT "> " #define PROMPT "> "
#define OK 0 #define OK 0
#define FAILED 1 #define FAILED 1
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private functions - Command line parse Private functions - Command line parse
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Read an Address from the command line */ /* Read an Address from the command line */
static int ReadHexAddress(Address *addr) static int ReadHexAddress( Address* addr )
{ {
char *p = strtok((char *)NULL, TOK_DELIMITERS); char* p = strtok( ( char* )NULL, TOK_DELIMITERS );
return (p == (char *)NULL || return ( p == ( char* )NULL || sscanf( p, ADDRESS_FMT, addr ) != 1 ) ? FAILED : OK;
sscanf(p, ADDRESS_FMT, addr) != 1) ? FAILED : OK;
} }
/* Read a Nibble from the command line */ /* Read a Nibble from the command line */
static int ReadHexDatum(Nibble *n) static int ReadHexDatum( Nibble* n )
{ {
Address addr; Address addr;
int st; int st;
if((st = ReadHexAddress(&addr)) == OK) *n = (Nibble)addr; if ( ( st = ReadHexAddress( &addr ) ) == OK )
return st; *n = ( Nibble )addr;
return st;
} }
/* Read a DECIMAL count from the command line */ /* Read a DECIMAL count from the command line */
static int ReadCount(int *count) static int ReadCount( int* count )
{ {
char *p = strtok((char *)NULL, TOK_DELIMITERS); char* p = strtok( ( char* )NULL, TOK_DELIMITERS );
return (p == (char *)NULL || sscanf(p, COUNT_FMT, count) != 1 || return ( p == ( char* )NULL || sscanf( p, COUNT_FMT, count ) != 1 || *count <= 0 ) ? FAILED : OK;
*count <= 0) ? FAILED : OK;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private functions - Command execution Private functions - Command execution
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Run the emulator; this function exits normally only when an /* Run the emulator; this function exits normally only when an
EmulatorIntRequest() is posted and satisfied EmulatorIntRequest() is posted and satisfied
*/ */
static int run(void) static int run( void )
{ {
Emulator(); Emulator();
return OK; return OK;
} }
/* Set the debug level */ /* Set the debug level */
static int debug(void) static int debug( void )
{ {
Address addr; Address addr;
if(ReadHexAddress(&addr)) return FAILED; if ( ReadHexAddress( &addr ) )
SetDebugLevel((int)addr); return FAILED;
return OK; SetDebugLevel( ( int )addr );
return OK;
} }
/* Check the mapping of an Address and print */ /* Check the mapping of an Address and print */
static int map_check(void) static int map_check( void )
{ {
Address addr; Address addr;
char ob[MOD_MAP_CHECK_OB_SIZE]; char ob[ MOD_MAP_CHECK_OB_SIZE ];
if(ReadHexAddress(&addr)) return FAILED; if ( ReadHexAddress( &addr ) )
ModMapCheck(addr, ob); return FAILED;
puts(ob); ModMapCheck( addr, ob );
return OK; puts( ob );
return OK;
} }
/* Print the current module map table */ /* Print the current module map table */
static int map(void) static int map( void )
{ {
char ob[MOD_MAP_TABLE_OB_SIZE]; char ob[ MOD_MAP_TABLE_OB_SIZE ];
ModMapTable(ob); ModMapTable( ob );
puts(ob); puts( ob );
return OK; return OK;
} }
/* Write nibbles into memory */ /* Write nibbles into memory */
static int w(void) static int w( void )
{ {
Address addr; Address addr;
Nibble n; Nibble n;
if(ReadHexAddress(&addr)) return FAILED; if ( ReadHexAddress( &addr ) )
while(ReadHexDatum(&n) == OK) WriteNibble(addr++, n); return FAILED;
return OK; while ( ReadHexDatum( &n ) == OK )
WriteNibble( addr++, n );
return OK;
} }
/* Read nibbles from memory */ /* Read nibbles from memory */
static int r(void) static int r( void )
{ {
Address addr; Address addr;
int count; int count;
if(ReadHexAddress(&addr)) return FAILED; if ( ReadHexAddress( &addr ) )
if(ReadCount(&count)) count=1; return FAILED;
if ( ReadCount( &count ) )
count = 1;
while(count-->0) while ( count-- > 0 ) {
{ printf( "A_%05X\t%X\n", addr, ( int )FetchNibble( addr ) );
printf("A_%05X\t%X\n", addr, (int)FetchNibble(addr)); addr++;
addr++; }
}
return OK; return OK;
} }
/* Disassemble */ /* Disassemble */
static int d(void) static int d( void )
{ {
Address addr; Address addr;
int count; int count;
char ob[DISASSEMBLE_OB_SIZE]; char ob[ DISASSEMBLE_OB_SIZE ];
if(ReadHexAddress(&addr)) return FAILED; if ( ReadHexAddress( &addr ) )
if(ReadCount(&count)) count=1; return FAILED;
if ( ReadCount( &count ) )
count = 1;
while(count-->0) while ( count-- > 0 ) {
{ addr = Disassemble( addr, ob );
addr = Disassemble(addr, ob); puts( ob );
puts(ob); }
}
return OK; return OK;
} }
/* Print CPU status */ /* Print CPU status */
static int cpu(void) static int cpu( void )
{ {
char ob[DUMP_CPU_STATUS_OB_SIZE]; char ob[ DUMP_CPU_STATUS_OB_SIZE ];
DumpCpuStatus(ob); DumpCpuStatus( ob );
puts(ob); puts( ob );
return OK; return OK;
} }
/* Reset CPU */ /* Reset CPU */
static int reset(void) static int reset( void )
{ {
CpuReset(); CpuReset();
return OK; return OK;
} }
/* Save & Exit */ /* Save & Exit */
static int mon_exit(void) static int mon_exit( void )
{ {
ModSave(); ModSave();
CpuSave(); CpuSave();
exit(EXIT_SUCCESS); exit( EXIT_SUCCESS );
return OK; /* 3.1: Keep compiler happy */ return OK; /* 3.1: Keep compiler happy */
} }
/* Quit without saving */ /* Quit without saving */
static int mon_quit(void) static int mon_quit( void )
{ {
exit(EXIT_SUCCESS); exit( EXIT_SUCCESS );
return OK; /* 3.1: Keep compiler happy */ return OK; /* 3.1: Keep compiler happy */
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Command table Command table
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
struct TEntry struct TEntry {
{ char* name;
char *name; char* desc;
char *desc; int ( *function )( void );
int (*function)(void);
}; };
#define TableSize(t) (sizeof(t)/sizeof(struct TEntry)) #define TableSize( t ) ( sizeof( t ) / sizeof( struct TEntry ) )
/* Forward declaration for the Help funcion */ /* Forward declaration for the Help funcion */
static int Help(void); static int Help( void );
static const struct TEntry table[] = static const struct TEntry table[] = {
{ {"help", "Print this information", Help },
{ "help", "Print this information", Help }, {"run", "Run the emulator with current CPU status", run },
{ "run", "Run the emulator with current CPU status", run }, {"?", "<addr>, Check address mapping", map_check},
{ "?", "<addr>, Check address mapping", map_check }, {"r", "<addr> [count], Read nibbles from memory", r },
{ "r", "<addr> [count], Read nibbles from memory", r }, {"w", "<addr> [n]..., Write nibbles into memory", w },
{ "w", "<addr> [n]..., Write nibbles into memory", w }, {"d", "<addr> [count], Disassemble starting from 'addr'", d },
{ "d", "<addr> [count], Disassemble starting from 'addr'", d }, {"cpu", "Print CPU status", cpu },
{ "cpu", "Print CPU status", cpu }, {"map", "Print the contents of the module map table", map },
{ "map", "Print the contents of the module map table", map }, {"debug", "Set the debugging level", debug },
{ "debug", "Set the debugging level", debug }, {"reset", "Reset CPU", reset },
{ "reset", "Reset CPU", reset }, {"exit", "Save emulator state & exit", mon_exit },
{ "exit", "Save emulator state & exit", mon_exit }, {"quit", "Quit emulator WITHOUT saving its state", mon_quit }
{ "quit", "Quit emulator WITHOUT saving its state", mon_quit }
}; };
/* Invoke the command 'tk' and return a status code */ /* Invoke the command 'tk' and return a status code */
static int InvokeCommand(char *tk) static int InvokeCommand( char* tk )
{ {
int i; int i;
for(i=0; i<TableSize(table) && strcmp(tk, table[i].name); i++); for ( i = 0; i < TableSize( table ) && strcmp( tk, table[ i ].name ); i++ )
return i==TableSize(table) ? FAILED : table[i].function(); ;
return i == TableSize( table ) ? FAILED : table[ i ].function();
} }
/* Print help information */ /* Print help information */
static int Help(void) static int Help( void )
{ {
int i; int i;
for(i=0; i<TableSize(table); i++) for ( i = 0; i < TableSize( table ); i++ )
printf("%s\t\t%s\n", table[i].name, table[i].desc); printf( "%s\t\t%s\n", table[ i ].name, table[ i ].desc );
return OK; return OK;
} }
/* Handler for SIGINT during monitor execution */ /* Handler for SIGINT during monitor execution */
static void sigint_handler(int s) static void sigint_handler( int s ) { EmulatorIntRequest(); }
{
EmulatorIntRequest();
}
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -322,58 +319,53 @@ static void sigint_handler(int s)
This function implements a very simple interactive monitor. This function implements a very simple interactive monitor.
.call : .call :
Monitor(); Monitor();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
CPU_W_BAD_MONITOR_CMD CPU_W_BAD_MONITOR_CMD
From lower level modules From lower level modules
.notes : .notes :
1.1, 18-Feb-1998, creation 1.1, 18-Feb-1998, creation
.- */ .- */
void Monitor(void) void Monitor( void )
{ {
char cmd[LINE_BUFFER_SIZE]; char cmd[ LINE_BUFFER_SIZE ];
char old_cmd[LINE_BUFFER_SIZE]; char old_cmd[ LINE_BUFFER_SIZE ];
char *tk; char* tk;
/* Clear old_cmd buffer */ /* Clear old_cmd buffer */
strcpy(old_cmd, ""); strcpy( old_cmd, "" );
/* Establish SIGINT handler */ /* Establish SIGINT handler */
signal(SIGINT, sigint_handler); signal( SIGINT, sigint_handler );
/* Infinite loop; it's exited only when a condition is signalled */ /* Infinite loop; it's exited only when a condition is signalled */
while(1) while ( 1 ) {
{ /* Write prompt */
/* Write prompt */ fputs( PROMPT, stdout );
fputs(PROMPT, stdout); fflush( stdout );
fflush(stdout);
if(fgets(cmd, LINE_BUFFER_SIZE, stdin) == (char *)NULL || if ( fgets( cmd, LINE_BUFFER_SIZE, stdin ) == ( char* )NULL || ( tk = strtok( cmd, TOK_DELIMITERS ) ) == ( char* )NULL ) {
(tk = strtok(cmd, TOK_DELIMITERS)) == (char *)NULL) /* New command empty; try old command */
{ if ( ( tk = strtok( old_cmd, TOK_DELIMITERS ) ) != ( char* )NULL )
/* New command empty; try old command */ if ( InvokeCommand( tk ) )
if((tk = strtok(old_cmd, TOK_DELIMITERS)) != (char *)NULL) ChfCondition CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk ChfEnd;
if(InvokeCommand(tk)) ChfSignal();
ChfCondition CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk ChfEnd; }
ChfSignal();
else {
/* Save command */
strcpy( old_cmd, cmd );
/* New command */
if ( InvokeCommand( tk ) ) {
ChfCondition CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk ChfEnd;
ChfSignal();
}
}
} }
else
{
/* Save command */
strcpy(old_cmd, cmd);
/* New command */
if(InvokeCommand(tk))
{
ChfCondition CPU_W_BAD_MONITOR_CMD, CHF_WARNING, tk ChfEnd;
ChfSignal();
}
}
}
} }

View file

@ -83,24 +83,22 @@ static char rcs_id[] = "$Id";
#include "cpu.h" #include "cpu.h"
#include "disk_io.h" #include "disk_io.h"
#define CHF_MODULE_ID UTIL_CHF_MODULE_ID #define CHF_MODULE_ID UTIL_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/* Maximum size of source ROM (bytes) handled by this utility; set to /* Maximum size of source ROM (bytes) handled by this utility; set to
a reasonable value a reasonable value
*/ */
#define MAX_SRC_SIZE (4*1024*1024) #define MAX_SRC_SIZE ( 4 * 1024 * 1024 )
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf parameters - Do not change. Chf parameters - Do not change.
The ABNORMAL_EXIT_CODE is taken from stdlib.h (EXIT_FAILURE) The ABNORMAL_EXIT_CODE is taken from stdlib.h (EXIT_FAILURE)
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define CONDITION_STACK_SIZE 16 #define CONDITION_STACK_SIZE 16
#define HANDLER_STACK_SIZE 8 #define HANDLER_STACK_SIZE 8
#define ABNORMAL_EXIT_CODE EXIT_FAILURE #define ABNORMAL_EXIT_CODE EXIT_FAILURE
/* Conditional prefix and mandatory suffix to make a message catalog /* Conditional prefix and mandatory suffix to make a message catalog
name from cat_base_name. name from cat_base_name.
@ -108,30 +106,26 @@ static char rcs_id[] = "$Id";
static const char cat_prefix[] = "./"; static const char cat_prefix[] = "./";
static const char cat_suffix[] = ".cat"; static const char cat_suffix[] = ".cat";
#define CAT_PREFIX_LEN (sizeof(cat_prefix)+1) #define CAT_PREFIX_LEN ( sizeof( cat_prefix ) + 1 )
#define CAT_SUFFIX_LEN (sizeof(cat_suffix)+1) #define CAT_SUFFIX_LEN ( sizeof( cat_suffix ) + 1 )
/* Message catalog base_name */ /* Message catalog base_name */
static const char cat_base_name[] = "saturn"; static const char cat_base_name[] = "saturn";
/* Condition codes used by this utility */ /* Condition codes used by this utility */
#define UTIL_I_PACK_USAGE 1 #define UTIL_I_PACK_USAGE 1
#define UTIL_F_PACK_CMD_LINE 2 #define UTIL_F_PACK_CMD_LINE 2
#define UTIL_F_PACK_STAT 3 #define UTIL_F_PACK_STAT 3
#define UTIL_F_PACK_SRC_SIZE 4 #define UTIL_F_PACK_SRC_SIZE 4
#define UTIL_F_PACK_MALLOC 5 #define UTIL_F_PACK_MALLOC 5
#define UTIL_F_PACK_OPEN 6 #define UTIL_F_PACK_OPEN 6
#define UTIL_F_PACK_READ 7 #define UTIL_F_PACK_READ 7
#define UTIL_F_PACK_WRITE_NIBBLES 8 #define UTIL_F_PACK_WRITE_NIBBLES 8
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
.title : main .title : main
@ -144,150 +138,131 @@ static const char cat_base_name[] = "saturn";
3.6, 2-Oct-2000, creation 3.6, 2-Oct-2000, creation
.- */ .- */
int main(int argc, char *argv[]) int main( int argc, char* argv[] )
{ {
char *cat_name; /* Message catalog name */ char* cat_name; /* Message catalog name */
struct stat statb; /* stat() buffer on source file */ struct stat statb; /* stat() buffer on source file */
char *b; /* Source buffer */ char* b; /* Source buffer */
Nibble *nb; /* Nibble buffer */ Nibble* nb; /* Nibble buffer */
int d; /* Source file descriptor */ int d; /* Source file descriptor */
int i; int i;
int st; int st;
if((cat_name = malloc(sizeof(cat_base_name) if ( ( cat_name = malloc( sizeof( cat_base_name ) + CAT_PREFIX_LEN + CAT_SUFFIX_LEN + 1 ) ) == NULL ) {
+CAT_PREFIX_LEN+CAT_SUFFIX_LEN+1)) fprintf( stderr, "Cat_name initialization failed\n" );
== NULL) exit( ABNORMAL_EXIT_CODE );
{
fprintf(stderr, "Cat_name initialization failed\n");
exit(ABNORMAL_EXIT_CODE);
} }
/* Generate catalog name, without optional prefix */ /* Generate catalog name, without optional prefix */
strcpy(cat_name, cat_base_name); strcpy( cat_name, cat_base_name );
strcat(cat_name, cat_suffix); strcat( cat_name, cat_suffix );
/* Chf initialization with msgcat subsystem; /* Chf initialization with msgcat subsystem;
notice that on some systems (e.g. Digital UNIX) catopen() can succeed notice that on some systems (e.g. Digital UNIX) catopen() can succeed
even if it was not able to open the right message catalog; better even if it was not able to open the right message catalog; better
try it now. try it now.
*/ */
if((st = ChfMsgcatInit( if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
argv[0], /* Application's name */ CHF_DEFAULT, /* Options */
CHF_DEFAULT, /* Options */ cat_name, /* Name of the message catalog */
cat_name, /* Name of the message catalog */ CONDITION_STACK_SIZE, /* Size of the condition stack */
CONDITION_STACK_SIZE, /* Size of the condition stack */ HANDLER_STACK_SIZE, /* Size of the handler stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */ ABNORMAL_EXIT_CODE /* Abnormal exit code */
ABNORMAL_EXIT_CODE /* Abnormal exit code */ ) ) != CHF_S_OK ||
)) != CHF_S_OK ChfGetMessage( CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL ) == NULL ) {
|| if ( st != CHF_S_OK && st != CHF_F_CATOPEN ) {
ChfGetMessage(CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL) == NULL) fprintf( stderr, "Chf initialization failed\n" );
{ exit( ABNORMAL_EXIT_CODE );
if(st != CHF_S_OK && st != CHF_F_CATOPEN) }
{
fprintf(stderr, "Chf initialization failed\n");
exit(ABNORMAL_EXIT_CODE);
}
else else {
{ fprintf( stderr, "Default message catalog open failed; trying alternate\n" );
fprintf(stderr,
"Default message catalog open failed; trying alternate\n");
/* Bring down Chf before initializing it again */ /* Bring down Chf before initializing it again */
if(st == CHF_S_OK) ChfExit(); if ( st == CHF_S_OK )
ChfExit();
/* Try alternate message catalog name (with prefix) */ /* Try alternate message catalog name (with prefix) */
strcpy(cat_name, cat_prefix); strcpy( cat_name, cat_prefix );
strcat(cat_name, cat_base_name); strcat( cat_name, cat_base_name );
strcat(cat_name, cat_suffix); strcat( cat_name, cat_suffix );
if((st = ChfMsgcatInit( if ( ( st = ChfMsgcatInit( argv[ 0 ], /* Application's name */
argv[0], /* Application's name */ CHF_DEFAULT, /* Options */
CHF_DEFAULT, /* Options */ cat_name, /* Name of the message catalog */
cat_name, /* Name of the message catalog */ CONDITION_STACK_SIZE, /* Size of the condition stack */
CONDITION_STACK_SIZE, /* Size of the condition stack */ HANDLER_STACK_SIZE, /* Size of the handler stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */ ABNORMAL_EXIT_CODE /* Abnormal exit code */
ABNORMAL_EXIT_CODE /* Abnormal exit code */ ) ) != CHF_S_OK ||
)) != CHF_S_OK ChfGetMessage( CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL ) == NULL ) {
|| fprintf( stderr, "Alternate Chf initialization failed\n" );
ChfGetMessage(CHF_MODULE_ID, UTIL_I_PACK_USAGE, NULL) == NULL) exit( ABNORMAL_EXIT_CODE );
{ }
fprintf(stderr, "Alternate Chf initialization failed\n"); }
exit(ABNORMAL_EXIT_CODE);
}
}
} }
/* cat_name no longer needed */ /* cat_name no longer needed */
free(cat_name); free( cat_name );
/* Now, do some useful work; pack argv[1] into argv[2] */ /* Now, do some useful work; pack argv[1] into argv[2] */
if(argc != 3) if ( argc != 3 ) {
{ ChfCondition UTIL_I_PACK_USAGE, CHF_INFO ChfEnd;
ChfCondition UTIL_I_PACK_USAGE, CHF_INFO ChfEnd; ChfCondition UTIL_F_PACK_CMD_LINE, CHF_FATAL ChfEnd;
ChfCondition UTIL_F_PACK_CMD_LINE, CHF_FATAL ChfEnd; ChfSignal();
ChfSignal();
} }
/* Get the size of the source file */ /* Get the size of the source file */
if(stat(argv[1], &statb)) if ( stat( argv[ 1 ], &statb ) ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition UTIL_F_PACK_STAT, CHF_FATAL, argv[ 1 ] ChfEnd;
ChfCondition UTIL_F_PACK_STAT, CHF_FATAL, argv[1] ChfEnd; ChfSignal();
ChfSignal();
} }
/* Check that actual size is reasonable */ /* Check that actual size is reasonable */
if(statb.st_size > MAX_SRC_SIZE) if ( statb.st_size > MAX_SRC_SIZE ) {
{ ChfCondition UTIL_F_PACK_SRC_SIZE, CHF_FATAL, statb.st_size ChfEnd;
ChfCondition UTIL_F_PACK_SRC_SIZE, CHF_FATAL, statb.st_size ChfEnd; ChfSignal();
ChfSignal();
} }
/* Allocate source buffer */ /* Allocate source buffer */
if((b = (char *)malloc(statb.st_size)) == (char *)NULL if ( ( b = ( char* )malloc( statb.st_size ) ) == ( char* )NULL ||
|| (nb = (Nibble *)malloc(sizeof(Nibble) * statb.st_size)) ( nb = ( Nibble* )malloc( sizeof( Nibble ) * statb.st_size ) ) == ( Nibble* )NULL ) {
== (Nibble *)NULL) ChfErrnoCondition;
{ ChfCondition UTIL_F_PACK_MALLOC, CHF_FATAL, statb.st_size ChfEnd;
ChfErrnoCondition; ChfSignal();
ChfCondition UTIL_F_PACK_MALLOC, CHF_FATAL, statb.st_size ChfEnd;
ChfSignal();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* open/read/close */ /* open/read/close */
if((d = open(argv[1], O_RDONLY)) == -1) if ( ( d = open( argv[ 1 ], O_RDONLY ) ) == -1 ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition UTIL_F_PACK_OPEN, CHF_FATAL, argv[ 1 ] ChfEnd;
ChfCondition UTIL_F_PACK_OPEN, CHF_FATAL, argv[1] ChfEnd; ChfSignal();
ChfSignal();
} }
if(read(d, b, statb.st_size) != statb.st_size) if ( read( d, b, statb.st_size ) != statb.st_size ) {
{ ChfErrnoCondition;
ChfErrnoCondition;
(void)close(d); ( void )close( d );
ChfCondition UTIL_F_PACK_READ, CHF_FATAL, argv[1] ChfEnd; ChfCondition UTIL_F_PACK_READ, CHF_FATAL, argv[ 1 ] ChfEnd;
ChfSignal(); ChfSignal();
} }
(void)close(d); ( void )close( d );
/* Convert char -> Nibble */ /* Convert char -> Nibble */
for(i=0; i<statb.st_size; i++) for ( i = 0; i < statb.st_size; i++ )
nb[i] = (Nibble)b[i]; nb[ i ] = ( Nibble )b[ i ];
/* Source buffer no longer needed */ /* Source buffer no longer needed */
free(b); free( b );
/* Write */ /* Write */
if(WriteNibblesToFile(nb, statb.st_size, argv[2])) if ( WriteNibblesToFile( nb, statb.st_size, argv[ 2 ] ) ) {
{ ChfCondition UTIL_F_PACK_WRITE_NIBBLES, CHF_FATAL ChfEnd;
ChfCondition UTIL_F_PACK_WRITE_NIBBLES, CHF_FATAL ChfEnd; ChfSignal();
ChfSignal();
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View file

@ -86,7 +86,7 @@ static char rcs_id[] = "$Id: romram.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include <stdlib.h> #include <stdlib.h>
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#include <unistd.h> /* access() */ #include <unistd.h> /* access() */
#include <errno.h> #include <errno.h>
#include "config.h" #include "config.h"
@ -98,26 +98,24 @@ static char rcs_id[] = "$Id: romram.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include "args.h" #include "args.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID #define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/* 3.2: The rom/ram storage areas are now dynamically allocated in /* 3.2: The rom/ram storage areas are now dynamically allocated in
a private struct ModStatus_48. The dynamic allocation is performed during a private struct ModStatus_48. The dynamic allocation is performed during
Rom initialization, and the following macro allows us to reuse the Rom initialization, and the following macro allows us to reuse the
existing code with minimal updates. existing code with minimal updates.
*/ */
static struct ModStatus_48 *mod_status_48; static struct ModStatus_48* mod_status_48;
#define mod_status_hdw mod_status.hdw
#define mod_status_rom mod_status_48->rom
#define mod_status_ram mod_status_48->ram
#define mod_status_port_1 mod_status_48->port_1
#define mod_status_port_2 mod_status_48->port_2
#define mod_status_hdw mod_status.hdw
#define mod_status_rom mod_status_48->rom
#define mod_status_ram mod_status_48->ram
#define mod_status_port_1 mod_status_48->port_1
#define mod_status_port_2 mod_status_48->port_2
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Rom module Rom module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -130,41 +128,35 @@ static struct ModStatus_48 *mod_status_48;
module status structure, and initializes the Rom module. module status structure, and initializes the Rom module.
.call : .call :
RomInit(); RomInit();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_F_ROM_INIT MOD_F_ROM_INIT
MOD_F_MOD_STATUS_ALLOC MOD_F_MOD_STATUS_ALLOC
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
.- */ .- */
void RomInit(void) void RomInit( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomInit"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomInit" );
if((mod_status_48 = if ( ( mod_status_48 = ( struct ModStatus_48* )malloc( sizeof( struct ModStatus_48 ) ) ) == ( struct ModStatus_48* )NULL ) {
(struct ModStatus_48 *)malloc(sizeof(struct ModStatus_48))) ChfErrnoCondition;
== (struct ModStatus_48 *)NULL) ChfCondition MOD_F_MOD_STATUS_ALLOC, CHF_FATAL, sizeof( struct ModStatus_48 ) ChfEnd;
{ ChfSignal();
ChfErrnoCondition;
ChfCondition MOD_F_MOD_STATUS_ALLOC, CHF_FATAL,
sizeof(struct ModStatus_48) ChfEnd;
ChfSignal();
} }
if(ReadNibblesFromFile(args.rom_file_name, N_ROM_SIZE, mod_status_rom)) if ( ReadNibblesFromFile( args.rom_file_name, N_ROM_SIZE, mod_status_rom ) ) {
{ ChfCondition MOD_F_ROM_INIT, CHF_FATAL ChfEnd;
ChfCondition MOD_F_ROM_INIT, CHF_FATAL ChfEnd; ChfSignal();
ChfSignal();
} }
} }
/* .+ /* .+
.title : RomSave .title : RomSave
@ -175,22 +167,18 @@ void RomInit(void)
nothing. nothing.
.call : .call :
RomSave(); RomSave();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
.- */ .- */
void RomSave(void) void RomSave( void ) { debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomSave" ); }
{
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomSave");
}
/* .+ /* .+
@ -202,25 +190,24 @@ void RomSave(void)
and returns it. and returns it.
.call : .call :
d = RomRead(rel_address); d = RomRead(rel_address);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 26-Jan-1998, creation 1.1, 26-Jan-1998, creation
.- */ .- */
Nibble RomRead(Address rel_address) Nibble RomRead( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomRead"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomRead" );
return mod_status_rom[rel_address]; return mod_status_rom[ rel_address ];
} }
/* .+ /* .+
.title : RomWrite .title : RomWrite
@ -231,30 +218,29 @@ Nibble RomRead(Address rel_address)
ROM location. It signals an error condition and does nothing. ROM location. It signals an error condition and does nothing.
.call : .call :
RomWrite(rel_address, datum); RomWrite(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_ROM_WRITE MOD_E_ROM_WRITE
.notes : .notes :
1.1, 26-Jan-1998, creation 1.1, 26-Jan-1998, creation
.- */ .- */
void RomWrite(Address rel_address, Nibble datum) void RomWrite( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite" );
ChfCondition MOD_E_ROM_WRITE, CHF_ERROR, rel_address, datum ChfEnd; ChfCondition MOD_E_ROM_WRITE, CHF_ERROR, rel_address, datum ChfEnd;
ChfSignal(); ChfSignal();
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Main Ram module Main Ram module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -266,32 +252,30 @@ void RomWrite(Address rel_address, Nibble datum)
This function initializes the Ram module. This function initializes the Ram module.
.call : .call :
RamInit(); RamInit();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_W_RAM_INIT MOD_W_RAM_INIT
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
.- */ .- */
void RamInit(void) void RamInit( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamInit"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamInit" );
if(ReadNibblesFromFile(args.ram_file_name, N_RAM_SIZE, mod_status_ram)) if ( ReadNibblesFromFile( args.ram_file_name, N_RAM_SIZE, mod_status_ram ) ) {
{ ChfCondition MOD_W_RAM_INIT, CHF_WARNING ChfEnd;
ChfCondition MOD_W_RAM_INIT, CHF_WARNING ChfEnd; ChfSignal();
ChfSignal();
(void)memset(mod_status_ram, 0, sizeof(mod_status_ram)); ( void )memset( mod_status_ram, 0, sizeof( mod_status_ram ) );
} }
} }
/* .+ /* .+
.title : RamSave .title : RamSave
@ -301,33 +285,31 @@ void RamInit(void)
This function saves the status of the Ram module to disk. This function saves the status of the Ram module to disk.
.call : .call :
RamSave(); RamSave();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_RAM_SAVE MOD_E_RAM_SAVE
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
2.4, 12-Sep-2000, update 2.4, 12-Sep-2000, update
- upon failure, added push of ChfErrnoCondition to condition stack. - upon failure, added push of ChfErrnoCondition to condition stack.
.- */ .- */
void RamSave(void) void RamSave( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamSave"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamSave" );
if(WriteNibblesToFile(mod_status_ram, N_RAM_SIZE, args.ram_file_name)) if ( WriteNibblesToFile( mod_status_ram, N_RAM_SIZE, args.ram_file_name ) ) {
{ ChfErrnoCondition;
ChfErrnoCondition; ChfCondition MOD_E_RAM_SAVE, CHF_ERROR ChfEnd;
ChfCondition MOD_E_RAM_SAVE, CHF_ERROR ChfEnd; ChfSignal();
ChfSignal(); }
}
} }
/* .+ /* .+
.title : RamRead .title : RamRead
@ -338,25 +320,24 @@ void RamSave(void)
and returns it. and returns it.
.call : .call :
d = RamRead(rel_address); d = RamRead(rel_address);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 26-Jan-1998, creation 1.1, 26-Jan-1998, creation
.- */ .- */
Nibble RamRead(Address rel_address) Nibble RamRead( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamRead"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamRead" );
return mod_status_ram[rel_address]; return mod_status_ram[ rel_address ];
} }
/* .+ /* .+
.title : RamWrite .title : RamWrite
@ -367,28 +348,27 @@ Nibble RamRead(Address rel_address)
of the internal RAM. of the internal RAM.
.call : .call :
RamWrite(rel_address, datum); RamWrite(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 26-Jan-1998, creation 1.1, 26-Jan-1998, creation
.- */ .- */
void RamWrite(Address rel_address, Nibble datum) void RamWrite( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite" );
mod_status_ram[rel_address] = datum; mod_status_ram[ rel_address ] = datum;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Ce1 module Ce1 module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -401,33 +381,31 @@ void RamWrite(Address rel_address, Nibble datum)
Back Switcher. Back Switcher.
.call : .call :
Ce1Init(); Ce1Init();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void Ce1Init(void) void Ce1Init( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init" );
/* Check if bank-switcher accelerators are valid; if not, initialize /* Check if bank-switcher accelerators are valid; if not, initialize
them to a reasonable value (that is, select Port_2 bank 0). them to a reasonable value (that is, select Port_2 bank 0).
*/ */
if(!mod_status_hdw.accel_valid) if ( !mod_status_hdw.accel_valid ) {
{ mod_status_hdw.accel_valid = 1;
mod_status_hdw.accel_valid = 1; mod_status_hdw.accel.a48.bs_address = ( XAddress )0;
mod_status_hdw.accel.a48.bs_address = (XAddress)0; }
}
} }
/* .+ /* .+
.title : Ce1Save .title : Ce1Save
@ -437,28 +415,27 @@ void Ce1Init(void)
This function saves the status of the Ce1 module. This function saves the status of the Ce1 module.
.call : .call :
Ce1Save(); Ce1Save();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void Ce1Save(void) void Ce1Save( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save" );
/* Nothing to be done herel the bank-switcher accelerators are saved /* Nothing to be done herel the bank-switcher accelerators are saved
by the hdw modules by the hdw modules
*/ */
} }
/* .+ /* .+
.title : Ce1Read .title : Ce1Read
@ -471,37 +448,35 @@ void Ce1Save(void)
most significant bits of Port_2 addresses when accessing that port. most significant bits of Port_2 addresses when accessing that port.
.call : .call :
d = Ce1Read(rel_address); d = Ce1Read(rel_address);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_I_BS_ADDRESS MOD_I_BS_ADDRESS
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
Nibble Ce1Read(Address rel_address) Nibble Ce1Read( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read" );
debug1(DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address); debug1( DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
/* Save the read address into the hdw accelerators. /* Save the read address into the hdw accelerators.
bs_address can be directly or-ed with a relative port address to bs_address can be directly or-ed with a relative port address to
obtain a valid index in Port_2 obtain a valid index in Port_2
*/ */
#ifdef N_PORT_2_BANK #ifdef N_PORT_2_BANK
mod_status_hdw.accel.a48.bs_address = mod_status_hdw.accel.a48.bs_address = ( ( XAddress )( ( rel_address >> 1 ) & 0x1F ) << 18 ) & ( N_PORT_2_SIZE - 1 );
((XAddress)((rel_address >> 1) & 0x1F) << 18) & (N_PORT_2_SIZE-1);
#endif #endif
return (Nibble)0x0; return ( Nibble )0x0;
} }
/* .+ /* .+
.title : Ce1Write .title : Ce1Write
@ -513,31 +488,30 @@ Nibble Ce1Read(Address rel_address)
state of mod_status_hdw.accel.a48.bs_address is *not* changed. state of mod_status_hdw.accel.a48.bs_address is *not* changed.
.call : .call :
Ce1Write(rel_address, datum); Ce1Write(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_CE1_WRITE MOD_E_CE1_WRITE
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void Ce1Write(Address rel_address, Nibble datum) void Ce1Write( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write" );
ChfCondition MOD_E_CE1_WRITE, CHF_ERROR, rel_address, datum ChfEnd; ChfCondition MOD_E_CE1_WRITE, CHF_ERROR, rel_address, datum ChfEnd;
ChfSignal(); ChfSignal();
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Ce2 module Ce2 module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -549,68 +523,61 @@ void Ce1Write(Address rel_address, Nibble datum)
This function initializes the Ce2 module, corresponding to Port 1. This function initializes the Ce2 module, corresponding to Port 1.
.call : .call :
Ce2Init(); Ce2Init();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_W_PORT_1_INIT MOD_W_PORT_1_INIT
MOD_I_PORT_1_WP MOD_I_PORT_1_WP
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void Ce2Init(void) void Ce2Init( void )
{ {
Nibble new_status; Nibble new_status;
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init" );
if(ReadNibblesFromFile(args.port_1_file_name, N_PORT_1_SIZE, if ( ReadNibblesFromFile( args.port_1_file_name, N_PORT_1_SIZE, mod_status_port_1 ) ) {
mod_status_port_1)) ChfCondition MOD_W_PORT_1_INIT, CHF_WARNING ChfEnd;
{ ChfSignal();
ChfCondition MOD_W_PORT_1_INIT, CHF_WARNING ChfEnd;
ChfSignal();
(void)memset(mod_status_port_1, 0, sizeof(mod_status_port_1)); ( void )memset( mod_status_port_1, 0, sizeof( mod_status_port_1 ) );
new_status = new_status = mod_status_hdw.card_status & ~( CE2_CARD_PRESENT | CE2_CARD_WE );
mod_status_hdw.card_status & ~(CE2_CARD_PRESENT|CE2_CARD_WE);
} }
else else {
{ /* Card present; check write protection */
/* Card present; check write protection */ new_status = mod_status_hdw.card_status | CE2_CARD_PRESENT;
new_status = mod_status_hdw.card_status | CE2_CARD_PRESENT;
if(access(args.port_1_file_name, W_OK) == 0) if ( access( args.port_1_file_name, W_OK ) == 0 )
new_status |= CE2_CARD_WE; new_status |= CE2_CARD_WE;
else else {
{ new_status &= ~CE2_CARD_WE;
new_status &= ~CE2_CARD_WE;
ChfErrnoCondition; ChfErrnoCondition;
ChfCondition MOD_I_PORT_1_WP, CHF_INFO ChfEnd; ChfCondition MOD_I_PORT_1_WP, CHF_INFO ChfEnd;
ChfSignal(); ChfSignal();
} }
} }
if(new_status != mod_status_hdw.card_status) if ( new_status != mod_status_hdw.card_status ) {
{ /* card_status changed; update, set MP bit in HST and post
/* card_status changed; update, set MP bit in HST and post interrupt request.
interrupt request. */
*/ mod_status_hdw.card_status = new_status;
mod_status_hdw.card_status = new_status; cpu_status.HST |= HST_MP_MASK;
cpu_status.HST |= HST_MP_MASK; CpuIntRequest( INT_REQUEST_IRQ );
CpuIntRequest(INT_REQUEST_IRQ);
} }
} }
/* .+ /* .+
.title : Ce2Save .title : Ce2Save
@ -621,35 +588,31 @@ void Ce2Init(void)
not write-protected. not write-protected.
.call : .call :
Ce2Save(); Ce2Save();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_PORT_1_SAVE MOD_E_PORT_1_SAVE
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void Ce2Save(void) void Ce2Save( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save" );
/* Attempt to save only if port is write-enabled */ /* Attempt to save only if port is write-enabled */
if((mod_status_hdw.card_status & CE2_CARD_WE) && if ( ( mod_status_hdw.card_status & CE2_CARD_WE ) && WriteNibblesToFile( mod_status_port_1, N_PORT_1_SIZE, args.port_1_file_name ) ) {
WriteNibblesToFile(mod_status_port_1, N_PORT_1_SIZE, ChfErrnoCondition;
args.port_1_file_name)) ChfCondition MOD_E_PORT_1_SAVE, CHF_ERROR ChfEnd;
{ ChfSignal();
ChfErrnoCondition;
ChfCondition MOD_E_PORT_1_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
} }
} }
/* .+ /* .+
.title : Ce2Read .title : Ce2Read
@ -659,26 +622,25 @@ void Ce2Save(void)
This function reads a nibble from the Ce2 module. This function reads a nibble from the Ce2 module.
.call : .call :
d = Ce2Read(rel_address) d = Ce2Read(rel_address)
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
Nibble Ce2Read(Address rel_address) Nibble Ce2Read( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read" );
return mod_status_port_1[rel_address]; return mod_status_port_1[ rel_address ];
} }
/* .+ /* .+
.title : Ce2Write .title : Ce2Write
@ -688,29 +650,28 @@ Nibble Ce2Read(Address rel_address)
This function writes a nibble to the Ce2 module. This function writes a nibble to the Ce2 module.
.call : .call :
Ce2Write(rel_address, datum); Ce2Write(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void Ce2Write(Address rel_address, Nibble datum) void Ce2Write( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write" );
mod_status_port_1[rel_address] = datum; mod_status_port_1[ rel_address ] = datum;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
NCe3 module NCe3 module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -723,76 +684,68 @@ void Ce2Write(Address rel_address, Nibble datum)
(bank switched) port 2. (bank switched) port 2.
.call : .call :
NCe3Init(); NCe3Init();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_W_PORT_2_INIT MOD_W_PORT_2_INIT
MOD_I_PORT_2_WP MOD_I_PORT_2_WP
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void NCe3Init(void) void NCe3Init( void )
{ {
Nibble new_status; Nibble new_status;
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init" );
#ifdef N_PORT_2_BANK #ifdef N_PORT_2_BANK
if(ReadNibblesFromFile(args.port_2_file_name, N_PORT_2_SIZE, if ( ReadNibblesFromFile( args.port_2_file_name, N_PORT_2_SIZE, mod_status_port_2 ) ) {
mod_status_port_2)) ChfCondition MOD_W_PORT_2_INIT, CHF_WARNING ChfEnd;
{ ChfSignal();
ChfCondition MOD_W_PORT_2_INIT, CHF_WARNING ChfEnd;
ChfSignal();
(void)memset(mod_status_port_2, 0, sizeof(mod_status_port_2)); ( void )memset( mod_status_port_2, 0, sizeof( mod_status_port_2 ) );
new_status = new_status = mod_status_hdw.card_status & ~( NCE3_CARD_PRESENT | NCE3_CARD_WE );
mod_status_hdw.card_status & ~(NCE3_CARD_PRESENT|NCE3_CARD_WE);
} }
else else {
{ /* Card present; check write protection */
/* Card present; check write protection */ new_status = mod_status_hdw.card_status | NCE3_CARD_PRESENT;
new_status = mod_status_hdw.card_status | NCE3_CARD_PRESENT;
if(access(args.port_2_file_name, W_OK) == 0) if ( access( args.port_2_file_name, W_OK ) == 0 )
new_status |= NCE3_CARD_WE; new_status |= NCE3_CARD_WE;
else else {
{ new_status &= ~NCE3_CARD_WE;
new_status &= ~NCE3_CARD_WE;
ChfErrnoCondition; ChfErrnoCondition;
ChfCondition MOD_I_PORT_2_WP, CHF_INFO ChfEnd; ChfCondition MOD_I_PORT_2_WP, CHF_INFO ChfEnd;
ChfSignal(); ChfSignal();
} }
} }
#else #else
/* If N_PORT_2_BANK is undefined, Port 2 is not emulated */ /* If N_PORT_2_BANK is undefined, Port 2 is not emulated */
new_status = new_status = mod_status_hdw.card_status & ~( NCE3_CARD_PRESENT | NCE3_CARD_WE );
mod_status_hdw.card_status & ~(NCE3_CARD_PRESENT|NCE3_CARD_WE);
#endif #endif
if(new_status != mod_status_hdw.card_status) if ( new_status != mod_status_hdw.card_status ) {
{ /* card_status changed; update, set MP bit in HST and post
/* card_status changed; update, set MP bit in HST and post interrupt request.
interrupt request. */
*/ mod_status_hdw.card_status = new_status;
mod_status_hdw.card_status = new_status; cpu_status.HST |= HST_MP_MASK;
cpu_status.HST |= HST_MP_MASK; CpuIntRequest( INT_REQUEST_IRQ );
CpuIntRequest(INT_REQUEST_IRQ);
} }
} }
/* .+ /* .+
.title : NCe3Save .title : NCe3Save
@ -802,37 +755,33 @@ void NCe3Init(void)
This function saves the status of the NCe3 module. This function saves the status of the NCe3 module.
.call : .call :
NCe3Save(); NCe3Save();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_PORT_2_SAVE MOD_E_PORT_2_SAVE
.notes : .notes :
1.1, 11-Feb-1998, creation 1.1, 11-Feb-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void NCe3Save(void) void NCe3Save( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save" );
#ifdef N_PORT_2_BANK #ifdef N_PORT_2_BANK
/* Attempt to save only if port is write-enabled */ /* Attempt to save only if port is write-enabled */
if((mod_status_hdw.card_status & NCE3_CARD_WE) && if ( ( mod_status_hdw.card_status & NCE3_CARD_WE ) && WriteNibblesToFile( mod_status_port_2, N_PORT_2_SIZE, args.port_2_file_name ) ) {
WriteNibblesToFile(mod_status_port_2, N_PORT_2_SIZE, ChfErrnoCondition;
args.port_2_file_name)) ChfCondition MOD_E_PORT_2_SAVE, CHF_ERROR ChfEnd;
{ ChfSignal();
ChfErrnoCondition;
ChfCondition MOD_E_PORT_2_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
} }
#endif #endif
} }
/* .+ /* .+
.title : NCe3Read .title : NCe3Read
@ -842,37 +791,35 @@ void NCe3Save(void)
This function reads a nibble from the NCe3 module. This function reads a nibble from the NCe3 module.
.call : .call :
d = NCe3Read(rel_address) d = NCe3Read(rel_address)
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_NCE3_READ MOD_E_NCE3_READ
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
Nibble NCe3Read(Address rel_address) Nibble NCe3Read( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read" );
#ifdef N_PORT_2_BANK #ifdef N_PORT_2_BANK
return return mod_status_port_2[ rel_address | mod_status_hdw.accel.a48.bs_address ];
mod_status_port_2[rel_address | mod_status_hdw.accel.a48.bs_address];
#else #else
ChfCondition MOD_E_NCE3_READ, CHF_ERROR, rel_address ChfEnd; ChfCondition MOD_E_NCE3_READ, CHF_ERROR, rel_address ChfEnd;
ChfSignal(); ChfSignal();
return (Nibble)0; return ( Nibble )0;
#endif #endif
} }
/* .+ /* .+
.title : NCe3Write .title : NCe3Write
@ -883,28 +830,27 @@ Nibble NCe3Read(Address rel_address)
it is not currently implemented. it is not currently implemented.
.call : .call :
NCe3Write(rel_address, datum); NCe3Write(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_NCE3_WRITE MOD_E_NCE3_WRITE
.notes : .notes :
1.1, 23-Jan-1998, creation 1.1, 23-Jan-1998, creation
2.4, 11-Sep-2000, implemented 2.4, 11-Sep-2000, implemented
.- */ .- */
void NCe3Write(Address rel_address, Nibble datum) void NCe3Write( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write" );
#ifdef N_PORT_2_BANK #ifdef N_PORT_2_BANK
mod_status_port_2[rel_address | mod_status_hdw.accel.a48.bs_address] mod_status_port_2[ rel_address | mod_status_hdw.accel.a48.bs_address ] = datum;
= datum;
#else #else
ChfCondition MOD_E_NCE3_WRITE, CHF_ERROR, rel_address, datum ChfEnd; ChfCondition MOD_E_NCE3_WRITE, CHF_ERROR, rel_address, datum ChfEnd;

View file

@ -98,7 +98,7 @@ static char rcs_id[] = "$Id: romram49.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
#include <stdlib.h> #include <stdlib.h>
#include <setjmp.h> #include <setjmp.h>
#include <string.h> #include <string.h>
#include <unistd.h> /* access() */ #include <unistd.h> /* access() */
#include <errno.h> #include <errno.h>
#include "config.h" #include "config.h"
@ -111,28 +111,26 @@ static char rcs_id[] = "$Id: romram49.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
#include "args.h" #include "args.h"
#define CHF_MODULE_ID MOD_CHF_MODULE_ID #define CHF_MODULE_ID MOD_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
#define FLASH_VIEW_SELECTOR 0x40000
#define FLASH_BANK_MASK 0x3FFFF
#define FLASH_VIEW_SELECTOR 0x40000 #define CE2_RAM_OFFSET 0x80000
#define FLASH_BANK_MASK 0x3FFFF #define NCE3_RAM_OFFSET 0xC0000
#define NCE3_RAM_MASK 0x3FFFF
#define CE2_RAM_OFFSET 0x80000 #define HDW_LCR_OFFSET 0x1C
#define NCE3_RAM_OFFSET 0xC0000 #define LCR_LED 0x8
#define NCE3_RAM_MASK 0x3FFFF
#define HDW_LCR_OFFSET 0x1C
#define LCR_LED 0x8
/* 3.3: This is no longer static, because flash49.c needs access to /* 3.3: This is no longer static, because flash49.c needs access to
the Flash ROM array... yes, I know this is not particularly nice, the Flash ROM array... yes, I know this is not particularly nice,
*/ */
struct ModStatus_49 *mod_status_49; struct ModStatus_49* mod_status_49;
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Rom module Rom module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -145,42 +143,35 @@ struct ModStatus_49 *mod_status_49;
module status structure, and initializes the Flash Rom module. module status structure, and initializes the Flash Rom module.
.call : .call :
RomInit49(); RomInit49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_F_ROM_INIT MOD_F_ROM_INIT
MOD_F_MOD_STATUS_ALLOC MOD_F_MOD_STATUS_ALLOC
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void RomInit49(void) void RomInit49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomInit49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomInit49" );
if((mod_status_49 = if ( ( mod_status_49 = ( struct ModStatus_49* )malloc( sizeof( struct ModStatus_49 ) ) ) == ( struct ModStatus_49* )NULL ) {
(struct ModStatus_49 *)malloc(sizeof(struct ModStatus_49))) ChfErrnoCondition;
== (struct ModStatus_49 *)NULL) ChfCondition MOD_F_MOD_STATUS_ALLOC, CHF_FATAL, sizeof( struct ModStatus_49 ) ChfEnd;
{ ChfSignal();
ChfErrnoCondition;
ChfCondition MOD_F_MOD_STATUS_ALLOC, CHF_FATAL,
sizeof(struct ModStatus_49) ChfEnd;
ChfSignal();
} }
if(ReadNibblesFromFile(args.rom_file_name, N_FLASH_SIZE_49, if ( ReadNibblesFromFile( args.rom_file_name, N_FLASH_SIZE_49, mod_status_49->flash ) ) {
mod_status_49->flash)) ChfCondition MOD_F_ROM_INIT, CHF_FATAL ChfEnd;
{ ChfSignal();
ChfCondition MOD_F_ROM_INIT, CHF_FATAL ChfEnd;
ChfSignal();
} }
} }
/* .+ /* .+
.title : RomSave49 .title : RomSave49
@ -190,33 +181,30 @@ void RomInit49(void)
This function saves the status of the Flash Rom. This function saves the status of the Flash Rom.
.call : .call :
RomSave49(); RomSave49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_ROM_SAVE MOD_E_ROM_SAVE
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
3.3, 25-Sep-2000, implemented 3.3, 25-Sep-2000, implemented
.- */ .- */
void RomSave49(void) void RomSave49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomSave49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomSave49" );
if(WriteNibblesToFile(mod_status_49->flash, N_FLASH_SIZE_49, if ( WriteNibblesToFile( mod_status_49->flash, N_FLASH_SIZE_49, args.rom_file_name ) ) {
args.rom_file_name)) ChfErrnoCondition;
{ ChfCondition MOD_E_ROM_SAVE, CHF_ERROR ChfEnd;
ChfErrnoCondition; ChfSignal();
ChfCondition MOD_E_ROM_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
} }
} }
/* .+ /* .+
.title : RomRead49 .title : RomRead49
@ -227,30 +215,28 @@ void RomSave49(void)
'rel_address' and returns it. 'rel_address' and returns it.
.call : .call :
d = RomRead49(rel_address); d = RomRead49(rel_address);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
Nibble RomRead49(Address rel_address) Nibble RomRead49( Address rel_address )
{ {
register XAddress view; register XAddress view;
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomRead49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomRead49" );
view = mod_status.hdw.accel.a49.view[ view = mod_status.hdw.accel.a49.view[ ( rel_address & FLASH_VIEW_SELECTOR ) != 0 ];
(rel_address & FLASH_VIEW_SELECTOR) != 0];
return mod_status_49->flash[view | (rel_address & FLASH_BANK_MASK)]; return mod_status_49->flash[ view | ( rel_address & FLASH_BANK_MASK ) ];
} }
/* .+ /* .+
.title : RomWrite49 .title : RomWrite49
@ -266,31 +252,30 @@ Nibble RomRead49(Address rel_address)
Those cycles are silently ignored. Those cycles are silently ignored.
.call : .call :
RomWrite49(rel_address, datum); RomWrite49(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
3.3, 26-Sep-2000, implemented 3.3, 26-Sep-2000, implemented
.- */ .- */
void RomWrite49(Address rel_address, Nibble datum) void RomWrite49( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RomWrite49" );
/* Ignore write cycles through ROM controller; HP49 ROM 1.19-4 /* Ignore write cycles through ROM controller; HP49 ROM 1.19-4
can do this when to ON key is pressed. can do this when to ON key is pressed.
*/ */
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Main Ram module Main Ram module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -302,33 +287,30 @@ void RomWrite49(Address rel_address, Nibble datum)
This function initializes the Ram module. This function initializes the Ram module.
.call : .call :
RamInit49(); RamInit49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_W_RAM_INIT MOD_W_RAM_INIT
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void RamInit49(void) void RamInit49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamInit49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamInit49" );
if(ReadNibblesFromFile(args.ram_file_name, N_RAM_SIZE_49, if ( ReadNibblesFromFile( args.ram_file_name, N_RAM_SIZE_49, mod_status_49->ram ) ) {
mod_status_49->ram)) ChfCondition MOD_W_RAM_INIT, CHF_WARNING ChfEnd;
{ ChfSignal();
ChfCondition MOD_W_RAM_INIT, CHF_WARNING ChfEnd;
ChfSignal();
(void)memset(mod_status_49->ram, 0, sizeof(mod_status_49->ram)); ( void )memset( mod_status_49->ram, 0, sizeof( mod_status_49->ram ) );
} }
} }
/* .+ /* .+
.title : RamSave49 .title : RamSave49
@ -338,32 +320,29 @@ void RamInit49(void)
This function saves the status of the Ram module to disk. This function saves the status of the Ram module to disk.
.call : .call :
RamSave49(); RamSave49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_E_RAM_SAVE MOD_E_RAM_SAVE
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void RamSave49(void) void RamSave49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamSave49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamSave49" );
if(WriteNibblesToFile(mod_status_49->ram, N_RAM_SIZE_49, if ( WriteNibblesToFile( mod_status_49->ram, N_RAM_SIZE_49, args.ram_file_name ) ) {
args.ram_file_name)) ChfErrnoCondition;
{ ChfCondition MOD_E_RAM_SAVE, CHF_ERROR ChfEnd;
ChfErrnoCondition; ChfSignal();
ChfCondition MOD_E_RAM_SAVE, CHF_ERROR ChfEnd;
ChfSignal();
} }
} }
/* .+ /* .+
.title : RamRead49 .title : RamRead49
@ -374,25 +353,24 @@ void RamSave49(void)
and returns it. and returns it.
.call : .call :
d = RamRead49(rel_address); d = RamRead49(rel_address);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
Nibble RamRead49(Address rel_address) Nibble RamRead49( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamRead49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamRead49" );
return mod_status_49->ram[rel_address]; return mod_status_49->ram[ rel_address ];
} }
/* .+ /* .+
.title : RamWrite49 .title : RamWrite49
@ -403,28 +381,27 @@ Nibble RamRead49(Address rel_address)
of the internal RAM. of the internal RAM.
.call : .call :
RamWrite49(rel_address, datum); RamWrite49(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void RamWrite49(Address rel_address, Nibble datum) void RamWrite49( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "RamWrite49" );
mod_status_49->ram[rel_address] = datum; mod_status_49->ram[ rel_address ] = datum;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Ce1 module Ce1 module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -437,34 +414,31 @@ void RamWrite49(Address rel_address, Nibble datum)
Back Switcher. Back Switcher.
.call : .call :
Ce1Init49(); Ce1Init49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void Ce1Init49(void) void Ce1Init49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Init49" );
/* Check if bank-switcher accelerators are valid; if not, initialize /* Check if bank-switcher accelerators are valid; if not, initialize
them to a reasonable value (that is, select Flash Rom bank 0 for them to a reasonable value (that is, select Flash Rom bank 0 for
both views). both views).
*/ */
if(!mod_status.hdw.accel_valid) if ( !mod_status.hdw.accel_valid ) {
{ mod_status.hdw.accel_valid = 1;
mod_status.hdw.accel_valid = 1; mod_status.hdw.accel.a49.view[ 0 ] = mod_status.hdw.accel.a49.view[ 1 ] = ( XAddress )0;
mod_status.hdw.accel.a49.view[0] =
mod_status.hdw.accel.a49.view[1] = (XAddress)0;
} }
} }
/* .+ /* .+
.title : Ce1Save49 .title : Ce1Save49
@ -474,40 +448,36 @@ void Ce1Init49(void)
This function saves the status of the Ce1 module. This function saves the status of the Ce1 module.
.call : .call :
Ce1Save49(); Ce1Save49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void Ce1Save49(void) void Ce1Save49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Save49" );
/* Nothing to be done here; the bank-switcher accelerators are saved /* Nothing to be done here; the bank-switcher accelerators are saved
by the hdw modules by the hdw modules
*/ */
} }
/* This fragment of code is used by both Ce1Read49() and Ce1Write49(); /* This fragment of code is used by both Ce1Read49() and Ce1Write49();
the macro definition is here to allow us to write the code once and the macro definition is here to allow us to write the code once and
use it many times without incurring a function call overhead. use it many times without incurring a function call overhead.
*/ */
#define Ce1SetViews \ #define Ce1SetViews \
{ \ { \
mod_status.hdw.accel.a49.view[0] = \ mod_status.hdw.accel.a49.view[ 0 ] = ( ( XAddress )( ( rel_address >> 5 ) & 0x03 ) << 18 ); \
((XAddress)((rel_address >> 5) & 0x03) << 18); \ \
\ mod_status.hdw.accel.a49.view[ 1 ] = ( ( XAddress )( ( rel_address >> 1 ) & 0x0F ) << 18 ); \
mod_status.hdw.accel.a49.view[1] = \ }
((XAddress)((rel_address >> 1) & 0x0F) << 18); \
}
/* .+ /* .+
@ -522,33 +492,32 @@ void Ce1Save49(void)
most significant bits of addresses when accessing Flash Rom. most significant bits of addresses when accessing Flash Rom.
.call : .call :
d = Ce1Read49(rel_address); d = Ce1Read49(rel_address);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_I_BS_ADDRESS MOD_I_BS_ADDRESS
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
Nibble Ce1Read49(Address rel_address) Nibble Ce1Read49( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Read49" );
debug1(DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address); debug1( DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
/* Save the ROM view base addresses address into the hdw accelerators. /* Save the ROM view base addresses address into the hdw accelerators.
view[] can be directly or-ed with a relative port address to view[] can be directly or-ed with a relative port address to
obtain a valid index in Flash Rom. obtain a valid index in Flash Rom.
*/ */
Ce1SetViews; Ce1SetViews;
return (Nibble)0x0; return ( Nibble )0x0;
} }
/* .+ /* .+
.title : Ce1Write49 .title : Ce1Write49
@ -562,34 +531,33 @@ Nibble Ce1Read49(Address rel_address)
most significant bits of addresses when accessing Flash Rom. most significant bits of addresses when accessing Flash Rom.
.call : .call :
Ce1Write49(rel_address, datum); Ce1Write49(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory; ignored Nibble datum, datum to be written into memory; ignored
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
MOD_I_BS_ADDRESS MOD_I_BS_ADDRESS
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void Ce1Write49(Address rel_address, Nibble datum) void Ce1Write49( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce1Write49" );
debug1(DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address); debug1( DEBUG_C_MODULES, MOD_I_BS_ADDRESS, rel_address );
/* Save the ROM view base addresses address into the hdw accelerators. /* Save the ROM view base addresses address into the hdw accelerators.
view[] can be directly or-ed with a relative port address to view[] can be directly or-ed with a relative port address to
obtain a valid index in Flash Rom. obtain a valid index in Flash Rom.
*/ */
Ce1SetViews; Ce1SetViews;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Ce2 module Ce2 module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -602,13 +570,13 @@ void Ce1Write49(Address rel_address, Nibble datum)
the first bank of ERAM. the first bank of ERAM.
.call : .call :
Ce2Init49(); Ce2Init49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
3.4, 27-Sep-2000, update: 3.4, 27-Sep-2000, update:
@ -616,15 +584,15 @@ void Ce1Write49(Address rel_address, Nibble datum)
HP39/40 firmware. HP39/40 firmware.
.- */ .- */
void Ce2Init49(void) void Ce2Init49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Init49" );
/* Set base of ce2 area */ /* Set base of ce2 area */
mod_status_49->ce2 = mod_status_49->ram + CE2_RAM_OFFSET; mod_status_49->ce2 = mod_status_49->ram + CE2_RAM_OFFSET;
/* CE2 always present and write enabled */ /* CE2 always present and write enabled */
mod_status.hdw.card_status |= (CE2_CARD_PRESENT|CE2_CARD_WE); mod_status.hdw.card_status |= ( CE2_CARD_PRESENT | CE2_CARD_WE );
#if 0 #if 0
/* card_status changed; update, set MP bit in HST and post /* card_status changed; update, set MP bit in HST and post
@ -635,7 +603,6 @@ void Ce2Init49(void)
#endif #endif
} }
/* .+ /* .+
.title : Ce2Save49 .title : Ce2Save49
@ -645,25 +612,24 @@ void Ce2Init49(void)
This function saves the status of the Ce2 module. This function saves the status of the Ce2 module.
.call : .call :
Ce2Save49(); Ce2Save49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void Ce2Save49(void) void Ce2Save49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Save49" );
/* Do nothing; the whole RAM is saved by RamSave49() */ /* Do nothing; the whole RAM is saved by RamSave49() */
} }
/* .+ /* .+
.title : Ce2Read49 .title : Ce2Read49
@ -673,25 +639,24 @@ void Ce2Save49(void)
This function reads a nibble from the Ce2 module. This function reads a nibble from the Ce2 module.
.call : .call :
d = Ce2Read49(rel_address) d = Ce2Read49(rel_address)
.input : .input :
Address rel_address, memory address Address rel_address, memory address
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
Nibble Ce2Read49(Address rel_address) Nibble Ce2Read49( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Read49" );
return mod_status_49->ce2[rel_address]; return mod_status_49->ce2[ rel_address ];
} }
/* .+ /* .+
.title : Ce2Write49 .title : Ce2Write49
@ -701,28 +666,27 @@ Nibble Ce2Read49(Address rel_address)
This function writes a nibble to the Ce2 module. This function writes a nibble to the Ce2 module.
.call : .call :
Ce2Write49(rel_address, datum); Ce2Write49(rel_address, datum);
.input : .input :
Address rel_address, memory address Address rel_address, memory address
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void Ce2Write49(Address rel_address, Nibble datum) void Ce2Write49( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "Ce2Write49" );
mod_status_49->ce2[rel_address] = datum; mod_status_49->ce2[ rel_address ] = datum;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
NCe3 module NCe3 module
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -735,13 +699,13 @@ void Ce2Write49(Address rel_address, Nibble datum)
the first bank of ERAM. the first bank of ERAM.
.call : .call :
NCe3Init49(); NCe3Init49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
3.4, 27-Sep-2000, update: 3.4, 27-Sep-2000, update:
@ -749,15 +713,15 @@ void Ce2Write49(Address rel_address, Nibble datum)
HP39/40 firmware. HP39/40 firmware.
.- */ .- */
void NCe3Init49(void) void NCe3Init49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Init49" );
/* Set base of nce3 area */ /* Set base of nce3 area */
mod_status_49->nce3 = mod_status_49->ram + NCE3_RAM_OFFSET; mod_status_49->nce3 = mod_status_49->ram + NCE3_RAM_OFFSET;
/* NCE3 always present and write enabled */ /* NCE3 always present and write enabled */
mod_status.hdw.card_status |= (NCE3_CARD_PRESENT|NCE3_CARD_WE); mod_status.hdw.card_status |= ( NCE3_CARD_PRESENT | NCE3_CARD_WE );
#if 0 #if 0
/* card_status changed; update, set MP bit in HST and post /* card_status changed; update, set MP bit in HST and post
@ -768,7 +732,6 @@ void NCe3Init49(void)
#endif #endif
} }
/* .+ /* .+
.title : NCe3Save49 .title : NCe3Save49
@ -778,25 +741,24 @@ void NCe3Init49(void)
This function saves the status of the NCe3 module. This function saves the status of the NCe3 module.
.call : .call :
NCe3Save49(); NCe3Save49();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
.- */ .- */
void NCe3Save49(void) void NCe3Save49( void )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Save49" );
/* Do nothing; the whole RAM is saved by RamSave49() */ /* Do nothing; the whole RAM is saved by RamSave49() */
} }
/* .+ /* .+
.title : NCe3Read49 .title : NCe3Read49
@ -814,33 +776,29 @@ void NCe3Save49(void)
the ABSOLUTE address of the memory access. the ABSOLUTE address of the memory access.
.call : .call :
d = NCe3Read49(rel_address) d = NCe3Read49(rel_address)
.input : .input :
Address rel_address, memory address (ABSOLUTE) Address rel_address, memory address (ABSOLUTE)
.output : .output :
Nibble *d, datum read from memory Nibble *d, datum read from memory
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
3.3, 25-Sep-2000, update 3.3, 25-Sep-2000, update
- added vectors into flash49 for FlashROM read ops - added vectors into flash49 for FlashROM read ops
.- */ .- */
Nibble NCe3Read49(Address rel_address) Nibble NCe3Read49( Address rel_address )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Read49" );
return return ( mod_status.hdw.hdw[ HDW_LCR_OFFSET ] & LCR_LED )
(mod_status.hdw.hdw[HDW_LCR_OFFSET] & LCR_LED) ? FlashRead49( mod_status.hdw.accel.a49.view[ ( rel_address & FLASH_VIEW_SELECTOR ) != 0 ] |
? FlashRead49( ( rel_address & FLASH_BANK_MASK ) )
mod_status.hdw.accel.a49.view[ : mod_status_49->nce3[ rel_address & NCE3_RAM_MASK ];
(rel_address & FLASH_VIEW_SELECTOR) != 0]
| (rel_address & FLASH_BANK_MASK))
: mod_status_49->nce3[rel_address & NCE3_RAM_MASK];
} }
/* .+ /* .+
.title : NCe3Write49 .title : NCe3Write49
@ -859,29 +817,27 @@ Nibble NCe3Read49(Address rel_address)
.call : .call :
NCe3Write49(rel_address, datum); NCe3Write49(rel_address, datum);
.input : .input :
Address rel_address, memory address (ABSOLUTE) Address rel_address, memory address (ABSOLUTE)
Nibble datum, datum to be written into memory Nibble datum, datum to be written into memory
.output : .output :
void void
.status_codes : .status_codes :
MOD_I_CALLED MOD_I_CALLED
.notes : .notes :
3.2, 21-Sep-2000, creation 3.2, 21-Sep-2000, creation
3.3, 25-Sep-2000, update 3.3, 25-Sep-2000, update
- added vectors into flash49 for FlashROM write ops - added vectors into flash49 for FlashROM write ops
.- */ .- */
void NCe3Write49(Address rel_address, Nibble datum) void NCe3Write49( Address rel_address, Nibble datum )
{ {
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write49"); debug1( DEBUG_C_TRACE, MOD_I_CALLED, "NCe3Write49" );
if(mod_status.hdw.hdw[HDW_LCR_OFFSET] & LCR_LED) if ( mod_status.hdw.hdw[ HDW_LCR_OFFSET ] & LCR_LED )
FlashWrite49(mod_status.hdw.accel.a49.view[ FlashWrite49( mod_status.hdw.accel.a49.view[ ( rel_address & FLASH_VIEW_SELECTOR ) != 0 ] | ( rel_address & FLASH_BANK_MASK ),
(rel_address & FLASH_VIEW_SELECTOR) != 0] datum );
| (rel_address & FLASH_BANK_MASK),
datum);
else else
mod_status_49->nce3[rel_address & NCE3_RAM_MASK] = datum; mod_status_49->nce3[ rel_address & NCE3_RAM_MASK ] = datum;
} }

File diff suppressed because it is too large Load diff

View file

@ -80,65 +80,62 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macro/Data type definitions Macro/Data type definitions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define SERIAL_RCS_INFO "$Revision: 4.1 $ $State: Rel $" #define SERIAL_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define SERIAL_I_CALLED 101 /* Function %s called */ #define SERIAL_I_CALLED 101 /* Function %s called */
#define SERIAL_I_REVISION 102 /* Serial port emulation rev. %s */ #define SERIAL_I_REVISION 102 /* Serial port emulation rev. %s */
#define SERIAL_I_READ 103 /* Read %s -> %x */ #define SERIAL_I_READ 103 /* Read %s -> %x */
#define SERIAL_I_WRITE 104 /* Write %s %x -> %x */ #define SERIAL_I_WRITE 104 /* Write %s %x -> %x */
#define SERIAL_I_RBR 105 /* Read RBR -> %x */ #define SERIAL_I_RBR 105 /* Read RBR -> %x */
#define SERIAL_I_TBR 106 /* Write TBR <- %x */ #define SERIAL_I_TBR 106 /* Write TBR <- %x */
#define SERIAL_I_PTY_NAME 107 /* Slave pty name is %s */ #define SERIAL_I_PTY_NAME 107 /* Slave pty name is %s */
#define SERIAL_W_EMPTY_RRB 201 /* Read from empty RX buffer, rcs=%x */ #define SERIAL_W_EMPTY_RRB 201 /* Read from empty RX buffer, rcs=%x */
#define SERIAL_W_FULL_TRB 202 /* Write into full TX buffer, tcs=%x */ #define SERIAL_W_FULL_TRB 202 /* Write into full TX buffer, tcs=%x */
#define SERIAL_W_NOPTY 203 /* 3.16: Pty support not available */ #define SERIAL_W_NOPTY 203 /* 3.16: Pty support not available */
#define SERIAL_E_TRB_DRAIN 301 /* Error draining TX buffer */ #define SERIAL_E_TRB_DRAIN 301 /* Error draining TX buffer */
#define SERIAL_E_RRB_CHARGE 302 /* Error charging RX buffer */ #define SERIAL_E_RRB_CHARGE 302 /* Error charging RX buffer */
#define SERIAL_E_PTY_CLOSE 303 /* Error closing pty */ #define SERIAL_E_PTY_CLOSE 303 /* Error closing pty */
#define SERIAL_F_OPENPTY 401 /* openpty() failed on master pty */ #define SERIAL_F_OPENPTY 401 /* openpty() failed on master pty */
#define SERIAL_F_FCNTL 402 /* fcntl() failed on master pty */ #define SERIAL_F_FCNTL 402 /* fcntl() failed on master pty */
#define SERIAL_F_OPEN_MASTER 403 /* Can't open pty master %s */ #define SERIAL_F_OPEN_MASTER 403 /* Can't open pty master %s */
#define SERIAL_F_GRANTPT 404 /* grantpt() failed on master pty */ #define SERIAL_F_GRANTPT 404 /* grantpt() failed on master pty */
#define SERIAL_F_UNLOCKPT 405 /* unlockpt() failed on master pty */ #define SERIAL_F_UNLOCKPT 405 /* unlockpt() failed on master pty */
#define SERIAL_F_OPEN_SLAVE 406 /* Can't open pty slave %s */ #define SERIAL_F_OPEN_SLAVE 406 /* Can't open pty slave %s */
#define SERIAL_F_PUSH 407 /* ioctl(I_PUSH,%s) failed on slave */ #define SERIAL_F_PUSH 407 /* ioctl(I_PUSH,%s) failed on slave */
#define SERIAL_F_TCGETATTR 408 /* tcgetattr() failed on master */ #define SERIAL_F_TCGETATTR 408 /* tcgetattr() failed on master */
#define SERIAL_F_TCSETATTR 409 /* tcsetattr() failed on master */ #define SERIAL_F_TCSETATTR 409 /* tcsetattr() failed on master */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Initialization */ /* Initialization */
const char *SerialInit(void); const char* SerialInit( void );
void SerialClose(void); void SerialClose( void );
/* Information about slave side of pty */ /* Information about slave side of pty */
const char *SerialPtyName(void); const char* SerialPtyName( void );
/* Register read */ /* Register read */
Nibble Serial_IOC_Read(void); Nibble Serial_IOC_Read( void );
Nibble Serial_RCS_Read(void); Nibble Serial_RCS_Read( void );
Nibble Serial_TCS_Read(void); Nibble Serial_TCS_Read( void );
int8 Serial_RBR_Read(void); int8 Serial_RBR_Read( void );
/* Register write */ /* Register write */
void Serial_IOC_Write(Nibble n); void Serial_IOC_Write( Nibble n );
void Serial_RCS_Write(Nibble n); void Serial_RCS_Write( Nibble n );
void Serial_TCS_Write(Nibble n); void Serial_TCS_Write( Nibble n );
void Serial_CRER_Write(Nibble n); void Serial_CRER_Write( Nibble n );
void Serial_TBR_Write(int8 d); void Serial_TBR_Write( int8 d );
/* Event handling */ /* Event handling */
void HandleSerial(void); void HandleSerial( void );

717
src/t48.c
View file

@ -87,391 +87,395 @@ static char rcs_id[] = "$Id: t48.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include "args.h" #include "args.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID X11_CHF_MODULE_ID #define CHF_MODULE_ID X11_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf parameters - Do not change. Chf parameters - Do not change.
The ABNORMAL_EXIT_CODE is taken from stdlib.h (EXIT_FAILURE) The ABNORMAL_EXIT_CODE is taken from stdlib.h (EXIT_FAILURE)
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define MAIN_MSGCAT_NAME "t48.cat" #define MAIN_MSGCAT_NAME "t48.cat"
#define CONDITION_STACK_SIZE 16 #define CONDITION_STACK_SIZE 16
#define HANDLER_STACK_SIZE 8 #define HANDLER_STACK_SIZE 8
#define ABNORMAL_EXIT_CODE EXIT_FAILURE #define ABNORMAL_EXIT_CODE EXIT_FAILURE
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Other parameters Other parameters
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define APP_CLASS "T48" #define APP_CLASS "T48"
#define LCD_BACKGROUND "green" #define LCD_BACKGROUND "green"
#define LCD_FOREGROUND "black" #define LCD_FOREGROUND "black"
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private variables Private variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
static XtAppContext app_context; static XtAppContext app_context;
static Widget shell_widget; static Widget shell_widget;
/* Command line options descriptor */ /* Command line options descriptor */
XrmOptionDescRec options[] = XrmOptionDescRec options[] = {
{ /* option, specifier, argKind, value */
/* option, specifier, argKind, value */ { "-reset", "*reset", XrmoptionNoArg, "True" },
{ "-reset", "*reset", XrmoptionNoArg, "True" }, { "-monitor", "*monitor", XrmoptionNoArg, "True" },
{ "-monitor", "*monitor", XrmoptionNoArg, "True" }, { "-path", "*path", XrmoptionSepArg },
{ "-path", "*path", XrmoptionSepArg }, { "-cpu", "*cpu", XrmoptionSepArg },
{ "-cpu", "*cpu", XrmoptionSepArg }, { "-mod", "*mod", XrmoptionSepArg },
{ "-mod", "*mod", XrmoptionSepArg }, { "-hdw", "*hdw", XrmoptionSepArg },
{ "-hdw", "*hdw", XrmoptionSepArg }, { "-rom", "*rom", XrmoptionSepArg },
{ "-rom", "*rom", XrmoptionSepArg }, { "-ram", "*ram", XrmoptionSepArg },
{ "-ram", "*ram", XrmoptionSepArg }, { "-port1", "*port1", XrmoptionSepArg },
{ "-port1", "*port1", XrmoptionSepArg }, { "-port2", "*port2", XrmoptionSepArg }
{ "-port2", "*port2", XrmoptionSepArg }
}; };
#define NUM_OPTIONS (sizeof(options)/sizeof(XrmOptionDescRec)) #define NUM_OPTIONS ( sizeof( options ) / sizeof( XrmOptionDescRec ) )
/* Application fallback resources */ /* Application fallback resources */
String fallback_resources[] = String fallback_resources[] = {
{ NULL /* Null terminated */
NULL /* Null terminated */
}; };
/* Application options container */ /* Application options container */
struct app_opt struct app_opt {
{ Boolean reset;
Boolean reset; Boolean monitor;
Boolean monitor; Pixel fg_pix;
Pixel fg_pix; Pixel bg_pix;
Pixel bg_pix; String path;
String path; String cpu;
String cpu; String mod;
String mod; String hdw;
String hdw; String rom;
String rom; String ram;
String ram; String port1;
String port1; String port2;
String port2;
}; };
/* Application resources/options descriptor */ /* Application resources/options descriptor */
XtResource app_res[] = XtResource app_res[] = {
{ {"foreground", "Foreground", XtRPixel, sizeof( Pixel ), XtOffsetOf( struct app_opt, fg_pix ), XtRString, LCD_FOREGROUND},
{ "foreground", "Foreground", {"background", "Background", XtRPixel, sizeof( Pixel ), XtOffsetOf( struct app_opt, bg_pix ), XtRString, LCD_BACKGROUND},
XtRPixel, sizeof(Pixel), XtOffsetOf(struct app_opt, fg_pix), {"reset", "Reset", XtRBoolean, sizeof( Boolean ), XtOffsetOf( struct app_opt, reset ), XtRString, "False" },
XtRString, LCD_FOREGROUND {"monitor", "Monitor", XtRBoolean, sizeof( Boolean ), XtOffsetOf( struct app_opt, monitor ), XtRString, "False" },
}, {"path", "Path", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, path ), XtRString, "." },
{ "background", "Background", {"cpu", "Cpu", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, cpu ), XtRString, "cpu" },
XtRPixel, sizeof(Pixel), XtOffsetOf(struct app_opt, bg_pix), {"mod", "Mod", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, mod ), XtRString, "mod" },
XtRString, LCD_BACKGROUND {"hdw", "Hdw", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, hdw ), XtRString, "hdw" },
}, {"rom", "Rom", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, rom ), XtRString, "rom" },
{ "reset", "Reset", {"ram", "Ram", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, ram ), XtRString, "ram" },
XtRBoolean, sizeof(Boolean), XtOffsetOf(struct app_opt, reset), {"port1", "Port1", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, port1 ), XtRString, "port1" },
XtRString, "False" {"port2", "Port2", XtRString, sizeof( String ), XtOffsetOf( struct app_opt, port2 ), XtRString, "port2" }
},
{ "monitor", "Monitor",
XtRBoolean, sizeof(Boolean), XtOffsetOf(struct app_opt, monitor),
XtRString, "False"
},
{ "path", "Path",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, path),
XtRString, "."
},
{ "cpu", "Cpu",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, cpu),
XtRString, "cpu"
},
{ "mod", "Mod",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, mod),
XtRString, "mod"
},
{ "hdw", "Hdw",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, hdw),
XtRString, "hdw"
},
{ "rom", "Rom",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, rom),
XtRString, "rom"
},
{ "ram", "Ram",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, ram),
XtRString, "ram"
},
{ "port1", "Port1",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, port1),
XtRString, "port1"
},
{ "port2", "Port2",
XtRString, sizeof(String), XtOffsetOf(struct app_opt, port2),
XtRString, "port2"
}
}; };
#define NUM_APP_RES (sizeof(app_res)/sizeof(XtResource)) #define NUM_APP_RES ( sizeof( app_res ) / sizeof( XtResource ) )
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public variables Public variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Emulator options */ /* Emulator options */
struct Args args; struct Args args;
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private functions Private functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* KeySym -> HP48 'enum Key' translator */ /* KeySym -> HP48 'enum Key' translator */
static enum Key Ks2K(KeySym ks) static enum Key Ks2K( KeySym ks )
{ {
switch(ks) switch ( ks ) {
{ /* Backspace */
/* Backspace */ case XK_BackSpace:
case XK_BackSpace: return KEY_BKSP; return KEY_BKSP;
/* Delete */ /* Delete */
case XK_Delete: return KEY_DEL; case XK_Delete:
case XK_KP_Delete: return KEY_DEL; return KEY_DEL;
case XK_KP_Delete:
return KEY_DEL;
/* Enter */ /* Enter */
case XK_KP_Enter: return KEY_ENTER; case XK_KP_Enter:
case XK_Return: return KEY_ENTER; return KEY_ENTER;
case XK_Return:
return KEY_ENTER;
/* Cursor keys */ /* Cursor keys */
case XK_KP_Left: return KEY_LEFT; case XK_KP_Left:
case XK_Left: return KEY_LEFT; return KEY_LEFT;
case XK_Left:
return KEY_LEFT;
case XK_KP_Right: return KEY_RIGHT; case XK_KP_Right:
case XK_Right: return KEY_RIGHT; return KEY_RIGHT;
case XK_Right:
return KEY_RIGHT;
case XK_KP_Up: return KEY_UP; case XK_KP_Up:
case XK_Up: return KEY_UP; return KEY_UP;
case XK_Up:
return KEY_UP;
case XK_KP_Down: return KEY_DOWN; case XK_KP_Down:
case XK_Down: return KEY_DOWN; return KEY_DOWN;
case XK_Down:
return KEY_DOWN;
/* Function keys */ /* Function keys */
case XK_F1: return KEY_F1; case XK_F1:
case XK_F2: return KEY_F2; return KEY_F1;
case XK_F3: return KEY_F3; case XK_F2:
case XK_F4: return KEY_F4; return KEY_F2;
case XK_F5: return KEY_F5; case XK_F3:
case XK_F6: return KEY_F6; return KEY_F3;
case XK_F4:
return KEY_F4;
case XK_F5:
return KEY_F5;
case XK_F6:
return KEY_F6;
/* Shift L, R, Alpha, ON */ /* Shift L, R, Alpha, ON */
case XK_Shift_L: return KEY_SH_L; case XK_Shift_L:
case XK_Shift_R: return KEY_SH_R; return KEY_SH_L;
case XK_Alt_L: return KEY_ALPHA; case XK_Shift_R:
case XK_Alt_R: return KEY_ALPHA; return KEY_SH_R;
case XK_Escape: return KEY_ON; case XK_Alt_L:
return KEY_ALPHA;
case XK_Alt_R:
return KEY_ALPHA;
case XK_Escape:
return KEY_ON;
/* Numeric keypad and surroundings */ /* Numeric keypad and surroundings */
case XK_KP_0: return KEY_0; case XK_KP_0:
case XK_KP_1: return KEY_1; return KEY_0;
case XK_KP_2: return KEY_2; case XK_KP_1:
case XK_KP_3: return KEY_3; return KEY_1;
case XK_KP_4: return KEY_4; case XK_KP_2:
case XK_KP_5: return KEY_5; return KEY_2;
case XK_KP_6: return KEY_6; case XK_KP_3:
case XK_KP_7: return KEY_7; return KEY_3;
case XK_KP_8: return KEY_8; case XK_KP_4:
case XK_KP_9: return KEY_9; return KEY_4;
case XK_KP_5:
return KEY_5;
case XK_KP_6:
return KEY_6;
case XK_KP_7:
return KEY_7;
case XK_KP_8:
return KEY_8;
case XK_KP_9:
return KEY_9;
case XK_KP_Decimal: return KEY_DOT; case XK_KP_Decimal:
return KEY_DOT;
case XK_KP_Add: return KEY_ADD; case XK_KP_Add:
case XK_plus: return KEY_ADD; return KEY_ADD;
case XK_plus:
return KEY_ADD;
case XK_KP_Subtract: return KEY_SUB; case XK_KP_Subtract:
case XK_minus: return KEY_SUB; return KEY_SUB;
case XK_minus:
return KEY_SUB;
case XK_KP_Multiply: return KEY_MUL; case XK_KP_Multiply:
case XK_asterisk: return KEY_MUL; return KEY_MUL;
case XK_asterisk:
return KEY_MUL;
case XK_KP_Divide: return KEY_DIV; case XK_KP_Divide:
case XK_slash: return KEY_DIV; return KEY_DIV;
case XK_slash:
return KEY_DIV;
case XK_KP_Space: return KEY_SPC; case XK_KP_Space:
case XK_space: return KEY_SPC; return KEY_SPC;
case XK_space:
return KEY_SPC;
/* Upper half of the keyboard */ /* Upper half of the keyboard */
case XK_1: return KEY_MTH; case XK_1:
case XK_2: return KEY_PRG; return KEY_MTH;
case XK_3: return KEY_CST; case XK_2:
case XK_4: return KEY_VAR; return KEY_PRG;
case XK_5: return KEY_UP; case XK_3:
case XK_6: return KEY_NXT; return KEY_CST;
case XK_4:
return KEY_VAR;
case XK_5:
return KEY_UP;
case XK_6:
return KEY_NXT;
case XK_q: return KEY_AP; case XK_q:
case XK_w: return KEY_STO; return KEY_AP;
case XK_e: return KEY_EVAL; case XK_w:
case XK_r: return KEY_LEFT; return KEY_STO;
case XK_t: return KEY_DOWN; case XK_e:
case XK_y: return KEY_RIGHT; return KEY_EVAL;
case XK_r:
return KEY_LEFT;
case XK_t:
return KEY_DOWN;
case XK_y:
return KEY_RIGHT;
case XK_a: return KEY_SIN; case XK_a:
case XK_s: return KEY_COS; return KEY_SIN;
case XK_d: return KEY_TAN; case XK_s:
case XK_f: return KEY_SQRT; return KEY_COS;
case XK_g: return KEY_POWER; case XK_d:
case XK_h: return KEY_INV; return KEY_TAN;
case XK_f:
return KEY_SQRT;
case XK_g:
return KEY_POWER;
case XK_h:
return KEY_INV;
case XK_z: return KEY_ENTER; case XK_z:
case XK_x: return KEY_ENTER; return KEY_ENTER;
case XK_c: return KEY_CHS; case XK_x:
case XK_v: return KEY_EEX; return KEY_ENTER;
case XK_b: return KEY_DEL; case XK_c:
case XK_n: return KEY_BKSP; return KEY_CHS;
case XK_v:
return KEY_EEX;
case XK_b:
return KEY_DEL;
case XK_n:
return KEY_BKSP;
/* Other useful aliases */ /* Other useful aliases */
case XK_Tab: return KEY_NXT; case XK_Tab:
case XK_apostrophe: return KEY_AP; return KEY_NXT;
case XK_period: return KEY_DOT; case XK_apostrophe:
return KEY_AP;
case XK_period:
return KEY_DOT;
/* Save */ /* Save */
case XK_Control_L: case XK_Control_L:
ModSave(); ModSave();
CpuSave(); CpuSave();
exit(0); exit( 0 );
} }
return KEY_NULL; return KEY_NULL;
} }
/* X Event handler, called by the X Toolkit when appropriate */ /* X Event handler, called by the X Toolkit when appropriate */
static void XEventHandler(Widget w, XtPointer cl_data, XEvent *ev, static void XEventHandler( Widget w, XtPointer cl_data, XEvent* ev, Boolean* cont )
Boolean *cont)
{ {
KeySym ks; KeySym ks;
debug1(DEBUG_C_TRACE|DEBUG_C_X11, X11_I_CALLED, "XEventHandler"); debug1( DEBUG_C_TRACE | DEBUG_C_X11, X11_I_CALLED, "XEventHandler" );
/* Continue to dispatch */ /* Continue to dispatch */
*cont = True; *cont = True;
if(ev->type == Expose) if ( ev->type == Expose ) {
{ debug1( DEBUG_C_X11, X11_I_LCD_EXPOSE, ev->xexpose.count );
debug1(DEBUG_C_X11, X11_I_LCD_EXPOSE, ev->xexpose.count); if ( ev->xexpose.count == 0 )
if(ev->xexpose.count == 0) RefreshLcd(); RefreshLcd();
}
else if(ev->type == KeyPress || ev->type == KeyRelease)
{
(void)XLookupString((XKeyEvent *)ev, (char *)NULL, 0, &ks,
(XComposeStatus *)NULL);
if(ev->type == KeyPress)
{
debug1(DEBUG_C_X11, X11_I_KEY_PRESS, ks);
KeybPress(Ks2K(ks));
} }
else if(ev->type = KeyRelease) else if ( ev->type == KeyPress || ev->type == KeyRelease ) {
{ ( void )XLookupString( ( XKeyEvent* )ev, ( char* )NULL, 0, &ks, ( XComposeStatus* )NULL );
debug1(DEBUG_C_X11, X11_I_KEY_RELEASE, ks);
KeybRelease(Ks2K(ks));
}
}
else if ( ev->type == KeyPress ) {
{ debug1( DEBUG_C_X11, X11_I_KEY_PRESS, ks );
/* Unknown X Event - discard */ KeybPress( Ks2K( ks ) );
debug1(DEBUG_C_X11, X11_I_X_EVENT, ev->type); }
}
else if ( ev->type = KeyRelease ) {
debug1( DEBUG_C_X11, X11_I_KEY_RELEASE, ks );
KeybRelease( Ks2K( ks ) );
}
}
else {
/* Unknown X Event - discard */
debug1( DEBUG_C_X11, X11_I_X_EVENT, ev->type );
}
} }
/* Path/name dynamic allocator */ /* Path/name dynamic allocator */
static char *GetPathname(String path, String name) static char* GetPathname( String path, String name )
{ {
char *s = malloc(strlen(path)+strlen(name)+2); char* s = malloc( strlen( path ) + strlen( name ) + 2 );
strcpy(s, path); strcat(s, "/"); strcat(s, name); strcpy( s, path );
return s; strcat( s, "/" );
strcat( s, name );
return s;
} }
/* Initialize the X interface */ /* Initialize the X interface */
void InitializeX(int argc, char *argv[], struct app_opt *opt) void InitializeX( int argc, char* argv[], struct app_opt* opt )
{ {
unsigned long fg_pix, bg_pix; unsigned long fg_pix, bg_pix;
XSetWindowAttributes attr; XSetWindowAttributes attr;
Arg xt_args[20]; Arg xt_args[ 20 ];
int n; int n;
debug1(DEBUG_C_TRACE, X11_I_CALLED, "InitializeX"); debug1( DEBUG_C_TRACE, X11_I_CALLED, "InitializeX" );
/* Setup Arg vector for shell widget creation */ /* Setup Arg vector for shell widget creation */
n = 0; n = 0;
XtSetArg(xt_args[n], XtNwidth, 131*2+2*8); n++; XtSetArg( xt_args[ n ], XtNwidth, 131 * 2 + 2 * 8 );
XtSetArg(xt_args[n], XtNminWidth, 131*2+2*8); n++; n++;
XtSetArg(xt_args[n], XtNmaxWidth, 131*2+2*8); n++; XtSetArg( xt_args[ n ], XtNminWidth, 131 * 2 + 2 * 8 );
XtSetArg(xt_args[n], XtNheight, 64*2+28); n++; n++;
XtSetArg(xt_args[n], XtNminHeight, 64*2+28); n++; XtSetArg( xt_args[ n ], XtNmaxWidth, 131 * 2 + 2 * 8 );
XtSetArg(xt_args[n], XtNmaxHeight, 64*2+28); n++; n++;
XtSetArg(xt_args[n], XtNx, 0); n++; XtSetArg( xt_args[ n ], XtNheight, 64 * 2 + 28 );
XtSetArg(xt_args[n], XtNy, 0); n++; n++;
XtSetArg(xt_args[n], XtNinput, True); n++; XtSetArg( xt_args[ n ], XtNminHeight, 64 * 2 + 28 );
n++;
XtSetArg( xt_args[ n ], XtNmaxHeight, 64 * 2 + 28 );
n++;
XtSetArg( xt_args[ n ], XtNx, 0 );
n++;
XtSetArg( xt_args[ n ], XtNy, 0 );
n++;
XtSetArg( xt_args[ n ], XtNinput, True );
n++;
/* Initialize application, parse command line options, /* Initialize application, parse command line options,
create its main shell. create its main shell.
*/ */
shell_widget = XtAppInitialize( shell_widget = XtAppInitialize( &app_context, APP_CLASS, options, NUM_OPTIONS, &argc, argv, fallback_resources, xt_args, n );
&app_context,
APP_CLASS,
options, NUM_OPTIONS,
&argc, argv,
fallback_resources,
xt_args, n
);
/* Check unknown options - argv[0] always contains program name */ /* Check unknown options - argv[0] always contains program name */
if(argc > 1) if ( argc > 1 ) {
{ int i;
int i; for ( i = 1; i < argc; i++ )
for(i=1; i<argc; i++) ChfCondition X11_E_BAD_OPTION, CHF_ERROR, argv[ i ] ChfEnd;
ChfCondition X11_E_BAD_OPTION, CHF_ERROR, argv[i] ChfEnd;
ChfCondition X11_I_USAGE, CHF_INFO, argv[0] ChfEnd; ChfCondition X11_I_USAGE, CHF_INFO, argv[ 0 ] ChfEnd;
ChfSignal(); ChfSignal();
} }
/* Get application options and fill the 'struct app_opt opt' structure */ /* Get application options and fill the 'struct app_opt opt' structure */
XtGetApplicationResources( XtGetApplicationResources( shell_widget, ( XtPointer )opt, app_res, NUM_APP_RES, ( ArgList )NULL, ( Cardinal )0 );
shell_widget,
(XtPointer)opt,
app_res,
NUM_APP_RES,
(ArgList)NULL,
(Cardinal)0
);
/* Add private event handler for the main shell */ /* Add private event handler for the main shell */
XtAddEventHandler( XtAddEventHandler( shell_widget, KeyPressMask | KeyReleaseMask | ExposureMask, False, /* Don't call with non-maskable events */
shell_widget, XEventHandler, ( XtPointer )NULL );
KeyPressMask|KeyReleaseMask|ExposureMask,
False, /* Don't call with non-maskable events */
XEventHandler,
(XtPointer)NULL
);
/* Realize shell widget */ /* Realize shell widget */
XtRealizeWidget(shell_widget); XtRealizeWidget( shell_widget );
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -484,41 +488,40 @@ void InitializeX(int argc, char *argv[], struct app_opt *opt)
It must handle the X Events relevant for the application. It must handle the X Events relevant for the application.
.call : .call :
HandleXEvents(); HandleXEvents();
.input : .input :
void void
.output : .output :
void void
.status_codes : .status_codes :
X11_I_CALLED X11_I_CALLED
X11_I_LCD_EXPOSE X11_I_LCD_EXPOSE
X11_I_KEY_PRESS X11_I_KEY_PRESS
X11_I_KEY_RELEASE X11_I_KEY_RELEASE
X11_I_X_EVENT X11_I_X_EVENT
.notes : .notes :
1.1, 19-Feb-1998, creation 1.1, 19-Feb-1998, creation
.- */ .- */
void HandleXEvents(void) void HandleXEvents( void )
{ {
debug1(DEBUG_C_TRACE, X11_I_CALLED, "HandleXEvents"); debug1( DEBUG_C_TRACE, X11_I_CALLED, "HandleXEvents" );
/* If there is at least one event pending, process the first event. /* If there is at least one event pending, process the first event.
NOTE: This is an IF instead of a WHILE for two reasons: NOTE: This is an IF instead of a WHILE for two reasons:
- to be sure that X Events related to the keyboard interface are - to be sure that X Events related to the keyboard interface are
actually 'seen' by the HP48, since the current keyboard emulator actually 'seen' by the HP48, since the current keyboard emulator
has no key memory. has no key memory.
- this function will be called again very soon, so the Events queue - this function will be called again very soon, so the Events queue
will not starve anyway. will not starve anyway.
*/ */
if(XtAppPending(app_context)) if ( XtAppPending( app_context ) )
XtAppProcessEvent(app_context, XtIMAll); XtAppProcessEvent( app_context, XtIMAll );
} }
/* .+ /* .+
.title : main .title : main
@ -531,66 +534,60 @@ void HandleXEvents(void)
1.1, 19-Feb-1998, creation 1.1, 19-Feb-1998, creation
.- */ .- */
int main(int argc, char *argv[]) int main( int argc, char* argv[] )
{ {
struct app_opt opt; struct app_opt opt;
/* Chf initialization with msgcat subsystem */ /* Chf initialization with msgcat subsystem */
if(ChfMsgcatInit( if ( ChfMsgcatInit( argv[ 0 ], /* Application's name */
argv[0], /* Application's name */ CHF_DEFAULT, /* Options */
CHF_DEFAULT, /* Options */ MAIN_MSGCAT_NAME, /* Name of the message catalog */
MAIN_MSGCAT_NAME, /* Name of the message catalog */ CONDITION_STACK_SIZE, /* Size of the condition stack */
CONDITION_STACK_SIZE, /* Size of the condition stack */ HANDLER_STACK_SIZE, /* Size of the handler stack */
HANDLER_STACK_SIZE, /* Size of the handler stack */ ABNORMAL_EXIT_CODE /* Abnormal exit code */
ABNORMAL_EXIT_CODE /* Abnormal exit code */ ) != CHF_S_OK ) {
) != CHF_S_OK) fprintf( stderr, "Chf initialization failed\n" );
{ exit( ABNORMAL_EXIT_CODE );
fprintf(stderr, "Chf initialization failed\n"); }
exit(ABNORMAL_EXIT_CODE);
}
debug1(DEBUG_C_TRACE|DEBUG_C_REVISION, X11_I_REVISION, "$Id: t48.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $"); debug1( DEBUG_C_TRACE | DEBUG_C_REVISION, X11_I_REVISION, "$Id: t48.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $" );
/* Initialize X */ /* Initialize X */
InitializeX(argc, argv, &opt); InitializeX( argc, argv, &opt );
/* Initialize LCD window */ /* Initialize LCD window */
InitLcd(XtDisplay(shell_widget), XtWindow(shell_widget), InitLcd( XtDisplay( shell_widget ), XtWindow( shell_widget ), opt.fg_pix, opt.bg_pix );
opt.fg_pix, opt.bg_pix);
/* Fill the emulator options data structure */ /* Fill the emulator options data structure */
args.cpu_file_name = GetPathname(opt.path, opt.cpu); args.cpu_file_name = GetPathname( opt.path, opt.cpu );
args.mod_file_name = GetPathname(opt.path, opt.mod); args.mod_file_name = GetPathname( opt.path, opt.mod );
args.hdw_file_name = GetPathname(opt.path, opt.hdw); args.hdw_file_name = GetPathname( opt.path, opt.hdw );
args.rom_file_name = GetPathname(opt.path, opt.rom); args.rom_file_name = GetPathname( opt.path, opt.rom );
args.ram_file_name = GetPathname(opt.path, opt.ram); args.ram_file_name = GetPathname( opt.path, opt.ram );
args.port_1_file_name = GetPathname(opt.path, opt.port1); args.port_1_file_name = GetPathname( opt.path, opt.port1 );
args.port_2_file_name = GetPathname(opt.path, opt.port2); args.port_2_file_name = GetPathname( opt.path, opt.port2 );
/* Initialize peripheral modules */ /* Initialize peripheral modules */
ModInit(); ModInit();
/* Initialize peripheral modules */ /* Initialize peripheral modules */
CpuInit(); CpuInit();
/* Reset the system, if required */ /* Reset the system, if required */
if(opt.reset) if ( opt.reset ) {
{ ModReset();
ModReset(); CpuReset();
CpuReset(); }
}
if(opt.monitor) if ( opt.monitor ) {
{ /* Call Monitor */
/* Call Monitor */ Monitor();
Monitor(); }
}
else else {
{ /* Call Emulator directly */
/* Call Emulator directly */ Emulator();
Emulator(); }
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

1710
src/x11.c

File diff suppressed because it is too large Load diff

View file

@ -101,57 +101,52 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macro/Data type definitions Macro/Data type definitions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define X11_RCS_INFO "$Revision: 4.1 $ $State: Rel $" #define X11_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
typedef void (*FsbContinuation)(int proceed, char *file_name);
typedef void ( *FsbContinuation )( int proceed, char* file_name );
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Global variables Global variables
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define X11_I_CALLED 101 /* Function %s called */ #define X11_I_CALLED 101 /* Function %s called */
#define X11_I_LCD_PAR 102 /* LCD Parameter %s: %x */ #define X11_I_LCD_PAR 102 /* LCD Parameter %s: %x */
#define X11_I_LCD_EXPOSE 103 /* LCD X Expose event, count=%d */ #define X11_I_LCD_EXPOSE 103 /* LCD X Expose event, count=%d */
#define X11_I_KEY_PRESS 104 /* 2.1: Pressed key %s */ #define X11_I_KEY_PRESS 104 /* 2.1: Pressed key %s */
#define X11_I_KEY_RELEASE 105 /* 2.1: Released key %s */ #define X11_I_KEY_RELEASE 105 /* 2.1: Released key %s */
#define X11_I_REVISION 107 /* X11 interface revision: %s */ #define X11_I_REVISION 107 /* X11 interface revision: %s */
#define X11_I_USAGE 108 /* Usage %s: ... */ #define X11_I_USAGE 108 /* Usage %s: ... */
#define X11_I_FACE 109 /* Selected face %s */ #define X11_I_FACE 109 /* Selected face %s */
#define X11_I_NKEYS 110 /* The face has %d keys */ #define X11_I_NKEYS 110 /* The face has %d keys */
#define X11_I_KEY 111 /* Creating key %d, inOut %s */ #define X11_I_KEY 111 /* Creating key %d, inOut %s */
#define X11_I_FOUND_CS 112 /* Found cs widget %s, value %s */ #define X11_I_FOUND_CS 112 /* Found cs widget %s, value %s */
#define X11_I_HIER 113 /* Traversing widget %s */ #define X11_I_HIER 113 /* Traversing widget %s */
#define X11_I_HIER_NC 114 /* Current widget has %d children */ #define X11_I_HIER_NC 114 /* Current widget has %d children */
#define X11_W_BAD_ACTION_CALL 201 /* Xt Action called with %d args */ #define X11_W_BAD_ACTION_CALL 201 /* Xt Action called with %d args */
#define X11_W_UNKNOWN_ATOM 202 /* X Atom %s unknown */ #define X11_W_UNKNOWN_ATOM 202 /* X Atom %s unknown */
#define X11_W_NO_FSB_CONT 203 /* 3.13: FSB continuation not set */ #define X11_W_NO_FSB_CONT 203 /* 3.13: FSB continuation not set */
#define X11_W_TOO_MANY_MSG 204 /* 3.15: Too many messages (max %d) */ #define X11_W_TOO_MANY_MSG 204 /* 3.15: Too many messages (max %d) */
#define X11_E_BAD_OPTION 301 /* Invalid option: %s */ #define X11_E_BAD_OPTION 301 /* Invalid option: %s */
#define X11_E_NO_WM_COMMAND 302 /* WM_COMMAND property bad/not set */ #define X11_E_NO_WM_COMMAND 302 /* WM_COMMAND property bad/not set */
#define X11_E_NO_FSB_TSEG 303 /* 3.13: No txt seg in fsb XmString */ #define X11_E_NO_FSB_TSEG 303 /* 3.13: No txt seg in fsb XmString */
#define X11_F_X_ERROR 401 /* X Window System fatal error */ #define X11_F_X_ERROR 401 /* X Window System fatal error */
#define X11_F_NO_KEYS 402 /* 3.15: Face has no keys */ #define X11_F_NO_KEYS 402 /* 3.15: Face has no keys */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
void HandleXEvents(void); void HandleXEvents( void );
void IdleXLoop(unsigned long max_wait); void IdleXLoop( unsigned long max_wait );
void InitializeGui(int argc, char *argv[]); void InitializeGui( int argc, char* argv[] );
void ActivateFSB(char *title, char *file_name, FsbContinuation continuation); void ActivateFSB( char* title, char* file_name, FsbContinuation continuation );

View file

@ -94,88 +94,71 @@ static char rcs_id[] = "$Id: x_func.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <X11/Xlib.h> /* Main X header */ #include <X11/Xlib.h> /* Main X header */
#include <X11/Intrinsic.h> /* Main Xt header */ #include <X11/Intrinsic.h> /* Main Xt header */
#include "config.h" #include "config.h"
#include "machdep.h" #include "machdep.h"
#include "cpu.h" #include "cpu.h"
#include "modules.h" #include "modules.h"
#include "disk_io.h" #include "disk_io.h"
#include "x11.h" /* ActivateFSB() */ #include "x11.h" /* ActivateFSB() */
#include "x_func.h" #include "x_func.h"
#include "args.h" #include "args.h"
#include "debug.h" #include "debug.h"
#define CHF_MODULE_ID X_FUNC_CHF_MODULE_ID #define CHF_MODULE_ID X_FUNC_CHF_MODULE_ID
#include <Chf.h> #include <Chf.h>
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private functions: CPU access Private functions: CPU access
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Return the A field of a DataRegister as an integer. */ /* Return the A field of a DataRegister as an integer. */
static int R2int(const Nibble *r) static int R2int( const Nibble* r )
{ {
return( return ( ( ( int )r[ 0 ] ) | ( ( int )r[ 1 ] << 4 ) | ( ( int )r[ 2 ] << 8 ) | ( ( int )r[ 3 ] << 12 ) | ( ( int )r[ 4 ] << 16 ) );
((int)r[0] ) |
((int)r[1] << 4) |
((int)r[2] << 8) |
((int)r[3] << 12) |
((int)r[4] << 16)
);
} }
/* Return the contents of the byte pointed by addr. /* Return the contents of the byte pointed by addr.
Memory is accessed through ReadNibble() Memory is accessed through ReadNibble()
*/ */
static int ByteFromAddress(Address addr) static int ByteFromAddress( Address addr ) { return ( int )ReadNibble( addr ) + ( int )ReadNibble( addr + 1 ) * 16; }
{
return (int)ReadNibble(addr) + (int)ReadNibble(addr+1) * 16;
}
/* Return a dynamically-allocated copy of the contents of the IDNT /* Return a dynamically-allocated copy of the contents of the IDNT
object pointed by D1. D1 points to the *body* of the object pointed by D1. D1 points to the *body* of the
RPL object, that is, to the IDNT length byte directly and *not* RPL object, that is, to the IDNT length byte directly and *not*
to the prologue. to the prologue.
*/ */
static char *NameFromD1(void) static char* NameFromD1( void )
{ {
Address addr = cpu_status.D1; /* Points to the IDNT body */ Address addr = cpu_status.D1; /* Points to the IDNT body */
int len = ByteFromAddress(addr); /* IDNT length */ int len = ByteFromAddress( addr ); /* IDNT length */
char *name = XtMalloc(len+1); /* IDNT name buffer */ char* name = XtMalloc( len + 1 ); /* IDNT name buffer */
int c; int c;
/* Read the name; toascii() is there to avoid 'strange' characters */ /* Read the name; toascii() is there to avoid 'strange' characters */
for(c=0; c<len; c++) for ( c = 0; c < len; c++ ) {
{ addr += 2;
addr += 2; name[ c ] = ( char )toascii( ByteFromAddress( addr ) );
name[c] = (char)toascii(ByteFromAddress(addr));
} }
name[c] = '\0'; /* Terminate and return the name */ name[ c ] = '\0'; /* Terminate and return the name */
return name; return name;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Private functions: action routines Private functions: action routines
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Set the emulator speed to the given value (in MHz); the desired speed /* Set the emulator speed to the given value (in MHz); the desired speed
value is held in the A field of the C CPU register. No handshake. value is held in the A field of the C CPU register. No handshake.
*/ */
static void SetSpeed(Nibble function_code) static void SetSpeed( Nibble function_code )
{ {
debug1(DEBUG_C_TRACE, X_FUNC_I_CALLED, "SetSpeed"); debug1( DEBUG_C_TRACE, X_FUNC_I_CALLED, "SetSpeed" );
#ifndef REAL_CPU_SPEED #ifndef REAL_CPU_SPEED
ChfCondition X_FUNC_E_NO_SPEED, CHF_ERROR ChfEnd; ChfCondition X_FUNC_E_NO_SPEED, CHF_ERROR ChfEnd;
@ -183,149 +166,131 @@ static void SetSpeed(Nibble function_code)
#else #else
{ {
int new_speed; int new_speed;
/* Get new_speed from A field of C register */ /* Get new_speed from A field of C register */
new_speed = R2int(cpu_status.C); new_speed = R2int( cpu_status.C );
/* Compute inner loop limit; 4 is the real CPU speed in MHz when /* Compute inner loop limit; 4 is the real CPU speed in MHz when
the limit is set to INNER_LOOP_MAX. No overflow checks, the limit is set to INNER_LOOP_MAX. No overflow checks,
because new_speed is >=0, has an architectural upper limit of 2^20, because new_speed is >=0, has an architectural upper limit of 2^20,
and int are at least 2^31. and int are at least 2^31.
*/ */
cpu_status.inner_loop_max = (new_speed * INNER_LOOP_MAX) / 4; cpu_status.inner_loop_max = ( new_speed * INNER_LOOP_MAX ) / 4;
/* Notify the user about the speed change */ /* Notify the user about the speed change */
if(cpu_status.inner_loop_max) if ( cpu_status.inner_loop_max )
ChfCondition X_FUNC_I_SET_SPEED, CHF_INFO, new_speed ChfEnd; ChfCondition X_FUNC_I_SET_SPEED, CHF_INFO, new_speed ChfEnd;
else else
ChfCondition X_FUNC_I_MAX_SPEED, CHF_INFO ChfEnd; ChfCondition X_FUNC_I_MAX_SPEED, CHF_INFO ChfEnd;
ChfSignal(); ChfSignal();
} }
#endif #endif
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* This array holds the binary headers for all known hw configurations; /* This array holds the binary headers for all known hw configurations;
here, '?' is a wildcard character when reading from file here, '?' is a wildcard character when reading from file
(see ReadObjectFromFile()) and is replaced by 'S' when writing (see ReadObjectFromFile()) and is replaced by 'S' when writing
to file (see WriteObjectToFile()). to file (see WriteObjectToFile()).
*/ */
struct BinHdrMapping struct BinHdrMapping {
{ char* hw;
char *hw; char* hdr;
char *hdr;
}; };
static const struct BinHdrMapping bin_hdr_mapping[] = static const struct BinHdrMapping bin_hdr_mapping[] = {
{ {"hp48", "HPHP48-?"},
{ "hp48", "HPHP48-?" }, {"hp49", "HPHP49-?"}
{ "hp49", "HPHP49-?" }
}; };
#define N_BIN_HDR_MAPPING (sizeof(bin_hdr_mapping)/sizeof(bin_hdr_mapping[0])) #define N_BIN_HDR_MAPPING ( sizeof( bin_hdr_mapping ) / sizeof( bin_hdr_mapping[ 0 ] ) )
/* Return the header of binary files for current hw configuration; /* Return the header of binary files for current hw configuration;
return NULL if the header cannot be determined. In the latter case, return NULL if the header cannot be determined. In the latter case,
generate an appropriate condition. generate an appropriate condition.
*/ */
static const char *BinaryHeader(void) static const char* BinaryHeader( void )
{ {
int i; int i;
for(i=0; i<N_BIN_HDR_MAPPING; i++) for ( i = 0; i < N_BIN_HDR_MAPPING; i++ )
if(strcmp(args.hw, bin_hdr_mapping[i].hw) == 0) if ( strcmp( args.hw, bin_hdr_mapping[ i ].hw ) == 0 )
return bin_hdr_mapping[i].hdr; return bin_hdr_mapping[ i ].hdr;
ChfCondition X_FUNC_E_NO_BIN_HDR, CHF_ERROR, args.hw ChfEnd; ChfCondition X_FUNC_E_NO_BIN_HDR, CHF_ERROR, args.hw ChfEnd;
return (char *)NULL; return ( char* )NULL;
} }
/* This function is the continuation of Kget(); it is invoked when the /* This function is the continuation of Kget(); it is invoked when the
user interaction with the FSB ends. user interaction with the FSB ends.
*/ */
static void KgetContinuation(int proceed, char *file_name) static void KgetContinuation( int proceed, char* file_name )
{ {
/* Check whether continuation should proceed */ /* Check whether continuation should proceed */
if(!proceed) if ( !proceed ) {
{ ChfCondition X_FUNC_W_ABORTED, CHF_WARNING ChfEnd;
ChfCondition X_FUNC_W_ABORTED, CHF_WARNING ChfEnd; ChfSignal();
ChfSignal();
} }
else else {
{ /* Ok to proceed; read:
/* Ok to proceed; read: - target start address from A[A]
- target start address from A[A] - target end address from C[A]
- target end address from C[A] - binary header with BinaryHeader()
- binary header with BinaryHeader() */
*/ int start_addr = R2int( cpu_status.A );
int start_addr = R2int(cpu_status.A); int end_addr = R2int( cpu_status.C );
int end_addr = R2int(cpu_status.C); const char* bin_hdr = BinaryHeader();
const char *bin_hdr = BinaryHeader();
debug1(DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name); debug1( DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name );
debug3(DEBUG_C_X_FUNC, X_FUNC_I_KGET, start_addr, end_addr, bin_hdr); debug3( DEBUG_C_X_FUNC, X_FUNC_I_KGET, start_addr, end_addr, bin_hdr );
if(bin_hdr == (const char *)NULL if ( bin_hdr == ( const char* )NULL || ReadObjectFromFile( file_name, bin_hdr, ( Address )start_addr, ( Address )end_addr ) ) {
|| ReadObjectFromFile(file_name, bin_hdr, (Address)start_addr, ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
(Address)end_addr)) ChfSignal();
{ }
ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
ChfSignal();
}
} }
CpuRunRequest(); CpuRunRequest();
} }
/* This function is the continuation of Send(); it is invoked when the /* This function is the continuation of Send(); it is invoked when the
user interaction with the FSB ends. user interaction with the FSB ends.
*/ */
static void SendContinuation(int proceed, char *file_name) static void SendContinuation( int proceed, char* file_name )
{ {
if(!proceed) if ( !proceed ) {
{ ChfCondition X_FUNC_W_ABORTED, CHF_WARNING ChfEnd;
ChfCondition X_FUNC_W_ABORTED, CHF_WARNING ChfEnd; ChfSignal();
ChfSignal();
} }
else else {
{ /* Ok to proceed; read:
/* Ok to proceed; read: - source start address from A[A]
- source start address from A[A] - source end address from C[A]
- source end address from C[A] - binary header with BinaryHeader()
- binary header with BinaryHeader() */
*/ int start_addr = R2int( cpu_status.A );
int start_addr = R2int(cpu_status.A); int end_addr = R2int( cpu_status.C );
int end_addr = R2int(cpu_status.C); const char* bin_hdr = BinaryHeader();
const char *bin_hdr = BinaryHeader();
debug1(DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name); debug1( DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name );
debug3(DEBUG_C_X_FUNC, X_FUNC_I_SEND, start_addr, end_addr, bin_hdr); debug3( DEBUG_C_X_FUNC, X_FUNC_I_SEND, start_addr, end_addr, bin_hdr );
if(bin_hdr == (const char *)NULL if ( bin_hdr == ( const char* )NULL || WriteObjectToFile( ( Address )start_addr, ( Address )end_addr, bin_hdr, file_name ) ) {
|| WriteObjectToFile((Address)start_addr, ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
(Address)end_addr, bin_hdr, file_name)) ChfSignal();
{ }
ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
ChfSignal();
}
} }
CpuRunRequest(); CpuRunRequest();
} }
/* This function does the setup of a transfer, performing the following /* This function does the setup of a transfer, performing the following
actions: actions:
@ -336,137 +301,117 @@ static void SendContinuation(int proceed, char *file_name)
be invoked when the user interaction ends be invoked when the user interaction ends
- Halts the CPU - Halts the CPU
*/ */
static void SetupXfer( static void SetupXfer( int msg, const char* def_msg, FsbContinuation cont )
int msg, const char *def_msg, FsbContinuation cont)
{ {
debug1(DEBUG_C_TRACE, X_FUNC_I_CALLED, "SetupXfer"); debug1( DEBUG_C_TRACE, X_FUNC_I_CALLED, "SetupXfer" );
if(CpuHaltAllowed()) if ( CpuHaltAllowed() ) {
{ char* fsb_title = XtNewString( ChfGetMessage( CHF_MODULE_ID, msg, def_msg ) );
char *fsb_title =
XtNewString(ChfGetMessage(CHF_MODULE_ID, msg, def_msg));
char *fsb_file = char* fsb_file = NameFromD1();
NameFromD1();
ActivateFSB(fsb_title, fsb_file, cont); ActivateFSB( fsb_title, fsb_file, cont );
/* Free *before* CpuHaltRequest() because it does not return, and /* Free *before* CpuHaltRequest() because it does not return, and
ActivateFSB() copied its argument when necessary. ActivateFSB() copied its argument when necessary.
*/ */
XtFree(fsb_title); XtFree( fsb_title );
XtFree(fsb_file); XtFree( fsb_file );
(void)CpuHaltRequest(); ( void )CpuHaltRequest();
} }
else else {
{ ChfCondition X_FUNC_E_NO_HALT, CHF_ERROR ChfEnd;
ChfCondition X_FUNC_E_NO_HALT, CHF_ERROR ChfEnd; ChfSignal();
ChfSignal();
} }
} }
/* This is the emulator's extended function for 'kget': this function /* This is the emulator's extended function for 'kget': this function
transfers a file from disk into the calculator's memory. transfers a file from disk into the calculator's memory.
*/ */
static void Kget(Nibble function_code) static void Kget( Nibble function_code )
{ {
debug1(DEBUG_C_TRACE, X_FUNC_I_CALLED, "Kget"); debug1( DEBUG_C_TRACE, X_FUNC_I_CALLED, "Kget" );
/* Setup File Selection Box if transfers are *not* in batch mode */ /* Setup File Selection Box if transfers are *not* in batch mode */
if(! args.batchXfer) if ( !args.batchXfer )
SetupXfer(X_FUNC_M_KGET, "Kget", KgetContinuation); SetupXfer( X_FUNC_M_KGET, "Kget", KgetContinuation );
else else {
{ /* Ok to proceed; read:
/* Ok to proceed; read: - file name from @D1
- file name from @D1 - target start address from A[A]
- target start address from A[A] - target end address from C[A]
- target end address from C[A] - binary header with BinaryHeader()
- binary header with BinaryHeader() */
*/ char* file_name = NameFromD1();
char *file_name = NameFromD1(); int start_addr = R2int( cpu_status.A );
int start_addr = R2int(cpu_status.A); int end_addr = R2int( cpu_status.C );
int end_addr = R2int(cpu_status.C); const char* bin_hdr = BinaryHeader();
const char *bin_hdr = BinaryHeader();
debug1(DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name); debug1( DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name );
debug3(DEBUG_C_X_FUNC, X_FUNC_I_KGET, start_addr, end_addr, bin_hdr); debug3( DEBUG_C_X_FUNC, X_FUNC_I_KGET, start_addr, end_addr, bin_hdr );
if(bin_hdr == (const char *)NULL if ( bin_hdr == ( const char* )NULL || ReadObjectFromFile( file_name, bin_hdr, ( Address )start_addr, ( Address )end_addr ) ) {
|| ReadObjectFromFile(file_name, bin_hdr, (Address)start_addr, ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
(Address)end_addr)) ChfSignal();
{ }
ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
ChfSignal();
}
} }
} }
/* This is the emulator's extended function for 'send': this function /* This is the emulator's extended function for 'send': this function
transfers an object from the calculator's memory into a disk file. transfers an object from the calculator's memory into a disk file.
*/ */
static void Send(Nibble function_code) static void Send( Nibble function_code )
{ {
debug1(DEBUG_C_TRACE, X_FUNC_I_CALLED, "Send"); debug1( DEBUG_C_TRACE, X_FUNC_I_CALLED, "Send" );
/* Setup File Selection Box if transfers are *not* in batch mode */ /* Setup File Selection Box if transfers are *not* in batch mode */
if(! args.batchXfer) if ( !args.batchXfer )
SetupXfer(X_FUNC_M_SEND, "Send", SendContinuation); SetupXfer( X_FUNC_M_SEND, "Send", SendContinuation );
else else {
{ /* Ok to proceed; read:
/* Ok to proceed; read: - file name from @D1
- file name from @D1 - source start address from A[A]
- source start address from A[A] - source end address from C[A]
- source end address from C[A] - binary header with BinaryHeader()
- binary header with BinaryHeader() */
*/ char* file_name = NameFromD1();
char *file_name = NameFromD1(); int start_addr = R2int( cpu_status.A );
int start_addr = R2int(cpu_status.A); int end_addr = R2int( cpu_status.C );
int end_addr = R2int(cpu_status.C); const char* bin_hdr = BinaryHeader();
const char *bin_hdr = BinaryHeader();
debug1(DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name); debug1( DEBUG_C_X_FUNC, X_FUNC_I_FILE_NAME, file_name );
debug3(DEBUG_C_X_FUNC, X_FUNC_I_SEND, start_addr, end_addr, bin_hdr); debug3( DEBUG_C_X_FUNC, X_FUNC_I_SEND, start_addr, end_addr, bin_hdr );
if(bin_hdr == (const char *)NULL if ( bin_hdr == ( const char* )NULL || WriteObjectToFile( ( Address )start_addr, ( Address )end_addr, bin_hdr, file_name ) ) {
|| WriteObjectToFile((Address)start_addr, ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
(Address)end_addr, bin_hdr, file_name)) ChfSignal();
{ }
ChfCondition X_FUNC_W_FAILED, CHF_WARNING ChfEnd;
ChfSignal();
}
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Dispatch table of emulator's extended functions, indexed by function code; Dispatch table of emulator's extended functions, indexed by function code;
the function code is propagated to functions in the table. the function code is propagated to functions in the table.
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
typedef void (*XFunc)(Nibble); typedef void ( *XFunc )( Nibble );
static const XFunc function[] = static const XFunc function[] = {
{ SetSpeed, /* Function code 0 */
SetSpeed, /* Function code 0 */ Kget, /* 1 */
Kget, /* 1 */ Send /* 2 */
Send /* 2 */
}; };
#define N_X_FUNC (sizeof(function)/sizeof(function[0])) #define N_X_FUNC ( sizeof( function ) / sizeof( function[ 0 ] ) )
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Public functions Public functions
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* .+ /* .+
@ -480,35 +425,32 @@ static const XFunc function[] =
the calculator side are made through CPU registers. the calculator side are made through CPU registers.
.call : .call :
ExtendedFunction(function_code); ExtendedFunction(function_code);
.input : .input :
Nibble function_code, function code Nibble function_code, function code
.output : .output :
void void
.status_codes : .status_codes :
X_FUNC_I_CALLED X_FUNC_I_CALLED
X_FUNC_I_CODE X_FUNC_I_CODE
X_FUNC_W_BAD_CODE X_FUNC_W_BAD_CODE
* Any other condition code generated by action functions * Any other condition code generated by action functions
.notes : .notes :
3.13, 3-Nov-2000, creation 3.13, 3-Nov-2000, creation
.- */ .- */
void ExtendedFunction(Nibble function_code) void ExtendedFunction( Nibble function_code )
{ {
debug1(DEBUG_C_TRACE, X_FUNC_I_CALLED, "ExtendedFunction"); debug1( DEBUG_C_TRACE, X_FUNC_I_CALLED, "ExtendedFunction" );
debug1(DEBUG_C_X_FUNC, X_FUNC_I_CODE, function_code); debug1( DEBUG_C_X_FUNC, X_FUNC_I_CODE, function_code );
/* Some sanity checks, first */ /* Some sanity checks, first */
if(function_code < 0 if ( function_code < 0 || function_code >= N_X_FUNC || function[ ( int )function_code ] == ( XFunc )NULL ) {
|| function_code >= N_X_FUNC ChfCondition X_FUNC_W_BAD_CODE, CHF_WARNING, function_code ChfEnd;
|| function[(int)function_code] == (XFunc)NULL) ChfSignal();
{
ChfCondition X_FUNC_W_BAD_CODE, CHF_WARNING, function_code ChfEnd;
ChfSignal();
} }
/* Dispatch */ /* Dispatch */
else else
function[(int)function_code](function_code); function[ ( int )function_code ]( function_code );
} }

View file

@ -69,41 +69,38 @@
.- */ .- */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Macro/Data type definitions - require cpu.h Macro/Data type definitions - require cpu.h
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
/* Extended function codes (argument of XFunction()) */ /* Extended function codes (argument of XFunction()) */
#define X_FUNC_SET_SPEED (Nibble)0 #define X_FUNC_SET_SPEED ( Nibble )0
#define X_FUNC_KGET (Nibble)1 #define X_FUNC_KGET ( Nibble )1
#define X_FUNC_SEND (Nibble)2 #define X_FUNC_SEND ( Nibble )2
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Chf condition codes Chf condition codes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#define X_FUNC_I_CALLED 101 /* Function %s called */ #define X_FUNC_I_CALLED 101 /* Function %s called */
#define X_FUNC_I_CODE 102 /* Function code %d */ #define X_FUNC_I_CODE 102 /* Function code %d */
#define X_FUNC_I_SET_SPEED 103 /* Speed set to %dMhz (%d mult.) */ #define X_FUNC_I_SET_SPEED 103 /* Speed set to %dMhz (%d mult.) */
#define X_FUNC_I_MAX_SPEED 104 /* Emulator at max speed */ #define X_FUNC_I_MAX_SPEED 104 /* Emulator at max speed */
#define X_FUNC_I_FILE_NAME 105 /* Transferring file name %s */ #define X_FUNC_I_FILE_NAME 105 /* Transferring file name %s */
#define X_FUNC_I_KGET 106 /* Kget start:%x end:%x hdr:%s */ #define X_FUNC_I_KGET 106 /* Kget start:%x end:%x hdr:%s */
#define X_FUNC_I_SEND 107 /* Send start:%x end:%x hdr:%s */ #define X_FUNC_I_SEND 107 /* Send start:%x end:%x hdr:%s */
#define X_FUNC_W_BAD_CODE 201 /* Bad function code %d ignored */ #define X_FUNC_W_BAD_CODE 201 /* Bad function code %d ignored */
#define X_FUNC_W_ABORTED 202 /* Aborted by user */ #define X_FUNC_W_ABORTED 202 /* Aborted by user */
#define X_FUNC_W_FAILED 203 /* Operation failed */ #define X_FUNC_W_FAILED 203 /* Operation failed */
#define X_FUNC_E_NO_HALT 301 /* Cpu halt not allowed */ #define X_FUNC_E_NO_HALT 301 /* Cpu halt not allowed */
#define X_FUNC_E_NO_SPEED 302 /* No speed control available */ #define X_FUNC_E_NO_SPEED 302 /* No speed control available */
#define X_FUNC_E_NO_BIN_HDR 303 /* Can't determine hdr for hw %s */ #define X_FUNC_E_NO_BIN_HDR 303 /* Can't determine hdr for hw %s */
#define X_FUNC_F_xxx 401 #define X_FUNC_F_xxx 401
#define X_FUNC_M_KGET 501 /* FSB title for Kget function */ #define X_FUNC_M_KGET 501 /* FSB title for Kget function */
#define X_FUNC_M_SEND 502 /* FSB title for Send function */ #define X_FUNC_M_SEND 502 /* FSB title for Send function */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Function prototypes Function prototypes
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
void ExtendedFunction(Nibble function_code); void ExtendedFunction( Nibble function_code );