dslinux/user/pixil/pixilDT/NxDb Makefile NxDb.dsp NxDb.dsw blkio.c db.c index.c nxdb.cxx use.c

amadeus dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:26:49 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/pixil/pixilDT/NxDb
In directory antilope:/tmp/cvs-serv11916/pixilDT/NxDb

Added Files:
	Makefile NxDb.dsp NxDb.dsw blkio.c db.c index.c nxdb.cxx use.c 
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it

--- NEW FILE: NxDb.dsw ---
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!

###############################################################################

Project: "NxDb"=.\NxDb.dsp - Package Owner=<4>

Package=<5>
{{{
}}}

Package=<4>
{{{
}}}

###############################################################################

Global:

Package=<5>
{{{
}}}

Package=<3>
{{{
}}}

###############################################################################


--- NEW FILE: use.c ---
/*                                                                       
 * Copyright (c) 2003 Century Software, Inc.   All Rights Reserved.     
 *                                                                       
 * This file is part of the PIXIL Operating Environment                 
 *                                                                       
 * The use, copying and distribution of this file is governed by one    
 * of two licenses, the PIXIL Commercial License, or the GNU General    
 * Public License, version 2.                                           
 *                                                                       
 * Licensees holding a valid PIXIL Commercial License may use this file 
 * in accordance with the PIXIL Commercial License Agreement provided   
 * with the Software. Others are governed under the terms of the GNU   
 * General Public License version 2.                                    
 *                                                                       
 * This file may be distributed and/or modified under the terms of the  
 * GNU General Public License version 2 as published by the Free        
 * Software Foundation and appearing in the file LICENSE.GPL included   
 * in the packaging of this file.                                      
 *                                                                       
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING  
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A            
 * PARTICULAR PURPOSE.                                                  
 *                                                                       
 * RESTRICTED RIGHTS LEGEND                                             
 *                                                                     
 * Use, duplication, or disclosure by the government is subject to      
 * restriction as set forth in paragraph (b)(3)(b) of the Rights in     
 * Technical Data and Computer Software clause in DAR 7-104.9(a).       
 *                                                                      
 * See http://www.pixil.org/gpl/ for GPL licensing       
 * information.                                                         
 *                                                                      
 * See http://www.pixil.org/license.html or              
 * email cetsales at centurysoftware.com for information about the PIXIL   
 * Commercial License Agreement, or if any conditions of this licensing 
 * are not clear to you.                                                
 */

#include <stdio.h>
#include <string.h>
#include "file.h"

#include "VCMemoryLeak.h"

/*
 * use.c - common database record get/put routines
 *
 * from 8/6/85 mt15b
 */

/* local data*/
static struct usefile usefile[NUSEFILES];
static struct field *p;
static char *cp;

/* local procs*/
static void chguse(int fileno);
static void chkuse(int fileno);
static void setpcp(int var);

int
get16(char *addr)
{
    return ((unsigned char) addr[0]) | (((int) (unsigned char) addr[1]) << 8);
}

void
put16(char *addr, unsigned short val16)
{

    *addr++ = val16;
    *addr = val16 >> 8;
}


long
get32(char *addr)
{

    return ((unsigned char) addr[0]) |
	(((long) (unsigned char) addr[1]) << 8) |
	(((long) (unsigned char) addr[2]) << 16) |
	(((long) (unsigned char) addr[3]) << 24);
}


void
put32(char *addr, long val32)
{

    *addr++ = val32;
    *addr++ = val32 >> 8;
    *addr++ = val32 >> 16;
    *addr = val32 >> 24;
}


void
use(int fileno, struct fildes *fp, struct ndxfile *nfp)
{

    chguse(fileno);
    usefile[fileno].fp = fp;
    if (fp != NULL) {
	fp->ndxfp = nfp;
    }
    usefile[fileno].recno = -1;
}

static void
chguse(int fileno)
{
    if (usefile[fileno].uchanged) {
	putrec(usefile[fileno].recno, usefile[fileno].fp,
	       usefile[fileno].rbuf);
	usefile[fileno].uchanged = 0;
    }
}

static void
chkuse(int fileno)
{
    struct fildes *fp;

    if (fileno < 0 || fileno > NUSEFILES)
	fatal(5);		/* chkuse: bad fileno */
    fp = usefile[fileno].fp;
    if (fp->currec != usefile[fileno].recno) {
	chguse(fileno);
	getrec(fp->currec, fp, usefile[fileno].rbuf);
	usefile[fileno].recno = fp->currec;
    }
}

/*
 * return value of file variable
 * on entry, hi byte of var is fileno, lo byte is fieldno
 */
char *
val(int var)
{
    register int len;
    static char varbuf[65];	/* max var len is 64! */

    setpcp(var);
    if ((len = p->size) > 64)
	len = 64;
    fcopy(cp, varbuf, len);
    return (varbuf);
}

short
ival(int var)
{
    setpcp(var);
    return (get16(cp));
}

long
lval(int var)
{
    setpcp(var);
    return (get32(cp));
}

void
replace(int var, union w newval)
{
    setpcp(var);
    switch (p->type) {
    case 'c':
	memcpy(cp, newval.ptr, p->size);
	break;
    case 'd':
    case 'i':
	put16(cp, newval.word);
	break;
    case 'l':
	put32(cp, newval.lword);
	break;
    }
    usefile[var >> 8].uchanged = 1;
}

int
find(int fileno, char *key)
{
    struct fildes *fp;

    fp = usefile[fileno].fp;
    return (fp->currec = search(key, fp->ndxfp, 0));
}

void
store(void *dst, int var)
{
    setpcp(var);
    switch (p->type) {
    case 'c':
	fcopy(cp, (char *) dst, p->size);
	break;
    case 'd':
    case 'i':
	put16((char *) dst, get16(cp));
	break;
    case 'l':
	put32((char *) dst, get32(cp));
	break;
    }
}

static void
setpcp(int var)
{
    register int fileno, fieldno;

    fileno = var >> 8;
    fieldno = var & 0xff;
    chkuse(fileno);
    p = &usefile[fileno].fp->fieldp[fieldno];
    cp = &usefile[fileno].rbuf[p->offset];
}

/*
 * delete current record in usefile
 */
void
udelrec(int fileno)
{
    chkuse(fileno);
    usefile[fileno].rbuf[0] = '*';
    usefile[fileno].uchanged = 1;
}

/*
 * copy a string field replacing nulls with blanks
 */
char *
fcopy(char *src, char *dst, int len)
{
#if 0
    while (len--)
	if (*src)
	    *dst++ = *src++;
	else {
	    *dst++ = ' ';
	    src++;
	}
    *dst++ = 0;			/* null terminate */
    return (dst);
#else
    while (len--)
	*dst++ = *src++;
    *dst++ = 0;
    return (dst);
#endif
}

--- NEW FILE: index.c ---
/*                                                                       
 * Copyright (c) 2003 Century Software, Inc.   All Rights Reserved.     
 *                                                                       
 * This file is part of the PIXIL Operating Environment                 
 *                                                                       
 * The use, copying and distribution of this file is governed by one    
 * of two licenses, the PIXIL Commercial License, or the GNU General    
 * Public License, version 2.                                           
 *                                                                       
 * Licensees holding a valid PIXIL Commercial License may use this file 
 * in accordance with the PIXIL Commercial License Agreement provided   
 * with the Software. Others are governed under the terms of the GNU   
 * General Public License version 2.                                    
 *                                                                       
 * This file may be distributed and/or modified under the terms of the  
 * GNU General Public License version 2 as published by the Free        
 * Software Foundation and appearing in the file LICENSE.GPL included   
 * in the packaging of this file.                                      
 *                                                                       
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING  
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A            
 * PARTICULAR PURPOSE.                                                  
 *                                                                       
 * RESTRICTED RIGHTS LEGEND                                             
 *                                                                     
 * Use, duplication, or disclosure by the government is subject to      
 * restriction as set forth in paragraph (b)(3)(b) of the Rights in     
 * Technical Data and Computer Software clause in DAR 7-104.9(a).       
 *                                                                      
 * See http://www.pixil.org/gpl/ for GPL licensing       
 * information.                                                         
 *                                                                      
 * See http://www.pixil.org/license.html or              
 * email cetsales at centurysoftware.com for information about the PIXIL   
 * Commercial License Agreement, or if any conditions of this licensing 
 * are not clear to you.                                                
 */

