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

/* gpcfg.c - handler for pic configurations
   Copyright 2006	Michael Ballbach
   Copyright 2014-2016	Molnár Károly
 */

#include "gpcfg.h"

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

static int _cdecl _cmp(void const *P1, void const *P2) {
  gp_cfg_device_t const &d1 = *(gp_cfg_device_t const *)P1;
  gp_cfg_device_t const &d2 = *(gp_cfg_device_t const *)P2;
  return strcasecmp(d1.name, d2.name);
}

/*------------------------------------------------------------------------------------------------*/
/* Locate a PIC configuration device structure by name. */
const gp_cfg_device_t* gp_cfg_find_pic(const char *Pic) {
  gp_cfg_device_t fake_dev = { NULL, 0, NULL };
  fake_dev.name = Pic;
  return (const gp_cfg_device_t *)bsearch(&fake_dev, gp_cfg_devices, gp_cfg_device_count,
	sizeof(gp_cfg_device_t), _cmp);
}

/*------------------------------------------------------------------------------------------------*/
/* Locate a PIC by name, pass a list of names to use, try each in order. */

FUNC(const gp_cfg_device_t*) gp_cfg_find_pic_multi_name(const char *const *Pics, unsigned Count) {
  for (unsigned i = 0; i < Count; i++) {
    const gp_cfg_device_t *dev = gp_cfg_find_pic(Pics[i]);
    if (dev) return dev;
  }
  return NULL;
}

/*------------------------------------------------------------------------------------------------*/
/* Give the real boundaries of the config address section. */

FUNC(void) gp_cfg_real_config_boundaries(const gp_cfg_device_t *Device, int *Address_low, int *Address_high) {
  const gp_cfg_addr_t* addr = Device->addresses;
  *Address_low  = addr[0].address;
  *Address_high = addr[Device->address_count - 1].address;
}

/*------------------------------------------------------------------------------------------------*/
/* Find a configuration directive in a processor's config db. */

FUNC(const gp_cfg_directive_t*) gp_cfg_find_directive(const gp_cfg_device_t *Device, const char *Dname, unsigned *Out_config_addr, uint16_t *Out_def_value) {
  const gp_cfg_addr_t*addr = Device->addresses;

  for (unsigned i = Device->address_count; i; ++addr, --i) {
    const gp_cfg_directive_t *dir = addr->directives;
    for (unsigned j = addr->directive_count; j; ++dir, --j) {
      if (strcasecmp(Dname, dir->name) == 0) {
        if (Out_config_addr) *Out_config_addr = addr->address;
        if (Out_def_value) *Out_def_value = addr->def_value;
        return dir;
      }
    }
  }
  return NULL;
}

/*------------------------------------------------------------------------------------------------*/
/* Lists in brief all configuration in a processor's config db. */

FUNC(void) gp_cfg_brief_device(const gp_cfg_device_t *Device, const char *Head, int Addr_digits, int Word_digits, bool Pic18J) {
  unsigned              i;
  unsigned              j;
  unsigned              word_mask;
  unsigned              mask;
  unsigned              def_value;
  unsigned              xinst_mask;
  const gp_cfg_addr_t      *addr;
  const gp_cfg_directive_t *dir;

  word_mask = ((UINT_MAX << (Word_digits * 4)) & UINT_MAX) ^ UINT_MAX;

  for (i = Device->address_count, addr = Device->addresses; i; ++addr, --i) {
    mask = 0;
    xinst_mask = 0;
    for (j = addr->directive_count, dir = addr->directives; j; ++dir, --j) {
      mask |= dir->mask;

      if (strcasecmp(dir->name, "XINST") == 0) {
        xinst_mask = dir->mask;
      }
    }

    def_value = addr->def_value;

    if (!Pic18J || ((addr->address & 1) == 0)) {
      def_value &= mask;
    }

    printf("%s0x%0*X 0x%0*X 0x%0*X", Head, Addr_digits, addr->address, Word_digits, mask,
           Word_digits, def_value);

    if (xinst_mask > 0) {
      printf(" 0x%0*X", Word_digits, (~xinst_mask) & word_mask);
    }

    printf("\n");
  }
}

/*------------------------------------------------------------------------------------------------*/
/* Lists all configuration in a processor's config db. */

