/* db2tex.c - data base to TeX;         UKE/EDV, Bernd Paradies, 18.10.90
* Kleinere �nderungen: H. Astheimer, UKE-Kinderklinik, 16.4.91
* Gr��ere  �nderungen: K. Rath,      UKE-Kinderklinik, 20.1.92
*
*
*                  Copyright (c) 1990, 1991, 1992
*                Universit�ts Krankenhaus Eppendorf
*                 Abt. f. H�matologie und Onkologie
*                          Kinderklinik
*                        Martinistra�e 52
*                        2000 Hamburg 20
*
*
* AUTHOR:  Bernd Paradies
*
* SYNTAX:  dbtex [-hq][-n rep-lines] [-o output-file] [TeX-file] [rep-file]
*
* DESCRIPTION:
*   dbtex setzt f�r Spaltennamen in TeX-Dateien den entsprechenden
*   Spalteninhalt ein. Die Spalteninhalte werden �ber eine Datei im
*   'Standard'-Report-Format eingelesen, wobei f�r jede Zeile der
*   Report-Datei eine TeX-Datei mit den Spaltendaten erzeugt wird.
*   Eine typische Anwendung f�r dbtex w�re z.B. ein Serienbrief, bei
*   dem der Adressenkopf variiert.
*
* OPTIONS:
*
*  -n : setzt die maximale Anzahl der Zeilen, die von der Report-Datei
*       eingelesen wird.
*  -o : setzt einen neuen Namen f�r die Ausgabe-Dateien.
*       dbtex -o brief.deu erzwingt Ausgabe in brief.deu
*       (statt dbtex.def) und brief.deu2 (statt dbtex.inp).
*  -q : unterdr�ckt die Ausgabe.
*  -c : nur Compilieren
*  -h : Hilfstext und Copyright
*
*
* INTERNAS:
*   Es wird zun�chst ein Text-Rumpf erstellt und im zweiten
*   Durchgang die Report-Datei Zeile f�r Zeile ausgewertet (GetReport).
*   Dabei werden die Spalteninhalte dem Rumpf als Macros zugewiesen.
*
* FILES:
*   db2tex.h:  header-file
*   db2tex.c:  main
*   db_tex.c:  Routinen f�r die Behandlung von TeX-Dateien
*
* BUGS:
*   - beim L�schen der tempor�ren Dateien wird keine weitere
*     �berpr�fung vorgenommen, ob z.B. das Original gel�scht wird.
*   - die Fehlermeldungen und Warnungen sind in deutsch und englisch.
*   27.12.90:
*   - "dbtex a.tex a.rep" stellt nicht a.rep her.
*   -
*
*/

static char  sccsid[] = "@(#)db2tex ; v1.30/bp+kr ; 01/92";

#include "db2tex.h"


char    SpTab[MAXSPALTEN][50];
int     SpLen[MAXSPALTEN];
int     SpNr = 0;

int     TxtZeilen, GetRepZeilen, RepZeilen, DefZeilen, InpZeilen;
int     MaxReport = MAXREP;

BOOL    BeginDocument = FALSE;
BOOL    EndDocument   = FALSE;
FILE   *InpFile = NULL;
FILE   *DefFile = NULL;
FILE   *ShFile  = NULL;
FILE   *stdlog  = stderr;

int     OptQuiet   = FALSE;
int     OptCompile = FALSE;
int     OptOutput  = FALSE;
char   *prgname    = NULL;
char   *prgpath    = NULL;

#define   DelFile(nm)   if (!OptQuiet) printf("L�sche: %s\n",nm); unlink(nm);

/* ====================================================================== */

PUBLIC  FILE *_fopen(name, mode)
       char *name;
       char *mode;
{
FILE   *Txt;
char    Err[80];

 if ( (Txt = fopen (name, mode)) == NULL )
 {
   strcpy (Err, "Can't open file: ");
   strcat (Err, name);
   error (Err);
 }
 return (Txt);
}

/* ---------------------------------------------------------------------- */