#include <stdio.h>
#include "file.h"

#include "VCMemoryLeak.h"

/*
 * index.c - B* tree index file access routines
 *
 * from 11/18/85 mt15b by greg haerr
 */
#define RECNOSIZE	sizeof(short)	/* sizeof record number */
/* leaf & ptr block struct*/
#define PAGETYPE(p)	(p->buf[ 0])	/* Leaf or Ptr, != 0 is ptr */
#define NKEYS(p)	(get16(&p->buf[ 1]))	/* # keys this page */
#define setNKEYS(p,v)	(put16(&p->buf[ 1],v))	/* # keys this page */
/* ptr block struct*/
#define BLK0(p)		(get16(&p->buf[ 3]))	/* blk 0 ptr */
#define setBLK0(p,v)	(put16(&p->buf[ 3],v))	/* blk 0 ptr */
#define PKEY1(p)	(&p->buf[ 5])	/* address of first key, pblk */
#define BLKNO(p)	(get16(&p[ gkeylen]))	/* address of next block at p */
#define setBLKNO(p,v)	(put16(&p[ gkeylen],v))	/* address of next block at p */
/* leaf block struct*/
#define FPTR(p)		(get16(&p->buf[ 3]))	/* forward block ptr */
#define setFPTR(p,v)	(put16(&p->buf[ 3],v))	/* forward block ptr */
#define BPTR(p)		(get16(&p->buf[ 5]))	/* backward block ptr */
#define setBPTR(p,v)	(put16(&p->buf[ 5],v))	/* backward block ptr */
#define LKEY1(p)	(&p->buf[ 7])	/* address of first key, lblk */
#define RECNO(p)	(get16(&p[ gkeylen]))	/* address of recno at p */
#define setRECNO(p,v)	(put16(&p[ gkeylen],v))	/* address of recno at p */
#define KEY1OFF		7	/* offset of key #1 in buf */
#define moveleft(s,d,c)	memcpy(d,s,c)
#define F_INT		02	/* char/integer index */
#define F_MULT		04	/* unique/multiple keys */
struct passup
{				/* key pass-up structure */
    char key[11];		/* key, max len = 10 */
    short pblkno;		/* block # */
};

/* local data*/
static char gkeylen;		/* global key length */
static char *gkey;		/* global key ptr */
static char gkeytyp;		/* key type, 0=char, 1=integer */
static struct ndxfile *gfp;	/* global index file */
static int gmode;		/* global mode, 0 = search only */
static int grec;		/* global rec# */

/* local procs*/
static int isrch(int blkno, struct passup *v);
static int dsrch(int blk, struct passup *v);
static void keycopy(char *src, char *dst);
static int keycomp(char *key);
static void moveright(char *asrc, char *adst, int cnt);
static int ierr(int n);

/*
 * search for key in index file fp, if mode != 0, insert as record #mode if
 * not found
 */
int
search(char *key, struct ndxfile *fp, int mode)
{
    register struct buffer *bp;
    register struct buffer *nbp;
    register char *p;
    register int n;
    struct passup v;
    short kbuf;

    gfp = fp;
    gmode = mode;
    gkeylen = gfp->keylen;
    if ((gkeytyp = (gfp->ftype & F_INT)) != 0) {
	gkey = (char *) &kbuf;
	put16((char *) &kbuf, (int) key);
    } else
	gkey = key;
    n = isrch(0, &v);
    if (gmode == 0)		/* search only */
	return (n);
    if (n) {			/* allocate new root node */
	//fprintf(stderr, "search: root passup key=%9s, blkno=%d\n", v.key, v.pblkno);
	if ((nbp = lockb(newblk((struct fildes *) gfp))) == NULL)
	    return (ierr(0));	/* isrch: new root bp fail */
	if ((bp = getblk(0, (struct fildes *) gfp)) == NULL) {
	    unlock(nbp);
	    return (ierr(1));	/* search: bp getblk fail */
	}
	memcpy(nbp->buf, bp->buf, BLKSIZ);	/* copy block 0 */
	PAGETYPE(bp) = 'P';
	setNKEYS(bp, 1);
	setBLK0(bp, nbp->blkno);
	p = PKEY1(bp);
	keycopy(v.key, p);
	setBLKNO(p, v.pblkno);
	bp->changed = 1;
	if (n = FPTR(nbp)) {
	    bp = getblk(n, (struct fildes *) gfp);
	    setBPTR(bp, nbp->blkno);
	    bp->changed = 1;
	}
	if (n = BPTR(nbp)) {
	    bp = getblk(n, (struct fildes *) gfp);
	    setFPTR(bp, nbp->blkno);
	    bp->changed = 1;
	}
	unlock(nbp);
    }
    return (gmode);
}

/*
 * recursive B* tree search (two level only for now)
 */
static int
isrch(int blkno, struct passup *v)
{
    register struct buffer *bp, *nbp;
    char *p, *ap;
    int n, r;
    struct passup u;

  again:
    if ((bp = getblk(blkno, (struct fildes *) gfp)) == NULL)
	return (ierr(2));	/* isrch: bp getblk fail */
    n = NKEYS(bp);
#ifdef UNIV
    if ((gfp == &FAndx2 || gfp == &FAndx3) && n == RECMAX - 5 && gmode) {
	printf("\007***Warning: 5 activities left, space to continue");
	chrin();
    }
    if ((gfp == &FAndx2 || gfp == &FAndx3) && n > RECMAX)
	return (fatal(8));
#endif
    if (PAGETYPE(bp) == 0) {	/* leaf node */
	p = LKEY1(bp);
	while (n > 0 && keycomp(p) < 0) {
	    p += gkeylen + 2;
	    n--;
	}
	if (gmode == 0) {	/* search only */
	    if ((gfp->ftype & F_MULT) && n <= 0)	/* mult keys */
		if ((blkno = FPTR(bp)) != 0) {
		    /*dprintf( "isrch: mult next blk"); */
		    goto again;
		}
	    if (n <= 0 || keycomp(p) != 0)
		return (0);
	    else {
		gfp->curblk = bp->blkno;
		gfp->curoff = NKEYS(bp) - n + 1;
		return (RECNO(p));
	    }
	}
	if (gfp->maxkeys > NKEYS(bp)) {	/* insert, no split needed */
	    while (n > 0 && keycomp(p) == 0) {
		p += gkeylen + 2;
		n--;
	    }
	    if (n != 0)
		moveright(p, p + gkeylen + 2, n * (gkeylen + 2));
	    keycopy(gkey, p);
	    setRECNO(p, gmode);	/* gmode = recno */
	    setNKEYS(bp, NKEYS(bp) + 1);
	    bp->changed = 1;
	    return (0);		/* no passup */
	} else {		/* insert, split leaf */
	    /*dprintf( "isrch: lnode split\n"); */
	    lockb(bp);
	    if ((nbp = lockb(newblk((struct fildes *) gfp))) == NULL) {
		unlock(bp);
		return (ierr(3));	/* isrch: nbp getblk fail */
	    }
	    r = (gfp->maxkeys + 1) / 2;
	    /* copy right page to new block */
	    memcpy(LKEY1(nbp),
		   LKEY1(bp) + (gkeylen + 2) * (gfp->maxkeys / 2),
		   (gkeylen + 2) * (gfp->maxkeys - (gfp->maxkeys / 2)));
	    setNKEYS(nbp, r);
	    setNKEYS(bp, r);
	    bp->changed = 1;
	    if (n >= r) {	/* insert left page */
		n -= r;
		setNKEYS(bp, NKEYS(bp) + 1);
	    } else {		/* insert right page */
		p = LKEY1(nbp) + (p - LKEY1(bp)) -
		    (gkeylen + 2) * (gfp->maxkeys / 2);
		setNKEYS(nbp, NKEYS(nbp) + 1);
	    }
	    if (n != 0)
		moveright(p, p + gkeylen + 2, n * (gkeylen + 2));
	    keycopy(gkey, p);
	    setRECNO(p, gmode);
	    setFPTR(nbp, n = FPTR(bp));
	    setFPTR(bp, nbp->blkno);
	    setBPTR(nbp, bp->blkno);
	    unlock(bp);
	    if (n != 0) {
		if ((bp = getblk(n, (struct fildes *) gfp)) == NULL) {
		    unlock(nbp);
		    return (ierr(4));	/* isrch: bptr getblk fail */
		}
		setBPTR(bp, nbp->blkno);
		bp->changed = 1;
	    }
	    keycopy(LKEY1(nbp), v->key);
	    v->pblkno = nbp->blkno;
	    unlock(nbp);
	    return (1);		/* passup */
	}
    } else {			/* ptr node */
	ap = p = PKEY1(bp);
	if (gfp->ftype & F_MULT)	/* multiple keys */
	    for (r = 0; r < n; r++) {
		if (keycomp(ap) >= 0)
		    break;
		p = ap;
		ap += gkeylen + 2;
	} else			/* unique keys */
	    for (r = 0; r < n; r++) {
		if (keycomp(ap) > 0)
		    break;
		p = ap;
		ap += gkeylen + 2;
	    }
	if (r == 0)
	    n = BLK0(bp);
	else
	    n = BLKNO(p);
	/*dprintf( "psrch %d\n", n); */
	lockb(bp);
	n = isrch(n, &u);
	unlock(bp);
	if (gmode == 0)
	    return (n);
	if (n) {		/* passup */
	    /*dprintf( "isrch: passup key=%9s, blkno=%d\n", u.key, u.pblkno); */
	    n = NKEYS(bp);
	    if (n >= gfp->maxkeys)
		return (ierr(5));	/* isrch: pnode overflow */
	    if (r < n)
		moveright(ap, ap + gkeylen + 2, (n - r) * (gkeylen + 2));
	    keycopy(u.key, ap);
	    setBLKNO(ap, u.pblkno);
	    setNKEYS(bp, NKEYS(bp) + 1);
	    bp->changed = 1;
	}
	return (0);
    }
}

