%{
#include <stdio.h>
#include <ctype.h>
#include <X11/Intrinsic.h>
#include <unistd.h>
#include "bibview.h"


#define YYSTYPE char

#define __RUNTIME_YYMAXDEPTH
#define YYMAXDEPTH 1000

#define MAX_UEBERGABE  20000

char uebergabe[MAX_UEBERGABE];
int ueIdx = 0;

FILE *tempDatei;
extern FILE *yyin;
extern YY_NEW_FILE;
extern int yy_init;

extern int fld_indent, cont_indent, newline_indent;

typedef struct _Snode {
                       char inh;
                       int slen;
                       struct _Snode *next;
} Snode;

/*******************************************/
/* Globale Variablen                       */
/*******************************************/

int yynline;
int yynflexcalls;
int yynerrs;
char errorstr[MAX_ERRORSTRLEN];

/*******************************************/
/* Lokale Variablen                        */
/*******************************************/

static Snode *key = NULL;            
static Snode *fldname = NULL;       
static Snode *fldcont = NULL;      

static char errstr[MAX_ERRLINELENGTH];
#ifdef GERMAN
static char *anfhelpstr = 
  "Es wurden leider Fehler entdeckt\n\n\t%15s\t\t%10s\t%10s\n";
static char *endhelpstr = 
  "\n%40s: %3d Fehler";
#else
static char *anfhelpstr = 
  "Sorry, but there were syntax errors:\n\n\t%15s\t\t%10s\t%10s\n";
static char *endhelpstr = 
  "\n%40s: %3d errors";
#endif
static CardType cardtype;
static CardData *card = NULL;
static UserFld *helpufield = NULL;
static String helpFldName = NULL;
static String errkey;
static Errcode err;
static BibPtr glbbp;
static int beginIdx;
static int keyline;
static int errorline;

/*******************************************/
/* Lokale Funktionen                       */
/*******************************************/

static void PushSign(Snode **w, char a);
static void AppendSign(Snode **w, char a);
static void FreeStack(Snode **s);
static void StackToString(Snode *s, char **text); 
static void GetKey();
static void GetFldNameCont();
static void SecStrcat(int maxlen, char *str1, char *str2);

static int SetInputFile(char *file);
static int SkipSpace(char *text, Snode **new);
static int SkipNewLineSpace(char *text);
static int StringIsPeteEmpty(char *text);
static void WriteRecToFile(CardData *card, FILE *datei);
static long WriteLineToFile(FILE *datei, char *feld, char *inh);
%}
%token  COMMENT
%token  STRING
%token  PREAMBLE
%token  ARTICLE
%token  BOOK
%token  BOOKLET
%token  CONFERENCE
%token  INBOOK
%token  INCOLLECTION
%token  INPROCEEDINGS
%token  MANUAL
%token  MASTERSTHESIS
%token  MISC
%token  PHDTHESIS
%token  PROCEEDINGS
%token  TECHREPORT
%token  UNPUBLISHED
%token  TYPE
%token  KOMMA
%token  EQ
%token  LGKL
%token  RGKL
%token  LRKL
%token  RRKL
%token  DAZ
%token  ZAUN
%token  PROZENT
%token  ZEICHEN
%token  WHITE_SPACE
%token  BUCHSTABE_ZAHL
%token  KOMMENTAR


%%

datei  
         :  between datei
         |  entry datei
         |  entry
         |  between
between
	 : KOMMA
	 | EQ
	 | LGKL
	 | RGKL
	 | LRKL
	 | RRKL
	 | DAZ
	 | ZAUN
	 | PROZENT
	 | ZEICHEN
	 | WHITE_SPACE
	 | BUCHSTABE_ZAHL
	 | KOMMENTAR

entry
	 :  COMMENT
	 |  string
	 |  preamble
	 |  eintrag
         |  error RGKL
	      {StackToString(key, &errkey);
	       FreeStack(&key);
	       if ((errkey!=NULL) && (errkey[0]!='\0')){
		 sprintf(errstr, "\t%15s:\t%10d\t%10d\n", 
				 errkey, errorline-keyline, errorline-1);
                 XtFree(errkey);
		 errkey = NULL;
		 }
               else
		 sprintf(errstr, "\t%15s:\t%10d\t%10d\n", "key unknown", 
				     errorline-keyline, errorline-1);
               SecStrcat(MAX_ERRORSTRLEN, errorstr, errstr);
	       }
	    