PUBLIC  char *strtoupper(Str)
       char *Str;
{
REG ii;

 for (ii=0; ii != strlen (Str); ii++)
   Str[ii] = toupper (Str[ii]);
 return (Str);
}

/* ---------------------------------------------------------------------- */

PUBLIC char *delblank(Str)
      char *Str;
{
char *Text;

 Text = Str;
 while (*Text == BLANK)            /* die vorderen Leerzeichen entfernen */
   Text++;
 strcpy (Str, Text);
 Text = Str + strlen(Str) - 1;

 while ( (*Text == BLANK) && (Text != Str) )
 {
   *Text = 0;                      /* die hinteren entfernen */
    Text--;
 }
 return (Str);
}

/* ---------------------------------------------------------------------- */

PUBLIC char *ChkName(Name)
      char *Name;
{
char  UpName[MAXZEILE];
REG   ii;

 strtoupper(strcpy (UpName, Name));   /* alles in Gro�-Buchstaben */

 for (ii=0; ii != SpNr; ii++)
   if (strncmp (SpTab[ii], UpName, strlen (SpTab[ii])) == 0)
     return (SpTab[ii]);                             /* gefunden ! */

 return (NULL);                                      /* nicht gefunden */
}

/* ---------------------------------------------------------------------- */

PUBLIC int   GetSQL(Zeile)
      char *Zeile;
{
char  *Zptr;
char   SpNamen[MAXZEILE];

 if ( (Zeile[0] != '%') || (Zeile[1] != '$') )
   error ("Falsches db2tex-Format: fehlende Spaltenbeschreibung in Zeile(1)");

 Zeile[strlen(Zeile)-1] = 0;                                /* \n l�schen */
 Zptr = strtok (strcpy (SpNamen, strtoupper (Zeile)), " ");

 while ( Zptr != NULL )
 {
   if (SpNr > MAXSPALTEN)
     error ("Zuviele Spalten !");

   if ( (Zptr = strtok (NULL, " ")) != NULL )
     strcpy (SpTab[SpNr++], Zptr);
 }

 if (SpNr == 0)
   error ("Keine Spalten zu verarbeiten !\n");

 return (0);
}

/* ---------------------------------------------------------------------- */

PUBLIC int   GetReport(Nr,Zeile)
      int   Nr;
      char *Zeile;
{
int     NameNr = 0;
char   *Sptr;
REG     ii;

 if (Nr >= (MaxReport))  return (0);

 switch (Nr)
 {
   case 1:  Sptr = strtok (Zeile, " ");
            while ( (Sptr != NULL) && (NameNr++ < SpNr) )
              Sptr = strtok (NULL, " ");

            if (SpNr > NameNr)
              warning ("Es fehlen Spalten in der Report-Datei. Anzahl",
                       (SpNr-NameNr) );
            break;

   case 2:  for (ii=0; ii != SpNr; ii++)
              SpLen[ii] = (ii==0) ? strlen (strtok (Zeile, SEP))
                                  : strlen (strtok (NULL,  SEP));
            break;

   default: PutTexRep(Nr, Zeile);
            GetRepZeilen++;
            break;
 }
 return (0);
}

/* ---------------------------------------------------------------------- */

PUBLIC int    WalkFile(Fname,Action)
      char  *Fname;
      int  (*Action)();
{
FILE  *Txt;
char   Zeile[MAXZEILE];
int    Nr = 0;

 Txt = _fopen (Fname, "r");

 while ( fgets (Zeile, MAXZEILE, Txt) != NULL )
   Action (++Nr, Zeile);

 fclose (Txt);
 return (Nr);    /* liefere Anzahl der gelesenen Zeilen zur�ck */
}

/* ---------------------------------------------------------------------- */

#define KEY_ZAHL   16

