#include <stddef.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>

#include "FTreg.h"
#include "memory.h"

union un1 {
  int i;
  char ch[sizeof(int)];
};

static char *parser(s)
char *s;
{
  union un1 u;
  char *temp;
  char *p;
  int accumulator = 0;

  assert(s != (char *)NULL);
  for (p=s; *p != '\0'; ++p) {
    switch (*p) {
    case '0': accumulator = accumulator*10 + 0; break;
    case '1': accumulator = accumulator*10 + 1; break;
    case '2': accumulator = accumulator*10 + 2; break;
    case '3': accumulator = accumulator*10 + 3; break;
    case '4': accumulator = accumulator*10 + 4; break;
    case '5': accumulator = accumulator*10 + 5; break;
    case '6': accumulator = accumulator*10 + 6; break;
    case '7': accumulator = accumulator*10 + 7; break;
    case '8': accumulator = accumulator*10 + 8; break;
    case '9': accumulator = accumulator*10 + 9; break;
    case ' ': break;
    case '-': accumulator = -accumulator; break;
    default: return (char *)NULL; /* illegal character */
    }
  }
  u.i = accumulator;
  temp = (char *)Memory_allocate(sizeof u);
  (NORET)memcpy(temp, &(u.ch[0]), sizeof(u.ch));
  return temp;
}

static char *un_parser(s)
char *s;
{
  char *temp1;
  union un1 u;

  (NORET)memcpy(&(u.ch[0]), s, sizeof(u.ch));
  temp1 = (char *)Memory_allocate(15); /* ??? */
  sprintf(temp1, "%d", u.i);
  return temp1;
}

static int int_equal(value, pattern)
char *value, *pattern;
{
  union un1 u1, u2;

  (NORET)memcpy(&(u1.ch[0]), value, sizeof(u1.ch));
  (NORET)memcpy(&(u2.ch[0]), pattern, sizeof(u2.ch));
  return u1.i == u2.i;
}

static int int_notequal(value, pattern)
char *value, *pattern;
{
  union un1 u1, u2;

  (NORET)memcpy(&(u1.ch[0]), value, sizeof(u1.ch));
  (NORET)memcpy(&(u2.ch[0]), pattern, sizeof(u2.ch));
  return u1.i != u2.i;
}

static int int_less(value, pattern)
char *value, *pattern;
{
  union un1 u1, u2;

  (NORET)memcpy(&(u1.ch[0]), value, sizeof(u1.ch));
  (NORET)memcpy(&(u2.ch[0]), pattern, sizeof(u2.ch));
  return u2.i > u1.i;
}

static int int_less_eq(value, pattern)
char *value, *pattern;
{
  union un1 u1, u2;

  (NORET)memcpy(&(u1.ch[0]), value, sizeof(u1.ch));
  (NORET)memcpy(&(u2.ch[0]), pattern, sizeof(u2.ch));
  return u2.i >= u1.i;
}

static int int_greater(value, pattern)
char *value, *pattern;
{
  union un1 u1, u2;

  (NORET)memcpy(&(u1.ch[0]), value, sizeof(u1.ch));
  (NORET)memcpy(&(u2.ch[0]), pattern, sizeof(u2.ch));
  return u2.i < u1.i;
}

static int int_greater_eq(value, pattern)
char *value, *pattern;
{
  union un1 u1, u2;

  (NORET)memcpy(&(u1.ch[0]), value, sizeof(u1.ch));
  (NORET)memcpy(&(u2.ch[0]), pattern, sizeof(u2.ch));
  return u2.i <= u1.i;
}

static NORET int_free(data)
char *data;
{
  Memory_free(data);
}

/*  The name of the first item in each group below will appear in the */
 /*  ruleeditor menu.  All the other items are equivalent ways to name that */
 /*  field operator. */
static FieldOpArg fieldOpList[]={
  { "=",int_equal },
  { "equal",int_equal },
  { "equals",int_equal },

  { "<",int_less },

  { "<=",int_less_eq },
  { "=<",int_less_eq },

  { ">",int_greater },

  { ">=",int_greater_eq },
  { "=>",int_greater_eq },

  { "!=", int_notequal },
  { "~=", int_notequal },
  { "not equal", int_notequal },
  { "not equals", int_notequal },
  { (char *)NULL, NULL}
};

static struct AlFieldTypeRegistry_str  int_FTrec={
  "Integer",
  parser,
  un_parser,
  fieldOpList,
  NULL,
  NULL,
  int_free,
};

struct AlFieldTypeRegistry_str  *int_FTrecptr = &int_FTrec;

