/*
FILE:     ndb_cifparse_iolib.C
*/
/*
VERSION:  3.101
*/
/*
DATE:     8/27/2004
*/
/*
  Comments and Questions to: sw-help@rcsb.rutgers.edu
*/
/*
COPYRIGHT 1999-2004 Rutgers - The State University of New Jersey

This software is provided WITHOUT WARRANTY OF MERCHANTABILITY OR
FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTY, EXPRESS OR
IMPLIED.  RUTGERS MAKE NO REPRESENTATION OR WARRANTY THAT THE
SOFTWARE WILL NOT INFRINGE ANY PATENT, COPYRIGHT OR OTHER
PROPRIETARY RIGHT.

The user of this software shall indemnify, hold harmless and defend
Rutgers, its governors, trustees, officers, employees, students,
agents and the authors against any and all claims, suits,
losses, liabilities, damages, costs, fees, and expenses including
reasonable attorneys' fees resulting from or arising out of the
use of this software.  This indemnification shall include, but is
not limited to, any and all claims alleging products liability.
*/
/*
               PDB SOFTWARE LICENSE AGREEMENT

BY CLICKING THE ACCEPTANCE BUTTON OR INSTALLING OR USING 
THIS "SOFTWARE, THE INDIVIDUAL OR ENTITY LICENSING THE  
SOFTWARE ("LICENSEE") IS CONSENTING TO BE BOUND BY AND IS 
BECOMING A PARTY TO THIS AGREEMENT.  IF LICENSEE DOES NOT 
AGREE TO ALL OF THE TERMS OF THIS AGREEMENT
THE LICENSEE MUST NOT INSTALL OR USE THE SOFTWARE.

1. LICENSE AGREEMENT

This is a license between you ("Licensee") and the Protein Data Bank (PDB) 
at Rutgers, The State University of New Jersey (hereafter referred to 
as "RUTGERS").   The software is owned by RUTGERS and protected by 
copyright laws, and some elements are protected by laws governing 
trademarks, trade dress and trade secrets, and may be protected by 
patent laws. 

2. LICENSE GRANT

RUTGERS grants you, and you hereby accept, non-exclusive, royalty-free 
perpetual license to install, use, modify, prepare derivative works, 
incorporate into other computer software, and distribute in binary 
and source code format, or any derivative work thereof, together with 
any associated media, printed materials, and on-line or electronic 
documentation (if any) provided by RUTGERS (collectively, the "SOFTWARE"), 
subject to the following terms and conditions: (i) any distribution 
of the SOFTWARE shall bind the receiver to the terms and conditions 
of this Agreement; (ii) any distribution of the SOFTWARE in modified 
form shall clearly state that the SOFTWARE has been modified from 
the version originally obtained from RUTGERS.  

2. COPYRIGHT; RETENTION OF RIGHTS.  

The above license grant is conditioned on the following: (i) you must 
reproduce all copyright notices and other proprietary notices on any 
copies of the SOFTWARE and you must not remove such notices; (ii) in 
the event you compile the SOFTWARE, you will include the copyright 
notice with the binary in such a manner as to allow it to be easily 
viewable; (iii) if you incorporate the SOFTWARE into other code, you 
must provide notice that the code contains the SOFTWARE and include 
a copy of the copyright notices and other proprietary notices.  All 
copies of the SOFTWARE shall be subject to the terms of this Agreement.  

3. NO MAINTENANCE OR SUPPORT; TREATMENT OF ENHANCEMENTS 

RUTGERS is under no obligation whatsoever to: (i) provide maintenance 
or support for the SOFTWARE; or (ii) to notify you of bug fixes, patches, 
or upgrades to the features, functionality or performance of the 
SOFTWARE ("Enhancements") (if any), whether developed by RUTGERS 
or third parties.  If, in its sole discretion, RUTGERS makes an 
Enhancement available to you and RUTGERS does not separately enter 
into a written license agreement with you relating to such bug fix, 
patch or upgrade, then it shall be deemed incorporated into the SOFTWARE 
and subject to this Agreement. You are under no obligation whatsoever 
to provide any Enhancements to RUTGERS or the public that you may 
develop over time; however, if you choose to provide your Enhancements 
to RUTGERS, or if you choose to otherwise publish or distribute your 
Enhancements, in source code form without contemporaneously requiring 
end users or RUTGERS to enter into a separate written license agreement 
for such Enhancements, then you hereby grant RUTGERS a non-exclusive,
royalty-free perpetual license to install, use, modify, prepare
derivative works, incorporate into the SOFTWARE or other computer
software, distribute, and sublicense your Enhancements or derivative
works thereof, in binary and source code form.

4. FEES.  There is no license fee for the SOFTWARE.  If Licensee
wishes to receive the SOFTWARE on media, there may be a small charge
for the media and for shipping and handling.  Licensee is
responsible for any and all taxes.

5. TERMINATION.  Without prejudice to any other rights, Licensor
may terminate this Agreement if Licensee breaches any of its terms
and conditions.  Upon termination, Licensee shall destroy all
copies of the SOFTWARE.

6. PROPRIETARY RIGHTS.  Title, ownership rights, and intellectual
property rights in the Product shall remain with RUTGERS.  Licensee 
acknowledges such ownership and intellectual property rights and will 
not take any action to jeopardize, limit or interfere in any manner 
with RUTGERS' ownership of or rights with respect to the SOFTWARE.  
The SOFTWARE is protected by copyright and other intellectual 
property laws and by international treaties.  Title and related 
rights in the content accessed through the SOFTWARE is the property 
of the applicable content owner and is protected by applicable law.  
The license granted under this Agreement gives Licensee no rights to such
content.

7. DISCLAIMER OF WARRANTY.  THE SOFTWARE IS PROVIDED FREE OF 
CHARGE, AND, THEREFORE, ON AN "AS IS" BASIS, WITHOUT WARRANTY OF 
ANY KIND, INCLUDING WITHOUT LIMITATION THE WARRANTIES THAT IT 
IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE 
OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND 
PERFORMANCE OF THE SOFTWARE IS BORNE BY LICENSEE.  SHOULD THE 
SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, THE LICENSEE AND NOT 
LICENSOR ASSUMES THE ENTIRE COST OF ANY SERVICE AND REPAIR.  
THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF 
THIS AGREEMENT.  NO USE OF THE PRODUCT IS AUTHORIZED HEREUNDER 
EXCEPT UNDER THIS DISCLAIMER.

8. LIMITATION OF LIABILITY.  TO THE MAXIMUM EXTENT PERMITTED BY
APPLICABLE LAW,  IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY 
INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 
OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, INCLUDING, 
WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK 
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL 
OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF ADVISED OF THE
POSSIBILITY THEREOF. 
*/
/* 
  PURPOSE:       This collection of routines provides a simple interface 
                 to the DDL 2.1 compliant CIF files.
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "ndb_cifparse.h"

void ndb_cif_print_item_name_tab(FILE *fp, const char *itemName, int *linePos);
static char null_char[2] = "?"; /* The character output for null data values */

char ndb_cif_set_null_char(char new_null)
     /* Change the CIF character identifying a NULL data value .
      */
{
  char old_null;
  old_null = null_char[0];
  null_char[0] = new_null;
  return old_null;
}

int cifp_parse();
int ddl_parse();
int ddl_format_parse();
int dic_parse();
int dic_format_parse();


int ndb_cif_read_file(CifHandle *cf,FILE *fp)
{
  extern CifHandle cif_Cif;
  extern FILE *cifp_in;
  extern int cif_NDBlineNo;
  extern char  cif_BString[];

  
  /* variables from parser */
  extern int  *cif_fieldList;
  extern char *cif_pBufValue;
  extern char  BString[];
  
  /* variables from lexer */
  extern int   cif_NDBmaxValueLength;
  extern char  *cif_tBuf;
  extern int   cif_tBufLen, cif_tBufFree, cif_tBufChunkSize;
  extern int   cif_isText;
  extern int   cif_duz;


  cif_Cif=*cf;
  cif_NDBlineNo=1;
  
  cif_fieldList = NULL;
  cif_pBufValue=NULL;
  strcpy(cif_BString,"");
  
  cif_NDBmaxValueLength=80;
  cif_tBuf=NULL;
  cif_tBufLen=0, cif_tBufFree=0, cif_tBufChunkSize=256;
  cif_isText = FALSE;
  cif_duz=0;
  
  if (fp == NULL ) {
    return 0;
  }
  cifp_in = fp;
  rewind(cifp_in);
  if (cifp_parse() != 0) { /* YYACCEPT */ 
	 *cf=cif_Cif;
    ndb_cif_rewind_datablock(cf);
    if (cif_tBuf) free(cif_tBuf);
    if (cif_fieldList) free(cif_fieldList);
    return FALSE;
  }
  *cf=cif_Cif;
  if (cif_tBuf) free(cif_tBuf);
  if (cif_fieldList) free(cif_fieldList);
  return (*cf).curDatablock+1;
}


int ndb_cif_read_ddl(CifHandle *cf,FILE *fp)
{
  extern CifHandle ddl_Cif;
  extern FILE *ddl_in;
  extern int ddl_NDBlineNo;

  /* variables from parser */
  extern int  *ddl_fieldList, *ddl_fieldList2;
  extern char *ddl_pBufValue;
  extern char  ddl_BString[];
  extern int *ddl_newRow;
  
  /* variables from lexer */
  extern int   ddl_NDBmaxValueLength;
  extern char  *ddl_tBuf;
  extern int   ddl_tBufLen, ddl_tBufFree, ddl_tBufChunkSize;
  extern int   ddl_isText;
  extern int   ddl_duz;
  extern int   ddl_isSave;

  ddl_Cif=*cf;
  ddl_NDBlineNo=1;
  ddl_isSave=0;
  
  ddl_fieldList = NULL;
  ddl_pBufValue=NULL;
  strcpy(ddl_BString,"");
  ddl_newRow = NULL;
  ddl_fieldList2 = NULL;

  ddl_NDBmaxValueLength=80;
  ddl_tBuf=NULL;
  ddl_tBufLen=0, ddl_tBufFree=0, ddl_tBufChunkSize=256;
  ddl_isText = FALSE;
  ddl_duz=0;

  if (fp == NULL ) {
    return 0;
  }
  ddl_in = fp;
  rewind(ddl_in);
  if (ddl_parse() != 0) { /* YYACCEPT */ 
    *cf=ddl_Cif;
    ndb_cif_rewind_datablock(cf);
    if (ddl_tBuf) free(ddl_tBuf);
    if (ddl_fieldList) free(ddl_fieldList);
    if (ddl_fieldList2) free(ddl_fieldList2);
    if (ddl_newRow) free(ddl_newRow);
    return FALSE;
  }
  *cf=ddl_Cif;
  if (ddl_tBuf) free(ddl_tBuf);
  if (ddl_fieldList) free(ddl_fieldList);
  if (ddl_fieldList2) free(ddl_fieldList2);
  if (ddl_newRow) free(ddl_newRow);
  return (*cf).curDatablock+1;
}


int ndb_cif_read_ddl_with_format(CifHandle *cf,FILE *fp,CifHandle *format)
{
  extern CifHandle  ddl_f_Cif;
  extern FILE *ddl_format_in;
  extern int  ddl_f_NDBlineNo;
  extern CifHandle  ddl_f_form;

  /* variables from parser */
  extern int  * ddl_f_fieldList, * ddl_f_fieldList2;
  extern char * ddl_f_pBufValue;
  extern int  * ddl_f_newRow;
  extern char   ddl_f_BString[];
  
  /* variables from lexer */
  extern int    ddl_f_NDBmaxValueLength;
  extern char  * ddl_f_tBuf;
  extern int    ddl_f_tBufLen,  ddl_f_tBufFree,  ddl_f_tBufChunkSize;
  extern int    ddl_f_isText;
  extern int    ddl_f_duz;
  extern int    ddl_f_isSave;

   ddl_f_Cif=*cf;
   ddl_f_NDBlineNo=1;
   ddl_f_isSave = 0;
  
   ddl_f_fieldList = NULL;
   ddl_f_fieldList2 = NULL;
   ddl_f_pBufValue=NULL;
  strcpy( ddl_f_BString,"");
   ddl_f_newRow = NULL;

   ddl_f_NDBmaxValueLength=80;
   ddl_f_tBuf=NULL;
   ddl_f_tBufLen=0,  ddl_f_tBufFree=0,  ddl_f_tBufChunkSize=256;
   ddl_f_isText = FALSE;
   ddl_f_duz=0;

   ddl_f_form=*format;
  
  if (fp == NULL ) {
    return 0;
  }
  ddl_format_in = fp;
  rewind(ddl_format_in);
  if (ddl_format_parse() != 0) { /* YYACCEPT */ 
	 *cf= ddl_f_Cif;
    ndb_cif_rewind_datablock(cf);
    if (ddl_f_tBuf) free(ddl_f_tBuf);
    if (ddl_f_fieldList) free(ddl_f_fieldList);
    if (ddl_f_fieldList2) free(ddl_f_fieldList2);
    if (ddl_f_newRow) free(ddl_f_newRow);
    return FALSE;
  }
  *cf= ddl_f_Cif;
  *format=ddl_f_form;
  if (ddl_f_tBuf) free(ddl_f_tBuf);
  if (ddl_f_fieldList) free(ddl_f_fieldList);
  if (ddl_f_fieldList2) free(ddl_f_fieldList2);
  if (ddl_f_newRow) free(ddl_f_newRow);
  return (*cf).curDatablock+1;
}


