/* c4code.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */ #include "d4all.h" #ifdef __TURBOC__ #pragma hdrstop #endif /* __TUROBC__ */ #ifdef S4WINTEL #include #endif /* S4WINTEL */ #if S4VERSION != 6001 #error Your CodeBase source version does not match your header file version. #endif #ifdef S4TESTING #include #include #include #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 #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 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