meta,
C++
14 Methoden:
/* private: */ void ExecUt :: read_env
/* private: */ void ExecUt :: show // hidden by macros
|
/* public: */ BOOL ExecUt :: ok_At
/* public: */ void ExecUt :: NewCounters
/* public: */ void ExecUt :: PutCounters
/* public: */ void ExecUt :: count_init
/* public: */ void ExecUt :: count_show
#define static
#include exec_ut.h : cpp
#include exec_ut.c1 : cpp
#undef BB
#undef BBStr
#undef bb
#undef bbStr
#define BB
#define BBStr( x,y,z ) ;
#define bb
#define bbStr( x,y,z ) ;
#ifndef procNestOn
#undef LB_
#undef LE_
#undef LE_ret
#undef ret
#undef ret_
#undef __
#undef ___
#define LB_( x ) {
#define LE_ }
#define ret_ return ;
#define LE_ret( x ) return( x ); }
#define ret( x ) return( x );
#define __
#define ___
#endif
#include procnestoff
#ifdef prot_
#include btree.h : cpp
#endif
#define m_exut
#undef getenv
#undef fopen
#define retError( e,m ) { errno = e ; set_errDescr( m ); return ; }
#include toscreen.h : cpp
#ifdef __WINDOWS__
#include <afxwin.h>
#include ewinapp.h
#include <stdarg.h>
int _cdecl printf( const char* szFmt, ... )
{
#ifndef __OPTIMIZED__
va_list l;
va_start(l, szFmt);
char szT[512];
vsprintf(szT, szFmt, l);
TRACE("printf: %s\n", szT);
#endif
return( 0 );
}
#endif
/* public: */ BOOL ExecUt :: atErr
// -----------------------------------------------------------------------------
(
char * mess
, char * erro
)
LB_("ExecUt.atErr")
to_( mess, '[' ) mess += 1 ; skip_space( mess );
LE_ret( At( mess, erro ) )
/* public: */ void ExecUt :: TMPName
/* -----------------------------------------------------------------------------
create path name = TMPDir/tmpNr
-----------------------------------------------------------------------------
*/ (
path & name
)
LB_("ExecUt.TMPName")
sprintf( name, "%s/%i", TMPDir, ++TMPNr );
if ( TMPNr == 1 ) S_ "mkdir %s", TMPDir _Do
LE_
/* public: */ BOOL ExecUt :: ViewStdout(
/* -----------------------------------------------------------------------------
-----------------------------------------------------------------------------
*/ )
{
if no_this return( false );
fflush( stout ); path f ; get_std_file( f, ".sto" );
#ifdef __WINDOWS__
WinExec( f, SW_SHOWNORMAL);
#else
S_ "type %s", f _Do
#endif
return( true );
}
/* public: */ BOOL ExecUt :: ViewStderr(
/* -----------------------------------------------------------------------------
-----------------------------------------------------------------------------
*/ )
{
if no_this return( false );
fflush( sterr ); path f ; get_std_file( f, ".err" );
#ifdef __WINDOWS__
WinExec( f, SW_SHOWNORMAL);
#else
S_ "type %s", f _Do
#endif
return( true );
}
/* public: */ void ExecUt :: trace_yourself(
/* -----------------------------------------------------------------------------
Diese Methode dient dem Nachweis:
delete( exut ) macht den this pointer n i c h t zu 0 ,
Folgender Code etwa druckt 3 Mal dieselbe Adresse:
ExecUt * xxx = new ExecUt( "" );
xxx -> trace_yourself(); printf( "xxx = %p\n", exut ); delete( xxx );
xxx -> trace_yourself();
-----------------------------------------------------------------------------
*/ )
{
printf( "this( ExecUt ) = %p\n", this );
}
/* public: */ ExecUt :: ~ExecUt
/* -----------------------------------------------------------------------------
Der Aufrufer garantiert: -
- sein Auftrag: Close stout und sterr, dann gebe auf dem Heap
allokierten Speicher frei.
Die Funktion garantiert: -
----------------------------------------------------------------------------- ::
*/ (
)
{
// deadlock if temp dir too full !!!!
if no_this NO_this
#ifdef __TESTCOVER__
{
PutCounters();
}
#endif
#ifndef __OPTIMIZED__
ok_rem_heap( 1 );
#endif
#ifdef __DOS_OR_QUICK_WIN__
#ifdef __QUICK_WIN__
printf( "\n\n ok - f e r t i g " );
#else
printf( "ok" );
#endif
#else
// zeige Pop Up Window mit Erfolgsmeldung (oder ...)
#endif
#ifdef __SPU__
#undef fclose
#endif
#define f_close( x ) { fflush( x ); fclose( x ); }
if ( stout ) f_close( stout )
if ( sterr && sterr != stout ) f_close( sterr )
if ( ef && ef != stout && ef != sterr ) f_close( ef )
#ifndef __MAXIMAL_TRACE__
if ( * err_file && no_error ) unlink( err_file );
#endif
#ifdef __SPU__
#endif
destroyed = stopped = true ;
}
/* private: */ void ExecUt :: read_env
/* -----------------------------------------------------------------------------
read environment to str
-----------------------------------------------------------------------------
*/ (
char * str // out: value
, char * evar // in : of environment variable
)
{
if no_this NO_this
if ( getenv( evar ) ) strcpy( str, getenv( evar ) ); else *str = 0 ;
}
/* private: */ void ExecUt :: do_Exit
/* -----------------------------------------------------------------------------
fatal error that cannot be handled by exut
-----------------------------------------------------------------------------
*/ (
int en // in: an EN_... defined in en.h
)
{
if no_this NO_this
#ifdef __WINDOWS__
char mess[ 300 ] ; sprintf( mess,
"Function Call %i detected an implementation e r r o r \n"
"Documentation not possible\n", call_nr );
PToScreen ps ; ps.message( mess ) ;
EWinApp * pApp = ( EWinApp * ) AfxGetApp();
if ( pApp ) pApp -> Exit() ; else AfxAbort() ;
#else
// printf( "\nS y s t e m E r r o r : %s\n\n", semantics( en ) );
printf( "\nS y s t e m E r r o r in %s.exe: %s\n\n"
, this_exe, semantics( en ) );
exit( en );
#endif
}
/* public: */ void ExecUt :: get_std_file
/* -----------------------------------------------------------------------------
Der Aufrufer garantiert: 'fn zeigt auf ein char[n] mit L_path <= n
- sein Auftrag: Schreibe dort hinein den Pfad zur vom Prozess erzeugten
Datei *.ext ( 'ext = .err, .ste, oder .sto ).
Die Funktion garantiert: -
-----------------------------------------------------------------------------
*/ (
char * fn // out: the path
, char * ext // in : extension .err, .ste, or .sto
)
{
strcpy( fn, std_file );
if ( ! ext ) strcat( fn, ".err" );
esif ( is( ext, ".sto", 4 ) && stout == ef ) strcat( fn, ".err" );
esif ( is( ext, ".ste", 4 ) && sterr == ef ) strcat( fn, ".err" );
esif ( is( ext, ".ste", 4 ) ) strcat( fn, ".ste" );
esif ( is( ext, ".sto", 4 ) ) strcat( fn, ".sto" );
else strcat( fn, ".err" );
}
/* public: */ void ExecUt :: throw_error // hidden by macros
/* -----------------------------------------------------------------------------
report an unexpected error
-----------------------------------------------------------------------------
*/ (
int Line
, char * File
)
{
if ( ! *errA ) strcpy( errA, "faulty code" );
printf( "\n\nfatal error %i.%s, call_nr = %u, errno = %i, %s\n[\n\n%s\n\n]"
, Line, File, call_nr, errno, checkPoint, errA );
checkPoint = "exec_ut :: throw_error" ;
// if ( ! *errA ) strcpy( errA, "faulty code" );
//
*errA = 0 ;
throw errMess ;
}
/* public: */ void ExecUt :: set_errDescr // hidden by macros
/* -----------------------------------------------------------------------------
describe an error
-----------------------------------------------------------------------------
*/ (
char * descr // further description of the error
)
{
if no_this NO_this
if ( ! descr ) descr = ( char * )semantics( errno );
char * x1 = errDescr ;
char * x2 = errDescr + L_err - 1 ;
while ( *descr && x1 < x2 ) *x1++ = *descr++ ; *x1 = 0 ;
// Do n o t use strcpy() here - strcpy() as well as strlen() cause
// desaster if 'descr is not NULL terminated.
}
/* public: */ BOOL ExecUt :: IsValid(
/* -----------------------------------------------------------------------------
return BOOL( 'this object exists and is ok' )
-----------------------------------------------------------------------------
*/ )
{
return( ! stopped );
}
/* public: */ ExecUt :: ExecUt
/* -----------------------------------------------------------------------------
Initialize Mechanismus zur Beobachtung des Programmablaufs
-----------------------------------------------------------------------------
*/ (
char * app_name // DOS Name of application
)
{
#undef system
rRest = 0 ;
sprintf( errme, "\n\nerror --> " ); errst = errme + 12 ;
stack_shown = 0 ;
counters = "1tc\\counters" ; inproc = "??" ;
#ifdef __TESTCOVER__
{
int k = 0 ; while ( k < L_wp ) wp[ k++ ] = 0 ;
}
#endif
suggest_trace = step_TR = 100 ; // S_ "del *.err" _Do ABSTURZ !!!
strcpy( errDescr, "no exut object" );
sto1 = sto = 0 ; stn = -1 ; app_errors = 0 ;
stout = sterr = 0 ;
destroyed = stopped = no_error = true ;
at1 = at = maxdepth ;
char * c ;
c = getenv( "SHOW_AT" ); show_at = ( c )? atoi(c) : INT_MAX ;
c = getenv( "FROM_PROC" ); trace_from = ( c )? atoi(c) : INT_MAX ;
#ifndef __OPTIMIZED__
{
FILE * f = fopen( "xtrace", "r" );
if ( f )
then {
fscanf( f, "%i", &trace_from ); fclose( f );
}
else trace_from = INT_MAX ;
}
#endif
if ( show_at <= 0 ) show_at = 1 ; // darf n i e <= 0 sein !!!
if ( show_at < trace_from ) trace_from = show_at - 200 ;
comm = comment ; comm_end = comment + L_comment ;
exit_type = "ret To" ;
int j = 0 ;
for ( j = 0 ; j <= maxdepth ; j++ ) // initialize for safety
{
stack[ j ].proc = "" ;
stack[ j ].file = "" ;
stack[ j ].comm = "" ;
}
to_f = ef = stderr ; to_stack = true ;
// to_f = ef = stdout ; to_stack = true ; // nicht immer gut !!!
c = getenv( "TRACE_DIR" );
if ( c )
then strcpy( err_file, getenv( "trace_DIR" ) );
else strcpy( err_file, "c:\\tmp" );
{
// check if TRACE_DIR exists:
struct stat st ; stat( err_file, &st );
if ( ! ( st.st_mode & S_IFDIR ))
{
path comm ; sprintf( comm, "mkdir %s", err_file ); system( comm );
if ( errno )
{
strcpy( err_file, "." );
}
}
}
if ( *err_file ) strcat( err_file, "\\" ); // else current directory
#ifdef __SPU__
path e_bat ; sprintf( e_bat, "%se.bat", err_file );
#endif
if ( *app_name )
then {
strcpy( ccc, app_name ); ccc[5] = 0 ;
for ( j = 0 ; j < 5 ; j++ ) if ( ccc[j] == '.' ) ccc[j] = 0 ;
}
else strcpy( ccc, "app" );
strcat( err_file, ccc ); strcat( err_file, "_1.err" );
char * ext = err_file + strlen( err_file ) - 5 ; int n = 100 ;
strcpy( TMPDir, err_file ); TMPDir_e = TMPDir + strlen( TMPDir ) - 4 ;
*TMPDir_e = 0 ; TMPNr = 0 ;
while ( ef == stderr )
{
S_ "echo x > x.err " _Do // to avoid 'Could not find *.err':
S_ "del *.err > NUL" _Do
struct stat B ; ok ; stat( (char *)err_file, &B );
if no_such_file
then {
#ifdef __OPTIMIZED__
ef = stdout ;
// ef = fopen( err_file , "w+" );
//
#else
ef = stdout ;
#endif
#ifdef __WINDOWS__
if ( ! ef ) retError( EN_cannot_create_trace_file, 0 );
#else
if ( ! ef ) return ;
#endif
}
else {
if ( 220 <= n ) ef = stdout ;
#ifdef __WINDOWS__
if ( errno ) retError( errno , 0 );
if ( n == 99 ) retError( EN_too_many_error_files, 0 );
#else
if ( errno || 220 <= n )
{
printf( "\nerror: Too many files in TRACE_DIR,"
" cannot create %s", err_file );
exit( 1 );
}
#endif
sprintf( ext, "%i.err", ( n-50 ) % 100 );
unlink( err_file ); ok
sprintf( ext, "%i.err", ++n % 100 );
}
}
strcpy( std_file, err_file ); j = strlen( err_file ) - 4 ;
#ifdef __CREATE_STO__
memcpy( std_file + j, ".sto", 5 ); stout = fopen( std_file, "w+" );
#else
stout = ef ;
#endif
#ifdef __CREATE_STE__
memcpy( std_file + j, ".ste", 5 ); sterr = fopen( std_file, "w+" );
#else
sterr = ef ;
#endif
std_file[ j ] = 0 ;
to_f = ef ; also_to_f = 0 ; to_stack = true ; errno = 0 ;
// fprintf( ef, "trace_from = %ld\n", trace_from );
#ifdef __WINDOWS__
if ( errno ) retError( errno, 0 );
#else
if ( errno ) return ;
c = getenv( "TRACE_TO_STDOUT" );
if ( c ) { if ( *c == '1' ) ef = stdout ; }
#endif
std_file[ j ] = 0 ;
to_f = ef ; also_to_f = 0 ; to_stack = true ; errno = 0 ;
// fprintf( ef, "trace_from = %ld\n", trace_from );
/*
#ifdef __SPU__
#undef fclose
FILE * f = fopen( e_bat, "w+" );
fprintf( f, "vi %s", err_file ); fclose( f ); errno = 0 ;
#define system safe_ut.ok_system
#define fclose safe_ut.ok_close
#endif
*/
destroyed = stopped = false ;
if ( ef == stdout ) strcpy( err_file, "stdout" );
// printf( "\nok Constructor exec_ut, errno = %i\n", errno );
}
/* public: */ char * ExecUt :: get_err_path
/* -----------------------------------------------------------------------------
return pointer to name of *.err, *.sto, *.ste without extension
-----------------------------------------------------------------------------
*/ (
)
{
if no_this return( "" ); else return( std_file );
}
/* public: */ void ExecUt :: enter_f // hidden by macros
/* -----------------------------------------------------------------------------
push function call
-----------------------------------------------------------------------------
*/ (
char * proc // name of proc
, char * file // name of file where the proc is defined
, int line //
)
{
//
// , proc, line, file, errno, call_nr );
int merrno = errno ;
if no_this { printf( "\n?--> %s", proc ); NO_this }
if ( call_nr % 512 == 0 )
then {
FILE * f = fopen( "c:\\trace_.bat", "w+" ); ok // muss sein
fprintf( f, "call trace %i 1 \n", call_nr - 600 );
fclose( f );
}
#define proc_loop stack[ 0 ].call_nr
if ( at )
then {
at1 = --at ; comm[0] = 0 ;
/*
if ( stack[ at ].proc == proc ) proc_loop++ ; else proc_loop = 0 ;
if ( proc_loop % 2000 == 0 )
{
printf( "proc_loop ??: %s %s.%i \n", proc, file, line );
}
*/
stack[ at ].comm = ++comm ;
stack[ at ].call_nr = ++call_nr ;
stack[ at ].file = file ;
stack[ at ].line = line ;
stack[ at ].proc = proc ;
stack[ at ].errn = merrno ;
stack[ at ].recover = 0 ; // no recovery from SysError
}
else {
stack[1].errn = merrno = EN_stack_too_deep ; at += 8 ; exit(1);
}
#ifdef __MAXIMAL_TRACE__
if ( sto != sto1 ) errno = EN_storage_corrupted ;
if ( trace_from < call_nr )
{
/*
if ( call_nr < trace_from + 50 )
for ( int k = maxdepth - 1 ; at < k ; k-- )
{
fprintf( ef, " %30i %s \n", stack[ k ].line, stack[ k ].proc );
}
*/
fprintf( ef, "--> %2i %s, call %i\n", maxdepth-at, proc, call_nr );
}
#endif
if ( merrno ) { errno = merrno ; show(1); }
if ( suggest_trace < call_nr )
{
suggest_trace = call_nr + step_TR ;
S_ "echo trace %li 1 %li > xtrace.bat", call_nr - step_TR
, call_nr - step_TR _Do
}
#undef proc_loop
//
}
/* public: */ BOOL ExecUt :: at_E // hidden by macros
/* -----------------------------------------------------------------------------
trace errno at watch point
-----------------------------------------------------------------------------
*/ (
int line
)
{
if no_this return( EN_ok );
stack[ at ].line = line ;
stack[ at ].errn = errno ; return( errno );
}
/* private: */ void ExecUt :: message_fErr
/* -----------------------------------------------------------------------------
-----------------------------------------------------------------------------
*/ (
char * mess
)
{
fprintf( ef, mess );
#ifdef __WINDOWS__
#ifdef __MFC__
TRACE( mess ); // into Debugger Window or nowhere
#endif
#else
if ( stderr != ef )
{
fprintf( stderr, "%sdescribed in %s\n%s", mess, err_file
, stack[ at ].comm );
}
#endif
}
/* public: */ void ExecUt :: AnotherAppErr
/* -----------------------------------------------------------------------------
-----------------------------------------------------------------------------
*/ (
char * mess
)
{
app_errors ++ ;
#ifdef __WINDOWS__
#ifdef __MFC__
PToScreen ps ; ps.message( mess ) ;
#endif
#else
printf( "\nERROR: %s\n", mess );
#endif
fprintf( sterr, "\nERROR: %s\n", mess );
}
/* private: */ void ExecUt :: fatal_error_at // hidden by macros
/* -----------------------------------------------------------------------------
tell the system you detected a fatal error
-----------------------------------------------------------------------------
*/ (
int line
)
{
fatal_error_at( stack[ at ].file, line );
}
/* public: */ void ExecUt :: fatal_error_at
/* -----------------------------------------------------------------------------
tell the system you detected a fatal error
-----------------------------------------------------------------------------
*/ (
char * file
, int line
)
{
if no_this NO_this
// ?errS "fatal error" );
no_error = false ;
printf( "\nfatal error: Last checkpoint: %s", checkPoint );
if ( ! errno ) errno = EN_syserror ;
errNo = errno ;
stack[ at ].line = line ; putErr( errno, file, line ); exit(1);
// unlink( "stopAtErr" ) ok exit(1);
show(2); stop( -1 );
}
/* public: */ void ExecUt :: to_trace // hidden by macros
/* -----------------------------------------------------------------------------
concatenate str to stack[ at ].comm
-----------------------------------------------------------------------------
*/ (
char * str
)
{
if no_this NO_this
if ( ! str ) str = "( null )" ;
int s = strlen( str );
if ( comm_end <= comm + s ) comm = comment + 1 ;
memcpy( comm, str, s );
comm += s ;
fprintf( ef, "%s", str );
}
/* public: */ void ExecUt :: set_errno // hidden by macros
/* -----------------------------------------------------------------------------
set errno a n d description of error
err_descr is pointing to some string produced via 'sprintf(...)' - it may
contain arbitrarily long comment describing the situation in which the error
was found.
-----------------------------------------------------------------------------
*/ (
int err_code
, char * err_descr
)
{
if no_this NO_this
to_trace( err_descr ) ; errno = err_code ;
}
/* public: */ void ExecUt :: end_f // hidden by macros
/* -----------------------------------------------------------------------------
pop function call (exit at 'LE_')
-----------------------------------------------------------------------------
*/ (
int line // of return
)
{
if no_this NO_this
if ( errno ) fatal_error_at( stack[ at ].file, line );
#ifndef __OPTIMIZED__
exit_type = "end " ; exit_f( line ); exit_type = "ret to " ;
#endif
}
/* public: */ void ExecUt :: at_return // hidden by macros
/* -----------------------------------------------------------------------------
pop function call (exit at a 'return' point)
-----------------------------------------------------------------------------
*/ (
int line // of return
)
{
if no_this NO_this
if ( errno ) fatal_error_at( stack[ at ].file, line );
#ifndef __OPTIMIZED__
exit_f( line );
#endif
}
/* public: */ void ExecUt :: putErr // hidden by macros
// -----------------------------------------------------------------------------
(
int err
, char * file
, int line
)
{
if no_this NO_this
errno = err ;
if ( err )
then {
path t ; sprintf( t,
"\nErrNo( %18s ) at %6i.%s\n", semantics( err ), line, file );
to_trace( t );
}
else stack[ at ].comm = "" ;
#ifndef __OPTIMIZED__
exit_f( line );
#endif
}
/* public: */ void ExecUt :: exit_f // hidden by macros
/* -----------------------------------------------------------------------------
pop function call (exit at a 'return' point)
-----------------------------------------------------------------------------
*/ (
int line // of return
)
{
if no_this NO_this
//
if ( maxdepth <= at ) return ; // da oft trace nicht von Anfang an
// if ( maxdepth <= at )
if ( maxdepth < at )
then {
#ifdef LB_tr
#else
printf( "\nerror: %i = maxdepth <= at = %i\n", maxdepth, at );
#endif
if ( at == maxdepth ) return ;
printf( "\nerror: exut out of step\n" );
at = maxdepth ; comm = comment ; // re-initialize
// at -= 10 ;
sprintf( sss, "W a r n i n g : ExecUt out of step \n" ); exit(1);
trace( sss ); show(3);
*sss = 0 ;
}
else {
comm = stack[ at ].comm - 1 ;
/* if ( trace_from < call_nr )
{
sprintf( sss, " "
"exit %s at %i\n", stack[ at ].proc, line );
trace( sss );
}
*/
// return out of:
// sprintf( sss, "< %s", stack [ at ].proc );
stack[ at ].line = line ; // server's exit
stack[ at++ ].errn = errno ; // server's errno at exit
}
#ifdef __MAXIMAL_TRACE__
if ( trace_from < call_nr ) fprintf( ef, " %2i_%s%i.%s %s\n"
, maxdepth - at + 1
, exit_type
, stack[ at ].line
, stack[ at ].file, sss );
fflush( ef );
#endif
}
/* public: */ void ExecUt :: count
/* -----------------------------------------------------------------------------
Store test coverage for the given code line (= return from a method).
-----------------------------------------------------------------------------
*/ (
char * file
, int line
)
LB_("ExecUt.count")
#ifdef prot_
sprintf( cName, "%s.%i", file, line ); KVStore st ;
counter[ counterNames -> Get( cName, st ) ]++ ;
#endif
LE_
/* public: */ void ExecUt :: count_init
/* -----------------------------------------------------------------------------
Create all counter names
The given file has to be a concatenation of all already preprocessed
compilation units.
-----------------------------------------------------------------------------
*/ (
char * file
)
LB_("ExecUt.count_init")
#ifdef prot_
rBuffer B( file, "" ); Surr s ;
while ( B.find( 1, "xut.count(", 0 ) )
{
char * c = B.z + B.a + 12 ; if ( c[-1] != '"' ) fErr
char * e = c ; to_( e, '"' ) *e++ = '.' ;
char * x = e + 1 ;
while ( isdigit( *x ) ) *e++ = *x++ ; *e = 0 ;
s = counterNames -> StrIns( c );
}
if ( e_prot_ <= s ) fErr
#endif
LE_
/* public: */ void ExecUt :: count_show
/* -----------------------------------------------------------------------------
show test coverage
-----------------------------------------------------------------------------
*/ (
char * file
, int line
)
LB_("ExecUt.count_show")
#ifdef prot_
KVStore st ; Surr s = counterNames -> GetFirst( st );
while ( s )
{
fprintf( ef, "%-8i %s", s, st.k ); s = counterNames -> Next( st );
}
#endif
LE_
/* public: */ void ExecUt :: NewCounters(
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Reinitialize counters for test coverage (i.e. make them 0).
-----------------------------------------------------------------------------
*/ )
LB_("ExecUt.NewCounters")
#ifdef __TESTCOVER__
unlink( counters ); ok
for ( int k = 0 ; k < L_wp ; ) wp[ k++ ] = 0 ;
PutCounters();
#endif
LE_
/* public: */ void ExecUt :: PutCounters(
/* -----------------------------------------------------------------------------
Der Aufrufer sagt:
Addiere die in diesem Lauf errechnete Testberdeckung zur schon
frher erreichten.
Die Funktion garantiert: fErr || ok
-----------------------------------------------------------------------------
*/ )
LB_("ExecUt.PutCounters")
#ifdef __TESTCOVER__
int L = sizeof( int ) * L_wp ;
int f = _open( counters, O_BINARY | O_RDWR );
if ( errno )
then {
ok f = _open( counters, O_BINARY | O_RDWR | O_CREAT,
S_IREAD | S_IWRITE ); EE
}
else {
int wp_alt[ L_wp ] ; if ( read( f, wp_alt, L ) != L ) fErr
int k = -1 ; while ( ++k < L_wp ) wp[ k ] += wp_alt[ k ] ;
}
if ( write( f, wp, L ) != L ) fErr
close( f );
#endif
LE_
/* private: */ void ExecUt :: show // hidden by macros
/* -----------------------------------------------------------------------------
stop program because of a fatal error detected
show all data in the current execution stack
-----------------------------------------------------------------------------
*/ (
int Von
)
{
//
// , Von, errno, inproc );
ERRNo = errno ; if ( stack_shown++ ) exit( 1 );
#ifdef __SPU__
/*
fprintf( ef, "\n%p %p %p %p %p %p \n"
"stdout stderr ef stout sterr to_f \n" ,
stdout, stderr, ef , stout , sterr , to_f );
*/
#endif
#ifdef __OPTIMIZED__
fprintf( ef, "\n\nCode version 'minimal checks'" );
#else
fprintf( ef, "\n\nCode version 'maximal checks'" );
#endif
fprintf( ef, " on %s:\n\nStack is\n\n%s", currentTime( 0 )
, stack[ at ].comm );
stack[ at ].errn = errno ;
uint j = maxdepth ; int recover = 0 ;
if ( j-1 <= at1 )
then {
*comm = 0 ; fprintf( ef, "%s\n", comment );
}
if ( at1 < at-3 ) at1 = at-3 ;
trace_from = INT_MAX ;
while ( at1 <= --j )
{
comm[ 0 ] = 0 ;
if ( j < at ) stack[ j ].comm = comment ; // no comment
char * pr = stack[ j ].proc ;
int s = strlen( pr ) - 1 ;
while ( isalnum( pr[s] ) || pr[s] == '_' ) s-- ;
stack[ j ].proc[ 28 ] = 0 ;
#define error(x) stack[ x ].proc \
, semantics( stack[ x ].errn ) \
, stack[ x ].line \
, stack[ x ].file
if ( j == at-1 )
then fPrintf( ef, "--> %-28s : %s at %i %s\n", error( j ) );
else {
if ( j == at-2 )
fprintf( ef, "\n Last checkpoint before was\n" );
fPrintf( ef, " %-28s : at %i %s\n", stack[ j ].proc
, stack[ j ].line
, stack[ j ].file );
}
#undef error
// if ( stack[ j ].recover ) recover = stack[ j ].recover ;
}
if ( show_at )
then {
fflush( ef );
}
if ( recover )
then {
// throw syserror exception or do the recovery here (e.g. by sending
// a signal 'restart me' to a master process and then stopping).
printf( "RECOVER not yet implemented\n" ); exit( -1 );
}
// else ret_
// else exit( 1 );//exit fhrt komischerweise in einen unendlichen loop !!!
}
/* public: virtual */ void ExecUt :: stop
/* -----------------------------------------------------------------------------
show a window telling the user that an error occurred
-----------------------------------------------------------------------------
*/ (
int en // if ( en <= 0 ): error is a system error
// if ( en > 0 ): error is an application error
)
{
#ifndef __OPTIMIZED__
char comm[ 200 ] ;
sprintf( comm, "echo %i > xtrace", call_nr - 100 );
#undef system
system( comm );
#define system safe_ut.ok_system
#endif
if ( stopped )
then {
printf( "\n stop: %i, stopped = %i\n", en, stopped ); exit(1);
}
if ( en < 0 )
then {
char mess[ 300 ] ;
//
errno = ERRNo ;
// if ( 1 < call_nr ) sprintf( mess,
if ( 0 ) sprintf( mess,
"S y s t e m E r r o r at call_nr %i, trace in %s, errno = %i\n%s"
, call_nr
, err_file
, errno, stack[ at ].comm );
else sprintf( mess, "%s.exe atLB = %i: "
// "S y s t e m E r r o r \"%s\" , see %s\n%s"
"S y s t e m E r r o r \"%s\" %s"
, this_exe
, atLB
, semantics( errNo )
// , err_file
, stack[ at ].comm );
PToScreen ps ; ps.message( mess ) ;
}
else ;
printf( "\nis errno %i, last LB_ was in %s\n\n", errNo, inproc );
#ifndef __OPTIMIZED__
ok_rem_heap( 0 );
#endif
#ifdef __WINDOWS__
printf( "__WINDOWS__" );
EWinApp * pApp = ( EWinApp * ) AfxGetApp();
if ( pApp ) pApp -> Exit() ; else AfxAbort() ;
#else
exit( en );
#endif
stopped = 1 ;
}
#ifdef __WINDOWS__
#include "en_s1.h"
#endif
/* public: */ const char * ExecUt :: semantics
/* -----------------------------------------------------------------------------
return pointer to semantics of a error code 'code'
-----------------------------------------------------------------------------
*/ (
int code // in: any value EN_...
)
{
if no_this return( "" );
if ( 0 < code && code <= 42 ) return( strerror( code ) );
#ifdef MICROSOFT
if ( 0 < code )
if ( code < 500 || 16000 < code ) return( strerror( code ) );
#endif
switch ( code )
{
case 0 : return( "ok" );
#ifdef __WINDOWS__
#include "en_s2.h" // aus "en.h" mittels en_sem.exe erzeugt
#else
#include "en_sem.h" // aus "en.h" mittels en_sem.exe erzeugt
#endif
default: {
sprintf( nosem, "unspecified errno: %i", errno );
return( nosem );
}
}
}
/* public: */ void ExecUt :: trace_config
/* -----------------------------------------------------------------------------
Der Aufrufer garantiert: -
- sein Auftrag: set trace destination to_f and redefine trace_from
Die Funktion garantiert: -
Diese Prozedur wird vor allem dann aufzurufen sein, wenn Trace direkt auf
den Bildschirm (als stderr) gegeben werden soll - etwa deswegen, weil der
Prozess vor seinem Absturz kein flush auf die Diagnosedatei mehr machen
kann (DOS und QUICK_WIN Programme).
-----------------------------------------------------------------------------
*/ (
FILE * to_file // in: if 0 reset to *.err file
, char from // in: if 'e' according to FROM_PROC
// else from now on
)
{
if no_this return ;
if ( to_file ) to_f = to_file ; else to_f = ef ;
also_to_f = ( to_f && to_f != ef ) ;
if ( from == 'e' )
then {
char * c = getenv( "FROM_PROC" ); trace_from = ( c )? atoi(c) : 0 ;
}
else trace_from = call_nr ;
if not_path_exists( "xtrace.bat" )
{
FILE * f = create( "xtrace.bat" );
fprintf( f, "call trace 9999999 0 9999999" );
close( f );
}
S_ "call xtrace.bat" _Do
#ifdef __WINDOWS__
if ( to_f == stdout ) to_f = stout ;
if ( to_f == stderr ) to_f = sterr ;
#endif
}
/* public: */ void ExecUt :: at_code_position // see mt.h
/* -----------------------------------------------------------------------------
trace code position
-----------------------------------------------------------------------------
*/ (
char * file
, int line
)
{
if no_this return ;
if ( trace_from <= call_nr )
{
fprintf( ef, " %i\n", line );
}
}
/* public: */ void ExecUt :: trace_always // hidden by macros
/* -----------------------------------------------------------------------------
trace even if call_nr < trace_from
-----------------------------------------------------------------------------
*/ (
char * str
)
{
if no_this NO_this
fprintf( ef, "%s", str );
if ( also_to_f ) fprintf( to_f, "%s", str );
}
/* public: */ void ExecUt :: show_text
/* -----------------------------------------------------------------------------
trace the first n_... characters of txt
-----------------------------------------------------------------------------
*/ (
char * name // any string
, char * txt // any text
, int n_chars //
)
{
if no_this NO_this
if ( trace_from < call_nr )
{
if ( 230 < n_chars ) n_chars = 230 ;
if ( L_sss <= n_chars ) n_chars = L_sss - 1 ;
memcpy( sss, txt, n_chars ); sss[ n_chars ] = 0 ;
for ( int i = 0 ; i < n_chars ; i++ ) if ( !sss[i] ) sss[i] = '?' ;
S_ "%s = ...[%s]...\n", name, sss _TR
}
}
/* public: */ void ExecUt :: trace // hidden by macros
// -----------------------------------------------------------------------------
(
char * str
)
{
if no_this NO_this
#ifdef __WINDOWS__
#ifdef __MFC__
TRACE( str ); // nimmt Parameter wie printf
#endif
#endif
if ( to_stack ) to_trace( str );
if ( also_to_f ) fprintf( to_f, "\n%s", str );
}
/* public: */ void ExecUt :: trace // hidden by macros
// -----------------------------------------------------------------------------
(
char * name
, char * wert
)
{
if no_this NO_this
if ( ! wert ) wert = "( null )" ;
if ( to_stack )
then {
sprintf( sss, "\n%s = [", name );
char * c1 = ( char * ) wert ; // Betrug des const in der SS
char * c2 = sss + strlen( sss ) ;
char * c3 = c1 + 200 ;
while ( *c1 && c1 < c3 ) *c2++ = *c1++ ; *c2 = 0 ;
if ( c1 == c3 ) strcpy( c2, " ... \n" );
else strcpy( c2, "]\n" );
to_trace( sss );
}
if ( also_to_f )
then {
const int cs = 80 ; char c[ cs ];
memcpy( c, wert, cs ); c[ cs-1 ] = 0 ;
fprintf( to_f, "\n%s = (%s)", name, c );
}
}
/* public: */ void ExecUt :: trace // hidden by macros
// -----------------------------------------------------------------------------
(
BOOL onoff
)
{
if no_this NO_this
if ( onoff )
then trace_from = 0 ;
else trace_from = LONG_MAX ;
}
/* public: */ void ExecUt :: trace // hidden by macros
// -----------------------------------------------------------------------------
(
char * name //
, pointer wert //
)
{
if ( to_stack )
then {
if no_this return ;
sprintf( sss, "\n%s = %p", name, wert ); to_trace( sss );
}
if ( also_to_f )
then {
fprintf( to_f, "\n%s = (%p)", name, wert );
}
}
/* public: */ void ExecUt :: trace // hidden by macros
// -----------------------------------------------------------------------------
(
char * name
, long wert
)
{
if no_this NO_this
char str[ 12 ] ; *str = 0 ;
uchar c = abs( wert ) % 256 ;
if ( abs( wert ) == c )
then {
if ( isprint(( char ) c ) ) sprintf( str, "'%c' = ", ( char ) c );
}
if ( to_stack )
then {
sprintf( sss, "\n%s = %s%ld", name, str, wert ); to_trace( sss );
}
if ( also_to_f )
then {
fprintf( to_f, "\n%s = %s(%ld)", name, str, wert );
}
}
/* public: */ void ExecUt :: xrace // hidden by macros
/* -----------------------------------------------------------------------------
PROBLEM -- warum ????????????
-----------------------------------------------------------------------------
*/ (
char * name
, double wert
)
{
if no_this NO_this
char str[ 40 ] ; s_( str, "%f", wert ); trace( name, str );
}
/* public: */ void ExecUt :: trace // hidden by macros
/* -----------------------------------------------------------------------------
Klassen K, deren Instanzen als Trace auszugeben sein sollen, mssen eine
Methode K :: trace() bereitstellen, mit der sich jede Instanz selbst per
ExecUt :: trace drucken kann. Sie tun das dann, wenn sie Spezialisierung
der Klasse 'EStandardServices' sind.
Aufruf solcher Trace-Befehle nur per Macro L1_ (damit in der optimierten
Version des Systems garantiert kein Trace-Kommando mehr steht).
-----------------------------------------------------------------------------
*/ (
char * name //
, EStandardServices & wert // the object to be traced
)
{
if no_this NO_this
wert.trace( name, ef );
if ( also_to_f ) wert.trace( name, to_f );
}
/* Beispiel eine ausgedruckten Kellers (Diagnosedaten sind stets solche, die
die unmittelbar ber ihnen stehende Funktion gesammelt hat):
Execution Stack ( error in call 109 ):
main program : ok at 89 main.h
rB_cpp_ic.cpp_ic : ok at 123 rbcppic.cpp
rB_cpp_ic.shift_me : ok at 162 rbcppic.cpp
len of e:\tmp\xx_edit = 585216,, 4096 = L, gel = 0
rBuffer.find : ok at 271 rbuffer.cpp
--> rBuffer.f_write : not_an_open_file at 448 rbuffer.cpp
*/
/* public: */ void ExecUt :: ok_new_sto // hidden by macros
/* -----------------------------------------------------------------------------
register allocated item
-----------------------------------------------------------------------------
*/ (
pointer ref //
, int line // where allocated in the file
, char * file //
)
{
if no_this NO_this
stn = ( ++stn % L_hdescr_page );
if ( ! stn )
then {
heap_descr_page * pre = sto ;
sto1 = sto = new heap_descr_page ; sto->pre = pre ;
}
sto -> sto[ stn ].ref = ref ;
sto -> sto[ stn ].line = line ;
sto -> sto[ stn ].file = file ;
// S_ "%p heap - new_sto at %i.%s\n", ref, line, file _TR_a
}
/* public: */ void ExecUt :: ok_rem_sto // hidden by macros
/* -----------------------------------------------------------------------------
unregister heap item
-----------------------------------------------------------------------------
*/ (
pointer ref //
)
{
if ( ! ref || no_this ) return ;
S_ "Heap %p rem_sto \n", ref _TR
int a = stn ;
while ( sto )
{
while ( 0 <= a )
{
if ( sto -> sto[ a ].ref == ref )
then { sto -> sto[ a ].line = 0 ; return ; }
a-- ;
}
sto1 = sto = sto->pre ; a = L_hdescr_page - 1 ;
if ( ! sto ) stn = -1 ; // damit ok_new_sto() neu anfangen kann
}
S_ "W a r n i n g : rem_sto() cannot find the item %p \n", ref _TR
show_heap
}
/* public: */ void ExecUt :: ok_rem_heap // hidden by macros
/* -----------------------------------------------------------------------------
search the heap for still allocated items
-----------------------------------------------------------------------------
*/ (
BOOL check // true, if you expect the heap to be empty
)
{
if no_this NO_this
int a = stn ; long items = 0 ;
while ( sto )
{
while ( 0 <= a )
{
if ( sto -> sto[ a ].line )
then {
if ( check )
then {
++ items ;
S_ "delete storage allocated at %5ld %s\n"
, sto -> sto[ a ].line
, sto -> sto[ a ].file _TR
}
// Das delete hier aber nicht wirklich anwenden -
// wir wollen ja nur sehen, was vergessen wurde!
}
a-- ;
}
heap_descr_page * pre = sto->pre ; delete( sto ); sto1 = sto = pre ;
a = L_hdescr_page - 1 ;
}
stn = L_hdescr_page - 1 ;
if ( items ) errno = EN_still_allocated_items ; // hier ja kein fErr !!
}
/* public: */ void ExecUt :: ok_show_heap // hidden by macros
/* -----------------------------------------------------------------------------
show all items not yet deallocated
-----------------------------------------------------------------------------
*/ (
char * file
, int line
)
LB_("ExecUt.ok_show_heap")
S_ "Heap at %i in %s: \n----\n", line, file _TR
int a = stn ; long items = 0 ;
while ( sto )
{
while ( 0 <= a )
{
if ( sto -> sto[ a ].line )
then {
S_ "Heap %p allocated at %5ld %s\n"
, sto -> sto[ a ].ref
, sto -> sto[ a ].line
, sto -> sto[ a ].file _TR
items++ ;
}
a-- ;
}
sto1 = sto = sto->pre ; a = L_hdescr_page - 1 ;
}
S_ "Heap items: %ld \n", items _TR
LE_
/* public: */ BOOL ExecUt :: ok_At
// -----------------------------------------------------------------------------
(
char * c
, char * s
)
{
while ( *s && *s == *c ) { s++ ; c++ ; }
return( ! *s );
}
/* public: */ BOOL ExecUt :: ok_iAt
// -----------------------------------------------------------------------------
(
char * c
, char * s
)
{
while ( *s && upper( *s ) == upper( *c ) ) { s++ ; c++ ; }
return( ! *s );
}
/* public: */ int ExecUt :: ok_norm
/* -----------------------------------------------------------------------------
Ersetze in 'str alle 'fc durch 'tc, return strlen( str )
-----------------------------------------------------------------------------
*/ (
char * str
, char fc
, char tc
)
LB_("ExecUt.ok_norm")
if ( errno == 2 ) errno = 0 ; // file not found
if ( errno ) errno = 0 ; //
if ( errno ) fErr1( str )
if ( ! str ) en_fErr( EN_NULL_pointer ) esif ( ! *str ) ret( 0 )
int n = 0 ;
while ( *str )
{
if ( *str == fc ) { *str = tc ; n++ ; }
str++ ;
}
if ( errno ) fErr3( errno, n, str );
LE_ret( n )
#undef m_exut
#define m_exut exut.
#define getenv safe_ut.ok_getenv
#define fopen safe_ut.ok_fopen
#undef __EXEC_UT_CPP__
#undef static
#endif