sourcepawn/compiler/sp_symhash.c
author Asher Baker <asherkin@gmail.com>
Sun Jul 29 02:51:50 2012 +0100 (2012-07-29)
changeset 3590 6908e80a69af
parent 3078 a246d38d2c41
permissions -rw-r--r--
Added some useful IDA scripts (NPOTB).
     1 /* vim: set ts=4 sw=4 tw=99 et: */
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <assert.h>
     5 #include "sp_file_headers.h"
     6 #include "sc.h"
     7 #include "sp_symhash.h"
     8 
     9 SC_FUNC uint32_t
    10 NameHash(const char *str)
    11 {
    12   size_t len = strlen(str);
    13   const uint8_t *data = (uint8_t *)str;
    14   #undef get16bits
    15   #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
    16       || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
    17     #define get16bits(d) (*((const uint16_t *) (d)))
    18   #endif
    19   #if !defined (get16bits)
    20     #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
    21                      +(uint32_t)(((const uint8_t *)(d))[0]) )
    22   #endif
    23   uint32_t hash = len, tmp;
    24   int rem;
    25 
    26   if (len <= 0 || data == NULL) return 0;
    27 
    28   rem = len & 3;
    29   len >>= 2;
    30 
    31   /* Main loop */
    32   for (;len > 0; len--) {
    33       hash  += get16bits (data);
    34       tmp    = (get16bits (data+2) << 11) ^ hash;
    35       hash   = (hash << 16) ^ tmp;
    36       data  += 2*sizeof (uint16_t);
    37       hash  += hash >> 11;
    38   }
    39 
    40   /* Handle end cases */
    41   switch (rem) {
    42     case 3: hash += get16bits (data);
    43       hash ^= hash << 16;
    44       hash ^= data[sizeof (uint16_t)] << 18;
    45       hash += hash >> 11;
    46       break;
    47     case 2: hash += get16bits (data);
    48       hash ^= hash << 11;
    49       hash += hash >> 17;
    50       break;
    51     case 1: hash += *data;
    52       hash ^= hash << 10;
    53       hash += hash >> 1;
    54   }
    55 
    56   /* Force "avalanching" of final 127 bits */
    57   hash ^= hash << 3;
    58   hash += hash >> 5;
    59   hash ^= hash << 4;
    60   hash += hash >> 17;
    61   hash ^= hash << 25;
    62   hash += hash >> 6;
    63 
    64   return hash;
    65 
    66   #undef get16bits
    67 }
    68 
    69 SC_FUNC HashTable *NewHashTable()
    70 {
    71     HashTable *ht = (HashTable*)malloc(sizeof(HashTable));
    72     if (!ht)
    73         return ht;
    74     ht->buckets = (HashEntry **)calloc(32, sizeof(HashEntry *));
    75     if (!ht->buckets) {
    76         free(ht);
    77         return NULL;
    78     }
    79     ht->nbuckets = 32;
    80     ht->nused = 0;
    81     ht->bucketmask = 32 - 1;
    82     return ht;
    83 }
    84 
    85 SC_FUNC void
    86 DestroyHashTable(HashTable *ht)
    87 {
    88     uint32_t i;
    89     if (!ht)
    90         return;
    91     for (i = 0; i < ht->nbuckets; i++) {
    92         HashEntry *he = ht->buckets[i];
    93         while (he != NULL) {
    94             HashEntry *next = he->next;
    95             free(he);
    96             he = next;
    97         }
    98     }
    99     free(ht->buckets);
   100     free(ht);
   101 }
   102 
   103 SC_FUNC symbol *
   104 FindTaggedInHashTable(HashTable *ht, const char *name, int fnumber,
   105                       int *cmptag)
   106 {
   107     int count=0;
   108     symbol *firstmatch=NULL;
   109     uint32_t hash = NameHash(name);
   110     uint32_t bucket = hash & ht->bucketmask;
   111     HashEntry *he = ht->buckets[bucket];
   112 
   113     assert(cmptag!=NULL);
   114 
   115     while (he != NULL) {
   116         symbol *sym = he->sym;
   117         if ((sym->parent==NULL || sym->ident==iCONSTEXPR) &&
   118             (sym->fnumber<0 || sym->fnumber==fnumber) &&
   119             (strcmp(sym->name, name) == 0))
   120         {
   121             /* return closest match or first match; count number of matches */
   122             if (firstmatch==NULL)
   123                 firstmatch=sym;
   124             if (*cmptag==0)
   125                 count++;
   126             if (*cmptag==sym->tag) {
   127                 *cmptag=1;    /* good match found, set number of matches to 1 */
   128                 return sym;
   129             }
   130         }
   131         he = he->next;
   132     }
   133 
   134     if (firstmatch!=NULL)
   135         *cmptag=count;
   136     return firstmatch;
   137 }
   138 
   139 SC_FUNC symbol *
   140 FindInHashTable(HashTable *ht, const char *name, int fnumber)
   141 {
   142     uint32_t hash = NameHash(name);
   143     uint32_t bucket = hash & ht->bucketmask;
   144     HashEntry *he = ht->buckets[bucket];
   145 
   146     while (he != NULL) {
   147         symbol *sym = he->sym;
   148         if ((sym->parent==NULL || sym->ident==iCONSTEXPR) &&
   149             (sym->fnumber<0 || sym->fnumber==fnumber) &&
   150             (strcmp(sym->name, name) == 0))
   151         {
   152             return sym;
   153         }
   154         he = he->next;
   155     }
   156 
   157     return NULL;
   158 }
   159 
   160 static void
   161 ResizeHashTable(HashTable *ht)
   162 {
   163     uint32_t i;
   164     uint32_t xnbuckets = ht->nbuckets * 2;
   165     uint32_t xbucketmask = xnbuckets - 1;
   166     HashEntry **xbuckets = (HashEntry **)calloc(xnbuckets, sizeof(HashEntry*));
   167     if (!xbuckets)
   168         return;
   169 
   170     for (i = 0; i < ht->nbuckets; i++) {
   171         HashEntry *he = ht->buckets[i];
   172         while (he != NULL) {
   173             HashEntry *next = he->next;
   174             uint32_t bucket = he->sym->hash & xbucketmask;
   175             he->next = xbuckets[bucket];
   176             xbuckets[bucket] = he;
   177             he = next;
   178         }
   179     }
   180     free(ht->buckets);
   181     ht->buckets = xbuckets;
   182     ht->nbuckets = xnbuckets;
   183     ht->bucketmask = xbucketmask;
   184 }
   185 
   186 SC_FUNC void
   187 AddToHashTable(HashTable *ht, symbol *sym)
   188 {
   189     uint32_t bucket = sym->hash & ht->bucketmask;
   190     HashEntry **hep, *he;
   191 
   192     hep = &ht->buckets[bucket];
   193     while (*hep) {
   194         assert((*hep)->sym != sym);
   195         hep = &(*hep)->next;
   196     }
   197 
   198     he = (HashEntry *)malloc(sizeof(HashEntry));
   199     if (!he)
   200       error(123);
   201     he->sym = sym;
   202     he->next = NULL;
   203     *hep = he;
   204     ht->nused++;
   205 
   206     if (ht->nused > ht->nbuckets && ht->nbuckets <= INT_MAX / 2)
   207         ResizeHashTable(ht);
   208 }
   209 
   210 SC_FUNC void
   211 RemoveFromHashTable(HashTable *ht, symbol *sym)
   212 {
   213     uint32_t bucket = sym->hash & ht->bucketmask;
   214     HashEntry **hep = &ht->buckets[bucket];
   215     HashEntry *he = *hep;
   216 
   217     while (he != NULL) {
   218         if (he->sym == sym) {
   219             *hep = he->next;
   220             free(he);
   221             ht->nused--;
   222             return;
   223         }
   224         hep = &he->next;
   225         he = *hep;
   226     }
   227 
   228     assert(0);
   229 }
   230