+++ /dev/null
-/*
- 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: openisis.c,v 1.67 2003/06/03 11:25:02 kripke Exp $
- main file of openisis executable.
-*/
-
-#ifdef HAVE_PTHREAD
-#define HAVE_THREADS
-#endif
-
-#include <assert.h>
-#include <stdlib.h> /* free */
-#include <string.h> /* strcmp */
-#ifdef WIN32
-# include <sys/timeb.h>
-# include <sys/types.h>
-# define timeval _timeb
-#else
-# include <unistd.h> /* gettimeofday */
-#endif
-#include <sys/time.h> /* gettimeofday */
-#ifdef HAVE_PTHREAD
-#include <pthread.h> /* threaded crashtest */
-#endif
-
-#include "openisis.h"
-
-/*
- temporary library includes for testing of functions
- that should later be accessible via openisis.h
-*/
-#include "lio.h"
-extern Db* ldb_getdb (int dbid);
-
-
-/* ************************************************************
- private types
-*/
-typedef enum { /* what to do */
- DO_DUMP,
- DO_SCAN, /* simple full scan */
- DO_SEARCH, /* basic index based searching */
- DO_TERMS, /* list terms */
- DO_CHECK, /* check db */
- DO_PERF, /* do random reads for performance checking */
- DO_CRASH, /* do multi-threaded crashtest */
- DO_SPLIT, /* split a field value */
- DO_STREAM, /* stream in records */
- DO_MFNLIST, /* fetch records by mfn list */
- DO_IFLOAD, /* read a lk2-style file from stdin */
- DO_SWLOAD, /* load stopwords */
- DO_IFDUMP, /* dump a lk2-style file to stdout */
- DO_FDT, /* print fdt */
- DO_VUTF /* validate UTF-8 input */
-} todo;
-
-typedef enum {
- FMT_MFN, /* rowid only */
- FMT_MFNF, /* rowid, 1st field */
- FMT_PROP, /* property style */
- FMT_TXT, /* plaintext masterfile style */
- FMT_TXTW /* plaintext masterfile style with W lines */
-} format;
-
-typedef enum {
- IFM_DUMP,
- IFM_TAB,
- IFM_OLD, /* dump old index */
- IFM_COPY, /* copy old index */
- IFM_CHK /* check (new oxi) index */
-} ifmode;
-
-
-/* ************************************************************
- private data
-*/
-static const char *pft;
-static const char **term, **val;
-static OpenIsisSet *post;
-int nterm, nval;
-static int db = -1, wdb = -1, append = 0, idxall = 0;
-
-/* ************************************************************
- private functions
-*/
-static int argchk ( const char *param, const char *n, const char *v )
-{
- return strcmp( param, n ) ? 0 : v ? 1 :
- (openIsisSMsg( OPENISIS_ERR_INVAL, "no value for param '%s'", param ), 0);
-} /* argchk */
-
-
-static int print ( OpenIsisRec *r, int freeit, format f )
-{
- union { OpenIsisRec r; char buf[10000]; } x;
- int i, ret;
- if ( ! r ) {
- if ( FMT_TXT == f )
- openIsisSMsg( 1, "\n" );
- return -1;
- }
- ret = r->rowid;
- if ( pft ) {
- OpenIsisRec *q;
- OPENISIS_INITBUF(x);
- q = openIsisFmt( &x.r, pft, r );
- if ( freeit )
- free( r );
- freeit = q != &x.r;
- r = q;
- }
- if ( FMT_MFN == f )
- openIsisSMsg( 1, "%d\n", r->rowid );
- else if ( FMT_MFNF == f )
- openIsisSMsg( 1, "%d %.*s\n", r->rowid,
- 0 == r->len ? 1 : (int)r->field[0].len,
- 0 == r->len ? "-" : r->field[0].val );
- else if ( FMT_TXT <= f ) {
- openIsisSMsg( 1, "\n" ); /* blank line */
- if ( FMT_TXTW == f )
- openIsisSMsg( 1, "W\t%d\n", r->rowid );
- for ( i=0; i<r->len; i++ ) {
- if ( r->field[i].val )
- openIsisSMsg( 1, "%d\t%.*s\n", r->field[i].tag,
- (int)r->field[i].len, r->field[i].val );
- else
- openIsisSMsg( 1, "%d\t%d\n", r->field[i].tag, r->field[i].len );
- }
- } else for ( i=0; i<r->len; i++ ) {
- if ( ! r->field[i].val ) { /* shouldn't happen -- numeric ? */
- openIsisSMsg( 1, "%d.?=%d\n", r->rowid, r->field[i].len );
- continue;
- }
- openIsisSMsg( 1, "%d.%d=%.*s\n", r->rowid, r->field[i].tag,
- (int)r->field[i].len, r->field[i].val );
- if ( r->field[i].len && '^' == *r->field[i].val ) { /* split subfields */
- OpenIsisRec *rf = openIsisReadField( 0, r->field+i );
- if ( rf ) {
- int j;
- for ( j=0; j<rf->len; j++ )
- openIsisSMsg( 1, "%d.%d.%c=%.*s\n",
- r->rowid, r->field[i].tag,
- (0x60 & (int)rf->field[j].tag ) ?
- (int)rf->field[j].tag : ' ',
- (int)rf->field[j].len, rf->field[j].val );
- free( rf );
- }
- }
- }
- if ( 0 <= wdb ) {
- OpenIsisRec *q = 0;
- int ok;
- if ( append )
- r->rowid = 0;
- if ( idxall && r != &x.r ) { /* add index entries for all fields */
- OPENISIS_INITBUF(x);
- q = &x.r;
- for ( i=0; i<r->len; i++ ) {
- char hit[64];
- OpenIsisField *fld = r->field + i;
- sprintf( hit, "%d.%d.%d.1 ", r->rowid, fld->tag, i );
- OPENISIS_RADDS( q, OPENISIS_XHIT, hit, q != &x.r );
- OPENISIS_RCAT( q, fld->val, fld->len, q != &x.r );
- }
- }
- ok = openIsisDWritex( wdb, r, q );
- openIsisSMsg( 1, "wrote mfn %d (%d)\n", r->rowid, ok );
- }
- if ( freeit )
- free( r );
- return ret;
-} /* print */
-
-
-static void printid ( int id, format f )
-{
- if ( FMT_MFN == f && 0 > wdb )
- openIsisSMsg( 1, "%d\n", id );
- else
- print( openIsisReadRow( db, id ), !0, f );
-} /* printid */
-
-
-static int printlk2 ( void *me, OpenIsisKey *key, OpenIsisHit *hit )
-{
- (void)me;
- if ( key && hit )
- /* 30 key BLANK 7 mfn BLANK 5 tag BLANK 4 occ BLANK 4 pos*/
- openIsisSMsg( 1, "%-30.*s %7u %5u %4u %4u\n",
- key->len, key->byt, hit->mfn, hit->tag, hit->occ, hit->pos );
- return 0;
-} /* printlk2 */
-
-
-static int printtab ( void *me, OpenIsisKey *key, OpenIsisHit *hit )
-{
- (void)me;
- if ( key && hit )
- /* 30 key BLANK 7 mfn BLANK 5 tag BLANK 4 occ BLANK 4 pos*/
- openIsisSMsg( 1, "%.*s\t%u\t%u\t%u\t%u\n",
- key->len, key->byt, hit->mfn, hit->tag, hit->occ, hit->pos );
- return 0;
-} /* printtab */
-
-
-/* timing utility. set the timeval, return milliseconds since last call. */
-#ifdef WIN32
-static int millis ( struct _timeb *tb )
-{
- struct _timeb otb = *tb;
- _ftime( tb );
- return (tb->time - otb.time)*1000 + (tb->millitm - otb.millitm);
-} /* millis */
-#else
-static int millis ( struct timeval *tv )
-{
- struct timeval otv = *tv;
- gettimeofday( tv, 0 );
- return (tv->tv_sec - otv.tv_sec)*1000 + (tv->tv_usec - otv.tv_usec)/1000;
-} /* millis */
-#endif
-
-#ifdef HAVE_PTHREAD
-int myOpenIsisLockFunc ( int lock )
-{
- static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; /* the "fast" kind */
- static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
- /*
- LOG_DBG( LOG_ERROR, "thread %d op 0x%08x", (int)pthread_self(), lock );
- */
- switch ( OPENISIS_WAIT & lock ) {
- case OPENISIS_RELE: return pthread_mutex_unlock( &mut );
- case OPENISIS_LOCK: return pthread_mutex_lock( &mut );
- case OPENISIS_WAKE: return pthread_cond_broadcast( &cond );
- case OPENISIS_WAIT: return pthread_cond_wait( &cond, &mut );
- }
- return -1;
-}
-#else
-# define myOpenIsisLockFunc 0
-#endif
-
-typedef struct {
- int start;
-} threadarg;
-
-/* (p)thread routine */
-static void * run ( void *arg )
-{
- struct timeval tv;
- int m;
- threadarg *my = (threadarg *)arg;
- int start = my->start;
- int i;
-
- millis( &tv );
- for ( i=start+1; i++!=start; ) {
- int j;
- if ( i >= nterm )
- i = 0;
- for ( j=0; j<post[i].len; j++ ) {
- int mfn = post[i].id[j];
- OpenIsisRec *r = openIsisReadRow( db, mfn );
- if ( ! r ) {
- openIsisSMsg( 2, "no rec %d\n", mfn );
- continue;
- }
- if ( 0 >= r->len )
- openIsisSMsg( 2, "no fields for %d\n", mfn );
- else if ( r->field[0].len != (int)strlen(val[mfn])
- || memcmp( r->field[0].val, val[mfn], r->field[0].len )
- )
- openIsisSMsg( 2, "mismatch on %d\n", mfn );
- free( r );
- }
- }
- m = millis(&tv);
- openIsisSMsg( 1, "thread %d@%d terminated after %.3f seconds\n",
-#ifdef HAVE_THREADS
- (int)pthread_self()
-#else
- 0L
-#endif
- , start, m/1000. );
- return (void *)m;
-} /* run */
-
-
-/* multithreaded crashtest */
-static int crash ( const char *pre )
-{
- struct timeval tv;
- union { OpenIsisRec r; char buf[10000]; } x;
- int l;
- int p = 0;
- int i, pass;
- int fd = 2;
- threadarg def;
-
- millis( &tv );
- x.r.len = 0;
- x.r.bytes = sizeof(x);
- nterm = 0;
- while ( openIsisTerm( &x.r, db, pre ) && x.r.len )
- nterm += x.r.len;
- openIsisSMsg( fd, "%d terms\n", nterm );
- openIsisSMsg( fd, "%.3f sec\n", millis(&tv)/1000. );
-
- term = (const char **)malloc( nterm * sizeof(*term) );
- post = (OpenIsisSet *)malloc( nterm * sizeof(*post) );
- nterm = 0;
- nval = 0;
- while ( openIsisTerm( &x.r, db, pre ) && x.r.len ) {
- for ( i=0; i<x.r.len; i++, nterm++ ) {
- int cnt;
- OpenIsisSet *set = post+nterm;
- char *c = malloc( x.r.field[i].len + 1 );
-
- memcpy( c, x.r.field[i].val, x.r.field[i].len );
- c[ x.r.field[i].len ] = 0;
- term[ nterm ] = c;
-
- set->len = 0;
- openIsisQuery( set, db, c, OPENISIS_QRY_KEYEQ, 0 );
- if ( 0 >= set->len ) {
- openIsisSMsg( 2, "no results for '%s'\n", c );
- return 1;
- }
- for ( cnt = 0; cnt < set->len; cnt++ )
- if ( nval < set->id[cnt] )
- nval = set->id[cnt];
- p += set->len;
- }
- }
- openIsisSMsg( fd, "%d postings max mfn %d\n", p, nval );
- openIsisSMsg( fd, "%.3f sec\n", millis(&tv)/1000. );
-
- val = (const char **)malloc( (1+nval) * sizeof(*val) );
- for ( i=1; i<=nval; i++ ) {
- OpenIsisRec *r = openIsisReadRow( db, i );
- val[i] = 0;
- if ( ! r ) {
- openIsisSMsg( 2, "no rec %d\n", i );
- continue;
- }
- if ( 0 < r->len ) {
- char *c = malloc( r->field[0].len + 1 );
-
- memcpy( c, r->field[0].val, r->field[0].len );
- c[ r->field[0].len ] = 0;
- val[i] = c;
- }
- free( r );
- }
- l = millis(&tv);
- openIsisSMsg( fd, "sequential read %d rows in %.3f seconds %d rows per sec\n",
- nval, l/1000., nval*1000/(l?l:1) );
-
- def.start = 0;
- i = 0;
- run( &def );
- l = millis(&tv);
- run( &def );
- l = millis(&tv);
- run( &def );
- l = millis(&tv);
- openIsisSMsg( fd, "in-thread run in %.3f seconds %d rows per sec\n",
- l/1000., p*1000/(l?l:1) );
-#ifdef HAVE_THREADS
-#define passes 3
- {
- static int nThreads[] = { 8, 2, 1, 4 };
- int res[ sizeof(nThreads)/sizeof(nThreads[0]) ];
- pthread_t th[ 8 /* max. nThreads */ ];
- threadarg arg[ sizeof(th)/sizeof(th[0]) ];
- int j;
-
-
- for ( i=0; i<(int)(sizeof(nThreads)/sizeof(nThreads[0])); i++ )
- res[i] = 0;
- for ( j=0; j<(int)(sizeof(th)/sizeof(th[0])); j++ )
-#if 0
- if ( ! (arg[j].ses = openIsisSesGet( -1, 0 )) ) {
- openIsisSMsg( fd, "could not get %dth session\n", j );
- return 1;
- }
-#endif
- for ( pass=0; pass<passes; pass++ )
- for ( i=0; i<(int)(sizeof(nThreads)/sizeof(nThreads[0])); i++ ) {
- int rps, avg;
- millis(&tv);
- assert( nThreads[i] <= (int)(sizeof(th)/sizeof(th[0])) );
- for ( j=0; j<nThreads[i]; j++ ) {
- arg[j].start = j*nterm/nThreads[i];
- if ( pthread_create( th+j, 0, run, arg+j ) )
- th[j] = (pthread_t)0;
- }
- openIsisSMsg( fd, "started %d threads\n", nThreads[i] );
- avg = 0;
- for ( j=0; j<nThreads[i]; j++ ) {
- int t;
- pthread_join( th[j], (void**)&t );
- avg += t;
- }
- avg /= nThreads[i];
- l = millis(&tv);
- rps = (int)(nThreads[i] * p * 1000 / avg);
- openIsisSMsg( fd, "joined %d threads avg %.3f after %.3f seconds %d rows per sec\n",
- nThreads[i], avg/1000., l/1000., rps );
- res[i] += rps;
- }
- for ( i=0; i<(int)(sizeof(nThreads)/sizeof(nThreads[0])); i++ )
- openIsisSMsg( fd, "%d threads %d rows per sec\n", nThreads[i], res[i]/passes );
- }
-#else
- (void)pass; /* avoid compiler warning */
-#endif /* HAVE_THREADS */
- return 0;
-} /* crash */
-
-
-/* ************************************************************
- package functions
-*/
-/* ************************************************************
- public functions
-*/
-int main ( int argc, const char **argv )
-{
- int ret = 0;
- int i,intarg=0;
- todo what = DO_DUMP;
- format fmt = FMT_TXT;
- int check = OPENISIS_CHK_FIX;
- int searchmode = OPENISIS_QRY_KEYAT;
- int idxmode = OPENISIS_IDXPF;
- const char *search = 0;
- const char *idxto = 0;
- int needdb = !0;
- const char *dowrite = 0;
- ifmode ifm = IFM_DUMP;
- OpenIsisRec *argr;
- OpenIsisDb *odb;
-
- /* initialize minimal env */
- openIsisCOpen(0);
- argr = openIsisRSet( 0,
- OPENISIS_RFDT|OPENISIS_RARGV|OPENISIS_RIGN | (argc-1),
- openIsisFdtSyspar, argv+1 );
-
- if ( 2 == argc && ! strcmp("-version",argv[1]) ) {
- openIsisSMsg( 0, "%s\n", OPENISIS_VERSION );
- goto bye;
- }
- /* check options ... */
- for ( i=0; i < argc; ) {
- const char *n = argv[i], *v = 0;
- assert( n );
- if ( '-' == n[0] )
- n++;
- if ( 1 == argc - i || '-' == argv[i+1][0] ) { /* no value */
- i++;
- } else {
- v = argv[i+1];
- assert( v );
- i += 2;
- }
-
- if ( argchk("logfile",n,v) )
- openIsisLog( '=', v );
- else if ( argchk("v",n,v) )
- openIsisLog( *v, 0 );
- else if ( argchk("scan",n,v) ) {
- what = DO_SCAN;
- search = v;
- }
- else if ( argchk("search",n,v) ) {
- what = DO_SEARCH;
- search = v;
- }
- else if ( argchk("upto",n,v) ) {
- idxmode = OPENISIS_IDXUPTO;
- idxto = v;
- }
- else if ( argchk("incl",n,v) ) {
- idxmode = OPENISIS_IDXINCL;
- idxto = v;
- }
- else if ( argchk("query",n,v) ) {
- what = DO_SEARCH;
- searchmode = OPENISIS_QRY_SIMPLE;
- search = v;
- }
- else if ( argchk("terms",n,v) ) {
- what = DO_TERMS;
- search = v;
- }
- else if ( argchk("perf",n,v) ) {
- what = DO_PERF;
- intarg = atoi(v);
- }
- else if ( argchk("crash",n,v) ) {
- what = DO_CRASH;
- search = v;
- }
- else if ( argchk("split",n,v) ) {
- what = DO_SPLIT;
- search = v;
- needdb = 0;
- }
- else if ( argchk("fmt",n,v) ) {
- if ( ! strcmp("mfn",v) )
- fmt =FMT_MFN;
- else if ( ! strcmp("mfnf",v) )
- fmt =FMT_MFNF;
- else if ( ! strcmp("prop",v) )
- fmt =FMT_PROP;
- else if ( ! strcmp("txt",v) )
- fmt =FMT_TXT;
- else if ( ! strcmp("txtw",v) )
- fmt =FMT_TXTW;
- }
- else if ( ! strcmp("check",n) )
- what = DO_CHECK;
- else if ( ! strcmp("vutf",n) ) {
- what = DO_VUTF;
- needdb = 0;
- } else if ( argchk("pft",n,v) )
- pft = v;
- else if ( ! strcmp("stream",n) ) {
- what = DO_STREAM;
- needdb = 0;
- } else if ( argchk("write",n,v) )
- dowrite = v;
- else if ( argchk("append",n,v) ) {
- dowrite = v;
- append = !0;
- } else if ( ! strcmp("idxall",n) )
- idxall = !0;
- else if ( ! strcmp("mfnlist",n) )
- what = DO_MFNLIST;
- else if ( argchk("ifload",n,v) ) {
- what = DO_IFLOAD;
- intarg = atoi(v);
- } else if ( ! strcmp("swload",n) ) {
- what = DO_SWLOAD;
- } else if ( ! strcmp("ifadd",n) ) {
- what = DO_IFLOAD;
- intarg = -1;
- } else if ( ! strcmp("ifdel",n) ) {
- what = DO_IFLOAD;
- intarg = -2;
- } else if ( ! strcmp("ifcopy",n) ) {
- what = DO_IFDUMP;
- ifm = IFM_COPY;
- } else if ( ! strcmp("ifchk",n) ) {
- what = DO_IFDUMP;
- ifm = IFM_CHK;
- } else if ( ! strcmp("iftab",n) ) {
- what = DO_IFDUMP;
- ifm = IFM_TAB;
- } else if ( ! strcmp("ifdump",n) )
- what = DO_IFDUMP;
- else if ( ! strcmp("noxi",n) )
- ifm = IFM_OLD;
- else if ( argchk("out",n,v) ) {
- char buf[256] = ">";
- int l = strlen(v);
- if ( l < 254 ) {
- memcpy( buf+1, v, l );
- buf[l+2] = 0;
- openIsisSOpen( buf, 0, 0 );
- }
- }
- else if ( argchk("fdtdump",n,v) ) {
- what = DO_FDT;
- intarg = atoi(v);
- }
- } /* while argc */
-
-
- if ( needdb && 0 > (db = openIsisOpen( 0, argv + 1, argc - 1 )) ) {
- openIsisSMsg( 2,
- "openisis " OPENISIS_VERSION "\n\n"
- "please specify a valid database with -db, e.g.\n"
- "-db /winisis/data/cds\n"
- "\n"
- "other options are:\n"
- "-search term search for term\n"
- "-query \"query\" run a query like \"water * plant\"\n"
- "-terms term list terms matching term (e.g. plant$)\n"
- );
- /* warning: string length `580' is greater than the minimum length
- * `509' ISO C89 is required to support
- */
- openIsisSMsg( 2,
- "-fmt mfn for a search or query, list only the mfn\n"
- "-fmt mfnf for a search or query, list the mfn and 1st field\n"
- "-pft \"pft\" use printformat (currently very limited)\n"
- "-write dbpath specify a db where records are written to\n"
- "-mfnlist read mfns from stdin\n"
- "-ifload pctfree read .lk2-index from stdin\n"
- "\n"
- "default output format is one field per line like tag<TAB>value\n"
- );
- ret = 1;
- goto bye;
- }
-
- if ( dowrite && 0 > (wdb = openIsisOpen( dowrite, 0, 0 )) ) {
- openIsisSMsg( 2, "could not open write target db '%s'\n", dowrite );
- ret = 2;
- goto bye;
- }
-
-
- switch ( what ) {
- case DO_DUMP: {
- int max = openIsisMaxRowid( db );
- int rowid;
- for ( rowid = 1; rowid <= max; rowid++ )
- printid( rowid, fmt );
- } break; /* DO_DUMP */
- case DO_MFNLIST: {
- char *buf = 0;
- int l;
- while ( 0 <= (l = openIsisSReadln( &buf )) ) {
- int id = 0;
- while ( l-- )
- id = 10*id + *buf++ - '0';
- if ( id )
- printid( id, fmt );
- }
- } break; /* DO_MFNLIST */
- case DO_SCAN: {
- int max = openIsisMaxRowid( db );
- int rowid;
- for ( rowid = 1; 0 < rowid && rowid <= max; rowid++ )
- rowid = print( openIsisScan( db, rowid, 0, search ), !0, fmt );
- } break; /* DO_SCAN */
- case DO_SEARCH: {
- int cnt;
- OpenIsisSet set;
- set.len = 0;
- openIsisQuery( &set, db, search, searchmode, 0 );
- if ( 0 >= set.len ) {
- openIsisSMsg( 2, "no results for '%s'\n", search );
- ret = 1;
- goto bye;
- }
- /* openIsisSMsg( 2, "%d\trows for\t%s\n", set.len, search ); */
- for ( cnt = 0; cnt < set.len; cnt++ )
- printid( set.id[cnt], fmt );
- } break; /* DO_SEARCH */
- case DO_TERMS: {
- union { OpenIsisRec r; char buf[10000]; } x;
- x.r.len = 0;
- x.r.bytes = sizeof(x);
- while ( openIsisTerm( &x.r, db, search ) && x.r.len ) {
- /* openIsisSMsg( 1, "%d terms\n", x.r.len ); */
- for ( i=0; i<x.r.len; i++ )
- openIsisSMsg( 1, "%.*s\n", (int)x.r.field[i].len, x.r.field[i].val );
- }
- } break; /* DO_TERMS */
- case DO_PERF: {
- int max = openIsisMaxRowid( db );
- while ( 0 < intarg-- ) {
- OpenIsisRec *r = openIsisReadRow( db, 1+((int)rand() % max) );
- free( r );
- }
- } break; /* DO_PERF */
- case DO_CHECK:
- ret = openIsisCheck( db, check );
- goto bye;
- case DO_CRASH:
- ret = crash( search );
- goto bye;
- case DO_SPLIT: {
- OpenIsisField f;
- OpenIsisRec *r;
- f.tag = 24; f.val = search; f.len = strlen(search);
- r = openIsisReadField( 0, &f );
- if ( r )
- for ( i=0; i<r->len; i++ )
- openIsisSMsg( 1, "%c=%.*s\n", (int)r->field[i].tag,
- (int)r->field[i].len, r->field[i].val );
- } break;
- case DO_STREAM: {
- OpenIsisIos ios;
- OpenIsisRecStream rs = { 0, OPENISIS_STOPONEMPTY, 0, 0, 0 };
- LIO_SINIT( &ios, lio_stdio, "stdin", LIO_IN );
- rs.in = &ios; /* some gcc versions need it this way */
- while ( 0 < (i = openIsisSGetr( &rs )) )
- print( rs.rec, 0, fmt );
- } break;
- case DO_IFLOAD:
- case DO_SWLOAD: {
- OpenIsisKey key;
- OpenIsisHit hit;
- OpenIsisIndex idx = openIsisIdxOpen( db, intarg );
- char *buf = 0;
- int l, lines = 0;
-
- memset( &hit, 0, sizeof(hit) );
- hit.dbn = (-2 == intarg) ? 0xffff : 0; /* secret key for ifdel */
- while ( 0 <= (l = openIsisSReadln( &buf )) && buf ) {
- char *t = memchr( buf, '\t', l );
- if ( DO_SWLOAD == what ) {
- memcpy( key.byt, buf, key.len = (unsigned char)l );
- } else if ( t ) { /* tab delimited */
- key.len = (unsigned char)(t - buf);
- memcpy( key.byt, buf, key.len );
- if ( 0 >= (l -= t-buf+1) || !(t = memchr( buf=t+1, '\t', l )) )
- continue;
- hit.mfn = (unsigned) openIsisA2i( buf, t-buf );
- if ( 0 >= (l -= t-buf+1) || !(t = memchr( buf=t+1, '\t', l )) )
- continue;
- hit.tag = (unsigned short) openIsisA2i( buf, t-buf );
- if ( 0 >= (l -= t-buf+1) || !(t = memchr( buf=t+1, '\t', l )) )
- continue;
- hit.occ = (unsigned short) openIsisA2i( buf, t-buf );
- if ( 0 >= (l -= t-buf+1) )
- continue;
- hit.pos = (unsigned short) openIsisA2i( t+1, l );
- } else {
- /* 10/30 key BLANK 7 mfn BLANK 5 tag BLANK 4 occ BLANK 4 pos*/
- int eok = l - 24; /* pos of blank after key, 10 or 30 */
- if ( 54 != l && 34 != l ) {
- openIsisSMsg( OPENISIS_ERR_INVAL,
- "bad ifload input len %d, want 34 or54 bytes + newline\n", l );
- break;
- }
- for ( i=eok-1; ' ' == buf[i] && i--; )
- ;
- key.len = (unsigned char) (++i);
- memcpy( key.byt, buf, key.len );
- log_msg( LOG_VERBOSE, "'%.*s'", 7, buf+eok+1 );
- hit.mfn = (unsigned) openIsisA2i( buf+eok+1, 7 );
- hit.tag = (unsigned short)openIsisA2i( buf+eok+9, 5 );
- hit.occ = (unsigned short)openIsisA2i( buf+eok+15, 4 );
- hit.pos = (unsigned short)openIsisA2i( buf+eok+20, 4 );
- }
- log_msg( LOG_VERBOSE, "'%.*s' %d %d %d %d",
- key.len, key.byt, hit.mfn, hit.tag, hit.occ, hit.pos );
- if ( openIsisIdxAdd( idx, &key, &hit ) )
- break;
- if ( !(++lines & 0x3ff) )
- log_msg( LOG_INFO, "%dK lines", lines >> 10 );
- }
- openIsisIdxDone( idx );
- } break;
- case DO_IFDUMP: {
- OpenIsisIdxLoop l;
- memset( &l, 0, sizeof(l) );
- l.flg = idxmode;
- switch ( ifm ) {
- case IFM_OLD:
- l.flg |= OPENISIS_IDXTRAD;
- case IFM_DUMP:
- l.cb = (OpenIsisIdxCb*)printlk2;
- break;
- case IFM_TAB:
- l.cb = (OpenIsisIdxCb*)printtab;
- break;
- case IFM_COPY:
- l.flg |= OPENISIS_IDXTRAD;
- l.me = openIsisIdxOpen( 0 <= wdb ? wdb : db, 0 );
- l.cb = (OpenIsisIdxCb*)openIsisIdxAdd;
- break;
- case IFM_CHK:
- /* nuttin */
- break;
- }
- if ( search )
- memcpy( l.key.byt, search,
- l.key.len = (unsigned char)strlen( search ) );
- if ( idxto )
- memcpy( l.to.byt, idxto,
- l.to.len = (unsigned char)strlen( idxto ) );
- openIsisIdxLoop( db, &l );
- if ( IFM_COPY == ifm )
- openIsisIdxDone( (OpenIsisIndex)l.me );
- } break;
- case DO_FDT:
- odb = ldb_getdb( db );
- if ( odb && odb->fdt )
- print( openIsisFFdt2Rec( odb->fdt, 0, intarg ), 0, fmt );
- break;
- case DO_VUTF: {
- char buf[1024];
- int t = 0, f = 0, g;
- while ( 0 < (g = lio_read( &lio_in, buf, sizeof(buf) )) ) {
- int l = openIsisValidUTF8( buf, g, &f );
- if ( l ) {
- openIsisSMsg( OPENISIS_ERR_INVAL,
- "at total %d = %d+%d\n", l-1+t, l-1, t );
- ret = 1;
- goto bye;
- }
- t += g;
- }
- }
- } /* switch ( what ) */
-bye:
- if ( 0 <= db )
- openIsisClose( db );
- if ( 0 <= wdb )
- openIsisClose( wdb );
-
- /* at least with WINE,
- atexit cleanup is not performed
- unless we explicitly call exit :(
- */
- exit( ret );
- return ret;
-} /* openisis main */