campo-sirio/cb/source/c4code.c

2598 lines
60 KiB
C
Raw Normal View History

/* c4code.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
#include "d4all.h"
#ifdef __TURBOC__
#pragma hdrstop
#endif /* __TUROBC__ */
#ifdef S4WINTEL
#include <process.h>
#endif /* S4WINTEL */
#if S4VERSION != 6001
#error Your CodeBase source version does not match your header file version.
#endif
#ifdef S4TESTING
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#endif
#ifdef S4WINTEL
#ifdef __TURBOC__
#pragma hdrstop
#ifndef __DLL__
#ifndef S4OS2PM
#ifndef S4WIN32
#ifndef S4WINDOWS
extern unsigned _stklen ;
#endif
#endif
#endif
#endif
#endif
#ifdef _MSC_VER
#ifndef __DLL__
#include <malloc.h>
#endif
#endif
#endif
#ifdef S4CBPP
#ifdef __cplusplus
#include "d4data.hpp"
#endif
#endif
#ifdef S4TESTING
FILE4 s4test ;
#else
#ifdef S4TRACK_FILES
FILE4 s4test ;
#endif
#endif
char f4memoNullChar = '\0' ;
char *expr4buf = 0 ;
static unsigned int numCode4 = 0 ; /* used to determine when mem4reset() should be called */
int code4numCodeBase( void )
{
return numCode4 ;
}
#ifdef S4SEMAPHORE
#ifdef S4OS2
#include <time.h>
static char sem4mem[20], sem4expr[20] ;
static HMTX hmtx4mem, hmtx4expr ;
#endif
#endif
#ifdef S4IBMOS2
#ifdef S4OS2DLL
#ifndef __MULTI__ /* no multi-thread code is being produced */
int errno = 0 ;
#endif
#endif
#endif
#ifdef __DLL__
#ifdef S4PASCAL
#ifndef S4WIN32
typedef char far* LPSTR ;
typedef unsigned int HANDLE ;
typedef unsigned short WORD ;
#define PASCAL _pascal
#define S4USE_WEP
#endif
#endif
#ifndef S4PASCAL_DOS
#ifdef S4DLL
HINSTANCE cb5inst = (HINSTANCE)NULL ;
#endif
#endif
#ifdef S4OS2
ULONG _dllmain (ULONG termflag, HMODULE modhandle)
{
#ifdef S4SEMAPHORE
int i ;
APIRET rc ;
time_t t ;
#endif
if ( termflag == 0 )
{
#ifdef S4SEMAPHORE
strcpy( sem4expr, "\\SEM32\\S4A" ) ;
strcpy( sem4mem, "\\SEM32\\S4B" ) ;
for ( i = 0 ; i < 100 ; i++ )
{
u4delaySec() ;
time( &t ) ;
t %= 10000L ;
c4ltoa45( t, sem4expr + 10, -4 ) ;
c4ltoa45( t, sem4mem + 10, -4 ) ;
rc = DosCreateMutexSem( sem4expr, &hmtx4expr, 0, 0 ) ;
if ( rc != 0 )
continue ;
rc = DosCreateMutexSem( sem4mem, &hmtx4mem, 0, 0 ) ;
if ( rc != 0 )
{
DosCloseMutexSem( hmtx4expr ) ;
continue ;
}
return 1 ;
}
#else
return 1 ;
#endif
}
else
{
#ifdef S4SEMAPHORE
DosCloseMutexSem( hmtx4mem ) ;
DosCloseMutexSem( hmtx4expr ) ;
#endif
}
return 1 ;
}
#endif
#ifdef S4PASCAL_DOS
/* 20-file handle fix for Pascal DOS */
void setfilemax (void) ;
#pragma startup setfilemax 0
#ifdef P4ARGS_USED
#pragma argsused
#endif
void setfilemax (void)
{
asm
{
/*; If default number of file handles have changed then tell DOS*/
cmp _nfile, 20
jbe NoChange
cmp [_osmajor], 3 ;/* Check for >= DOS 3.3*/
jb NoChange
ja DoChange
cmp [_osminor], 1Eh
jb NoChange
}
DoChange:
asm
{
mov ax, 5801h /*; Set last fit allocation*/
mov bx, 2
int 21h
jc BadInit
mov ah, 67h /*; Expand handle table*/
mov bx, _nfile
int 21h
jc BadInit
mov ax, 5801h /*; Set first fit allocation*/
mov bx, 0
int 21h
jnc NoChange
}
BadInit:
abort () ;
NoChange:
return ;
}
int far PASCAL LibMain( HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize, LPSTR lpCmdLine )
{
_nfile = 255 ;
setfilemax() ;
return 1 ;
}
#endif /* S4PASCAL_DOS */
#ifndef S4WIN32
#ifndef S4PASCAL_DOS
#ifdef S4WINDOWS
#ifdef P4ARGS_USED
#pragma argsused
#endif
int far PASCAL LibMain( HINSTANCE hInstance, WORD wDataSeg, WORD cbHeapSize, LPSTR lpCmdLine )
{
if ( !cb5inst )
cb5inst = hInstance ;
return 1 ;
}
#endif /* S4WINDOWS */
#endif /* S4PASCAL_DOS */
#ifdef P4ARGS_USED
#pragma argsused
#endif
int S4FUNCTION WEP( int nParameter )
{
return 1 ;
}
#else
BOOL APIENTRY DllMain( HANDLE hModule, DWORD reasonForCall, LPVOID reserved )
{
if ( !cb5inst )
cb5inst = hModule ;
return 1 ;
}
#endif /* S4WIN32 */
#ifndef S4PASCAL_DOS
HINSTANCE S4FUNCTION c4dllInst( void )
{
return cb5inst ;
}
#endif /* S4PASCAL_DOS */
#endif /* __DLL__ */
#ifndef S4OFF_COMMUNICATIONS
#ifndef S4SERVER
static int code4userConnect( CODE4 *c4, const char *userName, const char *password )
{
int rc ;
long version ;
CONNECTION4 *connection ;
static char defaultUser[] = "PUBLIC" ;
if ( c4->defaultServer == 0 )
return 0 ;
connection = c4->defaultServer->connect ;
if ( connection == 0 )
return 0 ;
if ( userName == 0 )
userName = defaultUser ;
else
if ( userName[0] == 0 )
userName = defaultUser ;
if ( password == 0 )
password = "" ;
connection4assign( connection, CON4CONNECT, 0L, 0L ) ;
version = S4VERSION ;
connection4addData( connection, &version, sizeof( version ), 0 ) ;
connection4addData( connection, userName, strlen( userName ) + 1, 0 ) ;
connection4addData( connection, password, strlen( password ) + 1, 0 ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
return rc ;
rc = connection4status( connection ) ;
if ( rc < 0 )
connection4error( connection, c4, rc, E91005 ) ;
return rc ;
}
int S4FUNCTION code4connect( CODE4 *c4, const char *serverId, const char *processId, const char *userName, const char *password, const char *protocol )
{
int rc ;
#ifndef S4DOS
int len ;
#endif
#ifdef S4VBASIC
if ( c4parm_check( c4, 1, E91004 ) )
return 0 ;
#endif
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return error4( 0, e4parm_null, E91004 ) ;
#endif
if ( c4->defaultServer != 0 )
return r4connected ;
#ifndef S4DOS
if ( c4->protocol[0] == 0 )
{
if ( protocol == 0 )
return error4( 0, e4parm_null, E81005 ) ;
if ( protocol[0] == 0 )
return error4( 0, e4parm_null, E81005 ) ;
}
if ( protocol != 0 )
if ( protocol[0] != 0 )
{
len = strlen( protocol ) ;
#ifdef E4PARM_HIGH
if ( len > LEN4PROTOCOL )
return error4( 0, e4parm, E81005 ) ;
#endif
memcpy( c4->protocol, protocol, len ) ;
c4->protocol[len] = 0 ;
}
#endif
c4->defaultServer = socket4alloc( c4 ) ;
if ( c4->defaultServer == 0 )
return error4( c4, e4connection, E81001 ) ;
if ( serverId == 0 )
serverId = DEF4SERVER_ID ;
else
if ( serverId[0] == 0 )
serverId = DEF4SERVER_ID ;
if ( processId == 0 )
processId = DEF4PROCESS_ID ;
else
if ( processId[0] == 0 )
processId = DEF4PROCESS_ID ;
rc = socket4init( c4->defaultServer, c4, serverId, processId ) ;
if ( rc == 0 )
rc = socket4connect( c4->defaultServer, serverId, processId ) ;
#ifndef S4UTILS
if ( rc == 0 )
rc = code4userConnect( c4, userName, password ) ;
#endif
if ( rc != 0 )
{
socket4initUndo( c4->defaultServer ) ;
socket4free( c4->defaultServer ) ;
c4->defaultServer = 0 ;
return rc ;
}
return 0 ;
}
#ifdef S4UTIL
int S4FUNCTION code4passwordSet( CODE4 *c4, const char *userId, const char *oldPass, const char *newPass ) ;
{
CONNECTION4 *connection ;
unsigned short int len[3] ;
#ifdef E4PARM_HIGH
if ( userId == 0 || oldPass == 0 || newPass == 0 )
return error4( c4, e4parmNull, E91017 ) ;
#endif
connection = c4->defaultServer->connect ;
if ( connection == 0 ) /* not connected */
return error4( c4, e4connection, E91017 ) ;
connection4assign( connection, CON4PASSWORD_SET, 0L, 0L ) ;
len[0] = strlen( userId ) ;
len[1] = strlen( oldPass ) ;
len[2] = strlen( newPass ) ;
connection4send( connection ) ;
connection4addData( connection, len, sizeof( len ), 0 ) ;
connection4addData( connection, userId, len[0], 0 ) ;
connection4addData( connection, oldPass, len[1], 0 ) ;
connection4addData( connection, newPass, len[2], 0 ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
return rc ;
return connection4status( connection ) ;
}
#endif /* S4UTIL */
#endif /* S4SERVER */
#endif /* S4OFF_COMMUNICATIONS */
#ifdef P4ARGS_USED
#pragma argsused
#endif
int S4FUNCTION code4initLow( CODE4 *c4, const char *defaultProtocol, long versionId )
{
char v1[10], v2[10] ;
#ifdef S4WINDOWS
int n;
#endif
#ifdef S4TESTING
int exclusiveFlag ;
int openFlag ;
char *envLog ;
#ifdef S4CASE_SEN
char *logFile = "T4TEST.log" ;
#else
char *logFile = "T4TEST.LOG" ;
#endif
#else
#ifdef S4TRACK_FILES
int openFlag ;
char *envLog ;
#ifdef S4CASE_SEN
char *logFile = "T4TEST.log" ;
#else
char *logFile = "T4TEST.LOG" ;
#endif
#endif
#endif
#ifndef S4SERVER
int rc ;
#endif
#ifdef S4CLIENT
#ifndef S4DOS
int len ;
#endif
#endif
#ifndef S4OFF_OPTIMIZE
#ifdef S4OPTIMIZE_STATS
DATA4 *stat ;
int oldOffErr ;
#endif
#endif
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return error4( 0, e4parm, E91001 ) ;
#endif
/***********************************************************************
This code must reside at the beginning of the function to ensure that
no file open/create incorrectly auto-starts the optimization process
***********************************************************************/
#ifdef S4WINDOWS
n = SetHandleCount(40);
#endif
#ifndef S4OFF_OPTIMIZE
c4->hadOpt = 1 ;
#endif
#ifdef S4TESTING
if ( numCode4 == 0 )
{
memset( &s4test, 0, sizeof( s4test ) ) ;
s4test.hand = -1 ;
}
#else
#ifdef S4TRACK_FILES
if ( numCode4 == 0 )
{
memset( &s4test, 0, sizeof( s4test ) ) ;
s4test.hand = -1 ;
}
#endif
#endif
if ( versionId != S4VERSION )
{
c4ltoa45( e4version, v1, sizeof( v1 ) ) ;
c4ltoa45( S4VERSION, v2, sizeof( v2 ) ) ;
return error4describe( c4, e4version, E91001, v1, v2, 0 ) ;
}
memset( (void *)c4, 0, sizeof( CODE4 ) ) ;
/* if a DLL, can't check the stack length since this is a separate executable */
#ifndef S4WIN32
#ifndef S4WINDOWS
#ifndef __DLL__
#ifdef __TURBOC__
#ifndef S4OS2PM
if ( _stklen < 5000U ) /* 5000 seems to be an appropriate minimum */
return error4( c4, e4result, E81003 ) ;
#endif
#endif
#endif
#ifdef _MSC_VER
if ( stackavail() < 5000U )
error4( c4, e4result, E81003 ) ;
#endif
#endif
#endif
if ( numCode4 == 0 )
mem4init() ;
numCode4++ ;
#ifdef E4ANALYZE
c4->debugInt = E4DEBUG_INT ; /* Some random value for double checking. */
#else
#ifdef S4VBASIC
c4->debugInt = E4DEBUG_INT ; /* Some random value for double checking. */
#endif /* S4VBASIC */
#endif /* E4MISC */
#ifndef S4OFF_MEMO
c4->memSizeMemoExpr = 0x400 ; /* 1024 */
#endif
c4->numericStrLen = 17 ; /* default length for clipper numeric keys is 10 */
c4->decimals = 2 ;
/* Flags initialization */
c4->errCreate = 1 ;
c4->errDefaultUnique = r4uniqueContinue ;
c4->errExpr = 1 ;
c4->errFieldName = 1 ;
c4->errOpen = 1 ;
#ifndef S4OFF_INDEX
c4->errTagName = 1 ;
#endif
c4->autoOpen = 1 ;
c4->safety = 1 ;
#ifndef S4OFF_MULTI
c4->lockDelay = 100 ;
#endif
c4->collatingSequence = sort4machine ; /* default to FoxPro 2.x values */
c4->codePage = cp0 ;
c4->memStartDataFile = 5 ;
c4->memExpandDataFile = 5 ;
#ifndef S4OFF_INDEX
c4->memStartTagFile = 10 ;
c4->memExpandTagFile =5 ;
#endif
#ifndef S4SINGLE
c4->memStartLock = 5 ;
c4->memExpandLock = 10 ;
#endif
#ifndef N4OTHER
c4->memStartIndexFile = 5 ;
c4->memExpandIndexFile = 5 ;
#endif
#ifndef S4OFF_MULTI
c4->lockAttemptsSingle = 1 ;
#endif
#ifdef S4SERVER
#ifdef S4DEBUG_LOG
c4->logFile.hand = -1 ;
#endif
c4->lockAttempts = 1 ;
c4->memStartClient = 5 ;
c4->memExpandClient = 5 ;
#ifdef N4OTHER
c4->memStartIndex = 10 ;
c4->memStartTag = 10 ;
c4->memExpandIndex = 5 ;
c4->memExpandTag = 10 ;
#endif
#else
c4->errGo = 1 ;
c4->errSkip = 1 ;
c4->errRelate = 1 ;
#ifndef S4OFF_MULTI
c4->lockAttempts = WAIT4EVER ; /* wait forever */
#endif
c4->singleOpen = 1 ;
#ifndef S4OFF_ENFORCE_LOCK
c4->lockEnforce = 0 ;
#endif
#ifdef S4OFF_OPTIMIZE
#ifndef S4OFF_INDEX
c4->memSizeBlock = 0x400 ; /* 1024 */
#endif
#else
c4->memSizeBlock = 0x400 ; /* 1024 */
#endif
c4->memSizeSortPool = 0xF000 ; /* 61440 */
c4->memSizeSortBuffer = 0x1000 ; /* 4096 */
c4->memSizeBuffer = 0x8000 ; /* 32768 */
#ifndef S4OFF_MEMO
c4->memSizeMemo = 0x200 ; /* 512 */
#endif
c4->memStartData = 10 ;
c4->memExpandData = 5 ;
#ifndef S4OFF_INDEX
c4->memExpandBlock = 10 ;
c4->memStartBlock = 10 ;
c4->memStartIndex = 10 ;
c4->memStartTag = 10 ;
c4->memExpandIndex = 5 ;
c4->memExpandTag = 10 ;
#endif
#endif
#ifdef S4CLIENT
#ifndef S4DOS
if ( defaultProtocol != 0 )
{
len = strlen( defaultProtocol ) ;
#ifdef E4PARM_HIGH
if ( len > LEN4PROTOCOL )
return error4( 0, e4parm, E81005 ) ;
#endif
memcpy( c4->protocol, defaultProtocol, len ) ;
c4->protocol[len] = 0 ;
}
#endif
#else
c4->doIndexVerify = 1 ;
#endif
#ifndef S4OFF_TRAN
#ifndef S4OFF_WRITE
#ifndef S4CIENT
c4->log = LOG4ON ;
#endif
#ifdef S4STAND_ALONE
c4->logOpen = 1 ;
#endif
#endif
#endif
#ifndef S4OFF_COMMUNICATIONS
#ifdef S4TIMEOUT_HOOK
c4->timeout = 100 ;
#else
c4->timeout = -1 ;
#endif
#endif
#ifndef S4OPTIMIZE_OFF
c4->doOpt = 1 ; /* by default do optimization */
#ifndef S4SERVER
c4->optimize = OPT4EXCLUSIVE ; /* by default optimize non-shared files */
c4->optimizeWrite = OPT4EXCLUSIVE ;
#endif /* S4SERVER */
#endif /* not S4OPTIMIZE_OFF */
#ifndef S4SERVER
rc = code4tranInit( c4 ) ;
if ( rc < 0 )
return error4( c4, rc, E91001 ) ;
#ifndef S4OFF_COMMUNICATIONS
c4->clientDataCount = 1 ;
#endif
#ifndef S4LANGUAGE
code4dateFormatSet( c4, "MM/DD/YY" ) ;
#else
#ifdef S4GERMAN
code4dateFormatSet( c4, "DD.MM.YY" ) ;
#endif
#ifdef S4FRENCH
code4dateFormatSet( c4, "MM/DD/YY" ) ;
#endif
#ifdef S4SWEDISH
code4dateFormatSet( c4, "YYYY-MM-DD" ) ;
#endif
#ifdef S4FINNISH
code4dateFormatSet( c4, "YYYY-MM-DD" ) ;
#endif
#ifdef S4NORWEGIAN
code4dateFormatSet( c4, "DD-MM-YYYY" ) ;
#endif
#endif
#endif
c4->initialized = 1 ;
if ( numCode4 == 1 )
{
#ifdef S4TESTING
openFlag = c4->errOpen ;
exclusiveFlag = c4->accessMode ;
c4->errOpen = 0 ;
c4->accessMode = OPEN4DENY_NONE ;
envLog = getenv( "T4LOG" ) ;
if ( envLog ) /* if env. var. exists, use it */
logFile = envLog ;
if ( file4open( &s4test, c4, logFile, 0 ) != r4success )
file4create( &s4test, c4, logFile, 0 ) ;
c4->accessMode = exclusiveFlag ;
c4->errOpen = openFlag ;
#else
#ifdef S4TRACK_FILES
openFlag = c4->errOpen ;
c4->errOpen = 0 ;
envLog = getenv( "CB51_LOG" ) ;
if ( envLog ) /* if env. var. exists, use it */
logFile = envLog ;
if ( file4open( &s4test, c4, logFile, 0 ) != r4success )
file4create( &s4test, c4, logFile, 0 ) ;
c4->errOpen = openFlag ;
#endif
#endif
}
#ifndef S4SERVER
#ifndef S4SINGLE
#ifdef S4CB51
code4unlockAutoSet( c4, LOCK4DATA ) ;
#else
code4unlockAutoSet( c4, LOCK4ALL ) ;
#endif
#endif
#endif
#ifndef S4OFF_OPTIMIZE
#ifdef S4OPTIMIZE_STATS
stat = c4->statusDbf ;
if ( stat == 0 ) /* open the stat database */
{
oldOffErr = c4->errOpen ;
c4->errOpen = 0 ;
c4->statusDbf = d4open( c4, "OPT4STAT" ) ;
c4->errOpen = oldOffErr ;
stat = c4->statusDbf ;
if ( stat == 0 )
error4set( c4, 0 ) ;
else
{
d4optimize( stat, OPT4OFF ) ;
c4->typeFld = d4field( stat, "TYPE" ) ;
c4->fileNameFld = d4field( stat, "FILE_NAME" ) ;
c4->offsetFld = d4field( stat, "OFFSET" ) ;
c4->lengthFld = d4field( stat, "LENGTH" ) ;
if ( c4->typeFld == 0 || c4->fileNameFld == 0 || c4->offsetFld == 0 || c4->lengthFld == 0 )
{
d4close( stat ) ;
c4->statusDbf = 0 ;
}
}
}
#endif
#endif /* S4OFF_OPTIMIZE */
#ifdef S4WRITE_DELAY
/* if the begin thread fails, then delay-writes are simply not enabled,
which is ok because it will simply be bypassed. */
InitializeCriticalSection( &c4->critical4delayWriteList ) ;
c4->pendingWriteEvent = CreateEvent( 0, TRUE, FALSE, 0 ) ;
if ( c4->pendingWriteEvent != INVALID_HANDLE_VALUE )
{
/* cast unsigned long to long for BORLAND C++ avoid warning message
(verified with Borland) */
if ( (long)_beginthread( file4writeDelayMain, 5000, c4 ) == -1 )
{
CloseHandle( c4->pendingWriteEvent ) ;
DeleteCriticalSection( &c4->critical4delayWriteList ) ;
}
else
while ( c4->delayWritesEnabled != 1 ) /* ensure thread starts to avoid initUndo thread corruptions */
Sleep( 0 ) ;
}
#endif
#ifdef S4READ_ADVANCE
/* if the begin thread fails, then delay-writes are simply not enabled,
which is ok because it will simply be bypassed. */
InitializeCriticalSection( &c4->critical4advanceReadList ) ;
c4->pendingReadEvent = CreateEvent( 0, TRUE, FALSE, 0 ) ;
if ( c4->pendingReadEvent != INVALID_HANDLE_VALUE )
{
/* cast unsigned long to long for BORLAND C++ avoid warning message
(verified with Borland) */
if ( (long)_beginthread( file4advanceReadMain, 5000, c4 ) == -1 )
{
CloseHandle( c4->pendingReadEvent ) ;
DeleteCriticalSection( &c4->critical4advanceReadList ) ;
}
else
while ( c4->advanceReadsEnabled != 1 ) /* ensure thread starts to avoid initUndo thread corruptions */
Sleep( 0 ) ;
}
#endif
/***********************************************************************
This code must reside at the end of the function to ensure that no
file open/create incorrectly auto-starts the optimization process
***********************************************************************/
#ifndef S4OFF_OPTIMIZE
c4->hadOpt = 1 ;
#ifdef S4SERVER
c4->memMaxPercent = -1 ; /* use server configuration file */
#else
c4->memMaxPercent = 25 ; /* default use 25% of available memory */
#endif
#ifdef S4OS2
c4->memStartMax = 0xF0000L ;
#else
#ifndef S4WINTEL
c4->memStartMax = 0xF0000L ;
#else
#ifdef S4WINDOWS
c4->memStartMax = 0xF0000L ;
#else
c4->memStartMax = 0x50000L ;
#endif /* S4WINDOWS */
#endif
#endif
#endif
return 0 ;
}
/* if doInit is set to 1, code4init() is called on the allocated CODE4 */
CODE4 *S4FUNCTION code4allocLow( int doInit, const char *defaultProtocol, long versionId )
{
CODE4 *c4 ;
#ifndef S4CBPP
c4 = (CODE4 *)u4alloc( (long)sizeof( CODE4 ) ) ;
#else
#ifdef __cplusplus
c4 = (CODE4 *)u4alloc( (long)sizeof( Code4 ) ) ;
#else
c4 = (CODE4 *)u4alloc( (long)sizeof( CODE4 ) ) ;
#endif
#endif
if ( c4 == 0 )
return 0 ;
if ( doInit == 1 )
code4initLow( c4, defaultProtocol, versionId ) ;
return c4 ;
}
void S4FUNCTION expr4calcDelete( EXPR4CALC *calc )
{
CODE4 *c4;
if( !calc || !calc->expr )
return;
c4 = calc->expr->codeBase ;
#ifndef S4SERVER
if( calc->total != 0 )
{
expr4free( calc->total->resetExpression );
l4remove( &c4->totalList, calc->total ) ;
mem4free( c4->totalMemory, calc->total ) ;
}
#endif
#ifdef S4SERVER
l4remove( &c4->currentClient->calcList, calc ) ;
#else
l4remove( &c4->calcList, calc ) ;
#endif
expr4free( calc->expr ) ;
mem4free( c4->calcMemory, calc ) ;
}
void S4FUNCTION code4calcReset( CODE4 *c4 )
{
LIST4 *list ;
#ifdef S4CLIENT
CONNECTION4 *connection ;
int rc ;
#endif
#ifdef E4PARM_HIGH
if ( c4 == 0 )
{
error4( 0, e4parm_null, E90921 ) ;
return ;
}
#endif
#ifdef S4SERVER
list = &c4->currentClient->calcList ;
#else
list = &c4->calcList ;
#endif
if( list > (LIST4 *)NULL )
{
while( list->nLink > 0 )
expr4calcDelete( (EXPR4CALC *)list->lastNode ) ;
#ifdef S4CLIENT
if ( c4->defaultServer != 0 )
{
connection = c4->defaultServer->connect ;
rc = connection4assign( connection, CON4CALC_RESET, 0, 0 ) ;
if ( rc < 0 )
return ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
return ;
rc = connection4status( connection ) ;
if ( rc < 0 )
connection4error( connection, c4, rc, E90921 ) ;
}
#endif
}
}
#ifdef S4MEM_PRINT
extern char *write4buf ;
extern FILE4SEQ_WRITE *file4seqPtr ;
#endif
static int code4initUndo2( CODE4 *c4, int doClose )
{
#ifdef S4DISTRIBUTED
#ifdef S4CLIENT
SOCKET4 *socket, *socketNext ;
#endif
#endif
#ifndef S4OFF_COMMUNICATIONS
MESSAGE4DATA *message ;
#endif
#ifndef S4SERVER
#ifndef S4OFF_TRAN
#endif
#endif
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return e4parm_null ;
#endif
if ( c4->initialized == 0 ) /* already uninitialized */
return 0 ;
#ifdef E4MISC
if ( numCode4 == 0 ) /* code4initUndo already called... */
{
if ( doClose == 1 ) /* if zero, don't error out since severe already */
return error4( 0, e4info, E81004 ) ;
else
return e4info ;
}
#endif
#ifdef S4SEMAPHORE
#ifdef S4OS2
DosCloseMutexSem( hmtx4mem ) ;
DosCloseMutexSem( hmtx4expr ) ;
#endif
#endif
#ifndef S4OPTIMIZE_OFF
code4optSuspend( c4 ) ;
#endif
#ifndef S4SERVER
#ifndef S4OFF_TRAN
#ifndef S4CLIENT
if ( code4transEnabled( c4 ) )
#endif
if ( code4tranStatus( c4 ) == r4active )
code4tranRollback( c4 ) ;
#endif
if ( doClose )
code4close( c4 ) ;
#endif
#ifndef S4SERVER
code4calcReset( c4 ) ;
#ifndef S4OFF_COMMUNICATIONS
#ifdef S4DISTRIBUTED
socketNext = (SOCKET4 *)l4first( &c4->servers ) ;
for ( ;; )
{
socket = socketNext ;
if ( socket == 0 )
break ;
socketNext = (SOCKET4 *)l4next( &c4->servers, socket ) ;
socket4initUndo( socket ) ;
l4remove( &c4->servers, socket ) ;
socket4free( socket ) ;
}
#else
if ( c4->defaultServer != 0 )
{
socket4initUndo( c4->defaultServer ) ;
socket4free( c4->defaultServer ) ;
}
#endif
c4->defaultServer = 0 ;
#endif
#ifndef S4OFF_TRAN
code4tranInitUndo( c4 ) ;
#endif
#endif
#ifdef S4OPTIMIZE_STATS
if ( c4->statusDbf != 0 )
{
d4close( c4->statusDbf ) ;
c4->statusDbf = 0 ;
}
#endif
if ( c4->version != 0 )
{
u4free( c4->version ) ;
c4->version = 0 ;
}
#ifdef S4MNDX
if ( c4->memoUseBuffer != 0 )
{
u4free( c4->memoUseBuffer ) ;
c4->memoUseBuffer = 0 ;
}
#endif
#ifdef S4WRITE_DELAY
/* set the event semaphore to terminate the delay-write thread */
if ( c4->delayWritesEnabled )
{
c4->initUndoDelayWrite = CreateEvent( 0, TRUE, FALSE, 0 ) ;
if ( c4->initUndoDelayWrite != INVALID_HANDLE_VALUE )
{
InterlockedIncrement( &c4->uninitializeDelayWrite ) ;
/* notify the write thread */
if ( SetEvent( c4->pendingWriteEvent ) == TRUE ) /* wait for the delay-write thread to uninitialize */
WaitForSingleObject( c4->initUndoDelayWrite, INFINITE ) ;
CloseHandle( c4->initUndoDelayWrite ) ;
CloseHandle( c4->pendingWriteEvent ) ;
DeleteCriticalSection( &c4->critical4delayWriteList ) ;
}
}
#endif
#ifdef S4READ_ADVANCE
/* set the event semaphore to terminate the advance-read thread */
if ( c4->advanceReadsEnabled )
{
c4->initUndoAdvanceRead = CreateEvent( 0, TRUE, FALSE, 0 ) ;
if ( c4->initUndoAdvanceRead != INVALID_HANDLE_VALUE )
{
InterlockedIncrement( &c4->uninitializeAdvanceRead ) ;
/* notify the write thread */
if ( SetEvent( c4->pendingReadEvent ) == TRUE ) /* wait for the delay-write thread to uninitialize */
WaitForSingleObject( c4->initUndoAdvanceRead, INFINITE ) ;
CloseHandle( c4->initUndoAdvanceRead ) ;
CloseHandle( c4->pendingReadEvent ) ;
DeleteCriticalSection( &c4->critical4advanceReadList ) ;
}
}
#endif
#ifndef S4OFF_INDEX
mem4release( c4->indexMemory ) ;
c4->indexMemory = 0 ;
mem4release( c4->index4fileMemory ) ;
c4->index4fileMemory = 0 ;
#endif
mem4release( c4->dataMemory ) ;
c4->dataMemory = 0 ;
mem4release( c4->data4fileMemory ) ;
c4->data4fileMemory = 0 ;
#ifndef S4OFF_MULTI
mem4release( c4->lockMemory ) ;
c4->lockMemory = 0 ;
mem4release( c4->lockLinkMemory ) ;
c4->lockLinkMemory = 0 ;
#endif
#ifndef S4OFF_INDEX
mem4release( c4->tagMemory ) ;
c4->tagMemory = 0 ;
mem4release( c4->tagFileMemory ) ;
c4->tagFileMemory = 0 ;
#endif
mem4release( c4->dataListMemory ) ;
c4->dataListMemory = 0 ;
mem4release( c4->relateDataListMemory ) ;
c4->relateDataListMemory = 0 ;
mem4release( c4->relateMemory ) ;
c4->relateMemory = 0 ;
mem4release( c4->relateListMemory ) ;
c4->relateListMemory = 0 ;
mem4release( c4->relationMemory ) ;
c4->relationMemory = 0 ;
mem4release( c4->calcMemory ) ;
c4->calcMemory = 0 ;
#ifdef S4SERVER
if ( c4->catalogClient != 0 )
{
mem4free( c4->clientMemory, c4->catalogClient ) ;
c4->catalogClient = 0 ;
}
mem4release( c4->clientMemory ) ;
c4->clientMemory = 0 ;
#endif
#ifndef S4STAND_ALONE
message4release( c4 ) ;
#endif
mem4release( c4->bitmapMemory ) ;
c4->bitmapMemory = 0 ;
if ( c4->fieldBuffer != 0 )
{
u4free( c4->fieldBuffer ) ;
c4->fieldBuffer = 0 ;
c4->bufLen = 0 ;
}
if ( c4->exprWorkBuf != 0 )
{
u4free( c4->exprWorkBuf ) ;
c4->exprWorkBuf = 0 ;
c4->exprBufLen = 0 ;
}
if ( c4->storedKey != 0 )
{
u4free( c4->storedKey ) ;
c4->storedKey = 0 ;
c4->storedKeyLen = 0 ;
}
if ( c4->errorLog != 0 )
{
if ( c4->errorLog->hand > 0 )
file4close( c4->errorLog ) ;
u4free( c4->errorLog ) ;
c4->errorLog = 0 ;
}
#ifdef E4ANALYZE
c4->debugInt = 0 ; /* Some random value for double checking. */
#endif
#ifdef S4DEBUG_LOG
#ifdef S4SERVER
code4logInitUndo( c4 ) ;
#endif
#endif
#ifndef S4OFF_TRAN
if ( c4->tranData != 0 )
{
u4free( c4->tranData ) ;
c4->tranData = 0 ;
c4->tranDataLen = 0 ;
}
#endif
#ifndef S4OFF_COMMUNICATIONS
for ( ;; )
{
message = (MESSAGE4DATA *)l4pop( &c4->availDataMessages ) ;
if ( message == 0 )
break ;
if ( message->didAlloc == 1 )
{
u4free( message->allocatedData ) ;
message->didAlloc = 0 ;
}
mem4free( c4->messageLinkMemory, message ) ;
}
mem4release( c4->messageLinkMemory ) ;
c4->messageLinkMemory = 0 ;
mem4release( c4->connectionMemory ) ;
c4->connectionMemory = 0 ;
mem4release( c4->connectionNetMemory ) ;
c4->connectionNetMemory = 0 ;
#endif
numCode4-- ;
#ifdef S4TESTING
if ( s4test.codeBase == c4 )
{
if ( s4test.hand )
{
#ifdef S4MEM_PRINT
if ( write4buf != 0 )
{
file4seqWriteFlush( file4seqPtr ) ;
u4free( write4buf ) ;
write4buf = 0 ;
}
#endif
file4close( &s4test ) ;
}
}
#else
#ifdef S4TRACK_FILES
if ( s4test.codeBase == c4 )
if ( s4test.hand )
file4close( &s4test ) ;
#endif
#endif
if ( numCode4 == 0 ) /* reset memory */
mem4reset() ;
c4->initialized = 0 ;
return error4code( c4 ) ;
}
#ifndef S4SERVER
void S4FUNCTION code4exit( CODE4 *c4 )
{
#ifndef S4WINDOWS
int rc ;
if ( c4 == 0 )
rc = -1 ;
else
{
rc = c4->errorCode ;
#endif
code4initUndo2( c4, 0 ) ;
#ifdef E4MISC
#ifdef S4TESTING
mem4freeCheck( 100 ) ;
mem4checkMemory() ;
mem4reset() ;
#endif
#endif
#ifndef S4WINDOWS
}
exit( rc ) ;
#else
#ifdef S4TESTING
u4terminate() ;
#else
FatalAppExit( 0, E4_MESSAG_EXI ) ;
#endif
#endif
}
#endif /* S4SERVER */
int S4FUNCTION code4initUndo( CODE4 *c4 )
{
#ifdef S4SERVER
return code4initUndo2( c4, 0 ) ;
#else
return code4initUndo2( c4, 1 ) ;
#endif
}
#ifndef S4SERVER
int S4FUNCTION code4close( CODE4 *c4 )
{
DATA4 *dataOn, *dataNext ;
LIST4 *list ;
#ifdef S4VBASIC
if ( c4parm_check( c4, 1, E91003 ) )
return -1 ;
#endif /* S4VBASIC */
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return error4( 0, e4parm_null, E91003 ) ;
#endif
list = tran4dataList( (&(c4->c4trans.trans)) ) ;
for ( dataNext = (DATA4 *)l4first( list ) ; ; )
{
dataOn = dataNext ;
if ( dataOn == 0 )
break ;
dataNext = (DATA4 *)l4next( list, dataNext ) ;
if ( dataOn == dataNext ) /* error -- stuck in endless loop */
return -1 ;
#ifndef S4OFF_OPTIMIZE
#ifdef S4OPTIMIZE_STATS
/* don't close the internal opt tracking dbf here. */
if ( dataOn != dataOn->codeBase->statusDbf )
#endif
#endif
d4close( dataOn ) ;
}
if ( error4code( c4 ) < 0 )
return error4code( c4 ) ;
return 0 ;
}
#endif
/* input must be in capital letters */
DATA4FILE *dfile4data( CODE4 *c4, const char *aliasName )
{
DATA4FILE *dataOn ;
#ifdef E4MISC
DATA4FILE *dataResult ;
#endif
#ifdef E4PARM_LOW
if ( c4 == 0 || aliasName == 0 )
{
error4( c4, e4parm_null, E91102 ) ;
return 0 ;
}
#endif
dataOn = 0 ;
#ifdef E4MISC
dataResult = 0 ;
#endif
for(;;)
{
dataOn = (DATA4FILE *)l4next( &c4->dataFileList, dataOn ) ;
if ( !dataOn )
break ;
if ( strcmp( aliasName, dfile4name( dataOn ) ) == 0 )
{
#ifdef E4MISC
if ( dataResult != 0 )
{
error4( c4, e4info, E83501 ) ;
return 0 ;
}
dataResult = dataOn ;
#else
return dataOn ;
#endif /* E4MISC */
}
}
#ifdef E4MISC
return dataResult ;
#else
return dataOn ;
#endif
}
#ifdef P4ARGS_USED
#pragma argsused
#endif
DATA4 *tran4dataName( TRAN4 *trans, const char *name, const long clientId, const int doPath )
{
DATA4 *dataOn ;
#ifdef E4MISC
DATA4 *dataResult ;
#endif
#ifndef S4CLIENT
char name1[258] ;
#endif
#ifdef E4ANALYZE
if ( tran4verify( trans, 1 ) < 0 )
return 0 ;
#endif
dataOn = 0 ;
#ifdef E4MISC
dataResult = 0 ;
#endif
#ifndef S4CLIENT
u4nameCurrent( name1, sizeof( name1 ), name ) ;
#ifdef S4CASE_SEN
u4nameExt( name1, sizeof( name1 ), ".dbf", 0 ) ;
#else
u4nameExt( name1, sizeof( name1 ), ".DBF", 0 ) ;
#endif
#endif
for (;; )
{
dataOn = (DATA4 *)l4next( tran4dataList( trans ), dataOn ) ;
if ( dataOn == 0 )
break ;
if ( strcmp( name, d4alias( dataOn ) ) == 0 ) /* try simple alias check */
{
#ifdef S4SERVER
if ( clientId != 0 )
dataOn->clientId = clientId ;
#endif
#ifdef E4MISC
if ( dataResult != 0 )
{
error4( trans->c4trans->c4, e4info, E83501 ) ;
return 0 ;
}
dataResult = dataOn ;
#else
return dataOn ;
#endif
}
#ifndef S4CLIENT
#ifdef E4MISC
else
#endif
/* otherwise, try file name check */
if ( doPath )
if ( strcmp( name1, dataOn->dataFile->file.name ) == 0 )
{
#ifdef S4SERVER
if ( clientId != 0 )
dataOn->clientId = clientId ;
#endif
#ifdef E4MISC
if ( dataResult != 0 )
{
error4( trans->c4trans->c4, e4info, E83501 ) ;
return 0 ;
}
dataResult = dataOn ;
#else
return dataOn ;
#endif
}
#endif
}
#ifdef E4MISC
return dataResult ;
#else
return dataOn ;
#endif
}
/* gets the data4 corresponding to the serverId, and sets the current clientId to clientId */
DATA4 *tran4data( TRAN4 *trans, const long serverId, const long clientId )
{
DATA4 *dataOn ;
#ifdef E4MISC
DATA4 *dataResult ;
#endif
#ifdef S4SERVER
int rc = 0 ;
#endif
#ifdef E4ANALYZE
if ( tran4verify( trans, 1 ) < 0 )
return 0 ;
#endif
dataOn = 0 ;
#ifdef E4MISC
dataResult = 0 ;
#endif
for (;; )
{
dataOn = (DATA4 *)l4next( tran4dataList( trans ), dataOn ) ;
if ( dataOn == 0 )
break ;
if ( data4serverId( dataOn ) == serverId )
{
dataOn->clientId = clientId ;
#ifdef E4MISC
if ( dataResult != 0 )
{
error4( trans->c4trans->c4, e4info, E83501 ) ;
return 0 ;
}
dataResult = dataOn ;
#else
break ;
#endif
}
}
/*
#ifdef S4SERVER
#ifdef E4MISC
if ( dataResult != 0 )
rc = d4tagUniqueSync( dataResult ) ;
#else
if ( dataOn != 0 )
rc = d4tagUniqueSync( dataOn ) ;
#endif
if ( rc < 0 )
return 0 ;
#endif
*/
#ifdef E4MISC
return dataResult ;
#else
return dataOn ;
#endif
}
DATA4 *S4FUNCTION code4data( CODE4 *c4, const char *aliasName )
{
char buf[12] ;
#ifdef S4SERVER
RELATE4 *relate ;
#endif
#ifdef S4VBASIC
if ( c4parm_check( c4, 1, E91102 ) )
return 0 ;
#endif /* S4VBASIC */
#ifdef E4PARM_HIGH
if ( c4 == 0 || aliasName == 0 )
{
error4( c4, e4parm_null, E91102 ) ;
return 0 ;
}
#endif
u4ncpy( buf, aliasName, sizeof( buf ) ) ;
#ifndef S4CASE_SEN
c4upper( buf ) ;
#endif
#ifdef S4SERVER
if ( c4->currentRelation == 0 )
return tran4dataName( code4trans( c4 ), buf, 0L, 1 ) ;
relate = &(c4->currentRelation->relate) ;
for ( ;; )
{
if ( relate == 0 )
return 0 ;
if ( strcmp( aliasName, d4alias( relate->data ) ) == 0 )
return relate->data ;
if ( relate4next( &relate ) == 2 )
return 0 ;
}
#else
return tran4dataName( code4trans( c4 ), buf, 0L, 0 ) ;
#endif
}
const char *code4version( CODE4 *c4 )
{
char ver[] = "S4VERSION" ;
#ifdef E4PARM_HIGH
if ( c4 == 0 )
{
error4( 0, e4parm_null, E91111 ) ;
return 0 ;
}
#endif
if ( c4->version == 0 )
{
c4->version = (char *)u4allocFree( c4, (long)sizeof( ver ) ) ;
if ( c4->version == 0 )
return 0 ;
memcpy( c4->version, ver, sizeof( ver ) ) ;
}
return c4->version ;
}
#ifdef S4CLIENT
/* used for testing only */
int S4FUNCTION code4catalogSet( CODE4 *c4, int catalogAdd, int catalogStatus )
{
CONNECTION4 *connection ;
CONNECTION4CATALOG_SET_INFO_IN infoIn ;
int rc ;
if ( c4->defaultServer != 0 )
{
connection = c4->defaultServer->connect ;
connection4assign( connection, CON4CATALOG, 0L, 0L ) ;
infoIn.catalogAdd = catalogAdd ;
infoIn.catalogStatus = catalogStatus ;
connection4addData( connection, &infoIn, sizeof(CONNECTION4CATALOG_SET_INFO_IN), 0 ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
return rc ;
rc = connection4status( connection ) ;
if ( rc < 0 )
connection4error( connection, c4, rc, 0 ) ;
return rc ;
}
return 0 ;
}
const char *S4FUNCTION code4serverName( CODE4 *c4 )
{
#ifdef E4PARM_HIGH
if ( c4 == 0 )
{
error4( 0, e4parm_null, E91112 ) ;
return 0 ;
}
#endif
#ifdef S4OFF_COMMUNICATIONS
return 0 ;
#else
if ( c4->defaultServer == 0 )
return 0 ;
return c4->defaultServer->serverName ;
#endif
}
int S4FUNCTION code4indexFormat( CODE4 *c4 )
{
#ifdef S4OFF_INDEX
return 0 ;
#else
CONNECTION4 *connection ;
int rc ;
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return error4( 0, e4parm_null, E91110 ) ;
#endif
if ( c4->indexFormat != 0 )
return c4->indexFormat ;
if ( c4->defaultServer == 0 )
return r4unknown ;
connection = c4->defaultServer->connect ;
if ( connection == 0 )
return r4unknown ;
connection4assign( connection, CON4INDEX_FORMAT, 0L, 0L ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
return error4stack( c4, rc, E91110 ) ;
rc = connection4status( connection ) ;
if ( rc < 0 )
return connection4error( connection, c4, rc, E91110 ) ;
#ifdef E4MISC
switch( rc )
{
case r4ndx:
case r4mdx:
case r4cdx:
case r4ntx:
break ;
default:
return error4( c4, e4info, E81102 ) ;
}
#endif
c4->indexFormat = rc ;
return rc ;
#endif
}
/*#ifdef S4TESTING*/
/* for testing only, restarts the server if this is the last client, after
we disconnect */
int S4FUNCTION code4serverRestart( CODE4 *c4 )
{
CONNECTION4 *connection ;
int rc ;
connection = c4->defaultServer->connect ;
if ( connection == 0 )
return error4( c4, e4connection, E81102 ) ;
connection4assign( connection, CON4RESTART, 0L, 0L ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
return error4stack( c4, rc, E91110 ) ;
rc = connection4status( connection ) ;
if ( rc < 0 )
return connection4error( connection, c4, rc, E91110 ) ;
return rc ;
}
/* for testing only, causes a server crash */
int S4FUNCTION code4serverCrash( CODE4 *c4 )
{
CONNECTION4 *connection ;
int rc ;
connection = c4->defaultServer->connect ;
if ( connection == 0 )
return error4( c4, e4connection, E81102 ) ;
connection4assign( connection, CON4CRASH, 0L, 0L ) ;
connection4send( connection ) ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
return error4stack( c4, rc, E91110 ) ;
rc = connection4status( connection ) ;
if ( rc < 0 )
return connection4error( connection, c4, rc, E91110 ) ;
return rc ;
}
#else /* S4CLIENT */
#ifdef P4ARGS_USED
#pragma argsused
#endif
int S4FUNCTION code4indexFormat( CODE4 *c4 )
{
#ifdef S4OFF_INDEX
return 0 ;
#else
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return error4( 0, e4parm_null, E91110 ) ;
#endif
#ifdef S4MDX
return r4mdx ;
#endif
#ifdef S4FOX
return r4cdx ;
#endif
#ifdef S4CLIPPER
return r4ntx ;
#endif
#ifdef S4NDX
return r4ndx ;
#endif
#endif
}
#endif
#ifndef S4SERVER
#ifdef S4STAND_ALONE
#ifndef S4OFF_WRITE
#ifndef S4OFF_TRAN
int S4FUNCTION code4logCreate( CODE4 *c4, const char *fileName, const char *userId )
{
int rc ;
static char defaultUser[] = "PUBLIC" ;
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return error4( c4, e4parm_null, E91013 ) ;
#endif
if ( userId == 0 )
userId = defaultUser ;
else
if ( userId[0] == 0 ) /* null string */
userId = defaultUser ;
if ( c4->c4trans.transFile != 0 )
return r4logOpen ;
if ( fileName == 0 )
#ifdef S4CASE_SEN
fileName = "C4.log" ;
#else
fileName = "C4.LOG" ;
#endif
else
if ( fileName[0] == 0 ) /* null string */
#ifdef S4CASE_SEN
fileName = "C4.log" ;
#else
fileName = "C4.LOG" ;
#endif
rc = code4transFileEnable( &c4->c4trans, fileName, 1 ) ;
#ifndef S4UTILS
tran4addUser( &c4->c4trans.trans, 0L, userId, (unsigned short int)strlen( userId ) ) ;
#endif
return rc ;
}
const char *S4FUNCTION code4logFileName( CODE4 *c4 )
{
#ifdef E4PARM_HIGH
if ( c4 == 0 )
{
error4( c4, e4parm_null, E91014 ) ;
return 0 ;
}
#endif
if ( c4->c4trans.transFile == 0 )
return 0 ;
return c4->c4trans.transFile->file.name ;
}
int S4FUNCTION code4logOpen( CODE4 *c4, const char *fileName, const char *userId )
{
int rc ;
static char defaultUser[] = "PUBLIC" ;
#ifdef E4PARM_HIGH
if ( c4 == 0 )
return error4( c4, e4parm_null, E91015 ) ;
#endif
if ( userId == 0 )
userId = defaultUser ;
else
if ( userId[0] == 0 ) /* null string */
userId = defaultUser ;
if ( c4->c4trans.transFile != 0 )
return r4logOpen ;
if ( fileName == 0 )
#ifdef S4CASE_SEN
fileName = "C4.log" ;
#else
fileName = "C4.LOG" ;
#endif
else
if ( fileName[0] == 0 ) /* null string */
#ifdef S4CASE_SEN
fileName = "C4.log" ;
#else
fileName = "C4.LOG" ;
#endif
rc = code4transFileEnable( code4trans( c4 )->c4trans, fileName, 0 ) ;
#ifndef S4UTILS
tran4addUser( &c4->c4trans.trans, 0L, userId, (unsigned short int)strlen( userId ) ) ;
#endif
return rc ;
}
void S4FUNCTION code4logOpenOff( CODE4 *c4 )
{
#ifdef E4PARM_HIGH
if ( c4 == 0 )
{
error4( c4, e4parm_null, E91016 ) ;
return ;
}
#endif
c4->logOpen = 0 ;
}
#endif /* S4OFF_TRAN */
#endif /* S4OFF_WRITE */
#endif /* S4STAND_ALONE */
#endif /* S4SERVER */
const char *S4FUNCTION code4indexExtension( CODE4 *c4 )
{
if ( c4->indexExtension[0] == 0 )
switch ( code4indexFormat( c4 ) )
{
case r4mdx:
#ifdef S4CASE_SEN
memcpy( c4->indexExtension, "mdx", 3 ) ;
#else
memcpy( c4->indexExtension, "MDX", 3 ) ;
#endif
break ;
case r4cdx:
#ifdef S4CASE_SEN
memcpy( c4->indexExtension, "cdx", 3 ) ;
#else
memcpy( c4->indexExtension, "CDX", 3 ) ;
#endif
break ;
case r4ntx:
#ifdef S4CASE_SEN
memcpy( c4->indexExtension, "ntx", 3 ) ;
#else
memcpy( c4->indexExtension, "NTX", 3 ) ;
#endif
break ;
case r4ndx:
#ifdef S4CASE_SEN
memcpy( c4->indexExtension, "ndx", 3 ) ;
#else
memcpy( c4->indexExtension, "NDX", 3 ) ;
#endif
break ;
default:
return 0 ;
}
return c4->indexExtension ;
}
#ifdef S4FOX
#define S4FORMAT 1
#endif
#ifdef S4CLIPPER
#ifdef S4FORMAT
#error Choose only one CodeBase index file compatibility option.
#endif
#define S4FORMAT 2
#endif
#ifdef S4MDX
#ifdef S4FORMAT
#error Choose only one CodeBase index file compatibility option.
#endif
#define S4FORMAT 4
#endif
#ifdef S4CLIENT
#ifndef S4FORMAT
#define S4FORMAT 0
#endif
#else
#ifndef S4FORMAT
#error You must define either S4FOX, S4CLIPPER or S4MDX
#endif
#endif
#ifdef S4CLIENT
#define S4CLIENT_VAL 0x8
#else
#define S4CLIENT_VAL 0x0
#endif
#ifdef S4DOS
#define S4OPERATING 0x10
#endif
#ifdef S4WIN16
#ifdef S4OPERATING
#error Choose only one of CodeBase switches S4DOS, S4WIN16, S4WIN32, S4OS2, S4UNIX, S4MACINTOSH or S4PASCAL_WIN
#endif
#define S4OPERATING 0x20
#endif
#ifdef S4WIN32
#ifdef S4OPERATING
#error Choose only one of CodeBase switches S4DOS, S4WIN16, S4WIN32, S4OS2, S4UNIX, S4MACINTOSH or S4PASCAL_WIN
#endif
#define S4OPERATING 0x40
#endif
#ifdef S4STAND_ALONE
#define S4STAND_ALONE_VAL 0x80
#else
#define S4STAND_ALONE_VAL 0x0
#endif
#ifdef S4OS2
#ifdef S4OPERATING
#error Choose only one of CodeBase switches S4DOS, S4WIN16, S4WIN32, S4OS2, S4UNIX, S4MACINTOSH or S4PASCAL_WIN
#endif
#define S4OPERATING 0x100
#endif
#ifdef S4UNIX
#ifdef S4OPERATING
#error Choose only one of CodeBase switches S4DOS, S4WIN16, S4WIN32, S4OS2, S4UNIX, S4MACINTOSH or S4PASCAL_WIN
#endif
#define S4OPERATING 0x200
#endif
/* */
/* */
/* */
/* */
/* */
/* */
#ifdef S4PASCAL_WIN
#ifdef S4OPERATING
#error Choose only one of CodeBase switches S4DOS, S4WIN16, S4WIN32, S4OS2, S4UNIX, S4MACINTOSH or S4PASCAL_WIN
#endif
#define S4OPERATING 0x800
#endif
#ifndef S4OPERATING
#error Must choose one of CodeBase switches S4DOS, S4WIN16, S4WIN32, S4OS2, S4UNIX, S4MACINTOSH or S4PASCAL_WIN
#endif
#ifdef S4CB51
#define S4CB51_VAL 0x1000
#else
#define S4CB51_VAL 0
#endif
#ifdef S4SAFE
#define S4SAFE_VAL 0x2000
#else
#define S4SAFE_VAL 0
#endif
#ifdef S4LOCK_HOOK
#define S4LOCK_HOOK_VAL 0x4000
#else
#define S4LOCK_HOOK_VAL 0
#endif
#ifdef S4MAX
#define S4MAX_VAL 0x8000
#else
#define S4MAX_VAL 0
#endif
#ifdef S4TIMEOUT_HOOK
#define S4TIMEOUT_HOOK_VAL 0x10000
#else
#define S4TIMEOUT_HOOK_VAL 0
#endif
#ifdef E4ANALYZE
#define E4ANALYZE_VAL 0x20000
#else
#define E4ANALYZE_VAL 0
#endif
#ifdef E4DEBUG
#define E4DEBUG_VAL 0x40000
#else
#define E4DEBUG_VAL 0
#endif
#ifdef E4HOOK
#define E4HOOK_VAL 0x80000
#else
#define E4HOOK_VAL 0
#endif
#ifdef E4LINK
#define E4LINK_VAL 0x100000
#else
#define E4LINK_VAL 0
#endif
#ifdef E4MISC
#define E4MISC_VAL 0x200000
#else
#define E4MISC_VAL 0
#endif
#ifdef E4OFF
#define E4OFF_VAL 0x400000
#else
#define E4OFF_VAL 0
#endif
#ifdef E4OFF_STRING
#define E4OFF_STRING_VAL 0x800000
#else
#define E4OFF_STRING_VAL 0
#endif
#ifdef E4PARM_HIGH
#define E4PARM_HIGH_VAL 0x1000000
#else
#define E4PARM_HIGH_VAL 0
#endif
#ifdef E4PAUSE
#define E4PAUSE_VAL 0x2000000
#else
#define E4PAUSE_VAL 0
#endif
#ifdef E4STOP
#define E4STOP_VAL 0x4000000
#else
#define E4STOP_VAL 0
#endif
#ifdef E4STOP_CRITICAL
#define E4STOP_CRITICAL_VAL 0x8000000
#else
#define E4STOP_CRITICAL_VAL 0
#endif
#ifdef S4OFF_INDEX
#define S4OFF_INDEX_VAL 0x10000000
#else
#define S4OFF_INDEX_VAL 0
#endif
#ifdef S4OFF_MEMO
#define S4OFF_MEMO_VAL 0x20000000
#else
#define S4OFF_MEMO_VAL 0
#endif
#ifdef S4OFF_MULTI
#define S4OFF_MULTI_VAL 0x40000000
#else
#define S4OFF_MULTI_VAL 0
#endif
#ifdef S4OFF_OPTIMIZE
#define S4OFF_OPTIMIZE_VAL 0x80000000
#else
#define S4OFF_OPTIMIZE_VAL 0
#endif
/*
no room for these switches
#ifdef S4OFF_REPORT
#define S4OFF_REPORT_VAL 0x100000000
#else
#define S4OFF_REPORT_VAL 0
#endif
#ifdef S4OFF_TRAN
#define S4OFF_TRAN_VAL 0x200000000
#else
#define S4OFF_TRAN_VAL 0
#endif
#ifdef S4OFF_WRITE
#define S4OFF_WRITE_VAL 0x400000000
#else
#define S4OFF_WRITE_VAL 0
#endif
*/
long S4FUNCTION u4switch()
{
return (long) ( S4FORMAT + S4OPERATING + S4CB51_VAL + S4SAFE_VAL +
S4LOCK_HOOK_VAL + S4MAX_VAL + S4TIMEOUT_HOOK_VAL + E4ANALYZE_VAL +
E4DEBUG_VAL + E4HOOK_VAL + E4LINK_VAL + E4MISC_VAL + E4OFF_VAL +
E4OFF_STRING_VAL + E4PARM_HIGH_VAL + E4PAUSE_VAL + E4STOP_VAL +
E4STOP_CRITICAL_VAL + S4OFF_INDEX_VAL + S4OFF_MEMO_VAL +
S4OFF_MULTI_VAL + S4OFF_OPTIMIZE_VAL +
/* S4OFF_REPORT_VAL + S4OFF_TRAN_VAL + S4OFF_WRITE_VAL + no room */
S4CLIENT_VAL + S4STAND_ALONE_VAL ) ;
}
#ifdef S4VB_DOS
DATA4 *d4data_v( CODE4 *c4, char *alias )
{
return code4data( c4, c4str(alias) ) ;
}
#endif
/*#ifdef S4CB51*/
#ifndef S4SERVER
#ifdef S4DLL_BUILD
#ifndef S4PASCAL_DOS
#define CTRL4SERVERNAMESIZE 260
/*Structures for CodeControls Functions */
typedef struct ctrl4code_tag
{
LINK4 link ;
HINSTANCE hInst ;
CODE4 *code ;
int alloc ;
LIST4 form ;
#ifdef S4CLIENT
char ServerName[CTRL4SERVERNAMESIZE] ;
#endif
}CTRL4CODE ;
/***************************************************************\
\***************************************************************/
int S4FUNCTION ctrl4addCode( HINSTANCE hInst ) ; /*450*/
void S4FUNCTION ctrl4codeListInit( void ) ; /*451*/
void S4FUNCTION ctrl4freeCtrlNode( CTRL4CODE *node ) ;
void S4FUNCTION ctrl4freeCodeList( void ) ; /*452*/
CTRL4CODE * S4FUNCTION ctrl4getCtrlCode( HINSTANCE hInst ) ; /*453*/
void S4FUNCTION ctrl4getServerName( HINSTANCE hInst,char *serverName,int strLen ) ; /* 5 oh something */
void S4FUNCTION ctrl4setServerName( HINSTANCE hInst,char *serverName ) ; /* 5 oh something */
void S4FUNCTION ctrl4initVBX( CODE4 *code,HINSTANCE hInstance,int initialize ) ; /*454*/
void S4FUNCTION ctrl4initVBXUndo( CODE4 *code,HINSTANCE hInstance ) ; /*455*/
/***************************************************************\
* List Containing CODE4 and hInstance
* structures for CodeControls
\***************************************************************/
LIST4 ctrl4codeListVBX ;
/***************************************************************\
\***************************************************************/
void S4FUNCTION ctrl4codeListInit( void )
{
/*memset( &ctrl4codeListVBX,0,sizeof( LIST4 ) );*/
}
/***************************************************************\
\***************************************************************/
int S4FUNCTION ctrl4addCode( HINSTANCE hInst )
{
CTRL4CODE *node ;
if ( !hInst )
return -1 ;
node = ( CTRL4CODE * ) u4alloc( sizeof( CTRL4CODE ) ) ;
if ( node )
{
node->hInst = hInst ;
node->alloc = 1 ;
node->code = NULL ;
l4add( &ctrl4codeListVBX,node ) ;
}
return 0 ;
}
/***************************************************************\
\***************************************************************/
void S4FUNCTION ctrl4freeCtrlNode( CTRL4CODE *node )
{
if ( node )
{
l4remove( &ctrl4codeListVBX,node ) ;
if ( node->code )
{
code4initUndo( node->code ) ;
u4free( node->code ) ;
}
u4free( node ) ;
}
}
/***************************************************************\
\***************************************************************/
void S4FUNCTION ctrl4freeCodeList( void )
{
CTRL4CODE *node ;
for( node = ( CTRL4CODE * ) l4first( &ctrl4codeListVBX );node != NULL; )
{
l4remove( &ctrl4codeListVBX,node ) ;
if ( node->code && node->alloc )
{
code4initUndo( node->code ) ;
u4free( node->code ) ;
}
u4free( node ) ;
node = ( CTRL4CODE * ) l4next( &ctrl4codeListVBX,node ) ;
}
}
/***************************************************************\
\***************************************************************/
CTRL4CODE * S4FUNCTION ctrl4getCtrlCode( HINSTANCE hInst )
{
CTRL4CODE *node,*returnnode = NULL ;
if ( hInst == 0 )
return NULL ;
for( node = ( CTRL4CODE * ) l4first( &ctrl4codeListVBX );node != NULL; )
{
if ( node->hInst == hInst )
{
returnnode = node ;
node = NULL ;
}
else
node = ( CTRL4CODE * ) l4next( &ctrl4codeListVBX,node ) ;
}
return returnnode ;
}
/***************************************************************\
\***************************************************************/
void S4FUNCTION ctrl4initVBXUndo( CODE4 *code,HINSTANCE hInstance )
{
CTRL4CODE *node ;
node = ctrl4getCtrlCode( hInstance ) ;
if ( node )
{
if ( code != node->code )
code4initUndo( code ) ;
code4initUndo( node->code ) ;
if ( node->alloc )
{
u4free( node->code ) ;
}
l4remove( &ctrl4codeListVBX,node ) ;
u4free( node ) ;
}
}
/***************************************************************\
\***************************************************************/
void S4FUNCTION ctrl4initVBX( CODE4 *code, HINSTANCE hInstance, int initialize )
{
int dealloc ;
CODE4 *oldcode ;
CTRL4CODE *node ;
if ( code )
{
node = ctrl4getCtrlCode( hInstance ) ;
if ( !node )
{
ctrl4addCode( hInstance ) ;
node = ctrl4getCtrlCode( hInstance ) ;
if ( node )
node->alloc = 0 ;
}
if ( node )
{
if ( node->code )
{
dealloc = 0 ;
if ( node->alloc )
dealloc = IDYES ;
else
dealloc = MessageBox( 0,
"Warning! Detected two calls to ctrl4init\nwithout intervening call to ctrl4initUndo!\n\nOk to free previously allocated CODE4 memory ?","Multiple CODE4 Detected"
,MB_YESNO|MB_TASKMODAL|MB_ICONEXCLAMATION ) ;
if ( dealloc == IDYES )
{
oldcode = node->code ;
ctrl4initVBXUndo( node->code,hInstance ) ;
u4free( oldcode ) ;
node->code = NULL ;
}
}
node->alloc = 0 ;
node->code = code ;
if ( initialize )
{
#ifdef S4CLIENT
char setProtocol = 0 ;
/* must choose a default protocol for C/C++ client/server dll
if user will be calling ctrl4init() */
#ifndef S4VBASIC
#ifndef S4PASCAL
setProtocol = 1 ;
#endif
#endif
if( setProtocol )
code4initLow( code, "C4SPX.DLL", S4VERSION ) ;
else
#ifdef S4SPX
code4initLow( code, "C4SPX.DLL", S4VERSION ) ;
#else
code4initLow( code, "C4SOCK.DLL", S4VERSION ) ;
#endif
#else
code4init( code ) ;
#endif
}
}
}
}
#ifdef S4CLIENT
void S4FUNCTION ctrl4getServerName( HINSTANCE hInst,char *serverName,int strLen ) /*5 oh something*/
{
CTRL4CODE *code = NULL ;
if ( !hInst )
return ;
if ( !serverName || strLen <= 0 )
return ;
memset( serverName,0,strLen ) ;
code = ctrl4getCtrlCode( hInst ) ;
if ( code )
{
memcpy( serverName,code->ServerName,min( strLen,CTRL4SERVERNAMESIZE ) ) ;
}
return ;
}
void S4FUNCTION ctrl4setServerName( HINSTANCE hInst,char *serverName ) /*5 oh something*/
{
CTRL4CODE *code = NULL ;
if ( !hInst )
return ;
if ( !serverName )
return ;
code = ctrl4getCtrlCode( hInst ) ;
if ( code )
{
memcpy( code->ServerName,serverName,CTRL4SERVERNAMESIZE ) ;
}
return ;
}
#else
#ifdef S4STAND_ALONE
#ifdef P4ARGS_USED
#pragma argsused
#endif
void S4FUNCTION ctrl4getServerName( HINSTANCE hInst,char *serverName,int strLen ) /*5 oh something*/
{
return ;
}
#ifdef P4ARGS_USED
#pragma argsused
#endif
void S4FUNCTION ctrl4setServerName( HINSTANCE hInst,char *serverName ) /*5 oh something*/
{
return ;
}
#endif
#endif /* S4CLIENT */
#endif /* S4PASCAL_DOS */
#endif /* S4DLL_BUILD */
#endif /* S4SERVER */
/*#endif */ /* S4CB51 */
#ifdef S4STAND_ALONE
/* assumes that code4tranInitLow has already been called internally ( code4init ) */
#ifndef S4OFF_TRAN
#ifndef S4OFF_WRITE
int S4FUNCTION code4tranInit2( CODE4 *c4, const char *fileName, const char *charId )
{
int rc ;
#ifdef E4PARM_LOW
if ( c4 == 0 || fileName == 0 )
return error4( 0, e4parm_null, E93801 ) ;
#endif
c4->c4trans.c4 = c4 ;
rc = code4transFileEnable( &c4->c4trans, fileName, 0 ) ;
if ( rc < 0 )
return rc ;
c4->c4trans.trans.c4trans = &c4->c4trans ;
if ( charId != 0 )
return tran4addUser( &c4->c4trans.trans, 0L, charId, ( unsigned short )strlen( charId ) ) ;
return 0 ;
}
#endif
#endif
int S4FUNCTION code4tranInit( CODE4 *c4 )
{
#ifdef E4PARM_LOW
if ( c4 == 0 )
return error4( 0, e4parm_null, E93802 ) ;
#endif
c4->c4trans.c4 = c4 ;
c4->c4trans.trans.c4trans = &c4->c4trans ;
tran4dataListSet( &c4->c4trans.trans, &c4->c4trans.trans.localDataList ) ;
return 0 ;
}
#endif
#ifdef S4CLIENT
#ifndef S4INLINE
int S4FUNCTION code4tranInit2( CODE4 *c4, const char *fileName, const char *charId )
{
#ifdef E4PARM_LOW
if ( c4 == 0 || fileName == 0 )
return error4( 0, e4parm_null, E93801 ) ;
#endif
return 0 ;
}
#endif
int S4FUNCTION code4tranInit( CODE4 *c4 )
{
#ifdef E4PARM_LOW
if ( c4 == 0 )
return error4( 0, e4parm_null, E93802 ) ;
#endif
#ifndef S4OFF_TRAN
if ( code4transEnabled( c4 ) )
return 0 ;
#endif
c4->c4trans.c4 = c4 ;
c4->c4trans.trans.c4trans = &c4->c4trans ;
#ifndef S4OFF_TRAN
c4->c4trans.enabled = 1 ;
#endif
tran4dataListSet( &c4->c4trans.trans, &c4->c4trans.trans.localDataList ) ;
return 0 ;
}
#endif
#ifndef S4OFF_TRAN
#ifndef S4OFF_WRITE
#ifdef S4CLIENT
#ifndef S4INLINE
void code4tranInitUndo( CODE4 *c4 )
{
return ;
}
#endif /* S4INLINE */
#else
int code4tranInitUndoLow( TRAN4 *t4, const long clientId )
{
int rc ;
if ( t4 == 0 )
return 0 ;
if ( t4->c4trans->enabled == 1 && t4->userId[0] != 0 ) /* if it has been initialized */
{
rc = tran4set( t4, t4->currentTranStatus, -1L, clientId, TRAN4INIT_UNDO, 0, 0L, 0L ) ;
if ( rc < 0 )
return rc ;
if ( tran4lowAppend( t4, 0 ) != 0 )
return e4transAppend ;
memset( t4->userId, 0, sizeof( t4->userId ) ) ;
}
t4->dataPos = 0 ;
return 0 ;
}
#ifdef S4STAND_ALONE
void code4tranInitUndo( CODE4 *c4 )
{
#ifdef E4PARM_LOW
if ( c4 == 0 )
{
error4( 0, e4parm_null, E93804 ) ;
return ;
}
#endif
if ( code4transEnabled( c4 ) )
code4transInitUndo( &c4->c4trans ) ;
}
#endif /* S4STAND_ALONE */
#endif
#endif
#endif