char *KeyWords[KEY_ZAHL] =
     { /* File-Parameter:
          0       1         2      3        4      5                       */
          "TEXT", "REPORT", "DEF", "INPUT", "DVI", "OUTPUT",
       /* TeX-Parameter:
          6         7         8          9          10        11           */
          "DVITPS", "DVITTY", "PRINTER", "TEXPOOL", "VIRTEX", "UMLT2TEX",
       /* Sonstiges:
          12       13              14     15                               */
          "QUIET", "COMPILE_ONLY", "SEP", "OUTDEV"};

PUBLIC int GetIni(IniFile)
FILE *IniFile;
{
  int  DateiEnde     = NULL;
  int  ConfigCounter = NULL;
  char zbuf[80];
  char *tbuf;
  int  Zaehler;
  int  EndLine = 0;

  while ( !DateiEnde )
  {
      DateiEnde = feof(IniFile);
      if ( DateiEnde )
      {
          continue;
      }

      zbuf[0] = '\0';

      fgets(zbuf,80,IniFile);
      zbuf[strlen(zbuf)-1] = '\0';                  /* Strip LF            */

      if ( (strlen(zbuf) < 2) || (zbuf[0] == '#') ) /*Kommentare,Leerzeilen*/
      {
          continue;
      }

      tbuf = (char *)strtok(zbuf,"=");
      for ( Zaehler = 0 ; Zaehler < KEY_ZAHL ; Zaehler++ )
      {
          if ( strcmp(tbuf,KeyWords[Zaehler]) == NULL )
          {
              ConfigCounter++;
              tbuf = (char *)NULL;
              tbuf = (char *)strtok(NULL," ");
              switch ( Zaehler )
              {
                  case  0:                                 /* TEXT         */
                           strcpy(TxtName,tbuf);
                           break;
                  case  1:                                 /* REPORT       */
                           strcpy(RepName,tbuf);
                           break;
                  case  2:                                 /* DEF          */
                           strcpy(DefName,tbuf);
                           break;
                  case  3:                                 /* INPUT        */
                           strcpy(InpName,tbuf);
                           break;
                  case  4:                                 /* DVI          */
                           strcpy(DviName,tbuf);
                           break;
                  case  5:                                 /* OUTPUT       */
                           OptOutput = TRUE;
                           strcpy(OutName,tbuf);
                           break;
                  case  6:                                 /* DVITPS       */
                           DVITPS[0] = '\0';
                           sprintf(DVITPS,"%s/%s",TEXPOOL,tbuf);
                           EndLine = 0;
                           while ( !EndLine )
                           {
                               tbuf = (char *)NULL;
                               if ( (tbuf = (char *)strtok(NULL," ")) == NULL )
                               {
                                   EndLine++;
                                   continue;
                               }
                               strcat(DVITPS," ");
                               strcat(DVITPS,tbuf);
                           } /* ENDE: while */
                           break;
                  case  7:                                 /* DVITTY       */
                           DVITTY[0] = '\0';
                           sprintf(DVITTY,"%s/%s",TEXPOOL,tbuf);
                           EndLine = 0;
                           while ( !EndLine )
                           {
                               tbuf = (char *)NULL;
                               if ( (tbuf = (char *)strtok(NULL," ")) == NULL )
                               {
                                   EndLine++;
                                   continue;
                               }
                               strcat(DVITTY," ");
                               strcat(DVITTY,tbuf);
                           } /* ENDE: while */
                           break;
                  case  8:                                 /* PRINTER      */
                           PRINTER[0] = '\0';
                           if ( tbuf[0] == '$' )
                               strcpy(PRINTER,getenv(&tbuf[1]));
                           else
                               strcpy(PRINTER,tbuf);
                           break;
                  case  9:                                 /* TEXPOOL      */
                           TEXPOOL[0] = '\0';
                           if ( tbuf[0] == '$' )
                               strcpy(TEXPOOL,getenv(&tbuf[1]));
                           else
                               strcpy(TEXPOOL,tbuf);
                           break;
                  case 10:                                 /* VIRTEX       */
                           VIRTEX[0] = '\0';
                           sprintf(VIRTEX,"%s/%s",TEXPOOL,tbuf);
                           EndLine = 0;
                           while ( !EndLine )
                           {
                               tbuf = (char *)NULL;
                               if ( (tbuf = (char *)strtok(NULL," ")) == NULL )
                               {
                                   EndLine++;
                                   continue;
                               }
                               strcat(VIRTEX," ");
                               strcat(VIRTEX,tbuf);
                           } /* ENDE: while */
                           break;
                  case 11:                                 /* UMLT2TEX     */
                           UMLT2TEX[0] = '\0';
                           sprintf(UMLT2TEX,"%s/%s",TEXPOOL,tbuf);
                           break;
                  case 12:                                 /* QUIET        */
                           if ( strcmp(tbuf,"yes") == NULL )
                               OptQuiet = TRUE;
                           break;
                  case 13:                                 /* COMPILE_ONLY */
                           if ( strcmp(tbuf,"yes") == NULL )
                               OptCompile = TRUE;
                           break;
                  case 14:                                 /* SEP          */
                           SEP[0] = '\0';
/*                          strcpy(SEP,tbuf);*/
                           if (tbuf[0] == '\'' || tbuf[0] == '\"')
                             SEP[0] = ' ';
                           else
                             SEP[0] = tbuf[0];
                             SEP[1] = '\0';
                           break;
                  case 15:                                 /* OUTDEV       */
                           OUTDEV[0] = '\0';
                           strcpy(OUTDEV,tbuf);
                           break;

                  default: break;               /* Alles andere ignorieren */

              } /* ENDE: switch(Zaehler) */
              break;
          }  /* ENDE: if(strcmp()) */
      } /* ENDE: for(Zaehler) */

  } /* ENDE: while(DateiEnde) */

  return(ConfigCounter);

} /* ENDE: GetIni() */