string
         :  STRING LGKL allstringG RGKL
              {         
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@STRING"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 
         |  STRING leerraum LGKL allstringG RGKL
              {          
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@STRING"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 
         |  STRING LRKL allstringR RRKL 
              {         
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@STRING"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 
         |  STRING leerraum LRKL allstringR RRKL
              {         
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@STRING"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 

preamble
         :  PREAMBLE LGKL allstringG RGKL
              {         
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@PREAMBLE"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 
         |  PREAMBLE leerraum LGKL allstringG RGKL 
              {         
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@PREAMBLE"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 
         |  PREAMBLE LRKL allstringR RRKL
              {         
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@PREAMBLE"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 
         |  PREAMBLE leerraum LRKL allstringR RRKL
              {         
		keyline = yynline;
                beginIdx = SkipNewLineSpace(uebergabe);
                fprintf(tempDatei,"@PREAMBLE"); 
                fprintf(tempDatei,"%s\n",&uebergabe[beginIdx]); 
                ueIdx = 0;
              } 

allstringG
         :  WHITE_SPACE allstringG
         |  KOMMENTAR allstringG
         |  ZEICHEN  allstringG
         |  BUCHSTABE_ZAHL allstringG
         |  KOMMA allstringG
         |  EQ allstringG
         |  ZAUN allstringG
         |  PROZENT allstringG
         |  DAZ allstringG
         |  LGKL allstringG RGKL allstringG
         |  LGKL RGKL allstringG
         |  LGKL allstringG RGKL
         |  LGKL RGKL
         |  LRKL allstringG
         |  RRKL allstringG
         |  WHITE_SPACE
         |  KOMMENTAR
         |  ZEICHEN
         |  BUCHSTABE_ZAHL
         |  KOMMA
         |  EQ
         |  ZAUN
         |  PROZENT 
         |  DAZ
         |  LRKL
         |  RRKL 

allstringR
         :  WHITE_SPACE allstringR
         |  KOMMENTAR allstringR
         |  ZEICHEN  allstringR
         |  BUCHSTABE_ZAHL allstringR
         |  KOMMA allstringR
         |  EQ allstringR
         |  ZAUN allstringR
         |  PROZENT allstringR
         |  DAZ allstringR
         |  LGKL allstringR RGKL allstringR
         |  LGKL RGKL allstringR
         |  LGKL allstringR RGKL
         |  LGKL RGKL
         |  LRKL allstringR RRKL allstringR
         |  LRKL allstringR RRKL
         |  LRKL RRKL
         |  WHITE_SPACE
         |  KOMMENTAR
         |  ZEICHEN
         |  BUCHSTABE_ZAHL
         |  KOMMA
         |  EQ
         |  ZAUN
         |  PROZENT
         |  DAZ
eintrag 
         :  eingabetyp LGKL schluessel KOMMA felder leerraum RGKL 
                {                 
                  GetKey();
                }
         |  eingabetyp leerraum LGKL schluessel KOMMA felder leerraum RGKL 
                {
                  GetKey();
                }
         |  eingabetyp LGKL schluessel KOMMA felder RGKL 
                {
                  GetKey();
                }
         |  eingabetyp leerraum LGKL schluessel KOMMA felder RGKL
                {
                  GetKey();
                }
         |  eingabetyp LRKL schluessel KOMMA felder leerraum RRKL 
                {
                  GetKey();
                }
         |  eingabetyp leerraum LRKL schluessel KOMMA felder leerraum RRKL
                {
                  GetKey();
                }
         |  eingabetyp LRKL schluessel KOMMA felder RRKL 
                {
                  GetKey();
                }
         |  eingabetyp leerraum LRKL schluessel KOMMA felder RRKL
                {
                  GetKey();
                }

eingabetyp
	  :  TYPE
                {
		  err = dbtMakeCard(&card);
		  card->cardtype = cardtype = 
		     glbNameToType(strlower(uebergabe)); 
		  if (cardtype == illegal)
		     card->cardtype = cardtype = MAX_BIBTEX_TYPES;
		  Scalloc(&card->cardtypestr, uebergabe);
                }

schluessel 
            :  leerraum schl
            |  schl leerraum
            |  leerraum schl leerraum
            |  schl


schl
            :  BUCHSTABE_ZAHL schl
                {
                  PushSign(&key, $1);
		  keyline = yynline;
                }
            |  ZEICHEN schl
                {
                  PushSign(&key, $1);
		  keyline = yynline;
                }
            |  DAZ schl
                {
                  PushSign(&key, $1);
		  keyline = yynline;
                }
            |  PROZENT schl
                {
                  PushSign(&key, '%');
		  keyline = yynline;
                  PushSign(&key, '\\');
                }
            |  BUCHSTABE_ZAHL 
                {
                  PushSign(&key, $1);
		  keyline = yynline;
                }
            |  ZEICHEN 
                {
                  PushSign(&key, $1);
		  keyline = yynline;
                }
            |  EQ
                {
                  PushSign(&key, $1);
		  keyline = yynline;
                }
            |  DAZ 
                {
                  PushSign(&key, $1);
		  keyline = yynline;
                }
            |  PROZENT 
                {
                  PushSign(&key, '%');
                  PushSign(&key, '\\');
		  keyline = yynline;
                }

felder 
          :  leerraum feld KOMMA felder
          |  feld KOMMA felder
          |  leerraum feld KOMMA
          |  leerraum feld KOMMA leerraum
          |  feld KOMMA 
          |  feld KOMMA  leerraum
          |  leerraum feld
          |  feld
          |  feld leerraum
          

feld 
          :  feldname leerraum EQ konkatenation
                {
                  GetFldNameCont();
                }
          |  feldname EQ konkatenation 
                {
                  GetFldNameCont();
                }

feldname
          :  BUCHSTABE_ZAHL feldname
                {
                  PushSign(&fldname, $1);
                  ueIdx = 0;
                }
          |  ZEICHEN feldname
                {
                  PushSign(&fldname, $1);
                  ueIdx = 0;
                }
          |  BUCHSTABE_ZAHL
                {
                  PushSign(&fldname, $1);
                  ueIdx = 0;
                }
          |  ZEICHEN 
                {
                  PushSign(&fldname, $1);
                  ueIdx = 0;
                }

leerraum
          :  WHITE_SPACE  leerraum
          |  KOMMENTAR leerraum
          |  WHITE_SPACE
          |  KOMMENTAR
      
konkatenation
             :  konkatenation ZAUN konkatenation
             |  feldinhalt
             |  feldinhalt leerraum
             |  leerraum feldinhalt 
             |  leerraum feldinhalt leerraum

feldinhalt
          :  LGKL allstringG RGKL
          |  DAZ dazfeldinhalt DAZ 
          |  DAZ DAZ 
          |  LGKL RGKL
          |  makro

makro
            :  BUCHSTABE_ZAHL makro
            |  ZEICHEN makro
            |  BUCHSTABE_ZAHL 
            |  ZEICHEN 

dazfeldinhalt
          :  WHITE_SPACE dazfeldinhalt
          |  KOMMENTAR dazfeldinhalt
          |  BUCHSTABE_ZAHL dazfeldinhalt
          |  ZEICHEN dazfeldinhalt
          |  KOMMA dazfeldinhalt
	  |  PROZENT dazfeldinhalt
          |  EQ dazfeldinhalt
          |  ZAUN dazfeldinhalt
          |  LRKL dazfeldinhalt
          |  RRKL dazfeldinhalt
          |  LGKL dazdaz RGKL
          |  LGKL dazdaz RGKL dazfeldinhalt
          |  LGKL RGKL
          |  LGKL RGKL dazfeldinhalt
          |  WHITE_SPACE
          |  KOMMENTAR
          |  BUCHSTABE_ZAHL
          |  ZEICHEN
          |  KOMMA
	  |  PROZENT
	  |  EQ
          |  ZAUN
          |  LRKL
          |  RRKL

dazdaz
          :  WHITE_SPACE dazdaz
          |  KOMMENTAR dazdaz
          |  BUCHSTABE_ZAHL dazdaz
          |  ZEICHEN dazdaz
          |  LRKL dazdaz
          |  RRKL dazdaz
          |  LGKL dazdaz RGKL
          |  LGKL dazdaz RGKL dazdaz
          |  LGKL RGKL
          |  LGKL RGKL dazdaz
          |  WHITE_SPACE
          |  KOMMENTAR
          |  BUCHSTABE_ZAHL
          |  KOMMA dazdaz
          |  DAZ dazdaz
          |  EQ dazdaz
          |  ZEICHEN
          |  LRKL
          |  RRKL
          |  KOMMA
          |  DAZ

%%


static int SkipNewLineSpace(char *text)
{ 
 int erg, back;

 erg = 0;
 while (erg < MAX_UEBERGABE) {
   if (*text == '{' ||  *text == '(') {
     back = strlen(text);
     text = text + back;
     while (*text != '}' && *text != ')') { 
       *text = '\0';
       text--;
     }
     return erg;
   }
   text++;
   erg++;
 }
 return 0;
}




static int SkipSpace(char *text, Snode **new)
{
 int erg, lgkl, daz, index, inmakro;
 
 index = 0;
 lgkl = 0;
 daz = 0;
 inmakro = 0;

 while ((*text == ' ' || *text == '=' || *text == '\t') && index < ueIdx) { text++; index++; }
 erg = index;
 if (*text == '{') {
   lgkl += 1;
   index++;
   text++; 
   inmakro = 0;
 }
 else if (*text == '"') {
   daz += 1;
   index++;
   text++; 
   inmakro = 0;
 }
 else {
   AppendSign(new, '@');
   AppendSign(new, *text);
   index++;
   text++; 
   inmakro = 1;
 }
 while (index < ueIdx) {
   if (*text == '{') {
     if (lgkl >= 1 || daz >= 1) {  /* Klammer in String */
       AppendSign(new, *text);
     }
     text++;                       /* Klammer nach Zaun */
     index++;
     lgkl += 1;
     inmakro = 0;
   }
   else if (*text == '\n') {
     AppendSign(new, *text);
     text++;
     index++;
     while ((*text == ' ') || (*text == '\t')){
        text++;
	index++;
	}
     inmakro = 0;
   }
   else if (*text == '}') {
     if ((lgkl > 1) || (daz >= 1)) {
       AppendSign(new, *text);
     } 
     text++;
     index++;
     lgkl -= 1;
     inmakro = 0;
   }
   else if (*text == '"') {
     if (lgkl >= 1) {
       AppendSign(new, *text);
       text++;
       index++;
     } 
     else {
       text++;
       index++;
       if (daz == 0) daz++;
       else daz = 0;
     }
     inmakro = 0;
   }
   else if (*text == '#') {        /* Space vor/nach Konkatenation */
     if (lgkl < 1 && daz < 1) {
       if (text[index-1] != ' ') AppendSign(new, ' ');
       AppendSign(new, '@');       /* # -> @# */
       AppendSign(new, *text);
       if (text[index+1] != ' ') AppendSign(new, ' ');
     }
     else {                        /* Konkatenation in String */
       AppendSign(new, *text);
     }
     text++;
     index++;
     inmakro = 0;
   } 
   else if (*text == ',') {        /* Komma am Ende */
     if (lgkl < 1 && daz != 1) break;
     else {
       AppendSign(new, *text);
       text++;
       index++;
     }
     inmakro = 0;
   }
   else if (*text == ')') {        /* runde Klammer am Ende */
     if (lgkl < 1 && daz != 1) break;
     else {
       AppendSign(new, *text);
       text++;
       index++;
     }
     inmakro = 0;
   }
   else if (isalnum(*text)) {
     if (lgkl < 1 && daz < 1 && (inmakro==0)) {
       if (text[index-1] != ' ') AppendSign(new, ' ');
       AppendSign(new, '@');       /* makro -> @makro */
       AppendSign(new, *text);
       inmakro = 1;
     }
     else {                        /* Zeichen in String */
       AppendSign(new, *text);
     }
     text++;
     index++;
   } 
   else {                        /* sonstiges Zeichen in String */
     AppendSign(new, *text);
     text++;
     index++;
     inmakro = 0;
   } 
 }
 return erg;
  
}



static void PushSign(Snode **w, char a)
{
 Snode *hnode, *oldw;

 if (*w == NULL) {
   hnode = (Snode *)XtCalloc(1,sizeof(Snode));
   hnode->inh = a;
   hnode->slen = 1;
   hnode->next = NULL;
   *w = hnode;
 }
 else {
   oldw = *w; 
   hnode = (Snode *)XtCalloc(1,sizeof(Snode));
   hnode->inh = a;
   hnode->slen = oldw->slen + 1;
   hnode->next = oldw;
   *w = hnode;
}
}


static void AppendSign(Snode **w, char a)
{
 Snode *hnode, *oldw;
 int newslen;

 if (*w == NULL) {
   hnode = (Snode *)XtCalloc(1,sizeof(Snode));
   hnode->inh = a;
   hnode->slen = 1;
   hnode->next = NULL;
   *w = hnode;
 }
 else {
   oldw = *w; 
   newslen = 1;
   while (oldw->next != NULL) {
     newslen++; 
     oldw = oldw->next;
   }
   newslen++; 
   hnode = (Snode *)XtCalloc(1,sizeof(Snode));
   hnode->inh = a;
   hnode->slen = 1;
   hnode->next = NULL;
   oldw->next = hnode;
   oldw = *w; 
   oldw->slen = newslen;      /* echte Laenge nur im 1. El. */
}
}


static void FreeStack(Snode **s)
{
 Snode *h, *del;

 del = *s;
 while (del != NULL) {
   h = del->next;
   XtFree((char *)del);
   del = h;
 }
 *s = NULL;
} 


static void StackToString(Snode *s, char **text) 
{
  char *help;
  
  if (s==NULL)
     help = (char *)XtCalloc(1,1);
  else
     help = (char *)XtCalloc(1,s->slen+1);
  *text = help;
  while (s != NULL) {
    *help = s->inh; 
    s = s->next;
    help++;
  }
  *help = '\0';
  help--;
  while (*help == '\n') {    /* NL am Ende vom Wort loeschen */
    *help = '\0';
    help--;
  }
}



static void GetKey()
{
  StackToString(key, &card->mainkey);
  FreeStack(&key);
  err = dbtInsert(glbbp, card);
  err = dbtDeleteCard(&card);
}


static void GetFldNameCont()
{
  int found;
  FieldName i;
  
  if (helpFldName != NULL) {
    XtFree((char *)helpFldName);
    helpFldName = NULL;
  }
  StackToString(fldname, &helpFldName);
  strlower(helpFldName); 
  SkipSpace(uebergabe, &fldcont);
  found = 0;
  for (i=0;i<MAX_FIELDS && (!found);i++) {
      if (strcmp(helpFldName, glbFldToName(i)) == 0) {
         if (isstandardfield(i, cardtype))
            StackToString(fldcont, &card->field[i]);
         else {
            err = dbtMakeUserFld(&helpufield);
            Scalloc(&helpufield->fldName, helpFldName);
            StackToString(fldcont, &helpufield->fldData); 
            err = dbtAppendUserFld(&card->ufield, helpufield);
            }
         found = 1; 
         break;
      }
  }
  if (!found){
     err = dbtMakeUserFld(&helpufield);
     Scalloc(&helpufield->fldName, helpFldName);
     StackToString(fldcont, &helpufield->fldData); 
     err = dbtAppendUserFld(&card->ufield, helpufield);
     }
  FreeStack(&fldname);
  FreeStack(&fldcont);
}

static void SecStrcat(int maxlen, char *str1, char *str2)
{
 if (strlen(str1)+strlen(str2) < maxlen)
    strcat(str1, str2);
}

static int SetInputFile(char *file)
{
 char *infilename; 
    
 if (file)
 {
  infilename = file;

  if (access(infilename, F_OK) != 0)
     return BIF_ENOTEXISTS;

  yyin = fopen(infilename, "r" );

  if ( yyin == NULL ) {
    return BIF_EOPEN;  
  }
  return BIF_OK;  
 }
 else
 {
   yyin = stdin;
   infilename = "<stdin>";
   return BIF_OK;  
 }
}


/*********************************************
 * BibTeX-Datei lesen                        *
 *********************************************/
Errcode bifFileRead(BibPtr bp)
{
  int erg;

  yynline = 1; 
  yynflexcalls = 0;
  hlpQuitHelpError(7);

  sprintf(errorstr, anfhelpstr, "KEY", "OFFSET", "LINE");
#ifdef NO_TEMPNAM
  bp->tempfile = (char *)tmpnam(NULL);
  bp->macrofile = (char *)tmpnam(NULL);
#else
  bp->tempfile = (char *)tempnam(NULL, NULL);
  bp->macrofile = (char *)tempnam(NULL, NULL);
#endif
  tempDatei = fopen(bp->macrofile, "w" );

  if ((erg = SetInputFile(bp->filepath)) == BIF_ENOTEXISTS){
     glbbp = bp;
     fclose(tempDatei);
     return BIF_OK;
     }
  
  if ((erg = glbContIllegalChar(bp->filepath)) != 1) return ERR_NOBIB;
  glbbp = bp; 
  erg = yyparse();
  fclose(tempDatei);
  uebergabe[0] = '\0';
  sprintf(errstr, endhelpstr, bp->filepath, yynerrs);
  SecStrcat(MAX_ERRORSTRLEN, errorstr, errstr);
  ueIdx = 0;
  if (erg == 0) {
    if (yyin) fclose(yyin);
    erg = yynline;
    if (yynerrs > 0)
       return yynline-1;
    else
       return BIF_OK;
  }
  else {
    erg = -yynline;
    yy_init = 1;
    if (yyin) fclose(yyin);
    FreeStack(&key);
    FreeStack(&fldname);
    FreeStack(&fldcont);
    return (Errcode)erg;
  }
}



Errcode bifFileWrite(BibPtr bp)
{
 char sysStr[2*MAX_FILEPATHLEN];
 CardListNode *cl = NULL;
 char wcKey[] = ".";
 CardData *wcCard;
 Errcode status;

 if (bp->macrofile!=NULL){
    sprintf(sysStr, "cp  %s %s", bp->macrofile, bp->tempfile);
    system(sysStr);
    tempDatei = fopen(bp->tempfile, "r+");
    }
 else
    {tempDatei = fopen(bp->tempfile, "w+");
     }

 if (tempDatei == NULL) return BIF_EWRITE;

   /* build list with wildcard search */
   if ((status = (int)dbtMakeCard(&wcCard)) != OK) {
      guwError(status);
   }
   wcCard->cardtype = (int)regexpr;
   wcCard->mainkey = glbNewString(".");
   if ((status = dbtSearchList(bp->treeIdx, wcCard, &cl, bp->sortedby)) != OK) {
      guwError(status); 
      return(status);
   }

 while (cl != NULL) {
   WriteRecToFile(cl->data, tempDatei);
   cl = cl->next;
 } 

 fclose(tempDatei);
 sprintf(sysStr, "cp  %s %s", bp->tempfile, bp->filepath);
 system(sysStr);
 return BIF_OK;
}


Errcode bifFileListWrite(BibPtr bp, CardListNode *list, String fname)
{
 CardListNode *hlist;
 Errcode erg;
 char sysStr[2*MAX_FILEPATHLEN];
 
 if (bp->macrofile!=NULL){
    sprintf(sysStr, "cp  %s %s", bp->macrofile, fname);
    system(sysStr);
    tempDatei = fopen(fname, "r+");
    }
 else
    {tempDatei = fopen(fname, "w+");
     }

 if (tempDatei == NULL) return BIF_EWRITE;
 hlist = list;
 while (hlist != NULL) {
   WriteRecToFile(hlist->data, tempDatei);
   hlist = hlist->next;
 } 
 fclose(tempDatei);
 return BIF_OK;
}


static long WriteLineToFile(FILE *datei, char *feld, char *inh)
{
  int inmakro = 0;    /* weder Makro, noch String */
  int instring = 0;
  int isempty = 1;
  int zaehler;
  long pos; 
  char *blank, *blankptr, *zeichen; 
  
  blank = (char *)XtMalloc(100);
  blankptr = blank;

  for (zaehler = 0; zaehler < fld_indent; zaehler++)
     fprintf(datei," ");
  fprintf(datei,"%s", feld);
  zaehler += strlen(feld);
  for (;zaehler < cont_indent - 3; zaehler++)
     fprintf(datei," ");
  fprintf(datei," = ");
  zeichen = inh;
  while (*zeichen!='\0'){
   switch (*zeichen){
     case ' ':
     case '\t':
	  if (instring)
	     *blankptr++ = *zeichen;
          else if (inmakro){
	     fprintf(datei, " ");
	     inmakro = 0;
	     }
          break;
     case '\n':
	  if (instring){
	     *blankptr++ = *zeichen;
	     for (zaehler = 0; zaehler < newline_indent; zaehler++)
	        *blankptr++ = ' ';
             }
          else if (inmakro){
	     fprintf(datei, " ");
	     inmakro = 0;
	     }
          break;
     case '@':
          if (inmakro)
	     fprintf(datei, " ");
          else if (instring){
	     fprintf(datei, "} ");
	     inmakro = 1;
	     instring = 0;
	     }
          else {
	     inmakro = 1;
	     instring = 0;
	     }
          break;
     case '#':
          if (isempty && inmakro) {
	     fprintf(datei, "{ } #");
             blankptr = blank;
	     *blankptr = '\0';
	     inmakro = 0;
	     }
          else if (inmakro){
	     fprintf(datei, "# ");
             blankptr = blank;
	     *blankptr = '\0';
	     inmakro = 0;
	     }
          else if (instring) 
	     fprintf(datei, "#");
          else {
	     fprintf(datei, "{#");
	     instring = 1;
	     }
          break;
      default:
          isempty = 0;
          if (inmakro)
	     fprintf(datei, "%c", *zeichen);
          else if (instring){
	     *blankptr++ = '\0';
	     fprintf(datei, "%s", blank);
	     blankptr = blank;
	     fprintf(datei, "%c", *zeichen);
	     }
          else{
	     fprintf(datei, "{%c", *zeichen);
	     instring = 1;
	     inmakro = 0;
	     }
          break;
      } /* case */
  zeichen++;
  } /* while */
	   
  if ((isempty==1) && (inmakro==0) && (instring==0))
    fprintf(datei,"{ }");    
  else if (instring) {
    fprintf(datei,"}");    
  }
        
  pos = ftell(datei);
  fprintf(datei,",\n");
  XtFree(blank);
  return pos;
}

static void WriteRecToFile(CardData *card, FILE *datei)
{
 UserFld *h;
 String newType;
 long pos;
 FieldName i;

 fseek(datei, 0L, SEEK_END); 
 fprintf(datei,"\n");
 pos = ftell(datei);
 newType = glbNewString(card->cardtypestr);
 fprintf(datei,"@%s{%s",newType, card->mainkey);
 XtFree(newType);
 pos = ftell(datei);
 fprintf(datei,",\n");

 for (i=0; i<MAX_FIELDS; i++) {
    if (!StringIsPeteEmpty(card->field[i]))
       pos = WriteLineToFile(datei, glbFldToUpName(i), card->field[i]);
 }
 h = card->ufield; 
 while (h) {
   if (!StringIsPeteEmpty(h->fldData)) 
      pos = WriteLineToFile(datei,h->fldName,h->fldData);    
   h = h->next;
 }   
 fseek(datei, pos, SEEK_SET);
 fprintf(datei,"\n}\n\n");
}



static int StringIsPeteEmpty(char *text)
{
 if (text == NULL || *text == '\0') return 1;
 return 0;
}



yyerror(char *s)
{

 fputs(s, stderr);
 putc('\n', stderr);
}

#ifdef BIFMAIN

int main(int argc, char *argv[])
{
 Bib bp;
 int erg, b1, i;
 Errcode err;

#ifdef YYDEBUG
       extern int yydebug;

       yydebug = 1;
#endif

 strcpy(bp.filepath, argv[1]);
 dbtGetFreeTreeIdx(&b1);
 bp.treeIdx = b1;
 err = bifFileRead(&bp);
 err = bifFileWrite(&bp);
}

#endif