int ndb_cif_read_dic(CifHandle *cf,FILE *fp,CifHandle *ddlin,FILE *fp_ddl)
{
  extern CifHandle dic_Cif;
  extern CifHandle dic_ddl;
  extern FILE *dic_in;
  extern int dic_NDBlineNo;
  FILE *fp1;

  /* variables from parser */
  extern int  *dic_fieldList , *dic_fieldList2;
  extern int  *dic_newRow;
  extern char *dic_pBufValue;
  extern char  dic_BString[];
  extern char *dic_save;
  
  /* variables from lexer */
  extern int   dic_NDBmaxValueLength;
  extern char  *dic_tBuf;
  extern int   dic_tBufLen, dic_tBufFree, dic_tBufChunkSize;
  extern int   dic_isText;
  extern int   dic_duz;
  extern int   dic_isSave;
  
  dic_ddl=*ddlin;
  if (fp == NULL ) {
    return 0;
  }
  ndb_cif_read_ddl(&dic_ddl,fp_ddl);
  dic_NDBlineNo=1;
  dic_Cif=*cf;
  dic_in = fp;
  dic_fieldList = NULL;
  dic_fieldList2 = NULL;
  dic_newRow = NULL;
  dic_save = NULL;
  dic_pBufValue=NULL;
  strcpy(dic_BString,"");
  
  dic_NDBmaxValueLength=80;
  dic_tBuf=NULL;
  dic_tBufLen=0, dic_tBufFree=0, dic_tBufChunkSize=256;
  dic_isText = FALSE;
  dic_duz=0;
  
  rewind(dic_in);
  if (dic_parse() != 0) { /* YYACCEPT */ 
	 *cf=dic_Cif;
    ndb_cif_rewind_datablock(cf);
    if (dic_tBuf) free(dic_tBuf);
    if (dic_fieldList) free(dic_fieldList);
    if (dic_fieldList2) free(dic_fieldList2);
    if (dic_newRow) free(dic_newRow);
    return FALSE;
  }
  *cf=dic_Cif;
  *ddlin=dic_ddl;
  if (dic_tBuf) free(dic_tBuf);
  if (dic_fieldList) free(dic_fieldList);
  if (dic_fieldList2) free(dic_fieldList2);
  if (dic_newRow) free(dic_newRow);
  return (*cf).curDatablock+1;
}

int ndb_cif_read_dic_with_format(CifHandle *cf,FILE *fp_cf,CifHandle *ddlin,FILE *fp_ddl,CifHandle *format)
{
  extern CifHandle dic_f_Cif;
  extern CifHandle dic_f_ddl;
  extern FILE *dic_format_in;
  extern int dic_f_NDBlineNo;
  extern CifHandle dic_f_form;

  /* variables from parser */
  extern int  *dic_f_fieldList , *dic_f_fieldList2;
  extern int  *dic_f_newRow;
  extern char *dic_f_pBufValue;
  extern char  dic_f_BString[];
  extern char *dic_f_save;
  
  /* variables from lexer */
  extern int   dic_f_NDBmaxValueLength;
  extern char  *dic_f_tBuf;
  extern int   dic_f_tBufLen, dic_f_tBufFree, dic_f_tBufChunkSize;
  extern int   dic_f_isText;
  extern int   dic_f_duz;
  extern int   dic_f_isSave;
  
  dic_f_ddl=*ddlin;
  
  if (fp_cf == NULL ) {
    return 0;
  }
  ndb_cif_read_ddl(&dic_f_ddl,fp_ddl);

  dic_f_NDBlineNo=1;
  dic_f_Cif=*cf;
  dic_f_form=*format;
  dic_format_in = fp_cf;

  dic_f_fieldList = NULL;
  dic_f_fieldList2 = NULL;
  dic_f_newRow = NULL;
  dic_f_save = NULL;
  dic_f_pBufValue=NULL;
  strcpy(dic_f_BString,"");
  
  dic_f_NDBmaxValueLength=80;
  dic_f_tBuf=NULL;
  dic_f_tBufLen=0, dic_f_tBufFree=0, dic_f_tBufChunkSize=256;
  dic_f_isText = FALSE;
  dic_f_duz=0;
  
  rewind(dic_format_in);
  if (dic_format_parse() != 0) { /* YYACCEPT */ 
	 *cf=dic_f_Cif;
    ndb_cif_rewind_datablock(cf);
    if (dic_f_tBuf) free(dic_f_tBuf);
    if (dic_f_fieldList) free(dic_f_fieldList);
    if (dic_f_fieldList2) free(dic_f_fieldList2);
    if (dic_f_newRow) free(dic_f_newRow);
    return FALSE;
  }
  *cf=dic_f_Cif;
  *format=dic_f_form;
  *ddlin=dic_f_ddl;
  if (dic_f_tBuf) free(dic_f_tBuf);
  if (dic_f_fieldList) free(dic_f_fieldList);
  if (dic_f_fieldList2) free(dic_f_fieldList2);
  if (dic_f_newRow) free(dic_f_newRow);
  return (*cf).curDatablock+1;
}



int ndb_cif_write_file(CifHandle *cf,FILE *fp)
{
  int i, datablockId, categoryId, rowId, linePos, numColumn, numRow, ilen, allocBuf;
  char *itemValue=NULL, itemName[MxNameLen], datablockName[MxNameLen];

  /* Open input and output files */
  if (fp == NULL ) {
    return 0;
  }
  allocBuf=5000;
  datablockId = ndb_cif_rewind_datablock(cf);
  itemValue=(char *)calloc(allocBuf+1,sizeof(char));

  do {
    ndb_cif_current_datablock_name(cf,datablockName);
    ndb_log_message(NDB_MSG_DEBUG4, "Writing data block %s[%d of %d]\n",
		    datablockName,
		    ndb_cif_current_datablock(cf),
		    ndb_cif_count_datablock(cf));
    fprintf(fp, "data_%s\n", datablockName);
    do {
      categoryId = ndb_cif_current_category(cf);
      numColumn = ndb_cif_count_column(cf);
      numRow = ndb_cif_count_row(cf);
      fprintf(fp, "#\n");
      if (numRow <=1) {
	for (i=0; i< numColumn; i++) {
	  ndb_cif_get_item_name(cf,i+1, itemName);
	  ndb_cif_print_item_name(fp, itemName, &linePos);
	  ilen = ndb_cif_get_item_value_length(cf,i+1);
	  if (ilen > allocBuf) {
	     allocBuf+=ilen;
	     itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
	  }
	  ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
	  ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
	  if (linePos != 0) fprintf(fp, "\n");
	}
      }
      else {
	fprintf(fp, "loop_\n");
	for (i=0; i< numColumn; i++) {
	  ndb_cif_get_item_name(cf,i+1, itemName);
	  ndb_cif_print_item_name(fp, itemName, &linePos);
	  fprintf(fp, "\n");
	}
	do {
	  linePos = 0;
	  for (i=0; i< numColumn; i++) {
	    ilen = ndb_cif_get_item_value_length(cf,i+1);
	    if (ilen > allocBuf) {
	      allocBuf+=ilen;
	      itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
	    }
	    ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
	    ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
	  }
	  if (linePos != 0) fprintf(fp, "\n");
	  rowId = ndb_cif_next_row(cf);
	}  while (rowId);
      }
      fflush(fp);
      categoryId = ndb_cif_next_category(cf);
    } while (categoryId);
    fprintf(fp, "#\n");
    fflush(fp);
    datablockId = ndb_cif_next_datablock(cf);
  } while (datablockId);
  free(itemValue);
  ndb_cif_rewind_datablock(cf);
  return(1);
}

