Revision 238 (by dpavlin, 2004/03/08 17:46:16) tagging openisis 0.9.0
/*
	openisis - an open implementation of the CDS/ISIS database
	Version 0.8.x (patchlevel see file Version)
	Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	see README for more information
EOH */

/*
	$Id: lstr.c,v 1.13 2003/04/08 00:20:53 kripke Exp $
	implementation of record cooking.
*/
#include <stdlib.h>

#include "lstr.h"
#include "luti.h"


/* ************************************************************
	private types
*/
/* ************************************************************
	private data
*/
static const char * nameMfc[] = {
	"Mfc", "CTLM", "NMFN", "NMFB", "NMFP", "TYPE", "RCNT", "MFX1", "MFX2", "MFX3"
};

static int descMfc[] = {
	LSTRSIZE( 9, 0, 0 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,
	LMBRINT,
	LMBRINT,
	LMBRSHORT,
	LMBRSHORT,
	LMBRINT,
	LMBRINT,
	LMBRINT,
	LMBRINT
}; /* descMfc */


static const char * nameMfr[] = {
	"Mfr", "MFN", "RECL", "BWB", "BWP", "BASE", "NVF", "STAT",
	"TAG", "'POS", "LEN"
};
static int descMfr[] = {
	LSTRSIZE( 7, 3, 0 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,
	LMBRSHORT,
	LMBRINT,
	LMBRSHORT,

	LMBRSHORT,
	LMBRSHORT,
	LMBRSHORT,

	LMBRSHORT,
	LMBRSHORT,
	LMBRSHORT
}; /* descMfr */

/* aligned version */
static int descMfrA[] = {
	LSTRSIZE( 7, 3, 0 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,
	LMBRSHORT,
	LSTRLOFF( LMBRINT, 8 ),
	LMBRSHORT,

	LMBRSHORT,
	LMBRSHORT,
	LMBRSHORT,

	LMBRSHORT,
	LMBRSHORT,
	LMBRSHORT
}; /* descMfr */

static const char * nameXrf[] = {
	"Xrf", "XPOS", "XREC"
};
static int descXrf[] = {
	LSTRSIZE( 1, 1, 127 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,
	LMBRINT
}; /* descXrf */

static const char ** nameMst[LSTR_MST] = {
	nameMfc, nameMfr, nameXrf
};

static int* descMst[LSTR_MST] = {
	descMfc, /* MST head */
	descMfr, /* MST record */
	descXrf  /* XRF record */
};

static int* descMstA[LSTR_MST] = {
	descMfc, /* MST head */
	descMfrA, /* MST record */
	descXrf  /* XRF record */
};


static const char * nameCnt[] = {
	"Cnt", "TYPE", "ORDN", "ORDF", "N", "K", "LEV", "POSR", "NMAX", "FMAX", "ABNO"
};
static int descCnt[] = {
	LSTRSIZE( 10, 0, 0 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRSHORT, /* TYPE */
	LMBRSHORT, /* ORDN */
	LMBRSHORT, /* ORDF */
	LMBRSHORT, /* N */
	LMBRSHORT, /* K */
	LMBRSHORT, /* LEV */
	LMBRINT,   /* POSR */
	LMBRINT,   /* NMAX */
	LMBRINT,   /* FMAX */
	LMBRSHORT  /* ABNO */
}; /* descCnt */

static int descCntA[] = {
	LSTRSIZE( 10, 0, 0 ), /* sizes (fix, rep, occ) */
	0,28,44,
	LMBRSHORT, /* TYPE */
	LMBRSHORT, /* ORDN */
	LMBRSHORT, /* ORDF */
	LMBRSHORT, /* N */
	LMBRSHORT, /* K */
	LMBRSHORT, /* LEV */
	LMBRINT,   /* POSR */
	LMBRINT,   /* NMAX */
	LMBRINT,   /* FMAX */
	LMBRSHORT  /* ABNO */
}; /* descCntA */

static const char * nameN0[] = {
	"N0", "POS", "OCK", "TYPE", "'KEY", "REF"
};
static int descN01[] = {
	LSTRSIZE( 3, 2, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	10,        /* KEY */
	LMBRINT    /* REF */
};

static int descN01A[] = {
	LSTRSIZE( 3, 2, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	10,        /* KEY */
	LSTRLOFF( LMBRINT, 12 )    /* REF */
};

static int descN02[] = {
	LSTRSIZE( 3, 2, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	30,        /* KEY */
	LMBRINT    /* REF */
};
static int descN02A[] = {
	LSTRSIZE( 3, 2, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	30,        /* KEY */
	LSTRLOFF( LMBRINT, 32 )    /* REF */
};

static const char * nameL0[] = {
	"L0", "POS", "OCK", "TYPE", "PS", "'KEY", "INFB", "INFP"
};
static int descL01[] = {
	LSTRSIZE( 4, 3, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	LMBRINT,   /* PS */
	10,        /* KEY */
	LMBRINT,   /* INFB */
	LMBRINT    /* INFP */
};
static int descL01A[] = {
	LSTRSIZE( 4, 3, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	LMBRINT,   /* PS */
	10,        /* KEY */
	LSTRLOFF( LMBRINT, 12 ),   /* INFB */
	LMBRINT    /* INFP */
};


static int descL02[] = {
	LSTRSIZE( 4, 3, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	LMBRINT,   /* PS */
	30,        /* KEY */
	LMBRINT,   /* INFB */
	LMBRINT    /* INFP */
};
static int descL02A[] = {
	LSTRSIZE( 4, 3, 10 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* POS */
	LMBRSHORT, /* OCK */
	LMBRSHORT, /* TYPE */
	LMBRINT,   /* PS */
	30,        /* KEY */
	LSTRLOFF( LMBRINT, 32 ),   /* INFB */
	LMBRINT    /* INFP */
};

static const char * nameIfp[] = {
	"IfH", "NXTB", "NXTP", "TOTP", "SEGP", "SEGC", "MFN", "INFO"
};
static int descIfp[] = {
#ifdef CONVERT_POSTINGS
	/*
	to properly convert postings,
	the repeated part needs to be a big-endian 64bit int

	however, converting can't be done in a straightforward fashion anyway,
	since posting segments have holes of one or two longs at block boundaries
	*/
	LSTRSIZE( 5, 2, 1 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
	LMBRINT,   /* */
	LMBRINT,   /* */
#else
	LSTRSIZE( 5, 0, 0 ), /* sizes (fix, rep, occ) */
	LSTR_AUTOLENGTHS,
#endif
	LMBRINT,   /* */
	LMBRINT,   /* */
	LMBRINT,   /* */
	LMBRINT,   /* */
	LMBRINT    /* */
};

static const char ** nameInv[LSTR_INV] = {
	nameCnt,
	nameN0,
	nameL0,
	nameN0,
	nameL0,
	nameIfp
};

static int* descInv[LSTR_INV] = {
	descCnt, /* CNT record */
	descN01, /* N01 record */
	descL01, /* L01 record */
	descN02, /* N02 record */
	descL02, /* L02 record */
	descIfp  /* Ifp record */
};

static int* descInvA[LSTR_INV] = {
	descCntA, /* CNT record */
	descN01A, /* N01 record */
	descL01A, /* L01 record */
	descN02A, /* N02 record */
	descL02A, /* L02 record */
	descIfp  /* Ifp record */
};


/* ************************************************************
	private functions
*/
/* ************************************************************
	package data
*/
const LstrSet lstrlib[LSET_SETS] = {
	{ /* Isis 1 MST */
		nameMst, { descMst, descMstA }
	}, 
	{ /* Isis 1 INV */
		nameInv, { descInv, descInvA }
	}, 
}; /* lstrlib */

/* ************************************************************
	package functions
*/
/* ************************************************************
	public functions
*/
int lstr_auto ( int *str ) {
	static int pow2[] = { 1, 2, 4, 8 };
	int ret = 0;
	int fix,rep,occ,i;
	int *xmbrs, txlen, tilen;
	int nmbrs, off = 0, xlen[2] = {0,0}, blen[2] = {0,0}, x=0;
	

	if ( NULL == str ) {
#define DOALL( x ) \
	for ( i=0; i<(int)(sizeof(x)/sizeof(x[0])); i++ ) \
		if ( NULL != x[i] ) ret |= lstr_auto( x[i] )
		DOALL( descMst );
		DOALL( descInv );
		DOALL( descMstA );
		DOALL( descInvA );
		return ret;
	}

	fix = LSTRFIX(*str);
	rep = LSTRREP(*str);
	occ = LSTROCC(*str);
	xmbrs = str + LSTR_XMBR;
	nmbrs = fix;

	for ( x=0; ; x++ ) { /* fix and rep */
		for ( i=0; i<nmbrs; i++ ) {
			int xmbr = xmbrs[i];
			int len;
			if ( LONG2OFF( xmbr ) )
				off = LONG2OFF( xmbr );
			else {
				xmbrs[i] |= off << 16;
			}
			if ( LMBRISNUM(xmbr) )
				len = pow2[ LMBRLD(xmbr) ];
			else {
				len = LONG2LEN(xmbr);
				blen[x] += len+1;
			}
			LOG_DBG( LOG_ALL, "x.i %d.%d off %3ld, xmbr %08x len %d",
				x, i, off, xmbrs[i], len );
			off += len;
			if ( xlen[x] < off )
				xlen[x] = off;
		}
		/* done with one part */
		if ( x || !rep ) /* was 2nd */
			break;
		xmbrs += fix;
		nmbrs  = rep;
		off    = 0;
	}
	/* got length's and buffer lengths of both parts */
	LOG_DBG( LOG_ALL, "%08x %08x %d %d: xl %d %d bl %d %d",
		str[0], str[1], str[2], str[3],
		xlen[0], xlen[1], blen[0], blen[1] );
	if ( !(short)(str[LSTR_XRLO] >> 16) )
		str[LSTR_XRLO] |= xlen[0] << 16;
	else if ( xlen[0] > (short)(str[LSTR_XRLO] >> 16) )
		log_msg( LOG_WARN, "short xlen[0] %hd < %d",
			(short)(str[LSTR_XRLO] >> 16), xlen[0] );
	if ( !(short)str[LSTR_XRLO] )
		str[LSTR_XRLO] |= 0xffff & xlen[1];
	else if ( xlen[1] > (short)str[LSTR_XRLO] )
		log_msg( LOG_WARN, "short xlen[1] %hd < %d",
			(short)str[LSTR_XRLO], xlen[1] );
	/* build totals applying occ */
	txlen = (short)(str[LSTR_XRLO] >> 16)
		+ (int)occ*(short)str[LSTR_XRLO];
	if ( !str[LSTR_XLEN] )
		str[LSTR_XLEN] = txlen;
	else if ( txlen > str[LSTR_XLEN] )
		log_msg( LOG_WARN, "short xlen %d < %d",
			str[LSTR_XLEN], txlen );
	tilen = LSTRLEN(*str) + blen[0] + (int)occ*blen[1];
	if ( !str[LSTR_ILEN] )
		str[LSTR_ILEN] = tilen;
	else if ( tilen > str[LSTR_ILEN] )
		log_msg( LOG_WARN, "short ilen %d < %d",
			str[LSTR_ILEN], tilen );
	LOG_DBG( LOG_ALL, "%08x xrlo %08x xl %d il %d",
		str[0], str[1], str[2], str[3] );
	return ret;
}	/* lstr_auto */