/*
 * delete key with record # rec from index file fp
 */
int
Delete(char *key, int rec, struct ndxfile *fp)
{
    struct passup v;
    short kbuf;

    grec = rec;
    gfp = fp;
    gkeylen = gfp->keylen;
    if ((gkeytyp = (gfp->ftype & F_INT)) != 0) {
	gkey = (char *) &kbuf;
	put16((char *) &kbuf, (int) key);
    } else
	gkey = key;
    gfp->curblk = -1;
    dsrch(0, &v);
    return (grec);
}

/*
 * recursive B* tree delete
 */
static int
dsrch(int blk, struct passup *v)
{
    register struct buffer *bp, *nbp;
    char *p, *ap;
    int n, r;
    struct passup u;

  again:
    if ((bp = getblk(blk, (struct fildes *) gfp)) == NULL)
	return (0);
    n = NKEYS(bp);
    if (PAGETYPE(bp) == 0) {	/* root node is leaf node */
	p = LKEY1(bp);
	while (n > 0 && RECNO(p) != grec) {
	    if (keycomp(p) > 0)
		break;
	    p += gkeylen + 2;
	    n--;
	}
	if ((gfp->ftype & F_MULT) && n <= 0)	/* mult keys */
	    if ((blk = FPTR(bp)) != 0) {
		/*dprintf( "dsrch: mult nxt blk"); */
		goto again;
	    }
	if (n <= 0 || keycomp(p) != 0 || RECNO(p) != grec) {
	    grec = 0;
	    return (ierr(6));	/* dsrch: key not found */
	}
	if (n > 1)
	    moveleft(p + gkeylen + 2, p, (n - 1) * (gkeylen + 2));
	setNKEYS(bp, NKEYS(bp) - 1);
	bp->changed = 1;
	if ((NKEYS(bp) > gfp->maxkeys / 2) || (blk == 0))
	    return (0);		/* aok */
	lockb(bp);
	if ((r = FPTR(bp)) != 0) {	/* fwd blk not empty */
	    if ((nbp = getblk(r, (struct fildes *) gfp)) == NULL) {
		unlock(bp);
		return (ierr(7));	/* dsrch: nbp getblk fail */
	    }
	    p = LKEY1(bp) + (NKEYS(bp) * (gkeylen + 2));
	    ap = LKEY1(nbp);
	    if (NKEYS(nbp) > gfp->maxkeys / 2) {	/* annect 1 */
		/*dprintf( "dsrch: annect 1\n"); */
		memcpy(p, ap, gkeylen + 2);	/* copy key */
		setNKEYS(bp, NKEYS(bp) + 1);
		moveleft(ap + gkeylen + 2, ap,
			 (NKEYS(nbp) - 1) * (gkeylen + 2));
		setNKEYS(nbp, NKEYS(nbp) - 1);
		nbp->changed = 1;
		keycopy(ap, v->key);
		v->pblkno = nbp->blkno;
		unlock(bp);
		return (1);	/* change key in ptr blk */
	    }
	    /*dprintf( "dsrch: annect all\n"); */
	    v->pblkno = nbp->blkno;	/* save blk # to delete */
	    memcpy(p, ap, NKEYS(nbp) * (gkeylen + 2));	/* annect all */
	    setNKEYS(bp, NKEYS(bp) + NKEYS(nbp));
	    setFPTR(bp, r = FPTR(nbp));	/* relink fwd ptr */
	    unlock(bp);
	    if (r != 0) {
		n = bp->blkno;
		if ((bp = getblk(r, (struct fildes *) gfp)) == NULL) {
		    ierr(21);	/* dsrch: nbp fptr fail */
		    return (2);
		}
		setBPTR(bp, n);
		bp->changed = 1;
	    }
	    return (2);		/* delete blk # in ptr blk */
	}
	if (NKEYS(bp) == 0) {	/* fptr null, no keys */
	    /*dprintf( "dsrch: fptr null, no keys\n"); */
	    v->pblkno = bp->blkno;
	    r = BPTR(bp);	/* set bwd ptr to NULL */
	    unlock(bp);
	    if (r != 0) {
		if ((bp = getblk(r, (struct fildes *) gfp)) == NULL) {
		    ierr(22);	/* dsrch: nbp bptr fail */
		    return (2);
		}
		setFPTR(bp, 0);
		bp->changed = 1;
	    }
	    return (2);
	}
	unlock(bp);
	return (0);		/* aok */
    } else {			/* ptr node */
	ap = p = PKEY1(bp);
	if (gfp->ftype & F_MULT)	/* mult keys */
	    for (r = 0; r < n; r++) {
		if (keycomp(ap) >= 0)
		    break;
		p = ap;
		ap += gkeylen + 2;
	} else			/* unique keys */
	    for (r = 0; r < n; r++) {
		if (keycomp(ap) > 0)
		    break;
		p = ap;
		ap += gkeylen + 2;
	    }
	if (r == 0)
	    n = BLK0(bp);
	else
	    n = BLKNO(p);
	lockb(bp);
	/*dprintf( "dsrch %d\n", n); */
	n = dsrch(n, &u);
	switch (n) {
	case 2:		/* delete passup blk # from ptr blk */
	    /*dprintf( "dsrch: delete blk #%d\n", u.pblkno); */
	    if (NKEYS(bp) == 1) {	/* ptr back to leaf node */
		if (u.pblkno == BLK0(bp)) {
		    p = PKEY1(bp);
		    blk = BLKNO(p);
		} else
		    blk = BLK0(bp);
		if ((nbp = getblk(blk, (struct fildes *) gfp)) == NULL) {
		    unlock(bp);
		    return (ierr(8));	/* dsrch: nbp leaf fail */
		}
		memcpy(bp->buf, nbp->buf, BLKSIZ);
		setFPTR(bp, 0);
		setBPTR(bp, 0);
		bp->changed = 1;
		unlock(bp);
		return (0);	// was ;
	    }
	    p = PKEY1(bp);
	    n = NKEYS(bp);
	    if (u.pblkno == BLK0(bp)) {
		setBLK0(bp, BLKNO(p));
		r = 0;
	    } else {
		for (r = 0; r < n; r++) {
		    if (u.pblkno == BLKNO(p))
			break;
		    p += gkeylen + 2;
		}
		if (r >= n) {
		    unlock(bp);
		    return (ierr(9));	/* dsrch: blk find fail */
		}
	    }
	    if (n - r - 1 > 0)
		moveleft(p + gkeylen + 2, p, (n - r - 1) * (gkeylen + 2));
	    setNKEYS(bp, NKEYS(bp) - 1);
	    bp->changed = 1;
	    unlock(bp);
	    return (0);		// was ;
	case 1:		/* change passup blk #'s key */
	    n = NKEYS(bp);
	    p = PKEY1(bp);
	    /*dprintf( "dsrch: change blk #%d key to %9s\n", u.pblkno, u.key); */
	    for (r = 0; r < n; r++) {
		if (u.pblkno == BLKNO(p)) {
		    keycopy(u.key, p);
		    bp->changed = 1;
		    unlock(bp);
		    return (0);	// was ;
		}
		p += gkeylen + 2;
	    }
	    unlock(bp);
	    return (ierr(10));
	}
	unlock(bp);
    }
}