int ndb_cif_write_ddl_by_format(CifHandle *cf,FILE *fp,CifHandle*format)
{
  int i,j,m,k,n,p,r, IndexC,IndexI,Index1,Index2,Index3;
  int numColumn, numRow,numRowI,numRowC,numRow1,numRow2,numRow3;
  int datablockId, categoryId, rowId, linePos, ilen;
  char *itemValue=NULL,*itemValue1=NULL,*itemValue2=NULL,*itemValue3=NULL;
  char *itemValueC=NULL, *itemValueI=NULL;
  int  allocBuf, allocBuf1, allocBuf2, allocBuf3, allocBufC, allocBufI;
  char itemName[MxNameLen], datablockName[MxNameLen];
  char categoryName[MxNameLen];

  /* Open input and output files */
  if (fp == NULL ) {
    return 0;
  }
  allocBuf=5000;
  allocBuf1=5000;
  allocBuf2=5000;
  allocBuf3=5000;
  allocBufC=5000;
  allocBufI=5000;
  ndb_cif_rewind_datablock(format);
  datablockId = ndb_cif_rewind_datablock(cf);
  itemValue=(char *)calloc(allocBuf+1,sizeof(char));
  itemValue1=(char *)calloc(allocBuf1+1,sizeof(char));
  itemValue2=(char *)calloc(allocBuf2+1,sizeof(char));
  itemValue3=(char *)calloc(allocBuf3+1,sizeof(char));
  itemValueC=(char *)calloc(allocBufC+1,sizeof(char));
  itemValueI=(char *)calloc(allocBufI+1,sizeof(char));

  do {
    ndb_cif_current_datablock_name(cf,datablockName);
    ndb_log_message(NDB_MSG_DEBUG4, "Writing data block %s[%d of %d]\n",
						  datablockName,
						  ndb_cif_current_datablock(cf),
						  ndb_cif_count_datablock(cf));
    fprintf(fp, "data_%s\n", datablockName);
    ndb_cif_move_category_by_name(format,datablockName,"data");
    numRow1=ndb_cif_count_row(format);
    for (j=0;j<numRow1;j++) {;
    ilen = ndb_cif_get_item_value_length(format,1);
    if (ilen > allocBuf) {
      allocBuf+=ilen;
      itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
    }
    ndb_cif_get_item_value(format,1,itemValue,allocBuf);
    ndb_cif_move_category_by_name(cf,datablockName,itemValue);
    categoryId = ndb_cif_current_category(cf);
    numColumn = ndb_cif_count_column(cf);
    numRow = ndb_cif_count_row(cf);
    fprintf(fp, "#\n");
    if (numRow <=1) {
      for (i=0; i< numColumn; i++) {
		  ndb_cif_get_item_name(cf,i+1, itemName);
		  ndb_cif_print_item_name(fp, itemName, &linePos);
		  ilen = ndb_cif_get_item_value_length(cf,i+1);
		  if (ilen > allocBuf) {
			 allocBuf+=ilen;
			 itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
		  }
		  ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
		  ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
		  if (linePos != 0) fprintf(fp, "\n");
      }
    }
    else {
      fprintf(fp, "loop_\n");
      for (i=0; i< numColumn; i++) {
		  ndb_cif_get_item_name(cf,i+1, itemName);
		  ndb_cif_print_item_name(fp, itemName, &linePos);
		  fprintf(fp, "\n");
      }
      do {
		  linePos = 0;
		  for (i=0; i< numColumn; i++) {
			 ilen = ndb_cif_get_item_value_length(cf,i+1);
			 if (ilen > allocBuf) {
				allocBuf+=ilen;
				itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
			 }
			 ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
			 ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
		  }
		  if (linePos != 0) fprintf(fp, "\n");
		  rowId = ndb_cif_next_row(cf);
      }  while (rowId);
    }
    ndb_cif_next_row(format);
    }
    ndb_cif_move_category_by_name(cf,datablockName,"item");
    numRowI=ndb_cif_count_row(cf);
    Index1=ndb_cif_get_column_id(cf,datablockName,"item","name");
    Index2=ndb_cif_get_column_id(cf,datablockName,"item","category_id");
    Index3=ndb_cif_get_column_id(cf,datablockName,"item","mandatory_code");
    
    ndb_cif_move_category_by_name(cf,datablockName,"category");
    numRowC=ndb_cif_count_row(cf);
    IndexC=ndb_cif_get_column_id(cf,datablockName,"category","id");
    
    ndb_cif_move_category_by_name(format,datablockName,"category");
    numRow1=ndb_cif_count_row(format);
    
    /*****          write save frame for category          *****/
    
    for (i=0;i<numRowC;i++) {
      ilen = ndb_cif_get_item_value_length(cf,IndexC);
      if (ilen > allocBufC) {
		  allocBufC+=ilen;
		  itemValueC = (char *)  realloc(itemValueC, sizeof(char) * (allocBufC+1));
      } 
      ndb_cif_get_item_value(cf,IndexC,itemValueC,allocBufC);
      fprintf(fp, "save_%s\n", itemValueC);
      
      for (k=0;k<numRow1;k++) {
		  ilen = ndb_cif_get_item_value_length(format,1);
		  if (ilen > allocBuf) {
			 allocBuf+=ilen;
			 itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
		  }
		  ndb_cif_get_item_value(format,1,itemValue,allocBuf);
		  ndb_cif_move_category_by_name(cf,datablockName,itemValue);
		  
		  /* now I have to find item with imlicit mandatory code in table  */
		  /*  item in ddl then, looking for all data in appropriate table  */
		  /* where the item isequal  to category.id                        */
		  
		  if (strcmp(itemValue,"category")!=0) {
			 ndb_cif_move_category_by_name(cf,datablockName,"item");
			 m=ndb_cif_item_row_1_key(cf,Index2,itemValue);
			 ilen = ndb_cif_get_item_value_length(cf,Index2);
			 if (ilen > allocBuf2) {
				allocBuf2+=ilen;
				itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
			 }
			 ndb_cif_get_item_value(cf,Index2,itemValue2,allocBuf2);
			 ilen = ndb_cif_get_item_value_length(cf,Index3);
			 if (ilen > allocBuf3) {
				allocBuf3+=ilen;
				itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
			 }
			 ndb_cif_get_item_value(cf,Index3,itemValue3,allocBuf3);
			 if (m!=0){
				n=m;
				while ((n<numRowI)&&( strcmp(itemValue2,itemValue)!=0 ||strcmp(itemValue3,"implicit")!=0)) {
				  ndb_cif_next_row(cf);
				  ilen = ndb_cif_get_item_value_length(cf,Index2);
				  if (ilen > allocBuf2) {
					 allocBuf2+=ilen;
					 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
	      }
				  ndb_cif_get_item_value(cf,Index2,itemValue2,allocBuf2);
				  ilen = ndb_cif_get_item_value_length(cf,Index3);
				  if (ilen > allocBuf3) {
					 allocBuf3+=ilen;
					 itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
				  }
				  ndb_cif_get_item_value(cf,Index3,itemValue3,allocBuf3);
	      n++;
				}
				if (n<numRowI) {
				  ilen = ndb_cif_get_item_value_length(cf,Index1);
				  if (ilen > allocBuf1) {
					 allocBuf1+=ilen;
					 itemValue1 = (char *) realloc(itemValue1, sizeof(char) * (allocBuf1+1));
				  }
				  ndb_cif_get_item_value(cf,Index1,itemValue1,allocBuf1);
				  ndb_cif_move_category_by_name(cf,datablockName,itemValue2);
				  ndb_cif_get_item_keyword_from_item_name(cf,itemName,itemValue1);
				  IndexI=ndb_cif_get_column_id(cf,datablockName,itemValue2,itemName);
				  n=ndb_cif_item_row_1_key(cf,IndexI,itemValueC);
				  if (n!=0) {
					 p=0;
					 ilen = ndb_cif_get_item_value_length(cf,IndexI);
					 if (ilen > allocBuf2) {
						allocBuf2+=ilen;
						itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
					 }
					 p=ndb_cif_next_row(cf);
					 ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
					 while (STRCMP(itemValue2,itemValueC)!=0 && p!=0) {
						p=ndb_cif_next_row(cf);
						ilen = ndb_cif_get_item_value_length(cf,IndexI);
						if (ilen > allocBuf2) {
						  allocBuf2+=ilen;
						  itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
						}
						ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
						
					 }
					 numColumn=ndb_cif_count_column(cf);
					 if (STRCMP(itemValue2,itemValueC)==0 && p!=0) {
						fprintf(fp,"loop_\n");						
						for (j=0; j< numColumn; j++) {
						  ndb_cif_get_item_name(cf,j+1, itemName);
						  ndb_cif_print_item_name(fp, itemName, &linePos);
						  fprintf(fp,"\n");
						}
						linePos=0;
						ndb_cif_move_row(cf,n);
						for (j=0;j<numColumn;j++) {
						  ilen = ndb_cif_get_item_value_length(cf,j+1);
						  if (ilen > allocBuf) {
							 allocBuf+=ilen;
							 itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
						  }
						  ndb_cif_get_item_value(cf,j+1, itemValue, allocBuf2);
						  ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
						}
						if (linePos != 0) fprintf(fp, "\n");
						linePos=0;
						ndb_cif_move_row(cf,p);
						for (j=0;j<numColumn;j++) {
						  ilen = ndb_cif_get_item_value_length(cf,j+1);
						  if (ilen > allocBuf) {
							 allocBuf+=ilen;
							 itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
						  }
						  ndb_cif_get_item_value(cf,j+1, itemValue, allocBuf);
						  ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
						}
						if (linePos != 0) fprintf(fp, "\n");
						n=0;
						p = ndb_cif_next_row(cf);
						while (p!=0){
						  linePos = 0;
						  ilen = ndb_cif_get_item_value_length(cf,IndexI);
						  if (ilen > allocBuf2) {
							 allocBuf2+=ilen;
							 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
						  }
						  ndb_cif_get_item_value(cf,IndexI, itemValue2, allocBuf2);
						  if (STRCMP(itemValue2,itemValueC) == 0) {
							 for (j=0;j<numColumn;j++) {
								ilen = ndb_cif_get_item_value_length(cf,j+1);
								if (ilen > allocBuf) {
								  allocBuf+=ilen;
								  itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
								}
								ndb_cif_get_item_value(cf,j+1, itemValue, allocBuf);
								ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
							 }
							 if (linePos != 0) fprintf(fp, "\n");
						  }
						  p = ndb_cif_next_row(cf);
						}
					 }
					 else {
						if (n!=0) {
						  ndb_cif_move_row(cf,n);
						  for (j=0; j< numColumn; j++) {
							 ndb_cif_get_item_name(cf,j+1, itemName);
							 ndb_cif_print_item_name(fp, itemName, &linePos);
							 ilen = ndb_cif_get_item_value_length(cf,j+1);
							 if (ilen > allocBuf) {
								allocBuf+=ilen;
								itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
							 }
							 ndb_cif_get_item_value(cf,j+1, itemValue2, allocBuf2);
							 ndb_cif_print_item_value_pr(fp, itemValue2, &linePos);
							 if (linePos != 0) fprintf(fp, "\n");
						  }
						}  
					 }
				  }
				}
			 }
		  }
		  else {
			 
			 numColumn=ndb_cif_count_column(cf);
			 
			 for (j=0; j< numColumn; j++) {
				ndb_cif_get_item_name(cf,j+1, itemName);
				ndb_cif_print_item_name(fp, itemName, &linePos);
				ilen = ndb_cif_get_item_value_length(cf,j+1);
				if (ilen > allocBuf2) {
				  allocBuf2+=ilen;
				  itemValue2 = (char *)  realloc(itemValue2, sizeof(char) * (allocBuf2+1));
				}
				ndb_cif_get_item_value(cf,j+1, itemValue2, allocBuf2);
				ndb_cif_print_item_value_pr(fp, itemValue2, &linePos);
				if (linePos != 0) fprintf(fp, "\n");
			 }
		  }
		  ndb_cif_next_row(format);
      }
      fprintf(fp,"save_\n");
      fprintf(fp,"\n");
      
		/*****          write save frame for item          ******/	
      
      ndb_cif_move_category_by_name(cf,datablockName,"item");
      
      ndb_cif_move_category_by_name(format,datablockName,"item");
      numRow3=ndb_cif_count_row(format);
      
      r=ndb_cif_item_row_1_key(cf,Index2,itemValueC);
		
      while ((r<=numRowI) && (r!=0)) { 
		  ilen = ndb_cif_get_item_value_length(cf,Index1);
		  if (ilen > allocBufI) {
			 allocBufI+=ilen;
			 itemValueI = (char *) realloc(itemValueI, sizeof(char) * (allocBufI+1));
		  }
		  ndb_cif_get_item_value(cf,Index1,itemValueI,allocBufI);
		  ilen = ndb_cif_get_item_value_length(cf,Index2);
		  if (ilen > allocBuf2) {
			 allocBuf2+=ilen;
			 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
		  }
		  ndb_cif_get_item_value(cf,Index2,itemValue2,allocBuf2);
		  if (strcmp(itemValueC,itemValue2)==0) {
			 fprintf(fp, "save_%s\n", itemValueI);
			 
			 for (k=0;k<numRow3;k++) {
				ilen = ndb_cif_get_item_value_length(format,1);
				if (ilen > allocBuf3) {
				  allocBuf3+=ilen;
				  itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf3+1));
				}
				ndb_cif_get_item_value(format,1,itemValue,allocBuf3);
				ndb_cif_move_category_by_name(cf,datablockName,itemValue);
				if (strcmp(itemValue,"item")!=0) {
				  ndb_cif_move_category_by_name(cf,datablockName,"item");
				  
				  m=ndb_cif_item_row_1_key(cf,Index2,itemValue);
				  ilen = ndb_cif_get_item_value_length(cf,Index2);
				  if (ilen > allocBuf2) {
					 allocBuf2+=ilen;
					 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
				  }
				  ndb_cif_get_item_value(cf,Index2,itemValue2,allocBuf2);
				  ilen = ndb_cif_get_item_value_length(cf,Index3);
				  if (ilen > allocBuf3) {
					 allocBuf3+=ilen;
					 itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
				  }
				  ndb_cif_get_item_value(cf,Index3,itemValue3,allocBuf3);
				  if (m!=0){
					 n=m;
					 while ((n<numRowI)&&( strcmp(itemValue2,itemValue)!=0 ||strcmp(itemValue3,"implicit")!=0)) {
						ndb_cif_next_row(cf);
						ilen = ndb_cif_get_item_value_length(cf,Index2);
						if (ilen > allocBuf2) {
						  allocBuf2+=ilen;
						  itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
						}
						ndb_cif_get_item_value(cf,Index2,itemValue2,allocBuf2);
						ilen = ndb_cif_get_item_value_length(cf,Index3);
						if (ilen > allocBuf3) {
						  allocBuf3+=ilen;
						  itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
						}
						ndb_cif_get_item_value(cf,Index3,itemValue3,allocBuf3);
						n++;
					 }
					 if (n<numRowI) {
						ilen = ndb_cif_get_item_value_length(cf,Index1);
						if (ilen > allocBuf1) {
						  allocBuf1+=ilen;
						  itemValue1 = (char *) realloc(itemValue1, sizeof(char) * (allocBuf1+1));
						}
						ndb_cif_get_item_value(cf,Index1,itemValue1,allocBuf1);
						ndb_cif_move_category_by_name(cf,datablockName,itemValue2);
						ndb_cif_get_item_keyword_from_item_name(cf,itemName,itemValue1);
						IndexI=ndb_cif_get_column_id(cf,datablockName,itemValue2,itemName);
						n=ndb_cif_item_row_1_key(cf,IndexI,itemValueI);
						if (n!=0) {
						  p=0;
						  ilen = ndb_cif_get_item_value_length(cf,IndexI);
						  if (ilen > allocBuf2) {
							 allocBuf2+=ilen;
							 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
						  }
						  p=ndb_cif_next_row(cf);
						  ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
						  while (STRCMP(itemValue2,itemValueI)!=0&&p!=0) {
							 p=ndb_cif_next_row(cf);
							 ilen = ndb_cif_get_item_value_length(cf,IndexI);
							 if (ilen > allocBuf2) {
								allocBuf2+=ilen;
								itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
							 }
							 ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);		
						  }
						  numColumn=ndb_cif_count_column(cf);
						  if (STRCMP(itemValue2,itemValueI)==0 && p!=0) {
							 fprintf(fp, "loop_\n");
							 for (j=0; j<numColumn; j++) {
								ndb_cif_get_item_name(cf,j+1,itemName);
								ndb_cif_print_item_name(fp, itemName, &linePos);
								fprintf(fp,"\n");
							 }
							 linePos=0;
							 ndb_cif_move_row(cf,n);
							 for (j=0; j<numColumn; j++) {						  
								ilen = ndb_cif_get_item_value_length(cf,j+1);
								if (ilen > allocBuf) {
								  allocBuf+=ilen;
								  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
								}
								ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
								ndb_cif_print_item_value_pr(fp,itemValue,&linePos);
							 }
							 if (linePos !=0) fprintf(fp, "\n");
							 linePos=0;
							 ndb_cif_move_row(cf,p);
							 for (j=0; j<numColumn; j++) {						  
								ilen = ndb_cif_get_item_value_length(cf,j+1);
								if (ilen > allocBuf) {
								  allocBuf+=ilen;
								  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
								}
								ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
								ndb_cif_print_item_value_pr(fp,itemValue,&linePos);
							 }
							 if (linePos !=0) fprintf(fp, "\n");					 
							 n=0;
							 p = ndb_cif_next_row(cf);
							 while (p!=0) {
								linePos=0;
								ilen = ndb_cif_get_item_value_length(cf,IndexI);
								if (ilen > allocBuf2) {
								  allocBuf2+=ilen;
								  itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
								}
								ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
								if (STRCMP(itemValue2,itemValueI)==0) {
								  for (j=0; j<numColumn; j++) {						  
									 ilen = ndb_cif_get_item_value_length(cf,j+1);
									 if (ilen > allocBuf) {
										allocBuf+=ilen;
										itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
									 }
									 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
									 ndb_cif_print_item_value_pr(fp,itemValue,&linePos);
								  }
								  if (linePos !=0) fprintf(fp, "\n");
								}
								p=ndb_cif_next_row(cf);
							 }
						  }
						  else {
							 if (n!=0) {
								ndb_cif_move_row(cf,n);
								
								for (j=0; j<numColumn; j++) {	
								  ndb_cif_get_item_name(cf,j+1, itemName);
								  ndb_cif_print_item_name(fp, itemName, &linePos);
								  ilen = ndb_cif_get_item_value_length(cf,j+1);
								  if (ilen > allocBuf) {
									 allocBuf+=ilen;
									 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
								  }
								  ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
								  ndb_cif_print_item_value_pr(fp,itemValue,&linePos);
								  if (linePos !=0) fprintf(fp, "\n");
								}
							 }
						  }
						} 
					 }
				  }				  
				}
				else {
	      
				  ndb_cif_item_row_1_key(cf,IndexI,itemValueI);
				  numColumn=ndb_cif_count_column(cf);
				  
				  for (j=0; j< numColumn; j++) {
					 ndb_cif_get_item_name(cf,j+1, itemName);
					 ndb_cif_print_item_name(fp, itemName, &linePos);
					 ilen = ndb_cif_get_item_value_length(cf,j+1);
					 if (ilen > allocBuf2) {
						allocBuf2+=ilen;
						itemValue2 = (char *)  realloc(itemValue2, sizeof(char) * (allocBuf2+1));
					 }
					 ndb_cif_get_item_value(cf,j+1, itemValue2, allocBuf2);
					 ndb_cif_print_item_value_pr(fp, itemValue2, &linePos);
					 if (linePos != 0) fprintf(fp, "\n");
				  }
				}
				
				ndb_cif_next_row(format);
			 }
			 fprintf(fp,"save_\n");
			 fprintf(fp,"\n");
		  }
		  ndb_cif_move_category_by_name(cf,datablockName,"item");
		  ndb_cif_move_row(cf,r);
		  r=ndb_cif_next_row(cf);
		  ndb_cif_move_category_by_name(format,datablockName,"item");
		  ndb_cif_rewind_category(format);
      }
      ndb_cif_move_category_by_name(cf,datablockName,"category");
      ndb_cif_next_row(cf);
      ndb_cif_move_category_by_name(format,datablockName,"category");
      ndb_cif_rewind_category(format);
    }
    fflush(fp);
    datablockId = ndb_cif_next_datablock(cf);
  } while (datablockId);
  if (itemValue !=NULL) free(itemValue);
  if (itemValue1 !=NULL) free(itemValue1);
  if (itemValue2 !=NULL) free(itemValue2);
  if (itemValue3 !=NULL) free(itemValue3);
  if (itemValueC !=NULL) free(itemValueC);
  if (itemValueI !=NULL) free(itemValueI);
  ndb_cif_rewind_datablock(cf);
  return(1);
}






