Source code of Windows XP (NT5)
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.

1255 lines
23 KiB

  1. /*
  2. * This module contains the definitions for the inline functions used by the
  3. * name undecorator. It is intended that this file should be included
  4. * somewhere in the source file for the undecorator to maximise the chance
  5. * that they will be truly inlined.
  6. */
  7. // The following class is a special node class, used in the implementation
  8. // of the internal chaining mechanism of the 'DName's
  9. class charNode;
  10. class pcharNode;
  11. class pDNameNode;
  12. class DNameStatusNode;
  13. #if ( NO_VIRTUAL )
  14. enum NodeType
  15. {
  16. charNode_t,
  17. pcharNode_t,
  18. pDNameNode_t,
  19. DNameStatusNode_t
  20. };
  21. #endif // NO_VIRTUAL
  22. class DNameNode
  23. {
  24. private:
  25. #if NO_VIRTUAL
  26. NodeType typeIndex;
  27. #endif // NO_VIRTUAL
  28. DNameNode * next;
  29. protected:
  30. #if ( !NO_VIRTUAL )
  31. __near DNameNode ();
  32. #else // } elif NO_VIRTUAL {
  33. __near DNameNode ( NodeType );
  34. #endif // NO_VIRTUAL
  35. __near DNameNode ( const DNameNode & );
  36. public:
  37. virtual int __near length () const PURE;
  38. virtual char __near getLastChar () const PURE;
  39. virtual pchar_t __near getString ( pchar_t, int ) const PURE;
  40. DNameNode * __near clone ();
  41. DNameNode * __near nextNode () const;
  42. DNameNode & __near operator += ( DNameNode * );
  43. };
  44. class charNode : public DNameNode
  45. {
  46. private:
  47. char me;
  48. public:
  49. __near charNode ( char );
  50. virtual int __near length () const;
  51. virtual char __near getLastChar () const;
  52. virtual pchar_t __near getString ( pchar_t, int ) const;
  53. };
  54. class pcharNode : public DNameNode
  55. {
  56. private:
  57. pchar_t me;
  58. int myLen;
  59. public:
  60. __near pcharNode ( pcchar_t, int = 0 );
  61. virtual int __near length () const;
  62. virtual char __near getLastChar () const;
  63. virtual pchar_t __near getString ( pchar_t, int ) const;
  64. };
  65. class pDNameNode : public DNameNode
  66. {
  67. private:
  68. DName * me;
  69. public:
  70. __near pDNameNode ( DName * );
  71. virtual int __near length () const;
  72. virtual char __near getLastChar () const;
  73. virtual pchar_t __near getString ( pchar_t, int ) const;
  74. };
  75. class DNameStatusNode : public DNameNode
  76. {
  77. private:
  78. #define TruncationMessage (" ?? ")
  79. #define TruncationMessageLength (4)
  80. DNameStatus me;
  81. int myLen;
  82. public:
  83. __near DNameStatusNode ( DNameStatus );
  84. virtual int __near length () const;
  85. virtual char __near getLastChar () const;
  86. virtual pchar_t __near getString ( pchar_t, int ) const;
  87. };
  88. // Memory allocation functions
  89. inline void __far * __near __pascal operator new ( size_t sz, HeapManager &, int noBuffer )
  90. { return heap.getMemory ( sz, noBuffer ); }
  91. void __far * __near HeapManager::getMemory ( size_t sz, int noBuffer )
  92. {
  93. // Align the allocation on an appropriate boundary
  94. sz = (( sz + PACK_SIZE-1 ) & ~(PACK_SIZE-1) );
  95. if ( noBuffer )
  96. return ( *pOpNew )( sz );
  97. else
  98. {
  99. // Handle a potential request for no space
  100. if ( !sz )
  101. sz = PACK_SIZE;
  102. if ( blockLeft < sz )
  103. {
  104. // Is the request greater than the largest buffer size ?
  105. if ( sz > memBlockSize )
  106. return 0; // If it is, there is nothing we can do
  107. // Allocate a new block
  108. Block * pNewBlock = rnew Block;
  109. // Did the allocation succeed ? If so connect it up
  110. if ( pNewBlock )
  111. {
  112. // Handle the initial state
  113. if ( tail )
  114. tail = tail->next = pNewBlock;
  115. else
  116. head = tail = pNewBlock;
  117. // Compute the remaining space
  118. blockLeft = memBlockSize - sz;
  119. } // End of IF then
  120. else
  121. return 0; // Oh-oh! Memory allocation failure
  122. } // End of IF then
  123. else
  124. blockLeft -= sz; // Deduct the allocated amount
  125. // And return the buffer address
  126. return &( tail->memBlock[ blockLeft ]);
  127. } // End of IF else
  128. } // End of "HeapManager" FUNCTION "getMemory(size_t,int)"
  129. // Friend functions of 'DName'
  130. inline DName __near __pascal operator + ( char c, const DName & rd )
  131. { return DName ( c ) + rd; }
  132. inline DName __near __pascal operator + ( DNameStatus st, const DName & rd )
  133. { return DName ( st ) + rd; }
  134. inline DName __near __pascal operator + ( pcchar_t s, const DName & rd )
  135. { return DName ( s ) + rd; }
  136. // The 'DName' constructors
  137. inline __near DName::DName () { node = 0; stat = DN_valid; isIndir = 0; isAUDC = 0; isAUDTThunk = 0; isArrayType = 0; NoTE = 0; }
  138. inline __near DName::DName ( DNameNode * pd ) { node = pd; stat = DN_valid; isIndir = 0; isAUDC = 0; isAUDTThunk = 0; isArrayType = 0; NoTE = 0; }
  139. __near DName::DName ( char c )
  140. {
  141. stat = DN_valid;
  142. isIndir = 0;
  143. isAUDC = 0;
  144. isAUDTThunk = 0;
  145. isArrayType = 0;
  146. node = 0;
  147. NoTE = 0;
  148. // The NULL character is boring, do not copy
  149. if ( c )
  150. doPchar ( &c, 1 );
  151. } // End of "DName" CONSTRUCTOR '(char)'
  152. #if 1
  153. inline __near DName::DName ( const DName & rd )
  154. {
  155. stat = rd.stat;
  156. isIndir = rd.isIndir;
  157. isAUDC = rd.isAUDC;
  158. isAUDTThunk = rd.isAUDTThunk;
  159. isArrayType = rd.isArrayType;
  160. node = rd.node;
  161. NoTE = rd.NoTE;
  162. } // End of "DName" CONSTRUCTOR '(const DName&)'
  163. #endif
  164. __near DName::DName ( DName * pd )
  165. {
  166. if ( pd )
  167. {
  168. node = gnew pDNameNode ( pd );
  169. stat = ( node ? DN_valid : DN_error );
  170. } // End of IF else
  171. else
  172. {
  173. stat = DN_valid;
  174. node = 0;
  175. } // End of IF else
  176. isIndir = 0;
  177. isAUDC = 0;
  178. isAUDTThunk = 0;
  179. isArrayType = 0;
  180. NoTE = 0;
  181. } // End of "DName" CONSTRUCTOR '( DName* )'
  182. __near DName::DName ( pcchar_t s )
  183. {
  184. stat = DN_valid;
  185. node = 0;
  186. isIndir = 0;
  187. isAUDC = 0;
  188. isAUDTThunk = 0;
  189. isArrayType = 0;
  190. NoTE = 0;
  191. if ( s )
  192. doPchar ( s, und_strlen ( s ));
  193. } // End of "DName" CONSTRUCTOR '(pcchar_t)'
  194. __near DName::DName ( pcchar_t & name, char terminator )
  195. {
  196. stat = DN_valid;
  197. isIndir = 0;
  198. isAUDC = 0;
  199. isAUDTThunk = 0;
  200. isArrayType = 0;
  201. node = 0;
  202. NoTE = 0;
  203. // Is there a string ?
  204. if ( name )
  205. if ( *name )
  206. {
  207. int len = 0;
  208. // How long is the string ?
  209. pcchar_t s;
  210. for ( s = name; *name && ( *name != terminator ); name++ )
  211. if ( isValidIdentChar ( *name ) || UnDecorator::doNoIdentCharCheck () )
  212. len++;
  213. else
  214. {
  215. stat = DN_invalid;
  216. return;
  217. } // End of IF else
  218. // Copy the name string fragment
  219. doPchar ( s, len );
  220. // Now gobble the terminator if present, handle error conditions
  221. if ( *name )
  222. {
  223. if ( *name++ != terminator )
  224. {
  225. stat = DN_error;
  226. node = 0;
  227. } // End of IF then
  228. else
  229. stat = DN_valid;
  230. } // End of IF then
  231. elif ( status () == DN_valid )
  232. stat = DN_truncated;
  233. } // End of IF then
  234. else
  235. stat = DN_truncated;
  236. else
  237. stat = DN_invalid;
  238. } // End of "DName" CONSTRUCTOR '(pcchar_t&,char)'
  239. __near DName::DName ( unsigned long num )
  240. {
  241. char buf[ 11 ];
  242. char * pBuf = buf + 10;
  243. stat = DN_valid;
  244. node = 0;
  245. isIndir = 0;
  246. isAUDC = 0;
  247. isAUDTThunk = 0;
  248. isArrayType = 0;
  249. NoTE = 0;
  250. // Essentially, 'ultoa ( num, buf, 10 )' :-
  251. *pBuf = 0;
  252. do
  253. {
  254. *( --pBuf ) = (char)(( num % 10 ) + '0' );
  255. num /= 10UL;
  256. } while ( num );
  257. doPchar ( pBuf, ( 10 - (int) ( pBuf - buf )));
  258. } // End of "DName" CONSTRUCTOR '(unsigned long)'
  259. __near DName::DName ( int num )
  260. {
  261. char buf[ 12 ];
  262. char * pBuf = buf + 11;
  263. stat = DN_valid;
  264. node = 0;
  265. isIndir = 0;
  266. isAUDC = 0;
  267. isAUDTThunk = 0;
  268. isArrayType = 0;
  269. NoTE = 0;
  270. // Essentially, 'ltoa ( num, buf, 10 )' :-
  271. *pBuf = 0;
  272. bool fSigned = false;
  273. if (num < 0) {
  274. fSigned = true;
  275. num = -num;
  276. }
  277. do
  278. {
  279. *( --pBuf ) = (char)(( num % 10 ) + '0' );
  280. num /= 10UL;
  281. } while ( num );
  282. if (fSigned) {
  283. *(--pBuf) = '-';
  284. }
  285. doPchar ( pBuf, ( 11 - (int) ( pBuf - buf )));
  286. }
  287. __near DName::DName ( DNameStatus st )
  288. {
  289. stat = ((( st == DN_invalid ) || ( st == DN_error )) ? st : DN_valid );
  290. node = gnew DNameStatusNode ( st );
  291. isIndir = 0;
  292. isAUDC = 0;
  293. isAUDTThunk = 0;
  294. isArrayType = 0;
  295. NoTE = 0;
  296. if ( !node )
  297. stat = DN_error;
  298. } // End of "DName" CONSTRUCTOR '(DNameStatus)'
  299. // Now the member functions for 'DName'
  300. int __near DName::isValid () const { return (( status () == DN_valid ) || ( status () == DN_truncated )); }
  301. int __near DName::isEmpty () const { return (( node == 0 ) || !isValid ()); }
  302. inline DNameStatus __near DName::status () const { return (DNameStatus)stat; } // The cast is to keep Glockenspiel quiet
  303. inline void __near DName::clearStatus () { stat = DN_valid; }
  304. inline DName & __near DName::setPtrRef () { isIndir = 1; return *this; }
  305. inline int __near DName::isPtrRef () const { return isIndir; }
  306. inline int __near DName::isUDC () const { return ( !isEmpty () && isAUDC ); }
  307. inline void __near DName::setIsUDC () { if ( !isEmpty ()) isAUDC = TRUE; }
  308. inline int __near DName::isUDTThunk () const { return ( !isEmpty () && isAUDTThunk ); }
  309. inline void __near DName::setIsUDTThunk () { if ( !isEmpty ()) isAUDTThunk = TRUE; }
  310. inline void __near DName::setIsArray () { isArrayType = 1; }
  311. inline int __near DName::isArray () const { return isArrayType; }
  312. inline int DName::isNoTE () const { return NoTE; }
  313. inline void DName::setIsNoTE () { NoTE = TRUE; }
  314. int __near DName::length () const
  315. {
  316. int len = 0;
  317. if ( !isEmpty ())
  318. for ( DNameNode * pNode = node; pNode; pNode = pNode->nextNode ())
  319. len += pNode->length ();
  320. return len;
  321. } // End of "DName" FUNCTION "length"
  322. char __near DName::getLastChar () const
  323. {
  324. DNameNode * pLast = 0;
  325. if ( !isEmpty ())
  326. for ( DNameNode * pNode = node; pNode; pNode = pNode->nextNode ())
  327. if ( pNode->length () != 0 )
  328. pLast = pNode;
  329. return pLast != 0 ? pLast->getLastChar () : '\0';
  330. } // End of "DName" FUNCTION "getLastChar"
  331. pchar_t __near DName::getString ( pchar_t buf, int max ) const
  332. {
  333. if ( !isEmpty ())
  334. {
  335. // Does the caller want a buffer allocated ?
  336. if ( !buf )
  337. {
  338. max = length () + 1;
  339. buf = gnew char[ max ]; // Get a buffer big enough
  340. } // End of IF then
  341. // If memory allocation failure, then return no buffer
  342. if ( buf )
  343. {
  344. // Now, go through the process of filling the buffer (until max is reached)
  345. int curLen = max;
  346. DNameNode * curNode = node;
  347. pchar_t curBuf = buf;
  348. while ( curNode && ( curLen > 0 ))
  349. {
  350. int fragLen = curNode->length ();
  351. pchar_t fragBuf = 0;
  352. // Skip empty nodes
  353. if ( fragLen )
  354. {
  355. // Handle buffer overflow
  356. if (( curLen - fragLen ) < 0 )
  357. fragLen = curLen;
  358. // Now copy 'len' number of bytes of the piece to the buffer
  359. fragBuf = curNode->getString ( curBuf, fragLen );
  360. // Should never happen, but handle it anyway
  361. if ( fragBuf )
  362. {
  363. // Update string position
  364. curLen -= fragLen;
  365. curBuf += fragLen;
  366. } // End of IF
  367. } // End of IF
  368. // Move on to the next name fragment
  369. curNode = curNode->nextNode ();
  370. } // End of WHILE
  371. *curBuf = 0; // Always NULL terminate the resulting string
  372. } // End of IF
  373. } // End of IF then
  374. elif ( buf )
  375. *buf = 0;
  376. // Return the buffer
  377. return buf;
  378. } // End of "DName" FUNCTION "getString(pchar_t,int)"
  379. DName __near DName::operator + ( char ch ) const
  380. {
  381. DName local ( *this );
  382. if ( local.isEmpty ())
  383. local = ch;
  384. else
  385. local += ch;
  386. // And return the newly formed 'DName'
  387. return local;
  388. } // End of "DName" OPERATOR "+(char)"
  389. DName __near DName::operator + ( pcchar_t str ) const
  390. {
  391. DName local ( *this );
  392. if ( local.isEmpty ())
  393. local = str;
  394. else
  395. local += str;
  396. // And return the newly formed 'DName'
  397. return local;
  398. } // End of "DName" OPERATOR "+(pcchar_t)"
  399. DName __near DName::operator + ( const DName & rd ) const
  400. {
  401. DName local ( *this );
  402. if ( local.isEmpty ())
  403. local = rd;
  404. elif ( rd.isEmpty ())
  405. local += rd.status ();
  406. else
  407. local += rd;
  408. // And return the newly formed 'DName'
  409. return local;
  410. } // End of "DName" OPERATOR "+(const DName&)"
  411. DName __near DName::operator + ( DName * pd ) const
  412. {
  413. DName local ( *this );
  414. if ( local.isEmpty ())
  415. local = pd;
  416. else
  417. local += pd;
  418. // And return the newly formed 'DName'
  419. return local;
  420. } // End of "DName" OPERATOR "+(DName*)"
  421. DName __near DName::operator + ( DNameStatus st ) const
  422. {
  423. DName local ( *this );
  424. if ( local.isEmpty ())
  425. local = st;
  426. else
  427. local += st;
  428. // And return the newly formed 'DName'
  429. return local;
  430. } // End of "DName" OPERATOR "+(DNameStatus)"
  431. DName & __near DName::operator += ( char ch )
  432. {
  433. if ( ch )
  434. if ( isEmpty ())
  435. *this = ch;
  436. else
  437. {
  438. node = node->clone ();
  439. if ( node )
  440. *node += gnew charNode ( ch );
  441. else
  442. stat = DN_error;
  443. } // End of IF
  444. // And return self
  445. return *this;
  446. } // End of "DName" OPERATOR "+=(char)"
  447. DName & __near DName::operator += ( pcchar_t str )
  448. {
  449. if ( str && *str )
  450. if ( isEmpty ())
  451. *this = str;
  452. else
  453. {
  454. node = node->clone ();
  455. if ( node )
  456. *node += gnew pcharNode ( str );
  457. else
  458. stat = DN_error;
  459. } // End of IF
  460. // And return self
  461. return *this;
  462. } // End of "DName" OPERATOR "+=(pcchar_t)"
  463. DName & __near DName::operator += ( const DName & rd )
  464. {
  465. if ( rd.isEmpty ())
  466. *this += rd.status ();
  467. else
  468. if ( isEmpty ())
  469. *this = rd;
  470. else
  471. {
  472. node = node->clone ();
  473. if ( node )
  474. *node += rd.node;
  475. else
  476. stat = DN_error;
  477. } // End of IF
  478. // And return self
  479. return *this;
  480. } // End of "DName" OPERATOR "+=(const DName&)"
  481. DName & __near DName::operator += ( DName * pd )
  482. {
  483. if ( pd )
  484. if ( isEmpty ())
  485. *this = pd;
  486. elif (( pd->status () == DN_valid ) || ( pd->status () == DN_truncated ))
  487. {
  488. DNameNode * pNew = gnew pDNameNode ( pd );
  489. if ( pNew )
  490. {
  491. node = node->clone ();
  492. if ( node )
  493. *node += pNew;
  494. } // End of IF then
  495. else
  496. node = 0;
  497. if ( !node )
  498. stat = DN_error;
  499. } // End of IF then
  500. else
  501. *this += pd->status ();
  502. // And return self
  503. return *this;
  504. } // End of "DName" OPERATOR "+=(DName*)"
  505. DName & __near DName::operator += ( DNameStatus st )
  506. {
  507. if ( isEmpty () || (( st == DN_invalid ) || ( st == DN_error )))
  508. *this = st;
  509. else
  510. {
  511. DNameNode * pNew = gnew DNameStatusNode ( st );
  512. if ( pNew )
  513. {
  514. node = node->clone ();
  515. if ( node )
  516. *node += pNew;
  517. } // End of IF then
  518. else
  519. node = 0;
  520. if ( !node )
  521. stat = DN_error;
  522. } // End of IF else
  523. // Return self
  524. return *this;
  525. } // End of "DName" OPERATOR "+=(DNameStatus)"
  526. DName & __near DName::operator |= ( const DName & rd )
  527. {
  528. // Attenuate the error status. Always becomes worse. Don't propogate truncation
  529. if (( status () != DN_error ) && !rd.isValid ())
  530. stat = rd.status ();
  531. // And return self
  532. return *this;
  533. } // End of "DName" OPERATOR '|=(const DName&)'
  534. DName & __near DName::operator = ( char ch )
  535. {
  536. isIndir = 0;
  537. isAUDC = 0;
  538. isAUDTThunk = 0;
  539. isArrayType = 0;
  540. doPchar ( &ch, 1 );
  541. return *this;
  542. } // End of "DName" OPERATOR '=(char)'
  543. DName & __near DName::operator = ( pcchar_t str )
  544. {
  545. isIndir = 0;
  546. isAUDC = 0;
  547. isAUDTThunk = 0;
  548. isArrayType = 0;
  549. doPchar ( str, und_strlen ( str ));
  550. // And return self
  551. return *this;
  552. } // End of "DName" OPERATOR '=(pcchar_t)'
  553. DName & __near DName::operator = ( const DName & rd )
  554. {
  555. if (( status () == DN_valid ) || ( status () == DN_truncated ))
  556. {
  557. stat = rd.stat;
  558. isIndir = rd.isIndir;
  559. isAUDC = rd.isAUDC;
  560. isAUDTThunk = rd.isAUDTThunk;
  561. isArrayType = rd.isArrayType;
  562. node = rd.node;
  563. } // End of IF
  564. // And return self
  565. return *this;
  566. } // End of "DName" OPERATOR '=(const DName&)'
  567. DName & __near DName::operator = ( DName * pd )
  568. {
  569. if (( status () == DN_valid ) || ( status () == DN_truncated ))
  570. if ( pd )
  571. {
  572. isIndir = 0;
  573. isAUDC = 0;
  574. isAUDTThunk = 0;
  575. isArrayType = 0;
  576. node = gnew pDNameNode ( pd );
  577. if ( !node )
  578. stat = DN_error;
  579. } // End of IF then
  580. else
  581. *this = DN_error;
  582. // And return self
  583. return *this;
  584. } // End of "DName" OPERATOR '=(DName*)'
  585. DName & __near DName::operator = ( DNameStatus st )
  586. {
  587. if (( st == DN_invalid ) || ( st == DN_error ))
  588. {
  589. node = 0;
  590. if ( status () != DN_error )
  591. stat = st;
  592. } // End of IF then
  593. elif (( status () == DN_valid ) || ( status () == DN_truncated ))
  594. {
  595. isIndir = 0;
  596. isAUDC = 0;
  597. isAUDTThunk = 0;
  598. isArrayType = 0;
  599. node = gnew DNameStatusNode ( st );
  600. if ( !node )
  601. stat = DN_error;
  602. } // End of ELIF then
  603. // And return self
  604. return *this;
  605. } // End of "DName" OPERATOR '=(DNameStatus)'
  606. // Private implementation functions for 'DName'
  607. void __near DName::doPchar ( pcchar_t str, int len )
  608. {
  609. if ( !(( status () == DN_invalid ) || ( status () == DN_error )))
  610. if ( node )
  611. *this = DN_error;
  612. elif ( str && len )
  613. {
  614. // Allocate as economically as possible
  615. switch ( len )
  616. {
  617. case 0:
  618. stat = DN_error;
  619. break;
  620. case 1:
  621. node = gnew charNode ( *str );
  622. if ( !node )
  623. stat = DN_error;
  624. break;
  625. default:
  626. node = gnew pcharNode ( str, len );
  627. if ( !node )
  628. stat = DN_error;
  629. break;
  630. } // End of SWITCH
  631. } // End of ELIF
  632. else
  633. stat = DN_invalid;
  634. } // End of "DName" FUNCTION "doPchar(pcchar_t,int)"
  635. // The member functions for the 'Replicator'
  636. inline int __near Replicator::isFull () const { return ( index == 9 ); }
  637. inline __near Replicator::Replicator ()
  638. : ErrorDName ( DN_error ), InvalidDName ( DN_invalid )
  639. { index = -1; }
  640. Replicator & __near Replicator::operator += ( const DName & rd )
  641. {
  642. if ( !isFull () && !rd.isEmpty ())
  643. {
  644. DName * pNew = gnew DName ( rd );
  645. // Don't update if failed
  646. if ( pNew )
  647. dNameBuffer[ ++index ] = pNew;
  648. } // End of IF
  649. return *this;
  650. } // End of "Replicator" OPERATOR '+=(const DName&)'
  651. const DName & __near Replicator::operator [] ( int x ) const
  652. {
  653. if (( x < 0 ) || ( x > 9 ))
  654. return ErrorDName;
  655. elif (( index == -1 ) || ( x > index ))
  656. return InvalidDName;
  657. else
  658. return *dNameBuffer[ x ];
  659. } // End of "Replicator" OPERATOR '[](int)'
  660. // The member functions for the 'DNameNode' classes
  661. #if ( !NO_VIRTUAL )
  662. __near DNameNode::DNameNode ()
  663. #else // } elif NO_VIRTUAL {
  664. __near DNameNode::DNameNode ( NodeType ndTy )
  665. : typeIndex ( ndTy )
  666. #endif // NO_VIRTUAL
  667. { next = 0; }
  668. inline __near DNameNode::DNameNode ( const DNameNode & rd ) { next = (( rd.next ) ? rd.next->clone () : 0 ); }
  669. inline DNameNode * __near DNameNode::nextNode () const { return next; }
  670. DNameNode * __near DNameNode::clone ()
  671. {
  672. return gnew pDNameNode ( gnew DName ( this ));
  673. }
  674. #if ( NO_VIRTUAL )
  675. int __near DNameNode::length () const
  676. { // Pure function, should not be called
  677. switch ( typeIndex )
  678. {
  679. case charNode_t:
  680. return ((charNode*)this )->length ();
  681. case pcharNode_t:
  682. return ((pcharNode*)this )->length ();
  683. case pDNameNode_t:
  684. return ((pDNameNode*)this )->length ();
  685. case DNameStatusNode_t:
  686. return ((DNameStatusNode*)this )->length ();
  687. } // End of SWITCH
  688. return 0;
  689. }
  690. char __near DNameNode::getLastChar () const
  691. { // Pure function, should not be called
  692. switch ( typeIndex )
  693. {
  694. case charNode_t:
  695. return ((charNode*)this )->getLastChar ();
  696. case pcharNode_t:
  697. return ((pcharNode*)this )->getLastChar ();
  698. case pDNameNode_t:
  699. return ((pDNameNode*)this )->getLastChar ();
  700. case DNameStatusNode_t:
  701. return ((DNameStatusNode*)this )->getLastChar ();
  702. } // End of SWITCH
  703. return 0;
  704. }
  705. pchar_t __near DNameNode::getString ( pchar_t s, int l ) const
  706. { // Pure function, should not be called
  707. switch ( typeIndex )
  708. {
  709. case charNode_t:
  710. return ((charNode*)this )->getString ( s, l );
  711. case pcharNode_t:
  712. return ((pcharNode*)this )->getString ( s, l );
  713. case pDNameNode_t:
  714. return ((pDNameNode*)this )->getString ( s, l );
  715. case DNameStatusNode_t:
  716. return ((DNameStatusNode*)this )->getString ( s, l );
  717. } // End of SWITCH
  718. return 0;
  719. }
  720. #endif // NO_VIRTUAL
  721. DNameNode & __near DNameNode::operator += ( DNameNode * pNode )
  722. {
  723. if ( pNode )
  724. {
  725. if ( next )
  726. {
  727. // Skip to the end of the chain
  728. DNameNode* pScan;
  729. for ( pScan = next; pScan->next; pScan = pScan->next )
  730. ;
  731. // And append the new node
  732. pScan->next = pNode;
  733. } // End of IF then
  734. else
  735. next = pNode;
  736. } // End of IF
  737. // And return self
  738. return *this;
  739. } // End of "DNameNode" OPERATOR '+=(DNameNode*)'
  740. // The 'charNode' virtual functions
  741. __near charNode::charNode ( char ch )
  742. #if ( NO_VIRTUAL )
  743. : DNameNode ( charNode_t )
  744. #endif // NO_VIRTUAL
  745. { me = ch; }
  746. inline int __near charNode::length () const { return 1; }
  747. inline char __near charNode::getLastChar () const { return me; }
  748. pchar_t __near charNode::getString ( pchar_t buf, int len ) const
  749. {
  750. if ( buf && len )
  751. *buf = me;
  752. else
  753. buf = 0;
  754. // Now return the character
  755. return buf;
  756. } // End of "charNode" FUNCTION "getString(pchar_t,int)"
  757. // The 'pcharNode' virtual functions
  758. inline int __near pcharNode::length () const { return myLen; }
  759. inline char __near pcharNode::getLastChar () const { return ( myLen ? me[ myLen - 1 ] : '\0' ); }
  760. __near pcharNode::pcharNode ( pcchar_t str, int len )
  761. #if ( NO_VIRTUAL )
  762. : DNameNode ( pcharNode_t )
  763. #endif // NO_VIRTUAL
  764. {
  765. // Get length if not supplied
  766. if ( !len && str )
  767. len = und_strlen ( str );
  768. // Allocate a new string buffer if valid state
  769. if ( len && str )
  770. {
  771. me = gnew char[ len ];
  772. myLen = len;
  773. if ( me )
  774. und_strncpy ( me, str, len );
  775. } // End of IF then
  776. else
  777. {
  778. me = 0;
  779. myLen = 0;
  780. } // End of IF else
  781. } // End of "pcharNode" CONSTRUCTOR '(pcchar_t,int)'
  782. pchar_t __near pcharNode::getString ( pchar_t buf, int len ) const
  783. {
  784. // Use the shorter of the two lengths (may not be NULL terminated)
  785. if ( len > pcharNode::length ())
  786. len = pcharNode::length ();
  787. // Do the copy as appropriate
  788. return (( me && buf && len ) ? und_strncpy ( buf, me, len ) : 0 );
  789. } // End of "pcharNode" FUNCTION "getString(pchar_t,int)"
  790. // The 'pDNameNode' virtual functions
  791. __near pDNameNode::pDNameNode ( DName * pName )
  792. #if ( NO_VIRTUAL )
  793. : DNameNode ( pDNameNode_t )
  794. #endif // NO_VIRTUAL
  795. { me = (( pName && (( pName->status () == DN_invalid ) || ( pName->status () == DN_error ))) ? 0 : pName ); }
  796. inline int __near pDNameNode::length () const { return ( me ? me->length () : 0 ); }
  797. inline char __near pDNameNode::getLastChar () const { return ( me ? me->getLastChar () : '\0' ); }
  798. pchar_t __near pDNameNode::getString ( pchar_t buf, int len ) const
  799. { return (( me && buf && len ) ? me->getString ( buf, len ) : 0 ); }
  800. // The 'DNameStatusNode' virtual functions
  801. __near DNameStatusNode::DNameStatusNode ( DNameStatus stat )
  802. #if ( NO_VIRTUAL )
  803. : DNameNode ( DNameStatusNode_t )
  804. #endif // NO_VIRTUAL
  805. { me = stat; myLen = (( me == DN_truncated ) ? TruncationMessageLength : 0 ); }
  806. inline int __near DNameStatusNode::length () const { return myLen; }
  807. inline char __near DNameStatusNode::getLastChar () const
  808. { return (( me == DN_truncated ) ? TruncationMessage[ TruncationMessageLength - 1 ] : '\0' ); }
  809. pchar_t __near DNameStatusNode::getString ( pchar_t buf, int len ) const
  810. {
  811. // Use the shorter of the two lengths (may not be NULL terminated)
  812. if ( len > DNameStatusNode::length ())
  813. len = DNameStatusNode::length ();
  814. // Do the copy as appropriate
  815. return ((( me == DN_truncated ) && buf && len ) ? und_strncpy ( buf, TruncationMessage, len ) : 0 );
  816. } // End of "DNameStatusNode" FUNCTION "getString(pchar_t,int)"
  817. static unsigned int __near __pascal und_strlen ( pcchar_t str )
  818. {
  819. unsigned int len;
  820. for ( len = 0; *str; str++ )
  821. len++;
  822. return len;
  823. } // End of FUNCTION "und_strlen"
  824. static pchar_t __near __pascal und_strncpy ( pchar_t dst, pcchar_t src, unsigned int len )
  825. {
  826. for ( char __far * d = dst; ( len && ( *d = *src )); d++, src++, len-- )
  827. ;
  828. return dst;
  829. } // End of FUNCTION "und_strncpy"
  830. static unsigned int __near __pascal und_strncmp ( pcchar_t first, pcchar_t last, unsigned int count)
  831. {
  832. if (!count)
  833. return(0);
  834. while (--count && *first && *first == *last)
  835. {
  836. first++;
  837. last++;
  838. }
  839. return( *(unsigned char *)first - *(unsigned char *)last );
  840. }