int
next(struct fildes *fp)
{
    register struct ndxfile *nfp;
    register struct buffer *bp;
    register int blk;
    register int n;
    char rbuf[MAXRECSIZ];

    //fprintf(stderr, "next(fp)\n");

    fp->eof = 0;

    if (!fp->ndxfp) {

	//fprintf(stderr, "\t!fp->ndxfp()\n");  
	do {
	    if (++fp->currec > fp->nrecs) {
		fp->currec = fp->nrecs;
		fp->eof = 1;
		return (0);
	    }
	    getrec(fp->currec, fp, rbuf);
	} while (rbuf[0] == '*');
	//fprintf(stderr, "\treturn fp->currec\n");
	return (fp->currec);
    }

    nfp = fp->ndxfp;
    gfp = nfp;

    if ((blk = nfp->curblk) == -1) {
	//fp->eof = 1;
	return (ierr(12));	/* next: no currency */
    }

  nxtblk:
    if ((bp = getblk(blk, (struct fildes *) nfp)) == NULL)
	return (ierr(11));	/* next: bp getblk fail */
#ifdef UNIV
    n = NKEYS(bp);
    if ((gfp == &FAndx2 || gfp == &FAndx3) && n > RECMAX)
	return (fatal(8));
#endif
    if (++(nfp->curoff) > NKEYS(bp)) {
	if ((blk = FPTR(bp)) != 0) {
	    nfp->curblk = blk;
	    nfp->curoff = 0;
	    goto nxtblk;
	}
	nfp->curoff = NKEYS(bp);
	fp->eof = 1;
	return (0);
    }
    n = (nfp->keylen + 2) * (nfp->curoff - 1) + nfp->keylen + KEY1OFF;
    fp->currec = get16(&bp->buf[n]);
    if (fp->currec > fp->nrecs || fp->currec <= 0)
	return (ierr(13));	/* next: invalid currec */
    return (fp->currec);
}

int
prev(struct fildes *fp)
{
    register struct ndxfile *nfp;
    register struct buffer *bp;
    register int blk;
    register int n;
    char rbuf[MAXRECSIZ];

    fp->eof = 0;
    if (!fp->ndxfp) {
	do {
	    if (--fp->currec <= 0) {
		fp->currec = 1;
		fp->eof = 1;
		return (0);
	    }
	    getrec(fp->currec, fp, rbuf);
	} while (rbuf[0] == '*');
	return (fp->currec);
    }
    nfp = fp->ndxfp;
    gfp = nfp;
    if ((blk = nfp->curblk) == -1)
	return (ierr(14));	/* prev: no currency */
    if ((bp = getblk(blk, (struct fildes *) nfp)) == NULL)
	return (ierr(15));	/* prev: bp getblk fail */
    if (--(nfp->curoff) <= 0) {
	if ((blk = BPTR(bp)) != 0) {
	    if ((bp = getblk(blk, (struct fildes *) nfp)) == NULL)
		return (ierr(16));	/* prev: bptr getblk fail */
	    nfp->curblk = blk;
	    nfp->curoff = NKEYS(bp);
	    goto ok;
	}
	nfp->curoff = 1;
	fp->eof = 1;
	return (0);
    }
  ok:
    n = (nfp->keylen + 2) * (nfp->curoff - 1) + nfp->keylen + KEY1OFF;
    fp->currec = get16(&bp->buf[n]);
    return (fp->currec);
}

int
gotop(struct fildes *fp)
{

    register struct ndxfile *nfp;
    register struct buffer *bp;

    fp->eof = 0;
    if (!fp->ndxfp) {
	fp->currec = 0;
	return (next(fp));
    }
    nfp = fp->ndxfp;
    gfp = nfp;
    if ((bp = getblk(0, (struct fildes *) nfp)) == NULL)
	return (ierr(17));	/* gotop: bp getblk fail */
    if (PAGETYPE(bp) != 0)
	if ((bp = getblk(BLK0(bp), (struct fildes *) nfp)) == NULL)
	    return (ierr(18));	/* gotop: blk0 getblk fail */
    nfp->curblk = bp->blkno;
    if (NKEYS(bp) == 0) {
	nfp->curoff = 0;
	fp->eof = 1;
	return (0);
    }
    nfp->curoff = 1;
    return (fp->currec = get16(&bp->buf[nfp->keylen + KEY1OFF]));
}

int
gobot(struct fildes *fp)
{
    register struct ndxfile *nfp;
    register struct buffer *bp;
    register char *p;
    register int n;

    fp->eof = 0;
    if (!fp->ndxfp) {
	fp->currec = fp->nrecs + 1;
	return (prev(fp));
    }
    nfp = fp->ndxfp;
    gfp = nfp;
    if ((bp = getblk(0, (struct fildes *) nfp)) == NULL)
	return (ierr(19));	/* gobot: bp getblk fail */
    gkeylen = nfp->keylen;
    if (PAGETYPE(bp) != 0) {
	p = PKEY1(bp) + ((NKEYS(bp) - 1) * (gkeylen + 2));
	if ((bp = getblk(BLKNO(p), (struct fildes *) nfp)) == NULL)
	    return (ierr(20));	/* gobot: blkno getblk fail */
    }
    nfp->curblk = bp->blkno;
    if (NKEYS(bp) == 0) {
	nfp->curoff = 0;
	fp->eof = 1;
	return (0);
    }
    nfp->curoff = NKEYS(bp);
    n = (nfp->keylen + 2) * (nfp->curoff - 1) + nfp->keylen + KEY1OFF;
    return (fp->currec = get16(&bp->buf[n]));
}

int
gotorec(struct fildes *fp, int rec)
{
    fp->eof = 0;
    if (fp->nrecs == 0 || rec == 0) {
	fp->currec = 0;
	fp->eof = 1;
    } else {
	fp->currec = rec - 1;
	next(fp);
    }
    return (fp->currec);
}

static void
keycopy(char *src, char *dst)
{
    register int n;

    if (gkeytyp)
	put16(dst, (int) get16(src));
    else {
	n = gkeylen;
	while (n--)
	    *dst++ = *src++;
    }
}

static int
keycomp(char *key)
{
    register int n;
    register char *p;

    if (gkeytyp)
	return (get16(key) - get16(gkey));
    n = gkeylen;
    p = gkey;
    while (--n >= 0 && *p++ == *key++)
	continue;
    return (n < 0 ? 0 : *--key - *--p);
}

