/*
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 */