FUNC(void) gp_cfg_full_list_device(const gp_cfg_device_t *Device, const char *Head, int Addr_digits, int Word_digits) {
  unsigned               headlen;
  unsigned               i;
  unsigned               j;
  unsigned               k;
  unsigned               len;
  unsigned               maxlen;
  unsigned               mask;
  unsigned               def_value;
  const gp_cfg_addr_t       *addr;
  const gp_cfg_directive_t  *dir;
  const gp_cfg_option_t    **opt;
  const char                *txt;

  headlen = strlen(Head);

  /* Determine the maximum length of the option names. */
  maxlen = 0;
  for (i = Device->address_count, addr = Device->addresses; i; ++addr, --i) {
    for (j = addr->directive_count, dir = addr->directives; j; ++dir, --j) {
      for (k = dir->option_count, opt = dir->options; k; ++opt, --k) {
        len = strlen((*opt)->name);

        if (maxlen < len) {
          maxlen = len;
        }
      }
    }
  }

  for (i = Device->address_count, addr = Device->addresses; i; ++addr, --i) {
    for (mask = 0, j = addr->directive_count, dir = addr->directives; j; ++dir, --j) {
      mask |= dir->mask;
    }

    printf("%saddress = 0x%0*X, mask = 0x%0*X, default = 0x%0*X\n", Head, Addr_digits,
           addr->address, Word_digits, mask, Word_digits, addr->def_value);

    for (j = addr->directive_count, dir = addr->directives; j; ++dir, --j) {
      def_value = addr->def_value & dir->mask;
      printf("%*s%s\n", headlen, "Directive: ", dir->name);

      for (k = dir->option_count, opt = dir->options; k; ++opt, --k) {
        if (def_value == (*opt)->value) {
          txt = " (default)";
        }
        else {
          txt = "";
        }

        printf("%*s  %-*s = 0x%0*X%s\n", headlen, "Option: ", maxlen, (*opt)->name,
               Word_digits, (*opt)->value, txt);
      }
    }
  }
}

/*------------------------------------------------------------------------------------------------*/
/* Locate an option for a directive. Return it or NULL. */

FUNC(const gp_cfg_option_t*) gp_cfg_find_option(const gp_cfg_directive_t *Directive, const char *Option) {
  unsigned            i;
  const gp_cfg_option_t **opt;

  for (i = Directive->option_count, opt = Directive->options; i; ++opt, --i) {
    if (strcasecmp((*opt)->name, Option) == 0) {
      return *opt;
    }
  }

  return NULL;
}

/*------------------------------------------------------------------------------------------------*/
/* Find a configuration in a processor's config db. */

const gp_cfg_addr_t * gp_cfg_find_config(const gp_cfg_device_t *Device, unsigned Address) {
  unsigned         i;
  const gp_cfg_addr_t *addr;

  for (i = Device->address_count, addr = Device->addresses; i; ++addr, --i) {
    if (addr->address == Address) {
      return addr;
    }
  }

  return NULL;
}

/*------------------------------------------------------------------------------------------------*/
/* Return 0xffff or the default for the address and device passed. */

FUNC(uint16_t) gp_cfg_get_default(const gp_cfg_device_t *Device, unsigned Address)
{
  const gp_cfg_addr_t *addr;

  addr = gp_cfg_find_config(Device, Address);
  return ((addr) ? addr->def_value : 0xFFFF);
}

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

FUNC(unsigned) gp_cfg_decode_directive(const gp_cfg_device_t *Device, unsigned Address, unsigned Value,
	gp_cfg_addr_hit_t *Hit) {
  unsigned               i;
  unsigned               j;
  unsigned               count;
  const gp_cfg_addr_t       *addr;
  const gp_cfg_directive_t  *dir;
  const gp_cfg_option_t    **opt;
  unsigned               val;
  unsigned               max;
  unsigned               len;

  if ((addr = gp_cfg_find_config(Device, Address)) == NULL) {
    return 0;
  }

  Hit->def_value = addr->def_value;
  count = 0;
  max   = 0;
  for (i = addr->directive_count, dir = addr->directives; i; ++dir, --i) {
    val = Value & dir->mask;

    for (j = dir->option_count, opt = dir->options; j; ++opt, --j) {
      if (count >= GP_CFG_ADDR_HIT_MAX) {
        fprintf(stderr, "%s(): The size of gp_cfg_addr_hit_t too small!\n", "gp_cfg_decode_directive");
        goto exit_loop;
      }

      if (val == (*opt)->value) {
        Hit->pairs[count].directive = dir;
        Hit->pairs[count].option    = *opt;
        len = strlen(dir->name);

        if (max < len) {
          max = len;
        }

        ++count;
        break;
      }
    }
  }

exit_loop:

  Hit->pair_count    = count;
  Hit->max_dir_width = max;
  return count;
}
Detected encoding: UTF-80