int ndb_cif_write_dic_by_format(CifHandle *cf,FILE *fp,CifHandle *ddl,CifHandle*format,int implicit)
{
  int i,j,m,k,n,p,r, IndexC,IndexI,Index1,Index2,Index3;
  int numRowId,Index1d,Index2d,Index3d;
  int numColumn, numRow,numRowI,numRowC,numRow1,numRow2,numRow3;
  int numCat;
  int datablockId, categoryId, rowId, ilen;
  int linePos;
  char *itemValue=NULL,*itemValue1=NULL,*itemValue2=NULL,*itemValue3=NULL;
  char *itemValueC=NULL, *itemValueI=NULL;
  int  allocBuf, allocBuf1, allocBuf2, allocBuf3, allocBufC, allocBufI;
  char itemName[MxNameLen];
  char datablockName1[MxNameLen],datablockName2[MxNameLen],datablockName3[MxNameLen];
  char categoryName[MxNameLen];
  tree *btree;
  int  Id;

  /* Open input and output files */
  if (fp == NULL ) {
    return 0;
  }
  allocBuf=5000;
  allocBuf1=5000;
  allocBuf2=5000;
  allocBuf3=5000;
  allocBufC=5000;
  allocBufI=5000;
  ndb_cif_rewind_datablock(format);
  ndb_cif_rewind_datablock(ddl);
  ndb_cif_current_datablock_name(ddl,datablockName1);
  ndb_cif_current_datablock_name(format,datablockName3);
  datablockId = ndb_cif_rewind_datablock(cf);
  itemValue=(char *)calloc(allocBuf+1,sizeof(char));
  itemValue1=(char *)calloc(allocBuf1+1,sizeof(char));
  itemValue2=(char *)calloc(allocBuf2+1,sizeof(char));
  itemValue3=(char *)calloc(allocBuf3+1,sizeof(char));
  itemValueC=(char *)calloc(allocBufC+1,sizeof(char));
  itemValueI=(char *)calloc(allocBufI+1,sizeof(char));

  do {
    numCat=ndb_cif_count_category(cf);
    btree=(tree *)malloc(numCat*sizeof(tree)+1);
    for (i=0;i<numCat;i++) {
      InitBTree(&btree[i]);
    }
    ndb_cif_current_datablock_name(cf,datablockName2);
    ndb_log_message(NDB_MSG_DEBUG4, "Writing data block %s[%d of %d]\n",
						  datablockName2,
						  ndb_cif_current_datablock(cf),
						  ndb_cif_count_datablock(cf));
    fprintf(fp, "data_%s\n", datablockName2);
    ndb_cif_move_category_by_name(format,datablockName3,"data");
    numRow1=ndb_cif_count_row(format);
    for (j=0;j<numRow1;j++) {
      ilen = ndb_cif_get_item_value_length(format,1);
      if (ilen > allocBuf) {
		  allocBuf+=ilen;
		  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
      }
      ndb_cif_get_item_value(format,1,itemValue,allocBuf);
      ndb_cif_move_category_by_name(cf,datablockName2,itemValue);
      categoryId = ndb_cif_current_category(cf);
      numColumn = ndb_cif_count_column(cf);
      numRow = ndb_cif_count_row(cf);
      fprintf(fp, "#\n");
      if (numRow <=1) {
		  for (i=0; i< numColumn; i++) {
			 ndb_cif_get_item_name(cf,i+1, itemName);
			 ndb_cif_print_item_name_tab(fp, itemName, &linePos);
			 ilen = ndb_cif_get_item_value_length(cf,i+1);
			 if (ilen > allocBuf) {
				allocBuf+=ilen;
				itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
			 }
			 ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
			 ndb_cif_print_item_value_tab(fp, itemValue, &linePos);
			 if (linePos != 0) fprintf(fp, "\n");
		  }
      }
      else {
		  fprintf(fp, "   loop_\n");
		  for (i=0; i< numColumn; i++) {
			 ndb_cif_get_item_name(cf,i+1, itemName);
			 ndb_cif_print_item_name(fp, itemName, &linePos); /**/
			 fprintf(fp, "\n");
		  }
		  do {
			 linePos = 0;
			 for (i=0; i< numColumn; i++) {
				ilen = ndb_cif_get_item_value_length(cf,i+1);
				if (ilen > allocBuf) {
				  allocBuf+=ilen;
				  itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
				}
				ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
				ndb_cif_print_item_value_pr(fp, itemValue, &linePos); /**/
			 }
			 if (linePos != 0) fprintf(fp, "\n");
			 rowId = ndb_cif_next_row(cf);
		  }  while (rowId);
      }
      ndb_cif_next_row(format);
    }
    ndb_cif_move_category_by_name(ddl,datablockName1,"item");
    numRowId=ndb_cif_count_row(ddl);
    Index1d=ndb_cif_get_column_id(ddl,datablockName1,"item","name");
    Index2d=ndb_cif_get_column_id(ddl,datablockName1,"item","category_id");
    Index3d=ndb_cif_get_column_id(ddl,datablockName1,"item","mandatory_code");
    
    ndb_cif_move_category_by_name(cf,datablockName2,"item");
    numRowI=ndb_cif_count_row(cf);
    Index1=ndb_cif_get_column_id(cf,datablockName2,"item","name");
    Index2=ndb_cif_get_column_id(cf,datablockName2,"item","category_id");
    Index3=ndb_cif_get_column_id(cf,datablockName2,"item","mandatory_code");
    
    ndb_cif_move_category_by_name(format,datablockName3,"category");
    numRow1=ndb_cif_count_row(format); 
    ndb_cif_put_item_keyword(format,"implicit");
    for (i=0;i<numRow1;i++){
      ilen = ndb_cif_get_item_value_length(format,1);
      if (ilen > allocBuf) {
		  allocBuf+=ilen;
		  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
      }
      ndb_cif_get_item_value(format,1,itemValue,allocBuf);
      if (STRCMP(itemValue,"category")!=0) {
		  ndb_cif_move_category_by_name(ddl,datablockName1,"item");/**/
		  m=ndb_cif_item_row_1_keycase(ddl,Index2d,itemValue);
		  ilen = ndb_cif_get_item_value_length(ddl,Index2d);
		  if (ilen > allocBuf2) {
			 allocBuf2+=ilen;
			 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
		  }
		  ndb_cif_get_item_value(ddl,Index2d,itemValue2,allocBuf2);
		  ilen = ndb_cif_get_item_value_length(ddl,Index3d);
		  if (ilen > allocBuf3) {
			 allocBuf3+=ilen;
			 itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
		  }
		  ndb_cif_get_item_value(ddl,Index3d,itemValue3,allocBuf3);
		  n=m;
		  while ((n<numRowId)&&( STRCMP(itemValue2,itemValue)!=0 ||strcmp(itemValue3,"implicit")!=0)) {
			 ndb_cif_next_row(ddl);
			 ilen = ndb_cif_get_item_value_length(ddl,Index2d);
			 if (ilen > allocBuf2) {
				allocBuf2+=ilen;
				itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
			 }
			 ndb_cif_get_item_value(ddl,Index2d,itemValue2,allocBuf2);
			 ilen = ndb_cif_get_item_value_length(ddl,Index3d);
			 if (ilen > allocBuf3) {
				allocBuf3+=ilen;
				itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
			 }
			 ndb_cif_get_item_value(ddl,Index3d,itemValue3,allocBuf3);
			 n++;
		  }
		  if (n<numRowId) {
			 ilen = ndb_cif_get_item_value_length(ddl,Index1d);
			 if (ilen > allocBuf1) {
				allocBuf1+=ilen;
				itemValue1 = (char *) realloc(itemValue1, sizeof(char) * (allocBuf1+1));
			 }
			 ndb_cif_get_item_value(ddl,Index1d,itemValue1,allocBuf1);
			 ndb_cif_get_item_keyword_from_item_name(ddl,itemName,itemValue1);
		  }
		  
		  ndb_cif_put_item_value(format,2,itemName);
		  ndb_cif_move_category_by_name(cf,datablockName2,itemValue);
		  Id=ndb_cif_current_category(cf);
		  ndb_cif_build_category_index(cf,&btree[Id],itemName,0);
      }
      else {
		  ndb_cif_put_item_value(format,2,"id");
		  ndb_cif_move_category_by_name(cf,datablockName2,itemValue);
		  Id=ndb_cif_current_category(cf);
		  ndb_cif_build_category_index(cf,&btree[Id],"id",0);
      }
      ndb_cif_next_row(format);
    }
    ndb_cif_rewind_category(format);
    
    ndb_cif_move_category_by_name(format,datablockName3,"item");
    numRow3=ndb_cif_count_row(format);
    ndb_cif_put_item_keyword(format,"implicit");
    for (k=0;k<numRow3;k++) {
      ilen = ndb_cif_get_item_value_length(format,1);
      if (ilen > allocBuf) {
		  allocBuf+=ilen;
		  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
      }
      ndb_cif_get_item_value(format,1,itemValue,allocBuf);
      
      if (STRCMP(itemValue,"item")!=0) {
		  ndb_cif_move_category_by_name(ddl,datablockName1,"item");
		  
		  m=ndb_cif_item_row_1_keycase(ddl,Index2d,itemValue);
		  ilen = ndb_cif_get_item_value_length(ddl,Index2d);
		  if (ilen > allocBuf2) {
			 allocBuf2+=ilen;
			 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
		  }
		  ndb_cif_get_item_value(ddl,Index2d,itemValue2,allocBuf2);
		  ilen = ndb_cif_get_item_value_length(ddl,Index3d);
		  if (ilen > allocBuf3) {
			 allocBuf3+=ilen;
			 itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
		  }
		  ndb_cif_get_item_value(ddl,Index3d,itemValue3,allocBuf3);
		  n=m;
		  while ((n<numRowId)&&( STRCMP(itemValue2,itemValue)!=0 ||strcmp(itemValue3,"implicit")!=0)) {
			 ndb_cif_next_row(ddl);
			 ilen = ndb_cif_get_item_value_length(ddl,Index2d);
			 if (ilen > allocBuf2) {
				allocBuf2+=ilen;
				itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
			 }
			 ndb_cif_get_item_value(ddl,Index2d,itemValue2,allocBuf2);
			 ilen = ndb_cif_get_item_value_length(ddl,Index3d);
			 if (ilen > allocBuf3) {
				allocBuf3+=ilen;
				itemValue3 = (char *) realloc(itemValue3, sizeof(char) * (allocBuf3+1));
			 }
			 ndb_cif_get_item_value(ddl,Index3d,itemValue3,allocBuf3);
			 n++;
		  }
		  if (n<numRowId) {
			 ilen = ndb_cif_get_item_value_length(ddl,Index1d);
			 if (ilen > allocBuf1) {
				allocBuf1+=ilen;
				itemValue1 = (char *) realloc(itemValue1, sizeof(char) * (allocBuf1+1));
			 }
			 ndb_cif_get_item_value(ddl,Index1d,itemValue1,allocBuf1);
			 ndb_cif_get_item_keyword_from_item_name(ddl,itemName,itemValue1);
		  }
		  ndb_cif_put_item_value(format,2,itemName);
		  ndb_cif_move_category_by_name(cf,datablockName2,itemValue);
		  Id=ndb_cif_current_category(cf);
		  ndb_cif_build_category_index(cf,&btree[Id],itemName,0);
      }
      else {
		  ndb_cif_put_item_value(format,2,"name");
		  ndb_cif_move_category_by_name(cf,datablockName2,itemValue);
		  Id=ndb_cif_current_category(cf);
		  ndb_cif_build_category_index(cf,&btree[Id],"category_id",0);
      }
      ndb_cif_next_row(format);
    }
    ndb_cif_rewind_category(format);
    
    ndb_cif_move_category_by_name(format,datablockName3,"category");
    
    ndb_cif_move_category_by_name(cf,datablockName2,"category");
    Id=ndb_cif_current_category(cf);
    ndb_cif_go_first(cf,&btree[Id]);  
    numRowC=ndb_cif_count_row(cf);
    IndexC=ndb_cif_get_column_id(cf,datablockName2,"category","id");
	 
	 /* write save frame for category */
	 
    for (i=0;i<numRowC;i++) { 
      ilen = ndb_cif_get_item_value_length(cf,IndexC);
      if (ilen > allocBufC) {
		  allocBufC+=ilen;
		  itemValueC = (char *) realloc(itemValueC, sizeof(char) * (allocBufC+1));
      }
      ndb_cif_get_item_value(cf,IndexC,itemValueC,allocBufC);
      fprintf(fp, "save_%s\n", itemValueC);
      for (k=0;k<numRow1;k++) {
		  ilen = ndb_cif_get_item_value_length(format,1);
		  if (ilen > allocBuf) {
			 allocBuf+=ilen;
			 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
		  }
		  ndb_cif_get_item_value(format,1,itemValue,allocBuf);
		  ndb_cif_move_category_by_name(cf,datablockName2,itemValue);
		  Id=ndb_cif_current_category(cf);
		  ilen = ndb_cif_get_item_value_length(format,2);
		  if (ilen > allocBuf2) {
			 allocBuf2+=ilen;
			 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
		  }
		  ndb_cif_get_item_value(format,2,itemValue2,allocBuf2);
		  IndexI=ndb_cif_get_column_id(cf,datablockName2,itemValue,itemValue2);
		  n=ndb_cif_item_row_1_key_index(cf,&btree[Id],itemValueC,0);
		  /* In a particular table looking for all rows that have the item(with 
			  mandatory code = implicit) equal to the name of category  */
		  if (n!=0) {
			 p=ndb_cif_next_row_index(cf,&btree[Id]);
			 ilen = ndb_cif_get_item_value_length(cf,IndexI);
			 if (ilen > allocBuf2) {
				allocBuf2+=ilen;
				itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
			 }
			 ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
			 numColumn=ndb_cif_count_column(cf);
			 if (STRCMP(itemValue2,itemValueC)==0 && p!=0) {
				fprintf(fp, "   loop_\n");
				if (implicit == 0) {
				  for (j=0; j<numColumn; j++) {
					 if (IndexI!=j+1) {
						ndb_cif_get_item_name(cf,j+1,itemName);
						ndb_cif_print_item_name_tab(fp, itemName, &linePos);
						fprintf(fp,"\n");
					 }
				  }
				}
				else {
				  for (j=0; j<numColumn; j++) {
					 ndb_cif_get_item_name(cf,j+1,itemName);
					 ndb_cif_print_item_name_tab(fp, itemName, &linePos);
					 fprintf(fp,"\n");
				  }
				}
				linePos=0;
				ndb_cif_prev_row_index(cf,&btree[Id]);
				if (implicit == 0) {
				  for (j=0; j<numColumn; j++) {
					 if (IndexI!=j+1) {
						ilen = ndb_cif_get_item_value_length(cf,j+1);
						if (ilen > allocBuf) {
						  allocBuf+=ilen;
						  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						}
						ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
					 }
				  }
				  if (linePos !=0) fprintf(fp, "\n");
				}
				else {
				  for (j=0; j<numColumn; j++) {
					 ilen = ndb_cif_get_item_value_length(cf,j+1);
					 if (ilen > allocBuf) {
						allocBuf+=ilen;
						itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
					 }
					 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
					 ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
				  }
				  if (linePos !=0) fprintf(fp, "\n");
				}
				linePos=0;
				ndb_cif_next_row_index(cf,&btree[Id]);
				if (implicit == 0) {
				  for (j=0; j<numColumn; j++) {
					 if (IndexI != j+1) {
						ilen = ndb_cif_get_item_value_length(cf,j+1);
						if (ilen > allocBuf) {
						  allocBuf+=ilen;
						  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						}
						ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
					 }
				  }
				  if (linePos !=0) fprintf(fp, "\n");						  
				}
				else {
				  for (j=0; j<numColumn; j++) {
					 ilen = ndb_cif_get_item_value_length(cf,j+1);
					 if (ilen > allocBuf) {
						allocBuf+=ilen;
						itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
					 }
					 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
					 ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
				  }
				  if (linePos !=0) fprintf(fp, "\n");
				}
				
				n=0;
				p = ndb_cif_next_row_index(cf,&btree[Id]);
				linePos=0;
				ilen = ndb_cif_get_item_value_length(cf,IndexI);
				if (ilen > allocBuf) {
				  allocBuf+=ilen;
				  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
				}
				ndb_cif_get_item_value(cf,IndexI,itemValue,allocBuf);
				while (STRCMP(itemValue,itemValueC)==0 && p!=0) {
				  if (implicit == 0) {
					 for (j=0; j<numColumn; j++) {
						if (IndexI != j+1) {
						  ilen = ndb_cif_get_item_value_length(cf,j+1);
						  if (ilen > allocBuf) {
							 allocBuf+=ilen;
							 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						  }
						  ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						  ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						}
					 }
					 if (linePos !=0) fprintf(fp, "\n");
				  }
				  else {
					 for (j=0; j<numColumn; j++) {
						ilen = ndb_cif_get_item_value_length(cf,j+1);
						if (ilen > allocBuf) {
						  allocBuf+=ilen;
						  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						}
						ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
					 }
					 if (linePos !=0) fprintf(fp, "\n");
				  }
				  p=ndb_cif_next_row_index(cf,&btree[Id]);
				  ilen = ndb_cif_get_item_value_length(cf,IndexI);
				  if (ilen > allocBuf) {
					 allocBuf+=ilen;
					 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
				  }
				  ndb_cif_get_item_value(cf,IndexI,itemValue,allocBuf);
				}
			 }
			 else {
				if (n!=0) {
				  if (STRCMP(itemValue2,itemValueC)!=0)
					 ndb_cif_prev_row_index(cf,&btree[Id]);
				  if (implicit == 0) {
					 for (j=0; j<numColumn; j++) {
						if (IndexI != j+1) {
						  ndb_cif_get_item_name(cf,j+1, itemName);
						  ndb_cif_print_item_name_tab(fp, itemName, &linePos);
						  ilen = ndb_cif_get_item_value_length(cf,j+1);
						  if (ilen > allocBuf) {
							 allocBuf+=ilen;
							 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						  }
						  ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						  ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						  if (linePos !=0) fprintf(fp, "\n");
						}
					 }
				  }
				  else {
					 for (j=0; j<numColumn; j++) {
						ndb_cif_get_item_name(cf,j+1, itemName);
						ndb_cif_print_item_name_tab(fp, itemName, &linePos);
						ilen = ndb_cif_get_item_value_length(cf,j+1);
						if (ilen > allocBuf) {
						  allocBuf+=ilen;
						  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						}
						ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						if (linePos !=0) fprintf(fp, "\n");
					 }
				  }
				}
			 }
		  }
		  ndb_cif_next_row(format);
      }
      
      fprintf(fp,"save_\n");
      fprintf(fp,"\n");
		
		/*   write save frame for item           */	

      ndb_cif_move_category_by_name(cf,datablockName2,"item");
      Id=ndb_cif_current_category(cf);
      ndb_cif_move_category_by_name(format,datablockName3,"item");
      
      r=ndb_cif_item_row_1_key_index(cf,&btree[Id],itemValueC,0);
      ilen = ndb_cif_get_item_value_length(cf,Index2);
      if (ilen > allocBuf2) {
		  allocBuf2+=ilen;
		  itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
      }
      ndb_cif_get_item_value(cf,Index2,itemValue2,allocBuf2);
      while (strcasecmp(itemValueC,itemValue2)==0 && (r!=0)) {
		  ilen = ndb_cif_get_item_value_length(cf,Index1);
		  if (ilen > allocBufI) {
			 allocBufI+=ilen;
			 itemValueI = (char *) realloc(itemValueI, sizeof(char) * (allocBufI+1));
		  }
		  ndb_cif_get_item_value(cf,Index1,itemValueI,allocBufI);
		  fprintf(fp, "save_%s\n", itemValueI);
		  
		  for (k=0;k<numRow3;k++) {
			 ilen = ndb_cif_get_item_value_length(format,1);
			 if (ilen > allocBuf) {
				allocBuf+=ilen;
				itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
			 }
			 ndb_cif_get_item_value(format,1,itemValue,allocBuf);
			 if (strcasecmp(itemValue,"item")==0) {
				numColumn=ndb_cif_count_column(cf);
				ndb_cif_move_category_by_name(cf,datablockName2,"item");
				if (implicit == 0) {
				  for (j=0; j<numColumn; j++) {
					 if (IndexI != j+1) {
						ndb_cif_get_item_name(cf,j+1, itemName);
						ndb_cif_print_item_name_tab(fp, itemName, &linePos);
						ilen = ndb_cif_get_item_value_length(cf,j+1);
						if (ilen > allocBuf) {
						  allocBuf+=ilen;
						  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						}
						ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						if (linePos !=0) fprintf(fp, "\n");
					 }
				  }
				}
				else {
				  for (j=0; j<numColumn; j++) {	
					 ndb_cif_get_item_name(cf,j+1, itemName);
					 ndb_cif_print_item_name_tab(fp, itemName, &linePos);
					 ilen = ndb_cif_get_item_value_length(cf,j+1);
					 if (ilen > allocBuf) {
						allocBuf+=ilen;
						itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
					 }
					 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
					 ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
					 if (linePos !=0) fprintf(fp, "\n");
				  }
				}
			 }
			 else {
				ndb_cif_move_category_by_name(cf,datablockName2,itemValue);
				Id=ndb_cif_current_category(cf);
				n=ndb_cif_item_row_1_key_index(cf,&btree[Id],itemValueI,0);
				ilen = ndb_cif_get_item_value_length(format,2);
				if (ilen > allocBuf2) {
				  allocBuf2+=ilen;
				  itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
				}
				ndb_cif_get_item_value(format,2,itemValue2,allocBuf2);
				IndexI=ndb_cif_get_column_id(cf,datablockName2,itemValue,itemValue2);
				if (n!=0) {
				  p=ndb_cif_next_row_index(cf,&btree[Id]);
				  ilen = ndb_cif_get_item_value_length(cf,IndexI);
				  if (ilen > allocBuf2) {
					 allocBuf2+=ilen;
					 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
				  }
				  ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
				  numColumn=ndb_cif_count_column(cf);
				  if (STRCMP(itemValue2,itemValueI)==0 && p!=0) {
					 fprintf(fp, "   loop_\n");
					 if (implicit ==0) {
						for (j=0; j<numColumn; j++) {
						  if (IndexI != j+1) {
							 ndb_cif_get_item_name(cf,j+1,itemName);
							 ndb_cif_print_item_name_tab(fp, itemName, &linePos);
							 fprintf(fp,"\n");
						  }
						}								  
					 }
					 else {
						for (j=0; j<numColumn; j++) {
						  ndb_cif_get_item_name(cf,j+1,itemName);
						  ndb_cif_print_item_name_tab(fp, itemName, &linePos);
						  fprintf(fp,"\n");
						}								  
					 }
					 linePos=0;
					 ndb_cif_prev_row_index(cf,&btree[Id]);
					 if (implicit == 0) {
						for (j=0; j<numColumn; j++) {
						  if (IndexI!= j+1) {
							 ilen = ndb_cif_get_item_value_length(cf,j+1);
							 if (ilen > allocBuf) {
								allocBuf+=ilen;
								itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
							 }
							 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
							 ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						  }
						}
						if (linePos !=0) fprintf(fp, "\n");
					 }
					 else {
						for (j=0; j<numColumn; j++) {						  
						  ilen = ndb_cif_get_item_value_length(cf,j+1);
						  if (ilen > allocBuf) {
							 allocBuf+=ilen;
							 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						  }
						  ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						  ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						}
						if (linePos !=0) fprintf(fp, "\n");
					 }
					 linePos=0;
					 ndb_cif_next_row_index(cf,&btree[Id]);
					 if (implicit == 0) {
						for (j=0; j<numColumn; j++) {
						  if (IndexI != j+1) {
							 ilen = ndb_cif_get_item_value_length(cf,j+1);
							 if (ilen > allocBuf) {
								allocBuf+=ilen;
								itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
							 }
							 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
							 ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						  }
						}
						if (linePos !=0) fprintf(fp, "\n");
					 }
					 else {
						for (j=0; j<numColumn; j++) {						  
						  ilen = ndb_cif_get_item_value_length(cf,j+1);
						  if (ilen > allocBuf) {
							 allocBuf+=ilen;
							 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						  }
						  ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						  ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						}
						if (linePos !=0) fprintf(fp, "\n");
					 }
					 n=0;
					 p = ndb_cif_next_row_index(cf,&btree[Id]);
					 linePos=0;
					 ilen = ndb_cif_get_item_value_length(cf,IndexI);
					 if (ilen > allocBuf2) {
						allocBuf2+=ilen;
						itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
					 }
					 ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
					 while (STRCMP(itemValue2,itemValueI)==0 && p!=0) {
						if (implicit == 0) {
						  for (j=0; j<numColumn; j++) {						
							 if (IndexI != j+1) {
								ilen = ndb_cif_get_item_value_length(cf,j+1);
								if (ilen > allocBuf) {
								  allocBuf+=ilen;
								  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
								}
								ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
								ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
							 }
						  }
						  if (linePos !=0) fprintf(fp, "\n");
						}
						else {
						  for (j=0; j<numColumn; j++) {			  
							 ilen = ndb_cif_get_item_value_length(cf,j+1);
							 if (ilen > allocBuf) {
								allocBuf+=ilen;
								itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
							 }
							 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
							 ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
						  }
						  if (linePos !=0) fprintf(fp, "\n");
						  ilen = ndb_cif_get_item_value_length(cf,j+1);
						  if (ilen > allocBuf) {
							 allocBuf+=ilen;
							 itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
						  }
						  ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
						}
						
						p=ndb_cif_next_row_index(cf,&btree[Id]);
						linePos=0;
						ilen = ndb_cif_get_item_value_length(cf,IndexI);
						if (ilen > allocBuf2) {
						  allocBuf2+=ilen;
						  itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
						}
						ndb_cif_get_item_value(cf,IndexI,itemValue2,allocBuf2);
						
					 }
				  }
				  else {
					 if (n!=0) {
						if (STRCMP(itemValue2,itemValueI)!=0) {
						  ndb_cif_prev_row_index(cf,&btree[Id]);
						}
						if (implicit == 0) {
						  for (j=0; j<numColumn; j++) {
							 if (IndexI != j+1) {
								ndb_cif_get_item_name(cf,j+1, itemName);
								ndb_cif_print_item_name_tab(fp, itemName, &linePos);
								ilen = ndb_cif_get_item_value_length(cf,j+1);
								if (ilen > allocBuf) {
								  allocBuf+=ilen;
								  itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
								}
								ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
								ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
								if (linePos !=0) fprintf(fp, "\n");
							 }
						  }
						}
						else {
						  for (j=0; j<numColumn; j++) {	
							 ndb_cif_get_item_name(cf,j+1, itemName);
							 ndb_cif_print_item_name_tab(fp, itemName, &linePos);
							 ilen = ndb_cif_get_item_value_length(cf,j+1);
							 if (ilen > allocBuf) {
								allocBuf+=ilen;
								itemValue = (char *) realloc(itemValue, sizeof(char) * (allocBuf+1));
							 }
							 ndb_cif_get_item_value(cf,j+1,itemValue,allocBuf);
							 ndb_cif_print_item_value_tab(fp,itemValue,&linePos);
							 if (linePos !=0) fprintf(fp, "\n");
						  }
						}
					 }
				  }
				}
			 }
			 ndb_cif_next_row(format);
		  }
		  ndb_cif_rewind_category(format);
		  fprintf(fp,"save_\n");
		  fprintf(fp,"\n");
		  
		  ndb_cif_move_category_by_name(cf,datablockName2,"item");
		  Id=ndb_cif_current_category(cf);
		  r=ndb_cif_next_row_index(cf,&btree[Id]);
		  ilen = ndb_cif_get_item_value_length(cf,Index2);
		  if (ilen > allocBuf2) {
			 allocBuf2+=ilen;
			 itemValue2 = (char *) realloc(itemValue2, sizeof(char) * (allocBuf2+1));
		  }
		  ndb_cif_get_item_value(cf,Index2,itemValue2,allocBuf2);
      }
      ndb_cif_move_category_by_name(format,datablockName3,"item");
      ndb_cif_rewind_category(format);
      ndb_cif_move_category_by_name(cf,datablockName2,"category");
      Id=ndb_cif_current_category(cf);
      ndb_cif_next_row_index(cf,&btree[Id]);
      ndb_cif_move_category_by_name(format,datablockName3,"category");
      ndb_cif_rewind_category(format);
      ndb_cif_rewind_row(format);
    }
    fflush(fp);
    datablockId = ndb_cif_next_datablock(cf);
	 for (i=0; i<numCat; i++){
		FreeBTree(&btree[i]);
	 }
	 if (btree!=NULL) free(btree);
  } while (datablockId);
  if (itemValue !=NULL) free(itemValue);
  if (itemValue1 !=NULL) free(itemValue1);
  if (itemValue2 !=NULL) free(itemValue2);
  if (itemValue3 !=NULL) free(itemValue3);
  if (itemValueC !=NULL) free(itemValueC);
  if (itemValueI !=NULL) free(itemValueI);
  return(1);
}