/* ---------------------------------------------------------------------- */

PRIVATE info(void)
{
REG  ii;

 if (!OptQuiet)
 {
   printf ("\n%s:\n", prgname);
   printf ("\t EINGABE: %s (Textdatei,   Z:%i)\n",   TxtName, TxtZeilen);
   printf ("\t EINGABE: %s (Reportdatei, Z:%i von %i)\n\n",
                            RepName, GetRepZeilen, RepZeilen);

   if (!OptCompile)
     printf ("\t AUSGABE: %s\n", OptOutput ? OutName : "(interaktiv)");
   else
   {
     printf ("\t AUSGABE: %s (Zwischendatei, Z:%i)\n", InpName,InpZeilen);
     printf ("\t AUSGABE: %s (Zwischendatei, Z:%i)\n", DefName, DefZeilen);
   }
   printf ("\n\t Max. Report-Zeilen: %i\n", MaxReport-3);
   if (SpNr != 0)
   {
     printf ("\t Benutzte Spalten: ");
     for (ii=0; ii!=SpNr; ii++)
       printf ("%s ", SpTab[ii]);
     printf ("\n");
   }
   printf ("\n");
 }
}

/* ---------------------------------------------------------------------- */

PRIVATE usage(void)
{
 printf ("\n");
 printf ("(c) UKE-Kinderklinik, Abt.f. H�matologie und Onkologie, ");
 printf ("AG EDV & Statistik\n\n");

 printf ("%s   Ver 1.30, 24.01.92\n","db2tex - data base to TeX.", prgname);
 printf ("Usage: %s [-hqc][-n report-lines] [-o output-file] ", prgname);
 printf ("[TeX-file] [report-file] \n");
 printf ("Options:\n");
 printf ("\t -c : compile only\n");
 printf ("\t -n : set max. report lines\n");
 printf ("\t -o : set output file name\n");
 printf ("\t -q : quiet running\n");
 printf ("\t -h : this help text\n\n");
 printf ("Default file name: %s\n", TxtName);
 printf ("\n");
}

/* ---------------------------------------------------------------------- */

PRIVATE void atexit(void)
{
/*
 if (MemBlocks != 0)
   warning ("missing free ! - MemBlocks: ", MemBlocks);
*/
}


/* ---------------------------------------------------------------------- */

