You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1298 lines
24 KiB
1298 lines
24 KiB
/*
|
|
* This module contains the definitions for the inline functions used by the
|
|
* name undecorator. It is intended that this file should be included
|
|
* somewhere in the source file for the undecorator to maximise the chance
|
|
* that they will be truly inlined.
|
|
*/
|
|
|
|
// The following class is a special node class, used in the implementation
|
|
// of the internal chaining mechanism of the 'DName's
|
|
|
|
class charNode;
|
|
class pcharNode;
|
|
class pDNameNode;
|
|
class DNameStatusNode;
|
|
|
|
|
|
#if ( NO_VIRTUAL )
|
|
enum NodeType
|
|
{
|
|
charNode_t,
|
|
pcharNode_t,
|
|
pDNameNode_t,
|
|
DNameStatusNode_t
|
|
|
|
};
|
|
#endif // NO_VIRTUAL
|
|
|
|
|
|
class DNameNode
|
|
{
|
|
private:
|
|
|
|
#if NO_VIRTUAL
|
|
NodeType typeIndex;
|
|
#endif // NO_VIRTUAL
|
|
|
|
DNameNode * next;
|
|
|
|
protected:
|
|
|
|
#if ( !NO_VIRTUAL )
|
|
__near DNameNode ();
|
|
#else // } elif NO_VIRTUAL {
|
|
__near DNameNode ( NodeType );
|
|
#endif // NO_VIRTUAL
|
|
|
|
__near DNameNode ( const DNameNode & );
|
|
|
|
public:
|
|
|
|
virtual int __near length () const PURE;
|
|
virtual pchar_t __near getString ( pchar_t, int ) const PURE;
|
|
DNameNode * __near clone ();
|
|
DNameNode * __near nextNode () const;
|
|
|
|
DNameNode & __near operator += ( DNameNode * );
|
|
|
|
};
|
|
|
|
|
|
class charNode : public DNameNode
|
|
{
|
|
private:
|
|
char me;
|
|
|
|
public:
|
|
__near charNode ( char );
|
|
|
|
virtual int __near length () const;
|
|
virtual pchar_t __near getString ( pchar_t, int ) const;
|
|
|
|
};
|
|
|
|
|
|
class pcharNode : public DNameNode
|
|
{
|
|
private:
|
|
pchar_t me;
|
|
int myLen;
|
|
|
|
public:
|
|
__near pcharNode ( pcchar_t, int = 0 );
|
|
|
|
virtual int __near length () const;
|
|
virtual pchar_t __near getString ( pchar_t, int ) const;
|
|
|
|
};
|
|
|
|
|
|
class pDNameNode : public DNameNode
|
|
{
|
|
private:
|
|
DName * me;
|
|
|
|
public:
|
|
__near pDNameNode ( DName * );
|
|
|
|
virtual int __near length () const;
|
|
virtual pchar_t __near getString ( pchar_t, int ) const;
|
|
|
|
};
|
|
|
|
|
|
class DNameStatusNode : public DNameNode
|
|
{
|
|
private:
|
|
#define TruncationMessage (" ?? ")
|
|
#define TruncationMessageLength (4)
|
|
|
|
DNameStatus me;
|
|
int myLen;
|
|
|
|
public:
|
|
__near DNameStatusNode ( DNameStatus );
|
|
|
|
virtual int __near length () const;
|
|
virtual pchar_t __near getString ( pchar_t, int ) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Memory allocation functions
|
|
|
|
inline void __far * __near __pascal operator new ( size_t sz, HeapManager &, int noBuffer )
|
|
{ return heap.getMemory ( sz, noBuffer ); }
|
|
|
|
void __far * __near HeapManager::getMemory ( size_t sz, int noBuffer )
|
|
{
|
|
FTRACE(HeapManager::getMemory);
|
|
// Align the allocation on an appropriate boundary
|
|
|
|
sz = (( sz + PACK_SIZE ) & ~PACK_SIZE );
|
|
|
|
if ( noBuffer )
|
|
{
|
|
#if STDEBUG
|
|
actual += sz;
|
|
#endif // STDEBUG
|
|
|
|
#if ( !USE_CRT_HEAP )
|
|
return ( *pOpNew )( sz );
|
|
#else // } elif USE_CRT_HEAP {
|
|
return malloc ( sz );
|
|
#endif // USE_CRT_HEAP
|
|
|
|
} // End of IF then
|
|
else
|
|
{
|
|
// Handler a potential request for no space
|
|
|
|
if ( !sz )
|
|
sz = 1;
|
|
#if STDEBUG
|
|
requested += sz;
|
|
#endif // STDEBUG
|
|
|
|
if ( blockLeft < sz )
|
|
{
|
|
// Is the request greater than the largest buffer size ?
|
|
|
|
if ( sz > memBlockSize )
|
|
return 0; // If it is, there is nothing we can do
|
|
|
|
|
|
// Allocate a new block
|
|
|
|
Block * pNewBlock = rnew Block;
|
|
|
|
|
|
// Did the allocation succeed ? If so connect it up
|
|
|
|
if ( pNewBlock )
|
|
{
|
|
// Handle the initial state
|
|
|
|
if ( tail )
|
|
tail = tail->next = pNewBlock;
|
|
else
|
|
head = tail = pNewBlock;
|
|
|
|
// Compute the remaining space
|
|
|
|
blockLeft = memBlockSize - sz;
|
|
|
|
} // End of IF then
|
|
else
|
|
return 0; // Oh-oh! Memory allocation failure
|
|
|
|
} // End of IF then
|
|
else
|
|
blockLeft -= sz; // Deduct the allocated amount
|
|
|
|
// And return the buffer address
|
|
|
|
return &( tail->memBlock[ blockLeft ]);
|
|
|
|
} // End of IF else
|
|
} // End of "HeapManager" FUNCTION "getMemory(unsigned int,int)"
|
|
|
|
|
|
|
|
|
|
// Friend functions of 'DName'
|
|
|
|
DName __near __pascal operator + ( char c, const DName & rd )
|
|
{ return DName ( c ) + rd; }
|
|
|
|
DName __near __pascal operator + ( DNameStatus st, const DName & rd )
|
|
{ return DName ( st ) + rd; }
|
|
|
|
DName __near __pascal operator + ( pcchar_t s, const DName & rd )
|
|
{ return DName ( s ) + rd; }
|
|
|
|
|
|
// The 'DName' constructors
|
|
|
|
inline_p3 __near DName::DName () { node = 0; stat = DN_valid; isIndir = 0; isAUDC = 0; }
|
|
inline __near DName::DName ( DNameNode * pd ) { node = pd; stat = DN_valid; isIndir = 0; isAUDC = 0; }
|
|
|
|
__near DName::DName ( char c )
|
|
{
|
|
FTRACE(DName::DName(char));
|
|
stat = DN_valid;
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
node = 0;
|
|
|
|
// The NULL character is boring, do not copy
|
|
|
|
if ( c )
|
|
doPchar ( &c, 1 );
|
|
|
|
} // End of "DName" CONSTRUCTOR '(char)'
|
|
|
|
|
|
#if 1
|
|
__near DName::DName ( const DName & rd )
|
|
{
|
|
#if STDEBUG
|
|
FTRACE(DName::DName(const DName&));
|
|
shallowCopies++;
|
|
#endif // STDEBUG
|
|
|
|
stat = rd.stat;
|
|
isIndir = rd.isIndir;
|
|
isAUDC = rd.isAUDC;
|
|
node = rd.node;
|
|
|
|
} // End of "DName" CONSTRUCTOR '(const DName&)'
|
|
#endif
|
|
|
|
#if ( !VERS_P3 )
|
|
__near DName::DName ( DName * pd )
|
|
{
|
|
FTRACE(DName::DName(DName*));
|
|
if ( pd )
|
|
{
|
|
node = gnew pDNameNode ( pd );
|
|
stat = ( node ? DN_valid : ERROR );
|
|
|
|
} // End of IF else
|
|
else
|
|
{
|
|
stat = DN_valid;
|
|
node = 0;
|
|
|
|
} // End of IF else
|
|
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
|
|
} // End of "DName" CONSTRUCTOR '( DName* )'
|
|
#endif // !VERS_P3
|
|
|
|
|
|
__near DName::DName ( pcchar_t s )
|
|
{
|
|
FTRACE(DName::DName(pcchar_t));
|
|
stat = DN_valid;
|
|
node = 0;
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
|
|
if ( s )
|
|
doPchar ( s, strlen ( s ));
|
|
|
|
} // End of "DName" CONSTRUCTOR '(pcchar_t)'
|
|
|
|
|
|
__near DName::DName ( pcchar_t & name, char terminator )
|
|
{
|
|
FTRACE(DName::DName(pcchar_t&,char));
|
|
stat = DN_valid;
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
node = 0;
|
|
|
|
// Is there a string ?
|
|
|
|
if ( name )
|
|
if ( *name )
|
|
{
|
|
int len = 0;
|
|
|
|
|
|
// How long is the string ?
|
|
|
|
for ( pcchar_t s = name; *name && ( *name != terminator ); name++ )
|
|
if ( isValidIdentChar ( *name ))
|
|
len++;
|
|
else
|
|
{
|
|
stat = DN_invalid;
|
|
|
|
return;
|
|
|
|
} // End of IF else
|
|
|
|
// Copy the name string fragment
|
|
|
|
doPchar ( s, len );
|
|
|
|
// Now gobble the terminator if present, handle error conditions
|
|
|
|
if ( *name )
|
|
{
|
|
if ( *name++ != terminator )
|
|
{
|
|
stat = ERROR;
|
|
node = 0;
|
|
|
|
} // End of IF then
|
|
else
|
|
stat = DN_valid;
|
|
|
|
} // End of IF then
|
|
elif ( status () == DN_valid )
|
|
stat = DN_truncated;
|
|
|
|
} // End of IF then
|
|
else
|
|
stat = DN_truncated;
|
|
else
|
|
stat = DN_invalid;
|
|
|
|
} // End of "DName" CONSTRUCTOR '(pcchar_t&,char)'
|
|
|
|
|
|
#if ( !VERS_P3 )
|
|
__near DName::DName ( unsigned long num )
|
|
{
|
|
FTRACE(DName::DName(unsigned long));
|
|
char buf[ 11 ];
|
|
char * pBuf = buf + 10;
|
|
|
|
|
|
stat = DN_valid;
|
|
node = 0;
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
|
|
// Essentially, 'ultoa ( num, buf, 10 )' :-
|
|
|
|
*pBuf = 0;
|
|
|
|
do
|
|
{
|
|
*( --pBuf ) = (char)(( num % 10 ) + '0' );
|
|
num /= 10UL;
|
|
|
|
} while ( num );
|
|
|
|
doPchar ( pBuf, ( 10 - (int)( pBuf - buf )));
|
|
|
|
} // End of "DName" CONSTRUCTOR '(unsigned long)'
|
|
#endif // !VERS_P3
|
|
|
|
|
|
__near DName::DName ( DNameStatus st )
|
|
{
|
|
FTRACE(DName::DName(DNameStatus));
|
|
stat = ((( st == DN_invalid ) || ( st == DN_error )) ? st : DN_valid );
|
|
node = gnew DNameStatusNode ( st );
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
|
|
if ( !node )
|
|
stat = ERROR;
|
|
|
|
} // End of "DName" CONSTRUCTOR '(DNameStatus)'
|
|
|
|
|
|
|
|
// Now the member functions for 'DName'
|
|
|
|
int __near DName::isValid () const { return (( status () == DN_valid ) || ( status () == DN_truncated )); }
|
|
int __near DName::isEmpty () const { return (( node == 0 ) || !isValid ()); }
|
|
|
|
inline DNameStatus __near DName::status () const { return (DNameStatus)stat; } // The cast is to keep Glockenspiel quiet
|
|
|
|
#if ( !VERS_P3 )
|
|
inline DName & __near DName::setPtrRef () { isIndir = 1; return *this; }
|
|
inline int __near DName::isPtrRef () const { return isIndir; }
|
|
inline int __near DName::isUDC () const { return ( !isEmpty () && isAUDC ); }
|
|
inline void __near DName::setIsUDC () { if ( !isEmpty ()) isAUDC = TRUE; }
|
|
#endif // !VERS_P3
|
|
|
|
int __near DName::length () const
|
|
{
|
|
FTRACE(DName::length);
|
|
int len = 0;
|
|
|
|
|
|
if ( !isEmpty ())
|
|
for ( DNameNode * pNode = node; pNode; pNode = pNode->nextNode ())
|
|
len += pNode->length ();
|
|
|
|
return len;
|
|
|
|
} // End of "DName" FUNCTION "length"
|
|
|
|
|
|
pchar_t __near DName::getString ( pchar_t buf, int max ) const
|
|
{
|
|
FTRACE(DName::getString);
|
|
if ( !isEmpty ())
|
|
{
|
|
// Does the caller want a buffer allocated ?
|
|
|
|
if ( !buf )
|
|
{
|
|
max = length () + 1;
|
|
buf = gnew char[ max ]; // Get a buffer big enough
|
|
|
|
} // End of IF then
|
|
|
|
// If memory allocation failure, then return no buffer
|
|
|
|
if ( buf )
|
|
{
|
|
// Now, go through the process of filling the buffer (until max is reached)
|
|
|
|
int curLen = max;
|
|
DNameNode * curNode = node;
|
|
pchar_t curBuf = buf;
|
|
|
|
|
|
while ( curNode && ( curLen > 0 ))
|
|
{
|
|
int fragLen = curNode->length ();
|
|
pchar_t fragBuf = 0;
|
|
|
|
|
|
// Skip empty nodes
|
|
|
|
if ( fragLen )
|
|
{
|
|
// Handle buffer overflow
|
|
|
|
if (( curLen - fragLen ) < 0 )
|
|
fragLen = curLen;
|
|
|
|
// Now copy 'len' number of bytes of the piece to the buffer
|
|
|
|
fragBuf = curNode->getString ( curBuf, fragLen );
|
|
|
|
// Should never happen, but handle it anyway
|
|
|
|
if ( fragBuf )
|
|
{
|
|
// Update string position
|
|
|
|
curLen -= fragLen;
|
|
curBuf += fragLen;
|
|
|
|
} // End of IF
|
|
} // End of IF
|
|
|
|
// Move on to the next name fragment
|
|
|
|
curNode = curNode->nextNode ();
|
|
|
|
} // End of WHILE
|
|
|
|
*curBuf = 0; // Always NULL terminate the resulting string
|
|
|
|
} // End of IF
|
|
} // End of IF then
|
|
elif ( buf )
|
|
*buf = 0;
|
|
|
|
// Return the buffer
|
|
|
|
return buf;
|
|
|
|
} // End of "DName" FUNCTION "getString(pchar_t,int)"
|
|
|
|
|
|
#if ( !VERS_P3 )
|
|
DName __near DName::operator + ( char ch ) const
|
|
{
|
|
FTRACE(DName::+(char));
|
|
DName local ( *this );
|
|
|
|
|
|
if ( local.isEmpty ())
|
|
local = ch;
|
|
else
|
|
local += ch;
|
|
|
|
// And return the newly formed 'DName'
|
|
|
|
return local;
|
|
|
|
} // End of "DName" OPERATOR "+(char)"
|
|
#endif // !VERS_P3
|
|
|
|
|
|
DName __near DName::operator + ( pcchar_t str ) const
|
|
{
|
|
FTRACE(DName::+(pcchar_t));
|
|
DName local ( *this );
|
|
|
|
|
|
if ( local.isEmpty ())
|
|
local = str;
|
|
else
|
|
local += str;
|
|
|
|
// And return the newly formed 'DName'
|
|
|
|
return local;
|
|
|
|
} // End of "DName" OPERATOR "+(pcchar_t)"
|
|
|
|
|
|
DName __near DName::operator + ( const DName & rd ) const
|
|
{
|
|
FTRACE(DName::+(const DName&));
|
|
DName local ( *this );
|
|
|
|
|
|
if ( local.isEmpty ())
|
|
local = rd;
|
|
elif ( rd.isEmpty ())
|
|
local += rd.status ();
|
|
else
|
|
local += rd;
|
|
|
|
// And return the newly formed 'DName'
|
|
|
|
return local;
|
|
|
|
} // End of "DName" OPERATOR "+(const DName&)"
|
|
|
|
|
|
#if ( !VERS_P3 )
|
|
DName __near DName::operator + ( DName * pd ) const
|
|
{
|
|
FTRACE(DName::+(DName*));
|
|
DName local ( *this );
|
|
|
|
|
|
if ( local.isEmpty ())
|
|
local = pd;
|
|
else
|
|
local += pd;
|
|
|
|
// And return the newly formed 'DName'
|
|
|
|
return local;
|
|
|
|
} // End of "DName" OPERATOR "+(DName*)"
|
|
|
|
|
|
DName __near DName::operator + ( DNameStatus st ) const
|
|
{
|
|
FTRACE(DName::+(DNameStatus));
|
|
DName local ( *this );
|
|
|
|
|
|
if ( local.isEmpty ())
|
|
local = st;
|
|
else
|
|
local += st;
|
|
|
|
// And return the newly formed 'DName'
|
|
|
|
return local;
|
|
|
|
} // End of "DName" OPERATOR "+(DNameStatus)"
|
|
|
|
|
|
|
|
DName & __near DName::operator += ( char ch )
|
|
{
|
|
FTRACE(DName::+=(char));
|
|
if ( ch )
|
|
if ( isEmpty ())
|
|
*this = ch;
|
|
else
|
|
{
|
|
node = node->clone ();
|
|
|
|
if ( node )
|
|
*node += gnew charNode ( ch );
|
|
else
|
|
stat = ERROR;
|
|
|
|
} // End of IF
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR "+=(char)"
|
|
|
|
|
|
DName & __near DName::operator += ( pcchar_t str )
|
|
{
|
|
FTRACE(DName::+=(pcchar_t));
|
|
if ( str && *str )
|
|
if ( isEmpty ())
|
|
*this = str;
|
|
else
|
|
{
|
|
node = node->clone ();
|
|
|
|
if ( node )
|
|
*node += gnew pcharNode ( str );
|
|
else
|
|
stat = ERROR;
|
|
|
|
} // End of IF
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR "+=(pcchar_t)"
|
|
#endif // !VERS_P3
|
|
|
|
|
|
DName & __near DName::operator += ( const DName & rd )
|
|
{
|
|
FTRACE(DName::+=(const DName&));
|
|
if ( rd.isEmpty ())
|
|
*this += rd.status ();
|
|
else
|
|
if ( isEmpty ())
|
|
*this = rd;
|
|
else
|
|
{
|
|
node = node->clone ();
|
|
|
|
if ( node )
|
|
*node += rd.node;
|
|
else
|
|
stat = ERROR;
|
|
|
|
} // End of IF
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR "+=(const DName&)"
|
|
|
|
|
|
#if ( !VERS_P3 )
|
|
DName & __near DName::operator += ( DName * pd )
|
|
{
|
|
FTRACE(DName::+=(DName*));
|
|
if ( pd )
|
|
if ( isEmpty ())
|
|
*this = pd;
|
|
elif (( pd->status () == DN_valid ) || ( pd->status () == DN_truncated ))
|
|
{
|
|
DNameNode * pNew = gnew pDNameNode ( pd );
|
|
|
|
|
|
if ( pNew )
|
|
{
|
|
node = node->clone ();
|
|
|
|
if ( node )
|
|
*node += pNew;
|
|
|
|
} // End of IF then
|
|
else
|
|
node = 0;
|
|
|
|
if ( !node )
|
|
stat = ERROR;
|
|
|
|
} // End of IF then
|
|
else
|
|
*this += pd->status ();
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR "+=(DName*)"
|
|
|
|
|
|
DName & __near DName::operator += ( DNameStatus st )
|
|
{
|
|
FTRACE(DName::+=(DNameStatus));
|
|
if ( isEmpty () || (( st == DN_invalid ) || ( st == DN_error )))
|
|
*this = st;
|
|
else
|
|
{
|
|
DNameNode * pNew = gnew DNameStatusNode ( st );
|
|
|
|
|
|
if ( pNew )
|
|
{
|
|
node = node->clone ();
|
|
|
|
if ( node )
|
|
*node += pNew;
|
|
|
|
} // End of IF then
|
|
else
|
|
node = 0;
|
|
|
|
if ( !node )
|
|
stat = ERROR;
|
|
|
|
} // End of IF else
|
|
|
|
// Return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR "+=(DNameStatus)"
|
|
|
|
|
|
|
|
DName & __near DName::operator |= ( const DName & rd )
|
|
{
|
|
FTRACE(DName::=(const DName&));
|
|
// Attenuate the error status. Always becomes worse. Don't propogate truncation
|
|
|
|
if (( status () != DN_error ) && !rd.isValid ())
|
|
stat = rd.status ();
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR '|=(const DName&)'
|
|
|
|
|
|
|
|
DName & __near DName::operator = ( char ch )
|
|
{
|
|
FTRACE(DName::=(char));
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
|
|
doPchar ( &ch, 1 );
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR '=(char)'
|
|
#endif // !VERS_P3
|
|
|
|
|
|
DName & __near DName::operator = ( pcchar_t str )
|
|
{
|
|
FTRACE(DName::=(pcchar_t));
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
|
|
doPchar ( str, strlen ( str ));
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR '=(pcchar_t)'
|
|
|
|
|
|
DName & __near DName::operator = ( const DName & rd )
|
|
{
|
|
FTRACE(DName::=(const DName&));
|
|
if (( status () == DN_valid ) || ( status () == DN_truncated ))
|
|
{
|
|
#if STDEBUG
|
|
shallowAssigns++;
|
|
#endif // STDEBUG
|
|
|
|
stat = rd.stat;
|
|
isIndir = rd.isIndir;
|
|
isAUDC = rd.isAUDC;
|
|
node = rd.node;
|
|
|
|
} // End of IF
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR '=(const DName&)'
|
|
|
|
|
|
#if ( !VERS_P3 )
|
|
DName & __near DName::operator = ( DName * pd )
|
|
{
|
|
FTRACE(DName::=(DName*));
|
|
if (( status () == DN_valid ) || ( status () == DN_truncated ))
|
|
if ( pd )
|
|
{
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
node = gnew pDNameNode ( pd );
|
|
|
|
if ( !node )
|
|
stat = ERROR;
|
|
|
|
} // End of IF then
|
|
else
|
|
*this = ERROR;
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR '=(DName*)'
|
|
|
|
|
|
DName & __near DName::operator = ( DNameStatus st )
|
|
{
|
|
FTRACE(DName::=(DNameStatus));
|
|
if (( st == DN_invalid ) || ( st == DN_error ))
|
|
{
|
|
node = 0;
|
|
|
|
if ( status () != DN_error )
|
|
stat = st;
|
|
|
|
} // End of IF then
|
|
elif (( status () == DN_valid ) || ( status () == DN_truncated ))
|
|
{
|
|
isIndir = 0;
|
|
isAUDC = 0;
|
|
node = gnew DNameStatusNode ( st );
|
|
|
|
if ( !node )
|
|
stat = ERROR;
|
|
|
|
} // End of ELIF then
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DName" OPERATOR '=(DNameStatus)'
|
|
#endif // !VERS_P3
|
|
|
|
|
|
// Private implementation functions for 'DName'
|
|
|
|
void __near DName::doPchar ( pcchar_t str, int len )
|
|
{
|
|
FTRACE(DName::doPchar);
|
|
if ( !(( status () == DN_invalid ) || ( status () == DN_error )))
|
|
if ( node )
|
|
*this = ERROR;
|
|
elif ( str && len )
|
|
{
|
|
// Allocate as economically as possible
|
|
|
|
switch ( len )
|
|
{
|
|
case 0:
|
|
stat = ERROR;
|
|
break;
|
|
|
|
case 1:
|
|
node = gnew charNode ( *str );
|
|
|
|
if ( !node )
|
|
stat = ERROR;
|
|
break;
|
|
|
|
default:
|
|
node = gnew pcharNode ( str, len );
|
|
|
|
if ( !node )
|
|
stat = ERROR;
|
|
break;
|
|
|
|
} // End of SWITCH
|
|
} // End of ELIF
|
|
else
|
|
stat = DN_invalid;
|
|
|
|
} // End of "DName" FUNCTION "doPchar(pcchar_t,int)"
|
|
|
|
|
|
|
|
// The member functions for the 'Replicator'
|
|
|
|
inline int __near Replicator::isFull () const { return ( index == 9 ); }
|
|
inline __near Replicator::Replicator ()
|
|
: ErrorDName ( DN_error ), InvalidDName ( DN_invalid )
|
|
{ index = -1; }
|
|
|
|
|
|
|
|
Replicator & __near Replicator::operator += ( const DName & rd )
|
|
{
|
|
FTRACE(Replicator::+=);
|
|
if ( !isFull () && !rd.isEmpty ())
|
|
{
|
|
DName * pNew = gnew DName ( rd );
|
|
|
|
|
|
// Don't update if failed
|
|
|
|
if ( pNew )
|
|
dNameBuffer[ ++index ] = pNew;
|
|
|
|
} // End of IF
|
|
|
|
return *this;
|
|
|
|
} // End of "Replicator" OPERATOR '+=(const DName&)'
|
|
|
|
|
|
const DName & __near Replicator::operator [] ( int x ) const
|
|
{
|
|
FTRACE(Replicator::[]);
|
|
if (( x < 0 ) || ( x > 9 ))
|
|
return ErrorDName;
|
|
elif (( index == -1 ) || ( x > index ))
|
|
{
|
|
(void)ERROR;
|
|
|
|
return InvalidDName;
|
|
|
|
} // End of ELIF then
|
|
else
|
|
return *dNameBuffer[ x ];
|
|
|
|
} // End of "Replicator" OPERATOR '[](int)'
|
|
|
|
|
|
|
|
// The member functions for the 'DNameNode' classes
|
|
|
|
#if ( !NO_VIRTUAL )
|
|
__near DNameNode::DNameNode ()
|
|
#else // } elif NO_VIRTUAL {
|
|
__near DNameNode::DNameNode ( NodeType ndTy )
|
|
: typeIndex ( ndTy )
|
|
#endif // NO_VIRTUAL
|
|
{ next = 0; }
|
|
|
|
inline __near DNameNode::DNameNode ( const DNameNode & rd ) { next = (( rd.next ) ? rd.next->clone () : 0 ); }
|
|
|
|
inline DNameNode * __near DNameNode::nextNode () const { return next; }
|
|
|
|
DNameNode * __near DNameNode::clone ()
|
|
{
|
|
#if STDEBUG
|
|
FTRACE(DNameNode::clone);
|
|
clones++;
|
|
#endif // STDEBUG
|
|
|
|
return gnew pDNameNode ( gnew DName ( this ));
|
|
}
|
|
|
|
#if ( STDEBUG || NO_VIRTUAL )
|
|
int __near DNameNode::length () const
|
|
{ // Pure function, should not be called
|
|
FTRACE(DNameNode::length);
|
|
|
|
#if ( NO_VIRTUAL )
|
|
switch ( typeIndex )
|
|
{
|
|
case charNode_t:
|
|
return ((charNode*)this )->length ();
|
|
|
|
case pcharNode_t:
|
|
return ((pcharNode*)this )->length ();
|
|
|
|
case pDNameNode_t:
|
|
return ((pDNameNode*)this )->length ();
|
|
|
|
case DNameStatusNode_t:
|
|
return ((DNameStatusNode*)this )->length ();
|
|
|
|
} // End of SWITCH
|
|
#endif // NO_VIRTUAL
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
pchar_t __near DNameNode::getString ( pchar_t s, int l ) const
|
|
{ // Pure function, should not be called
|
|
FTRACE(DNameNode::getString);
|
|
|
|
#if ( NO_VIRTUAL )
|
|
switch ( typeIndex )
|
|
{
|
|
case charNode_t:
|
|
return ((charNode*)this )->getString ( s, l );
|
|
|
|
case pcharNode_t:
|
|
return ((pcharNode*)this )->getString ( s, l );
|
|
|
|
case pDNameNode_t:
|
|
return ((pDNameNode*)this )->getString ( s, l );
|
|
|
|
case DNameStatusNode_t:
|
|
return ((DNameStatusNode*)this )->getString ( s, l );
|
|
|
|
} // End of SWITCH
|
|
#endif // NO_VIRTUAL
|
|
|
|
return 0;
|
|
}
|
|
#endif // STDEBUG || NO_VIRTUAL
|
|
|
|
|
|
DNameNode & __near DNameNode::operator += ( DNameNode * pNode )
|
|
{
|
|
FTRACE(DNameNode::+=(DNameNode*));
|
|
if ( pNode )
|
|
{
|
|
if ( next )
|
|
{
|
|
// Skip to the end of the chain
|
|
|
|
for ( DNameNode* pScan = next; pScan->next; pScan = pScan->next )
|
|
;
|
|
|
|
// And append the new node
|
|
|
|
pScan->next = pNode;
|
|
|
|
} // End of IF then
|
|
else
|
|
next = pNode;
|
|
|
|
} // End of IF
|
|
|
|
// And return self
|
|
|
|
return *this;
|
|
|
|
} // End of "DNameNode" OPERATOR '+=(DNameNode*)'
|
|
|
|
|
|
|
|
// The 'charNode' virtual functions
|
|
|
|
inline_p3 __near charNode::charNode ( char ch )
|
|
#if ( NO_VIRTUAL )
|
|
: DNameNode ( charNode_t )
|
|
#endif // NO_VIRTUAL
|
|
{ me = ch; }
|
|
|
|
inline int __near charNode::length () const { return 1; }
|
|
|
|
inline_pwb
|
|
inline_lnk
|
|
pchar_t __near charNode::getString ( pchar_t buf, int len ) const
|
|
{
|
|
FTRACE(charNode::getString);
|
|
if ( buf && len )
|
|
*buf = me;
|
|
else
|
|
buf = 0;
|
|
|
|
// Now return the character
|
|
|
|
return buf;
|
|
|
|
} // End of "charNode" FUNCTION "getString(pchar_t,int)"
|
|
|
|
|
|
|
|
// The 'pcharNode' virtual functions
|
|
|
|
inline int __near pcharNode::length () const { return myLen; }
|
|
|
|
|
|
__near pcharNode::pcharNode ( pcchar_t str, int len )
|
|
#if ( NO_VIRTUAL )
|
|
: DNameNode ( pcharNode_t )
|
|
#endif // NO_VIRTUAL
|
|
{
|
|
FTRACE(pcharNode::pcharNode);
|
|
// Get length if not supplied
|
|
|
|
if ( !len && str )
|
|
len = strlen ( str );
|
|
|
|
// Allocate a new string buffer if valid state
|
|
|
|
if ( len && str )
|
|
{
|
|
me = gnew char[ len ];
|
|
myLen = len;
|
|
|
|
if ( me )
|
|
strncpy ( me, str, len );
|
|
|
|
} // End of IF then
|
|
else
|
|
{
|
|
me = 0;
|
|
myLen = 0;
|
|
|
|
} // End of IF else
|
|
} // End of "pcharNode" CONSTRUCTOR '(pcchar_t,int)'
|
|
|
|
|
|
inline_pwb
|
|
inline_lnk
|
|
pchar_t __near pcharNode::getString ( pchar_t buf, int len ) const
|
|
{
|
|
FTRACE(pcharNode::getString);
|
|
// Use the shorter of the two lengths (may not be NULL terminated)
|
|
|
|
if ( len > pcharNode::length ())
|
|
len = pcharNode::length ();
|
|
|
|
// Do the copy as appropriate
|
|
|
|
return (( me && buf && len ) ? strncpy ( buf, me, len ) : 0 );
|
|
|
|
} // End of "pcharNode" FUNCTION "getString(pchar_t,int)"
|
|
|
|
|
|
|
|
// The 'pDNameNode' virtual functions
|
|
|
|
inline_p3 __near pDNameNode::pDNameNode ( DName * pName )
|
|
#if ( NO_VIRTUAL )
|
|
: DNameNode ( pDNameNode_t )
|
|
#endif // NO_VIRTUAL
|
|
{ me = (( pName && (( pName->status () == DN_invalid ) || ( pName->status () == DN_error ))) ? 0 : pName ); }
|
|
|
|
inline int __near pDNameNode::length () const { return ( me ? me->length () : 0 ); }
|
|
|
|
inline_pwb
|
|
inline_lnk
|
|
pchar_t __near pDNameNode::getString ( pchar_t buf, int len ) const
|
|
{ return (( me && buf && len ) ? me->getString ( buf, len ) : 0 ); }
|
|
|
|
|
|
|
|
// The 'DNameStatusNode' virtual functions
|
|
|
|
inline_p3 __near DNameStatusNode::DNameStatusNode ( DNameStatus stat )
|
|
#if ( NO_VIRTUAL )
|
|
: DNameNode ( DNameStatusNode_t )
|
|
#endif // NO_VIRTUAL
|
|
{ me = stat; myLen = (( me == DN_truncated ) ? TruncationMessageLength : 0 ); }
|
|
|
|
inline int __near DNameStatusNode::length () const { return myLen; }
|
|
|
|
inline_pwb
|
|
inline_lnk
|
|
pchar_t __near DNameStatusNode::getString ( pchar_t buf, int len ) const
|
|
{
|
|
FTRACE(DNameStatusNode::getString);
|
|
// Use the shorter of the two lengths (may not be NULL terminated)
|
|
|
|
if ( len > DNameStatusNode::length ())
|
|
len = DNameStatusNode::length ();
|
|
|
|
// Do the copy as appropriate
|
|
|
|
return ((( me == DN_truncated ) && buf && len ) ? strncpy ( buf, TruncationMessage, len ) : 0 );
|
|
|
|
} // End of "DNameStatusNode" FUNCTION "getString(pchar_t,int)"
|
|
|
|
|
|
|
|
static unsigned int __near __pascal strlen ( pcchar_t str )
|
|
{
|
|
for ( unsigned int len = 0; *str; str++ )
|
|
len++;
|
|
|
|
return len;
|
|
|
|
} // End of FUNCTION "strlen"
|
|
|
|
|
|
static pchar_t __near __pascal strncpy ( pchar_t dst, pcchar_t src, unsigned int len )
|
|
{
|
|
for ( char __far * d = dst; ( len && ( *d = *src )); d++, src++, len-- )
|
|
;
|
|
|
|
return dst;
|
|
|
|
} // End of FUNCTION "strncpy"
|
|
|
|
|
|
#if STDEBUG
|
|
void CallTrace::Dump ( const DName & rd, pcchar_t sym, int line )
|
|
{
|
|
if ( trace && !inTrace )
|
|
{
|
|
inTrace = 1;
|
|
rd.getString ( buf, 512 );
|
|
buf[ rd.length ()] = 0;
|
|
indent ( mark );
|
|
fprintf ( fp, " > DName '%s' #%d: '%s' == '%s'\n", name, line, sym, buf );
|
|
fflush ( fp );
|
|
inTrace = 0;
|
|
}
|
|
}
|
|
|
|
void CallTrace::Dump ( const DNameNode & rd, pcchar_t sym, int line )
|
|
{
|
|
if ( trace && !inTrace )
|
|
{
|
|
inTrace = 1;
|
|
rd.getString ( buf, 512 );
|
|
buf[ rd.length ()] = 0;
|
|
indent ( mark );
|
|
fprintf ( fp, " > DNameNode '%s' #line %d : '%s' == '%s'\n", name, line, sym, buf );
|
|
fflush ( fp );
|
|
inTrace = 0;
|
|
}
|
|
}
|
|
|
|
void CallTrace::Dump ( unsigned long ul, pcchar_t sym, int line )
|
|
{
|
|
if ( trace )
|
|
{
|
|
indent ( mark );
|
|
fprintf ( fp, " > ulong '%s' #line %d : '%s' == '0x%08.08LX'\n", name, line, sym, ul );
|
|
fflush ( fp );
|
|
}
|
|
}
|
|
|
|
void CallTrace::Dump ( void* p, pcchar_t sym, int line )
|
|
{
|
|
if ( trace )
|
|
{
|
|
indent ( mark );
|
|
fprintf ( fp, " > void* '%s' #line %d : '%s' == '%p'\n", name, line, sym, p );
|
|
fflush ( fp );
|
|
}
|
|
}
|
|
|
|
void CallTrace::Dump ( const char* p, pcchar_t sym, int line )
|
|
{
|
|
if ( trace )
|
|
{
|
|
indent ( mark );
|
|
fprintf ( fp, " > char* '%s' #line %d : '%s' == '%s'\n", name, line, sym, p );
|
|
fflush ( fp );
|
|
}
|
|
}
|
|
|
|
void CallTrace::Track ( pcchar_t file, int line )
|
|
{
|
|
if ( trace )
|
|
{
|
|
indent ( mark );
|
|
fprintf ( fp, " > Track '%s' : #line %d \"%s\"\n", name, line, file );
|
|
fflush ( fp );
|
|
}
|
|
}
|
|
|
|
void CallTrace::LogError ( int line )
|
|
{
|
|
if ( trace )
|
|
{
|
|
indent ( mark );
|
|
fprintf ( fp, " > Log Error '%s' : #line %d\n", name, line );
|
|
fflush ( fp );
|
|
}
|
|
}
|
|
|
|
void CallTrace::Message ( pcchar_t msg, int line )
|
|
{
|
|
if ( trace )
|
|
{
|
|
indent ( mark );
|
|
fprintf ( fp, " > Message '%s' : #line %d \"%s\"\n", name, line, msg );
|
|
fflush ( fp );
|
|
}
|
|
}
|
|
#endif // STDEBUG
|
|
|