void *ixemulbase;
int *ixemul_errno;
char *_ctype_;
void **__sF;

typedef unsigned long ulong;

extern void  __link_data_hashes();
extern ulong __link_data_offsets[];
extern void  __link_text_hashes();
extern void  __link_text_offsets();

static int relocate(char *base, ulong *f, ulong *hashes, ulong *offsets)
{
  int cnt = (f ? *f++ : 0), ind = 0, i;

  while (cnt--)
  {
    ulong hash = *f++;
    short relocs = *((short *)f)++;

    while (offsets[ind] != -1 && hashes[ind] != hash)
      ind++;

    if (offsets[ind] == -1)
      return 0;
    i = relocs;
    if (*((long *)(base + f[0])) == offsets[ind] + f[relocs])
      return 1;
    while (i--)
    {
      *((long *)(base + f[0])) = offsets[ind] + f[relocs];
      f++;
    }
    f += relocs;
    ind++;
  }
  return 1;
}

int __LibSetVarsInstance(char *stext, ulong *tf, ulong *td,
			 char *sdata, ulong *df, ulong *dd,
			 ulong *libdata, int argc, void *ixbase,
			 int *errnoptr, char *ctype, void **sf)
{
  int cnt;
  int ind = 0;
  ulong *hashes, *offsets;

  switch (argc)
  {
    default:
    case 4:
      if (sf) __sF = sf;
    case 3:
      if (ctype) _ctype_ = ctype;
    case 2:
      if (errnoptr) ixemul_errno = errnoptr;
    case 1:
      if (ixbase) ixemulbase = ixbase;
    case 0:
  }

  /* ixemulbase *must* be set */
  if (ixemulbase == NULL)
    return 0;

  if (!relocate(stext, tf, (ulong *)__link_text_hashes,
                           (ulong *)__link_text_offsets))
    return 0;

  if (!relocate(sdata, df, (ulong *)__link_text_hashes,
                           (ulong *)__link_text_offsets))
    return 0;

  if (!relocate(stext, td, (ulong *)__link_data_hashes,
                           (ulong *)__link_data_offsets))
    return 0;

  if (!relocate(sdata, dd, (ulong *)__link_data_hashes,
                           (ulong *)__link_data_offsets))
    return 0;

  hashes = (ulong *)__link_data_hashes;
  offsets = __link_data_offsets;
  cnt = (libdata ? *libdata++ : 0);
  ind = 0;
  while (cnt--)
  {
    ulong hash = *libdata;
    
    while (offsets[ind] != -1 && hashes[ind] != hash)
      ind++;
    if (offsets[ind] == -1)
      return 0;
    *libdata++ = offsets[ind++];
  }
  return 1;
}
