Leaked source code of windows server 2003
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.

846 lines
34 KiB

  1. /*
  2. * Copyright Microsoft Corporation, 1983-1989
  3. *
  4. * This Module contains Proprietary Information of Microsoft
  5. * Corporation and should be treated as Confidential.
  6. */
  7. /*
  8. * NEWSYM.C -- Symbol table routine.
  9. *
  10. * Modifications:
  11. *
  12. * 05-Jan-1989 RB Delete MaskSymbols hack.
  13. */
  14. #include <minlit.h> /* Types and constants */
  15. #include <bndtrn.h> /* More types and constants */
  16. #include <bndrel.h> /* More types and constants */
  17. #include <lnkio.h> /* Linker I/O definitions */
  18. #include <lnkmsg.h> /* Error messages */
  19. #include <extern.h> /* External declarations */
  20. #if NEWSYM
  21. #if OSXENIX
  22. #define _osmode 1 /* Xenix is always protect mode */
  23. #endif
  24. #endif /* NEWSYM */
  25. #ifndef IRHTEMAX
  26. #ifdef DOSX32
  27. #define IRHTEMAX 16384
  28. #else
  29. #define IRHTEMAX 256
  30. #endif
  31. #endif
  32. LOCAL WORD IHashKey(BYTE *psb);
  33. LOCAL PROPTYPE CreateNewSym(WORD irhte, BYTE *psym, ATTRTYPE attr);
  34. #if AUTOVM
  35. LOCAL RBTYPE AllocVirtMem(WORD cb);
  36. LOCAL FTYPE fVirtualAllocation = FALSE;
  37. #endif
  38. #define _32k 0x8000
  39. typedef struct _SymTabBlock
  40. {
  41. struct _SymTabBlock FAR *next;
  42. WORD size;
  43. WORD used;
  44. BYTE FAR *mem;
  45. }
  46. SYMTABBLOCK;
  47. SYMTABBLOCK *pSymTab;
  48. SYMTABBLOCK FAR *pCurBlock;
  49. #if NOT NEWSYM
  50. BYTE symtab[CBMAXSYMSRES];
  51. /* Resident portion of symbol table */
  52. #endif
  53. LOCAL BYTE mpattrcb[] = /* Attribute size have to be <= 255 */
  54. /* Map attribute to struct size */
  55. {
  56. 3,
  57. CBPROPSN, /* Size of APROPSNTYPE */
  58. CBPROPSN, /* Size of APROPSNTYPE */
  59. (CBPROPNAME>CBPROPUNDEF)? CBPROPNAME: CBPROPUNDEF,
  60. /* Max(CBPROPNAME,CBPROPUNDEF) */
  61. (CBPROPNAME>CBPROPUNDEF)? CBPROPNAME: CBPROPUNDEF,
  62. /* Max(CBPROPNAME,CBPROPUNDEF) */
  63. CBPROPFILE, /* Size of APROPFILETYPE */
  64. CBPROPGROUP, /* Size of APROPGROUPTYPE */
  65. (CBPROPNAME>CBPROPUNDEF)? CBPROPNAME: CBPROPUNDEF,
  66. /* Max(CBPROPNAME,CBPROPUNDEF) */
  67. CBHTE, /* Size of AHTETYPE */
  68. CBPROPCOMDAT, /* Size of APROPCOMDAT */
  69. CBPROPALIAS, /* Size of APROPALIAS */
  70. #if OSEGEXE
  71. /* These two are always at the end */
  72. /* Adding something make sure that */
  73. /* this stays that way */
  74. CBPROPEXP, /* Size of APROPEXPTYPE */
  75. CBPROPIMP, /* Size of APROPIMPTYPE */
  76. #endif
  77. 3
  78. };
  79. #if NEWSYM AND (CPU8086 OR CPU286 OR DOSEXTENDER)
  80. LOCAL WORD cbMaxBlk; /* # bytes available in block */
  81. LOCAL WORD cbMacBlk; /* # bytes allocated in block */
  82. LOCAL WORD saBlk; /* Address of current block */
  83. #endif
  84. /*
  85. * INTERFACE TO ASSEMBLY LANGUAGE FUNCTIONS
  86. */
  87. #if NEWSYM AND (CPU8086 OR CPU286 OR DOSEXTENDER)
  88. WORD saFirst; /* Address of 1st block */
  89. #endif
  90. RBTYPE rgrhte[IRHTEMAX];
  91. /* Symbol hash table */
  92. /****************************************************************
  93. * *
  94. * InitSym: *
  95. * *
  96. * This function takes no arguments and returns no meaningful *
  97. * value. It initializes the symbol table handler. *
  98. * *
  99. ****************************************************************/
  100. void InitSym(void) /* Initialize symbol table handler */
  101. {
  102. // Allocate first symbol table memory block
  103. pSymTab = (SYMTABBLOCK FAR *) GetMem(sizeof(SYMTABBLOCK));
  104. pSymTab->mem = (BYTE FAR *) GetMem(_32k);
  105. pSymTab->size = _32k;
  106. pSymTab->used = 0;
  107. pCurBlock = pSymTab;
  108. }
  109. #if AUTOVM
  110. /****************************************************************
  111. * *
  112. * FetchSym: *
  113. * *
  114. * This function fetches a symbol from the symbol table given *
  115. * its virtual address. The symbol may either be resident or *
  116. * in virtual memory. *
  117. * *
  118. ****************************************************************/
  119. BYTE FAR * NEAR FetchSym(rb, fDirty)
  120. RBTYPE rb; /* Virtual address */
  121. WORD fDirty; /* Dirty page flag */
  122. {
  123. union {
  124. long vptr; /* Virtual pointer */
  125. BYTE FAR *fptr; /* FAR pointer */
  126. struct {
  127. unsigned short offset;
  128. /* Offset value */
  129. unsigned short seg;
  130. } /* Segmnet value */
  131. ptr;
  132. }
  133. pointer; /* Different ways to describe pointer */
  134. pointer.fptr = rb;
  135. if(pointer.ptr.seg) /* If resident - segment value != 0 */
  136. {
  137. picur = 0; /* Picur not valid */
  138. return(pointer.fptr); /* Return pointer */
  139. }
  140. pointer.fptr = (BYTE FAR *) mapva(AREASYMS + (pointer.vptr << SYMSCALE),fDirty);
  141. /* Fetch from virtual memory */
  142. return(pointer.fptr);
  143. }
  144. #endif
  145. /****************************************************************
  146. * *
  147. * IHashKey: *
  148. * *
  149. * This function hashes a length-prefixed string and returns *
  150. * hash value. *
  151. * *
  152. ****************************************************************/
  153. #if NOASM
  154. #define FOUR_BYTE_HASH
  155. #ifdef FOUR_BYTE_HASH
  156. LOCAL WORD IHashKey(psb)
  157. BYTE *psb; /* Pointer to length-prefixed string */
  158. {
  159. unsigned cb = *psb++;
  160. unsigned hash = cb;
  161. while (cb >= sizeof(unsigned))
  162. {
  163. hash = ((hash >> 28) | (hash << 4)) ^ (*(unsigned UNALIGNED *)psb | 0x20202020);
  164. cb -= sizeof(unsigned);
  165. psb += sizeof(unsigned);
  166. }
  167. while (cb)
  168. {
  169. hash = ((hash >> 28) | (hash << 4)) ^ (*psb++ | 0x20);
  170. cb--;
  171. }
  172. return ((WORD)hash) ^ (WORD)(hash>>16);
  173. }
  174. #else
  175. LOCAL WORD IHashKey(psb)
  176. BYTE *psb; /* Pointer to length-prefixed string */
  177. {
  178. #if defined(M_I386)
  179. _asm
  180. {
  181. push edi ; Save edi
  182. push esi ; Save esi
  183. mov ebx, psb ; ebx = pointer to length prefixed string
  184. xor edx, edx
  185. mov dl, byte ptr [ebx] ; edx = string length
  186. mov edi, edx ; edi = hash value
  187. mov esi, ebx
  188. add esi, edx ; esi = &psb[psb[0]]
  189. std ; Loop down
  190. HashLoop:
  191. xor eax, eax
  192. lodsb ; Get char from DS:ESI into AL
  193. or eax, 0x20
  194. mov cl, dl
  195. and cl, 3
  196. shl eax, cl
  197. add edi, eax
  198. dec edx
  199. jg HashLoop ; Allow for EDX = -1 here so we don't have to special-case null symbol.
  200. cld
  201. mov eax, edi ; eax = hash value
  202. pop esi
  203. pop edi
  204. }
  205. #else
  206. REGISTER WORD i; /* Index */
  207. REGISTER WORD hashval; /* Hash value */
  208. /* NOTE: IRHTEMAX MUST BE 256 OR THIS FUNCTION WILL FAIL */
  209. hashval = B2W(psb[0]); /* Get length as initial hash value */
  210. #if DEBUG
  211. fputs("Hashing ",stderr); /* Message */
  212. OutSb(stderr,psb); /* Symbol */
  213. fprintf(stderr," length %d\r\n",hashval);
  214. /* Length */
  215. #endif
  216. for(i = hashval; i; --i) /* Loop through string */
  217. {
  218. /*
  219. * Old hash function:
  220. *
  221. * hashval = rorb(hashval,2) ^ (B2W(psb[i]) | 040);
  222. */
  223. hashval += (WORD) ((B2W(psb[i]) | 040) << (i & 3));
  224. /* Hash */
  225. }
  226. #if DEBUG
  227. fprintf(stderr,"Hash value: %u\r\n",hashval);
  228. #endif
  229. #if IRHTEMAX == 512
  230. return((hashval & 0xfeff) | ((psb[0] & 1) << 8));
  231. #else
  232. return(hashval); /* Return value */
  233. #endif
  234. #endif // M_I386
  235. }
  236. #endif /*FOUR_BYTE_HASH*/
  237. #endif /*NOASM*/
  238. #if AUTOVM
  239. /****************************************************************
  240. * *
  241. * AllocVirtMem: *
  242. * *
  243. * This function takes as its input a WORD n, and it allocates *
  244. * n continguous bytes in the symbol area and returns a *
  245. * virtual pointer to the first of those bytes. The bytes *
  246. * are guaranteed to reside on the same virtual page. *
  247. * *
  248. ****************************************************************/
  249. LOCAL RBTYPE AllocVirtMem(cb)
  250. WORD cb;
  251. {
  252. WORD rbLimVbf; /* End of current page */
  253. WORD rb; /* Address of allocated bytes */
  254. WORD x;
  255. ASSERT(cb <= PAGLEN); /* Cannot alloc. more than 512 bytes */
  256. x = cb;
  257. cb = (WORD) ((cb + (1 << SYMSCALE) - 1) >> SYMSCALE);
  258. /* Determine number of units wanted */
  259. if(rbMacSyms > (WORD) (0xFFFF - cb)) Fatal(ER_symovf);
  260. /* Check for symbol table overflow */
  261. rbLimVbf = (rbMacSyms + (1 << (LG2PAG - SYMSCALE)) - 1) &
  262. (~0 << (LG2PAG - SYMSCALE)); /* Find limit of current page */
  263. if((WORD) (rbMacSyms + cb) > rbLimVbf && rbLimVbf) rbMacSyms = rbLimVbf;
  264. /* If alloc. would cross page
  265. * boundary, start with new page
  266. */
  267. rb = rbMacSyms; /* Get address to return */
  268. rbMacSyms += cb; /* Update pointer to end of area */
  269. #if FALSE
  270. fprintf(stderr,"Allocated %u bytes at VA %x\r\n",cb << SYMSCALE,rb);
  271. #endif
  272. return((BYTE FAR *) (long) rb);
  273. /* Return the address */
  274. }
  275. #endif
  276. /*** RbAllocSymNode - symbol table memory allocator
  277. *
  278. * Purpose:
  279. * This function takes as its input a WORD n, and it allocates
  280. * n continguous bytes in the symbol area and returns a
  281. * pointer to the first of those bytes. The bytes are
  282. * guaranteed to reside on the same virtual page (when not in
  283. * memory).
  284. *
  285. *
  286. * Input:
  287. * cb - number of bytes to allocate
  288. *
  289. * Output:
  290. * Pointer to allocated memory area. Pointer can be real or virtual.
  291. *
  292. * Exceptions:
  293. * I/O error in temporary file used for VM.
  294. *
  295. * Notes:
  296. * Uses differnet strategy depending under which operating system
  297. * memory is allocated.
  298. *
  299. *************************************************************************/
  300. RBTYPE NEAR RbAllocSymNode(WORD cb)
  301. {
  302. SYMTABBLOCK FAR *pTmp;
  303. RBTYPE rb; /* Address of allocated bytes */
  304. #if defined( _WIN32 )
  305. // Round up allocation size to keep returned pointers
  306. // at least DWORD aligned.
  307. cb = ( cb + sizeof(DWORD) - 1 ) & ~( sizeof(DWORD) - 1 );
  308. #endif // _WIN32
  309. if ((WORD) (pCurBlock->used + cb) >= pCurBlock->size)
  310. {
  311. // Allocate new symbol table memory block
  312. pTmp = (SYMTABBLOCK FAR *) GetMem(sizeof(SYMTABBLOCK));
  313. pTmp->mem = (BYTE FAR *) GetMem(_32k);
  314. pTmp->size = _32k;
  315. pTmp->used = 0;
  316. pCurBlock->next = pTmp;
  317. pCurBlock = pTmp;
  318. }
  319. // Sub-allocated in the current block
  320. rb = (RBTYPE) &(pCurBlock->mem[pCurBlock->used]);
  321. pCurBlock->used += cb;
  322. cbSymtab += cb;
  323. return(rb);
  324. }
  325. void FreeSymTab(void)
  326. {
  327. SYMTABBLOCK FAR *pTmp;
  328. SYMTABBLOCK FAR *pNext;
  329. FFREE(mplnamerhte);
  330. FFREE(mpsegraFirst);
  331. FFREE(mpgsndra);
  332. FFREE(mpgsnrprop);
  333. FFREE(mpsegsa);
  334. FFREE(mpgsnseg);
  335. FFREE(mpseggsn);
  336. for (pTmp = pSymTab; pTmp != NULL;)
  337. {
  338. pNext = pTmp->next;
  339. FFREE(pTmp->mem);
  340. FFREE(pTmp);
  341. pTmp = pNext;
  342. }
  343. }
  344. /****************************************************************
  345. * *
  346. * PropAdd: *
  347. * *
  348. * This function adds a property to a hash table entry node. *
  349. * It returns the location of the property. Inputs are the *
  350. * virtual address of the hash table entry and the attribute *
  351. * (or property) to be added. *
  352. * *
  353. ****************************************************************/
  354. PROPTYPE NEAR PropAdd(rhte,attr)
  355. RBTYPE rhte; /* Virtual addr of hash tab ent */
  356. ATTRTYPE attr; /* Attribute to add to entry */
  357. {
  358. REGISTER AHTEPTR hte; /* Hash table entry pointer */
  359. REGISTER APROPPTR aprop; /* Property list pointer */
  360. RBTYPE rprop; /* Property cell list pointer */
  361. DEBUGVALUE(rhte); /* Debug info */
  362. DEBUGVALUE(attr); /* Debug info */
  363. hte = (AHTEPTR ) FetchSym(rhte,TRUE);
  364. /* Fetch from VM */
  365. DEBUGVALUE(hte); /* Debug info */
  366. rprop = hte->rprop; /* Save pointer to property list */
  367. vrprop = RbAllocSymNode(mpattrcb[attr]);
  368. /* Allocate symbol space */
  369. hte->rprop = vrprop; /* Complete link */
  370. aprop = (APROPPTR ) FetchSym(vrprop,TRUE);
  371. /* Fetch the property cell */
  372. FMEMSET(aprop,'\0',mpattrcb[attr]); /* Zero the space */
  373. aprop->a_attr = attr; /* Store the attribute */
  374. aprop->a_next = rprop; /* Set link */
  375. #if NEW_LIB_SEARCH
  376. if (attr == ATTRUND && fStoreUndefsInLookaside)
  377. StoreUndef((APROPNAMEPTR)aprop, rhte, 0, 0);
  378. #endif
  379. return((PROPTYPE) aprop); /* Return pointer */
  380. }
  381. /****************************************************************
  382. * *
  383. * PropRhteLookup: *
  384. * *
  385. * "Look up a property on hash table entry (possibly creating *
  386. * it) and return pointer to property. *
  387. * *
  388. * Input: rhte Virtual address of hash table entry. *
  389. * attr Property to look up. *
  390. * fCreate Flag to create property cell if not *
  391. * present. *
  392. * Return: pointer to property cell." *
  393. * *
  394. ****************************************************************/
  395. PROPTYPE NEAR PropRhteLookup(rhte,attr,fCreate)
  396. RBTYPE rhte; /* Virt. addr. of hash table entry */
  397. ATTRTYPE attr; /* Property to look up */
  398. FTYPE fCreate; /* Create property cell flag */
  399. {
  400. REGISTER APROPPTR aprop;
  401. AHTEPTR ahte;
  402. DEBUGVALUE(rhte); /* Debug info */
  403. DEBUGVALUE(attr); /* Debug info */
  404. DEBUGVALUE(fCreate); /* Debug info */
  405. vrhte = rhte; /* Set global */
  406. ahte = (AHTEPTR ) FetchSym(rhte,FALSE);
  407. /* Fetch symbol */
  408. vrprop = ahte->rprop;
  409. vfCreated = FALSE; /* Assume no creation takes place */
  410. for(;;)
  411. {
  412. aprop = (APROPPTR ) FetchSym(vrprop,FALSE);
  413. /* Fetch from VM */
  414. if(aprop->a_attr == attr) /* If match found */
  415. {
  416. DEBUGMSG("Match found"); /* Debug message */
  417. return((PROPTYPE) aprop); /* Return address of cell */
  418. }
  419. DEBUGMSG("Following link:"); /* Debug message */
  420. vrprop = aprop->a_next; /* Try next item in list */
  421. DEBUGVALUE(vrprop); /* Debug info */
  422. if(aprop->a_attr == ATTRNIL) /* If no entry here */
  423. {
  424. DEBUGMSG("Match NOT found");/* Debug message */
  425. if(!fCreate) /* If creation inhibited */
  426. {
  427. /* Debug info */
  428. return(PROPNIL); /* Return nil pointer */
  429. }
  430. vfCreated = (FTYPE) TRUE; /* A new creation! */
  431. DEBUGMSG("Leaving PropRhteLookup with value of PropAdd");
  432. /* Debug message */
  433. return(PropAdd(vrhte,attr));/* Let someone else do it */
  434. }
  435. }
  436. }
  437. /****************************************************************
  438. * *
  439. * RhteFromProp: *
  440. * *
  441. * give back the master rhte for this prop entry *
  442. * *
  443. * Input: aprop mapped address of the propery cell *
  444. * *
  445. * Return: Virtual address of hash table entry. *
  446. * *
  447. ****************************************************************/
  448. RBTYPE NEAR RhteFromProp(aprop)
  449. APROPPTR aprop; /* address of property block */
  450. {
  451. RBTYPE MYvrprop;
  452. /* if we're already at the head, we have to go all the way around
  453. * to compute the *virutal* address of the head
  454. */
  455. for(;;)
  456. {
  457. DEBUGMSG("Following link:"); /* Debug message */
  458. MYvrprop = aprop->a_next; /* Try next item in list */
  459. DEBUGVALUE(MYvrprop); /* Debug info */
  460. aprop = (APROPPTR) FetchSym(MYvrprop,FALSE);
  461. /* Fetch from VM */
  462. if(aprop->a_attr == ATTRNIL) /* If no entry here */
  463. {
  464. return(MYvrprop); /* found head -- return it */
  465. }
  466. }
  467. }
  468. #if NEWSYM AND NOASM
  469. FTYPE NEAR SbNewComp(ps1,ps2,fncs)
  470. BYTE *ps1; /* Pointer to symbol */
  471. BYTE FAR *ps2; /* Pointer to FAR symbol */
  472. FTYPE fncs; /* True if not case-sensitive */
  473. {
  474. WORD length; /* No. of char.s to compare */
  475. length = B2W(*ps1); /* Get length */
  476. if (!fncs) /* If case-sensitive */
  477. { /* Simple string comparison */
  478. while (length && (*++ps1 == *++ps2)) {
  479. length--;
  480. }
  481. return((FTYPE) (length ? FALSE : TRUE)); /* Success iff nothing left */
  482. }
  483. while(length--)
  484. {
  485. #ifdef _MBCS
  486. ps1++;
  487. ps2++;
  488. if (IsLeadByte(*ps1))
  489. if (*((WORD *)ps1) != *((WORD *)ps2)) {
  490. return FALSE;
  491. }
  492. else {
  493. ps1++;
  494. ps2++;
  495. length--;
  496. continue;
  497. }
  498. else
  499. #else
  500. if(*++ps1 == *++ps2)
  501. continue; /* Bytes match */
  502. else
  503. #endif
  504. if((*ps1 & 0137) != (*ps2 & 0137)) {
  505. return(FALSE);
  506. }
  507. }
  508. return(TRUE); /* They match */
  509. }
  510. #endif
  511. /****************************************************************
  512. * *
  513. * PropSymLookup: *
  514. * *
  515. * This function looks up a symbol and its property. It *
  516. * can create an entry, if necessary. It returns a pointer to *
  517. * the property cell. It takes as its inputs a pointer to a *
  518. * symbol, the property to look up, and a flag which specifies *
  519. * if a new property cell is to be created in the event that *
  520. * one of the given type does not already exist. *
  521. * *
  522. ****************************************************************/
  523. #if NOASM
  524. PROPTYPE NEAR PropSymLookup(psym,attr,fCreate)
  525. BYTE *psym; /* Pointer to length-prefixed string */
  526. ATTRTYPE attr; /* Attribute to look up */
  527. WORD fCreate; /* Create prop cell if not found */
  528. {
  529. AHTEPTR ahte; /* Pointer to hash table entry */
  530. WORD hashval; /* Hash value */
  531. #if DEBUG /* If debugging on */
  532. fputs("Looking up ",stderr); /* Message */
  533. OutSb(stderr,psym); /* Symbol */
  534. fprintf(stderr,"(%d) with attr %d\r\n",B2W(psym[0]),B2W(attr));
  535. #endif /* End debugging code */
  536. hashval = IHashKey(psym); /* Get hash index */
  537. vrhte = rgrhte[hashval % IRHTEMAX]; /* Get VM address of chain */
  538. vfCreated = FALSE; /* Assume nothing will be created */
  539. for(;;)
  540. {
  541. DEBUGVALUE(vrhte); /* Debug info */
  542. if(vrhte == RHTENIL) /* If nil pointer */
  543. {
  544. DEBUGMSG("Empty slot found");
  545. /* Debug message */
  546. if(!fCreate) /* If creation inhibited */
  547. {
  548. return(PROPNIL); /* Return nil pointer */
  549. }
  550. else
  551. {
  552. DEBUGMSG("Leaving PropSymLookup with value of CreateNewSym");
  553. return CreateNewSym(hashval, psym, attr);
  554. }
  555. }
  556. DEBUGMSG("Collision"); /* Debug message */
  557. ahte = (AHTEPTR ) FetchSym(vrhte,FALSE);
  558. /* Fetch from VM */
  559. #if DEBUG
  560. fputs("Comparing \"",stderr); /* Message */
  561. OutSb(stderr,psym); /* Symbol */
  562. fprintf(stderr,"\"(%d) to \"",B2W(psym[0]));
  563. /* Message */
  564. OutSb(stderr,GetFarSb(ahte->cch)); /* Symbol */
  565. fprintf(stderr,"\"(%d) %signoring case\r\n",
  566. B2W(ahte->cch[0]),fIgnoreCase? "": "NOT ");
  567. /* Message */
  568. #endif
  569. if(hashval == ahte->hashval && psym[0] == ahte->cch[0]
  570. && SbNewComp(psym,(BYTE FAR *)ahte->cch,fIgnoreCase))
  571. { /* If a match found */
  572. DEBUGMSG("Match found"); /* Debug message */
  573. DEBUGMSG("Leaving PropSymLookup w/ val of PropRhteLookup");
  574. return(PropRhteLookup(vrhte,attr, (FTYPE) fCreate));
  575. /* Return property cell pointer */
  576. }
  577. vrhte = ahte->rhteNext; /* Move down list */
  578. DEBUGMSG("Following link:"); /* Debug message */
  579. DEBUGVALUE(vrhte); /* Debug info */
  580. }
  581. }
  582. #endif /*NOASM*/
  583. /****************************************************************
  584. * *
  585. * CreateNewSym: *
  586. * *
  587. * This function adds the given symbol into the hash table at *
  588. * the position indicated by hashval. If attr is not ATTRNIL *
  589. * then it also creates the specified property type *
  590. * *
  591. ****************************************************************/
  592. LOCAL PROPTYPE NEAR CreateNewSym(hashval, psym, attr)
  593. WORD hashval; /* the hash value of this symbol */
  594. BYTE *psym; /* Pointer to length-prefixed string */
  595. ATTRTYPE attr; /* Attribute to create */
  596. {
  597. AHTEPTR ahte; /* Pointer to hash table entry */
  598. WORD irhte; /* hash bucket */
  599. irhte = hashval % IRHTEMAX;
  600. vfCreated = TRUE; /* New creation */
  601. vrhte = RbAllocSymNode((WORD) (CBHTE + B2W(psym[0])));
  602. /* Allocate space for symbol entry */
  603. ahte = (AHTEPTR ) FetchSym(vrhte,TRUE);
  604. /* Fetch symbol from virtual memory */
  605. ahte->rhteNext = rgrhte[irhte];
  606. /* Tack on chain */
  607. DEBUGMSG("Origin of original chain:");
  608. DEBUGVALUE(rgrhte[irhte]); /* Debug info */
  609. ahte->attr = ATTRNIL; /* Symbol has Nil attribute */
  610. ahte->rprop = vrhte; /* Prop list points to self */
  611. ahte->hashval = hashval; /* Save hash value */
  612. memcpy(ahte->cch, psym, psym[0] + 1);
  613. rgrhte[irhte] = vrhte; /* Make new symbol first in chain */
  614. DEBUGMSG("Origin of new chain:");
  615. DEBUGVALUE(rgrhte[irhte]); /* Debug info */
  616. if(attr != ATTRNIL) /* If property to give symbol */
  617. {
  618. DEBUGMSG("Leaving PropSymLookup with the value of PropAdd");
  619. return(PropAdd(vrhte,attr));
  620. /* Add the attribute */
  621. }
  622. /* Debug info */
  623. return(PROPNIL); /* Nothing to return */
  624. }
  625. /****************************************************************
  626. * *
  627. * The legendary EnSyms: *
  628. * *
  629. * This function applies a function to all symbol/property *
  630. * pairs that have a particular property. It takes as its *
  631. * inputs a pointer to a function to call and a property to *
  632. * look for. EnSyms() does not return a meaningful value. *
  633. * *
  634. ****************************************************************/
  635. void BigEnSyms(void (*pproc)(APROPNAMEPTR papropName,
  636. RBTYPE rhte,
  637. RBTYPE rprop,
  638. WORD fNewHte), ATTRTYPE attr)
  639. {
  640. APROPPTR aprop; /* Pointer to a property cell */
  641. AHTEPTR ahte; /* Pointer to a hash table entry */
  642. WORD irhte; /* Hash table index */
  643. RBTYPE rhte; /* Hash table entry address */
  644. ATTRTYPE attrT;
  645. FTYPE fNewHte;
  646. RBTYPE rprop;
  647. RBTYPE rhteNext;
  648. RBTYPE rpropNext;
  649. DEBUGVALUE(attr); /* Debug info */
  650. for(irhte = 0; irhte < IRHTEMAX; ++irhte)
  651. { /* Look through hash table */
  652. rhte = rgrhte[irhte]; /* Get pointer to chain */
  653. while(rhte != RHTENIL) /* While not at end of chain */
  654. {
  655. DEBUGVALUE(rhte); /* Debug info */
  656. ahte = (AHTEPTR ) FetchSym(rhte,FALSE);
  657. /* Fetch entry from VM */
  658. DEBUGSB(ahte->cch); /* Debug info */
  659. fNewHte = (FTYPE) TRUE; /* First call on this hash tab entry */
  660. rhteNext = ahte->rhteNext; /* Get pointer to next in chain */
  661. rprop = ahte->rprop; /* Get pointer to property list */
  662. for(;;) /* Loop to search property list */
  663. {
  664. aprop = (APROPPTR ) FetchSym(rprop,FALSE);
  665. /* Fetch entry from symbol table */
  666. rpropNext = aprop->a_next;
  667. /* Get pointer to next in list */
  668. attrT = aprop->a_attr; /* Get the attribute */
  669. DEBUGVALUE(attrT); /* Debug info */
  670. if(attr == attrT || attr == ATTRNIL)
  671. { /* If property is acceptable */
  672. (*pproc)((APROPNAMEPTR) aprop, rhte, rprop, (WORD) fNewHte);
  673. /* Apply function to node */
  674. fNewHte = FALSE; /* Next call (if any) won't be first */
  675. }
  676. if(attrT == ATTRNIL) break;
  677. /* Break if at end of prop list */
  678. rprop = rpropNext; /* Move down the list */
  679. }
  680. rhte = rhteNext; /* Move down the chain */
  681. }
  682. }
  683. }
  684. #if PROFSYM
  685. /*
  686. * ProfSym : Profile the symbol table, displaying results to stdout
  687. */
  688. void ProfSym ()
  689. {
  690. REGISTER AHTEPTR ahte; /* Pointer to a hash table entry */
  691. WORD irhte; /* Hash table index */
  692. RBTYPE rhte; /* Hash table entry address */
  693. unsigned cSymbols = 0; /* # of symtab entries */
  694. unsigned cBktlen = 0; /* Total length of buckets */
  695. unsigned bucketlen; /* Current bucket length */
  696. unsigned maxBkt = 0;
  697. long sumBktSqr = 0L; /* Sum of bucketlen squared */
  698. int bdist[6];
  699. bdist[0] = bdist[1] = bdist[2] = bdist[3] = bdist[4] = bdist[5] = 0;
  700. for(irhte = 0; irhte < IRHTEMAX; ++irhte)
  701. { /* Look through hash table */
  702. rhte = rgrhte[irhte]; /* Get pointer to chain */
  703. bucketlen = 0;
  704. while(rhte != RHTENIL) /* While not at end of chain */
  705. {
  706. ++cSymbols;
  707. ++bucketlen;
  708. ahte = (AHTEPTR ) FetchSym(rhte,FALSE);
  709. rhte = ahte->rhteNext; /* Move down the chain */
  710. }
  711. if (bucketlen >= 5)
  712. bdist[5]++;
  713. else
  714. bdist[bucketlen]++;
  715. sumBktSqr += bucketlen * bucketlen;
  716. cBktlen += bucketlen;
  717. if(bucketlen > maxBkt) maxBkt = bucketlen;
  718. }
  719. fprintf(stdout,"\r\n");
  720. fprintf(stdout,"Total number of buckets = %6u\r\n",IRHTEMAX);
  721. fprintf(stdout,"Total number of symbols = %6u\r\n",cSymbols);
  722. fprintf(stdout,"Sum of bucketlen^2 = %6lu\r\n",sumBktSqr);
  723. fprintf(stdout,"(cSymbols^2)/#buckets = %6lu\r\n",
  724. ((long) cSymbols * cSymbols) / IRHTEMAX);
  725. fprintf(stdout,"Average bucket length = %6u\r\n",cBktlen/IRHTEMAX);
  726. fprintf(stdout,"Maximum bucket length = %6u\r\n",maxBkt);
  727. fprintf(stdout,"# of buckets with 0 = %6u\r\n",bdist[0]);
  728. fprintf(stdout,"# of buckets with 1 = %6u\r\n",bdist[1]);
  729. fprintf(stdout,"# of buckets with 2 = %6u\r\n",bdist[2]);
  730. fprintf(stdout,"# of buckets with 3 = %6u\r\n",bdist[3]);
  731. fprintf(stdout,"# of buckets with 4 = %6u\r\n",bdist[4]);
  732. fprintf(stdout,"# of buckets with >= 5 = %6u\r\n",bdist[5]);
  733. fprintf(stdout,"\r\n");
  734. }
  735. #endif /*PROFSYM*/
  736. #if DEBUG AND ( NOT defined( _WIN32 ) )
  737. void DispMem( void)
  738. {
  739. unsigned int mem_para, mem_kb;
  740. unsigned int error_code=0;
  741. _asm{
  742. mov bx, 0xffff
  743. mov ax, 0x4800
  744. int 21h
  745. jc Error
  746. mov bx, 0xffff
  747. jmp MyEnd
  748. Error:
  749. mov error_code, ax
  750. MyEnd:
  751. mov mem_para, bx
  752. }
  753. mem_kb = mem_para>>6;
  754. if(error_code == 8 || error_code)
  755. fprintf( stdout, "\r\nAvailable Memory: %u KB, %u paragraphs, error: %d\r\n", mem_kb, mem_para, error_code);
  756. else
  757. fprintf( stdout, "\r\nMemory Error No %d\r\n", error_code);
  758. fflush(stdout);
  759. }
  760. #endif