static void
moveright(char *asrc, char *adst, int cnt)
{
    register char *src, *dst;

    src = asrc + cnt;
    dst = adst + cnt;
    while (cnt--)
	*--dst = *--src;
}

static int
ierr(int n)
{
    printf("\007*** Index Error #%d, file=%s, ", n, gfp->filext);
    if (gkeytyp)
	printf("key=%d", get16(gkey));
    else
	printf("key=%9s", gkey);
    printf("\n");
    return (0);
}

--- NEW FILE: nxdb.cxx ---
/*                                                                       
 * Copyright (c) 2003 Century Software, Inc.   All Rights Reserved.     
 *                                                                       
 * This file is part of the PIXIL Operating Environment                 
 *                                                                       
 * The use, copying and distribution of this file is governed by one    
 * of two licenses, the PIXIL Commercial License, or the GNU General    
 * Public License, version 2.                                           
 *                                                                       
 * Licensees holding a valid PIXIL Commercial License may use this file 
 * in accordance with the PIXIL Commercial License Agreement provided   
 * with the Software. Others are governed under the terms of the GNU   
 * General Public License version 2.                                    
 *                                                                       
 * This file may be distributed and/or modified under the terms of the  
 * GNU General Public License version 2 as published by the Free        
 * Software Foundation and appearing in the file LICENSE.GPL included   
 * in the packaging of this file.                                      
 *                                                                       
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING  
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A            
 * PARTICULAR PURPOSE.                                                  
 *                                                                       
 * RESTRICTED RIGHTS LEGEND                                             
 *                                                                     
 * Use, duplication, or disclosure by the government is subject to      
 * restriction as set forth in paragraph (b)(3)(b) of the Rights in     
 * Technical Data and Computer Software clause in DAR 7-104.9(a).       
 *                                                                      
 * See http://www.pixil.org/gpl/ for GPL licensing       
 * information.                                                         
 *                                                                      
 * See http://www.pixil.org/license.html or              
 * email cetsales at centurysoftware.com for information about the PIXIL   
 * Commercial License Agreement, or if any conditions of this licensing 
 * are not clear to you.                                                
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "nxdb.h"

#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
#include <stdlib.h>
#endif

#ifdef WIN32
#include <iostream>
#include <direct.h>
#include "../getopt/getopt.h"
#include "VCMemoryLeak.h"
#endif

#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>

#ifndef WIN32
#include <unistd.h>
#endif

#define OPTIONS "p:k:d:m:"
char *p_arg = 0;

NxDb::NxDb(int argc, char *argv[])
{
    int c;
    path = ".";
    while ((c = getopt(argc, argv, OPTIONS)) != -1) {
	switch (c) {
	case 'p':
	    path = optarg;

	    /*
	       p_arg = optarg;
	       struct stat dir;
	       if ( stat(p_arg, &dir) == 0) {
	       path = p_arg;
	       }
	     */
	    break;
	default:
	    break;
	}			// switch
    }				// while
    dbNum = 0;
    dbinit(0);
}

int
NxDb::Open(string _dbName, fildes * _dbDesc,
	   field * _dbField, int var, int path_flag)
{

    Register(_dbName, _dbDesc, _dbField, var);

    // Open Database
    string path_dbName;
    if (path_flag)
	path_dbName = _dbName;
    else {
	int len = path.length() - 1;
	if (path[len] != '/' && _dbName[0] != '/')
	    path += '/';
	path_dbName = path + _dbName;
    }
    struct stat dir;
    if (0 != stat(path.c_str(), &dir)) {

#ifndef WIN32
	mkdir(path.c_str(), S_IRWXU);
	
#else /* 
 */
	_mkdir(path.c_str());
	
#endif
    }
    if (!dbopen(_dbDesc, (char *) path_dbName.c_str())) {
	fprintf(stderr, "(1) Unable to open:[%s.%s]\n", path_dbName.c_str(),
		_dbDesc->filext);
	return 0;
    } else {
	fprintf(stderr, "Open DB: [%s] fp: %d\n", path_dbName.c_str(),
		_dbDesc->fildesc);
    }
    return 1;
}

int
NxDb::Close(string _dbName)
{

    int dbNumber = db[_dbName];
    fildes *_dbDesc = dbDesc[dbNumber];
    
dbclose(_dbDesc);
    
#ifdef WIN32
	return (0);
    
#endif
}

void
NxDb::Register(string _dbName, fildes * _dbDesc, field * _dbField, int var)
{
    TDatabase::iterator p = db.find(_dbName);

    if (p == db.end()) {
	db.insert(TValue(_dbName, dbNum));
	dbNum++;
    }

    TDatabase::iterator result = db.find(_dbName);

    if (result == db.end()) {
	exit(-1);
    } else {
	int dbNumber = db[_dbName];
	dbDesc[dbNumber] = _dbDesc;
	dbField[dbNumber] = _dbField;
    }
}

int
NxDb::Create(string _dbName, fildes * _dbDesc, field * _dbField, int var,
	     int path_flag)
{
    string path_dbName;
    if (path_flag)
	path_dbName = _dbName;
    else
	path_dbName = path + _dbName;
    if (!dbcreat(_dbDesc, (char *) path_dbName.c_str())) {
	cerr << "NxDb::Could not create: " << path_dbName << _dbDesc->
	    filext << endl;
	exit(-1);
    }
    Register(_dbName, _dbDesc, _dbField, var);

    //  use(0, NULL, NULL);
    Close(_dbName);
    return 1;
}

int
NxDb::SetFlags(const string _dbName, const int &recno, const int &flags)
{

#ifdef DEBUG
    //assert(db.find(_dbName) != db.end());

#endif /*  */
    char buf[MAXRECSIZ];
    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    int ok = getrec(recno, fp, &buf[0]);
    if (ok)
	fp->flags = flags;

    else
	return -1;
    ok = putrec(recno, fp, &buf[0]);
    dbsave(fp);
    if (ok)
	return 0;

    else
	return -2;
}

int
NxDb::GetFlags(const string _dbName, const int &recno, int &flags)
{

#ifdef DEBUG
    //assert(db.find(_dbName) != db.end());

#endif /*  */
    char buf[MAXRECSIZ];
    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    int ok = getrec(recno, fp, &buf[0]);

    //if (ok)
    flags = fp->flags;

    //cout << "GetFlags(): fp->flags = " << fp->flags << endl;
    //else
    //      return -1;
    return ok;
}

void
NxDb::Insert(string _dbName, char *record)
{

    cerr << "Insert\n";

    int dbNumber = db[_dbName];
    fildes *fp = dbDesc[dbNumber];
    int recno = APPEND;
    char ret_buf[MAXRECSIZ];


    for (int i = 1; i <= fp->nrecs; i++) {
	getrec(i, fp, ret_buf);
	if (recerased(fp)) {
	    break;
	}
    }
    fp->flags = NEW;
    putrec(recno, fp, record);

    //cout << "Insert(): recno = " << fp->currec << endl;
    dbsave(fp);
}

void
NxDb::Insert(string _dbName, char *record, int &rec)
{

#ifdef DEBUG
    //assert(db.find(_dbName) != db.end());

#endif /*  */
    int dbNumber = db[_dbName];
    fildes *fp = dbDesc[dbNumber];
    int recno = APPEND;
    char ret_buf[MAXRECSIZ];

    // look for an empty spot
    for (int i = 1; i <= fp->nrecs; i++) {
	getrec(i, fp, ret_buf);
	if (recerased(fp)) {
	    break;
	}
    }
    fp->flags = NEW;
    putrec(recno, fp, record);

    //cout << "fp->currec = " << fp->currec << endl;
    rec = fp->currec;
    dbsave(fp);
}

void
NxDb::Edit(string _dbName, int recno, char *record)
{

    cerr << "Edit." << endl;

    int dbNumber = db[_dbName];
    fildes *fp = dbDesc[dbNumber];

    // If record has NEW bit set, keep the new bit
    // or else set the bit to changed
    if (!(fp->flags & NEW))
	fp->flags = CHANGED;

    //cout << "Edit() recno = " << recno << endl;
    putrec(recno, fp, record);
    dbsave(fp);
}

