cleanup and documentation updates
[webpac] / openisis / openisis.c
diff --git a/openisis/openisis.c b/openisis/openisis.c
deleted file mode 100644 (file)
index 4640f7f..0000000
+++ /dev/null
@@ -1,837 +0,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: 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 */