PUBLIC int   main(argc,argv,envp)
      int   argc;
      char *argv[];
      char *envp[];
{
IMPORT  char *optarg;
IMPORT  int   optind;
IMPORT  int   opterr;
REG     int   Opt;
FILE   *IniFile;
char    IniFileName_1[60];
char    IniFileName_2[20];

 /* -- Initialsierung */

 prgname = (char *)basename(argv[0]);         /* Eigenen Namen feststellen */
 prgpath = (char *)dirname(argv[0]);          /* wo bin gestartet ?        */

 sprintf(IniFileName_1,"%s/%s.ini",prgpath,prgname);
 sprintf(IniFileName_2,"%s.ini",prgname);

 TxtZeilen = GetRepZeilen = RepZeilen = DefZeilen = InpZeilen = 0;

 /* -- Diverse Variable vorbelegen, danach die Standard-Startdatei suchen, */
 /* -- anschlie�end evtl. eine individuelle Startdatei. Die Variablen wer- */
 /* -- in dieser Reihenfolge belegt und ggfls. �berschrieben!              */
 /* -- Eingestellte Optionen werden von Kommandozeilen-Parametern evtl.    */
 /* -- nocheinmal �berschrieben !!!                                        */

 /* Default-Belegung :
 */
 sprintf (TxtName, "%s.%s",  prgname, STDTEXNAME);
 sprintf (RepName, "%s.%s",  prgname, STDREPNAME);
 sprintf (DefName, "%s.%s",  prgname, STDDEFNAME);
 sprintf (InpName, "%s.%s",  prgname, STDINPNAME);
 sprintf (DviName, "%s.dvi", prgname);
 strcpy  (OutName, "");
 strcpy  (TEXPOOL, STDTEXPOOL);
 sprintf (VIRTEX,  "%s/%s",  TEXPOOL, STDVIRTEX);
 sprintf (DVITPS,  "%s/%s",  TEXPOOL, STDDVITPS);
 sprintf (DVITTY,  "%s/%s",  TEXPOOL, STDDVITTY);
 sprintf (PRINTER, "%s",     STDPRINTER);

 /* Nach .ini-Datei erst im Start- und dann im aktuellen Verzeichnis
 ** suchen :
 */
 if ( IniFile = fopen(IniFileName_1,"r") )
 {
     GetIni(IniFile);
     fclose(IniFile);
 }
 else
 {
     fprintf(stderr,"\n%s: Standard-Startdatei %s nicht gefunden!\n");
 } /* ENDE: if(IniFileName_1) */

 if ( IniFile = fopen(IniFileName_2,"r") )
 {
     GetIni(IniFile);
     fclose(IniFile);
 } /* ENDE: if(IniFileName_2) */

 /* -- Parameter-Auswertung */

 while ( (Opt = getopt (argc, argv, "hcqo:n:")) != EOF)
   switch (Opt)
   {
     case 'h' :  usage(); exit (0);                               break;
     case 'q' :  OptQuiet   = TRUE;                               break;/*i*/
     case 'n' :  MaxReport  = atoi (optarg);                      break;
     case 'c' :  OptCompile = TRUE;                               break;/*i*/
     case 'o' :  OptOutput  = TRUE; strcpy(OutName, optarg);      break;/*i*/
     default  :  usage();           error ("Unbekannte option");  break;
   }

 if (argv[optind] != NULL)
 {
   strcpy (TxtName, argv[optind]);
   if (argv[optind+1] != NULL)
     strcpy (RepName, argv[optind+1]);
 }


 /* -- Informationen */
 MaxReport += 3;
 info();

 /* -- GetTex und GetReport */

 do_tex();


 /* -- Abschlu�-Statistik */

 DefZeilen += 5;
 info();

 if (!OptCompile)
 {
   if (!OptQuiet)
     printf ("Zwischendateien werden wieder gel�scht !\n");
     DelFile(DefName);
     DelFile(InpName);
     DelFile(DviName);
 }

 atexit();
 return (0);
}

/* -- end of file ------------------------------------------------------- */