int ndb_cif_write_file_pr1(CifHandle *cf,FILE *fp)
{
  int i, j, datablockId, categoryId, rowId, linePos, numColumn, numRow, ilen, allocBuf;
  char *itemValue=NULL, itemName[MxNameLen], datablockName[MxNameLen];
  int *cwidth=NULL;
  
  /* Open input and output files */
  if (fp == NULL ) {
    return 0;
  }
  allocBuf=5000;
  datablockId = ndb_cif_rewind_datablock(cf);
  itemValue=(char *)calloc(allocBuf+1,sizeof(char));

  do {
    ndb_cif_current_datablock_name(cf,datablockName);
    ndb_log_message(NDB_MSG_DEBUG4, "Writing data block %s[%d of %d]\n",
		    datablockName,
		    ndb_cif_current_datablock(cf),
		    ndb_cif_count_datablock(cf));
    fprintf(fp, "data_%s\n", datablockName);
    do {
      categoryId = ndb_cif_current_category(cf);
      numColumn = ndb_cif_count_column(cf);
      numRow = ndb_cif_count_row(cf);
      fprintf(fp, "#\n");
      if (numRow <=1) {
	for (i=0; i< numColumn; i++) {
	  ndb_cif_get_item_name(cf,i+1, itemName);
	  ndb_cif_print_item_name(fp, itemName, &linePos);
	  ilen = ndb_cif_get_item_value_length(cf,i+1);
	  if (ilen > allocBuf) {
	     allocBuf+=ilen;
	     itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
	  }
	  ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
	  ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
	  if (linePos != 0) fprintf(fp, "\n");
	}
      }
      else {
		  fprintf(fp, "loop_\n");
		  for (i=0; i< numColumn; i++) {
			 ndb_cif_get_item_name(cf,i+1, itemName);
			 ndb_cif_print_item_name(fp, itemName, &linePos);
			 fprintf(fp, "\n");
		  }
		  
		  cwidth = (int *) calloc(numColumn, sizeof(int));
		  for (i=0; i< numColumn; i++) { cwidth[i]=-1; }
		  ndb_cif_rewind_row(cf);
		  do {
			 for (i=0; i< numColumn; i++) {
				ilen=ndb_cif_get_item_value_length(cf,i+1);
				if ( ilen > cwidth[i]) cwidth[i]=ilen;
			 }
			 rowId = ndb_cif_next_row(cf);
		  } while (rowId);
		  
		  ndb_cif_rewind_row(cf);
		  do {
			 linePos = 0;
			 
			 ilen = ndb_cif_get_item_value_length(cf,1);
			 if (ilen > allocBuf) {
				allocBuf+=ilen;
				itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
			 }
			 ndb_cif_get_item_value(cf,1, itemValue, allocBuf);
			 ilen=ndb_cif_print_item_value_pr(fp, itemValue, &linePos); 
			 
			 for (i=1; i< numColumn; i++) { 
				if (linePos !=0 )
				  for (j=0; j < 2+cwidth[i-1]-ilen; j++) fprintf(fp," ");
				linePos+=2+cwidth[i-1]-ilen;
				ilen = ndb_cif_get_item_value_length(cf,i+1);
				if (ilen > allocBuf) {
				  allocBuf+=ilen;
				  itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
				}
				ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
				ilen=ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
			 }
			 if (linePos != 0) fprintf(fp, "\n");
			 rowId = ndb_cif_next_row(cf);
		  }  while (rowId);
		  if (cwidth) free(cwidth);
      }
      fflush(fp);
      categoryId = ndb_cif_next_category(cf);
    } while (categoryId);
    fprintf(fp, "#\n");
    fflush(fp);
    datablockId = ndb_cif_next_datablock(cf);
  } while (datablockId);
  free(itemValue);
  ndb_cif_rewind_datablock(cf);
  return(1);
}




