📄 borland.c
字号:
#include "includes.h"
/*
* Some of the following procedures have to do with floating point error
* handling. This type of error handling is not well-specified by
* C language standards and is strictly Borland-dependent.
*
* Many Borland compiler dependencies are collected together in this
* module. See also module RTEXEC.C for other host dependencies related
* to the real-time executive, and module SERIAL.C for host dependencies
* related to interrupt-dependent serial communications.
*/
/* Define some Borland-type exception structures. */
#ifdef __cplusplus /* Accommodate a C/C++ difference. */
typedef void (*fptr)(int);
#else
typedef void (*fptr)();
#endif
typedef struct /* Floating-point error structure. */
{
int FPEtype;
char *string ;
} FLT_ERR ;
/* ASCII interpretations of floating-point error codes. */
static FLT_ERR _fpe_msg[] =
{
{FPE_INVALID,"Invalid operation/Domain error"},
{FPE_ZERODIVIDE,"Floating divide by zero"},
{FPE_OVERFLOW,"Overflow"},
{FPE_UNDERFLOW,"Underflow"},
{FPE_INEXACT,"Partial loss of precision"},
{FPE_INTDIV0,"Integer divide by zero"},
};
/* ASCII interpretations of runtime math library error codes. */
static char *whyS [] =
{
"argument domain error",
"argument singularity ",
"overflow range error ",
"underflow range error",
"total loss of significance",
"partial loss of significance"
};
/* Borland method for setting the main program's initial stack size.
The GPS software designer may want to decrease the stack size when
stack requirements are finalized. */
extern unsigned _stklen=30000;
/****************************************************************************
* Function: int ControlBreakHandler(void)
*
* Receives control when the user presses CTL-BREAK. This prevents a crash-out
* which would not restore the PC's state. The longjmp restores the task state
* to what existed in task MAIN at the call to setjmp(). Execution resumes at
* that point and the program terminates.
*
* Input: None.
*
* Output: None.
*
* Return Value: TRUE.
****************************************************************************/
int ControlBreakHandler(void)
{
longjmp(cbrkjmp,1);
return(TRUE);
}
/****************************************************************************
* Function: void SuppressCursor(void)
*
* Saves the PC's current cursor type setting, then turns it off. A blinking
* cursor is inappropriate for displays which are updated in a random access
* fashion.
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void SuppressCursor(void)
{
_AH=3; /* Save old cursor shape. */
_BH=0;
geninterrupt(0x10);
oldcursorshape=_CX;
_AH=1; /* Suppress blinking cursor. */
_CH=0x20;
geninterrupt(0x10);
}
/****************************************************************************
* Function: void RestoreCursor(void)
*
* Restores the previously saved PC cursor type setting.
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void RestoreCursor(void)
{
_AH=1; /* Restore old cursor shape. */
_CX=oldcursorshape;
geninterrupt(0x10);
}
/****************************************************************************
* Function: void Checkpoint(char *ProcName, unsigned UserCheckpoint)
*
* Record a checkpoint to indicate that a task did something. The GPS
* software designer may call this routine from a task (but not from an ISR)
* to set a procedure name and a user checkpoint number (1-65535) in
* CurrentTask's TCB. In the event of a floating point or math library runtime
* error, or a termination by a call to the routine DumpCheckpoints, the
* following information is reported to stderr before program termination:
*
* 1) Current task name.
*
* 2) Procedure name which has been previously set in the TCB
* by this routine.
*
* 3) The nature of the error.
*
* 4) Previously reported checkpoints of this and other tasks
* immediately prior to the error.
*
* This facility should be used during software development. For production,
* this routine can be stubbed out.
*
* Input: ProcName - the procedure name.
* UserCheckpoint - the checkpoint number.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void Checkpoint(char *ProcName, unsigned UserCheckpoint)
{
int i;
CKPTstruc *CK;
tcbstruc *T;
PROTECT++;
T = &TCB[CurrentTask];
CK = &CKPT[NextCKPT];
NextCKPT = (NextCKPT+1) % NCKPT;
/* Store new checkpoint information in CurrentTask's TCB. */
T->UserCheckpoint = UserCheckpoint;
for(i=0;i<15;i++)
{
if((T->ProcName[i] = ProcName[i])==0)
break;
}
T->ProcName[15] = 0; /* To ensure string termination. */
/* Store new checkpoint information in the checkpoint log. */
CK->UserCheckpoint = UserCheckpoint;
CK->TaskNum = CurrentTask;
strcpy(CK->ProcName,T->ProcName);
if(_SS == T->STRTSS) /* Monitor task's stack usage. */
if(_SP < T->MinSP)
T->MinSP = _SP;
PROTECT--;
}
/****************************************************************************
* Function: void TCBComment(char *CommentString)
*
* Record a comment regarding something that a task did. The GPS designer may
* call this routine to put a comment (maximum 15 characters) in CurrentTask's
* TCB. The F9 Task Statuses display shows this comment. It is useful to
* determine whether a task has in fact taken some action of interest.
*
* Input: CommentString - the comment string.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void TCBComment(char *CommentString)
{
int i;
tcbstruc *T;
PROTECT++;
T = &TCB[CurrentTask];
for(i=0;i<15;i++)
if((T->Comment[i] = CommentString[i])==0)
break;
T->Comment[15] = 0x00; /* To ensure string termination. */
PROTECT--;
}
/****************************************************************************
* Function: void DumpCheckpoints(void)
*
* Dump a log of saved checkpoints and terminate execution. The GPS designer
* may call this routine to report the sequence of events that occurred
* immediately prior to an error condition.
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void DumpCheckpoints(void)
{
int i;
CKPTstruc *CK;
PROTECT++;
fprintf(stderr,"*** Current task at time of abort: %s\n",
TCB[CurrentTask].TNAME);
fprintf(stderr,"*** Current checkpoints, by task:\n");
for(i=0;i<100;i++)
{
fprintf(stderr,"*** Task: %10s Proc: %16s User checkpoint: %d\n",
TCB[i].TNAME,TCB[i].ProcName,TCB[i].UserCheckpoint);
if(stricmp(TCB[i].TNAME,"MAIN")==0)
break;
}
fprintf(stderr,"*** Checkpoint log (earliest first, latest last):\n");
for(i=0;i<NCKPT;i++)
{
CK = &CKPT[(NextCKPT+i)%NCKPT];
if(CK->UserCheckpoint==0)
continue;
fprintf(stderr,"*** Task: %10s Proc: %16s User checkpoint: %d\n",
TCB[CK->TaskNum].TNAME,CK->ProcName,CK->UserCheckpoint);
}
QuitGpsBuilderWithError();
}
/****************************************************************************
* void FPError(int code, int subcode)
*
* Borland floating point coprocessor/emulator exception handler. Every
* floating point exception is fatal. In a numerically correct application,
* such errors arise mainly for three reasons:
*
* 1) Memory corruption due to stack overflow (try to maintain a
* comfortable margin in the task stacks).
*
* 2) Shared floating point variables which are accessed without
* protection against a task switch (PROTECT++/PROTECT--).
*
* 3) Memory corruption by an out-of-bounds subscript or pointer.
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
#pragma warn -par
void FPError(int code, int subcode)
{
int i;
PROTECT++;
_fpreset(); /* Reset the coprocessor/ */
fprintf(stderr,"\n*** Floating point coprocessor/emulator error.\n");
for(i=0;i<6;i++)
{
if(_fpe_msg[i].FPEtype==subcode)
fprintf(stderr, "*** Error type: %s\n",_fpe_msg[i].string);
}
DumpCheckpoints();
}
#pragma warn .par
/****************************************************************************
* Function: void SetFPErrorHandler(void)
*
* This sets the Borland floating point exception handler to FPERROR, which is
* GPS Builder's own error handling. The default error handling is totally
* inadequate for most applications, since it gives no indication of where the
* error occurred.
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void SetFPErrorHandler(void)
{
signal(SIGFPE, (fptr)FPError);
}
/****************************************************************************
* Function: int _FARFUNC matherr(struct exception *e)
*
* Borland runtime math library exception handler for copiler version 3.1.
* Underflows are fixed up by replacing the result with 0.0, which is
* reasonable under most cicumstances. Total loss of precision is ignored,
* which is less reasonable, but the GPS designer should not allow this
* situation to occur in the first place. All other errors are considered
* fatal. The checkpoint log is printed and execution is terminated.
*
* Input: e - the exception structure.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
#if (CompilerVersion==31)
int _FARFUNC matherr(struct exception *e)
{
PROTECT++;
if(e->type == UNDERFLOW) /* Flush underflow to 0. */
{
e->retval = 0;
PROTECT--;
return(TRUE);
}
if(e->type == TLOSS) /* Total loss of precision, ignore the problem. */
{
PROTECT--;
return(TRUE);
}
/* All other errors are fatal. */
fprintf(stderr,"\n*** Math library runtime error.\n");
fprintf (stderr,"*** %s (%8g,%8g): %s\n",
e->name, e->arg1, e->arg2, whyS [e->type - 1]);
DumpCheckpoints();
return(FALSE);
}
#endif
/****************************************************************************
* Function: int _FARFUNC _matherr(struct exception *e)
*
* Borland runtime math library exception handler for copiler version 4.0.
* Underflows are fixed up by replacing the result with 0.0, which is
* reasonable under most cicumstances. Total loss of precision is ignored,
* which is less reasonable, but the GPS designer should not allow this
* situation to occur in the first place. All other errors are considered
* fatal. The checkpoint log is printed and execution is terminated.
*
* Input: e - the exception structure.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
#if (CompilerVersion>31)
int _FARFUNC _matherr(struct exception *e)
{
PROTECT++;
if(e->type == UNDERFLOW) /* Flush underflow to 0. */
{
e->retval = 0;
PROTECT--;
return(TRUE);
}
if(e->type == TLOSS) /* Total loss of precision, ignore the problem. */
{
PROTECT--;
return(TRUE);
}
/* All other errors are fatal. */
fprintf(stderr,"\n*** Math library runtime error.\n");
fprintf (stderr,"*** %s (%8g,%8g): %s\n",
e->name, e->arg1, e->arg2, whyS [e->type - 1]);
DumpCheckpoints();
return(FALSE);
}
#endif
/****************************************************************************
* Function: void ClearScreen(void)
*
* Clears the scrren by calling the Borland specific function clscr().
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void ClearScreen(void)
{
clrscr();
}
/****************************************************************************
* Function: void InstallControlBreakHandler(void)
*
* Installs a handler for Ctrl-C and Ctrl-Break by calling the Borland
* specific function ctrlbrk().
*
* Input: None.
*
* Output: None.
*
* Return Value: None.
****************************************************************************/
void InstallControlBreakHandler(void)
{
ctrlbrk(ControlBreakHandler);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -