Source file: /~heha/hs/gputils64-210929.zip/libgputils/gpsymbol.cpp

/* GP Symbol table support.
   Copyright 2014-2016	Molnár Károly
*/

#include "stdhdr.h"
#include "libgputils.h"


int hash128_t::compare(const hash128_t&b)const{
  if (hi < b.hi) return -1;
  if (hi > b.hi) return 1;
  if (lo < b.lo) return -1;
  if (lo > b.lo) return 1;
  return 0;
}

/*------------------------------------------------------------------------------------------------*/

static int _cdecl _hash_sort_cmp(const void *P0, const void *P1) {
  const gp_hash_t &h0 = *(const gp_hash_t *)P0;
  const gp_hash_t &h1 = *(const gp_hash_t *)P1;
  int v = h0.hash.compare(h1.hash);
  if (v) return v;

  const char* s0 = h0.symbol ? h0.symbol->name : 0;
  const char* s1 = h1.symbol ? h1.symbol->name : 0;

  if (!s0 && !s1) return 0;

  if (s0 && s1) return strcmp(s0, s1);

  if (s0) return 1;

  return -1;
}

/*------------------------------------------------------------------------------------------------*/

static int _cdecl _hash_find_cmp(const void *P0, const void *P1) {
  const gp_hash_t &h0 = *(const gp_hash_t *)P0;
  const gp_hash_t &h1 = *(const gp_hash_t *)P1;
  return h0.hash.compare(h1.hash);
}

/*------------------------------------------------------------------------------------------------*/

FUNC(gp_hash_t*) gp_symbol_make_hash_table(gp_object_t *Object) {
  if (!Object) return 0;
  unsigned n_symbols = 0;
  FOR(gp_symbol_list_t,symbol,Object->symbol_list) {
    FlagClr(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);

    if ((symbol->pclass != C_FILE)    && (symbol->pclass != C_EOF) &&
        (symbol->pclass != C_SECTION) && (symbol->section_name)) {
      ++n_symbols;
      FlagSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
    }
  }

  gp_hash_t*table = new gp_hash_t[n_symbols];
  memset(table,0,sizeof*table*n_symbols);

  Object->symbol_hashtable      = table;
  Object->symbol_hashtable_size = n_symbols;

  gp_hash_t*tp = table;
  FOR(gp_symbol_list_t,it,Object->symbol_list) {
    if (FlagIsSet(it->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE)) {
      hash128_t&h = tp->hash;
      h.reset();
      h.hash(it->section_name);
      h.hash((char*)&it->value, sizeof it->value);
      tp->symbol = &*it;
      ++tp;
    }
  }

  qsort(table, n_symbols, sizeof(gp_hash_t), _hash_sort_cmp);
  return table;
}

/*------------------------------------------------------------------------------------------------*/

/* Search a symbol on the basis of value and owner section name. */

const gp_symbol_t* gp_symbol_find(const gp_object_t *Object, const char *Section_name, gp_symvalue_t Symbol_value) {
  gp_hash_t  gp_hash;
  gp_hash_t *ret;

  if (!Object || !Section_name) return 0;

  if (!Object->symbol_hashtable || !Object->symbol_hashtable_size) return 0;

  gp_hash.hash.hash(Section_name,false);
  gp_hash.hash.hash((char*)&Symbol_value,sizeof(Symbol_value));

  ret = (gp_hash_t *)bsearch(&gp_hash, Object->symbol_hashtable, Object->symbol_hashtable_size,
                             sizeof(gp_hash_t), _hash_find_cmp);

  return ret ? ret->symbol : NULL;
}

/*------------------------------------------------------------------------------------------------*/

static int _cdecl _value_cmp(const void *P0, const void *P1) {
  const gp_symbol_t *s0 = *(const gp_symbol_t **)P0;
  const gp_symbol_t *s1 = *(const gp_symbol_t **)P1;
  gp_symvalue_t      v0 = s0->value;
  gp_symvalue_t      v1 = s1->value;

  if (v0 < v1) {
    return -1;
  }

  if (v0 > v1) {
    return 1;
  }

  return 0;
}

/*------------------------------------------------------------------------------------------------*/

/* Collects those labels that belong to the same "Section". */

gp_symbol_t** gp_symbol_make_label_array(gp_section_t *Section, unsigned Org_to_byte_shift,
                           unsigned *Num_labels) {
  gp_symbol_t   **array;
  gp_symvalue_t   start_addr;
  gp_symvalue_t   end_addr;
  unsigned    i;
  unsigned    n_labels;

  if (!Section || !Num_labels) return 0;

  start_addr = gp_insn_from_byte(Org_to_byte_shift, Section->address);
  end_addr   = start_addr + gp_insn_from_byte(Org_to_byte_shift, Section->size);

  n_labels = 0;
  gp_symbol_list_t::iterator symbol = Section->symbol;
  while (&*symbol) {
    FlagClr(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);

    if (((symbol->pclass == C_EXT) || (symbol->pclass == C_LABEL)) &&
        (symbol->section) && FlagsIsNotAllClr(symbol->section->flags, STYP_ROM_AREA)) {
      if ((symbol->value >= start_addr) && (symbol->value < end_addr)) {
        ++n_labels;
        FlagSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
      }
    }
    symbol++;
  }

  if (n_labels == 0) {
    return NULL;
  }

  array = new gp_symbol_t*[n_labels];

  i      = 0;
  symbol = Section->symbol;
  while (&*symbol) {
    if (FlagIsSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE)) {
      array[i] = &*symbol;
      ++i;
    }
    symbol++;
  }

  qsort(array, n_labels, sizeof(gp_symbol_t *), _value_cmp);

  *Num_labels = n_labels;
  return array;
}

/*------------------------------------------------------------------------------------------------*/

/* Collects those registers that belong to the same "Section". */

gp_symbol_t** gp_symbol_make_register_array(gp_object_t *Object, unsigned &Num_registers) {
  if (!Object || !Num_registers) return 0;
  unsigned n_registers = 0;
  FOR(gp_symbol_list_t,symbol,Object->symbol_list) {
    FlagClr(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);

    if ((symbol->pclass != C_FILE) && (symbol->pclass != C_EOF) && (symbol->pclass != C_SECTION) &&
        (symbol->section) && FlagsIsNotAllClr(symbol->section->flags, STYP_RAM_AREA)) {
      ++n_registers;
      FlagSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
    }
  }
  if (!n_registers) return 0;

  gp_symbol_t**array = new gp_symbol_t*[n_registers];

  unsigned i = 0;
  FOR(gp_symbol_list_t,it,Object->symbol_list)
   if (FlagIsSet(it->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE)) array[i++] = &*it;

  qsort(array, n_registers, sizeof(gp_symbol_t *), _value_cmp);

  Num_registers = n_registers;
  return array;
}

/*------------------------------------------------------------------------------------------------*/

/* Search a symbol on the basis of value. */

gp_symbol_t* gp_symbol_find_by_value(gp_symbol_t **Array, unsigned Num_symbols, gp_symvalue_t Value) {
  gp_symbol_t   symbol;
  gp_symbol_t  *sptr;
  gp_symbol_t **ret;

  if ((Array == NULL) || (Num_symbols == 0)) {
    return NULL;
  }

  symbol.value = Value;
  sptr         = &symbol;
  ret = (gp_symbol_t **)bsearch(&sptr, Array, Num_symbols, sizeof(gp_symbol_t *), _value_cmp);
  return ((ret) ? *ret : NULL);
}

/*------------------------------------------------------------------------------------------------*/

/* Delete a symbol on the basis of value. */

bool gp_symbol_delete_by_value(gp_symbol_t **Array, unsigned *Num_symbols, gp_symvalue_t Value) {
  unsigned   n_symbols;
  gp_symbol_t    symbol;
  gp_symbol_t   *sptr;
  gp_symbol_t  **ret;
  unsigned   dst;
  unsigned   src;
  unsigned   num;

  if ((Array == NULL) || (Num_symbols == NULL) || ((n_symbols = *Num_symbols) == 0)) {
    return false;
  }

  symbol.value = Value;
  sptr         = &symbol;
  ret = (gp_symbol_t **)bsearch(&sptr, Array, n_symbols, sizeof(gp_symbol_t *), _value_cmp);

  if (ret) {
    dst = ret - Array;
    src = dst + 1;
    num = n_symbols - src;

    if (num != 0) {
      memmove(&Array[dst], &Array[src], num * sizeof(gp_symbol_t *));
    }

    *Num_symbols = n_symbols - 1;
    return true;
  }

  return false;
}
Detected encoding: UTF-80