void
NxDb::DeleteRec(string _dbName, int recno)
{

    int dbNumber = db[_dbName];
    fildes *fp = dbDesc[dbNumber];
    char ret_buf[MAXRECSIZ];
    getrec(recno, fp, ret_buf);

    // If a NEW occurs and then is immediately
    // delete, it would send the deleted record
    // across during a sync, which the other side
    // would not know about. Therefore, ERASE instead
    // of DELETED.
    //////////////////////////////////////////////////
    if (fp->flags & NxDb::NEW)
	fp->flags = NxDb::ERASED;

    else
	fp->flags = NxDb::DELETED;

    //cout << "DeleteRec(): fp->flags = " << fp->flags << endl;
    putrec(recno, fp, ret_buf);

    //fp->flags = 0;
    dbsave(fp);
}

void
NxDb::EraseRec(string _dbName, int recno)
{

#ifdef DEBUG
    //assert(db.find(_dbName) != db.end());

#endif /*  */
    int dbNumber = db[_dbName];
    fildes *fp = dbDesc[dbNumber];
    char ret_buf[MAXRECSIZ];
    getrec(recno, fp, ret_buf);
    fp->flags = NxDb::ERASED;
    putrec(recno, fp, ret_buf);
    fp->flags = 0;
    dbsave(fp);
}

int
NxDb::NumRecs(string _dbName)
{

    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    return fp->nrecs;
}

int
NxDb::Select(string _dbName, int ret[], int ret_size, bool bDeleteFlag,
	     int flags)
{

    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    char ret_buf[MAXRECSIZ];

    int idx = 0;
    for (int i = 1; i <= fp->nrecs; i++) {
	getrec(i, fp, ret_buf);
	if (flags != -1) {

	    //cout << "fp->flags = " << fp->flags << endl;
	    //cout << "flags = " << flags << endl;
	    if (!(fp->flags & flags))
		continue;
	} else {
	    if (fp->flags & NxDb::ERASED ||	// Skip erase records
		(fp->flags & NxDb::DELETED && !bDeleteFlag)) {	// Skip logically deleted records if bDeleteFlag not set
		continue;
	    }
	}
	ret[idx] = i;
	idx++;
    }
    return idx;
}

int
NxDb::Select(string _dbName, char *value, int fieldNo, int ret[],
	     int ret_size, bool bDeleteFlag)
{

    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    field *_dbField = dbField[dbNumber];
    char ret_buf[MAXRECSIZ];
    int idx = 0;
    char type;
    type = _dbField[fieldNo].type;

    for (int i = 1; i <= fp->nrecs; i++) {
	if (idx == ret_size) {
	    return idx;
	}
	memset(ret_buf, 0, MAXRECSIZ);
	getrec(i, fp, ret_buf);

	//cout << "\tSelect(): recno = " << i << endl;
	if (recdeleted(fp) && !bDeleteFlag) {

	    //cout << "recdeleted()\n";
	    continue;
	}
	if (type == 'c') {
	    if (strcmp(value, &ret_buf[_dbField[fieldNo].offset]) == 0) {
		ret[idx] = i;
		idx++;
	    }
	} else if ((type == 'd') || (type == 'i')) {
	    int num = get16(&ret_buf[_dbField[fieldNo].offset]);
	    if (num == atoi(value)) {
		ret[idx] = i;
		idx++;
	    }
	} else if (type == 'l') {
	    long num = get32(&ret_buf[_dbField[fieldNo].offset]);
	    if (num == strtol(value, NULL, 10)) {
		ret[idx] = i;
		idx++;
	    }
	} else {
	    return idx;
	}
    }
    return idx;
}

int
NxDb::Extract(string _dbName, int recno, char *ret_buf)
{
    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    return getrec(recno, fp, ret_buf);
}

int
NxDb::Extract(string _dbName, int recno, int fieldNo, char *ret_buf)
{

    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    field *_dbField = dbField[dbNumber];
    char type;
    char rec_buf[MAXRECSIZ];
    int ival = 0;
    long lval = 0;
    type = _dbField[fieldNo].type;
    if (getrec(recno, fp, rec_buf) == 0)
	return 0;
    switch (type) {
    case 'c':{

	    //cout << "Extract(): c\n";
	    //int size = int(_dbField[fieldNo].size);
	    //size = size - 1;
	    //cerr << "Extract(): size = " << size << endl;
	    //memset(ret_buf, 0, size);
	    strcpy(ret_buf, &rec_buf[_dbField[fieldNo].offset]);

	    //ret_buf[size] = 0;
	    return 1;
	}
    case 'd':
    case 'i':
	ival = get16(&rec_buf[_dbField[fieldNo].offset]);

	//cout << "Extract(): i = " << ival << endl;
	sprintf(ret_buf, "%d", ival);
	return 1;
    case 'l':
	lval = get32(&rec_buf[_dbField[fieldNo].offset]);

	//cout << "Extract(): l\n";
	sprintf(ret_buf, "%ld", lval);
	return 1;
    default:
	break;
    }
    return 0;
}

int
NxDb::ExtractDeleted(string _dbName, int recno, int fieldNo, char *ret_buf)
{

#ifdef DEBUG
    //assert(db.find(_dbName) != db.end());

#endif /*  */
    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    field *_dbField = dbField[dbNumber];
    char type;
    char rec_buf[MAXRECSIZ];
    int ival = 0;
    long lval = 0;
    type = _dbField[fieldNo].type;
    if (getrec(recno, fp, rec_buf) == 1)
	return 0;
    switch (type) {
    case 'c':

	//cout << "Extract(): c\n";
	strcpy(ret_buf, &rec_buf[_dbField[fieldNo].offset]);
	return 1;
    case 'd':
    case 'i':
	ival = get16(&rec_buf[_dbField[fieldNo].offset]);

	//cout << "Extract(): i = " << ival << endl;
	sprintf(ret_buf, "%d", ival);
	return 1;
    case 'l':
	lval = get32(&rec_buf[_dbField[fieldNo].offset]);

	//cout << "Extract(): l\n";
	sprintf(ret_buf, "%ld", lval);
	return 1;
    default:
	break;
    }
    return 0;
}

field *
NxDb::GetField(string _dbName)
{
    int dbNumber = db[_dbName];
    struct field *fp = dbField[dbNumber];

    return fp;
}

fildes *
NxDb::GetFilDes(string _dbName)
{
    int dbNumber = db[_dbName];
    struct fildes *fp = dbDesc[dbNumber];
    return fp;
}

void
NxDb::Purge(string _dbName, int fieldNo, char *value)
{

    int dbNumber = db[_dbName];
    fildes *fp = dbDesc[dbNumber];
    char ret_buf[MAXRECSIZ];
    if (fieldNo != -1) {

	// Purge specific records
	for (int i = 1; i <= fp->nrecs; i++) {
	    Extract(_dbName, i, fieldNo, ret_buf);
	    if (strcmp(ret_buf, value) == 0)
		DeleteRec(_dbName, i);
	}
    } else {

	// Purge all records
	for (int i = 1; i < fp->nrecs; i++)
	    DeleteRec(_dbName, i);
    }
}
void
fatal(int n)
{
    printf("*** Fatal Error #%d\n", n);
}

--- NEW FILE: NxDb.dsp ---
# Microsoft Developer Studio Project File - Name="NxDb" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (x86) Static Library" 0x0104

CFG=NxDb - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "NxDb.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "NxDb.mak" CFG="NxDb - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "NxDb - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "NxDb - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE 

# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe

!IF  "$(CFG)" == "NxDb - Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "HAVE_CONFIG_H" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo

!ELSEIF  "$(CFG)" == "NxDb - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /I "." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "HAVE_CONFIG_H" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo

!ENDIF 

# Begin Target

# Name "NxDb - Win32 Release"
# Name "NxDb - Win32 Debug"
# Begin Group "Source Files"

# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File

