import original from hpcalc.org
This commit is contained in:
commit
d7531876d4
125 changed files with 43983 additions and 0 deletions
85
BUGS.txt
Normal file
85
BUGS.txt
Normal file
|
@ -0,0 +1,85 @@
|
|||
2000-12-21 Ivan Cibrario Bertolotti <cibrario@refolo.iriti.cnr.it>
|
||||
|
||||
* >4.1, BUG: add installation support for IRIX and Ultrix
|
||||
|
||||
* >4.1, BUG: 'pack' exits with 'Chf initialization failed'
|
||||
if setlocale() fails during Chf initialization; apply the same
|
||||
patch as 'saturn'.
|
||||
Reported by Julian Einwag <julian@brightstar.swin.de>
|
||||
|
||||
* >4.1, BUG: Bad interaction with 'Emulate3Buttons' option
|
||||
of XFree86; need key memory or key dispatch delay.
|
||||
Reported by Dean Darlison <dean@dasco.ltd.uk>
|
||||
|
||||
2000-11-30 Ivan Cibrario Bertolotti <cibrario@refolo.iriti.cnr.it>
|
||||
|
||||
* >3.17: with HP49 ROM 1.19-4, command-line activity
|
||||
results in a lot of late hits during unconfig. Investigate
|
||||
why, in this case, late hits do not result in immediate hits
|
||||
in subsequent unconfigs.
|
||||
|
||||
* >3.17, Saturn.ad, BUG: some X Terminals, e.g. VXT2000,
|
||||
don't have an Escape key; the existing conventions,
|
||||
e.g. F11 for Escape on VXT2000, conflicts with the
|
||||
existing shortcuts.
|
||||
|
||||
2000-11-28 Ivan Cibrario Bertolotti <cibrario@refolo.iriti.cnr.it>
|
||||
|
||||
* >3.17, Saturn.ad, BUG: some X Terminals, e.g. VXT2000, only have a
|
||||
Delete (*not* BackSpace) key; make sure that backspace shortcut
|
||||
is available anyway in baseTranslations.
|
||||
|
||||
2000-11-21 Ivan Cibrario Bertolotti <cibrario@refolo.iriti.cnr.it>
|
||||
|
||||
* >3.15, BUG: xmodem file transfers don't work with
|
||||
big binary objects (like lib 258); flow control?
|
||||
(Fixed in 3.17)
|
||||
|
||||
2000-11-20 Ivan Cibrario Bertolotti <cibrario@refolo.iriti.cnr.it>
|
||||
|
||||
* >3.15: Revise init/reset sequence to be ready to accept
|
||||
interrupt requests during module initialization.
|
||||
|
||||
* >3.15: Reset bank switcher when '-reset' is asserted
|
||||
|
||||
2000-11-16 Ivan Cibrario Bertolotti <cibrario@refolo.iriti.cnr.it>
|
||||
|
||||
* >3.15, serial.c: Implement hangup on exit on pty;
|
||||
kermit insists that 'A serial connection might still be active'
|
||||
even when the emulator is no longer running.
|
||||
(Possibly not a bug)
|
||||
|
||||
* >3.15: IRIX support
|
||||
(Implemented in 3.16)
|
||||
|
||||
* >3.15, sutil: update with =recover code for HP49
|
||||
(Updated in 4.1)
|
||||
|
||||
* >3.15, sutil: implement for HP48
|
||||
(Implemented in 4.1)
|
||||
|
||||
* >=3.15, config.h, Ultrix: usleep() not supported;
|
||||
disable REAL_CPU_SPEED on this platform
|
||||
(Implemented in 3.16)
|
||||
(NEW_FILE: config_x.h)
|
||||
|
||||
* >=3.15, Imakefile, Ultrix: EXTRA_TAIL_LIBRARIES = -li
|
||||
(Implemented in 3.16)
|
||||
|
||||
* >=3.15, Chf, Ultrix: add default compile mode for unsupported
|
||||
platforms
|
||||
(Implemented in 3.16)
|
||||
|
||||
* =3.15, using.texi: pty name message no longer signaled
|
||||
(Fixed in 3.16)
|
||||
|
||||
* >=3.15, serial.c: remove #error and install a dummy handler instead
|
||||
(Fixed in 3.16; tested on already supported platforms and Ultrix)
|
||||
|
||||
* >=3.15, Saturn.ad, Ultrix: Keypad's numeric keys don't work;
|
||||
they work removing the leading ':' specifier
|
||||
(Fixed in 3.16, both code and documentation; tested on all platforms)
|
||||
|
||||
* =3.15, x11.c: remove XmNapplyCallback from file_sel_box
|
||||
(Fixed in 3.16; tested on supported platforms)
|
||||
|
10
Chf/Bugs
Normal file
10
Chf/Bugs
Normal file
|
@ -0,0 +1,10 @@
|
|||
2001-01-25 Ivan Cibrario Bertolotti <cibrario@brontolo.iriti.cnr.it>
|
||||
|
||||
* Win32 support is limited to the Windows CE platform
|
||||
|
||||
* _REENTRANT is not supported on Win32.
|
||||
|
||||
2000-05-29 Ivan Cibrario Bertolotti <cibrario@brontolo.cstv.to.cnr.it>
|
||||
|
||||
* chf.texi: Bad punctuation characters after xref.
|
||||
(Fixed in 2.2)
|
371
Chf/Chf.h
Normal file
371
Chf/Chf.h
Normal file
|
@ -0,0 +1,371 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: Chf.h,v 2.2 2001/01/25 11:56:44 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: Chf.h,v $, main header
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 2-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This is the main header of the Condition Handling Facility
|
||||
|
||||
.include : stdio.h setjmp.h (Win32: tchar.h)
|
||||
|
||||
.notes :
|
||||
$Log: Chf.h,v $
|
||||
Revision 2.2 2001/01/25 11:56:44 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 2.1 2000/05/26 14:10:08 cibrario
|
||||
- Revised unwind context passing mechanism; redefined CHF_NULL_CONTEXT
|
||||
- New macros: CHF_NULL_HANDLER, CHF_MAJOR_RELEASE_NUMBER,
|
||||
CHF_MINOR_RELEASE_NUMBER
|
||||
- New ChfAction value: CHF_UNWIND_KEEP; fixed spelling of ChfAction value:
|
||||
CHF_SIGNALLING -> CHF_SIGNALING
|
||||
- Added structured condition handling macros: ChfTry, ChfCatch, ChfEndTry
|
||||
|
||||
Revision 1.6 1997/01/15 13:41:20 cibrario
|
||||
Defined the new data type ChfPointer, a generic (void *) pointer. Each
|
||||
condition handler can have a private handler context pointer, of type
|
||||
ChfPointer, that the function ChfPushHandler() stores and that is passed
|
||||
to the handler when it's activated.
|
||||
Fixed a wrong adjustment of the condition handlers stack pointer after
|
||||
an unwind operation.
|
||||
|
||||
Revision 1.5 1996/10/04 09:45:30 cibrario
|
||||
Updated the condition message format in the private header ChfPriv.h to
|
||||
improve internationalization
|
||||
|
||||
Revision 1.4 1996/09/25 13:21:11 cibrario
|
||||
Added macro CHF_LIBRARY_ID; it contains the current ID of the CHF library.
|
||||
The module chf_init.o will contain it as a static char[] variable.
|
||||
|
||||
Revision 1.2 1996/06/11 13:02:10 cibrario
|
||||
Added prototype for ChfGetTopCondition()
|
||||
|
||||
Revision 1.1 1996/05/28 12:56:47 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Win32 & UNICODE support
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfChar TCHAR
|
||||
#define ChfText(x) _T(x)
|
||||
#define ChfSigjmp_buf jmp_buf
|
||||
#define ChfSigsetjmp(x,y) setjmp(x)
|
||||
#define ChfSiglongjmp(x,y) longjmp(x,y)
|
||||
#else
|
||||
#define ChfChar char
|
||||
#define ChfText(x) x
|
||||
#define ChfSigjmp_buf sigjmp_buf
|
||||
#define ChfSigsetjmp(x,y) sigsetjmp(x,y)
|
||||
#define ChfSiglongjmp(x,y) siglongjmp(x,y)
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
CHF implementation limits and other symbolic constants
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_MAX_MESSAGE_LENGTH 256
|
||||
#define CHF_UNKNOWN_LINE_NUMBER (-1)
|
||||
#define CHF_UNKNOWN_FILE_NAME (ChfChar *)NULL
|
||||
#define CHF_NULL_DESCRIPTOR (ChfDescriptor *)NULL
|
||||
#define CHF_NULL_CONTEXT (void *)NULL
|
||||
#define CHF_NULL_POINTER (ChfPointer *)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_MAJOR_RELEASE_NUMBER 2
|
||||
#define CHF_MINOR_RELEASE_NUMBER 2
|
||||
|
||||
#define CHF_MODULE_NAMES_SET 1
|
||||
#define CHF_SET 2
|
||||
#define CHF_ERRNO_SET 3
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Condition codes
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_S_OK 0
|
||||
#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_EMPTY 3 /* Handler stack is empty */
|
||||
#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_MALLOC 6 /* Dynamic memory allocation failed */
|
||||
#define CHF_F_NOT_AVAILABLE 7 /* Function not available */
|
||||
#define CHF_F_SETLOCALE 10 /* setlocale() failed */
|
||||
#define CHF_F_CATOPEN 11 /* catopen() failed */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
typedef enum /* Condition severity codes */
|
||||
{
|
||||
CHF_SUCCESS,
|
||||
CHF_INFO,
|
||||
CHF_WARNING,
|
||||
CHF_ERROR,
|
||||
CHF_FATAL
|
||||
}
|
||||
ChfSeverity;
|
||||
|
||||
typedef enum /* Condition handler action codes */
|
||||
{
|
||||
CHF_CONTINUE, /* Continue application */
|
||||
CHF_RESIGNAL, /* Resignal to next handler */
|
||||
CHF_UNWIND, /* Stack unwind */
|
||||
CHF_UNWIND_KEEP /* Unwind, keep last cond. group */
|
||||
}
|
||||
ChfAction;
|
||||
|
||||
typedef int /* CHF options */
|
||||
ChfOptions;
|
||||
|
||||
#define CHF_DEFAULT 0x0000 /* default flags */
|
||||
#define CHF_ABORT 0x0001 /* use abort() instead of exit() */
|
||||
|
||||
typedef enum /* Current CHF state */
|
||||
{
|
||||
CHF_UNKNOWN,
|
||||
CHF_IDLE,
|
||||
CHF_SIGNALING,
|
||||
CHF_UNWINDING,
|
||||
CHF_SIGNAL_UNWINDING
|
||||
}
|
||||
ChfState;
|
||||
|
||||
typedef struct ChfDescriptor_S /* Condition descriptor */
|
||||
{
|
||||
int module_id; /* Module identifier */
|
||||
int condition_code; /* Condition code */
|
||||
ChfSeverity severity; /* Severity */
|
||||
int line_number; /* Line # or CHF_UNK_LINE_NUMBER */
|
||||
const ChfChar *file_name; /* File name or CHF_UNK_FILE_NAME */
|
||||
ChfChar message[CHF_MAX_MESSAGE_LENGTH]; /* Partial message */
|
||||
struct ChfDescriptor_S *next; /* Link to next descriptor */
|
||||
}
|
||||
ChfDescriptor;
|
||||
|
||||
typedef struct ChfTable_S /* Standalone message table */
|
||||
{
|
||||
int module; /* Module identifier */
|
||||
int code; /* Condition code */
|
||||
ChfChar *msg_template; /* Message template */
|
||||
}
|
||||
ChfTable;
|
||||
|
||||
typedef /* Generic pointer */
|
||||
void *ChfPointer;
|
||||
|
||||
typedef /* Condition handler */
|
||||
ChfAction (*ChfHandler)(
|
||||
const ChfDescriptor *,
|
||||
const ChfState,
|
||||
ChfPointer
|
||||
);
|
||||
|
||||
typedef /* Message retrieval 'get_message' function */
|
||||
const ChfChar * (*ChfMrsGet)(
|
||||
void *,
|
||||
const int,
|
||||
const int,
|
||||
const ChfChar *default_message
|
||||
);
|
||||
|
||||
typedef /* Message retrieval 'exit' function */
|
||||
void (*ChfMrsExit)(
|
||||
void *
|
||||
);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Condition generation macros
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CHF_EXTENDED_INFO)
|
||||
#define ChfCondition \
|
||||
ChfGenerate( \
|
||||
CHF_MODULE_ID, \
|
||||
ChfText(__FILE__), __LINE__,
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfErrnoCondition
|
||||
#else
|
||||
#define ChfErrnoCondition \
|
||||
ChfGenerate( \
|
||||
CHF_ERRNO_SET, \
|
||||
ChfText(__FILE__), __LINE__, \
|
||||
errno, \
|
||||
CHF_ERROR \
|
||||
)
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define ChfCondition \
|
||||
ChfGenerate( \
|
||||
CHF_MODULE_ID, \
|
||||
CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER,
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfErrnoCondition
|
||||
#else
|
||||
#define ChfErrnoCondition \
|
||||
ChfGenerate( \
|
||||
CHF_ERRNO_SET, \
|
||||
CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER, \
|
||||
errno, \
|
||||
CHF_ERROR \
|
||||
)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define ChfEnd \
|
||||
)
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Structured condition handling
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define ChfTry \
|
||||
{\
|
||||
ChfSigjmp_buf _chf_sigjmp_buf;\
|
||||
if(ChfSigsetjmp(_chf_sigjmp_buf, 1) == 0)\
|
||||
{\
|
||||
ChfPushHandler(CHF_NULL_HANDLER, _chf_sigjmp_buf, CHF_NULL_POINTER);
|
||||
|
||||
#define ChfCatch \
|
||||
ChfPopHandler();\
|
||||
}\
|
||||
else\
|
||||
{
|
||||
|
||||
#define ChfEndTry \
|
||||
ChfDiscard();\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Other macros
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define ChfGetNextDescriptor(d) (d)->next
|
||||
#define ChfGetModuleId(d) (d)->module_id
|
||||
#define ChfGetConditionCode(d) (d)->condition_code
|
||||
#define ChfGetSeverity(d) (d)->severity
|
||||
#define ChfGetLineNumber(d) (d)->line_number
|
||||
#define ChfGetFileName(d) (d)->file_name
|
||||
#define ChfGetPartialMessage(d) (d)->message
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int ChfInit( /* Generic initialization */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
void *mrs_data, /* Message retrieval private data */
|
||||
ChfMrsGet mrs_get, /* 'GetMessage' function */
|
||||
ChfMrsExit mrs_exit, /* 'Exit' function */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
int ChfMsgcatInit( /* Initialization with msgcat subsystem */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfChar *msgcat_name, /* Name of the message catalog */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
int ChfStaticInit( /* Initialization with static message tables */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfTable *table, /* Static message table */
|
||||
const size_t table_size, /* Size of the message table */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
int ChfWin32Init( /* Initialization within _WIN32 */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
#ifndef _WIN32
|
||||
void *instance, /* Fake arguments */
|
||||
#else
|
||||
HINSTANCE instance, /* App. instance handle */
|
||||
#endif
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
void ChfExit( /* Exit */
|
||||
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 ChfPopHandler( /* Pop a handler */
|
||||
void
|
||||
);
|
||||
|
||||
ChfChar *ChfBuildMessage( /* Build a condition message */
|
||||
const ChfDescriptor *descriptor
|
||||
);
|
||||
|
||||
void ChfSignal( /* Signal the current conditions */
|
||||
void
|
||||
);
|
||||
|
||||
void ChfDiscard( /* Discard the current conditions */
|
||||
void
|
||||
);
|
||||
|
||||
void ChfGenerate( /* Generate a condition into the stack */
|
||||
const int module_id,
|
||||
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
|
||||
);
|
155
Chf/ChfPriv.h
Normal file
155
Chf/ChfPriv.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: ChfPriv.h,v 2.2 2001/01/25 11:57:57 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: ChfPriv.h,v $, main header
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 2-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This is the private header of the Condition Handling Facility
|
||||
|
||||
.include : *
|
||||
|
||||
.notes :
|
||||
$Log: ChfPriv.h,v $
|
||||
Revision 2.2 2001/01/25 11:57:57 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 2.1 2000/05/26 14:14:36 cibrario
|
||||
- Defined new abort codes: CHF_ABORT_GET_CONTEXT, CHF_ABORT_PTHREAD
|
||||
- Redefined .unwind_context field of ChfHandlerDescriptor
|
||||
- Conditional retarget of chf_context for multithreading support
|
||||
- Declared new private function: _ChfGetContext() (mt support only)
|
||||
|
||||
Revision 1.6 1997/01/15 13:38:24 cibrario
|
||||
Added the new field .handler_context to struct ChfHandlerDescriptor_S, to
|
||||
store, for each condition handler, the private handler context pointer.
|
||||
|
||||
Revision 1.5 1996/10/04 09:43:51 cibrario
|
||||
Updated the condition message format to improve internationalization
|
||||
|
||||
Revision 1.1 1996/05/28 12:56:37 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Macros
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_MODULE_ID CHF_SET
|
||||
#define CHF_TMP_MESSAGE_LENGTH (2*CHF_MAX_MESSAGE_LENGTH)
|
||||
#define CHF_DEF_MESSAGE_LENGTH 40
|
||||
#define CHF_DEF_PARTIAL_MSG_FMT ChfText("Code <%d>d")
|
||||
#define CHF_DEF_MID_MSG_FMT ChfText("Mid <%d>d")
|
||||
#define CHF_EXTENDED_INFO_FMT ChfText("(%s,%d)")
|
||||
#define CHF_SEVERITY_NAMES \
|
||||
{ ChfText("S"), ChfText("I"), ChfText("W"), ChfText("E"), ChfText("F") }
|
||||
#define CHF_UNKNOWN_SEVERITY ChfText("?")
|
||||
#define CHF_MESSAGE_SEPARATOR ChfText("-")
|
||||
#define CHF_MESSAGE_TERMINATOR ChfText("\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()
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_ABORT_SILENT 0
|
||||
#define CHF_ABORT_INIT 1
|
||||
#define CHF_ABORT_MSG_OVF 2
|
||||
#define CHF_ABORT_INVALID_ACTION 3
|
||||
#define CHF_ABORT_DUP_INIT 4
|
||||
#define CHF_ABORT_ALREADY_UNWINDING 5
|
||||
#define CHF_ABORT_IMPROPERLY_HANDLED 6
|
||||
#define CHF_ABORT_FATAL_UNWINDING 7
|
||||
#define CHF_ABORT_COND_STACK_OVF 8
|
||||
#define CHF_ABORT_GET_CONTEXT 9
|
||||
#define CHF_ABORT_PTHREAD 10
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct ChfHandlerDescriptor_S
|
||||
{
|
||||
ChfHandler handler;
|
||||
void *unwind_context;
|
||||
ChfPointer handler_context;
|
||||
}
|
||||
ChfHandlerDescriptor;
|
||||
|
||||
typedef struct ChfContext_S /* CHF Context */
|
||||
{
|
||||
ChfState state; /* Current CHF state */
|
||||
const ChfChar *app_name; /* Application's name */
|
||||
ChfOptions options; /* Options */
|
||||
void *mrs_data; /* Message retrieval private data */
|
||||
ChfMrsGet mrs_get; /* 'GetMessage' function */
|
||||
ChfMrsExit mrs_exit; /* 'Exit' function */
|
||||
int condition_stack_size; /* Size of the condition stack */
|
||||
int handler_stack_size; /* Size of the handler stack */
|
||||
int exit_code; /* Abnormal exit code */
|
||||
ChfDescriptor *condition_stack; /* Condition stack */
|
||||
ChfDescriptor *condition_base; /* Current condition stack base */
|
||||
ChfDescriptor *condition_sp; /* Current condition stack pointer */
|
||||
ChfHandlerDescriptor *handler_stack; /* Handler stack */
|
||||
ChfHandlerDescriptor *handler_sp; /* Current handler stack pointer */
|
||||
ChfChar *message_buffer; /* Message buffer */
|
||||
}
|
||||
ChfContext;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Multithreading support
|
||||
------------------------------------------------------------------------- */
|
||||
#ifdef _REENTRANT
|
||||
#define chf_context (*_ChfGetContext())
|
||||
#else
|
||||
#define chf_context _chf_context
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
extern ChfContext _chf_context; /* CHF Context */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private function prototypes
|
||||
------------------------------------------------------------------------- */
|
||||
#ifdef _REENTRANT
|
||||
ChfContext *_ChfGetContext(void);
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private redirection of stdlib functions needed by Win32
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfStrlen _tcslen
|
||||
#define ChfStrcpy _tcscpy
|
||||
#define ChfStrcat _tcscat
|
||||
#define ChfStrncpy _tcsncpy
|
||||
#define ChfSprintf _stprintf
|
||||
#define ChfVsprintf _vstprintf
|
||||
#else
|
||||
#define ChfStrlen strlen
|
||||
#define ChfStrcpy strcpy
|
||||
#define ChfStrcat strcat
|
||||
#define ChfStrncpy strncpy
|
||||
#define ChfSprintf sprintf
|
||||
#define ChfVsprintf vsprintf
|
||||
#endif
|
209
Chf/Makefile
Normal file
209
Chf/Makefile
Normal file
|
@ -0,0 +1,209 @@
|
|||
# ICB, 2-Oct-2000
|
||||
# Minor off-line changes to support stand-alone build in saturn
|
||||
#
|
||||
# ICB, 16-Nov-2000
|
||||
# Off-line change: added default compile mode for unsupported platforms
|
||||
|
||||
# .+
|
||||
#
|
||||
# .identifier : $Id: Makefile,v 2.1 2000/05/29 13:53:07 cibrario Rel $
|
||||
# .context : CHF, Condition Handling Facility
|
||||
# .title : $RCSfile: Makefile,v $, Makefile
|
||||
# .kind : Makefile
|
||||
# .author : Ivan Cibrario B.
|
||||
# .site : CSTV-CNR
|
||||
# .creation : 3-May-1996
|
||||
# .keywords : *
|
||||
# .description :
|
||||
# Makefile for the CHF library
|
||||
# .notes :
|
||||
# $Log: Makefile,v $
|
||||
# Revision 2.1 2000/05/29 13:53:07 cibrario
|
||||
# - Deep revision to support transparent, multi-platform builds
|
||||
# - Added multithreading support
|
||||
# - New/revised targets: test, doc, clean
|
||||
#
|
||||
# Revision 1.2 1996/06/11 13:03:06 cibrario
|
||||
# Added new module chf_top.c
|
||||
#
|
||||
# Revision 1.1 1996/05/29 09:12:10 cibrario
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
# .-
|
||||
|
||||
#
|
||||
# Platform-dependent definitions. Edit when required, for example to
|
||||
# add a new platform.
|
||||
#
|
||||
# There is a set of definitions per platform; the prefix or the definition
|
||||
# names is the value returned by a plain 'uname' on that platform.
|
||||
#
|
||||
# CC: cc compiler
|
||||
# TS_CFLAGS: cc flags to enable multithreading
|
||||
# TS_LOADLIBES: ld flags and additional libraries to enable multithreading
|
||||
# F_CFLAGS: cc feature test macros
|
||||
# O_CFLAGS: cc optimization control flags and other, additional flags
|
||||
#
|
||||
# Supported platforms:
|
||||
# OSF1 Digital UNIX v4.0
|
||||
# SunOS Solaris v2.6
|
||||
# Linux Linux 2.1
|
||||
#
|
||||
# In addition, if the first build fails, a second attempt is made
|
||||
# using the X_CC and X_CFLAGS fallback values.
|
||||
|
||||
OSF1_CC = cc
|
||||
OSF1_TS_CFLAGS = -pthread
|
||||
OSF1_TS_LOADLIBES = -pthread
|
||||
OSF1_F_CFLAGS = "-D_POSIX_C_SOURCE=199506L -D_XOPEN_SOURCE"
|
||||
OSF1_O_CFLAGS = "-O3 -std1"
|
||||
|
||||
SunOS_CC = gcc
|
||||
SunOS_TS_CFLAGS = -D_REENTRANT
|
||||
SunOS_TS_LOADLIBES = -lpthread
|
||||
SunOS_F_CFLAGS = -D_POSIX_C_SOURCE=199506L
|
||||
SunOS_O_CFLAGS = "-O3 -ansi -pedantic"
|
||||
|
||||
Linux_CC = cc
|
||||
Linux_TS_CFLAGS = -D_REENTRANT
|
||||
Linux_TS_LOADLIBES = -lpthread
|
||||
Linux_F_CFLAGS = -D_POSIX_C_SOURCE=199506L
|
||||
Linux_O_CFLAGS = "-O3 -ansi -pedantic"
|
||||
|
||||
#
|
||||
# Destination paths for library objects, C headers, binaries, message catalog
|
||||
# sources and X resource files. Edit as required.
|
||||
#
|
||||
DESTLIBDIR = $(HOME)/lib
|
||||
DESTHDRDIR = $(HOME)/include
|
||||
DESTBINDIR = $(HOME)/bin
|
||||
DESTMSFDIR = $(HOME)/msf
|
||||
DESTRESDIR = $(HOME)/res
|
||||
|
||||
#
|
||||
# The default target recursively invokes make defining UNAME to the
|
||||
# string returned by uname; this is used to make appropriate
|
||||
# platform-dependent definitions above.
|
||||
#
|
||||
all:
|
||||
@$(MAKE) UNAME=`uname` build || \
|
||||
$(MAKE) UNAME=Unknown CC='"$(X_CC)"' O_CFLAGS='"$(X_CFLAGS)"' build
|
||||
|
||||
#
|
||||
# Vectored definitions; see above and do not edit.
|
||||
#
|
||||
CC = $($(UNAME)_CC)
|
||||
TS_CFLAGS = $($(UNAME)_TS_CFLAGS)
|
||||
TS_LOADLIBES = $($(UNAME)_TS_LOADLIBES)
|
||||
F_CFLAGS = $($(UNAME)_F_CFLAGS)
|
||||
O_CFLAGS = $($(UNAME)_O_CFLAGS)
|
||||
|
||||
#
|
||||
# Include common definitions
|
||||
#
|
||||
include Makefile_def
|
||||
|
||||
#
|
||||
# Build directories for single-threaded and multi-threaded lib versions
|
||||
#
|
||||
ST_BUILD_DIR = ./st_build
|
||||
MT_BUILD_DIR = ./mt_build
|
||||
|
||||
#
|
||||
# Library names
|
||||
#
|
||||
ST_LIB_NAME = libChf.a
|
||||
MT_LIB_NAME = libChf_r.a
|
||||
|
||||
#
|
||||
# Library paths
|
||||
#
|
||||
ST_LIB_PATH = $(ST_BUILD_DIR)/$(ST_LIB_NAME)
|
||||
MT_LIB_PATH = $(MT_BUILD_DIR)/$(MT_LIB_NAME)
|
||||
|
||||
#
|
||||
# build: Create and populate build directories; for each build directory,
|
||||
# make dependencies and rebuild
|
||||
#
|
||||
build: $(ST_LIB_PATH) $(MT_LIB_PATH)
|
||||
|
||||
#
|
||||
# test: Build and executes test programs
|
||||
#
|
||||
test:
|
||||
@$(MAKE) UNAME=`uname` do_test
|
||||
@echo "All tests completed successfully"
|
||||
|
||||
do_test: $(ST_LIB_PATH) $(MT_LIB_PATH)
|
||||
@cd $(ST_BUILD_DIR) && \
|
||||
$(MAKE) test CC=$(CC) LIB=$(ST_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) > test.log 2>&1
|
||||
@cd $(MT_BUILD_DIR) && \
|
||||
$(MAKE) test CC=$(CC) LIB=$(MT_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) \
|
||||
TS_CFLAGS=$(TS_CFLAGS) TS_LOADLIBES=$(TS_LOADLIBES) >> test.log 2>&1
|
||||
|
||||
#
|
||||
# doc: Make documentation files
|
||||
#
|
||||
doc:
|
||||
makeinfo chf.texi
|
||||
texi2dvi chf.texi; dvips -o chf.ps chf.dvi
|
||||
|
||||
#
|
||||
# clean: Remove build directories
|
||||
#
|
||||
clean:
|
||||
rm -rf $(ST_BUILD_DIR) $(MT_BUILD_DIR)
|
||||
|
||||
#
|
||||
# install: Move all files to their directories
|
||||
# ICB, 23-Oct-2000: Do nothing
|
||||
#
|
||||
install: $(ST_LIB_PATH) $(MT_LIB_PATH) $(HDR) $(MSF) $(RES)
|
||||
|
||||
#
|
||||
# Prepare the build directories for use
|
||||
#
|
||||
# ICB, 16-Nov-2000
|
||||
# Off-line change: Force the build to fail with exit 1 if CC is undefined
|
||||
#
|
||||
$(ST_BUILD_DIR) $(MT_BUILD_DIR):
|
||||
@[ "$(CC)" = "" ] && \
|
||||
{ echo "Warning: using X_ defaults"; exit 1; } ; \
|
||||
mkdir $@ && \
|
||||
cd $@ && \
|
||||
ln -s ../Makefile_sub Makefile && \
|
||||
for s in $(SRC) $(TSRC) $(HDR) $(MSF) $(TMSF) $(RES) ; do \
|
||||
ln -s ../$$s $$s ; \
|
||||
done
|
||||
|
||||
#
|
||||
# Make the libraries; the rebuild is forced here because only the
|
||||
# sub-makes have module dependencies.
|
||||
#
|
||||
# ICB, 16-Nov-2000
|
||||
# Off-line change: Force the build to fail with exit 1 if CC is undefined
|
||||
#
|
||||
$(ST_LIB_PATH): $(ST_BUILD_DIR) force
|
||||
@[ "$(CC)" = "" ] && \
|
||||
{ echo "Warning: using X_ defaults"; exit 1; } ; \
|
||||
cd $(ST_BUILD_DIR) && \
|
||||
$(MAKE) depend CC=$(CC) LIB=$(ST_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) && \
|
||||
$(MAKE) all CC=$(CC) LIB=$(ST_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS)
|
||||
|
||||
$(MT_LIB_PATH): $(MT_BUILD_DIR) force
|
||||
@[ "$(CC)" = "" ] && \
|
||||
{ echo "Warning: using X_ defaults"; exit 1; } ; \
|
||||
cd $(MT_BUILD_DIR) && \
|
||||
$(MAKE) depend CC=$(CC) LIB=$(MT_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) \
|
||||
TS_CFLAGS=$(TS_CFLAGS) TS_LOADLIBES=$(TS_LOADLIBES) && \
|
||||
$(MAKE) all CC=$(CC) LIB=$(MT_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) \
|
||||
TS_CFLAGS=$(TS_CFLAGS) TS_LOADLIBES=$(TS_LOADLIBES)
|
||||
|
||||
force:
|
68
Chf/Makefile_def
Normal file
68
Chf/Makefile_def
Normal file
|
@ -0,0 +1,68 @@
|
|||
# .+
|
||||
#
|
||||
# .identifier : $Id: Makefile_def,v 2.2 2001/01/25 11:59:19 cibrario Exp $
|
||||
# .context : CHF, Condition Handling Facility
|
||||
# .title : $RCSfile: Makefile_def,v $, Makefile
|
||||
# .kind : Makefile
|
||||
# .author : Ivan Cibrario B.
|
||||
# .site : CSTV-CNR
|
||||
# .creation : 22-May-2000
|
||||
# .keywords : *
|
||||
# .description :
|
||||
# Makefile for CHF library common definitions; no platform dependencies here.
|
||||
# .notes :
|
||||
# $Log: Makefile_def,v $
|
||||
# Revision 2.2 2001/01/25 11:59:19 cibrario
|
||||
# Added partial Win32 support (Windows CE only).
|
||||
#
|
||||
# Revision 2.1 2000/05/29 13:08:39 cibrario
|
||||
# *** empty log message ***
|
||||
#
|
||||
#
|
||||
# .-
|
||||
|
||||
#
|
||||
# Source files
|
||||
#
|
||||
SRC = chf_init.c chf_gen.c chf_sig.c chf_abrt.c chf_hdlr.c \
|
||||
chf_msgc.c chf_st.c \
|
||||
chf_top.c \
|
||||
chf_win32.c
|
||||
|
||||
TSRC = test01.c test02.c test03.c test04.c test05.c test06.c \
|
||||
test07.c
|
||||
|
||||
HDR = Chf.h ChfPriv.h
|
||||
|
||||
MSF = chf.msf
|
||||
|
||||
TMSF = test01.msf
|
||||
|
||||
RES =
|
||||
|
||||
#
|
||||
# Target object files
|
||||
#
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
#
|
||||
# Target test programs
|
||||
#
|
||||
TBIN = $(TSRC:.c=)
|
||||
|
||||
#
|
||||
# Other definitions
|
||||
#
|
||||
HPATH = -I.
|
||||
LPATH = -L.
|
||||
|
||||
CFLAGS = $(F_CFLAGS) $(O_CFLAGS) $(TS_CFLAGS) $(U_CFLAGS) $(HPATH)
|
||||
LFLAGS = $(F_CFLAGS) $(L_CFLAGS) $(TS_LFLAGS) $(U_CFLAGS) $(HPATH)
|
||||
LDFLAGS = $(LPATH)
|
||||
|
||||
LOADLIBES = $(LIB) $(TS_LOADLIBES) $(I_LOADLIBES) $(U_LOADLIBES)
|
||||
|
||||
#
|
||||
# Solaris spelling of LOADLIBES
|
||||
#
|
||||
LDLIBS = $(LOADLIBES)
|
40
Chf/Makefile_sub
Normal file
40
Chf/Makefile_sub
Normal file
|
@ -0,0 +1,40 @@
|
|||
# .+
|
||||
#
|
||||
# .identifier : $Id: Makefile_sub,v 2.1 2000/05/29 13:08:51 cibrario Rel $
|
||||
# .context : CHF, Condition Handling Facility
|
||||
# .title : $RCSfile: Makefile_sub,v $, Makefile
|
||||
# .kind : Makefile
|
||||
# .author : Ivan Cibrario B.
|
||||
# .site : CSTV-CNR
|
||||
# .creation : 22-May-2000
|
||||
# .keywords : *
|
||||
# .description :
|
||||
# Makefile for CHF library subdirectories
|
||||
# .notes :
|
||||
# $Log: Makefile_sub,v $
|
||||
# Revision 2.1 2000/05/29 13:08:51 cibrario
|
||||
# *** empty log message ***
|
||||
#
|
||||
#
|
||||
# .-
|
||||
|
||||
#
|
||||
# Include common definitions
|
||||
#
|
||||
include ../Makefile_def
|
||||
|
||||
#
|
||||
# Targets
|
||||
#
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(OBJ)
|
||||
$(AR) $(ARFLAGS) $@ $?
|
||||
|
||||
test: $(TBIN)
|
||||
@for b in $(TBIN) ; do \
|
||||
./$$b ; \
|
||||
done
|
||||
|
||||
depend: $(SRC)
|
||||
@makedepend $(HPATH) $(SRC)
|
52
Chf/RCS/Bugs,v
Normal file
52
Chf/RCS/Bugs,v
Normal file
|
@ -0,0 +1,52 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.11.53.35; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.29.14.44.41; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@2001-01-25 Ivan Cibrario Bertolotti <cibrario@@brontolo.iriti.cnr.it>
|
||||
|
||||
* Win32 support is limited to the Windows CE platform
|
||||
|
||||
* _REENTRANT is not supported on Win32.
|
||||
|
||||
2000-05-29 Ivan Cibrario Bertolotti <cibrario@@brontolo.cstv.to.cnr.it>
|
||||
|
||||
* chf.texi: Bad punctuation characters after xref.
|
||||
(Fixed in 2.2)
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@d1 6
|
||||
d10 1
|
||||
a10 1
|
||||
|
||||
@
|
611
Chf/RCS/Chf.h,v
Normal file
611
Chf/RCS/Chf.h,v
Normal file
|
@ -0,0 +1,611 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.11.56.44; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.26.14.10.08; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.6;
|
||||
|
||||
1.6
|
||||
date 97.01.15.13.41.20; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.5;
|
||||
|
||||
1.5
|
||||
date 96.10.04.09.45.30; author cibrario; state Beta;
|
||||
branches;
|
||||
next 1.4;
|
||||
|
||||
1.4
|
||||
date 96.09.25.13.21.11; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.2;
|
||||
|
||||
1.2
|
||||
date 96.06.11.13.02.10; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.56.47; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This is the main header of the Condition Handling Facility
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: Chf.h,v 2.1 2000/05/26 14:10:08 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: Chf.h,v $, main header
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 2-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This is the main header of the Condition Handling Facility
|
||||
|
||||
.include : stdio.h setjmp.h (Win32: tchar.h)
|
||||
|
||||
.notes :
|
||||
$Log: Chf.h,v $
|
||||
Revision 2.1 2000/05/26 14:10:08 cibrario
|
||||
- Revised unwind context passing mechanism; redefined CHF_NULL_CONTEXT
|
||||
- New macros: CHF_NULL_HANDLER, CHF_MAJOR_RELEASE_NUMBER,
|
||||
CHF_MINOR_RELEASE_NUMBER
|
||||
- New ChfAction value: CHF_UNWIND_KEEP; fixed spelling of ChfAction value:
|
||||
CHF_SIGNALLING -> CHF_SIGNALING
|
||||
- Added structured condition handling macros: ChfTry, ChfCatch, ChfEndTry
|
||||
|
||||
Revision 1.6 1997/01/15 13:41:20 cibrario
|
||||
Defined the new data type ChfPointer, a generic (void *) pointer. Each
|
||||
condition handler can have a private handler context pointer, of type
|
||||
ChfPointer, that the function ChfPushHandler() stores and that is passed
|
||||
to the handler when it's activated.
|
||||
Fixed a wrong adjustment of the condition handlers stack pointer after
|
||||
an unwind operation.
|
||||
|
||||
Revision 1.5 1996/10/04 09:45:30 cibrario
|
||||
Updated the condition message format in the private header ChfPriv.h to
|
||||
improve internationalization
|
||||
|
||||
Revision 1.4 1996/09/25 13:21:11 cibrario
|
||||
Added macro CHF_LIBRARY_ID; it contains the current ID of the CHF library.
|
||||
The module chf_init.o will contain it as a static char[] variable.
|
||||
|
||||
Revision 1.2 1996/06/11 13:02:10 cibrario
|
||||
Added prototype for ChfGetTopCondition()
|
||||
|
||||
Revision 1.1 1996/05/28 12:56:47 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Win32 & UNICODE support
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfChar TCHAR
|
||||
#define ChfText(x) _T(x)
|
||||
#define ChfSigjmp_buf jmp_buf
|
||||
#define ChfSigsetjmp(x,y) setjmp(x)
|
||||
#define ChfSiglongjmp(x,y) longjmp(x,y)
|
||||
#else
|
||||
#define ChfChar char
|
||||
#define ChfText(x) x
|
||||
#define ChfSigjmp_buf sigjmp_buf
|
||||
#define ChfSigsetjmp(x,y) sigsetjmp(x,y)
|
||||
#define ChfSiglongjmp(x,y) siglongjmp(x,y)
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
CHF implementation limits and other symbolic constants
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_MAX_MESSAGE_LENGTH 256
|
||||
#define CHF_UNKNOWN_LINE_NUMBER (-1)
|
||||
#define CHF_UNKNOWN_FILE_NAME (ChfChar *)NULL
|
||||
#define CHF_NULL_DESCRIPTOR (ChfDescriptor *)NULL
|
||||
#define CHF_NULL_CONTEXT (void *)NULL
|
||||
#define CHF_NULL_POINTER (ChfPointer *)NULL
|
||||
#define CHF_NULL_HANDLER (ChfHandler)NULL
|
||||
#define CHF_LIBRARY_ID ChfText("$Id: Chf.h,v 2.1 2000/05/26 14:10:08 cibrario Exp $")
|
||||
|
||||
#define CHF_MAJOR_RELEASE_NUMBER 2
|
||||
#define CHF_MINOR_RELEASE_NUMBER 2
|
||||
|
||||
#define CHF_MODULE_NAMES_SET 1
|
||||
#define CHF_SET 2
|
||||
#define CHF_ERRNO_SET 3
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Condition codes
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_S_OK 0
|
||||
#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_EMPTY 3 /* Handler stack is empty */
|
||||
#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_MALLOC 6 /* Dynamic memory allocation failed */
|
||||
#define CHF_F_NOT_AVAILABLE 7 /* Function not available */
|
||||
#define CHF_F_SETLOCALE 10 /* setlocale() failed */
|
||||
#define CHF_F_CATOPEN 11 /* catopen() failed */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
typedef enum /* Condition severity codes */
|
||||
{
|
||||
CHF_SUCCESS,
|
||||
CHF_INFO,
|
||||
CHF_WARNING,
|
||||
CHF_ERROR,
|
||||
CHF_FATAL
|
||||
}
|
||||
ChfSeverity;
|
||||
|
||||
typedef enum /* Condition handler action codes */
|
||||
{
|
||||
CHF_CONTINUE, /* Continue application */
|
||||
CHF_RESIGNAL, /* Resignal to next handler */
|
||||
CHF_UNWIND, /* Stack unwind */
|
||||
CHF_UNWIND_KEEP /* Unwind, keep last cond. group */
|
||||
}
|
||||
ChfAction;
|
||||
|
||||
typedef int /* CHF options */
|
||||
ChfOptions;
|
||||
|
||||
#define CHF_DEFAULT 0x0000 /* default flags */
|
||||
#define CHF_ABORT 0x0001 /* use abort() instead of exit() */
|
||||
|
||||
typedef enum /* Current CHF state */
|
||||
{
|
||||
CHF_UNKNOWN,
|
||||
CHF_IDLE,
|
||||
CHF_SIGNALING,
|
||||
CHF_UNWINDING,
|
||||
CHF_SIGNAL_UNWINDING
|
||||
}
|
||||
ChfState;
|
||||
|
||||
typedef struct ChfDescriptor_S /* Condition descriptor */
|
||||
{
|
||||
int module_id; /* Module identifier */
|
||||
int condition_code; /* Condition code */
|
||||
ChfSeverity severity; /* Severity */
|
||||
int line_number; /* Line # or CHF_UNK_LINE_NUMBER */
|
||||
const ChfChar *file_name; /* File name or CHF_UNK_FILE_NAME */
|
||||
ChfChar message[CHF_MAX_MESSAGE_LENGTH]; /* Partial message */
|
||||
struct ChfDescriptor_S *next; /* Link to next descriptor */
|
||||
}
|
||||
ChfDescriptor;
|
||||
|
||||
typedef struct ChfTable_S /* Standalone message table */
|
||||
{
|
||||
int module; /* Module identifier */
|
||||
int code; /* Condition code */
|
||||
ChfChar *msg_template; /* Message template */
|
||||
}
|
||||
ChfTable;
|
||||
|
||||
typedef /* Generic pointer */
|
||||
void *ChfPointer;
|
||||
|
||||
typedef /* Condition handler */
|
||||
ChfAction (*ChfHandler)(
|
||||
const ChfDescriptor *,
|
||||
const ChfState,
|
||||
ChfPointer
|
||||
);
|
||||
|
||||
typedef /* Message retrieval 'get_message' function */
|
||||
const ChfChar * (*ChfMrsGet)(
|
||||
void *,
|
||||
const int,
|
||||
const int,
|
||||
const ChfChar *default_message
|
||||
);
|
||||
|
||||
typedef /* Message retrieval 'exit' function */
|
||||
void (*ChfMrsExit)(
|
||||
void *
|
||||
);
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Condition generation macros
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CHF_EXTENDED_INFO)
|
||||
#define ChfCondition \
|
||||
ChfGenerate( \
|
||||
CHF_MODULE_ID, \
|
||||
ChfText(__FILE__), __LINE__,
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfErrnoCondition
|
||||
#else
|
||||
#define ChfErrnoCondition \
|
||||
ChfGenerate( \
|
||||
CHF_ERRNO_SET, \
|
||||
ChfText(__FILE__), __LINE__, \
|
||||
errno, \
|
||||
CHF_ERROR \
|
||||
)
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define ChfCondition \
|
||||
ChfGenerate( \
|
||||
CHF_MODULE_ID, \
|
||||
CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER,
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfErrnoCondition
|
||||
#else
|
||||
#define ChfErrnoCondition \
|
||||
ChfGenerate( \
|
||||
CHF_ERRNO_SET, \
|
||||
CHF_UNKNOWN_FILE_NAME, CHF_UNKNOWN_LINE_NUMBER, \
|
||||
errno, \
|
||||
CHF_ERROR \
|
||||
)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define ChfEnd \
|
||||
)
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Structured condition handling
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define ChfTry \
|
||||
{\
|
||||
ChfSigjmp_buf _chf_sigjmp_buf;\
|
||||
if(ChfSigsetjmp(_chf_sigjmp_buf, 1) == 0)\
|
||||
{\
|
||||
ChfPushHandler(CHF_NULL_HANDLER, _chf_sigjmp_buf, CHF_NULL_POINTER);
|
||||
|
||||
#define ChfCatch \
|
||||
ChfPopHandler();\
|
||||
}\
|
||||
else\
|
||||
{
|
||||
|
||||
#define ChfEndTry \
|
||||
ChfDiscard();\
|
||||
}\
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Other macros
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define ChfGetNextDescriptor(d) (d)->next
|
||||
#define ChfGetModuleId(d) (d)->module_id
|
||||
#define ChfGetConditionCode(d) (d)->condition_code
|
||||
#define ChfGetSeverity(d) (d)->severity
|
||||
#define ChfGetLineNumber(d) (d)->line_number
|
||||
#define ChfGetFileName(d) (d)->file_name
|
||||
#define ChfGetPartialMessage(d) (d)->message
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int ChfInit( /* Generic initialization */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
void *mrs_data, /* Message retrieval private data */
|
||||
ChfMrsGet mrs_get, /* 'GetMessage' function */
|
||||
ChfMrsExit mrs_exit, /* 'Exit' function */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
int ChfMsgcatInit( /* Initialization with msgcat subsystem */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfChar *msgcat_name, /* Name of the message catalog */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
int ChfStaticInit( /* Initialization with static message tables */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfTable *table, /* Static message table */
|
||||
const size_t table_size, /* Size of the message table */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
int ChfWin32Init( /* Initialization within _WIN32 */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
#ifndef _WIN32
|
||||
void *instance, /* Fake arguments */
|
||||
#else
|
||||
HINSTANCE instance, /* App. instance handle */
|
||||
#endif
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
);
|
||||
|
||||
void ChfExit( /* Exit */
|
||||
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 ChfPopHandler( /* Pop a handler */
|
||||
void
|
||||
);
|
||||
|
||||
ChfChar *ChfBuildMessage( /* Build a condition message */
|
||||
const ChfDescriptor *descriptor
|
||||
);
|
||||
|
||||
void ChfSignal( /* Signal the current conditions */
|
||||
void
|
||||
);
|
||||
|
||||
void ChfDiscard( /* Discard the current conditions */
|
||||
void
|
||||
);
|
||||
|
||||
void ChfGenerate( /* Generate a condition into the stack */
|
||||
const int module_id,
|
||||
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
|
||||
);
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@- Revised unwind context passing mechanism; redefined CHF_NULL_CONTEXT
|
||||
- New macros: CHF_NULL_HANDLER, CHF_MAJOR_RELEASE_NUMBER,
|
||||
CHF_MINOR_RELEASE_NUMBER
|
||||
- New ChfAction value: CHF_UNWIND_KEEP; fixed spelling of ChfAction value:
|
||||
CHF_SIGNALLING -> CHF_SIGNALING
|
||||
- Added structured condition handling macros: ChfTry, ChfCatch, ChfEndTry
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: Chf.h,v 1.6 1997/01/15 13:41:20 cibrario Exp cibrario $
|
||||
d14 1
|
||||
a14 1
|
||||
.include : stdio.h setjmp.h
|
||||
d18 8
|
||||
d53 19
|
||||
d77 1
|
||||
a77 1
|
||||
#define CHF_UNKNOWN_FILE_NAME (char *)NULL
|
||||
d82 1
|
||||
a82 1
|
||||
#define CHF_LIBRARY_ID "$Id: Chf.h,v 1.6 1997/01/15 13:41:20 cibrario Exp cibrario $"
|
||||
d85 1
|
||||
a85 1
|
||||
#define CHF_MINOR_RELEASE_NUMBER 1
|
||||
d103 1
|
||||
d153 2
|
||||
a154 2
|
||||
const char *file_name; /* File name or CHF_UNK_FILE_NAME */
|
||||
char message[CHF_MAX_MESSAGE_LENGTH]; /* Partial message */
|
||||
d163 1
|
||||
a163 1
|
||||
char *template; /* Message template */
|
||||
d178 1
|
||||
a178 1
|
||||
const char * (*ChfMrsGet)(
|
||||
d182 1
|
||||
a182 1
|
||||
const char *default_message
|
||||
d199 1
|
||||
a199 1
|
||||
__FILE__, __LINE__,
|
||||
d201 3
|
||||
d207 1
|
||||
a207 1
|
||||
__FILE__, __LINE__, \
|
||||
d211 1
|
||||
d219 3
|
||||
d229 1
|
||||
d243 2
|
||||
a244 2
|
||||
sigjmp_buf _chf_sigjmp_buf;\
|
||||
if(sigsetjmp(_chf_sigjmp_buf, 1) == 0)\
|
||||
d279 1
|
||||
a279 1
|
||||
const char *app_name, /* Application's name */
|
||||
d290 1
|
||||
a290 1
|
||||
const char *app_name, /* Application's name */
|
||||
d292 1
|
||||
a292 1
|
||||
const char *msgcat_name, /* Name of the message catalog */
|
||||
d299 1
|
||||
a299 1
|
||||
const char *app_name, /* Application's name */
|
||||
d308 13
|
||||
d339 1
|
||||
a339 1
|
||||
char *ChfBuildMessage( /* Build a condition message */
|
||||
d353 1
|
||||
a353 1
|
||||
const char *file_name,
|
||||
d360 1
|
||||
a360 1
|
||||
const char *ChfGetMessage( /* Retrieve a condition message */
|
||||
d363 1
|
||||
a363 1
|
||||
const char *default_message
|
||||
@
|
||||
|
||||
|
||||
1.6
|
||||
log
|
||||
@Defined the new data type ChfPointer, a generic (void *) pointer. Each
|
||||
condition handler can have a private handler context pointer, of type
|
||||
ChfPointer, that the function ChfPushHandler() stores and that is passed
|
||||
to the handler when it's activated.
|
||||
Fixed a wrong adjustment of the condition handlers stack pointer after
|
||||
an unwind operation.
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: Chf.h,v 1.5 1996/10/04 09:45:30 cibrario Beta cibrario $
|
||||
d18 8
|
||||
d52 1
|
||||
a52 1
|
||||
#define CHF_NULL_CONTEXT (jmp_buf *)NULL
|
||||
d54 5
|
||||
a58 1
|
||||
#define CHF_LIBRARY_ID "$Id: Chf.h,v 1.5 1996/10/04 09:45:30 cibrario Beta cibrario $"
|
||||
d98 2
|
||||
a99 1
|
||||
CHF_UNWIND /* Stack unwind */
|
||||
d113 1
|
||||
a113 1
|
||||
CHF_SIGNALLING,
|
||||
d202 23
|
||||
d282 1
|
||||
a282 1
|
||||
jmp_buf *unwind_context, /* Unwind context */
|
||||
@
|
||||
|
||||
|
||||
1.5
|
||||
log
|
||||
@Updated the condition message format in the private header ChfPriv.h to
|
||||
improve internationalization
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: Chf.h,v 1.4 1996/09/25 13:21:11 cibrario Exp cibrario $
|
||||
d18 4
|
||||
d45 2
|
||||
a46 1
|
||||
#define CHF_LIBRARY_ID "$Id: Chf.h,v 1.4 1996/09/25 13:21:11 cibrario Exp cibrario $"
|
||||
d126 3
|
||||
d132 2
|
||||
a133 1
|
||||
const ChfState
|
||||
d246 2
|
||||
a247 1
|
||||
jmp_buf *unwind_context /* Unwind context */
|
||||
@
|
||||
|
||||
|
||||
1.4
|
||||
log
|
||||
@Added macro CHF_LIBRARY_ID; it contains the current ID of the CHF library.
|
||||
The module chf_init.o will contain it as a static char[] variable.
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: Chf.h,v 1.2 1996/06/11 13:02:10 cibrario Exp cibrario $
|
||||
d18 4
|
||||
d41 1
|
||||
a41 1
|
||||
#define CHF_LIBRARY_ID "$Id$"
|
||||
@
|
||||
|
||||
|
||||
1.2
|
||||
log
|
||||
@Added prototype for ChfGetTopCondition()
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: Chf.h,v 1.1 1996/05/28 12:56:47 cibrario Exp cibrario $
|
||||
d18 3
|
||||
d37 1
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, main header
|
||||
d17 3
|
||||
a19 1
|
||||
$Log$
|
||||
d21 1
|
||||
d262 4
|
||||
@
|
298
Chf/RCS/ChfPriv.h,v
Normal file
298
Chf/RCS/ChfPriv.h,v
Normal file
|
@ -0,0 +1,298 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.11.57.57; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.26.14.14.36; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.6;
|
||||
|
||||
1.6
|
||||
date 97.01.15.13.38.24; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.5;
|
||||
|
||||
1.5
|
||||
date 96.10.04.09.43.51; author cibrario; state Beta;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.56.37; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This is the private header of the Condition Handling Facility
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: ChfPriv.h,v 2.1 2000/05/26 14:14:36 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: ChfPriv.h,v $, main header
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 2-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This is the private header of the Condition Handling Facility
|
||||
|
||||
.include : *
|
||||
|
||||
.notes :
|
||||
$Log: ChfPriv.h,v $
|
||||
Revision 2.1 2000/05/26 14:14:36 cibrario
|
||||
- Defined new abort codes: CHF_ABORT_GET_CONTEXT, CHF_ABORT_PTHREAD
|
||||
- Redefined .unwind_context field of ChfHandlerDescriptor
|
||||
- Conditional retarget of chf_context for multithreading support
|
||||
- Declared new private function: _ChfGetContext() (mt support only)
|
||||
|
||||
Revision 1.6 1997/01/15 13:38:24 cibrario
|
||||
Added the new field .handler_context to struct ChfHandlerDescriptor_S, to
|
||||
store, for each condition handler, the private handler context pointer.
|
||||
|
||||
Revision 1.5 1996/10/04 09:43:51 cibrario
|
||||
Updated the condition message format to improve internationalization
|
||||
|
||||
Revision 1.1 1996/05/28 12:56:37 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Macros
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_MODULE_ID CHF_SET
|
||||
#define CHF_TMP_MESSAGE_LENGTH (2*CHF_MAX_MESSAGE_LENGTH)
|
||||
#define CHF_DEF_MESSAGE_LENGTH 40
|
||||
#define CHF_DEF_PARTIAL_MSG_FMT ChfText("Code <%d>d")
|
||||
#define CHF_DEF_MID_MSG_FMT ChfText("Mid <%d>d")
|
||||
#define CHF_EXTENDED_INFO_FMT ChfText("(%s,%d)")
|
||||
#define CHF_SEVERITY_NAMES \
|
||||
{ ChfText("S"), ChfText("I"), ChfText("W"), ChfText("E"), ChfText("F") }
|
||||
#define CHF_UNKNOWN_SEVERITY ChfText("?")
|
||||
#define CHF_MESSAGE_SEPARATOR ChfText("-")
|
||||
#define CHF_MESSAGE_TERMINATOR ChfText("\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()
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#define CHF_ABORT_SILENT 0
|
||||
#define CHF_ABORT_INIT 1
|
||||
#define CHF_ABORT_MSG_OVF 2
|
||||
#define CHF_ABORT_INVALID_ACTION 3
|
||||
#define CHF_ABORT_DUP_INIT 4
|
||||
#define CHF_ABORT_ALREADY_UNWINDING 5
|
||||
#define CHF_ABORT_IMPROPERLY_HANDLED 6
|
||||
#define CHF_ABORT_FATAL_UNWINDING 7
|
||||
#define CHF_ABORT_COND_STACK_OVF 8
|
||||
#define CHF_ABORT_GET_CONTEXT 9
|
||||
#define CHF_ABORT_PTHREAD 10
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct ChfHandlerDescriptor_S
|
||||
{
|
||||
ChfHandler handler;
|
||||
void *unwind_context;
|
||||
ChfPointer handler_context;
|
||||
}
|
||||
ChfHandlerDescriptor;
|
||||
|
||||
typedef struct ChfContext_S /* CHF Context */
|
||||
{
|
||||
ChfState state; /* Current CHF state */
|
||||
const ChfChar *app_name; /* Application's name */
|
||||
ChfOptions options; /* Options */
|
||||
void *mrs_data; /* Message retrieval private data */
|
||||
ChfMrsGet mrs_get; /* 'GetMessage' function */
|
||||
ChfMrsExit mrs_exit; /* 'Exit' function */
|
||||
int condition_stack_size; /* Size of the condition stack */
|
||||
int handler_stack_size; /* Size of the handler stack */
|
||||
int exit_code; /* Abnormal exit code */
|
||||
ChfDescriptor *condition_stack; /* Condition stack */
|
||||
ChfDescriptor *condition_base; /* Current condition stack base */
|
||||
ChfDescriptor *condition_sp; /* Current condition stack pointer */
|
||||
ChfHandlerDescriptor *handler_stack; /* Handler stack */
|
||||
ChfHandlerDescriptor *handler_sp; /* Current handler stack pointer */
|
||||
ChfChar *message_buffer; /* Message buffer */
|
||||
}
|
||||
ChfContext;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Multithreading support
|
||||
------------------------------------------------------------------------- */
|
||||
#ifdef _REENTRANT
|
||||
#define chf_context (*_ChfGetContext())
|
||||
#else
|
||||
#define chf_context _chf_context
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
extern ChfContext _chf_context; /* CHF Context */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private function prototypes
|
||||
------------------------------------------------------------------------- */
|
||||
#ifdef _REENTRANT
|
||||
ChfContext *_ChfGetContext(void);
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private redirection of stdlib functions needed by Win32
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ChfStrlen _tcslen
|
||||
#define ChfStrcpy _tcscpy
|
||||
#define ChfStrcat _tcscat
|
||||
#define ChfStrncpy _tcsncpy
|
||||
#define ChfSprintf _stprintf
|
||||
#define ChfVsprintf _vstprintf
|
||||
#else
|
||||
#define ChfStrlen strlen
|
||||
#define ChfStrcpy strcpy
|
||||
#define ChfStrcat strcat
|
||||
#define ChfStrncpy strncpy
|
||||
#define ChfSprintf sprintf
|
||||
#define ChfVsprintf vsprintf
|
||||
#endif
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@- Defined new abort codes: CHF_ABORT_GET_CONTEXT, CHF_ABORT_PTHREAD
|
||||
- Redefined .unwind_context field of ChfHandlerDescriptor
|
||||
- Conditional retarget of chf_context for multithreading support
|
||||
- Declared new private function: _ChfGetContext() (mt support only)
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: ChfPriv.h,v 1.6 1997/01/15 13:38:24 cibrario Exp cibrario $
|
||||
d18 6
|
||||
d45 11
|
||||
a55 10
|
||||
#define CHF_DEF_PARTIAL_MSG_FMT "Code <%d>d"
|
||||
#define CHF_DEF_MID_MSG_FMT "Mid <%d>d"
|
||||
#define CHF_EXTENDED_INFO_FMT "(%s,%d)"
|
||||
#define CHF_SEVERITY_NAMES { "S", "I", "W", "E", "F" }
|
||||
#define CHF_UNKNOWN_SEVERITY "?"
|
||||
#define CHF_MESSAGE_SEPARATOR "-"
|
||||
#define CHF_MESSAGE_TERMINATOR "\n"
|
||||
#define CHF_ABORT_HEADER "ChfAbort-F-"
|
||||
#define CHF_ABORT_BAD_CODE_FMT "Bad abort code <%d>d\n"
|
||||
#define CHF_ABORT_GOOD_CODE_FMT "%s\n"
|
||||
d91 1
|
||||
a91 1
|
||||
const char *app_name; /* Application's name */
|
||||
d104 1
|
||||
a104 1
|
||||
char *message_buffer; /* Message buffer */
|
||||
d132 21
|
||||
@
|
||||
|
||||
|
||||
1.6
|
||||
log
|
||||
@Added the new field .handler_context to struct ChfHandlerDescriptor_S, to
|
||||
store, for each condition handler, the private handler context pointer.
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: ChfPriv.h,v 1.5 1996/10/04 09:43:51 cibrario Beta cibrario $
|
||||
d18 4
|
||||
d64 2
|
||||
d76 1
|
||||
a76 1
|
||||
jmp_buf *unwind_context;
|
||||
d103 10
|
||||
d116 1
|
||||
a116 1
|
||||
extern ChfContext chf_context; /* CHF Context */
|
||||
d120 1
|
||||
a120 1
|
||||
Function prototypes
|
||||
d122 3
|
||||
@
|
||||
|
||||
|
||||
1.5
|
||||
log
|
||||
@Updated the condition message format to improve internationalization
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: ChfPriv.h,v 1.1 1996/05/28 12:56:37 cibrario Exp cibrario $
|
||||
d18 3
|
||||
d71 1
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, main header
|
||||
d17 3
|
||||
a19 1
|
||||
$Log$
|
||||
d21 1
|
||||
d35 1
|
||||
a35 2
|
||||
#define CHF_SEVERITY_NAMES { "success", \
|
||||
"info", "warning", "error", "fatal" }
|
||||
d37 1
|
||||
a37 1
|
||||
#define CHF_MESSAGE_SEPARATOR ": "
|
||||
d39 1
|
||||
a39 1
|
||||
#define CHF_ABORT_HEADER "ChfAbort: "
|
||||
@
|
333
Chf/RCS/Makefile,v
Normal file
333
Chf/RCS/Makefile,v
Normal file
|
@ -0,0 +1,333 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.53.07; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.2;
|
||||
|
||||
1.2
|
||||
date 96.06.11.13.03.06; author cibrario; state Beta;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.29.09.12.10; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@Makefile for the CHF library
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@- Deep revision to support transparent, multi-platform builds
|
||||
- Added multithreading support
|
||||
- New/revised targets: test, doc, clean
|
||||
@
|
||||
text
|
||||
@# .+
|
||||
#
|
||||
# .identifier : $Id: Makefile,v 1.2 1996/06/11 13:03:06 cibrario Beta cibrario $
|
||||
# .context : CHF, Condition Handling Facility
|
||||
# .title : $RCSfile: Makefile,v $, Makefile
|
||||
# .kind : Makefile
|
||||
# .author : Ivan Cibrario B.
|
||||
# .site : CSTV-CNR
|
||||
# .creation : 3-May-1996
|
||||
# .keywords : *
|
||||
# .description :
|
||||
# Makefile for the CHF library
|
||||
# .notes :
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.2 1996/06/11 13:03:06 cibrario
|
||||
# Added new module chf_top.c
|
||||
#
|
||||
# Revision 1.1 1996/05/29 09:12:10 cibrario
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
# .-
|
||||
|
||||
#
|
||||
# Platform-dependent definitions. Edit when required, for example to
|
||||
# add a new platform.
|
||||
#
|
||||
# There is a set of definitions per platform; the prefix or the definition
|
||||
# names is the value returned by a plain 'uname' on that platform.
|
||||
#
|
||||
# CC: cc compiler
|
||||
# TS_CFLAGS: cc flags to enable multithreading
|
||||
# TS_LOADLIBES: ld flags and additional libraries to enable multithreading
|
||||
# F_CFLAGS: cc feature test macros
|
||||
# O_CFLAGS: cc optimization control flags and other, additional flags
|
||||
#
|
||||
# Supported platforms:
|
||||
# OSF1 Digital UNIX v4.0
|
||||
# SunOS Solaris v2.6
|
||||
# Linux Linux 2.1
|
||||
#
|
||||
|
||||
OSF1_CC = cc
|
||||
OSF1_TS_CFLAGS = -pthread
|
||||
OSF1_TS_LOADLIBES = -pthread
|
||||
OSF1_F_CFLAGS = "-D_POSIX_C_SOURCE=199506L -D_XOPEN_SOURCE"
|
||||
OSF1_O_CFLAGS = "-O3 -std1"
|
||||
|
||||
SunOS_CC = gcc
|
||||
SunOS_TS_CFLAGS = -D_REENTRANT
|
||||
SunOS_TS_LOADLIBES = -lpthread
|
||||
SunOS_F_CFLAGS = -D_POSIX_C_SOURCE=199506L
|
||||
SunOS_O_CFLAGS = "-O3 -ansi -pedantic"
|
||||
|
||||
Linux_CC = cc
|
||||
Linux_TS_CFLAGS = -D_REENTRANT
|
||||
Linux_TS_LOADLIBES = -lpthread
|
||||
Linux_F_CFLAGS = -D_POSIX_C_SOURCE=199506L
|
||||
Linux_O_CFLAGS = "-O3 -ansi -pedantic"
|
||||
|
||||
#
|
||||
# Destination paths for library objects, C headers, binaries, message catalog
|
||||
# sources and X resource files. Edit as required.
|
||||
#
|
||||
DESTLIBDIR = $(HOME)/lib
|
||||
DESTHDRDIR = $(HOME)/include
|
||||
DESTBINDIR = $(HOME)/bin
|
||||
DESTMSFDIR = $(HOME)/msf
|
||||
DESTRESDIR = $(HOME)/res
|
||||
|
||||
#
|
||||
# The default target recursively invokes make defining UNAME to the
|
||||
# string returned by uname; this is used to make appropriate
|
||||
# platform-dependent definitions above.
|
||||
#
|
||||
default:
|
||||
@@$(MAKE) UNAME=`uname` all
|
||||
|
||||
#
|
||||
# Vectored definitions; see above and do not edit.
|
||||
#
|
||||
CC = $($(UNAME)_CC)
|
||||
TS_CFLAGS = $($(UNAME)_TS_CFLAGS)
|
||||
TS_LOADLIBES = $($(UNAME)_TS_LOADLIBES)
|
||||
F_CFLAGS = $($(UNAME)_F_CFLAGS)
|
||||
O_CFLAGS = $($(UNAME)_O_CFLAGS)
|
||||
|
||||
#
|
||||
# Include common definitions
|
||||
#
|
||||
include Makefile_def
|
||||
|
||||
#
|
||||
# Build directories for single-threaded and multi-threaded lib versions
|
||||
#
|
||||
ST_BUILD_DIR = ./st_build
|
||||
MT_BUILD_DIR = ./mt_build
|
||||
|
||||
#
|
||||
# Library names
|
||||
#
|
||||
ST_LIB_NAME = libChf.a
|
||||
MT_LIB_NAME = libChf_r.a
|
||||
|
||||
#
|
||||
# Library paths
|
||||
#
|
||||
ST_LIB_PATH = $(ST_BUILD_DIR)/$(ST_LIB_NAME)
|
||||
MT_LIB_PATH = $(MT_BUILD_DIR)/$(MT_LIB_NAME)
|
||||
|
||||
#
|
||||
# all: Create and populate build directories; for each build directory,
|
||||
# make dependencies and rebuild
|
||||
#
|
||||
all: $(ST_LIB_PATH) $(MT_LIB_PATH)
|
||||
|
||||
#
|
||||
# test: Build and executes test programs
|
||||
#
|
||||
test:
|
||||
@@$(MAKE) UNAME=`uname` do_test
|
||||
@@echo "All tests completed successfully"
|
||||
|
||||
do_test: $(ST_LIB_PATH) $(MT_LIB_PATH)
|
||||
@@cd $(ST_BUILD_DIR) && \
|
||||
$(MAKE) test CC=$(CC) LIB=$(ST_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) > test.log 2>&1
|
||||
@@cd $(MT_BUILD_DIR) && \
|
||||
$(MAKE) test CC=$(CC) LIB=$(MT_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) \
|
||||
TS_CFLAGS=$(TS_CFLAGS) TS_LOADLIBES=$(TS_LOADLIBES) >> test.log 2>&1
|
||||
|
||||
#
|
||||
# doc: Make documentation files
|
||||
#
|
||||
doc:
|
||||
makeinfo chf.texi
|
||||
texi2dvi chf.texi; dvips -o chf.ps chf.dvi
|
||||
|
||||
#
|
||||
# clean: Remove build directories
|
||||
#
|
||||
clean:
|
||||
rm -rf $(ST_BUILD_DIR) $(MT_BUILD_DIR)
|
||||
|
||||
#
|
||||
# install: Move all files to their directories
|
||||
#
|
||||
install: $(ST_LIB_PATH) $(MT_LIB_PATH) $(HDR) $(MSF) $(RES)
|
||||
chmod u+w $(ST_LIB_PATH) $(MT_LIB_PATH) $(BIN) $(HDR) $(MSF) $(RES)
|
||||
cp $(ST_LIB_PATH) $(MT_LIB_PATH) $(DESTLIBDIR)
|
||||
cp $(HDR) $(DESTHDRDIR)
|
||||
cp $(MSF) $(DESTMSFDIR)
|
||||
echo cp $(RES) $(DESTRESDIR)
|
||||
|
||||
#
|
||||
# Prepare the build directories for use
|
||||
#
|
||||
$(ST_BUILD_DIR) $(MT_BUILD_DIR):
|
||||
@@mkdir $@@ && \
|
||||
cd $@@ && \
|
||||
ln -s ../Makefile_sub Makefile && \
|
||||
for s in $(SRC) $(TSRC) $(HDR) $(MSF) $(TMSF) $(RES) ; do \
|
||||
ln -s ../$$s $$s ; \
|
||||
done
|
||||
|
||||
#
|
||||
# Make the libraries; the rebuild is forced here because only the
|
||||
# sub-makes have module dependencies.
|
||||
#
|
||||
$(ST_LIB_PATH): $(ST_BUILD_DIR) force
|
||||
@@cd $(ST_BUILD_DIR) && \
|
||||
$(MAKE) depend CC=$(CC) LIB=$(ST_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) && \
|
||||
$(MAKE) all CC=$(CC) LIB=$(ST_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS)
|
||||
|
||||
$(MT_LIB_PATH): $(MT_BUILD_DIR) force
|
||||
@@cd $(MT_BUILD_DIR) && \
|
||||
$(MAKE) depend CC=$(CC) LIB=$(MT_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) \
|
||||
TS_CFLAGS=$(TS_CFLAGS) TS_LOADLIBES=$(TS_LOADLIBES) && \
|
||||
$(MAKE) all CC=$(CC) LIB=$(MT_LIB_NAME) \
|
||||
F_CFLAGS=$(F_CFLAGS) O_CFLAGS=$(O_CFLAGS) \
|
||||
TS_CFLAGS=$(TS_CFLAGS) TS_LOADLIBES=$(TS_LOADLIBES)
|
||||
|
||||
force:
|
||||
@
|
||||
|
||||
|
||||
1.2
|
||||
log
|
||||
@Added new module chf_top.c
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
# .identifier : $Id: Makefile,v 1.1 1996/05/29 09:12:10 cibrario Exp cibrario $
|
||||
d15 3
|
||||
d25 37
|
||||
d63 1
|
||||
a63 1
|
||||
# sources and X resource files.
|
||||
d72 9
|
||||
a80 1
|
||||
# Source files
|
||||
d82 5
|
||||
a86 3
|
||||
SRC = chf_init.c chf_gen.c chf_sig.c chf_abrt.c chf_hdlr.c \
|
||||
chf_msgc.c chf_st.c \
|
||||
chf_top.c
|
||||
d88 4
|
||||
a91 1
|
||||
HDR = Chf.h ChfPriv.h
|
||||
d93 5
|
||||
a97 1
|
||||
MSF = chf.msf
|
||||
d99 5
|
||||
a103 1
|
||||
RES =
|
||||
d106 1
|
||||
a106 1
|
||||
# Targets
|
||||
d108 2
|
||||
a109 3
|
||||
OBJ = $(SRC:.c=.o)
|
||||
LIB = libChf.a
|
||||
BIN =
|
||||
d111 5
|
||||
d118 1
|
||||
a118 1
|
||||
# Other definitions
|
||||
d120 3
|
||||
a122 3
|
||||
HPATH = -I. -I$(DESTHDRDIR)
|
||||
LPATH = -L. -L$(DESTLIBDIR)
|
||||
OFLAG = -O
|
||||
d124 8
|
||||
a131 2
|
||||
CFLAGS = $(OFLAG) $(U_CFLAGS) $(HPATH)
|
||||
LDFLAGS = $(LPATH)
|
||||
d134 1
|
||||
a134 3
|
||||
# setenv U_LOADLIBES "-li" on Ultrix
|
||||
# setenv U_LOADLIBES "" on Digital UNIX
|
||||
# setenv U_LOADLIBES "-lintl" on SCO UNIX
|
||||
d136 3
|
||||
a138 1
|
||||
LOADLIBES = $(LIB) $(U_LOADLIBES)
|
||||
d141 1
|
||||
a141 1
|
||||
# Targets
|
||||
d143 2
|
||||
a144 1
|
||||
all: $(LIB) $(BIN)
|
||||
d146 6
|
||||
a151 4
|
||||
install: $(LIB) $(BIN) $(HDR) $(MSF)
|
||||
chmod u+w $(LIB) $(BIN) $(HDR) $(MSF)
|
||||
cp $(LIB) $(DESTLIBDIR)
|
||||
echo cp $(BIN) $(DESTBINDIR)
|
||||
d156 30
|
||||
a185 8
|
||||
depend: $(SRC)
|
||||
makedepend $(HPATH) $(SRC)
|
||||
|
||||
lint:
|
||||
$(LINT) -u $(CFLAGS) $(SRC)
|
||||
|
||||
$(LIB): $(OBJ)
|
||||
$(AR) $(ARFLAGS) $@@ $?
|
||||
d187 1
|
||||
a187 1
|
||||
test: test.c $(LIB)
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
# .identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
# .title : $RCSfile$, Makefile
|
||||
d14 3
|
||||
a16 1
|
||||
# $Log$
|
||||
d18 1
|
||||
d35 2
|
||||
a36 1
|
||||
chf_msgc.c chf_st.c
|
||||
@
|
116
Chf/RCS/Makefile_def,v
Normal file
116
Chf/RCS/Makefile_def,v
Normal file
|
@ -0,0 +1,116 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.11.59.19; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.08.39; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@# .+
|
||||
#
|
||||
# .identifier : $Id: Makefile_def,v 2.1 2000/05/29 13:08:39 cibrario Rel cibrario $
|
||||
# .context : CHF, Condition Handling Facility
|
||||
# .title : $RCSfile: Makefile_def,v $, Makefile
|
||||
# .kind : Makefile
|
||||
# .author : Ivan Cibrario B.
|
||||
# .site : CSTV-CNR
|
||||
# .creation : 22-May-2000
|
||||
# .keywords : *
|
||||
# .description :
|
||||
# Makefile for CHF library common definitions; no platform dependencies here.
|
||||
# .notes :
|
||||
# $Log: Makefile_def,v $
|
||||
# Revision 2.1 2000/05/29 13:08:39 cibrario
|
||||
# *** empty log message ***
|
||||
#
|
||||
#
|
||||
# .-
|
||||
|
||||
#
|
||||
# Source files
|
||||
#
|
||||
SRC = chf_init.c chf_gen.c chf_sig.c chf_abrt.c chf_hdlr.c \
|
||||
chf_msgc.c chf_st.c \
|
||||
chf_top.c \
|
||||
chf_win32.c
|
||||
|
||||
TSRC = test01.c test02.c test03.c test04.c test05.c test06.c \
|
||||
test07.c
|
||||
|
||||
HDR = Chf.h ChfPriv.h
|
||||
|
||||
MSF = chf.msf
|
||||
|
||||
TMSF = test01.msf
|
||||
|
||||
RES =
|
||||
|
||||
#
|
||||
# Target object files
|
||||
#
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
#
|
||||
# Target test programs
|
||||
#
|
||||
TBIN = $(TSRC:.c=)
|
||||
|
||||
#
|
||||
# Other definitions
|
||||
#
|
||||
HPATH = -I.
|
||||
LPATH = -L.
|
||||
|
||||
CFLAGS = $(F_CFLAGS) $(O_CFLAGS) $(TS_CFLAGS) $(U_CFLAGS) $(HPATH)
|
||||
LFLAGS = $(F_CFLAGS) $(L_CFLAGS) $(TS_LFLAGS) $(U_CFLAGS) $(HPATH)
|
||||
LDFLAGS = $(LPATH)
|
||||
|
||||
LOADLIBES = $(LIB) $(TS_LOADLIBES) $(I_LOADLIBES) $(U_LOADLIBES)
|
||||
|
||||
#
|
||||
# Solaris spelling of LOADLIBES
|
||||
#
|
||||
LDLIBS = $(LOADLIBES)
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
# .identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
# .title : $RCSfile$, Makefile
|
||||
d14 3
|
||||
a16 1
|
||||
# $Log$
|
||||
d18 1
|
||||
d26 2
|
||||
a27 1
|
||||
chf_top.c
|
||||
@
|
62
Chf/RCS/Makefile_sub,v
Normal file
62
Chf/RCS/Makefile_sub,v
Normal file
|
@ -0,0 +1,62 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.08.51; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@# .+
|
||||
#
|
||||
# .identifier : $Id$
|
||||
# .context : CHF, Condition Handling Facility
|
||||
# .title : $RCSfile$, Makefile
|
||||
# .kind : Makefile
|
||||
# .author : Ivan Cibrario B.
|
||||
# .site : CSTV-CNR
|
||||
# .creation : 22-May-2000
|
||||
# .keywords : *
|
||||
# .description :
|
||||
# Makefile for CHF library subdirectories
|
||||
# .notes :
|
||||
# $Log$
|
||||
#
|
||||
# .-
|
||||
|
||||
#
|
||||
# Include common definitions
|
||||
#
|
||||
include ../Makefile_def
|
||||
|
||||
#
|
||||
# Targets
|
||||
#
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(OBJ)
|
||||
$(AR) $(ARFLAGS) $@@ $?
|
||||
|
||||
test: $(TBIN)
|
||||
@@for b in $(TBIN) ; do \
|
||||
./$$b ; \
|
||||
done
|
||||
|
||||
depend: $(SRC)
|
||||
@@makedepend $(HPATH) $(SRC)
|
||||
@
|
109
Chf/RCS/chf.msf,v
Normal file
109
Chf/RCS/chf.msf,v
Normal file
|
@ -0,0 +1,109 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @$ . @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.12.00.19; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.26.14.17.21; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.57.06; author cibrario; state Beta;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@Message source file for the CHF conditions
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@$ .+
|
||||
$ .
|
||||
$ .identifier : $Id: chf.msf,v 2.1 2000/05/26 14:17:21 cibrario Rel cibrario $
|
||||
$ .context :
|
||||
$ .title : $RCSfile: chf.msf,v $
|
||||
$ .kind : Makefile
|
||||
$ .author : Ivan Cibrario B.
|
||||
$ .site : CSTV-CNR
|
||||
$ .creation : 27-May-1996
|
||||
$ .keywords : *
|
||||
$ .description :
|
||||
$ . Message source file for the CHF conditions
|
||||
$ .notes :
|
||||
$ . $Log: chf.msf,v $
|
||||
$ . Revision 2.1 2000/05/26 14:17:21 cibrario
|
||||
$ . Updated documentation block and RCS log message header to prevent
|
||||
$ . gencat warnings on Linux boxes
|
||||
$ .
|
||||
$ . Revision 1.1 1996/05/28 12:57:06 cibrario
|
||||
$ . Initial revision
|
||||
$ .
|
||||
$ .-
|
||||
|
||||
$set 1
|
||||
2 Chf
|
||||
3 Errno
|
||||
|
||||
$set 2
|
||||
1 Condition stack is full
|
||||
2 Handler stack is full
|
||||
3 Handler stack is empty
|
||||
4 Wrong Chf state for requested operation
|
||||
5 Invalid action code from handler (code=<%d>d)
|
||||
6 Dynamic memory allocation failed
|
||||
7 Function not implemented
|
||||
10 setlocale() failed
|
||||
11 catopen() failed
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@Updated documentation block and RCS log message header to prevent
|
||||
gencat warnings on Linux boxes
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
$ .identifier : $Id: chf.msf,v 1.1 1996/05/28 12:57:06 cibrario Beta cibrario $
|
||||
d15 4
|
||||
d35 1
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d2 2
|
||||
a3 2
|
||||
$
|
||||
$ .identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
$ .title : $RCSfile$
|
||||
d12 1
|
||||
a12 1
|
||||
$ Message source file for the CHF conditions
|
||||
d14 4
|
||||
a17 2
|
||||
$ $Log$
|
||||
$
|
||||
@
|
123
Chf/RCS/chf.rc,v
Executable file
123
Chf/RCS/chf.rc,v
Executable file
|
@ -0,0 +1,123 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2;
|
||||
locks; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.12.00.46; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
1002 "Chf"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
2001 "Condition stack is full"
|
||||
2002 "Handler stack is full"
|
||||
2003 "Handler stack is empty"
|
||||
2004 "Wrong state for requested operation"
|
||||
2005 "Invalid action code from handler (code=<%d>d)"
|
||||
2006 "Dynamic memory allocation failed"
|
||||
2007 "Function not available"
|
||||
2010 "setlocale() failed"
|
||||
2011 "catopen() failed"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Italian (Italy) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Italian (Italy) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@
|
2677
Chf/RCS/chf.texi,v
Normal file
2677
Chf/RCS/chf.texi,v
Normal file
File diff suppressed because it is too large
Load diff
312
Chf/RCS/chf_abrt.c,v
Normal file
312
Chf/RCS/chf_abrt.c,v
Normal file
|
@ -0,0 +1,312 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.12.08.24; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.26.14.22.07; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.53.26; author cibrario; state Beta;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This module implements the CHF function ChfAbort()
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: chf_abrt.c,v 2.1 2000/05/26 14:22:07 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_abrt.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF function ChfAbort()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_abrt.c,v $
|
||||
Revision 2.1 2000/05/26 14:22:07 cibrario
|
||||
- Conditional inclusion of pthread.h (mt support)
|
||||
- Expanded abort message table with mt support messages
|
||||
- ChfAbort() with CHF_ABORT flag clear and mt support enabled now
|
||||
exits invoking thread only
|
||||
|
||||
Revision 1.1 1996/05/28 12:53:26 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_abrt.c,v 2.1 2000/05/26 14:22:07 cibrario Rel cibrario $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Abort codes message table; the relative position of the messages must
|
||||
match the numeric codes CHF_ABORT_xxxx defined in ChfPriv.h
|
||||
*/
|
||||
static const ChfChar *message_table[] =
|
||||
{
|
||||
(const ChfChar *)NULL,
|
||||
ChfText("Not initialized"),
|
||||
ChfText("Temporary message buffer overflow"),
|
||||
ChfText("Invalid action from last chance handler"),
|
||||
ChfText("Already initialized"),
|
||||
ChfText("Unwind request while unwinding"),
|
||||
ChfText("Improperly handled condition"),
|
||||
ChfText("Fatal condition while unwinding"),
|
||||
ChfText("Condition stack overflow"),
|
||||
ChfText("Can't prime a new Chf context"),
|
||||
ChfText("Pthread interaction failed")
|
||||
};
|
||||
|
||||
#define MESSAGE_TABLE_SIZE (sizeof(message_table)/sizeof(const ChfChar *))
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfAbort
|
||||
.kind : C function
|
||||
.creation : 13-May-1996
|
||||
.description :
|
||||
This function prints the message associated with 'abort_code' and then
|
||||
immediately aborts either the application (when multithreading support not
|
||||
enabled or CHF_ABORT set) or the invoking thread only (multithreading
|
||||
support enabled and CHF_ABORT not set). The abort is performed either:
|
||||
- using abort() if either CHF has not been correctly initialized or
|
||||
the chf_context.options flag CHF_ABORT is set
|
||||
- using exit(chf_context.exit_code) (multithreading support not enabled)
|
||||
or pthread_exit(chf_context.exit_code) (multithreading support enabled)
|
||||
if the flag is clear
|
||||
|
||||
No message is printed if the abort code is CHF_ABORT_SILENT; this code
|
||||
is used, for example, by the default condition handler to terminate the
|
||||
application when a CHF_FATAL condition occours.
|
||||
|
||||
NOTE: This function must be called only when either a serious internal CHF
|
||||
failure occurs or it's necessary to abort the application.
|
||||
|
||||
WIN32:
|
||||
|
||||
- stderr stream is not supported; the abort message is displayed in a
|
||||
message box only if Chf has been correctly initialized, otherwise the
|
||||
abort will be done silently
|
||||
|
||||
- abort() is not supported and has been replaced by exit(EXIT_FAILURE)
|
||||
|
||||
.call :
|
||||
ChfAbort(abort_code);
|
||||
.input :
|
||||
const int abort_code, abort_code
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 13-May-1996, creation
|
||||
2.1, 19-May-2000, update:
|
||||
- added multithreading support
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support
|
||||
|
||||
.- */
|
||||
void ChfAbort( /* Abort application */
|
||||
const int abort_code
|
||||
)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if(abort_code != CHF_ABORT_SILENT)
|
||||
{
|
||||
TCHAR abort_msg[CHF_MAX_MESSAGE_LENGTH];
|
||||
HWND active_window;
|
||||
|
||||
/* stderr not available;
|
||||
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(chf_context.state == CHF_UNKNOWN || chf_context.options & CHF_ABORT)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
else
|
||||
/* Else, exit the application anyway, but with the exit code
|
||||
registered by the application. Don't use PostQuitMessage(),
|
||||
because the contract is that ChfAbort() never returns to the caller.
|
||||
*/
|
||||
#ifndef _REENTRANT
|
||||
exit(chf_context.exit_code);
|
||||
#else
|
||||
#error "_REENTRANT not supported yet"
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(abort_code != CHF_ABORT_SILENT)
|
||||
{
|
||||
fputs(CHF_ABORT_HEADER, stderr);
|
||||
|
||||
if(abort_code < 0 || abort_code >= MESSAGE_TABLE_SIZE)
|
||||
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
|
||||
#ifndef _REENTRANT
|
||||
exit(chf_context.exit_code);
|
||||
#else
|
||||
pthread_exit((void *)(chf_context.exit_code));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@- Conditional inclusion of pthread.h (mt support)
|
||||
- Expanded abort message table with mt support messages
|
||||
- ChfAbort() with CHF_ABORT flag clear and mt support enabled now
|
||||
exits invoking thread only
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: chf_abrt.c,v 1.1 1996/05/28 12:53:26 cibrario Beta cibrario $
|
||||
d18 6
|
||||
d31 1
|
||||
a31 1
|
||||
static char rcs_id[] = "$Id: chf_abrt.c,v 1.1 1996/05/28 12:53:26 cibrario Beta cibrario $";
|
||||
d36 1
|
||||
d38 1
|
||||
d41 5
|
||||
d57 1
|
||||
a57 1
|
||||
static const char *message_table[] =
|
||||
d59 11
|
||||
a69 11
|
||||
(const char *)NULL,
|
||||
"Not initialized",
|
||||
"Temporary message buffer overflow",
|
||||
"Invalid action from last chance handler",
|
||||
"Already initialized",
|
||||
"Unwind request while unwinding",
|
||||
"Improperly handled condition",
|
||||
"Fatal condition while unwinding",
|
||||
"Condition stack overflow",
|
||||
"Can't prime a new Chf context",
|
||||
"Pthread interaction failed"
|
||||
d72 1
|
||||
a72 1
|
||||
#define MESSAGE_TABLE_SIZE (sizeof(message_table)/sizeof(const char *))
|
||||
d96 9
|
||||
a104 1
|
||||
failure occours or it's necessary to abort the application.
|
||||
d118 2
|
||||
d126 49
|
||||
d195 1
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, condition generation
|
||||
d17 3
|
||||
a19 1
|
||||
$Log$
|
||||
d21 1
|
||||
d25 1
|
||||
a25 1
|
||||
static char rcs_id[] = "$Id$";
|
||||
d36 4
|
||||
d54 3
|
||||
a56 1
|
||||
"Condition stack overflow"
|
||||
d69 3
|
||||
a71 1
|
||||
immediately aborts the application. The abort is performed either:
|
||||
d74 3
|
||||
a76 1
|
||||
- using exit(chf_context.exit_code) if the flag is clear
|
||||
d95 2
|
||||
d118 1
|
||||
d120 3
|
||||
@
|
253
Chf/RCS/chf_gen.c,v
Normal file
253
Chf/RCS/chf_gen.c,v
Normal file
|
@ -0,0 +1,253 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:1.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.12.10.22; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.53.59; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This module contains the condition generation function of CHF
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: chf_gen.c,v 1.1 1996/05/28 12:53:59 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_gen.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module contains the condition generation function of CHF
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_gen.c,v $
|
||||
Revision 1.1 1996/05/28 12:53:59 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_gen.c,v 1.1 1996/05/28 12:53:59 cibrario Rel cibrario $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfGenerate
|
||||
.kind : C function
|
||||
.creation : 3-May-1996
|
||||
.description :
|
||||
This function generates a condition descriptor for the condition described
|
||||
by 'module_id', 'file_name', 'line_number', 'condition_code' and 'severity',
|
||||
and the partial message associated with it, specialized with the additional
|
||||
arguments '...'; the new condition descriptor is put onto the top of the
|
||||
condition stack.
|
||||
|
||||
If the condition stack is full, this function generates the condition
|
||||
CHF_F_COND_STACK_FULL and immediately invokes ChfSignal() for the current
|
||||
condition stack.
|
||||
|
||||
NOTE: This function calls the CHF function 'ChfAbort()' to
|
||||
abort the application if either:
|
||||
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
|
||||
- there is an overflow in the internal buffer used during the
|
||||
generation of the partial message associated with the condition
|
||||
(abort code CHF_ABORT_MSG_OVF)
|
||||
- there was an attempt to generate a condition while the CHF condition
|
||||
CHF_F_COND_STACK_FULL (condition stack full) was being signalled
|
||||
(abort code CHF_ABORT_COND_STACK_OVF)
|
||||
|
||||
|
||||
.call :
|
||||
ChfGenerate(module_id, file_name, line_number,
|
||||
condition_code, severity, ...);
|
||||
.input :
|
||||
const int module_id, module identifier
|
||||
const char *file_name, file name
|
||||
const int line_number, line number
|
||||
const int condition_code, condition code
|
||||
const ChfSeverity severity, severity
|
||||
..., additional arguments
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
(*) CHF_F_COND_STACK_FULL, the condition stack is full
|
||||
.notes :
|
||||
1.1, 3-May-1996, creation
|
||||
|
||||
.- */
|
||||
void ChfGenerate( /* Generate a condition into the stack */
|
||||
const int module_id,
|
||||
const ChfChar *file_name,
|
||||
const int line_number,
|
||||
const int condition_code,
|
||||
const ChfSeverity severity,
|
||||
...
|
||||
)
|
||||
{
|
||||
ChfDescriptor *new_descriptor;
|
||||
va_list aux_arg;
|
||||
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
/* Prepare the additional arguments list */
|
||||
va_start(aux_arg, severity);
|
||||
|
||||
if((new_descriptor = chf_context.condition_sp) -
|
||||
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,
|
||||
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;
|
||||
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,
|
||||
ChfGetMessage(CHF_MODULE_ID, CHF_F_COND_STACK_FULL,
|
||||
ChfText("Condition stack is full")), CHF_MAX_MESSAGE_LENGTH-1);
|
||||
new_descriptor->message[CHF_MAX_MESSAGE_LENGTH-1] = '\0';
|
||||
|
||||
new_descriptor->next = CHF_NULL_DESCRIPTOR;
|
||||
chf_context.condition_sp++;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else
|
||||
ChfAbort(CHF_ABORT_COND_STACK_OVF);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ChfChar def_message[CHF_DEF_MESSAGE_LENGTH];
|
||||
ChfChar tmp_message[CHF_TMP_MESSAGE_LENGTH];
|
||||
|
||||
new_descriptor->module_id = module_id;
|
||||
new_descriptor->condition_code = condition_code;
|
||||
new_descriptor->severity = severity;
|
||||
new_descriptor->line_number = line_number;
|
||||
new_descriptor->file_name = file_name;
|
||||
|
||||
/* Generate the default message */
|
||||
ChfSprintf(def_message, CHF_DEF_PARTIAL_MSG_FMT, condition_code);
|
||||
|
||||
/* Generate the partial message associated with the condition using a
|
||||
temporary area
|
||||
*/
|
||||
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 */
|
||||
ChfStrncpy(new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH-1);
|
||||
new_descriptor->message[CHF_MAX_MESSAGE_LENGTH-1] = '\0';
|
||||
|
||||
/* Link the new descriptor with the current descriptor list, if it
|
||||
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++;
|
||||
}
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, condition generation
|
||||
d17 3
|
||||
a19 1
|
||||
$Log$
|
||||
d21 1
|
||||
d25 1
|
||||
a25 1
|
||||
static char rcs_id[] = "$Id$";
|
||||
d30 1
|
||||
d32 1
|
||||
d37 5
|
||||
d93 1
|
||||
a93 1
|
||||
const char *file_name,
|
||||
d126 1
|
||||
a126 1
|
||||
strncpy(new_descriptor->message,
|
||||
d128 1
|
||||
a128 1
|
||||
"Condition stack is full"), CHF_MAX_MESSAGE_LENGTH-1);
|
||||
d143 2
|
||||
a144 2
|
||||
char def_message[CHF_DEF_MESSAGE_LENGTH];
|
||||
char tmp_message[CHF_TMP_MESSAGE_LENGTH];
|
||||
d153 1
|
||||
a153 1
|
||||
sprintf(def_message, CHF_DEF_PARTIAL_MSG_FMT, condition_code);
|
||||
d159 1
|
||||
a159 1
|
||||
vsprintf(tmp_message,
|
||||
d165 1
|
||||
a165 1
|
||||
strncpy(new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH-1);
|
||||
@
|
407
Chf/RCS/chf_hdlr.c,v
Normal file
407
Chf/RCS/chf_hdlr.c,v
Normal file
|
@ -0,0 +1,407 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.12.12.46; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.26.14.45.04; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.6;
|
||||
|
||||
1.6
|
||||
date 97.01.15.13.44.39; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.54.28; author cibrario; state Beta;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This module implements the CHF functions ChfPushHandler() and
|
||||
ChfPopHandler()
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: chf_hdlr.c,v 2.1 2000/05/26 14:45:04 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_hdlr.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF functions ChfPushHandler() and
|
||||
ChfPopHandler()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_hdlr.c,v $
|
||||
Revision 2.1 2000/05/26 14:45:04 cibrario
|
||||
- Implemented StructuredHelper(), the structured condition handling
|
||||
helper handler
|
||||
- Updated ChfPushHandler() to push the structured condition handling
|
||||
helper when new_handler is CHF_NULL_HANDLER
|
||||
- unwind_context is now a sigjmp_buf, passed as argument directly,
|
||||
that is, without additional address operators
|
||||
- improved documentation of ChfPopHandler()
|
||||
|
||||
Revision 1.6 1997/01/15 13:44:39 cibrario
|
||||
The function ChfPushHandler() has the new argument 'handler_context'.
|
||||
|
||||
Revision 1.1 1996/05/28 12:54:28 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_hdlr.c,v 2.1 2000/05/26 14:45:04 cibrario Rel cibrario $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : StructuredHelper
|
||||
.kind : C function
|
||||
.creation : 19-May-2000
|
||||
.description :
|
||||
This function is the structured condition handling helper of CHF.
|
||||
It's automatically pushed into the condition handler stack by
|
||||
ChfPushHandler() when its 'new_handler' argument is CHF_NULL_HANDLER,
|
||||
and performs the following functions:
|
||||
|
||||
- if called during an ordinary signalling operation with a
|
||||
CHF_FATAL condition, it requests the action CHF_UNWIND_KEEP
|
||||
|
||||
- if called when Chf is in any other state, or with a
|
||||
severity less than CHF_FATAL, it requests the action CHF_RESIGNAL
|
||||
|
||||
The structured condition handling helper currently makes no use of
|
||||
handler_context.
|
||||
|
||||
.call :
|
||||
action = StructuredHelper(desc, state, context);
|
||||
.input :
|
||||
const ChfDescriptor *desc, condition descriptor
|
||||
const ChfState state, current CHF state
|
||||
.output :
|
||||
ChfAction action, action requested by the handler
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
2.1, 19-May-2000, creation
|
||||
|
||||
.- */
|
||||
static ChfAction StructuredHelper(
|
||||
const ChfDescriptor *desc,
|
||||
const ChfState state,
|
||||
ChfPointer handler_context
|
||||
)
|
||||
{
|
||||
ChfAction action;
|
||||
const ChfDescriptor *d;
|
||||
|
||||
return((state == CHF_SIGNALING && ChfGetSeverity(desc) == CHF_FATAL)
|
||||
? CHF_UNWIND_KEEP : CHF_RESIGNAL);
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfPushHandler
|
||||
.kind : C function
|
||||
.creation : 13-May-1996
|
||||
.description :
|
||||
This function pushes the new condition handler 'new_handler' with its
|
||||
associated longjmp context pointed by 'unwind_context' into the handler
|
||||
stack and returns CHF_S_OK to the caller. If 'new_handler' is
|
||||
CHF_NULL_HANDLER, the special structured condition handling helper
|
||||
'StructuredHelper()' is pushed instead.
|
||||
|
||||
Moreover, this function saves a copy of the pointer 'handler_context'; it
|
||||
will be passed to 'new_handler' upon each subsequent activation, and
|
||||
therefore can be used as a private handler context pointer. The user must
|
||||
assure that the information pointed by 'handler_context', if any, will
|
||||
remain valid until 'new_handler' is popped from the condition stack.
|
||||
'handler_context' may be set to the special (null) value CHF_NULL_POINTER to
|
||||
indicate that the handler hasn't any private context information.
|
||||
|
||||
If, in the future, the handler will request the CHF_UNWIND action, the
|
||||
setjmp() function invocation that established 'unwind_context' will appear
|
||||
to return again.
|
||||
|
||||
'unwind_context' can be the reserved (null) pointer CHF_NULL_CONTEXT; in
|
||||
this case, if the handler will request the CHF_UNWIND_ACTION, the
|
||||
application will be silently terminated calling ChfAbort() with abort code
|
||||
CHF_ABORT_SILENT.
|
||||
|
||||
If some error occours during the execution, the function will generate
|
||||
and immediately signal one of the conditions listed below and marked with
|
||||
(*). The function will never return dorectly to the caller, since all
|
||||
conditions are CHF_FATAL.
|
||||
|
||||
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
|
||||
the CHF subsystem has not been initialized.
|
||||
|
||||
.call :
|
||||
ChfPushHandler(new_handler, unwind_context);
|
||||
.input :
|
||||
ChfHandler new_handler, new condition handler
|
||||
void *unwind_context, handler unwind context pointer
|
||||
ChfPointer handler_context, private handler context pointer
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
(*) CHF_F_BAD_STATE, bad CHF state for requested operation
|
||||
(*) CHF_F_HDLR_STACK_FULL, the handler stack is full
|
||||
.notes :
|
||||
1.1, 13-May-1996, creation
|
||||
1.6, 15-Jan-1997, update:
|
||||
- added the argument 'handler_context'
|
||||
- improved documentation
|
||||
2.1, 19-May-2000, update:
|
||||
- now using sigjmp_buf as unwind_context
|
||||
- added StructuredHelper handling
|
||||
|
||||
.- */
|
||||
void ChfPushHandler( /* Push a new handler into the stack */
|
||||
ChfHandler new_handler,
|
||||
void *unwind_context,
|
||||
ChfPointer handler_context
|
||||
)
|
||||
{
|
||||
/* 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_IDLE)
|
||||
{
|
||||
ChfCondition CHF_F_BAD_STATE, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* Check if the handler stack is full */
|
||||
else if(chf_context.handler_sp - chf_context.handler_stack >=
|
||||
chf_context.handler_stack_size)
|
||||
{
|
||||
ChfCondition CHF_F_HDLR_STACK_FULL, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
chf_context.handler_sp->unwind_context = unwind_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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfPopHandler
|
||||
.kind : C function
|
||||
.creation : 13-May-1996
|
||||
.description :
|
||||
This function pops the topmost condition handler from the handler stack and
|
||||
returns to the caller.
|
||||
|
||||
If some error occours during the execution, the function will generate
|
||||
and immediately signal one of the conditions listed below and marked with
|
||||
(*). The function will never return directly to the caller, since all
|
||||
conditions are CHF_FATAL.
|
||||
|
||||
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
|
||||
the CHF subsystem has not been initialized.
|
||||
|
||||
.call :
|
||||
ChfPopHandler();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
CHF_F_BAD_STATE, bad CHF state for requested operation
|
||||
CHF_F_HDLR_STACK_FULL, the handler stack is full
|
||||
.notes :
|
||||
1.1, 13-May-1996, creation
|
||||
1.6, 15-Jan-1997, update:
|
||||
- improved documentation
|
||||
2.1, 19-May-2000, update:
|
||||
- improved documentation
|
||||
|
||||
.- */
|
||||
void ChfPopHandler( /* Pop a handler */
|
||||
void
|
||||
)
|
||||
{
|
||||
/* 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_IDLE)
|
||||
{
|
||||
ChfCondition CHF_F_BAD_STATE, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* Check if the handler stack is empty */
|
||||
else if(chf_context.handler_sp == chf_context.handler_stack)
|
||||
{
|
||||
ChfCondition CHF_F_HDLR_STACK_EMPTY, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* Discard the topmost condition handler */
|
||||
else
|
||||
--chf_context.handler_sp;
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@- Implemented StructuredHelper(), the structured condition handling
|
||||
helper handler
|
||||
- Updated ChfPushHandler() to push the structured condition handling
|
||||
helper when new_handler is CHF_NULL_HANDLER
|
||||
- unwind_context is now a sigjmp_buf, passed as argument directly,
|
||||
that is, without additional address operators
|
||||
- improved documentation of ChfPopHandler()
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: chf_hdlr.c,v 1.6 1997/01/15 13:44:39 cibrario Exp cibrario $
|
||||
d19 9
|
||||
d38 1
|
||||
a38 1
|
||||
static char rcs_id[] = "$Id: chf_hdlr.c,v 1.6 1997/01/15 13:44:39 cibrario Exp cibrario $";
|
||||
d43 1
|
||||
d45 1
|
||||
d48 5
|
||||
@
|
||||
|
||||
|
||||
1.6
|
||||
log
|
||||
@The function ChfPushHandler() has the new argument 'handler_context'.
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: chf_hdlr.c,v 1.1 1996/05/28 12:54:28 cibrario Beta $
|
||||
d19 3
|
||||
d29 1
|
||||
a29 1
|
||||
static char rcs_id[] = "$Id: chf_hdlr.c,v 1.1 1996/05/28 12:54:28 cibrario Beta $";
|
||||
d43 47
|
||||
d96 3
|
||||
a98 1
|
||||
stack and returns CHF_S_OK to the caller.
|
||||
d129 1
|
||||
a129 1
|
||||
jmp_buf *unwind_context, handler unwind context pointer
|
||||
d141 3
|
||||
d148 1
|
||||
a148 1
|
||||
jmp_buf *unwind_context,
|
||||
d177 2
|
||||
a178 1
|
||||
chf_context.handler_sp->handler = new_handler;
|
||||
d202 1
|
||||
a202 1
|
||||
ChfPopHandler(new_handler);
|
||||
d204 1
|
||||
a204 1
|
||||
const int abort_code, abort_code
|
||||
d214 2
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, condition generation
|
||||
d18 3
|
||||
a20 1
|
||||
$Log$
|
||||
d22 1
|
||||
d26 1
|
||||
a26 1
|
||||
static char rcs_id[] = "$Id$";
|
||||
d47 8
|
||||
d74 1
|
||||
a74 1
|
||||
cc = ChfPushHandler(new_handler, unwind_context);
|
||||
d76 3
|
||||
a78 3
|
||||
ChfHandler new_handler,
|
||||
jmp_buf *unwind_context
|
||||
const int abort_code, abort_code
|
||||
d80 1
|
||||
a80 1
|
||||
int cc, condition code
|
||||
d86 3
|
||||
d93 2
|
||||
a94 1
|
||||
jmp_buf *unwind_context
|
||||
d121 1
|
||||
d150 1
|
||||
a150 1
|
||||
int cc, condition code
|
||||
a153 1
|
||||
CHF_I_UNWIND_DONE, unwind succesfully completed
|
||||
d156 2
|
||||
@
|
1074
Chf/RCS/chf_init.c,v
Normal file
1074
Chf/RCS/chf_init.c,v
Normal file
File diff suppressed because it is too large
Load diff
292
Chf/RCS/chf_msgc.c,v
Normal file
292
Chf/RCS/chf_msgc.c,v
Normal file
|
@ -0,0 +1,292 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:1.3;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.14.06.47; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.3;
|
||||
|
||||
1.3
|
||||
date 96.06.21.14.19.22; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.55.15; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This module contains the CHF initialization function ChfMsgcatInit()
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: chf_msgc.c,v 1.3 1996/06/21 14:19:22 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_msgc.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 17-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module contains the CHF initialization function ChfMsgcatInit()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_msgc.c,v $
|
||||
Revision 1.3 1996/06/21 14:19:22 cibrario
|
||||
Bug fix: the private context of the message retrieval facility was
|
||||
never freed by ExitMessage()
|
||||
|
||||
Revision 1.1 1996/05/28 12:55:15 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_msgc.c,v 1.3 1996/06/21 14:19:22 cibrario Rel cibrario $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <locale.h>
|
||||
#include <nl_types.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global and static variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef struct
|
||||
{
|
||||
nl_catd catalog; /* Message catalog descriptor */
|
||||
}
|
||||
ChfMsgcatContext;
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
static const char *GetMessage(
|
||||
void *private_context,
|
||||
const int module_id,
|
||||
const int condition_code,
|
||||
const char *default_message
|
||||
)
|
||||
{
|
||||
return(catgets(((ChfMsgcatContext *)private_context)->catalog, module_id,
|
||||
condition_code, default_message));
|
||||
}
|
||||
|
||||
static void ExitMessage(
|
||||
void *private_context
|
||||
)
|
||||
{
|
||||
(void)catclose(((ChfMsgcatContext *)private_context)->catalog);
|
||||
free(private_context);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfMsgcatInit
|
||||
.kind : C function
|
||||
.creation : 17-May-1996
|
||||
.description :
|
||||
This function initializes CHF and returns to the caller a condition code;
|
||||
that code will be either CHF_S_OK if the initialization was succesful,
|
||||
or one of the other values listed below.
|
||||
|
||||
It's necessary to invoke succesfully either ChfMsgcatInit() or one of the
|
||||
other CHF initialization routines before using any other CHF function.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
|
||||
if CHF has already been initialized before.
|
||||
|
||||
WIN32:
|
||||
|
||||
- this function is not available due to lack of system support, and
|
||||
always returns CHF_F_NOT_AVAILABLE
|
||||
|
||||
.call :
|
||||
cc = ChfMsgcatInit(app_name, options,
|
||||
msgcat_name,
|
||||
condition_stack_size, handler_stack_size,
|
||||
exit_code);
|
||||
.input :
|
||||
const char *app_name, Application's name
|
||||
const ChfOptions options, Options
|
||||
const char *msgcat_name, Name of the message catalog
|
||||
const int condition_stack_size, Size of the condition stack
|
||||
const int handler_stack_size, Size of the handler stack
|
||||
const int exit_code, Abnormal exit code
|
||||
.output :
|
||||
int cc, condition code
|
||||
.status_codes :
|
||||
CHF_F_SETLOCALE, setlocale() failed
|
||||
CHF_F_CATOPEN, catopen() failed
|
||||
CHF_F_MALLOC, FATAL, memory allocation failed
|
||||
CHF_F_NOT_AVAILABLE, FATAL, function not available
|
||||
.notes :
|
||||
1.1, 17-May-1996, creation
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support
|
||||
|
||||
.- */
|
||||
int ChfMsgcatInit( /* Initialization with msgcat subsystem */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfChar *msgcat_name, /* Name of the message catalog */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
/* This function always fails in _WIN32, because message catalogs
|
||||
are not supported.
|
||||
*/
|
||||
return CHF_F_NOT_AVAILABLE;
|
||||
|
||||
#else
|
||||
ChfMsgcatContext *private_context;
|
||||
int cc;
|
||||
|
||||
if((private_context =
|
||||
(ChfMsgcatContext *)malloc(sizeof(ChfMsgcatContext))) ==
|
||||
(ChfMsgcatContext *)NULL)
|
||||
cc = CHF_F_MALLOC;
|
||||
|
||||
else if(setlocale(LC_ALL, "") == (char *)NULL)
|
||||
{
|
||||
free(private_context);
|
||||
cc = CHF_F_SETLOCALE;
|
||||
}
|
||||
|
||||
else if((private_context->catalog = catopen(msgcat_name, 0)) ==
|
||||
(nl_catd)(-1))
|
||||
{
|
||||
free(private_context);
|
||||
cc = CHF_F_CATOPEN;
|
||||
}
|
||||
|
||||
else if((cc = ChfInit(app_name, options, (void *)private_context,
|
||||
GetMessage, ExitMessage, condition_stack_size, handler_stack_size,
|
||||
exit_code)) != CHF_S_OK)
|
||||
{
|
||||
(void)catclose(private_context->catalog);
|
||||
free(private_context);
|
||||
}
|
||||
|
||||
else
|
||||
cc = CHF_S_OK;
|
||||
|
||||
return cc;
|
||||
|
||||
#endif
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
1.3
|
||||
log
|
||||
@Bug fix: the private context of the message retrieval facility was
|
||||
never freed by ExitMessage()
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: chf_msgc.c,v 1.1 1996/05/28 12:55:15 cibrario Exp cibrario $
|
||||
d18 4
|
||||
d29 1
|
||||
a29 1
|
||||
static char rcs_id[] = "$Id: chf_msgc.c,v 1.1 1996/05/28 12:55:15 cibrario Exp cibrario $";
|
||||
d34 1
|
||||
d36 1
|
||||
d39 1
|
||||
d42 1
|
||||
d44 5
|
||||
d61 1
|
||||
d67 1
|
||||
d75 1
|
||||
d94 1
|
||||
d117 5
|
||||
d140 1
|
||||
d143 2
|
||||
d148 1
|
||||
a148 1
|
||||
const char *app_name, /* Application's name */
|
||||
d150 1
|
||||
a150 1
|
||||
const char *msgcat_name, /* Name of the message catalog */
|
||||
d156 7
|
||||
d196 2
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, condition generation
|
||||
d17 3
|
||||
a19 1
|
||||
$Log$
|
||||
d21 1
|
||||
d25 1
|
||||
a25 1
|
||||
static char rcs_id[] = "$Id$";
|
||||
d76 1
|
||||
@
|
546
Chf/RCS/chf_sig.c,v
Normal file
546
Chf/RCS/chf_sig.c,v
Normal file
|
@ -0,0 +1,546 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.14.07.42; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.26.14.31.28; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.6;
|
||||
|
||||
1.6
|
||||
date 97.01.15.13.34.45; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.55.51; author cibrario; state Beta;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This module implements the condition signalling function of CHF
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: chf_sig.c,v 2.1 2000/05/26 14:31:28 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_sig.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the condition signalling function of CHF
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_sig.c,v $
|
||||
Revision 2.1 2000/05/26 14:31:28 cibrario
|
||||
- Fixed spelling of CHF_SIGNALLING -> CHF_SIGNALING
|
||||
- Replaced longjmp() with siglongjmp()
|
||||
- New ChfAction code CHF_UNWIND_KEEP: ChfSignal() unwinds the
|
||||
execution stack, but keeps the topmost condition group on the
|
||||
condition stack
|
||||
|
||||
Revision 1.6 1997/01/15 13:34:45 cibrario
|
||||
Fixed a wrong adjustment of the condition handler stack pointer after
|
||||
an unwind operation.
|
||||
Updated the condition handler calls in order to pass to the handlers the
|
||||
private handler context pointer.
|
||||
|
||||
Revision 1.1 1996/05/28 12:55:51 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_sig.c,v 2.1 2000/05/26 14:31:28 cibrario Rel cibrario $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfSignal
|
||||
.kind : C function
|
||||
.creation : 10-May-1996
|
||||
.description :
|
||||
This function signals the topmost condition group currently in the
|
||||
condition stack, and performs the actions requested by the condition
|
||||
handlers.
|
||||
|
||||
NOTE: This function uses the CHF function 'ChfAbort()' to
|
||||
abort the application if either
|
||||
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
|
||||
- the last handler on the handler stack has returned an invalid action
|
||||
code (abort code CHF_ABORT_INVALID_ACTION)
|
||||
- one of the handlers has requested the CHF_UNWIND action while
|
||||
CHF was already unwinding (abort code CHF_ABORT_ALREADY_UNWINDING)
|
||||
- a CHF_FATAL condition was signalled while CHF was unwinding
|
||||
(abort code CHF_ABORT_FATAL_UNWINDING)
|
||||
- all the handlers refused to handle a condition (abort code
|
||||
CHF_ABORT_IMPROPERLY_HANDLED)
|
||||
|
||||
.call :
|
||||
ChfSignal();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
(*) CHF_F_COND_STACK_FULL, the condition stack is full
|
||||
(*) CHF_F_INVALID_ACTION, invalid handler action (%d)
|
||||
.notes :
|
||||
1.1, 10-May-1996, creation
|
||||
1.6, 15-Jan-1997, update & bug fix:
|
||||
- fixed a wrong adjustment of the condition handler stack pointer after
|
||||
an unwind operation.
|
||||
- updated the condition handler calls in order to pass to the handlers the
|
||||
private handler context pointer, too.
|
||||
2.1, 19-May-2000, update:
|
||||
- added support for structured condition handling
|
||||
|
||||
.- */
|
||||
void ChfSignal(
|
||||
void
|
||||
)
|
||||
{
|
||||
ChfState saved_state;
|
||||
ChfDescriptor *saved_condition_base;
|
||||
ChfDescriptor *current_condition;
|
||||
ChfHandlerDescriptor *saved_handler_sp;
|
||||
ChfHandlerDescriptor *handler_up;
|
||||
ChfHandlerDescriptor *unwind_handler;
|
||||
ChfAction handler_result;
|
||||
|
||||
/* 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
|
||||
CHF_UNWINDING change to CHF_SIGNAL_UNWINDING, otherwise remain in the
|
||||
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;
|
||||
saved_condition_base = chf_context.condition_base;
|
||||
chf_context.condition_base = chf_context.condition_sp;
|
||||
|
||||
/* Save the current condition handler pointer */
|
||||
saved_handler_sp = chf_context.handler_sp;
|
||||
|
||||
/* Call the condition handlers; the loop will exit either:
|
||||
- when the handler stack is empty, or
|
||||
- when the current handler returns either CHF_CONTINUE or CHF_UNWIND
|
||||
*/
|
||||
handler_result = CHF_RESIGNAL;
|
||||
while(handler_result == CHF_RESIGNAL &&
|
||||
chf_context.handler_sp > chf_context.handler_stack)
|
||||
{
|
||||
chf_context.handler_sp--;
|
||||
|
||||
/* The current condition handler, described by chf_context.handler_sp,
|
||||
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 signal 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 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().
|
||||
|
||||
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 */
|
||||
chf_context.state = saved_state;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfDiscard
|
||||
.kind : C function
|
||||
.creation : 17-May-1996
|
||||
.description :
|
||||
This function discards the topmost condition group currently in the
|
||||
condition stack, without signalling it. The function does nothing if
|
||||
the condition stack is empty.
|
||||
|
||||
NOTE: This function uses the CHF function 'ChfAbort()' to
|
||||
abort the application if either
|
||||
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
|
||||
|
||||
.call :
|
||||
ChfDiscard();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 17-May-1996, creation
|
||||
|
||||
.- */
|
||||
void ChfDiscard( /* Discard the current conditions */
|
||||
void
|
||||
)
|
||||
{
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
/* Reset the current condition stack pointer to the current condition
|
||||
stack base pointer
|
||||
*/
|
||||
chf_context.condition_sp = chf_context.condition_base;
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@- Fixed spelling of CHF_SIGNALLING -> CHF_SIGNALING
|
||||
- Replaced longjmp() with siglongjmp()
|
||||
- New ChfAction code CHF_UNWIND_KEEP: ChfSignal() unwinds the
|
||||
execution stack, but keeps the topmost condition group on the
|
||||
condition stack
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: chf_sig.c,v 1.6 1997/01/15 13:34:45 cibrario Exp cibrario $
|
||||
d18 7
|
||||
d38 1
|
||||
a38 1
|
||||
static char rcs_id[] = "$Id: chf_sig.c,v 1.6 1997/01/15 13:34:45 cibrario Exp cibrario $";
|
||||
d43 1
|
||||
d45 1
|
||||
d48 5
|
||||
d320 1
|
||||
a320 1
|
||||
siglongjmp(unwind_handler->unwind_context, 1);
|
||||
@
|
||||
|
||||
|
||||
1.6
|
||||
log
|
||||
@Fixed a wrong adjustment of the condition handler stack pointer after
|
||||
an unwind operation.
|
||||
Updated the condition handler calls in order to pass to the handlers the
|
||||
private handler context pointer.
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, condition generation
|
||||
d17 7
|
||||
a23 1
|
||||
$Log$
|
||||
d31 1
|
||||
a31 1
|
||||
static char rcs_id[] = "$Id$";
|
||||
d81 2
|
||||
d98 1
|
||||
a98 1
|
||||
state. If CHF was CHF_IDLE change state to CHF_SIGNALLING, else if CHF was
|
||||
d100 1
|
||||
a100 1
|
||||
previous state (that must be CHF_SIGNALLING)
|
||||
d106 1
|
||||
a106 1
|
||||
chf_context.state = CHF_SIGNALLING;
|
||||
d153 1
|
||||
a153 1
|
||||
/* When the CHF state is CHF_SIGNALLING, any condition group generated
|
||||
d167 1
|
||||
a167 1
|
||||
if(chf_context.state == CHF_SIGNALLING)
|
||||
d214 1
|
||||
d236 1
|
||||
d259 1
|
||||
a259 1
|
||||
handler_result = handler_up->handler(
|
||||
d278 18
|
||||
a295 5
|
||||
/* Restore the condition stack pointers, discarding all condition
|
||||
groups.
|
||||
*/
|
||||
chf_context.condition_base = chf_context.condition_sp =
|
||||
chf_context.condition_stack;
|
||||
d306 1
|
||||
a306 1
|
||||
longjmp(*(unwind_handler->unwind_context), 1);
|
||||
d315 1
|
||||
a315 1
|
||||
(chf_context.state == CHF_SIGNALLING) ?
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d18 2
|
||||
d21 1
|
||||
d70 5
|
||||
d142 2
|
||||
a143 1
|
||||
current_condition, chf_context.state);
|
||||
d250 2
|
||||
a251 1
|
||||
current_condition, chf_context.state);
|
||||
d262 3
|
||||
a264 2
|
||||
handler that requested the unwind and must be adjusted to
|
||||
point to the handler that immediately precedes it.
|
||||
d266 1
|
||||
a266 1
|
||||
unwind_handler = chf_context.handler_sp--;
|
||||
@
|
295
Chf/RCS/chf_st.c,v
Normal file
295
Chf/RCS/chf_st.c,v
Normal file
|
@ -0,0 +1,295 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:1.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.14.08.45; author cibrario; state Exp;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 96.05.28.12.56.14; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This module implements the CHF initialization function ChfStaticInit()
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: chf_st.c,v 1.1 1996/05/28 12:56:14 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_st.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 24-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF initialization function ChfStaticInit()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_st.c,v $
|
||||
Revision 1.1 1996/05/28 12:56:14 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_st.c,v 1.1 1996/05/28 12:56:14 cibrario Rel cibrario $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global and static variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ChfTable *table;
|
||||
size_t size;
|
||||
}
|
||||
ChfStaticContext;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Win32 does not have bsearch();
|
||||
provide a simple one from glibc here.
|
||||
*/
|
||||
static void *bsearch(
|
||||
const void *key,
|
||||
const void *base,
|
||||
size_t nmemb,
|
||||
size_t size,
|
||||
int (*compar)(const void *, const void *)
|
||||
)
|
||||
{
|
||||
size_t l, u, idx;
|
||||
const void *p;
|
||||
int comparison;
|
||||
|
||||
l = 0;
|
||||
u = nmemb;
|
||||
while (l < u)
|
||||
{
|
||||
idx = (l + u) / 2;
|
||||
p = (void *) (((const char *) base) + (idx * size));
|
||||
comparison = (*compar) (key, p);
|
||||
if (comparison < 0)
|
||||
u = idx;
|
||||
else if (comparison > 0)
|
||||
l = idx + 1;
|
||||
else
|
||||
return (void *) p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define GT 1
|
||||
#define LT -1
|
||||
#define EQ 0
|
||||
|
||||
static int Search(
|
||||
const void *l,
|
||||
const void *r
|
||||
)
|
||||
{
|
||||
if(((ChfTable *)l)->module > ((ChfTable *)r)->module)
|
||||
return(GT);
|
||||
|
||||
else if(((ChfTable *)l)->module < ((ChfTable *)r)->module)
|
||||
return(LT);
|
||||
|
||||
else if(((ChfTable *)l)->code > ((ChfTable *)r)->code)
|
||||
return(GT);
|
||||
|
||||
else if(((ChfTable *)l)->code < ((ChfTable *)r)->code)
|
||||
return(LT);
|
||||
|
||||
return(EQ);
|
||||
}
|
||||
|
||||
static const ChfChar *StGetMessage(
|
||||
void *private_context,
|
||||
const int module_id,
|
||||
const int condition_code,
|
||||
const ChfChar *default_message
|
||||
)
|
||||
{
|
||||
ChfTable key;
|
||||
ChfTable *res;
|
||||
|
||||
key.module = module_id;
|
||||
key.code = condition_code;
|
||||
|
||||
if((res = bsearch(&key, ((ChfStaticContext *)private_context)->table,
|
||||
((ChfStaticContext *)private_context)->size, sizeof(ChfTable), Search)) ==
|
||||
(void *)NULL)
|
||||
return(default_message);
|
||||
|
||||
return(((ChfTable *)res)->msg_template);
|
||||
}
|
||||
|
||||
static void ExitMessage(
|
||||
void *private_context
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfStaticInit
|
||||
.kind : C function
|
||||
.creation : 24-May-1996
|
||||
.description :
|
||||
This function initializes CHF and returns to the caller a condition code;
|
||||
that code will be either CHF_S_OK if the initialization was succesful,
|
||||
or one of the other values listed below.
|
||||
|
||||
It's necessary to invoke succesfully either ChfStaticInit() or one of the
|
||||
other CHF initialization routines before using any other CHF function.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
|
||||
if CHF has already been initialized before.
|
||||
|
||||
.call :
|
||||
cc = ChfStaticInit(app_name, options,
|
||||
table, table_size,
|
||||
condition_stack_size, handler_stack_size,
|
||||
exit_code);
|
||||
.input :
|
||||
const char *app_name, Application's name
|
||||
const ChfOptions options, Options
|
||||
const ChfTable *table, pointer to the static message table
|
||||
const size_t table_size, size of the table (# of entries)
|
||||
const int condition_stack_size, Size of the condition stack
|
||||
const int handler_stack_size, Size of the handler stack
|
||||
const int exit_code, Abnormal exit code
|
||||
.output :
|
||||
int cc, condition code
|
||||
.status_codes :
|
||||
CHF_F_MALLOC, FATAL, memory allocation failed
|
||||
.notes :
|
||||
1.1, 27-May-1996, creation
|
||||
|
||||
.- */
|
||||
int ChfStaticInit( /* Initialization with static message tables */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfTable *table, /* Static message table */
|
||||
const size_t table_size, /* Size of the message table */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
)
|
||||
{
|
||||
ChfStaticContext *private_context;
|
||||
int cc;
|
||||
|
||||
if((private_context =
|
||||
(ChfStaticContext *)malloc(sizeof(ChfStaticContext))) ==
|
||||
(ChfStaticContext *)NULL)
|
||||
cc = CHF_F_MALLOC;
|
||||
|
||||
else if((cc = ChfInit(app_name, options, (void *)private_context,
|
||||
StGetMessage, ExitMessage, condition_stack_size, handler_stack_size,
|
||||
exit_code)) != CHF_S_OK)
|
||||
free(private_context);
|
||||
|
||||
else
|
||||
{
|
||||
private_context->table = table;
|
||||
private_context->size = table_size;
|
||||
cc = CHF_S_OK;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Initial revision
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$, condition generation
|
||||
d17 3
|
||||
a19 1
|
||||
$Log$
|
||||
d21 1
|
||||
d25 1
|
||||
a25 1
|
||||
static char rcs_id[] = "$Id$";
|
||||
d30 1
|
||||
d32 1
|
||||
d36 5
|
||||
d65 35
|
||||
d124 1
|
||||
a124 1
|
||||
static const char *GetMessage(
|
||||
d128 1
|
||||
a128 1
|
||||
const char *default_message
|
||||
d142 1
|
||||
a142 1
|
||||
return(((ChfTable *)res)->template);
|
||||
d194 1
|
||||
a194 1
|
||||
const char *app_name, /* Application's name */
|
||||
d212 1
|
||||
a212 1
|
||||
GetMessage, ExitMessage, condition_stack_size, handler_stack_size,
|
||||
@
|
192
Chf/RCS/chf_top.c,v
Normal file
192
Chf/RCS/chf_top.c,v
Normal file
|
@ -0,0 +1,192 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.14.09.21; author cibrario; state Exp;
|
||||
branches;
|
||||
next 2.1;
|
||||
|
||||
2.1
|
||||
date 2000.05.26.14.23.33; author cibrario; state Rel;
|
||||
branches;
|
||||
next 1.2;
|
||||
|
||||
1.2
|
||||
date 96.06.11.12.47.17; author cibrario; state Beta;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@This module implements the CHF function ChfGetTopCondition()
|
||||
@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@Added partial Win32 support (Windows CE only).
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id: chf_top.c,v 2.1 2000/05/26 14:23:33 cibrario Rel cibrario $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_top.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 5-Jun-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF function ChfGetTopCondition()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_top.c,v $
|
||||
Revision 2.1 2000/05/26 14:23:33 cibrario
|
||||
ChfGetTopCondition() used to return a pointer to the wrong condition
|
||||
descriptor; fixed.
|
||||
|
||||
Revision 1.2 1996/06/11 12:47:17 cibrario
|
||||
file creation
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_top.c,v 2.1 2000/05/26 14:23:33 cibrario Rel cibrario $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfGetTopCondition
|
||||
.kind : C function
|
||||
.creation : 5-Jun-1996
|
||||
.description :
|
||||
This function returns to the caller a pointer to the top condition of
|
||||
the current condition group. It generates and immediately signals the
|
||||
condition CHF_F_BAD_STATE if the current condition group is empty.
|
||||
|
||||
|
||||
NOTE: During condition signalling, CHF creates a new, empty, condition group
|
||||
immediately before starting the invocation sequence of the condition
|
||||
handlers, as described in the documentation. Therefore
|
||||
ChfGetTopCondition(), if called from a condition handler, will return
|
||||
a pointer to the top condition generated during the handling ONLY, and
|
||||
NOT to the top condition of the condition group being signalled. The
|
||||
latter pointer is directly available, as an argument, to the condition
|
||||
handlers.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
|
||||
if CHF hasn't been correctly initialized.
|
||||
|
||||
NOTE: The returned pointer is no longer valid when any other CHF function
|
||||
is called after ChfGetTopCondition().
|
||||
|
||||
.call :
|
||||
d = ChfGetTopCondition();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
const ChfDescriptor *d, condition descriptor
|
||||
.status_codes :
|
||||
|
||||
.notes :
|
||||
1.2, 17-May-1996, creation
|
||||
2.1, 24-May-2000, bug fix:
|
||||
- condition stack referenced incorrectly
|
||||
|
||||
.- */
|
||||
const ChfDescriptor *ChfGetTopCondition( /* Retrieve top condition */
|
||||
void
|
||||
)
|
||||
{
|
||||
ChfDescriptor *d;
|
||||
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
if((d = chf_context.condition_sp) == chf_context.condition_base)
|
||||
{
|
||||
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* The top element of the condition group is the element immediately
|
||||
below the stack pointer.
|
||||
*/
|
||||
return d-1;
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@ChfGetTopCondition() used to return a pointer to the wrong condition
|
||||
descriptor; fixed.
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id: chf_top.c,v 1.2 1996/06/11 12:47:17 cibrario Beta cibrario $
|
||||
d18 4
|
||||
d29 1
|
||||
a29 1
|
||||
static char rcs_id[] = "$Id: chf_top.c,v 1.2 1996/06/11 12:47:17 cibrario Beta cibrario $";
|
||||
d34 1
|
||||
d36 1
|
||||
d40 5
|
||||
@
|
||||
|
||||
|
||||
1.2
|
||||
log
|
||||
@file creation
|
||||
@
|
||||
text
|
||||
@d3 1
|
||||
a3 1
|
||||
.identifier : $Id$
|
||||
d5 1
|
||||
a5 1
|
||||
.title : $RCSfile$
|
||||
d17 3
|
||||
a19 1
|
||||
$Log$
|
||||
d21 1
|
||||
d25 1
|
||||
a25 1
|
||||
static char rcs_id[] = "$Id$";
|
||||
d78 2
|
||||
d97 4
|
||||
a100 1
|
||||
return d;
|
||||
@
|
212
Chf/RCS/chf_win32.c,v
Normal file
212
Chf/RCS/chf_win32.c,v
Normal file
|
@ -0,0 +1,212 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.14.11.58; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* .+
|
||||
|
||||
.identifier : $Id$
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile$, Win32 initialization function
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 19-Jan-2001
|
||||
.keywords : *
|
||||
.description :
|
||||
This module contains the CHF initialization function ChfWin32Init()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log$
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global and static variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef struct
|
||||
{
|
||||
HINSTANCE instance; /* App. instance handle */
|
||||
ChfChar buffer[CHF_MAX_MESSAGE_LENGTH]; /* Temporary buffer */
|
||||
}
|
||||
ChfWin32Context;
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
static const ChfChar *Win32GetMessage(
|
||||
void *private_context,
|
||||
const int module_id,
|
||||
const int condition_code,
|
||||
const ChfChar *default_message
|
||||
)
|
||||
{
|
||||
if(!LoadString(
|
||||
((ChfWin32Context *)private_context)->instance,
|
||||
module_id*1000 + condition_code,
|
||||
((ChfWin32Context *)private_context)->buffer,
|
||||
CHF_MAX_MESSAGE_LENGTH-1))
|
||||
return default_message;
|
||||
|
||||
return ((ChfWin32Context *)private_context)->buffer;
|
||||
}
|
||||
|
||||
static void ExitMessage(
|
||||
void *private_context
|
||||
)
|
||||
{
|
||||
free(private_context);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfWin32Init
|
||||
.kind : C function
|
||||
.creation : 19-Jan-2001
|
||||
.description :
|
||||
This function initializes CHF and returns to the caller a condition code;
|
||||
that code will be either CHF_S_OK if the initialization was succesful,
|
||||
or one of the other values listed below.
|
||||
|
||||
It's necessary to invoke succesfully either ChfWin32Init() or one of the
|
||||
other CHF initialization routines before using any other CHF function.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
|
||||
if CHF has already been initialized before.
|
||||
|
||||
WIN32:
|
||||
|
||||
- This function is available in Win32 only; it will return
|
||||
CHF_F_NOT_AVAILABLE on Unix platforma.
|
||||
|
||||
- message retrieval is done through the LoadString() Win32 function.
|
||||
This function does not support message sets, so the linear message id
|
||||
passed to it is made by module_id*1000 + condition_code. The following
|
||||
limits are in effect:
|
||||
0 <= condition_code <= 999
|
||||
0 <= module_id <= 64
|
||||
|
||||
.call :
|
||||
cc = ChfWin32Init(app_name, options,
|
||||
msgcat_name,
|
||||
condition_stack_size, handler_stack_size,
|
||||
exit_code);
|
||||
.input :
|
||||
const ChfChar *app_name, Application's name
|
||||
const ChfOptions options, Options
|
||||
HINSTANCE instance, App. instance handle
|
||||
const int condition_stack_size, Size of the condition stack
|
||||
const int handler_stack_size, Size of the handler stack
|
||||
const int exit_code, Abnormal exit code
|
||||
.output :
|
||||
int cc, condition code
|
||||
.status_codes :
|
||||
CHF_F_MALLOC, FATAL, memory allocation failed
|
||||
CHF_F_NOT_AVAILABLE, FATAL, function not available
|
||||
.notes :
|
||||
2.2, 19-Jan-2001, creation
|
||||
|
||||
.- */
|
||||
int ChfWin32Init( /* Initialization within _WIN32 */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
#ifndef _WIN32
|
||||
void *instance, /* Fake arguments */
|
||||
#else
|
||||
HINSTANCE instance, /* App. instance handle */
|
||||
#endif
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
/* This function is available only in Win32 */
|
||||
return CHF_F_NOT_AVAILABLE;
|
||||
|
||||
#else
|
||||
ChfWin32Context *private_context;
|
||||
int cc;
|
||||
|
||||
if((private_context =
|
||||
(ChfWin32Context *)malloc(sizeof(ChfWin32Context))) ==
|
||||
(ChfWin32Context *)NULL)
|
||||
cc = CHF_F_MALLOC;
|
||||
|
||||
else if((cc = ChfInit(app_name, options, (void *)private_context,
|
||||
Win32GetMessage, ExitMessage, condition_stack_size, handler_stack_size,
|
||||
exit_code)) != CHF_S_OK)
|
||||
{
|
||||
free(private_context);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Save Win32 specific context items into private Chf context */
|
||||
private_context->instance = instance;
|
||||
|
||||
cc = CHF_S_OK;
|
||||
}
|
||||
|
||||
return cc;
|
||||
|
||||
#endif
|
||||
}
|
||||
@
|
509
Chf/RCS/libChf.vcp,v
Executable file
509
Chf/RCS/libChf.vcp,v
Executable file
|
@ -0,0 +1,509 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2;
|
||||
locks; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.14.12.47; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@# Microsoft eMbedded Visual Tools Project File - Name="libChf" - Package Owner=<4>
|
||||
# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (WCE x86em) Static Library" 0x7f04
|
||||
# TARGTYPE "Win32 (WCE ARM) Static Library" 0x8504
|
||||
|
||||
CFG=libChf - Win32 (WCE ARM) Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "libChf.vcn".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "libChf.vcn" CFG="libChf - Win32 (WCE ARM) Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "libChf - Win32 (WCE ARM) Release" (based on "Win32 (WCE ARM) Static Library")
|
||||
!MESSAGE "libChf - Win32 (WCE ARM) Debug" (based on "Win32 (WCE ARM) Static Library")
|
||||
!MESSAGE "libChf - Win32 (WCE x86em) Release" (based on "Win32 (WCE x86em) Static Library")
|
||||
!MESSAGE "libChf - Win32 (WCE x86em) Debug" (based on "Win32 (WCE x86em) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
# PROP ATL_Project 2
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ARMRel"
|
||||
# PROP BASE Intermediate_Dir "ARMRel"
|
||||
# PROP BASE CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "ARMRel"
|
||||
# PROP Intermediate_Dir "ARMRel"
|
||||
# PROP CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=clarm.exe
|
||||
# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "NDEBUG" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /Oxs /M$(CECrtMT) /c
|
||||
# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "NDEBUG" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /Oxs /M$(CECrtMT) /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "ARMDbg"
|
||||
# PROP BASE Intermediate_Dir "ARMDbg"
|
||||
# PROP BASE CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "ARMDbg"
|
||||
# PROP Intermediate_Dir "ARMDbg"
|
||||
# PROP CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=clarm.exe
|
||||
# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /M$(CECrtMTDebug) /c
|
||||
# ADD CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /M$(CECrtMTDebug) /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "X86EMRel"
|
||||
# PROP BASE Intermediate_Dir "X86EMRel"
|
||||
# PROP BASE CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "X86EMRel"
|
||||
# PROP Intermediate_Dir "X86EMRel"
|
||||
# PROP CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_LIB" /YX /Oxs /Gz /c
|
||||
# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_LIB" /YX /Oxs /Gz /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "X86EMDbg"
|
||||
# PROP BASE Intermediate_Dir "X86EMDbg"
|
||||
# PROP BASE CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "X86EMDbg"
|
||||
# PROP Intermediate_Dir "X86EMDbg"
|
||||
# PROP CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_LIB" /YX /Gz /c
|
||||
# ADD CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_LIB" /FR /YX /Gz /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "libChf - Win32 (WCE ARM) Release"
|
||||
# Name "libChf - Win32 (WCE ARM) Debug"
|
||||
# Name "libChf - Win32 (WCE x86em) Release"
|
||||
# Name "libChf - Win32 (WCE x86em) Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_abrt.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_gen.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_hdlr.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_init.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_msgc.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_sig.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_st.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_top.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_win32.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Chf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChfPriv.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "rc"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@
|
39
Chf/RCS/resource.h,v
Executable file
39
Chf/RCS/resource.h,v
Executable file
|
@ -0,0 +1,39 @@
|
|||
head 2.2;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.2;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.2
|
||||
date 2001.01.25.14.13.01; author cibrario; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.2
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by chf.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@
|
118
Chf/RCS/test01.c,v
Normal file
118
Chf/RCS/test01.c,v
Normal file
|
@ -0,0 +1,118 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.55.50; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* $Id$
|
||||
Chf test program.
|
||||
Simple initialization.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
puts("test01");
|
||||
|
||||
system("gencat test01.cat test01.msf");
|
||||
system("gencat test01.cat chf.msf");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
/* ChfGetMessage:
|
||||
message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not
|
||||
*/
|
||||
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1");
|
||||
if(strcmp(msg, "Set_255,Message_1")) 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 */
|
||||
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 3
|
||||
|| d->severity != CHF_WARNING
|
||||
|| 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 */
|
||||
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
|
||||
|
||||
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
e->module_id != CHF_MODULE_ID
|
||||
|| e->condition_code != 4
|
||||
|| e->severity != CHF_INFO
|
||||
|| 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 */
|
||||
ChfDiscard();
|
||||
|
||||
/* This is line 77 */
|
||||
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 5
|
||||
|| d->severity != CHF_ERROR
|
||||
|| 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 */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@
|
43
Chf/RCS/test01.msf,v
Normal file
43
Chf/RCS/test01.msf,v
Normal file
|
@ -0,0 +1,43 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.09.38; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@$set 1
|
||||
255 Chf Test
|
||||
|
||||
$set 255
|
||||
1 Set_255,Message_1
|
||||
3 Set_255,Arg_%d,Message_3
|
||||
4 Set_255,Arg_%s,Message_4
|
||||
5 Set_255,Arg_%d-%d,Message_5
|
||||
6 Set_255,Message_6 (thread %d, sub-condition)
|
||||
7 Set_255,Message_7 (thread %d, main)
|
||||
8 Set_255,Message_8 (thread %d, main)
|
||||
9 Set_255,Message_9
|
||||
|
||||
10 Invalid descriptor link detected
|
||||
11 Bad hdlr stack push count %d; should be %d
|
||||
12 Bad cond stack push count %d; should be %d
|
||||
|
||||
20 Structured exc handling test cond
|
||||
@
|
146
Chf/RCS/test02.c,v
Normal file
146
Chf/RCS/test02.c,v
Normal file
|
@ -0,0 +1,146 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.56.44; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* $Id: test02.c,v 2.1 2000/05/29 13:09:53 cibrario Exp cibrario $
|
||||
Chf test program.
|
||||
Simple initialization - multithreaded.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not */
|
||||
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1");
|
||||
if(strcmp(msg, "Set_255,Message_1")) 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 */
|
||||
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 3
|
||||
|| d->severity != CHF_WARNING
|
||||
|| 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 */
|
||||
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
|
||||
|
||||
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
e->module_id != CHF_MODULE_ID
|
||||
|| e->condition_code != 4
|
||||
|| e->severity != CHF_INFO
|
||||
|| 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 */
|
||||
ChfDiscard();
|
||||
|
||||
/* This is line 67 */
|
||||
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 5
|
||||
|| d->severity != CHF_ERROR
|
||||
|| 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;
|
||||
}
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test02");
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(st = pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
printf("pthread_create: error %d", st);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(st = pthread_join(t[i], &ret))
|
||||
{
|
||||
printf("pthread_join: error %d", st);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
#endif
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@
|
112
Chf/RCS/test03.c,v
Normal file
112
Chf/RCS/test03.c,v
Normal file
|
@ -0,0 +1,112 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.10.29; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* $Id$
|
||||
Chf test program.
|
||||
Generation and signal - single and multithreaded
|
||||
|
||||
$Log$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* 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 7, CHF_INFO, (int)arg ChfEnd;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
ChfSignal();
|
||||
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test03");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@
|
353
Chf/RCS/test04.c,v
Normal file
353
Chf/RCS/test04.c,v
Normal file
|
@ -0,0 +1,353 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.10.38; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* $Id$
|
||||
Chf test program.
|
||||
General condition handling - single and multithreaded
|
||||
|
||||
$Log$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
struct tdata_s
|
||||
{
|
||||
const ChfDescriptor *d, *e;
|
||||
int phase;
|
||||
};
|
||||
|
||||
ChfAction h1(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
if(c != tdata_p->e ||
|
||||
ChfGetNextDescriptor(c) != tdata_p->d)
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
else
|
||||
action = CHF_CONTINUE;
|
||||
|
||||
return action;
|
||||
|
||||
}
|
||||
|
||||
ChfAction h2(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
switch(s)
|
||||
{
|
||||
case CHF_SIGNALING:
|
||||
{
|
||||
if(c != tdata_p->e
|
||||
|| ChfGetNextDescriptor(c) != tdata_p->d
|
||||
|| (tdata_p->phase != 2 && tdata_p->phase != 4))
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
action = (ChfGetConditionCode(c) != 8 ? CHF_CONTINUE : CHF_UNWIND);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHF_UNWINDING:
|
||||
{
|
||||
if(tdata_p->phase != 4) exit(EXIT_FAILURE);
|
||||
tdata_p->phase = 5;
|
||||
action = CHF_CONTINUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
ChfAction h3(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
/* This handler must be invoked only during the first signal */
|
||||
if(tdata_p->phase != 3) exit(EXIT_FAILURE);
|
||||
|
||||
switch(s)
|
||||
{
|
||||
case CHF_SIGNALING:
|
||||
{
|
||||
if(ChfGetConditionCode(c) != 9 ||
|
||||
ChfGetNextDescriptor(c) != NULL)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
tdata_p->phase = 4;
|
||||
action = CHF_CONTINUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
ChfAction h4(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
/* This handler must be invoked only during the first signal */
|
||||
if(tdata_p->phase != 2) exit(EXIT_FAILURE);
|
||||
|
||||
switch(s)
|
||||
{
|
||||
case CHF_SIGNALING:
|
||||
{
|
||||
if(c != tdata_p->e
|
||||
|| ChfGetNextDescriptor(c) != tdata_p->d)
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* This generates a new group and signals it */
|
||||
tdata_p->phase = 3;
|
||||
ChfCondition 9, CHF_INFO ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
if(tdata_p->phase != 4) exit(EXIT_FAILURE);
|
||||
tdata_p->phase = 5;
|
||||
|
||||
if(c != tdata_p->e
|
||||
|| ChfGetNextDescriptor(c) != tdata_p->d)
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
else
|
||||
action = CHF_CONTINUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
volatile struct tdata_s tdata;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h1, NULL, (ChfPointer)(&tdata));
|
||||
|
||||
/* Generate a condition group and signal it */
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
ChfSignal();
|
||||
|
||||
/* Pop the handler */
|
||||
ChfPopHandler();
|
||||
|
||||
/* Generate a new condition group with (apparently) wrong linkage
|
||||
and signal it; this checks that the handler has actually been
|
||||
removed.
|
||||
*/
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = NULL;
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = NULL;
|
||||
ChfSignal();
|
||||
|
||||
/* Conditional unwind test */
|
||||
{
|
||||
sigjmp_buf jb;
|
||||
|
||||
tdata.phase = 0;
|
||||
if(setjmp(jb) == 0)
|
||||
{
|
||||
ChfPushHandler(h2, jb, (ChfPointer)(&tdata));
|
||||
|
||||
/* Generate a condition group and signal it */
|
||||
tdata.phase = 1;
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
/* This does not trigger an unwind */
|
||||
tdata.phase = 2;
|
||||
ChfSignal();
|
||||
|
||||
tdata.phase = 3;
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 8, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
/* This MUST trigger an unwind */
|
||||
tdata.phase = 4;
|
||||
ChfSignal();
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unwind */
|
||||
if(tdata.phase != 5)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
ChfPopHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/* Condition generation and signal while a signal is in progress;
|
||||
this requires two handlers.
|
||||
*/
|
||||
{
|
||||
tdata.phase = 0;
|
||||
|
||||
ChfPushHandler(h3, NULL, (ChfPointer)&tdata);
|
||||
ChfPushHandler(h4, NULL, (ChfPointer)&tdata);
|
||||
|
||||
tdata.phase = 1;
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
tdata.phase = 2;
|
||||
ChfSignal();
|
||||
|
||||
if(tdata.phase != 5)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
ChfPopHandler();
|
||||
ChfPopHandler();
|
||||
}
|
||||
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test04");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@
|
269
Chf/RCS/test05.c,v
Normal file
269
Chf/RCS/test05.c,v
Normal file
|
@ -0,0 +1,269 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.10.46; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* $Id$
|
||||
Chf test program.
|
||||
Condition & Handler stacks oveflow checks - single and multithreaded
|
||||
|
||||
$Log$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
#define H_STACK_SIZE 10
|
||||
#define C_STACK_SIZE 30
|
||||
|
||||
/* Dummy handler; pushed only to verify that the handler stack overflow
|
||||
checks are correct.
|
||||
*/
|
||||
ChfAction h1(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
return CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
/* Overflow check handler; it unwinds if the CHF_F_HDLR_STACK_FULL
|
||||
condition is signalled exactly after H_STACK_SIZE-2 invocations
|
||||
of ChfPushHandler(), it resignals a modified condition if the
|
||||
condition is signalled too early
|
||||
*/
|
||||
ChfAction h2(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
int push_count = *((int *)p);
|
||||
ChfAction action;
|
||||
|
||||
if(s == CHF_SIGNALING)
|
||||
{
|
||||
if(ChfGetModuleId(c) == CHF_SET
|
||||
&& ChfGetConditionCode(c) == CHF_F_HDLR_STACK_FULL)
|
||||
{
|
||||
/* Handler stack is full; check correctness of the descriptor */
|
||||
if(push_count == H_STACK_SIZE-2
|
||||
&& ChfGetNextDescriptor(c) == NULL
|
||||
&& ChfGetSeverity(c) == CHF_FATAL)
|
||||
action = CHF_UNWIND;
|
||||
else
|
||||
{
|
||||
ChfCondition 11, CHF_FATAL, push_count, H_STACK_SIZE-2
|
||||
ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
action = CHF_RESIGNAL;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
/* Overflow check handler; it unwinds if the CHF_F_COND_STACK_FULL
|
||||
condition is signalled exactly after C_STACK_SIZE invocations
|
||||
of ChfCondition, it resignals a modified condition if the
|
||||
condition is signalled too early
|
||||
*/
|
||||
ChfAction h3(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
int push_count = *((int *)p);
|
||||
ChfAction action;
|
||||
|
||||
if(s == CHF_SIGNALING)
|
||||
{
|
||||
if(ChfGetModuleId(c) == CHF_SET
|
||||
&& ChfGetConditionCode(c) == CHF_F_COND_STACK_FULL)
|
||||
{
|
||||
/* Handler stack is full; check correctness of the descriptor */
|
||||
if(push_count == C_STACK_SIZE
|
||||
&& ChfGetNextDescriptor(c) == NULL
|
||||
&& ChfGetSeverity(c) == CHF_FATAL)
|
||||
action = CHF_UNWIND;
|
||||
else
|
||||
{
|
||||
ChfCondition 12, CHF_FATAL, push_count, C_STACK_SIZE
|
||||
ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
action = CHF_RESIGNAL;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
int push_count = 0;
|
||||
sigjmp_buf jb;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* Check handler stack overflow checks */
|
||||
if(sigsetjmp(jb, 1) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h2, jb, (ChfPointer)(&push_count));
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
/* Push dummy handlers until an error should occur */
|
||||
for(; push_count<H_STACK_SIZE-1; push_count++)
|
||||
ChfPushHandler(h1, NULL, NULL);
|
||||
|
||||
/* No error? Bad! */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Flow control returns here if 'handler stack full' was signalled
|
||||
at the correct place.
|
||||
Check condition stack overflow checks
|
||||
*/
|
||||
push_count = 0;
|
||||
if(sigsetjmp(jb, 1) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h3, jb, (ChfPointer)(&push_count));
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
/* Push dummy conditions until an error should occur */
|
||||
for(; push_count<=C_STACK_SIZE; push_count++)
|
||||
ChfCondition 1, CHF_INFO ChfEnd;
|
||||
|
||||
/* No error? Bad! */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Flow control returns here if 'condition stack full' was signalled
|
||||
at the correct place.
|
||||
Check condition stack overflow again, to ensure that no spurious
|
||||
conditions were left out in the previous check.
|
||||
*/
|
||||
push_count = 0;
|
||||
if(sigsetjmp(jb, 1) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h3, jb, (ChfPointer)(&push_count));
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
/* Push dummy conditions until an error should occur */
|
||||
for(; push_count<=C_STACK_SIZE; push_count++)
|
||||
ChfCondition 1, CHF_INFO ChfEnd;
|
||||
|
||||
/* No error? Bad! */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return (void *)EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test05");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat",
|
||||
C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
{
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if((int)ret != EXIT_SUCCESS)
|
||||
exit((int)ret);
|
||||
}
|
||||
|
||||
st = EXIT_SUCCESS;
|
||||
#else
|
||||
st = (int)task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(st);
|
||||
}
|
||||
|
||||
@
|
160
Chf/RCS/test06.c,v
Normal file
160
Chf/RCS/test06.c,v
Normal file
|
@ -0,0 +1,160 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.10.55; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* $Id$
|
||||
Chf test program.
|
||||
Structured condition handling - single and multithreaded
|
||||
|
||||
$Log$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
#define H_STACK_SIZE 10
|
||||
#define C_STACK_SIZE 30
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
volatile int phase = 0;
|
||||
|
||||
ChfTry
|
||||
{
|
||||
phase = 1;
|
||||
ChfCondition 20, CHF_SUCCESS ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 2;
|
||||
ChfCondition 20, CHF_INFO ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 3;
|
||||
ChfCondition 20, CHF_WARNING ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 4;
|
||||
ChfCondition 20, CHF_ERROR ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 5;
|
||||
ChfCondition 20, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
/* Should not be reached */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
ChfCatch
|
||||
{
|
||||
/* Catched an exception; check descriptor */
|
||||
const ChfDescriptor *d = ChfGetTopCondition();
|
||||
if(d == NULL
|
||||
|| ChfGetNextDescriptor(d) != NULL
|
||||
|| ChfGetModuleId(d) != CHF_MODULE_ID
|
||||
|| ChfGetConditionCode(d) != 20)
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
ChfEndTry;
|
||||
|
||||
/* Check that the condition stack actually is empty after catch */
|
||||
ChfTry
|
||||
{
|
||||
volatile const ChfDescriptor *e = ChfGetTopCondition();
|
||||
}
|
||||
ChfCatch
|
||||
{
|
||||
const ChfDescriptor *d = ChfGetTopCondition();
|
||||
if(d == NULL
|
||||
|| ChfGetNextDescriptor(d) != NULL
|
||||
|| ChfGetModuleId(d) != CHF_SET
|
||||
|| ChfGetConditionCode(d) != CHF_F_BAD_STATE)
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
ChfEndTry;
|
||||
|
||||
return (void *)EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test06");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat",
|
||||
C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
{
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if((int)ret != EXIT_SUCCESS)
|
||||
exit((int)ret);
|
||||
}
|
||||
|
||||
st = EXIT_SUCCESS;
|
||||
#else
|
||||
st = (int)task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(st);
|
||||
}
|
||||
|
||||
@
|
128
Chf/RCS/test07.c,v
Normal file
128
Chf/RCS/test07.c,v
Normal file
|
@ -0,0 +1,128 @@
|
|||
head 2.1;
|
||||
access;
|
||||
symbols
|
||||
V4_1_1_1:2.1
|
||||
Rel_2_1:2.1;
|
||||
locks; strict;
|
||||
comment @ * @;
|
||||
|
||||
|
||||
2.1
|
||||
date 2000.05.29.13.57.17; author cibrario; state Rel;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@@
|
||||
|
||||
|
||||
2.1
|
||||
log
|
||||
@*** empty log message ***
|
||||
@
|
||||
text
|
||||
@/* $Id: test07.c,v 2.1 2000/05/29 13:11:01 cibrario Exp cibrario $
|
||||
Chf test program.
|
||||
Simple initialization.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
extern ChfTable message_table[];
|
||||
extern size_t message_table_size;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
puts("test07");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfStaticInit(argv[0], CHF_DEFAULT,
|
||||
message_table, message_table_size, 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
/* ChfGetMessage:
|
||||
message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not
|
||||
*/
|
||||
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1");
|
||||
if(strcmp(msg, "Set_255,Message_1")) 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 */
|
||||
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 3
|
||||
|| d->severity != CHF_WARNING
|
||||
|| 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 */
|
||||
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
|
||||
|
||||
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
e->module_id != CHF_MODULE_ID
|
||||
|| e->condition_code != 4
|
||||
|| e->severity != CHF_INFO
|
||||
|| 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 */
|
||||
ChfDiscard();
|
||||
|
||||
/* This is line 77 */
|
||||
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 5
|
||||
|| d->severity != CHF_ERROR
|
||||
|| 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 */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
ChfTable message_table[] =
|
||||
{
|
||||
{ CHF_MODULE_ID, 1, "Set_255,Message_1" },
|
||||
{ CHF_MODULE_ID, 3, "Set_255,Arg_%d,Message_3" },
|
||||
{ CHF_MODULE_ID, 4, "Set_255,Arg_%s,Message_4" },
|
||||
{ CHF_MODULE_ID, 5, "Set_255,Arg_%d-%d,Message_5" }
|
||||
};
|
||||
|
||||
size_t message_table_size = sizeof(message_table)/sizeof(message_table[0]);
|
||||
@
|
40
Chf/chf.msf
Normal file
40
Chf/chf.msf
Normal file
|
@ -0,0 +1,40 @@
|
|||
$ .+
|
||||
$ .
|
||||
$ .identifier : $Id: chf.msf,v 2.2 2001/01/25 12:00:19 cibrario Exp $
|
||||
$ .context :
|
||||
$ .title : $RCSfile: chf.msf,v $
|
||||
$ .kind : Makefile
|
||||
$ .author : Ivan Cibrario B.
|
||||
$ .site : CSTV-CNR
|
||||
$ .creation : 27-May-1996
|
||||
$ .keywords : *
|
||||
$ .description :
|
||||
$ . Message source file for the CHF conditions
|
||||
$ .notes :
|
||||
$ . $Log: chf.msf,v $
|
||||
$ . Revision 2.2 2001/01/25 12:00:19 cibrario
|
||||
$ . Added partial Win32 support (Windows CE only).
|
||||
$ .
|
||||
$ . Revision 2.1 2000/05/26 14:17:21 cibrario
|
||||
$ . Updated documentation block and RCS log message header to prevent
|
||||
$ . gencat warnings on Linux boxes
|
||||
$ .
|
||||
$ . Revision 1.1 1996/05/28 12:57:06 cibrario
|
||||
$ . Initial revision
|
||||
$ .
|
||||
$ .-
|
||||
|
||||
$set 1
|
||||
2 Chf
|
||||
3 Errno
|
||||
|
||||
$set 2
|
||||
1 Condition stack is full
|
||||
2 Handler stack is full
|
||||
3 Handler stack is empty
|
||||
4 Wrong Chf state for requested operation
|
||||
5 Invalid action code from handler (code=<%d>d)
|
||||
6 Dynamic memory allocation failed
|
||||
7 Function not implemented
|
||||
10 setlocale() failed
|
||||
11 catopen() failed
|
99
Chf/chf.rc
Executable file
99
Chf/chf.rc
Executable file
|
@ -0,0 +1,99 @@
|
|||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
1002 "Chf"
|
||||
END
|
||||
|
||||
STRINGTABLE DISCARDABLE
|
||||
BEGIN
|
||||
2001 "Condition stack is full"
|
||||
2002 "Handler stack is full"
|
||||
2003 "Handler stack is empty"
|
||||
2004 "Wrong state for requested operation"
|
||||
2005 "Invalid action code from handler (code=<%d>d)"
|
||||
2006 "Dynamic memory allocation failed"
|
||||
2007 "Function not available"
|
||||
2010 "setlocale() failed"
|
||||
2011 "catopen() failed"
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Italian (Italy) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Italian (Italy) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
2053
Chf/chf.texi
Normal file
2053
Chf/chf.texi
Normal file
File diff suppressed because it is too large
Load diff
199
Chf/chf_abrt.c
Normal file
199
Chf/chf_abrt.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_abrt.c,v 2.2 2001/01/25 12:08:24 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_abrt.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF function ChfAbort()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_abrt.c,v $
|
||||
Revision 2.2 2001/01/25 12:08:24 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 2.1 2000/05/26 14:22:07 cibrario
|
||||
- Conditional inclusion of pthread.h (mt support)
|
||||
- Expanded abort message table with mt support messages
|
||||
- ChfAbort() with CHF_ABORT flag clear and mt support enabled now
|
||||
exits invoking thread only
|
||||
|
||||
Revision 1.1 1996/05/28 12:53:26 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_abrt.c,v 2.2 2001/01/25 12:08:24 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Abort codes message table; the relative position of the messages must
|
||||
match the numeric codes CHF_ABORT_xxxx defined in ChfPriv.h
|
||||
*/
|
||||
static const ChfChar *message_table[] =
|
||||
{
|
||||
(const ChfChar *)NULL,
|
||||
ChfText("Not initialized"),
|
||||
ChfText("Temporary message buffer overflow"),
|
||||
ChfText("Invalid action from last chance handler"),
|
||||
ChfText("Already initialized"),
|
||||
ChfText("Unwind request while unwinding"),
|
||||
ChfText("Improperly handled condition"),
|
||||
ChfText("Fatal condition while unwinding"),
|
||||
ChfText("Condition stack overflow"),
|
||||
ChfText("Can't prime a new Chf context"),
|
||||
ChfText("Pthread interaction failed")
|
||||
};
|
||||
|
||||
#define MESSAGE_TABLE_SIZE (sizeof(message_table)/sizeof(const ChfChar *))
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfAbort
|
||||
.kind : C function
|
||||
.creation : 13-May-1996
|
||||
.description :
|
||||
This function prints the message associated with 'abort_code' and then
|
||||
immediately aborts either the application (when multithreading support not
|
||||
enabled or CHF_ABORT set) or the invoking thread only (multithreading
|
||||
support enabled and CHF_ABORT not set). The abort is performed either:
|
||||
- using abort() if either CHF has not been correctly initialized or
|
||||
the chf_context.options flag CHF_ABORT is set
|
||||
- using exit(chf_context.exit_code) (multithreading support not enabled)
|
||||
or pthread_exit(chf_context.exit_code) (multithreading support enabled)
|
||||
if the flag is clear
|
||||
|
||||
No message is printed if the abort code is CHF_ABORT_SILENT; this code
|
||||
is used, for example, by the default condition handler to terminate the
|
||||
application when a CHF_FATAL condition occours.
|
||||
|
||||
NOTE: This function must be called only when either a serious internal CHF
|
||||
failure occurs or it's necessary to abort the application.
|
||||
|
||||
WIN32:
|
||||
|
||||
- stderr stream is not supported; the abort message is displayed in a
|
||||
message box only if Chf has been correctly initialized, otherwise the
|
||||
abort will be done silently
|
||||
|
||||
- abort() is not supported and has been replaced by exit(EXIT_FAILURE)
|
||||
|
||||
.call :
|
||||
ChfAbort(abort_code);
|
||||
.input :
|
||||
const int abort_code, abort_code
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 13-May-1996, creation
|
||||
2.1, 19-May-2000, update:
|
||||
- added multithreading support
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support
|
||||
|
||||
.- */
|
||||
void ChfAbort( /* Abort application */
|
||||
const int abort_code
|
||||
)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if(abort_code != CHF_ABORT_SILENT)
|
||||
{
|
||||
TCHAR abort_msg[CHF_MAX_MESSAGE_LENGTH];
|
||||
HWND active_window;
|
||||
|
||||
/* stderr not available;
|
||||
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(chf_context.state == CHF_UNKNOWN || chf_context.options & CHF_ABORT)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
else
|
||||
/* Else, exit the application anyway, but with the exit code
|
||||
registered by the application. Don't use PostQuitMessage(),
|
||||
because the contract is that ChfAbort() never returns to the caller.
|
||||
*/
|
||||
#ifndef _REENTRANT
|
||||
exit(chf_context.exit_code);
|
||||
#else
|
||||
#error "_REENTRANT not supported yet"
|
||||
#endif
|
||||
|
||||
#else
|
||||
if(abort_code != CHF_ABORT_SILENT)
|
||||
{
|
||||
fputs(CHF_ABORT_HEADER, stderr);
|
||||
|
||||
if(abort_code < 0 || abort_code >= MESSAGE_TABLE_SIZE)
|
||||
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
|
||||
#ifndef _REENTRANT
|
||||
exit(chf_context.exit_code);
|
||||
#else
|
||||
pthread_exit((void *)(chf_context.exit_code));
|
||||
#endif
|
||||
#endif
|
||||
}
|
179
Chf/chf_gen.c
Normal file
179
Chf/chf_gen.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_gen.c,v 2.2 2001/01/25 12:10:22 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_gen.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module contains the condition generation function of CHF
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_gen.c,v $
|
||||
Revision 2.2 2001/01/25 12:10:22 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 1.1 1996/05/28 12:53:59 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_gen.c,v 2.2 2001/01/25 12:10:22 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfGenerate
|
||||
.kind : C function
|
||||
.creation : 3-May-1996
|
||||
.description :
|
||||
This function generates a condition descriptor for the condition described
|
||||
by 'module_id', 'file_name', 'line_number', 'condition_code' and 'severity',
|
||||
and the partial message associated with it, specialized with the additional
|
||||
arguments '...'; the new condition descriptor is put onto the top of the
|
||||
condition stack.
|
||||
|
||||
If the condition stack is full, this function generates the condition
|
||||
CHF_F_COND_STACK_FULL and immediately invokes ChfSignal() for the current
|
||||
condition stack.
|
||||
|
||||
NOTE: This function calls the CHF function 'ChfAbort()' to
|
||||
abort the application if either:
|
||||
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
|
||||
- there is an overflow in the internal buffer used during the
|
||||
generation of the partial message associated with the condition
|
||||
(abort code CHF_ABORT_MSG_OVF)
|
||||
- there was an attempt to generate a condition while the CHF condition
|
||||
CHF_F_COND_STACK_FULL (condition stack full) was being signalled
|
||||
(abort code CHF_ABORT_COND_STACK_OVF)
|
||||
|
||||
|
||||
.call :
|
||||
ChfGenerate(module_id, file_name, line_number,
|
||||
condition_code, severity, ...);
|
||||
.input :
|
||||
const int module_id, module identifier
|
||||
const char *file_name, file name
|
||||
const int line_number, line number
|
||||
const int condition_code, condition code
|
||||
const ChfSeverity severity, severity
|
||||
..., additional arguments
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
(*) CHF_F_COND_STACK_FULL, the condition stack is full
|
||||
.notes :
|
||||
1.1, 3-May-1996, creation
|
||||
|
||||
.- */
|
||||
void ChfGenerate( /* Generate a condition into the stack */
|
||||
const int module_id,
|
||||
const ChfChar *file_name,
|
||||
const int line_number,
|
||||
const int condition_code,
|
||||
const ChfSeverity severity,
|
||||
...
|
||||
)
|
||||
{
|
||||
ChfDescriptor *new_descriptor;
|
||||
va_list aux_arg;
|
||||
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
/* Prepare the additional arguments list */
|
||||
va_start(aux_arg, severity);
|
||||
|
||||
if((new_descriptor = chf_context.condition_sp) -
|
||||
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,
|
||||
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;
|
||||
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,
|
||||
ChfGetMessage(CHF_MODULE_ID, CHF_F_COND_STACK_FULL,
|
||||
ChfText("Condition stack is full")), CHF_MAX_MESSAGE_LENGTH-1);
|
||||
new_descriptor->message[CHF_MAX_MESSAGE_LENGTH-1] = '\0';
|
||||
|
||||
new_descriptor->next = CHF_NULL_DESCRIPTOR;
|
||||
chf_context.condition_sp++;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else
|
||||
ChfAbort(CHF_ABORT_COND_STACK_OVF);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ChfChar def_message[CHF_DEF_MESSAGE_LENGTH];
|
||||
ChfChar tmp_message[CHF_TMP_MESSAGE_LENGTH];
|
||||
|
||||
new_descriptor->module_id = module_id;
|
||||
new_descriptor->condition_code = condition_code;
|
||||
new_descriptor->severity = severity;
|
||||
new_descriptor->line_number = line_number;
|
||||
new_descriptor->file_name = file_name;
|
||||
|
||||
/* Generate the default message */
|
||||
ChfSprintf(def_message, CHF_DEF_PARTIAL_MSG_FMT, condition_code);
|
||||
|
||||
/* Generate the partial message associated with the condition using a
|
||||
temporary area
|
||||
*/
|
||||
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 */
|
||||
ChfStrncpy(new_descriptor->message, tmp_message, CHF_MAX_MESSAGE_LENGTH-1);
|
||||
new_descriptor->message[CHF_MAX_MESSAGE_LENGTH-1] = '\0';
|
||||
|
||||
/* Link the new descriptor with the current descriptor list, if it
|
||||
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++;
|
||||
}
|
||||
}
|
264
Chf/chf_hdlr.c
Normal file
264
Chf/chf_hdlr.c
Normal file
|
@ -0,0 +1,264 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_hdlr.c,v 2.2 2001/01/25 12:12:46 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_hdlr.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF functions ChfPushHandler() and
|
||||
ChfPopHandler()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_hdlr.c,v $
|
||||
Revision 2.2 2001/01/25 12:12:46 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 2.1 2000/05/26 14:45:04 cibrario
|
||||
- Implemented StructuredHelper(), the structured condition handling
|
||||
helper handler
|
||||
- Updated ChfPushHandler() to push the structured condition handling
|
||||
helper when new_handler is CHF_NULL_HANDLER
|
||||
- unwind_context is now a sigjmp_buf, passed as argument directly,
|
||||
that is, without additional address operators
|
||||
- improved documentation of ChfPopHandler()
|
||||
|
||||
Revision 1.6 1997/01/15 13:44:39 cibrario
|
||||
The function ChfPushHandler() has the new argument 'handler_context'.
|
||||
|
||||
Revision 1.1 1996/05/28 12:54:28 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_hdlr.c,v 2.2 2001/01/25 12:12:46 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : StructuredHelper
|
||||
.kind : C function
|
||||
.creation : 19-May-2000
|
||||
.description :
|
||||
This function is the structured condition handling helper of CHF.
|
||||
It's automatically pushed into the condition handler stack by
|
||||
ChfPushHandler() when its 'new_handler' argument is CHF_NULL_HANDLER,
|
||||
and performs the following functions:
|
||||
|
||||
- if called during an ordinary signalling operation with a
|
||||
CHF_FATAL condition, it requests the action CHF_UNWIND_KEEP
|
||||
|
||||
- if called when Chf is in any other state, or with a
|
||||
severity less than CHF_FATAL, it requests the action CHF_RESIGNAL
|
||||
|
||||
The structured condition handling helper currently makes no use of
|
||||
handler_context.
|
||||
|
||||
.call :
|
||||
action = StructuredHelper(desc, state, context);
|
||||
.input :
|
||||
const ChfDescriptor *desc, condition descriptor
|
||||
const ChfState state, current CHF state
|
||||
.output :
|
||||
ChfAction action, action requested by the handler
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
2.1, 19-May-2000, creation
|
||||
|
||||
.- */
|
||||
static ChfAction StructuredHelper(
|
||||
const ChfDescriptor *desc,
|
||||
const ChfState state,
|
||||
ChfPointer handler_context
|
||||
)
|
||||
{
|
||||
ChfAction action;
|
||||
const ChfDescriptor *d;
|
||||
|
||||
return((state == CHF_SIGNALING && ChfGetSeverity(desc) == CHF_FATAL)
|
||||
? CHF_UNWIND_KEEP : CHF_RESIGNAL);
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfPushHandler
|
||||
.kind : C function
|
||||
.creation : 13-May-1996
|
||||
.description :
|
||||
This function pushes the new condition handler 'new_handler' with its
|
||||
associated longjmp context pointed by 'unwind_context' into the handler
|
||||
stack and returns CHF_S_OK to the caller. If 'new_handler' is
|
||||
CHF_NULL_HANDLER, the special structured condition handling helper
|
||||
'StructuredHelper()' is pushed instead.
|
||||
|
||||
Moreover, this function saves a copy of the pointer 'handler_context'; it
|
||||
will be passed to 'new_handler' upon each subsequent activation, and
|
||||
therefore can be used as a private handler context pointer. The user must
|
||||
assure that the information pointed by 'handler_context', if any, will
|
||||
remain valid until 'new_handler' is popped from the condition stack.
|
||||
'handler_context' may be set to the special (null) value CHF_NULL_POINTER to
|
||||
indicate that the handler hasn't any private context information.
|
||||
|
||||
If, in the future, the handler will request the CHF_UNWIND action, the
|
||||
setjmp() function invocation that established 'unwind_context' will appear
|
||||
to return again.
|
||||
|
||||
'unwind_context' can be the reserved (null) pointer CHF_NULL_CONTEXT; in
|
||||
this case, if the handler will request the CHF_UNWIND_ACTION, the
|
||||
application will be silently terminated calling ChfAbort() with abort code
|
||||
CHF_ABORT_SILENT.
|
||||
|
||||
If some error occours during the execution, the function will generate
|
||||
and immediately signal one of the conditions listed below and marked with
|
||||
(*). The function will never return dorectly to the caller, since all
|
||||
conditions are CHF_FATAL.
|
||||
|
||||
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
|
||||
the CHF subsystem has not been initialized.
|
||||
|
||||
.call :
|
||||
ChfPushHandler(new_handler, unwind_context);
|
||||
.input :
|
||||
ChfHandler new_handler, new condition handler
|
||||
void *unwind_context, handler unwind context pointer
|
||||
ChfPointer handler_context, private handler context pointer
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
(*) CHF_F_BAD_STATE, bad CHF state for requested operation
|
||||
(*) CHF_F_HDLR_STACK_FULL, the handler stack is full
|
||||
.notes :
|
||||
1.1, 13-May-1996, creation
|
||||
1.6, 15-Jan-1997, update:
|
||||
- added the argument 'handler_context'
|
||||
- improved documentation
|
||||
2.1, 19-May-2000, update:
|
||||
- now using sigjmp_buf as unwind_context
|
||||
- added StructuredHelper handling
|
||||
|
||||
.- */
|
||||
void ChfPushHandler( /* Push a new handler into the stack */
|
||||
ChfHandler new_handler,
|
||||
void *unwind_context,
|
||||
ChfPointer handler_context
|
||||
)
|
||||
{
|
||||
/* 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_IDLE)
|
||||
{
|
||||
ChfCondition CHF_F_BAD_STATE, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* Check if the handler stack is full */
|
||||
else if(chf_context.handler_sp - chf_context.handler_stack >=
|
||||
chf_context.handler_stack_size)
|
||||
{
|
||||
ChfCondition CHF_F_HDLR_STACK_FULL, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
chf_context.handler_sp->unwind_context = unwind_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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfPopHandler
|
||||
.kind : C function
|
||||
.creation : 13-May-1996
|
||||
.description :
|
||||
This function pops the topmost condition handler from the handler stack and
|
||||
returns to the caller.
|
||||
|
||||
If some error occours during the execution, the function will generate
|
||||
and immediately signal one of the conditions listed below and marked with
|
||||
(*). The function will never return directly to the caller, since all
|
||||
conditions are CHF_FATAL.
|
||||
|
||||
NOTE: This function calls ChfAbort() with abort code CHF_ABORT_INIT if
|
||||
the CHF subsystem has not been initialized.
|
||||
|
||||
.call :
|
||||
ChfPopHandler();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
CHF_F_BAD_STATE, bad CHF state for requested operation
|
||||
CHF_F_HDLR_STACK_FULL, the handler stack is full
|
||||
.notes :
|
||||
1.1, 13-May-1996, creation
|
||||
1.6, 15-Jan-1997, update:
|
||||
- improved documentation
|
||||
2.1, 19-May-2000, update:
|
||||
- improved documentation
|
||||
|
||||
.- */
|
||||
void ChfPopHandler( /* Pop a handler */
|
||||
void
|
||||
)
|
||||
{
|
||||
/* 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_IDLE)
|
||||
{
|
||||
ChfCondition CHF_F_BAD_STATE, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* Check if the handler stack is empty */
|
||||
else if(chf_context.handler_sp == chf_context.handler_stack)
|
||||
{
|
||||
ChfCondition CHF_F_HDLR_STACK_EMPTY, CHF_FATAL
|
||||
ChfEnd;
|
||||
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* Discard the topmost condition handler */
|
||||
else
|
||||
--chf_context.handler_sp;
|
||||
}
|
780
Chf/chf_init.c
Normal file
780
Chf/chf_init.c
Normal file
|
@ -0,0 +1,780 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_init.c,v 2.2 2001/01/25 14:05:23 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_init.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF initialization function ChfInit()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_init.c,v $
|
||||
Revision 2.2 2001/01/25 14:05:23 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 2.1 2000/05/26 15:30:42 cibrario
|
||||
- Renamed static context chf_context to _chf_context; it is now in
|
||||
actual use only when mt support is not enabled, otherwise it is
|
||||
used only as a prototype to prime the per-thread contexts on demand
|
||||
- Conditional definition of mt support static variables
|
||||
(context_mutex to access the static master context, fputs_mutex to
|
||||
ensure the atomicity of DefaultHandler() while it is printing a
|
||||
sequence of grouped condition messages) and functions (DestroyContext()
|
||||
to destroy a per-thread context when the owning thread terminates)
|
||||
- Deeply revised ChfInit() and ChfExit() to implement multithreading
|
||||
support
|
||||
- Implemented function _ChfGetContext() to return a pointer to the
|
||||
per-thread Chf context, creating them on-demand.
|
||||
|
||||
Revision 1.6 1997/01/15 13:37:19 cibrario
|
||||
The Chf condition handlers now have a third argument: the private handler
|
||||
context pointer; the code has been updated accordingly.
|
||||
|
||||
Revision 1.4 1996/09/25 13:29:01 cibrario
|
||||
Added static char[] variable rcs_lib_id; it contains the value of the
|
||||
CHF_LIBRARY_ID macro. The header Chf.h sets that macro to its RCS Id,
|
||||
that is also the Id of the whole Chf library.
|
||||
|
||||
Revision 1.1 1996/05/28 12:54:58 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_init.c,v 2.2 2001/01/25 14:05:23 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global and static variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* Chf Library Id */
|
||||
#ifndef lint
|
||||
static ChfChar rcs_lib_id[] = CHF_LIBRARY_ID;
|
||||
#endif
|
||||
|
||||
/* CHF context */
|
||||
ChfContext _chf_context;
|
||||
|
||||
/* Message separator and severity names for ChfBuildMessage() */
|
||||
static const ChfChar separator[] = CHF_MESSAGE_SEPARATOR;
|
||||
static const ChfChar *severity_name[] = CHF_SEVERITY_NAMES;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Multithreading support
|
||||
------------------------------------------------------------------------- */
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
|
||||
/* Mutex to access chf_context during initialization and exit;
|
||||
mutex to puts condition messages on stderr (DefaultHandler)
|
||||
*/
|
||||
static pthread_mutex_t context_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t fputs_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* Chf data key */
|
||||
static pthread_key_t data_key;
|
||||
|
||||
/* This function is called to destroy a Chf context when the owning
|
||||
thread terminated.
|
||||
*/
|
||||
static void DestroyContext(void *context)
|
||||
{
|
||||
free(((ChfContext *)context)->message_buffer);
|
||||
free(((ChfContext *)context)->handler_stack);
|
||||
free(((ChfContext *)context)->condition_stack);
|
||||
free(context);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : DefaultHandler
|
||||
.kind : C function
|
||||
.creation : 17-May-1996
|
||||
.description :
|
||||
This function is the default condition handler of CHF. It's automatically
|
||||
pushed into the condition handler stack by ChfInit() and performs the
|
||||
following functions:
|
||||
|
||||
- if called during an unwind, it returns immediately to the caller,
|
||||
requesting the action CHF_RESIGNAL, else
|
||||
|
||||
- if the severity of the condition being signalled is greater than
|
||||
CHF_SUCCESS, it prints the messages associated with the entire
|
||||
condition group on stderr using the standard function
|
||||
ChfBuildMessage() to build the messages.
|
||||
|
||||
- if the severity of the condition being signalled is less than
|
||||
CHF_FATAL, it returns to the caller requesting the action
|
||||
CHF_CONTINUE, else
|
||||
|
||||
- if the CHF_FATAL condition was NOT signalled during an unwind
|
||||
operation, it returns to the caller requesting the action
|
||||
CHF_UNWIND, otherwise it requests the action CHF_RESIGNAL.
|
||||
|
||||
WIN32:
|
||||
|
||||
- stderr stream is not available and modal MessageBox require the
|
||||
parent's handle to work reliably; the default handler does not print
|
||||
anything
|
||||
|
||||
.call :
|
||||
action = DefaultHandler(desc, state, context);
|
||||
.input :
|
||||
const ChfDescriptor *desc, condition descriptor
|
||||
const ChfState state, current CHF state
|
||||
.output :
|
||||
ChfAction action, action requested by the handler
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 16-May-1996, creation
|
||||
1.6, 15-Jan-1997, update:
|
||||
- the Chf condition handlers now have a third argument: the private
|
||||
handler context pointer.
|
||||
2.1, 25-May-2000, update:
|
||||
- added multithreading support
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support
|
||||
|
||||
.- */
|
||||
static ChfAction DefaultHandler(
|
||||
const ChfDescriptor *desc,
|
||||
const ChfState state,
|
||||
ChfPointer handler_context
|
||||
)
|
||||
{
|
||||
ChfAction action;
|
||||
const ChfDescriptor *d;
|
||||
|
||||
if(state == CHF_UNWINDING)
|
||||
/* If CHF is unwinding, do nothing */
|
||||
action = CHF_RESIGNAL;
|
||||
|
||||
else
|
||||
{
|
||||
/* Print the condition messages, if necessary. The sequence of fputs()
|
||||
is done atomically if multithreading support is enabled.
|
||||
In Win32, the default handler does not print anything.
|
||||
*/
|
||||
if(ChfGetSeverity(desc) > CHF_SUCCESS)
|
||||
{
|
||||
#ifdef _REENTRANT
|
||||
if(pthread_mutex_lock(&fputs_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
for(d = desc; d != CHF_NULL_DESCRIPTOR; d = ChfGetNextDescriptor(d))
|
||||
fputs(ChfBuildMessage(d), stderr);
|
||||
#endif
|
||||
#ifdef _REENTRANT
|
||||
if(pthread_mutex_unlock(&fputs_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the action code to the Chf handler dispatcher */
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : scopy
|
||||
.kind : C function
|
||||
.creation : 16-May-1996
|
||||
.description :
|
||||
This function writes the NUL-terminated string pointed by 'q' starting
|
||||
from 'p', including the NUL terminator and without trepassing 'p_end'.
|
||||
The function returns a pointer to the NUL-terminator just written.
|
||||
|
||||
.call :
|
||||
np = scopy(p, q, p_end);
|
||||
.input :
|
||||
char *p, starting position for the write
|
||||
const char *q, pointer to the string to be copied
|
||||
char *p_end, pointer to the end of the output area
|
||||
.output :
|
||||
char *np, pointer to the NUL-terminator just written
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 16-May-1996, creation
|
||||
|
||||
.- */
|
||||
static ChfChar *scopy(
|
||||
ChfChar *p,
|
||||
const ChfChar *q,
|
||||
ChfChar *p_end
|
||||
)
|
||||
{
|
||||
size_t q_len = ChfStrlen(q);
|
||||
size_t p_avail = p_end - p;
|
||||
|
||||
if(q_len < p_avail)
|
||||
{
|
||||
ChfStrcpy(p, q);
|
||||
p += q_len;
|
||||
}
|
||||
|
||||
else if(p_avail > 1)
|
||||
{
|
||||
ChfStrncpy(p, q, p_avail-2);
|
||||
p[p_avail-1] = '\0';
|
||||
p = p_end;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfGetMessage
|
||||
.kind : C function
|
||||
.creation : 17-May-1996
|
||||
.description :
|
||||
This function retrieves the message associated with the pair
|
||||
('module_id', 'condition_code') and returns a pointer to it. The function
|
||||
will return 'default_message' if it isn't able to retrieve the message.
|
||||
If module_id==CHF_ERRNO_SET, the function will use strerror(), if
|
||||
necessary, to retrieve the requested message.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
|
||||
if CHF hasn't been correctly initialized.
|
||||
|
||||
NOTE: The returned pointer points to per-thread static storage, which will be
|
||||
overwritten by subsequent calls to this function.
|
||||
|
||||
WIN32:
|
||||
|
||||
- strerror() is not supported; the last-chance translation of condition
|
||||
codes in CHF_ERRNO_SET is not performed
|
||||
|
||||
.call :
|
||||
message = ChfGetMessage(module_id, condition_code,
|
||||
default_message);
|
||||
.input :
|
||||
const int module_id, module identifier
|
||||
const int condition_code, condition code
|
||||
const char *default_message, default message
|
||||
.output :
|
||||
const char *message, pointer to the retrieved message
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 17-May-1996, creation
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support
|
||||
|
||||
.- */
|
||||
const ChfChar *ChfGetMessage( /* Retrieve a condition message */
|
||||
const int module_id,
|
||||
const int condition_code,
|
||||
const ChfChar *default_message
|
||||
)
|
||||
{
|
||||
const ChfChar *message;
|
||||
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
if((message = chf_context.mrs_get(chf_context.mrs_data,
|
||||
module_id, condition_code, default_message)) == default_message &&
|
||||
module_id == CHF_ERRNO_SET)
|
||||
# ifdef _WIN32
|
||||
message = default_message;
|
||||
# else
|
||||
message = strerror(condition_code);
|
||||
# endif
|
||||
|
||||
return(message);
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfBuildMessage
|
||||
.kind : C function
|
||||
.creation : 16-May-1996
|
||||
.description :
|
||||
This function builds the message associated with the given condition
|
||||
descriptor and returns a pointer to a string containing it.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
|
||||
if CHF hasn't been correctly initialized.
|
||||
|
||||
NOTE: The returned pointer points to per-thread static storage, which will be
|
||||
overwritten by subsequent calls to this function.
|
||||
|
||||
WIN32:
|
||||
|
||||
- to save space, the application's name and severity code are not
|
||||
included in the message
|
||||
|
||||
.call :
|
||||
msg = ChfBuildMessage(descriptor);
|
||||
.input :
|
||||
const ChfDescriptor *descriptor, condition descriptor
|
||||
.output :
|
||||
char *msg, pointer to the message associated with 'descriptor'
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 16-May-1996, creation
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support
|
||||
|
||||
.- */
|
||||
ChfChar *ChfBuildMessage( /* Build a condition message */
|
||||
const ChfDescriptor *descriptor
|
||||
)
|
||||
{
|
||||
ChfChar *tmp_p;
|
||||
ChfChar *tmp_end;
|
||||
ChfChar def_message[CHF_DEF_MESSAGE_LENGTH];
|
||||
ChfSeverity severity;
|
||||
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
/* Set appropriate pointers to the start/end of the message buffer */
|
||||
tmp_p = chf_context.message_buffer;
|
||||
tmp_end = tmp_p + CHF_MAX_MESSAGE_LENGTH;
|
||||
|
||||
#ifndef _WIN32
|
||||
/* The message starts with "<app_name>: " if the condition is the first of
|
||||
its condition group, with "\t" if not.
|
||||
*/
|
||||
if(descriptor == chf_context.condition_sp-1)
|
||||
{
|
||||
tmp_p = scopy(tmp_p, chf_context.app_name, tmp_end);
|
||||
tmp_p = scopy(tmp_p, separator, tmp_end);
|
||||
}
|
||||
|
||||
else
|
||||
tmp_p = scopy(tmp_p, ChfText("\t"), tmp_end);
|
||||
#endif
|
||||
|
||||
/* The message continues with the module name */
|
||||
ChfSprintf(def_message, CHF_DEF_MID_MSG_FMT, ChfGetModuleId(descriptor));
|
||||
|
||||
tmp_p = scopy(tmp_p,
|
||||
ChfGetMessage(CHF_MODULE_NAMES_SET, ChfGetModuleId(descriptor),
|
||||
def_message), tmp_end);
|
||||
|
||||
/* Add also the extended information, if any */
|
||||
if(ChfGetLineNumber(descriptor) != CHF_UNKNOWN_LINE_NUMBER)
|
||||
{
|
||||
tmp_p = scopy(tmp_p, ChfText(" "), tmp_end);
|
||||
|
||||
ChfSprintf(def_message, CHF_EXTENDED_INFO_FMT,
|
||||
ChfGetFileName(descriptor), ChfGetLineNumber(descriptor));
|
||||
|
||||
tmp_p = scopy(tmp_p, def_message, tmp_end);
|
||||
}
|
||||
|
||||
tmp_p = scopy(tmp_p, separator, tmp_end);
|
||||
|
||||
#ifndef _WIN32
|
||||
/* Add the severity code of the message */
|
||||
tmp_p = scopy(tmp_p,
|
||||
((severity = ChfGetSeverity(descriptor)) < CHF_SUCCESS ||
|
||||
severity > CHF_FATAL) ? CHF_UNKNOWN_SEVERITY : severity_name[severity],
|
||||
tmp_end);
|
||||
|
||||
tmp_p = scopy(tmp_p, separator, tmp_end);
|
||||
#endif
|
||||
|
||||
/* The message ends with the partial message from the descriptor */
|
||||
tmp_p = scopy(tmp_p, ChfGetPartialMessage(descriptor), tmp_end);
|
||||
(void)scopy(tmp_p, CHF_MESSAGE_TERMINATOR, tmp_end);
|
||||
|
||||
return chf_context.message_buffer;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfInit
|
||||
.kind : C function
|
||||
.creation : 13-May-1996
|
||||
.description :
|
||||
This function initializes CHF and returns to the caller a condition code;
|
||||
that code will be either CHF_S_OK if the initialization was succesful,
|
||||
or one of the other values listed below.
|
||||
|
||||
It's necessary to invoke succesfully ChfInit() before using any other CHF
|
||||
function.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
|
||||
if CHF has already been initialized before.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_PTHREAD
|
||||
if a pthread operation fails.
|
||||
|
||||
.call :
|
||||
cc = ChfInit(app_name, options,
|
||||
mrs_data, mrs_get, mrs_exit,
|
||||
condition_stack_size, handler_stack_size,
|
||||
exit_code);
|
||||
.input :
|
||||
const char *app_name, Application's name
|
||||
const ChfOptions options, Options
|
||||
void *mrs_data, Message retrieval private data
|
||||
ChfMrsGet mrs_get, 'GetMessage' function
|
||||
ChfMrsExit mrs_exit, 'Exit' function
|
||||
const int condition_stack_size, Size of the condition stack
|
||||
const int handler_stack_size, Size of the handler stack
|
||||
const int exit_code, Abnormal exit code
|
||||
.output :
|
||||
int cc, condition code
|
||||
.status_codes :
|
||||
CHF_F_MALLOC, FATAL, dynamic memory allocation failed
|
||||
.notes :
|
||||
1.1, 13-May-1996, creation
|
||||
1.6, 15-Jan-1997, update:
|
||||
- updated the call to ChfPushHandler() to accomodate its new interface.
|
||||
2.1, 19-May-2000, update:
|
||||
- added multithreading support
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support; a malloc() call was not portable.
|
||||
|
||||
.- */
|
||||
int ChfInit( /* Generic initialization */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
void *mrs_data, /* Message retrieval private data */
|
||||
ChfMrsGet mrs_get, /* 'GetMessage' function */
|
||||
ChfMrsExit mrs_exit, /* 'Exit' function */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
)
|
||||
{
|
||||
int cc;
|
||||
|
||||
/* Check that CHF has not been initialized yet */
|
||||
#ifndef _REENTRANT
|
||||
if(_chf_context.state != CHF_UNKNOWN) ChfAbort(CHF_ABORT_DUP_INIT);
|
||||
#else
|
||||
/* Reentrant check; lock context_mutex first */
|
||||
if(pthread_mutex_lock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
if(_chf_context.state != CHF_UNKNOWN)
|
||||
{
|
||||
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
ChfAbort(CHF_ABORT_DUP_INIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _REENTRANT
|
||||
if((_chf_context.condition_stack =
|
||||
(ChfDescriptor *)
|
||||
malloc((size_t)(condition_stack_size+1)*sizeof(ChfDescriptor))) ==
|
||||
CHF_NULL_DESCRIPTOR)
|
||||
cc = CHF_F_MALLOC;
|
||||
|
||||
else if((_chf_context.handler_stack =
|
||||
(ChfHandlerDescriptor *)
|
||||
malloc((size_t)handler_stack_size*sizeof(ChfHandlerDescriptor))) ==
|
||||
(ChfHandlerDescriptor *)NULL)
|
||||
{
|
||||
free(_chf_context.condition_stack);
|
||||
cc = CHF_F_MALLOC;
|
||||
}
|
||||
|
||||
else if((_chf_context.message_buffer =
|
||||
(ChfChar *)malloc(
|
||||
(size_t)(CHF_MAX_MESSAGE_LENGTH) * sizeof(ChfChar))) == (ChfChar *)NULL)
|
||||
{
|
||||
free(_chf_context.condition_stack);
|
||||
free(_chf_context.handler_stack);
|
||||
cc = CHF_F_MALLOC;
|
||||
}
|
||||
|
||||
else
|
||||
#else
|
||||
/* Reentrant init: condition_stack, handler_stack, message_buffer
|
||||
are not needed in the master Chf context.
|
||||
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);
|
||||
#endif
|
||||
|
||||
cc = CHF_S_OK;
|
||||
}
|
||||
|
||||
#ifdef _REENTRANT
|
||||
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
#endif
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfExit
|
||||
.kind : C function
|
||||
.creation : 24-May-1996
|
||||
.description :
|
||||
This function shuts down CHF and returns nothing to the caller; after
|
||||
calling ChfExit() the application can continue, but any subsequent call
|
||||
to any other CHF function, except the inizialization functions, will abort
|
||||
the application using 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.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_PTHREAD
|
||||
if a pthread operation fails.
|
||||
|
||||
.call :
|
||||
ChfExit();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 24-May-1996, creation
|
||||
2.1, 19-May-2000, update:
|
||||
- added multithreading support
|
||||
|
||||
.- */
|
||||
void ChfExit(
|
||||
void
|
||||
)
|
||||
{
|
||||
/* Check that CHF has been correctly initialized */
|
||||
#ifndef _REENTRANT
|
||||
if(_chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
#else
|
||||
/* Reentrant check; lock context_mutex first */
|
||||
if(pthread_mutex_lock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
if(_chf_context.state == CHF_UNKNOWN)
|
||||
{
|
||||
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
ChfAbort(CHF_ABORT_INIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Destroy the context associated with this thread now; this is necessary
|
||||
to ensure that the context is actually destroyed when a single-threaded
|
||||
application links with the multithreaded version of Chf: in this case,
|
||||
pthread_exit() is called *after* ChfExit(), the Chf data key no longer
|
||||
exists when pthread_exit() is called and the destructor registered
|
||||
with pthread_key_create() does not take place.
|
||||
The data pointer associated with the Chf data key is set to NULL to
|
||||
avoid any subsequent reactivation of the destructor.
|
||||
*/
|
||||
#ifdef _REENTRANT
|
||||
DestroyContext(&chf_context);
|
||||
if(pthread_setspecific(data_key, (void *)NULL))
|
||||
{
|
||||
(void)pthread_mutex_unlock(&context_mutex);
|
||||
ChfAbort(CHF_ABORT_PTHREAD);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shut down the message retrieval subsystem first */
|
||||
_chf_context.mrs_exit(_chf_context.mrs_data);
|
||||
|
||||
#ifndef _REENTRANT
|
||||
/* Free the dynamic memory previously allocated */
|
||||
free(_chf_context.message_buffer);
|
||||
free(_chf_context.handler_stack);
|
||||
free(_chf_context.condition_stack);
|
||||
#else
|
||||
/* Destroy the Chf data key */
|
||||
if(pthread_key_delete(data_key)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
#endif
|
||||
|
||||
/* Reset CHF state to prevent subsequent calls to ChfExit() itself */
|
||||
_chf_context.state = CHF_UNKNOWN;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
if(pthread_mutex_unlock(&context_mutex)) ChfAbort(CHF_ABORT_PTHREAD);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : _ChfGetContext
|
||||
.kind : C function
|
||||
.creation : 19-May-2000
|
||||
.description :
|
||||
This function dynamically primes a new Chf context for the calling
|
||||
thread (if necessary), and returns a pointer to that context to
|
||||
the caller. If something does wrong, it aborts the application
|
||||
with ChfAbort(CHF_ABORT_GET_CONTEXT).
|
||||
|
||||
Results are unpredictable if this function is called before a
|
||||
successful call to ChfInit().
|
||||
|
||||
.call :
|
||||
context = _ChfGetContext(void);
|
||||
.input :
|
||||
.output :
|
||||
ChfContext *context, per-thread Chf context
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
2.1, 19-May-2000, creation
|
||||
|
||||
.- */
|
||||
ChfContext *_ChfGetContext(
|
||||
void
|
||||
)
|
||||
{
|
||||
ChfContext *context;
|
||||
|
||||
#ifndef _REENTRANT
|
||||
/* This function is doomed to fail if _REENTRANT is not defined */
|
||||
ChfAbort(CHF_ABORT_GET_CONTEXT);
|
||||
return((ChfContext *)NULL);
|
||||
#else
|
||||
/* Get the thread-specific context pointer associated with the
|
||||
CHF data key */
|
||||
if((context = (ChfContext *)pthread_getspecific(data_key))
|
||||
== (ChfContext *)NULL)
|
||||
{
|
||||
/* No context pointer; prime a new one, cloning the master context */
|
||||
if((context = (ChfContext *)malloc(sizeof(ChfContext)))
|
||||
== (ChfContext *)NULL)
|
||||
ChfAbort(CHF_ABORT_GET_CONTEXT);
|
||||
|
||||
memcpy(context, &_chf_context, sizeof(ChfContext));
|
||||
|
||||
/* Allocate per-thread stacks and message buffer */
|
||||
if((context->condition_stack =
|
||||
(ChfDescriptor *)
|
||||
malloc((size_t)(context->condition_stack_size+1)
|
||||
*sizeof(ChfDescriptor))) == CHF_NULL_DESCRIPTOR)
|
||||
ChfAbort(CHF_ABORT_GET_CONTEXT);
|
||||
|
||||
if((context->handler_stack =
|
||||
(ChfHandlerDescriptor *)
|
||||
malloc((size_t)(context->handler_stack_size)
|
||||
*sizeof(ChfHandlerDescriptor))) == (ChfHandlerDescriptor *)NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return context;
|
||||
#endif
|
||||
}
|
201
Chf/chf_msgc.c
Normal file
201
Chf/chf_msgc.c
Normal file
|
@ -0,0 +1,201 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_msgc.c,v 2.2 2001/01/25 14:06:47 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_msgc.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 17-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module contains the CHF initialization function ChfMsgcatInit()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_msgc.c,v $
|
||||
Revision 2.2 2001/01/25 14:06:47 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 1.3 1996/06/21 14:19:22 cibrario
|
||||
Bug fix: the private context of the message retrieval facility was
|
||||
never freed by ExitMessage()
|
||||
|
||||
Revision 1.1 1996/05/28 12:55:15 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_msgc.c,v 2.2 2001/01/25 14:06:47 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include <locale.h>
|
||||
#include <nl_types.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global and static variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef struct
|
||||
{
|
||||
nl_catd catalog; /* Message catalog descriptor */
|
||||
}
|
||||
ChfMsgcatContext;
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
static const char *GetMessage(
|
||||
void *private_context,
|
||||
const int module_id,
|
||||
const int condition_code,
|
||||
const char *default_message
|
||||
)
|
||||
{
|
||||
return(catgets(((ChfMsgcatContext *)private_context)->catalog, module_id,
|
||||
condition_code, default_message));
|
||||
}
|
||||
|
||||
static void ExitMessage(
|
||||
void *private_context
|
||||
)
|
||||
{
|
||||
(void)catclose(((ChfMsgcatContext *)private_context)->catalog);
|
||||
free(private_context);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfMsgcatInit
|
||||
.kind : C function
|
||||
.creation : 17-May-1996
|
||||
.description :
|
||||
This function initializes CHF and returns to the caller a condition code;
|
||||
that code will be either CHF_S_OK if the initialization was succesful,
|
||||
or one of the other values listed below.
|
||||
|
||||
It's necessary to invoke succesfully either ChfMsgcatInit() or one of the
|
||||
other CHF initialization routines before using any other CHF function.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
|
||||
if CHF has already been initialized before.
|
||||
|
||||
WIN32:
|
||||
|
||||
- this function is not available due to lack of system support, and
|
||||
always returns CHF_F_NOT_AVAILABLE
|
||||
|
||||
.call :
|
||||
cc = ChfMsgcatInit(app_name, options,
|
||||
msgcat_name,
|
||||
condition_stack_size, handler_stack_size,
|
||||
exit_code);
|
||||
.input :
|
||||
const char *app_name, Application's name
|
||||
const ChfOptions options, Options
|
||||
const char *msgcat_name, Name of the message catalog
|
||||
const int condition_stack_size, Size of the condition stack
|
||||
const int handler_stack_size, Size of the handler stack
|
||||
const int exit_code, Abnormal exit code
|
||||
.output :
|
||||
int cc, condition code
|
||||
.status_codes :
|
||||
CHF_F_SETLOCALE, setlocale() failed
|
||||
CHF_F_CATOPEN, catopen() failed
|
||||
CHF_F_MALLOC, FATAL, memory allocation failed
|
||||
CHF_F_NOT_AVAILABLE, FATAL, function not available
|
||||
.notes :
|
||||
1.1, 17-May-1996, creation
|
||||
2.2, 22-Jan-2001, update:
|
||||
- added Win32 support
|
||||
|
||||
.- */
|
||||
int ChfMsgcatInit( /* Initialization with msgcat subsystem */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfChar *msgcat_name, /* Name of the message catalog */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
/* This function always fails in _WIN32, because message catalogs
|
||||
are not supported.
|
||||
*/
|
||||
return CHF_F_NOT_AVAILABLE;
|
||||
|
||||
#else
|
||||
ChfMsgcatContext *private_context;
|
||||
int cc;
|
||||
|
||||
if((private_context =
|
||||
(ChfMsgcatContext *)malloc(sizeof(ChfMsgcatContext))) ==
|
||||
(ChfMsgcatContext *)NULL)
|
||||
cc = CHF_F_MALLOC;
|
||||
|
||||
else if(setlocale(LC_ALL, "") == (char *)NULL)
|
||||
{
|
||||
free(private_context);
|
||||
cc = CHF_F_SETLOCALE;
|
||||
}
|
||||
|
||||
else if((private_context->catalog = catopen(msgcat_name, 0)) ==
|
||||
(nl_catd)(-1))
|
||||
{
|
||||
free(private_context);
|
||||
cc = CHF_F_CATOPEN;
|
||||
}
|
||||
|
||||
else if((cc = ChfInit(app_name, options, (void *)private_context,
|
||||
GetMessage, ExitMessage, condition_stack_size, handler_stack_size,
|
||||
exit_code)) != CHF_S_OK)
|
||||
{
|
||||
(void)catclose(private_context->catalog);
|
||||
free(private_context);
|
||||
}
|
||||
|
||||
else
|
||||
cc = CHF_S_OK;
|
||||
|
||||
return cc;
|
||||
|
||||
#endif
|
||||
}
|
402
Chf/chf_sig.c
Normal file
402
Chf/chf_sig.c
Normal file
|
@ -0,0 +1,402 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_sig.c,v 2.2 2001/01/25 14:07:42 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_sig.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 3-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the condition signalling function of CHF
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_sig.c,v $
|
||||
Revision 2.2 2001/01/25 14:07:42 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 2.1 2000/05/26 14:31:28 cibrario
|
||||
- Fixed spelling of CHF_SIGNALLING -> CHF_SIGNALING
|
||||
- Replaced longjmp() with siglongjmp()
|
||||
- New ChfAction code CHF_UNWIND_KEEP: ChfSignal() unwinds the
|
||||
execution stack, but keeps the topmost condition group on the
|
||||
condition stack
|
||||
|
||||
Revision 1.6 1997/01/15 13:34:45 cibrario
|
||||
Fixed a wrong adjustment of the condition handler stack pointer after
|
||||
an unwind operation.
|
||||
Updated the condition handler calls in order to pass to the handlers the
|
||||
private handler context pointer.
|
||||
|
||||
Revision 1.1 1996/05/28 12:55:51 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_sig.c,v 2.2 2001/01/25 14:07:42 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfSignal
|
||||
.kind : C function
|
||||
.creation : 10-May-1996
|
||||
.description :
|
||||
This function signals the topmost condition group currently in the
|
||||
condition stack, and performs the actions requested by the condition
|
||||
handlers.
|
||||
|
||||
NOTE: This function uses the CHF function 'ChfAbort()' to
|
||||
abort the application if either
|
||||
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
|
||||
- the last handler on the handler stack has returned an invalid action
|
||||
code (abort code CHF_ABORT_INVALID_ACTION)
|
||||
- one of the handlers has requested the CHF_UNWIND action while
|
||||
CHF was already unwinding (abort code CHF_ABORT_ALREADY_UNWINDING)
|
||||
- a CHF_FATAL condition was signalled while CHF was unwinding
|
||||
(abort code CHF_ABORT_FATAL_UNWINDING)
|
||||
- all the handlers refused to handle a condition (abort code
|
||||
CHF_ABORT_IMPROPERLY_HANDLED)
|
||||
|
||||
.call :
|
||||
ChfSignal();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
(*) CHF_F_COND_STACK_FULL, the condition stack is full
|
||||
(*) CHF_F_INVALID_ACTION, invalid handler action (%d)
|
||||
.notes :
|
||||
1.1, 10-May-1996, creation
|
||||
1.6, 15-Jan-1997, update & bug fix:
|
||||
- fixed a wrong adjustment of the condition handler stack pointer after
|
||||
an unwind operation.
|
||||
- updated the condition handler calls in order to pass to the handlers the
|
||||
private handler context pointer, too.
|
||||
2.1, 19-May-2000, update:
|
||||
- added support for structured condition handling
|
||||
|
||||
.- */
|
||||
void ChfSignal(
|
||||
void
|
||||
)
|
||||
{
|
||||
ChfState saved_state;
|
||||
ChfDescriptor *saved_condition_base;
|
||||
ChfDescriptor *current_condition;
|
||||
ChfHandlerDescriptor *saved_handler_sp;
|
||||
ChfHandlerDescriptor *handler_up;
|
||||
ChfHandlerDescriptor *unwind_handler;
|
||||
ChfAction handler_result;
|
||||
|
||||
/* 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
|
||||
CHF_UNWINDING change to CHF_SIGNAL_UNWINDING, otherwise remain in the
|
||||
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;
|
||||
saved_condition_base = chf_context.condition_base;
|
||||
chf_context.condition_base = chf_context.condition_sp;
|
||||
|
||||
/* Save the current condition handler pointer */
|
||||
saved_handler_sp = chf_context.handler_sp;
|
||||
|
||||
/* Call the condition handlers; the loop will exit either:
|
||||
- when the handler stack is empty, or
|
||||
- when the current handler returns either CHF_CONTINUE or CHF_UNWIND
|
||||
*/
|
||||
handler_result = CHF_RESIGNAL;
|
||||
while(handler_result == CHF_RESIGNAL &&
|
||||
chf_context.handler_sp > chf_context.handler_stack)
|
||||
{
|
||||
chf_context.handler_sp--;
|
||||
|
||||
/* The current condition handler, described by chf_context.handler_sp,
|
||||
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 signal 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 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().
|
||||
|
||||
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 */
|
||||
chf_context.state = saved_state;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfDiscard
|
||||
.kind : C function
|
||||
.creation : 17-May-1996
|
||||
.description :
|
||||
This function discards the topmost condition group currently in the
|
||||
condition stack, without signalling it. The function does nothing if
|
||||
the condition stack is empty.
|
||||
|
||||
NOTE: This function uses the CHF function 'ChfAbort()' to
|
||||
abort the application if either
|
||||
- CHF has not been initialized correctly (abort code CHF_ABORT_INIT)
|
||||
|
||||
.call :
|
||||
ChfDiscard();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
none
|
||||
.notes :
|
||||
1.1, 17-May-1996, creation
|
||||
|
||||
.- */
|
||||
void ChfDiscard( /* Discard the current conditions */
|
||||
void
|
||||
)
|
||||
{
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
/* Reset the current condition stack pointer to the current condition
|
||||
stack base pointer
|
||||
*/
|
||||
chf_context.condition_sp = chf_context.condition_base;
|
||||
}
|
227
Chf/chf_st.c
Normal file
227
Chf/chf_st.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_st.c,v 2.2 2001/01/25 14:08:45 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_st.c,v $, condition generation
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 24-May-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF initialization function ChfStaticInit()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_st.c,v $
|
||||
Revision 2.2 2001/01/25 14:08:45 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 1.1 1996/05/28 12:56:14 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_st.c,v 2.2 2001/01/25 14:08:45 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global and static variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ChfTable *table;
|
||||
size_t size;
|
||||
}
|
||||
ChfStaticContext;
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Win32 does not have bsearch();
|
||||
provide a simple one from glibc here.
|
||||
*/
|
||||
static void *bsearch(
|
||||
const void *key,
|
||||
const void *base,
|
||||
size_t nmemb,
|
||||
size_t size,
|
||||
int (*compar)(const void *, const void *)
|
||||
)
|
||||
{
|
||||
size_t l, u, idx;
|
||||
const void *p;
|
||||
int comparison;
|
||||
|
||||
l = 0;
|
||||
u = nmemb;
|
||||
while (l < u)
|
||||
{
|
||||
idx = (l + u) / 2;
|
||||
p = (void *) (((const char *) base) + (idx * size));
|
||||
comparison = (*compar) (key, p);
|
||||
if (comparison < 0)
|
||||
u = idx;
|
||||
else if (comparison > 0)
|
||||
l = idx + 1;
|
||||
else
|
||||
return (void *) p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define GT 1
|
||||
#define LT -1
|
||||
#define EQ 0
|
||||
|
||||
static int Search(
|
||||
const void *l,
|
||||
const void *r
|
||||
)
|
||||
{
|
||||
if(((ChfTable *)l)->module > ((ChfTable *)r)->module)
|
||||
return(GT);
|
||||
|
||||
else if(((ChfTable *)l)->module < ((ChfTable *)r)->module)
|
||||
return(LT);
|
||||
|
||||
else if(((ChfTable *)l)->code > ((ChfTable *)r)->code)
|
||||
return(GT);
|
||||
|
||||
else if(((ChfTable *)l)->code < ((ChfTable *)r)->code)
|
||||
return(LT);
|
||||
|
||||
return(EQ);
|
||||
}
|
||||
|
||||
static const ChfChar *StGetMessage(
|
||||
void *private_context,
|
||||
const int module_id,
|
||||
const int condition_code,
|
||||
const ChfChar *default_message
|
||||
)
|
||||
{
|
||||
ChfTable key;
|
||||
ChfTable *res;
|
||||
|
||||
key.module = module_id;
|
||||
key.code = condition_code;
|
||||
|
||||
if((res = bsearch(&key, ((ChfStaticContext *)private_context)->table,
|
||||
((ChfStaticContext *)private_context)->size, sizeof(ChfTable), Search)) ==
|
||||
(void *)NULL)
|
||||
return(default_message);
|
||||
|
||||
return(((ChfTable *)res)->msg_template);
|
||||
}
|
||||
|
||||
static void ExitMessage(
|
||||
void *private_context
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfStaticInit
|
||||
.kind : C function
|
||||
.creation : 24-May-1996
|
||||
.description :
|
||||
This function initializes CHF and returns to the caller a condition code;
|
||||
that code will be either CHF_S_OK if the initialization was succesful,
|
||||
or one of the other values listed below.
|
||||
|
||||
It's necessary to invoke succesfully either ChfStaticInit() or one of the
|
||||
other CHF initialization routines before using any other CHF function.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
|
||||
if CHF has already been initialized before.
|
||||
|
||||
.call :
|
||||
cc = ChfStaticInit(app_name, options,
|
||||
table, table_size,
|
||||
condition_stack_size, handler_stack_size,
|
||||
exit_code);
|
||||
.input :
|
||||
const char *app_name, Application's name
|
||||
const ChfOptions options, Options
|
||||
const ChfTable *table, pointer to the static message table
|
||||
const size_t table_size, size of the table (# of entries)
|
||||
const int condition_stack_size, Size of the condition stack
|
||||
const int handler_stack_size, Size of the handler stack
|
||||
const int exit_code, Abnormal exit code
|
||||
.output :
|
||||
int cc, condition code
|
||||
.status_codes :
|
||||
CHF_F_MALLOC, FATAL, memory allocation failed
|
||||
.notes :
|
||||
1.1, 27-May-1996, creation
|
||||
|
||||
.- */
|
||||
int ChfStaticInit( /* Initialization with static message tables */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
const ChfTable *table, /* Static message table */
|
||||
const size_t table_size, /* Size of the message table */
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
)
|
||||
{
|
||||
ChfStaticContext *private_context;
|
||||
int cc;
|
||||
|
||||
if((private_context =
|
||||
(ChfStaticContext *)malloc(sizeof(ChfStaticContext))) ==
|
||||
(ChfStaticContext *)NULL)
|
||||
cc = CHF_F_MALLOC;
|
||||
|
||||
else if((cc = ChfInit(app_name, options, (void *)private_context,
|
||||
StGetMessage, ExitMessage, condition_stack_size, handler_stack_size,
|
||||
exit_code)) != CHF_S_OK)
|
||||
free(private_context);
|
||||
|
||||
else
|
||||
{
|
||||
private_context->table = table;
|
||||
private_context->size = table_size;
|
||||
cc = CHF_S_OK;
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
115
Chf/chf_top.c
Normal file
115
Chf/chf_top.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_top.c,v 2.2 2001/01/25 14:09:21 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_top.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 5-Jun-1996
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the CHF function ChfGetTopCondition()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_top.c,v $
|
||||
Revision 2.2 2001/01/25 14:09:21 cibrario
|
||||
Added partial Win32 support (Windows CE only).
|
||||
|
||||
Revision 2.1 2000/05/26 14:23:33 cibrario
|
||||
ChfGetTopCondition() used to return a pointer to the wrong condition
|
||||
descriptor; fixed.
|
||||
|
||||
Revision 1.2 1996/06/11 12:47:17 cibrario
|
||||
file creation
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_top.c,v 2.2 2001/01/25 14:09:21 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfGetTopCondition
|
||||
.kind : C function
|
||||
.creation : 5-Jun-1996
|
||||
.description :
|
||||
This function returns to the caller a pointer to the top condition of
|
||||
the current condition group. It generates and immediately signals the
|
||||
condition CHF_F_BAD_STATE if the current condition group is empty.
|
||||
|
||||
|
||||
NOTE: During condition signalling, CHF creates a new, empty, condition group
|
||||
immediately before starting the invocation sequence of the condition
|
||||
handlers, as described in the documentation. Therefore
|
||||
ChfGetTopCondition(), if called from a condition handler, will return
|
||||
a pointer to the top condition generated during the handling ONLY, and
|
||||
NOT to the top condition of the condition group being signalled. The
|
||||
latter pointer is directly available, as an argument, to the condition
|
||||
handlers.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_INIT
|
||||
if CHF hasn't been correctly initialized.
|
||||
|
||||
NOTE: The returned pointer is no longer valid when any other CHF function
|
||||
is called after ChfGetTopCondition().
|
||||
|
||||
.call :
|
||||
d = ChfGetTopCondition();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
const ChfDescriptor *d, condition descriptor
|
||||
.status_codes :
|
||||
|
||||
.notes :
|
||||
1.2, 17-May-1996, creation
|
||||
2.1, 24-May-2000, bug fix:
|
||||
- condition stack referenced incorrectly
|
||||
|
||||
.- */
|
||||
const ChfDescriptor *ChfGetTopCondition( /* Retrieve top condition */
|
||||
void
|
||||
)
|
||||
{
|
||||
ChfDescriptor *d;
|
||||
|
||||
/* Check that CHF has been correctly initialized */
|
||||
if(chf_context.state == CHF_UNKNOWN) ChfAbort(CHF_ABORT_INIT);
|
||||
|
||||
if((d = chf_context.condition_sp) == chf_context.condition_base)
|
||||
{
|
||||
ChfCondition CHF_F_BAD_STATE, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* The top element of the condition group is the element immediately
|
||||
below the stack pointer.
|
||||
*/
|
||||
return d-1;
|
||||
}
|
191
Chf/chf_win32.c
Normal file
191
Chf/chf_win32.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
/* .+
|
||||
|
||||
.identifier : $Id: chf_win32.c,v 2.2 2001/01/25 14:11:58 cibrario Exp $
|
||||
.context : CHF, Condition Handling Facility
|
||||
.title : $RCSfile: chf_win32.c,v $, Win32 initialization function
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 19-Jan-2001
|
||||
.keywords : *
|
||||
.description :
|
||||
This module contains the CHF initialization function ChfWin32Init()
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: chf_win32.c,v $
|
||||
Revision 2.2 2001/01/25 14:11:58 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: chf_win32.c,v 2.2 2001/01/25 14:11:58 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "Chf.h"
|
||||
#include "ChfPriv.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Global and static variables
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private type definitions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef struct
|
||||
{
|
||||
HINSTANCE instance; /* App. instance handle */
|
||||
ChfChar buffer[CHF_MAX_MESSAGE_LENGTH]; /* Temporary buffer */
|
||||
}
|
||||
ChfWin32Context;
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Private functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
static const ChfChar *Win32GetMessage(
|
||||
void *private_context,
|
||||
const int module_id,
|
||||
const int condition_code,
|
||||
const ChfChar *default_message
|
||||
)
|
||||
{
|
||||
if(!LoadString(
|
||||
((ChfWin32Context *)private_context)->instance,
|
||||
module_id*1000 + condition_code,
|
||||
((ChfWin32Context *)private_context)->buffer,
|
||||
CHF_MAX_MESSAGE_LENGTH-1))
|
||||
return default_message;
|
||||
|
||||
return ((ChfWin32Context *)private_context)->buffer;
|
||||
}
|
||||
|
||||
static void ExitMessage(
|
||||
void *private_context
|
||||
)
|
||||
{
|
||||
free(private_context);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
Public functions
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ChfWin32Init
|
||||
.kind : C function
|
||||
.creation : 19-Jan-2001
|
||||
.description :
|
||||
This function initializes CHF and returns to the caller a condition code;
|
||||
that code will be either CHF_S_OK if the initialization was succesful,
|
||||
or one of the other values listed below.
|
||||
|
||||
It's necessary to invoke succesfully either ChfWin32Init() or one of the
|
||||
other CHF initialization routines before using any other CHF function.
|
||||
|
||||
NOTE: This function will call ChfAbort() with abort code CHF_ABORT_DUP_INIT
|
||||
if CHF has already been initialized before.
|
||||
|
||||
WIN32:
|
||||
|
||||
- This function is available in Win32 only; it will return
|
||||
CHF_F_NOT_AVAILABLE on Unix platforma.
|
||||
|
||||
- message retrieval is done through the LoadString() Win32 function.
|
||||
This function does not support message sets, so the linear message id
|
||||
passed to it is made by module_id*1000 + condition_code. The following
|
||||
limits are in effect:
|
||||
0 <= condition_code <= 999
|
||||
0 <= module_id <= 64
|
||||
|
||||
.call :
|
||||
cc = ChfWin32Init(app_name, options,
|
||||
msgcat_name,
|
||||
condition_stack_size, handler_stack_size,
|
||||
exit_code);
|
||||
.input :
|
||||
const ChfChar *app_name, Application's name
|
||||
const ChfOptions options, Options
|
||||
HINSTANCE instance, App. instance handle
|
||||
const int condition_stack_size, Size of the condition stack
|
||||
const int handler_stack_size, Size of the handler stack
|
||||
const int exit_code, Abnormal exit code
|
||||
.output :
|
||||
int cc, condition code
|
||||
.status_codes :
|
||||
CHF_F_MALLOC, FATAL, memory allocation failed
|
||||
CHF_F_NOT_AVAILABLE, FATAL, function not available
|
||||
.notes :
|
||||
2.2, 19-Jan-2001, creation
|
||||
|
||||
.- */
|
||||
int ChfWin32Init( /* Initialization within _WIN32 */
|
||||
const ChfChar *app_name, /* Application's name */
|
||||
const ChfOptions options, /* Options */
|
||||
#ifndef _WIN32
|
||||
void *instance, /* Fake arguments */
|
||||
#else
|
||||
HINSTANCE instance, /* App. instance handle */
|
||||
#endif
|
||||
const int condition_stack_size, /* Size of the condition stack */
|
||||
const int handler_stack_size, /* Size of the handler stack */
|
||||
const int exit_code /* Abnormal exit code */
|
||||
)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
/* This function is available only in Win32 */
|
||||
return CHF_F_NOT_AVAILABLE;
|
||||
|
||||
#else
|
||||
ChfWin32Context *private_context;
|
||||
int cc;
|
||||
|
||||
if((private_context =
|
||||
(ChfWin32Context *)malloc(sizeof(ChfWin32Context))) ==
|
||||
(ChfWin32Context *)NULL)
|
||||
cc = CHF_F_MALLOC;
|
||||
|
||||
else if((cc = ChfInit(app_name, options, (void *)private_context,
|
||||
Win32GetMessage, ExitMessage, condition_stack_size, handler_stack_size,
|
||||
exit_code)) != CHF_S_OK)
|
||||
{
|
||||
free(private_context);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Save Win32 specific context items into private Chf context */
|
||||
private_context->instance = instance;
|
||||
|
||||
cc = CHF_S_OK;
|
||||
}
|
||||
|
||||
return cc;
|
||||
|
||||
#endif
|
||||
}
|
485
Chf/libChf.vcp
Executable file
485
Chf/libChf.vcp
Executable file
|
@ -0,0 +1,485 @@
|
|||
# Microsoft eMbedded Visual Tools Project File - Name="libChf" - Package Owner=<4>
|
||||
# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (WCE x86em) Static Library" 0x7f04
|
||||
# TARGTYPE "Win32 (WCE ARM) Static Library" 0x8504
|
||||
|
||||
CFG=libChf - Win32 (WCE ARM) Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "libChf.vcn".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "libChf.vcn" CFG="libChf - Win32 (WCE ARM) Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "libChf - Win32 (WCE ARM) Release" (based on "Win32 (WCE ARM) Static Library")
|
||||
!MESSAGE "libChf - Win32 (WCE ARM) Debug" (based on "Win32 (WCE ARM) Static Library")
|
||||
!MESSAGE "libChf - Win32 (WCE x86em) Release" (based on "Win32 (WCE x86em) Static Library")
|
||||
!MESSAGE "libChf - Win32 (WCE x86em) Debug" (based on "Win32 (WCE x86em) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
# PROP ATL_Project 2
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "ARMRel"
|
||||
# PROP BASE Intermediate_Dir "ARMRel"
|
||||
# PROP BASE CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "ARMRel"
|
||||
# PROP Intermediate_Dir "ARMRel"
|
||||
# PROP CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=clarm.exe
|
||||
# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "NDEBUG" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /Oxs /M$(CECrtMT) /c
|
||||
# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "NDEBUG" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /Oxs /M$(CECrtMT) /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "ARMDbg"
|
||||
# PROP BASE Intermediate_Dir "ARMDbg"
|
||||
# PROP BASE CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "ARMDbg"
|
||||
# PROP Intermediate_Dir "ARMDbg"
|
||||
# PROP CPU_ID "{D6518FFC-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=clarm.exe
|
||||
# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /M$(CECrtMTDebug) /c
|
||||
# ADD CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_LIB" /YX /M$(CECrtMTDebug) /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "X86EMRel"
|
||||
# PROP BASE Intermediate_Dir "X86EMRel"
|
||||
# PROP BASE CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "X86EMRel"
|
||||
# PROP Intermediate_Dir "X86EMRel"
|
||||
# PROP CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_LIB" /YX /Oxs /Gz /c
|
||||
# ADD CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_LIB" /YX /Oxs /Gz /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "X86EMDbg"
|
||||
# PROP BASE Intermediate_Dir "X86EMDbg"
|
||||
# PROP BASE CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "X86EMDbg"
|
||||
# PROP Intermediate_Dir "X86EMDbg"
|
||||
# PROP CPU_ID "{D6518FF4-710F-11D3-99F2-00105A0DF099}"
|
||||
# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
|
||||
# PROP Target_Dir ""
|
||||
CPP=cl.exe
|
||||
# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_LIB" /YX /Gz /c
|
||||
# ADD CPP /nologo /W3 /Zi /Od /D "DEBUG" /D _WIN32_WCE=$(CEVersion) /D "WIN32" /D "STRICT" /D "_WIN32_WCE_EMULATION" /D "INTERNATIONAL" /D "USA" /D "INTLMSG_CODEPAGE" /D "$(CePlatform)" /D "i486" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_LIB" /FR /YX /Gz /c
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "libChf - Win32 (WCE ARM) Release"
|
||||
# Name "libChf - Win32 (WCE ARM) Debug"
|
||||
# Name "libChf - Win32 (WCE x86em) Release"
|
||||
# Name "libChf - Win32 (WCE x86em) Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_abrt.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_A=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_gen.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_G=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_hdlr.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_H=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_init.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_I=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_msgc.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_M=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_sig.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_S=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_st.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_ST=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_top.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_T=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf_win32.c
|
||||
|
||||
!IF "$(CFG)" == "libChf - Win32 (WCE ARM) Release"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE ARM) Debug"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Release"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ELSEIF "$(CFG)" == "libChf - Win32 (WCE x86em) Debug"
|
||||
|
||||
DEP_CPP_CHF_W=\
|
||||
".\Chf.h"\
|
||||
".\ChfPriv.h"\
|
||||
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Chf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChfPriv.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "rc"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\chf.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
15
Chf/resource.h
Executable file
15
Chf/resource.h
Executable file
|
@ -0,0 +1,15 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by chf.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
93
Chf/test01.c
Normal file
93
Chf/test01.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* $Id: test01.c,v 2.1 2000/05/29 13:55:50 cibrario Rel $
|
||||
Chf test program.
|
||||
Simple initialization.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
puts("test01");
|
||||
|
||||
system("gencat test01.cat test01.msf");
|
||||
system("gencat test01.cat chf.msf");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
/* ChfGetMessage:
|
||||
message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not
|
||||
*/
|
||||
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1");
|
||||
if(strcmp(msg, "Set_255,Message_1")) 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 */
|
||||
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 3
|
||||
|| d->severity != CHF_WARNING
|
||||
|| 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 */
|
||||
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
|
||||
|
||||
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
e->module_id != CHF_MODULE_ID
|
||||
|| e->condition_code != 4
|
||||
|| e->severity != CHF_INFO
|
||||
|| 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 */
|
||||
ChfDiscard();
|
||||
|
||||
/* This is line 77 */
|
||||
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 5
|
||||
|| d->severity != CHF_ERROR
|
||||
|| 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 */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
18
Chf/test01.msf
Normal file
18
Chf/test01.msf
Normal file
|
@ -0,0 +1,18 @@
|
|||
$set 1
|
||||
255 Chf Test
|
||||
|
||||
$set 255
|
||||
1 Set_255,Message_1
|
||||
3 Set_255,Arg_%d,Message_3
|
||||
4 Set_255,Arg_%s,Message_4
|
||||
5 Set_255,Arg_%d-%d,Message_5
|
||||
6 Set_255,Message_6 (thread %d, sub-condition)
|
||||
7 Set_255,Message_7 (thread %d, main)
|
||||
8 Set_255,Message_8 (thread %d, main)
|
||||
9 Set_255,Message_9
|
||||
|
||||
10 Invalid descriptor link detected
|
||||
11 Bad hdlr stack push count %d; should be %d
|
||||
12 Bad cond stack push count %d; should be %d
|
||||
|
||||
20 Structured exc handling test cond
|
121
Chf/test02.c
Normal file
121
Chf/test02.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/* $Id: test02.c,v 2.1 2000/05/29 13:56:44 cibrario Rel $
|
||||
Chf test program.
|
||||
Simple initialization - multithreaded.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not */
|
||||
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1");
|
||||
if(strcmp(msg, "Set_255,Message_1")) 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 */
|
||||
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 3
|
||||
|| d->severity != CHF_WARNING
|
||||
|| 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 */
|
||||
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
|
||||
|
||||
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
e->module_id != CHF_MODULE_ID
|
||||
|| e->condition_code != 4
|
||||
|| e->severity != CHF_INFO
|
||||
|| 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 */
|
||||
ChfDiscard();
|
||||
|
||||
/* This is line 67 */
|
||||
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 5
|
||||
|| d->severity != CHF_ERROR
|
||||
|| 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;
|
||||
}
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test02");
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(st = pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
printf("pthread_create: error %d", st);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(st = pthread_join(t[i], &ret))
|
||||
{
|
||||
printf("pthread_join: error %d", st);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
#endif
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
90
Chf/test03.c
Normal file
90
Chf/test03.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
/* $Id: test03.c,v 2.1 2000/05/29 13:10:29 cibrario Rel $
|
||||
Chf test program.
|
||||
Generation and signal - single and multithreaded
|
||||
|
||||
$Log: test03.c,v $
|
||||
Revision 2.1 2000/05/29 13:10:29 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* 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 7, CHF_INFO, (int)arg ChfEnd;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
ChfSignal();
|
||||
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test03");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
331
Chf/test04.c
Normal file
331
Chf/test04.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/* $Id: test04.c,v 2.1 2000/05/29 13:10:38 cibrario Rel $
|
||||
Chf test program.
|
||||
General condition handling - single and multithreaded
|
||||
|
||||
$Log: test04.c,v $
|
||||
Revision 2.1 2000/05/29 13:10:38 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
struct tdata_s
|
||||
{
|
||||
const ChfDescriptor *d, *e;
|
||||
int phase;
|
||||
};
|
||||
|
||||
ChfAction h1(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
if(c != tdata_p->e ||
|
||||
ChfGetNextDescriptor(c) != tdata_p->d)
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
else
|
||||
action = CHF_CONTINUE;
|
||||
|
||||
return action;
|
||||
|
||||
}
|
||||
|
||||
ChfAction h2(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
switch(s)
|
||||
{
|
||||
case CHF_SIGNALING:
|
||||
{
|
||||
if(c != tdata_p->e
|
||||
|| ChfGetNextDescriptor(c) != tdata_p->d
|
||||
|| (tdata_p->phase != 2 && tdata_p->phase != 4))
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
action = (ChfGetConditionCode(c) != 8 ? CHF_CONTINUE : CHF_UNWIND);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHF_UNWINDING:
|
||||
{
|
||||
if(tdata_p->phase != 4) exit(EXIT_FAILURE);
|
||||
tdata_p->phase = 5;
|
||||
action = CHF_CONTINUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
ChfAction h3(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
/* This handler must be invoked only during the first signal */
|
||||
if(tdata_p->phase != 3) exit(EXIT_FAILURE);
|
||||
|
||||
switch(s)
|
||||
{
|
||||
case CHF_SIGNALING:
|
||||
{
|
||||
if(ChfGetConditionCode(c) != 9 ||
|
||||
ChfGetNextDescriptor(c) != NULL)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
tdata_p->phase = 4;
|
||||
action = CHF_CONTINUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
ChfAction h4(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
struct tdata_s *tdata_p = (struct tdata_s *)p;
|
||||
ChfAction action;
|
||||
|
||||
/* This handler must be invoked only during the first signal */
|
||||
if(tdata_p->phase != 2) exit(EXIT_FAILURE);
|
||||
|
||||
switch(s)
|
||||
{
|
||||
case CHF_SIGNALING:
|
||||
{
|
||||
if(c != tdata_p->e
|
||||
|| ChfGetNextDescriptor(c) != tdata_p->d)
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* This generates a new group and signals it */
|
||||
tdata_p->phase = 3;
|
||||
ChfCondition 9, CHF_INFO ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
if(tdata_p->phase != 4) exit(EXIT_FAILURE);
|
||||
tdata_p->phase = 5;
|
||||
|
||||
if(c != tdata_p->e
|
||||
|| ChfGetNextDescriptor(c) != tdata_p->d)
|
||||
{
|
||||
ChfCondition 10, CHF_FATAL ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
else
|
||||
action = CHF_CONTINUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
volatile struct tdata_s tdata;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h1, NULL, (ChfPointer)(&tdata));
|
||||
|
||||
/* Generate a condition group and signal it */
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
ChfSignal();
|
||||
|
||||
/* Pop the handler */
|
||||
ChfPopHandler();
|
||||
|
||||
/* Generate a new condition group with (apparently) wrong linkage
|
||||
and signal it; this checks that the handler has actually been
|
||||
removed.
|
||||
*/
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = NULL;
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = NULL;
|
||||
ChfSignal();
|
||||
|
||||
/* Conditional unwind test */
|
||||
{
|
||||
sigjmp_buf jb;
|
||||
|
||||
tdata.phase = 0;
|
||||
if(setjmp(jb) == 0)
|
||||
{
|
||||
ChfPushHandler(h2, jb, (ChfPointer)(&tdata));
|
||||
|
||||
/* Generate a condition group and signal it */
|
||||
tdata.phase = 1;
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
/* This does not trigger an unwind */
|
||||
tdata.phase = 2;
|
||||
ChfSignal();
|
||||
|
||||
tdata.phase = 3;
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 8, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
/* This MUST trigger an unwind */
|
||||
tdata.phase = 4;
|
||||
ChfSignal();
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unwind */
|
||||
if(tdata.phase != 5)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
ChfPopHandler();
|
||||
}
|
||||
}
|
||||
|
||||
/* Condition generation and signal while a signal is in progress;
|
||||
this requires two handlers.
|
||||
*/
|
||||
{
|
||||
tdata.phase = 0;
|
||||
|
||||
ChfPushHandler(h3, NULL, (ChfPointer)&tdata);
|
||||
ChfPushHandler(h4, NULL, (ChfPointer)&tdata);
|
||||
|
||||
tdata.phase = 1;
|
||||
ChfCondition 6, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.d = ChfGetTopCondition();
|
||||
ChfCondition 7, CHF_INFO, (int)arg ChfEnd;
|
||||
tdata.e = ChfGetTopCondition();
|
||||
|
||||
tdata.phase = 2;
|
||||
ChfSignal();
|
||||
|
||||
if(tdata.phase != 5)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
ChfPopHandler();
|
||||
ChfPopHandler();
|
||||
}
|
||||
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test04");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat", 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else
|
||||
task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
247
Chf/test05.c
Normal file
247
Chf/test05.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
/* $Id: test05.c,v 2.1 2000/05/29 13:10:46 cibrario Rel $
|
||||
Chf test program.
|
||||
Condition & Handler stacks oveflow checks - single and multithreaded
|
||||
|
||||
$Log: test05.c,v $
|
||||
Revision 2.1 2000/05/29 13:10:46 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
#define H_STACK_SIZE 10
|
||||
#define C_STACK_SIZE 30
|
||||
|
||||
/* Dummy handler; pushed only to verify that the handler stack overflow
|
||||
checks are correct.
|
||||
*/
|
||||
ChfAction h1(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
return CHF_RESIGNAL;
|
||||
}
|
||||
|
||||
/* Overflow check handler; it unwinds if the CHF_F_HDLR_STACK_FULL
|
||||
condition is signalled exactly after H_STACK_SIZE-2 invocations
|
||||
of ChfPushHandler(), it resignals a modified condition if the
|
||||
condition is signalled too early
|
||||
*/
|
||||
ChfAction h2(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
int push_count = *((int *)p);
|
||||
ChfAction action;
|
||||
|
||||
if(s == CHF_SIGNALING)
|
||||
{
|
||||
if(ChfGetModuleId(c) == CHF_SET
|
||||
&& ChfGetConditionCode(c) == CHF_F_HDLR_STACK_FULL)
|
||||
{
|
||||
/* Handler stack is full; check correctness of the descriptor */
|
||||
if(push_count == H_STACK_SIZE-2
|
||||
&& ChfGetNextDescriptor(c) == NULL
|
||||
&& ChfGetSeverity(c) == CHF_FATAL)
|
||||
action = CHF_UNWIND;
|
||||
else
|
||||
{
|
||||
ChfCondition 11, CHF_FATAL, push_count, H_STACK_SIZE-2
|
||||
ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
action = CHF_RESIGNAL;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
/* Overflow check handler; it unwinds if the CHF_F_COND_STACK_FULL
|
||||
condition is signalled exactly after C_STACK_SIZE invocations
|
||||
of ChfCondition, it resignals a modified condition if the
|
||||
condition is signalled too early
|
||||
*/
|
||||
ChfAction h3(
|
||||
const ChfDescriptor *c,
|
||||
const ChfState s,
|
||||
ChfPointer p
|
||||
)
|
||||
{
|
||||
int push_count = *((int *)p);
|
||||
ChfAction action;
|
||||
|
||||
if(s == CHF_SIGNALING)
|
||||
{
|
||||
if(ChfGetModuleId(c) == CHF_SET
|
||||
&& ChfGetConditionCode(c) == CHF_F_COND_STACK_FULL)
|
||||
{
|
||||
/* Handler stack is full; check correctness of the descriptor */
|
||||
if(push_count == C_STACK_SIZE
|
||||
&& ChfGetNextDescriptor(c) == NULL
|
||||
&& ChfGetSeverity(c) == CHF_FATAL)
|
||||
action = CHF_UNWIND;
|
||||
else
|
||||
{
|
||||
ChfCondition 12, CHF_FATAL, push_count, C_STACK_SIZE
|
||||
ChfEnd;
|
||||
action = CHF_RESIGNAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
action = CHF_RESIGNAL;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
int push_count = 0;
|
||||
sigjmp_buf jb;
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
printf("\tThread %d\n", (int)arg);
|
||||
|
||||
/* Check handler stack overflow checks */
|
||||
if(sigsetjmp(jb, 1) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h2, jb, (ChfPointer)(&push_count));
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
/* Push dummy handlers until an error should occur */
|
||||
for(; push_count<H_STACK_SIZE-1; push_count++)
|
||||
ChfPushHandler(h1, NULL, NULL);
|
||||
|
||||
/* No error? Bad! */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Flow control returns here if 'handler stack full' was signalled
|
||||
at the correct place.
|
||||
Check condition stack overflow checks
|
||||
*/
|
||||
push_count = 0;
|
||||
if(sigsetjmp(jb, 1) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h3, jb, (ChfPointer)(&push_count));
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
/* Push dummy conditions until an error should occur */
|
||||
for(; push_count<=C_STACK_SIZE; push_count++)
|
||||
ChfCondition 1, CHF_INFO ChfEnd;
|
||||
|
||||
/* No error? Bad! */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Flow control returns here if 'condition stack full' was signalled
|
||||
at the correct place.
|
||||
Check condition stack overflow again, to ensure that no spurious
|
||||
conditions were left out in the previous check.
|
||||
*/
|
||||
push_count = 0;
|
||||
if(sigsetjmp(jb, 1) == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Push the handler */
|
||||
ChfPushHandler(h3, jb, (ChfPointer)(&push_count));
|
||||
|
||||
/* The sleep() is here to increase contention between threads */
|
||||
sleep(1);
|
||||
|
||||
/* Push dummy conditions until an error should occur */
|
||||
for(; push_count<=C_STACK_SIZE; push_count++)
|
||||
ChfCondition 1, CHF_INFO ChfEnd;
|
||||
|
||||
/* No error? Bad! */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return (void *)EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test05");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat",
|
||||
C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
{
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if((int)ret != EXIT_SUCCESS)
|
||||
exit((int)ret);
|
||||
}
|
||||
|
||||
st = EXIT_SUCCESS;
|
||||
#else
|
||||
st = (int)task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(st);
|
||||
}
|
||||
|
138
Chf/test06.c
Normal file
138
Chf/test06.c
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* $Id: test06.c,v 2.1 2000/05/29 13:10:55 cibrario Rel $
|
||||
Chf test program.
|
||||
Structured condition handling - single and multithreaded
|
||||
|
||||
$Log: test06.c,v $
|
||||
Revision 2.1 2000/05/29 13:10:55 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
#define H_STACK_SIZE 10
|
||||
#define C_STACK_SIZE 30
|
||||
|
||||
|
||||
void *task(void *arg)
|
||||
{
|
||||
volatile int phase = 0;
|
||||
|
||||
ChfTry
|
||||
{
|
||||
phase = 1;
|
||||
ChfCondition 20, CHF_SUCCESS ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 2;
|
||||
ChfCondition 20, CHF_INFO ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 3;
|
||||
ChfCondition 20, CHF_WARNING ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 4;
|
||||
ChfCondition 20, CHF_ERROR ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
phase = 5;
|
||||
ChfCondition 20, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
/* Should not be reached */
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
ChfCatch
|
||||
{
|
||||
/* Catched an exception; check descriptor */
|
||||
const ChfDescriptor *d = ChfGetTopCondition();
|
||||
if(d == NULL
|
||||
|| ChfGetNextDescriptor(d) != NULL
|
||||
|| ChfGetModuleId(d) != CHF_MODULE_ID
|
||||
|| ChfGetConditionCode(d) != 20)
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
ChfEndTry;
|
||||
|
||||
/* Check that the condition stack actually is empty after catch */
|
||||
ChfTry
|
||||
{
|
||||
volatile const ChfDescriptor *e = ChfGetTopCondition();
|
||||
}
|
||||
ChfCatch
|
||||
{
|
||||
const ChfDescriptor *d = ChfGetTopCondition();
|
||||
if(d == NULL
|
||||
|| ChfGetNextDescriptor(d) != NULL
|
||||
|| ChfGetModuleId(d) != CHF_SET
|
||||
|| ChfGetConditionCode(d) != CHF_F_BAD_STATE)
|
||||
return (void *)EXIT_FAILURE;
|
||||
}
|
||||
ChfEndTry;
|
||||
|
||||
return (void *)EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#define N_THREADS 50
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
int i;
|
||||
void *ret;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
pthread_t t[N_THREADS];
|
||||
#endif
|
||||
|
||||
puts("test06");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfMsgcatInit(argv[0], CHF_DEFAULT, "./test01.cat",
|
||||
C_STACK_SIZE, H_STACK_SIZE, EXIT_FAILURE))
|
||||
exit(st);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
/* Create */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
if(pthread_create(&(t[i]), NULL, task, (void *)i))
|
||||
{
|
||||
perror("pthread_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Join */
|
||||
for(i=0; i<N_THREADS; i++)
|
||||
{
|
||||
if(pthread_join(t[i], &ret))
|
||||
{
|
||||
perror("pthread_join");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else if((int)ret != EXIT_SUCCESS)
|
||||
exit((int)ret);
|
||||
}
|
||||
|
||||
st = EXIT_SUCCESS;
|
||||
#else
|
||||
st = (int)task((void *)0);
|
||||
#endif
|
||||
|
||||
/* Exit Chf */
|
||||
ChfExit();
|
||||
exit(st);
|
||||
}
|
||||
|
103
Chf/test07.c
Normal file
103
Chf/test07.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* $Id: test07.c,v 2.1 2000/05/29 13:57:17 cibrario Rel $
|
||||
Chf test program.
|
||||
Simple initialization.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CHF_MODULE_ID 255
|
||||
#define CHF_EXTENDED_INFO
|
||||
#include "Chf.h"
|
||||
|
||||
extern ChfTable message_table[];
|
||||
extern size_t message_table_size;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int st;
|
||||
const char *msg;
|
||||
const ChfDescriptor *d, *e;
|
||||
|
||||
puts("test07");
|
||||
|
||||
/* Initialization */
|
||||
if(st = ChfStaticInit(argv[0], CHF_DEFAULT,
|
||||
message_table, message_table_size, 50, 10, 1))
|
||||
exit(st);
|
||||
|
||||
/* ChfGetMessage:
|
||||
message (CHF_MODULE_ID, 1) exists, (CHF_MODULE_ID, 2) does not
|
||||
*/
|
||||
msg = ChfGetMessage(CHF_MODULE_ID, 1, "Default_1");
|
||||
if(strcmp(msg, "Set_255,Message_1")) 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 */
|
||||
ChfCondition 3, CHF_WARNING, 456 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 3
|
||||
|| d->severity != CHF_WARNING
|
||||
|| 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 */
|
||||
ChfCondition 4, CHF_INFO, "arg" ChfEnd;
|
||||
|
||||
if((e = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
e->module_id != CHF_MODULE_ID
|
||||
|| e->condition_code != 4
|
||||
|| e->severity != CHF_INFO
|
||||
|| 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 */
|
||||
ChfDiscard();
|
||||
|
||||
/* This is line 77 */
|
||||
ChfCondition 5, CHF_ERROR, 456, 789 ChfEnd;
|
||||
|
||||
if((d = ChfGetTopCondition()) == NULL) exit(EXIT_FAILURE);
|
||||
if(
|
||||
d->module_id != CHF_MODULE_ID
|
||||
|| d->condition_code != 5
|
||||
|| d->severity != CHF_ERROR
|
||||
|| 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 */
|
||||
ChfExit();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
ChfTable message_table[] =
|
||||
{
|
||||
{ CHF_MODULE_ID, 1, "Set_255,Message_1" },
|
||||
{ CHF_MODULE_ID, 3, "Set_255,Arg_%d,Message_3" },
|
||||
{ CHF_MODULE_ID, 4, "Set_255,Arg_%s,Message_4" },
|
||||
{ CHF_MODULE_ID, 5, "Set_255,Arg_%d-%d,Message_5" }
|
||||
};
|
||||
|
||||
size_t message_table_size = sizeof(message_table)/sizeof(message_table[0]);
|
80
INSTALL.txt
Normal file
80
INSTALL.txt
Normal file
|
@ -0,0 +1,80 @@
|
|||
$Id: INSTALL.txt,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
|
||||
Quick build/installation instructions; shell commands are preceded by '$':
|
||||
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
|
||||
|
||||
To build saturn from the source distribution, follow these steps:
|
||||
|
||||
0) Create an empty directory, and unpack the source distribution archive
|
||||
into it, for example:
|
||||
|
||||
$ mkdir build_dir
|
||||
$ cd build_dir
|
||||
$ gunzip < ../saturn_src_V4_1.tar.gz | tar xf - .
|
||||
|
||||
If you are reading this notice, you probably have already done this...
|
||||
|
||||
|
||||
1) Generate the platform-specific Makefile:
|
||||
|
||||
$ xmkmf
|
||||
|
||||
On Solaris platforms, if gcc is your default (or only) compiler,
|
||||
you may need to force its selection, using the following
|
||||
command instead of xmkmf:
|
||||
|
||||
$ imake -DUseInstalled -DHasGcc -I/usr/openwin/lib/X11/config
|
||||
|
||||
|
||||
2) Generate module dependencies:
|
||||
|
||||
$ make depend
|
||||
|
||||
|
||||
3) Build saturn:
|
||||
|
||||
$ make
|
||||
|
||||
|
||||
4) Build the documentation.
|
||||
You need a working Texinfo system to do this:
|
||||
|
||||
$ make doc
|
||||
|
||||
|
||||
5) Optionally, install saturn systemwide (you need root privileges
|
||||
to do this):
|
||||
|
||||
$ make install
|
||||
|
||||
|
||||
6) Enjoy
|
229
Imakefile
Normal file
229
Imakefile
Normal file
|
@ -0,0 +1,229 @@
|
|||
# .+
|
||||
#
|
||||
# .identifier : $Id: Imakefile,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
# .context : SATURN, Saturn CPU / HP48 emulator
|
||||
# .title : $RCSfile: Imakefile,v $
|
||||
# .kind : Makefile
|
||||
# .author : Ivan Cibrario B.
|
||||
# .site : CSTV-CNR
|
||||
# .creation : *
|
||||
# .keywords : *
|
||||
# .description :
|
||||
# Imakefile.
|
||||
# .notes :
|
||||
# $Log: Imakefile,v $
|
||||
# Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
# Public release.
|
||||
#
|
||||
# Revision 3.16 2000/11/21 16:37:20 cibrario
|
||||
# Ultrix/IRIX support:
|
||||
# - Propagate CC and CFLAGS to Chf library as fallback values
|
||||
# - Added -li library for Ultrix
|
||||
# - Use RM directly if needed macros are not available
|
||||
#
|
||||
# Revision 3.14 2000/11/13 10:24:52 cibrario
|
||||
# Implemented fast load/save; improved keyboard interface emulation at
|
||||
# high emulated CPU speed:
|
||||
#
|
||||
# - New file disk_io_obj.c
|
||||
#
|
||||
# Revision 3.13 2000/11/09 11:14:50 cibrario
|
||||
# Revised to add file selection box GUI element, CPU halt/run
|
||||
# requests and emulator's extended functions:
|
||||
#
|
||||
# - New files: x_func.h, x_func.c, x_func.msf
|
||||
#
|
||||
# Revision 3.9 2000/10/24 16:12:55 cibrario
|
||||
# Added Texinfo documentation targets
|
||||
#
|
||||
# Revision 3.8 2000/10/23 13:18:58 cibrario
|
||||
# Bug fixes:
|
||||
# - saturn.cat did not contain Chf messages
|
||||
# - extended 'clean' target to remove saturn.cat as well
|
||||
# - CatDestination was wrong on Debian GNU/Linux
|
||||
#
|
||||
# Revision 3.6 2000/10/02 13:54:04 cibrario
|
||||
# ROM handling utilities:
|
||||
# - Added support for stand-alone build of Chf library in its subdirectory
|
||||
# - Added build commands for 'pack' utility
|
||||
#
|
||||
# Revision 3.5 2000/10/02 09:55:10 cibrario
|
||||
# Linux support:
|
||||
# - openpty() is in -lutil
|
||||
# - message catalog must be installed in /usr/lib/locale/C
|
||||
#
|
||||
# Revision 3.3 2000/09/26 15:26:07 cibrario
|
||||
# Revised to implement Flash ROM write access:
|
||||
# - Added new files flash49.c and flash49.msf
|
||||
#
|
||||
# Revision 3.2 2000/09/22 13:21:33 cibrario
|
||||
# Implemented preliminary support of HP49 hw architecture:
|
||||
# - added new modules hw_config.c and romram49.c to SRCS list
|
||||
#
|
||||
# Revision 2.5 2000/09/14 15:41:16 cibrario
|
||||
# Added new files serial.c and serial.msf
|
||||
#
|
||||
# Revision 2.1 2000/09/08 15:39:34 cibrario
|
||||
# Added automatic installation of application default file and
|
||||
# message catalog; removed platform-dependent options.
|
||||
#
|
||||
# Revision 1.1 1998/02/19 12:03:28 cibrario
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
# .-
|
||||
|
||||
#
|
||||
# Stand-alone build of Chf library in its subdirectory
|
||||
#
|
||||
# 3.16: Propagate CC and CFLAGS to Chf library as fallback values
|
||||
#
|
||||
#define IHaveSubdirs
|
||||
#define PassCDebugFlags X_CC="$(CC)" X_CFLAGS="$(CFLAGS)"
|
||||
SUBDIRS = Chf
|
||||
MakeSubdirs($(SUBDIRS))
|
||||
|
||||
#
|
||||
# Programs built by this Imakefile
|
||||
#
|
||||
PROGRAMS= saturn pack
|
||||
|
||||
#
|
||||
# Source/object files
|
||||
# Each row corresponds to a group of files; each group has its own
|
||||
# CHF module identifier and message catalog source file.
|
||||
#
|
||||
SRCS1= debug.c \
|
||||
cpu.c dis.c emulator.c monitor.c \
|
||||
modules.c hw_config.c romram.c romram49.c hdw.c keyb.c \
|
||||
disk_io.c disk_io_obj.c \
|
||||
display.c x11.c \
|
||||
serial.c flash49.c x_func.c\
|
||||
saturn.c
|
||||
|
||||
#
|
||||
# Message catalog source files for the modules defined above.
|
||||
#
|
||||
MSFS= debug.msf \
|
||||
cpu.msf \
|
||||
modules.msf \
|
||||
disk_io.msf \
|
||||
x11.msf \
|
||||
serial.msf flash49.msf x_func.msf\
|
||||
saturn.msf util.msf \
|
||||
Chf/chf.msf
|
||||
|
||||
#
|
||||
# Source/object files of secondary target
|
||||
#
|
||||
SRCS2= pack.c
|
||||
|
||||
#
|
||||
# Automatic generation of object file list
|
||||
#
|
||||
OBJS1= $(SRCS1:.c=.o)
|
||||
OBJS2= $(SRCS2:.c=.o) disk_io.o debug.o
|
||||
|
||||
#
|
||||
# Now, some extras... bring the Chf library in.
|
||||
#
|
||||
EXTRA_INCLUDES = -I./Chf
|
||||
EXTRA_LOAD_FLAGS = -L./Chf/st_build
|
||||
|
||||
# 3.5: Added linux support; openpty() is in -lutil
|
||||
#
|
||||
|
||||
#if defined(LinuxArchitecture)
|
||||
EXTRA_ARCH_LIBRARIES = -lutil
|
||||
#endif
|
||||
|
||||
# 3.16: Added Ultrix support; catopen() is in -li
|
||||
#
|
||||
|
||||
#if defined(UltrixArchitecture)
|
||||
EXTRA_TAIL_LIBRARIES = -li
|
||||
#endif
|
||||
|
||||
EXTRA_LIBRARIES = $(EXTRA_ARCH_LIBRARIES) \
|
||||
-lXm $(XTOOLLIB) $(XLIB) -lChf \
|
||||
$(EXTRA_TAIL_LIBRARIES)
|
||||
|
||||
#
|
||||
# Main Target
|
||||
#
|
||||
ComplexProgramTarget_1(saturn,NullParameter,NullParameter)
|
||||
|
||||
#
|
||||
# Main Target
|
||||
#
|
||||
ComplexProgramTarget_2(pack,NullParameter,NullParameter)
|
||||
|
||||
#
|
||||
# Installation of the application default file; primary target only.
|
||||
#
|
||||
InstallAppDefaults(Saturn)
|
||||
|
||||
#
|
||||
# Special message catalog targets
|
||||
#
|
||||
saturn.cat: $(MSFS)
|
||||
for msf in $? ; \
|
||||
do gencat saturn.cat $$msf ; \
|
||||
done
|
||||
|
||||
all:: saturn.cat
|
||||
|
||||
#
|
||||
# 3.16: Use RM directly if macro is not available
|
||||
#
|
||||
#ifdef ImakeConfigRelease
|
||||
clean::
|
||||
RemoveFile(saturn.cat)
|
||||
#else
|
||||
clean::
|
||||
$(RM) saturn.cat
|
||||
#endif
|
||||
|
||||
#
|
||||
# Determine destination of saturn.cat; for now, few architectures are
|
||||
# supported.
|
||||
#
|
||||
#if defined(AlphaArchitecture)
|
||||
#define CatDestination /usr/lib/nls/msg/C
|
||||
#elif defined(SunArchitecture)
|
||||
#define CatDestination /usr/lib/locale/C/LC_MESSAGES
|
||||
#elif defined(LinuxArchitecture)
|
||||
#define CatDestination /usr/share/locale/C/LC_MESSAGES
|
||||
#endif
|
||||
|
||||
#if defined(CatDestination)
|
||||
InstallNonExecFile(saturn.cat,CatDestination)
|
||||
#else
|
||||
install::
|
||||
echo "*** Can't determine CatDestination; install saturn.cat manually"
|
||||
#endif
|
||||
|
||||
#
|
||||
# TexInfo Documentation
|
||||
#
|
||||
MAKEINFO= makeinfo
|
||||
TEXI2DVI= texi2dvi
|
||||
DVIPS= dvips
|
||||
|
||||
doc:
|
||||
$(MAKEINFO) saturn.texi
|
||||
$(TEXI2DVI) saturn.texi && $(DVIPS) -o saturn.ps saturn.dvi
|
||||
@echo "*** Install saturn.info manually, please"
|
||||
|
||||
#
|
||||
# 3.16: Use RM directly if macro is not available
|
||||
#
|
||||
#ifdef ImakeConfigRelease
|
||||
clean::
|
||||
RemoveFiles(*.aux *.cp *.cps *.dvi *.fn *.info *.ky *.log *.pg)
|
||||
RemoveFiles(*.ps *.toc *.tp *.vr)
|
||||
#else
|
||||
clean::
|
||||
$(RM) *.aux *.cp *.cps *.dvi *.fn *.info *.ky *.log *.pg
|
||||
$(RM) *.ps *.toc *.tp *.vr
|
||||
#endif
|
49
README.txt
Normal file
49
README.txt
Normal file
|
@ -0,0 +1,49 @@
|
|||
$Id: README.txt,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
|
||||
|
||||
To get started with the saturn software, follow these steps:
|
||||
|
||||
- If you have an user-level binary distribution, read the file
|
||||
BUILD_INFO.txt and check that the platform on which the
|
||||
saturn software was built is compatible with yours.
|
||||
|
||||
- If you have a source distribution, follow the instructions
|
||||
of INSTALL.txt to build the binaries and, optionally,
|
||||
to install them.
|
||||
|
||||
- Read the documentation of the saturn software, above all chapter 2.
|
||||
You must build the documentation yourself as explained in INSTALL.txt
|
||||
if you have a source distribution; instead, if you have a binary
|
||||
distribution, both info and PostScript files are already there.
|
||||
|
||||
- If you are in a real hurry and wish to emulate an HP49 as soon
|
||||
as possible, run the ./quick_start shell script.
|
100
args.h
Normal file
100
args.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: args.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: args.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 19-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This header declares a global data structure containing the emulator
|
||||
invocation arguments; this data structure is initialized before startup,
|
||||
either by means of argc/argv or in other ways.
|
||||
|
||||
.include : config.h
|
||||
|
||||
.notes :
|
||||
$Log: args.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.15 2000/11/15 14:03:06 cibrario
|
||||
GUI enhancements and assorted bug fixes:
|
||||
- added .batchXfer boolean (corresponding to command-line option
|
||||
-batchXfer) to struct Args
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:25 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 2.1 2000/09/08 14:45:06 cibrario
|
||||
Added the following fields to 'struct Args': reset, monitor, hw.
|
||||
The latter mimes the setting of the -hw command line option and
|
||||
of the *hw top-level application resource; the former two have
|
||||
been added to export them cleanly from the GUI modules.
|
||||
|
||||
* Revision 1.1 1998/02/17 11:58:37 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Data type definitions - require config.h
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
struct Args
|
||||
{
|
||||
int reset; /* 2.1: Force emulator reset */
|
||||
int monitor; /* 2.1: Call monitor() on startup */
|
||||
int batchXfer; /* 3.15: Non-interactive file transfers */
|
||||
char *mod_file_name;
|
||||
char *cpu_file_name;
|
||||
char *hdw_file_name;
|
||||
char *rom_file_name;
|
||||
char *ram_file_name;
|
||||
char *port_1_file_name;
|
||||
char *port_2_file_name;
|
||||
char *hw; /* 2.1: Hardware configuration (unused) */
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
extern struct Args args;
|
5
cindex.texi
Normal file
5
cindex.texi
Normal file
|
@ -0,0 +1,5 @@
|
|||
@c $Id: cindex.texi,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
|
||||
@node Concept Index, , GNU GENERAL PUBLIC LICENSE, Top
|
||||
@unnumbered Concept Index
|
||||
@printindex cp
|
148
clopt.texi
Normal file
148
clopt.texi
Normal file
|
@ -0,0 +1,148 @@
|
|||
@c $Id: clopt.texi,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
|
||||
@node Command Line Options, Customizing saturn, Using the Emulator, Top
|
||||
@chapter Command Line Options
|
||||
@cindex Command Line Options
|
||||
|
||||
The @code{saturn} program accepts the command line options listed below;
|
||||
notice that recent versions of the X Toolkit allow you to abbreviate
|
||||
option's names to their shortest, non-ambiguous prefix.
|
||||
|
||||
@table @code
|
||||
@item -reset
|
||||
This option instructs @code{saturn} to reset the emulated CPU,
|
||||
by forcing a jump to address @code{0}, before starting execution.
|
||||
It should be useful when the emulated calculator ``gets stuck'', since
|
||||
it has the same effect as pressing the reset switch on the real
|
||||
calculator.
|
||||
|
||||
@item -monitor
|
||||
This option instructs @code{saturn} to enter the monitor/debugger
|
||||
during startup; since this feature of @code{saturn} is pitiful,
|
||||
use of this option is strongly discouraged for now.
|
||||
|
||||
@item -batchXfer
|
||||
When this option is present on the command line, all fast file
|
||||
transfers requested through the @code{sutil} library will be
|
||||
made in batch mode, that is, @code{saturn} will always load and save
|
||||
files in the current directory and will use the default file names
|
||||
given by the calculator, without any user interaction.
|
||||
|
||||
@item -stateDir @var{dir_name}
|
||||
This option must be followed by the name of a directory, @var{dir_name};
|
||||
@code{saturn} will use this directory to load/save the calculator's
|
||||
state. By specifying different state directories, you can emulate
|
||||
multiple calculator models and/or multiple instances of the same
|
||||
calculator, even simultaneously. However, keep in mind that
|
||||
calculator's state files are @strong{not} platform-independent, so you
|
||||
cannot share them among different platforms. The default value of this
|
||||
option is @code{.}, that is, by default @code{saturn} places its
|
||||
state files in the current directory.
|
||||
|
||||
@item -cpu @var{cpu_state}
|
||||
This option must be followed by the name of a file, @var{cpu_state},
|
||||
relative to the emulator's state directory; @code{saturn} will use
|
||||
this file to load/save the calculator's emulated CPU state.
|
||||
The default value of this option is @code{cpu}.
|
||||
|
||||
@item -mod @var{mod_state}
|
||||
This option must be followed by the name of a file, @var{mod_state},
|
||||
relative to the emulator's state directory; @code{saturn} will use
|
||||
this file to load/save the calculator's emulated peripheral modules
|
||||
state.
|
||||
The default value of this option is @code{mod}.
|
||||
|
||||
@item -hdw @var{hdw_state}
|
||||
This option must be followed by the name of a file, @var{hdw_state},
|
||||
relative to the emulator's state directory; @code{saturn} will use
|
||||
this file to load/save the calculator's emulated peripheral devices
|
||||
state.
|
||||
The default value of this option is @code{hdw}.
|
||||
|
||||
@item -rom @var{rom_image}
|
||||
This option must be followed by the name of a file, @var{rom_image},
|
||||
relative to the emulator's state directory; @code{saturn} will use
|
||||
this file to load (and save, when emulating an HP49) the calculator's
|
||||
ROM image.
|
||||
The default value of this option is @code{rom}.
|
||||
|
||||
@item -ram @var{ram_image}
|
||||
This option must be followed by the name of a file, @var{ram_image},
|
||||
relative to the emulator's state directory; @code{saturn} will use
|
||||
this file to load/save the calculator's main RAM image.
|
||||
The default value of this option is @code{ram}.
|
||||
|
||||
@item -port1 @var{port1_image}
|
||||
This option must be followed by the name of a file, @var{port1_image},
|
||||
relative to the emulator's state directory; @code{saturn} will use
|
||||
this file to load/save the calculator's port 1 image.
|
||||
The default value of this option is @code{port1}.
|
||||
This option is meaningful only when emulating an HP48GX.
|
||||
|
||||
@item -port2 @var{port2_image}
|
||||
This option must be followed by the name of a file, @var{port2_image},
|
||||
relative to the emulator's state directory; @code{saturn} will use
|
||||
this file to load/save the calculator's port 2 image.
|
||||
The default value of this option is @code{port2}.
|
||||
This option is meaningful only when emulating an HP48GX.
|
||||
|
||||
@item -face @var{face_name}
|
||||
This option must be followed by the name of a faceplate, @var{face_name},
|
||||
defined in the application resources of @code{saturn}. The faceplate
|
||||
defines the ``look'' of the emulated calculator, such as its color
|
||||
and the size and position of its keys, the mapping between
|
||||
calculator's keys and IN/OUT codes seen by the CPU, and keyboard
|
||||
shortcuts. Each user can define its own faceplates for @code{saturn},
|
||||
and use them without rebuilding the executable; for more information
|
||||
see @ref{Customizing saturn}. The application resource file
|
||||
distributed with @code{saturn} defines the following faceplates:
|
||||
|
||||
@table @code
|
||||
@item hp48
|
||||
Naive HP48GX faceplate
|
||||
@item hp49
|
||||
Naive HP49 faceplate
|
||||
@item hp40
|
||||
Naive HP40 faceplate
|
||||
@end table
|
||||
|
||||
The default value of this option is @code{hp48}, corresponding
|
||||
to a naive HP48GX faceplate in the default application resource
|
||||
file distributed with @code{saturn}.
|
||||
|
||||
@item -hw @var{hw_name}
|
||||
This option must be followed by the name of an hardware configuration,
|
||||
@var{hw_name}, chosen among those supported by @code{saturn}.
|
||||
The hardware configuration defines things like ROM/RAM sizes, bank
|
||||
switching mechanism, and so on. Currently, @code{saturn} supports two
|
||||
hardware configurations:
|
||||
|
||||
@table @code
|
||||
@item hp48
|
||||
HP48GX calculator
|
||||
@item hp49
|
||||
HP49 calculator, also suitable to emulate the HP40
|
||||
@end table
|
||||
|
||||
Even if @code{saturn} has a modular structure, unfortunately
|
||||
general users cannot add custom hardware architectures to it
|
||||
without rebuilding the executable. Moreover, since I am a lazy guy,
|
||||
the steps required to do this are not documented at all.
|
||||
@end table
|
||||
|
||||
In addition, @code{saturn} understands all standard X Toolkit command-line
|
||||
options, and does its best to honor them. Among such options, the
|
||||
most useful ones are:
|
||||
|
||||
@table @code
|
||||
@item -display @var{display_name}
|
||||
This option must be followed by a valid X display name, and instructs
|
||||
the emulator to use that display to show its windows. If this option
|
||||
is not present on the command line the default display, that is,
|
||||
the display named by the @code{DISPLAY} environment variable, is used.
|
||||
@item -xrm @var{resource_spec}
|
||||
This option must be followed by a valid X resource specifier, and
|
||||
allows you to add/override one or more @code{saturn}'s X resources
|
||||
``on-the-fly''.
|
||||
@end table
|
||||
|
267
config.h
Normal file
267
config.h
Normal file
|
@ -0,0 +1,267 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: config.h,v 4.1.1.1 2002/11/11 16:13:29 cibrario Exp $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: config.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 28-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This file configures the Saturn / HP48 emulator.
|
||||
|
||||
.include : *
|
||||
|
||||
.notes :
|
||||
$Log: config.h,v $
|
||||
Revision 4.1.1.1 2002/11/11 16:13:29 cibrario
|
||||
Small screen support; preliminary
|
||||
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.16 2000/11/21 16:38:23 cibrario
|
||||
Ultrix/IRIX support:
|
||||
- Include config_x.h (automatic exceptions to user configuration)
|
||||
|
||||
Revision 3.14 2000/11/13 10:23:43 cibrario
|
||||
Implemented fast load/save; improved keyboard interface emulation at
|
||||
high emulated CPU speed:
|
||||
|
||||
- New configuration option: CPU_SLOW_IN (enabled by default)
|
||||
|
||||
Revision 3.13 2000/11/09 11:21:18 cibrario
|
||||
Revised to add file selection box GUI element, CPU halt/run
|
||||
requests and emulator's extended functions:
|
||||
|
||||
- Updated documentation of CPU_SPIN_SHUTDN and REAL_CPU_SPEED
|
||||
- Defined new Chf module identifier: X_FUNC_CHF_MODULE_ID
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:25 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.6 2000/10/02 13:52:32 cibrario
|
||||
ROM handling utilities:
|
||||
- Added new Chf module identifier: UTIL_CHF_MODULE_ID
|
||||
|
||||
Revision 3.5 2000/10/02 09:40:35 cibrario
|
||||
Linux support:
|
||||
- documented new compile-time option: REAL_CPU_SPEED
|
||||
|
||||
Revision 3.3 2000/09/26 15:24:20 cibrario
|
||||
Revised to implement Flash ROM write access:
|
||||
- Added new Chf module identifier FLASH_CHF_MODULE_ID
|
||||
|
||||
* Revision 3.2 2000/09/22 13:34:43 cibrario
|
||||
* Implemented preliminary support of HP49 hw architecture:
|
||||
* - Re-enabled DEBUG
|
||||
* - Documented new HP49_SUPPORT option, and enabled it by default
|
||||
*
|
||||
* Revision 3.1 2000/09/20 14:15:42 cibrario
|
||||
* Revised to implement passive CPU shutdown:
|
||||
* - disabled DEBUG option by default
|
||||
* - enhanced documentation of CPU_SPIN_SHUTDN; this option is now
|
||||
* disabled by default.
|
||||
*
|
||||
* Revision 2.6 2000/09/15 09:28:48 cibrario
|
||||
* Enhanced documentation of serial emulation options; added
|
||||
* template of SERIAL_FORCE_STREAMSPTY definition (commented out
|
||||
* by default)
|
||||
*
|
||||
* Revision 2.5 2000/09/14 15:40:24 cibrario
|
||||
* - Added description and default values of configuration options
|
||||
* SERIAL_FORCE_OPENPTY and SERIAL_FORCE_STREAMSPTY.
|
||||
* - Added new Chf module identifier SERIAL_CHF_MODULE_ID, used by the
|
||||
* serial port emulation modules.
|
||||
*
|
||||
* Revision 2.4 2000/09/12 15:50:40 cibrario
|
||||
* Added description and default definition of N_PORT_2_BANK
|
||||
*
|
||||
* Revision 2.1 2000/09/08 15:43:46 cibrario
|
||||
* Disabled DEBUG option by default; documented new GUI option
|
||||
* FORCE_NONMODAL.
|
||||
*
|
||||
* Revision 1.1 1998/02/17 14:57:15 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/* CHF_EXTENDED_INFO:
|
||||
Define this symbol if extended information is desired during condition
|
||||
handling; this is usually useful only for debugging purposes.
|
||||
*/
|
||||
/* #define CHF_EXTENDED_INFO */
|
||||
|
||||
|
||||
/* DEBUG:
|
||||
Define this symbol to include the debugging code for all source modules
|
||||
in the executable image.
|
||||
|
||||
At run-time, the debug level can be set using the function SetDebugLevel();
|
||||
the initial debug level is set to the value of the symbol DEBUG_LEVEL,
|
||||
if it is defined, otherwise it is set to zero.
|
||||
*/
|
||||
/* #define DEBUG */
|
||||
|
||||
|
||||
/* DEBUG_LEVEL:
|
||||
When this symbol is defined and the debugging code has been included
|
||||
in the executable image (DEBUG symbol set), the initial debug level
|
||||
is set to its value.
|
||||
|
||||
The value must be the bitwise OR of zero or more of the symbols
|
||||
DEBUG_C_<> defined in debug.h; each of them corresponds to a class
|
||||
of debugging conditions that can be individually enabled or disabled.
|
||||
*/
|
||||
#define DEBUG_LEVEL DEBUG_C_REVISION
|
||||
|
||||
|
||||
/* CPU_SPIN_SHUTDN
|
||||
If this symbol is defined, the cpu module implements the SHUTDN
|
||||
instruction as a spin loop; when the instruction is encountered in the
|
||||
run stream, the program counter is reset to the starting nibble of its
|
||||
opcode.
|
||||
|
||||
If this symbol is not defined, the cpu module implements the SHUTDN
|
||||
instruction signaling a Chf condition; the main emulator loop
|
||||
condition handler works in concert with the GUI module to implement
|
||||
an idle loop when this condition is handled.
|
||||
|
||||
This option MUST be defined if the revision of either the cpu emulation
|
||||
module (cpu.c) or the GUI module (x11.c) is less than 3.1.
|
||||
|
||||
Starting from release 3.1, this option is disabled by default, to
|
||||
waste as little (real) cpu time as possible; however, expect a
|
||||
loss of timing accuracy.
|
||||
|
||||
Notice also that when this function is defined the CpuHaltRequest()
|
||||
and CpuRunRequest() functions are disabled; as a consequence, all
|
||||
interactive emulator's extended functions will be disabled as well.
|
||||
*/
|
||||
/* #define CPU_SPIN_SHUTDN */
|
||||
|
||||
|
||||
/* 2.1: FORCE_NONMODAL
|
||||
If this symbol is defined, nonmodal navigation is forced in the
|
||||
OSF/Motif GUI, by setting navigationType to XmNONE and traversalOn
|
||||
to False at the source code level.
|
||||
*/
|
||||
/* #define FORCE_NONMODAL */
|
||||
|
||||
|
||||
/* 2.4: N_PORT_2_BANK
|
||||
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
|
||||
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.
|
||||
*/
|
||||
#define N_PORT_2_BANK 8
|
||||
|
||||
|
||||
/* 2.5: SERIAL_FORCE_OPENPTY, SERIAL_FORCE_STREAMSPTY
|
||||
Optionally define exactly one of these symbols to force the use of a
|
||||
particular pty implementation; if no symbols are defined, the
|
||||
serial port emulation modules will do their best to automatically
|
||||
determine the most appropriate implementation for the platform at hand.
|
||||
*/
|
||||
/* #define SERIAL_FORCE_OPENPTY */
|
||||
/* #define SERIAL_FORCE_STREAMSPTY */
|
||||
|
||||
|
||||
/* 3.2: HP49_SUPPORT
|
||||
Define this symbol to enable HP49-specific support code in the
|
||||
emulator; it does not harm if this symbol is defined when emulating
|
||||
a HP48, too, since all changed should be backward-compatible.
|
||||
*/
|
||||
#define HP49_SUPPORT
|
||||
|
||||
|
||||
/* 3.13: REAL_CPU_SPEED
|
||||
Define this symbol (recommended) to force the emulated CPU to run
|
||||
no faster than a software-controlled limit; by default, the limit
|
||||
is close to the real CPU speed.
|
||||
*/
|
||||
#define REAL_CPU_SPEED
|
||||
|
||||
|
||||
/* 3.14: CPU_SLOW_IN
|
||||
Define this symbol (recommended) to slow down the A=IN and C=IN
|
||||
instructions depending on the current emulated CPU speed.
|
||||
|
||||
The value of the macro determines the gain of the relation between
|
||||
CPU speed and slow down ratio.
|
||||
*/
|
||||
#define CPU_SLOW_IN 16
|
||||
|
||||
|
||||
/* 4.1.1.1: LCD_MAG
|
||||
This symbol represents the magnification ratio of the emulated LCD pixels
|
||||
when drawn on the emulated display; supported values are 1 and 2; 2 is the
|
||||
default. Currently, the value cannot be set at runtime for performance
|
||||
reasons.
|
||||
*/
|
||||
#define LCD_MAG 1
|
||||
|
||||
|
||||
/* 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
|
||||
for more than LONG_PRESS_THR milliseconds, the key stays pressed after
|
||||
release.
|
||||
*/
|
||||
#define LONG_PRESS_THR 1000
|
||||
|
||||
|
||||
/* Chf Module Identifiers:
|
||||
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.
|
||||
*/
|
||||
#define MAIN_CHF_MODULE_ID 10
|
||||
#define CPU_CHF_MODULE_ID 11
|
||||
#define MOD_CHF_MODULE_ID 12
|
||||
#define DISK_IO_CHF_MODULE_ID 13
|
||||
#define X11_CHF_MODULE_ID 14
|
||||
#define SERIAL_CHF_MODULE_ID 15 /* 2.5 */
|
||||
#define FLASH_CHF_MODULE_ID 16 /* 3.3 */
|
||||
#define UTIL_CHF_MODULE_ID 17 /* 3.6 */
|
||||
#define X_FUNC_CHF_MODULE_ID 18 /* 3.13 */
|
||||
#define DEBUG_CHF_MODULE_ID 30
|
||||
|
||||
|
||||
/* 3.16: Include automatic exceptions to user configuration */
|
||||
#include "config_x.h"
|
65
config_x.h
Normal file
65
config_x.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: config_x.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HPxx emulator
|
||||
.title : $RCSfile: config_x.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 20-Nov-2000
|
||||
.keywords : *
|
||||
.description :
|
||||
This file is included by config.h and automatically disables any
|
||||
user configuration option known to be unsupported on the current platform.
|
||||
|
||||
.include : *
|
||||
|
||||
.notes :
|
||||
$Log: config_x.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.16 2000/11/21 16:38:44 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/* REAL_CPU_SPEED is not supported on ultrix, because there is no usleep() */
|
||||
#ifdef ultrix
|
||||
#undef REAL_CPU_SPEED
|
||||
#endif
|
352
cpu.h
Normal file
352
cpu.h
Normal file
|
@ -0,0 +1,352 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: cpu.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: cpu.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : *
|
||||
.keywords : *
|
||||
.description :
|
||||
Main header for the Saturn CPU emulation modules. References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
.include : config.h machdep.h
|
||||
|
||||
.notes :
|
||||
$Log: cpu.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.14 2000/11/13 11:31:16 cibrario
|
||||
Implemented fast load/save; improved keyboard interface emulation at
|
||||
high emulated CPU speed:
|
||||
|
||||
- Revision number bump with no changes
|
||||
|
||||
Revision 3.13 2000/11/09 11:27:14 cibrario
|
||||
Revised to add file selection box GUI element, CPU halt/run
|
||||
requests and emulator's extended functions:
|
||||
|
||||
- Added new fields:
|
||||
struct CpuStatus.halt (number of pending halt requests)
|
||||
struct CpuStatus.inner_loop_max (upper limit of inner_loop)
|
||||
- New condition codes: CPU_I_HALT, CPU_I_RUN, CPU_E_NO_HALT
|
||||
- New prototypes: CpuHaltRequest(), CpuRunRequest(), CpuHaltAllowed()
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:31 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.8 2000/10/23 13:13:08 cibrario
|
||||
Bug fix:
|
||||
Adjusted INNER_LOOP_MAX and INNER_LOOP_MED to get closer to
|
||||
real CPU speed.
|
||||
|
||||
Revision 3.5 2000/10/02 09:43:37 cibrario
|
||||
Linux support:
|
||||
- Added definition of INNER_LOOP_MAX; it is used to give an upper limit
|
||||
to the emulated CPU speed on fast machines, when REAL_CPU_SPEED is
|
||||
defined.
|
||||
|
||||
Revision 3.1 2000/09/20 13:42:30 cibrario
|
||||
Revised to implement passive CPU shutdown:
|
||||
- new status codes CPU_I_TIMER_ST, CPU_I_TIMER_EXP, CPU_I_IDLE_X_LOOP,
|
||||
CPU_I_ELAPSED
|
||||
|
||||
* Revision 2.4 2000/09/12 15:19:47 cibrario
|
||||
* Added definition of XAddress (extended address) data type; it is
|
||||
* required to implement emulation of Port 1 and 2.
|
||||
*
|
||||
* Revision 2.1 2000/09/08 14:48:52 cibrario
|
||||
* - Declared prototypes of new functions EmulatorInit() and EmulatorExit()
|
||||
* - Defined new 'enum ExitOption' data type, used by EmulatorExit()
|
||||
*
|
||||
* Revision 1.1 1998/02/18 11:50:43 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macro/Data type definitions - require machdep.h
|
||||
|
||||
N_SCRATCH_REGISTER_ALL, used during scratch register space allocation
|
||||
is larger than necessary to avoid additional checks on the validity of
|
||||
the R register index fields during emulation
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* General */
|
||||
#define NIBBLE_PER_REGISTER 16
|
||||
#define N_WORKING_REGISTER 4
|
||||
#define N_SCRATCH_REGISTER 5
|
||||
#define N_SCRATCH_REGISTER_ALL 8
|
||||
#define N_DATA_POINTER_REGISTER 2
|
||||
#define RETURN_STACK_SIZE 8
|
||||
#define NIBBLE_VALUES 16
|
||||
|
||||
#define INT_HANDLER_PC ((Address)0x0000F)
|
||||
|
||||
#define DISASSEMBLE_OB_SIZE 128
|
||||
#define DUMP_CPU_STATUS_OB_SIZE 512
|
||||
|
||||
#define CPU_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
|
||||
|
||||
|
||||
/* Instruction opcode access macros:
|
||||
GetFS(f) returns the short field-selector value from the
|
||||
given nibble (bits 2..0)
|
||||
|
||||
GetImmFS(f) returns the immediate-field-selector flag from the
|
||||
given nibble (bit 3)
|
||||
=0: regular field selector
|
||||
!=0: immediate field selector
|
||||
|
||||
GetOC_1(o) returns the short operation code from the given
|
||||
nibble (bits 3..2 >>2)
|
||||
|
||||
GetOC_2(f, o) returns the long operation code from the given
|
||||
nibbles (f bit 3, o bits 3..2)
|
||||
|
||||
GetOC_3b(o) returns the long operation code from the given
|
||||
nibble (bits 2..0)
|
||||
|
||||
GetRP(o) returns the register-pair identifier from the given
|
||||
nibble (bits 1..0)
|
||||
|
||||
GetRn(r) returns the R register index from the given nibble
|
||||
(bits 2..0)
|
||||
|
||||
GetAC(r) returns the A/C register flag from the given nibble
|
||||
(bit 3)
|
||||
=0: register A
|
||||
!=0: register C
|
||||
|
||||
GetAS(r) returns the add/subtract flag from the given nibble
|
||||
(bit 3)
|
||||
=0: add
|
||||
!=0: subtract
|
||||
*/
|
||||
#define GetFS(f) ((f) & 0x7)
|
||||
#define GetImmFS(o) ((o) & 0x8)
|
||||
#define GetOC_1(o) (((o) & 0xC)>>2)
|
||||
#define GetOC_2(f, o) ((((f) & 0x8)>>1) | (((o) & 0xC)>>2))
|
||||
#define GetOC_3b(o) ((o) & 0x7)
|
||||
#define GetRP(o) ((o) & 0x3)
|
||||
#define GetRn(r) ((r) & 0x7)
|
||||
#define GetAC(r) ((r) & 0x8)
|
||||
#define GetAS(r) ((r) & 0x8)
|
||||
|
||||
|
||||
/* Field selector codes */
|
||||
#define FS_P 0
|
||||
#define FS_WP 1
|
||||
#define FS_XS 2
|
||||
#define FS_X 3
|
||||
#define FS_S 4
|
||||
#define FS_M 5
|
||||
#define FS_B 6
|
||||
#define FS_W 7
|
||||
#define FS_A 15
|
||||
#define N_FS 16 /* Total # of FS codes */
|
||||
|
||||
|
||||
/* Register pair codes */
|
||||
#define RP_AB 0
|
||||
#define RP_BC 1
|
||||
#define RP_CA 2
|
||||
#define RP_DC 3
|
||||
#define N_RP 4 /* Total # of RP codes */
|
||||
|
||||
|
||||
/* Masks */
|
||||
#define NIBBLE_MASK ((Nibble)0xF)
|
||||
#define ADDRESS_MASK ((Address)0xFFFFF)
|
||||
|
||||
#define CLRST_MASK ((ProgramStatusRegister)0xF000)
|
||||
#define D_S_MASK ((Address)0xF0000)
|
||||
#define RETURN_SP_MASK 0x7
|
||||
|
||||
|
||||
typedef int1 Bit;
|
||||
typedef int4 Nibble;
|
||||
typedef int20 Address;
|
||||
typedef int12 OutputRegister;
|
||||
typedef int16 InputRegister;
|
||||
typedef int16 ProgramStatusRegister;
|
||||
typedef Nibble DataRegister[NIBBLE_PER_REGISTER];
|
||||
|
||||
/* The XAddress data type holds extended addresses used to access Port 2 */
|
||||
typedef int32 XAddress;
|
||||
|
||||
enum IntRequest
|
||||
{
|
||||
INT_REQUEST_NONE,
|
||||
INT_REQUEST_IRQ,
|
||||
INT_REQUEST_NMI
|
||||
};
|
||||
|
||||
struct CpuStatus
|
||||
{
|
||||
DataRegister work[N_WORKING_REGISTER];
|
||||
#define A work[0]
|
||||
#define B work[1]
|
||||
#define C work[2]
|
||||
#define D work[3]
|
||||
|
||||
DataRegister R[N_SCRATCH_REGISTER_ALL];
|
||||
#define R0 R[0]
|
||||
#define R1 R[1]
|
||||
#define R2 R[2]
|
||||
#define R3 R[3]
|
||||
#define R4 R[4]
|
||||
|
||||
Address DAT[N_DATA_POINTER_REGISTER];
|
||||
#define D0 DAT[0]
|
||||
#define D1 DAT[1]
|
||||
|
||||
Nibble P;
|
||||
Address PC;
|
||||
InputRegister IN;
|
||||
OutputRegister OUT;
|
||||
ProgramStatusRegister ST;
|
||||
|
||||
Nibble HST;
|
||||
#define HST_MP_MASK 0x08
|
||||
#define HST_SR_MASK 0x04
|
||||
#define HST_SB_MASK 0x02
|
||||
#define HST_XM_MASK 0x01
|
||||
|
||||
Address return_stack[RETURN_STACK_SIZE];
|
||||
int return_sp;
|
||||
|
||||
int fs_idx_lo[N_FS];
|
||||
int fs_idx_hi[N_FS];
|
||||
int hexmode; /* DEC/HEX mode, 1=HEX */
|
||||
int carry; /* Carry bit 1=set */
|
||||
int shutdn; /* SHUTDN flag, 1=executed */
|
||||
int halt; /* 3.13: # of pending Halt */
|
||||
int int_enable; /* Int. enable, 1=enabled */
|
||||
int int_service; /* Int. service, 1=service */
|
||||
enum IntRequest int_pending; /* Pending interrupt request */
|
||||
|
||||
/* 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
|
||||
it has the default value INNER_LOOP_MAX, that should be close to the
|
||||
real cpu speed (~4MHz).
|
||||
*/
|
||||
int inner_loop; /* Inner loop multiplier */
|
||||
int inner_loop_max; /* Max value of inner_loop */
|
||||
#define INNER_LOOP_MAX 26
|
||||
#define INNER_LOOP_MED 13
|
||||
#define INNER_LOOP_MIN 2
|
||||
|
||||
#ifdef CPU_SPIN_LOOP
|
||||
int reset_req; /* Reset req. after shutdn */
|
||||
#endif
|
||||
};
|
||||
|
||||
enum ExitOption /* 2.1: EmulatorExit() option */
|
||||
{
|
||||
IMMEDIATE_EXIT,
|
||||
SAVE_AND_EXIT
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
extern struct CpuStatus cpu_status;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Chf condition codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define CPU_I_CALLED 101 /* Function %s called */
|
||||
#define CPU_I_EXECUTING 102 /* Executing @PC %X */
|
||||
#define CPU_I_SHUTDN 103 /* Shutdown */
|
||||
#define CPU_I_WAKE 104 /* Wake */
|
||||
#define CPU_I_INT 105 /* %s request accepted */
|
||||
#define CPU_I_INT_PENDING 106 /* %s request pending */
|
||||
#define CPU_I_RTI_LOOP 107 /* RTI loop to service %s */
|
||||
#define CPU_I_RTI_END 108 /* RTI returning */
|
||||
#define CPU_I_INTON 109 /* INTON servicing %s */
|
||||
#define CPU_I_REVISION 110 /* CPU emulation revision: %s */
|
||||
#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_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_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_ELAPSED 117 /* 3.1: Spent %d us in idle loop */
|
||||
#define CPU_I_HALT 118 /* 3.13: CPU halted */
|
||||
#define CPU_I_RUN 119 /* 3.13: CPU running */
|
||||
#define CPU_W_RESETTING 201 /* Resetting CPU */
|
||||
#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_SAVE 302 /* Can't save CPU status */
|
||||
#define CPU_E_NO_HALT 303 /* 3.13: Halt/Run not allowed */
|
||||
#define CPU_F_INTERR 401 /* Internal error %s */
|
||||
#define CPU_F_BAD_SHUTDN 402 /* Unexpected CPU shutdown */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
void CpuInit(void);
|
||||
void CpuReset(void);
|
||||
void CpuSave(void);
|
||||
void OneStep(void);
|
||||
void CpuIntRequest(enum IntRequest ireq);
|
||||
void CpuWake(void);
|
||||
void Emulator(void);
|
||||
void EmulatorIntRequest(void);
|
||||
void EmulatorInit(void); /* 2.1 */
|
||||
void EmulatorExit(enum ExitOption opt); /* 2.1 */
|
||||
int CpuHaltRequest(void); /* 3.13 */
|
||||
int CpuRunRequest(void); /* 3.13 */
|
||||
int CpuHaltAllowed(void); /* 3.13 */
|
||||
|
||||
Address Disassemble(Address pc, char ob[DISASSEMBLE_OB_SIZE]);
|
||||
void DumpCpuStatus(char ob[DUMP_CPU_STATUS_OB_SIZE]);
|
64
cpu.msf
Normal file
64
cpu.msf
Normal file
|
@ -0,0 +1,64 @@
|
|||
$ .+
|
||||
$ .identifier : $Id: cpu.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
$ .context : SATURN, Saturn CPU / HP48 emulator
|
||||
$ .title : $RCSfile: cpu.msf,v $
|
||||
$ .kind : Message catalog source
|
||||
$ .author : Ivan Cibrario B.
|
||||
$ .site : CSTV-CNR
|
||||
$ .creation : 13-Feb-1998
|
||||
$ .keywords : *
|
||||
$ .description :
|
||||
$ Message catalog source file for the CPU emulation modules.
|
||||
$ .notes :
|
||||
$ . $Log: cpu.msf,v $
|
||||
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
$ . Public release.
|
||||
$ .
|
||||
$ . Revision 3.13 2000/11/09 11:27:48 cibrario
|
||||
$ . Revised to add file selection box GUI element, CPU halt/run
|
||||
$ . requests and emulator's extended functions:
|
||||
$ .
|
||||
$ . - New messages: 118, 119, 303
|
||||
$ .
|
||||
$ . Revision 3.8 2000/10/19 14:56:52 cibrario
|
||||
$ . Bug fix:
|
||||
$ . Removed lines with empty directives
|
||||
$ .
|
||||
$ Revision 3.1 2000/09/20 13:44:30 cibrario
|
||||
$ Revised to implement passive CPU shutdown:
|
||||
$ - new messages 114, 115, 116, 117
|
||||
$ .
|
||||
$ Revision 1.1 1998/02/18 11:50:36 cibrario
|
||||
$ Initial revision
|
||||
$ .-
|
||||
|
||||
$set 1
|
||||
11 Cpu
|
||||
|
||||
$set 11
|
||||
101 Function [%s] called
|
||||
102 Executing @ PC[%05X]
|
||||
103 CPU shutdown executed
|
||||
104 CPU wake-up executed
|
||||
105 %s request accepted
|
||||
106 %s request pending
|
||||
107 RTI loop to service %s
|
||||
108 RTI returning
|
||||
109 INTON servicing %s
|
||||
110 CPU emulator [%s]
|
||||
111 Timer1 expired CTRL[%01X]
|
||||
112 Timer2 expired CTRL[%01X]
|
||||
113 Emulator interrupt request detected
|
||||
114 Timer[%s] Ctrl[%01X] Val[%08X]
|
||||
115 Timer[%s] expires in [%d]d ms
|
||||
116 Starting idle loop, timeout [%d]d ms
|
||||
117 Spooling up after [%d]d us in idle loop
|
||||
118 CPU halted by CpuHaltRequest()
|
||||
119 CPU awoken by CpuRunRequest()
|
||||
201 Can't restore CPU status from disk; resetting CPU
|
||||
202 Monitor command syntax error [%s]
|
||||
301 Bad opcode @ PC[%05X], N[%01X]
|
||||
302 Can't save CPU status to disk
|
||||
303 Halt/Run requests not allowed; #undef CPU_SPIN_SHUTDN
|
||||
401 Internal error [%s]
|
||||
402 Unexpected CPU shutdown
|
393
custom.texi
Normal file
393
custom.texi
Normal file
|
@ -0,0 +1,393 @@
|
|||
@c $Id: custom.texi,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
|
||||
@node Customizing saturn, The sutil Library, Command Line Options, Top
|
||||
@chapter Customizing saturn
|
||||
@cindex Customizing saturn
|
||||
|
||||
The @code{saturn} program uses OSF/Motif widgets to make up its
|
||||
user interface, and supports the standard X application
|
||||
resource mechanism for customization; in addition, it is fully
|
||||
internationalized and uses a message catalog to retrieve almost
|
||||
all error and informational messages the user will ever see.
|
||||
|
||||
Therefore, you can modify the ``look and feel'' of @code{saturn}
|
||||
to fit your preferences to a great extent, without touching
|
||||
the source code and/or rebuilding the executable.
|
||||
|
||||
This chapter deals with advanced customization, that is, X resources,
|
||||
message catalog, and so on, and does not discuss the command-line
|
||||
options of @code{saturn}; see @ref{Command Line Options}, for more
|
||||
information about command-line options.
|
||||
|
||||
@menu
|
||||
* Widget Tree::
|
||||
* Custom Resources::
|
||||
* Application Actions::
|
||||
* Message Catalog::
|
||||
* Environment Variables::
|
||||
* Customizing the Translation Table::
|
||||
* Customizing the Font Size::
|
||||
* Configuration Options::
|
||||
@end menu
|
||||
|
||||
|
||||
@node Widget Tree, Custom Resources, Customizing saturn, Customizing saturn
|
||||
@section Widget Tree
|
||||
@cindex Widget Tree
|
||||
|
||||
This is @code{saturn}'s widget tree; all widgets are standard Motif
|
||||
widgets. See the Motif documentation for more information about
|
||||
standard widget's resources.
|
||||
|
||||
@table @code
|
||||
@item main (XmMainWindow)
|
||||
This is the emulator's main window, and is a child of the main
|
||||
application shell.
|
||||
@item *fsb (XmFileSelectionBox)
|
||||
This is the file selection box that pops up when a fast load/save
|
||||
operation is started. Notice the star; it is there because this
|
||||
widget is wrapped in a dialog.
|
||||
@item *error (XmMessageBox)
|
||||
This is the message box that pops up when @code{saturn} wants to tell
|
||||
something to the user, usually when an error occurs. Notice the star; it
|
||||
is there because this widget is wrapped in a dialog.
|
||||
@item main.@var{faceplate} (XmRowColumn)
|
||||
This container contains all widgets of the calculator's faceplate.
|
||||
The name of this widget, @var{faceplate}, depends on the value
|
||||
of the custom resource @code{.face}; this way you can define
|
||||
a different set of resources for each faceplate.
|
||||
@item main.@var{faceplate}.kbd (XmForm)
|
||||
This form contains all calculator's keys.
|
||||
@item main.@var{faceplate}.kbd.@var{n} (XmForm)
|
||||
Another @code{XmForm}, containing all widgets pertaining to calculator's
|
||||
key number @var{n}.
|
||||
@item main.@var{faceplate}.kbd.@var{n}.ul (XmLabel)
|
||||
@itemx main.@var{faceplate}.kbd.@var{n}.ur (XmLabel)
|
||||
@itemx main.@var{faceplate}.kbd.@var{n}.ll (XmLabel)
|
||||
@itemx main.@var{faceplate}.kbd.@var{n}.lr (XmLabel)
|
||||
These widgets contain, respectively, the upper-left, upper-right,
|
||||
lower-left, and lower-right label of calculator's key number @var{n}.
|
||||
@item main.@var{faceplate}.kbd.@var{n}.btn (XmToggleButton)
|
||||
This widget represents calculator's key number @var{n}.
|
||||
@item main.@var{faceplate}.frame (XmFrame)
|
||||
This widget encloses the LCD display area.
|
||||
@item main.@var{faceplate}.frame.lcd (XmDrawingArea)
|
||||
This widget is the LCD display area of the emulated calculator.
|
||||
@item main.@var{faceplate}.msg (XmTextField)
|
||||
This text field is used by the emulator to display its most important
|
||||
messages; for example, it is used to display the name of the
|
||||
emulator's pseudo-terminal.
|
||||
@end table
|
||||
|
||||
In the list above:
|
||||
|
||||
@table @var
|
||||
@item faceplate
|
||||
is the name of the active calculator's faceplate selected by the
|
||||
@code{.face} custom resource.
|
||||
@item n
|
||||
is the ASCII decimal representation of a non-negative integer number,
|
||||
that identifies a calculator's key uniquely; its value goes from
|
||||
@code{0} to the value of the @var{faceplate}.@code{nKeys} resource minus
|
||||
one, inclusive.
|
||||
@end table
|
||||
|
||||
@node Custom Resources, Application Actions, Widget Tree, Customizing saturn
|
||||
@section Custom Resources
|
||||
@cindex Custom Resources
|
||||
|
||||
In addition to standard Motif resources, @code{saturn} has the
|
||||
following custom resources:
|
||||
|
||||
@table @code
|
||||
@item main.@var{faceplate}.nKeys
|
||||
This resource must translate into an integer, representing the number of
|
||||
keys that faceplate @var{faceplate} has.
|
||||
@item main.@var{faceplate}.kbd.@var{n}.btn.inOut
|
||||
This resource associates calculator's key number @var{n} with a
|
||||
combination of IN/OUT codes seen by the emulated CPU. It is a
|
||||
string, and can be either:
|
||||
|
||||
@table @code
|
||||
@item @var{o}/@var{i}
|
||||
When pressed, the key activates the bit(s) of the IN register specified
|
||||
by the @var{i} bit @strong{mask}, when bit @strong{number} @var{o} is
|
||||
set in the OUT register. Both @var{i} and @var{o} are hexadecimal
|
||||
constants. For example, on the HP49 the calculator's function key
|
||||
@code{F1} sets the IN bit mask @code{01} when OUT bit number @code{5} is set;
|
||||
accordingly, the IN/OUT mapping of this key is @code{5/01}.
|
||||
@item *
|
||||
This special value uniquely identifies the ON/Cancel key.
|
||||
@end table
|
||||
@item *compoundString
|
||||
This custom resource can be set for @code{XmLabel} and
|
||||
@code{XmToggleButton} widgets only and, when set, overrides the standard
|
||||
resource @code{labelString}. Its value is a string with the
|
||||
following syntax:
|
||||
|
||||
@example
|
||||
@var{compoundString}: ([# @var{fontlist_tag}] @var{string})*
|
||||
@end example
|
||||
|
||||
Here, @var{string} is a sequence of ordinary characters,
|
||||
excluding @code{#}, and @var{fontlist_tag} can be:
|
||||
@table @code
|
||||
@item #
|
||||
Put a single @code{#} character in current compound string segment.
|
||||
@item @var{space}
|
||||
Create a new compound string segment using @code{XmFONTLIST_DEFAULT_TAG}
|
||||
as tag.
|
||||
@item @var{tag}
|
||||
Create a new segment using @var{tag} as tag; @var{tag} can be
|
||||
any single character, except @code{#} and @var{space}.
|
||||
@end table
|
||||
|
||||
Each segment is limited to @code{MAX_CS_SEGMENT_LEN} characters; longer
|
||||
segments are silently truncated.
|
||||
|
||||
The resource is scanned from left to right according to the syntax
|
||||
described above. The result is a compound string (@code{XmString})
|
||||
that becomes the @code{labelString} resource of the target widget.
|
||||
The original value of the @code{labelString} resource is discarded
|
||||
when @code{compoundString} is defined. This resource allows you
|
||||
to have more than one font in button labels.
|
||||
@end table
|
||||
|
||||
In the list above:
|
||||
|
||||
@table @var
|
||||
@item faceplate
|
||||
is the name of the calculator's faceplate selected by the
|
||||
@code{.face} custom resource.
|
||||
@item n
|
||||
is the ASCII decimal representation of a non-negative integer number
|
||||
that uniquely identifies a calculator's key; its value goes from
|
||||
@code{0} to the value of the @var{faceplate}.@code{nKeys} resource minus
|
||||
one, inclusive.
|
||||
@end table
|
||||
|
||||
Notice also that all command-line options are mapped into custom
|
||||
top-level application resources, too; in this case, the name of the
|
||||
resource is the same as the name of the option. For example,
|
||||
the @code{-face} command-line option is mapped to the custom
|
||||
resource @code{.face}.
|
||||
|
||||
@node Application Actions, Message Catalog, Custom Resources, Customizing saturn
|
||||
@section Application Actions
|
||||
@cindex Application Actions
|
||||
|
||||
The emulator installs the application actions listed below:
|
||||
|
||||
@table @code
|
||||
@item kbdKeyPress
|
||||
@itemx kbdKeyRelease
|
||||
Both actions accept one string as argument; the string represents an
|
||||
IN/OUT mapping with the same syntax already described for the
|
||||
@code{inOut} custom resource. These functions command the emulation of
|
||||
a key press and key release event, respectively.
|
||||
@end table
|
||||
|
||||
These actions are useful to define keyboard shortcuts. For example, on
|
||||
the HP49 the calculator's function key @code{F1} sets the IN bit mask
|
||||
@code{01} when OUT bit number @code{5} is set; accordingly, the IN/OUT
|
||||
mapping of this key is @code{5/01}.
|
||||
|
||||
If you want to define the X keysym @code{F1} to act as a shortcut for
|
||||
this calculator's key, simply add the following two lines to the
|
||||
@code{translations} resource of your faceplate:
|
||||
|
||||
@example
|
||||
...
|
||||
<KeyDown>F1: kbdKeyPress(5/01) \n\
|
||||
<KeyUp>F1: kbdKeyRelease(5/01) \n\
|
||||
...
|
||||
@end example
|
||||
|
||||
|
||||
@node Message Catalog, Environment Variables, Application Actions, Customizing saturn
|
||||
@section Message Catalog
|
||||
@cindex Message Catalog
|
||||
|
||||
The @code{saturn} emulator opens the message catalog @code{saturn.cat}
|
||||
during startup, and retrieves all its messages from there. Internally,
|
||||
@code{saturn} uses a pair of integers to uniquely identify a message.
|
||||
|
||||
By default, that is, when the @code{NLSPATH} environment variable is not
|
||||
set, @code{saturn} first attempts to locate the message catalog in the
|
||||
system's default location of such files; if this first attempt fails,
|
||||
@code{saturn} prints a warning and generates an alternate catalog name
|
||||
using the directory name found in @code{argv[0]}; if even this second
|
||||
attempt fails, @code{saturn} tries again using the @code{C} locale
|
||||
instead of the current one. If all attempts fail, @code{saturn}
|
||||
terminated.
|
||||
|
||||
The @code{.msf} files found in the source distribution of @code{saturn}
|
||||
list all message codes and translate them into human-readable english
|
||||
messages; they can be used as a starting point to prepare message
|
||||
catalogs for additional languages. See the documentation of
|
||||
@code{gencat}, for more information about how to process them to
|
||||
generate a @code{.cat} file.
|
||||
|
||||
|
||||
@node Environment Variables, Customizing the Translation Table, Message Catalog, Customizing saturn
|
||||
@section Environment Variables
|
||||
@cindex Environment Variables
|
||||
|
||||
The @code{saturn} emulator looks at the following environment variables:
|
||||
|
||||
@table @code
|
||||
@item NLSPATH
|
||||
@itemx LC_ALL
|
||||
@itemx LC_MESSAGES
|
||||
@itemx LANG
|
||||
These environment variables are used to locate the @code{saturn}'s
|
||||
message catalog, and to specialize the load paths of application
|
||||
resources; see the documentation of @code{catopen()} and
|
||||
@code{XtResolvePathname()}, for more information.
|
||||
|
||||
@item DISPLAY
|
||||
This variable contains the default X display name used by @code{saturn}.
|
||||
|
||||
@item XENVIRONMENT
|
||||
This variable is used to locate the per-host user environment
|
||||
resources; see the documentation of @code{XtDisplayInitialize()}, for
|
||||
more information.
|
||||
|
||||
@item XUSERFILESEARCHPATH
|
||||
@itemx XAPPLRESDIR
|
||||
These variables control the loading process of the user's application
|
||||
resource file; see the documentation of @code{XtDisplayInitialize()}, for
|
||||
more information.
|
||||
|
||||
@item XFILESEARCHPATH
|
||||
This variable controls the loading process of the application class
|
||||
resource file; see the documentation of @code{XtDisplayInitialize()}, for
|
||||
more information.
|
||||
@end table
|
||||
|
||||
|
||||
@node Customizing the Translation Table, Customizing the Font Size, Environment Variables, Customizing saturn
|
||||
@section Customizing the Translation Table
|
||||
@cindex Customizing the Translation Table
|
||||
|
||||
As said before, all widgets in a given faceplate have their own
|
||||
translation table; this table is useful to define keyboard
|
||||
shortcuts. The default application resource file distributed
|
||||
with the emulator, @file{Saturn.ad}, already contains a
|
||||
predefined set of shortcuts; to customize it, proceed
|
||||
as follows:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Locate the translation table of the faceplate you are interested in.
|
||||
For example, the predefined HP49's faceplate name is @code{hp49}; the X
|
||||
resource specifier of its base translation table is:
|
||||
|
||||
@example
|
||||
*hp49*baseTranslations
|
||||
@end example
|
||||
|
||||
@item
|
||||
This resource has two lines of text for each key on the real keyboard
|
||||
you want to map on the emulated keyboard; for example, these lines map
|
||||
the @code{0} keypad key to the @code{0} key of the calculator:
|
||||
|
||||
@example
|
||||
<KeyDown>KP_0: kbdKeyPress(3/01) \n\
|
||||
<KeyUp>KP_0: kbdKeyRelease(3/01) \n\
|
||||
@end example
|
||||
|
||||
@item
|
||||
Here, @code{KP_0} is the name of the X keysym (representing a keyboard
|
||||
key or a combination of keys) that is currently mapped to the @code{0}
|
||||
key (@code{3/01} are the OUT/IN bit masks of the @code{0} key on the
|
||||
calculator, reflecting its wiring on the calculator's keyboard). To
|
||||
change the mapping to another key, simply replace the old X keysym name
|
||||
with the new one. For example, if you want to remap the @code{F8} key
|
||||
to the @code{0} key, update the lines above as follows:
|
||||
|
||||
@example
|
||||
<KeyDown>F8: kbdKeyPress(3/01) \n\
|
||||
<KeyUp>F8: kbdKeyRelease(3/01) \n\
|
||||
@end example
|
||||
|
||||
If you want to keep the existing mapping, too, duplicate the existing
|
||||
lines and change the X keysym on the duplicate only.
|
||||
|
||||
@item
|
||||
To get the keysym name of a given key you can use, for example, the
|
||||
@code{xev} utility: when you start it, it opens a small window on your
|
||||
screen and starts dumping on stdout all X events that window receives.
|
||||
Give the focus to the @code{xev} window, press the key you are
|
||||
interested in and look at its output; you should see something like:
|
||||
|
||||
@example
|
||||
KeyPress event, serial 22, synthetic NO, window 0x4800001,
|
||||
root 0x26, subw 0x0, time 18446744071995733347, (77,-9),
|
||||
root:(123,37),
|
||||
state 0x1, keycode 34 (keysym 0x7b, braceleft), same_screen YES,
|
||||
XLookupString gives 1 characters: "@{"
|
||||
@end example
|
||||
|
||||
Here, I pressed the @code{@{} key, and @code{xev} is telling me that its
|
||||
keysym name is @code{braceleft}. Use that name if you want to put the
|
||||
@code{@{} key in translations.
|
||||
|
||||
@item
|
||||
Be careful with continuation characters: each line of the translation
|
||||
table resource except the last one must end with @code{\n\}
|
||||
|
||||
@item
|
||||
Keep in mind that this is a simple example; actually, since
|
||||
@code{saturn} leverages the standard X Toolkit translation table parser
|
||||
and translator, it accepts the @strong{full} translation table syntax
|
||||
described in MIT documents, that is much more complex and powerful than
|
||||
this.
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@node Customizing the Font Size, Configuration Options, Customizing the Translation Table, Customizing saturn
|
||||
@section Customizing the Font Size
|
||||
@cindex Customizing the Font Size
|
||||
|
||||
The simplest way to change the size of the @code{saturn}'s main window
|
||||
is to change the size of the fonts it uses. To do this, locate the
|
||||
@code{fontList} resources of the faceplate you want to modify in your
|
||||
application resource file. For example, the default application
|
||||
resource file sets the following resources for the @code{hp49}
|
||||
faceplate:
|
||||
|
||||
@example
|
||||
*hp49.kbd*fontList: *helvetica-*-r-*-*-12-*,*symbol-*-*-*-*-12-*=S
|
||||
*hp49.kbd*btn.fontList: *helvetica-*-r-*-*-14-*,*symbol-*-*-*-*-14-*=S
|
||||
@end example
|
||||
|
||||
Fonts are selected with their standard XLFD font designators;
|
||||
in the above lines, @code{12} and @code{14} are the @code{pxlsz} specifiers.
|
||||
Make them smaller to reduce the font size; make them bigger to
|
||||
enlarge the font size. For example:
|
||||
|
||||
@example
|
||||
*hp49.kbd*fontList: *helvetica-*-r-*-*-8-*,*symbol-*-*-*-*-8-*=S
|
||||
*hp49.kbd*btn.fontList: *helvetica-*-r-*-*-10-*,*symbol-*-*-*-*-10-*=S
|
||||
@end example
|
||||
|
||||
reduces the window size to about 400x700 pixels on my system.
|
||||
|
||||
If this is not enough, you can define a brand new keyboard layout;
|
||||
again, no need to touch the source code, only resources must be
|
||||
updated. Hint: for each key, its @code{topPosition},
|
||||
@code{bottomPosition}, @code{leftPosition} and @code{rightPosition}
|
||||
resources determine where the key is located on the keyboard faceplate.
|
||||
|
||||
|
||||
@node Configuration Options, , Customizing the Font Size, Customizing saturn
|
||||
@section Configuration Options
|
||||
@cindex Configuration Options
|
||||
|
||||
In addition to the run-time customization methods mentioned above,
|
||||
@code{saturn} has build-time configuration options, too. See the
|
||||
documentation embedded in the source file @code{config.h}, for more
|
||||
information. Of course, you can change these options only if you build
|
||||
@code{saturn} yourself from the source distribution.
|
127
debug.c
Normal file
127
debug.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: debug.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: debug.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 28-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
Debugging support.
|
||||
|
||||
.include : debug.h
|
||||
|
||||
.notes :
|
||||
$Log: debug.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:32 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 1.1 1998/02/17 11:42:30 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: debug.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID DEBUG_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Static/Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG_LEVEL
|
||||
int debug_level = DEBUG_LEVEL;
|
||||
#else
|
||||
int debug_level = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Public functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* .+
|
||||
|
||||
.title : SetDebugLevel
|
||||
.kind : C function
|
||||
.creation : 28-Jan-1998
|
||||
.description :
|
||||
If runtime debug support is enabled (symbol DEBUG defined during executable
|
||||
image build) this function updates the 'debug_level' flag, otherwise
|
||||
it signals a condition and does nothing more.
|
||||
|
||||
.call :
|
||||
SetDebugLevel(new_level)
|
||||
.input :
|
||||
int new_level, new value of the debug_level flag
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
DEBUG_W_NOT_SUPPORTED
|
||||
.notes :
|
||||
1.1, 28-Jan-1998, creation
|
||||
|
||||
.- */
|
||||
void SetDebugLevel(int new_level)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
debug_level = new_level;
|
||||
#else
|
||||
ChfCondition DEBUG_W_NOT_SUPPORTED, CHF_WARNING ChfEnd;
|
||||
ChfSignal();
|
||||
#endif
|
||||
}
|
173
debug.h
Normal file
173
debug.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: debug.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: debug.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 19-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This header defines the following macros:
|
||||
|
||||
- debug0(debug_class, condition_code)
|
||||
- debug1(debug_class, condition_code, arg_1)
|
||||
- debug2(debug_class, condition_code, arg_1, arg_2)
|
||||
- debug3(debug_class, condition_code, arg_1, arg_2, arg_3)
|
||||
|
||||
used throughout the source code for debugging purposes.
|
||||
|
||||
If the DEBUG cpp symbol is defined, each invocation of these macros is
|
||||
expanded into a block of code that, at runtime, checks if the global
|
||||
variable 'debug_level' has set at least one of the bit 'debug_class' has
|
||||
set (in other words, it checks if the current debug level enables at
|
||||
least one of the classes to which the debugging condition belongs).
|
||||
|
||||
If this condition is met, the code generates and immediately signals
|
||||
the given condition code using the Chf facility, with severity CHF_INFO,
|
||||
otherwise nothing is done.
|
||||
|
||||
The arguments arg_1, arg_2, and arg_3 are used as additional arguments
|
||||
of the condition.
|
||||
|
||||
If the DEBUG cpp symbol is not defined, the macros are defined as a null
|
||||
macros.
|
||||
|
||||
.include : Chf.h
|
||||
|
||||
.notes :
|
||||
$Log: debug.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.13 2000/11/09 11:28:34 cibrario
|
||||
Revised to add file selection box GUI element, CPU halt/run
|
||||
requests and emulator's extended functions:
|
||||
|
||||
- Added new debug class: DEBUG_C_X_FUNC
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:32 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.3 2000/09/26 15:20:40 cibrario
|
||||
Revised to implement Flash ROM write access:
|
||||
- Added new debug class: DEBUG_C_FLASH
|
||||
|
||||
* Revision 2.7 2000/09/19 10:51:13 cibrario
|
||||
* Added new debug class: DEBUG_C_MOD_CACHE
|
||||
*
|
||||
* Revision 2.5 2000/09/14 14:34:13 cibrario
|
||||
* Added new debug class: DEBUG_C_SERIAL
|
||||
*
|
||||
* Revision 1.1 1998/02/18 11:54:33 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define debug_preamble(debug_class, condition_code) \
|
||||
{ \
|
||||
extern int debug_level; \
|
||||
if(debug_level & (debug_class)) \
|
||||
{ \
|
||||
ChfCondition (condition_code), CHF_INFO
|
||||
|
||||
#define debug_postamble \
|
||||
ChfEnd; \
|
||||
ChfSignal(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define debug0(debug_class, condition_code) \
|
||||
debug_preamble(debug_class, condition_code) \
|
||||
debug_postamble
|
||||
|
||||
#define debug1(debug_class, condition_code, arg_1) \
|
||||
debug_preamble(debug_class, condition_code), arg_1 \
|
||||
debug_postamble
|
||||
|
||||
#define debug2(debug_class, condition_code, arg_1, arg_2) \
|
||||
debug_preamble(debug_class, condition_code), arg_1, arg_2 \
|
||||
debug_postamble
|
||||
|
||||
#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_postamble
|
||||
|
||||
#else
|
||||
|
||||
#define debug0(debug_class, condition_code)
|
||||
#define debug1(debug_class, condition_code, arg_1)
|
||||
#define debug2(debug_class, condition_code, arg_1, arg_2)
|
||||
#define debug3(debug_class, condition_code, arg_1, arg_2, arg_3)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Debug classes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define DEBUG_C_TRACE 0x8000 /* Function Call trace */
|
||||
#define DEBUG_C_MODULES 0x4000 /* Modules configuration */
|
||||
#define DEBUG_C_DISPLAY 0x2000 /* Display activity */
|
||||
#define DEBUG_C_INT 0x1000 /* Interrupt activity */
|
||||
#define DEBUG_C_TIMERS 0x0800 /* Timers activity */
|
||||
#define DEBUG_C_SERIAL 0x0400 /* 2.5: Serial port activity */
|
||||
#define DEBUG_C_MOD_CACHE 0x0200 /* 2.7: Module cache */
|
||||
#define DEBUG_C_IMPLEMENTATION 0x0100 /* Feature implementation */
|
||||
#define DEBUG_C_FLASH 0x0080 /* 3.3: Flash ROM */
|
||||
#define DEBUG_C_X_FUNC 0x0040 /* 3.13: Extended functions */
|
||||
#define DEBUG_C_REVISION 0x0010 /* Revision information */
|
||||
#define DEBUG_C_X11 0x0001 /* X11 Interface */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Chf condition codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define DEBUG_W_NOT_SUPPORTED 201 /* Debug not supported */
|
||||
#define DEBUG_W_BAD_CMD 202 /* Invalid command */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
void SetDebugLevel(int new_level);
|
29
debug.msf
Normal file
29
debug.msf
Normal file
|
@ -0,0 +1,29 @@
|
|||
$ .+
|
||||
$ .identifier : $Id: debug.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
$ .context : SATURN, Saturn CPU / HP48 emulator
|
||||
$ .title : $RCSfile: debug.msf,v $
|
||||
$ .kind : Message catalog source
|
||||
$ .author : Ivan Cibrario B.
|
||||
$ .site : CSTV-CNR
|
||||
$ .creation : 13-Feb-1998
|
||||
$ .keywords : *
|
||||
$ .description :
|
||||
$ Message catalog source file for the debugging support modules.
|
||||
$ .notes :
|
||||
$ . $Log: debug.msf,v $
|
||||
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
$ . Public release.
|
||||
$ .
|
||||
$ . Revision 3.8 2000/10/19 14:55:10 cibrario
|
||||
$ . Bug fix:
|
||||
$ . Removed lines with empty directives
|
||||
$ .
|
||||
$ Revision 1.1 1998/02/18 11:54:02 cibrario
|
||||
$ Initial revision
|
||||
$ .-
|
||||
|
||||
$set 1
|
||||
30 Debug
|
||||
|
||||
$set 30
|
||||
201 Debug not supported; Rebuild with -DDEBUG
|
322
disk_io.c
Normal file
322
disk_io.c
Normal file
|
@ -0,0 +1,322 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: disk_io.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: disk_io.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 23-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the disk I/O functions used by the emulator to
|
||||
save and restore the machine status to/from disk files.
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, disk_io.h
|
||||
|
||||
.notes :
|
||||
$Log: disk_io.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:36 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 1.1 1998/02/17 11:54:38 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: disk_io.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "disk_io.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ReadNibblesFromFile
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function reads 'size' nibbles from the disk file named 'name',
|
||||
and stores them into main memory starting from 'dest'. It returns to the
|
||||
caller a status code.
|
||||
|
||||
.call :
|
||||
st = ReadNibbledFromFile(name, size, dest);
|
||||
.input :
|
||||
const char *name, file name
|
||||
int size, size of the file (nibbles, NOT bytes)
|
||||
.output :
|
||||
Nibble *dest, pointer to the destination memory area
|
||||
int st, status code
|
||||
.status_codes :
|
||||
DISK_IO_I_CALLED (signalled)
|
||||
DISK_IO_E_OPEN
|
||||
DISK_IO_E_GETC
|
||||
.notes :
|
||||
1.1, 11-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
int ReadNibblesFromFile(const char *name, int size, Nibble *dest)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
int by;
|
||||
int st = DISK_IO_S_OK;
|
||||
|
||||
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadNibblesFromFile");
|
||||
|
||||
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;
|
||||
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
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function writes 'size' nibbles taken from 'src' into the file 'name'.
|
||||
It returns to the caller a status code
|
||||
|
||||
.call :
|
||||
st = WriteNibblesToFile(src, size, name);
|
||||
.input :
|
||||
const Nibble *src, pointer to data to be written
|
||||
int size, # of nibble to write
|
||||
const char *name, file name
|
||||
.output :
|
||||
int st, status code
|
||||
.status_codes :
|
||||
DISK_IO_I_CALLED (signalled)
|
||||
DISK_IO_E_OPEN
|
||||
DISK_IO_E_PUTC
|
||||
DISK_IO_E_CLOSE
|
||||
.notes :
|
||||
1.1, 11-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
int WriteNibblesToFile(const Nibble *src, int size, const char *name)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
int by;
|
||||
int st = DISK_IO_S_OK;
|
||||
|
||||
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteNibblesToFile");
|
||||
|
||||
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;
|
||||
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
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function reads the contents of the structure 's', with size 's_size',
|
||||
from the disk file 'name' and returns a status code to the caller.
|
||||
|
||||
.call :
|
||||
st = ReadStructFromFile(name, s_size, s);
|
||||
.input :
|
||||
const char *name, file name
|
||||
size_t s_size, structure size
|
||||
.output :
|
||||
void *s, pointer to the structure
|
||||
.status_codes :
|
||||
DISK_IO_I_CALLED (signalled)
|
||||
DISK_IO_E_OPEN
|
||||
DISK_IO_E_READ
|
||||
.notes :
|
||||
1.1, 11-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
int ReadStructFromFile(const char *name, size_t s_size, void *s)
|
||||
{
|
||||
FILE *f;
|
||||
int st = DISK_IO_S_OK;
|
||||
|
||||
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadStructFromFile");
|
||||
|
||||
if((f = fopen(name, "rb")) == (FILE *)NULL)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
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);
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : WriteStructToFile
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function writes the structure 's', with size 's_size', to the file
|
||||
'name' and returns to the caller a status code.
|
||||
|
||||
.call :
|
||||
st =WriteStructToFile(s, s_size, name);
|
||||
.input :
|
||||
const void *s, pointer to the structure to be written
|
||||
size_t s_size, structure size
|
||||
const char *name, output file name
|
||||
.output :
|
||||
int st, status code
|
||||
.status_codes :
|
||||
DISK_IO_I_CALLED (signalled)
|
||||
DISK_IO_E_OPEN
|
||||
DISK_IO_E_WRITE
|
||||
DISK_IO_E_CLOSE
|
||||
.notes :
|
||||
1.1, 11-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
int WriteStructToFile(const void *s, size_t s_size, const char *name)
|
||||
{
|
||||
FILE *f;
|
||||
int st = DISK_IO_S_OK;
|
||||
|
||||
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteStructToFile");
|
||||
|
||||
if((f = fopen(name, "wb")) == (FILE *)NULL)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
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)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
100
disk_io.h
Normal file
100
disk_io.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: disk_io.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: disk_io.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 28-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This header declares the disk I/O functions used by the emulator to
|
||||
save/restore the machine stats to/from disk files.
|
||||
|
||||
.include : config.h machdep.h cpu.h
|
||||
|
||||
.notes :
|
||||
$Log: disk_io.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.14 2000/11/13 10:31:16 cibrario
|
||||
Implemented fast load/save; improved keyboard interface emulation at
|
||||
high emulated CPU speed:
|
||||
|
||||
- New condition codes: DISK_IO_E_BAD_HDR, DISK_IO_E_SIZE
|
||||
- New prototypes: ReadObjectFromFile(), WriteObjectToFile()
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:36 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 1.1 1998/02/17 11:55:02 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Chf condition codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define DISK_IO_S_OK 0 /* Function completed succesfully */
|
||||
#define DISK_IO_I_CALLED 101 /* Function %s called */
|
||||
#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_PUTC 403 /* putc() to 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_CLOSE 406 /* Close file %s failed */
|
||||
#define DISK_IO_E_BAD_HDR 407 /* File %s has a bad header */
|
||||
#define DISK_IO_E_SIZE 408 /* File %s too large */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int ReadNibblesFromFile(const char *name, int size, Nibble *dest);
|
||||
int WriteNibblesToFile(const Nibble *src, int size, const char *name);
|
||||
int ReadStructFromFile(const char *name, size_t s_size, void *s);
|
||||
int WriteStructToFile(const void *s, size_t s_size, const char *name);
|
||||
|
||||
int ReadObjectFromFile(
|
||||
const char *name, const char *hdr, Address start, Address end);
|
||||
int WriteObjectToFile(
|
||||
Address start, Address end, const char *hdr, const char *name);
|
44
disk_io.msf
Normal file
44
disk_io.msf
Normal file
|
@ -0,0 +1,44 @@
|
|||
$ .+
|
||||
$ .identifier : $Id: disk_io.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
$ .context : SATURN, Saturn CPU / HP48 emulator
|
||||
$ .title : $RCSfile: disk_io.msf,v $
|
||||
$ .kind : Message catalog source
|
||||
$ .author : Ivan Cibrario B.
|
||||
$ .site : CSTV-CNR
|
||||
$ .creation : 13-Feb-1998
|
||||
$ .keywords : *
|
||||
$ .description :
|
||||
$ Message catalog source file for the disk I/O functions.
|
||||
$ .notes :
|
||||
$ . $Log: disk_io.msf,v $
|
||||
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
$ . Public release.
|
||||
$ .
|
||||
$ . Revision 3.14 2000/11/13 10:32:24 cibrario
|
||||
$ . Implemented fast load/save; improved keyboard interface emulation at
|
||||
$ . high emulated CPU speed:
|
||||
$ .
|
||||
$ . - Fixed spelling error in message 405
|
||||
$ . - Added new messages: 407, 408
|
||||
$ .
|
||||
$ . Revision 3.8 2000/10/19 14:58:41 cibrario
|
||||
$ . Bug fix:
|
||||
$ . Removed lines with empty directives
|
||||
$ .
|
||||
$ Revision 1.1 1998/02/17 11:54:49 cibrario
|
||||
$ Initial revision
|
||||
$ .-
|
||||
|
||||
$set 1
|
||||
13 Disk_IO
|
||||
|
||||
$set 13
|
||||
101 Function [%s] called
|
||||
401 Can't open file [%s]
|
||||
402 getc() failed reading file [%s]
|
||||
403 putc() failed writing file [%s]
|
||||
404 fread() failed reading file [%s]
|
||||
405 fwrite() failed writing file [%s]
|
||||
406 Close file [%s] failed
|
||||
407 File [%s] has a bad header
|
||||
408 File [%s] is too large
|
317
disk_io_obj.c
Normal file
317
disk_io_obj.c
Normal file
|
@ -0,0 +1,317 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: disk_io_obj.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HPxx emulator
|
||||
.title : $RCSfile: disk_io_obj.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : IRITI-CNR
|
||||
.creation : 10-Nov-2000
|
||||
.keywords : *
|
||||
.description :
|
||||
This module implements the disk I/O functions used by the emulator to
|
||||
save and restore an object to/from disk files.
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, disk_io.h
|
||||
|
||||
.notes :
|
||||
$Log: disk_io_obj.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.14 2000/11/13 11:24:20 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: disk_io_obj.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "disk_io.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID DISK_IO_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ReadObjectFromFile
|
||||
.kind : C function
|
||||
.creation : 10-Nov-2000
|
||||
.description :
|
||||
This function reads an object from file 'name' and stores it into
|
||||
the calculator's memory from nibble address 'start' inclusive to nibble
|
||||
address 'end' exclusive.
|
||||
|
||||
The presence of header 'hdr' in the disk file is checked, then the
|
||||
header is stripped before starting the transfer. In 'hdr', '?'
|
||||
is a wildcard character that matches any input character.
|
||||
|
||||
Objects with an odd number of nibbles are padded to an even
|
||||
size adding a 0 nibble to their end; the trailing zero *is* stored
|
||||
in calculator's memory.
|
||||
|
||||
When the object size exceeds the available space this function
|
||||
transfers its head anyway, thereby corrupting the calculator's
|
||||
memory between 'start' and 'end', except the first N_SAVE_AREA nibbles.
|
||||
|
||||
This function returns to the caller a status code.
|
||||
|
||||
.call :
|
||||
st = ReadObjectFromFile(name, hdr, start, end);
|
||||
|
||||
.input :
|
||||
const char *name, input file name
|
||||
const char *hdr, file header
|
||||
Address start, start address (inclusive)
|
||||
Address end, end address (exclusive)
|
||||
.output :
|
||||
int st, status code
|
||||
.status_codes :
|
||||
DISK_IO_I_CALLED (signalled)
|
||||
DISK_IO_E_OPEN
|
||||
DISK_IO_E_GETC
|
||||
DISK_IO_E_BAD_HDR
|
||||
DISK_IO_E_SIZE
|
||||
.notes :
|
||||
3.14, 10-Nov-2000, creation
|
||||
|
||||
.- */
|
||||
int ReadObjectFromFile(
|
||||
const char *name, const char *hdr, Address start, Address end)
|
||||
{
|
||||
size_t hdr_len = strlen(hdr);
|
||||
FILE *f;
|
||||
int i;
|
||||
int by;
|
||||
Address cur;
|
||||
|
||||
#define N_SAVE_AREA 10
|
||||
Nibble save_area[N_SAVE_AREA];
|
||||
|
||||
int st = DISK_IO_S_OK;
|
||||
|
||||
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "ReadObjectFromFile");
|
||||
|
||||
/* Save first nibbles of target space into save_area */
|
||||
for(cur=start, i=0; cur < end && i<N_SAVE_AREA; cur++, i++)
|
||||
save_area[i] = ReadNibble(cur);
|
||||
|
||||
if((f = fopen(name, "rb")) == (FILE *)NULL)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Check and skip header */
|
||||
for(i=0; i<hdr_len; i++)
|
||||
{
|
||||
by = getc(f);
|
||||
|
||||
if(by == EOF)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
else if(hdr[i] != '?' && by != hdr[i])
|
||||
{
|
||||
ChfCondition st=DISK_IO_E_BAD_HDR, CHF_ERROR, name ChfEnd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(st == DISK_IO_S_OK)
|
||||
{
|
||||
cur = start;
|
||||
|
||||
/* Header check/skip OK; transfer */
|
||||
while((by = getc(f)) != EOF)
|
||||
{
|
||||
/* Next byte available in by; check available space */
|
||||
if(cur >= end-1)
|
||||
{
|
||||
ChfCondition st=DISK_IO_E_SIZE, CHF_ERROR, name ChfEnd;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Store it */
|
||||
WriteNibble(cur++, (Nibble)(by & 0x0F));
|
||||
WriteNibble(cur++, (Nibble)((by & 0xF0) >> 4));
|
||||
}
|
||||
|
||||
/* Check why getc() failed */
|
||||
if(ferror(f) && !feof(f))
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_GETC, CHF_ERROR, name ChfEnd;
|
||||
}
|
||||
|
||||
/* Recover from save_area if transfer failed */
|
||||
if(st)
|
||||
for(cur=start, i=0; cur < end && i<N_SAVE_AREA; cur++, i++)
|
||||
WriteNibble(cur, save_area[i]);
|
||||
}
|
||||
|
||||
(void)fclose(f);
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : WriteObjectToFile
|
||||
.kind : C function
|
||||
.creation : 10-Nov-2000
|
||||
.description :
|
||||
This function writes an object located in calculator's memory,
|
||||
from nibble address 'start' inclusive to nibble address 'end' exclusive,
|
||||
into the file 'name'. The header 'hdr' is prepended to the actual
|
||||
object and objects with an odd number of nibbles are padded to an even
|
||||
size adding a 0 nibble to their end. In 'hdr', the wildcard character
|
||||
'?' is replaced by 'S' when the header is written on disk.
|
||||
|
||||
This function returns to the caller a status code.
|
||||
|
||||
.call :
|
||||
st = WriteObjectToFile(start, end, hdr, name);
|
||||
.input :
|
||||
Address start, start address (inclusive)
|
||||
Address end, end address (exclusive)
|
||||
const char *hdr, file header
|
||||
const char *name, output file name
|
||||
.output :
|
||||
int st, status code
|
||||
.status_codes :
|
||||
DISK_IO_I_CALLED (signalled)
|
||||
DISK_IO_E_OPEN
|
||||
DISK_IO_E_PUTC
|
||||
DISK_IO_E_CLOSE
|
||||
.notes :
|
||||
3.14, 10-Nov-2000, creation
|
||||
|
||||
.- */
|
||||
int WriteObjectToFile(
|
||||
Address start, Address end, const char *hdr, const char *name)
|
||||
{
|
||||
size_t hdr_len = strlen(hdr);
|
||||
FILE *f;
|
||||
int i;
|
||||
int by;
|
||||
Address cur;
|
||||
|
||||
int st = DISK_IO_S_OK;
|
||||
|
||||
debug1(DEBUG_C_TRACE, DISK_IO_I_CALLED, "WriteObjectFromFile");
|
||||
|
||||
if((f = fopen(name, "wb")) == (FILE *)NULL)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_OPEN, CHF_ERROR, name ChfEnd;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Write header; replace wildcard character '?' with 'S' */
|
||||
for(i=0; i<hdr_len; i++)
|
||||
{
|
||||
if(putc(hdr[i] == '?' ? 'S' : hdr[i], f) == EOF)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(st == DISK_IO_S_OK)
|
||||
{
|
||||
cur = start;
|
||||
|
||||
while(cur < end-1)
|
||||
{
|
||||
/* Make a byte with two nibbles */
|
||||
by = (int)ReadNibble(cur++);
|
||||
by |= (int)ReadNibble(cur++) << 4;
|
||||
|
||||
if(putc(by, f) == EOF)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the last odd nibble, if necessary */
|
||||
if(st == DISK_IO_S_OK && cur == end-1)
|
||||
{
|
||||
by = (int)ReadNibble(cur++);
|
||||
|
||||
if(putc(by, f) == EOF)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_PUTC, CHF_ERROR, name ChfEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the output file anyway */
|
||||
if(fclose(f) == EOF)
|
||||
{
|
||||
ChfErrnoCondition;
|
||||
ChfCondition st=DISK_IO_E_CLOSE, CHF_ERROR, name ChfEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return st;
|
||||
}
|
628
display.c
Normal file
628
display.c
Normal file
|
@ -0,0 +1,628 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: display.c,v 4.1.1.1 2002/11/11 16:12:46 cibrario Exp $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: display.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 29-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This source module emulates the Lcd driver of the Yorke chip.
|
||||
|
||||
References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
NOTE: In the current (r1.1) implementation, the control fields
|
||||
mod_status.hdw.lcd_offset and mod_status.hdw.lcd_contrast are
|
||||
not supported. Therefore, the emulation accuracy is sometimes
|
||||
poor; for example, the Equation Writer does not work well with
|
||||
large equations.
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, modules.h, display.h
|
||||
|
||||
.notes :
|
||||
$Log: display.c,v $
|
||||
Revision 4.1.1.1 2002/11/11 16:12:46 cibrario
|
||||
Small screen support; preliminary
|
||||
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:37 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.8 2000/10/23 13:15:36 cibrario
|
||||
Bug fix:
|
||||
In InitLcd(), added a clip rectangle to GC, to avoid drawing non-existent
|
||||
pixels, that is, pixels that *do* exist in the frame buffer, but should
|
||||
never be viewed on screen.
|
||||
|
||||
Revision 3.5 2000/10/02 09:44:42 cibrario
|
||||
Linux support:
|
||||
- gcc does not like array subscripts with type 'char', and it is right.
|
||||
|
||||
Revision 3.1 2000/09/20 13:47:58 cibrario
|
||||
Minor updates and fixes to avoid gcc compiler warnings on Solaris
|
||||
when -ansi -pedantic -Wall options are selected.
|
||||
|
||||
* Revision 1.1 1998/02/17 14:14:39 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: display.c,v 4.1.1.1 2002/11/11 16:12:46 cibrario Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h> /* 3.1: memset() */
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "display.h"
|
||||
#include "x11.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID X11_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
#ifndef LCD_MAG
|
||||
# define LCD_MAG 2 /* 4.1.1.1: Compat. default */
|
||||
#endif
|
||||
|
||||
#define NIBBLES_PER_ROW 34 /* 136 pixel total */
|
||||
#define MAX_ROWS 64 /* 64 rows total */
|
||||
#define N_ANN 6 /* # of annunciators */
|
||||
#define LCD_X_ORIGIN 1+4*(LCD_MAG-1) /* x origin */
|
||||
|
||||
#if LCD_MAG==1
|
||||
# define LCD_Y_ORIGIN 14 /* y origin */
|
||||
#else
|
||||
# define LCD_Y_ORIGIN 20 /* y origin */
|
||||
#endif
|
||||
|
||||
/* 3.8: Origin and size of clip rectangle */
|
||||
#define LCD_CLIP_X_ORIGIN LCD_X_ORIGIN
|
||||
#define LCD_CLIP_Y_ORIGIN 0 /* Don't clip annunciators */
|
||||
#define LCD_CLIP_WIDTH 131*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
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Static/Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static /*const*/ char nibble_bitmap_data[NIBBLE_VALUES][LCD_MAG] =
|
||||
{
|
||||
#if LCD_MAG==1
|
||||
{ 0x00 }, /* ---- */
|
||||
{ 0x01 }, /* *--- */
|
||||
{ 0x02 }, /* -*-- */
|
||||
{ 0x03 }, /* **-- */
|
||||
{ 0x04 }, /* --*- */
|
||||
{ 0x05 }, /* *-*- */
|
||||
{ 0x06 }, /* -**- */
|
||||
{ 0x07 }, /* ***- */
|
||||
{ 0x08 }, /* ---* */
|
||||
{ 0x09 }, /* *--* */
|
||||
{ 0x0a }, /* -*-* */
|
||||
{ 0x0b }, /* **-* */
|
||||
{ 0x0c }, /* --** */
|
||||
{ 0x0d }, /* *-** */
|
||||
{ 0x0e }, /* -*** */
|
||||
{ 0x0f } /* **** */
|
||||
#elif LCD_MAG==2
|
||||
{ 0x00, 0x00 }, /* ---- */
|
||||
{ 0x03, 0x03 }, /* *--- */
|
||||
{ 0x0c, 0x0c }, /* -*-- */
|
||||
{ 0x0f, 0x0f }, /* **-- */
|
||||
{ 0x30, 0x30 }, /* --*- */
|
||||
{ 0x33, 0x33 }, /* *-*- */
|
||||
{ 0x3c, 0x3c }, /* -**- */
|
||||
{ 0x3f, 0x3f }, /* ***- */
|
||||
{ 0xc0, 0xc0 }, /* ---* */
|
||||
{ 0xc3, 0xc3 }, /* *--* */
|
||||
{ 0xcc, 0xcc }, /* -*-* */
|
||||
{ 0xcf, 0xcf }, /* **-* */
|
||||
{ 0xf0, 0xf0 }, /* --** */
|
||||
{ 0xf3, 0xf3 }, /* *-** */
|
||||
{ 0xfc, 0xfc }, /* -*** */
|
||||
{ 0xff, 0xff } /* **** */
|
||||
#else
|
||||
# error "Bad LCD_MAG; supported values are 1 and 2"
|
||||
#endif
|
||||
};
|
||||
|
||||
static /*const*/ struct
|
||||
{
|
||||
int mask; /* Bit mask */
|
||||
int x, y; /* Position */
|
||||
int w, h; /* Width, Height */
|
||||
char bitmap_data[24]; /* Bitmap data */
|
||||
}
|
||||
|
||||
#define ANN_X(i) (8*LCD_MAG+(22*LCD_MAG+1)*i)
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static Nibble lcd_buffer[MAX_ROWS][NIBBLES_PER_ROW];
|
||||
static int ann_buffer;
|
||||
static int clean;
|
||||
|
||||
static Display *display;
|
||||
static Window window;
|
||||
static GC gc;
|
||||
static unsigned long fg_pixel, bg_pixel;
|
||||
static unsigned int depth;
|
||||
|
||||
static Pixmap nibble_pixmap[NIBBLE_VALUES];
|
||||
static Pixmap ann_pixmap[N_ANN];
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* .+
|
||||
|
||||
.title : InitPixmaps
|
||||
.kind : C function
|
||||
.creation : 29-Jan-1998
|
||||
.description :
|
||||
This function initializes the pixmaps for the Lcd screen elements and
|
||||
stores them into the appropriate global variables.
|
||||
|
||||
.call :
|
||||
InitPixmaps();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
X11_I_CALLED
|
||||
X11_F_X_ERROR
|
||||
.notes :
|
||||
1.1, 29-Jan-1998, creation
|
||||
|
||||
.- */
|
||||
static void InitPixmaps(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
debug1(DEBUG_C_TRACE, X11_I_CALLED, "InitPixmaps");
|
||||
|
||||
/* Initialize nibble_pixmap */
|
||||
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, bg_pixel, depth
|
||||
)) ==
|
||||
None)
|
||||
{
|
||||
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize ann_pixmap */
|
||||
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,
|
||||
fg_pixel, bg_pixel, depth
|
||||
)) ==
|
||||
None)
|
||||
{
|
||||
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ClearLcd
|
||||
.kind : C function
|
||||
.creation : 29-Jan-1998
|
||||
.description :
|
||||
This function clears the Lcd screen
|
||||
|
||||
.call :
|
||||
ClearLcd();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
X11_I_CALLED
|
||||
.notes :
|
||||
1.1, 29-Jan-1998, creation
|
||||
|
||||
.- */
|
||||
static void ClearLcd(void)
|
||||
{
|
||||
debug1(DEBUG_C_TRACE, X11_I_CALLED, "ClearLcd");
|
||||
|
||||
/* Clear Lcd display */
|
||||
(void)memset((void *)lcd_buffer, 0, sizeof(lcd_buffer));
|
||||
ann_buffer = 0;
|
||||
|
||||
XClearWindow(display, window);
|
||||
XFlush(display);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Public funcitons
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* .+
|
||||
|
||||
.title : InitLcd
|
||||
.kind : C function
|
||||
.creation : 29-Jan-1998
|
||||
.description :
|
||||
This function initializes the Lcd driver emulator and prepares it for use.
|
||||
The LCD screen is initially cleared.
|
||||
|
||||
.call :
|
||||
InitLcd(lcd_display, lcd_window, lcd_fg_pixel, lcd_bg_pixel);
|
||||
.input :
|
||||
Display *lcd_display, X display
|
||||
Window lcd_window, X window to be used for display
|
||||
unsigned long lcd_fg_pixel, foreground color to be used
|
||||
unsigned long lcd_bg_pixel, background color to be used
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
X11_I_CALLED
|
||||
X11_F_X_ERROR
|
||||
.notes :
|
||||
1.1, 29-Jan-1998, creation
|
||||
3.8, 23-Oct-2000, bug fix:
|
||||
- added clip rectangle to GC, to avoid drawing non-existent pixels.
|
||||
|
||||
.- */
|
||||
void InitLcd(Display *lcd_display, Window lcd_window,
|
||||
unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel)
|
||||
{
|
||||
XWindowAttributes xwa;
|
||||
XGCValues gc_values;
|
||||
|
||||
debug1(DEBUG_C_TRACE, X11_I_CALLED, "InitLcdWindow");
|
||||
|
||||
display = lcd_display;
|
||||
window = lcd_window;
|
||||
fg_pixel = lcd_fg_pixel;
|
||||
bg_pixel = lcd_bg_pixel;
|
||||
|
||||
/* Get window attributes and initialize window depth */
|
||||
if(XGetWindowAttributes(display, window, &xwa) == 0)
|
||||
{
|
||||
ChfCondition X11_F_X_ERROR, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
depth = xwa.depth;
|
||||
|
||||
/* Create GC */
|
||||
gc_values.function = GXcopy;
|
||||
gc_values.plane_mask = AllPlanes;
|
||||
gc_values.subwindow_mode = IncludeInferiors;
|
||||
gc_values.foreground = lcd_fg_pixel;
|
||||
gc_values.background = lcd_bg_pixel;
|
||||
gc_values.graphics_exposures = False;
|
||||
|
||||
gc = XCreateGC(display, window,
|
||||
GCFunction|GCPlaneMask|GCForeground|GCBackground|GCSubwindowMode|
|
||||
GCGraphicsExposures,
|
||||
&gc_values);
|
||||
|
||||
{
|
||||
/* 3.8: This clip rectangle prevents XCopyArea() (in DrawLcd()) from
|
||||
drawing non-visible pixels
|
||||
*/
|
||||
XRectangle rect[1];
|
||||
|
||||
rect[0].x = LCD_CLIP_X_ORIGIN; /* This is the clip rectangle */
|
||||
rect[0].y = LCD_CLIP_Y_ORIGIN;
|
||||
rect[0].width = LCD_CLIP_WIDTH;
|
||||
rect[0].height = LCD_CLIP_HEIGHT;
|
||||
|
||||
XSetClipRectangles(
|
||||
display, gc,
|
||||
0, 0, /* Alsolute clip X,Y origin */
|
||||
rect, 1, YXBanded);
|
||||
}
|
||||
|
||||
/* Initialize Pixmaps */
|
||||
InitPixmaps();
|
||||
|
||||
/* Clear screen and initialize the static memory areas */
|
||||
ClearLcd();
|
||||
|
||||
/* Set the 'display is clean' flag */
|
||||
clean = 1;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : DrawLcd
|
||||
.kind : C function
|
||||
.creation : 29-Jan-1998
|
||||
.description :
|
||||
This function redraws the Lcd screen from the information contained in
|
||||
the mod_status.hdw structure.
|
||||
|
||||
.call :
|
||||
DrawLcd();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
X11_I_CALLED
|
||||
X11_I_LCD_PAR
|
||||
.notes :
|
||||
1.1, 29-Jan-1998, creation
|
||||
|
||||
.- */
|
||||
void DrawLcd(void)
|
||||
{
|
||||
Address addr = mod_status.hdw.lcd_base_addr;
|
||||
int y, x;
|
||||
Nibble v;
|
||||
|
||||
debug1(DEBUG_C_TRACE, X11_I_CALLED, "DrawLcd");
|
||||
|
||||
/* If the debug class DEBUG_C_DISPLAY is enabled, print the display
|
||||
parameters
|
||||
*/
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_base_addr",
|
||||
(int)mod_status.hdw.lcd_base_addr);
|
||||
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_on",
|
||||
(int)mod_status.hdw.lcd_on);
|
||||
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_contrast",
|
||||
(int)mod_status.hdw.lcd_contrast);
|
||||
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_vlc",
|
||||
(int)mod_status.hdw.lcd_vlc);
|
||||
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_offset",
|
||||
(int)mod_status.hdw.lcd_offset);
|
||||
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_line_offset",
|
||||
(int)mod_status.hdw.lcd_line_offset);
|
||||
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_menu_addr",
|
||||
(int)mod_status.hdw.lcd_menu_addr);
|
||||
|
||||
debug2(DEBUG_C_DISPLAY, X11_I_LCD_PAR, "_ann",
|
||||
(int)mod_status.hdw.lcd_ann);
|
||||
|
||||
/* Check if display is on */
|
||||
if(!mod_status.hdw.lcd_on)
|
||||
{
|
||||
/* Display is off; clear lcd if necessary */
|
||||
if(!clean)
|
||||
{
|
||||
/* Set the 'display is clean' flag and clear the screen */
|
||||
clean = 1;
|
||||
ClearLcd();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* Scan menu display rows */
|
||||
addr = mod_status.hdw.lcd_menu_addr;
|
||||
for(; y<MAX_ROWS; 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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan annunciators */
|
||||
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
|
||||
.kind : C function
|
||||
.creation : 17-Feb-1998
|
||||
.description :
|
||||
This function refreshes the Lcd screen after a X Window Expose event.
|
||||
|
||||
.call :
|
||||
RefreshLcd();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
X11_I_CALLED
|
||||
.notes :
|
||||
1.1, 17-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
void RefreshLcd(void)
|
||||
{
|
||||
debug1(DEBUG_C_TRACE, X11_I_CALLED, "RefreshLcd");
|
||||
|
||||
ClearLcd();
|
||||
DrawLcd();
|
||||
}
|
93
display.h
Normal file
93
display.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: display.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: display.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 28-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This header contains all definitions and declarations related to the
|
||||
HP48's LCD display emulator. References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, modules.h, X11/Xlib.h
|
||||
|
||||
.notes :
|
||||
$Log: display.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:38 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 1.1 1998/02/17 11:51:31 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Data type definitions - require config.h, machdep.h, cpu.h
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macros
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
void InitLcd(Display *lcd_display, Window lcd_window,
|
||||
unsigned long lcd_fg_pixel, unsigned long lcd_bg_pixel);
|
||||
|
||||
void DrawLcd(void);
|
||||
void RefreshLcd(void);
|
701
emulator.c
Normal file
701
emulator.c
Normal file
|
@ -0,0 +1,701 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: emulator.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: emulator.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 2-Feb-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This file contains the main loop of the emulator. For efficiency reasons,
|
||||
this module also emulates both T1 and T2 timers. References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
.include : config.h, machdep.h, cpu.h
|
||||
|
||||
.notes :
|
||||
$Log: emulator.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.13 2000/11/09 11:30:40 cibrario
|
||||
Revised to add file selection box GUI element, CPU halt/run
|
||||
requests and emulator's extended functions:
|
||||
|
||||
- The upper limit to the CPU speed can now be changed at runtime.
|
||||
- Fixed a bug in EmulatorLoopHandler(): it could return an invalid
|
||||
Chf action code.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:39 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.5 2000/10/02 09:48:04 cibrario
|
||||
Linux support:
|
||||
- EmulatorLoop(): revised to force an upper limit to the CPU speed if
|
||||
the compile-time option REAL_CPU_SPEED is defined: inner_loop is
|
||||
limited to INNER_LOOP_MAX and the excess time is spent sleeping.
|
||||
|
||||
Revision 3.2 2000/09/22 13:43:09 cibrario
|
||||
Implemented preliminary support of HP49 hw architecture:
|
||||
- EmulatorInit() now invokes ModSelectDescription() to select
|
||||
the appropriate calculator's hw configuration depending on the
|
||||
setting of the 'hw' user option.
|
||||
|
||||
* Revision 3.1 2000/09/20 14:12:45 cibrario
|
||||
* Revised to implement passive CPU shutdown:
|
||||
* - enhanced EmulatorLoopHandler() to handle the CPU_I_SHUTDN condition
|
||||
* when CPU_SPIN_SHUTDN is not defined.
|
||||
*
|
||||
* Revision 2.5 2000/09/14 14:45:37 cibrario
|
||||
* Added call to HandleSerial() in EmulatorLoop(), in order to
|
||||
* handle external events related to serial port emulation.
|
||||
*
|
||||
* Revision 2.4 2000/09/12 15:17:18 cibrario
|
||||
* Updated EmulatorInit() in order to invoke CpuInit() before ModInit(),
|
||||
* so that interrupt requests generated by ModInit() are honored as
|
||||
* they should. This is required to implement emulation of Port 1 and 2.
|
||||
*
|
||||
* Revision 2.1 2000/09/08 14:57:49 cibrario
|
||||
* - Removed explicit cast of second argument from calls to gettimeofday()
|
||||
* - Minor fixes needed by Chf Release 2
|
||||
* - Defined new convenience functions EmulatorInit() and EmulatorExit();
|
||||
* they can be invoked to reset/initialize the emulation core and
|
||||
* to prepare it to exit, respectively.
|
||||
*
|
||||
* Revision 1.1 1998/02/18 11:49:21 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: emulator.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "display.h"
|
||||
#include "x11.h"
|
||||
#include "serial.h"
|
||||
#include "args.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID CPU_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private macros / variables / functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define T1_MULTIPLIER (8192/16) /* T2/T1 increment ratio */
|
||||
#define T1_INTERVAL 62500 /* us per T1 increment */
|
||||
#define T2_INTERVAL 122 /* us per T2 increment */
|
||||
|
||||
/* 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
|
||||
struct timeval and to avoid starvation of the serial port emulation
|
||||
module (*); T1_MS_MULTIPLIER and T2_MS_DIVISOR are approximate
|
||||
values used only to compute e reasonable timeout for IdleXLoop();
|
||||
the actual update of timers is carried out using T1_INTERVAL
|
||||
and T2_INTERVAL, and should be more accurate.
|
||||
|
||||
|
||||
(*) XXX This constraint will be removed when the serial port emulation
|
||||
module will support asynchronous selection on pty fd and will
|
||||
be able to interact with the GUI's select mechanism.
|
||||
*/
|
||||
#define T1_MS_MULTIPLIER 63 /* 3.1: Milliseconds per T1 tick (~) */
|
||||
#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 T1_OVF_MASK NIBBLE_MASK /* 3.1: Timer overflow masks */
|
||||
#define T2_OVF_MASK 0xFFFFFFFF
|
||||
|
||||
#define LCD_T1_MASK 0x3 /* LCD refresh timing mask */
|
||||
#define INT_T1_MASK 0xF /* Int. req. timing mask */
|
||||
|
||||
static int emulator_int_req = 0; /* Interrupt request flag */
|
||||
|
||||
/* This function contains the main emulator loop; under normal conditions,
|
||||
it never returns to the caller. The only way to exit this function is
|
||||
to signal a Chf condition that triggers an unwind operation.
|
||||
*/
|
||||
static void EmulatorLoop(void)
|
||||
{
|
||||
struct timeval old_t, cur_t;
|
||||
int ela;
|
||||
int inner_loop = cpu_status.inner_loop;
|
||||
int t1_count = 0;
|
||||
int i, j;
|
||||
|
||||
debug1(DEBUG_C_TRACE, CPU_I_CALLED, "EmulatorLoop");
|
||||
|
||||
/* Ignore past interrupt requests */
|
||||
emulator_int_req = 0;
|
||||
|
||||
/* Get current time of day */
|
||||
gettimeofday(&old_t, NULL);
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* T1 loop */
|
||||
for(j=0; j<T1_MULTIPLIER; j++)
|
||||
{
|
||||
/* Inner loop */
|
||||
for(i=0; i<inner_loop; i++) OneStep();
|
||||
|
||||
/* T2 update */
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_TRUN)
|
||||
{
|
||||
if(--mod_status.hdw.t2_val == 0xFFFFFFFF)
|
||||
{
|
||||
debug1(DEBUG_C_TIMERS, CPU_I_TIMER2_EX, mod_status.hdw.t2_ctrl);
|
||||
|
||||
mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ;
|
||||
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_WAKE)
|
||||
CpuWake();
|
||||
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_INT)
|
||||
CpuIntRequest(INT_REQUEST_IRQ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* T1 update */
|
||||
mod_status.hdw.t1_val = (mod_status.hdw.t1_val - 1) & NIBBLE_MASK;
|
||||
if(mod_status.hdw.t1_val == 0xF)
|
||||
{
|
||||
debug1(DEBUG_C_TIMERS, CPU_I_TIMER1_EX, mod_status.hdw.t1_ctrl);
|
||||
|
||||
mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ;
|
||||
|
||||
if(mod_status.hdw.t1_ctrl & T1_CTRL_WAKE)
|
||||
CpuWake();
|
||||
|
||||
if(mod_status.hdw.t1_ctrl & T1_CTRL_INT)
|
||||
CpuIntRequest(INT_REQUEST_IRQ);
|
||||
}
|
||||
|
||||
/* LCD update */
|
||||
if((t1_count++ & LCD_T1_MASK) == 0) DrawLcd();
|
||||
|
||||
/* Emulator Interrupt Request */
|
||||
if((t1_count & INT_T1_MASK) == 0 && emulator_int_req)
|
||||
{
|
||||
ChfCondition CPU_I_EMULATOR_INT, CHF_INFO ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
/* X Events handling */
|
||||
HandleXEvents();
|
||||
|
||||
/* Handle serial port */
|
||||
HandleSerial();
|
||||
|
||||
/* Adjust inner_loop limit */
|
||||
gettimeofday(&cur_t, NULL);
|
||||
|
||||
ela = (cur_t.tv_sec - old_t.tv_sec) * 1000000 +
|
||||
(cur_t.tv_usec - old_t.tv_usec);
|
||||
|
||||
inner_loop = inner_loop * T1_INTERVAL / ela;
|
||||
if(inner_loop < INNER_LOOP_MIN) inner_loop = INNER_LOOP_MIN;
|
||||
|
||||
#ifdef REAL_CPU_SPEED
|
||||
/* 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
|
||||
cpu_status.inner_loop_max
|
||||
and the excess time, if any, is spent sleeping; usleep() is
|
||||
BSD 4.3-specific, but most recent systems should offer it anyway,
|
||||
well, I hope.
|
||||
The special value cpu_status.inner_loop_max==0 gives maximum speed.
|
||||
*/
|
||||
if(cpu_status.inner_loop_max != 0
|
||||
&& inner_loop >= cpu_status.inner_loop_max)
|
||||
{
|
||||
inner_loop = cpu_status.inner_loop_max;
|
||||
if(T1_INTERVAL > ela) usleep(T1_INTERVAL - ela);
|
||||
}
|
||||
#endif
|
||||
|
||||
cpu_status.inner_loop = inner_loop;
|
||||
old_t = cur_t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Condition handler for the EmulatorLoop */
|
||||
static ChfAction EmulatorLoopHandler(
|
||||
const ChfDescriptor *d,
|
||||
const ChfState s,
|
||||
ChfPointer ctx
|
||||
)
|
||||
{
|
||||
ChfAction act;
|
||||
|
||||
/* Check Chf state */
|
||||
switch(s)
|
||||
{
|
||||
/* 2.1: Chf release 2 fixed the spelling of 'SIGNALING' */
|
||||
case CHF_SIGNALING:
|
||||
/* ChfSignal() in progress */
|
||||
if(ChfGetModuleId(d) == CPU_CHF_MODULE_ID)
|
||||
{
|
||||
/* Condition from CPU modules; check Condition Code */
|
||||
switch(ChfGetConditionCode(d))
|
||||
{
|
||||
#ifdef CPU_SPIN_SHUTDN
|
||||
case CPU_I_SHUTDN:
|
||||
/* CPU shutdown signalled with CPU_SPIN_SHUTDN defined;
|
||||
Fatal error.
|
||||
*/
|
||||
ChfCondition CPU_F_BAD_SHUTDN, CHF_FATAL ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
act = CHF_RESIGNAL;
|
||||
break;
|
||||
#else
|
||||
case CPU_I_SHUTDN:
|
||||
{
|
||||
/* 3.1: CPU_SPIN_SHUTDN is not defined, and the cpu emulator
|
||||
has just executed a shutdown instruction.
|
||||
Let's do something a little tricky here:
|
||||
|
||||
1- redraw the LCD
|
||||
|
||||
2- handle serial port activities
|
||||
|
||||
3- determine which timer will expire first, and
|
||||
compute an approximate value of the maximum duration
|
||||
of the shutdown --> ms
|
||||
|
||||
4- handle serial port activities
|
||||
|
||||
5- enter the inner idle loop; it breaks when either an
|
||||
X Event occurred (possibly clearing the shutdown) or
|
||||
the shutdown timeout elapses
|
||||
|
||||
6- determine the actual time we spend in the idle loop
|
||||
(X timeouts are not accurate enough for this purpose)
|
||||
|
||||
7- update T1 and T2, check their state and wake/interrupt
|
||||
the CPU if necessary
|
||||
|
||||
Activities 3-7 above are enclosed in an outer loop because we
|
||||
cannot be absolutely sure of the actual time spent
|
||||
in the idle loop; moreover, not all X Events actually
|
||||
spool up the CPU. The outer loop breaks when the CPU is
|
||||
actually brought out of shutdown.
|
||||
|
||||
frac_t1 and frac_t2 contain the number of microseconds
|
||||
not accounted for in the last T1/T2 update, respectively;
|
||||
they help minimize the cumulative timing error induced
|
||||
by executing the outer idle loop more than once.
|
||||
*/
|
||||
struct timeval start_idle, end_idle;
|
||||
int frac_t1=0, frac_t2=0;
|
||||
|
||||
gettimeofday(&start_idle, NULL);
|
||||
|
||||
/* Redraw the LCD immediately before entering idle loop;
|
||||
this ensures that the latest LCD updated actually
|
||||
get to the screen.
|
||||
*/
|
||||
DrawLcd();
|
||||
|
||||
/* Handle serial port activity before entering the outer idle
|
||||
loop, because this could possibly bring the cpu out of
|
||||
shutdown right now.
|
||||
*/
|
||||
HandleSerial();
|
||||
|
||||
/* XXX
|
||||
If either timer has a pending service request,
|
||||
process it immediately. It is not clear why it was
|
||||
not processed *before* shutdown, though.
|
||||
*/
|
||||
if(mod_status.hdw.t1_ctrl & T1_CTRL_SREQ)
|
||||
{
|
||||
if(mod_status.hdw.t1_ctrl & T1_CTRL_WAKE)
|
||||
CpuWake();
|
||||
|
||||
if(mod_status.hdw.t1_ctrl & T1_CTRL_INT)
|
||||
CpuIntRequest(INT_REQUEST_IRQ);
|
||||
}
|
||||
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_SREQ)
|
||||
{
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_WAKE)
|
||||
CpuWake();
|
||||
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_INT)
|
||||
CpuIntRequest(INT_REQUEST_IRQ);
|
||||
}
|
||||
|
||||
while(cpu_status.shutdn)
|
||||
{
|
||||
unsigned long ms = MAX_IDLE_X_LOOP_TIMEOUT;
|
||||
unsigned long mst;
|
||||
int ela;
|
||||
int ela_ticks;
|
||||
|
||||
debug3(DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (during SHUTDN)",
|
||||
mod_status.hdw.t1_ctrl, mod_status.hdw.t1_val);
|
||||
debug3(DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T2 (during SHUTDN)",
|
||||
mod_status.hdw.t2_ctrl, mod_status.hdw.t2_val);
|
||||
|
||||
/* Determine which timer will expire first */
|
||||
if(mod_status.hdw.t1_ctrl & (T1_CTRL_INT|T1_CTRL_WAKE))
|
||||
{
|
||||
/* T1 will do something on expiration */
|
||||
mst = ((unsigned long)mod_status.hdw.t1_val + 1)
|
||||
* T1_MS_MULTIPLIER;
|
||||
|
||||
debug2(DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T1", mst);
|
||||
|
||||
if(mst < ms) ms = mst;
|
||||
}
|
||||
|
||||
if((mod_status.hdw.t2_ctrl & T2_CTRL_TRUN)
|
||||
&& (mod_status.hdw.t2_ctrl & (T2_CTRL_INT|T2_CTRL_WAKE)))
|
||||
{
|
||||
/* T2 is running and will do something on expiration */
|
||||
mst = ((unsigned long)mod_status.hdw.t2_val + 1)
|
||||
/ T2_MS_DIVISOR;
|
||||
|
||||
debug2(DEBUG_C_TIMERS, CPU_I_TIMER_EXP, "T2", mst);
|
||||
|
||||
if(mst < ms) ms = mst;
|
||||
}
|
||||
|
||||
/* Handle serial port activities at each iteration of
|
||||
the outer idle loop; this ensures that the serial
|
||||
port emulation will not starve.
|
||||
*/
|
||||
HandleSerial();
|
||||
|
||||
/* Enter idle loop, possibly with timeout;
|
||||
The loop breaks when:
|
||||
- any X Event occurs (possibly clearing the shutdown)
|
||||
- the given timeout expires
|
||||
*/
|
||||
debug1(DEBUG_C_TIMERS, CPU_I_IDLE_X_LOOP, ms);
|
||||
IdleXLoop(ms);
|
||||
|
||||
/* End of idle loop; compute actual elapsed time */
|
||||
gettimeofday(&end_idle, NULL);
|
||||
|
||||
ela = (end_idle.tv_sec - start_idle.tv_sec) * 1000000 +
|
||||
(end_idle.tv_usec - start_idle.tv_usec);
|
||||
|
||||
/* Update start_idle here to contain lag */
|
||||
start_idle = end_idle;
|
||||
|
||||
debug1(DEBUG_C_TIMERS, CPU_I_ELAPSED, ela);
|
||||
|
||||
/* Update timers and act accordingly */
|
||||
ela_ticks = ((ela+frac_t1) + T1_INTERVAL/2) / T1_INTERVAL;
|
||||
frac_t1 = (ela+frac_t1) - ela_ticks * T1_INTERVAL;
|
||||
|
||||
if(ela_ticks > mod_status.hdw.t1_val)
|
||||
{
|
||||
debug1(DEBUG_C_TIMERS, CPU_I_TIMER1_EX,
|
||||
mod_status.hdw.t1_ctrl);
|
||||
|
||||
mod_status.hdw.t1_ctrl |= T1_CTRL_SREQ;
|
||||
|
||||
if(mod_status.hdw.t1_ctrl & T1_CTRL_WAKE)
|
||||
CpuWake();
|
||||
|
||||
if(mod_status.hdw.t1_ctrl & T1_CTRL_INT)
|
||||
CpuIntRequest(INT_REQUEST_IRQ);
|
||||
}
|
||||
|
||||
mod_status.hdw.t1_val =
|
||||
(mod_status.hdw.t1_val - ela_ticks) & T1_OVF_MASK;
|
||||
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_TRUN)
|
||||
{
|
||||
ela_ticks = ((ela+frac_t2) + T2_INTERVAL/2) / T2_INTERVAL;
|
||||
frac_t2 = (ela+frac_t2) - ela_ticks * T2_INTERVAL;
|
||||
|
||||
if(ela_ticks > mod_status.hdw.t2_val)
|
||||
{
|
||||
debug1(DEBUG_C_TIMERS, CPU_I_TIMER2_EX,
|
||||
mod_status.hdw.t2_ctrl);
|
||||
|
||||
mod_status.hdw.t2_ctrl |= T2_CTRL_SREQ;
|
||||
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_WAKE)
|
||||
CpuWake();
|
||||
|
||||
if(mod_status.hdw.t2_ctrl & T2_CTRL_INT)
|
||||
CpuIntRequest(INT_REQUEST_IRQ);
|
||||
}
|
||||
|
||||
mod_status.hdw.t2_val =
|
||||
(mod_status.hdw.t2_val - ela_ticks) & T2_OVF_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
debug3(DEBUG_C_TIMERS, CPU_I_TIMER_ST, "T1 (after SHUTDN)",
|
||||
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);
|
||||
|
||||
act = CHF_CONTINUE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CPU_I_EMULATOR_INT:
|
||||
/* Emulator interrupt; unwind */
|
||||
act = CHF_UNWIND;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Condition Code not handled; resignal */
|
||||
act = CHF_RESIGNAL;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
/* Condition from other modules; resignal */
|
||||
act = CHF_RESIGNAL;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other states; resignal the condition */
|
||||
act = CHF_RESIGNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return act;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Public functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : Emulator
|
||||
.kind : C function
|
||||
.creation : 17-Feb-1998
|
||||
.description :
|
||||
This function implements the main emulator loop. For efficiency reasons,
|
||||
it also emulates both T1 and T2 timers. Under normal conditions, this
|
||||
function returns to the caller only when an emulator interrupt request
|
||||
has been posted using EmulatorIntRequest().
|
||||
|
||||
The only way to exit this function (with a non-local jump) is to signal
|
||||
a Chf Condition that triggers an unwind operation.
|
||||
|
||||
.call :
|
||||
Emulator();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
CPU_I_CALLED
|
||||
CPU_I_TIMER1_EX
|
||||
CPU_I_TIMER2_EX
|
||||
Other conditions signalled by lower level modules
|
||||
.notes :
|
||||
1.1, 17-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
void Emulator(void)
|
||||
{
|
||||
jmp_buf unwind_context;
|
||||
|
||||
debug1(DEBUG_C_TRACE, CPU_I_CALLED, "Emulator");
|
||||
|
||||
/* Setup unwind_context */
|
||||
if(setjmp(unwind_context) == 0)
|
||||
{
|
||||
/* Push condition handler, with NULL context */
|
||||
ChfPushHandler(EmulatorLoopHandler, &unwind_context, (ChfPointer)NULL);
|
||||
|
||||
/* Activate emulator loop */
|
||||
EmulatorLoop();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Unwinding after an emulator interrupt */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : EmulatorIntRequest
|
||||
.kind : C function
|
||||
.creation : 18-Feb-1998
|
||||
.description :
|
||||
This function posts an interrupt request for the running emulator loop.
|
||||
The request will be satisfied as soon as possible and Emulator() will
|
||||
return to the caller.
|
||||
|
||||
.call :
|
||||
EmulatorIntRequest();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
*
|
||||
.notes :
|
||||
1.1, 18-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
void EmulatorIntRequest(void)
|
||||
{
|
||||
emulator_int_req = 1;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : EmulatorInit
|
||||
.kind : C function
|
||||
.creation : 8-Sep-2000
|
||||
.description :
|
||||
This function initializes the cpu and modules emulator subsystems;
|
||||
if the reset emulator option is set, a reset is forced on both
|
||||
subsystems, too.
|
||||
|
||||
.call :
|
||||
EmulatorInit();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
* Status codes signaled by CpuInit() and CpuReset()
|
||||
* Status codes signaled by ModInit() and ModReset()
|
||||
.notes :
|
||||
2.1, 8-Sep-2000, creation
|
||||
2.4, 12-Sep-2000, update
|
||||
- invoke CpuInit() before ModInit() so that interrupt requests
|
||||
generated by ModInit() are honored as they should.
|
||||
3.2, 21-Sep-2000, update:
|
||||
- now invoking ModSelectDescription(args.hw) to select and
|
||||
register an appropriate module description table depending on
|
||||
args.hw option.
|
||||
|
||||
.- */
|
||||
void EmulatorInit(void)
|
||||
{
|
||||
/* Select a module description table */
|
||||
ModSelectDescription(args.hw);
|
||||
|
||||
/* Initialize cpu and modules subsystems */
|
||||
CpuInit();
|
||||
ModInit();
|
||||
|
||||
/* Reset if appropriate */
|
||||
if(args.reset)
|
||||
{
|
||||
CpuReset();
|
||||
ModReset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : EmulatorExit
|
||||
.kind : C function
|
||||
.creation : 8-Sep-2000
|
||||
.description :
|
||||
This function prepares the emulator to exit. If 'opt' is SAVE_AND_EXIT,
|
||||
it also attempts to save the emulator's state on mass storage. Notice
|
||||
that this function never exits the application directly, but always
|
||||
returns to the caller unless an unrecoverable error occurs.
|
||||
|
||||
.call :
|
||||
EmulatorExit(opt);
|
||||
.input :
|
||||
enum ExitOption opt, emulator exit option
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
* Status codes signaled by CpuSave() and ModSave()
|
||||
.notes :
|
||||
2.1, 8-Sep-2000, creation
|
||||
|
||||
.- */
|
||||
void EmulatorExit(enum ExitOption opt)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
|
||||
case SAVE_AND_EXIT:
|
||||
/* Save state of cpu and modules subsystems */
|
||||
ModSave();
|
||||
CpuSave();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Default behavior; do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
525
flash49.c
Normal file
525
flash49.c
Normal file
|
@ -0,0 +1,525 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: flash49.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HPxx emulator
|
||||
.title : $RCSfile: flash49.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 25-Sep-2000
|
||||
.keywords : *
|
||||
.description :
|
||||
This module emulates the Internal Flash Rom of the HP49.
|
||||
|
||||
References:
|
||||
|
||||
28F160S5/28F320S5 Data Sheet, by Intel Corp.
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, modules.h flash49.h
|
||||
|
||||
.notes :
|
||||
$Log: flash49.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:40 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.5 2000/10/02 09:49:18 cibrario
|
||||
Linux support:
|
||||
- added a default case in StoreData()'s switch; this is cleaner, and
|
||||
makes gcc happier.
|
||||
|
||||
Revision 3.3 2000/09/26 15:30:14 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: flash49.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "flash49.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "args.h"
|
||||
|
||||
#define CHF_MODULE_ID FLASH_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private Macro/Data type definitions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define BLOCK_SIZE 0x10000
|
||||
#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)
|
||||
|
||||
|
||||
/* Flash cycle types */
|
||||
enum FlashCycle
|
||||
{
|
||||
FLASH_CYCLE_READ = 0,
|
||||
FLASH_CYCLE_WRITE,
|
||||
|
||||
FLASH_CYCLE_N /* Total # of cycle types */
|
||||
};
|
||||
|
||||
/* State transition function */
|
||||
typedef int (*FlashF)
|
||||
(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data);
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private state variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* External storage */
|
||||
extern struct ModStatus_49 *mod_status_49;
|
||||
|
||||
static int r_buffer; /* Nibble buffer during read */
|
||||
static int w_buffer; /* Nibble buffer during write */
|
||||
static enum FlashState fsm_state; /* FSM state */
|
||||
|
||||
/* Write buffer */
|
||||
#define WB_COUNT_MASK 0x1F
|
||||
#define WB_SIZE 0x20
|
||||
static int wb_count; /* Counter for Write to Buffer */
|
||||
static int wb_cdown; /* Count down */
|
||||
static XAddress wb_start; /* Start address for Write to Buffer */
|
||||
static int wb[WB_SIZE]; /* Write buffer */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
State transition private functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* This function is called by default for unhandled state transitions */
|
||||
static int BadCommand(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
/* Unknown command: signal and reset state to FLASH_ST_READ_ARRAY */
|
||||
ChfCondition FLASH_W_BAD_CMD, CHF_WARNING,
|
||||
*state, cycle, address, data
|
||||
ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
*state = FLASH_ST_READ_ARRAY;
|
||||
return 0; /* Dummy result */
|
||||
}
|
||||
|
||||
|
||||
/* This function is called to read the Flash Rom array */
|
||||
static int ReadArray(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
/* Read a byte from the array; no state transitions */
|
||||
return
|
||||
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 */
|
||||
static int ParseCommand(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
switch(data)
|
||||
{
|
||||
case FLASH_CMD_READ_ARRAY:
|
||||
/* Transition to FLASH_ST_READ_ARRAY state */
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Array");
|
||||
*state = FLASH_ST_READ_ARRAY;
|
||||
break;
|
||||
|
||||
case FLASH_CMD_CLR_SR:
|
||||
/* Clear status register; section 4.5 on Data Sheet.
|
||||
The current implementation does nothing, because
|
||||
the value of the status register is fixed. No state transitions.
|
||||
*/
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Clear Status");
|
||||
break;
|
||||
|
||||
case FLASH_CMD_WRITE_BUFFER:
|
||||
/* Write to Buffer; section 4.8 on Data Sheet.
|
||||
Transition to FLASH_ST_READ_XSR state.
|
||||
*/
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (start)");
|
||||
*state = FLASH_ST_READ_XSR;
|
||||
break;
|
||||
|
||||
case FLASH_CMD_READ_SR:
|
||||
/* Read Status; section 4.4 on Data Sheet.
|
||||
Transition to FLASH_ST_READ_SR state.
|
||||
*/
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read Status");
|
||||
*state = FLASH_ST_READ_SR;
|
||||
break;
|
||||
|
||||
case FLASH_CMD_BL_ERASE:
|
||||
/* Block Erase; section 4.6 on Data Sheet.
|
||||
Transition to FLASH_ST_BL_ERASE state.
|
||||
Consistency of block addresses is not checked.
|
||||
*/
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Erase Block (start)");
|
||||
*state = FLASH_ST_BL_ERASE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown command; signal, ignore, keep current state. */
|
||||
ChfCondition FLASH_W_BAD_CMD, CHF_WARNING,
|
||||
*state, cycle, address, data
|
||||
ChfEnd;
|
||||
ChfSignal();
|
||||
break;
|
||||
}
|
||||
|
||||
return 0; /* No result; this is a write cycle */
|
||||
}
|
||||
|
||||
|
||||
/* This function returns to the caller the value of XSR */
|
||||
static int ReadXSR(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
/* Return XSR status; a buffer is always available in the current
|
||||
emulation scheme. Keep current state.
|
||||
*/
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read XSR");
|
||||
return FLASH_XSR_WBS;
|
||||
}
|
||||
|
||||
|
||||
/* This function returns to the caller the value of SR */
|
||||
static int ReadSR(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
/* Return SR status; the WSM executes in zero time in the current
|
||||
emulation scheme. Keep current state.
|
||||
*/
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Read SR");
|
||||
return FLASH_SR_WSMS;
|
||||
}
|
||||
|
||||
|
||||
/* This function is called to store the WRITE_BUFFER byte count;
|
||||
both wb_count and wb_cdown are set; StoreData() decrements the
|
||||
latter, WriteConfirm() uses the former to determine how many bytes
|
||||
must write to the Flash array.
|
||||
*/
|
||||
static int StoreCount(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
/* Store WRITE_BUFFER count; next state is FLASH_ST_WRITE_DATA */
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (count)");
|
||||
wb_count = wb_cdown = data & WB_COUNT_MASK;
|
||||
|
||||
*state = FLASH_ST_WRITE_DATA_1;
|
||||
return 0; /* No result; this is a write cycle */
|
||||
}
|
||||
|
||||
|
||||
/* 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 function transitions to state FLASH_ST_WRITE_CONFIRM when all
|
||||
bytes have been stored.
|
||||
*/
|
||||
static int StoreData(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
int index;
|
||||
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (data)");
|
||||
|
||||
/* Store WRITE_BUFFER data; the first write also stores the
|
||||
buffer starting address.
|
||||
*/
|
||||
switch(*state)
|
||||
{
|
||||
|
||||
case FLASH_ST_WRITE_DATA_1:
|
||||
wb_start = address;
|
||||
wb[0] = data;
|
||||
*state = FLASH_ST_WRITE_DATA_N;
|
||||
break;
|
||||
|
||||
case FLASH_ST_WRITE_DATA_N:
|
||||
index = address - wb_start;
|
||||
if(index < 0 || index >= WB_SIZE)
|
||||
{
|
||||
ChfCondition FLASH_W_BAD_ADDRESS, CHF_WARNING,
|
||||
*state, cycle, address, data
|
||||
ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
else
|
||||
wb[index] = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
*state = FLASH_ST_READ_ARRAY;
|
||||
break;
|
||||
}
|
||||
|
||||
if(--wb_cdown < 0)
|
||||
*state = FLASH_ST_WRITE_CONFIRM;
|
||||
|
||||
return 0; /* No result; this is a write cycle */
|
||||
}
|
||||
|
||||
|
||||
/* This function expects a Write to Buffer confirmation command
|
||||
(FLASH_CMD_WRITE_BUFFER_2); if it is received, the write buffer
|
||||
is copied into the Flash Rom array, otherwise the write cycle is
|
||||
aborted. In both cases, the new state is FLASH_ST_READ_ARRAY.
|
||||
*/
|
||||
static int WriteConfirm(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Write to Buffer (end)");
|
||||
|
||||
/* Expect Write to Buffer confirmation code */
|
||||
if(data == FLASH_CMD_WRITE_BUFFER_2)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Confirmation OK; write.
|
||||
Remember that wb_count is the byte count MINUS 1.
|
||||
*/
|
||||
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)+1]
|
||||
= HighNibble(wb[i]);
|
||||
}
|
||||
}
|
||||
|
||||
*state = FLASH_ST_READ_ARRAY;
|
||||
return 0; /* No result */
|
||||
}
|
||||
|
||||
|
||||
/* If the FLASH_CMD_BL_ERASE_2 command is received, this function erases
|
||||
the block pointed by the current address; otherwise the block erase
|
||||
operation is aborted.
|
||||
In both cases, the new state is FLASH_ST_READ_SR.
|
||||
*/
|
||||
static int BlockErase(enum FlashState *state, enum FlashCycle cycle,
|
||||
XAddress address, int data)
|
||||
{
|
||||
debug1(DEBUG_C_FLASH, FLASH_I_FSM_OP, "Block Erase (end)");
|
||||
|
||||
/* Expect Write to Buffer confirmation code */
|
||||
if(data == FLASH_CMD_BL_ERASE_2)
|
||||
{
|
||||
XAddress block_base = BlockBase(address);
|
||||
int i;
|
||||
|
||||
/* Confirmation OK; erase */
|
||||
for(i=0; i<BLOCK_SIZE; i++)
|
||||
{
|
||||
mod_status_49->flash[
|
||||
NibbleAddress(block_base+i)] = (Nibble)0xF;
|
||||
mod_status_49->flash[
|
||||
NibbleAddress(block_base+i)+1] = (Nibble)0xF;
|
||||
}
|
||||
}
|
||||
|
||||
*state = FLASH_ST_READ_SR;
|
||||
return 0; /* No result */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
FSM state diagram; two-dimensional array of FlashF; each function
|
||||
is invoked when the FSM is in a given state (first index), and
|
||||
a particular cycle (second index) is requested.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static FlashF F[FLASH_ST_N][FLASH_CYCLE_N] =
|
||||
{
|
||||
{ ReadArray, ParseCommand }, /* FLASH_ST_READ_ARRAY */
|
||||
{ ReadSR, ParseCommand }, /* FLASH_ST_READ_SR */
|
||||
{ ReadXSR, StoreCount }, /* FLASH_ST_READ_XSR */
|
||||
{ BadCommand, StoreData }, /* FLASH_ST_WRITE_DATA_1 */
|
||||
{ BadCommand, StoreData }, /* FLASH_ST_WRITE_DATA_N */
|
||||
{ BadCommand, WriteConfirm }, /* FLASH_ST_WRITE_CONFIRM */
|
||||
{ BadCommand, BlockErase } /* FLASH_ST_BL_ERASE */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Other private functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* This function invokes the FSM to execute the given 'cycle',
|
||||
with 'address' and 'data' as arguments. Returns the
|
||||
result of the FSM, if any.
|
||||
*/
|
||||
static int FSM(enum FlashCycle cycle, XAddress address, int data)
|
||||
{
|
||||
int result;
|
||||
|
||||
debug2(DEBUG_C_FLASH, FLASH_I_FSM, fsm_state, cycle);
|
||||
debug2(DEBUG_C_FLASH, FLASH_I_FSM_AD, address, data);
|
||||
|
||||
result = F[fsm_state][cycle](&fsm_state, cycle, address, data);
|
||||
|
||||
debug2(DEBUG_C_FLASH, FLASH_I_FSM_RESULT, fsm_state, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Public functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : FlashRead49
|
||||
.kind : C function
|
||||
.creation : 25-Sep-2000
|
||||
.description :
|
||||
This function reads the nibble @address from Flash Rom and returns it
|
||||
to the caller.
|
||||
|
||||
This function DOES NOT supports even/odd nibble accesses at non-contiguous
|
||||
addresses.
|
||||
|
||||
.call :
|
||||
n = FlashRead49(address);
|
||||
.input :
|
||||
XAddress address
|
||||
.output :
|
||||
Nibble n
|
||||
.status_codes :
|
||||
FLASH_I_READ
|
||||
FLASH_I_FSM_OP
|
||||
FLASH_W_BAD_CMD
|
||||
.notes :
|
||||
3.3, 25-Sep-2000, creation
|
||||
|
||||
.- */
|
||||
Nibble FlashRead49(XAddress address)
|
||||
{
|
||||
Nibble result;
|
||||
|
||||
if(IsOdd(address))
|
||||
/* Odd address, return buffered data from previous read */
|
||||
result = HighNibble(r_buffer);
|
||||
|
||||
else
|
||||
{
|
||||
/* Even address, invoke FSM */
|
||||
r_buffer = FSM(FLASH_CYCLE_READ, ByteAddress(address), 0);
|
||||
result = LowNibble(r_buffer);
|
||||
}
|
||||
|
||||
|
||||
debug2(DEBUG_C_TRACE|DEBUG_C_FLASH, FLASH_I_READ, address, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : FlashWrite49
|
||||
.kind : C function
|
||||
.creation : 25-Sep-2000
|
||||
.description :
|
||||
This function writes nibble datum @address into Flash Rom.
|
||||
|
||||
This function DOES NOT supports even/odd nibble accesses at non-contiguous
|
||||
addresses.
|
||||
|
||||
.call :
|
||||
FlashWrite49(address, datum);
|
||||
.input :
|
||||
XAddress address
|
||||
Nibble datum
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
FLASH_I_WRITE
|
||||
FLASH_I_FSM_OP
|
||||
FLASH_W_BAD_CMD
|
||||
FLASH_W_BAD_ADDRESS
|
||||
.notes :
|
||||
3.3, 25-Sep-2000, creation
|
||||
|
||||
.- */
|
||||
void FlashWrite49(XAddress address, Nibble datum)
|
||||
{
|
||||
debug2(DEBUG_C_TRACE|DEBUG_C_FLASH, FLASH_I_WRITE, address, datum);
|
||||
|
||||
if(IsOdd(address))
|
||||
/* Odd address, invoke FSM; ignore result */
|
||||
FSM(FLASH_CYCLE_WRITE, ByteAddress(address),
|
||||
w_buffer|ShiftHigh(datum));
|
||||
|
||||
else
|
||||
/* Even address, buffer datum */
|
||||
w_buffer = datum;
|
||||
|
||||
}
|
164
flash49.h
Normal file
164
flash49.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: flash49.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HPxx emulator
|
||||
.title : $RCSfile: flash49.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 25-Sep-2000
|
||||
.keywords : *
|
||||
.description :
|
||||
This header contains all definitions and declarations related to the
|
||||
Internal Flash ROM emulation module of the HP49. References:
|
||||
|
||||
Known deficiencies of the current Flash ROM emulation:
|
||||
|
||||
- some (many) commands are not emulated, even BCS ones.
|
||||
- program/erase times are not emulated
|
||||
- suspension is not supported
|
||||
|
||||
References:
|
||||
|
||||
28F160S5/28F320S5 Data Sheet, by Intel Corp.
|
||||
|
||||
.include : config.h machdep.h cpu.h modules.h
|
||||
|
||||
.notes :
|
||||
$Log: flash49.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:41 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.3 2000/09/26 15:30:07 cibrario
|
||||
*** empty log message ***
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macro/Data type definitions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define FLASH49_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
|
||||
|
||||
|
||||
/* Command Set Definitions, Table 3 on Data Sheet.
|
||||
Both BCS and SCS commands are listed here; commands marked with
|
||||
(*) are not implemented.
|
||||
|
||||
The last fixed byte of multibyte commands has a '_2' suffix.
|
||||
*/
|
||||
#define FLASH_CMD_READ_ARRAY 0xFF /* BCS */
|
||||
#define FLASH_CMD_READ_ID 0x90 /* BCS (*) */
|
||||
#define FLASH_CMD_READ_QUERY 0x98 /* SCS (*) */
|
||||
#define FLASH_CMD_READ_SR 0x70 /* BCS */
|
||||
#define FLASH_CMD_CLR_SR 0x50 /* BCS */
|
||||
#define FLASH_CMD_WRITE_BUFFER 0xE8 /* SCS */
|
||||
# define FLASH_CMD_WRITE_BUFFER_2 0xD0
|
||||
#define FLASH_CMD_BW_PGM 0x40 /* BCS (*) */
|
||||
#define FLASH_CMD_BW_PGM_ALT 0x10 /* BCS, alternate (*) */
|
||||
#define FLASH_CMD_BL_ERASE 0x20 /* BCS */
|
||||
# define FLASH_CMD_BL_ERASE_2 0xD0
|
||||
#define FLASH_CMD_SUSPEND 0xB0 /* BCS (*) */
|
||||
#define FLASH_CMD_RESUME 0xD0 /* BCS (*) */
|
||||
#define FLASH_CMD_STS_CONFIG 0xB8 /* SCS (*) */
|
||||
#define FLASH_CMD_BL_LB 0x60 /* SCS (*) */
|
||||
# define FLASH_CMD_BL_LB_SET 0x01
|
||||
# define FLASH_CMD_BL_LB_CLR 0xD0
|
||||
#define FLASH_CMD_CHIP_ERASE 0x30 /* SCS (*) */
|
||||
# define FLASH_CMD_CHIP_ERASE_2 0xD0
|
||||
|
||||
|
||||
/* Status Register bit masks, Table 15 on Data Sheet
|
||||
*/
|
||||
#define FLASH_SR_WSMS 0x80 /* WSM state, 0=busy, 1=ready */
|
||||
#define FLASH_SR_ESS 0x40 /* Erase suspend, 1=suspended */
|
||||
#define FLASH_SR_ECLBS 0x20 /* 1=Error during erasure */
|
||||
#define FLASH_SR_BWSLBS 0x10 /* 1=Error during program */
|
||||
#define FLASH_SR_VPPS 0x08 /* 1=Vpp error */
|
||||
#define FLASH_SR_BWSS 0x04 /* Program suspend, 1=suspended */
|
||||
#define FLASH_SR_DPS 0x02 /* 1=Lock encountered */
|
||||
|
||||
|
||||
/* Extended Status Register bit masks, Table 16 on Data Sheet
|
||||
*/
|
||||
#define FLASH_XSR_WBS 0x80 /* Write buffer status 1=available */
|
||||
|
||||
|
||||
/* State of the Flash FSM, derived from command descriptions on
|
||||
pages 16...28 and from flowcharts on Figure 6...12 of Data Sheet
|
||||
*/
|
||||
enum FlashState
|
||||
{
|
||||
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_XSR, /* Read XSR after CMD_WRITE_BUFFER */
|
||||
FLASH_ST_WRITE_DATA_1, /* Write data after ST_WRITE_COUNT */
|
||||
FLASH_ST_WRITE_DATA_N, /* Write data after first write */
|
||||
FLASH_ST_WRITE_CONFIRM, /* Write confirmation after (ST_WRITE_DATA)* */
|
||||
FLASH_ST_BL_ERASE, /* Block erase started */
|
||||
FLASH_ST_N /* Total # of FSM states */
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Chf condition codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define FLASH_I_READ 101 /* Read from address %x: %d */
|
||||
#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_AD 104 /* FSM address %x, data %x */
|
||||
#define FLASH_I_FSM_RESULT 105 /* FSM next state %d, result %x */
|
||||
#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_ADDRESS 202 /* Bad addr st%d, cycle%d, a%x, d%d */
|
||||
#define FLASH_E_xxx 301
|
||||
#define FLASH_F_xxx 401
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Read/Write operations, nibble-by-nibble */
|
||||
Nibble FlashRead49(XAddress address);
|
||||
void FlashWrite49(XAddress address, Nibble datum);
|
38
flash49.msf
Normal file
38
flash49.msf
Normal file
|
@ -0,0 +1,38 @@
|
|||
$ .+
|
||||
$ .identifier : $Id: flash49.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
$ .context : SATURN, Saturn CPU / HPxx emulator
|
||||
$ .title : $RCSfile: flash49.msf,v $
|
||||
$ .kind : Message catalog source
|
||||
$ .author : Ivan Cibrario B.
|
||||
$ .site : CSTV-CNR
|
||||
$ .creation : 25-Sep-2000
|
||||
$ .keywords : *
|
||||
$ .description :
|
||||
$ Message catalog source file for the flash rom emulator.
|
||||
$ .notes :
|
||||
$ . $Log: flash49.msf,v $
|
||||
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
$ . Public release.
|
||||
$ .
|
||||
$ . Revision 3.8 2000/10/19 15:00:41 cibrario
|
||||
$ . Bug fix:
|
||||
$ . Removed lines with empty directives
|
||||
$ .
|
||||
$ Revision 3.3 2000/09/26 15:30:28 cibrario
|
||||
$ *** empty log message ***
|
||||
$ .-
|
||||
|
||||
$set 1
|
||||
16 Flash
|
||||
|
||||
$set 16
|
||||
101 Read (Nibble) A[%08X] D[%01X]
|
||||
102 Write (Nibble) A[%08X] D[%01X]
|
||||
103 FSM STATE[%d] CYCLE[%d]
|
||||
104 \tFSM Args: (Byte)A[%08X] D[%02X]
|
||||
105 \tFSM Next: STATE[%d] RESULT[%02X]
|
||||
106 \tFSM Operation: [%s]
|
||||
201 Command unknown/not implemented - FSM Info:\n\
|
||||
\tSTATE[%d] CYCLE[%d] A[%08X] D[%02X]
|
||||
202 Invalid address in Write to Buffer - FSM Info:\n\
|
||||
\tSTATE[%d] CYCLE[%d] A[%08X] D[%02X]
|
392
gpl.texi
Normal file
392
gpl.texi
Normal file
|
@ -0,0 +1,392 @@
|
|||
@node GNU GENERAL PUBLIC LICENSE, Concept Index, Tips Tricks and Known Bugs, Top
|
||||
@unnumbered GNU GENERAL PUBLIC LICENSE
|
||||
@center Version 2, June 1991
|
||||
|
||||
@c This file is intended to be included in another file.
|
||||
|
||||
@display
|
||||
Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
@end display
|
||||
|
||||
@unnumberedsec Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software---to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
@iftex
|
||||
@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
@end iftex
|
||||
@ifinfo
|
||||
@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
@end ifinfo
|
||||
|
||||
@enumerate 0
|
||||
@item
|
||||
This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The ``Program'', below,
|
||||
refers to any such program or work, and a ``work based on the Program''
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term ``modification''.) Each licensee is addressed as ``you''.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
@item
|
||||
You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
@item
|
||||
You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
@enumerate a
|
||||
@item
|
||||
You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
@item
|
||||
You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
@item
|
||||
If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
@end enumerate
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
@item
|
||||
You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
@enumerate a
|
||||
@item
|
||||
Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
@item
|
||||
Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
@item
|
||||
Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
@end enumerate
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
@item
|
||||
You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
@item
|
||||
You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
@item
|
||||
Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
@item
|
||||
If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
@item
|
||||
If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
@item
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and ``any
|
||||
later version'', you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
@item
|
||||
If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
@iftex
|
||||
@heading NO WARRANTY
|
||||
@end iftex
|
||||
@ifinfo
|
||||
@center NO WARRANTY
|
||||
@end ifinfo
|
||||
|
||||
@item
|
||||
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
@item
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
@end enumerate
|
||||
|
||||
@iftex
|
||||
@heading END OF TERMS AND CONDITIONS
|
||||
@end iftex
|
||||
@ifinfo
|
||||
@center END OF TERMS AND CONDITIONS
|
||||
@end ifinfo
|
||||
|
||||
@page
|
||||
@unnumberedsec Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the ``copyright'' line and a pointer to where the full notice is found.
|
||||
|
||||
@smallexample
|
||||
@var{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) 19@var{yy} @var{name of author}
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
@end smallexample
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
@smallexample
|
||||
Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@end smallexample
|
||||
|
||||
The hypothetical commands @samp{show w} and @samp{show c} should show
|
||||
the appropriate parts of the General Public License. Of course, the
|
||||
commands you use may be called something other than @samp{show w} and
|
||||
@samp{show c}; they could even be mouse-clicks or menu items---whatever
|
||||
suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a ``copyright disclaimer'' for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
@example
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
@var{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
@end example
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
78
gpl_replace
Executable file
78
gpl_replace
Executable file
|
@ -0,0 +1,78 @@
|
|||
#!/bin/csh
|
||||
#
|
||||
# $Id: gpl_replace,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
#
|
||||
# This script adds/replaces the GPL header $gpl_template in
|
||||
# all .c and .h files in the RCS repository. Must be executed on
|
||||
# a clean (no locked files) repository.
|
||||
#
|
||||
# Arguments:
|
||||
#
|
||||
# argv[1]: -r argument to ci
|
||||
# argv[2]: -m argument to ci, default provided
|
||||
|
||||
if( $#argv < 1 ) then
|
||||
echo "gpl_replace: missing target release number"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
if( $#argv == 1 ) then
|
||||
set argv = ($argv "Added/Replaced GPL header")
|
||||
endif
|
||||
|
||||
set gpl_template = gpl_template
|
||||
set rcs_flist = `ls RCS/*.[ch],v`
|
||||
set exit_code = 0
|
||||
|
||||
co $gpl_template
|
||||
if( $status != 0 ) then
|
||||
echo "gpl_replace: co ${gpl_template} failed"
|
||||
exit 9
|
||||
endif
|
||||
|
||||
foreach rcs_file ($rcs_flist)
|
||||
set file = `basename $rcs_file ,v`
|
||||
set s_file = "${file}_s"
|
||||
set j_file = "${file}_j"
|
||||
set b_file = "${file}_b"
|
||||
|
||||
# Extract file from repository
|
||||
co -l $file
|
||||
if( $status != 0 ) then
|
||||
echo "gpl_replace: ${file}: checkout failed; edit manually"
|
||||
set exit_code = 2
|
||||
continue
|
||||
endif
|
||||
|
||||
sed -e '/.*+-+.*/,$\!d' $file > $s_file
|
||||
|
||||
if( -z $s_file ) then
|
||||
# File does not contain the template yet; add
|
||||
cat $gpl_template - $file > $j_file <<EOF
|
||||
|
||||
/* +-+ */
|
||||
|
||||
EOF
|
||||
else
|
||||
# File did contain an older template; replace
|
||||
cat $gpl_template - $s_file > $j_file <<EOF
|
||||
|
||||
EOF
|
||||
endif
|
||||
|
||||
rm $s_file
|
||||
mv $file $b_file
|
||||
mv $j_file $file
|
||||
ci -r$argv[1] -m"$argv[2]" $file
|
||||
|
||||
# Remove backup file only if update was ok
|
||||
if( $status == 0 ) then
|
||||
rm $b_file
|
||||
else
|
||||
echo "gpl_replace: ${file}: ci failed; backup in ${b_file}"
|
||||
rcs -u $file
|
||||
set exit_code = 3
|
||||
continue
|
||||
endif
|
||||
end
|
||||
exit $exit_code
|
30
gpl_template
Normal file
30
gpl_template
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
565
hdw.c
Normal file
565
hdw.c
Normal file
|
@ -0,0 +1,565 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: hdw.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: hdw.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 23-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This module emulates the Hdw peripheral module, that controls all
|
||||
peripheral devices of the HP48. The Hdw Read/Write functions simply update
|
||||
the contents of the mod_status.hdw structure to reflect the contents of the
|
||||
actual Hdw registers. The actual emulation of the devices is performed
|
||||
by other source modules. References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, modules.h
|
||||
|
||||
.notes :
|
||||
$Log: hdw.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.13 2000/11/09 11:32:05 cibrario
|
||||
Revised to add file selection box GUI element, CPU halt/run
|
||||
requests and emulator's extended functions:
|
||||
|
||||
- Added code to trampoline to ExtendedFunction() when the calculator
|
||||
writes something into the lower nibble of the serial port's
|
||||
Receiver Buffer Register.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:42 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.2 2000/09/22 13:46:30 cibrario
|
||||
Implemented preliminary support of HP49 hw architecture:
|
||||
- The HP49 firmware (1.19-4) reads a nibble from 0x30 for unknown reasons;
|
||||
conditionally (#ifdef HP49_SUPPORT) enabled reads from relative
|
||||
addresses 0x30..0x34 without signaling a warning.
|
||||
|
||||
* Revision 3.1 2000/09/20 13:48:52 cibrario
|
||||
* Minor updates and fixes to avoid gcc compiler warnings on Solaris
|
||||
* when -ansi -pedantic -Wall options are selected.
|
||||
*
|
||||
* Revision 2.5 2000/09/14 15:08:59 cibrario
|
||||
* Update HdwRead() and HdwWrite() to support serial port emulation;
|
||||
* read/write from/to serial port register are mapped into invocation
|
||||
* of functions in the serial port emulation module. This module
|
||||
* merely provides buffering for multi-nibble hdw registers.
|
||||
*
|
||||
* Revision 2.4 2000/09/12 15:24:27 cibrario
|
||||
* Bug fix and update required to implement emulation of Port 1 and 2:
|
||||
* - fixed an improper memset() call in HdwInit()
|
||||
* - HdwRead() now returns the value of mod_status.hdw_card_status when
|
||||
* relative address 0x0F is read from.
|
||||
*
|
||||
* Revision 1.1 1998/02/17 11:49:59 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: hdw.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h> /* 3.1: memset() */
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "disk_io.h"
|
||||
#include "serial.h" /* 2.5: Serial port emulation module */
|
||||
#include "x_func.h" /* 3.13: Extended emulator functions */
|
||||
#include "debug.h"
|
||||
|
||||
#include "args.h"
|
||||
|
||||
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
static const int addr_mask[] = { 0x0000F, 0x000F0, 0x00F00, 0x0F000, 0xF0000 };
|
||||
|
||||
static const int32 int32_mask[] =
|
||||
{ 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F000,
|
||||
0x000F0000, 0x00F00000, 0x0F000000, 0xF0000000 };
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : HdwInit
|
||||
.kind : C function
|
||||
.creation : 23-Jan-1998
|
||||
.description :
|
||||
This function initializes the Hdw module, restoring the status of the
|
||||
peripheral devices associated to it from disk.
|
||||
|
||||
.call :
|
||||
HdwInit();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
MOD_I_CALLED
|
||||
MOD_W_HDW_INIT
|
||||
.notes :
|
||||
1.1, 23-Jan-1998, creation
|
||||
2.4, 11-Sep-2000, bug fix:
|
||||
memset() invocation was improper, and could lead to memory corruption
|
||||
|
||||
.- */
|
||||
void HdwInit(void)
|
||||
{
|
||||
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwInit");
|
||||
|
||||
if(ReadStructFromFile(args.hdw_file_name, sizeof(mod_status.hdw),
|
||||
&mod_status.hdw))
|
||||
{
|
||||
ChfCondition MOD_W_HDW_INIT, CHF_WARNING ChfEnd;
|
||||
ChfSignal();
|
||||
|
||||
(void)memset(&mod_status.hdw, 0, sizeof(mod_status.hdw));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : HdwSave
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function saves the current status of the peripheral devices associated
|
||||
to the Hdw module to disk.
|
||||
|
||||
.call :
|
||||
HdwSave();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
MOD_I_CALLED
|
||||
MOD_E_HDW_SAVE
|
||||
.notes :
|
||||
1.1, 11-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
void HdwSave(void)
|
||||
{
|
||||
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwSave");
|
||||
|
||||
if(WriteStructToFile(&mod_status.hdw, sizeof(mod_status.hdw),
|
||||
args.hdw_file_name))
|
||||
{
|
||||
ChfCondition MOD_E_HDW_SAVE, CHF_ERROR ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : HdwRead
|
||||
.kind : C function
|
||||
.creation : 23-Jan-1998
|
||||
.description :
|
||||
This function reads a nibble from the Hdw module.
|
||||
|
||||
.call :
|
||||
d = HdwRead(rel_address);
|
||||
.input :
|
||||
Address rel_address, relative address
|
||||
.output :
|
||||
Nibble d, data
|
||||
.status_codes :
|
||||
MOD_I_CALLED
|
||||
MOD_W_HDW_READ
|
||||
.notes :
|
||||
1.1, 23-Jan-1998, creation
|
||||
2.4, 11-Sep-2000, update
|
||||
- read from rel_address 0x0F now returns the current value of
|
||||
mod_status.hdw.card_status; its value is set during the
|
||||
initialization of other peripheral modules.
|
||||
2.5, 14-Sep-2000, update
|
||||
- added support for serial port emulation
|
||||
|
||||
.- */
|
||||
Nibble HdwRead(Address rel_address)
|
||||
{
|
||||
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwRead");
|
||||
|
||||
/* 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[],
|
||||
simply put a break in the case, otherwise code any special action for
|
||||
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:
|
||||
return (mod_status.hdw.serial_rbr = Serial_RBR_Read()) & 0x0F;
|
||||
|
||||
case 0x15:
|
||||
return (mod_status.hdw.serial_rbr >> 4) & 0x0F;
|
||||
|
||||
case 0x0E: /* Card interface */
|
||||
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
|
||||
/* 3.2: The HP49 firmware (1.19-4) reads a nibble from 0x30 */
|
||||
case 0x30:
|
||||
case 0x31:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
case 0x34:
|
||||
return (Nibble)0x0;
|
||||
#endif
|
||||
|
||||
case 0x37: /* Timer 1 value */
|
||||
return mod_status.hdw.t1_val;
|
||||
|
||||
case 0x38: /* Timer 2 value */
|
||||
case 0x39:
|
||||
case 0x3A:
|
||||
case 0x3B:
|
||||
case 0x3C:
|
||||
case 0x3D:
|
||||
case 0x3E:
|
||||
case 0x3F:
|
||||
return
|
||||
(Nibble)((mod_status.hdw.t2_val >> ((rel_address-0x38)*4)) & 0x0F);
|
||||
|
||||
default:
|
||||
ChfCondition MOD_W_HDW_READ, CHF_WARNING, rel_address ChfEnd;
|
||||
ChfSignal();
|
||||
return (Nibble)0xF;
|
||||
}
|
||||
|
||||
/* Read from hdw register array */
|
||||
return mod_status.hdw.hdw[rel_address];
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : HdwWrite
|
||||
.kind : C function
|
||||
.creation : 23-Jan-1998
|
||||
.description :
|
||||
This function writes a nibble to the Hdw module.
|
||||
|
||||
.call :
|
||||
HdwWrite(rel_address, data);
|
||||
.input :
|
||||
Address rel_address, relative address
|
||||
Nibble data, data to be written
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
MOD_I_CALLED
|
||||
MOD_W_HDW_WRITE
|
||||
.notes :
|
||||
1.1, 23-Jan-1998, creation
|
||||
2.5, 14-Sep-2000, update
|
||||
- added support for serial port emulation
|
||||
|
||||
.- */
|
||||
void HdwWrite(Address rel_address, Nibble data)
|
||||
{
|
||||
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "HdwWrite");
|
||||
|
||||
/* 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
|
||||
the switch, instead, simply takes care to shadow the hdw register into
|
||||
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:
|
||||
ExtendedFunction(data);
|
||||
break;
|
||||
|
||||
/* Serial port transmitter buffer; the actual write takes place
|
||||
when the MS nibble is written; serial_tbr buffers the LS nibble.
|
||||
*/
|
||||
case 0x16:
|
||||
mod_status.hdw.serial_tbr =
|
||||
(mod_status.hdw.serial_tbr & 0xF0) | (int8)data;
|
||||
break;
|
||||
|
||||
case 0x17:
|
||||
mod_status.hdw.serial_tbr =
|
||||
(mod_status.hdw.serial_tbr & 0x0F) | ((int8)data << 4);
|
||||
Serial_TBR_Write(mod_status.hdw.serial_tbr);
|
||||
break;
|
||||
|
||||
case 0x18: /* Service request */
|
||||
case 0x19:
|
||||
break;
|
||||
|
||||
case 0x1A: /* IR Control Register */
|
||||
break;
|
||||
|
||||
case 0x1B: /* Base nibble offset */
|
||||
break;
|
||||
|
||||
case 0x1C: /* IR Status Register */
|
||||
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;
|
||||
}
|
317
hw_config.c
Normal file
317
hw_config.c
Normal file
|
@ -0,0 +1,317 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: hw_config.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HPxx emulator
|
||||
.title : $RCSfile: hw_config.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 21-Sep-2000
|
||||
.keywords : *
|
||||
.description :
|
||||
This module contains the module description tables for all HPxx
|
||||
hardware configurations currently supported. Moreover, it implements
|
||||
the function ModSelectDescription(hw), to select and register a
|
||||
module description table depending on an hardware configuration
|
||||
selection string (hw). References:
|
||||
|
||||
Guide to the Saturn Processor Rev. 1.0b by Matthew Mastracci
|
||||
HP49 Memory Explained, USENET post, by Steve Sousa.
|
||||
|
||||
.include : config.h machdep.h, cpu.h, modules.h
|
||||
|
||||
.notes :
|
||||
$Log: hw_config.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:43 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.3 2000/09/26 15:18:16 cibrario
|
||||
Revised to implement Flash ROM write access:
|
||||
- updated description of ModDescription table components
|
||||
- the HP49 NCE3 controller now has MOD_MAP_FLAGS_ABS set in .map_flags
|
||||
|
||||
* Revision 3.2 2000/09/22 14:40:18 cibrario
|
||||
* *** empty log message ***
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: hw_config.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Module description tables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
extern void RomInit(void);
|
||||
extern void HdwInit(void);
|
||||
extern void RamInit(void);
|
||||
extern void Ce1Init(void);
|
||||
extern void Ce2Init(void);
|
||||
extern void NCe3Init(void);
|
||||
|
||||
extern void RomSave(void);
|
||||
extern void HdwSave(void);
|
||||
extern void RamSave(void);
|
||||
extern void Ce1Save(void);
|
||||
extern void Ce2Save(void);
|
||||
extern void NCe3Save(void);
|
||||
|
||||
extern Nibble RomRead(Address);
|
||||
extern Nibble HdwRead(Address);
|
||||
extern Nibble RamRead(Address);
|
||||
extern Nibble Ce1Read(Address);
|
||||
extern Nibble Ce2Read(Address);
|
||||
extern Nibble NCe3Read(Address);
|
||||
|
||||
extern void RomWrite(Address, Nibble);
|
||||
extern void HdwWrite(Address, Nibble);
|
||||
extern void RamWrite(Address, Nibble);
|
||||
extern void Ce1Write(Address, Nibble);
|
||||
extern void Ce2Write(Address, Nibble);
|
||||
extern void NCe3Write(Address, Nibble);
|
||||
|
||||
extern void RomInit49(void);
|
||||
extern void HdwInit49(void);
|
||||
extern void RamInit49(void);
|
||||
extern void Ce1Init49(void);
|
||||
extern void Ce2Init49(void);
|
||||
extern void NCe3Init49(void);
|
||||
|
||||
extern void RomSave49(void);
|
||||
extern void HdwSave49(void);
|
||||
extern void RamSave49(void);
|
||||
extern void Ce1Save49(void);
|
||||
extern void Ce2Save49(void);
|
||||
extern void NCe3Save49(void);
|
||||
|
||||
extern Nibble RomRead49(Address);
|
||||
extern Nibble HdwRead49(Address);
|
||||
extern Nibble RamRead49(Address);
|
||||
extern Nibble Ce1Read49(Address);
|
||||
extern Nibble Ce2Read49(Address);
|
||||
extern Nibble NCe3Read49(Address);
|
||||
|
||||
extern void RomWrite49(Address, Nibble);
|
||||
extern void HdwWrite49(Address, Nibble);
|
||||
extern void RamWrite49(Address, Nibble);
|
||||
extern void Ce1Write49(Address, Nibble);
|
||||
extern void Ce2Write49(Address, Nibble);
|
||||
extern void NCe3Write49(Address, Nibble);
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *hw;
|
||||
ModDescription description;
|
||||
}
|
||||
|
||||
table[] =
|
||||
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
HP48
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
{
|
||||
"hp48",
|
||||
|
||||
{
|
||||
/* name, id, access_prio,
|
||||
init, save,
|
||||
read, write,
|
||||
r_config, r_abs_base_addr, r_size,
|
||||
map_flags
|
||||
*/
|
||||
|
||||
{ "ROM (ROM)", 0x00, 0,
|
||||
RomInit, RomSave,
|
||||
RomRead, RomWrite,
|
||||
MOD_CONFIGURED, 0x00000, 0xFFFFF,
|
||||
},
|
||||
|
||||
{ "Hardware Regs. (HDW)", 0x19, 5,
|
||||
HdwInit, HdwSave,
|
||||
HdwRead, HdwWrite,
|
||||
MOD_SIZE_CONFIGURED, 0x00000, 0x00040,
|
||||
},
|
||||
|
||||
{ "Internal RAM (RAM)", 0x03, 4,
|
||||
RamInit, RamSave,
|
||||
RamRead, RamWrite,
|
||||
MOD_UNCONFIGURED, 0, 0,
|
||||
},
|
||||
|
||||
{ "Bank Select (CE1)", 0x05, 2,
|
||||
Ce1Init, Ce1Save,
|
||||
Ce1Read, Ce1Write,
|
||||
MOD_UNCONFIGURED, 0, 0,
|
||||
},
|
||||
|
||||
{ "Port 1 Control (CE2)", 0x07, 3,
|
||||
Ce2Init, Ce2Save,
|
||||
Ce2Read, Ce2Write,
|
||||
MOD_UNCONFIGURED, 0, 0,
|
||||
},
|
||||
|
||||
{ "Port 2 Control (NCE3)", 0x01, 1,
|
||||
NCe3Init, NCe3Save,
|
||||
NCe3Read, NCe3Write,
|
||||
MOD_UNCONFIGURED, 0, 0,
|
||||
}
|
||||
}},
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
HP49
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
{
|
||||
"hp49",
|
||||
|
||||
{
|
||||
/* name, id, access_prio,
|
||||
init, save,
|
||||
read, write,
|
||||
r_config, r_abs_base_addr, r_size,
|
||||
map_flags
|
||||
*/
|
||||
|
||||
{ "ROM (ROM)", 0x00, 0,
|
||||
RomInit49, RomSave49,
|
||||
RomRead49, RomWrite49,
|
||||
MOD_CONFIGURED, 0x00000, 0xFFFFF,
|
||||
},
|
||||
|
||||
{ "Hardware Regs. (HDW)", 0x19, 5,
|
||||
HdwInit, HdwSave,
|
||||
HdwRead, HdwWrite,
|
||||
MOD_SIZE_CONFIGURED, 0x00000, 0x00040,
|
||||
},
|
||||
|
||||
{ "IRAM (RAM)", 0x03, 4,
|
||||
RamInit49, RamSave49,
|
||||
RamRead49, RamWrite49,
|
||||
MOD_UNCONFIGURED, 0, 0,
|
||||
},
|
||||
|
||||
{ "Bank Select (CE1)", 0x05, 2,
|
||||
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]))
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Public functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : ModSelectDescription
|
||||
.kind : C function
|
||||
.creation : 21-Sep-2000
|
||||
.description :
|
||||
This function selects and registers (invoking ModRegisterDescription())
|
||||
a module description table depending on the hardware configuration
|
||||
string passed as argument.
|
||||
|
||||
.call :
|
||||
ModSelectDescription(hw)
|
||||
.input :
|
||||
const char *hw, hardware configuration string
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
MOD_I_CALLED
|
||||
MOD_E_NO_MATCH
|
||||
.notes :
|
||||
1.1, 28-Jan-1998, creation
|
||||
|
||||
.- */
|
||||
void ModSelectDescription(const char *hw)
|
||||
{
|
||||
int i;
|
||||
|
||||
debug1(DEBUG_C_TRACE, MOD_I_CALLED, "ModSelectDescription");
|
||||
|
||||
for(i=0; i<N_DESCRIPTIONS && strcmp(hw, table[i].hw); i++);
|
||||
|
||||
if(i==N_DESCRIPTIONS)
|
||||
{
|
||||
ChfCondition MOD_E_NO_MATCH, CHF_ERROR, hw ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else
|
||||
ModRegisterDescription(table[i].description);
|
||||
}
|
128
introd.texi
Normal file
128
introd.texi
Normal file
|
@ -0,0 +1,128 @@
|
|||
@c $Id: introd.texi,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
|
||||
@node Introduction and License Conditions, Preparing saturn for Use, Top, Top
|
||||
@chapter Introduction and License Conditions
|
||||
@cindex Introduction
|
||||
@cindex License Conditions
|
||||
|
||||
The @code{saturn} software is a poor-man's emulator of the HP48GX, HP49,
|
||||
and HP40 calculators made by Hewlett-Packard. It should compile and run
|
||||
on any recent, XPG4-UNIX compliant, Unix-like system with a working X
|
||||
Window System interface and OSF/Motif-compatible libraries. For
|
||||
example, @code{saturn} is known to work on the following systems:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Digital UNIX V4.0D on a Digital AlphaStation 200 4/100
|
||||
@item
|
||||
Solaris 2.6 on a Sun Ultra 5, GNU gcc compiler
|
||||
@item
|
||||
Debian GNU/Linux 2.1v0 with LessTif 0.91.8 on a HP Kayak XU
|
||||
@item
|
||||
Ultrix 4.4 on a Digital DECsystem 5500, GNU make@footnote{Limited
|
||||
support: REAL_CPU_SPEED build option and serial port emulation
|
||||
are not available}
|
||||
@item
|
||||
IRIX 6.5 on a SiliconGraphics Octane
|
||||
@end itemize
|
||||
|
||||
If you succeed in building @code{saturn} on a system not mentioned
|
||||
above, plase drop an email to the author, so that this documentation
|
||||
can be updated.
|
||||
|
||||
@strong{Important notice:} I, the author, wrote the source code of
|
||||
@code{saturn} in my spare time and, more often than not, while I was in
|
||||
a hurry; therefore, it neither is nor intends to be a shiny reference
|
||||
about good programming practice and so on. The documentation embedded
|
||||
in the source code often is sparse, incomplete and not much useful; even
|
||||
the structure of the code itself and some design choices, seen in
|
||||
retrospective, are not so appropriate.
|
||||
|
||||
The @code{saturn} software is ``free''; this means that everyone is free to
|
||||
use it and free to redistribute it on a free basis. However,
|
||||
@code{saturn} is @strong{not} in the public domain; it is copyrighted
|
||||
and there are restrictions on its distribution, but these restrictions
|
||||
are designed to permit everything that a good cooperating citizen would
|
||||
want to do. What is not allowed is to try to prevent others from
|
||||
further sharing any version of these programs that they might get from
|
||||
you.
|
||||
|
||||
Also, for my own protection, I must make certain that everyone finds
|
||||
out that there is no warranty for the @code{saturn} software. If this
|
||||
program is modified by someone else and passed on, I want their
|
||||
recipients to know that what they have is not what I distributed, so
|
||||
that any problems introduced by others will not reflect on my
|
||||
reputation.
|
||||
|
||||
The precise conditions of the licenses for the programs currently
|
||||
being distributed that relate to @code{saturn} are found in the General Public
|
||||
License. For more information, see @ref{GNU GENERAL PUBLIC LICENSE}.
|
||||
|
||||
In addition, the name of IRITI-CNR shall not be used in advertising
|
||||
or publicity pertaining to distribution of the software or of any
|
||||
derived work without specific, written prior permission.
|
||||
|
||||
Bug reports or suggestions for @code{saturn} are most welcome. To do
|
||||
this, please contact the author, preferably by email, at the following
|
||||
address:
|
||||
|
||||
@sp 2
|
||||
@center Ivan Cibrario Bertolotti
|
||||
@center IRITI - National Research Council
|
||||
@center c/o IEN "Galileo Ferraris"
|
||||
@center Strada delle Cacce, 91
|
||||
@center 10135 - Torino (ITALY)
|
||||
@center email: cibrario@@iriti.cnr.it
|
||||
@sp 2
|
||||
|
||||
For bug reports and/or build problems, please include at least:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
the release number of the @code{saturn} component involved.
|
||||
@item
|
||||
hardware, operating system, and compiler versions.
|
||||
@item
|
||||
for bugs, the calculator model on which the bug arises,
|
||||
the release number of the calculator's ROM image you have,
|
||||
a thorough description of the problem and, if possible,
|
||||
a patch.
|
||||
@item
|
||||
for build problems, a transcript of the build session,
|
||||
preferably made by @code{script} and, if possible,
|
||||
a patch.
|
||||
@item
|
||||
anything else that you think would be helpful, provided
|
||||
its size is reasonable. In particular, do @strong{not}
|
||||
send me your ROM images; this is not only a copyright violation,
|
||||
it will also hog my mailbox.
|
||||
@end itemize
|
||||
|
||||
Last, but not least, I wish to thank the following
|
||||
people; without their help, @code{saturn} would probably
|
||||
not exist:
|
||||
|
||||
@sp 2
|
||||
@center My little twin sons, Samuele and Guglielmo
|
||||
@center (I denied them the time I spent developing @code{saturn})
|
||||
@sp 1
|
||||
@center Jean-Yves Avenard
|
||||
@center (No need to say why...)
|
||||
@sp 1
|
||||
@center Bernard Parisse
|
||||
@center (Instant-load code, beta test and good advice)
|
||||
@sp 1
|
||||
@center Matthew Mastracci
|
||||
@center (author of the "Guide to the Saturn Processor")
|
||||
@sp 1
|
||||
@center Eddie C. Dost
|
||||
@center (author of @code{x48})
|
||||
@sp 1
|
||||
@c A simple ligature requires much work iftex...
|
||||
@iftex
|
||||
@center Sebastien Carlier and Christoph Gie@ss elink
|
||||
@end iftex
|
||||
@ifinfo
|
||||
@center Sebastien Carlier and Christoph Giesselink
|
||||
@end ifinfo
|
||||
@center (respectively, author and maintainer of @code{emu48}).
|
341
keyb.c
Normal file
341
keyb.c
Normal file
|
@ -0,0 +1,341 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: keyb.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: keyb.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 29-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This module emulates the keyboard interface of the Yorke chip.
|
||||
References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
NOTE: In the current (r1.1) implementation,
|
||||
the emulation accuracy could be poor.
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, modules.h, keyb.h
|
||||
|
||||
.notes :
|
||||
$Log: keyb.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.13 2000/11/09 11:32:49 cibrario
|
||||
Revised to add file selection box GUI element, CPU halt/run
|
||||
requests and emulator's extended functions:
|
||||
|
||||
- Implemented KeybReset()
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:44 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 2.1 2000/09/08 15:17:32 cibrario
|
||||
Deep revision to accommodate the new GUI: all facilities to map a
|
||||
key code (enum Key) into an IN/OUT pair have been removed,
|
||||
because the GUI now does this function itself; KeybPress() and
|
||||
KeybRelease() now directly accept an IN/OUT pair as input.
|
||||
|
||||
* Revision 1.1 1998/02/17 11:53:23 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: keyb.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "keyb.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID MOD_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
#define OUT_BITS 12
|
||||
|
||||
/* cur_in:
|
||||
|
||||
This array contains the current value the CPU IN register will assume
|
||||
for each bit set in the OUT register.
|
||||
*/
|
||||
static InputRegister cur_in[OUT_BITS];
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : KeybRSI
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function is called by the CPU emulator when the RSI instruction is
|
||||
executed. It resets the keyboard interrupt system and posts a maskable
|
||||
interrupt request if any key is pressed.
|
||||
|
||||
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.
|
||||
|
||||
.call :
|
||||
KeybRSI();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
*
|
||||
.notes :
|
||||
1.1, 17-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
void KeybRSI(void)
|
||||
{
|
||||
/* Post an IRQ if the IN register is not zero */
|
||||
|
||||
CpuIntRequest(KeybIN((OutputRegister)0x1FF) != (InputRegister)0 ?
|
||||
INT_REQUEST_IRQ : INT_REQUEST_NONE);
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : KeybIn
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function is called by the CPU emulator when either a C=IN or a A=IN
|
||||
instruction is executed. It scans the keyboard and returns the current
|
||||
value of the IN register for the given value of the OUT reguster.
|
||||
|
||||
.call :
|
||||
in = KeybIN(out);
|
||||
.input :
|
||||
OutputRegister out, current value of the OUT register
|
||||
.output :
|
||||
InputRegister in, computed value of the IN register
|
||||
.status_codes :
|
||||
*
|
||||
.notes :
|
||||
1.1, 17-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
InputRegister KeybIN(OutputRegister out)
|
||||
{
|
||||
/* Compute the current value of the IN register */
|
||||
InputRegister in = (InputRegister)0;
|
||||
int bit;
|
||||
|
||||
/* For each bit set in the 'out' register, OR the corresponding IN register
|
||||
value into 'in'
|
||||
*/
|
||||
for(bit=0; bit<OUT_BITS; bit++)
|
||||
{
|
||||
if(out & 0x01) in |= cur_in[bit];
|
||||
out >>= 1;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : KeybPress
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function tells to the keyboard emulator that key 'key' has been
|
||||
pressed. It updates the internal keyboard status information and, if
|
||||
necessary, posts an interrupt request to the CPU.
|
||||
|
||||
.call :
|
||||
KeybPress(key);
|
||||
.input :
|
||||
const char *key, identifies the key that has been pressed.
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
MOD_W_BAD_KEY
|
||||
MOD_W_BAD_OUT_BIT
|
||||
.notes :
|
||||
1.1, 17-Feb-1998, creation
|
||||
2.1, 6-Sep-2000,
|
||||
deeply revised to accomodate the new GUI
|
||||
|
||||
.- */
|
||||
void KeybPress(const char *key)
|
||||
{
|
||||
if(strcmp(key, "*") == 0)
|
||||
{
|
||||
/* This is the ON key */
|
||||
int i;
|
||||
|
||||
/* Set all 0x8000 lines */
|
||||
for(i=0; i<OUT_BITS; i++) cur_in[i] |= 0x8000;
|
||||
|
||||
/* Post an interrupt request to the CPU */
|
||||
CpuIntRequest(INT_REQUEST_NMI);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
int in_val, out_bit;
|
||||
|
||||
if(sscanf(key, "%x/%x", &out_bit, &in_val) != 2)
|
||||
{
|
||||
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else if(out_bit < 0 || out_bit >= OUT_BITS)
|
||||
{
|
||||
ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Update the cur_in array */
|
||||
cur_in[out_bit] |= in_val;
|
||||
|
||||
/* Post an interrupt request to the CPU */
|
||||
CpuIntRequest(INT_REQUEST_NMI);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : KeybRelease
|
||||
.kind : C function
|
||||
.creation : 11-Feb-1998
|
||||
.description :
|
||||
This function tells to the keyboard emulator that key 'key' has been
|
||||
released. It updates the internal keyboard status information.
|
||||
|
||||
.call :
|
||||
KeybRelease(key);
|
||||
.input :
|
||||
const char *key, identifies the key that has been released.
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
MOD_W_BAD_KEY
|
||||
MOD_W_BAD_OUT_BIT
|
||||
.notes :
|
||||
1.1, 17-Feb-1998, creation
|
||||
2.1, 6-Sep-2000,
|
||||
deeply revised to accomodate the new GUI
|
||||
|
||||
.- */
|
||||
void KeybRelease(const char *key)
|
||||
{
|
||||
if(strcmp(key, "*") == 0)
|
||||
{
|
||||
/* This is the ON key */
|
||||
int i;
|
||||
|
||||
/* Reset all 0x8000 lines */
|
||||
for(i=0; i<OUT_BITS; i++) cur_in[i] &= 0x7FFF;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
int in_val, out_bit;
|
||||
|
||||
if(sscanf(key, "%x/%x", &out_bit, &in_val) != 2)
|
||||
{
|
||||
ChfCondition MOD_W_BAD_KEY, CHF_WARNING, key ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else if(out_bit < 0 || out_bit >= OUT_BITS)
|
||||
{
|
||||
ChfCondition MOD_W_BAD_OUT_BIT, CHF_WARNING, out_bit ChfEnd;
|
||||
ChfSignal();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Update the cur_in array */
|
||||
cur_in[out_bit] &= ~in_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* .+
|
||||
|
||||
.title : KeybReset
|
||||
.kind : C function
|
||||
.creation : 7-Nov-2000
|
||||
.description :
|
||||
This function resets the emulated keyboard; all keys are released.
|
||||
|
||||
.call :
|
||||
KeybReset();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
.notes :
|
||||
3.13, 7-Nov-2000, creation
|
||||
|
||||
.- */
|
||||
void KeybReset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Reset all 0x8000 lines */
|
||||
for(i=0; i<OUT_BITS; i++) cur_in[i] = 0;
|
||||
}
|
88
keyb.h
Normal file
88
keyb.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: keyb.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: keyb.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 17-Feb-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
Header for the keyboard emulation module. References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
.include : config.h, machdep.h, cpu.h, modules.h
|
||||
|
||||
.notes :
|
||||
$Log: keyb.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.13 2000/11/09 11:33:28 cibrario
|
||||
Revised to add file selection box GUI element, CPU halt/run
|
||||
requests and emulator's extended functions:
|
||||
|
||||
- Added prototype of KeybReset()
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:45 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 2.1 2000/09/08 15:02:14 cibrario
|
||||
Updated prototypes of KeybPress() and KeybRelease() to accommodate
|
||||
the new GUI. As a consequence, suppressed the definition of
|
||||
'enum Key', no longer needed.
|
||||
|
||||
* Revision 1.1 1998/02/17 11:53:34 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
void KeybRSI(void);
|
||||
InputRegister KeybIN(OutputRegister out);
|
||||
void KeybPress(const char *key);
|
||||
void KeybRelease(const char *key);
|
||||
void KeybReset(void);
|
75
machdep.h
Normal file
75
machdep.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: machdep.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: machdep.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 28-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
Machine-dependent type definitions.
|
||||
|
||||
.include : config.h
|
||||
|
||||
.notes :
|
||||
$Log: machdep.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:45 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 1.1 1998/02/17 11:58:48 cibrario
|
||||
Initial revision
|
||||
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Data type definitions
|
||||
All Data types must be SIGNED
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
typedef char int1;
|
||||
typedef char int4;
|
||||
typedef char int8;
|
||||
typedef int int12;
|
||||
typedef int int16;
|
||||
typedef int int20;
|
||||
typedef int int32;
|
9
make_dist
Executable file
9
make_dist
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# $Id: make_dist,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
#
|
||||
# This script builds the RCS distribution tar, saturn_RCS.tar;
|
||||
# to do this, it first executes a 'make clean'.
|
||||
|
||||
make clean
|
||||
tar cf saturn_RCS.tar RCS/* Chf/*
|
44
make_src_dist
Executable file
44
make_src_dist
Executable file
|
@ -0,0 +1,44 @@
|
|||
#!/bin/csh
|
||||
#
|
||||
# $Id: make_src_dist,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
#
|
||||
# This script builds the source distribution tar, saturn_src_....tar;
|
||||
# the source distribution contains a snapshot of the RCS repository
|
||||
# for release $argv[1]. The name of the source distribution tar
|
||||
# includes $argv[1] as its last component.
|
||||
|
||||
if( $#argv < 1 ) then
|
||||
echo "make_src_dist: missing target release number"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
set rel = $argv[1]
|
||||
set target_tar = saturn_src_$rel.tar
|
||||
set rcs_flist = (RCS/*,v)
|
||||
set flist = ""
|
||||
set exit_code = 0
|
||||
|
||||
foreach rcs_file ($rcs_flist)
|
||||
set file = `basename $rcs_file ,v`
|
||||
|
||||
# Extract file from repository
|
||||
co -r$rel $file
|
||||
if( $status != 0 ) then
|
||||
echo "make_src_dist: ${file}: checkout failed for release $rel"
|
||||
set exit_code = 2
|
||||
continue
|
||||
endif
|
||||
|
||||
# Add file to file list
|
||||
set flist = ($flist $file)
|
||||
end
|
||||
|
||||
make clean
|
||||
tar cf $target_tar $flist Chf/*
|
||||
|
||||
if( $status != 0 ) then
|
||||
echo "make_src_dist: tar failed"
|
||||
set exit_code = 3
|
||||
endif
|
||||
|
||||
exit $exit_code
|
102
make_ubin_dist
Executable file
102
make_ubin_dist
Executable file
|
@ -0,0 +1,102 @@
|
|||
#!/bin/csh
|
||||
#
|
||||
# $Id: make_ubin_dist,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
#
|
||||
# This script builds a user-level binary distribution for release
|
||||
# $argv[1]. The name of the binary distribution tar
|
||||
# includes $argv[1] as its last component.
|
||||
#
|
||||
# $argv[2] contains the make Makefile command
|
||||
|
||||
if( $#argv < 1 ) then
|
||||
echo "make_ubin_dist: missing target release number"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
if( $#argv < 2 ) then
|
||||
echo "make_ubin_dist: missing make Makefile command"
|
||||
exit 1
|
||||
endif
|
||||
|
||||
set rel = $argv[1]
|
||||
set src_tar = saturn_src_$rel.tar
|
||||
set ubin_tar = saturn_ubin_$rel.tar
|
||||
|
||||
set special_flist = (sutil_48.lib sutil_49.lib)
|
||||
|
||||
set bin_flist = (README.txt BUILD_INFO.txt saturn Saturn.ad saturn.cat run_saturn quick_start saturn.ps saturn.info pack)
|
||||
|
||||
./make_src_dist $rel
|
||||
if( $status != 0 && $status != 2 ) then
|
||||
echo "make_ubin_dist: make_src_dist failed"
|
||||
exit 2
|
||||
endif
|
||||
|
||||
mkdir tmp_ubin; cd tmp_ubin
|
||||
|
||||
tar xvf ../$src_tar
|
||||
if( $status != 0 ) then
|
||||
echo "make_ubin_dist: source tar extract failed"
|
||||
exit 3
|
||||
endif
|
||||
|
||||
cat - > BUILD_INFO.txt <<EOF
|
||||
This is a user-level binary distribution of saturn release $rel.
|
||||
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
|
||||
The distribution was created on:
|
||||
`date`
|
||||
The build host was (uname -a):
|
||||
`uname -a`
|
||||
EOF
|
||||
|
||||
if( $status != 0 ) then
|
||||
echo "make_ubin_dist: can't create BUILD_INFO.txt"
|
||||
exit 4
|
||||
endif
|
||||
|
||||
$argv[2]
|
||||
make depend; make; make doc
|
||||
|
||||
# Special: Copy special binaries down
|
||||
foreach special ($special_flist)
|
||||
cp ../$special .
|
||||
end
|
||||
|
||||
tar cvf ../$ubin_tar $bin_flist $special_flist
|
||||
|
||||
if( $status != 0 ) then
|
||||
echo "make_ubin_dist: can't create binary tar"
|
||||
exit 5
|
||||
endif
|
||||
|
||||
cd ..
|
||||
rm -rf tmp_ubin
|
616
modules.h
Normal file
616
modules.h
Normal file
|
@ -0,0 +1,616 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: modules.h,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: modules.h,v $
|
||||
.kind : C header
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 28-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This header contains all definitions and declarations related to the
|
||||
peripheral modules of the HP48. References:
|
||||
|
||||
SASM.DOC by HP (HORN disk 4)
|
||||
Guide to the Saturn Processor Rev. 0.00f by Matthew Mastracci
|
||||
entries.srt by Mika Heiskanen (mheiskan@vipunen.hut.fi)
|
||||
x48 source code by Eddie C. Dost (ecd@dressler.de)
|
||||
|
||||
.include : config.h machdep.h cpu.h
|
||||
|
||||
.notes :
|
||||
$Log: modules.h,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:50 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.3 2000/09/26 15:10:22 cibrario
|
||||
Revised to implement Flash ROM write access:
|
||||
- Added .map_flags field to struct ModDescriptionEntry
|
||||
- New status code MOD_E_ROM_SAVE
|
||||
|
||||
* Revision 3.2 2000/09/22 14:05:32 cibrario
|
||||
* Implemented preliminary support of HP49 hw architecture:
|
||||
* - moved ROM/RAM storage areas in ModStatus into private,
|
||||
* configuration-specific, dynamically allocated data structures.
|
||||
* - added flash-rom access accelerators for the hp49 hw configuration
|
||||
* - added new status codes: MOD_E_NO_MATCH, MOD_F_MOD_STATUS_ALLOC,
|
||||
* MOD_F_NO_DESCRIPTION
|
||||
* - added prototype of new functions: ModSelectDescription(),
|
||||
* ModRegisterDescription()
|
||||
*
|
||||
* Revision 3.1 2000/09/20 14:00:40 cibrario
|
||||
* Minor updates and fixes to avoid gcc compiler warnings on Solaris
|
||||
* when -ansi -pedantic -Wall options are selected.
|
||||
*
|
||||
* Revision 2.7 2000/09/19 11:12:46 cibrario
|
||||
* Deeply revised to implement module config/unconfig cache.
|
||||
*
|
||||
* Revision 2.5 2000/09/14 15:20:18 cibrario
|
||||
* Added serial port buffer registers .serial_rbr and .serial_tbr
|
||||
* in struct ModHdw; the hdw module uses them to buffer nibbles
|
||||
* to/from multi-nibble registers.
|
||||
*
|
||||
* Revision 2.4 2000/09/12 15:47:32 cibrario
|
||||
* The follwing updates were required to implement emulation of Port 1
|
||||
* and 2, and to prepare the support of additional hw configurations:
|
||||
* - added an hw configuration-dependent field to struct ModHdw: .accel;
|
||||
* this field holds information useful to accelerate frequently executed
|
||||
* operations on a given hw architecture.
|
||||
* In the current hw configuration, it is used to hold the last
|
||||
* address extension loaded into the bank switcher's F/F.
|
||||
* The .accel_valid field indicates whether .accel is valid or not;
|
||||
* .accel_valid is cleared when the ModHdw structure has not been read
|
||||
* back correctly from mass storage.
|
||||
* - added a new member to ModHdw: .card_status;
|
||||
* it represent the current card status (HDW relative address 0x0F).
|
||||
* - added storage space in struct ModStatus to accommodate Port 1 and 2.
|
||||
* - added new status codes: MOD_I_BS_ADDRESS, MOD_I_PORT_1_WP,
|
||||
* MOD_I_PORT_2_WP, MOD_W_PORT_1_INIT, MOD_W_PORT_2_INIT,
|
||||
* MOD_E_PORT_1_SAVE, MOD_E_CE1_WRITE, MOD_E_PORT_2_SAVE,
|
||||
* MOD_E_NCE3_READ, MOD_E_NCE3_WRITE.
|
||||
*
|
||||
* Revision 2.1 2000/09/08 15:20:50 cibrario
|
||||
* Updated template of MOD_W_BAD_KEY status code; added new status
|
||||
* code MOD_W_BAD_OUT_BIT. Both changes reflect the updates made to
|
||||
* the keyboard emulation module in order to accommodate the new GUI.
|
||||
*
|
||||
* Revision 1.1 1998/02/17 14:55:04 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Data type definitions - require config.h, machdep.h, cpu.h
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define N_MOD 6
|
||||
#define N_PAGE_TABLE_ENTRIES 16384
|
||||
#define N_ROM_SIZE 512*1024*2
|
||||
#define N_RAM_SIZE 128*1024*2
|
||||
#define N_FLASH_SIZE_49 2048*1024*2 /* 3.2 */
|
||||
#define N_RAM_SIZE_49 512*1024*2 /* 3.2 */
|
||||
|
||||
/* 2.4: Port_1 (CE2) size */
|
||||
#define N_PORT_1_SIZE 128*1024*2
|
||||
/* 2.4: Port_2 (NCE3) size */
|
||||
#define N_PORT_2_SIZE N_PORT_2_BANK*128*1024*2
|
||||
|
||||
#define N_HDW_SIZE 256
|
||||
|
||||
#define MOD_MAP_CHECK_OB_SIZE 128
|
||||
#define MOD_MAP_TABLE_OB_SIZE 512
|
||||
|
||||
/* 2.7: Number of entries in module config cache */
|
||||
#define N_MOD_CACHE_ENTRIES 8
|
||||
|
||||
#define MOD_RCS_INFO "$Revision: 4.1 $ $State: Rel $"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macros
|
||||
|
||||
ModAddress returns the base address of a page, given its number (Address)
|
||||
ModOffset returns the page offset of an address (int)
|
||||
ModPage returns the page number of an address (Address)
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define ModAddress(page) ((Address)(page) << 6)
|
||||
#define ModPage(address) ((int)(((address) & 0xFFFC0) >> 6))
|
||||
#define ModOffset(address) ((address) & 0x0003F)
|
||||
|
||||
|
||||
/*
|
||||
ModDescription
|
||||
|
||||
This const array contains an entry for each peripheral module connected
|
||||
to the peripheral bus of the Saturn CPU; the entry describes the
|
||||
characteristics of the module.
|
||||
|
||||
name: the mnemonic name of the module; the Saturn CPU doesn't
|
||||
actually use this information, but it's still useful during
|
||||
debugging.
|
||||
|
||||
id: the ID of the module, returned by the C=ID instruction
|
||||
when the module is unconfigured.
|
||||
|
||||
access_prio: the access priority of the module, when the address spaces of
|
||||
more than one module overlap. Higher values correspond to
|
||||
higher priorities.
|
||||
|
||||
The configuration priority of the module, when there is more
|
||||
than one unconfigured module on the peripheral bus, is
|
||||
determined implicitly by the order in which the module
|
||||
descriptions into the array. The modules that come first
|
||||
in the array are configured first.
|
||||
|
||||
init: this function is called, without arguments, during VM startup
|
||||
to initialize the device. For example, the initialization
|
||||
function for the ROM module will read the ROM image from
|
||||
disk and store them into the module status structure.
|
||||
|
||||
read: this function reads a nibble from the module. It receives the
|
||||
relative address of the nibble to be read. The read function
|
||||
can return an interrupt request for the CPU.
|
||||
|
||||
write: this function writes a nibble to the module. It receives the
|
||||
relative address and the value of the nibble to be written.
|
||||
The write function can return an interrupt request for the CPU.
|
||||
|
||||
r_config: this flag contains the configuration status of the module after
|
||||
a bus reset. If the after-reset configuration status is
|
||||
MOD_CONFIGURED, the module can never be unconfigured.
|
||||
|
||||
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
|
||||
configured automatically 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
|
||||
configured automatically after a bus reset.
|
||||
|
||||
map_flags: special map flags:
|
||||
MOD_MAP_FLAGS_ABS pass absolute addresses to module
|
||||
read/write functions
|
||||
|
||||
Notice that the current implementation requires that the index of
|
||||
the HDW registers in the mod_description table must be fixed
|
||||
and equal to MOD_HDW_INDEX... this is unfortunate.
|
||||
*/
|
||||
|
||||
typedef void (*ModInitFunction)(void);
|
||||
|
||||
typedef void (*ModSaveFunction)(void);
|
||||
|
||||
typedef Nibble (*ModReadFunction)(Address rel_addr);
|
||||
|
||||
typedef void (*ModWriteFunction)(Address rel_addr, Nibble data);
|
||||
|
||||
enum ModConfig
|
||||
{
|
||||
MOD_UNCONFIGURED,
|
||||
MOD_SIZE_CONFIGURED,
|
||||
MOD_CONFIGURED
|
||||
};
|
||||
|
||||
struct ModDescriptionEntry
|
||||
{
|
||||
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
|
||||
|
||||
This array contains an entry for each peripheral module connected
|
||||
to the peripheral bus of the Saturn CPU; the entry describes the
|
||||
dynamic mapping information of the module:
|
||||
|
||||
config: contains the current configuration status 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.
|
||||
|
||||
size: contains the current size of the address window of the module.
|
||||
It's valid only if the module is currently configured.
|
||||
*/
|
||||
struct ModMapInfoEntry
|
||||
{
|
||||
enum ModConfig config;
|
||||
Address abs_base_addr;
|
||||
Address size;
|
||||
};
|
||||
|
||||
typedef struct ModMapInfoEntry ModMapInfo[N_MOD];
|
||||
|
||||
|
||||
/*
|
||||
ModPageTable
|
||||
|
||||
This array contains an entry (of type ModPageTableEntry) for each 'page'
|
||||
(of size #40 nibbles) of the Saturn CPU physical address space. For
|
||||
each page, the following information is stored:
|
||||
|
||||
index: the index of the module that responds to the address range of
|
||||
the page in the ModDescription table.The special value
|
||||
MOD_NO_MOD_INDEX indicates that no module responds to the
|
||||
address range.
|
||||
|
||||
rel_base_addr: the relative base address of the page in the address
|
||||
space of the module that responds to the address range of
|
||||
the page, if any.
|
||||
|
||||
read, write: the read/write functions of the module that responds to the
|
||||
address range of the page, if any.
|
||||
|
||||
Relative address calculation for module access
|
||||
|
||||
The Saturn Physical Address (SPA) is divided into two portions:
|
||||
|
||||
* Page Index (PI): PI = (SPA & 0xFFFC0) >> 6
|
||||
* Offset (OFF): OFF = (SPA & 0x0003F)
|
||||
|
||||
The Page Index determines which module will respond to the module
|
||||
access operation. ModPageTable[PI] contains the following information:
|
||||
|
||||
* Relative Base Address (RBA)
|
||||
|
||||
The relative address (RA) therefore will be RA = RBA | OFF; then, the
|
||||
appropriate module access function, found again in ModPageTable[PI],
|
||||
is called.
|
||||
|
||||
*/
|
||||
struct ModPageTableEntry
|
||||
{
|
||||
int index;
|
||||
#define MOD_NO_MOD_INDEX (-1)
|
||||
|
||||
Address rel_base_addr;
|
||||
ModReadFunction read;
|
||||
ModWriteFunction write;
|
||||
};
|
||||
|
||||
typedef struct ModPageTableEntry ModPageTable[N_PAGE_TABLE_ENTRIES];
|
||||
|
||||
|
||||
/* struct ModCache (2.7)
|
||||
|
||||
This structure holds the caching information for module config/unconfig.
|
||||
|
||||
The .config field is an array of ModCacheConfigEntry, and contains
|
||||
the module configuration cache information. Each entry is a pair
|
||||
(tag, map_ptr). The map_ptr field, when non-null,
|
||||
points to the struct ModMap to be used when a module config command,
|
||||
with the given tag address as argument, is executed.
|
||||
|
||||
The .victim field points to the entry of .config to be used
|
||||
whenever a new fresh cache entry is needed after a cache miss.
|
||||
Currently, It is incremented by one at each replacement, thus
|
||||
implementing a very simple fifo replacement policy.
|
||||
|
||||
The .unconfig field is an array of struct ModMap pointers, and
|
||||
contains the module unconfiguration cache information.
|
||||
The .unconfig[i] array element, when non-null, points to the
|
||||
struct ModMap to be used when a module unconfig command, unconfiguring
|
||||
the i-th module, is executed.
|
||||
|
||||
The .config_point field is set if the struct ModMap is a point
|
||||
of the module configuration tree where a config was completed.
|
||||
It it used to walk back correctly when caching an unconfig.
|
||||
|
||||
This .ref_count is incremented by one when the struct ModMap
|
||||
is referenced by an unconfig link; it is used to avoid freeing
|
||||
referenced structures.
|
||||
|
||||
The .link field links all cached struct ModMap together.
|
||||
*/
|
||||
struct ModCacheTableEntry
|
||||
{
|
||||
Address tag;
|
||||
struct ModMap *map_ptr;
|
||||
};
|
||||
|
||||
struct ModCache
|
||||
{
|
||||
struct ModCacheTableEntry config[N_MOD_CACHE_ENTRIES];
|
||||
int victim;
|
||||
|
||||
struct ModMap *(unconfig[N_MOD]);
|
||||
|
||||
int config_point;
|
||||
int ref_count;
|
||||
|
||||
struct ModMap *link;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
struct ModMap
|
||||
|
||||
This structure contains all the mapping information about the peripheral
|
||||
modules of the Saturn CPU. Its components are:
|
||||
|
||||
map_info: this array describes the dynamic mapping information of
|
||||
each module connected to the Saturn peripheral bus.
|
||||
|
||||
page_table: this array describes the current layout of the address space
|
||||
of the Saturn CPU.
|
||||
|
||||
cache (2.7): this structure holds caching information used to speed up
|
||||
module config/unconfig instructions
|
||||
|
||||
*/
|
||||
struct ModMap
|
||||
{
|
||||
ModMapInfo map_info;
|
||||
ModPageTable page_table;
|
||||
struct ModCache cache;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
struct ModStatus
|
||||
|
||||
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
|
||||
to easily access the status of other devices.
|
||||
|
||||
struct ModHdw
|
||||
|
||||
This substructure contains the status of all peripheral devices controlled
|
||||
by the hdw module.
|
||||
|
||||
3.2: To support the HP49 hw configuration, the original ModStatus structure
|
||||
has been splitted in two:
|
||||
|
||||
- (new) struct ModStatus: contains configuration-independent status
|
||||
information (.hdw), and configuration-dependent accelerators (.hdw.accel).
|
||||
The overall layout of the structure is the same for all configurations,
|
||||
and it is publicily accessible.
|
||||
|
||||
- struct ModStatus_xx (corresponding to all fields of the original
|
||||
ModStatus structure except .hdw): contains the storage areas for
|
||||
ROM and RAM in configuration 'xx', and is private to the
|
||||
configuration-specific ROM/RAM emulation module.
|
||||
|
||||
*/
|
||||
struct ModHdw48Accel
|
||||
{
|
||||
XAddress bs_address; /* Bank Switcher ext. address */
|
||||
};
|
||||
|
||||
struct ModHdw49Accel
|
||||
{
|
||||
XAddress view[2]; /* Base of Flash views */
|
||||
};
|
||||
|
||||
struct ModHdw
|
||||
{
|
||||
Nibble hdw[N_HDW_SIZE]; /* HDW registers */
|
||||
|
||||
/* LCD driver */
|
||||
Address lcd_base_addr; /* LCD driver base address */
|
||||
int lcd_on; /* LCD driver enable flag */
|
||||
int lcd_contrast; /* LCD contrast value */
|
||||
int lcd_vlc; /* LCD vertical line count */
|
||||
int lcd_offset; /* LCD horizontal offset */
|
||||
int lcd_line_offset; /* LCD line offset */
|
||||
Address lcd_menu_addr; /* LCD menu base address */
|
||||
int lcd_ann; /* LCD annunciators status */
|
||||
|
||||
/* Timers */
|
||||
Nibble t1_ctrl; /* Timer 1 control */
|
||||
#define T1_CTRL_EXTRA 0x01
|
||||
#define T1_CTRL_INT 0x02
|
||||
#define T1_CTRL_WAKE 0x04
|
||||
#define T1_CTRL_SREQ 0x08
|
||||
|
||||
Nibble t2_ctrl; /* Timer 2 control */
|
||||
#define T2_CTRL_TRUN 0x01
|
||||
#define T2_CTRL_INT 0x02
|
||||
#define T2_CTRL_WAKE 0x04
|
||||
#define T2_CTRL_SREQ 0x08
|
||||
|
||||
Nibble t1_val; /* Timer 1 value */
|
||||
int32 t2_val; /* Timer 2 value */
|
||||
|
||||
/* 2.4: New member required to support Port emulation */
|
||||
Nibble card_status; /* Card status (hdw register 0x0F) */
|
||||
#define NCE3_CARD_PRESENT 0x01
|
||||
#define CE2_CARD_PRESENT 0x02
|
||||
#define NCE3_CARD_WE 0x04
|
||||
#define CE2_CARD_WE 0x08
|
||||
|
||||
/* 2.4: Hw configuration-specific members used as accelerators;
|
||||
accel_valid is non-zero if the accelerators are valid
|
||||
*/
|
||||
int accel_valid;
|
||||
|
||||
union
|
||||
{
|
||||
struct ModHdw48Accel a48;
|
||||
struct ModHdw49Accel a49;
|
||||
} accel;
|
||||
|
||||
/* 2.5: Serial port buffer registers */
|
||||
int8 serial_rbr;
|
||||
int8 serial_tbr;
|
||||
|
||||
/* Misc */
|
||||
int16 crc; /* CRC */
|
||||
};
|
||||
|
||||
struct ModStatus
|
||||
{
|
||||
struct ModHdw hdw; /* HDW status */
|
||||
};
|
||||
|
||||
struct ModStatus_48
|
||||
{
|
||||
Nibble rom[N_ROM_SIZE]; /* Internal ROM */
|
||||
Nibble ram[N_RAM_SIZE]; /* Internal RAM */
|
||||
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 */
|
||||
#ifdef N_PORT_2_BANK
|
||||
Nibble port_2[N_PORT_2_SIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ModStatus_49
|
||||
{
|
||||
Nibble flash[N_FLASH_SIZE_49]; /* Internal Flash ROM */
|
||||
Nibble ram[N_RAM_SIZE_49]; /* Internal RAM */
|
||||
Nibble *ce2, *nce3; /* ERAM bases */
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
extern struct ModStatus mod_status;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Chf condition codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define MOD_I_CALLED 101 /* Function %s called */
|
||||
#define MOD_I_INITIALIZING 102 /* Initializing module %s */
|
||||
#define MOD_I_RESETTING 103 /* Resetting module %s */
|
||||
#define MOD_I_GET_ID 106 /* ModGetID returning %x */
|
||||
#define MOD_I_CONFIG 107 /* ModConfig %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_NOT_IMPLEMENTED 110 /* Function %s not implemented */
|
||||
#define MOD_I_REVISION 111 /* Modules revision: %s */
|
||||
#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_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_CACHED_UNCONFIG 116 /* 2.7: Cached ModUnconfig completed */
|
||||
#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_MISS 119 /* 2.7: Late unconfig miss */
|
||||
#define MOD_W_BAD_CONFIG 202 /* Bad ModConfig %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_READ 205 /* Bad HdwRead %x */
|
||||
#define MOD_W_RESETTING_ALL 206 /* Resetting all modules */
|
||||
#define MOD_W_RAM_INIT 207 /* Can't initialize internal RAM */
|
||||
#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_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_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_E_BAD_READ 301 /* Read unmapped addr %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_RAM_SAVE 304 /* Can't save internal RAM 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_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_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_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_F_MAP_SAVE 401 /* Can't save mod_map information */
|
||||
#define MOD_F_ROM_INIT 402 /* Can't initialize internal ROM */
|
||||
#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_CHAIN_CORRUPTED 405 /* 2.7: ModMap chain corrupted */
|
||||
#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_NO_DESCRIPTION 408 /* 3.2: No module description */
|
||||
#define MOD_M_NOT_MAPPED 501 /* Address %x not mapped */
|
||||
#define MOD_M_MAPPED 502 /* Address %x mapped to %s:%x */
|
||||
#define MOD_M_MAP_TABLE_TITLE 503 /* */
|
||||
#define MOD_M_MAP_TABLE_ROW 504 /* %s %x %x %s */
|
||||
#define MOD_M_MAP_CONFIGURED 505 /* Configured */
|
||||
#define MOD_M_MAP_SZ_CONFIGURED 506 /* Size configured */
|
||||
#define MOD_M_MAP_UNCONFIGURED 507 /* Unconfigured */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Initialization */
|
||||
void ModSelectDescription(const char *hw);
|
||||
void ModRegisterDescription(ModDescription p);
|
||||
void ModInit(void);
|
||||
void ModSave(void);
|
||||
void ModReset(void);
|
||||
|
||||
/* Configuration */
|
||||
Address ModGetID(void);
|
||||
void ModConfig(Address config_info);
|
||||
void ModUnconfig(Address unconfig_info);
|
||||
|
||||
/* Read/Write */
|
||||
Nibble FetchNibble(Address addr);
|
||||
Nibble ReadNibble(Address addr);
|
||||
void WriteNibble(Address addr, Nibble datum);
|
||||
|
||||
/* Monitor */
|
||||
void ModMapCheck(Address addr, char ob[MOD_MAP_CHECK_OB_SIZE]);
|
||||
void ModMapTable(char ob[MOD_MAP_TABLE_OB_SIZE]);
|
103
modules.msf
Normal file
103
modules.msf
Normal file
|
@ -0,0 +1,103 @@
|
|||
$ .+
|
||||
$ .identifier : $Id: modules.msf,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
$ .context : SATURN, Saturn CPU / HP48 emulator
|
||||
$ .title : $RCSfile: modules.msf,v $
|
||||
$ .kind : Message catalog source
|
||||
$ .author : Ivan Cibrario B.
|
||||
$ .site : CSTV-CNR
|
||||
$ .creation : 13-Feb-1998
|
||||
$ .keywords : *
|
||||
$ .description :
|
||||
$ Message catalog source file for the peripheral modules emulator.
|
||||
$ .notes :
|
||||
$ . $Log: modules.msf,v $
|
||||
$ . Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
$ . Public release.
|
||||
$ .
|
||||
$ . Revision 3.8 2000/10/19 14:58:01 cibrario
|
||||
$ . Bug fix:
|
||||
$ . Removed lines with empty directives
|
||||
$ .
|
||||
$ Revision 3.3 2000/09/26 15:05:33 cibrario
|
||||
$ Revised to implement Flash ROM write access:
|
||||
$ - Added message 312
|
||||
$ .
|
||||
$ Revision 3.2 2000/09/22 14:07:04 cibrario
|
||||
$ Implemented preliminary support of HP49 hw architecture:
|
||||
$ - added new messages: 311, 407, 408
|
||||
$ .
|
||||
$ Revision 2.7 2000/09/19 11:13:12 cibrario
|
||||
$ Deeply revised to implement config/unconfig cache.
|
||||
$ .
|
||||
$ Revision 2.4 2000/09/12 15:48:57 cibrario
|
||||
$ Added messages 112, 113, 114, 211, 212, 306, 307, 308, 309, 310
|
||||
$ .
|
||||
$ Revision 2.1 2000/09/08 15:22:17 cibrario
|
||||
$ Updated message 209; added message 210. Both updates reflect the
|
||||
$ changes made to the keyboard emulation module in order to
|
||||
$ accommodate the new GUI.
|
||||
$ .
|
||||
$ Revision 1.1 1998/02/17 14:53:53 cibrario
|
||||
$ Initial revision
|
||||
$ .-
|
||||
|
||||
$set 1
|
||||
12 Modules
|
||||
|
||||
$set 12
|
||||
101 Function [%s] called
|
||||
102 Initializing module [%s]
|
||||
103 Resetting module [%s]
|
||||
106 ModGetID -> [%05X]
|
||||
107 CONFIG M[%s] A[%05X] S[%05X]
|
||||
108 UNCNFG M[%s] A[%05X] S[%05X]
|
||||
109 Saving module [%s]
|
||||
110 Function [%s] not implemented
|
||||
111 Modules emulator: [%s]
|
||||
112 Bank Switcher F/F set to A[%05X]
|
||||
113 Port 1 has been write-protected
|
||||
114 Port 2 has been write-protected
|
||||
115 >>> PerfCtr [%s]=[%d]
|
||||
116 Cached UNCNFG completed
|
||||
117 Cached CONFIG A[%05X] completed
|
||||
118 Late UNCNFG cache hit
|
||||
119 Late UNCNFG cache miss
|
||||
202 Bad ModConfig [%05X] ignored
|
||||
203 Bad ModUnconfig [%05X] ignored
|
||||
204 Bad HdwWrite A[%05X] N[%01X]
|
||||
205 Bad HdwRead A[%05X]
|
||||
206 Resetting all modules
|
||||
207 Can't initialize internal RAM from disk
|
||||
208 Can't initialize HDW from disk
|
||||
209 Bad key [%s] ignored
|
||||
210 Bad out_bit [%x] ignored
|
||||
211 Can't initialize Port 1 from disk
|
||||
212 Can't initialize Port 2 from disk
|
||||
213 Unable to find CONFIG cache victim; flushing cache
|
||||
301 Read from unmapped A[%05X]
|
||||
302 Write to unmapped A[%05X] N[%01X]
|
||||
303 Write into ROM A[%05X] D[%01X]
|
||||
304 Can't save internal RAM status to disk
|
||||
305 Can't save HDW status to disk
|
||||
306 Can't save Port 1 status to disk
|
||||
307 Write into CE1 A[%05X] D[%01X]
|
||||
308 Can't save Port 1 status to disk
|
||||
309 Read from NCE3 A[%05X] when Port 2 is not present
|
||||
310 Write into NCE3 A[%05X] D[%01X] when Port 2 is not present
|
||||
311 Hardware configuration [%s] not supported
|
||||
312 Can't save Flash ROM status to disk
|
||||
401 Can't save module mapping info
|
||||
402 Can't initialize internal ROM
|
||||
403 Dynamic allocation of ModMap failed
|
||||
404 Bad alloc_c [%d] after FlushCache()
|
||||
405 Cached struct ModMap chain corrupted; freeing unlinked entry
|
||||
406 Unable to find CONFIG cache victim after cache flush
|
||||
407 Allocation of ModStatus_xx failed ([%d]d bytes needed)
|
||||
408 ModInit() invoked without registering a ModDescription first
|
||||
501 A[%05X] -> *Not Mapped*
|
||||
502 A[%05X] -> M[%s] R[%05X]
|
||||
503 Device\t\t\tAddress\tSize\tStatus
|
||||
504 %s\t%05X\t%05X\t%s
|
||||
505 Configured
|
||||
506 Size_configured
|
||||
507 *Unconfigured*
|
379
monitor.c
Normal file
379
monitor.c
Normal file
|
@ -0,0 +1,379 @@
|
|||
/* -------------------------------------------------------------------------
|
||||
saturn - A poor-man's emulator of some HP calculators
|
||||
Copyright (C) 1998-2000 Ivan Cibrario Bertolotti
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the documentation of this program; if not, write to
|
||||
the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
For more information, please contact the author, preferably by email,
|
||||
at the following address:
|
||||
|
||||
Ivan Cibrario Bertolotti
|
||||
IRITI - National Research Council
|
||||
c/o IEN "Galileo Ferraris"
|
||||
Strada delle Cacce, 91
|
||||
10135 - Torino (ITALY)
|
||||
|
||||
email: cibrario@iriti.cnr.it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
/* +-+ */
|
||||
|
||||
/* .+
|
||||
|
||||
.identifier : $Id: monitor.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $
|
||||
.context : SATURN, Saturn CPU / HP48 emulator
|
||||
.title : $RCSfile: monitor.c,v $
|
||||
.kind : C source
|
||||
.author : Ivan Cibrario B.
|
||||
.site : CSTV-CNR
|
||||
.creation : 28-Jan-1998
|
||||
.keywords : *
|
||||
.description :
|
||||
This file implements a simple interactive monitor, useful during
|
||||
test & debug.
|
||||
|
||||
.include : config.h, machdep.h, cpu.h
|
||||
|
||||
.notes :
|
||||
$Log: monitor.c,v $
|
||||
Revision 4.1 2000/12/11 09:54:19 cibrario
|
||||
Public release.
|
||||
|
||||
Revision 3.10 2000/10/24 16:14:51 cibrario
|
||||
Added/Replaced GPL header
|
||||
|
||||
Revision 3.1 2000/09/20 13:52:42 cibrario
|
||||
Minor updates and fixes to avoid gcc compiler warnings on Solaris
|
||||
when -ansi -pedantic -Wall options are selected.
|
||||
|
||||
* Revision 1.1 1998/02/18 11:49:53 cibrario
|
||||
* Initial revision
|
||||
*
|
||||
|
||||
.- */
|
||||
|
||||
#ifndef lint
|
||||
static char rcs_id[] = "$Id: monitor.c,v 4.1 2000/12/11 09:54:19 cibrario Rel $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "machdep.h"
|
||||
#include "cpu.h"
|
||||
#include "modules.h"
|
||||
#include "args.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define CHF_MODULE_ID CPU_CHF_MODULE_ID
|
||||
#include <Chf.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macro & Data type definitions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define LINE_BUFFER_SIZE 512
|
||||
#define TOK_DELIMITERS " \t\n"
|
||||
#define ADDRESS_FMT "%x"
|
||||
#define COUNT_FMT "%d"
|
||||
#define PROMPT "> "
|
||||
#define OK 0
|
||||
#define FAILED 1
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private functions - Command line parse
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Read an Address from the command line */
|
||||
static int ReadHexAddress(Address *addr)
|
||||
{
|
||||
char *p = strtok((char *)NULL, TOK_DELIMITERS);
|
||||
return (p == (char *)NULL ||
|
||||
sscanf(p, ADDRESS_FMT, addr) != 1) ? FAILED : OK;
|
||||
}
|
||||
|
||||
/* Read a Nibble from the command line */
|
||||
static int ReadHexDatum(Nibble *n)
|
||||
{
|
||||
Address addr;
|
||||
int st;
|
||||
if((st = ReadHexAddress(&addr)) == OK) *n = (Nibble)addr;
|
||||
return st;
|
||||
}
|
||||
|
||||
/* Read a DECIMAL count from the command line */
|
||||
static int ReadCount(int *count)
|
||||
{
|
||||
char *p = strtok((char *)NULL, TOK_DELIMITERS);
|
||||
return (p == (char *)NULL || sscanf(p, COUNT_FMT, count) != 1 ||
|
||||
*count <= 0) ? FAILED : OK;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private functions - Command execution
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Run the emulator; this function exits normally only when an
|
||||
EmulatorIntRequest() is posted and satisfied
|
||||
*/
|
||||
static int run(void)
|
||||
{
|
||||
Emulator();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Set the debug level */
|
||||
static int debug(void)
|
||||
{
|
||||
Address addr;
|
||||
if(ReadHexAddress(&addr)) return FAILED;
|
||||
SetDebugLevel((int)addr);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Check the mapping of an Address and print */
|
||||
static int map_check(void)
|
||||
{
|
||||
Address addr;
|
||||
char ob[MOD_MAP_CHECK_OB_SIZE];
|
||||
if(ReadHexAddress(&addr)) return FAILED;
|
||||
ModMapCheck(addr, ob);
|
||||
puts(ob);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Print the current module map table */
|
||||
static int map(void)
|
||||
{
|
||||
char ob[MOD_MAP_TABLE_OB_SIZE];
|
||||
ModMapTable(ob);
|
||||
puts(ob);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Write nibbles into memory */
|
||||
static int w(void)
|
||||
{
|
||||
Address addr;
|
||||
Nibble n;
|
||||
if(ReadHexAddress(&addr)) return FAILED;
|
||||
while(ReadHexDatum(&n) == OK) WriteNibble(addr++, n);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Read nibbles from memory */
|
||||
static int r(void)
|
||||
{
|
||||
Address addr;
|
||||
int count;
|
||||
if(ReadHexAddress(&addr)) return FAILED;
|
||||
if(ReadCount(&count)) count=1;
|
||||
|
||||
while(count-->0)
|
||||
{
|
||||
printf("A_%05X\t%X\n", addr, (int)FetchNibble(addr));
|
||||
addr++;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Disassemble */
|
||||
static int d(void)
|
||||
{
|
||||
Address addr;
|
||||
int count;
|
||||
char ob[DISASSEMBLE_OB_SIZE];
|
||||
|
||||
if(ReadHexAddress(&addr)) return FAILED;
|
||||
if(ReadCount(&count)) count=1;
|
||||
|
||||
while(count-->0)
|
||||
{
|
||||
addr = Disassemble(addr, ob);
|
||||
puts(ob);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Print CPU status */
|
||||
static int cpu(void)
|
||||
{
|
||||
char ob[DUMP_CPU_STATUS_OB_SIZE];
|
||||
DumpCpuStatus(ob);
|
||||
puts(ob);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Reset CPU */
|
||||
static int reset(void)
|
||||
{
|
||||
CpuReset();
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Save & Exit */
|
||||
static int mon_exit(void)
|
||||
{
|
||||
ModSave();
|
||||
CpuSave();
|
||||
exit(EXIT_SUCCESS);
|
||||
return OK; /* 3.1: Keep compiler happy */
|
||||
}
|
||||
|
||||
/* Quit without saving */
|
||||
static int mon_quit(void)
|
||||
{
|
||||
exit(EXIT_SUCCESS);
|
||||
return OK; /* 3.1: Keep compiler happy */
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Command table
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
struct TEntry
|
||||
{
|
||||
char *name;
|
||||
char *desc;
|
||||
int (*function)(void);
|
||||
};
|
||||
|
||||
#define TableSize(t) (sizeof(t)/sizeof(struct TEntry))
|
||||
|
||||
/* Forward declaration for the Help funcion */
|
||||
static int Help(void);
|
||||
|
||||
static const struct TEntry table[] =
|
||||
{
|
||||
{ "help", "Print this information", Help },
|
||||
{ "run", "Run the emulator with current CPU status", run },
|
||||
{ "?", "<addr>, Check address mapping", map_check },
|
||||
{ "r", "<addr> [count], Read nibbles from memory", r },
|
||||
{ "w", "<addr> [n]..., Write nibbles into memory", w },
|
||||
{ "d", "<addr> [count], Disassemble starting from 'addr'", d },
|
||||
{ "cpu", "Print CPU status", cpu },
|
||||
{ "map", "Print the contents of the module map table", map },
|
||||
{ "debug", "Set the debugging level", debug },
|
||||
{ "reset", "Reset CPU", reset },
|
||||
{ "exit", "Save emulator state & exit", mon_exit },
|
||||
{ "quit", "Quit emulator WITHOUT saving its state", mon_quit }
|
||||
};
|
||||
|
||||
/* Invoke the command 'tk' and return a status code */
|
||||
static int InvokeCommand(char *tk)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<TableSize(table) && strcmp(tk, table[i].name); i++);
|
||||
return i==TableSize(table) ? FAILED : table[i].function();
|
||||
}
|
||||
|
||||
/* Print help information */
|
||||
static int Help(void)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<TableSize(table); i++)
|
||||
printf("%s\t\t%s\n", table[i].name, table[i].desc);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Handler for SIGINT during monitor execution */
|
||||
static void sigint_handler(int s)
|
||||
{
|
||||
EmulatorIntRequest();
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Public functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* .+
|
||||
|
||||
.title : Monitor
|
||||
.kind : C function
|
||||
.creation : 18-Feb-1998
|
||||
.description :
|
||||
This function implements a very simple interactive monitor.
|
||||
|
||||
.call :
|
||||
Monitor();
|
||||
.input :
|
||||
void
|
||||
.output :
|
||||
void
|
||||
.status_codes :
|
||||
CPU_W_BAD_MONITOR_CMD
|
||||
From lower level modules
|
||||
.notes :
|
||||
1.1, 18-Feb-1998, creation
|
||||
|
||||
.- */
|
||||
void Monitor(void)
|
||||
{
|
||||
char cmd[LINE_BUFFER_SIZE];
|
||||
char old_cmd[LINE_BUFFER_SIZE];
|
||||
char *tk;
|
||||
|
||||
/* Clear old_cmd buffer */
|
||||
strcpy(old_cmd, "");
|
||||
|
||||
/* Establish SIGINT handler */
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
/* Infinite loop; it's exited only when a condition is signalled */
|
||||
while(1)
|
||||
{
|
||||
/* Write prompt */
|
||||
fputs(PROMPT, stdout);
|
||||
fflush(stdout);
|
||||
|
||||
if(fgets(cmd, LINE_BUFFER_SIZE, stdin) == (char *)NULL ||
|
||||
(tk = strtok(cmd, TOK_DELIMITERS)) == (char *)NULL)
|
||||
{
|
||||
/* New command empty; try old command */
|
||||
if((tk = strtok(old_cmd, TOK_DELIMITERS)) != (char *)NULL)
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue