/*********************************************************************
 *
 *  projet   : DilibDam
 *  module   : DamHfd  (Dilib Acces Method)
 *  fichier  : DamHfdBuild.c
 *  Auteur   : Jacques DUCLOY
 *  Date     : Octobre 93
 *  $Id: DamHfdBuild.c,v 1.4 2005/06/22 12:45:37 parmentf Exp $
 *********************************************************************
 *
 * Copyright (c) 1993 INIST - CNRS
 *
 *********************************************************************/
/**
   @file

   @brief DamHfdBuild command

   @section DamHfdBuildSYNOPSIS SYNOPSIS

   @code
   DamHfdBuild [-s] -h hfd_name [-f descriptor][-z]
   @endcode

   @section DamHfdBuildDESCRIPTION DESCRIPTION

   @p DamHfdBuild transforms a stream of records into a hfd file the
   organisation of which is described by DamHfd(5).


   @section DamHfdBuildOPTIONS OPTIONS
   
   @p -s (skip key) skips the beginning of each record (until tab).

   @p -h @p hfd_name is the root name of the resulting hfd file.

   @p -f @p hfd_descriptor is a stream containing hfd description (if
   omitted a default descriptor corresponding to Ilib Hfd structure is
   taken).

   @p -z to compress the hfd file. Needs @c find, @c xargs and @c gzip in @c /usr/bin


   @section DamHfdBuildEXAMPLES EXAMPLES

   Let file @p struct be:
   @code
   <hfd>
     <struct>
       <dir>
         <digit>ABC
	 <digit>123
       </dir>
       <dir>
         <digit>abc
	 <digit>123
       </dir>
       <file>
         <digit>xy
	 <digit>01
       </file>
       <key>
         <digit>01
	 <digit>05
       </key>
     </struct>
   </hfd>
   @endcode

   The following command:
   @code
   DamHfdBuild -h resul -f struct
   @endcode

   on file:
   @code
   <a>aaaaaaa</a>
   <a>bbbbbbb</a>
   <a>ccccccc</a>
   <a>ddddddd</a>
   <a>eeeeeee</a>   
   @endcode

   will produce:
   @code
   resul.hfd/
            A1.dd/
	         a1.dd/
		      x0.df
                         A1a1x000  <a>aaaaaaa</a>
                         A1a1x005  <a>bbbbbbb</a>
                         A1a1x010  <a>ccccccc</a>
                         A1a1x015  <a>ddddddd</a>
		      x1.df
                         A1a1x100  <a>eeeeeee</a>
   @endcode

   @see DamHfd(5), DamHfdMulti(1)

   @author &copy; INIST-CNRS
   @author Jacques DUCLOY, Dominique BESAGNI, P. CHARPENTIER
           <DilibMaster@inist.fr>
   @since  1993
   @return 0 if OK
   @return 1 if the arguments were not good

*/

#include <stdlib.h>	/* getopt + system */
#include <unistd.h>	/* getopt */
#include <stdio.h>
#include <string.h>
/* #include <malloc.h> useless since stdlib.h is included */
#include <sys/types.h>
#include <sys/stat.h>

#include "SgmlPath.h"

#include "DamFile.h"
#include "DamHfd.h"
void perror();

/******************* les options **********************************/
static int optionSkipKey;
static int optionCompress;
/******************* le controle de l'entrée **********************/

/* static int InputEOF_HasBeenFound=NULL; */
static int InputEOF_HasBeenFound=0;
static FILE *InputFile;

int InputNextRecord()
{
  int c; /*char c;*/
  if (InputEOF_HasBeenFound) return 0 /*NULL*/;
  if ((c=getc(InputFile))==EOF) 
     {
       InputEOF_HasBeenFound=1;
       return 0; /* return NULL; */
     };
  if (c=='\n') return InputNextRecord();
  ungetc(c,InputFile);
  return 1;
} /* InputNextRecord() */

void InputRecordCopyOnHfd(DamHCB *hcb)
{
  int c; /*char c;*/
  int tabHasBeenFounded;

  if  (optionSkipKey==1)
    {
      tabHasBeenFounded=0;
    }

  while ((c=getc(InputFile))!=EOF)
    {  
      if  (optionSkipKey==1)
	 {
	   if(tabHasBeenFounded==0)
	     {
	       if(c=='\t')tabHasBeenFounded=1;
	     }
	   else fputc(c,DamHCB_File(hcb));
	 }
      else fputc(c,DamHCB_File(hcb));
      if (c=='\n') return;
    }

  fputc('\n', DamHCB_File(hcb));
  InputEOF_HasBeenFound=1;
} /* InputRecordCopyOnHfd() */

int InputWriteNextRecordOnHfd(DamHCB *hcb)
{
  if (InputNextRecord())
    {
      fputs(DamHCB_RecordPath_NextKey(hcb),DamHCB_File(hcb));
      fputc('\t',DamHCB_File(hcb));
      InputRecordCopyOnHfd(hcb);
      return 1;
    }
  else return 0; /*return NULL; */
} /* InputWriteNextRecordOnHfd() */

/*******************************************************************/
DamHCB *DamHfdCreate(SgmlNode *desc, char *root, char mode)
{
  DamHCB *newHCB;
  SgmlNode *desc1;
  SgmlNode *nState;
  int nrec;
  char bufNum[20];

  desc1=SgmlCopy(desc);
  SgmlAddLeaf(desc1,"name",root);
  newHCB= DamHCB_Create(desc1);

  nState=SgmlAddLeaf(DamHCBdesc(newHCB),"state","creating");
  DamHCB_Print(newHCB);

  mkdir(DamHCB_RootPath(newHCB),newHCB->umask);
  DamHCB_ListDir_FirstDir(newHCB);

  nrec=0;

  DamHCB_FilePath_FirstFile(newHCB);
  if (InputNextRecord())
    {
      fputs(DamHCB_RecordPath_FirstKey(newHCB),DamHCB_File(newHCB));
      fputc('\t',DamHCB_File(newHCB));
      InputRecordCopyOnHfd(newHCB);
      nrec++;
    };
 
  while (InputWriteNextRecordOnHfd(newHCB)){nrec++;};

  fclose(DamHCB_File(newHCB));

  SgmlAddLeaf(DamHCBdesc(newHCB),"lastkey",DamHCB_LastKey(newHCB));
  sprintf(bufNum,"%d",nrec);
  SgmlAddLeaf(DamHCBdesc(newHCB),"nrec",bufNum);
  SgmlLeafPutString(nState,"created");
  DamHCB_Print(newHCB);

  return newHCB;
} /* DamHfdCreate() */

/**************************************************************************/

    int getopt();
    extern char *optarg;

void usage()
{
  perror ("usage: DamHfdBuild [-s] -h hfd_name [-f descriptor]\n");
  exit(1);
}

int main(int argc, char **argv)
{

  DamFile  *hfdModele;
  SgmlNode *hfdDesc;
  char *hfdName;
  char *sysCommand;
  int cod_arg;

  optionSkipKey=0;
  optionCompress=0;

  hfdDesc=SgmlFromString("<hfd><struct><dir><digit>0123456789ABCDRF</digit><digit>0123456789ABCDEF</digit></dir><file><digit>0123456789ABCDEF</digit><digit>0123456789ABCDEF</digit></file><key><digit>0123456789</digit><digit>0123456789</digit></key></struct></hfd>");
  if (argc<2)usage();

    while ((cod_arg = getopt(argc,argv,"f:h:s:z"))!=EOF)
      {
	switch(cod_arg) {
	case 'f' : 
	  hfdModele=DamFileCreate();
	  DamFileOpen(hfdModele,optarg);
	  hfdDesc=DamFileNextSgml(hfdModele);
	  DamFileClose(hfdModele);
	  break;
	case 'h' :
	  hfdName=DamGetPath(optarg, 'r', 'A');
	  break;
	case 's' :
	  optionSkipKey=1;
	  break;
	case 'z':
	  optionCompress=1;
	  break;
	default: usage();
	  break;
     }};
  InputFile=stdin;

  DamHfdCreate(hfdDesc,hfdName,'w');

  if(optionCompress) {
    sysCommand=malloc(sizeof(char)*(strlen(hfdName)+80));
    sprintf(sysCommand,
	    "/usr/bin/find %s.hfd -name \"*.df\" | /usr/bin/xargs /usr/bin/gzip ",
	    hfdName);
    system(sysCommand);
    free(sysCommand);
  }

  return 0;
}