SOURCE=.\blkio.c
# End Source File
# Begin Source File

SOURCE=.\db.c
# End Source File
# Begin Source File

SOURCE=.\index.c
# End Source File
# Begin Source File

SOURCE=.\nxdb.cxx
# End Source File
# Begin Source File

SOURCE=.\use.c
# End Source File
# End Group
# Begin Group "Header Files"

# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File

SOURCE=.\config.h
# End Source File
# Begin Source File

SOURCE=.\file.h
# End Source File
# Begin Source File

SOURCE=.\nxdb.h
# End Source File
# End Group
# End Target
# End Project

--- NEW FILE: db.c ---
/*                                                                       
 * Copyright (c) 2003 Century Software, Inc.   All Rights Reserved.     
 *                                                                       
 * This file is part of the PIXIL Operating Environment                 
 *                                                                       
 * The use, copying and distribution of this file is governed by one    
 * of two licenses, the PIXIL Commercial License, or the GNU General    
 * Public License, version 2.                                           
 *                                                                       
 * Licensees holding a valid PIXIL Commercial License may use this file 
 * in accordance with the PIXIL Commercial License Agreement provided   
 * with the Software. Others are governed under the terms of the GNU   
 * General Public License version 2.                                    
 *                                                                       
 * This file may be distributed and/or modified under the terms of the  
 * GNU General Public License version 2 as published by the Free        
 * Software Foundation and appearing in the file LICENSE.GPL included   
 * in the packaging of this file.                                      
 *                                                                       
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING  
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A            
 * PARTICULAR PURPOSE.                                                  
 *                                                                       
 * RESTRICTED RIGHTS LEGEND                                             
 *                                                                     
 * Use, duplication, or disclosure by the government is subject to      
 * restriction as set forth in paragraph (b)(3)(b) of the Rights in     
 * Technical Data and Computer Software clause in DAR 7-104.9(a).       
 *                                                                      
 * See http://www.pixil.org/gpl/ for GPL licensing       
 * information.                                                         
 *                                                                      
 * See http://www.pixil.org/license.html or              
 * email cetsales at centurysoftware.com for information about the PIXIL   
 * Commercial License Agreement, or if any conditions of this licensing 
 * are not clear to you.                                                
 */

#include <stdio.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <fcntl.h>
#ifdef WIN32
#include <io.h>
#endif
#include "file.h"

#include "VCMemoryLeak.h"

/*
 * db.c - database & index file open/close/create routines
 *
 * from 9/9/85 mt15b
 */

#ifndef WIN32
#define O_BINARY	0
#endif
static char *str2cat(char *f1, char *ext);

struct buffer *getblk();

extern struct buffer *startbuf, *endbuf;
extern char apflag;

/*
 * create a database or index file
 */
int
dbcreat(struct fildes *fp, char *name)
{
    int fd, ret;

    if ((fd = creat(str2cat(name, fp->filext), 0666)) < 0)
	return (0);
    close(fd);
    apflag = 1;
    ret = dbopen(fp, name);
    apflag = 0;
    return (ret);

}

/*
 * open a database or index file
 */
int
dbopen(struct fildes *fp, char *name)
{
    int fd, off, x;
    struct buffer *bp;

    if ((fd = open(str2cat(name, fp->filext), O_RDWR | O_BINARY)) < 0)
	return (0);
    fp->fildesc = fd;
    fp->fchanged = 0;
    bp = getblk(0, fp);
    if (fp->ftype) {		/* index file */
	((struct ndxfile *) fp)->maxkeys =
	    ((BLKSIZ - 7) / (2 + ((struct ndxfile *) fp)->keylen));
	((struct ndxfile *) fp)->curblk = -1;
	return (1);
    }
    fp->nrecs = get16(&bp->buf[0]);
    fp->currec = 1;

    off = 1;			/* byte 0 is deleted flag */
    for (fd = 0; fp->fieldp[fd].type; fd++) {
	//if( fd >= MAXFIELDS)
	//fatal( x);
	fp->fieldp[fd].offset = off;
	x = fp->fieldp[fd].size;
	switch (fp->fieldp[fd].type) {
	case 'c':
	case 'n':		/* pt only */
	    off += x;
	    break;
	case 'd':
	case 'i':
	    off += x * sizeof(short);
	    break;
	case 'l':
	    off += x * sizeof(long);
	    break;
	}
    }

    x = 1;
    fp->fieldp[fd].offset = off;
    off += x * sizeof(long);

    fp->nfields++;

    fp->nfields = fd;

    fp->recsiz = off;
    if (off > MAXRECSIZ)
	fatal(4);		/* max rec size overflow */
    return (1);
}

/*
 * close and write database or index file
 */
void
dbclose(struct fildes *fp)
{
    struct buffer *bp;

    if (fp->fchanged) {
	bp = getblk(0, fp);
	if (!fp->ftype)
	    put16(&bp->buf[0], fp->nrecs);
	putblk(bp);
    }

    for (bp = startbuf; bp < endbuf; bp++)
	if (bp->fptr == fp) {
	    if (bp->changed)
		putblk(bp);
	    bp->usecnt = 0;
	    bp->fptr = NULL;
	}
    close(fp->fildesc);
}

/*
 * write the database or index file
 */
void
dbsave(struct fildes *fp)
{
    struct buffer *bp;

    if (fp->fchanged) {
	bp = getblk(0, fp);
	if (!fp->ftype)
	    put16(&bp->buf[0], fp->nrecs);
	putblk(bp);
    }

    for (bp = startbuf; bp < endbuf; bp++)
	if (bp->fptr == fp) {
	    if (bp->changed)
		putblk(bp);
	    bp->usecnt = 0;
	    bp->fptr = NULL;
	}
}

static char *
str2cat(char *f1, char *ext)
{
    char *p;
    static char buf[69];

    p = buf;
    while (*f1)
	*p++ = *f1++;
    *p++ = '.';
    while ((*p++ = *ext++) != 0)
	continue;
    return (buf);
}

--- NEW FILE: Makefile ---
CXX = g++
CC = gcc

ifeq ($(CONFIG_DEBUG),y)
CFLAGS+=-g -O0 -Wall -DDEBUG
endif

CFLAGS += -Wall -I../include

%.o:%.c
	$(CC) $(CFLAGS) -c $<

%.o:%.cpp
	$(CXX) $(CFLAGS) -c $<

%.o:%.cxx
	$(CXX) $(CFLAGS) -c $<

libNxDb.a: blkio.o db.o nxdb.o index.o use.o
	$(AR) -ru $@ $^

blkio.o: blkio.c

db.o: db.c

nxdb.o: nxdb.cxx

index.o: index.c

use.o: use.c

clean:
	@ rm -f ide
	@ rm -f *.o
	@ rm -f *.a

install:


--- NEW FILE: blkio.c ---
/*                                                                       
 * Copyright (c) 2003 Century Software, Inc.   All Rights Reserved.     
 *                                                                       
 * This file is part of the PIXIL Operating Environment                 
 *                                                                       
 * The use, copying and distribution of this file is governed by one    
 * of two licenses, the PIXIL Commercial License, or the GNU General    
 * Public License, version 2.                                           
 *                                                                       
 * Licensees holding a valid PIXIL Commercial License may use this file 
 * in accordance with the PIXIL Commercial License Agreement provided   
 * with the Software. Others are governed under the terms of the GNU   
 * General Public License version 2.                                    
 *                                                                       
 * This file may be distributed and/or modified under the terms of the  
 * GNU General Public License version 2 as published by the Free        
 * Software Foundation and appearing in the file LICENSE.GPL included   
 * in the packaging of this file.                                      
 *                                                                       
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING  
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A            
 * PARTICULAR PURPOSE.                                                  
 *                                                                       
 * RESTRICTED RIGHTS LEGEND                                             
 *                                                                     
 * Use, duplication, or disclosure by the government is subject to      
 * restriction as set forth in paragraph (b)(3)(b) of the Rights in     
 * Technical Data and Computer Software clause in DAR 7-104.9(a).       
 *                                                                      
 * See http://www.pixil.org/gpl/ for GPL licensing       
 * information.                                                         
 *                                                                      
 * See http://www.pixil.org/license.html or              
 * email cetsales at centurysoftware.com for information about the PIXIL   
 * Commercial License Agreement, or if any conditions of this licensing 
 * are not clear to you.                                                
 */

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

