/**********************************************************************
 * Program to generate keyword database
 *
 * $Author: lwvanels $
 * $Source: /mit/olhdev/src/util/RCS/mk_keywords.c,v $
 * $Header: /mit/olhdev/src/util/RCS/mk_keywords.c,v 1.2 92/08/11 13:31:06 lwvanels Exp Locker: vanharen $
 *
 * Copyright (c) 1990, Massachusetts Institute of Technology
 **********************************************************************/

#ifndef lint
static char mk_keywords_c[] = "$Header: /mit/olhdev/src/util/RCS/mk_keywords.c,v 1.2 92/08/11 13:31:06 lwvanels Exp Locker: vanharen $";
#endif lint

#include <errno.h>
#include <com_err.h>
extern int strcasecmp(); 	/* XXX should be in <strings.h> */
#include <strings.h>
#include "memory.h"
#include "menu.h"
#define MENU_LABEL_FORMAT "Topics matching keyword \"%s\""
#define DEFAULT_VERBOSE 1

compar(s1, s2)
     char **s1;
     char **s2;
{
  return(strcasecmp(*s1, *s2));
}

usage(s)
     char *s;
{
  fprintf(stderr, "Usage: %s [-q -s -n]\n", s);
  exit(1);
}

main(argc, argv)
     int argc;
     char *argv[];
{
  Menu *m, *main_menu, *mng;
  MenuEntry *e, *e1;
  long code;
  int i, j, k, n;
  int verbose = DEFAULT_VERBOSE;
  int no_save = 0;
  char c;
  char *ng, *node;
  char *keywords[64];		/* XXX hard limit to keywords per entry */
  char *ptr, buf[256], label[256];
  char *old_keyword = "", *basename, *s;
  char **array;
  int asize = 0;
  char *program = "mk_keywords";

  if (argc == 2) {
    if (argv[1][0] == '-') {
      switch(argv[1][1]) {
      case 'v':
	verbose = 1;
	break;
      case 'q':
      case 's':
	verbose = 0;
	break;
      case 'n':
	no_save = 1;
	break;
      default:
	usage(argv[0]);
      }
    } else usage(argv[0]);
  }
  if (argc > 2) usage(argv[0]);

  config_loc = "/mit/logos/lib/config.menu";
  config_locker = "logos";
    
  init_hash_table();
  
  code = menu_init(NULL);
  if (code) {
    com_err(argv[0], code, "while initializing");
    exit(1);
  }
  e = find_group("main");
  code = menu_load(e, &main_menu);
  if (code) {
    com_err(program, code, "loading main menu");
    exit(1);
  }

  /* Loop i through node groups */
  for (i=1; i < size_menu(main_menu); i++) {
    c = *(field_value(nth_entry(main_menu, i), DO_KEYWORDS));
    if (c != 'y' && c != 'Y') continue;
    ng = field_value(nth_entry(main_menu, i), NODE_ID);
    if (verbose) printf("Loading keywords from \"%s\" node group...\n", ng);
    code = menu_load(nth_entry(main_menu, i), &m);
    if (code) {
      com_err(argv[0], code, "while loading \"%s\" (ignored)", ng);
      continue;
    }

    /* Loop j through entries in each node group */
    for (j=1; j < m->size; j++) {
      ptr = field_value(nth_entry(m, j), KEYWORDS);
      if (*ptr == '\0') continue;
      node = field_value(nth_entry(m, j), NODE_ID);
      strcpy(buf, ptr);
      n = break_colons(buf, keywords);

      /* Loop k through keywords in each entry */
      for (k=0; k<n; k++) {
	if (asize) {
	  array = ResizeArray(char *, array, ++asize);
	} else {
	  array = NewArray(char *, ++asize);
	}
	if (!array) {
	  perror(argv[0]);
	  exit(1);
	}
	array[asize-1] = NewArray(char, strlen(keywords[k])+strlen(ng)+
				  strlen(node)+3);
	if (!array[asize-1]) {
	  perror(argv[0]);
	  exit(1);
	}
	strcpy(array[asize-1], keywords[k]);
	strcat(array[asize-1], ":");
	strcat(array[asize-1], ng);
	strcat(array[asize-1], ":");
	strcat(array[asize-1], node);
      }
    }
  }
  qsort(array, asize, sizeof(char *), compar);

  /* Create node group with header */
  code = newmenu(&mng);
  resizemenu(mng, 1);
  if (code) goto ABORT;
  code = field_set(nth_entry(mng, 0), TYPE, "KEYWORD NODE GROUP");
  if (code) goto ABORT;
  code = field_set(nth_entry(mng, 0), FILE_FORMAT, "MENU");
  if (code) goto ABORT;
  code = field_set(nth_entry(mng, 0), NODE_LABEL, "Keyword list");
  if (code) goto ABORT;
  code = field_set(nth_entry(mng, 0), IN_KEYWORDS, "y");
  if (code) goto ABORT;

  e = find_group(KEYWORDS);
  if (!e) {
    fprintf(stderr, "%s: no keyword node group\n", argv[0]);
    exit(1);
  }
  mng->file = NewString(field_value(e, FILE_LOCATION));
  if (!mng->file) {
    code = (long) errno;
    goto ABORT;
  }
  strcpy(mng->file, field_value(e, FILE_LOCATION));
  basename = rindex(mng->file, '/');
  if (!basename++) basename = mng->file;
  
  m = NULL;

  for (i=0; i < asize; i++) {
    ptr = index(array[i], ':');
    *(ptr++) = '\0';
    if (strcasecmp(array[i], old_keyword)) {
      /* deal with new keyword */
      strcpy(buf, array[i]);
      for(s=buf; *s != '\0'; s++)
	if (*s == ' ') *s = '_';	/* convert spaces to underscores */
      if (m) {
	/* save old menu file */
	if (!no_save) {
	  code = menu_file_save(m, m->file);
	  if (code) {
	    com_err(argv[0], code, "while saving %s", m->file);
	    exit(1);
	  }
	}
	freemenu(m);
	m = NULL;
      }
      if (i+1 == asize ||
	  !(strncasecmp(array[i], array[i+1], strlen(array[i])) == 0 &&
	    array[i+1][strlen(array[i])] == ':')) {
	/* Unique keyword */
	if (verbose) printf("Unique\t\"%s\"\n", array[i]);
	resizemenu(mng, mng->size + 1);
	e = nth_entry(mng, mng->size - 1);
	field_set(e, NODE_ID, buf);
	field_set(e, NODE_LABEL, array[i]);
	field_set(e, POINTER, ptr);
	old_keyword = array[i];
	continue;		/* XXX Why doesn't this work? */
      }

      /* create new menu file w header */
      if (verbose) printf("Menu\t\"%s\"\n", array[i]);
      code = newmenu(&m);
      if (code) goto ABORT;
      m->file = NewArray(char, basename - mng->file + strlen(buf) + 1);
      if (!m->file) {
	code = (long) errno;
	goto ABORT;
      }
      strncpy(m->file, mng->file, basename - mng->file);
      m->file[basename - mng->file] = '\0';
      strcat(m->file, buf);
      resizemenu(m, 1);

      /* put entry to node group and menu 0th entry */
      resizemenu(mng, mng->size + 1);
      e = nth_entry(mng, mng->size - 1);
      field_set(e, TYPE, "MENU");
      field_set(m->entry, TYPE, "MENU");
      field_set(e, FILE_FORMAT, "MENU");
      field_set(m->entry, FILE_FORMAT, "MENU");
      sprintf(label, MENU_LABEL_FORMAT, array[i]); 
      field_set(e, NODE_LABEL, array[i]);
      field_set(m->entry, NODE_LABEL, label);
      field_set(e, IN_KEYWORDS, "y");
      field_set(m->entry, IN_KEYWORDS, "y");
      field_set(e, FILE_LOCATION, m->file);
      field_set(e, NODE_ID, buf);
    }

    if (m) {
      resizemenu(m, m->size + 1);
      e = nth_entry(m, m->size - 1);
      code = pointerEntry(ptr, &e1);
      if (code) {
	com_err(argv[0], code, "while following pointer \"%s\"", ptr);
      } else {
	field_set(e, NODE_LABEL, field_value(e1, NODE_LABEL));
      }
      field_set(e, POINTER, ptr);
    }
    old_keyword = array[i];
  }

  if (!no_save) {
    code = menu_file_save(mng, mng->file);
    if (code) {
      com_err(argv[0], code, "while saving %s", mng->file);
      exit(1);
    }
  }
  exit(0);

 ABORT:
  com_err(argv[0], code, "");
  exit(1);
}
