/* 
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/
#ident "$Header: cat_build.c 1.2 90/05/02 $@(#)cat_build.c	1.2 89/12/06 "

#include <filehdr.h>
#include <stdio.h>
#include "nl_types.h"
#include "nl_type2.h"
#include <malloc.h>

extern int list;
extern char *gettxt();

struct cat_set *sets;
/*
 * Read a catalog and build the internal structure
 */
cat_build(catname)
  char *catname;
{
  FILE *fd;
  struct filehdr hdr;
  
  if ((fd = fopen(catname, "r")) == 0){
    return FALSE;
  }
    
  /*
   * Read file header
   */
  if (fread((char *)&hdr, sizeof(struct filehdr), 1, fd) != 1){
    fprintf(stderr, gettxt("gencat:1","%s : Cannot read header\n"), catname);
    fatal();
  }
    
  /*
   * Test for library
   * or old style malloc
   */
#ifdef u3b2
  if ( hdr.f_magic == WE32MAGIC) {
#endif
#ifdef i386
  if ( hdr.f_magic == I386MAGIC) {
#endif
    fclose(fd);
    cat_lib_build(catname,hdr);
  } else 
  if (((struct cat_hdr*)(&hdr))->hdr_magic == CAT_MAGIC) {
    cat_malloc_build(catname,fd);
    fclose(fd);
  } else {
    fprintf(stderr, gettxt("gencat:2","%s : Not a message catalog\n"), catname);
    fatal();
  }
  return TRUE;
}

static
cat_malloc_build (catname,fd)
  char  *catname;
  FILE *fd;
{
  struct cat_hdr hdr;
  struct cat_set *cur_set, *set_last;
  struct cat_msg *cur_msg, *msg_last;
  char *data;
  struct cat_set_hdr set_hdr;
  struct cat_msg_hdr msg_hdr;
  register int i;

    
  /*
   * Read malloc file header
   */
  rewind(fd);
  if (fread((char *)&hdr, sizeof(struct cat_hdr), 1, fd) != 1){
    fprintf(stderr, gettxt("gencat:3","%s : Cannot read header\n"), catname);
    fatal();
  }
  /*
   * Read sets headers
   */
  for (i = 0 ; i < hdr.hdr_set_nr ; i++){
    struct cat_set *new;
    if ((new = (struct cat_set *)malloc(sizeof(struct cat_set))) == 0){
      fprintf(stderr, gettxt("gencat:4","Out of memory (cat_build.c (1))\n"));
      fatal();
    }
    if (fread((char *)&set_hdr, sizeof(struct cat_set_hdr), 1, fd) != 1){
      fprintf(stderr, gettxt("gencat:5","Cannot read set headers\n"));
      fatal();
    }
    new->set_nr = set_hdr.shdr_set_nr;
    new->set_msg_nr = set_hdr.shdr_msg_nr;
    new->set_next = 0;
    if (sets == 0)
      sets = new;
    else
      set_last->set_next = new;
    set_last = new;
  }

  /*
   * Read messages headers
   */
  for (cur_set = sets ; cur_set != 0 ; cur_set = cur_set->set_next){
    cur_set->set_msg = 0;
    for (i = 0 ; i < cur_set->set_msg_nr ; i++){
      struct cat_msg *new;

      if ((new = (struct cat_msg *)malloc(sizeof(struct cat_msg))) == 0){
        fprintf(stderr, gettxt("gencat:6","Out of memory (cat_build.c (2))\n"));
        fatal();
      }
      if (fread((char *)&msg_hdr, sizeof(struct cat_msg_hdr), 1, fd) != 1){
        fprintf(stderr, gettxt("gencat:7","%s: Cannot read message headers\n"), catname);
        fatal();
      }
      new->msg_nr = msg_hdr.msg_nr;
      new->msg_len = msg_hdr.msg_len;
      new->msg_next = 0;
      if (cur_set->set_msg == 0)
        cur_set->set_msg = new;
      else
        msg_last->msg_next = new;
      msg_last = new;
    }
  }
  
  /*
   * Read messages.
   */
  for (cur_set = sets ; cur_set != 0 ; cur_set = cur_set->set_next){
    for (cur_msg = cur_set->set_msg ;cur_msg!= 0;cur_msg= cur_msg->msg_next){

      if (fread(msg_buf, 1, cur_msg->msg_len, fd) != cur_msg->msg_len ){
        fprintf(stderr, gettxt("gencat:8","%s: Cannot read messages\n"), catname);
        fatal();
      }

      /*
       * Put message in the temp file and keep offset
       */
      cur_msg->msg_off = ftell(tempfile);

      if (list)
	printf(gettxt("gencat:9","Set %d,Message %d,Offset %d,Length %d\n%.*s\n*\n"),
	  cur_set->set_nr,cur_msg->msg_nr,cur_msg->msg_off,cur_msg->msg_len,
	  cur_msg->msg_len,msg_buf);

      if (fwrite(msg_buf, 1, cur_msg->msg_len, tempfile) != cur_msg->msg_len){
        fprintf(stderr, gettxt("gencat:10","add_msg : Write error in temp file\n"));
        fatal();
      }
    }
  }
}

static
cat_lib_build (catname,fd,hdr)
  char  *catname;
  FILE *fd;
  struct filehdr *hdr;
{
  struct cat_set *cur_set, *set_last;
  struct cat_msg *cur_msg, *msg_last;
  char *data;
  struct cat_set_hdr set_hdr;
  struct cat_msg_hdr msg_hdr;
  struct l_cat_set mkmsgs_set;
  register int i;
  register int j;
  register int k;
  int addr;
  char **msg_addr;
  int msg_num;
  int set_num;
  int *msg_ptr;
  int *set_ptr;
  struct cat_set *new;
  extern int msgattach();
  extern int msgdetach();

  /*
   * attach library to get at data
   * dont need read headers then
   */
  if ((addr = msgattach(catname)) == -1) {
    extern int errno;
    fprintf(stderr,gettxt("gencat:11","Can't attach %s Errno %d\n"),catname,errno);
    fatal();
  }

  /*
   * get message number 
   * and start of messages
   */
  msg_num  = ((int*)addr)[0];
  msg_addr = (char**)(addr + ((int*)addr)[1]);
  msg_ptr  = (int*)(addr + sizeof (int));
  set_num  = msg_ptr[msg_num];
  set_ptr  = &(msg_ptr[msg_num+1]);
  if ((int*)msg_addr <= set_ptr) {
    /*
     * is mkmsgs input
     * so there is no set info;
     */
    mkmsgs_set.first_msg = 0;
    mkmsgs_set.last_msg = msg_num;
    set_num = 1;
    set_ptr = (int*)&mkmsgs_set;
  }

  /*
   * get the set info out
   * of a UEL shared library
   */
  
  /*
   * the next line says
   * while there are still sets
   */
  for(i=1;i<=set_num;i++,set_ptr = (int *)((char*)(set_ptr) + sizeof(struct l_cat_set))) {
    if ((new = (struct cat_set *)malloc(sizeof(struct cat_set))) == 0){
      fprintf(stderr, gettxt("gencat:12","Out of memory (cat_build.c (10))\n"));
      msgdetach(addr);
      fatal();
    }
    new->set_nr = i;
    new->set_next = 0;
    if (sets == 0)
      sets = new;
    else
      set_last->set_next = new;
    set_last = new;

    /*
     * create message headers
     */
    new->set_msg = 0;
    for(j=1, k=((struct l_cat_set*)(set_ptr))->first_msg;
	j <=((struct l_cat_set*)(set_ptr))->last_msg && k != 0; k++, j++) {
        /*
         * check if message if so fill message header then put message
         * intempfile
         */
        if (msg_ptr[k-1] != (int)NULL) {

          struct cat_msg *new_msg;
	  char *p = (char*)((msg_ptr[k-1]) + addr);
          if ((new_msg=(struct cat_msg *)malloc(sizeof(struct cat_msg))) == 0){
            fprintf(stderr, gettxt("gencat:13","Out of memory (cat_build.c (20))\n"));
	    msgdetach(addr);
            fatal();
	  }
          if (new->set_msg == 0) 
	    new->set_msg = new_msg;
	  else
	    msg_last->msg_next = new_msg;
	  new_msg->msg_nr = j;
	  new_msg->msg_len = strlen(p)+1;
	  new_msg->msg_next = 0;
	  msg_last = new_msg;
	  /*
	   * write message to tempfile
	   */
          new_msg->msg_off = ftell(tempfile);
	  if (list)
	    printf(gettxt("gencat:14","Set %d,Message %d,Offset %d,Length %d,Text %.*s\n*\n"),
	    i,j,new_msg->msg_off,new_msg->msg_len,
	    new_msg->msg_len,p);
          if(fwrite(p,1,new_msg->msg_len,tempfile)!=new_msg->msg_len){
            fprintf(stderr, gettxt("gencat:15","add_msg : Write error in temp file\n"));
	    msgdetach(addr);
            fatal();
          }
	}
    }
  }
  msgdetach(addr);
}