int ndb_cif_write_file_pr(CifHandle *cf,FILE *fp)
{
  int i, j, datablockId, categoryId, rowId, linePos, numColumn, numRow, ilen, allocBuf;
  char *itemValue=NULL, itemName[MxNameLen], datablockName[MxNameLen];
  int *cwidth=NULL;

  /* Open input and output files */
  if (fp == NULL ) {
    return 0;
  }
  allocBuf=5000;
  datablockId = ndb_cif_rewind_datablock(cf);
  itemValue=(char *)calloc(allocBuf+1,sizeof(char));

  do {
    ndb_cif_current_datablock_name(cf,datablockName);
    ndb_log_message(NDB_MSG_DEBUG4, "Writing data block %s[%d of %d]\n",
						  datablockName,
						  ndb_cif_current_datablock(cf),
						  ndb_cif_count_datablock(cf));
    fprintf(fp, "data_%s\n", datablockName);
    do {
      categoryId = ndb_cif_current_category(cf);
      numColumn = ndb_cif_count_column(cf);
      numRow = ndb_cif_count_row(cf);
      fprintf(fp, "#\n");
      if (numRow <=1) {
		  for (i=0; i< numColumn; i++) {
			 ndb_cif_get_item_name(cf,i+1, itemName);
			 ndb_cif_print_item_name(fp, itemName, &linePos);
			 ilen = ndb_cif_get_item_value_length(cf,i+1);
			 if (ilen > allocBuf) {
				allocBuf+=ilen;
				itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
			 }
			 ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
			 ndb_cif_print_item_value_pr(fp, itemValue, &linePos);
			 if (linePos != 0) fprintf(fp, "\n");
		  }
      }
      else {
		  fprintf(fp, "loop_\n");
		  for (i=0; i< numColumn; i++) {
			 ndb_cif_get_item_name(cf,i+1, itemName);
			 ndb_cif_print_item_name(fp, itemName, &linePos);
			 fprintf(fp, "\n");
		  }
		  
		  cwidth = (int *) calloc(numColumn, sizeof(int));
		  for (i=0; i< numColumn; i++) { cwidth[i]=-1; }
		  ndb_cif_rewind_row(cf);
		  do {
			 for (i=0; i< numColumn; i++) {
				ilen=ndb_cif_get_item_value_length(cf,i+1);
				if ( ilen > cwidth[i]) cwidth[i]=ilen;
			 }
			 rowId = ndb_cif_next_row(cf);
		  } while (rowId);
		  
		  ndb_cif_rewind_row(cf);
		  do {
			 linePos = 0;
			 for (i=0; i< numColumn; i++) {
				ilen = ndb_cif_get_item_value_length(cf,i+1);
				if (ilen > allocBuf) {
				  allocBuf+=ilen;
				  itemValue = (char *)  realloc(itemValue, sizeof(char) * (allocBuf+1));
				}
				ndb_cif_get_item_value(cf,i+1, itemValue, allocBuf);
				ilen=ndb_cif_print_item_value_pr(fp, itemValue, &linePos); 
				for (j=0; j < 2+cwidth[i]-ilen; j++) fprintf(fp," ");
				linePos+=2+cwidth[i]-ilen;
			 }
			 if (linePos != 0) fprintf(fp, "\n");
			 rowId = ndb_cif_next_row(cf);
		  }  while (rowId);
		  if (cwidth) free(cwidth);
      }
      fflush(fp);
      categoryId = ndb_cif_next_category(cf);
    } while (categoryId);
    fprintf(fp, "#\n");
    fflush(fp);
    datablockId = ndb_cif_next_datablock(cf);
  } while (datablockId);
  free(itemValue);
  ndb_cif_rewind_datablock(cf);
  return(1);
}


