af15e0698b
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
1106 lines
34 KiB
C
Executable File
1106 lines
34 KiB
C
Executable File
/* e4error.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
|
||
|
||
#include "d4all.h"
|
||
|
||
#ifdef __TURBOC__
|
||
#pragma hdrstop
|
||
#endif /* __TUROBC__ */
|
||
|
||
#ifdef S4WINTEL
|
||
#ifndef S4WINDOWS
|
||
#include <conio.h>
|
||
#endif /* not S4WINDOWS */
|
||
#endif /* S4WINTEL */
|
||
|
||
#ifdef S4OS2PM
|
||
#define E4MSGBOXID 9513
|
||
#endif
|
||
|
||
#ifdef S4VB_DOS
|
||
#define V4ERROR 1
|
||
#define V4SEVERE 2
|
||
#endif
|
||
|
||
#ifdef S4OS2PM
|
||
#ifndef E4ERROR_OFF
|
||
#ifndef E4OFF_STRING
|
||
extern ERROR4INFO_ARRAY *error4array ;
|
||
#endif
|
||
#endif
|
||
#endif
|
||
int S4FUNCTION error4file( CODE4 *c4, S4CONST char *name, const int overwrite )
|
||
{
|
||
int rc, oldOpenError, oldCreateError, oldSafety ;
|
||
|
||
if ( c4->errorLog != 0 )
|
||
return -1 ;
|
||
|
||
c4->errorLog = (FILE4 *)u4allocEr( c4, sizeof( FILE4 ) ) ;
|
||
if ( c4->errorLog == 0 )
|
||
return e4memory ;
|
||
c4->errorLog->hand = -1 ;
|
||
|
||
oldSafety = c4->safety ;
|
||
if ( overwrite == 0 )
|
||
{
|
||
oldOpenError = c4->errOpen ;
|
||
c4->errOpen = 0 ;
|
||
rc = file4open( c4->errorLog, c4, name, 1 ) ;
|
||
c4->errOpen = oldOpenError ;
|
||
if ( rc != r4noOpen ) /* if open failed, try create */
|
||
return rc ;
|
||
c4->safety = 1 ; /* file shouldn't exist */
|
||
}
|
||
else
|
||
c4->safety = 0 ; /* ignore setting for overwrite */
|
||
|
||
oldCreateError = c4->errCreate ;
|
||
c4->errCreate = 0 ;
|
||
rc = file4create( c4->errorLog, c4, name, 1 ) ;
|
||
c4->errCreate = oldCreateError ;
|
||
c4->safety = oldSafety ;
|
||
|
||
return rc ;
|
||
}
|
||
|
||
void error4logAppend( CODE4 *c4, int errCode1, long errCode2, const char *desc1, const char *desc2, const char *desc3 )
|
||
{
|
||
int len ;
|
||
char num[11] ;
|
||
const char *ptr ;
|
||
FILE4 *errorLog ;
|
||
|
||
/* in case one of the file writes fails, avoid endless error loop */
|
||
errorLog = c4->errorLog ;
|
||
c4->errorLog = 0 ;
|
||
|
||
memset( num, 0, sizeof( num ) ) ;
|
||
c4ltoa45( (long)errCode1, num, sizeof( num ) - 1 ) ;
|
||
file4write( errorLog, file4len( errorLog ), num, strlen( num ) ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
|
||
ptr = e4text( errCode1 ) ;
|
||
if ( ptr != 0 )
|
||
{
|
||
file4write( errorLog, file4len( errorLog ), ptr, strlen( ptr ) ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
}
|
||
|
||
memset( num, 0, sizeof( num ) ) ;
|
||
c4ltoa45( error4number2( errCode2 ), num, sizeof( num ) - 1 ) ;
|
||
file4write( errorLog, file4len( errorLog ), num, strlen( num ) ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
|
||
#ifndef E4OFF_STRING
|
||
ptr = error4text( c4, errCode2 ) ;
|
||
if ( ptr != 0 )
|
||
{
|
||
file4write( errorLog, file4len( errorLog ), ptr, strlen( ptr ) ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
}
|
||
#endif
|
||
|
||
#ifdef E4FILE_LINE
|
||
if ( s4fileName != 0 )
|
||
{
|
||
file4write( errorLog, file4len( errorLog ), code4fileName(), strlen( code4fileName() ) ) ;
|
||
memset( num, 0, sizeof( num ) ) ;
|
||
c4ltoa45( code4lineNo(), num, sizeof( num ) - 1 ) ;
|
||
file4write( errorLog, file4len( errorLog ), num, strlen( num ) ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
}
|
||
#endif
|
||
|
||
if ( desc1 != 0 )
|
||
{
|
||
len = strlen( desc1 ) ;
|
||
file4write( errorLog, file4len( errorLog ), desc1, (unsigned int)len ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
}
|
||
if ( desc2 != 0 )
|
||
{
|
||
len = strlen( desc2 ) ;
|
||
file4write( errorLog, file4len( errorLog ), desc2, (unsigned int)len ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
}
|
||
if ( desc3 != 0 )
|
||
{
|
||
len = strlen( desc3 ) ;
|
||
file4write( errorLog, file4len( errorLog ), desc3, (unsigned int)len ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
}
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
file4write( errorLog, file4len( errorLog ), "\r\n", strlen( "\r\n" ) ) ;
|
||
|
||
c4->errorLog = errorLog ;
|
||
}
|
||
|
||
#ifndef S4SERVER
|
||
#ifdef S4CONSOLE
|
||
#ifdef E4PAUSE
|
||
static void error4pause( void )
|
||
{
|
||
#ifndef S4WINTEL
|
||
getchar() ;
|
||
#else
|
||
getch() ;
|
||
#endif
|
||
}
|
||
#endif
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef S4WINDOWS
|
||
#ifdef __TURBOC__
|
||
#if __TURBOC__ == 0x297 /* if Borland C++ 2.0 */
|
||
#ifdef __cplusplus
|
||
extern "C"{ void FAR PASCAL FatalAppExit(WORD,LPSTR) ; }
|
||
#else
|
||
void FAR PASCAL FatalAppExit(WORD,LPSTR) ;
|
||
#endif /* __cplusplus */
|
||
#endif /* __TUROBC__ == 0x297 */
|
||
#endif /* __TUROBC__ */
|
||
|
||
#ifndef __SC__
|
||
#ifdef __ZTC__
|
||
#ifdef __cplusplus
|
||
extern "C"{ void FAR PASCAL FatalAppExit(unsigned short,LPSTR) ; }
|
||
#else
|
||
void FAR PASCAL FatalAppExit(unsigned short,LPSTR) ;
|
||
#endif /* __cplusplus */
|
||
#endif /* __ZTC__ */
|
||
#endif /* __SC__ */
|
||
|
||
#ifdef _MSC_VER
|
||
#if _MSC_VER == 600
|
||
#ifdef __cplusplus
|
||
extern "C"{ void FAR PASCAL FatalAppExit(WORD,LPSTR) ; }
|
||
#else
|
||
void FAR PASCAL FatalAppExit(WORD,LPSTR) ;
|
||
#endif /* __cplusplus */
|
||
#endif /* _MSC_VER == 600 */
|
||
#endif /* _MSC_VER */
|
||
#endif /* S4WINDOWS */
|
||
|
||
S4CONST char *bad4data = "Invalid or Unknown Error Code" ;
|
||
|
||
#ifndef E4ERROR_OFF
|
||
#ifndef S4LANGUAGE
|
||
|
||
ERROR4DATA e4errorData[] =
|
||
{
|
||
/* General Disk Access Errors */
|
||
{ e4close, "Closing File" },
|
||
{ e4create, "Creating File" },
|
||
{ e4len, "Determining File Length" },
|
||
{ e4lenSet, "Setting File Length" },
|
||
{ e4lock, "Locking File" },
|
||
{ e4open, "Opening File" },
|
||
{ e4permiss, "Permission Error Opening File" },
|
||
{ e4access, "Access Error Opening File" },
|
||
{ e4numFiles, "File Handle Count Overflow Error Opening File" },
|
||
{ e4fileFind, "File Find Error Opening File" },
|
||
{ e4instance, "Duplicate Instance Found Error Opening File" },
|
||
{ e4read, "Reading File" },
|
||
{ e4remove, "Removing File" },
|
||
{ e4rename, "Renaming File" },
|
||
{ e4seek, "Seeking to File Position" },
|
||
{ e4unlock, "Unlocking File" },
|
||
{ e4write, "Writing to File" },
|
||
{ e4authorize, "Authorization Error (access denied)" },
|
||
|
||
/* Database Specific Errors */
|
||
{ e4data, "File is not a Data File" },
|
||
{ e4fieldName, "Unrecognized Field Name" },
|
||
{ e4fieldType, "Unrecognized Field Type" },
|
||
{ e4recordLen, "Record Length is too Large" },
|
||
{ e4append, "Record Append Attempt Past End of File" },
|
||
|
||
/* Index File Specific Errors */
|
||
{ e4entry, "Tag Entry Missing" },
|
||
{ e4index, "Not a Correct Index File" },
|
||
{ e4tagName, "Tag Name not Found" },
|
||
{ e4unique, "Unique Key Error" },
|
||
{ e4tagInfo, "Tag Information Invalid" },
|
||
|
||
/* Expression Evaluation Errors */
|
||
{ e4commaExpected, "Comma or Bracket Expected" },
|
||
{ e4complete, "Expression not Complete" },
|
||
{ e4dataName, "Data File Name not Located" },
|
||
{ e4lengthErr, "IIF() Needs Parameters of Same Length" },
|
||
{ e4notConstant, "SUBSTR() and STR() need Constant Parameters" },
|
||
{ e4numParms, "Number of Parameters is Wrong" },
|
||
{ e4overflow, "Overflow while Evaluating Expression" },
|
||
{ e4rightMissing, "Right Bracket Missing" },
|
||
{ e4typeSub, "Sub-expression Type is Wrong" },
|
||
{ e4unrecFunction, "Unrecognized Function" },
|
||
{ e4unrecOperator, "Unrecognized Operator" },
|
||
{ e4unrecValue, "Unrecognized Value"} ,
|
||
{ e4unterminated, "Unterminated String"} ,
|
||
{ e4tagExpr, "Expression Invalid for Tag"} ,
|
||
|
||
/* Optimization Errors */
|
||
{ e4opt, "Optimization Error"} ,
|
||
{ e4optSuspend, "Optimization Removal Failure"} ,
|
||
{ e4optFlush, "Optimization File Flushing Failure"} ,
|
||
|
||
/* Relation Errors */
|
||
{ e4lookupErr, "Matching Slave Record Not Located"} ,
|
||
{ e4relate, "Relation Error"} ,
|
||
{ e4relateRefer, "Relation Referred to Does Not Exist or is Not Initialized"} ,
|
||
|
||
/* Report Errors */
|
||
{ e4report, "Report Error"} ,
|
||
{ e4styleCreate, "Error Creating Style"},
|
||
{ e4styleSelect, "Error Selecting Style"},
|
||
{ e4styleIndex, "Error Finding Style"},
|
||
{ e4areaCreate, "Error Creating Area"},
|
||
{ e4groupCreate, "Error Creating Group"},
|
||
{ e4groupExpr, "Error Setting Group Reset-Expression"},
|
||
{ e4totalCreate, "Error Creating Total"},
|
||
{ e4objCreate, "Error Creating Object"},
|
||
{ e4repWin, "Error In Windows Output"},
|
||
{ e4repOut, "Error In Report Output"},
|
||
{ e4repSave, "Error Saving Report"},
|
||
{ e4repRet, "Error Retrieving Report"},
|
||
{ e4repData, "Error In Sending Report to Data File"},
|
||
|
||
/* Critical Errors */
|
||
{ e4info, "Unexpected Information"} ,
|
||
{ e4memory, "Out of Memory"} ,
|
||
{ e4parm, "Unexpected Parameter"} ,
|
||
{ e4parm_null, "Null Input Parameter unexpected"} ,
|
||
{ e4demo, "Exceeded Maximum Record Number for Demonstration"} ,
|
||
{ e4result, "Unexpected Result"} ,
|
||
{ e4verify, "Structure Verification Failure"} ,
|
||
|
||
/* Not Supported Errors */
|
||
{ e4notIndex, "Function unsupported: library compiled with S4OFF_INDEX" },
|
||
{ e4notMemo, "Function unsupported: library compiled with S4OFF_MEMO" },
|
||
{ e4notRename, "Function unsupported: library compiled with S4NO_RENAME" },
|
||
{ e4notWrite, "Function unsupported: library compiled with S4OFF_WRITE" },
|
||
{ e4notClipper, "Function unsupported: library not compiled with S4CLIPPER" },
|
||
{ e4notLock, "Function unsupported: library not compiled with S4LOCK_HOOK" },
|
||
/* { e4notHook, "Function unsupported: library not compiled with E4HOOK" }, */
|
||
{ e4notSupported, "Function unsupported" },
|
||
|
||
{ e4version, "Application/Library version mismatch" },
|
||
|
||
{ e4memoCorrupt, "Memo File Corrupt" },
|
||
{ e4memoCreate, "Error Creating Memo File" },
|
||
|
||
{ e4max, "CodeBase Capabilities Exceeded (system maxed out)" },
|
||
|
||
{ e4transViolation, "Transaction Violation Error" },
|
||
{ e4trans, "Transaction Error" },
|
||
{ e4rollback, "Transaction Rollback Failure" },
|
||
{ e4commit, "Transaction Commit Failure" },
|
||
|
||
{ e4codeBase, "CodeBase in an Unacknowledged Error State" },
|
||
{ e4name, "Name not Found error" },
|
||
{ e4corrupt, "Communication Information Corrupt" },
|
||
|
||
{ e4connection, "Connection Failure" },
|
||
{ e4socket, "Socket Failure" },
|
||
{ e4net, "Network Failure" },
|
||
{ e4loadlib, "Failure Loading Communication DLL" },
|
||
{ e4timeOut, "Network Timed Out" },
|
||
{ e4message, "Communication Message Corrupt" },
|
||
{ e4packetLen, "Communication Packet Length Mismatch" },
|
||
{ e4packet, "Communication Packet Corrupt" },
|
||
{ e4server, "Server Failure" },
|
||
{ e4config, "Server Configuration Failure" },
|
||
|
||
{ e4transAppend, "Error Appending Information to Log File" },
|
||
{ e4cat, "Catalog Failure" },
|
||
{ e4struct, "Data Structure Corrupt or not Initialized" },
|
||
{ 0, 0 },
|
||
} ;
|
||
|
||
#endif /* not S4LANGUAGE */
|
||
|
||
#ifdef S4LANGUAGE
|
||
#ifdef S4GERMAN
|
||
|
||
S4CONST char *bad4data = "Invalid or Unknown Error Code" ;
|
||
|
||
ERROR4DATA e4errorData[] =
|
||
{
|
||
/* Allgemeine Fehler beim Diskzugriff (General Disk Access Errors) */
|
||
{ e4create, "Anlegen einer Datei" },
|
||
{ e4open, "<EFBFBD>ffnen einer Datei" },
|
||
{ e4read, "Lesen einer Datei" },
|
||
{ e4seek, "Suchen einer Position in der Datei " },
|
||
{ e4write, "Schreiben einer Datei" },
|
||
{ e4close, "Schlie<EFBFBD>en einer Datei" },
|
||
{ e4remove, "L<EFBFBD>schen einer Datei" },
|
||
{ e4lock, "Locken einer Datei" },
|
||
{ e4unlock, "Freigeben einer Datei" },
|
||
{ e4len, "Festlegen der L<>nge einer Datei" },
|
||
{ e4lenSet, "Einstellen der L<>nge einer Datei" },
|
||
{ e4rename, "Umnennen einer Datei" },
|
||
|
||
/* Datenbank spezifische Fehler (Database Specific Errors) */
|
||
{ e4data, "Datei is keiner DatenBank" },
|
||
{ e4recordLen, "Datensatzl<EFBFBD>nge zu gro<72>" },
|
||
{ e4fieldName, "Unbekannter Feldname" },
|
||
{ e4fieldType, "Feldtyp" },
|
||
|
||
/* Indexdatei spezifische Fehler (Index File Specific Errors) */
|
||
{ e4index, "Datei is keine Indexdatei" },
|
||
{ e4entry, "Indexdatei is veraltet" },
|
||
{ e4unique, "Schul<EFBFBD>sel ist schon einmal vorhanden" },
|
||
{ e4tagName, "Name des 'Tag'"},
|
||
|
||
/* Fehler bei der Bewertung von Ausdr<64>cken (Expressions Evaluation Errors) */
|
||
{ e4commaExpected, "\",\" oder \")\" erwartet" },
|
||
{ e4complete, "Ausdruck ist nich vollst<73>ndig" },
|
||
{ e4dataName, "Keine offene Datenbank" },
|
||
{ e4numParms, "Ung<EFBFBD>ltige Anzahl von Parametern im Ausdruck"},
|
||
{ e4overflow, "<EFBFBD>berlauf bei der Auswertung eines Ausdrucks" },
|
||
{ e4rightMissing, "Rechte Klammer im Ausdruck fehlt" },
|
||
{ e4unrecFunction, "Unbekannte Funktion im Ausdruck" },
|
||
{ e4unrecOperator, "Unbekannter Operator im Ausdruck" },
|
||
{ e4unrecValue, "Unbekannter Wert im Ausdruck"} ,
|
||
{ e4unterminated, "Nicht abgeschlossene Zeichenkette im Ausdruck"} ,
|
||
|
||
/* Optimization Errors */
|
||
{ e4opt, "Optimization Error"} , /*!!!GERMAN*/
|
||
{ e4optSuspend, "Optimization Removal Failure"} , /*!!!GERMAN*/
|
||
{ e4optFlush, "Optimization File Flushing Failure"} , /*!!!GERMAN*/
|
||
|
||
/* Relation Errors */
|
||
{ e4lookupErr, "Matching Slave Record Not Located"} ,
|
||
|
||
/* Kritische Fehler (Critical Errors) */
|
||
{ e4memory, "Kein Speicher mehr verf<72>gbar"} ,
|
||
{ e4info, "Unerwartete Information" },
|
||
{ e4parm, "Unerwarteter Parameter"},
|
||
{ e4parm_null, "Null Input Parameter unexpected"} ,
|
||
{ e4demo, "Exceeded Maximum Record Number for Demonstration"} , /*!!!GERMAN*/
|
||
{ e4result, "Unerwartetes Ergebnis"},
|
||
{ 0, 0 },
|
||
} ;
|
||
|
||
#endif /* S4GERMAN */
|
||
|
||
#ifdef S4FRENCH
|
||
|
||
ERROR4DATA e4errorData[] =
|
||
{
|
||
/* General Disk Access Errors */
|
||
{ e4create, "En cr<63>ant le fichier" },
|
||
{ e4open, "En engageant le fichier" },
|
||
{ e4read, "En lisant le fichier" },
|
||
{ e4seek, "En se pla<6C>ant dans le fichier" },
|
||
{ e4write, "En <20>crivant dans le fichier" },
|
||
{ e4close, "En lib<69>rant le fichier" },
|
||
{ e4remove, "En effa<66>ant le fichier" },
|
||
{ e4lock, "En bloquant le fichier" },
|
||
{ e4unlock, "En d<>bloquant le fichier" },
|
||
{ e4len, "En d<>terminant la longueur du fichier" },
|
||
{ e4lenSet, "Mise <20> jour de la longueur du fichier" },
|
||
{ e4rename, "D<EFBFBD>nomination du fichier" },
|
||
|
||
/* Database Specific Errors */
|
||
{ e4data, "Le fichier n'est pas une base de donn<6E>es:" },
|
||
{ e4recordLen, "La fiche est trop grande" },
|
||
{ e4fieldName, "Champ inconnu" },
|
||
{ e4fieldType, "Type de champ inconnu" },
|
||
|
||
/* Index File Specific Errors */
|
||
{ e4index, "Ce n'est pas un fichier d'indice" },
|
||
{ e4entry, "Le fichier d'indice n'est pas <20> jour" },
|
||
{ e4unique, "La clef n'est pas unique" },
|
||
{ e4tagName, "L'article d<>sign<67> par l'indice n'existe pas" },
|
||
|
||
/* Expression Evaluation Errors */
|
||
{ e4commaExpected, "\",\" ou \")\" manquant dans l'expression" },
|
||
{ e4complete, "Expression incompl<70>te" },
|
||
{ e4dataName, "La base r<>f<EFBFBD>r<EFBFBD>e dans l'expression n'est pas pr<70>sente" },
|
||
{ e4numParms, "Nombre ill<6C>gal de crit<69>res dans l'expression"},
|
||
{ e4overflow, "L'expression donne un r<>sultat trop grand" },
|
||
{ e4rightMissing, "Parenth<EFBFBD>se manquante dans l'expression" },
|
||
{ e4typeSub, "Un param<61>tre est de la mauvaise sorte" },
|
||
{ e4unrecFunction, "L'expression contient une fonction inconnue" },
|
||
{ e4unrecOperator, "L'expression contient un op<6F>rateur inconnu" },
|
||
{ e4unrecValue, "L'expression contient une valeur inconnue"} ,
|
||
{ e4unterminated, "Apostrophe manquante dans l'expression"} ,
|
||
|
||
/* Optimization Errors */
|
||
{ e4opt, "Optimization Error"} ,
|
||
{ e4optSuspend, "Optimization Removal Failure"} ,
|
||
{ e4optFlush, "Optimization File Flushing Failure"} ,
|
||
|
||
/* Relation Errors */
|
||
{ e4lookupErr, "Matching Slave Record Not Located"} ,
|
||
|
||
/* Critical Errors */
|
||
{ e4memory, "Plus de m<>moire disponible" } ,
|
||
{ e4info, "Information inexpect<63>e"} ,
|
||
{ e4parm, "Param<EFBFBD>tre inexpect<63>"} ,
|
||
{ e4parm_null, "Null Input Parameter unexpected"} ,
|
||
{ e4demo, "Au maximum d'articles dans la version de d<>monstration" } ,
|
||
{ e4result, "R<EFBFBD>sultat inexpect<63>"} ,
|
||
{ 0, 0 },
|
||
} ;
|
||
|
||
#endif /* S4FRENCH */
|
||
|
||
#ifdef S4SCANDINAVIAN
|
||
|
||
ERROR4DATA e4errorData[] =
|
||
{
|
||
/* General Disk Access Errors */
|
||
{ e4create, "Creating File" },
|
||
{ e4open, "Opening File" },
|
||
{ e4read, "Reading File" },
|
||
{ e4seek, "Seeking to File Position" },
|
||
{ e4write, "Writing to File" },
|
||
{ e4close, "Closing File" },
|
||
{ e4remove, "Removing File" },
|
||
{ e4lock, "Locking File" },
|
||
{ e4unlock, "Unlocking File" },
|
||
{ e4len, "Determining File Length" },
|
||
{ e4lenSet, "Setting File Length" },
|
||
{ e4rename, "Renaming File" },
|
||
|
||
/* Database Specific Errors */
|
||
{ e4data, "File is not a Data File" },
|
||
{ e4recordLen, "Record Length is too Large" },
|
||
{ e4fieldName, "Unrecognized Field Name" },
|
||
{ e4fieldType, "Unrecognized Field Type" },
|
||
|
||
/* Index File Specific Errors */
|
||
{ e4index, "Not a Correct Index File" },
|
||
{ e4entry, "Tag Entry Missing" },
|
||
{ e4unique, "Unique Key Error" },
|
||
{ e4tagName, "Tag Name not Found" },
|
||
|
||
/* Expression Evaluation Errors */
|
||
{ e4commaExpected, "Comma or Bracket Expected" },
|
||
{ e4complete, "Expression not Complete" },
|
||
{ e4dataName, "Data File Name not Located" },
|
||
{ e4lengthErr, "IIF() Needs Parameters of Same Length" },
|
||
{ e4notConstant, "SUBSTR() and STR() need Constant Parameters" },
|
||
{ e4numParms, "Number of Parameters is Wrong" },
|
||
{ e4overflow, "Overflow while Evaluating Expression" },
|
||
{ e4rightMissing, "Right Bracket Missing" },
|
||
{ e4typeSub, "Sub-expression Type is Wrong" },
|
||
{ e4unrecFunction, "Unrecognized Function" },
|
||
{ e4unrecOperator, "Unrecognized Operator" },
|
||
{ e4unrecValue, "Unrecognized Value"} ,
|
||
{ e4unterminated, "Unterminated String"} ,
|
||
|
||
/* Optimization Errors */
|
||
{ e4opt, "Optimization Error"} ,
|
||
{ e4optSuspend, "Optimization Removal Failure"} ,
|
||
{ e4optFlush, "Optimization File Flushing Failure"} ,
|
||
|
||
/* Relation Errors */
|
||
{ e4relate, "Relation Error"} ,
|
||
{ e4lookupErr, "Matching Slave Record Not Located"} ,
|
||
|
||
/* Report Errors */
|
||
{ e4report, "Report Error"} ,
|
||
|
||
/* Critical Errors */
|
||
{ e4memory, "Out of Memory"} ,
|
||
{ e4info, "Unexpected Information"} ,
|
||
{ e4parm, "Unexpected Parameter"} ,
|
||
{ e4parm_null, "Null Input Parameter unexpected"} ,
|
||
{ e4demo, "Exceeded Maximum Record Number for Demonstration"} ,
|
||
{ e4result, "Unexpected Result"} ,
|
||
{ 0, 0 },
|
||
} ;
|
||
#endif /* S4SCANDINAVIAN */
|
||
|
||
#endif /* S4LANGUAGE */
|
||
|
||
#endif /* S4ERROR_OFF */
|
||
|
||
#ifndef S4INLINE
|
||
int S4FUNCTION error4code( CODE4 *c4 )
|
||
{
|
||
#ifdef E4PARM_LOW
|
||
if ( c4 == 0 )
|
||
return error4( 0, e4parm_null, E96602 ) ;
|
||
#endif
|
||
return c4->errorCode ;
|
||
}
|
||
#endif
|
||
|
||
int S4FUNCTION error4set( CODE4 *c4, const int newErrCode )
|
||
{
|
||
int oldErrCode ;
|
||
|
||
#ifdef E4PARM_LOW
|
||
if ( c4 == 0 )
|
||
return error4( 0, e4parm_null, E96601 ) ;
|
||
#endif
|
||
|
||
oldErrCode = error4code( c4 ) ;
|
||
c4->errorCode = newErrCode ;
|
||
return oldErrCode ;
|
||
}
|
||
|
||
#ifdef S4CB51
|
||
S4CONST char *S4FUNCTION e4text( const int errCode )
|
||
#else
|
||
S4CONST char *e4text( const int errCode )
|
||
#endif
|
||
{
|
||
#ifndef E4ERROR_OFF
|
||
int i ;
|
||
|
||
for ( i = 0 ; (int)e4errorData[i].errorNum != 0 ; i++ )
|
||
if ( e4errorData[i].errorNum == errCode )
|
||
return e4errorData[i].errorData ;
|
||
#endif
|
||
|
||
return bad4data ; /* errCode not matched */
|
||
}
|
||
|
||
#ifdef S4OS2PM
|
||
|
||
void error4out( CODE4 *c4, int errCode1, long errCode2, const char *desc1, const char *desc2, const char *desc3 )
|
||
{
|
||
int pos = 0 , descNumber = 1 ;
|
||
const char *ptr, *errPtr ;
|
||
HAB e4hab ;
|
||
HMQ e4hmq ;
|
||
char errorStr[100] ;
|
||
#ifndef E4ERROR_OFF
|
||
#ifndef E4OFF_STRING
|
||
const char *tPtr ;
|
||
#endif
|
||
#endif
|
||
|
||
if ( c4 != 0 )
|
||
c4->errorCode = errCode1 ;
|
||
|
||
#ifndef E4ERROR_OFF
|
||
if ( c4 != 0 )
|
||
if ( c4->errOff )
|
||
return ;
|
||
|
||
if (errCode1 != 0)
|
||
{
|
||
strcpy( errorStr, E4_ERROR ) ;
|
||
strcat( errorStr, " #: " ) ;
|
||
c4ltoa45( errCode1, (char *)errorStr+9, 5 ) ;
|
||
pos = 13 ;
|
||
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
|
||
strcpy( errorStr + pos, E4_ERROR ) ;
|
||
strcat( errorStr + pos, " #: " ) ;
|
||
errorStr[strlen(errorStr)] = ' ' ;
|
||
c4ltoa45( error4number2( errCode2 ), (char *)errorStr + pos + 9, 6 ) ;
|
||
pos += 16 ;
|
||
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
|
||
errPtr = e4text( errCode1 ) ;
|
||
if ( errPtr != 0 )
|
||
{
|
||
strcpy( errorStr+pos, errPtr ) ;
|
||
pos += strlen( errPtr ) ;
|
||
errorStr[pos++] = '\r\n' ;
|
||
}
|
||
}
|
||
|
||
#ifndef E4OFF_STRING
|
||
tPtr = error4text( c4, errCode2 ) ;
|
||
if ( tPtr != 0 )
|
||
{
|
||
strcpy( errorStr + pos, tPtr ) ;
|
||
pos += strlen( tPtr ) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
#endif
|
||
|
||
ptr = desc1 ;
|
||
while ( (ptr != (char *) 0) && (descNumber <= 3 ) )
|
||
{
|
||
if ( strlen(desc1)+pos+3 >= sizeof(errorStr) )
|
||
break ;
|
||
strcpy( errorStr + pos, ptr ) ;
|
||
pos += strlen(ptr) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
if ( descNumber++ == 1 )
|
||
ptr = desc2 ;
|
||
else
|
||
ptr = desc3 ;
|
||
}
|
||
|
||
#ifdef E4FILE_LINE
|
||
if ( code4fileName() != 0 )
|
||
if ( strlen( code4fileName() )+pos+8 < sizeof(errorStr) )
|
||
{
|
||
strcpy( errorStr + pos, code4fileName() ) ;
|
||
pos += strlen( code4fileName() ) ;
|
||
errorStr[pos++] = ' ' ;
|
||
c4ltoa45( code4lineNo(), (char *)errorStr+pos, 6 ) ;
|
||
pos += 5 ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
#endif
|
||
|
||
errorStr[pos] = 0 ;
|
||
|
||
/* In case the application has done no PM Initialization, set up an
|
||
instance to allow for the error output to occur */
|
||
|
||
e4hab = WinInitialize(0) ;
|
||
if ( e4hab == NULLHANDLE )
|
||
return ;
|
||
|
||
e4hmq = WinCreateMsgQueue(e4hab, 0) ;
|
||
|
||
if ( e4hmq == NULLHANDLE )
|
||
{
|
||
WinTerminate(e4hab) ;
|
||
return ;
|
||
}
|
||
|
||
/* And print out the error via a desktop message box */
|
||
WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, errorStr, "Error", E4MSGBOXID, MB_OK | MB_MOVEABLE | MB_CUACRITICAL ) ;
|
||
WinDestroyMsgQueue( e4hmq );
|
||
WinTerminate(e4hab) ;
|
||
#endif /* E4ERROR_OFF */
|
||
}
|
||
|
||
#endif /* S4OS2PM */
|
||
|
||
#ifdef S4WINDOWS
|
||
|
||
/* S4WINDOWS */
|
||
void error4out( CODE4 *c4, int errCode1, long errCode2, const char *desc1, const char *desc2, const char *desc3 )
|
||
{
|
||
#ifndef E4ERROR_OFF
|
||
char errorStr[257] ;
|
||
const char *ptr, *errPtr ;
|
||
#endif
|
||
int pos=0, descNumber = 1 ;
|
||
#ifdef S4TESTING
|
||
#ifdef S4SERVER
|
||
WORD wType ;
|
||
#endif
|
||
#else
|
||
WORD wType ;
|
||
#endif
|
||
#ifndef E4ERROR_OFF
|
||
#ifndef E4OFF_STRING
|
||
const char *tPtr ;
|
||
#endif
|
||
#endif
|
||
|
||
if ( c4 != 0 )
|
||
c4->errorCode = errCode1 ;
|
||
|
||
#ifndef E4ERROR_OFF
|
||
if ( c4 != 0 )
|
||
if ( c4->errOff )
|
||
return ;
|
||
|
||
if (errCode1 != 0)
|
||
{
|
||
memset( errorStr, ' ', sizeof( errorStr ) - 1 ) ;
|
||
|
||
strcpy( errorStr, E4_ERROR ) ;
|
||
strcat( errorStr, " #: " ) ;
|
||
c4ltoa45( (long)errCode1, (char *)errorStr+9, 5 ) ;
|
||
pos = 31 ;
|
||
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
|
||
strcpy( errorStr + pos, E4_ERROR ) ;
|
||
strcat( errorStr + pos, " #: " ) ;
|
||
errorStr[strlen(errorStr)] = ' ' ;
|
||
c4ltoa45( error4number2( errCode2 ), (char *)errorStr + pos + 9, 6 ) ;
|
||
pos += 16 ;
|
||
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
|
||
errPtr = e4text( errCode1 ) ;
|
||
if ( errPtr != 0 )
|
||
{
|
||
strcpy( errorStr + pos, errPtr ) ;
|
||
pos += strlen( errPtr ) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
|
||
#ifndef E4OFF_STRING
|
||
tPtr = error4text( c4, errCode2 ) ;
|
||
if ( tPtr != 0 )
|
||
{
|
||
strcpy( errorStr + pos, tPtr ) ;
|
||
pos += strlen( tPtr ) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
#endif
|
||
|
||
}
|
||
|
||
ptr = desc1 ;
|
||
while ( (ptr != (char *) 0) && (descNumber <= 3 ) )
|
||
{
|
||
if ( strlen( desc1 ) + pos + 3 >= sizeof( errorStr ) )
|
||
break ;
|
||
strcpy( errorStr+pos, ptr ) ;
|
||
pos += strlen(ptr) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
if ( descNumber++ == 1 )
|
||
ptr = desc2 ;
|
||
else
|
||
ptr = desc3 ;
|
||
}
|
||
|
||
#ifdef E4FILE_LINE
|
||
if ( s4fileName != 0 )
|
||
if ( strlen(s4fileName)+pos+8 < sizeof(errorStr) )
|
||
{
|
||
strcpy( errorStr + pos, s4fileName ) ;
|
||
pos += strlen( s4fileName ) ;
|
||
errorStr[pos++] = ' ' ;
|
||
c4ltoa45( s4lineNo, (char *)errorStr+pos, 6 ) ;
|
||
pos += 6 ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
#endif
|
||
|
||
errorStr[pos] = 0 ;
|
||
|
||
#ifdef S4TESTING
|
||
u4writeErr( errorStr, 1 ) ;
|
||
#endif
|
||
|
||
OemToAnsi( errorStr, errorStr ) ;
|
||
|
||
#ifdef S4TESTING
|
||
#ifdef S4SERVER
|
||
wType = MB_OK | MB_ICONSTOP ;
|
||
if ( errCode1 == e4memory )
|
||
wType |= MB_SYSTEMMODAL ;
|
||
/* server should not error, so ok to leave in */
|
||
if ( MessageBox( 0, errorStr, E4_ERROR_COD, wType ) == 0 )
|
||
FatalAppExit( 0, E4_MEMORY_ERR ) ;
|
||
#endif
|
||
#else
|
||
wType = MB_OK | MB_ICONSTOP ;
|
||
if ( errCode1 == e4memory )
|
||
wType |= MB_SYSTEMMODAL ;
|
||
if ( MessageBox( 0, errorStr, E4_ERROR_COD, wType ) == 0 )
|
||
FatalAppExit( 0, E4_MEMORY_ERR ) ;
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
#endif /* S4WINDOWS */
|
||
|
||
#ifdef S4VB_DOS
|
||
|
||
/* S4VB_DOS */
|
||
void error4out( CODE4 *c4, int errCode1, long errCode2, const char *desc1, const char *desc2, const char *desc3 )
|
||
{
|
||
|
||
}
|
||
#endif /* S4VB_DOS */
|
||
|
||
#ifdef S4CONSOLE
|
||
|
||
/* S4CONSOLE */
|
||
void error4out( CODE4 *c4, int errCode1, long errCode2, const char *desc1, const char *desc2, const char *desc3 )
|
||
{
|
||
#ifdef S4TESTING
|
||
char errorStr[257] ;
|
||
const char *errPtr ;
|
||
int pos=0 ;
|
||
#endif
|
||
#ifndef E4ERROR_OFF
|
||
#ifndef E4OFF_STRING
|
||
char const *tPtr ;
|
||
#endif
|
||
#endif
|
||
char const * ptr ;
|
||
int descNumber = 1 ;
|
||
|
||
if ( c4 != 0 )
|
||
c4->errorCode = errCode1 ;
|
||
|
||
#ifndef E4ERROR_OFF
|
||
if ( c4 != 0 )
|
||
if ( c4->errOff )
|
||
return ;
|
||
|
||
#ifdef S4TESTING
|
||
if (errCode1 != 0)
|
||
{
|
||
memset( errorStr, ' ', sizeof( errorStr ) - 1 ) ;
|
||
|
||
strcpy( errorStr, E4_ERROR ) ;
|
||
strcat( errorStr, " #: " ) ;
|
||
c4ltoa45( (long)errCode1, (char *)errorStr+9, 5 ) ;
|
||
pos = 31 ;
|
||
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
|
||
strcpy( errorStr + pos, E4_ERROR ) ;
|
||
strcat( errorStr + pos, " #: " ) ;
|
||
errorStr[strlen(errorStr)] = ' ' ;
|
||
c4ltoa45( error4number2( errCode2 ), (char *)errorStr + pos + 9, 6 ) ;
|
||
pos += 16 ;
|
||
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
|
||
errPtr = e4text( errCode1 ) ;
|
||
if ( errPtr != 0 )
|
||
{
|
||
strcpy( errorStr + pos, errPtr ) ;
|
||
pos += strlen( errPtr ) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
|
||
#ifndef E4OFF_STRING
|
||
tPtr = error4text( c4, errCode2 ) ;
|
||
if ( tPtr != 0 )
|
||
{
|
||
strcpy( errorStr + pos, tPtr ) ;
|
||
pos += strlen( tPtr ) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
#endif
|
||
|
||
}
|
||
|
||
ptr = desc1 ;
|
||
while ( (ptr != (char *) 0) && (descNumber <= 3 ) )
|
||
{
|
||
if ( strlen( desc1 ) + pos + 3 >= sizeof( errorStr ) )
|
||
break ;
|
||
strcpy( errorStr+pos, ptr ) ;
|
||
pos += strlen(ptr) ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
if ( descNumber++ == 1 )
|
||
ptr = desc2 ;
|
||
else
|
||
ptr = desc3 ;
|
||
}
|
||
|
||
#ifdef E4FILE_LINE
|
||
if ( s4fileName != 0 )
|
||
if ( strlen(s4fileName)+pos+8 < sizeof(errorStr) )
|
||
{
|
||
strcpy( errorStr + pos, s4fileName ) ;
|
||
pos += strlen( s4fileName ) ;
|
||
errorStr[pos++] = ' ' ;
|
||
c4ltoa45( s4lineNo, (char *)errorStr+pos, 6 ) ;
|
||
pos += 6 ;
|
||
errorStr[pos++] = '\r' ;
|
||
errorStr[pos++] = '\n' ;
|
||
}
|
||
#endif
|
||
|
||
errorStr[pos] = 0 ;
|
||
|
||
u4writeErr( errorStr, 1 ) ;
|
||
#else
|
||
if (errCode1 != 0)
|
||
{
|
||
fprintf( stderr, E4_ERROR_NUM ) ;
|
||
fprintf( stderr, " %d, %ld \r\n", errCode1, error4number2( errCode2 ) ) ;
|
||
ptr = e4text( errCode1 ) ;
|
||
if ( ptr != 0 )
|
||
fprintf( stderr, "%s\r\n",e4text( errCode1 ) ) ;
|
||
#ifndef E4OFF_STRING
|
||
tPtr = error4text( c4, errCode2 ) ;
|
||
if ( tPtr != 0 )
|
||
fprintf( stderr, "%s\r\n",error4text( c4, errCode2 ) ) ;
|
||
#endif
|
||
}
|
||
|
||
ptr = desc1 ;
|
||
while ( (ptr != (char *) 0) && (descNumber <= 3 ) )
|
||
{
|
||
fprintf( stderr, "\r\r\n" ) ;
|
||
fprintf( stderr, ptr ) ;
|
||
if ( descNumber++ == 1 )
|
||
ptr = desc2 ;
|
||
else
|
||
ptr = desc3 ;
|
||
}
|
||
|
||
fprintf( stderr, "\r\r\n" ) ;
|
||
#ifdef E4FILE_LINE
|
||
if ( s4fileName != 0 )
|
||
fprintf( stderr, "File: %s Line:%d\r\r\n", s4fileName, s4lineNo ) ;
|
||
#endif
|
||
#endif /* S4TESTING */
|
||
|
||
#endif /* E4ERROR_OFF */
|
||
}
|
||
#endif
|
||
|
||
#ifdef E4FILE_LINE
|
||
/* use globals to hold the current file name and line number */
|
||
const char *s4fileName = 0 ;
|
||
int s4lineNo = 0 ;
|
||
|
||
#ifdef S4WINDOWS
|
||
int S4FUNCTION code4lineNo( void )
|
||
{
|
||
return s4lineNo ;
|
||
}
|
||
|
||
const char *S4FUNCTION code4fileName( void )
|
||
{
|
||
return s4fileName ;
|
||
}
|
||
|
||
void S4FUNCTION code4lineNoSet( int val )
|
||
{
|
||
s4lineNo = val ;
|
||
}
|
||
|
||
void S4FUNCTION code4fileNameSet( const char *ptr )
|
||
{
|
||
s4fileName = ptr ;
|
||
}
|
||
#endif
|
||
#endif
|
||
|
||
#ifndef E4FILE_LINE
|
||
/*int S4FUNCTION e4( CODE4 *c4, int errCode, const char *desc )*/
|
||
/*{*/
|
||
/* return error4describe( c4, errCode, 0L, desc, 0, 0 ) ;*/
|
||
/*}*/
|
||
#endif
|
||
|
||
#ifdef E4STACK
|
||
int S4FUNCTION error4stackDefault( CODE4 *c4, const int errCode1, const long errCode2 )
|
||
{
|
||
return error4describeExecute( c4, errCode1, errCode2, 0, 0, 0 ) ;
|
||
}
|
||
#endif
|
||
|
||
int S4FUNCTION error4default( CODE4 *c4, const int errCode1, const long errCode2 )
|
||
{
|
||
return error4describeExecute( c4, errCode1, errCode2, 0, 0, 0 ) ;
|
||
}
|
||
|
||
int S4FUNCTION error4describeDefault( CODE4 *c4, const int errCode1, const long errCode2, const char *s1, const char *s2, const char *s3 )
|
||
{
|
||
return error4describeExecute( c4, errCode1, errCode2, s1, s2, s3 ) ;
|
||
}
|
||
|
||
int S4FUNCTION error4describeExecute( CODE4 *c4, const int errCode1, const long errCode2, const char *s1, const char *s2, const char *s3 )
|
||
{
|
||
#ifdef E4HOOK
|
||
#ifndef S4SERVER
|
||
if ( c4 != 0 )
|
||
{
|
||
c4->errorCode = errCode1 ;
|
||
c4->errorCode2 = errCode2 ;
|
||
}
|
||
#endif
|
||
|
||
error4hook( c4, errCode1, errCode2, s1, s2, s3 ) ;
|
||
return errCode1 ;
|
||
#else
|
||
/* display error local to operating system */
|
||
if ( c4 != 0 )
|
||
if ( c4->errorLog != 0 )
|
||
if ( c4->errorLog->hand > 0 )
|
||
error4logAppend( c4, errCode1, errCode2, s1, s2, s3 ) ;
|
||
error4out( c4, errCode1, errCode2, s1, s2, s3 ) ;
|
||
if ( c4 != 0 )
|
||
{
|
||
#ifndef E4ERROR_OFF
|
||
#ifdef S4CONSOLE
|
||
#ifdef E4PAUSE
|
||
if ( c4->errOff == 0 )
|
||
error4pause() ;
|
||
#endif
|
||
#endif
|
||
#endif
|
||
c4->errorCode = errCode1 ;
|
||
c4->errorCode2 = errCode2 ;
|
||
}
|
||
|
||
#ifdef E4STOP
|
||
code4exit( c4 ) ;
|
||
#endif
|
||
|
||
#ifdef E4STOP_CRITICAL
|
||
if ( c4 == 0 )
|
||
code4exit( c4 ) ;
|
||
switch ( errCode1 )
|
||
{
|
||
case e4info:
|
||
case e4memory:
|
||
case e4parm:
|
||
case e4parm_null:
|
||
case e4result:
|
||
case e4struct:
|
||
code4exit( c4 ) ;
|
||
}
|
||
#endif
|
||
|
||
if ( errCode1 == e4demo )
|
||
code4exit( c4 ) ;
|
||
|
||
return errCode1 ;
|
||
#endif
|
||
}
|
||
|
||
#ifndef S4SERVER
|
||
void S4FUNCTION error4exitTest( CODE4 *c4 )
|
||
{
|
||
if ( c4 == 0 )
|
||
return ;
|
||
if ( error4code( c4 ) < 0 )
|
||
code4exit( c4 ) ;
|
||
}
|
||
#endif /* S4SERVER */
|
||
|
||
#ifdef S4CB51
|
||
#ifndef S4SERVER
|
||
void S4FUNCTION e4severe( const int errCode, const char *desc )
|
||
{
|
||
#ifdef E4HOOK
|
||
error4hook( 0, errCode, 0, desc, 0, 0 ) ;
|
||
#else
|
||
error4out( 0, errCode, 0, desc, 0, 0 ) ;
|
||
#ifdef S4CONSOLE
|
||
#ifdef E4PAUSE
|
||
error4pause() ;
|
||
#endif
|
||
#endif
|
||
#endif
|
||
code4exit( 0 ) ;
|
||
}
|
||
#endif
|
||
|
||
int S4FUNCTION e4describe( CODE4 *c4, int errCode, const char *s1, const char *s2, const char *s3 )
|
||
{
|
||
return error4describe( c4, errCode, 0L, s1, s2, s3 ) ;
|
||
}
|
||
#endif
|