#ifndef WIN32
#include <unistd.h>
#endif
#include <malloc.h>
#ifdef WIN32
#include <io.h>
#include <memory.h>
#endif
#include "file.h"

#include "VCMemoryLeak.h"
/* 
 * blkio.c - block i/o routines
 *
 * from 8/25/85 mt15b
 */
#define	MIN(a,b)		((a) < (b) ? (a) : (b))
#define	MAX(a,b) 		((a) > (b) ? (a) : (b))
#define dprintf printf
#define MAXBUFS	20		/* max number of in-core buffers */
#define LOCKVAL	32767		/* value of usecnt to lock buffer incore */
struct buffer *startbuf;	/* ptr to first buffer */
struct buffer *endbuf;		/* ptr past last buffer */
char apflag = 0;		/* append mode flag for getblk() */

/* local data*/
static int lockclock = 0;

/* local procs*/
static int bread(int fd, char *buf, int blk);
static int bwrite(int fd, char *buf, int blk);
static int bfilesize(int fd);
static struct buffer *berr(char *str, int blk, struct fildes *fp);

/*
 * read record recno from file fp into recbuf, return 1 if ok
 */
int
getrec(int recno, struct fildes *fp, char *recbuf)
{
    int off, cnt, n, blk;
    struct buffer *bp;
    long offset;
    char *tmpBuf;
    if ((recno == 0))
	return (0);
    cnt = fp->recsiz;
    offset = (recno - 1) * (long) cnt + RECOFF;
    tmpBuf = recbuf;

    do {
	blk = (int) (offset >> BLKSHFT);	/* logical blk # */
	off = (int) (offset & BLKMSK);	/* offset in blk */
	n = umin(BLKSIZ - off, cnt);	/* calc read cnt */
	if ((bp = getblk(blk, fp)) == NULL)
	    return (0);
	memcpy(recbuf, &bp->buf[off], n);
	recbuf += n;
	cnt -= n;
	offset += n;
    } while (cnt != 0);
    fp->flags = get32(&tmpBuf[fp->recsiz - sizeof(long)]);

#if 0
    if (fp->flags) {
	fprintf(stderr, "getrec: %ld\n", fp->flags);
    }
#endif /*  */
    return (!recdeleted(fp));
}


// returns true if the record can be safely overwritten
int
recerased(struct fildes *fp)
{
    return (fp->flags & 0xF0);
}

int
recdeleted(struct fildes *fp)
{

    /*printf("blkio.c recdeleted may need to check more flags\n"); */
    return ((fp->flags & 0xF0) | (fp->flags & 0x01));
}

int
putrec(int recno, struct fildes *fp, char *recbuf)
{
    int off, cnt, n, blk;
    struct buffer *bp;
    long offset;

#ifndef WIN32
    int i;

#endif
    if (recno == 0 || recno > fp->nrecs) {
	fprintf(stderr, "\007*** Putrec: invalid record number %d\n", recno);
	return (0);
    }
    if (recno == APPEND) {	/* check for append mode */
	recno = fp->currec = ++fp->nrecs;
	fp->fchanged = 1;
	apflag = 1;
    }
    cnt = fp->recsiz;
    offset = (recno - 1) * (long) cnt + RECOFF;
    put32(&recbuf[cnt - sizeof(long)], fp->flags);

    do {
	blk = (int) (offset >> BLKSHFT);
	off = (int) (offset & BLKMSK);
	n = umin(BLKSIZ - off, cnt);
	if ((bp = getblk(blk, fp)) == NULL) {
	    return (0);
	}
	memcpy(&bp->buf[off], recbuf, n);
	bp->changed = 1;
	recbuf += n;
	cnt -= n;
	offset += n;
    } while (cnt != 0);
    apflag = 0;
    return (1);
}
struct buffer *
getblk(int blk, struct fildes *fp)
{
    struct buffer *bp, *savbp;
    if (++lockclock >= LOCKVAL)	/* lru timing */
	lockclock = 1;
    savbp = NULL;
    for (bp = startbuf; bp < endbuf; bp++) {
	if (bp->blkno == blk && bp->fptr == fp) {
	    bp->usecnt = lockclock;
	    return (bp);
	}
	if (savbp == NULL || bp->usecnt < savbp->usecnt)
	    savbp = bp;
    }
    if (savbp->usecnt == LOCKVAL)
	return berr("all bufs locked", blk, fp);
    if (savbp->changed) {	/* write buffer if modified */
	putblk(savbp);
    }
    if (!bread(fp->fildesc, savbp->buf, blk)) {
	if (apflag) {
	    memset(savbp->buf, 0, BLKSIZ);
	    savbp->changed = 1;
	} else {
	    return berr("read error", blk, fp);
	}
    }
    savbp->blkno = blk;
    savbp->fptr = fp;
    savbp->usecnt = lockclock;
    return (savbp);
}

void
putblk(struct buffer *bp)
{
    if (bp == NULL)
	return;
    bwrite(bp->fptr->fildesc, bp->buf, bp->blkno);
    bp->changed = 0;
}
struct buffer *
newblk(struct fildes *fp)
{
    struct buffer *bp;
    int blk;
    blk = 0;
    for (bp = startbuf; bp < endbuf; bp++)
	if (bp->fptr == fp)
	    blk = MAX(blk, bp->blkno);
    fprintf(stderr, "newblk: filesize=%d, max incore blk=%d,",
	    bfilesize(fp->fildesc), blk);
    blk = MAX(bfilesize(fp->fildesc), blk + 1);
    fprintf(stderr, "new=%d\n", blk);
    apflag = 1;
    bp = getblk(blk, fp);
    apflag = 0;
    return (bp);
}
struct buffer *
lockb(struct buffer *bp)
{
    if (bp)
	bp->usecnt = LOCKVAL;
    return (bp);
}

void
unlock(struct buffer *bp)
{
    if (++lockclock >= LOCKVAL)	/* lru timing */
	lockclock = 1;
    bp->usecnt = lockclock;
}

void
dbinit(int maxbufs)
{
    register struct buffer *bp;
    if (maxbufs <= 0)
	maxbufs = MAXBUFS;
    while ((startbuf = malloc(sizeof(struct buffer) * maxbufs)) == NULL) {
	if (--maxbufs < 4)
	    fatal(9);		/* no memory */
    }
    endbuf = startbuf + maxbufs;
    for (bp = startbuf; bp < endbuf; bp++) {
	bp->usecnt = 0;
	bp->fptr = NULL;
	bp->changed = 0;
    }
}
static int
bread(int fd, char *buf, int blk)
{
    lseek(fd, (long) blk << 10, 0);
    if (read(fd, buf, 1024) != 1024)
	return (0);
    return (1);
}
static int
bwrite(int fd, char *buf, int blk)
{

#ifndef WIN32
    int i;

#endif
    lseek(fd, (long) blk << 10, 0);
    if (write(fd, buf, 1024) != 1024) {
	return (0);
    }
    return (1);
}


/*
 * return file size in 1K blocks
 */
static int
bfilesize(int fd)
{
#if UNIX
    struct stat sbuf;
    if (fstat(fd, &sbuf) < 0)
	return (0);
    return ((int) (sbuf.st_size / (long) BLKSIZ));
#else
    return ((int) (lseek(fd, 0L, 2) / (long) BLKSIZ));
#endif
}
unsigned int
umin(unsigned int a, unsigned int b)
{
    if (a < b)
	return (a);
    return (b);
}
static struct buffer *
berr(char *str, int blk, struct fildes *fp)
{
    printf("\007*** getblk: %s, blk=%d, file=%s\n", str, blk, fp->filext);
    return (NULL);
}




More information about the dslinux-commit mailing list