void ndb_cif_print_item_name(FILE *fp, const char *itemName, int *linePos)
{
  fprintf(fp, "%s  ", itemName);
  *linePos = strlen(itemName) +2;
}


void ndb_cif_print_item_value(FILE *fp, const char *itemValue, int *linePos) 
{
  int i, str_len, multipleLine, multipleWord, embeddedQuotes, len;

  /* NULL VALUE */
  if (itemValue == NULL || !strcmp(itemValue,"")) { 
    if (*linePos < MxNameLen - 1) {
      (*linePos) +=1;
      fprintf(fp, null_char);
      if (*linePos < MxNameLen -2) {
		  fprintf(fp, "  ");
		  (*linePos) +=2;
      }
      else {
		  fprintf(fp, "\n");
		  (*linePos) = 0;
      }
    }
    else {
      fprintf(fp, "\n?  ");
      (*linePos) = 3;
    }
    return;
  }
  
  str_len = strlen(itemValue);
  multipleLine = FALSE;
  multipleWord = FALSE;
  embeddedQuotes = FALSE;
  len = 0;
  for (i=0; i<str_len; i++) {
    if (itemValue[i] == ' ') multipleWord = TRUE;
    else if (itemValue[i] == '\n') multipleLine =TRUE ;
    else if (itemValue[i] == '\'' || itemValue[i] == '\"') embeddedQuotes =TRUE ;
    if (itemValue[i] == '\t') len +=8;
    else                      len ++;
  }
  if (embeddedQuotes && multipleWord) multipleLine = TRUE;
  if (embeddedQuotes) multipleWord = TRUE;
  
  if (len > MxNameLen || multipleLine) {
    if (*linePos != 0)
      fprintf(fp, "\n");
    fprintf(fp, ";%s", itemValue);
	 fprintf(fp, "\n");
    fprintf(fp, ";\n");
    *linePos = 0;
  }
  else {
    if (!multipleWord && len + (*linePos) > MxNameLen ||
		  multipleWord && len + 2 + (*linePos) > MxNameLen) 
      fprintf(fp, "\n");
    if (multipleWord) {
      fprintf(fp, "\'%s\'", itemValue);
      (*linePos) += (len + 2);
    }
    else {
      fprintf(fp, "%s", itemValue);
      (*linePos) += len ;
    }
    if (*linePos +2 < MxNameLen) {
      fprintf(fp, "  ");
      (*linePos) +=2;
    }
    else {
      fprintf(fp, "\n");
      (*linePos) = 0;
    }
  }
}



int ndb_cif_print_item_value_pr(FILE *fp, const char *itemValue, int *linePos) 
{
  int i, str_len, multipleLine, multipleWord, embeddedQuotes, len;
  int MAXLINE=80;
  
  /* NULL VALUE */
  if (itemValue == NULL || !strcmp(itemValue,"")) { 
    if (*linePos < MAXLINE - 1) {
      (*linePos) +=1;
      fprintf(fp, null_char);
      if (*linePos < MAXLINE -2) {
		  fprintf(fp, "  ");
		  (*linePos) +=2;
      }
      else {
		  fprintf(fp, "\n");
		  (*linePos) = 0;
      }
    }
    else {
      fprintf(fp, "\n?  ");
      (*linePos) = 3;
    }
    return 3;
  }
  
  str_len = strlen(itemValue);
  multipleLine = FALSE;
  multipleWord = FALSE;
  embeddedQuotes = FALSE;
  len = 0;
  if (itemValue[0] == '_') multipleWord = TRUE;
  if (itemValue[0] == ';') multipleWord = TRUE;

  if (strncasecmp(itemValue,"data_",5)==0) multipleWord = TRUE;
  if (strncasecmp(itemValue,"save_",5)==0) multipleWord = TRUE;
  if (strncasecmp(itemValue,"loop_",5)==0) multipleWord = TRUE;

  for (i=0; i<str_len; i++) {
    if (itemValue[i] == ' ') multipleWord = TRUE;
    else if (itemValue[i] == '\n') multipleLine =TRUE ;
    else if (itemValue[i] == '\'' || itemValue[i] == '\"') embeddedQuotes =TRUE ;
    if (itemValue[i] == '\t') len +=8;
    else                      len ++;
  }
  if (embeddedQuotes && multipleWord) multipleLine = TRUE;
  if (embeddedQuotes) multipleWord = TRUE;

  if (len > MAXLINE || multipleLine) {
    if (*linePos != 0)
      fprintf(fp, "\n");
    fprintf(fp, ";%s", itemValue);
	 fprintf(fp, "\n");
    fprintf(fp, ";\n");
    *linePos = 0;
  }
  else {
    if (!multipleWord && len + (*linePos) > MAXLINE ||
		  multipleWord && len + 2 + (*linePos) > MAXLINE) 
      fprintf(fp, "\n");
    if (multipleWord) {
		if (len + 2 + (*linePos) > MAXLINE ){
		  (*linePos) = 0;
		}
      fprintf(fp, "\'%s\'", itemValue);
      (*linePos) += (len + 2);
    }
    else {
      fprintf(fp, "%s", itemValue);
      (*linePos) += len ;
    }
    if (*linePos +2 < MAXLINE) {
      fprintf(fp, "  ");
      (*linePos) +=2;
    }
    else {
      fprintf(fp, "\n");
      (*linePos) = 0;
    }
  }
  if (multipleWord || multipleLine || embeddedQuotes) 
    return (str_len+2);
  else
    return (str_len);
      
}

void ndb_cif_print_item_name_tab(FILE *fp, const char *itemName, int *linePos)
{
  int i;
  int start=40;

  fprintf(fp,"   ");
  fprintf(fp, "%s  ", itemName);
  *linePos = 3+strlen(itemName) +2;
  while (*linePos>start)
	 start=start+10;
  for (i=0;i<=start-(*linePos);i++)
	 fprintf(fp," ");
  *linePos=start;
  
}

