/*
 * ACME - a crossassembler for producing 6502/65c02/65816 code.
 * Copyright (C) 1998 Marco Baye
 * Have a look at "acme.c" for further info
 */

/*
 * List item definitions
 */

#ifndef item_H
#define item_H

/* Flags for newly created labels */
#define LABELFLAG_DEFAULT       0

/* The following definition is a part of all variants of the general structure
 * "ListItem". The first element of that structure *has* to be the pointer to
 * the list's next item, because the lookup routine treats the
 * startpointer-array's elements as if they were "ListItem"s (though the array
 * just contains pointers).*/
#define STRUCTHEADER_B          \
  ListItem         *Next;       \
  int               Hash;       \
  union {                       \
    struct {                    \
      unsigned char b0;         \
      unsigned char b1;         \
      unsigned char b2;         \
      unsigned char b3;         \
    } Bytes;                    \
    void           *Body;       \
  } Data;                       \
  char              Type;

/* Official ANSI-C does not allow to predefine any union elements but the
 * first. Because of that, here the structure is defined once again (just with
 * a different ordering of union elements). :( */
#define STRUCTHEADER_P          \
  ListItem         *Next;       \
  int               Hash;       \
  union {                       \
    void           *Body;       \
    struct {                    \
      unsigned char b0;         \
      unsigned char b1;         \
      unsigned char b2;         \
      unsigned char b3;         \
    } Bytes;                    \
  } Data;                       \
  char              Type;

/* Definitions for accessing the structures' data bytes */
#define FLAGS   b0
#define VALUE   b0
#define GROUP   b1
#define LOW     b1
#define HIGH    b2
#define BANK    b3

/* The following structure is the one that is used throughout the whole
 * program: Its last element is the zero-terminated name string.*/
typedef struct ListItem ListItem;
struct ListItem {
  STRUCTHEADER_B
  char String[LSMAX + 1];
};

/* As I don't want to waste memory, each list item only gets as much of it as
 * is necessary. The following structure only reserves space for *one* string
 * character - the terminator; so "sizeof()" can deliver the space needed for
 * a list item without a name string.*/
typedef struct SizeStruct SizeStruct;
struct SizeStruct {
  STRUCTHEADER_B
  char String[1];
};

/* All predefined list items have exactly matching lengths. */
typedef struct KeyStruct2_B KeyStruct2_B;
struct KeyStruct2_B {
  STRUCTHEADER_B
  char String[3];
};

typedef struct KeyStruct3_B KeyStruct3_B;
struct KeyStruct3_B {
  STRUCTHEADER_B
  char String[4];
};

typedef struct KeyStruct4_B KeyStruct4_B;
struct KeyStruct4_B {
  STRUCTHEADER_B
  char String[5];
};

typedef struct KeyStruct5_B KeyStruct5_B;
struct KeyStruct5_B {
  STRUCTHEADER_B
  char String[6];
};


typedef struct KeyStruct2_P KeyStruct2_P;
struct KeyStruct2_P {
  STRUCTHEADER_P
  char String[3];
};

typedef struct KeyStruct3_P KeyStruct3_P;
struct KeyStruct3_P {
  STRUCTHEADER_P
  char String[4];
};

typedef struct KeyStruct4_P KeyStruct4_P;
struct KeyStruct4_P {
  STRUCTHEADER_P
  char String[5];
};

typedef struct KeyStruct5_P KeyStruct5_P;
struct KeyStruct5_P {
  STRUCTHEADER_P
  char String[6];
};

typedef struct KeyStruct6_P KeyStruct6_P;
struct KeyStruct6_P {
  STRUCTHEADER_P
  char String[7];
};

typedef struct KeyStruct7_P KeyStruct7_P;
struct KeyStruct7_P {
  STRUCTHEADER_P
  char String[8];
};

/*
 * Prototypes
 */
/* Array of pointers to start of item lists (because of 8-bit hash) */
static ListItem      *pPointerTable[256];
static unsigned char  FN_Struct_Hash(ListItem *, int);
static ListItem      *FN_Struct_Search(ListItem *, char, int, int);
static ListItem      *FN_Struct_GetZoned(Sixteen, int, int, int);
static ListItem      *FN_Struct_GetPreparedLabel(Sixteen, int, int);

#endif
