/*

    File:    init.c
    Authors: Richard Hooker, Graham Toal
    Purpose: Loading of dictionary for spelling checker.
    Functions exported:  dawg_init, pack_init
    Internal functions:  spell_init

Description:

The address of a dictionary (either a PACKed dict or a DAWG) is set up by
this procedure.  This gives us the option of connecting the dict in read-only
(or copy-on-write) virtual memory.  On non-VM machines, we simply allocate a
large buffer into which the relevant part of the dictionary is loaded.

The magic number is used to check the dict type, *and* the machine byte-sex.
If the sex is reversed, even a VM system has to load the data into writable
memory (so that it can reverse it).

*/

#include "splib.h"

/*######################### INTERNAL FUNCTIONS #########################*/


static long
#ifndef __STDC__
sex_change(number)
long number;
#else
sex_change(long number)
#endif /* __STDC__ */
{                /* Most inefficient and cumbersome (but safe) version) */
  long b0, b1, b2, b3;
  b0 = number&255L;   number >>= 8L;
  b1 = number&255L;   number >>= 8L;
  b2 = number&255L;   number >>= 8L;
  b3 = number&255L;
  number = b0;        number <<= 8L;
  number = number|b1; number <<= 8L;
  number = number|b2; number <<= 8L;
  number = number|b3;
  return(number);
}


/*####################### EXPORTED FUNCTIONS #########################*/

int
#ifndef __STDC__
dawg_init(filename, dictp, nedgesp)
char *filename;
NODE **dictp;
INDEX *nedgesp;
#else
dawg_init(char *filename, NODE **dictp, INDEX *nedgesp)
#endif /* __STDC__ */
{
#define dict (*dictp)
#define nedges (*nedgesp)
FILE *fp; INDEX count;
long dawg_magic;
int reversing = FALSE;

  /*  init_dict("") gets default */
  if (*filename == '\0') filename = DEFAULT_DAWG;

  /* Open the file and find out the size of the dict -- which
     is stored in the first word.  Later I'll change the dict format
     to have a header, and the header will have to be skipped by
     this module. */

  if ((fp = fopen(filename, "rb")) == NULL) {
    fprintf (stderr, "Can\'t open file \"%s\"\n", filename);
    return(FALSE);
  }
  dawg_magic = word_get(fp);
  if (dawg_magic == REVERSE_DAWG_MAGIC) {
    fprintf(stderr, "*** Warning: You are using a byte-sex reversed dictionary (%s)\n",
      filename);
    fprintf(stderr, "             It will be more efficient if you can reverse it.\n");
    reversing = TRUE;
    dawg_magic = sex_change(dawg_magic);
  }
  if (dawg_magic != DAWG_MAGIC) {
    fprintf(stderr, "*** Error: file %s is not in dawg format\n", filename);
    return(FALSE);
  }
  if (reversing) {
    nedges = sex_change(word_get(fp));
  } else {
    nedges = word_get(fp);
  }
#ifdef DEBUG
fprintf(stderr, "dawg contains %8lx edges\n", nedges);
#endif
  /* Allocate precisely enough memory for all edges + 0 at root node. */
  if ((dict = MALLOC((nedges+1), sizeof(NODE *))) == 0) {
    fprintf (stderr, "Can\'t allocate space (%ld bytes) for dictionary\n",
                     (long)(nedges+1)*sizeof(NODE *));
    return(FALSE);
  }

  dict[0] = 0; /* Root node set to 0; terminal nodes point to 0. */

  /* very soon to output the 0 to the file, so memory-mapped files work! */

  /* Load in the dictionary.  Routine 'getwords' should be efficient */
  count = words_get(dict, (long)(sizeof(NODE)*nedges), fp);
  if (reversing) {
    INDEX i;
    for (i = 0; i < nedges; i++) {
      dict[i] = sex_change(dict[i]);
    }
  }
  if (count != sizeof(NODE)*nedges) {
    fprintf(stderr,
      "Failed to read dictionary %s - wanted %ld bytes, got %ld\n",
      filename, sizeof(NODE)*nedges, count);
    return(FALSE);
  }
  fclose(fp);

  return(TRUE);
#undef nedges
#undef dict
}