int ndb_cif_print_item_value_tab(FILE *fp, const char *itemValue, int *linePos) 
{
  int i, str_len, multipleLine, multipleWord, embeddedQuotes, len;
  int MAXLINE=80;
  int kvant=12;
  int startcol=15;
  int start=3;
  int start2=6;

  if (*linePos==0) {
	 fprintf(fp,"      ");
	 *linePos=start2;
  }
  /* NULL VALUE */
  if (itemValue == NULL || !strcmp(itemValue,"")) { 
    if (*linePos < MAXLINE - 1) {
      (*linePos) +=1;
      fprintf(fp, "%s",null_char);
      if (*linePos < MAXLINE -2) {
		  fprintf(fp, "  ");
		  (*linePos) +=2;
      }
      else {
		  fprintf(fp, "\n");
		  (*linePos) = 0;
      }
    }
    else {
      fprintf(fp, "\n?  ");  
      (*linePos) = 3;
    }

	 while (*linePos>startcol)
		startcol=startcol+kvant;
		for (i=0;i<startcol-(*linePos);i++)
		  fprintf(fp," ");
		*linePos=startcol;
    return 3;

  }

  str_len = strlen(itemValue);
  multipleLine = FALSE;
  multipleWord = FALSE;
  embeddedQuotes = FALSE;
  len = 0;
  if (itemValue[0] == '_') multipleWord = TRUE;
  if (strncasecmp(itemValue,"data_",5)==0) multipleWord = TRUE;
  if (strncasecmp(itemValue,"save_",5)==0) multipleWord = TRUE;
  if (strncasecmp(itemValue,"loop_",5)==0) multipleWord = TRUE;

  for (i=0; i<str_len; i++) {
    if (itemValue[i] == ' ') multipleWord = TRUE;
    else if (itemValue[i] == '\n') multipleLine =TRUE ;
    else if (itemValue[i] == '\'' || itemValue[i] == '\"') embeddedQuotes =TRUE ;
    if (itemValue[i] == '\t') len +=8;
    else                      len ++;
  }
  if (embeddedQuotes && multipleWord) multipleLine = TRUE;
  if (embeddedQuotes) multipleWord = TRUE;

  if (len> MAXLINE || multipleLine) {
    if (*linePos != 0)
      fprintf(fp, "\n");
    fprintf(fp, ";%s", itemValue);
      fprintf(fp, "\n");
    fprintf(fp, ";\n");
    *linePos = 0;
  }
  else {
    if (!multipleWord && len + (*linePos) > MAXLINE ||
		  multipleWord && len + 2 + (*linePos) > MAXLINE) {
      fprintf(fp, "\n");
		(*linePos) = start2;
		fprintf(fp, "      ");
	 }
    if (multipleWord) {
      fprintf(fp, "\'%s\'", itemValue);
      (*linePos) += (len + 2);
    }
    else {
      fprintf(fp, "%s", itemValue);
      (*linePos) += len ;
    }
    if (*linePos +2 < MAXLINE) {
      fprintf(fp, "  ");
      (*linePos) +=2;
    }
  }

	 while (*linePos>startcol)
		startcol=startcol+kvant;
		for (i=0;i<startcol-(*linePos);i++)
		  fprintf(fp," ");
		*linePos=startcol;
	 
  if (multipleWord || multipleLine || embeddedQuotes) 
    return (str_len+2);
  else
    return (str_len);
}

void ndb_cif_write_category(CifHandle *cf,FILE *fp)
{
  int icol, irow, datablockId, categoryId, numColumn, numRow, linePos;
  int str_len1, str_len, i;
  char itemName[MxNameLen];
  NdbCifRowFormat *pRow;
  NdbCifCategoryFormat *pCat;
  static int *colwidth = NULL;

  datablockId = ndb_cif_current_datablock(cf);
  categoryId = ndb_cif_current_category(cf);
  numColumn = ndb_cif_count_column(cf);
  numRow = ndb_cif_count_row(cf);
  fprintf(fp, "#\n");
  pCat = &(*cf).datablocks[datablockId-1].categories[categoryId-1];
  if (numRow <=1) {
    if (numRow == 1)
      pRow = &pCat->rows[0];
	 
    for (icol=0; icol< numColumn; icol++) {
      ndb_cif_get_item_name(cf,icol+1, itemName);
      ndb_cif_print_item_name(fp, itemName, &linePos);
		
      if (numRow == 0 || pRow->columns[icol] == NULL) 
		  ndb_cif_print_formatted_item_value(fp, &linePos, "" , TRUE, 1);
      else 
		  ndb_cif_print_formatted_item_value(fp, &linePos, pRow->columns[icol], TRUE, 1);
    }
  }
  else {
    fprintf(fp, "loop_\n");
	 
    /* counting colwidth */
    colwidth = (int *)   realloc(colwidth, sizeof(int) *numColumn);
    for (icol=0; icol< numColumn; icol++) 
      colwidth[icol] = 1;
    ndb_cif_rewind_row(cf);
    for (icol=0; icol< numColumn; icol++) {
      for (irow=0; irow< numRow; irow++, ndb_cif_next_row(cf)) {
		  pRow = &pCat->rows[irow];
		  if (pRow != NULL && pRow->columns[icol] != NULL) {
			 str_len = strlen(pRow->columns[icol]);
			 str_len1 = 0;
			 for (i=0; i<str_len+1; i++)
				if (pRow->columns[icol][i] == '\n' || pRow->columns[icol][i] == 0) {
				  if (colwidth[icol] < i - str_len1 +1)
					 colwidth[icol] = i-str_len1;
				  str_len1 = i;
				}
		  }
      }
      ndb_cif_rewind_row(cf);
    }
	 
    for (icol=0; icol< numColumn; icol++) {
      ndb_cif_get_item_name(cf,icol+1, itemName);
      ndb_cif_print_item_name(fp, itemName, &linePos);
      fprintf(fp, "\n");
    }
    irow = 1;
    ndb_cif_rewind_row(cf);
    do {
      pRow = &pCat->rows[irow-1];
      linePos = 0;
      for (icol=0; icol< numColumn; icol++) {
		  if (icol == numColumn-1)
			 ndb_cif_print_formatted_item_value(fp, &linePos, pRow->columns[icol], TRUE,
															colwidth[icol]);
		  else
			 ndb_cif_print_formatted_item_value(fp, &linePos, pRow->columns[icol], FALSE,
															colwidth[icol]);
      }
      irow = ndb_cif_next_row(cf);
    }  while (irow);
  }
  fflush(fp);
}

void ndb_cif_print_formatted_item_value(FILE *outfile, int *offset, 
					char *value, int newline_end,
					int fieldLength)
/* ---------------------------------------------------------------------
                       print_cif_value
   Rule: 1. If there're single quotes or newlines in value or it exceed 80 
            characters, then it is assumed to be mutiple line value
	    put semi-colon at the begining and end of the value
	    definitely, the *offset will be set to 0
            
         2. If it is less than 80 character there're spaces in the value,
	    then single quotes are put around the value
         3. Single word

	 For 2 and 3, if it will exceed 80 characters after printing out the
         value has to be checked. and *offset has to be updated. 
         If newline_end is true, only multiple-word and single-word values
         need to print a new line
	 
   Parameters: FILE *outfile: file pointer 
               int  *offset:  to keep track the current position of column
	       char *value:   the value to be printed
	       int newline_end: Should a new line to be printed at the end
                                or not. 
 ---------------------------------------------------------------------*/
{
  int str_len, i, pos, len, newline;
  char tmpstring[MxNameLen], fieldFormat[MxNameLen];

  if (value == NULL || !strcmp("",value)) {
    value = (char *) calloc(2, sizeof(char));
    strcpy(value, null_char);
  }

  str_len = strlen(value);
  for (newline=0; newline<str_len; newline++)
    if (value[newline] == '\'' || value[newline] == '\n') break;
  
  /* Multiple line value, or there're '\n' or '\' in the value */
  if (str_len > 76 || newline != str_len) {
    if (*offset != 0)
      fprintf(outfile, "\n");
    fprintf(outfile, ";\n");
    pos = 0;
    while (pos < str_len) {
      memset(tmpstring, 0, MxNameLen);
      strncpy(tmpstring, &value[pos], MxNameLen-1);
      if ( str_len -pos > MxNameLen)
		  len = 78;
      else
		  len = str_len - pos;
		
      i = 0;
      if (newline != str_len && value[newline] == '\n') 
		  for (i= len; i> 0; i--) 
			 if (tmpstring[i] == '\n') break;
      /* Did not find newline, in these 80 character, try to find break point */
      if (i == 0) {
		  for (i= len; i> 0; i--) 
			 if (!isalnum(tmpstring[i]) && tmpstring[i] != '.') break;
		  if (i == 0)
			 i = len;
      }
      memset(tmpstring, 0, MxNameLen);
      if (value[i+pos] == '\n') 
		  strncpy(tmpstring, &value[pos], i);
      else 
		  strncpy(tmpstring, &value[pos], i+1);
      pos +=(i+1);
      fprintf(outfile, "%s\n",tmpstring);
    }
    fprintf(outfile, ";\n");
    *offset = 0;
  }
  else {

    /* Check if after adding the new value, it will exceed 80 character */
    if (str_len + (*offset) > 75 || fieldLength + (*offset) > 75)  {
      fprintf(outfile, "\n");
      *offset = 0;
    }

    /* Check if it is mutiple word value */
    for (i=0; i<str_len; i++)
      if (value[i] == ' ') break;

    /* 
     * if value is mutiple words put quotes in the front and at the end, 
     * and if it is not at the beginning of the line, leave some spaces 
     * from previous value
     */
    if (i == str_len) {
      if (*offset != 0) 
		  sprintf(tmpstring, " %s\0", value);
      else 
		  strcpy(tmpstring, value);
    }
    else {
      if (*offset != 0) 
		  sprintf(tmpstring, " \'%s\'\0", value);
      else
		  sprintf(tmpstring, "\'%s\'\0", value);
    }
    if (str_len < fieldLength) { 
      if ((fieldLength+3) > 80) str_len +=3;
      else str_len = fieldLength+3;
    } else str_len +=3;

    sprintf(fieldFormat,"%%-%ds",str_len);
    fprintf(outfile, fieldFormat, tmpstring);

    (*offset) += (str_len);

    /* If it need a newline at the end of value, put it */
    if (newline_end) fprintf(outfile, "\n");
  }
}


int ndb_cif_item_row_1_keycase(CifHandle *cf,const int colId, char *fieldValue)
  /* In the current category, examine all the rows and return the row number if fieldValue
     is found, and also also set the current row to i. If the row is not found return 0.
  */
{
  int i;
  int curDatablock, curCategory;
  NdbCifRowFormat *pRow;
  NdbCifCategoryFormat *pCategory;
  
  if ((*cf).numDatablock == 0)  return 0;
  if ((*cf).curDatablock >= (*cf).numDatablock ||
		((*cf).datablocks[(*cf).curDatablock].curCategory >=
		 (*cf).datablocks[(*cf).curDatablock].numCategory))
	 return 0;
  
  curDatablock = (*cf).curDatablock;
  curCategory = (*cf).datablocks[curDatablock].curCategory;
  pCategory = &(*cf).datablocks[curDatablock].categories[curCategory];
  
  if (colId <= 0 ||
		colId >  pCategory->numCol)
	 return 0;
  
  for (i = 0; i < pCategory->numRow; i++)
	 {
		pRow = &pCategory->rows[i];
		if ((pRow->columns[colId-1] != NULL) 
			 && !STRCMP(fieldValue, pRow->columns[colId-1]))
		  {
			 pCategory->curRow = i;    
			 return i + 1;
		  }
	 }
  return 0;
}

void ndb_cif_encapsulate(char **a)
/* puts the encapsulated characters into string. At the
	begining of string puts 5 $, and one $ at the begining of
	every new line in the string
*/
{
  int i,j;
  int len,len1;
  char * value;
  char x[3];
  unsigned int hexNum;
  len=strlen(*a);
  len1=6;

  if (strncmp (*a,"$$$$$",5)!=0) {
	 value = (char *)malloc(len1);
	 strcpy(value,"$$$$$");
	 j=5;
	 for (i=0;i<=len;i++)
		{
		  if (isascii((*a)[i])==0){
		    value[j]='\\';
		    j=j+3;
		    len1=len1+3;
		  value=(char *)realloc(value,len1);
		    value[j-2]='x';
                    hexNum = 0x000000FF & (*a)[i];
		    sprintf(x,"%X",hexNum);
		    value[j-1]=x[0];
		    value[j]=x[1];
		  }
		  else
		    value[j]=(*a)[i];
		  j++;
		  len1++;
		  value=(char *)realloc(value,len1);
		  if ((*a)[i]=='\n') {
			 value[j]='$';
			 j++;
			 len1++;
			 value=(char *)realloc(value,len1);
		  }
		}
	 if (*a!=NULL) free(*a);
	 *a=value;
  }
}


void ndb_cif_de_encapsulate(char ** a)
{
  int i,j;
  int len;
  char * value;
  len=strlen(*a);
  if (strncmp (*a,"$$$$$",5)==0) {
	 value = (char *)malloc(len);
	 j=0;
	 for (i=5;i<=len;i++)
		{
		  value[j]=(*a)[i];
		  j++;
		  if ((*a)[i]=='\n') {
			 i++;
		  }
		}
	 if (*a!=NULL) free(*a);
	 *a=value;
  }
}
