/* routine to read dictionary */
#include <stdio.h>	   
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>

#include "parse.h"

// method: read_dict
//
// arguments:
//  char *dir: (input) directory which dict_file exists
//  char *dict_file: (input) filename of dict_file
//  Gram *gram: (input\output) pointer to grammar file to use
//  char **sym_buf_start: (input\output) location of symbol buffer to use
//                        to hold these syms. This is a larger buffer with
//                        all the strings just placed back-to-back.
//  char *sym_buf_end: (input) end of the buffer. for buffer checks
//
// return: number of words in sym_buf. exit(-1) on error.
//
// uses no global variables
// this function reads in the dictionary file of all words in the grammar.
// this is so that they can be looked up easily because the net file uses
// nothing but number indexes.
//
int read_dict(char *dir, char *dict_file, Gram *gram, char **sym_buf_start,
	      char *sym_buf_end) {
  FILE	*fp;
  int		idx;
  int         num_words;
  char	filename[LABEL_LEN];
  char	*sym_ptr;
  
  // Error checking
  // dir\dict_file not checked because they will fail below without
  // crashing the program
  //
  if (gram == NULL || sym_buf_start == NULL || *sym_buf_start == NULL ||
      sym_buf_end == NULL) {
    printf("read_dict() had null pointers passed in, exiting\n");
    exit(-1);
  }
  
  // Attempt to open the dict_file
  sprintf(filename, "%s/%s", dir, dict_file);
  
  if( !(fp = fopen(filename, "r")) ) {
    printf("read_dict: can't open %s\n", filename);
    return(0);
  }
  
  sym_ptr = *sym_buf_start;
  
  // malloc space for word pointers
  if( !(gram->wrds = (char **)calloc(MAX_WRDS, sizeof(char *)))) {
    printf("can't allocate space for script buffer\n");
    exit(-1);
  }
  
  // for each of the entries in the dict_file to the respective place in the
  // array has requested by the 'index' in the dict_file
  //
  for(num_words = 0; fscanf(fp, "%s %d", sym_ptr, &idx) == 2; num_words++) {
    if ((idx < 0) || (idx > MAX_WRDS)) {
      printf("word number for %s out of range\n", sym_ptr);
      exit(-1);
    }
    
    gram->wrds[idx] = sym_ptr;
    sym_ptr += (int)strlen(sym_ptr) + 1;
    
    if (sym_ptr >= sym_buf_end) {
      fprintf(stderr, "ERROR: overflow SymBufSize %d\n", SymBufSize);
      exit(-1);
    }
  }
  
  fclose(fp);
  
  *sym_buf_start = sym_ptr;
  gram->num_words = num_words;
  
  return(num_words);
}



// method: find_word
//
// arguments:
//  char *s: (input) directory which dict_file exists
//  Gram *gram: (input\output) pointer to grammar file to use
//
// return: index of word to find. -1 on error
//
// uses no global variables
// looks for the index of this word in the grammar file passed in.
//
int find_word(char *s, Gram *gram) {

  unsigned short key;
  char *c;
  int idx;
  
  // Note, the above file is the file that reads in this file. It does
  // not have any hashing in it. That means that the code that the dict file
  // is created from must do this hashing. This is done in compile_grammar.c
  // and is the same algo should it should be fine.
  //
  // use first two chars as hash key
  //
  c = (char *) &key;
  *c = *s;
  c++;
  *c = *(s+1);
  
  idx = key;
  for( ; idx < MAX_WRDS; idx++) {
    // since start with hash key, if we reach an unallocated spot, we have
    // run out of words that begin w/ those 2 first letters
    //
    if( !gram->wrds[idx] ) return(-1);
    if( !strcmp(gram->wrds[idx], s) ) return(idx);
  }
  return(-1);
}

